Skip to content

Commit 85101fb

Browse files
authored
Merge pull request #89 from APiccolo89/ap-mckenzie-temp
Slab-internal temperature and linear thermal averaging
2 parents 9209aff + 84e0e0c commit 85101fb

File tree

3 files changed

+202
-6
lines changed

3 files changed

+202
-6
lines changed

docs/src/man/geodynamic_setups.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ GeophysicalModelGenerator.LithosphericTemp
2020
GeophysicalModelGenerator.ConstantPhase
2121
GeophysicalModelGenerator.Compute_Phase
2222
GeophysicalModelGenerator.LithosphericPhases
23+
GeophysicalModelGenerator.McKenzie_subducting_slab
24+
GeophysicalModelGenerator.LinearWeightedTemperature
2325
```

src/Setup_geometry.jl

Lines changed: 150 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ export AddBox!, AddSphere!, AddEllipsoid!, AddCylinder!, AddLayer!,
1313
makeVolcTopo,
1414
ConstantTemp, LinearTemp, HalfspaceCoolingTemp, SpreadingRateTemp, LithosphericTemp,
1515
ConstantPhase, LithosphericPhases,
16-
Compute_ThermalStructure, Compute_Phase
16+
Compute_ThermalStructure, Compute_Phase,
17+
McKenzie_subducting_slab, LinearWeightedTemperature
1718

1819

1920
"""
@@ -101,10 +102,10 @@ function AddBox!(Phase, Temp, Grid::AbstractGeneralGrid; # requi
101102

102103

103104
# Set phase number & thermal structure in the full domain
104-
ztop = zlim[2] - Origin[3]
105-
zbot = zlim[1] - Origin[3]
106-
ind = findall( (Xrot .>= (xlim[1] - Origin[1])) .& (Xrot .<= (xlim[2] - Origin[1])) .&
107-
(Yrot .>= (ylim[1] - Origin[2])) .& (Yrot .<= (ylim[2] - Origin[2])) .&
105+
ztop = maximum(zlim) - Origin[3]
106+
zbot = minimum(zlim) - Origin[3]
107+
ind = findall( (Xrot .>= (minimum(xlim) - Origin[1])) .& (Xrot .<= (maximum(xlim) - Origin[1])) .&
108+
(Yrot .>= (minimum(ylim) - Origin[2])) .& (Yrot .<= (maximum(ylim) - Origin[2])) .&
108109
(Zrot .>= zbot) .& (Zrot .<= ztop) )
109110

110111
# Compute thermal structure accordingly. See routines below for different options
@@ -1032,3 +1033,147 @@ end
10321033

10331034
# allow AbstractGeneralGrid instead of Z and Ztop
10341035
Compute_Phase(Phase, Temp, Grid::LaMEM_grid, s::LithosphericPhases) = Compute_Phase(Phase, Temp, Grid.X, Grid.Y, Grid.Z, s::LithosphericPhases, Ztop=maximum(Grid.coord_z))
1036+
1037+
1038+
1039+
"""
1040+
McKenzie_subducting_slab
1041+
1042+
Thermal structure by McKenzie for a subducted slab that is fully embedded in the mantle.
1043+
1044+
Parameters
1045+
===
1046+
- Tsurface: Top T [C]
1047+
- Tmantle: Bottom T [C]
1048+
- Adiabat: Adiabatic gradient in K/km
1049+
- v_cm_yr: Subduction velocity [cm/yr]
1050+
- κ: Thermal diffusivity [m2/s]
1051+
- it: Number iterations employed in the harmonic summation
1052+
1053+
"""
1054+
@with_kw_noshow mutable struct McKenzie_subducting_slab <: AbstractThermalStructure
1055+
Tsurface::Float64 = 20.0 # top T
1056+
Tmantle::Float64 = 1350.0 # bottom T
1057+
Adiabat::Float64 = 0.4 # Adiabatic gradient in K/km
1058+
v_cm_yr::Float64 = 2.0 # velocity of subduction [cm/yr]
1059+
κ::Float64 = 1e-6 # Thermal diffusivity [m2/s]
1060+
it::Int64 = 36 # number of harmonic summation (look Mckenzie formula)
1061+
end
1062+
1063+
"""
1064+
Compute_ThermalStructure(Temp, X, Y, Z, s::McKenzie_subducting_slab)
1065+
1066+
Compute the temperature field of a `McKenzie_subducting_slab`. Uses the analytical solution
1067+
of McKenzie (1969) ["Speculations on the consequences and causes of plate motions"]. The functions assumes
1068+
that the bottom of the slab is the coordinate Z=0. Internally the function shifts the coordinate.
1069+
Parameters
1070+
=============================
1071+
Temp Temperature array
1072+
X X Array
1073+
Y Y Array
1074+
Z Z Array
1075+
Phase Phase array
1076+
s McKenzie_subducting_slab
1077+
1078+
"""
1079+
function Compute_ThermalStructure(Temp, X, Y, Z,Phase, s::McKenzie_subducting_slab)
1080+
@unpack Tsurface, Tmantle, Adiabat, v_cm_yr, κ, it = s
1081+
1082+
# Thickness of the layer:
1083+
D0 = (maximum(Z)-minimum(Z));
1084+
Zshift = Z .- Z[end] # McKenzie model is defined with Z = 0 at the bottom of the slab
1085+
1086+
# Convert subduction velocity from cm/yr -> m/s;
1087+
convert_velocity = 1/(100.0*365.25*60.0*60.0*24.0);
1088+
v_s = v_cm_yr*convert_velocity;
1089+
1090+
# calculate the thermal Reynolds number
1091+
Re = (v_s*D0*1000)/2/κ; # factor 1000 to transfer D0 from km to m
1092+
1093+
# McKenzie model
1094+
sc = 1/D0
1095+
σ = ones(size(Temp));
1096+
# Dividi et impera
1097+
for i=1:it
1098+
a = (-1.0).^(i)./(i.*pi)
1099+
b = (Re .- (Re.^2 .+ i^2.0 .* pi^2.0).^(0.5)) .*X .*sc;
1100+
c = sin.(i .*pi .*(1 .- abs.(Zshift .*sc))) ;
1101+
e = exp.(b);
1102+
σ .+= 2*a.*e.*c
1103+
end
1104+
1105+
Temp .= Tsurface .+ (Tmantle-Tsurface).*σ;
1106+
Temp .= Temp + (Adiabat*abs.(Z))
1107+
1108+
return Temp
1109+
end
1110+
1111+
"""
1112+
LinearWeightedTemperature
1113+
1114+
Structure that defined a linear average temperature between two temperature fields as a function of distance
1115+
1116+
Parameters
1117+
===
1118+
- w_min: Minimum weight
1119+
- w_max: Maximum weight
1120+
- crit_dist: Critical distance
1121+
- dir: Direction of the averaging (`:X`, `:Y` or `:Z`)
1122+
- F1: First temperature field
1123+
- F2: Second temperature field
1124+
1125+
"""
1126+
@with_kw_noshow mutable struct LinearWeightedTemperature <: AbstractThermalStructure
1127+
w_min::Float64 = 0.0;
1128+
w_max::Float64 = 1.0;
1129+
crit_dist::Float64 = 100.0;
1130+
dir::Symbol =:X;
1131+
F1::AbstractThermalStructure = ConstantTemp();
1132+
F2::AbstractThermalStructure = ConstantTemp();
1133+
end
1134+
1135+
"""
1136+
Weight average along distance
1137+
Do a weight average between two field along a specified direction
1138+
Given a distance {could be any array, from X,Y} -> it increase from the origin the weight of
1139+
F1, while F2 decreases.
1140+
This function has been conceived for averaging the solution of Mckenzie and half space cooling model, but in
1141+
can be used to smooth the temperature field from continent ocean:
1142+
-> Select the boundary to apply;
1143+
-> transform the coordinate such that dist represent the perpendicular direction along which you want to apply
1144+
this smoothening and in a such way that 0.0 is the point in which the weight of F1 is equal to 0.0;
1145+
-> Select the points that belongs to this area -> compute the thermal fields {F1} {F2} -> then modify F.
1146+
"""
1147+
function Compute_ThermalStructure(Temp, X, Y, Z, Phase, s::LinearWeightedTemperature)
1148+
@unpack w_min, w_max, crit_dist,dir = s;
1149+
@unpack F1, F2 = s;
1150+
1151+
if dir === :X
1152+
dist = X;
1153+
elseif dir ===:Y
1154+
dist = Y;
1155+
else
1156+
dist = Z;
1157+
end
1158+
1159+
# compute the 1D thermal structures
1160+
Temp1 = zeros(size(Temp));
1161+
Temp2 = zeros(size(Temp));
1162+
Temp1 = Compute_ThermalStructure(Temp1, X, Y, Z, Phase, F1);
1163+
Temp2 = Compute_ThermalStructure(Temp2, X, Y, Z, Phase, F2);
1164+
1165+
# Compute the weights
1166+
weight = w_min .+(w_max-w_min) ./(crit_dist) .*(dist)
1167+
1168+
ind_1 = findall(weight .>w_max);
1169+
ind_2 = findall(weight .<w_min);
1170+
1171+
# Change the weight
1172+
weight[ind_1] .= w_max;
1173+
weight[ind_2] .= w_min;
1174+
1175+
# Average temperature
1176+
Temp .= Temp1 .*(1.0 .- weight) + Temp2 .* weight;
1177+
1178+
return Temp
1179+
end

test/test_setup_geometry.jl

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,53 @@ AddBox!(Phases,Temp,Grid, xlim=(-100,100), zlim=(-100,0),
161161
phase=LithosphericPhases(Layers=[20 15 65], Phases = [1 2 3], Tlab=nothing),
162162
DipAngle=30.0, T=LithosphericTemp(lbound="flux",nz=201))
163163

164-
@test sum(Temp[Int64(nel/2),Int64(nel/2),:]) 37359.648604722104
164+
@test sum(Temp[Int64(nel/2),Int64(nel/2),:]) 37359.648604722104
165+
166+
167+
# Test the McKenzie thermal structure
168+
169+
# Create CartGrid struct
170+
x = LinRange(0.0,1200.0,64);
171+
y = LinRange(0.0,1200.0,64);
172+
z = LinRange(-660,50,64);
173+
Cart = CartData(XYZGrid(x, y, z));
174+
175+
# initialize phase and temperature matrix
176+
Phase = ones(Int32,size(Cart));
177+
Temp = ones(Float64,size(Cart))*1350;
178+
179+
# Create thermal structures
180+
TsHC = HalfspaceCoolingTemp(Tsurface=20.0, Tmantle=1350, Age=120, Adiabat=0.4)
181+
TsMK = McKenzie_subducting_slab(Tsurface = 20.0, Tmantle = 1350.0, v_cm_yr = 4.0, Adiabat = 0.0)
182+
183+
@test TsMK.v_cm_yr == 4.0
184+
@test TsMK.it == 36
185+
186+
# Add a box with a McKenzie thermal structure
187+
188+
# horizontal
189+
Temp = ones(Float64,size(Cart))*1350;
190+
AddBox!(Phase, Temp, Cart; xlim=(0.0,600.0),ylim=(0.0,600.0), zlim=(-80.0, 0.0), phase = ConstantPhase(5), T=TsMK);
191+
@test sum(Temp) 3.518172093383281e8
192+
193+
# inclined slab
194+
Temp = ones(Float64,size(Cart))*1350;
195+
AddBox!(Phase, Temp, Cart; xlim=(0.0,600.0),ylim=(0.0,600.0), zlim=(-80.0,0),StrikeAngle=0, DipAngle=45, phase = ConstantPhase(5), T=TsMK);
196+
@test sum(Temp) 3.5125017626287365e8
197+
198+
199+
200+
# horizontal slab, constant T
201+
T_slab = LinearWeightedTemperature(0,1,600.0,:X,ConstantTemp(1000), ConstantTemp(2000));
202+
Temp = ones(Float64,size(Cart))*1350;
203+
AddBox!(Phase, Temp, Cart; xlim=(0.0,600.0),ylim=(0.0,600.0), zlim=(-80.0, 0.0), phase = ConstantPhase(5), T=T_slab);
204+
@test sum(Temp) 3.549127111111111e8
205+
206+
# horizontal slab, halfspace and McKenzie
207+
T_slab = LinearWeightedTemperature(crit_dist=600, F1=TsHC, F2=TsMK);
208+
Temp = ones(Float64,size(Cart))*1350;
209+
AddBox!(Phase, Temp, Cart; xlim=(0.0,600.0),ylim=(0.0,600.0), zlim=(-80.0, 0.0), phase = ConstantPhase(5), T=T_slab);
210+
@test sum(Temp) 3.499457641038468e8
211+
212+
213+
Data_Final = AddField(Cart,"Temp",Temp)

0 commit comments

Comments
 (0)