POSTPROCESSING METHODS#

class sstatics.core.postprocessing.bar_stress_disc.BarStressDistribution(bar, deform, force, n_disc=10)#

Bases: object

Assemble and evaluate the beam differential equation and compute stresses.

This class constructs the differential equation of the deflection curve (bending line) for a given bar using the bar geometry, deformations and internal force vector. The differential equation is discretized into n_disc segments and evaluated at the corresponding n_disc + 1 positions along the bar. The discretized internal force result (force_disc) returned by the differential equation solution is then used to compute section stresses at each evaluation point using CrossSectionStress.

Parameters:
barBar

The bar for which the differential equation and stress distribution are computed.

deformnumpy.ndarray

Deformation vector of the bar (shape (6, 1)). These are the nodal deformation values from the structural solution used to assemble the differential equation.

forcenumpy.ndarray

Internal force vector of the bar (shape (6, 1)). These are the nodal/internal forces from the structural solution.

n_discint, default=10

Number of discretization segments along the bar (number of evaluation points = n_disc + 1). The differential equation is evaluated at these points.

Raises:
ValueError

If deform or force does not have shape (6, 1), or if n_disc < 1.

Examples

>>> from sstatics.core.preprocessing import
...     (Bar, Node, CrossSection, Material)
>>> # assume system solved and `bar`, `deform`, `force` are available
>>> stress_dist = BarStressDistribution(bar, deform, force, n_disc=10)
>>> stress_dist.x.shape
(11, 1)
>>> stress_disc = stress_dist.stress_disc
>>> stress_disc.shape
(11, 4)
>>> stress_at_mid = stress_dist.stress_at_z(0.05)
>>> stress_at_mid.shape
(11, 3)
property force_disc#

Discretized internal forces along the bar.

Returns:
numpy.ndarray

Array of shape (n_disc + 1, 3) where columns correspond to: 0 → axial force N 1 → shear force V 2 → bending moment M

Examples

>>> from sstatics.core.preprocessing import
...     (Bar, Node, CrossSection, Material)
>>> bar = Bar(...)
>>> deform = np.zeros((6, 1))
>>> force = np.zeros((6, 1))
>>> stress_dist = BarStressDistribution(bar, deform, force, n_disc=10)
>>> forces = stress_dist.internal_forces
>>> forces[:, 0]  # axial forces
stress_at_z(z)#

Stress distribution at a specified height z along the cross-section.

Parameters:
zfloat

Height in the local z-direction where stresses are evaluated.

Returns:
numpy.ndarray

Array of shape (n_disc + 1, 3) where columns correspond to: 0 → normal stress σ_normal 1 → shear stress τ_shear 2 → bending stress σ_bending

Examples

>>> from sstatics.core.preprocessing import
...     (Bar, Node, CrossSection, Material)
>>> bar = Bar(...)
>>> deform = np.zeros((6, 1))
>>> force = np.zeros((6, 1))
>>> stress_dist = BarStressDistribution(bar, deform, force, n_disc=10)
>>> sigma_mid = stress_dist.stress_at_z(0.05)
>>> sigma_mid.shape
(11, 3)
>>> sigma_mid[:, 0]  # normal stress at z = 0.05
property stress_disc#

Stress distribution at the extreme fibers (top and bottom) along the bar.

Returns:
numpy.ndarray

Array of shape (n_disc + 1, 4) where columns correspond to: 0 → normal stress σ_normal 1 → shear stress τ_shear 2 → bending stress σ_bending at bottom fiber 3 → bending stress σ_bending at top fiber

Notes

Uses the cross-section boundary coordinates to compute bending stresses at top and bottom fibers.

Examples

>>> from sstatics.core.preprocessing import
...     (Bar, Node, CrossSection, Material)
>>> bar = Bar(...)
>>> deform = np.zeros((6, 1))
>>> force = np.zeros((6, 1))
>>> stress_dist = BarStressDistribution(bar, deform, force, n_disc=10)
>>> sigma = stress_dist.stress_disc
>>> sigma.shape
(11, 4)
>>> sigma[:, 2]  # bending stress at bottom fiber
property x#

Discretized positions along the bar length.

Returns:
numpy.ndarray

Array of shape (n_disc + 1,) containing positions along the bar from 0 to bar length.

Examples

>>> from sstatics.core.preprocessing import
...     (Bar, Node, CrossSection, Material)
>>> bar = Bar(...)
>>> deform = np.zeros((6, 1))
>>> force = np.zeros((6, 1))
>>> stress_dist = BarStressDistribution(bar, deform, force, n_disc=10)
>>> stress_dist.x
array([0.0, 0.1, 0.2, ..., bar.length])
class sstatics.core.postprocessing.bending_line.BendingLine(dgl_list)#

Bases: object

Combines local beam deformations and transforms them into the global coordinate system.

