weac 3.0.2__tar.gz → 3.1.1__tar.gz
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-3.0.2 → weac-3.1.1}/CITATION.cff +1 -1
- {weac-3.0.2/src/weac.egg-info → weac-3.1.1}/PKG-INFO +2 -2
- {weac-3.0.2 → weac-3.1.1}/pyproject.toml +3 -3
- {weac-3.0.2 → weac-3.1.1}/src/weac/__init__.py +1 -1
- {weac-3.0.2 → weac-3.1.1}/src/weac/analysis/__init__.py +2 -2
- {weac-3.0.2 → weac-3.1.1}/src/weac/analysis/analyzer.py +60 -26
- {weac-3.0.2 → weac-3.1.1}/src/weac/analysis/criteria_evaluator.py +112 -15
- {weac-3.0.2 → weac-3.1.1}/src/weac/analysis/plotter.py +391 -26
- {weac-3.0.2 → weac-3.1.1}/src/weac/components/layer.py +7 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac/core/field_quantities.py +27 -23
- {weac-3.0.2 → weac-3.1.1}/src/weac/core/unknown_constants_solver.py +13 -13
- {weac-3.0.2 → weac-3.1.1}/src/weac/utils/geldsetzer.py +10 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac/utils/snow_types.py +5 -0
- {weac-3.0.2 → weac-3.1.1/src/weac.egg-info}/PKG-INFO +2 -2
- {weac-3.0.2 → weac-3.1.1}/src/weac.egg-info/requires.txt +1 -1
- {weac-3.0.2 → weac-3.1.1}/tests/analysis/test_analyzer.py +36 -0
- {weac-3.0.2 → weac-3.1.1}/tests/analysis/test_criteria_evaluator.py +53 -5
- {weac-3.0.2 → weac-3.1.1}/tests/test_regression_simulation.py +4 -4
- {weac-3.0.2 → weac-3.1.1}/LICENSE +0 -0
- {weac-3.0.2 → weac-3.1.1}/MANIFEST.in +0 -0
- {weac-3.0.2 → weac-3.1.1}/README.md +0 -0
- {weac-3.0.2 → weac-3.1.1}/img/bc.png +0 -0
- {weac-3.0.2 → weac-3.1.1}/img/layering.png +0 -0
- {weac-3.0.2 → weac-3.1.1}/img/logo.png +0 -0
- {weac-3.0.2 → weac-3.1.1}/img/model.png +0 -0
- {weac-3.0.2 → weac-3.1.1}/img/profiles.png +0 -0
- {weac-3.0.2 → weac-3.1.1}/img/systems.png +0 -0
- {weac-3.0.2 → weac-3.1.1}/setup.cfg +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac/components/__init__.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac/components/config.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac/components/criteria_config.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac/components/model_input.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac/components/scenario_config.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac/components/segment.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac/constants.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac/core/__init__.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac/core/eigensystem.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac/core/scenario.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac/core/slab.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac/core/slab_touchdown.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac/core/system_model.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac/logging_config.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac/utils/__init__.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac/utils/misc.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac/utils/snowpilot_parser.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac.egg-info/SOURCES.txt +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac.egg-info/dependency_links.txt +0 -0
- {weac-3.0.2 → weac-3.1.1}/src/weac.egg-info/top_level.txt +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/__init__.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/analysis/__init__.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/components/__init__.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/components/test_configs.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/components/test_layer.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/core/__init__.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/core/test_eigensystem.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/core/test_field_quantities.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/core/test_scenario.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/core/test_slab.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/core/test_slab_touchdown.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/core/test_system_model.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/run_tests.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/test_comparison_results.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/utils/__init__.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/utils/json_helpers.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/utils/test_json_helpers.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/utils/test_misc.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/utils/test_snowpilot_parser.py +0 -0
- {weac-3.0.2 → weac-3.1.1}/tests/utils/weac_reference_runner.py +0 -0
|
@@ -8,7 +8,7 @@ authors:
|
|
|
8
8
|
- family-names: "Weissgraeber"
|
|
9
9
|
given-names: "Philipp"
|
|
10
10
|
orcid: "https://orcid.org/0000-0001-8320-8672"
|
|
11
|
-
version: 3.
|
|
11
|
+
version: 3.1.1
|
|
12
12
|
date-released: 2021-12-30
|
|
13
13
|
identifiers:
|
|
14
14
|
- description: Collection of archived snapshots of all versions of WEAC
|
|
@@ -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
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "weac"
|
|
7
|
-
version = "3.
|
|
7
|
+
version = "3.1.1"
|
|
8
8
|
authors = [{ name = "2phi GbR", email = "mail@2phi.de" }]
|
|
9
9
|
description = "Weak layer anticrack nucleation model"
|
|
10
10
|
readme = "README.md"
|
|
@@ -20,7 +20,7 @@ classifiers = [
|
|
|
20
20
|
]
|
|
21
21
|
dependencies = [
|
|
22
22
|
"matplotlib>=3.9.1",
|
|
23
|
-
"numpy>=2.0
|
|
23
|
+
"numpy>=2.3.5,<2.4.0",
|
|
24
24
|
"scipy>=1.14.0",
|
|
25
25
|
"pydantic>=2.11.7",
|
|
26
26
|
"snowpylot>=1.1.3",
|
|
@@ -123,7 +123,7 @@ ignore = [
|
|
|
123
123
|
]
|
|
124
124
|
|
|
125
125
|
[tool.bumpversion]
|
|
126
|
-
current_version = "3.
|
|
126
|
+
current_version = "3.1.1"
|
|
127
127
|
|
|
128
128
|
[[tool.bumpversion.files]]
|
|
129
129
|
filename = "pyproject.toml"
|
|
@@ -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
|
]
|
|
@@ -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
|
+
)
|