示例#1
0
        SpatialOperator CreateAdvectionSpatialOperator(IncompressibleBoundaryCondMap bcMap)
        {
            Func <int[], int[], int[], int> QuadOrderFunction = QuadOrderFunc.SumOfMaxDegrees();

            string[] parameterList;
            parameterList = ArrayTools.Cat(
                VariableNames.Velocity0Vector(D),
                VariableNames.Velocity0MeanVector(D),
                "div(U)");

            SpatialOperator SO = new SpatialOperator(new string[] { "LevelSet" },
                                                     parameterList,
                                                     new string[] { "Phi-Evo" },
                                                     QuadOrderFunc.NonLinear(2));

            //div(u*phi)
            SO.EquationComponents["Phi-Evo"].Add(new LevelSetLLFFlux(GridDat, bcMap));
            //-phi*div(u)
            SO.EquationComponents["Phi-Evo"].Add(new FextSource());
            SO.Commit();
            return(SO);
        }
        /// <summary>
        /// Creating the time integrated DG-FEM discretization of the level set advection equation
        /// </summary>
        /// <param name="LevelSet"></param>
        /// <param name="ExtensionVelocity"></param>
        /// <param name="e"></param>
        void CreateAdvectionSpatialOperator(SinglePhaseField LevelSet, SinglePhaseField ExtensionVelocity, ExplicitEuler.ChangeRateCallback e, SubGrid subGrid)
        {
            SpatialOperator SO;
            Func <int[], int[], int[], int> QuadOrderFunction = QuadOrderFunc.Linear();
            int D = LevelSet.GridDat.SpatialDimension;

            //FieldFactory<SinglePhaseField> fac = new FieldFactory<SinglePhaseField>(SinglePhaseField.Factory);
            //VectorField<SinglePhaseField> LevelSetGradient = new VectorField<SinglePhaseField>(D,
            //    LevelSet.Basis,fac);

            SO = new SpatialOperator(1, 1, 1, QuadOrderFunction, new string[] { "LS", "S", "Result" });
            double PenaltyBase = ((double)((LevelSet.Basis.Degree + 1) * (LevelSet.Basis.Degree + D))) / ((double)D);

            SO.EquationComponents["Result"].Add(new ScalarVelocityAdvectionFlux(GridDat, PenaltyBase));
            SO.Commit();
            this.TimeIntegrator = new RungeKutta(RungeKuttaScheme.ExplicitEuler, SO, new CoordinateMapping(LevelSet), new CoordinateMapping(ExtensionVelocity), subGrid);

            // Performing the task e
            if (e != null)
            {
                this.TimeIntegrator.OnBeforeComputeChangeRate += e;
            }
        }
示例#3
0
        unsafe public static void Laplacian(ref int GridRef,
                                            ref int DgDegree,

                                            out int ierr)
        {
            try {
                // grid, etc
                // =========

                GridData grd = null;// (GridData)(Infrastructure.GetObject(GridRef));

                var b   = new Basis(grd, DgDegree);
                var map = new UnsetteledCoordinateMapping(b);

                var L  = new Laplace(1.3, grd.Cells.cj);
                var op = new SpatialOperator(1, 0, 1, QuadOrderFunc.Linear(), "T", "c1");
                op.EquationComponents["c1"].Add(L);
                op.Commit();

                // evaluate operator
                // =================

                var      Mtx = new BlockMsrMatrix(map, map);
                double[] B   = new double[map.LocalLength];

                var eval = op.GetMatrixBuilder(map, null, map);
                eval.ComputeMatrix(Mtx, B);

                // return data
                // ===========

                throw new NotImplementedException("todo");
            } catch (Exception e) {
                ierr = Infrastructure.ErrorHandler(e);
            }
            ierr = 0;
        }
示例#4
0
        /// <summary>
        /// Includes assembly of the matrix.
        /// </summary>
        /// <param name="L"></param>
        protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L)
        {
            using (FuncTrace tr = new FuncTrace()) {
                // create operator
                // ===============
                {
                    double D              = this.GridData.SpatialDimension;
                    double penalty_base   = (T.Basis.Degree + 1) * (T.Basis.Degree + D) / D;
                    double penalty_factor = base.Control.penalty_poisson;

                    BoundaryCondMap <BoundaryType> PoissonBcMap = new BoundaryCondMap <BoundaryType>(this.GridData, this.Control.BoundaryValues, "T");

                    LapaceIp = new SpatialOperator(1, 1, QuadOrderFunc.SumOfMaxDegrees(), "T", "T");

                    MultidimensionalArray LengthScales;
                    if (this.GridData is GridData)
                    {
                        LengthScales = ((GridData)GridData).Cells.cj;
                    }
                    else if (this.GridData is AggregationGridData)
                    {
                        LengthScales = ((AggregationGridData)GridData).AncestorGrid.Cells.cj;
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }

                    var flux = new ipFlux(penalty_base * base.Control.penalty_poisson, LengthScales, PoissonBcMap);

                    LapaceIp.EquationComponents["T"].Add(flux);

                    LapaceIp.Commit();
                }
            }
        }
示例#5
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);
            }
        }
示例#6
0
        public static SpatialOperator BuildEulerOperator(IGridData gridData, CompressibleControl control)
        {
            // Boundary condition map
            Material material = control.GetMaterial();
            IBoundaryConditionMap boundaryMap = new CompressibleBoundaryCondMap(gridData, control, material);

            // Initialize operator
            SpatialOperator EulerOperator = new SpatialOperator(
                new string[] { CompressibleVariables.Density, CompressibleVariables.Momentum.xComponent, CompressibleVariables.Momentum.yComponent, CompressibleVariables.Energy },
                new string[] { },
                new string[] { CompressibleVariables.Density, CompressibleVariables.Momentum.xComponent, CompressibleVariables.Momentum.yComponent, CompressibleVariables.Energy },
                QuadOrderFunc.NonLinearWithoutParameters(2)
                );

            // Map fluxes
            EulerOperator.EquationComponents[CompressibleVariables.Density].Add(new OptimizedHLLCDensityFlux(boundaryMap, material));
            EulerOperator.EquationComponents[CompressibleVariables.Momentum.xComponent].Add(new OptimizedHLLCMomentumFlux(boundaryMap, 0, material));
            EulerOperator.EquationComponents[CompressibleVariables.Momentum.yComponent].Add(new OptimizedHLLCMomentumFlux(boundaryMap, 1, material));
            EulerOperator.EquationComponents[CompressibleVariables.Energy].Add(new OptimizedHLLCEnergyFlux(boundaryMap, material));

            EulerOperator.Commit();

            return(EulerOperator);
        }
示例#7
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(new[] { "A" }, 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();
        }
