VertexCFD  0.0-dev
VertexCFD_BCStrategy_BoundaryFluxBase_impl.hpp
1 #ifndef VERTEXCFD_BOUNDARYCONDITION_BOUNDARYFLUXBASE_IMPL_HPP
2 #define VERTEXCFD_BOUNDARYCONDITION_BOUNDARYFLUXBASE_IMPL_HPP
3 
4 #include "VertexCFD_BoundaryState_ViscousGradient.hpp"
5 #include "VertexCFD_BoundaryState_ViscousPenaltyParameter.hpp"
6 #include "VertexCFD_Integrator_BoundaryGradBasisDotVector.hpp"
7 
8 #include <Panzer_DOF.hpp>
9 #include <Panzer_DOFGradient.hpp>
10 #include <Panzer_DotProduct.hpp>
11 #include <Panzer_Integrator_BasisTimesScalar.hpp>
12 #include <Panzer_Normals.hpp>
13 #include <Panzer_Sum.hpp>
14 
15 #include <Phalanx_DataLayout.hpp>
16 #include <Phalanx_DataLayout_MDALayout.hpp>
17 #include <Phalanx_MDField.hpp>
18 
19 #include <map>
20 #include <string>
21 #include <vector>
22 
23 namespace VertexCFD
24 {
25 namespace BoundaryCondition
26 {
27 //---------------------------------------------------------------------------//
28 template<class EvalType, int NumSpaceDim>
29 BoundaryFluxBase<EvalType, NumSpaceDim>::BoundaryFluxBase(
30  const panzer::BC& bc, const Teuchos::RCP<panzer::GlobalData>& global_data)
31  : panzer::BCStrategy<EvalType>(bc)
32  , panzer::GlobalDataAcceptorDefaultImpl(global_data)
33 {
34  // Initialize `bnd_prefix` to use with second-order flux
35  bnd_prefix.insert({"BOUNDARY_", "BOUNDARY_"});
36  bnd_prefix.insert({"PENALTY_BOUNDARY_", "PENALTY_"});
37  bnd_prefix.insert({"SYMMETRY_BOUNDARY_", "SYMMETRY_"});
38 }
39 
40 //---------------------------------------------------------------------------//
41 // Initialize class members
42 template<class EvalType, int NumSpaceDim>
44  const panzer::PhysicsBlock& side_pb,
45  std::unordered_map<std::string, std::string>& )
46 {
47  // Get the maximum of integration rule order
48  const auto& irules = side_pb.getIntegrationRules();
49  int integration_order = 0;
50  for (const auto& pair : irules)
51  {
52  integration_order = std::max(integration_order, pair.second->order());
53  }
54 
55  // Assign an integration rule for side normal evaluator
56  _ir = Teuchos::rcp(
57  new panzer::IntegrationRule(integration_order, side_pb.cellData()));
58 
59  // Create a map between dof and integration rule
60  const auto& dof_basis_pair = side_pb.getProvidedDOFs();
61  for (const auto& dof_basis : dof_basis_pair)
62  {
63  _dof_basis_pair.insert({dof_basis.first, dof_basis.second});
64  const Teuchos::RCP<panzer::IntegrationRule> ir = Teuchos::rcp(
65  new panzer::IntegrationRule(integration_order, side_pb.cellData()));
66  }
67 }
68 
69 //---------------------------------------------------------------------------//
70 // Get model id class members: this function retrieves the model id from the
71 // boundary conditions (multiple equation sets per block) or physics blocks
72 // (one equation set per block)
73 template<class EvalType, int NumSpaceDim>
75  const Teuchos::ParameterList& bc_params,
76  const panzer::PhysicsBlock& side_pb,
77  std::string& model_id,
78  Teuchos::ParameterList& side_pb_list) const
79 {
80  if (bc_params.isType<std::string>("Model ID"))
81  {
82  // TODO: This logic is currently not used and will have to be updated
83  // when using composite boundaries.
84  model_id = bc_params.get<std::string>("Model ID");
85  for (auto itr = side_pb.getParameterList()->begin();
86  itr != side_pb.getParameterList()->end();
87  ++itr)
88  {
89  const auto sublist
90  = Teuchos::getValue<Teuchos::ParameterList>(itr->second);
91  if (sublist.get<std::string>("Model ID") == model_id)
92  {
93  side_pb_list = sublist;
94  }
95  }
96  }
97  else if (side_pb.getParameterList()->numParams() != 1)
98  {
99  const std::string msg
100  = "\n\nERROR: Multiple equation sets are being solved on a single "
101  "block but `Model ID` is not being specified in the "
102  "corresponding boundary condition lists.\n\n";
103  throw std::runtime_error(msg);
104  }
105  else
106  {
107  model_id
108  = side_pb.getParameterList()->sublist("child0").get<std::string>(
109  "Model ID");
110  side_pb_list = side_pb.getParameterList()->sublist("child0");
111  }
112 }
113 
114 //---------------------------------------------------------------------------//
115 // Get integration basis for a variable with name `dof_name`.
116 template<class EvalType, int NumSpaceDim>
118  const panzer::PhysicsBlock& , const std::string& dof_name) const
119 {
120  const Teuchos::RCP<panzer::PureBasis> basis = _dof_basis_pair.at(dof_name);
121 
122  return panzer::basisIRLayout(basis, *_ir);
123 }
124 
125 //---------------------------------------------------------------------------//
126 // Register degree of freedom and gradients for a variable with name `dof_name`
127 template<class EvalType, int NumSpaceDim>
129  PHX::FieldManager<panzer::Traits>& fm,
130  const panzer::PhysicsBlock& side_pb,
131  const std::string& dof_name) const
132 {
133  // Degree of freedom (DOF)
134  const auto basis_layout = this->getBasisIRLayout(side_pb, dof_name);
135  Teuchos::ParameterList dof_params;
136  dof_params.set<std::string>("Name", dof_name);
137  dof_params.set<Teuchos::RCP<panzer::BasisIRLayout>>("Basis", basis_layout);
138  dof_params.set<Teuchos::RCP<panzer::IntegrationRule>>("IR", _ir);
139  const auto dof_op
140  = Teuchos::rcp(new panzer::DOF<EvalType, panzer::Traits>(dof_params));
141  this->template registerEvaluator<EvalType>(fm, dof_op);
142 
143  // Gradient
144  dof_params.set<std::string>("Gradient Name", "GRAD_" + dof_name);
145  const auto gd_op = Teuchos::rcp(
146  new panzer::DOFGradient<EvalType, panzer::Traits>(dof_params));
147  this->template registerEvaluator<EvalType>(fm, gd_op);
148 }
149 
150 //---------------------------------------------------------------------------//
151 // Register side nornal evaluator
152 template<class EvalType, int NumSpaceDim>
153 void BoundaryFluxBase<EvalType, NumSpaceDim>::registerSideNormals(
154  PHX::FieldManager<panzer::Traits>& fm,
155  const panzer::PhysicsBlock& side_pb) const
156 {
157  std::stringstream normal_params_name;
158  normal_params_name << "Side Normal:" << side_pb.cellData().side();
159  Teuchos::ParameterList normal_params(normal_params_name.str());
160  normal_params.set<std::string>("Name", "Side Normal");
161  normal_params.set<int>("Side ID", side_pb.cellData().side());
162  normal_params.set<Teuchos::RCP<panzer::IntegrationRule>>("IR", _ir);
163  normal_params.set<bool>("Normalize", true);
164  const auto normal_op = Teuchos::rcp(
165  new panzer::Normals<EvalType, panzer::Traits>(normal_params));
166  this->template registerEvaluator<EvalType>(fm, normal_op);
167 }
168 
169 //---------------------------------------------------------------------------//
170 template<class EvalType, int NumSpaceDim>
171 void BoundaryFluxBase<EvalType, NumSpaceDim>::registerConvectionTypeFluxOperator(
172  std::pair<const std::string, std::string> dof_eq_pair,
173  std::unordered_map<std::string, std::vector<std::string>>& eq_res_map,
174  const std::string& closure_name,
175  PHX::FieldManager<panzer::Traits>& fm,
176  const panzer::PhysicsBlock& side_pb,
177  const double& multiplier) const
178 {
179  // Local variables
180  const std::string eq_name = dof_eq_pair.first;
181  const std::string dof_name = dof_eq_pair.second;
182  const std::string normal_dot_name = "Normal Dot Flux " + eq_name;
183 
184  // Register dot product evaluator
185  const std::string flux_name = "BOUNDARY_" + closure_name + "_FLUX_"
186  + eq_name;
187  const auto normal_dot_flux_op
188  = panzer::buildEvaluator_DotProduct<EvalType, panzer::Traits>(
189  normal_dot_name, *_ir, "Side Normal", flux_name);
190  this->template registerEvaluator<EvalType>(fm, normal_dot_flux_op);
191 
192  // Convective flux integral.
193  const auto basis_layout = this->getBasisIRLayout(side_pb, dof_name);
194  const std::string residual_name = closure_name + "_BOUNDARY_RESIDUAL_"
195  + eq_name;
196  const auto convective_flux_op = Teuchos::rcp(
197  new panzer::Integrator_BasisTimesScalar<EvalType, panzer::Traits>(
198  panzer::EvaluatorStyle::EVALUATES,
199  residual_name,
200  normal_dot_name,
201  *basis_layout,
202  *_ir,
203  multiplier));
204  this->template registerEvaluator<EvalType>(fm, convective_flux_op);
205 
206  // Add residual name to `eq_res_map`
207  eq_res_map[eq_name].push_back(residual_name);
208 }
209 
210 //---------------------------------------------------------------------------//
211 // Register closure models used for the symmetric penalty method
212 template<class EvalType, int NumSpaceDim>
213 void BoundaryFluxBase<EvalType, NumSpaceDim>::registerPenaltyAndViscousGradientOperator(
214  std::pair<const std::string, std::string> dof_eq_pair,
215  PHX::FieldManager<panzer::Traits>& fm,
216  const panzer::PhysicsBlock& side_pb,
217  const Teuchos::ParameterList& bc_params) const
218 {
219  // Local variables
220  const std::string eq_name = dof_eq_pair.first;
221  const std::string dof_name = dof_eq_pair.second;
222  const auto basis_layout = this->getBasisIRLayout(side_pb, dof_name);
223 
224  // Check for user-specified penalty parameter
225  double penalty = 10.0;
226 
227  // For temperature, default penalty is set to 1000.0
228  if (dof_name == "temperature")
229  penalty = 1000.0;
230 
231  if (bc_params.isSublist("Penalty Parameters"))
232  {
233  const auto penalty_list = bc_params.sublist("Penalty Parameters");
234  if (penalty_list.isType<double>(dof_name))
235  {
236  penalty = penalty_list.get<double>(dof_name);
237  }
238  }
239 
240  // Create viscous penalty parameter evaluator.
241  const auto viscous_penalty_op
242  = Teuchos::rcp(new ViscousPenaltyParameter<EvalType, panzer::Traits>(
243  *_ir, *(basis_layout->getBasis()), dof_name, penalty));
244  this->template registerEvaluator<EvalType>(fm, viscous_penalty_op);
245 
246  // Create boundary gradients.
247  const auto viscous_gradient_op = Teuchos::rcp(
248  new ViscousGradient<EvalType, panzer::Traits>(*_ir, dof_name));
249  this->template registerEvaluator<EvalType>(fm, viscous_gradient_op);
250 }
251 
252 //---------------------------------------------------------------------------//
253 // Register Laplace-type operators
254 template<class EvalType, int NumSpaceDim>
255 void BoundaryFluxBase<EvalType, NumSpaceDim>::registerViscousTypeFluxOperator(
256  std::pair<const std::string, std::string> dof_eq_pair,
257  std::unordered_map<std::string, std::vector<std::string>>& eq_res_map,
258  const std::string closure_name,
259  PHX::FieldManager<panzer::Traits>& fm,
260  const panzer::PhysicsBlock& side_pb,
261  const double& multiplier) const
262 {
263  const std::string eq_name = dof_eq_pair.first;
264  const std::string dof_name = dof_eq_pair.second;
265  const auto basis_layout = this->getBasisIRLayout(side_pb, dof_name);
266 
267  // Symmetric interior penalty method residual 1.
268  // FIXME: The dot product evaluator is not on the device in
269  // Trilinos 13.0.1
270  const std::string normal_dot_viscous_name = "Normal Dot " + closure_name
271  + " Flux " + eq_name;
272  const std::string flux_name = "BOUNDARY_" + closure_name + "_FLUX_"
273  + eq_name;
274  auto normal_dot_viscous_flux_op
275  = panzer::buildEvaluator_DotProduct<EvalType, panzer::Traits>(
276  normal_dot_viscous_name, *_ir, "Side Normal", flux_name);
277  this->template registerEvaluator<EvalType>(fm, normal_dot_viscous_flux_op);
278 
279  const std::string bnd_resid = closure_name + "_BOUNDARY_RESIDUAL_"
280  + eq_name;
281  auto bnd_op = Teuchos::rcp(
282  new panzer::Integrator_BasisTimesScalar<EvalType, panzer::Traits>(
283  panzer::EvaluatorStyle::EVALUATES,
284  bnd_resid,
285  normal_dot_viscous_name,
286  *basis_layout,
287  *_ir,
288  -multiplier));
289  this->template registerEvaluator<EvalType>(fm, bnd_op);
290  eq_res_map[eq_name].push_back(bnd_resid);
291 
292  // Symmetric interior penalty method residual 2.
293  const std::string penalty_bnd_resid = "PENALTY_BOUNDARY_RESIDUAL_"
294  + eq_name;
295  auto bnd_penalty_op = Teuchos::rcp(
296  new Integrator::BoundaryGradBasisDotVector<EvalType, panzer::Traits>(
297  panzer::EvaluatorStyle::EVALUATES,
298  penalty_bnd_resid,
299  "PENALTY_BOUNDARY_" + closure_name + "_FLUX_" + eq_name,
300  *basis_layout,
301  *_ir,
302  -multiplier));
303  this->template registerEvaluator<EvalType>(fm, bnd_penalty_op);
304  eq_res_map[eq_name].push_back(penalty_bnd_resid);
305 
306  // Symmetric interior penalty method residual 3.
307  // FIXME: The dot product evaluator is not on the device in
308  // Trilinos 13.0.1
309  const std::string normal_dot_scaled_penalty_viscous_name
310  = "Normal Dot Scaled Penalty " + closure_name + " Flux " + eq_name;
311  const std::string scaled_penalty_flux_name
312  = "SYMMETRY_BOUNDARY_" + closure_name + "_FLUX_" + eq_name;
313  auto normal_dot_scaled_penalty_viscous_flux_op
314  = panzer::buildEvaluator_DotProduct<EvalType, panzer::Traits>(
315  normal_dot_scaled_penalty_viscous_name,
316  *_ir,
317  "Side Normal",
318  scaled_penalty_flux_name);
319  this->template registerEvaluator<EvalType>(
320  fm, normal_dot_scaled_penalty_viscous_flux_op);
321 
322  const std::string scaled_penalty_bnd_resid = "SYMMETRY_BOUNDARY_RESIDUAL_"
323  + eq_name;
324  auto scaled_bnd_penalty_op = Teuchos::rcp(
325  new panzer::Integrator_BasisTimesScalar<EvalType, panzer::Traits>(
326  panzer::EvaluatorStyle::EVALUATES,
327  scaled_penalty_bnd_resid,
328  normal_dot_scaled_penalty_viscous_name,
329  *basis_layout,
330  *_ir,
331  multiplier));
332  this->template registerEvaluator<EvalType>(fm, scaled_bnd_penalty_op);
333  eq_res_map[eq_name].push_back(scaled_penalty_bnd_resid);
334 }
335 
336 //---------------------------------------------------------------------------//
337 // Register residuals collected in `eq_res_map` for each equation.
338 template<class EvalType, int NumSpaceDim>
339 void BoundaryFluxBase<EvalType, NumSpaceDim>::registerResidual(
340  std::pair<const std::string, std::string> dof_eq_pair,
341  std::unordered_map<std::string, std::vector<std::string>>& eq_res_map,
342  PHX::FieldManager<panzer::Traits>& fm,
343  const panzer::PhysicsBlock& side_pb) const
344 {
345  // Local variables
346  const std::string eq_name = dof_eq_pair.first;
347  const std::string dof_name = dof_eq_pair.second;
348  const auto basis_layout = this->getBasisIRLayout(side_pb, dof_name);
349 
350  // Initialize residual vector
351  auto residuals = Teuchos::rcp(new std::vector<std::string>);
352  for (auto& res : eq_res_map[eq_name])
353  residuals->push_back(res);
354 
355  // Register residuals
356  Teuchos::ParameterList sum_params;
357  sum_params.set("Sum Name", "BOUNDARY_RESIDUAL_" + eq_name);
358  sum_params.set("Values Names", residuals);
359  sum_params.set("Data Layout", basis_layout->getBasis()->functional);
360  auto sum_op = Teuchos::rcp(
361  new panzer::SumStatic<EvalType, panzer::Traits, panzer::Cell, panzer::BASIS>(
362  sum_params));
363  this->template registerEvaluator<EvalType>(fm, sum_op);
364 }
365 
366 //---------------------------------------------------------------------------//
367 // Register and scatter residual for each equation
368 template<class EvalType, int NumSpaceDim>
370  std::pair<const std::string, std::string> dof_eq_pair,
371  PHX::FieldManager<panzer::Traits>& fm,
372  const panzer::PhysicsBlock& ,
373  const panzer::LinearObjFactory<panzer::Traits>& lof) const
374 {
375  const std::string& eq_name = dof_eq_pair.first;
376  const std::string& dof_name = dof_eq_pair.second;
377  const Teuchos::RCP<const panzer::PureBasis> basis
378  = _dof_basis_pair.at(dof_name);
379 
380  const std::string residual_name = "BOUNDARY_RESIDUAL_" + eq_name;
381  Teuchos::ParameterList p("Scatter: " + residual_name + " to " + eq_name);
382 
383  const std::string scatter_field_name
384  = "Dummy Scatter: " + this->m_bc.identifier() + residual_name;
385  p.set("Scatter Name", scatter_field_name);
386  p.set("Basis", basis);
387 
388  auto residual_names = Teuchos::rcp(new std::vector<std::string>);
389  residual_names->push_back(residual_name);
390  p.set("Dependent Names", residual_names);
391 
392  auto names_map = Teuchos::rcp(new std::map<std::string, std::string>);
393  names_map->insert(
394  std::pair<std::string, std::string>(residual_name, dof_name));
395  p.set("Dependent Map", names_map);
396 
397  auto scatter_op = lof.buildScatter<EvalType>(p);
398 
399  this->template registerEvaluator<EvalType>(fm, scatter_op);
400 
401  // Require variables
402  auto dummy_layout = Teuchos::rcp(new PHX::MDALayout<panzer::Dummy>(0));
403  const PHX::Tag<typename EvalType::ScalarT> tag(scatter_field_name,
404  dummy_layout);
405  fm.template requireField<EvalType>(tag);
406 }
407 //---------------------------------------------------------------------------//
408 
409 } // end namespace BoundaryCondition
410 } // end namespace VertexCFD
411 
412 #endif // end VERTEXCFD_BOUNDARYCONDITION_BOUNDARYFLUXBASE_IMPL_HPP
VertexCFD::BoundaryCondition::BoundaryFluxBase::initialize
void initialize(const panzer::PhysicsBlock &side_pb, std::unordered_map< std::string, std::string > &dof_eq_map)
Definition: VertexCFD_BCStrategy_BoundaryFluxBase_impl.hpp:43
VertexCFD::BoundaryCondition::BoundaryFluxBase
Definition: VertexCFD_BCStrategy_BoundaryFluxBase.hpp:25
VertexCFD
Definition: tstMethodManufacturedSolutionBC.cpp:23
VertexCFD::BoundaryCondition::BoundaryFluxBase::registerScatterOperator
void registerScatterOperator(std::pair< const std::string, std::string > dof_eq_pair, PHX::FieldManager< panzer::Traits > &fm, const panzer::PhysicsBlock &side_pb, const panzer::LinearObjFactory< panzer::Traits > &lof) const
Definition: VertexCFD_BCStrategy_BoundaryFluxBase_impl.hpp:369
VertexCFD::BoundaryCondition::BoundaryFluxBase::getBasisIRLayout
auto getBasisIRLayout(const panzer::PhysicsBlock &side_pb, const std::string &dof_name) const
Definition: VertexCFD_BCStrategy_BoundaryFluxBase_impl.hpp:117