https://mooseframework.inl.gov
SolutionUserObjectBase.C
Go to the documentation of this file.
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 #include "SolutionUserObjectBase.h"
11 
12 // MOOSE includes
13 #include "ConsoleUtils.h"
14 #include "MooseError.h"
15 #include "MooseMesh.h"
16 #include "MooseUtils.h"
17 #include "MooseVariableFE.h"
18 #include "RotationMatrix.h"
19 #include "Function.h"
20 
21 // libMesh includes
22 #include "libmesh/equation_systems.h"
23 #include "libmesh/mesh_function.h"
24 #include "libmesh/numeric_vector.h"
25 #include "libmesh/nonlinear_implicit_system.h"
26 #include "libmesh/transient_system.h"
27 #include "libmesh/parallel_mesh.h"
28 #include "libmesh/serial_mesh.h"
29 #include "libmesh/exodusII_io.h"
30 #include "libmesh/exodusII_io_helper.h"
31 #include "libmesh/nemesis_io.h"
32 #include "libmesh/nemesis_io_helper.h"
33 #include "libmesh/enum_xdr_mode.h"
34 #include "libmesh/string_to_enum.h"
35 
38 {
39  // Get the input parameters from the parent class
41 
42  // Add required parameters
43  params.addRequiredParam<MeshFileName>(
44  "mesh", "The name of the mesh file (must be xda/xdr, exodusII or nemesis file).");
45  params.addParam<std::vector<std::string>>(
46  "system_variables",
47  std::vector<std::string>(),
48  "The name of the nodal and elemental variables from the file you want to use for values");
49  params.addParam<bool>(
50  "force_replicated_source_mesh",
51  false,
52  "Whether to force the serialization of the source mesh. This can be useful for discontinuous "
53  "variables or if the partitioning of the source mesh and the current mesh are different");
54 
55  // When using XDA/XDR files the following must be defined
56  params.addParam<FileName>(
57  "es",
58  "<not supplied>",
59  "The name of the file holding the equation system info in xda/xdr format (xda/xdr only).");
60  params.addParam<std::string>(
61  "system",
62  "nl0",
63  "The name of the system to pull values out of (xda/xdr only). The default name for the "
64  "nonlinear system is 'nl0', auxiliary system is 'aux0'");
65 
66  // When using ExodusII a specific time is extracted
67  params.addParam<std::string>("timestep",
68  "Index of the single timestep used or \"LATEST\" for "
69  "the last timestep (exodusII only). If not supplied, "
70  "time interpolation will occur.");
71 
72  // Choose the interpolation order for incoming nodal variables
73  params.addParam<MooseEnum>("nodal_variable_order",
74  MooseEnum("FIRST SECOND", "FIRST"),
75  "Specifies the order of the nodal solution data.");
76 
77  // Add ability to perform coordinate transformation: scale, factor
78  params.addParam<std::vector<Real>>(
79  "scale", std::vector<Real>(LIBMESH_DIM, 1), "Scale factor for points in the simulation");
80  params.addParam<std::vector<Real>>("scale_multiplier",
81  std::vector<Real>(LIBMESH_DIM, 1),
82  "Scale multiplying factor for points in the simulation");
83  params.addParam<std::vector<Real>>("translation",
84  std::vector<Real>(LIBMESH_DIM, 0),
85  "Translation factors for x,y,z coordinates of the simulation");
86  params.addParam<RealVectorValue>("rotation0_vector",
87  RealVectorValue(0, 0, 1),
88  "Vector about which to rotate points of the simulation.");
89  params.addParam<Real>(
90  "rotation0_angle",
91  0.0,
92  "Anticlockwise rotation angle (in degrees) to use for rotation about rotation0_vector.");
93  params.addParam<RealVectorValue>("rotation1_vector",
94  RealVectorValue(0, 0, 1),
95  "Vector about which to rotate points of the simulation.");
96  params.addParam<Real>(
97  "rotation1_angle",
98  0.0,
99  "Anticlockwise rotation angle (in degrees) to use for rotation about rotation1_vector.");
100 
101  // following lines build the default_transformation_order
102  MultiMooseEnum default_transformation_order(
103  "rotation0 translation scale rotation1 scale_multiplier", "translation scale");
104  params.addParam<MultiMooseEnum>(
105  "transformation_order",
106  default_transformation_order,
107  "The order to perform the operations in. Define R0 to be the rotation matrix encoded by "
108  "rotation0_vector and rotation0_angle. Similarly for R1. Denote the scale by s, the "
109  "scale_multiplier by m, and the translation by t. Then, given a point x in the simulation, "
110  "if transformation_order = 'rotation0 scale_multiplier translation scale rotation1' then "
111  "form p = R1*(R0*x*m - t)/s. Then the values provided by the SolutionUserObjectBase at "
112  "point x "
113  "in the simulation are the variable values at point p in the mesh.");
114  params.addParamNamesToGroup("scale scale_multiplier translation rotation0_vector rotation0_angle "
115  "rotation1_angle transformation_order",
116  "Coordinate system transformation");
117  params.addClassDescription("Reads a variable from a mesh in one simulation to another");
118  return params;
119 }
120 
121 // Static mutex definition
123 
125  : GeneralUserObject(parameters),
126  _file_type(MooseEnum("xda=0 exodusII=1 xdr=2 nemesis=3")),
127  _mesh_file(getParam<MeshFileName>("mesh")),
128  _es_file(getParam<FileName>("es")),
129  _system_name(getParam<std::string>("system")),
130  _system_variables(getParam<std::vector<std::string>>("system_variables")),
131  _exodus_time_index(-1),
132  _interpolate_times(false),
133  _system(nullptr),
134  _system2(nullptr),
135  _interpolation_time(0.0),
136  _interpolation_factor(0.0),
137  _exodus_times(nullptr),
138  _exodus_index1(0),
139  _exodus_index2(0),
140  _nodal_variable_order(getParam<MooseEnum>("nodal_variable_order")),
141  _scale(getParam<std::vector<Real>>("scale")),
142  _scale_multiplier(getParam<std::vector<Real>>("scale_multiplier")),
143  _translation(getParam<std::vector<Real>>("translation")),
144  _rotation0_vector(getParam<RealVectorValue>("rotation0_vector")),
145  _rotation0_angle(getParam<Real>("rotation0_angle")),
146  _r0(RealTensorValue()),
147  _rotation1_vector(getParam<RealVectorValue>("rotation1_vector")),
148  _rotation1_angle(getParam<Real>("rotation1_angle")),
149  _r1(RealTensorValue()),
150  _transformation_order(getParam<MultiMooseEnum>("transformation_order")),
151  _force_replicated_source(getParam<bool>("force_replicated_source_mesh")),
152  _initialized(false)
153 {
154  // form rotation matrices with the specified angles
155  Real halfPi = libMesh::pi / 2.0;
156  Real a;
157  Real b;
158 
159  a = std::cos(halfPi * -_rotation0_angle / 90.0);
160  b = std::sin(halfPi * -_rotation0_angle / 90.0);
161  // the following is an anticlockwise rotation about z
162  RealTensorValue rot0_z(a, -b, 0, b, a, 0, 0, 0, 1);
163  // form the rotation matrix that will take rotation0_vector to the z axis
165  // _r0 is then: rotate points so vec0 lies along z; then rotate about angle0; then rotate points
166  // back
167  _r0 = vec0_to_z.transpose() * (rot0_z * vec0_to_z);
168 
169  a = std::cos(halfPi * -_rotation1_angle / 90.0);
170  b = std::sin(halfPi * -_rotation1_angle / 90.0);
171  // the following is an anticlockwise rotation about z
172  RealTensorValue rot1_z(a, -b, 0, b, a, 0, 0, 0, 1);
173  // form the rotation matrix that will take rotation1_vector to the z axis
175  // _r1 is then: rotate points so vec1 lies along z; then rotate about angle1; then rotate points
176  // back
177  _r1 = vec1_to_z.transpose() * (rot1_z * vec1_to_z);
178 
179  if (isParamValid("timestep") && getParam<std::string>("timestep") == "-1")
180  mooseError("A \"timestep\" of -1 is no longer supported for interpolation. Instead simply "
181  "remove this parameter altogether for interpolation");
182 
183  // check for possible inconsistencies between mesh and input data
185  mooseInfo(
186  "The mesh has second-order elements, be sure to set 'nodal_variable_order' if needed.");
187 }
188 
189 void
191 {
192  if (!isParamSetByUser("es"))
193  paramError("es", "Equation system file (.xda or .xdr) should have been specified");
194 
195  // Check that the required files exist
198 
199  // Read the libmesh::mesh from the xda file
200  _mesh->read(_mesh_file);
201 
202  // Create the libmesh::EquationSystems
203  _es = std::make_unique<EquationSystems>(*_mesh);
204 
205  // Use new read syntax (binary)
206  if (_file_type == "xdr")
207  _es->read(_es_file,
209  EquationSystems::READ_HEADER | EquationSystems::READ_DATA |
210  EquationSystems::READ_ADDITIONAL_DATA);
211 
212  // Use new read syntax
213  else if (_file_type == "xda")
214  _es->read(_es_file,
216  EquationSystems::READ_HEADER | EquationSystems::READ_DATA |
217  EquationSystems::READ_ADDITIONAL_DATA);
218 
219  // This should never occur, just in case produce an error
220  else
221  mooseError("Failed to determine proper read method for XDA/XDR equation system file: ",
222  _es_file);
223 
224  // Update and store the EquationSystems name locally
225  _es->update();
226  _system = &_es->get_system(_system_name);
227 }
228 
229 void
231 {
232  // Define a default system name
233  if (_system_name == "")
234  _system_name = "SolutionUserObjectSystem";
235 
236  // Read the Exodus or Nemesis file
237  if (_file_type == "exodusII")
238  {
239  _exodusII_io = std::make_unique<libMesh::ExodusII_IO>(*_mesh);
240  _exodusII_io->read(_mesh_file);
241  _exodus_times = &_exodusII_io->get_time_steps();
242  }
243  else
244  {
245  _nemesis_io = std::make_unique<libMesh::Nemesis_IO>(*_mesh);
246  _nemesis_io->read(_mesh_file);
247  _exodus_times = &_nemesis_io->get_time_steps();
248  }
249  // Same routine for Nemesis
251 
252  if (isParamValid("timestep"))
253  {
254  std::string s_timestep = getParam<std::string>("timestep");
255  int n_steps = (_file_type == "exodusII") ? _exodusII_io->get_num_time_steps()
256  : _nemesis_io->get_num_time_steps();
257  if (s_timestep == "LATEST")
258  _exodus_time_index = n_steps;
259  else
260  {
261  std::istringstream ss(s_timestep);
262  if (!((ss >> _exodus_time_index) && ss.eof()) || _exodus_time_index > n_steps)
263  mooseError("Invalid value passed as \"timestep\". Expected \"LATEST\" or a valid integer "
264  "less than ",
265  n_steps,
266  ", received ",
267  s_timestep);
268  }
269  }
270  else
271  // Interpolate between times rather than using values from a set timestep
272  _interpolate_times = true;
273 
274  // Check that the number of time steps is valid
275  int num_exo_times = _exodus_times->size();
276  if (num_exo_times == 0)
277  mooseError("In SolutionUserObjectBase, exodus file contains no timesteps.");
278 
279  // Account for parallel mesh
280  if (_fe_problem.mesh().isDistributedMesh() && (_file_type != "exodusII") &&
282  {
283  _mesh->allow_renumbering(true);
284  _mesh->prepare_for_use();
285  }
286  else
287  {
288  _mesh->allow_renumbering(false);
289  _mesh->prepare_for_use();
290  }
291 
292  // Create EquationSystems object for solution
293  _es = std::make_unique<EquationSystems>(*_mesh);
295  _system = &_es->get_system(_system_name);
296 
297  // Get the variable name lists as set; these need to be sets to perform set_intersection
298  const std::vector<std::string> & all_nodal((_file_type == "exodusII")
299  ? _exodusII_io->get_nodal_var_names()
300  : _nemesis_io->get_nodal_var_names());
301  const std::vector<std::string> & all_elemental((_file_type == "exodusII")
302  ? _exodusII_io->get_elem_var_names()
303  : _nemesis_io->get_elem_var_names());
304  const std::vector<std::string> & all_scalar((_file_type == "exodusII")
305  ? _exodusII_io->get_global_var_names()
306  : _nemesis_io->get_global_var_names());
307 
308  // Build nodal/elemental variable lists, limit to variables listed in 'system_variables', if
309  // provided
310  // This function could be called more than once, so clear the member variables so we don't keep
311  // adding to the vectors
312  _nodal_variables.clear();
313  _elemental_variables.clear();
314  _scalar_variables.clear();
315  if (!_system_variables.empty())
316  {
317  for (const auto & var_name : _system_variables)
318  {
319  if (std::find(all_nodal.begin(), all_nodal.end(), var_name) != all_nodal.end())
320  _nodal_variables.push_back(var_name);
321  else if (std::find(all_elemental.begin(), all_elemental.end(), var_name) !=
322  all_elemental.end())
323  _elemental_variables.push_back(var_name);
324  else if (std::find(all_scalar.begin(), all_scalar.end(), var_name) != all_scalar.end())
325  // We checked other variables types first, so if a postprocessor has the same name as a
326  // field variable, it won't get loaded as a scalar variable
327  _scalar_variables.push_back(var_name);
328  else
329  paramError("system_variables", "Variable '" + var_name + "' was not found in Exodus file");
330  }
331  }
332  else
333  {
334  _nodal_variables = all_nodal;
335  _elemental_variables = all_elemental;
336 
337  for (auto var_name : all_scalar)
338  // Check if the scalar matches any field variables, and ignore the var if it does. This means
339  // its a Postprocessor.
340  if (std::find(begin(_nodal_variables), end(_nodal_variables), var_name) ==
341  _nodal_variables.end() &&
342  std::find(begin(_elemental_variables), end(_elemental_variables), var_name) ==
343  _elemental_variables.end())
344  _scalar_variables.push_back(var_name);
345  }
346 
347  // Add the variables to the system
348  for (const auto & var_name : _nodal_variables)
349  _system->add_variable(var_name, Utility::string_to_enum<Order>(_nodal_variable_order));
350 
351  for (const auto & var_name : _elemental_variables)
352  _system->add_variable(var_name, CONSTANT, MONOMIAL);
353 
354  for (const auto & var_name : _scalar_variables)
355  _system->add_variable(var_name, FIRST, SCALAR);
356 
357  // Helper for copying from the ExodusII/Nemesis file
358  const auto copy_solutions = [this](auto & io, libMesh::System & system, unsigned int index)
359  {
360  for (const auto & var_name : _nodal_variables)
361  io.copy_nodal_solution(system, var_name, var_name, index);
362 
363  for (const auto & var_name : _elemental_variables)
364  io.copy_elemental_solution(system, var_name, var_name, index);
365 
366  if (_scalar_variables.size() > 0)
367  io.copy_scalar_solution(system, _scalar_variables, _scalar_variables, index);
368  };
369 
370  // Initialize the equations systems
371  _es->init();
372 
373  // Interpolate times
374  if (_interpolate_times)
375  {
376  // Create a second equation system
377  _es2 = std::make_unique<EquationSystems>(*_mesh);
379  _system2 = &_es2->get_system(_system_name);
380 
381  // Add the variables to the system
382  for (const auto & var_name : _nodal_variables)
383  _system2->add_variable(var_name, Utility::string_to_enum<Order>(_nodal_variable_order));
384 
385  for (const auto & var_name : _elemental_variables)
386  _system2->add_variable(var_name, CONSTANT, MONOMIAL);
387 
388  for (const auto & var_name : _scalar_variables)
389  _system2->add_variable(var_name, FIRST, SCALAR);
390 
391  // Initialize
392  _es2->init();
393 
394  // Update the times for interpolation (initially start at 0)
396 
397  // Copy the solutions from the first system
398  if (_file_type == "exodusII")
399  {
400  copy_solutions(*_exodusII_io, *_system, _exodus_index1 + 1);
401  copy_solutions(*_exodusII_io, *_system2, _exodus_index2 + 1);
402  }
403  else
404  {
405  copy_solutions(*_nemesis_io, *_system, _exodus_index1 + 1);
406  copy_solutions(*_nemesis_io, *_system2, _exodus_index2 + 1);
407  }
408 
409  // Update the systems
410  _system->update();
411  _es->update();
412  _system2->update();
413  _es2->update();
414  }
415 
416  // Non-interpolated times
417  else
418  {
419  if (_exodus_time_index > num_exo_times)
420  mooseError("In SolutionUserObjectBase, timestep = ",
422  ", but there are only ",
423  num_exo_times,
424  " time steps.");
425 
426  // Copy the values from the ExodusII/Nemsis file
427  if (_file_type == "exodusII")
428  copy_solutions(*_exodusII_io, *_system, _exodus_time_index);
429  else
430  copy_solutions(*_nemesis_io, *_system, _exodus_time_index);
431 
432  // Update the equations systems
433  _system->update();
434  _es->update();
435  }
436 }
437 
438 Real
439 SolutionUserObjectBase::directValue(const Node * node, const std::string & var_name) const
440 {
441  // Get the libmesh variable and system numbers
442  unsigned int var_num = _system->variable_number(var_name);
443  unsigned int sys_num = _system->number();
444 
445  // Get the node id and associated dof
446  dof_id_type node_id = node->id();
447  const Node & sys_node = _system->get_mesh().node_ref(node_id);
448  mooseAssert(sys_node.n_dofs(sys_num, var_num) > 0,
449  "Variable " << var_name << " has no DoFs on node " << sys_node.id());
450  dof_id_type dof_id = sys_node.dof_number(sys_num, var_num, 0);
451 
452  // Return the desired value for the dof
453  return directValue(dof_id);
454 }
455 
456 Real
457 SolutionUserObjectBase::directValue(const Elem * elem, const std::string & var_name) const
458 {
459  // Get the libmesh variable and system numbers
460  unsigned int var_num = _system->variable_number(var_name);
461  unsigned int sys_num = _system->number();
462 
463  // Get the element id and associated dof
464  dof_id_type elem_id = elem->id();
465  const Elem & sys_elem = _system->get_mesh().elem_ref(elem_id);
466  mooseAssert(sys_elem.n_dofs(sys_num, var_num) > 0,
467  "Variable " << var_name << " has no DoFs on element " << sys_elem.id());
468  dof_id_type dof_id = sys_elem.dof_number(sys_num, var_num, 0);
469 
470  // Return the desired value
471  return directValue(dof_id);
472 }
473 
474 void
476 {
477 }
478 
479 void
481 {
482 }
483 
484 void
486 {
487  // Update time interpolation for ExodusII or Nemesis solution
488  if (_interpolate_times)
490 
491  // Clear the caches
494 }
495 
496 void
498 {
499 }
500 
501 void
503 {
504 
505  // Make sure this only happens once
506  if (_initialized)
507  return;
508 
509  // We need to detect exodus files early
510  const bool has_exodus_extension =
511  MooseUtils::hasExtension(_mesh_file, "e", /*strip_exodus_ext =*/true) ||
512  MooseUtils::hasExtension(_mesh_file, "exo", true);
513  const bool has_nemesis_extension =
514  MooseUtils::hasExtension(_mesh_file, "n", /*strip_exodus_ext =*/true) ||
515  MooseUtils::hasExtension(_mesh_file, "nem", true);
516  if (has_exodus_extension)
517  _file_type = "exodusII";
518  else if (has_nemesis_extension)
519  _file_type = "nemesis";
520 
521  // Create a libmesh::Mesh object for storing the loaded data.
522  if (!_fe_problem.mesh().isDistributedMesh() || (_file_type == "exodusII") ||
524  _mesh = std::make_unique<ReplicatedMesh>(_communicator);
525  else
526  _mesh = std::make_unique<DistributedMesh>(_communicator);
527 
528  // ExodusII or Nemesis mesh file supplied
529  if (has_exodus_extension || has_nemesis_extension)
531 
532  // XDA mesh file supplied
533  else if (MooseUtils::hasExtension(_mesh_file, "xda"))
534  {
535  _file_type = "xda";
536  readXda();
537  }
538 
539  // XDR mesh file supplied
540  else if (MooseUtils::hasExtension(_mesh_file, "xdr"))
541  {
542  _file_type = "xdr";
543  readXda();
544  }
545 
546  // Produce an error for an unknown file type
547  else
548  mooseError(
549  "In SolutionUserObjectBase, invalid file type: only .xda, .xdr, .exo and .e supported");
550 
551  // Initialize the serial solution vector
554 
555  // Pull down a full copy of this vector on every processor so we can get values in parallel
557 
558  // Vector of variable numbers to apply the MeshFunction to
559  std::vector<unsigned int> var_nums;
560 
561  // If no variables were given, use all of them
562  if (_system_variables.empty())
563  {
565  for (const auto & var_num : var_nums)
566  _system_variables.push_back(_system->variable_name(var_num));
567  }
568 
569  // Otherwise, gather the numbers for the variables given
570  else
571  {
572  for (const auto & var_name : _system_variables)
573  var_nums.push_back(_system->variable_number(var_name));
574  }
575 
576  // Create the MeshFunction for working with the solution data
577  _mesh_function = std::make_unique<libMesh::MeshFunction>(
578  *_es, *_serialized_solution, _system->get_dof_map(), var_nums);
579  _mesh_function->init();
580 
581  // Tell the MeshFunctions that we might be querying them outside the
582  // mesh, so we can handle any errors at the MOOSE rather than at the
583  // libMesh level.
584  DenseVector<Number> default_values;
585  _mesh_function->enable_out_of_mesh_mode(default_values);
586 
587  // Build second MeshFunction for interpolation
588  if (_interpolate_times)
589  {
590  // Need to pull down a full copy of this vector on every processor so we can get values in
591  // parallel
595 
596  // Create the MeshFunction for the second copy of the data
597  _mesh_function2 = std::make_unique<libMesh::MeshFunction>(
599  _mesh_function2->init();
600  _mesh_function2->enable_out_of_mesh_mode(default_values);
601  }
602 
603  // Populate the MeshFunction variable index
604  for (unsigned int i = 0; i < _system_variables.size(); ++i)
605  {
606  std::string name = _system_variables[i];
608  }
609 
610  // If the start time is not the same as in the exodus file, we may need this on INITIAL
611  if (_interpolate_times)
613 
614  // Set initialization flag
615  _initialized = true;
616 }
617 
618 MooseEnum
620 {
621  return _file_type;
622 }
623 
624 void
626 {
627  if (_t != _interpolation_time)
628  {
630  {
631  // Helper to copy/update solutions from a file IO to a system
632  const auto update_solutions = [this](auto & io, libMesh::System & system, unsigned int index)
633  {
634  for (const auto & var_name : _nodal_variables)
635  io.copy_nodal_solution(system, var_name, var_name, index);
636  for (const auto & var_name : _elemental_variables)
637  io.copy_elemental_solution(system, var_name, var_name, index);
638  if (_scalar_variables.size() > 0)
639  io.copy_scalar_solution(system, _scalar_variables, _scalar_variables, index);
640  };
641 
642  if (_file_type == "exodusII")
643  update_solutions(*_exodusII_io, *_system, _exodus_index1 + 1);
644  else
645  update_solutions(*_nemesis_io, *_system, _exodus_index1 + 1);
646 
647  _system->update();
648  _es->update();
650 
651  if (_file_type == "exodusII")
652  update_solutions(*_exodusII_io, *_system2, _exodus_index2 + 1);
653  else
654  update_solutions(*_nemesis_io, *_system2, _exodus_index2 + 1);
655 
656  _system2->update();
657  _es2->update();
659  }
661  }
662 }
663 
664 bool
666 {
667  if (_file_type != "exodusII" && _file_type != "nemesis")
668  mooseError("getTimeInterpolationData only applicable for exodusII or Nemesis file type");
669 
670  int old_index1 = _exodus_index1;
671  int old_index2 = _exodus_index2;
672 
673  int num_exo_times = _exodus_times->size();
674 
675  const auto solution_time = solutionSampleTime();
676 
677  if (solution_time < (*_exodus_times)[0])
678  {
679  _exodus_index1 = 0;
680  _exodus_index2 = 0;
681  _interpolation_factor = 0.0;
682  }
683  else
684  {
685  for (int i = 0; i < num_exo_times - 1; ++i)
686  {
687  if (solution_time <= (*_exodus_times)[i + 1])
688  {
689  _exodus_index1 = i;
690  _exodus_index2 = i + 1;
692  (solution_time - (*_exodus_times)[i]) / ((*_exodus_times)[i + 1] - (*_exodus_times)[i]);
693  break;
694  }
695  else if (i == num_exo_times - 2)
696  {
697  _exodus_index1 = num_exo_times - 1;
698  _exodus_index2 = num_exo_times - 1;
699  _interpolation_factor = 1.0;
700  break;
701  }
702  }
703  }
704 
705  bool indices_modified(false);
706 
707  if (_exodus_index1 != old_index1 || _exodus_index2 != old_index2)
708  indices_modified = true;
709 
710  return indices_modified;
711 }
712 
713 unsigned int
714 SolutionUserObjectBase::getLocalVarIndex(const std::string & var_name) const
715 {
716  // Extract the variable index for the MeshFunction(s)
717  std::map<std::string, unsigned int>::const_iterator it = _local_variable_index.find(var_name);
718  if (it == _local_variable_index.end())
719  mooseError("Value requested for nonexistent variable '",
720  var_name,
721  "' in the '",
722  name(),
723  "' SolutionUserObjectBase.\nSystem selected: ",
724  _system_name,
725  "\nAvailable variables:\n",
727  return it->second;
728 }
729 
730 Real
732  const Point & p,
733  const std::string & var_name,
734  const MooseEnum & weighting_type,
735  const std::set<subdomain_id_type> * subdomain_ids) const
736 {
737  // first check if the FE type is continuous because in that case the value is
738  // unique and we can take a short cut, the default weighting_type found_first also
739  // shortcuts out
740  auto family =
742  .getVariable(
744  .feType()
745  .family;
746 
747  if (weighting_type == 1 ||
748  (family != L2_LAGRANGE && family != MONOMIAL && family != L2_HIERARCHIC))
749  return pointValue(t, p, var_name, subdomain_ids);
750 
751  // the shape function is discontinuous so we need to compute a suitable unique value
752  std::map<const Elem *, Real> values = discontinuousPointValue(t, p, var_name);
753  switch (weighting_type)
754  {
755  case 2:
756  {
757  Real average = 0.0;
758  for (auto & v : values)
759  average += v.second;
760  return average / Real(values.size());
761  }
762  case 4:
763  {
764  Real smallest_elem_id_value = std::numeric_limits<Real>::max();
765  dof_id_type smallest_elem_id = _fe_problem.mesh().maxElemId();
766  for (auto & v : values)
767  if (v.first->id() < smallest_elem_id)
768  {
769  smallest_elem_id = v.first->id();
770  smallest_elem_id_value = v.second;
771  }
772  return smallest_elem_id_value;
773  }
774  case 8:
775  {
776  Real largest_elem_id_value = std::numeric_limits<Real>::lowest();
777  dof_id_type largest_elem_id = 0;
778  for (auto & v : values)
779  if (v.first->id() > largest_elem_id)
780  {
781  largest_elem_id = v.first->id();
782  largest_elem_id_value = v.second;
783  }
784  return largest_elem_id_value;
785  }
786  }
787 
788  mooseError("SolutionUserObjectBase::pointValueWrapper reaches line that it should not be able to "
789  "reach.");
790  return 0.0;
791 }
792 
793 Real
795  const Point & p,
796  const std::string & var_name,
797  const std::set<subdomain_id_type> * subdomain_ids) const
798 {
799  const unsigned int local_var_index = getLocalVarIndex(var_name);
800  return pointValue(t, p, local_var_index, subdomain_ids);
801 }
802 
803 Real
804 SolutionUserObjectBase::pointValue(Real libmesh_dbg_var(t),
805  const Point & p,
806  const unsigned int local_var_index,
807  const std::set<subdomain_id_type> * subdomain_ids) const
808 {
809  // Create copy of point
810  Point pt(p);
811 
812  // do the transformations
813  for (unsigned int trans_num = 0; trans_num < _transformation_order.size(); ++trans_num)
814  {
815  if (_transformation_order[trans_num] == "rotation0")
816  pt = _r0 * pt;
817  else if (_transformation_order[trans_num] == "translation")
818  for (const auto i : make_range(Moose::dim))
819  pt(i) -= _translation[i];
820  else if (_transformation_order[trans_num] == "scale")
821  for (const auto i : make_range(Moose::dim))
822  pt(i) /= _scale[i];
823  else if (_transformation_order[trans_num] == "scale_multiplier")
824  for (const auto i : make_range(Moose::dim))
825  pt(i) *= _scale_multiplier[i];
826  else if (_transformation_order[trans_num] == "rotation1")
827  pt = _r1 * pt;
828  }
829 
830  // Extract the value at the current point
831  Real val = evalMeshFunction(pt, local_var_index, 1, subdomain_ids);
832 
833  // Interpolate
834  if (_interpolate_times && (_file_type == "exodusII" || _file_type == "nemesis"))
835  {
836  mooseAssert(t == _interpolation_time,
837  "Time passed into value() must match time at last call to timestepSetup()");
838  Real val2 = evalMeshFunction(pt, local_var_index, 2, subdomain_ids);
839  val = val + (val2 - val) * _interpolation_factor;
840  }
841 
842  return val;
843 }
844 
845 std::map<const Elem *, Real>
847  Real t,
848  const Point & p,
849  const std::string & var_name,
850  const std::set<subdomain_id_type> * subdomain_ids) const
851 {
852  const unsigned int local_var_index = getLocalVarIndex(var_name);
853  return discontinuousPointValue(t, p, local_var_index, subdomain_ids);
854 }
855 
856 std::map<const Elem *, Real>
858  Real libmesh_dbg_var(t),
859  Point pt,
860  const unsigned int local_var_index,
861  const std::set<subdomain_id_type> * subdomain_ids) const
862 {
863  // do the transformations
864  for (unsigned int trans_num = 0; trans_num < _transformation_order.size(); ++trans_num)
865  {
866  if (_transformation_order[trans_num] == "rotation0")
867  pt = _r0 * pt;
868  else if (_transformation_order[trans_num] == "translation")
869  for (const auto i : make_range(Moose::dim))
870  pt(i) -= _translation[i];
871  else if (_transformation_order[trans_num] == "scale")
872  for (const auto i : make_range(Moose::dim))
873  pt(i) /= _scale[i];
874  else if (_transformation_order[trans_num] == "scale_multiplier")
875  for (const auto i : make_range(Moose::dim))
876  pt(i) *= _scale_multiplier[i];
877  else if (_transformation_order[trans_num] == "rotation1")
878  pt = _r1 * pt;
879  }
880 
881  // Extract the value at the current point
882  std::map<const Elem *, Real> map =
883  evalMultiValuedMeshFunction(pt, local_var_index, 1, subdomain_ids);
884 
885  // Interpolate
886  if (_interpolate_times && (_file_type == "exodusII" || _file_type == "nemesis"))
887  {
888  mooseAssert(t == _interpolation_time,
889  "Time passed into value() must match time at last call to timestepSetup()");
890  std::map<const Elem *, Real> map2 = evalMultiValuedMeshFunction(pt, local_var_index, 2);
891 
892  if (map.size() != map2.size())
893  mooseError(
894  "In SolutionUserObjectBase::discontinuousPointValue map and map2 have different size");
895 
896  // construct the interpolated map
897  for (auto & k : map)
898  {
899  if (map2.find(k.first) == map2.end())
900  mooseError(
901  "In SolutionUserObjectBase::discontinuousPointValue map and map2 have differing keys");
902  Real val = k.second;
903  Real val2 = map2[k.first];
904  map[k.first] = val + (val2 - val) * _interpolation_factor;
905  }
906  }
907 
908  return map;
909 }
910 
913  Real t,
914  const Point & p,
915  const std::string & var_name,
916  const MooseEnum & weighting_type,
917  const std::set<subdomain_id_type> * subdomain_ids) const
918 {
919  // the default weighting_type found_first shortcuts out
920  if (weighting_type == 1)
921  return pointValueGradient(t, p, var_name, subdomain_ids);
922 
923  // the shape function is discontinuous so we need to compute a suitable unique value
924  std::map<const Elem *, RealGradient> values =
925  discontinuousPointValueGradient(t, p, var_name, subdomain_ids);
926  switch (weighting_type)
927  {
928  case 2:
929  {
930  RealGradient average = RealGradient(0.0, 0.0, 0.0);
931  for (auto & v : values)
932  average += v.second;
933  return average / Real(values.size());
934  }
935  case 4:
936  {
937  RealGradient smallest_elem_id_value;
938  dof_id_type smallest_elem_id = _fe_problem.mesh().maxElemId();
939  for (auto & v : values)
940  if (v.first->id() < smallest_elem_id)
941  {
942  smallest_elem_id = v.first->id();
943  smallest_elem_id_value = v.second;
944  }
945  return smallest_elem_id_value;
946  }
947  case 8:
948  {
949  RealGradient largest_elem_id_value;
950  dof_id_type largest_elem_id = 0;
951  for (auto & v : values)
952  if (v.first->id() > largest_elem_id)
953  {
954  largest_elem_id = v.first->id();
955  largest_elem_id_value = v.second;
956  }
957  return largest_elem_id_value;
958  }
959  }
960 
961  mooseError("SolutionUserObjectBase::pointValueGradientWrapper reaches line that it should not be "
962  "able to reach.");
963  return RealGradient(0.0, 0.0, 0.0);
964 }
965 
968  const Point & p,
969  const std::string & var_name,
970  const std::set<subdomain_id_type> * subdomain_ids) const
971 {
972  const unsigned int local_var_index = getLocalVarIndex(var_name);
973  return pointValueGradient(t, p, local_var_index, subdomain_ids);
974 }
975 
977 SolutionUserObjectBase::pointValueGradient(Real libmesh_dbg_var(t),
978  Point pt,
979  const unsigned int local_var_index,
980  const std::set<subdomain_id_type> * subdomain_ids) const
981 {
982  // do the transformations
983  for (unsigned int trans_num = 0; trans_num < _transformation_order.size(); ++trans_num)
984  {
985  if (_transformation_order[trans_num] == "rotation0")
986  pt = _r0 * pt;
987  else if (_transformation_order[trans_num] == "translation")
988  for (const auto i : make_range(Moose::dim))
989  pt(i) -= _translation[i];
990  else if (_transformation_order[trans_num] == "scale")
991  for (const auto i : make_range(Moose::dim))
992  pt(i) /= _scale[i];
993  else if (_transformation_order[trans_num] == "scale_multiplier")
994  for (const auto i : make_range(Moose::dim))
995  pt(i) *= _scale_multiplier[i];
996  else if (_transformation_order[trans_num] == "rotation1")
997  pt = _r1 * pt;
998  }
999 
1000  // Extract the value at the current point
1001  RealGradient val = evalMeshFunctionGradient(pt, local_var_index, 1, subdomain_ids);
1002 
1003  // Interpolate
1004  if (_interpolate_times && (_file_type == "exodusII" || _file_type == "nemesis"))
1005  {
1006  mooseAssert(t == _interpolation_time,
1007  "Time passed into value() must match time at last call to timestepSetup()");
1008  RealGradient val2 = evalMeshFunctionGradient(pt, local_var_index, 2, subdomain_ids);
1009  val = val + (val2 - val) * _interpolation_factor;
1010  }
1011 
1012  return val;
1013 }
1014 
1015 std::map<const Elem *, RealGradient>
1017  Real t,
1018  const Point & p,
1019  const std::string & var_name,
1020  const std::set<subdomain_id_type> * subdomain_ids) const
1021 {
1022  const unsigned int local_var_index = getLocalVarIndex(var_name);
1023  return discontinuousPointValueGradient(t, p, local_var_index, subdomain_ids);
1024 }
1025 
1026 std::map<const Elem *, RealGradient>
1028  Real libmesh_dbg_var(t),
1029  Point pt,
1030  const unsigned int local_var_index,
1031  const std::set<subdomain_id_type> * subdomain_ids) const
1032 {
1033  // do the transformations
1034  for (unsigned int trans_num = 0; trans_num < _transformation_order.size(); ++trans_num)
1035  {
1036  if (_transformation_order[trans_num] == "rotation0")
1037  pt = _r0 * pt;
1038  else if (_transformation_order[trans_num] == "translation")
1039  for (const auto i : make_range(Moose::dim))
1040  pt(i) -= _translation[i];
1041  else if (_transformation_order[trans_num] == "scale")
1042  for (const auto i : make_range(Moose::dim))
1043  pt(i) /= _scale[i];
1044  else if (_transformation_order[trans_num] == "scale_multiplier")
1045  for (const auto i : make_range(Moose::dim))
1046  pt(i) *= _scale_multiplier[i];
1047  else if (_transformation_order[trans_num] == "rotation1")
1048  pt = _r1 * pt;
1049  }
1050 
1051  // Extract the value at the current point
1052  std::map<const Elem *, RealGradient> map =
1053  evalMultiValuedMeshFunctionGradient(pt, local_var_index, 1, subdomain_ids);
1054 
1055  // Interpolate
1056  if (_interpolate_times && (_file_type == "exodusII" || _file_type == "nemesis"))
1057  {
1058  mooseAssert(t == _interpolation_time,
1059  "Time passed into value() must match time at last call to timestepSetup()");
1060  std::map<const Elem *, RealGradient> map2 =
1061  evalMultiValuedMeshFunctionGradient(pt, local_var_index, 1, subdomain_ids);
1062 
1063  if (map.size() != map2.size())
1064  mooseError(
1065  "In SolutionUserObjectBase::discontinuousPointValue map and map2 have different size");
1066 
1067  // construct the interpolated map
1068  for (auto & k : map)
1069  {
1070  if (map2.find(k.first) == map2.end())
1071  mooseError(
1072  "In SolutionUserObjectBase::discontinuousPointValue map and map2 have differing keys");
1073  RealGradient val = k.second;
1074  RealGradient val2 = map2[k.first];
1075  map[k.first] = val + (val2 - val) * _interpolation_factor;
1076  }
1077  }
1078 
1079  return map;
1080 }
1081 
1082 Real
1084 {
1085  Real val = (*_serialized_solution)(dof_index);
1086  if (_interpolate_times && (_file_type == "exodusII" || _file_type == "nemesis"))
1087  {
1088  Real val2 = (*_serialized_solution2)(dof_index);
1089  val = val + (val2 - val) * _interpolation_factor;
1090  }
1091  return val;
1092 }
1093 
1094 Real
1096  const unsigned int local_var_index,
1097  unsigned int func_num,
1098  const std::set<subdomain_id_type> * subdomain_ids) const
1099 {
1100  // Storage for mesh function output
1101  DenseVector<Number> output;
1102 
1103  // Extract a value from the _mesh_function
1104  {
1105  Threads::spin_mutex::scoped_lock lock(_solution_user_object_mutex);
1106 
1107  if (func_num == 1)
1108  {
1109  // Check the cache
1110  if (p == _cached_p && (!subdomain_ids || (*subdomain_ids == _cached_subdomain_ids)))
1111  return _cached_values(local_var_index);
1112 
1113  // else get a new value
1114  (*_mesh_function)(p, 0.0, output, subdomain_ids);
1115  // and cache it
1116  _cached_p = p;
1117  if (subdomain_ids)
1118  _cached_subdomain_ids = *subdomain_ids;
1119  _cached_values = output;
1120  }
1121 
1122  // Extract a value from _mesh_function2
1123  else if (func_num == 2)
1124  {
1125  // Check the cache
1126  if (p == _cached_p2 && (!subdomain_ids || (*subdomain_ids == _cached_subdomain_ids2)))
1127  return _cached_values2(local_var_index);
1128 
1129  // else get a new value
1130  (*_mesh_function2)(p, 0.0, output, subdomain_ids);
1131  // and cache it
1132  _cached_p2 = p;
1133  if (subdomain_ids)
1134  _cached_subdomain_ids2 = *subdomain_ids;
1135  _cached_values2 = output;
1136  }
1137  else
1138  mooseError("The func_num must be 1 or 2");
1139  }
1140 
1141  // Error if the data is out-of-range, which will be the case if the mesh functions are evaluated
1142  // outside the domain
1143  if (output.size() == 0)
1144  {
1145  std::ostringstream oss;
1146  p.print(oss);
1147  mooseError("Failed to access the data for variable '",
1148  _system_variables[local_var_index],
1149  "' at point ",
1150  oss.str(),
1151  " in the '",
1152  name(),
1153  "' SolutionUserObjectBase");
1154  }
1155  return output(local_var_index);
1156 }
1157 
1158 std::map<const Elem *, Real>
1160  const Point & p,
1161  const unsigned int local_var_index,
1162  unsigned int func_num,
1163  const std::set<subdomain_id_type> * subdomain_ids) const
1164 {
1165  // Storage for mesh function output
1166  std::map<const Elem *, DenseVector<Number>> temporary_output;
1167 
1168  // Extract a value from the _mesh_function
1169  {
1170  Threads::spin_mutex::scoped_lock lock(_solution_user_object_mutex);
1171  if (func_num == 1)
1172  _mesh_function->discontinuous_value(p, 0.0, temporary_output, subdomain_ids);
1173 
1174  // Extract a value from _mesh_function2
1175  else if (func_num == 2)
1176  _mesh_function2->discontinuous_value(p, 0.0, temporary_output, subdomain_ids);
1177 
1178  else
1179  mooseError("The func_num must be 1 or 2");
1180  }
1181 
1182  // Error if the data is out-of-range, which will be the case if the mesh functions are evaluated
1183  // outside the domain
1184  if (temporary_output.size() == 0)
1185  {
1186  std::ostringstream oss;
1187  p.print(oss);
1188  mooseError("Failed to access the data for variable '",
1189  _system_variables[local_var_index],
1190  "' at point ",
1191  oss.str(),
1192  " in the '",
1193  name(),
1194  "' SolutionUserObjectBase");
1195  }
1196 
1197  // Fill the actual map that is returned
1198  std::map<const Elem *, Real> output;
1199  for (auto & k : temporary_output)
1200  {
1201  mooseAssert(
1202  k.second.size() > local_var_index,
1203  "In SolutionUserObjectBase::evalMultiValuedMeshFunction variable with local_var_index "
1204  << local_var_index << " does not exist");
1205  output[k.first] = k.second(local_var_index);
1206  }
1207 
1208  return output;
1209 }
1210 
1213  const Point & p,
1214  const unsigned int local_var_index,
1215  unsigned int func_num,
1216  const std::set<subdomain_id_type> * subdomain_ids) const
1217 {
1218  // Storage for mesh function output
1219  std::vector<Gradient> output;
1220 
1221  // Extract a value from the _mesh_function
1222  {
1223  Threads::spin_mutex::scoped_lock lock(_solution_user_object_mutex);
1224  if (func_num == 1)
1225  _mesh_function->gradient(p, 0.0, output, subdomain_ids);
1226 
1227  // Extract a value from _mesh_function2
1228  else if (func_num == 2)
1229  _mesh_function2->gradient(p, 0.0, output, subdomain_ids);
1230 
1231  else
1232  mooseError("The func_num must be 1 or 2");
1233  }
1234 
1235  // Error if the data is out-of-range, which will be the case if the mesh functions are evaluated
1236  // outside the domain
1237  if (output.size() == 0)
1238  {
1239  std::ostringstream oss;
1240  p.print(oss);
1241  mooseError("Failed to access the data for variable '",
1242  _system_variables[local_var_index],
1243  "' at point ",
1244  oss.str(),
1245  " in the '",
1246  name(),
1247  "' SolutionUserObjectBase");
1248  }
1249  return output[local_var_index];
1250 }
1251 
1252 std::map<const Elem *, RealGradient>
1254  const Point & p,
1255  const unsigned int local_var_index,
1256  unsigned int func_num,
1257  const std::set<subdomain_id_type> * subdomain_ids) const
1258 {
1259  // Storage for mesh function output
1260  std::map<const Elem *, std::vector<Gradient>> temporary_output;
1261 
1262  // Extract a value from the _mesh_function
1263  {
1264  Threads::spin_mutex::scoped_lock lock(_solution_user_object_mutex);
1265  if (func_num == 1)
1266  _mesh_function->discontinuous_gradient(p, 0.0, temporary_output, subdomain_ids);
1267 
1268  // Extract a value from _mesh_function2
1269  else if (func_num == 2)
1270  _mesh_function2->discontinuous_gradient(p, 0.0, temporary_output, subdomain_ids);
1271 
1272  else
1273  mooseError("The func_num must be 1 or 2");
1274  }
1275 
1276  // Error if the data is out-of-range, which will be the case if the mesh functions are evaluated
1277  // outside the domain
1278  if (temporary_output.size() == 0)
1279  {
1280  std::ostringstream oss;
1281  p.print(oss);
1282  mooseError("Failed to access the data for variable '",
1283  _system_variables[local_var_index],
1284  "' at point ",
1285  oss.str(),
1286  " in the '",
1287  name(),
1288  "' SolutionUserObjectBase");
1289  }
1290 
1291  // Fill the actual map that is returned
1292  std::map<const Elem *, RealGradient> output;
1293  for (auto & k : temporary_output)
1294  {
1295  mooseAssert(
1296  k.second.size() > local_var_index,
1297  "In SolutionUserObjectBase::evalMultiValuedMeshFunction variable with local_var_index "
1298  << local_var_index << " does not exist");
1299  output[k.first] = k.second[local_var_index];
1300  }
1301 
1302  return output;
1303 }
1304 
1305 const std::vector<std::string> &
1307 {
1308  return _system_variables;
1309 }
1310 
1311 bool
1312 SolutionUserObjectBase::isVariableNodal(const std::string & var_name) const
1313 {
1314  return std::find(_nodal_variables.begin(), _nodal_variables.end(), var_name) !=
1315  _nodal_variables.end();
1316 }
1317 
1318 Real
1319 SolutionUserObjectBase::scalarValue(Real /*t*/, const std::string & var_name) const
1320 {
1321  unsigned int var_num = _system->variable_number(var_name);
1322  const DofMap & dof_map = _system->get_dof_map();
1323  std::vector<dof_id_type> dofs;
1324  dof_map.SCALAR_dof_indices(dofs, var_num);
1325  // We can handle only FIRST order scalar variables
1326  return directValue(dofs[0]);
1327 }
1328 
1329 void
1331 {
1332 #ifdef LIBMESH_HAVE_EXODUS_API
1333  const auto * exio_helper = (_file_type == "exodusII") ? &_exodusII_io->get_exio_helper()
1334  : &_nemesis_io->get_nemio_helper();
1335  const auto & id_to_block = exio_helper->id_to_block_names;
1336  _block_name_to_id.clear();
1337  _block_id_to_name.clear();
1338  for (const auto & it : id_to_block)
1339  {
1340  _block_name_to_id[it.second] = it.first;
1341  _block_id_to_name[it.first] = it.second;
1342  }
1343 #endif
1344 }
L2_HIERARCHIC
const THREAD_ID _tid
Thread ID of this postprocessor.
MultiMooseEnum _transformation_order
transformations (rotations, translation, scales) are performed in this order
void mooseInfo(Args &&... args) const
Definition: MooseBase.h:344
std::vector< std::string > _system_variables
A list of variables to extract from the read system.
static InputParameters validParams()
SolutionUserObjectBase(const InputParameters &parameters)
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
Definition: KokkosUtils.h:40
std::unique_ptr< libMesh::MeshFunction > _mesh_function2
Pointer to second libMesh::MeshFuntion, used for interpolation.
const libMesh::FEType & feType() const
Get the type of finite element object.
std::unique_ptr< libMesh::EquationSystems > _es
Pointer to the libMesh::EquationSystems object.
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sin(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tan
const bool _force_replicated_source
Whether to force the source mesh to be replicated.
RealVectorValue _rotation0_vector
vector about which to rotate
const std::vector< Real > * _exodus_times
The times available in the ExodusII file.
virtual void initialSetup() override
Initialize the System and Mesh objects for the solution being read.
void updateTimeInterpolationFromFile()
Updates the times for interpolating ExodusII or Nemesis data.
virtual Real solutionSampleTime()=0
Get the time at which to sample the solution.
SCALAR
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Definition: MooseBase.h:467
static InputParameters validParams()
void readXda()
Method for reading XDA mesh and equation systems file(s) This method is called by the constructor whe...
static Threads::spin_mutex _solution_user_object_mutex
std::map< const Elem *, libMesh::RealGradient > discontinuousPointValueGradient(Real t, const Point &p, const std::string &var_name, const std::set< subdomain_id_type > *subdomain_ids=nullptr) const
Returns the gradient at a specific location and variable for cases where the gradient is multivalued ...
FIRST
bool updateInterpolationBracketingTimeIndices()
Updates the time indices to interpolate between for ExodusII or Nemesis data.
TypeTensor< T > transpose() const
std::unique_ptr< NumericVector< Number > > _serialized_solution2
Pointer to second serial solution, used for interpolation.
std::vector< Real > _scale
Scale parameter.
std::vector< Real > _translation
Translation.
Real _rotation1_angle
angle (in degrees) which to rotate through about vector _rotation1_vector
unsigned int size() const
Return the number of active items in the MultiMooseEnum.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
virtual dof_id_type maxElemId() const
Definition: MooseMesh.C:3220
Real _rotation0_angle
angle (in degrees) which to rotate through about vector _rotation0_vector
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:163
MooseEnum getSolutionFileType() const
Get the type of file that was read.
void get_all_variable_numbers(std::vector< unsigned int > &all_variable_numbers) const
int _exodus_time_index
Current ExodusII time index.
std::unique_ptr< libMesh::ExodusII_IO > _exodusII_io
Pointer to the libMesh::ExodusII used to read the files.
Real _interpolation_time
Time in the current simulation at which the solution interpolation was last updated.
std::unique_ptr< libMesh::EquationSystems > _es2
Pointer to second libMesh::EquationSystems object, used for interpolation.
const Parallel::Communicator & _communicator
std::map< const Elem *, Real > evalMultiValuedMeshFunction(const Point &p, const unsigned int local_var_index, unsigned int func_num, const std::set< subdomain_id_type > *subdomain_ids=nullptr) const
A wrapper method for calling the various MeshFunctions that calls the mesh function functionality for...
libMesh::RealGradient evalMeshFunctionGradient(const Point &p, const unsigned int local_var_index, unsigned int func_num, const std::set< subdomain_id_type > *subdomain_ids=nullptr) const
A wrapper method interfacing with the libMesh mesh function for evaluating the gradient.
std::unique_ptr< NumericVector< Number > > _serialized_solution
Pointer to the serial solution vector.
Point _cached_p
Cached points.
bool _initialized
True if initial_setup has executed.
std::unique_ptr< libMesh::Nemesis_IO > _nemesis_io
Pointer to the libMesh::Nemesis_IO used to read the files.
const MeshBase & get_mesh() const
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
virtual const MooseVariableFieldBase & getVariable(const THREAD_ID tid, const std::string &var_name, Moose::VarKindType expected_var_type=Moose::VarKindType::VAR_ANY, Moose::VarFieldType expected_var_field_type=Moose::VarFieldType::VAR_FIELD_ANY) const override
Returns the variable reference for requested variable which must be of the expected_var_type (Nonline...
dof_id_type n_dofs() const
std::map< SubdomainName, SubdomainID > _block_name_to_id
Map from block ID to block names. Read from the ExodusII file.
void SCALAR_dof_indices(std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
auto max(const L &left, const R &right)
unsigned int variable_number(std::string_view var) const
virtual void timestepSetup() override
When reading ExodusII files, this will update the interpolation times.
DenseVector< Number > _cached_values2
virtual void execute() override
Execute method.
DenseVector< Number > _cached_values
Cached values.
std::unique_ptr< libMesh::MeshBase > _mesh
Pointer the libMesh::mesh object.
FEProblemBase & _fe_problem
Reference to the FEProblemBase for this user object.
libMesh::System * _system
Pointer libMesh::System class storing the read solution.
CONSTANT
unsigned int number() const
RealVectorValue _rotation1_vector
vector about which to rotate
const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:103
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template cos(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(cos
std::string formatString(std::string message, const std::string &prefix)
Add new lines and prefixes to a string for pretty display in output NOTE: This makes a copy of the st...
Definition: ConsoleUtils.C:583
std::string _mesh_file
The XDA/ExodusII/XDR/Nemesis file that is being read.
std::unique_ptr< NumericVector< Number > > solution
std::vector< std::string > _scalar_variables
Stores names of scalar variables.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:54
RealTensorValue _r1
Rotation matrix that performs the "_rotation1_angle about rotation1_vector".
unsigned int add_variable(std::string_view var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
const std::string & variable_name(const unsigned int i) const
std::string stringify(const T &t)
conversion to string
Definition: Conversion.h:64
bool hasSecondOrderElements()
check if the mesh has SECOND order elements
Definition: MooseMesh.C:3842
virtual void initialize() override
Called before execute() is ever called so that data can be cleared.
Real evalMeshFunction(const Point &p, const unsigned int local_var_index, unsigned int func_num, const std::set< subdomain_id_type > *subdomain_ids=nullptr) const
A wrapper method for calling the various MeshFunctions used for reading the data. ...
MONOMIAL
Real scalarValue(Real t, const std::string &var_name) const
Returns a value of a global variable.
const MooseEnum _nodal_variable_order
Nodal variable order, used when reading in solution data.
libMesh::System * _system2
Pointer to a second libMesh::System object, used for interpolation.
GenericRealTensorValue< is_ad > rotVecToZ(GenericRealVectorValue< is_ad > vec)
provides a rotation matrix that will rotate the vector vec to the z axis (the "2" direction) ...
virtual void update()
bool hasExtension(const std::string &filename, std::string ext, bool strip_exodus_ext)
Definition: MooseUtils.C:387
Real directValue(const Node *node, const std::string &var_name) const
Return a value directly from a Node.
void readBlockIdMapFromExodusII()
Read block ID map from the ExodusII file.
const std::vector< std::string > & variableNames() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
bool isVariableNodal(const std::string &var_name) const
std::map< std::string, unsigned int > _local_variable_index
Stores the local index need by MeshFunction.
std::map< const Elem *, libMesh::RealGradient > evalMultiValuedMeshFunctionGradient(const Point &p, const unsigned int local_var_index, unsigned int func_num, const std::set< subdomain_id_type > *subdomain_ids=nullptr) const
A wrapper method interfacing with the libMesh mesh function that calls the gradient functionality for...
Real pointValueWrapper(Real t, const Point &p, const std::string &var_name, const MooseEnum &weighting_type=weightingType(), const std::set< subdomain_id_type > *subdomain_ids=nullptr) const
Returns a value at a specific location and variable checking for multiple values and weighting these ...
int _exodus_index1
Time index 1, used for interpolation.
virtual const Elem & elem_ref(const dof_id_type i) const
std::vector< std::string > _nodal_variables
Stores names of nodal variables.
std::string _es_file
The XDA/XDR file that contians the EquationSystems data (xda/xdr only)
IntRange< T > make_range(T beg, T end)
virtual MooseMesh & mesh() override
static std::unique_ptr< NumericVector< Number > > build(const Parallel::Communicator &comm, SolverPackage solver_package=libMesh::default_solver_package(), ParallelType parallel_type=AUTOMATIC)
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition: MooseBase.h:281
RealTensorValue _r0
Rotation matrix that performs the "_rotation0_angle about rotation0_vector".
virtual unsigned int size() const override final
L2_LAGRANGE
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
std::vector< std::string > _elemental_variables
Stores names of elemental variables.
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object...
virtual const Node & node_ref(const dof_id_type i) const
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition: MooseBase.h:209
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type...
void readExodusIIOrNemesis()
Method for reading an ExodusII or Nemesis file, which is called when a mesh file with a ...
MooseEnum _file_type
File type to read (0 = xda; 1 = ExodusII, 2 = xdr, 3 = Nemesis)
libMesh::RealGradient pointValueGradientWrapper(Real t, const Point &p, const std::string &var_name, const MooseEnum &weighting_type=weightingType(), const std::set< subdomain_id_type > *subdomain_ids=nullptr) const
Returns the gradient at a specific location and variable checking for multiple values and weighting t...
std::vector< Real > _scale_multiplier
scale_multiplier parameter
std::unique_ptr< libMesh::MeshFunction > _mesh_function
Pointer the libMesh::MeshFunction object that the read data is stored.
bool _interpolate_times
Flag for triggering interpolation of ExodusII data.
virtual bool isDistributedMesh() const
Returns the final Mesh distribution type.
Definition: MooseMesh.h:1140
bool checkFileReadable(const std::string &filename, bool check_line_endings, bool throw_on_unreadable, bool check_for_git_lfs_pointer)
Definition: MooseUtils.C:254
std::string _system_name
The system name to extract from the XDA/XDR file (xda/xdr only)
const DofMap & get_dof_map() const
bool isParamSetByUser(const std::string &name) const
Test if the supplied parameter is set by a user, as opposed to not set or set to default.
Definition: MooseBase.h:215
std::map< const Elem *, Real > discontinuousPointValue(Real t, Point pt, const unsigned int local_var_index, const std::set< subdomain_id_type > *subdomain_ids=nullptr) const
Returns a value at a specific location and variable for cases where the solution is multivalued at el...
Real pointValue(Real t, const Point &p, const unsigned int local_var_index, const std::set< subdomain_id_type > *subdomain_ids=nullptr) const
Returns a value at a specific location and variable (see SolutionFunction)
unsigned int getLocalVarIndex(const std::string &var_name) const
Returns the local index for a given variable name.
int _exodus_index2
Time index 2, used for interpolation.
Real _interpolation_factor
Interpolation weight factor.
std::map< SubdomainID, SubdomainName > _block_id_to_name
Map from block names to block IDs. Read from the ExodusII file.
virtual void finalize() override
Finalize.
uint8_t dof_id_type
const Real pi
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
This method takes a space delimited list of parameter names and adds them to the specified group name...
std::set< subdomain_id_type > _cached_subdomain_ids2
libMesh::RealGradient pointValueGradient(Real t, const Point &p, const std::string &var_name, const std::set< subdomain_id_type > *subdomain_ids=nullptr) const
Returns the gradient at a specific location and variable (see SolutionFunction)
std::set< subdomain_id_type > _cached_subdomain_ids
Cached subdomain ids.