Beispiel #1
0
        /// <summary>
        /// Jacobi iteration
        /// </summary>
        public void Solve <U, V>(U xl, V bl)
            where U : IList <double>
            where V : IList <double>
        {
            int L = xl.Count;

            double[] ql = new double[L];

            double iter0_ResNorm = 0;

            for (int iIter = 0; true; iIter++)
            {
                ql.SetV(bl);
                Mtx.SpMV(-1.0, xl, 1.0, ql);
                double ResNorm = ql.L2NormPow2().MPISum().Sqrt();

                if (iIter == 0)
                {
                    iter0_ResNorm = ResNorm;

                    if (this.IterationCallback != null)
                    {
                        double[] _xl = xl.ToArray();
                        double[] _bl = bl.ToArray();
                        Mtx.SpMV(-1.0, _xl, 1.0, _bl);
                        this.IterationCallback(iIter + 1, _xl, _bl, this.m_MultigridOp);
                    }
                }

                if (!TerminationCriterion(iIter, iter0_ResNorm, ResNorm))
                {
                    m_Converged = true;
                    return;
                }

                Diag.SpMV(1.0, xl, 1.0, ql);


                //xl.ScaleV(1.0 - omega);
                invDiag.SpMV(omega, ql, 1.0 - omega, xl);

                //for(int i = 0; i < L; i++) {
                //    xl[i] = omega * ((ql[i] + diag[i] * xl[i]) / diag[i])
                //        + (1.0 - omega) * xl[i];
                //}



                if (this.IterationCallback != null)
                {
                    double[] _xl = xl.ToArray();
                    double[] _bl = bl.ToArray();
                    Mtx.SpMV(-1.0, _xl, 1.0, _bl);
                    this.IterationCallback(iIter + 1, _xl, _bl, this.m_MultigridOp);
                }
            }
        }
        /// <summary>
        /// computes the residual on this level.
        /// </summary>
        public void Residual(double[] Res, double[] X, double[] B)
        {
            Debug.Assert(Res.Length == m_MgOperator.Mapping.LocalLength);
            Debug.Assert(X.Length == m_MgOperator.Mapping.LocalLength);
            Debug.Assert(B.Length == m_MgOperator.Mapping.LocalLength);
            int L = Res.Length;

            Array.Copy(B, Res, L);
            OpMatrix.SpMV(-1.0, X, 1.0, Res);
            //Res.AccV(1.0, B);


            /*
             * int L = Res.Count;
             *
             * var OpMatrix_coarse = m_MgOperator.CoarserLevel.OperatorMatrix;
             * int Lc = OpMatrix_coarse._RowPartitioning.LocalLength;
             *
             * double[] Xc = new double[Lc];
             * double[] Bc = new double[Lc];
             * m_MgOperator.CoarserLevel.Restrict(X, Xc);
             * m_MgOperator.CoarserLevel.Restrict(B, Bc);
             *
             * double[] Res_coarse = Bc; Bc = null;
             * OpMatrix_coarse.SpMV(-1.0, Xc, 1.0, Res_coarse);
             *
             * m_MgOperator.CoarserLevel.Restrict(Res, Res_coarse);
             *
             * double[] Res1 = new double[L];// Res.ToArray();
             * m_MgOperator.CoarserLevel.Prolongate(-1.0, Res1, 0.0, Res_coarse);
             *
             * double alpha = ParallelBlas.MPI_ddot(Res, Res1) / Res1.L2NormPow2().MPISum();
             *
             *
             *
             * double[] RemRes = Res.ToArray();
             * RemRes.AccV(-alpha, Res1);
             *
             * Res1.ScaleV(alpha);
             *
             *
             * int iLevel = m_MgOperator.LevelIndex;
             * Console.Write("    ");
             * for(int iLv = 0; iLv <= iLevel; iLv++) {
             *  Console.Write("  ");
             * }
             *
             * Console.WriteLine(iLevel + " " + Res.L2Norm().ToString("0.####E-00") + "   " + RemRes.L2Norm().ToString("0.####E-00") + "   " + Res1.L2Norm().ToString("0.####E-00") + "   " + GenericBlas.InnerProd(RemRes, Res1));
             *
             * //viz.PlotVectors(new double[][] { Res.ToArray(), Res1, Res_coarse, RemRes }, new[] { "Residual", "ProloResi", "CarseResi", "RestResi" });
             */
        }
Beispiel #3
0
 /// <summary>
 /// computes the residual on this level.
 /// </summary>
 public void Residual <V1, V2, V3>(V1 rl, V2 xl, V3 bl)
     where V1 : IList <double>
     where V2 : IList <double>
     where V3 : IList <double>
 {
     OpMatrix.SpMV(-1.0, xl, 0.0, rl);
     rl.AccV(1.0, bl);
 }
Beispiel #4
0
 /// <summary>
 /// computes the residual on this level.
 /// </summary>
 public double Residual <V1, V2, V3>(V1 rl, V2 xl, V3 bl)
     where V1 : IList <double>
     where V2 : IList <double>
     where V3 : IList <double>
 {
     OpMatrix.SpMV(-1.0, xl, 0.0, rl);
     rl.AccV(1.0, bl);
     return(rl.MPI_L2Norm());
 }
        protected virtual void UpdateChangeRate(double PhysTime, double[] k)
        {
            BlockMsrMatrix OpMtx = new BlockMsrMatrix(this.CurrentStateMapping);

            double[] OpAff = new double[this.CurrentStateMapping.LocalLength];
            base.ComputeOperatorMatrix(OpMtx, OpAff, this.CurrentStateMapping, this.CurrentStateMapping.Fields.ToArray(), base.GetAgglomeratedLengthScales(), PhysTime);

            k.SetV(OpAff);
            OpMtx.SpMV(1.0, this.m_CurrentState, 1.0, k);
        }
