Example #1
0
        /// <summary>
        /// sets values for <see cref="Cell.CellFaceTags"/> by using a
        /// <paramref name="EdgeTagFunc"/>-function; also adds entries with empty names
        /// to the <see cref="EdgeTagNames"/>-dictionary, if the edge tag
        /// returned by the <paramref name="EdgeTagFunc"/>-function is not in
        /// the dictionary
        /// </summary>
        static public void DefineEdgeTags(this IGrid g, Func <Vector, string> EdgeTagFunc, params string[] EdgeTagNamesToEnsure)
        {
            int D = g.SpatialDimension;

            double[] x = new double[D];
            MultidimensionalArray GlobalVerticesOut = MultidimensionalArray.CreateWrapper(x, 1, D);

            Dictionary <string, byte> EdgeTagNames_Reverse = new Dictionary <string, byte>();

            EdgeTagNames_Reverse.Add("inner edge", 0);
            int[] etUseCount = new int[byte.MaxValue];
            foreach (var kv in g.EdgeTagNames)
            {
                if (kv.Key == 0)
                {
                }
                else
                {
                    EdgeTagNames_Reverse.Add(kv.Value, kv.Key);

                    if (kv.Key >= GridCommons.FIRST_PERIODIC_BC_TAG)
                    {
                        etUseCount[kv.Key] = 1;
                    }
                }
            }



            GridCommons baseGrid = null;

            if (g is GridCommons gcm)
            {
                baseGrid = gcm;
            }
            else if (g is Aggregation.AggregationGrid ag)
            {
                baseGrid = ag.RootGrid as GridCommons;
            }
            var GrdDatTmp = g.iGridData;

            // loop over edges...
            bool LoopOverEdges(Func <int, int, int, byte> GetEt)
            {
                bool _GridChanged = false;
                int  NoOfEdges    = GrdDatTmp.iGeomEdges.Count;

                for (int iEdge = 0; iEdge < NoOfEdges; ++iEdge)
                {
                    if (GrdDatTmp.iGeomEdges.IsEdgeBoundaryEdge(iEdge))
                    {
                        int jCell = GrdDatTmp.iGeomEdges.CellIndices[iEdge, 0];
                        int iFace = GrdDatTmp.iGeomEdges.FaceIndices[iEdge, 0];

                        // get edge tag
                        byte et = GetEt(iEdge, jCell, iFace);

                        // record edge tag
                        if (baseGrid != null)
                        {
                            var _Cell   = baseGrid.Cells[jCell];
                            var allCFTs = _Cell.CellFaceTags;
                            int found   = 0;
                            if (allCFTs != null)
                            {
                                for (int i = 0; i < allCFTs.Length; i++)
                                {
                                    if (allCFTs[i].NeighCell_GlobalID < 0 && allCFTs[i].FaceIndex == iFace)
                                    {
                                        found++;
                                        if (allCFTs[i].EdgeTag == et)
                                        {
                                            // nop
                                        }
                                        else
                                        {
                                            allCFTs[i].EdgeTag = et;
                                            _GridChanged       = true;
                                        }
                                    }
                                }
                            }

                            if (found > 1)
                            {
                                throw new ApplicationException(string.Format("Cell face tags inconsistent in cell (GlId={0},LocIdx={1}): found {2} boundary tags for face {3}.", _Cell.GlobalID, jCell, found, iFace));
                            }
                            if (found <= 0)
                            {
                                CellFaceTag CFT = new CellFaceTag()
                                {
                                    EdgeTag            = et,
                                    FaceIndex          = iFace,
                                    NeighCell_GlobalID = long.MinValue
                                };

                                CFT.AddToArray(ref baseGrid.Cells[jCell].CellFaceTags);
                                _GridChanged = true;
                            }
                        }
                        GrdDatTmp.iGeomEdges.EdgeTags[iEdge] = et;

                        etUseCount[et]++;
                    }
                }

                return(_GridChanged);
            }

            byte RecordTag(int iedge, int jCell, int iFace)
            {
                var KRef = GrdDatTmp.iGeomCells.GetRefElement(jCell);

                // call edge-tag-name function
                GrdDatTmp.TransformLocal2Global(KRef.GetFaceCenter(iFace), GlobalVerticesOut, jCell);
                string EdgeTagName = EdgeTagFunc(x);

                // obtain edge tag
                if (!EdgeTagNames_Reverse.ContainsKey(EdgeTagName))
                {
                    int NewTag = EdgeTagNames_Reverse.Count;
                    Debug.Assert(NewTag > 0);
                    if (NewTag >= GridCommons.FIRST_PERIODIC_BC_TAG)
                    {
                        throw new ApplicationException("To many different edge tag names; at maximum " + (Classic.GridCommons.FIRST_PERIODIC_BC_TAG - 1) + " different tags for non-periodic boundaries.");
                    }
                    EdgeTagNames_Reverse.Add(EdgeTagName, (byte)NewTag);
                }
                var et = EdgeTagNames_Reverse[EdgeTagName];

                return(et);
            }

            // pass 1: assign edge tags locally
            bool GridChanged = LoopOverEdges(RecordTag);

            GridChanged = GridChanged.MPIOr();



            // pass 2: MPI syncronization
            if (GridChanged && g.Size > 1)
            {
                byte[] ETTranslation = SyncEdgeTagsOverMPI(EdgeTagNames_Reverse);
                if (ETTranslation != null)
                {
                    LoopOverEdges(delegate(int iedge, int jCell, int iFace) {
                        byte oldEt = GrdDatTmp.iGeomEdges.EdgeTags[iedge];
                        byte newEt = ETTranslation[oldEt];
                        return(newEt);
                    });
                }
            }


            // store & return
            etUseCount = etUseCount.MPISum();
            g.EdgeTagNames.Clear();
            foreach (var kv in EdgeTagNames_Reverse)
            {
                if (kv.Value == 0 || etUseCount[kv.Value] > 0)
                {
                    g.EdgeTagNames.Add(kv.Value, kv.Key);
                }
            }

            if (GridChanged)
            {
                g.InvalidateGridData();
                Console.WriteLine("Grid Edge Tags changed.");
            }

            foreach (string EdgeTagName in EdgeTagNamesToEnsure)
            {
                g.AddEdgeTag(EdgeTagName);
            }
        }