Example #1
0
        protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt)
        {
            dt = 1.0;
            base.NoOfTimesteps = 1;

            Console.WriteLine("Timestep #{0}, dt = {1} ...", TimestepNo, dt);

            // test the auto-extrapolation
            // ---------------------------

            double x0 = 0.17 * (phystime + dt);

            this.Pressure.UpdateBehaviour = BehaveUnder_LevSetMoovement.AutoExtrapolate;
            this.LevSet.ProjectField((_2D)((x, y) => ((x - 0.83 - x0) / 0.8).Pow2() + (y / 0.8).Pow2() - 1.0));
            this.LsTrk.UpdateTracker();


            var RefPressure = new XDGField(this.Pressure.Basis);

            RefPressure.ProjectField((_2D)((x, y) => 1 - y * y));
            RefPressure.Acc(-1.0, Pressure);

            AutoExtrapolationErr = RefPressure.L2Norm();
            Console.WriteLine("Error of extrapolation: " + AutoExtrapolationErr);



            // PlotCurrentState(phystime + dt, TimestepNo);


            Console.WriteLine("done.");

            return(dt);
        }
Example #2
0
        protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt)
        {
            dt = Control.dtFixed;


            Console.WriteLine("Timestep #{0}, dt = {1} ...", TimestepNo, dt);

            // advance level-set
            // -----------------

            double x0 = 0.17 * (phystime + dt);

            this.Pressure.UpdateBehaviour = BehaveUnder_LevSetMoovement.AutoExtrapolate;
            this.LevSet.ProjectField((_2D)((x, y) => Phi(new[] { x, y }, x0)));
            this.LsTrk.PushStacks();
            this.LsTrk.UpdateTracker(phystime + dt);


            // update markers
            // --------------
            this.Amarker.Clear();
            this.Bmarker.Clear();
            this.Amarker.AccConstant(1.0, this.LsTrk.Regions.GetSpeciesMask("A"));
            this.Bmarker.AccConstant(1.0, this.LsTrk.Regions.GetSpeciesMask("B"));

            // test the auto-extrapolation
            // ---------------------------

            var RefPressure = new XDGField(this.Pressure.Basis);

            RefPressure.GetSpeciesShadowField("A").ProjectField(PressureExactA);
            RefPressure.GetSpeciesShadowField("B").ProjectField(PressureExactB);
            RefPressure.Acc(-1.0, Pressure);

            AutoExtrapolationErr = RefPressure.L2Norm();
            Console.WriteLine("Error of extrapolation: " + AutoExtrapolationErr);
            Assert.LessOrEqual(AutoExtrapolationErr, 1.0e-8, "Error after auto-extrapolation to high.");


            Console.WriteLine("done.");

            return(dt);
        }
