Example 1D
Note
This example is from Benchmark Problem 1 (hence referred as BP1).
Define Parameters¶
First, we load the package
1 2 | using JuEQ using Plots |
Instead of using SI unit, we refactor ours into the follow:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | ms2mmyr = 365 * 86400 * 1e3 # convert velocity from m/s to mm/yr ρ = 2670.0 # density [kg/m³] vs = 3464.0 # shear wave velocity [m/s] σ = 500.0 # effective normal stress [bar] a0 = 0.010 # frictional paramter `a` in vw zone amax = 0.025 # frictional paramter `a` in vs zone b0 = 0.015 # frictional paramter `b` L = 8.0 # critical distance [mm] vpl = 1e-9 * ms2mmyr # plate rate [mm/yr] vinit = 1e-9 * ms2mmyr # initial velocity [mm/yr] v0 = 1e-6 * ms2mmyr # reference velocity [mm/yr] f0 = 0.6 # reference frictional coefficient H = 15.0 # vw zone [km] h = 3.0 # vw-vs changing zone [km] Wf = 40.0 # fault depth [km] Δz = 100.0e-3 # grid size interval [km] tf = 400.0; # simulation time [yr] |
1 | 400.0 |
Warning
Make sure your units are consistent across the whole variable space. Pontenial imporvement may incoporate Unitful.jl package.
Then we arrive at some parameters that are implicit by above:
1 2 3 4 | μ = vs^2 * ρ / 1e5 / 1e6 # shear modulus [bar·km/mm] λ = μ # poisson material η = μ / 2(vs * 1e-3 * 365 * 86400) ngrid = round(Int, Wf / Δz); # number of grids |
1 | 400 |
Now, we start to construct our model using parameters above. First, we create a 'fault' by specifying fault type and depth:
Tip
Here, we do not need to provide dip
for strike-slip fault as it automatically choose 90
. See fault
.
Construct Model¶
1 | fa = fault(StrikeSlipFault, Wf); |
1 | PlaneFaultDomain{StrikeSlipFault,1,Float64}(90.0, (40.0,)) |
Next, we generate the grid regarding the fault
we just created by giving number of grids:
Note
This package use ξ
for denoting downdip coordinate and x
for along-strike one. See discretize
.
1 | gd = discretize(fa; nξ=ngrid); |
1 | JuEQ.BEMGrid_1D{Array{Float64,1},Array{Array{Float64,1},1},Float64,Int64}([-0.05, -0.15, -0.25, -0.35, -0.45, -0.55, -0.65, -0.75, -0.85, -0.95 … -39.05, -39.15, -39.25, -39.35, -39.45, -39.55, -39.65, -39.75, -39.85, -39.95], 0.1, 400, Array{Float64,1}[[-0.1, 0.0], [-0.2, -0.1], [-0.3, -0.2], [-0.4, -0.3], [-0.5, -0.4], [-0.6, -0.5], [-0.7, -0.6], [-0.8, -0.7], [-0.9, -0.8], [-1.0, -0.9] … [-39.1, -39.0], [-39.2, -39.1], [-39.3, -39.2], [-39.4, -39.3], [-39.5, -39.4], [-39.6, -39.5], [-39.7, -39.6], [-39.8, -39.7], [-39.9, -39.8], [-40.0, -39.9]], [-0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0 … -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0], [-0.05, -0.15, -0.25, -0.35, -0.45, -0.55, -0.65, -0.75, -0.85, -0.95 … -39.05, -39.15, -39.25, -39.35, -39.45, -39.55, -39.65, -39.75, -39.85, -39.95], [-500.0, 500.0]) |
Next, we construct the required frictional parameter profile:
1 2 3 4 | z = -gd.ξ az = fill(a0, size(z)) az[z .≥ (H + h)] .= amax az[H .< z .< H + h] = a0 .+ (amax - a0) / (h / Δz) * collect(1: Int(h / Δz)); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 30-element Array{Float64,1}: 0.0105 0.011 0.0115 0.012 0.0125 0.013000000000000001 0.0135 0.014 0.0145 0.015 ⋮ 0.020999999999999998 0.0215 0.022 0.0225 0.023 0.0235 0.024 0.0245 0.025 |
Then, we provide the required initial condition satisfying uniform slip distribution over the depth:
1 2 3 4 5 | τ0 = σ * amax * asinh(vinit / 2v0 * exp((f0 + b0 * log(v0 / vinit)) / amax)) + η * vinit τz = fill(τ0, size(z)) θz = @. L / v0 * exp(az / b0 * log(2v0 / vinit * sinh((τz - η * vinit) / az / σ)) - f0 / b0) vz = fill(vinit, size(z)) u0 = hcat(vz, θz); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 400×2 Array{Float64,2}: 31.536 0.000253678 31.536 0.000253678 31.536 0.000253678 31.536 0.000253678 31.536 0.000253678 31.536 0.000253678 31.536 0.000253678 31.536 0.000253678 31.536 0.000253678 31.536 0.000253678 ⋮ 31.536 0.253678 31.536 0.253678 31.536 0.253678 31.536 0.253678 31.536 0.253678 31.536 0.253678 31.536 0.253678 31.536 0.253678 31.536 0.253678 |
Let's simulate only the first 200 years:
1 | tspan = (0., 200.); |
1 | (0.0, 200.0) |
Finally, we provide the material properties w.r.t. our 'fault', 'grid' as well as other necessary parameters predefined using the same grid size & dimension:
1 | mp = properties(;fault=fa, grid=gd, parameters=[:a=>az, :b=>b0, :L=>L, :σ=>σ, :η=>η, :k=>[:λ=>λ, :μ=>μ], :vpl=>vpl, :f0=>f0, :v0=>v0]); |
1 2 3 4 5 6 7 8 9 10 11 12 13 | [ Info: Calculating stiffness tensor ... [ Info: Fault material properties establised. JuEQ.PlaneMaterialProperties{1,Float64,Array{Float64,1},Array{Float64,2}} dims: Tuple{Int64} a: Array{Float64}((400,)) [0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 … 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025] b: Array{Float64}((400,)) [0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015 … 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015] L: Array{Float64}((400,)) [8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0 … 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0] k: Array{Float64}((400, 400)) [1.35974 -0.815844 … -6.39586e-6 -6.36374e-6; -0.815844 1.98134 … -6.39609e-6 -6.36397e-6; … ; -6.39586e-6 -6.39609e-6 … 2.03961 -0.679871; -6.36374e-6 -6.36397e-6 … -0.679871 2.03961] σ: Array{Float64}((400,)) [500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0 … 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0] η: Array{Float64}((400,)) [1.4664e-9, 1.4664e-9, 1.4664e-9, 1.4664e-9, 1.4664e-9, 1.4664e-9, 1.4664e-9, 1.4664e-9, 1.4664e-9, 1.4664e-9 … 1.4664e-9, 1.4664e-9, 1.4664e-9, 1.4664e-9, 1.4664e-9, 1.4664e-9, 1.4664e-9, 1.4664e-9, 1.4664e-9, 1.4664e-9] vpl: Float64 31.536 f0: Float64 0.6 v0: Float64 31536.0 |
Tip
Check properties
for extended options.
Check our profile now:
1 | plot([mp.a, mp.b], z, label=["a", "b"], yflip=true, ylabel="Depth (km)") |
Documenter.Documents.RawHTML("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n
We then contruct the ODEProblem
as following by stating which state evolution law to use and frcitonal law form, plus initial condition and simulation time:
1 | prob = EarthquakeCycleProblem(gd, mp, u0, tspan; se=DieterichStateLaw(), fform=RForm()); |
1 2 3 | ODEProblem with uType Array{Float64,2} and tType Float64. In-place: true timespan: (0.0, 200.0) u0: [31.536 0.000253678; 31.536 0.000253678; … ; 31.536 0.253678; 31.536 0.253678] |
Solve Model¶
We then solve the ODEs:
1 | sol = solve(prob, Tsit5(), reltol=1e-6, abstol=1e-6); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | retcode: Success Interpolation: specialized 4th order "free" interpolation t: 4814-element Array{Float64,1}: 0.0 6.483553518719132e-5 9.44532839048002e-5 0.00014950199694886354 0.0001969017343314171 0.0002589370267499311 0.00032362086183610665 0.0004000242025107322 0.0004844340682573306 0.0005812591543481377 ⋮ 198.66317580661035 198.81599601090952 198.9735692145639 199.13681420817997 199.30704525039675 199.48496682770454 199.66952071102318 199.8589025257933 200.0 u: 4814-element Array{Array{Float64,2},1}: [31.536 0.000253678; 31.536 0.000253678; … ; 31.536 0.253678; 31.536 0.253678] [22.4215 0.000318453; 22.4215 0.000318453; … ; 31.536 0.253678; 31.536 0.253678] [19.6236 0.000348045; 19.6236 0.000348045; … ; 31.536 0.253678; 31.536 0.253678] [15.747 0.000403048; 15.747 0.000403048; … ; 31.536 0.253678; 31.536 0.253678] [13.3297 0.000450411; 13.3297 0.000450411; … ; 31.536 0.253678; 31.536 0.253678] [10.9855 0.000512401; 10.9855 0.000512401; … ; 31.536 0.253678; 31.536 0.253678] [9.1923 0.000577041; 9.1923 0.000577041; … ; 31.536 0.253678; 31.536 0.253678] [7.62907 0.000653395; 7.62907 0.000653395; … ; 31.536 0.253678; 31.536 0.253678] [6.35871 0.000737754; 6.35871 0.000737754; … ; 31.536 0.253678; 31.536 0.253678] [5.28542 0.000834524; 5.28542 0.000834524; … ; 31.536 0.253678; 31.536 0.253678] ⋮ [0.000251795 3.02087; 0.00025182 3.02087; … ; 39.5126 0.201016; 36.8001 0.216185] [0.000236784 3.17367; 0.000236808 3.17367; … ; 39.2862 0.202129; 36.6489 0.217045] [0.00022298 3.33123; 0.000223003 3.33123; … ; 39.0508 0.203309; 36.4921 0.217951] [0.000210202 3.49446; 0.000210224 3.49446; … ; 38.8067 0.204558; 36.3297 0.218908] [0.000198281 3.66468; 0.000198302 3.66468; … ; 38.5537 0.205881; 36.1616 0.219915] [0.000187127 3.84258; 0.000187147 3.84258; … ; 38.2928 0.207276; 35.9886 0.220973] [0.000176761 4.02712; 0.000176781 4.02712; … ; 38.0279 0.208724; 35.813 0.222065] [0.000167214 4.21648; 0.000167232 4.21648; … ; 37.7635 0.210201; 35.638 0.223175] [0.000160724 4.35757; 0.000160741 4.35757; … ; 37.5721 0.21129; 35.5113 0.223989] |
Tip
For details of solving options, see here.
Tip
Raise the accuracy option if you get instability when solving these ODEs.
Results¶
The first event happens at around 196 year:
1 2 | maxv = max_velocity(sol) plot(sol.t, log10.(maxv / ms2mmyr), xlabel="Time (year)", ylabel="Max Velocity (log10 (m/s))", xlims=(190, 200), label="") |
Documenter.Documents.RawHTML("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n
Note
Click here for the slip evolution over 3000 years simulation. It may need some time to load the page.
This page was generated using Literate.jl.