Skip to content

Commit 0e47fee

Browse files
authored
Merge pull request #154 from adbayonao/Andres_Bayona_2
New function for generating tectonic plates with custom geometries and constant depth
2 parents 6fcbb86 + 7c602ad commit 0e47fee

File tree

3 files changed

+139
-3
lines changed

3 files changed

+139
-3
lines changed

src/Setup_geometry.jl

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Base: show
1111
# These are routines that help to create input geometries, such as slabs with a given angle
1212
#
1313

14-
export add_box!, add_sphere!, add_ellipsoid!, add_cylinder!, add_layer!, add_polygon!, add_slab!, add_stripes!, add_volcano!, add_fault!,
14+
export add_box!, add_sphere!, add_ellipsoid!, add_cylinder!, add_layer!, add_polygon!, add_plate!, add_slab!, add_stripes!, add_volcano!, add_fault!,
1515
make_volc_topo,
1616
ConstantTemp, LinearTemp, HalfspaceCoolingTemp, SpreadingRateTemp, LithosphericTemp, LinearWeightedTemperature,
1717
McKenzie_subducting_slab,
@@ -299,7 +299,7 @@ function add_box!(Phase, Temp, Grid::AbstractGeneralGrid; # required input
299299
Phase[ind_flat] = compute_phase(Phase[ind_flat], Temp[ind_flat], Xrot[ind], Yrot[ind], Zrot[ind], phase)
300300
end
301301
if segments !== nothing
302-
Temp[ind_flat] = compute_thermal_structure(Temp[ind_flat], X[ind], Y[ind], Z[ind], Phase[ind_flat], T, segments)
302+
Temp[ind_flat] = compute_thermal_structure(Temp[ind_flat], Xrot[ind], Yrot[ind], Zrot[ind], Phase[ind_flat], T, segments)
303303
else
304304
Temp[ind_flat] = compute_thermal_structure(Temp[ind_flat], Xrot[ind], Yrot[ind], Zrot[ind], Phase[ind_flat], T)
305305
end
@@ -768,6 +768,91 @@ function add_polygon!(
768768
return nothing
769769
end
770770

771+
"""
772+
add_plate!(Phase, Temp, Grid::AbstractGeneralGrid; xlim=(), ylim=(), zlim::Tuple = (0.0,0.8), phase = ConstantPhase(1), T=nothing, segments=nothing, cell=false )
773+
Adds a tectonic plate with phase and temperature structure to a 3D model setup.
774+
This function enables the definition of tectonic plates in the xy plane and projects them along the z-axis, providing a flexible approach to model complex plate geometries.
775+
Parameters
776+
==========
777+
- `Phase` - Phase array (consistent with Grid)
778+
- `Temp` - Temperature array (consistent with Grid)
779+
- `Grid` - Grid structure (usually obtained with read_LaMEM_inputfile)
780+
- `xlim` - `x`-coordinate of the polygon points, same ordering as ylim, number of points unlimited
781+
- `ylim` - `y`-coordinate of the polygon points, same ordering as xlim, number of points unlimited
782+
- `zlim` - `z`-coordinate range for projecting the polygon (start and stop, two values)
783+
- `phase` - Specifies the phase of the plate. See `ConstantPhase()`
784+
- `T` - Specifies the temperature of the plate. See `ConstantTemp()`, `LinearTemp()`, `HalfspaceCoolingTemp()`, `SpreadingRateTemp()`
785+
- `segments` - Optional. Allows for thermal segmentation within the polygon. Useful for ridge systems or complex thermal structures.
786+
- `cell` - If true, `Phase` and `Temp` are defined on cell centers
787+
Example
788+
========
789+
Tectonic plate in the xy plane with phase and temperature structure:
790+
```julia-repl
791+
julia> Grid = CartData(xyz_grid(x, y, z))
792+
Grid:
793+
nel : (512, 512, 128)
794+
marker/cell : (1, 1, 1)
795+
markers : (512, 512, 128)
796+
x ϵ [-1000.0 : 0.0]
797+
y ϵ [-1000.0 : 1000.0]
798+
z ϵ [-660.0 : 0.0]
799+
julia> Phases = zeros(Int32, size(Grid.X))
800+
julia> Temp = zeros(Float64, size(Grid.X))
801+
julia> segments = [
802+
((-500.0, -1000.0), (-500.0, 0.0)), # Segment 1
803+
((-250.0, 0.0), (-250.0, 200.0)), # Segment 2
804+
((-750.0, 200.0), (-750.0, 1000.0)) # Segment 3
805+
]
806+
julia> lith = LithosphericPhases(Layers=[15 55], Phases=[1 2], Tlab=1250)
807+
julia> add_plate!(Phases, Temp, Grid;
808+
xlim=(-1000.0, -750.0, -250.0, 0.0, -250.0, -750.0),
809+
ylim=(0.0, 500.0, 500.0, 0.0, -500.0, -500.0),
810+
zlim=(-150.0, 0.0),
811+
phase=lith,
812+
T=SpreadingRateTemp(SpreadingVel=3),
813+
segments=segments)
814+
julia> Grid = addfield(Grid, (; Phases, Temp)) # Add fields
815+
julia> write_paraview(Grid, "Plate") # Save model to Paraview
816+
1-element Vector{String}:
817+
"Plate.vts"
818+
"""
819+
820+
function add_plate!(Phase, Temp, Grid::AbstractGeneralGrid;
821+
xlim=(), ylim=(), zlim::Tuple = (0.0,0.8),
822+
phase = ConstantPhase(1),
823+
T=nothing, segments=nothing, cell=false )
824+
825+
xlim_ = collect(xlim)
826+
ylim_ = collect(ylim)
827+
zlim_ = collect(zlim)
828+
829+
X, Y, Z = coordinate_grids(Grid, cell=cell)
830+
ind = zeros(Bool, size(X))
831+
ind_slice = zeros(Bool, size(X[:, :, 1]))
832+
833+
for k = 1:size(Z, 3)
834+
if zlim_[1] <= Z[1, 1, k] <= zlim_[2]
835+
inpolygon!(ind_slice, xlim_, ylim_, X[:, :, k], Y[:, :, k])
836+
@views ind[:, :, k] = ind_slice
837+
else
838+
@views ind[:, :, k] = zeros(size(X[:, :, 1]))
839+
end
840+
end
841+
842+
if !isempty(ind)
843+
if T != nothing
844+
if segments !== nothing
845+
Temp[ind] = compute_thermal_structure(Temp[ind], X[ind], Y[ind], Z[ind], Phase[ind], T, segments)
846+
else
847+
Temp[ind] = compute_thermal_structure(Temp[ind], X[ind], Y[ind], Z[ind], Phase[ind], T)
848+
end
849+
end
850+
Phase[ind] = compute_phase(Phase[ind], Temp[ind], X[ind], Y[ind], Z[ind], phase)
851+
end
852+
853+
return nothing
854+
end
855+
771856
"""
772857
xrot, yrot, zrot = Rot3D(X::Number,Y::Number,Z::Number, cosStrikeAngle, sindStrikeAngle, cosDipAngle, sinDipAngle)
773858
@@ -1147,7 +1232,7 @@ Note: the thermal age at the mid oceanic ridge is set to 1 year to avoid divisio
11471232
Adiabat = 0 # Adiabatic gradient in K/km
11481233
MORside = "left" # side of box where the MOR is located
11491234
SpreadingVel = 3 # spreading velocity [cm/yr]
1150-
AgeRidge = 0 # Age of the ridge [Myrs
1235+
AgeRidge = 0 # Age of the ridge [Myrs]
11511236
maxAge = 60 # maximum thermal age of plate [Myrs]
11521237
end
11531238

test/runtests.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ using Test
7878
include("test_ridge_segments.jl")
7979
end
8080

81+
@testset "Plate Tests" begin
82+
include("test_plate.jl")
83+
end
84+
8185
@testset "Waterflow" begin
8286
include("test_WaterFlow.jl")
8387
end

test/test_plate.jl

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using GeophysicalModelGenerator
2+
using Test
3+
4+
@testset "Plate Tests" begin
5+
# Grid parameters
6+
nx, ny, nz = 512, 512, 128
7+
x = range(-1000, 0, length=nx)
8+
y = range(-1000, 1000, length=ny)
9+
z = range(-660, 0, length=nz)
10+
Grid = CartData(xyz_grid(x, y, z))
11+
12+
# Phases and temperature
13+
Phases = fill(2, nx, ny, nz)
14+
Temp = fill(1350.0, nx, ny, nz)
15+
16+
# Ridge Segments
17+
segments = [
18+
((-500.0, -1000.0), (-500.0, 0.0)), # Segment 1
19+
((-250.0, 0.0), (-250.0, 200.0)), # Segment 2
20+
((-750.0, 200.0), (-750.0, 1000.0)) # Segment 3
21+
]
22+
23+
# Lithospheric phases
24+
lith = LithosphericPhases(Layers=[15 55], Phases=[1 2], Tlab=1250)
25+
26+
# Replace add_box with add_polygon_xy to allow for arbitrary-shaped ridges
27+
add_plate!(Phases, Temp, Grid;
28+
xlim=(-1000.0, -750.0, -250.0, 0.0, -250.0, -750.0),
29+
ylim=(0.0, 500.0, 500.0, 0.0, -500.0, -500.0),
30+
zlim=(-150.0, 0.0),
31+
phase=lith,
32+
T=SpreadingRateTemp(SpreadingVel=3),
33+
segments=segments)
34+
35+
# Add and save results
36+
Grid = addfield(Grid, (; Phases, Temp))
37+
write_paraview(Grid, "Plate")
38+
39+
@test minimum(Temp) >= 0.0 # Minimum temperature
40+
@test maximum(Temp) <= 1350.0 # Maximum temperature
41+
@test all((0), Temp) # Ensure no negative temperatures
42+
@test all((1350), Temp) # Ensure no temperatures above max
43+
44+
# Check if phases are correctly assigned in expected regions
45+
@test first(Phases) == 2 # Example: Verify a point's phase
46+
@test last(Phases) == 2 # Example: Verify another point's phase.
47+
end

0 commit comments

Comments
 (0)