diff --git a/structuralcodes/__init__.py b/structuralcodes/__init__.py index 2e12a34a..08101845 100644 --- a/structuralcodes/__init__.py +++ b/structuralcodes/__init__.py @@ -4,7 +4,7 @@ from . import codes, core, geometry, materials, sections from .codes import get_design_codes, set_design_code, set_national_annex -from .core.errors import StructuralCodesWarning +from .core.errors import InformationWarning, StructuralCodesWarning __version__ = '0.6.4' @@ -20,3 +20,4 @@ ] warnings.filterwarnings(action='error', category=StructuralCodesWarning) +warnings.filterwarnings(action='always', category=InformationWarning) diff --git a/structuralcodes/core/errors.py b/structuralcodes/core/errors.py index 059dd6af..ba985dc8 100644 --- a/structuralcodes/core/errors.py +++ b/structuralcodes/core/errors.py @@ -6,6 +6,16 @@ class StructuralCodesWarning(Warning): class NoConvergenceWarning(StructuralCodesWarning): - """A warning that indicates that no convergence was reached for an - iterative solver. + """Warning for lack of convergence. + + A warning that indicates that no convergence was reached for an + iterative solver. The solution should be inspected with care. + """ + + +class InformationWarning(StructuralCodesWarning): + """Warning for simple information. + + A warning that indicates that some information that should be taken care + by user, but the calculation is not invalid. """ diff --git a/structuralcodes/sections/_generic.py b/structuralcodes/sections/_generic.py index cfb89002..098c16ce 100644 --- a/structuralcodes/sections/_generic.py +++ b/structuralcodes/sections/_generic.py @@ -21,7 +21,7 @@ from structuralcodes.materials.basic import ElasticMaterial from ..core.base import Section, SectionCalculator -from ..core.errors import NoConvergenceWarning +from ..core.errors import InformationWarning, NoConvergenceWarning from .section_integrators import SectionIntegrator, integrator_factory @@ -149,10 +149,11 @@ def _calculate_gross_section_properties(self) -> s_res.SectionProperties: if isinstance(polygon, MultiPolygon): gp.perimeter = 0.0 warnings.warn( - 'Perimiter computation for a multi polygon is not defined.' + 'Perimiter computation for a multi polygon is not defined.', + category=InformationWarning, ) - - gp.perimeter = polygon.exterior.length + else: + gp.perimeter = polygon.exterior.length # Computation of area: this is taken directly from shapely gp.area = self.section.geometry.area diff --git a/tests/test_sections/test_generic_section.py b/tests/test_sections/test_generic_section.py index e862a08e..f24c8056 100644 --- a/tests/test_sections/test_generic_section.py +++ b/tests/test_sections/test_generic_section.py @@ -7,9 +7,13 @@ from shapely import Polygon from structuralcodes.codes.ec2_2004 import reinforcement_duct_props -from structuralcodes.core.errors import NoConvergenceWarning +from structuralcodes.core.errors import ( + InformationWarning, + NoConvergenceWarning, +) from structuralcodes.geometry import ( CircularGeometry, + CompoundGeometry, RectangularGeometry, SurfaceGeometry, add_reinforcement, @@ -1993,3 +1997,27 @@ def test_section_mm_domain_warning(b, h, n_bars, diameter, fck, fyk): # Check that the results arrays have the same size assert len(res.m_y) == len(res_good.m_y) + + +def test_perimeter_multipolygon(): + """Test calculating the perimeter of a multipolygon. + + This resoves issue #329. + """ + mat = ElasticMaterial(E=210000, density=7850) + rect1 = SurfaceGeometry( + poly=Polygon([(0, 0), (100, 0), (100, 10), (0, 10)]), + material=mat, + ) + rect2 = SurfaceGeometry( + poly=Polygon([(0, 200), (100, 200), (100, 210), (0, 210)]), + material=mat, + ) + + compound = CompoundGeometry([rect1, rect2]) + section = GenericSection(compound, integrator='marin') + + with pytest.warns(InformationWarning): + gp = section.gross_properties + + assert math.isclose(gp.perimeter, 0)