示例#1
0
 public void MakeContinuous(SinglePhaseField DGLevelSet, SinglePhaseField LevelSet, CellMask Domain)
 {
     FEMLevSet.ProjectDGField(1.0, DGLevelSet, Domain);
     LevelSet.Clear();
     FEMLevSet.AccToDGField(1.0, LevelSet, Domain);
     LevelSet.AccLaidBack(1.0, DGLevelSet, Domain.Complement());
 }
示例#2
0
 public void MakeContinuous(SinglePhaseField DGLevelSet, SinglePhaseField LevelSet, CellMask Domain)
 {
     if (ReferenceEquals(DGLevelSet, LevelSet))
     {
         // Do nothing
     }
     else
     {
         LevelSet.Clear();
         LevelSet.AccLaidBack(1.0, DGLevelSet);
     }
 }
示例#3
0
        /// <summary>
        /// Computes the new level set field at time <paramref name="Phystime"/> + <paramref name="dt"/>.
        /// This is a 'driver function' which provides a universal interface to the various level set evolution algorithms.
        /// It also acts as a callback to the time stepper (see <see cref="m_BDF_Timestepper"/> resp. <see cref="m_RK_Timestepper"/>),
        /// i.e. it matches the signature of
        /// <see cref="BoSSS.Solution.XdgTimestepping.DelUpdateLevelset"/>.
        /// </summary>
        /// <param name="Phystime"></param>
        /// <param name="dt"></param>
        /// <param name="CurrentState">
        /// The current solution (velocity and pressure), since the complete solution is provided by the time stepper,
        /// only the velocity components(supposed to be at the beginning) are used.
        /// </param>
        /// <param name="underrelax">
        /// </param>
        public double DelUpdateLevelSet(DGField[] CurrentState, double Phystime, double dt, double underrelax, bool incremental)
        {
            using (new FuncTrace()) {
                //dt *= underrelax;
                int       D           = base.Grid.SpatialDimension;
                int       iTimestep   = hack_TimestepIndex;
                DGField[] EvoVelocity = CurrentState.GetSubVector(0, D);


                // ========================================================
                // Backup old level-set, in order to compute the residual
                // ========================================================

                SinglePhaseField LsBkUp = new SinglePhaseField(this.LevSet.Basis);
                LsBkUp.Acc(1.0, this.LevSet);
                CellMask oldCC = LsTrk.Regions.GetCutCellMask();

                // ====================================================
                // set evolution velocity, but only on the CUT-cells
                // ====================================================

                #region Calculate density averaged Velocity for each cell

                ConventionalDGField[] meanVelocity = GetMeanVelocityFromXDGField(EvoVelocity);

                #endregion


                // ===================================================================
                // backup interface properties (mass conservation, surface changerate)
                // ===================================================================

                #region backup interface props

                double oldSurfVolume  = 0.0;
                double oldSurfLength  = 0.0;
                double SurfChangerate = 0.0;
                if (this.Control.CheckInterfaceProps)
                {
                    oldSurfVolume  = XNSEUtils.GetSpeciesArea(this.LsTrk, LsTrk.GetSpeciesId("A"));
                    oldSurfLength  = XNSEUtils.GetInterfaceLength(this.LsTrk);
                    SurfChangerate = EnergyUtils.GetSurfaceChangerate(this.LsTrk, meanVelocity, this.m_HMForder);
                }

                #endregion

                // ====================================================
                // perform level-set evolution
                // ====================================================

                #region level-set evolution

                // set up for Strang splitting
                SinglePhaseField DGLevSet_old;
                if (incremental)
                {
                    DGLevSet_old = this.DGLevSet.Current.CloneAs();
                }
                else
                {
                    DGLevSet_old = this.DGLevSet[0].CloneAs();
                }


                // set up for underrelaxation
                SinglePhaseField DGLevSet_oldIter = this.DGLevSet.Current.CloneAs();

                //PlotCurrentState(hack_Phystime, new TimestepNumber(new int[] { hack_TimestepIndex, 0 }), 2);

                // actual evolution
                switch (this.Control.Option_LevelSetEvolution)
                {
                case LevelSetEvolution.None:
                    throw new ArgumentException("illegal call");

                case LevelSetEvolution.FastMarching: {
                    NarrowMarchingBand.Evolve_Mk2(
                        dt, this.LsTrk, DGLevSet_old, this.DGLevSet.Current, this.DGLevSetGradient,
                        meanVelocity, this.ExtensionVelocity.Current.ToArray(),      //new DGField[] { LevSetSrc },
                        this.m_HMForder, iTimestep);

                    //FastMarchReinitSolver = new FastMarchReinit(DGLevSet.Current.Basis);
                    //CellMask Accepted = LsTrk.Regions.GetCutCellMask();
                    //CellMask ActiveField = LsTrk.Regions.GetNearFieldMask(1);
                    //CellMask NegativeField = LsTrk.Regions.GetSpeciesMask("A");
                    //FastMarchReinitSolver.FirstOrderReinit(DGLevSet.Current, Accepted, NegativeField, ActiveField);

                    break;
                }

                case LevelSetEvolution.Fourier: {
                    Fourier_Timestepper.moveLevelSet(dt, meanVelocity);
                    if (incremental)
                    {
                        Fourier_Timestepper.updateFourierLevSet();
                    }
                    Fourier_LevSet.ProjectToDGLevelSet(this.DGLevSet.Current, this.LsTrk);
                    break;
                }

                case LevelSetEvolution.Prescribed: {
                    this.DGLevSet.Current.Clear();
                    this.DGLevSet.Current.ProjectField(1.0, this.Control.Phi.Vectorize(Phystime + dt));
                    break;
                }

                case LevelSetEvolution.ScalarConvection: {
                    var LSM = new LevelSetMover(EvoVelocity,
                                                this.ExtensionVelocity,
                                                this.LsTrk,
                                                XVelocityProjection.CutCellVelocityProjectiontype.L2_plain,
                                                this.DGLevSet,
                                                this.BcMap);

                    int check1 = this.ExtensionVelocity.PushCount;
                    int check2 = this.DGLevSet.PushCount;

                    this.DGLevSet[1].Clear();
                    this.DGLevSet[1].Acc(1.0, DGLevSet_old);
                    LSM.Advect(dt);

                    if (check1 != this.ExtensionVelocity.PushCount)
                    {
                        throw new ApplicationException();
                    }
                    if (check2 != this.DGLevSet.PushCount)
                    {
                        throw new ApplicationException();
                    }

                    break;
                }

                case LevelSetEvolution.ExtensionVelocity: {
                    DGLevSetGradient.Clear();
                    DGLevSetGradient.Gradient(1.0, DGLevSet.Current);

                    ExtVelMover.Advect(dt);

                    // Fast Marching: Specify the Domains first
                    // Perform Fast Marching only on the Far Field
                    if (this.Control.AdaptiveMeshRefinement)
                    {
                        int      NoCells = ((GridData)this.GridData).Cells.Count;
                        BitArray Refined = new BitArray(NoCells);
                        for (int j = 0; j < NoCells; j++)
                        {
                            if (((GridData)this.GridData).Cells.GetCell(j).RefinementLevel > 0)
                            {
                                Refined[j] = true;
                            }
                        }
                        CellMask Accepted      = new CellMask(this.GridData, Refined);
                        CellMask AcceptedNeigh = Accepted.AllNeighbourCells();

                        Accepted = Accepted.Union(AcceptedNeigh);
                        CellMask ActiveField   = Accepted.Complement();
                        CellMask NegativeField = LsTrk.Regions.GetSpeciesMask("A");
                        FastMarchReinitSolver.FirstOrderReinit(DGLevSet.Current, Accepted, NegativeField, ActiveField);
                    }
                    else
                    {
                        CellMask Accepted      = LsTrk.Regions.GetNearFieldMask(1);
                        CellMask ActiveField   = Accepted.Complement();
                        CellMask NegativeField = LsTrk.Regions.GetSpeciesMask("A");
                        FastMarchReinitSolver.FirstOrderReinit(DGLevSet.Current, Accepted, NegativeField, ActiveField);
                    }
                    //SubGrid AcceptedGrid = new SubGrid(Accepted);
                    //ReInitPDE.ReInitialize(Restriction: AcceptedGrid);

                    //CellMask ActiveField = Accepted.Complement();
                    //CellMask NegativeField = LsTrk.Regions.GetSpeciesMask("A");
                    //FastMarchReinitSolver.FirstOrderReinit(DGLevSet.Current, Accepted, NegativeField, ActiveField);

                    //ReInitPDE.ReInitialize();

                    break;
                }

                default:
                    throw new ApplicationException();
                }


                // performing underrelaxation
                if (underrelax < 1.0)
                {
                    this.DGLevSet.Current.Scale(underrelax);
                    this.DGLevSet.Current.Acc((1.0 - underrelax), DGLevSet_oldIter);
                }

                //PlotCurrentState(hack_Phystime, new TimestepNumber(new int[] { hack_TimestepIndex, 1 }), 2);


                #endregion


                // ======================
                // postprocessing
                // =======================

                if (this.Control.ReInitPeriod > 0 && hack_TimestepIndex % this.Control.ReInitPeriod == 0)
                {
                    Console.WriteLine("Filtering DG-LevSet");
                    SinglePhaseField FiltLevSet = new SinglePhaseField(DGLevSet.Current.Basis);
                    FiltLevSet.AccLaidBack(1.0, DGLevSet.Current);
                    Filter(FiltLevSet, 2, oldCC);
                    DGLevSet.Current.Clear();
                    DGLevSet.Current.Acc(1.0, FiltLevSet);

                    Console.WriteLine("FastMarchReInit performing FirstOrderReInit");
                    FastMarchReinitSolver = new FastMarchReinit(DGLevSet.Current.Basis);
                    CellMask Accepted      = LsTrk.Regions.GetCutCellMask();
                    CellMask ActiveField   = LsTrk.Regions.GetNearFieldMask(1);
                    CellMask NegativeField = LsTrk.Regions.GetSpeciesMask("A");
                    FastMarchReinitSolver.FirstOrderReinit(DGLevSet.Current, Accepted, NegativeField, ActiveField);
                }

                #region ensure continuity

                // make level set continuous
                CellMask CC    = LsTrk.Regions.GetCutCellMask4LevSet(0);
                CellMask Near1 = LsTrk.Regions.GetNearMask4LevSet(0, 1);
                CellMask PosFF = LsTrk.Regions.GetLevelSetWing(0, +1).VolumeMask;
                ContinuityEnforcer.MakeContinuous(this.DGLevSet.Current, this.LevSet, Near1, PosFF);

                if (this.Control.Option_LevelSetEvolution == LevelSetEvolution.FastMarching)
                {
                    CellMask Nearband = Near1.Union(CC);
                    this.DGLevSet.Current.Clear(Nearband);
                    this.DGLevSet.Current.AccLaidBack(1.0, this.LevSet, Nearband);
                    //ContinuityEnforcer.SetFarField(this.DGLevSet.Current, Near1, PosFF);
                }

                //PlotCurrentState(hack_Phystime, new TimestepNumber(new int[] { hack_TimestepIndex, 2 }), 2);

                #endregion


                for (int d = 0; d < D; d++)
                {
                    this.XDGvelocity.Velocity[d].UpdateBehaviour = BehaveUnder_LevSetMoovement.AutoExtrapolate;
                }



                // ===============
                // tracker update
                // ===============

                this.LsTrk.UpdateTracker(Phystime + dt, incremental: true);

                // update near field (in case of adaptive mesh refinement)
                if (this.Control.AdaptiveMeshRefinement && this.Control.Option_LevelSetEvolution == LevelSetEvolution.FastMarching)
                {
                    Near1 = LsTrk.Regions.GetNearMask4LevSet(0, 1);
                    PosFF = LsTrk.Regions.GetLevelSetWing(0, +1).VolumeMask;
                    ContinuityEnforcer.SetFarField(this.DGLevSet.Current, Near1, PosFF);
                    ContinuityEnforcer.SetFarField(this.LevSet, Near1, PosFF);
                }


                // ==================================================================
                // check interface properties (mass conservation, surface changerate)
                // ==================================================================

                if (this.Control.CheckInterfaceProps)
                {
                    double currentSurfVolume = XNSEUtils.GetSpeciesArea(this.LsTrk, LsTrk.GetSpeciesId("A"));
                    double massChange        = ((currentSurfVolume - oldSurfVolume) / oldSurfVolume) * 100;
                    Console.WriteLine("Change of mass = {0}%", massChange);

                    double currentSurfLength    = XNSEUtils.GetInterfaceLength(this.LsTrk);
                    double actualSurfChangerate = (currentSurfLength - oldSurfLength) / dt;
                    Console.WriteLine("Interface divergence = {0}", SurfChangerate);
                    Console.WriteLine("actual surface changerate = {0}", actualSurfChangerate);
                }


                // ==================
                // compute residual
                // ==================

                var newCC = LsTrk.Regions.GetCutCellMask();
                LsBkUp.Acc(-1.0, this.LevSet);
                double LevSetResidual = LsBkUp.L2Norm(newCC.Union(oldCC));

                return(LevSetResidual);
            }
        }
