-
Notifications
You must be signed in to change notification settings - Fork 12
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
Tests for Terminator Toy and SplitPrescribedTransport #465
Changes from 5 commits
e433e77
730b107
4a2df00
3076528
2918b52
b0b7750
78a0c0f
216c7d9
7275a70
6200cc0
366c7a5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
""" | ||
This tests the terminator toy physics scheme that models the interaction | ||
of two chemical species through coupled ODEs. | ||
""" | ||
|
||
from gusto import * | ||
from firedrake import IcosahedralSphereMesh, Constant, cos, \ | ||
sin, SpatialCoordinate, Function, max_value, as_vector, \ | ||
errornorm, norm | ||
import numpy as np | ||
|
||
|
||
def run_terminator_toy(dirname): | ||
|
||
# ------------------------------------------------------------------------ # | ||
# Set up model objects | ||
# ------------------------------------------------------------------------ # | ||
|
||
# A much larger timestep than in proper simulations, as this | ||
# tests moving towards a steady state with no flow. | ||
dt = 100000. | ||
|
||
# Make the mesh and domain | ||
R = 6371220. | ||
mesh = IcosahedralSphereMesh(radius=R, | ||
refinement_level=3, degree=2) | ||
|
||
domain = Domain(mesh, dt, 'BDM', 1) | ||
|
||
# get lat lon coordinates | ||
x = SpatialCoordinate(mesh) | ||
lamda, theta, _ = lonlatr_from_xyz(x[0], x[1], x[2]) | ||
|
||
domain = Domain(mesh, dt, 'BDM', 1) | ||
|
||
# Define the interacting species | ||
X = ActiveTracer(name='X', space='DG', | ||
variable_type=TracerVariableType.mixing_ratio, | ||
transport_eqn=TransportEquationType.advective) | ||
|
||
X2 = ActiveTracer(name='X2', space='DG', | ||
variable_type=TracerVariableType.mixing_ratio, | ||
transport_eqn=TransportEquationType.advective) | ||
|
||
tracers = [X, X2] | ||
|
||
# Equation | ||
V = domain.spaces("HDiv") | ||
eqn = CoupledTransportEquation(domain, active_tracers=tracers, Vu=V) | ||
|
||
output = OutputParameters(dirname=dirname+"/terminator_toy", | ||
dumpfreq=10) | ||
io = IO(domain, output) | ||
|
||
# Define the reaction rates: | ||
theta_c = np.pi/9. | ||
lamda_c = -np.pi/3. | ||
|
||
k1 = max_value(0, sin(theta)*sin(theta_c) + cos(theta)*cos(theta_c)*cos(lamda-lamda_c)) | ||
k2 = 1 | ||
|
||
physics_schemes = [(TerminatorToy(eqn, k1=k1, k2=k2, species1_name='X', | ||
species2_name='X2'), BackwardEuler(domain))] | ||
|
||
# Set up a non-divergent, time-varying, velocity field | ||
def u_t(t): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the wind is zero, do we need a function prescribing the velocity? Or could we just set the initial velocity to zero? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't find a way to get the prescribed_transporting_velocity to work without giving it a function. |
||
return as_vector((Constant(0)*lamda, Constant(0)*lamda, Constant(0)*lamda)) | ||
|
||
transport_scheme = SSPRK3(domain) | ||
transport_method = [DGUpwind(eqn, 'X'), DGUpwind(eqn, 'X2')] | ||
|
||
X_0 = 4e-6 + 0*lamda | ||
X2_0 = 0*lamda | ||
|
||
transport_scheme = SSPRK3(domain) | ||
transport_method = [DGUpwind(eqn, 'X'), DGUpwind(eqn, 'X2')] | ||
|
||
stepper = SplitPrescribedTransport(eqn, transport_scheme, io, | ||
spatial_methods=transport_method, | ||
physics_schemes=physics_schemes, | ||
prescribed_transporting_velocity=u_t) | ||
|
||
stepper.fields("X").interpolate(X_0) | ||
stepper.fields("X2").interpolate(X2_0) | ||
|
||
stepper.run(t=0, tmax=10*dt) | ||
|
||
# Compute the steady state solution to compare to | ||
steady_space = domain.spaces('DG') | ||
X_steady = Function(steady_space) | ||
X2_steady = Function(steady_space) | ||
|
||
X_T_0 = 4e-6 | ||
r = k1/(4*k2) | ||
D_val = sqrt(r**2 + 2*X_T_0*r) | ||
|
||
X_steady.interpolate(D_val - r) | ||
X2_steady.interpolate(0.5*(X_T_0 - D_val + r)) | ||
|
||
return stepper, X_steady, X2_steady | ||
|
||
|
||
def test_terminator_toy_setup(tmpdir): | ||
dirname = str(tmpdir) | ||
stepper, X_steady, X2_steady = run_terminator_toy(dirname) | ||
X_field = stepper.fields("X") | ||
X2_field = stepper.fields("X2") | ||
|
||
# Assert that the physics scheme has sufficiently moved | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like a sensible test to me! |
||
# the species fields near their steady state solutions | ||
assert errornorm(X_field, X_steady)/norm(X_steady) < 0.25, "The X field is not sufficiently close to the steady state profile" | ||
assert errornorm(X2_field, X2_steady)/norm(X2_steady) < 0.25, "The X2 field is not sufficiently close to the steady state profile" |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,7 +37,7 @@ def run_wind_drag(dirname, implicit_formulation): | |
eqn = CompressibleEulerEquations(domain, parameters) | ||
|
||
# I/O | ||
output = OutputParameters(dirname=dirname+"/surface_fluxes", | ||
output = OutputParameters(dirname=dirname+"/wind_drag", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for fixing this! |
||
dumpfreq=1, | ||
dumplist=['u']) | ||
io = IO(domain, output) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this is just a test and the spatial discretisation is not important, could we use a coarser grid? e.g. refinement level 2?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point. Using a refinement level of 2 still successfully tests the ODEs moving the system towards the steady state, although I will need to halve the timestep size and slacken the tolerance on the test (error less than 0.4) to adjust.