Exemplo n.º 1
0
        static double JumpNorm(DGField f)
        {
            GridData grd      = (GridData)f.GridDat;
            int      D        = grd.SpatialDimension;
            var      e2cTrafo = grd.Edges.Edge2CellTrafos;

            f.MPIExchange();

            double Unorm = 0;

            EdgeQuadrature.GetQuadrature(
                new int[] { D + 1 }, grd,
                (new EdgeQuadratureScheme()).Compile(grd, f.Basis.Degree * 2),
                delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {  // Evaluate
                NodeSet NS = QR.Nodes;
                EvalResult.Clear();
                int NoOfNodes = NS.NoOfNodes;
                for (int j = 0; j < Length; j++)
                {
                    int iEdge    = j + i0;
                    int jCell_IN = grd.Edges.CellIndices[iEdge, 0];
                    int jCell_OT = grd.Edges.CellIndices[iEdge, 1];
                    var uDiff    = EvalResult.ExtractSubArrayShallow(new int[] { j, 0, 0 }, new int[] { j, NoOfNodes - 1, -1 });

                    if (jCell_OT >= 0)
                    {
                        int iTrafo_IN = grd.Edges.Edge2CellTrafoIndex[iEdge, 0];
                        int iTrafo_OT = grd.Edges.Edge2CellTrafoIndex[iEdge, 1];

                        MultidimensionalArray uIN = MultidimensionalArray.Create(1, NoOfNodes);
                        MultidimensionalArray uOT = MultidimensionalArray.Create(1, NoOfNodes);

                        NodeSet NS_IN = NS.GetVolumeNodeSet(grd, iTrafo_IN);
                        NodeSet NS_OT = NS.GetVolumeNodeSet(grd, iTrafo_OT);

                        f.Evaluate(jCell_IN, 1, NS_IN, uIN);
                        f.Evaluate(jCell_OT, 1, NS_OT, uOT);

                        uDiff.Acc(+1.0, uIN);
                        uDiff.Acc(-1.0, uOT);
                    }
                    else
                    {
                        uDiff.Clear();
                    }
                }

                EvalResult.ApplyAll(x => x * x);
            },
                delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {  // SaveIntegrationResults
                Unorm += ResultsOfIntegration.Sum();
            }).Execute();

            Unorm = Unorm.MPISum();

            return(Unorm.Sqrt());
        }
Exemplo 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);
        }
        private MultidimensionalArray EdgeQuadrature(ICompositeQuadRule <QuadRule> surfRule)
        {
            int E   = this.GridData.iLogicalEdges.Count;
            var ret = MultidimensionalArray.Create(E);

            BoSSS.Foundation.Quadrature.EdgeQuadrature.GetQuadrature(
                new int[] { 1 }, this.GridData,
                surfRule,
                delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { // Evaluate
                EvalResult.SetAll(1.0);
            },
                delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults
                ret.ExtractSubArrayShallow(new int[] { i0 }, new int[] { i0 + Length - 1 })
                .Set(ResultsOfIntegration.ExtractSubArrayShallow(-1, 0));
            }).Execute();

            return(ret);
        }
Exemplo n.º 4
0
        void OrthonormalityTest()
        {
            Basis B   = f1.Basis;
            int   N   = B.Length;
            var   Mtx = new FullMatrix(N, N);

            double TotErrSum = 0.0;

            CellQuadrature.GetQuadrature(new int[] { N, N }, this.GridDat,
                                         (new CellQuadratureScheme(true)).Compile(GridDat, Math.Min(B.Degree * 2, 16)),
                                         delegate(MultidimensionalArray NodesUntransformed, int iKref) {
                var ret = new NodeSetController.NodeSetContainer[] {
                    GridDat.NSC.CreateContainer(NodesUntransformed, iKref)
                };
                return(ret);
            },
                                         delegate(int i0, int Length, int NoOfNodes, MultidimensionalArray EvalResult) { // void Del_Evaluate
                var BasisVal = B.CellEval(0, i0, Length);

                EvalResult.Multiply(1.0, BasisVal, BasisVal, 0.0, "jknm", "jkn", "jkm");
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults
                for (int i = 0; i < Length; i++)
                {
                    var MassMtx = ResultsOfIntegration.ExtractSubArrayShallow(i, -1, -1);

                    double errsum = 0;
                    for (int n = 0; n < N; n++)
                    {
                        for (int m = 0; m < N; m++)
                        {
                            double soll = (n == m) ? 1.0 : 0.0;
                            errsum     += Math.Abs(MassMtx[m, n] - soll);
                        }
                    }

                    TotErrSum += errsum;
                }
            }).Execute();


            Console.WriteLine("orthonormality error sum:" + TotErrSum);
        }
        private MultidimensionalArray CellQuadrature(ICompositeQuadRule <QuadRule> surfRule)
        {
            int J   = this.GridData.iLogicalCells.NoOfLocalUpdatedCells;
            var ret = MultidimensionalArray.Create(J);

            BoSSS.Foundation.Quadrature.CellQuadrature.GetQuadrature(
                new int[] { 1 }, this.GridData,
                surfRule,
                delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { // Evaluate
                //Integrand.Evaluate(i0, Length, 0, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
                EvalResult.SetAll(1.0);
            },
                delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults
                var A = ret.ExtractSubArrayShallow(new int[] { i0 }, new int[] { i0 + Length - 1 });
                var B = ResultsOfIntegration.ExtractSubArrayShallow(-1, 0);
                A.Set(B);
            }).Execute();

            return(ret);
        }
