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