Beispiel #6
0
        static void RestictionMatrixTestRec(int p, IEnumerable <MultigridMapping> MgMapSeq)
        {
            var currentLevelMap           = MgMapSeq.First();
            AggregationGridBasis AggBasis = currentLevelMap.AggBasis[0];

            var map = new UnsetteledCoordinateMapping(new Basis(grid, p));

            Random rnd = new Random();

            double[] OrigVec  = map.LocalLength.ForLoop(i => rnd.NextDouble());
            double[] RestVec  = new double[AggBasis.LocalDim];
            double[] PrlgVec  = new double[OrigVec.Length];
            double[] RestVec2 = new double[RestVec.Length];
            double[] PrlgVec2 = new double[OrigVec.Length];


            AggBasis.RestictFromFullGrid(OrigVec, RestVec);
            AggBasis.ProlongateToFullGrid(PrlgVec, RestVec);

            BlockMsrMatrix RestOp = new BlockMsrMatrix(MgMapSeq.First(), MgMapSeq.First().ProblemMapping);

            AggBasis.GetRestrictionMatrix(RestOp, MgMapSeq.First(), 0);
            RestOp.SpMV(1.0, OrigVec, 0.0, RestVec2);

            BlockMsrMatrix PrlgOp = RestOp.Transpose();

            PrlgOp.SpMV(1.0, RestVec2, 0.0, PrlgVec2);

            double RestErrNorm = GenericBlas.L2Dist(RestVec2, RestVec);
            double PrlgErrNorm = GenericBlas.L2Dist(PrlgVec2, PrlgVec);
            double LostInfNorm = GenericBlas.L2Dist(OrigVec, PrlgVec2);

            //Console.WriteLine("Rest. matrix test: {0}, Prolong. matrix test {1}, Lost info {2}", RestErrNorm, PrlgErrNorm, LostInfNorm);
            Assert.IsTrue(RestErrNorm < 1.0e-10);
            Assert.IsTrue(PrlgErrNorm < 1.0e-10);

            // restriction onto level itself
            BlockMsrMatrix RestMtx   = currentLevelMap.FromOtherLevelMatrix(currentLevelMap);
            BlockMsrMatrix ShldBeEye = BlockMsrMatrix.Multiply(RestMtx, RestMtx.Transpose());

            ShldBeEye.AccEyeSp(-1.0);
            double errNorm = ShldBeEye.InfNorm();

            Console.WriteLine("Id norm {0} \t (level {1})", errNorm, currentLevelMap.AggGrid.MgLevel);
            Assert.IsTrue(errNorm < 1.0e-8);


            // recursion
            if (MgMapSeq.Count() > 1)
            {
                RestictionMatrixTestRec(p, MgMapSeq.Skip(1));
            }
        }
Beispiel #7
0
        void DerivativeByFluxLinear(SinglePhaseField fin, SinglePhaseField fres, int d, SinglePhaseField fBnd)
        {
            var Op = (new LinearDerivFlx(d)).Operator();

            BlockMsrMatrix OpMtx = new BlockMsrMatrix(fres.Mapping, fin.Mapping);

            double[] OpAff = new double[fres.Mapping.LocalLength];
            Op.ComputeMatrixEx(fin.Mapping, new DGField[] { fBnd }, fres.Mapping,
                               OpMtx, OpAff, OnlyAffine: false);

            fres.Clear();
            fres.CoordinateVector.Acc(1.0, OpAff);
            OpMtx.SpMV(1.0, fin.CoordinateVector, 1.0, fres.CoordinateVector);
        }
Beispiel #8
0
        /// <summary>
        /// Jacobi iteration
        /// </summary>
        /// <param name="l">muligrid level</param>
        /// <param name="NoOfIter">number of Jacobi-Iterations</param>
        public void Solve <U, V>(U xl, V bl)
            where U : IList <double>
            where V : IList <double>
        {
            int L = xl.Count;

            double[] ql = new double[L];

            for (int iIter = 0; iIter < NoOfIterations; iIter++)
            {
                this.m_ThisLevelIterations++;
                ql.SetV(bl);
                Mtx.SpMV(-1.0, xl, 1.0, ql);
                if (this.m_Tolerance > 0)
                {
                    double ResNorm = ql.L2NormPow2().MPISum().Sqrt();
                    if (ResNorm < this.m_Tolerance)
                    {
                        m_Converged = true;
                        return;
                    }
                }

                for (int i = 0; i < L; i++)
                {
                    xl[i] = omega * ((ql[i] + diag[i] * xl[i]) / diag[i]) + (1.0 - omega) * xl[i];
                }

                if (this.IterationCallback != null)
                {
                    double[] _xl = xl.ToArray();
                    double[] _bl = bl.ToArray();
                    Mtx.SpMV(-1.0, _xl, 1.0, _bl);
                    this.IterationCallback(iIter, _xl, _bl, this.m_mgop);
                }
            }
        }
        private void RKstage(double dt, double[][] k, int s, BlockMsrMatrix MsInv, BlockMsrMatrix M0, double[] u0, double[] coefficients)
        {
            // Copy coordinates to temp array since SpMV (below) does not
            // support in-place computation
            double[] tempCoordinates = CurrentState.ToArray();
            M0.SpMV(1.0, u0, 0.0, tempCoordinates); // Non-agglomerated
            for (int l = 0; l < s; l++)
            {
                tempCoordinates.AccV(-coefficients[l] * dt, k[l]); // Non-agglomerated
            }

            speciesMap.Agglomerator.ManipulateRHS(tempCoordinates, Mapping);
            MsInv.SpMV(1.0, tempCoordinates, 0.0, CurrentState);
            speciesMap.Agglomerator.Extrapolate(CurrentState.Mapping);
        }
Beispiel #10
0
        static void PolynomialRestAndPrlgTestRec(int p, MultigridMapping[] MgMapSeq)
        {
            var AggBasis = MgMapSeq.First().AggBasis[0];
            //var AggBasis = aggBasisEs[1];
            //{
            var Orig = new SinglePhaseField(new Basis(grid, p));

            SetTestValue(Orig);
            var Test = Orig.CloneAs();

            double[] OrigVec = Orig.CoordinateVector.ToArray();
            double[] RestVec = new double[AggBasis.LocalDim];
            double[] PrlgVec = new double[OrigVec.Length];


            AggBasis.RestictFromFullGrid(OrigVec, RestVec);
            Test.Clear();
            AggBasis.ProlongateToFullGrid(PrlgVec, RestVec);

            BlockMsrMatrix RestOp = new BlockMsrMatrix(MgMapSeq[0], MgMapSeq[0].ProblemMapping);

            AggBasis.GetRestrictionMatrix(RestOp, MgMapSeq[0], 0);
            double[] RestVec2 = new double[RestVec.Length];
            RestOp.SpMV(1.0, OrigVec, 0.0, RestVec2);


            Test.Clear();
            Test.CoordinateVector.Acc(1.0, PrlgVec);


            Test.Acc(-1.0, Orig);
            double ErrNorm = Test.L2Norm();

            Console.WriteLine("Polynomial Restriction/Prolongation test (p={1}, level={2}): {0}", ErrNorm, p, -MgMapSeq.Length);
            Assert.Less(ErrNorm, 1.0e-8);

            if (MgMapSeq.Length > 1)
            {
                PolynomialRestAndPrlgTestRec(p, MgMapSeq.Skip(1).ToArray());
            }
        }
