-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
306477a
commit fd65762
Showing
2 changed files
with
347 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
# Model setup | ||
As described in the original [paper](https://doi.org/10.5194/se-15-567-2024), the domain consists of a Cartesian box of $\Omega \in [0, 3000] \times [0, -660]$ km, with two 80km thick oceanic plates over the asthenospheric mantle. | ||
|
||
We will use GeophysicalModelGenerator.jl to generate the initial geometry, material phases, and thermal field of our models. We will start by defining the dimensions and resolution of our model, as well as initializing the `Grid2D` object and two arrays `Phases` and `Temp` that host the material phase (given by an integer) and the thermal field, respectively. | ||
|
||
```julia | ||
nx, nz = 512, 218 | ||
Tbot = 1474.0 # [Celsius] | ||
model_depth = 660 | ||
air_thickness = 10 | ||
x = range(0, 3000, nx); | ||
z = range(-model_depth, air_thickness, nz); | ||
Grid2D = CartData(xyz_grid(x,0,z)) | ||
Phases = zeros(Int64, nx, 1, nz); | ||
Temp = fill(Tbot, nx, 1, nz); | ||
``` | ||
|
||
In this model we have four material phases given by: | ||
|
||
| Material | Phase number | | ||
| :---------------- | :----------: | | ||
| asthenosphere | 0 | | ||
| oceanic lithosphere | 1 | | ||
| oceanic crust | 3 | | ||
| air | 4 | | ||
|
||
We will start by initializing the model as asthenospheric mantle, with a thermal profile given by the half-space cooling model with an age of 80 Myrs. | ||
|
||
```julia | ||
add_box!( | ||
Phases, | ||
Temp, | ||
Grid2D; | ||
xlim =(0, 3000), | ||
zlim =(-model_depth, 0.0), | ||
phase = LithosphericPhases(Layers=[], Phases=[0]), | ||
T = HalfspaceCoolingTemp(Tsurface=20, Tmantle=Tbot, Age=80,Adiabat=0.4) | ||
) | ||
``` | ||
|
||
Next we add a horizontal 80km thick oceanic lithosphere. Note that we leave a 100km buffer zone next to the vertical boundaries of the domain, to facilitate the sliding of the oceanic plates. | ||
```julia | ||
add_box!( | ||
Phases, | ||
Temp, | ||
Grid2D; | ||
xlim =(100, 3000-100), # with 100 km buffer zones | ||
zlim =(-model_depth, 0.0), | ||
phase = LithosphericPhases(Layers=[80], Phases=[1 0]), | ||
T = HalfspaceCoolingTemp(Tsurface=20, Tmantle=Tbot, Age=80, Adiabat=0.4) | ||
) | ||
``` | ||
|
||
As in the original paper, we add a 8km thick crust on top of the subducting oceanic plate. | ||
```julia | ||
# Add right oceanic plate crust | ||
add_box!( | ||
Phases, | ||
Temp, | ||
Grid2D; | ||
xlim =(3000-1430, 3000-200), | ||
zlim =(-model_depth, 0.0), | ||
Origin = nothing, StrikeAngle=0, DipAngle=0, | ||
phase = LithosphericPhases(Layers=[8 72], Phases=[2 1 0]), | ||
T = HalfspaceCoolingTemp(Tsurface=20, Tmantle=Tbot, Age=80, Adiabat=0.4) | ||
) | ||
``` | ||
|
||
And finally we add the subducting slab, whith the trench located at 1430km from the right-hand-side boundary. | ||
|
||
```julia | ||
add_box!( | ||
Phases, | ||
Temp, | ||
Grid2D; | ||
xlim = (3000-1430, 3000-1430-250), | ||
zlim = (-80, 0.0), | ||
Origin = (nothing, StrikeAngle=0, DipAngle=-30), | ||
phase = LithosphericPhases(Layers=[8 72], Phases=[2 1 0]), | ||
T = HalfspaceCoolingTemp(Tsurface=20, Tmantle=Tbot, Age=80, Adiabat=0.4) | ||
) | ||
``` | ||
|
||
```julia | ||
heatmap(x,z,Temp[:,1,:]) | ||
|
||
surf = Grid2D.z.val .> 0.0 | ||
Temp[surf] .= 20.0 | ||
Phases[surf] .= 3 | ||
|
||
Grid2D = addfield(Grid2D,(;Phases, Temp)) | ||
|
||
li = (abs(last(x)-first(x)), abs(last(z)-first(z))).* 1e3 | ||
origin = (x[1], z[1]) .* 1e3 | ||
|
||
ph = Phases[:,1,:] .+ 1 | ||
|
||
li, origin, ph, Temp[:,1,:].+273 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,248 @@ | ||
# 2D subduction | ||
|
||
Model setups taken from [Hummel, et al 2024](https://doi.org/10.5194/se-15-567-2024). | ||
|
||
# Model setup | ||
We will use GeophysicalModelGenerator.jl to generate the initial geometry, material phases, and thermal field of our models. | ||
|
||
|
||
# Initialize packages | ||
|
||
Load JustRelax necessary modules and define backend. | ||
```julia | ||
using CUDA | ||
using JustRelax, JustRelax.JustRelax2D, JustRelax.DataIO | ||
const backend_JR = CUDABackend | ||
``` | ||
|
||
For this benchmark we will use particles to track the advection of the material phases and their information. For this, we will use [JustPIC.jl](https://github.com/JuliaGeodynamics/JustPIC.jl) | ||
```julia | ||
using JustPIC, JustPIC._2D | ||
const backend = CPUBackend # Options: CPUBackend, CUDABackend, AMDGPUBackend | ||
``` | ||
|
||
We will also use `ParallelStencil.jl` to write some device-agnostic helper functions: | ||
```julia | ||
using ParallelStencil | ||
@init_parallel_stencil(Threads, Float64, 2) #or (CUDA, Float64, 2) or (AMDGPU, Float64, 2) | ||
``` | ||
and will use [GeoParams.jl](https://github.com/JuliaGeodynamics/GeoParams.jl/tree/main) to define and compute physical properties of the materials: | ||
```julia | ||
using GeoParams | ||
``` | ||
|
||
# Script | ||
|
||
## Model domain | ||
```julia | ||
nx = ny = 64 # number of cells per dimension | ||
igg = IGG( | ||
init_global_grid(nx, ny, 1; init_MPI= true)... | ||
) # initialize MPI grid | ||
ly = 1.0 # domain length in y | ||
lx = ly # domain length in x | ||
ni = nx, ny # number of cells | ||
li = lx, ly # domain length in x- and y- | ||
di = @. li / ni # grid step in x- and -y | ||
origin = 0.0, 0.0 # origin coordinates | ||
grid = Geometry(ni, li; origin = origin) | ||
(; xci, xvi) = grid # nodes at the center and vertices of the cells | ||
dt = Inf | ||
``` | ||
|
||
## Physical properties using GeoParams | ||
```julia | ||
τ_y = 1.6 # yield stress. If do_DP=true, τ_y stand for the cohesion: c*cos(ϕ) | ||
ϕ = 30 # friction angle | ||
C = τ_y # Cohesion | ||
η0 = 1.0 # viscosity | ||
G0 = 1.0 # elastic shear modulus | ||
Gi = G0/(6.0-4.0) # elastic shear modulus perturbation | ||
εbg = 1.0 # background strain-rate | ||
η_reg = 8e-3 # regularisation "viscosity" | ||
dt = η0/G0/4.0 # assumes Maxwell time of 4 | ||
el_bg = ConstantElasticity(; G=G0, Kb=4) | ||
el_inc = ConstantElasticity(; G=Gi, Kb=4) | ||
visc = LinearViscous(; η=η0) | ||
pl = DruckerPrager_regularised(; # non-regularized plasticity | ||
C = C, | ||
ϕ = ϕ, | ||
η_vp = η_reg, | ||
Ψ = 0 | ||
) | ||
``` | ||
## Rheology | ||
```julia | ||
rheology = ( | ||
# Low density phase | ||
SetMaterialParams(; | ||
Phase = 1, | ||
Density = ConstantDensity(; ρ = 0.0), | ||
Gravity = ConstantGravity(; g = 0.0), | ||
CompositeRheology = CompositeRheology((visc, el_bg, pl)), | ||
Elasticity = el_bg, | ||
|
||
), | ||
# High density phase | ||
SetMaterialParams(; | ||
Density = ConstantDensity(; ρ = 0.0), | ||
Gravity = ConstantGravity(; g = 0.0), | ||
CompositeRheology = CompositeRheology((visc, el_inc, pl)), | ||
Elasticity = el_inc, | ||
), | ||
) | ||
``` | ||
|
||
# Phase anomaly | ||
|
||
Helper function to initialize material phases with `ParallelStencil.jl` | ||
```julia | ||
function init_phases!(phase_ratios, xci, radius) | ||
ni = size(phase_ratios.center) | ||
origin = 0.5, 0.5 | ||
|
||
@parallel_indices (i, j) function init_phases!(phases, xc, yc, o_x, o_y, radius) | ||
x, y = xc[i], yc[j] | ||
if ((x-o_x)^2 + (y-o_y)^2) > radius^2 | ||
JustRelax.@cell phases[1, i, j] = 1.0 | ||
JustRelax.@cell phases[2, i, j] = 0.0 | ||
|
||
else | ||
JustRelax.@cell phases[1, i, j] = 0.0 | ||
JustRelax.@cell phases[2, i, j] = 1.0 | ||
end | ||
return nothing | ||
end | ||
|
||
@parallel (@idx ni) init_phases!(phase_ratios.center, xci..., origin..., radius) | ||
end | ||
|
||
``` | ||
|
||
and finally we need the phase ratios at the cell centers: | ||
```julia | ||
phase_ratios = PhaseRatio(backend_JR, ni, length(rheology)) | ||
init_phases!(phase_ratios, xci, radius) | ||
``` | ||
|
||
## Stokes arrays | ||
|
||
Stokes arrays object | ||
```julia | ||
stokes = StokesArrays(backend_JR, ni) | ||
``` | ||
|
||
## Initialize viscosity fields | ||
|
||
We initialize the buoyancy forces and viscosity | ||
```julia | ||
ρg = @zeros(ni...), @zeros(ni...) | ||
η = @ones(ni...) | ||
args = (; T = thermal.Tc, P = stokes.P, dt = Inf) | ||
compute_ρg!(ρg[2], phase_ratios, rheology, args) | ||
compute_viscosity!(stokes, 1.0, phase_ratios, args, rheology, (-Inf, Inf)) | ||
``` | ||
where `(-Inf, Inf)` is the viscosity cutoff. | ||
|
||
## Boundary conditions | ||
```julia | ||
flow_bcs = FlowBoundaryConditions(; | ||
free_slip = (left = true, right = true, top = true, bot = true), | ||
no_slip = (left = false, right = false, top = false, bot=false), | ||
) | ||
stokes.V.Vx .= PTArray([ x*εbg for x in xvi[1], _ in 1:ny+2]) | ||
stokes.V.Vy .= PTArray([-y*εbg for _ in 1:nx+2, y in xvi[2]]) | ||
flow_bcs!(stokes, flow_bcs) # apply boundary conditions | ||
update_halo!(stokes.V.Vx, stokes.V.Vy) | ||
|
||
``` | ||
|
||
## Pseuo-transient coefficients | ||
```julia | ||
pt_stokes = PTStokesCoeffs(li, di; ϵ=1e-4, CFL = 1 / √2.1) | ||
``` | ||
|
||
## Just before solving the problem... | ||
In this benchmark we want to keep track of τII, the total time `ttot`, and the analytical elastic solution `sol` | ||
```julia | ||
solution(ε, t, G, η) = 2 * ε * η * (1 - exp(-G * t / η)) | ||
``` | ||
and store their time history in the vectors: | ||
```julia | ||
τII = Float64[] | ||
sol = Float64[] | ||
ttot = Float64[] | ||
``` | ||
|
||
## Advancing one time step | ||
|
||
1. Solve stokes | ||
```julia | ||
solve!( | ||
stokes, | ||
pt_stokes, | ||
di, | ||
flow_bcs, | ||
ρg, | ||
phase_ratios, | ||
rheology, | ||
args, | ||
dt, | ||
igg; | ||
kwargs = (; | ||
iterMax = 150e3, | ||
nout = 200, | ||
viscosity_cutoff = (-Inf, Inf), | ||
verbose = true | ||
) | ||
) | ||
``` | ||
2. calculate the second invariant and push to history vectors | ||
```julia | ||
tensor_invariant!(stokes.ε) | ||
push!(τII, maximum(stokes.τ.xx)) | ||
|
||
@parallel (@idx ni .+ 1) multi_copy!(@tensor(stokes.τ_o), @tensor(stokes.τ)) | ||
@parallel (@idx ni) multi_copy!( | ||
@tensor_center(stokes.τ_o), @tensor_center(stokes.τ) | ||
) | ||
|
||
it += 1 | ||
t += dt | ||
|
||
push!(sol, solution(εbg, t, G0, η0)) | ||
push!(ttot, t) | ||
``` | ||
# Visualization | ||
We will use `Makie.jl` to visualize the results | ||
```julia | ||
using GLMakie | ||
``` | ||
|
||
## Fields | ||
```julia | ||
# visualisation of high density inclusion | ||
th = 0:pi/50:3*pi; | ||
xunit = @. radius * cos(th) + 0.5; | ||
yunit = @. radius * sin(th) + 0.5; | ||
|
||
fig = Figure(size = (1600, 1600), title = "t = $t") | ||
ax1 = Axis(fig[1,1], aspect = 1, title = L"\tau_{II}", titlesize=35) | ||
ax2 = Axis(fig[2,1], aspect = 1, title = L"E_{II}", titlesize=35) | ||
ax3 = Axis(fig[1,2], aspect = 1, title = L"\log_{10}(\varepsilon_{II})", titlesize=35) | ||
ax4 = Axis(fig[2,2], aspect = 1) | ||
heatmap!(ax1, xci..., Array(stokes.τ.II) , colormap=:batlow) | ||
heatmap!(ax2, xci..., Array(log10.(stokes.EII_pl)) , colormap=:batlow) | ||
heatmap!(ax3, xci..., Array(log10.(stokes.ε.II)) , colormap=:batlow) | ||
lines!(ax2, xunit, yunit, color = :black, linewidth = 5) | ||
lines!(ax4, ttot, τII, color = :black) | ||
lines!(ax4, ttot, sol, color = :red) | ||
hidexdecorations!(ax1) | ||
hidexdecorations!(ax3) | ||
save(joinpath(figdir, "$(it).png"), fig) | ||
fig | ||
``` | ||
|
||
### Final model | ||
Shear Bands evolution in a 2D visco-elasto-plastic rheology model | ||
![Shearbands](../assets/movies/DP_nx2058_2D.gif) |