The primary goal here is to develop a Normalisation class that both merges the functionality of SimulationNormalisation and ConventionNormalisation, and forbids the redefinition of units after creation. This would avoid the need to regularly rebuild the pint cache, which is causing significant performance issues, and would guarantee that physical units (e.g. lref_minor_radius_myrun0001) would always remain valid after definition.
There are two new classes that facilitate this:
ConstNormalisation: The new Normalisation subclass (this would just be renamed Normalisation in the final version).
LocalGKSimulation: A class that wraps up a ConstNormalisation, LocalGeometry, LocalSpecies, and Numerics. It permits the user to generate new instances of itself with new units conventions, geometries, species, or numerics. For example:
In this case, new_simulation will contain a brand new ConstNormalisation, LocalGeometry, LocalSpecies, and Numerics. Editing any of these new instances will not overwrite details of the originals. More complex transformations can be performed by chaining function calls:
Crucially, only LocalGKSimulation is responsible for generating new normalisations. Currently, physical units are set up as side effects of several functions throughout the code, and this makes it difficult to track how they evolve through the program.
I'm hoping to move towards a model in which LocalGeometry and LocalSpecies can be created using either simulation units or physical units via standard constructors, and, besides each having a normalise/with_units function that returns new instances, they won't have to worry about managing norms themselves. For now, I've had to make a few temporary edits to these classes just to get things working.
In the final version, LocalGKSimulation would be the object returned by GKInput readers, and the object passed in to write new input files. I'd like to see Pyro act as a manager of LocalGKSimulation instances, which I think would be a lot simpler than its current context-switching design. LocalGKSimulation would also be an input to GKOutput, as its contain all the needed units, geometry details, etc. It would also avoid the need to create deepcopies throughout the project, as PyroScan could make new LocalGKSimulation instances instead.
Examples of how to use this new interface are in the added tests.
A proper implementation would need to be split into several milestones. Issue https://github.com/pyro-kinetics/pyrokinetics/issues/336 would be a good place to start. There are also several other issues I ran into that I'm not sure how to handle:
I made steps towards the removal of units such as tref_deuterium, mref_hydrogen, etc, and opted instead for just tref_electron and tref_ion, as although deuterium isn't always present, we can always guarantee the presence of at least one negative species and one positive species. However, I'm aware that this won't cover many cases. For example, what if masses are defined relative to deuterium, but tref and nref are defined relative to a merged species representing a deuterium/tritium blend? I'll need a more complex solution than the one presented here.
There's a new way to set up SimulationNormalisation from a GKInput, which defines a new bespoke ConventionNormalisation. This method uses set_all_references and add_convention_normalisation in place of set_lref, set_bref and set_kinetic_references, but performs very similar jobs. I'm having a hard time figuring out all the minor differences, but one of the major ones is that arbitrary vref units can be set up. I'm not sure how best to handle this.
I'm not handling beta/beta_ref properly.
LocalSpecies defines domega_drho, which is always defined in normalised units, even if generated from a Kinetics instance. This would have to be replaced with a more general domega_dr, which would either have dimensions of [time]^-1 [length]^-1 or [vref] [lref]^-2. Currently it always needs to be in terms of [lref]. I'm unsure if this would break things.
This is a demonstration of a possible solution to Issues https://github.com/pyro-kinetics/pyrokinetics/issues/326 and https://github.com/pyro-kinetics/pyrokinetics/issues/337. I don't expect this to ever be merged!
The primary goal here is to develop a
Normalisation
class that both merges the functionality ofSimulationNormalisation
andConventionNormalisation
, and forbids the redefinition of units after creation. This would avoid the need to regularly rebuild the pint cache, which is causing significant performance issues, and would guarantee that physical units (e.g.lref_minor_radius_myrun0001
) would always remain valid after definition.There are two new classes that facilitate this:
ConstNormalisation
: The newNormalisation
subclass (this would just be renamedNormalisation
in the final version).LocalGKSimulation
: A class that wraps up aConstNormalisation
,LocalGeometry
,LocalSpecies
, andNumerics
. It permits the user to generate new instances of itself with new units conventions, geometries, species, or numerics. For example:In this case,
new_simulation
will contain a brand newConstNormalisation
,LocalGeometry
,LocalSpecies
, andNumerics
. Editing any of these new instances will not overwrite details of the originals. More complex transformations can be performed by chaining function calls:Crucially, only
LocalGKSimulation
is responsible for generating new normalisations. Currently, physical units are set up as side effects of several functions throughout the code, and this makes it difficult to track how they evolve through the program.I'm hoping to move towards a model in which
LocalGeometry
andLocalSpecies
can be created using either simulation units or physical units via standard constructors, and, besides each having anormalise
/with_units
function that returns new instances, they won't have to worry about managingnorms
themselves. For now, I've had to make a few temporary edits to these classes just to get things working.In the final version,
LocalGKSimulation
would be the object returned byGKInput
readers, and the object passed in to write new input files. I'd like to seePyro
act as a manager ofLocalGKSimulation
instances, which I think would be a lot simpler than its current context-switching design.LocalGKSimulation
would also be an input toGKOutput
, as its contain all the needed units, geometry details, etc. It would also avoid the need to create deepcopies throughout the project, asPyroScan
could make newLocalGKSimulation
instances instead.Examples of how to use this new interface are in the added tests.
A proper implementation would need to be split into several milestones. Issue https://github.com/pyro-kinetics/pyrokinetics/issues/336 would be a good place to start. There are also several other issues I ran into that I'm not sure how to handle:
I made steps towards the removal of units such as
tref_deuterium
,mref_hydrogen
, etc, and opted instead for justtref_electron
andtref_ion
, as although deuterium isn't always present, we can always guarantee the presence of at least one negative species and one positive species. However, I'm aware that this won't cover many cases. For example, what if masses are defined relative to deuterium, buttref
andnref
are defined relative to a merged species representing a deuterium/tritium blend? I'll need a more complex solution than the one presented here.There's a new way to set up
SimulationNormalisation
from aGKInput
, which defines a new bespokeConventionNormalisation
. This method usesset_all_references
andadd_convention_normalisation
in place ofset_lref
,set_bref
andset_kinetic_references
, but performs very similar jobs. I'm having a hard time figuring out all the minor differences, but one of the major ones is that arbitraryvref
units can be set up. I'm not sure how best to handle this.I'm not handling
beta
/beta_ref
properly.LocalSpecies
definesdomega_drho
, which is always defined in normalised units, even if generated from aKinetics
instance. This would have to be replaced with a more generaldomega_dr
, which would either have dimensions of[time]^-1 [length]^-1
or[vref] [lref]^-2
. Currently it always needs to be in terms of[lref]
. I'm unsure if this would break things.