Beispiel #11
0
        static void RestictionMatrixTestRec(int p, IEnumerable <MultigridMapping> MgMapSeq)
        {
            AggregationGridBasis AggBasis = MgMapSeq.First().AggBasis[0];
            var map = new UnsetteledCoordinateMapping(new Basis(grid, p));

            Random rnd = new Random();

            double[] OrigVec  = map.LocalLength.ForLoop(i => rnd.NextDouble());
            double[] RestVec  = new double[AggBasis.LocalDim];
            double[] PrlgVec  = new double[OrigVec.Length];
            double[] RestVec2 = new double[RestVec.Length];
            double[] PrlgVec2 = new double[OrigVec.Length];


            AggBasis.RestictFromFullGrid(OrigVec, RestVec);
            AggBasis.ProlongateToFullGrid(PrlgVec, RestVec);

            BlockMsrMatrix RestOp = new BlockMsrMatrix(MgMapSeq.First(), MgMapSeq.First().ProblemMapping);

            AggBasis.GetRestrictionMatrix(RestOp, MgMapSeq.First(), 0);
            RestOp.SpMV(1.0, OrigVec, 0.0, RestVec2);

            BlockMsrMatrix PrlgOp = RestOp.Transpose();

            PrlgOp.SpMV(1.0, RestVec2, 0.0, PrlgVec2);

            double RestErrNorm = GenericBlas.L2Dist(RestVec2, RestVec);
            double PrlgErrNorm = GenericBlas.L2Dist(PrlgVec2, PrlgVec);
            double LostInfNorm = GenericBlas.L2Dist(OrigVec, PrlgVec2);

            //Console.WriteLine("Rest. matrix test: {0}, Prolong. matrix test {1}, Lost info {2}", RestErrNorm, PrlgErrNorm, LostInfNorm);
            Debug.Assert(RestErrNorm < 1.0e-10);
            Debug.Assert(PrlgErrNorm < 1.0e-10);

            if (MgMapSeq.Count() > 1)
            {
                RestictionMatrixTestRec(p, MgMapSeq.Skip(1));
            }
        }
Beispiel #12
0
        public static void SpMVTest(
            [Values(XDGusage.none, XDGusage.mixed1, XDGusage.mixed2, XDGusage.all)] XDGusage UseXdg,
            [Values(1, 3)] int DGOrder,
            [Values(false, true)] bool compressL1,
            [Values(false, true)] bool compressL2)
        {
            unsafe
            {
                int[] Params = new int[8], ParamsGlob = new int[8];
                fixed(int *pParams = Params, pParamsGlob = ParamsGlob)
                {
                    pParams[0] = (int)UseXdg;
                    pParams[1] = DGOrder;
                    pParams[2] = compressL1 ? 1 : 0;
                    pParams[3] = compressL2 ? 1 : 0;
                    pParams[4] = -pParams[0];
                    pParams[5] = -pParams[1];
                    pParams[6] = -pParams[2];
                    pParams[7] = -pParams[3];

                    csMPI.Raw.Allreduce((IntPtr)pParams, (IntPtr)pParamsGlob, 8, csMPI.Raw._DATATYPE.INT, csMPI.Raw._OP.MIN, csMPI.Raw._COMM.WORLD);
                }

                int[] ParamsMin = ParamsGlob.GetSubVector(0, 4);
                int[] ParamsMax = ParamsGlob.GetSubVector(4, 4);
                for (int i = 0; i < 4; i++)
                {
                    if (Params[i] != ParamsMin[i])
                    {
                        throw new ApplicationException();
                    }
                    if (Params[i] != -ParamsMax[i])
                    {
                        throw new ApplicationException();
                    }
                }

                Console.WriteLine("SpMVTest({0},{1},{2},{3})", UseXdg, DGOrder, compressL1, compressL2);
            }

            using (var solver = new Matrix_MPItestMain()
            {
                m_UseXdg = UseXdg, m_DGorder = DGOrder
            }) {
                // create the test data
                // ====================

                BoSSS.Solution.Application.CommandLineOptions opts = null;
                //opts = new BoSSS.Solution.Application.CommandLineOptions();
                solver.Init(null, opts);
                solver.RunSolverMode();

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

                BlockMsrMatrix M = solver.OperatorMatrix;
                double[]       B = new double[M.RowPartitioning.LocalLength];
                double[]       X = new double[M.ColPartition.LocalLength];

                Random R = new Random();
                for (int i = 0; i < X.Length; i++)
                {
                    X[i] = R.NextDouble();
                }
                for (int i = 0; i < B.Length; i++)
                {
                    B[i] = R.NextDouble();
                }

                double[] Bb4 = B.CloneAs();

                double RefNorm = B.L2NormPow2().MPISum().Sqrt() * 1e-10;

                stw.Start();

                M.SpMV(1.6, X, 0.5, B);

                stw.Stop();

                //M.SaveToTextFileSparse(@"C:\tmp\M.txt");
                //M11.SaveToTextFileSparse(@"C:\tmp\M11.txt");
                //M12.SaveToTextFileSparse(@"C:\tmp\M12.txt");
                //M21.SaveToTextFileSparse(@"C:\tmp\M21.txt");
                //M22.SaveToTextFileSparse(@"C:\tmp\M22.txt");
                //M22xM21.SaveToTextFileSparse(@"C:\tmp\M22xM21.txt");


                using (var MatlabRef = new BatchmodeConnector()) {
                    MultidimensionalArray CheckRes = MultidimensionalArray.Create(1, 1);

                    MatlabRef.PutSparseMatrix(M, "M");
                    MatlabRef.PutVector(Bb4, "Bref");
                    MatlabRef.PutVector(B, "B");
                    MatlabRef.PutVector(X, "X");


                    MatlabRef.Cmd("Bref = Bref*0.5 + M*X*1.6;");
                    MatlabRef.Cmd("errB = norm(B - Bref, 2);");

                    MatlabRef.Cmd("CheckRes = [errB];");
                    MatlabRef.GetMatrix(CheckRes, "CheckRes");



                    MatlabRef.Execute();

                    Console.WriteLine("Matlab check SpMV: " + CheckRes[0, 0]);


                    Assert.LessOrEqual(CheckRes[0, 0], RefNorm, "Error in SpMV");
                }


                Console.WriteLine("Time spend in matrix operations: " + stw.Elapsed.TotalSeconds + " sec.");

                TotTime_MatrixOp += stw.Elapsed;
            }
        }
Beispiel #13
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;
            }
        }
