weac 3.0.2__py3-none-any.whl → 3.1.1__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 +1 -1
- weac/analysis/__init__.py +2 -2
- weac/analysis/analyzer.py +60 -26
- weac/analysis/criteria_evaluator.py +112 -15
- weac/analysis/plotter.py +391 -26
- weac/components/layer.py +7 -0
- weac/core/field_quantities.py +27 -23
- weac/core/unknown_constants_solver.py +13 -13
- weac/utils/geldsetzer.py +10 -0
- weac/utils/snow_types.py +5 -0
- {weac-3.0.2.dist-info → weac-3.1.1.dist-info}/METADATA +2 -2
- {weac-3.0.2.dist-info → weac-3.1.1.dist-info}/RECORD +15 -15
- {weac-3.0.2.dist-info → weac-3.1.1.dist-info}/WHEEL +0 -0
- {weac-3.0.2.dist-info → weac-3.1.1.dist-info}/licenses/LICENSE +0 -0
- {weac-3.0.2.dist-info → weac-3.1.1.dist-info}/top_level.txt +0 -0
weac/__init__.py
CHANGED
weac/analysis/__init__.py
CHANGED
|
@@ -8,7 +8,7 @@ from .criteria_evaluator import (
|
|
|
8
8
|
CoupledCriterionResult,
|
|
9
9
|
CriteriaEvaluator,
|
|
10
10
|
FindMinimumForceResult,
|
|
11
|
-
|
|
11
|
+
SteadyStateResult,
|
|
12
12
|
)
|
|
13
13
|
from .plotter import Plotter
|
|
14
14
|
|
|
@@ -18,6 +18,6 @@ __all__ = [
|
|
|
18
18
|
"CoupledCriterionHistory",
|
|
19
19
|
"CoupledCriterionResult",
|
|
20
20
|
"FindMinimumForceResult",
|
|
21
|
-
"
|
|
21
|
+
"SteadyStateResult",
|
|
22
22
|
"Plotter",
|
|
23
23
|
]
|
weac/analysis/analyzer.py
CHANGED
|
@@ -214,7 +214,7 @@ class Analyzer:
|
|
|
214
214
|
], # Convert to t/mm^3
|
|
215
215
|
"tensile_strength": [
|
|
216
216
|
layer.tensile_strength for layer in self.sm.slab.layers
|
|
217
|
-
],
|
|
217
|
+
], # in kPa
|
|
218
218
|
}
|
|
219
219
|
|
|
220
220
|
# Repeat properties for each grid point in the layer
|
|
@@ -225,7 +225,7 @@ class Analyzer:
|
|
|
225
225
|
return si
|
|
226
226
|
|
|
227
227
|
@track_analyzer_call
|
|
228
|
-
def Sxx(self, Z, phi, dz=2, unit="kPa"):
|
|
228
|
+
def Sxx(self, Z, phi, dz=2, unit="kPa", normalize: bool = False):
|
|
229
229
|
"""
|
|
230
230
|
Compute axial normal stress in slab layers.
|
|
231
231
|
|
|
@@ -239,6 +239,10 @@ class Analyzer:
|
|
|
239
239
|
Element size along z-axis (mm). Default is 2 mm.
|
|
240
240
|
unit : {'kPa', 'MPa'}, optional
|
|
241
241
|
Desired output unit. Default is 'kPa'.
|
|
242
|
+
normalize : bool, optional
|
|
243
|
+
Toggle normalization. If True, normalize stress values to the tensile strength of each layer (dimensionless).
|
|
244
|
+
When normalized, the `unit` parameter is ignored and values are returned as ratios.
|
|
245
|
+
Default is False.
|
|
242
246
|
|
|
243
247
|
Returns
|
|
244
248
|
-------
|
|
@@ -258,30 +262,34 @@ class Analyzer:
|
|
|
258
262
|
m = Z.shape[1]
|
|
259
263
|
|
|
260
264
|
# Initialize axial normal stress Sxx
|
|
261
|
-
|
|
265
|
+
Sxx_MPa = np.zeros(shape=[n, m])
|
|
262
266
|
|
|
263
267
|
# Compute axial normal stress Sxx at grid points in MPa
|
|
264
268
|
for i, z in enumerate(zi):
|
|
265
|
-
|
|
269
|
+
E_MPa = zmesh["E"][i]
|
|
266
270
|
nu = zmesh["nu"][i]
|
|
267
|
-
|
|
271
|
+
Sxx_MPa[i, :] = E_MPa / (1 - nu**2) * self.sm.fq.du_dx(Z, z)
|
|
268
272
|
|
|
269
273
|
# Calculate weight load at grid points and superimpose on stress field
|
|
270
274
|
qt = -rho * G_MM_S2 * np.sin(np.deg2rad(phi))
|
|
271
|
-
|
|
272
|
-
# for i, qi in enumerate(qt[:-1]):
|
|
273
|
-
# Sxx[i, :] += qi * (zi[i + 1] - zi[i])
|
|
274
|
-
# Sxx[-1, :] += qt[-1] * (zi[-1] - zi[-2])
|
|
275
|
-
# New Implementation: Changed for numerical stability
|
|
275
|
+
|
|
276
276
|
dz = np.diff(zi)
|
|
277
|
-
|
|
278
|
-
|
|
277
|
+
Sxx_MPa[:-1, :] += qt[:-1, np.newaxis] * dz[:, np.newaxis]
|
|
278
|
+
Sxx_MPa[-1, :] += qt[-1] * dz[-1]
|
|
279
|
+
|
|
280
|
+
# Normalize tensile stresses to tensile strength
|
|
281
|
+
if normalize:
|
|
282
|
+
tensile_strength_kPa = zmesh["tensile_strength"]
|
|
283
|
+
tensile_strength_MPa = tensile_strength_kPa / 1e3
|
|
284
|
+
# Normalize axial normal stress to layers' tensile strength
|
|
285
|
+
normalized_Sxx = Sxx_MPa / tensile_strength_MPa[:, None]
|
|
286
|
+
return normalized_Sxx
|
|
279
287
|
|
|
280
288
|
# Return axial normal stress in specified unit
|
|
281
|
-
return convert[unit] *
|
|
289
|
+
return convert[unit] * Sxx_MPa
|
|
282
290
|
|
|
283
291
|
@track_analyzer_call
|
|
284
|
-
def Txz(self, Z, phi, dz=2, unit="kPa"):
|
|
292
|
+
def Txz(self, Z, phi, dz=2, unit="kPa", normalize: bool = False):
|
|
285
293
|
"""
|
|
286
294
|
Compute shear stress in slab layers.
|
|
287
295
|
|
|
@@ -295,6 +303,9 @@ class Analyzer:
|
|
|
295
303
|
Element size along z-axis (mm). Default is 2 mm.
|
|
296
304
|
unit : {'kPa', 'MPa'}, optional
|
|
297
305
|
Desired output unit. Default is 'kPa'.
|
|
306
|
+
normalize : bool, optional
|
|
307
|
+
Toggle normalization. If True, normalize shear stress values to the tensile strength of each layer (dimensionless).
|
|
308
|
+
When normalized, the `unit` parameter is ignored and values are returned as ratios. Default is False.
|
|
298
309
|
|
|
299
310
|
Returns
|
|
300
311
|
-------
|
|
@@ -332,14 +343,22 @@ class Analyzer:
|
|
|
332
343
|
|
|
333
344
|
# Integrate -dsxx_dx along z and add cumulative weight load
|
|
334
345
|
# to obtain shear stress Txz in MPa
|
|
335
|
-
|
|
336
|
-
|
|
346
|
+
Txz_MPa = cumulative_trapezoid(dsxx_dx, zi, axis=0, initial=0)
|
|
347
|
+
Txz_MPa += cumulative_trapezoid(qt, zi, initial=0)[:, None]
|
|
348
|
+
|
|
349
|
+
# Normalize shear stresses to tensile strength
|
|
350
|
+
if normalize:
|
|
351
|
+
tensile_strength_kPa = zmesh["tensile_strength"]
|
|
352
|
+
tensile_strength_MPa = tensile_strength_kPa / 1e3
|
|
353
|
+
# Normalize shear stress to layers' tensile strength
|
|
354
|
+
normalized_Txz = Txz_MPa / tensile_strength_MPa[:, None]
|
|
355
|
+
return normalized_Txz
|
|
337
356
|
|
|
338
357
|
# Return shear stress Txz in specified unit
|
|
339
|
-
return convert[unit] *
|
|
358
|
+
return convert[unit] * Txz_MPa
|
|
340
359
|
|
|
341
360
|
@track_analyzer_call
|
|
342
|
-
def Szz(self, Z, phi, dz=2, unit="kPa"):
|
|
361
|
+
def Szz(self, Z, phi, dz=2, unit="kPa", normalize: bool = False):
|
|
343
362
|
"""
|
|
344
363
|
Compute transverse normal stress in slab layers.
|
|
345
364
|
|
|
@@ -353,6 +372,10 @@ class Analyzer:
|
|
|
353
372
|
Element size along z-axis (mm). Default is 2 mm.
|
|
354
373
|
unit : {'kPa', 'MPa'}, optional
|
|
355
374
|
Desired output unit. Default is 'kPa'.
|
|
375
|
+
normalize : bool, optional
|
|
376
|
+
Toggle normalization. If True, normalize stress values to the tensile strength of each layer (dimensionless).
|
|
377
|
+
When normalized, the `unit` parameter is ignored and values are returned as ratios.
|
|
378
|
+
Default is False.
|
|
356
379
|
|
|
357
380
|
Returns
|
|
358
381
|
-------
|
|
@@ -366,7 +389,7 @@ class Analyzer:
|
|
|
366
389
|
# Get mesh along z-axis
|
|
367
390
|
zmesh = self.get_zmesh(dz=dz)
|
|
368
391
|
zi = zmesh["z"]
|
|
369
|
-
|
|
392
|
+
rho_t_mm3 = zmesh["rho"]
|
|
370
393
|
qs = self.sm.scenario.surface_load
|
|
371
394
|
# Get dimensions of stress field (n rows, m columns)
|
|
372
395
|
n = len(zi)
|
|
@@ -387,16 +410,24 @@ class Analyzer:
|
|
|
387
410
|
dsxx_dxdx[i, :] = E / (1 - nu**2) * (du0_dxdxdx + z * dpsi_dxdxdx)
|
|
388
411
|
|
|
389
412
|
# Calculate weight load at grid points
|
|
390
|
-
qn =
|
|
413
|
+
qn = -rho_t_mm3 * G_MM_S2 * np.cos(np.deg2rad(phi))
|
|
391
414
|
|
|
392
415
|
# Integrate dsxx_dxdx twice along z to obtain transverse
|
|
393
416
|
# normal stress Szz in MPa
|
|
394
417
|
integrand = cumulative_trapezoid(dsxx_dxdx, zi, axis=0, initial=0)
|
|
395
|
-
|
|
396
|
-
|
|
418
|
+
Szz_MPa = cumulative_trapezoid(integrand, zi, axis=0, initial=0)
|
|
419
|
+
Szz_MPa += cumulative_trapezoid(qn, zi, initial=0)[:, None]
|
|
420
|
+
|
|
421
|
+
# Normalize tensile stresses to tensile strength
|
|
422
|
+
if normalize:
|
|
423
|
+
tensile_strength_kPa = zmesh["tensile_strength"]
|
|
424
|
+
tensile_strength_MPa = tensile_strength_kPa / 1e3
|
|
425
|
+
# Normalize transverse normal stress to layers' tensile strength
|
|
426
|
+
normalized_Szz = Szz_MPa / tensile_strength_MPa[:, None]
|
|
427
|
+
return normalized_Szz
|
|
397
428
|
|
|
398
|
-
# Return
|
|
399
|
-
return convert[unit] *
|
|
429
|
+
# Return transverse normal stress Szz in specified unit
|
|
430
|
+
return convert[unit] * Szz_MPa
|
|
400
431
|
|
|
401
432
|
@track_analyzer_call
|
|
402
433
|
def principal_stress_slab(
|
|
@@ -438,6 +469,8 @@ class Analyzer:
|
|
|
438
469
|
'min', or if normalization of compressive principal stress
|
|
439
470
|
is requested.
|
|
440
471
|
"""
|
|
472
|
+
convert = {"kPa": 1e3, "MPa": 1}
|
|
473
|
+
|
|
441
474
|
# Raise error if specified component is not available
|
|
442
475
|
if val not in ["min", "max"]:
|
|
443
476
|
raise ValueError(f"Component {val} not defined.")
|
|
@@ -460,9 +493,10 @@ class Analyzer:
|
|
|
460
493
|
# Normalize tensile stresses to tensile strength
|
|
461
494
|
if normalize and val == "max":
|
|
462
495
|
zmesh = self.get_zmesh(dz=dz)
|
|
463
|
-
|
|
496
|
+
tensile_strength_kPa = zmesh["tensile_strength"]
|
|
497
|
+
tensile_strength_converted = tensile_strength_kPa / 1e3 * convert[unit]
|
|
464
498
|
# Normalize maximum principal stress to layers' tensile strength
|
|
465
|
-
normalized_Ps = Ps /
|
|
499
|
+
normalized_Ps = Ps / tensile_strength_converted[:, None]
|
|
466
500
|
return normalized_Ps
|
|
467
501
|
|
|
468
502
|
# Return absolute principal stresses
|
|
@@ -95,9 +95,42 @@ class CoupledCriterionResult:
|
|
|
95
95
|
|
|
96
96
|
|
|
97
97
|
@dataclass
|
|
98
|
-
class
|
|
98
|
+
class MaximalStressResult:
|
|
99
99
|
"""
|
|
100
|
-
Holds the results of the
|
|
100
|
+
Holds the results of the maximal stress evaluation.
|
|
101
|
+
|
|
102
|
+
Attributes:
|
|
103
|
+
-----------
|
|
104
|
+
principal_stress_kPa: np.ndarray
|
|
105
|
+
The principal stress in kPa.
|
|
106
|
+
Sxx_kPa: np.ndarray
|
|
107
|
+
The axial normal stress in kPa.
|
|
108
|
+
principal_stress_norm: np.ndarray
|
|
109
|
+
The normalized principal stress to the tensile strength of the layers.
|
|
110
|
+
Sxx_norm: np.ndarray
|
|
111
|
+
The normalized axial normal stress to the tensile strength of the layers.
|
|
112
|
+
max_principal_stress_norm: float
|
|
113
|
+
The normalized maximum principal stress to the tensile strength of the layers.
|
|
114
|
+
max_Sxx_norm: float
|
|
115
|
+
The normalized maximum axial normal stress to the tensile strength of the layers.
|
|
116
|
+
slab_tensile_criterion: float
|
|
117
|
+
The slab tensile criterion, i.e. the portion of the slab thickness that is prone
|
|
118
|
+
to fail under tensile stresses in the steady state (between 0 and 1).
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
principal_stress_kPa: np.ndarray
|
|
122
|
+
Sxx_kPa: np.ndarray
|
|
123
|
+
principal_stress_norm: np.ndarray
|
|
124
|
+
Sxx_norm: np.ndarray
|
|
125
|
+
max_principal_stress_norm: float
|
|
126
|
+
max_Sxx_norm: float
|
|
127
|
+
slab_tensile_criterion: float
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@dataclass
|
|
131
|
+
class SteadyStateResult:
|
|
132
|
+
"""
|
|
133
|
+
Holds the results of the Steady State evaluation.
|
|
101
134
|
|
|
102
135
|
Attributes:
|
|
103
136
|
-----------
|
|
@@ -107,15 +140,21 @@ class SSERRResult:
|
|
|
107
140
|
The message of the evaluation.
|
|
108
141
|
touchdown_distance : float
|
|
109
142
|
The touchdown distance.
|
|
110
|
-
|
|
111
|
-
The
|
|
112
|
-
touchdown distance from
|
|
143
|
+
energy_release_rate : float
|
|
144
|
+
The steady-state energy release rate calculated with the
|
|
145
|
+
touchdown distance from the differential energy release rate.
|
|
146
|
+
maximal_stress_result: MaximalStressResult
|
|
147
|
+
The maximal stresses in the system at the touchdown distance.
|
|
148
|
+
system: SystemModel
|
|
149
|
+
The modified system model used for the steady state evaluation.
|
|
113
150
|
"""
|
|
114
151
|
|
|
115
152
|
converged: bool
|
|
116
153
|
message: str
|
|
117
154
|
touchdown_distance: float
|
|
118
|
-
|
|
155
|
+
energy_release_rate: float
|
|
156
|
+
maximal_stress_result: MaximalStressResult
|
|
157
|
+
system: SystemModel
|
|
119
158
|
|
|
120
159
|
|
|
121
160
|
@dataclass
|
|
@@ -641,12 +680,12 @@ class CriteriaEvaluator:
|
|
|
641
680
|
_recursion_depth=_recursion_depth + 1,
|
|
642
681
|
)
|
|
643
682
|
|
|
644
|
-
def
|
|
683
|
+
def evaluate_SteadyState(
|
|
645
684
|
self,
|
|
646
685
|
system: SystemModel,
|
|
647
686
|
vertical: bool = False,
|
|
648
687
|
print_call_stats: bool = False,
|
|
649
|
-
) ->
|
|
688
|
+
) -> SteadyStateResult:
|
|
650
689
|
"""
|
|
651
690
|
Evaluates the Touchdown Distance in the Steady State and the Steady State
|
|
652
691
|
Energy Release Rate.
|
|
@@ -671,9 +710,9 @@ class CriteriaEvaluator:
|
|
|
671
710
|
UserWarning,
|
|
672
711
|
)
|
|
673
712
|
system_copy = copy.deepcopy(system)
|
|
674
|
-
system_copy.
|
|
713
|
+
system_copy.toggle_touchdown(True)
|
|
675
714
|
system_copy.update_scenario(scenario_config=ScenarioConfig(phi=0.0))
|
|
676
|
-
l_BC =
|
|
715
|
+
l_BC = system_copy.slab_touchdown.l_BC
|
|
677
716
|
|
|
678
717
|
segments = [
|
|
679
718
|
Segment(length=5e3, has_foundation=True, m=0.0),
|
|
@@ -684,16 +723,22 @@ class CriteriaEvaluator:
|
|
|
684
723
|
phi=0.0, # Slab Touchdown works only for flat slab
|
|
685
724
|
cut_length=2 * l_BC,
|
|
686
725
|
)
|
|
687
|
-
# system_copy.config.touchdown = True
|
|
688
726
|
system_copy.update_scenario(segments=segments, scenario_config=scenario_config)
|
|
689
727
|
touchdown_distance = system_copy.slab_touchdown.touchdown_distance
|
|
690
728
|
analyzer = Analyzer(system_copy, printing_enabled=print_call_stats)
|
|
691
|
-
|
|
692
|
-
|
|
729
|
+
energy_release_rate, _, _ = analyzer.differential_ERR(unit="J/m^2")
|
|
730
|
+
maximal_stress_result = self._calculate_maximal_stresses(
|
|
731
|
+
system_copy, print_call_stats=print_call_stats
|
|
732
|
+
)
|
|
733
|
+
if print_call_stats:
|
|
734
|
+
analyzer.print_call_stats(message="evaluate_SteadyState Call Statistics")
|
|
735
|
+
return SteadyStateResult(
|
|
693
736
|
converged=True,
|
|
694
|
-
message="
|
|
737
|
+
message="Steady State evaluation successful.",
|
|
695
738
|
touchdown_distance=touchdown_distance,
|
|
696
|
-
|
|
739
|
+
energy_release_rate=energy_release_rate,
|
|
740
|
+
maximal_stress_result=maximal_stress_result,
|
|
741
|
+
system=system_copy,
|
|
697
742
|
)
|
|
698
743
|
|
|
699
744
|
def find_minimum_force(
|
|
@@ -1170,3 +1215,55 @@ class CriteriaEvaluator:
|
|
|
1170
1215
|
|
|
1171
1216
|
# Return the difference from the target
|
|
1172
1217
|
return g_delta_diff - target
|
|
1218
|
+
|
|
1219
|
+
def _calculate_maximal_stresses(
|
|
1220
|
+
self,
|
|
1221
|
+
system: SystemModel,
|
|
1222
|
+
print_call_stats: bool = False,
|
|
1223
|
+
) -> MaximalStressResult:
|
|
1224
|
+
"""
|
|
1225
|
+
Calculate the maximal stresses in the system.
|
|
1226
|
+
|
|
1227
|
+
Parameters
|
|
1228
|
+
----------
|
|
1229
|
+
system : SystemModel
|
|
1230
|
+
The system model to analyze.
|
|
1231
|
+
print_call_stats : bool, optional
|
|
1232
|
+
Whether to print analyzer call statistics. Default is False.
|
|
1233
|
+
|
|
1234
|
+
Returns
|
|
1235
|
+
-------
|
|
1236
|
+
MaximalStressResult
|
|
1237
|
+
Object containing both absolute (in kPa) and normalized stress fields,
|
|
1238
|
+
along with maximum normalized stress values.
|
|
1239
|
+
"""
|
|
1240
|
+
analyzer = Analyzer(system, printing_enabled=print_call_stats)
|
|
1241
|
+
_, Z, _ = analyzer.rasterize_solution(num=4000, mode="cracked")
|
|
1242
|
+
Sxx_kPa = analyzer.Sxx(Z=Z, phi=system.scenario.phi, dz=5, unit="kPa")
|
|
1243
|
+
principal_stress_kPa = analyzer.principal_stress_slab(
|
|
1244
|
+
Z=Z, phi=system.scenario.phi, dz=5, unit="kPa"
|
|
1245
|
+
)
|
|
1246
|
+
Sxx_norm = analyzer.Sxx(
|
|
1247
|
+
Z=Z, phi=system.scenario.phi, dz=5, unit="kPa", normalize=True
|
|
1248
|
+
)
|
|
1249
|
+
principal_stress_norm = analyzer.principal_stress_slab(
|
|
1250
|
+
Z=Z, phi=system.scenario.phi, dz=5, unit="kPa", normalize=True
|
|
1251
|
+
)
|
|
1252
|
+
max_principal_stress_norm = np.max(principal_stress_norm)
|
|
1253
|
+
max_Sxx_norm = np.max(Sxx_norm)
|
|
1254
|
+
# evaluate for each height level if the slab is prone to fail under tensile stresses
|
|
1255
|
+
height_level_prone_to_fail = np.max(Sxx_norm, axis=1)
|
|
1256
|
+
slab_tensile_criterion = np.mean(height_level_prone_to_fail)
|
|
1257
|
+
if print_call_stats:
|
|
1258
|
+
analyzer.print_call_stats(
|
|
1259
|
+
message="_calculate_maximal_stresses Call Statistics"
|
|
1260
|
+
)
|
|
1261
|
+
return MaximalStressResult(
|
|
1262
|
+
principal_stress_kPa=principal_stress_kPa,
|
|
1263
|
+
Sxx_kPa=Sxx_kPa,
|
|
1264
|
+
principal_stress_norm=principal_stress_norm,
|
|
1265
|
+
Sxx_norm=Sxx_norm,
|
|
1266
|
+
max_principal_stress_norm=max_principal_stress_norm,
|
|
1267
|
+
max_Sxx_norm=max_Sxx_norm,
|
|
1268
|
+
slab_tensile_criterion=slab_tensile_criterion,
|
|
1269
|
+
)
|
weac/analysis/plotter.py
CHANGED
|
@@ -885,48 +885,56 @@ class Plotter:
|
|
|
885
885
|
zmax = np.max(Zsl + scale * Wsl) + pad
|
|
886
886
|
zmin = np.min(Zsl) - pad
|
|
887
887
|
|
|
888
|
-
#
|
|
889
|
-
|
|
888
|
+
# Filter out NaN values from weak layer coordinates
|
|
889
|
+
nanmask = np.isfinite(xwl)
|
|
890
|
+
xwl_finite = xwl[nanmask]
|
|
890
891
|
|
|
891
|
-
#
|
|
892
|
-
|
|
893
|
-
|
|
892
|
+
# Compute weak-layer grid coordinates (cm) - only for finite xwl
|
|
893
|
+
Xwl, Zwl = np.meshgrid(1e-1 * xwl_finite, [1e-1 * (zi[-1] + H / 2), zmax])
|
|
894
|
+
|
|
895
|
+
# Assemble weak-layer displacement field (top and bottom) - only for finite xwl
|
|
896
|
+
Uwl = np.vstack([Usl[-1, nanmask], np.zeros(xwl_finite.shape[0])])
|
|
897
|
+
Wwl = np.vstack([Wsl[-1, nanmask], np.zeros(xwl_finite.shape[0])])
|
|
894
898
|
|
|
895
899
|
# Compute stress or displacement fields
|
|
896
900
|
match field:
|
|
897
901
|
# Horizontal displacements (um)
|
|
898
902
|
case "u":
|
|
899
903
|
slab = 1e4 * Usl
|
|
900
|
-
weak = 1e4 * Usl[-1,
|
|
904
|
+
weak = 1e4 * Usl[-1, nanmask]
|
|
901
905
|
label = r"$u$ ($\mu$m)"
|
|
902
906
|
# Vertical deflection (um)
|
|
903
907
|
case "w":
|
|
904
908
|
slab = 1e4 * Wsl
|
|
905
|
-
weak = 1e4 * Wsl[-1,
|
|
909
|
+
weak = 1e4 * Wsl[-1, nanmask]
|
|
906
910
|
label = r"$w$ ($\mu$m)"
|
|
907
|
-
# Axial normal stresses (kPa)
|
|
908
911
|
case "Sxx":
|
|
909
|
-
slab = analyzer.Sxx(z, phi, dz=dz, unit="kPa")
|
|
910
|
-
weak = np.zeros(
|
|
911
|
-
label =
|
|
912
|
+
slab = analyzer.Sxx(z, phi, dz=dz, unit="kPa", normalize=normalize)
|
|
913
|
+
weak = np.zeros(xwl_finite.shape[0])
|
|
914
|
+
label = (
|
|
915
|
+
r"$\sigma_{xx}/\sigma_+$" if normalize else r"$\sigma_{xx}$ (kPa)"
|
|
916
|
+
)
|
|
912
917
|
# Shear stresses (kPa)
|
|
913
918
|
case "Txz":
|
|
914
|
-
slab = analyzer.Txz(z, phi, dz=dz, unit="kPa")
|
|
915
|
-
weak = Tauwl
|
|
916
|
-
label = r"$\tau_{xz}$ (kPa)"
|
|
919
|
+
slab = analyzer.Txz(z, phi, dz=dz, unit="kPa", normalize=normalize)
|
|
920
|
+
weak = Tauwl[nanmask]
|
|
921
|
+
label = r"$\tau_{xz}/\sigma_+$" if normalize else r"$\tau_{xz}$ (kPa)"
|
|
917
922
|
# Transverse normal stresses (kPa)
|
|
918
923
|
case "Szz":
|
|
919
|
-
slab = analyzer.Szz(z, phi, dz=dz, unit="kPa")
|
|
920
|
-
weak = Sigmawl
|
|
921
|
-
label =
|
|
924
|
+
slab = analyzer.Szz(z, phi, dz=dz, unit="kPa", normalize=normalize)
|
|
925
|
+
weak = Sigmawl[nanmask]
|
|
926
|
+
label = (
|
|
927
|
+
r"$\sigma_{zz}/\sigma_+$" if normalize else r"$\sigma_{zz}$ (kPa)"
|
|
928
|
+
)
|
|
922
929
|
# Principal stresses
|
|
923
930
|
case "principal":
|
|
924
931
|
slab = analyzer.principal_stress_slab(
|
|
925
932
|
z, phi, dz=dz, val="max", unit="kPa", normalize=normalize
|
|
926
933
|
)
|
|
927
|
-
|
|
934
|
+
weak_full = analyzer.principal_stress_weaklayer(
|
|
928
935
|
z, val="min", unit="kPa", normalize=normalize
|
|
929
936
|
)
|
|
937
|
+
weak = weak_full[nanmask]
|
|
930
938
|
if normalize:
|
|
931
939
|
label = (
|
|
932
940
|
r"$\sigma_\mathrm{I}/\sigma_+$ (slab), "
|
|
@@ -937,11 +945,6 @@ class Plotter:
|
|
|
937
945
|
r"$\sigma_\mathrm{I}$ (kPa, slab), "
|
|
938
946
|
r"$\sigma_\mathrm{I\!I\!I}$ (kPa, weak layer)"
|
|
939
947
|
)
|
|
940
|
-
case _:
|
|
941
|
-
raise ValueError(
|
|
942
|
-
f"Invalid input '{field}' for field. Valid options are "
|
|
943
|
-
"'u', 'w', 'Sxx', 'Txz', 'Szz', or 'principal'"
|
|
944
|
-
)
|
|
945
948
|
|
|
946
949
|
# Complement label
|
|
947
950
|
label += r" $\longrightarrow$"
|
|
@@ -968,10 +971,9 @@ class Plotter:
|
|
|
968
971
|
|
|
969
972
|
# Plot deformed weak-layer _outline
|
|
970
973
|
if system_type in ["-pst", "pst-", "-vpst", "vpst-"]:
|
|
971
|
-
nanmask = np.isfinite(xwl)
|
|
972
974
|
ax.plot(
|
|
973
|
-
_outline(Xwl
|
|
974
|
-
_outline(Zwl
|
|
975
|
+
_outline(Xwl + scale * Uwl),
|
|
976
|
+
_outline(Zwl + scale * Wwl),
|
|
975
977
|
"k",
|
|
976
978
|
linewidth=1,
|
|
977
979
|
)
|
|
@@ -1033,6 +1035,369 @@ class Plotter:
|
|
|
1033
1035
|
|
|
1034
1036
|
return fig
|
|
1035
1037
|
|
|
1038
|
+
def plot_visualize_deformation(
|
|
1039
|
+
self,
|
|
1040
|
+
xsl: np.ndarray,
|
|
1041
|
+
xwl: np.ndarray,
|
|
1042
|
+
z: np.ndarray,
|
|
1043
|
+
analyzer: Analyzer,
|
|
1044
|
+
window: float | None = None,
|
|
1045
|
+
weaklayer_proportion: float | None = None,
|
|
1046
|
+
dz: int = 2,
|
|
1047
|
+
levels: int = 300,
|
|
1048
|
+
field: Literal["w", "u", "principal", "Sxx", "Txz", "Szz"] = "w",
|
|
1049
|
+
normalize: bool = True,
|
|
1050
|
+
filename: str = "visualize_deformation",
|
|
1051
|
+
) -> Figure:
|
|
1052
|
+
"""
|
|
1053
|
+
Plot visualize deformation of the slab and weak layer.
|
|
1054
|
+
|
|
1055
|
+
Parameters
|
|
1056
|
+
----------
|
|
1057
|
+
xsl : np.ndarray
|
|
1058
|
+
Slab x-coordinates.
|
|
1059
|
+
xwl : np.ndarray
|
|
1060
|
+
Weak layer x-coordinates.
|
|
1061
|
+
z : np.ndarray
|
|
1062
|
+
Solution vector.
|
|
1063
|
+
analyzer : Analyzer
|
|
1064
|
+
Analyzer instance.
|
|
1065
|
+
window: float | None, optional
|
|
1066
|
+
Window size for the plot. Shows the right edge of the slab, where the slab is deformed. Default is None.
|
|
1067
|
+
weaklayer_proportion: float | None, optional
|
|
1068
|
+
Proportion of the plot to allocate to the weak layer. Default is None.
|
|
1069
|
+
dz : int, optional
|
|
1070
|
+
Element size along z-axis (mm). Default is 2 mm.
|
|
1071
|
+
levels : int, optional
|
|
1072
|
+
Number of levels for the colormap. Default is 300.
|
|
1073
|
+
field : str, optional
|
|
1074
|
+
Field to plot ('w', 'u', 'principal', 'Sxx', 'Txz', 'Szz'). Default is 'w'.
|
|
1075
|
+
normalize : bool, optional
|
|
1076
|
+
Toggle normalization. Default is True.
|
|
1077
|
+
filename : str, optional
|
|
1078
|
+
Filename for saving plot. Default is "visualize_deformation".
|
|
1079
|
+
|
|
1080
|
+
Returns
|
|
1081
|
+
-------
|
|
1082
|
+
matplotlib.figure.Figure
|
|
1083
|
+
The generated plot figure.
|
|
1084
|
+
"""
|
|
1085
|
+
fig = plt.figure(figsize=(10, 8))
|
|
1086
|
+
ax = fig.add_subplot(111)
|
|
1087
|
+
|
|
1088
|
+
zi = analyzer.get_zmesh(dz=dz)["z"]
|
|
1089
|
+
H = analyzer.sm.slab.H
|
|
1090
|
+
phi = analyzer.sm.scenario.phi
|
|
1091
|
+
system_type = analyzer.sm.scenario.system_type
|
|
1092
|
+
fq = analyzer.sm.fq
|
|
1093
|
+
sigma_comp = (
|
|
1094
|
+
analyzer.sm.weak_layer.sigma_comp
|
|
1095
|
+
) # Compressive strength of the weak layer [kPa]
|
|
1096
|
+
|
|
1097
|
+
# Compute slab displacements on grid (cm)
|
|
1098
|
+
Usl = np.vstack([fq.u(z, h0=h0, unit="cm") for h0 in zi])
|
|
1099
|
+
Wsl = np.vstack([fq.w(z, unit="cm") for _ in zi])
|
|
1100
|
+
Sigmawl = np.where(np.isfinite(xwl), fq.sig(z, unit="kPa"), np.nan)
|
|
1101
|
+
Tauwl = np.where(np.isfinite(xwl), fq.tau(z, unit="kPa"), np.nan)
|
|
1102
|
+
|
|
1103
|
+
# Put coordinate origin at horizontal center
|
|
1104
|
+
if system_type in ["skier", "skiers"]:
|
|
1105
|
+
xsl = xsl - max(xsl) / 2
|
|
1106
|
+
xwl = xwl - max(xwl) / 2
|
|
1107
|
+
|
|
1108
|
+
# Physical dimensions in cm
|
|
1109
|
+
H_cm = H * 1e-1 # Slab height in cm
|
|
1110
|
+
h_cm = analyzer.sm.weak_layer.h * 1e-1 # Weak layer height in cm
|
|
1111
|
+
crack_h_cm = analyzer.sm.scenario.crack_h * 1e-1 # Crack height in cm
|
|
1112
|
+
|
|
1113
|
+
# Compute slab grid coordinates with vertical origin at top surface (cm)
|
|
1114
|
+
Xsl, Zsl = np.meshgrid(1e-1 * (xsl), 1e-1 * (zi + H / 2))
|
|
1115
|
+
|
|
1116
|
+
# Calculate maximum displacement first (needed for proportion calculation)
|
|
1117
|
+
max_w_displacement = np.nanmax(np.abs(Wsl))
|
|
1118
|
+
|
|
1119
|
+
# Calculate dynamic proportions based on displacement
|
|
1120
|
+
# Weak layer percentage = weak_layer_height / max_displacement (as ratio)
|
|
1121
|
+
# But capped at 40% maximum
|
|
1122
|
+
if weaklayer_proportion is None:
|
|
1123
|
+
if max_w_displacement > 0:
|
|
1124
|
+
weaklayer_proportion = min(0.3, (h_cm / max_w_displacement) * 0.1)
|
|
1125
|
+
else:
|
|
1126
|
+
weaklayer_proportion = 0.3
|
|
1127
|
+
|
|
1128
|
+
# Slab takes the remaining space
|
|
1129
|
+
slab_proportion = 1.0 - weaklayer_proportion
|
|
1130
|
+
cracked_ratio = crack_h_cm / h_cm
|
|
1131
|
+
cracked_proportion = weaklayer_proportion * cracked_ratio
|
|
1132
|
+
|
|
1133
|
+
# Set up plot coordinate system
|
|
1134
|
+
# Plot height is normalized: slab (0 to slab_proportion), weak layer (slab_proportion to slab_proportion+weaklayer_proportion)
|
|
1135
|
+
total_height_plot = (
|
|
1136
|
+
slab_proportion + weaklayer_proportion
|
|
1137
|
+
) # Total height without displacement
|
|
1138
|
+
# Map physical dimensions to plot coordinates
|
|
1139
|
+
deformation_scale = weaklayer_proportion / h_cm
|
|
1140
|
+
|
|
1141
|
+
# Get x-axis limits spanning all provided x values (deformed and undeformed)
|
|
1142
|
+
xmax = np.max([np.max(Xsl), np.max(Xsl + deformation_scale * Usl)]) + 10.0
|
|
1143
|
+
xmin = np.min([np.min(Xsl), np.min(Xsl + deformation_scale * Usl)]) - 10.0
|
|
1144
|
+
|
|
1145
|
+
# Calculate zmax including maximum deformation
|
|
1146
|
+
zmax = total_height_plot
|
|
1147
|
+
|
|
1148
|
+
# Convert physical coordinates to plot coordinates for slab
|
|
1149
|
+
# Zsl is in cm, we need to map it to plot coordinates (0 to slab_proportion)
|
|
1150
|
+
Zsl_plot = (Zsl / H_cm) * slab_proportion
|
|
1151
|
+
|
|
1152
|
+
# Filter out NaN values from weak layer coordinates
|
|
1153
|
+
nanmask = np.isfinite(xwl)
|
|
1154
|
+
xwl_finite = xwl[nanmask]
|
|
1155
|
+
|
|
1156
|
+
# Compute weak-layer grid coordinates in plot units
|
|
1157
|
+
# Weak layer extends from bottom of slab (slab_proportion) to total height (1.0)
|
|
1158
|
+
Xwl, Zwl_plot = np.meshgrid(
|
|
1159
|
+
1e-1 * xwl_finite, [slab_proportion, total_height_plot]
|
|
1160
|
+
)
|
|
1161
|
+
|
|
1162
|
+
# Assemble weak-layer displacement field (top and bottom) - only for finite xwl
|
|
1163
|
+
Uwl = np.vstack([Usl[-1, nanmask], np.zeros(xwl_finite.shape[0])])
|
|
1164
|
+
Wwl = np.vstack([Wsl[-1, nanmask], np.zeros(xwl_finite.shape[0])])
|
|
1165
|
+
|
|
1166
|
+
# Convert slab displacements to plot coordinates
|
|
1167
|
+
# Scale factor for displacements:
|
|
1168
|
+
# So scaled displacement in plot units = scale * Wsl
|
|
1169
|
+
Wsl_plot = (
|
|
1170
|
+
deformation_scale * Wsl
|
|
1171
|
+
) # Already in plot units (proportion of total height)
|
|
1172
|
+
Usl_plot = deformation_scale * Usl # Horizontal displacements also scaled
|
|
1173
|
+
Wwl_plot = deformation_scale * Wwl # Weak layer displacements
|
|
1174
|
+
Uwl_plot = deformation_scale * Uwl # Weak layer horizontal displacements
|
|
1175
|
+
|
|
1176
|
+
# Compute stress or displacement fields
|
|
1177
|
+
match field:
|
|
1178
|
+
# Horizontal displacements (um)
|
|
1179
|
+
case "u":
|
|
1180
|
+
slab = 1e4 * Usl
|
|
1181
|
+
weak = 1e4 * Usl[-1, nanmask]
|
|
1182
|
+
label = r"$u$ ($\mu$m)"
|
|
1183
|
+
# Vertical deflection (um)
|
|
1184
|
+
case "w":
|
|
1185
|
+
slab = 1e4 * Wsl
|
|
1186
|
+
weak = 1e4 * Wsl[-1, nanmask]
|
|
1187
|
+
label = r"$w$ ($\mu$m)"
|
|
1188
|
+
# Axial normal stresses (kPa)
|
|
1189
|
+
case "Sxx":
|
|
1190
|
+
slab = analyzer.Sxx(z, phi, dz=dz, unit="kPa", normalize=normalize)
|
|
1191
|
+
weak = np.zeros(xwl_finite.shape[0])
|
|
1192
|
+
label = (
|
|
1193
|
+
r"$\sigma_{xx}/\sigma_+$" if normalize else r"$\sigma_{xx}$ (kPa)"
|
|
1194
|
+
)
|
|
1195
|
+
# Shear stresses (kPa)
|
|
1196
|
+
case "Txz":
|
|
1197
|
+
slab = analyzer.Txz(z, phi, dz=dz, unit="kPa", normalize=normalize)
|
|
1198
|
+
weak = Tauwl[nanmask]
|
|
1199
|
+
label = r"$\tau_{xz}/\sigma_+$" if normalize else r"$\tau_{xz}$ (kPa)"
|
|
1200
|
+
# Transverse normal stresses (kPa)
|
|
1201
|
+
case "Szz":
|
|
1202
|
+
slab = analyzer.Szz(z, phi, dz=dz, unit="kPa", normalize=normalize)
|
|
1203
|
+
weak = Sigmawl[nanmask]
|
|
1204
|
+
label = (
|
|
1205
|
+
r"$\sigma_{zz}/\sigma_+$" if normalize else r"$\sigma_{zz}$ (kPa)"
|
|
1206
|
+
)
|
|
1207
|
+
# Principal stresses
|
|
1208
|
+
case "principal":
|
|
1209
|
+
slab = analyzer.principal_stress_slab(
|
|
1210
|
+
z, phi, dz=dz, val="max", unit="kPa", normalize=normalize
|
|
1211
|
+
)
|
|
1212
|
+
weak_full = analyzer.principal_stress_weaklayer(
|
|
1213
|
+
z, sc=sigma_comp, val="min", unit="kPa", normalize=normalize
|
|
1214
|
+
)
|
|
1215
|
+
weak = weak_full[nanmask]
|
|
1216
|
+
if normalize:
|
|
1217
|
+
label = (
|
|
1218
|
+
r"$\sigma_\mathrm{I}/\sigma_+$ (slab), "
|
|
1219
|
+
r"$\sigma_\mathrm{I\!I\!I}/\sigma_-$ (weak layer)"
|
|
1220
|
+
)
|
|
1221
|
+
else:
|
|
1222
|
+
label = (
|
|
1223
|
+
r"$\sigma_\mathrm{I}$ (kPa, slab), "
|
|
1224
|
+
r"$\sigma_\mathrm{I\!I\!I}$ (kPa, weak layer)"
|
|
1225
|
+
)
|
|
1226
|
+
|
|
1227
|
+
# Complement label
|
|
1228
|
+
label += r" $\longrightarrow$"
|
|
1229
|
+
|
|
1230
|
+
# Assemble weak-layer output on grid
|
|
1231
|
+
weak = np.vstack([weak, weak])
|
|
1232
|
+
|
|
1233
|
+
# Normalize colormap
|
|
1234
|
+
absmax = np.nanmax(np.abs([slab.min(), slab.max(), weak.min(), weak.max()]))
|
|
1235
|
+
clim = np.round(absmax, _significant_digits(absmax))
|
|
1236
|
+
levels = np.linspace(-clim, clim, num=levels + 1, endpoint=True)
|
|
1237
|
+
|
|
1238
|
+
# Plot baseline
|
|
1239
|
+
ax.axhline(zmax, color="k", linewidth=1)
|
|
1240
|
+
|
|
1241
|
+
# Plot outlines of the undeformed and deformed slab (using plot coordinates)
|
|
1242
|
+
ax.plot(_outline(Xsl), _outline(Zsl_plot), "--", alpha=0.3, linewidth=1)
|
|
1243
|
+
ax.plot(
|
|
1244
|
+
_outline(Xsl + Usl_plot),
|
|
1245
|
+
_outline(Zsl_plot + Wsl_plot),
|
|
1246
|
+
"-",
|
|
1247
|
+
linewidth=1,
|
|
1248
|
+
color="k",
|
|
1249
|
+
)
|
|
1250
|
+
|
|
1251
|
+
# Plot cracked weak-layer outline (where there is no weak layer)
|
|
1252
|
+
xwl_cracked = xsl[~nanmask]
|
|
1253
|
+
Xwl_cracked, Zwl_cracked_plot = np.meshgrid(
|
|
1254
|
+
1e-1 * xwl_cracked,
|
|
1255
|
+
[slab_proportion + cracked_proportion, total_height_plot],
|
|
1256
|
+
)
|
|
1257
|
+
# No displacements for the cracked weak layer outline (undeformed)
|
|
1258
|
+
if xwl_cracked.shape[0] > 0:
|
|
1259
|
+
ax.plot(
|
|
1260
|
+
_outline(Xwl_cracked),
|
|
1261
|
+
_outline(Zwl_cracked_plot),
|
|
1262
|
+
"k-",
|
|
1263
|
+
alpha=0.3,
|
|
1264
|
+
linewidth=1,
|
|
1265
|
+
)
|
|
1266
|
+
|
|
1267
|
+
# Then plot the deformed weak-layer outline where it exists
|
|
1268
|
+
if system_type in ["-pst", "pst-", "-vpst", "vpst-"]:
|
|
1269
|
+
ax.plot(
|
|
1270
|
+
_outline(Xwl + Uwl_plot),
|
|
1271
|
+
_outline(Zwl_plot + Wwl_plot),
|
|
1272
|
+
"k",
|
|
1273
|
+
linewidth=1,
|
|
1274
|
+
)
|
|
1275
|
+
|
|
1276
|
+
cmap = plt.get_cmap("RdBu_r")
|
|
1277
|
+
cmap.set_over(_adjust_lightness(cmap(1.0), 0.9))
|
|
1278
|
+
cmap.set_under(_adjust_lightness(cmap(0.0), 0.9))
|
|
1279
|
+
|
|
1280
|
+
# Plot fields (using plot coordinates)
|
|
1281
|
+
ax.contourf(
|
|
1282
|
+
Xsl + Usl_plot,
|
|
1283
|
+
Zsl_plot + Wsl_plot,
|
|
1284
|
+
slab,
|
|
1285
|
+
levels=levels,
|
|
1286
|
+
cmap=cmap,
|
|
1287
|
+
extend="both",
|
|
1288
|
+
)
|
|
1289
|
+
ax.contourf(
|
|
1290
|
+
Xwl + Uwl_plot,
|
|
1291
|
+
Zwl_plot + Wwl_plot,
|
|
1292
|
+
weak,
|
|
1293
|
+
levels=levels,
|
|
1294
|
+
cmap=cmap,
|
|
1295
|
+
extend="both",
|
|
1296
|
+
)
|
|
1297
|
+
if xwl_cracked.shape[0] > 0:
|
|
1298
|
+
ax.contourf(
|
|
1299
|
+
Xwl_cracked,
|
|
1300
|
+
Zwl_cracked_plot,
|
|
1301
|
+
np.zeros((2, xwl_cracked.shape[0])),
|
|
1302
|
+
levels=levels,
|
|
1303
|
+
cmap=cmap,
|
|
1304
|
+
extend="both",
|
|
1305
|
+
)
|
|
1306
|
+
|
|
1307
|
+
# Plot setup
|
|
1308
|
+
# Set y-limits to match plot coordinate system (0 to total_height_plot = 1.0)
|
|
1309
|
+
plot_ymin = -0.1
|
|
1310
|
+
plot_ymax = (
|
|
1311
|
+
total_height_plot # Should be 1.0 (slab_proportion + weaklayer_proportion)
|
|
1312
|
+
)
|
|
1313
|
+
|
|
1314
|
+
# Set limits first, then aspect ratio to avoid matplotlib adjusting limits
|
|
1315
|
+
if window is None:
|
|
1316
|
+
ax.set_xlim([xmin, xmax])
|
|
1317
|
+
else:
|
|
1318
|
+
ax.set_xlim([xmax - window, xmax])
|
|
1319
|
+
ax.set_ylim([plot_ymin, plot_ymax])
|
|
1320
|
+
ax.invert_yaxis()
|
|
1321
|
+
ax.use_sticky_edges = False
|
|
1322
|
+
|
|
1323
|
+
# Hide the default y-axis on main axis (we'll use custom axes)
|
|
1324
|
+
ax.yaxis.set_visible(False)
|
|
1325
|
+
|
|
1326
|
+
# Set up dual y-axes
|
|
1327
|
+
# Right axis: slab height in cm (0 at top, H_cm at bottom of slab)
|
|
1328
|
+
ax_right = ax.twinx()
|
|
1329
|
+
slab_height_max = H_cm
|
|
1330
|
+
# Map plot coordinates to physical slab height values
|
|
1331
|
+
# Plot: 0 to slab_proportion (0.6) maps to physical: 0 to H_cm
|
|
1332
|
+
slab_height_ticks = np.linspace(0, slab_height_max, num=5)
|
|
1333
|
+
slab_height_positions_plot = (
|
|
1334
|
+
slab_height_ticks / slab_height_max
|
|
1335
|
+
) * slab_proportion
|
|
1336
|
+
ax_right.set_yticks(slab_height_positions_plot)
|
|
1337
|
+
ax_right.set_yticklabels([f"{tick:.1f}" for tick in slab_height_ticks])
|
|
1338
|
+
# Ensure right axis ticks and label are on the right side
|
|
1339
|
+
ax_right.yaxis.tick_right()
|
|
1340
|
+
ax_right.yaxis.set_label_position("right")
|
|
1341
|
+
ax_right.set_ylim([plot_ymin, plot_ymax])
|
|
1342
|
+
ax_right.invert_yaxis()
|
|
1343
|
+
ax_right.set_ylabel(
|
|
1344
|
+
r"slab depth [cm] $\longleftarrow$", rotation=90, labelpad=5, loc="top"
|
|
1345
|
+
)
|
|
1346
|
+
|
|
1347
|
+
# Left axis: weak layer height in mm (0 at bottom of slab, h at bottom of weak layer)
|
|
1348
|
+
ax_left = ax.twinx()
|
|
1349
|
+
weak_layer_h_mm = analyzer.sm.weak_layer.h
|
|
1350
|
+
# Map plot coordinates to physical weak layer height values
|
|
1351
|
+
# Plot: slab_proportion (0.6) to total_height_plot (1.0) maps to physical: 0 to h_mm
|
|
1352
|
+
weaklayer_height_ticks = np.linspace(0, weak_layer_h_mm, num=3)
|
|
1353
|
+
# Map from plot coordinates (slab_proportion to 1.0) to physical (0 to h_mm)
|
|
1354
|
+
weaklayer_height_positions_plot = (
|
|
1355
|
+
slab_proportion
|
|
1356
|
+
+ (weaklayer_height_ticks / weak_layer_h_mm) * weaklayer_proportion
|
|
1357
|
+
)
|
|
1358
|
+
ax_left.set_yticks(weaklayer_height_positions_plot)
|
|
1359
|
+
ax_left.set_yticklabels([f"{tick:.1f}" for tick in weaklayer_height_ticks])
|
|
1360
|
+
# Move left axis to the left side
|
|
1361
|
+
ax_left.yaxis.tick_left()
|
|
1362
|
+
ax_left.yaxis.set_label_position("left")
|
|
1363
|
+
ax_left.set_ylim([plot_ymin, plot_ymax])
|
|
1364
|
+
ax_left.invert_yaxis()
|
|
1365
|
+
ax_left.set_ylabel(
|
|
1366
|
+
r"weaklayer depth [mm] $\longleftarrow$",
|
|
1367
|
+
rotation=90,
|
|
1368
|
+
labelpad=5,
|
|
1369
|
+
loc="bottom",
|
|
1370
|
+
)
|
|
1371
|
+
|
|
1372
|
+
# Plot labels
|
|
1373
|
+
ax.set_xlabel(r"lateral position $x$ (cm) $\longrightarrow$")
|
|
1374
|
+
ax.set_title(
|
|
1375
|
+
f"{field}{' (normalized to tensile strength)' if normalize else ''}",
|
|
1376
|
+
size=10,
|
|
1377
|
+
)
|
|
1378
|
+
|
|
1379
|
+
# Show colorbar
|
|
1380
|
+
ticks = np.linspace(levels[0], levels[-1], num=11, endpoint=True)
|
|
1381
|
+
fig.colorbar(
|
|
1382
|
+
ax.contourf(
|
|
1383
|
+
Xsl + Usl_plot,
|
|
1384
|
+
Zsl_plot + Wsl_plot,
|
|
1385
|
+
slab,
|
|
1386
|
+
levels=levels,
|
|
1387
|
+
cmap=cmap,
|
|
1388
|
+
extend="both",
|
|
1389
|
+
),
|
|
1390
|
+
orientation="horizontal",
|
|
1391
|
+
ticks=ticks,
|
|
1392
|
+
label=label,
|
|
1393
|
+
aspect=35,
|
|
1394
|
+
)
|
|
1395
|
+
|
|
1396
|
+
# Save figure
|
|
1397
|
+
self._save_figure(filename, fig)
|
|
1398
|
+
|
|
1399
|
+
return fig
|
|
1400
|
+
|
|
1036
1401
|
def plot_stress_envelope(
|
|
1037
1402
|
self,
|
|
1038
1403
|
system_model: SystemModel,
|
weac/components/layer.py
CHANGED
|
@@ -94,6 +94,10 @@ def _sigrist_tensile_strength(rho, unit: Literal["kPa", "MPa"] = "kPa"):
|
|
|
94
94
|
return convert[unit] * 240 * (rho / RHO_ICE) ** 2.44
|
|
95
95
|
|
|
96
96
|
|
|
97
|
+
# TODO: Compressive Strength from Schöttner
|
|
98
|
+
# (11 +/- 7) * (rho/rho_0) ^ (5.4 +/- 0.5)
|
|
99
|
+
|
|
100
|
+
|
|
97
101
|
class Layer(BaseModel):
|
|
98
102
|
"""
|
|
99
103
|
Regular slab layer (no foundation springs).
|
|
@@ -225,6 +229,9 @@ class WeakLayer(BaseModel):
|
|
|
225
229
|
)
|
|
226
230
|
sigma_c: float = Field(default=6.16, gt=0, description="Tensile strength [kPa]")
|
|
227
231
|
tau_c: float = Field(default=5.09, gt=0, description="Shear strength [kPa]")
|
|
232
|
+
sigma_comp: float = Field(
|
|
233
|
+
default=2.6, gt=0, description="Compressive strength [kPa]"
|
|
234
|
+
)
|
|
228
235
|
E_method: Literal["bergfeld", "scapazzo", "gerling"] = Field(
|
|
229
236
|
default="bergfeld",
|
|
230
237
|
description="Method to calculate the Young's modulus",
|
weac/core/field_quantities.py
CHANGED
|
@@ -58,19 +58,23 @@ class FieldQuantities: # pylint: disable=too-many-instance-attributes, too-many
|
|
|
58
58
|
h0: float = 0,
|
|
59
59
|
unit: LengthUnit = "mm",
|
|
60
60
|
) -> float | np.ndarray:
|
|
61
|
-
"""
|
|
61
|
+
"""
|
|
62
|
+
Horizontal displacement `u = u₀ + h₀ ψ` at depth `h₀` (mm).
|
|
63
|
+
"""
|
|
62
64
|
return self._unit_factor(unit) * (Z[0, :] + h0 * self.psi(Z))
|
|
63
65
|
|
|
64
66
|
def du_dx(self, Z: np.ndarray, h0: float) -> float | np.ndarray:
|
|
65
|
-
"""Derivative u' = u₀' + h₀ ψ'."""
|
|
67
|
+
"""Derivative u' = u₀' + h₀ ψ' (-)."""
|
|
66
68
|
return Z[1, :] + h0 * self.dpsi_dx(Z)
|
|
67
69
|
|
|
68
70
|
def w(self, Z: np.ndarray, unit: LengthUnit = "mm") -> float | np.ndarray:
|
|
69
|
-
"""
|
|
71
|
+
"""
|
|
72
|
+
Center-line (vertical) deflection `w` (mm).
|
|
73
|
+
"""
|
|
70
74
|
return self._unit_factor(unit) * Z[2, :]
|
|
71
75
|
|
|
72
76
|
def dw_dx(self, Z: np.ndarray) -> float | np.ndarray:
|
|
73
|
-
"""First derivative w'."""
|
|
77
|
+
"""First derivative `w'` (-)."""
|
|
74
78
|
return Z[3, :]
|
|
75
79
|
|
|
76
80
|
def psi(
|
|
@@ -78,32 +82,32 @@ class FieldQuantities: # pylint: disable=too-many-instance-attributes, too-many
|
|
|
78
82
|
Z: np.ndarray,
|
|
79
83
|
unit: AngleUnit = "rad",
|
|
80
84
|
) -> float | np.ndarray:
|
|
81
|
-
"""Rotation
|
|
85
|
+
"""Rotation `ψ` of the mid-plane (rad)."""
|
|
82
86
|
factor = self._unit_factor(unit)
|
|
83
87
|
return factor * Z[4, :]
|
|
84
88
|
|
|
85
89
|
def dpsi_dx(self, Z: np.ndarray) -> float | np.ndarray:
|
|
86
|
-
"""First derivative
|
|
90
|
+
"""First derivative `ψ'` (rad/mm)."""
|
|
87
91
|
return Z[5, :]
|
|
88
92
|
|
|
89
93
|
def N(self, Z: np.ndarray) -> float | np.ndarray:
|
|
90
|
-
"""Axial normal force N = A11 u' + B11
|
|
94
|
+
"""Axial normal force `N = A11 u' + B11 ψ'` in the slab [N]"""
|
|
91
95
|
return self.es.A11 * Z[1, :] + self.es.B11 * Z[5, :]
|
|
92
96
|
|
|
93
97
|
def M(self, Z: np.ndarray) -> float | np.ndarray:
|
|
94
|
-
"""Bending moment M = B11 u' + D11
|
|
98
|
+
"""Bending moment `M = B11 u' + D11 ψ'` in the slab [Nmm]"""
|
|
95
99
|
return self.es.B11 * Z[1, :] + self.es.D11 * Z[5, :]
|
|
96
100
|
|
|
97
101
|
def V(self, Z: np.ndarray) -> float | np.ndarray:
|
|
98
|
-
"""Vertical shear force V = kA55(w' +
|
|
102
|
+
"""Vertical shear force `V = kA55(w' + ψ)` [N]"""
|
|
99
103
|
return self.es.kA55 * (Z[3, :] + Z[4, :])
|
|
100
104
|
|
|
101
105
|
def sig(self, Z: np.ndarray, unit: StressUnit = "MPa") -> float | np.ndarray:
|
|
102
|
-
"""Weak-layer normal stress"""
|
|
106
|
+
"""Weak-layer normal stress `sig = -kn * w`"""
|
|
103
107
|
return -self._unit_factor(unit) * self.es.weak_layer.kn * self.w(Z)
|
|
104
108
|
|
|
105
109
|
def tau(self, Z: np.ndarray, unit: StressUnit = "MPa") -> float | np.ndarray:
|
|
106
|
-
"""Weak-layer shear stress"""
|
|
110
|
+
"""Weak-layer shear stress `tau = -kt * (w' * h/2 - u(h=H/2))`"""
|
|
107
111
|
return (
|
|
108
112
|
-self._unit_factor(unit)
|
|
109
113
|
* self.es.weak_layer.kt
|
|
@@ -114,11 +118,11 @@ class FieldQuantities: # pylint: disable=too-many-instance-attributes, too-many
|
|
|
114
118
|
)
|
|
115
119
|
|
|
116
120
|
def eps(self, Z: np.ndarray) -> float | np.ndarray:
|
|
117
|
-
"""Weak-layer normal strain"""
|
|
121
|
+
"""Weak-layer normal strain `eps = -w / h`"""
|
|
118
122
|
return -self.w(Z) / self.es.weak_layer.h
|
|
119
123
|
|
|
120
124
|
def gamma(self, Z: np.ndarray) -> float | np.ndarray:
|
|
121
|
-
"""Weak-layer shear strain
|
|
125
|
+
"""Weak-layer shear strain `gamma = (w' * h/2 - u(h=H/2)) / h`"""
|
|
122
126
|
return (
|
|
123
127
|
self.dw_dx(Z) / 2 - self.u(Z, h0=self.es.slab.H / 2) / self.es.weak_layer.h
|
|
124
128
|
)
|
|
@@ -176,9 +180,9 @@ class FieldQuantities: # pylint: disable=too-many-instance-attributes, too-many
|
|
|
176
180
|
|
|
177
181
|
def dz_dxdx(self, z: np.ndarray, phi: float, qs: float) -> np.ndarray:
|
|
178
182
|
"""
|
|
179
|
-
Get second derivative z''(x) = K*z'(x) of the solution vector.
|
|
183
|
+
Get second derivative `z''(x) = K*z'(x)` of the solution vector.
|
|
180
184
|
|
|
181
|
-
z''(x) = [u''(x) u'''(x) w''(x) w'''(x) psi''(x), psi'''(x)]^T
|
|
185
|
+
`z''(x) = [u''(x) u'''(x) w''(x) w'''(x) psi''(x), psi'''(x)]^T`
|
|
182
186
|
|
|
183
187
|
Parameters
|
|
184
188
|
----------
|
|
@@ -200,7 +204,7 @@ class FieldQuantities: # pylint: disable=too-many-instance-attributes, too-many
|
|
|
200
204
|
|
|
201
205
|
def du0_dxdx(self, z: np.ndarray, phi: float, qs: float) -> float | np.ndarray:
|
|
202
206
|
"""
|
|
203
|
-
Get second derivative of the horiz. centerline displacement u0''(x).
|
|
207
|
+
Get second derivative of the horiz. centerline displacement `u0''(x)` (mm⁻¹).
|
|
204
208
|
|
|
205
209
|
Parameters
|
|
206
210
|
----------
|
|
@@ -213,13 +217,13 @@ class FieldQuantities: # pylint: disable=too-many-instance-attributes, too-many
|
|
|
213
217
|
-------
|
|
214
218
|
ndarray, float
|
|
215
219
|
Second derivative of the horizontal centerline displacement
|
|
216
|
-
u0''(x)
|
|
220
|
+
`u0''(x)`.
|
|
217
221
|
"""
|
|
218
222
|
return self.dz_dx(z, phi, qs)[1, :]
|
|
219
223
|
|
|
220
224
|
def dpsi_dxdx(self, z: np.ndarray, phi: float, qs: float) -> float | np.ndarray:
|
|
221
225
|
"""
|
|
222
|
-
Get second derivative of the cross-section rotation psi''(x).
|
|
226
|
+
Get second derivative of the cross-section rotation `psi''(x)` (mm⁻²).
|
|
223
227
|
|
|
224
228
|
Parameters
|
|
225
229
|
----------
|
|
@@ -231,13 +235,13 @@ class FieldQuantities: # pylint: disable=too-many-instance-attributes, too-many
|
|
|
231
235
|
Returns
|
|
232
236
|
-------
|
|
233
237
|
ndarray, float
|
|
234
|
-
Second derivative of the cross-section rotation psi''(x)
|
|
238
|
+
Second derivative of the cross-section rotation psi''(x).
|
|
235
239
|
"""
|
|
236
240
|
return self.dz_dx(z, phi, qs)[5, :]
|
|
237
241
|
|
|
238
242
|
def du0_dxdxdx(self, z: np.ndarray, phi: float, qs: float) -> float | np.ndarray:
|
|
239
243
|
"""
|
|
240
|
-
Get third derivative of the horiz. centerline displacement u0'''(x).
|
|
244
|
+
Get third derivative of the horiz. centerline displacement `u0'''(x)` (mm⁻²).
|
|
241
245
|
|
|
242
246
|
Parameters
|
|
243
247
|
----------
|
|
@@ -250,13 +254,13 @@ class FieldQuantities: # pylint: disable=too-many-instance-attributes, too-many
|
|
|
250
254
|
-------
|
|
251
255
|
ndarray, float
|
|
252
256
|
Third derivative of the horizontal centerline displacement
|
|
253
|
-
u0'''(x)
|
|
257
|
+
u0'''(x).
|
|
254
258
|
"""
|
|
255
259
|
return self.dz_dxdx(z, phi, qs)[1, :]
|
|
256
260
|
|
|
257
261
|
def dpsi_dxdxdx(self, z: np.ndarray, phi: float, qs: float) -> float | np.ndarray:
|
|
258
262
|
"""
|
|
259
|
-
Get third derivative of the cross-section rotation psi'''(x).
|
|
263
|
+
Get third derivative of the cross-section rotation `psi'''(x)` (mm⁻³).
|
|
260
264
|
|
|
261
265
|
Parameters
|
|
262
266
|
----------
|
|
@@ -268,6 +272,6 @@ class FieldQuantities: # pylint: disable=too-many-instance-attributes, too-many
|
|
|
268
272
|
Returns
|
|
269
273
|
-------
|
|
270
274
|
ndarray, float
|
|
271
|
-
Third derivative of the cross-section rotation psi'''(x)
|
|
275
|
+
Third derivative of the cross-section rotation psi'''(x).
|
|
272
276
|
"""
|
|
273
277
|
return self.dz_dxdx(z, phi, qs)[5, :]
|
|
@@ -273,17 +273,17 @@ class UnknownConstantsSolver:
|
|
|
273
273
|
Arguments
|
|
274
274
|
---------
|
|
275
275
|
zl : ndarray
|
|
276
|
-
Solution vector (6x1) or (6x6) at left end of beam
|
|
276
|
+
Solution vector (6x1) or (6x6) at left end of beam segment.
|
|
277
277
|
zr : ndarray
|
|
278
|
-
Solution vector (6x1) or (6x6) at right end of beam
|
|
278
|
+
Solution vector (6x1) or (6x6) at right end of beam segment.
|
|
279
279
|
has_foundation : boolean
|
|
280
280
|
Indicates whether segment has foundation(True) or not (False).
|
|
281
281
|
Default is False.
|
|
282
282
|
pos: {'left', 'mid', 'right', 'l', 'm', 'r'}, optional
|
|
283
|
-
Determines whether the
|
|
284
|
-
is a left boundary
|
|
285
|
-
center
|
|
286
|
-
|
|
283
|
+
Determines whether the segment under consideration
|
|
284
|
+
is a left boundary segment (left, l), one of the
|
|
285
|
+
center segment (mid, m), or a right boundary
|
|
286
|
+
segment (right, r). Default is 'mid'.
|
|
287
287
|
|
|
288
288
|
Returns
|
|
289
289
|
-------
|
|
@@ -310,7 +310,7 @@ class UnknownConstantsSolver:
|
|
|
310
310
|
bcs[2],
|
|
311
311
|
fq.u(zr, h0=0), # ui(xi = li)
|
|
312
312
|
fq.w(zr), # wi(xi = li)
|
|
313
|
-
fq.psi(zr), #
|
|
313
|
+
fq.psi(zr), # psi(xi = li)
|
|
314
314
|
fq.N(zr), # Ni(xi = li)
|
|
315
315
|
fq.M(zr), # Mi(xi = li)
|
|
316
316
|
fq.V(zr), # Vi(xi = li)
|
|
@@ -321,13 +321,13 @@ class UnknownConstantsSolver:
|
|
|
321
321
|
[
|
|
322
322
|
-fq.u(zl, h0=0), # -ui(xi = 0)
|
|
323
323
|
-fq.w(zl), # -wi(xi = 0)
|
|
324
|
-
-fq.psi(zl), # -
|
|
324
|
+
-fq.psi(zl), # -psi(xi = 0)
|
|
325
325
|
-fq.N(zl), # -Ni(xi = 0)
|
|
326
326
|
-fq.M(zl), # -Mi(xi = 0)
|
|
327
327
|
-fq.V(zl), # -Vi(xi = 0)
|
|
328
328
|
fq.u(zr, h0=0), # ui(xi = li)
|
|
329
329
|
fq.w(zr), # wi(xi = li)
|
|
330
|
-
fq.psi(zr), #
|
|
330
|
+
fq.psi(zr), # psi(xi = li)
|
|
331
331
|
fq.N(zr), # Ni(xi = li)
|
|
332
332
|
fq.M(zr), # Mi(xi = li)
|
|
333
333
|
fq.V(zr), # Vi(xi = li)
|
|
@@ -347,7 +347,7 @@ class UnknownConstantsSolver:
|
|
|
347
347
|
[
|
|
348
348
|
-fq.u(zl, h0=0), # -ui(xi = 0)
|
|
349
349
|
-fq.w(zl), # -wi(xi = 0)
|
|
350
|
-
-fq.psi(zl), # -
|
|
350
|
+
-fq.psi(zl), # -psi(xi = 0)
|
|
351
351
|
-fq.N(zl), # -Ni(xi = 0)
|
|
352
352
|
-fq.M(zl), # -Mi(xi = 0)
|
|
353
353
|
-fq.V(zl), # -Vi(xi = 0)
|
|
@@ -385,9 +385,9 @@ class UnknownConstantsSolver:
|
|
|
385
385
|
Default is False.
|
|
386
386
|
pos : {'left', 'mid', 'right', 'l', 'm', 'r'}, optional
|
|
387
387
|
Determines whether the segement under consideration
|
|
388
|
-
is a left boundary
|
|
389
|
-
center
|
|
390
|
-
|
|
388
|
+
is a left boundary segment (left, l), one of the
|
|
389
|
+
center segment (mid, m), or a right boundary
|
|
390
|
+
segment (right, r). Default is 'mid'.
|
|
391
391
|
|
|
392
392
|
Returns
|
|
393
393
|
-------
|
weac/utils/geldsetzer.py
CHANGED
|
@@ -82,18 +82,23 @@ HAND_HARDNESS = {
|
|
|
82
82
|
"F-": 0.67,
|
|
83
83
|
"F": 1,
|
|
84
84
|
"F+": 1.33,
|
|
85
|
+
"F-4F": 1.5,
|
|
85
86
|
"4F-": 1.67,
|
|
86
87
|
"4F": 2,
|
|
87
88
|
"4F+": 2.33,
|
|
89
|
+
"4F-1F": 2.5,
|
|
88
90
|
"1F-": 2.67,
|
|
89
91
|
"1F": 3,
|
|
90
92
|
"1F+": 3.33,
|
|
93
|
+
"1F-P": 3.5,
|
|
91
94
|
"P-": 3.67,
|
|
92
95
|
"P": 4,
|
|
93
96
|
"P+": 4.33,
|
|
97
|
+
"P-K": 4.5,
|
|
94
98
|
"K-": 4.67,
|
|
95
99
|
"K": 5,
|
|
96
100
|
"K+": 5.33,
|
|
101
|
+
"K-I": 5.5,
|
|
97
102
|
"I-": 5.67,
|
|
98
103
|
"I": 6,
|
|
99
104
|
"I+": 6.33,
|
|
@@ -117,18 +122,23 @@ HAND_HARDNESS_TO_DENSITY = {
|
|
|
117
122
|
"F-": 71.7,
|
|
118
123
|
"F": 103.7,
|
|
119
124
|
"F+": 118.4,
|
|
125
|
+
"F-4F": 123.15,
|
|
120
126
|
"4F-": 127.9,
|
|
121
127
|
"4F": 158.2,
|
|
122
128
|
"4F+": 163.7,
|
|
129
|
+
"4F-1F": 176.15,
|
|
123
130
|
"1F-": 188.6,
|
|
124
131
|
"1F": 208,
|
|
125
132
|
"1F+": 224.4,
|
|
133
|
+
"1F-P": 238.6,
|
|
126
134
|
"P-": 252.8,
|
|
127
135
|
"P": 275.9,
|
|
128
136
|
"P+": 314.6,
|
|
137
|
+
"P-K": 336.85,
|
|
129
138
|
"K-": 359.1,
|
|
130
139
|
"K": 347.4,
|
|
131
140
|
"K+": 407.8,
|
|
141
|
+
"K-I": 407.8,
|
|
132
142
|
"I-": 407.8,
|
|
133
143
|
"I": 407.8,
|
|
134
144
|
"I+": 407.8,
|
weac/utils/snow_types.py
CHANGED
|
@@ -65,18 +65,23 @@ class HandHardness(str, Enum):
|
|
|
65
65
|
Fm = "F-"
|
|
66
66
|
F = "F"
|
|
67
67
|
Fp = "F+"
|
|
68
|
+
F_4F = "F-4F"
|
|
68
69
|
_4Fm = "4F-"
|
|
69
70
|
_4F = "4F"
|
|
70
71
|
_4Fp = "4F+"
|
|
72
|
+
_4F_1F = "4F-1F"
|
|
71
73
|
_1Fm = "1F-"
|
|
72
74
|
_1F = "1F"
|
|
73
75
|
_1Fp = "1F+"
|
|
76
|
+
_1F_P = "1F-P"
|
|
74
77
|
Pm = "P-"
|
|
75
78
|
P = "P"
|
|
76
79
|
Pp = "P+"
|
|
80
|
+
P_K = "P-K"
|
|
77
81
|
Km = "K-"
|
|
78
82
|
K = "K"
|
|
79
83
|
Kp = "K+"
|
|
84
|
+
K_I = "K-I"
|
|
80
85
|
Im = "I-"
|
|
81
86
|
I = "I"
|
|
82
87
|
Ip = "I+"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: weac
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.1.1
|
|
4
4
|
Summary: Weak layer anticrack nucleation model
|
|
5
5
|
Author-email: 2phi GbR <mail@2phi.de>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -17,7 +17,7 @@ Requires-Python: >=3.12
|
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
License-File: LICENSE
|
|
19
19
|
Requires-Dist: matplotlib>=3.9.1
|
|
20
|
-
Requires-Dist: numpy
|
|
20
|
+
Requires-Dist: numpy<2.4.0,>=2.3.5
|
|
21
21
|
Requires-Dist: scipy>=1.14.0
|
|
22
22
|
Requires-Dist: pydantic>=2.11.7
|
|
23
23
|
Requires-Dist: snowpylot>=1.1.3
|
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
weac/__init__.py,sha256=
|
|
1
|
+
weac/__init__.py,sha256=kgTwOD6mYTXI3qvj9z5uFDNJH84Toa29jQuKAu-5P_M,76
|
|
2
2
|
weac/constants.py,sha256=BX8ifZhFciCuzzako1p-2Wh5CWWzR3cPdvyu501UtUs,1194
|
|
3
3
|
weac/logging_config.py,sha256=GJn4Fs80dDRpbPkSPByCmIOLkEI01dbeuMMSv_IDgoM,1103
|
|
4
|
-
weac/analysis/__init__.py,sha256=
|
|
5
|
-
weac/analysis/analyzer.py,sha256
|
|
6
|
-
weac/analysis/criteria_evaluator.py,sha256=
|
|
7
|
-
weac/analysis/plotter.py,sha256=
|
|
4
|
+
weac/analysis/__init__.py,sha256=FDbmQLC5zmT8OJftqNYgihXc8WYB1b9FasFPGzkKVU8,498
|
|
5
|
+
weac/analysis/analyzer.py,sha256=-yoOqsdQvpNvBc-U2nqB4UEKHGTMBu23lVPJqKxUVcs,29095
|
|
6
|
+
weac/analysis/criteria_evaluator.py,sha256=yiKQV6ccgNnDMEky18zlHT3YfvoxdqCQtnPHKhbnrJA,47624
|
|
7
|
+
weac/analysis/plotter.py,sha256=ibkH4rzQ2pqQVXPRfek722e8eU3vP63uysb-Q-EzfC0,80556
|
|
8
8
|
weac/components/__init__.py,sha256=94WIUVjPI3U-grN_7v0oi9bZB3Z8rCBcx9wJPOwJBAQ,439
|
|
9
9
|
weac/components/config.py,sha256=tnOnJ0M-_knZBhdr052nDyyFFAZN0f2hQ68XRuXG6d8,869
|
|
10
10
|
weac/components/criteria_config.py,sha256=f2agU7nXWURFAw8_68igiSk5aICUxwaB9u3Qasit-Q0,2909
|
|
11
|
-
weac/components/layer.py,sha256=
|
|
11
|
+
weac/components/layer.py,sha256=kfghjavzCqzzGrkKzllMMT4qD3F0pcYfk1ZHgM6rvE0,10755
|
|
12
12
|
weac/components/model_input.py,sha256=oyX4p7PgaAtUXXtpvV8XO_KxwOXtG1TB0x7rXxNfCFA,3330
|
|
13
13
|
weac/components/scenario_config.py,sha256=Tam-m9DQtdjmTm-lKQ8Dcjqje04ttJS2X3v_Nn7AUHQ,2563
|
|
14
14
|
weac/components/segment.py,sha256=F279KcAAkRuJKWav_BZ4BanO96WZm4KXtKHinFZki7s,941
|
|
15
15
|
weac/core/__init__.py,sha256=pRyCKD8XD3qXVUWtFG7N3cS91P5x5d8Jpr1hMEgxQ2U,233
|
|
16
16
|
weac/core/eigensystem.py,sha256=b7KXi2weCY9IVlH_7lCTXzKSx_pLdWY-x8BPjHL5nKo,13736
|
|
17
|
-
weac/core/field_quantities.py,sha256=
|
|
17
|
+
weac/core/field_quantities.py,sha256=rr0KvM5Eu9AR43CQrrODJJkXkM2b2N3BWk2dE38f64c,9175
|
|
18
18
|
weac/core/scenario.py,sha256=vHHe-JDWc-8ECVfy6lFGVtJmIIKRc0J9iUEGR8zckdw,6050
|
|
19
19
|
weac/core/slab.py,sha256=YwbAf7ogYDn3p0nXfj3IjVqwA6ro3jBSg2wXb_io_gQ,5125
|
|
20
20
|
weac/core/slab_touchdown.py,sha256=k30FyvclH_Q3mCZNTbJkNhSenv3ja6qSNhhkmi5p04A,14009
|
|
21
21
|
weac/core/system_model.py,sha256=HAZuquY6p1wf5QuUPA6VOVDIICeCxOaeXqk1dSfEzNY,15513
|
|
22
|
-
weac/core/unknown_constants_solver.py,sha256=
|
|
22
|
+
weac/core/unknown_constants_solver.py,sha256=kzB8351UC03rVcJWez0FAwdawI2tERbpcgqMRKgYbi8,17753
|
|
23
23
|
weac/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
|
-
weac/utils/geldsetzer.py,sha256=
|
|
24
|
+
weac/utils/geldsetzer.py,sha256=Rmn_PUyeomPLfxZlj9LDbdBBRDWovavrQenka318TIM,3681
|
|
25
25
|
weac/utils/misc.py,sha256=lGz0IDDJ_3nvYjSkivPJ5Xscl1D_AmvQLSjaL7SUbKs,3674
|
|
26
|
-
weac/utils/snow_types.py,sha256=
|
|
26
|
+
weac/utils/snow_types.py,sha256=OKSY8LzfKycSjg7uSUZkSXUzwhcw1D1fZs5S3hVQtUM,1573
|
|
27
27
|
weac/utils/snowpilot_parser.py,sha256=drOLnUg7uzMJMO9qU9x79xZkqQfFPCCQonVpU9S0x8U,13682
|
|
28
|
-
weac-3.
|
|
29
|
-
weac-3.
|
|
30
|
-
weac-3.
|
|
31
|
-
weac-3.
|
|
32
|
-
weac-3.
|
|
28
|
+
weac-3.1.1.dist-info/licenses/LICENSE,sha256=ojZPWKFHbFGDrlNOvuAKGH9WcKhpLHWZPcQ4SzhK91M,1082
|
|
29
|
+
weac-3.1.1.dist-info/METADATA,sha256=0cdfjFenF40KllOBi5gLkyOSkdA3Ko_1LAdX43AlUK4,25593
|
|
30
|
+
weac-3.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
31
|
+
weac-3.1.1.dist-info/top_level.txt,sha256=8tyXUHPFU4Ba_5kPtpwvXo5l6GjJmOnODVBJFygpdeE,5
|
|
32
|
+
weac-3.1.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|