Skip to content

Commit 3cfe332

Browse files
Merge pull request #28 from robbievanleeuwen/new_material_module
New material module
2 parents 0c2cbd0 + 41f5936 commit 3cfe332

28 files changed

+2147
-742
lines changed

concreteproperties/analysis_section.py

+93-85
Large diffs are not rendered by default.

concreteproperties/concrete_section.py

+437-361
Large diffs are not rendered by default.

concreteproperties/design_codes.py

+36-16
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
from copy import deepcopy
44
from math import inf
5-
from typing import TYPE_CHECKING, List, Optional, Tuple
5+
from multiprocessing.sharedctypes import Value
6+
from typing import TYPE_CHECKING, List, Tuple
67

78
import numpy as np
89
from rich.live import Live
@@ -12,7 +13,7 @@
1213
import concreteproperties.results as res
1314
import concreteproperties.stress_strain_profile as ssp
1415
import concreteproperties.utils as utils
15-
from concreteproperties.material import Concrete, Steel
16+
from concreteproperties.material import Concrete, SteelBar
1617

1718
if TYPE_CHECKING:
1819
from concreteproperties.concrete_section import ConcreteSection
@@ -60,8 +61,8 @@ def create_steel_material(
6061
self,
6162
yield_strength: float,
6263
colour: str = "grey",
63-
) -> Steel:
64-
"""Returns a steel material object.
64+
) -> SteelBar:
65+
"""Returns a steel bar material object.
6566
6667
List assumptions of material properties here...
6768
@@ -76,7 +77,7 @@ def create_steel_material(
7677
def get_gross_properties(
7778
self,
7879
**kwargs,
79-
) -> res.ConcreteProperties:
80+
) -> res.GrossProperties:
8081
"""Returns the gross section properties of the reinforced concrete section.
8182
8283
:param kwargs: Keyword arguments passed to
@@ -90,7 +91,7 @@ def get_gross_properties(
9091
def get_transformed_gross_properties(
9192
self,
9293
**kwargs,
93-
) -> res.TransformedConcreteProperties:
94+
) -> res.TransformedGrossProperties:
9495
"""Transforms gross section properties.
9596
9697
:param kwargs: Keyword arguments passed to
@@ -232,7 +233,13 @@ def calculate_ultimate_stress(
232233

233234

234235
class AS3600(DesignCode):
235-
"""Design code class for Australian standard AS 3600:2018."""
236+
"""Design code class for Australian standard AS 3600:2018.
237+
238+
Note that this design code only supports :class:`~concreteproperties.pre.Concrete`
239+
and :class:`~concreteproperties.pre.SteelBar` material objects. Meshed
240+
:class:`~concreteproperties.pre.Steel` material objects are **not** supported
241+
as this falls under the composite structures design code.
242+
"""
236243

237244
def __init__(
238245
self,
@@ -252,11 +259,22 @@ def assign_concrete_section(
252259

253260
self.concrete_section = concrete_section
254261

262+
# check to make sure there are no meshed reinforcement regions
263+
if self.concrete_section.reinf_geometries_meshed:
264+
raise ValueError(
265+
"Meshed reinforcement is not supported in this design code."
266+
)
267+
255268
# determine reinforcement class
256269
self.reinforcement_class = "N"
257270

258-
for steel_geom in self.concrete_section.steel_geometries:
259-
if steel_geom.material.stress_strain_profile.fracture_strain < 0.05:
271+
for steel_geom in self.concrete_section.reinf_geometries_lumped:
272+
if (
273+
abs(
274+
steel_geom.material.stress_strain_profile.get_ultimate_tensile_strain()
275+
)
276+
< 0.05
277+
):
260278
self.reinforcement_class = "L"
261279

262280
# calculate squash and tensile load
@@ -343,8 +361,8 @@ def create_steel_material(
343361
yield_strength: float = 500,
344362
ductility_class: str = "N",
345363
colour: str = "grey",
346-
) -> Steel:
347-
r"""Returns a steel material object.
364+
) -> SteelBar:
365+
r"""Returns a steel bar material object.
348366
349367
| **Material assumptions:**
350368
| - *Density*: 7850 kg/m\ :sup:`3`
@@ -367,7 +385,7 @@ def create_steel_material(
367385
else:
368386
raise ValueError("ductility_class must be N or L.")
369387

370-
return Steel(
388+
return SteelBar(
371389
name=f"{yield_strength:.0f} MPa Steel (AS 3600:2018)",
372390
density=7.85e-6,
373391
stress_strain_profile=ssp.SteelElasticPlastic(
@@ -406,7 +424,7 @@ def squash_tensile_load(
406424
squash_load += force_c
407425

408426
# loop through all steel geometries
409-
for steel_geom in self.concrete_section.steel_geometries:
427+
for steel_geom in self.concrete_section.reinf_geometries_lumped:
410428
# calculate area and centroid
411429
area = steel_geom.calculate_area()
412430

@@ -415,7 +433,9 @@ def squash_tensile_load(
415433
strain=0.025
416434
)
417435

418-
force_t = -area * steel_geom.material.stress_strain_profile.yield_strength
436+
force_t = (
437+
-area * steel_geom.material.stress_strain_profile.get_yield_strength()
438+
)
419439

420440
# add to totals
421441
squash_load += force_c
@@ -500,10 +520,10 @@ def get_n_ub(
500520
# get compressive strain at extreme fibre
501521
eps_cu = self.concrete_section.gross_properties.conc_ultimate_strain
502522

503-
# 4) calculate d_n at balanced load
523+
# calculate d_n at balanced load
504524
d_nb = d_0 * (eps_cu) / (eps_sy + eps_cu)
505525

506-
# 5) calculate axial force at balanced load
526+
# calculate axial force at balanced load
507527
balanced_res = self.concrete_section.calculate_ultimate_section_actions(
508528
d_n=d_nb, ultimate_results=res.UltimateBendingResults(theta=theta)
509529
)

concreteproperties/material.py

+69-30
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,35 @@
11
from __future__ import annotations
22

33
from dataclasses import dataclass, field
4-
from typing import TYPE_CHECKING
54

6-
from concreteproperties.stress_strain_profile import (
7-
ConcreteServiceProfile,
8-
ConcreteUltimateProfile,
9-
SteelProfile,
10-
)
5+
import concreteproperties.stress_strain_profile as ssp
116

127

13-
@dataclass(eq=True)
14-
class Concrete:
8+
@dataclass
9+
class Material:
10+
"""Generic class for a *concreteproperties* material.
11+
12+
:param name: Material name
13+
:param density: Material density (mass per unit volume)
14+
:param stress_strain_profile: Material stress-strain profile
15+
:param colour: Colour of the material for rendering
16+
:param meshed: If set to True, the entire material region is meshed; if set to
17+
False, the material region is treated as a lumped circular mass at its centroid
18+
"""
19+
20+
name: str
21+
density: float
22+
stress_strain_profile: ssp.StressStrainProfile
23+
colour: str
24+
meshed: bool
25+
26+
def __post_init__(self):
27+
# set elastic modulus
28+
self.elastic_modulus = self.stress_strain_profile.get_elastic_modulus()
29+
30+
31+
@dataclass
32+
class Concrete(Material):
1533
"""Class for a concrete material.
1634
1735
:param name: Concrete material name
@@ -27,45 +45,66 @@ class Concrete:
2745

2846
name: str
2947
density: float
30-
stress_strain_profile: ConcreteServiceProfile
31-
ultimate_stress_strain_profile: ConcreteUltimateProfile
48+
stress_strain_profile: ssp.ConcreteServiceProfile
49+
ultimate_stress_strain_profile: ssp.ConcreteUltimateProfile
3250
alpha_squash: float
3351
flexural_tensile_strength: float
3452
colour: str
53+
meshed: bool = field(default=True, init=False)
3554

3655
def __post_init__(self):
37-
self.elastic_modulus = self.stress_strain_profile.get_elastic_modulus()
56+
super().__post_init__()
3857

39-
if not isinstance(self.stress_strain_profile, ConcreteServiceProfile):
40-
raise ValueError(
41-
"Concrete stress_strain_profile must be a ConcreteServiceProfile object"
42-
)
58+
if not isinstance(self.stress_strain_profile, ssp.ConcreteServiceProfile):
59+
msg = "Concrete stress_strain_profile must be a "
60+
msg += "ConcreteServiceProfile object."
61+
raise ValueError(msg)
4362

44-
if not isinstance(self.ultimate_stress_strain_profile, ConcreteUltimateProfile):
45-
raise ValueError(
46-
"Concrete ultimate_stress_strain_profile must be a ConcreteUltimateProfile object"
47-
)
63+
if not isinstance(
64+
self.ultimate_stress_strain_profile, ssp.ConcreteUltimateProfile
65+
):
66+
msg = "Concrete ultimate_stress_strain_profile must be a "
67+
msg += "ConcreteUltimateProfile object."
68+
raise ValueError(msg)
4869

4970

50-
@dataclass(eq=True)
51-
class Steel:
52-
"""Class for a steel material.
71+
@dataclass
72+
class Steel(Material):
73+
"""Class for a steel material with the entire region meshed to allow for strain
74+
variation across the section, e.g. structural steel profiles.
5375
5476
:param name: Steel material name
5577
:param density: Steel density (mass per unit volume)
56-
:param stress_strain_profile: Ultimate steel stress-strain profile
78+
:param stress_strain_profile: Steel stress-strain profile
5779
:param colour: Colour of the material for rendering
5880
"""
5981

6082
name: str
6183
density: float
62-
stress_strain_profile: SteelProfile
84+
stress_strain_profile: ssp.StressStrainProfile
6385
colour: str
86+
meshed: bool = field(default=True, init=False)
87+
88+
89+
@dataclass
90+
class SteelBar(Steel):
91+
"""Class for a steel bar material, treated as a lumped circular mass with a constant
92+
strain.
93+
94+
:param name: Steel bar material name
95+
:param density: Steel bar density (mass per unit volume)
96+
:param stress_strain_profile: Steel bar stress-strain profile
97+
:param colour: Colour of the material for rendering
98+
"""
99+
100+
name: str
101+
density: float
102+
stress_strain_profile: ssp.StressStrainProfile
103+
colour: str
104+
meshed: bool = field(default=False, init=False)
64105

65-
def __post_init__(self):
66-
self.elastic_modulus = self.stress_strain_profile.get_elastic_modulus()
67106

68-
if not isinstance(self.stress_strain_profile, SteelProfile):
69-
raise ValueError(
70-
"Steel stress_strain_profile must be a SteelProfile object"
71-
)
107+
# @dataclass
108+
# class SteelStrand(Steel):
109+
# # placeholder
110+
# pass

concreteproperties/post.py

-4
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,10 @@
44
from typing import TYPE_CHECKING, Optional, Tuple, Union
55

66
import matplotlib.pyplot as plt
7-
import numpy as np
87

98
if TYPE_CHECKING:
109
import matplotlib
1110

12-
from concreteproperties.analysis_section import AnalysisSection
13-
from concreteproperties.concrete_section import ConcreteSection
14-
1511

1612
@contextlib.contextmanager
1713
def plotting_context(

0 commit comments

Comments
 (0)