Пример #1
0
        protected override SayeQuadRule BuildQuadRule(MultidimensionalArray X, double X_weight, int heightDirection, double length)
        {
            QuadRule gaussRule_1D = Line.Instance.GetQuadratureRule(order);

            double[,] nodesArr = new double[gaussRule_1D.NoOfNodes, 2];
            for (int i = 0; i < gaussRule_1D.NoOfNodes; ++i)
            {
                for (int j = 0; j < 2; ++j)
                {
                    nodesArr[i, j] = X[0, j];
                    if (j == heightDirection)
                    {
                        nodesArr[i, j] += length / 2 * gaussRule_1D.Nodes[i, 0];
                    }
                }
            }

            MultidimensionalArray weights = gaussRule_1D.Weights.CloneAs();

            weights.Scale(length / 2);
            weights.Scale(X_weight);

            MultidimensionalArray nodes = new MultidimensionalArray(2);

            nodes.InitializeFrom(nodesArr);
            SayeQuadRule transformed_GaussRule_1D = new SayeQuadRule(nodes, weights);

            return(transformed_GaussRule_1D);
        }
Пример #2
0
            /// <summary>
            /// Computes the residual of the Eikonal equation.
            /// </summary>
            protected override void Evaluate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult)
            {
                NodeSet QuadNodes = QR.Nodes;
                var     gradPhi   = m_gradPhi;
                int     D         = m_phi.GridDat.SpatialDimension;
                int     NoOfNodes = QuadNodes.NoOfNodes;

                m_phi.EvaluateGradient(i0, Length, QuadNodes, m_gradPhi);

                for (int i = 0; i < Length; i++)
                {
                    for (int n = 0; n < NoOfNodes; n++)
                    {
                        // compute the residual of the Eikonal equation:
                        double acc = 0;

                        for (int d = 0; d < D; d++)
                        {
                            double dPhi_dxd = gradPhi[i, n, d];
                            acc += dPhi_dxd * dPhi_dxd;
                        }

                        acc  = Math.Sqrt(acc);
                        acc -= 1;

                        // L2-Norm of the residual:
                        EvalResult[i, n, 0] = acc * acc;
                    }
                }
            }
Пример #3
0
        protected override SayeQuadRule SetGaussQuadratureNodes(SayeSquare arg)
        {
            //Aquire needed data
            //------------------------------------------------------------------------------------------------------------
            QuadRule gaussRule_2D = Square.Instance.GetQuadratureRule(order);
            MultidimensionalArray nodes_GaussRule_2D   = ((MultidimensionalArray)gaussRule_2D.Nodes).CloneAs();
            MultidimensionalArray weights_GaussRule_2D = gaussRule_2D.Weights.CloneAs();

            double[] diameters = arg.Diameters;
            MultidimensionalArray centerArr = arg.GetCellCenter().ExtractSubArrayShallow(new int[] { 0, -1 });
            double jacobian = diameters[0] * diameters[1];

            //AffineTransformation of nodes, scale weights
            //------------------------------------------------------------------------------------------------------------
            //Scale Nodes
            for (int i = 0; i < 2; ++i)
            {
                nodes_GaussRule_2D.ColScale(i, diameters[i]);
            }
            //Scale Weights
            weights_GaussRule_2D.Scale(jacobian);
            //Move Nodes
            int[] index = new int[] { 0, -1 };
            for (int i = 0; i < gaussRule_2D.NoOfNodes; ++i)
            {
                index[0] = i;
                nodes_GaussRule_2D.AccSubArray(1, centerArr, index);
            }

            //Set return data
            //------------------------------------------------------------------------------------------------------------
            SayeQuadRule transformed_GaussRule_2D = new SayeQuadRule(nodes_GaussRule_2D, weights_GaussRule_2D);

            return(transformed_GaussRule_2D);
        }
Пример #4
0
            /// <summary>
            /// For each cell \f$ K\f$   in the given
            /// range and for each \f$ \vec{\Lambda}\f$
            /// in <see cref="LevelSetVolumeQuadRuleFactory.lambdaBasis"/>:
            /// Computes
            /// \f$
            /// \int \limits_{\{\vec{x}; \varphi(\vec{x}) = 0 \}  \cap K} \vec{\Lambda} \cdot \vec{n}_I \;ds,
            /// \f$
            /// where \f$ \varphi\f$  is the level set
            /// function and \f$ \vec{n}_I\f$  denotes the
            /// unit normal vector on \f$ \varphi\f$
            /// </summary>
            protected override void Evaluate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult)
            {
                NodeSet QuadNodes = QR.Nodes;
                int     D         = gridData.SpatialDimension;
                int     NoOfNodes = QuadNodes.NoOfNodes;

                MultidimensionalArray levelSetNormals = owner.LevelSetData.GetLevelSetReferenceNormals(QuadNodes, i0, Length);
                MultidimensionalArray metrics         = owner.LevelSetData.GetLevelSetNormalReferenceToPhysicalMetrics(
                    QuadNodes, i0, Length);

                for (int i = 0; i < Length; i++)
                {
                    MultidimensionalArray lambdaValues = owner.EvaluateLambdas(i0 + i, QuadNodes);

                    for (int j = 0; j < NoOfNodes; j++)
                    {
                        for (int k = 0; k < m_TotalNoOfIntegralsPerItem; k++)
                        {
                            for (int d = 0; d < D; d++)
                            {
                                EvalResult[i, j, k] += lambdaValues[j, k, d] * levelSetNormals[i, j, d];
                            }

                            EvalResult[i, j, k] *= metrics[i, j];
                        }
                    }
                }
            }
Пример #5
0
        public QuadRule Evaluate(int Cell, T arg)
        {
            //Setup algorithm
            //----------------------------------------------------------------------
            cell = Cell;
            TreeNode <T> recursionTree = new TreeNode <T>();
            TreeNode <T> fullSpace     = recursionTree.AddChild(arg);

            //Build Integrand
            //----------------------------------------------------------------------
            SayeRecursion(fullSpace);

            //Evaluate Integrand
            //----------------------------------------------------------------------
            //Fill nodesAndWeights
            recursionTree.UnrollFunc(IntegrandEvaluation);
            //ConvertToQuadRule
            QuadRule toRuleThemAll = fullSpace.Value.NodesAndWeights.GetQuadRule();

            //Handle empty QuadRule
            if (toRuleThemAll.NoOfNodes == 0)
            {
                Debug.WriteLine("Evaluation of cell {0} returned empty Quadrule", cell);
                toRuleThemAll = CreateZeroQuadrule();
            }

            return(toRuleThemAll);
        }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="lsData"></param>
        /// <param name="rootFindingAlgorithm">
        /// One-dimensional root-finding algorithm for determining roots of the
        /// level set function on edges of the edges of the volume simplex.
        /// Default is <see cref="LineSegment.DefaultRootFindingAlgorithm"/>
        /// </param>
        /// <param name="jumpType">
        /// Determines the level set region to be integrated over (negative
        /// level set values, positive level set values, or both)
        /// </param>
        public LevelSetEdgeVolumeQuadRuleFactory(
            LevelSetTracker.LevelSetData lsData, LineSegment.IRootFindingAlgorithm rootFindingAlgorithm = null, JumpTypes jumpType = JumpTypes.Heaviside)
        {
            if (lsData.GridDat.Cells.RefElements.Length > 1)
            {
                throw new NotImplementedException(
                          "Multiple reference elements currently not supported");
            }
            this.LevelSetData      = lsData;
            this.jumpType          = jumpType;
            this.levelSetIndex     = lsData.LevelSetIndex;
            CoFaceQuadRuleFactory  = new CutLineOnEdgeQuadRuleFactory(lsData, rootFindingAlgorithm, jumpType);
            edgeSurfaceRuleFactory = new LevelSetEdgeSurfaceQuadRuleFactory(lsData, CoFaceQuadRuleFactory, jumpType);

            // Use vertices; Since it is only used on edges that are considered
            // uncut, they _should_ all have the same sign
            RefElement simplex      = LevelSetData.GridDat.Grid.RefElements[0];
            RefElement edgeSimplex  = simplex.FaceRefElement;
            QuadRule   signEdgeRule = new QuadRule()
            {
                Nodes   = edgeSimplex.Vertices,
                Weights = MultidimensionalArray.Create(edgeSimplex.NoOfVertices)
            };

            signTestRule = new CellBoundaryFromEdgeRuleFactory <CellBoundaryQuadRule>(
                LevelSetData.GridDat, simplex, new FixedRuleFactory <QuadRule>(signEdgeRule)).
                           GetQuadRuleSet(new CellMask(LevelSetData.GridDat, Chunk.GetSingleElementChunk(0)), -1).
                           First().Rule;
        }
Пример #7
0
        protected override QuadRule CreateZeroQuadrule()
        {
            QuadRule zeroRule = QuadRule.CreateEmpty(RefElement, 1, RefElement.SpatialDimension);

            zeroRule.Nodes.LockForever();
            return(zeroRule);
        }
