VertexCFD  0.0-dev
VertexCFD_EquationSet_FullInductionMHD_impl.hpp
1 #ifndef VERTEXCFD_EQUATIONSET_FULLINDUCTIONMHD_IMPL_HPP
2 #define VERTEXCFD_EQUATIONSET_FULLINDUCTIONMHD_IMPL_HPP
3 
4 #include <Panzer_BasisIRLayout.hpp>
5 #include <Panzer_IntegrationRule.hpp>
6 
7 #include <Panzer_Integrator_BasisTimesScalar.hpp>
8 #include <Panzer_Integrator_GradBasisDotVector.hpp>
9 
10 #include <Phalanx_FieldManager.hpp>
11 
12 #include <Teuchos_ParameterList.hpp>
13 #include <Teuchos_RCP.hpp>
14 #include <Teuchos_StandardParameterEntryValidators.hpp>
15 
16 namespace VertexCFD
17 {
18 namespace EquationSet
19 {
20 //---------------------------------------------------------------------------//
21 template<class EvalType>
22 FullInductionMHD<EvalType>::FullInductionMHD(
23  const Teuchos::RCP<Teuchos::ParameterList>& params,
24  const int& default_integration_order,
25  const panzer::CellData& cell_data,
26  const Teuchos::RCP<panzer::GlobalData>& global_data,
27  const bool build_transient_support)
28  : panzer::EquationSet_DefaultImpl<EvalType>(params,
29  default_integration_order,
30  cell_data,
31  global_data,
32  build_transient_support)
33 {
34  // This equation set is always transient.
35  if (!this->buildTransientSupport())
36  {
37  throw std::logic_error(
38  "Transient support is required for solving all equation sets.");
39  }
40 
41  // Get the number of space dimensions.
42  _num_space_dim = cell_data.baseCellDimension();
43  if (!(_num_space_dim == 2 || _num_space_dim == 3))
44  {
45  throw std::runtime_error("Number of space dimensions not supported");
46  }
47 
48  // Check for fluid or solid domain to restrict input parameters accordingly
49  const bool fluid_mhd = params->get<std::string>("Type")
50  == "FullInductionMHD";
51 
52  // Set default parameter values and validate the inputs.
53  Teuchos::ParameterList valid_parameters;
54  this->setDefaultValidParameters(valid_parameters);
55  valid_parameters.set(
56  "Model ID", "", "Closure model id associated with this equation set");
57  valid_parameters.set("Basis Order", 1, "Order of the basis");
58  valid_parameters.set("Integration Order", 2, "Order of the integration");
59  valid_parameters.set(
60  "Build Resistive Flux", false, "Resistive flux boolean");
61  valid_parameters.set("Build Induction Constant Source",
62  false,
63  "Induction equation constant source boolean");
64  valid_parameters.set("Build Magnetic Correction Potential Equation",
65  false,
66  "Solve full induction equation with divergence "
67  "cleaning");
68  if (fluid_mhd)
69  {
70  valid_parameters.set("Build Divergence Cleaning Source",
71  false,
72  "Divergence cleaning source boolean");
73  valid_parameters.set("Build Godunov-Powell Source",
74  false,
75  "Godunov-Powell source boolean");
76  }
77  valid_parameters.set("Build Magnetic Correction Damping Source",
78  false,
79  "Magnetic Correction damping source boolean");
80  params->validateParametersAndSetDefaults(valid_parameters);
81 
82  // Extract parameters.
83  const int basis_order = params->get<int>("Basis Order", 1);
84  const int integration_order
85  = params->get<int>("Integration Order", basis_order + 1);
86  const std::string model_id = params->get<std::string>("Model ID");
87  const bool build_ind_equ_const_source
88  = params->get<bool>("Build Induction Constant Source");
89  const bool build_magn_corr
90  = params->get<bool>("Build Magnetic Correction Potential Equation");
91  _build_resistive_flux = params->get<bool>("Build Resistive Flux");
92  const bool build_div_cleaning_src
93  = fluid_mhd ? params->get<bool>("Build Divergence Cleaning Source")
94  : false;
95  const bool build_godunov_powell_source
96  = fluid_mhd ? params->get<bool>("Build Godunov-Powell Source") : false;
97  const bool build_magn_corr_damping_src
98  = params->get<bool>("Build Magnetic Correction Damping Source");
99 
100  // convective flux is not evaluated for solid domains when there is no
101  // divergence cleaning
102  _build_convective_flux = fluid_mhd || build_magn_corr;
103 
104  // Initialize equation names and variables names for full induction model
105  for (int d = 0; d < _num_space_dim; ++d)
106  {
107  const std::string ds = std::to_string(d);
108  _equ_dof_fim_pair.insert(
109  {"induction_" + ds, "induced_magnetic_field_" + ds});
110  }
111 
112  if (build_magn_corr)
113  {
114  _equ_dof_fim_pair.insert(
115  {"magnetic_correction_potential", "scalar_magnetic_potential"});
116  }
117 
118  // Functions to set dofs
119  auto set_dofs
120  = [&, this](const std::string& equ_name, const std::string& dof_name) {
121  const std::string residual_name = "RESIDUAL_" + equ_name;
122  const std::string scatter_name = "SCATTER_" + equ_name;
123  const std::string basis_type = "HGrad";
124  this->addDOF(dof_name,
125  basis_type,
126  basis_order,
127  integration_order,
128  residual_name,
129  scatter_name);
130  this->addDOFGrad(dof_name);
131  this->addDOFTimeDerivative(dof_name);
132  };
133 
134  // Setup degrees of freedom for FIM equations
135  for (auto it : _equ_dof_fim_pair)
136  {
137  const auto equ_name = it.first;
138  const auto dof_name = it.second;
139  set_dofs(equ_name, dof_name);
140  // Set up the source terms for induction equations
141  if (std::string::npos != equ_name.find("induction"))
142  {
143  std::unordered_map<std::string, bool> source_term;
144  source_term.insert(
145  {"GODUNOV_POWELL_SOURCE", build_godunov_powell_source});
146  source_term.insert({"CONSTANT_SOURCE", build_ind_equ_const_source});
147  _equ_source_term.insert({equ_name, source_term});
148  }
149  if (std::string::npos != equ_name.find("magnetic_correction"))
150  {
151  std::unordered_map<std::string, bool> source_term;
152  source_term.insert({"DIV_CLEANING_SOURCE", build_div_cleaning_src});
153  source_term.insert({"DAMPING_SOURCE", build_magn_corr_damping_src});
154  _equ_source_term.insert({equ_name, source_term});
155  }
156  }
157 
158  // Add closure models and set-up DOFs
159  this->addClosureModel(model_id);
160  this->setupDOFs();
161 }
162 
163 //---------------------------------------------------------------------------//
164 template<class EvalType>
165 void FullInductionMHD<EvalType>::buildAndRegisterEquationSetEvaluators(
166  PHX::FieldManager<panzer::Traits>& fm,
167  const panzer::FieldLibrary&,
168  const Teuchos::ParameterList&) const
169 {
170  // Integration data. The same rule and basis is used for all DOFs in this
171  // implementation so use the lagrange pressure field to get this data.
172  const auto it = _equ_dof_fim_pair.find("induction_0");
173  const auto ir = this->getIntRuleForDOF(it->second);
174  const auto basis = this->getBasisIRLayoutForDOF(it->second);
175 
176  // Add basis time residuals
177  auto add_basis_time_scalar_residual = [&, this](
178  const std::string& equ_name,
179  const std::string& residual_name,
180  const double& multiplier,
181  std::vector<std::string>& op_names) {
182  const std::string closure_model_residual = residual_name + "_"
183  + equ_name;
184  const std::string full_residual = "RESIDUAL_" + closure_model_residual;
185  auto op = Teuchos::rcp(
186  new panzer::Integrator_BasisTimesScalar<EvalType, panzer::Traits>(
187  panzer::EvaluatorStyle::EVALUATES,
188  full_residual,
189  closure_model_residual,
190  *basis,
191  *ir,
192  multiplier));
193  this->template registerEvaluator<EvalType>(fm, op);
194  op_names.push_back(full_residual);
195  };
196 
197  // Add grad-basis time residuals
198  auto add_grad_basis_time_residual = [&, this](
199  const std::string& equ_name,
200  const std::string& residual_name,
201  const double& multiplier,
202  std::vector<std::string>& op_names) {
203  const std::string closure_model_residual = residual_name + "_"
204  + equ_name;
205  const std::string full_residual = "RESIDUAL_" + closure_model_residual;
206  auto op = Teuchos::rcp(
207  new panzer::Integrator_GradBasisDotVector<EvalType, panzer::Traits>(
208  panzer::EvaluatorStyle::EVALUATES,
209  full_residual,
210  closure_model_residual,
211  *basis,
212  *ir,
213  multiplier));
214  this->template registerEvaluator<EvalType>(fm, op);
215  op_names.push_back(full_residual);
216  };
217 
218  // Build total residuals for FIM equations
219  for (auto it : _equ_dof_fim_pair)
220  {
221  // Define local variables
222  const auto eq_name = it.first;
223  const auto dof_name = it.second;
224  std::vector<std::string> residual_operator_names;
225 
226  // Add time residuals
227  add_basis_time_scalar_residual(
228  eq_name, "DQDT", 1.0, residual_operator_names);
229 
230  // Add convective fluxes
231  if (_build_convective_flux)
232  {
233  add_grad_basis_time_residual(
234  eq_name, "CONVECTIVE_FLUX", -1.0, residual_operator_names);
235  }
236 
237  // Add resistive fluxes
238  if (_build_resistive_flux)
239  {
240  add_grad_basis_time_residual(
241  eq_name, "RESISTIVE_FLUX", 1.0, residual_operator_names);
242  }
243 
244  // Add source terms
245  for (const auto& [src_name, add_src] : _equ_source_term.at(eq_name))
246  {
247  if (add_src)
248  {
249  add_basis_time_scalar_residual(
250  eq_name, src_name, -1.0, residual_operator_names);
251  }
252  }
253 
254  // Build and register residuals
255  this->buildAndRegisterResidualSummationEvaluator(
256  fm, dof_name, residual_operator_names, "RESIDUAL_" + eq_name);
257  }
258 }
259 
260 //---------------------------------------------------------------------------//
261 
262 } // end namespace EquationSet
263 } // end namespace VertexCFD
264 
265 #endif // end VERTEXCFD_EQUATIONSET_FULLINDUCTIONMHD_IMPL_HPP
VertexCFD
Definition: tstMethodManufacturedSolutionBC.cpp:23