示例#8
0
        /// <summary>
        /// Obtaining the time integrated spatial discretization of the reinitialization equation in a narrow band around the zero level set, based on a Godunov's numerical Hamiltonian calculation
        /// </summary>
        /// <param name="LS"> The level set function </param>
        /// <param name="Restriction"> The narrow band around the zero level set </param>
        /// <param name="NumberOfTimesteps">
        /// maximum number of pseudo-timesteps
        /// </param>
        /// <param name="thickness">
        /// The smoothing width of the signum function.
        /// This is the main stabilization parameter for re-initialization.
        /// It should be set to approximately 3 cells.
        /// </param>
        /// <param name="TimestepSize">
        /// size of the pseudo-timestep
        /// </param>
        public void ReInitialize(LevelSet LS, SubGrid Restriction, double thickness, double TimestepSize, int NumberOfTimesteps)
        {
            using (var tr = new FuncTrace()) {
                // log parameters:
                tr.Info("thickness: " + thickness.ToString(NumberFormatInfo.InvariantInfo));
                tr.Info("TimestepSize: " + TimestepSize.ToString(NumberFormatInfo.InvariantInfo));
                tr.Info("NumberOfTimesteps: " + NumberOfTimesteps);

                ExplicitEuler TimeIntegrator;

                SpatialOperator SO;
                Func <int[], int[], int[], int> QuadratureOrder = QuadOrderFunc.NonLinear(3);
                if (m_ctx.SpatialDimension == 2)
                {
                    SO = new SpatialOperator(1, 5, 1, QuadratureOrder, new string[] { "LS", "LSCGV", "LSDG[0]", "LSUG[0]", "LSDG[1]", "LSUG[1]", "Result" });
                    SO.EquationComponents["Result"].Add(new GodunovHamiltonian(m_ctx, thickness));
                    SO.Commit();
                    TimeIntegrator = new RungeKutta(m_Scheme, SO, new CoordinateMapping(LS), new CoordinateMapping(LSCGV, LSDG[0], LSUG[0], LSDG[1], LSUG[1]), sgrd: Restriction);
                }
                else
                {
                    SO = new SpatialOperator(1, 7, 1, QuadratureOrder, new string[] { "LS", "LSCGV", "LSDG[0]", "LSUG[0]", "LSDG[1]", "LSUG[1]", "LSDG[2]", "LSUG[2]", "Result" });
                    SO.EquationComponents["Result"].Add(new GodunovHamiltonian(m_ctx, thickness));
                    SO.Commit();
                    TimeIntegrator = new RungeKutta(m_Scheme, SO, new CoordinateMapping(LS), new CoordinateMapping(LSCGV, LSDG[0], LSUG[0], LSDG[1], LSUG[1], LSDG[2], LSUG[2]), sgrd: Restriction);
                }



                // Calculating the gradients in each sub-stage of a Runge-Kutta integration procedure
                ExplicitEuler.ChangeRateCallback EvalGradients = delegate(double t1, double t2) {
                    LSUG.Clear();
                    CalculateLevelSetGradient(LS, LSUG, "Upwind", Restriction);

                    LSDG.Clear();
                    CalculateLevelSetGradient(LS, LSDG, "Downwind", Restriction);

                    LSCG.Clear();
                    CalculateLevelSetGradient(LS, LSCG, "Central", Restriction);

                    LSCGV.Clear();
                    var VolMask = (Restriction != null) ? Restriction.VolumeMask : null;
                    LSCGV.ProjectAbs(1.0, VolMask, LSCG.ToArray());
                };
                TimeIntegrator.OnBeforeComputeChangeRate += EvalGradients;


                {
                    EvalGradients(0, 0);
                    var GodunovResi = new SinglePhaseField(LS.Basis, "Residual");
                    SO.Evaluate(1.0, 0.0, LS.Mapping, TimeIntegrator.ParameterMapping.Fields, GodunovResi.Mapping, Restriction);

                    //Tecplot.Tecplot.PlotFields(ArrayTools.Cat<DGField>( LSUG, LSDG, LS, GodunovResi), "Residual", 0, 3);
                }



                // pseudo-timestepping
                // ===================
                double   factor     = 1.0;
                double   time       = 0;
                LevelSet prevLevSet = new LevelSet(LS.Basis, "prevLevSet");

                CellMask RestrictionMask = (Restriction == null) ? null : Restriction.VolumeMask;

                for (int i = 0; (i < NumberOfTimesteps); i++)
                {
                    tr.Info("Level set reinitialization pseudo-timestepping, timestep " + i);

                    // backup old Levelset
                    // -------------------
                    prevLevSet.Clear();
                    prevLevSet.Acc(1.0, LS, RestrictionMask);

                    // time integration
                    // ----------------
                    double dt = TimestepSize * factor;
                    tr.Info("dt = " + dt.ToString(NumberFormatInfo.InvariantInfo) + " (factor = " + factor.ToString(NumberFormatInfo.InvariantInfo) + ")");
                    TimeIntegrator.Perform(dt);
                    time += dt;

                    // change norm
                    // ------

                    prevLevSet.Acc(-1.0, LS, RestrictionMask);
                    double ChangeNorm = prevLevSet.L2Norm(RestrictionMask);
                    Console.WriteLine("Reinit: PseudoTime: {0}  - Changenorm: {1}", i, ChangeNorm);

                    //Tecplot.Tecplot.PlotFields(new SinglePhaseField[] { LS }, m_ctx, "Reinit-" + i, "Reinit-" + i, i, 3);
                }

                //*/
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="jCell"></param>
        /// <param name="AcceptedMask"></param>
        /// <param name="Phi"></param>
        /// <param name="gradPhi"></param>
        /// <param name="__DiffusionCoeff">Output: if artificial diffusion is turned</param>
        /// <param name="MaxAllowedPhi">Input: upper threshold for the values of <paramref name="Phi"/> in cell <see cref="jCell"/>.</param>
        /// <param name="MinAllowedPhi">Input: lower threshold for the values of <paramref name="Phi"/> in cell <see cref="jCell"/>.</param>
        /// <returns></returns>
        public bool LocalSolve_Iterative(int jCell, BitArray AcceptedMask, SinglePhaseField Phi, VectorField <SinglePhaseField> gradPhi, SinglePhaseField __DiffusionCoeff, double MaxAllowedPhi, double MinAllowedPhi)
        {
            //this.LocalSolve_Geometric(jCell, AcceptedMask, Phi, +1, out MinAllowedPhi, out MaxAllowedPhi);) {
            int N   = this.LevelSetBasis.GetLength(jCell);
            int i0G = this.LevelSetMapping.GlobalUniqueCoordinateIndex(0, jCell, 0);
            int i0L = this.LevelSetMapping.LocalUniqueCoordinateIndex(0, jCell, 0);

            SinglePhaseField __AcceptedMask = new SinglePhaseField(new Basis(this.GridDat, 0), "accepted");

            for (int j = 0; j < AcceptedMask.Length; j++)
            {
                __AcceptedMask.SetMeanValue(j, AcceptedMask[j] ? 1.0 : 0.0);
            }


            // subgrid on which we are working, consisting only of one cell
            SubGrid jCellGrid = new SubGrid(new CellMask(this.GridDat, Chunk.GetSingleElementChunk(jCell)));

            // create spatial operator
            IEvaluatorNonLin evo;
            {
                SpatialOperator op = new SpatialOperator(1, 2, 1, QuadOrderFunc.NonLinear(2), "Phi", "dPhi_dx0", "dPhi_dx1", "cod1");
                op.EquationComponents["cod1"].Add(new ReinitOperator());
                op.EdgeQuadraturSchemeProvider   = g => (new EdgeQuadratureScheme(domain: EdgeMask.GetEmptyMask(g)));
                op.VolumeQuadraturSchemeProvider = g => (new CellQuadratureScheme(domain: jCellGrid.VolumeMask));
                op.Commit();

                evo = op.GetEvaluatorEx(Phi.Mapping.Fields, gradPhi.Mapping.Fields, Phi.Mapping);
                evo.ActivateSubgridBoundary(jCellGrid.VolumeMask, subGridBoundaryTreatment: SubGridBoundaryModes.InnerEdge);
            }

            // create artificial diffusion operator
            MultidimensionalArray DiffMtx;

            double[]        DiffRhs;
            SpatialOperator dop;
            {
                double penaltyBase = this.LevelSetBasis.Degree + 2;
                penaltyBase = penaltyBase.Pow2();

                dop = (new ArtificialViscosity(AcceptedMask, penaltyBase, GridDat.Cells.h_min, jCell, -1.0)).Operator(1);

                MsrMatrix _DiffMtx = new MsrMatrix(this.LevelSetMapping, this.LevelSetMapping);
                double[]  _DiffRhs = new double[this.LevelSetMapping.LocalLength];

                dop.ComputeMatrixEx(this.LevelSetMapping, new DGField[] { Phi, null, null }, this.LevelSetMapping,
                                    _DiffMtx, _DiffRhs, OnlyAffine: false,
                                    edgeQuadScheme: (new EdgeQuadratureScheme(domain: jCellGrid.AllEdgesMask)),
                                    volQuadScheme: (new CellQuadratureScheme(domain: jCellGrid.VolumeMask)));

                // extract matrix for 'jCell'
                DiffMtx = MultidimensionalArray.Create(N, N);
                DiffRhs = new double[N];
                for (int n = 0; n < N; n++)
                {
#if DEBUG
                    int      Lr;
                    int[]    row_cols = null;
                    double[] row_vals = null;
                    Lr = _DiffMtx.GetRow(i0G + n, ref row_cols, ref row_vals);
                    for (int lr = 0; lr < Lr; lr++)
                    {
                        int    ColIndex = row_cols[lr];
                        double Value    = row_vals[lr];
                        Debug.Assert((ColIndex >= i0G && ColIndex < i0G + N) || (Value == 0.0), "Matrix is expected to be block-diagonal.");
                    }
#endif
                    for (int m = 0; m < N; m++)
                    {
                        DiffMtx[n, m] = _DiffMtx[i0G + n, i0G + m];
                    }
                    DiffRhs[n] = _DiffRhs[i0L + n];
                }

#if DEBUG
                var Test = DiffMtx.Transpose();
                Test.Acc(-1.0, DiffMtx);
                Debug.Assert(Test.InfNorm() <= 1.0e-8);
#endif
            }

            // find 'good' initial value by geometric solve AND
            // thresholds for the maximum an minimal value of Phi
            double Range = MaxAllowedPhi - MinAllowedPhi;
            MinAllowedPhi -= 0.1 * Range;
            MaxAllowedPhi += 0.1 * Range;


            // timestep for pseudo-timestepping
            double dt = 0.5 * this.GridDat.Cells.h_min[jCell] / (((double)(this.LevelSetBasis.Degree)).Pow2());


            DGField[] PlotFields = new DGField[] { Phi, gradPhi[0], gradPhi[1], __DiffusionCoeff, __AcceptedMask };
            //Tecplot.Tecplot.PlotFields(Params, "itt_0", "EllipicReinit", 0, 3);

            double[] PrevVal = new double[N];
            double[] NextVal = new double[N];
            Phi.Coordinates.GetRow(jCell, PrevVal);

            // pseudo-timestepping
            //if(jCell == 80)
            //    Tecplot.Tecplot.PlotFields(PlotFields, "itt_0", "EllipicReinit", 0, 3);
            //Console.Write("  Local solve cell " + jCell + " ... ");

            bool   converged      = false;
            double DiffusionCoeff = 0;
            int    IterGrowCount  = 0; // number of iterations in which the residual grew
            double LastResi       = double.NaN;
            for (int iIter = 0; iIter < 1000; iIter++)
            {
                //Console.Write("  Local solve iteration " + iIter + " ... ");
                PerformRKstep(dt, jCell, AcceptedMask, Phi, gradPhi, evo);

                __DiffusionCoeff.SetMeanValue(jCell, DiffusionCoeff);

                if (jCell == 80)
                {
                    DiffusionCoeff = 0.1;
                }
                if (DiffusionCoeff > 0)
                {
                    //Console.WriteLine(" Diffusion on.");


                    double[] _DiffRhs = new double[this.LevelSetMapping.LocalLength];


                    dop.ComputeMatrixEx(this.LevelSetMapping, new DGField[] { Phi, gradPhi[0], gradPhi[1] }, this.LevelSetMapping,
                                        default(MsrMatrix), _DiffRhs, OnlyAffine: true,
                                        edgeQuadScheme: (new EdgeQuadratureScheme(domain: jCellGrid.AllEdgesMask)),
                                        volQuadScheme: (new CellQuadratureScheme(domain: CellMask.GetEmptyMask(this.GridDat))));

                    // extract matrix for 'jCell'
                    for (int n = 0; n < N; n++)
                    {
                        DiffRhs[n] = _DiffRhs[i0L + n];
                    }

                    PerformArtificialDiffusion(dt * DiffusionCoeff, jCell, Phi, DiffMtx, DiffRhs);
                }
                Phi.Coordinates.GetRow(jCell, NextVal);
                double   resi = Math.Sqrt(GenericBlas.L2DistPow2(NextVal, PrevVal) / GenericBlas.L2NormPow2(PrevVal));
                double[] A    = NextVal;
                NextVal = PrevVal;
                PrevVal = A;
                if (iIter > 0 && resi > LastResi)
                {
                    IterGrowCount++;
                }
                else
                {
                    IterGrowCount = 0;
                }
                LastResi = resi;


                if (resi < 1.0e-10)
                {
                    converged = true;
                    break;
                }

                double maxPhi, minPhi;
                Phi.GetExtremalValuesInCell(out minPhi, out maxPhi, jCell);

                bool MinAlarm  = minPhi < MinAllowedPhi;
                bool Maxalarm  = maxPhi > MaxAllowedPhi;
                bool GrowAlarm = IterGrowCount > 4;
                bool IterAlarm = iIter >= 50;

                if (MinAlarm || Maxalarm || GrowAlarm)
                {
                    // Diffusion coefficient should be increased
                    if (DiffusionCoeff == 0)
                    {
                        DiffusionCoeff = 1.0e-2;
                    }
                    else
                    {
                        if (DiffusionCoeff < 1.0e3)
                        {
                            DiffusionCoeff *= 2;
                        }
                    }
                    //Console.WriteLine("   increasing Diffusion: {0}, Alarms : {1}{2}{3}{4}", DiffusionCoeff, MinAlarm ? 1 : 0, Maxalarm ? 1 : 0, GrowAlarm ? 1 : 0, IterAlarm ? 1 : 0);
                }


                //if(jCell == 80 && iIter < 100)
                //    Tecplot.Tecplot.PlotFields(PlotFields, "itt_" + (iIter + 1), "EllipicReinit", iIter + 1, 3);
            }


            return(converged);
        }
示例#10
0
        /// <summary>
        /// Declaration of the spatial operator
        /// </summary>
        protected override SpatialOperator GetOperatorInstance(int D)
        {
            // instantiate boundary condition mapping
            // ======================================
            boundaryCondMap = new IncompressibleBoundaryCondMap(this.GridData, this.Control.BoundaryValues, PhysicsMode.Incompressible);

            // instantiate operator
            // ====================
            string[] CodName = (new[] { "ResidualMomentumX", "ResidualMomentumY", "ResidualMomentumZ" }).GetSubVector(0, D).Cat("ResidualConti");

            var op = new SpatialOperator(
                __DomainVar: VariableNames.VelocityVector(D).Cat(VariableNames.Pressure),
                __ParameterVar: VariableNames.GravityVector(D),
                __CoDomainVar: CodName,
                QuadOrderFunc: QuadOrderFunc.NonLinear(2));

            op.LinearizationHint = LinearizationHint.GetJacobiOperator;

            // Temporal Operator
            // =================

            var TempOp = new ConstantTemporalOperator(op, 0.0); // init with entire diagonal set to 0.0

            op.TemporalOperator = TempOp;

            for (int d = 0; d < D; d++)
            {
                TempOp.SetDiagonal(CodName[d], Control.Density); // set momentum equation entries to density
            }
            // Pressure Reference
            // ==================

            // if there is no Dirichlet boundary condition,
            // the mean value of the pressure is free:
            op.FreeMeanValue[VariableNames.Pressure] = !boundaryCondMap.DirichletPressureBoundary;

            // Momentum Equation
            // =================

            // convective part:
            {
                for (int d = 0; d < D; d++)
                {
                    var comps = op.EquationComponents[CodName[d]];

                    var ConvBulk = new LocalLaxFriedrichsConvection(D, boundaryCondMap, d, Control.Density);
                    comps.Add(ConvBulk); // bulk component
                }
            }

            // pressure part:
            {
                for (int d = 0; d < D; d++)
                {
                    var comps = op.EquationComponents[CodName[d]];
                    var pres  = new PressureGradientLin_d(d, boundaryCondMap);
                    comps.Add(pres); // bulk component
                }
            }

            // viscous part:
            {
                for (int d = 0; d < D; d++)
                {
                    var comps = op.EquationComponents[CodName[d]];

                    double penalty_bulk = this.Control.PenaltySafety;

                    var Visc = new swipViscosity_Term1(penalty_bulk, d, D, boundaryCondMap,
                                                       ViscosityOption.ConstantViscosity,
                                                       constantViscosityValue: Control.Viscosity);
                    comps.Add(Visc); // bulk component GradUTerm
                }
            }


            // Continuity equation
            // ===================
            {
                for (int d = 0; d < D; d++)
                {
                    var src = new Divergence_DerivativeSource(d, D);
                    var flx = new Divergence_DerivativeSource_Flux(d, boundaryCondMap);
                    op.EquationComponents[CodName[D]].Add(src);
                    op.EquationComponents[CodName[D]].Add(flx);
                }


                //IBM_Op.EquationComponents["div"].Add(new PressureStabilization(1, 1.0 / this.Control.PhysicalParameters.mu_A));
            }

            // Gravity parameter
            // =================

            op.ParameterFactories.Add(delegate(IReadOnlyDictionary <string, DGField> DomainVarFields) {
                return(D.ForLoop(d => (VariableNames.Gravity_d(d), this.Gravity[d] as DGField)));
            });


            // commit & return
            // ===============
            op.Commit();
            return(op);
        }
示例#11
0
        protected override SpatialOperator GetSpatialOperator(SolverConfiguration SolverConf, int SpatialComponent, int SpatialDirection)
        {
            SpatialOperator DivergenceOp = new SpatialOperator(new string[] { VariableNames.Velocity_d(SpatialComponent) }, new string[] { "div_d" }, QuadOrderFunc.Linear());

            DivergenceOp.EquationComponents["div_d"].Add(new Divergence_DerivativeSource(SpatialComponent, SolverConf.SpatialDimension));
            DivergenceOp.EquationComponents["div_d"].Add(new Divergence_DerivativeSource_Flux(SpatialComponent, SolverConf.BcMap));
            DivergenceOp.Commit();
            return(DivergenceOp);
        }
示例#12
0
        protected override SpatialOperator GetSpatialOperator(SolverConfiguration SolverConf, int SpatialComponent, int SpatialDirection)
        {
            SpatialOperator PressureOp = new SpatialOperator(new string[] { VariableNames.Pressure }, new string[] { "p1" }, QuadOrderFunc.Linear());

            PressureOp.EquationComponents["p1"].Add(new PressureGradientLin_d(SpatialDirection, SolverConf.BcMap));

            if (SolverConf.Control.PressureGradientSource != null)
            {
                PressureOp.EquationComponents["p1"].Add(
                    new SrcPressureGradientLin_d(SolverConf.Control.PressureGradientSource[SpatialDirection]));
            }

            PressureOp.Commit();
            return(PressureOp);
        }
 /// <summary>
 /// creates the spatial operator that consists only of component <paramref name="c"/>
 /// </summary>
 public static XSpatialOperatorMk2 XOperator(this IEquationComponent c, int DegreeOfNonlinearity = 1)
 {
     return(XOperator(c, QuadOrderFunc.NonLinear(DegreeOfNonlinearity)));
 }
示例#14
0
 /// <summary>
 /// creates the spatial operator that consists only of component <paramref name="c"/>
 /// </summary>
 public static XSpatialOperatorMk2 XOperator(this IEquationComponent c, IEnumerable <string> species, int DegreeOfNonlinearity = 1)
 {
     return(XOperator(c, species, QuadOrderFunc.NonLinear(DegreeOfNonlinearity)));
 }
示例#15
0
        protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L)
        {
            using (FuncTrace tr = new FuncTrace()) {
                this.BcMap = new IncompressibleBoundaryCondMap(this.GridData, grid.GetBoundaryConfig(), PhysicsMode.Incompressible);


                // assemble system, create matrix
                // ------------------------------



                int D = GridData.SpatialDimension;
                //double penalty_base = ((double)((U[0].Basis.Degree + 1) * (U[0].Basis.Degree + D))) / ((double)D);
                double penalty_base   = 1.0;
                double penalty_factor = 1.2;



                // equation assembly
                // -----------------
                string[] CodNames = D.ForLoop(i => "C" + i);
                Operator = new SpatialOperator(VariableNames.VelocityVector(D), new string[] { VariableNames.ViscosityMolecular }, CodNames, QuadOrderFunc.Linear());

                for (int d = 0; d < D; d++)
                {
                    if ((this.whichTerms & Terms.T1) != 0)
                    {
                        var flx1 = new swipViscosity_Term1(penalty_base * penalty_factor, d, D, BcMap, ViscosityOption.VariableViscosity);

                        flx1.g_Diri_Override = this.solution.U;
                        flx1.g_Neu_Override  = this.solution.dU;
                        Operator.EquationComponents[CodNames[d]].Add(flx1);
                    }
                    if ((this.whichTerms & Terms.T2) != 0)
                    {
                        var flx2 = new swipViscosity_Term2(penalty_base * penalty_factor, d, D, BcMap, ViscosityOption.VariableViscosity);

                        flx2.g_Diri_Override = this.solution.U;
                        flx2.g_Neu_Override  = this.solution.dU;
                        Operator.EquationComponents[CodNames[d]].Add(flx2);
                    }
                    if ((this.whichTerms & Terms.T3) != 0)
                    {
                        var flx3 = new swipViscosity_Term3(penalty_base * penalty_factor, d, D, BcMap, ViscosityOption.VariableViscosity);

                        flx3.g_Diri_Override = this.solution.U;
                        flx3.g_Neu_Override  = this.solution.dU;
                        Operator.EquationComponents[CodNames[d]].Add(flx3);
                    }
                } // */
                Operator.Commit();


                var map = this.U.Mapping;
                OperatorMtx = new MsrMatrix(map, map);
                Operator.ComputeMatrixEx(map, new DGField[] { this.mu }, map,
                                         OperatorMtx, this.bnd.CoordinateVector,
                                         volQuadScheme: null, edgeQuadScheme: null);

                // test for matrix symmetry
                // ========================

                if (base.MPISize == 1)
                {
                    double MatrixAssymmetry = OperatorMtx.SymmetryDeviation();
                    Console.WriteLine("Matrix asymmetry: " + MatrixAssymmetry);
                    Assert.LessOrEqual(Math.Abs(MatrixAssymmetry), 1.0e-10);
                }
            }
        }
示例#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
                        }
                    }
                });
            }
