In some very rare cases the residual power check can stop the
integration too early.
For example, this extremely unlikely chain of events was observed in a
few cases while performing a parameter sweep (~3000 simulations):
1. n⊥ converges on wrong branch ⇒ α jumps ⇒ dP/ds jumps (common)
2. dP/ds jumps close to the peak (unlikely)
3. the peak of dP/ds is close to 0.6P₀ (unlikely)
4. dP/ds jumps to dP/ds_max + 10⁻¹² ⇒ wrong peak found (very unlikely)
5. peak is at exactly the current point
⇒ three-point interpolation fails (unlikely)
This adds a sort of simplified JSON RPC. It makes possible to interface
with GRAY from any other program without writing bindings or using some
FFI. It works simply by starting GRAY in a subprocess and communicating
with it using a pipe.
Both requests and replies are a single line of text: commands are sent
to the stdin and GRAY replies with a JSON object on the stdout.
The commands include setting/getting any GRAY parameter, reloading the
input files, starting the simulation and quitting.
This adds a single switch to configure GRAY for realtime operation.
In realtime a single ray is traced until absorption reaches ≈50% of the
total. The simulation is stopped immediately after returning only the
position (as ρ_p=√ψ) of the peak. So, no post-processing is performed at
all. In addition:
- all outputs units are inactivated (equivalent to passing --units 0);
- current drive computation is disabled (ecrh_cd.ieccd=0);
- absorption is computed in weakly relativistic approximation
(ecrh_cd.iwarm=1);
- reflections and multiple plasma passes are disabled;
This implements a method to control the integrator step size based on
the integration error and resonance conditions. The main advantages are that:
- the ray trajectories have a bounded error;
- the initial step size can be large as to quickly traverse the vacuum;
- the results no longer depend on the choice of the step size.
The error is estimated from the real part of the dispersion relation
Λ(x̅, N̅), which if solved exactly should be zero.
The error bound is set to a strict value when crossing the plasma
boundary to ensure a correct coupling and is relaxed afterwards.
Finally, when the ray is approaching a resonance the controller ensures
the step size is small compared to the absorption profile.
This change makes the integration method of the raytracing equations
configurable and significantly simplifies the integrator subroutine
by moving the implementation details outside.
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.