public int i0Func(int jCell, int iVar) { if (VarIsXdg[iVar]) { int iSpc = m_LsRegion.GetSpeciesIndex(this.m_spId, jCell); return m_Map.GlobalUniqueCoordinateIndex(iVar, jCell, iSpc * NS[iVar]); } else { return m_Map.GlobalUniqueCoordinateIndex(iVar, jCell, 0); } }
/// <summary> /// Accumulates an identity matrix, but only for selected variabels /// </summary> /// <param name="M">matrix to be modified (input/output)</param> /// <param name="factor"></param> /// <param name="iVar"></param> static public void AccEyeSp(this ISparseMatrix M, UnsetteledCoordinateMapping map, int[] iVar, double factor = 1.0) { using (new FuncTrace()) { if (M.RowPartitioning.LocalLength != M.ColPartition.LocalLength) { throw new ArgumentException("supported only for quadratic matrices"); } if (map.LocalLength != M.RowPartitioning.LocalLength) { throw new ArgumentException(); } int J = map.GridDat.iLogicalCells.NoOfLocalUpdatedCells; for (int j = 0; j < J; j++) { foreach (int f in iVar) { int Np = map.BasisS[f].GetLength(j); for (int n = 0; n < Np; n++) { int idx = map.GlobalUniqueCoordinateIndex(f, j, n); M.SetDiagonalElement(idx, M.GetDiagonalElement(idx) + factor); } } } } }
/// <summary> /// writes the dammed result of the integration to the sparse matrix /// </summary> protected override void SaveIntegrationResults(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { int Mmax = m_ColMap.MaxTotalNoOfCoordinatesPerCell; int Nmax = m_RowMap.MaxTotalNoOfCoordinatesPerCell; int[] _i0 = new int[] { int.MaxValue, 0, 1 }; int[] _iE = new int[] { -1, Nmax - 1, _i0[2] + Mmax - 1 }; int[] _i0aff = new int[] { int.MaxValue, 0, 0 }; int[] _iEaff = new int[] { -1, Nmax - 1, -1 }; bool saveMtx = this.OperatorMatrix != null; bool saveAff = this.OperatorAffine != null; // loop over cells... for (int i = 0; i < Length; i++) { int jCell = i + i0; int Row0 = m_RowMap.LocalUniqueCoordinateIndex(0, jCell, 0); int Row0_g = m_RowMap.i0 + Row0; if (saveMtx) { _i0[0] = i; _iE[0] = -1; var BlockRes = ResultsOfIntegration.ExtractSubArrayShallow(_i0, _iE); int Col0_g = m_ColMap.GlobalUniqueCoordinateIndex(0, jCell, 0); //for (int r = BlockRes.NoOfRows - 1; r >= 0; r--) // for (int c = BlockRes.NoOfCols - 1; c >= 0; c--) // OperatorMatrix[Row0_g + r, Col0_g + c] += BlockRes[r, c]; OperatorMatrix.AccBlock(Row0_g, Col0_g, 1.0, BlockRes); } if (saveAff) { _i0aff[0] = i; _iEaff[0] = -1; var BlockRes = ResultsOfIntegration.ExtractSubArrayShallow(_i0aff, _iEaff); for (int r = BlockRes.GetLength(0) - 1; r >= 0; r--) { OperatorAffine[Row0 + r] += BlockRes[r]; } } } }
virtual public void GetRestrictionMatrix(BlockMsrMatrix rest, MultigridMapping mgMap, int iFld) { if (!object.ReferenceEquals(mgMap.AggBasis[iFld], this)) { throw new ArgumentException(); } UnsetteledCoordinateMapping fullmap = mgMap.ProblemMapping; int[] degree = mgMap.DgDegree; foreach (var b in fullmap.BasisS) { if (!b.IsSubBasis(this.DGBasis)) { throw new ArgumentException(""); } if (b.MaximalLength != b.MinimalLength) { throw new NotSupportedException(); } } if (fullmap.BasisS.Count != degree.Length) { throw new ArgumentException(); } int NoFld = degree.Length; int[] FullLength = fullmap.BasisS.Select(b => b.Length).ToArray(); int[] RestLength = NoFld.ForLoop( l => fullmap.BasisS[l].Polynomials[0].Where(poly => poly.AbsoluteDegree <= degree[l]).Count()); int[] RestOffset = new int[NoFld]; for (int f = 1; f < NoFld; f++) { RestOffset[f] = RestOffset[f - 1] + RestLength[f - 1]; } int NR = RestLength.Sum(); int JAGG = this.AggGrid.iLogicalCells.NoOfLocalUpdatedCells; var ag = this.AggGrid; var agCls = ag.iLogicalCells.AggregateCellToParts; //Partitioning RowMap = new Partitioning(JAGG * NR); int MpiOffset_row = rest.RowPartitioning.i0; for (int jagg = 0; jagg < JAGG; jagg++) { int[] agCl = agCls[jagg]; int K = agCl.Length; for (int k = 0; k < K; k++) // loop over the cells which form the aggregated cell... { int jCell = agCl[k]; int M = RestLength[iFld]; int N = FullLength[iFld]; var Block = this.CompositeBasis[jagg].ExtractSubArrayShallow(new int[] { k, 0, 0 }, new int[] { k - 1, N - 1, M - 1 }); //for(int f = 0; f < NoFld; f++) { // loop over DG fields in mapping... int i0Col = fullmap.GlobalUniqueCoordinateIndex(iFld, jCell, 0); int i0Row = jagg * NR + RestOffset[iFld] + MpiOffset_row; //rest.AccBlock(i0Row, i0Col, 1.0, Block); for (int m = 0; m < M; m++) { for (int n = 0; n < N; n++) { rest[i0Row + m, i0Col + n] = Block[n, m]; } } } } }
/// <summary> /// Tools for updating operator matrices under level-set movement, when ordering of DOFs (the mapping) changes. /// </summary> public static void OperatorLevelSetUpdate(LevelSetTracker LsTrk, BlockMsrMatrix[] OpMtx, UnsetteledCoordinateMapping RowMap, UnsetteledCoordinateMapping ColMap) { using (new FuncTrace()) { BoSSS.Foundation.Grid.IGridData GridData = LsTrk.GridDat; int JE = GridData.iLogicalCells.NoOfCells; int Jup = GridData.iLogicalCells.NoOfLocalUpdatedCells; int cell_j0 = GridData.CellPartitioning.i0; // build index mappings // ==================== int[,] _old2NewRows, _old2NewCols; { List <Tuple <int, int> > old2NewRows = new List <Tuple <int, int> >(); List <Tuple <int, int> > old2NewCols = new List <Tuple <int, int> >(); List <Tuple <int, int> > old2NewColsExt = new List <Tuple <int, int> >(); // loop over cells for (int j = 0; j < JE; j++) { int[] RowIdxUpdate; if (j < Jup) { RowIdxUpdate = MappingUpdate(LsTrk, j, RowMap, false); } else { RowIdxUpdate = null; } int[] ColIdxUpdate = MappingUpdate(LsTrk, j, ColMap, false); Debug.Assert((j >= Jup) || ((RowIdxUpdate != null) == (ColIdxUpdate != null))); if (RowIdxUpdate != null) { //Debug.Assert(RowMap.GetBlockLen(cell_j0 + j) == RowMap.MaxTotalNoOfCoordinatesPerCell); //Debug.Assert(RowIdxUpdate.Length == RowMap.GetBlockLen(cell_j0 + j)); int i0 = RowMap.GetBlockI0(cell_j0 + j); int II = RowIdxUpdate.Length; for (int ii = 0; ii < II; ii++) { int iOld = ii + i0; int iNew = RowIdxUpdate[ii] + i0; if (RowIdxUpdate[ii] >= 0) { Debug.Assert(old2NewRows.Count == 0 || old2NewRows[old2NewRows.Count - 1].Item1 < iOld); old2NewRows.Add(new Tuple <int, int>(iOld, iNew)); } } } if (ColIdxUpdate != null) { //Debug.Assert(ColMap.MinTotalNoOfCoordinatesPerCell == ColMap.MaxTotalNoOfCoordinatesPerCell); //Debug.Assert(ColMap.GetBlockLen(cell_j0 + j) == ColMap.MaxTotalNoOfCoordinatesPerCell); //Debug.Assert(ColIdxUpdate.Length == ColMap.GetBlockLen(cell_j0 + j)); // mapping is old-->new, i.e. new[IdxUpdate[k]] = old[k] for all k //int i0 = ColMap.GetBlockI0(cell_j0 + j); //int jLoc; //if (j < Jup) // jLoc = j; //else // jLoc = LsTrk.GridDat.iParallel.Global2LocalIdx[cell_j0 + j]; int i0 = ColMap.GlobalUniqueCoordinateIndex(0, j, 0); //Debug.Assert() int II = ColIdxUpdate.Length; for (int ii = 0; ii < II; ii++) { int iOld = ii + i0; int iNew = ColIdxUpdate[ii] + i0; if (ColIdxUpdate[ii] >= 0) { if (j < Jup) { Debug.Assert(old2NewCols.Count == 0 || old2NewCols[old2NewCols.Count - 1].Item1 < iOld); old2NewCols.Add(new Tuple <int, int>(iOld, iNew)); } else { old2NewColsExt.Add(new Tuple <int, int>(iOld, iNew)); } } } } } // data conversion int I = old2NewRows.Count; _old2NewRows = new int[I, 2]; for (int i = 0; i < I; i++) { var t = old2NewRows[i]; _old2NewRows[i, 0] = t.Item1; _old2NewRows[i, 1] = t.Item2; } int J = old2NewCols.Count + old2NewColsExt.Count; old2NewColsExt.Sort((a, b) => a.Item1 - b.Item1); _old2NewCols = new int[J, 2]; int ja = 0, jb = 0; for (int j = 0; j < J; j++) { Tuple <int, int> t; if (ja < old2NewCols.Count && jb < old2NewColsExt.Count) { Tuple <int, int> t1, t2; t1 = old2NewCols[ja]; t2 = old2NewColsExt[jb]; Debug.Assert(t1.Item1 != t2.Item1); if (t1.Item1 < t2.Item1) { t = t1; ja++; } else { t = t2; jb++; } } else if (ja < old2NewCols.Count) { t = old2NewCols[ja]; ja++; } else { Debug.Assert(jb < old2NewColsExt.Count); Debug.Assert(ja >= old2NewCols.Count); t = old2NewColsExt[jb]; jb++; } _old2NewCols[j, 0] = t.Item1; _old2NewCols[j, 1] = t.Item2; Debug.Assert(j == 0 || _old2NewCols[j - 1, 0] < _old2NewCols[j, 0]); } Debug.Assert(ja == old2NewCols.Count); Debug.Assert(jb == old2NewColsExt.Count); } // update matrices // =============== for (int iMtx = 0; iMtx < OpMtx.Length; iMtx++) { if (OpMtx[iMtx] != null) { OpMtx[iMtx] = OpMtx[iMtx].RecyclePermute(RowMap, ColMap, _old2NewRows, _old2NewCols); } } } }
/// <summary> /// computes the mass matrices for a given mapping and accumulates the mass matrix to some other matrix. /// </summary> public void AccMassMatrix <T>(T M, UnsetteledCoordinateMapping mapping, IDictionary <SpeciesId, IEnumerable <double> > _alpha, bool inverse = false) where T : IMutableMatrixEx // { using (new FuncTrace()) { var _basisS = mapping.BasisS.ToArray(); var ctx = _basisS[0].GridDat; int J = ctx.iLogicalCells.NoOfLocalUpdatedCells; if (!M.RowPartitioning.EqualsPartition(mapping)) { throw new ArgumentException("Mismatch in row mapping."); } if (!M.ColPartition.EqualsPartition(mapping)) { throw new ArgumentException("Mismatch in column mapping."); } if (!_alpha.Keys.IsSubsetOf(this.AvailableSpecies)) { throw new ArgumentException("trying to obtain mass matrix for species that is not supported by this factory."); } foreach (var __alpha in _alpha.Values) { if (__alpha.Count() != _basisS.Length) { throw new ArgumentException("Number of alpha's must match number of variables/fields in mapping."); } } LevelSetTracker.LevelSetRegions regions = null;// XDGSpaceMetrics.LevelSetRegions; // compute the Mass-Blocks for the cut cells... // -------------------------------------------- int _MaxDeg = _basisS.Max(b => b.Degree); var RequestedSpecies = _alpha.Keys; UpdateBlocks(_MaxDeg, RequestedSpecies); Dictionary <SpeciesId, MassMatrixBlockContainer>[] invBlocks = null; if (inverse) { invBlocks = GetInverseMassMatrixBlocks(RequestedSpecies, mapping.BasisS.Select(b => b.Degree).ToArray()); //VariableAgglomerationSwitch = new bool[VariableAgglomerationSwitch.Length]; //VariableAgglomerationSwitch.SetAll(true); // we already took care about this in the 'GetInverseMassMatrixBlocks' } // set the matrix // -------------- for (int fld = 0; fld < _basisS.Length; fld++) // loop over Variables in mapping... // loop over species... { foreach (var species in _alpha.Keys) { double alpha = _alpha[species].ElementAt(fld); int[] jSub2jCell = this.MassBlocks[species].jSub2jCell; if (alpha != 0.0) { // properties of the basis XDGBasis Xbasis = _basisS[fld] as XDGBasis; Basis nonXbasis; Basis basis = _basisS[fld]; if (Xbasis != null) { nonXbasis = Xbasis.NonX_Basis; regions = Xbasis.Tracker.Regions; // compute species indices with respect to **actual** regions !!!! //if (!object.ReferenceEquals(Xbasis.Tracker, this.XDGSpaceMetrics.)) // throw new ArgumentException(); } else { nonXbasis = _basisS[fld]; } int N = nonXbasis.Length; // get Mass-Matrix subblock MultidimensionalArray Mass; if (!inverse) { Mass = this.MassBlocks[species].MassMatrixBlocks; } else { Mass = invBlocks[fld][species].MassMatrixBlocks; Debug.Assert(Mass.GetLength(1) == N); Debug.Assert(Mass.GetLength(2) == N); } // set diagonal element 1.0 in all cells of the subgrid // (later, we subtract 1.0 from the diagonal in cut cells) var speciesMask = XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(species); { foreach (int jCell in speciesMask.ItemEnum) { int iSpc = 0; if (Xbasis != null) { int NoOfSpc = regions.GetNoOfSpecies(jCell); iSpc = regions.GetSpeciesIndex(species, jCell); } int n0 = mapping.GlobalUniqueCoordinateIndex(fld, jCell, N * iSpc); for (int n = 0; n < N; n++) { M[n0 + n, n0 + n] += alpha; } } } // now, set then Non-Identity blocks in the cut cells var speciesBitMask = speciesMask.GetBitMask(); { int JSUB = jSub2jCell.Length; for (int jsub = 0; jsub < JSUB; jsub++) // loop over cut cells { int jCell = jSub2jCell[jsub]; if (!speciesBitMask[jCell]) { continue; } int iSpc = 0; if (Xbasis != null) { int NoOfSpc = regions.GetNoOfSpecies(jCell); iSpc = regions.GetSpeciesIndex(species, jCell); } var MassSub = Mass.ExtractSubArrayShallow(new int[] { jsub, 0, 0 }, new int[] { jsub - 1, N - 1, N - 1 }); int i0 = mapping.GlobalUniqueCoordinateIndex(fld, jCell, N * iSpc); for (int n = 0; n < N; n++) // loop over rows (within block) { for (int m = 0; m < N; m++) // loop over columns (within block) { M[i0 + n, i0 + m] += alpha * MassSub[n, m] - (m == n ? alpha : 0.0); } } } } } } } } }