protected override void ComputeValues(NodeSet NS, int j0, int Len, MultidimensionalArray output)
                {
                    MultidimensionalArray Phi     = m_owner.GetLevSetValues(NS, j0, Len);
                    MultidimensionalArray GradPhi = m_owner.GetLevelSetReferenceGradients(NS, j0, Len);
                    MultidimensionalArray HessPhi = m_owner.GetLevelSetReferenceHessian(NS, j0, Len);

                    MultidimensionalArray ooNormGrad = new MultidimensionalArray(2);
                    MultidimensionalArray Laplace    = new MultidimensionalArray(2);
                    MultidimensionalArray Q          = new MultidimensionalArray(3);

                    int K = output.GetLength(1);
                    int D = GradPhi.GetLength(2);

                    Debug.Assert(D == this.m_owner.m_owner.GridDat.SpatialDimension);

                    ooNormGrad.Allocate(Len, K);
                    Laplace.Allocate(Len, K);
                    Q.Allocate(Len, K, D);


                    // compute the monstrous formula
                    // -----------------------------

                    // norm of Gradient:
                    for (int d = 0; d < D; d++)
                    {
                        var GradPhi_d = GradPhi.ExtractSubArrayShallow(-1, -1, d);
                        ooNormGrad.Multiply(1.0, GradPhi_d, GradPhi_d, 1.0, "ik", "ik", "ik");
                    }
                    ooNormGrad.ApplyAll(x => 1.0 / Math.Sqrt(x));

                    // laplacian of phi:
                    for (int d = 0; d < D; d++)
                    {
                        var HessPhi_d_d = HessPhi.ExtractSubArrayShallow(-1, -1, d, d);
                        Laplace.Acc(1.0, HessPhi_d_d);
                    }

                    // result = Laplacian(phi)/|Grad phi|
                    output.Multiply(1.0, Laplace, ooNormGrad, 0.0, "ik", "ik", "ik");


                    // result = Grad(1/|Grad(phi)|)
                    for (int d1 = 0; d1 < D; d1++)
                    {
                        var Qd = Q.ExtractSubArrayShallow(-1, -1, d1);

                        for (int d2 = 0; d2 < D; d2++)
                        {
                            var Grad_d2    = GradPhi.ExtractSubArrayShallow(-1, -1, d2);
                            var Hess_d2_d1 = HessPhi.ExtractSubArrayShallow(-1, -1, d2, d1);

                            Qd.Multiply(-1.0, Grad_d2, Hess_d2_d1, 1.0, "ik", "ik", "ik");
                        }
                    }

                    ooNormGrad.ApplyAll(x => x * x * x);

                    output.Multiply(1.0, GradPhi, Q, ooNormGrad, 1.0, "ik", "ikd", "ikd", "ik");
                }
Esempio n. 2
0
        /// <summary>
        /// Change-of-basis, in cell 0
        /// </summary>
        /// <param name="jCell"></param>
        /// <param name="pl"></param>
        public MultidimensionalArray GetChangeofBasisMatrix(int jCell, PolynomialList pl)
        {
            var m_Context = this.GridDat;
            int N         = this.Length;
            int M         = pl.Count;
            int J         = this.GridDat.iLogicalCells.NoOfLocalUpdatedCells;

            if (jCell < 0 || jCell >= J)
            {
                throw new ArgumentOutOfRangeException("cell index out of range");
            }
            MultidimensionalArray Mtx = MultidimensionalArray.Create(N, M);


            var cellMask = new CellMask(m_Context, new[] { new Chunk()
                                                           {
                                                               i0 = jCell, Len = 1
                                                           } }, MaskType.Geometrical);

            // we project the basis function from 'jCell1' onto 'jCell0'

            CellQuadrature.GetQuadrature(new int[2] {
                N, M
            }, m_Context,
                                         (new CellQuadratureScheme(true, cellMask)).Compile(m_Context, this.Degree + pl.MaxAbsoluteDegree), // integrate over target cell
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray _EvalResult) {
                NodeSet nodes_Cell0 = QR.Nodes;
                Debug.Assert(Length == 1);

                //NodesGlobal.Allocate(1, nodes_Cell0.GetLength(0), nodes_Cell0.GetLength(1));
                //m_Context.TransformLocal2Global(nodes_Cell0, jCell0, 1, NodesGlobal, 0);
                //var nodes_Cell1 = new NodeSet(GridDat.iGeomCells.GetRefElement(jCell1), nodes_Cell0.GetLength(0), nodes_Cell0.GetLength(1));
                //m_Context.TransformGlobal2Local(NodesGlobal.ExtractSubArrayShallow(0, -1, -1), nodes_Cell1, jCell1, null);
                //nodes_Cell1.LockForever();

                var phi_0 = this.CellEval(nodes_Cell0, jCell, 1).ExtractSubArrayShallow(0, -1, -1);
                MultidimensionalArray R = MultidimensionalArray.Create(QR.NoOfNodes, pl.Count);
                pl.Evaluate(nodes_Cell0, R);

                var EvalResult = _EvalResult.ExtractSubArrayShallow(0, -1, -1, -1);
                EvalResult.Multiply(1.0, R, phi_0, 0.0, "knm", "km", "kn");
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                Debug.Assert(Length == 1);

                var res = ResultsOfIntegration.ExtractSubArrayShallow(0, -1, -1);
                Mtx.Clear();
                Mtx.Acc(1.0, res);
            }).Execute();

            return(Mtx);
        }
Esempio n. 3
0
        /// <summary>
        /// Transforms the given <paramref name="origTarget"/> into some
        /// serializable format.
        /// </summary>
        /// <param name="origTarget"></param>
        /// <returns></returns>
        public static object GetTarget(object origTarget)
        {
            if (origTarget is IMutableMatrixEx)
            {
                // Hack: Type is not serializable, so use full matrix instead
                origTarget = origTarget.As <IMutableMatrixEx>().ToFullMatrixOnProc0();
            }
            else if (origTarget is NodeSet)
            {
                NodeSet nodeSet            = origTarget.Cast <NodeSet>();
                MultidimensionalArray temp = MultidimensionalArray.Create(nodeSet.Lengths);
                temp.Acc(1.0, nodeSet);
                origTarget = temp;
            }

            return(origTarget);
        }
