/// <summary>
        /// Legacy interface, preserved as static function.
        /// </summary>
        public static void ComputeMatrixEx <M, V>(
            this XSpatialOperator xOp,
            LevelSetTracker lsTrk,
            UnsetteledCoordinateMapping DomainMap, IList <DGField> Parameters, UnsetteledCoordinateMapping CodomainMap,
            M Matrix, V AffineOffset, bool OnlyAffine, double time, bool ParameterMPIExchange,
            IDictionary <SpeciesId, MultidimensionalArray> CellLengthScales,
            IDictionary <SpeciesId, MultidimensionalArray> InterfaceLengthScales, MultidimensionalArray SlipLengths,
            SubGrid SubGrid, params SpeciesId[] whichSpc)
            where M : IMutableMatrixEx
            where V : IList <double> //
        {
            var SpeciesDictionary = new Dictionary <SpeciesId, XSpatialOperator.QrSchemPair>();

            foreach (var sp in whichSpc)
            {
                SpeciesDictionary.Add(sp, new XSpatialOperator.QrSchemPair());
            }

            ComputeMatrixEx <M, V>(
                xOp,
                lsTrk,
                DomainMap, Parameters, CodomainMap,
                Matrix, AffineOffset, OnlyAffine, time,
                ParameterMPIExchange, SpeciesDictionary, CellLengthScales,
                InterfaceLengthScales, SlipLengths,
                //agg, out mass,
                SubGrid);
        }
Пример #2
0
        /// <summary>
        /// Based on the Ideas by
        /// C. Basting and D. Kuzmin,
        /// “A minimization-based finite element formulation for interface-preserving level set reinitialization”,
        /// Computing, vol. 95, no. 1, pp. 13–25, Dec. 2012.
        /// </summary>
        /// <param name="LSTrck"></param>
        /// <param name="bcmap">Boundary Conditions for the LevelSet Equations</param>
        /// <param name="Control">various parameters <paramref name="EllipticReinitControl"/></param>
        public Extender(SinglePhaseField Extension, LevelSetTracker LSTrck, ILevelSetComponent InterfaceFlux, List <DGField> InterfaceParams, VectorField <SinglePhaseField> LevelSetGradient, EllipticExtVelAlgoControl Control)
        {
            if (InterfaceFlux.ParameterOrdering.Count != InterfaceParams.Count)
            {
                throw new ArgumentException("Missmatch in Number of Parameters and expected amount in the given flux.");
            }
            this.InterfaceParams = InterfaceParams;

            this.Control = Control;
            int D = LSTrck.GridDat.SpatialDimension;

            //this.InterfaceValue = InterfaceValue;
            //InterfaceValue.Identification = "InterfaceValue";
            this.Extension = Extension;

            this.LevelSetTracker = LSTrck;
            Phi = LevelSetTracker.LevelSets[0] as LevelSet;
            this.LevelSetGradient = LevelSetGradient;

            switch (Control.FluxVariant)
            {
            case FluxVariant.GradientBased:
                // Flux Direction based on Mean Level Set Gradient
                MeanLevelSetGradient = new VectorField <SinglePhaseField>(
                    D.ForLoop(
                        d => new SinglePhaseField(
                            new Basis(LSTrck.GridDat, 0), VariableNames.MeanLevelSetGradientComponent(d)
                            )
                        )
                    );
                BulkParams = new List <DGField> {
                };
                BulkParams = ArrayTools.Cat(BulkParams, LevelSetGradient.ToArray(), Phi, MeanLevelSetGradient.ToArray(), InterfaceParams.ToArray());
                break;

            case FluxVariant.ValueBased:
                // Flux Direction Based on Cell-Averaged Level-Set Value
                MeanLevelSet = new SinglePhaseField(new Basis(LSTrck.GridDat, 0), "MeanLevelSet");
                BulkParams   = ArrayTools.Cat(LevelSetGradient.ToArray(), Phi, MeanLevelSet);
                break;

            case FluxVariant.SWIP:
                BulkParams = LevelSetGradient.ToArray();
                break;

            default:
                throw new NotImplementedException();
            }


            this.D = LevelSetTracker.GridDat.SpatialDimension;

            double PenaltyBase = Control.PenaltyMultiplierFlux * ((double)((Phi.Basis.Degree + 1) * (Phi.Basis.Degree + D))) / ((double)D);

            DefineBulkOperator(LSTrck, InterfaceFlux, D, PenaltyBase);

            Operator_interface = InterfaceFlux.XOperator(QuadOrderFunc.FixedOrder(2 * Extension.Basis.Degree + 2));
        }
Пример #3
0
        protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L)
        {
            Op = new XSpatialOperator(1, 0, 1, QuadOrderFunc.SumOfMaxDegrees(RoundUp: true), "u", "c1");

            Op.EquationComponents["c1"].Add(new DxFlux());                   // Flux in Bulk Phase;
            Op.EquationComponents["c1"].Add(new LevSetFlx_phi0(this.LsTrk)); // flux am lev-set 0
            Op.EquationComponents["c1"].Add(new LevSetFlx_phi1(this.LsTrk)); // flux am lev-set 1

            Op.Commit();
        }
Пример #4
0
        /// <summary>
        /// creates the spatial operator that consists only of component <paramref name="c"/>
        /// </summary>
        public static XSpatialOperator XOperator(this IEquationComponent c)
        {
            string[] Codomain = new string[] { "v1" };
            string[] Domain   = c.ArgumentOrdering.ToArray();
            string[] Param    = (c.ParameterOrdering != null) ? c.ParameterOrdering.ToArray() : new string[0];

            XSpatialOperator ret = new XSpatialOperator(Domain, Param, Codomain);

            ret.EquationComponents[Codomain[0]].Add(c);
            ret.Commit();

            return(ret);
        }
Пример #5
0
        protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L)
        {
            m_quadOrder = u1.Basis.Degree * 2;

            Op = new XSpatialOperator(2, 0, 2, (A, B, c) => m_quadOrder, "u1", "u2", "c1", "c2");

            Op.EquationComponents["c1"].Add(new DxFlux("u1", -3.0)); // Flux in Bulk Phase;
            Op.EquationComponents["c1"].Add(new LevSetFlx(this.LsTrk, "u1", -3.0));

            Op.EquationComponents["c2"].Add(new DxFlux("u1", +3.0)); // Flux in Bulk Phase;
            Op.EquationComponents["c2"].Add(new LevSetFlx(this.LsTrk, "u1", +3.0));
            Op.EquationComponents["c2"].Add(new DxFlux("u2", 77.7)); // Flux in Bulk Phase;
            Op.EquationComponents["c2"].Add(new LevSetFlx(this.LsTrk, "u2", 77.7));

            Op.Commit();
        }
 /// <summary>
 /// Legacy interface, preserved as static function.
 /// </summary>
 static public void ComputeMatrixEx <M, V>(
     this XSpatialOperator xOp,
     LevelSetTracker lsTrk,
     UnsetteledCoordinateMapping DomainMap, IList <DGField> Parameters, UnsetteledCoordinateMapping CodomainMap,
     M Matrix, V AffineOffset, bool OnlyAffine, double time, bool MPIParameterExchange,
     params SpeciesId[] whichSpc)
     where M : IMutableMatrixEx
     where V : IList <double> //
 {
     ComputeMatrixEx <M, V>(
         xOp,
         lsTrk,
         DomainMap, Parameters, CodomainMap,
         Matrix, AffineOffset,
         OnlyAffine, time, MPIParameterExchange, subGrid: null, whichSpc: whichSpc
         );
 }
Пример #7
0
        protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L)
        {
            int quadorder = this.u.Basis.Degree * 2 + 1;

            Op = new XSpatialOperator(1, 0, 1, (A, B, C) => quadorder, "u", "c1");

            var blkFlux = new DxFlux(this.LsTrk, alpha_A, alpha_B);

            Op.EquationComponents["c1"].Add(blkFlux);                                     // Flux in Bulk Phase;
            Op.EquationComponents["c1"].Add(new LevSetFlx(this.LsTrk, alpha_A, alpha_B)); // flux am lev-set 0

            Op.Commit();

            if (L == null)
            {
                TimeIntegration = new XdgBDFTimestepping(
                    new DGField[] { u }, new DGField[] { uResidual }, base.LsTrk,
                    true,
                    DelComputeOperatorMatrix, null, DelUpdateLevelset,
                    3, // BDF3
                       //-1, // Crank-Nicolson
                       //0, // Explicit Euler
                    LevelSetHandling.LieSplitting,
                    MassMatrixShapeandDependence.IsTimeDependent,
                    SpatialOperatorType.LinearTimeDependent,
                    MassScale,
                    MultigridOperatorConfig,
                    this.MultigridSequence,
                    this.LsTrk.SpeciesIdS.ToArray(),
                    quadorder,
                    this.THRESHOLD,
                    true,
                    this.Control.NonLinearSolver,
                    this.Control.LinearSolver);
            }
            else
            {
                Debug.Assert(object.ReferenceEquals(this.MultigridSequence[0].ParentGrid, this.GridData));
                TimeIntegration.DataRestoreAfterBalancing(L, new DGField[] { u }, new DGField[] { uResidual }, base.LsTrk, this.MultigridSequence);
            }
        }
 /// <summary>
 /// Legacy interface, preserved as static function.
 /// </summary>
 static public void ComputeMatrixEx <M, V>(
     this XSpatialOperator xOp,
     LevelSetTracker lsTrk,
     UnsetteledCoordinateMapping DomainMap, IList <DGField> Parameters, UnsetteledCoordinateMapping CodomainMap,
     M Matrix, V AffineOffset, bool OnlyAffine,
     double time, bool ParameterMPIExchange,
     IDictionary <SpeciesId, MultidimensionalArray> CellLengthScales,
     IDictionary <SpeciesId, MultidimensionalArray> InterfaceLengthScales, MultidimensionalArray SlipLengths,
     params SpeciesId[] whichSpc)
     where M : IMutableMatrixEx
     where V : IList <double> //
 {
     ComputeMatrixEx <M, V>(
         xOp,
         lsTrk,
         DomainMap, Parameters, CodomainMap,
         Matrix, AffineOffset, OnlyAffine, time,
         ParameterMPIExchange,
         CellLengthScales,
         InterfaceLengthScales, SlipLengths,
         null, whichSpc);
 }
        /// <summary>
        /// Legacy interface, preserved as static function.
        /// </summary>
        static public void ComputeMatrixEx <M, V>(
            this XSpatialOperator xOp,
            LevelSetTracker lsTrk,
            UnsetteledCoordinateMapping DomainMap, IList <DGField> Parameters, UnsetteledCoordinateMapping CodomainMap,
            M Matrix, V AffineOffset, bool OnlyAffine,
            double time,
            bool MPIParameterExchange,
            SubGrid subGrid, params SpeciesId[] whichSpc)
            where M : IMutableMatrixEx
            where V : IList <double>  //
        {
            Console.WriteLine("Warning: Legacy interface!");
            Console.WriteLine("         Usage of XDG without an agglomerated penalty!");


            int order = xOp.GetOrderFromQuadOrderFunction(DomainMap, Parameters, CodomainMap);
            MultiphaseCellAgglomerator dummy = lsTrk.GetAgglomerator(lsTrk.SpeciesIdS.ToArray(), order, 0.0);
            Dictionary <SpeciesId, MultidimensionalArray> Idummy = dummy.XDGSpaceMetrics.CutCellMetrics.InterfaceArea;


            var bla = new Dictionary <SpeciesId, XSpatialOperator.QrSchemPair>();

            foreach (var sp in whichSpc)
            {
                bla.Add(sp, new XSpatialOperator.QrSchemPair());
            }

            ComputeMatrixEx <M, V>(
                xOp,
                lsTrk,
                DomainMap, Parameters, CodomainMap,
                Matrix, AffineOffset,
                OnlyAffine, time, MPIParameterExchange, bla,
                dummy.CellLengthScales, Idummy, SubGrid: subGrid);

            Debug.Assert(dummy.TotalNumberOfAgglomerations <= 0, "internal error");
        }
Пример #10
0
        protected override void CreateEquationsAndSolvers(LoadbalData L)
        {
            Op = new XSpatialOperator(1, 0, 1, QuadOrderFunc.SumOfMaxDegrees(RoundUp: true), "u", "c1");

            var blkFlux = new DxFlux(this.LsTrk, Control.alpha_A, Control.alpha_B);

            Op.EquationComponents["c1"].Add(blkFlux);                                                     // Flux in Bulk Phase;
            Op.EquationComponents["c1"].Add(new LevSetFlx(this.LsTrk, Control.alpha_A, Control.alpha_B)); // flux am lev-set 0
            Op.OnIntegratingBulk += blkFlux.NowIntegratingBulk;

            Op.Commit();

            if (L == null)
            {
                TimeIntegration = new XdgBDFTimestepping(
                    new DGField[] { u }, new DGField[] { uResidual }, base.LsTrk,
                    true,
                    DelComputeOperatorMatrix, DelUpdateLevelset, DelUpdateCutCellMetrics,
                    3, // BDF3
                    //-1, // Crank-Nicolson
                    //0, // Explicit Euler
                    LevelSetHandling.LieSplitting,
                    MassMatrixShapeandDependence.IsTimeDependent,
                    SpatialOperatorType.LinearTimeDependent,
                    MassScale,
                    MultigridOperatorConfig,
                    this.MultigridSequence,
                    this.THRESHOLD,
                    true);
            }
            else
            {
                Debug.Assert(object.ReferenceEquals(this.MultigridSequence[0].ParentGrid, this.GridData));
                TimeIntegration.DataRestoreAfterBalancing(L, new DGField[] { u }, new DGField[] { uResidual }, base.LsTrk, this.MultigridSequence);
            }
        }
Пример #11
0
        protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L)
        {
            if (Operator != null)
            {
                return;
            }

            // create operator
            // ---------------

            Func <double[], double, double> S;

            switch (this.Control.InterfaceMode)
            {
            case InterfaceMode.MovingInterface:
                S = this.Control.S;
                break;

            case InterfaceMode.Splitting:
                S = (X, t) => 0.0;
                break;

            default:
                throw new NotImplementedException();
            }

            int quadOrder;

            if (this.Control.Eq == Equation.ScalarTransport)
            {
                quadOrder = this.LinearQuadratureDegree;

                Func <double[], double, double>[] uBnd = new Func <double[], double, double> [this.Grid.EdgeTagNames.Keys.Max() + 1];
                for (int iEdgeTag = 1; iEdgeTag < uBnd.Length; iEdgeTag++)
                {
                    string nameEdgeTag;
                    if (this.Grid.EdgeTagNames.TryGetValue((byte)iEdgeTag, out nameEdgeTag))
                    {
                        if (!this.Control.BoundaryValues[nameEdgeTag].Evaluators.TryGetValue("u", out uBnd[iEdgeTag]))
                        {
                            uBnd[iEdgeTag] = (X, t) => 0.0;
                        }
                    }
                }

                Operator = new XSpatialOperator(1, 2, 1, (A, B, C) => quadOrder, "u", "Vx", "Vy", "Cod1");
                Operator.EquationComponents["Cod1"].Add(new TranportFlux_Bulk()
                {
                    Inflow = uBnd
                });
                Operator.EquationComponents["Cod1"].Add(new TransportFlux_Interface(this.LsTrk, S));
                Operator.Commit();
            }
            else if (this.Control.Eq == Equation.HeatEq)
            {
                quadOrder = this.LinearQuadratureDegree;

                Operator = new XSpatialOperator(1, 0, 1, (A, B, C) => quadOrder, "u", "Cod1");

                var bulkFlx = new HeatFlux_Bulk()
                {
                    m_muA = this.Control.muA, m_muB = this.Control.muB, m_rhsA = this.Control.rhsA, m_rhsB = this.Control.rhsB
                };
                var intfFlx = new HeatFlux_Interface(this.LsTrk, S)
                {
                    m_muA = this.Control.muA, m_muB = this.Control.muB
                };

                Operator.EquationComponents["Cod1"].Add(bulkFlx);
                Operator.EquationComponents["Cod1"].Add(intfFlx);
                Operator.Commit();
            }
            else if (this.Control.Eq == Equation.Burgers)
            {
                quadOrder = this.NonlinearQuadratureDegree;

                Operator = new XSpatialOperator(1, 1, 1, (A, B, C) => quadOrder, "u", "u0", "Cod1");
                Operator.EquationComponents["Cod1"].Add(new BurgersFlux_Bulk()
                {
                    Direction = this.Control.BurgersDirection, Inflow = this.Control.u_Ex
                });
                Operator.EquationComponents["Cod1"].Add(new BurgersFlux_Interface(this.LsTrk, S, this.Control.BurgersDirection));
                Operator.Commit();
            }
            else
            {
                throw new NotImplementedException();
            }

            // create timestepper
            // ------------------

            LevelSetHandling lsh;

            switch (this.Control.InterfaceMode)
            {
            case InterfaceMode.MovingInterface:
                lsh = LevelSetHandling.Coupled_Once;
                break;

            case InterfaceMode.Splitting:
                lsh = LevelSetHandling.LieSplitting;
                break;

            default:
                throw new NotImplementedException();
            }

            RungeKuttaScheme rksch = null;
            int bdfOrder           = -1000;

            if (this.Control.TimeSteppingScheme == TimeSteppingScheme.CrankNicolson)
            {
                bdfOrder = -1;
            }
            else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.ExplicitEuler)
            {
                bdfOrder = 0;
            }
            else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.ImplicitEuler)
            {
                bdfOrder = 1;
            }
            else if (this.Control.TimeSteppingScheme.ToString().StartsWith("BDF"))
            {
                bdfOrder = Convert.ToInt32(this.Control.TimeSteppingScheme.ToString().Substring(3));
            }
            else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.RK1)
            {
                rksch = RungeKuttaScheme.ExplicitEuler;
            }
            else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.RK1u1)
            {
                rksch = RungeKuttaScheme.ExplicitEuler2;
            }
            else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.RK2)
            {
                rksch = RungeKuttaScheme.Heun2;
            }
            else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.RK3)
            {
                rksch = RungeKuttaScheme.TVD3;
            }
            else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.RK4)
            {
                rksch = RungeKuttaScheme.RungeKutta1901;
            }
            else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.RK_ImplicitEuler)
            {
                rksch = RungeKuttaScheme.ImplicitEuler;
            }
            else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.RK_CrankNic)
            {
                rksch = RungeKuttaScheme.CrankNicolson;
            }
            else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.RK_IMEX3)
            {
                rksch = RungeKuttaScheme.IMEX3;
            }
            else
            {
                throw new NotImplementedException();
            }


            if (bdfOrder > -1000)
            {
                m_BDF_Timestepper = new XdgBDFTimestepping(new DGField[] { this.u }, new DGField[] { this.Residual }, LsTrk, true,
                                                           DelComputeOperatorMatrix, DelUpdateLevelset,
                                                           bdfOrder,
                                                           lsh,
                                                           MassMatrixShapeandDependence.IsTimeDependent,
                                                           SpatialOperatorType.LinearTimeDependent,
                                                           MassScale,
                                                           null, base.MultigridSequence,
                                                           this.LsTrk.SpeciesIdS.ToArray(), quadOrder,
                                                           this.Control.AgglomerationThreshold, false);
            }
            else
            {
                m_RK_Timestepper = new XdgRKTimestepping(new DGField[] { this.u }, new DGField[] { this.Residual }, LsTrk,
                                                         DelComputeOperatorMatrix, DelUpdateLevelset,
                                                         rksch,
                                                         lsh,
                                                         MassMatrixShapeandDependence.IsTimeDependent,
                                                         SpatialOperatorType.LinearTimeDependent,
                                                         MassScale,
                                                         null, base.MultigridSequence,
                                                         this.LsTrk.SpeciesIdS.ToArray(), quadOrder,
                                                         this.Control.AgglomerationThreshold, false);
            }
        }
