https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
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
69 {
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
92void
94{
97 else
99
100 // Check that the grid is well-defined
102 {
103 Real min_dist = _widths.norm();
104 Real min_center_dist = _center_positions->getMinDistanceBetweenPositions();
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))
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(Moose::dim))
118 {
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
133unsigned int
135{
136 return divisionIndex(elem.vertex_average());
137}
138
139unsigned int
141{
142 unsigned int offset = 0;
143 // Determine the local grid bounds
144 Point bottom_left, top_right, p;
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)))
187 "Querying the division index for a point of a boundary between two regions in X: " +
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)))
200 "Querying the division index for a point of a boundary between two regions in Y: " +
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)))
213 "Querying the division index for a point of a boundary between two regions in Z: " +
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}
registerMooseObject("MooseApp", CartesianGridDivision)
const ExecFlagType EXEC_INITIAL
Definition Moose.C:30
void ErrorVector unsigned int
Divides the mesh based on a Cartesian grid.
virtual void initialize() override
Set up any data members that would be necessary to obtain the division indices.
const Positions *const _center_positions
Positions object holding the centers of the grids, if user-specified.
const unsigned int _nx
Number of divisions in the X direction.
const bool _outside_grid_counts_as_border
Whether to map outside the grid onto the corner.
virtual unsigned int divisionIndex(const Point &pt) const override
Return the index of the division to which the point belongs.
CartesianGridDivision(const InputParameters &parameters)
const Point _widths
Width of the grid in all 3 axes.
const unsigned int _ny
Number of divisions in the Y direction.
const unsigned int _nz
Number of divisions in the Z direction.
const Point *const _center
Center of the grid, if user-specified.
Point _bottom_left
Bottom left point of the grid.
Point _top_right
Top right point of the grid.
static InputParameters validParams()
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.
void addRequiredRangeCheckedParam(const std::string &name, const std::string &parsed_function, const std::string &doc_string)
These methods add an range checked parameters.
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 addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump.
Base class for MeshDivision objects.
static InputParameters validParams()
Class constructor.
const FEProblemBase *const _fe_problem
Pointer to the problem, needed to retrieve pointers to various objects.
void setNumDivisions(const unsigned int ndivs)
Set the number of divisions.
const MooseMesh & _mesh
Mesh that is being divided.
bool _mesh_fully_indexed
Whether the mesh is fully covered / indexed, all elements and points have a valid index.
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
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition MooseBase.h:271
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition MooseBase.h:199
libMesh::BoundingBox getInflatedProcessorBoundingBox(Real inflation_multiplier=0.01) const
Get a (slightly inflated) processor bounding box.
Definition MooseMesh.C:3520
const Point & getPosition(unsigned int index, bool initial) const
Getter for a single position at a known index.
Definition Positions.C:59
unsigned int getNearestPositionIndex(const Point &target, bool initial) const
Find the nearest Position index for a given point.
Definition Positions.C:96
unsigned int getNumPositions(bool initial=false) const
}
Definition Positions.h:37
Real getMinDistanceBetweenPositions() const
Find the minimum distance between positions.
Definition Positions.C:242
void mooseWarning(Args &&... args) const
unsigned int INVALID_DIVISION_INDEX
Invalid subdomain id to return when outside the mesh division.
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition Moose.h:165
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:64