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 "TimeDependentEquationSystem.h" 13 : 14 : namespace Moose::MFEM 15 : { 16 274 : TimeDependentEquationSystem::TimeDependentEquationSystem( 17 274 : const Moose::MFEM::TimeDerivativeMap & time_derivative_map) 18 274 : : _dt(1.0), _time_derivative_map(time_derivative_map) 19 : { 20 274 : } 21 : 22 : void 23 290 : TimeDependentEquationSystem::AddKernel(std::shared_ptr<MFEMKernel> kernel) 24 : { 25 290 : if (!_time_derivative_map.isTimeDerivative(kernel->getTrialVariableName())) 26 : { 27 145 : EquationSystem::AddKernel(kernel); 28 145 : return; 29 : } 30 : 31 : const auto & trial_var_name = 32 145 : _time_derivative_map.getTimeIntegralName(kernel->getTrialVariableName()); 33 145 : const auto & test_var_name = kernel->getTestVariableName(); 34 145 : AddEliminatedVariableNameIfMissing(trial_var_name); 35 145 : AddTestVariableNameIfMissing(test_var_name); 36 : // Register new td kernels map if not present for the test variable 37 145 : if (!_td_kernels_map.Has(test_var_name)) 38 : { 39 : auto kernel_field_map = 40 139 : std::make_shared<Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>>(); 41 139 : _td_kernels_map.Register(test_var_name, std::move(kernel_field_map)); 42 139 : } 43 : // Register new td kernels map if not present for the test/trial variable pair 44 145 : if (!_td_kernels_map.Get(test_var_name)->Has(trial_var_name)) 45 : { 46 145 : auto kernels = std::make_shared<std::vector<std::shared_ptr<MFEMKernel>>>(); 47 145 : _td_kernels_map.Get(test_var_name)->Register(trial_var_name, std::move(kernels)); 48 145 : } 49 145 : _td_kernels_map.GetRef(test_var_name).Get(trial_var_name)->push_back(std::move(kernel)); 50 : } 51 : 52 : void 53 1048 : TimeDependentEquationSystem::BuildBilinearForms() 54 : { 55 : // Register bilinear forms 56 2114 : for (const auto i : index_range(_test_var_names)) 57 : { 58 1066 : const auto & test_var_name = _test_var_names.at(i); 59 : 60 : // Apply kernels to blf 61 1066 : _blfs.Register(test_var_name, std::make_shared<mfem::ParBilinearForm>(_test_pfespaces.at(i))); 62 1066 : auto blf = _blfs.GetShared(test_var_name); 63 1066 : blf->SetAssemblyLevel(_assembly_level); 64 1066 : ApplyBoundaryBLFIntegrators<mfem::ParBilinearForm>( 65 1066 : test_var_name, test_var_name, blf, _integrated_bc_map, _dt); 66 1066 : ApplyDomainBLFIntegrators<mfem::ParBilinearForm>( 67 1066 : test_var_name, test_var_name, blf, _kernels_map, _dt); 68 : // Apply dt*du/dt contributions from the operator on the trial variable 69 2132 : ApplyDomainBLFIntegrators<mfem::ParBilinearForm>( 70 1066 : test_var_name, test_var_name, blf, _td_kernels_map); 71 : // Assemble 72 1066 : blf->Assemble(); 73 : 74 : // Apply kernels to td_blf 75 1066 : _td_blfs.Register(test_var_name, 76 2132 : std::make_shared<mfem::ParBilinearForm>(_test_pfespaces.at(i))); 77 1066 : auto td_blf = _td_blfs.GetShared(test_var_name); 78 1066 : td_blf->SetAssemblyLevel(_assembly_level); 79 2132 : ApplyDomainBLFIntegrators<mfem::ParBilinearForm>( 80 1066 : test_var_name, test_var_name, td_blf, _td_kernels_map); 81 : // Assemble 82 1066 : td_blf->Assemble(); 83 1066 : } 84 1048 : } 85 : 86 : void 87 1048 : TimeDependentEquationSystem::BuildMixedBilinearForms() 88 : { 89 : // Register mixed bilinear forms. Note that not all combinations may 90 : // have a kernel. 91 : 92 : // Create mblf for each test/coupled variable pair with an added kernel. 93 : // Mixed bilinear forms with coupled variables that are not trial variables are 94 : // associated with contributions from eliminated variables. 95 2114 : for (const auto i : index_range(_test_var_names)) 96 : { 97 1066 : const auto & test_var_name = _test_var_names.at(i); 98 1066 : auto test_mblfs = std::make_shared<Moose::MFEM::NamedFieldsMap<mfem::ParMixedBilinearForm>>(); 99 2168 : for (const auto j : index_range(_coupled_var_names)) 100 : { 101 1102 : const auto & coupled_var_name = _coupled_var_names.at(j); 102 2204 : auto mblf = std::make_shared<mfem::ParMixedBilinearForm>(_coupled_pfespaces.at(j), 103 1102 : _test_pfespaces.at(i)); 104 : // Register MixedBilinearForm if kernels exist for it, and assemble kernels 105 1102 : if (test_var_name != coupled_var_name) 106 : { 107 : // Apply all mixed kernels with this test/trial pair 108 36 : ApplyBoundaryBLFIntegrators<mfem::ParMixedBilinearForm>( 109 36 : coupled_var_name, test_var_name, mblf, _integrated_bc_map, _dt); 110 36 : ApplyDomainBLFIntegrators<mfem::ParMixedBilinearForm>( 111 36 : coupled_var_name, test_var_name, mblf, _kernels_map, _dt); 112 : // Apply dt*du/dt contributions from the operator on the trial variable 113 72 : ApplyDomainBLFIntegrators<mfem::ParMixedBilinearForm>( 114 36 : coupled_var_name, test_var_name, mblf, _td_kernels_map); 115 36 : if (mblf->GetDBFI()->Size() || mblf->GetBBFI()->Size()) 116 : { 117 : // Assemble mixed bilinear forms 118 36 : mblf->SetAssemblyLevel(_assembly_level); 119 36 : mblf->Assemble(); 120 : // Register mixed bilinear forms associated with a single trial variable 121 : // for the current test variable 122 36 : test_mblfs->Register(coupled_var_name, mblf); 123 : } 124 : } 125 1102 : } 126 : // Register all mixed bilinear form sets associated with a single test variable 127 1066 : _mblfs.Register(test_var_name, test_mblfs); 128 1066 : } 129 : 130 : // Register mixed bilinear forms. Note that not all combinations may 131 : // have a kernel. 132 : 133 : // Create mblf for each test/trial variable pair with an added kernel 134 2114 : for (const auto i : index_range(_test_var_names)) 135 : { 136 1066 : const auto & test_var_name = _test_var_names.at(i); 137 : auto test_td_mblfs = 138 1066 : std::make_shared<Moose::MFEM::NamedFieldsMap<mfem::ParMixedBilinearForm>>(); 139 2168 : for (const auto j : index_range(_trial_var_names)) 140 : { 141 1102 : const auto & trial_var_name = _trial_var_names.at(j); 142 2204 : auto td_mblf = std::make_shared<mfem::ParMixedBilinearForm>(_test_pfespaces.at(j), 143 1102 : _test_pfespaces.at(i)); 144 : // Register MixedBilinearForm if kernels exist for it, and assemble kernels 145 1102 : if (test_var_name != trial_var_name) 146 : { 147 : // Apply all mixed kernels with this test/trial pair 148 72 : ApplyDomainBLFIntegrators<mfem::ParMixedBilinearForm>( 149 36 : trial_var_name, test_var_name, td_mblf, _td_kernels_map); 150 : // Assemble mixed bilinear form 151 36 : if (td_mblf->GetDBFI()->Size() || td_mblf->GetBBFI()->Size()) 152 : { 153 18 : td_mblf->SetAssemblyLevel(_assembly_level); 154 18 : td_mblf->Assemble(); 155 : // Register mixed bilinear forms associated with a single trial variable 156 : // for the current test variable 157 18 : test_td_mblfs->Register(trial_var_name, td_mblf); 158 : } 159 : } 160 1102 : } 161 : // Register all mixed bilinear forms associated with a single test variable 162 1066 : _td_mblfs.Register(test_var_name, test_td_mblfs); 163 1066 : } 164 1048 : } 165 : 166 : void 167 1048 : TimeDependentEquationSystem::BuildNonlinearForms() 168 : { 169 : // Register non-linear Action forms 170 2114 : for (const auto i : index_range(_test_var_names)) 171 : { 172 1066 : auto test_var_name = _test_var_names.at(i); 173 1066 : _nlfs.Register(test_var_name, std::make_shared<mfem::ParNonlinearForm>(_test_pfespaces.at(i))); 174 : // Apply kernels 175 1066 : auto nlf = _nlfs.GetShared(test_var_name); 176 1066 : nlf->SetEssentialTrueDofs(_ess_tdof_lists.at(i)); 177 1066 : ApplyDomainNLFIntegrators(test_var_name, nlf, _kernels_map, _dt); 178 1066 : ApplyBoundaryNLFIntegrators(test_var_name, nlf, _integrated_bc_map, _dt); 179 1066 : } 180 1048 : } 181 : 182 : void 183 1048 : TimeDependentEquationSystem::EliminateCoupledVariables() 184 : { 185 2114 : for (const auto & test_var_name : _test_var_names) 186 : { 187 1066 : auto & lf = *_lfs.Get(test_var_name) *= _dt; 188 2162 : for (const auto & eliminated_var_name : _eliminated_var_names) 189 1096 : if (eliminated_var_name == test_var_name) 190 : { 191 : // if implicit, add contribution to linear form from terms involving state 192 : // The AddMult method in mfem::BilinearForm is not defined for non-legacy assembly 193 1060 : mfem::Vector lf_prev(lf.Size()); 194 1060 : auto & td_blf = *_td_blfs.Get(test_var_name); 195 1060 : td_blf.Mult(*_eliminated_variables.Get(test_var_name), lf_prev); 196 1060 : lf += lf_prev; 197 1060 : } 198 72 : else if (_td_mblfs.Has(test_var_name) && 199 36 : _td_mblfs.Get(test_var_name)->Has(eliminated_var_name)) 200 : { 201 18 : auto & td_mblf = *_td_mblfs.Get(test_var_name)->Get(eliminated_var_name); 202 18 : td_mblf.AddMult(*_eliminated_variables.Get(eliminated_var_name), lf); 203 : } 204 : } 205 : // Eliminate contributions from other coupled variables. 206 1048 : EquationSystem::EliminateCoupledVariables(); 207 1048 : } 208 : 209 : } // namespace Moose::MFEM 210 : 211 : #endif