Пример #8
0
            protected override void Evaluate(int i0, int Length, QuadRule rule, MultidimensionalArray EvalResult)
            {
                NodeSet Nodes = rule.Nodes;
                int     F     = m_fields.Length;
                int     D     = GridDat.SpatialDimension;

                for (int f = 0; f < F; f++)
                {
                    m_fields[f].Evaluate(i0, Length, Nodes, evalRes[f]);
                }

                GridDat.TransformLocal2Global(Nodes, i0, Length, X, 0);
                int NoOfNodes = Nodes.NoOfNodes;

                double[] _x   = new double[D];
                double[] args = new double[F];
                for (int i = 0; i < Length; i++)
                {
                    for (int n = 0; n < NoOfNodes; n++)
                    {
                        for (int f = 0; f < F; f++)
                        {
                            args[f] = evalRes[f][i, n];
                        }
                        for (int d = 0; d < D; d++)
                        {
                            _x[d] = X[i, n, d];
                        }

                        EvalResult[i, n, 0] = m_f(_x, args, i + i0);
                    }
                }
            }
Пример #9
0
        private double SetUpConfiguration()
        {
            testCase.UpdateLevelSet(levelSet);
            levelSetTracker.UpdateTracker(__NearRegionWith: 0, incremental: false, __LevSetAllowedMovement: 2);

            XDGField.Clear();
            XDGField.GetSpeciesShadowField("A").ProjectField(
                1.0, testCase.JumpingFieldSpeciesAInitialValue, default(CellQuadratureScheme));
            XDGField.GetSpeciesShadowField("B").ProjectField(
                1.0, testCase.JumpingFieldSpeciesBInitialValue, default(CellQuadratureScheme));

            SinglePhaseField.Clear();
            SinglePhaseField.ProjectField(testCase.ContinuousFieldInitialValue);

            double referenceValue = testCase.Solution;

            if (testCase is IVolumeTestCase)
            {
                QuadRule standardRule = Grid.RefElements[0].GetQuadratureRule(2 * XDGField.Basis.Degree + 1);
                ScalarFieldQuadrature uncutQuadrature = new ScalarFieldQuadrature(
                    GridData,
                    XDGField,
                    new CellQuadratureScheme(
                        new FixedRuleFactory <QuadRule>(standardRule),
                        levelSetTracker.Regions.GetCutCellSubGrid().Complement().VolumeMask),
                    standardRule.OrderOfPrecision);
                uncutQuadrature.Execute();

                referenceValue -= uncutQuadrature.Result;
            }

            return(referenceValue);
        }
Пример #10
0
        private void WriteVolumeNodes(StreamWriter log, IQuadRuleFactory <QuadRule> ruleFactory, int order, SubGrid subGrid, ITestCase testCase, int selectedCell = -1)
        {
            foreach (var chunkRulePair in ruleFactory.GetQuadRuleSet(subGrid.VolumeMask, order))
            {
                foreach (int cell in chunkRulePair.Chunk.Elements)
                {
                    QuadRule rule = chunkRulePair.Rule;

                    MultidimensionalArray globalVertices = MultidimensionalArray.Create(
                        1, rule.NoOfNodes, Grid.SpatialDimension);
                    MultidimensionalArray metrics = levelSetTracker.DataHistories[0].Current.GetLevelSetNormalReferenceToPhysicalMetrics(
                        rule.Nodes, cell, 1);
                    GridData.TransformLocal2Global(rule.Nodes, cell, 1, globalVertices, 0);

                    if (selectedCell >= 0 && cell != selectedCell)
                    {
                        continue;
                    }

                    for (int k = 0; k < rule.NoOfNodes; k++)
                    {
                        double weight = rule.Weights[k];

                        if (testCase is ISurfaceTestCase)
                        {
                            // Use to get correct HMF weights in reference coordinate
                            // system (surface weights are already divided by $metrics
                            // to save this step in actual quadrature)
                            //weight *= metrics[0, k];
                        }

                        if (Grid.SpatialDimension == 2)
                        {
                            log.WriteLine(
                                "{0}\t{1}\t{2}\t{3}\t{4}",
                                cell,
                                k,
                                globalVertices[0, k, 0].ToString(formatInfo),
                                globalVertices[0, k, 1].ToString(formatInfo),
                                Math.Round(weight, 2).ToString(formatInfo));
                        }
                        else
                        {
                            log.WriteLine(
                                "{0}\t{1}\t{2}\t{3}\t{4}\t{5}",
                                cell,
                                k,
                                globalVertices[0, k, 0].ToString(formatInfo),
                                globalVertices[0, k, 1].ToString(formatInfo),
                                globalVertices[0, k, 2].ToString(formatInfo),
                                weight.ToString(formatInfo));
                        }
                    }
                }
            }
        }
Пример #11
0
        /// <summary>
        /// Sums up all weights associated with a quadrature rule and reports
        /// an error if the sum is not equal to the volume
        /// (<see cref="RefElement.Volume"/>) of the simplex.
        /// </summary>
        /// <param name="order">The <b>requested</b> order</param>
        /// <param name="rule">The quadrature rule</param>
        private void TestSumOfWeights(int order, QuadRule rule)
        {
            double error = Math.Abs(rule.Weights.Sum() - GetSimplex().Volume);

            // This error should be much smaller (and was much smaller on the
            // old master branch); Should be investigated.
            Assert.That(
                error <= 1e-9,
                "Sum of weights != Simplex volume (Deviance: " + String.Format("{0:e}", error) + ")");
        }
Пример #12
0
        /// <summary>
        /// Computes the matrix matrix
        /// V_ij = sum_k{p_i(nodes(k) * p_j(nodes(k)) * weights(k)}
        /// for a given quadrature rule (where p_i and p_j are the orthonormal
        /// polynomials supplied by the quadrature rule) and reports an error
        /// if this matrix differs from the identity matrix
        /// </summary>
        /// <param name="order">The <b>requested</b> order</param>
        /// <param name="rule">The quadrature rule</param>
        /// <param name="polynomials">The orthonormal polynomials</param>
        private void TestMassMatrix(int order, QuadRule rule, PolynomialList polynomials)
        {
            MultidimensionalArray[] values = new MultidimensionalArray[polynomials.Count];
            for (int i = 0; i < polynomials.Count; i++)
            {
                values[i] = MultidimensionalArray.Create(rule.NoOfNodes);
                polynomials[i].Evaluate(values[i], rule.Nodes);
            }

            //For every exactly integrable polynomial i
            for (int i = 0; i < polynomials.Count; i++)
            {
                // Check if quadrature rule is suitable
                if (polynomials[i].AbsoluteDegree > order)
                {
                    continue;
                }

                //For every exactly integrable co-polynomial j
                for (int j = 0; j <= i; j++)
                {
                    // Check if quadrature rule is suitable
                    if (polynomials[i].AbsoluteDegree + polynomials[j].AbsoluteDegree > order)
                    {
                        continue;
                    }

                    double result = 0;
                    for (int k = 0; k < rule.NoOfNodes; k++)
                    {
                        result += values[i][k] * values[j][k] * rule.Weights[k];
                    }

                    //Elements should be zero except of diagonal elements
                    double expectedResult = 0.0;
                    if (i == j)
                    {
                        expectedResult = 1.0;
                    }

                    //Store maximum absolute error for the report we want to create
                    double error = Math.Abs(result - expectedResult);
                    //Console.WriteLine("MassMatrixError: {0}", error);

                    Assert.That(
                        error <= 1e-9,
                        String.Format(
                            "MassMatrix[" + i + "," + j + "] should be {0} but is off by {1:e} for order {2}",
                            expectedResult,
                            error,
                            order));
                }
            }
        }
Пример #13
0
        private void WriteSurfaceNodes(StreamWriter log, IQuadRuleFactory <QuadRule> ruleFactory, int order, SubGrid subGrid)
        {
            var edgeRules = ruleFactory.GetQuadRuleSet(
                levelSetTracker.Regions.GetCutCellSubGrid().AllEdgesMask, order);

            foreach (var chunkRulePair in edgeRules)
            {
                foreach (int edge in chunkRulePair.Chunk.Elements)
                {
                    QuadRule rule = chunkRulePair.Rule;

                    int cell = GridData.iGeomEdges.CellIndices[edge, 0];

                    NodeSet volumeVertices = new NodeSet(
                        GridData.iGeomCells.GetRefElement(cell),
                        rule.NoOfNodes, Grid.SpatialDimension);
                    Grid.RefElements[0].TransformFaceCoordinates(
                        GridData.iGeomEdges.FaceIndices[edge, 0], rule.Nodes, volumeVertices);
                    volumeVertices.LockForever();

                    MultidimensionalArray globalVertices = MultidimensionalArray.Create(
                        1, rule.NoOfNodes, Grid.SpatialDimension);
                    GridData.TransformLocal2Global(volumeVertices, cell, 1, globalVertices, 0);
                    for (int k = 0; k < rule.NoOfNodes; k++)
                    {
                        if (Grid.SpatialDimension == 2)
                        {
                            log.WriteLine(
                                "{0}\t{1}\t{2}\t{3}\t{4}",
                                cell,
                                k,
                                globalVertices[0, k, 0].ToString(formatInfo),
                                globalVertices[0, k, 1].ToString(formatInfo),
                                rule.Weights[k].ToString(formatInfo));
                        }
                        else
                        {
                            log.WriteLine(
                                "{0}\t{1}\t{2}\t{3}\t{4}\t{5}",
                                cell,
                                k,
                                globalVertices[0, k, 0].ToString(formatInfo),
                                globalVertices[0, k, 1].ToString(formatInfo),
                                globalVertices[0, k, 2].ToString(formatInfo),
                                rule.Weights[k].ToString(formatInfo));
                        }
                    }
                }
            }
        }
