static bool IsAnc(IGridData gdat, AggregationGridData aGdat) { if (object.ReferenceEquals(aGdat.ParentGrid, gdat)) { return(true); } if (aGdat.ParentGrid is AggregationGridData) { return(IsAnc(gdat, (AggregationGridData)(aGdat.ParentGrid))); } return(false); }
/// <summary> /// creates an initial aggregated grid which is in fact equivalent to <paramref name="g"/> /// </summary> public static AggregationGridData ZeroAggregation(IGridData g) { //var Cls = g.Cells; int J = g.iLogicalCells.NoOfLocalUpdatedCells; int D = g.SpatialDimension; int[][] AggregateCells = new int[J][]; for (int j = 0; j < J; j++) { AggregateCells[j] = new int[] { j }; } AggregationGridData ret = new AggregationGridData(g, AggregateCells); return(ret); }
/// <summary> /// Constructor. /// </summary> /// <param name="pGrid"> /// Parent grid. /// </param> /// <param name="AggregationCells"> /// Coarse cells which build up the fine cells. /// - 1st index: coarse (i.e. this) grid cell index /// - 2nd index: enumeration /// - content: local cell index into the parent grid <paramref name="pGrid"/>. /// </param> /// <param name="AggregationCellGids"> /// GlobalID's for each of the <paramref name="AggregationCells"/>; /// Optional, can be null - in this case, GlobalID's are chosen automatically; /// If not null, length must be equal to 1st length of <paramref name="AggregationCells"/>. /// </param> public AggregationGrid(IGrid pGrid, int[][] AggregationCells, long[] AggregationCellGids = null) { m_ParentGrid = pGrid; m_ParentGridID = pGrid.ID; m_GridGuid = Guid.NewGuid(); if (AggregationCellGids != null) { if (AggregationCellGids.Length != AggregationCells.Length) { throw new ArgumentException("array length mismatch"); } } m_CellPartitioning = new Partitioning(AggregationCells.Length); var gdat = new AggregationGridData(this, AggregationCells); int J = AggregationCells.Length; if (AggregationCellGids == null) { AggregationCellGids = new long[J]; int i0 = m_CellPartitioning.i0; for (int j = 0; j < J; j++) { AggregationCellGids[j] = j + i0; } } long[] parentGid = pGrid.iGridData.CurrentGlobalIdPermutation.Values; AggCells = new AggCell[J]; for (int j = 0; j < J; j++) { int[] AggCell = AggregationCells[j]; int L = AggCell.Length; AggCells[j].GlobalID = AggregationCellGids[j]; AggCells[j].PartGlobalId = new long[L]; long[] _PartGlobalId = AggCells[j].PartGlobalId; for (int iPart = 0; iPart < L; iPart++) { _PartGlobalId[iPart] = parentGid[AggCell[iPart]]; } } m_GridData = gdat; }
MultidimensionalArray CA(int _jAgg, int Np) { AggregationGridData ag = this.m_owner; var compCell = ag.iLogicalCells.AggregateCellToParts[_jAgg]; int thisMgLevel = ag.MgLevel; var scl = m_owner.AncestorGrid.ChefBasis.Scaling; var R = MultidimensionalArray.Create(compCell.Length, Np, Np); for (int i = 0; i < compCell.Length; i++) { int jG = compCell[i]; if (!m_owner.AncestorGrid.Cells.IsCellAffineLinear(jG)) { throw new NotImplementedException("nonlin cell -- todo"); } for (int n = 0; n < Np; n++) { R[i, n, n] = scl[jG]; } } #if DEBUG bool[] btouch = new bool[compCell.Length]; #endif int[] AggIndex = new int[] { _jAgg }; _BasisData basisLevel = this; for (int mgLevelIdx = thisMgLevel; mgLevelIdx >= 0; mgLevelIdx--) { AggregationGridData mgLevel = basisLevel.m_owner; int[][] agg2part_parrent = mgLevel.ParentGrid.iLogicalCells.AggregateCellToParts; #if DEBUG btouch.Clear(); #endif foreach (int jAgg in AggIndex) { //MultidimensionalArray Inj_j; //if (mgLevelIdx > 0) { var Inj_j = basisLevel.Injectors[jAgg]; //} else { // Inj_j = MultidimensionalArray.Create(1, Np, Np); // for (int n = 0; n < Np; n++) { // m_CompositeBasis[jAgg][0, n, n] = 1.0; // } //} int[] FineAgg = mgLevel.jCellCoarse2jCellFine[jAgg]; Debug.Assert(FineAgg.Length == Inj_j.GetLength(0)); for (int iSrc = 0; iSrc < FineAgg.Length; iSrc++) // loop over finer level cells { int jAgg_fine = FineAgg[iSrc]; // Inj_j[iSrc,-,-] is injector // from cell 'jAgg' on level 'mgLevelIdx' (coarse level) // to cell 'jAgg_fine' on level 'mgLevelIdx - 1' (fine level) var Inj_j_iSrc = Inj_j.ExtractSubArrayShallow(iSrc, -1, -1); int[] TargCells;// = mgLevel.ParentGrid.iLogicalCells.AggregateCellToParts[jAgg_fine]; if (agg2part_parrent != null) { TargCells = agg2part_parrent[jAgg_fine]; } else { TargCells = new int[] { jAgg_fine } }; foreach (int j in TargCells) { int iTarg = Array.IndexOf(compCell, j); if (iTarg < 0) { throw new ApplicationException("error in alg"); } #if DEBUG if (btouch[iTarg] == true) { throw new ApplicationException(); } btouch[iTarg] = true; #endif var R_iTarg = R.ExtractSubArrayShallow(iTarg, -1, -1); R_iTarg.Multiply(1.0, Inj_j_iSrc, R_iTarg.CloneAs(), 0.0, "nm", "nk", "km"); //if (thisMgLevel == 1 && Np == 10) { // var check = MultidimensionalArray.Create(Np, Np); // check.GEMM(1.0, R_iTarg, R_iTarg.Transpose(), 0.0); // check.AccEye(-1.0); // var bla = check.InfNorm(); // Console.WriteLine("Check norm: " + bla); //} } } } // Rekursions-Scheisse: // - - - - - - - - - - - //if (mgLevelIdx > 0) { { List <int> nextAggIndex = new List <int>(); foreach (int jAgg in AggIndex) { int[] NextLevel = mgLevel.jCellCoarse2jCellFine[jAgg]; #if DEBUG foreach (int i in NextLevel) { Debug.Assert(nextAggIndex.Contains(i) == false); } #endif nextAggIndex.AddRange(NextLevel); } AggIndex = nextAggIndex.ToArray(); if (m_owner.ParentGrid is AggregationGridData) { basisLevel = ((AggregationGridData)(m_owner.ParentGrid)).m_ChefBasis; } else { basisLevel = null; } } //else { // AggIndex = null; // mgLevel = null; //} } return(R); } }
internal _BasisData(AggregationGridData o) : base(o) { m_owner = o; }
/// <summary> /// Creates a sequence of aggregated grids, suitable for a multigrid algorithm /// </summary> /// <param name="GridDat">original grid</param> /// <param name="MaxDepth">maximum number of refinements</param> /// <returns></returns> public static AggregationGridData[] CreateSequence(IGridData GridDat, int MaxDepth = -1) { using (new FuncTrace()) { int D = GridDat.SpatialDimension; MaxDepth = MaxDepth >= 0 ? MaxDepth : int.MaxValue; //int cutoff = MaxDepth < 0 ? int.MaxValue : MaxDepth * skip; // create sequence of aggregation multigrid grids and basises // ========================================================== List <AggregationGridData> aggGrids = new List <AggregationGridData>(); aggGrids.Add(ZeroAggregation(GridDat)); while (true) { if (aggGrids.Count >= MaxDepth) { break; } AggregationGridData grid = Coarsen(aggGrids.Last(), (int)(Math.Pow(2, D))); if ((grid.iLogicalCells.NoOfLocalUpdatedCells.MPISum() >= aggGrids.Last().iLogicalCells.NoOfLocalUpdatedCells.MPISum())) { // no more refinement possible break; } aggGrids.Add(grid); #if DEBUG int iLevel = aggGrids.Count - 2; // index of fine level (finer == low index) int JFine = aggGrids[iLevel].iLogicalCells.Count; int JCoarse = aggGrids[iLevel + 1].iLogicalCells.Count; Debug.Assert(aggGrids[iLevel + 1].iLogicalCells.Count == (aggGrids[iLevel + 1].iLogicalCells.NoOfLocalUpdatedCells + aggGrids[iLevel + 1].iLogicalCells.NoOfExternalCells)); // test that the coarse grid has significantly less cells than the fine grid. double dJfine = aggGrids[iLevel].iLogicalCells.NoOfLocalUpdatedCells; double dJcoarse = aggGrids[iLevel + 1].iLogicalCells.NoOfLocalUpdatedCells; if (JCoarse >= 10) { Debug.Assert(dJfine * 0.8 >= dJcoarse); } // test the coarse-to-fine map bool[] testMarker = new bool[JFine]; int[][] C2F = aggGrids[iLevel + 1].jCellCoarse2jCellFine; Debug.Assert(C2F.Length == JCoarse); for (int jC = 0; jC < JCoarse; jC++) { foreach (int jF in C2F[jC]) { Debug.Assert(testMarker[jF] == false); testMarker[jF] = true; } } for (int jF = 0; jF < JFine; jF++) { Debug.Assert(testMarker[jF] == true); } // test the fine-to-coarse mapping int[] F2C = aggGrids[iLevel + 1].jCellFine2jCellCoarse; Debug.Assert(F2C.Length == JFine); for (int jF = 0; jF < JFine; jF++) { Debug.Assert(C2F[F2C[jF]].Contains(jF)); } #endif } // return return(aggGrids.ToArray()); } }
/// <summary> /// assigns the cell index of the aggregated cell <em>j</em> to all (fine) grid cells that /// the aggregated cell <em>j</em> consists of. /// </summary> static public void ColorDGField(this AggregationGridData ag, DGField f) { IGridData Anc = f.GridDat; if (!IsAnc(Anc, ag)) { throw new ArgumentException("Field 'f' must be defined on an ancestor grid of 'ag'."); } f.Clear(); int Jag = ag.iLogicalCells.NoOfLocalUpdatedCells; int Janc = Anc.iLogicalCells.NoOfLocalUpdatedCells; Debug.Assert(Anc.iGeomCells.Count == ag.iGeomCells.Count); int[] jG2jL = Anc.iGeomCells.GeomCell2LogicalCell; int[] Colors = new int[Jag]; BitArray Marked = new BitArray(Janc); for (int j = 0; j < Jag; j++) // loop over logical/aggregate cells // determine colors of neighbor cells { int[] Neighs = ag.iLogicalCells.CellNeighbours[j]; var NeighColors = Neighs.Select(jN => Colors[jN]); // select color for cell 'j' int iCol = 1; for (iCol = 1; iCol < 2 * Jag; iCol++) { if (!NeighColors.Contains(iCol)) { break; } } Colors[j] = iCol; // color all logical cells in ancestor grid // idea: convert to geometrical and back to logical // in this way we can e.g. skip multiple grid levels foreach (int jGeom in ag.iLogicalCells.AggregateCellToParts[j]) { int jLogAnc; if (jG2jL != null) { jLogAnc = jG2jL[jGeom]; } else { jLogAnc = jGeom; } if (!Marked[jLogAnc]) { f.SetMeanValue(jLogAnc, iCol); Marked[jLogAnc] = true; } else { // nop } } } }
internal LogEdgeData(AggregationGridData __owner) { m_Owner = __owner; }
void InitGridData() { if (m_GridData != null) { return; } if (this.Size > 1) { Console.WriteLine("Warning: will probably not work in parallel"); } // compute mapping: // globalID -> Global Index for parent grid // ================================================= var ParentGids = this.ParentGrid.iGridData.CurrentGlobalIdPermutation; var ParentIdx = ParentGids.Invert(); // get parent grid indices for aggregation cells // ================================================= int[][] AggIdx; { int J = this.AggCells.Length; AggIdx = new int[J][]; int L = 0; for (int j = 0; j < J; j++) { L += this.AggCells[j].PartGlobalId.Length; } long[] InputBuffer = new long[L]; int l = 0; for (int j = 0; j < J; j++) { long[] src = this.AggCells[j].PartGlobalId; Array.Copy(src, 0, InputBuffer, l, src.Length); l += src.Length; } long[] EvalBuffer = new long[L]; ParentIdx.EvaluatePermutation(InputBuffer, EvalBuffer); int i0_Parent = ParentGrid.CellPartitioning.i0; int J_Parent = ParentGrid.iGridData.iLogicalCells.NoOfLocalUpdatedCells; l = 0; for (int j = 0; j < J; j++) { int AG = this.AggCells[j].PartGlobalId.Length; int[] AggIdx_j = new int[AG]; AggIdx[j] = AggIdx_j; for (int k = 0; k < AG; k++) // loop over parts of aggregation cell { Debug.Assert(EvalBuffer[l] >= 0); Debug.Assert(EvalBuffer[l] < ParentGrid.NumberOfCells); AggIdx_j[k] = (int)EvalBuffer[l] - i0_Parent; Debug.Assert(AggIdx_j[k] >= 0); Debug.Assert(AggIdx_j[k] < J_Parent); l++; } } } // create grid data // =================== m_GridData = new AggregationGridData(ParentGrid.iGridData, AggIdx); }
/// <summary> /// Creates a sequence of aggregated grids, suitable for a multigrid algorithm /// </summary> /// <param name="GridDat">original grid</param> /// <param name="MaxDepth">maximum number of refinements</param> /// <returns></returns> public static AggregationGridData[] CreateSequence(IGridData GridDat, int MaxDepth = -1) { using (new FuncTrace()) { int D = GridDat.SpatialDimension; MaxDepth = MaxDepth >= 0 ? MaxDepth : int.MaxValue; //int cutoff = MaxDepth < 0 ? int.MaxValue : MaxDepth * skip; // create sequence of aggregation multigrid grids and basises // ========================================================== List <AggregationGridData> aggGrids = new List <AggregationGridData>(); aggGrids.Add(ZeroAggregation(GridDat)); var localNoOfCells = new List <int>(); var globalNoOfCells = new List <int>(); localNoOfCells.Add(aggGrids[0].iLogicalCells.NoOfLocalUpdatedCells); globalNoOfCells.Add(aggGrids[0].CellPartitioning.TotalLength); while (true) { if (aggGrids.Count >= MaxDepth) { break; } AggregationGridData grid = Coarsen(aggGrids.Last(), (int)(Math.Pow(2, D))); //AggregationGridData grid = Coarsen_hardcoded(aggGrids.Last(), (int)(Math.Pow(2, D))); int Jloc = grid.CellPartitioning.LocalLength; int Jtot = grid.CellPartitioning.TotalLength; bool localReduction = (Jloc < localNoOfCells.Last()).MPIOr(); bool globalReduction = Jtot < globalNoOfCells.Last(); if (localReduction == false || globalReduction == false) { // no more refinement possible break; } aggGrids.Add(grid); localNoOfCells.Add(Jloc); globalNoOfCells.Add(Jtot); #if DEBUG int iLevel = aggGrids.Count - 2; // index of fine level (finer == low index) int JFine = aggGrids[iLevel].iLogicalCells.Count; int JCoarse = aggGrids[iLevel + 1].iLogicalCells.Count; Debug.Assert(aggGrids[iLevel + 1].iLogicalCells.Count == (aggGrids[iLevel + 1].iLogicalCells.NoOfLocalUpdatedCells + aggGrids[iLevel + 1].iLogicalCells.NoOfExternalCells)); // test that the coarse grid has significantly less cells than the fine grid. double dJfine = globalNoOfCells[iLevel]; double dJcoarse = globalNoOfCells[iLevel + 1]; if (JCoarse >= 10) { if (!(dJfine * 0.8 >= dJcoarse)) { Console.Error.WriteLine($"Warning: aggregation multigrid seems de-generate, nonly reducting from {globalNoOfCells[iLevel]} to {globalNoOfCells[iLevel + 1]} cells from level {iLevel} to {iLevel + 1}"); } } // test the coarse-to-fine map bool[] testMarker = new bool[JFine]; int[][] C2F = aggGrids[iLevel + 1].jCellCoarse2jCellFine; Debug.Assert(C2F.Length == JCoarse); for (int jC = 0; jC < JCoarse; jC++) { foreach (int jF in C2F[jC]) { Debug.Assert(testMarker[jF] == false); testMarker[jF] = true; } } for (int jF = 0; jF < JFine; jF++) { Debug.Assert(testMarker[jF] == true); } // test the fine-to-coarse mapping int[] F2C = aggGrids[iLevel + 1].jCellFine2jCellCoarse; Debug.Assert(F2C.Length == JFine); for (int jF = 0; jF < JFine; jF++) { Debug.Assert(C2F[F2C[jF]].Contains(jF)); } #endif } // return return(aggGrids.ToArray()); } }