public static void TestNonLinearSolverConfigurations() { //Arrange --- set configs var ACS = new AppControlSolver(); NonLinearSolverConfig nlconfig = ACS.NonLinearSolver; LinearSolverConfig lconfig = ACS.LinearSolver; lconfig.verbose = true; lconfig.NoOfMultigridLevels = 3; lconfig.TargetBlockSize = 10; nlconfig.verbose = true; var SF = new SolverFactory(nlconfig, lconfig); //Arrange --- get test multigrid operator stuff AggregationGridData[] seq; var MGO = Utils.CreateTestMGOperator(out seq, Resolution: 10); var map = MGO.Mapping; var changeofbasisis = Utils.GetAllMGConfig(MGO); var agggridbasisis = Utils.GetAllAggGridBasis(MGO); //Arrange --- get nonlinear codes available var nonlincodes = (NonLinearSolverCode[])Enum.GetValues(typeof(NonLinearSolverCode)); NonlinearSolver NLsolver = null; //Arrange --- get test linear Solver to set in NLsolver ISolverSmootherTemplate LinSolver = null; LinearSolverCode[] LinTestcandidates = { LinearSolverCode.classic_pardiso, LinearSolverCode.exp_gmres_levelpmg }; // in order to test the GMRES variants of the NL solver //Act and Assert foreach (var lincode in LinTestcandidates) { lconfig.SolverCode = lincode; TestDelegate nldlg = () => SF.GenerateNonLin(out NLsolver, out LinSolver, null, agggridbasisis, changeofbasisis, seq); SF.Clear(); foreach (NonLinearSolverCode nlcode in nonlincodes) { nlconfig.SolverCode = nlcode; if (nlconfig.SolverCode == NonLinearSolverCode.selfmade) { SF.Selfmade_nonlinsolver = new Newton(null, agggridbasisis, changeofbasisis); } Assert.DoesNotThrow(nldlg, "", null); Assert.IsNotNull(NLsolver); } Console.WriteLine("===="); } }
public void UseSolver <T1, T2>(ISolverSmootherTemplate solver, T1 INOUT_X, T2 IN_RHS, bool UseGuess = true) where T1 : IList <double> where T2 : IList <double> { if (this.LevelIndex != 0) { throw new NotSupportedException("Not Inteded to be called on any multi-grid level but the finest one."); } int I = this.Mapping.ProblemMapping.LocalLength; if (INOUT_X.Count != I) { throw new ArgumentException("Vector length mismatch.", "INOUT_X"); } if (IN_RHS.Count != I) { throw new ArgumentException("Vector length mismatch.", "IN_RHS"); } if (this.FinerLevel != null) { throw new NotSupportedException("This method may only be called on the top level."); } //if(this.Mapping.AggGrid.NoOfAggregateCells != this.Mapping.ProblemMapping.GridDat.Cells.NoOfCells) // throw new ArgumentException(); //int J = this.Mapping.AggGrid.NoOfAggregateCells; int L = this.Mapping.LocalLength; double[] X = new double[L]; double[] B = new double[L]; this.TransformRhsInto(IN_RHS, B); if (UseGuess) { this.TransformSolInto(INOUT_X, X); } solver.ResetStat(); solver.Solve(X, B); this.TransformSolFrom(INOUT_X, X); }
/// <summary> /// Returns either a solver for the Navier-Stokes or the Stokes system. /// E.g. for testing purposes, one might also use a nonlinear solver on a Stokes system. /// </summary> protected virtual string GetSolver(out NonlinearSolver nonlinSolver, out ISolverSmootherTemplate linearSolver) { nonlinSolver = null; linearSolver = null; if (Config_SpatialOperatorType != SpatialOperatorType.Nonlinear) { m_nonlinconfig.SolverCode = BoSSS.Solution.Control.NonLinearSolverCode.Picard; } XdgSolverFactory.GenerateNonLin(out nonlinSolver, out linearSolver, this.AssembleMatrixCallback, this.MultigridBasis, Config_MultigridOperator, MultigridSequence); string ls_strg = String.Format("{0}", m_linearconfig.SolverCode); string nls_strg = String.Format("{0}", m_nonlinconfig.SolverCode); if ((this.Config_LevelSetHandling == LevelSetHandling.Coupled_Iterative) && (nonlinSolver.Equals(typeof(FixpointIterator)))) { ((FixpointIterator)nonlinSolver).CoupledIteration_Converged = LevelSetConvergenceReached; } // set callback for diagnostic output // ---------------------------------- if (nonlinSolver != null) { nonlinSolver.IterationCallback += this.LogResis; if (linearSolver != null && linearSolver is ISolverWithCallback) { //((ISolverWithCallback)linearSolver).IterationCallback = this.MiniLogResi; } } else { if (linearSolver != null && linearSolver is ISolverWithCallback) { ((ISolverWithCallback)linearSolver).IterationCallback = this.LogResis; } } return(String.Format("nonlinear Solver: {0}, linear Solver: {1}", nls_strg, ls_strg)); }
public static void TestLinearSolverConfigurations() { //Arrange --- configs var ACS = new AppControlSolver(); LinearSolverConfig lconfig = ACS.LinearSolver; NonLinearSolverConfig nlconfig = ACS.NonLinearSolver; // is not of interest in this test, but we have to set this ... lconfig.verbose = true; lconfig.NoOfMultigridLevels = 3; lconfig.TargetBlockSize = 10; var SF = new SolverFactory(nlconfig, lconfig); //Arrange --- Multigrid stuff AggregationGridData[] seq; var MGO = Utils.CreateTestMGOperator(out seq, Resolution: 10); var changeofbasisis = Utils.GetAllMGConfig(MGO); var agggridbasisis = Utils.GetAllAggGridBasis(MGO); //Arrange --- get available lincodes var lincodes = (LinearSolverCode[])Enum.GetValues(typeof(LinearSolverCode)); ISolverSmootherTemplate LinSolver = null; TestDelegate lindlg = () => SF.GenerateLinear(out LinSolver, agggridbasisis, changeofbasisis); //Act and Assert foreach (LinearSolverCode code in lincodes) { SF.Clear(); lconfig.SolverCode = code; if (code == LinearSolverCode.selfmade) { SF.Selfmade_linsolver = new DirectSolver() { WhichSolver = DirectSolver._whichSolver.PARDISO } } ; Assert.DoesNotThrow(lindlg, "", null); Assert.IsNotNull(LinSolver); } }
/// <summary> /// Returns either a solver for the Navier-Stokes or the Stokes system. /// E.g. for testing purposes, one might also use a nonlinear solver on a Stokes system. /// </summary> /// <param name="nonlinSolver"></param> /// <param name="linearSolver"></param> protected virtual string GetSolver(out NonlinearSolver nonlinSolver, out ISolverSmootherTemplate linearSolver) { nonlinSolver = null; linearSolver = null; string solverDescription = ""; // this.Control.option_solver; //solverDescription = string.Format("; No. of cells: {0}, p = {1}/{2}; MaxKrylovDim {3}, MaxIter {4};", // this.GridData.Partitioning.TotalLength, // this.CurrentVel[0].Basis.Degree, // this.Pressure.Basis.Degree, // MaxKrylovDim, // MaxIterations); // define solver // ------------- if (this.RequiresNonlinearSolver) { // +++++++++++++++++++++++++++++++++++++++++++++ // the nonlinear solvers: // +++++++++++++++++++++++++++++++++++++++++++++ switch (Config_NonlinearSolver) { case NonlinearSolverMethod.Picard: nonlinSolver = new FixpointIterator( this.AssembleMatrixCallback, this.MultigridBasis, this.Config_MultigridOperator) { MaxIter = Config_MaxIterations, MinIter = Config_MinIterations, m_LinearSolver = Config_linearSolver, m_SessionPath = SessionPath, ConvCrit = Config_SolverConvergenceCriterion, UnderRelax = Config_UnderRelax, }; if (this.Config_LevelSetHandling == LevelSetHandling.Coupled_Iterative) { ((FixpointIterator)nonlinSolver).CoupledIteration_Converged = LevelSetConvergenceReached; } break; case NonlinearSolverMethod.Newton: nonlinSolver = new Newton( this.AssembleMatrixCallback, this.MultigridBasis, this.Config_MultigridOperator) { maxKrylovDim = Config_MaxKrylovDim, MaxIter = Config_MaxIterations, MinIter = Config_MinIterations, ApproxJac = Newton.ApproxInvJacobianOptions.DirectSolver, Precond = Config_linearSolver, GMRESConvCrit = Config_SolverConvergenceCriterion, ConvCrit = Config_SolverConvergenceCriterion, m_SessionPath = SessionPath, }; break; case NonlinearSolverMethod.NewtonGMRES: nonlinSolver = new Newton( this.AssembleMatrixCallback, this.MultigridBasis, this.Config_MultigridOperator) { maxKrylovDim = Config_MaxKrylovDim, MaxIter = Config_MaxIterations, MinIter = Config_MinIterations, ApproxJac = Newton.ApproxInvJacobianOptions.GMRES, Precond = Config_linearSolver, //Precond = new RheologyJacobiPrecond() { m_We = 0.1}, GMRESConvCrit = Config_SolverConvergenceCriterion, ConvCrit = Config_SolverConvergenceCriterion, m_SessionPath = SessionPath, }; break; default: throw new NotImplementedException(); } } else { // +++++++++++++++++++++++++++++++++++++++++++++ // the linear solvers: // +++++++++++++++++++++++++++++++++++++++++++++ linearSolver = Config_linearSolver; } // set callback for diagnostic output // ---------------------------------- if (nonlinSolver != null) { nonlinSolver.IterationCallback += this.LogResis; } if (linearSolver != null && linearSolver is ISolverWithCallback) { ((ISolverWithCallback)linearSolver).IterationCallback = this.LogResis; } // return // ------ return(solverDescription); }
/// <summary> /// Ganz ok. /// </summary> ISolverSmootherTemplate MultilevelSchwarz(MultigridOperator op) { var solver = new SoftPCG() { m_MaxIterations = 500, m_Tolerance = 1.0e-12 }; //var solver = new OrthonormalizationScheme() { // MaxIter = 500, // Tolerance = 1.0e-10, //}; //var solver = new SoftGMRES() { // m_MaxIterations = 500, // m_Tolerance = 1.0e-10, //}; // my tests show that the ideal block size may be around 10'000 int DirectKickIn = base.Control.TargetBlockSize; MultigridOperator Current = op; ISolverSmootherTemplate[] MultigridChain = new ISolverSmootherTemplate[base.MultigridSequence.Length]; for (int iLevel = 0; iLevel < base.MultigridSequence.Length; iLevel++) { int SysSize = Current.Mapping.TotalLength; int NoOfBlocks = (int)Math.Ceiling(((double)SysSize) / ((double)DirectKickIn)); bool useDirect = false; useDirect |= (SysSize < DirectKickIn); useDirect |= iLevel == base.MultigridSequence.Length - 1; useDirect |= NoOfBlocks.MPISum() <= 1; if (useDirect) { MultigridChain[iLevel] = new DirectSolver() { WhichSolver = DirectSolver._whichSolver.PARDISO, TestSolution = false }; } else { ClassicMultigrid MgLevel = new ClassicMultigrid() { m_MaxIterations = 1, m_Tolerance = 0.0 // termination controlled by top level PCG }; MultigridChain[iLevel] = MgLevel; ISolverSmootherTemplate pre, pst; if (iLevel > 0) { Schwarz swz1 = new Schwarz() { m_MaxIterations = 1, CoarseSolver = null, m_BlockingStrategy = new Schwarz.METISBlockingStrategy() { NoOfPartsPerProcess = NoOfBlocks }, Overlap = 0 // overlap does **NOT** seem to help }; SoftPCG pcg1 = new SoftPCG() { m_MinIterations = 5, m_MaxIterations = 5 }; SoftPCG pcg2 = new SoftPCG() { m_MinIterations = 5, m_MaxIterations = 5 }; var preChain = new ISolverSmootherTemplate[] { swz1, pcg1 }; var pstChain = new ISolverSmootherTemplate[] { swz1, pcg2 }; pre = new SolverSquence() { SolverChain = preChain }; pst = new SolverSquence() { SolverChain = pstChain }; } else { // +++++++++++++++++++++++++++++++++++++++++++++++++++ // top level - use only iterative (non-direct) solvers // +++++++++++++++++++++++++++++++++++++++++++++++++++ pre = new BlockJacobi() { NoOfIterations = 3, omega = 0.5 }; pst = new BlockJacobi() { NoOfIterations = 3, omega = 0.5 }; //preChain = new ISolverSmootherTemplate[] { pcg1 }; //pstChain = new ISolverSmootherTemplate[] { pcg2 }; } //if (iLevel > 0) { // MgLevel.PreSmoother = pre; // MgLevel.PostSmoother = pst; //} else { // //MgLevel.PreSmoother = pcg1; // ganz schlechte Idee, konvergiert gegen FALSCHE lösung // //MgLevel.PostSmoother = pcg2; // ganz schlechte Idee, konvergiert gegen FALSCHE lösung // MgLevel.PreSmoother = pre; // MgLevel.PostSmoother = pst; //} MgLevel.PreSmoother = pre; MgLevel.PostSmoother = pst; } if (iLevel > 0) { ((ClassicMultigrid)(MultigridChain[iLevel - 1])).CoarserLevelSolver = MultigridChain[iLevel]; } if (useDirect) { Console.WriteLine("MG: using {0} levels, lowest level DOF is {1}, target size is {2}.", iLevel + 1, SysSize, DirectKickIn); break; } Current = Current.CoarserLevel; } // end of level loop solver.Precond = MultigridChain[0]; //solver.PrecondS = new[] { MultigridChain[0] }; return solver; }
/// <summary> /// Automatic choice of linear solver depending on problem size, immersed boundary, polynomial degree, etc. /// </summary> static ISolverSmootherTemplate AutomaticChoice(IBM_Control Control, XdgBDFTimestepping Timestepper) { //int pV = Control.FieldOptions["VelocityX"].Degree; int pP = Control.FieldOptions["Pressure"].Degree; int pV = pP + 1; // Detecting variables for solver determination var D = Timestepper.MultigridSequence[0].SpatialDimension; var cellsLoc = Timestepper.MultigridSequence[0].CellPartitioning.LocalLength; var cellsGlo = Timestepper.MultigridSequence[0].CellPartitioning.TotalLength; ISolverSmootherTemplate tempsolve = null; var size = Timestepper.MultigridSequence[0].CellPartitioning.MpiSize; // !!!!!!!!!!!UNTERSCHEIDUNG OB PICARD ODER NEWTON!!!!!!!!!!!! if (Timestepper.Config_NonlinearSolver == NonlinearSolverMethod.NewtonGMRES) { // Spatial Dimension switch (D) { case 1: break; throw new NotImplementedException("Currently not implemented for " + D + " Dimensions"); //break; case 2: throw new NotImplementedException("Currently not implemented for " + D + " Dimensions"); //break; case 3: var dofsPerCell3D = (3 * (pV * pV * pV + 6 * pV * pV + 11 * pV + 6) / 6 + 1 * (pP * pP * pP + 6 * pP * pP + 11 * pP + 6) / 6); var dofsLoc = dofsPerCell3D * cellsLoc; var dofsGlo = dofsPerCell3D * cellsGlo; var PPP = (int)Math.Ceiling(dofsLoc / 6500.0); Console.WriteLine("Analysing the problem yields " + PPP + " parts per process."); if (dofsGlo > 10000) { if (Control.NoOfMultigridLevels < 2) { throw new ApplicationException("At least 2 Multigridlevels are required"); } Timestepper.Config_linearSolver = new Schwarz() { m_BlockingStrategy = new Schwarz.METISBlockingStrategy() { NoOfPartsPerProcess = PPP, }, Overlap = 1, CoarseSolver = DetermineMGSquence(Control.NoOfMultigridLevels - 2) }; } else { Timestepper.Config_linearSolver = new DirectSolver() { WhichSolver = DirectSolver._whichSolver.MUMPS }; } break; default: throw new NotImplementedException("Currently not implemented for " + D + " Dimensions"); } } else { // Spatial Dimension switch (D) { case 1: break; throw new NotImplementedException("Currently not implemented for " + D + " Dimensions"); //break; case 2: throw new NotImplementedException("Currently not implemented for " + D + " Dimensions"); //break; case 3: var dofsPerCell3D = (3 * (pV * pV * pV + 6 * pV * pV + 11 * pV + 6) / 6 + 1 * (pP * pP * pP + 6 * pP * pP + 11 * pP + 6) / 6); var dofsLoc = dofsPerCell3D * cellsLoc; var dofsGlo = dofsPerCell3D * cellsGlo; if (dofsGlo > 10000) { if (Control.NoOfMultigridLevels < 2) { throw new ApplicationException("At least 2 Multigridlevels are required"); } tempsolve = new SoftGMRES() { MaxKrylovDim = Timestepper.Config_MaxKrylovDim, m_Tolerance = Timestepper.Config_SolverConvergenceCriterion, Precond = new Schwarz() { m_BlockingStrategy = new Schwarz.SimpleBlocking() { NoOfPartsPerProcess = (int)Math.Ceiling(dofsLoc / 6500.0), }, Overlap = 1, CoarseSolver = DetermineMGSquence(Control.NoOfMultigridLevels - 2) }, }; } else { tempsolve = new DirectSolver() { WhichSolver = DirectSolver._whichSolver.MUMPS }; } break; default: throw new NotImplementedException("Currently not implemented for " + D + " Dimensions"); } } return(tempsolve); //Timestepper. // Wenn Gesamtproblem in 2D < 100000 DoFs -> Direct Solver // Wenn Gesamtproblem in 3D < 10000 DoFs -> Direct Solver // Block Solve 3D ca. 6000 DoFs per Process -> Adjust Blocks per Process // Coarse Solve ca. 5000 bis 10000 DoFs. -> Adjust Multigrid Levels }
/// <summary> /// Choose solver depending on configurations made in the control file. /// </summary> /// <param name="nonlinSol"></param> /// <param name="linSol"></param> /// <param name="Timestepper"></param> public static void ChooseSolver(IBM_Control Control, ref XdgBDFTimestepping Timestepper) { // Set several solver options for Timestepper Timestepper.Config_SolverConvergenceCriterion = Control.Solver_ConvergenceCriterion; Timestepper.Config_MaxIterations = Control.MaxSolverIterations; Timestepper.Config_MinIterations = Control.MinSolverIterations; Timestepper.Config_MaxKrylovDim = Control.MaxKrylovDim; // Set to pseudo Picard if the Stokes equations should be solved if (Control.PhysicalParameters.IncludeConvection == false) { Control.NonlinearSolve = NonlinearSolverCodes.Picard; } ISolverSmootherTemplate templinearSolve = null; switch (Control.LinearSolve) { case LinearSolverCodes.automatic: templinearSolve = AutomaticChoice(Control, Timestepper); break; case LinearSolverCodes.classic_mumps: templinearSolve = new DirectSolver() { WhichSolver = DirectSolver._whichSolver.MUMPS }; break; case LinearSolverCodes.classic_pardiso: templinearSolve = new DirectSolver() { WhichSolver = DirectSolver._whichSolver.PARDISO }; break; case LinearSolverCodes.exp_schwarz_directcoarse_overlap: if (Control.NoOfMultigridLevels < 2) { throw new ApplicationException("At least 2 Multigridlevels are required"); } templinearSolve = new Schwarz() { m_BlockingStrategy = new Schwarz.METISBlockingStrategy() { NoOfPartsPerProcess = 1, }, Overlap = 1, CoarseSolver = DetermineMGSquence(Control.NoOfMultigridLevels - 2) }; break; case LinearSolverCodes.exp_schwarz_directcoarse: if (Control.NoOfMultigridLevels < 2) { throw new ApplicationException("At least 2 Multigridlevels are required"); } templinearSolve = new Schwarz() { m_BlockingStrategy = new Schwarz.METISBlockingStrategy() { NoOfPartsPerProcess = 1, }, Overlap = 0, CoarseSolver = DetermineMGSquence(Control.NoOfMultigridLevels - 2) }; break; case LinearSolverCodes.exp_schwarz_Kcycle_directcoarse: if (Control.NoOfMultigridLevels < 2) { throw new ApplicationException("At least 2 Multigridlevels are required"); } templinearSolve = new Schwarz() { m_BlockingStrategy = new Schwarz.MultigridBlocks() { Depth = Control.NoOfMultigridLevels - 1 }, Overlap = 0, CoarseSolver = DetermineMGSquence(Control.NoOfMultigridLevels - 2) }; break; case LinearSolverCodes.exp_schwarz_Kcycle_directcoarse_overlap: if (Control.NoOfMultigridLevels < 2) { throw new ApplicationException("At least 2 Multigridlevels are required"); } templinearSolve = new Schwarz() { m_BlockingStrategy = new Schwarz.MultigridBlocks() { Depth = Control.NoOfMultigridLevels - 1 }, Overlap = 1, CoarseSolver = DetermineMGSquence(Control.NoOfMultigridLevels - 2) }; break; case LinearSolverCodes.exp_softgmres: templinearSolve = new SoftGMRES() { MaxKrylovDim = Timestepper.Config_MaxKrylovDim, m_Tolerance = Timestepper.Config_SolverConvergenceCriterion, }; break; case LinearSolverCodes.exp_softgmres_schwarz_Kcycle_directcoarse_overlap: templinearSolve = new SoftGMRES() { MaxKrylovDim = Timestepper.Config_MaxKrylovDim, m_Tolerance = Timestepper.Config_SolverConvergenceCriterion, Precond = new Schwarz() { m_BlockingStrategy = new Schwarz.MultigridBlocks() { Depth = Control.NoOfMultigridLevels - 1 }, Overlap = 1, CoarseSolver = DetermineMGSquence(Control.NoOfMultigridLevels - 2) }, }; break; case LinearSolverCodes.exp_softgmres_schwarz_directcoarse_overlap: if (Control.NoOfMultigridLevels < 2) { throw new ApplicationException("At least 2 Multigridlevels are required"); } templinearSolve = new SoftGMRES() { MaxKrylovDim = Timestepper.Config_MaxKrylovDim, m_Tolerance = Timestepper.Config_SolverConvergenceCriterion, Precond = new Schwarz() { m_BlockingStrategy = new Schwarz.METISBlockingStrategy() { NoOfPartsPerProcess = 1, }, Overlap = 1, CoarseSolver = DetermineMGSquence(Control.NoOfMultigridLevels - 2) }, }; break; case LinearSolverCodes.exp_multigrid: if (Control.NoOfMultigridLevels < 2) { throw new ApplicationException("At least 2 Multigridlevels are required"); } templinearSolve = new ILU() { }; break; case LinearSolverCodes.exp_ILU: templinearSolve = new ILU() { }; break; case LinearSolverCodes.exp_Schur: templinearSolve = new SchurPrecond() { SchurOpt = SchurPrecond.SchurOptions.decoupledApprox }; break; case LinearSolverCodes.exp_Simple: templinearSolve = new SchurPrecond() { SchurOpt = SchurPrecond.SchurOptions.SIMPLE }; break; case LinearSolverCodes.exp_AS_1000: if (Timestepper.MultigridSequence[0].SpatialDimension == 3) //3D --> 212940DoF { templinearSolve = new Schwarz() { m_BlockingStrategy = new Schwarz.METISBlockingStrategy() { //noofparts = 76, NoOfPartsPerProcess = 213, // Warum 76 }, CoarseSolver = new DirectSolver() { WhichSolver = DirectSolver._whichSolver.MUMPS //PARDISO }, Overlap = 1 }; } else //2D --> 75088DoF { templinearSolve = new Schwarz() { m_BlockingStrategy = new Schwarz.METISBlockingStrategy() { //noofparts = 213, NoOfPartsPerProcess = 213, }, CoarseSolver = new DirectSolver() { WhichSolver = DirectSolver._whichSolver.MUMPS //PARDISO }, Overlap = 1 }; } break; case LinearSolverCodes.exp_AS_5000: if (Timestepper.MultigridSequence[0].SpatialDimension == 3) //3D --> 212940DoF { templinearSolve = new Schwarz() { m_BlockingStrategy = new Schwarz.METISBlockingStrategy() { //noofparts = 43, NoOfPartsPerProcess = 43, }, CoarseSolver = new DirectSolver() { WhichSolver = DirectSolver._whichSolver.MUMPS //PARDISO }, Overlap = 1 }; } else //2D --> 75088DoF { templinearSolve = new Schwarz() { m_BlockingStrategy = new Schwarz.METISBlockingStrategy() { //noofparts = 16, NoOfPartsPerProcess = 43, }, CoarseSolver = new DirectSolver() { WhichSolver = DirectSolver._whichSolver.MUMPS //PARDISO }, Overlap = 1 }; } break; case LinearSolverCodes.exp_AS_10000: if (Timestepper.MultigridSequence[0].SpatialDimension == 3) //3D --> 212940DoF { templinearSolve = new Schwarz() { m_BlockingStrategy = new Schwarz.METISBlockingStrategy() { //noofparts = 22, NoOfPartsPerProcess = 22, }, CoarseSolver = new DirectSolver() { WhichSolver = DirectSolver._whichSolver.MUMPS //PARDISO }, Overlap = 1 }; } else //2D --> 75088DoF { templinearSolve = new Schwarz() { m_BlockingStrategy = new Schwarz.METISBlockingStrategy() { //noofparts = 8, NoOfPartsPerProcess = 22, // }, CoarseSolver = new DirectSolver() { WhichSolver = DirectSolver._whichSolver.MUMPS //PARDISO }, Overlap = 1 }; } break; case LinearSolverCodes.exp_AS_MG: templinearSolve = new Schwarz() { m_BlockingStrategy = new Schwarz.MultigridBlocks() { //depth = asdepth, Depth = 2, }, CoarseSolver = new DirectSolver() { WhichSolver = DirectSolver._whichSolver.MUMPS //PARDISO }, Overlap = 1 }; break; case LinearSolverCodes.exp_localPrec: templinearSolve = new LocalizedOperatorPrec() { m_dt = Control.GetFixedTimestep(), m_muA = Control.PhysicalParameters.mu_A, }; break; default: throw new NotImplementedException("Linear solver option not available"); } // Set nonlinear Solver switch (Control.NonlinearSolve) { case NonlinearSolverCodes.NewtonGMRES: Timestepper.Config_NonlinearSolver = NonlinearSolverMethod.NewtonGMRES; Timestepper.Config_linearSolver = templinearSolve; break; case NonlinearSolverCodes.Picard: Timestepper.Config_NonlinearSolver = NonlinearSolverMethod.Picard; Timestepper.Config_linearSolver = templinearSolve; break; case NonlinearSolverCodes.Newton: Timestepper.Config_NonlinearSolver = NonlinearSolverMethod.Newton; Timestepper.Config_linearSolver = templinearSolve; break; case NonlinearSolverCodes.PicardGMRES: Timestepper.Config_NonlinearSolver = NonlinearSolverMethod.Picard; Timestepper.Config_linearSolver = new SoftGMRES() { MaxKrylovDim = Timestepper.Config_MaxKrylovDim, m_Tolerance = Timestepper.Config_SolverConvergenceCriterion, Precond = templinearSolve, m_MaxIterations = Timestepper.Config_MaxIterations, }; break; default: throw new NotImplementedException("Nonlinear solver option not available"); } }