Esempio n. 4
0
        /// <summary>
        /// curvature computation according to Bonnet's formula
        /// Copy-Paste from <see cref="LevelSet.EvaluatetotalCurvature"/>, since there is no analytic formula for the curvature of an ellipse
        /// </summary>
        public void EvaluateTotalCurvature(int j0, int Len, NodeSet NodeSet, MultidimensionalArray result)
        {
            // (siehe FK, persoenliche Notizen, 08mar13)


            // checks
            // ------

            int K = NodeSet.NoOfNodes;

            if (result.Dimension != 2)
            {
                throw new ArgumentException();
            }
            if (result.GetLength(0) != Len)
            {
                throw new ArgumentException();
            }
            if (result.GetLength(1) != K)
            {
                throw new ArgumentException();
            }
            int D = NodeSet.SpatialDimension;
            //Debug.Assert(D == this.GridDat.SpatialDimension);


            // buffers:
            // --------
            //MultidimensionalArray Phi = new MultidimensionalArray(2);
            MultidimensionalArray GradPhi = new MultidimensionalArray(3);
            MultidimensionalArray HessPhi = new MultidimensionalArray(4);

            MultidimensionalArray ooNormGrad = new MultidimensionalArray(2);
            MultidimensionalArray Laplace    = new MultidimensionalArray(2);
            MultidimensionalArray Q          = new MultidimensionalArray(3);

            //Phi.Allocate(Len, K);
            GradPhi.Allocate(Len, K, D);
            HessPhi.Allocate(Len, K, D, D);
            ooNormGrad.Allocate(Len, K);
            Laplace.Allocate(Len, K);
            Q.Allocate(Len, K, D);

            // derivatives
            // -----------

            // evaluate gradient
            this.EvaluateGradient(j0, Len, NodeSet, GradPhi);

            // evaluate Hessian
            this.EvaluateHessian(j0, Len, NodeSet, HessPhi);


            // compute the monstrous formula
            // -----------------------------

            // norm of Gradient:
            for (int d = 0; d < D; d++)
            {
                var GradPhi_d = GradPhi.ExtractSubArrayShallow(-1, -1, d);
                ooNormGrad.Multiply(1.0, GradPhi_d, GradPhi_d, 1.0, "ik", "ik", "ik");
            }
            ooNormGrad.ApplyAll(x => 1.0 / Math.Sqrt(x));

            // laplacian of phi:
            for (int d = 0; d < D; d++)
            {
                var HessPhi_d_d = HessPhi.ExtractSubArrayShallow(-1, -1, d, d);
                Laplace.Acc(1.0, HessPhi_d_d);
            }

            // result = Laplacian(phi)/|Grad phi|
            result.Multiply(1.0, Laplace, ooNormGrad, 0.0, "ik", "ik", "ik");


            // result += Grad(1/|Grad(phi)|)
            for (int d1 = 0; d1 < D; d1++)
            {
                var Qd = Q.ExtractSubArrayShallow(-1, -1, d1);

                for (int d2 = 0; d2 < D; d2++)
                {
                    var Grad_d2    = GradPhi.ExtractSubArrayShallow(-1, -1, d2);
                    var Hess_d2_d1 = HessPhi.ExtractSubArrayShallow(-1, -1, d2, d1);

                    Qd.Multiply(-1.0, Grad_d2, Hess_d2_d1, 1.0, "ik", "ik", "ik");
                }
            }

            ooNormGrad.ApplyAll(x => x * x * x);

            result.Multiply(1.0, GradPhi, Q, ooNormGrad, 1.0, "ik", "ikd", "ikd", "ik");
        }
