Line data Source code
1 : #ifdef MOOSE_MFEM_ENABLED 2 : 3 : #pragma once 4 : 5 : #include "libmesh/ignore_warnings.h" 6 : #include "mfem/miniapps/common/pfem_extras.hpp" 7 : #include "libmesh/restore_warnings.h" 8 : #include "EquationSystem.h" 9 : #include "MFEMComplexKernel.h" 10 : #include "MFEMComplexIntegratedBC.h" 11 : #include "MFEMComplexEssentialBC.h" 12 : 13 : namespace Moose::MFEM 14 : { 15 : /* 16 : Class to store weak form components (bilinear and linear forms, and optionally 17 : mixed and nonlinear forms) and build methods 18 : */ 19 : class ComplexEquationSystem : public EquationSystem 20 : { 21 : public: 22 63 : ComplexEquationSystem() = default; 23 63 : ~ComplexEquationSystem() = default; 24 : 25 : // Build forms 26 : virtual void Init(GridFunctions & gridfunctions, 27 : ComplexGridFunctions & cmplx_gridfunctions, 28 : mfem::AssemblyLevel assembly_level) override; 29 : 30 : ///Nonlinear Mult (Used by Newton-solver not necessarily nonlinear) 31 : virtual void Mult(const mfem::Vector & x, mfem::Vector & y) const override; 32 : 33 : /// Build all forms comprising this EquationSystem 34 : virtual void BuildEquationSystem() override; 35 : 36 : /// Build linear forms and eliminate constrained DoFs 37 : virtual void BuildLinearForms() override; 38 : 39 : /// Build bilinear forms (diagonal Jacobian contributions) 40 : virtual void BuildBilinearForms() override; 41 : 42 : /// Apply essential BC(s) associated with var_name to set true DoFs of trial_gf and update 43 : /// markers of all essential boundaries 44 : virtual void ApplyComplexEssentialBC(const std::string & var_name, 45 : mfem::ParComplexGridFunction & trial_gf, 46 : mfem::Array<int> & global_ess_markers); 47 : /// Update all essentially constrained true DoF markers and values on boundaries 48 : virtual void ApplyEssentialBCs() override; 49 : 50 : /// Add complex kernels 51 : void AddComplexKernel(std::shared_ptr<MFEMComplexKernel> kernel); 52 : 53 : /// Add complex integrated BCs 54 : void AddComplexIntegratedBC(std::shared_ptr<MFEMComplexIntegratedBC> bc); 55 : 56 : /// Add complex essential BCs 57 : void AddComplexEssentialBCs(std::shared_ptr<MFEMComplexEssentialBC> bc); 58 : 59 : /// Form matrix-free representation of system operator. 60 : /// Used when EquationSystem assembly level is set to 'FULL', 'ELEMENT', 'PARTIAL', or 'NONE'. 61 : virtual void FormSystemOperator(mfem::OperatorHandle & op, 62 : mfem::BlockVector & trueX, 63 : mfem::BlockVector & trueRHS) override; 64 : 65 : /// Form matrix representation of system operator as a HypreParMatrix. 66 : /// Used when EquationSystem assembly level is set to 'LEGACY'. 67 : virtual void FormSystemMatrix(mfem::OperatorHandle & op, 68 : mfem::BlockVector & trueX, 69 : mfem::BlockVector & trueRHS) override; 70 : 71 : /// Update variable from solution vector after solve 72 : virtual void SetTrialVariablesFromTrueVectors(const mfem::BlockVector & trueX) const override; 73 : 74 : /// Template method for applying BilinearFormIntegrators on domains from kernels to a SesquilinearForm 75 : template <class FormType> 76 : void ApplyDomainBLFIntegrators( 77 : const std::string & trial_var_name, 78 : const std::string & test_var_name, 79 : std::shared_ptr<FormType> form, 80 : NamedFieldsMap<NamedFieldsMap<std::vector<std::shared_ptr<MFEMComplexKernel>>>> & 81 : kernels_map); 82 : 83 : /// Method for applying LinearFormIntegrators on domains from kernels to a ParComplexLinearForm 84 : inline void ApplyDomainLFIntegrators( 85 : const std::string & test_var_name, 86 : std::shared_ptr<mfem::ParComplexLinearForm> form, 87 : NamedFieldsMap<NamedFieldsMap<std::vector<std::shared_ptr<MFEMComplexKernel>>>> & 88 : kernels_map); 89 : 90 : /// Template method for applying BilinearFormIntegrators on boudaries from kernels to a SesquilinearForm 91 : template <class FormType> 92 : void ApplyBoundaryBLFIntegrators( 93 : const std::string & trial_var_name, 94 : const std::string & test_var_name, 95 : std::shared_ptr<FormType> form, 96 : NamedFieldsMap<NamedFieldsMap<std::vector<std::shared_ptr<MFEMComplexIntegratedBC>>>> & 97 : integrated_bc_map); 98 : 99 : /// Method for applying LinearFormIntegrators on boundaries from kernels to a ParComplexLinearForm 100 : inline void ApplyBoundaryLFIntegrators( 101 : const std::string & test_var_name, 102 : std::shared_ptr<mfem::ParComplexLinearForm> form, 103 : NamedFieldsMap<NamedFieldsMap<std::vector<std::shared_ptr<MFEMComplexIntegratedBC>>>> & 104 : integrated_bc_map); 105 : 106 0 : virtual bool Complex() const override { return true; } 107 : 108 : protected: 109 : // Complex Linear and Bilinear Forms 110 : NamedFieldsMap<mfem::ParSesquilinearForm> _slfs; 111 : NamedFieldsMap<mfem::ParComplexLinearForm> _clfs; 112 : 113 : // Complex kernels and integrated BCs 114 : NamedFieldsMap<NamedFieldsMap<std::vector<std::shared_ptr<MFEMComplexKernel>>>> 115 : _cmplx_kernels_map; 116 : NamedFieldsMap<NamedFieldsMap<std::vector<std::shared_ptr<MFEMComplexIntegratedBC>>>> 117 : _cmplx_integrated_bc_map; 118 : 119 : // Complex essential BCs 120 : NamedFieldsMap<std::vector<std::shared_ptr<MFEMComplexEssentialBC>>> _cmplx_essential_bc_map; 121 : 122 : /// Pointers to coupled variables not part of the reduced EquationSystem. 123 : ComplexGridFunctions _cmplx_eliminated_variables; 124 : 125 : /// Complex Gridfunctions holding essential constraints from Dirichlet BCs 126 : std::vector<std::unique_ptr<mfem::ParComplexGridFunction>> _cmplx_var_ess_constraints; 127 : 128 : // Pointer to complex GridFunctions to enable updates during nonlinear iterations 129 : Moose::MFEM::ComplexGridFunctions * _complex_gfuncs; 130 : }; 131 : 132 : template <class FormType> 133 : void 134 42 : ComplexEquationSystem::ApplyDomainBLFIntegrators( 135 : const std::string & trial_var_name, 136 : const std::string & test_var_name, 137 : std::shared_ptr<FormType> form, 138 : NamedFieldsMap<NamedFieldsMap<std::vector<std::shared_ptr<MFEMComplexKernel>>>> & kernels_map) 139 : { 140 42 : if (kernels_map.Has(test_var_name) && kernels_map.Get(test_var_name)->Has(trial_var_name)) 141 : { 142 42 : auto kernels = kernels_map.GetRef(test_var_name).GetRef(trial_var_name); 143 105 : for (auto & kernel : kernels) 144 : { 145 63 : mfem::BilinearFormIntegrator * integ_real = kernel->getRealBFIntegrator(); 146 63 : mfem::BilinearFormIntegrator * integ_imag = kernel->getImagBFIntegrator(); 147 : 148 63 : if (integ_real || integ_imag) 149 : { 150 63 : kernel->isSubdomainRestricted() 151 63 : ? form->AddDomainIntegrator( 152 0 : std::move(integ_real), std::move(integ_imag), kernel->getSubdomainMarkers()) 153 63 : : form->AddDomainIntegrator(std::move(integ_real), std::move(integ_imag)); 154 : } 155 : } 156 42 : } 157 42 : } 158 : 159 : inline void 160 42 : ComplexEquationSystem::ApplyDomainLFIntegrators( 161 : const std::string & test_var_name, 162 : std::shared_ptr<mfem::ParComplexLinearForm> form, 163 : NamedFieldsMap<NamedFieldsMap<std::vector<std::shared_ptr<MFEMComplexKernel>>>> & kernels_map) 164 : { 165 42 : if (kernels_map.Has(test_var_name)) 166 : { 167 42 : auto kernels = kernels_map.GetRef(test_var_name).GetRef(test_var_name); 168 105 : for (auto & kernel : kernels) 169 : { 170 63 : mfem::LinearFormIntegrator * integ_real = kernel->getRealLFIntegrator(); 171 63 : mfem::LinearFormIntegrator * integ_imag = kernel->getImagLFIntegrator(); 172 : 173 63 : if (integ_real || integ_imag) 174 : { 175 0 : kernel->isSubdomainRestricted() 176 0 : ? form->AddDomainIntegrator( 177 0 : std::move(integ_real), std::move(integ_imag), kernel->getSubdomainMarkers()) 178 0 : : form->AddDomainIntegrator(std::move(integ_real), std::move(integ_imag)); 179 : } 180 : } 181 42 : } 182 42 : } 183 : 184 : template <class FormType> 185 : void 186 42 : ComplexEquationSystem::ApplyBoundaryBLFIntegrators( 187 : const std::string & trial_var_name, 188 : const std::string & test_var_name, 189 : std::shared_ptr<FormType> form, 190 : NamedFieldsMap<NamedFieldsMap<std::vector<std::shared_ptr<MFEMComplexIntegratedBC>>>> & 191 : integrated_bc_map) 192 : { 193 49 : if (integrated_bc_map.Has(test_var_name) && 194 7 : integrated_bc_map.Get(test_var_name)->Has(trial_var_name)) 195 : { 196 7 : auto bcs = integrated_bc_map.GetRef(test_var_name).GetRef(trial_var_name); 197 21 : for (auto & bc : bcs) 198 : { 199 14 : mfem::BilinearFormIntegrator * integ_real = bc->getRealBFIntegrator(); 200 14 : mfem::BilinearFormIntegrator * integ_imag = bc->getImagBFIntegrator(); 201 : 202 14 : if (integ_real || integ_imag) 203 : { 204 14 : bc->isBoundaryRestricted() 205 42 : ? form->AddBoundaryIntegrator( 206 28 : std::move(integ_real), std::move(integ_imag), bc->getBoundaryMarkers()) 207 0 : : form->AddBoundaryIntegrator(std::move(integ_real), std::move(integ_imag)); 208 : } 209 : } 210 7 : } 211 42 : } 212 : 213 : inline void 214 42 : ComplexEquationSystem::ApplyBoundaryLFIntegrators( 215 : const std::string & test_var_name, 216 : std::shared_ptr<mfem::ParComplexLinearForm> form, 217 : NamedFieldsMap<NamedFieldsMap<std::vector<std::shared_ptr<MFEMComplexIntegratedBC>>>> & 218 : integrated_bc_map) 219 : { 220 42 : if (integrated_bc_map.Has(test_var_name)) 221 : { 222 7 : auto bcs = integrated_bc_map.GetRef(test_var_name).GetRef(test_var_name); 223 21 : for (auto & bc : bcs) 224 : { 225 14 : mfem::LinearFormIntegrator * integ_real = bc->getRealLFIntegrator(); 226 14 : mfem::LinearFormIntegrator * integ_imag = bc->getImagLFIntegrator(); 227 : 228 14 : if (integ_real || integ_imag) 229 : { 230 7 : bc->isBoundaryRestricted() 231 21 : ? form->AddBoundaryIntegrator( 232 14 : std::move(integ_real), std::move(integ_imag), bc->getBoundaryMarkers()) 233 0 : : form->AddBoundaryIntegrator(std::move(integ_real), std::move(integ_imag)); 234 : } 235 : } 236 7 : } 237 42 : } 238 : 239 : } 240 : 241 : #endif