40 UniformGrid3(
const double lower[3],
const double spacing[3],
const int numCells[3],
const T& initial = T {})
43 for (
int a = 0; a < 3; ++a) {
44 if (!(spacing[a] > 0.0))
45 throw std::invalid_argument(
"UniformGrid3: the spacing must be positive");
47 throw std::invalid_argument(
"UniformGrid3: the number of cells must be at least 1");
48 m_lower[a] = lower[a];
49 m_spacing[a] = spacing[a];
50 m_numCells[a] = numCells[a];
51 const std::size_t nodes =
static_cast<std::size_t
>(numCells[a]) + 1;
52 if (size > std::vector<T>().max_size() / nodes)
53 throw std::invalid_argument(
"UniformGrid3: too many nodes");
56 m_values.assign(size, initial);
60 int NumCells(
int axis)
const {
return m_numCells[axis]; }
63 double Spacing(
int axis)
const {
return m_spacing[axis]; }
66 double NodeCoordinate(
int axis,
int index)
const {
return m_lower[axis] + index * m_spacing[axis]; }
69 T&
At(
int i,
int j,
int k) {
return m_values[Index(i, j, k)]; }
72 const T&
At(
int i,
int j,
int k)
const {
return m_values[Index(i, j, k)]; }
85 for (
int a = 0; a < 3; ++a) {
86 const double scaled = (pos[a] - m_lower[a]) / m_spacing[a];
87 if (!(scaled >= -boundarySlack && scaled <= m_numCells[a] + boundarySlack))
107 for (
int a = 0; a < 3; ++a) {
108 const double scaled = std::clamp((pos[a] - m_lower[a]) / m_spacing[a], 0.0,
static_cast<double>(m_numCells[a]));
109 cell[a] = std::min(
static_cast<int>(std::floor(scaled)), m_numCells[a] - 1);
110 fraction[a] = scaled - cell[a];
113 for (
int corner = 0; corner < 8; ++corner) {
116 for (
int a = 0; a < 3; ++a) {
117 const bool upper = (corner >> a) & 1;
118 node[a] = cell[a] + (upper ? 1 : 0);
119 weight *= upper ? fraction[a] : 1.0 - fraction[a];
121 sum = sum + weight *
At(node[0], node[1], node[2]);
128 static constexpr double boundarySlack = 1e-9;
130 std::size_t Index(
int i,
int j,
int k)
const
132 const std::size_t numX =
static_cast<std::size_t
>(m_numCells[0] + 1);
133 const std::size_t numY =
static_cast<std::size_t
>(m_numCells[1] + 1);
134 return static_cast<std::size_t
>(i) + numX * (
static_cast<std::size_t
>(j) + numY *
static_cast<std::size_t
>(k));
137 double m_lower[3] = {0.0, 0.0, 0.0};
138 double m_spacing[3] = {1.0, 1.0, 1.0};
139 int m_numCells[3] = {0, 0, 0};
140 std::vector<T> m_values;