///|
pub(all) struct PoissonResult {
potential : Array[Double]
residual : Double
iterations : Int
} derive(Debug, ToJson)
///|
pub fn poisson_residual(
grid : Grid1D,
potential : ArrayView[Double],
source : ArrayView[Double],
) -> Double {
let laplacian = periodic_laplacian(grid, potential)
let length = if laplacian.length() < source.length() {
laplacian.length()
} else {
source.length()
}
if length == 0 {
0.0
} else {
let error = Array::makei(length, fn(i) { -laplacian[i] - source[i] })
l2_norm(error) / length.to_double().sqrt()
}
}
///|
fn zero_mean(values : Array[Double]) -> Unit {
let average = mean(values)
for i in 0.. PoissonResult {
let potential = zeros(source.length())
zero_mean(potential)
let mut residual = poisson_residual(grid, potential, source)
let mut iterations = 0
for _ in 0.. tolerance {
let next = zeros(source.length())
for i in 0.. Field1D {
let result = solve_periodic_poisson(grid, source, max_iterations~, tolerance~)
let electric = periodic_gradient(grid, result.potential).map(fn(value) {
-value
})
let rho = source.to_owned()
{ grid, charge_density: rho, electric, potential: result.potential }
}