Orogenic Landscape Modelling¶
We investigate the drainage network dynamics and the steady-state drainage patterns that emerge from erosion of an uplifting mountain.
import quagmire as qg
qg.nd = qg.scaling.non_dimensionalise
u = qg.scaling._scaling.u
scaling_coefficients = qg.scaling._scaling.get_coefficients()
scaling_coefficients["[length]"] = 80 * u.km
scaling_coefficients["[time]"] = 1000 * u.years
Utilities¶
Create Mesh¶
from quagmire import QuagMesh
from quagmire import tools as meshtools
from quagmire import function as fn
from quagmire import equation_systems as systems
import quagmire
import numpy as np
import matplotlib.pyplot as plt
from time import time
%matplotlib inline
minX, maxX = 0.0, qg.nd(80. * u.km)
minY, maxY = 0.0, qg.nd(40. * u.km)
dx, dy = qg.nd(500 * u.m), qg.nd(500 * u.m)
x1, y1, simplices = meshtools.square_mesh(minX, maxX, minY, maxY, dx, dy, random_scale=1.0)
DM = meshtools.create_DMPlex(x1, y1, simplices, boundary_vertices=None)
mesh = QuagMesh(DM, verbose=True, tree=True)
print( "\nNumber of points in the triangulation: {}".format(mesh.npoints))
print( "Downhill neighbour paths: {}".format(mesh.downhill_neighbours))
boundary_mask_fn = fn.misc.levelset(mesh.mask)
Initial topography¶
with mesh.deform_topography():
mesh.topography.data = 0.
with mesh.deform_topography():
new_elevation = qg.nd(100.*u.meter) * mesh.mask
mesh.topography.data = new_elevation.evaluate(mesh)
Rainfall Function¶
rainfall_fn = mesh.add_variable(name="rainfall")
rainfall_fn.data = qg.nd(1.*u.m / u.year)
Uplift function¶
uplift_rate_fn = mesh.add_variable(name="uplift")
uplift_rate_fn = qg.nd(1.0 * u.mm / u.year) * mesh.mask
Stream Power Law¶
# vary these and visualise difference
m = fn.parameter(0.5)
n = fn.parameter(1.0)
K = fn.parameter(qg.nd(5.0e-6 / u.year))
# create stream power function
upstream_precipitation_integral_fn = mesh.upstream_integral_fn(rainfall_fn)
stream_power_fn = K*upstream_precipitation_integral_fn**m * mesh.slope**n * boundary_mask_fn
# evaluate on the mesh
sp = stream_power_fn.evaluate(mesh)
Diffusion and Transport Solvers¶
import quagmire.equation_systems as systems
## Set up diffusion solver
diffusion_solver = systems.DiffusionEquation(mesh=mesh)
diffusion_solver.neumann_x_mask = fn.misc.levelset(mesh.mask, invert=True)
diffusion_solver.neumann_y_mask = fn.misc.levelset(mesh.mask, invert=True)
diffusion_solver.dirichlet_mask = fn.parameter(0.0)
diffusion_solver.diffusivity = fn.parameter(qg.nd(0.8 * u.m**2 / u.year))
diffusion_solver.verify() # Does nothing but is supposed to check we have everything necessary
# not needed to run
hillslope = diffusion_solver.phi
hillslope.data = mesh.topography.data
## Set up transport solver
transport_solver = systems.ErosionDepositionEquation(mesh=mesh, m=0.5, n=1.0)
transport_solver.rainfall = rainfall_fn
transport_solver.verify()
Timestepping¶
mesh.verbose = False
save_fields = True
efficiency = fn.parameter(qg.nd(5.0e-6 / u.year))
h5_filename = "fields_{:06d}.h5"
stats = "Step {:04d} | dt {:.5f} | time {:.4f} | min/mean/max height {:.3f}/{:.3f}/{:.3f} | step walltime {:.3f}"
sim_time = 0.0
steps = 20
for i in range(steps):
t = time()
topography0 = mesh.topography.copy()
# get timestep size
dt = min(diffusion_solver.diffusion_timestep(), transport_solver.erosion_deposition_timestep())
# build diffusion, erosion + deposition
diffusion_rate = diffusion_solver.diffusion_rate_fn(mesh.topography).evaluate(mesh)
erosion_rate, deposition_rate = transport_solver.erosion_deposition_local_equilibrium(efficiency)
uplift_rate = uplift_rate_fn.evaluate(mesh)
dhdt = diffusion_rate - erosion_rate + uplift_rate #+ deposition_rate
# do not rebuilt downhill matrix at half timestep
mesh.topography.unlock()
mesh.topography.data = mesh.topography.data + 0.5*dt*dhdt
mesh.topography.lock()
# get timestep size
dt = min(diffusion_solver.diffusion_timestep(), transport_solver.erosion_deposition_timestep())
# build diffusion, erosion + deposition
diffusion_rate = diffusion_solver.diffusion_rate_fn(mesh.topography).evaluate(mesh)
erosion_rate, deposition_rate = transport_solver.erosion_deposition_local_equilibrium(efficiency)
uplift_rate = uplift_rate_fn.evaluate(mesh)
dhdt = diffusion_rate - erosion_rate + uplift_rate#+ deposition_rate
# now take full timestep
with mesh.deform_topography():
mesh.topography.data = topography0.data + dt*dhdt
if save_fields:
mesh.save_mesh_to_hdf5(h5_filename.format(i))
mesh.save_field_to_hdf5(h5_filename.format(i), topo=mesh.topography.data)
quagmire.tools.generate_xdmf(h5_filename.format(i))
sim_time += dt
if i/steps*100 in list(range(0,100,10)):
topo_scaled = qg.scaling.dimensionalise(mesh.topography.data, u.meter)
simulation_time = qg.scaling.dimensionalise(sim_time, u.year)
print(stats.format(i, dt, simulation_time, topo_scaled.min(), topo_scaled.mean(),
topo_scaled.max(), time() - t))