Пример #12
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;
            }
        }
Пример #13
0
        public OperatorFactory(
            OperatorConfiguration config,
            LevelSetTracker _LsTrk,
            int _HMFdegree,
            int degU,
            IncompressibleMultiphaseBoundaryCondMap BcMap,
            bool _movingmesh,
            bool _evaporation,
            bool _staticInt)
        {
            // variable names
            // ==============
            D          = _LsTrk.GridDat.SpatialDimension;
            this.LsTrk = _LsTrk;
            //this.momentFittingVariant = momentFittingVariant;
            this.HMFDegree           = _HMFdegree;
            this.dntParams           = config.dntParams.CloneAs();
            this.physParams          = config.physParams.CloneAs();
            this.UseExtendedVelocity = config.UseXDG4Velocity;
            this.movingmesh          = _movingmesh;
            this.evaporation         = _evaporation;

            // test input
            // ==========
            {
                if (config.DomBlocks.GetLength(0) != 2 || config.CodBlocks.GetLength(0) != 2)
                {
                    throw new ArgumentException();
                }
                if (config.physParams.mu_A == 0.0 && config.physParams.mu_B == 0.0)
                {
                    muIs0 = true;
                }
                else
                {
                    if (config.physParams.mu_A <= 0)
                    {
                        throw new ArgumentException();
                    }
                    if (config.physParams.mu_B <= 0)
                    {
                        throw new ArgumentException();
                    }
                }

                if (config.physParams.rho_A <= 0)
                {
                    throw new ArgumentException();
                }
                if (config.physParams.rho_B <= 0)
                {
                    throw new ArgumentException();
                }

                if (_LsTrk.SpeciesNames.Count != 2)
                {
                    throw new ArgumentException();
                }
                if (!(_LsTrk.SpeciesNames.Contains("A") && _LsTrk.SpeciesNames.Contains("B")))
                {
                    throw new ArgumentException();
                }
            }


            // full operator:
            CodName = ((new string[] { "momX", "momY", "momZ" }).GetSubVector(0, D)).Cat("div");
            Params  = ArrayTools.Cat(
                VariableNames.Velocity0Vector(D),
                VariableNames.Velocity0MeanVector(D),
                "Curvature",
                (new string[] { "surfForceX", "surfForceY", "surfForceZ" }).GetSubVector(0, D),
                (new string[] { "NX", "NY", "NZ" }).GetSubVector(0, D),
                (new string[] { "GradTempX", "GradTempY", "GradTempZ" }.GetSubVector(0, D)),
                VariableNames.Temperature,
                "DisjoiningPressure");
            DomName = ArrayTools.Cat(VariableNames.VelocityVector(D), VariableNames.Pressure);

            // selected part:
            if (config.CodBlocks[0])
            {
                CodNameSelected = ArrayTools.Cat(CodNameSelected, CodName.GetSubVector(0, D));
            }
            if (config.CodBlocks[1])
            {
                CodNameSelected = ArrayTools.Cat(CodNameSelected, CodName.GetSubVector(D, 1));
            }

            if (config.DomBlocks[0])
            {
                DomNameSelected = ArrayTools.Cat(DomNameSelected, DomName.GetSubVector(0, D));
            }
            if (config.DomBlocks[1])
            {
                DomNameSelected = ArrayTools.Cat(DomNameSelected, DomName.GetSubVector(D, 1));
            }

            muA   = config.physParams.mu_A;
            muB   = config.physParams.mu_B;
            rhoA  = config.physParams.rho_A;
            rhoB  = config.physParams.rho_B;
            sigma = config.physParams.Sigma;

            MatInt = !evaporation;

            double kA    = 0.0;
            double kB    = 0.0;
            double hVapA = 0.0;
            double hVapB = 0.0;

            double Tsat  = 0.0;
            double R_int = 0.0;
            double p_c   = 0.0;

            if (evaporation)
            {
                kA    = config.thermParams.k_A;
                kB    = config.thermParams.k_B;
                hVapA = config.thermParams.hVap_A;
                hVapB = config.thermParams.hVap_B;

                Tsat = config.thermParams.T_sat;
                p_c  = config.thermParams.pc;
                //double T_intMin = 0.0;
                double f = config.thermParams.fc;
                double R = config.thermParams.Rc;
                //double pc = config.thermParams.pc;

                if (config.thermParams.hVap_A > 0 && config.thermParams.hVap_B < 0)
                {
                    R_int = ((2.0 - f) / (2 * f)) * Tsat * Math.Sqrt(2 * Math.PI * R * Tsat) / (rhoB * hVapA.Pow2());
                    //T_intMin = Tsat * (1 + (pc / (rhoA * hVapA.Pow2())));
                }
                else if (config.thermParams.hVap_A < 0 && config.thermParams.hVap_B > 0)
                {
                    R_int = ((2.0 - f) / (2 * f)) * Tsat * Math.Sqrt(2 * Math.PI * R * Tsat) / (rhoA * hVapB.Pow2());
                    //T_intMin = Tsat * (1 + (pc / (rhoB * hVapB.Pow2())));
                }
                this.CurvatureRequired = true;
            }



            //if (!MatInt)
            //    throw new NotSupportedException("Non-Material interface is NOT tested!");

            // create Operator
            // ===============
            m_OP = new XSpatialOperator(DomNameSelected, Params, CodNameSelected, (A, B, C) => _HMFdegree);

            // build the operator
            // ==================
            {
                // Momentum equation
                // =================

                if (config.physParams.IncludeConvection && config.Transport)
                {
                    for (int d = 0; d < D; d++)
                    {
                        var comps = m_OP.EquationComponents[CodName[d]];

                        // convective part:
                        // variante 1:

                        double LFFA = config.dntParams.LFFA;
                        double LFFB = config.dntParams.LFFB;


                        var conv = new Operator.Convection.ConvectionInBulk_LLF(D, BcMap, d, rhoA, rhoB, LFFA, LFFB, LsTrk);
                        comps.Add(conv);                                                                                                                                 // Bulk component

                        comps.Add(new Operator.Convection.ConvectionAtLevelSet_LLF(d, D, LsTrk, rhoA, rhoB, LFFA, LFFB, config.physParams.Material, BcMap, movingmesh)); // LevelSet component
                        //comps.Add(new Operator.Convection.ConvectionAtLevelSet_weightedLLF(d, D, LsTrk, rhoA, rhoB, LFFA, LFFB, BcMap, movingmesh));       // LevelSet component

                        if (evaporation)
                        {
                            //comps.Add(new Operator.Convection.ConvectionAtLevelSet_Divergence(d, D, LsTrk, rhoA, rhoB, config.dntParams.ContiSign, config.dntParams.RescaleConti, kA, kB, hVapA, R_int, Tsat, sigma, p_c));
                            //comps.Add(new Operator.Convection.ConvectionAtLevelSet_nonMaterialLLF(d, D, LsTrk, rhoA, rhoB, kA, kB, hVapA, R_int, Tsat, sigma, p_c));
                            //comps.Add(new Operator.Convection.ConvectionAtLevelSet_nonMaterial(d, D, LsTrk, rhoA, rhoB, kA, kB, hVapA, R_int, Tsat, sigma, p_c));
                        }

                        // variante 3:
                        //var convA = new LocalConvection(D, d, rhoA, rhoB, this.config.varMode, LsTrk);
                        //XOP.OnIntegratingBulk += convA.SetParameter;
                        //comps.Add(convA);
                        //////var convB = new LocalConvection2(D, d, rhoA, rhoB, varMode, LsTrk); // macht Bum-Bum!
                        ////XOP.OnIntegratingBulk += convB.SetParameter;
                        ////comps.Add(convB);
                    }

                    this.U0meanrequired = true;
                }

                // pressure gradient
                // =================

                if (config.PressureGradient)
                {
                    for (int d = 0; d < D; d++)
                    {
                        var comps = m_OP.EquationComponents[CodName[d]];


                        var pres = new Operator.Pressure.PressureInBulk(d, BcMap);
                        comps.Add(pres);

                        //if (!MatInt)
                        //    throw new NotSupportedException("New Style pressure coupling does not support non-material interface.");
                        var presLs = new Operator.Pressure.PressureFormAtLevelSet(d, D, LsTrk); //, dntParams.UseWeightedAverages, muA, muB);
                        comps.Add(presLs);

                        //if (evaporation) {
                        //    var presLSGen = new Operator.Pressure.GeneralizedPressureFormAtLevelSet(d, D, LsTrk, config.thermParams.p_sat, hVapA);
                        //    comps.Add(presLSGen);
                        //}
                    }
                }

                // viscous operator
                // ================

                if (config.Viscous && !muIs0)
                {
                    for (int d = 0; d < D; d++)
                    {
                        var comps = m_OP.EquationComponents[CodName[d]];
                        // viscous part:
                        //double _D = D;
                        //double penalty_mul = dntParams.PenaltySafety;
                        //double _p = degU;
                        //double penalty_base = (_p + 1) * (_p + _D) / _D;
                        //double penalty = penalty_base * penalty_mul;
                        double penalty = dntParams.PenaltySafety;
                        switch (dntParams.ViscosityMode)
                        {
                        case ViscosityMode.Standard: {
                            // Bulk operator:
                            var Visc = new Operator.Viscosity.ViscosityInBulk_GradUTerm(
                                dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0,
                                BcMap, d, D, muA, muB);         // , _betaA: this.physParams.betaS_A, _betaB: this.physParams.betaS_B);

                            comps.Add(Visc);

                            if (dntParams.UseGhostPenalties)
                            {
                                var ViscPenalty = new Operator.Viscosity.ViscosityInBulk_GradUTerm(penalty * 1.0, 0.0, BcMap, d, D, muA, muB);
                                m_OP.GhostEdgesOperator.EquationComponents[CodName[d]].Add(ViscPenalty);
                            }
                            // Level-Set operator:
                            comps.Add(new Operator.Viscosity.ViscosityAtLevelSet_Standard(LsTrk, muA, muB, penalty * 1.0, d, true));

                            break;
                        }

                        case ViscosityMode.TransposeTermMissing: {
                            // Bulk operator:
                            var Visc = new Operator.Viscosity.ViscosityInBulk_GradUTerm(
                                dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0,
                                BcMap, d, D, muA, muB);
                            comps.Add(Visc);

                            if (dntParams.UseGhostPenalties)
                            {
                                var ViscPenalty = new Operator.Viscosity.ViscosityInBulk_GradUTerm(penalty * 1.0, 0.0, BcMap, d, D, muA, muB);
                                m_OP.GhostEdgesOperator.EquationComponents[CodName[d]].Add(ViscPenalty);
                            }
                            // Level-Set operator:
                            comps.Add(new Operator.Viscosity.ViscosityAtLevelSet_Standard(LsTrk, muA, muB, penalty * 1.0, d, false));

                            break;
                        }

                        case ViscosityMode.ExplicitTransformation: {
                            // Bulk operator
                            var Visc = new Operator.Viscosity.ViscosityInBulk_GradUTerm(
                                dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0,
                                BcMap, d, D, muA, muB);
                            comps.Add(Visc);
                            if (dntParams.UseGhostPenalties)
                            {
                                var ViscPenalty = new Operator.Viscosity.ViscosityInBulk_GradUTerm(penalty * 1.0, 0.0, BcMap, d, D, muA, muB);
                                m_OP.GhostEdgesOperator.EquationComponents[CodName[d]].Add(ViscPenalty);
                            }

                            //Level-Set operator:
                            //comps.Add(new Operator.Viscosity.ViscosityAtLevelSet_Explicit(d, D, LsTrk, penalty, muA, muB));
                            throw new NotSupportedException("Beim refact rausgeflogen, braucht eh kein Mensch. fk, 08jan16.");

                            //break;
                        }

                        case ViscosityMode.FullySymmetric: {
                            // Bulk operator
                            var Visc1 = new Operator.Viscosity.ViscosityInBulk_GradUTerm(
                                dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0,
                                BcMap, d, D, muA, muB, _betaA: this.physParams.betaS_A, _betaB: this.physParams.betaS_B);
                            var Visc2 = new Operator.Viscosity.ViscosityInBulk_GradUtranspTerm(
                                dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0,
                                BcMap, d, D, muA, muB, _betaA: this.physParams.betaS_A, _betaB: this.physParams.betaS_B);
                            //var Visc3 = new Operator.Viscosity.ViscosityInBulk_divTerm(dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0, BcMap, d, D, muA, muB);


                            comps.Add(Visc1);
                            comps.Add(Visc2);
                            //comps.Add(Visc3);

                            if (dntParams.UseGhostPenalties)
                            {
                                var Visc1Penalty = new Operator.Viscosity.ViscosityInBulk_GradUTerm(
                                    penalty, 0.0,
                                    BcMap, d, D, muA, muB);
                                var Visc2Penalty = new Operator.Viscosity.ViscosityInBulk_GradUtranspTerm(
                                    penalty, 0.0,
                                    BcMap, d, D, muA, muB);
                                //var Visc3Penalty = new Operator.Viscosity.ViscosityInBulk_divTerm(
                                //    penalty, 0.0,
                                //    BcMap, d, D, muA, muB);
                                //m_OP.OnIntegratingBulk += Visc3Penalty.SetParameter;
                                m_OP.GhostEdgesOperator.EquationComponents[CodName[d]].Add(Visc1Penalty);
                                m_OP.GhostEdgesOperator.EquationComponents[CodName[d]].Add(Visc2Penalty);
                                //m_OP.AndresHint.EquationComponents[CodName[d]].Add(Visc3Penalty);
                            }

                            // Level-Set operator
                            comps.Add(new Operator.Viscosity.ViscosityAtLevelSet_FullySymmetric(LsTrk, muA, muB, penalty, d, _staticInt, dntParams.UseWeightedAverages));

                            if (this.evaporation)
                            {
                                comps.Add(new Operator.Viscosity.GeneralizedViscosityAtLevelSet_FullySymmetric(LsTrk, muA, muB, penalty, d, rhoA, rhoB, kA, kB, hVapA, R_int, Tsat, sigma, p_c));
                            }

                            break;
                        }

                        default:
                            throw new NotImplementedException();
                        }
                    }
                }

                // Continuum equation
                // ==================

                if (config.continuity)
                {
                    for (int d = 0; d < D; d++)
                    {
                        var src = new Operator.Continuity.DivergenceInBulk_Volume(d, D, rhoA, rhoB, config.dntParams.ContiSign, config.dntParams.RescaleConti);
                        var flx = new Operator.Continuity.DivergenceInBulk_Edge(d, BcMap, rhoA, rhoB, config.dntParams.ContiSign, config.dntParams.RescaleConti);
                        m_OP.EquationComponents["div"].Add(flx);
                        m_OP.EquationComponents["div"].Add(src);
                    }

                    var divPen = new Operator.Continuity.DivergenceAtLevelSet(D, LsTrk, rhoA, rhoB, MatInt, config.dntParams.ContiSign, config.dntParams.RescaleConti, _staticInt); //, dntParams.UseWeightedAverages, muA, muB);
                    m_OP.EquationComponents["div"].Add(divPen);

                    if (evaporation)
                    {
                        var divPenGen = new Operator.Continuity.GeneralizedDivergenceAtLevelSet(D, LsTrk, rhoA, rhoB, config.dntParams.ContiSign, config.dntParams.RescaleConti, kA, kB, hVapA, R_int, Tsat, sigma, p_c);
                        m_OP.EquationComponents["div"].Add(divPenGen);
                    }

                    //// pressure stabilization
                    //if (this.config.PressureStab) {
                    //    Console.WriteLine("Pressure Stabilization active.");
                    //var pStabi = new PressureStabilization(0.0001, 0.0001);
                    //    m_OP.OnIntegratingBulk += pStabi.SetParameter;
                    //    m_OP.EquationComponents["div"].Add(pStabi);
                    ////var pStabiLS = new PressureStabilizationAtLevelSet(D, LsTrk, rhoA, muA, rhoB, muB, sigma, this.config.varMode, MatInt);
                    //    //XOP.EquationComponents["div"].Add(pStabiLS);
                    //} else {
                    //    Console.WriteLine("Pressure Stabilization INACTIVE.");
                    //}
                }

                // surface tension
                // ===============

                if (config.PressureGradient && config.physParams.Sigma != 0.0)
                {
                    // isotropic part of the surface stress tensor
                    if (config.dntParams.SST_isotropicMode == SurfaceStressTensor_IsotropicMode.LaplaceBeltrami_Flux ||
                        config.dntParams.SST_isotropicMode == SurfaceStressTensor_IsotropicMode.LaplaceBeltrami_Local ||
                        config.dntParams.SST_isotropicMode == SurfaceStressTensor_IsotropicMode.LaplaceBeltrami_ContactLine)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            if (config.dntParams.SST_isotropicMode != SurfaceStressTensor_IsotropicMode.LaplaceBeltrami_ContactLine)
                            {
                                IEquationComponent G = new SurfaceTension_LaplaceBeltrami_Surface(d, config.physParams.Sigma * 0.5);
                                IEquationComponent H = new SurfaceTension_LaplaceBeltrami_BndLine(d, config.physParams.Sigma * 0.5, config.dntParams.SST_isotropicMode == SurfaceStressTensor_IsotropicMode.LaplaceBeltrami_Flux);
                                m_OP.SurfaceElementOperator.EquationComponents[CodName[d]].Add(G);
                                m_OP.SurfaceElementOperator.EquationComponents[CodName[d]].Add(H);
                            }
                            else
                            {
                                //G = new SurfaceTension_LaplaceBeltrami2_Surface(d, config.physParams.Sigma * 0.5);
                                //H = new SurfaceTension_LaplaceBeltrami2_BndLine(d, config.physParams.Sigma * 0.5, config.physParams.Theta_e, config.physParams.betaL);
                                IEquationComponent isoSurfT = new IsotropicSurfaceTension_LaplaceBeltrami(d, D, config.physParams.Sigma * 0.5, BcMap.EdgeTag2Type, BcMap, config.physParams.theta_e, config.physParams.betaL, _staticInt);
                                m_OP.SurfaceElementOperator.EquationComponents[CodName[d]].Add(isoSurfT);
                            }
                        }

                        this.NormalsRequired = true;
                    }
                    else if (config.dntParams.SST_isotropicMode == SurfaceStressTensor_IsotropicMode.Curvature_Projected ||
                             config.dntParams.SST_isotropicMode == SurfaceStressTensor_IsotropicMode.Curvature_ClosestPoint ||
                             config.dntParams.SST_isotropicMode == SurfaceStressTensor_IsotropicMode.Curvature_LaplaceBeltramiMean ||
                             config.dntParams.SST_isotropicMode == SurfaceStressTensor_IsotropicMode.Curvature_Fourier)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            m_OP.EquationComponents[CodName[d]].Add(new CurvatureBasedSurfaceTension(d, D, LsTrk, config.physParams.Sigma));
                        }

                        this.CurvatureRequired = true;

                        /*
                         * Console.WriteLine("REM: hack in Operator factory");
                         * for(int d = 0; d < D; d++) {
                         *  //var G = new SurfaceTension_LaplaceBeltrami_Surface(d, config.physParams.Sigma * 0.5);
                         *  var H = new SurfaceTension_LaplaceBeltrami_BndLine(d, config.physParams.Sigma * 0.5, config.dntParams.surfTensionMode == SurfaceTensionMode.LaplaceBeltrami_Flux);
                         *
                         *  //m_OP.SurfaceElementOperator.EquationComponents[CodName[d]].Add(G);
                         *  m_OP.SurfaceElementOperator.EquationComponents[CodName[d]].Add(H);
                         * }
                         *
                         * this.NormalsRequired = true;
                         */
                    }
                    else
                    {
                        throw new NotImplementedException("Not implemented.");
                    }


                    // dynamic part
                    if (config.dntParams.SurfStressTensor != SurfaceSressTensor.Isotropic)
                    {
                        double muI  = config.physParams.mu_I;
                        double lamI = config.physParams.lambda_I;

                        double penalty_base = (degU + 1) * (degU + D) / D;
                        double penalty      = penalty_base * dntParams.PenaltySafety;

                        // surface shear viscosity
                        if (config.dntParams.SurfStressTensor == SurfaceSressTensor.SurfaceRateOfDeformation ||
                            config.dntParams.SurfStressTensor == SurfaceSressTensor.SemiImplicit ||
                            config.dntParams.SurfStressTensor == SurfaceSressTensor.FullBoussinesqScriven)
                        {
                            for (int d = 0; d < D; d++)
                            {
                                var surfDeformRate = new BoussinesqScriven_SurfaceDeformationRate_GradU(d, muI * 0.5, penalty);
                                m_OP.SurfaceElementOperator.EquationComponents[CodName[d]].Add(surfDeformRate);
                                //m_OP.OnIntegratingSurfaceElement += surfDeformRate.SetParameter;

                                if (config.dntParams.SurfStressTensor != SurfaceSressTensor.SemiImplicit)
                                {
                                    var surfDeformRateT = new BoussinesqScriven_SurfaceDeformationRate_GradUTranspose(d, muI * 0.5, penalty);
                                    m_OP.SurfaceElementOperator.EquationComponents[CodName[d]].Add(surfDeformRateT);
                                    //m_OP.OnIntegratingSurfaceElement += surfDeformRateT.SetParameter;
                                }
                            }
                        }
                        // surface dilatational viscosity
                        if (config.dntParams.SurfStressTensor == SurfaceSressTensor.SurfaceVelocityDivergence ||
                            config.dntParams.SurfStressTensor == SurfaceSressTensor.FullBoussinesqScriven)
                        {
                            for (int d = 0; d < D; d++)
                            {
                                var surfVelocDiv = new BoussinesqScriven_SurfaceVelocityDivergence(d, muI * 0.5, lamI * 0.5, penalty, BcMap.EdgeTag2Type);
                                m_OP.SurfaceElementOperator.EquationComponents[CodName[d]].Add(surfVelocDiv);
                                //m_OP.OnIntegratingSurfaceElement += surfVelocDiv.SetParameter;
                            }
                        }
                    }


                    // stabilization
                    if (config.dntParams.UseLevelSetStabilization)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            m_OP.EquationComponents[CodName[d]].Add(new LevelSetStabilization(d, D, LsTrk));
                        }
                    }
                }


                // surface force term
                // ==================


                if (config.PressureGradient && config.physParams.useArtificialSurfaceForce)
                {
                    for (int d = 0; d < D; d++)
                    {
                        m_OP.EquationComponents[CodName[d]].Add(new SurfaceTension_ArfForceSrc(d, D, LsTrk));
                    }
                }


                // evaporation (mass flux)
                // =======================

                if (evaporation)
                {
                    for (int d = 0; d < D; d++)
                    {
                        m_OP.EquationComponents[CodName[d]].Add(new Operator.DynamicInterfaceConditions.MassFluxAtInterface(d, D, LsTrk, rhoA, rhoB, kA, kB, hVapA, R_int, Tsat, sigma, p_c));
                    }
                }
            }

            // Finalize
            // ========

            m_OP.Commit();
        }
