OGS
MeshElementGrid.cpp
Go to the documentation of this file.
1/*
2 * \file
3 * \brief Definition of the class MeshElementGrid.
4 *
5 * \copyright
6 * Copyright (c) 2012-2024, OpenGeoSys Community (http://www.opengeosys.org)
7 * Distributed under a Modified BSD License.
8 * See accompanying file LICENSE.txt or
9 */
10
11#include "MeshElementGrid.h"
12
13#include <algorithm>
14#include <bitset>
15#include <cmath>
16#include <memory>
17
19#include "MeshLib/Mesh.h"
20#include "MeshLib/Node.h"
21
22namespace MeshLib
23{
25 : _aabb{mesh.getNodes().cbegin(), mesh.getNodes().cend()},
26 _n_steps({{1, 1, 1}})
27{
28 auto getDimensions = [](auto const& min, auto const& max)
29 {
30 std::bitset<3> dim; // all bits are set to zero.
31 for (std::size_t k(0); k < 3; ++k)
32 {
33 double const tolerance(
34 std::nexttoward(max[k], std::numeric_limits<double>::max()) -
35 max[k]);
36 if (std::abs(max[k] - min[k]) > tolerance)
37 {
38 dim[k] = true;
39 }
40 }
41 return dim;
42 };
43
44 auto const [min_pnt, max_pnt] = _aabb.getMinMaxPoints();
45 auto const dim = getDimensions(min_pnt, max_pnt);
46
47 std::array<double, 3> const delta{{max_pnt[0] - min_pnt[0],
48 max_pnt[1] - min_pnt[1],
49 max_pnt[2] - min_pnt[2]}};
50
51 const std::size_t n_eles(mesh.getNumberOfElements());
52 const std::size_t n_eles_per_cell(100);
53
54 // *** condition: n_eles / n_cells < n_eles_per_cell
55 // where n_cells = _n_steps[0] * _n_steps[1] * _n_steps[2]
56 // *** with _n_steps[0] =
57 // ceil(pow(n_eles*delta[0]*delta[0]/(n_eles_per_cell*delta[1]*delta[2]),
58 // 1/3.)));
59 // _n_steps[1] = _n_steps[0] * delta[1]/delta[0],
60 // _n_steps[2] = _n_steps[0] * delta[2]/delta[0]
61 auto sc_ceil = [](double v)
62 { return static_cast<std::size_t>(std::ceil(v)); };
63
64 switch (dim.count())
65 {
66 case 3: // 3d case
67 _n_steps[0] =
68 sc_ceil(std::cbrt(n_eles * delta[0] * delta[0] /
69 (n_eles_per_cell * delta[1] * delta[2])));
70 _n_steps[1] =
71 sc_ceil(_n_steps[0] * std::min(delta[1] / delta[0], 100.0));
72 _n_steps[2] =
73 sc_ceil(_n_steps[0] * std::min(delta[2] / delta[0], 100.0));
74 break;
75 case 2: // 2d cases
76 if (dim[0] && dim[2])
77 { // 2d case: xz plane, y = const
78 _n_steps[0] = sc_ceil(std::sqrt(n_eles * delta[0] /
79 (n_eles_per_cell * delta[2])));
80 _n_steps[2] = sc_ceil(_n_steps[0] * delta[2] / delta[0]);
81 }
82 else if (dim[0] && dim[1])
83 { // 2d case: xy plane, z = const
84 _n_steps[0] = sc_ceil(std::sqrt(n_eles * delta[0] /
85 (n_eles_per_cell * delta[1])));
86 _n_steps[1] = sc_ceil(_n_steps[0] * delta[1] / delta[0]);
87 }
88 else if (dim[1] && dim[2])
89 { // 2d case: yz plane, x = const
90 _n_steps[1] = sc_ceil(std::sqrt(n_eles * delta[1] /
91 (n_eles_per_cell * delta[2])));
92 _n_steps[2] =
93 sc_ceil(n_eles * delta[2] / (n_eles_per_cell * delta[1]));
94 }
95 break;
96 case 1: // 1d cases
97 for (std::size_t k(0); k < 3; ++k)
98 {
99 if (dim[k])
100 {
101 _n_steps[k] =
102 sc_ceil(static_cast<double>(n_eles) / n_eles_per_cell);
103 }
104 }
105 }
106
107 // some frequently used expressions to fill the vector of elements per grid
108 // cell
109 for (std::size_t k(0); k < 3; k++)
110 {
111 _step_sizes[k] = delta[k] / _n_steps[k];
112 _inverse_step_sizes[k] = 1.0 / _step_sizes[k];
113 }
114
115 _elements_in_grid_box.resize(_n_steps[0] * _n_steps[1] * _n_steps[2]);
116 sortElementsInGridCells(mesh);
117}
118
119Eigen::Vector3d const& MeshElementGrid::getMinPoint() const
120{
121 return _aabb.getMinPoint();
122}
123
124Eigen::Vector3d const& MeshElementGrid::getMaxPoint() const
125{
126 return _aabb.getMaxPoint();
127}
128
130{
131 for (auto const element : mesh.getElements())
132 {
133 if (!sortElementInGridCells(*element))
134 {
135 OGS_FATAL("Sorting element (id={:d}) into mesh element grid.",
136 element->getID());
137 }
138 }
139}
140
142{
143 std::array<std::size_t, 3> min{};
144 std::array<std::size_t, 3> max{};
145 std::pair<bool, std::array<std::size_t, 3>> c(getGridCellCoordinates(
146 *(static_cast<MathLib::Point3d const*>(element.getNode(0)))));
147 if (c.first)
148 {
149 min = c.second;
150 max = min;
151 }
152 else
153 {
154 return false;
155 }
156
157 for (std::size_t k(1); k < element.getNumberOfNodes(); ++k)
158 {
159 // compute coordinates of the grid for each node of the element
161 *(static_cast<MathLib::Point3d const*>(element.getNode(k))));
162 if (!c.first)
163 {
164 return false;
165 }
166
167 for (std::size_t j(0); j < 3; ++j)
168 {
169 if (min[j] > c.second[j])
170 {
171 min[j] = c.second[j];
172 }
173 if (max[j] < c.second[j])
174 {
175 max[j] = c.second[j];
176 }
177 }
178 }
179
180 const std::size_t n_plane(_n_steps[0] * _n_steps[1]);
181
182 // If a node of an element is almost equal to the upper right point of the
183 // AABB the grid cell coordinates computed by getGridCellCoordintes() could
184 // be to large (due to numerical errors). The following lines ensure that
185 // the grid cell coordinates are in the valid range.
186 for (std::size_t k(0); k < 3; ++k)
187 {
188 max[k] = std::min(_n_steps[k] - 1, max[k]);
189 }
190
191 // insert the element into the grid cells
192 for (std::size_t i(min[0]); i <= max[0]; i++)
193 {
194 for (std::size_t j(min[1]); j <= max[1]; j++)
195 {
196 for (std::size_t k(min[2]); k <= max[2]; k++)
197 {
198 _elements_in_grid_box[i + j * _n_steps[0] + k * n_plane]
199 .push_back(&element);
200 }
201 }
202 }
203
204 return true;
205}
206
207std::pair<bool, std::array<std::size_t, 3>>
209{
210 bool valid(true);
211 std::array<std::size_t, 3> coords{};
212
213 for (std::size_t k(0); k < 3; ++k)
214 {
215 const double d(p[k] - _aabb.getMinPoint()[k]);
216 if (d < 0.0)
217 {
218 valid = false;
219 coords[k] = 0;
220 }
221 else if (_aabb.getMaxPoint()[k] <= p[k])
222 {
223 valid = false;
224 coords[k] = _n_steps[k] - 1;
225 }
226 else
227 {
228 coords[k] = static_cast<std::size_t>(d * _inverse_step_sizes[k]);
229 }
230 }
231
232 return std::make_pair(valid, coords);
233}
234} // namespace MeshLib
Definition of the Element class.
#define OGS_FATAL(...)
Definition Error.h:26
std::vector< std::size_t > getNodes(GeoLib::Point const &pnt, std::vector< MeshLib::Node * > const &nodes, MeshLib::PropertyVector< int > const &mat_ids, std::pair< int, int > const &mat_limits, std::pair< double, double > const &elevation_limits, MeshLib::Mesh const &mesh)
Definition of the Mesh class.
Definition of the Node class.
std::pair< std::size_t, std::size_t > getDimensions(std::string const &line)
Returns raster dimensions from the "Zone"-description.
Eigen::Vector3d const & getMaxPoint() const
Definition AABB.h:187
Eigen::Vector3d const & getMinPoint() const
Definition AABB.h:180
virtual unsigned getNumberOfNodes() const =0
virtual const Node * getNode(unsigned idx) const =0
void sortElementsInGridCells(MeshLib::Mesh const &mesh)
std::vector< std::vector< MeshLib::Element const * > > _elements_in_grid_box
MeshElementGrid(MeshLib::Mesh const &mesh)
std::pair< bool, std::array< std::size_t, 3 > > getGridCellCoordinates(MathLib::Point3d const &p) const
bool sortElementInGridCells(MeshLib::Element const &element)
Eigen::Vector3d const & getMinPoint() const
std::array< double, 3 > _inverse_step_sizes
std::array< std::size_t, 3 > _n_steps
Eigen::Vector3d const & getMaxPoint() const
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
Definition Mesh.h:109