Example #3
0
        public static void XDG_MatrixPolynomialRestAndPrlgTest(
            [Values(0, 1, 2, 3)] int p,
            [Values(0.0, 0.3)] double AggregationThreshold,
            [Values(0, 1)] int TrackerWidth)
        {
            XQuadFactoryHelper.MomentFittingVariants variant = XQuadFactoryHelper.MomentFittingVariants.OneStepGaussAndStokes;
            var xt = new XDGTestSetup(p, AggregationThreshold, TrackerWidth, MultigridOperator.Mode.Eye, variant);


            // test matrix version of the restriction operator
            // -----------------------------------------------

            List <MultigridMapping> MultigridMaps = new List <MultigridMapping>();

            for (var mgop = xt.XdgMultigridOp; mgop != null; mgop = mgop.CoarserLevel)
            {
                MultigridMaps.Add(mgop.Mapping);
            }

            for (int iLevel = 0; iLevel < MgSeq.Length; iLevel++)
            {
                MultigridMapping mgMap = MultigridMaps[iLevel];
                var XAggBasis          = mgMap.AggBasis[0];

                // set the test field:
                XDGField Test = new XDGField(xt.XB, "Test");
                Random   rand = new Random();
                for (int i = 0; i < Test.CoordinateVector.Count; i++)
                {
                    Test.CoordinateVector[i] = rand.NextDouble();
                }
                xt.agg.ClearAgglomerated(Test.CoordinateVector, Test.Mapping);

                // do restriction/prolongation (Reference)
                double[] RestVecRef = new double[XAggBasis.LocalDim];
                XAggBasis.RestictFromFullGrid(Test.CoordinateVector, RestVecRef);

                // and now with the matrix:
                BlockMsrMatrix RestMtx = new BlockMsrMatrix(mgMap, mgMap.ProblemMapping);
                XAggBasis.GetRestrictionMatrix(RestMtx, mgMap, 0);
                double[] RestVec = new double[mgMap.LocalLength];
                RestMtx.SpMV(1.0, Test.CoordinateVector, 0.0, RestVec);

                double[] X1 = new double[xt.XdgMultigridOp.Mapping.LocalLength];
                XDGField X2 = new XDGField(Test.Basis);
                xt.XdgMultigridOp.TransformSolInto(Test.CoordinateVector, X1);
                xt.XdgMultigridOp.TransformSolFrom(X2.CoordinateVector, X1);
                //xt.agg.Extrapolate(X2.CoordinatesAsVector, X2.Mapping);
                var ERR2 = Test.CloneAs();
                ERR2.Acc(-1.0, X2);
                double ERR2Norm = ERR2.L2Norm();
                //Console.WriteLine("MultigridOperator TranformInto/FransformFrom mismatch: " + ERR2Norm);
                Assert.LessOrEqual(ERR2Norm, 1.0e-8);

                // compare
                double ERR  = 0.0;
                int    Nmax = XAggBasis.MaximalLength;
                for (int jAgg = 0; jAgg < mgMap.AggGrid.iLogicalCells.NoOfLocalUpdatedCells; jAgg++)
                {
                    int i0Ref = jAgg * Nmax;
                    int i0Tst = mgMap.LocalUniqueIndex(0, jAgg, 0);
                    int N     = mgMap.GetLength(jAgg);

                    for (int n = 0; n < N; n++)
                    {
                        double dist = RestVecRef[i0Ref + n] - RestVec[i0Tst + n];
                        ERR += dist.Pow2();
                    }
                }
                Console.WriteLine("Restriction matrix test (iLevel = {0}): {1}", iLevel, ERR);
                Assert.LessOrEqual(ERR, 1.0e-8);

                //
                double[] PrlgVecA = new double[XAggBasis.LocalDim];
                double[] PrlgVecB = new double[mgMap.LocalLength];
                for (int jAgg = 0; jAgg < mgMap.AggGrid.iLogicalCells.NoOfLocalUpdatedCells; jAgg++)
                {
                    int i0Ref = jAgg * Nmax;
                    int i0Tst = mgMap.LocalUniqueIndex(0, jAgg, 0);
                    int N     = mgMap.GetLength(jAgg);

                    for (int n = 0; n < N; n++)
                    {
                        double rndVal = rand.NextDouble();
                        PrlgVecA[i0Ref + n] = rndVal;
                        PrlgVecB[i0Tst + n] = rndVal;
                    }
                }

                XDGField QA = new XDGField(Test.Basis);
                XDGField QB = new XDGField(Test.Basis);

                XAggBasis.ProlongateToFullGrid(QA.CoordinateVector, PrlgVecA);
                var PrlgMtx = RestMtx.Transpose();
                PrlgMtx.SpMV(1.0, PrlgVecB, 0.0, QB.CoordinateVector);

                XDGField ERR5 = QA.CloneAs();
                ERR5.Acc(-1.0, QB);
                double ERR5_Norm = ERR5.L2Norm();
                Console.WriteLine("Prolongation matrix test (iLevel = {0}): {1}", iLevel, ERR5_Norm);
                Assert.LessOrEqual(ERR5_Norm, 1.0e-8);
            }
        }
