Skip to main content

FEMAP neutral file parser

Project description

FEMAP neutral file parser

  • Free software: MIT license

Features and limitations

Parse and render FEMAP neutral files. For now, three blocks are interpreted:

  • Block 100 “Neutral File Header”

  • Block 450 “Output Sets”

  • Block 451 “Output Data Vectors”

Usage

To use FEMAP neutral Parser in a project:

>>> from femap_neutral_parser import Parser

To instantiate a new parser, just pass a file path:

>>> neu = Parser("tests/data/mystran_00.NEU")

To have a list of available blocks:

>>> neu.available_blocks()
{'header': 100, 'output_sets': 450, '_output_vectors': 451}

Or maybe in a more human-friendly way is to use info() method, which prints available results and outputs:

>>> neu.info()
<BLANKLINE>
Analysis
========
 * subcase 1: Analyse. NASTRAN SPC 1 - lc1. test (MYSTRAN::Static)
 * subcase 2: Analyse. NASTRAN SPC 1 - lc2. test (MYSTRAN::Static)
<BLANKLINE>
Outputs
=======
access to one of them using `._output_vectors[<title>][<SubcaseID>]['record']
<BLANKLINE>
 * displacements::t_total -> RSS translation
 * displacements::t1 -> T1 translation
 * displacements::t2 -> T2 translation
 * ...
 * cbar_stress::min_comb_a -> BAR EndA Min Stress
 * cbar_stress::min_comb_b -> BAR EndB Min Stress

Access available blocs by attribute:

>>> from pprint import pprint as pp
>>> pp(neu.output_sets)
{1: {'anal_type': 'Static',
     'from_prog': 'Unknown',
     'integer_format': None,
     'notes': '',
     'process_type': None,
     'title': 'Analyse. NASTRAN SPC 1 - lc1. test',
     'value': 0.0},
 2: {'anal_type': 'Static',
     'from_prog': 'Unknown',
     'integer_format': None,
     'notes': '',
     'process_type': None,
     'title': 'Analyse. NASTRAN SPC 1 - lc2. test',
     'value': 0.0}}

Low-level data access

Under the hood, output vectors (block451) are organized as nested dictionaries [<vector title>][<LCID>]:

>>> pp(neu._output_vectors["displacements::t_total"][2])
{'abs_max': 2.578386,
 'calc_warn': True,
 'cent_total': True,
 'comp_dir': 1,
 'component_vec': [10002.0,
                   10003.0,
                   10004.0,
                   0.0,
                   0.0,
                   0.0,
                   0.0,
                   0.0,
                   0.0,
                   0.0],
 'id_max': 7,
 'id_min': 1,
 'max_val': 2.578386,
 'min_val': 0.0,
 'record': array([( 1, 0.000000e+00), ( 2, 2.045391e-01), ( 3, 0.000000e+00),
       ( 4, 1.468270e-02), ( 5, 9.231050e-05), ( 6, 6.276400e-01),
       ( 7, 2.578386e+00), ( 8, 1.025100e-01), ( 9, 2.578363e+00),
       (10, 1.916094e+00), (11, 1.100510e+00), (12, 2.389742e+00)],
      dtype=[('NodeID', '<i8'), ('displacements::t_total', '<f8')]),
 'vecID': 10001}

Aggregated Outputs

Slightly highest level than _output_vectors access, aggregated output is available using Parser.vectors() method. For example, to get all outputs for translations vectors:

>>> arr = neu.vectors(("displacements::t1", "displacements::t2", "displacements::t3"))
>>> arr
rec.array([( 1,  0.        , 0.,  0.000000e+00, 1),
           ( 2, -0.1870816 , 0.,  0.000000e+00, 1),
           ...
           (11,  0.        , 0., -1.100510e+00, 2),
           (12,  0.        , 0., -2.389742e+00, 2)],
          dtype=[('NodeID', '<i8'), ('displacements::t1', '<f8'), ('displacements::t2', '<f8'), ('displacements::t3', '<f8'), ('SubcaseID', '<i8')])

Returned value is a numpy structured array (https://numpy.org/doc/stable/user/basics.rec.html). If Pandas is available, you can request to have a DataFrame instead:

>>> neu.vectors(("displacements::t1", "displacements::t2", "displacements::t3"), asdf=True)
                   displacements::t1  displacements::t2  displacements::t3
SubcaseID NodeID
1         1       0.000000       0.0  0.000000
          2      -0.187082       0.0  0.000000
...
          11      0.000000       0.0 -0.956073
          12      0.000000       0.0 -1.602912
2         1       0.000000       0.0  0.000000
          2      -0.204539       0.0  0.000000
...
          11      0.000000       0.0 -1.100510
          12      0.000000       0.0 -2.389742

You can also request sub-cases IDs, or request raw headers:

>>> neu.vectors(("displacements::t1", "displacements::t2", "displacements::t3"), asdf=True, raw=True,
...              SubcaseIDs=2)
                  T1 translation  T2 translation  T3 translation
SubcaseID NodeID
2         1             0.000000             0.0        0.000000
          2            -0.204539             0.0        0.000000
...
          11            0.000000             0.0       -1.100510
          12            0.000000             0.0       -2.389742

High-Level access

At highest level, you can use the get method that already organize vectors for you:

>>> neu.get(what="displacements", asdf=True)
                        t1   t2        t3        r1        r2            r3
SubcaseID NodeID
1         1       0.000000  0.0  0.000000 -0.000432  0.008923  4.699029e-03
          2      -0.187082  0.0  0.000000  0.000432  0.008923  4.666047e-03
...
2         1       0.000000  0.0  0.000000 -0.000007  0.009755  5.137517e-03
          2      -0.204539  0.0  0.000000  0.000007  0.009755  5.101457e-03
...
          11      0.000000  0.0 -1.100510  0.000000  0.010988  1.006013e-06
          12      0.000000  0.0 -2.389742  0.000000  0.004149  1.360364e-08

One can get the list of high-level shortcuts using Parser.get_vectors() which will return a set of available headers:

>>> neu.get_vectors() == {
... 'elem_gpf',
... 'force_vectors',
... 'displacements',
... 'summed_gpf',
... 'mpc_forces',
... 'constraint_gpf',
... 'cbar_force',
... 'cbar_stress',
... 'cbush_force',
... 'cbush_stress',
... 'cbar_ms',
... 'applied_gpf',
... 'spc_forces',
... 'cbeam_force'
... }
True

Requirements

Beside Python>=3.8, only numpy is required. numpy arrays are released as https://numpy.org/doc/stable/user/basics.rec.html, which makes conversions to Pandas a breeze.

If Pandas is installed (which is advised), the asdf parameters are valid.

Testing

For testing, making docs or coding, all the dev requirements are provided in requirements_dev.txt.

From a blank virtual environment, clone this repo:

git clone https://framagit.org/numenic/femap_neutral_parser.git

Create a Python virtual environment, and activate it:

python -m venv fnp
source fnp/bin/activate

Install requirements:

cd femap_neutral_parser
pip install -r requirements.txt  # install numpy
pip install -r requirements_dev.txt
pip install -e .  # install femap-neutral-parser in new venv

Now testing:

make test  # or make coverage

Building docs:

make docs

History

0.8.3 (2021-09-12)

Major internal refactoring

  • output_vectors becomes internal (_output_vectors). The recommended ways to access data is now Parser.vectors() or Parser.get() at a higher level.

  • no more autotranslate initialisation parameter. Everything is harmonized under the hood.

0.6.0 (2021-07-12)

  • add engineering shortcuts

  • harmonize NodeID and SubcaseID with pynastran

  • vectors are now case insensible

0.5.0 (2021-04-16)

  • improve parsing speed on large files

0.4.0 (2021-04-16)

add:

  • Parser.info()

  • Parser.vectors()

0.3.0 (2021-04-16)

  • add Parser.info() and Parser.vectors()

  • update documentation

  • add info() doprint option

0.2.0 - 0.3.0 (2021-04-16)

  • Update Documentation

0.1.0 (2021-03-24)

First release on PyPI.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

femap_neutral_parser-0.14.0.tar.gz (46.4 kB view details)

Uploaded Source

Built Distribution

femap_neutral_parser-0.14.0-py2.py3-none-any.whl (23.6 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file femap_neutral_parser-0.14.0.tar.gz.

File metadata

  • Download URL: femap_neutral_parser-0.14.0.tar.gz
  • Upload date:
  • Size: 46.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.8.13

File hashes

Hashes for femap_neutral_parser-0.14.0.tar.gz
Algorithm Hash digest
SHA256 ca6ac11ef2ff8631826c74256243ec223ff51921f97b174106618b19cfa22877
MD5 ad9f1711987a03c1d8bda3cb35f26811
BLAKE2b-256 5847cf59bd64d8a41acfdff9468cbc0e98c0e1b7e4fa68688a0e717edcea6dd8

See more details on using hashes here.

File details

Details for the file femap_neutral_parser-0.14.0-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for femap_neutral_parser-0.14.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 d1267761da9d84bf16afbd0fa7aee13c0059306a5441705d9f2a9246663a30ef
MD5 1297fc042d1795fc7eead9a57ecd3b13
BLAKE2b-256 66f37ba082357c8f27581e934177cb9f545ad5f3d13f410766fd8dd87f13fe00

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page