weac 3.1.2__tar.gz → 3.1.3__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.
Files changed (68) hide show
  1. {weac-3.1.2 → weac-3.1.3}/CITATION.cff +1 -1
  2. {weac-3.1.2/src/weac.egg-info → weac-3.1.3}/PKG-INFO +1 -1
  3. {weac-3.1.2 → weac-3.1.3}/pyproject.toml +2 -2
  4. {weac-3.1.2 → weac-3.1.3}/src/weac/__init__.py +1 -1
  5. {weac-3.1.2 → weac-3.1.3}/src/weac/analysis/criteria_evaluator.py +4 -1
  6. {weac-3.1.2 → weac-3.1.3}/src/weac/components/__init__.py +2 -1
  7. {weac-3.1.2 → weac-3.1.3}/src/weac/components/config.py +10 -0
  8. {weac-3.1.2 → weac-3.1.3}/src/weac/components/scenario_config.py +2 -0
  9. {weac-3.1.2 → weac-3.1.3}/src/weac/core/slab_touchdown.py +29 -12
  10. {weac-3.1.2 → weac-3.1.3}/src/weac/core/system_model.py +24 -1
  11. {weac-3.1.2 → weac-3.1.3/src/weac.egg-info}/PKG-INFO +1 -1
  12. {weac-3.1.2 → weac-3.1.3}/LICENSE +0 -0
  13. {weac-3.1.2 → weac-3.1.3}/MANIFEST.in +0 -0
  14. {weac-3.1.2 → weac-3.1.3}/README.md +0 -0
  15. {weac-3.1.2 → weac-3.1.3}/img/bc.png +0 -0
  16. {weac-3.1.2 → weac-3.1.3}/img/layering.png +0 -0
  17. {weac-3.1.2 → weac-3.1.3}/img/logo.png +0 -0
  18. {weac-3.1.2 → weac-3.1.3}/img/model.png +0 -0
  19. {weac-3.1.2 → weac-3.1.3}/img/profiles.png +0 -0
  20. {weac-3.1.2 → weac-3.1.3}/img/systems.png +0 -0
  21. {weac-3.1.2 → weac-3.1.3}/setup.cfg +0 -0
  22. {weac-3.1.2 → weac-3.1.3}/src/weac/analysis/__init__.py +0 -0
  23. {weac-3.1.2 → weac-3.1.3}/src/weac/analysis/analyzer.py +0 -0
  24. {weac-3.1.2 → weac-3.1.3}/src/weac/analysis/plotter.py +0 -0
  25. {weac-3.1.2 → weac-3.1.3}/src/weac/components/criteria_config.py +0 -0
  26. {weac-3.1.2 → weac-3.1.3}/src/weac/components/layer.py +0 -0
  27. {weac-3.1.2 → weac-3.1.3}/src/weac/components/model_input.py +0 -0
  28. {weac-3.1.2 → weac-3.1.3}/src/weac/components/segment.py +0 -0
  29. {weac-3.1.2 → weac-3.1.3}/src/weac/constants.py +0 -0
  30. {weac-3.1.2 → weac-3.1.3}/src/weac/core/__init__.py +0 -0
  31. {weac-3.1.2 → weac-3.1.3}/src/weac/core/eigensystem.py +0 -0
  32. {weac-3.1.2 → weac-3.1.3}/src/weac/core/field_quantities.py +0 -0
  33. {weac-3.1.2 → weac-3.1.3}/src/weac/core/scenario.py +0 -0
  34. {weac-3.1.2 → weac-3.1.3}/src/weac/core/slab.py +0 -0
  35. {weac-3.1.2 → weac-3.1.3}/src/weac/core/unknown_constants_solver.py +0 -0
  36. {weac-3.1.2 → weac-3.1.3}/src/weac/logging_config.py +0 -0
  37. {weac-3.1.2 → weac-3.1.3}/src/weac/utils/__init__.py +0 -0
  38. {weac-3.1.2 → weac-3.1.3}/src/weac/utils/geldsetzer.py +0 -0
  39. {weac-3.1.2 → weac-3.1.3}/src/weac/utils/misc.py +0 -0
  40. {weac-3.1.2 → weac-3.1.3}/src/weac/utils/snow_types.py +0 -0
  41. {weac-3.1.2 → weac-3.1.3}/src/weac/utils/snowpilot_parser.py +0 -0
  42. {weac-3.1.2 → weac-3.1.3}/src/weac.egg-info/SOURCES.txt +0 -0
  43. {weac-3.1.2 → weac-3.1.3}/src/weac.egg-info/dependency_links.txt +0 -0
  44. {weac-3.1.2 → weac-3.1.3}/src/weac.egg-info/requires.txt +0 -0
  45. {weac-3.1.2 → weac-3.1.3}/src/weac.egg-info/top_level.txt +0 -0
  46. {weac-3.1.2 → weac-3.1.3}/tests/__init__.py +0 -0
  47. {weac-3.1.2 → weac-3.1.3}/tests/analysis/__init__.py +0 -0
  48. {weac-3.1.2 → weac-3.1.3}/tests/analysis/test_analyzer.py +0 -0
  49. {weac-3.1.2 → weac-3.1.3}/tests/analysis/test_criteria_evaluator.py +0 -0
  50. {weac-3.1.2 → weac-3.1.3}/tests/components/__init__.py +0 -0
  51. {weac-3.1.2 → weac-3.1.3}/tests/components/test_configs.py +0 -0
  52. {weac-3.1.2 → weac-3.1.3}/tests/components/test_layer.py +0 -0
  53. {weac-3.1.2 → weac-3.1.3}/tests/core/__init__.py +0 -0
  54. {weac-3.1.2 → weac-3.1.3}/tests/core/test_eigensystem.py +0 -0
  55. {weac-3.1.2 → weac-3.1.3}/tests/core/test_field_quantities.py +0 -0
  56. {weac-3.1.2 → weac-3.1.3}/tests/core/test_scenario.py +0 -0
  57. {weac-3.1.2 → weac-3.1.3}/tests/core/test_slab.py +0 -0
  58. {weac-3.1.2 → weac-3.1.3}/tests/core/test_slab_touchdown.py +0 -0
  59. {weac-3.1.2 → weac-3.1.3}/tests/core/test_system_model.py +0 -0
  60. {weac-3.1.2 → weac-3.1.3}/tests/run_tests.py +0 -0
  61. {weac-3.1.2 → weac-3.1.3}/tests/test_comparison_results.py +0 -0
  62. {weac-3.1.2 → weac-3.1.3}/tests/test_regression_simulation.py +0 -0
  63. {weac-3.1.2 → weac-3.1.3}/tests/utils/__init__.py +0 -0
  64. {weac-3.1.2 → weac-3.1.3}/tests/utils/json_helpers.py +0 -0
  65. {weac-3.1.2 → weac-3.1.3}/tests/utils/test_json_helpers.py +0 -0
  66. {weac-3.1.2 → weac-3.1.3}/tests/utils/test_misc.py +0 -0
  67. {weac-3.1.2 → weac-3.1.3}/tests/utils/test_snowpilot_parser.py +0 -0
  68. {weac-3.1.2 → weac-3.1.3}/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.1.2
