weac.core package¶
Submodules¶
- weac.core.eigensystem module
EigensystemEigensystem.weak_layerEigensystem.slabEigensystem.A11Eigensystem.B11Eigensystem.D11Eigensystem.kA55Eigensystem.K0Eigensystem.ewCEigensystem.ewREigensystem.evCEigensystem.evREigensystem.sREigensystem.sCEigensystem.A11Eigensystem.B11Eigensystem.D11Eigensystem.kA55Eigensystem.K0Eigensystem.KEigensystem.ewCEigensystem.ewREigensystem.evCEigensystem.evREigensystem.sREigensystem.sCEigensystem.__init__()Eigensystem.slabEigensystem.weak_layerEigensystem.calc_eigensystem()Eigensystem.assemble_system_matrix()Eigensystem.calc_eigenvalues_and_eigenvectors()Eigensystem.zh()Eigensystem.zp()Eigensystem.get_load_vector()
- weac.core.field_quantities module
FieldQuantitiesFieldQuantities.__init__()FieldQuantities.u()FieldQuantities.du_dx()FieldQuantities.w()FieldQuantities.dw_dx()FieldQuantities.psi()FieldQuantities.dpsi_dx()FieldQuantities.N()FieldQuantities.M()FieldQuantities.V()FieldQuantities.sig()FieldQuantities.tau()FieldQuantities.eps()FieldQuantities.gamma()FieldQuantities.Gi()FieldQuantities.Gii()FieldQuantities.dz_dx()FieldQuantities.dz_dxdx()FieldQuantities.du0_dxdx()FieldQuantities.dpsi_dxdx()FieldQuantities.du0_dxdxdx()FieldQuantities.dpsi_dxdxdx()
- weac.core.scenario module
ScenarioScenario.liScenario.kiScenario.miScenario.system_typeScenario.phiScenario.LScenario.crack_hScenario.liScenario.kiScenario.miScenario.cum_sum_liScenario.qwScenario.qnScenario.qtScenario.LScenario.crack_hScenario.__init__()Scenario.scenario_configScenario.segmentsScenario.weak_layerScenario.slabScenario.system_typeScenario.phiScenario.surface_loadScenario.cut_lengthScenario.refresh_from_config()Scenario.get_segment_idx()
- weac.core.slab module
- weac.core.slab_touchdown module
SlabTouchdownSlabTouchdown.collapsed_weak_layerSlabTouchdown.straight_scenarioSlabTouchdown.l_ABSlabTouchdown.l_BCSlabTouchdown.touchdown_modeSlabTouchdown.touchdown_distanceSlabTouchdown.collapsed_weak_layer_kRSlabTouchdown.__init__()SlabTouchdown.scenarioSlabTouchdown.eigensystemSlabTouchdown.collapsed_eigensystem
- weac.core.system_model module
SystemModelSystemModel.configSystemModel.slabSystemModel.weak_layerSystemModel.scenarioSystemModel.eigensystemSystemModel.slab_touchdownSystemModel.unknown_constantsSystemModel.__init__()SystemModel.configSystemModel.weak_layerSystemModel.slabSystemModel.scenarioSystemModel.fqSystemModel.eigensystemSystemModel.slab_touchdownSystemModel.unknown_constantsSystemModel.uncracked_unknown_constantsSystemModel.update_weak_layer()SystemModel.update_layers()SystemModel.update_scenario()SystemModel.toggle_touchdown()SystemModel.z()
- weac.core.unknown_constants_solver module
Module contents¶
Core modules for the WEAC model.
- class weac.core.Eigensystem(weak_layer, slab)[source]¶
Bases:
objectCalculates system properties and solves the eigenvalue problem for a layered beam on an elastic foundation (Winkler model).
- System properties
- -----------------
- A11¶
- Type:
float # extensional stiffness
- B11¶
- Type:
float # coupling stiffness
- D11¶
- Type:
float # bending stiffness
- kA55¶
- Type:
float # shear stiffness
- K0¶
- Type:
float # foundation stiffness
- Eigenvalues and Eigenvectors
- ----------------------------
- ewC¶
- Type:
NDArray[np.complex128] # shape (k): Complex Eigenvalues
- ewR¶
- Type:
NDArray[np.float64] # shape (k): Real Eigenvalues
- evC¶
- Type:
NDArray[np.complex128] # shape (6, k): Complex Eigenvectors
- evR¶
- Type:
NDArray[np.float64] # shape (6, k): Real Eigenvectors
- sR¶
# (for numerical robustness)
- Type:
NDArray[np.float64] # shape (k): Real positive eigenvalue shifts
- sC¶
# (for numerical robustness)
- Type:
NDArray[np.float64] # shape (k): Complex positive eigenvalue shifts
- assemble_system_matrix(kn, kt)[source]¶
Assemble first-order ODE system matrix K.
Using the solution vector z = [u, u’, w, w’, psi, psi’] the ODE system is written in the form Az’ + Bz = d and rearranged to z’ = -(A^-1)Bz + (A^-1)d = Kz + q
- Returns:
System matrix K (6x6).
- Return type:
NDArray[np.float64]
- Parameters:
kn (float | None)
kt (float | None)
- calc_eigenvalues_and_eigenvectors(system_matrix)[source]¶
Calculate eigenvalues and eigenvectors of the system matrix.
Parameters:¶
system_matrix: NDArray # system_matrix size (6x6) of the eigenvalue problem
Return:¶
ewC: NDArray[np.complex128] # shape (k): Complex Eigenvalues ewR: NDArray[np.float64] # shape (g): Real Eigenvalues evC: NDArray[np.complex128] # shape (6, k): Complex Eigenvectors evR: NDArray[np.float64] # shape (6, g): Real Eigenvectors sR: NDArray[np.float64] # shape (k): Real positive eigenvalue shifts
# (for numerical robustness)
- sC: NDArray[np.float64] # shape (g): Complex positive eigenvalue shifts
# (for numerical robustness)
- Parameters:
system_matrix (ndarray[tuple[Any, ...], dtype[float64]])
- Return type:
tuple[ndarray[tuple[Any, …], dtype[complex128]], ndarray[tuple[Any, …], dtype[float64]], ndarray[tuple[Any, …], dtype[complex128]], ndarray[tuple[Any, …], dtype[float64]], ndarray[tuple[Any, …], dtype[float64]], ndarray[tuple[Any, …], dtype[float64]]]
- get_load_vector(phi, qs=0)[source]¶
Compute system load vector q.
Using the solution vector z = [u, u’, w, w’, psi, psi’] the ODE system is written in the form Az’ + Bz = d and rearranged to z’ = -(A ^ -1)Bz + (A ^ -1)d = Kz + q
- Parameters:
phi (float) – Inclination [deg]. Counterclockwise positive.
qs (float) – Surface Load [N/mm]
- Returns:
System load vector q (6x1).
- Return type:
ndarray
- zh(x, length=0, has_foundation=True)[source]¶
Compute bedded or free complementary solution at position x.
- Parameters:
x (float) – Horizontal coordinate (mm).
length (float, optional) – Segment length (mm). Default is 0.
has_foundation (bool) – Indicates whether segment has foundation or not. Default is True.
- Returns:
zh – Complementary solution matrix (6x6) at position x.
- Return type:
ndarray
- zp(x, phi=0, has_foundation=True, qs=0)[source]¶
Compute bedded or free particular integrals at position x.
- Parameters:
x (float) – Horizontal coordinate (mm).
phi (float) – Inclination (degrees).
has_foundation (bool) – Indicates whether segment has foundation (True) or not (False). Default is True.
qs (float) – additional surface load weight
- Returns:
zp – Particular integral vector (6x1) at position x.
- Return type:
ndarray
- A11: float¶
- B11: float¶
- D11: float¶
- kA55: float¶
- K0: float¶
- K: ndarray[tuple[Any, ...], dtype[_ScalarT]]¶
- ewC: ndarray[tuple[Any, ...], dtype[complex128]]¶
- ewR: ndarray[tuple[Any, ...], dtype[float64]]¶
- evC: ndarray[tuple[Any, ...], dtype[complex128]]¶
- evR: ndarray[tuple[Any, ...], dtype[float64]]¶
- sR: ndarray[tuple[Any, ...], dtype[float64]]¶
- sC: ndarray[tuple[Any, ...], dtype[float64]]¶
- class weac.core.Scenario(scenario_config, segments, weak_layer, slab)[source]¶
Bases:
objectSets up the scenario on which the eigensystem is solved.
- Parameters:
scenario_config (ScenarioConfig)
segments (List[Segment])
weak_layer (WeakLayer)
slab (Slab)
- li¶
length of segment i [mm]
- Type:
List[float]
- ki¶
booleans indicating foundation support for segment i
- Type:
List[bool]
- mi¶
skier masses (kg) on boundary of segment i and i+1 [kg]
- Type:
List[float]
- system_type¶
- Type:
SystemType
- phi¶
Angle of slab in positive in counter-clockwise direction [deg]
- Type:
float
- L¶
Length of the model [mm]
- Type:
float
- crack_h¶
Height of the crack [mm]
- Type:
float
- __init__(scenario_config, segments, weak_layer, slab)[source]¶
- Parameters:
scenario_config (ScenarioConfig)
segments (List[Segment])
weak_layer (WeakLayer)
slab (Slab)
- get_segment_idx(x)[source]¶
Get the segment index for a given x-coordinate or coordinates.
- Parameters:
x (Union[float, Sequence[float], np.ndarray]) – A single x-coordinate or a sequence of x-coordinates.
- Returns:
The segment index or an array of indices.
- Return type:
Union[int, np.ndarray]
- refresh_from_config()[source]¶
Pull changed values out of scenario_config and recompute derived attributes.
- scenario_config: ScenarioConfig¶
- li: ndarray¶
- ki: ndarray¶
- mi: ndarray¶
- cum_sum_li: ndarray¶
- system_type: Literal['skier', 'skiers', 'pst-', '-pst', 'rot', 'trans', 'vpst-', '-vpst']¶
- phi: float¶
- surface_load: float¶
- qw: float¶
- qn: float¶
- qt: float¶
- L: float¶
- crack_h: float¶
- cut_length: float¶
- class weac.core.Slab(layers)[source]¶
Bases:
objectParameters of all layers assembled into a slab, provided as np.ndarray for easier access.
Coordinate frame: - z-axis points downward (first index: top layer, last index: bottom layer) - z = 0 is set at the mid-point of the slab’s thickness
- Parameters:
layers (List[Layer])
- zi_mid¶
z-coordinate of the layer i mid-point
- Type:
np.ndarray
- zi_bottom¶
z-coordinate of the layer i (boundary towards bottom)
- Type:
np.ndarray
- rhoi¶
densities of the layer i [t/mm^3]
- Type:
np.ndarray
- hi¶
thickness of the layer i [mm]
- Type:
np.ndarray
- Ei¶
Young’s modulus of the layer i [MPa]
- Type:
np.ndarray
- Gi¶
Shear Modulus of the layer i [MPa]
- Type:
np.ndarray
- nui¶
Poisson Ratio of the layer i [-]
- Type:
np.ndarray
- H¶
Total slab thickness (i.e. assembled layers) [mm]
- Type:
float
- z_cog¶
z-coordinate of Center of Gravity [mm]
- Type:
float
- qw¶
Weight Load of the slab [N/mm]
- Type:
float
- calc_vertical_center_of_gravity(phi)[source]¶
Vertical PSTs use triangular slabs (with horizontal cuts on the slab ends) Calculate center of gravity of triangular slab segments for vertical PSTs.
- Parameters:
phi (float) – Slope angle [deg]
- Returns:
x_cog (float) – Horizontal coordinate of center of gravity [mm]
z_cog (float) – Vertical coordinate of center of gravity [mm]
w (float) – Weight of the slab segment that is cut off or added [t]
- rhoi: ndarray¶
- hi: ndarray¶
- Ei: ndarray¶
- Gi: ndarray¶
- nui: ndarray¶
- z0: float¶
- zi_mid: ndarray¶
- zi_bottom: ndarray¶
- H: float¶
- z_cog: float¶
- qw: float¶
- class weac.core.SystemModel(model_input, config=None)[source]¶
Bases:
objectThe heart of the WEAC simulation system for avalanche release modeling.
This class orchestrates all components of the WEAC simulation, including slab mechanics, weak layer properties, touchdown calculations, and the solution of unknown constants for beam-on-elastic-foundation problems.
The SystemModel follows a lazy evaluation pattern using cached properties, meaning expensive calculations (eigensystem, touchdown, unknown constants) are only computed when first accessed and then cached for subsequent use.
Extracting Unknown Constants:
The primary output of the SystemModel is the unknown_constants matrix, which contains the solution constants for the beam segments:
```python # Basic usage system = SystemModel(model_input=model_input, config=config) constants = system.unknown_constants # Shape: (6, N) where N = number of segments
# Each column represents the 6 constants for one segment: # constants[:, i] = [C1, C2, C3, C4, C5, C6] for segment i # These constants define the beam deflection solution within that segment ```
Calculation Flow:
Eigensystem: Computes eigenvalues/eigenvectors for the beam-foundation system
Slab Touchdown (if enabled): Calculates touchdown behavior and updates segment lengths
Unknown Constants: Solves the linear system for beam deflection constants
Touchdown Behavior:
When config.touchdown=True, the system automatically: - Calculates touchdown mode (A: free-hanging, B: point contact, C: in contact) - Determines touchdown length based on slab-foundation interaction - Redefines scenario segments to use touchdown length instead of crack length - This matches the behavior of the original WEAC implementation
Performance Notes:
First access to unknown_constants triggers all necessary calculations
Subsequent accesses return cached results instantly
Use update_* methods to modify parameters and invalidate caches as needed
Example Usage:
```python from weac.components import ModelInput, Layer, Segment, Config from weac.core.system_model import SystemModel
# Define system components layers = [Layer(rho=200, h=150), Layer(rho=300, h=100)] segments = [Segment(length=10000, has_foundation=True, m=0),
Segment(length=4000, has_foundation=False, m=0)]
# Create system system = SystemModel(model_input=model_input, config=Config(touchdown=True))
# Solve system and extract results constants = system.unknown_constants # Solution constants (6 x N_segments) touchdown_info = system.slab_touchdown # Touchdown analysis (if enabled) eigensystem = system.eigensystem # Eigenvalue problem solution ```
- Parameters:
model_input (ModelInput)
config (Config)
- config¶
Configuration settings including touchdown enable/disable
- slab¶
Slab properties (thickness, material properties per layer)
- Type:
- weak_layer¶
Weak layer properties (stiffness, thickness, etc.)
- scenario¶
Scenario definition (segments, loads, boundary conditions)
- eigensystem¶
Eigenvalue problem solution (computed lazily)
- slab_touchdown¶
Touchdown analysis results (computed lazily if enabled)
- Type:
- unknown_constants¶
Solution constants matrix (computed lazily)
- Type:
numpy.ndarray
- __init__(model_input, config=None)[source]¶
- Parameters:
model_input (ModelInput)
config (Config | None)
- property eigensystem: Eigensystem¶
Solve for the eigensystem.
- property fq: FieldQuantities¶
Compute the field quantities.
- property slab_touchdown: SlabTouchdown | None¶
Solve for the slab touchdown. Modifies the scenario object in place by replacing the undercut segment with a new segment of length equal to the touchdown distance if the system is a PST or VPST.
- property uncracked_unknown_constants: ndarray¶
Solve for the uncracked unknown constants. This is the solution for the case where the slab is cracked nowhere.
- property unknown_constants: ndarray¶
Solve for the unknown constants matrix defining beam deflection in each segment.
This is the core solution of the WEAC beam-on-elastic-foundation problem. The unknown constants define the deflection, slope, moment, and shear force distributions within each beam segment.
Returns:¶
- np.ndarray: Solution constants matrix of shape (6, N_segments)
Each column contains the 6 constants for one segment: [C1, C2, C3, C4, C5, C6]
These constants are used in the general solution: u(x) = Σ Ci * φi(x) + up(x)
Where φi(x) are the homogeneous solutions and up(x) is the particular solution.
Notes
For touchdown systems, segment lengths are automatically adjusted based on touchdown calculations before solving
The solution accounts for boundary conditions, load transmission between segments, and foundation support
Results are cached after first computation for performance
Example
```python system = SystemModel(model_input, config) C = system.unknown_constants # Shape: (6, 2) for 2-segment system
# Constants for first segment segment_0_constants = C[:, 0]
# Use with eigensystem to compute field quantities x = 1000 # Position in mm segment_length = system.scenario.li[0] ```
- update_scenario(segments=None, scenario_config=None)[source]¶
Update fields on scenario_config (if present) or on the Scenario object itself, then refresh and invalidate constants.
- Parameters:
segments (List[Segment] | None)
scenario_config (ScenarioConfig | None)
- z(x, C, length, phi, has_foundation=True, qs=0)[source]¶
Assemble solution vector at positions x.
- Parameters:
x (float or sequence) – Horizontal coordinate (mm). Can be sequence of length N.
C (ndarray) – Vector of constants (6xN) at positions x.
length (float) – Segment length (mm).
phi (float) – Inclination (degrees).
has_foundation (bool) – Indicates whether segment has foundation (True) or not (False). Default is True.
qs (float) – Surface Load [N/mm]
- Returns:
z – Solution vector (6xN) at position x.
- Return type:
ndarray