SteveDoyle2 / pyNastran

A Python-based interface tool for Nastran's file formats
Other
393 stars 154 forks source link

Shear-Moment-Diagram Documentation #700

Closed Czarified closed 2 years ago

Czarified commented 2 years ago

I've been trying to learn pyNastran methods for interface loads, and Load/Moment Diagrams. This has been a very frustrating process, since the documentation for these functions is sparse.

I found an m4 blog post walking through the process, but the function calls seem to be different than in my version (Python: 3.10.4, pyNastran: 1.3.4).

from pyNastran.op2.tables.ogf_gridPointForces.smt import smt_setup, plot_smt
from pyNastran.bdf.mesh_utils.cut_model_by_plane import get_element_centroids, get_stations
import numpy as np

deck = BDF()
deck.read_bdf(deck_filename)

(nids, nid_cd, xyz_cid0, icd_transform, eids, element_centroids_cid0) = smt_setup(deck)

## Starting and Ending Points
# (Exact numbers made up for this thread)
p1 = np.array([500.0, 0.0, 9.0])        # Start at the nose
p3 = np.array([0.0, 0.0, 0.0])            # March towards origin

zaxis = p1 + np.array([0., 0., 1.])  # point B
# defines the XZ plane for the shears/moments
p2 = p1 + np.array([1., 0., 1.])  # point C

xyz1, xyz2, xyz3, i, k, coord_out, stations = get_stations(
    deck, p1, p2, p3, zaxis, nplanes=20
)

I'm expecting my i vector to have a large and negative x-component, and a small and negative z-component, but instead I see the opposite: array([-0.01932164, 0. , 0.99981332])

Am I correct in assuming the i vector is the vector along which to take section cuts? If so, I would expect the stations variable to be an array of length 20, equally spaced from ~500 to 0.

I apologize if I'm just missing something obvious here, but I've been scratching my head on this for several hours for a couple days, with no luck.

SteveDoyle2 commented 2 years ago

So maybe first off, that blog post is referencing a version that was never released. The blog release was supposed to be timed with 1.4, so when I found out it was released much later, I was too busy and not ready for a release. So...1.4 is the dev version and I highly recommend that for doing SMT. It's a lot more streamlined.

Am I correct in assuming the i vector is the vector along which to take section cuts?

No. i is the axis of the output data (e.g., torque is about the i axis). coord_out defines the march direction and we march in the i axis of that coordinate system. In the 1.4 code, that corresponds to iaxis_march, but doesn't exist in the 1.3 code (it's just coord_out.i).

At least conceptually, I think you're big point of confusion is the projection method. The default is method='Z-Axis Projection' and you're using method='CORD2R' options. I find "Z-Axis Projection" to be much easier, so that's what I use. The code below shows an example of each.

from pyNastran.bdf.bdf import BDF
from pyNastran.op2.tables.ogf_gridPointForces.smt import smt_setup, plot_smt
from pyNastran.bdf.mesh_utils.cut_model_by_plane import get_element_centroids, get_stations
import numpy as np

deck = BDF()

## Starting and Ending Points
# (Exact numbers made up for this thread)

p1 = np.array([500.0, 0.0, 9.0])        # Start at the nose
p3 = np.array([0.0, 0.0, 0.0])          # March towards origin

# defines the XZ plane for the shears/moments
p2 = p1 + np.array([1., 0., 1.])  # point C

# Either method is fine, but depends how you want to define z-axis
if 0:
    zaxis = p1 + np.array([0., 0., 1.])  # point B
    xyz1, xyz2, xyz3, i, k, coord_out, iaxis_march, x_stations_march = get_stations(
        deck, p1, p2, p3, zaxis, nplanes=20,
        method='CORD2R',
    )
else:
    zaxis = np.array([0., 0., 1.])  # point B
    xyz1, xyz2, xyz3, i, k, coord_out, iaxis_march, x_stations_march = get_stations(
        deck, p1, p2, p3, zaxis, nplanes=20,
        method='Z-Axis Projection',
    )