Exemplo n.º 6
0
        MultidimensionalArray StokesAnsatzRHS(Basis TestBasis, CellBoundaryQuadratureScheme cellBndSchme, CellMask _mask, int order)
        {
            var GridDat = this.tracker.GridDat;
            CellBoundaryQuadrature <CellBoundaryQuadRule> qBnd = null;

            int N = TestBasis.Length;
            int D = GridDat.SpatialDimension;
            MultidimensionalArray RHS = MultidimensionalArray.Create(D, N, _mask.NoOfItemsLocally);

            double[] CellN       = new double[D]; // cell normal
            double[] SurfN       = new double[D]; // level-set normal
            double[] OutwardTang = new double[D]; // level-set tangent, outward of cell

            if (D != 2)
            {
                throw new NotSupportedException("Currently only supported for spatial dimension of 2.");
            }

            //MultidimensionalArray Nudes = null;
            int jSgrd = 0;

            qBnd = CellBoundaryQuadrature <CellBoundaryQuadRule> .GetQuadrature(new int[] { D, N },
                                                                                GridDat, cellBndSchme.Compile(GridDat, order),
                                                                                delegate(int i0, int Length, CellBoundaryQuadRule NS, MultidimensionalArray EvalResult) { // Evaluate
                //MultidimensionalArray BasisValues = TestBasis.Evaluate(0);                 // reference
                //var LSNormals = LsTrk.GetLevelSetReferenceNormals(iLevSet, 0, i0, Length); // reference
                MultidimensionalArray BasisValues = TestBasis.CellEval(NS.Nodes, i0, Length);                   // physical
                MultidimensionalArray LSNormals   = this.LevelSetData.GetLevelSetNormals(NS.Nodes, i0, Length); // physical

                for (int i = 0; i < Length; i++)                                                                // loop over cells
                //if(i0 + i == 1) {
                //    EvalResult.ExtractSubArrayShallow(i, -1, -1, -1).Clear();
                //    continue;
                //}

                {
                    CellBoundaryQuadRule cR = qBnd.CurrentRule;
                    int[] NodesPerEdge      = cR.NumbersOfNodesPerFace;
                    var Kref      = cR.RefElement;
                    int NoOfFaces = Kref.NoOfFaces;
                    int iNode     = 0;

                    Debug.Assert(NoOfFaces == NodesPerEdge.Length);
                    for (int e = 0; e < NoOfFaces; e++)       // loop over the faces of the cell

                    {
                        if (NodesPerEdge[e] <= 0)
                        {
                            continue;
                        }

                        // reference:
                        //for (int d = 0; d < D; d++) {
                        //    CellN[d] = Kref.FaceNormals[e, d];
                        //}
                        // ~~~~

                        // physical:
                        var FaceNodes   = new NodeSet(Kref, cR.Nodes.ExtractSubArrayShallow(new int[] { iNode, 0 }, new int[] { iNode + NodesPerEdge[e] - 1, D - 1 }));
                        var FaceNormals = MultidimensionalArray.Create(NodesPerEdge[e], D);
                        GridDat.Edges.GetNormalsForCell(FaceNodes, i0, e, FaceNormals);
                        // ~~~~

                        for (int _n = 0; _n < NodesPerEdge[e]; _n++)       // loop over nodes in one edge
                        {
                            for (int d = 0; d < D; d++)
                            {
                                SurfN[d] = LSNormals[i, iNode, d];
                                CellN[d] = FaceNormals[_n, d];     // physical
                            }
                            tangente(SurfN, CellN, OutwardTang);

                            for (int n = 0; n < N; n++)                                                     // loop over Test polynomials (the same as the basis polynomials)
                            {
                                for (int d = 0; d < D; d++)                                                 // loop over spatial direction
                                {
                                    EvalResult[i, iNode, d, n] = BasisValues[i, iNode, n] * OutwardTang[d]; // physical
                                    //EvalResult[i, iNode, d, n] = BasisValues[iNode, n]*OutwardTang[d]; // reference
                                }
                            }

                            iNode++;
                        }
                    }
                    Debug.Assert(iNode == EvalResult.GetLength(1));
                }
            },
                                                                                delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults
                for (int i = 0; i < Length; i++)
                {
                    var ResPart   = RHS.ExtractSubArrayShallow(new int[] { 0, 0, jSgrd }, new int[] { D - 1, N - 1, jSgrd - 1 });
                    int NoOfFaces = ResultsOfIntegration.GetLength(1);

                    for (int e = 0; e < NoOfFaces; e++)
                    {
                        var ip = ResultsOfIntegration.ExtractSubArrayShallow(new int[] { i, e, 0, 0 }, new int[] { i - 1, e - 1, D - 1, N - 1 });
                        ResPart.Acc(1.0, ip);
                    }
                    jSgrd++;
                }
            },
                                                                                cs : CoordinateSystem.Physical);

            qBnd.Execute();

            var ret = RHS.ResizeShallow(N * D, _mask.NoOfItemsLocally);

            return(ret);
        }