Пример #14
0
        public void TestNominalOrder()
        {
            var simplex = GetSimplex();

            int highestKnownOrder = simplex.HighestKnownOrder;

            for (int i = 0; i <= highestKnownOrder; i++)
            {
                QuadRule rule      = simplex.GetQuadratureRule(i);
                int      realOrder = rule.OrderOfPrecision;
                Assert.IsTrue(
                    realOrder >= i,
                    "Requested order < real order (" + realOrder + ")");
            }
        }
Пример #15
0
        /// <summary>
        /// Projects every basis polynomial for the quadrature rule of the
        /// given order onto a single cell grid supplied by the sub-class and
        /// approximates the LInfinity error of the projection.
        /// </summary>
        /// <remarks>
        /// The DG projection uses a quadrature rule of 2*n+1 for a basis of
        /// order n. Thus, make sure <paramref name="order"/> that a quadrature
        /// rule of order 2*order+1 exists before calling this method</remarks>
        /// <param name="order">The <b>requested</b> order</param>
        /// <param name="polynomials">The orthonormal polynomials</param>
        /// <param name="rule">The tested quadrature rule</param>
        private void TestProjectionError(int order, PolynomialList polynomials, QuadRule rule)
        {
            Basis basis = new Basis(context, order);

            for (int i = 0; i < polynomials.Count; i++)
            {
                if (2 * polynomials[i].AbsoluteDegree + 1 > order)
                {
                    // Not integrable _exactly_ with this rule
                    continue;
                }

                DGField        field    = new SinglePhaseField(basis);
                ScalarFunction function = delegate(MultidimensionalArray input, MultidimensionalArray output) {
                    polynomials[i].Evaluate(output, new NodeSet(rule.RefElement, input));
                };
                field.ProjectField(function);

                double LInfError = 0;
                for (int j = 0; j < rule.NoOfNodes; j++)
                {
                    MultidimensionalArray result = MultidimensionalArray.Create(1, 1);
                    NodeSet point = new NodeSet(context.iGeomCells.GetRefElement(0), 1, rule.SpatialDim);
                    for (int k = 0; k < rule.SpatialDim; k++)
                    {
                        point[0, k] = rule.Nodes[j, k];
                    }
                    point.LockForever();

                    //Evaluate pointwise because we don't want the accumulated
                    //result
                    field.Evaluate(0, 1, point, result, 0.0);

                    MultidimensionalArray exactResult = MultidimensionalArray.Create(1);
                    polynomials[i].Evaluate(exactResult, point);

                    LInfError = Math.Max(Math.Abs(result[0, 0] - exactResult[0]), LInfError);
                }
                //Console.WriteLine("ProjectionError: {0}", LInfError);

                Assert.IsTrue(
                    LInfError <= 1e-13,
                    String.Format(
                        "Projection error too high for polynomial {0}. Error: {1:e}",
                        i,
                        LInfError));
            }
        }
Пример #16
0
        protected override void Evaluate(int i0, int Length, QuadRule qr, MultidimensionalArray EvalResult)
        {
            if (field is XDGField)
            {
                SpeciesId speciesB = new SpeciesId()
                {
                    cntnt = 11112
                };

                MultidimensionalArray result = EvalResult.ExtractSubArrayShallow(-1, -1, 0);
                ((XDGField)field).GetSpeciesShadowField(speciesB).Evaluate(i0, Length, qr.Nodes, result, 0, 0.0);
            }
            else
            {
                field.Evaluate(i0, Length, qr.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
            }
        }
Пример #17
0
        public void TestProjectionError()
        {
            var simplex = GetSimplex();

            int maxOrder = Math.Min(
                simplex.HighestKnownOrder,
                simplex.HighestSupportedPolynomialDegree);

            //In a field of order i, the a field automatically uses a
            //quadrature rule of order 2i+1 to compute the DG projection.
            //Thus, we can only (and need only to) orders i for which it is
            //guaranteed that a rule of order 2i-1 exists, too
            for (int i = 0; 2 * i + 1 <= maxOrder; i++)
            {
                QuadRule rule = simplex.GetQuadratureRule(i);
                TestProjectionError(i, simplex.GetOrthonormalPolynomials(maxOrder), rule);
            }
        }
Пример #18
0
        /// <summary>
        /// quadrature for a point is trivial - it's just evaluation a the point,
        /// so there is only one quadrature rule with one node that is valid for any order;
        /// </summary>
        /// <param name="DesiredOrder">
        /// any positive integer value;
        /// </param>
        /// <returns>
        /// An exact quad. rule for arbitrary functions in zero dimensions !!!
        /// </returns>
        public override QuadRule GetQuadratureRule(int DesiredOrder)
        {
            if (DesiredOrder < 0)
            {
                throw new ArgumentOutOfRangeException("negative polynomial degree.");
            }

            QuadRule qr = new QuadRule();

            qr.OrderOfPrecision = int.MaxValue;
            qr.Nodes            = new NodeSet(this, 1, 1);
            qr.Nodes[0, 0]      = 0.0;
            qr.Nodes.LockForever();
            qr.Weights    = MultidimensionalArray.Create(1);
            qr.Weights[0] = 1.0;


            return(qr);
        }
Пример #19
0
            /// <summary>
            /// Modulates the result of
            /// <see cref="EvaluateDivergenceOfIntegrand"/> by the weights
            /// given by <see cref="EvaluateWeightFunction"/>.
            /// </summary>
            protected override void Evaluate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult)
            {
                NodeSet QuadNodes = QR.Nodes;
                int     NoOfNodes = QuadNodes.NoOfNodes;

                m_Owner.EvaluateDivergenceOfIntegrand(QuadNodes, i0, Length, EvalResult);
                m_Owner.EvaluateWeightFunction(QuadNodes, i0, Length, m_WeightBuffer);

                for (int i = 0; i < Length; i++)
                {
                    for (int j = 0; j < NoOfNodes; j++)
                    {
                        double gamma = m_WeightBuffer[i, j];
                        for (int k = 0; k < m_Owner.m_NoOfIntegrands; k++)
                        {
                            EvalResult[i, j, k] *= gamma;
                        }
                    }
                }
            }
Пример #20
0
        /// <summary>
        /// Returns surface and volume quadrature nodes, respectively.
        /// </summary>
        /// <param name="Cell"></param>
        /// <param name="arg"></param>
        /// <returns></returns>
        public QuadRule[] ComboEvaluate(int Cell, T arg)
        {
            //Setup algorithm
            //----------------------------------------------------------------------
            arg.Surface = false;
            cell        = Cell;
            TreeNode <T> recursionTree = new TreeNode <T>();
            TreeNode <T> fullSpace     = recursionTree.AddChild(arg);

            //Build Integrand
            //----------------------------------------------------------------------
            SayeRecursion(fullSpace);

            //Evaluate Integrand
            //----------------------------------------------------------------------
            //Fill nodesAndWeights

            SurfRule = GetEmptySurfaceRule();
            recursionTree.UnrollFunc(ComboIntegrandEvaluation);

            //Convert data to QuadRule. The volume rule is saved in SayeArgument as in the single algorithm.
            //The surface rule is saved SurfRule.
            QuadRule[] rulezOfKrom = new QuadRule[2];
            rulezOfKrom[0] = fullSpace.Value.NodesAndWeights.GetQuadRule(); //Volume rule
            rulezOfKrom[1] = SurfRule.GetQuadRule();                        //Surface rule

            //Handle empty QuadRule
            if (rulezOfKrom[0].NoOfNodes == 0)
            {
                Debug.WriteLine("Evaluation of cell {0} returned empty volume quadrule", cell);
                rulezOfKrom[0] = CreateZeroQuadrule();
            }
            if (rulezOfKrom[1].NoOfNodes == 0)
            {
                Debug.WriteLine("Evaluation of cell {0} returned empty surface quadrule", cell);
                rulezOfKrom[1] = CreateZeroQuadrule();
            }


            return(rulezOfKrom);
        }
Пример #21
0
        public void TestSumOfWeights()
        {
            var simplex = GetSimplex();

            int highestKnownOrder = simplex.HighestKnownOrder;

            QuadRule lastQuadRule = null;

            for (int i = 0; i <= highestKnownOrder; i++)
            {
                QuadRule rule = simplex.GetQuadratureRule(i);
                if (lastQuadRule == rule)
                {
                    // Same rule, nothing new to test
                    continue;
                }

                TestSumOfWeights(i, rule);
                lastQuadRule = rule;
            }
        }
