private void ExperimentalSolver(out double mintime, out double maxtime, out bool Converged, out int NoOfIter, out int DOFs) { using (var tr = new FuncTrace()) { mintime = double.MaxValue; maxtime = 0; Converged = false; NoOfIter = int.MaxValue; DOFs = 0; AggregationGridBasis[][] XAggB; using (new BlockTrace("Aggregation_basis_init", tr)) { XAggB = AggregationGridBasis.CreateSequence(base.MultigridSequence, u.Mapping.BasisS); } XAggB.UpdateXdgAggregationBasis(this.Op_Agglomeration); var MassMatrix = this.Op_mass.GetMassMatrix(this.u.Mapping, new double[] { 1.0 }, false, this.LsTrk.SpeciesIdS.ToArray()); double[] _RHSvec = this.GetRHS(); Stopwatch stw = new Stopwatch(); stw.Reset(); stw.Start(); Console.WriteLine("Setting up multigrid operator..."); int p = this.u.Basis.Degree; var MultigridOp = new MultigridOperator(XAggB, this.u.Mapping, this.Op_Matrix, this.Op_mass.GetMassMatrix(new UnsetteledCoordinateMapping(this.u.Basis), false), OpConfig); Assert.True(MultigridOp != null); int L = MultigridOp.Mapping.LocalLength; DOFs = MultigridOp.Mapping.TotalLength; double[] RHSvec = new double[L]; MultigridOp.TransformRhsInto(_RHSvec, RHSvec); ISolverSmootherTemplate exsolver; SolverFactory SF = new SolverFactory(this.Control.NonLinearSolver, this.Control.LinearSolver); List <Action <int, double[], double[], MultigridOperator> > Callbacks = new List <Action <int, double[], double[], MultigridOperator> >(); Callbacks.Add(CustomItCallback); SF.GenerateLinear(out exsolver, MultigridSequence, OpConfig, Callbacks); using (new BlockTrace("Solver_Init", tr)) { exsolver.Init(MultigridOp); } /* * string filename = "XdgPoisson" + this.Grid.SpatialDimension + "p" + this.u.Basis.Degree + "R" + this.Grid.CellPartitioning.TotalLength; * MultigridOp.OperatorMatrix.SaveToTextFileSparse(filename + ".txt"); * RHSvec.SaveToTextFile(filename + "_rhs.txt"); * * var uEx = this.u.CloneAs(); * Op_Agglomeration.ClearAgglomerated(uEx.Mapping); * var CO = new ConvergenceObserver(MultigridOp, MassMatrix, uEx.CoordinateVector.ToArray()); * uEx = null; * CO.TecplotOut = "PoissonConvergence"; * //CO.PlotDecomposition(this.u.CoordinateVector.ToArray()); * * if (exsolver is ISolverWithCallback) { * ((ISolverWithCallback)exsolver).IterationCallback = CO.IterationCallback; * } * //*/ XDGField u2 = u.CloneAs(); using (new BlockTrace("Solver_Run", tr)) { // use solver (on XDG-field 'u2'). u2.Clear(); MultigridOp.UseSolver(exsolver, u2.CoordinateVector, _RHSvec); Console.WriteLine("Solver: {0}, converged? {1}, {2} iterations.", exsolver.GetType().Name, exsolver.Converged, exsolver.ThisLevelIterations); this.Op_Agglomeration.Extrapolate(u2.Mapping); Assert.IsTrue(exsolver.Converged, "Iterative solver did not converge."); } stw.Stop(); mintime = Math.Min(stw.Elapsed.TotalSeconds, mintime); maxtime = Math.Max(stw.Elapsed.TotalSeconds, maxtime); Converged = exsolver.Converged; NoOfIter = exsolver.ThisLevelIterations; // compute error between reference solution and multigrid solver XDGField ErrField = u2.CloneAs(); ErrField.Acc(-1.0, u); double ERR = ErrField.L2Norm(); double RelERR = ERR / u.L2Norm(); Assert.LessOrEqual(RelERR, 1.0e-6, "Result from iterative solver above threshold."); } }
private void RKstageImplicit(double PhysTime, double dt, double[][] k, int s, BlockMsrMatrix[] Mass, CoordinateVector u0, double ActualLevSetRelTime, double[] RK_as, double RelTime) { Debug.Assert(s < m_RKscheme.Stages); Debug.Assert(m_RKscheme.c[s] > 0); Debug.Assert(RK_as[s] != 0); int Ndof = m_CurrentState.Count; // ========= // RHS setup // ========= m_ImplStParams = new ImplicitStage_AssiParams() { m_CurrentDt = dt, m_CurrentPhystime = PhysTime, m_IterationCounter = 0, m_ActualLevSetRelTime = ActualLevSetRelTime, m_RelTime = RelTime, m_k = k, m_u0 = u0, m_Mass = Mass, m_RK_as = RK_as, m_s = s }; // ================ // solve the system // ================ NonlinearSolver nonlinSolver; ISolverSmootherTemplate linearSolver; GetSolver(out nonlinSolver, out linearSolver); if (RequiresNonlinearSolver) { // Nonlinear Solver (Navier-Stokes) // -------------------------------- nonlinSolver.SolverDriver(m_CurrentState, default(double[])); // Note: the RHS is passed as the affine part via 'this.SolverCallback' } else { // Linear Solver (Stokes) // ---------------------- // build the saddle-point matrix BlockMsrMatrix System, MaMa; double[] RHS; this.AssembleMatrixCallback(out System, out RHS, out MaMa, CurrentStateMapping.Fields.ToArray(), true); RHS.ScaleV(-1); // update the multigrid operator MultigridOperator mgOperator = new MultigridOperator(this.MultigridBasis, CurrentStateMapping, System, MaMa, this.Config_MultigridOperator); // init linear solver linearSolver.Init(mgOperator); // try to solve the saddle-point system. mgOperator.UseSolver(linearSolver, m_CurrentState, RHS); // 'revert' agglomeration m_CurrentAgglomeration.Extrapolate(CurrentStateMapping); } // ================ // reset // ================ m_ImplStParams = null; }
/// <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); } } }