Exemplo n.º 7
0
        protected MultidimensionalArray GaußAnsatzRHS(DivergenceFreeBasis TestBasis, CellBoundaryQuadratureScheme cellBndScheme, CellMask _mask, int order)
        {
            var _Context = this.tracker.GridDat;
            int D        = this.tracker.GridDat.Grid.SpatialDimension;
            int N        = TestBasis.Count;
            var coordSys = CoordinateSystem.Reference;
            var LsTrk    = this.tracker;
            int Nrhs     = _mask.NoOfItemsLocally;

            Debug.Assert(N % D == 0);
            N /= D;
            MultidimensionalArray RHS = MultidimensionalArray.Create(N, Nrhs);

            var splx      = this.Kref;
            int NoOfFaces = splx.NoOfFaces;
            //var normals = _Context.GridDat.Normals;
            CellBoundaryQuadrature <CellBoundaryQuadRule> qBnd = null;

            int jSgrd = 0;

            qBnd = CellBoundaryQuadrature <CellBoundaryQuadRule> .GetQuadrature(new int[] { N },
                                                                                _Context, cellBndScheme.Compile(_Context, order),
                                                                                delegate(int i0, int Length, CellBoundaryQuadRule QR, MultidimensionalArray EvalResult) { // Evaluate
                NodeSet Nodes = QR.Nodes;
                MultidimensionalArray BasisValues;
                if (coordSys == CoordinateSystem.Physical)
                {
                    //BasisValues = TestBasis.CellEval(Nodes, i0, Length);
                    throw new NotImplementedException("todo");
                }
                else if (coordSys == CoordinateSystem.Reference)
                {
                    BasisValues = TestBasis.Values.GetValues(Nodes);
                }
                else
                {
                    throw new NotImplementedException();
                }

                for (int i = 0; i < Length; i++)       // loop over cells

                {
                    CellBoundaryQuadRule cR = qBnd.CurrentRule;
                    int[] NodesPerEdge      = cR.NumbersOfNodesPerFace;
                    Debug.Assert(object.ReferenceEquals(splx, cR.RefElement));

                    int iNode = 0;

                    Debug.Assert(NoOfFaces == NodesPerEdge.Length);
                    for (int e = 0; e < NoOfFaces; e++)              // loop over the faces of the cell
                    {
                        for (int _n = 0; _n < NodesPerEdge[e]; _n++) // loop over nodes in one edge
                        {
                            for (int n = 0; n < N; n++)              // loop over Test polynomials (the same as the basis polynomials)
                            {
                                double acc = 0;
                                for (int d = 0; d < D; d++)       // loop over spatial directions

                                {
                                    if (coordSys == CoordinateSystem.Physical)
                                    {
                                        throw new NotImplementedException("todo");
                                        //int q = _Context.GridDat.LocalCellIndexToEdges[i+i0, e];
                                        //int iEdge = Math.Abs(q) - 1;
                                        //double Nsign = Math.Sign(q);
                                        //double Nd = normals[iEdge, d];
                                        //EvalResult[i, iNode, n, d] = BasisValues[i, iNode, n]*Nd*Nsign;
                                    }
                                    else
                                    {
                                        Debug.Assert(coordSys == CoordinateSystem.Reference);
                                        double Nd = splx.FaceNormals[e, d];
                                        //Debug.Assert(Nd == normals[iEdge, d]*Nsign);
                                        acc += BasisValues[iNode, n *D + d] * Nd;
                                    }
                                }
                                EvalResult[i, iNode, n] = acc;
                            }

                            iNode++;
                        }
                    }
                    Debug.Assert(iNode == EvalResult.GetLength(1));
                }
            },
                                                                                delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults
                for (int i = 0; i < Length; i++)
                {
                    var ResPart = RHS.ExtractSubArrayShallow(new int[] { 0, jSgrd }, new int[] { N - 1, jSgrd - 1 });

                    for (int e = 0; e < NoOfFaces; e++)
                    {
                        var ip = ResultsOfIntegration.ExtractSubArrayShallow(new int[] { i, e, 0 }, new int[] { i - 1, e - 1, N - 1 });
                        ResPart.Acc(1.0, ip);
                    }
                    jSgrd++;
                }
            },
                                                                                cs : coordSys);

            qBnd.Execute();


            return(RHS);
        }