Example #4
0
        public static void XDG_MatrixPolynomialRestAndPrlgTest_2(
            [Values(0, 1, 2, 3)] int p,
            [Values(0.0, 0.3)] double AggregationThreshold,
            [Values(0, 1)] int TrackerWidth,
            [Values(MultigridOperator.Mode.Eye, MultigridOperator.Mode.IdMass)] MultigridOperator.Mode mode)
        {
            if (AggregationThreshold < 0.1 && p >= 3 && mode == MultigridOperator.Mode.IdMass)
            {
                // this test combination is not supposed to work:
                // without agglomeration, for high p, the mass matrix may be indefinite in small cut-cells
                // => Cholesky decomposition on mass matrix fails, i.e. 'mode == IdMass' cannot succseed.
                return;
            }


            XQuadFactoryHelper.MomentFittingVariants variant = XQuadFactoryHelper.MomentFittingVariants.OneStepGaussAndStokes;
            var xt = new XDGTestSetup(p, AggregationThreshold, TrackerWidth, mode, variant);


            // Restriction & prolongation together with orthonormalization
            // -----------------------------------------------------------


            for (var mgop = xt.MultigridOp; mgop != null; mgop = mgop.CoarserLevel)
            {
                var Itself = mgop.Mapping.FromOtherLevelMatrix(mgop.Mapping);
                Itself.AccEyeSp(-1.0);
                double Itslef_Norm = Itself.InfNorm();
                //Console.WriteLine("Level {0}, Restriction onto itself {1}", mgm.LevelIndex, Itslef_Norm);
                Assert.LessOrEqual(Itslef_Norm, 1.0e-8);
            }

            {
                // test change of basis on top level

                XDGField uTestRnd = new XDGField(xt.XB);
                Random   rnd      = new Random();
                for (int i = 0; i < uTestRnd.CoordinateVector.Count; i++)
                {
                    uTestRnd.CoordinateVector[i] = rnd.NextDouble();
                }
                xt.agg.ClearAgglomerated(uTestRnd.CoordinateVector, uTestRnd.Mapping);

                // perform change of basis on top level ...
                int      Ltop       = xt.MultigridOp.Mapping.LocalLength;
                double[] uTest_Fine = new double[Ltop];
                xt.MultigridOp.TransformSolInto(uTestRnd.CoordinateVector, uTest_Fine);

                // .. and back
                XDGField uError2 = uTestRnd.CloneAs();
                uError2.Clear();
                xt.MultigridOp.TransformSolFrom(uError2.CoordinateVector, uTest_Fine);

                // compare:
                uError2.Acc(-1.0, uTestRnd);
                double NORM_uError = uError2.L2Norm();

                // output
                Console.WriteLine("Top level change of basis error: {0}", NORM_uError);
                Assert.LessOrEqual(NORM_uError, 1.0e-8);
            }

            {
                // perform change of basis on top level
                int      Ltop       = xt.MultigridOp.Mapping.LocalLength;
                double[] uTest_Fine = new double[Ltop];
                xt.MultigridOp.TransformSolInto(xt.uTest.CoordinateVector, uTest_Fine);


                // check for each level of the multigrid operator...
                for (int iLevel = 0; iLevel < MgSeq.Count() - 1; iLevel++)
                {
                    double[] uTest_Prolonged = new double[Ltop];

                    XDG_Recursive(0, iLevel, xt.MultigridOp, uTest_Fine, uTest_Prolonged);

                    XDGField uError = xt.uTest.CloneAs();
                    uError.Clear();
                    xt.MultigridOp.TransformSolFrom(uError.CoordinateVector, uTest_Prolonged);
                    xt.agg.Extrapolate(uError.Mapping);

                    uError.Acc(-1.0, xt.uTest);
                    double NORM_uError = uError.L2Norm();

                    Console.WriteLine("Rest/Prlg error, level {0}: {1}", iLevel, NORM_uError);
                    Assert.LessOrEqual(NORM_uError, 1.0e-8);
                }
            }
        }