Esempio n. 5
0
        /// <summary>
        /// Computation of mean curvature according to Bonnet's formula.
        /// </summary>
        /// <param name="scale"></param>
        /// <param name="Output">
        /// output.
        /// </param>
        /// <param name="quadScheme"></param>
        /// <param name="UseCenDiffUpTo">
        /// Either 0, 1, or 2:
        /// If 0, all derivatives are computed locally (broken derivative);
        /// if 1, the first order derivatives are computed by central
        /// differences, while the second order ones are computed locally,
        /// based on the first order ones;
        /// if 2, all derivatives are computed by central differences.
        /// </param>
        /// <param name="_1stDerivDegree">
        /// Relative DG polynomial degree for the 1st order derivatives, i.e.
        /// degree is <paramref name="_1stDerivDegree"/>+<em>p</em>, where
        /// <em>p</em> is the degree of this field.
        /// Only active if <paramref name="UseCenDiffUpTo"/> is greater than 0.
        /// </param>
        /// <param name="_2ndDerivDegree">
        /// Relative DG polynomial degree for the 2nd order derivatives, i.e.
        /// degree is <paramref name="_2ndDerivDegree"/>+<em>p</em>, where
        /// <em>p</em> is the degree of this field. Only active if
        /// <paramref name="UseCenDiffUpTo"/> is greater than 1.
        /// </param>
        /// <remarks>
        /// using central differences causes memory allocation: <em>D</em>
        /// fields for <paramref name="UseCenDiffUpTo"/>=1, and
        /// <em>D</em>*(<em>D</em>+1) for <paramref name="UseCenDiffUpTo"/>=2,
        /// where <em>D</em> notates the spatial dimension.
        /// </remarks>
        public void ProjectTotalcurvature2(
            double scale,
            SinglePhaseField Output,
            int UseCenDiffUpTo,
            int _1stDerivDegree             = 0,
            int _2ndDerivDegree             = 0,
            CellQuadratureScheme quadScheme = null)
        {
            using (new FuncTrace()) {
                if (UseCenDiffUpTo < 0 || UseCenDiffUpTo > 2)
                {
                    throw new ArgumentOutOfRangeException();
                }

                //int M = Output.Basis.Length;
                //int N = this.Basis.Length;
                int D = this.GridDat.SpatialDimension;
                //var NSC = m_context.NSC;

                SubGrid sgrd = null;
                SpatialOperator.SubGridBoundaryModes bndMode = SpatialOperator.SubGridBoundaryModes.InnerEdge;
                if (UseCenDiffUpTo >= 1 && quadScheme != null && quadScheme.Domain != null)
                {
                    sgrd    = new SubGrid(quadScheme.Domain);
                    bndMode = SpatialOperator.SubGridBoundaryModes.OpenBoundary;
                }

                // compute 1st order derivatives by central differences, if desired
                // ================================================================
                Basis B2 = new Basis(this.GridDat, this.Basis.Degree + _1stDerivDegree);

                SinglePhaseField[] GradientVector = null;
                if (UseCenDiffUpTo >= 1)
                {
                    GradientVector = new SinglePhaseField[D];
                    for (int d = 0; d < D; d++)
                    {
                        GradientVector[d] = new SinglePhaseField(B2);
                        GradientVector[d].DerivativeByFlux(1.0, this, d, sgrd, bndMode);
                    }
                }

                // compute 2nd order derivatives by central differences, if desired
                // ===============================================================
                Basis B3 = new Basis(this.GridDat, this.Basis.Degree + _2ndDerivDegree);

                SinglePhaseField[,] HessianTensor = null;
                if (UseCenDiffUpTo >= 2)
                {
                    HessianTensor = new SinglePhaseField[D, D];
                    for (int d1 = 0; d1 < D; d1++)
                    {
                        for (int d2 = 0; d2 < D; d2++)
                        {
                            HessianTensor[d1, d2] = new SinglePhaseField(B3);
                            HessianTensor[d1, d2].DerivativeByFlux(1.0, GradientVector[d1], d2, sgrd, bndMode);
                        }
                    }
                }

                // compute and project
                // ===================

                // buffers:
                MultidimensionalArray Phi     = new MultidimensionalArray(2);
                MultidimensionalArray GradPhi = new MultidimensionalArray(3);
                MultidimensionalArray HessPhi = new MultidimensionalArray(4);

                MultidimensionalArray ooNormGrad = new MultidimensionalArray(2);
                MultidimensionalArray Laplace    = new MultidimensionalArray(2);
                MultidimensionalArray Q          = new MultidimensionalArray(3);

                // evaluate/project:
                //double Erracc = 0;
                Output.ProjectField(scale,
                                    (ScalarFunctionEx) delegate(int j0, int Len, NodeSet NodeSet, MultidimensionalArray result) { // ScalarFunction2
                    Debug.Assert(result.Dimension == 2);
                    Debug.Assert(Len == result.GetLength(0));
                    int K = result.GetLength(1); // number of nodes


                    // alloc buffers
                    // -------------

                    if (Phi.GetLength(0) != Len || Phi.GetLength(1) != K)
                    {
                        Phi.Allocate(Len, K);
                        GradPhi.Allocate(Len, K, D);
                        HessPhi.Allocate(Len, K, D, D);
                        ooNormGrad.Allocate(Len, K);
                        Laplace.Allocate(Len, K);
                        Q.Allocate(Len, K, D);
                    }
                    else
                    {
                        Phi.Clear();
                        GradPhi.Clear();
                        HessPhi.Clear();
                        ooNormGrad.Clear();
                        Laplace.Clear();
                        Q.Clear();
                    }

                    // evaluate Gradient and Hessian
                    // -----------------------------

                    if (UseCenDiffUpTo >= 1)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            GradientVector[d].Evaluate(j0, Len, NodeSet, GradPhi.ExtractSubArrayShallow(-1, -1, d));
                        }
                    }
                    else
                    {
                        this.EvaluateGradient(j0, Len, NodeSet, GradPhi);
                    }

                    if (UseCenDiffUpTo == 2)
                    {
                        for (int d1 = 0; d1 < D; d1++)
                        {
                            for (int d2 = 0; d2 < D; d2++)
                            {
                                HessianTensor[d1, d2].Evaluate(j0, Len, NodeSet, HessPhi.ExtractSubArrayShallow(-1, -1, d1, d2));
                            }
                        }
                    }
                    else if (UseCenDiffUpTo == 1)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            var GradientVector_d = GradientVector[d];
                            GradientVector_d.EvaluateGradient(j0, Len, NodeSet, HessPhi.ExtractSubArrayShallow(-1, -1, d, -1), 0, 0.0);
                        }
                    }
                    else if (UseCenDiffUpTo == 0)
                    {
                        this.EvaluateHessian(j0, Len, NodeSet, HessPhi);
                    }
                    else
                    {
                        Debug.Assert(false);
                    }

                    // compute the monstrous formula
                    // -----------------------------

                    // norm of Gradient:
                    for (int d = 0; d < D; d++)
                    {
                        var GradPhi_d = GradPhi.ExtractSubArrayShallow(-1, -1, d);
                        ooNormGrad.Multiply(1.0, GradPhi_d, GradPhi_d, 1.0, "ik", "ik", "ik");
                    }
                    ooNormGrad.ApplyAll(x => 1.0 / Math.Sqrt(x));

                    // laplacian of phi:
                    for (int d = 0; d < D; d++)
                    {
                        var HessPhi_d_d = HessPhi.ExtractSubArrayShallow(-1, -1, d, d);
                        Laplace.Acc(1.0, HessPhi_d_d);
                    }

                    // result = Laplacian(phi)/|Grad phi|
                    result.Multiply(1.0, Laplace, ooNormGrad, 0.0, "ik", "ik", "ik");


                    // result = Grad(1/|Grad(phi)|)
                    for (int d1 = 0; d1 < D; d1++)
                    {
                        var Qd = Q.ExtractSubArrayShallow(-1, -1, d1);

                        for (int d2 = 0; d2 < D; d2++)
                        {
                            var Grad_d2    = GradPhi.ExtractSubArrayShallow(-1, -1, d2);
                            var Hess_d2_d1 = HessPhi.ExtractSubArrayShallow(-1, -1, d2, d1);

                            Qd.Multiply(-1.0, Grad_d2, Hess_d2_d1, 1.0, "ik", "ik", "ik");
                        }
                    }

                    ooNormGrad.ApplyAll(x => x * x * x);

                    result.Multiply(1.0, GradPhi, Q, ooNormGrad, 1.0, "ik", "ikd", "ikd", "ik");

                    //for (int i = 0; i < Len; i++) {
                    //    for (int k = 0; k < K; k++) {
                    //        double acc = 0;
                    //        for (int d = 0; d < D; d++) {
                    //            acc += GradPhi[i,k,d]*Q[i,k,d]*ooNormGrad[i,k];
                    //        }

                    //        Erracc += (acc - result[i,k]).Abs();
                    //    }
                    //}
                },
                                    quadScheme.SaveCompile(this.GridDat, (Output.Basis.Degree + this.m_Basis.Degree * (this.m_Basis.Degree - 1) * D) * 2)
                                    );
            }
        }
