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 : auto test_mblfs = 99 1066 : std::make_shared<Moose::MFEM::NamedFieldsMap<Moose::MFEM::ParMixedBilinearForm>>(); 100 2168 : for (const auto j : index_range(_coupled_var_names)) 101 : { 102 1102 : const auto & coupled_var_name = _coupled_var_names.at(j); 103 2204 : auto mblf = std::make_shared<Moose::MFEM::ParMixedBilinearForm>(_coupled_pfespaces.at(j), 104 1102 : _test_pfespaces.at(i)); 105 : // Register MixedBilinearForm if kernels exist for it, and assemble kernels 106 1102 : if (test_var_name != coupled_var_name) 107 : { 108 : // Apply all mixed kernels with this test/trial pair 109 36 : ApplyBoundaryBLFIntegrators<Moose::MFEM::ParMixedBilinearForm>( 110 36 : coupled_var_name, test_var_name, mblf, _integrated_bc_map, _dt); 111 36 : ApplyDomainBLFIntegrators<Moose::MFEM::ParMixedBilinearForm>( 112 36 : coupled_var_name, test_var_name, mblf, _kernels_map, _dt); 113 : // Apply dt*du/dt contributions from the operator on the trial variable 114 72 : ApplyDomainBLFIntegrators<Moose::MFEM::ParMixedBilinearForm>( 115 36 : coupled_var_name, test_var_name, mblf, _td_kernels_map); 116 36 : if (mblf->GetDBFI()->Size() || mblf->GetBBFI()->Size()) 117 : { 118 : // Assemble mixed bilinear forms 119 36 : mblf->SetAssemblyLevel(_assembly_level); 120 36 : mblf->Assemble(); 121 : // Register mixed bilinear forms associated with a single trial variable 122 : // for the current test variable 123 36 : test_mblfs->Register(coupled_var_name, mblf); 124 : } 125 : } 126 1102 : } 127 : // Register all mixed bilinear form sets associated with a single test variable 128 1066 : _mblfs.Register(test_var_name, test_mblfs); 129 1066 : } 130 : 131 : // Register mixed bilinear forms. Note that not all combinations may 132 : // have a kernel. 133 : 134 : // Create mblf for each test/trial variable pair with an added kernel 135 2114 : for (const auto i : index_range(_test_var_names)) 136 : { 137 1066 : const auto & test_var_name = _test_var_names.at(i); 138 : auto test_td_mblfs = 139 1066 : std::make_shared<Moose::MFEM::NamedFieldsMap<Moose::MFEM::ParMixedBilinearForm>>(); 140 2168 : for (const auto j : index_range(_trial_var_names)) 141 : { 142 1102 : const auto & trial_var_name = _trial_var_names.at(j); 143 2204 : auto td_mblf = std::make_shared<Moose::MFEM::ParMixedBilinearForm>(_test_pfespaces.at(j), 144 1102 : _test_pfespaces.at(i)); 145 : // Register MixedBilinearForm if kernels exist for it, and assemble kernels 146 1102 : if (test_var_name != trial_var_name) 147 : { 148 : // Apply all mixed kernels with this test/trial pair 149 72 : ApplyDomainBLFIntegrators<Moose::MFEM::ParMixedBilinearForm>( 150 36 : trial_var_name, test_var_name, td_mblf, _td_kernels_map); 151 : // Assemble mixed bilinear form 152 36 : if (td_mblf->GetDBFI()->Size() || td_mblf->GetBBFI()->Size()) 153 : { 154 18 : td_mblf->SetAssemblyLevel(_assembly_level); 155 18 : td_mblf->Assemble(); 156 : // Register mixed bilinear forms associated with a single trial variable 157 : // for the current test variable 158 18 : test_td_mblfs->Register(trial_var_name, td_mblf); 159 : } 160 : } 161 1102 : } 162 : // Register all mixed bilinear forms associated with a single test variable 163 1066 : _td_mblfs.Register(test_var_name, test_td_mblfs); 164 1066 : } 165 1048 : } 166 : 167 : void 168 1048 : TimeDependentEquationSystem::BuildNonlinearForms() 169 : { 170 : // Register non-linear Action forms 171 2114 : for (const auto i : index_range(_test_var_names)) 172 : { 173 1066 : auto test_var_name = _test_var_names.at(i); 174 1066 : _nlfs.Register(test_var_name, std::make_shared<mfem::ParNonlinearForm>(_test_pfespaces.at(i))); 175 : // Apply kernels 176 1066 : auto nlf = _nlfs.GetShared(test_var_name); 177 1066 : nlf->SetEssentialTrueDofs(_ess_tdof_lists.at(i)); 178 1066 : ApplyDomainNLFIntegrators(test_var_name, nlf, _kernels_map, _dt); 179 1066 : ApplyBoundaryNLFIntegrators(test_var_name, nlf, _integrated_bc_map, _dt); 180 1066 : } 181 1048 : } 182 : 183 : void 184 1048 : TimeDependentEquationSystem::EliminateCoupledVariables() 185 : { 186 2114 : for (const auto & test_var_name : _test_var_names) 187 : { 188 1066 : auto & lf = *_lfs.Get(test_var_name) *= _dt; 189 2162 : for (const auto & eliminated_var_name : _eliminated_var_names) 190 1096 : if (eliminated_var_name == test_var_name) 191 : { 192 : // if implicit, add contribution to linear form from terms involving state 193 : // The AddMult method in mfem::BilinearForm is not defined for non-legacy assembly 194 1060 : mfem::Vector lf_prev(lf.Size()); 195 1060 : auto & td_blf = *_td_blfs.Get(test_var_name); 196 1060 : td_blf.Mult(*_eliminated_variables.Get(test_var_name), lf_prev); 197 1060 : lf += lf_prev; 198 1060 : } 199 72 : else if (_td_mblfs.Has(test_var_name) && 200 36 : _td_mblfs.Get(test_var_name)->Has(eliminated_var_name)) 201 : { 202 18 : auto & td_mblf = *_td_mblfs.Get(test_var_name)->Get(eliminated_var_name); 203 18 : td_mblf.AddMult(*_eliminated_variables.Get(eliminated_var_name), lf); 204 : } 205 : } 206 : // Eliminate contributions from other coupled variables. 207 1048 : EquationSystem::EliminateCoupledVariables(); 208 1048 : } 209 : 210 : } // namespace Moose::MFEM 211 : 212 : #endif