Beispiel #1
0
        /// <summary>
        /// clone
        /// </summary>
        public object Clone()
        {
            var ret = new BCElement();

            ret.GlobalID             = this.GlobalID;
            ret.TransformationParams = this.TransformationParams.CloneAs();
            ret.NodeIndices          = this.NodeIndices.CloneAs();
            ret.EdgeTag = this.EdgeTag;
            ret.Type    = this.Type;
            return(ret);
        }
Beispiel #2
0
        static bool AreCellsEqual(GridCommons A, GridCommons B)
        {
            if (object.ReferenceEquals(A, B))
            {
                return(true);
            }
            if ((A == null) != (B == null))
            {
                return(false);
            }


            if (A.Cells == null)
            {
                throw new ArgumentException();
            }
            int A_NumberOfBcCells = A.NumberOfBcCells;

            int match = 1;

            {
                // load cells of grid B, if required
                // ---------------------------------

                Cell[] B_Cells;
                if (B.Cells == null)
                {
                    throw new Exception("Cells are not initialized");
                }
                else
                {
                    B_Cells = B.Cells;
                }

                if (A.Cells.Length != B_Cells.Length)
                {
                    throw new ApplicationException();
                }

                // put the cells of B into the same order as those of A
                // ----------------------------------------------------

                {
                    // tau   is the GlobalID-permutation that we have for the loaded vector
                    // sigma is the current GlobalID-permutation of the grid
                    var sigma = new Permutation(A.Cells.Select(cell => cell.GlobalID).ToArray(), csMPI.Raw._COMM.WORLD);
                    var tau   = new Permutation(B_Cells.Select(cell => cell.GlobalID).ToArray(), csMPI.Raw._COMM.WORLD);

                    if (sigma.TotalLength != tau.TotalLength)
                    {
                        // should have been checked already
                        throw new ArgumentException();
                    }

                    // compute resorting permutation
                    Permutation invSigma  = sigma.Invert();
                    Permutation Resorting = invSigma * tau;
                    tau      = null; // Werfen wir sie dem GC zum Fraße vor!
                    invSigma = null;

                    // put dg coordinates into right order
                    Resorting.ApplyToVector(B_Cells.CloneAs(), B_Cells);
                }

                // compare cells
                // -------------

                for (int j = 0; j < A.Cells.Length; j++)
                {
                    Cell Ca = A.Cells[j];
                    Cell Cb = B_Cells[j];

                    Debug.Assert(Ca.GlobalID == Cb.GlobalID);

                    if (!ArrayTools.ListEquals(Ca.NodeIndices, Cb.NodeIndices, (ia, ib) => ia == ib))
                    {
                        match = 0;
                        break;
                    }

                    if (Ca.Type != Cb.Type)
                    {
                        match = 0;
                        break;
                    }

                    if (Ca.CellFaceTags != null || Cb.CellFaceTags != null)
                    {
                        CellFaceTag[] CFTA = Ca.CellFaceTags != null ? Ca.CellFaceTags : new CellFaceTag[0];
                        CellFaceTag[] CFTB = Cb.CellFaceTags != null ? Cb.CellFaceTags : new CellFaceTag[0];

                        if (CFTA.Length != CFTB.Length)
                        {
                            match = 0;
                            break;
                        }

                        bool setMatch = true;
                        for (int i1 = 0; i1 < CFTA.Length; i1++)
                        {
                            bool b = false;
                            for (int j1 = 0; j1 < CFTB.Length; j1++)
                            {
                                if (CFTA[i1].Equals(CFTB[j1]))
                                {
                                    b = true;
                                    break;
                                }
                            }

                            if (b == false)
                            {
                                setMatch = false;
                                break;
                            }
                        }

                        if (!setMatch)
                        {
                            match = 0;
                            break;
                        }
                    }


                    double h      = Math.Min(Ca.TransformationParams.MindistBetweenRows(), Cb.TransformationParams.MindistBetweenRows());
                    double L2Dist = Ca.TransformationParams.L2Dist(Cb.TransformationParams);
                    if (L2Dist > h * 1.0e-9)
                    {
                        match = 0;
                        break;
                    }
                }
            }


            if (A_NumberOfBcCells > 0)
            {
                BCElement[] B_BcCells;
                if (B.BcCells == null && !B.BcCellsStorageGuid.Equals(Guid.Empty))
                {
                    throw new Exception("Bc Cells are not initialized");
                }
                else
                {
                    B_BcCells = B.BcCells;
                }

                if (A.BcCells.Length != B_BcCells.Length)
                {
                    throw new ApplicationException("Internal error.");
                }


                // put the cells of B into the same order as those of A
                // ----------------------------------------------------

                {
                    long Offset = A.NumberOfCells_l;

                    // tau   is the GlobalID-permutation that we have for the loaded vector
                    // sigma is the current GlobalID-permutation of the grid
                    var sigma = new Permutation(A.BcCells.Select(cell => cell.GlobalID - Offset).ToArray(), csMPI.Raw._COMM.WORLD);
                    var tau   = new Permutation(B_BcCells.Select(cell => cell.GlobalID - Offset).ToArray(), csMPI.Raw._COMM.WORLD);

                    if (sigma.TotalLength != tau.TotalLength)
                    {
                        // should have been checked already
                        throw new ArgumentException();
                    }

                    // compute resorting permutation
                    Permutation invSigma  = sigma.Invert();
                    Permutation Resorting = invSigma * tau;
                    tau      = null; // Werfen wir sie dem GC zum Fraße vor!
                    invSigma = null;

                    // put dg coordinates into right order
                    Resorting.ApplyToVector(B_BcCells.CloneAs(), B_BcCells);
                }


                // compare cells
                // -------------

                for (int j = 0; j < A.BcCells.Length; j++)
                {
                    BCElement Ca = A.BcCells[j];
                    BCElement Cb = B_BcCells[j];

                    Debug.Assert(Ca.GlobalID == Cb.GlobalID);

                    if (!ArrayTools.ListEquals(Ca.NodeIndices, Cb.NodeIndices, (ia, ib) => ia == ib))
                    {
                        match = 0;
                        break;
                    }

                    if (Ca.Type != Cb.Type)
                    {
                        match = 0;
                        break;
                    }

                    if (Ca.Conformal != Cb.Conformal)
                    {
                        match = 0;
                        break;
                    }

                    if (Ca.EdgeTag != Cb.EdgeTag)
                    {
                        match = 0;
                        break;
                    }


                    if (Ca.NeighCell_GlobalIDs != null || Cb.NeighCell_GlobalIDs != null)
                    {
                        long[] NgA = Ca.NeighCell_GlobalIDs != null ? Ca.NeighCell_GlobalIDs : new long[0];
                        long[] NgB = Cb.NeighCell_GlobalIDs != null ? Cb.NeighCell_GlobalIDs : new long[0];

                        if (NgA.Length != NgB.Length)
                        {
                            match = 0;
                            break;
                        }

                        bool setMatch = true;
                        for (int i1 = 0; i1 < NgA.Length; i1++)
                        {
                            bool b = false;
                            for (int j1 = 0; j1 < NgB.Length; j1++)
                            {
                                if (NgA[i1] == NgB[j1])
                                {
                                    b = true;
                                    break;
                                }
                            }

                            if (b == false)
                            {
                                setMatch = false;
                                break;
                            }
                        }

                        if (!setMatch)
                        {
                            match = 0;
                            break;
                        }
                    }


                    double h      = Math.Min(Ca.TransformationParams.MindistBetweenRows(), Cb.TransformationParams.MindistBetweenRows());
                    double L2Dist = Ca.TransformationParams.L2Dist(Cb.TransformationParams);
                    if (L2Dist > h * 1.0e-9)
                    {
                        match = 0;
                        break;
                    }
                }
            }


            match = match.MPIMin();
            return(match > 0);
        }
