LCOV - code coverage report
Current view: top level - include/mfem/solvers - MFEMLORLinearSolverBase.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 329044 Lines: 44 53 83.0 %
Date: 2026-08-03 21:12:22 Functions: 58 58 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             : #pragma once
      13             : 
      14             : #include "MFEMLinearSolverBase.h"
      15             : 
      16             : namespace Moose::MFEM
      17             : {
      18             : /**
      19             :  * Base class for LOR compatible linear MFEM solvers and preconditioners.
      20             :  * Any LOR-capable MFEM solver T must inherit from LORLinearSolverBase<T>.
      21             :  * The user is free to specialize LORLinearSolverBase<T>::UpdateEquationSystemContext()
      22             :  * if the provided template definition is not appropriate, for instance if additional
      23             :  * setup is required or if building an mfem::LORSolver<T> object is unnecessary.
      24             :  */
      25             : template <class MFEMSolverType>
      26             : class LORLinearSolverBase : public LinearSolverBase
      27             : {
      28             : public:
      29             :   static InputParameters validParams();
      30             : 
      31             :   LORLinearSolverBase(const InputParameters & parameters);
      32             : 
      33             : protected:
      34             :   /// Update the wrapped MFEM solver parameters
      35             :   virtual void SetSolverParameters(MFEMSolverType & solver) = 0;
      36             : 
      37             :   virtual void UpdateEquationSystemContext() override;
      38             : 
      39             :   /// Variable defining whether to use LOR solver
      40             :   bool _lor;
      41             :   mfem::ParBilinearForm * _a;
      42             :   mfem::Array<int> _ess_bdr_markers;
      43             :   mfem::Array<int> _ess_tdofs;
      44             : 
      45             : private:
      46             :   void SetLORSolver();
      47             : 
      48             :   /// Checks for the correct configuration of quadrature bases for LOR spectral equivalence
      49             :   virtual void CheckSpectralEquivalence(mfem::ParBilinearForm & blf) const;
      50             : 
      51             :   /// Rebuild any Low-Order-Refined components from the unreduced bilinear form. Called only when
      52             :   /// _lor is true, before the assembled linear operator has been set via SetOperator. Default
      53             :   /// no-op; override in solvers or preconditioners that construct LOR-related data from the
      54             :   /// bilinear form.
      55             :   virtual void SetupLOR(std::shared_ptr<Moose::MFEM::EquationSystem> equation_system);
      56             : };
      57             : 
      58             : template <class MFEMSolverType>
      59             : InputParameters
      60       25244 : LORLinearSolverBase<MFEMSolverType>::validParams()
      61             : {
      62       25244 :   InputParameters params = LinearSolverBase::validParams();
      63       75732 :   params.addParam<bool>("low_order_refined", false, "Set usage of Low-Order Refined solver.");
      64       25244 :   return params;
      65           0 : }
      66             : 
      67             : template <class MFEMSolverType>
      68        1969 : LORLinearSolverBase<MFEMSolverType>::LORLinearSolverBase(const InputParameters & parameters)
      69        1969 :   : LinearSolverBase(parameters), _lor(parameters.get<bool>("low_order_refined"))
      70             : {
      71        1969 : }
      72             : 
      73             : template <typename T, typename... Ts>
      74             : constexpr bool is_any_of_v = (std::is_same_v<T, Ts> || ...);
      75             : 
      76             : template <class MFEMSolverType>
      77             : void
      78          64 : LORLinearSolverBase<MFEMSolverType>::CheckSpectralEquivalence(mfem::ParBilinearForm & blf) const
      79             : {
      80          64 :   if (auto fec = dynamic_cast<const mfem::H1_FECollection *>(blf.FESpace()->FEColl()))
      81             :   {
      82          43 :     if (fec->GetBasisType() != mfem::BasisType::GaussLobatto)
      83           0 :       mooseError("Low-Order-Refined solver requires the FESpace basis to be GaussLobatto "
      84             :                  "for H1 elements.");
      85             :   }
      86          21 :   else if (auto fec = dynamic_cast<const mfem::ND_FECollection *>(blf.FESpace()->FEColl()))
      87             :   {
      88          28 :     if (fec->GetClosedBasisType() != mfem::BasisType::GaussLobatto ||
      89          14 :         fec->GetOpenBasisType() != mfem::BasisType::IntegratedGLL)
      90           0 :       mooseError("Low-Order-Refined solver requires the FESpace closed-basis to be GaussLobatto "
      91             :                  "and the open-basis to be IntegratedGLL for ND elements.");
      92             :   }
      93           7 :   else if (auto fec = dynamic_cast<const mfem::RT_FECollection *>(blf.FESpace()->FEColl()))
      94             :   {
      95          14 :     if (fec->GetClosedBasisType() != mfem::BasisType::GaussLobatto ||
      96           7 :         fec->GetOpenBasisType() != mfem::BasisType::IntegratedGLL)
      97           0 :       mooseError("Low-Order-Refined solver requires the FESpace closed-basis to be GaussLobatto "
      98             :                  "and the open-basis to be IntegratedGLL for RT elements.");
      99             :   }
     100          64 : }
     101             : 
     102             : template <class MFEMSolverType>
     103             : void
     104        3726 : LORLinearSolverBase<MFEMSolverType>::UpdateEquationSystemContext()
     105             : {
     106        3726 :   Moose::MFEM::LinearSolverBase::UpdateEquationSystemContext();
     107        3726 :   if (_lor && GetPreconditioner())
     108           0 :     mooseError("LOR solver cannot take a preconditioner");
     109        3726 :   if (_lor)
     110             :   {
     111          57 :     SetupLOR(_equation_system);
     112             :     if constexpr (is_any_of_v<MFEMSolverType, mfem::HypreAMS, mfem::HypreADS>)
     113          14 :       if (_a->ParFESpace()->GetMesh()->GetTypicalElementGeometry() != mfem::Geometry::Type::CUBE)
     114           0 :         mooseError("LOR HypreAMS/ADS Solver only supports hex meshes.");
     115          57 :     SetLORSolver();
     116             :   }
     117             :   else if constexpr (!is_any_of_v<MFEMSolverType,
     118             :                                   mfem::OperatorJacobiSmoother,
     119             :                                   mfem::HypreBoomerAMG,
     120             :                                   mfem::HypreAMS,
     121             :                                   mfem::HypreADS>)
     122        1843 :     SetPreconditioner(static_cast<MFEMSolverType &>(GetSolver()));
     123        3726 : }
     124             : 
     125             : template <class MFEMSolverType>
     126             : void
     127          64 : LORLinearSolverBase<MFEMSolverType>::SetupLOR(
     128             :     std::shared_ptr<Moose::MFEM::EquationSystem> equation_system)
     129             : {
     130          64 :   if (!equation_system)
     131           0 :     mooseError("LOR solver setup requires an EquationSystem to be defined.");
     132          64 :   if (equation_system->IsComplex())
     133           0 :     mooseError("LOR solve is not supported for complex equation systems.");
     134          64 :   if (equation_system->IsMultivariate())
     135           0 :     mooseError("LOR solve is only supported for single-variable systems");
     136             : 
     137          64 :   const auto & test_var_name = equation_system->GetTestVarNames().at(0);
     138          64 :   _a = &equation_system->GetBilinearForm(test_var_name);
     139          64 :   CheckSpectralEquivalence(*_a);
     140          64 :   _ess_bdr_markers = equation_system->GetEssentialBoundaryMarkers(test_var_name);
     141          64 :   _a->ParFESpace()->GetEssentialTrueDofs(_ess_bdr_markers, _ess_tdofs);
     142          64 : }
     143             : 
     144             : template <class MFEMSolverType>
     145             : void
     146          57 : LORLinearSolverBase<MFEMSolverType>::SetLORSolver()
     147             : {
     148             :   mfem::LORSolver<MFEMSolverType> * lor_solver;
     149             :   if constexpr (is_any_of_v<MFEMSolverType, mfem::HypreGMRES, mfem::HypreFGMRES, mfem::HyprePCG>)
     150             :   {
     151           6 :     mfem::ParLORDiscretization lor_disc(*_a, _ess_tdofs);
     152           6 :     lor_solver = new mfem::LORSolver<MFEMSolverType>(lor_disc, _a->ParFESpace()->GetComm());
     153           6 :   }
     154             :   else
     155          51 :     lor_solver = new mfem::LORSolver<MFEMSolverType>(*_a, _ess_tdofs);
     156          57 :   SetSolverParameters(lor_solver->GetSolver());
     157          57 :   SetSolver(lor_solver);
     158          57 : }
     159             : 
     160             : } // namespace Moose::MFEM
     161             : 
     162             : #endif

Generated by: LCOV version 1.14