Exemplo n.º 8
0
        /// <summary>
        /// computes derivatives in various ways and compares them against known values.
        /// </summary>
        protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt)
        {
            base.EndTime       = 0.0;
            base.NoOfTimesteps = 0;

            int D = this.GridData.SpatialDimension;
            int J = this.GridData.iLogicalCells.NoOfLocalUpdatedCells;

            Console.WriteLine("DerivativeTest.exe, test case #" + GRID_CASE + " ******************************");

            //var Fix = this.GridData.iGeomEdges.FaceIndices;
            //for(int iEdge = 0; iEdge < Fix.GetLength(0); iEdge++) {
            //    Debug.Assert(Fix[iEdge, 0] >= 0);
            //    Debug.Assert(Fix[iEdge, 1] >= 0);
            //}

            // sealing test
            // =================

            if (this.GridData is Foundation.Grid.Classic.GridData)
            {
                TestSealing(this.GridData);
            }

            // cell volume and edge area check, if possible
            // ===============================================


            if (this.CellVolume > 0)
            {
                double err      = 0;
                double Treshold = 1.0e-10;


                for (int j = 0; j < J; j++)
                {
                    err += Math.Abs(this.GridData.iLogicalCells.GetCellVolume(j) - this.CellVolume);
                }

                bool passed = (err < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine("Cell volume error: " + err + " passed? " + passed);
                Console.WriteLine("--------------------------------------------");
            }

            if (this.EdgeArea > 0)
            {
                double err      = 0;
                double Treshold = 1.0e-10;

                int E = this.GridData.iLogicalEdges.Count;

                for (int e = 0; e < E; e++)
                {
                    err += Math.Abs(this.GridData.iLogicalEdges.GetEdgeArea(e) - this.EdgeArea);
                }

                bool passed = (err < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine("Edge area error: " + err + " passed? " + passed);
                Console.WriteLine("--------------------------------------------");
            }

            // Orthonormality of basis in physical coords
            // ==========================================

            {
                Basis Bs      = this.f1.Basis;
                int   N       = Bs.Length;
                int   degQuad = this.GridData.iLogicalCells.GetInterpolationDegree(0) * D + Bs.Degree + 3;
                int[] jG2jL   = this.GridData.iGeomCells.GeomCell2LogicalCell;


                // mass matrix: should be identity!
                MultidimensionalArray MassMatrix = MultidimensionalArray.Create(J, N, N);

                // compute mass matrix by quadrature.
                var quad = CellQuadrature.GetQuadrature(new int[] { N, N }, base.GridData,
                                                        (new CellQuadratureScheme()).Compile(base.GridData, degQuad),
                                                        delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                    NodeSet QuadNodes = QR.Nodes;
                    MultidimensionalArray BasisVals = Bs.CellEval(QuadNodes, i0, Length);
                    EvalResult.Multiply(1.0, BasisVals, BasisVals, 0.0, "jknm", "jkn", "jkm");
                },
                                                        delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                    if (jG2jL != null)
                    {
                        for (int i = 0; i < Length; i++)
                        {
                            int jG = i + i0;
                            MassMatrix.ExtractSubArrayShallow(jG2jL[jG], -1, -1)
                            .Acc(1.0, ResultsOfIntegration.ExtractSubArrayShallow(i, -1, -1));
                        }
                    }
                    else
                    {
                        MassMatrix.SetSubArray(ResultsOfIntegration, new int[] { i0, 0, 0 }, new int[] { i0 + Length - 1, N - 1, N - 1 });
                    }
                },
                                                        cs: CoordinateSystem.Physical);
                quad.Execute();

                // check that mass matrix is Id.
                int    MaxErrorCell = -1;
                double MaxError     = -1;
                for (int j = 0; j < J; j++)
                {
                    MultidimensionalArray MassMatrix_j = MassMatrix.ExtractSubArrayShallow(j, -1, -1);
                    MassMatrix_j.AccEye(-1.0);

                    double Norm_j = MassMatrix_j.InfNorm();
                    if (Norm_j > MaxError)
                    {
                        MaxError     = Norm_j;
                        MaxErrorCell = j;
                    }
                }

                bool passed = (MaxError < 1.0e-8);
                m_passed = m_passed && passed;
                Console.WriteLine("Mass Matrix, maximum error in Cell #" + MaxErrorCell + ", mass matrix error norm: " + MaxError + " passed? " + passed);
            }

            // Broken Derivatives
            // =================

            double totalVolume = (new SubGrid(CellMask.GetFullMask(this.GridData))).Volume;

            for (int d = 0; d < D; d++)
            {
                // compute
                f1Gradient_Numerical[d].Clear();
                f1Gradient_Numerical[d].Derivative(1.0, f1, d);
                f2Gradient_Numerical[d].Clear();
                f2Gradient_Numerical[d].Derivative(1.0, f2, d);

                // subtract analytical
                var Errfield1 = f1Gradient_Numerical[d].CloneAs();
                Errfield1.Acc(-1, f1Gradient_Analytical[d]);

                var Errfield2 = f2Gradient_Numerical[d].CloneAs();
                Errfield2.Acc(-1, f2Gradient_Analytical[d]);

                Console.WriteLine("Broken Derivatives: ");

                double Treshold = 1.0e-10;
                if (AltRefSol)
                {
                    Treshold = 1.0e-4; // not exactly polynomial, therefore a higher threshold
                }
                double err1_dx = Errfield1.L2Norm() / totalVolume;
                bool   passed  = (err1_dx < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| df1/dx{0}_Numerical - df1/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err1_dx, passed));

                double err2_dx = Errfield2.L2Norm() / totalVolume;
                passed   = (err2_dx < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| df2/dx{0}_Numerical - df2/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err2_dx, passed));

                Console.WriteLine("--------------------------------------------");
            }

            // Flux Derivatives
            // =================
            for (int d = 0; d < D; d++)
            {
                // compute
                f1Gradient_Numerical[d].Clear();
                f1Gradient_Numerical[d].DerivativeByFlux(1.0, f1, d);
                f2Gradient_Numerical[d].Clear();
                f2Gradient_Numerical[d].DerivativeByFlux(1.0, f2, d);

                f1Gradient_Numerical[d].CheckForNanOrInf(true, true, true);
                f2Gradient_Numerical[d].CheckForNanOrInf(true, true, true);

                // subtract analytical
                var Errfield1 = f1Gradient_Numerical[d].CloneAs();
                Errfield1.Acc(-1, f1Gradient_Analytical[d]);

                var Errfield2 = f2Gradient_Numerical[d].CloneAs();
                Errfield2.Acc(-1, f2Gradient_Analytical[d]);

                Console.WriteLine("Flux Derivatives: ");

                double Treshold = 1.0e-10;
                if (AltRefSol)
                {
                    Treshold = 1.0e-4; // not exactly polynomial, therefore a higher threshold
                }
                double err1_dx = Errfield1.L2Norm() / totalVolume;
                bool   passed  = (err1_dx < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| df1/dx{0}_Numerical - df1/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err1_dx, passed));

                double err2_dx = Errfield2.L2Norm() / totalVolume;
                passed   = (err2_dx < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| df2/dx{0}_Numerical - df2/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err2_dx, passed));

                Console.WriteLine("--------------------------------------------");
            }


            // Linear flux Derivatives
            // =======================
            for (int d = 0; d < D; d++)
            {
                double[] korrekto = f1Gradient_Numerical[d].CoordinateVector.ToArray();

                // compute
                DerivativeByFluxLinear(f1, f1Gradient_Numerical[d], d, f1);
                DerivativeByFluxLinear(f2, f2Gradient_Numerical[d], d, f2);

                // subtract analytical
                var Errfield1 = f1Gradient_Numerical[d].CloneAs();
                Errfield1.Acc(-1, f1Gradient_Analytical[d]);

                var Errfield2 = f2Gradient_Numerical[d].CloneAs();
                Errfield2.Acc(-1, f2Gradient_Analytical[d]);

                Console.WriteLine("Linear Flux Derivatives: ");

                double Treshold = 1.0e-10;
                if (AltRefSol)
                {
                    Treshold = 1.0e-4; // not exactly polynomial, therefore a higher threshold
                }
                double err1_dx = Errfield1.L2Norm() / totalVolume;
                bool   passed  = (err1_dx < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| df1/dx{0}_Numerical - df1/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err1_dx, passed));

                double err2_dx = Errfield2.L2Norm() / totalVolume;
                passed   = (err2_dx < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| df2/dx{0}_Numerical - df2/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err2_dx, passed));

                Console.WriteLine("--------------------------------------------");
            }

            // Laplacian, nonlinear
            // ====================

            if (!AltRefSol)
            {
                var Laplace = (new ipLaplace()).Operator(1);

                Laplace.Evaluate(new DGField[] { this.f1 }, new DGField[] { this.Laplace_f1_Numerical });
                Laplace.Evaluate(new DGField[] { this.f2 }, new DGField[] { this.Laplace_f2_Numerical });

                double Treshold = 1.0e-8;

                // subtract analytical
                var Errfield1 = Laplace_f1_Numerical.CloneAs();
                Errfield1.Acc(-1, Laplace_f1_Analytical);

                var Errfield2 = Laplace_f2_Numerical.CloneAs();
                Errfield2.Acc(-1, Laplace_f2_Analytical);

                double err_Lf1 = Errfield1.L2Norm() / totalVolume;
                bool   passed  = (err_Lf1 < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| /\\f1 Numerical - /\\f1 Analytical ||_2 = {0} (nonlinear evaluation), passed? {1}", err_Lf1, passed));

                double err_Lf2 = Errfield2.L2Norm() / totalVolume;
                passed   = (err_Lf2 < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| /\\f2 Numerical - /\\f2 Analytical ||_2 = {0} (nonlinear evaluation), passed? {1}", err_Lf2, passed));

                Console.WriteLine("--------------------------------------------");
            }


            // Laplacian, linear
            // ====================

            if (!AltRefSol)
            {
                var Laplace = (new ipLaplace()).Operator(1);

                var LaplaceMtx    = new BlockMsrMatrix(this.f1.Mapping, this.Laplace_f1_Numerical.Mapping);
                var LaplaceAffine = new double[LaplaceMtx.RowPartitioning.LocalLength];

                Laplace.ComputeMatrix(this.f1.Mapping, null, this.Laplace_f1_Numerical.Mapping,
                                      LaplaceMtx, LaplaceAffine, false);

                this.Laplace_f1_Numerical.CoordinateVector.SetV(LaplaceAffine);
                LaplaceMtx.SpMV(1.0, this.f1.CoordinateVector, 1.0, this.Laplace_f1_Numerical.CoordinateVector);

                this.Laplace_f2_Numerical.CoordinateVector.SetV(LaplaceAffine);
                LaplaceMtx.SpMV(1.0, this.f2.CoordinateVector, 1.0, this.Laplace_f2_Numerical.CoordinateVector);

                // subtract analytical
                var Errfield1 = Laplace_f1_Numerical.CloneAs();
                Errfield1.Acc(-1, Laplace_f1_Analytical);

                var Errfield2 = Laplace_f2_Numerical.CloneAs();
                Errfield2.Acc(-1, Laplace_f2_Analytical);


                double Treshold = 1.0e-8;

                double err_Lf1 = Errfield1.L2Norm() / totalVolume;
                bool   passed  = (err_Lf1 < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| /\\f1 Numerical - /\\f1 Analytical ||_2 = {0} (linear evaluation), passed? {1}", err_Lf1, passed));

                double err_Lf2 = Errfield2.L2Norm() / totalVolume;
                passed   = (err_Lf2 < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| /\\f2 Numerical - /\\f2 Analytical ||_2 = {0} (linear evaluation), passed? {1}", err_Lf2, passed));


                // comparison of finite difference Jacobian and Operator matrix
                if (TestFDJacobian)
                {
                    this.f1.Clear();
                    var FDJbuilder = Laplace.GetFDJacobianBuilder(this.f1.Mapping.Fields, null, this.f1.Mapping,
                                                                  delegate(IEnumerable <DGField> U0, IEnumerable <DGField> Params) {
                        return;
                    });
                    var CheckMatrix = new BlockMsrMatrix(FDJbuilder.CodomainMapping, FDJbuilder.DomainMapping);
                    var CheckAffine = new double[FDJbuilder.CodomainMapping.LocalLength];
                    FDJbuilder.ComputeMatrix(CheckMatrix, CheckAffine);

                    var ErrMatrix = LaplaceMtx.CloneAs();
                    var ErrAffine = LaplaceAffine.CloneAs();
                    ErrMatrix.Acc(-1.0, CheckMatrix);
                    ErrAffine.AccV(-1.0, CheckAffine);
                    double LinfMtx = ErrMatrix.InfNorm();
                    double L2Aff   = ErrAffine.L2NormPow2().MPISum().Sqrt();
                    bool   passed1 = (LinfMtx < 1.0e-3);
                    bool   passed2 = (L2Aff < Treshold);
                    Console.WriteLine("Finite Difference Jacobian: Matrix/Affine delta norm {0} {1}, passed? {2} {3}", LinfMtx, L2Aff, passed1, passed2);
                    m_passed = m_passed && passed1;
                    m_passed = m_passed && passed2;
                }
                Console.WriteLine("--------------------------------------------");
            }



            // finally...
            // =================

            if (m_passed)
            {
                Console.WriteLine("All tests passed. *****************************");
            }
            else
            {
                Console.WriteLine("Some error above threshold. *******************");
            }

            return(0.0); // return some artificial timestep
        }
Exemplo n.º 9
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);
            //    }
            //}
        }
Exemplo 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);
                    }
                }
            }
        }
Exemplo n.º 11
0
        static internal void ComputeMassMatrixBlocks(
            IEnumerable <SpeciesId> _SpeciesIds,
            out Dictionary <SpeciesId, MassMatrixBlockContainer> Result,
            Basis b,
            XDGSpaceMetrics homie)
        {
            using (var tracer = new FuncTrace()) {
                if (b is XDGBasis)
                {
                    throw new ArgumentException();
                }
                var ctx = homie.GridDat;

                Result = new Dictionary <SpeciesId, MassMatrixBlockContainer>();
                var schemeHelper = homie.XQuadSchemeHelper;
                int Nnx          = b.Length;

                int quadorder = homie.CutCellQuadOrder;


                // define domains and allocate memory
                // ==================================


                foreach (var Species in _SpeciesIds)   // loop over species...

                // interation dom
                {
                    var _IntegrationDomain = homie.LevelSetRegions.GetSpeciesMask(Species).Intersect(homie.LevelSetRegions.GetCutCellMask());

                    // domain for mass-matrix blocks (include agglomeration targets)
                    var _BlockDomain = _IntegrationDomain; //.Union(Agg.GetAgglomerator(Species).AggInfo.AllAffectedCells);

                    // alloc mem for blocks
                    var _MassMatrixBlocksSpc = MultidimensionalArray.Create(_BlockDomain.NoOfItemsLocally, Nnx, Nnx);

                    // Subgrid index to cell index
                    int[] _jSub2jCell = _BlockDomain.ItemEnum.ToArray();

                    // cell to subgrid index
                    //Dictionary<int, int> _jCell2jSub;
                    //if (Agg.GetAgglomerator(Species).AggInfo.AgglomerationPairs.Length > 0) {
                    //    _jCell2jSub = new Dictionary<int, int>();
                    //    for (int i = 0; i < _jSub2jCell.Length; i++) {
                    //        _jCell2jSub.Add(_jSub2jCell[i], i);
                    //    }
                    //} else {
                    //    _jCell2jSub = null;
                    //}

                    Result.Add(Species, new MassMatrixBlockContainer()
                    {
                        IntegrationDomain = _IntegrationDomain,
                        MassMatrixBlocks  = _MassMatrixBlocksSpc,
                        //jCell2jSub = _jCell2jSub,
                        jSub2jCell = _jSub2jCell
                    });
                }

                // compute blocks
                // ==============

                foreach (var Species in _SpeciesIds)
                {
                    // get quad scheme
                    CellQuadratureScheme scheme = schemeHelper.GetVolumeQuadScheme(Species, IntegrationDomain: Result[Species].IntegrationDomain);

                    // result storage
                    var MassMatrixBlocksSpc = Result[Species].MassMatrixBlocks;

                    tracer.Info("mass matrix quad order: " + quadorder);

                    // compute the products of the basis functions:
                    int      BlockCnt     = -1;
                    int[]    BlockCell    = Result[Species].jSub2jCell;
                    CellMask speciesCells = homie.LevelSetRegions.GetSpeciesMask(Species);
                    CellQuadrature.GetQuadrature(
                        new int[] { Nnx, Nnx },
                        ctx,
                        scheme.Compile(ctx, quadorder),
                        delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                        // Del_Evaluate
                        // ~~~~~~~~~~~~~
                        var BasisVal = b.CellEval(QR.Nodes, i0, Length);
                        EvalResult.Multiply(1.0, BasisVal, BasisVal, 0.0, "ikmn", "ikm", "ikn");
                    },
                        delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                        // Del_SaveIntegrationResults
                        // ~~~~~~~~~~~~~~~~~~~~~~~~~~

                        for (int i = 0; i < Length; i++)
                        {
                            int jCell = i0 + i;
                            BlockCnt++;

                            // insert ID block in agglomeration target cells (if necessary):
                            // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                            var Block = MassMatrixBlocksSpc.ExtractSubArrayShallow(BlockCnt, -1, -1);
                            while (BlockCell[BlockCnt] < jCell)
                            {
                                // agglomeration source/target cell that is not cut
                                // mass matrix is identity (full) or zero (void)
                                Block.Clear();
                                if (speciesCells.Contains(BlockCell[BlockCnt]))
                                {
                                    // cell is full
                                    for (int nn = 0; nn < Nnx; nn++)
                                    {
                                        Block[nn, nn] = 1.0;
                                    }
                                }
                                BlockCnt++;
                                Block = MassMatrixBlocksSpc.ExtractSubArrayShallow(BlockCnt, -1, -1);
                            }

                            // store computed block
                            // - - - - - - - - - - -
                            Debug.Assert(BlockCell[BlockCnt] == jCell);
                            MassMatrixBlocksSpc.ExtractSubArrayShallow(BlockCnt, -1, -1)
                            .Set(ResultsOfIntegration.ExtractSubArrayShallow(i, -1, -1));
#if DEBUG
                            for (int n = 0; n < Nnx; n++)
                            {
                                for (int m = 0; m < Nnx; m++)
                                {
                                    Debug.Assert(Block[n, m] == Block[m, n]);
                                }
                            }
#endif
                        }
                    }).Execute();
                    // ------------------------------------ quadrature end.

                    BlockCnt++;
                    while (BlockCnt < MassMatrixBlocksSpc.GetLength(0))
                    {
                        // agglomeration source/target cell that is not cut
                        // mass matrix is identity (full) or zero (void)
                        var Block = MassMatrixBlocksSpc.ExtractSubArrayShallow(BlockCnt, -1, -1);
                        Block.Clear();
                        if (speciesCells.Contains(BlockCell[BlockCnt]))
                        {
                            // cell is full
                            for (int nn = 0; nn < Nnx; nn++)
                            {
                                Block[nn, nn] = 1.0;
                            }
                        }
                        BlockCnt++;
                    }


                    /*
                     * // test mass matrix for positive definiteness
                     * {
                     *  int JSUB = MassMatrixBlocksSpc.GetLength(0);
                     *  SubGrid Idom = null;
                     *
                     *  int failCount = 0;
                     *  var PosDefiniteTest = new FullMatrix(Nnx, Nnx);
                     *
                     *  for (int jsub = 0; jsub < JSUB; jsub++) {
                     *      PosDefiniteTest.Clear();
                     *      PosDefiniteTest.Acc(MassMatrixBlocksSpc.ExtractSubArrayShallow(jsub, -1, -1), 1.0);
                     *
                     *      try {
                     *          PosDefiniteTest.Clear();
                     *          PosDefiniteTest.Acc(MassMatrixBlocksSpc.ExtractSubArrayShallow(jsub, -1, -1), 1.0);
                     *          PosDefiniteTest.InvertSymmetrical();
                     *
                     *          //PosDefiniteTest.Clear();
                     *          //PosDefiniteTest.AccEye(1.0);
                     *          //PosDefiniteTest.Acc(MassMatrixBlocksSpc.ExtractSubArrayShallow(jsub, -1, -1), -1.0);
                     *          //PosDefiniteTest.InvertSymmetrical();
                     *      } catch (ArithmeticException ae) {
                     *          if (Idom == null)
                     *              Idom = new SubGrid(scheme.Domain);
                     *
                     *          int jCell = Idom.SubgridIndex2LocalCellIndex[jsub];
                     *          long Gid = Tracker.GridDat.Cells.GetCell(jCell).GlobalID;
                     *
                     *
                     *          double volFrac = Tracker.GetSpeciesVolume(jCell, Species)/ctx.Cells.GetCellVolume(jCell);
                     *
                     *          var errString = string.Format("Indefinite mass matrix in cell: globalId = {0}, local index = {1}, species {2}; \n   cell volume fraction: {3};\n   [{4}]", Gid, jCell, Tracker.GetSpeciesName(Species), volFrac, ae.Message);
                     *          tracer.Logger.Error(errString);
                     *          //Console.WriteLine(errString);
                     *          failCount++;
                     *      }
                     *  }
                     *
                     *  if (failCount > 0) {
                     *      var errString = string.Format("Indefinite mass matrix in {0} of {1} cut cells", failCount, JSUB);
                     *      tracer.Logger.Error(errString);
                     *      Console.WriteLine(errString);
                     *  } else {
                     *      Console.WriteLine("No indefinite mass matrix blocks");
                     *  }
                     *
                     * }
                     * // */

                    // backup before agglomeration (required if we wanna treat e.g. velocity in DG and pressure in XDG)
                    //MultidimensionalArray[] massMatrixBlocksB4Agglom = new MultidimensionalArray[Result[Species].jSub2jCell.Length];
                    //Result[Species].MassMatrixBlocks_B4Agglom = massMatrixBlocksB4Agglom;
                    //var _jCell2jSub = Result[Species].jCell2jSub;
                    //int J = ctx.Cells.NoOfLocalUpdatedCells;
                    //foreach (var pair in Agg.GetAgglomerator(Species).AggInfo.AgglomerationPairs) {

                    //    foreach (int jCell in new int[] { pair.jCellSource, pair.jCellTarget }) { // create a backup of source and target cell
                    //        if (jCell >= J)
                    //            continue;

                    //        int jSub = _jCell2jSub[jCell];

                    //        if (massMatrixBlocksB4Agglom[jSub] == null) {
                    //            massMatrixBlocksB4Agglom[jSub] = MassMatrixBlocksSpc.ExtractSubArrayShallow(jSub, -1, -1).CloneAs();
                    //        }
                    //    }
                    //}

                    // agglomeration
                    //Agg.GetAgglomerator(Species).ManipulateMassMatrixBlocks(MassMatrixBlocksSpc, b, Result[Species].jSub2jCell, Result[Species].jCell2jSub);
                    //throw new NotImplementedException("todo");
                }
            }
        }