ElectromagneticFields.jl – Modules
ElectromagneticFields.FIELD_CACHE — Constant
The generated functions built so far, keyed by what determines them.
Because the parameters are arguments rather than literals, the code depends on the equilibrium's type and on the names and shapes of its parameters, not on their values, so every field matching one already built is a lookup: no trace, no code generation and no compilation. The entries hold the bare generated functions; the parameter values are attached per field when it is constructed.
Populated during this package's precompilation for the equilibria in its workload, and it survives into the package image, so those types cost nothing in a fresh session.
The cache assumes the methods defining a field do not change within a session. Redefine an A₁ or a metric coefficient — under Revise, say — and clear_field_cache! is what makes the next FieldFunctions see it.
ElectromagneticFields.FIELD_FUNCTION_DOCS — Constant
Every quantity a FieldFunctions generates, as name => (shape, description).
This is the single source for three things that must not drift apart: the fields of the generated NamedTuple, the accessors exported for them, and their docstrings. x in a description is the cartesian coordinates and ξ the chart's own; derivatives are always with respect to ξ.
ElectromagneticFields.FIELD_FUNCTION_NAMES — Constant
The names of the generated functions a FieldFunctions holds, which are also the keys of functions(field) and the names of the accessors exported for them.
ElectromagneticFields.FieldFunction — Type
FieldFunction(f, p)A function built by Symbolics.build_function together with the parameter values to call it with.
The generated code is free of the equilibrium's parameters: it takes them as an argument, so one compiled function serves every parameter value of an equilibrium type. p holds the values from the equilibrium struct, flattened by parameter_values, and the wrapper supplies them so that callers do not have to.
The wrapper also fixes two things about the generated function. build_function builds its output container similarto the argument container, so the same generated function returns an SMatrix for an SVector argument and a heap Matrix for a Vector one — the latter allocating, up to 6 KiB for a rank-three tensor. Converting the coordinates to an SVector first keeps every call allocation free whatever the caller passes.
And it converts the result to float(eltype(ξ)). A structurally constant body — g♭ of a cartesian chart, φ and E♭ of a purely magnetic equilibrium — is emitted with Int literals and would otherwise return Int, making every component of one field disagree with the others and forcing a runtime promotion in the caller.
ElectromagneticFields.FieldFunctions — Type
FieldFunctions(equ, pert = ZeroPerturbation(); cse = true, cache = true, cache_module)The electromagnetic field of equ, perturbed by pert, as a value: a struct of compiled functions built from a symbolic trace of the equilibrium's chart, metric and vector potential.
Unlike a set of functions evaluated into a module, this is an ordinary object. It can be built inside a function, stored, and passed to a vector field that depends on the field — typically in a GeometricEquations problem's parameters, from which the equation function evaluates the components it needs.
Accessors
Every stored function is reached through an exported generic taking the field first, and accepts either a coordinate vector or three scalars:
field = FieldFunctions(ThetaPinchEquilibrium())
B♭(field, t, ξ) # covariant components of B, an SVector{3}
B♭(field, t, ξ₁, ξ₂, ξ₃) # the same
B♭(field, t, ξ)[1] # one component
B(field, t, ξ) # |B|, a scalarA quantity that has several representations carries the musical isomorphism that produces it: ♭ for a lowered index, ♯ for a raised one, ♮ for physical components. The bare letter is the magnitude, so B is |B| and DB, DDB are its gradient and Hessian.
| covariant | contravariant | physical | derivatives | |
|---|---|---|---|---|
| vector potential | A♭ | A♯ | DA♭, DDA♭ | |
| magnetic field | B♭ | B♯ | B♮ | DB♭; two-form B♭♭; magnitude B, DB, DDB |
| unit magnetic field | b♭ | b♯ | b♮ | Db♭, Db♮, DDb♭ |
| perpendicular frame | a♭, c♭ | a♯, c♯ | a♮, c♮ | |
| electric field | E♭ | E♯ | DE♭ | |
| metric | g♭ | g♯ | Dg♭, Dg♯, DDg♭, DDg♯ |
The chart contributes to_cartesian, from_cartesian, DF, DF̄, J, rangemin and rangemax, and the scalar potential φ.
Four things are data rather than functions: parameters(field) returns the equilibrium's scalar parameters, coordinates(field) the equilibrium's own coordinate helpers such as R, r, θ and ϕ, periodic(field) an SVector{3, Bool} saying which coordinates of the chart are periodic, and orientation(field) the sign of the chart's handedness — see orientation. functions(field) returns all of the above generated functions as a NamedTuple.
Parameters
The generated code is free of the equilibrium's parameters: it is traced in terms of R₀, B₀, q₀ … and takes their values as an argument, which the field supplies from the equilibrium struct on every call. Two fields of the same type therefore share their compiled code exactly, and differ only in the values they pass — which is what lets one precompiled function set serve every parameter value. See parameter_names for what counts as a parameter.
cache reuses the generated functions of a type already built, which is what makes constructing any of the shipped equilibria free — they are traced during this package's precompilation and the cache survives into its image. Redefining a method a field is built from, under Revise say, makes the cached code stale; clear_field_cache! discards it. cache_module says where the generated bodies are kept, and a package building a field during its own precompilation must set it; see @precompilable_fields.
cse names each repeated subexpression once instead of emitting it in full every time it occurs. It is on by default and is value-preserving; turning it off makes the generated code easier to read against a paper and considerably slower.
ElectromagneticFields.@precompilable_fields — Macro
@precompilable_fieldsPrepare the calling module to hold fields built during its own precompilation.
A generated function keeps its body in a cache inside some module, and that cache only survives precompilation when the module is the one being precompiled. Put this at the top level of a package that builds a field there, and pass that module to FieldFunctions as cache_module:
module MyModel
using ElectromagneticFields
@precompilable_fields
const FIELD = FieldFunctions(AxisymmetricTokamakCylindricalEquilibrium(6.2, 5.3, 2.0);
cache_module = @__MODULE__)
endMyModel then carries the field in its package image: no trace, no code generation and no compilation happen when it is loaded. Add a PrecompileTools.@compile_workload calling the accessors to cache their compiled code as well, and the first evaluation in a session costs microseconds.
Without this the field still works, but it is rebuilt on every load.
ElectromagneticFields.AxisymmetricTokamakCartesianITER — Method
AxisymmetricTokamakCartesianITER()AxisymmetricTokamakCartesianEquilibrium with ITER's parameters, ITER_R₀, ITER_B₀ and ITER_q₀.
ElectromagneticFields.AxisymmetricTokamakCylindricalITER — Method
AxisymmetricTokamakCylindricalITER()AxisymmetricTokamakCylindricalEquilibrium with ITER's parameters, ITER_R₀, ITER_B₀ and ITER_q₀.
ElectromagneticFields.AxisymmetricTokamakToroidalITER — Method
AxisymmetricTokamakToroidalITER()AxisymmetricTokamakToroidalEquilibrium with ITER's parameters, ITER_R₀, ITER_B₀ and ITER_q₀.
ElectromagneticFields.A♭ — Method
A♭(field::FieldFunctions, t, ξ)
A♭(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)Covariant components $A_i$ of the vector potential, as the equilibrium supplied them.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.A♯ — Method
A♯(field::FieldFunctions, t, ξ)
A♯(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)Contravariant components $A^i = g^{ij} A_j$.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.B — Method
B(field::FieldFunctions, t, ξ)
B(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)The magnitude $|B| = \sqrt{B^i B_i}$.
Returns scalar, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.B♭ — Method
B♭(field::FieldFunctions, t, ξ)
B♭(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)Covariant components $B_i$ of the magnetic field.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.B♭♭ — Method
B♭♭(field::FieldFunctions, t, ξ)
B♭♭(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)The magnetic two-form $B_{ij} = (∂_i A_j - ∂_j A_i)/2$, antisymmetric by construction.
Returns SMatrix{3,3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.B♮ — Method
B♮(field::FieldFunctions, t, ξ)
B♮(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)Physical components, in the orthonormal frame.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.B♯ — Method
B♯(field::FieldFunctions, t, ξ)
B♯(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)Contravariant components $B^i$.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.DA♭ — Method
DA♭(field::FieldFunctions, t, ξ)
DA♭(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)$∂_j A_i$, indexed [i,j].
Returns SMatrix{3,3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.DB — Method
DB(field::FieldFunctions, t, ξ)
DB(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)The gradient $∂_i |B|$.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.DB♭ — Method
DB♭(field::FieldFunctions, t, ξ)
DB♭(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)$∂_j B_i$, indexed [i,j].
Returns SMatrix{3,3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.DDA♭ — Method
DDA♭(field::FieldFunctions, t, ξ)
DDA♭(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)$∂_k ∂_j A_i$, indexed [i,j,k].
Returns SArray{3,3,3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.DDB — Method
DDB(field::FieldFunctions, t, ξ)
DDB(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)The Hessian $∂_j ∂_i |B|$.
Returns SMatrix{3,3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.DDb♭ — Method
DDb♭(field::FieldFunctions, t, ξ)
DDb♭(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)$∂_k ∂_j b_i$, indexed [i,j,k].
Returns SArray{3,3,3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.DDg♭ — Method
DDg♭(field::FieldFunctions, t, ξ)
DDg♭(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)$∂_l ∂_k g_{ij}$, indexed [i,j,k,l].
Returns SArray{3,3,3,3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.DDg♯ — Method
DDg♯(field::FieldFunctions, t, ξ)
DDg♯(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)$∂_l ∂_k g^{ij}$, indexed [i,j,k,l].
Returns SArray{3,3,3,3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.DE♭ — Method
DE♭(field::FieldFunctions, t, ξ)
DE♭(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)$∂_j E_i$, indexed [i,j].
Returns SMatrix{3,3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.DF — Method
DF(field::FieldFunctions, t, ξ)
DF(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)The tangent map ${DF^i}_j = ∂x^i / ∂ξ^j$.
Returns SMatrix{3,3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.DF̄ — Method
DF̄(field::FieldFunctions, t, ξ)
DF̄(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)The inverse tangent map $∂ξ^i / ∂x^j$.
Returns SMatrix{3,3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.Db♭ — Method
Db♭(field::FieldFunctions, t, ξ)
Db♭(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)$∂_j b_i$, indexed [i,j].
Returns SMatrix{3,3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.Db♮ — Method
Db♮(field::FieldFunctions, t, ξ)
Db♮(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)$∂_j$ of the physical components of $b$.
Returns SMatrix{3,3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.Dg♭ — Method
Dg♭(field::FieldFunctions, t, ξ)
Dg♭(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)$∂_k g_{ij}$, indexed [i,j,k].
Returns SArray{3,3,3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.Dg♯ — Method
Dg♯(field::FieldFunctions, t, ξ)
Dg♯(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)$∂_k g^{ij}$, indexed [i,j,k].
Returns SArray{3,3,3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.E♭ — Method
E♭(field::FieldFunctions, t, ξ)
E♭(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)Covariant components $E_i = -∂_i φ$ of the electric field.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.E♯ — Method
E♯(field::FieldFunctions, t, ξ)
E♯(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)Contravariant components $E^i$.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.J — Method
J(field::FieldFunctions, t, ξ)
J(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)The volume element $\sqrt{|g|} = |\det DF|$. It carries no sign; see orientation.
Returns scalar, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.SolovevDoubleXpointEquilibrium — Method
SolovevDoubleXpointEquilibrium(R₀, B₀, ϵ, κ, δ, α, xsep, ysep)A SolovevXpointEquilibrium built from the seven up-down symmetric constraints alone, so that the X-point at (xsep, ysep) is mirrored by one at (xsep, -ysep). The five asymmetric coefficients are zero.
ElectromagneticFields.SolovevDoubleXpointEquilibriumNSTX — Method
SolovevDoubleXpointEquilibrium with NSTX's parameters.
ElectromagneticFields.SolovevEquilibriumFRC — Method
SolovevEquilibrium approximating a field-reversed configuration.
ElectromagneticFields.SolovevEquilibriumITER — Method
SolovevEquilibrium with ITER's parameters.
ElectromagneticFields.SolovevEquilibriumNSTX — Method
SolovevEquilibrium with NSTX's parameters.
ElectromagneticFields.SolovevXpointEquilibriumITER — Method
SolovevXpointEquilibrium with ITER's parameters.
ElectromagneticFields.SolovevXpointEquilibriumNSTX — Method
SolovevXpointEquilibrium with NSTX's parameters.
ElectromagneticFields.a♭ — Method
a♭(field::FieldFunctions, t, ξ)
a♭(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)Covariant components of $a$, the first of the two vectors perpendicular to $b$. It reverses on a path through the points where $b$ is parallel to the coordinate basis vector it is built from, and so does $c$.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.a♮ — Method
a♮(field::FieldFunctions, t, ξ)
a♮(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)Physical components of $a$.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.a♯ — Method
a♯(field::FieldFunctions, t, ξ)
a♯(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)Contravariant components of $a$.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.b♭ — Method
b♭(field::FieldFunctions, t, ξ)
b♭(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)Covariant components of the unit vector $b = B/|B|$.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.b♮ — Method
b♮(field::FieldFunctions, t, ξ)
b♮(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)Physical components of $b$.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.b♯ — Method
b♯(field::FieldFunctions, t, ξ)
b♯(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)Contravariant components of $b$.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.clear_field_cache! — Method
clear_field_cache!()Discard the generated functions cached by FieldFunctions, so that the next field of each type is traced afresh. Needed only after redefining a method that a field is built from.
ElectromagneticFields.contravariant_to_covariant — Method
Returns the i-th component of the one-form corresponding to the vector v
ElectromagneticFields.contravariant_to_physical — Method
Returns the i-th component of the physical coordinate representation of the vector v
ElectromagneticFields.coordinates — Method
coordinates(field)The equilibrium's own coordinate helpers as a NamedTuple of functions — X, Y, Z, R, r, θ, ϕ and r² for the equilibria that define them. Which names are present varies per equilibrium, which is why these are not accessors of their own.
ElectromagneticFields.covariant_to_contravariant — Method
Returns the i-th component of the vector corresponding to the one-form α
ElectromagneticFields.covariant_to_physical — Method
Returns the i-th component of the physical coordinate representation of the one-form α
ElectromagneticFields.crossproduct — Method
Returns the m-th component of the cross-product between the vectors v and w
ElectromagneticFields.c♭ — Method
c♭(field::FieldFunctions, t, ξ)
c♭(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)Covariant components of $c = b × a$, completing the triad.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.c♮ — Method
c♮(field::FieldFunctions, t, ξ)
c♮(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)Physical components of $c$.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.c♯ — Method
c♯(field::FieldFunctions, t, ξ)
c♯(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)Contravariant components of $c$.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.from_cartesian — Method
from_cartesian(x, equ::AnalyticField)Evaluate the inverse chart map $ξ(x)$ of an equilibrium directly, without generating any code.
This two-argument method shares its name with the FieldFunctions accessor from_cartesian(field, t, x), and the number of arguments is what picks between them. from_cartesian(x, equ) reaches this method, which returns an allocating Vector; the accessor is the three-argument one and returns an SVector{3}. Prefer the accessor unless the equilibrium is all you have.
ElectromagneticFields.from_cartesian — Method
from_cartesian(field::FieldFunctions, t, ξ)
from_cartesian(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)The inverse chart map, $ξ(x)$.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.generate_field_expressions — Method
generate_field_expressions(equ, pert)Build the symbolic expression for every quantity FieldFunctions stores, returned as a NamedTuple whose keys are that struct's field names.
Each value is a Num, or a StaticArray of Num of the quantity's tensor rank: SVector{3} for a one-form or a vector, SMatrix{3,3} for a Jacobian or the metric, SArray{Tuple{3,3,3}} and SArray{Tuple{3,3,3,3}} for the higher derivatives. The container matters — build_function builds its output similarto what it is given.
ElectromagneticFields.get_functions — Function
get_functions(equ)The equilibrium's own coordinate helpers, as a NamedTuple mapping each name to a method taking (x, equ) — (X = X, Y = Y, Z = Z, R = R, r = r, θ = θ, ϕ = ϕ, r² = r²) for the axisymmetric equilibria. They are generated alongside the field and reached through coordinates(field).
Which names an equilibrium offers is its own business, which is why these are a NamedTuple rather than accessors of their own. Defining no method means the field has none.
ElectromagneticFields.get_parameters — Function
get_parameters(equ)The fields of equ that are parameters of the electromagnetic field, in the order its constructor takes them.
Defining no method means every field but name, which is what all the equilibria here want. Define one for a type with a field that is not a parameter — a cache, say — bearing in mind that the generated code takes exactly these as its argument, so anything the A₁, φ or metric methods read and this does not list is frozen into the code as a literal. See parameter_names, which applies the default.
A method may return a different set of names for each instance of a type; the cache keys on the names, so each set gets code of its own. A value frozen as a literal is invisible to the cache, which keys on the types and the parameter names and shapes alone: two equilibria differing only in such a value share one entry, and the second gets the first one's code. List the value as a parameter, or build the field with cache = false.
ElectromagneticFields.g♭ — Method
g♭(field::FieldFunctions, t, ξ)
g♭(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)The metric $g_{ij}$.
Returns SMatrix{3,3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.g♯ — Method
g♯(field::FieldFunctions, t, ξ)
g♯(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)The inverse metric $g^{ij}$.
Returns SMatrix{3,3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.hodge²¹ — Method
Returns the m-th component of the one-form corresponding to the two-form β
ElectromagneticFields.magnitude — Method
Returns the length of the vector v
ElectromagneticFields.normalize! — Method
Normalises the vector v in the metric g
ElectromagneticFields.normalize — Method
Normalises the vector v in the metric g
ElectromagneticFields.orientation — Method
orientation(equ)Sign of the chart's orientation: +1 if (ξ¹, ξ², ξ³) is right-handed, -1 if left-handed.
J(x, equ) is the volume element √|g| = |det DF|, which is what most of the machinery here wants and what J returns. The Hodge star and the cross product, however, are orientation-dependent and need the signed determinant det DF = orientation(equ) * J(x, equ).
Several of the charts in this package are left-handed — (R, Z, ϕ) and (r, θ, ϕ) both have det DF < 0, since the right-handed orderings would be (R, ϕ, Z) and (r, ϕ, θ) — so this is not a corner case. Getting it wrong reverses B without any other visible symptom: the same vector potential yields a magnetic field antiparallel to the one the cartesian chart gives at the same physical point.
Orientation of the charts in this package
Every equilibrium built on CartesianEquilibrium uses the identity map (x, y, z), so DF = I, J = 1 and the chart is right-handed. The four families below define their own coordinates, and all four are left-handed — in each case because the toroidal angle ϕ sits in the third slot where the right-handed ordering would put the second poloidal coordinate.
| chart | coordinates (ξ¹, ξ², ξ³) | J | det DF | orientation |
|---|---|---|---|---|
CartesianEquilibrium and all its subtypes | (x, y, z) | 1 | +1 | +1 |
AxisymmetricTokamakCylindricalEquilibrium | (R, Z, ϕ) | R | -R | -1 |
AxisymmetricTokamakToroidalEquilibrium | (r, θ, ϕ) | r R | -r R | -1 |
AxisymmetricTokamakToroidalRegularizationEquilibrium | (r, θ, ϕ) | r R | -r R | -1 |
AbstractSolovevEquilibrium | (R/R₀, Z/R₀, ϕ) | R R₀² | -R R₀² | -1 |
Concretely: AxisymmetricTokamakCartesianEquilibrium, SolovevSymmetricEquilibrium, ThetaPinchEquilibrium, DipoleField, ABCEquilibrium, SingularEquilibrium, SymmetricQuadraticEquilibrium, QuadraticPotentialsField and the three Penning traps are right-handed; AxisymmetricTokamakCylindricalEquilibrium, AxisymmetricTokamakToroidalEquilibrium, AxisymmetricTokamakToroidalRegularizationEquilibrium and every Solov'ev equilibrium other than SolovevSymmetricEquilibrium (which is a cartesian chart despite the name) are left-handed.
FieldFunctions stores the sign as a value rather than generating a function for it, since it depends on neither t nor ξ, and orientation(field) returns it. A loaded field therefore recovers det DF = orientation(field) * J(field, t, ξ) without the equilibrium object.
test/analytic/equilibria.jl asserts det(DF) ≈ orientation * J for each of the charts above, and separately that the stored value equals the trait it was generated from. A new chart that declares the wrong sign therefore fails immediately rather than silently flipping its own B, and so does a generator that stops tracking the trait.
ElectromagneticFields.parameter_names — Method
parameter_names(field)The fields of an equilibrium or perturbation that are parameters of the electromagnetic field, in the order its constructor takes them.
Every field of the struct except name by default, which is what the equilibria here want. Override get_parameters for a type with a field that is not a parameter — a cache, say — bearing in mind that anything the A₁/φ/metric methods read must be listed, or the generated code will have it baked in as a literal rather than taking it as an argument.
ElectromagneticFields.parameter_shape — Method
parameter_shape(field)How the parameters of field spread over the flattened tuple parameter_values returns: one entry per name, -1 for a scalar and the length for a vector.
The generated code reads its parameter argument positionally, so which slot carries which meaning follows from this shape and not from the number of slots — two splits totalling the same, such as (2, 3) and (3, 2), map the slots differently. It is part of the key FieldFunctions looks its cache up by, next to the names from parameter_names, which the shape does not carry.
A scalar takes -1 rather than 0 so that it cannot read as a vector of length zero. The shape then determines the number of slots, which makes it strictly finer than that number: two fields this tells apart are never served each other's code.
ElectromagneticFields.parameter_values — Method
parameter_values(field)The parameters of field flattened into a Tuple of scalars, which is the form the generated code takes them in. A parameter that is itself a vector — the Solov'ev coefficients — contributes each of its entries.
ElectromagneticFields.rangemax — Method
rangemax(field::FieldFunctions, t, ξ)
rangemax(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)Upper bounds of the coordinate domain.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.rangemin — Method
rangemin(field::FieldFunctions, t, ξ)
rangemin(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)Lower bounds of the coordinate domain.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.symbolic_copy — Method
symbolic_copy(field)A copy of field whose parameters are symbolic, so that tracing through it produces expressions in the parameters rather than in their values. Returns the copy and the symbols, flattened in the order parameter_values uses.
The reconstruction assumes the convention every field here follows: a parametric struct whose first member is name and whose inner constructor takes the remaining members in order. A type that departs from it should add a method.
ElectromagneticFields.to_cartesian — Method
to_cartesian(ξ, equ::AnalyticField)Evaluate the chart map $x(ξ)$ of an equilibrium directly, without generating any code.
This two-argument method shares its name with the FieldFunctions accessor to_cartesian(field, t, ξ), and the number of arguments is what picks between them. to_cartesian(ξ, equ) reaches this method, which returns an allocating Vector; the accessor is the three-argument one and returns an SVector{3}. Prefer the accessor unless the equilibrium is all you have.
ElectromagneticFields.to_cartesian — Method
to_cartesian(field::FieldFunctions, t, ξ)
to_cartesian(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)The chart map, $x(ξ)$.
Returns SVector{3}, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.
ElectromagneticFields.φ — Method
φ(field::FieldFunctions, t, ξ)
φ(field::FieldFunctions, t, ξ₁, ξ₂, ξ₃)The electrostatic potential, zero unless the field defines one.
Returns scalar, of float(eltype(ξ)). Allocation free for any coordinate container.
See FieldFunctions for the naming scheme and the full list of quantities.