66 const int nel = mesh.
GetNE();
68 Vector elmin(nel*sdim), elmax(nel*sdim);
69 elmin = numeric_limits<real_t>::max();
70 elmax = -numeric_limits<real_t>::max();
76 for (
int e = 0; e < nel; e++)
79 for (
int v = 0; v < verts.
Size(); v++)
82 for (
int d = 0; d < sdim; d++)
84 elmin(d*nel + e) = min(elmin(d*nel + e), coord[d]);
85 elmax(d*nel + e) = max(elmax(d*nel + e), coord[d]);
93 nodes->GetElementBounds(elmin, elmax, nref);
97 Setup(elmin, elmax, nel, nx_arr,
false);
108 MFEM_VERIFY(0 < sdim && sdim <= 3,
109 "BBoxTensorGridMap only supports spatial dimensions 1, 2, and 3.");
112 MFEM_VERIFY(elmin.
Size() == sdim * nel && elmax.
Size() == sdim * nel,
113 "Element bounds size must match dim * nel.");
117 Setup(elmin, elmax, nel, nx_arr, by_max_size);
126 Setup(elmin, elmax, nel, nx, by_max_size);
129void BBoxTensorGridMap::Setup(
Vector &elmin,
Vector &elmax,
132 MFEM_VERIFY(0 < sdim && sdim <= 3,
133 "BBoxTensorGridMap only supports spatial dimensions 1, 2, and 3.");
134 MFEM_VERIFY(nx.
Size() == sdim,
135 "BBoxTensorGridMap requires nx to have the same size as the number of dimensions.");
138 MFEM_VERIFY(elmin.
Size() == sdim * nel && elmax.
Size() == sdim * nel,
139 "Element bounds size must match dim * nel.");
149 MFEM_VERIFY(nx[0] >= 0,
150 "BBoxTensorGridMap requires a nonnegative max-size hint.");
154 for (
int d = 0; d < nx.
Size(); d++)
156 MFEM_VERIFY(nx[d] > 0,
157 "BBoxTensorGridMap requires positive number of divisions in each dimension.");
164 if (by_max_size) { lmap_nx = 1; }
165 SetGridFac(lmap_fac, lmap_nx, lmap_bnd_min, lmap_bnd_max);
167 lmap_nxd = lmap_nx[0];
168 for (
int d = 1; d < sdim; d++)
170 lmap_nxd *= lmap_nx[d];
173 lgrid_map.
SetSize(lmap_nxd + 1);
174 lgrid_map = lmap_nxd + 1;
178 for (
int d = 0; d < sdim; d++)
180 Vector elmind(elmin.
GetData() + d*nel, nel);
181 Vector elmaxd(elmax.
GetData() + d*nel, nel);
182 lmap_bnd_min[d] = elmind.
Min();
183 lmap_bnd_max[d] = elmaxd.
Max();
186 Array<int> elmin_h, elmax_h;
187 unsigned int store_size;
191 int nlow = 1, nhigh = nmax > nel ? ceil(
pow(nmax - nel, 1.0 / sdim)) : 1;
192 int size_low = 2 + nel;
194 while (nhigh - nlow > 1)
196 int nmid = nlow + (nhigh - nlow) / 2;
198 for (
int d = 1; d < sdim; d++)
203 SetGridFac(lmap_fac, lmap_nx, lmap_bnd_min, lmap_bnd_max);
205 lmap_bnd_min, lmap_bnd_max,
208 if (size <= nmax) { nlow = nmid; size_low = size; }
209 else { nhigh = nmid; }
213 for (
int d = 1; d < sdim; d++)
217 store_size = size_low;
218 SetGridFac(lmap_fac, lmap_nx, lmap_bnd_min, lmap_bnd_max);
219 if (size != size_low)
222 lmap_bnd_min, lmap_bnd_max,
229 SetGridFac(lmap_fac, lmap_nx, lmap_bnd_min, lmap_bnd_max);
231 lmap_nxd = lmap_nx[0];
232 for (
int d = 1; d < sdim; d++)
234 lmap_nxd *= lmap_nx[d];
246 lgrid_map[0] = lmap_nxd + 1;
248 Array<unsigned int> grid_el_count(lmap_nxd);
251 for (
int e = 0; e < nel; e++)
253 int klim = sdim < 3 ? 1 : (elmax_h[2*nel+e]-elmin_h[2*nel+e]);
254 int jlim = sdim < 2 ? 1 : (elmax_h[1*nel+e]-elmin_h[1*nel+e]);
255 int ilim = (elmax_h[0*nel+e]-elmin_h[0*nel+e]);
256 for (
int k = 0; k < klim; k++)
258 int koff = sdim < 3 ? 0 :
259 (elmin_h[2*nel + e] + k) * lmap_nx[0] * lmap_nx[1];
260 for (
int j = 0; j < jlim; j++)
262 int joff = sdim < 2 ? 0 : (elmin_h[1*nel + e] + j) * lmap_nx[0];
263 for (
int i = 0; i < ilim; i++)
265 int ioff = elmin_h[e] + i;
266 int idx = ioff + joff + koff;
267 grid_el_count[idx]++;
273 for (
unsigned int e = 0; e < lmap_nxd; e++)
275 lgrid_map[e + 1] = lgrid_map[e] + grid_el_count[e];
278 for (
int e = 0; e < nel; e++)
280 int klim = sdim < 3 ? 1 : (elmax_h[2*nel+e]-elmin_h[2*nel+e]);
281 int jlim = sdim < 2 ? 1 : (elmax_h[1*nel+e]-elmin_h[1*nel+e]);
282 int ilim = (elmax_h[0*nel+e]-elmin_h[0*nel+e]);
283 for (
int k = 0; k < klim; k++)
285 int koff = sdim < 3 ? 0 :
286 (elmin_h[2*nel+e] + k) * lmap_nx[0] * lmap_nx[1];
287 for (
int j = 0; j < jlim; j++)
289 int joff = sdim < 2 ? 0 : (elmin_h[1*nel + e] + j) * lmap_nx[0];
290 for (
int i = 0; i < ilim; i++)
292 int ioff = elmin_h[e] + i;
293 int idx = ioff + joff + koff;
294 lgrid_map[lgrid_map[idx+1]-grid_el_count[idx]]=e;
295 grid_el_count[idx]--;
304 MFEM_ASSERT(i >= 0 && (
unsigned int)i < lmap_nxd,
305 "Access element " << i <<
" of local grid with cells = "
307 int start = lgrid_map[i];
308 int end = lgrid_map[i + 1];
310 for (
int j = start; j < end; j++)
312 elements[j - start] = lgrid_map[j];
319 MFEM_ASSERT(xyz.
Size() == sdim,
320 "Point must have the same dimension as the grid.");
322 for (
int d = sdim-1; d >= 0; --d)
324 if (xyz(d) < lmap_bnd_min(d) || xyz(d) > lmap_bnd_max(d))
329 int i = (int)floor((xyz(d) - lmap_bnd_min(d)) * lmap_fac[d]);
330 sum += i < 0 ? 0 : (lmap_nx[d] - 1 < i ? lmap_nx[d] - 1 : i);
337 MFEM_ASSERT(xyz.
Size() == sdim,
338 "Point must have the same dimension as the grid.");
351 int &imin,
int &imax)
357 int i0 = floor( (xmin - lh_bnd_min[d]) * lh_fac[d] );
358 int i1 = ceil ( (xmax - lh_bnd_min[d]) * lh_fac[d] );
359 imin = std::clamp(i0, 0, lh_n[d] - 1);
360 imax = std::clamp(i1, imin + 1, lh_n[d]);
368 for (
int d = 0; d <
dim; d++)
370 real_t length = lh_bnd_max[d] - lh_bnd_min[d];
373 lh_fac[d] = nx[d] / length;
392 const int dim = lh_bnd_min.
Size();
393 const int nel = elmin.
Size()/
dim;
396 for (
int i = 0; i < nel; i++)
399 for (
int d = 0; d <
dim; d++)
402 elmin[d*nel + i], elmax[d*nel + i],
403 elmin_h[d*nel + i], elmax_h[d*nel + i]);
404 int imax = elmax_h[d*nel + i];
405 int imin = elmin_h[d*nel + i];
406 count_el *= (imax - imin);
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int Size() const
Return the logical size of the array.
Array< int > GridCellToElements(int i) const
Get list of elements corresponding to a grid cell.
static void GetGridRange(const int d, const Array< int > &lh_n, const Vector &lh_fac, const Vector &lh_bnd_min, const real_t &xmin, const real_t &xmax, int &imin, int &imax)
Get local (1D) indices for cells of tensor grid that intersect with the given bounding box.
int GetGridCellFromPoint(Vector &xyz) const
Get grid cell index for a given point.
BBoxTensorGridMap(Mesh &mesh, int nx)
Constructor for a given mesh and resolution of Cartesian grid.
static void SetGridFac(Vector &lh_fac, const Array< int > &nx, const Vector &lh_bnd_min, const Vector &lh_bnd_max)
Set grid fac - number of grid cells per unit grid extent.
static int GetGridCountAndRange(const Array< int > &lh_n, const Vector &lh_fac, const Vector &lh_bnd_min, const Vector &lh_bnd_max, const Vector &elmin, const Vector &elmax, Array< int > &elmin_h, Array< int > &elmax_h)
Get grid count and range - total number of grid cells that intersect with all elements of the mesh an...
Array< int > MapPointToElements(Vector &xyz) const
Map a point to possible overlapping elements.
Class for grid function - Vector with associated FE space.
void GetElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of element i.
int GetNE() const
Returns number of elements.
int SpaceDimension() const
Dimension of the physical space containing the mesh.
void GetNodes(Vector &node_coord) const
const real_t * GetVertex(int i) const
Return pointer to vertex i's coordinates.
real_t Max() const
Returns the maximal element of the vector.
int Size() const
Returns the size of the vector.
void SetSize(int s)
Resize the vector to size s.
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
real_t Min() const
Returns the minimal element of the vector.
MFEM_HOST_DEVICE dual< value_type, gradient_type > pow(dual< value_type, gradient_type > a, dual< value_type, gradient_type > b)
implementation of a (dual) raised to the b (dual) power
std::array< int, NCMesh::MaxFaceNodes > nodes