Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split State into Domain and IO #320

Merged
merged 15 commits into from
Jan 20, 2023
Merged

Split State into Domain and IO #320

merged 15 commits into from
Jan 20, 2023

Conversation

tommbendall
Copy link
Contributor

@tommbendall tommbendall commented Dec 12, 2022

This PR splits apart the state object -- at the moment this is a bit of a random bag of various different things. The idea is to make this into coherent objects which should then interact in a way that really captures what is going on in the model.

The separation of things is as follows:

Spaces

  • the SpaceCreator is now in its own file (function_spaces.py).
  • spaces can now be created by specifying horizontal and vertical degree separately

Domain

  • a new object to hold the mesh, the spaces and other things related to the geometry (e.g. the k vector, the perp operator and is_spherical)
  • horizontal and vertical degrees can be specified, or just the degree (if they are both the same)
  • the de Rham complex spaces are all automatically set up with the domain
  • holds dt

IO

  • holds and controls checkpointing and outputting

Equation

  • takes and holds the parameters for the equation

Timestepper

  • now holds the prognostic fields
  • now has a routine to set the reference profiles

To make this work, there are several other parts of the model that have to change:

Fields

  • The StateFields object has been extended -- it is now initialised from a
    TimeLevelFields object and existing fields can be added to it. This is
    intended so that the fields in the StateFields object can be pointers, and
    so at the start/end of time steps, prognostic fields don't need copying into/
    out of this object.
  • Specifically, the prognostics in StateFields point to the
    timestepper.x.np1 fields
  • Every field in the StateFields object has a type (prognostic, prescribed,
    diagnostic or derived) which can help determine how that field is treated.
  • The equation unfortunately may need to see some other fields (for instance
    the shallow-water equation needs Coriolis and topography fields). To address
    this I have created a PrescribedFields object which is stored in the
    equation. See below for more discussion.

Diagnostics

  • As the StateFields are now held by the time stepper, the interface to setting
    up the diagnostics must change, since the diagnostics need to see this object
    (both to search for fields in it and also to store the diagnostics themselves).
    A lot of the diagnostic code has then been reorganised.
  • The base diagnostic field __init__ contains an interface to specify which
    function space the diagnostic field should be computed in, and what method
    should be used to compute it (interpolation, projection, etc.)
  • The base diagnostic field setup routine creates an object for evaluating the
    diagnostic, i.e. an Interpolator or a Projector. This avoids us repeatedly
    calling .project within the time loop.
  • The diagnostic field setup routine must create a self.expr corresponding
    to the diagnostic field. Then, the super setup method is called to create the
    evaluator object.
  • Almost all diagnostic fields now inherit the compute method from base class,
    which simply calls the evaluator.
  • steady_state_errors and perturbations are no longer special cases and do
    not need special handling, so these have been removed from the output_parameters

Linear Solver

  • for the compressible linear solver, I have had to move the pre-computation of
    two fields from the _setup_solver method to the solve method. This is
    because these pre-computations involve the reference profiles, which will not
    have been set up when the solver is initialised. However it means these
    computations are happening every time the solver is called, so we need to find
    a way to avoid this.
  • I have removed the moisture argument from the linear_solver. This
    information can now be obtained from the active tracers.

Initialisation

  • initial conditions are now specified after the time stepper is initialised.
    Thus we have a clean separation in the code between: (a) building the model's
    objects, (b) specifying the initial conditions, and (c) running the model. I
    think this will make easy to create a Model object.

Reference Profiles

  • these are now specified through the stepper.
  • the reference profiles are stored in equation.X_ref, which is now used by the
    linear solver.
  • the semi-implicit time stepper now throws an error if the reference profiles
    haven't been initialised.

Miscellaneous

  • I have had to fix a handful of bugs/oddities in other parts of the code

@tommbendall tommbendall marked this pull request as draft December 12, 2022 14:16
@tommbendall tommbendall marked this pull request as ready for review January 7, 2023 13:37
@@ -954,7 +954,7 @@ def __init__(self, domain, parameters, Omega=None, sponge=None,
muexpr = conditional(z <= zc,
0.0,
mubar*sin((pi/2.)*(z-zc)/(H-zc))**2)
self.mu = Function(W_DG).interpolate(muexpr)
self.mu = self.prescribed_fields("coriolis", W_DG).interpolate(muexpr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the sponge function on the Coriolis space? Do we need to change the name of the space?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah that's a typo! Sorry, that should be the string "sponge" for the name of the field

Copy link
Contributor

@jshipton jshipton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extensively discussed offline - looks great, thanks Tom!

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.

2 participants