print(f'xyz1 = {xyz1}')
print(f'xyz2 = {xyz2}')
print(f'xyz3 = {xyz3}')
print(f'i = {i}')
print(f'{coord_out}')
print(f'iaxis_march = {iaxis_march}')
print(f'x_stations_march = {x_stations_march}; n={len(x_stations_march)}')

xyz1 = [500.   0.   9.]
xyz2 = [501.   0.  10.]
xyz3 = [0. 0. 0.]
i = [1. 0. 0.]
CORD2R                      500.      0.      9.    500.      0.     10.
            501.      0.      9.

iaxis_march = [-0.99983804  0.         -0.01799708]
x_stations_march = [  0.          26.32005229  52.64010457  78.96015686 105.28020915
 131.60026143 157.92031372 184.240366   210.56041829 236.88047058
 263.20052286 289.52057515 315.84062744 342.16067972 368.48073201
 394.80078429 421.12083658 447.44088887 473.76094115 500.08099344]; n=20
Czarified commented 2 years ago

Hi Steve, thanks for responding! That all seems to track. I tried installing the current main branch, but now I'm getting a weird error when reading in the same op2. I definitely don't have a negative node id in my bdf, and the solution otherwise seems fine. Again, it read it before I upgraded.

I did the python setup.py install to get the api and the GUI, but pynastrangui doesn't seem to work now either.

image

