weac 2.6.1__py3-none-any.whl → 2.6.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- weac/__init__.py +4 -8
- weac/eigensystem.py +180 -139
- weac/inverse.py +5 -8
- weac/layered.py +24 -9
- weac/mixins.py +7 -9
- weac/plot.py +244 -196
- weac/tools.py +6 -5
- {weac-2.6.1.dist-info → weac-2.6.2.dist-info}/METADATA +13 -2
- weac-2.6.2.dist-info/RECORD +12 -0
- {weac-2.6.1.dist-info → weac-2.6.2.dist-info}/WHEEL +1 -1
- weac-2.6.1.dist-info/RECORD +0 -12
- {weac-2.6.1.dist-info → weac-2.6.2.dist-info/licenses}/LICENSE +0 -0
- {weac-2.6.1.dist-info → weac-2.6.2.dist-info}/top_level.txt +0 -0
weac/plot.py
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
# pylint: disable=too-many-arguments,too-many-statements
|
|
4
4
|
|
|
5
5
|
# Standard library imports
|
|
6
|
-
import os
|
|
7
6
|
import colorsys
|
|
7
|
+
import os
|
|
8
8
|
|
|
9
9
|
# Third party imports
|
|
10
10
|
import matplotlib.colors as mc
|
|
@@ -19,28 +19,32 @@ from weac.tools import isnotebook
|
|
|
19
19
|
|
|
20
20
|
def set_plotstyles():
|
|
21
21
|
"""Define styles plot markers, labels and colors."""
|
|
22
|
-
labelstyle = {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
labelstyle = { # Text style of plot labels
|
|
23
|
+
"backgroundcolor": "w",
|
|
24
|
+
"horizontalalignment": "center",
|
|
25
|
+
"verticalalignment": "center",
|
|
26
|
+
}
|
|
26
27
|
# markerstyle = { # Style of plot markers
|
|
27
28
|
# 'marker': 'o',
|
|
28
29
|
# 'markersize': 5,
|
|
29
30
|
# 'markerfacecolor': 'w',
|
|
30
31
|
# 'zorder': 3}
|
|
31
|
-
colors = np.array(
|
|
32
|
-
[
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
32
|
+
colors = np.array(
|
|
33
|
+
[ # TUD color palette
|
|
34
|
+
["#DCDCDC", "#B5B5B5", "#898989", "#535353"], # gray
|
|
35
|
+
["#5D85C3", "#005AA9", "#004E8A", "#243572"], # blue
|
|
36
|
+
["#009CDA", "#0083CC", "#00689D", "#004E73"], # ocean
|
|
37
|
+
["#50B695", "#009D81", "#008877", "#00715E"], # teal
|
|
38
|
+
["#AFCC50", "#99C000", "#7FAB16", "#6A8B22"], # green
|
|
39
|
+
["#DDDF48", "#C9D400", "#B1BD00", "#99A604"], # lime
|
|
40
|
+
["#FFE05C", "#FDCA00", "#D7AC00", "#AE8E00"], # yellow
|
|
41
|
+
["#F8BA3C", "#F5A300", "#D28700", "#BE6F00"], # sand
|
|
42
|
+
["#EE7A34", "#EC6500", "#CC4C03", "#A94913"], # orange
|
|
43
|
+
["#E9503E", "#E6001A", "#B90F22", "#961C26"], # red
|
|
44
|
+
["#C9308E", "#A60084", "#951169", "#732054"], # magenta
|
|
45
|
+
["#804597", "#721085", "#611C73", "#4C226A"], # purple
|
|
46
|
+
]
|
|
47
|
+
)
|
|
44
48
|
return labelstyle, colors
|
|
45
49
|
|
|
46
50
|
|
|
@@ -57,13 +61,19 @@ class MidpointNormalize(mc.Normalize):
|
|
|
57
61
|
|
|
58
62
|
def __call__(self, value, clip=None):
|
|
59
63
|
"""Make instances callable as functions."""
|
|
60
|
-
normalized_min = max(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
normalized_min = max(
|
|
65
|
+
0,
|
|
66
|
+
0.5 * (1 - abs((self.midpoint - self.vmin) / (self.midpoint - self.vmax))),
|
|
67
|
+
)
|
|
68
|
+
normalized_max = min(
|
|
69
|
+
1,
|
|
70
|
+
0.5 * (1 + abs((self.vmax - self.midpoint) / (self.midpoint - self.vmin))),
|
|
71
|
+
)
|
|
64
72
|
normalized_mid = 0.5
|
|
65
|
-
x, y =
|
|
66
|
-
|
|
73
|
+
x, y = (
|
|
74
|
+
[self.vmin, self.midpoint, self.vmax],
|
|
75
|
+
[normalized_min, normalized_mid, normalized_max],
|
|
76
|
+
)
|
|
67
77
|
return np.ma.masked_array(np.interp(value, x, y))
|
|
68
78
|
|
|
69
79
|
|
|
@@ -113,8 +123,8 @@ def tight_central_distribution(limit, samples=100, tightness=1.5):
|
|
|
113
123
|
ndarray
|
|
114
124
|
Array of values more tightly spaced around 0.
|
|
115
125
|
"""
|
|
116
|
-
stop = limit**(1/tightness)
|
|
117
|
-
levels = np.linspace(0, stop, num=int(samples/2), endpoint=True)**tightness
|
|
126
|
+
stop = limit ** (1 / tightness)
|
|
127
|
+
levels = np.linspace(0, stop, num=int(samples / 2), endpoint=True) ** tightness
|
|
118
128
|
return np.unique(np.hstack([-levels[::-1], levels]))
|
|
119
129
|
|
|
120
130
|
|
|
@@ -141,6 +151,7 @@ def adjust_lightness(color, amount=0.5):
|
|
|
141
151
|
c = colorsys.rgb_to_hls(*mc.to_rgb(c))
|
|
142
152
|
return colorsys.hls_to_rgb(c[0], max(0, min(1, amount * c[1])), c[2])
|
|
143
153
|
|
|
154
|
+
|
|
144
155
|
# === PLOT SLAB PROFILE =======================================================
|
|
145
156
|
|
|
146
157
|
|
|
@@ -148,11 +159,11 @@ def slab_profile(instance):
|
|
|
148
159
|
"""Create bar chart of slab profile."""
|
|
149
160
|
# Plot Setup
|
|
150
161
|
plt.rcdefaults()
|
|
151
|
-
plt.rc(
|
|
152
|
-
plt.rc(
|
|
162
|
+
plt.rc("font", family="serif", size=10)
|
|
163
|
+
plt.rc("mathtext", fontset="cm")
|
|
153
164
|
|
|
154
165
|
# Create figure
|
|
155
|
-
fig = plt.figure(figsize=(8/3, 4))
|
|
166
|
+
fig = plt.figure(figsize=(8 / 3, 4))
|
|
156
167
|
ax1 = fig.gca()
|
|
157
168
|
|
|
158
169
|
# Initialize coordinates
|
|
@@ -169,15 +180,15 @@ def slab_profile(instance):
|
|
|
169
180
|
y.append(total_heigth)
|
|
170
181
|
|
|
171
182
|
# Set axis labels
|
|
172
|
-
ax1.set_xlabel(r
|
|
173
|
-
ax1.set_ylabel(r
|
|
183
|
+
ax1.set_xlabel(r"$\longleftarrow$ Density $\rho$ (kg/m$^3$)")
|
|
184
|
+
ax1.set_ylabel(r"Height above weak layer (mm) $\longrightarrow$")
|
|
174
185
|
|
|
175
186
|
ax1.set_xlim(500, 0)
|
|
176
187
|
|
|
177
188
|
ax1.fill_betweenx(y, 0, x)
|
|
178
189
|
|
|
179
190
|
# Save figure
|
|
180
|
-
save_plot(name=
|
|
191
|
+
save_plot(name="profile")
|
|
181
192
|
|
|
182
193
|
# Reset plot styles
|
|
183
194
|
plt.rcdefaults()
|
|
@@ -185,13 +196,27 @@ def slab_profile(instance):
|
|
|
185
196
|
# Clear Canvas
|
|
186
197
|
plt.close()
|
|
187
198
|
|
|
199
|
+
|
|
188
200
|
# === DEFORMATION CONTOUR PLOT ================================================
|
|
189
201
|
|
|
190
202
|
|
|
191
|
-
def deformed(
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
203
|
+
def deformed(
|
|
204
|
+
instance,
|
|
205
|
+
xsl,
|
|
206
|
+
xwl,
|
|
207
|
+
z,
|
|
208
|
+
phi,
|
|
209
|
+
dz=2,
|
|
210
|
+
scale=100,
|
|
211
|
+
window=np.inf,
|
|
212
|
+
pad=2,
|
|
213
|
+
levels=300,
|
|
214
|
+
aspect=2,
|
|
215
|
+
field="principal",
|
|
216
|
+
normalize=True,
|
|
217
|
+
dark=False,
|
|
218
|
+
filename="cont",
|
|
219
|
+
):
|
|
195
220
|
"""
|
|
196
221
|
Plot 2D deformed solution with displacement or stress fields.
|
|
197
222
|
|
|
@@ -239,44 +264,44 @@ def deformed(instance, xsl, xwl, z, phi, dz=2, scale=100,
|
|
|
239
264
|
"""
|
|
240
265
|
# Plot Setup
|
|
241
266
|
plt.rcdefaults()
|
|
242
|
-
plt.rc(
|
|
243
|
-
plt.rc(
|
|
267
|
+
plt.rc("font", family="serif", size=10)
|
|
268
|
+
plt.rc("mathtext", fontset="cm")
|
|
244
269
|
|
|
245
270
|
# Set dark figure background if requested
|
|
246
271
|
if dark:
|
|
247
|
-
plt.style.use(
|
|
272
|
+
plt.style.use("dark_background")
|
|
248
273
|
fig = plt.figure()
|
|
249
274
|
ax = plt.gca()
|
|
250
|
-
fig.set_facecolor(
|
|
251
|
-
ax.set_facecolor(
|
|
275
|
+
fig.set_facecolor("#282c34")
|
|
276
|
+
ax.set_facecolor("white")
|
|
252
277
|
|
|
253
278
|
# Calculate top-to-bottom vertical positions (mm) in beam coordinate system
|
|
254
279
|
zi = instance.get_zmesh(dz=dz)[:, 0]
|
|
255
280
|
h = instance.h
|
|
256
281
|
|
|
257
282
|
# Compute slab displacements on grid (cm)
|
|
258
|
-
Usl = np.vstack([instance.u(z, z0=z0, unit=
|
|
259
|
-
Wsl = np.vstack([instance.w(z, unit=
|
|
283
|
+
Usl = np.vstack([instance.u(z, z0=z0, unit="cm") for z0 in zi])
|
|
284
|
+
Wsl = np.vstack([instance.w(z, unit="cm") for _ in zi])
|
|
260
285
|
|
|
261
286
|
# Put coordinate origin at horizontal center
|
|
262
|
-
if instance.system in [
|
|
263
|
-
xsl = xsl - max(xsl)/2
|
|
264
|
-
xwl = xwl - max(xwl)/2
|
|
287
|
+
if instance.system in ["skier", "skiers"]:
|
|
288
|
+
xsl = xsl - max(xsl) / 2
|
|
289
|
+
xwl = xwl - max(xwl) / 2
|
|
265
290
|
|
|
266
291
|
# Compute slab grid coordinates with vertical origin at top surface (cm)
|
|
267
|
-
Xsl, Zsl = np.meshgrid(1e-1*(xsl), 1e-1*(zi + h/2))
|
|
292
|
+
Xsl, Zsl = np.meshgrid(1e-1 * (xsl), 1e-1 * (zi + h / 2))
|
|
268
293
|
|
|
269
294
|
# Get x-coordinate of maximum deflection w (cm) and derive plot limits
|
|
270
|
-
xfocus = xsl[np.max(np.argmax(Wsl, axis=1))]/10
|
|
271
|
-
xmax = np.min([np.max([Xsl, Xsl+scale*Usl]) + pad, xfocus + window/2])
|
|
272
|
-
xmin = np.max([np.min([Xsl, Xsl+scale*Usl]) - pad, xfocus - window/2])
|
|
295
|
+
xfocus = xsl[np.max(np.argmax(Wsl, axis=1))] / 10
|
|
296
|
+
xmax = np.min([np.max([Xsl, Xsl + scale * Usl]) + pad, xfocus + window / 2])
|
|
297
|
+
xmin = np.max([np.min([Xsl, Xsl + scale * Usl]) - pad, xfocus - window / 2])
|
|
273
298
|
|
|
274
299
|
# Scale shown weak-layer thickness with to max deflection and add padding
|
|
275
|
-
zmax = np.max(Zsl + scale*Wsl) + pad
|
|
300
|
+
zmax = np.max(Zsl + scale * Wsl) + pad
|
|
276
301
|
zmin = np.min(Zsl) - pad
|
|
277
302
|
|
|
278
303
|
# Compute weak-layer grid coordinates (cm)
|
|
279
|
-
Xwl, Zwl = np.meshgrid(1e-1*xwl, [1e-1*(zi[-1] + h/2), zmax])
|
|
304
|
+
Xwl, Zwl = np.meshgrid(1e-1 * xwl, [1e-1 * (zi[-1] + h / 2), zmax])
|
|
280
305
|
|
|
281
306
|
# Assemble weak-layer displacement field (top and bottom)
|
|
282
307
|
Uwl = np.row_stack([Usl[-1, :], np.zeros(xwl.shape[0])])
|
|
@@ -285,51 +310,56 @@ def deformed(instance, xsl, xwl, z, phi, dz=2, scale=100,
|
|
|
285
310
|
# Compute stress or displacement fields
|
|
286
311
|
match field:
|
|
287
312
|
# Horizontal displacements (um)
|
|
288
|
-
case
|
|
289
|
-
slab = 1e4*Usl
|
|
290
|
-
weak = 1e4*Usl[-1, :]
|
|
291
|
-
label = r
|
|
313
|
+
case "u":
|
|
314
|
+
slab = 1e4 * Usl
|
|
315
|
+
weak = 1e4 * Usl[-1, :]
|
|
316
|
+
label = r"$u$ ($\mu$m)"
|
|
292
317
|
# Vertical deflection (um)
|
|
293
|
-
case
|
|
294
|
-
slab = 1e4*Wsl
|
|
295
|
-
weak = 1e4*Wsl[-1, :]
|
|
296
|
-
label = r
|
|
318
|
+
case "w":
|
|
319
|
+
slab = 1e4 * Wsl
|
|
320
|
+
weak = 1e4 * Wsl[-1, :]
|
|
321
|
+
label = r"$w$ ($\mu$m)"
|
|
297
322
|
# Axial normal stresses (kPa)
|
|
298
|
-
case
|
|
299
|
-
slab = instance.Sxx(z, phi, dz=dz, unit=
|
|
323
|
+
case "Sxx":
|
|
324
|
+
slab = instance.Sxx(z, phi, dz=dz, unit="kPa")
|
|
300
325
|
weak = np.zeros(xwl.shape[0])
|
|
301
|
-
label = r
|
|
326
|
+
label = r"$\sigma_{xx}$ (kPa)"
|
|
302
327
|
# Shear stresses (kPa)
|
|
303
|
-
case
|
|
304
|
-
slab = instance.Txz(z, phi, dz=dz, unit=
|
|
305
|
-
weak = instance.get_weaklayer_shearstress(
|
|
306
|
-
|
|
307
|
-
label = r'$\tau_{xz}$ (kPa)'
|
|
328
|
+
case "Txz":
|
|
329
|
+
slab = instance.Txz(z, phi, dz=dz, unit="kPa")
|
|
330
|
+
weak = instance.get_weaklayer_shearstress(x=xwl, z=z, unit="kPa")[1]
|
|
331
|
+
label = r"$\tau_{xz}$ (kPa)"
|
|
308
332
|
# Transverse normal stresses (kPa)
|
|
309
|
-
case
|
|
310
|
-
slab = instance.Szz(z, phi, dz=dz, unit=
|
|
311
|
-
weak = instance.get_weaklayer_normalstress(
|
|
312
|
-
|
|
313
|
-
label = r'$\sigma_{zz}$ (kPa)'
|
|
333
|
+
case "Szz":
|
|
334
|
+
slab = instance.Szz(z, phi, dz=dz, unit="kPa")
|
|
335
|
+
weak = instance.get_weaklayer_normalstress(x=xwl, z=z, unit="kPa")[1]
|
|
336
|
+
label = r"$\sigma_{zz}$ (kPa)"
|
|
314
337
|
# Principal stresses
|
|
315
|
-
case
|
|
338
|
+
case "principal":
|
|
316
339
|
slab = instance.principal_stress_slab(
|
|
317
|
-
z, phi, dz=dz, val=
|
|
340
|
+
z, phi, dz=dz, val="max", unit="kPa", normalize=normalize
|
|
341
|
+
)
|
|
318
342
|
weak = instance.principal_stress_weaklayer(
|
|
319
|
-
z, val=
|
|
343
|
+
z, val="min", unit="kPa", normalize=normalize
|
|
344
|
+
)
|
|
320
345
|
if normalize:
|
|
321
|
-
label=
|
|
322
|
-
|
|
346
|
+
label = (
|
|
347
|
+
r"$\sigma_\mathrm{I}/\sigma_+$ (slab), "
|
|
348
|
+
r"$\sigma_\mathrm{I\!I\!I}/\sigma_-$ (weak layer)"
|
|
349
|
+
)
|
|
323
350
|
else:
|
|
324
|
-
label=
|
|
325
|
-
|
|
351
|
+
label = (
|
|
352
|
+
r"$\sigma_\mathrm{I}$ (kPa, slab), "
|
|
353
|
+
r"$\sigma_\mathrm{I\!I\!I}$ (kPa, weak layer)"
|
|
354
|
+
)
|
|
326
355
|
case _:
|
|
327
356
|
raise ValueError(
|
|
328
357
|
f"Invalid input '{field}' for field. Valid options are "
|
|
329
|
-
"'u', 'w', 'Sxx', 'Txz', 'Szz', or 'principal'"
|
|
358
|
+
"'u', 'w', 'Sxx', 'Txz', 'Szz', or 'principal'"
|
|
359
|
+
)
|
|
330
360
|
|
|
331
361
|
# Complement label
|
|
332
|
-
label += r
|
|
362
|
+
label += r" $\longrightarrow$"
|
|
333
363
|
|
|
334
364
|
# Assemble weak-layer output on grid
|
|
335
365
|
weak = np.row_stack([weak, weak])
|
|
@@ -337,26 +367,27 @@ def deformed(instance, xsl, xwl, z, phi, dz=2, scale=100,
|
|
|
337
367
|
# Normalize colormap
|
|
338
368
|
absmax = np.nanmax(np.abs([slab.min(), slab.max(), weak.min(), weak.max()]))
|
|
339
369
|
clim = np.round(absmax, significant_digits(absmax))
|
|
340
|
-
levels = np.linspace(-clim, clim, num=levels+1, endpoint=True)
|
|
370
|
+
levels = np.linspace(-clim, clim, num=levels + 1, endpoint=True)
|
|
341
371
|
# nanmax = np.nanmax([slab.max(), weak.max()])
|
|
342
372
|
# nanmin = np.nanmin([slab.min(), weak.min()])
|
|
343
373
|
# norm = MidpointNormalize(vmin=nanmin, vmax=nanmax)
|
|
344
374
|
|
|
345
375
|
# Plot baseline
|
|
346
|
-
plt.axhline(zmax, color=
|
|
376
|
+
plt.axhline(zmax, color="k", linewidth=1)
|
|
347
377
|
|
|
348
378
|
# Plot outlines of the undeformed and deformed slab
|
|
349
|
-
plt.plot(outline(Xsl), outline(Zsl),
|
|
350
|
-
plt.plot(outline(Xsl + scale*Usl),
|
|
351
|
-
outline(Zsl + scale*Wsl),
|
|
352
|
-
'k', linewidth=1)
|
|
379
|
+
plt.plot(outline(Xsl), outline(Zsl), "k--", alpha=0.3, linewidth=1)
|
|
380
|
+
plt.plot(outline(Xsl + scale * Usl), outline(Zsl + scale * Wsl), "k", linewidth=1)
|
|
353
381
|
|
|
354
382
|
# Plot deformed weak-layer outline
|
|
355
|
-
if instance.system in [
|
|
383
|
+
if instance.system in ["-pst", "pst-", "-vpst", "vpst-"]:
|
|
356
384
|
nanmask = np.isfinite(xwl)
|
|
357
|
-
plt.plot(
|
|
358
|
-
|
|
359
|
-
|
|
385
|
+
plt.plot(
|
|
386
|
+
outline(Xwl[:, nanmask] + scale * Uwl[:, nanmask]),
|
|
387
|
+
outline(Zwl[:, nanmask] + scale * Wwl[:, nanmask]),
|
|
388
|
+
"k",
|
|
389
|
+
linewidth=1,
|
|
390
|
+
)
|
|
360
391
|
|
|
361
392
|
# Colormap
|
|
362
393
|
cmap = plt.cm.RdBu_r
|
|
@@ -364,15 +395,25 @@ def deformed(instance, xsl, xwl, z, phi, dz=2, scale=100,
|
|
|
364
395
|
cmap.set_under(adjust_lightness(cmap(0.0), 0.9))
|
|
365
396
|
|
|
366
397
|
# Plot fields
|
|
367
|
-
plt.contourf(
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
398
|
+
plt.contourf(
|
|
399
|
+
Xsl + scale * Usl,
|
|
400
|
+
Zsl + scale * Wsl,
|
|
401
|
+
slab,
|
|
402
|
+
levels=levels, # norm=norm,
|
|
403
|
+
cmap=cmap,
|
|
404
|
+
extend="both",
|
|
405
|
+
)
|
|
406
|
+
plt.contourf(
|
|
407
|
+
Xwl + scale * Uwl,
|
|
408
|
+
Zwl + scale * Wwl,
|
|
409
|
+
weak,
|
|
410
|
+
levels=levels, # norm=norm,
|
|
411
|
+
cmap=cmap,
|
|
412
|
+
extend="both",
|
|
413
|
+
)
|
|
373
414
|
|
|
374
415
|
# Plot setup
|
|
375
|
-
plt.axis(
|
|
416
|
+
plt.axis("scaled")
|
|
376
417
|
plt.xlim([xmin, xmax])
|
|
377
418
|
plt.ylim([zmin, zmax])
|
|
378
419
|
plt.gca().set_aspect(aspect)
|
|
@@ -380,14 +421,13 @@ def deformed(instance, xsl, xwl, z, phi, dz=2, scale=100,
|
|
|
380
421
|
plt.gca().use_sticky_edges = False
|
|
381
422
|
|
|
382
423
|
# Plot labels
|
|
383
|
-
plt.gca().set_xlabel(r
|
|
384
|
-
plt.gca().set_ylabel(
|
|
385
|
-
plt.title(
|
|
424
|
+
plt.gca().set_xlabel(r"lateral position $x$ (cm) $\longrightarrow$")
|
|
425
|
+
plt.gca().set_ylabel("depth below surface\n" + r"$\longleftarrow $ $d$ (cm)")
|
|
426
|
+
plt.title(rf"${scale}\!\times\!$ scaled deformations (cm)", size=10)
|
|
386
427
|
|
|
387
428
|
# Show colorbar
|
|
388
429
|
ticks = np.linspace(levels[0], levels[-1], num=11, endpoint=True)
|
|
389
|
-
plt.colorbar(orientation=
|
|
390
|
-
label=label, aspect=35)
|
|
430
|
+
plt.colorbar(orientation="horizontal", ticks=ticks, label=label, aspect=35)
|
|
391
431
|
|
|
392
432
|
# Save figure
|
|
393
433
|
save_plot(name=filename)
|
|
@@ -403,95 +443,104 @@ def deformed(instance, xsl, xwl, z, phi, dz=2, scale=100,
|
|
|
403
443
|
|
|
404
444
|
|
|
405
445
|
def plot_data(
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
446
|
+
name,
|
|
447
|
+
ax1data,
|
|
448
|
+
ax1label,
|
|
449
|
+
ax2data=None,
|
|
450
|
+
ax2label=None,
|
|
451
|
+
labelpos=None,
|
|
452
|
+
vlines=True,
|
|
453
|
+
li=False,
|
|
454
|
+
mi=False,
|
|
455
|
+
ki=False,
|
|
456
|
+
xlabel=r"Horizontal position $x$ (cm)",
|
|
457
|
+
):
|
|
411
458
|
"""Plot data. Base function."""
|
|
412
459
|
# Figure setup
|
|
413
460
|
plt.rcdefaults()
|
|
414
|
-
plt.rc(
|
|
415
|
-
plt.rc(
|
|
461
|
+
plt.rc("font", family="serif", size=10)
|
|
462
|
+
plt.rc("mathtext", fontset="cm")
|
|
416
463
|
|
|
417
464
|
# Plot styles
|
|
418
465
|
labelstyle, colors = set_plotstyles()
|
|
419
466
|
|
|
420
467
|
# Create figure
|
|
421
|
-
fig = plt.figure(figsize=(4, 8/3))
|
|
468
|
+
fig = plt.figure(figsize=(4, 8 / 3))
|
|
422
469
|
ax1 = fig.gca()
|
|
423
470
|
|
|
424
471
|
# Axis limits
|
|
425
|
-
ax1.autoscale(axis=
|
|
472
|
+
ax1.autoscale(axis="x", tight=True)
|
|
426
473
|
|
|
427
474
|
# Set axis labels
|
|
428
|
-
ax1.set_xlabel(xlabel + r
|
|
429
|
-
ax1.set_ylabel(ax1label + r
|
|
475
|
+
ax1.set_xlabel(xlabel + r" $\longrightarrow$")
|
|
476
|
+
ax1.set_ylabel(ax1label + r" $\longrightarrow$")
|
|
430
477
|
|
|
431
478
|
# Plot x-axis
|
|
432
|
-
ax1.axhline(0, linewidth=0.5, color=
|
|
479
|
+
ax1.axhline(0, linewidth=0.5, color="gray")
|
|
433
480
|
|
|
434
481
|
# Plot vertical separators
|
|
435
482
|
if vlines:
|
|
436
|
-
ax1.axvline(0, linewidth=0.5, color=
|
|
483
|
+
ax1.axvline(0, linewidth=0.5, color="gray")
|
|
437
484
|
for i, f in enumerate(ki):
|
|
438
485
|
if not f:
|
|
439
|
-
ax1.axvspan(
|
|
440
|
-
|
|
486
|
+
ax1.axvspan(
|
|
487
|
+
sum(li[:i]) / 10,
|
|
488
|
+
sum(li[: i + 1]) / 10,
|
|
489
|
+
facecolor="gray",
|
|
490
|
+
alpha=0.05,
|
|
491
|
+
zorder=100,
|
|
492
|
+
)
|
|
441
493
|
for i, m in enumerate(mi, start=1):
|
|
442
494
|
if m > 0:
|
|
443
|
-
ax1.axvline(sum(li[:i])/10, linewidth=0.5, color=
|
|
495
|
+
ax1.axvline(sum(li[:i]) / 10, linewidth=0.5, color="gray")
|
|
444
496
|
else:
|
|
445
|
-
ax1.autoscale(axis=
|
|
497
|
+
ax1.autoscale(axis="y", tight=True)
|
|
446
498
|
|
|
447
499
|
# Calculate labelposition
|
|
448
500
|
if not labelpos:
|
|
449
501
|
x = ax1data[0][0]
|
|
450
|
-
labelpos = int(0.95*len(x[~np.isnan(x)]))
|
|
502
|
+
labelpos = int(0.95 * len(x[~np.isnan(x)]))
|
|
451
503
|
|
|
452
504
|
# Fill left y-axis
|
|
453
505
|
i = 0
|
|
454
506
|
for x, y, label in ax1data:
|
|
455
507
|
i += 1
|
|
456
|
-
if label ==
|
|
508
|
+
if label == "" or "FEA" in label:
|
|
457
509
|
# line, = ax1.plot(x, y, 'k:', linewidth=1)
|
|
458
|
-
ax1.plot(x, y, linewidth=3, color=
|
|
459
|
-
line, = ax1.plot(x, y,
|
|
510
|
+
ax1.plot(x, y, linewidth=3, color="white")
|
|
511
|
+
(line,) = ax1.plot(x, y, ":", linewidth=1) # , color='black'
|
|
460
512
|
thislabelpos = -2
|
|
461
513
|
x, y = x[~np.isnan(x)], y[~np.isnan(x)]
|
|
462
|
-
xtx = (x[thislabelpos - 1] + x[thislabelpos])/2
|
|
463
|
-
ytx = (y[thislabelpos - 1] + y[thislabelpos])/2
|
|
464
|
-
ax1.text(xtx, ytx, label, color=line.get_color(),
|
|
465
|
-
**labelstyle)
|
|
514
|
+
xtx = (x[thislabelpos - 1] + x[thislabelpos]) / 2
|
|
515
|
+
ytx = (y[thislabelpos - 1] + y[thislabelpos]) / 2
|
|
516
|
+
ax1.text(xtx, ytx, label, color=line.get_color(), **labelstyle)
|
|
466
517
|
else:
|
|
467
518
|
# Plot line
|
|
468
|
-
ax1.plot(x, y, linewidth=3, color=
|
|
469
|
-
line, = ax1.plot(x, y, linewidth=1)
|
|
519
|
+
ax1.plot(x, y, linewidth=3, color="white")
|
|
520
|
+
(line,) = ax1.plot(x, y, linewidth=1)
|
|
470
521
|
# Line label
|
|
471
522
|
x, y = x[~np.isnan(x)], y[~np.isnan(x)]
|
|
472
523
|
if len(x) > 0:
|
|
473
|
-
xtx = (x[labelpos - 10*i - 1] + x[labelpos - 10*i])/2
|
|
474
|
-
ytx = (y[labelpos - 10*i - 1] + y[labelpos - 10*i])/2
|
|
475
|
-
ax1.text(xtx, ytx, label, color=line.get_color(),
|
|
476
|
-
**labelstyle)
|
|
524
|
+
xtx = (x[labelpos - 10 * i - 1] + x[labelpos - 10 * i]) / 2
|
|
525
|
+
ytx = (y[labelpos - 10 * i - 1] + y[labelpos - 10 * i]) / 2
|
|
526
|
+
ax1.text(xtx, ytx, label, color=line.get_color(), **labelstyle)
|
|
477
527
|
|
|
478
528
|
# Fill right y-axis
|
|
479
529
|
if ax2data:
|
|
480
530
|
# Create right y-axis
|
|
481
531
|
ax2 = ax1.twinx()
|
|
482
532
|
# Set axis label
|
|
483
|
-
ax2.set_ylabel(ax2label + r
|
|
533
|
+
ax2.set_ylabel(ax2label + r" $\longrightarrow$")
|
|
484
534
|
# Fill
|
|
485
535
|
for x, y, label in ax2data:
|
|
486
536
|
# Plot line
|
|
487
|
-
ax2.plot(x, y, linewidth=3, color=
|
|
488
|
-
line, = ax2.plot(x, y, linewidth=1, color=colors[8, 0])
|
|
537
|
+
ax2.plot(x, y, linewidth=3, color="white")
|
|
538
|
+
(line,) = ax2.plot(x, y, linewidth=1, color=colors[8, 0])
|
|
489
539
|
# Line label
|
|
490
540
|
x, y = x[~np.isnan(x)], y[~np.isnan(x)]
|
|
491
|
-
xtx = (x[labelpos - 1] + x[labelpos])/2
|
|
492
|
-
ytx = (y[labelpos - 1] + y[labelpos])/2
|
|
493
|
-
ax2.text(xtx, ytx, label, color=line.get_color(),
|
|
494
|
-
**labelstyle)
|
|
541
|
+
xtx = (x[labelpos - 1] + x[labelpos]) / 2
|
|
542
|
+
ytx = (y[labelpos - 1] + y[labelpos]) / 2
|
|
543
|
+
ax2.text(xtx, ytx, label, color=line.get_color(), **labelstyle)
|
|
495
544
|
|
|
496
545
|
# Save figure
|
|
497
546
|
save_plot(name)
|
|
@@ -506,105 +555,104 @@ def plot_data(
|
|
|
506
555
|
# === PLOT WRAPPERS ===========================================================
|
|
507
556
|
|
|
508
557
|
|
|
509
|
-
def displacements(instance, x, z, i=
|
|
558
|
+
def displacements(instance, x, z, i="", **segments):
|
|
510
559
|
"""Wrap for dispalcements plot."""
|
|
511
560
|
data = [
|
|
512
|
-
[x/10, instance.u(z, z0=0, unit=
|
|
513
|
-
[x/10, -instance.w(z, unit=
|
|
514
|
-
[x/10, instance.psi(z, unit=
|
|
561
|
+
[x / 10, instance.u(z, z0=0, unit="mm"), r"$u_0\ (\mathrm{mm})$"],
|
|
562
|
+
[x / 10, -instance.w(z, unit="mm"), r"$-w\ (\mathrm{mm})$"],
|
|
563
|
+
[x / 10, instance.psi(z, unit="degrees"), r"$\psi\ (^\circ)$ "],
|
|
515
564
|
]
|
|
516
|
-
plot_data(ax1label=r
|
|
517
|
-
name='disp' + str(i), **segments)
|
|
565
|
+
plot_data(ax1label=r"Displacements", ax1data=data, name="disp" + str(i), **segments)
|
|
518
566
|
|
|
519
567
|
|
|
520
|
-
def section_forces(instance, x, z, i=
|
|
568
|
+
def section_forces(instance, x, z, i="", **segments):
|
|
521
569
|
"""Wrap section forces plot."""
|
|
522
570
|
data = [
|
|
523
|
-
[x/10, instance.N(z), r
|
|
524
|
-
[x/10, instance.M(z), r
|
|
525
|
-
[x/10, instance.V(z), r
|
|
571
|
+
[x / 10, instance.N(z), r"$N$"],
|
|
572
|
+
[x / 10, instance.M(z), r"$M$"],
|
|
573
|
+
[x / 10, instance.V(z), r"$V$"],
|
|
526
574
|
]
|
|
527
|
-
plot_data(ax1label=r
|
|
528
|
-
name='forc' + str(i), **segments)
|
|
575
|
+
plot_data(ax1label=r"Section forces", ax1data=data, name="forc" + str(i), **segments)
|
|
529
576
|
|
|
530
577
|
|
|
531
|
-
def stresses(instance, x, z, i=
|
|
578
|
+
def stresses(instance, x, z, i="", **segments):
|
|
532
579
|
"""Wrap stress plot."""
|
|
533
580
|
data = [
|
|
534
|
-
[x/10, instance.tau(z, unit=
|
|
535
|
-
[x/10, instance.sig(z, unit=
|
|
581
|
+
[x / 10, instance.tau(z, unit="kPa"), r"$\tau$"],
|
|
582
|
+
[x / 10, instance.sig(z, unit="kPa"), r"$\sigma$"],
|
|
536
583
|
]
|
|
537
|
-
plot_data(ax1label=r
|
|
538
|
-
name='stress' + str(i), **segments)
|
|
584
|
+
plot_data(ax1label=r"Stress (kPa)", ax1data=data, name="stress" + str(i), **segments)
|
|
539
585
|
|
|
540
586
|
|
|
541
587
|
def stress_criteria(x, stress, **segments):
|
|
542
588
|
"""Wrap plot of stress and energy criteria."""
|
|
543
|
-
data = [
|
|
544
|
-
|
|
545
|
-
]
|
|
546
|
-
plot_data(ax1label=r'Criteria', ax1data=data,
|
|
547
|
-
name='crit', **segments)
|
|
589
|
+
data = [[x / 10, stress, r"$\sigma/\sigma_\mathrm{c}$"]]
|
|
590
|
+
plot_data(ax1label=r"Criteria", ax1data=data, name="crit", **segments)
|
|
548
591
|
|
|
549
592
|
|
|
550
593
|
def err_comp(da, Gdif, Ginc, mode=0):
|
|
551
594
|
"""Wrap energy release rate plot."""
|
|
552
595
|
data = [
|
|
553
|
-
[da/10, 1e3*Gdif[mode, :], r
|
|
554
|
-
[da/10, 1e3*Ginc[mode, :], r
|
|
596
|
+
[da / 10, 1e3 * Gdif[mode, :], r"$\mathcal{G}$"],
|
|
597
|
+
[da / 10, 1e3 * Ginc[mode, :], r"$\bar{\mathcal{G}}$"],
|
|
555
598
|
]
|
|
556
599
|
plot_data(
|
|
557
|
-
xlabel=r
|
|
558
|
-
ax1label=r
|
|
559
|
-
ax1data=data,
|
|
600
|
+
xlabel=r"Crack length $\Delta a$ (cm)",
|
|
601
|
+
ax1label=r"Energy release rate (J/m$^2$)",
|
|
602
|
+
ax1data=data,
|
|
603
|
+
name="err",
|
|
604
|
+
vlines=False,
|
|
605
|
+
)
|
|
560
606
|
|
|
561
607
|
|
|
562
|
-
def err_modes(da, G, kind=
|
|
608
|
+
def err_modes(da, G, kind="inc"):
|
|
563
609
|
"""Wrap energy release rate plot."""
|
|
564
|
-
label = r
|
|
610
|
+
label = r"$\bar{\mathcal{G}}$" if kind == "inc" else r"$\mathcal{G}$"
|
|
565
611
|
data = [
|
|
566
|
-
[da/10, 1e3*G[2, :], label + r
|
|
567
|
-
[da/10, 1e3*G[1, :], label + r
|
|
568
|
-
[da/10, 1e3*G[0, :], label + r
|
|
612
|
+
[da / 10, 1e3 * G[2, :], label + r"$_\mathrm{I\!I}$"],
|
|
613
|
+
[da / 10, 1e3 * G[1, :], label + r"$_\mathrm{I}$"],
|
|
614
|
+
[da / 10, 1e3 * G[0, :], label + r"$_\mathrm{I+I\!I}$"],
|
|
569
615
|
]
|
|
570
616
|
plot_data(
|
|
571
|
-
xlabel=r
|
|
572
|
-
ax1label=r
|
|
573
|
-
ax1data=data,
|
|
617
|
+
xlabel=r"Crack length $a$ (cm)",
|
|
618
|
+
ax1label=r"Energy release rate (J/m$^2$)",
|
|
619
|
+
ax1data=data,
|
|
620
|
+
name="modes",
|
|
621
|
+
vlines=False,
|
|
622
|
+
)
|
|
574
623
|
|
|
575
624
|
|
|
576
625
|
def fea_disp(instance, x, z, fea):
|
|
577
626
|
"""Wrap dispalcements plot."""
|
|
578
627
|
data = [
|
|
579
|
-
[fea[:, 0]/10, -np.flipud(fea[:, 1]), r
|
|
580
|
-
[fea[:, 0]/10, np.flipud(fea[:, 2]), r
|
|
628
|
+
[fea[:, 0] / 10, -np.flipud(fea[:, 1]), r"FEA $u_0$"],
|
|
629
|
+
[fea[:, 0] / 10, np.flipud(fea[:, 2]), r"FEA $w_0$"],
|
|
581
630
|
# [fea[:, 0]/10, -np.flipud(fea[:, 3]), r'FEA $u(z=-h/2)$'],
|
|
582
631
|
# [fea[:, 0]/10, np.flipud(fea[:, 4]), r'FEA $w(z=-h/2)$'],
|
|
583
|
-
[fea[:, 0]/10,
|
|
584
|
-
|
|
585
|
-
[x/10, instance.
|
|
586
|
-
[x/10,
|
|
587
|
-
[x/10, np.rad2deg(instance.psi(z)), r'$\psi$']
|
|
632
|
+
[fea[:, 0] / 10, np.flipud(np.rad2deg(fea[:, 5])), r"FEA $\psi$"],
|
|
633
|
+
[x / 10, instance.u(z, z0=0), r"$u_0$"],
|
|
634
|
+
[x / 10, -instance.w(z), r"$-w$"],
|
|
635
|
+
[x / 10, np.rad2deg(instance.psi(z)), r"$\psi$"],
|
|
588
636
|
]
|
|
589
637
|
plot_data(
|
|
590
|
-
ax1label=r
|
|
591
|
-
|
|
638
|
+
ax1label=r"Displacements (mm)", ax1data=data, name="fea_disp", labelpos=-50
|
|
639
|
+
)
|
|
592
640
|
|
|
593
641
|
|
|
594
642
|
def fea_stress(instance, xb, zb, fea):
|
|
595
643
|
"""Wrap stress plot."""
|
|
596
644
|
data = [
|
|
597
|
-
[fea[:, 0]/10, 1e3*np.flipud(fea[:, 2]), r
|
|
598
|
-
[fea[:, 0]/10, 1e3*np.flipud(fea[:, 3]), r
|
|
599
|
-
[xb/10, instance.tau(zb, unit=
|
|
600
|
-
[xb/10, instance.sig(zb, unit=
|
|
645
|
+
[fea[:, 0] / 10, 1e3 * np.flipud(fea[:, 2]), r"FEA $\sigma_2$"],
|
|
646
|
+
[fea[:, 0] / 10, 1e3 * np.flipud(fea[:, 3]), r"FEA $\tau_{12}$"],
|
|
647
|
+
[xb / 10, instance.tau(zb, unit="kPa"), r"$\tau$"],
|
|
648
|
+
[xb / 10, instance.sig(zb, unit="kPa"), r"$\sigma$"],
|
|
601
649
|
]
|
|
602
|
-
plot_data(ax1label=r
|
|
603
|
-
labelpos=-50)
|
|
650
|
+
plot_data(ax1label=r"Stress (kPa)", ax1data=data, name="fea_stress", labelpos=-50)
|
|
604
651
|
|
|
605
652
|
|
|
606
653
|
# === SAVE FUNCTION ===========================================================
|
|
607
654
|
|
|
655
|
+
|
|
608
656
|
def save_plot(name):
|
|
609
657
|
"""
|
|
610
658
|
Show or save plot depending on interpreter
|
|
@@ -614,14 +662,14 @@ def save_plot(name):
|
|
|
614
662
|
name : string
|
|
615
663
|
Name for the figure.
|
|
616
664
|
"""
|
|
617
|
-
filename = name +
|
|
665
|
+
filename = name + ".png"
|
|
618
666
|
# Show figure if on jupyter notebook
|
|
619
667
|
if isnotebook():
|
|
620
668
|
plt.show()
|
|
621
669
|
# Save figure if on terminal
|
|
622
670
|
else:
|
|
623
671
|
# Make directory if not yet existing
|
|
624
|
-
if not os.path.isdir(os.path.join(os.getcwd(),
|
|
625
|
-
os.mkdir(
|
|
626
|
-
plt.savefig(
|
|
672
|
+
if not os.path.isdir(os.path.join(os.getcwd(), "plots")):
|
|
673
|
+
os.mkdir("plots")
|
|
674
|
+
plt.savefig("plots/" + filename, bbox_inches="tight")
|
|
627
675
|
return
|