@@ -129,3 +129,192 @@ function GMG_subduction_2D(nx, ny)
129129
130130 return li, origin, ph, T
131131end
132+
133+ # ------------------------------------------------------------
134+ # Non-uniform grid helpers (logistic refinement)
135+ # ------------------------------------------------------------
136+
137+ function logistic_vertices (
138+ n_cells:: Int ,
139+ L:: Float64 ,
140+ x0:: Float64 ;
141+ x_center:: Float64 ,
142+ w_ref:: Float64 ,
143+ refine_factor:: Float64 ,
144+ k:: Float64 = 4.0 ,
145+ )
146+ # Compute cell widths with a logistic stretching weight, then integrate.
147+ widths_lin = fill (L / n_cells, n_cells)
148+ x_centers_u = [x0 + (i - 0.5 ) * (L / n_cells) for i in 1 : n_cells]
149+
150+ local_width_weight (x) = begin
151+ d = abs (x - x_center) / w_ref
152+ s = 1 / (1 + exp (- k * (d - 1.0 )))
153+ 1 + (refine_factor - 1 ) * s
154+ end
155+
156+ widths = similar (widths_lin)
157+ @inbounds for i in 1 : n_cells
158+ widths[i] = widths_lin[i] * local_width_weight (x_centers_u[i])
159+ end
160+
161+ # Renormalize to preserve the total domain length exactly.
162+ widths .*= L / sum (widths)
163+
164+ vertices = zeros (n_cells + 1 )
165+ vertices[1 ] = x0
166+ @inbounds for i in 1 : n_cells
167+ vertices[i + 1 ] = vertices[i] + widths[i]
168+ end
169+
170+ return vertices, widths
171+ end
172+
173+ function subduction_nonuniform_coords_1d (
174+ n_points:: Int ,
175+ x0:: Float64 ,
176+ x1:: Float64 ;
177+ ref_grid:: Int ,
178+ refine_factor:: Float64 ,
179+ w_ref_ratio:: Float64 ,
180+ x_center_frac:: Float64 ,
181+ k:: Float64 = 4.0 ,
182+ )
183+ if ref_grid == 0 || refine_factor == 1.0
184+ # Preserve the original type returned by `Geometry` (LinRange/StepRangeLen),
185+ # which downstream JustPIC advection currently dispatches on.
186+ return LinRange (x0, x1, n_points)
187+ end
188+
189+ n_cells = n_points - 1
190+ L = x1 - x0
191+ x_center = x0 + x_center_frac * L
192+ w_ref = w_ref_ratio * abs (L)
193+
194+ vertices, _ = logistic_vertices (
195+ n_cells,
196+ abs (L),
197+ x0;
198+ x_center = x_center,
199+ w_ref = w_ref,
200+ refine_factor = refine_factor,
201+ k = k,
202+ )
203+ return vertices
204+ end
205+
206+ """
207+ Like `GMG_subduction_2D`, but also returns the non-uniform 1D coordinate vectors
208+ needed by the DYREL grid setup:
209+ `xvi` (staggered/vertex coordinates) and `xci` (cell-center coordinates) in meters.
210+ """
211+ function GMG_subduction_2D_with_coords (
212+ nx_points:: Int ,
213+ ny_points:: Int ;
214+ ref_grid:: Int = 0 ,
215+ refine_factor:: Float64 = 4.0 ,
216+ w_ref_ratio:: Float64 = 1 / 2 ,
217+ k:: Float64 = 4.0 ,
218+ x_center_frac:: Float64 = 0.5 ,
219+ y_center_frac:: Float64 = 0.5 ,
220+ )
221+ model_depth = 660
222+ Tbot = 1474.0
223+ x0_km, x1_km = 0.0 , 3000.0
224+ air_thickness = 15.0
225+ z0_km, z1_km = - model_depth * 1.0 , air_thickness
226+
227+ # Our coordinate arrays are "points" for CartData: xvi has length nx_points.
228+ x = subduction_nonuniform_coords_1d (
229+ nx_points,
230+ x0_km,
231+ x1_km;
232+ ref_grid = ref_grid,
233+ refine_factor = refine_factor,
234+ w_ref_ratio = w_ref_ratio,
235+ x_center_frac = x_center_frac,
236+ k = k,
237+ )
238+ z = subduction_nonuniform_coords_1d (
239+ ny_points,
240+ z0_km,
241+ z1_km;
242+ ref_grid = ref_grid,
243+ refine_factor = refine_factor,
244+ w_ref_ratio = w_ref_ratio,
245+ x_center_frac = y_center_frac,
246+ k = k,
247+ )
248+
249+ Grid2D = CartData (xyz_grid (x, 0 , z))
250+
251+ # Phases and temperature on the CartData grid points ------------------
252+ Phases = zeros (Int64, nx_points, 1 , ny_points)
253+ Temp = fill (Tbot, nx_points, 1 , ny_points)
254+ Tlab = 1300
255+
256+ # phases
257+ # 0: asthenosphere
258+ # 1: lithosphere
259+ # 2: subduction lithosphere
260+ # 3: oceanic crust
261+ # 4: air
262+ add_box! (
263+ Phases,
264+ Temp,
265+ Grid2D;
266+ xlim = (0 , 3000 ),
267+ zlim = (- model_depth, 0.0 ),
268+ Origin = nothing , StrikeAngle = 0 , DipAngle = 0 ,
269+ phase = LithosphericPhases (Layers = [], Phases = [0 ], Tlab = Tlab),
270+ T = HalfspaceCoolingTemp (Tsurface = 20 , Tmantle = Tbot, Age = 50 , Adiabat = 0 ),
271+ )
272+
273+ # Add left oceanic plate
274+ add_box! (
275+ Phases,
276+ Temp,
277+ Grid2D;
278+ xlim = (100 , 3000 - 100 ),
279+ zlim = (- model_depth, 0.0 ),
280+ Origin = nothing , StrikeAngle = 0 , DipAngle = 0 ,
281+ phase = LithosphericPhases (Layers = [80 ], Phases = [1 , 0 ], Tlab = Tlab),
282+ T = HalfspaceCoolingTemp (Tsurface = 20 , Tmantle = Tbot, Age = 50 , Adiabat = 0 ),
283+ )
284+
285+ # Velocity box (same values as the uniform setup)
286+ add_vel_box! (
287+ cenx = (3000 - 2430 ) * 1.0e3 , # m
288+ cenz = - 40.0 * 1.0e3 , # m
289+ widthx = 250.0 * 1.0e3 , # m
290+ widthz = 140.0 * 1.0e3 , # m
291+ vx = 4.0e-9 , # m/s
292+ # vy = -4.0e-9, # m/s (optional)
293+ )
294+
295+ # Surface overwrite
296+ surf = Grid2D. z. val .> 0.0
297+ Temp[surf] .= 20.0
298+ Phases[surf] .= 3
299+
300+ Grid2D = addfield (Grid2D, (; Phases, Temp))
301+ write_paraview (Grid2D, " Initial_Setup_Subduction_rank" )
302+
303+ # Convert coordinates/geometry to meters for DYREL
304+ li = (abs (last (x) - first (x)), abs (last (z) - first (z))) .* 1.0e3
305+ origin = (x[1 ], z[1 ]) .* 1.0e3
306+
307+ ph = Phases[:, 1 , :] .+ 1
308+ T = Temp[:, 1 , :] .+ 273
309+
310+ # Staggered grid coordinate vectors in meters:
311+ # - xvi are vertices (length nx_points)
312+ # - xci are cell centers (length nx_points-1)
313+ xvi = (x .* 1.0e3 , z .* 1.0e3 )
314+ xci = (
315+ 0.5 .* (x[1 : end - 1 ] .+ x[2 : end ]) .* 1.0e3 ,
316+ 0.5 .* (z[1 : end - 1 ] .+ z[2 : end ]) .* 1.0e3 ,
317+ )
318+
319+ return li, origin, ph, T, xvi, xci
320+ end
0 commit comments