Example #5
0
        protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt)
        {
            Console.WriteLine("    Timestep # " + TimestepNo + ", phystime = " + phystime);

            //phystime = 1.8;
            LsUpdate(phystime);


            // operator-matrix assemblieren
            MsrMatrix OperatorMatrix = new MsrMatrix(u.Mapping, u.Mapping);

            double[] Affine = new double[OperatorMatrix.RowPartitioning.LocalLength];
            MultiphaseCellAgglomerator Agg;
            MassMatrixFactory          Mfact;

            // Agglomerator setup
            int quadOrder = Op.QuadOrderFunction(new int[] { u.Basis.Degree }, new int[0], new int[] { u.Basis.Degree });

            //Agg = new MultiphaseCellAgglomerator(new CutCellMetrics(MomentFittingVariant, quadOrder, LsTrk, ), this.THRESHOLD, false);
            Agg = LsTrk.GetAgglomerator(new SpeciesId[] { LsTrk.GetSpeciesId("B") }, quadOrder, this.THRESHOLD);

            Console.WriteLine("Inter-Process agglomeration? " + Agg.GetAgglomerator(LsTrk.GetSpeciesId("B")).AggInfo.InterProcessAgglomeration);
            if (this.THRESHOLD > 0.01)
            {
                TestAgglomeration_Extraploation(Agg);
                TestAgglomeration_Projection(quadOrder, Agg);
            }

            // operator matrix assembly
            Op.ComputeMatrixEx(LsTrk,
                               u.Mapping, null, u.Mapping,
                               OperatorMatrix, Affine, false, 0.0, true,
                               Agg.CellLengthScales,
                               LsTrk.GetSpeciesId("B"));
            Agg.ManipulateMatrixAndRHS(OperatorMatrix, Affine, u.Mapping, u.Mapping);

            // mass matrix factory
            Mfact = LsTrk.GetXDGSpaceMetrics(new SpeciesId[] { LsTrk.GetSpeciesId("B") }, quadOrder, 1).MassMatrixFactory;// new MassMatrixFactory(u.Basis, Agg);

            // Mass matrix/Inverse Mass matrix
            //var MassInv = Mfact.GetMassMatrix(u.Mapping, new double[] { 1.0 }, true, LsTrk.GetSpeciesId("B"));
            var Mass = Mfact.GetMassMatrix(u.Mapping, new double[] { 1.0 }, false, LsTrk.GetSpeciesId("B"));

            Agg.ManipulateMatrixAndRHS(Mass, default(double[]), u.Mapping, u.Mapping);
            var MassInv = Mass.InvertBlocks(OnlyDiagonal: true, Subblocks: true, ignoreEmptyBlocks: true, SymmetricalInversion: false);


            // test that operator depends only on B-species values
            double DepTest = LsTrk.Regions.GetSpeciesSubGrid("B").TestMatrixDependency(OperatorMatrix, u.Mapping, u.Mapping);

            Console.WriteLine("Matrix dependency test: " + DepTest);
            Assert.LessOrEqual(DepTest, 0.0);

            // diagnostic output
            Console.WriteLine("Number of Agglomerations (all species): " + Agg.TotalNumberOfAgglomerations);
            Console.WriteLine("Number of Agglomerations (species 'B'): " + Agg.GetAgglomerator(LsTrk.GetSpeciesId("B")).AggInfo.SourceCells.NoOfItemsLocally.MPISum());

            // operator auswerten:
            double[] x = new double[Affine.Length];
            BLAS.daxpy(x.Length, 1.0, Affine, 1, x, 1);
            OperatorMatrix.SpMVpara(1.0, u.CoordinateVector, 1.0, x);
            MassInv.SpMV(1.0, x, 0.0, du_dx.CoordinateVector);
            Agg.GetAgglomerator(LsTrk.GetSpeciesId("B")).Extrapolate(du_dx.Mapping);


            // markieren, wo ueberhaupt A und B sind
            Bmarker.AccConstant(1.0, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);
            Amarker.AccConstant(+1.0, LsTrk.Regions.GetSpeciesSubGrid("A").VolumeMask);
            Xmarker.AccConstant(+1.0, LsTrk.Regions.GetSpeciesSubGrid("X").VolumeMask);

            // compute error
            ERR.Clear();
            ERR.Acc(1.0, du_dx_Exact, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);
            ERR.Acc(-1.0, du_dx, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);
            double L2Err = ERR.L2Norm(LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);

            Console.WriteLine("L2 Error: " + L2Err);

            XERR.Clear();
            XERR.GetSpeciesShadowField("B").Acc(1.0, ERR, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);
            double xL2Err = XERR.L2Norm();

            Console.WriteLine("L2 Error (in XDG space): " + xL2Err);



            // check error
            if (this.THRESHOLD > 0.01)
            {
                // without agglomeration, the error in very tiny cut-cells may be large over the whole cell
                // However, the error in the XDG-space should be small under all circumstances
                Assert.LessOrEqual(L2Err, 1.0e-6);
            }
            Assert.LessOrEqual(xL2Err, 1.0e-6);

            bool IsPassed = ((L2Err <= 1.0e-6 || this.THRESHOLD <= 0.01) && xL2Err <= 1.0e-7);

            if (IsPassed)
            {
                Console.WriteLine("Test PASSED");
            }
            else
            {
                Console.WriteLine("Test FAILED: check errors.");
            }

            // return/Ende
            base.NoOfTimesteps = 17;
            //base.NoOfTimesteps = 2;
            dt = 0.3;
            return(dt);
        }