This class collects the local deformations u (axial) and w (transverse) derived from DifferentialEquation objects and transforms them into the global coordinate system of the overall structure. For each beam, the global deformations are returned as lists of x- and z-coordinates representing the deformed shape.

Parameters:
dgl_listlist of DifferentialEquation

List of DifferentialEquation objects, one per beam.

class sstatics.core.postprocessing.cross_section_stress.CrossSectionStress(cross_section)#

Bases: object

Calculate stresses in a cross-section under various loading conditions.

This class provides methods to compute normal, bending, and shear stresses for a given cross-section geometry, and combines these effects as needed.

Parameters:
cross_sectionCrossSection

The cross-section object containing all geometric properties.

Attributes:
cross_sectionCrossSection

The cross-section object containing all geometric properties.

_normal_stress_discfloat or None

Cache for normal stress values.

_bending_stress_discfloat or None

Cache for bending stress values.

_shear_stress_discfloat or None

Cache for shear stress values.

Examples

Define a T-shaped cross-section geometry using polygons:

>>> from sstatics.core.preprocessing import CrossSection
>>> from sstatics.core.preprocessing.geometry.objects import Polygon
>>> geometry = [
...     Polygon([(0, 0), (30, 0), (30, 3), (0, 3), (0, 0)]),
...     Polygon([(14, 3), (16, 3), (16, 43), (14, 43), (14, 3)])
... ]
>>> cs = CrossSection(geometry=geometry)
>>> cs_stress = CrossSectionStress(cross_section=cs)

Calculate normal, bending, and shear stresses:

>>> n = 2  # Normal force
>>> m_yy = 10  # Bending moment
>>> v_z = 10  # Shear force
>>> # Normal stress calculation
>>> cs_stress.normal_stress(n)
0.011764705882352941
>>> # Bending stress calculation
>>> cs_stress.bending_stress(m_yy)
0.010353175572198118
>>> # Shear stress calculation at specific height
>>> cs_stress.shear_stress(v_z)
0.162453504934344
>>> # Get shear stress distribution for plotting
>>> z_values, tau_values = cs_stress.shear_stress_disc(
...     v_z=v_z, z_i=3.01, z_j=43, n_disc=10
... )
>>> # Combined axial and bending stress
>>> cs_stress.combine_axial_bending_stress(n=n, m_yy=m_yy)
0.007931993275962822
bending_stress(m_yy=0, z=None)#

Calculate bending stress due to bending moment.

Parameters:
m_yyfloat, optional

Bending moment about the y-axis (default: 0).

zfloat, optional

Vertical coordinate from the neutral axis. If None, automatically selects the farthest point from the neutral axis (default: None).

Returns:
float

Bending stress at the specified location.

Raises:
ValueError

If z is outside the cross-sectional bounds.

Notes

Bending stress is calculated using the flexure formula: σ = My*c/Iy where c is the distance from the neutral axis.

bending_stress_disc(m_yy=0)#

Calculate bending stress distribution at the extreme fibers of the cross-section.

This method computes the bending stress at the top and bottom boundaries of the cross-section, which will be the maximum and minimum values.

Parameters:
m_yyfloat, optional

Bending moment about the y-axis (default: 0).

Returns:
list of [tuple, list]

A list containing:

  • Boundaries of the cross-section (zb)

  • List of bending stress values at top and bottom boundaries

    [bending_stress_bottom, bending_stress_top]

Notes

Bending stress varies linearly across the cross-section, with maximum values at the extreme fibers (top and bottom). The stress is calculated using: σ = My*c/I, where c is the distance from the neutral axis.

combine_axial_bending_stress(n=0, m_yy=0, z=0)#

Calculate combined normal and bending stress.

Parameters:
nfloat, optional

Normal force applied to the cross-section (default: 0).

m_yyfloat, optional

Bending moment about the y-axis (default: 0).

zfloat, optional

Vertical coordinate for bending stress calculation (default: 0).

Returns:
float

Combined stress at the specified location.

Notes

When both normal force and bending moment are present, the total stress is the algebraic sum of axial stress and bending stress.

normal_stress(n=0, z=None)#

Calculate normal stress due to axial force.

Parameters:
nfloat, optional

Normal force applied to the cross-section (default: 0).

zfloat, optional

Vertical coordinate. Not used for normal stress but kept for interface consistency with other stress methods (default: None).

Returns:
float

Normal stress distribution (uniform across the cross-section).

Raises:
ValueError

If z is outside the cross-sectional bounds.

Notes

Normal stress is calculated as the ratio of normal force to cross-sectional area according to the formula: σ = N/A

normal_stress_disc(n=0)#

Calculate normal stress distribution across the cross-section.

Since normal stress is uniform across the cross-section, this method returns a constant stress value at the top and bottom boundaries.

Parameters:
nfloat, optional

Normal force applied to the cross-section (default: 0).

Returns:
list of [tuple, list]

