LCOV - code coverage report
Current view: top level - include/mfem/equation_systems - EquationSystem.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 48 50 96.0 %
Date: 2025-07-17 01:28:37 Functions: 8 9 88.9 %
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 MFEM_ENABLED
      11             : 
      12             : #pragma once
      13             : #include "libmesh/ignore_warnings.h"
      14             : #include "mfem/miniapps/common/pfem_extras.hpp"
      15             : #include "libmesh/restore_warnings.h"
      16             : #include "MFEMIntegratedBC.h"
      17             : #include "MFEMEssentialBC.h"
      18             : #include "MFEMContainers.h"
      19             : #include "MFEMKernel.h"
      20             : #include "MFEMMixedBilinearFormKernel.h"
      21             : #include "ScaleIntegrator.h"
      22             : 
      23             : namespace Moose::MFEM
      24             : {
      25             : 
      26             : /*
      27             : Class to store weak form components (bilinear and linear forms, and optionally
      28             : mixed and nonlinear forms) and build methods
      29             : */
      30             : class EquationSystem : public mfem::Operator
      31             : {
      32             : 
      33             : public:
      34             :   friend class EquationSystemProblemOperator;
      35             :   friend class TimeDomainEquationSystemProblemOperator;
      36             : 
      37         134 :   EquationSystem() = default;
      38             :   ~EquationSystem() override;
      39             : 
      40             :   // add test variable to EquationSystem;
      41             :   virtual void AddTestVariableNameIfMissing(const std::string & test_var_name);
      42             :   virtual void AddTrialVariableNameIfMissing(const std::string & trial_var_name);
      43             : 
      44             :   // Add kernels.
      45             :   virtual void AddKernel(std::shared_ptr<MFEMKernel> kernel);
      46             :   virtual void AddIntegratedBC(std::shared_ptr<MFEMIntegratedBC> kernel);
      47             :   virtual void AddEssentialBC(std::shared_ptr<MFEMEssentialBC> bc);
      48             :   virtual void ApplyEssentialBCs();
      49             : 
      50             :   // Build forms
      51             :   virtual void Init(Moose::MFEM::GridFunctions & gridfunctions,
      52             :                     const Moose::MFEM::FESpaces & fespaces,
      53             :                     mfem::AssemblyLevel assembly_level);
      54             :   virtual void BuildLinearForms();
      55             :   virtual void BuildBilinearForms();
      56             :   virtual void BuildMixedBilinearForms();
      57             :   virtual void BuildEquationSystem();
      58             : 
      59             :   // Form linear system, with essential boundary conditions accounted for
      60             :   virtual void FormLinearSystem(mfem::OperatorHandle & op,
      61             :                                 mfem::BlockVector & trueX,
      62             :                                 mfem::BlockVector & trueRHS);
      63             : 
      64             :   virtual void
      65             :   FormSystem(mfem::OperatorHandle & op, mfem::BlockVector & trueX, mfem::BlockVector & trueRHS);
      66             :   virtual void FormLegacySystem(mfem::OperatorHandle & op,
      67             :                                 mfem::BlockVector & trueX,
      68             :                                 mfem::BlockVector & trueRHS);
      69             : 
      70             :   // Build linear system, with essential boundary conditions accounted for
      71             :   virtual void BuildJacobian(mfem::BlockVector & trueX, mfem::BlockVector & trueRHS);
      72             : 
      73             :   /// Compute residual y = Mu
      74             :   void Mult(const mfem::Vector & u, mfem::Vector & residual) const override;
      75             : 
      76             :   /// Compute J = M + grad_H(u)
      77             :   mfem::Operator & GetGradient(const mfem::Vector & u) const override;
      78             : 
      79             :   // Update variable from solution vector after solve
      80             :   using mfem::Operator::RecoverFEMSolution;
      81             :   virtual void RecoverFEMSolution(mfem::BlockVector & trueX,
      82             :                                   Moose::MFEM::GridFunctions & gridfunctions);
      83             : 
      84             :   std::vector<mfem::Array<int>> _ess_tdof_lists;
      85             : 
      86         134 :   const std::vector<std::string> & TrialVarNames() const { return _trial_var_names; }
      87          24 :   const std::vector<std::string> & TestVarNames() const { return _test_var_names; }
      88             : 
      89             : protected:
      90             :   // Deletes the HypreParMatrix associated with any pointer stored in _h_blocks,
      91             :   // and then proceeds to delete all dynamically allocated memory for _h_blocks
      92             :   // itself, resetting all dimensions to zero.
      93             :   void DeleteAllBlocks();
      94             : 
      95             :   bool VectorContainsName(const std::vector<std::string> & the_vector,
      96             :                           const std::string & name) const;
      97             : 
      98             :   // Test variables are associated with LinearForms,
      99             :   // whereas trial variables are associated with gridfunctions.
     100             : 
     101             :   // Names of all variables corresponding to gridfunctions. This may differ
     102             :   // from test_var_names when time derivatives are present.
     103             :   std::vector<std::string> _trial_var_names;
     104             :   // Pointers to trial variables.
     105             :   Moose::MFEM::GridFunctions _trial_variables;
     106             :   // Names of all test variables corresponding to linear forms in this equation
     107             :   // system
     108             :   std::vector<std::string> _test_var_names;
     109             :   std::vector<mfem::ParFiniteElementSpace *> _test_pfespaces;
     110             : 
     111             :   // Components of weak form. // Named according to test variable
     112             :   Moose::MFEM::NamedFieldsMap<mfem::ParBilinearForm> _blfs;
     113             :   Moose::MFEM::NamedFieldsMap<mfem::ParLinearForm> _lfs;
     114             :   Moose::MFEM::NamedFieldsMap<mfem::ParNonlinearForm> _nlfs;
     115             :   Moose::MFEM::NamedFieldsMap<Moose::MFEM::NamedFieldsMap<mfem::ParMixedBilinearForm>>
     116             :       _mblfs; // named according to trial variable
     117             : 
     118             :   /**
     119             :    * Template method for applying BilinearFormIntegrators on domains from kernels to a BilinearForm,
     120             :    * or MixedBilinearForm
     121             :    */
     122             :   template <class FormType>
     123             :   void ApplyDomainBLFIntegrators(
     124             :       const std::string & trial_var_name,
     125             :       const std::string & test_var_name,
     126             :       std::shared_ptr<FormType> form,
     127             :       Moose::MFEM::NamedFieldsMap<
     128             :           Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>> & kernels_map);
     129             : 
     130             :   void ApplyDomainLFIntegrators(
     131             :       const std::string & test_var_name,
     132             :       std::shared_ptr<mfem::ParLinearForm> form,
     133             :       Moose::MFEM::NamedFieldsMap<
     134             :           Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>> & kernels_map);
     135             : 
     136             :   template <class FormType>
     137             :   void ApplyBoundaryBLFIntegrators(
     138             :       const std::string & trial_var_name,
     139             :       const std::string & test_var_name,
     140             :       std::shared_ptr<FormType> form,
     141             :       Moose::MFEM::NamedFieldsMap<
     142             :           Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMIntegratedBC>>>> &
     143             :           integrated_bc_map);
     144             : 
     145             :   void ApplyBoundaryLFIntegrators(
     146             :       const std::string & test_var_name,
     147             :       std::shared_ptr<mfem::ParLinearForm> form,
     148             :       Moose::MFEM::NamedFieldsMap<
     149             :           Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMIntegratedBC>>>> &
     150             :           integrated_bc_map);
     151             : 
     152             :   // gridfunctions for setting Dirichlet BCs
     153             :   std::vector<std::unique_ptr<mfem::ParGridFunction>> _xs;
     154             :   std::vector<std::unique_ptr<mfem::ParGridFunction>> _dxdts;
     155             : 
     156             :   mfem::Array2D<const mfem::HypreParMatrix *> _h_blocks;
     157             : 
     158             :   // Arrays to store kernels to act on each component of weak form. Named
     159             :   // according to test variable
     160             :   Moose::MFEM::NamedFieldsMap<Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>>
     161             :       _kernels_map;
     162             :   Moose::MFEM::NamedFieldsMap<
     163             :       Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMIntegratedBC>>>>
     164             :       _integrated_bc_map;
     165             :   Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMEssentialBC>>> _essential_bc_map;
     166             : 
     167             :   mutable mfem::OperatorHandle _jacobian;
     168             : 
     169             :   mfem::AssemblyLevel _assembly_level;
     170             : };
     171             : 
     172             : template <class FormType>
     173             : void
     174         262 : EquationSystem::ApplyDomainBLFIntegrators(
     175             :     const std::string & trial_var_name,
     176             :     const std::string & test_var_name,
     177             :     std::shared_ptr<FormType> form,
     178             :     Moose::MFEM::NamedFieldsMap<
     179             :         Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>> & kernels_map)
     180             : {
     181         262 :   if (kernels_map.Has(test_var_name) && kernels_map.Get(test_var_name)->Has(trial_var_name))
     182             :   {
     183         254 :     auto kernels = kernels_map.GetRef(test_var_name).GetRef(trial_var_name);
     184         548 :     for (auto & kernel : kernels)
     185             :     {
     186         294 :       mfem::BilinearFormIntegrator * integ = kernel->createBFIntegrator();
     187         294 :       if (integ != nullptr)
     188             :       {
     189         270 :         kernel->isSubdomainRestricted()
     190         270 :             ? form->AddDomainIntegrator(std::move(integ), kernel->getSubdomainMarkers())
     191         270 :             : form->AddDomainIntegrator(std::move(integ));
     192             :       }
     193             :     }
     194         254 :   }
     195         262 : }
     196             : 
     197             : inline void
     198         170 : EquationSystem::ApplyDomainLFIntegrators(
     199             :     const std::string & test_var_name,
     200             :     std::shared_ptr<mfem::ParLinearForm> form,
     201             :     Moose::MFEM::NamedFieldsMap<
     202             :         Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>> & kernels_map)
     203             : {
     204         170 :   if (kernels_map.Has(test_var_name))
     205             :   {
     206         170 :     auto kernels = kernels_map.GetRef(test_var_name).GetRef(test_var_name);
     207         380 :     for (auto & kernel : kernels)
     208             :     {
     209         210 :       mfem::LinearFormIntegrator * integ = kernel->createLFIntegrator();
     210         210 :       if (integ != nullptr)
     211             :       {
     212          24 :         kernel->isSubdomainRestricted()
     213          24 :             ? form->AddDomainIntegrator(std::move(integ), kernel->getSubdomainMarkers())
     214          24 :             : form->AddDomainIntegrator(std::move(integ));
     215             :       }
     216             :     }
     217         170 :   }
     218         170 : }
     219             : 
     220             : template <class FormType>
     221             : void
     222         262 : EquationSystem::ApplyBoundaryBLFIntegrators(
     223             :     const std::string & trial_var_name,
     224             :     const std::string & test_var_name,
     225             :     std::shared_ptr<FormType> form,
     226             :     Moose::MFEM::NamedFieldsMap<
     227             :         Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMIntegratedBC>>>> &
     228             :         integrated_bc_map)
     229             : {
     230         298 :   if (integrated_bc_map.Has(test_var_name) &&
     231          36 :       integrated_bc_map.Get(test_var_name)->Has(trial_var_name))
     232             :   {
     233          36 :     auto bcs = integrated_bc_map.GetRef(test_var_name).GetRef(trial_var_name);
     234          72 :     for (auto & bc : bcs)
     235             :     {
     236          36 :       mfem::BilinearFormIntegrator * integ = bc->createBFIntegrator();
     237          36 :       if (integ != nullptr)
     238             :       {
     239          32 :         bc->isBoundaryRestricted()
     240          32 :             ? form->AddBoundaryIntegrator(std::move(integ), bc->getBoundaryMarkers())
     241           0 :             : form->AddBoundaryIntegrator(std::move(integ));
     242             :       }
     243             :     }
     244          36 :   }
     245         262 : }
     246             : 
     247             : inline void
     248         170 : EquationSystem::ApplyBoundaryLFIntegrators(
     249             :     const std::string & test_var_name,
     250             :     std::shared_ptr<mfem::ParLinearForm> form,
     251             :     Moose::MFEM::NamedFieldsMap<
     252             :         Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMIntegratedBC>>>> &
     253             :         integrated_bc_map)
     254             : {
     255         170 :   if (integrated_bc_map.Has(test_var_name))
     256             :   {
     257          20 :     auto bcs = integrated_bc_map.GetRef(test_var_name).GetRef(test_var_name);
     258          40 :     for (auto & bc : bcs)
     259             :     {
     260          20 :       mfem::LinearFormIntegrator * integ = bc->createLFIntegrator();
     261          20 :       if (integ != nullptr)
     262             :       {
     263          20 :         bc->isBoundaryRestricted()
     264          20 :             ? form->AddBoundaryIntegrator(std::move(integ), bc->getBoundaryMarkers())
     265           0 :             : form->AddBoundaryIntegrator(std::move(integ));
     266             :       }
     267             :     }
     268          20 :   }
     269         170 : }
     270             : 
     271             : /*
     272             : Class to store weak form components for time dependent PDEs
     273             : */
     274             : class TimeDependentEquationSystem : public EquationSystem
     275             : {
     276             : public:
     277             :   TimeDependentEquationSystem();
     278             : 
     279             :   void AddTrialVariableNameIfMissing(const std::string & trial_var_name) override;
     280             : 
     281             :   virtual void SetTimeStep(double dt);
     282             :   virtual void UpdateEquationSystem();
     283             : 
     284             :   virtual void AddKernel(std::shared_ptr<MFEMKernel> kernel) override;
     285             :   virtual void BuildBilinearForms() override;
     286             :   virtual void FormLegacySystem(mfem::OperatorHandle & op,
     287             :                                 mfem::BlockVector & truedXdt,
     288             :                                 mfem::BlockVector & trueRHS) override;
     289             :   virtual void FormSystem(mfem::OperatorHandle & op,
     290             :                           mfem::BlockVector & truedXdt,
     291             :                           mfem::BlockVector & trueRHS) override;
     292             : 
     293             :   const std::vector<std::string> & TrialVarTimeDerivativeNames() const;
     294             : 
     295             : protected:
     296             :   mfem::ConstantCoefficient _dt_coef; // Coefficient for timestep scaling
     297             :   std::vector<std::string> _trial_var_time_derivative_names;
     298             : 
     299             :   Moose::MFEM::NamedFieldsMap<Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>>
     300             :       _td_kernels_map;
     301             :   // Container to store contributions to weak form of the form (F du/dt, v)
     302             :   Moose::MFEM::NamedFieldsMap<mfem::ParBilinearForm> _td_blfs;
     303             : };
     304             : 
     305             : inline const std::vector<std::string> &
     306          24 : TimeDependentEquationSystem::TrialVarTimeDerivativeNames() const
     307             : {
     308          24 :   return _trial_var_time_derivative_names;
     309             : }
     310             : 
     311             : } // namespace Moose::MFEM
     312             : 
     313             : #endif

Generated by: LCOV version 1.14