Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #ifdef MOOSE_MFEM_ENABLED 11 : 12 : #include "MFEMLinearSolverBase.h" 13 : #include "MFEMProblem.h" 14 : #include "MFEMEigensolverBase.h" 15 : 16 : namespace Moose::MFEM 17 : { 18 : InputParameters 19 31552 : LinearSolverBase::validParams() 20 : { 21 31552 : InputParameters params = SolverBase::validParams(); 22 63104 : params.addClassDescription( 23 : "Base class for defining linear mfem::Solver derived classes for Moose."); 24 94656 : params.addParam<bool>("low_order_refined", false, "Set usage of Low-Order Refined solver."); 25 31552 : return params; 26 0 : } 27 : 28 2139 : LinearSolverBase::LinearSolverBase(const InputParameters & parameters) 29 6417 : : SolverBase(parameters), _lor{getParam<bool>("low_order_refined")}, _preconditioner{nullptr} 30 : { 31 2139 : } 32 : 33 : template <typename T> 34 : void 35 965 : LinearSolverBase::SetPreconditioner(T & solver) 36 : { 37 2895 : if (isParamSetByUser("preconditioner")) 38 : { 39 938 : if (!_preconditioner) 40 : { 41 1734 : auto & pre = getMFEMProblem().getMFEMObject<LinearSolverBase>( 42 2601 : "Moose::MFEM::SolverBase", getParam<MFEMSolverName>("preconditioner")); 43 : // Take shared ownership so the preconditioner outlives the solver 44 867 : _preconditioner = std::static_pointer_cast<LinearSolverBase>(pre.shared_from_this()); 45 : } 46 : 47 938 : if (dynamic_cast<const EigensolverBase *>(GetPreconditioner())) 48 0 : mooseError("Eigensolvers cannot be used as preconditioners."); 49 : 50 938 : auto & mfem_pre = _preconditioner->GetSolver(); 51 : if constexpr (std::is_base_of_v<mfem::HypreSolver, T> || std::is_same_v<mfem::HypreAME, T>) 52 831 : if (auto * const hypre_pre = dynamic_cast<mfem::HypreSolver *>(&mfem_pre)) 53 831 : solver.SetPreconditioner(*hypre_pre); 54 : else 55 0 : mooseError("hypre solver preconditioners must themselves be hypre solvers"); 56 : else 57 107 : solver.SetPreconditioner(mfem_pre); 58 : } 59 965 : } 60 : 61 : template void LinearSolverBase::SetPreconditioner(mfem::CGSolver &); 62 : template void LinearSolverBase::SetPreconditioner(mfem::GMRESSolver &); 63 : template void LinearSolverBase::SetPreconditioner(mfem::HypreFGMRES &); 64 : template void LinearSolverBase::SetPreconditioner(mfem::HypreGMRES &); 65 : template void LinearSolverBase::SetPreconditioner(mfem::HyprePCG &); 66 : template void LinearSolverBase::SetPreconditioner(mfem::HypreLOBPCG &); 67 : template void LinearSolverBase::SetPreconditioner(mfem::HypreAME &); 68 : 69 : void 70 2154 : LinearSolverBase::SetOperator(mfem::OperatorHandle & op) 71 : { 72 : mooseAssert(_solver, "setOperator called before the solver was constructed"); 73 2154 : _solver->SetOperator(*op); 74 2154 : } 75 : 76 : void 77 57 : LinearSolverBase::CheckSpectralEquivalence(mfem::ParBilinearForm & blf) const 78 : { 79 57 : if (auto fec = dynamic_cast<const mfem::H1_FECollection *>(blf.FESpace()->FEColl())) 80 : { 81 43 : if (fec->GetBasisType() != mfem::BasisType::GaussLobatto) 82 0 : mooseError("Low-Order-Refined solver requires the FESpace basis to be GaussLobatto " 83 : "for H1 elements."); 84 : } 85 14 : else if (auto fec = dynamic_cast<const mfem::ND_FECollection *>(blf.FESpace()->FEColl())) 86 : { 87 14 : if (fec->GetClosedBasisType() != mfem::BasisType::GaussLobatto || 88 7 : fec->GetOpenBasisType() != mfem::BasisType::IntegratedGLL) 89 0 : mooseError("Low-Order-Refined solver requires the FESpace closed-basis to be GaussLobatto " 90 : "and the open-basis to be IntegratedGLL for ND elements."); 91 : } 92 7 : else if (auto fec = dynamic_cast<const mfem::RT_FECollection *>(blf.FESpace()->FEColl())) 93 : { 94 14 : if (fec->GetClosedBasisType() != mfem::BasisType::GaussLobatto || 95 7 : fec->GetOpenBasisType() != mfem::BasisType::IntegratedGLL) 96 0 : mooseError("Low-Order-Refined solver requires the FESpace closed-basis to be GaussLobatto " 97 : "and the open-basis to be IntegratedGLL for RT elements."); 98 : } 99 57 : } 100 : } // namespace Moose::MFEM 101 : 102 : #endif