15 #include "libmesh/mesh_modification.h" 28 Real alpha = 0, beta = 0, gamma = 0;
30 const bool must_rotate_axes =
33 bool negative_radii =
false;
35 if (up_direction == X)
37 alpha = 90, beta = 0, gamma = 0;
43 _z_axis = processZAxis(X);
45 else if (_r_axis == Y)
47 negative_radii =
true;
49 _z_axis = processZAxis(Y);
55 else if (up_direction == Y)
56 alpha = 0, beta = 0, gamma = 0;
57 else if (up_direction == Z)
59 alpha = 0, beta = -90, gamma = 0;
65 _z_axis = processZAxis(Z);
67 else if (_r_axis == Y)
69 negative_radii =
true;
71 _z_axis = processZAxis(X);
80 _euler_angles = {{alpha, beta, gamma}};
82 _rotate = std::make_unique<RealTensorValue>(
87 mooseError(
"Rotation yields negative radial values");
93 const bool must_rotate_axes =
95 bool axes_rotated =
false;
98 const auto angles = std::make_tuple(alpha, beta, gamma);
99 if (angles == std::make_tuple(0, 90, 0))
105 "'_z_axis' is not an expected value");
109 else if (_r_axis == Y)
113 "'_z_axis' is not an expected value");
121 _euler_angles = {{alpha, beta, gamma}};
122 _rotate = std::make_unique<RealTensorValue>(
126 if (must_rotate_axes && !axes_rotated)
127 mooseError(
"Unsupported manual angle prescription in 'MooseAppCoordTransform::setRotation'. " 128 "For non-Cartesian coordinate systems, the only currently supported rotation is " 129 "(alpha, beta, gamma) = (0, 90, 0)");
135 _length_unit = length_unit;
146 _coord_type = coord_type;
150 if (rz_symmetry_axis ==
INVALID)
151 mooseError(
"For RZ coordinate systems, the 'rz_symmetry_axis' parameter must be provided to " 152 "'MooseAppCoordTransform::setCoordinateSystem'");
154 _z_axis = rz_symmetry_axis;
155 _r_axis = _z_axis == X ? Y : X;
164 const auto & params =
mesh.parameters();
169 const auto & coord_sys =
mesh.getCoordSystem();
170 std::unordered_set<Moose::CoordinateSystemType> coord_types;
171 auto map_it = coord_sys.begin();
173 if (map_it == coord_sys.end())
179 for (; map_it != coord_sys.end(); ++map_it)
180 coord_types.insert(map_it->second);
182 _has_different_coord_sys = coord_types.size() > 1;
184 if (
mesh.usingGeneralAxisymmetricCoordAxes())
185 _using_general_rz_coord_axes =
true;
197 params.addDeprecatedParam<std::vector<SubdomainName>>(
199 "Block IDs for the coordinate systems.",
200 "Please use the 'coord_block' parameter instead.");
201 params.addParam<std::vector<SubdomainName>>(
203 "Block IDs for the coordinate systems. If this parameter is specified, then it must " 204 "encompass all the subdomains on the mesh.");
208 "coord_type", coord_types,
"Type of the coordinate system per block param");
210 "rz_coord_axis", rz_coord_axis,
"The rotation axis (X | Y) for axisymmetric coordinates");
211 params.addParam<std::vector<SubdomainName>>(
212 "rz_coord_blocks",
"Blocks using general axisymmetric coordinate systems");
213 params.addParam<std::vector<Point>>(
"rz_coord_origins",
214 "Axis origin points for each block in 'rz_coord_blocks'");
215 params.addParam<std::vector<RealVectorValue>>(
216 "rz_coord_directions",
"Axis directions for each block in 'rz_coord_blocks'");
217 params.addParam<std::string>(
219 "How much distance one mesh length unit represents, e.g. 1 cm, 1 nm, 1 ft, 5inches");
220 params.addRangeCheckedParam<
Real>(
222 "-180<alpha_rotation<=180",
223 "The number of degrees that the domain should be alpha-rotated using the Euler " 224 "angle ZXZ convention from https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix in " 225 "order to align with a canonical physical space of your choosing.");
226 params.addRangeCheckedParam<
Real>(
228 "-180<beta_rotation<=180",
229 "The number of degrees that the domain should be beta-rotated using the Euler " 230 "angle ZXZ convention from https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix in " 231 "order to align with a canonical physical space of your choosing.");
232 params.addRangeCheckedParam<
Real>(
234 "-180<gamma_rotation<=180",
235 "The number of degrees that the domain should be gamma-rotated using the Euler " 236 "angle ZXZ convention from https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix in " 237 "order to align with a canonical physical space of your choosing.");
242 "Specify what axis corresponds to the up direction in physical space (the opposite of the " 243 "gravity vector if you will). If this parameter is provided, we will perform a single 90 " 244 "degree rotation of the domain--if the provided axis is 'x' or 'z', we will not rotate if " 245 "the axis is 'y'--such that a point which was on the provided axis will now lie on the " 246 "y-axis, e.g. the y-axis is our canonical up direction. If you want finer grained control " 247 "than this, please use the 'alpha_rotation', 'beta_rotation', and 'gamma_rotation' " 249 params.addParamNamesToGroup(
250 "block coord_type coord_block rz_coord_axis rz_coord_blocks rz_coord_origins " 251 "rz_coord_directions",
252 "Coordinate system");
253 params.addParamNamesToGroup(
254 "length_unit alpha_rotation beta_rotation gamma_rotation up_direction",
255 "Transformations relative to parent application frame of reference");
263 _has_different_coord_sys(false),
264 _using_general_rz_coord_axes(false),
265 _length_unit(
std::string(
"1*m")),
267 _mesh_transformed(false)
274 const auto & params =
mesh.parameters();
279 const bool has_alpha = params.isParamValid(
"alpha_rotation");
280 const bool has_beta = params.isParamValid(
"beta_rotation");
281 const bool has_gamma = params.isParamValid(
"gamma_rotation");
282 const auto & up_direction = params.get<
MooseEnum>(
"up_direction");
284 if (has_alpha || has_beta || has_gamma)
286 if (up_direction.isValid())
287 mooseError(
"Cannot simultaneously set rotation angles as well as an up direction");
289 const auto alpha = (has_alpha ? params.get<
Real>(
"alpha_rotation") :
Real(0));
290 const auto beta = (has_beta ? params.get<
Real>(
"beta_rotation") :
Real(0));
291 const auto gamma = (has_gamma ? params.get<
Real>(
"gamma_rotation") :
Real(0));
295 else if (up_direction.isValid())
301 if (params.isParamValid(
"length_unit"))
309 _has_different_coord_sys(false),
310 _using_general_rz_coord_axes(false),
311 _length_unit(
std::string(
"1*m")),
313 _mesh_transformed(false)
318 : _coord_type(other._coord_type),
319 _r_axis(other._r_axis),
320 _z_axis(other._z_axis),
321 _has_different_coord_sys(other._has_different_coord_sys),
322 _using_general_rz_coord_axes(other._using_general_rz_coord_axes),
323 _length_unit(other._length_unit),
324 _euler_angles(other._euler_angles),
325 _mesh_transformed(other._mesh_transformed)
328 _scale = std::make_unique<RealTensorValue>(*other.
_scale);
338 _has_different_coord_sys(
std::
get<7>(minimal_data)),
339 _using_general_rz_coord_axes(
std::
get<8>(minimal_data)),
340 _length_unit(
std::string(
"1*m")),
341 _euler_angles(
std::
get<3>(minimal_data)),
342 _mesh_transformed(
std::
get<9>(minimal_data))
344 if (std::get<0>(minimal_data))
346 if (std::get<2>(minimal_data))
355 const Real scale_factor =
_scale ? (*_scale)(0, 0) : 1;
356 return {
static_cast<short int>(bool(
_scale)),
358 static_cast<short int>(
bool(
_rotate)),
361 static_cast<unsigned int>(
_r_axis),
362 static_cast<unsigned int>(
_z_axis),
381 _scale = std::make_unique<RealTensorValue>(*other.
_scale);
420 mooseError(
"Running MultiApps 'in position' is only supported for XYZ coordinate systems");
423 mooseError(
"Scaling and rotation are currently not supported for general axisymmetric " 424 "coordinate systems.");
427 mooseError(
"App mesh is being transformed twice");
434 if (translation !=
Point(0, 0, 0))
435 MeshTools::Modification::translate(
mesh, translation(0), translation(1), translation(2));
449 const auto matrix_elem = (*_rs)(i, j);
463 : _our_app_transform(our_app_transform),
464 _destination_app_transform(nullptr),
465 _skip_coordinate_collapsing(false)
495 for (
unsigned int i = 0; i < LIBMESH_DIM; ++i)
497 r_squared += ret(i) * ret(i);
509 for (
unsigned int i = 0; i < LIBMESH_DIM; ++i)
510 r_squared += ret(i) * ret(i);
520 for (
unsigned int i = 0; i < LIBMESH_DIM; ++i)
525 "Our point should be 0 if we are evaluating at an index that is neither our r or z-axis");
526 r_squared += ret(i) * ret(i);
562 mooseError(
"Coordinate collapsing occurred in going to the reference space. There is no unique " 576 mooseError(
"Scaling and rotation are currently not supported for general axisymmetric " 577 "coordinate systems.");
588 "The destination coordinate system has different coordinate systems and we have coordinate " 589 "system(s) that could require coordinate collapsing when transforming from our coordinate " 590 "system to the destination coordinate system. Because our transform method only takes a " 591 "point argument, and not subdomain arguments, the transform is ambiguous");
596 mooseError(
"When the destination coordinate system is RZ or RSPHERICAL, we have to perform " 597 "coordinate collapsing based on *our* coordinate system. However, we have multiple " 598 "coordinate systems, and since when evaluating transformations, we are only " 599 "called with a Point argument, we do not know what subdomain we are on and " 600 "consequently we do not know what coordinate collapse to apply.");
604 mooseError(
"If either this app or the destination app uses general axisymmetric axes, " 605 "coordinate collapsing must be skipped.");
static TensorValue< Real > extrinsic_rotation_matrix(Real angle1_deg, Real angle2_deg, Real angle3_deg)
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Function to check whether two variables are equal within an absolute tolerance.
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
T * get(const std::unique_ptr< T > &u)
The MooseUtils::get() specializations are used to support making forwards-compatible code changes fro...
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
TensorValue< Real > RealTensorValue
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Physical unit management class with runtime unit string parsing, unit checking, unit conversion...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sqrt(_arg)) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tanh
IntRange< T > make_range(T beg, T end)
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type...