/// <summary> /// Updates the XDG component of an aggregation basis according to the new agglomeration. /// </summary> public static void UpdateXdgAggregationBasis(this AggregationGridBasis[][] MultigridBasis, MultiphaseCellAgglomerator CurrentAgglomeration) { bool useX = false; var _XdgAggregationBasis = new XdgAggregationBasis[MultigridBasis.Length]; for (int iLevel = 0; iLevel < MultigridBasis.Length; iLevel++) { XdgAggregationBasis[] xab = MultigridBasis[iLevel].Where(b => b is XdgAggregationBasis).Select(b => ((XdgAggregationBasis)b)).ToArray(); if (xab != null && xab.Length > 0) { for (int ib = 1; ib < xab.Length; ib++) { if (!(object.ReferenceEquals(xab[ib].DGBasis.GridDat, CurrentAgglomeration.Tracker.GridDat))) { throw new ApplicationException(); } if (!object.ReferenceEquals(xab[0], xab[ib])) { throw new ArgumentException("One should only use one XDG aggregation basis per multigrid level."); } } _XdgAggregationBasis[iLevel] = xab[0]; useX = true; } } if (useX) { foreach (var xmgb in _XdgAggregationBasis) { xmgb.Update(CurrentAgglomeration); } } }
/// <summary> /// ctor. /// </summary> /// <param name="xb"> /// XDG basis on original grid /// </param> /// <param name="parentBasis"> /// basis on parent grid /// </param> /// <param name="ag"> /// aggregation grid level. /// </param> /// <param name="inj"> /// injection operators. /// </param> internal XdgAggregationBasis(XDGBasis xb, XdgAggregationBasis parentBasis, AggregationGridData ag, MultidimensionalArray[] inj) : base(xb.NonX_Basis, parentBasis, ag, inj) // { using (new FuncTrace()) { this.XDGBasis = xb; this.XCompositeBasis = new MultidimensionalArray[base.AggGrid.iLogicalCells.NoOfLocalUpdatedCells][]; } }
/// <summary> /// Returns global unique indices which correlate to a certain species and basises. /// </summary> /// <param name="Fields"> /// Indices into <see cref="BasisS"/> /// </param> /// <param name="map"> /// </param> /// <returns>a list of global (over all MPI processes) unique indices.</returns> public int[] GetSubvectorIndices(Foundation.XDG.SpeciesId Species, params int[] Fields) { var map = this.ProblemMapping; var _BasisS = map.BasisS.ToArray(); //XdgAggregationBasis XaggBasis; //if(this.AggBasis is XdgAggregationBasis) { // // super-quick and super-dirty fix // XaggBasis = (XdgAggregationBasis)(this.AggBasis); // foreach(var b in _BasisS) { // if(!b.IsSubBasis(XaggBasis.XDGBasis)) // throw new ArgumentException(); // } //} else { // throw new NotSupportedException(); //} XdgAggregationBasis[] XaggBasis = new XdgAggregationBasis[_BasisS.Length]; for (int iVar = 0; iVar < _BasisS.Length; iVar++) { Basis b = _BasisS[iVar]; if (b is BoSSS.Foundation.XDG.XDGBasis) { if (!b.IsSubBasis(((XdgAggregationBasis)(this.AggBasis[iVar])).XDGBasis)) { throw new ArgumentException(); } XaggBasis[iVar] = ((XdgAggregationBasis)(this.AggBasis[iVar])); } else { //if(!b.IsSubBasis(this.AggBasis[iVar].DGBasis)) // throw new ArgumentException(); throw new NotSupportedException(); } } var ag = this.AggGrid; int JAGG = ag.iLogicalCells.NoOfLocalUpdatedCells; Partitioning p = new Partitioning(JAGG); List <int> R = new List <int>(); int j0_aggCell = p.i0; { int Nofields = this.m_DgDegree.Length; int[] Nfld = new int[Nofields]; int[] Ofst = new int[Nofields]; int i0 = this.Partitioning.i0; for (int jAgg = 0; jAgg < JAGG; jAgg++) { for (int ifld = 0; ifld < Nofields; ifld++) { int pField = this.m_DgDegree[ifld]; Nfld[ifld] = this.AggBasis[ifld].GetLength(jAgg, pField); if (ifld > 0) { Ofst[ifld] = Ofst[ifld - 1] + Nfld[ifld - 1]; } } int Ncell = Ofst[Nofields - 1] + Nfld[Nofields - 1]; for (int i = 0; i < Fields.Length; i++) { int iSpc = XaggBasis[i].GetSpeciesIndex(jAgg, Species); if (iSpc >= 0) { int NoSpc = XaggBasis[i].GetNoOfSpecies(jAgg); int iField = Fields[i]; int pField = this.m_DgDegree[iField]; int N_iField = Nfld[iField]; int N0 = Ofst[iField]; int N_Spc = N_iField / NoSpc; Debug.Assert(N_iField % NoSpc == 0); for (int n = 0; n < N_Spc; n++) { int iX = i0 + n + N0 + N_Spc * iSpc; R.Add(iX); Debug.Assert(this.Partitioning.IsInLocalRange(iX)); Debug.Assert(iX - j0_aggCell == this.LocalUniqueIndex(iField, jAgg, n + N_Spc * iSpc)); } } } i0 += Ncell; } } return(R.ToArray()); }
/// <summary> /// Prolongation/Injection operator to finer grid level. /// </summary> public BlockMsrMatrix GetProlongationOperator(MultigridMapping finerLevel) { using (new FuncTrace()) { // Argument checking // ================= if (!object.ReferenceEquals(finerLevel.AggGrid, this.AggGrid.ParentGrid)) { throw new ArgumentException("Only prolongation/injection to next level is supported."); } if (finerLevel.AggBasis.Length != this.AggBasis.Length) { throw new ArgumentException(""); } int NoOfVar = this.AggBasis.Length; MultidimensionalArray[][] InjOp = new MultidimensionalArray[NoOfVar][]; AggregationGridBasis[] B = new AggregationGridBasis[NoOfVar]; bool[] useX = new bool[NoOfVar]; int[] DegreeS = new int[NoOfVar]; int[] DegreeSfine = new int[NoOfVar]; for (int iVar = 0; iVar < NoOfVar; iVar++) { InjOp[iVar] = this.AggBasis[iVar].InjectionOperator; B[iVar] = AggBasis[iVar]; DegreeS[iVar] = this.DgDegree[iVar]; DegreeSfine[iVar] = finerLevel.DgDegree[iVar]; if (DegreeSfine[iVar] < DegreeS[iVar]) { throw new ArgumentException("Lower DG degree on finer grid is not supported by this method "); } useX[iVar] = this.AggBasis[iVar] is XdgAggregationBasis; if (useX[iVar] != (finerLevel.AggBasis[iVar] is XdgAggregationBasis)) { throw new ArgumentException("XDG / DG mismatch between this and finer level for " + iVar + "-th variable."); } } XdgAggregationBasis XB = null; XdgAggregationBasis XBf = null; int[][,] spcIdxMap = null; SpeciesId[][] spc = null; //SpeciesId[][] spcf = null; for (int iVar = 0; iVar < NoOfVar; iVar++) { if (useX[iVar]) { XB = (XdgAggregationBasis)(B[iVar]); XBf = (XdgAggregationBasis)(finerLevel.AggBasis[iVar]); spcIdxMap = XB.SpeciesIndexMapping; spc = XB.AggCellsSpecies; //spcf = XBf.AggCellsSpecies; break; } } int[] Np = this.AggBasis[0].GetNp(); int[] Np_fine = finerLevel.AggBasis[0].GetNp(); // create matrix // ============= // init retval var PrlgMtx = new BlockMsrMatrix(finerLevel, this); int[][] C2F = this.AggGrid.jCellCoarse2jCellFine; int JCoarse = this.AggGrid.iLogicalCells.NoOfLocalUpdatedCells; //Debug.Assert((JCoarse == C2F.Length) || ()); for (int jc = 0; jc < JCoarse; jc++) // loop over coarse cells... { int[] AggCell = C2F[jc]; int I = AggCell.Length; for (int iVar = 0; iVar < NoOfVar; iVar++) { int DgDeg = DegreeS[iVar]; int DgDegF = DegreeSfine[iVar]; MultidimensionalArray Inj_iVar_jc = InjOp[iVar][jc]; Debug.Assert(Inj_iVar_jc.GetLength(0) == I); bool useX_iVar = false; if (useX[iVar]) { if (spcIdxMap[jc] != null) { useX_iVar = true; } } if (useX_iVar) { //throw new NotImplementedException("todo"); int NoOfSpc = XB.GetNoOfSpecies(jc); int Np_col = Np[DgDeg]; Debug.Assert(Np_col * NoOfSpc == B[iVar].GetLength(jc, DgDeg)); for (int iSpc = 0; iSpc < NoOfSpc; iSpc++) // loop over species { SpeciesId spc_jc_i = spc[jc][iSpc]; int Col0 = this.GlobalUniqueIndex(iVar, jc, Np_col * iSpc); for (int i = 0; i < I; i++) // loop over finer cells { int jf = AggCell[i]; int iSpc_Row = XBf.GetSpeciesIndex(jf, spc_jc_i); if (iSpc_Row < 0) { // nothing to do continue; } int Np_row = Np_fine[DgDegF]; Debug.Assert(Np_row * XBf.GetNoOfSpecies(jf) == finerLevel.AggBasis[iVar].GetLength(jf, DgDegF)); int Row0 = finerLevel.GlobalUniqueIndex(iVar, jf, Np_row * iSpc_Row); //if(Row0 <= 12 && 12 < Row0 + Np_row) { // if(Col0 <= 3 && 3 < Col0 + Np_col) { // Debugger.Break(); // } //} PrlgMtx.AccBlock(Row0, Col0, 1.0, Inj_iVar_jc.ExtractSubArrayShallow(new[] { i, 0, 0 }, new[] { i - 1, Np_row - 1, Np_col - 1 })); } } } else { // ++++++++++++++++++ // standard DG branch // ++++++++++++++++++ int Np_col = Np[DgDeg]; Debug.Assert(Np_col == B[iVar].GetLength(jc, DgDeg)); int Col0 = this.GlobalUniqueIndex(iVar, jc, 0); for (int i = 0; i < I; i++) // loop over finer cells { int jf = AggCell[i]; int Np_row = Np_fine[DgDegF]; Debug.Assert(Np_row == finerLevel.AggBasis[iVar].GetLength(jf, DgDegF)); int Row0 = finerLevel.GlobalUniqueIndex(iVar, jf, 0); PrlgMtx.AccBlock(Row0, Col0, 1.0, Inj_iVar_jc.ExtractSubArrayShallow(new[] { i, 0, 0 }, new[] { i - 1, Np_row - 1, Np_col - 1 })); //if(Row0 <= 12 && 12 < Row0 + Np_row) { // if(Col0 <= 3 && 3 < Col0 + Np_col) { // Debugger.Break(); // } // } } } } } // return // ====== return(PrlgMtx); } }