NodeSet ProjectOntoLevset(int jCell, NodeSet Nodes) { int D = Nodes.GetLength(1); int NoOfNodes = Nodes.GetLength(0); var m_Context = this.tracker.GridDat; LevelSet LevSet = (LevelSet)(this.tracker.LevelSets[this.LevelSetIndex]); MultidimensionalArray LevSetValues = MultidimensionalArray.Create(1, NoOfNodes); MultidimensionalArray LevSetGrad = MultidimensionalArray.Create(1, NoOfNodes, D); MultidimensionalArray x0_i_Local = MultidimensionalArray.Create(1, NoOfNodes, D); MultidimensionalArray x0_i_Global = MultidimensionalArray.Create(1, NoOfNodes, D); // quadrature nodes in global coordinates MultidimensionalArray x0_ip1_Local = MultidimensionalArray.Create(1, NoOfNodes, D); MultidimensionalArray x0_ip1_Global = MultidimensionalArray.Create(NoOfNodes, D); // set initial value; x0_i_Local.SetSubArray(Nodes, 0, -1, -1); int NN = NoOfNodes; for (int i = 0; i < 10; i++) { double radiusError = 0; int j = jCell; LevSet.Evaluate(j, 1, Nodes, LevSetValues, 0, 0.0); LevSet.EvaluateGradient(j, 1, Nodes, LevSetGrad); m_Context.TransformLocal2Global(new NodeSet(this.Kref, x0_i_Local.ExtractSubArrayShallow(0, -1, -1)), j, 1, x0_i_Global, 0); for (int nn = 0; nn < NN; nn++) { double sc = 0; for (int d = 0; d < D; d++) { sc += LevSetGrad[0, nn, d].Pow2(); } for (int d = 0; d < D; d++) { double xd = x0_i_Global[0, nn, d] - LevSetGrad[0, nn, d] * LevSetValues[0, nn] / sc; x0_ip1_Global[nn, d] = xd; } radiusError += Math.Abs(LevSetValues[0, nn]); } m_Context.TransformGlobal2Local(x0_ip1_Global, x0_ip1_Local, j, 1, 0); // next iter: x0_i <- x0_{i+1} x0_i_Local.Set(x0_ip1_Local); Nodes = (new NodeSet(this.Kref, x0_i_Local.ExtractSubArrayShallow(0, -1, -1))); } return(Nodes); }
public QuadRule GetCutCellQuadRule(LevelSet levelSet, int baseOrder, int cell) { // Build tree subdivisionTree.ResetToSavePoint(); NestedVertexSet currentSet = baseVertexSet; for (int i = minLevels; i < maxLevels; i++) { if (currentSet.LocalNumberOfVertices == 0) { // No new vertices were added during last subdivision break; } NodeSetController.NodeSetContainer nsc = context.NSC.CreateContainer(currentSet.Vertices, -1.0); uint lh = context.NSC.LockNodeSetFamily(nsc); MultidimensionalArray levelSetValues = MultidimensionalArray.Create(1, nsc.NodeSet.GetLength(0)); levelSet.Evaluate(cell, 1, 0, levelSetValues); context.NSC.UnlockNodeSetFamily(lh); subdivisionTree.ReadLevelSetValues(levelSetValues.ExtractSubArrayShallow(0, -1)); currentSet = new NestedVertexSet(currentSet); subdivisionTree.Subdivide(currentSet, true); } // Read level set values of leaves (only if IsCut is used!) if (currentSet.Vertices != null) { NodeSetController.NodeSetContainer nsc2 = context.NSC.CreateContainer(currentSet.Vertices, -1.0); uint lh2 = context.NSC.LockNodeSetFamily(nsc2); MultidimensionalArray levelSetValues2 = MultidimensionalArray.Create(1, nsc2.NodeSet.GetLength(0)); levelSet.Evaluate(cell, 1, 0, levelSetValues2); context.NSC.UnlockNodeSetFamily(lh2); subdivisionTree.ReadLevelSetValues(levelSetValues2.ExtractSubArrayShallow(0, -1)); } // Construct rule List <double[]> nodes = new List <double[]>(); List <double> weights = new List <double>(); foreach (SimplexSubdivisionTree.Node leave in subdivisionTree.Leaves) { double det = leave.TransformationFromRoot.Matrix.Determinat(); QuadRule rule; if (leave.IsCut) { rule = GetStandardQuadRule(baseOrder); } else { rule = GetStandardQuadRule(1); } for (int i = 0; i < rule.NoOfNodes; i++) { double[] vertex = ArrayTools.GetRow(rule.Nodes, i); nodes.Add(leave.TransformationFromRoot.Transform(vertex)); weights.Add(det * rule.Weights[i]); } } QuadRule result = new QuadRule(); result.Nodes = NodesToRectangularArray(nodes); result.Weights = weights.ToArray(); return(result); }