This requires cascadia30.mshout
containing the geometry of the triangulated fault surface, from
https://github.com/dmelgarm/MudPy/blob/master/examples/fakequakes/3D/cascadia30.mshout
It also requires a rupture scenario in the form of a .rupt
file from the collection of fakequakes at https://zenodo.org/record/59943#.WgHuahNSxE4.
This sample uses one rupture scenario extracted from data/cascadia.001297
.
%matplotlib inline
from clawpack.geoclaw import dtopotools
import numpy as np
from copy import copy
import matplotlib.pyplot as pl
import os
fault_geometry_file = './cascadia30.mshout'
print('Reading fault geometry from %s' % fault_geometry_file)
print('\nHeader:\n')
print(open(fault_geometry_file).readline())
# read in .mshout (CSZ geoemetry)
cascadia = np.loadtxt(fault_geometry_file,skiprows=1)
cascadia[:,[3,6,9,12]] = 1e3*abs(cascadia[:,[3,6,9,12]])
print('Loaded geometry for %i triangular subfaults' % cascadia.shape[0])
For example, the first triangular fault in the given geometry of CSZ has the nodes
print(cascadia[0,4:7])
print(cascadia[0,7:10])
print(cascadia[0,10:13])
Set up a fault model with these subfaults, without yet specifying a particular earthquake scenario.
fault0 = dtopotools.Fault()
fault0.subfaults = []
nsubfaults = cascadia.shape[0]
for j in range(nsubfaults):
subfault0 = dtopotools.SubFault()
node1 = cascadia[j,4:7].tolist()
node2 = cascadia[j,7:10].tolist()
node3 = cascadia[j,10:13].tolist()
node_list = [node1,node2,node3]
subfault0.set_corners(node_list,projection_zone='10T')
fault0.subfaults.append(subfault0)
Now we can plot the triangular subplots:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy
fig = plt.figure(figsize=(15,10))
#ax = fig.add_subplot(121, projection='3d')
ax = fig.add_axes([.05,.05,.65,.9], projection='3d')
for s in fault0.subfaults:
c = s.corners
c.append(c[0])
c = numpy.array(c)
ax.plot(c[:,0],c[:,1],-c[:,2]/1000.,color='b')
ax.view_init(10,60)
ax.set_xlabel('Longitude')
ax.set_ylabel('Latitude')
ax.set_zlabel('Depth (km)')
ax.set_title('Triangular subfaults')
#ax = fig.add_subplot(122)
ax = fig.add_axes([.75,.05,.2,.9])
for s in fault0.subfaults:
c = s.corners
c.append(c[0])
c = numpy.array(c)
ax.plot(c[:,0],c[:,1], 'b')
ax.set_aspect(1./numpy.cos(45*numpy.pi/180.))
ax.set_xlabel('Longitude')
ax.set_ylabel('Latitude')
ax.set_title('Plan view')
We now read in rupture scenario, using data from [https://zenodo.org/record/59943#.WgHuahNSxE4].
rupt_fname = '_cascadia.001297.rupt'
print("Reading earthquake data from %s" % rupt_fname)
rupture_parameters = np.loadtxt(rupt_fname,skiprows=1)
This data is used to set the slip and rake on each of the subfaults loaded above. Since this is a dynamic rupture, we also set the rupture_time
and rise_time
of each subfault.
fault0 = dtopotools.Fault()
fault0.subfaults = []
fault0.rupture_type = 'kinematic'
rake = 90. # assume same rake for all subfaults
J = int(np.floor(cascadia.shape[0]))
for j in range(J):
subfault0 = dtopotools.SubFault()
node1 = cascadia[j,4:7].tolist()
node2 = cascadia[j,7:10].tolist()
node3 = cascadia[j,10:13].tolist()
node_list = [node1,node2,node3]
ss_slip = rupture_parameters[j,8]
ds_slip = rupture_parameters[j,9]
rake = np.rad2deg(np.arctan2(ds_slip, ss_slip))
subfault0.set_corners(node_list,projection_zone='10T')
subfault0.rupture_time = rupture_parameters[j,12]
subfault0.rise_time = rupture_parameters[j,7]
subfault0.rake = rake
slip = np.sqrt(ds_slip ** 2 + ss_slip ** 2)
subfault0.slip = slip
fault0.subfaults.append(subfault0)
We now run the create_dtopography
routine to generate dynamic seafloor deformations at a given set of times. This applies the Okada model to each of the subfaults and evaluates the surface displacement on the grid given by x,y
, at each time. These are summed up over all subfaults to compute the total deformation.
x,y = fault0.create_dtopo_xy(dx = 4/60.)
print('Will create dtopo on arrays of shape %i by %i' % (len(x),len(y)))
tfinal = max([subfault1.rupture_time + subfault1.rise_time for subfault1 in fault0.subfaults])
times0 = np.linspace(0.,tfinal,100)
dtopo0 = fault0.create_dtopography(x,y,times=times0,verbose=True);
x.shape,y.shape, dtopo0.dZ.shape
fig,(ax0,ax1,ax2, ax3) = pl.subplots(ncols=4,nrows=1,figsize=(16,6))
fault0.plot_subfaults(axes=ax0,slip_color=True,plot_box=False);
ax0.set_title('Slip on Fault');
X = dtopo0.X; Y = dtopo0.Y; dZ_at_t = dtopo0.dZ_at_t
dz_max = dtopo0.dZ.max()
t0 = 0.25*tfinal # time to plot deformation
dtopotools.plot_dZ_colors(X,Y,dZ_at_t(t0),axes=ax1,
cmax_dZ = dz_max, add_colorbar=False);
ax1.set_title('Seafloor at time t=' + str(t0));
t0 = 0.5*tfinal # time to plot deformation
dtopotools.plot_dZ_colors(X,Y,dZ_at_t(t0),axes=ax2,
cmax_dZ = dz_max, add_colorbar=False);
ax2.set_title('Seafloor at time t=' + str(t0));
t0 = tfinal # time to plot deformation
dtopotools.plot_dZ_colors(X,Y,dZ_at_t(t0),axes=ax3,
cmax_dZ = dz_max, add_colorbar=True);
ax3.set_title('Seafloor at time t=' + str(t0));
#fig.savefig('CSZ_triangular.png');
This shows where the rupture originates and how it propagates outward. Each vertical bar shows the rupture time and duration of one subfault.
pl.figure(figsize=(14,8))
pl.axes()
latitudes = [s.latitude for s in fault0.subfaults]
rise_times = [s.rise_time for s in fault0.subfaults]
rupture_times = [s.rupture_time for s in fault0.subfaults]
for j,lat in enumerate(latitudes):
pl.plot([lat,lat],[rupture_times[j],rupture_times[j]+rise_times[j]],'b')
pl.xlabel('latitude')
pl.ylabel('seconds')
pl.title('rupture time + rise time of each triangle vs. latitude')
Same longitude, increasing latitude...
pl.figure(figsize=(10,9))
for kk in range(5):
pl.subplot(5,1,kk+1)
j = 60
k = 50 + 25*kk
pl.title('dynamic deformation at fixed location (' + '{:4.2f}'.format(x[j]) \
+ ',' + '{:4.2f}'.format(y[k]) + ')' )
pl.plot(dtopo0.times,dtopo0.dZ[:,k,j]);
pl.ylabel('dZ (meters)');
pl.xlabel('time (seconds)');
pl.tight_layout()
ruptno = rupt_fname.split('.')[1]
fname = 'cascadia' + ruptno + '.dtt3'
dtopo0.write(fname, dtopo_type=3)
print('Created %s, with dynamic rupture of a Mw %.2f event' % (fname, fault0.Mw()))
from clawpack.visclaw.JSAnimation import IPython_display
import clawpack.visclaw.JSAnimation.JSAnimation_frametools as J
dz_max = abs(dtopo0.dZ).max()
# Incorporate this function in dtopotools to replace animate_dz_colors?
def plot_subfaults_dZ(t, fig):
fig.clf()
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
fault0.plot_subfaults(axes=ax1, slip_color=True, plot_box=False,
slip_time=t)
dtopo0.plot_dZ_colors(axes=ax2, t=t, cmax_dZ=dz_max)
return fig
plotdir = '_plots'
J.make_plotdir(plotdir, clobber=True)
fig = pl.figure(figsize=(12,5))
for k,t in enumerate(dtopo0.times[::10]):
plot_subfaults_dZ(t,fig)
J.save_frame(k, verbose=False)
pl.close(fig)
anim = J.make_anim(plotdir)
anim