public QuadRuleFactory(Context context, LevelSetTracker tracker, int maxLevels, int minLevels) { this.context = context; this.tracker = tracker; this.maxLevels = maxLevels; this.minLevels = minLevels; baseVertexSet = new NestedVertexSet(context.Grid.SpatialDimension); double[,] vertices = context.Grid.GridSimplex.Vertices; int verticesPerCell = vertices.GetLength(0); int[] polyhedronVertices = new int[verticesPerCell]; for (int i = 0; i < verticesPerCell; i++) { double[] vertex = ArrayTools.GetRow(vertices, i); polyhedronVertices[i] = baseVertexSet.RegisterVertex(vertex); } subdivisionTree = new SimplexSubdivisionTree(context.Grid.GridSimplex, baseVertexSet, polyhedronVertices); for (int i = 0; i < minLevels; i++) { subdivisionTree.Subdivide(baseVertexSet, false); } subdivisionTree.SetSavePoint(); }
/// <summary> /// applies this transformation to a series of vectors /// </summary> public double[,] Transform(double[,] vtx) { if (vtx.GetLength(1) != DomainDimension) { throw new ArgumentException("spatial dimension mismatch"); } int L = vtx.GetLength(0); var ret = new double[L, CodomainDimension]; double[] x = new double[DomainDimension]; for (int l = 0; l < L; l++) { ArrayTools.GetRow(vtx, l, x); var yl = Transform(x); ret.SetRow(l, yl); } return(ret); }
/// <summary> /// Computes the projection of all /// <see cref="SpatialDimension"/>-dimensional basis polynomials in /// <paramref name="basis"/> onto this line segment and stores the /// result in <see cref="ProjectedPolynomialCoefficients"/> /// </summary> /// <param name="basis"> /// A basis containing the polynomials to be projected /// </param> /// <remarks> /// Don't ask me (B. Müller) how it works, so please don't touch it. I /// remember that I coded it but even at that time, I didn't fully /// understand <b>why</b> it works. /// </remarks> public void ProjectBasisPolynomials(Basis basis) { int NoOfRefElm = 1; int iKref = Array.IndexOf(basis.GridDat.iGeomCells.RefElements, this.m_Kref); int noOfPolynomials = basis.Polynomials[iKref].Count; int noOfCoefficientsPerDimension = basis.Degree + 1; MultidimensionalArray[] T = new MultidimensionalArray[SpatialDimension]; ProjectedPolynomialCoefficients = MultidimensionalArray.Create(NoOfRefElm, noOfPolynomials, noOfCoefficientsPerDimension); // Construct transformations for (int d = 0; d < SpatialDimension; d++) { double a = 0.5 * (End[d] - Start[d]); double b = 0.5 * (Start[d] + End[d]); T[d] = MultidimensionalArray.Create(noOfCoefficientsPerDimension, noOfCoefficientsPerDimension); for (int i = 0; i < noOfCoefficientsPerDimension; i++) { for (int j = 0; j < noOfCoefficientsPerDimension; j++) { if (i > j) { continue; } T[d][i, j] = j.Choose(i) * Math.Pow(a, i) * Math.Pow(b, j - i); } } } { for (int p = 0; p < noOfPolynomials; p++) { Polynomial currentPolynomial = basis.Polynomials[iKref][p]; double[] coefficients = new double[noOfCoefficientsPerDimension]; // Transform coefficients to D-dimensional "matrix" MultidimensionalArray originalCoefficients = MultidimensionalArray.Create( Enumerable.Repeat(noOfCoefficientsPerDimension, SpatialDimension).ToArray()); for (int j = 0; j < currentPolynomial.Coeff.Length; j++) { int[] exponents = ArrayTools.GetRow(currentPolynomial.Exponents, j); originalCoefficients[exponents] += currentPolynomial.Coeff[j]; } // Do projection switch (SpatialDimension) { case 1: T[0].GEMV(1.0, originalCoefficients.Storage, 0.0, coefficients); break; case 2: MultidimensionalArray coefficientMatrix = MultidimensionalArray.Create(noOfCoefficientsPerDimension, noOfCoefficientsPerDimension); coefficientMatrix.Set(originalCoefficients); coefficientMatrix = T[1] * (T[0] * coefficientMatrix).TransposeInPlace(); // Only left upper triangle can possibly be populated for (int i = 0; i < noOfCoefficientsPerDimension; i++) { for (int j = 0; j < i + 1; j++) { coefficients[i] += coefficientMatrix[i - j, j]; } } break; case 3: MultidimensionalArray matrix = MultidimensionalArray.Create( noOfCoefficientsPerDimension, noOfCoefficientsPerDimension); MultidimensionalArray[] Ty = new MultidimensionalArray[noOfCoefficientsPerDimension]; for (int i = 0; i < noOfCoefficientsPerDimension; i++) { matrix.Set(originalCoefficients.ExtractSubArrayShallow(-1, -1, i)); Ty[i] = T[1] * (T[0] * matrix).TransposeInPlace(); } // Only left upper triangle can possibly be populated MultidimensionalArray tempCoefficients = MultidimensionalArray.Create(noOfCoefficientsPerDimension, Ty[0].NoOfRows); for (int i = 0; i < Ty[0].NoOfRows; i++) { for (int j = 0; j < i + 1; j++) { int index = i - j; for (int k = 0; k < noOfCoefficientsPerDimension; k++) { tempCoefficients[k, i] += Ty[k][index, j]; } } } MultidimensionalArray transformedTempCoefficients = T[2] * tempCoefficients; for (int i = 0; i < noOfCoefficientsPerDimension; i++) { for (int j = 0; j < i + 1; j++) { coefficients[i] += transformedTempCoefficients[i - j, j]; } } break; default: throw new ApplicationException("Invalid spatial dimension"); } ProjectedPolynomialCoefficients.ExtractSubArrayShallow(0, p, -1).AccVector(1.0, coefficients); } } }
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); }