Esempio n. 6
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="velocity"></param>
        /// <returns></returns>
        public override double[] ComputeChangerate(double dt, ConventionalDGField[] velocity, double[] current_FLSprop)
        {
            GridData        grdat = (GridData)velocity[0].GridDat;
            FieldEvaluation fEval = new FieldEvaluation(grdat);

            MultidimensionalArray VelocityAtSamplePoints = MultidimensionalArray.Create(current_interfaceP.Lengths);

            int outP = fEval.Evaluate(1, velocity, current_interfaceP, 0, VelocityAtSamplePoints);

            if (outP != 0)
            {
                throw new Exception("points outside the grid for fieldevaluation");
            }

            // change rate for the material points is the velocity at the points
            if (FourierEvolve == Fourier_Evolution.MaterialPoints)
            {
                double[] velAtP = new double[2 * numFp];
                for (int sp = 0; sp < numFp; sp++)
                {
                    velAtP[sp * 2]     = VelocityAtSamplePoints[sp, 0];
                    velAtP[sp * 2 + 1] = VelocityAtSamplePoints[sp, 1];
                }
                return(velAtP);
            }

            // compute an infinitesimal change of sample points at the Fourier points/ change of Fourier modes
            MultidimensionalArray interfaceP_evo = current_interfaceP.CloneAs();
            double dt_infin = dt * 1e-3;

            interfaceP_evo.Acc(dt_infin, VelocityAtSamplePoints);

            RearrangeOntoPeriodicDomain(interfaceP_evo);
            double[] samplP_change = current_samplP.CloneAs();
            InterpolateOntoFourierPoints(interfaceP_evo, samplP_change);

            if (FourierEvolve == Fourier_Evolution.FourierPoints)
            {
                samplP_change.AccV(-1.0, current_samplP);
                samplP_change.ScaleV(1.0 / dt_infin);
                return(samplP_change);
            }
            else
            if (FourierEvolve == Fourier_Evolution.FourierModes)
            {
                Complex[] samplP_complex = new Complex[numFp];
                for (int sp = 0; sp < numFp; sp++)
                {
                    samplP_complex[sp] = (Complex)samplP_change[sp];
                }
                //Complex[] DFT_change = DFT.NaiveForward(samplP_complex, FourierOptions.Matlab);
                Complex[] DFT_change = samplP_complex; samplP_complex = null;
                Fourier.Forward(DFT_change, FourierOptions.Matlab);
                double[] DFT_change_double = new double[2 * numFp];
                for (int sp = 0; sp < numFp; sp++)
                {
                    DFT_change_double[sp * 2]     = (DFT_change[sp].Real - DFT_coeff[sp].Real) / dt_infin;
                    DFT_change_double[sp * 2 + 1] = (DFT_change[sp].Imaginary - DFT_coeff[sp].Imaginary) / dt_infin;
                }
                return(DFT_change_double);
            }
            else
            {
                throw new ArgumentException();
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Compares the cell surface and the boundary integral.
        /// </summary>
        public static void TestSealing(IGridData gdat)
        {
            int J = gdat.iLogicalCells.NoOfLocalUpdatedCells;

            int[,] E2Clog = gdat.iGeomEdges.LogicalCellIndices;

            //
            // compute cell surface via edge integrals
            //
            MultidimensionalArray CellSurf1 = MultidimensionalArray.Create(J);

            EdgeQuadrature.GetQuadrature(new int[] { 1 },
                                         gdat, new EdgeQuadratureScheme().Compile(gdat, 2),
                                         delegate(int i0, int Length, QuadRule rule, MultidimensionalArray EvalResult) { // evaluate
                EvalResult.SetAll(1.0);
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // save results
                for (int i = 0; i < Length; i++)
                {
                    int iEdge   = i + i0;
                    int jCellIn = E2Clog[iEdge, 0];
                    int jCellOt = E2Clog[iEdge, 1];

                    CellSurf1[jCellIn] += ResultsOfIntegration[i, 0];
                    if (jCellOt >= 0 && jCellOt < J)
                    {
                        CellSurf1[jCellOt] += ResultsOfIntegration[i, 0];
                    }
                }
            }).Execute();

            //
            // compute cell surface via cell boundary integrals
            //
            var cbqs = new CellBoundaryQuadratureScheme(false, null);

            foreach (var Kref in gdat.iGeomCells.RefElements)
            {
                cbqs.AddFactory(new StandardCellBoundaryQuadRuleFactory(Kref));
            }

            MultidimensionalArray CellSurf2 = MultidimensionalArray.Create(J);

            CellBoundaryQuadrature <CellBoundaryQuadRule> .GetQuadrature(new int[] { 1 },
                                                                         gdat, cbqs.Compile(gdat, 2),
                                                                         delegate(int i0, int Length, CellBoundaryQuadRule rule, MultidimensionalArray EvalResult) { // evaluate
                EvalResult.SetAll(1.0);
            },
                                                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // save results
                int NoOfFaces = ResultsOfIntegration.GetLength(1);
                for (int i = 0; i < Length; i++)
                {
                    int jCell = i + i0;
                    for (int iFace = 0; iFace < NoOfFaces; iFace++)
                    {
                        CellSurf2[jCell] += ResultsOfIntegration[i, iFace, 0];
                    }
                }
            }, cs : CoordinateSystem.Physical).Execute();

            //
            // compare
            //
            MultidimensionalArray Err = CellSurf1.CloneAs();

            Err.Acc(-1.0, CellSurf2);
            double ErrNorm = Err.L2Norm();
            double TotSurf = CellSurf1.L2Norm();

            Console.WriteLine("Area Check " + Err.L2Norm());
            Assert.LessOrEqual(ErrNorm / TotSurf, 1.0e-8);

            //for (int j = 0; j < J; j++) {
            //    if (Err[j].Abs() >= 1.0e-6) {
            //        Console.WriteLine("Mismatch between edge area and cell surface area in cell {0}, GlobalId {1}, No. of neighbors {3},  {2:0.####E-00}", j, gdat.CurrentGlobalIdPermutation.Values[j], Err[j], gdat.Cells.CellNeighbours[j].Length);
            //        schas.SetMeanValue(j, 1);
            //    }
            //}
        }
Esempio n. 8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="velocity"></param>
        /// <returns></returns>
        public override double[] ComputeChangerate(double dt, ConventionalDGField[] velocity, double[] current_FLSprop)
        {
            setMaterialInterfacePoints(current_FLSprop);

            GridData        grdat = (GridData)(velocity[0].GridDat);
            FieldEvaluation fEval = new FieldEvaluation(grdat);

            // Movement of the material interface points
            MultidimensionalArray VelocityAtSamplePointsXY = MultidimensionalArray.Create(current_interfaceP.Lengths);

            int outP = fEval.Evaluate(1, velocity, current_interfaceP, 0, VelocityAtSamplePointsXY);

            if (outP != 0)
            {
                throw new Exception("points outside the grid for fieldevaluation");
            }

            int numIp = current_interfaceP.Lengths[0];


            // change rate for the material points is the velocity at the points
            if (FourierEvolve == Fourier_Evolution.MaterialPoints)
            {
                double[] velAtP = new double[2 * numIp];
                for (int sp = 0; sp < numIp; sp++)
                {
                    velAtP[sp * 2]       = VelocityAtSamplePointsXY[sp, 0];
                    velAtP[(sp * 2) + 1] = VelocityAtSamplePointsXY[sp, 1];
                }
                return(velAtP);
            }

            // compute an infinitesimal change of sample points at the Fourier points/ change of Fourier modes
            MultidimensionalArray interfaceP_evo = current_interfaceP.CloneAs();
            double dt_infin = dt * 1e-3;

            interfaceP_evo.Acc(dt_infin, VelocityAtSamplePointsXY);

            // Movement of the center point
            MultidimensionalArray center_evo       = center.CloneAs();
            MultidimensionalArray VelocityAtCenter = center.CloneAs();

            switch (CenterMove)
            {
            case CenterMovement.None: {
                VelocityAtCenter.Clear();
                break;
            }

            case CenterMovement.Reconstructed: {
                center_evo = GetGeometricCenter(interfaceP_evo);
                //Console.WriteLine("center_evo = ({0}, {1}) / center = ({2}, {3})", center_evo[0, 0], center_evo[0, 1], center[0, 0], center[0, 1]);
                MultidimensionalArray center_change = center_evo.CloneAs();
                center_change.Acc(-1.0, center);
                center_change.Scale(1.0 / dt_infin);
                VelocityAtCenter[0, 0] = center_change[0, 0];
                VelocityAtCenter[0, 1] = center_change[0, 1];
                break;
            }

            case CenterMovement.VelocityAtCenter: {
                outP = fEval.Evaluate(1, velocity, center, 0, VelocityAtCenter);
                if (outP != 0)
                {
                    throw new Exception("center point outside the grid for fieldevaluation");
                }
                center_evo.Acc(dt_infin, VelocityAtCenter);
                break;
            }
            }
            //Console.WriteLine("Velocity at Center point = ({0}, {1})", VelocityAtCenter[0, 0], VelocityAtCenter[0, 1]);

            // transform to polar coordiantes
            MultidimensionalArray interP_evo_polar = interfaceP_polar.CloneAs();

            for (int sp = 0; sp < numIp; sp++)
            {
                double x_c = interfaceP_evo[sp, 0] - center_evo[0, 0];
                double y_c = interfaceP_evo[sp, 1] - center_evo[0, 1];

                double theta = Math.Atan2(y_c, x_c);
                if (theta < 0)
                {
                    theta = Math.PI * 2 + theta;
                }
                ;
                interP_evo_polar[sp, 0] = theta;
                interP_evo_polar[sp, 1] = Math.Sqrt(x_c.Pow2() + y_c.Pow2());
            }

            RearrangeOntoPeriodicDomain(interP_evo_polar);
            double[] samplP_change = current_samplP.CloneAs();
            InterpolateOntoFourierPoints(interP_evo_polar, samplP_change);

            if (FourierEvolve == Fourier_Evolution.FourierPoints)
            {
                samplP_change.AccV(-1.0, current_samplP);
                samplP_change.ScaleV(1.0 / dt_infin);
                double[] FPchange = new double[numFp + 2];
                FPchange[0] = VelocityAtCenter[0, 0];
                FPchange[1] = VelocityAtCenter[0, 1];
                for (int p = 0; p < numFp; p++)
                {
                    FPchange[p + 2] = samplP_change[p];
                }
                return(FPchange);
            }
            else
            if (FourierEvolve == Fourier_Evolution.FourierModes)
            {
                Complex[] samplP_complex = new Complex[numFp];
                for (int sp = 0; sp < numFp; sp++)
                {
                    samplP_complex[sp] = (Complex)samplP_change[sp];
                }
                //Complex[] DFTchange = DFT.NaiveForward(samplP_complex, FourierOptions.Matlab);
                Complex[] DFTchange = samplP_complex; samplP_complex = null;
                Fourier.Forward(DFTchange, FourierOptions.Matlab);
                double[] DFTchange_double = new double[2 * numFp + 2];
                DFTchange_double[0] = VelocityAtCenter[0, 0];
                DFTchange_double[1] = VelocityAtCenter[0, 1];
                for (int sp = 0; sp < numFp; sp++)
                {
                    DFTchange_double[2 + (sp * 2)]     = (DFTchange[sp].Real - DFT_coeff[sp].Real) / dt_infin;
                    DFTchange_double[2 + (sp * 2) + 1] = (DFTchange[sp].Imaginary - DFT_coeff[sp].Imaginary) / dt_infin;
                }
                return(DFTchange_double);
            }
            else
            {
                throw new ArgumentException();
            }
        }
Esempio n. 9
0
        /// <summary>
        /// %
        /// </summary>
        /// <param name="output"></param>
        /// <param name="input">input DG field; unchanged on </param>
        public void Perform(SinglePhaseField output, SinglePhaseField input)
        {
            if (!output.Basis.Equals(this.m_bOutput))
            {
                throw new ArgumentException("output basis mismatch");
            }
            if (!input.Basis.Equals(this.m_bInput))
            {
                throw new ArgumentException("output basis mismatch");
            }

            var GridDat = this.m_bOutput.GridDat;
            int N       = m_bOutput.Length;
            int Nin     = m_bInput.Length;
            int J       = GridDat.iLogicalCells.NoOfLocalUpdatedCells;

            diagnosis = new double[N * J];

            double[] RHS = new double[N];
            double[] f2  = new double[N];
            double[] g1  = new double[N];
            MultidimensionalArray Trf = MultidimensionalArray.Create(N, N);

            input.MPIExchange();


            for (int jCell = 0; jCell < J; jCell++)
            {
                Debug.Assert((this.AggregateBasisTrafo[jCell] != null) == (this.Stencils[jCell] != null));

                //FullMatrix invMassM = this.InvMassMatrix[jCell];
                MultidimensionalArray ExPolMtx = this.AggregateBasisTrafo[jCell];

                if (ExPolMtx != null)
                {
                    int[] Stencil_jCells = this.Stencils[jCell];
                    int   K = Stencil_jCells.Length;
                    Debug.Assert(Stencil_jCells[0] == jCell);

                    var coordIn = input.Coordinates;
                    //for(int n = Math.Min(Nin, N) - 1; n >= 0; n--) {
                    //    RHS[n] = coordIn[jCell, n];
                    //}
                    RHS.ClearEntries();
                    g1.ClearEntries();

                    var oldCoords = input.Coordinates.GetRow(jCell);

                    for (int k = 0; k < K; k++)
                    {
                        int jNeigh = Stencil_jCells[k];
                        for (int n = Math.Min(input.Basis.Length, N) - 1; n >= 0; n--)
                        {
                            f2[n] = input.Coordinates[jNeigh, n];
                        }
                        if (Nlim != null && Nlim[jNeigh] > 0)
                        {
                            for (int n = Nlim[jNeigh]; n < RHS.Length; n++)
                            {
                                f2[n] = 0;
                            }
                        }

                        for (int l = 0; l < N; l++)
                        {
                            double acc = 0;
                            for (int i = 0; i < N; i++)
                            {
                                acc += ExPolMtx[k, i, l] * f2[i];
                            }
                            RHS[l] += acc;
                        }
                    }

                    if (Nlim != null && Nlim[jCell] > 0)
                    {
                        for (int n = Nlim[jCell]; n < RHS.Length; n++)
                        {
                            RHS[n] = 0;
                        }
                    }

                    for (int l = 0; l < N; l++)
                    {
                        diagnosis[jCell * N + l] = RHS[l];
                    }

                    //invMassM.gemv(1.0, RHS, 0.0, g1);

                    Trf.Clear();
                    Trf.Acc(1.0, ExPolMtx.ExtractSubArrayShallow(0, -1, -1));

                    //Trf.Solve(FulCoords, AggCoords);
                    Trf.gemv(1.0, RHS, 0.0, g1);


                    if (Nlim != null && Nlim[jCell] > 0)
                    {
                        for (int n = Nlim[jCell]; n < RHS.Length; n++)
                        {
                            g1[n] = 0;
                        }
                    }

                    if (Nlim == null)
                    {
                        output.Coordinates.SetRow(jCell, g1);
                    }
                    else
                    {
                        if ((Nlim[jCell] <= 0 && this.notchangeunlim))
                        {
                            output.Coordinates.SetRow(jCell, oldCoords);
                        }
                        else
                        {
                            output.Coordinates.SetRow(jCell, g1);
                        }
                    }
                }
            }

            output.MPIExchange();
        }
Esempio n. 10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="CellPairs">
        /// 1st index: list of cells <br/>
        /// 2nd index: in {0, 1}
        /// </param>
        /// <param name="M">
        /// 1st index: corresponds with 1st index of <paramref name="CellPairs"/><br/>
        /// 2nd index: matrix row index <br/>
        /// 3rd index: matrix column index
        /// </param>
        /// <param name="Minv">the inverse of <paramref name="M"/></param>
        /// <remarks>
        /// Let \f$ K_j \f$ and \f$ K_i \f$ be two different cells with a linear-affine
        /// transformation to the reference element.
        /// Here, \f$ j \f$=<paramref name="CellPairs"/>[a,0] and \f$ i \f$=<paramref name="CellPairs"/>[a,1].
        /// The DG-basis in these cells can uniquely be represented as
        /// \f[
        /// \phi_{j n} (\vec{x}) = p_n (\vec{x}) \vec{1}_{K_j} (\vec{x})
        /// \textrm{ and }
        /// \phi_{i m} (\vec{x}) = q_m (\vec{x}) \vec{1}_{K_i} (\vec{x})
        /// \f]
        /// where \f$ \vec{1}_X \f$ denotes the characteristic function for set \f$ X \f$
        /// and \f$ p_n\f$  and \f$ p_m\f$  are polynomials.
        /// Then, for the output \f$ M \f$ =<paramref name="M"/>[a,-,-] fulfills
        /// \f[
        /// \phi_{j n} + \sum_{m} M_{m n} \phi_{i m}
        /// =
        /// p_n \vec{1}_{K_j \cup K_i}
        /// \f]
        /// </remarks>
        public void GetExtrapolationMatrices(int[,] CellPairs, MultidimensionalArray M, MultidimensionalArray Minv = null)
        {
            var m_Context = this.GridDat;
            int N         = this.Length;
            int Esub      = CellPairs.GetLength(0);
            int JE        = this.GridDat.iLogicalCells.Count;
            int J         = this.GridDat.iLogicalCells.NoOfLocalUpdatedCells;

            if (CellPairs.GetLength(1) != 2)
            {
                throw new ArgumentOutOfRangeException("second dimension is expected to be 2!");
            }
            if (M.Dimension != 3)
            {
                throw new ArgumentException();
            }
            if (M.GetLength(0) != Esub)
            {
                throw new ArgumentException();
            }
            if (M.GetLength(1) != N || M.GetLength(2) != N)
            {
                throw new ArgumentException();
            }
            if (Minv != null)
            {
                if (Minv.GetLength(0) != Esub)
                {
                    throw new ArgumentException();
                }
                if (Minv.GetLength(1) != N || Minv.GetLength(2) != N)
                {
                    throw new ArgumentException();
                }
            }

            MultidimensionalArray NodesGlobal = new MultidimensionalArray(3);
            MultidimensionalArray Minv_tmp    = MultidimensionalArray.Create(N, N);
            MultidimensionalArray M_tmp       = MultidimensionalArray.Create(N, N);


            for (int esub = 0; esub < Esub; esub++)   // loop over the cell pairs...

            {
                int jCell0 = CellPairs[esub, 0];
                int jCell1 = CellPairs[esub, 1];
                if (jCell0 < 0 || jCell0 >= JE)
                {
                    throw new ArgumentOutOfRangeException("Cell index out of range.");
                }
                if (jCell1 < 0 || jCell1 >= JE)
                {
                    throw new ArgumentOutOfRangeException("Cell index out of range.");
                }

                bool swap;
                if (jCell0 >= J)
                {
                    //if(true) {
                    swap = true;
                    int a = jCell0;
                    jCell0 = jCell1;
                    jCell1 = a;
                }
                else
                {
                    swap = false;
                }


                if (!m_Context.iGeomCells.IsCellAffineLinear(jCell0))
                {
                    throw new NotSupportedException("Currently not supported for curved cells.");
                }
                if (!m_Context.iGeomCells.IsCellAffineLinear(jCell1))
                {
                    throw new NotSupportedException("Currently not supported for curved cells.");
                }

                Debug.Assert(jCell0 < J);

                var cellMask = new CellMask(m_Context, new[] { new Chunk()
                                                               {
                                                                   i0 = jCell0, Len = 1
                                                               } }, MaskType.Geometrical);

                // we project the basis function from 'jCell1' onto 'jCell0'

                CellQuadrature.GetQuadrature(new int[2] {
                    N, N
                }, m_Context,
                                             (new CellQuadratureScheme(true, cellMask)).Compile(m_Context, this.Degree * 2), // integrate over target cell
                                             delegate(int i0, int Length, QuadRule QR, MultidimensionalArray _EvalResult) {
                    NodeSet nodes_Cell0 = QR.Nodes;
                    Debug.Assert(Length == 1);

                    NodesGlobal.Allocate(1, nodes_Cell0.GetLength(0), nodes_Cell0.GetLength(1));
                    m_Context.TransformLocal2Global(nodes_Cell0, jCell0, 1, NodesGlobal, 0);
                    var nodes_Cell1 = new NodeSet(GridDat.iGeomCells.GetRefElement(jCell1), nodes_Cell0.GetLength(0), nodes_Cell0.GetLength(1));
                    m_Context.TransformGlobal2Local(NodesGlobal.ExtractSubArrayShallow(0, -1, -1), nodes_Cell1, jCell1, null);
                    nodes_Cell1.LockForever();


                    var phi_0 = this.CellEval(nodes_Cell0, jCell0, 1).ExtractSubArrayShallow(0, -1, -1);
                    var phi_1 = this.CellEval(nodes_Cell1, jCell1, 1).ExtractSubArrayShallow(0, -1, -1);

                    var EvalResult = _EvalResult.ExtractSubArrayShallow(0, -1, -1, -1);

                    EvalResult.Multiply(1.0, phi_1, phi_0, 0.0, "kmn", "kn", "km");
                },
                                             /*_SaveIntegrationResults:*/ delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                    Debug.Assert(Length == 1);

                    var res = ResultsOfIntegration.ExtractSubArrayShallow(0, -1, -1);
                    Minv_tmp.Clear();
                    Minv_tmp.Acc(1.0, res);
                }).Execute();

                // compute the inverse
                Minv_tmp.InvertTo(M_tmp);

                // store
                if (!swap)
                {
                    M.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, M_tmp);
                    if (Minv != null)
                    {
                        Minv.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, Minv_tmp);
                    }
                }
                else
                {
                    M.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, Minv_tmp);
                    if (Minv != null)
                    {
                        Minv.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, M_tmp);
                    }
                }
            }
        }
Esempio n. 11
0
        static private void EvalComponent <T>(LevSetIntParams _inParams,
                                              int gamma, EquationComponentArgMapping <T> bf,
                                              MultidimensionalArray[][] argsPerComp, MultidimensionalArray[,] argsSum,
                                              int componentIdx,
                                              MultidimensionalArray ParamFieldValuesPos, MultidimensionalArray ParamFieldValuesNeg,
                                              int DELTA,
                                              Stopwatch timer,
                                              IDictionary <SpeciesId, MultidimensionalArray> LengthScales,
                                              CallComponent <T> ComponentFunc) where T : ILevelSetComponent
        {
            timer.Start();


            for (int i = 0; i < bf.m_AllComponentsOfMyType.Length; i++)    // loop over equation components
            {
                var comp = bf.m_AllComponentsOfMyType[i];

                LengthScales.TryGetValue(comp.NegativeSpecies, out _inParams.NegCellLengthScale);
                LengthScales.TryGetValue(comp.PositiveSpecies, out _inParams.PosCellLengthScale);

                argsPerComp[gamma][i].Clear();

                int NoOfArgs = bf.NoOfArguments[i];
                Debug.Assert(NoOfArgs == comp.ArgumentOrdering.Count);
                int NoOfParams = bf.NoOfParameters[i];
                Debug.Assert(NoOfParams == ((comp.ParameterOrdering != null) ? comp.ParameterOrdering.Count : 0));


                // map parameters
                _inParams.ParamsPos = new MultidimensionalArray[NoOfParams];
                _inParams.ParamsNeg = new MultidimensionalArray[NoOfParams];
                for (int c = 0; c < NoOfParams; c++)
                {
                    int targ = bf.AllToSub[i, c + NoOfArgs] - DELTA;
                    Debug.Assert(targ >= 0);
                    _inParams.ParamsPos[c] = ParamFieldValuesPos.ExtractSubArrayShallow(targ, -1, -1);
                    _inParams.ParamsNeg[c] = ParamFieldValuesNeg.ExtractSubArrayShallow(targ, -1, -1);
                }

                // evaluate equation components
                ComponentFunc(comp, gamma, i, _inParams);
#if DEBUG
                argsPerComp[gamma][i].CheckForNanOrInf();
#endif

                // sum up bilinear forms:
                {
                    MultidimensionalArray Summand = argsPerComp[gamma][i];

                    if (componentIdx >= 0)
                    {
                        for (int c = 0; c < NoOfArgs; c++)   // loop over arguments of equation component
                        {
                            int   targ   = bf.AllToSub[i, c];
                            int[] selSum = new int[Summand.Dimension];
                            selSum.SetAll(-1);
                            selSum[componentIdx] = c;

                            MultidimensionalArray Accu = argsSum[gamma, targ];

                            //int[] selAccu = new int[Accu.Dimension];
                            //selAccu.SetAll(-1);
                            //selAccu[componentIdx] = targ;
#if DEBUG
                            Summand.ExtractSubArrayShallow(selSum).CheckForNanOrInf();
#endif

                            Accu.Acc(1.0, Summand.ExtractSubArrayShallow(selSum));
                        }
                    }
                    else
                    {
                        // affin
#if DEBUG
                        Summand.CheckForNanOrInf();
#endif
                        MultidimensionalArray Accu = argsSum[gamma, 0];
                        Accu.Acc(1.0, Summand);
                    }
                }
            }
            timer.Stop();
        }
Esempio n. 12
0
        static internal void InvertMassMatrixBlocks(
            out Dictionary <SpeciesId, MassMatrixBlockContainer> MassMatrixBlocksInv,
            Dictionary <SpeciesId, MassMatrixBlockContainer> MassMatrixBlocks,
            int N)
        {
            using (new FuncTrace()) {
                MassMatrixBlocksInv = new Dictionary <SpeciesId, MassMatrixBlockContainer>();
                foreach (var Species in MassMatrixBlocks.Keys)
                {
                    var mblk = MassMatrixBlocks[Species].MassMatrixBlocks;
                    //var mblkB4agg = MassMatrixBlocks[Species].MassMatrixBlocks_B4Agglom;
                    var invmblk = MultidimensionalArray.Create(mblk.GetLength(0), N, N);
                    MassMatrixBlocksInv.Add(Species,
                                            new MassMatrixBlockContainer()
                    {
                        MassMatrixBlocks = invmblk,
                        //jCell2jSub = MassMatrixBlocks[Species].jCell2jSub,
                        jSub2jCell        = MassMatrixBlocks[Species].jSub2jCell,
                        IntegrationDomain = MassMatrixBlocks[Species].IntegrationDomain
                    });

                    int B = mblk.GetLength(0);
                    Debug.Assert(mblk.GetLength(2) >= N);

                    MultidimensionalArray blk     = MultidimensionalArray.Create(N, N);
                    MultidimensionalArray inv_Blk = MultidimensionalArray.Create(N, N);


                    // loop over all cut cells (mass matrix blocks)...
                    for (int b = 0; b < B; b++)
                    {
                        MultidimensionalArray _blk;
                        //if ((aggSw == true) || (mblkB4agg[b] == null)) {
                        _blk = mblk.ExtractSubArrayShallow(new int[] { b, 0, 0 }, new int[] { b - 1, N - 1, N - 1 });
                        //} else {
                        //    Debug.Assert(aggSw == false);
                        //    Debug.Assert(mblkB4agg[b] != null);
                        //    _blk = mblkB4agg[b].ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { N - 1, N - 1 });
                        //}

                        blk.Set(_blk);
                        if (blk.ContainsNanOrInf(true, true))
                        {
                            throw new ArithmeticException("NAN/INF in mass matrix.");
                        }

                        if (blk.InfNorm() == 0.0)
                        {
                            // a zero-block
                            invmblk.ExtractSubArrayShallow(b, -1, -1).Clear();
                        }
                        else
                        {
                            //blk.Invert(inv_Blk);
                            try {
                                inv_Blk.Clear();
                                inv_Blk.Acc(1.0, blk);
                                inv_Blk.InvertSymmetrical();

#if DEBUG
                                for (int n = 0; n < N; n++)
                                {
                                    for (int m = 0; m < N; m++)
                                    {
                                        Debug.Assert(inv_Blk[n, m] == inv_Blk[m, n]);
                                    }
                                }
#endif
                            } catch (ArithmeticException) {
                                Console.WriteLine("WARNING: indefinite mass matrix.");
                                blk.InvertTo(inv_Blk);
#if DEBUG
                                for (int n = 0; n < N; n++)
                                {
                                    for (int m = 0; m < N; m++)
                                    {
                                        Debug.Assert(Math.Abs(inv_Blk[n, m] - inv_Blk[m, n]) / (Math.Abs(inv_Blk[n, m]) + Math.Abs(inv_Blk[m, n])) <= 1.0e-9);
                                    }
                                }
#endif
                            }

                            if (blk.ContainsNanOrInf(true, true))
                            {
                                throw new ArithmeticException("NAN/INF in inverse mass matrix.");
                            }

                            invmblk.SetSubMatrix(inv_Blk, b, -1, -1);
                        }

                        /*
                         * bool Choleski_failed = false;
                         * bool Symmelim_failed = false;
                         * try {
                         *  blk.Initialize(_blk);
                         *  blk.InvertSymmetrical();
                         * } catch (ArithmeticException) {
                         *  Choleski_failed = true;
                         * }
                         * try {
                         *  blk.Initialize(_blk);
                         *  FullMatrix.TiredRoutine(blk);
                         * } catch (ArithmeticException) {
                         *  Symmelim_failed = true;
                         * }
                         *
                         * if (Choleski_failed || Symmelim_failed) {
                         *  Console.WriteLine("Mass matrix defect ({0},{1}): species {2}, jsub = {3};", Choleski_failed, Symmelim_failed,  LsTrk.GetSpeciesName(Species), b);
                         *
                         *  int J = LsTrk.Ctx.Grid.NoOfUpdateCells;
                         *  if (MassErrors == null) {
                         *      MassErrors = new Dictionary<SpeciesId, System.Collections.BitArray>();
                         *  }
                         *  if (!MassErrors.ContainsKey(Species)) {
                         *      MassErrors.Add(Species, new System.Collections.BitArray(J));
                         *  }
                         *  var _MassErrors = MassErrors[Species];
                         *
                         *  int[] globalIdx = cutted.SubgridIndex2LocalCellIndex;
                         *  int jCell = globalIdx[b];
                         *
                         *  _MassErrors[jCell] = true;
                         *
                         * }
                         * //*/
                    }
                }
            }
        }
