Skip to content

Commit 0cd4f37

Browse files
committed
Merge detect_plates and detect_plates_vzcheck
New configuration variables `plates.vzratio` and `distribution` control plate limit detection and plotting of plate size distribution.
1 parent eba1d4b commit 0cd4f37

File tree

3 files changed

+56
-120
lines changed

3 files changed

+56
-120
lines changed

stagpy/config.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,13 @@ def _index_collection(arg):
190190
'Plot deviatoric stress instead of velocity on field plots')),
191191
('continents', switch_opt(True, None,
192192
'Whether to shade continents on plots')),
193-
('vzcheck', switch_opt(False, None,
194-
'activate Colin\'s version with vz checking')),
193+
('vzratio',
194+
Conf(0., True, None, {}, True,
195+
'Ratio of mean vzabs used as threshold for plates limits')),
195196
('timeprofile', switch_opt(False, None,
196197
'nb of plates as function of time')),
198+
('distribution', switch_opt(False, None,
199+
'Plot plate size distribution')),
197200
('zoom',
198201
Conf(None, True, None, {'type': float},
199202
False, 'zoom around surface')),

stagpy/error.py

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -163,23 +163,6 @@ def __init__(self, zoom):
163163
super().__init__(f'Zoom angle should be in [0,360] (received {zoom})')
164164

165165

166-
class StagnantLidError(StagpyError):
167-
"""Raised when unexpected stagnant lid regime is found.
168-
169-
Args:
170-
sdat (:class:`~stagpy.stagyydata.StagyyData`): the StagyyData
171-
instance for which a stagnant lid regime was found.
172-
173-
Attributes:
174-
sdat (:class:`~stagpy.stagyydata.StagyyData`): the StagyyData
175-
instance for which a stagnant lid regime was found.
176-
"""
177-
178-
def __init__(self, sdat):
179-
self.sdat = sdat
180-
super().__init__(f'Stagnant lid regime for {sdat}')
181-
182-
183166
class MissingDataError(StagpyError, KeyError):
184167
"""Raised when requested data is not present in output."""
185168

stagpy/plates.py

Lines changed: 51 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -14,63 +14,20 @@
1414
from .stagyydata import StagyyData
1515

1616

17-
def detect_plates_vzcheck(step, vz_thres_ratio=0):
17+
def _vzcheck(iphis, snap, vz_thres):
1818
"""Detect plates and check with vz and plate size."""
19-
v_z = step.fields['v3'].values[0, :-1, :, 0]
20-
v_x = step.fields['v2'].values[0, :, :, 0]
21-
tcell = step.fields['T'].values[0, :, :, 0]
22-
n_z = step.geom.nztot
23-
nphi = step.geom.nptot
24-
r_c = step.geom.r_centers
25-
r_w = step.geom.r_walls
26-
dphi = 1 / nphi
27-
28-
flux_c = n_z * [0]
29-
for i_z in range(0, n_z):
30-
flux_c[i_z] = np.sum((tcell[:, i_z] - step.timeinfo.loc['Tmean']) *
31-
v_z[:, i_z]) * r_w[i_z] * dphi
32-
33-
# checking stagnant lid, criterion seems weird!
34-
if all(abs(flux_c[i_z]) <= np.max(flux_c) / 50
35-
for i_z in range(n_z - n_z // 20, n_z)):
36-
raise error.StagnantLidError(step.sdat)
37-
38-
# verifying horizontal plate speed and closeness of plates
39-
vphi_surf = v_x[:, -1]
40-
dvphi = np.diff(vphi_surf) / (r_c[-1] * dphi)
41-
dvx_thres = 16 * step.timeinfo.loc['vrms']
42-
43-
limits = [
44-
phi for phi in range(nphi)
45-
if (abs(dvphi[phi]) >= dvx_thres and
46-
all(abs(dvphi[i % nphi]) <= abs(dvphi[phi])
47-
for i in range(phi - nphi // 33, phi + nphi // 33)))
48-
]
49-
5019
# verifying vertical velocity
51-
vz_thres = 0
52-
if vz_thres_ratio > 0:
53-
vz_mean = (np.sum(step.rprofs['vzabs'].values * np.diff(r_w)) /
54-
(r_w[-1] - r_w[0]))
55-
vz_thres = vz_mean * vz_thres_ratio
56-
k = 0
57-
for i in range(len(limits)):
58-
vzm = 0
59-
phi = limits[i - k]
60-
for i_z in range(1 if phi == nphi - 1 else 0, n_z):
61-
vzm += (abs(v_z[phi, i_z]) +
62-
abs(v_z[phi - 1, i_z]) +
63-
abs(v_z[(phi + 1) % nphi, i_z])) / (n_z * 3)
64-
20+
vzabs = np.abs(snap.fields['v3'].values[0, ..., 0])
21+
argdel = []
22+
for i, iphi in enumerate(iphis):
23+
vzm = np.mean(vzabs[[iphi - 1, iphi, iphi + 1], :])
6524
if vzm < vz_thres:
66-
limits.remove(phi)
67-
k += 1
68-
69-
return limits, dvphi, vphi_surf
25+
argdel.append(i)
26+
return np.delete(iphis, argdel)
7027

7128

7229
@lru_cache()
73-
def detect_plates(snap):
30+
def detect_plates(snap, vz_thres_ratio=0):
7431
"""Detect plates using derivative of horizontal velocity."""
7532
dvphi = _surf_diag(snap, 'dv2').values
7633

@@ -100,6 +57,15 @@ def detect_plates(snap):
10057
if argdel:
10158
iridges = np.delete(iridges, argdel)
10259

60+
# additional check on vz
61+
if vz_thres_ratio > 0:
62+
r_w = snap.geom.r_walls
63+
vz_mean = (np.sum(snap.rprofs['vzabs'].values * np.diff(r_w)) /
64+
(r_w[-1] - r_w[0]))
65+
vz_thres = vz_mean * vz_thres_ratio
66+
itrenches = _vzcheck(itrenches, snap, vz_thres)
67+
iridges = _vzcheck(iridges, snap, vz_thres)
68+
10369
return itrenches, iridges
10470

10571

@@ -215,7 +181,7 @@ def plot_at_surface(snap, names):
215181
facecolor='#8B6914')
216182
axis.set_ylim([ymin, ymax])
217183
phi = snap.geom.p_centers
218-
itrenches, iridges = detect_plates(snap)
184+
itrenches, iridges = detect_plates(snap, conf.plates.vzratio)
219185
_plot_plate_limits(axis, phi[itrenches], phi[iridges])
220186
if len(vplt) == 1:
221187
axis.set_ylabel(label)
@@ -228,7 +194,7 @@ def plot_at_surface(snap, names):
228194

229195
def _write_trench_diagnostics(step, vrms_surf, fid):
230196
"""Print out some trench diagnostics."""
231-
itrenches, _ = detect_plates(step)
197+
itrenches, _ = detect_plates(step, conf.plates.vzratio)
232198
time = step.time * vrms_surf *\
233199
conf.scaling.ttransit / conf.scaling.yearins / 1.e6
234200
isurf = _isurf(step)
@@ -299,7 +265,7 @@ def plot_scalar_field(snap, fieldname):
299265

300266
# Put arrow where ridges and trenches are
301267
phi = snap.geom.p_centers
302-
itrenches, iridges = detect_plates(snap)
268+
itrenches, iridges = detect_plates(snap, conf.plates.vzratio)
303269
_plot_plate_limits_field(axis, snap.geom.rcmb,
304270
phi[itrenches], phi[iridges])
305271

@@ -335,60 +301,44 @@ def cmd():
335301
conf.core
336302
"""
337303
sdat = StagyyData()
338-
if not conf.plates.vzcheck:
339-
isurf = _isurf(next(iter(sdat.walk)))
340-
vrms_surf = sdat.walk.filter(rprofs=True)\
341-
.rprofs_averaged['vhrms'].values[isurf]
342-
343-
with open(f'plates_trenches_{sdat.walk.stepstr}.dat', 'w') as fid:
344-
fid.write('# istep time time_My phi_trench vel_trench '
345-
'distance phi_cont age_trench_My\n')
346-
347-
for step in sdat.walk.filter(fields=['T']):
348-
# could check other fields too
349-
_write_trench_diagnostics(step, vrms_surf, fid)
350-
plot_at_surface(step, conf.plates.plot)
351-
plot_scalar_field(step, conf.plates.field)
352-
else:
353-
nb_plates = []
354-
time = []
355-
istart, iend = None, None
304+
305+
isurf = _isurf(next(iter(sdat.walk)))
306+
vrms_surf = sdat.walk.filter(rprofs=True)\
307+
.rprofs_averaged['vhrms'].values[isurf]
308+
nb_plates = []
309+
time = []
310+
istart, iend = None, None
311+
312+
with open(f'plates_trenches_{sdat.walk.stepstr}.dat', 'w') as fid:
313+
fid.write('# istep time time_My phi_trench vel_trench '
314+
'distance phi_cont age_trench_My\n')
356315

357316
for step in sdat.walk.filter(fields=['T']):
358317
# could check other fields too
318+
_write_trench_diagnostics(step, vrms_surf, fid)
319+
plot_at_surface(step, conf.plates.plot)
320+
plot_scalar_field(step, conf.plates.field)
359321
if conf.plates.timeprofile:
360322
time.append(step.timeinfo.loc['t'])
361-
istart = step.isnap if istart is None else istart
362-
iend = step.isnap
363-
phi = step.geom.p_centers
364-
limits, dvphi, vphi_surf = detect_plates_vzcheck(step)
365-
limits.sort()
366-
sizeplates = [phi[limits[0]] + 2 * np.pi - phi[limits[-1]]]
367-
for lim in range(1, len(limits)):
368-
sizeplates.append(phi[limits[lim]] - phi[limits[lim - 1]])
369-
phi_lim = [phi[i] for i in limits]
370-
dvp_lim = [dvphi[i] for i in limits]
371-
fig, axes = plt.subplots(nrows=2, sharex=True, figsize=(6.4, 6.4))
372-
axes[0].plot(step.geom.p_walls, vphi_surf)
373-
axes[0].set_ylabel(r"Horizontal velocity $v_\phi$")
374-
axes[1].plot(phi, dvphi)
375-
axes[1].scatter(phi_lim, dvp_lim, color='red')
376-
axes[1].set_ylabel(r"$dv_\phi/d\phi$")
377-
axes[1].set_xlabel(r"$\phi$")
378-
saveplot(fig, 'plate_limits', step.isnap)
379-
fig, axis = plt.subplots()
380-
axis.hist(sizeplates, 10, (0, np.pi))
381-
axis.set_ylabel("Number of plates")
382-
axis.set_xlabel(r"$\phi$-span")
383-
saveplot(fig, 'plate_size_distribution', step.isnap)
384-
385-
nb_plates.append(len(limits))
323+
itr, ird = detect_plates(step, conf.plates.vzratio)
324+
nb_plates.append(itr.size + ird.size)
325+
istart = step.isnap if istart is None else istart
326+
iend = step.isnap
327+
if conf.plates.distribution:
328+
phi = step.geom.p_centers
329+
itr, ird = detect_plates(step, conf.plates.vzratio)
330+
limits = np.concatenate((itr, ird))
331+
limits.sort()
332+
sizeplates = [phi[limits[0]] + 2 * np.pi - phi[limits[-1]]]
333+
for lim in range(1, len(limits)):
334+
sizeplates.append(phi[limits[lim]] - phi[limits[lim - 1]])
335+
fig, axis = plt.subplots()
336+
axis.hist(sizeplates, 10, (0, np.pi))
337+
axis.set_ylabel("Number of plates")
338+
axis.set_xlabel(r"$\phi$-span")
339+
saveplot(fig, 'plates_size_distribution', step.isnap)
386340

387341
if conf.plates.timeprofile:
388-
for i in range(2, len(nb_plates) - 3):
389-
nb_plates[i] = (nb_plates[i - 2] + nb_plates[i - 1] +
390-
nb_plates[i] + nb_plates[i + 1] +
391-
nb_plates[i + 2]) / 5
392342
figt, axis = plt.subplots()
393343
axis.plot(time, nb_plates)
394344
axis.set_xlabel("Time")

0 commit comments

Comments
 (0)