VertexCFD  0.0-dev
VertexCFD_Compute_ErrorNorms_impl.hpp
1 #ifndef VERTEXCFD_COMPUTE_ERRORNORMS_IMPL_HPP
2 #define VERTEXCFD_COMPUTE_ERRORNORMS_IMPL_HPP
3 
4 #include <Panzer_ResponseEvaluatorFactory_Functional.hpp>
5 
6 #include <Teuchos_DefaultMpiComm.hpp>
7 
8 #include <string>
9 #include <vector>
10 
11 namespace VertexCFD
12 {
13 namespace ComputeErrorNorms
14 {
15 //---------------------------------------------------------------------------//
16 template<class Scalar>
17 ErrorNorms<Scalar>::ErrorNorms(
18  const Teuchos::RCP<panzer_stk::STK_Interface>& mesh,
19  const Teuchos::RCP<const panzer::LinearObjFactory<panzer::Traits>>& lof,
20  const Teuchos::RCP<panzer::ResponseLibrary<panzer::Traits>>& response_library,
21  const std::vector<Teuchos::RCP<panzer::PhysicsBlock>>& physics_blocks,
22  const panzer::ClosureModelFactory_TemplateManager<panzer::Traits>& cm_factory,
23  const Teuchos::ParameterList& closure_params,
24  const Teuchos::ParameterList& user_params,
25  const Teuchos::RCP<panzer::EquationSetFactory>& eq_set_factory,
26  const double volume,
27  const int integration_order)
28  : _lof(lof)
29  , _response_library(response_library)
30  , _physics_blocks(physics_blocks)
31  , _cm_factory(cm_factory)
32  , _closure_params(closure_params)
33  , _user_params(user_params)
34  , _eq_set_factory(eq_set_factory)
35  , _volume(volume)
36 {
37  // Check which equation set is used by scanning the closure model list.
38  // NOTE: we may want to update ComputeErrorNorms to require that
39  // equations to be included in the error norm output be explicitly
40  // listed in the "User Data -> Compute Error Norms" input.
41  bool build_ns_error_norms = true;
42  bool build_temp_error_norms = false;
43  bool build_inductionless_error_norms = false;
44  bool build_rad_error_norms = false;
45  bool build_fim_error_norms = false;
46  bool build_lsvof_error_norms = false;
47  for (auto it = closure_params.begin(); it != closure_params.end(); ++it)
48  {
49  const std::string name = it->first;
50  if (closure_params.isSublist(name))
51  {
52  const auto p = closure_params.sublist(name);
53  // All cases but NS equations
54  if (p.isType<std::string>("Closure Factory Type"))
55  {
56  if (p.get<std::string>("Closure Factory Type")
57  == "Full Induction MHD")
58  {
59  build_fim_error_norms = true;
60  }
61  else if (p.get<std::string>("Closure Factory Type")
62  == "SolidElectricPotential")
63  {
64  build_inductionless_error_norms = true;
65  }
66  else if (p.get<std::string>("Closure Factory Type") == "LSVOF")
67  {
68  build_lsvof_error_norms = true;
69  }
70  else if (p.get<std::string>("Closure Factory Type") == "RAD")
71  {
72  build_rad_error_norms = true;
73  }
74  else if (p.get<std::string>("Closure Factory Type")
75  == "Conduction")
76  {
77  build_temp_error_norms = true;
78  }
79  }
80 
81  // NS equations ('Closure Factory Type' is defaulted to
82  // 'Navier-Stokes'). This logic will be simplified once all physics
83  // are implemented in independent equation set class.
84  if (p.isSublist("Fluid Properties"))
85  {
86  if (p.sublist("Fluid Properties")
87  .isType<bool>("Build Temperature Equation"))
88  {
89  build_temp_error_norms
90  = p.sublist("Fluid Properties")
91  .get<bool>("Build Temperature Equation");
92  }
93 
94  if (p.sublist("Fluid Properties")
95  .isType<bool>("Build Inductionless MHD Equation"))
96  {
97  build_inductionless_error_norms
98  = p.sublist("Fluid Properties")
99  .get<bool>("Build Inductionless MHD Equation");
100  }
101  }
102  }
103  }
104 
105  // If solving RAD equation, disable NS equations
106  if (build_rad_error_norms)
107  build_ns_error_norms = false;
108 
109  // If using LSVOF model, check if NS equation is disabled
110  if (build_lsvof_error_norms)
111  {
112  for (auto it = closure_params.begin(); it != closure_params.end(); ++it)
113  {
114  const std::string name = it->first;
115  if (closure_params.isSublist(name))
116  {
117  const auto p = closure_params.sublist(name);
118  if (p.isSublist("LSVOF_Properties"))
119  {
120  const Teuchos::ParameterList& lsvof_params
121  = p.sublist("LSVOF_Properties");
122 
123  if (lsvof_params.isType<bool>("Build LSVOF Navier-Stokes "
124  "Equations"))
125  {
126  build_ns_error_norms = lsvof_params.get<bool>(
127  "Build LSVOF Navier-Stokes Equations");
128  }
129  }
130  }
131  }
132  }
133 
134  // Initialize names of equation based on the equation set name
135  std::vector<std::string> eq_name;
136  _num_space_dim = mesh->getDimension();
137 
138  // If solving RAD equation, Add species
139  if (build_rad_error_norms)
140  {
141  for (auto it = closure_params.begin(); it != closure_params.end(); ++it)
142  {
143  const std::string name = it->first;
144  if (closure_params.isSublist(name))
145  {
146  const auto p = closure_params.sublist(name);
147  const auto rad_params = p.sublist("Model Parameters");
148  const int num_species
149  = rad_params.isType<int>("Number of Species")
150  ? rad_params.get<int>("Number of Species")
151  : 1;
152  for (int i = 0; i < num_species; ++i)
153  {
154  eq_name.push_back("reaction_advection_diffusion_equation_"
155  + std::to_string(i));
156  }
157  }
158  }
159  }
160 
161  // NOTE: ordering of error norms in 'eq_name' must be preserved for
162  // regression tests to pass. New error terms should be added to the end of
163  // the list after the existing terms.
164 
165  // Add Continuity first
166  if (build_ns_error_norms)
167  {
168  eq_name.push_back("continuity");
169  }
170 
171  // Temperature equation
172  if (build_temp_error_norms)
173  {
174  eq_name.push_back("energy");
175  }
176 
177  // Induction less equation
178  if (build_inductionless_error_norms)
179  {
180  eq_name.push_back("electric_potential_equation");
181  }
182 
183  // Full induction equation
184  if (build_fim_error_norms)
185  {
186  for (int i = 0; i < _num_space_dim; ++i)
187  {
188  eq_name.push_back("induction_" + std::to_string(i));
189  }
190  }
191 
192  // Momentum equation
193  if (build_ns_error_norms)
194  {
195  // Momentum equation
196  for (int i = 0; i < _num_space_dim; ++i)
197  eq_name.push_back("momentum_" + std::to_string(i));
198  }
199 
200  // LSVOF scalar equations
201  if (build_lsvof_error_norms)
202  {
203  for (auto it = closure_params.begin(); it != closure_params.end(); ++it)
204  {
205  const std::string name = it->first;
206  if (closure_params.isSublist(name))
207  {
208  const auto p = closure_params.sublist(name);
209  if (p.isSublist("LSVOF_Properties"))
210  {
211  const Teuchos::ParameterList& lsvof_params
212  = p.sublist("LSVOF_Properties");
213 
214  const std::string lsvof_model
215  = lsvof_params.get<std::string>("LSVOF Model");
216 
217  const int num_phases
218  = lsvof_params.get<int>("Number of Phases");
219 
220  if (lsvof_model == "VOF")
221  {
222  for (int phase = 1; phase < num_phases; ++phase)
223  {
224  const Teuchos::ParameterList& phase_list
225  = lsvof_params.sublist(
226  "Phase " + std::to_string(phase));
227 
228  const std::string phase_name
229  = phase_list.get<std::string>("Phase Name");
230 
231  eq_name.push_back("alpha_" + phase_name);
232  }
233  }
234  }
235  }
236  }
237  }
238 
239  // Add response library
240  std::vector<std::string> element_blocks;
241  mesh->getElementBlockNames(element_blocks);
242 
243  panzer::FunctionalResponse_Builder<int, int> response_builder;
244  response_builder.comm = Teuchos::getRawMpiComm(*(mesh->getComm()));
245  response_builder.cubatureDegree = integration_order;
246  response_builder.requiresCellIntegral = true;
247 
248  // L1 error norm
249  auto add_dof_L1 = [&](const std::string& dof) {
250  response_builder.quadPointField = "L1_Error_" + dof;
251  _response_library->addResponse(
252  dof + "_L1_error_norms", element_blocks, response_builder);
253 
254  _L1_error_norms.emplace_back(dof);
255  };
256 
257  // L2 error norm
258  auto add_dof_L2 = [&](const std::string& dof) {
259  response_builder.quadPointField = "L2_Error_" + dof;
260  _response_library->addResponse(
261  dof + "_L2_error_norms", element_blocks, response_builder);
262 
263  _L2_error_norms.emplace_back(dof);
264  };
265 
266  // Add L1 and L2 error norms
267  for (auto& element : eq_name)
268  {
269  add_dof_L1(element);
270  add_dof_L2(element);
271  }
272 
273  // Finalize construction of response library
274  _response_library->buildResponseEvaluators(
275  _physics_blocks, _cm_factory, _closure_params, _user_params);
276 }
277 
278 //---------------------------------------------------------------------------//
279 template<class Scalar>
280 void ErrorNorms<Scalar>::ComputeNorms(
281  const Teuchos::RCP<Tempus::SolutionState<Scalar>>& working_state)
282 {
283  // Get the working X
284  auto x = working_state->getX();
285 
286  // Assemble linear system
287  panzer::AssemblyEngineInArgs in_args;
288  in_args.container_ = _lof->buildLinearObjContainer();
289  in_args.ghostedContainer_ = _lof->buildGhostedLinearObjContainer();
290  in_args.evaluate_transient_terms = false;
291  in_args.time = working_state->getTime();
292 
293  _lof->initializeGhostedContainer(panzer::LinearObjContainer::X,
294  *(in_args.ghostedContainer_));
295 
296  auto thyra_container
297  = Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<double>>(
298  in_args.container_);
299  thyra_container->set_x_th(
300  Teuchos::rcp_const_cast<Thyra::VectorBase<double>>(x));
301 
302  // Set up resp, resp_func, resp_vec for L1_error_norms
303  for (auto& dof : _L1_error_norms)
304  {
305  auto resp = _response_library->getResponse<panzer::Traits::Residual>(
306  dof.name + "_L1_error_norms");
307  auto resp_func = Teuchos::rcp_dynamic_cast<
308  panzer::Response_Functional<panzer::Traits::Residual>>(resp);
309  auto resp_vec = Thyra::createMember(resp_func->getVectorSpace());
310  resp_func->setVector(resp_vec);
311  }
312 
313  // Set up resp, resp_func, resp_vec for L2_error_norms
314  for (auto& dof : _L2_error_norms)
315  {
316  auto resp = _response_library->getResponse<panzer::Traits::Residual>(
317  dof.name + "_L2_error_norms");
318  auto resp_func = Teuchos::rcp_dynamic_cast<
319  panzer::Response_Functional<panzer::Traits::Residual>>(resp);
320  auto resp_vec = Thyra::createMember(resp_func->getVectorSpace());
321  resp_func->setVector(resp_vec);
322  }
323 
324  _response_library->addResponsesToInArgs<panzer::Traits::Residual>(in_args);
325  _response_library->evaluate<panzer::Traits::Residual>(in_args);
326 
327  // Compute L1 error norm
328  for (auto& dof : _L1_error_norms)
329  {
330  auto resp = _response_library->getResponse<panzer::Traits::Residual>(
331  dof.name + "_L1_error_norms");
332  auto resp_func = Teuchos::rcp_dynamic_cast<
333  panzer::Response_Functional<panzer::Traits::Residual>>(resp);
334  dof.error_norm = (resp_func->value) / _volume;
335  }
336 
337  // Compute L2 error norm
338  for (auto& dof : _L2_error_norms)
339  {
340  auto resp = _response_library->getResponse<panzer::Traits::Residual>(
341  dof.name + "_L2_error_norms");
342  auto resp_func = Teuchos::rcp_dynamic_cast<
343  panzer::Response_Functional<panzer::Traits::Residual>>(resp);
344  dof.error_norm = std::sqrt(resp_func->value) / _volume;
345  }
346 }
347 
348 //---------------------------------------------------------------------------//
349 
350 } // end namespace ComputeErrorNorms
351 } // end namespace VertexCFD
352 
353 #endif // end VERTEXCFD_COMPUTE_ERRORNORMS_IMPL_HPP
VertexCFD
Definition: tstMethodManufacturedSolutionBC.cpp:23