示例#4
0
        /// <summary>
        /// Single run of the solver
        /// </summary>
        protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt)
        {
            using (new FuncTrace()) {
                if (Control.ExactSolution_provided)
                {
                    Tex.Clear();
                    Tex.ProjectField(this.Control.InitialValues_Evaluators["Tex"]);

                    RHS.Clear();
                    RHS.ProjectField(this.Control.InitialValues_Evaluators["RHS"]);
                }

                if (Control.AdaptiveMeshRefinement == false)
                {
                    base.NoOfTimesteps = -1;
                    if (TimestepNo > 1)
                    {
                        throw new ApplicationException("steady-state-equation.");
                    }
                    base.TerminationKey = true;
                }

                // Update matrices
                // ---------------

                UpdateMatrices();


                // call solver
                // -----------
                double mintime, maxtime;
                bool   converged;
                int    NoOfIterations;

                ClassicSolve(out mintime, out maxtime, out converged, out NoOfIterations);


                Console.WriteLine("finished; " + NoOfIterations + " iterations.");
                Console.WriteLine("converged? " + converged);
                Console.WriteLine("Timespan: " + mintime + " to " + maxtime + " seconds");


                base.QueryHandler.ValueQuery("minSolRunT", mintime, true);
                base.QueryHandler.ValueQuery("maxSolRunT", maxtime, true);
                base.QueryHandler.ValueQuery("Conv", converged ? 1.0 : 0.0, true);
                base.QueryHandler.ValueQuery("NoIter", NoOfIterations, true);
                base.QueryHandler.ValueQuery("NoOfCells", this.GridData.CellPartitioning.TotalLength, true);
                base.QueryHandler.ValueQuery("DOFs", T.Mapping.TotalLength, true);
                base.QueryHandler.ValueQuery("BlockSize", T.Basis.Length, true);



                if (base.Control.ExactSolution_provided)
                {
                    Error.Clear();
                    Error.AccLaidBack(1.0, Tex);
                    Error.AccLaidBack(-1.0, T);

                    double L2_ERR = Error.L2Norm();
                    Console.WriteLine("\t\tL2 error on " + this.Grid.NumberOfCells + ": " + L2_ERR);
                    base.QueryHandler.ValueQuery("SolL2err", L2_ERR, true);
                }

                // evaluate residual
                // =================
                {
                    this.ResiualKP1.Clear();
                    if (this.Control.InitialValues_Evaluators.ContainsKey("RHS"))
                    {
                        this.ResiualKP1.ProjectField(this.Control.InitialValues_Evaluators["RHS"]);
                    }

                    var ev = this.LapaceIp.GetEvaluator(T.Mapping, ResiualKP1.Mapping);
                    ev.Evaluate(-1.0, 1.0, ResiualKP1.CoordinateVector);
                }

                // return
                // ======

                return(0.0);
            }
        }