A list containing:

  • Boundaries of the cross-section (zb)

  • List of normal stress values at top and bottom boundaries

    [normal_stress_top, normal_stress_bottom]

Notes

The normal stress is constant throughout the cross-section and is calculated using the formula: σ = N/A, where N is the normal force and A is the cross-sectional area.

shear_stress(v_z=0, z=None)#

Calculate shear stress distribution due to transverse force.

Parameters:
v_zfloat, optional

Transverse force in the z-direction (default: 0).

zfloat, optional

Vertical coordinate where shear stress is calculated. If None, defaults to the center of mass (default: None).

Returns:
float

Shear stress at the specified location.

Notes

This method calculates shear stress using Jourawski’s formula: τ = V*S/(I*t), where S is the first moment of area, I is the second moment of area, and t is the width at the location of interest.

Calculation of the First Moment of Area (S): The first moment of area S is calculated for the portion of the cross-section above the specified height z. The process involves:

  1. Creating a partial cross-section above the specified height z

  2. Calculating the area of this partial section

  3. Determining the distance between the centroid of the full cross-section and the centroid of the partial section

  4. Computing S as the product of the partial area and this distance

Mathematically: S = A_partial * c, where c is the distance between the centroids of the full and partial cross-sections.

Important Restriction: This implementation is most accurate for thin-walled cross-sections where the thickness/height ratio is small. For thick-walled sections or complex geometries, more advanced methods (such as elasticity solutions) or finite element methods should be used to capture the complete stress state accurately.

shear_stress_disc(v_z, z_i, z_j, n_disc=20)#

Calculate shear stress distribution between two specified heights.

This method computes shear stress values at multiple points along the height of the cross-section between given z-coordinates.

Parameters:
v_zfloat

Transverse force in the z-direction.

z_ifloat

Starting z-coordinate for the calculation.

z_jfloat

Ending z-coordinate for the calculation.

n_discint, optional

Number of discretization points between z_i and z_j (default: 20).

Returns:
list of [array, list]

A list containing:

  • Array of z-values from z_i to z_j with n_disc+1 points

  • List of shear stress values corresponding to each z-position

Notes

This method uses linear spacing to create discrete points between z_i and z_j, then calculates the shear stress at each point using the shear_stress method. The results can be used for plotting or further analysis of shear stress distribution.

static thickness_at_height(points, z)#

Computes the cross-section thickness (horizontal distance) at a given height z based on polygon points.

Parameters:
pointslist[tuple[float, float]]

List of (y, z) or (x, z) coordinates of the polygon contour. The polygon must be closed (first == last point).

zfloat

The height at which the thickness should be computed.

Returns:
float

The horizontal thickness (distance in y-direction) at height z. Returns 0.0 if there are no points exactly at that height.

zero_line(n=0, m_yy=0)#

Calculate the location of the zero-stress line (neutral axis) under combined loading.

Parameters:
nfloat, optional

Normal force applied to the cross-section (default: 0).

m_yyfloat, optional

Bending moment about the y-axis (default: 0).

Returns:
float

Vertical coordinate of the zero-stress line.

Notes

The zero-stress line is where the combined normal and bending stress equals zero. This is found by setting σ = N/A + My*c/I = 0 and solving for c, which gives c = -N*I/(M*A).

class sstatics.core.postprocessing.differential_equation.DifferentialEquation(bar, deform, forces, n_disc=10)#

Bases: object

Calculates discrete result vector for the provided bar.

Parameters:
barBar

The bar that is to be discretised.

deformnumpy.ndarray

The deformation vector of the bar with shape (6, 1).

forcesnumpy.ndarray

The force vector of the bar with shape (6, 1).

n_discint, default=10

Number of discrete points along the bar for discretisation.

Raises:
ValueError

deform and forces need to have a shape of (6, 1)

ValueError

n_disc has to be greater than zero.

Examples

>>> from sstatics.core.preprocessing import Bar, BarLineLoad, CrossSection
>>> from sstatics.core.preprocessing import Material, Node, System
>>> from sstatics.core.calc_methods import FirstOrder
>>> from sstatics.core.postprocessing import DifferentialEquation
>>> n1 = Node(0, 0, u='fixed', w='fixed')
>>> n2 = Node(4, 0, w='fixed')
>>> cross = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377)
>>> mat = Material(210000000, 0.1, 81000000, 0.1)
>>> load = BarLineLoad(1, 1, 'z', 'bar', 'exact')
>>> bar = Bar(n1, n2, cross, mat, line_loads=load)
>>> system = System([bar])
>>> fo = FirstOrder(system)
>>> results = fo.bar_deform_total, fo.internal_forces
>>> de = DifferentialEquation(bar, results[0][0], results[1][0], n_disc=10)
property deform_disc#

Evaluate displacement-related result vectors along the bar.

This method computes the axial displacement u(x), transverse displacement w(x), and slope φ(x) at discretized positions along the bar. The values are determined by analysing the corresponding polynomial functions from the coefficient matrices.

