Пример #1
0
        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();
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        /// <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);
                }
            }
        }
Пример #4
0
        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);
        }