Skip to content

Demo: Immutable normalisations#363

Open
LiamPattinson wants to merge 11 commits intounstablefrom
experimental/local_gk_simulation
Open

Demo: Immutable normalisations#363
LiamPattinson wants to merge 11 commits intounstablefrom
experimental/local_gk_simulation

Conversation

@LiamPattinson
Copy link
Copy Markdown
Collaborator

This is a demonstration of a possible solution to Issues #326 and #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 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:
new_simulation = simulation.with_geometry(my_new_geometry)

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:

new_simulation = simulation.with_geometry(geometry).with_species(species).to_gk_code("GENE")

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 #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.

LiamPattinson and others added 11 commits May 31, 2024 12:05
Adds a variant on both SimulationNormalisation and
ConventionNormalisation that provides very similar behaviour,
but without the option to redefine units after creation.
Also avoids splitting funcitonality between two classes that
each depend on each other.

Started work on a class to bundle together LocalGeometry,
LocalSpecies, Numerics, and a Normalisation. The aim is for
this to be an immutable representation of a single simulation,
and modifications to it will generate a new instance.
Creates new norms when converting from GS2 to GENE etc.
Only implemented to start from GS2, and only as a
demonstration
- Uses raw variables in place of dicts for species params.
- Has a separate function call per lref, bref, mref, etc
- Added _mutate function that can convert convention, geometry,
  and species all at once. Added nicer functions with reduced
  argument lists.
- LocalGKSimulation __init__ does simple initialisation,
  classmethod new() builds from sensible inputs. This is because
  other methods on the class need to construct new instances,
  and calling self.__class__.__new__(self.__class__) feels
  wrong.
- Simplified logic in some places. Probably made it worse in
  others.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant