/// <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); }
/// <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); }
/// <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; } }
/// <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; } } }