/// <summary> /// Constructor /// </summary> /// <param name="__ProblemMapping"> /// Mapping of original problem, equal to <see cref="ProblemMapping"/>. /// </param> /// <param name="__aggGrdB"> /// Sequence of aggregation grid DG basis objects, correlates to original mapping /// </param> /// <param name="DgDegrees"></param> public MultigridMapping(UnsetteledCoordinateMapping __ProblemMapping, AggregationGridBasis[] __aggGrdB, int[] DgDegrees) { using (new FuncTrace()) { // check args // =========== if (__aggGrdB.Length != __ProblemMapping.BasisS.Count) { throw new ArgumentException("Mismatch between number of multigrid basis objects and number of variables in problem mapping."); } var mgGrid = __aggGrdB[0].AggGrid; for (int iVar = 0; iVar < __aggGrdB.Length; iVar++) { if (__ProblemMapping.BasisS[iVar] is BoSSS.Foundation.XDG.XDGBasis) { if (!(__aggGrdB[iVar] is XdgAggregationBasis)) { throw new ArgumentException(); } } else if (__ProblemMapping.BasisS[iVar] is BoSSS.Foundation.Basis) { //if((__aggGrdB[iVar] is XdgAggregationBasis)) // throw new ArgumentException(); } if (!object.ReferenceEquals(mgGrid, __aggGrdB[iVar].AggGrid)) { throw new ArgumentException("Basis object must all be defined on the same grid."); } } // find basis with maximum degree // ============================== this.ProblemMapping = __ProblemMapping; //this.MaxBasis = ProblemMapping.BasisS.ElementAtMax(basis => basis.Degree); this.m_DgDegree = DgDegrees.CloneAs(); //if(!this.MaxBasis.IsSubBasis(__aggGrdB.DGBasis)) { // throw new ArgumentException("Basis on aggregation grid is insufficient;"); //} if (m_DgDegree.Length != __ProblemMapping.BasisS.Count()) { throw new ArgumentException("Wrong number of DG degrees."); } for (int i = 0; i < m_DgDegree.Length; i++) { if (m_DgDegree[i] < 0) { throw new ArgumentException("DG degree must be greater of equal to 0."); } if (m_DgDegree[i] > __ProblemMapping.BasisS[i].Degree) { throw new ArgumentException("DG degree on sub-level can not exceed DG degree of the original problem."); } } // create basis for this level // =========================== this.AggBasis = __aggGrdB; // min/max length // ============== { int Smin = 0; int Smax = 0; int Nofields = this.m_DgDegree.Length; for (int ifld = 0; ifld < Nofields; ifld++) { Smin += this.AggBasis[ifld].GetMinimalLength(this.m_DgDegree[ifld]); Smax += this.AggBasis[ifld].GetMaximalLength(this.m_DgDegree[ifld]); } this.MinimalLength = Smin; this.MaximalLength = Smax; } // offsets // ======= if (this.MinimalLength != this.MaximalLength) { int JAGGloc = this.AggGrid.iLogicalCells.NoOfLocalUpdatedCells; int JAGGtot = this.AggGrid.iLogicalCells.Count; int[] __i0Tmp = new int[JAGGtot]; HashSet <int> BlockLen = new HashSet <int>(); int LL = 0; for (int jag = 0; jag < JAGGloc; jag++) { int S = 0; for (int i = 0; i < m_DgDegree.Length; i++) { S += this.AggBasis[i].GetLength(jag, m_DgDegree[i]); } if (jag < JAGGloc - 1) { __i0Tmp[jag + 1] = __i0Tmp[jag] + S; } else { LL = __i0Tmp[jag] + S; } BlockLen.Add(S); } Partitioning = new Partitioning(LL); int i0Part = Partitioning.i0; m_i0 = new int[JAGGtot + 1]; for (int jag = 0; jag < JAGGloc; jag++) { m_i0[jag] = __i0Tmp[jag]; // store local i0 index __i0Tmp[jag] += i0Part; // convert to global index } m_i0[JAGGloc] = LL; __i0Tmp.MPIExchange(this.AggGrid); // compute global cell i0's in the external range m_i0_ExtGlob = new int[JAGGtot - JAGGloc]; Array.Copy(__i0Tmp, JAGGloc, m_i0_ExtGlob, 0, JAGGtot - JAGGloc); // compute local cell i0's in the external range (very confusing) for (int jag = JAGGloc; jag < JAGGtot; jag++) { int S = 0; for (int i = 0; i < m_DgDegree.Length; i++) { S += this.AggBasis[i].GetLength(jag, m_DgDegree[i]); } m_i0[jag + 1] = this.m_i0[jag] + S; BlockLen.Add(S); } // build look-up for block types m_Len2SublockType = new Dictionary <int, int>(); m_Subblk_i0 = new int[BlockLen.Count][]; m_SubblkLen = new int[BlockLen.Count][]; int type = 0; foreach (int S in BlockLen) { m_Subblk_i0[type] = new int[] { 0 }; m_SubblkLen[type] = new int[] { S }; m_Len2SublockType.Add(S, type); type++; } #if DEBUG for (int jag = JAGGloc; jag < JAGGtot; jag++) { Debug.Assert(Partitioning.IsInLocalRange(m_i0_ExtGlob[jag - JAGGloc]) == false); } #endif } else { m_Subblk_i0 = new int[][] { new int[] { 0 } }; m_SubblkLen = new int[][] { new int[] { this.MaximalLength } }; Partitioning = new Partitioning(this.AggGrid.iLogicalCells.NoOfLocalUpdatedCells * this.MaximalLength); } Debug.Assert(Partitioning != null); Debug.Assert(Partitioning.LocalLength == this.LocalLength); } }