11
+ version: 3.1.3
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.1.2
3
+ Version: 3.1.3
4
4
  Summary: Weak layer anticrack nucleation model
5
5
  Author-email: 2phi GbR <mail@2phi.de>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "weac"
7
- version = "3.1.2"
7
+ version = "3.1.3"
8
8
  authors = [{ name = "2phi GbR", email = "mail@2phi.de" }]
9
9
  description = "Weak layer anticrack nucleation model"
10
10
  readme = "README.md"
@@ -123,7 +123,7 @@ ignore = [
123
123
  ]
124
124
 
125
125
  [tool.bumpversion]
126
- current_version = "3.1.2"
126
+ current_version = "3.1.3"
127
127
 
128
128
  [[tool.bumpversion.files]]
129
129
  filename = "pyproject.toml"
@@ -2,4 +2,4 @@
2
2
  WEAC - Weak Layer Anticrack Nucleation Model
3
3
  """
4
4
 
5
- __version__ = "3.1.2"
5
+ __version__ = "3.1.3"
@@ -24,7 +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
+ from weac.components.scenario_config import TouchdownMode
28
28
  from weac.core.system_model import SystemModel
29
29
 
30
30
  logger = logging.getLogger(__name__)
@@ -741,6 +741,9 @@ class CriteriaEvaluator:
741
741
  cut_length=cut_distance,
742
742
  )
743
743
  system_copy.update_scenario(segments=segments, scenario_config=scenario_config)
744
+ # Force the requested mode to avoid floating-point precision issues
745
+ # when l_AB/l_BC are recalculated with different scenario parameters
746
+ system_copy.set_forced_touchdown_mode(mode)
744
747
  touchdown_distance = system_copy.slab_touchdown.touchdown_distance
745
748
  analyzer = Analyzer(system_copy, printing_enabled=print_call_stats)
746
749
  energy_release_rate, _, _ = analyzer.differential_ERR(unit="J/m^2")
@@ -7,7 +7,7 @@ from .criteria_config import CriteriaConfig
7
7
  from .layer import Layer, WeakLayer
8
8
  from .model_input import ModelInput
9
9
  from .segment import Segment
10
- from .scenario_config import ScenarioConfig, SystemType
10
+ from .scenario_config import ScenarioConfig, SystemType, TouchdownMode
11
11
 
12
12
  __all__ = [
13
13
  "Config",
@@ -18,4 +18,5 @@ __all__ = [
18
18
  "ScenarioConfig",
19
19
  "ModelInput",
20
20
  "SystemType",
21
+ "TouchdownMode",
21
22
  ]
@@ -12,6 +12,8 @@ field_name: type = Field(..., gt=0, description="Description")
12
12
 
13
13
  from pydantic import BaseModel, Field
14
14
 
15
+ from weac.components.scenario_config import TouchdownMode
16
+
15
17
 
16
18
  class Config(BaseModel):
17
19
  """
