To improve the analytical model correctness this changes the formula
of the toroidal flux to lift the large aspect ratio approximation (a << R₀).
In fact, Φ(r) = B₀πr² is technically inconsistent with the field varying
as B₀R₀/R. The exact expression is:
Φ(r) = B₀πr² 2/[1 + √(1 - r²/R₀²)],
which is approximately equal to the former for r << R₀.
Note that this change introduces a divergence in the poloidal field at
r=R₀ (since ∂Φ/∂r → +∞), so the domain of the equilibrium has been
restricted to r<R₀, as expected.
This should not be a concern because the field outside the plasma
boundary is never directly, particularly not by the integrator.
Directly mapping r(R,z) to ρ_p greatly simplifies the implementation of
pol_flux, but also produces a weird current profile and resonance curve.
This keeps the previous changes to the model but reverts the mapping to
the previous one: r → ρ_t.
This changes all the print_* subroutines to not depend on q_spline,
either for the ψ data points or just their number.
In fact, in the new analytical model q_spline doesn't exist anymore.
Pro: This allows to mark q_spline as private.
This change combines `equian` and `equinum_psi` into a new `pol_flux`
subroutine that computes ψ(R,z) and derivatives for either numerical or
analytical equilibria.
Similarly, `equian` (the fpol and dfpol outputs) and `equinum_fpol` are
combined intro `pol_curr` that computes F(ψ) and its derivative.
Callers of these subroutines do not select a specific version based on
the value of `iequil` anymore.
- Hide the implementation of the re-normalisation of the ψ(R,z) spline
by adjusting the spline coefficients, instead of shifting and
rescaling after each evaluation.
- Correct the value of `psia` = ψ(X point) - ψ(O point) after the ψ(R,z)
spline has been re-normalised.
This fixes another instance of decoupling between the values of X and
∇X that introduce a systematic error in the numerical integration of
the raytracing equations.
Here the issue is caused by the different normalisations used,
specifically X=X(ψ_n') and ∇X=∇X(ψ_n), where ψ_n' is the re-normalised
spline of the normalised flux and ψ_n the spline of the normalised
flux.
See d0a5a9f for more details on problems resulting from this error.
- Change `equian` and `equinum_psi` to return the normalised values
for both the flux and its derivatives, to avoid confusions.
Callers that needed the unnormalised derivatives now multiply
explicitly by `psia`.
This change modifies the analytical equilibrium in order to simplify the
computation of the poloidal flux normalization and the derivatives.
In the power law parametrisation of the safety factor, ρ_t is replaced
with ρ_p and, similarly, the normalised poloidal radius is now
identified with ρ_p, instead of ρ_t.
With the same parameters (q₀,q₁,α...), this choice slightly changes the
plasma current distribution, but enables us to obtain a closed form for
ψ_a = ψ(r=a) and the relation ρ_t(ρ_p). In fact, both expressions are
now obtained by integrating the q(ρ_p), instead of 1/q(ρ_t), which has
no elementary antiderivative.
As the normalisation is now computed exactly, the values of the
normalised flux ψ_n = ψ/ψ_a and the gradient ∇ψ (entering the raytracing
equations in X and ∇X, respectively) are computed to the same precision.
Previously, ψ_n was computed to a lower precision due to the use of a
simple trapezoid integration of 1/q(ρ_p) for ψ_a, while ∇ψ was computed
up to machine precision using an exact formula.
This error effectively caused a very slight decoupling between X=ω_p²/ω²
and ∇X that introduced a systematic error in the numerical solution of
the raytracing equations.
The error manifests itself as a bias with a weak dependency on X in the
values taken by the dispersion function Λ(r̅, n̅) on the phase-space
points generated by the integrator. More specifically,
lim h→0 Λ(r̅_i, n̅_i) = -kX(r̅_i)
where h is the integrator step size;
r̅_i is the position at the i-th step;
k ≈ -3.258⋅10⁻⁵ and depends only on the number of points used to
perform the trapedoid integral for ψ_a (as ~ 1/n²).
After this change Λ behaves consistently with being a conserved quantity
(zero) up to the cumulative integration error of the 4° order
Runge-Kutta method. In fact we now have that:
Λ(r̅_i, n̅_i) ∝ - h⁴ ‖∂⁴X(r̅_i)/∂r̅⁴‖
It must be said that within this model the relation ρ_p(ρ_t) can't be
computed analytically (inverting ρ_t(ρ_p) produces a trascendental
equation of the form b = x + c x^α). However, this relation is not
necessary for raytracing and is easily solved, up to machine
precision, using minpack.
In addition, this change also makes the model consistetly use the
cocos=3 and fully implements the ability to force the signs of I_p, B_φ
(via equilibrium.sgni,sgnb) and rescaling the field (via
equilibrium.factb).
In the case of analytic equilibrium without a limiter contour, the
simple limiter was built incorrectly due to an unnecessary conversion
from cm (the equilibrium data are already in metre).
The ρ_p/ρ_t mapping is 1:1, so the interpolation must always preserve
monotonicity, of which cubic splines generally make no guarantee.
Note: Linear interpolation does not provide even C¹ continuity, but
these data is not directly used in the numerical integration, so it
should be fine. Ideally this should be replaced with cubic splines
computed with the Fritsch–Carlson algorithm.
- rename errocodes → gray_errors
- restructure the errors into a `error_spec` type
- make the list of errors easily extensible
- rewrite the `print_errn`, `print_errhcd` (now `print_err_raytracing`,
`print_err_ecrh_cd`) subroutine to handle arbitrary errors
- add functions to easily manipulate errors
(`raise_error`, `has_error`, `is_critical`)
- remove print statements from quadpack
- log all errors to stderr using the logger module
This adds a new `splines` module which implements a high-level interface
for creating and evaluating splines and rewrite almost all modules to
use it. Also, notably:
1. both `simplespline` and DIERCKX splines can now used with a uniform
interface
2. most complexity due to handling working space arrays is gone
3. memory management has been significantly simplified too
This converts the last remaining warnings to use the logging system.
Also drops `catand` and replace it with the intrinsic `atan`, which
supports complex as well as real numbers.
Note: before 3eab989d the `catand` function was actually incorrent!
The definition of arctan(z) can be obtained starting from the identity
d/dz arctan(z) = 1/(1 + z²) = ½ [1/(1 + iz) + 1/(1 - iz)],
integrating and using the definition log(z) = ∫₁^z dz/z,
arctan(z) = -i/2 [log(1 + iz) - log(1 - iz)].
If log is the principal branch, log(z) = log|z| + i arg(z), then
arctan(z) = -i/2 log(w) = 1/2 arg(w) -i/2 log|w|
where w = (1 + iz)/(1 - iz). Finally, the real part is
Re arctan(z) = 1/2 atan2(2Re(z), 1 - |z|²).
The term -|z|² is missing from the `catand` definition of GRAY,
but is present in the original Fortran 77 code from [SLATEC]:
it has probably been lost in the translation.
[SLATEC]: https://people.math.sc.edu/Burkardt/f_src/slatec/slatec.f90
- merge branch with a method to control the speed of iteration and
improve the convergence of `warmdisp` (thanks Thomas)
- unify `diel_tens_fr` and `diel_tens_wr` into a single subroutine,
`dielectric_tensor`
- stay as close as possible to the notation of Daniela Farina's paper
- make `sox` an integer
- mark more subroutines as pure
- add more comments
Some of the outputs of disp_deriv and plas_deriv are only needed
when updating the local plasma quantities (ywppla_upd) and not when
integrating the raytracing equations (rkstep).
This change save some unnecessary computations and variable definitions.
Also add some comments to disp_deriv
- Add missing array allocations
- Add parameter for varying number of columns in input files
- Change output unit numbers (dirty fix. Original units created an empty
named file, but wrote in default named fort.* files)
- Documentation is not built anymore with the default `all` rule to
improve portability. It must be built explicitly with `make docs`.
- Font types are not specified to allow building on systems with a
restricted set of fonts.
- Syntax fixes in the documentation Markdown.