https://mooseframework.inl.gov
CartesianGridDivision.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 "CartesianGridDivision.h"
11 #include "MooseMesh.h"
12 #include "Positions.h"
13 #include "FEProblemBase.h"
14 
15 #include "libmesh/elem.h"
16 
18 
21 {
23  params.addClassDescription("Divide the mesh along a Cartesian grid. Numbering increases from "
24  "bottom to top and from left to right and from back to front. The "
25  "inner ordering is X, then Y, then Z");
26  params.addParam<Point>("bottom_left", "Bottom-back-left corner of the grid");
27  params.addParam<Point>("top_right", "Top-front-right corner of the grid");
28  params.addParam<Point>("center", "Center of the Cartesian grid");
29  params.addParam<PositionsName>("center_positions",
30  "Positions of the centers of divided Cartesian grids");
31  params.addParam<Point>("widths", "Widths in the X, Y and Z directions");
32  params.addRequiredRangeCheckedParam<unsigned int>("nx", "nx>0", "Number of divisions in X");
33  params.addRequiredRangeCheckedParam<unsigned int>("ny", "ny>0", "Number of divisions in Y");
34  params.addRequiredRangeCheckedParam<unsigned int>("nz", "nz>0", "Number of divisions in Z");
35  params.addParam<bool>(
36  "assign_domain_outside_grid_to_border",
37  false,
38  "Whether to map the domain outside the grid back to the border of the grid");
39 
40  return params;
41 }
42 
44  : MeshDivision(parameters),
45  _bottom_left(isParamValid("bottom_left") ? getParam<Point>("bottom_left") : Point(0, 0, 0)),
46  _top_right(isParamValid("top_right") ? getParam<Point>("top_right") : Point(0, 0, 0)),
47  _center(isParamValid("center") ? &getParam<Point>("center") : nullptr),
48  _center_positions(
49  isParamValid("center_positions")
50  ? &_fe_problem->getPositionsObject(getParam<PositionsName>("center_positions"))
51  : nullptr),
52  _widths(isParamValid("widths") ? getParam<Point>("widths") : Point(_top_right - _bottom_left)),
53  _nx(getParam<unsigned int>("nx")),
54  _ny(getParam<unsigned int>("ny")),
55  _nz(getParam<unsigned int>("nz")),
56  _outside_grid_counts_as_border(getParam<bool>("assign_domain_outside_grid_to_border"))
57 {
59 
60  // Check non-overlapping inputs for the dimensions of the grid
61  if ((_center || _center_positions) && (isParamValid("bottom_left") || isParamValid("top_right")))
62  mooseError("Either the center or the edges of the grids must be specified");
63  if ((isParamValid("top_right") + isParamValid("bottom_left") == 1) && !isParamValid("widths"))
64  paramError("bottom_left",
65  "Both bottom_left and top_right must be passed to be able to determine the width");
66 
67  // Pre-determine the bounds if we can
68  if (!_center_positions && _center)
69  {
70  _bottom_left = *_center - _widths / 2;
71  _top_right = *_center + _widths / 2;
72  }
73 
74  // Check widths
75  if (_widths(0) < 0)
76  paramError("top_right",
77  "Top-front-right corner must be right (X axis) of bottom-left-back corner");
78  if (_widths(1) < 0)
79  paramError("top_right",
80  "Top-front-right corner must be in front (Y axis) of bottom-left-back corner");
81  if (_widths(2) < 0)
82  paramError("top_right",
83  "Top-front-right corner must be on top (Z axis) of bottom-left-back corner");
84  if ((_nx > 1) && MooseUtils::absoluteFuzzyEqual(_widths(0), 0))
85  paramError("nx", "Subdivision number must be 1 if width is 0 in X direction");
86  if ((_ny > 1) && MooseUtils::absoluteFuzzyEqual(_widths(1), 0))
87  paramError("ny", "Subdivision number must be 1 if width is 0 in Y direction");
88  if ((_nz > 1) && MooseUtils::absoluteFuzzyEqual(_widths(2), 0))
89  paramError("nz", "Subdivision number must be 1 if width is 0 in Z direction");
90 }
91 
92 void
94 {
95  if (!_center_positions)
97  else
99 
100  // Check that the grid is well-defined
101  if (_center_positions)
102  {
103  Real min_dist = _widths.norm();
105  // Note that if the positions are not co-planar, the distance reported would be bigger but there
106  // could still be an overlap. Looking at min_center_dist is not enough
107  if (MooseUtils::absoluteFuzzyGreaterThan(min_dist, min_center_dist))
108  mooseWarning(
109  "Cartesian grids centered on the positions are too close to each other (min distance: ",
110  min_center_dist,
111  "), closer than the extent of each grid. Mesh division is ill-defined");
112  }
113 
114  // Examine mesh bounding box to see if the mesh may not be fully contained
115  _mesh_fully_indexed = true;
117  for (auto i : make_range(LIBMESH_DIM))
118  {
119  if (_center_positions)
120  {
121  _mesh_fully_indexed = false;
122  break;
123  }
124  else if (_bottom_left(i) > _mesh.getInflatedProcessorBoundingBox(0).first(i) ||
126  {
127  _mesh_fully_indexed = false;
128  break;
129  }
130  }
131 }
132 
133 unsigned int
134 CartesianGridDivision::divisionIndex(const Elem & elem) const
135 {
136  return divisionIndex(elem.vertex_average());
137 }
138 
139 unsigned int
141 {
142  unsigned int offset = 0;
143  // Determine the local grid bounds
144  Point bottom_left, top_right, p;
145  if (_center_positions)
146  {
147  // If dividing using positions, find the closest position and
148  // look at the relative position of the point compared to that position
149  const bool initial = _fe_problem->getCurrentExecuteOnFlag() == EXEC_INITIAL;
150  const auto nearest_grid_center_index = _center_positions->getNearestPositionIndex(pt, initial);
151  offset = nearest_grid_center_index * _nx * _ny * _nz;
152  const auto nearest_grid_center =
153  _center_positions->getPosition(nearest_grid_center_index, initial);
154  bottom_left = -_widths / 2;
155  top_right = _widths / 2;
156  p = pt - nearest_grid_center;
157  }
158  else
159  {
160  bottom_left = _bottom_left;
161  top_right = _top_right;
162  p = pt;
163  }
164 
166  {
167  if (MooseUtils::absoluteFuzzyLessThan(p(0), bottom_left(0)) ||
168  MooseUtils::absoluteFuzzyGreaterThan(p(0), top_right(0)))
170  if (MooseUtils::absoluteFuzzyLessThan(p(1), bottom_left(1)) ||
171  MooseUtils::absoluteFuzzyGreaterThan(p(1), top_right(1)))
173  if (MooseUtils::absoluteFuzzyLessThan(p(2), bottom_left(2)) ||
174  MooseUtils::absoluteFuzzyGreaterThan(p(2), top_right(2)))
176  }
177 
178  const auto not_found = MooseMeshDivision::INVALID_DIVISION_INDEX;
179  auto ix = not_found, iy = not_found, iz = not_found;
180 
181  // Look inside the grid and on the left / back / bottom
182  for (const auto jx : make_range(_nx + 1))
183  {
184  const auto border_x = bottom_left(0) + _widths(0) * jx / _nx;
185  if (jx > 0 && jx < _nx && MooseUtils::absoluteFuzzyEqual(border_x, p(0)))
186  mooseWarning(
187  "Querying the division index for a point of a boundary between two regions in X: " +
188  Moose::stringify(p));
189  if (border_x >= p(0))
190  {
191  ix = (jx > 0) ? jx - 1 : 0;
192  break;
193  }
194  }
195  for (const auto jy : make_range(_ny + 1))
196  {
197  const auto border_y = bottom_left(1) + _widths(1) * jy / _ny;
198  if (jy > 0 && jy < _ny && MooseUtils::absoluteFuzzyEqual(border_y, p(1)))
199  mooseWarning(
200  "Querying the division index for a point of a boundary between two regions in Y: " +
201  Moose::stringify(p));
202  if (border_y >= p(1))
203  {
204  iy = (jy > 0) ? jy - 1 : 0;
205  break;
206  }
207  }
208  for (const auto jz : make_range(_nz + 1))
209  {
210  const auto border_z = bottom_left(2) + _widths(2) * jz / _nz;
211  if (jz > 0 && jz < _nz && MooseUtils::absoluteFuzzyEqual(border_z, p(2)))
212  mooseWarning(
213  "Querying the division index for a point of a boundary between two regions in Z: " +
214  Moose::stringify(p));
215  if (border_z >= p(2))
216  {
217  iz = (jz > 0) ? jz - 1 : 0;
218  break;
219  }
220  }
221 
222  // Look on the right / front / top of the grid
223  if (MooseUtils::absoluteFuzzyGreaterEqual(p(0), top_right(0)))
224  ix = _nx - 1;
225  if (MooseUtils::absoluteFuzzyGreaterEqual(p(1), top_right(1)))
226  iy = _ny - 1;
227  if (MooseUtils::absoluteFuzzyGreaterEqual(p(2), top_right(2)))
228  iz = _nz - 1;
229 
230  // Handle edge case on widths
231  if (ix == not_found && MooseUtils::absoluteFuzzyEqual(_widths(0), 0))
232  ix = 0;
233  if (iy == not_found && MooseUtils::absoluteFuzzyEqual(_widths(1), 0))
234  iy = 0;
235  if (iz == not_found && MooseUtils::absoluteFuzzyEqual(_widths(2), 0))
236  iz = 0;
237  mooseAssert(ix != not_found, "We should have found a mesh division bin in X");
238  mooseAssert(iy != not_found, "We should have found a mesh division bin in Y");
239  mooseAssert(iz != not_found, "We should have found a mesh division bin in Z");
240 
241  return offset + ix + _nx * iy + iz * _nx * _ny;
242 }
virtual unsigned int divisionIndex(const Point &pt) const override
Return the index of the division to which the point belongs.
void addRequiredRangeCheckedParam(const std::string &name, const std::string &parsed_function, const std::string &doc_string)
These methods add an range checked parameters.
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.
Definition: MooseUtils.h:380
Point _top_right
Top right point of the grid.
const ExecFlagType & getCurrentExecuteOnFlag() const
Return/set the current execution flag.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
Divides the mesh based on a Cartesian grid.
const Point _widths
Width of the grid in all 3 axes.
const Point & getPosition(unsigned int index, bool initial) const
Getter for a single position at a known index.
Definition: Positions.C:59
const Point *const _center
Center of the grid, if user-specified.
Base class for MeshDivision objects.
Definition: MeshDivision.h:35
const MooseMesh & _mesh
Mesh that is being divided.
Definition: MeshDivision.h:74
void mooseWarning(Args &&... args) const
Emits a warning prefixed with object name and type.
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
unsigned int getNearestPositionIndex(const Point &target, bool initial) const
Find the nearest Position index for a given point.
Definition: Positions.C:96
const bool _outside_grid_counts_as_border
Whether to map outside the grid onto the corner.
Point _bottom_left
Bottom left point of the grid.
const unsigned int _nx
Number of divisions in the X direction.
virtual void initialize() override
Set up any data members that would be necessary to obtain the division indices.
bool absoluteFuzzyLessThan(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Function to check whether a variable is less than another variable within an absolute tolerance...
Definition: MooseUtils.h:475
unsigned int getNumPositions(bool initial=false) const
}
Definition: Positions.h:37
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 ...
std::string stringify(const T &t)
conversion to string
Definition: Conversion.h:64
unsigned int INVALID_DIVISION_INDEX
Invalid subdomain id to return when outside the mesh division.
Definition: MeshDivision.h:28
static InputParameters validParams()
bool _mesh_fully_indexed
Whether the mesh is fully covered / indexed, all elements and points have a valid index...
Definition: MeshDivision.h:77
void setNumDivisions(const unsigned int ndivs)
Set the number of divisions.
Definition: MeshDivision.h:65
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
CartesianGridDivision(const InputParameters &parameters)
const unsigned int _ny
Number of divisions in the Y direction.
const FEProblemBase *const _fe_problem
Pointer to the problem, needed to retrieve pointers to various objects.
Definition: MeshDivision.h:71
IntRange< T > make_range(T beg, T end)
libMesh::BoundingBox getInflatedProcessorBoundingBox(Real inflation_multiplier=0.01) const
Get a (slightly inflated) processor bounding box.
Definition: MooseMesh.C:3414
bool absoluteFuzzyGreaterEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Function to check whether a variable is greater than or equal to another variable within an absolute ...
Definition: MooseUtils.h:404
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
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...
const Positions *const _center_positions
Positions object holding the centers of the grids, if user-specified.
Real getMinDistanceBetweenPositions() const
Find the minimum distance between positions.
Definition: Positions.C:242
static InputParameters validParams()
Class constructor.
Definition: MeshDivision.C:14
void ErrorVector unsigned int
bool absoluteFuzzyGreaterThan(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Function to check whether a variable is greater than another variable within an absolute tolerance...
Definition: MooseUtils.h:428
const unsigned int _nz
Number of divisions in the Z direction.
registerMooseObject("MooseApp", CartesianGridDivision)
const ExecFlagType EXEC_INITIAL
Definition: Moose.C:28