Beispiel #14
0
        //
        //
        /// <summary>
        /// applies the agglomeration on a general matrix
        /// </summary>
        /// <param name="Matrix">the matrix that should be manipulated.</param>
        /// <param name="Rhs">the right-hand-side that should be manipulated</param>
        /// <param name="ColMap"></param>
        /// <param name="ColMapAggSw">Turns column agglomeration on/off fore each variable individually; default == null is on. </param>
        /// <param name="RowMap"></param>
        /// <param name="RowMapAggSw">The same shit as for <paramref name="ColMapAggSw"/>, just for rows.</param>
        public void ManipulateMatrixAndRHS<M, T>(M Matrix, T Rhs, UnsetteledCoordinateMapping RowMap, UnsetteledCoordinateMapping ColMap, bool[] RowMapAggSw = null, bool[] ColMapAggSw = null)
            where M : IMutableMatrixEx
            where T : IList<double>
        {
            MPICollectiveWatchDog.Watch();
            //var mtxS = GetFrameMatrices(Matrix, RowMap, ColMap);

            if (Matrix == null && Rhs == null)
                // nothing to do
                return;

            if (TotalNumberOfAgglomerations <= 0)
                // nothing to do
                return;

            if (RowMapAggSw != null)
                throw new NotImplementedException();

            // generate agglomeration sparse matrices
            // ======================================

            int RequireRight;
            if (Matrix == null) {
                // we don't need multiplication-from-the-right at all
                RequireRight = 0;
            } else {
                if (RowMap.EqualsUnsetteled(ColMap) && ArrayTools.ListEquals(ColMapAggSw, RowMapAggSw)) {
                    // we can use the same matrix for right and left multiplication
                    RequireRight = 1;

                } else {
                    // separate matrix for the multiplication-from-the-right is required
                    RequireRight = 2;
                }
            }

            BlockMsrMatrix LeftMul = null, RightMul = null;
            {

                foreach (var kv in DictAgglomeration) {
                    var Species = kv.Key;
                    var m_Agglomerator = kv.Value;

                    if (m_Agglomerator != null) {

                        CellMask spcMask = this.Tracker.Regions.GetSpeciesMask(Species);

                        MiniMapping rowMini = new MiniMapping(RowMap, Species, this.Tracker.Regions);
                        BlockMsrMatrix LeftMul_Species = m_Agglomerator.GetRowManipulationMatrix(RowMap, rowMini.MaxDeg, rowMini.NoOfVars, rowMini.i0Func, rowMini.NFunc, false, spcMask);
                        if (LeftMul == null) {
                            LeftMul = LeftMul_Species;
                        } else {
                            LeftMul.Acc(1.0, LeftMul_Species);
                        }

                        if (!object.ReferenceEquals(LeftMul, RightMul) && RightMul != null) {
                            MiniMapping colMini = new MiniMapping(ColMap, Species, this.Tracker.Regions);
                            BlockMsrMatrix RightMul_Species = m_Agglomerator.GetRowManipulationMatrix(ColMap, colMini.MaxDeg, colMini.NoOfVars, colMini.i0Func, colMini.NFunc, false, spcMask);

                            if (RightMul == null) {
                                RightMul = RightMul_Species;
                            } else {
                                RightMul.Acc(1.0, RightMul_Species);
                            }

                        } else if (RequireRight == 1) {
                            RightMul = LeftMul;
                        } else {
                            RightMul = null;
                        }
                    }
                }
            }

            // apply the agglomeration to the matrix
            // =====================================

            if (Matrix != null) {
                BlockMsrMatrix RightMulTr = RightMul.Transpose();

                BlockMsrMatrix _Matrix;
                if (Matrix is BlockMsrMatrix) {
                    _Matrix = (BlockMsrMatrix)((object)Matrix);
                } else {
                    _Matrix = Matrix.ToBlockMsrMatrix(RowMap, ColMap);
                }

                var AggMatrix = BlockMsrMatrix.Multiply(LeftMul, BlockMsrMatrix.Multiply(_Matrix, RightMulTr));

                if (object.ReferenceEquals(_Matrix, Matrix)) {
                    _Matrix.Clear();
                    _Matrix.Acc(1.0, AggMatrix);
                } else {
                    Matrix.Acc(-1.0, _Matrix); //   das ist so
                    Matrix.Acc(1.0, AggMatrix); //  meagaschlecht !!!!!!
                }
            }

            // apply the agglomeration to the Rhs
            // ==================================

            if (Rhs != null) {

                double[] tmp = Rhs.ToArray();
                if (object.ReferenceEquals(tmp, Rhs))
                    throw new ApplicationException("Flache kopie sollte eigentlich ausgeschlossen sein!?");

                LeftMul.SpMV(1.0, tmp, 0.0, Rhs);
            }
        }
Beispiel #15
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
        }
Beispiel #16
0
        /// <summary>
        /// implementation of the CG algorithm
        /// </summary>
        /// <param name="_x"></param>
        /// <param name="_R"></param>
        /// <param name="stats"></param>
        public void Solve <Vec1, Vec2>(Vec1 _x, Vec2 _R)
            where Vec1 : IList <double>
            where Vec2 : IList <double>
        {
            double[] x, R;
            if (_x is double[])
            {
                x = _x as double[];
            }
            else
            {
                x = _x.ToArray();
            }
            if (_R is double[])
            {
                R = _R as double[];
            }
            else
            {
                R = _R.ToArray();
            }

            int L = x.Length;

            double[] P = new double[L];

            //double[] R = rhs; // rhs is only needed once, so we can use it to store residuals
            double[] V = new double[L];
            double[] Z = new double[L];


            // compute P0, R0
            // ==============
            GenericBlas.dswap(L, x, 1, P, 1);
            m_OptMatrix.SpMV(-1.0, P, 1.0, R);
            if (IterationCallback != null)
            {
                IterationCallback(NoOfIterations, P.CloneAs(), R.CloneAs(), this.m_MgOp);
            }
            GenericBlas.dswap(L, x, 1, P, 1);
            if (Precond != null)
            {
                Precond.Solve(Z, R);
                P.SetV(Z);
            }
            else
            {
                P.SetV(R);
            }

            double alpha   = R.InnerProd(P);
            double alpha_0 = alpha;
            double ResNorm;

            ResNorm = Math.Sqrt(alpha);

            // iterate
            // =======
            NoOfIterations++; // one iteration has allready been performed (P0, R0)
            for (int n = 1; n < this.m_MaxIterations; n++)
            {
                if (ResNorm <= m_Tolerance && NoOfIterations >= m_MinIterations)
                {
                    this.m_Converged = true;
                    break;
                }
                NoOfIterations++;

                if (Math.Abs(alpha) <= double.Epsilon)
                {
                    // numerical breakdown
                    break;
                }


                m_Matrix.SpMV(1.0, P, 0, V);
                double VxP = V.InnerProd(P);
                //Console.WriteLine("VxP: {0}", VxP);
                if (double.IsNaN(VxP) || double.IsInfinity(VxP))
                {
                    throw new ArithmeticException();
                }
                double lambda = alpha / VxP;
                if (double.IsNaN(lambda) || double.IsInfinity(lambda))
                {
                    throw new ArithmeticException();
                }


                x.AccV(lambda, P);

                R.AccV(-lambda, V);

                if (IterationCallback != null)
                {
                    IterationCallback(NoOfIterations, x.CloneAs(), R.CloneAs(), this.m_MgOp);
                }

                if (Precond != null)
                {
                    Z.Clear();
                    Precond.Solve(Z, R);
                }
                else
                {
                    Z.SetV(R);
                }

                double alpha_neu = R.InnerProd(Z).MPISum();

                // compute residual norm
                ResNorm = R.L2NormPow2().MPISum().Sqrt();

                P.ScaleV(alpha_neu / alpha);
                P.AccV(1.0, Z);

                alpha = alpha_neu;
            }

            if (!object.ReferenceEquals(_x, x))
            {
                _x.SetV(x);
            }
            if (!object.ReferenceEquals(_R, R))
            {
                _R.SetV(R);
            }


            return;
        }
