include/pops/mesh/index/box2d.hpp Source FileΒΆ

adc_cpp: include/pops/mesh/index/box2d.hpp Source File
adc_cpp 0.3.0
Model-free C++23 core for coupled hyperbolic-elliptic systems on adaptive (AMR) meshes, with MPI and GPU (Kokkos) backends
box2d.hpp
Go to the documentation of this file.
1
12
13#pragma once
14
15#include <pops/core/foundation/types.hpp> // POPS_HD: nx/ny/length called from Geometry::dx() inside a device kernel
16
17#include <algorithm>
18#include <cstdint>
19
20namespace pops {
21
22// Integer division rounded down (toward -inf), consistent on both sides of zero: the only correct
23// division for NEGATIVE indices (ghost layers) during coarsen / spatial hash. C++ division truncates
24// toward zero; we subtract 1 when the remainder is non-zero and of opposite sign to the divisor (the
25// truncated quotient was then rounded up). Shared low-level building block (Box2D coarsen, BoxHash bin
26// hashing, coarse->fine indices in refinement.hpp). b != 0 expected.
28POPS_HD constexpr int floor_div(int a, int b) {
29 const int q = a / b, rem = a % b;
30 return (rem != 0 && ((rem < 0) != (b < 0))) ? q - 1 : q;
31}
32
37struct Box2D {
38 int lo[2]{0, 0};
39 int hi[2]{-1, -1}; // empty by default (hi < lo)
40
42 static Box2D from_extents(int nx, int ny) { return Box2D{{0, 0}, {nx - 1, ny - 1}}; }
43
44 // POPS_HD: Geometry::dx()/dy() (themselves POPS_HD) read domain.nx()/ny(); a device kernel that
45 // calls geom.x_cell(i) descends down to here. Without POPS_HD this is a __host__ from __device__ ->
46 // nvcc yields GARBAGE (often 0) with no error. Pure integer arithmetic, device-safe, host unchanged.
48 POPS_HD int length(int d) const { return hi[d] - lo[d] + 1; }
50 POPS_HD int nx() const { return length(0); }
52 POPS_HD int ny() const { return length(1); }
54 std::int64_t num_cells() const {
55 return static_cast<std::int64_t>(std::max(0, nx())) * std::max(0, ny());
56 }
58 bool empty() const { return hi[0] < lo[0] || hi[1] < lo[1]; }
59
61 bool contains(int i, int j) const { return i >= lo[0] && i <= hi[0] && j >= lo[1] && j <= hi[1]; }
63 bool contains(const Box2D& b) const {
64 return !b.empty() && b.lo[0] >= lo[0] && b.hi[0] <= hi[0] && b.lo[1] >= lo[1] &&
65 b.hi[1] <= hi[1];
66 }
67
69 Box2D grow(int n) const { return {{lo[0] - n, lo[1] - n}, {hi[0] + n, hi[1] + n}}; }
71 Box2D grow(int d, int n) const {
72 Box2D b = *this;
73 b.lo[d] -= n;
74 b.hi[d] += n;
75 return b;
76 }
78 Box2D shift(int d, int s) const {
79 Box2D b = *this;
80 b.lo[d] += s;
81 b.hi[d] += s;
82 return b;
83 }
84
86 Box2D refine(int r) const {
87 return {{lo[0] * r, lo[1] * r}, {hi[0] * r + r - 1, hi[1] * r + r - 1}};
88 }
90 Box2D coarsen(int r) const {
91 return {{floor_div(lo[0], r), floor_div(lo[1], r)}, {floor_div(hi[0], r), floor_div(hi[1], r)}};
92 }
93
95 Box2D intersect(const Box2D& o) const {
96 return {{std::max(lo[0], o.lo[0]), std::max(lo[1], o.lo[1])},
97 {std::min(hi[0], o.hi[0]), std::min(hi[1], o.hi[1])}};
98 }
99
100 bool operator==(const Box2D&) const = default;
101};
102
103} // namespace pops
Definition amr_hierarchy.hpp:29
POPS_HD constexpr int floor_div(int a, int b)
Integer division of a by b rounded down (handles a < 0 AND b < 0). POPS_HD constexpr (kernels).
Definition box2d.hpp:28
2D integer index space, cell-centered.
Definition box2d.hpp:37
bool empty() const
true if the box contains no cell (hi < lo in one direction).
Definition box2d.hpp:58
static Box2D from_extents(int nx, int ny)
Box [0, nx-1] x [0, ny-1] covering nx*ny cells from the index origin.
Definition box2d.hpp:42
Box2D grow(int n) const
Grows the box by n cells in ALL directions (uniform ghost layer).
Definition box2d.hpp:69
Box2D grow(int d, int n) const
Grows by n cells in the SINGLE direction d (n may be negative to shrink).
Definition box2d.hpp:71
POPS_HD int length(int d) const
Number of cells in direction d (= hi[d] - lo[d] + 1); negative if the box is empty....
Definition box2d.hpp:48
POPS_HD int nx() const
Width (direction 0). POPS_HD (called from Geometry::dx() in a device kernel).
Definition box2d.hpp:50
int hi[2]
Definition box2d.hpp:39
Box2D coarsen(int r) const
Coarsens by a ratio r via FLOOR division of each corner (handles the negative ghost indices).
Definition box2d.hpp:90
bool contains(int i, int j) const
true if cell (i, j) is inside the box (lo/hi bounds inclusive).
Definition box2d.hpp:61
POPS_HD int ny() const
Height (direction 1). POPS_HD (called from Geometry::dy() in a device kernel).
Definition box2d.hpp:52
Box2D shift(int d, int s) const
Translates the box by s cells in direction d (lo and hi shifted by the same s).
Definition box2d.hpp:78
int lo[2]
Definition box2d.hpp:38
Box2D refine(int r) const
Refines by a ratio r: each cell becomes an r x r block ([lo, hi] -> [lo*r, hi*r + r-1]).
Definition box2d.hpp:86
Box2D intersect(const Box2D &o) const
Intersection of the two boxes (possibly empty: hi < lo if they do not overlap).
Definition box2d.hpp:95
std::int64_t num_cells() const
Total number of cells (nx*ny, floored at 0 per direction): 0 if the box is empty.
Definition box2d.hpp:54
bool operator==(const Box2D &) const =default
bool contains(const Box2D &b) const
true if box b (non-empty) is entirely contained in *this.
Definition box2d.hpp:63
Base scalar types and the POPS_HD macro (host+device portability).
#define POPS_HD
Definition types.hpp:25