示例#5
0
        /// <summary>
        /// Update scalar field variables after solving scalar equation.
        /// </summary>
        /// <param name="SolverConf"></param>
        /// <param name="ModeRelaxScalar"></param>
        /// <param name="relax_scalar"></param>
        /// <param name="Scalar"></param>
        /// <param name="ScalarRes"></param>
        /// <param name="ScalarMean"></param>
        /// <param name="Rho"></param>
        /// <param name="Eta"></param>
        /// <param name="RhoMatrix"></param>
        /// <param name="EoS"></param>
        /// <param name="ThermodynamicPressure">Null for multiphase flows.</param>
        public static void UpdateScalarFieldVariables(SIMPLEControl SolverConf, RelaxationTypes ModeRelaxScalar, double relax_scalar,
                                                      ScalarFieldHistory <SinglePhaseField> Scalar, SinglePhaseField ScalarRes, SinglePhaseField ScalarMean,
                                                      SinglePhaseField Rho, SinglePhaseField Eta, QuadratureMatrix RhoMatrix, MaterialLaw EoS,
                                                      SinglePhaseField ThermodynamicPressure, bool UpdateRhoVisc = true)
        {
            using (new FuncTrace()) {
                // Explicit Under-Relaxation of scalar variable
                // ============================================

                if (ModeRelaxScalar == RelaxationTypes.Explicit)
                {
                    // phi = alpha * phi_new + (1-alpha) * phi_old
                    Scalar.Current.Scale(relax_scalar);
                    Scalar.Current.Acc((1.0 - relax_scalar), ScalarRes);
                }

                // Scalar residual
                // ===============

                ScalarRes.Scale(-1.0);
                ScalarRes.Acc(1.0, Scalar.Current);

                // ScalarMean
                // ==========

                ScalarMean.Clear();
                ScalarMean.AccLaidBack(1.0, Scalar.Current);

                // Thermodynamic pressure - only for Low-Mach number flows
                // =======================================================

                switch (SolverConf.PhysicsMode)
                {
                case PhysicsMode.LowMach:
                    LowMachSIMPLEControl lowMachConf = SolverConf as LowMachSIMPLEControl;
                    if (lowMachConf.ThermodynamicPressureMode == ThermodynamicPressureMode.MassDetermined)
                    {
                        ThermodynamicPressure.Clear();
                        ThermodynamicPressure.AccConstant(((MaterialLawLowMach)EoS).GetMassDeterminedThermodynamicPressure(lowMachConf.InitialMass.Value, Scalar.Current));
                    }
                    break;

                case PhysicsMode.Multiphase:
                    break;

                default:
                    throw new ApplicationException();
                }

                if (UpdateRhoVisc)
                {
                    // Density
                    // =======

                    Rho.Clear();
                    Rho.ProjectFunction(1.0, EoS.GetDensity, null, Scalar.Current);
                    RhoMatrix.Update();

                    // Viscosity
                    // =========

                    Eta.Clear();
                    Eta.ProjectFunction(1.0, EoS.GetViscosity, null, Scalar.Current);
                }
            }
        }