@@ -21,11 +23,19 @@ class Config(BaseModel):
21
23
  ----------
22
24
  touchdown : bool
23
25
  Whether slab touchdown on the collapsed weak layer is considered.
26
+ forced_touchdown_mode : TouchdownMode | None
27
+ If set, forces the touchdown mode instead of calculating it from l_AB/l_BC.
28
+ This avoids floating-point precision issues when the mode boundary values
29
+ are recalculated with different scenario parameters.
24
30
  """
25
31
 
26
32
  touchdown: bool = Field(
27
33
  default=False, description="Whether to include slab touchdown in the analysis"
28
34
  )
35
+ forced_touchdown_mode: TouchdownMode | None = Field(
36
+ default=None,
37
+ description="Force a specific touchdown mode instead of auto-calculating",
38
+ )
29
39
 
30
40
 
31
41
  if __name__ == "__main__":
@@ -11,6 +11,8 @@ SystemType = Literal[
11
11
  "skier", "skiers", "pst-", "-pst", "rot", "trans", "vpst-", "-vpst"
12
12
  ]
13
13
 
14
+ TouchdownMode = Literal["A_free_hanging", "B_point_contact", "C_in_contact"]
15
+
14
16
 
15
17
  class ScenarioConfig(BaseModel):
16
18
  """
@@ -9,7 +9,7 @@ from typing import Literal
9
9
  from scipy.optimize import brentq
10
10
 
11
11
  from weac.components.layer import WeakLayer
12
- from weac.components.scenario_config import ScenarioConfig
12
+ from weac.components.scenario_config import ScenarioConfig, TouchdownMode
13
13
  from weac.components.segment import Segment
14
14
  from weac.constants import STIFFNESS_COLLAPSE_FACTOR
15
15
  from weac.core.eigensystem import Eigensystem
@@ -20,9 +20,6 @@ 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
-
26
23
  class SlabTouchdown: # pylint: disable=too-many-instance-attributes,too-few-public-methods