Returns:
numpy.ndarray
A (n, 3) array, where:
  • n is the number of evaluation points + 1 (n_disc + 1),

  • Column 0 contains the axial displacement u(x),

  • Column 1 contains the transverse displacement w(x),

  • Column 2 contains the slope φ(x).

See also

_eval_poly()

Notes

The polynomials are evaluated using self._eval_poly, which uses a Vandermonde matrix for efficient vectorized evaluation.

Examples

>>> dgl = DifferentialEquation(...)
>>> deforms = dgl.deform_disc

The values can be accessed as:

>>> u_vals = deforms[:, 0]     # axial displacement
>>> w_vals = deforms[:, 1]     # transverse displacement
>>> phi_vals = deforms[:, 2]   # slope
property forces_disc#

Evaluate internal force result vectors along the bar.

This method computes the normal force N(x), shear force V(x), and bending moment M(x) at discretized positions along the bar. The values are determined by analysing the corresponding polynomial functions from the coefficient matrices.

Returns:
numpy.ndarray
A (n, 3) array, where:
  • n is the number of evaluation points + 1 (n_disc + 1),

  • Column 0 contains the normal force N(x),

  • Column 1 contains the shear force V(x),

  • Column 2 contains the bending moment M(x).

See also

_eval_poly()

Notes

The polynomials are evaluated using self._eval_poly, which uses a Vandermonde matrix for efficient vectorized evaluation.

Examples

>>> dgl = DifferentialEquation(...)
>>> forces = dgl.forces_disc

The values can be accessed as:

>>> n_vals = forces[:, 0]  # normal force
>>> v_vals = forces[:, 1]  # shear force
>>> m_vals = forces[:, 2]  # moment
property x#

Discrete positions along the bar length for evaluation.

Returns:
numpy.ndarray

Linearly spaced coordinates from 0 to bar length with n_disc + 1 points.

Examples

>>> dgl = DGL(...)
>>> bar_result.x
array([0.  0.4 0.8 1.2 1.6 2.  2.4 2.8 3.2 3.6 4. ])
property x_coef#

Polynomial coefficients for the differential equation in the local x-direction.

This method returns the coefficient matrix for evaluating internal quantities in the x-direction using a degree-3 polynomial. The matrix has shape (4, 3), where each row corresponds to a polynomial term of increasing degree (constant up to cubic), and each column represents a physical quantity.

Returns:
numpy.ndarray

A (4, 3) matrix of polynomial coefficients.

Notes

The following variables are used:

\(l\): Length of the bar.

\(EA\): Axial stiffness.

\(N\): Normal force at the start of bar.

\(u\): Axial displacement at the start of bar.

\(p_{i,x}, p_{j,x}\): Distributed load in local x-direction at the start and end of the bar.

The difference between the load values is:

\[dp_x = p_{j,x} - p_{i,x}\]

The polynomial coefficients in the local x-direction are calculated using the following matrix equation:

\[\begin{split}a_{x} = \begin{bmatrix} p_{i,x} & -N & u \\ \dfrac{dp_x}{l} & -p_{i,x} & -\dfrac{N}{EA} \\ 0 & -\dfrac{dp_x}{2l} & \dfrac{p_{i,x}}{2EA} \\ 0 & 0 & \dfrac{dp_x}{6lEA} \end{bmatrix}\end{split}\]

The matrix columns correspond to the following physical quantities:

  1. Linearly distributed load in local x-direction, \(p_x(x)\)

  2. Normal force along the bar axis, \(N(x)\)

  3. Axial deformation in local x-direction, \(u(x)\)

The resulting coefficients allow pointwise evaluation of these quantities along the bar axis in local x-direction.

Examples

Polynomial for linearly distributed load in local x-direction >>> dgl = DifferentialEquation(…) >>> dgl.x_coef[:, 0] array([ 0. 0. 0. 0.])

This represents the polynomial: \(p(x) = 0\)

property z_coef#

Polynomial coefficients for the differential equation in the local z-direction.

This method returns the coefficient matrix for evaluating internal quantities in the z-direction using a degree-5 polynomial. The matrix has shape (6, 5), where each row corresponds to a polynomial term of increasing degree (constant up to quintic), and each column represents a physical quantity.

Returns:
numpy.ndarray

A (6, 5) matrix of polynomial coefficients.

Notes

The following variables are used:

\(l\): Length of the bar.

\(EI\): Flexural stiffness.

\(V, M\): Shear force and bending moment at the start of bar.

\(w, \varphi\): Transverse displacement and slope at the start of bar.

\(p_{i,z}, p_{j,z}\): Distributed load in the local z-direction at the start and end of the bar.

The difference between the load values is:

\[dp_z = p_{j,z} - p_{i,z}\]

The polynomial coefficients in the local z-direction are calculated using the following matrix equation:

