Пример #1
0
        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);
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        /// <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;
 }
Пример #6
0
        /// <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());
            }
        }
Пример #7
0
        /// <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;
 }
Пример #9
0
        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);
        }
Пример #10
0
        /// <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());
            }
        }