-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for ACI 318-19 #76
Comments
One thing to be aware of, the metric and imperial versions of ACI318 have slight differences in many of the formulas for the constants. They are not a direct conversion to many decimal places, and it will lead to small inconsistencies in the answers when compared against metric or imperial workings. So if implementing both most methods for returning factors would need both metric and imperial equations. Converting the end answer probably will be close but not comparable to other tools you might be checking against. When you first call the class you might need to have a variable that drives the metric or the imperial version of the code equations being utilised.
I'd say as a design code NZS3101 is much closer to ACI318 than AS3600, NZS3101 is based on ACI318 after all, whereas AS3600 kind of does its own thing in many areas. So I'd expect many of the functions you could simply copy across from the One thing I would say about the AS300 class is a lot of the calculations are all under one method for alpha/gamma factors and so forth, and are not refactored out into separate methods like the Anyway, let me know if there are any specific questions you have on the |
Hi @Lomarandil great to hear, looking forward to seeing the progress! Agree that it's probably easiest to build on NZS & AS design codes, happy to answer any questions you have here on in a discussion post. There are also some basic guidelines here. |
Fair point. It's not the kind of precision that bothers me as a practitioner, but I can see the value in getting it spot-on for validation purposes. With that in mind, would we rather have the imperial/metric variable? Or just have two design codes, ACI 318 and 318M?
You know, I'll have to check. My experience has always been in low seismic design category applications, so I'm not very familiar with the requirements for SDC C/D/E structures.
Yes, I can definitely implement this in the ACI class. |
@Lomarandil, a few thoughts/brain dump below:- I'd imagine one class with both equations if they differ slightly would probably be the most logical approach, this would prevent repeating larger amounts of identical code and make it easier to maintain if there are future revisions to the equations. Though could have one parent class with the other over-riding any methods with different constants in equations where appropriate. i.e. From my perspective, I think the best way to do it might be to firstly consider listing out where the differences in equations and constants in equations might lay between imperial and metric versions and simply have a single method that sets these constants when the If you do this you could still have a Apart from having to consider the output units potentially differently for metric and imperial, that way you're going to have the same code and no need to double up in each method with a metric and an imperial version of the same equation. Though defining the constants at the beginning of an individual method is fine and means all the values that might change in the future are grouped together. Sometimes having something more readily read/understood is better than writing really efficient/streamlined code with lots of inheritance that is hard to interpret. Until you know how much difference might exist between equations and how many methods might need alternative metric/imperial versions I guess it is hard to say. I suspect you'll be getting either imperial or metric up and running and then looking at the best way to implement the other one once you have it up and working. |
class ACI318:
def __init__(self, metric: bool = False):
self.metric = metric
self.metric_test()
def metric_test(self):
if self.metric:
print(f"I'm inside ACI318 and metric = {self.metric}")
else:
print(f"I'm inside ACI318 and metric = {self.metric}")
class ACI318M(ACI318):
def __init__(self):
super().__init__(metric=True)
design_code = ACI318()
design_code_metric = ACI318M() returns:-
This is what I meant, only thing you need in |
To save you a little bit of time I have this class with imperial and metric ACI 318-19 formulas started for the purpose of column design: class ACIConcrete:
def __init__(self, fc=4000, density=145, lightweight=False, Ec_method="Density", units="Imperial"):
self.fc = fc
self.density = density
self.ec_method = Ec_method
self.lightweight = lightweight
self.eu = 0.003
self.units = units
def elastic_modulus(self):
# ACI 318-19 - Section 19.2.2
if self.ec_method == "Density":
if self.units == "Imperial":
# ACI 318-19 - Eq. 19.2.2.1.a
Ec = math.pow(self.density, 1.5)*33*math.sqrt(self.fc)
else:
# ACI 318-19 - App. C SI-Metric Equiv. for Eq. 19.2.2.1.a
Ec = math.pow(self.density, 1.5)*0.043*math.sqrt(self.fc)
else:
if self.units == "Imperial":
# ACI 318-19 - Eq. 19.2.2.1.b
Ec = 57000*math.sqrt(self.fc)
else:
# ACI 318-19 - App. C SI-Metric Equiv. for Eq. 19.2.2.1.b
Ec = 4700*math.sqrt(self.fc)
self.Ec = Ec
return Ec
def lambdac(self):
# ACI 318-19 - Section 19.2.4
if self.lightweight:
# ACI 318-19 - 19.2.4.2
lam = 0.75
else:
# ACI 318-19 - 19.2.4.3
lam = 1.0
self.lam = lam
return lam
def modulus_of_rupture(self):
# ACI 318-19 - Section 19.2.3
lam = self.lambdac()
if self.units == "Imperial":
# ACI 318-19 eq. 19.2.3.1
fr = lam*7.5*math.sqrt(self.fc)
else:
# ACI 318-19 - App. C SI-Metric Equiv. for Eq. 19.2.3.1
fr = lam*0.62*math.sqrt(self.fc)
self.fr = fr
return fr
def beta1(self):
# ACI 318-19 - Table 22.2.2.4.3
if self.units == "Imperial":
if self.fc <= 2500:
beta1 = 0
elif self.fc >= 8000:
beta1 = 0.65
elif 2500 <= self.fc and self.fc <= 4000:
beta1 = 0.85
else:
beta1 = 0.85 - ((0.05*(self.fc-4000))/1000)
else:
# ACI 318-19 - App. C SI-Metric Equiv. for 22.2.2.4.3(b)
# 1000 psi = 7 Mpa as defined by ACI, correct this for actual
# unit conversion
if self.fc <= 17.5:
beta1 = 0
elif self.fc >= 56:
beta1 = 0.65
elif 17.5 <= self.fc and self.fc <= 28:
beta1 = 0.85
else:
beta1 = 0.85 - ((0.05*(self.fc-28))/7)
self.beta1 = beta1
return beta1
def phi_nm(self, et, ety, ties="Other"):
eu = self.eu
if ties == "Spiral":
if et > ety:
phi = 0.75
classification = "Compression-controlled"
elif et < (ety-eu):
phi = 0.9
classification = "Tension-controlled"
else:
phi = 0.75 + ((0.15*(et-ety))/(-1*eu))
classification = "Transition"
else:
if et > ety:
phi = 0.65
classification = "Compression-controlled"
elif et < (ety-eu):
phi = 0.9
classification = "Tension-controlled"
else:
phi = 0.65 + ((0.25*(et-ety))/(-1*eu))
classification = "Transition"
return {"Phi": phi,"Classification":classification}
def pn_max(self, Ag, Ast, fy, ties="Other"):
#ACI 318-19 - 22.4.2.1
if fy > 80000:
fy = 80000
Po = (0.85*self.fc*(Ag-Ast))+(Ast*fy)
if ties == "Spiral":
pn_max = 0.85*Po
phi = 0.75
else:
pn_max = 0.80*Po
phi = 0.65
pu_max = phi*pn_max
return {"Pn_max":pn_max,"Phi":phi,"Pu_max":pu_max}
def pnt_max(self, Ast, fy):
#ACI 318-19 - 22.4.3
pnt_max = Ast*fy
phi = 0.9
put_max = phi*pnt_max
return {"Pnt_max":pnt_max,"Phi":phi,"Put_max":put_max} |
Hi @Lomarandil @robbievanleeuwen, I see that this has somewhat stalled, but I am willing to help get this going. Would be happy to contribute this along with other implementations. Where should I start? Thanks! |
Thanks Dan -- I stalled out quickly with my rudimentary programming
knowledge -- couldn't sort out how to pull strain values at the time.
Supportive of this being picked up again!
…On Wed, Aug 28, 2024 at 9:32 AM Dank ***@***.***> wrote:
Hi @Lomarandil <https://github.com/Lomarandil> @robbievanleeuwen
<https://github.com/robbievanleeuwen>,
I see that this has somewhat stalled, but I am willing to help get this
going.
I've written something already to modify the axial-moment interaction
diagrams according to the ductility requirements in ACI318.
Would be happy to contribute this along with other implementations.
Where should I start?
Thanks!
Dan
—
Reply to this email directly, view it on GitHub
<#76 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AK2P4M37YTMM4G652NSHDQTZTXUPJAVCNFSM6AAAAABNIRV3J6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGMJVGY4DGMBXGQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Sounds good. I'll fork the main repo and get started. @robbievanleeuwen feel free to assign this to me! |
Ah - I am having issues with the install. |
Alright, now that you guys have made all these refinements and process improvements, I'm ready to stand on those shoulders to implement ACI 318-19.
Perhaps more accurately, I've started work on a fork implementing ACI 318-19M. I figure that if we get the bones figured out first, skinning it in imperial units (per issue #48) can be a separate undertaking. After a false start adapting Agents NZS code, I've decided to first start by adapting the AS module (easier to wrap my head around for now).
Current work is in the ACI2 branch here: https://github.com/Lomarandil/concrete-properties-ACI/tree/Lomarandil-ACI2
My apologies, I'm still a programming and Github noob, just learning by doing. Please feel free to suggest corrections or style improvements.
The text was updated successfully, but these errors were encountered: