diff --git a/tests/solver/Test_wilsonclover_mg.cc b/tests/solver/Test_wilsonclover_mg.cc index fee8fa4c..e21aa5ab 100644 --- a/tests/solver/Test_wilsonclover_mg.cc +++ b/tests/solver/Test_wilsonclover_mg.cc @@ -151,8 +151,16 @@ public: } }; +template class MultiGridPreconditionerBase : public LinearFunction { +public: + virtual ~MultiGridPreconditionerBase() = default; + virtual void setup() = 0; + virtual void operator()(Field const &in, Field &out) = 0; + virtual void runChecks() = 0; +}; + template -class MultiGridPreconditioner : public LinearFunction> { +class MultiGridPreconditioner : public MultiGridPreconditionerBase> { public: ///////////////////////////////////////////// // Type Definitions @@ -213,10 +221,10 @@ public: static_assert((nBasis & 0x1) == 0, "MG Preconditioner only supports an even number of basis vectors"); int nb = nBasis / 2; - // TODO: to get this to work for more than two levels, I would need to either implement coarse spins or have a template specialization of this class also for the finest level - for(int n = 0; n < nb; n++) { - _Aggregates.subspace[n + nb] = g5 * _Aggregates.subspace[n]; - } + // // TODO: to get this to work for more than two levels, I would need to either implement coarse spins or have a template specialization of this class also for the finest level + // for(int n = 0; n < nb; n++) { + // _Aggregates.subspace[n + nb] = g5 * _Aggregates.subspace[n]; + // } _CoarseMatrix.CoarsenOperator(_LevelInfo.Grids[_CurrentLevel], fineMdagMOp, _Aggregates); @@ -473,7 +481,7 @@ public: // Specialization for the coarsest level template -class MultiGridPreconditioner : public LinearFunction> { +class MultiGridPreconditioner : public MultiGridPreconditionerBase> { public: ///////////////////////////////////////////// // Type Definitions @@ -528,6 +536,29 @@ public: template using NLevelMGPreconditioner = MultiGridPreconditioner; +template +std::unique_ptr>> +createMGInstance(MultiGridParams &mgParams, LevelInfo &levelInfo, Matrix &FineMat, Matrix &SmootherMat) { + + // clang-format off + #define CASE_FOR_N_LEVELS(nLevels) \ + case nLevels: \ + return std::unique_ptr>( \ + new NLevelMGPreconditioner(mgParams, levelInfo, FineMat, SmootherMat)); \ + break; + // clang-format on + + switch(mgParams.nLevels) { + CASE_FOR_N_LEVELS(2); + CASE_FOR_N_LEVELS(3); + CASE_FOR_N_LEVELS(4); + default: + std::cout << GridLogError << "We currently only support nLevels ∈ {2, 3, 4}" << std::endl; + exit(EXIT_FAILURE); + break; + } +} + int main(int argc, char **argv) { Grid_init(&argc, &argv); @@ -619,29 +650,16 @@ int main(int argc, char **argv) { std::cout << GridLogMessage << "Testing Multigrid for Wilson" << std::endl; std::cout << GridLogMessage << "**************************************************" << std::endl; - TrivialPrecon TrivialPrecon; - NLevelMGPreconditioner TwoLevelMGPreconDw(mgParams, levelInfo, Dw, Dw); - // NLevelMGPreconditioner ThreeLevelMGPreconDw(mgParams, levelInfo, Dw, Dw); - // NLevelMGPreconditioner FourLevelMGPreconDw(mgParams, levelInfo, Dw, Dw); + TrivialPrecon TrivialPrecon; + auto MGPreconDw = createMGInstance(mgParams, levelInfo, Dw, Dw); - TwoLevelMGPreconDw.setup(); - TwoLevelMGPreconDw.runChecks(); - - // ThreeLevelMGPreconDw.setup(); - // ThreeLevelMGPreconDw.runChecks(); - - // FourLevelMGPreconDw.setup(); - // FourLevelMGPreconDw.runChecks(); - - // NLevelMGPreconDw.setup(); - // NLevelMGPreconDw.runChecks(); + MGPreconDw->setup(); + MGPreconDw->runChecks(); std::vector>> solversDw; 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)); + solversDw.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, *MGPreconDw, 100, false)); for(auto const &solver : solversDw) { std::cout << "Starting with a new solver" << std::endl; @@ -654,32 +672,18 @@ int main(int argc, char **argv) { std::cout << GridLogMessage << "Testing Multigrid for Wilson Clover" << std::endl; std::cout << GridLogMessage << "**************************************************" << std::endl; - NLevelMGPreconditioner TwoLevelMGPreconDwc( - mgParams, levelInfo, Dwc, Dwc); - // NLevelMGPreconditioner ThreeLevelMGPreconDwc(mgParams, velInfo, Dwc, Dwc); - // NLevelMGPreconditioner FourLevelMGPreconDwc(lelevelInfo, Dwc, Dwc); + auto MGPreconDwc = createMGInstance(mgParams, levelInfo, Dwc, Dwc); - TwoLevelMGPreconDwc.setup(); - TwoLevelMGPreconDwc.runChecks(); - - // ThreeLevelMGPreconDwc.setup(); - // ThreeLevelMGPreconDwc.runChecks(); - - // FourLevelMGPreconDwc.setup(); - // FourLevelMGPreconDwc.runChecks(); - - // NLevelMGPreconDwc.setup(); - // NLevelMGPreconDwc.runChecks(); + MGPreconDwc->setup(); + MGPreconDwc->runChecks(); std::vector>> solversDwc; 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)); + solversDwc.emplace_back(new FlexibleGeneralisedMinimalResidual(1.0e-12, 50000, *MGPreconDwc, 100, false)); for(auto const &solver : solversDwc) { - std::cout << "Starting with a new solver" << std::endl; + std::cout << std::endl << "Starting with a new solver" << std::endl; result = zero; (*solver)(MdagMOpDwc, src, result); std::cout << std::endl;