Reduction Theorem: Calculate Deformation#
Computing the vertical deformation w at midspan of Bar 2 using the Reduction Theorem
In this example, the vertical deformation w at the midpoint of Bar 2 is computed using the Reduction Theorem. The frame is initially statically indeterminate with a degree of indeterminacy equal to 1. By introducing a hinge at the right end of Bar 2, the system becomes statically determinate and suitable for applying the Reduction Theorem.
To obtain the desired deformation at midspan, a virtual vertical load is applied at position x = 0.5 of Bar 2. The deformation is computed from the work equation of the virtual system.
To verify the correctness of the procedure, the same deformation is calculated analytically using classical integration-table formulas. Both results agree within numerical tolerance, confirming the correctness of the computed internal forces and the Reduction Theorem implementation.
You can find the example as an executable Python file here.
Define the Structural System#
In this section, the static system is modeled. For a detailed step-by-step workflow, refer to the “Getting Started” example.
[1]:
# 1. Import required modules
from sstatics.core.calc_methods import ReductionTheorem
from sstatics.core.preprocessing import (
Node, Bar, Material, CrossSection, System, BarLineLoad
)
from sstatics.core.postprocessing.graphic_objects import ObjectRenderer, SystemGeo
import numpy as np
# 2. Define material and cross-section
material = Material(21000, 1, 1, 1)
cs = CrossSection(1, 1, 1, 1, 1)
# 3. Define frame nodes
n1 = Node(0, 0, u='fixed', w='fixed')
n2 = Node(0, -2)
n3 = Node(4, -2)
n4 = Node(4, 0, u='fixed', w='fixed')
# 4. Define loads
line_load = BarLineLoad(pi=2.5, pj=2.5, direction='z')
# 5. Define bars
bar_1 = Bar(n1, n2, cs, material, deformations="moment")
bar_2 = Bar(n2, n3, cs, material, line_loads=line_load,
deformations="moment")
bar_3 = Bar(n3, n4, cs, material, deformations="moment")
system = System([bar_1, bar_2, bar_3])
# Visualize system
ObjectRenderer(SystemGeo(system, show_bar_text=True), 'mpl').show(show_axis=False)
Perform the Reduction Theorem#
Next, we pass the modeled system to the ReductionTheorem class.
[2]:
# 6. Initialize Reduction Theorem
red = ReductionTheorem(system)
Determine the Degree of Static Indeterminacy#
Before creating a released system, it is necessary to determine the degree of static indeterminacy. This value can be obtained using the function degree_of_static_indeterminacy.
For our modeled system, the degree of static indeterminacy is:
[3]:
print("Degree of static indeterminacy (before):",
red.degree_of_static_indeterminacy)
Degree of static indeterminacy (before): 1
Create Released System#
We now know that our modeled system is statically indeterminate of degree 1. The released system represents the corresponding statically determinate system of the original model.
To obtain such a system, certain restraints must be released. However, it is essential that the structure remains stable after doing so.
There are three available methods:
``modify_node()`` Modifies a support condition. The modeled node is passed to the function, and the specific degree of freedom to be released is defined.
``modify_bar()`` Modifies a bar by introducing a hinge. The modeled bar is passed to the function, and a hinge is added to release the corresponding internal restraint.
``delete_bar()`` Removes a bar from the structure. However, the software does not internally check the deformation contributions to verify whether removing a bar is structurally safe.
In this example, we choose to introduce a moment hinge at the end of bar 2.
[4]:
# 7. Remove the redundant rotational constraint by inserting a hinge
red.modify_bar(bar_2, 'hinge_phi_j')
Check the Degree of Static Indeterminacy Again#
Now we check the degree of static indeterminacy once more to verify that it is now equal to 0. A value of 0 indicates that the system is statically determinate, meaning the released system has been successfully created.
[5]:
print("Degree of static indeterminacy (after):",
red.degree_of_static_indeterminacy)
Degree of static indeterminacy (after): 0
The released system is now statically determinate.
Plot the Released System#
It is possible to visualize the released system using plot_released_system(). This allows you to inspect the modified structure and verify which connections or supports were released.
[6]:
# Show the released system
red.plot_released_system()
Create a Virtual Load System#
Once the released system has been fully created, we can generate the corresponding virtual load system based on it.
A virtual load must be applied at the exact location where the deformation is to be evaluated. There are three options for defining such a virtual load:
``add_virtual_node_load`` – apply a virtual nodal load
``add_virtual_bar_load`` – apply a virtual load directly to a bar
``add_virtual_moment_couple`` – apply a virtual moment couple
⚠️ Note: Only one virtual load may be applied in the virtual system.
In this example, the goal is to compute the vertical deformation at the midspan of bar 2. Therefore, a virtual bar load in the z-direction is applied at the relative position 0.5 along the bar. With this step, the virtual system is fully defined.
[7]:
# 8. Apply a virtual unit vertical load at midspan of Bar 2
red.add_virtual_bar_load(bar_2, 'fz', position=0.5)
# Show virtual system
ObjectRenderer(SystemGeo(red.virtual_system), 'mpl').show(show_axis=False)
Retrieve the Desired Deformation#
The requested deformation can now be obtained using the deformation() function. Depending on the material properties, cross-section parameters and the nodal coordinates provided, the deformation is returned in the corresponding unit.
[8]:
# 9. Compute deformation using the Reduction Theorem
delta_reduction = red.deformation()
print("w(midspan) (Reduction Theorem):", delta_reduction)
# Expected: ~1.587747932183352e-04 m
w(midspan) (Reduction Theorem): 0.0001587747932183352
Verify the Results#
In the next step, we verify the computed deformation to ensure its correctness. To do this, the hand-calculation is replicated using integration tables. For the manual evaluation, the moment diagrams of both systems are needed:
the original system with real loads, and
the released system with the applied virtual load.
To obtain these moment distributions, both systems are plotted with their corresponding bending moment diagrams. These plots allow a direct comparison between the numerical results and the hand-calculated integration approach.
[9]:
# 10. Hand calculation using classical integration tables
red.plot('real', kind='moment')
red.plot('virt', kind='moment')
To compute the deformation, the moment areas are now superimposed using the formulas from the integration tables.
[10]:
delta_hand = (
1/2 * 1 * (-2.5) * 4 / 21000 +
5/12 * 1 * 5 * 4 / 21000
)
print("w(midspan) (Hand calculation):", delta_hand)
# Expected: ~1.5873015873e-04 m
w(midspan) (Hand calculation): 0.00015873015873015878
Comparison of the Two Methods
The deformations obtained from both methods can now be compared.
[11]:
# 11. Verify equality of both methods
print("Results match:",
np.allclose(delta_reduction, delta_hand, atol=1e-7))
Results match: True
This demonstrates that the results from both methods match, confirming the validity of the calculations.