OP2 java parser/library

201 views
Skip to first unread message

tarres...@gmail.com

unread,
May 26, 2015, 7:04:21 AM5/26/15
to pynast...@googlegroups.com
Hi Steve,

Althoug this is not the correct forum to aks this question, it's the only I found to find some help me about.

I’m working on a free-source Java parser for Nastran OP2 files.
The purpose is to write a java library to open an op2 file and retrieve data to manipulate Nastran Results to, for example, average stress values, etc.

I have two sources of information to know which the file format of op2 files:
1.- pyNastran documention/code (thanks very much for your invaluable job!!!)
2.- DMAP programmer’s guide (pdf from MSC)

I’m able to open an op2 file, read data as integers (4-bytes), little endian, but I can´t link the data with the corresponding data structure that is defined in DMAP guide.

Perhaps this is explained within the pyNastran code, but I not Python programmer, so it´s hard to read trough the code.

I would appreciate if you could provide me with some hints/information about how to de-encrypt the data.


What I’m able to do so far is to read the file header (date, NASTRAN FORT TAPE ID CODE - XXXXXXXX ……. and separate different DATA BLOCKS (I guess there are two types of data blocks, IFP & OFP).

I have attached example of what the file includes for both, IFP & OFP blocks.



OFP Data Blocks

4, 2, 4,
8, 8-bytes length , 8, //When converted to CHAR => OES1X1

4, -1, 4,
4, 7, 4,
28, 28-bytes length , 28, //

4, -2, 4, //Marker
4, 1, 4,
4, 0, 4,

4, 7, 4,
28, 28-bytes length , 28, //

4, -3, 4, //Marker
4, 1, 4,
4, 0, 4,

4, 146, 4,
584, 584-bytes length , 584, //How to read the data, how the data is structured

4, -4, 4, //Marker
4, 1, 4,
4, 0, 4,

4, 12, 4,
120, 120-bytes length , 120, // How to read the data, how the data is structured

4, -5, 4, //Marker
4, 1, 4,
4, 0, 4,

4, 0, 4, //END OF DATA BLOCK

4, 0, 4, //END OF FILE (IF PRESENT)


IFP Data Blocks

4, 2, 4,
8, 8-bytes length , 8, //When converted to CHAR => GEOM2

4, -1, 4,
4, 7, 4,
28, 28-bytes length , 28 // (I guess) DMAP guide = Header + trailer word

4, -2, 4, //Marker
4, 1, 4,
4, 0, 4,

4, 2, 4,
8, 8-bytes length , 8, //

4, -3, 4, //Marker
4, 1, 4,
4, 0, 4,

4, 115, 4,
460, 28-bytes length , 460, //How to read the data, how the data is structured

4, -4, 4, //Marker
4, 1, 4,
4, 0, 4,

4, 3, 4,
12, 12-bytes length , 12 //I guess that this is some trailer record for IFP tables

4, -5, 4, //Marker
4, 1, 4,
4, 0, 4,

4, 0, 4, //END OF DATA BLOCK


Thanks very much in advance.
Javier

Steven Doyle

unread,
May 26, 2015, 1:18:28 PM5/26/15
to pynast...@googlegroups.com
Javier, 

I think of the problem a bit differently mainly because I've abstracted away a lot of the complexity of the OP2.  I call the OFP tables "geometry tables" and the IFP tables "result tables").  I never actually knew their official names :)

First off, if I have a block like:
4, 2, 4,                                         // 8 = 2*4

8,    8-bytes length     , 8,            //When converted to CHAR  =>  GEOM2

The first 4 tells you what block size you will read (4 bytes / 4 bytes per int32=1 int), so you read 1 value.  Then you read another 4 because you just read a set of value(s).  The 2 then tells you what block size you're going to read.  So we now expect to read a 2*4=8, then we're read 8 bytes, and then we'll read another 8.

For large data blocks, they will overbound the max storage size and the rest will be stored in the next N blocks.  There is no way to get the number of blocks before reading the data.  You just need to identify that you're not done reading the data based on the marker information.

The introduction to a block starts with the name, then the [-1, 1, 0] set of values (markers), where a marker is (4, n, 4).  Markers count from -1 to -N, and indicate the type of data that will be on a table.  

A -1 table has the basic block information (e.g. name), -2 has the date, -3 has metadata about the block that will follow.  The meta data includes time step/frequency/load id, table code, analysis type, device code, sort1/sort2, stress/strain flag).  This meta data is also specific to the block type though many blocks are basically duplicates of others (e.g. an OUG is the same as OVG and OAG; displacement/temperature, velocity/acceleration).  The fact that the meta data exists is why I don't develop the F06/PCH reader.  It's so useful and the other formats don't have it.  -4 has the data (e.g. for a OUG displacement block it's (node_id + analysis_code)*1000, grid_point_type_integer (e.g. GRID/SPOINT/RINGAX/EPOINT), tx, ty, tz, rx, ry, rz).  The following tables (e.g. -5, -6, -7, -8, ...) are optional and are repeats of tables -3 and -4 if necessary.  As you said, the block is capped off with a 0 marker and the entire OP2 is capped off with a 0 marker as well.  You can use these to identify if a block is closing, repeating or the OP2 failed.

OES/OSTR, OEF table (stress/strain, force), have an additional element_id_flag that tell you what kind of data block you're going to read in table -4.  Based on the single element flag (1 to roughly 267) or the geometry triple flags, you can usually identify which section in DMAP the definition of the data is stored.  As some sections are very misleading, I'd recommend making sure node id/element id are found correctly by printing out the IDs and making sure you don't see something crazy like -138535343 or 8342859124.  Printing out the data in an F06 table really helps to verify that you'e parsed things properly.

If you get into superelements and optimization histories, you'll start getting duplicate node/element ids at the same time, so when you're really confused, that's why.  PyNastran supports superelements but it doesn't support optimization histories (e.g. a full 100 elements are analyzed on iteration 1, 10 elements on iteration 2, 3 on iteration 3).

There are also some unique tables that don't really follow any established pattern such as the eigenvalue tables and the HISADD tables, but most of the standard ones do.  

I'd also recommend against parsing the geometry tables.  They don't always exist and you'll end up with an integer representing something a PBARL's shape (instead of HAT/T/ROD0).  You'll also end up with node IDs that overbound the max value and other inconsistent behavior (e.g. the PSHELL and PBARL), so it's just easier to read the BDF.

The OP2 class also has a binary_debug flag that will probably help you.  I'm sure it's not perfect, but (I think) it's fairly accurate.

I hope that helps!  Also, do you have a link to your project for people that want to take a look?

Steve


--
You received this message because you are subscribed to the Google Groups "pyNastran dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pynastran-de...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

tarres...@gmail.com

unread,
May 26, 2015, 5:35:55 PM5/26/15
to pynast...@googlegroups.com
Steve,
I do not know how to thanks you for your prompt and accurate answer.

Thanks a lot!!

Now I have to digest all your information and code for a while.

Once I finish a basic class to read stress values for some elements (CQUAD, CBAR...) I will publish it the files. I will let you know.

Best regards
Javier
Reply all
Reply to author
Forward
0 new messages