numerics 0.1.0
Loading...
Searching...
No Matches
fields.hpp
Go to the documentation of this file.
1/// @file pde/fields.hpp
2/// @brief 3D scalar and vector fields on Cartesian grids, with PDE field
3/// solvers.
4///
5/// ScalarField3D -- potential phi(x,y,z) on a uniform grid with trilinear
6/// sampling. VectorField3D -- three ScalarField3D components; sample() returns
7/// trilinear (fx,fy,fz). FieldSolver -- static PDE utilities (Poisson solve,
8/// gradient, divergence, curl). MagneticSolver -- static utilities for J =
9/// -sigma*grad(phi) and B = curl(A) via vector Poisson.
10#pragma once
11
12#include "spatial/grid3d.hpp"
14#include <array>
15#include <utility>
16#include <vector>
17
18namespace num {
19
20// ScalarField3D
21
23 public:
24 /// @param nx,ny,nz Grid resolution
25 /// @param dx Cell size [m]
26 /// @param ox,oy,oz World-space origin
27 ScalarField3D(int nx,
28 int ny,
29 int nz,
30 float dx,
31 float ox = 0.0f,
32 float oy = 0.0f,
33 float oz = 0.0f);
34
36 return grid_;
37 }
38 const Grid3D& grid() const {
39 return grid_;
40 }
41
42 int nx() const {
43 return grid_.nx();
44 }
45 int ny() const {
46 return grid_.ny();
47 }
48 int nz() const {
49 return grid_.nz();
50 }
51 float dx() const {
52 return static_cast<float>(grid_.dx());
53 }
54 float ox() const {
55 return ox_;
56 }
57 float oy() const {
58 return oy_;
59 }
60 float oz() const {
61 return oz_;
62 }
63
64 void set(int i, int j, int k, double v) {
65 grid_.set(i, j, k, v);
66 }
67 void fill(double v) {
68 grid_.fill(v);
69 }
70 /// Fill every cell with f(i, j, k).
71 template<typename F>
72 void fill(F&& f) { grid_.fill(std::forward<F>(f)); }
73
74 /// Construct and fill from callable f(i, j, k) -> double.
75 template<typename F>
76 ScalarField3D(int nx, int ny, int nz, float dx, F&& f,
77 float ox = 0.0f, float oy = 0.0f, float oz = 0.0f)
78 : ScalarField3D(nx, ny, nz, dx, ox, oy, oz) { fill(std::forward<F>(f)); }
79
80 /// Trilinear interpolation at world position (x,y,z).
81 /// Returns 0 outside the grid domain.
82 float sample(float x, float y, float z) const;
83
84 private:
85 Grid3D grid_;
86 float ox_, oy_, oz_;
87};
88
89// VectorField3D
90
92 ScalarField3D x, y, z; ///< x, y, z components on the same grid layout
93
94 VectorField3D(int nx,
95 int ny,
96 int nz,
97 float dx,
98 float ox = 0.0f,
99 float oy = 0.0f,
100 float oz = 0.0f);
101
102 /// Trilinear-interpolated field vector at world position.
103 std::array<float, 3> sample(float px, float py, float pz) const;
104
105 /// Multiply all components by scalar s.
106 void scale(float s);
107};
108
109// FieldSolver
110
112 public:
113 /// Dirichlet boundary condition: fix phi = value at grid node flat_idx.
114 struct DirichletBC {
115 int flat_idx; ///< k*ny*nx + j*nx + i
116 double value;
117 };
118
119 /// Solve Laplacian(phi) = source with phi=0 on all boundaries (Dirichlet).
120 /// phi is both the initial guess and the output solution.
121 /// Internally solves the SPD system (-Laplacian)phi = -source via
122 /// matrix-free CG.
124 const ScalarField3D& source,
125 double tol = 1e-6,
126 int max_iter = 500);
127
128 /// Solve div(coeff * grad(phi)) = 0 with arbitrary Dirichlet BCs.
129 ///
130 /// Typical use: current flow in a heterogeneous conductor (coeff =
131 /// conductivity sigma). Imposes BCs via symmetric penalty elimination so
132 /// the system remains SPD -> CG converges. Neumann (zero normal flux) on
133 /// all non-BC boundaries.
135 const ScalarField3D& coeff,
136 const std::vector<DirichletBC>& bcs,
137 double tol = 1e-6,
138 int max_iter = 500);
139
140 /// Compute grad(phi) via central finite differences (one-sided at
141 /// boundaries).
143
144 /// Compute div(f) via central finite differences.
145 static ScalarField3D divergence(const VectorField3D& f);
146
147 /// Compute curl(A) via central finite differences (one-sided at
148 /// boundaries).
149 static VectorField3D curl(const VectorField3D& A);
150};
151
152// MagneticSolver
153
155 public:
156 static constexpr double MU0 = 1.2566370614e-6; ///< mu_0 [H/m]
157
158 /// Compute current density J = -sigma*grad(phi) [A/m^2].
159 static VectorField3D current_density(const ScalarField3D& sigma,
160 const ScalarField3D& phi);
161
162 /// Solve for static magnetic field B given current density J.
163 /// Solves Laplacian(A) = -mu0*J (Coulomb gauge, Dirichlet A=0) via three CG
164 /// solves, then returns B = curl(A).
166 double tol = 1e-6,
167 int max_iter = 500);
168};
169
170} // namespace num
static VectorField3D gradient(const ScalarField3D &phi)
Definition fields.cpp:165
static SolverResult solve_var_poisson(ScalarField3D &phi, const ScalarField3D &coeff, const std::vector< DirichletBC > &bcs, double tol=1e-6, int max_iter=500)
Definition fields.cpp:92
static SolverResult solve_poisson(ScalarField3D &phi, const ScalarField3D &source, double tol=1e-6, int max_iter=500)
Definition fields.cpp:65
static VectorField3D curl(const VectorField3D &A)
Definition fields.cpp:179
static ScalarField3D divergence(const VectorField3D &f)
Compute div(f) via central finite differences.
Definition fields.cpp:172
double dx() const
Definition grid3d.hpp:30
int ny() const
Definition grid3d.hpp:24
int nz() const
Definition grid3d.hpp:27
int nx() const
Definition grid3d.hpp:21
void fill(real v)
Definition grid3d.cpp:14
void set(int i, int j, int k, real v)
Definition grid3d.hpp:44
static VectorField3D solve_magnetic_field(const VectorField3D &J, double tol=1e-6, int max_iter=500)
Definition fields.cpp:205
static VectorField3D current_density(const ScalarField3D &sigma, const ScalarField3D &phi)
Compute current density J = -sigma*grad(phi) [A/m^2].
Definition fields.cpp:189
static constexpr double MU0
mu_0 [H/m]
Definition fields.hpp:156
void set(int i, int j, int k, double v)
Definition fields.hpp:64
float oy() const
Definition fields.hpp:57
float ox() const
Definition fields.hpp:54
void fill(F &&f)
Fill every cell with f(i, j, k).
Definition fields.hpp:72
int nx() const
Definition fields.hpp:42
ScalarField3D(int nx, int ny, int nz, float dx, F &&f, float ox=0.0f, float oy=0.0f, float oz=0.0f)
Construct and fill from callable f(i, j, k) -> double.
Definition fields.hpp:76
float dx() const
Definition fields.hpp:51
float sample(float x, float y, float z) const
Definition fields.cpp:18
int ny() const
Definition fields.hpp:45
const Grid3D & grid() const
Definition fields.hpp:38
Grid3D & grid()
Definition fields.hpp:35
float oz() const
Definition fields.hpp:60
int nz() const
Definition fields.hpp:48
void fill(double v)
Definition fields.hpp:67
3D Cartesian scalar grid backed by num::Vector storage.
constexpr real phi
Golden ratio.
Definition math.hpp:44
constexpr real e
Definition math.hpp:43
Umbrella include for all linear solvers.
Dirichlet boundary condition: fix phi = value at grid node flat_idx.
Definition fields.hpp:114
int flat_idx
k*ny*nx + j*nx + i
Definition fields.hpp:115
std::array< float, 3 > sample(float px, float py, float pz) const
Trilinear-interpolated field vector at world position.
Definition fields.cpp:48
ScalarField3D z
x, y, z components on the same grid layout
Definition fields.hpp:92
ScalarField3D x
Definition fields.hpp:92
void scale(float s)
Multiply all components by scalar s.
Definition fields.cpp:52
ScalarField3D y
Definition fields.hpp:92