robbievanleeuwen / concrete-properties Goto Github PK
View Code? Open in Web Editor NEWCalculate section properties for reinforced concrete sections.
Home Page: https://concrete-properties.rtfd.io
License: MIT License
Calculate section properties for reinforced concrete sections.
Home Page: https://concrete-properties.rtfd.io
License: MIT License
Is your feature request related to a problem? Please describe.
Biaxial bending diagrams and to a lesser extent, interaction diagrams, can take a long time to generate. Both of these features involve a number of independent calculations, currently implemented in a for loop.
Describe the solution you'd like
Using the python multiprocessing
module would allow these computations to be performed in parallel on multiple cores, vastly speeding up these analyses.
Hi @robbievanleeuwen,
Working through the example in the documentation (https://concrete-properties.readthedocs.io/en/stable/examples/as3600.html) in a JupyterNotebook, I noted that the parameter kuo for a beam in pure bending, is incorrectly exported as 0.0000 with d_n as infinite when calculating the ultimate bending capacity. This is reflected in both my JupyterNotebook and the online documentation.
f_ult_res, ult_res, phi = design_code.ultimate_bending_capacity()
ult_res.print_results()
print(f"kuo = {ult_res.k_u:.4f}")
The bending capacity 'Muo' and factored capacity 'phi.Muo' are still correct. If I set n_star to something small (0.0001), ku is comes out correctly at 0.0898.
Working through the code I believe the error may be in as3600.py line 431, where I suspect it should be "greater than or equal to".
# regular calculation
elif n_design > 0:
ult_res = self.concrete_section.ultimate_bending_capacity(theta=theta, n=n_design / phi)
Are you able to verify whether my understanding of what the code is doing here would still be valid with this change?
P.S. Note that kuo is correctly calculated using the more general (not code specific) module.
concreteproperties version: <0.6.1>
Python version: <3.10>
OS version and name: <Windows 11 Home 23H2>
I am on the latest
stable concreteproperties version, installed using a recommended method.
I have searched the issues
of this repo and believe that this is not a duplicate.
I have consulted the documentation
for any relevant information.
The error is deceptive and just appears as matplotlib errors:
<AxesSubplot:title={'center':'Pure Bending'}>Exception in Tkinter callback
Traceback (most recent call last):
File "/home/ccaprani/anaconda3/envs/secprop/lib/python3.9/tkinter/__init__.py", line 1892, in __call__
return self.func(*args)
File "/home/ccaprani/anaconda3/envs/secprop/lib/python3.9/tkinter/__init__.py", line 814, in callit
func(*args)
File "/home/ccaprani/anaconda3/envs/secprop/lib/python3.9/site-packages/matplotlib/backends/_backend_tk.py", line 240, in idle_draw
self.draw()
File "/home/ccaprani/anaconda3/envs/secprop/lib/python3.9/site-packages/matplotlib/backends/backend_tkagg.py", line 9, in draw
super().draw()
File "/home/ccaprani/anaconda3/envs/secprop/lib/python3.9/site-packages/matplotlib/backends/backend_agg.py", line 406, in draw
self.figure.draw(self.renderer)
File "/home/ccaprani/anaconda3/envs/secprop/lib/python3.9/site-packages/matplotlib/artist.py", line 74, in draw_wrapper
result = draw(artist, renderer, *args, **kwargs)
File "/home/ccaprani/anaconda3/envs/secprop/lib/python3.9/site-packages/matplotlib/artist.py", line 51, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "/home/ccaprani/anaconda3/envs/secprop/lib/python3.9/site-packages/matplotlib/figure.py", line 2790, in draw
mimage._draw_list_compositing_images(
File "/home/ccaprani/anaconda3/envs/secprop/lib/python3.9/site-packages/matplotlib/image.py", line 132, in _draw_list_compositing_images
a.draw(renderer)
File "/home/ccaprani/anaconda3/envs/secprop/lib/python3.9/site-packages/matplotlib/artist.py", line 51, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "/home/ccaprani/anaconda3/envs/secprop/lib/python3.9/site-packages/matplotlib/_api/deprecation.py", line 431, in wrapper
return func(*inner_args, **inner_kwargs)
File "/home/ccaprani/anaconda3/envs/secprop/lib/python3.9/site-packages/matplotlib/axes/_base.py", line 2921, in draw
mimage._draw_list_compositing_images(renderer, self, artists)
File "/home/ccaprani/anaconda3/envs/secprop/lib/python3.9/site-packages/matplotlib/image.py", line 132, in _draw_list_compositing_images
a.draw(renderer)
File "/home/ccaprani/anaconda3/envs/secprop/lib/python3.9/site-packages/matplotlib/artist.py", line 51, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "/home/ccaprani/anaconda3/envs/secprop/lib/python3.9/site-packages/matplotlib/collections.py", line 350, in draw
self.update_scalarmappable()
File "/home/ccaprani/anaconda3/envs/secprop/lib/python3.9/site-packages/matplotlib/collections.py", line 912, in update_scalarmappable
if self._A.ndim > 1 and not isinstance(self, QuadMesh):
AttributeError: 'list' object has no attribute 'ndim'
I've tracked it back to this line:
concrete-properties/concreteproperties/results.py
Line 1352 in bbdd6b1
Presumably there is something wrong in the way that the lumped reo patches are being created for my structure. Unfortunately I can't share the structure I'm working on, but I'm parking this low-effort issue notice here and will update if I find out more.
I've noticed as well that the way the moment curvature analysis adaptively scales the curvature step it almost always just keeps increasing the curvature in each step. so by the time you get closer to the failure point the answers get very widely spaced.
if moment_diff <= delta_m_min:
kappa_inc *= 2
elif moment_diff >= delta_m_max:
kappa_inc *= 0.5
To demonstrate, first image is replacing 2 with 1.01, and 0.5 with 0.99 to arbitrarily limit to a much smaller step. You can appreciate the differences in the results in the below images for the same section. So by default the answer gets cruder and crude as it proceeds and you start to miss the fundamental behaviour I think. Note the general shape and higher curvature achieved when the steps are smaller.
It feels like the final point should always be undertaken at the failure strain. At the moment the final analysis point returned is only the point evaluated before a moment step goes over the failure strain. Which with a cruder step could be quite a bit lower than the actual true failure strain.
Originally posted by @Agent6-6-6 in #44 (comment)
Not sure if you've come across this, or whether it is even within the control of concrete-properties. But when running a biaxial interaction analyses, you sometimes randomly get these errors note below. It randomly freezes for a while and then throws up these errors, but the analysis always completes:-
Exception ignored in: <function Variable.__del__ at 0x0000021859A91D30>
Traceback (most recent call last):
File "C:\Users\xxxx\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 363, in __del__
if self._tk.getboolean(self._tk.call("info", "exists", self._name)):
RuntimeError: main thread is not in main loop
Exception ignored in: <function Variable.__del__ at 0x0000021859A91D30>
Traceback (most recent call last):
File "C:\Users\xxxx\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 363, in __del__
if self._tk.getboolean(self._tk.call("info", "exists", self._name)):
RuntimeError: main thread is not in main loop
Exception ignored in: <function Variable.__del__ at 0x0000021859A91D30>
Traceback (most recent call last):
File "C:\Users\xxxx\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 363, in __del__
if self._tk.getboolean(self._tk.call("info", "exists", self._name)):
RuntimeError: main thread is not in main loop
Exception ignored in: <function Variable.__del__ at 0x0000021859A91D30>
Traceback (most recent call last):
File "C:\Users\xxxx\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 363, in __del__
if self._tk.getboolean(self._tk.call("info", "exists", self._name)):
RuntimeError: main thread is not in main loop
Exception ignored in: <function Image.__del__ at 0x0000021859ACF670>
Traceback (most recent call last):
File "C:\Users\xxxx\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 4017, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <function Variable.__del__ at 0x0000021859A91D30>
Traceback (most recent call last):
File "C:\Users\xxxx\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 363, in __del__
if self._tk.getboolean(self._tk.call("info", "exists", self._name)):
RuntimeError: main thread is not in main loop
Exception ignored in: <function Variable.__del__ at 0x0000021859A91D30>
Traceback (most recent call last):
File "C:\Users\xxxx\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 363, in __del__
if self._tk.getboolean(self._tk.call("info", "exists", self._name)):
RuntimeError: main thread is not in main loop
Exception ignored in: <function Variable.__del__ at 0x0000021859A91D30>
Traceback (most recent call last):
File "C:\Users\xxxx\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 363, in __del__
if self._tk.getboolean(self._tk.call("info", "exists", self._name)):
✅ Biaxial bending diagram generated ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% [ 7.2030 s ]RuntimeError: main thread is not in main loop
Exception ignored in: <function Variable.__del__ at 0x0000021859A91D30>
Traceback (most recent call last):
File "C:\Users\xxxx\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 363, in __del__
if self._tk.getboolean(self._tk.call("info", "exists", self._name)):
RuntimeError: main thread is not in main loop
Exception ignored in: <function Image.__del__ at 0x0000021859ACF670>
Traceback (most recent call last):
File "C:\Users\xxxx\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 4017, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
✅ Biaxial bending diagram generated ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% [ 7.2030 s ]
When generating the interaction diagrams, I think you should be checking the neutral axis depth is between Zero
& the Depth of section divided by the gamma factor
. If you want the point where the section has all of the concrete area under full compression then because you're factoring the neutral access depth by gamma (I think in your nomenclature) to work out the depth of the compression block, you need to do this.
For example otherwise as it is currently implemented for a section of say 400mm depth when factored by gamma of 0.85 in the analysis to determine the compression block depth 'a', it will only mean you're capturing analysis points from zero compression block depth to 0.85*400 = 340 compression block depth when you determine the points you're working out the moment capacity for to generate the interaction diagram. So you're missing out on data points where the compression block is between 0.85 and 1.0 times the section depth in this example.
I was trying to work out why your interaction diagrams have a much wider spaced range between the last point before the squash load and the squash load, and believe this is one of the reasons, you're missing a few data points at larger neutral axis depths (how much depends on the value of gamma).
Hopefully that makes sense, if not let me know and I can try explain.
Actions:
M=0
so that point_in_diagram()
works as intended. Currently for asymmetric diagrams it is possible to have a point reported as outside the diagram when it should strictly be in the diagram (conservative). However, there should currently be no unconservative reporting.max_comp
computation. We don't need to compute above max_comp
.Originally posted by @Agent6-6-6 in #66 (comment)
Originally posted by Agent6-6-6 August 7, 2022
alpha_squash
which is stored as part of the concrete material is really more specific only to a AS3600 code implementation of the interaction diagram.To Do:
alpha_squash
from Concrete
as it is now obsoleteAS3600
to use calculated alpha_squash
- perhaps implement a ConcreteAS
object?Support Python 3.12!
I think I'll go with defaulting to using the gross section centroid (no material properties applied), with the option to use a user defined centroid if desired.
Originally posted by @robbievanleeuwen in #9 (reply in thread)
Actions:
Hi @robbievanleeuwen
concrete_section.ultimate_bending_capacity()
needs a way of detecting when you analyse a section and enter an axial load that is greater than maximum compression capacity of a cross section. Not having this ability may lead to unconservative results being accepted as being true.
This could be handled within the individual design_code
code if easier, by checking the axial load is less than the max compression before calling concrete_section.ultimate_bending_capacity()
.
But I was thinking you'd be better implementing a max_comp
similar to what you did for the generation of an M/N interaction diagram within concrete_section.ultimate_bending_capacity()
??
If there are issues installing concreteproperties
in the meantime, consider first installing an earlier version of sectionproperties
:
pip install sectionproperties==2.1.5
pip install concreteproperties
Hello @robbievanleeuwen,
I tried to use (https://robbievanleeuwen.github.io/concrete-properties/notebooks/stress_analysis.html) example I can calculate stresses but I can't show them. I take the error in below. My codes are same with example I didn't change anything.
if self._A.ndim > 1 and not isinstance(self, QuadMesh):
AttributeError: 'list' object has no attribute 'ndim'
Thanks.
As per the title, no in-built method exists to calculate cracking moment under the presence of axial tension or compression forces. The assumption of the built-in calculate_cracking_moment()
method is N*=0 kN
Under tension or compression, there is a direct tensile stress (and potentially a moment on the assumption of the axial load acting at the geometric centroid if section is non-symmetric) that is required to be combined with the moment component of stress.
I don't know if this is a bug or a misunderstanding in what is being reported. But if you review MomentCurvatureResults.n
I'd expect that if undertaking an analysis at an axial load of 0 (as this is all that is currently implemented), then for equilibrium these axial loads would be zero as you're looping through all the concrete and steel geometries and adding all the force and moment contributions into the list of moment curvature results.
However this is not the case, you get a whole lot of random numbers like this:-
[0.0, -0.477399625587168, -0.7160994383370962, 0.36906589552563673, -1.042456716982997, -1.418755254032476, -1.676857578247109, 1.7723948539223784, 0.24788216741399083, 1.3830480518536206, 2.277053881669417, 2.392449132697948, 2.1055746989477484, 2.859097843946074, 3.2615732805716107, 2.495338162385451, -4.403265472748899, -5.889407494905754, 6.210181255810312, 7.746934336988488, -7.578399773250567, 10.018343768431805, 5725.446966758347, -11.60338317399146, -11.855866280500777, -13.434843217459274, -12.631551284663146, -15.377393476694124, 13.965917276596883]
If you add a few print statements to the example results in moment_curvature.ipynb
examples you should see what I mean.
This seems to indicate convergence is not being achieved, as for the correct moment being reported the axial equilibrium should equal zero with no external axial load being added. Unless I'm misunderstanding here what is being reported?
I cannot seem to track down the issue (as going into the moment curvature code is like going down a rabbithole as it relies on so many other functions for evaluating stresses, strains, etc that I get a bit lost in what is being worked out/returned having not written it myself!).
But it might be related to the assumed centroid not being the geometric centroid as I noted in #9 (reply in thread)_, and the fact this can throw out either the moment or axial force equilibrium depending on which one you're evaluating. There probably should probably be a check that the axial equilibrium is equal to the external axial load, otherwise raise an exception?
Also.....
When I define my own non-linear stress/strain relationship I tend to get a moment capacity several times the maximum capacity of the section, I'm sure this is related to this issue, but cannot seem to find the culprit and guess solving the above issue my help identify the issue once code base is working as intended. EDIT - sorted this, for future reference - needed to return stress strain relationship to zero in the tension half of the relationship.
Also with the predefined ConcreteLinearNoTension
& ConcreteLinear
materials, there should be a horizontal part of the curve to the ultimate strain? If you address #47, then you end up with quite different moment curvature response as it is reliant on the defined curve for these classes as it tops out at 0.001 strain.
In most analyses, it is assumed that the Angle between the neutral axis and x is theta, which in turn is the Angle between the resultant bending moment and the x axis. Is it correct?
Originally posted by Agent6-6-6 July 24, 2022
"where you're dealing with a variable phi, when doing the interaction curve I believe for accuracy at the point where phi changes from variable to constant you should really be injecting an additional axial load point to capture exact point of change on the interaction curve."
When you print results of say a ultimate bending analysis to the terminal, the resulting table values are consistent with the analysis units, for an SI analysis N & mm.
I feel having a way in these methods to return in kN and kNm via a multiplied scaling factor (like n_scale = 1e-3, m_scale = 1e-6), or other for Imperial units would be useful. As typically you're interested in the answer in these units?
By default return in N & mm, but have option to scale by another factor to units more consistent with typical analyses like kN and kNm for axial and moment respectively if working in SI units.
Thoughts?
I've noted in the AS3600
class (and by extension the NZS3101 class I've been developing following your lead), that the ultimate_bending_capacity
method has an input n
which is noted as being the net axial load
.
Also, the concrete_section
class ultimate_bending_capacity
method has input n
and is also described as net axial load
. However, this one is expecting n=n/phi
as an input so they are not quite the same thing when called from a design code method.
One of them is not correctly defined as they are not quite the same thing, should the design code class input be renamed something different with a description like :param n_load: axial design load/action
or something like that to reflect that it is a design action and not the net axial load if that is being defined as concrete_section
class?
Potentially as well, this requires expanding on the definition in the concrete_section
class that net axial load n
really means net axial load, defined as axial design load/action divided by phi (n=n_load/phi)
if a non-unity
Perhaps also considering renaming n
to n_net
further separates the two different definitions?
This would also further distinguishes where n
might often be utilised for a counter or something like that by a user.
Design codes often have rules around strand not being effective as compression reinforcement. So expectation would be that there would probably only be a tension branch for the strand materials not tension and compression.
If you're aware of some codes allowing strands to be utilised in compression, then a boolean variable could be added to only return the tension branch (or a boolean variable to return both branches, with a default of just the tension branch being created).
Hi @robbievanleeuwen, this is a bit of a weird one that I have encountered a few times and boiled it down the following:-
Describe the bug
Running the code below results in various consistent errors occurring from crashing the kernel and returning a triangle-related error. However, it completes every now and then (often only the first time you run it from VSCode in a jupyter notebook after booting up, but the next time you run it the same errors)!
Very weird, beyond my skills to really diagnose the cause.
This behaviour seems to occur when utilising a doubly symmetric section (section and reinforcement), and with a theta
of 45 degrees only.
One thing I have noted is if say you go to 45+180 or 45+90 degrees rotation for the same section effectively being analysed, it always works. So it is something specifically about 45-degree neutral axes rotation that's causing the effect as far as I can tell.
Can you confirm you see the same behaviour? Any ideas?
Error variation 1
Error variation 2
To Reproduce
Run this code
import numpy as np
import matplotlib.pyplot as plt
import concreteproperties.stress_strain_profile as ssp
from concreteproperties.material import Concrete
from concreteproperties.material import SteelBar
from sectionproperties.pre.library.concrete_sections import concrete_rectangular_section
from concreteproperties.concrete_section import ConcreteSection
from concreteproperties.results import MomentInteractionResults
concrete = Concrete(
name="40 MPa Concrete",
density=2.4e-6,
stress_strain_profile=ssp.ConcreteLinear(elastic_modulus=30e3),
ultimate_stress_strain_profile=ssp.RectangularStressBlock(
compressive_strength=40,
alpha=0.85,
gamma=0.77,
ultimate_strain=0.003,
),
flexural_tensile_strength=3.4,
colour="lightgrey",
)
steel = SteelBar(
name="500 MPa Steel",
density=7.85e-6,
stress_strain_profile=ssp.SteelElasticPlastic(
yield_strength=500,
elastic_modulus=200e3,
fracture_strain=0.15,
),
colour="grey",
)
bar_dia = 20
geom_col = concrete_rectangular_section(
b=600,
d=600,
dia_top=bar_dia,
n_top=4,
dia_bot=bar_dia,
n_bot=4,
dia_side=bar_dia,
n_side=2,
n_circle=8,
cover=35 + 12,
area_top=bar_dia**2 * np.pi / 4,
area_bot=bar_dia**2 * np.pi / 4,
area_side=bar_dia**2 * np.pi / 4,
conc_mat=concrete,
steel_mat=steel,
)
conc_sec_col = ConcreteSection(geom_col)
conc_sec_col.plot_section()
f_mi_res = conc_sec_col.moment_interaction_diagram(theta=45 * np.pi / 180)
print('Success?')
f_mi_res.plot_diagram()
Desktop (please complete the following information):
Describe the bug
I tried pip installing concreteproperties this morning and the design_codes
module wasn't included. Is this a bug or is this feature still in development at this point?
To Reproduce
Steps to reproduce the behaviour: pip install concreteproperties
Expected behaviour
design_codes
module included in installation.
Originally posted by Agent6-6-6 July 23, 2022
"Many codes ACI318 and NZS3101 have a hard upper cutoff for the axial load a section can take... additionally it may be useful to also report the control points and have an option to plot these points on the interaction curves?"
Features to add to moment_interaction_diagram()
:
max_comp: Optional[float] = None
.d_n=D
) and pure bending (N=0
).n_points
to also have the option of providing a list between control points. By default a single value is provided, say 24. If more control points are provided this can be extended to a list e.g. [10, 24] is 10 points between 1st and 2nd control point and 24 points between 2nd and 3rd control point.While the 3D plot is a great visualization, it's hard to use in practice.
I'm sure that a more Python adept user would be able to create a matplotlib 2D plot with multiple biaxial bending diagrams (e.g. contours for different values of N), but I'm struggling.
It would be great if plot_multiple_diagrams for biaxial bending had a built-in option for a 2D flattened plot.
Perhaps a warning is warranted in the docs for this one?
yeah that would make sense, saying something like stress-strain relationship not intended for section capacity analyses, and only intended for section properties analyses? I guess those particular relationships are not a lot of interest from a design standpoint if you know what you're doing, but you could imagine someone incorrectly using it if they didn't understand what they were doing!
Originally posted by @Agent6-6-6 in #49 (comment)
@robbievanleeuwen, I've noted one peculiarity with the way the improvements to M/N curves have been implemented as merged in #66.
When dealing with a max_comp
scenario or a proportionally lower upper limit, then when using n_points
or n_spacing
it puts in the evenly spaced points not between the limits being lower value of upper limit or max_comp
, but over the entire default range and the unused points are truncated at max_comp
. i.e. it just culls some of the points, rather than spacing the defined points between the refined limits if they were lower or higher once max_comp truncates the axial loads to consider for example.
This leads to some issues when plotting the results with a loss of fidelity in the curves due to a significantly reduced number of axial and moment points being returned.
So if you're using a relatively low max_comp
, say for wall design where limits are much lower (in NZ for example singularly reinforced walls it can be as low as 0.015Agfc), then you only get a fraction of the points specified because of the significantly reduced axial load range, and potentially a very jagged plot as a result.
For example, this plot has low max_comp
, but with default n_points = 24, because of the reduced range due to the upper limit only 6 intermediate points are plotted in addition to any defined control points, the others were truncated.
Resolution
I think it would potentially be as easy as distributing the points between the refined limits that will be returned from the method, rather than spacing them between the larger original range of axial load points. So if max_comp
is lower than the axial load corresponding to the upper limit, redefine the upper limit as max_comp
. Then generate the evenly spaced points between the revised limits for the full specified number of points being returned to maintain a "nice curve".
Hopefully, that's all clear and made sense!
In concrete_section.calculate_ultimate_section_actions()
when the m_xy results are calculated, you're effectively calculating an absolute value, so when you plot based on the m_xy moments for a given theta you get some weird results where the values bounce back off the vertical axes when you have an unsymmetrical M/N curve:-
Not quite sure how to address this, need some way of adjusting the sign appropriately based on what plan quadrant your result is in relative the neutral axis or load angle (load angle being as discussed in #31) you've analysed?
Potentially it's as easy as just checking if both m_x or m_y change sign from some prior or following value in the positive side of the curve (depending on what way it is stepping through the axial loads) that you know is past the origin. Then for the plot the m_xy resultant it's deemed negative as its crossed the origin? That would signal the results straddle an orthogonal vertical plane through the origin?.......... I'm sure it' trickier than this though given not yet working in terms of load angle for the M/N curves!
I kind of think to go along with this conversation maybe the docs also need a section/page on the analysis assumptions so user is fully informed on any assumptions and possible pitfalls. Most of this is assumed in any analysis, but no harm in explicitly stating it for clarity. You know the usual stuff like for example:-
Plane sections remain plane (Bernoulli), i.e. sections perpendicular to the axis of bending that are plane before bending remain plane after bending
The strains in both the concrete and the reinforcement varies linearly through the depth of the member, i.e. cross section strains are proportional to the distance from the neutral axis
The strain in the reinforcement is equal to the strain in the concrete at the same level/position, i.e. a perfect bond exists between the reinforcement and the concrete
Any reinforcement is considered as being characterised by a single strain value at the centre of the reinforcement, i.e. for the analysis the strain gradient across the bar diameter is not considered
The maximum strain at the extreme concrete compression fibre is assumed to reach a maximum limiting compressive strain
The stresses in the concrete and reinforcement can be determined from the strains using stress-strain curves for both concrete and steel
The tensile strength of concrete is neglected in strength calculations
The member does not buckle before the ultimate strength of the cross section is attained
The compressive stress-strain relationship for concrete may be assumed to be rectangular, trapezoidal, bilinear, parabolic, or any other arbitrary shape that results in prediction of strength in substantial agreement with the results of comprehensive tests
Other???
Originally posted by @Agent6-6-6 in #9 (reply in thread)
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.
AS3600.moment_interaction_diagram()
does not have an option for a neutral axis angle theta
not equal to zero.
Further, other variables relating to the number of points etc. are not modifiable.
In going through implementing #80, I've noted the following doesn't seem consistent in the numbers utilised.
The example in material.rst
implies a variable youngs modulus E for the strain calculations, and stresses provided max out at 40MPa but compressive strength is defined as only 32 MPa so inputs don't seem consistent with one another. Maybe I'm missing something here though, but it seems like this needs to be modified to a constant E consistent with the specified compressive strength and the maximum compressive strength and max stress aligned so they are the same value?
from concreteproperties.stress_strain_profile import ConcreteUltimateProfile
ConcreteUltimateProfile(
strains=[-20 / 30e3, 0, 20 / 30e3, 30 / 25e3, 40 / 20e3, 0.003],
stresses=[0, 0, 20, 30, 40, 40],
compressive_strength=32,
).plot_stress_strain()
I think this is a case where ultimate_strain
(don't think this is even initiated for this generic profile or parent class which would presumably cause some issues if it was used for a design_code check) and possibly compressive_strength
should possibly just be populated from the user input at the end of the __post_init__
method and not initiate compressive_strength
as an input:-
i.e. self.ultimate_strain = max(self.strains)
, and similar for the concrete_strength
variable.
labels
, control_points
or n_points
do not matchcontrol_points
, rather than raising an exception if not sortedOriginally posted by @Agent6-6-6 in #32 (reply in thread)
Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
Describe the solution you'd like
A clear and concise description of what you want to happen.
Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
Additional context
Add any other context or screenshots about the feature request here.
Describe the bug
Under StressStrainProfile
class the get_ultimate_compressive_strain
method returns max(self.strains)
Whereas under ConcreteServiceProfile
class the get_ultimate_compressive_strain
method it returns self.ultimate_strain
(believe this is incorrect)
When dealing with service stress/strain profiles, some models for confined concrete mean much larger strains are possible than the defined ultimate strain
of a material used for normal ultimate design, so returning this value from ConcreteServiceProfile
based classes is incorrect as may not even be a variable that's defined in the service stress/strain profile as it is irrelevant (this is my case).
The various get_ultimate_compressive_strain
methods should all return max(self.strains)
in my opinion? Note the same applies for returning the tension cases as well, should be min(self.strains)
.
For ConcreteUltimateProfile
the max(self.strains)
is correct as ultimate profiles currently included naturally should be defined based on the maximum ultimate_strain
being the maximum compressive strain based on the appropriate compression block formulation. It's never going to be higher for ultimate design checks, but for service checks concrete models can be higher.
For example a service stress/strain relationship for confined concrete based on a Mander Confined Concrete model for a concrete that at Ultimate design would be limited to 0.003 strain, shows max strain at failure when considering the effects of confinement could be substantially higher (in this case for the service profile the ultimate_strain variable is irrelevant and can have init=false
applied in child classes which causes an error when you use the get_ultimate_compressive_strain
method from ConcreteServiceProfile
):-
Hopefully that makes sense!
Similar to implementation for moment interaction results object
Originally posted by robbievanleeuwen July 27, 2022
Improvements to the way concreteproperties handles different materials.
Currently concreteproperties only allows steel reinforcing bars to be defined as lumped masses. Further, there is no architecture in place to introduce new materials, e.g. carbon fibre, stainless steel etc. A new material module is proposed that allows steel to be considered as structural sections and the simple creation of new material models.
classDiagram
Material <|-- Concrete
Material <|-- Steel
Steel <|-- SteelBar
Steel <|-- SteelStrand
Material <|-- OtherMaterials
class Material{
str name
float density
StressStrainProfile stress_strain_profile
str colour
bool meshed = True
}
class Concrete{
ConcreteUltimateProfile ultimate_stress_strain_profile
float alpha_squash
float flexural_tensile_strength
}
class SteelBar{
bool meshed = False
}
class SteelStrand{
bool meshed = False
other_revelant_parameters
}
Is your feature request related to a problem? Please describe.
When undertaking a moment-curvature analysis, there does not seem to be any way to undertake the analysis with an axial load applied to a member when analysing a column for example?
Describe the solution you'd like
Add the ability to specify an axial load so moment curvature analyses of columns can be undertaken
Additional context
Moment curvature response is highly dependant on the axial load applied to a member for example:-
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.