5.1. Refinement of points to correct ψ¶
PsiContour
and
FineContour
objects represent
flux surfaces – surfaces of constant \(\psi\) – so all points beloning to
them should be at positions where \(\psi(R,Z)=\psi_\mathrm{C}\), where
\(\psi_\mathrm{C}\) is the nominal \(\psi\)-value of the contour and
\(\psi(R,Z)\) is defined by the psi()
method provided by
Equilibrum
. However, the
initial placement of the points at each stage of the grid generation process is
given by the result of either an ODE integration or an interpolation or
extrapolation from the positions of some other points, so the point will not
(initially) lie exactly on the flux surface – there will be some small error
in the \(\psi\)-value.
To reduce the difference between the initial \(\psi\) for each point and
the nominal \(\psi_\mathrm{C}\) below a tolerance (set by refine_atol
),
PsiContour.refinePoint()
uses one of several
methods to refine the position of the point:
refinePointNewton()
- uses a Newton iteration. Usually converges quickly if the initial guess is close to the final point.refinePointIntegrate()
- integrates along a vector \((dR/d\psi,dZ/d\psi)\) usingscipy.integrate.solve_ivp
- PsiContour.refinePointNewton(p, tangent, *, psi, width, atol)
Use Newton iteration to refine point. This should converge quickly if the original point is sufficiently close.
- PsiContour.refinePointIntegrate(p, tangent, *, psi, width, atol)
Integrates across flux surfaces from
p
Integrates this:
\[\begin{split}\begin{eqnarray} \frac{dR}{d\psi} &=& \frac{d\psi}{dR} \frac{1}{((d\psi/dZ)^2 + (d\psi/dR)^2)} \\ \frac{dZ}{d\psi} &=& \frac{d\psi}{dZ} \frac{1}{((d\psi/dZ)^2 + (d\psi/dR)^2)} \end{eqnarray}\end{split}\]Usually quick but does not respect
atol
, so final result may not be as accurate as desired.Note: This is the method used in the original IDL Hypnotoad
- PsiContour.refinePointLinesearch(p, tangent, *, psi, width, atol)
Refine the location of a point p, using a line search method.
A line of length
width
is constructed perpendicular to thetangent
direction, andscipy.optimize.brentq
is used to search the line for the point where \(\psi\) takes its nominal value. If the search fails (for example because \(\psi\) is not monotonically varying along the line), it is retried recursively, using half the width each time.Usually robust, but can be slow.
The initial width is set by the
refine_width
setting.
A final option is available, 'integrate+newton'
which first uses
refinePointIntegrate()
to quickly
improve the initial guess, and then uses refinePointNewton()
to find an accurate
final position.
The choice of which method to use is set by the refine_method
option
('newton'
, 'integrate'
, 'line'
, or 'integrate+newton'
).
Multiple options can be passed in a list, in which case they will be tried in
order until one of them converges without error. This can be useful in case
different methods are more robust in different parts of the grid.