https://mooseframework.inl.gov
TransformGenerator.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 "TransformGenerator.h"
11 #include "libmesh/mesh_modification.h"
12 #include "CastUniquePointer.h"
13 
14 #include "libmesh/mesh_tools.h"
15 
17 
20 {
21  MooseEnum transforms("TRANSLATE=1 TRANSLATE_CENTER_ORIGIN=2 TRANSLATE_MIN_ORIGIN=3 ROTATE=4 "
22  "SCALE=5 ROTATE_WITH_MATRIX=6 ROTATE_EXT=7");
23 
25 
26  params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify");
27  params.addClassDescription("Applies a linear transform to the entire mesh.");
29  "transform",
30  transforms,
31  "The type of transformation to perform (TRANSLATE, TRANSLATE_CENTER_ORIGIN, "
32  "TRANSLATE_MIN_ORIGIN, ROTATE, SCALE, ROTATE_WITH_MATRIX, ROTATE_EXT)");
33  params.addParam<RealVectorValue>(
34  "vector_value",
35  "The value to use for the transformation. When using TRANSLATE or SCALE, the "
36  "xyz coordinates are applied in each direction respectively. When using "
37  "ROTATE, the values are interpreted as the Euler angles phi, theta and psi "
38  "given in degrees. For ROTATE_EXT, an extrinsic rotation is carried out using prescribed "
39  "Euler angles alpha, beta, and gamma in degrees.");
40  params.addParam<RealTensorValue>(
41  "rotation_matrix",
42  "Precomputed extrinsic rotation matrix to be applied to mesh (ROTATE_WITH_MATRIX option).");
43 
44  return params;
45 }
46 
48  : MeshGenerator(parameters),
49  _input(getMesh("input")),
50  _transform(getParam<MooseEnum>("transform"))
51 {
52  if ((_transform != "TRANSLATE_CENTER_ORIGIN" && _transform != "TRANSLATE_MIN_ORIGIN" &&
53  _transform != "ROTATE_WITH_MATRIX") &&
54  !isParamValid("vector_value"))
55  paramError("transform",
56  "The parameter 'vector_value' must be supplied with 'transform' = ",
57  _transform);
58 }
59 
60 std::unique_ptr<MeshBase>
62 {
63  std::unique_ptr<MeshBase> mesh = std::move(_input);
64 
65  RealVectorValue vector_value;
66  RealTensorValue rotation_matrix;
67  if (_transform == 2 || _transform == 3)
68  {
69  const auto bbox = MeshTools::create_bounding_box(*mesh);
70  if (_transform == 2)
71  vector_value = -0.5 * (bbox.max() + bbox.min());
72  else
73  vector_value = -bbox.min();
74  }
75  else if (_transform == 6)
76  rotation_matrix = getParam<RealTensorValue>("rotation_matrix");
77  else
78  vector_value = getParam<RealVectorValue>("vector_value");
79 
80  // Any non-identity transform is going to invalidate any existing
81  // point locator
82  mesh->clear_point_locator();
83 
84  switch (_transform)
85  {
86  case 1:
87  case 2:
88  case 3:
89  MeshTools::Modification::translate(*mesh, vector_value(0), vector_value(1), vector_value(2));
90  // libMesh translate() fails to properly mark the spatial
91  // dimension as unprepared in cases where we've displaced a 1D
92  // mesh in y or z or a 2D mesh in z. Until that's fixed we work
93  // around the bug.
94  mesh->unset_has_cached_elem_data();
95  break;
96  case 4:
97  MeshTools::Modification::rotate(*mesh, vector_value(0), vector_value(1), vector_value(2));
98  // libMesh rotate() tries to set the spatial dimension properly,
99  // and probably does for all realistic use cases, but there are
100  // at least hypothetical cases where it could be wrong.
101  //
102  // Until that's fixed we work around it.
103  mesh->unset_has_cached_elem_data();
104  break;
105  case 5:
106  MeshTools::Modification::scale(*mesh, vector_value(0), vector_value(1), vector_value(2));
107  // Is anybody using scale() to just squash a manifold's spatial
108  // dimension down to its mesh dimension? Let's be safe until
109  // libMesh is handling that case.
110  mesh->unset_has_cached_elem_data();
111  break;
112  case 6:
113  TransformGenerator::rotateWithMatrix(*mesh, rotation_matrix);
114  break;
115  case 7:
116  TransformGenerator::rotateExtrinsic(*mesh, vector_value(0), vector_value(1), vector_value(2));
117  break;
118  }
119 
120  mesh->unset_is_prepared();
121  return dynamic_pointer_cast<MeshBase>(mesh);
122 }
123 
124 void
126  const Real alpha,
127  const Real beta,
128  const Real gamma)
129 {
130 #if LIBMESH_DIM == 3
131  const auto R = RealTensorValue::extrinsic_rotation_matrix(
132  alpha, beta, gamma); // this line is the only difference from rotate...
133 
134  // Let's not try to guess what this did to our spatial dimension (it
135  // could have reduced it, depending on the input mesh!), let's just
136  // mark that it needs to be recomputed.
137  mesh.unset_has_cached_elem_data();
138 
139  for (auto & node : mesh.node_ptr_range())
140  {
141  Point & pt = *node;
142  pt = R * pt;
143  }
144 #else
145  libmesh_ignore(mesh, alpha, beta, gamma);
146  libmesh_error_msg(
147  "MeshTools::Modification::rotate() requires libMesh to be compiled with LIBMESH_DIM==3");
148 #endif
149 }
150 
151 void
153  const GenericRealTensorValue<false> & rotation_matrix)
154 {
155 #if LIBMESH_DIM == 3
156  // Let's not try to guess what this did to our spatial dimension,
157  // let's just mark that it needs to be recomputed.
158  mesh.unset_has_cached_elem_data();
159 
160  for (auto & node : mesh.node_ptr_range())
161  {
162  Point & pt = *node;
163  pt = rotation_matrix * pt;
164  }
165 
166 #else
167  libmesh_ignore(mesh, phi, theta, psi);
168  libmesh_error_msg(
169  "MeshTools::Modification::rotate() requires libMesh to be compiled with LIBMESH_DIM==3");
170 #endif
171 }
const MooseEnum _transform
the transform to apply to the mesh
static InputParameters validParams()
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
registerMooseObject("MooseApp", TransformGenerator)
MeshBase & mesh
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
std::unique_ptr< T_DEST, T_DELETER > dynamic_pointer_cast(std::unique_ptr< T_SRC, T_DELETER > &src)
These are reworked from https://stackoverflow.com/a/11003103.
Moose::GenericType< RealTensorValue, is_ad > GenericRealTensorValue
Definition: MooseTypes.h:699
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...
TransformGenerator(const InputParameters &parameters)
TensorValue< Real > RealTensorValue
void libmesh_ignore(const Args &...)
std::unique_ptr< MeshBase > & _input
the input mesh
void rotateExtrinsic(MeshBase &mesh, const Real alpha, const Real beta, const Real gamma)
Rotate the mesh using extrinsic rotation with given angles.
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:54
static InputParameters validParams()
Definition: MeshGenerator.C:23
void rotateWithMatrix(MeshBase &mesh, const GenericRealTensorValue< false > &rotation_matrix)
Rotate a mesh using a given rotation matrix.
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...
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...
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition: MooseBase.h:209
MeshGenerators are objects that can modify or add to an existing mesh.
Definition: MeshGenerator.h:33