\[\begin{split}a_{z} = \begin{bmatrix} p_{i,z} & -V & -M & \varphi & w \\ \dfrac{dp_z}{l} & -p_{i,z} & -V & -\dfrac{M}{EI} & -\varphi \\ 0 & -\dfrac{dp_z}{2l} & -\dfrac{p_{i,z}}{2} & -\dfrac{V}{2EI} & \dfrac{M}{2EI} \\ 0 & 0 & -\dfrac{dp_z}{6l} & -\dfrac{p_{i,z}}{6EI} & \dfrac{V}{6EI} \\ 0 & 0 & 0 & -\dfrac{dp_z}{24lEI} & \dfrac{p_{i,z}}{24EI} \\ 0 & 0 & 0 & 0 & \dfrac{dp_z}{120lEI} \end{bmatrix}\end{split}\]

The matrix columns correspond to the following physical quantities:

  1. Linearly distributed load in local z-direction, \(p_z(x)\)

  2. Shear force in local z-direction, \(V(x)\)

  3. Bending moment about the y-axis, \(M(x)\)

  4. Slope of the deflection curve in z-direction, \(\varphi(x)\)

  5. Transverse deformation in local z-direction, \(w(x)\)

The resulting coefficients allow pointwise evaluation of these quantities along the bar axis in local z-direction.

Examples

Polynomial for the shear force function in local z-direction:

>>> dgl = DifferentialEquation(...)
>>> dgl.z_coef[:, 1]
array([ 2. -1. -0.  0.  0.  0.])

This represents the polynomial: \(V(x) = 2 - 1 x\)

Polynomial for the slope of the deflection curve in z-direction

>>> dgl = DifferentialEquation(...)
>>> dgl.z_coef[:, 3]
array([-4.58592008e-04 -0.00000000e+00  1.71972003e-04 -2.86620005e-05
-0.00000000e+00  0.00000000e+00])

This represents the polynomial: \(\varphi(x) = -4.59 \cdot 10^{-4} + 1.72 \cdot 10^{-4} x^2 - 2.87 \cdot 10^{-5} x^3\)

class sstatics.core.postprocessing.differential_equation_second_order.DifferentialEquationSecond(bar, deform, forces, n_disc=10, f_axial=-1)#

Bases: DifferentialEquation

Calculates discrete result vector for the provided bar using

second-order analysis.

Parameters:
barBarSecond

The bar that is to be discretised.

deformnumpy.ndarray

The deformation vector of the bar with shape (6, 1).

forcesnumpy.ndarray

The force vector of the bar with shape (6, 1).

n_discint, default=10

Number of discrete points along the bar for discretisation.

f_axialfloat, default=-1

The axial force (\(L\)) applied to the beam element, which is obtained from the internal force results of the first-order theory.

Raises:
ValueError

deform and forces need to have a shape of (6, 1)

ValueError

n_disc has to be greater than zero.

ValueError

f_axial can not be equal to zero.

property deform_disc#

Evaluate displacement-related result vectors along the bar.

This method computes the axial displacement u(x), transverse displacement w(x), and slope φ(x) at discretized positions along the bar. The values are determined by analysing the corresponding polynomial functions from the coefficient matrices.

Returns:
numpy.ndarray
A (n, 3) array, where:
  • n is the number of evaluation points + 1 (n_disc + 1),

  • Column 0 contains the axial displacement u(x),

  • Column 1 contains the transverse displacement w(x),

  • Column 2 contains the slope φ(x).

See also

_eval_poly()

Notes

The polynomials are evaluated using self._eval_poly, which uses a Vandermonde matrix for efficient vectorized evaluation.

Examples

>>> dgl = DifferentialEquation(...)
>>> deforms = dgl.deform_disc

The values can be accessed as:

>>> u_vals = deforms[:, 0]     # axial displacement
>>> w_vals = deforms[:, 1]     # transverse displacement
>>> phi_vals = deforms[:, 2]   # slope
property forces_disc#

Evaluate internal force result vectors along the bar.

This method computes the normal force N(x), shear force V(x), and bending moment M(x) at discretized positions along the bar. The values are determined by analysing the corresponding polynomial functions from the coefficient matrices.

Returns:
numpy.ndarray
A (n, 3) array, where:
  • n is the number of evaluation points + 1 (n_disc + 1),

  • Column 0 contains the normal force N(x),

  • Column 1 contains the shear force V(x),

  • Column 2 contains the bending moment M(x).

See also

_eval_poly()

Notes

The polynomials are evaluated using self._eval_poly, which uses a Vandermonde matrix for efficient vectorized evaluation.

Examples

>>> dgl = DifferentialEquation(...)
>>> forces = dgl.forces_disc

The values can be accessed as:

>>> n_vals = forces[:, 0]  # normal force
>>> v_vals = forces[:, 1]  # shear force
>>> m_vals = forces[:, 2]  # moment
property p_iz#

