weac 3.1.1__py3-none-any.whl → 3.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
weac/__init__.py CHANGED
@@ -2,4 +2,4 @@
2
2
  WEAC - Weak Layer Anticrack Nucleation Model
3
3
  """
4
4
 
5
- __version__ = "3.1.1"
5
+ __version__ = "3.1.2"
@@ -24,6 +24,7 @@ from weac.components import (
24
24
  WeakLayer,
25
25
  )
26
26
  from weac.constants import RHO_ICE
27
+ from weac.core.slab_touchdown import TouchdownMode
27
28
  from weac.core.system_model import SystemModel
28
29
 
29
30
  logger = logging.getLogger(__name__)
@@ -683,6 +684,7 @@ class CriteriaEvaluator:
683
684
  def evaluate_SteadyState(
684
685
  self,
685
686
  system: SystemModel,
687
+ mode: TouchdownMode = "C_in_contact",
686
688
  vertical: bool = False,
687
689
  print_call_stats: bool = False,
688
690
  ) -> SteadyStateResult:
@@ -710,18 +712,33 @@ class CriteriaEvaluator:
710
712
  UserWarning,
711
713
  )
712
714
  system_copy = copy.deepcopy(system)
715
+ # Evaluate touchdown distance for flat slab
713
716
  system_copy.toggle_touchdown(True)
714
- system_copy.update_scenario(scenario_config=ScenarioConfig(phi=0.0))
715
- l_BC = system_copy.slab_touchdown.l_BC
717
+ segments = [
718
+ Segment(length=5e3, has_foundation=True, m=0.0),
719
+ Segment(length=5e3, has_foundation=False, m=0.0),
720
+ ]
721
+ system_copy.update_scenario(
722
+ segments=segments, scenario_config=ScenarioConfig(phi=0.0)
723
+ )
724
+
725
+ cut_distance = 0
726
+ match mode:
727
+ case "C_in_contact":
728
+ cut_distance = 2 * system_copy.slab_touchdown.l_BC
729
+ case "B_point_contact":
730
+ cut_distance = system_copy.slab_touchdown.l_BC - 1e-3
731
+ case "A_free_hanging":
732
+ cut_distance = system_copy.slab_touchdown.l_AB - 1e-3
716
733
 
717
734
  segments = [
718
735
  Segment(length=5e3, has_foundation=True, m=0.0),
719
- Segment(length=2 * l_BC, has_foundation=False, m=0.0),
736
+ Segment(length=cut_distance, has_foundation=False, m=0.0),
720
737
  ]
721
738
  scenario_config = ScenarioConfig(
722
739
  system_type="vpst-" if vertical else "pst-",
723
740
  phi=0.0, # Slab Touchdown works only for flat slab
724
- cut_length=2 * l_BC,
741
+ cut_length=cut_distance,
725
742
  )
726
743
  system_copy.update_scenario(segments=segments, scenario_config=scenario_config)
727
744
  touchdown_distance = system_copy.slab_touchdown.touchdown_distance
weac/components/layer.py CHANGED
@@ -94,8 +94,43 @@ 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)
97
+ def _adam_tensile_strength(rho, unit: Literal["kPa", "MPa"] = "kPa"):
98
+ """
99
+ Estimate the tensile strength of a slab layer from its density.
100
+
101
+ Uses the density parametrization of Adam (2025).
102
+
103
+ Arguments
104
+ ---------
105
+ rho : ndarray, float
106
+ Layer density (kg/m^3).
107
+ unit : str, optional
108
+ Desired output unit of the layer strength. Default is 'kPa'.
109
+
110
+ Returns
111
+ -------
112
+ ndarray
113
+ Tensile strength in specified unit.
114
+ """
115
+ convert = {"kPa": 1e3, "MPa": 1}
116
+ TS_0 = 1.0 # [MPa]
117
+ kappa = 3.45 # [-]
118
+ # Adam's equation is given in MPa
119
+ return TS_0 * (rho / RHO_ICE) ** kappa * convert[unit]
120
+
121
+
122
+ # # TODO: Compressive Strength from Schöttner
123
+ # def _schotter_compressive_strength(rho, unit: Literal["kPa", "MPa"] = "kPa"):
124
+ # """
125
+ # Estimate the compressive strength of a slab layer from its density.
126
+ # On the compressive strength of weak snow layers of depth hoar - Schöttner (2025).
127
+
128
+ # Uses the density parametrization of Schöttner (2025).
129
+ # """
130
+ # convert = {"kPa": 1e3, "MPa": 1}
131
+ # CS_0 = 11.0 # [MPa]
132
+ # CS_1 = 5.4 # [-]
133
+ # return CS_0 * (rho / RHO_ICE) ** CS_1 * convert[unit]
99
134
 
