LCOV - code coverage report
Current view: top level - src/mfem/solvers - MFEMSolverBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 37 43 86.0 %
Date: 2026-05-29 20:35:17 Functions: 11 11 100.0 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.14