PART 4 - 966 feature request add torsion steel check#968
PART 4 - 966 feature request add torsion steel check#968GerjanDorgelo wants to merge 69 commits into
Conversation
…istance checks and enhance Report class with equation splitting functionality
…vironments and rename split_on to split_after for clarity
…ests for equation handling
… output format to PDF
… and update tests accordingly
…ge properties for calculations
…able naming for flange properties
…RolledIandHSection
…prehensive test coverage
…earStrengthIProfileCheck
…Check tests for accuracy
…ion block for HEB profile
…StrengthIProfileCheck
… update related tests
📝 WalkthroughWalkthroughThis PR adds three new Eurocode 3 steel strength check modules (shear, torsion, combined torsion-shear) for Class 1/2 and 3/4 sections, refactors formula 6.18 sub A to support split-flange geometry, extends the Profile API with stress calculation methods, enhances equation rendering with multi-line support, and includes comprehensive test coverage. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant CheckShear as CheckStrengthShear<br/>(Class12/34)
participant Profile as SteelCrossSection<br/>& Profile
participant Formula as Formula<br/>Components
participant Report as Report<br/>Generator
User->>CheckShear: Instantiate with v, axis,<br/>gamma_m0
CheckShear->>Profile: Access cross-section<br/>geometry & material
CheckShear->>Profile: Retrieve unit stresses or<br/>compute shear area
Profile-->>CheckShear: Return stress/area data
CheckShear->>Formula: Build shear_area() or<br/>shear_stress() formula
Formula-->>CheckShear: Formula object
CheckShear->>Formula: Build plastic/elastic<br/>resistance formula
Formula-->>CheckShear: Resistance formula
CheckShear->>Formula: Build unity_check formula<br/>(v_ed / v_pl_rd or tau_ed / tau_max)
Formula-->>CheckShear: Unity check formula
CheckShear->>CheckShear: Evaluate unity_check<br/>& compute result()
CheckShear->>Report: Generate detailed report()<br/>with formulas, values,<br/>& conditional messaging
Report-->>CheckShear: Report object
CheckShear-->>User: Return CheckResult<br/>& Report
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 6✅ Passed checks (6 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #968 +/- ##
==========================================
Coverage 100.00% 100.00%
==========================================
Files 423 426 +3
Lines 13121 13477 +356
==========================================
+ Hits 13121 13477 +356 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…nd improve stress calculation in CheckStrengthShearClass34
…les' into 966-feature-request-add-torsion-steel-check
…date references in tests
…heckStrengthTorsionShearClass34 for class 3 and 4 sections
…perties parameter and improve fixture definitions
…les' of https://github.com/Blueprints-org/blueprints into 960-feature-request-add-plastic-shear-check-for-i-profiles
…dd-plastic-shear-check-for-i-profiles
…earClass12 for consistency
…ng NotImplementedError for unsupported profile types test: add tests for source_docs() method in CheckStrengthShearClass12 and CheckStrengthShearClass34
…dd-torsion-steel-check
…les' into 966-feature-request-add-torsion-steel-check
- Updated CheckStrengthStVenantTorsionClass1234 to streamline calculations and improve clarity. - Introduced static method for source documents and refined torsional resistance calculations. - Enhanced reporting functionality to provide clearer output for torsion checks. - Refactored CheckStrengthTorsionShearClass12IProfile and CheckStrengthTorsionShearClass34 to improve structure and readability. - Updated test cases for torsion strength checks to remove unnecessary section properties and improve clarity. - Ensured all tests pass with the new structure and logic.
…engthTorsionShearClass12 and update references
…s; update torsion shear check documentation
There was a problem hiding this comment.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tests/utils/test_report.py (1)
106-110:⚠️ Potential issue | 🟡 MinorTest renamed to
test_multline_add_text_calls— likely a typo.This test validates multiple sequential
add_paragraphcalls, not the LaTeXmultlineenvironment. The rename fromtest_multiline_add_text_callstotest_multline_add_text_callsappears to be an accidental edit. "multiline" (natural English) fits the test's purpose better than "multline" (the LaTeX environment name), since this test has nothing to do with equation splitting.
🤖 Fix all issues with AI agents
In `@blueprints/checks/eurocode/steel/strength_shear.py`:
- Around line 204-206: The class docstring for CheckStrengthShearClass34
incorrectly says "plastic" while the implementation (and the name field "Elastic
shear strength check") performs the elastic shear check (formula 6.19); update
the docstring to describe the elastic shear force resistance check for steel
cross-section class 3 and 4 (Eurocode 3), optionally referencing formula 6.19 to
match the implemented behavior in CheckStrengthShearClass34 and keep the
description consistent with the `name` attribute.
- Around line 105-107: Replace the runtime-only assertion in the I-profile shear
area calculation with a hard validation that always runs: in the function that
contains the assert checking parameters a, b1, b2, tf1, tf2, tw, hw, r1, r2 (the
I-profile shear area calculator in strength_shear.py) raise a ValueError (or a
custom validation exception) with the same message when any of those params is
None instead of using assert; keep the same message text ("All profile
parameters must be defined for I-profile shear area calculation.") and reference
the same parameter names so callers and tests can detect and handle the
validation error.
- Around line 278-287: elastic_resistance() can produce NaN when shear_stress()
returns 0 (e.g. when self.v == 0) due to 0*inf semantics; update
elastic_resistance to guard against zero shear stress or zero shear force by
checking sig_zxy == 0 or self.v == 0 and return 0.0 in that case, otherwise
compute the existing formula using self.steel_cross_section.yield_strength,
self.gamma_m0 and KN_TO_N; reference the elastic_resistance and shear_stress
methods and the attributes self.v, self.steel_cross_section.yield_strength, and
self.gamma_m0.
In `@blueprints/checks/eurocode/steel/strength_torsion_shear.py`:
- Around line 213-219: The report shows signed torsional stress because
total_stress_val is computed with the signed moment; update the calculation in
strength_torsion_shear.py so total_stress_val = unit_torsional_shear_stress() *
abs(self.m_x) (use abs(self.m_x) instead of self.m_x) and then pass that
absolute value into report.add_paragraph (references:
unit_torsional_shear_stress, m_x, total_stress_val, report.add_paragraph) to
match the check logic that uses abs(self.m_x).
- Line 1: Update the module docstring in
blueprints/checks/eurocode/steel/strength_torsion_shear.py to correctly
reference "Eurocode 3 (EN 1993-1-1)" instead of "Eurocode 2" and state that the
implemented checks use formulas 6.25/6.26 for combined torsion and shear (not
6.23); keep the brief description of the module purpose (torsional shear stress
resistance with shear force present) but correct the standard and formula
numbers to match the implemented logic in this module.
- Around line 56-69: The example uses an undefined variable mx when constructing
CheckStrengthTorsionShearClass12; change the argument to use the declared m_x
variable (i.e., pass m_x into CheckStrengthTorsionShearClass12) so the call to
CheckStrengthTorsionShearClass12(heb_300_s355, mx, v=v, axis=axis, gamma_m0=1.0)
becomes consistent with the earlier m_x declaration and avoids the NameError.
In `@blueprints/checks/eurocode/steel/strength_torsion.py`:
- Line 1: The module docstring in
blueprints/checks/eurocode/steel/strength_torsion.py incorrectly says "Eurocode
2"; update the top-level docstring to reference "Eurocode 3" (EN 1993-1-1) and
adjust the descriptive text accordingly so the module correctly states it
implements torsional shear stress resistance per Eurocode 3 (EN 1993-1-1).
- Around line 45-58: Update the example to use the actual class name and import
path: replace the import of TorsionStrengthCheck from
blueprints.checks.eurocode.steel.torsion_strength with the correct import of
CheckStrengthStVenantTorsionClass1234 from
blueprints.checks.eurocode.steel.strength_torsion, and instantiate that class
(replace TorsionStrengthCheck(...) with
CheckStrengthStVenantTorsionClass1234(...)) so the example matches the real
symbol names.
In `@blueprints/structural_sections/_profile.py`:
- Around line 236-239: The Returns docstring incorrectly states "Callable[...,
StressPost]" but the method returns a StressPost directly (it calls
section.calculate_stress(...)); update the Returns section to "StressPost" and
change the description to reflect that the function returns a StressPost
instance (e.g., "StressPost — stress distribution result from
section.calculate_stress") so the docstring matches the actual return value.
- Around line 269-289: The docstring for the unit_stress method incorrectly
declares the return type as StressPost; update the docstring to match the actual
return type (dict[str, Any]) or otherwise describe that it returns a dictionary
representing the unit stress distribution. Locate the unit_stress method and
change the "Returns" section (and the type on the first line of the docstring,
if present) so it accurately states dict[str, Any] and describes the returned
dict from calculate_stress(...).get_stress()[0]; leave the implementation and
the _unit_stress_cache handling unchanged.
In `@tests/checks/eurocode/steel/test_strength_torsion.py`:
- Around line 26-44: Rename the two misnamed test functions to reflect they test
torsion: change test_result_tension_ok to test_result_torsion_ok and
test_result_tension_not_ok to test_result_torsion_not_ok; update any
references/usages (e.g., in test discovery or fixtures) and keep the body
unchanged — these tests instantiate CheckStrengthStVenantTorsionClass1234 with
m_x and assert torsional unity_check/factor_of_safety, so only the function
names need renaming for clarity.
🧹 Nitpick comments (10)
blueprints/utils/report/report.py (1)
153-174: The sort comment is slightly misleading but the logic is correct.The comment on line 158 says "Sort by decreasing index so insertion doesn't affect later positions," but the sort is on the tuple
(n, char), not on the actual string position. The code still works correctly because each\\insertion doesn't introduce new occurrences of the target split characters, so subsequent searches on the modified string always find the correct nth occurrence regardless of processing order.One edge-case to be aware of: if
split_afteris used with inline equations (line 177), the\\line breaks inside$...$inline math won't render as line breaks. Consider guarding against this or documenting thatsplit_afteris only meaningful for block equations.blueprints/checks/eurocode/steel/strength_torsion_shear.py (2)
78-78:section_propertiesfield is declared but never used in Class12.The field is accepted and stored, but none of the methods (e.g.
unit_torsional_shear_stress,shear_area,raw_shear_resistance, etc.) referenceself.section_properties. Compare withCheckStrengthStVenantTorsionClass1234instrength_torsion.pywhich actually populates and uses it in__post_init__. If this is intended for future use, consider removing it to avoid confusion, or wire it up if it was intended to be used.
81-85: Consider usingisinstanceinstead of exacttype()check.
type(...) not in implemented_shapeswon't match subclasses ofIProfile. While this may not be an issue today,isinstanceis the idiomatic check and is more resilient to future inheritance.📝 Proposed fix
- implemented_shapes = (IProfile,) - if type(self.steel_cross_section.profile) not in implemented_shapes: + if not isinstance(self.steel_cross_section.profile, IProfile): raise NotImplementedError(f"The provided profile shape {type(self.steel_cross_section.profile).__name__} has not been implemented yet.")tests/checks/eurocode/steel/test_strength_torsion_shear.py (1)
73-79: Mutating a class-scoped frozen fixture is fragile and order-dependent.Using
object.__setattr__(heb_steel_cross_section, "fabrication_method", ...)on ascope="class"fixture modifies shared state across all tests in the class. This makes tests order-dependent — for example,test_source_docswill see whateverfabrication_methodwas last set by a preceding test. If tests are reordered or run in isolation, results could differ.Consider using the dedicated
heb_welded_steel_cross_sectionfixture (already defined in conftest) instead of mutating the shared one, or switch toscope="function"for fixtures that need per-test mutation.Also applies to: 83-83, 100-102
blueprints/checks/eurocode/steel/strength_torsion.py (1)
64-71:section_propertiesis computed and cached but never read by any method.
__post_init__populatesself.section_properties, butunit_torsional_shear_stress(),torsional_resistance(), and other methods never reference it — they go throughself.steel_cross_section.profile.unit_stress()which independently creates its ownSectionand computes its own properties. Either this field should be wired into the computation path, or it can be removed to avoid the unnecessary overhead of computing section properties that are never used.tests/checks/eurocode/steel/test_strength_shear.py (3)
29-30: Non-standardpytest.approxargument order.Throughout the tests,
pytest.approx(result.unity_check, 0.005)is used as the left-hand side of==. While this works (the second positional arg isrel), the idiomatic pattern is to placepytest.approxon the expected side:assert result.unity_check == pytest.approx(0.99, rel=0.005)This makes the test intent clearer ("actual ≈ expected") and avoids confusion about the positional
relargument. This pattern is repeated throughout the file (~20 occurrences).
115-116: Dead comparison —calc_without_section_propsis identical tocalc.The variable name
calc_without_section_propsimplies this was testing a scenario wheresection_propertiesis omitted, butCheckStrengthShearClass34no longer has asection_propertiesparameter. Both instances are constructed identically, soassert calc == calc_without_section_propsis trivially true and tests nothing useful.Either remove the redundant assertion or, if testing equality semantics is intended, add a brief comment explaining the purpose.
25-25: Consider documenting the origin of the "magic" capacity values.The test values like
355 * 4.74 / 1.732 * 0.99encodef_y * A_v_cm² / √3 * utilization_ratio, but this is not immediately obvious. A brief inline comment explaining the formula would help future maintainers verify correctness, e.g.:# V_pl_Rd ≈ f_y * A_v / √3 (units: N/mm² * cm² → kN after implicit conversion) v = 355 * 4.74 / 1.732 * 0.99This applies to all similar test value computations in this file.
blueprints/utils/report/_report_to_word.py (2)
444-461: Multi-line equation rendering looks correct.The approach of stripping environment wrappers, splitting on
\\, and rendering each chunk as a separate centered paragraph is clean. Tag placement on the final line only is the correct behavior for numbered multi-line equations.One minor edge-case: if the equation content happens to produce an empty string after splitting (e.g., trailing
\\),self._formula("")would be called and could fail inlatex2mathml. Consider filtering out blank lines:Optional defensive guard
- for idx, line in enumerate(lines): + for idx, line in enumerate(lines): + if not line.strip(): + continue
178-178: Regex capturesmultline|equationbut the group is unused.The pattern
r"\\begin\{(multline|equation)\}"includes a capture group, but the matched group value is never read — the type is always set to"equation"from the dictionary key. This works correctly but the capture group is unnecessary. A non-capturing group(?:multline|equation)would be slightly more precise.
| assert all(param is not None for param in [a, b1, b2, tf1, tf2, tw, hw, r1, r2]), ( | ||
| "All profile parameters must be defined for I-profile shear area calculation." | ||
| ) |
There was a problem hiding this comment.
assert used for production validation — can be silently disabled with python -O.
Using assert for input validation is unreliable because assertions are stripped when Python runs with the -O (optimize) flag. Replace with an explicit ValueError or a custom validation exception to guarantee the check always runs.
Proposed fix
- assert all(param is not None for param in [a, b1, b2, tf1, tf2, tw, hw, r1, r2]), (
- "All profile parameters must be defined for I-profile shear area calculation."
- )
+ if not all(param is not None for param in [a, b1, b2, tf1, tf2, tw, hw, r1, r2]):
+ raise ValueError("All profile parameters must be defined for I-profile shear area calculation.")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| assert all(param is not None for param in [a, b1, b2, tf1, tf2, tw, hw, r1, r2]), ( | |
| "All profile parameters must be defined for I-profile shear area calculation." | |
| ) | |
| if not all(param is not None for param in [a, b1, b2, tf1, tf2, tw, hw, r1, r2]): | |
| raise ValueError("All profile parameters must be defined for I-profile shear area calculation.") |
🤖 Prompt for AI Agents
In `@blueprints/checks/eurocode/steel/strength_shear.py` around lines 105 - 107,
Replace the runtime-only assertion in the I-profile shear area calculation with
a hard validation that always runs: in the function that contains the assert
checking parameters a, b1, b2, tf1, tf2, tw, hw, r1, r2 (the I-profile shear
area calculator in strength_shear.py) raise a ValueError (or a custom validation
exception) with the same message when any of those params is None instead of
using assert; keep the same message text ("All profile parameters must be
defined for I-profile shear area calculation.") and reference the same parameter
names so callers and tests can detect and handle the validation error.
| @dataclass(frozen=True) | ||
| class CheckStrengthShearClass34: | ||
| """Class to perform plastic shear force resistance check for steel cross-section class 3 and 4 (Eurocode 3). |
There was a problem hiding this comment.
Docstring says "plastic" but this is the elastic shear check.
The class docstring reads "Class to perform plastic shear force resistance check…" but CheckStrengthShearClass34 implements the elastic shear check (formula 6.19, not 6.18). The name field on line 254 correctly says "Elastic shear strength check", so this is just a copy-paste slip in the docstring.
- """Class to perform plastic shear force resistance check for steel cross-section class 3 and 4 (Eurocode 3).
+ """Class to perform elastic shear force resistance check for steel cross-section class 3 and 4 (Eurocode 3).📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @dataclass(frozen=True) | |
| class CheckStrengthShearClass34: | |
| """Class to perform plastic shear force resistance check for steel cross-section class 3 and 4 (Eurocode 3). | |
| `@dataclass`(frozen=True) | |
| class CheckStrengthShearClass34: | |
| """Class to perform elastic shear force resistance check for steel cross-section class 3 and 4 (Eurocode 3). |
🤖 Prompt for AI Agents
In `@blueprints/checks/eurocode/steel/strength_shear.py` around lines 204 - 206,
The class docstring for CheckStrengthShearClass34 incorrectly says "plastic"
while the implementation (and the name field "Elastic shear strength check")
performs the elastic shear check (formula 6.19); update the docstring to
describe the elastic shear force resistance check for steel cross-section class
3 and 4 (Eurocode 3), optionally referencing formula 6.19 to match the
implemented behavior in CheckStrengthShearClass34 and keep the description
consistent with the `name` attribute.
| def elastic_resistance(self) -> float: | ||
| """Calculate the shear force elastic resistance of the steel cross-section (EN 1993-1-1:2005 art. 6.2.6). | ||
|
|
||
| Returns | ||
| ------- | ||
| float | ||
| The calculated shear force resistance in N. | ||
| """ | ||
| sig_zxy = self.shear_stress() | ||
| return float(self.steel_cross_section.yield_strength / np.sqrt(3) / self.gamma_m0 / sig_zxy * abs(self.v) * KN_TO_N) |
There was a problem hiding this comment.
Division by zero in elastic_resistance() when v == 0.
When v == 0, shear_stress() returns 0, and the expression ... / sig_zxy * abs(self.v) ... evaluates to inf * 0 = nan (numpy semantics). This nan is then passed to CheckResult.from_comparison, which appears to handle provided == 0 gracefully (tests pass), but the intermediate nan is fragile and could break if CheckResult or downstream logic changes.
Consider guarding explicitly:
Proposed fix
def elastic_resistance(self) -> float:
...
sig_zxy = self.shear_stress()
+ if sig_zxy == 0:
+ return float("inf")
return float(self.steel_cross_section.yield_strength / np.sqrt(3) / self.gamma_m0 / sig_zxy * abs(self.v) * KN_TO_N)🤖 Prompt for AI Agents
In `@blueprints/checks/eurocode/steel/strength_shear.py` around lines 278 - 287,
elastic_resistance() can produce NaN when shear_stress() returns 0 (e.g. when
self.v == 0) due to 0*inf semantics; update elastic_resistance to guard against
zero shear stress or zero shear force by checking sig_zxy == 0 or self.v == 0
and return 0.0 in that case, otherwise compute the existing formula using
self.steel_cross_section.yield_strength, self.gamma_m0 and KN_TO_N; reference
the elastic_resistance and shear_stress methods and the attributes self.v,
self.steel_cross_section.yield_strength, and self.gamma_m0.
| @@ -0,0 +1,413 @@ | |||
| """Module for checking torsional shear stress resistance with shear force present (Eurocode 2, formula 6.23).""" | |||
There was a problem hiding this comment.
Module docstring references "Eurocode 2" instead of "Eurocode 3".
EN 1993-1-1 is Eurocode 3 (steel structures), not Eurocode 2 (concrete). Also, this module implements formulas 6.25/6.26 (combined torsion + shear), not 6.23.
📝 Proposed fix
-"""Module for checking torsional shear stress resistance with shear force present (Eurocode 2, formula 6.23)."""
+"""Module for checking torsional shear stress resistance with shear force present (Eurocode 3, EN 1993-1-1:2005, formulas 6.25/6.26)."""📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| """Module for checking torsional shear stress resistance with shear force present (Eurocode 2, formula 6.23).""" | |
| """Module for checking torsional shear stress resistance with shear force present (Eurocode 3, EN 1993-1-1:2005, formulas 6.25/6.26).""" |
🤖 Prompt for AI Agents
In `@blueprints/checks/eurocode/steel/strength_torsion_shear.py` at line 1, Update
the module docstring in
blueprints/checks/eurocode/steel/strength_torsion_shear.py to correctly
reference "Eurocode 3 (EN 1993-1-1)" instead of "Eurocode 2" and state that the
implemented checks use formulas 6.25/6.26 for combined torsion and shear (not
6.23); keep the brief description of the module purpose (torsional shear stress
resistance with shear force present) but correct the standard and formula
numbers to match the implemented logic in this module.
| ------- | ||
| from blueprints.checks.eurocode.steel.strength_torsion_shear import CheckStrengthTorsionShearClass12 | ||
| from blueprints.materials.steel import SteelMaterial, SteelStrengthClass | ||
| from blueprints.structural_sections.steel.standard_profiles.heb import HEB | ||
|
|
||
| steel_material = SteelMaterial(steel_class=SteelStrengthClass.S355) | ||
| heb_300_profile = HEB.HEB300.with_corrosion(1.5) | ||
| m_x = 10 # Applied torsional moment in kNm | ||
| v = 100 # Applied shear force in kN | ||
| axis = "Vz" # Shear force applied in z-direction | ||
|
|
||
| heb_300_s355 = SteelCrossSection(profile=heb_300_profile, material=steel_material) | ||
| calc = CheckStrengthTorsionShearClass12(heb_300_s355, mx, v=v, axis=axis, gamma_m0=1.0) | ||
| calc.report().to_word("torsion_and_shear_strength.docx", language="nl") |
There was a problem hiding this comment.
Example code has an undefined variable mx.
Line 68 references mx but the local variable on line 63 is m_x. This will cause a NameError if anyone copies the example.
📝 Proposed fix
- calc = CheckStrengthTorsionShearClass12(heb_300_s355, mx, v=v, axis=axis, gamma_m0=1.0)
+ calc = CheckStrengthTorsionShearClass12(heb_300_s355, m_x=m_x, v=v, axis=axis, gamma_m0=1.0)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ------- | |
| from blueprints.checks.eurocode.steel.strength_torsion_shear import CheckStrengthTorsionShearClass12 | |
| from blueprints.materials.steel import SteelMaterial, SteelStrengthClass | |
| from blueprints.structural_sections.steel.standard_profiles.heb import HEB | |
| steel_material = SteelMaterial(steel_class=SteelStrengthClass.S355) | |
| heb_300_profile = HEB.HEB300.with_corrosion(1.5) | |
| m_x = 10 # Applied torsional moment in kNm | |
| v = 100 # Applied shear force in kN | |
| axis = "Vz" # Shear force applied in z-direction | |
| heb_300_s355 = SteelCrossSection(profile=heb_300_profile, material=steel_material) | |
| calc = CheckStrengthTorsionShearClass12(heb_300_s355, mx, v=v, axis=axis, gamma_m0=1.0) | |
| calc.report().to_word("torsion_and_shear_strength.docx", language="nl") | |
| ------- | |
| from blueprints.checks.eurocode.steel.strength_torsion_shear import CheckStrengthTorsionShearClass12 | |
| from blueprints.materials.steel import SteelMaterial, SteelStrengthClass | |
| from blueprints.structural_sections.steel.standard_profiles.heb import HEB | |
| steel_material = SteelMaterial(steel_class=SteelStrengthClass.S355) | |
| heb_300_profile = HEB.HEB300.with_corrosion(1.5) | |
| m_x = 10 # Applied torsional moment in kNm | |
| v = 100 # Applied shear force in kN | |
| axis = "Vz" # Shear force applied in z-direction | |
| heb_300_s355 = SteelCrossSection(profile=heb_300_profile, material=steel_material) | |
| calc = CheckStrengthTorsionShearClass12(heb_300_s355, m_x=m_x, v=v, axis=axis, gamma_m0=1.0) | |
| calc.report().to_word("torsion_and_shear_strength.docx", language="nl") |
🤖 Prompt for AI Agents
In `@blueprints/checks/eurocode/steel/strength_torsion_shear.py` around lines 56 -
69, The example uses an undefined variable mx when constructing
CheckStrengthTorsionShearClass12; change the argument to use the declared m_x
variable (i.e., pass m_x into CheckStrengthTorsionShearClass12) so the call to
CheckStrengthTorsionShearClass12(heb_300_s355, mx, v=v, axis=axis, gamma_m0=1.0)
becomes consistent with the earlier m_x declaration and avoids the NameError.
| @@ -0,0 +1,184 @@ | |||
| """Module for checking torsional shear stress resistance (Eurocode 2, formula 6.23).""" | |||
There was a problem hiding this comment.
Module docstring references "Eurocode 2" instead of "Eurocode 3".
Same issue as in strength_torsion_shear.py. EN 1993-1-1 is Eurocode 3.
📝 Proposed fix
-"""Module for checking torsional shear stress resistance (Eurocode 2, formula 6.23)."""
+"""Module for checking torsional shear stress resistance (Eurocode 3, EN 1993-1-1:2005, formula 6.23)."""📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| """Module for checking torsional shear stress resistance (Eurocode 2, formula 6.23).""" | |
| """Module for checking torsional shear stress resistance (Eurocode 3, EN 1993-1-1:2005, formula 6.23).""" |
🤖 Prompt for AI Agents
In `@blueprints/checks/eurocode/steel/strength_torsion.py` at line 1, The module
docstring in blueprints/checks/eurocode/steel/strength_torsion.py incorrectly
says "Eurocode 2"; update the top-level docstring to reference "Eurocode 3" (EN
1993-1-1) and adjust the descriptive text accordingly so the module correctly
states it implements torsional shear stress resistance per Eurocode 3 (EN
1993-1-1).
| Example | ||
| ------- | ||
| from blueprints.checks.eurocode.steel.torsion_strength import TorsionStrengthCheck | ||
| from blueprints.materials.steel import SteelMaterial, SteelStrengthClass | ||
| from blueprints.structural_sections.steel.standard_profiles.heb import HEB | ||
|
|
||
| steel_material = SteelMaterial(steel_class=SteelStrengthClass.S355) | ||
| heb_300_profile = HEB.HEB300.with_corrosion(1.5) | ||
| m_x = 10 # Applied torsional moment in kNm | ||
|
|
||
| heb_300_s355 = SteelCrossSection(profile=heb_300_profile, material=steel_material) | ||
| calc = TorsionStrengthCheck(heb_300_s355, m_x, gamma_m0=1.0) | ||
| calc.report().to_word("torsion_strength.docx", language="nl") | ||
|
|
There was a problem hiding this comment.
Example code references old class name and import path.
The example imports TorsionStrengthCheck from blueprints.checks.eurocode.steel.torsion_strength, but the actual class is CheckStrengthStVenantTorsionClass1234 in blueprints.checks.eurocode.steel.strength_torsion.
📝 Proposed fix
- from blueprints.checks.eurocode.steel.torsion_strength import TorsionStrengthCheck
+ from blueprints.checks.eurocode.steel.strength_torsion import CheckStrengthStVenantTorsionClass1234
from blueprints.materials.steel import SteelMaterial, SteelStrengthClass
from blueprints.structural_sections.steel.standard_profiles.heb import HEB
steel_material = SteelMaterial(steel_class=SteelStrengthClass.S355)
heb_300_profile = HEB.HEB300.with_corrosion(1.5)
m_x = 10 # Applied torsional moment in kNm
heb_300_s355 = SteelCrossSection(profile=heb_300_profile, material=steel_material)
- calc = TorsionStrengthCheck(heb_300_s355, m_x, gamma_m0=1.0)
- calc.report().to_word("torsion_strength.docx", language="nl")
+ calc = CheckStrengthStVenantTorsionClass1234(heb_300_s355, m_x=m_x, gamma_m0=1.0)
+ calc.report().to_word("torsion_strength.docx", language="nl")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Example | |
| ------- | |
| from blueprints.checks.eurocode.steel.torsion_strength import TorsionStrengthCheck | |
| from blueprints.materials.steel import SteelMaterial, SteelStrengthClass | |
| from blueprints.structural_sections.steel.standard_profiles.heb import HEB | |
| steel_material = SteelMaterial(steel_class=SteelStrengthClass.S355) | |
| heb_300_profile = HEB.HEB300.with_corrosion(1.5) | |
| m_x = 10 # Applied torsional moment in kNm | |
| heb_300_s355 = SteelCrossSection(profile=heb_300_profile, material=steel_material) | |
| calc = TorsionStrengthCheck(heb_300_s355, m_x, gamma_m0=1.0) | |
| calc.report().to_word("torsion_strength.docx", language="nl") | |
| Example | |
| ------- | |
| from blueprints.checks.eurocode.steel.strength_torsion import CheckStrengthStVenantTorsionClass1234 | |
| from blueprints.materials.steel import SteelMaterial, SteelStrengthClass | |
| from blueprints.structural_sections.steel.standard_profiles.heb import HEB | |
| steel_material = SteelMaterial(steel_class=SteelStrengthClass.S355) | |
| heb_300_profile = HEB.HEB300.with_corrosion(1.5) | |
| m_x = 10 # Applied torsional moment in kNm | |
| heb_300_s355 = SteelCrossSection(profile=heb_300_profile, material=steel_material) | |
| calc = CheckStrengthStVenantTorsionClass1234(heb_300_s355, m_x=m_x, gamma_m0=1.0) | |
| calc.report().to_word("torsion_strength.docx", language="nl") |
🤖 Prompt for AI Agents
In `@blueprints/checks/eurocode/steel/strength_torsion.py` around lines 45 - 58,
Update the example to use the actual class name and import path: replace the
import of TorsionStrengthCheck from
blueprints.checks.eurocode.steel.torsion_strength with the correct import of
CheckStrengthStVenantTorsionClass1234 from
blueprints.checks.eurocode.steel.strength_torsion, and instantiate that class
(replace TorsionStrengthCheck(...) with
CheckStrengthStVenantTorsionClass1234(...)) so the example matches the real
symbol names.
| Returns | ||
| ------- | ||
| Callable[..., StressPost] | ||
| A function that calculates the stress distribution when called. |
There was a problem hiding this comment.
Docstring return type is incorrect.
The Returns section says Callable[..., StressPost] with description "A function that calculates the stress distribution when called." However, the method signature returns StressPost directly, and the implementation indeed returns the result of section.calculate_stress(...) which is a StressPost. The docstring appears to be a leftover from a different design.
📝 Proposed fix
Returns
-------
- Callable[..., StressPost]
- A function that calculates the stress distribution when called.
+ StressPost
+ The stress distribution for the given internal forces.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Returns | |
| ------- | |
| Callable[..., StressPost] | |
| A function that calculates the stress distribution when called. | |
| Returns | |
| ------- | |
| StressPost | |
| The stress distribution for the given internal forces. |
🤖 Prompt for AI Agents
In `@blueprints/structural_sections/_profile.py` around lines 236 - 239, The
Returns docstring incorrectly states "Callable[..., StressPost]" but the method
returns a StressPost directly (it calls section.calculate_stress(...)); update
the Returns section to "StressPost" and change the description to reflect that
the function returns a StressPost instance (e.g., "StressPost — stress
distribution result from section.calculate_stress") so the docstring matches the
actual return value.
| def unit_stress(self) -> dict[str, Any]: | ||
| """Calculate the unit stress distribution for the profile. | ||
|
|
||
| This property is cached, so the calculation is performed only once per instance. | ||
|
|
||
| Returns | ||
| ------- | ||
| StressPost | ||
| The unit stress distribution for the profile. | ||
| """ | ||
| # Check if we already have cached unit stress | ||
| if self._unit_stress_cache is not None: | ||
| return self._unit_stress_cache | ||
|
|
||
| # Calculate unit stress | ||
| result = self.calculate_stress(1, 1, 1, 1, 1, 1).get_stress()[0] | ||
|
|
||
| # Cache the result | ||
| object.__setattr__(self, "_unit_stress_cache", result) | ||
|
|
||
| return result |
There was a problem hiding this comment.
Docstring return type says StressPost but the method returns dict[str, Any].
The type hint on line 269 correctly says -> dict[str, Any], and the implementation returns self.calculate_stress(...).get_stress()[0] which is a dict. The docstring on lines 276-277 should match.
📝 Proposed fix
Returns
-------
- StressPost
- The unit stress distribution for the profile.
+ dict[str, Any]
+ The unit stress distribution dictionary for the profile (first element from get_stress()).🤖 Prompt for AI Agents
In `@blueprints/structural_sections/_profile.py` around lines 269 - 289, The
docstring for the unit_stress method incorrectly declares the return type as
StressPost; update the docstring to match the actual return type (dict[str,
Any]) or otherwise describe that it returns a dictionary representing the unit
stress distribution. Locate the unit_stress method and change the "Returns"
section (and the type on the first line of the docstring, if present) so it
accurately states dict[str, Any] and describes the returned dict from
calculate_stress(...).get_stress()[0]; leave the implementation and the
_unit_stress_cache handling unchanged.
| def test_result_tension_ok(self, unp_steel_cross_section: SteelCrossSection) -> None: | ||
| """Test result() for ok tension load.""" | ||
| m_x = -0.3896 * 0.99 | ||
| calc = CheckStrengthStVenantTorsionClass1234(unp_steel_cross_section, m_x, gamma_m0=1.0) | ||
| result = calc.result() | ||
| assert result.is_ok is True | ||
| assert pytest.approx(result.unity_check, 0.005) == 0.99 | ||
| assert pytest.approx(result.factor_of_safety, 0.005) == 1 / 0.99 | ||
| assert calc.report() | ||
|
|
||
| def test_result_tension_not_ok(self, unp_steel_cross_section: SteelCrossSection) -> None: | ||
| """Test result() for not ok tension load.""" | ||
| m_x = 0.3896 * 1.01 | ||
| calc = CheckStrengthStVenantTorsionClass1234(unp_steel_cross_section, m_x, gamma_m0=1.0) | ||
| result = calc.result() | ||
| assert result.is_ok is False | ||
| assert pytest.approx(result.unity_check, 0.005) == 1.01 | ||
| assert pytest.approx(result.factor_of_safety, 0.005) == 1 / 1.01 | ||
| assert calc.report() |
There was a problem hiding this comment.
Test method names say "tension" but they test torsion.
test_result_tension_ok and test_result_tension_not_ok test torsional moment (m_x) scenarios, not tension. This appears to be a naming oversight from copy-paste. Consider renaming for clarity.
📝 Proposed fix
- def test_result_tension_ok(self, unp_steel_cross_section: SteelCrossSection) -> None:
- """Test result() for ok tension load."""
+ def test_result_torsion_ok(self, unp_steel_cross_section: SteelCrossSection) -> None:
+ """Test result() for ok torsion load."""
m_x = -0.3896 * 0.99
...
- def test_result_tension_not_ok(self, unp_steel_cross_section: SteelCrossSection) -> None:
- """Test result() for not ok tension load."""
+ def test_result_torsion_not_ok(self, unp_steel_cross_section: SteelCrossSection) -> None:
+ """Test result() for not ok torsion load."""
m_x = 0.3896 * 1.01
...🤖 Prompt for AI Agents
In `@tests/checks/eurocode/steel/test_strength_torsion.py` around lines 26 - 44,
Rename the two misnamed test functions to reflect they test torsion: change
test_result_tension_ok to test_result_torsion_ok and test_result_tension_not_ok
to test_result_torsion_not_ok; update any references/usages (e.g., in test
discovery or fixtures) and keep the body unchanged — these tests instantiate
CheckStrengthStVenantTorsionClass1234 with m_x and assert torsional
unity_check/factor_of_safety, so only the function names need renaming for
clarity.
Description
must be checked after PART 3 has been checked
feature request add torsion steel check. must be checked after Shear has been added as i use features introduced there.
Please note: only features St. Venant torsion. Warping torsion is horrible and needs 3d FEM.
As Blueprints uses different coordinates than sectionproperties. see for converstion above.
Fixes #966
Type of change
Please delete options that are not relevant.
Checklist:
Summary by CodeRabbit
Release Notes
New Features
Improvements