454454# Internal function that rotates the coordinates
455455function Rot3D! (X,Y,Z, StrikeAngle, DipAngle)
456456
457+ #=
457458 # rotation matrixes
458459 roty = [cosd(-DipAngle) 0 sind(-DipAngle) ; 0 1 0 ; -sind(-DipAngle) 0 cosd(-DipAngle)];
459460 rotz = [cosd(StrikeAngle) -sind(StrikeAngle) 0 ; sind(StrikeAngle) cosd(StrikeAngle) 0 ; 0 0 1]
@@ -466,10 +467,39 @@ function Rot3D!(X,Y,Z, StrikeAngle, DipAngle)
466467 Y[i] = CoordRot[2];
467468 Z[i] = CoordRot[3];
468469 end
470+ =#
471+
472+ # precompute trigonometric functions (expensive!)
473+ sindStrikeAngle, cosStrikeAngle = sincosd (StrikeAngle)
474+ sinDipAngle, cosDipAngle = sincosd (- DipAngle) # note the minus here to be consistent with the earlier version of the code
475+ for i in eachindex (X)
476+ X[i], Y[i], Z[i] = Rot3D (X[i], Y[i], Z[i], cosStrikeAngle, sindStrikeAngle, cosDipAngle, sinDipAngle)
477+ end
469478
470479 return nothing
471480end
472481
482+ """
483+ xrot, yrot, zrot = Rot3D(X::Number,Y::Number,Z::Number, cosStrikeAngle, sindStrikeAngle, cosDipAngle, sinDipAngle)
484+
485+ Perform rotation for a point in 3D space
486+ """
487+ function Rot3D (X:: Number ,Y:: Number ,Z:: Number , cosStrikeAngle, sindStrikeAngle, cosDipAngle, sinDipAngle)
488+
489+ # rotation matrixes
490+ # roty = [cosd(-DipAngle) 0 sind(-DipAngle) ; 0 1 0 ; -sind(-DipAngle) 0 cosd(-DipAngle)];
491+ roty = [cosDipAngle 0 sinDipAngle ; 0 1 0 ; - sinDipAngle 0 cosDipAngle]; # note that dip-angle is changed from before!
492+ rotz = [cosStrikeAngle - sindStrikeAngle 0 ; sindStrikeAngle cosStrikeAngle 0 ; 0 0 1 ]
493+
494+ CoordVec = [X, Y, Z]
495+ CoordRot = rotz* CoordVec;
496+ CoordRot = roty* CoordRot;
497+
498+ return CoordRot[1 ], CoordRot[2 ], CoordRot[3 ]
499+ end
500+
501+
502+
473503"""
474504makeVolcTopo(Grid::LaMEM_grid; center::Array{Float64, 1}, height::Float64, radius::Float64, crater::Float64,
475505 base=0.0m, background=nothing)
@@ -1061,19 +1091,19 @@ Parameters
10611091end
10621092
10631093"""
1064- Compute_ThermalStructure(Temp, X, Y, Z, s::McKenzie_subducting_slab)
1094+ Compute_ThermalStructure(Temp, X, Y, Z, Phase, s::McKenzie_subducting_slab)
10651095
10661096Compute the temperature field of a `McKenzie_subducting_slab`. Uses the analytical solution
10671097of McKenzie (1969) ["Speculations on the consequences and causes of plate motions"]. The functions assumes
10681098that the bottom of the slab is the coordinate Z=0. Internally the function shifts the coordinate.
10691099Parameters
10701100=============================
10711101Temp Temperature array
1072- X X Array
1073- Y Y Array
1074- Z Z Array
1075- Phase Phase array
1076- s McKenzie_subducting_slab
1102+ - `X` X Array
1103+ - `Y` Y Array
1104+ - `Z` Z Array
1105+ - ` Phase` Phase array
1106+ - `s` McKenzie_subducting_slab
10771107
10781108"""
10791109function Compute_ThermalStructure (Temp, X, Y, Z,Phase, s:: McKenzie_subducting_slab )
@@ -1181,21 +1211,18 @@ function Compute_ThermalStructure(Temp, X, Y, Z, Phase, s::LinearWeightedTempera
11811211end
11821212
11831213
1184- abstract type Trench_slab end
1214+ abstract type AbstractTrenchSlab end
11851215
11861216"""
11871217 Trench structure
1188- [Dev Comments]: I wanted to leave some fields for future implementation. For example, if you take an arbitrary path
1189- that can be projected to a linear segment, an user can discretize it, and can create an arbitrary trench geometry.
1190- The type of bending can be further customize, but certain geometry can be tricky with the actual finding slab. In the future,
1191- we can introduce structures that handle that and use multiple dispatch of the function finding slab to handle the most tricky geometries
1218+
1219+ Structure that defines the geometry of the trench and the slab.
11921220
11931221Parameters
11941222===
11951223
1196- - `n_seg_xy` - Number of segment through which the trench strike is discretize (for now, is one by default)
1197- - `A` - The first point of the trench | The coordinate will be transformed and rotated as a function of the
1198- - `B` - The second point of the trench | slope of the segment, and w.r.t. to the point A.
1224+ - `Start` - Start of the trench (`x`,`y`) coordinates
1225+ - `End` - End of the trench (`x`,`y`) coordinates
11991226- `n_seg` - The number of segment through which the slab is discretize along the dip
12001227- `L0` - The length of the slab
12011228- `D0` - The thickness of the slab
@@ -1210,26 +1237,29 @@ Parameters
12101237- `type_bending` - is the type of bending angle of the slab [`:Linear`, `:Ribe`].
12111238 The angle of slab changes as a function of `l` (∈ [0,L0]). `l` is the actual distance along the slab length from
12121239 the trench.
1213- In case of `:Linear` θ(l) = ((θ_max - 0.0)/(Lb-0))*l;
1214- In case of `:Ribe` θ(l) = θ_max*l^2*((3*Lb-2*l))/(Lb^3) (ref*);
1215- (ref*) Ribe 2010 [Bending mechanics and mode selection in free subduction: a thin-sheet analysis]
1240+ In case:
1241+ - `:Linear`
1242+ ```math θ(l) = ((θ_max - 0.0)/(Lb-0))*l ```;
1243+ - `:Ribe`
1244+ ```math θ(l) = θ_max*l^2*((3*Lb-2*l))/(Lb^3) ```;
1245+ which is taken from Ribe 2010 [Bending mechanics and mode selection in free subduction: a thin-sheet analysis]
1246+
12161247 For l>Lb, θ(l) = θ_max;
12171248# [Dev] Potential development: using the elastic bending differential equation and numerically integrate
12181249#- `WZ` - Thickness of the weakzone.
12191250
12201251"""
1221- @with_kw_noshow mutable struct Trench <: Trench_slab
1222- n_seg_xy:: Int64 = 1 # Number of segment of the trench plane view (for now, 1 segment)
1223- A:: Array{Float64} = (0.0 ,0.0 ) # Coordinate 1 {set of coordinates}
1224- B:: Array{Float64} = (0.0 ,1.0 ) # Coordinate 2 {set of coordinates}
1225- n_seg:: Int64 = 50 # definition segment
1226- L0:: Float64 = 400 # length of the slab
1227- D0:: Float64 = 100 # thickness of the slab
1228- Lb:: Float64 = 200 # Length at which all the bending is happening (Lb<=L0)
1229- θ_max:: Float64 = 45 # max bending angle, (must be converted into radians)
1230- direction:: Float64 = 1.0 # Direction of the bending angle.
1231- d_decoupling:: Float64 = 100 # decoupling depth of the slab
1232- type_bending:: Symbol = :Ribe # Mode Ribe | Linear | Customize
1252+ @with_kw_noshow mutable struct Trench{Nseg} <: AbstractTrenchSlab
1253+ Start:: NTuple{Nseg,Float64} = (0.0 ,0.0 ) # Start (x,y) coordinates of trench (in mapview)
1254+ End:: NTuple{Nseg,Float64} = (0.0 ,1.0 ) # End (x,y) coordinates of trench (in mapview)
1255+ n_seg:: Int64 = 50 # number of segments in downdip direction
1256+ L0:: Float64 = 400.0 # length of the slab
1257+ D0:: Float64 = 100.0 # thickness of the slab
1258+ Lb:: Float64 = 200.0 # Length at which all the bending is happening (Lb<=L0)
1259+ θ_max:: Float64 = 45.0 # max bending angle, (must be converted into radians)
1260+ direction:: Float64 = 1.0 # Direction of the bending angle.
1261+ d_decoupling:: Float64 = 100 # decoupling depth of the slab
1262+ type_bending:: Symbol = :Ribe # Mode Ribe | Linear | Customize
12331263end
12341264
12351265"""
@@ -1249,7 +1279,7 @@ Next, it compute the coordinates assuming that the trench is at 0.0, and assumin
12491279"""
12501280function compute_slab_surface (trench:: Trench )
12511281
1252- @unpack D0, L0, n_seg, Lb, θ_max, n_seg_xy, A, B, type_bending, direction = trench;
1282+ @unpack D0, L0, n_seg, Lb, θ_max, type_bending, direction = trench;
12531283
12541284 # Convert θ_max into radians
12551285 θ_max *= π / 180 ;
@@ -1325,36 +1355,37 @@ function compute_bending_angle(θ_max::Float64,Lb::Float64,l::Float64,type::Symb
13251355 return θ
13261356end
13271357
1358+ #=
13281359"""
13291360 transform_coordinate!(X,Y,Z,XT,YT,A,B,direction)
13301361
13311362Transform the coordinate such that the new x axis (XT) is parallel to the segment A-B of the slab. The rotation is
13321363anticlockwise. If θ_max is negative, it multiplies YT with the sign of the angle, changing the dip of the subduction.
13331364It returns Bn -> which is the point B coordinate in the new transformed system.
13341365"""
1335- function transform_coordinate! (X,Y,Z,XT,YT,A,B ,direction)
1366+ function transform_coordinate!(X,Y,Z,XT,YT,Start,End ,direction)
13361367
13371368 # find the slope of AB points
1338- s = (B [2 ]- A [2 ])/ (B [1 ]- A [1 ])
1369+ s = (End [2]-Start [2])/(End [1]-Start [1])
13391370
13401371 angle_rot = -atand(s);
13411372
13421373 # Shift the origin
1343- XT .= X .- A [1 ];
1344- YT .= Y .- A [2 ];
1374+ XT .= X .- Start [1];
1375+ YT .= Y .- Start [2];
13451376
13461377 Bn = zeros(3);
13471378
1348- Bn[1 ] = B [1 ]- A [1 ];
1379+ Bn[1] = End [1]-Start [1];
13491380
1350- Bn[2 ] = B [2 ]- A [2 ];
1381+ Bn[2] = End [2]-Start [2];
13511382
13521383 Bn[3] = 0.0;
13531384
13541385 # Transform the coordinates
13551386 Rot3D!(XT,YT,Z, angle_rot, 0);
13561387
1357- YT .= YT * direction;
1388+ YT .*= direction;
13581389
13591390 #Find Point B in the new coordinate system
13601391 roty = [cosd(-0) 0 sind(-0) ; 0 1 0 ; -sind(-0) 0 cosd(-0)];
@@ -1365,22 +1396,25 @@ function transform_coordinate!(X,Y,Z,XT,YT,A,B,direction)
13651396
13661397 return Bn
13671398end
1399+ =#
13681400
13691401"""
1370- find_slab!(ls, d, X,Y,Z, θ_max, A, B , Top, Bottom, seg_slab, D0, L0)
1402+ find_slab!(ls, d, X,Y,Z, Start, End , Top, Bottom, seg_slab, D0, L0)
13711403
13721404Function that finds the perpendicular distance to the top and bottom of the slab `d`, and the current length of the slab `l`.
13731405
1374-
13751406"""
1376- function find_slab! (ls, d, X,Y,Z, θ_max, A,B ,Top,Bottom,seg_slab,D0,L0,direction)
1407+ function find_slab! (ls, d, X,Y,Z, Start, End ,Top,Bottom,seg_slab,D0,L0,direction)
13771408
1378- # Create the XT,YT
1379- XT = zero (X);
1380- YT = zero (Y);
1409+ # Perform rotation of 3D coordinates along the angle from Start -> End:
1410+ Xrot = X .- Start[1 ];
1411+ Yrot = Y .- Start[2 ];
1412+ StrikeAngle = - atand ((End[2 ]- Start[2 ])/ (End[1 ]- Start[1 ]))
1413+ Rot3D! (Xrot,Yrot,Z, StrikeAngle, 0.0 )
13811414
1382- # Function to transform the coordinate
1383- xb = transform_coordinate! (X,Y,Z,XT,YT,A,B,direction);
1415+ xb = Rot3D (End[1 ]- Start[1 ],End[2 ]- Start[2 ], 0.0 , cosd (StrikeAngle), sind (StrikeAngle), 1.0 , 0.0 )
1416+
1417+ # xb1 = transform_coordinate!(X,Y,Z,Xrot,Yrot,Start,End,direction);
13841418
13851419 # dl
13861420 dl = L0/ seg_slab;
@@ -1409,10 +1443,10 @@ function find_slab!(ls, d, X,Y,Z, θ_max, A,B,Top,Bottom,seg_slab,D0,L0,directio
14091443 zmin = minimum (poly_z);
14101444 zmax = maximum (poly_z);
14111445
1412- ind_s = findall (0.0 .<= XT .<= xb[1 ] .&& ymin .<= YT .<= ymax .&& zmin .<= Z .<= zmax);
1446+ ind_s = findall (0.0 .<= Xrot .<= xb[1 ] .&& ymin .<= Yrot .<= ymax .&& zmin .<= Z .<= zmax);
14131447
14141448 # Find the particles
1415- yp = YT [ind_s];
1449+ yp = Yrot [ind_s];
14161450
14171451 zp = Z[ind_s];
14181452
@@ -1442,7 +1476,7 @@ function find_slab!(ls, d, X,Y,Z, θ_max, A,B,Top,Bottom,seg_slab,D0,L0,directio
14421476
14431477 for ip = 1 : particle_n
14441478
1445- point_ = [YT [ind_seg[ip]],Z[ind_seg[ip]]];
1479+ point_ = [Yrot [ind_seg[ip]],Z[ind_seg[ip]]];
14461480
14471481 d[ind_seg[ip]] = ScatteredInterpolation. evaluate (itp1,point_)[1 ];
14481482 ls[ind_seg[ip]] = ScatteredInterpolation. evaluate (itp2,point_)[1 ];
@@ -1459,10 +1493,10 @@ end
14591493Internal routine which finds distance perpendicular (`d`) and along (`ls`) the slab, as specified in `trench`.
14601494"""
14611495function find_slab_distance! (ls, d, trench, Top, Bottom, X,Y,Z)
1462- @unpack D0, L0, n_seg, Lb, θ_max, n_seg_xy, A, B, type_bending , direction = trench;
1496+ @unpack D0, L0, n_seg, Start, End , direction = trench;
14631497
14641498 # Finds the distance to the slab
1465- GeophysicalModelGenerator. find_slab! (ls, d, X,Y,Z, θ_max,A,B, Top,Bottom,n_seg,D0,L0,direction);
1499+ GeophysicalModelGenerator. find_slab! (ls, d, X,Y,Z, Start,End, Top,Bottom,n_seg,D0,L0,direction);
14661500
14671501 return nothing
14681502end
@@ -1532,7 +1566,7 @@ function addSlab!(Phase, Temp, Grid::AbstractGeneralGrid, trench::Trench;
15321566 Temp[ind] = Compute_ThermalStructure (Temp[ind], ls[ind], Y[ind], d[ind], Phase[ind],T);
15331567 end
15341568
1535- # Set the phase. Different routines are available for that - see below.
1569+ # Set the phase
15361570 Phase[ind] = Compute_Phase (Phase[ind], Temp[ind], ls[ind], Y[ind], d[ind], phase)
15371571
15381572 # Place holder of the weak zone: it is simply using the find slab routine, and cutting it at d_decoupling.
0 commit comments