100
135
 
101
136
  class Layer(BaseModel):
@@ -114,6 +149,10 @@ class Layer(BaseModel):
114
149
  Young's modulus E [MPa]. If omitted it is derived from ``rho``.
115
150
  G : float, optional
116
151
  Shear modulus G [MPa]. If omitted it is derived from ``E`` and ``nu``.
152
+ tensile_strength: float
153
+ Tensile strength [kPa].
154
+ tensile_strength_method: Literal["sigrist", "adam", "hybrid"]
155
+ Method to calculate the tensile strength.
117
156
  """
118
157
 
119
158
  # has to be provided
@@ -129,8 +168,8 @@ class Layer(BaseModel):
129
168
  tensile_strength: float = Field(
130
169
  default=0.0, ge=0, description="Tensile strength [kPa]"
131
170
  )
132
- tensile_strength_method: Literal["sigrist"] = Field(
133
- default="sigrist",
171
+ tensile_strength_method: Literal["sigrist", "adam", "hybrid"] = Field(
172
+ default="hybrid",
134
173
  description="Method to calculate the tensile strength",
135
174
  )
136
175
  E_method: Literal["bergfeld", "scapazzo", "gerling"] = Field(
@@ -153,17 +192,23 @@ class Layer(BaseModel):
153
192
  else:
154
193
  raise ValueError(f"Invalid E_method: {self.E_method}")
155
194
  object.__setattr__(self, "G", self.G or self.E / (2 * (1 + self.nu)))
156
- if self.tensile_strength_method == "sigrist":
157
- object.__setattr__(
158
- self,
159
- "tensile_strength",
160
- self.tensile_strength
161
- or _sigrist_tensile_strength(self.rho, unit="kPa"),
162
- )
163
- else:
164
- raise ValueError(
165
- f"Invalid tensile_strength_method: {self.tensile_strength_method}"
166
- )
195
+
196
+ if not self.tensile_strength:
197
+ if self.tensile_strength_method == "sigrist":
198
+ ts_value = _sigrist_tensile_strength(self.rho, unit="kPa")
199
+ elif self.tensile_strength_method == "adam":
200
+ ts_value = _adam_tensile_strength(self.rho, unit="kPa")
201
+ elif self.tensile_strength_method == "hybrid":
202
+ # Use Sigrist for rho < 250, Adam for rho >= 250
203
+ if self.rho < 250:
204
+ ts_value = _sigrist_tensile_strength(self.rho, unit="kPa")
205
+ else:
206
+ ts_value = _adam_tensile_strength(self.rho, unit="kPa")
207
+ else:
208
+ raise ValueError(
209
+ f"Invalid tensile_strength_method: {self.tensile_strength_method}"
210
+ )
211
+ object.__setattr__(self, "tensile_strength", ts_value)
167
212
 
168
213
  @model_validator(mode="after")
169
214
  def validate_positive_E_G(self):
@@ -20,6 +20,9 @@ from weac.core.unknown_constants_solver import UnknownConstantsSolver
20
20
  logger = logging.getLogger(__name__)
21
21
 
22
22
 
23
+ TouchdownMode = Literal["A_free_hanging", "B_point_contact", "C_in_contact"]
24
+
25
+
23
26
  class SlabTouchdown: # pylint: disable=too-many-instance-attributes,too-few-public-methods
24
27
  """
25
28
  Handling the touchdown situation in a PST.
@@ -56,7 +59,7 @@ class SlabTouchdown: # pylint: disable=too-many-instance-attributes,too-few-pub
56
59
  Length of the crack for transition of stage A to stage B [mm]
57
60
  l_BC : float
58
61
  Length of the crack for transition of stage B to stage C [mm]
59
- touchdown_mode : Literal["A_free_hanging", "B_point_contact", "C_in_contact"]
62
+ touchdown_mode : TouchdownMode
60
63
  Type of touchdown mode
61
64
  touchdown_distance : float
62
65
  Length of the touchdown segment [mm]
@@ -74,9 +77,7 @@ class SlabTouchdown: # pylint: disable=too-many-instance-attributes,too-few-pub
74
77
  straight_scenario: Scenario
75
78
  l_AB: float
76
79
  l_BC: float
77
- touchdown_mode: Literal[
78
- "A_free_hanging", "B_point_contact", "C_in_contact"
79
- ] # Three types of contact with collapsed weak layer
80
+ touchdown_mode: TouchdownMode # Three types of contact with collapsed weak layer
80
81
  touchdown_distance: float
81
82
  collapsed_weak_layer_kR: float | None = None
82
83
 
weac/core/system_model.py CHANGED
@@ -335,8 +335,7 @@ class SystemModel:
335
335
  weak_layer=self.weak_layer,
336
336
  slab=self.slab,
337
337
  )
338
- if self.config.touchdown:
339
- self._invalidate_slab_touchdown()
338
+ self._invalidate_slab_touchdown()
340
339
  self._invalidate_constants()
341
340
 
342
341
  def toggle_touchdown(self, touchdown: bool):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: weac
3
- Version: 3.1.1
3
+ Version: 3.1.2
4
4
  Summary: Weak layer anticrack nucleation model
5
5
  Author-email: 2phi GbR <mail@2phi.de>
6
6
  License-Expression: MIT
@@ -1,14 +1,14 @@
1
- weac/__init__.py,sha256=kgTwOD6mYTXI3qvj9z5uFDNJH84Toa29jQuKAu-5P_M,76
1
+ weac/__init__.py,sha256=CIiVU46-0zhtGbOm2zgB-Pcnh5wzVzn5DojC3CJQmDA,76
2
2
  weac/constants.py,sha256=BX8ifZhFciCuzzako1p-2Wh5CWWzR3cPdvyu501UtUs,1194
3
3
  weac/logging_config.py,sha256=GJn4Fs80dDRpbPkSPByCmIOLkEI01dbeuMMSv_IDgoM,1103
4
4
  weac/analysis/__init__.py,sha256=FDbmQLC5zmT8OJftqNYgihXc8WYB1b9FasFPGzkKVU8,498
5
5
  weac/analysis/analyzer.py,sha256=-yoOqsdQvpNvBc-U2nqB4UEKHGTMBu23lVPJqKxUVcs,29095
6
- weac/analysis/criteria_evaluator.py,sha256=yiKQV6ccgNnDMEky18zlHT3YfvoxdqCQtnPHKhbnrJA,47624
6
+ weac/analysis/criteria_evaluator.py,sha256=u4nvlkqTxNB0_7xp8ycRPe9RLuTLHP6_VzNlTG9q-nw,48286
7
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=kfghjavzCqzzGrkKzllMMT4qD3F0pcYfk1ZHgM6rvE0,10755
11
+ weac/components/layer.py,sha256=Ut0B9jKW4a6GVPxV43A4VCtAQJYk6ZA3MX8gt2aJBcQ,12491
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
@@ -17,16 +17,16 @@ weac/core/eigensystem.py,sha256=b7KXi2weCY9IVlH_7lCTXzKSx_pLdWY-x8BPjHL5nKo,1373
17
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
- weac/core/slab_touchdown.py,sha256=k30FyvclH_Q3mCZNTbJkNhSenv3ja6qSNhhkmi5p04A,14009
21
- weac/core/system_model.py,sha256=HAZuquY6p1wf5QuUPA6VOVDIICeCxOaeXqk1dSfEzNY,15513
20
+ weac/core/slab_touchdown.py,sha256=fTKrTblYC4i7CDQe_WIReUNdJXES7K5POBb5Fm2kHg4,13980
21
+ weac/core/system_model.py,sha256=rTsQqqKMYcyJCQw3ogsUCKgXmnJlnL9l4tjV5Tfpg1Y,15475
22
22
  weac/core/unknown_constants_solver.py,sha256=kzB8351UC03rVcJWez0FAwdawI2tERbpcgqMRKgYbi8,17753
23
23
  weac/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  weac/utils/geldsetzer.py,sha256=Rmn_PUyeomPLfxZlj9LDbdBBRDWovavrQenka318TIM,3681
25
25
  weac/utils/misc.py,sha256=lGz0IDDJ_3nvYjSkivPJ5Xscl1D_AmvQLSjaL7SUbKs,3674
26
26
  weac/utils/snow_types.py,sha256=OKSY8LzfKycSjg7uSUZkSXUzwhcw1D1fZs5S3hVQtUM,1573
27
27
  weac/utils/snowpilot_parser.py,sha256=drOLnUg7uzMJMO9qU9x79xZkqQfFPCCQonVpU9S0x8U,13682
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,,
28
+ weac-3.1.2.dist-info/licenses/LICENSE,sha256=ojZPWKFHbFGDrlNOvuAKGH9WcKhpLHWZPcQ4SzhK91M,1082
29
+ weac-3.1.2.dist-info/METADATA,sha256=xkJGkSjRAFW5BmqW99JDo9R1G71zq9rlh2gEOBl_P74,25593
30
+ weac-3.1.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
31
+ weac-3.1.2.dist-info/top_level.txt,sha256=8tyXUHPFU4Ba_5kPtpwvXo5l6GjJmOnODVBJFygpdeE,5
32
+ weac-3.1.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5