Exemple #1
0
        private void AssembleMatrix(double MU_A, double MU_B, out BlockMsrMatrix M, out double[] b, out MultiphaseCellAgglomerator agg, out MassMatrixFactory massFact)
        {
            using (var tr = new FuncTrace()) {
                // create operator
                // ===============

                if (this.Control.SetDefaultDiriBndCnd)
                {
                    this.Control.xLaplaceBCs.g_Diri      = ((CommonParamsBnd inp) => 0.0);
                    this.Control.xLaplaceBCs.IsDirichlet = (inp => true);
                }

                double D                  = this.GridData.SpatialDimension;
                int    p                  = u.Basis.Degree;
                double penalty_base       = (p + 1) * (p + D) / D;
                double penalty_multiplyer = base.Control.penalty_multiplyer;

                XQuadFactoryHelper.MomentFittingVariants momentFittingVariant;
                if (D == 3)
                {
                    momentFittingVariant = XQuadFactoryHelper.MomentFittingVariants.Classic;
                }

                momentFittingVariant = this.Control.CutCellQuadratureType;

                int order = this.u.Basis.Degree * 2;

                XSpatialOperator Op = new XSpatialOperator(1, 1, (A, B, C) => order, "u", "c1");
                var lengthScales    = ((BoSSS.Foundation.Grid.Classic.GridData)GridData).Cells.PenaltyLengthScales;
                var lap             = new XLaplace_Bulk(this.LsTrk, penalty_multiplyer * penalty_base, "u", this.Control.xLaplaceBCs, 1.0, MU_A, MU_B, lengthScales, this.Control.ViscosityMode);
                Op.EquationComponents["c1"].Add(lap);                                                                                          // Bulk form
                Op.EquationComponents["c1"].Add(new XLaplace_Interface(this.LsTrk, MU_A, MU_B, penalty_base * 2, this.Control.ViscosityMode)); // coupling form

                Op.Commit();

                // create agglomeration
                // ====================

                var map = new UnsetteledCoordinateMapping(u.Basis);

                //agg = new MultiphaseCellAgglomerator(
                //    new CutCellMetrics(momentFittingVariant,
                //        QuadOrderFunc.SumOfMaxDegrees(RoundUp: true)(map.BasisS.Select(bs => bs.Degree).ToArray(), new int[0], map.BasisS.Select(bs => bs.Degree).ToArray()),
                //        //this.HMFDegree,
                //        LsTrk, this.LsTrk.SpeciesIdS.ToArray()),
                //    this.Control.AgglomerationThreshold, false);
                agg = LsTrk.GetAgglomerator(this.LsTrk.SpeciesIdS.ToArray(), order, this.Control.AgglomerationThreshold);

                // compute matrix
                // =============
                using (new BlockTrace("XdgMatrixAssembly", tr)) {
                    M = new BlockMsrMatrix(map, map);
                    b = new double[M.RowPartitioning.LocalLength];

                    Op.ComputeMatrixEx(LsTrk,
                                       map, null, map,
                                       M, b, false, 0.0, true,
                                       agg.CellLengthScales, null, null, //out massFact,
                                       this.LsTrk.SpeciesIdS.ToArray());
                }
                // compare with linear evaluation
                // ==============================
                DGField[]        testDomainFieldS = map.BasisS.Select(bb => new XDGField(bb as XDGBasis)).ToArray();
                CoordinateVector test             = new CoordinateVector(testDomainFieldS);

                DGField[]        errFieldS = map.BasisS.Select(bb => new XDGField(bb as XDGBasis)).ToArray();
                CoordinateVector Err       = new CoordinateVector(errFieldS);

                var eval = Op.GetEvaluatorEx(LsTrk,
                                             testDomainFieldS, null, map);

                foreach (var s in this.LsTrk.SpeciesIdS)
                {
                    eval.SpeciesOperatorCoefficients[s].CellLengthScales = agg.CellLengthScales[s];
                }

                eval.time = 0.0;
                int    L = test.Count;
                Random r = new Random();
                for (int i = 0; i < L; i++)
                {
                    test[i] = r.NextDouble();
                }



                double[] R1 = new double[L];
                double[] R2 = new double[L];
                eval.Evaluate(1.0, 1.0, R1);

                R2.AccV(1.0, b);
                M.SpMV(1.0, test, 1.0, R2);

                Err.AccV(+1.0, R1);
                Err.AccV(-1.0, R2);

                double ErrDist = GenericBlas.L2DistPow2(R1, R2).MPISum().Sqrt();

                double Ref = test.L2NormPow2().MPISum().Sqrt();

                Assert.LessOrEqual(ErrDist, Ref * 1.0e-5, "Mismatch between explicit evaluation of XDG operator and matrix.");


                // agglomeration wahnsinn
                // ======================

                agg.ManipulateMatrixAndRHS(M, b, map, map);

                foreach (var S in this.LsTrk.SpeciesNames)
                {
                    Console.WriteLine("  Species {0}: no of agglomerated cells: {1}",
                                      S, agg.GetAgglomerator(this.LsTrk.GetSpeciesId(S)).AggInfo.SourceCells.NoOfItemsLocally);
                }


                // mass matrix factory
                // ===================

                Basis maxB = map.BasisS.ElementAtMax(bss => bss.Degree);
                //massFact = new MassMatrixFactory(maxB, agg);
                massFact = LsTrk.GetXDGSpaceMetrics(this.LsTrk.SpeciesIdS.ToArray(), order).MassMatrixFactory;
            }
        }
