@@ -13,7 +13,8 @@ export AddBox!, AddSphere!, AddEllipsoid!, AddCylinder!, AddLayer!, addPolygon!
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
@@ -1142,4 +1143,149 @@ function Compute_Phase(Phase, Temp, X, Y, Z, s::LithosphericPhases; Ztop=0)
11421143end
11431144
11441145# allow AbstractGeneralGrid instead of Z and Ztop
1145- 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))
1146+ 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))
1147+
1148+
1149+ """
1150+ McKenzie_subducting_slab
1151+
1152+ Thermal structure by McKenzie for a subducted slab that is fully embedded in the mantle.
1153+
1154+ Parameters
1155+ ===
1156+ - Tsurface: Top T [C]
1157+ - Tmantle: Bottom T [C]
1158+ - Adiabat: Adiabatic gradient in K/km
1159+ - v_cm_yr: Subduction velocity [cm/yr]
1160+ - κ: Thermal diffusivity [m2/s]
1161+ - it: Number iterations employed in the harmonic summation
1162+
1163+ """
1164+ @with_kw_noshow mutable struct McKenzie_subducting_slab <: AbstractThermalStructure
1165+ Tsurface:: Float64 = 20.0 # top T
1166+ Tmantle:: Float64 = 1350.0 # bottom T
1167+ Adiabat:: Float64 = 0.4 # Adiabatic gradient in K/km
1168+ v_cm_yr:: Float64 = 2.0 # velocity of subduction [cm/yr]
1169+ κ:: Float64 = 1e-6 # Thermal diffusivity [m2/s]
1170+ it:: Int64 = 36 # number of harmonic summation (look Mckenzie formula)
1171+ end
1172+
1173+ """
1174+ Compute_ThermalStructure(Temp, X, Y, Z, s::McKenzie_subducting_slab)
1175+
1176+ Compute the temperature field of a `McKenzie_subducting_slab`. Uses the analytical solution
1177+ of McKenzie (1969) ["Speculations on the consequences and causes of plate motions"]. The functions assumes
1178+ that the bottom of the slab is the coordinate Z=0. Internally the function shifts the coordinate.
1179+
1180+ Parameters
1181+ ====
1182+ - Temp Temperature array
1183+ - X X Array
1184+ - Y Y Array
1185+ - Z Z Array
1186+ - Phase Phase array
1187+ - s McKenzie_subducting_slab
1188+
1189+ """
1190+ function Compute_ThermalStructure (Temp, X, Y, Z,Phase, s:: McKenzie_subducting_slab )
1191+ @unpack Tsurface, Tmantle, Adiabat, v_cm_yr, κ, it = s
1192+
1193+ # Thickness of the layer:
1194+ D0 = (maximum (Z)- minimum (Z));
1195+ Zshift = Z .- Z[end ] # McKenzie model is defined with Z = 0 at the bottom of the slab
1196+
1197+ # Convert subduction velocity from cm/yr -> m/s;
1198+ convert_velocity = 1 / (100.0 * 365.25 * 60.0 * 60.0 * 24.0 );
1199+ v_s = v_cm_yr* convert_velocity;
1200+
1201+ # calculate the thermal Reynolds number
1202+ Re = (v_s* D0* 1000 )/ 2 / κ; # factor 1000 to transfer D0 from km to m
1203+
1204+ # McKenzie model
1205+ sc = 1 / D0
1206+ σ = ones (size (Temp));
1207+ # Dividi et impera
1208+ for i= 1 : it
1209+ a = (- 1.0 ). ^ (i). / (i.* pi )
1210+ b = (Re .- (Re.^ 2 .+ i^ 2.0 .* pi ^ 2.0 ). ^ (0.5 )) .* X .* sc;
1211+ c = sin .(i .* pi .* (1 .- abs .(Zshift .* sc))) ;
1212+ e = exp .(b);
1213+ σ .+ = 2 * a.* e.* c
1214+ end
1215+
1216+ Temp .= Tsurface .+ (Tmantle- Tsurface). * σ;
1217+ Temp .= Temp + (Adiabat* abs .(Z))
1218+
1219+ return Temp
1220+ end
1221+
1222+ """
1223+ LinearWeightedTemperature
1224+
1225+ Structure that defined a linear average temperature between two temperature fields as a function of distance
1226+
1227+ Parameters
1228+ ===
1229+ - w_min: Minimum weight
1230+ - w_max: Maximum weight
1231+ - crit_dist: Critical distance
1232+ - dir: Direction of the averaging (`:X`, `:Y` or `:Z`)
1233+ - F1: First temperature field
1234+ - F2: Second temperature field
1235+
1236+ """
1237+ @with_kw_noshow mutable struct LinearWeightedTemperature <: AbstractThermalStructure
1238+ w_min:: Float64 = 0.0 ;
1239+ w_max:: Float64 = 1.0 ;
1240+ crit_dist:: Float64 = 100.0 ;
1241+ dir:: Symbol = :X ;
1242+ F1:: AbstractThermalStructure = ConstantTemp ();
1243+ F2:: AbstractThermalStructure = ConstantTemp ();
1244+ end
1245+
1246+ """
1247+ Weight average along distance
1248+ Do a weight average between two field along a specified direction
1249+ Given a distance {could be any array, from X,Y} -> it increase from the origin the weight of
1250+ F1, while F2 decreases.
1251+ This function has been conceived for averaging the solution of Mckenzie and half space cooling model, but in
1252+ can be used to smooth the temperature field from continent ocean:
1253+ -> Select the boundary to apply;
1254+ -> transform the coordinate such that dist represent the perpendicular direction along which you want to apply
1255+ this smoothening and in a such way that 0.0 is the point in which the weight of F1 is equal to 0.0;
1256+ -> Select the points that belongs to this area -> compute the thermal fields {F1} {F2} -> then modify F.
1257+ """
1258+ function Compute_ThermalStructure (Temp, X, Y, Z, Phase, s:: LinearWeightedTemperature )
1259+ @unpack w_min, w_max, crit_dist,dir = s;
1260+ @unpack F1, F2 = s;
1261+
1262+ if dir === :X
1263+ dist = X;
1264+ elseif dir === :Y
1265+ dist = Y;
1266+ else
1267+ dist = Z;
1268+ end
1269+
1270+ # compute the 1D thermal structures
1271+ Temp1 = zeros (size (Temp));
1272+ Temp2 = zeros (size (Temp));
1273+ Temp1 = Compute_ThermalStructure (Temp1, X, Y, Z, Phase, F1);
1274+ Temp2 = Compute_ThermalStructure (Temp2, X, Y, Z, Phase, F2);
1275+
1276+ # Compute the weights
1277+ weight = w_min .+ (w_max- w_min) ./ (crit_dist) .* (dist)
1278+
1279+ ind_1 = findall (weight .> w_max);
1280+ ind_2 = findall (weight .< w_min);
1281+
1282+ # Change the weight
1283+ weight[ind_1] .= w_max;
1284+ weight[ind_2] .= w_min;
1285+
1286+ # Average temperature
1287+ Temp .= Temp1 .* (1.0 .- weight) + Temp2 .* weight;
1288+
1289+ return Temp
1290+ end
1291+
0 commit comments