Example #6
0
        private void ExperimentalSolver(out double mintime, out double maxtime, out bool Converged, out int NoOfIter, out int DOFs)
        {
            using (var tr = new FuncTrace()) {
                mintime   = double.MaxValue;
                maxtime   = 0;
                Converged = false;
                NoOfIter  = int.MaxValue;
                DOFs      = 0;

                AggregationGridBasis[][] XAggB;
                using (new BlockTrace("Aggregation_basis_init", tr)) {
                    XAggB = AggregationGridBasis.CreateSequence(base.MultigridSequence, u.Mapping.BasisS);
                }
                XAggB.UpdateXdgAggregationBasis(this.Op_Agglomeration);

                var      MassMatrix = this.Op_mass.GetMassMatrix(this.u.Mapping, new double[] { 1.0 }, false, this.LsTrk.SpeciesIdS.ToArray());
                double[] _RHSvec    = this.GetRHS();



                Stopwatch stw = new Stopwatch();
                stw.Reset();
                stw.Start();

                Console.WriteLine("Setting up multigrid operator...");

                int p           = this.u.Basis.Degree;
                var MultigridOp = new MultigridOperator(XAggB, this.u.Mapping,
                                                        this.Op_Matrix,
                                                        this.Op_mass.GetMassMatrix(new UnsetteledCoordinateMapping(this.u.Basis), false),
                                                        OpConfig);
                Assert.True(MultigridOp != null);

                int L = MultigridOp.Mapping.LocalLength;
                DOFs = MultigridOp.Mapping.TotalLength;

                double[] RHSvec = new double[L];
                MultigridOp.TransformRhsInto(_RHSvec, RHSvec);


                ISolverSmootherTemplate exsolver;

                SolverFactory SF = new SolverFactory(this.Control.NonLinearSolver, this.Control.LinearSolver);
                List <Action <int, double[], double[], MultigridOperator> > Callbacks = new List <Action <int, double[], double[], MultigridOperator> >();
                Callbacks.Add(CustomItCallback);
                SF.GenerateLinear(out exsolver, MultigridSequence, OpConfig, Callbacks);



                using (new BlockTrace("Solver_Init", tr)) {
                    exsolver.Init(MultigridOp);
                }

                /*
                 * string filename = "XdgPoisson" + this.Grid.SpatialDimension + "p" + this.u.Basis.Degree + "R" + this.Grid.CellPartitioning.TotalLength;
                 * MultigridOp.OperatorMatrix.SaveToTextFileSparse(filename + ".txt");
                 * RHSvec.SaveToTextFile(filename + "_rhs.txt");
                 *
                 * var uEx = this.u.CloneAs();
                 * Op_Agglomeration.ClearAgglomerated(uEx.Mapping);
                 * var CO = new ConvergenceObserver(MultigridOp, MassMatrix, uEx.CoordinateVector.ToArray());
                 * uEx = null;
                 * CO.TecplotOut = "PoissonConvergence";
                 * //CO.PlotDecomposition(this.u.CoordinateVector.ToArray());
                 *
                 * if (exsolver is ISolverWithCallback) {
                 *  ((ISolverWithCallback)exsolver).IterationCallback = CO.IterationCallback;
                 * }
                 * //*/
                XDGField u2 = u.CloneAs();
                using (new BlockTrace("Solver_Run", tr)) {
                    // use solver (on XDG-field 'u2').
                    u2.Clear();
                    MultigridOp.UseSolver(exsolver, u2.CoordinateVector, _RHSvec);
                    Console.WriteLine("Solver: {0}, converged? {1}, {2} iterations.", exsolver.GetType().Name, exsolver.Converged, exsolver.ThisLevelIterations);
                    this.Op_Agglomeration.Extrapolate(u2.Mapping);
                    Assert.IsTrue(exsolver.Converged, "Iterative solver did not converge.");
                }
                stw.Stop();
                mintime   = Math.Min(stw.Elapsed.TotalSeconds, mintime);
                maxtime   = Math.Max(stw.Elapsed.TotalSeconds, maxtime);
                Converged = exsolver.Converged;
                NoOfIter  = exsolver.ThisLevelIterations;

                // compute error between reference solution and multigrid solver
                XDGField ErrField = u2.CloneAs();
                ErrField.Acc(-1.0, u);
                double ERR    = ErrField.L2Norm();
                double RelERR = ERR / u.L2Norm();
                Assert.LessOrEqual(RelERR, 1.0e-6, "Result from iterative solver above threshold.");
            }
        }