Exemple #2
0
        void TestAgglomeration_Projection(int quadOrder, MultiphaseCellAgglomerator Agg)
        {
            var Bmask      = LsTrk.Regions.GetSpeciesMask("B");
            var BbitMask   = Bmask.GetBitMask();
            var XDGmetrics = LsTrk.GetXDGSpaceMetrics(new SpeciesId[] { LsTrk.GetSpeciesId("B") }, quadOrder, 1);

            int degree = Math.Max(0, this.u.Basis.Degree - 1);

            _2D SomePolynomial;

            if (degree == 0)
            {
                SomePolynomial = (x, y) => 3.2;
            }
            else if (degree == 1)
            {
                SomePolynomial = (x, y) => 3.2 + x - 2.4 * y;
            }
            else
            {
                SomePolynomial = (x, y) => x * x + y * y;
            }

            // ------------------------------------------------
            // project the polynomial onto a single-phase field
            // ------------------------------------------------
            SinglePhaseField NonAgglom = new SinglePhaseField(new Basis(this.GridData, degree), "NonAgglom");

            NonAgglom.ProjectField(1.0,
                                   SomePolynomial.Vectorize(),
                                   new CellQuadratureScheme(true, Bmask));

            // ------------------------------------------------
            // project the polynomial onto the aggomerated XDG-field
            // ------------------------------------------------

            var qsh = XDGmetrics.XQuadSchemeHelper;

            // Compute the inner product of 'SomePolynomial' with the cut-cell-basis, ...
            SinglePhaseField xt = new SinglePhaseField(NonAgglom.Basis, "test");

            xt.ProjectField(1.0,
                            SomePolynomial.Vectorize(),
                            qsh.GetVolumeQuadScheme(this.LsTrk.GetSpeciesId("B")).Compile(this.GridData, Agg.CutCellQuadratureOrder));

            CoordinateMapping map = xt.Mapping;

            // ... change to the cut-cell-basis, ...
            double[] xVec = xt.CoordinateVector.ToArray();
            Agg.ManipulateMatrixAndRHS(default(MsrMatrix), xVec, map, null);

            {
                double[] xVec2 = xVec.CloneAs();
                Agg.ClearAgglomerated(xVec2, map); // clearing should have no effect now.

                double Err3 = GenericBlas.L2DistPow2(xVec, xVec2).MPISum().Sqrt();
                Assert.LessOrEqual(Err3, 0.0);
            }

            // ... multiply with the inverse mass-matrix, ...
            var            Mfact   = XDGmetrics.MassMatrixFactory;
            BlockMsrMatrix MassMtx = Mfact.GetMassMatrix(map, false);

            Agg.ManipulateMatrixAndRHS(MassMtx, default(double[]), map, map);
            var InvMassMtx = MassMtx.InvertBlocks(OnlyDiagonal: true, Subblocks: true, ignoreEmptyBlocks: true, SymmetricalInversion: true);

            double[] xAggVec = new double[xVec.Length];

            InvMassMtx.SpMV(1.0, xVec, 0.0, xAggVec);

            // ... and extrapolate.
            // Since we projected a polynomial, the projection is exact and after extrapolation, must be equal
            // to the polynomial.
            xt.CoordinateVector.SetV(xAggVec);
            Agg.Extrapolate(xt.Mapping);

            // ------------------------------------------------
            // check the error
            // ------------------------------------------------


            //double Err2 = xt.L2Error(SomePolynomial.Vectorize(), new CellQuadratureScheme(domain: Bmask));
            double Err2 = NonAgglom.L2Error(xt);

            Console.WriteLine("Agglom: projection and extrapolation error: " + Err2);
            Assert.LessOrEqual(Err2, 1.0e-10);
        }
Exemple #3
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);
        }