PREPROCESSING METHODS#
- class sstatics.core.preprocessing.bar.Bar(node_i, node_j, cross_section, material, hinge_u_i=False, hinge_w_i=False, hinge_phi_i=False, hinge_u_j=False, hinge_w_j=False, hinge_phi_j=False, deformations=('moment', 'normal'), line_loads=(), temp=<factory>, point_loads=())#
Bases:
objectCreate a bar for a statical system.
- Parameters:
- node_i
Node Node at the start of the bar.
- node_j
Node Node at the end of the bar.
- cross_section
CrossSection Cross-sectional properties of the bar.
- material
Material Material properties of the bar.
- hinge_u_i
bool, default=False Normal hinge at the start of the bar.
- hinge_w_i
bool, default=False Shear hinge at the start of the bar.
- hinge_phi_i
bool, default=False Moment hinge at the start of the bar.
- hinge_u_j
bool, default=False Normal hinge at the end of the bar.
- hinge_w_j
bool, default=False Shear hinge at the end of the bar.
- hinge_phi_j
bool, default=False Moment hinge at the end of the bar.
- deformations
tuple|list, default=(‘moment’, ‘normal’) Deformation components considered in the calculation. Valid options: “moment”, “normal”, “shear”.
- line_loads
tuple|list, default=() Distributed loads acting on the bar.
- temp
BarTemp, default=(BarTemp(0, 0)) Temperature loads acting on the bar.
- point_loads
tuple|list, default=() Point loads acting on the bar.
- node_i
- Raises:
- ValueError
node_iandnode_jneed to have different locations.- ValueError
There has to be at least one deformation component.
- ValueError
Valid deformation keywords are “moment”, “normal” and “shear”.
- property EA#
Alias of
axial_rigidity.
- property EI#
Alias of
flexural_stiffness.
- property GA_s#
Alias of
shear_stiffness.
- property axial_rigidity#
Calculates the axial rigidity (\(EA\)) of the bar.
The axial rigidity is defined as the product of the Young’s modulus (\(E\)) and the area (\(A\)).
- Returns:
floatThe axial rigidity \(EA\).
Notes
The axial rigidity is given by:
\[EA = E \cdot A\]If the axial deformation component is not to be considered in the calculation (
deformationsdoes not include ‘normal’), the axial rigidity of the bar is scaled to reduce the deformation component so that the axial deformation becomes negligibly small.\[EA = 1000 \cdot E \cdot A\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> 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) >>> b = Bar(n1, n2, cross, mat, deformations=['moment', 'normal']) >>> b.axial_rigidity 1613640.0 >>> b = Bar(n1, n2, cross, mat, deformations=['moment']) >>> b.axial_rigidity 1613640000.0
- f0(hinge_modification=True, to_node_coord=True)#
Represents the vector of internal forces at the beam element ends in the load-deformation state (LDS).
Due to external loads acting on the beam element, internal forces develop at the element ends. These internal forces are assembled in the vector \(f^{(0)'}\).
- Parameters:
- Returns:
numpy.arrayThe 6x1 vector of internal forces at the beam element ends due to external loads.
See also
Notes
The beam element can be subjected to distributed loads and point loads. In statically indeterminate systems, internal forces may also arise due to temperature effects and support deformations. These loading cases are collected within the algorithm.
If hinges are present in the beam, it is necessary to modify the stiffness matrix and load vector to account for discontinuities in deformations at hinge locations.
Finally, the load vector may be transformed into the nodal coordinate system if required.
- property f0_displacement#
Calculates the internal forces due to support stresses related to the local bar coordinate system.
- Returns:
numpy.array6x1 vector of the internal forces due to support stresses.
Notes
The support displacements of the initial and end nodes are combined into a 6x1 vector. By multiplying the stiffness matrix with the acting support displacements, the resulting internal forces are obtained. Since the support displacements are given in the node coordinate system, a transformation using the transformation matrix is required to obtain the internal forces in the bar coordinate system.
The vector is calculated using the following mathematical equations:
\[f^{0'} = k^{'} \cdot \Delta^{'}\]Including the transformation matrix, the following equation is used:
\[\begin{split}f^{0'} = k^{'} \cdot T \cdot \left\lbrace\begin{array}{c} u_i \\ w_i \\ \varphi_i \\ u_j \\ w_j \\ \varphi_j \end{array}\right\rbrace\end{split}\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> from sstatics.core.preprocessing.dof import NodeDisplacement >>> displace = NodeDisplacement(0, 0.005, 0) >>> n1 = Node(0, 0, u='fixed', w='fixed', phi='fixed') >>> n2 = Node(4, 0, w='fixed', displacements=displace) >>> cross = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377) >>> mat = Material(210000000, 0.1, 81000000, 1.2e-5) >>> b = Bar(n1, n2, cross, mat) >>> b.f0_displacement array([[0], [-5.45146875], [10.9029375], [0], [5.45146875], [10.9029375]])
- property f0_line#
Calculates the internal forces due to external line loads related to the local bar coordinate system.
- Returns:
numpy.array6x1 vector of the internal forces due to external loads
Notes
In the calculation of the deformation method, the load deformation state (LDS) of the bar element is considered in addition to unit deformation state (UDS) of the unloaded bar. For common loading conditions, internal forces are tabulated in engineering handbooks. The implemented vector for internal forces due to distributed loads assumes a trapezoidal load distribution. The vector also takes shear deformations into account.
The vector is calculated using the following mathematical equations:
\[\begin{split}f^{0'} = \left\lbrace\begin{array}{c} f_{x,i}^{(0)'} \\\\ f_{z,i}^{(0)'} \\\\ f_{M,i}^{(0)'} \\\\ f_{x,j}^{(0)'} \\\\ f_{z,j}^{(0)'} \\\\ f_{M,j}^{(0)'} \end{array}\right\rbrace = \left\lbrace\begin{array}{c} \dfrac{(7n_i + 3 n_j) \ell}{20} \\\\ \dfrac{(40EIp_j + 80EIp_i + 3GA_s \ell^2 p_j + 7 G A_s \ell^2 p_i) \ell}{240 EI + 20 GA_s \ell^2} \\\\ -\dfrac{(30 EI p_j + 30 EI p_i + 2 GA_s \ell p_j + 3 GA_s \ell^2 p_i) \ell^2}{720EI + 60 GA_s \ell^2} \\\\ -\dfrac{(3n_i + 7 n_j) \ell}{20} \\\\ -\dfrac{(80EIp_j + 40EIp_i + 7GA_s \ell^2 p_j + 3 G A_s \ell^2 p_i) \ell}{240 EI + 20 GA_s \ell^2} \\\\ -\dfrac{(30 EI p_j + 30 EI p_i + 3 GA_s \ell p_j + 2 GA_s \ell^2 p_i) \ell^2}{720EI + 60 GA_s \ell^2} \end{array}\right\rbrace\end{split}\]
- property f0_point#
Calculates the internal forces due to point loads related to the local bar coordinate system.
The method rotates the point load components from the system coordination system into the bar coordination system. Only point load componants at the beginning (position = 0) and at the end (position = 1) of the beam are included.
- Returns:
numpy.array6x1 vector of the rotated point load components.
Notes
The transformation is performed using the following rotation matrix:
\[\begin{split}f^{0'}= \begin{bmatrix} \cos(\alpha- \beta_i) & \sin(\alpha - \beta_i) & 0 & 0 & 0 & 0\\ -\sin(\alpha - \beta_i) & \cos(\alpha - \beta_i) & 0 & 0 & 0 & 0\\ 0 & 0 & 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & \cos(\alpha- \beta_j) & \sin(\alpha - \beta_j) & 0 \\ 0 & 0 & 0 & -\sin(\alpha - \beta_j) & \cos(\alpha - \beta_j) & 0\\ 0 & 0 & 0 & 0 & 0 & 1 \end{bmatrix}^{T} \cdot f^{0}_{load}\end{split}\]
- property f0_temp#
Calculates the internal forces due to temperature loads related to the local bar coordinate system.
- Returns:
numpy.array6x1 vector of the internal forces due to temperature loads.
Notes
The vector is calculated by the following mathmatical equations:
\[\begin{split}f^{0'} = \left\lbrace\begin{array}{c} \alpha_T \cdot T \cdot E \cdot A \\ 0 \\ \dfrac{\alpha_T \cdot \Delta T \cdot E \cdot I}{h} \\ - \alpha_T \cdot T \cdot E \cdot A \\ 0 \\ - \dfrac{\alpha_T \cdot \Delta T \cdot E \cdot I}{h} \end{array}\right\rbrace\end{split}\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> from sstatics.core.preprocessing.temperature import BarTemp >>> n1 = Node(0, 0, u='fixed', w='fixed', phi='fixed') >>> n2 = Node(4, 0, u='fixed', w='fixed', phi='fixed') >>> cross = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377) >>> mat = Material(210000000, 0.1, 81000000, 1.2e-5) >>> temp = BarTemp(15, 30) >>> b = Bar(n1, n2, cross, mat, temp=temp) >>> b.f0_temp array([[435.6828], [0], [5.23341], [-435.6828], [0], [-5.23341]])
- property flexural_stiffness#
Calculates the flexural stiffness (\(EI\)) of the element.
The flexural stiffness is defined as the product of the Young’s modulus (\(E\)) and the second moment of area (moment of inertia, \(I\)) of the cross-section.
- Returns:
floatThe flexural stiffness \(EI\).
Notes
The flexural stiffness is given by:
\[EI = E \cdot I\]If the bending deformation component is not to be considered in the calculation (
deformationsdoes not include ‘moment’), the flexural stiffness of the bar is scaled to reduce the deformation component so that the bending deformation becomes negligibly small.\[EI = 1000 \cdot E \cdot I\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> 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) >>> b = Bar(n1, n2, cross, mat, deformations=['moment', 'normal']) >>> b.flexural_stiffness 5814.900000000001 >>> b = Bar(n1, n2, cross, mat, deformations=['normal']) >>> b.flexural_stiffness 5814900.000000001
- property hinge#
Creates a tuple containing bar hinges at both ends of a structural element.
This method assembles and returns the hinge conditions of a bar at its start node (i) and end node (j). Hinges define how the bar is allowed to move or rotate at its ends.
The tuple consists of six elements representing the hinges at each node:
- Returns:
- tuple
- A 6-tuple containing the hinge parameters in the following order:
hinge_u_i(bool): Normal hinge at node i.hinge_w_i(bool): Shear hinge at node i.hinge_phi_i(bool): Moment hinge at node i.hinge_u_j(bool): Normal at node j.hinge_w_j(bool): Shear hinge at node j.hinge_phi_j(bool): Moment at node j.
Notes
A value of
Trueindicates the presence of a hinge, whileFalseindicates a rigid connection at that degree of freedom.Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> n1 = Node(0, 0, u='fixed', w='fixed', phi='fixed') >>> n2 = Node(4, 0, u='fixed', w='fixed', phi='fixed') >>> cross = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377) >>> mat = Material(210000000, 0.1, 81000000, 0.1) >>> b = Bar(n1, n2, cross, mat, hinge_w_i=True, hinge_phi_j=True) >>> b.hinge (False, True, False, False, False, True)
- property inclination#
Calculates the inclination of the beam in relation to the node coordinates.
- Returns:
floatAngle of inclination in rad.
Notes
The inclination is calcultated by using the following equation:
\[\alpha = \arctan \frac{(-z_2 + z_1)}{(x_2 - x_1)}\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> node_1 = Node(0, 0) >>> node_2 = Node(4, -2) >>> cross_sec = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377) >>> material = Material(210000000, 0.1, 81000000, 0.1) >>> bar_1 = Bar(node_1, node_2, cross_sec, material) >>> bar_1.inclination 0.7853981634
- property length#
Calculates the distance between two nodes that define the bar element.
- Returns:
floatLength of bar element.
Notes
The length is calcultated by using the following equation:
\[L = \sqrt{(x_2 - x_1)^2 + (z_2 - z_1)^2}\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> node_1 = Node(2, 5) >>> node_2 = Node(10, 6) >>> cross_sec = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377) >>> material = Material(210000000, 0.1, 81000000, 0.1) >>> bar_1 = Bar(node_1, node_2, cross_sec, material) >>> bar_1.length 8.06225774829855
- property line_load#
The overall line load on a bar element as a 6x1 vector.
- Returns:
numpy.arraySum of all line loads specified in
line_loads.
See also
Notes
If no line loads are specified, then a 6x1 zero vector is returned. The load components are rotated by the inclination of the beam.
Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> node_1 = Node(0, 0) >>> node_2 = Node(3, -4) >>> cross_sec = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377) >>> material = Material(210000000, 0.1, 81000000, 0.1) >>> Bar(node_1, node_2, cross_sec, material).line_load array([[0], [0], [0], [0], [0], [0]])
>>> from sstatics.core.preprocessing.loads import BarLineLoad >>> line_loads = (BarLineLoad(1, 1, 'z', 'bar', 'exact'), >>> BarLineLoad(2, 3, 'x', 'system', 'proj')) >>> Bar(node_1, node_2, cross_sec, material, >>> line_loads=line_loads).line_load array([[0.96], [2.28], [0], [1.44], [2.92], [0]])
- property phi#
Calculates the stiffness contributions of shear deformation.
- Returns:
floatStiffness contributions of shear deformation.
Notes
\[\phi = \dfrac{12 \cdot E \cdot I}{GA_s \cdot \ell^2}\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> 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) >>> b = Bar(n1, n2, cross, mat) >>> b.phi 0.0007499999999999999 >>> b = Bar(n1, n2, cross, mat, deformations=['moment', 'shear']) >>> b.phi 0.011165837860598733
- property point_load#
The overall point load on a bar element as a 6x1 vector.
- Returns:
numpy.arraySum of all point loads specified in
point_loads.
See also
Notes
If no point loads are specified, then a 6x1 zero vector is returned.
Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> node_1 = Node(0, 0) >>> node_2 = Node(3, 0) >>> cross_sec = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377) >>> material = Material(210000000, 0.1, 81000000, 0.1) >>> Bar(node_1, node_2, cross_sec, material).point_load array([[0], [0], [0], [0], [0], [0]])
>>> from sstatics.core.preprocessing.loads import BarPointLoad >>> import numpy >>> point_loads = (BarPointLoad(1, 0, 0), >>> BarPointLoad(0, 2, numpy.pi/4, position=1)) >>> Bar(node_1, node_2, cross_sec, material, >>> point_loads=point_loads).point_load array([[1], [0], [0], [1.41421356], [1.41421356], [0]])
- property shear_stiffness#
Calculates the shear stiffness (\(GA_s\)) of the bar.
The shear stiffness is calculated using the shear modulus (\(G\)) and the shear area (\(A_s\)). The modification of the shear area (\(A_s\)) compared to the cross-sectional area (\(A\)) is taken into account using the shear correction factor (\(\kappa\)).
- Returns:
floatThe shear stiffness \(GA_s\).
Notes
The shear stiffness is given by:
\[GA_s = G \cdot A \cdot \kappa\]If the shear deformation component is not to be considered in the calculation (
deformationsdoes not include ‘shear’), the flexural stiffness of the bar is scaled to reduce the deformation component so that the shear deformation becomes negligibly small.\[GA_s = 1000 \cdot EI\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> 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) >>> b = Bar(n1, n2, cross, mat, deformations=['moment', 'normal']) >>> b.shear_stiffness 5814900.000000001 >>> b = Bar(n1, n2, cross, mat, deformations=['moment', 'shear']) >>> b.shear_stiffness 390581.97463079996
- stiffness_matrix(hinge_modification=True, to_node_coord=True)#
Represents the element stiffness matrix for the beam element \(k^{'}\).
The element stiffness matrix defines the relationship between nodal displacements and rotations of a beam element and the resulting internal forces at its ends.
- Parameters:
- Returns:
numpy.arrayThe 6x6 matrix representing the element stiffness matrix.
See also
Notes
The element stiffness matrix is symmetric and depends on the order of calculation and the applied approach. If the beam is shear-flexible, the shear component is included in the matrix.
The general form of the element stiffness matrix \(k^{'}\) for a shear-rigid beam is:
\[\begin{split}k^{'} = \left[\begin{array}{rrr|rrr} \dfrac{EA}{\ell} & 0 & 0 & -\dfrac{EA}{\ell} & 0 & 0 \\ 0 & \dfrac{12EI}{\ell^3} & -\dfrac{6EI}{\ell^2} & 0 & -\dfrac{12EI}{\ell^3} & -\dfrac{6EI}{\ell^2} \\ 0 & -\dfrac{6EI}{\ell^2} & \dfrac{4EI}{\ell} & 0 & \dfrac{6EI}{\ell^2} & \dfrac{2EI}{\ell} \\ \hline -\dfrac{EA}{\ell} & 0 & 0 & \dfrac{EA}{\ell} & 0 & 0 \\ 0 & -\dfrac{12EI}{\ell^3} & \dfrac{6EI}{\ell^2} & 0 & \dfrac{12EI}{\ell^3} & \dfrac{6EI}{\ell^2} \\ 0 & -\dfrac{6EI}{\ell^2} & \dfrac{2EI}{\ell} & 0 & \dfrac{6EI}{\ell^2} & \dfrac{4EI}{\ell} \\ \end{array}\right]\end{split}\]If hinges are present in the beam, it is necessary to modify the stiffness matrix to account for discontinuities in deformations at hinge locations.
Finally, the stiffness matrix may be transformed into the nodal coordinate system if required.
- property stiffness_shear_force#
Computes the element stiffness matrix considering shear effects.
- Returns:
numpy.arrayA 6x6 matrix representing the element stiffness matrix according to first-order theory, including shear effects.
Notes
The element stiffness matrix accounts for the deformation components of the beam due to axial force, bending, and shear. The factor
phidescribes the influence of shear deformation.The general form of the element stiffness matrix \(k^{'}\) is given by:
\[\begin{split}k^{'} = \left[\begin{array}{rrr|rrr} \dfrac{EA}{\ell} & 0 & 0 & -\dfrac{EA}{\ell} & 0 & 0 \\ 0 & \dfrac{12EI}{\ell^3 ( 1 + \phi)} & -\dfrac{6EI}{\ell^2 (1 + \phi)} & 0 & -\dfrac{12EI}{\ell^3(1 + \phi)} & - \dfrac{6EI}{\ell^2(1 + \phi)} \\ 0 & -\dfrac{6EI}{\ell^2(1 + \phi)} & \dfrac{EI(4 + \phi)}{\ell (1 + \phi)} & 0 & \dfrac{6EI}{\ell^2(1 + \phi)} & \dfrac{EI(2 - \phi)}{\ell(1 + \phi)} \\ \hline -\dfrac{EA}{\ell} & 0 & 0 & \dfrac{EA}{\ell} & 0 & 0 \\ 0 & -\dfrac{12EI}{\ell^3(1 + \phi)} & \dfrac{6EI}{\ell^2(1 + \phi)} & 0 & \dfrac{12EI}{\ell^3(1 + \phi)} & \dfrac{6EI} {\ell^2(1 + \phi)} \\ 0 & -\dfrac{6EI}{\ell^2(1 + \phi)} & \dfrac{EI(2 - \phi)}{\ell (1 + \phi)} & 0 & \dfrac{6EI}{\ell^2(1 + \phi)} & \dfrac{EI(4 + \phi)}{\ell(1 + \phi)} \\ \end{array}\right]\end{split}\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> from sstatics.core.preprocessing.loads import BarLineLoad >>> n1, n2 = Node(0, 0), Node(0, -4) >>> cross = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377) >>> material = Material(210000000, 0.1, 81000000, 0.1) >>> deform = ['moment', 'normal', 'shear'] >>> b = Bar(n1, n2, cross, material, deformations=deform) >>> b.stiffness_shear_force array([[1, 0, 0, 1, 0, 0], [0, 0.9889574613, 0.9889574613, 0, 0.9889574613, 0.9889574613], [0, 0.9889574613, 0.991718096, 0, 0.9889574613, 0.983436192], [1, 0, 0, 1, 0, 0], [0, 0.9889574613, 0.9889574613, 0, 0.9889574613, 0.9889574613], [0, 0.9889574613, 0.983436192, 0, 0.9889574613, 0.991718096]])
- transformation_matrix(to_node_coord=True)#
Create a 6x6 rotation matrix based on the bar’s inclination and node components.
- Parameters:
- to_node_coord
bool, default=True Determines whether a transformation into the node coordinate system takes place.
Trueif transformation to the node coordinate system is applied.Falseif the transformation is not applied.
- to_node_coord
- Returns:
numpy.arrayA 6x6 matrix for rotating 6x1 vectors.
Notes
If the transformation to the node coordinate system is not applied, the rotation angle is determined solely by the inclination of the bar:
alpha = bar.inclination.If the transformation to the node coordinate system is applied, the rotation is calculated by subtracting the node rotations from the bar inclination:
alpha_i = bar.inclination - bar.node_i.rotationalpha_j = bar.inclination - bar.node_j.rotationThe resulting matrix has the form
\[\begin{split}\left[\begin{array}{cccccc} \cos(\alpha_i) & \sin(\alpha_i) & 0 & 0 & 0 & 0\\ -\sin(\alpha_i) & \cos(\alpha_i) & 0 & 0 & 0 & 0\\ 0 & 0 & 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & \cos(\alpha_j) & \sin(\alpha_j) & 0 \\ 0 & 0 & 0 & -\sin(\alpha_j) & \cos(\alpha_j) & 0 \\ 0 & 0 & 0 & 0 & 0 & 1 \end{array}\right]\end{split}\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> import numpy >>> node_1 = Node(0, 0, rotation=numpy.pi/4) >>> node_2 = Node(4, -3) >>> cross_sec = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377) >>> material = Material(210000000, 0.1, 81000000, 0.1) >>> bar = Bar(node_1, node_2, cross_sec, material) >>> bar.transformation_matrix() array([[0.98994949, -0.14142136, 0., 0., 0., 0.], [0.14142136, 0.98994949, 0., 0., 0., 0.], [0., 0., 1., 0., 0., 0.], [0., 0., 0., 0.8, 0.6, 0.], [0., 0., 0., -0.6, 0.8, 0.], [0., 0., 0., 0., 0., 1.]]) >>> bar.transformation_matrix(False) array([[0.8, 0.6, 0., 0., 0., 0.], [-0.6, 0.8, 0., 0., 0., 0.], [0., 0., 1., 0., 0., 0.], [0., 0., 0., 0.8, 0.6, 0.], [0., 0., 0., -0.6, 0.8, 0.], [0., 0., 0., 0., 0., 1.]])
- class sstatics.core.preprocessing.bar.BarSecond(node_i, node_j, cross_section, material, hinge_u_i=False, hinge_w_i=False, hinge_phi_i=False, hinge_u_j=False, hinge_w_j=False, hinge_phi_j=False, deformations=('moment', 'normal'), line_loads=(), temp=<factory>, point_loads=(), approach='analytic', f_axial=0)#
Bases:
BarCreate a bar for a statical system for the second order matrix approach.
- Parameters:
- node_i
Node Node at the start of the bar.
- node_j
Node Node at the end of the bar.
- cross_section
CrossSection Cross-sectional properties of the bar.
- material
Material Material properties of the bar.
- hinge_u_i
bool, default=False Normal hinge at the start of the bar.
- hinge_w_i
bool, default=False Shear hinge at the start of the bar.
- hinge_phi_i
bool, default=False Moment hinge at the start of the bar.
- hinge_u_j
bool, default=False Normal hinge at the end of the bar.
- hinge_w_j
bool, default=False Shear hinge at the end of the bar.
- hinge_phi_j
bool, default=False Moment hinge at the end of the bar.
- deformations
tuple|list, default=(‘moment’, ‘normal’) Deformation components considered in the calculation. Valid options: “moment”, “normal”, “shear”.
- line_loads
tuple|list, default=() Distributed loads acting on the bar.
- temp
BarTemp, default=(BarTemp(0, 0)) Temperature loads acting on the bar.
- point_loads
tuple|list, default=() Point loads acting on the bar.
- approach{‘analytic’, ‘taylor’, ‘p_delta’}, default=’analytic’
Selects the second-order formulation for the modified stiffness:
'analytic'Closed-form exact geometric stiffness effects.'p_delta'P–Δ geometric stiffness formulation.'taylor'Taylor-series expansion
- f_axial:any`float`, default=0
The axial force (\(L\)) applied to the beam element, which is obtained from the internal force results of the first-order theory.
- node_i
- Raises:
- ValueError
node_iandnode_jneed to have different locations.- ValueError
There has to be at least one deformation component.
- ValueError
Valid deformation keywords are “moment”, “normal” and “shear”.
- property B_s#
Alias of
modified_flexural_stiffness.
- property EA#
- property EI#
- property GA_s#
- property axial_rigidity#
Calculates the axial rigidity (\(EA\)) of the bar.
The axial rigidity is defined as the product of the Young’s modulus (\(E\)) and the area (\(A\)).
- Returns:
floatThe axial rigidity \(EA\).
Notes
The axial rigidity is given by:
\[EA = E \cdot A\]If the axial deformation component is not to be considered in the calculation (
deformationsdoes not include ‘normal’), the axial rigidity of the bar is scaled to reduce the deformation component so that the axial deformation becomes negligibly small.\[EA = 1000 \cdot E \cdot A\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> 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) >>> b = Bar(n1, n2, cross, mat, deformations=['moment', 'normal']) >>> b.axial_rigidity 1613640.0 >>> b = Bar(n1, n2, cross, mat, deformations=['moment']) >>> b.axial_rigidity 1613640000.0
- property characteristic_number#
Returns the characteristic number \(\mu\) of the beam element.
This dimensionless characteristic number integrates both the bending and shear stiffness as well as the axial force in the beam. It is used in the correction functions applied in the calculation of the load vector and stiffness matrix based on the analytical approach of second-order theory.
- Returns:
floatThe dimensionless characteristic number \(\mu\).
Notes
It should be noted that the correction functions are not defined at \(\mu = 0\), which may lead to numerical instabilities in this range.
The characteristic number is defined by the following equation:
\[\mu = \sqrt{\dfrac{\mid L \mid}{B_s}} \cdot \ell\]
- f0(hinge_modification=True, to_node_coord=True)#
Represents the vector of internal forces at the beam element ends in the load-deformation state (LDS).
Due to external loads acting on the beam element, internal forces develop at the element ends. These internal forces are assembled in the vector \(f^{(0)'}\).
- Parameters:
- Returns:
numpy.arrayThe 6x1 vector of internal forces at the beam element ends due to external loads.
See also
Notes
The beam element can be subjected to distributed loads and point loads. In statically indeterminate systems, internal forces may also arise due to temperature effects and support deformations. These loading cases are collected within the algorithm.
If hinges are present in the beam, it is necessary to modify the stiffness matrix and load vector to account for discontinuities in deformations at hinge locations.
Finally, the load vector may be transformed into the nodal coordinate system if required.
- property f0_displacement#
Calculates the internal forces due to support stresses related to the local bar coordinate system.
- Returns:
numpy.array6x1 vector of the internal forces due to support stresses.
Notes
The support displacements of the initial and end nodes are combined into a 6x1 vector. By multiplying the stiffness matrix with the acting support displacements, the resulting internal forces are obtained. Since the support displacements are given in the node coordinate system, a transformation using the transformation matrix is required to obtain the internal forces in the bar coordinate system.
The vector is calculated using the following mathematical equations:
\[f^{0'} = k^{'} \cdot \Delta^{'}\]Including the transformation matrix, the following equation is used:
\[\begin{split}f^{0'} = k^{'} \cdot T \cdot \left\lbrace\begin{array}{c} u_i \\ w_i \\ \varphi_i \\ u_j \\ w_j \\ \varphi_j \end{array}\right\rbrace\end{split}\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> from sstatics.core.preprocessing.dof import NodeDisplacement >>> displace = NodeDisplacement(0, 0.005, 0) >>> n1 = Node(0, 0, u='fixed', w='fixed', phi='fixed') >>> n2 = Node(4, 0, w='fixed', displacements=displace) >>> cross = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377) >>> mat = Material(210000000, 0.1, 81000000, 1.2e-5) >>> b = Bar(n1, n2, cross, mat) >>> b.f0_displacement array([[0], [-5.45146875], [10.9029375], [0], [5.45146875], [10.9029375]])
- property f0_line#
Calculates the internal forces due to external line loads related to the local bar coordinate system.
This method computes the load vector associated with external line loads and adjusts it according to the selected second-order analysis approach. If a second-order method is selected but the axial force
f_axialis zero, the modified stiffness terms cannot be evaluated and the load vector from first-order theory is returned instead.If the selected analysis approach requires
f_axialbut it is undefined or set to zero, the method falls back to the first-order load vector, since second-order effects cannot be computed in that case.- Returns:
numpy.array6x1 vector of the internal forces due to external loads
- property f0_line_analytic#
Calculates the internal forces due to external line loads related to the local bar coordinate system for the analytical solution of the second-order theory.
To calculate the internal forces for the second-order theory, this function considers the particular solution while taking into account the axial force \(L\) in the beam element.
- Returns:
numpy.array6x1 vector of the internal forces due to external loads for the analytical solution of the second-order theory.
Notes
The application of continuous element loads can generate full constraint forces in the base element. This function calculates the particular solution of the deformation line according to the second-order theory. The particular solution is determined separately for positive and negative axial forces \(L\), which are evaluated based on the input parameter.
For negative axial forces, the internal forces are given by:
\[\begin{split}f^{0'} = \left\lbrace\begin{array}{c} -\dfrac{(7n_i + 3 n_j) \ell}{20} \\ -\dfrac{B_s \mu^2}{\ell^2} \cdot c_2 - [\dfrac{\ell}{\mu^2} + \dfrac{EI}{GA_s \ell}] (p_j - p_i) \\ \dfrac{B_s \mu^2}{\ell^2} \cdot c_3 - [\dfrac{\ell^2}{\mu^2} + \dfrac{EI}{GA_s}] \cdot p_i \\ \dfrac{(3n_i + 7 n_j) \ell}{20} \\ -\dfrac{B_s \mu^2}{\ell^2} \cdot c_2 - p_i \cdot \ell - [\dfrac{\ell}{\mu^2} + \dfrac{EI}{GA_s \ell} + \dfrac{\ell}{2}] (p_j - p_i) \\ \dfrac{B_s \mu^2}{\ell^2} [c_3 \cdot \cos (\mu) + c_4 \cdot \sin ( \mu)] - [\dfrac{\ell^2}{\mu^2} + \dfrac{EI}{GA_s}] \cdot p_j \end{array}\right\rbrace\end{split}\]with the coefficients:
\[\begin{split}\begin{array}{ll} c_1 = \dfrac{\ell^2}{6 B_s \mu^3} \cdot & \bigg(\dfrac{3 \big[ GA_s \ell^4 + 2 B_s \ell^2 \mu^2 + \frac{B_{s}^2}{GA_s} \mu^4 \big] \sinh (\mu) (p_i + p_j)} {GA_s \ell^2 \mu \sin (\mu) + 2 [GA_s \ell^2 + B_s \mu^2] (\cos ( \mu) - 1)}\\\\ & + \dfrac{6 EI \ell^2 \mu (1- \cos ( \mu)) (p_i - p_j)}{GA_s \ell^2 \mu \sin (\mu) + 2 [GA_s \ell^2 + B_s \mu^2] (\cos ( \mu) - 1)} \\\\ & + \dfrac{[B_s \ell^2 \mu^3 + GA_s \ell^4 \mu] [p_i + 2 p_j + (2 p_i + p_j) \cos (\mu)]}{GA_s \ell^2 \mu \sin (\mu) + 2 [GA_s \ell^2 + B_s \mu^2] (\cos ( \mu) - 1)}\bigg) \end{array}\end{split}\]\[\begin{split}\begin{array}{ll} c_2 = -\dfrac{\ell^3}{6 B_s \mu^3} \cdot & \bigg(\dfrac{12 EI ( 1- \cos ( \mu)) (p_i - p_j) + GA_s \ell^2 \mu \sin (\mu) (2 p_i + p_j)} {GA_s \ell^2 \mu \sin (\mu) + 2 [GA_s \ell^2 + B_s \mu^2] (\cos ( \mu) - 1)}\\\\ & - \dfrac{3 (GA_s \ell^2 + B_s \mu^2) (1 - \cos ( \mu)) (p_i + p_j)}{GA_s \ell^2 \mu \sin (\mu) + 2 [GA_s \ell^2 + B_s \mu^2] (\cos ( \mu) - 1))}\bigg) \end{array}\end{split}\]\[c_3 = - c_1\]\[c_4 = -\bigg[ \dfrac{B_s \mu}{G A_s \ell} + \dfrac{\ell}{\mu} \bigg] \cdot c_2 - \dfrac{EI \ell^2 ( p_j - p_i)}{B_s GA_s \mu^3}\]For positive axial forces, the internal forces are given by:
\[\begin{split}f^{0'} = \left\lbrace\begin{array}{c} -\dfrac{(7n_i + 3 n_j) \ell}{20} \\ \dfrac{B_s \mu^2}{\ell^2} \cdot c_2 + [\dfrac{\ell}{\mu^2} - \dfrac{EI}{GA_s \ell}] (p_j - p_i) \\ -\dfrac{B_s \mu^2}{\ell^2} \cdot c_3 + [\dfrac{\ell^2}{\mu^2} - \dfrac{EI}{GA_s}] \cdot p_i \\ \dfrac{(3n_i + 7 n_j) \ell}{20} \\ -\dfrac{B_s \mu^2}{\ell^2} \cdot c_2 - \dfrac{(p_j + p_i) \ell}{2} + [\dfrac{\ell}{\mu^2} + \dfrac{EI}{GA_s \ell}] (p_j - p_i) \\ -B_s \cdot [c_3 \cdot \dfrac{\mu^2}{\ell^2} \cosh (\mu) + c_4 \cdot \dfrac{\mu^2}{\ell^2} \sinh ( \mu)] + [\dfrac{\ell^2} {\mu^2} - \dfrac{EI}{GA_s}] \cdot p_j \end{array}\right\rbrace\end{split}\]with the coefficients:
\[\begin{split}\begin{array}{ll} c_1 = \dfrac{\ell^2}{6 B_s \mu^3} \cdot & \bigg(\dfrac{3 \big[GA_s \ell^4 - 2 B_s \ell^2 \mu^2 + \frac{B_{s}^2}{GA_s} \mu^4 \big] \sinh (\mu) (p_i + p_j)}{2 [GA_s \ell^2 - B_s \mu^2] (1- \cosh (\mu)) + GA_s \ell^2 \mu \sinh(\mu)}\\\\ & + \dfrac{6 EI \ell^2 \mu (1- \cosh ( \mu)) (p_i - p_j)}{2 [GA_s \ell^2 - B_s \mu^2] (1- \cosh (\mu)) + GA_s \ell^2 \mu \sinh(\mu)} \\\\ & + \dfrac{[B_s \ell^2 \mu^3 - GA_s \ell^4 \mu] [p_i + 2 p_j + (2 p_i + p_j) \cosh (\mu)]}{2 [GA_s \ell^2 - B_s \mu^2] (1- \cosh (\mu)) + GA_s \ell^2 \mu \sinh(\mu)}\bigg) \end{array}\end{split}\]\[\begin{split}\begin{array}{ll} c_2 = -\dfrac{\ell^3}{6 B_s \mu^3} \cdot & \bigg(\dfrac{12 EI ( 1- \cosh ( \mu)) (p_i - p_j) - GA_s \ell^2 \mu \sinh (\mu) (2 p_i + p_j)} {2 [GA_s \ell^2 - B_s \mu^2] (1- \cosh (\mu)) + GA_s \ell^2 \mu \sinh(\mu)}\\\\ & - \dfrac{3 (GA_s \ell^2 - B_s \mu^2) (1 - \cosh ( \mu)) (p_i + p_j)}{2 [GA_s \ell^2 - B_s \mu^2] (1- \cosh (\mu)) + GA_s \ell^2 \mu \sinh(\mu)}\bigg) \end{array}\end{split}\]\[c_3 = - c_1\]\[c_4 = \bigg[ \dfrac{B_s \mu}{G A_s \ell} - \dfrac{\ell}{\mu} \bigg] \cdot c_2 + \dfrac{EI \ell^2 ( p_j - p_i)}{B_s GA_s \mu^3}\]
- property f0_line_taylor#
Calculates the internal forces due to external line loads related to the local bar coordinate system for the Taylor series expansion of the second-order theory.
To calculate the internal forces for the second-order theory, this function considers the Taylor series expansion while taking into account the axial force \(L\) in the beam element.
- Returns:
numpy.array6x1 vector of the internal forces due to external loads for the Taylor series expansion of the second-order theory.
Notes
The application of continuous element loads can generate full constraint forces in the base element. This function calculates the internal forces by using a Taylor series expansion according to the second-order theory.
The vector is calculated by the following mathmatical equations:
\[\begin{split}\begin{array}{ll} f_{z,i}^{(0)'} = \dfrac{\ell}{20} \cdot & \bigg(\dfrac{720 B_{s}^2 (p_j + p_i) - 4 EIGA_s \ell^2 (p_j - p_i) + 20 B_s GA_s \ell^2 ( 5 p_j + 7 p_i)}{(12 B_s + GA_s \ell^2)^2}\\\\ & \dfrac{(GA_s)^2 \ell^4 (3 p_j + 7 p_i)}{(12 B_s + GA_s \ell^2)^2} - \dfrac{EI (p_j - p_i)}{GA_s \ell} - \dfrac{12 B_s}{L \ell} \cdot \dfrac{(EI - B_s) (p_j - p_i)}{(12 B_s + GA_s \ell^2)}\bigg) \end{array}\end{split}\]\[\begin{split}\begin{array}{ll} f_{M,i}^{(0)'} = & \dfrac{4320 B_{s}^3(p_j + p_i) + 6 EI (GA_s)^2 \ell^4 (p_j- p_i) + 60 B_s GA_s \ell^2 (12B_s p_i - GA_s \ell^2 p_j)}{60 GA_s (12 B_s + GA_s \ell^2)^2}\\\\ & - \dfrac{(GA_s)^3 \ell^6 (2p_j + 3 p_i)}{60 GA_s (12 B_s + GA_s \ell^2)^2} - \dfrac{EI}{GA_s} \cdot p_i + \dfrac{6 B_s}{L} \cdot \dfrac{(EI - B_s) ( p_j - p_i)} {(12 B_s + GA_s \ell^2)} \end{array}\end{split}\]\[f_{z,j}^{(0)'} = f_{z,i}^{(0)'} - \dfrac{(p_j + p_i) \cdot \ell}{2}\]\[\begin{split}\begin{array}{ll} f_{M,j}^{(0)'} = & \dfrac{4320 B_{s}^3(p_j + p_i) - 6 EI (GA_s)^2 \ell^4 (p_j- p_i) + 60 B_s GA_s \ell^2 (12B_s p_j - GA_s \ell^2 p_i)}{60 GA_s (12 B_s + GA_s \ell^2)^2}\\\\ & - \dfrac{(GA_s)^3 \ell^6 (3p_j + 2 p_i)}{60 GA_s (12 B_s + GA_s \ell^2)^2} - \dfrac{EI}{GA_s} \cdot p_j - \dfrac{6 B_s} {L} \cdot \dfrac{(EI - B_s) ( p_j - p_i)}{(12 B_s + GA_s \ell^2)} \end{array}\end{split}\]\[\begin{split}f^{0'} = \left\lbrace\begin{array}{c} -\dfrac{(7n_i + 3 n_j) \ell}{20} \\\\ -f_{z,i}^{(0)'} \\\\ -f_{M,i}^{(0)'} \\\\ -\dfrac{(3n_i + 7 n_j) \ell}{20}\\\\ f_{z,j}^{(0)'}\\\\ f_{M,j}^{(0)'} \end{array}\right\rbrace\end{split}\]
- property f0_point#
Calculates the internal forces due to point loads related to the local bar coordinate system.
The method rotates the point load components from the system coordination system into the bar coordination system. Only point load componants at the beginning (position = 0) and at the end (position = 1) of the beam are included.
- Returns:
numpy.array6x1 vector of the rotated point load components.
Notes
The transformation is performed using the following rotation matrix:
\[\begin{split}f^{0'}= \begin{bmatrix} \cos(\alpha- \beta_i) & \sin(\alpha - \beta_i) & 0 & 0 & 0 & 0\\ -\sin(\alpha - \beta_i) & \cos(\alpha - \beta_i) & 0 & 0 & 0 & 0\\ 0 & 0 & 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & \cos(\alpha- \beta_j) & \sin(\alpha - \beta_j) & 0 \\ 0 & 0 & 0 & -\sin(\alpha - \beta_j) & \cos(\alpha - \beta_j) & 0\\ 0 & 0 & 0 & 0 & 0 & 1 \end{bmatrix}^{T} \cdot f^{0}_{load}\end{split}\]
- property f0_temp#
Calculates the internal forces due to temperature loads related to the local bar coordinate system.
- Returns:
numpy.array6x1 vector of the internal forces due to temperature loads.
Notes
The vector is calculated by the following mathmatical equations:
\[\begin{split}f^{0'} = \left\lbrace\begin{array}{c} \alpha_T \cdot T \cdot E \cdot A \\ 0 \\ \dfrac{\alpha_T \cdot \Delta T \cdot E \cdot I}{h} \\ - \alpha_T \cdot T \cdot E \cdot A \\ 0 \\ - \dfrac{\alpha_T \cdot \Delta T \cdot E \cdot I}{h} \end{array}\right\rbrace\end{split}\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> from sstatics.core.preprocessing.temperature import BarTemp >>> n1 = Node(0, 0, u='fixed', w='fixed', phi='fixed') >>> n2 = Node(4, 0, u='fixed', w='fixed', phi='fixed') >>> cross = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377) >>> mat = Material(210000000, 0.1, 81000000, 1.2e-5) >>> temp = BarTemp(15, 30) >>> b = Bar(n1, n2, cross, mat, temp=temp) >>> b.f0_temp array([[435.6828], [0], [5.23341], [-435.6828], [0], [-5.23341]])
- property flexural_stiffness#
Calculates the flexural stiffness (\(EI\)) of the element.
The flexural stiffness is defined as the product of the Young’s modulus (\(E\)) and the second moment of area (moment of inertia, \(I\)) of the cross-section.
- Returns:
floatThe flexural stiffness \(EI\).
Notes
The flexural stiffness is given by:
\[EI = E \cdot I\]If the bending deformation component is not to be considered in the calculation (
deformationsdoes not include ‘moment’), the flexural stiffness of the bar is scaled to reduce the deformation component so that the bending deformation becomes negligibly small.\[EI = 1000 \cdot E \cdot I\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> 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) >>> b = Bar(n1, n2, cross, mat, deformations=['moment', 'normal']) >>> b.flexural_stiffness 5814.900000000001 >>> b = Bar(n1, n2, cross, mat, deformations=['normal']) >>> b.flexural_stiffness 5814900.000000001
- property hinge#
Creates a tuple containing bar hinges at both ends of a structural element.
This method assembles and returns the hinge conditions of a bar at its start node (i) and end node (j). Hinges define how the bar is allowed to move or rotate at its ends.
The tuple consists of six elements representing the hinges at each node:
- Returns:
- tuple
- A 6-tuple containing the hinge parameters in the following order:
hinge_u_i(bool): Normal hinge at node i.hinge_w_i(bool): Shear hinge at node i.hinge_phi_i(bool): Moment hinge at node i.hinge_u_j(bool): Normal at node j.hinge_w_j(bool): Shear hinge at node j.hinge_phi_j(bool): Moment at node j.
Notes
A value of
Trueindicates the presence of a hinge, whileFalseindicates a rigid connection at that degree of freedom.Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> n1 = Node(0, 0, u='fixed', w='fixed', phi='fixed') >>> n2 = Node(4, 0, u='fixed', w='fixed', phi='fixed') >>> cross = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377) >>> mat = Material(210000000, 0.1, 81000000, 0.1) >>> b = Bar(n1, n2, cross, mat, hinge_w_i=True, hinge_phi_j=True) >>> b.hinge (False, True, False, False, False, True)
- property inclination#
Calculates the inclination of the beam in relation to the node coordinates.
- Returns:
floatAngle of inclination in rad.
Notes
The inclination is calcultated by using the following equation:
\[\alpha = \arctan \frac{(-z_2 + z_1)}{(x_2 - x_1)}\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> node_1 = Node(0, 0) >>> node_2 = Node(4, -2) >>> cross_sec = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377) >>> material = Material(210000000, 0.1, 81000000, 0.1) >>> bar_1 = Bar(node_1, node_2, cross_sec, material) >>> bar_1.inclination 0.7853981634
- property length#
Calculates the distance between two nodes that define the bar element.
- Returns:
floatLength of bar element.
Notes
The length is calcultated by using the following equation:
\[L = \sqrt{(x_2 - x_1)^2 + (z_2 - z_1)^2}\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> node_1 = Node(2, 5) >>> node_2 = Node(10, 6) >>> cross_sec = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377) >>> material = Material(210000000, 0.1, 81000000, 0.1) >>> bar_1 = Bar(node_1, node_2, cross_sec, material) >>> bar_1.length 8.06225774829855
- property line_load#
The overall line load on a bar element as a 6x1 vector.
- Returns:
numpy.arraySum of all line loads specified in
line_loads.
See also
Notes
If no line loads are specified, then a 6x1 zero vector is returned. The load components are rotated by the inclination of the beam.
Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> node_1 = Node(0, 0) >>> node_2 = Node(3, -4) >>> cross_sec = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377) >>> material = Material(210000000, 0.1, 81000000, 0.1) >>> Bar(node_1, node_2, cross_sec, material).line_load array([[0], [0], [0], [0], [0], [0]])
>>> from sstatics.core.preprocessing.loads import BarLineLoad >>> line_loads = (BarLineLoad(1, 1, 'z', 'bar', 'exact'), >>> BarLineLoad(2, 3, 'x', 'system', 'proj')) >>> Bar(node_1, node_2, cross_sec, material, >>> line_loads=line_loads).line_load array([[0.96], [2.28], [0], [1.44], [2.92], [0]])
- property modified_flexural_stiffness#
Computes the modified flexural stiffness (\(B_s\)) based on second-order theory , considering both shear deformations and axial force effects.
The modified flexural stiffness \(B_s\) accounts for shear deformations and the influence of axial force on the beam element.
- Returns:
floatThe modified flexural stiffness \(B_s\).
Notes
The modified flexural stiffness is calculated [1] :
\[B_s = EI \cdot ( 1 + \dfrac{L}{GA_s})\]References
[1]Spura, Christian: Einführung in die Balkentheorie nach Timoshenko und Euler-Bernoulli. Springer Vieweg, 2019 https://doi.org/10.1007/978-3-658-25216-8
- property phi#
Calculates the stiffness contributions of shear deformation.
- Returns:
floatStiffness contributions of shear deformation.
Notes
\[\phi = \dfrac{12 \cdot E \cdot I}{GA_s \cdot \ell^2}\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> 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) >>> b = Bar(n1, n2, cross, mat) >>> b.phi 0.0007499999999999999 >>> b = Bar(n1, n2, cross, mat, deformations=['moment', 'shear']) >>> b.phi 0.011165837860598733
- property point_load#
The overall point load on a bar element as a 6x1 vector.
- Returns:
numpy.arraySum of all point loads specified in
point_loads.
See also
Notes
If no point loads are specified, then a 6x1 zero vector is returned.
Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> node_1 = Node(0, 0) >>> node_2 = Node(3, 0) >>> cross_sec = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377) >>> material = Material(210000000, 0.1, 81000000, 0.1) >>> Bar(node_1, node_2, cross_sec, material).point_load array([[0], [0], [0], [0], [0], [0]])
>>> from sstatics.core.preprocessing.loads import BarPointLoad >>> import numpy >>> point_loads = (BarPointLoad(1, 0, 0), >>> BarPointLoad(0, 2, numpy.pi/4, position=1)) >>> Bar(node_1, node_2, cross_sec, material, >>> point_loads=point_loads).point_load array([[1], [0], [0], [1.41421356], [1.41421356], [0]])
- property shear_stiffness#
Calculates the shear stiffness (\(GA_s\)) of the bar.
The shear stiffness is calculated using the shear modulus (\(G\)) and the shear area (\(A_s\)). The modification of the shear area (\(A_s\)) compared to the cross-sectional area (\(A\)) is taken into account using the shear correction factor (\(\kappa\)).
- Returns:
floatThe shear stiffness \(GA_s\).
Notes
The shear stiffness is given by:
\[GA_s = G \cdot A \cdot \kappa\]If the shear deformation component is not to be considered in the calculation (
deformationsdoes not include ‘shear’), the flexural stiffness of the bar is scaled to reduce the deformation component so that the shear deformation becomes negligibly small.\[GA_s = 1000 \cdot EI\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> 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) >>> b = Bar(n1, n2, cross, mat, deformations=['moment', 'normal']) >>> b.shear_stiffness 5814900.000000001 >>> b = Bar(n1, n2, cross, mat, deformations=['moment', 'shear']) >>> b.shear_stiffness 390581.97463079996
- stiffness_matrix(hinge_modification=True, to_node_coord=True)#
Return the modified element stiffness matrix \(k'\) of the beam element.
This method constructs the element stiffness matrix that relates nodal displacements and rotations to the corresponding internal forces at the element ends. Depending on the chosen analysis approach, the matrix may include shear flexibility effects, second-order (P–Δ) modifications and hinge adjustments.
- Parameters:
- hinge_modificationbool, default=True
If
True, the stiffness matrix is adjusted to account for hinges at one or both ends of the element.- to_node_coordbool, default=True
If
True, the stiffness matrix is transformed from the local bar coordinate system into the global nodal coordinate system.
- Returns:
- numpy.ndarray
The
6×6modified element stiffness matrix.
See also
Notes
The element stiffness matrix is symmetric and depends on the order of calculation and the applied approach. If the beam is shear-flexible, the shear component is included in the matrix.
The general form of the element stiffness matrix \(k^{'}\) for a shear-rigid beam is:
\[\begin{split}k^{'} = \left[\begin{array}{rrr|rrr} \dfrac{EA}{\ell} & 0 & 0 & -\dfrac{EA}{\ell} & 0 & 0 \\ 0 & \dfrac{12EI}{\ell^3} & -\dfrac{6EI}{\ell^2} & 0 & -\dfrac{12EI}{\ell^3} & -\dfrac{6EI}{\ell^2} \\ 0 & -\dfrac{6EI}{\ell^2} & \dfrac{4EI}{\ell} & 0 & \dfrac{6EI}{\ell^2} & \dfrac{2EI}{\ell} \\ \hline -\dfrac{EA}{\ell} & 0 & 0 & \dfrac{EA}{\ell} & 0 & 0 \\ 0 & -\dfrac{12EI}{\ell^3} & \dfrac{6EI}{\ell^2} & 0 & \dfrac{12EI}{\ell^3} & \dfrac{6EI}{\ell^2} \\ 0 & -\dfrac{6EI}{\ell^2} & \dfrac{2EI}{\ell} & 0 & \dfrac{6EI}{\ell^2} & \dfrac{4EI}{\ell} \\ \end{array}\right]\end{split}\]For second-order theory, the modified stiffness contributions are applied element-wise to this general form.
If hinges are present in the beam, it is necessary to modify the stiffness matrix to account for discontinuities in deformations at hinge locations.
Finally, the stiffness matrix may be transformed into the nodal coordinate system if required.
- property stiffness_matrix_analytic#
- Creates the element stiffness matrix according to second-order
theory for the analytical solution.
To establish the stiffness matrix based on second-order theory, four correction functions must be calculated, which account for the influence of the axial force (\(L\)).
- Returns:
numpy.arrayA 6x6 matrix representing the theoretically exact element stiffness matrix according to second-order theory for a shear-flexible and bending-flexible beam under constant negative or positive axial force.
Notes
The correction functions are computed depending on the sign of the axial force. The functions are also dependent on the
characteristic_number, which is defined by the equation:\[\mu = \sqrt{\dfrac{\mid L \mid}{B_s}} \cdot \ell\]For a negative axial force, the following equations apply:
\[f_1(\mu) = - \dfrac{B_s}{12EI} \cdot \dfrac{\mu^3 \cdot \sin ( \mu)}{2 [\frac{B_s}{GA_s \ell^2} \mu^2 + 1] (\cos (\mu) - 1) + \mu \cdot \sin ( \mu)}\]\[f_2(\mu) = \dfrac{B_s}{6EI} \cdot \dfrac{(\cos (\mu) - 1) \cdot \mu^2}{2 [\frac{B_s}{GA_s \ell^2} \mu^2 + 1] (\cos (\mu) - 1) + \mu \cdot \sin ( \mu)}\]\[f_3(\mu) = -\dfrac{B_s}{4EI} \cdot \dfrac{\big([\frac{B_s}{GA_s \ell^2} \mu^2 + 1] \sin ( \mu) - \mu \cdot \cos( \mu ) \big) \cdot \mu}{2 [\frac{B_s}{GA_s \ell^2} \mu^2 + 1] (\cos (\mu) - 1) + \mu \cdot \sin ( \mu)}\]\[f_4(\mu) = \dfrac{B_s}{2EI} \cdot \dfrac{\big([\frac{B_s}{GA_s \ell^2} \mu^2 + 1] \sin ( \mu) - \mu \big) \cdot \mu}{2 [\frac {B_s}{GA_s \ell^2} \mu^2 + 1] (\cos (\mu) - 1) + \mu \cdot \sin ( \mu)}\]For a positive axial force, the equations are as follows:
\[f_1(\mu) = \dfrac{B_s}{12EI} \cdot \dfrac{\mu^3 \cdot \sinh ( \mu)}{2 [\frac{B_s}{GA_s \ell^2} \mu^2 + 1] (\cosh (\mu) - 1) + \mu \cdot \sinh ( \mu)}\]\[f_2(\mu) = \dfrac{B_s}{6EI} \cdot \dfrac{(\cosh (\mu) - 1) \cdot \mu^2}{2 [\frac{B_s}{GA_s \ell^2} \mu^2 + 1] (\cosh (\mu) - 1) + \mu \cdot \sinh ( \mu)}\]\[f_3(\mu) = \dfrac{B_s}{4EI} \cdot \dfrac{\big([\frac{B_s}{GA_s \ell^2} \mu^2 + 1] \sinh ( \mu) - \mu \cdot \cosh( \mu ) \big) \cdot \mu}{2 [\frac{B_s}{GA_s \ell^2} \mu^2 + 1] (\cosh (\mu) - 1) + \mu \cdot \sinh ( \mu)}\]\[f_4(\mu) = \dfrac{B_s}{2EI} \cdot \dfrac{\big([\frac{B_s}{GA_s \ell^2} \mu^2 + 1] \sinh ( \mu) - \mu \big) \cdot \mu}{2 [ \frac{B_s}{GA_s \ell^2} \mu^2 + 1] (\cosh (\mu) - 1) + \mu \cdot \sinh ( \mu)}\]Which leads to the element stiffness matrix:
\[\begin{split}k^{'} = \left[\begin{array}{rrr|rrr} \dfrac{EA}{\ell} & 0 & 0 & -\dfrac{EA}{\ell} & 0 & 0 \\ 0 & \dfrac{12EI}{\ell^3} \cdot f_1 & -\dfrac{6EI}{\ell^2} \cdot f_2 & 0 & -\dfrac{12EI}{\ell^3}\cdot f_1 & -\dfrac{6EI} {\ell^2}\cdot f_2 \\ 0 & -\dfrac{6EI}{\ell^2}\cdot f_2 & \dfrac{4EI}{\ell}\cdot f_3 & 0 & \dfrac{6EI}{\ell^2}\cdot f_2 & \dfrac{2EI}{\ell}\cdot f_4 \\ \hline -\dfrac{EA}{\ell} & 0 & 0 & \dfrac{EA}{\ell} & 0 & 0 \\ 0 & -\dfrac{12EI}{\ell^3}\cdot f_1 & \dfrac{6EI}{\ell^2}\cdot f_2 & 0 & \dfrac{12EI}{\ell^3}\cdot f_1 & \dfrac{6EI}{\ell^2} \cdot f_2 \\ 0 & -\dfrac{6EI}{\ell^2}\cdot f_2 & \dfrac{2EI}{\ell}\cdot f_4 & 0 & \dfrac{6EI}{\ell^2}\cdot f_2 & \dfrac{4EI}{\ell}\cdot f_3 \end{array}\right]\end{split}\]Examples
>>> from sstatics.core.preprocessing.bar import BarSecond >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> from sstatics.core.preprocessing.loads import NodePointLoad >>> n_load = NodePointLoad(0, 182, 0, rotation=0) >>> n1 = Node(0, 0, u='fixed', w='fixed', phi='fixed') >>> n2 = Node(0, -4, loads=n_load) >>> cross = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377) >>> material = Material(210000000, 0.1, 81000000, 0.1) >>> line_load = BarLineLoad(1, 1.5, 'z', 'bar', 'exact') >>> force = -181.99971053936605 >>> b = BarSecond(n1, n2, cross, material, line_loads=line_load) >>> b.stiffness_matrix_analytic array([[1, 0, 0, 1, 0, 0], [0, 0.9491546296, 0.9908554233, 0, 0.9491546296, 0.9908554233], [0, 0.9908554233, 0.9826126598, 0, 0.9908554233, 1.0073409503], [1, 0, 0, 1, 0, 0], [0, 0.9491546296, 0.9908554233, 0, 0.9491546296, 0.9908554233], [0, 0.9908554233, 1.0073409503, 0, 0.9908554233, 0.9826126598]])
- property stiffness_matrix_p_delta#
Creates the geometric stiffness matrix \(k_{G}^{'}\)
The geometric stiffness matrix describes the relationship between beam forces and displacements. It represents the transverse forces resulting from the moment offset of axial forces (\(L\)) according to second-order theory.
- Returns:
numpy.arrayA 6x6 matrix representing the geometric stiffness matrix according to second-order theory for the P- \(\Delta\) -effect.
Notes
To obtain the approximate solution considering the P-Delta effect, a geometric stiffness matrix is added to the element stiffness matrix from first-order theory.
\[k^{'} = k_{0}^{'} + k_{G}^{'}\]The geometric stiffness matrix is given by:
\[\begin{split}k_{G}^{'} = \left[\begin{array}{ccc|ccc} 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & \dfrac{L}{\ell} & 0 & 0 & -\dfrac{L}{\ell} & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 \\ \hline 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & -\dfrac{L}{\ell} & 0 & 0 & \dfrac{L}{\ell} & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 \\ \end{array}\right]\end{split}\]
- property stiffness_matrix_taylor#
Creates the element stiffness matrix according to second-order theory for a Taylor series.
To establish the stiffness matrix based on second-order theory, four correction functions must be calculated, which account for the influence of the axial force (\(L\)).
- Returns:
numpy.arrayA 6x6 matrix representing the theoretically exact element stiffness matrix according to second-order theory for a shear-flexible and bending-flexible beam under constant negative or positive axial force.
Notes
The correction function are calculated by the following equations:
\[f_1= \dfrac{B_s}{12EI ( \frac{B_s}{GA_s \ell^2}+ \frac{1}{12})} + \dfrac{L \ell^2}{144 EI} \cdot \Bigg(\dfrac{\frac{B_s}{GA_s \ell^2} + \frac{1}{10}}{(\frac{B_s}{GA_s \ell^2} + \frac{1} {12})^2}\Bigg)\]\[f_2= \dfrac{B_s}{12EI ( \frac{B_s}{GA_s \ell^2}+ \frac{1}{12})} + \dfrac{L \ell^2}{8640 EI} \cdot \Bigg(\dfrac{1}{(\frac{B_s} {GA_s \ell^2} + \frac{1}{12})^2}\Bigg)\]\[f_3= \dfrac{B_s ( \frac{B_s}{GA_s \ell^2}+ \frac{1}{3})}{4EI ( \frac{B_s}{GA_s \ell^2}+ \frac{1}{12})} + \dfrac{L \ell^2} {48 EI} \cdot \Bigg(\dfrac{1}{240(\frac{B_s}{GA_s \ell^2} + \frac{1}{12})^2} + 1\Bigg)\]\[f_4= -\dfrac{B_s ( \frac{B_s}{GA_s \ell^2}- \frac{1}{6})}{2EI ( \frac{B_s}{GA_s \ell^2}+ \frac{1}{12})} + \dfrac{L \ell^2} {24 EI} \cdot \Bigg(\dfrac{1}{240(\frac{B_s}{GA_s \ell^2} + \frac{1}{12})^2} - 1\Bigg)\]Which leads to the element stiffness matrix:
\[\begin{split}k^{'} = \left[\begin{array}{rrr|rrr} \dfrac{EA}{\ell} & 0 & 0 & -\dfrac{EA}{\ell} & 0 & 0 \\ 0 & \dfrac{12EI}{\ell^3} \cdot f_1 & -\dfrac{6EI}{\ell^2} \cdot f_2 & 0 & -\dfrac{12EI}{\ell^3}\cdot f_1 & -\dfrac{6EI} {\ell^2}\cdot f_2 \\ 0 & -\dfrac{6EI}{\ell^2}\cdot f_2 & \dfrac{4EI}{\ell}\cdot f_3 & 0 & \dfrac{6EI}{\ell^2}\cdot f_2 & \dfrac{2EI}{\ell}\cdot f_4 \\ \hline -\dfrac{EA}{\ell} & 0 & 0 & \dfrac{EA}{\ell} & 0 & 0 \\ 0 & -\dfrac{12EI}{\ell^3}\cdot f_1 & \dfrac{6EI}{\ell^2}\cdot f_2 & 0 & \dfrac{12EI}{\ell^3}\cdot f_1 & \dfrac{6EI}{\ell^2} \cdot f_2 \\ 0 & -\dfrac{6EI}{\ell^2}\cdot f_2 & \dfrac{2EI}{\ell}\cdot f_4 & 0 & \dfrac{6EI}{\ell^2}\cdot f_2 & \dfrac{4EI}{\ell}\cdot f_3 \end{array}\right]\end{split}\]
- property stiffness_shear_force#
Computes the element stiffness matrix considering shear effects.
- Returns:
numpy.arrayA 6x6 matrix representing the element stiffness matrix according to first-order theory, including shear effects.
Notes
The element stiffness matrix accounts for the deformation components of the beam due to axial force, bending, and shear. The factor
phidescribes the influence of shear deformation.The general form of the element stiffness matrix \(k^{'}\) is given by:
\[\begin{split}k^{'} = \left[\begin{array}{rrr|rrr} \dfrac{EA}{\ell} & 0 & 0 & -\dfrac{EA}{\ell} & 0 & 0 \\ 0 & \dfrac{12EI}{\ell^3 ( 1 + \phi)} & -\dfrac{6EI}{\ell^2 (1 + \phi)} & 0 & -\dfrac{12EI}{\ell^3(1 + \phi)} & - \dfrac{6EI}{\ell^2(1 + \phi)} \\ 0 & -\dfrac{6EI}{\ell^2(1 + \phi)} & \dfrac{EI(4 + \phi)}{\ell (1 + \phi)} & 0 & \dfrac{6EI}{\ell^2(1 + \phi)} & \dfrac{EI(2 - \phi)}{\ell(1 + \phi)} \\ \hline -\dfrac{EA}{\ell} & 0 & 0 & \dfrac{EA}{\ell} & 0 & 0 \\ 0 & -\dfrac{12EI}{\ell^3(1 + \phi)} & \dfrac{6EI}{\ell^2(1 + \phi)} & 0 & \dfrac{12EI}{\ell^3(1 + \phi)} & \dfrac{6EI} {\ell^2(1 + \phi)} \\ 0 & -\dfrac{6EI}{\ell^2(1 + \phi)} & \dfrac{EI(2 - \phi)}{\ell (1 + \phi)} & 0 & \dfrac{6EI}{\ell^2(1 + \phi)} & \dfrac{EI(4 + \phi)}{\ell(1 + \phi)} \\ \end{array}\right]\end{split}\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> from sstatics.core.preprocessing.loads import BarLineLoad >>> n1, n2 = Node(0, 0), Node(0, -4) >>> cross = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377) >>> material = Material(210000000, 0.1, 81000000, 0.1) >>> deform = ['moment', 'normal', 'shear'] >>> b = Bar(n1, n2, cross, material, deformations=deform) >>> b.stiffness_shear_force array([[1, 0, 0, 1, 0, 0], [0, 0.9889574613, 0.9889574613, 0, 0.9889574613, 0.9889574613], [0, 0.9889574613, 0.991718096, 0, 0.9889574613, 0.983436192], [1, 0, 0, 1, 0, 0], [0, 0.9889574613, 0.9889574613, 0, 0.9889574613, 0.9889574613], [0, 0.9889574613, 0.983436192, 0, 0.9889574613, 0.991718096]])
- transformation_matrix(to_node_coord=True)#
Create a 6x6 rotation matrix based on the bar’s inclination and node components.
- Parameters:
- to_node_coord
bool, default=True Determines whether a transformation into the node coordinate system takes place.
Trueif transformation to the node coordinate system is applied.Falseif the transformation is not applied.
- to_node_coord
- Returns:
numpy.arrayA 6x6 matrix for rotating 6x1 vectors.
Notes
If the transformation to the node coordinate system is not applied, the rotation angle is determined solely by the inclination of the bar:
alpha = bar.inclination.If the transformation to the node coordinate system is applied, the rotation is calculated by subtracting the node rotations from the bar inclination:
alpha_i = bar.inclination - bar.node_i.rotationalpha_j = bar.inclination - bar.node_j.rotationThe resulting matrix has the form
\[\begin{split}\left[\begin{array}{cccccc} \cos(\alpha_i) & \sin(\alpha_i) & 0 & 0 & 0 & 0\\ -\sin(\alpha_i) & \cos(\alpha_i) & 0 & 0 & 0 & 0\\ 0 & 0 & 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & \cos(\alpha_j) & \sin(\alpha_j) & 0 \\ 0 & 0 & 0 & -\sin(\alpha_j) & \cos(\alpha_j) & 0 \\ 0 & 0 & 0 & 0 & 0 & 1 \end{array}\right]\end{split}\]Examples
>>> from sstatics.core.preprocessing.bar import Bar >>> from sstatics.core.preprocessing.cross_section import CrossSection >>> from sstatics.core.preprocessing.material import Material >>> from sstatics.core.preprocessing.node import Node >>> import numpy >>> node_1 = Node(0, 0, rotation=numpy.pi/4) >>> node_2 = Node(4, -3) >>> cross_sec = CrossSection(0.00002769, 0.007684, 0.2, 0.2, 0.6275377) >>> material = Material(210000000, 0.1, 81000000, 0.1) >>> bar = Bar(node_1, node_2, cross_sec, material) >>> bar.transformation_matrix() array([[0.98994949, -0.14142136, 0., 0., 0., 0.], [0.14142136, 0.98994949, 0., 0., 0., 0.], [0., 0., 1., 0., 0., 0.], [0., 0., 0., 0.8, 0.6, 0.], [0., 0., 0., -0.6, 0.8, 0.], [0., 0., 0., 0., 0., 1.]]) >>> bar.transformation_matrix(False) array([[0.8, 0.6, 0., 0., 0., 0.], [-0.6, 0.8, 0., 0., 0., 0.], [0., 0., 1., 0., 0., 0.], [0., 0., 0., 0.8, 0.6, 0.], [0., 0., 0., -0.6, 0.8, 0.], [0., 0., 0., 0., 0., 1.]])
- class sstatics.core.preprocessing.cross_section.CrossSection(*a, **k)#
Bases:
LoggerMixin- property area#
Returns the cross-sectional area.
- Returns:
floatCross-sectional area.
Examples
>>> from sstatics.core.preprocessing.cross_section import CrossSection >>> geo = [Polygon(points=[(0, 0), (2, 0), (2, 1), (0, 1), (0, 0)])] >>> cs = CrossSection(geometry=geo) >>> cs.area 2.0
- boundary()#
Determines the overall geometric boundaries of the cross-section in both the y- and z-directions.
- Returns:
- tuple of list of
float ([y_min, y_max], [z_min, z_max]) representing the horizontal and vertical extents of the cross-section.
- tuple of list of
Notes
The boundaries are computed based on all geometric components (polygon and circular sectors) that make up the cross-section.
If a polygon is present, its vertex coordinates are included directly.
For each circular sector, the corresponding boundary extents are obtained from its
boundary()method.Only circular sectors marked as positive (i.e., material present) are considered for determining the outer limits.
If neither polygons nor circular sectors are defined, the method returns zero boundaries.
- property center_of_mass_y#
Returns the y-coordinate of the centroid of the cross-section.
- Returns:
floatCentroid y-coordinate (\(c_y\)).
Examples
>>> from sstatics.core.preprocessing.cross_section import CrossSection >>> geo = [Polygon(points=[(0, 0), (2, 0), (2, 1), (0, 1), (0, 0)])] >>> cs = CrossSection(geometry=geo) >>> cs.center_of_mass_y 1
- property center_of_mass_z#
Returns the z-coordinate of the centroid of the cross-section.
- Returns:
floatCentroid z-coordinate (\(c_z\)).
Examples
>>> from sstatics.core.preprocessing.cross_section import CrossSection >>> geo = [Polygon(points=[(0, 0), (2, 0), (2, 1), (0, 1), (0, 0)])] >>> cs = CrossSection(geometry=geo) >>> cs.center_of_mass_z 0.5
- property height#
Returns the height of the cross-section.
- Returns:
floatCross-section height.
Notes
Calculated from polygon and circular sector geometry.
Examples
>>> from sstatics.core.preprocessing.cross_section import CrossSection >>> geo = [Polygon(points=[(0, 0), (2, 0), (2, 1), (0, 1), (0, 0)])] >>> cs = CrossSection(geometry=geo) >>> cs.height 1.0
- property logger#
Returns the logger instance associated with this object.
- Returns:
- logging.Logger
The configured logger.
- property mom_of_int#
Returns the moment of inertia of the cross-section.
- Returns:
floatMoment of inertia (\(I_{yy}\)), either from input or calculated.
Examples
>>> from sstatics.core.preprocessing.cross_section import CrossSection >>> geo = [Polygon(points=[(0, 0), (2, 0), (2, 1), (0, 1), (0, 0)])] >>> cs = CrossSection(geometry=geo) >>> cs.mom_of_int 0.16666666666666663
- property shear_cor#
Returns the shear correction factor.
- Returns:
floatShear correction factor (default 1.0).
Notes
Currently a fixed value; automatic calculation is not implemented.
Examples
>>> from sstatics.core.preprocessing.cross_section import CrossSection >>> I = 0.000405 >>> A = 0.054 >>> h = 0.3 >>> w = 0.18 >>> cs = CrossSection(I, A, h, w, shear_cor=0.85) >>> cs.shear_cor float(0.85)
- property static_moment#
Returns the static moments (first moments of area) about y and z axes if a geometry is defined.
- Returns:
- tuple of
float (\(S_y\), \(S_z\)) static moments.
- tuple of
Notes
Includes contributions from polygons and circular sectors.
Examples
>>> from sstatics.core.preprocessing.cross_section import CrossSection >>> geo = [Polygon(points=[(0, 0), (2, 0), (2, 1), (0, 1), (0, 0)])] >>> cs = CrossSection(geometry=geo) >>> sz, sy = cs.static_moment (np.float64(1.0), np.float64(2.0))
- property width#
Returns the width of the cross-section.
- Returns:
floatCross-section width.
Notes
Calculated from polygon and circular sector geometry.
Examples
>>> from sstatics.core.preprocessing.cross_section import CrossSection >>> geo = [Polygon(points=[(0, 0), (2, 0), (2, 1), (0, 1), (0, 0)])] >>> cs = CrossSection(geometry=geo) >>> cs.width 2.0
- class sstatics.core.preprocessing.dof.DegreesOfFreedom(x=0.0, z=0.0, phi=0.0)#
Bases:
objectRepresents the degrees of freedom in a 2D space with translation along
x,z, and rotationphi.- Parameters:
- property vector#
Returns the degrees of freedom as a 3x1 vector.
- Returns:
numpy.arrayA 3x1 vector representing [
x,z,phi].
- sstatics.core.preprocessing.dof.NodeDisplacement#
Alias of
DegreesOfFreedomto make clear that this class has the purpose to shift nodes.
- class sstatics.core.preprocessing.loads.BarLineLoad(pi, pj, direction='z', coord='bar', length='exact')#
Bases:
objectCreate a distributed line load applied to a structural bar element.
- Parameters:
- pi
float The force at the start of the bar element.
- pj
float The force at the end of the bar element.
- direction{‘x’, ‘z’}, default=’z’
- The direction in which the load acts. Can be either:
'x': Load acts in the global/local x-direction.'z': Load acts in the global/local z-direction.
- coord{‘bar’, ‘system’}, default=’bar’
- Specifies the coordinate system in which the load is defined. Can be either:
'bar': The load is applied in the local coordinate system of the bar.'system': The load is applied in the global coordinate system.
- length{‘exact’, ‘proj’}, default=’exact’
- Defines how the length of the load is considered. Can be either:
'exact': The exact length of the bar is used.'proj': The projection of the bar length onto the global coordinate system is used.
- pi
- Raises:
- ValueError
directionhas to be either'x'or'z'- ValueError
coordhas to be either'bar'or'system'- ValueError
lengthhas to be either'exact'or'proj'
- rotate(rotation)#
Rotates the load vector if the coordinate system is global.
- Parameters:
- rotation
float The rotation angle in rad.
- rotation
- Returns:
numpy.arrayThe rotated load vector.
Notes
If the load is defined in the local bar coordinate system, no rotation is applied.
If the load is defined in the global coordinate system, the transformation matrix accounts for rotation and projection effects.
Examples
>>> from sstatics.core.preprocessing.loads import BarLineLoad >>> BarLineLoad(1, 1, 'z', 'bar', 'exact').rotate(0) array([[0], [1], [0], [0], [1], [0]])
>>> from sstatics.core.preprocessing.loads import BarLineLoad >>> import numpy as np >>> BarLineLoad(1, 1, 'z', 'system', 'proj').rotate(np.deg2rad(30)) array([[-0.4330127], [0.75], [0], [-0.4330127], [0.75], [0]])
- property vector#
Computes the load vector for the bar element.
- Returns:
numpy.arrayA 6x1 vector representing the distributed load at the bar element.
Notes
The force at the start of the bar (pi) is assigned to index 0 (x) or 1 (z).
The force at the end of the bar (pj) is assigned to index 3 (x) or 4 (z).
If
piandpjare zero, then a 6x1 zero vector is returned.
- class sstatics.core.preprocessing.loads.BarPointLoad(x=0.0, z=0.0, phi=0.0, rotation=0.0, position=0.0)#
Bases:
PointLoadCreate a point load applied at a specific position along a bar.
- Parameters:
- x
float The force component in the x-direction.
- z
float The force component in the z-direction.
- phi
float The moment applied along the beam.
- rotation
float, default=0.0 The rotation of the load components in rad.
- position
float, default=0.0 Describes the relative position of the load along the bar. A value of 0 indicates the start of the bar, and 1 indicates the end of the bar.
- x
- Raises:
- ValueError
positionhas to be a value between 0 and 1.
See also
Notes
This class models a point load applied to a bar (or beam) at a specific position. The load is applied in the x and z directions and includes a moment (phi) along the beam. The position is a normalized value between 0 and 1, where 0 corresponds to the start of the bar and 1 corresponds to the end of the bar.
- rotate()#
Rotates the load vector based on its relative position.
- Returns:
numpy.arrayA 6x1 array representing the rotated load vector.
Notes
If
position== 0, the load is placed at the start of the bar.If
position== 1, the load is placed at the end of the bar.For intermediate positions (0 <
position< 1), the load contribution is considered elsewhere in the calculation and does not appear directly in this vector. A 6x1 zero vector is returned.
Examples
>>> from sstatics.core.preprocessing.loads import BarPointLoad >>> load = BarPointLoad(x=5.0, z=0.0, phi=0.0, position=0.0) >>> load.rotate() array([[5.], [0.], [0.], [0.], [0.], [0.]])
- property vector#
Returns the degrees of freedom as a 3x1 vector.
- Returns:
numpy.arrayA 3x1 vector representing [
x,z,phi].
- sstatics.core.preprocessing.loads.NodePointLoad#
Alias of
PointLoadto make the use case of this class more clear.
- class sstatics.core.preprocessing.loads.PointLoad(x=0.0, z=0.0, phi=0.0, rotation=0.0)#
Bases:
DegreesOfFreedomCreate a point load applied to a statical system.
This class is used to model a point load at a specific location, which can represent either a load applied at a node or along a bar. It includes force components in the x and z directions, as well as a rotational component (\(\phi\)), which can represent a moment applied to either a node or a bar.
- Parameters:
- x
float The force component in the x-direction. Represents the magnitude of the force along the x-axis.
- z
float The force component in the z-direction. Represents the magnitude of the force along the z-axis.
- phi
float The moment or rotational force applied at the load location. This can represent a torque at a node or a rotational component along a bar.
- rotation
float, default=0.0 The rotation of the load components, default is 0.0. This value specifies the initial angle (in rad) of the load’s vector relative to a reference orientation.
- x
See also
Notes
This class serves as the base class for modeling point loads.
- rotate(rotation)#
Rotates the point load by a given angle and applies the rotation to the load vector.
- Parameters:
- rotation
float The amount of rotation to apply, in radians. This is the angle by which the load vector is rotated relative to its current orientation.
- rotation
- Returns:
numpy.arrayThe 3x1 transformed load vector after applying the rotation.
Notes
The rotation is performed by multiplying the transformation matrix with the load vector. The angle for the transformation matrix is calculated by subtracting the rotation of the point load from the input rotation:
alpha = load.rotation - rotation\[\begin{split}\left(\begin{array}{ccc} \cos(\alpha) & \sin(\alpha) & 0 \\ -\sin(\alpha) & \cos(\alpha) & 0 \\ 0 & 0 & 1 \end{array}\right) \cdot \left(\begin{array}{c} x \\ z \\ \varphi \end{array}\right)\end{split}\]
- property vector#
Returns the degrees of freedom as a 3x1 vector.
- Returns:
numpy.arrayA 3x1 vector representing [
x,z,phi].
- class sstatics.core.preprocessing.material.Material(young_mod, poisson, shear_mod, therm_exp_coeff)#
Bases:
objectCreate a material for a statical system.
- Parameters:
- young_mod
float Young’s modulus (\(E\)), a measure of the material’s stiffness.
- poisson
float Poisson’s ratio (\(\nu\)), the negative ratio of transverse to axial strain.
- shear_mod
float Shear modulus (\(G\)), a measure of the material’s response to shear stress.
- therm_exp_coeff
float Thermal expansion coefficient (\(\alpha_T\)), describing how the material’s dimensions change with temperature (in 1/K).
- young_mod
- Raises:
- ValueError
young_mod,poisson,shear_mod, andtherm_exp_coeffhave to be greater than zero.
- class sstatics.core.preprocessing.modifier.SystemModifier(system)#
Bases:
objectModifies a given structural system by tracking and applying changes such as support modifications, bar hinge insertions, load deletions, and more.
This class maintains a mapping between original and modified components (bars and nodes), making it possible to incrementally update the system while preserving references to the original configuration. It is especially useful in structural mechanics for performing operations like virtual force methods or stepwise modifications for influence line generation.
- Parameters:
- system
System The structural system to be modified. This must include bars and nodes as fundamental elements, potentially with loads, supports, and other mechanical properties.
- system
- Attributes:
- bar_mapdict[
Bar, Optional[Bar]] A mapping from the original bars to their current (potentially modified) versions. This ensures that modifications can always refer back to the original structure. If a bar has been deleted, it is mapped to None.
This is essential for managing modifications over time without losing the relationship between system states.
- node_mapdict[
Node,Node] Maps original nodes to the current (possibly modified) versions. Used to consistently track changes in node-based properties like displacements, loads, and support conditions. The original node always remains the key.
This map ensures that new system configurations reflect changes such as support removals or load applications, while maintaining link to the original nodes.
- memory_modificationlist[tuple[Union[
Bar,Node], str]] Stores a log of all applied structural modifications. Each entry consists of an object (either a Bar or Node) and a string that describes what degree of freedom was modified (e.g., ‘u’, ‘w’, ‘phi’, or ‘hinge_phi_i’).
This is especially useful when constructing related systems later, for example when using the principle of virtual forces to create unit load systems corresponding to removed constraints.
- memory_bar_point_loaddict[
Bar, list[float]] Records bars that have point loads acting at positions strictly between 0 and 1 (non-endpoint). The list of floats denotes the relative position of each such load along the bar.
This is used to ensure that when systems are later subdivided or aligned (e.g., for assembling superposition systems or plotting influence lines), bars can be split consistently at these key locations.
The positions are automatically collected in __post_init__ and updated when new point loads are added via modification methods.
- bar_mapdict[
- create_uls_systems()#
Creates systems for unit load states.
After a modified system has been created, all modifications to bars or nodes are stored in the
memory_modificationlist.This method generates new systems representing unit load states, which are used in the force method. Unit loads are applied at the modified locations according to the type of modification:
Bar modifications (hinges) – A hinge modification requires applying a load pair (equal magnitude, opposite direction). The negativ load is applied to the modified bar at the hinge location, and the positiv load is applied to a connected bar without a hinge in the same degree of freedom. If all connected bars have a hinge, the first connected bar is used.
Node modifications (supports) – For a released degree of freedom, a unit load is applied directly to the node in the corresponding direction (horizontal, vertical, or rotational).
Bar deletion - For the removed bar unit loads are applied, at the connection points of the now deleted bar.
- Returns:
- list of
System A list of systems, each containing a single unit load state.
- list of
- delete_bar(bar_obj)#
Removes a bar from the system.
Updates the internal bar_map to mark the bar as deleted and reconstructs the system without the specified bar.
- delete_loads()#
Removes all loads from the current system.
This includes both nodal and bar loads (point and line loads) as well as thermal effects. It preserves the topology and geometry of the system, but clears external influences.
The system is reconstructed with the cleared nodes and bars. Also updates the internal mappings accordingly.
- Returns:
SystemThe updated system with all loads removed.
- division_positions_for(system)#
Return a division map for the given system based on the stored point load positions (memory_bar_point_load) of this modifier.
Each bar in the target system is matched to the corresponding bar of the modifier using the node coordinates. If matching bars are found and division positions exist, these positions are assigned to the new bar.
- Parameters:
- system
System The structural system for which the division map should be created.
- system
- Returns:
- dict[Bar, list[float]]
A dictionary mapping each matching bar in the given system to its division positions along the bar length.
- division_positions_mesh()#
Returns a dictionary mapping each bar to a list of relative positions (0 < pos < 1) where point loads exist. This is compatible with the user_divisions argument of Mesh.
- Returns:
- dict[Bar, list[float]]
A dictionary where keys are Bar objects and values are lists of division positions on that bar.
- insert_hinge(bar_obj, hinge)#
Inserts a hinge at a specific end and direction of a bar.
Modifies the selected bar by enabling a hinge for axial (u), shear (w), or moment (phi) behavior at the start (_i) or end (_j). Updates the system and internal memory for reconstruction or analysis.
- Parameters:
- bar_obj
Bar The target bar to modify.
- hingestr
The type and location of hinge, chosen from: ‘hinge_u_i’, ‘hinge_w_i’, ‘hinge_phi_i’, ‘hinge_u_j’, ‘hinge_w_j’, ‘hinge_phi_j’.
- bar_obj
- Returns:
SystemThe updated system with the hinge applied.
- Raises:
- ValueError
If the hinge is already present on the bar.
- modify_bar_force_vir(obj, force, virt_force=1, position=0)#
Applies a virtual point load to a bar.
Useful for virtual force methods to calculate internal forces (e.g., to determine internal actions). The load is placed at the specified relative position along the bar.
- Parameters:
- Returns:
SystemUpdated system with the virtual bar load.
- modify_node_force_vir(obj, force, virt_force=1)#
Applies a virtual load to a node.
This is used for virtual work or energy methods (e.g., to compute displacements). It modifies the node by assigning a virtual point load in the specified direction.
- Parameters:
- Returns:
SystemUpdated system with the virtual load applied to the node.
- modify_support(node_obj, support)#
Frees a specific degree of freedom (support) at a given node.
Modifies the boundary condition of the node, turning the specified support direction into a free (unconstrained) one. The system is updated accordingly, and all bars connected to the node are reconstructed.
- Parameters:
- node_obj
Node The node whose support is being modified.
- support{‘u’, ‘w’, ‘phi’}
Direction of the support to release: ‘u’ for horizontal, ‘w’ for vertical, ‘phi’ for rotational.
- node_obj
- Returns:
SystemThe system with the updated boundary condition.
- Raises:
- ValueError
If the selected support is already free.
- class sstatics.core.preprocessing.node.Node(x, z, rotation=0.0, u='free', w='free', phi='free', displacements=(), loads=(), debug=False)#
Bases:
LoggerMixinCreate a node for a statical system.
- Parameters:
- x, z
float Coordinates of the node in the x and z directions.
- rotation
float, default=0.0 Initial rotation of the node in radiant.
- u, w, phi{‘free’, ‘fixed’} or
float, default=’free’ - Boundary conditions (supports) for the node:
'free': no constraint'fixed': fully constrainedfloat: represents a spring support with a specific stiffness value (nib width).
- displacements
tuple, default=() Prescribed displacements acting on the node. hese should be instances of the
NodeDisplacement.- loads
tuple, default=() Point loads acting on the node. These should be instances of the
NodePointLoad.
- x, z
- Raises:
- ValueError
u,wandphihave to be either'free','fixed'or a real number.- ValueError
u,worphiare set to zero. A spring with a nib width of zero behaves like a free fixture and therefore the value need to be set to'free'.
- property displacement#
The overall node displacement as a 3x1 vector.
- Returns:
numpy.arraySum of all displacements specified in
displacements.
See also
NodeDisplacement
Notes
If no displacements were specified, then a 3x1 zero vector is returned.
Examples
>>> from sstatics.core.preprocessing.node import Node >>> Node(1, 2).displacement array([[0], [0], [0]])
>>> from sstatics.core.preprocessing.dof import NodeDisplacement >>> displacements = (NodeDisplacement(1.5, 2, 0.5), >>> NodeDisplacement(-2, 3, -0.3)) >>> Node(-1, 3, displacements=displacements).displacement array([[-0.5], [5], [0.2]])
- property elastic_support#
Sets the stiffness values from the support conditions on the diagonal of the matrix.
To account for the elastic support of nodes, the support conditions of
u,w, andphiare considered and placed on the diagonal of a zero matrix.- Returns:
numpy.arrayA 3x3 zero matrix with the diagonal populated by the values of
u,wandphi.
Notes
If an attribute is a string, its value is set to zero.
\[\begin{split}\begin{bmatrix} u & 0 & 0 \\ 0 & w & 0 \\ 0 & 0 & \varphi \\ \end{bmatrix}\end{split}\]Examples
>>> from sstatics.core.preprocessing.node import Node >>> Node(0, 0, u='fixed', w='fixed', phi='free').elastic_support array([[0, 0, 0], [0, 0, 0], [0, 0, 0]]) >>> Node(0, 0, u=100, w=200, phi=1000).elastic_support array([[100, 0, 0], [0, 200, 0], [0, 0, 1000]])
- property load#
Rotate the node loads.
Every load from
loadsis rotated by the node’s rotation by callingPointLoad.rotate. So the resulting rotation angle is calculated byalpha = load.rotation - node.rotation. Thus each rotated load is computed by\[\begin{split}\left(\begin{array}{c} \cos(\alpha) & \sin(\alpha) & 0 \\ -\sin(\alpha) & \cos(\alpha) & 0 \\ 0 & 0 & 1 \end{array}\right) \cdot \left(\begin{array}{c} x \\ z \\ \varphi \end{array}\right)\end{split}\]and summed up afterward.
- Returns:
numpy.arraySum of all loads specified in
loads.
See also
NodePointLoad
Notes
If no loads were specified, then a 3x1 zero vector is returned.
Examples
>>> from sstatics.core.preprocessing.node import Node >>> from sstatics.core.preprocessing.loads import NodePointLoad >>> import numpy >>> load = NodePointLoad(1, 2, 0.5, rotation=2 * numpy.pi) >>> Node(6, 5, rotation=numpy.pi, loads=(load,)).load array([[-1], [-2], [0.5]])
- property logger#
Returns the logger instance associated with this object.
- Returns:
- logging.Logger
The configured logger.
- same_location(other)#
Determine if two nodes have exactly the same
x- andz-coordinates.- Parameters:
- other
Node Second node to compare coordinates to.
- other
- Returns:
boolTrueif the nodes have exactly the same coordinates,Falseotherwise.
Examples
>>> from sstatics.core.preprocessing.node import Node >>> node = Node(1, 2) >>> node.same_location(Node(1, 2)) True >>> node.same_location(Node(1, -2)) False
- class sstatics.core.preprocessing.system.Mesh(bars, user_divisions=None)#
Bases:
objectRepresents a mesh of bars.
- Attributes:
- barsList[Bar | BarSecond]
A list of bars to be meshed.
- user_divisionsOptional[Dict[Bar, List[
float]]] Optional user-defined divisions for each bar.
Notes
The user_divisions dictionary maps each bar to a list of positions where the bar should be divided.
- bar_of(mesh_segment)#
Gets the original bar corresponding to a given mesh segment.
- Parameters:
- mesh_segmentBar | BarSecond
The mesh segment for which to retrieve the original bar.
- Returns:
- Bar | BarSecond
The original bar corresponding to the given mesh segment.
- generate()#
Generates the mesh based on the input bars and user divisions.
This method populates the mesh and user properties.
- Returns:
- None
Notes
The mesh generation process involves splitting the input bars into segments based on user-defined divisions and point loads.
- property mesh#
Gets the generated mesh.
- Returns:
- List[Bar | BarSecond]
The list of bars in the mesh.
- mesh_segments_of(bar)#
Gets the mesh segments corresponding to a given bar.
- Parameters:
- barBar | BarSecond
The bar for which to retrieve mesh segments.
- Returns:
- List[Bar | BarSecond]
The list of mesh segments corresponding to the given bar.
- property user#
Gets the user-defined mesh.
- Returns:
- List[Bar | BarSecond]
The list of bars in the user-defined mesh.
- user_segments_of(bar)#
Gets the user-defined segments corresponding to a given bar.
- Parameters:
- barBar | BarSecond
The bar for which to retrieve user-defined segments.
- Returns:
- List[Bar | BarSecond]
The list of user-defined segments corresponding to the given bar.
- class sstatics.core.preprocessing.system.System(bars, user_divisions=None)#
Bases:
objectRepresents a statical system composed of interconnected bars.
This class models a mechanical system made up of interconnected bars, where each bar connects two nodes.
- Parameters:
- Attributes:
- Raises:
- ValueError
Raised if any of the following conditions are met:
The list of bars is empty.
Two or more bars share the same geometric location.
Two distinct node instances occupy the same spatial position.
The system’s connectivity graph is not fully connected.
- bar_of(mesh_segment)#
Returns the original bar of a given mesh segment.
- Parameters:
- mesh_segmentBar | BarSecond
A bar segment from the generated mesh.
- Returns:
- Bar | BarSecond
The original bar from which the mesh segment was created.
- create_mesh(user_divisions=None)#
Creates the mesh for the current system.
- Parameters:
- user_divisionsdict, optional
A dictionary mapping bars to lists of relative positions at which the bars should be divided.
- Returns:
- None
Notes
This method initializes and generates a
Meshobject based on the system bars and optional user-defined divisions.
- property degree_of_static_indeterminacy#
Calculates the degree of static indeterminacy of the system.
This function checks the static determinacy of the currently modified system. A system is statically determinate if n = 0. It is statically indeterminate if n > 0 and statically unstable if n < 0.
- Returns:
intThe number of redundant constraints in the system.
- property mesh#
Returns the generated mesh bars.
- Returns:
- List[Bar | BarSecond]
The list of bars representing the generated mesh.
- mesh_segments_of(bar)#
Returns the mesh segments corresponding to a given bar.
- Parameters:
- barBar | BarSecond
The original bar.
- Returns:
- List[Bar | BarSecond]
The list of mesh segments derived from the given bar.
- property user_mesh#
Returns the user-defined mesh bars.
- Returns:
- List[Bar | BarSecond]
The list of bars resulting from user-defined divisions.
- user_segments_of(bar)#
Returns the user-defined segments of a given bar.
- Parameters:
- barBar | BarSecond
The original bar.
- Returns:
- List[Bar | BarSecond]
The list of user-defined segments of the bar.
- class sstatics.core.preprocessing.temperature.BarTemp(temp_o, temp_u)#
Bases:
objectCreate a temperature load case for a statical system.
- Parameters:
- Raises:
- ValueError
temp_o,temp_uhave to be greater than or equal to zero since its unit is Kelvin.
- property temp_delta#
Calculates the non-uniform temperature change in the unit Kelvin.
- Returns:
floatThe temperature difference between the upper and lower side of the neutral axis, indicating the non-uniform temperature change in Kelvin.
Notes
The non-uniform temperature change is given by:
\[\Delta T = T_u - T_o\]Examples
>>> from sstatics.core.preprocessing.temperature import BarTemp >>> temp_diff = BarTemp(10, 20).temp_delta 10.0
- property temp_s#
Calculates the uniform temperature change in the unit Kelvin.
- Returns:
floatAveraged value of temperature changes above and below the neutral axis in Kelvin.
Notes
The uniform temperature change is given by:
\[T = \dfrac{(T_o + T_u)}{2}\]Examples
>>> from sstatics.core.preprocessing.temperature import BarTemp >>> temp = BarTemp(15, 30).temp_s 22.5
- class sstatics.core.preprocessing.geometry.objects.CircularSector(center, radius, angle=0, start_angle=0, positive=True)#
Bases:
objectRepresents a two-dimensional circular sector defined by a center point, radius, angular span and a starting angle.
- Parameters:
- centertuple of
float The (y_0, z_0) coordinates of the center of the circular sector.
- radius
float The radius of the sector. Must be a positive value.
- angle
float The angular span of the sector in radians. Must be a non-zero number and lie within the range ± 2π.
- start_angle
float The angle (in radians) where the sector arc begins, measured clockwise from the positive y’-axis.
- positive
bool, optional Specifies whether the sector is a partial or cutout area of the total cross-section. If “True,” the sector contributes positively to calculations (e.g., area and moment). If “False,” it is treated as a ‘cutout’ and its contributions are subtracted. The default value is “True.”
- centertuple of
Notes
The constructor validates input to ensure that the circular sector is well-defined: - The center must be a 2D coordinate tuple of numeric values. - The radius must be greater than zero. - The angle must not be zero and must be in the range (-2π <= angle <= 2π). - Start angle must be a number (in radians).” - The ‘positive’ attribute must be a boolean value.
The sector is internally represented with geometric formulas for properties such as area, centroid, and moments of inertia. Optionally, the sector can be discretized into a polygon via the convert_to_polygon() method.
Examples
Create a circular sector in the first quadrant:
>>> from sstatics.core.preprocessing.geometry.objects import CircularSector >>> import numpy as np >>> c = CircularSector(center = (0,0), radius = 1, angle = np.pi/4, >>> start_angle = np.pi/8, positive = True >>> )
Creates the same circular sector with a negative angle range:
>>> c = CircularSector(center = (0,0), radius = 1, angle = -np.pi/4, >>> start_angle = 3*np.pi/8, positive = True >>> )
Access area and centroid:
>>> round(c.area, 2) 0.39 >>> round(c.center_of_mass_y, 2), round(c.center_of_mass_z, 2) (0.46, 0.46)
- property area#
Computes the area of the circular sector.
- Returns:
- float
The area of the circular sector.
Notes
The area of a circular sector is computed using the formula:
\[A = \frac{1}{2} \cdot r^2 \cdot \mid \varphi_M \mid\]where
\(r\) is the radius of circular sector
\(\varphi_M\) is the angular span of the sector in radians
Examples
>>> from sstatics.core.preprocessing.geometry.objects import >>> CircularSector >>> import numpy as np >>> c = CircularSector(center = (0,0), radius = 1, angle = np.pi/4, >>> start_angle = np.pi/8, positive = True >>> ) >>> round(c.area, 3) 0.393
- boundary()#
Computes the minimum and maximum boundaries of the circular sector in both the y- and z-directions.
- Returns:
- tuple of list of
floator np.float64 A tuple containing two lists:
The first list is
[y_min, y_max], representing the horizontal extent.The second list is
[z_min, z_max], representing the vertical extent.
- tuple of list of
Notes
This method determines the spatial boundaries of the circular sector by evaluating the coordinates of:
The two arc endpoints (start and end angles),
The circle center,
And optionally the extreme values (i.e., if the local \(y'\)- or \(z'\)-axis lies between the start and end points of the circle sector).
The method checks whether those extreme values within the angular range of the circular sector using
_angle_in_sector, and includes them if applicable. This ensures the correct bounding box even for partial sectors that span multiple quadrants.These boundary values are used to compute the overall width and height of the sector geometry.
Examples
>>> from sstatics.core.preprocessing.geometry import CircularSector >>> import numpy as np >>> c = CircularSector(center = (0,0), radius = 1, angle = np.pi/2, >>> start_angle = np.pi/4, positive = True >>> ) >>> c.boundary() ([-0.707, 0.707], [0.0, 1.0])
- property center_of_mass_y#
Computes the y-coordinate of the centroid (center of mass).
- Returns:
- np.float64
The centroid’s y-coordinate.
Notes
The centroid represents the geometric center of the circular sector. It is used to compute the statics moments.
\[y_c = \frac{2 \cdot r}{3 \cdot \varphi_M} \cdot (sin(\varphi_2) - sin(\varphi_1)) + y_0\]where
\(r\) is the radius of circular sector
\(\varphi_M\) is the angular span of the sector in radians
\(\varphi_1\) is the starting angle
\(\varphi_2\) is the ending angle
\(y_0\) is the y-coordinate of the center of the circular sector
This assumes uniform density and thickness.
- property center_of_mass_z#
Computes the z-coordinate of the centroid (center of mass).
- Returns:
- np.float64
The centroid’s z-coordinate.
Notes
The centroid represents the geometric center of the circular sector. It is used to compute the statics moments.
\[z_c = \frac{2 \cdot r}{3 \cdot \varphi_M} \cdot (cos(\varphi_1) - cos(\varphi_2)) + z_0\]where
\(r\) is the radius of circular sector
\(\varphi_M\) is the angular span of the sector in radians
\(\varphi_1\) is the starting angle
\(\varphi_2\) is the ending angle
\(z_0\) is the z-coordinate of the center of the circular sector
This assumes uniform density and thickness.
- convert_to_polygon(num_points=500)#
Converts the circular sector into an approximate polygon representation.
- Parameters:
- num_pointsint, optional
Number of points used to discretize the arc of the sector. Higher values yield a finer approximation. Default is 500.
- Returns:
- Polygon
A polygonal approximation of the circular sector, represented by a Polygon object.
Notes
The polygon is constructed by sampling num_points points along the arc defined by the sector’s start angle \(\varphi_1\), opening angle \(\varphi_M\), and radius \(r\). These points are connected together with the center point of the sector to form a closed polygonal shape.
The starting point of the arc is determined by start_angle.
Points are sampled at equidistant angles along the arc.
The last arc point is explicitly added (if not already present), to avoid floating point errors.
The center point is both the first and last point in the polygon to ensure proper closure.
The resulting polygon can be used for geometric computations such as area, static moments, and moment of inertia using existing polygon-based methods.
- property height#
Computes the height of the circular sector in the local z-direction.
- Returns:
- np.float64
Height of the circular sector (i.e., the range of z-coordinates).
Notes
The height is defined as:
\[h = z_{\text{max}} - z_{\text{min}}\]where \(z_{\text{max}}\) and \(z_{\text{min}}\) are the maximum and minimum vertical coordinates of the sectors’s boundary
- mom_of_int_steiner(distance)#
Applies the parallel axis theorem (Steiner’s theorem) to compute the moment of inertia about a shifted axis.
- Parameters:
- distancefloat
The perpendicular distance from the centroid to the desired axis (in the same units as the circular sector coordinates).
- Returns:
- float
The additional moment of inertia due to the axis shift, i.e. \(I_{\text{shift}} = A \cdot d^2\), where \(A\) is the area and \(d\) is the distance to the new axis.
Notes
This is used to shift the moment of inertia from one axis to another parallel axis according to the parallel axis theorem:
\[I = I_c + A \cdot d^2\]
- property mom_of_int_y#
Computes the second moment of area \(I_{\bar{y}}\) about the bar{y}-axis, referenced to the centroid coordinate system.
- Returns:
- np.float64
The second moment of area \(I_{\bar{y}}\), in units of length⁴.
Notes
The components are initially computed relative to the center of the circular sector \((y_0, z_0)\) and then shifted to the centroid using the parallel axis theorem:
\[ \begin{align}\begin{aligned}I_{y'} = \frac{r^4}{8} \cdot [|\varphi_M| - \frac{1}{2} \cdot (sin(2\varphi_2) - sin(2\varphi_1))]\\I_{\bar{y}} = I_{y'} - A \cdot (z_c - z_0)^2\end{aligned}\end{align} \]where
\(r\) is the radius of circular sector
\(\varphi_M\) is the angular span of the sector in radians
\(\varphi_1\) is the starting angle
\(\varphi_2\) is the ending angle
\(z_c\) is the z-coordinate of the centroid of the circular sector
\(z_0\) is the z-coordinate of the center of the circular sector
- property mom_of_int_z#
Computes the second moment of area \(I_{\bar{z}}\) about the bar{z}-axis, referenced to the centroid coordinate system.
- Returns:
- np.float64
The second moment of area \(I_{\bar{z}}\), in units of length⁴.
Notes
The components are initially computed relative to the center of the circular sector \((y_0, z_0)\) and then shifted to the centroid using the parallel axis theorem:
\[ \begin{align}\begin{aligned}I_{z'} = \frac{r^4}{8} \cdot [|\varphi_M| + \frac{1}{2} \cdot (sin(2\varphi_2) - sin(2\varphi_1))]\\I_{\bar{z}} = I_{z'} - A \cdot (y_c - y_0)^2\end{aligned}\end{align} \]where
\(r\) is the radius of circular sector
\(\varphi_M\) is the angular span of the sector in radians
\(\varphi_1\) is the starting angle
\(\varphi_2\) is the ending angle
\(y_c\) is the z-coordinate of the centroid of the circular sector
\(y_0\) is the z-coordinate of the center of the circular sector
- property static_moment#
Computes the static moments \(S_y\) and \(S_z\) of the circular sector with respect to the coordinate axes.
- Returns:
- tuple of np.float64
The static moments (S_y, S_z) of the circular sector.
Notes
The static moments (also called first moments of area) are used to compute the centroid of the entire composite cross-section (see class CrossSection).
\[S_y = A \cdot z_c\]\[S_z = A \cdot y_c\]Examples
>>> from sstatics.core.preprocessing.geometry.objects import >>> CircularSector >>> import numpy as np >>> c = CircularSector(center = (0,0), radius = 1, angle = np.pi/2, >>> start_angle = 0, positive = True >>> ) >>> round(c.static_moment[0], 3) 0.333 >>> round(c.static_moment[1], 3) 0.333
- property width#
Computes the width of the circular sector in the local y-direction.
- Returns:
- np.float64
Width of the circular sector (i.e., the range of y-coordinates).
Notes
The width is defined as:
\[w = y_{\text{max}} - y_{\text{min}}\]where \(y_{\text{max}}\) and \(y_{\text{min}}\) are the maximum and minimum horizontal coordinates of the sectors’s boundary
- class sstatics.core.preprocessing.geometry.objects.Polygon(points, holes=<factory>, positive=True)#
Bases:
objectRepresents a two-dimensional polygon with optional interior holes, defined by a sequence of (y, z) coordinate tuples.
- Parameters:
- pointslist of tuple of
float A list of 2D coordinates defining the exterior boundary of the polygon. The polygon must be closed; i.e., the first and last point must be identical. A minimum of three distinct points (excluding the closing point) is required.
- holeslist of tuple of
float, optional A list of holes, where each hole is defined by a list of coordinate tuples similar to the outer boundary. Each hole must also be closed. Default is an empty list (no holes).
- positive
bool, optional Specifies whether the polygon should be oriented positively (counterclockwise). This affects the internal construction of the Shapely polygon. Default is True.
- pointslist of tuple of
Notes
The constructor validates the input geometry to ensure that the polygon is well-defined: - At least three distinct points are required to define a polygon. - The first and last point of the outer boundary (and any hole) must be the same to ensure closure. - All coordinate entries must be tuples of two numeric values. - No two consecutive points may be identical.
Internally, the polygon is represented using a Shapely Polygon object and re-oriented if necessary. The coordinate arrays self.y and self.z are extracted for further geometric computations, such as area, centroid, and static moments.
Examples
Create a rectangular polygon with no holes:
>>> from sstatics.core.preprocessing.geometry.objects import Polygon >>> outer = [(0, 0), (4, 0), (4, 2), (0, 2), (0, 0)] >>> p = Polygon(points=outer)
Create a polygon with one rectangular hole:
>>> hole = [[(1, 0.5), (3, 0.5), (3, 1.5), (1, 1.5), (1, 0.5)]] >>> p = Polygon(points=outer, holes=hole)
Access area and centroid:
>>> round(p.area, 2) 6.0 >>> round(p.center_of_mass_y, 2), round(p.center_of_mass_z, 2) (2.0, 1.0)
- property area#
Computes the signed area of the polygon, including all interior holes.
- Returns:
floatThe signed area of the polygon. A positive value indicates counterclockwise orientation (positive geometry), while a negative value indicates clockwise orientation.
Notes
The area is computed using the shoelace formula:
\[ \begin{align}\begin{aligned}A = \frac{1}{2} \left| \sum_{i=1}^{n} y_i \cdot z_{(i+1)} - y_{ (i+1)} \cdot z_i \right|\\where\end{aligned}\end{align} \]\[(y_i, z_i)\]are the coordinates of the vertices.
Examples
>>> from sstatics.core.preprocessing.geometry.objects import Polygon >>> outer = [(0, 0), (4, 0), (4, 2), (0, 2), (0, 0)] >>> hole = [[(1, 0.5), (3, 0.5), (3, 1.5), (1, 1.5), (1, 0.5)]] >>> p = Polygon(points=outer, holes=hole) >>> round(p.area, 3) 6.0
- property center_of_mass_y#
Computes the y-coordinate of the centroid (center of mass).
- Returns:
- np.float64
The centroid’s y-coordinate.
Notes
The centroid represents the geometric center of the polygon. It is computed as the ratio of the first moment of area about the z-axis to the total area.
\[\bar{y} = \frac{S_y}{A}\]where
\(S_y\) is the static moment about the z-axis
\(A\) is the total area of the polygon
This assumes uniform density and thickness.
- property center_of_mass_z#
Computes the z-coordinate of the centroid (center of mass).
- Returns:
- np.float64
The centroid’s z-coordinate.
Notes
The centroid represents the geometric center of the polygon. It is computed as the ratio of the first moment of area about the y-axis to the total area.
\[\bar{z} = \frac{S_z}{A}\]where
\(S_z\) is the static moment about the y-axis
\(A\) is the total area of the polygon
This assumes uniform density and thickness.
- property height#
Computes the height of the polygon in the local z-direction.
- Returns:
- np.float64
The height of the polygon (i.e., the range of z-coordinates).
Notes
The height is defined as:
\[h = z_\text{max} - z_\text{min}\]where \(z_\text{max}\) and \(z_\text{min}\) are the maximum and minimum vertical coordinates of the polygon’s boundary, including holes.
- property iyy#
Returns the second moment of area about the y-axis.
- Returns:
floatMoment of inertia \(I_{yy}\) about the y-axis, relative to the centroidal coordinate system, in units of length⁴.
Notes
This value is extracted from the full second moment of inertia tensor and reflects the resistance of the shape to bending about the y-axis.
- property iyz#
Returns the product moment of inertia.
- Returns:
floatProduct moment of inertia \(I_{yz}\) relative to the centroidal coordinate system, in units of length⁴.
Notes
A nonzero product moment of inertia indicates that the principal axes of the shape are rotated relative to the coordinate system. This value is symmetric, i.e., \(I_{yz} = I_{zy}\).
- property izz#
Returns the second moment of area about the z-axis.
- Returns:
floatMoment of inertia \(I_{zz}\) about the z-axis, relative to the centroidal coordinate system, in units of length⁴.
Notes
This quantity indicates the resistance of the shape to bending about the z-axis and is derived from the inertia tensor.
- mom_of_int_steiner(center)#
Applies the parallel axis theorem (Steiner’s theorem) to compute the moment of inertia about a shifted axis.
- Parameters:
- center
float The perpendicular distance from the centroid to the desired axis (in the same units as the polygon coordinates).
- center
- Returns:
floatThe additional moment of inertia due to the axis shift, i.e. \(I_{\text{shift}} = A \cdot d^2\), where \(A\) is the area and \(d\) is the distance to the new axis.
Notes
This is used to shift the moment of inertia from the centroidal axis to another parallel axis according to the parallel axis theorem:
\[I = I_c + A \cdot d^2\]
- property moments_of_inertia_tensor#
Computes the second moment of area tensor (also known as the area moment of inertia tensor) relative to the centroid of the polygon.
- Returns:
- ndarray
A 2×2 symmetric numpy array representing the inertia tensor:
\[\begin{split}\begin{bmatrix} I_{yy} & I_{yz} \\ I_{zy} & I_{zz} \end{bmatrix}\end{split}\]All entries are in units of length⁴.
Notes
The components are initially computed relative to the origin and then shifted to the centroid using the parallel axis theorem:
\[\begin{split}I_{yy}^{\text{centroid}} = I_{yy}^0 - A \cdot z_c^2 \\ I_{zz}^{\text{centroid}} = I_{zz}^0 - A \cdot y_c^2 \\ I_{yz}^{\text{centroid}} = I_{yz}^0 - A \cdot y_c z_c\end{split}\]- where:
\(A\) is the area,
\((y_c, z_c)\) is the centroid.
This tensor is useful for calculating principal axes and moments, and for evaluating bending behavior in 2D beam cross-sections.
- property static_moment#
Computes the static moments \(S_z\) and \(S_y\) with respect to the coordinate axes.
- Returns:
- tuple of float or np.float64
The static moments (S_z, S_y) of the polygon.
Notes
The static moments (also called first moments of area) are used to compute the centroid of the polygon.
\[S_z = -\frac{1}{6} \sum (y_i z_{i-1} - y_{i-1} z_i) (z_i + z_{i-1})\]\[S_y = -\frac{1}{6} \sum (y_i z_{i-1} - y_{i-1} z_i) (y_i + y_{i-1})\]These are discrete approximations of the first moments:
\[S_z = \int_A z \, \mathrm{d}A, \quad S_y = \int_A y \, \mathrm{d}A\]Examples
Without holes:
>>> from sstatics.core.preprocessing.geometry.objects import Polygon >>> outer = [(0, 0), (4, 0), (4, 2), (0, 2), (0, 0)] >>> p = Polygon(points=outer) >>> sz, sy = p.static_moment >>> round(sz, 2) 10.67 >>> round(sy, 2) 21.33
- property width#
Computes the width of the polygon in the local y-direction.
- Returns:
- np.float64
The width of the polygon (i.e., the range of y-coordinates).
Notes
The width is defined as:
\[w = y_\text{max} - y_\text{min}\]where \(y_\text{max}\) and \(y_\text{min}\) are the maximum and minimum horizontal coordinates of the polygon’s boundary, including holes.
- class sstatics.core.preprocessing.geometry.operation.PolygonMerge(*a, **k)#
Bases:
LoggerMixinRepresents a combination of multiple positive and negative polygons, and provides methods to compute their geometric difference.
This class is used to merge a list of “positive” polygons and subtract one or more “negative” polygons (holes or cut-outs) from the result. Internally, it uses geometric union and difference operations based on Shapely.
- Parameters:
- positivelist of
Polygon, optional A list of polygons that define the base area to be merged. At least one polygon must be provided. All elements must be instances of the custom Polygon class.
- negativelist of
Polygon, optional A list of polygons to be subtracted (cut out) from the merged positive geometry. These are treated as holes or exclusions. Defaults to an empty list.
- positivelist of
- Attributes:
- positivelist of
Polygon The list of input polygons to be merged.
- negativelist of
Polygon The list of polygons to subtract from the merged positive area.
- unary_posshapely.geometry.Polygon or MultiPolygon
Union geometry of all positive polygons.
- unary_negshapely.geometry.Polygon or MultiPolygon or None
Union geometry of all negative polygons, or None if empty.
- positivelist of
- Raises:
- ValueError
If the positive list is empty.
- TypeError
If any element of positive or negative is not an instance of Polygon.
- difference()#
Computes the geometric difference between the union of the positive polygons and the union of the negative polygons.
- Returns:
PolygonA new Polygon instance representing the result of the difference operation.
- Raises:
- NotImplementedError
If the resulting geometry is a MultiPolygon, which is currently not supported.
- property logger#
Returns the logger instance associated with this object.
- Returns:
- logging.Logger
The configured logger.
- class sstatics.core.preprocessing.geometry.operation.SectorToPolygonHandler(*a, **k)#
Bases:
LoggerMixinHandles the interaction between regular polygons and circular sectors.
This class is responsible for checking overlaps between circular sectors and existing polygons. If an overlap is detected, the circular sector is converted into a polygon and added to the list of polygons. Otherwise, it is kept as a remaining circular sector.
- Parameters:
- polygonslist of Polygon
A list of existing polygonal shapes. Each element must be an instance of the custom Polygon class.
- circularlist of CircularSector
A list of circular sectors to be tested against the polygons. Each element must be an instance of CircularSector.
- Attributes:
- polygonslist of Polygon
The original list of polygon shapes.
- circular_sectorlist of CircularSector
The original list of circular sectors to be tested and potentially converted.
- Raises:
- TypeError
If any element in polygons is not a Polygon, or any element in circular is not a CircularSector.
- static bounding_boxes_overlap(a, b)#
Checks whether the bounding boxes of two Shapely polygons overlap.
- Parameters:
- ashapely.geometry.Polygon
First polygon.
- bshapely.geometry.Polygon
Second polygon.
- Returns:
- bool
True if the bounding boxes overlap, False otherwise.
- execute()#
Converts intersecting circular sectors to polygons and separates non-intersecting ones.
Each circular sector is checked for intersection with the existing polygons. If it intersects any polygon (based on bounding box and area of geometric intersection), it is converted to a polygon and added to the polygon list. Otherwise, it remains as a circular sector.
- Returns:
- tuple of (list of Polygon, list of CircularSector)
A list of polygons including the original ones and those converted from intersecting sectors.
A list of circular sectors that did not intersect any polygon.
- property logger#
Returns the logger instance associated with this object.
- Returns:
- logging.Logger
The configured logger.