@@ -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
10341035Compute_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
0 commit comments