Exemplo n.º 1
0
        /// <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);
        }
Exemplo n.º 2
0
        /// <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;
        }
Exemplo n.º 3
0
        /// <summary>
        /// 
        /// </summary>
        ISolverSmootherTemplate KcycleMultiSchwarz(MultigridOperator op) {
            var solver = new OrthonormalizationScheme() {
                MaxIter = 500,
                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;
            var PrecondChain = new List<ISolverSmootherTemplate>();
            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;


                ISolverSmootherTemplate levelSolver;
                if (useDirect) {
                    levelSolver = new DirectSolver() {
                        WhichSolver = DirectSolver._whichSolver.PARDISO,
                        TestSolution = false
                    };
                } else {

                    Schwarz swz1 = new Schwarz() {
                        m_MaxIterations = 1,
                        CoarseSolver = null,
                        m_BlockingStrategy = new Schwarz.METISBlockingStrategy() {
                            NoOfPartsPerProcess = NoOfBlocks
                        },
                        Overlap = 2 // overlap seems to help
                    };

                    SoftPCG pcg1 = new SoftPCG() {
                        m_MinIterations = 5,
                        m_MaxIterations = 5
                    };

                    //*/

                    var pre = new SolverSquence() {
                        SolverChain = new ISolverSmootherTemplate[] { swz1, pcg1 }
                    };

                    levelSolver = swz1;
                }

                if (iLevel > 0) {

                    GenericRestriction[] R = new GenericRestriction[iLevel];
                    for (int ir = 0; ir < R.Length; ir++) {
                        R[ir] = new GenericRestriction();
                        if (ir >= 1)
                            R[ir - 1].CoarserLevelSolver = R[ir];
                    }
                    R[iLevel - 1].CoarserLevelSolver = levelSolver;
                    PrecondChain.Add(R[0]);

                } else {
                    PrecondChain.Add(levelSolver);
                }


                if (useDirect) {
                    Console.WriteLine("Kswz: using {0} levels, lowest level DOF is {1}, target size is {2}.", iLevel + 1, SysSize, DirectKickIn);
                    break;
                }



                Current = Current.CoarserLevel;

            }


            if (PrecondChain.Count > 1) {
                /*
                // construct a V-cycle
                for (int i = PrecondChain.Count - 2; i>= 0; i--) {
                    PrecondChain.Add(PrecondChain[i]);
                }
                */

                var tmp = PrecondChain.ToArray();
                for (int i = 0; i < PrecondChain.Count; i++) {
                    PrecondChain[i] = tmp[PrecondChain.Count - 1 - i];
                }
            }



            solver.PrecondS = PrecondChain.ToArray();
            solver.MaxKrylovDim = solver.PrecondS.Length * 4;

            return solver;
        }
Exemplo n.º 4
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);

                }
            }
        }
Exemplo n.º 5
0
        /// <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
        }
Exemplo n.º 6
0
        /// <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");
            }
        }