Skip to content

Commit

Permalink
Merge pull request #399 from firedrakeproject/timestepping_physics
Browse files Browse the repository at this point in the history
PR #399: Evaluate physics at each stage of multistep methods
  • Loading branch information
tommbendall committed Jul 27, 2023
2 parents c173934 + b1aa590 commit 9fcd77a
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 9 deletions.
12 changes: 12 additions & 0 deletions gusto/time_discretisation.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,10 +373,14 @@ def solve_stage(self, x_in, stage):
self.x1.assign(self.x_out)

elif stage == 1:
for evaluate in self.evaluate_source:
evaluate(self.x1, self.dt)
self.solver.solve()
self.x1.assign(0.75*x_in + 0.25*self.x_out)

elif stage == 2:
for evaluate in self.evaluate_source:
evaluate(self.x1, self.dt)
self.solver.solve()
self.x1.assign((1./3.)*x_in + (2./3.)*self.x_out)

Expand Down Expand Up @@ -470,16 +474,22 @@ def solve_stage(self, x_in, stage):
self.x1.assign(x_in + 0.5 * self.dt * self.k1)

elif stage == 1:
for evaluate in self.evaluate_source:
evaluate(self.x1, self.dt)
self.solver.solve()
self.k2.assign(self.x_out)
self.x1.assign(x_in + 0.5 * self.dt * self.k2)

elif stage == 2:
for evaluate in self.evaluate_source:
evaluate(self.x1, self.dt)
self.solver.solve()
self.k3.assign(self.x_out)
self.x1.assign(x_in + self.dt * self.k3)

elif stage == 3:
for evaluate in self.evaluate_source:
evaluate(self.x1, self.dt)
self.solver.solve()
self.k4.assign(self.x_out)
self.x1.assign(x_in + 1/6 * self.dt * (self.k1 + 2*self.k2 + 2*self.k3 + self.k4))
Expand Down Expand Up @@ -538,6 +548,8 @@ def solve_stage(self, x_in, stage):
self.x1.assign(self.x_out)

elif stage == 1:
for evaluate in self.evaluate_source:
evaluate(self.x1, self.dt)
self.solver.solve()
self.x1.assign(0.5 * x_in + 0.5 * (self.x_out))

Expand Down
20 changes: 11 additions & 9 deletions integration-tests/physics/test_instant_rain.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ def run_instant_rain(dirname):
fexpr = Constant(0)

# Equation
# TODO: This should become a CoupledAdvectionEquation. Currently we set u
# and D to 0 in the ShallowWaterEquations so they do not evolve.
vapour = WaterVapour(name="water_vapour", space='DG')
rain = Rain(name="rain", space="DG",
transport_eqn=TransportEquationType.no_transport)
Expand All @@ -46,17 +48,17 @@ def run_instant_rain(dirname):
dumplist=['vapour', "rain"])
diagnostic_fields = [CourantNumber()]
io = IO(domain, output, diagnostic_fields=diagnostic_fields)
transport_method = DGUpwind(eqns, "water_vapour")
transport_method = [DGUpwind(eqns, "water_vapour")]

# Physics schemes
# define saturation function
saturation = Constant(0.5)
physics_schemes = [(InstantRain(eqns, saturation, rain_name="rain"),
ForwardEuler(domain))]
RK4(domain))]

# Time stepper
stepper = PrescribedTransport(eqns, RK4(domain), io, transport_method,
physics_schemes=physics_schemes)
stepper = SplitPhysicsTimestepper(eqns, RK4(domain), io, transport_method,
physics_schemes=physics_schemes)

# ------------------------------------------------------------------------ #
# Initial conditions
Expand All @@ -76,8 +78,8 @@ def run_instant_rain(dirname):
VD = FunctionSpace(mesh, "DG", 1)
initial_vapour = Function(VD).interpolate(vapour_expr)

# define expected solutions; vapour should be equal to saturation and rain
# should be (initial vapour - saturation)
# TODO: This test is based on the assumption that final vapour should be
# equal to saturation, which might not be true when timestepping physics.
vapour_true = Function(VD).interpolate(saturation)
rain_true = Function(VD).interpolate(vapour0 - saturation)

Expand All @@ -96,16 +98,16 @@ def test_instant_rain_setup(tmpdir):
r = stepper.fields("rain")

# check that the maximum of the vapour field is equal to the saturation
assert v.dat.data.max() - saturation.values() < 0.001, "The maximum of the final vapour field should be equal to saturation"
assert v.dat.data.max() - saturation.values() < 0.1, "The maximum of the final vapour field should be equal to saturation"

# check that the minimum of the vapour field hasn't changed
assert v.dat.data.min() - initial_vapour.dat.data.min() < 0.001, "The minimum of the vapour field should not change"
assert v.dat.data.min() - initial_vapour.dat.data.min() < 0.1, "The minimum of the vapour field should not change"

# check that the maximum of the excess vapour agrees with the maximum of the
# rain
VD = Function(v.function_space())
excess_vapour = Function(VD).interpolate(initial_vapour - saturation)
assert excess_vapour.dat.data.max() - r.dat.data.max() < 0.001
assert excess_vapour.dat.data.max() - r.dat.data.max() < 0.1

# check that the minimum of the rain is 0
assert r.dat.data.min() < 1e-8

0 comments on commit 9fcd77a

Please sign in to comment.