Example #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="Flds">
        /// a list of <em>M</em> DG fields.
        /// </param>
        /// <param name="Points">
        /// 2-dimensional: <br/>
        ///  - 1st index: point index, from 0 (including) to <em>N</em> (excluding)<br/>
        ///  - 2nd index: spatial dimension/direction
        /// </param>
        /// <param name="Result">
        /// result of the evaluation of the DG fields <paramref name="Flds"/> at points <paramref name="Points"/>.
        ///  - 1st index: point index, from 0 (including) to <em>N</em> (excluding)
        ///  - 2nd index: DG field, from 0 (including) to <em>M</em> (excluding).
        /// the result will be accumulated.
        /// </param>
        /// <param name="UnlocatedPoints">
        /// Optional, can be null; otherwise, an array of length <em>N</em>.
        /// On exit, in the latter case, true for every point that is not within the grid.
        /// </param>
        /// <param name="LocalCellIndices">
        /// Optional, can be null; otherwise, an array of length <em>N</em>.
        /// On exit, in the latter case, the <em>n</em>-th entry contains the local index of the cell
        /// where the <em>n</em>-th point is found.
        /// </param>
        /// <param name="beta">
        /// pre-scaling of <paramref name="Result"/> on entry, i.e. before accumulation
        /// </param>
        /// <param name="alpha">
        /// scaling of <paramref name="Flds"/> for evaluation
        /// </param>
        /// <returns>
        /// the number of points that are not within the grid;
        /// </returns>
        public int Evaluate(double alpha, IEnumerable <DGField> Flds, MultidimensionalArray Points, double beta, MultidimensionalArray Result, BitArray UnlocatedPoints = null, int[] LocalCellIndices = null)
        {
            // init / check args
            // =================

            int D = m_Context.Grid.SpatialDimension;
            int J = m_Context.Grid.NoOfUpdateCells;

            if (Points.Dimension != 2)
            {
                throw new ArgumentException("must be 2-dimensional", "Points");
            }
            int N = Points.GetLength(0);

            if (Result.Dimension != 2)
            {
                throw new ArgumentException("must be 2-dimensional", "Result");
            }
            if (Result.GetLength(0) != N)
            {
                throw new ArgumentException("mismatch in 1st dimension", "Points,Result");
            }
            DGField[] Fields = Flds.ToArray();
            int       M      = Fields.Length;

            for (int m = 0; m < M; m++)
            {
                if (!object.ReferenceEquals(this.m_Context, Fields[m].GridDat))
                {
                    throw new ArgumentException($"Mismatch in grid: field #{m} is defined on a different grid.");
                }
            }

            if (Result.GetLength(1) != Fields.Length)
            {
                throw new ArgumentException("2nd dimension of 'Result' and length of 'Flds' must be equal");
            }


            if (UnlocatedPoints == null)
            {
                UnlocatedPoints = new BitArray(N, false);
            }
            else
            {
                UnlocatedPoints.SetAll(false);
            }

            if (LocalCellIndices != null)
            {
                if (LocalCellIndices.Length != N)
                {
                    throw new ArgumentException("2nd dimension of 'Result' and length of 'LocalCellIndices' must be equal");
                }
                for (int n = 0; n < N; n++)
                {
                    LocalCellIndices[n] = int.MinValue;
                }
            }

            if (UnlocatedPoints.Length != N)
            {
                throw new ArgumentException("2nd dimension of 'Result' and length of 'UnlocatedPoints' must be equal");
            }

            double[] pt = new double[D];

            Result.Scale(beta);

            // build point localization
            // ========================

            // filter points that are outside the grid bounding box
            int[] Perm2 = new int[N];
            {
                int cnt = 0;
                var bb  = CellLoc.GridBB;
                for (int n = 0; n < N; n++)
                {
                    for (int d = 0; d < D; d++)
                    {
                        pt[d] = Points[n, d];
                    }

                    if (!bb.Contains(pt))
                    {
                        UnlocatedPoints[n] = true;
                    }
                    else
                    {
                        Perm2[cnt] = n;
                        cnt++;
                    }
                }

                Array.Resize(ref Perm2, cnt);
            }

            if (Perm2.Length <= 0)
            {
                UnlocatedPoints.SetAll(true);
                return(N); // we are done
            }

            int _cnt = 0;
            MultidimensionalArray pts = MultidimensionalArray.Create(Perm2.Length, D);

            for (int n = 0; n < N; n++)
            {
                if (!UnlocatedPoints[n])
                {
                    for (int d = 0; d < D; d++)
                    {
                        pts[_cnt, d] = Points[n, d];
                    }
                    _cnt++;
                }
            }
            int NU = N - Perm2.Length;

            UnlocatedPoints.SetAll(true);
            N = Perm2.Length;
            int[]             Perm = new int[N];
            int               NoOfUnassignedNodes = N;
            PointLocalization pl = new PointLocalization(pts, CellLoc.GridBB, Perm);

            pts = null; // not required anymore

            // localize Points / evaluate at
            // =============================

            MultidimensionalArray vertGlobalSupect1 = new MultidimensionalArray(2);
            MultidimensionalArray vertGlobalSupect  = new MultidimensionalArray(2);
            MultidimensionalArray vertLocalSuspect  = new MultidimensionalArray(3);
            NodeSet vertLocal = null;

            MultidimensionalArray[] fieldVal = new MultidimensionalArray[M];
            for (int m = 0; m < M; m++)
            {
                fieldVal[m] = new MultidimensionalArray(2);
            }

            //Console.WriteLine("debgcode akt.");
            //int[] bbsfound = new int[Points.GetLength(0)];
            BoundingBox CellTreeBB = new BoundingBox(D);
            BoundingBox CellBB     = new BoundingBox(D);


            // loop over cells ...
            for (int j = 0; j < J; j++)
            {
                // code of the cell: all bounding boxes in the tree that
                // share a point with the cell
                GeomBinTreeBranchCode bbcode; int bbBits;
                {
                    BoundingBoxCode __b = CellLoc.GetCellBoundingBoxCode(j);
                    bbcode = __b.Branch;
                    bbBits = (int)__b.SignificantBits;
                    CellLoc.GridBB.SubBoxFromCode(CellTreeBB, __b);
                }

                // cell bounding box is smaller than the bounding box in the tree
                m_Context.Cells.GetCellBoundingBox(j, CellBB);
                if (!CellTreeBB.Contains(CellBB)) // test
                {
                    throw new ApplicationException("internal error: should not happen");
                }
                CellBB.ExtendByFactor(0.001); // safety factor

                // determine all points in cell
                int iP0, Len;
                pl.GetPointsInBranch(bbcode, bbBits, out iP0, out Len);
                if (Len <= 0)
                {
                    // no points in cell j
                    continue;
                }

                // transform points to cell-local coordinates
                vertGlobalSupect1.Allocate(Len, D);
                double[] tempPt  = new double[D];
                int      tempLen = 0;
                int[]    nPts    = new int[Len];

                for (int n = 0; n < Len; n++)
                {
                    int nPt = Perm2[Perm[n + iP0]];
                    if (!UnlocatedPoints[nPt])
                    {
                        continue;
                    }

                    for (int d = 0; d < D; d++)
                    {
                        tempPt[d] = pl.Points[n + iP0, d];
                    }

                    if (CellBB.Contains(tempPt))
                    {
                        for (int d = 0; d < D; d++)
                        {
                            vertGlobalSupect1[tempLen, d] = tempPt[d];
                        }
                        nPts[tempLen] = nPt;
                        tempLen++;
                    }
                }
                Len = tempLen;
                if (Len <= 0)
                {
                    // no points in cell j
                    continue;
                }

                vertGlobalSupect.Allocate(Len, D);
                vertGlobalSupect.Set(vertGlobalSupect1.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { Len - 1, D - 1 }));

                vertLocalSuspect.Allocate(1, Len, D);
                CellLoc.GrdDat.TransformGlobal2Local(vertGlobalSupect, vertLocalSuspect, j, 1, 0);

                // test
                //for (int n = 0; n < Len; n++) {
                //    for (int d = 0; d < D; d++)
                //        pt[d] = vertGlobalSupect[n, d];

                //    if (!CellBB.Contains(pt))
                //        Console.WriteLine("Huramnet");
                //}

                var splx = m_Context.Cells.GetRefElement(j);

                // test whether the points in the bounding box of cell j
                // are also in cell j
                bool[] tatsaechlich = new bool[Len];
                int    Z            = 0;
                for (int n = 0; n < Len; n++)
                {
                    int nPt = nPts[n];

                    if (!UnlocatedPoints[nPt])
                    {
                        // point was already located in/assigned to another cell
                        continue;
                    }

                    for (int d = 0; d < D; d++)
                    {
                        pt[d] = vertGlobalSupect[n, d];
                    }
                    if (!CellBB.Contains(pt))
                    {
                        continue; // cell bounding box is usually smaller than the bounding box in the tree ('bbcode')
                    }

                    for (int d = 0; d < D; d++)
                    {
                        pt[d] = vertLocalSuspect[0, n, d];
                    }
                    if (splx.IsWithin(pt, 1.0e-8))
                    {
                        UnlocatedPoints[nPt] = false;
                        NoOfUnassignedNodes--;

                        if (LocalCellIndices != null)
                        {
                            LocalCellIndices[nPt] = j;
                        }

                        Z++;
                        tatsaechlich[n] = true;
                    }
                }
                if (Z <= 0)
                {
                    // no points in bb
                    continue;
                }

                // collect all vertices that are really in cell j
                vertLocal = new NodeSet(m_Context.Cells.GetRefElement(j), Z, D);
                int z = 0;
                for (int n = 0; n < Len; n++)
                {
                    if (!tatsaechlich[n])
                    {
                        continue;
                    }

                    for (int d = 0; d < D; d++)
                    {
                        vertLocal[z, d] = vertLocalSuspect[0, n, d];
                    }
                    z++;
                }
                vertLocal.LockForever();

                // evaluate Velocity Field there
                for (int m = 0; m < M; m++)
                {
                    fieldVal[m].Allocate(1, Z);
                }

                for (int m = 0; m < M; m++)
                {
                    Fields[m].Evaluate(j, 1, vertLocal, fieldVal[m]);
                }


                // store result of evaluation
                z = 0;
                for (int n = 0; n < Len; n++)
                {
                    //int nPt = Perm2[Perm[n + iP0]];
                    int nPt = nPts[n];

                    if (!tatsaechlich[n])
                    {
                        continue;
                    }

                    for (int m = 0; m < M; m++)
                    {
                        Result[nPt, m] += alpha * fieldVal[m][0, z];
                    }

                    z++;
                }
            }

            // return
            // ======
            return(NoOfUnassignedNodes + NU);
        }
Example #2
0
        /// <summary>
        /// for a cloud of points, this method finds the cells which contain the points
        /// </summary>
        /// <param name="_pts">
        /// Input: a cloud of points; 1st index: point index, 2nd index: spatial dimension;
        /// </param>
        /// <param name="LocalCellIdx">
        /// Output: for each point in <paramref name="_pts"/>, the the (local) index of the cell which contains the specific point
        /// </param>
        /// <param name="NoOfUnassigned">
        /// on exit, the number of points which cannot be assigned to one cell
        /// </param>
        public void LocalizePointsWithinGrid <T>(MultidimensionalArray _pts, T LocalCellIdx, out int NoOfUnassigned) where T : IList <int>
        {
            using (new FuncTrace()) {
                // init and check
                // ==============

                NoOfUnassigned = 0;

                GridData grd     = this.GrdDat;
                var      CellLoc = this;
                var      splxS   = grd.Grid.RefElements;

                int D = grd.SpatialDimension;
                int N = _pts.GetLength(0);
                if (_pts.Dimension != 2)
                {
                    throw new ArgumentException();
                }
                if (_pts.GetLength(0) != LocalCellIdx.Count)
                {
                    throw new ArgumentException();
                }
                if (_pts.GetLength(1) != D)
                {
                    throw new ArgumentException();
                }

                var UnlocatedPoints = new BitArray(N, false);

                int J = grd.Cells.NoOfLocalUpdatedCells;

                double[] pt = new double[D];


                // build point localization
                // ========================

                // filter points that are outside the grid bounding box
                int[] Perm2 = new int[N];
                {
                    int cnt = 0;
                    var bb  = CellLoc.GridBB;
                    for (int n = 0; n < N; n++)
                    {
                        _pts.ExtractVector(pt, 1, 0, D, n, 0);
                        //for (int d = 0; d < D; d++)
                        //    pt[d] = Points[n, d];

                        if (!bb.Contains(pt))
                        {
                            UnlocatedPoints[n] = true;
                            NoOfUnassigned++;
                        }
                        else
                        {
                            Perm2[cnt] = n;
                            cnt++;
                        }
                    }

                    Array.Resize(ref Perm2, cnt);
                }

                if (Perm2.Length <= 0)
                {
                    // all points are outside the bounding box of the grid !
                    LocalCellIdx.SetAll(int.MinValue);
                    return; // we are done
                }

                int _cnt = 0;
                MultidimensionalArray pts = MultidimensionalArray.Create(Perm2.Length, D);
                for (int n = 0; n < N; n++)
                {
                    if (!UnlocatedPoints[n])
                    {
                        for (int d = 0; d < D; d++)
                        {
                            pts[_cnt, d] = _pts[n, d];
                        }
                        _cnt++;
                    }
                }
                int NU = N - Perm2.Length;

                UnlocatedPoints.SetAll(true);
                N = Perm2.Length;
                int[]             Perm = new int[N];
                int               NoOfUnassignedNodes = N;
                PointLocalization pl = new PointLocalization(pts, CellLoc.GridBB, Perm);
                pts = null; // not required anymore


                // localize Points / evaluate at
                // =============================

                MultidimensionalArray vertGlobalSupect = new MultidimensionalArray(2);
                MultidimensionalArray vertLocalSuspect = new MultidimensionalArray(3);


                BoundingBox CellTreeBB = new BoundingBox(D);
                BoundingBox CellBB     = new BoundingBox(D);


                // loop over cells ...
                for (int j = 0; j < J; j++)
                {
                    // code of the cell: all bounding boxes in the tree that
                    // share a point with the cell
                    GeomBinTreeBranchCode bbcode; int bbBits;
                    {
                        BoundingBoxCode __b = CellLoc.GetCellBoundingBoxCode(j);
                        bbcode = __b.Branch;
                        bbBits = (int)__b.SignificantBits;
                        CellLoc.GridBB.SubBoxFromCode(CellTreeBB, __b);
                    }

                    // cell bounding box is smaller than the bounding box in the tree
                    grd.Cells.GetCellBoundingBox(j, CellBB);
                    if (!CellTreeBB.Contains(CellBB)) // test
                    {
                        throw new ApplicationException("internal error: should not happen");
                    }
                    CellBB.ExtendByFactor(0.001); // safety factor

                    // determine all points in cell
                    int iP0, Len;
                    pl.GetPointsInBranch(bbcode, bbBits, out iP0, out Len);
                    if (Len <= 0)
                    {
                        // no points in cell j
                        continue;
                    }

                    // transform points to cell-local coordinates
                    vertGlobalSupect.Allocate(Len, D);
                    vertLocalSuspect.Allocate(1, Len, D);
                    for (int n = 0; n < Len; n++)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            vertGlobalSupect[n, d] = pl.Points[n + iP0, d];
                        }
                    }
                    CellLoc.GrdDat.TransformGlobal2Local(vertGlobalSupect, vertLocalSuspect, j, 1, 0);

                    var Kref = grd.Cells.GetRefElement(j);

                    // test whether the points in the bounding box of cell j
                    // are also in cell j
                    for (int n = 0; n < Len; n++)
                    {
                        int nPt = Perm2[Perm[n + iP0]];

                        if (!UnlocatedPoints[nPt])
                        {
                            // point was already located in/assigned to another cell
                            continue;
                        }

                        for (int d = 0; d < D; d++)
                        {
                            pt[d] = vertGlobalSupect[n, d];
                        }
                        if (!CellBB.Contains(pt))
                        {
                            continue; // cell bounding box is usually smaller than the bounding box in the tree ('bbcode')
                        }

                        for (int d = 0; d < D; d++)
                        {
                            pt[d] = vertLocalSuspect[0, n, d];
                        }
                        if (Kref.IsWithin(pt))
                        {
                            UnlocatedPoints[nPt] = false;
                            NoOfUnassignedNodes--;

                            LocalCellIdx[nPt] = j;
                        }
                    }
                }

                // return
                NoOfUnassigned += NoOfUnassignedNodes;
            }
        }
Example #3
0
        /// <summary>
        /// Usually used after <see cref="MergeLogically(GridCommons, GridCommons)"/>; this method finds element boundaries
        /// which intersect geometrically, but not logically and inserts a <see cref="CellFaceTag"/> which connects those cells.
        /// </summary>
        /// <param name="g"></param>
        /// <param name="upsampling"></param>
        /// <returns></returns>
        public static GridCommons Seal(GridCommons g, int upsampling = 4)
        {
            GridCommons R = g.CloneAs();

            g = null;
            GridData gdat = new GridData(R);
            int      D    = gdat.SpatialDimension;
            int      J    = gdat.Cells.NoOfLocalUpdatedCells;

            if (R.CellPartitioning.MpiSize > 1)
            {
                throw new NotSupportedException("Not supported in MPI-parallel mode.");
            }

            //NodeSet[] TestNodes = gdat.Edges.EdgeRefElements.Select(KrefEdge => KrefEdge.GetSubdivisionTree(upsampling).GlobalVertice).ToArray();
            NodeSet[] TestNodes = gdat.Edges.EdgeRefElements.Select(KrefEdge => KrefEdge.GetBruteForceQuadRule(upsampling, 1).Nodes).ToArray();
            // Its better to use vertices in the interior of the element; if we use vertices at the corners, we might get
            // intersection of edges that just share one point.


            // Define all edges that will be tested (set to boundary edges)
            // ============================================================
            int[] UnknownEdges = gdat.BoundaryEdges.ItemEnum.ToArray();
            int   L            = UnknownEdges.Sum(iEdg => TestNodes[gdat.Edges.GetRefElementIndex(iEdg)].NoOfNodes);

            // Transform nodes on edges (that should be tested) to global coordinates
            // ======================================================================

            MultidimensionalArray TestNodesGlobal = MultidimensionalArray.Create(L, D);
            MultidimensionalArray NormalsGlobal   = MultidimensionalArray.Create(L, D);

            int[] NodeToEdge = new int[L]; // pointer l -> Edge index, where l is the first index into 'TestNodesGlobal' & 'NormalsGlobal'


            int[,] E2C = gdat.Edges.CellIndices;
            int cnt = 0;

            foreach (int iEdg in UnknownEdges)
            {
                int     iKref = gdat.Edges.GetRefElementIndex(iEdg);
                NodeSet Ns    = TestNodes[iKref];
                int     K     = Ns.NoOfNodes;

                int[] I0 = new int[] { cnt, 0 };
                int[] IE = new int[] { cnt + K - 1, D - 1 };

                MultidimensionalArray TN = gdat.GlobalNodes.GetValue_EdgeSV(Ns, iEdg, 1);
                TestNodesGlobal.SetSubArray(TN.ExtractSubArrayShallow(0, -1, -1), I0, IE);

                MultidimensionalArray N1 = gdat.Edges.NormalsCache.GetNormals_Edge(Ns, iEdg, 1);
                NormalsGlobal.SetSubArray(N1.ExtractSubArrayShallow(0, -1, -1), I0, IE);

                for (int i = cnt; i < cnt + K; i++)
                {
                    NodeToEdge[i] = iEdg;
                }

                cnt += K;
            }

            // binary tree to speed up point localization
            int[]             pl_Permutation = new int[L];
            PointLocalization pl             = new PointLocalization(TestNodesGlobal, 0.01, pl_Permutation);

            Debug.Assert(!object.ReferenceEquals(pl.Points, TestNodesGlobal));

            // compare search edges to all other nodes
            // =======================================

            // mapping: cell --> Neighbour cell index, face index
            // 1st index: Cell index;
            // 2nd index: enumeration
            List <Tuple <int, int> >[] FoundPairings = new List <Tuple <int, int> > [gdat.Cells.NoOfCells];

            int[][] C2E = gdat.Cells.Cells2Edges;
            byte[,] E2F = gdat.Edges.FaceIndices;

            int cnt2 = 0;

            for (int iEdgC = 0; iEdgC < UnknownEdges.Length; iEdgC++)   // loop over edges that may get sealed
            {
                int     iEdg  = UnknownEdges[iEdgC];
                int     iKref = gdat.Edges.GetRefElementIndex(iEdg);
                NodeSet Ns    = TestNodes[iKref];
                int     K     = Ns.NoOfNodes;

                int jCell1 = E2C[iEdg, 0];
                Debug.Assert(E2C[iEdg, 1] < 0);
                int iFace1 = E2F[iEdg, 0];
                Debug.Assert(E2F[iEdg, 1] == byte.MaxValue);


                int[] I0 = new int[] { cnt2, 0 };
                int[] IE = new int[] { cnt2 + K - 1, D - 1 };
                MultidimensionalArray TN = TestNodesGlobal.ExtractSubArrayShallow(I0, IE);
                //MultidimensionalArray N1 = NormalsGlobal.ExtractSubArrayShallow(I0, IE);

                // find bounding box for edge
                BoundingBox bbEdge = new BoundingBox(TN);
                if (bbEdge.h_min / bbEdge.h_max < 1.0e-5)
                {
                    // very thin bounding box, thicken slightly
                    double delta = bbEdge.h_max * 1.0e-5;
                    for (int d = 0; d < D; d++)
                    {
                        bbEdge.Min[d] -= delta;
                        bbEdge.Max[d] += delta;
                    }
                }
                bbEdge.ExtendByFactor(0.01);

                // determine binary code for bounding box
                int bbEdgeSigBits;
                GeomBinTreeBranchCode bbEdgeCode = GeomBinTreeBranchCode.Combine(
                    GeomBinTreeBranchCode.CreateFormPoint(pl.PointsBB, bbEdge.Min),
                    GeomBinTreeBranchCode.CreateFormPoint(pl.PointsBB, bbEdge.Max),
                    out bbEdgeSigBits);

                // determine all points in bounding box
                int iP0, Len;
                pl.GetPointsInBranch(bbEdgeCode, bbEdgeSigBits, out iP0, out Len);

                // determine all edged which potentially overlap with edge 'iEdg'
                HashSet <int> PotOvrlap = new HashSet <int>(); // a set of edge indices
                for (int n = 0; n < Len; n++)
                {
                    int l   = iP0 + n;
                    int iPt = pl_Permutation[l];
                    Debug.Assert(GenericBlas.L2DistPow2(pl.Points.GetRow(l), TestNodesGlobal.GetRow(iPt)) <= 0);

                    int iOvlpEdge = NodeToEdge[iPt];
                    if (iOvlpEdge != iEdg)
                    {
                        PotOvrlap.Add(iOvlpEdge);
                    }
                }
                //int[] PotOvrlap = UnknownEdges.CloneAs();


                // determine actually overlapping boundary edges:
                foreach (int iOvrlapEdge in PotOvrlap)
                {
                    int jCell2 = E2C[iOvrlapEdge, 0];
                    Debug.Assert(E2C[iOvrlapEdge, 1] < 0);
                    if (jCell2 == jCell1)
                    {
                        continue;
                    }
                    int iFace2 = E2F[iOvrlapEdge, 0];
                    Debug.Assert(E2F[iOvrlapEdge, 1] == byte.MaxValue);


                    int AllreadyFound = FoundPairings[jCell1] == null ?
                                        0 : FoundPairings[jCell1].Where(tp => tp.Item1 == jCell2 && tp.Item2 == iFace1).Count();
                    if (AllreadyFound > 1)
                    {
                        throw new ApplicationException("Error in algorithmus.");
                    }
                    if (AllreadyFound > 0)
                    {
                        continue;
                    }

                    var    Kref_j2 = gdat.Cells.GetRefElement(jCell2);
                    double h       = Kref_j2.GetMaxDiameter();

                    MultidimensionalArray LocVtx_j2 = MultidimensionalArray.Create(K, D);
                    bool[] NewtonConvervence        = new bool[K];
                    gdat.TransformGlobal2Local(TN, LocVtx_j2, jCell2, NewtonConvervence);

                    for (int k = 0; k < K; k++)   // loop over all transformed points
                    {
                        if (!NewtonConvervence[k])
                        {
                            continue;
                        }

                        double[] pt      = LocVtx_j2.GetRow(k);
                        double[] ptClose = new double[D];
                        double   dist    = Kref_j2.ClosestPoint(pt, ptClose);

                        if (dist > h * 1.0e-8)
                        {
                            continue;
                        }

                        AffineManifold Face     = Kref_j2.GetFacePlane(iFace2);
                        double         FaceDist = Face.PointDistance(pt);

                        if (FaceDist.Abs() > 1.0e-8 * h)
                        {
                            continue;
                        }


                        NodeSet Ns2 = new NodeSet(Kref_j2, pt);
                        MultidimensionalArray Normals2 = MultidimensionalArray.Create(1, D);
                        gdat.Edges.GetNormalsForCell(Ns2, jCell2, iFace2, Normals2);

                        double[] N1d = NormalsGlobal.GetRow(cnt2 + k);
                        double[] N2d = Normals2.GetRow(0);


                        //Check if face normals points exactly in the opposite direction, 2 ways:
                        // 1) calculate angle between both normals -> bad choice because of Math.Acos
                        // 2) inner product of two opposite vectors is -1
                        //if (Math.Abs(Math.Abs(Math.Acos(GenericBlas.InnerProd(N1d, N2d))) - Math.PI) > 1.0e-8)
                        if (Math.Abs(GenericBlas.InnerProd(N1d, N2d) + 1.0) > 1.0e-8)
                        {
                            continue;
                        }



                        // if we reach this point, jCell1 should match with jCell2/iFace2
                        if (FoundPairings[jCell1] == null)
                        {
                            FoundPairings[jCell1] = new List <Tuple <int, int> >();
                        }
                        if (FoundPairings[jCell2] == null)
                        {
                            FoundPairings[jCell2] = new List <Tuple <int, int> >();
                        }
                        FoundPairings[jCell1].Add(new Tuple <int, int>(jCell2, iFace1));
                        FoundPairings[jCell2].Add(new Tuple <int, int>(jCell1, iFace2));
                        break; // no need to test jCell1 vs. jCell2 anymore
                    }
                }

                cnt2 += K;
            }

            // add the newly found pairings to the grid
            for (int j = 0; j < J; j++)
            {
                var fp = FoundPairings[j];
                if (fp != null)
                {
                    foreach (var t in fp)
                    {
                        ArrayTools.AddToArray(new CellFaceTag()
                        {
                            EdgeTag               = 0,
                            FaceIndex             = t.Item2,
                            ConformalNeighborship = false,
                            NeighCell_GlobalID    = gdat.CurrentGlobalIdPermutation.Values[t.Item1]
                        }, ref R.Cells[j].CellFaceTags);
                    }
                }
            }

            return(R);
        }
Example #4
0
            /// <summary>
            /// computes <see cref="ZoneDriver.vertices"/> and
            /// <see cref="ZoneDriver.cellVertices"/>
            /// </summary>
            /// <param name="celVtx">
            /// input:
            /// vertices of each cell, unmerged;
            /// 1st index: cell index;
            /// 2nd index: vertex index within cell;
            /// 3rd index: spatial direction;
            /// </param>
            /// <param name="vertice">
            /// output: the merged vertices, i.e. each vertex from the <paramref name="celVtx"/>
            /// occurs only once.
            /// 1st index: vertex index;
            /// 2nd index: spatial direction
            /// </param>
            /// <param name="cellVertices">
            /// output: indices into the <paramref name="vertice"/>-array.
            /// 1st index: cell index;
            /// 2nd index: vertex index within cell;
            /// </param>
            /// <param name="h">
            /// cell measure
            /// </param>
            public static void InitializeVertice2(MultidimensionalArray celVtx, out int[,] cellVertices, out double[,] vertice, double[] h)
            {
                using (var tr = new FuncTrace()) {
                    // fk: bemerkung: sollte einegermaßen skalieren;
                    // Test am 10sept10: Gitter mit 400x400 dauert cd 8 sec., Gitter mit 800x400 dauert 16 sekunden

                    int J_update = celVtx.GetLength(0);
                    int D        = celVtx.GetLength(2);
                    int J        = J_update;


                    int NV = celVtx.GetLength(1);


                    // collect vertices
                    // ================

                    MultidimensionalArray Verts = MultidimensionalArray.Create(J * NV, D);

                    // loop over locally updated cells...
                    int cnt = 0;
                    for (int j = 0; j < J_update; j++)
                    {
                        // loop over cell vertices...
                        for (int iv = 0; iv < NV; iv++)
                        {
                            for (int d = 0; d < D; d++)
                            {
                                Verts[cnt, d] = celVtx[j, iv, d];
                            }
                            cnt++;
                        }
                    }

                    // build tree
                    // ==========

                    BoundingBox bb = new BoundingBox(Verts);
                    bb.ExtendByFactor(0.005);
                    int[]             Perm    = new int[Verts.GetLength(0)];
                    PointLocalization locTree = new PointLocalization(Verts, bb, Perm);
                    Verts = locTree.Points;

                    // eliminate duplicate points
                    // ==========================

                    double[]   pt          = new double[D];
                    int        N           = J * NV;
                    List <int> foundPoints = new List <int>();
                    int[]      AliasPts    = new int[J * NV];
                    ArrayTools.SetAll(AliasPts, int.MinValue);
                    int        NewVertice = 0;
                    List <int> VerticeTmp = new List <int>();


                    using (new BlockTrace("duplicate Point elimination", tr)) {
                        for (int j = 0; j < J; j++)
                        {
                            for (int _n = 0; _n < NV; _n++)
                            {
                                int n = j * NV + _n;

                                if (AliasPts[n] >= 0)
                                {
                                    continue; // point is already assigned.
                                }
                                for (int d = 0; d < D; d++)
                                {
                                    pt[d] = Verts[n, d];
                                }

                                //if (n == 95)
                                //    Console.Write("");

                                double eps = h[n / NV] * 1.0e-6;

                                locTree.FindNearPoints(foundPoints, eps, pt);
                                if (foundPoints.Count < 1)
                                {
                                    throw new ApplicationException("error in algorithm");
                                }
                                if (!foundPoints.Contains(n))
                                {
                                    throw new ApplicationException("error in algorithm");
                                }

                                VerticeTmp.Add(n);

                                for (int k = 0; k < foundPoints.Count; k++)
                                {
                                    AliasPts[foundPoints[k]] = NewVertice;
                                }

                                NewVertice++;
                            }
                        }
                    }

                    // test
                    // ====
                    for (int i = 0; i < AliasPts.Length; i++)
                    {
                        if (AliasPts[i] < 0)
                        {
                            throw new ApplicationException("error in alg");
                        }
                    }

                    // store results
                    // =============
                    int[] PermInv = new int[Perm.Length];
                    for (int i = 0; i < PermInv.Length; i++)
                    {
                        PermInv[Perm[i]] = i;
                    }

                    cellVertices = new int[J, NV];
                    for (int j = 0; j < J; j++)
                    {
                        for (int _n = 0; _n < NV; _n++)
                        {
                            int n = j * NV + _n;
                            cellVertices[j, _n] = AliasPts[PermInv[n]];
                        }
                    }

                    vertice = new double[VerticeTmp.Count, D];
                    for (int i = 0; i < NewVertice; i++)
                    {
                        int n = VerticeTmp[i];
                        for (int d = 0; d < D; d++)
                        {
                            vertice[i, d] = Verts[n, d];
                        }
                    }
                }
            }
Example #5
0
        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="loc"></param>
        /// <param name="QuadNodes">
        /// quad nodes outside the grid are ignored, i.e. the integrand is assumed to be 0
        /// </param>
        /// <param name="quadweights">
        /// </param>
        public Integrator(CellLocalization loc, double[,] QuadNodes, double[] quadweights)
        {
            int N = QuadNodes.GetLength(0);

            if (N != quadweights.Length)
            {
                throw new ArgumentException("length of 0-th dimension of arrays must match.");
            }
            int D = QuadNodes.GetLength(1);

            if (D != loc.GridBB.D)
            {
                throw new ArgumentException("mismatch in spatial dimension.");
            }
            int J = loc.GrdDat.Cells.NoOfLocalUpdatedCells;

            GridData gdat = loc.GrdDat;

            grdDat = gdat;

            // filter quad nodes outside of the bounding box
            // =============================================
            MultidimensionalArray QuadNodes2;

            double[] quadweights2;
            int[]    orgindex;
            {
                double[] pt     = new double[D];
                BitArray inside = new BitArray(N);

                int Found = 0;
                for (int n = 0; n < N; n++)
                {
                    for (int d = 0; d < D; d++)
                    {
                        pt[d] = QuadNodes[n, d];
                    }
                    bool ins = loc.GridBB.Contains(pt);

                    inside[n] = ins;
                    if (ins)
                    {
                        Found++;
                    }
                }

                QuadNodes2   = MultidimensionalArray.Create(Found, D);
                quadweights2 = new double[Found];
                orgindex     = new int[Found];

                int cnt = 0;
                for (int n = 0; n < N; n++)
                {
                    if (inside[n])
                    {
                        for (int d = 0; d < D; d++)
                        {
                            QuadNodes2[cnt, d] = QuadNodes[n, d];
                        }
                        quadweights2[cnt] = quadweights[cnt];
                        orgindex[cnt]     = n;
                        cnt++;
                    }
                }

                QuadNodes   = null;
                quadweights = null;
                N           = Found;
            }

            // build tree of quad nodes
            // ========================
            int[]             Perm = new int[N];
            PointLocalization qn   = new PointLocalization(QuadNodes2, loc.GridBB, Perm);

            double[] quadwegtNew  = new double[N];
            int[]    origindexNew = new int[N];
            for (int n = 0; n < N; n++)
            {
                quadwegtNew[n]  = quadweights2[Perm[n]];
                origindexNew[n] = orgindex[Perm[n]];
            }
            quadweights2 = null;

            // 1st index: cell index
            // 2nd index: quad node index within cell
            // 3rd index: spatial coordinate
            List <List <double[]> > QuadNodesPerCell = new List <List <double[]> >();

            // 1st index: cell index
            // 2nd index: quad node index within cell
            List <List <double> > QuadWeightsPerCell = new List <List <double> >();

            // 1st index: cell index
            // 2nd index: quad node index within cell
            List <List <int> > OrigIndexPerCell = new List <List <int> >();

            for (int j = 0; j < J; j++)
            {
                QuadNodesPerCell.Add(new List <double[]>());
                QuadWeightsPerCell.Add(new List <double>());
                OrigIndexPerCell.Add(new List <int>());
            }

            // try to assign the quad nodes to cells
            // =====================================
            BitArray PointsLocatedMarker = new BitArray(N); // mark every node, that we assign to a cell with
            int      NoOfUnassignedNodes = N;

            //int[] Cell4Quadnodes = new int[N];

            // loop over cells ...
            MultidimensionalArray vertGlobal = new MultidimensionalArray(2);
            MultidimensionalArray vertLocal  = new MultidimensionalArray(3);

            for (int j = 0; j < J; j++)
            {
                //if (loc.CellMaxCode[j] < Locations[0])
                //    continue; // skip the cell: contains none of the searched points
                //if (loc.CellMinCode[j] > Locations[N - 1])
                //    continue; // skip the cell: contains none of the searched points

                GeomBinTreeBranchCode bbcode; int bbBits;
                {
                    BoundingBoxCode __b = loc.GetCellBoundingBoxCode(j);
                    bbcode = __b.Branch;
                    bbBits = (int)__b.SignificantBits;
                }

                int iP0, Len;
                qn.GetPointsInBranch(bbcode, bbBits, out iP0, out Len);
                if (Len <= 0)
                {
                    continue;
                }

                vertGlobal.Allocate(Len, D);
                vertLocal.Allocate(1, Len, D);
                for (int n = 0; n < Len; n++)
                {
                    for (int d = 0; d < D; d++)
                    {
                        vertGlobal[n, d] = qn.Points[n + iP0, d];
                    }
                }
                gdat.TransformGlobal2Local(vertGlobal, vertLocal, j, 1, 0);


                var splx = gdat.Cells.GetRefElement(j);
                for (int n = 0; n < Len; n++)
                {
                    int nPt = n + iP0;
                    if (PointsLocatedMarker[nPt])
                    {
                        continue;
                    }

                    double[] pt = new double[D];
                    for (int d = 0; d < D; d++)
                    {
                        pt[d] = vertLocal[0, n, d];
                    }
                    if (splx.IsWithin(pt))
                    {
                        PointsLocatedMarker[nPt] = true;
                        NoOfUnassignedNodes--;
                        //Cell4Quadnodes[nPt] = j;

                        QuadNodesPerCell[j].Add(pt);
                        QuadWeightsPerCell[j].Add(quadwegtNew[nPt]);
                        OrigIndexPerCell[j].Add(origindexNew[nPt]);
                    }
                }
            }

            // record final data structures
            // ============================
            //m_QuadNodesPerCell = new MultidimensionalArray[J];
            m_QuadNodesPerCell       = new NodeSet[J];
            m_QuadWeightsPerCell     = new double[J][];
            m_OriginalQuadNodesIndex = new int[J][];
            MaxNumberOfNodes         = 0;
            for (int j = 0; j < J; j++)
            {
                List <double[]> NodesInCellj = QuadNodesPerCell[j];

                m_QuadWeightsPerCell[j]     = QuadWeightsPerCell[j].ToArray();
                m_OriginalQuadNodesIndex[j] = OrigIndexPerCell[j].ToArray();

                int NJ = NodesInCellj.Count;
                if (NJ > 0)
                {
                    var _QuadNodesPerCell_j = new NodeSet(grdDat.Cells.GetRefElement(j), NJ, D);
                    MaxNumberOfNodes = Math.Max(MaxNumberOfNodes, NJ);
                    for (int nn = 0; nn < NJ; nn++)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            _QuadNodesPerCell_j[nn, d] = NodesInCellj[nn][d];
                        }
                    }
                    _QuadNodesPerCell_j.LockForever();

                    m_QuadNodesPerCell[j] = _QuadNodesPerCell_j;
                }
                else
                {
                    m_QuadNodesPerCell[j] = null;
                }
            }
        }