Skip to content

Commit

Permalink
wip to make it easier to generate setups for present-day areas
Browse files Browse the repository at this point in the history
  • Loading branch information
boriskaus committed Jul 19, 2023
1 parent f50914b commit b4dba1b
Show file tree
Hide file tree
Showing 13 changed files with 358 additions and 10 deletions.
1 change: 0 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ makedocs(;
"Example 1: Sphere" => "man/juliasetup_example_sphere.md",
"Example 2: Volcano" => "man/juliasetup_LaPalma.md",
"Pluto notebooks" => "man/juliasetup_pluto.md",

"Available functions" => "man/LaMEM_ModelFunctions.md"],
"Run LaMEM" => "man/runlamem.md",
"Reading timesteps" => "man/readtimesteps.md",
Expand Down
Binary file added docs/src/man/LaPalma_CrossSection.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/src/man/LaPalma_topo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
182 changes: 181 additions & 1 deletion docs/src/man/juliasetup_LaPalma.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,184 @@
# La Palma volcano setup
# La Palma Volcano setup

In this example, we will show how to create a 3D model setup for the 2020 La Palma eruption. We mainly focus on the LaMEM part; see the [GeophysicalModelGenerator](https://github.com/JuliaGeodynamics/GeophysicalModelGenerator.jl) package for more details on how to plot earthquake data etc.

#### 1. Load packages & topography
Let's start with what we need:
```julia
julia> using LaMEM, GeophysicalModelGenerator, GMT, Plots
Loading GMT routines within GMG
WARNING: using GMT.meshgrid in module GeophysicalModelGenerator conflicts with an existing identifier.
adding Plots.jl plotting extensions for LaMEM
```

Load the topography, choose a projection point & project the topography to cartesian coordinates:
```julia
julia> Topo = ImportTopo(lon = [-18.7, -17.1], lat=[28.0, 29.2], file="@earth_relief_03s.grd");
julia> proj = ProjectionPoint(Lon=-17.84, Lat=28.56);
julia> Topo_cart = Convert2CartData(Topo, proj)
CartData
size : (1921, 1441, 1)
x ϵ [ -86.09445705828863 : 73.67229892155609]
y ϵ [ -63.5531883197492 : 73.28446155584604]
z ϵ [ -4.38352685546875 : 2.414]
fields : (:Topography,)
attributes: ["note"]
```
This shows the dimensions of our domain in kilometers. The issue is that this projected topography is not an orthogonal grid, but (slightly) distorted. In any case, we see the approximate dimensions of the grid (in horizontal directions), so we can create an orthogonal grid on which to project this:

```julia
julia> Topo_LaMEM = CartData(XYZGrid(-70:.2:70,-60:.2:70,0));
julia> Topo_LaMEM = ProjectCartData(Topo_LaMEM, Topo, proj)
```

We can plot it with:
```julia
julia> plot_topo(topo, clim=(-4,4))
```

![LaPalma_topo](LaPalma_topo.png)


#### 2. LaMEM Model setup

Next, we generate a model setup for LaMEM with:
```julia
julia> model = Model(Grid(x=[-50.,50.], y=[-40.,40.], z=[-80,15] , nel=(64,64,32)) )
LaMEM Model setup
|
|-- Scaling : GeoParams.Units.GeoUnits{GEO}
|-- Grid : nel=(64, 64, 32); xϵ(-50.0, 50.0), yϵ(-40.0, 40.0), zϵ(-80.0, 15.0)
|-- Time : nstep_max=50; nstep_out=1; time_end=1.0; dt=0.05
|-- Boundary conditions : noslip=[0, 0, 0, 0, 0, 0]
|-- Solution parameters : eta_min=1.0e18; eta_max=1.0e25; eta_ref=1.0e20; act_temp_diff=0
|-- Solver options : direct solver; superlu_dist; penalty term=10000.0
|-- Model setup options : Type=files;
|-- Output options : filename=output; pvd=1; avd=0; surf=0
|-- Materials : 0 phases;
```

##### Set geotherm and phases
We can set an initial constant, linear, geotherm with:
```julia
julia> Z = model.Grid.Grid.Z;
julia> Geotherm=30
julia> model.Grid.Temp = -Z.*Geotherm;
```
We will cutoff extreme values with:
```julia
julia> model.Grid.Temp[model.Grid.Temp.<20] .= 20;
julia> model.Grid.Temp[model.Grid.Temp.>1350] .= 1350;
julia> model.Grid
LaMEM grid with constant Δ:
nel : ([64], [64], [32])
marker/cell : (3, 3, 3)
x ϵ [-50.0 : 50.0]
y ϵ [-40.0 : 40.0]
z ϵ [-80.0 : 15.0]
Phases : range ϵ [0 - 0]
Temp : range ϵ [20.0 - 1350.0]
```

Set `Phases` to two everywhere:
```julia
julia> model.Grid.Phases .= 2;
```

Now set points above the topography to zero (will be air later), the ones above the topography but below zero to 'water` and below 40 km to mantle (if we had a Moho surface we could use that):
```julia
julia> AboveSurface!(model, Topo_LaMEM, phase=0, T=0)
julia> model.Grid.Phases[Z.<-0 .&& model.Grid.Phases .== 0] .= 1;
julia> model.Grid.Phases[Z.<-40] .= 3;
```
Finally, we define some magma chambers:
```julia
julia> AddSphere!(model, cen=(0,0,-35), radius=5, phase=ConstantPhase(5), T=ConstantTemp(1200));
julia> AddEllipsoid!(model, cen=(-1,0,-11), axes=(3,3,8), StrikeAngle=225, DipAngle=45, phase=ConstantPhase(5), T=ConstantTemp(1200));
julia> AddEllipsoid!(model, cen=(-0,0,-23), axes=(8,8,2), StrikeAngle=0, DipAngle=0, phase=ConstantPhase(5), T=ConstantTemp(1200));
```
We can plot a cross-section through the model:
```julia
julia> heatmap(model, x=0, field=:phase)
```
![LaPalma_CrossSection](LaPalma_CrossSection.png)
##### Set material properties
First we set air and water properties:
```julia
julia> air = set_air(alpha=3e-5, G=1e10, nu=0.2, ch=10e6, fr=30)
Phase 0 (air):
rho = 100.0
eta = 1.0e17
G = 1.0e10
nu = 0.2
ch = 1.0e7
fr = 30.0
alpha = 3.0e-5
Cp = 1000.0
k = 30.0
julia> water=deepcopy(air); water.Name="water"; water.ID=1
```
Next, we set the crust:
```julia
julia> crust = Phase(Name="Crust", ID=2, rho=2900, alpha=3e-5, disl_prof="Mafic_Granulite-Ranalli_1995",
G=3e10, nu=0.2, k=3, Cp=1000, ch=10e6, fr=30)
Phase 2 (Crust):
rho = 2900.0
disl_prof = Mafic_Granulite-Ranalli_1995
G = 3.0e10
nu = 0.2
ch = 1.0e7
fr = 30.0
alpha = 3.0e-5
Cp = 1000.0
k = 3.0
```
The mantle is done as a copy of that, while changing a few parameters:
```julia
julia> mantle = copy_phase(crust, Name="Mantle", ID=3, rho=3320.0, disl_prof="Dry_Olivine-Ranalli_1995", G=6.5e10, k=3.3);
```
And we define two different types of magma:
```julia
julia> andesite = Phase(Name="andesitic_magma",ID=4,rho=2700, alpha=3e-5, eta=1e18, G=1.5e10, nu=0.2, k=3, Cp=1000, T=980, ch=1e7, fr=30);
julia> dacite = copy_phase(andesite,Name="dacite_magma", ID=5, rho=2575.0, eta=1e19, T=800.0)
```
Now we add all of this to the model:
```julia
julia> rm_phase!(model)
julia> add_phase!(model, air, water, crust, mantle, andesite, dacite)
```
And check that we indeed have 6 phases:
```julia
julia> model
LaMEM Model setup
|
|-- Scaling : GeoParams.Units.GeoUnits{GEO}
|-- Grid : nel=(64, 64, 32); xϵ(-50.0, 50.0), yϵ(-40.0, 40.0), zϵ(-80.0, 15.0)
|-- Time : nstep_max=50; nstep_out=1; time_end=1.0; dt=0.05
|-- Boundary conditions : noslip=[0, 0, 0, 0, 0, 0]
|-- Solution parameters : eta_min=1.0e18; eta_max=1.0e25; eta_ref=1.0e20; act_temp_diff=0
|-- Solver options : direct solver; superlu_dist; penalty term=10000.0
|-- Model setup options : Type=files;
|-- Output options : filename=output; pvd=1; avd=0; surf=0
|-- Materials : 0 phases;
```
##### Add topography to model
We can add the topography grid that we created earlier to the model with:
```julia
julia> add_topography!(model, Topo_LaMEM)
```
##### Set solver options
You will want to use a multigrid solver in this case:
```julia
julia> model.Solver = Solver(SolverType="multigrid")
```
### 3. Run LaMEM
3 changes: 2 additions & 1 deletion src/LaMEM.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export LaMEM_Model, Model, Write_LaMEM_InputFile, create_initialsetup,
Output,
Materials, Phase, Softening, PhaseTransition, Dike,
add_phase!, rm_phase!, rm_last_phase!, replace_phase!, add_petsc!, add_softening!,
add_phasetransition!, add_dike!, add_geom!
add_phasetransition!, add_dike!, add_geom!, set_air, copy_phase,
add_topography!, AboveSurface!, BelowSurface!


using .Run.LaMEM_jll
Expand Down
30 changes: 30 additions & 0 deletions src/LaMEM_ModelGeneration/ErrorChecking.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,35 @@ function Check_LaMEM_Model(m::Model)
return nothing
end

"""
is_rectilinear(topography::CartData)
Checks whether `topography` is rectilinear
"""
function is_rectilinear(topography::CartData)
dx = extrema(diff(ustrip.(topography.x.val[:,:,1]), dims=1))
dy = extrema(diff(ustrip.(topography.y.val[:,:,1]), dims=2))

return (dx[2] dx[1]) .& (dy[2] dy[1])
end

"""
within_bounds(model::Model, topography::CartData)
Verifies that the bounds of the topography grid are larger than that of the model
"""
function within_bounds(model::Model, topography::CartData)
x_topo = extrema(topography.x.val)
y_topo = extrema(topography.y.val)
x =extrema(model.Grid.Grid.X)
y =extrema(model.Grid.Grid.Y)

if (x_topo[1]>x[1]) || (x_topo[2]<x[2]) ||
(y_topo[1]>y[1]) || (y_topo[2]<y[2])
within = false
else
within = true
end
return within
end

7 changes: 5 additions & 2 deletions src/LaMEM_ModelGeneration/FreeSurface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@ Base.@kwdef mutable struct FreeSurface
hDown::Float64 = 0.1

"half of transition zone"
dTrans::Float64 = 1.0
dTrans::Float64 = 1.0

"Topography grid"
Topography::Union{CartData, Nothing} = nothing
end

# Print info about the structure
Expand Down Expand Up @@ -126,7 +129,7 @@ function Write_LaMEM_InputFile(io, d::FreeSurface)

if surf_use==1
for f in fields
if getfield(d,f) != getfield(Reference,f)
if getfield(d,f) != getfield(Reference,f) && (f != :Topography)
# only print if value differs from reference value
name = rpad(String(f),15)
comment = get_doc(FreeSurface, f)
Expand Down
59 changes: 58 additions & 1 deletion src/LaMEM_ModelGeneration/GMG_interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
#
# Some wrappers around GMG routines

import GeophysicalModelGenerator: AddBox!, AddSphere!, AddEllipsoid!, AddCylinder!
import GeophysicalModelGenerator: AddBox!, AddSphere!, AddEllipsoid!, AddCylinder!, AboveSurface, BelowSurface
export AboveSurface!, BelowSurface!

"""
AddBox!(model::Model; xlim=Tuple{2}, [ylim=Tuple{2}], zlim=Tuple{2},
Expand Down Expand Up @@ -49,3 +50,59 @@ See the documentation of the GMG routine
"""
AddEllipsoid!(model::Model; kwargs...) = AddEllipsoid!(model.Grid.Phases, model.Grid.Temp, model.Grid.Grid; kwargs...)


"""
AboveSurface(model::Model, DataSurface_Cart::CartData)
Returns a boolean grid that is `true` if the `Phases/Temp` grid are above the surface
"""
AboveSurface(model::Model, DataSurface_Cart::CartData) = AboveSurface(model.Grid.Grid, DataSurface_Cart)


"""
AboveSurface!(model::Model, DataSurface_Cart::CartData; phase::Int64=nothing, T::Number=nothing)
Sets the `Temp` or `Phases` above the surface `DataSurface_Cart` to a constant value.
"""
function AboveSurface!(model::Model, DataSurface_Cart::CartData; phase::Union{Int64,Nothing}=nothing, T::Union{Number,Nothing}=nothing)

id = AboveSurface(model, DataSurface_Cart)
if !isnothing(phase)
model.Grid.Phases[id] .= phase
end
if !isnothing(T)
model.Grid.Temp[id] .= T
end

return nothing
end




"""
BelowSurface(model::Model, DataSurface_Cart::CartData)
Returns a boolean grid that is `true` if the `Phases/Temp` grid are below the surface
"""
BelowSurface(model::Model, DataSurface_Cart::CartData) = BelowSurface(model.Grid.Grid, DataSurface_Cart)


"""
BelowSurface!(model::Model, DataSurface_Cart::CartData; phase::Union{Int64,Nothing}=nothing, T::Union{Number,Nothing}=nothing)
Sets the `Temp` or `Phases` below the surface `DataSurface_Cart` to a constant value.
"""
function BelowSurface!(model::Model, DataSurface_Cart::CartData; phase::Union{Int64,Nothing}=nothing, T::Union{Number,Nothing}=nothing)

id = BelowSurface(model, DataSurface_Cart)
if !isnothing(phase)
model.Grid.Phases[id] .= phase
end
if !isnothing(T)
model.Grid.Temp[id] .= T
end

return nothing
end
3 changes: 2 additions & 1 deletion src/LaMEM_ModelGeneration/LaMEM_Model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,11 @@ include("Model.jl") # main LaMEM_Model
export Model

include("GMG_interface.jl")
export AboveSurface!, BelowSurface!

include("Utils.jl")
export add_phase!, rm_phase!, rm_last_phase!, add_petsc!, add_softening!,
add_phasetransition!, add_dike!, add_geom!, cross_section
add_phasetransition!, add_dike!, add_geom!, cross_section, add_topography!


include("ErrorChecking.jl")
Expand Down
2 changes: 1 addition & 1 deletion src/LaMEM_ModelGeneration/Materials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ function show(io::IO, d::Phase)
# print fields
for f in fields
if !isnothing(getfield(d,f)) & (f != :ID) & (f != :Name)
printstyled(io," $(rpad(String(f),6)) = $(getfield(d,f)) \n")
printstyled(io," $(rpad(String(f),9)) = $(getfield(d,f)) \n")
end
end

Expand Down
4 changes: 4 additions & 0 deletions src/LaMEM_ModelGeneration/Model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ function create_initialsetup(model::Model, cores::Int64=1, args::String="")
end

Write_LaMEM_InputFile(model, model.Output.param_file_name)

if !isnothing(model.FreeSurface.Topography)
Save_LaMEMTopography(model.FreeSurface.Topography, model.FreeSurface.surf_topo_file)
end

if model.ModelSetup.msetup=="files"
# write marker files to disk before running LaMEM
Expand Down
Loading

0 comments on commit b4dba1b

Please sign in to comment.