Chris A.
Chris A.

Reputation: 131

How do I output MSC Nastran stress results to a CSV file?

The F06 file contains the stresses for CQUAD4 elements. How do I output this data to a CSV file?

Upvotes: 0

Views: 165

Answers (1)

Chris A.
Chris A.

Reputation: 131

My recommendation is to read the stress or strain data directly from the MSC Nastran H5 result file.

Below is a Python script that writes out the stresses when PSHELL is used. Since PSHELL is used, you will get stresses/strains for the top and bottom of the shell thickness. Also, 2D elements can output data at center of the element OR the corners of the element. To keep things simple, the script outputs only the values at the center of the elements.

NOTE! The Python script dumps all the subcases to one CSV file. If you have multiple subcases/loadcases, I will leave it up to you to differentiate the data to your liking.

One very important question. In what coordinate system are you expecting the element values to be in?

For 2D elements, e.g. CQUAD4, by default element stresses are written out to the F06, OP2 and H5 in the element coordinate system (ECS). This is problematic because the ECSs could point in wildly different directions. See figure 1.

Figure 1 Element coordinate system and material coordinate system of nastran CQUAD4 elements

If you want to control the coordinate system in which the results are output, you could do the following:

  1. Use the MCID field of the 2D element entries to control the material coordinate system (MCS). In the examples below, the MCID is CID=1 and corresponds to CORD2C ID=1. The MCID field is the last field of each 2D element entry.
  2. Use PARAM,OMID,BOTH to output results in both the element coordinate system and material coordinate system.

If you look at figure 1, you can see the difference when ECS and MCS are used to output the stresses and strains.

HDF5OUT $ This outputs an H5 file in MSC Nastran 2021 and newer.
PARAM    OMID    BOTH $ This outputs 2D element results in the ECS and MCS
CQUAD4   1       1       1       2       18      17      1
CQUAD4   2       1       2       3       19      18      1
CQUAD4   3       1       3       4       20      19      1
CTRIA3   91      1       254     253     237      1
CTRIA3   92      1       237     238     254      1
$ Referenced Coordinate Frames
CORD2C   1               0.      0.      0.      0.      0.      1.     +     AT
+     AT 1.      0.      0.

app.py

# Instructions: Modify the path of the H5 file to your liking.
import h5py
import hdf5plugin
import numpy
import csv

def write_dataset_center_to_csv_file(path_of_h5_file, name_of_csv_file, name_of_csv_file_bottom):
    list_of_datasets_to_write_out = [
        '/NASTRAN/RESULT/ELEMENTAL/ELEMENT_OMID/STRESS/QUAD8',
        '/NASTRAN/RESULT/ELEMENTAL/ELEMENT_OMID/STRESS/QUADR',
        '/NASTRAN/RESULT/ELEMENTAL/ELEMENT_OMID/STRESS/QUAD4',
        '/NASTRAN/RESULT/ELEMENTAL/ELEMENT_OMID/STRESS/QUAD_CN',
        '/NASTRAN/RESULT/ELEMENTAL/ELEMENT_OMID/STRESS/TRIA3',
        '/NASTRAN/RESULT/ELEMENTAL/ELEMENT_OMID/STRESS/TRIA6',
        '/NASTRAN/RESULT/ELEMENTAL/ELEMENT_OMID/STRESS/TRIAR',
    ]

    # Create a file object for the H5 file
    file = h5py.File(path_of_h5_file, 'r')

    # Recover the DOMAINS dataset
    # ##############################################################################
    # The DOMAINS dataset contains information about the SUBCASE, TIME_FREQ_EIGR, etc.
    dataset_domains = file['/NASTRAN/RESULT/DOMAINS']

    # Store the 2D element stresses for the top and bottom of the thickness
    # ##############################################################################
    list_of_objects_top = []
    list_of_objects_bottom = []

    for dataset_name in list_of_datasets_to_write_out:
        if dataset_name in file:
            # Recover the dataset of interest
            dataset_original = file[dataset_name]

            column_names = list(dataset_original.dtype.names)
            name_of_last_column = column_names[len(column_names) - 1]
            column_names_domains = list(dataset_domains.dtype.names)
            attach_domains = False

            if name_of_last_column == 'DOMAIN_ID':
                attach_domains = True

            # Stresses at top and bottom for center of element
            for element_i in dataset_original:

                if isinstance(element_i['X1'], numpy.ndarray) is True:
                    object_to_store_top = { 'EID': element_i['EID'], 'X': element_i['X1'][0], 'Y': element_i['Y1'][0], 'XY': element_i['TXY1'][0], 'DOMAIN_ID': element_i['DOMAIN_ID'] }
                    object_to_store_bottom = { 'EID': element_i['EID'], 'X': element_i['X2'][0], 'Y': element_i['Y2'][0], 'XY': element_i['TXY2'][0], 'DOMAIN_ID': element_i['DOMAIN_ID'] }
                else:
                    object_to_store_top = { 'EID': element_i['EID'], 'X': element_i['X1'], 'Y': element_i['Y1'], 'XY': element_i['TXY1'], 'DOMAIN_ID': element_i['DOMAIN_ID'] }
                    object_to_store_bottom = { 'EID': element_i['EID'], 'X': element_i['X2'], 'Y': element_i['Y2'], 'XY': element_i['TXY2'], 'DOMAIN_ID': element_i['DOMAIN_ID'] }

                if attach_domains is True:
                    domain_id = element_i['DOMAIN_ID']

                    for domain_name in column_names_domains:
                        object_to_store_top[domain_name] = dataset_domains[domain_id - 1][domain_name]
                        object_to_store_bottom[domain_name] = dataset_domains[domain_id - 1][domain_name]

                list_of_objects_top.append(object_to_store_top)
                list_of_objects_bottom.append(object_to_store_bottom)

    # Dump the values to CSV files
    # ##############################################################################
    # Top
    keys = list_of_objects_top[0].keys()

    with open(name_of_csv_file, 'w', newline='') as output_file:
        dict_writer = csv.DictWriter(output_file, keys)
        dict_writer.writeheader()
        dict_writer.writerows(list_of_objects_top)

    # Bottom
    keys = list_of_objects_bottom[0].keys()

    with open(name_of_csv_file_bottom, 'w', newline='') as output_file:
        dict_writer = csv.DictWriter(output_file, keys)
        dict_writer.writeheader()
        dict_writer.writerows(list_of_objects_bottom)

if __name__ == '__main__':
    write_dataset_center_to_csv_file('/home/apricot/Downloads/prob004.h5', 'file_3_top.csv', 'file_3_bottom.csv')

Upvotes: 0

Related Questions