feat: add ACI 318-19 concrete and reinforcement material properties#343
feat: add ACI 318-19 concrete and reinforcement material properties#343gabe-kafka wants to merge 2 commits into
Conversation
f4d0636 to
a9987bf
Compare
| import typing as t | ||
|
|
||
| from . import ec2_2004, ec2_2023, mc2010, mc2020 | ||
| from . import aci318, ec2_2004, ec2_2023, mc2010, mc2020 |
There was a problem hiding this comment.
Minor comment about the naming.
For Eurocode 2 we decided to implement different generations in different modules, e.g. ec2_2004 for the first generation that was released in 2004, and ec2_2023 for the second generation that was released in 2023. The second generation is expected to become accepted as national governing design code around Europe some time in the period 2027-2028.
Please correct me if I am wrong here, but my impression is that the 19 in ACI318-19 indicates that it was released in 2019. Similarly, a slightly newer version was released in 2025 and named ACI318-25. If this is right, please consider indicating this in the name of the module, e.g. aci318_19 instead of just aci318.
There was a problem hiding this comment.
Morten, I agree with your comment. We need to keep different versions separate. When there is no change we can use the method of the previous version, but we may need to update the references and son on. So, yes it should be aci318-19
There was a problem hiding this comment.
this convention makes sense and you are right about the -19 -25 signaling release year. I will focus on ACI318-19 for now.
| from ._concrete import Concrete | ||
|
|
||
|
|
||
| class ConcreteACI318(Concrete): # noqa: N801 |
There was a problem hiding this comment.
Same minor comment as above, please consider renaming the class to ConcreteACI318_19.
| from ._reinforcement import Reinforcement | ||
|
|
||
|
|
||
| class ReinforcementACI318(Reinforcement): # noqa: N801 |
There was a problem hiding this comment.
Same minor comment as above, please consider renaming the class to ReinforcementACI318_19.
| self._fct = abs(fct) if fct is not None else None | ||
| self._wc = wc | ||
| self._lambda_s = lambda_s | ||
|
|
There was a problem hiding this comment.
In the other concrete classes we have implemented a .__post_init__ method which is responsible for validating the parameters that are set. See for example here. Please consider implementing a similar method here.
| """ | ||
| return { | ||
| 'fc': self.fcd(), | ||
| 'eps_0': 0.002, |
There was a problem hiding this comment.
Is there a clause in the code that sets the value eps_0 = 0.002? If it is, please consider implementing a function in the code module similar as for eps_cu. Furthermore, the value of eps_0 should preferably be taken from a property on this concrete class such that it is more transparent for the user what is routed to the constitutive laws. Please consider implementing this property, possibly calling the function for eps_0 in the code module.
| """ | ||
| return { | ||
| 'fc': self.fcd(), | ||
| 'eps_c': 0.002, |
There was a problem hiding this comment.
Same as for the comment related to eps_0 above.
| return fy / _Es | ||
|
|
||
|
|
||
| def reinforcement_grade_props( |
There was a problem hiding this comment.
Does ACI 318-19 also provide values for the strain at ultimate strength? If so, please consider including it in the return dictionary.
mortenengen
left a comment
There was a problem hiding this comment.
Thanks for this very nice contribution @gabe-kafka. I have left a couple of comments for you to consider while finalizing the PR. Please note that @talledodiego and @aperezcaldentey have also agreed to provide their reviews.
|
@gabe-kafka, in the above message you provided the following comment:
However, I have not experienced any pre-existing failues in the pipeline. Please elaborate so that we can triage this. |
|
|
||
| def fct(fc: float, lambda_s: float = 1.0) -> float: | ||
| """The approximate splitting tensile strength of concrete. | ||
|
|
There was a problem hiding this comment.
The formula used in this method does not correspond to ACI 318-19, Section 19.2.4.3, as stated. We should possibly delete this method as fct is not defined in ACI 318-19.
| @@ -0,0 +1,164 @@ | |||
| """Concrete material properties according to ACI 318-19.""" | |||
|
|
|||
There was a problem hiding this comment.
I suggest we order the methods as they appear in the code. Let's not jump from Chaper 19 to 22 and then back to 19.
| if fc >= 55: | ||
| return 0.65 | ||
| return 0.85 - 0.05 * (fc - 28) / 7 | ||
|
|
There was a problem hiding this comment.
Replace expression: 0.85 - 0.05 * (fc - 28) / 7 by 0.85-0.20/27*(fc-28) - why simplify and lose accuracy? I could drive some people crazy...
|
|
||
| Raises: | ||
| ValueError: If fc is not positive. | ||
| """ |
There was a problem hiding this comment.
According to Table 22.2.2.4.3. f'c must be greater that 17. We should set this as a lower limit. Not 0.
|
|
||
| def Ec(fc: float, wc: float = 2320.0) -> float: | ||
| """The modulus of elasticity of concrete. | ||
|
|
There was a problem hiding this comment.
Default value of concrete. The typical specific weight of concrete used in North American practice is 150 lbs/cf, which I roughly equivalent to a density of 150/(2.2*0.3048^3)≈2400 kg/m3. I understand this my have to do with going from specific weight to density using g=9.81 m/s2, but it is not clear for me how you derive it, as the units are not consistent. On the other hand, Eq. 19.2.2.1b provides a factor of 4700 which would lead to a value of w=2286 kg/m3.
| 'sand-lightweight': 0.85, | ||
| 'all-lightweight': 0.75, | ||
| } | ||
|
|
There was a problem hiding this comment.
The lambda factor in ACI-318-19 is a function of the weight and lies between 1.00 and 0.75. You provide 'sand-lightweight as an intermediate value. Consider programing the equation as a function of the weight (as done for the modulus of elasticity) or adding the values from Table 19.2.4.1 'lightweight, fine blend' and 'sand-lightweight, corase blend'
| alpha1, | ||
| beta1, | ||
| eps_cu, | ||
| fct, |
There was a problem hiding this comment.
fct not defined in ACI 318-19
| '80': {'fy': 550.0, 'fu': 690.0}, | ||
| '100': {'fy': 690.0, 'fu': 860.0}, | ||
| } | ||
|
|
There was a problem hiding this comment.
Values for Reinforcement grades based on table 20.2.1.3(a). Please add this reference to comments.
|
|
||
| def fy_design(fy: float, phi: float = 1.0) -> float: | ||
| """The design yield strength of reinforcement. | ||
|
|
There was a problem hiding this comment.
As you say, ACI does not consider a partial factor on steel. Why do we need to provide one? The user should not be able to introduce a value different that 1.00. If we need this method for compatibility reasons we shoudl delete phi as a KWARG.
| characteristic strength (fck). The parameter is named fck for | ||
| compatibility with the base class, but represents fc' in ACI | ||
| notation. An fc property is provided as an alias. | ||
|
|
There was a problem hiding this comment.
Note that fck is a 95% fractile, while f'c is a 90% fractile
| gamma_c defaults to 1.0 and should be left at 1.0 for | ||
| standard ACI 318 design. Reducing fc' via gamma_c is not | ||
| ACI 318 compliant. | ||
|
|
There was a problem hiding this comment.
I agree, so don't give the user the possibility of doing otherwise.
| (default: 2320). | ||
| gamma_c (float, optional): Partial factor for concrete. | ||
| Default is 1.0 (ACI does not use material partial | ||
| factors). |
There was a problem hiding this comment.
So we should not give the user this possibility. Delete parameter or do we need it for compatibility reasons? If so we should somehow force the user to input a value of 1.0.
| Ec (float, optional): The modulus of elasticity in MPa. | ||
| fr (float, optional): The modulus of rupture in MPa. | ||
| fct (float, optional): The splitting tensile strength | ||
| in MPa. |
There was a problem hiding this comment.
As commented above fct is not defined in ACI 318-19. We should not use it.
| fct (float, optional): The splitting tensile strength | ||
| in MPa. | ||
| wc (float): Unit weight of concrete in kg/m3 | ||
| (default: 2320). |
There was a problem hiding this comment.
Justify default value.
| Default is 1.0 for ACI 318 (no material partial | ||
| factor). | ||
| """ | ||
| return self._gamma_s or 1.0 |
There was a problem hiding this comment.
As commented on before for ACI we should set all material partial factors to 1.00 and not allow the user to change them. I don't think any good will come from this freedom.
Add the first American design code to the library. Implements material properties from ACI 318-19 Chapters 19, 20, and 22: Concrete (codes/aci318): - Ec: modulus of elasticity (Table 19.2.2.1) - fr: modulus of rupture (Eq. 19.2.3.1) - beta1: Whitney stress block depth factor (Table 22.2.2.4.3) - eps_cu: ultimate concrete strain (Section 22.2.2.1) - alpha1: stress block intensity (Section 22.2.2.4.1) - fct: splitting tensile strength (Section 19.2.4.3) - lambda_factor: lightweight modification factor (Table 19.2.4.2) Reinforcement (codes/aci318): - Es: modulus of elasticity (Section 20.2.2.2) - fy_design: design yield strength - epsyd: yield strain - reinforcement_grade_props: ASTM grade lookup (Table 20.2.2.4a) Material classes: - ConcreteACI318 with elastic, parabola-rectangle, and bilinear constitutive laws - ReinforcementACI318 with elastic and elastic-plastic laws ACI 318 uses LRFD (strength reduction factors on member capacity) rather than partial safety factors on material strength. Material classes default gamma_c=1.0 and gamma_s=1.0 accordingly. Ref: fib-international#187
a9987bf to
abb8aa5
Compare
|
Pushed a rebased update against current Summary of the changes:
Verification after rebasing:
For the EC2 2023 point: I should not have described this as a confirmed upstream/pipeline failure. It is reproducible locally in this workspace, while CI does not appear to show it. The exact local failure is |
Summary
Adds the first American design code to the library: ACI 318-19 material properties from Chapters 19, 20, and 22.
structuralcodes.codes.aci318_19, registered asaci318_19.Ec,fr,lambda_factor,eps_cu,eps_c0,alpha1, andbeta1as standalone functions following existing EC2/MC2010 patterns.fctis intentionally not included because ACI 318-19 does not define it.Es,fy_design,epsyd, andreinforcement_grade_propsfor the ACI 318-19 Table 20.2.1.3(a) grade lookup.ConcreteACI318_19andReinforcementACI318_19with constitutive law support (elastic, parabola-rectangle, and bilinear for concrete; elastic and elastic-plastic for steel).ConcreteACI318_19.from_psi(...),ReinforcementACI318_19.from_grade(...), andReinforcementACI318_19.from_ksi(...); values are converted at the API boundary and stored internally in SI units.All direct code/material APIs use SI internally (MPa, kg/m3).
ConcreteACI318_19accepts ACIfcdirectly;fckremains available only for compatibility with the shared concrete factory/base API.ACI vs Eurocode safety philosophy
ACI 318 uses LRFD. Strength reduction factors (
phi) are applied at member capacity level, not material level. The ACI material classes keepgamma_candgamma_sfor compatibility with the shared material APIs, but values other thanNoneor1.0now raiseValueError.Scope
Material properties only. No member design (shear, flexure, etc.) in this PR; that can follow once the architecture question in #187 is resolved.
Closes #187 (partially - first code added, more can follow).
Test plan
./venv/bin/python -m ruff check structuralcodes/codes/aci318_19 structuralcodes/materials/concrete/_concreteACI318_19.py structuralcodes/materials/reinforcement/_reinforcementACI318_19.py tests/test_aci318_19- passes./venv/bin/python -m ruff format --check structuralcodes/codes/aci318_19 structuralcodes/materials/concrete/_concreteACI318_19.py structuralcodes/materials/reinforcement/_reinforcementACI318_19.py tests/test_aci318_19- passes, 11 files already formatted./venv/bin/python -m pytest tests/test_aci318_19- 84 passed./venv/bin/python -m pytest- ran locally; 10,240 passed and 1 EC2 2023 expectation mismatch reproduced only in this workspace so far, not in CI:tests/test_ec2_2023/test_ec2_2023_section5_materials.py::test_eps_cs_50y[25-dry-800-CN-0.46333]returned0.45333333333333337vs expected0.46333set_design_code('aci318_19')->create_concrete(fck=28)->.Ecreturns the ACI normalweight value