示例#17
0
        /// <summary>
        /// Includes assembly of the matrix.
        /// </summary>
        /// <param name="L"></param>
        protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L)
        {
            using (FuncTrace tr = new FuncTrace()) {
                // create operator
                // ===============
                SpatialOperator LapaceIp;
                {
                    double D              = this.GridData.SpatialDimension;
                    double penalty_base   = (T.Basis.Degree + 1) * (T.Basis.Degree + D) / D;
                    double penalty_factor = base.Control.penalty_poisson;

                    BoundaryCondMap <BoundaryType> PoissonBcMap = new BoundaryCondMap <BoundaryType>(this.GridData, this.Control.BoundaryValues, "T");

                    LapaceIp = new SpatialOperator(1, 1, QuadOrderFunc.SumOfMaxDegrees(), "T", "T");
                    var flux = new ipFlux(penalty_base * base.Control.penalty_poisson, this.GridData.Cells.cj, PoissonBcMap);
                    LapaceIp.EquationComponents["T"].Add(flux);

                    LapaceIp.Commit();
                }

                // Create Matrices
                // ===============

                {
                    // time measurement for matrix assembly
                    Stopwatch stw = new Stopwatch();
                    stw.Start();

                    // console
                    Console.WriteLine("creating sparse system for {0} DOF's ...", T.Mapping.Ntotal);

                    // quadrature domain
                    var volQrSch = new CellQuadratureScheme(true, CellMask.GetFullMask(this.GridData));
                    var edgQrSch = new EdgeQuadratureScheme(true, EdgeMask.GetFullMask(this.GridData));

#if DEBUG
                    // in DEBUG mode, we compare 'MsrMatrix' (old, reference implementation) and 'BlockMsrMatrix' (new standard)
                    var RefLaplaceMtx = new MsrMatrix(T.Mapping);
#endif
                    using (new BlockTrace("SipMatrixAssembly", tr)) {
                        LaplaceMtx    = new BlockMsrMatrix(T.Mapping);
                        LaplaceAffine = new double[T.Mapping.LocalLength];

                        LapaceIp.ComputeMatrixEx(T.Mapping, null, T.Mapping,
                                                 LaplaceMtx, LaplaceAffine,
                                                 volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch);
                    }
#if DEBUG
                    LaplaceAffine.ClearEntries();
                    LapaceIp.ComputeMatrixEx(T.Mapping, null, T.Mapping,
                                             RefLaplaceMtx, LaplaceAffine,
                                             volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch);
                    MsrMatrix ErrMtx = RefLaplaceMtx.CloneAs();
                    ErrMtx.Acc(-1.0, LaplaceMtx);
                    double err    = ErrMtx.InfNorm();
                    double infNrm = LaplaceMtx.InfNorm();
                    Console.WriteLine("Matrix comparison error: " + err + ", matrix norm is: " + infNrm);
                    Assert.Less(err, infNrm * 1e-10, "MsrMatrix2 comparison failed.");
#endif
                    stw.Stop();
                    Console.WriteLine("done {0} sec.", stw.Elapsed.TotalSeconds);
                }


                //double condNo = LaplaceMtx.condest(BatchmodeConnector.Flavor.Octave);
                //Console.WriteLine("condition number: {0:0.####E-00} ",condNo);
            }
        }