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

Model Fails Statics Checks #102

Open
bjhowie opened this issue Sep 27, 2021 · 27 comments
Open

Model Fails Statics Checks #102

bjhowie opened this issue Sep 27, 2021 · 27 comments

Comments

@bjhowie
Copy link
Contributor

bjhowie commented Sep 27, 2021

Sorry to come again with problems and not solutions, but i'm having some trouble with a proof-of-concept lateral stability model that i have been trying to analyse with PyNite. It is a model of an RC building core and shear wall, with some rigid members connecting the two to represent the rigid floor diaphragm.

The model runs fine, and the stress plots on the quad elements look good, but the model fails statics checks. The global reactions are larger than the sum of the applied forces. The 'check_statics' function built in to the 'analyze' method confirms this.

Any thoughts on what could be causing this?

The code to generate the model is complex so i've pickled the model and attached it in a zip file below:

stability_test.zip

I have subclassed PyNite.FEModel3D so you'll need to use the below code to read the model.

import pickle

infile = ...

class customUnpickler(pickle.Unpickler):
    def find_class(self, module, name):
        if module == "Analysis.AnalysisBase":
            module = "PyNite.FEModel3D"
            name = "FEModel3D"

        return super().find_class(module, name)
    
with open(infile,mode="rb") as f: model=customUnpickler(f).load()


Also, i've noticed that Visualization._PrepContour fails when there are nodes in the model not connected to Quad or Plate elements.
node.contour = sum(node.contour)/len(node.contour) results in a divide by zero error.

@JWock82
Copy link
Owner

JWock82 commented Sep 27, 2021

Can you confirm you're using the latest version (0.0.49)? I recently fixed an issue in the statics check related to quadrilateral elements. I want to make sure this is not the same issue.

@bjhowie
Copy link
Contributor Author

bjhowie commented Sep 27, 2021

Yes, using 0.0.49

@JWock82
Copy link
Owner

JWock82 commented Sep 27, 2021

OK. I'll have a closer look at this.

@JWock82 JWock82 added the bug label Sep 27, 2021
@JWock82
Copy link
Owner

JWock82 commented Sep 30, 2021

Another question. I haven't looked at your model yet. But I did take another look at the code calculating the reactions. I had not updated it to account for spring supports yet. That's a newer feature I recently added. Does your model have spring supports?

@bjhowie
Copy link
Contributor Author

bjhowie commented Sep 30, 2021 via email

@JWock82
Copy link
Owner

JWock82 commented Oct 1, 2021

So I've fixed the issue with the divide by zero error. I've also published a new release as v0.0.50 with a few changes to the calculate reactions method. I'm not sure if this fixed it, but I can't check it since the model is pickled. I changed the Node class in version 0.0.50, so I get errors when I run your pickled version. Can you either verify that version 0.0.50 fixes your problem, or send me a new file that's compatible with v0.0.50?

@bjhowie
Copy link
Contributor Author

bjhowie commented Oct 2, 2021

Contours seem to be working now. Still having issues with the statics though.

I've re-run and attached the pickled model below. You'll still need to use the custom unpickler above to deal with the subclassed model class.
Let me know if it still doesnt work.

StabilityModel.zip

@JWock82
Copy link
Owner

JWock82 commented Oct 2, 2021

I'm trying to narrow the list of possible problems down. Will you confirm a few things for me?

  1. Does your model have any quadrilateral surface pressures applied? I didn't see any when I rendered it. It looked like nodal loads only.
  2. Are your elements rectangular? If so, can you switch them to rectangular plate elements instead of quads and see if you have the same issue. That would help me determine if it's a problem with the quad element formulation or something else.

@bjhowie
Copy link
Contributor Author

bjhowie commented Oct 3, 2021

  1. No, node loads only
  2. In the model i sent you, they are not perfectly rectangular. I created another model with rectangular plate elements and the issue still seemed to exist, so its likely not related to the quad element formulation

@JWock82
Copy link
Owner

JWock82 commented Oct 9, 2021

Update: I’m zeroing in on this bug. I’ve figured out how to replicate it in other models. It seems to occur when the plates aren’t parallel to a global plane. That suggests to me that the transformation matrix for these elements has a bug in some cases. I’ll keep looking at it.

@JWock82
Copy link
Owner

JWock82 commented Oct 9, 2021

Alright. I think I've got it figured out. There are two things going on here. First, I had been using the transpose of the transformation matrix instead of the inverse of it to save a little computational overhead. That should work for orthogonal matrices, but when I switch out the transpose with the inverse, the difference between loads and reactions closes a little. I'm not a matrix expert, and maybe this matrix is not orthogonal as I had thought, so I'll switch PyNite to use the inverse since that is mathematically how the algebra works out.