Beispiel #17
0
        public void UpdateSensorValues(CNSFieldSet fieldSet, ISpeciesMap speciesMap, CellMask cellMask)
        {
            DGField fieldToTest = fieldSet.ConservativeVariables.
                                  Concat(fieldSet.DerivedFields.Values).
                                  Where(f => f.Identification == sensorVariable.Name).
                                  Single();
            int degree    = fieldToTest.Basis.Degree;
            int noOfCells = fieldToTest.GridDat.iLogicalCells.NoOfLocalUpdatedCells;

            if (sensorValues == null || sensorValues.Length != noOfCells)
            {
                sensorValues = new double[noOfCells];
            }

            IMatrix coordinatesTimesMassMatrix;
            IMatrix coordinatesTruncatedTimesMassMatrix;

            if (speciesMap is ImmersedSpeciesMap ibmMap)
            {
                // Note: This has to be the _non_-agglomerated mass matrix
                // because we still live on the non-agglomerated mesh at this
                // point
                BlockMsrMatrix massMatrix = ibmMap.GetMassMatrixFactory(fieldToTest.Mapping).NonAgglomeratedMassMatrix;

                // Old
                DGField temp = fieldToTest.CloneAs();
                massMatrix.SpMV(1.0, fieldToTest.CoordinateVector, 0.0, temp.CoordinateVector);
                coordinatesTimesMassMatrix = temp.Coordinates;

                // Neu
                DGField uTruncated = fieldToTest.CloneAs();

                // Set all coordinates to zero
                for (int cell = 0; cell < uTruncated.Coordinates.NoOfRows; cell++)
                {
                    for (int coordinate = 0; coordinate < uTruncated.Coordinates.NoOfCols; coordinate++)
                    {
                        uTruncated.Coordinates[cell, coordinate] = 0;
                    }
                }

                // Copy only the coordiantes that belong to the highest modes
                foreach (int cell in cellMask.ItemEnum)
                {
                    foreach (int coordinate in fieldToTest.Basis.GetPolynomialIndicesForDegree(cell, degree))
                    {
                        uTruncated.Coordinates[cell, coordinate] = fieldToTest.Coordinates[cell, coordinate];
                    }
                }

                // Calculate M times u
                DGField vecF_Field = fieldToTest.CloneAs();
                massMatrix.SpMV(1.0, uTruncated.CoordinateVector, 0.0, vecF_Field.CoordinateVector);
                coordinatesTruncatedTimesMassMatrix = vecF_Field.Coordinates;
            }
            else
            {
                // Mass matrix is identity
                coordinatesTimesMassMatrix          = fieldToTest.Coordinates;
                coordinatesTruncatedTimesMassMatrix = fieldToTest.Coordinates;
            }
            //IMatrix coordinatesTimesMassMatrix = fieldToTest.Coordinates;

            //cellMask.SaveToTextFile("fluidCells.txt");

            // This is equivalent to norm(restrictedField) / norm(originalField)
            // Note: THIS WILL FAIL IN CUT CELLS
            foreach (int cell in cellMask.ItemEnum)
            {
                double numerator = 0.0;
                foreach (int coordinate in fieldToTest.Basis.GetPolynomialIndicesForDegree(cell, degree))
                {
                    //numerator += fieldToTest.Coordinates[cell, coordinate] * fieldToTest.Coordinates[cell, coordinate];
                    numerator += fieldToTest.Coordinates[cell, coordinate] * coordinatesTruncatedTimesMassMatrix[cell, coordinate];
                }

                double denominator = 0.0;
                for (int coordinate = 0; coordinate < fieldToTest.Basis.Length; coordinate++)
                {
                    //denominator += fieldToTest.Coordinates[cell, coordinate] * fieldToTest.Coordinates[cell, coordinate];
                    denominator += fieldToTest.Coordinates[cell, coordinate] * coordinatesTimesMassMatrix[cell, coordinate];
                }

                double result;
                if (denominator == 0.0)
                {
                    result = 0.0;
                }
                else
                {
                    result = numerator / denominator;
                }

                //Debug.Assert(denominator != 0, "Persson sensor: Denominator is zero!");

                //Debug.Assert(!(numerator / denominator).IsNaN(), "Persson sensor: Sensor value is NaN!");

                //Debug.Assert(numerator / denominator >= 0, "Persson sensor: Sensor value is negative!");

                sensorValues[cell] = result;
            }
        }
