pyrokinetics.normalisation#
Classes for working with different conventions for normalisation.
Each piece of software that Pyrokinetics works with may use its own convention for normalising physical quantities, and each individual run or simulation may have different physical reference values. We want to be able to convert normalised quantities between these different conventions and simulations.
For example, GS2 normalises lengths to the minor radius, while GENE
uses the major radius. We can convert lengths between the two codes if
we know either the aspect ratio, or both the minor and major radius in
physical units (for example, from a particular machine or equilibrium
code). Both codes normalise speeds to the thermal velocity, except
GS2’s definition includes an additional factor of the square root of
two; this means we can always convert normalised speeds between the
two codes simply by multipling or dividing by sqrt(2)
as
appropriate.
This module aims to make this process of conversion simpler by packaging up all the units and conventions together. Then, for example, we could convert a growth rate from GS2 to GENE’s normalisation like so:
growth_rate_gene = growth_rate_gs2.to(norms.gene)
where norms
is a SimulationNormalisation
instance.
We make a distinction between “simulation units” and “physical units”:
simulation units are named something like lref_minor_radius
, are
always valid for a particular code, have a fictional dimension such as
[lref]
, and usually need some extra information to convert them to
a different unit. Physical units, on the other hand, are associated
with a particular simulation and named something like
lref_minor_radius_run1234
, have a real reference value, for
example 1.5 metres
, and can be converted to other physical units
without extra information.
Importantly, for a given convention, we can convert between its simulation and physical units. For example, a length of one in GS2 simulation units (that is, without a physical reference value) is always equivalent to one GS2 physical length unit. This is equivalent to defining the reference length for the simulation.
We define a “convention” to be a set of simulation units. These are:
bref
: magnetic fieldlref
: Equilibrium lengthmref
: massnref
: densityqref
: chargetref
: temperaturevref
: velocityrhoref
: gyroradius
For example, the GS2 convention has an lref
of
lref_minor_radius
, and a vref
of vref_most_probable
; while
GENE has lref_major_radius
and vref_nrl
respectively.
A unique SimulationNormalisation
is created for each Pyro
instance, and contains a dict
of ConventionNormalisation
instances. Each of these conventions contains a full set of units,
that is lref
, bref
, and so on. The SimulationNormalisation
has a default convention whose units can be accessed directly.
Initially, the convention’s units refer to the simulation units for that particular convention, but can be set to physical units:
>>> norm = SimulationNormalisation("run1234")
# We can access the units either through a particular convention:
>>> norm.gs2.lref
<Unit('lref_minor_radius')>
# Or through `norm` directly for the default convention
>>> norm.lref
<Unit('lref_minor_radius')>
# Providing a physical reference value changes simulation units
# to physical units
>>> norm.set_lref(minor_radius=1.5)
>>> norm.lref
<Unit('lref_minor_radius_run1234')>
We use [pint](https://pint.readthedocs.io) (with some local modifications) for the units. Read their docs to understand how to work with units generally.
The modifications here are to enable converting units to a convention. To convert growth rates between GS2 and GENE we could do:
growth_rate_gene = growth_rate_gs2.to(norms.gene.vref / norms.gene.lref)
Or more succinctly:
growth_rate_gene = growth_rate_gs2.to(norms.gene)
which converts all (simulation or physical) units to GENE’s normalisation convention.
Warning
bref
is not a fundamental dimension, so converting magnetic
fields needs to be done directly:
# Wrong! Units will be mref * vref / qref / lref
B0_cgyro = B0_gene.to(norms.cgyro)
# Right! Units will be bref
B0_cgyro = B0_gene.to(norms.cgyro.bref)
beta
#
The magnetic \(\beta_N\) is a dimensionless quantity defined by:
When we have all of nref, tref, bref
we can compute beta_ref
,
and we only need to track which convention it was defined in. We do so
by giving it units in another arbitrary dimension, [beta_ref]
,
with distinct units for each convention. We also don’t need to keep
track of simulation and physical units separately, as these are always
directly convertable. [beta_ref]
is essentially just another name
for “percent”, but gives us a mechanism to convert between
normalisations.
Module Attributes
Particular normalisation conventions |
Functions
|
Copy data into a new dict, converting any quantities to other normalisation |
Classes
|
A description of a normalisation convention, including what species reference values use, whether the velocity includes a |
|
A concrete set of reference values/normalisations. |
|
Holds the normalisations for a given simulation for all the known conventions. |