Пример #14
0
        /// <summary>
        /// ctor.
        /// </summary>
        internal LECQuadratureLevelSet(IGridData context,
                                       XSpatialOperator DiffOp,
                                       M Matrix, V OffsetVec,
                                       UnsetteledCoordinateMapping RowMap, IList <DGField> ParamsMap, UnsetteledCoordinateMapping ColMap,
                                       LevelSetTracker lsTrk, int _iLevSet, ICollection <SpeciesId> SpeciesPair,
                                       ICompositeQuadRule <QuadRule> domAndRule,
                                       IDictionary <SpeciesId, MultidimensionalArray> __LenScales) //
            : base(new int[] { RowMap.MaxTotalNoOfCoordinatesPerCell, 1 + ((Matrix == null) ? 0 : ColMap.MaxTotalNoOfCoordinatesPerCell) },
                   context,
                   domAndRule) //
        {
            // ------------------
            // init custom timers
            // ------------------

            base.CustomTimers             = new Stopwatch[] { new Stopwatch(), new Stopwatch(), new Stopwatch(), new Stopwatch() };
            base.CustomTimers_Names       = new string[] { "Flux-Eval", "Basis-Eval", "Loops", "ParametersAndNormals" };
            base.CustomTimers_RootPointer = new int[4];
            ArrayTools.SetAll(base.CustomTimers_RootPointer, -1);

            // -----------------------------------
            // set members / check ctor parameters
            // -----------------------------------

            m_RowMap     = RowMap;
            m_ColMap     = ColMap;
            m_Parameters = (ParamsMap != null) ? ParamsMap.ToArray() : new DGField[0];
            m_LenScales  = __LenScales;


            if (m_RowMap.BasisS.Count != DiffOp.CodomainVar.Count)
            {
                throw new ArgumentException("mismatch between number of codomain variables in spatial operator and row mapping");
            }
            if (m_ColMap.BasisS.Count != DiffOp.DomainVar.Count)
            {
                throw new ArgumentException("mismatch between number of domain variables in spatial operator and column mapping");
            }
            if (m_Parameters.Length != DiffOp.ParameterVar.Count)
            {
                throw new ArgumentException("mismatch between number of parameter variables in spatial operator and given parameters");
            }

            int Gamma = m_RowMap.BasisS.Count;

            m_lsTrk = lsTrk;

            if (Matrix != null && (Matrix.RowPartitioning.LocalLength != RowMap.LocalLength))
            {
                throw new ArgumentException("mismatch between matrix number of rows and row mapping.");
            }
            if (Matrix != null && (Matrix.ColPartition.LocalLength != ColMap.LocalLength))
            {
                throw new ArgumentException("mismatch between matrix number of columns and column mapping.");
            }

            this.m_LevSetIdx = _iLevSet;

            this.OperatorMatrix = Matrix;
            this.OperatorAffine = OffsetVec;
            this.m_SpeciesPair  = SpeciesPair;

            // ------------------------
            // sort equation components
            // ------------------------

            //m_BiLinForms = DiffOp.GetArgMapping<IBilinearForm>(true, Compfilter<IBilinearForm>);
            //m_2ndDerivFlux = DiffOp.GetArgMapping<ILinear2ndDerivativeCouplingFlux>(true, Compfilter<ILinear2ndDerivativeCouplingFlux>);

            m_LsForm_UxV = DiffOp.GetArgMapping <ILinearLevelSetComponent_UxV>(true,
                                                                               eq => ((eq.LevelSetTerms & TermActivationFlags.UxV) != 0) && Compfilter(eq),
                                                                               eq => (eq is ILevelSetComponent) ? new LinearLevelSetComponentVectorizer(lsTrk, (ILevelSetComponent)eq) : null);
            m_LsForm_GradUxV = DiffOp.GetArgMapping <ILinearLevelSetComponent_GradUxV>(true,
                                                                                       eq => ((eq.LevelSetTerms & TermActivationFlags.GradUxV) != 0) && Compfilter(eq),
                                                                                       eq => (eq is ILevelSetComponent) ? new LinearLevelSetComponentVectorizer(lsTrk, (ILevelSetComponent)eq) : null);
            m_LsForm_UxGradV = DiffOp.GetArgMapping <ILinearLevelSetComponent_UxGradV>(true,
                                                                                       eq => ((eq.LevelSetTerms & TermActivationFlags.UxGradV) != 0) && Compfilter(eq),
                                                                                       eq => (eq is ILevelSetComponent) ? new LinearLevelSetComponentVectorizer(lsTrk, (ILevelSetComponent)eq) : null);
            m_LsForm_GradUxGradV = DiffOp.GetArgMapping <ILinearLevelSetComponent_GradUxGradV>(true,
                                                                                               eq => ((eq.LevelSetTerms & TermActivationFlags.GradUxGradV) != 0) && Compfilter(eq),
                                                                                               eq => (eq is ILevelSetComponent) ? new LinearLevelSetComponentVectorizer(lsTrk, (ILevelSetComponent)eq) : null);
            m_LsForm_V = DiffOp.GetArgMapping <ILinearLevelSetComponent_V>(true,
                                                                           eq => ((eq.LevelSetTerms & TermActivationFlags.V) != 0 && Compfilter(eq)),
                                                                           eq => (eq is ILevelSetComponent) ? new LinearLevelSetComponentVectorizer(lsTrk, (ILevelSetComponent)eq) : null);
            m_LsForm_GradV = DiffOp.GetArgMapping <ILinearLevelSetComponent_GradV>(true,
                                                                                   eq => ((eq.LevelSetTerms & TermActivationFlags.GradV) != 0) && Compfilter(eq),
                                                                                   eq => (eq is ILevelSetComponent) ? new LinearLevelSetComponentVectorizer(lsTrk, (ILevelSetComponent)eq) : null);

            // -----
            // alloc
            // -----

            AllocEmpty(m_LsForm_UxV, out Koeff_UxV, out Sum_Koeff_UxV, 5, false);
            AllocEmpty(m_LsForm_GradUxV, out Koeff_NablaUxV, out Sum_Koeff_NablaUxV, 6, false);
            AllocEmpty(m_LsForm_UxGradV, out Koeff_UxNablaV, out Sum_Koeff_UxNablaV, 6, false);
            AllocEmpty(m_LsForm_GradUxGradV, out Koeff_NablaUxNablaV, out Sum_Koeff_NablaUxNablaV, 7, false);

            AllocEmpty(m_LsForm_V, out Koeff_V, out Sum_Koeff_V, 3, true);
            AllocEmpty(m_LsForm_GradV, out Koeff_NablaV, out Sum_Koeff_NablaV, 4, true);
        }