Beispiel #18
0
        public void Solve <V1, V2>(V1 _X, V2 _B)
            where V1 : IList <double>
            where V2 : IList <double>
        {
            using (var tr = new FuncTrace())
            {
                double[] X, B;
                if (_X is double[])
                {
                    X = _X as double[];
                }
                else
                {
                    X = _X.ToArray();
                }
                if (_B is double[])
                {
                    B = _B as double[];
                }
                else
                {
                    B = _B.ToArray();
                }


                double bnrm2 = B.L2NormPow2().MPISum().Sqrt();
                if (bnrm2 == 0.0)
                {
                    bnrm2 = 1.0;
                }

                int Nloc = Matrix.RowPartitioning.LocalLength;
                int Ntot = Matrix.RowPartitioning.TotalLength;

                double[] r = new double[Nloc];
                double[] z = new double[Nloc];

                //r = M \ ( b-A*x );, where M is the precond
                z.SetV(B);
                Matrix.SpMV(-1.0, X, 1.0, z);
                if (IterationCallback != null)
                {
                    IterationCallback(0, X.CloneAs(), z.CloneAs(), this.m_mgop);
                }
                if (this.Precond != null)
                {
                    r.Clear();
                    this.Precond.Solve(r, z);
                }
                else
                {
                    r.SetV(z);
                }

                // Inserted for real residual
                double error2 = z.L2NormPow2().MPISum().Sqrt();

                double error = (r.L2NormPow2().MPISum().Sqrt()) / bnrm2;
                if (error < this.m_Tolerance)
                {
                    if (!object.ReferenceEquals(_X, X))
                    {
                        _X.SetV(X);
                    }
                    B.SetV(z);
                    this.m_Converged = true;
                    return;
                }

                if (MaxKrylovDim <= 0)
                {
                    throw new NotSupportedException("unsupported restart length.");
                }

                int                   m = MaxKrylovDim;
                double[][]            V = (m + 1).ForLoop(i => new double[Nloc]); //   V(1:n,1:m+1) = zeros(n,m+1);
                MultidimensionalArray H = MultidimensionalArray.Create(m + 1, m); //   H(1:m+1,1:m) = zeros(m+1,m);

                double[] cs = new double[m];
                double[] sn = new double[m];
                //double[] s = new double[m+1];
                double[] e1 = new double[Nloc];
                //if(Matrix.RowPartitioning.Rank == 0)
                e1[0] = 1.0;

                double[] s = new double[Nloc], w = new double[Nloc], y;
                double   temp;
                int      iter;
                for (iter = 1; iter <= m_MaxIterations; iter++)
                { // GMRES iterations
                  // r = M \ ( b-A*x );
                    z.SetV(B);
                    Matrix.SpMV(-1.0, X, 1.0, z);

                    error2 = z.L2NormPow2().MPISum().Sqrt();

                    if (this.Precond != null)
                    {
                        r.Clear();
                        this.Precond.Solve(r, z);
                    }
                    else
                    {
                        r.SetV(z);
                    }

                    // V(:,1) = r / norm( r );
                    double norm_r = r.L2NormPow2().MPISum().Sqrt();
                    V[0].SetV(r, alpha: (1.0 / norm_r));

                    //s = norm( r )*e1;
                    s.SetV(e1, alpha: norm_r);

                    int i;

                    #region Gram-Schmidt (construct orthonormal  basis using Gram-Schmidt)
                    for (i = 1; i <= m; i++)
                    {
                        this.NoOfIterations++;

                        #region Arnoldi procdure

                        //w = M \ (A*V(:,i));
                        Matrix.SpMV(1.0, V[i - 1], 0.0, z);
                        if (this.Precond != null)
                        {
                            w.Clear();
                            this.Precond.Solve(w, z);
                        }
                        else
                        {
                            w.SetV(z);
                        }

                        for (int k = 1; k <= i; k++)
                        {
                            H[k - 1, i - 1] = GenericBlas.InnerProd(w, V[k - 1]).MPISum();
                            //w = w - H(k,i)*V(:,k);
                            w.AccV(-H[k - 1, i - 1], V[k - 1]);
                        }

                        double norm_w = w.L2NormPow2().MPISum().Sqrt();
                        H[i + 1 - 1, i - 1] = norm_w; // the +1-1 actually makes me sure I haven't forgotten to subtract -1 when porting the code
                                                      //V(:,i+1) = w / H(i+1,i);
                        V[i + 1 - 1].SetV(w, alpha: (1.0 / norm_w));

                        #endregion

                        #region Givens rotation

                        for (int k = 1; k <= i - 1; k++)
                        {
                            // apply Givens rotation, H is Hessenbergmatrix
                            temp = cs[k - 1] * H[k - 1, i - 1] + sn[k - 1] * H[k + 1 - 1, i - 1];
                            H[k + 1 - 1, i - 1] = -sn[k - 1] * H[k - 1, i - 1] + cs[k - 1] * H[k + 1 - 1, i - 1];
                            H[k - 1, i - 1]     = temp;
                        }
                        //	 [cs(i),sn(i)] = rotmat( H(i,i), H(i+1,i) ); % form i-th rotation matrix
                        rotmat(out cs[i - 1], out sn[i - 1], H[i - 1, i - 1], H[i + 1 - 1, i - 1]);
                        temp                = cs[i - 1] * s[i - 1]; //                       % approximate residual norm
                        H[i - 1, i - 1]     = cs[i - 1] * H[i - 1, i - 1] + sn[i - 1] * H[i + 1 - 1, i - 1];
                        H[i + 1 - 1, i - 1] = 0.0;

                        #endregion

                        // update the residual vector (s == beta in many pseudocodes)
                        s[i + 1 - 1] = -sn[i - 1] * s[i - 1];
                        s[i - 1]     = temp;
                        error        = Math.Abs(s[i + 1 - 1]) / bnrm2;
                        //{
                        //    int rootRank = Matrix.RowPartitioning.FindProcess(i + 1 - 1);
                        //    if (Matrix.RowPartitioning.Rank == rootRank) {


                        //    } else {
                        //        error = double.NaN;
                        //    }
                        //    unsafe {
                        //        csMPI.Raw.Bcast((IntPtr)(&error), 1, csMPI.Raw._DATATYPE.DOUBLE, rootRank, Matrix.RowPartitioning.MPI_Comm);
                        //    }
                        //}

                        //using (StreamWriter writer = new StreamWriter(m_SessionPath + "//GMRES_Stats.txt", true))
                        //{
                        Console.WriteLine(i + "   " + error);
                        //}



                        if (error <= m_Tolerance)
                        {
                            // update approximation and exit
                            //using (StreamWriter writer = new StreamWriter(m_SessionPath + "//GMRES_Stats.txt", true))
                            //{
                            //    writer.WriteLine("");
                            //}

                            //y = H(1:i,1:i) \ s(1:i);
                            y = new double[i];
                            H.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { i - 1, i - 1 })
                            .Solve(y, s.GetSubVector(0, i));



                            // x = x + V(:,1:i)*y;
                            for (int ii = 0; ii < i; ii++)
                            {
                                X.AccV(y[ii], V[ii]);
                            }
                            this.m_Converged = true;
                            break;
                        }
                    }
                    #endregion
                    //Debugger.Launch();


                    if (error <= this.m_Tolerance)
                    {
                        this.m_Converged = true;
                        break;
                    }


                    // y = H(1:m,1:m) \ s(1:m);
                    y = new double[m];
                    H.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { m - 1, m - 1 })
                    .Solve(y, s.GetSubVector(0, m));
                    // update approximation: x = x + V(:,1:m)*y;
                    for (int ii = 0; ii < m; ii++)
                    {
                        X.AccV(y[ii], V[ii]);
                    }

                    // compute residual: r = M \ ( b-A*x )
                    z.SetV(B);
                    Matrix.SpMV(-1.0, X, 1.0, z);
                    if (IterationCallback != null)
                    {
                        error2 = z.L2NormPow2().MPISum().Sqrt();
                        IterationCallback(iter, X.CloneAs(), z.CloneAs(), this.m_mgop);
                        //IterationCallback(this.NoOfIterations, X.CloneAs(), z.CloneAs(), this.m_mgop);
                    }
                    if (this.Precond != null)
                    {
                        r.Clear();
                        this.Precond.Solve(r, z);
                    }
                    else
                    {
                        r.SetV(z);
                    }


                    norm_r       = r.L2NormPow2().MPISum().Sqrt();
                    s[i + 1 - 1] = norm_r;
                    error        = s[i + 1 - 1] / bnrm2; // % check convergence
                    //  if (error2 <= m_Tolerance) Check for error not error2
                    //break;
                }

                if (IterationCallback != null)
                {
                    z.SetV(B);
                    Matrix.SpMV(-1.0, X, 1.0, z);
                    IterationCallback(iter, X.CloneAs(), z.CloneAs(), this.m_mgop);
                }


                if (!object.ReferenceEquals(_X, X))
                {
                    _X.SetV(X);
                }
                B.SetV(z);
            }
        }
Beispiel #19
0
        /// <summary>
        /// %
        /// </summary>
        public void Solve <U, V>(U X, V B)
            where U : IList <double>
            where V : IList <double> //
        {
            using (var tr = new FuncTrace()) {
                double[] Residual = this.TestSolution ? B.ToArray() : null;

                string SolverName = "NotSet";
                using (var solver = GetSolver(m_Mtx)) {
                    SolverName = solver.GetType().FullName;
                    //Console.Write("Direct solver run {0}, using {1} ... ", IterCnt, solver.GetType().Name);
                    IterCnt++;
                    solver.Solve(X, B);
                    //Console.WriteLine("done.");
                }


                m_ThisLevelIterations++;

                if (Residual != null)
                {
                    //Console.Write("Checking residual (run {0}) ... ", IterCnt - 1);
                    double RhsNorm       = Residual.L2NormPow2().MPISum().Sqrt();
                    double MatrixInfNorm = m_Mtx.InfNorm();
                    m_Mtx.SpMV(-1.0, X, 1.0, Residual);

                    double ResidualNorm    = Residual.L2NormPow2().MPISum().Sqrt();
                    double SolutionNorm    = X.L2NormPow2().MPISum().Sqrt();
                    double Denom           = Math.Max(MatrixInfNorm, Math.Max(RhsNorm, Math.Max(SolutionNorm, Math.Sqrt(double.Epsilon))));
                    double RelResidualNorm = ResidualNorm / Denom;

                    //Console.WriteLine("done: Abs.: {0}, Rel.: {1}", ResidualNorm, RelResidualNorm);

                    if (RelResidualNorm > 1.0e-10)
                    {
                        //Console.WriteLine("High residual from direct solver: abs {0}, rel {1}", ResidualNorm , ResidualNorm / SolutionNorm);

                        m_Mtx.SaveToTextFileSparse("Mtx.txt");
                        X.SaveToTextFile("X.txt");
                        B.SaveToTextFile("B.txt");

                        string ErrMsg;
                        using (var stw = new StringWriter()) {
                            stw.WriteLine("High residual from direct solver (using {0}).", SolverName);
                            stw.WriteLine("    L2 Norm of RHS:         " + RhsNorm);
                            stw.WriteLine("    L2 Norm of Solution:    " + SolutionNorm);
                            stw.WriteLine("    L2 Norm of Residual:    " + ResidualNorm);
                            stw.WriteLine("    Relative Residual norm: " + RelResidualNorm);
                            stw.WriteLine("    Matrix Inf norm:        " + MatrixInfNorm);
                            stw.WriteLine("Dumping text versions of Matrix, Solution and RHS.");
                            ErrMsg = stw.ToString();
                        }
                        Console.WriteLine(ErrMsg);
                    }
                }

                if (this.IterationCallback != null)
                {
                    double[] _xl = X.ToArray();
                    double[] _bl = B.ToArray();
                    m_Mtx.SpMV(-1.0, _xl, 1.0, _bl);
                    this.IterationCallback(1, _xl, _bl, this.m_MultigridOp);
                }
            }
        }
Beispiel #20
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);
            }
        }
Beispiel #21
0
        /// <summary>
        ///
        /// </summary>
        public void AssembleMatrix_Timestepper <T>(
            int CutCellQuadOrder,
            BlockMsrMatrix OpMatrix, double[] OpAffine,
            Dictionary <SpeciesId, MultidimensionalArray> AgglomeratedCellLengthScales,
            IEnumerable <T> CurrentState,
            VectorField <SinglePhaseField> SurfaceForce,
            VectorField <SinglePhaseField> LevelSetGradient, SinglePhaseField ExternalyProvidedCurvature,
            UnsetteledCoordinateMapping RowMapping, UnsetteledCoordinateMapping ColMapping,
            double time, IEnumerable <T> CoupledCurrentState = null, IEnumerable <T> CoupledParams = null) where T : DGField
        {
            if (ColMapping.BasisS.Count != this.Op.DomainVar.Count)
            {
                throw new ArgumentException();
            }
            if (RowMapping.BasisS.Count != this.Op.CodomainVar.Count)
            {
                throw new ArgumentException();
            }

            // check:
            var Tracker = this.LsTrk;
            int D       = Tracker.GridDat.SpatialDimension;

            if (CurrentState != null && CurrentState.Count() != (D + 1))
            {
                throw new ArgumentException();
            }
            if (OpMatrix == null && CurrentState == null)
            {
                throw new ArgumentException();
            }
            DGField[] U0;
            if (CurrentState != null)
            {
                U0 = CurrentState.Take(D).ToArray();
            }
            else
            {
                U0 = null;
            }



            LevelSet Phi = (LevelSet)(Tracker.LevelSets[0]);

            SpeciesId[] SpcToCompute = AgglomeratedCellLengthScales.Keys.ToArray();

            IDictionary <SpeciesId, MultidimensionalArray> InterfaceLengths = this.LsTrk.GetXDGSpaceMetrics(this.LsTrk.SpeciesIdS.ToArray(), CutCellQuadOrder).CutCellMetrics.InterfaceArea;


            // advanced settings for the navier slip boundary condition
            // ========================================================

            CellMask SlipArea;

            switch (this.dntParams.GNBC_Localization)
            {
            case NavierSlip_Localization.Bulk: {
                SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask;
                break;
            }

            case NavierSlip_Localization.ContactLine: {
                SlipArea = null;
                break;
            }

            case NavierSlip_Localization.Nearband: {
                SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask.Intersect(this.LsTrk.Regions.GetNearFieldMask(this.LsTrk.NearRegionWidth));
                break;
            }

            case NavierSlip_Localization.Prescribed: {
                throw new NotImplementedException();
            }

            default:
                throw new ArgumentException();
            }


            MultidimensionalArray SlipLengths;

            SlipLengths = this.LsTrk.GridDat.Cells.h_min.CloneAs();
            SlipLengths.Clear();
            //SlipLengths.AccConstant(-1.0);

            if (SlipArea != null)
            {
                foreach (Chunk cnk in SlipArea)
                {
                    for (int i = cnk.i0; i < cnk.JE; i++)
                    {
                        switch (this.dntParams.GNBC_SlipLength)
                        {
                        case NavierSlip_SlipLength.hmin_DG: {
                            int degU = ColMapping.BasisS.ToArray()[0].Degree;
                            SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i] / (degU + 1);
                            break;
                        }

                        case NavierSlip_SlipLength.hmin_Grid: {
                            SlipLengths[i] = SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i];
                            break;
                        }

                        case NavierSlip_SlipLength.Prescribed_SlipLength: {
                            SlipLengths[i] = this.physParams.sliplength;
                            break;
                        }

                        case NavierSlip_SlipLength.Prescribed_Beta: {
                            SlipLengths[i] = -1.0;
                            break;
                        }
                        }
                    }
                }
            }



            // parameter assembly
            // ==================

            // normals:
            SinglePhaseField[] Normals; // Normal vectors: length not normalized - will be normalized at each quad node within the flux functions.
            if (this.NormalsRequired)
            {
                if (LevelSetGradient == null)
                {
                    LevelSetGradient = new VectorField <SinglePhaseField>(D, Phi.Basis, SinglePhaseField.Factory);
                    LevelSetGradient.Gradient(1.0, Phi);
                }
                Normals = LevelSetGradient.ToArray();
            }
            else
            {
                Normals = new SinglePhaseField[D];
            }

            // curvature:
            SinglePhaseField Curvature;

            if (this.CurvatureRequired)
            {
                Curvature = ExternalyProvidedCurvature;
            }
            else
            {
                Curvature = null;
            }

            // linearization velocity:
            DGField[] U0_U0mean;
            if (this.U0meanrequired)
            {
                XDGBasis U0meanBasis          = new XDGBasis(Tracker, 0);
                VectorField <XDGField> U0mean = new VectorField <XDGField>(D, U0meanBasis, "U0mean_", XDGField.Factory);

                U0_U0mean = ArrayTools.Cat <DGField>(U0, U0mean);
            }
            else
            {
                U0_U0mean = new DGField[2 * D];
            }

            // Temperature gradient for evaporation
            VectorField <DGField> GradTemp = new VectorField <DGField>(D, new XDGBasis(LsTrk, 0), XDGField.Factory);

            if (CoupledCurrentState != null)
            {
                DGField Temp = CoupledCurrentState.ToArray()[0];
                GradTemp = new VectorField <DGField>(D, Temp.Basis, "GradTemp", XDGField.Factory);
                XNSEUtils.ComputeGradientForParam(Temp, GradTemp, this.LsTrk);
            }

            // concatenate everything
            var Params = ArrayTools.Cat <DGField>(
                U0_U0mean,
                Curvature,
                ((SurfaceForce != null) ? SurfaceForce.ToArray() : new SinglePhaseField[D]),
                Normals,
                ((evaporation) ? GradTemp.ToArray() : new SinglePhaseField[D]),
                ((evaporation) ? CoupledCurrentState.ToArray <DGField>() : new SinglePhaseField[1]),
                ((evaporation) ? CoupledParams.ToArray <DGField>() : new SinglePhaseField[1]));  //((evaporation) ? GradTemp.ToArray() : new SinglePhaseField[D]));

            // linearization velocity:
            if (this.U0meanrequired)
            {
                VectorField <XDGField> U0mean = new VectorField <XDGField>(U0_U0mean.Skip(D).Take(D).Select(f => ((XDGField)f)).ToArray());

                U0mean.Clear();
                if (this.physParams.IncludeConvection)
                {
                    ComputeAverageU(U0, U0mean, CutCellQuadOrder, LsTrk.GetXDGSpaceMetrics(SpcToCompute, CutCellQuadOrder, 1).XQuadSchemeHelper);
                }
            }



            // assemble the matrix & affine vector
            // ===================================

            // compute matrix
            if (OpMatrix != null)
            {
                //Op.ComputeMatrixEx(Tracker,
                //    ColMapping, Params, RowMapping,
                //    OpMatrix, OpAffine, false, time, true,
                //    AgglomeratedCellLengthScales,
                //    InterfaceLengths, SlipLengths,
                //    SpcToCompute);

                XSpatialOperator.XEvaluatorLinear mtxBuilder = Op.GetMatrixBuilder(LsTrk, ColMapping, Params, RowMapping, SpcToCompute);

                foreach (var kv in AgglomeratedCellLengthScales)
                {
                    mtxBuilder.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value;
                    mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("SlipLengths", SlipLengths);
                    if (evaporation)
                    {
                        BitArray EvapMicroRegion = new BitArray(this.LsTrk.GridDat.Cells.Count);;  // this.LsTrk.GridDat.GetBoundaryCells().GetBitMask();
                        mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("EvapMicroRegion", EvapMicroRegion);
                    }
                }

                if (Op.SurfaceElementOperator.TotalNoOfComponents > 0)
                {
                    foreach (var kv in InterfaceLengths)
                    {
                        mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("InterfaceLengths", kv.Value);
                    }
                }

                mtxBuilder.time = time;

                mtxBuilder.ComputeMatrix(OpMatrix, OpAffine);

#if DEBUG
                // remark: remove this piece in a few months from now on (09may18) if no problems occur
                {
                    BlockMsrMatrix checkOpMatrix = new BlockMsrMatrix(RowMapping, ColMapping);
                    double[]       checkAffine   = new double[OpAffine.Length];

                    Op.ComputeMatrixEx(Tracker,
                                       ColMapping, Params, RowMapping,
                                       OpMatrix, OpAffine, false, time, true,
                                       AgglomeratedCellLengthScales,
                                       InterfaceLengths, SlipLengths,
                                       SpcToCompute);


                    double[] checkResult = checkAffine.CloneAs();
                    var      currentVec  = new CoordinateVector(CurrentState.ToArray());
                    checkOpMatrix.SpMV(1.0, new CoordinateVector(CurrentState.ToArray()), 1.0, checkResult);

                    double L2_dist = GenericBlas.L2DistPow2(checkResult, OpAffine).MPISum().Sqrt();
                    double RefNorm = (new double[] { checkResult.L2NormPow2(), OpAffine.L2NormPow2(), currentVec.L2NormPow2() }).MPISum().Max().Sqrt();

                    Assert.LessOrEqual(L2_dist, RefNorm * 1.0e-6);
                    Debug.Assert(L2_dist < RefNorm * 1.0e-6);
                }
#endif
            }
            else
            {
                XSpatialOperator.XEvaluatorNonlin eval = Op.GetEvaluatorEx(Tracker,
                                                                           CurrentState.ToArray(), Params, RowMapping,
                                                                           SpcToCompute);

                foreach (var kv in AgglomeratedCellLengthScales)
                {
                    eval.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value;
                    eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("SlipLengths", SlipLengths);
                    if (evaporation)
                    {
                        BitArray EvapMicroRegion = new BitArray(this.LsTrk.GridDat.Cells.Count);
                        eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("EvapMicroRegion", EvapMicroRegion);
                    }
                }

                if (Op.SurfaceElementOperator.TotalNoOfComponents > 0)
                {
                    foreach (var kv in InterfaceLengths)
                    {
                        eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("InterfaceLengths", kv.Value);
                    }
                }

                eval.time = time;

                eval.Evaluate(1.0, 1.0, OpAffine);
            }


            // check
            // =====

            /*
             * {
             *  DGField[] testDomainFieldS = ColMapping.BasisS.Select(bb => new XDGField(bb as XDGBasis)).ToArray();
             *  CoordinateVector test = new CoordinateVector(testDomainFieldS);
             *
             *  DGField[] errFieldS = ColMapping.BasisS.Select(bb => new XDGField(bb as XDGBasis)).ToArray();
             *  CoordinateVector Err = new CoordinateVector(errFieldS);
             *
             *  var eval = Op.GetEvaluatorEx(LsTrk,
             *      testDomainFieldS, Params, RowMapping);
             *
             *  foreach (var s in this.LsTrk.SpeciesIdS)
             *      eval.SpeciesOperatorCoefficients[s].CellLengthScales = AgglomeratedCellLengthScales[s];
             *
             *  eval.time = time;
             *  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, OpAffine);
             *  OpMatrix.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();
             *
             *  Debug.Assert(ErrDist <= Ref*1.0e-5, "Mismatch between explicit evaluation of XDG operator and matrix.");
             * }
             */
        }