From 04f9cf088dd59644179697cd2253ed25c4fc1b0b Mon Sep 17 00:00:00 2001 From: Daniel Richtmann Date: Tue, 27 Mar 2018 17:13:11 +0200 Subject: [PATCH] WilsonMG: Add more parameters to MultiGridParams struct --- tests/solver/Test_wilsonclover_mg.cc | 156 +++++++++++++++++++-------- 1 file changed, 114 insertions(+), 42 deletions(-) diff --git a/tests/solver/Test_wilsonclover_mg.cc b/tests/solver/Test_wilsonclover_mg.cc index f60a4bca..956e68db 100644 --- a/tests/solver/Test_wilsonclover_mg.cc +++ b/tests/solver/Test_wilsonclover_mg.cc @@ -68,18 +68,44 @@ public: } }; +// TODO: Can think about having one parameter struct per level and then a +// vector of these structs. How well would that work together with the +// serialization strategy of Grid? + // clang-format off struct MultiGridParams : Serializable { public: GRID_SERIALIZABLE_CLASS_MEMBERS(MultiGridParams, - int, nLevels, - std::vector>, blockSizes, - bool, kCycle); + int, nLevels, + std::vector>, blockSizes, // size == nLevels - 1 + std::vector, smootherTol, // size == nLevels - 1 + std::vector, smootherMaxOuterIter, // size == nLevels - 1 + std::vector, smootherMaxInnerIter, // size == nLevels - 1 + bool, kCycle, + std::vector, kCycleTol, // size == nLevels - 1 + std::vector, kCycleMaxOuterIter, // size == nLevels - 1 + std::vector, kCycleMaxInnerIter, // size == nLevels - 1 + double, coarseSolverTol, + int, coarseSolverMaxOuterIter, + int, coarseSolverMaxInnerIter); MultiGridParams(){}; }; MultiGridParams mgParams; // clang-format on +void checkParameterValidity(MultiGridParams const ¶ms) { + + auto correctSize = mgParams.nLevels - 1; + + assert(correctSize == params.blockSizes.size()); + assert(correctSize == params.smootherTol.size()); + assert(correctSize == params.smootherMaxOuterIter.size()); + assert(correctSize == params.smootherMaxInnerIter.size()); + assert(correctSize == params.kCycleTol.size()); + assert(correctSize == params.kCycleMaxOuterIter.size()); + assert(correctSize == params.kCycleMaxInnerIter.size()); +} + struct LevelInfo { public: std::vector> Seeds; @@ -316,8 +342,14 @@ public: FineVector fineTmp(in._grid); + auto maxSmootherIter = _MultiGridParams.smootherMaxOuterIter[_CurrentLevel] * _MultiGridParams.smootherMaxInnerIter[_CurrentLevel]; + TrivialPrecon fineTrivialPreconditioner; - FlexibleGeneralisedMinimalResidual fineFGMRES(1.0e-14, 1, fineTrivialPreconditioner, 1, false); + FlexibleGeneralisedMinimalResidual fineFGMRES(_MultiGridParams.smootherTol[_CurrentLevel], + maxSmootherIter, + fineTrivialPreconditioner, + _MultiGridParams.smootherMaxInnerIter[_CurrentLevel], + false); MdagMLinearOperator fineMdagMOp(_FineMatrix); MdagMLinearOperator fineSmootherMdagMOp(_SmootherMatrix); @@ -353,9 +385,20 @@ public: FineVector fineTmp(in._grid); + auto smootherMaxIter = _MultiGridParams.smootherMaxOuterIter[_CurrentLevel] * _MultiGridParams.smootherMaxInnerIter[_CurrentLevel]; + auto kCycleMaxIter = _MultiGridParams.kCycleMaxOuterIter[_CurrentLevel] * _MultiGridParams.kCycleMaxInnerIter[_CurrentLevel]; + TrivialPrecon fineTrivialPreconditioner; - FlexibleGeneralisedMinimalResidual fineFGMRES(1.0e-14, 1, fineTrivialPreconditioner, 1, false); - FlexibleGeneralisedMinimalResidual coarseFGMRES(1.0e-14, 1, *_NextPreconditionerLevel, 1, false); + FlexibleGeneralisedMinimalResidual fineFGMRES(_MultiGridParams.smootherTol[_CurrentLevel], + smootherMaxIter, + fineTrivialPreconditioner, + _MultiGridParams.smootherMaxInnerIter[_CurrentLevel], + false); + FlexibleGeneralisedMinimalResidual coarseFGMRES(_MultiGridParams.kCycleTol[_CurrentLevel], + kCycleMaxIter, + *_NextPreconditionerLevel, + _MultiGridParams.kCycleMaxInnerIter[_CurrentLevel], + false); MdagMLinearOperator fineMdagMOp(_FineMatrix); MdagMLinearOperator fineSmootherMdagMOp(_SmootherMatrix); @@ -521,8 +564,12 @@ public: virtual void operator()(Lattice const &in, Lattice &out) { + auto coarseSolverMaxIter = _MultiGridParams.coarseSolverMaxOuterIter * _MultiGridParams.coarseSolverMaxInnerIter; + + // On the coarsest level we only have a fine what I above call the fine level, no coarse one TrivialPrecon fineTrivialPreconditioner; - FlexibleGeneralisedMinimalResidual fineFGMRES(1.0e-14, 1, fineTrivialPreconditioner, 1, false); + FlexibleGeneralisedMinimalResidual fineFGMRES( + _MultiGridParams.coarseSolverTol, coarseSolverMaxIter, fineTrivialPreconditioner, _MultiGridParams.coarseSolverMaxInnerIter, false); MdagMLinearOperator fineMdagMOp(_FineMatrix); @@ -532,17 +579,8 @@ public: void runChecks() {} }; -template -using FourLevelMGPreconditioner = MultiGridPreconditioner; - -template -using ThreeLevelMGPreconditioner = MultiGridPreconditioner; - -template -using TwoLevelMGPreconditioner = MultiGridPreconditioner; - -template -using NLevelMGPreconditioner = MultiGridPreconditioner; +template +using NLevelMGPreconditioner = MultiGridPreconditioner; int main(int argc, char **argv) { @@ -575,11 +613,49 @@ int main(int argc, char **argv) { WilsonFermionR Dw(Umu, *FGrid, *FrbGrid, mass); WilsonCloverFermionR Dwc(Umu, *FGrid, *FrbGrid, mass, csw_r, csw_t, wilsonAnisCoeff, wcImplparams); - // mgParams.blockSizes = {{2, 2, 2, 2}, {2, 2, 1, 1}, {1, 1, 2, 1}}; - // mgParams.blockSizes = {{2, 2, 2, 2}, {2, 2, 1, 1}}; - mgParams.blockSizes = {{2, 2, 2, 2}}; - mgParams.nLevels = mgParams.blockSizes.size() + 1; - mgParams.kCycle = true; + // Params for two-level MG preconditioner + mgParams.nLevels = 2; + mgParams.blockSizes = {{2, 2, 2, 2}}; + mgParams.smootherTol = {1e-14}; + mgParams.smootherMaxOuterIter = {1}; + mgParams.smootherMaxInnerIter = {1}; + mgParams.kCycle = true; + mgParams.kCycleTol = {1e-14}; + mgParams.kCycleMaxOuterIter = {1}; + mgParams.kCycleMaxInnerIter = {1}; + mgParams.coarseSolverTol = 1e-14; + mgParams.coarseSolverMaxOuterIter = 1; + mgParams.coarseSolverMaxInnerIter = 1; + + // // Params for three-level MG preconditioner + // mgParams.nLevels = 3; + // mgParams.blockSizes = {{2, 2, 2, 2}, {2, 2, 1, 1}}; + // mgParams.smootherTol = {1e-14, 1e-14}; + // mgParams.smootherMaxOuterIter = {1, 1}; + // mgParams.smootherMaxInnerIter = {1, 1}; + // mgParams.kCycle = true; + // mgParams.kCycleTol = {1e-14, 1e-14}; + // mgParams.kCycleMaxOuterIter = {1, 1}; + // mgParams.kCycleMaxInnerIter = {1, 1}; + // mgParams.coarseSolverTol = 1e-14; + // mgParams.coarseSolverMaxOuterIter = 1; + // mgParams.coarseSolverMaxInnerIter = 1; + + // // // Params for four-level MG preconditioner + // mgParams.nLevels = 4; + // mgParams.blockSizes = {{2, 2, 2, 2}, {2, 2, 1, 1}, {1, 1, 2, 1}}; + // mgParams.smootherTol = {1e-14, 1e-14, 1e-14}; + // mgParams.smootherMaxOuterIter = {1, 1, 1}; + // mgParams.smootherMaxInnerIter = {1, 1, 1}; + // mgParams.kCycle = true; + // mgParams.kCycleTol = {1e-14, 1e-14, 1e-14}; + // mgParams.kCycleMaxOuterIter = {1, 1, 1}; + // mgParams.kCycleMaxInnerIter = {1, 1, 1}; + // mgParams.coarseSolverTol = 1e-14; + // mgParams.coarseSolverMaxOuterIter = 1; + // mgParams.coarseSolverMaxInnerIter = 1; + + checkParameterValidity(mgParams); std::cout << mgParams << std::endl; @@ -595,11 +671,10 @@ int main(int argc, char **argv) { std::cout << GridLogMessage << "Testing Multigrid for Wilson" << std::endl; std::cout << GridLogMessage << "**************************************************" << std::endl; - TrivialPrecon TrivialPrecon; - TwoLevelMGPreconditioner TwoLevelMGPreconDw(mgParams, levelInfo, Dw, Dw); - // ThreeLevelMGPreconditioner ThreeLevelMGPreconDw(levelInfo, Dw, Dw); - // FourLevelMGPreconditioner FourLevelMGPreconDw(levelInfo, Dw, Dw); - // NLevelMGPreconditioner NLevelMGPreconDw(levelInfo, Dw, Dw); + TrivialPrecon TrivialPrecon; + NLevelMGPreconditioner TwoLevelMGPreconDw(mgParams, levelInfo, Dw, Dw); + // NLevelMGPreconditioner ThreeLevelMGPreconDw(mgParams, levelInfo, Dw, Dw); + // NLevelMGPreconditioner FourLevelMGPreconDw(mgParams, levelInfo, Dw, Dw); TwoLevelMGPreconDw.setup(); TwoLevelMGPreconDw.runChecks(); @@ -615,11 +690,10 @@ int main(int argc, char **argv) { std::vector>> solversDw; - solversDw.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, TrivialPrecon, 1000, false)); - solversDw.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, TwoLevelMGPreconDw, 1000, false)); - // solversDw.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, ThreeLevelMGPreconDw, 1000, false)); - // solversDw.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, FourLevelMGPreconDw, 1000, false)); - // solversDw.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, NLevelMGPreconDw, 1000, false)); + solversDw.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, TrivialPrecon, 100, false)); + solversDw.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, TwoLevelMGPreconDw, 100, false)); + // solversDw.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, ThreeLevelMGPreconDw, 100, false)); + // solversDw.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, FourLevelMGPreconDw, 100, false)); for(auto const &solver : solversDw) { std::cout << "Starting with a new solver" << std::endl; @@ -632,11 +706,10 @@ int main(int argc, char **argv) { std::cout << GridLogMessage << "Testing Multigrid for Wilson Clover" << std::endl; std::cout << GridLogMessage << "**************************************************" << std::endl; - TwoLevelMGPreconditioner TwoLevelMGPreconDwc( + NLevelMGPreconditioner TwoLevelMGPreconDwc( mgParams, levelInfo, Dwc, Dwc); - // ThreeLevelMGPreconditioner ThreeLevelMGPreconDwc(levelInfo, Dwc, Dwc); - // FourLevelMGPreconditioner FourLevelMGPreconDwc(levelInfo, Dwc, Dwc); - // NLevelMGPreconditioner NLevelMGPreconDwc(levelInfo, Dwc, Dwc); + // NLevelMGPreconditioner ThreeLevelMGPreconDwc(mgParams, velInfo, Dwc, Dwc); + // NLevelMGPreconditioner FourLevelMGPreconDwc(lelevelInfo, Dwc, Dwc); TwoLevelMGPreconDwc.setup(); TwoLevelMGPreconDwc.runChecks(); @@ -652,11 +725,10 @@ int main(int argc, char **argv) { std::vector>> solversDwc; - solversDwc.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, TrivialPrecon, 1000, false)); - solversDwc.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, TwoLevelMGPreconDwc, 1000, false)); - // solversDwc.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, ThreeLevelMGPreconDwc, 1000, false)); - // solversDwc.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, FourLevelMGPreconDwc, 1000, false)); - // solversDwc.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, NLevelMGPreconDwc, 1000, false)); + solversDwc.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, TrivialPrecon, 100, false)); + solversDwc.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, TwoLevelMGPreconDwc, 100, false)); + // solversDwc.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, ThreeLevelMGPreconDwc, 100, false)); + // solversDwc.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, FourLevelMGPreconDwc, 100, false)); for(auto const &solver : solversDwc) { std::cout << "Starting with a new solver" << std::endl;