weac.core package¶
Submodules¶
- weac.core.eigensystem module
Eigensystem
Eigensystem.weak_layer
Eigensystem.slab
Eigensystem.A11
Eigensystem.B11
Eigensystem.D11
Eigensystem.kA55
Eigensystem.K0
Eigensystem.ewC
Eigensystem.ewR
Eigensystem.evC
Eigensystem.evR
Eigensystem.sR
Eigensystem.sC
Eigensystem.A11
Eigensystem.B11
Eigensystem.D11
Eigensystem.kA55
Eigensystem.K0
Eigensystem.K
Eigensystem.ewC
Eigensystem.ewR
Eigensystem.evC
Eigensystem.evR
Eigensystem.sR
Eigensystem.sC
Eigensystem.__init__()
Eigensystem.slab
Eigensystem.weak_layer
Eigensystem.calc_eigensystem()
Eigensystem.assemble_system_matrix()
Eigensystem.calc_eigenvalues_and_eigenvectors()
Eigensystem.zh()
Eigensystem.zp()
Eigensystem.get_load_vector()
- weac.core.field_quantities module
FieldQuantities
FieldQuantities.__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
Scenario
Scenario.li
Scenario.ki
Scenario.mi
Scenario.system_type
Scenario.phi
Scenario.L
Scenario.crack_h
Scenario.li
Scenario.ki
Scenario.mi
Scenario.cum_sum_li
Scenario.qw
Scenario.qn
Scenario.qt
Scenario.L
Scenario.crack_h
Scenario.__init__()
Scenario.scenario_config
Scenario.segments
Scenario.weak_layer
Scenario.slab
Scenario.system_type
Scenario.phi
Scenario.surface_load
Scenario.cut_length
Scenario.refresh_from_config()
Scenario.get_segment_idx()
- weac.core.slab module
- weac.core.slab_touchdown module
SlabTouchdown
SlabTouchdown.collapsed_weak_layer
SlabTouchdown.straight_scenario
SlabTouchdown.l_AB
SlabTouchdown.l_BC
SlabTouchdown.touchdown_mode
SlabTouchdown.touchdown_distance
SlabTouchdown.collapsed_weak_layer_kR
SlabTouchdown.__init__()
SlabTouchdown.scenario
SlabTouchdown.eigensystem
SlabTouchdown.collapsed_eigensystem
- weac.core.system_model module
SystemModel
SystemModel.config
SystemModel.slab
SystemModel.weak_layer
SystemModel.scenario
SystemModel.eigensystem
SystemModel.slab_touchdown
SystemModel.unknown_constants
SystemModel.__init__()
SystemModel.config
SystemModel.weak_layer
SystemModel.slab
SystemModel.scenario
SystemModel.fq
SystemModel.eigensystem
SystemModel.slab_touchdown
SystemModel.unknown_constants
SystemModel.uncracked_unknown_constants
SystemModel.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:
object
Calculates 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:
object
Sets 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:
object
Parameters 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:
object
The 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