numerics
Loading...
Searching...
No Matches
fields.cpp
Go to the documentation of this file.
1/// @file src/pde/fields.cpp
2/// @brief Implementations for num::ScalarField3D, VectorField3D, FieldSolver, MagneticSolver.
3#include "pde/fields.hpp"
4#include "pde/stencil.hpp"
6#include <algorithm>
7
8namespace num {
9
10// ============================================================
11// ScalarField3D
12// ============================================================
13
14ScalarField3D::ScalarField3D(int nx, int ny, int nz, float dx,
15 float ox, float oy, float oz)
16 : grid_(nx, ny, nz, static_cast<double>(dx))
17 , ox_(ox), oy_(oy), oz_(oz) {}
18
19float ScalarField3D::sample(float x, float y, float z) const {
20 const float gx = (x - ox_) / dx();
21 const float gy = (y - oy_) / dx();
22 const float gz = (z - oz_) / dx();
23
24 if (gx < 0 || gx >= nx()-1 || gy < 0 || gy >= ny()-1 || gz < 0 || gz >= nz()-1)
25 return 0.0f;
26
27 const int i0 = static_cast<int>(gx);
28 const int j0 = static_cast<int>(gy);
29 const int k0 = static_cast<int>(gz);
30 const float tx = gx - i0, ty = gy - j0, tz = gz - k0;
31
32 auto v = [&](int di, int dj, int dk) {
33 return static_cast<float>(grid_(i0+di, j0+dj, k0+dk));
34 };
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)));
39}
40
41// ============================================================
42// VectorField3D
43// ============================================================
44
45VectorField3D::VectorField3D(int nx, int ny, int nz, float dx,
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) {}
50
51std::array<float,3> VectorField3D::sample(float px, float py, float pz) const {
52 return { x.sample(px,py,pz), y.sample(px,py,pz), z.sample(px,py,pz) };
53}
54
55void VectorField3D::scale(float s) {
56 auto sc = [&](Grid3D& g) {
57 auto v = g.to_vector();
58 num::scale(v, static_cast<real>(s));
59 g.from_vector(v);
60 };
61 sc(x.grid()); sc(y.grid()); sc(z.grid());
62}
63
64// ============================================================
65// FieldSolver
66// ============================================================
67
69 const ScalarField3D& source,
70 double tol, int max_iter) {
71 const Grid3D& g = phi.grid();
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;
75
76 auto flat = [&](int i, int j, int k) -> idx {
77 return static_cast<idx>(k * ny * nx + j * nx + i);
78 };
79
80 Vector b(N, 0.0);
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)
84 b[flat(i,j,k)] = -source.grid()(i,j,k);
85
86 Vector xv = phi.grid().to_vector();
87 auto matvec = [&](const Vector& v, Vector& Av) {
88 neg_laplacian_3d(v, Av, nx, ny, nz, inv_dx2);
89 };
90 auto result = cg_matfree(matvec, b, xv, tol, static_cast<idx>(max_iter));
91 phi.grid().from_vector(xv);
92 return result;
93}
94
96 VectorField3D out(phi.nx(), phi.ny(), phi.nz(), phi.dx(),
97 phi.ox(), phi.oy(), phi.oz());
98 gradient_3d(phi.grid(), out.x.grid(), out.y.grid(), out.z.grid());
99 return out;
100}
101
103 ScalarField3D out(f.x.nx(), f.x.ny(), f.x.nz(), f.x.dx(),
104 f.x.ox(), f.x.oy(), f.x.oz());
105 divergence_3d(f.x.grid(), f.y.grid(), f.z.grid(), out.grid());
106 return out;
107}
108
110 VectorField3D B(A.x.nx(), A.x.ny(), A.x.nz(), A.x.dx(),
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());
113 return B;
114}
115
116// ============================================================
117// MagneticSolver
118// ============================================================
119
121 const ScalarField3D& phi) {
123 const Grid3D& sg = sigma.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) {
128 const double neg_s = -sg(i,j,k);
129 J.x.grid()(i,j,k) *= neg_s;
130 J.y.grid()(i,j,k) *= neg_s;
131 J.z.grid()(i,j,k) *= neg_s;
132 }
133 return J;
134}
135
137 double tol, int max_iter) {
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();
140
141 auto make_source = [&](const ScalarField3D& Jc) {
142 ScalarField3D src(nx, ny, nz, dx, ox, oy, oz);
143 const Grid3D& gJ = Jc.grid();
144 Grid3D& gs = src.grid();
145 for (int k=0;k<nz;++k)
146 for (int j=0;j<ny;++j)
147 for (int i=0;i<nx;++i)
148 gs(i,j,k) = -MU0 * gJ(i,j,k);
149 return src;
150 };
151
152 ScalarField3D Ax(nx, ny, nz, dx, ox, oy, oz);
153 ScalarField3D Ay(nx, ny, nz, dx, ox, oy, oz);
154 ScalarField3D Az(nx, ny, nz, dx, ox, oy, oz);
155
159
160 VectorField3D A(nx, ny, nz, dx, ox, oy, oz);
161 A.x = Ax; A.y = Ay; A.z = Az;
162 return FieldSolver::curl(A);
163}
164
165} // namespace num
static VectorField3D gradient(const ScalarField3D &phi)
Compute ∇φ via central finite differences (one-sided at boundaries).
Definition fields.cpp:95
static SolverResult solve_poisson(ScalarField3D &phi, const ScalarField3D &source, double tol=1e-6, int max_iter=500)
Definition fields.cpp:68
static VectorField3D curl(const VectorField3D &A)
Compute ∇×A via central finite differences (one-sided at boundaries).
Definition fields.cpp:109
static ScalarField3D divergence(const VectorField3D &f)
Compute ∇·f via central finite differences.
Definition fields.cpp:102
int nx() const
Definition grid3d.hpp:20
static VectorField3D solve_magnetic_field(const VectorField3D &J, double tol=1e-6, int max_iter=500)
Definition fields.cpp:136
static VectorField3D current_density(const ScalarField3D &sigma, const ScalarField3D &phi)
Compute current density J = −σ∇φ [A/m²].
Definition fields.cpp:120
static constexpr double MU0
μ₀ [H/m]
Definition fields.hpp:99
float oy() const
Definition fields.hpp:37
float ox() const
Definition fields.hpp:36
int nx() const
Definition fields.hpp:32
float dx() const
Definition fields.hpp:35
float sample(float x, float y, float z) const
Definition fields.cpp:19
ScalarField3D(int nx, int ny, int nz, float dx, float ox=0.0f, float oy=0.0f, float oz=0.0f)
Definition fields.cpp:14
int ny() const
Definition fields.hpp:33
Grid3D & grid()
Definition fields.hpp:29
float oz() const
Definition fields.hpp:38
int nz() const
Definition fields.hpp:34
double real
Definition types.hpp:10
constexpr real phi
Golden ratio.
Definition math.hpp:42
void curl_3d(const Grid3D &ax, const Grid3D &ay, const Grid3D &az, Grid3D &bx, Grid3D &by, Grid3D &bz)
Definition stencil.hpp:170
void neg_laplacian_3d(const Vector &x, Vector &y, int nx, int ny, int nz, double inv_dx2)
Definition stencil.hpp:109
constexpr T ipow(T x) noexcept
Compute x^N at compile time via repeated squaring.
std::size_t idx
Definition types.hpp:11
void matvec(const Matrix &A, const Vector &x, Vector &y, Backend b=default_backend)
y = A * x
Definition matrix.cpp:94
void scale(Vector &v, real alpha, Backend b=default_backend)
v *= alpha
Definition vector.cpp:27
void divergence_3d(const Grid3D &fx, const Grid3D &fy, const Grid3D &fz, Grid3D &out)
Definition stencil.hpp:151
void gradient_3d(const Grid3D &phi, Grid3D &gx, Grid3D &gy, Grid3D &gz)
Definition stencil.hpp:132
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.
Definition cg.cpp:66
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.
Definition fields.cpp:51
ScalarField3D z
x, y, z components on the same grid layout
Definition fields.hpp:57
VectorField3D(int nx, int ny, int nz, float dx, float ox=0.0f, float oy=0.0f, float oz=0.0f)
Definition fields.cpp:45
ScalarField3D x
Definition fields.hpp:57
void scale(float s)
Multiply all components by scalar s.
Definition fields.cpp:55
ScalarField3D y
Definition fields.hpp:57