Compute the equivalent distributed load at the start of the bar along the curved axis.

Returns:
float

Equivalent distributed load at the bar start.

Notes

Variables used:

  • \(\ell\): Length of the bar.

  • \(EI\): Flexural stiffness.

  • \(B_s\): Modified flexural stiffness.

  • \(GA_s\): Shear stiffness.

  • \(\mu\): Characteristic number of the beam element.

  • \(V_i, V_j\): Shear force at start and end of the bar.

  • \(M_i, M_j\): Bending moments at start and end of the bar.

  • \(p_{i,z}, p_{j,z}\): Distributed loads at start and end.

  • \(\text{factor} = \text{sign(f_axial)}\)

Formulas:

For \(f_{\text{axial}} < 0\):

\[p_{i,z} = \frac{- (EI \cdot p_{j,z} \cdot \mu^2 + GA_s \cdot \ell^2 \cdot p_{j,z} + GA_s \cdot \ell \cdot \mu^2 \cdot V_j - EI \cdot p_{j,z} \cdot \mu^2 \cdot \cos(\mu) - GA_s \cdot \ell^2 \cdot p_{j,z} \cdot \cos(\mu) - GA_s \cdot M_i \cdot \mu^3 \cdot \sin(\mu) + GA_s \cdot \ell \cdot \mu^2 \cdot V_i \cdot \cos(\mu))} {(EI \cdot \mu^2 + GA_s \cdot \ell^2) \cdot (\cos(\mu) + \mu \cdot \sin(\mu) - 1) \cdot \cosh(\mu) + 2}\]

For \(f_{\text{axial}} > 0\):

\[p_{i,z} = \frac{EI \cdot p_{j,z} \cdot \mu^2 - GA_s \cdot \ell^2 \cdot p_{j,z} + GA_s \cdot \ell \cdot \mu^2 \cdot V_j - EI \cdot p_{j,z} \cdot \mu^2 \cdot \cosh(\mu) + GA_s \cdot \ell^2 \cdot p_{j,z} \cdot \cosh(\mu) + GA_s \cdot M_i \cdot \mu^3 \cdot \sinh(\mu) + GA_s \cdot \ell \cdot \mu^2 \cdot V_i \cdot \cosh(\mu)} {(EI \cdot \mu^2 - GA_s \cdot \ell^2) \cdot (\mu \cdot \sinh(\mu) - \cosh(\mu) + 1)}\]
property p_jz#

Compute the equivalent distributed load at the end of the bar along the curved axis.

Returns:
float

Equivalent distributed load at the bar end.

Notes

Variables used:

  • \(\ell\): Length of the bar.

  • \(EI\): Flexural stiffness.

  • \(B_s\): Modified flexural stiffness.

  • \(GA_s\): Shear stiffness.

  • \(\mu\): Characteristic number of the beam element.

  • \(V_i, V_j\): Shear force at start and end of the bar.

  • \(M_i, M_j\): Bending moments at start and end of the bar.

  • \(p_{i,z}, p_{j,z}\): Distributed loads at start and end.

  • \(\text{factor} = \text{sign(f_axial)}\)

Formulas:

For \(f_{\text{axial}} < 0\):

\[p_{j,z} = \frac{- GA_s \cdot \mu \cdot ( -M_i \cdot \mu \cdot \cos(\mu) - M_j \cdot \mu + M_i \cdot \mu + M_j \cdot \mu \cdot \cos(\mu) - \ell \cdot V_i \cdot \sin(\mu) - \ell \cdot V_j \cdot \sin(\mu) + M_j \cdot \mu^2 \cdot \sin(\mu) + \ell \cdot \mu \cdot V_i + \ell \cdot \mu \cdot V_j \cdot \cos(\mu))} {(EI \cdot \mu^2 + GA_s \cdot \ell^2) \cdot (2 \cdot \cos(\mu) + \mu \cdot \sin(\mu) - 2)}\]

For \(f_{\text{axial}} > 0\):

\[p_{j,z} = \frac{- GA_s \cdot \mu \cdot ( M_j \cdot \mu - M_i \cdot \mu + M_i \cdot \mu \cdot \cosh(\mu) - M_j \cdot \mu \cdot \cosh(\mu) + \ell \cdot V_i \cdot \sinh(\mu) + \ell \cdot V_j \cdot \sinh(\mu) + M_j \cdot \mu^2 \cdot \sinh(\mu) - \ell \cdot \mu \cdot V_i - \ell \cdot \mu \cdot V_j \cdot \cosh(\mu))} {(EI \cdot \mu^2 - GA_s \cdot \ell^2) \cdot (\mu \cdot \sinh(\mu) - 2 \cdot \cosh(\mu) + 2)}\]
property x#

Discrete positions along the bar length for evaluation.

Returns:
numpy.ndarray

