Skip to content
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

Incorrect strain being returned from ConcreteServiceProfile #47

Closed
Agent6-6-6 opened this issue Sep 24, 2022 · 4 comments
Closed

Incorrect strain being returned from ConcreteServiceProfile #47

Agent6-6-6 opened this issue Sep 24, 2022 · 4 comments
Assignees

Comments

@Agent6-6-6
Copy link
Contributor

Agent6-6-6 commented Sep 24, 2022

Hi @robbievanleeuwen

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):-

mander

Hopefully that makes sense!

@Agent6-6-6
Copy link
Contributor Author

Note this also impacts the moment curvature analysis, as it would be failing at 0.003 instead of >0.008 strain in the above example....

@Agent6-6-6
Copy link
Contributor Author

Agent6-6-6 commented Sep 24, 2022

Note making the change suggested changing to max(self.strains) seems to address the brentq algorithm failed warning/failure noted in #46.

EDIT - only for some configurations it seems.

@robbievanleeuwen robbievanleeuwen self-assigned this Oct 10, 2022
@robbievanleeuwen robbievanleeuwen added the bug Something isn't working label Oct 10, 2022
@robbievanleeuwen
Copy link
Owner

Hi @Agent6-6-6, thanks for bringing this one up! Again, sorry for the radio silence, have had a bit of a busy spell!

I like this implementation better than what is currently there. A few thoughts looking at the existing concrete service profiles:

  • ConcreteServiceProfile, has a parameter called ultimate_strain, which is essentially the strain at which failure will occur in the moment-curvature analysis, ceasing the analysis. Perhaps I should rename this to failure_strain to avoid confusion? The new implementation of max(self.strains) has no impact on the generated stress-strain profile.
  • ConcreteLinear is intended as a simple way for a user to create a concrete service profile if they don't intend on performing a moment-curvature analysis, but need the elastic modulus for area, cracked properties etc.
    • If a user was to perform a moment-curvature analysis using this profile there is an optional ultimate_strain parameter that I could again rename to failure_strain?
    • Under the max(self.strains) implementation, the stress-strain profile would need to be amended (strain currently go from -0.001 to 0.001 and stresses outside this range are extrapolated as per the note here) such that max(self.strains) corresponds with failure_strain.
    • However, as stresses are extrapolated from this profile when a strain is outside the range of self.strains, horizontal portions would need to be added at the ends of the profiles to ensure extrapolation works correctly (if this isn't done, the brentq convergence doesn't work very well as the stresses it gets for extreme neutral axes are unrealistic).
    • There are two (possibly more?) solutions that I can see:
      1. Easy - have a very small horizontal portion after failure_strain, e.g. self.strains = [..., failure_strain, (1.0 + 1e-6) * failure_strain]
      2. Harder - each ConcreteServiceProfile must implement it's own version of the parentget_stress() method that only interpolates stresses within the range of self.strains and has an if statement that returns the applicable stress if the strain is outside of the range of self.strains.
  • ConcreteLinearNoTension and EurocodeNonLinear have a combination of the above two dot points. Note that EurocodeNonLinear has this horizontal portion already in its profile to prevent tension between returned for large compressive strains due to extrapolation. This is not currently a problem as get_ultimate_compressive_strain() currently returns self.ultimate_strain. As its currently implemented max(self.strains) would return the largest strain in this profile which is 1.01 * self.ultimate_strain (the horizontal portion of the profile).

In summary, happy to shift to what you are suggesting, but interested in hearing what you think on the above before I implement the change 👍

@Agent6-6-6
Copy link
Contributor Author

Agent6-6-6 commented Oct 13, 2022

@robbievanleeuwen I think I got around this by effectively repurposing the ultimate strain for the ConcreteServiceProfile based stress-strain profile I added yesterday in #40 for the modified Mander confined/unconfined concrete model.

Basically don't initialise the ultimate strain so user doesn't need to provide it as an input, and at the end of developing the stress/strain profile simply set ultimate_strain=max(self.strain). That way the ultimate strain for the service profile where not a fixed value returns the actual failure strain calculated which all seems to work without changing anything.

My main concern was if the user defined this parameter, then the get_ methods returned that vs the actual maximum strain that may have been generated in self.strains. But simply not requiring the user to input it and populating it at the end seems fine.

So I think this can be closed out as most ultimate profiles take a user input for the ultimate strain and that is the cutoff for analysis even if you add more curve past that for interpolation purposes (If I'm understanding the small extension on EurocodeNonLinear correctly. Any other variable strain stress-strain profiles could just utilise a similar method to the ModifiedMander profile I added in #40.

The confined/unconfined profile I added in #40 is predominantly for Moment-Curvature analyses, not intended for ultimate analyses.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants