15#include "libmesh/mesh_modification.h"
26 Real alpha = 0, beta = 0, gamma = 0;
28 const bool must_rotate_axes =
31 bool negative_radii =
false;
33 if (up_direction ==
X)
35 alpha = 90, beta = 0, gamma = 0;
45 negative_radii =
true;
53 else if (up_direction ==
Y)
54 alpha = 0, beta = 0, gamma = 0;
55 else if (up_direction ==
Z)
57 alpha = 0, beta = -90, gamma = 0;
67 negative_radii =
true;
80 _rotate = std::make_unique<RealTensorValue>(
81 RealTensorValue::extrinsic_rotation_matrix(alpha, beta, gamma));
85 mooseError(
"Rotation yields negative radial values");
91 const bool must_rotate_axes =
93 bool axes_rotated =
false;
96 const auto angles = std::make_tuple(alpha, beta, gamma);
97 if (angles == std::make_tuple(0, 90, 0))
103 "'_z_axis' is not an expected value");
111 "'_z_axis' is not an expected value");
120 _rotate = std::make_unique<RealTensorValue>(
121 RealTensorValue::extrinsic_rotation_matrix(alpha, beta, gamma));
124 if (must_rotate_axes && !axes_rotated)
125 mooseError(
"Unsupported manual angle prescription in 'MooseAppCoordTransform::setRotation'. "
126 "For non-Cartesian coordinate systems, the only currently supported rotation is "
127 "(alpha, beta, gamma) = (0, 90, 0)");
136 std::make_unique<RealTensorValue>(RealTensorValue(
scale, 0, 0, 0,
scale, 0, 0, 0,
scale));
148 if (rz_symmetry_axis ==
INVALID)
149 mooseError(
"For RZ coordinate systems, the 'rz_symmetry_axis' parameter must be provided to "
150 "'MooseAppCoordTransform::setCoordinateSystem'");
162 const auto & params =
mesh.parameters();
167 const auto & coord_sys =
mesh.getCoordSystem();
168 std::unordered_set<Moose::CoordinateSystemType> coord_types;
169 auto map_it = coord_sys.begin();
171 if (map_it == coord_sys.end())
177 for (; map_it != coord_sys.end(); ++map_it)
178 coord_types.insert(map_it->second);
182 if (
mesh.usingGeneralAxisymmetricCoordAxes())
195 params.addDeprecatedParam<std::vector<SubdomainName>>(
197 "Block IDs for the coordinate systems.",
198 "Please use the 'coord_block' parameter instead.");
199 params.addParam<std::vector<SubdomainName>>(
201 "Block IDs for the coordinate systems. If this parameter is specified, then it must "
202 "encompass all the subdomains on the mesh.");
206 "coord_type", coord_types,
"Type of the coordinate system per block param");
208 "rz_coord_axis", rz_coord_axis,
"The rotation axis (X | Y) for axisymmetric coordinates");
209 params.addParam<std::vector<SubdomainName>>(
210 "rz_coord_blocks",
"Blocks using general axisymmetric coordinate systems");
211 params.addParam<std::vector<Point>>(
"rz_coord_origins",
212 "Axis origin points for each block in 'rz_coord_blocks'");
213 params.addParam<std::vector<RealVectorValue>>(
214 "rz_coord_directions",
"Axis directions for each block in 'rz_coord_blocks'");
215 params.addParam<std::string>(
217 "How much distance one mesh length unit represents, e.g. 1 cm, 1 nm, 1 ft, 5inches");
218 params.addRangeCheckedParam<Real>(
220 "-180<alpha_rotation<=180",
221 "The number of degrees that the domain should be alpha-rotated using the Euler "
222 "angle ZXZ convention from https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix in "
223 "order to align with a canonical physical space of your choosing.");
224 params.addRangeCheckedParam<Real>(
226 "-180<beta_rotation<=180",
227 "The number of degrees that the domain should be beta-rotated using the Euler "
228 "angle ZXZ convention from https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix in "
229 "order to align with a canonical physical space of your choosing.");
230 params.addRangeCheckedParam<Real>(
232 "-180<gamma_rotation<=180",
233 "The number of degrees that the domain should be gamma-rotated using the Euler "
234 "angle ZXZ convention from https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix in "
235 "order to align with a canonical physical space of your choosing.");
240 "Specify what axis corresponds to the up direction in physical space (the opposite of the "
241 "gravity vector if you will). If this parameter is provided, we will perform a single 90 "
242 "degree rotation of the domain--if the provided axis is 'x' or 'z', we will not rotate if "
243 "the axis is 'y'--such that a point which was on the provided axis will now lie on the "
244 "y-axis, e.g. the y-axis is our canonical up direction. If you want finer grained control "
245 "than this, please use the 'alpha_rotation', 'beta_rotation', and 'gamma_rotation' "
247 params.addParamNamesToGroup(
248 "block coord_type coord_block rz_coord_axis rz_coord_blocks rz_coord_origins "
249 "rz_coord_directions",
250 "Coordinate system");
251 params.addParamNamesToGroup(
252 "length_unit alpha_rotation beta_rotation gamma_rotation up_direction",
253 "Transformations relative to parent application frame of reference");
258 : _coord_type(
Moose::COORD_XYZ),
261 _has_different_coord_sys(false),
262 _using_general_rz_coord_axes(false),
263 _length_unit(
std::string(
"1*m")),
265 _mesh_transformed(false)
272 const auto & params =
mesh.parameters();
277 const bool has_alpha = params.isParamValid(
"alpha_rotation");
278 const bool has_beta = params.isParamValid(
"beta_rotation");
279 const bool has_gamma = params.isParamValid(
"gamma_rotation");
280 const auto & up_direction = params.get<
MooseEnum>(
"up_direction");
282 if (has_alpha || has_beta || has_gamma)
284 if (up_direction.isValid())
285 mooseError(
"Cannot simultaneously set rotation angles as well as an up direction");
287 const auto alpha = (has_alpha ? params.get<Real>(
"alpha_rotation") : Real(0));
288 const auto beta = (has_beta ? params.get<Real>(
"beta_rotation") : Real(0));
289 const auto gamma = (has_gamma ? params.get<Real>(
"gamma_rotation") : Real(0));
293 else if (up_direction.isValid())
299 if (params.isParamValid(
"length_unit"))
304 : _coord_type(
Moose::COORD_XYZ),
307 _has_different_coord_sys(false),
308 _using_general_rz_coord_axes(false),
309 _length_unit(
std::string(
"1*m")),
311 _mesh_transformed(false)
316 : _coord_type(other._coord_type),
317 _r_axis(other._r_axis),
318 _z_axis(other._z_axis),
319 _has_different_coord_sys(other._has_different_coord_sys),
320 _using_general_rz_coord_axes(other._using_general_rz_coord_axes),
321 _length_unit(other._length_unit),
322 _euler_angles(other._euler_angles),
323 _mesh_transformed(other._mesh_transformed)
326 _scale = std::make_unique<RealTensorValue>(*other.
_scale);
333 : _coord_type(static_cast<
Moose::CoordinateSystemType>(
std::get<4>(minimal_data))),
334 _r_axis(static_cast<
Direction>(
std::get<5>(minimal_data))),
335 _z_axis(static_cast<
Direction>(
std::get<6>(minimal_data))),
336 _has_different_coord_sys(
std::get<7>(minimal_data)),
337 _using_general_rz_coord_axes(
std::get<8>(minimal_data)),
338 _length_unit(
std::string(
"1*m")),
339 _euler_angles(
std::get<3>(minimal_data)),
340 _mesh_transformed(
std::get<9>(minimal_data))
342 if (std::get<0>(minimal_data))
344 if (std::get<2>(minimal_data))
345 _rotate = std::make_unique<RealTensorValue>(RealTensorValue::extrinsic_rotation_matrix(
353 const Real scale_factor =
_scale ? (*_scale)(0, 0) : 1;
354 return {
static_cast<short int>(bool(
_scale)),
356 static_cast<short int>(
bool(
_rotate)),
359 static_cast<unsigned int>(
_r_axis),
360 static_cast<unsigned int>(
_z_axis),
379 _scale = std::make_unique<RealTensorValue>(*other.
_scale);
397 _rs = std::make_unique<RealTensorValue>(RealTensorValue(1, 0, 0, 0, 1, 0, 0, 0, 1));
418 mooseError(
"Running MultiApps 'in position' is only supported for XYZ coordinate systems");
421 mooseError(
"Scaling and rotation are currently not supported for general axisymmetric "
422 "coordinate systems.");
425 mooseError(
"App mesh is being transformed twice");
432 if (translation != Point(0, 0, 0))
433 MeshTools::Modification::translate(
mesh, translation(0), translation(1), translation(2));
447 const auto matrix_elem = (*_rs)(i, j);
450 if (!MooseUtils::absoluteFuzzyEqual(matrix_elem, 1))
453 else if (!MooseUtils::absoluteFuzzyEqual(matrix_elem, 0))
461 : _our_app_transform(our_app_transform),
462 _destination_app_transform(nullptr),
463 _skip_coordinate_collapsing(false)
493 for (
unsigned int i = 0; i < LIBMESH_DIM; ++i)
495 r_squared += ret(i) * ret(i);
497 const auto r = std::sqrt(r_squared);
507 for (
unsigned int i = 0; i < LIBMESH_DIM; ++i)
508 r_squared += ret(i) * ret(i);
510 const auto r = std::sqrt(r_squared);
518 for (
unsigned int i = 0; i < LIBMESH_DIM; ++i)
522 MooseUtils::absoluteFuzzyEqual(ret(i), 0),
523 "Our point should be 0 if we are evaluating at an index that is neither our r or z-axis");
524 r_squared += ret(i) * ret(i);
527 const auto r = std::sqrt(r_squared);
560 mooseError(
"Coordinate collapsing occurred in going to the reference space. There is no unique "
574 mooseError(
"Scaling and rotation are currently not supported for general axisymmetric "
575 "coordinate systems.");
586 "The destination coordinate system has different coordinate systems and we have coordinate "
587 "system(s) that could require coordinate collapsing when transforming from our coordinate "
588 "system to the destination coordinate system. Because our transform method only takes a "
589 "point argument, and not subdomain arguments, the transform is ambiguous");
594 mooseError(
"When the destination coordinate system is RZ or RSPHERICAL, we have to perform "
595 "coordinate collapsing based on *our* coordinate system. However, we have multiple "
596 "coordinate systems, and since when evaluating transformations, we are only "
597 "called with a Point argument, we do not know what subdomain we are on and "
598 "consequently we do not know what coordinate collapse to apply.");
602 mooseError(
"If either this app or the destination app uses general axisymmetric axes, "
603 "coordinate collapsing must be skipped.");
644 if (!MooseUtils::absoluteFuzzyEqual(
_translation(i), 0))
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Physical unit management class with runtime unit string parsing, unit checking, unit conversion,...
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type.
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.