Linearly spaced coordinates from 0 to bar length with n_disc + 1 points.

Examples

>>> dgl = DGL(...)
>>> bar_result.x
array([0.  0.4 0.8 1.2 1.6 2.  2.4 2.8 3.2 3.6 4. ])
property x_coef#

Polynomial coefficients for the differential equation in the local x-direction.

This method returns the coefficient matrix for evaluating internal quantities in the x-direction using a degree-3 polynomial. The matrix has shape (4, 3), where each row corresponds to a polynomial term of increasing degree (constant up to cubic), and each column represents a physical quantity.

Returns:
numpy.ndarray

A (4, 3) matrix of polynomial coefficients.

Notes

The following variables are used:

\(l\): Length of the bar.

\(EA\): Axial stiffness.

\(N\): Normal force at the start of bar.

\(u\): Axial displacement at the start of bar.

\(p_{i,x}, p_{j,x}\): Distributed load in local x-direction at the start and end of the bar.

The difference between the load values is:

\[dp_x = p_{j,x} - p_{i,x}\]

The polynomial coefficients in the local x-direction are calculated using the following matrix equation:

\[\begin{split}a_{x} = \begin{bmatrix} p_{i,x} & -N & u \\ \dfrac{dp_x}{l} & -p_{i,x} & -\dfrac{N}{EA} \\ 0 & -\dfrac{dp_x}{2l} & \dfrac{p_{i,x}}{2EA} \\ 0 & 0 & \dfrac{dp_x}{6lEA} \end{bmatrix}\end{split}\]

The matrix columns correspond to the following physical quantities:

  1. Linearly distributed load in local x-direction, \(p_x(x)\)

  2. Normal force along the bar axis, \(N(x)\)

  3. Axial deformation in local x-direction, \(u(x)\)

The resulting coefficients allow pointwise evaluation of these quantities along the bar axis in local x-direction.

Examples

Polynomial for linearly distributed load in local x-direction >>> dgl = DifferentialEquation(…) >>> dgl.x_coef[:, 0] array([ 0. 0. 0. 0.])

This represents the polynomial: \(p(x) = 0\)

property z_coef#

Compute the polynomial coefficients for the differential equation in the local z-direction.

Returns:
numpy.ndarray

A (6, 5) matrix of polynomial coefficients. Rows correspond to the basis functions: x^3, x^2, x, sinh/cosh or sin/cos, constant term. Columns correspond to different physical quantities.

Notes

Variables used:

  • \(\ell\): Length of the bar.

  • \(EI\): Flexural stiffness.

  • \(B_s\): Modified flexural stiffness.

  • \(GA_s\): Shear stiffness.

  • \(\mu\): Characteristic number of the beam element.

  • \(V, M\): Shear force and bending moment at the start.

  • \(w, \varphi\): Transverse displacement and slope at start.

  • \(p_{i,z}, p_{j,z}\): Distributed load at start and end.

  • \(dp_z = p_{j,z} - p_{i,z}\).

  • \(\text{factor} = \text{sign(f_axial)}\).

  • \(cor\): Correction term to satisfy boundary conditions.

Polynomial coefficients for L < 0:

\[\begin{split}a_z = \begin{bmatrix} 0 & -\dfrac{dp_z \cdot \ell}{\mu^2} - \dfrac{EI}{GA_s} \cdot \dfrac{dp_z}{\ell} & -\dfrac{p_{i,z} \cdot \ell^2}{\mu^2} - \dfrac{EI}{GA_s} \cdot p_{i,z} & c_2 & c_1 \\ -B_s \cdot c_3 \cdot \dfrac{\mu^4}{\ell^4} & B_s \cdot c_4 \cdot \dfrac{\mu^3}{\ell^3} & B_s \cdot c_3 \cdot \dfrac{\mu^2}{\ell^2} & c_4 \cdot \dfrac{\mu}{\ell} & c_3 \\ -B_s \cdot c_4 \cdot \dfrac{\mu^4}{\ell^4} & -B_s \cdot c_3 \cdot \dfrac{\mu^3}{\ell^3} & B_s \cdot c_4 \cdot \dfrac{\mu^2}{\ell^2} & -c_3 \cdot \dfrac{\mu}{\ell} & c_4 \\ 0 & 0 & -\dfrac{dp_z \cdot \ell}{\mu^2} - \dfrac{EI}{GA_s} \cdot \dfrac{dp_z}{\ell} & -\dfrac{p_{i,z} \cdot \ell^2}{2 \cdot B_s \cdot \mu^2} & c_2 + cor \\ 0 & 0 & 0 & -\dfrac{dp_z \cdot \ell}{2 \cdot B_s \cdot \mu^2} & \dfrac{p_{i,z} \cdot \ell^2}{2 \cdot B_s \cdot \mu^2} \\ 0 & 0 & 0 & 0 & \dfrac{dp_z \cdot \ell}{6 \cdot B_s \cdot \mu^2} \end{bmatrix}\end{split}\]