Пример #22
0
            protected override void Evaluate(int i0, int Length, QuadRule rule, MultidimensionalArray EvalResult)
            {
                NodeSet NodesUntransformed = rule.Nodes;
                int     M = NodesUntransformed.GetLength(0);
                //int D = NodesUntransformed.GetLength(1);

                MultidimensionalArray fieldvalsA = EvalResult.ResizeShallow(new int[] { Length, NodesUntransformed.GetLength(0) });

                fieldvalsA.Clear();
                m_FieldA.Evaluate(i0, Length, NodesUntransformed, fieldvalsA, 1.0);
                fieldvalsB.Clear();
                m_FieldB.Evaluate(i0, Length, NodesUntransformed, fieldvalsB, 1.0);

                for (int j = 0; j < Length; j++)
                {
                    for (int m = 0; m < M; m++)
                    {
                        EvalResult[j, m, 0] = fieldvalsA[j, m] * fieldvalsB[j, m];
                    }
                }
            }
Пример #23
0
        protected override void Evaluate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult)
        {
            int N         = m_Basis.MaximalLength;
            int NoOfNodes = QR.Nodes.NoOfNodes;

            if (((GridData)gridData).Cells.ContainsNonlinearCell())
            {
                throw new NotImplementedException();
            }

            MultidimensionalArray scaling = base.gridData.iGeomCells.JacobiDet;

            for (int i = 0; i < m_Fields.Length; i++)
            {
                m_Fields[i].Evaluate(i0, Length, QR.Nodes, FieldVals[i], 0, 0.0);
            }

            for (int j = 0; j < Length; j++)
            {
                int    jCell = j + i0;
                double sc    = 1.0 / scaling[jCell];

                for (int node = 0; node < NoOfNodes; node++)
                {
                    for (int BlkRowLoc = 0; BlkRowLoc < N; BlkRowLoc++)
                    {
                        for (int BlkColLoc = 0; BlkColLoc < N; BlkColLoc++)
                        {
                            double[] _FieldVals = new double[FieldVals.Length];
                            for (int i = 0; i < FieldVals.Length; i++)
                            {
                                _FieldVals[i] = FieldVals[i][j, node];
                            }
                            double FieldFuncValue = FieldFunc(_FieldVals);
                            EvalResult[j, node, BlkRowLoc *N + BlkColLoc] = BasisValues[node, BlkRowLoc] * BasisValues[node, BlkColLoc] * sc * FieldFuncValue;
                        }
                    }
                }
            }
        }
Пример #24
0
            public void Evaluate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult)
            {
                // Del_Evaluate
                // ~~~~~~~~~~~~~
                NodeSet NS        = QR.Nodes;
                int     NoOfNodes = NS.NoOfNodes;
                var     BasisVal  = b.CellEval(NS, i0, Length);

                EvalResult.ExtractSubArrayShallow(new int[] { 0, 0, 0, 0 }, new int[] { Length - 1, NoOfNodes - 1, Nnx - 1, Nnx - 1 })
                .Multiply(1.0, BasisVal, BasisVal, 0.0, "ikmn", "ikm", "ikn");

                if (UevalBuf == null)
                {
                    UevalBuf = MultidimensionalArray.Create(Length, NoOfNodes);
                }
                if (UevalBuf.GetLength(0) < Length || UevalBuf.GetLength(1) != NoOfNodes)
                {
                    UevalBuf.Allocate(Length, NoOfNodes);
                }
                MultidimensionalArray _UevalBuf;

                if (UevalBuf.GetLength(0) > Length)
                {
                    _UevalBuf = UevalBuf.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { Length - 1, NoOfNodes - 1 });
                }
                else
                {
                    Debug.Assert(UevalBuf.GetLength(0) == Length);
                    _UevalBuf = UevalBuf;
                }

                for (int d = 0; d < D; d++)
                {
                    _UevalBuf.Clear();
                    Uin[d].Evaluate(i0, Length, NS, _UevalBuf);

                    EvalResult.ExtractSubArrayShallow(new int[] { 0, 0, Nnx + d, 0 }, new int[] { Length - 1, NoOfNodes - 1, Nnx + d - 1, Nnx - 1 })
                    .Multiply(1.0, BasisVal, _UevalBuf, 0.0, "ikm", "ikm", "ik");
                }
            }
Пример #25
0
        public void TestMassMatrix()
        {
            var simplex = GetSimplex();

            // Limit order for run-time reasons
            int highestKnownOrder = Math.Min(simplex.HighestKnownOrder, 21);

            QuadRule lastQuadRule = null;

            for (int i = 0; i <= highestKnownOrder; i++)
            {
                QuadRule rule = simplex.GetQuadratureRule(i);
                if (lastQuadRule == rule)
                {
                    // Same rule, nothing new to test
                    continue;
                }

                TestMassMatrix(i, rule, simplex.GetOrthonormalPolynomials(Math.Min(highestKnownOrder, simplex.HighestSupportedPolynomialDegree)));
                lastQuadRule = rule;
            }
        }
        /// <summary>
        /// Updates <see cref="lambdaBasis"/>, <see cref="baseRule"/> and
        /// <see cref="basisValuesEdge"/> every time a different order is
        /// requested in <see cref="GetQuadRuleSet"/>
        /// </summary>
        /// <param name="order">
        /// The new order of the moment-fitting basis
        /// </param>
        private void SwitchOrder(int order)
        {
            int iKref     = this.LevelSetData.GridDat.Cells.RefElements.IndexOf(this.RefElement, (A, B) => object.ReferenceEquals(A, B));
            int noOfFaces = LevelSetData.GridDat.Grid.RefElements[iKref].NoOfFaces;
            int D         = RefElement.FaceRefElement.SpatialDimension;

            Polynomial[] basePolynomials           = RefElement.FaceRefElement.GetOrthonormalPolynomials(order).ToArray();
            Polynomial[] antiderivativePolynomials =
                new Polynomial[basePolynomials.Length * D];
            for (int i = 0; i < basePolynomials.Length; i++)
            {
                Polynomial p = basePolynomials[i];
                for (int d = 0; d < D; d++)
                {
                    Polynomial pNew = p.CloneAs();
                    for (int j = 0; j < p.Coeff.Length; j++)
                    {
                        pNew.Exponents[j, d]++;
                        pNew.Coeff[j] /= pNew.Exponents[j, d];
                        // Make sure divergence is Phi again
                        pNew.Coeff[j] /= D;
                    }
                    antiderivativePolynomials[i * D + d] = pNew;
                }
            }
            lambdaBasis = new PolynomialList(antiderivativePolynomials);

            int minNoOfPoints = GetNumberOfLambdas();

            int    minOrder     = 1;
            double safetyFactor = 1.6;

            while (RefElement.FaceRefElement.GetQuadratureRule(minOrder).NoOfNodes < safetyFactor * minNoOfPoints)
            {
                minOrder += 1;
            }

            QuadRule singleEdgeRule = RefElement.FaceRefElement.GetQuadratureRule(minOrder);

            baseRule = new CellBoundaryFromEdgeRuleFactory <CellBoundaryQuadRule>(
                LevelSetData.GridDat,
                LevelSetData.GridDat.Grid.RefElements[0],
                new FixedRuleFactory <QuadRule>(singleEdgeRule)).
                       GetQuadRuleSet(new CellMask(LevelSetData.GridDat, Chunk.GetSingleElementChunk(0)), -1).
                       First().Rule;

            //Basis singleEdgeBasis = new Basis(tracker.GridDat, order, RefElement.FaceRefElement);
            PolynomialList singleEdgeBasis = new PolynomialList(RefElement.FaceRefElement.GetOrthonormalPolynomials(order));

            //MultidimensionalArray edgeNodes = singleEdgeRule.Nodes.CloneAs();
            //basisValuesEdge = MultidimensionalArray.Create(
            //    singleEdgeRule.NoOfNodes, singleEdgeBasis.Count);
            //MultidimensionalArray monomials = Polynomial.GetMonomials(
            //    edgeNodes, RefElement.FaceRefElement.SpatialDimension, singleEdgeBasis.Degree);
            //for (int j = 0; j < singleEdgeBasis.MinimalLength; j++) {
            //    singleEdgeBasis.Polynomials[iKref, j].Evaluate(
            //        basisValuesEdge.ExtractSubArrayShallow(-1, j),
            //        edgeNodes,
            //        monomials);
            //}
            this.basisValuesEdge = singleEdgeBasis.Values.GetValues(singleEdgeRule.Nodes);
        }
