Example 2D Problem in PythonΒΆ

import fdfault
import numpy as np

# create problem

p = fdfault.problem('input_example')

# set rk and fd order

p.set_rkorder(4)
p.set_sbporder(4)

# set time step info

p.set_nt(1601)
p.set_cfl(0.3)
p.set_ninfo(50)

# set number of blocks and coordinate information

p.set_nblocks((1,2,1))
p.set_nx_block(([1601], [801, 801], [1]))

# set block dimensions

p.set_block_lx((0,0,0),(40.,20.))
p.set_block_lx((0,1,0),(40.,20.))

# set block boundary conditions

p.set_bounds((0,0,0),['absorbing', 'absorbing', 'absorbing', 'none'])
p.set_bounds((0,1,0),['absorbing', 'absorbing', 'none', 'absorbing'])

# set block surface

x = np.linspace(0., 40., 1601)
y = 20.*np.ones(1601)+0.5*np.sin(np.pi*x/40.)

surf = fdfault.curve(1601, 'y', x, y)

p.set_block_surf((0,0,0), 3, surf)
p.set_block_surf((0,1,0), 2, surf)

# set initial fields

p.set_stress((-100., 70., 0., -120., 0., 0.))

# set interface type

p.set_iftype(0,'slipweak')

# set slip weakening parameters

p.add_pert(fdfault.swparam('constant', dc = 0.4, mus = 0.676, mud = 0.525),0)
p.add_pert(fdfault.swparam('boxcar', x0 = 2.5, dx = 2.5, mus = 10000.),0)
p.add_pert(fdfault.swparam('boxcar', x0 = 37.5, dx = 2.5, mus = 10000.),0)

# add load perturbations

p.add_load(fdfault.load('boxcar',0., 20., 1.5, 0., 0., 0., 11.6, 0.))

# add output unit

p.add_output(fdfault.output('vxbody','vx',0, 1600, 50, 0, 1600, 2, 0, 1600, 2, 0, 0, 1))
p.add_output(fdfault.output('vybody','vy',0, 1600, 50, 0, 1600, 2, 0, 1600, 2, 0, 0, 1))
p.add_output(fdfault.output('vfault','V',0, 1600, 10, 0, 1600, 1, 801, 801, 1, 0, 0, 1))

p.write_input()

input_example.py illustrates how to set up a 2D problem with an irregular fault geometry and a uniform regional stress tensor. The diagram below shows the setup of the problem:

examples/input_example.*

Note that this illustration is not to scale when representing the height of the nonplanar fault surface (in the picture, the height of the fault curve is exaggerated).

The problem is very similar to test2d.in, but uses a Python file to handle the irregular coordinate geometry in order to automatically generate the files needed for the fault surface. In the python code, the surface is generated using numpy arrays and combined into a curve object. The curve object is then assigned to form the upper edge of the lower block and the lower edge of the upper block. The C++ code automatically handles grid generation once this boundary is specified for each block, so no additional information is require to set the mesh for the problem. However, if you attempt to set the two neighboring surfaces representing the fault to have different coordinates, the Python and C++ codes will give you an error message.

Because this problem uses an irregular surface, the initial stress is set using a uniform background stress tensor, rather than by specifying tractions on the fault surface. When the stress tensor is resolved onto the irregular fault surface, the shear and normal tractions become spatially variable and the rupture will not propagate uniformly in both spatial directions. In particular, slip is easier to the right of the hypocenter due to the fact that the right side is a releasing bend, while to the left of the hypocenter, the fault constitutes a restraining bend such that slip is slightly inhibited.

Other than these two differences, the problem setup is identical. This serves as an example of how to use the various classes in the Python module for creating a problem. In particular, the script uses the problem, curve, and output classes to handle the problem, curves representing block boundaries, and output units, respectively. In addition to these classes, the main additional class that is frequently used in creating problems is the material class, which sets the off-fault material properties in a given block.