Example #7
0
        protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt)
        {
            Console.WriteLine("    Timestep # " + TimestepNo + ", phystime = " + phystime);

            //phystime = 1.8;
            LsUpdate(phystime);


            // operator-matrix assemblieren
            MsrMatrix OperatorMatrix = new MsrMatrix(u.Mapping, u.Mapping);

            double[] Affine = new double[OperatorMatrix.RowPartitioning.LocalLength];

            // Agglomerator setup
            MultiphaseCellAgglomerator Agg = LsTrk.GetAgglomerator(new SpeciesId[] { LsTrk.GetSpeciesId("B") }, QuadOrder, this.THRESHOLD);

            // plausibility of cell length scales
            if (SER_PAR_COMPARISON)
            {
                TestLengthScales(QuadOrder, TimestepNo);
            }

            Console.WriteLine("Inter-Process agglomeration? " + Agg.GetAgglomerator(LsTrk.GetSpeciesId("B")).AggInfo.InterProcessAgglomeration);
            if (this.THRESHOLD > 0.01)
            {
                TestAgglomeration_Extraploation(Agg);
                TestAgglomeration_Projection(QuadOrder, Agg);
            }
            CheckExchange(true);
            CheckExchange(false);

            // operator matrix assembly
            XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Op.GetMatrixBuilder(base.LsTrk, u.Mapping, null, u.Mapping);
            mtxBuilder.time = 0.0;
            mtxBuilder.ComputeMatrix(OperatorMatrix, Affine);
            Agg.ManipulateMatrixAndRHS(OperatorMatrix, Affine, u.Mapping, u.Mapping);

            // mass matrix factory
            var Mfact = LsTrk.GetXDGSpaceMetrics(new SpeciesId[] { LsTrk.GetSpeciesId("B") }, QuadOrder, 1).MassMatrixFactory;// new MassMatrixFactory(u.Basis, Agg);

            // Mass matrix/Inverse Mass matrix
            //var MassInv = Mfact.GetMassMatrix(u.Mapping, new double[] { 1.0 }, true, LsTrk.GetSpeciesId("B"));
            var Mass = Mfact.GetMassMatrix(u.Mapping, new double[] { 1.0 }, false, LsTrk.GetSpeciesId("B"));

            Agg.ManipulateMatrixAndRHS(Mass, default(double[]), u.Mapping, u.Mapping);
            var MassInv = Mass.InvertBlocks(OnlyDiagonal: true, Subblocks: true, ignoreEmptyBlocks: true, SymmetricalInversion: false);


            // test that operator depends only on B-species values
            double DepTest = LsTrk.Regions.GetSpeciesSubGrid("B").TestMatrixDependency(OperatorMatrix, u.Mapping, u.Mapping);

            Console.WriteLine("Matrix dependency test: " + DepTest);
            Assert.LessOrEqual(DepTest, 0.0);

            // diagnostic output
            Console.WriteLine("Number of Agglomerations (all species): " + Agg.TotalNumberOfAgglomerations);
            Console.WriteLine("Number of Agglomerations (species 'B'): " + Agg.GetAgglomerator(LsTrk.GetSpeciesId("B")).AggInfo.SourceCells.NoOfItemsLocally.MPISum());

            // operator auswerten:
            double[] x = new double[Affine.Length];
            BLAS.daxpy(x.Length, 1.0, Affine, 1, x, 1);
            OperatorMatrix.SpMVpara(1.0, u.CoordinateVector, 1.0, x);
            MassInv.SpMV(1.0, x, 0.0, du_dx.CoordinateVector);
            Agg.GetAgglomerator(LsTrk.GetSpeciesId("B")).Extrapolate(du_dx.Mapping);

            // markieren, wo ueberhaupt A und B sind
            Bmarker.AccConstant(1.0, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);
            Amarker.AccConstant(+1.0, LsTrk.Regions.GetSpeciesSubGrid("A").VolumeMask);
            if (usePhi0 && usePhi1)
            {
                Xmarker.AccConstant(+1.0, LsTrk.Regions.GetSpeciesSubGrid("X").VolumeMask);
            }

            // compute error
            ERR.Clear();
            ERR.Acc(1.0, du_dx_Exact, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);
            ERR.Acc(-1.0, du_dx, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);
            double L2Err = ERR.L2Norm(LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);

            Console.WriteLine("L2 Error: " + L2Err);

            XERR.Clear();
            XERR.GetSpeciesShadowField("B").Acc(1.0, ERR, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);
            double xL2Err = XERR.L2Norm();

            Console.WriteLine("L2 Error (in XDG space): " + xL2Err);



            // check error
            double ErrorThreshold = 1.0e-1;

            if (this.MomentFittingVariant == XQuadFactoryHelper.MomentFittingVariants.OneStepGaussAndStokes)
            {
                ErrorThreshold = 1.0e-6; // HMF is designed for such integrands and should perform close to machine accuracy; on general integrands, the precision is different.
            }
            bool IsPassed = ((L2Err <= ErrorThreshold || this.THRESHOLD <= ErrorThreshold) && xL2Err <= ErrorThreshold);

            if (IsPassed)
            {
                Console.WriteLine("Test PASSED");
            }
            else
            {
                Console.WriteLine("Test FAILED: check errors.");
                //PlotCurrentState(phystime, TimestepNo, 3);
            }

            if (TimestepNo > 1)
            {
                if (this.THRESHOLD > ErrorThreshold)
                {
                    // without agglomeration, the error in very tiny cut-cells may be large over the whole cell
                    // However, the error in the XDG-space should be small under all circumstances
                    Assert.LessOrEqual(L2Err, ErrorThreshold, "DG L2 error of computing du_dx");
                }
                Assert.LessOrEqual(xL2Err, ErrorThreshold, "XDG L2 error of computing du_dx");
            }



            // return/Ende
            base.NoOfTimesteps = 17;
            //base.NoOfTimesteps = 2;
            dt = 0.3;
            return(dt);
        }