Пример #27
0
        void GetQuadRuleSet_Internal(int order)
        {
            using (new FuncTrace()) {
                int original_order = order;
                stpwGetQuadRuleSet.Start();
                order = Math.Max(order, 2); // Ansatz won't work below 2!
                int D = this.tracker.GridDat.SpatialDimension;;

                // check arguments, init
                // =====================

                CellMask _mask = this.MaxGrid;

                // subgrid on which the volume rule should be constructed
                // ======================================================
                CellBoundaryQuadratureScheme cellBndSchme     = new CellBoundaryQuadratureScheme(this.cellFaceFactory, _mask);
                CellBoundaryQuadratureScheme cellBndLineSchme = null;
                if (this.UseStokes)
                {
                    cellBndLineSchme = new CellBoundaryQuadratureScheme(this.LevelSetBoundaryLineFactory, _mask);
                }

                // set up
                // ======

                int NoOfEqTotal, NoOfStokesEq, NoOfGaußEq;
                DivergenceFreeBasis DivFreeBasis = this.UseGauß ? new DivergenceFreeBasis(tracker.GridDat, this.Kref, order + 1) : null;
                Basis ScalarBasis = this.UseStokes ? new Basis(this.tracker.GridDat, order + 1) : null; // we loose a order of 1 for the volume rule due to the divergence operator

                NoOfGaußEq   = DivFreeBasis != null ? (DivFreeBasis.Count / D) : 0;
                NoOfStokesEq = (ScalarBasis != null ? ScalarBasis.Length : 0) * D;

                NoOfEqTotal = NoOfGaußEq + NoOfStokesEq;

                // define Nodes
                // ============
                NodeSet NodeSet = null;
                {
                    if (this.Kref.GetType() == typeof(Square))
                    {
                        int K = (int)Math.Ceiling(Math.Sqrt(NoOfEqTotal * 1.7)) + 1;

                        var Nodes1D = GenericBlas.Linspace(-1, 1, K);

                        var _NodeSet = MultidimensionalArray.Create(K * K, 2);
                        int n        = 0;
                        for (int i = 0; i < K /*&& n <= NoOfEq*1.1*/; i++)
                        {
                            for (int j = 0; j < K /*&& n <= NoOfEq*1.1*/; j++)
                            {
                                _NodeSet[n, 0] = Nodes1D[i];
                                _NodeSet[n, 1] = Nodes1D[j];
                                n++;
                            }
                        }

                        NodeSet = new NodeSet(this.Kref, _NodeSet);
                    }
                    else
                    {
                        for (int o = 1; o < 1000000; o++)
                        {
                            var qr = Kref.GetBruteForceQuadRule(o, 0);
                            if (qr.NoOfNodes >= (NoOfEqTotal * 1.1))
                            {
                                NodeSet = qr.Nodes;
                                break;
                            }
                        }
                    }
                }
                int NoOfNodes = NodeSet.GetLength(0);

                // find RHS integrals
                // ==================

                MultidimensionalArray RHS_Gauß = null;
                if (this.UseGauß)
                {
                    stpwGetQuadRuleSet_GaussRHS.Start();
                    RHS_Gauß = this.GaußAnsatzRHS(DivFreeBasis, cellBndSchme, _mask, order);
                    stpwGetQuadRuleSet_GaussRHS.Stop();
                    Debug.Assert(RHS_Gauß.Dimension == 2);
                    Debug.Assert(RHS_Gauß.GetLength(0) == NoOfGaußEq);
                    Debug.Assert(RHS_Gauß.GetLength(1) == _mask.NoOfItemsLocally);
                }

                MultidimensionalArray RHS_Stokes = null;
                if (this.UseStokes)
                {
                    stpwGetQuadRuleSet_StokesRHS.Start();
                    RHS_Stokes = this.StokesAnsatzRHS(ScalarBasis, cellBndLineSchme, _mask, order);
                    stpwGetQuadRuleSet_StokesRHS.Stop();
                    Debug.Assert(RHS_Stokes.Dimension == 2);
                    Debug.Assert(RHS_Stokes.GetLength(0) == NoOfStokesEq);
                    Debug.Assert(RHS_Stokes.GetLength(1) == _mask.NoOfItemsLocally);
                }

                // construct da rule!
                // ==================
                ChunkRulePair <QuadRule>[] SurfaceRule;
                {
                    SurfaceRule = new ChunkRulePair <QuadRule> [_mask.NoOfItemsLocally];
                    var grddat = this.tracker.GridDat;

                    // loop over cells in subgrid...
                    int jSub = 0;
                    foreach (int jCell in _mask.ItemEnum)  // loop over cells in the mask


                    // setup System
                    // ============

                    {
                        NodeSet surfNodes;
                        if (this.SurfaceNodesOnZeroLevset)
                        {
                            surfNodes = ProjectOntoLevset(jCell, NodeSet);
                        }
                        else
                        {
                            surfNodes = NodeSet;
                        }

                        MultidimensionalArray metrics;
                        {
                            int iKref = grddat.Cells.GetRefElementIndex(jCell);
                            metrics = LevelSetData.GetLevelSetNormalReferenceToPhysicalMetrics(surfNodes, jCell, 1);
                        }

                        MultidimensionalArray Mtx_Gauss = null;
                        if (this.UseGauß)
                        {
                            Mtx_Gauss = GaußAnsatzMatrix(DivFreeBasis, surfNodes, jCell);
                            Debug.Assert(Mtx_Gauss.Dimension == 2);
                            Debug.Assert(Mtx_Gauss.GetLength(0) == NoOfGaußEq);
                            Debug.Assert(Mtx_Gauss.GetLength(1) == NoOfNodes);
                        }

                        MultidimensionalArray Mtx_Stokes = null;
                        if (this.UseStokes)
                        {
                            Mtx_Stokes = this.StokesAnsatzMatrix(ScalarBasis, surfNodes, jCell);
                            Debug.Assert(Mtx_Stokes.Dimension == 2);
                            Debug.Assert(Mtx_Stokes.GetLength(0) == NoOfStokesEq);
                            Debug.Assert(Mtx_Stokes.GetLength(1) == NoOfNodes);
                            for (int i = 0; i < NoOfStokesEq; i++)
                            {
                                for (int j = 0; j < NoOfNodes; j++)
                                {
                                    Mtx_Stokes[i, j] /= metrics[0, j];
                                }
                            }
                        }

                        stpwGetQuadRuleSet_SolveRHS.Start();

                        // convert to FORTRAN order
                        MultidimensionalArray _Mtx = MultidimensionalArray.Create(NoOfEqTotal, NoOfNodes);
                        if (this.UseGauß)
                        {
                            _Mtx.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { NoOfGaußEq - 1, NoOfNodes - 1 }).Set(Mtx_Gauss);
                        }
                        if (this.UseStokes)
                        {
                            _Mtx.ExtractSubArrayShallow(new int[] { NoOfGaußEq, 0 }, new int[] { NoOfStokesEq + NoOfGaußEq - 1, NoOfNodes - 1 }).Set(Mtx_Stokes);
                        }


                        // convert to FORTRAN order
                        Debug.Assert(NoOfNodes >= NoOfEqTotal);
                        MultidimensionalArray _RHS = MultidimensionalArray.Create(NoOfNodes, 1); // this is also output, so it must be larger!
                        {
                            for (int i = 0; i < NoOfGaußEq; i++)
                            {
                                _RHS[i, 0] = RHS_Gauß[i, jSub];
                            }
                            for (int i = 0; i < NoOfStokesEq; i++)
                            {
                                _RHS[i + NoOfGaußEq, 0] = RHS_Stokes[i, jSub];
                            }
                        }

                        MultidimensionalArray __RHS = null, __Mtx = null;
                        if (this.Docheck)
                        {
                            // values used for testing:
                            __RHS = MultidimensionalArray.Create(NoOfEqTotal);
                            for (int i = 0; i < NoOfEqTotal; i++)
                            {
                                __RHS[i] = _RHS[i, 0];
                            }
                            __Mtx = MultidimensionalArray.Create(_Mtx.NoOfRows, _Mtx.NoOfCols);
                            __Mtx.SetMatrix(_Mtx);
                        }

                        // solve system
                        // ============

                        //int M = _Mtx.NoOfRows;
                        //int N = _Mtx.NoOfCols;
                        //LAPACK.F77_LAPACK.DGELSY(M, N, _Mtx.Entries, _RHS.Entries, 1, 1.0e-14);
                        _Mtx.LeastSquareSolve(_RHS);


                        if (this.Docheck)
                        {
                            // Probe:
                            MultidimensionalArray X = MultidimensionalArray.Create(NoOfNodes); // weights
                            X.ResizeShallow(NoOfNodes, 1).SetMatrix(_RHS);
                            __RHS.Multiply(-1.0, __Mtx, X, 1.0, "j", "jk", "k");
                            double L2_ERR = __RHS.L2Norm();
                            if (L2_ERR > 1.0e-7)
                            {
                                throw new ApplicationException("Quadrature rule in cell " + jCell + " seems to be not very precise: L2_ERR = " + L2_ERR);
                            }
                            //Debug.Assert(L2_ERR < 1.0e-8, "Quadrature rule in cell " + jCell + " seems to be not very precise: L2_ERR = " + L2_ERR);
                            //if (L2_ERR > 1.0e-9)
                            //    Console.WriteLine("Warning: Quadrature rule in cell " + jCell + ": L2_ERR = " + L2_ERR);
                        }


                        stpwGetQuadRuleSet_SolveRHS.Stop();

                        // return da rule!
                        // ===============

                        {
                            {
                                // the surface rule
                                // ----------------

                                QuadRule qr_l = new QuadRule()
                                {
                                    OrderOfPrecision = order,
                                    Weights          = MultidimensionalArray.Create(NoOfNodes),
                                    Nodes            = surfNodes
                                };


                                for (int k = 0; k < NoOfNodes; k++)
                                {
                                    qr_l.Weights[k] = _RHS[k, 0] / metrics[0, k];
                                }

                                SurfaceRule[jSub] = new ChunkRulePair <QuadRule>(Chunk.GetSingleElementChunk(jCell), qr_l);
                            }
                        }
                        jSub++;
                    }
                }


                stpwGetQuadRuleSet.Stop();

                if (!this.m_SurfaceRules.ContainsKey(original_order))
                {
                    this.m_SurfaceRules.Add(original_order, SurfaceRule);
                }
            }
        }