Now for what I believe is the main issue. Plates/quads do not support a drilling degree of freedom. I've built in an artificial weak spring for these elements that prevents model instabilities for drilling loads. The stiffness of this weak spring is somewhat arbitrary, and has no "static" basis. The spring stiffness is calculated as 1/1000 of the smallest bending stiffness in the stiffness matrix. It's a placeholder to prevent a model instability, but it doesn't prevent the user from applying drilling loads to plates.

Your model does not have any drilling loads directly applied, but you do have quads connected to other quads that are not in the same plane and not orthogonal. They appear to be 45 degrees from each other. That means a component of the bending moment in one plate becomes a drilling load on its neighbor. That component becomes "lost" because the plates/quads are not formulated to be loaded that way.

@JWock82 JWock82 removed the bug label Oct 9, 2021
@bjhowie
Copy link
Contributor Author

bjhowie commented Oct 10, 2021

That makes some sense. I dont think it's the non-orthogonal quads that are doing it though, the problem seems to be with the connection of the beam elements to the quads. If i remove all of the beam elements the issue is resolved, even with the quads at ~45 degrees. Even if there are no loads applied to or via the beam elements it throws off the base reactions

The takeaway then is that, with the current element formulations, beam elements cannot connect to quad elements at a single point?

Dissapointing outcome. Is there a way that PyNite can at least detect these drilling conditions and throw an exception instead of happily reporting incorrect results?

@JWock82
Copy link
Owner

JWock82 commented Oct 10, 2021

You may be interested in the following links:

https://risa.com/risahelp/risa2d/Content/Common_Topics/Modeling%20Tips.htm

https://www.eng-tips.com/viewthread.cfm?qid=472062

It looks like there is a plate formulation out there that includes drilling:

https://onlinelibrary.wiley.com/doi/epdf/10.1002/cnm.1630070102

Maybe at some point I’ll pony up the $50 to purchase the document, and then spend the time to figure out how to implement it.

Based on the engineer-tips discussion above, it looks like some of these formulations are questionable, and diverge when the mesh size is reduced.

In most cases I’m willing to guess these errors are inconsequential. In your case, the floor diaphragm is primarily transferring shear to the shear walls. Drilling applied to the plates would be a secondary load transfer mechanism.

@JWock82
Copy link
Owner

JWock82 commented Oct 10, 2021

Also you may try using additional beam elements around the perimeter of the floor attached to the beams and plates. That would resolve the drilling by converting it into a force couple. That’s how my FEA text book suggests handling drilling.

You may also try setting the "J" property of your rigid links to something very small. That would force the load to transfer into the plates using a mechanism other than torsion.

@bjhowie
Copy link
Contributor Author

bjhowie commented Oct 10, 2021

Thanks. I found the same eng-tips article and thought it was quite helpful.

I'm not sure that this is the full story though. We shouldnt need to consider any drilling degrees of freedom to make this model solve (unlike the flag pole example in the article). There are many other loads paths that can transmit the load via translational push/pull action, but seemingly any model that is capable of attracting any miniscule amount of drilling load to the quads is thrown off entirely. Maybe i'm missing something.

Reducing torsional stiffness of rigid links makes no difference.

I will keep looking into it.

@JWock82
Copy link
Owner

JWock82 commented Oct 10, 2021

I agree there are plenty of stiffer alternate load paths available, which doesn’t make sense why the drilling stiffness has any impact. But when I adjust the drilling stiffness the unresolved load changes. I’ll keep digging into it.

@KASR
Copy link

KASR commented Oct 13, 2021

Hello,

Concerning the drilling degree of freedom stiffness, you could try to set the stiffness in the k_m routine by using the minimum eigenvalue of the stress-strain matrix. I commented everything elated to the drilling degrees in the k_b routine and added the following... note that I work with Matlab so I do not know the syntax to compute the eigenvalues using python, but you should get the idea. :)

# Add the term from the unexpanded matrix into the expanded matrix
k_exp[m, n] = k[i, j]

# compute drilling stiffness penalty parameter
#  --> eigenvalues of C_Membrane
k_rz = min( eig( C ) ) 

# Add the drilling degree of freedom's weak spring
k_exp[5, 5] = k_rz
k_exp[11, 11] = k_rz
k_exp[17, 17] = k_rz
k_exp[23, 23] = k_rz

@JWock82
Copy link
Owner

JWock82 commented Oct 20, 2021

I'm still looking into this issue. One thing I'm noticing is that the unbalanced forces on all these models seem relatively small. The table below is the statics check from the model you sent me. The unbalanced SumRY and SumRZ forces in the output below are about 3 orders of magnitude smaller than the SumRX forces. The unbalanced SumRMX moments below are one order of magnitude smaller than the SumFX forces, suggesting a moment arm of less than 1/10 of one length unit. I'm not sure what unit system these forces represent so I can't say if the differeces are significant. All the other forces seem pretty well balanced. This may just be a precision error after the math is crunched.

image

