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