Esempio n. 13
0
        private DoubleEdgeQuadRule CombineQr(DoubleEdgeQuadRule qrEdge, CellBoundaryQuadRule givenRule, int iFace, int jCell)
        {
            int D       = grd.SpatialDimension;
            var volSplx = m_cellBndQF.Simplex;
            int coD     = grd.Grid.GridSimplex.EdgeSimplex.SpatialDimension;

            // extract edge rule
            // -----------------

            int i0 = 0, iE = 0;

            for (int i = 0; i < iFace; i++)
            {
                i0 += givenRule.NumbersOfNodesPerEdge[i];
            }
            iE = i0 + givenRule.NumbersOfNodesPerEdge[iFace] - 1;

            if (iE < i0)
            {
                // rule is empty (measure is zero).

                if (qrEdge == null)
                {
                    DoubleEdgeQuadRule ret = new DoubleEdgeQuadRule();
                    ret.OrderOfPrecision = int.MaxValue - 1;
                    ret.Nodes            = MultidimensionalArray.Create(1, Math.Max(1, D - 1));
                    ret.Weights          = MultidimensionalArray.Create(1); // this is an empty rule, since the weight is zero!
                    ret.Median           = 1;
                    // (rules with zero nodes may cause problems at various places.)
                    return(ret);
                }
                else
                {
                    Debug.Assert(qrEdge.Median == qrEdge.NoOfNodes);
                    return(qrEdge);
                }
            }

            MultidimensionalArray NodesVol = givenRule.Nodes.ExtractSubArrayShallow(new int[] { i0, 0 }, new int[] { iE, D - 1 });
            MultidimensionalArray Weigts = givenRule.Weights.ExtractSubArrayShallow(new int[] { i0 }, new int[] { iE }).CloneAs();
            MultidimensionalArray Nodes = MultidimensionalArray.Create(iE - i0 + 1, coD);

            volSplx.VolumeToEdgeCoordinates(iFace, NodesVol, Nodes);

            //Debug.Assert((Weigts.Sum() - grd.Grid.GridSimplex.EdgeSimplex.Volume).Abs() < 1.0e-6, "i've forgotten the gramian");

            // combine
            // -------
            if (qrEdge == null)
            {
                // no rule defined yet - just set the one we have got
                // ++++++++++++++++++++++++++++++++++++++++++++++++++
                qrEdge                  = new DoubleEdgeQuadRule();
                qrEdge.Weights          = Weigts;
                qrEdge.Nodes            = Nodes;
                qrEdge.Median           = qrEdge.NoOfNodes;
                qrEdge.OrderOfPrecision = givenRule.OrderOfPrecision;
            }
            else
            {
                // take the mean of already defined and new rule
                // +++++++++++++++++++++++++++++++++++++++++++++

                int L1 = qrEdge.Nodes.GetLength(0);
                int L2 = Nodes.GetLength(0);
                Debug.Assert(coD == qrEdge.Nodes.GetLength(1));

                MultidimensionalArray newNodes = MultidimensionalArray.Create(L1 + L2, coD);
                newNodes.Set(qrEdge.Nodes, new int[] { 0, 0 }, new int[] { L1 - 1, coD - 1 });
                newNodes.Set(Nodes, new int[] { L1, 0 }, new int[] { L1 + L2 - 1, coD - 1 });

                MultidimensionalArray newWeights = MultidimensionalArray.Create(L1 + L2);
                newWeights.Acc(1.0, qrEdge.Weights, new int[] { 0 }, new int[] { L1 - 1 });
                newWeights.Acc(1.0, Weigts, new int[] { L1 }, new int[] { L1 + L2 - 1 });

                double oldSum = qrEdge.Weights.Sum();
                double newSum = Weigts.Sum();
                WeightInbalance += Math.Abs(oldSum - newSum);


                qrEdge.Nodes            = newNodes;
                qrEdge.Weights          = newWeights;
                qrEdge.Median           = L1;
                qrEdge.OrderOfPrecision = Math.Min(qrEdge.OrderOfPrecision, givenRule.OrderOfPrecision);
            }

            // return
            // ------
            return(qrEdge);
        }