Пример #15
0
        /// <summary>
        /// Based on the Ideas by
        /// C. Basting and D. Kuzmin,
        /// “A minimization-based finite element formulation for interface-preserving level set reinitialization”,
        /// Computing, vol. 95, no. 1, pp. 13–25, Dec. 2012.
        /// Create Spatial Operators and build the corresponding Matrices
        /// For the Left-Hand Side of the ReInitProblem
        /// RHS is computed on the fly in <see cref="ReInitSingleStep"/>
        /// The Bulk component is constant unless the grid changes, thus it is computed in <see cref="BuildOperators(CellQuadratureScheme)"/>.
        /// The Interface component changes with its motion.
        /// This component is calculated in <see cref="UpdateOperators(CellQuadratureScheme)"/>.
        /// </summary>
        /// <param name="LSTrck"></param>
        /// <param name="Control">various parameters <paramref name="EllipticReinitControl"/></param>
        /// <param name="HMFOrder">order of tghe interface quadrature</param>
        public EllipticReInit(LevelSetTracker LSTrck, EllipticReInitAlgoControl Control, SinglePhaseField LevelSetForReInit = null)
        {
            this.Control         = Control;
            this.LevelSetTracker = LSTrck;
            if (LevelSetForReInit == null)
            {
                Phi = LevelSetTracker.LevelSets[0] as SinglePhaseField;
            }
            else
            {
                Phi = LevelSetForReInit;
            }
            this.underrelaxation = Control.underrelaxation;

            Residual = new SinglePhaseField(Phi.Basis);
            OldPhi   = new SinglePhaseField(Phi.Basis);
            NewPhi   = new SinglePhaseField(Phi.Basis);
            foreach (SinglePhaseField f in new List <SinglePhaseField> {
                Residual, OldPhi, NewPhi
            })
            {
                f.Clear();
                f.Acc(1.0, Phi);
            }


            this.D = LevelSetTracker.GridDat.SpatialDimension;

            this.ConvergenceCriterion = Control.ConvergenceCriterion;
            this.MaxIteration         = Control.MaxIt;

            double PenaltyBase = ((double)((Phi.Basis.Degree + 1) * (Phi.Basis.Degree + D))) / ((double)D);


            /// Choose Forms according to Upwinding or Central Fluxes
            string[] paramNames;
            int      noOfParamFields;

            IEquationComponent BulkForm;
            RHSForm            myRHSForm;

            LevelSetGradient     = new VectorField <SinglePhaseField>(D, Phi.Basis, "LevelSetGradient", SinglePhaseField.Factory);
            MeanLevelSetGradient = new VectorField <SinglePhaseField>(D, new Basis(Phi.GridDat, 0), "MeanLevelSetGradient", SinglePhaseField.Factory);

            if (Control.Upwinding)
            {
                paramNames      = new string[] { "OldLevelSet", "MeanLevelSetGradient[0]", "MeanLevelSetGradient[1]" };
                noOfParamFields = D;
                LevelSetGradient.Clear();
                LevelSetGradient.Gradient(1.0, Phi);
                //LevelSetGradient.GradientByFlux(1.0, Phi);
                MeanLevelSetGradient.Clear();
                MeanLevelSetGradient.AccLaidBack(1.0, LevelSetGradient);

                parameterFields = ArrayTools.Cat(new SinglePhaseField[] { OldPhi }, MeanLevelSetGradient.ToArray());
                //throw new NotImplementedException("ToDO");
                BulkForm  = new EllipticReInitUpwindForm_Laplace(Control.PenaltyMultiplierFlux * PenaltyBase, LSTrck);
                myRHSForm = new EllipticReInitUpwindForm_RHS(Control.PenaltyMultiplierFlux * PenaltyBase, LSTrck);

                OldDirection = new double[MeanLevelSetGradient.CoordinateVector.ToArray().Length];
                for (int i = 0; i < MeanLevelSetGradient.CoordinateVector.Length; i++)
                {
                    OldDirection[i] = Math.Sign(MeanLevelSetGradient.CoordinateVector[i]);
                }
                NewDirection = OldDirection.CloneAs();
            }
            else
            {
                paramNames      = new string[] { };
                noOfParamFields = 0;
                parameterFields = new SinglePhaseField[] { };
                BulkForm        = new CentralDifferencesLHSForm(Control.PenaltyMultiplierFlux * PenaltyBase, LSTrck.GridDat.Cells.cj);
                myRHSForm       = new CentralDifferencesRHSForm(Control.PenaltyMultiplierFlux * PenaltyBase, LSTrck);
            }


            // SIP for the bulk Phase
            //this.Operator_bulk = new SpatialOperator(1, noOfParamFields, 1, QuadOrderFunc.SumOfMaxDegrees(1, RoundUp: false), variableNames);
            this.Operator_bulk = BulkForm.Operator();



            // Zero at the Interface
            // Calculate Quadrature Order
            Func <int[], int[], int[], int> InterfaceQuadOrder;

            InterfaceQuadOrder = QuadOrderFunc.FixedOrder(Phi.Basis.Degree * 2 + 2);

            // Generate Interface Operator
            this.Operator_interface = (new EllipticReInitInterfaceForm(Control.PenaltyMultiplierInterface * PenaltyBase, LSTrck)).XOperator(InterfaceQuadOrder);

            // Nonlinear Part on the RHS
            // switch for the potential functions
            switch (Control.Potential)
            {
            case ReInitPotential.BastingDoubleWell: {
                myRHSForm.DiffusionRate = ((d, b) => DiffusionRates.DoubleWell(d, b));
                break;
            };

            case ReInitPotential.BastingSingleWell: {
                myRHSForm.DiffusionRate = ((d, b) => DiffusionRates.SingleWell(d, b));
                break;
            };

            case ReInitPotential.SingleWellNear: {
                myRHSForm.DiffusionRate = ((d, b) => DiffusionRates.SingleWellNear(d, b));
                break;
            };

            case ReInitPotential.P4DoubleWell: {
                Console.WriteLine("Warning - This Option for Elliptic ReInit does not work well");
                myRHSForm.DiffusionRate = ((d, b) => DiffusionRates.DoubleWellAlternative(d, b));
                break;
            };

            case ReInitPotential.SingleWellOnCutDoubleWellElse: {
                myRHSForm.DiffusionRate = ((d, b) => DiffusionRates.SingleWellOnCutDoubleWellElse(d, b));
                break;
            }
            }
            Operator_RHS = myRHSForm.Operator(QuadOrderFunc.SumOfMaxDegrees(2, RoundUp: true));


            // The result of the nonlinear part on the rhs is projected on a single-phase field
            RHSField = new SinglePhaseField(Phi.Basis, "RHS");

            OpMatrix = new MsrMatrix(this.Phi.Mapping, this.Phi.Mapping);
            OpAffine = new double[OpMatrix.RowPartitioning.LocalLength];

            // Matrix and RHS for the Bulk component
            OpMatrix_bulk = new MsrMatrix(this.Phi.Mapping, this.Phi.Mapping);
            OpAffine_bulk = new double[OpMatrix.RowPartitioning.LocalLength];

            // Matrix and RHS for the Interface Penalty
            OpMatrix_interface = new MsrMatrix(this.Phi.Mapping, this.Phi.Mapping);
            OpAffine_interface = new double[OpMatrix.RowPartitioning.LocalLength];

            // Init Parameter Fields
            OldPhi.Clear();
            OldPhi.Acc(1.0, Phi);

            // Compute Matrices
            UpdateBulkMatrix();
        }
