15 float ox,
float oy,
float oz)
17 , ox_(ox), oy_(oy), oz_(oz) {}
20 const float gx = (x - ox_) /
dx();
21 const float gy = (y - oy_) /
dx();
22 const float gz = (z - oz_) /
dx();
27 const int i0 =
static_cast<int>(gx);
28 const int j0 =
static_cast<int>(gy);
29 const int k0 =
static_cast<int>(gz);
32 auto v = [&](
int di,
int dj,
int dk) {
35 return (1-
tz)*((1-
ty)*((1-
tx)*v(0,0,0) +
tx*v(1,0,0)) +
36 ty *((1-
tx)*v(0,1,0) +
tx*v(1,1,0))) +
37 tz *((1-
ty)*((1-
tx)*v(0,0,1) +
tx*v(1,0,1)) +
38 ty *((1-
tx)*v(0,1,1) +
tx*v(1,1,1)));
46 float ox,
float oy,
float oz)
47 : x(nx, ny, nz, dx, ox, oy, oz)
48 , y(nx, ny, nz, dx, ox, oy, oz)
49 , z(nx, ny, nz, dx, ox, oy, oz) {}
57 auto v =
g.to_vector();
72 const int nx =
g.
nx(), ny =
g.ny(), nz =
g.nz();
73 const double inv_dx2 = 1.0 / (
g.dx() *
g.dx());
74 const int N = nx * ny * nz;
76 auto flat = [&](
int i,
int j,
int k) ->
idx {
77 return static_cast<idx>(
k * ny * nx +
j * nx +
i);
81 for (
int k=1;
k<nz-1; ++
k)
82 for (
int j=1;
j<ny-1; ++
j)
83 for (
int i=1;
i<nx-1; ++
i)
91 phi.grid().from_vector(
xv);
104 f.x.ox(),
f.x.oy(),
f.x.oz());
111 A.x.ox(),
A.x.oy(),
A.x.oz());
112 curl_3d(
A.x.grid(),
A.y.grid(),
A.z.grid(),
B.x.grid(),
B.y.grid(),
B.z.grid());
124 const int nx =
sg.
nx(), ny =
sg.ny(), nz =
sg.nz();
125 for (
int k = 0;
k < nz; ++
k)
126 for (
int j = 0;
j < ny; ++
j)
127 for (
int i = 0;
i < nx; ++
i) {
138 const int nx = J.
x.
nx(), ny = J.
x.
ny(), nz = J.
x.
nz();
139 const float dx = J.
x.
dx(), ox = J.
x.
ox(), oy = J.
x.
oy(), oz = J.
x.
oz();
145 for (
int k=0;
k<nz;++
k)
146 for (
int j=0;
j<ny;++
j)
147 for (
int i=0;
i<nx;++
i)
static VectorField3D gradient(const ScalarField3D &phi)
Compute ∇φ via central finite differences (one-sided at boundaries).
static SolverResult solve_poisson(ScalarField3D &phi, const ScalarField3D &source, double tol=1e-6, int max_iter=500)
static VectorField3D curl(const VectorField3D &A)
Compute ∇×A via central finite differences (one-sided at boundaries).
static ScalarField3D divergence(const VectorField3D &f)
Compute ∇·f via central finite differences.
static VectorField3D solve_magnetic_field(const VectorField3D &J, double tol=1e-6, int max_iter=500)
static VectorField3D current_density(const ScalarField3D &sigma, const ScalarField3D &phi)
Compute current density J = −σ∇φ [A/m²].
static constexpr double MU0
μ₀ [H/m]
float sample(float x, float y, float z) const
ScalarField3D(int nx, int ny, int nz, float dx, float ox=0.0f, float oy=0.0f, float oz=0.0f)
constexpr real phi
Golden ratio.
void curl_3d(const Grid3D &ax, const Grid3D &ay, const Grid3D &az, Grid3D &bx, Grid3D &by, Grid3D &bz)
void neg_laplacian_3d(const Vector &x, Vector &y, int nx, int ny, int nz, double inv_dx2)
constexpr T ipow(T x) noexcept
Compute x^N at compile time via repeated squaring.
void matvec(const Matrix &A, const Vector &x, Vector &y, Backend b=default_backend)
y = A * x
void scale(Vector &v, real alpha, Backend b=default_backend)
v *= alpha
void divergence_3d(const Grid3D &fx, const Grid3D &fy, const Grid3D &fz, Grid3D &out)
void gradient_3d(const Grid3D &phi, Grid3D &gx, Grid3D &gy, Grid3D &gz)
SolverResult cg_matfree(MatVecFn matvec, const Vector &b, Vector &x, real tol=1e-6, idx max_iter=1000)
Matrix-free conjugate gradient for Ax = b where A is SPD.
3D scalar and vector fields on Cartesian grids, with PDE field solvers.
Higher-order stencil and grid-sweep utilities.
Umbrella include for all linear solvers.
std::array< float, 3 > sample(float px, float py, float pz) const
Trilinear-interpolated field vector at world position.
ScalarField3D z
x, y, z components on the same grid layout
VectorField3D(int nx, int ny, int nz, float dx, float ox=0.0f, float oy=0.0f, float oz=0.0f)
void scale(float s)
Multiply all components by scalar s.