/// <summary> /// Determines a solver sequence depending on MGlevels /// </summary> /// <param name="MGlevels"></param> /// <param name="CoarsestSolver"></param> /// <returns></returns> static ISolverSmootherTemplate DetermineMGSquence(int MGlevels) { ISolverSmootherTemplate solver; if (MGlevels > 0) { solver = new ClassicMultigrid() { CoarserLevelSolver = DetermineMGSquence(MGlevels - 1) }; } else { solver = new DirectSolver() { WhichSolver = DirectSolver._whichSolver.MUMPS }; } return(solver); }
/// <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; }