weac 2.6.1__py3-none-any.whl → 2.6.3__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 +8 -10
- weac/plot.py +244 -196
- weac/tools.py +6 -5
- {weac-2.6.1.dist-info → weac-2.6.3.dist-info}/METADATA +13 -2
- weac-2.6.3.dist-info/RECORD +12 -0
- {weac-2.6.1.dist-info → weac-2.6.3.dist-info}/WHEEL +1 -1
- weac-2.6.1.dist-info/RECORD +0 -12
- {weac-2.6.1.dist-info → weac-2.6.3.dist-info/licenses}/LICENSE +0 -0
- {weac-2.6.1.dist-info → weac-2.6.3.dist-info}/top_level.txt +0 -0
weac/__init__.py
CHANGED
|
@@ -6,16 +6,12 @@ dry-snow slab avalanche release.
|
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
# Module imports
|
|
9
|
-
from weac.layered import Layered
|
|
10
|
-
from weac.inverse import Inverse
|
|
11
9
|
from weac import plot
|
|
10
|
+
from weac.inverse import Inverse
|
|
11
|
+
from weac.layered import Layered
|
|
12
12
|
|
|
13
13
|
# Version
|
|
14
|
-
__version__ =
|
|
14
|
+
__version__ = "2.6.3"
|
|
15
15
|
|
|
16
16
|
# Public names
|
|
17
|
-
__all__ = [
|
|
18
|
-
'Layered',
|
|
19
|
-
'Inverse',
|
|
20
|
-
'plot'
|
|
21
|
-
]
|
|
17
|
+
__all__ = ["Layered", "Inverse", "plot"]
|
weac/eigensystem.py
CHANGED
|
@@ -90,7 +90,7 @@ class Eigensystem:
|
|
|
90
90
|
Describes the stiffnesses of weak-layer and slab.
|
|
91
91
|
"""
|
|
92
92
|
|
|
93
|
-
def __init__(self, system=
|
|
93
|
+
def __init__(self, system="pst-", touchdown=False):
|
|
94
94
|
"""
|
|
95
95
|
Initialize eigensystem with user input.
|
|
96
96
|
|
|
@@ -108,54 +108,51 @@ class Eigensystem:
|
|
|
108
108
|
to one layer. Default is [[240, 200], ].
|
|
109
109
|
"""
|
|
110
110
|
# Assign global attributes
|
|
111
|
-
self.g = 9810
|
|
112
|
-
self.lski = 1000
|
|
113
|
-
self.tol = 1e-3
|
|
114
|
-
self.system = system
|
|
111
|
+
self.g = 9810 # Gravitaiton (mm/s^2)
|
|
112
|
+
self.lski = 1000 # Effective out-of-plane length of skis (mm)
|
|
113
|
+
self.tol = 1e-3 # Relative Romberg integration tolerance
|
|
114
|
+
self.system = system # 'pst-', '-pst', 'vpst-', '-vpst', 'skier', 'skiers'
|
|
115
115
|
|
|
116
116
|
# Initialize weak-layer attributes that will be filled later
|
|
117
|
-
self.weak = False
|
|
118
|
-
self.t = False
|
|
119
|
-
self.kn = False
|
|
120
|
-
self.kt = False
|
|
117
|
+
self.weak = False # Weak-layer properties dictionary
|
|
118
|
+
self.t = False # Weak-layer thickness (mm)
|
|
119
|
+
self.kn = False # Weak-layer compressive stiffness
|
|
120
|
+
self.kt = False # Weak-layer shear stiffness
|
|
121
121
|
|
|
122
122
|
# Initialize slab attributes
|
|
123
|
-
self.p = 0
|
|
124
|
-
self.slab = False
|
|
125
|
-
self.k = False
|
|
126
|
-
self.h = False
|
|
127
|
-
self.zs = False
|
|
128
|
-
self.phi = False
|
|
129
|
-
self.A11 = False
|
|
130
|
-
self.B11 = False
|
|
131
|
-
self.D11 = False
|
|
132
|
-
self.kA55 = False
|
|
133
|
-
self.K0 = False
|
|
123
|
+
self.p = 0 # Surface line load (N/mm)
|
|
124
|
+
self.slab = False # Slab properties dictionary
|
|
125
|
+
self.k = False # Slab shear correction factor
|
|
126
|
+
self.h = False # Total slab height (mm)
|
|
127
|
+
self.zs = False # Z-coordinate of slab center of gravity (mm)
|
|
128
|
+
self.phi = False # Slab inclination (°)
|
|
129
|
+
self.A11 = False # Slab extensional stiffness
|
|
130
|
+
self.B11 = False # Slab bending-extension coupling stiffness
|
|
131
|
+
self.D11 = False # Slab bending stiffness
|
|
132
|
+
self.kA55 = False # Slab shear stiffness
|
|
133
|
+
self.K0 = False # Stiffness determinant
|
|
134
134
|
|
|
135
135
|
# Inizialize eigensystem attributes
|
|
136
|
-
self.ewC = False
|
|
137
|
-
self.ewR = False
|
|
138
|
-
self.evC = False
|
|
139
|
-
self.evR = False
|
|
140
|
-
self.sC = False
|
|
141
|
-
self.sR = False
|
|
136
|
+
self.ewC = False # Complex eigenvalues
|
|
137
|
+
self.ewR = False # Real eigenvalues
|
|
138
|
+
self.evC = False # Complex eigenvectors
|
|
139
|
+
self.evR = False # Real eigenvectors
|
|
140
|
+
self.sC = False # Stability shift of complex eigenvalues
|
|
141
|
+
self.sR = False # Stability shift of real eigenvalues
|
|
142
142
|
|
|
143
143
|
# Initialize touchdown attributes
|
|
144
144
|
self.touchdown = touchdown # Flag whether touchdown is possible
|
|
145
|
-
self.a = False
|
|
146
|
-
self.tc = False
|
|
147
|
-
self.ratio = False
|
|
148
|
-
self.betaU = False
|
|
149
|
-
self.betaC = False
|
|
150
|
-
self.mode = False
|
|
151
|
-
self.td = False
|
|
145
|
+
self.a = False # Cracklength
|
|
146
|
+
self.tc = False # Weak-layer collapse height (mm)
|
|
147
|
+
self.ratio = False # Stiffness ratio of collapsed to uncollapsed weak-layer
|
|
148
|
+
self.betaU = False # Ratio of slab to bedding stiffness (uncollapsed)
|
|
149
|
+
self.betaC = False # Ratio of slab to bedding stiffness (collapsed)
|
|
150
|
+
self.mode = False # Touchdown-mode can be either A, B, C or D
|
|
151
|
+
self.td = False # Touchdown length
|
|
152
152
|
|
|
153
153
|
def set_foundation_properties(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
E: float = 0.25,
|
|
157
|
-
nu: float = 0.25,
|
|
158
|
-
update: bool = False):
|
|
154
|
+
self, t: float = 30.0, E: float = 0.25, nu: float = 0.25, update: bool = False
|
|
155
|
+
):
|
|
159
156
|
"""
|
|
160
157
|
Set material properties and geometry of foundation (weak layer).
|
|
161
158
|
|
|
@@ -175,20 +172,19 @@ class Eigensystem:
|
|
|
175
172
|
foundation properties have changed.
|
|
176
173
|
"""
|
|
177
174
|
# Geometry
|
|
178
|
-
self.t = t
|
|
175
|
+
self.t = t # Weak-layer thickness (mm)
|
|
179
176
|
|
|
180
177
|
# Material properties
|
|
181
178
|
self.weak = {
|
|
182
|
-
|
|
183
|
-
|
|
179
|
+
"nu": nu, # Poisson's ratio (-)
|
|
180
|
+
"E": E, # Young's modulus (MPa)
|
|
184
181
|
}
|
|
185
182
|
|
|
186
183
|
# Recalculate the fundamental system after properties have changed
|
|
187
184
|
if update:
|
|
188
185
|
self.calc_fundamental_system()
|
|
189
186
|
|
|
190
|
-
def set_beam_properties(self, layers, C0=6.5, C1=4.4,
|
|
191
|
-
nu=0.25, update=False):
|
|
187
|
+
def set_beam_properties(self, layers, C0=6.5, C1=4.4, nu=0.25, update=False):
|
|
192
188
|
"""
|
|
193
189
|
Set material and properties geometry of beam (slab).
|
|
194
190
|
|
|
@@ -220,9 +216,9 @@ class Eigensystem:
|
|
|
220
216
|
E = bergfeld(layers[:, 0], C0=C0, C1=C1) # Young's modulus
|
|
221
217
|
|
|
222
218
|
# Derive other elastic properties
|
|
223
|
-
nu = nu*np.ones(layers.shape[0])
|
|
224
|
-
G = E/(2*(1 + nu))
|
|
225
|
-
self.k = 5/6
|
|
219
|
+
nu = nu * np.ones(layers.shape[0]) # Global poisson's ratio
|
|
220
|
+
G = E / (2 * (1 + nu)) # Shear modulus
|
|
221
|
+
self.k = 5 / 6 # Shear correction factor
|
|
226
222
|
|
|
227
223
|
# Compute total slab thickness and center of gravity
|
|
228
224
|
self.h, self.zs = calc_center_of_gravity(layers)
|
|
@@ -257,12 +253,12 @@ class Eigensystem:
|
|
|
257
253
|
def calc_foundation_stiffness(self):
|
|
258
254
|
"""Compute foundation normal and shear stiffness."""
|
|
259
255
|
# Elastic moduli (MPa) under plane-strain conditions
|
|
260
|
-
G = self.weak[
|
|
261
|
-
E = self.weak[
|
|
256
|
+
G = self.weak["E"] / (2 * (1 + self.weak["nu"])) # Shear modulus
|
|
257
|
+
E = self.weak["E"] / (1 - self.weak["nu"] ** 2) # Young's modulus
|
|
262
258
|
|
|
263
259
|
# Foundation (weak layer) stiffnesses (N/mm^3)
|
|
264
|
-
self.kn = E/self.t
|
|
265
|
-
self.kt = G/self.t
|
|
260
|
+
self.kn = E / self.t # Normal stiffness
|
|
261
|
+
self.kt = G / self.t # Shear stiffness
|
|
266
262
|
|
|
267
263
|
def get_ply_coordinates(self):
|
|
268
264
|
"""
|
|
@@ -278,7 +274,7 @@ class Eigensystem:
|
|
|
278
274
|
# Get list of ply (layer) thicknesses and prepend 0
|
|
279
275
|
t = np.concatenate(([0], self.slab[:, 1]))
|
|
280
276
|
# Calculate and return ply z-coordiantes
|
|
281
|
-
return np.cumsum(t) - self.h/2
|
|
277
|
+
return np.cumsum(t) - self.h / 2
|
|
282
278
|
|
|
283
279
|
def calc_laminate_stiffness_matrix(self):
|
|
284
280
|
"""
|
|
@@ -293,16 +289,16 @@ class Eigensystem:
|
|
|
293
289
|
# Add layerwise contributions
|
|
294
290
|
for i in range(len(z) - 1):
|
|
295
291
|
E, G, nu = self.slab[i, 2:5]
|
|
296
|
-
A11 = A11 + E/(1 - nu**2)*(z[i+1] - z[i])
|
|
297
|
-
B11 = B11 + 1/2*E/(1 - nu**2)*(z[i+1]**2 - z[i]**2)
|
|
298
|
-
D11 = D11 + 1/3*E/(1 - nu**2)*(z[i+1]**3 - z[i]**3)
|
|
299
|
-
kA55 = kA55 + self.k*G*(z[i+1] - z[i])
|
|
292
|
+
A11 = A11 + E / (1 - nu**2) * (z[i + 1] - z[i])
|
|
293
|
+
B11 = B11 + 1 / 2 * E / (1 - nu**2) * (z[i + 1] ** 2 - z[i] ** 2)
|
|
294
|
+
D11 = D11 + 1 / 3 * E / (1 - nu**2) * (z[i + 1] ** 3 - z[i] ** 3)
|
|
295
|
+
kA55 = kA55 + self.k * G * (z[i + 1] - z[i])
|
|
300
296
|
|
|
301
297
|
self.A11 = A11
|
|
302
298
|
self.B11 = B11
|
|
303
299
|
self.D11 = D11
|
|
304
300
|
self.kA55 = kA55
|
|
305
|
-
self.K0 = B11**2 - A11*D11
|
|
301
|
+
self.K0 = B11**2 - A11 * D11
|
|
306
302
|
|
|
307
303
|
def calc_system_matrix(self):
|
|
308
304
|
"""
|
|
@@ -321,29 +317,39 @@ class Eigensystem:
|
|
|
321
317
|
kt = self.kt
|
|
322
318
|
|
|
323
319
|
# Abbreviations (MIT t/2 im GGW, MIT w' in Kinematik)
|
|
324
|
-
K21 = kt*(-2*self.D11 + self.B11*(self.h + self.t))/(2*self.K0)
|
|
325
|
-
K24 = (
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
320
|
+
K21 = kt * (-2 * self.D11 + self.B11 * (self.h + self.t)) / (2 * self.K0)
|
|
321
|
+
K24 = (
|
|
322
|
+
2 * self.D11 * kt * self.t
|
|
323
|
+
- self.B11 * kt * self.t * (self.h + self.t)
|
|
324
|
+
+ 4 * self.B11 * self.kA55
|
|
325
|
+
) / (4 * self.K0)
|
|
326
|
+
K25 = (
|
|
327
|
+
-2 * self.D11 * self.h * kt
|
|
328
|
+
+ self.B11 * self.h * kt * (self.h + self.t)
|
|
329
|
+
+ 4 * self.B11 * self.kA55
|
|
330
|
+
) / (4 * self.K0)
|
|
331
|
+
K43 = kn / self.kA55
|
|
332
|
+
K61 = kt * (2 * self.B11 - self.A11 * (self.h + self.t)) / (2 * self.K0)
|
|
333
|
+
K64 = (
|
|
334
|
+
-2 * self.B11 * kt * self.t
|
|
335
|
+
+ self.A11 * kt * self.t * (self.h + self.t)
|
|
336
|
+
- 4 * self.A11 * self.kA55
|
|
337
|
+
) / (4 * self.K0)
|
|
338
|
+
K65 = (
|
|
339
|
+
2 * self.B11 * self.h * kt
|
|
340
|
+
- self.A11 * self.h * kt * (self.h + self.t)
|
|
341
|
+
- 4 * self.A11 * self.kA55
|
|
342
|
+
) / (4 * self.K0)
|
|
339
343
|
|
|
340
344
|
# System matrix
|
|
341
|
-
K = [
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
345
|
+
K = [
|
|
346
|
+
[0, 1, 0, 0, 0, 0],
|
|
347
|
+
[K21, 0, 0, K24, K25, 0],
|
|
348
|
+
[0, 0, 0, 1, 0, 0],
|
|
349
|
+
[0, 0, K43, 0, 0, -1],
|
|
350
|
+
[0, 0, 0, 0, 0, 1],
|
|
351
|
+
[K61, 0, 0, K64, K65, 0],
|
|
352
|
+
]
|
|
347
353
|
|
|
348
354
|
return np.array(K)
|
|
349
355
|
|
|
@@ -367,16 +373,28 @@ class Eigensystem:
|
|
|
367
373
|
"""
|
|
368
374
|
qn, qt = self.get_weight_load(phi)
|
|
369
375
|
pn, pt = self.get_surface_load(phi)
|
|
370
|
-
return np.array(
|
|
371
|
-
[
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
376
|
+
return np.array(
|
|
377
|
+
[
|
|
378
|
+
[0],
|
|
379
|
+
[
|
|
380
|
+
(
|
|
381
|
+
self.B11 * (self.h * pt - 2 * qt * self.zs)
|
|
382
|
+
+ 2 * self.D11 * (qt + pt)
|
|
383
|
+
)
|
|
384
|
+
/ (2 * self.K0)
|
|
385
|
+
],
|
|
386
|
+
[0],
|
|
387
|
+
[-(qn + pn) / self.kA55],
|
|
388
|
+
[0],
|
|
389
|
+
[
|
|
390
|
+
-(
|
|
391
|
+
self.A11 * (self.h * pt - 2 * qt * self.zs)
|
|
392
|
+
+ 2 * self.B11 * (qt + pt)
|
|
393
|
+
)
|
|
394
|
+
/ (2 * self.K0)
|
|
395
|
+
],
|
|
396
|
+
]
|
|
397
|
+
)
|
|
380
398
|
|
|
381
399
|
def calc_eigensystem(self):
|
|
382
400
|
"""Calculate eigenvalues and eigenvectors of the system matrix."""
|
|
@@ -384,7 +402,7 @@ class Eigensystem:
|
|
|
384
402
|
ew, ev = np.linalg.eig(self.calc_system_matrix())
|
|
385
403
|
# Classify real and complex eigenvalues
|
|
386
404
|
real = (ew.imag == 0) & (ew.real != 0) # real eigenvalues
|
|
387
|
-
cmplx = ew.imag > 0
|
|
405
|
+
cmplx = ew.imag > 0 # positive complex conjugates
|
|
388
406
|
# Eigenvalues
|
|
389
407
|
self.ewC = ew[cmplx]
|
|
390
408
|
self.ewR = ew[real].real
|
|
@@ -418,13 +436,13 @@ class Eigensystem:
|
|
|
418
436
|
Line load (N/mm) at center of gravity in tangential direction.
|
|
419
437
|
"""
|
|
420
438
|
# Convert units
|
|
421
|
-
phi = np.deg2rad(phi)
|
|
422
|
-
rho = self.slab[:, 0]*1e-12
|
|
439
|
+
phi = np.deg2rad(phi) # Convert inclination to rad
|
|
440
|
+
rho = self.slab[:, 0] * 1e-12 # Convert density to t/mm^3
|
|
423
441
|
# Sum up layer weight loads
|
|
424
|
-
q = sum(rho*self.g*self.slab[:, 1])
|
|
442
|
+
q = sum(rho * self.g * self.slab[:, 1]) # Line load (N/mm)
|
|
425
443
|
# Split into components
|
|
426
|
-
qn = q*np.cos(phi)
|
|
427
|
-
qt = -q*np.sin(phi)
|
|
444
|
+
qn = q * np.cos(phi) # Normal direction
|
|
445
|
+
qt = -q * np.sin(phi) # Tangential direction
|
|
428
446
|
|
|
429
447
|
return qn, qt
|
|
430
448
|
|
|
@@ -445,10 +463,10 @@ class Eigensystem:
|
|
|
445
463
|
Surface line load (N/mm) in tangential direction.
|
|
446
464
|
"""
|
|
447
465
|
# Convert units
|
|
448
|
-
phi = np.deg2rad(phi)
|
|
466
|
+
phi = np.deg2rad(phi) # Convert inclination to rad
|
|
449
467
|
# Split into components
|
|
450
|
-
pn = self.p*np.cos(phi)
|
|
451
|
-
pt = -self.p*np.sin(phi)
|
|
468
|
+
pn = self.p * np.cos(phi) # Normal direction
|
|
469
|
+
pt = -self.p * np.sin(phi) # Tangential direction
|
|
452
470
|
|
|
453
471
|
return pn, pt
|
|
454
472
|
|
|
@@ -470,10 +488,10 @@ class Eigensystem:
|
|
|
470
488
|
Ft : float
|
|
471
489
|
Skier load (N) in tangential direction.
|
|
472
490
|
"""
|
|
473
|
-
phi = np.deg2rad(phi)
|
|
474
|
-
F = 1e-3*np.array(m)*self.g/self.lski
|
|
475
|
-
Fn = F*np.cos(phi)
|
|
476
|
-
Ft = -F*np.sin(phi)
|
|
491
|
+
phi = np.deg2rad(phi) # Convert inclination to rad
|
|
492
|
+
F = 1e-3 * np.array(m) * self.g / self.lski # Total skier load (N)
|
|
493
|
+
Fn = F * np.cos(phi) # Normal skier load (N)
|
|
494
|
+
Ft = -F * np.sin(phi) # Tangential skier load (N)
|
|
477
495
|
|
|
478
496
|
return Fn, Ft
|
|
479
497
|
|
|
@@ -497,30 +515,41 @@ class Eigensystem:
|
|
|
497
515
|
Complementary solution matrix (6x6) at position x.
|
|
498
516
|
"""
|
|
499
517
|
if bed:
|
|
500
|
-
zh = np.concatenate(
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
518
|
+
zh = np.concatenate(
|
|
519
|
+
[
|
|
520
|
+
# Real
|
|
521
|
+
self.evR * np.exp(self.ewR * (x + l * self.sR)),
|
|
522
|
+
# Complex
|
|
523
|
+
np.exp(self.ewC.real * (x + l * self.sC))
|
|
524
|
+
* (
|
|
525
|
+
self.evC.real * np.cos(self.ewC.imag * x)
|
|
526
|
+
- self.evC.imag * np.sin(self.ewC.imag * x)
|
|
527
|
+
),
|
|
528
|
+
# Complex
|
|
529
|
+
np.exp(self.ewC.real * (x + l * self.sC))
|
|
530
|
+
* (
|
|
531
|
+
self.evC.imag * np.cos(self.ewC.imag * x)
|
|
532
|
+
+ self.evC.real * np.sin(self.ewC.imag * x)
|
|
533
|
+
),
|
|
534
|
+
],
|
|
535
|
+
axis=1,
|
|
536
|
+
)
|
|
511
537
|
else:
|
|
512
538
|
# Abbreviations
|
|
513
|
-
H14 = 3*self.B11/self.A11*x**2
|
|
514
|
-
H24 = 6*self.B11/self.A11*x
|
|
515
|
-
H54 = -3*x**2 + 6*self.K0/(self.A11*self.kA55)
|
|
539
|
+
H14 = 3 * self.B11 / self.A11 * x**2
|
|
540
|
+
H24 = 6 * self.B11 / self.A11 * x
|
|
541
|
+
H54 = -3 * x**2 + 6 * self.K0 / (self.A11 * self.kA55)
|
|
516
542
|
# Complementary solution matrix of free segments
|
|
517
543
|
zh = np.array(
|
|
518
|
-
[
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
544
|
+
[
|
|
545
|
+
[0, 0, 0, H14, 1, x],
|
|
546
|
+
[0, 0, 0, H24, 0, 1],
|
|
547
|
+
[1, x, x**2, x**3, 0, 0],
|
|
548
|
+
[0, 1, 2 * x, 3 * x**2, 0, 0],
|
|
549
|
+
[0, -1, -2 * x, H54, 0, 0],
|
|
550
|
+
[0, 0, -2, -6 * x, 0, 0],
|
|
551
|
+
]
|
|
552
|
+
)
|
|
524
553
|
|
|
525
554
|
return zh
|
|
526
555
|
|
|
@@ -564,23 +593,34 @@ class Eigensystem:
|
|
|
564
593
|
|
|
565
594
|
# Assemble particular integral vectors
|
|
566
595
|
if bed:
|
|
567
|
-
zp = np.array(
|
|
568
|
-
[
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
596
|
+
zp = np.array(
|
|
597
|
+
[
|
|
598
|
+
[
|
|
599
|
+
(qt + pt) / kt
|
|
600
|
+
+ h * qt * (h + t - 2 * zs) / (4 * kA55)
|
|
601
|
+
+ h * pt * (2 * h + t) / (4 * kA55)
|
|
602
|
+
],
|
|
603
|
+
[0],
|
|
604
|
+
[(qn + pn) / kn],
|
|
605
|
+
[0],
|
|
606
|
+
[-(qt * (h + t - 2 * zs) + pt * (2 * h + t)) / (2 * kA55)],
|
|
607
|
+
[0],
|
|
608
|
+
]
|
|
609
|
+
)
|
|
575
610
|
else:
|
|
576
|
-
zp = np.array(
|
|
577
|
-
[
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
611
|
+
zp = np.array(
|
|
612
|
+
[
|
|
613
|
+
[(-3 * (qt + pt) / A11 - B11 * (qn + pn) * x / K0) / 6 * x**2],
|
|
614
|
+
[(-2 * (qt + pt) / A11 - B11 * (qn + pn) * x / K0) / 2 * x],
|
|
615
|
+
[-A11 * (qn + pn) * x**4 / (24 * K0)],
|
|
616
|
+
[-A11 * (qn + pn) * x**3 / (6 * K0)],
|
|
617
|
+
[
|
|
618
|
+
A11 * (qn + pn) * x**3 / (6 * K0)
|
|
619
|
+
+ ((zs - B11 / A11) * qt - h * pt / 2 - (qn + pn) * x) / kA55
|
|
620
|
+
],
|
|
621
|
+
[(qn + pn) * (A11 * x**2 / (2 * K0) - 1 / kA55)],
|
|
622
|
+
]
|
|
623
|
+
)
|
|
584
624
|
|
|
585
625
|
return zp
|
|
586
626
|
|
|
@@ -608,9 +648,10 @@ class Eigensystem:
|
|
|
608
648
|
Solution vector (6xN) at position x.
|
|
609
649
|
"""
|
|
610
650
|
if isinstance(x, (list, tuple, np.ndarray)):
|
|
611
|
-
z = np.concatenate(
|
|
612
|
-
np.dot(self.zh(xi, l, bed), C)
|
|
613
|
-
|
|
651
|
+
z = np.concatenate(
|
|
652
|
+
[np.dot(self.zh(xi, l, bed), C) + self.zp(xi, phi, bed) for xi in x],
|
|
653
|
+
axis=1,
|
|
654
|
+
)
|
|
614
655
|
else:
|
|
615
656
|
z = np.dot(self.zh(x, l, bed), C) + self.zp(x, phi, bed)
|
|
616
657
|
|
weac/inverse.py
CHANGED
|
@@ -2,15 +2,13 @@
|
|
|
2
2
|
# pylint: disable=invalid-name
|
|
3
3
|
|
|
4
4
|
# Project imports
|
|
5
|
-
from weac.mixins import FieldQuantitiesMixin
|
|
6
|
-
from weac.mixins import SolutionMixin
|
|
7
|
-
from weac.mixins import AnalysisMixin
|
|
8
|
-
from weac.mixins import OutputMixin
|
|
9
5
|
from weac.eigensystem import Eigensystem
|
|
6
|
+
from weac.mixins import AnalysisMixin, FieldQuantitiesMixin, OutputMixin, SolutionMixin
|
|
10
7
|
|
|
11
8
|
|
|
12
|
-
class Inverse(
|
|
13
|
-
|
|
9
|
+
class Inverse(
|
|
10
|
+
FieldQuantitiesMixin, SolutionMixin, AnalysisMixin, OutputMixin, Eigensystem
|
|
11
|
+
):
|
|
14
12
|
"""
|
|
15
13
|
Fit the elastic properties of the layers of a snowpack.
|
|
16
14
|
|
|
@@ -25,8 +23,7 @@ class Inverse(FieldQuantitiesMixin, SolutionMixin, AnalysisMixin,
|
|
|
25
23
|
analysis from AnalysisMixin().
|
|
26
24
|
"""
|
|
27
25
|
|
|
28
|
-
def __init__(
|
|
29
|
-
self, system='pst-', layers=None, parameters=(6.0, 4.6, 0.25)):
|
|
26
|
+
def __init__(self, system="pst-", layers=None, parameters=(6.0, 4.6, 0.25)):
|
|
30
27
|
"""
|
|
31
28
|
Initialize model with user input.
|
|
32
29
|
|
weac/layered.py
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
"""Class for the elastic analysis of layered snow slabs."""
|
|
2
2
|
|
|
3
3
|
# Project imports
|
|
4
|
-
|
|
5
|
-
from weac.mixins import SlabContactMixin
|
|
6
|
-
from weac.mixins import SolutionMixin
|
|
7
|
-
from weac.mixins import AnalysisMixin
|
|
8
|
-
from weac.mixins import OutputMixin
|
|
4
|
+
|
|
9
5
|
from weac.eigensystem import Eigensystem
|
|
6
|
+
from weac.mixins import (
|
|
7
|
+
AnalysisMixin,
|
|
8
|
+
FieldQuantitiesMixin,
|
|
9
|
+
OutputMixin,
|
|
10
|
+
SlabContactMixin,
|
|
11
|
+
SolutionMixin,
|
|
12
|
+
)
|
|
10
13
|
|
|
11
14
|
|
|
12
|
-
class Layered(
|
|
13
|
-
|
|
15
|
+
class Layered(
|
|
16
|
+
FieldQuantitiesMixin,
|
|
17
|
+
SlabContactMixin,
|
|
18
|
+
SolutionMixin,
|
|
19
|
+
AnalysisMixin,
|
|
20
|
+
OutputMixin,
|
|
21
|
+
Eigensystem,
|
|
22
|
+
):
|
|
14
23
|
"""
|
|
15
24
|
Layered beam on elastic foundation model application interface.
|
|
16
25
|
|
|
@@ -21,7 +30,7 @@ class Layered(FieldQuantitiesMixin, SlabContactMixin, SolutionMixin,
|
|
|
21
30
|
analysis from AnalysisMixin().
|
|
22
31
|
"""
|
|
23
32
|
|
|
24
|
-
def __init__(self, system=
|
|
33
|
+
def __init__(self, system="pst-", layers=None, touchdown=False):
|
|
25
34
|
"""
|
|
26
35
|
Initialize model with user input.
|
|
27
36
|
|
|
@@ -44,6 +53,12 @@ class Layered(FieldQuantitiesMixin, SlabContactMixin, SolutionMixin,
|
|
|
44
53
|
super().__init__(system=system, touchdown=touchdown)
|
|
45
54
|
|
|
46
55
|
# Set material properties and set up model
|
|
47
|
-
self.set_beam_properties(
|
|
56
|
+
self.set_beam_properties(
|
|
57
|
+
layers
|
|
58
|
+
if layers
|
|
59
|
+
else [
|
|
60
|
+
[240, 200],
|
|
61
|
+
]
|
|
62
|
+
)
|
|
48
63
|
self.set_foundation_properties()
|
|
49
64
|
self.calc_fundamental_system()
|
weac/mixins.py
CHANGED
|
@@ -526,9 +526,12 @@ class SlabContactMixin:
|
|
|
526
526
|
Collapse-factor. Ratio of the crack height to the
|
|
527
527
|
uncollapsed weak-layer height.
|
|
528
528
|
"""
|
|
529
|
+
# mark argument as intentionally unused (API compatibility)
|
|
530
|
+
_ = cf
|
|
529
531
|
# subtract displacement under constact load from collapsed wl height
|
|
530
532
|
qn = self.calc_qn()
|
|
531
|
-
|
|
533
|
+
collapse_height = 4.70 * (1 - np.exp(-self.t / 7.78))
|
|
534
|
+
self.tc = collapse_height - qn / self.kn
|
|
532
535
|
|
|
533
536
|
def set_phi(self, phi):
|
|
534
537
|
"""
|
|
@@ -776,8 +779,8 @@ class SlabContactMixin:
|
|
|
776
779
|
"""Set class attributes for touchdown consideration"""
|
|
777
780
|
self.set_columnlength(L)
|
|
778
781
|
self.set_cracklength(a)
|
|
779
|
-
self.set_tc(cf)
|
|
780
782
|
self.set_phi(phi)
|
|
783
|
+
self.set_tc(cf)
|
|
781
784
|
self.set_stiffness_ratio(ratio)
|
|
782
785
|
|
|
783
786
|
def calc_touchdown_mode(self):
|
|
@@ -883,7 +886,7 @@ class SolutionMixin:
|
|
|
883
886
|
bc = np.array([self.N(z), self.M(z), self.V(z)])
|
|
884
887
|
else:
|
|
885
888
|
raise ValueError(
|
|
886
|
-
"Boundary conditions not defined for
|
|
889
|
+
f"Boundary conditions not defined for system of type {self.system}."
|
|
887
890
|
)
|
|
888
891
|
|
|
889
892
|
return bc
|
|
@@ -1441,9 +1444,7 @@ class AnalysisMixin:
|
|
|
1441
1444
|
# Solution at crack tip
|
|
1442
1445
|
z = self.z(li[idx], C[:, [idx]], li[idx], phi, bed=ki[idx])
|
|
1443
1446
|
# Mode I and II differential energy release rates
|
|
1444
|
-
Gdif[1:, j] = np.concatenate(
|
|
1445
|
-
(self.Gi(z, unit=unit), self.Gii(z, unit=unit))
|
|
1446
|
-
)
|
|
1447
|
+
Gdif[1:, j] = np.concatenate((self.Gi(z, unit=unit), self.Gii(z, unit=unit)))
|
|
1447
1448
|
|
|
1448
1449
|
# Sum mode I and II contributions
|
|
1449
1450
|
Gdif[0, :] = Gdif[1, :] + Gdif[2, :]
|
|
@@ -1481,10 +1482,7 @@ class AnalysisMixin:
|
|
|
1481
1482
|
nlayer = np.ceil((z[1:] - z[:-1]) / dz).astype(np.int32) + 1
|
|
1482
1483
|
# Calculate grid points as list of z-coordinates (mm)
|
|
1483
1484
|
zi = np.hstack(
|
|
1484
|
-
[
|
|
1485
|
-
np.linspace(z[i], z[i + 1], n, endpoint=True)
|
|
1486
|
-
for i, n in enumerate(nlayer)
|
|
1487
|
-
]
|
|
1485
|
+
[np.linspace(z[i], z[i + 1], n, endpoint=True) for i, n in enumerate(nlayer)]
|
|
1488
1486
|
)
|
|
1489
1487
|
# Get lists of corresponding elastic properties (E, nu, rho)
|
|
1490
1488
|
si = np.repeat(self.slab[:, [2, 4, 0]], nlayer, axis=0)
|