Пример #16
0
            public XDGTestSetup(
                int p,
                double AggregationThreshold,
                int TrackerWidth,
                MultigridOperator.Mode mumo,
                XQuadFactoryHelper.MomentFittingVariants momentFittingVariant,
                ScalarFunction LevSetFunc = null)
            {
                // Level set, tracker and XDG basis
                // ================================

                if (LevSetFunc == null)
                {
                    LevSetFunc = ((_2D)((x, y) => 0.8 * 0.8 - x * x - y * y)).Vectorize();
                }
                LevSet = new LevelSet(new Basis(grid, 2), "LevelSet");
                LevSet.Clear();
                LevSet.ProjectField(LevSetFunc);
                LsTrk = new LevelSetTracker(grid, XQuadFactoryHelper.MomentFittingVariants.Classic, TrackerWidth, new string[] { "A", "B" }, LevSet);
                LsTrk.UpdateTracker();

                XB = new XDGBasis(LsTrk, p);

                XSpatialOperator Dummy = new XSpatialOperator(1, 0, 1, QuadOrderFunc.SumOfMaxDegrees(RoundUp: true), "C1", "u");

                //Dummy.EquationComponents["c1"].Add(new
                Dummy.Commit();

                //Tecplot.PlotFields(new DGField[] { LevSet }, "agglo", 0.0, 3);


                // operator
                // ========

                Debug.Assert(p <= 4);
                XDGBasis opXB = new XDGBasis(LsTrk, 4); // we want to have a very precise quad rule
                var      map  = new UnsetteledCoordinateMapping(opXB);

                int quadOrder = Dummy.QuadOrderFunction(map.BasisS.Select(bs => bs.Degree).ToArray(), new int[0], map.BasisS.Select(bs => bs.Degree).ToArray());

                //agg = new MultiphaseCellAgglomerator(new CutCellMetrics(momentFittingVariant, quadOrder, LsTrk, LsTrk.SpeciesIdS.ToArray()), AggregationThreshold, false);
                agg = LsTrk.GetAgglomerator(LsTrk.SpeciesIdS.ToArray(), quadOrder, __AgglomerationTreshold: AggregationThreshold);


                foreach (var S in LsTrk.SpeciesIdS)
                {
                    Console.WriteLine("Species {0}, no. of agglomerated cells {1} ",
                                      LsTrk.GetSpeciesName(S),
                                      agg.GetAgglomerator(S).AggInfo.SourceCells.Count());
                }

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

                // Basis maxB = map.BasisS.ElementAtMax(b => b.Degree);
                //MassFact = new MassMatrixFactory(maxB, agg);
                MassFact = LsTrk.GetXDGSpaceMetrics(LsTrk.SpeciesIdS.ToArray(), quadOrder, 1).MassMatrixFactory;


                // Test field
                // ==========

                // set the test field: this is a polynomial function,
                // but different for each species; On this field, restriction followed by prolongation should be the identity
                this.Xdg_uTest = new XDGField(this.XB, "uTest");
                Dictionary <SpeciesId, double> dumia = new Dictionary <SpeciesId, double>();
                int i = 2;

                foreach (var Spc in LsTrk.SpeciesIdS)
                {
                    dumia.Add(Spc, i);
                    i -= 1;
                }
                SetTestValue(Xdg_uTest, dumia);


                // dummy operator matrix which fits polynomial degree p
                // ====================================================

                Xdg_opMtx = new BlockMsrMatrix(Xdg_uTest.Mapping, Xdg_uTest.Mapping);
                Xdg_opMtx.AccEyeSp(120.0);

                // XDG Aggregation BasiseS
                // =======================

                //XAggB = MgSeq.Select(agGrd => new XdgAggregationBasis[] { new XdgAggregationBasis(uTest.Basis, agGrd) }).ToArray();
                XAggB = new XdgAggregationBasis[MgSeq.Length][];
                var _XAggB = AggregationGridBasis.CreateSequence(MgSeq, Xdg_uTest.Mapping.BasisS);

                for (int iLevel = 0; iLevel < XAggB.Length; iLevel++)
                {
                    XAggB[iLevel] = new[] { (XdgAggregationBasis)(_XAggB[iLevel][0]) };
                    XAggB[iLevel][0].Update(agg);
                }

                // Multigrid Operator
                // ==================



                Xdg_opMtx = new BlockMsrMatrix(Xdg_uTest.Mapping, Xdg_uTest.Mapping);
                Xdg_opMtx.AccEyeSp(120.0);

                XdgMultigridOp = new MultigridOperator(XAggB, Xdg_uTest.Mapping,
                                                       Xdg_opMtx,
                                                       MassFact.GetMassMatrix(Xdg_uTest.Mapping, false),
                                                       new MultigridOperator.ChangeOfBasisConfig[][] {
                    new MultigridOperator.ChangeOfBasisConfig[] {
                        new MultigridOperator.ChangeOfBasisConfig()
                        {
                            VarIndex = new int[] { 0 }, mode = mumo, Degree = p
                        }
                    }
                });
            }
        /// <summary>
        /// Legacy interface, preserved as static function.
        /// </summary>
        static public void ComputeMatrixEx <M, V>(
            this XSpatialOperator xOp,
            LevelSetTracker lsTrk,
            UnsetteledCoordinateMapping DomainMap, IList <DGField> Parameters, UnsetteledCoordinateMapping CodomainMap,
            M Matrix, V AffineOffset, bool OnlyAffine, double time, bool MPIParameterExchange,
            IDictionary <SpeciesId, XSpatialOperator.QrSchemPair> SpeciesSchemes,
            IDictionary <SpeciesId, MultidimensionalArray> CellLengthScales,
            IDictionary <SpeciesId, MultidimensionalArray> InterfaceLengthScales,
            MultidimensionalArray SlipLengths = null,
            SubGrid SubGrid = null)
            where M : IMutableMatrixEx
            where V : IList <double> //
        {
            CellMask SubGridCellMask = null;
            EdgeMask SubGridEdgeMask = null;

            if (SubGrid != null)
            {
                SubGridCellMask = SubGrid.VolumeMask;
                /// I don't know why, but this seems to work:
                SubGridEdgeMask = SubGrid.AllEdgesMask;
                /// And this does not:
                //SubGridEdgeMask = SubGrid.InnerEdgesMask;
            }

            SpeciesId[] ReqSpecies = SpeciesSchemes.Keys.ToArray();

            //int order = xOp.GetOrderFromQuadOrderFunction(DomainMap, Parameters, CodomainMap);
            //var SchemeHelper = lsTrk.GetXDGSpaceMetrics(ReqSpecies, order, 1).XQuadSchemeHelper;

            //var SpeciesSchemes_out = new Dictionary<SpeciesId, XSpatialOperator.QrSchemPair>();

            //foreach(var SpeciesId in SpeciesSchemes.Keys) {
            //    EdgeQuadratureScheme edgeScheme;
            //    CellQuadratureScheme cellScheme;

            //    var qrSchemes = SpeciesSchemes[SpeciesId];

            //    bool AssembleOnFullGrid = (SubGrid == null);
            //    if(qrSchemes.EdgeScheme == null) {
            //        edgeScheme = SchemeHelper.GetEdgeQuadScheme(SpeciesId, AssembleOnFullGrid, SubGridEdgeMask);
            //    } else {
            //        //edgeScheme = qrSchemes.EdgeScheme;
            //        //throw new ArgumentException();
            //    }

            //    if(qrSchemes.CellScheme == null) {
            //        cellScheme = SchemeHelper.GetVolumeQuadScheme(SpeciesId, AssembleOnFullGrid, SubGridCellMask);
            //    } else {
            //        //cellScheme = qrSchemes.CellScheme;
            //        throw new ArgumentException();
            //    }

            //    SpeciesSchemes_out.Add(SpeciesId,
            //        new XSpatialOperator.QrSchemPair() {
            //            CellScheme = cellScheme,
            //            EdgeScheme = edgeScheme
            //        });

            //}


            var ev = xOp.GetMatrixBuilder(lsTrk, DomainMap, Parameters, CodomainMap, SpeciesSchemes);


            ev.time           = time;
            ev.MPITtransceive = MPIParameterExchange;

            foreach (var s in CellLengthScales.Keys)
            {
                if (ev.SpeciesOperatorCoefficients.ContainsKey(s))
                {
                    ev.SpeciesOperatorCoefficients[s].CellLengthScales = CellLengthScales[s];
                }
                else
                {
                    ev.SpeciesOperatorCoefficients.Add(s,
                                                       new CoefficientSet()
                    {
                        CellLengthScales = CellLengthScales[s],
                        GrdDat           = lsTrk.GridDat
                    });
                }

                if (InterfaceLengthScales != null)
                {
                    ev.SpeciesOperatorCoefficients[s].UserDefinedValues["InterfaceLengths"] = InterfaceLengthScales[s];
                }

                if (SlipLengths != null)
                {
                    ev.SpeciesOperatorCoefficients[s].UserDefinedValues["SlipLengths"] = SlipLengths;
                }
            }


            if (OnlyAffine)
            {
                ev.ComputeAffine(AffineOffset);
            }
            else
            {
                ev.ComputeMatrix(Matrix, AffineOffset);
            }
        }