示例#6
0
        /// <summary>
        /// Create Spatial Operators and build the corresponding Matrices
        /// </summary>
        public void ComputeMatrices(IList <DGField> InterfaceParams, bool nearfield)
        {
            OpMatrix = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping);
            OpAffine = new double[OpMatrix.RowPartitioning.LocalLength];

            OpMatrix_bulk = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping);
            OpAffine_bulk = new double[OpMatrix.RowPartitioning.LocalLength];

            OpMatrix_interface = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping);
            OpAffine_interface = new double[OpMatrix.RowPartitioning.LocalLength];


            //LevelSetTracker.GetLevelSetGradients(0,);

            // bulk part of the matrix
            //Operator_bulk.ComputeMatrix(
            //    Extension.Mapping,
            //    LevelSetGradient.ToArray(),
            //    Extension.Mapping,
            //    OpMatrix_bulk, OpAffine_bulk,
            //    OnlyAffine: false, sgrd: null);

            switch (Control.FluxVariant)
            {
            case FluxVariant.GradientBased:
                // Flux Direction based on Mean Level Set Gradient
                BulkParams = new List <DGField> {
                };                                      // Hack, to make ArrayTools.Cat produce a List of DGFields
                // second Hack: Does only work, when InterfaceParams is according to a single component flux,
                // else, we will have to change the boundary edge flux
                BulkParams = ArrayTools.Cat(BulkParams, LevelSetGradient.ToArray(), Phi, MeanLevelSetGradient.ToArray(), InterfaceParams.ToArray());
                MeanLevelSetGradient.Clear();
                MeanLevelSetGradient.AccLaidBack(1.0, LevelSetGradient);
                break;

            case FluxVariant.ValueBased:
                // Flux Direction Based on Cell-Averaged Level-Set Value
                BulkParams = ArrayTools.Cat(LevelSetGradient.ToArray(), Phi, MeanLevelSet);
                MeanLevelSet.Clear();
                MeanLevelSet.AccLaidBack(1.0, Phi);
                break;

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

            default:
                throw new Exception();
            }

            // Build Operator

            Operator_bulk.ComputeMatrixEx(Extension.Mapping,
                                          BulkParams,
                                          Extension.Mapping,
                                          OpMatrix_bulk, OpAffine_bulk,
                                          OnlyAffine: false,
                                          time: 0.0,
                                          edgeQuadScheme: new EdgeQuadratureScheme(true, nearfield ? LevelSetTracker.Regions.GetNearFieldSubgrid(1).InnerEdgesMask : null),
                                          volQuadScheme: new CellQuadratureScheme(true, nearfield ? LevelSetTracker.Regions.GetNearFieldSubgrid(1).VolumeMask : null)
                                          );

            Operator_interface.ComputeMatrixEx(
                LevelSetTracker,
                Extension.Mapping,
                InterfaceParams,
                Extension.Mapping,
                OpMatrix_interface,
                OpAffine_interface,
                OnlyAffine: false,
                time: 0,
                MPIParameterExchange: false,
                whichSpc: LevelSetTracker.GetSpeciesId("A")
                );