Пример #28
0
        /// <summary>
        /// Returns a <see cref="CellBoundaryQuadRule"/> for each cell in the
        /// given <paramref name="mask"/>. This rule consists of Gaussian
        /// quadrature rules on each continuous line segment on the edges of a
        /// given cell (where continuous means 'not intersected by the zero
        /// level set'
        /// </summary>
        /// <param name="mask"></param>
        /// <param name="order"></param>
        /// <returns></returns>
        public IEnumerable <IChunkRulePair <CellBoundaryQuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            if (!(mask is CellMask))
            {
                throw new ArgumentException("This works on cell basis, so a volume mask is required.");
            }
            //Console.WriteLine("boundary order: " + order);

            if (mask == null)
            {
                mask = CellMask.GetFullMask(levelSetData.GridDat);
            }

            if (order != lastOrder)
            {
                cache.Clear();
            }

            double[] EdgeToVolumeTransformationDeterminants = this.RefElement.FaceTrafoGramianSqrt;

            QuadRule baseRule = lineSimplex.GetQuadratureRule(order);
            int      D        = levelSetData.GridDat.SpatialDimension;
            var      _Cells   = levelSetData.GridDat.Cells;

            var result = new List <ChunkRulePair <CellBoundaryQuadRule> >(mask.NoOfItemsLocally);

            foreach (Chunk chunk in mask)
            {
                for (int i = 0; i < chunk.Len; i++)
                {
                    int cell = i + chunk.i0;

                    if (cache.ContainsKey(cell))
                    {
                        Debug.Assert(cache[cell].Nodes.IsLocked, "Quadrule with non-locked nodes in cache.");
                        result.Add(new ChunkRulePair <CellBoundaryQuadRule>(
                                       Chunk.GetSingleElementChunk(cell), cache[cell]));
                        continue;
                    }

                    List <double[]> nodes            = new List <double[]>();
                    List <double>   weights          = new List <double>();
                    int[]           noOfNodesPerEdge = new int[referenceLineSegments.Length];

                    for (int e = 0; e < referenceLineSegments.Length; e++)
                    {
                        LineSegment referenceSegment = referenceLineSegments[e];
                        int         iKref            = _Cells.GetRefElementIndex(cell);
                        double[]    roots            = referenceSegment.GetRoots(levelSetData.LevelSet, cell, iKref);
                        double      edgeDet          = EdgeToVolumeTransformationDeterminants[e];

                        LineSegment[] subSegments = referenceSegment.Split(roots);

                        for (int k = 0; k < subSegments.Length; k++)
                        {
                            // Evaluate sub segment at center to determine sign
                            NodeSet _point = new NodeSet(this.RefElement, subSegments[k].GetPointOnSegment(0.0));

                            double weightFactor = subSegments[k].Length / referenceSegment.Length;

                            if (weightFactor < 1.0e-14)
                            {
                                // segment has a length of approximately 0.0 => no need to care about it.
                                continue;
                            }

                            weightFactor *= edgeDet;

                            if (jumpType != JumpTypes.Implicit)
                            {
                                //using (tracker.GridDat.NSC.CreateLock(MultidimensionalArray.CreateWrapper(point, 1, D), this.iKref, -1.0)) {
                                MultidimensionalArray levelSetValue = this.levelSetData.GetLevSetValues(_point, cell, 1);

                                switch (jumpType)
                                {
                                case JumpTypes.Heaviside:
                                    if (levelSetValue[0, 0] <= -Tolerance)
                                    {
                                        continue;
                                    }
                                    break;

                                case JumpTypes.OneMinusHeaviside:
                                    if (levelSetValue[0, 0] >= Tolerance)
                                    {
                                        continue;
                                    }
                                    break;

                                case JumpTypes.Sign:
                                    weightFactor *= levelSetValue[0, 0].Sign();
                                    break;

                                default:
                                    throw new NotImplementedException();
                                }
                                //}
                            }

                            for (int m = 0; m < baseRule.NoOfNodes; m++)
                            {
                                // Base rule _always_ is a line rule, thus Nodes[*, _0_]
                                double[] point = subSegments[k].GetPointOnSegment(baseRule.Nodes[m, 0]);

                                weights.Add(weightFactor * baseRule.Weights[m]);
                                nodes.Add(point);

                                noOfNodesPerEdge[e]++;
                            }
                        }
                    }

                    if (weights.Count == 0)
                    {
                        result.Add(new ChunkRulePair <CellBoundaryQuadRule>(Chunk.GetSingleElementChunk(cell), emptyrule));
                        continue;
                    }

                    NodeSet localNodes = new NodeSet(this.RefElement, nodes.Count, D);
                    for (int j = 0; j < nodes.Count; j++)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            localNodes[j, d] = nodes[j][d];
                        }
                    }
                    localNodes.LockForever();

                    CellBoundaryQuadRule subdividedRule = new CellBoundaryQuadRule()
                    {
                        OrderOfPrecision      = order,
                        Weights               = MultidimensionalArray.Create(weights.Count),
                        Nodes                 = localNodes,
                        NumbersOfNodesPerFace = noOfNodesPerEdge
                    };
                    subdividedRule.Weights.SetSubVector(weights, -1);

                    cache.Add(cell, subdividedRule);

                    result.Add(new ChunkRulePair <CellBoundaryQuadRule>(
                                   Chunk.GetSingleElementChunk(cell), subdividedRule));
                }
            }

            return(result);
        }
