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 "MFEMSolverBase.h" 13 : #include "MFEMProblem.h" 14 : #include "MFEMEigensolverBase.h" 15 : 16 : InputParameters 17 31314 : MFEMSolverBase::validParams() 18 : { 19 31314 : InputParameters params = MFEMObject::validParams(); 20 62628 : params.addClassDescription("Base class for defining mfem::Solver derived classes for Moose."); 21 62628 : params.registerBase("MFEMSolverBase"); 22 62628 : params.registerSystemAttributeName("MFEMSolverBase"); 23 93942 : params.addParam<bool>("low_order_refined", false, "Set usage of Low-Order Refined solver."); 24 : 25 31314 : return params; 26 0 : } 27 : 28 2020 : MFEMSolverBase::MFEMSolverBase(const InputParameters & parameters) 29 : : MFEMObject(parameters), 30 2020 : _lor{getParam<bool>("low_order_refined")}, 31 2020 : _solver{nullptr}, 32 4040 : _preconditioner{nullptr} 33 : { 34 2020 : } 35 : 36 : template <typename T> 37 : void 38 2248 : MFEMSolverBase::setPreconditioner(T & solver) 39 : { 40 6744 : if (isParamSetByUser("preconditioner")) 41 : { 42 2221 : if (!_preconditioner) 43 : { 44 1616 : auto & pre = const_cast<MFEMSolverBase &>(getMFEMProblem().getMFEMObject<MFEMSolverBase>( 45 2424 : "MFEMSolverBase", getParam<MFEMSolverName>("preconditioner"))); 46 : // Take shared ownership so the preconditioner outlives the solver 47 808 : _preconditioner = std::static_pointer_cast<MFEMSolverBase>(pre.shared_from_this()); 48 : } 49 : 50 2221 : if (dynamic_cast<const MFEMEigensolverBase *>(_preconditioner.get())) 51 0 : mooseError("Eigensolvers cannot be used as preconditioners."); 52 : 53 2221 : auto & mfem_pre = _preconditioner->getSolver(); 54 : if constexpr (std::is_base_of_v<mfem::HypreSolver, T> || std::is_same_v<mfem::HypreAME, T>) 55 2077 : if (auto * const hypre_pre = dynamic_cast<mfem::HypreSolver *>(&mfem_pre)) 56 2077 : solver.SetPreconditioner(*hypre_pre); 57 : else 58 0 : mooseError("hypre solver preconditioners must themselves be hypre solvers"); 59 : else 60 144 : solver.SetPreconditioner(mfem_pre); 61 : } 62 2248 : } 63 : 64 : template void MFEMSolverBase::setPreconditioner(mfem::CGSolver &); 65 : template void MFEMSolverBase::setPreconditioner(mfem::GMRESSolver &); 66 : template void MFEMSolverBase::setPreconditioner(mfem::HypreFGMRES &); 67 : template void MFEMSolverBase::setPreconditioner(mfem::HypreGMRES &); 68 : template void MFEMSolverBase::setPreconditioner(mfem::HyprePCG &); 69 : template void MFEMSolverBase::setPreconditioner(mfem::HypreLOBPCG &); 70 : template void MFEMSolverBase::setPreconditioner(mfem::HypreAME &); 71 : 72 : void 73 26 : MFEMSolverBase::setOperator(mfem::OperatorHandle & op) 74 : { 75 : mooseAssert(_solver, "setOperator called before the solver was constructed"); 76 26 : _solver->SetOperator(*op); 77 26 : } 78 : 79 : void 80 54 : MFEMSolverBase::checkSpectralEquivalence(mfem::ParBilinearForm & blf) const 81 : { 82 54 : if (auto fec = dynamic_cast<const mfem::H1_FECollection *>(blf.FESpace()->FEColl())) 83 : { 84 43 : if (fec->GetBasisType() != mfem::BasisType::GaussLobatto) 85 0 : mooseError("Low-Order-Refined solver requires the FESpace basis to be GaussLobatto " 86 : "for H1 elements."); 87 : } 88 11 : else if (auto fec = dynamic_cast<const mfem::ND_FECollection *>(blf.FESpace()->FEColl())) 89 : { 90 8 : if (fec->GetClosedBasisType() != mfem::BasisType::GaussLobatto || 91 4 : fec->GetOpenBasisType() != mfem::BasisType::IntegratedGLL) 92 0 : mooseError("Low-Order-Refined solver requires the FESpace closed-basis to be GaussLobatto " 93 : "and the open-basis to be IntegratedGLL for ND elements."); 94 : } 95 7 : else if (auto fec = dynamic_cast<const mfem::RT_FECollection *>(blf.FESpace()->FEColl())) 96 : { 97 14 : if (fec->GetClosedBasisType() != mfem::BasisType::GaussLobatto || 98 7 : fec->GetOpenBasisType() != mfem::BasisType::IntegratedGLL) 99 0 : mooseError("Low-Order-Refined solver requires the FESpace closed-basis to be GaussLobatto " 100 : "and the open-basis to be IntegratedGLL for RT elements."); 101 : } 102 54 : } 103 : 104 : #endif