Skip to content

Commit 63427c2

Browse files
📝 Add docstrings to feature/mode-III
Docstrings generation was requested by @zacczakk. * #6 (comment) The following files were modified: * `weac/eigensystem.py` * `weac/layered.py`
1 parent 49bf36c commit 63427c2

2 files changed

Lines changed: 131 additions & 190 deletions

File tree

weac/eigensystem.py

Lines changed: 121 additions & 177 deletions
Original file line numberDiff line numberDiff line change
@@ -101,17 +101,9 @@ class Eigensystem:
101101

102102
def __init__(self, system='pst-', touchdown = False):
103103
"""
104-
Initialize eigensystem with user input.
105-
106-
Parameters
107-
----------
108-
system : {'pst-', '-pst', 'skier', 'skiers'}, optional
109-
Type of system to analyze:
110-
- 'pst-': PST cut from the right
111-
- '-pst': PST cut from the left
112-
- 'skier': One skier on infinite slab
113-
- 'skiers': Multiple skiers on infinite slab
114-
Default is 'pst-'.
104+
Initializes an Eigensystem instance for layered snow slab analysis.
105+
106+
Sets up default physical constants, system type, and initializes all attributes related to weak-layer properties, slab properties, eigenvalues, eigenvectors, system matrices, and touchdown analysis. The system type determines the loading and boundary conditions to be analyzed, such as PST cuts or skier loading scenarios.
115107
"""
116108
# Assign global attributes
117109
self.g = 9810 # Gravitation (mm/s^2)
@@ -162,26 +154,17 @@ def __init__(self, system='pst-', touchdown = False):
162154