Beispiel #3
0
        /// <summary>
        /// Concatenates grids <paramref name="A"/> and <paramref name="B"/> into one data structure.
        /// </summary>
        public static GridCommons MergeLogically(GridCommons A, GridCommons B)
        {
            GridCommons R = new GridCommons();

            R.m_GridGuid = Guid.NewGuid();


            //R.BcCellPartitioning; R.m_BcCellPartitioning
            //R.BcCells;
            //R.BcCellsStorageGuid;
            //R.CellPartitioning;
            //R.Cells;
            //R.Description;
            //R.EdgeRefElements;
            //R.EdgeTagNames;
            //R.GridGuid; == R.ID;
            //R.InversePeriodicTrafo on-demand
            //R.m_ClassNameOfEdgeRefElement
            //R.m_RefElements;
            //R.m_EdgeRefElements;

            /////////////////////////
            // merge ref elements
            /////////////////////////
            {
                R.m_RefElements = A.m_RefElements.CloneAs();
                int[] BrefElm = new int[B.m_RefElements.Length];
                for (int iKrefB = 0; iKrefB < BrefElm.Length; iKrefB++)
                {
                    RefElement Kref      = B.m_RefElements[iKrefB];
                    int        iKrefBNew = R.m_RefElements.IndexOf(Kref, (a, b) => a.Equals(b));
                    if (iKrefBNew < 0)
                    {
                        ArrayTools.AddToArray(Kref, ref R.m_RefElements);
                        iKrefBNew = B.m_RefElements.Length - 1;
                    }
                    BrefElm[iKrefB] = iKrefBNew;
                }

                R.m_EdgeRefElements = A.m_EdgeRefElements.CloneAs();
                int[] BEdgeRefElm = new int[B.m_EdgeRefElements.Length];
                for (int iEdgeKrefB = 0; iEdgeKrefB < BEdgeRefElm.Length; iEdgeKrefB++)
                {
                    RefElement Kref          = B.m_EdgeRefElements[iEdgeKrefB];
                    int        iEdgeKrefBNew = R.m_EdgeRefElements.IndexOf(Kref, (a, b) => a.Equals(b));
                    if (iEdgeKrefBNew < 0)
                    {
                        ArrayTools.AddToArray(Kref, ref R.m_EdgeRefElements);
                        iEdgeKrefBNew = B.m_EdgeRefElements.Length - 1;
                    }
                    BEdgeRefElm[iEdgeKrefB] = iEdgeKrefBNew;
                }
            }

            //////////////////////////////////////////
            // merge edge tags & periodic transformations
            //////////////////////////////////////////

            byte[] BNewEdgeTag = new byte[0xff]; // mapping: old edge tag in B (index) => edge tag in R (content)
            {
                R.m_PeriodicTrafo.AddRange(A.m_PeriodicTrafo.Select(at => at.CloneAs()).ToArray());

                R.m_EdgeTagNames.AddRange(A.m_EdgeTagNames);
                foreach (var kv in B.m_EdgeTagNames)
                {
                    byte   _EdgeTagB = kv.Key, _NewEdgeTagB;
                    string NameB = kv.Value;

                    if (R.m_EdgeTagNames.ContainsValue(NameB))
                    {
                        _NewEdgeTagB = R.m_EdgeTagNames.First(kv2 => kv2.Value.Equals(NameB)).Key;
                    }
                    else
                    {
                        _NewEdgeTagB = R.m_EdgeTagNames.Keys.Where(et => et < FIRST_PERIODIC_BC_TAG).Max();
                    }
                    BNewEdgeTag[_EdgeTagB] = _NewEdgeTagB;
                }


                AffineTrafo[] BperiodicTrafo = B.m_PeriodicTrafo.Select(at => at.CloneAs()).ToArray();

                for (int i = 0; i < BperiodicTrafo.Length; i++)
                {
                    var Tr        = BperiodicTrafo[i];
                    int _BEdgeTag = i + FIRST_PERIODIC_BC_TAG;
                    int _BNewEdgeTag;
                    int idxTr = R.m_PeriodicTrafo.IndexOf(Tr, (TrA, TrB) => TrA.ApproximateEquals(TrB));
                    if (idxTr < 0)
                    {
                        R.m_PeriodicTrafo.Add(Tr);
                        _BNewEdgeTag = R.m_PeriodicTrafo.Count + FIRST_PERIODIC_BC_TAG - 1;
                        R.m_EdgeTagNames.Add((byte)_BNewEdgeTag, B.m_EdgeTagNames[(byte)_BEdgeTag]);
                    }
                    else
                    {
                        _BNewEdgeTag = idxTr + FIRST_PERIODIC_BC_TAG;
                    }

                    BNewEdgeTag[_BEdgeTag] = (byte)_BNewEdgeTag;
                }
            }

            //////////////////////////
            // merge cells (logically)
            //////////////////////////
            {
                int  NodeOffset = A.NodePartitioning.TotalLength;
                long JAglb      = A.NumberOfCells_l;
                long JBglb      = B.NumberOfCells_l;
                long KAglb      = A.NoOfBcCells.MPISum();
                long KBglb      = B.NoOfBcCells.MPISum();


                int JA = A.Cells.Length;
                int JB = B.Cells.Length;
                R.Cells = new Cell[JA + JB];
                int KA = A.NoOfBcCells;
                int KB = B.NoOfBcCells;
                R.BcCells = new BCElement[KA + KB];

                // check GlobalIds of cells
                for (int ja = 0; ja < JA; ja++)
                {
                    Cell CA = A.Cells[ja];
                    if (CA.GlobalID < 0 || CA.GlobalID >= JAglb)
                    {
                        throw new ArgumentException("Illegal GlobalId in grid A.", "A");
                    }
                }
                for (int jb = 0; jb < JB; jb++)
                {
                    Cell CB = B.Cells[jb];
                    if (CB.GlobalID < 0 || CB.GlobalID >= JBglb)
                    {
                        throw new ArgumentException("Illegal GlobalId in grid B.", "B");
                    }
                }
                // check globalIDs of boundary elements
                for (int ka = 0; ka < KA; ka++)
                {
                    BCElement BcA = A.BcCells[ka];
                    if (BcA.GlobalID < JAglb || BcA.GlobalID >= JAglb + KAglb)
                    {
                        throw new ArgumentException("Illegal GlobalId for boundary element in grid A.", "A");
                    }
                }
                for (int kb = 0; kb < KB; kb++)
                {
                    BCElement BcB = B.BcCells[kb];
                    if (BcB.GlobalID < JB || BcB.GlobalID >= JBglb + KBglb)
                    {
                        throw new ArgumentException("Illegal GlobalId for boundary element in grid B.", "B");
                    }
                }

                // cells of A:
                // -----------
                for (int ja = 0; ja < JA; ja++)
                {
                    Cell CA = A.Cells[ja];

                    R.Cells[ja] = new Cell()
                    {
                        GlobalID             = CA.GlobalID,
                        NodeIndices          = CA.NodeIndices == null ? null : CA.NodeIndices.CloneAs(),
                        Type                 = CA.Type,
                        TransformationParams = CA.TransformationParams.CloneAs(),
                        CellFaceTags         = CA.CellFaceTags == null ? null : CA.CellFaceTags.Select(tag => new CellFaceTag()
                        {
                            EdgeTag               = tag.EdgeTag,
                            FaceIndex             = tag.FaceIndex,
                            ConformalNeighborship = tag.ConformalNeighborship,
                            NeighCell_GlobalID    = tag.NeighCell_GlobalID < JAglb ?
                                                    tag.NeighCell_GlobalID :        // normal cell
                                                    tag.NeighCell_GlobalID + JBglb, // boundary element
                            PeriodicInverse = tag.PeriodicInverse
                        }).ToArray()
                    };

                    Debug.Assert(R.Cells[ja].GlobalID >= 0 && R.Cells[ja].GlobalID < JAglb);
                    if (CA.CellFaceTags != null)
                    {
                        for (int i = 0; i < CA.CellFaceTags.Length; i++)
                        {
                            var cft    = R.Cells[ja].CellFaceTags[i];
                            var orgCft = CA.CellFaceTags[i];

                            Debug.Assert(
                                (orgCft.NeighCell_GlobalID < JAglb && cft.NeighCell_GlobalID >= 0 && cft.NeighCell_GlobalID < JAglb) || // normall cell
                                (orgCft.NeighCell_GlobalID >= JAglb && cft.NeighCell_GlobalID >= JAglb + JBglb && cft.NeighCell_GlobalID < JAglb + JBglb + KAglb));    // boundary element
                        }
                    }
                }

                // cells of B:
                // -----------
                for (int jb = 0; jb < JB; jb++)
                {
                    Cell CB = B.Cells[jb];

                    R.Cells[jb + JA] = new Cell()
                    {
                        GlobalID             = CB.GlobalID + JAglb,
                        NodeIndices          = CB.NodeIndices == null ? null : CB.NodeIndices.Select(idx => idx + NodeOffset).ToArray(),
                        Type                 = CB.Type,
                        TransformationParams = CB.TransformationParams.CloneAs(),
                        CellFaceTags         = CB.CellFaceTags == null ? null : CB.CellFaceTags.Select(tag => new CellFaceTag()
                        {
                            EdgeTag               = BNewEdgeTag[tag.EdgeTag],
                            FaceIndex             = tag.FaceIndex,
                            ConformalNeighborship = tag.ConformalNeighborship,
                            NeighCell_GlobalID    = tag.NeighCell_GlobalID + JAglb, // correct for normal cell and boundary element
                            PeriodicInverse       = tag.PeriodicInverse
                        }).ToArray()
                    };

                    Debug.Assert(R.Cells[jb + JA].GlobalID >= JAglb && R.Cells[jb + JA].GlobalID < JAglb + JBglb);
                    if (CB.CellFaceTags != null)
                    {
                        for (int i = 0; i < CB.CellFaceTags.Length; i++)
                        {
                            var cft    = R.Cells[jb + JA].CellFaceTags[i];
                            var orgCft = CB.CellFaceTags[i];

                            Debug.Assert(
                                (orgCft.NeighCell_GlobalID < JBglb && cft.NeighCell_GlobalID >= JAglb && cft.NeighCell_GlobalID < JAglb + JBglb) || // normall cell
                                (orgCft.NeighCell_GlobalID >= JBglb && cft.NeighCell_GlobalID >= JAglb + JBglb + KAglb && cft.NeighCell_GlobalID < JAglb + JBglb + KAglb + KBglb));    // boundary element
                        }
                    }
                }

                // boundary elements of A:
                // -----------------------

                for (int ka = 0; ka < KA; ka++)
                {
                    BCElement BcA = A.BcCells[ka];

                    R.BcCells[ka] = new BCElement()
                    {
                        Conformal           = BcA.Conformal,
                        GlobalID            = BcA.GlobalID + JBglb,
                        NeighCell_GlobalIDs = BcA.NeighCell_GlobalIDs == null ? null : BcA.NeighCell_GlobalIDs.Select(
                            gidN => gidN < JAglb ? gidN : gidN + JBglb).ToArray(),
                        EdgeTag              = BcA.EdgeTag,
                        NodeIndices          = BcA.NodeIndices == null ? null : BcA.NodeIndices.CloneAs(),
                        TransformationParams = BcA.TransformationParams.CloneAs(),
                        Type = BcA.Type
                    };

                    Debug.Assert(R.BcCells[ka].GlobalID >= JAglb + JBglb && R.BcCells[ka].GlobalID < JAglb + JBglb + KAglb);
                    if (BcA.NeighCell_GlobalIDs != null)
                    {
                        for (int i = 0; i < BcA.NeighCell_GlobalIDs.Length; i++)
                        {
                            long Ngid    = R.BcCells[ka].NeighCell_GlobalIDs[i];
                            long orgNgid = BcA.NeighCell_GlobalIDs[i];

                            Debug.Assert((orgNgid < JAglb && Ngid >= 0 && Ngid < JAglb) || // normall cell
                                         (orgNgid >= JAglb && Ngid >= JAglb + JBglb && Ngid < JAglb + JBglb + KAglb)); // boundary element
                        }
                    }
                }

                // boundary elements of B:
                // -----------------------

                for (int kb = 0; kb < KB; kb++)
                {
                    BCElement BcB = A.BcCells[kb];

                    R.BcCells[kb + KA] = new BCElement()
                    {
                        Conformal           = BcB.Conformal,
                        GlobalID            = BcB.GlobalID + JAglb,
                        NeighCell_GlobalIDs = BcB.NeighCell_GlobalIDs == null ? null : BcB.NeighCell_GlobalIDs.Select(
                            gidN => gidN < JBglb ? gidN + JAglb : gidN + JAglb).ToArray(),
                        EdgeTag              = BNewEdgeTag[BcB.EdgeTag],
                        NodeIndices          = BcB.NodeIndices == null ? null : BcB.NodeIndices.Select(idx => idx + NodeOffset).ToArray(),
                        TransformationParams = BcB.TransformationParams.CloneAs(),
                        Type = BcB.Type
                    };

                    Debug.Assert(R.BcCells[kb].GlobalID >= JAglb + JBglb + KAglb && R.BcCells[kb].GlobalID < JAglb + JBglb + KAglb + KBglb);
                    if (BcB.NeighCell_GlobalIDs != null)
                    {
                        for (int i = 0; i < BcB.NeighCell_GlobalIDs.Length; i++)
                        {
                            long Ngid    = R.BcCells[kb + KA].NeighCell_GlobalIDs[i];
                            long orgNgid = BcB.NeighCell_GlobalIDs[i];

                            Debug.Assert((orgNgid < JBglb && Ngid >= JAglb && Ngid < JAglb + JBglb) || // normall cell
                                         (orgNgid >= JBglb && Ngid >= JAglb + JBglb + KAglb && Ngid < JAglb + JBglb + KAglb + KBglb)); // boundary element
                        }
                    }
                }
            }

            return(R);
        }