#if DEBUG
            OpMatrix_bulk.CheckForNanOrInfM();
            OpAffine_bulk.CheckForNanOrInfV();

            OpMatrix_interface.CheckForNanOrInfM();
            OpAffine_interface.CheckForNanOrInfV();
#endif

            //Only for Debugging purposes
            //OpMatrix.SaveToTextFileSparse("C:\\tmp\\EllipticReInit.txt");

            Debug.Assert(OpMatrix_interface.GetDiagVector().L2Norm() > 0, "L2-Norm of Diagonal of InterfaceOperator is 0");
            Debug.Assert(OpMatrix_bulk.GetDiagVector().L2Norm() > 0, "L2-Norm of Diagonal of BulkOperator is 0");
#if DEBUG
            //Console.WriteLine( "L2-Norm of Diagonal of InterfaceOperator is {0}", OpMatrix_interface.GetDiagVector().L2Norm() );
#endif
            OpMatrix.Clear();
            OpMatrix.Acc(1.0, OpMatrix_bulk);
            OpMatrix.Acc(1.0, OpMatrix_interface);
            //Console.WriteLine("Op-Matrix Symmetry-Deviation: {0}", OpMatrix.SymmetryDeviation());
            OpMatrix.AssumeSymmetric = false;

            OpAffine.Clear();
            OpAffine.AccV(1.0, OpAffine_bulk);
            OpAffine.AccV(1.0, OpAffine_interface);