Polynomial coefficients for L > 0:

\[\begin{split}a_z = \begin{bmatrix} 0 & \dfrac{dp_z \cdot \ell}{\mu^2} - \dfrac{EI}{GA_s} \cdot \dfrac{dp_z}{\ell} & \dfrac{p_{i,z} \cdot \ell^2}{\mu^2} - \dfrac{EI}{GA_s} \cdot p_{i,z} & c_2 & c_1 \\ B_s \cdot c_3 \cdot \dfrac{\mu^4}{\ell^4} & -B_s \cdot c_4 \cdot \dfrac{\mu^3}{\ell^3} & -B_s \cdot c_3 \cdot \dfrac{\mu^2}{\ell^2} & c_4 \cdot \dfrac{\mu}{\ell} & c_3 \\ B_s \cdot c_4 \cdot \dfrac{\mu^4}{\ell^4} & -B_s \cdot c_3 \cdot \dfrac{\mu^3}{\ell^3} & -B_s \cdot c_4 \cdot \dfrac{\mu^2}{\ell^2} & -c_3 \cdot \dfrac{\mu}{\ell} & c_4 \\ 0 & 0 & \dfrac{dp_z \cdot \ell}{\mu^2} - \dfrac{EI}{GA_s} \cdot \dfrac{dp_z}{\ell} & -\dfrac{p_{i,z} \cdot \ell^2}{2 \cdot B_s \cdot \mu^2} & c_2 + cor \\ 0 & 0 & 0 & -\dfrac{dp_z \cdot \ell}{2 \cdot B_s \cdot \mu^2} & -\dfrac{p_{i,z} \cdot \ell^2}{2 \cdot B_s \cdot \mu^2} \\ 0 & 0 & 0 & 0 & -\dfrac{dp_z \cdot \ell}{6 \cdot B_s \cdot \mu^2} \end{bmatrix}\end{split}\]
class sstatics.core.postprocessing.equation_of_work.EquationOfWork(*a, **k)#

Bases: LoggerMixin

Evaluate the mechanical work equation between two structural systems.

The class forms all contributions of the mechanical work equation between a real system i and a virtual system j. Bar-based terms (bending, shear, normal force, temperature) and node-based terms (elastic supports, imposed displacements) are assembled separately. Matching of bars and nodes is performed via rounded coordinate keys, which also supports the special case of missing bars in one of the systems as occurs in reduction schemes or the force-method.

Parameters:
solution_iFirstOrder

Postprocessing result of the real system.

solution_jFirstOrder

Postprocessing result of the virtual system.

debugbool, optional

Enables extended logging output. Default is False.

Notes

The formulas assume polynomial representations of internal force per bar with coefficient arrays accessible via x_coef and z_coef. Material and section properties are read through the nested attributes of each bar result.

property delta_ij#

Total work interaction between system i and system j.

This value corresponds to the scalar work term

δ_ij = sum(bar terms) + sum(node terms)

and appears for example in reduction methods and the force method.

Returns:
float

The complete mechanical work contribution between both systems.

property logger#

Returns the logger instance associated with this object.

Returns:
logging.Logger

The configured logger.

property work_matrix_bars#

Assemble all bar-wise terms of the mechanical work equation.

For every bar that exists in both systems a 5-component vector is assembled:

[M, N, V, temp_const, temp_delta]

Missing bars in system j yield a zero row. The order of the rows follows the bar ordering of system i.

Returns:
numpy.ndarray

Array of shape (n_bars, 5) containing moment, normal, shear, temperature constant and temperature gradient work contributions.

property work_matrix_nodes#

Assemble all node-wise terms of the mechanical work equation.

For each node present in both systems the following four-component vector is assembled:

[elastic_F, elastic_M, disp_trans, disp_rot]

The method covers elastic support effects (springs in u, w, phi) and imposed displacements. Missing nodes yield a zero row.

Returns:
numpy.ndarray

Array of shape (n_nodes, 4) containing translational and rotational elastic-support work and the imposed-displacement contributions in translations and rotation.

class sstatics.core.postprocessing.rigid_body_motion.RigidBodyDisplacement(bar: sstatics.core.preprocessing.bar.Bar, deform: numpy.ndarray, n_disc: int = 10)#

Bases: object

property deform_disc#

Evaluate rigid body displacements along the bar.

Returns:
numpy.ndarray
A (n, 2) array, where:
  • n is the number of discretization points + 1 (n_disc + 1),

  • Column 0 contains the axial displacement u(x),

  • Column 1 contains the transverse displacement w(x).

u(x) = deform_disc[:, 0] w(x) = deform_disc[:, 1]

property x#

Discrete positions along the bar length for evaluation.

property x_coef#

Coefficients for the rigid axial displacement u(x).

property z_coef#

Coefficients for the rigid transverse displacement w(x).