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 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__ = '2.6.1'
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='pst-', touchdown=False):
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 # 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'
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 # 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
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 # 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
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 # 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
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 # 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
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
- self,
155
- t: float = 30.0,
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 # Weak-layer thickness (mm)
175
+ self.t = t # Weak-layer thickness (mm)
179
176
 
180
177
  # Material properties
181
178
  self.weak = {
182
- 'nu': nu, # Poisson's ratio (-)
183
- 'E': E # Young's modulus (MPa)
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]) # Global poisson's ratio
224
- G = E/(2*(1 + nu)) # Shear modulus
225
- self.k = 5/6 # Shear correction factor
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['E']/(2*(1 + self.weak['nu'])) # Shear modulus
261
- E = self.weak['E']/(1 - self.weak['nu']**2) # Young's modulus
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 # Normal stiffness
265
- self.kt = G/self.t # Shear stiffness
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 = (2*self.D11*kt*self.t
326
- - self.B11*kt*self.t*(self.h + self.t)
327
- + 4*self.B11*self.kA55)/(4*self.K0)
328
- K25 = (-2*self.D11*self.h*kt
329
- + self.B11*self.h*kt*(self.h + self.t)
330
- + 4*self.B11*self.kA55)/(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 = (-2*self.B11*kt*self.t
334
- + self.A11*kt*self.t*(self.h+self.t)
335
- - 4*self.A11*self.kA55)/(4*self.K0)
336
- K65 = (2*self.B11*self.h*kt
337
- - self.A11*self.h*kt*(self.h+self.t)
338
- - 4*self.A11*self.kA55)/(4*self.K0)
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 = [[0, 1, 0, 0, 0, 0],
342
- [K21, 0, 0, K24, K25, 0],
343
- [0, 0, 0, 1, 0, 0],
344
- [0, 0, K43, 0, 0, -1],
345
- [0, 0, 0, 0, 0, 1],
346
- [K61, 0, 0, K64, K65, 0]]
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
- [0],
372
- [(self.B11*(self.h*pt - 2*qt*self.zs)
373
- + 2*self.D11*(qt + pt))/(2*self.K0)],
374
- [0],
375
- [-(qn + pn)/self.kA55],
376
- [0],
377
- [-(self.A11*(self.h*pt - 2*qt*self.zs)
378
- + 2*self.B11*(qt + pt))/(2*self.K0)]
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 # positive complex conjugates
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) # Convert inclination to rad
422
- rho = self.slab[:, 0]*1e-12 # Convert density to t/mm^3
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]) # Line load (N/mm)
442
+ q = sum(rho * self.g * self.slab[:, 1]) # Line load (N/mm)
425
443
  # Split into components
426
- qn = q*np.cos(phi) # Normal direction
427
- qt = -q*np.sin(phi) # Tangential direction
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) # Convert inclination to rad
466
+ phi = np.deg2rad(phi) # Convert inclination to rad
449
467
  # Split into components
450
- pn = self.p*np.cos(phi) # Normal direction
451
- pt = -self.p*np.sin(phi) # Tangential direction
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) # Convert inclination to rad
474
- F = 1e-3*np.array(m)*self.g/self.lski # Total skier load (N)
475
- Fn = F*np.cos(phi) # Normal skier load (N)
476
- Ft = -F*np.sin(phi) # Tangential skier load (N)
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
- # Real
502
- self.evR*np.exp(self.ewR*(x + l*self.sR)),
503
- # Complex
504
- np.exp(self.ewC.real*(x + l*self.sC))*(
505
- self.evC.real*np.cos(self.ewC.imag*x)
506
- - self.evC.imag*np.sin(self.ewC.imag*x)),
507
- # Complex
508
- np.exp(self.ewC.real*(x + l*self.sC))*(
509
- self.evC.imag*np.cos(self.ewC.imag*x)
510
- + self.evC.real*np.sin(self.ewC.imag*x))], axis=1)
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
- [[0, 0, 0, H14, 1, x],
519
- [0, 0, 0, H24, 0, 1],
520
- [1, x, x**2, x**3, 0, 0],
521
- [0, 1, 2*x, 3*x**2, 0, 0],
522
- [0, -1, -2*x, H54, 0, 0],
523
- [0, 0, -2, -6*x, 0, 0]])
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
- [(qt + pt)/kt + h*qt*(h + t - 2*zs)/(4*kA55)
569
- + h*pt*(2*h + t)/(4*kA55)],
570
- [0],
571
- [(qn + pn)/kn],
572
- [0],
573
- [-(qt*(h + t - 2*zs) + pt*(2*h + t))/(2*kA55)],
574
- [0]])
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
- [(-3*(qt + pt)/A11 - B11*(qn + pn)*x/K0)/6*x**2],
578
- [(-2*(qt + pt)/A11 - B11*(qn + pn)*x/K0)/2*x],
579
- [-A11*(qn + pn)*x**4/(24*K0)],
580
- [-A11*(qn + pn)*x**3/(6*K0)],
581
- [A11*(qn + pn)*x**3/(6*K0)
582
- + ((zs - B11/A11)*qt - h*pt/2 - (qn + pn)*x)/kA55],
583
- [(qn + pn)*(A11*x**2/(2*K0) - 1/kA55)]])
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
- + self.zp(xi, phi, bed) for xi in x], axis=1)
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(FieldQuantitiesMixin, SolutionMixin, AnalysisMixin,
13
- OutputMixin, Eigensystem):
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
- from weac.mixins import FieldQuantitiesMixin
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(FieldQuantitiesMixin, SlabContactMixin, SolutionMixin,
13
- AnalysisMixin, OutputMixin, Eigensystem):
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='pst-', layers=None, touchdown=False):
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(layers if layers else [[240, 200], ])
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
- self.tc = cf * self.t - qn / self.kn
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" f"system of type {self.system}."
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)