9. Landscape Evolution¶
The local equilibrium transport law from Ex8-ErosionDeposition is implemented in a time-varying loop.
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 = -5.0, 5.0
minY, maxY = -5.0, 5.0,
spacingX = 0.02
spacingY = 0.02
minX, maxX = -5.0, 5.0
minY, maxY = -5.0, 5.0,
dx, dy = 0.05, 0.05
x1, y1, simplices = meshtools.elliptical_mesh(minX, maxX, minY, maxY, dx, dy, random_scale=0.0, refinement_levels=1)
DM = meshtools.create_DMPlex(x1, y1, simplices, boundary_vertices=None)
mesh = QuagMesh(DM, verbose=False, tree=True)
print( "\nNumber of points in the triangulation: {}".format(mesh.npoints))
print( "Downhill neighbour paths: {}".format(mesh.downhill_neighbours))
x = mesh.coords[:,0]
y = mesh.coords[:,1]
boundary_mask_fn = fn.misc.levelset(mesh.mask, 0.5)
radius = np.sqrt((x**2 + y**2))
theta = np.arctan2(y,x) + 0.1
height = np.exp(-0.025*(x**2 + y**2)**2)
# height += 0.5 * (1.0-0.2*radius)
height -= height.min()
with mesh.deform_topography():
mesh.downhill_neighbours = 2
mesh.topography.data = height
rainfall_fn = mesh.topography ** 2.0
# vary these and visualise difference
m = fn.parameter(1.0)
n = fn.parameter(1.0)
K = fn.parameter(1.0)
# 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)
import lavavu
verts = np.reshape(mesh.tri.points, (-1,2))
verts = np.insert(verts, 2, values=mesh.topography.data, axis=1)
# setup viewer
lv = lavavu.Viewer(border=False, background="#FFFFFF", resolution=[1000,600], near=-10.0)
tri1 = lv.triangles("triangles", wireframe=False)
tri1.vertices(verts)
tri1.indices(mesh.tri.simplices)
tri1.values(sp, "stream_power")
tri1.colourmap("drywet")
tri1.colourbar()
lv.window()
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(1.0)
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)
transport_solver.rainfall = rainfall_fn
transport_solver.verify()
Timestepping routine¶
import lavavu
verts = np.reshape(mesh.tri.points, (-1,2))
verts = np.insert(verts, 2, values=mesh.topography.data, axis=1)
mesh.save_mesh_to_hdf5("mesh.h5")
# setup viewer
lv = lavavu.Viewer(border=False, background="#FFFFFF", resolution=[1000,600], near=-10.0)
tri1 = lv.triangles("triangles", wireframe=False)
tri1.vertices(verts)
tri1.indices(mesh.tri.simplices)
save_fields = False
plot_lavavu = True
efficiency = fn.parameter(1.0)
# reset topography
mesh.verbose = False
with mesh.deform_topography():
mesh.topography.data = height.copy()
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 = 50
for i in range(0, 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)
dhdt = diffusion_rate - erosion_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)
dhdt = diffusion_rate - erosion_rate #+ deposition_rate
# now take full timestep
with mesh.deform_topography():
mesh.topography.data = topography0.data + dt*dhdt
# deal with local minima
# mesh.low_points_local_patch_fill()
# save fields
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))
if plot_lavavu:
lv.addstep(i)
verts[:,2] = mesh.topography.data
tri1.vertices(verts)
tri1.indices(mesh.tri.simplices)
tri1.values(erosion_rate, "incision")
tri1.values(deposition_rate, "deposition")
tri1.values(diffusion_rate, "diffusion")
sim_time += dt
if i/steps*100 in list(range(0,100,10)):
print(stats.format(i, dt, sim_time, mesh.topography.min(), mesh.topography.data.mean(),
mesh.topography.max(), time() - t))
# change in topography
delta_H = mesh.add_variable("dH")
delta_H.unlock()
delta_H.data = mesh.topography.data - height
delta_H.lock()
tri1.colourmap("drywet")
tri1.colourbar()
tri1.control.List(options=
["incision", "deposition", "diffusion"],
property="colourby", value="kappa", command="redraw")
# There are issues with lavavu here
lv.control.TimeStepper()
lv.window()
# Plot the stream power, erosion and deposition rates
fig, (ax1, ax2, ax3) = plt.subplots(1,3, figsize=(50,15))
for ax in [ax1, ax2, ax3]:
ax.axis('equal')
ax.axis('off')
dhmax = np.abs(delta_H.data).mean() * 3.0
# ermax = np.abs(incision_rate.data).mean() * 3.0
# depmax = np.abs(dhdt_fn.evaluate(mesh)).mean() * 3.0
#im1 = ax1.tripcolor(x, y, sp.tri.simplices, delta, cmap=plt.cm.RdBu, vmin=-dhmax, vmax=dhmax)
im1 = ax1.tripcolor(x, y, mesh.tri.simplices, mesh.topography.data, cmap=plt.cm.terrain)
im2 = ax2.tripcolor(x, y, mesh.tri.simplices, delta_H.data, cmap='RdBu', vmin=-dhmax, vmax=dhmax)
im3 = ax3.tripcolor(x, y, mesh.tri.simplices, dhdt, cmap='RdBu_r',)
fig.colorbar(im1, ax=ax1)
fig.colorbar(im2, ax=ax2)
fig.colorbar(im3, ax=ax3)
plt.show()