(For reference, I'm running this in JupyterLab, and I restarted all of it after upgrading.)

Czarified commented 2 years ago

So I tried going back to v1.3.4, and I can recreate this error another way:

model = read_op2_geom(op2_filename, include_results='grid_point_forces', debug=False, validate=False)

Looks like it's having trouble cross-referencing? Curiously, BDF.read_bdf() and OP2.read_op2() seem to do fine, and I have cross-referencing on.

For reference, this is the first grid card in my deck, and what it's failing on, and it is referenced by multiple CQUAD4 cards.

$<-- --><--  --><--  --><--  --><--  --><--  --><--  -->
GRID     1365922       0   440.0-11.7872-10.2785       0

This seems like a separate issue. I'll pull down one of your example models to try and learn the VMT procedure.

SteveDoyle2 commented 2 years ago

Yeah, so geometry in op2s can be weird. Most of the time, it's fine, but sometimes it can say leave out the GRID points/coords because it wrote them in another form or you just didn't dumb it. There's also information that's lost (e.g., the offt=GGG/BGG flag on the CBAR/CBEAM), so if read_op2_geom works, great, but it's not as good as the bdf.

Regarding the nid>0 thing, I'd need to see a deck. The op2 can be weird...

Czarified commented 2 years ago

Does the OP2.read_op2() method in the 1.4.0-dev version automatically try to build geometry? It doesn't seem to do this in 1.3.4.

SteveDoyle2 commented 2 years ago

They both do that if you're reading the geometry. There's probably some 32 vs. 64 bit thing going on. 1.4 has much better 64 bit support

Czarified commented 2 years ago

Back in 1.4.0-dev:

Looking into my deck some (sorry, I can't share). I think it's because of the garbage NX auto-numbering. Node id's reach 8-digits. Could it be an overflow thing due to 8-digit numbering?

I tried to renumber the model, and got everything much lower with pyNastran (thanks for xref! 😄) in a snap, but this hacky thing uses glue to join different parts (WIP), and I don't see now to manage SET identitification with pyNastran. Are the SET cards stored in the BDF object?

SteveDoyle2 commented 2 years ago

Yeah, not surprised you can't share it, but even just making a plate with fake loads is probably enough. I don't need sane results, just a bug. Alternatively, just comment the check.

SET1/3 cards are stored in the BDF object (.sets I think). Sets in the case control and in the main deck are different, so depends on exactly what you're referring to.

On Thu, Jun 30, 2022 at 1:47 PM Benjamin Crews @.***> wrote:

Back in 1.4.0-dev:

Looking into my deck some (sorry, I can't share). I think it's because of the garbage NX auto-numbering. Node id's reach 8-digits. Could it be an overflow thing due to 8-digit numbering?

I tried to renumber the model, and got everything much lower with pyNastran (thanks for xref! 😄) in a snap, but this hacky thing uses glue to join different parts (WIP), and I don't see now to manage SET identitification with pyNastran. Are the SET cards stored in the BDF object?

— Reply to this email directly, view it on GitHub https://github.com/SteveDoyle2/pyNastran/issues/700#issuecomment-1171661343, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAICUWM4ZXYKO4I6KVL7HZTVRYBXDANCNFSM52GCVHEQ . You are receiving this because you commented.Message ID: @.***>

Czarified commented 2 years ago

I have case control sets. Do they need to be bulk data sets for pyNastran?

I'll see if I can recreate the error in a toy model. I walked thru the blended wing body example and had no major issues.

On Thu, Jun 30, 2022, 5:05 PM Steven Doyle @.***> wrote:

Yeah, not surprised you can't share it, but even just making a plate with fake loads is probably enough. I don't need sane results, just a bug. Alternatively, just comment the check.

SET1/3 cards are stored in the BDF object (.sets I think). Sets in the case control and in the main deck are different, so depends on exactly what you're referring to.

On Thu, Jun 30, 2022 at 1:47 PM Benjamin Crews @.***> wrote:

Back in 1.4.0-dev:

Looking into my deck some (sorry, I can't share). I think it's because of the garbage NX auto-numbering. Node id's reach 8-digits. Could it be an overflow thing due to 8-digit numbering?

I tried to renumber the model, and got everything much lower with pyNastran (thanks for xref! 😄) in a snap, but this hacky thing uses glue to join different parts (WIP), and I don't see now to manage SET identitification with pyNastran. Are the SET cards stored in the BDF object?

— Reply to this email directly, view it on GitHub < https://github.com/SteveDoyle2/pyNastran/issues/700#issuecomment-1171661343 , or unsubscribe < https://github.com/notifications/unsubscribe-auth/AAICUWM4ZXYKO4I6KVL7HZTVRYBXDANCNFSM52GCVHEQ

. You are receiving this because you commented.Message ID: @.***>

— Reply to this email directly, view it on GitHub https://github.com/SteveDoyle2/pyNastran/issues/700#issuecomment-1171677259, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABVBQOUHX3I5ZYOK3GAX7EDVRYD3HANCNFSM52GCVHEQ . You are receiving this because you authored the thread.Message ID: @.***>

SteveDoyle2 commented 2 years ago

I have case control sets. Do they need to be bulk data sets for pyNastran?

No. They are stored in very different ways. Sets in the case control reference are node/element sets and go into something like DISP/STRESS. SET1 cards are commonly referenced by a SPLINE1 and because they're referenced by a SPLINE1, they're nodes. If they were referenced by a MONPNT1 card, they could be aero nodes/elements, structural nodes/elements depending.

Czarified commented 2 years ago

I'm going to close this for now. I walked through the process for the BWB model included in the repo. I can't say I fully understand it, but I can get it to work on a clean model.

I would love to see some more detailed documentation on this, preferably on the readthedocs website. Since v1.4.0 is significant for this capability, I will probably hold off on digging any deeper until that version is officially released.

Thanks for all the help, Steve!

SteveDoyle2 commented 2 years ago

I wouldn't count on that happening any time soon. It's a bit of a pain to do a release, moreso for a minor release (since I have to backport bug fixes), but still.

SMT is really geared around the GUI, which I probably should have mentioned. That's where Z-axis projection came from. I was mad I couldn't just set the z axis :)

On Wed, Jul 20, 2022 at 6:06 AM Benjamin Crews @.***> wrote:

Closed #700 https://github.com/SteveDoyle2/pyNastran/issues/700 as completed.

— Reply to this email directly, view it on GitHub https://github.com/SteveDoyle2/pyNastran/issues/700#event-7029205370, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAICUWO7H72HGWAWCLQ5KYTVU72TXANCNFSM52GCVHEQ . You are receiving this because you commented.Message ID: @.***>