Skip to content

Commit 2009599

Browse files
authored
Merge pull request #149 from JuliaGeodynamics/pa-volcano
New function: `add_fault!()` in 3D
2 parents e313a1a + 69fcbe5 commit 2009599

File tree

3 files changed

+211
-45
lines changed

3 files changed

+211
-45
lines changed

.github/workflows/draft-pdf.yml

Lines changed: 0 additions & 23 deletions
This file was deleted.

src/Setup_geometry.jl

Lines changed: 120 additions & 2 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!,
14+
export add_box!, add_sphere!, add_ellipsoid!, add_cylinder!, add_layer!, add_polygon!, add_slab!, add_stripes!, add_volcano!, add_fault!,
1515
make_volc_topo,
1616
ConstantTemp, LinearTemp, HalfspaceCoolingTemp, SpreadingRateTemp, LithosphericTemp, LinearWeightedTemperature,
1717
McKenzie_subducting_slab,
@@ -37,6 +37,24 @@ function flatten_index_dimensions(Phase, ind_vec::Vector{CartesianIndex{3}})
3737
return ind2D
3838
end
3939

40+
"""
41+
ind2D = flatten_index_dimensions(Phase, ind_vec::Vector{CartesianIndex{3}})
42+
43+
This converts the indices to purely 2D indices if the array `phase` is 2D
44+
"""
45+
function flatten_index_dimensions(Phase::AbstractArray{T, N}, ind_vec::Array{Bool, 3}) where {T,N}
46+
if N==2
47+
ind2D = Vector{CartesianIndex{2}}(undef,length(ind_vec))
48+
for (num, ind) in enumerate(ind_vec)
49+
ind2D[num] = CartesianIndex(ind[1], ind[3])
50+
end
51+
else
52+
ind2D = ind_vec
53+
end
54+
55+
return ind2D
56+
end
57+
4058
"""
4159
add_stripes!(Phase, Grid::AbstractGeneralGrid;
4260
stripAxes = (1,1,0),
@@ -792,7 +810,7 @@ function add_volcano!(
792810
end
793811
end
794812

795-
ind_flat = flatten_index_dimensions(Temp, ind)
813+
ind_flat = flatten_index_dimensions(Phases, ind)
796814

797815
# @views Temp[ind .== false] .= 0.0
798816
Temp[ind_flat] = compute_thermal_structure(Temp[ind_flat], Grid.x.val[ind], Grid.y.val[ind], depth[ind], Phases[ind_flat], T)
@@ -1929,3 +1947,103 @@ function add_slab!(Phase, Temp, Grid::AbstractGeneralGrid, trench::Trench;
19291947

19301948
return nothing
19311949
end
1950+
1951+
"""
1952+
add_fault!(Phase, Temp, Grid::AbstractGeneralGrid;
1953+
Start=(20,100), End=(10,80),
1954+
Fault_thickness=10.0,
1955+
Depth_extent=nothing,
1956+
DipAngle=0e0,
1957+
phase=ConstantPhase(1),
1958+
T=nothing,
1959+
cell=false)
1960+
1961+
Adds a fault to the given 3D grid by modifying the `Phase` and `Temp` arrays.
1962+
For a 2D grid, use `add_box` instead.
1963+
1964+
# Arguments
1965+
- `Phase`: Phase array
1966+
- `Temp`: Temp array
1967+
- `Grid`: The grid on which the fault is to be added.
1968+
- `Start`: Tuple representing the starting coordinates of the fault (X, Y).
1969+
- `End`: Tuple representing the ending coordinates of the fault (X, Y).
1970+
- `Fault_thickness`: Thickness of the fault.
1971+
- `Depth_extent`: Depth extent of the fault. If `nothing`, the fault extends through the entire domain.
1972+
- `DipAngle`: Dip angle of the fault.
1973+
- `phase`: Phase to be assigned to the fault.
1974+
- `T`: Temperature to be assigned to the fault. If `nothing`, the temperature is not modified.
1975+
1976+
1977+
# Example
1978+
```julia
1979+
add_fault!(Phase, Temp, Grid;
1980+
Start=(20,100), End=(10,80),
1981+
Fault_thickness=10.0,
1982+
Depth_extent=(-25.0, 0.0),
1983+
DipAngle=-10.0,
1984+
phase=ConstantPhase(1)
1985+
)
1986+
```
1987+
"""
1988+
function add_fault!(
1989+
Phase,
1990+
Temp,
1991+
Grid::AbstractGeneralGrid;
1992+
Start=(20,100),
1993+
End=(10,80),
1994+
Fault_thickness=10.0,
1995+
Depth_extent=nothing,
1996+
DipAngle=0e0,
1997+
phase=ConstantPhase(1),
1998+
T=nothing,
1999+
cell=false
2000+
)
2001+
2002+
# Extract the coordinates
2003+
X, Y, Z = coordinate_grids(Grid, cell=cell)
2004+
2005+
# Calculate the direction vector from Start to End
2006+
direction = (End[1] - Start[1], End[2] - Start[2])
2007+
length = sqrt(direction[1]^2 + direction[2]^2)
2008+
unit_direction = (direction[1], direction[2]) ./ length
2009+
2010+
# Calculate the fault region based on fault thickness and length
2011+
fault_half_thickness = Fault_thickness / 2
2012+
2013+
# Create a mask for the fault region
2014+
fault_mask = falses(size(X))
2015+
2016+
for k in 1:size(Z, 3), j in 1:size(Y, 2), i in 1:size(X, 1)
2017+
# Rotate the point using the dip angle
2018+
x_rot, y_rot, z_rot = Rot3D(X[i, j, k], Y[i, j, k], Z[i, j, k], 1.0, 0.0, cosd(DipAngle), sind(DipAngle))
2019+
2020+
# Calculate the projection of the rotated point onto the fault line
2021+
projection_length = (x_rot - Start[1]) * unit_direction[1] + (y_rot - Start[2]) * unit_direction[2]
2022+
if 0 projection_length length
2023+
# Calculate the perpendicular distance to the fault line
2024+
perpendicular_distance = abs((x_rot - Start[1]) * unit_direction[2] - (y_rot - Start[2]) * unit_direction[1])
2025+
if perpendicular_distance fault_half_thickness
2026+
fault_mask[i, j, k] = true
2027+
end
2028+
end
2029+
end
2030+
2031+
ind = findall(fault_mask)
2032+
2033+
# Apply depth extent if provided
2034+
if !isnothing(Depth_extent)
2035+
ind = ind[Z[ind] .≥ Depth_extent[1] .&& Z[ind] .≤ Depth_extent[2]]
2036+
end
2037+
2038+
ind_flat = flatten_index_dimensions(Phase, ind)
2039+
2040+
# Compute thermal structure accordingly
2041+
if T != nothing
2042+
Temp[ind_flat] = compute_thermal_structure(Temp[ind_flat], X[ind], Y[ind], Z[ind], Phase[ind_flat], T)
2043+
end
2044+
2045+
# Set the phase
2046+
Phase[ind_flat] = compute_phase(Phase[ind_flat], Temp[ind_flat], X[ind], Y[ind], Z[ind], phase)
2047+
2048+
return nothing
2049+
end

0 commit comments

Comments
 (0)