MADNESS 0.10.1
|
The source is here.
We wish to solve Poisson's equation within a non-homogeneous medium, i.e., in which the permittivity is not constant.
Expanding and rearranging yields,
We can interpret
Thus, our equation becomes (deliberately written in the form of a fixed point iteration — given a guess for
where
and
Let's solve a problem to which we know the exact answer — a point charge at the center of a sphere
The surface charge density integrated over the suface has the value
To implement the problem in MADNESS we want the permittivity defined as a function over all space, so we define a characteristic function
where
To smooth the discontinuity we replace the Heaviside step function with
where
Starting from an initial guess we could try to iterate our equation for
with
A more robust approach is to use a solver that exploits information from previous iterations (the Krylov subspace) to estimate the optimal direction and length of the step to take. Such a solver is provided by nonlinsol.h. Each iteration we pass the current solution and corresponding residual to the solver and it provides the next trial vector.
In the code you can switch between using the solver or simple iteration by changing the value of USE_SOLVER
.
One final point is how to compute the reciprocal of the permittivity. This operation is not provided explicity by MADNESS, in part because even functions that are analytically never zero, might be (nearly) zero due to numerical truncation. Handling this issue correctly is problem specific. More generally, we want to compute a function-of-a-function. If
There are various ways to do this. The simplest is employed here — we define a function (reciprocal()
) that is passed into the unaryop()
method that modifies the function in-place. This simple approach is justified here since we know our input function is never zero even due to numerical noise, and the output function is about as smooth as the input. If it were not, we might have to refine the input function to obtain the desired precision.