27
24
  """
28
25
  Handling the touchdown situation in a PST.
@@ -52,6 +49,9 @@ class SlabTouchdown: # pylint: disable=too-many-instance-attributes,too-few-pub
52
49
  -----------
53
50
  scenario: `Scenario`
54
51
  eigensystem: `Eigensystem`
52
+ forced_mode: `TouchdownMode | None`
53
+ If provided, forces this touchdown mode instead of calculating from l_AB/l_BC.
54
+ This avoids floating-point precision issues when scenario parameters change.
55
55
 
56
56
  Attributes:
57
57
  -----------
@@ -81,9 +81,15 @@ class SlabTouchdown: # pylint: disable=too-many-instance-attributes,too-few-pub
81
81
  touchdown_distance: float
82
82
  collapsed_weak_layer_kR: float | None = None
83
83
 
84
- def __init__(self, scenario: Scenario, eigensystem: Eigensystem):
84
+ def __init__(
85
+ self,
86
+ scenario: Scenario,
87
+ eigensystem: Eigensystem,
88
+ forced_mode: TouchdownMode | None = None,
89
+ ):
85
90
  self.scenario = scenario
86
91
  self.eigensystem = eigensystem
92
+ self._forced_mode = forced_mode
87
93
 
88
94
  # Create a new scenario config with phi=0 (flat slab) while preserving other settings
89
95
  self.flat_config = ScenarioConfig(
@@ -114,14 +120,25 @@ class SlabTouchdown: # pylint: disable=too-many-instance-attributes,too-few-pub
114
120
  self.l_BC = self._calc_l_BC()
115
121
  except ValueError:
116
122
  self.l_BC = self.scenario.L
117
- # Assign stage
118
- touchdown_mode = "A_free_hanging"
119
- if self.scenario.cut_length <= self.l_AB:
123
+
124
+ # Assign stage - use forced mode if provided, otherwise calculate from thresholds
125
+ if self._forced_mode is not None:
126
+ touchdown_mode = self._forced_mode
127
+ logger.debug(
128
+ "Using forced touchdown mode: %s (l_AB=%.2f, l_BC=%.2f, cut_length=%.2f)",
129
+ touchdown_mode,
130
+ self.l_AB,
131
+ self.l_BC,
132
+ self.scenario.cut_length,
133
+ )
134
+ else:
120
135
  touchdown_mode = "A_free_hanging"
121
- elif self.l_AB < self.scenario.cut_length <= self.l_BC:
122
- touchdown_mode = "B_point_contact"
123
- elif self.l_BC < self.scenario.cut_length:
124
- touchdown_mode = "C_in_contact"
136
+ if self.scenario.cut_length <= self.l_AB:
137
+ touchdown_mode = "A_free_hanging"
138
+ elif self.l_AB < self.scenario.cut_length <= self.l_BC:
139
+ touchdown_mode = "B_point_contact"
140
+ elif self.l_BC < self.scenario.cut_length:
141
+ touchdown_mode = "C_in_contact"
125
142
  self.touchdown_mode = touchdown_mode
126
143
 
127
144
  def _calc_touchdown_distance(self):
@@ -28,6 +28,7 @@ from weac.core.eigensystem import Eigensystem
28
28
  from weac.core.field_quantities import FieldQuantities
29
29
  from weac.core.scenario import Scenario
30
30
  from weac.core.slab import Slab
31
+ from weac.components.scenario_config import TouchdownMode
31
32
  from weac.core.slab_touchdown import SlabTouchdown
32
33
  from weac.core.unknown_constants_solver import UnknownConstantsSolver
33
34
 
@@ -164,7 +165,9 @@ class SystemModel:
164
165
  if self.config.touchdown:
165
166
  logger.info("Solving for Slab Touchdown")
166
167
  slab_touchdown = SlabTouchdown(
167
- scenario=self.scenario, eigensystem=self.eigensystem
168
+ scenario=self.scenario,
169
+ eigensystem=self.eigensystem,
170
+ forced_mode=self.config.forced_touchdown_mode,
168
171
  )
169
172
  logger.info(
170
173
  "Original cut_length: %s, touchdown_distance: %s",
@@ -345,6 +348,26 @@ class SystemModel:
345
348
  self._invalidate_slab_touchdown()
346
349
  self._invalidate_constants()
347
350
 
351
+ def set_forced_touchdown_mode(self, mode: TouchdownMode | None):
352
+ """
353
+ Set the forced touchdown mode.
354
+
355
+ When set, the touchdown mode calculation will use this mode instead of
356
+ calculating it from l_AB/l_BC thresholds. This avoids floating-point
357
+ precision issues when the mode boundaries are recalculated with different
358
+ scenario parameters.
359
+
360
+ Parameters
361
+ ----------
362
+ mode : TouchdownMode | None
363
+ The mode to force ("A_free_hanging", "B_point_contact", "C_in_contact"),
364
+ or None to use automatic calculation.
365
+ """
366
+ if self.config.forced_touchdown_mode != mode:
367
+ self.config.forced_touchdown_mode = mode
368
+ self._invalidate_slab_touchdown()
369
+ self._invalidate_constants()
370
+
348
371
  def _invalidate_eigensystem(self):
349
372
  """Invalidate the eigensystem."""
350
373
  self.__dict__.pop("eigensystem", None)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: weac
3
- Version: 3.1.2
3
+ Version: 3.1.3
4
4
  Summary: Weak layer anticrack nucleation model
5
5
  Author-email: 2phi GbR <mail@2phi.de>
6
6
  License-Expression: MIT
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes