{"id":19974262,"url":"https://github.com/gbroques/ccxmeshreader","last_synced_at":"2025-05-04T02:32:33.432Z","repository":{"id":62561190,"uuid":"293311996","full_name":"gbroques/ccxmeshreader","owner":"gbroques","description":"Reads a mesh from CalcluliX input (.inp) files.","archived":false,"fork":false,"pushed_at":"2020-09-15T00:37:58.000Z","size":127,"stargazers_count":6,"open_issues_count":6,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-17T15:13:38.488Z","etag":null,"topics":["calculix","calculix-crunchix","calculix-fem-solver","fem","finite-element-mesh","finite-element-method","finite-elements","inp","mesh","parser","reader"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gbroques.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-09-06T16:02:38.000Z","updated_at":"2023-03-31T16:40:09.000Z","dependencies_parsed_at":"2022-11-03T14:45:49.307Z","dependency_job_id":null,"html_url":"https://github.com/gbroques/ccxmeshreader","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbroques%2Fccxmeshreader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbroques%2Fccxmeshreader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbroques%2Fccxmeshreader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbroques%2Fccxmeshreader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gbroques","download_url":"https://codeload.github.com/gbroques/ccxmeshreader/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252279059,"owners_count":21722831,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["calculix","calculix-crunchix","calculix-fem-solver","fem","finite-element-mesh","finite-element-method","finite-elements","inp","mesh","parser","reader"],"created_at":"2024-11-13T03:14:28.788Z","updated_at":"2025-05-04T02:32:33.179Z","avatar_url":"https://github.com/gbroques.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ccxmeshreader\n\n[![PyPI version](https://badge.fury.io/py/ccxmeshreader.svg)](https://badge.fury.io/py/ccxmeshreader)\n[![Conda version](https://anaconda.org/gbroques/ccxmeshreader/badges/version.svg)](https://anaconda.org/gbroques/ccxmeshreader)\n[![Build Status](https://travis-ci.org/gbroques/ccxmeshreader.svg?branch=master)](https://travis-ci.org/gbroques/ccxmeshreader)\n\n* [Introduction](#introduction)\n* [Usage](#usage)\n* [Supported Keywords](#supported-keywords)\n    * [*NODE](#node)\n    * [*ELEMENT](#element)\n    * [*ELSET](#elset)\n    * [*MATERIAL](#material)\n        * [*ELASTIC](#elastic)\n    * [*INCLUDE](#include)\n* [Approach](#approach)\n* [Limitations](#limitations)\n* [Unit Tests](#unit-tests)\n\n## Introduction\nReads a mesh from CalcluliX input (`.inp`) files.\n\nOnly supports a limited set of keywords defining the mesh. See [Supported Keywords](#supported-keywords) for details.\n\n## Usage\n```python\nfrom ccxmeshreader import read_mesh\n\n\nmesh = read_mesh('path/to/some.inp')\n```\n\n## Supported Keywords\n\n### *NODE\nNodes and their coordinates are parsed and added to the dictionary returned by `read_mesh` in the `node_coordinates_by_number` key.\n\nThe `node_coordinates_by_number` key contains a dictionary where the key is the node number, and value is the coordinates as a three-element tuple with float values.\n\nFor example, given the following `*NODE` definition:\n```\n*NODE, NSET=Nall\n1,  1.0, 0.0, 0.1\n2,  3.0, 1.0, 2.0\n3,  0.9, 5.0, 7.0\n```\n```python\nmesh = read_mesh('example.inp')\nprint(mesh['node_coordinates_by_number'])\n```\n```\n{\n    1: (1.0, 0.0, 0.1),\n    2: (3.0, 1.0, 2.0),\n    3: (0.9, 5.0, 7.0)\n}\n```\n\nCurrently node sets are not supported, and the optional `NSET` parameter is ignored.\n\n### *ELEMENT\nElements and their associated nodes are parsed and added to the dictionary returned by `read_mesh` in the `element_dict_by_type` key.\n\nThe `element_dict_by_type` key contains a dictionary where the key is the element type, and value is another dictionary where the key is the element number,\nand value is a list of node numbers associated to the element.\n\nFor example, given the following `*ELEMENT` definition:\n```\n*ELEMENT, TYPE=C3D20R, ELSET=Eall\n1,  1, 2, 3\n2,  4, 5, 6\n```\n```python\nmesh = read_mesh('example.inp')\nprint(mesh['element_dict_by_type'])\n```\n```\n{\n    'C3D20R': {\n        1: [1, 2, 3]\n        2: [4, 5, 6]\n    }\n}\n```\n\nContinuation of data-lines ending with a comma `,` is supported. For example:\n\n```\n*ELEMENT, TYPE=C3D20R, ELSET=Eall\n1,  1, 2, 3,\n    4, 5, 6\n2,  7, 8, 9\n```\n```python\nmesh = read_mesh('example.inp')\nprint(mesh['element_dict_by_type'])\n```\n```\n{\n    'C3D20R': {\n        1: [1, 2, 3, 4, 5, 6]\n        2: [7, 8, 9]\n    }\n}\n```\n\n---\n\nIf the `ELSET` parameter is provided, then the element set will be added to the `element_set_by_name` dictionary returned in the mesh of `read_mesh` with the corresponding element numbers.\n\nFor example, from the above `*ELEMENT` definition:\n```python\nmesh = read_mesh('example.inp')\nprint(mesh['element_set_by_name'])\n```\n```\n{\n    'Eall': {1, 2}\n}\n```\n\n### *ELSET\nElement set definitions are parsed and added to the dictionary returned by `read_mesh` in the `element_set_by_name` key.\n\nThe `element_set_by_name` key contains a dictionary where the key is the name of the element set, and value is a set of element numbers.\n\nFor example, given the following `*ELEMENT` and `*ELSET` definitions:\n```\n*ELEMENT, TYPE=S4, ELSET=E1\n1, 1, 2, 3,\n   4, 5, 6\n2, 7, 8, 9\n\n*ELSET, ELSET=E2, GENERATE\n1, 4\n\n*ELSET,ELSET=E3\nE2, 5, 6\n```\n```python\nmesh = read_mesh('example.inp')\nprint(mesh['element_set_by_name'])\n```\n```\n{\n    'E1': {1, 2},\n    'E2': {1, 2, 3, 4}\n    'E3': {1, 2, 3, 4, 5, 6}\n}\n```\nThe optional `GENERATE` parameter is respected with start, end, and step.\n\n### *MATERIAL\nMaterials are parsed and added to the dictionary returned by `read_mesh` in the `materials` key.\n\nThe `materials` key contains a list of material dictionaries with properties depending upon subsequent material definition cards with the exception of the **required** `name` property.\n\nFor example, given the following `*MATERIAL` definition:\n```\n*MATERIAL, NAME=SolidMaterial\n*ELASTIC\n210000, 0.300\n```\n```python\nmesh = read_mesh('example.inp')\nprint(mesh['materials'])\n```\n```\n[\n    {\n        'name': 'SolidMaterial',\n        'elastic': {\n            'type': 'ISO',\n            'youngs_modulus': 210000,\n            'poissons_ratio': 0.300\n        }\n    }\n]\n```\n\n#### *ELASTIC\nCurrently only elastic properties of type `ISO` are supported.\n\n`ORTHO`, `ENGINEERING CONSTANTS`, and `ANISO` types are ignored.\n\nFor type `ISO`, the Young's modulus and Poisson's ratio are parsed and added under the `elastic` key in the material dictionary.\n\nFor example, given the following `*MATERIAL` definition:\n```\n*MATERIAL, NAME=SolidMaterial\n*ELASTIC\n210000, 0.300\n```\n```python\nmesh = read_mesh('example.inp')\nprint(mesh['materials'])\n```\n```\n[\n    {\n        'name': 'SolidMaterial',\n        'elastic': {\n            'type': 'ISO',\n            'youngs_modulus': 210000,\n            'poissons_ratio': 0.300\n        }\n    }\n]\n```\n\n### *INCLUDE\nFiles specified by the `*INCLUDE` keyword are read, but currently limited to relative file paths, and assumed to be relative to the path passed to `read_mesh`.\n\nRecursive includes (i.e. `*INCLUDE` statements in a previously included file) are not yet supported.\n\n## Approach\nThe approach this library takes is to read the `.inp` file in a `while` loop, line-by-line, until there are no lines left, and collect the nodes and elements that make up the mesh into a dictionary.\n\nIt does not use an intermediate step of parsing the `.inp` file into an abstract syntax tree -- as doing so would be costly and likely involve a parsing library.\n\nThus, `ccxmeshreader` can be considered light-weight and performant.\n\n## Limitations\nContinuation of keyword lines is not supported.\n\nFor example, trying to read the following `.inp` file:\n\n```\n*ELEMENT, TYPE=C3D20R,\nELSET=Eall\n```\n\nraises a `ccxmeshreader.ParserError`.\n\n## Unit Tests\nUnit tests are included in the `tests/` directory, and can be ran with the following command:\n\n    python -m unittest discover tests \"*_test.py\"\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgbroques%2Fccxmeshreader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgbroques%2Fccxmeshreader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgbroques%2Fccxmeshreader/lists"}