24 for (
int i = 0; i < N; ++i) {
25 for (
int j = 0; j < N; ++j) {
44 for (
int i = 0; i < N; ++i) {
45 int ip = (i + 1) % N, im = (i + N - 1) % N;
46 const T* row = x.
data() + (i * N);
47 const T* row_p = x.
data() + (ip * N);
48 const T* row_m = x.
data() + (im * N);
49 T* d = y.
data() + (i * N);
51 d[0] = row_p[0] + row_m[0] + row[1] + row[N - 1] - (T(4) * row[0]);
52 for (
int j = 1; j < N - 1; ++j) {
53 d[j] = row_p[j] + row_m[j] + row[j + 1] + row[j - 1] - (T(4) * row[j]);
55 d[N - 1] = row_p[N - 1] + row_m[N - 1] + row[0] + row[N - 2] - (T(4) * row[N - 1]);
69 for (
int i = 0; i < N; ++i) {
70 for (
int j = 0; j < N; ++j) {
72 T val = T(-30) * x[k];
75 val += T(16) * x[((i - 1) * N) + j];
78 val += T(16) * x[((i + 1) * N) + j];
82 val -= x[((i - 2) * N) + j];
85 val -= x[((i + 2) * N) + j];
89 val += T(16) * x[k - 1];
92 val += T(16) * x[k + 1];
133 real fx = std::fmod((px - ox) / h,
static_cast<real>(N));
134 real fy = std::fmod((py - oy) / h,
static_cast<real>(N));
139 idx i0 =
static_cast<idx>(fx) % N;
140 idx i1 = (i0 + 1) % N;
141 real fi = fx - std::floor(fx);
142 idx j0 =
static_cast<idx>(fy) % N;
143 idx j1 = (j0 + 1) % N;
144 real fj = fy - std::floor(fy);
145 return (1 - fi) * (1 - fj) * field[i0 * N + j0] + fi * (1 - fj) * field[i1 * N + j0]
146 + (1 - fi) * fj * field[i0 * N + j1] + fi * fj * field[i1 * N + j1];
150template<
typename T,
typename F>
152 std::vector<T> fiber(N);
153 for (
int j = 0; j < N; ++j) {
154 for (
int i = 0; i < N; ++i)
155 fiber[i] = data[i * N + j];
157 for (
int i = 0; i < N; ++i)
158 data[i * N + j] = fiber[i];
163template<
typename T,
typename F>
165 std::vector<T> fiber(N);
166 for (
int i = 0; i < N; ++i) {
167 for (
int j = 0; j < N; ++j)
168 fiber[j] = data[i * N + j];
170 for (
int j = 0; j < N; ++j)
171 data[i * N + j] = fiber[j];
178 for (
int i = 0; i < N; ++i) {
179 double xi = (i + 1) * h;
180 for (
int j = 0; j < N; ++j) {
181 u[
static_cast<std::size_t
>(i) * N + j] = f(xi, (j + 1) * h);
214 auto flat = [&](
int i,
int j,
int k) ->
idx {
215 return static_cast<idx>(k * ny * nx + j * nx + i);
217 for (
int k = 0; k < nz; ++k)
218 for (
int j = 0; j < ny; ++j)
219 for (
int i = 0; i < nx; ++i) {
220 idx id = flat(i, j, k);
221 if (i == 0 || i == nx - 1 || j == 0 || j == ny - 1 || k == 0 || k == nz - 1) {
225 * (6.0 * x[id] - x[flat(i + 1, j, k)] - x[flat(i - 1, j, k)]
226 - x[flat(i, j + 1, k)] - x[flat(i, j - 1, k)] - x[flat(i, j, k + 1)]
227 - x[flat(i, j, k - 1)]);
237 int nx =
phi.nx(), ny =
phi.ny(), nz =
phi.nz();
238 double inv2dx = 1.0 / (2.0 *
phi.dx());
239 for (
int k = 0; k < nz; ++k)
240 for (
int j = 0; j < ny; ++j)
241 for (
int i = 0; i < nx; ++i) {
242 int ip = std::min(i + 1, nx - 1), im = std::max(i - 1, 0);
243 int jp = std::min(j + 1, ny - 1), jm = std::max(j - 1, 0);
244 int kp = std::min(k + 1, nz - 1), km = std::max(k - 1, 0);
245 gx(i, j, k) = (
phi(ip, j, k) -
phi(im, j, k)) * inv2dx;
246 gy(i, j, k) = (
phi(i, jp, k) -
phi(i, jm, k)) * inv2dx;
247 gz(i, j, k) = (
phi(i, j, kp) -
phi(i, j, km)) * inv2dx;
256 int nx = fx.
nx(), ny = fx.
ny(), nz = fx.
nz();
257 double inv2dx = 1.0 / (2.0 * fx.
dx());
258 for (
int k = 0; k < nz; ++k)
259 for (
int j = 0; j < ny; ++j)
260 for (
int i = 0; i < nx; ++i) {
261 int ip = std::min(i + 1, nx - 1), im = std::max(i - 1, 0);
262 int jp = std::min(j + 1, ny - 1), jm = std::max(j - 1, 0);
263 int kp = std::min(k + 1, nz - 1), km = std::max(k - 1, 0);
264 out(i, j, k) = ((fx(ip, j, k) - fx(im, j, k)) + (fy(i, jp, k) - fy(i, jm, k))
265 + (fz(i, j, kp) - fz(i, j, km)))
277 int nx = ax.
nx(), ny = ax.
ny(), nz = ax.
nz();
278 double inv2dx = 1.0 / (2.0 * ax.
dx());
279 for (
int k = 0; k < nz; ++k)
280 for (
int j = 0; j < ny; ++j)
281 for (
int i = 0; i < nx; ++i) {
282 int ip = std::min(i + 1, nx - 1), im = std::max(i - 1, 0);
283 int jp = std::min(j + 1, ny - 1), jm = std::max(j - 1, 0);
284 int kp = std::min(k + 1, nz - 1), km = std::max(k - 1, 0);
286 (az(i, jp, k) - az(i, jm, k) - ay(i, j, kp) + ay(i, j, km)) * inv2dx;
288 (ax(i, j, kp) - ax(i, j, km) - az(ip, j, k) + az(im, j, k)) * inv2dx;
290 (ay(ip, j, k) - ay(im, j, k) - ax(i, jp, k) + ax(i, jm, k)) * inv2dx;
3D scalar and vector fields on uniform Cartesian grids.
2D uniform interior grid: geometry only, no field data.
void laplacian_stencil_2d(const BasicVector< T > &x, BasicVector< T > &y, int N)
void row_fiber_sweep(BasicVector< T > &data, int N, F &&f)
Apply a mutable 1D operation to each row fiber.
constexpr real phi
Golden ratio.
void neg_laplacian_3d(const Vector &x, Vector &y, int nx, int ny, int nz, double inv_dx2)
Compute on a 3D grid.
real sample_2d_periodic(const Vector &field, idx N, real h, real px, real py, real ox, real oy)
void curl_3d(const ScalarField3D &ax, const ScalarField3D &ay, const ScalarField3D &az, ScalarField3D &bx, ScalarField3D &by, ScalarField3D &bz)
Compute with central differences.
void laplacian_stencil_2d_4th(const BasicVector< T > &x, BasicVector< T > &y, int N)
Fourth-order 2D Laplacian cross stencil.
void gradient_3d(const ScalarField3D &phi, ScalarField3D &gx, ScalarField3D &gy, ScalarField3D &gz)
Compute with central differences.
void laplacian_stencil_2d_periodic(const BasicVector< T > &x, BasicVector< T > &y, int N)
Periodic second-order 2D Laplacian stencil.
void col_fiber_sweep(BasicVector< T > &data, int N, F &&f)
Apply a mutable 1D operation to each column fiber.
void divergence_3d(const ScalarField3D &fx, const ScalarField3D &fy, const ScalarField3D &fz, ScalarField3D &out)
Compute with central differences.
void fill_grid(Vector &u, int N, double h, F &&f)
Fill grid values at .
Scalar field on a 2D uniform interior grid.
Dense vector storage and operations.