163155
def set_foundation_properties(self, t=30, E=0.25, nu=0.25, rhoweak=100, constitutive='plane strain', update=False):
164156
"""
165-
Set material properties and geometry of foundation (weak layer).
166-
167-
Parameters
168-
----------
169-
t : float, optional
170-
Weak-layer thickness (mm). Default is 30.
171-
cf : float, optional
172-
Fraction by which the weak-layer thickness is reduced due to collapse.
173-
Default is 0.5.
174-
E : float, optional
175-
Weak-layer Young's modulus (MPa). Default is 0.25.
176-
nu : float, optional
177-
Weak-layer Poisson's ratio. Default is 0.25.
178-
rhoweak : float, optional
179-
Weak-layer density (kg/m^3). Default is 100.
180-
constitutive: string, optional
181-
Constitutive behavior of the weak layer in out-of-plane direction. Possible values are 'plane strain', 'plane stress' and 'uniaxial'
182-
update : bool, optional
183-
If True, recalculate the fundamental system after foundation properties
184-
have changed. Default is False.
157+
Sets the material properties and geometry of the weak-layer foundation.
158+
159+
Configures weak-layer thickness, Young's modulus, Poisson's ratio, and density, adjusting for the specified constitutive behavior ('plane strain', 'plane stress', or 'uniaxial'). Optionally updates the fundamental system if properties are changed and `update` is True.
160+
161+
Args:
162+
t: Weak-layer thickness in mm.
163+
E: Weak-layer Young's modulus in MPa.
164+
nu: Weak-layer Poisson's ratio.
165+
rhoweak: Weak-layer density in kg/m³.
166+
constitutive: Constitutive behavior for out-of-plane direction ('plane strain', 'plane stress', or 'uniaxial').
167+
update: If True, recalculates the fundamental system after updating properties.
185168
"""
186169
# Geometry
187170
self.t = t # Weak-layer thickness (mm)
@@ -209,34 +192,21 @@ def set_foundation_properties(self, t=30, E=0.25, nu=0.25, rhoweak=100, constit
209192
def set_beam_properties(self, layers, phi, theta=0, C0=6.5, C1=4.40,
210193
nu=0.25, b=290, k=5/6, update=False):
211194
"""
212-
Set material and geometry properties of beam (slab).
213-
214-
Parameters
215-
----------
216-
layers : list or str
217-
2D list of top-to-bottom layer densities and thicknesses.
218-
Columns are density (kg/m^3) and thickness (mm).
219-
If entered as str, last split must be available in database.
220-
phi : float
221-
Inclination of the slab (degrees).
222-
theta : float, optional
223-
Rotation of the slab (degrees). Default is 0.
224-
C0 : float, optional
225-
Multiplicative constant of Young's modulus parametrization
226-
according to Bergfeld et al. (2021). Default is 6.5.
227-
C1 : float, optional
228-
Exponent of Young's modulus parameterization according to
229-
Bergfeld et al. (2021). Default is 4.40.
230-
nu : float, optional
231-
Poisson's ratio. Default is 0.25.
232-
b : float, optional
233-
Total snowpack thickness (mm). Default is 290.
234-
k: float, optional
235-
Shear correction factor. Default is 5/6.
236-
update : bool, optional
237-
If True, recalculate the fundamental system after
238-
beam properties have changed. Default is False.
239-
"""
195+
Sets the material and geometric properties of the slab (beam), including layering, elastic moduli, inclination, and rotation.
196+
197+
Args:
198+
layers: 2D list or string specifying slab layering. If a list, each row contains density (kg/m³) and thickness (mm) for a layer. If a string, loads a predefined profile from the database.
199+
phi: Inclination angle of the slab in degrees.
200+
theta: Rotation angle of the slab in degrees (default 0).
201+
C0: Multiplicative constant for Young's modulus parameterization (default 6.5).
202+
C1: Exponent for Young's modulus parameterization (default 4.40).
203+
nu: Poisson's ratio for all layers (default 0.25).
204+
b: Total snowpack thickness in mm (default 290).
205+
k: Shear correction factor (default 5/6).
206+
update: If True, recalculates the fundamental system after updating properties.
207+
208+
If `layers` is a string, loads density, thickness, and Young's modulus from a database profile. Otherwise, computes Young's modulus for each layer using the Bergfeld parameterization. Updates slab attributes including thickness, center of gravity, and elastic properties. Optionally updates the system matrices if `update` is True.
209+
"""
240210
if isinstance(layers, str):
241211
# Read layering and Young's modulus from database
242212
layers, E = load_dummy_profile(layers.split()[-1])
@@ -270,22 +240,15 @@ def set_beam_properties(self, layers, phi, theta=0, C0=6.5, C1=4.40,
270240

271241
def set_surface_load(self, p, yA = 0, zA = 0, width = 1.):
272242
"""
273-
Set surface line load.
274-
275-
Define a distributed surface load p (N/mm) that acts
276-
in vertical (gravity) direction and the center of attack for optional additional weights.
277-
278-
Arguments
279-
---------
280-
p : float
281-
Total weight (kg) of the additional loads
282-
yA : float, optional
283-
y-coordinate of the additional loads (mm)
284-
zA : float, optional
285-
z-coordinate of the additional loads (mm)
286-
b : float, optional
287-
Width (mm) of an additional weight
243+
Sets a distributed surface line load acting in the vertical direction.
288244
245+
Defines the magnitude and location of an external surface load applied to the slab, including optional out-of-plane and lateral coordinates and load width.
246+
247+
Args:
248+
p: Magnitude of the distributed surface load (N/mm).
249+
yA: y-coordinate of the load application point (mm), optional.
250+
zA: z-coordinate of the load application point (mm), optional.
251+
width: Width over which the load is distributed (mm), optional.
289252
"""
290253
self.p = p # Total line load from the additional weigths
291254
self.zA = zA # z-coordiante of the additional weights
@@ -294,9 +257,9 @@ def set_surface_load(self, p, yA = 0, zA = 0, width = 1.):
294257

295258
def calc_laminate_stiffness_matrix(self):
296259
"""
297-
Provide ABD matrix.
298-
299-
Return plane-strain laminate stiffness matrix (ABD matrix).
260+
Calculates the plane-strain laminate stiffness matrix (ABD matrix) for the layered slab.
261+
262+
Computes extensional (A11), bending-extension coupling (B11), bending (D11), and shear (kA55, kB55, kD55) stiffness components by summing contributions from each layer based on their elastic properties and thicknesses. Updates the corresponding class attributes.
300263
"""
301264
# Number of plies and ply thicknesses (top to bottom)
302265
n = self.slab.shape[0]
@@ -331,11 +294,9 @@ def calc_laminate_stiffness_matrix(self):
331294

332295
def calc_system_matrix(self):
333296
"""
334-
Assemble first-order ODE system matrix.
335-
336-
Using the solution vector z = [u, u', w, w', psi, psi',phiU, phiU', phiW, phiW']
337-
the ODE system is written in the form Az' + Bz = d
338-
and rearranged to z' = -(A ^ -1) B z + (A ^ -1) d = E z + F
297+
Assembles the 24x24 first-order ODE system matrix for the layered beam on an elastic foundation.
298+
299+
The matrix incorporates slab and weak-layer stiffness, geometric, and material properties, and is used to represent the coupled equations of motion for the layered snow slab system. The resulting matrix is stored in `self.sysmat` and is fundamental for subsequent eigenvalue and solution computations.
339300
"""
340301
Ew = self.weak['E']
341302
nuw = self.weak['nu']
@@ -624,7 +585,11 @@ def calc_system_matrix(self):
624585
self.sysmat = np.array(SystemMatrixC)
625586

626587
def calc_eigensystem(self):
627-
"""Calculate eigenvalues and eigenvectors of the system matrix."""
588+
"""
589+
Computes and classifies the eigenvalues and eigenvectors of the system matrix.
590+
591+
Separates real and complex eigenvalues and their corresponding eigenvectors, storing them for later use. Sets numerical stability shifts for positive eigenvalues to enhance robustness.
592+
"""
628593
# Calculate eigenvalues (ew) and eigenvectors (ev)
629594
ew, ev = np.linalg.eig(self.sysmat)
630595
# Classify real and complex eigenvalues
@@ -641,26 +606,29 @@ def calc_eigensystem(self):
641606
self.sR[self.ewR > 0], self.sC[self.ewC > 0] = -1, -1
642607

643608
def calc_fundamental_system(self):
644-
"""Calculate the fundamental system of the problem."""
609+
"""
610+
Updates the fundamental system by recalculating stiffness matrices, the system matrix, and the eigensystem.
611+
612+
This method should be called after any change to slab or foundation properties to ensure all system matrices and eigenvalues are consistent with the current configuration.
613+
"""
645614
self.calc_laminate_stiffness_matrix()
646615
self.calc_system_matrix()
647616
self.calc_eigensystem()
648617

649618
def get_weight_load(self, phi, theta = 0):
650619
"""
651-
Calculate line loads from slab mass.
652-
653-
Arguments
654-
---------
655-
phi : float
656-
Inclination (degrees). Counterclockwise positive.
657-
658-
Returns
659-
-------
660-
qn : float
661-
Line load (N/mm) at center of gravity in normal direction.
662-
qt : float
663-
Line load (N/mm) at center of gravity in tangential direction.
620+
Calculates the line load components from the slab's own weight, accounting for inclination and rotation.
621+
622+
Args:
623+
phi: Slab inclination angle in degrees (counterclockwise positive).
624+
theta: Slab rotation angle in degrees (default is 0).
625+
626+
Returns:
627+
qx: Axial component of the line load (N/mm).
628+
qy: Out-of-plane component of the line load (N/mm).
629+
qz: Normal component of the line load (N/mm).
630+
631+
The load is decomposed into axial, out-of-plane, and normal directions at the slab's center of gravity.
664632
"""
665633
# Convert units
666634
phi = np.deg2rad(phi) # Convert inclination to rad
@@ -679,19 +647,14 @@ def get_weight_load(self, phi, theta = 0):
679647

680648
def get_surface_load(self, phi, theta = 0):
681649
"""
682-
Calculate surface line loads.
683-
684-
Arguments
685-
---------
686-
phi : float
687-
Inclination (degrees). Counterclockwise positive.
688-
689-
Returns
690-
-------
691-
pn : float
692-
Surface line load (N/mm) in normal direction.
693-
pt : float
694-
Surface line load (N/mm) in tangential direction.
650+
Calculates the components of the applied surface line load in tangential, out-of-plane, and normal directions based on slab inclination and rotation.
651+
652+
Args:
653+
phi: Slab inclination angle in degrees (counterclockwise positive).
654+
theta: Slab rotation angle in degrees (default is 0).
655+
656+
Returns:
657+
Tuple of floats (pt, po, pn) representing the surface line load (N/mm) in the tangential, out-of-plane, and normal directions, respectively.
695658
"""
696659
# Convert units
697660
phi = np.deg2rad(phi) # Convert inclination to rad
@@ -705,21 +668,17 @@ def get_surface_load(self, phi, theta = 0):
705668

706669
def get_skier_load(self, m, phi,theta = 0):
707670
"""
708-
Calculate skier point load.
709-
710-
Arguments
711-
---------
712-
m : float
713-
Skier weight (kg).
714-
phi : float
715-
Inclination (degrees). Counterclockwise positive.
716-
717-
Returns
718-
-------
719-
Fn : float
720-
Skier load (N) in normal direction.
721-
Ft : float
722-
Skier load (N) in tangential direction.
671+
Calculates the components of a skier's point load on the slab, accounting for inclination and rotation.
672+
673+
Args:
674+
m: Skier mass in kilograms.
675+
phi: Slab inclination angle in degrees (counterclockwise positive).
676+
theta: Slab rotation angle in degrees (default is 0).
677+
678+
Returns:
679+
Fx: Tangential component of the skier load (N).
680+
Fy: Out-of-plane component of the skier load (N).
681+
Fz: Normal component of the skier load (N).
723682
"""
724683
phi = np.deg2rad(phi) # Convert inclination to rad
725684
theta = np.deg2rad(theta) # Convert rotation to rad
@@ -733,22 +692,17 @@ def get_skier_load(self, m, phi,theta = 0):
733692

734693
def zh(self, x, l=0, bed=True):
735694
"""
736-
Compute bedded or free complementary solution at position x.
737-
738-
Arguments
739-
---------
740-
x : float
741-
Horizontal coordinate (mm).
742-
l : float, optional
743-
Segment length (mm). Default is 0.
744-
bed : bool
745-
Indicates whether segment has foundation or not. Default
746-
is True.
747-
748-
Returns
749-
-------
750-
zh : ndarray
751-
Complementary solution matrix (6x6) at position x.
695+
Computes the complementary solution matrix at position x for either a bedded (with foundation) or free (unbedded) segment.
696+
697+
For bedded segments, constructs the solution using eigenvalues and eigenvectors of the system matrix, combining real and complex parts. For free segments, returns a predefined matrix of polynomial and stiffness-based terms representing the complementary solution.
698+
699+
Args:
700+
x: Horizontal coordinate (mm).
701+
l: Segment length (mm), used for phase shifting in bedded segments.
702+
bed: If True, computes the solution for a bedded segment; if False, for a free segment.
703+
704+
Returns:
705+
The complementary solution matrix at position x. For bedded segments, the shape matches the system size (typically 24x24); for free segments, returns a 12x12 matrix.
752706
"""
753707

754708
A11 = self.A11
@@ -844,22 +798,19 @@ def zh(self, x, l=0, bed=True):
844798

845799
def zp(self, x, phi,theta = 0, bed=True, load = False):
846800
"""
847-
Compute bedded or free particular integrals at position x.
848-
849-
Arguments
850-
---------
851-
x : float
852-
Horizontal coordinate (mm).
853-
phi : float
854-
Inclination (degrees).
855-
bed : bool
856-
Indicates whether segment has foundation (True) or not
857-
(False). Default is True.
858-
859-
Returns
860-
-------
861-
zp : ndarray
862-
Particular integral vector (6x1) at position x.
801+
Computes the particular integral vector at position x for a layered beam system, accounting for slab inclination, rotation, and loading.
802+
803+
Depending on the `bed` flag, returns the particular solution for either a bedded segment (with elastic foundation) or a free segment (without foundation). The vector incorporates the effects of slab self-weight, surface loads, geometric properties, and material parameters. If `load` is False, external loads are omitted from the calculation.
804+
805+
Args:
806+
x: Horizontal coordinate (mm).
807+
phi: Slab inclination angle in degrees.
808+
theta: Slab rotation angle in degrees (default is 0).
809+
bed: If True, computes for a bedded segment; if False, for a free segment.
810+
load: If False, ignores external loads in the calculation.
811+
812+
Returns:
813+
ndarray: Particular integral vector at position x (24x1 for bedded, 12x1 for free segments).
863814
"""
864815
# Get weight and surface loads
865816
qx, qy, qz = self.get_weight_load(phi,theta)
@@ -974,26 +925,19 @@ def zp(self, x, phi,theta = 0, bed=True, load = False):
974925

975926
def z(self, x, C, l, phi, theta = 0, bed=True, load = True):
976927
"""
977-
Assemble solution vector at positions x.
978-
979-
Arguments
980-
---------
981-
x : float or squence
982-
Horizontal coordinate (mm). Can be sequence of length N.
983-
C : ndarray
984-
Vector of constants (6xN) at positions x.
985-
l : float
986-
Segment length (mm).
987-
phi : float
988-
Inclination (degrees).
989-
bed : bool
990-
Indicates whether segment has foundation (True) or not
991-
(False). Default is True.
992-
993-
Returns
994-
-------
995-
z : ndarray
996-
Solution vector (6xN) or (10xN) at position x.
928+
Computes the total solution vector at specified positions by combining the complementary and particular solutions.
929+
930+
Args:
931+
x: Scalar or sequence of horizontal positions (mm) where the solution is evaluated.
932+
C: Array of constants for the complementary solution.
933+
l: Segment length (mm).
934+
phi: Slab inclination angle in degrees.
935+
theta: Slab rotation angle in degrees (default is 0).
936+
bed: If True, computes for a segment with foundation; if False, for a free segment.
937+
load: If True, includes external loads in the particular solution.
938+
939+
Returns:
940+
The solution vector(s) at the specified position(s), with shape depending on the system (bedded or free segment).
997941
"""
998942
if isinstance(x, (list, tuple, np.ndarray)):
999943
z = np.concatenate([

0 commit comments

Comments
 (0)