Пример #18
0
        /// <summary>
        /// ctor.
        /// </summary>
        internal NECQuadratureLevelSet(IGridData context,
                                       XSpatialOperator DiffOp,
                                       V __ResultVector,
                                       IList <DGField> __DomainFields,
                                       IList <DGField> __Parameters,
                                       UnsetteledCoordinateMapping CodomainMap,
                                       LevelSetTracker lsTrk, int _iLevSet, Tuple <SpeciesId, SpeciesId> SpeciesPair,
                                       ICompositeQuadRule <QuadRule> domAndRule) //
            : base(new int[] { CodomainMap.MaxTotalNoOfCoordinatesPerCell },
                   context,
                   domAndRule) //
        {
            // -----------------------------------
            // set members / check ctor parameters
            // -----------------------------------
            m_lsTrk            = lsTrk;
            this.m_LevSetIdx   = _iLevSet;
            this.m_SpeciesPair = SpeciesPair;
            this.ResultVector  = __ResultVector;
            m_CodomainMap      = CodomainMap;
            var _Parameters = (__Parameters != null) ? __Parameters.ToArray() : new DGField[0];

            if (__DomainFields.Count != DiffOp.DomainVar.Count)
            {
                throw new ArgumentException("mismatch between number of domain variables in spatial operator and given domain variables");
            }
            if (_Parameters.Length != DiffOp.ParameterVar.Count)
            {
                throw new ArgumentException("mismatch between number of parameter variables in spatial operator and given parameters");
            }
            if (m_CodomainMap.NoOfVariables != DiffOp.CodomainVar.Count)
            {
                throw new ArgumentException("mismatch between number of codomain variables in spatial operator and given codomain mapping");
            }

            m_DomainAndParamFields = ArrayTools.Cat(__DomainFields, _Parameters);
            this.DELTA             = __DomainFields.Count;

            // ------------------------
            // sort equation components
            // ------------------------

            int Gamma = m_CodomainMap.NoOfVariables;

            m_NonlinLsForm_V = DiffOp.GetArgMapping <INonlinLevelSetForm_V>(true,
                                                                            eq => ((eq.LevelSetTerms & (TermActivationFlags.V | TermActivationFlags.UxV | TermActivationFlags.GradUxV)) != 0) && Compfilter(eq),
                                                                            eq => (eq is ILevelSetForm) ? new NonlinearLevelSetFormVectorizer((ILevelSetForm)eq) : null);
            m_NonlinLsForm_GradV = DiffOp.GetArgMapping <INonlinLevelSetForm_GradV>(true,
                                                                                    eq => ((eq.LevelSetTerms & (TermActivationFlags.GradV | TermActivationFlags.UxGradV | TermActivationFlags.GradUxGradV)) != 0) && Compfilter(eq),
                                                                                    eq => (eq is ILevelSetForm) ? new NonlinearLevelSetFormVectorizer((ILevelSetForm)eq) : null);


            m_ValueRequired    = new bool[m_DomainAndParamFields.Length];
            m_GradientRequired = new bool[m_DomainAndParamFields.Length];

            m_NonlinLsForm_V.DetermineReqFields(m_GradientRequired,
                                                comp => ((comp.LevelSetTerms & (TermActivationFlags.GradUxGradV | TermActivationFlags.GradUxV)) != 0));
            m_NonlinLsForm_GradV.DetermineReqFields(m_GradientRequired,
                                                    comp => ((comp.LevelSetTerms & (TermActivationFlags.GradUxGradV | TermActivationFlags.GradUxV)) != 0));
            m_NonlinLsForm_V.DetermineReqFields(m_ValueRequired,
                                                comp => ((comp.LevelSetTerms & (TermActivationFlags.UxGradV | TermActivationFlags.UxV)) != 0));
            m_NonlinLsForm_GradV.DetermineReqFields(m_ValueRequired,
                                                    comp => ((comp.LevelSetTerms & (TermActivationFlags.UxGradV | TermActivationFlags.UxV)) != 0));

            for (int i = __DomainFields.Count; i < m_DomainAndParamFields.Length; i++)
            {
                m_ValueRequired[i] = true; // parameters are always required!
            }


            // -----
            // alloc
            // -----

            Koeff_V     = new MultidimensionalArray[Gamma];
            Koeff_GradV = new MultidimensionalArray[Gamma];
            for (int gamma = 0; gamma < Gamma; gamma++)
            {
                Koeff_V[gamma]     = new MultidimensionalArray(3);
                Koeff_GradV[gamma] = new MultidimensionalArray(4);
            }

            int L = m_DomainAndParamFields.Length;

            m_FieldValuesPos         = new MultidimensionalArray[L];
            m_FieldValuesNeg         = new MultidimensionalArray[L];
            m_FieldGradientValuesPos = new MultidimensionalArray[L];
            m_FieldGradientValuesNeg = new MultidimensionalArray[L];

            for (int l = 0; l < L; l++)
            {
                if (m_ValueRequired[l])
                {
                    m_FieldValuesPos[l] = new MultidimensionalArray(2);
                    m_FieldValuesNeg[l] = new MultidimensionalArray(2);
                }

                if (m_GradientRequired[l])
                {
                    m_FieldGradientValuesPos[l] = new MultidimensionalArray(3);
                    m_FieldGradientValuesNeg[l] = new MultidimensionalArray(3);
                }
            }


            // ------------------
            // init custom timers
            // ------------------

            base.CustomTimers             = new Stopwatch[] { new Stopwatch(), new Stopwatch(), new Stopwatch(), new Stopwatch(), new Stopwatch() };
            base.CustomTimers_Names       = new string[] { "Flux-Eval", "Basis-Eval", "Loops", "ParametersAndNormals", "Field-Eval" };
            base.CustomTimers_RootPointer = new int[5];
            ArrayTools.SetAll(base.CustomTimers_RootPointer, -1);

            this.m_NonlinLsForm_V_Watches     = this.m_NonlinLsForm_V.InitStopWatches(0, this);
            this.m_NonlinLsForm_GradV_Watches = this.m_NonlinLsForm_GradV.InitStopWatches(0, this);

            Flux_Eval            = base.CustomTimers[0];
            Basis_Eval           = base.CustomTimers[1];
            Loops                = base.CustomTimers[2];
            ParametersAndNormals = base.CustomTimers[3];
            Field_Eval           = base.CustomTimers[4];
        }