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

Terminator #9

Merged
merged 13 commits into from
Aug 2, 2024
12 changes: 6 additions & 6 deletions transport/nair_lauritzen_non_divergent.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from gusto import *
from firedrake import IcosahedralSphereMesh, Constant, ge, le, exp, cos, \
sin, conditional, interpolate, SpatialCoordinate, VectorFunctionSpace, \
Function, assemble, dx, FunctionSpace, pi, min_value, acos
Function, assemble, dx, FunctionSpace, pi, min_value, acos, as_vector

import numpy as np

Expand Down Expand Up @@ -30,6 +30,7 @@
# Domain
mesh = IcosahedralSphereMesh(radius=R,
refinement_level=3, degree=2)

x = SpatialCoordinate(mesh)
domain = Domain(mesh, dt, 'BDM', 1)

Expand All @@ -38,7 +39,7 @@
eqn = AdvectionEquation(domain, V, "D")

# I/O
dirname = "nair_lauritzen_nondiv_dumptest_"+scalar_case
dirname = "nair_lauritzen_nondiv_"+scalar_case

# Dump the solution at each day
dumpfreq = int(day/dt)
Expand All @@ -47,20 +48,19 @@
output = OutputParameters(dirname=dirname,
dumplist_latlon=['D'],
dumpfreq = dumpfreq,
log_level="INFO",
dump_nc = True,
dump_vtus = False)

io = IO(domain, output)

# get lat lon coordinates
theta, lamda = latlon_coords(mesh)
lamda, theta, _ = lonlatr_from_xyz(x[0], x[1], x[2])

# Specify locations of the two bumps
theta_c1 = 0.0
theta_c2 = 0.0
lamda_c1 = -pi/6
lamda_c2 = pi/6
lamda_c1 = -pi/4
lamda_c2 = pi/4

if scalar_case == 'cosine_bells':

Expand Down
153 changes: 153 additions & 0 deletions transport/terminator_toy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
from gusto import *
from firedrake import IcosahedralSphereMesh, Constant, ge, le, exp, cos, \
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are the ge and le variables used? Could they be removed? The same might go for other things that have been imported

sin, conditional, interpolate, SpatialCoordinate, VectorFunctionSpace, \
Function, assemble, dx, FunctionSpace, pi, max_value, acos, as_vector

import numpy as np

# This script runs the Laurtizen et al. (2015) Terminator Toy
# test case. This examines the interaction of two species
# in the transport equation. There is coupling
# between the two species to model combination
# and dissociation.

######################

# Time parameters
day = 24.*60.*60.
dt = 900.
tmax = 12*day # this is 1036800s

# Radius of the Earth
R = 6371220.

# Domain
mesh = IcosahedralSphereMesh(radius=R,
refinement_level=3, degree=2)

x = SpatialCoordinate(mesh)

# get lat lon coordinates
lamda, theta, _ = lonlatr_from_xyz(x[0], x[1], x[2])

domain = Domain(mesh, dt, 'BDM', 1)

# Define the dry density and the two species as tracers
rho_d = ActiveTracer(name='rho_d', space='DG',
variable_type=TracerVariableType.density,
transport_eqn=TransportEquationType.conservative)

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 = [rho_d, X, X2]

# Equation
V = domain.spaces("HDiv")
eqn = CoupledTransportEquation(domain, active_tracers=tracers, Vu = V)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Remove the spaces around the equals sign!


# I/O
dirname = "terminator_toy"

# Dump the solution at each day
dumpfreq = int(day/dt)

# Set dump_nc = True to use tomplot.
output = OutputParameters(dirname=dirname,
dumpfreq = dumpfreq,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you remove the spaces from around the equals signs here?

dump_nc = True,
dump_vtus = True)

# Define intermediate sums to be able to use the TracerDensity diagnostic
X_plus_X2 = Sum('X', 'X2')
X_plus_X2_plus_X2 = Sum('X_plus_X2', 'X2')
tracer_diagnostic = TracerDensity('X_plus_X2_plus_X2', 'rho_d')

io = IO(domain, output, diagnostic_fields = [X_plus_X2, X_plus_X2_plus_X2, tracer_diagnostic])

# 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

terminator_stepper = BackwardEuler(domain)

physics_schemes = [(TerminatorToy(eqn, k1=k1, k2=k2, species1_name='X',
species2_name='X2'), terminator_stepper)]

# Set up two Gaussian bumps for the initial density field
Copy link
Collaborator

Choose a reason for hiding this comment

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

In the other examples I've been trying to put the initial conditions near the end, so that all of the model objects are set up close together. Would you be able to move the initial conditions to near the end of the file?

This doesn't quite work when there is a prescribed velocity which still needs specifying before the time stepper, but still works for the tracers

theta_c1 = 0.0
theta_c2 = 0.0
lamda_c1 = -pi/4
lamda_c2 = pi/4

X = cos(theta)*cos(lamda)
Y = cos(theta)*sin(lamda)
Z = sin(theta)

X1 = cos(theta_c1)*cos(lamda_c1)
Y1 = cos(theta_c1)*sin(lamda_c1)
Z1 = sin(theta_c1)

X2 = cos(theta_c2)*cos(lamda_c2)
Y2 = cos(theta_c2)*sin(lamda_c2)
Z2 = sin(theta_c2)

g1 = exp(-5*((X-X1)**2 + (Y-Y1)**2 + (Z-Z1)**2))
g2 = exp(-5*((X-X2)**2 + (Y-Y2)**2 + (Z-Z2)**2))

rho_expr = g1 + g2

X_T_0 = 4e-6
r = k1/(4*k2)
D_val = sqrt(r**2 + 2*X_T_0*r)

# Initial condition for each species
X_0 = D_val - r
X2_0 = 0.5*(X_T_0 - D_val + r)

T = tmax
k = 10*R/T

# Set up a non-divergent, time-varying, velocity field
def u_t(t):
u_zonal = k*(sin(lamda - 2*pi*t/T)**2)*sin(2*theta)*cos(pi*t/T) + ((2*pi*R)/T)*cos(theta)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you make sure that the indentation is 4 spaces here?

u_merid = k*sin(2*(lamda - 2*pi*t/T))*cos(theta)*cos(pi*t/T)

cartesian_u_expr = -u_zonal*sin(lamda) - u_merid*sin(theta)*cos(lamda)
cartesian_v_expr = u_zonal*cos(lamda) - u_merid*sin(theta)*sin(lamda)
cartesian_w_expr = u_merid*cos(theta)

u_expr = as_vector((cartesian_u_expr, cartesian_v_expr, cartesian_w_expr))

return u_expr

# Define limiters for the interacting species
limiter_space = domain.spaces('DG')
sublimiters = {'X': DG1Limiter(limiter_space), 'X2': DG1Limiter(limiter_space)}
MixedLimiter = MixedFSLimiter(eqn, sublimiters)

transport_scheme = SSPRK3(domain, limiter=MixedLimiter)
transport_method = [DGUpwind(eqn, 'rho_d'), DGUpwind(eqn, 'X'), DGUpwind(eqn, 'X2')]

# Timstepper that solves the physics separately to the dynamics
# with a defined prescribed transporting velocity
stepper = SplitPrescribedTransport(eqn, transport_scheme, io,
spatial_methods=transport_method,
physics_schemes=physics_schemes,
prescribed_transporting_velocity=u_t)

# Initial conditions
stepper.fields("rho_d").interpolate(rho_expr)
stepper.fields("X").interpolate(X_0)
stepper.fields("X2").interpolate(X2_0)

# Run until Termination!
stepper.run(t=0, tmax=tmax)