#if DEBUG
            //Console.WriteLine("Condition Number of Extension Operator {0}", OpMatrix.condest());
#endif
        }
示例#7
0
        /// <summary>
        /// Solution of the system
        /// <see cref="LaplaceMtx"/>*<see cref="T"/> + <see cref="LaplaceAffine"/> = <see cref="RHS"/>
        /// using the modular solver framework.
        /// </summary>
        private void ExperimentalSolve(out double mintime, out double maxtime, out bool Converged, out int NoOfIter) {
            using (var tr = new FuncTrace()) {
                int p = this.T.Basis.Degree;
                var MgSeq = this.MultigridSequence;
                mintime = double.MaxValue;
                maxtime = 0;
                Converged = false;
                NoOfIter = int.MaxValue;

                Console.WriteLine("Construction of Multigrid basis...");
                Stopwatch mgBasis = new Stopwatch();
                mgBasis.Start();
                AggregationGridBasis[][] AggBasis;
                using (new BlockTrace("Aggregation_basis_init", tr)) {
                    AggBasis = AggregationGridBasis.CreateSequence(MgSeq, new Basis[] { this.T.Basis });
                }
                mgBasis.Stop();
                Console.WriteLine("done. (" + mgBasis.Elapsed.TotalSeconds + " sec)");


                //foreach (int sz in new int[] { 1000, 2000, 5000, 10000, 20000 }) {
                //    base.Control.TargetBlockSize = sz;

                for (int irun = 0; irun < base.Control.NoOfSolverRuns; irun++) {
                    Stopwatch stw = new Stopwatch();
                    stw.Reset();
                    stw.Start();

                    Console.WriteLine("Setting up multigrid operator...");
                    var mgsetup = new Stopwatch();
                    mgsetup.Start();
                    var MultigridOp = new MultigridOperator(AggBasis, this.T.Mapping, this.LaplaceMtx, null, MgConfig);
                    mgsetup.Stop();
                    Console.WriteLine("done. (" + mgsetup.Elapsed.TotalSeconds + " sec)");


                    Console.WriteLine("Setting up solver...");
                    var solverSetup = new Stopwatch();
                    solverSetup.Start();
                    ISolverSmootherTemplate solver;
                    switch (base.Control.solver_name) {
                        case SolverCodes.exp_direct:
                            solver = new DirectSolver() {
                                WhichSolver = DirectSolver._whichSolver.PARDISO
                            };
                            break;

                        case SolverCodes.exp_direct_lapack:
                            solver = new DirectSolver() {
                                WhichSolver = DirectSolver._whichSolver.Lapack
                            };
                            break;

                        case SolverCodes.exp_softpcg_schwarz_directcoarse: {
                                double LL = this.LaplaceMtx._RowPartitioning.LocalLength;
                                int NoOfBlocks = (int)Math.Max(1, Math.Round(LL / (double)this.Control.TargetBlockSize));
                                Console.WriteLine("Additive Schwarz w. direct coarse, No of blocks: " + NoOfBlocks.MPISum());
                                solver = new SoftPCG() {
                                    m_MaxIterations = 50000,
                                    m_Tolerance = 1.0e-10,
                                    Precond = new Schwarz() {
                                        m_MaxIterations = 1,
                                        //CoarseSolver = new GenericRestriction() {
                                        //    CoarserLevelSolver = new GenericRestriction() {
                                        CoarseSolver = new DirectSolver() {
                                            WhichSolver = DirectSolver._whichSolver.PARDISO
                                            //            }
                                            //}
                                        },
                                        m_BlockingStrategy = new Schwarz.METISBlockingStrategy() {
                                            NoOfPartsPerProcess = NoOfBlocks
                                        },
                                        Overlap = 1,

                                    }
                                };
                                break;
                            }

                        case SolverCodes.exp_softpcg_schwarz: {
                                double LL = this.LaplaceMtx._RowPartitioning.LocalLength;
                                int NoOfBlocks = (int)Math.Max(1, Math.Round(LL / (double)this.Control.TargetBlockSize));
                                Console.WriteLine("Additive Schwarz, No of blocks: " + NoOfBlocks.MPISum());

                                solver = new SoftPCG() {
                                    m_MaxIterations = 50000,
                                    m_Tolerance = 1.0e-10,
                                    Precond = new Schwarz() {
                                        m_MaxIterations = 1,
                                        CoarseSolver = null,
                                        m_BlockingStrategy = new Schwarz.METISBlockingStrategy {
                                            NoOfPartsPerProcess = NoOfBlocks
                                        },
                                        Overlap = 1
                                    }
                                };
                                break;
                            }

                        case SolverCodes.exp_softpcg_mg:
                            solver = MultilevelSchwarz(MultigridOp);
                            break;


                        case SolverCodes.exp_Kcycle_schwarz:
                            solver = KcycleMultiSchwarz(MultigridOp);
                            break;

                        default:
                            throw new ApplicationException("unknown solver: " + this.Control.solver_name);
                    }

                    T.Clear();
                    T.AccLaidBack(1.0, Tex);
                    ConvergenceObserver CO = null;
                    //CO = new ConvergenceObserver(MultigridOp, null, T.CoordinateVector.ToArray());
                    //CO.TecplotOut = "oasch";
                    if (solver is ISolverWithCallback) {

                        if (CO == null) {
                            ((ISolverWithCallback)solver).IterationCallback = delegate (int iter, double[] xI, double[] rI, MultigridOperator mgOp) {
                                double l2_RES = rI.L2NormPow2().MPISum().Sqrt();

                                double[] xRef = new double[xI.Length];
                                MultigridOp.TransformSolInto(T.CoordinateVector, xRef);

                                double l2_ERR = GenericBlas.L2DistPow2(xI, xRef).MPISum().Sqrt();
                                Console.WriteLine("Iter: {0}\tRes: {1:0.##E-00}\tErr: {2:0.##E-00}\tRunt: {3:0.##E-00}", iter, l2_RES, l2_ERR, stw.Elapsed.TotalSeconds);
                                //Tjac.CoordinatesAsVector.SetV(xI);
                                //Residual.CoordinatesAsVector.SetV(rI);
                                //PlotCurrentState(iter, new TimestepNumber(iter), 3);
                            };
                        } else {
                            ((ISolverWithCallback)solver).IterationCallback = CO.IterationCallback;
                        }
                    }


                    using (new BlockTrace("Solver_Init", tr)) {
                        solver.Init(MultigridOp);
                    }
                    solverSetup.Stop();
                    Console.WriteLine("done. (" + solverSetup.Elapsed.TotalSeconds + " sec)");

                    Console.WriteLine("Running solver...");
                    var solverIteration = new Stopwatch();
                    solverIteration.Start();
                    double[] T2 = this.T.CoordinateVector.ToArray();
                    using (new BlockTrace("Solver_Run", tr)) {
                        solver.ResetStat();
                        T2.Clear();
                        var RHSvec = RHS.CoordinateVector.ToArray();
                        BLAS.daxpy(RHSvec.Length, -1.0, this.LaplaceAffine, 1, RHSvec, 1);
                        MultigridOp.UseSolver(solver, T2, RHSvec);
                        T.CoordinateVector.SetV(T2);
                    }
                    solverIteration.Stop();
                    Console.WriteLine("done. (" + solverIteration.Elapsed.TotalSeconds + " sec)");

                    Console.WriteLine("Pardiso phase 11: " + ilPSP.LinSolvers.PARDISO.PARDISOSolver.Phase_11.Elapsed.TotalSeconds);
                    Console.WriteLine("Pardiso phase 22: " + ilPSP.LinSolvers.PARDISO.PARDISOSolver.Phase_22.Elapsed.TotalSeconds);
                    Console.WriteLine("Pardiso phase 33: " + ilPSP.LinSolvers.PARDISO.PARDISOSolver.Phase_33.Elapsed.TotalSeconds);

                    // time measurement, statistics
                    stw.Stop();
                    mintime = Math.Min(stw.Elapsed.TotalSeconds, mintime);
                    maxtime = Math.Max(stw.Elapsed.TotalSeconds, maxtime);
                    Converged = solver.Converged;
                    NoOfIter = solver.ThisLevelIterations;

                    if (CO != null)
                        CO.PlotTrend(true, true, true);

                }
            }
        }
示例#8
0
        /// <summary>
        /// Create Spatial Operators and build the corresponding Matrices
        /// </summary>
        public void ComputeMatrices(IList <DGField> InterfaceParams, bool nearfield)
        {
            OpMatrix = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping);
            OpAffine = new double[OpMatrix.RowPartitioning.LocalLength];

            OpMatrix_bulk = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping);
            OpAffine_bulk = new double[OpMatrix.RowPartitioning.LocalLength];

            OpMatrix_interface = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping);
            OpAffine_interface = new double[OpMatrix.RowPartitioning.LocalLength];


            //LevelSetTracker.GetLevelSetGradients(0,);

            // bulk part of the matrix
            //Operator_bulk.ComputeMatrix(
            //    Extension.Mapping,
            //    LevelSetGradient.ToArray(),
            //    Extension.Mapping,
            //    OpMatrix_bulk, OpAffine_bulk,
            //    OnlyAffine: false, sgrd: null);

            switch (Control.FluxVariant)
            {
            case FluxVariant.GradientBased:
                // Flux Direction based on Mean Level Set Gradient
                BulkParams = new List <DGField> {
                };                                      // Hack, to make ArrayTools.Cat produce a List of DGFields
                // second Hack: Does only work, when InterfaceParams is according to a single component flux,
                // else, we will have to change the boundary edge flux
                BulkParams = ArrayTools.Cat(BulkParams, LevelSetGradient.ToArray(), Phi, MeanLevelSetGradient.ToArray(), InterfaceParams.ToArray());
                MeanLevelSetGradient.Clear();
                MeanLevelSetGradient.AccLaidBack(1.0, LevelSetGradient);
                break;

            case FluxVariant.ValueBased:
                // Flux Direction Based on Cell-Averaged Level-Set Value
                BulkParams = ArrayTools.Cat(LevelSetGradient.ToArray(), Phi, MeanLevelSet);
                MeanLevelSet.Clear();
                MeanLevelSet.AccLaidBack(1.0, Phi);
                break;

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

            default:
                throw new Exception();
            }

            // Build Operator

            Operator_bulk.ComputeMatrixEx(Extension.Mapping,
                                          BulkParams,
                                          Extension.Mapping,
                                          OpMatrix_bulk, OpAffine_bulk,
                                          OnlyAffine: false,
                                          time: 0.0,
                                          edgeQuadScheme: new EdgeQuadratureScheme(true, nearfield ? LevelSetTracker.Regions.GetNearFieldSubgrid(1).InnerEdgesMask : null),
                                          volQuadScheme: new CellQuadratureScheme(true, nearfield ? LevelSetTracker.Regions.GetNearFieldSubgrid(1).VolumeMask : null)
                                          );



            //Operator_interface.ComputeMatrixEx(
            //    LevelSetTracker,
            //    Extension.Mapping,
            //    InterfaceParams,
            //    Extension.Mapping,
            //    OpMatrix_interface,
            //    OpAffine_interface,
            //    OnlyAffine: false,
            //    time: 0,
            //    MPIParameterExchange: false,
            //    whichSpc: LevelSetTracker.GetSpeciesId("A")
            //    );

            Operator_interface.OperatorCoefficientsProvider =
                delegate(LevelSetTracker lstrk, SpeciesId spc, int quadOrder, int TrackerHistoryIdx, double time) {
                var r = new CoefficientSet()
                {
                };

                //throw new NotImplementedException("todo");
                return(r);
            };
            XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Operator_interface.GetMatrixBuilder(LevelSetTracker,
                                                                                                  Extension.Mapping, InterfaceParams, Extension.Mapping);

            MultiphaseCellAgglomerator dummy = LevelSetTracker.GetAgglomerator(LevelSetTracker.SpeciesIdS.ToArray(), 2 * Extension.Basis.Degree + 2, 0.0);

            mtxBuilder.CellLengthScales.Add(LevelSetTracker.GetSpeciesId("A"), dummy.CellLengthScales[LevelSetTracker.GetSpeciesId("A")]);

            mtxBuilder.time           = 0;
            mtxBuilder.MPITtransceive = false;
            mtxBuilder.ComputeMatrix(OpMatrix_interface, OpAffine_interface);

#if DEBUG
            OpMatrix_bulk.CheckForNanOrInfM();
            OpAffine_bulk.CheckForNanOrInfV();

            OpMatrix_interface.CheckForNanOrInfM();
            OpAffine_interface.CheckForNanOrInfV();
#endif

            //Only for Debugging purposes

            Debug.Assert(OpMatrix_interface.GetDiagVector().L2Norm() > 0, "L2-Norm of Diagonal of InterfaceOperator is 0");
            Debug.Assert(OpMatrix_bulk.GetDiagVector().L2Norm() > 0, "L2-Norm of Diagonal of BulkOperator is 0");
#if DEBUG
            //Console.WriteLine( "L2-Norm of Diagonal of InterfaceOperator is {0}", OpMatrix_interface.GetDiagVector().L2Norm() );
#endif
            OpMatrix.Clear();
            OpMatrix.Acc(1.0, OpMatrix_bulk);
            OpMatrix.Acc(1.0, OpMatrix_interface);
            //Console.WriteLine("Op-Matrix Symmetry-Deviation: {0}", OpMatrix.SymmetryDeviation());
            OpMatrix.AssumeSymmetric = false;

            OpAffine.Clear();
            OpAffine.AccV(1.0, OpAffine_bulk);
            OpAffine.AccV(1.0, OpAffine_interface);
#if DEBUG
            //Console.WriteLine("Condition Number of Extension Operator {0}", OpMatrix.condest());
#endif
        }