Пример #29
0
            /// <summary>
            /// Integrand evaluation.
            /// </summary>
            protected override void Evaluate(int i0, int Length, QuadRule rule, MultidimensionalArray EvalResult)
            {
                NodeSet NodesUntransformed = rule.Nodes;
                int     M = NodesUntransformed.GetLength(0);
                int     D = NodesUntransformed.GetLength(1);

                // evaluate scalar function ans store result in 'EvalResult'
                // =========================================================
                Debug.Assert(!((m_func != null) && (m_funcEx != null)));
                if (m_func != null || m_Map != null)
                {
                    GridDat.TransformLocal2Global(NodesUntransformed, i0, Length, m_NodesTransformed, 0);
                }

                if (m_func != null)
                {
                    MultidimensionalArray inp  = m_NodesTransformed.ResizeShallow(new int[] { Length *M, D });
                    MultidimensionalArray outp = EvalResult.ResizeShallow(new int[] { Length *M });
                    m_func(inp, outp);
                    Debug.Assert(m_funcEx == null);
                }
                if (m_funcEx != null)
                {
                    m_funcEx(i0, Length, NodesUntransformed, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
                    Debug.Assert(m_func == null);
                }


                if (m_Map == null)
                {
                    // L2 error branch
                    // +++++++++++++++

                    MultidimensionalArray fieldvals = EvalResult.ResizeShallow(new int[] { Length, NodesUntransformed.GetLength(0) });
                    m_Owner.Evaluate(i0, Length, NodesUntransformed, fieldvals, -1.0);

                    for (int j = 0; j < Length; j++)
                    {
                        for (int m = 0; m < M; m++)
                        {
                            double e;
                            e = EvalResult[j, m, 0];
                            EvalResult[j, m, 0] = e * e;
                        }
                    }
                }
                else
                {
                    // arbitrary mapping branch
                    // ++++++++++++++++++++++++

                    MultidimensionalArray fieldvals = MultidimensionalArray.Create(new int[] { Length, NodesUntransformed.GetLength(0) });
                    m_Owner.Evaluate(i0, Length, NodesUntransformed, fieldvals, -1.0);

                    double[] X = new double[D];

                    for (int j = 0; j < Length; j++)
                    {
                        for (int m = 0; m < M; m++)
                        {
                            double e;
                            e = EvalResult[j, m, 0];

                            for (int d = 0; d < D; d++)
                            {
                                X[d] = m_NodesTransformed[j, m, d];
                            }

                            EvalResult[j, m, 0] = this.m_Map(X, fieldvals[j, m], e);
                        }
                    }
                }
            }
Пример #30
0
        /// <summary>
        ///
        /// </summary>
        protected void EvaluateEx(int i0, int Length, QuadRule QR, MultidimensionalArray QuadResult)
        {
            NodeSet   NodesUntransformed = QR.Nodes;
            IGridData grid          = this.GridDat;
            int       D             = grid.SpatialDimension;
            int       NoOfEquations = m_CodomainBasisS.Length;
            int       NoOfNodes     = NodesUntransformed.NoOfNodes;
            bool      isAffine      = grid.iGeomCells.IsCellAffineLinear(i0);

            int[] geom2log = grid.iGeomCells.GeomCell2LogicalCell;
#if DEBUG
            for (int i = 1; i < Length; i++)
            {
                Debug.Assert(grid.iGeomCells.IsCellAffineLinear(i + i0) == isAffine);

                if (geom2log == null)
                {
                    for (int e = 0; e < base.m_CodomainBasisS.Length; e++)
                    {
                        Debug.Assert(base.m_CodomainBasisS[e].GetLength(i + i0) == base.m_CodomainBasisS[e].GetLength(i0));
                    }
                }
                else
                {
                    for (int e = 0; e < base.m_CodomainBasisS.Length; e++)
                    {
                        Debug.Assert(base.m_CodomainBasisS[e].GetLength(geom2log[i + i0]) == base.m_CodomainBasisS[e].GetLength(geom2log[i0]));
                    }
                }
            }
#endif

            // this is an EvaluateEx: we are also responsible for multiplying with quadrature weights and summing up!
            Debug.Assert(QuadResult.Dimension == 2);
            Debug.Assert(QuadResult.GetLength(0) == Length);
            Debug.Assert(QuadResult.GetLength(1) == base.m_CodomainMapping.BasisS.Sum(basis => basis.Length));

            // ===================
            // Evaluate all fields
            // ===================

            this.Field_Eval.Start();

            for (int f = 0; f < m_DomainFields.Length; f++)
            {
                if (m_ValueRequired[f])
                {
                    Debug.Assert(m_FieldValues[f] != null);
                    if (m_DomainFields[f] != null)
                    {
                        m_DomainFields[f].Evaluate(i0, Length, NodesUntransformed, m_FieldValues[f]);
                    }
                    else
                    {
                        // field is null => set to 0.0
                        m_FieldValues[f].Clear();
                    }
                }
            }

            for (int f = 0; f < m_GradientRequired.Length; f++)
            {
                if (m_GradientRequired[f])
                {
                    Debug.Assert(m_FieldGradients[f] != null);
                    if (m_DomainFields[f] != null)
                    {
                        m_DomainFields[f].EvaluateGradient(i0, Length, NodesUntransformed, m_FieldGradients[f]);
                    }
                    else
                    {
                        // field is null => set to 0.0
                        m_FieldValues[f].Clear();
                    }
                }
            }

            this.Field_Eval.Stop();



            // =====================================
            // Transform Nodes to global coordinates
            // =====================================

            this.ParametersAndNormals.Start();

            var NodesGlobalCoords = grid.GlobalNodes.GetValue_Cell(NodesUntransformed, i0, Length);
            //var NodesGlobalCoords = MultidimensionalArray.Create(Length, NoOfNodes, D);

            this.ParametersAndNormals.Stop();

            // =======================
            // Evaluate Flux functions
            // =======================


            bool[] RequireTestFunctionGradient = new bool[NoOfEquations];
            bool[] Cleared_m_FluxValues        = new bool[NoOfEquations];

            this.Flux_Eval.Start();

            // loop over all equations ...
            for (int e = 0; e < NoOfEquations; e++)
            {
                //                Field fld = m_CodomainFields[e];

                if (m_NonlinFluxes[e].m_AllComponentsOfMyType.Length + m_NonlinFluxesEx[e].m_AllComponentsOfMyType.Length > 0)
                {
                    m_FluxValues[e].Clear();
                    Cleared_m_FluxValues[e] = true;

                    RequireTestFunctionGradient[e] = true;

                    // sum up all INonlinearFlux - objects
                    int jjj = 0;
                    foreach (INonlinearFlux nonlinFlx in m_NonlinFluxes[e].m_AllComponentsOfMyType)
                    {
                        m_NonlinFluxesWatches[e][jjj].Start();
                        nonlinFlx.Flux(m_Time,
                                       NodesGlobalCoords,
                                       m_NonlinFluxes[e].MapArguments(m_FieldValues, nonlinFlx),
                                       0, Length,
                                       m_FluxValues[e]);
                        m_NonlinFluxesWatches[e][jjj].Stop();
                        jjj++;
                    }

                    // sum up all INonlinearFluxEx - objects
                    jjj = 0;
                    foreach (INonlinearFluxEx nonlinFlxEx in m_NonlinFluxesEx[e].m_AllComponentsOfMyType)
                    {
                        m_NonlinFluxesExWatches[e][jjj].Start();
                        nonlinFlxEx.Flux(m_Time,
                                         NodesGlobalCoords,
                                         m_NonlinFluxesEx[e].MapArguments(m_FieldValues, nonlinFlxEx),
                                         0, Length,
                                         m_FluxValues[e],
                                         i0);
                        m_NonlinFluxesExWatches[e][jjj].Stop();
                        jjj++;
                    }

                    m_FluxValues[e].Scale(-1.0);
                }
            }



            // =========================
            // Evaluate Source functions
            // =========================

            bool[] RequireTestfunction    = new bool[NoOfEquations];
            bool[] Cleared_m_SourceValues = new bool[NoOfEquations];

            for (int e = 0; e < NoOfEquations; e++)
            {
                //                Equation eq = m_Equations[e];
                //                Field fld = eq.MyField;

                if (m_NonlinSources[e].m_AllComponentsOfMyType.Length > 0)
                {
                    m_SourceValues[e].Clear();
                    Cleared_m_SourceValues[e] = true;

                    RequireTestfunction[e] = true;

                    // sum up all sources
                    int jjj = 0;
                    foreach (INonlinearSource nonlinSrc in m_NonlinSources[e].m_AllComponentsOfMyType)
                    {
                        m_NonlinSources_watch[e][jjj].Start();
                        nonlinSrc.Source(m_Time,
                                         NodesGlobalCoords,
                                         m_NonlinSources[e].MapArguments(m_FieldValues, nonlinSrc),
                                         0, i0, Length,
                                         m_SourceValues[e]);
                        m_NonlinSources_watch[e][jjj].Stop();
                        jjj++;
                    }
                }
            }

            // ==============
            // Evaluate Forms
            // ==============

            for (int e = 0; e < NoOfEquations; e++)
            {
                if (m_NonlinFormV[e].m_AllComponentsOfMyType.Length > 0)
                {
                    for (int icomp = 0; icomp < m_NonlinFormV[e].m_AllComponentsOfMyType.Length; icomp++)
                    {
                        INonlinVolumeForm_V nonlinform = m_NonlinFormV[e].m_AllComponentsOfMyType[icomp];

                        if ((nonlinform.VolTerms & (TermActivationFlags.UxV | TermActivationFlags.V | TermActivationFlags.GradUxV)) == 0)
                        {
                            continue;
                        }
                        else
                        {
                            m_NonlinFormV_watch[e][icomp].Start();
                            RequireTestfunction[e] = true;

                            if (!Cleared_m_SourceValues[e])
                            {
                                m_SourceValues[e].Clear();
                                Cleared_m_SourceValues[e] = true;
                            }

                            VolumFormParams vfp;
                            vfp.GridDat = base.GridDat;
                            vfp.j0      = i0;
                            vfp.Len     = Length;
                            vfp.Xglobal = NodesGlobalCoords;
                            vfp.time    = this.m_Time;
                            int NoArgs              = m_NonlinFormV[e].NoOfArguments[icomp];
                            int NoParams            = m_NonlinFormV[e].NoOfParameters[icomp];
                            var MappedArgsAndParams = m_NonlinFormV[e].MapArguments(this.m_FieldValues, nonlinform);
                            vfp.ParameterVars = MappedArgsAndParams.GetSubVector(NoArgs, NoParams);
                            var MappedArgs = MappedArgsAndParams.GetSubVector(0, NoArgs);

                            var MappedGradients = m_NonlinFormV[e].MapArguments(this.m_FieldGradients, nonlinform, true);

                            nonlinform.Form(ref vfp, MappedArgs, MappedGradients, this.m_SourceValues[e]);
                            m_NonlinFormV_watch[e][icomp].Stop();
                        }
                    }
                }
            }

            for (int e = 0; e < NoOfEquations; e++)
            {
                if (m_NonlinFormGradV[e].m_AllComponentsOfMyType.Length > 0)
                {
                    for (int icomp = 0; icomp < m_NonlinFormGradV[e].m_AllComponentsOfMyType.Length; icomp++)
                    {
                        INonlinVolumeForm_GradV nonlinform = m_NonlinFormGradV[e].m_AllComponentsOfMyType[icomp];

                        if ((nonlinform.VolTerms & (TermActivationFlags.GradUxGradV | TermActivationFlags.UxGradV | TermActivationFlags.GradV)) == 0)
                        {
                            continue;
                        }
                        else
                        {
                            m_NonlinFormGradV_watch[e][icomp].Start();
                            RequireTestFunctionGradient[e] = true;

                            if (!Cleared_m_FluxValues[e])
                            {
                                this.m_FluxValues[e].Clear();
                                Cleared_m_FluxValues[e] = true;
                            }

                            VolumFormParams vfp;
                            vfp.GridDat = base.GridDat;
                            vfp.j0      = i0;
                            vfp.Len     = Length;
                            vfp.Xglobal = NodesGlobalCoords;
                            vfp.time    = this.m_Time;
                            int NoArgs              = m_NonlinFormGradV[e].NoOfArguments[icomp];
                            int NoParams            = m_NonlinFormGradV[e].NoOfParameters[icomp];
                            var MappedArgsAndParams = m_NonlinFormGradV[e].MapArguments(this.m_FieldValues, nonlinform);
                            vfp.ParameterVars = MappedArgsAndParams.GetSubVector(NoArgs, NoParams);
                            var MappedArgs = MappedArgsAndParams.GetSubVector(0, NoArgs);

                            var MappedGradients = m_NonlinFormGradV[e].MapArguments(this.m_FieldGradients, nonlinform, true);

                            nonlinform.Form(ref vfp, MappedArgs, MappedGradients, this.m_FluxValues[e]);
                            m_NonlinFormGradV_watch[e][icomp].Stop();
                        }
                    }
                }
            }
            this.Flux_Eval.Stop();



            // ================
            // Transform fluxes
            // ================

            // its less work to multiply the fluxes by the inverse Jacobi,
            // than each test function gradient by inverse Jacobi.
            // Could be interpreted as transforming fluxes to Refelem, i think....

            this.Flux_Trafo.Start();

            MultidimensionalArray InverseJacobi = null, JacobiDet = null;
            for (int e = 0; e < NoOfEquations; e++)
            {
                Debug.Assert((m_FluxValues[e] != null) == (m_FluxValuesTrf[e] != null));

                if (m_FluxValues[e] != null)
                {
                    if (InverseJacobi == null)
                    {
                        if (isAffine)
                        {
                            InverseJacobi = grid.iGeomCells.InverseTransformation.ExtractSubArrayShallow(new int[] { i0, 0, 0 }, new int[] { i0 + Length - 1, D - 1, D - 1 });
                        }
                        else
                        {
                            InverseJacobi = grid.InverseJacobian.GetValue_Cell(QR.Nodes, i0, Length);
                            //InverseJacobi = MultidimensionalArray.Create(Length, NoOfNodes, D, D);
                        }
                    }

                    if (JacobiDet == null && !isAffine)
                    {
                        JacobiDet = grid.JacobianDeterminat.GetValue_Cell(QR.Nodes, i0, Length);
                    }

                    if (isAffine)
                    {
                        m_FluxValuesTrf[e].Multiply(1.0, m_FluxValues[e], InverseJacobi, 0.0, "jke", "jkd", "jed");
                        // for affine-linear cells the multiplication with Jacobi determinant is done AFTER quadrature, since it is constant per cell.
                    }
                    else
                    {
                        m_FluxValuesTrf[e].Multiply(1.0, m_FluxValues[e], InverseJacobi, 0.0, "jke", "jkd", "jked");
                        m_FluxValuesTrf[e].Multiply(1.0, m_FluxValuesTrf[e], JacobiDet, 0.0, "jke", "jke", "jk"); // apply scaling with Jacobi determinant, for integral transformation
                    }
                }

                if (m_SourceValues[e] != null)
                {
                    if (JacobiDet == null && !isAffine)
                    {
                        JacobiDet = grid.JacobianDeterminat.GetValue_Cell(QR.Nodes, i0, Length);
                    }
                    //JacobiDet = MultidimensionalArray.Create(Length, NoOfNodes);

                    // apply scaling with Jacobi determinant, for integral transformation
                    if (isAffine)
                    {
                        // nop: for affine-linear cells the multiplication with Jacobi determinant is done AFTER quadrature, since it is constant per cell.
                    }
                    else
                    {
                        m_SourceValues[e].Multiply(1.0, m_SourceValues[e], JacobiDet, 0.0, "jk", "jk", "jk");
                    }
                }
            }

            this.Flux_Trafo.Stop();



            // =======================
            // evaluate test functions
            // =======================

            this.Basis_Eval.Start();

            if (this.m_MaxCodBasis != null && QR.NoOfNodes != this.m_TestFuncWeighted.GetLength(0))
            {
                this.m_TestFuncWeighted.Allocate(QR.NoOfNodes, m_MaxCodBasis.GetLength(i0));
            }
            if (this.m_MaxCodBasis_Gradient != null && QR.NoOfNodes != this.m_TestFuncGradWeighted.GetLength(0))
            {
                this.m_TestFuncGradWeighted.Allocate(QR.NoOfNodes, m_MaxCodBasis_Gradient.GetLength(i0), D);
            }

            if (m_MaxCodBasis != null)
            {
                var testFunc = m_MaxCodBasis.Evaluate(QR.Nodes);
                m_TestFuncWeighted.Multiply(1.0, QR.Weights, testFunc, 0.0, "kn", "k", "kn");
            }

            if (m_MaxCodBasis_Gradient != null)
            {
                var testFuncGrad = m_MaxCodBasis_Gradient.EvaluateGradient(QR.Nodes);
                m_TestFuncGradWeighted.Multiply(1.0, QR.Weights, testFuncGrad, 0.0, "knd", "k", "knd");
            }
            this.Basis_Eval.Stop();

            // ==========================================
            // multiply with test functions / save result
            // ==========================================

            MultidimensionalArray OrthoTrf = null; // to transform back to ONB on physical space...
            int iBufOrthoTrf;
            if (isAffine)
            {
                OrthoTrf = TempBuffer.GetTempMultidimensionalarray(out iBufOrthoTrf, Length);
                OrthoTrf.Multiply(1.0,
                                  grid.iGeomCells.JacobiDet.ExtractSubArrayShallow(new int[] { i0 }, new int[] { i0 + Length - 1 }),
                                  grid.ChefBasis.Scaling.ExtractSubArrayShallow(new int[] { i0 }, new int[] { i0 + Length - 1 }),
                                  0.0,
                                  "j", "j", "j");
            }
            else
            {
                int MaxDegree = Math.Max(this.m_MaxCodBasis != null ? m_MaxCodBasis.Degree : 0, this.m_MaxCodBasis_Gradient != null ? m_MaxCodBasis_Gradient.Degree : 0);
                OrthoTrf     = grid.ChefBasis.OrthonormalizationTrafo.GetValue_Cell(i0, Length, MaxDegree);
                iBufOrthoTrf = int.MinValue;
            }

            this.Loops.Start();
            int N0, N;
            N0 = 0;
            for (int e = 0; e < NoOfEquations; e++)   // loop over equations...

            {
                if (geom2log != null)
                {
                    N = m_CodomainBasisS[e].GetLength(geom2log[i0]);
                }
                else
                {
                    N = m_CodomainBasisS[e].GetLength(i0);
                }

                int iBuf;
                MultidimensionalArray QuadResult_e = TempBuffer.GetTempMultidimensionalarray(out iBuf, Length, N);

                // fluxes
                // ------
                if (RequireTestFunctionGradient[e])
                {
                    MultidimensionalArray
                        Fluxes_e       = m_FluxValuesTrf[e],
                        testFuncGrad_e = null;
                    if (m_TestFuncGradWeighted.GetLength(1) == N)
                    {
                        testFuncGrad_e = m_TestFuncGradWeighted;
                    }
                    else
                    {
                        testFuncGrad_e = m_TestFuncGradWeighted.ExtractSubArrayShallow(new int[] { 0, 0, 0 }, new int[] { NoOfNodes - 1, N - 1, D - 1 });
                    }

                    QuadResult_e.Multiply(1.0, Fluxes_e, testFuncGrad_e, 0.0, "jn", "jke", "kne");
                }

                // sources
                // -------

                if (RequireTestfunction[e])
                {
                    MultidimensionalArray
                        SourceValues_e = m_SourceValues[e],
                        testFunc_e     = null;
                    if (m_TestFuncWeighted.GetLength(1) == N)
                    {
                        testFunc_e = m_TestFuncWeighted;
                    }
                    else
                    {
                        testFunc_e = m_TestFuncWeighted.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { NoOfNodes - 1, N - 1 });
                    }


                    QuadResult_e.Multiply(1.0, SourceValues_e, testFunc_e, 1.0, "jn", "jk", "kn");
                }

                // final transformations
                // ---------------------
                MultidimensionalArray trfQuadResult_e = QuadResult.ExtractSubArrayShallow(new int[] { 0, N0 }, new int[] { Length - 1, N0 + N - 1 });

                if (isAffine)
                {
                    trfQuadResult_e.Multiply(1.0, OrthoTrf, QuadResult_e, 0.0, "jn", "j", "jn");
                }
                else
                {
                    MultidimensionalArray _OrthoTrf;
                    if (OrthoTrf.GetLength(1) == N)
                    {
                        _OrthoTrf = OrthoTrf;
                    }
                    else
                    {
                        _OrthoTrf = OrthoTrf.ExtractSubArrayShallow(new int[] { 0, 0, 0 }, new int[] { Length - 1, N - 1, N - 1 });
                    }

                    trfQuadResult_e.Multiply(1.0, _OrthoTrf, QuadResult_e, 0.0, "jn", "jmn", "jm");
                }

                // next
                // ----

                TempBuffer.FreeTempBuffer(iBuf);
                N0 += N;
            }

            if (isAffine)
            {
                TempBuffer.FreeTempBuffer(iBufOrthoTrf);
            }

            this.Loops.Stop();

#if DEBUG
            QuadResult.CheckForNanOrInf(true, true, true);
#endif
        }