On other models I'm running that have the same issue I'm noticing that the unbalanced forces are minuscule, with zeros out to the 8th decimal place or more. The stress results from the models all compare reasonably to published solutions.

@JWock82
Copy link
Owner

JWock82 commented Oct 21, 2021

I looked at this again tonight. The largest of the unbalanced forces is reported by PyNite as 4440 in the table above. The force you've applied to the nodes in your model is 100,000 per node. That means the unbalanced force is only 4.44% of one of the nodal forces you've applied to the model.

I've been trying, but I can't seem to create a model that has a significant force/reaction imbalance. I think more and more that this is a computational precision error related to plates/quads. There is a lot of numerical integration associated with their force and stiffness matrices. I'm not surprised to see a slight imperfection in the results. I'm going to close this issue, but I'm going to keep an eye out for bad statics checks on all my future plate/quad models.

@JWock82 JWock82 closed this as completed Oct 21, 2021
@JWock82
Copy link
Owner

JWock82 commented Oct 23, 2021

I've spent the last couple of evenings reading through various formulations for plate drilling. I've also been playing with the drilling stiffness to see what happens. Here's what I've discovered:

  1. The unbalanced forces are influenced strongly by the value I use for the drilling stiffness.
  2. There are very complex formulations out there for the drilling stiffness terms. These formulations lead to mathematical "correctness". Whether they lead to engineering correctness is debatable.
  3. The approach PyNite takes of adding a weak spring is proposed by Bathe in "Finite Element Procedures, 2nd Ed." Example 4.19 (starting on p. 207).
  4. This procedure can be used for the DKMQ element which has the same drilling problem as the MITC4 element.
  5. Using a drilling stiffness value of near zero leads to irrational displaced shapes and severely imbalanced forces.
  6. Using a drilling stiffness value of nearly rigid also leads to irrational displaced shapes and severely imbalanced forces.
  7. Bathe recommends using a weak drilling stiffness of 1/1000 of the least diagonal term in the plate's stiffness matrix. PyNite takes this approach, but only considers the diagonal terms related to rotation.
  8. PyNite's displaced shapes seem rational with the 1/1000 stiffness term. The force and moment imbalances appear to be insignificant.

I don't have any plans to pursue this issue any further, but I'll reopen it and add a help wanted tag to this issue. I'll also tag this as a "program limitation". If someone wants to take this any further they are welcome to submit a pull-request. In the meantime, I recommend checking the statics for anything that looks significant. I may add a parameter that allows the user to specify the drilling stiffness in the future. That way you can adjust it if the statics check gets out of control. I may also add a feature that looks at the statics check for significant imbalances and reports errors if they get too large.

@JWock82
Copy link
Owner

JWock82 commented Nov 6, 2021

@bjhowie try running this model again with the latest version. I’ve corrected an issue I found with quadrilaterals related to their in-plane stiffness.

@bjhowie
Copy link
Contributor Author

bjhowie commented Nov 7, 2021

Hey, sorry i never got around to replying to your previous post. Unfortunate outcome, but sounds like it's an inherent limitation of the MITC4 plate formulation.

I ran it again with 0.0.52 but got similar results, in fact the phantom RY reaction increased slightly

image

The Y and Z reactions are small, but maybe not neglegible depending on the application.

@JWock82
Copy link
Owner

JWock82 commented Nov 7, 2021

Thanks bjhowie. I just added more unit testing for plates/quads to compare them against published solutions. Overall I'm finding that the plates are giving very accurate results for out-of-plane, in-plane, and combined forces.

@JWock82
Copy link
Owner

JWock82 commented Mar 13, 2024

@bjhowie,
Today I fixed an issue related to statics checks that may resolve this issue. I don't have access to your original file that showcased the issue. Do you still have it handy by chance?

@bjhowie
Copy link
Contributor Author

bjhowie commented Mar 13, 2024

I should have it somewhere. I'll have a dig around tonight and see if I can find it.

@bjhowie
Copy link
Contributor Author

bjhowie commented Mar 16, 2024

I couldn't find the code that generated the original model, but I used the pickled data attached in the post above to regenerate the model using version 0.0.93.

Your updates definitely seem to have helped the issue. RY and RZ are basically zero. I'm unsure if the RMX reaction is an issue? How is it calculated?
image

@bjhowie
Copy link
Contributor Author

bjhowie commented Mar 17, 2024

OK so i manage to find my old code that generated that model. Doesn't look like your latest changes have helped.

I've used it to generate two more models, one using quad elements and one using plates.
StabilityModels.zip

This is the statics check for the quads model:
image

And for the plates model:
image

Fairly similar but the phantom reactions change slightly, which is probably not unexpected.

I've got some members in there that are intended to represent a rigid diaphragm. In the examples above ive given them the material properties of steel, but if I increase the E value to something like 1E15 (effectively infinitely stiff) then the phantom reactions get very large and the RX sum is no longer correct.

image

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

No branches or pull requests

3 participants