# Openfoamparser
This is a simple Python library for parsing result or mesh files in OpenFOAM output files to Numpy arrays. Both ascii and binary format are supported.
Forked from [AppoloV openfoamparser](https://github.com/ApolloLV/openfoamparser).
Main new feature: bugfix of mesh parsing.
## Installation
Install with pip:
```shell
pip install openfoamparser_mai
```
or install with setup.py by:
```shell
python setup.py install
```
This package requires numpy.
## APIs
### parse field data
- parse_internal_field(fn): parse internal field data from file **fn**, and return field data as numpy.array
- parse_boundary_field(fn): parse boundary field data from file **fn**, return boundary dictionary with boundary name as keys and Numpy.array as values.
- parse_field_all(fn): parse internal field data and boundary field data from file **fn**.
### parse mesh
Class FoamMesh can parse mesh data (in ascii or binary format) and provide inquiry.
#### instantiation
- FoamMesh(path): initialization of class, read and parse mesh data (points, boundary, owner, neighbour, faces) from path/constant/polyMesh
#### instance variables
- points: Numpy.array, coordinates of points, in order of point id, read from mesh file **points**
- owner: a list, the owner cell id of each face, in order of face id, read from mesh file **owner**
- neighbour: a list, the neighbour cell id of each face, read from mesh file **neighbour**. For faces on boudary, their neighbours are boundary's id.
- faces: list of list, the ids of points composed the face, in order of face id, read from mesh file **faces**
- boundary: dictionary, with key of boundary name, value of a namedtuple, `namedtuple('Boundary', 'type, num, start, id')`, in which num is face numer, start is the id of start face, id is the boundary id, equals to `-10 - index`.
- num_point: points number
- num_face: face number
- num_inner_face: inner face number
- num_cell: cell number
- cell_centres: Numpy.array, cell centre coordinates, read from field file, default is None
- cell_volumes: Numpy.array, cell volumes, read from field file, None for default
- face_areas: Numpy.array, face areas, read from field file, None for default
- cell_neighours: list of list, cell neibour cells' id, in order of cell id
- cell_faces: list of list, cell's face id, in order of cell id
#### class methods
- parse_points_content(content): parse points data from mesh file's content, in binary mode
- parse_owner_neighbour_content(content): parse owner or neighbour data from mesh file's content, in binary mode
- parse_faces_content(content): parse faces data from mesh file's content, in binary mode
- parse_boundary_content(content): parse boundary data from mesh file's content, in binary mode
#### mesh inquiry interface
- cell_neighbour_cells(i): return cell neighbours' id of cell i, in list
- boundary_cells(bd): return a generator of cell's id adjacent to boundary **bd**
- is_cell_on_boundary(i, bd): check if cell i is on boundary **bd**. if **bd** is None, check all boundaries.
- is_face_on_boundary(i, bd): check if face i is on boundary **bd**. if **bd** is None, check all boundaries.
## Usage
```python
import Ofpp
V = Ofpp.parse_internal_field('0/V')
wb01 = Ofpp.parse_boundary_field('0.1/alpha.water')
U02,Ub02 = Ofpp.parse_field_all('0.2/U')
mesh = Ofpp.FoamMesh('.')
wall_cells = list(mesh.boundary_cells(b'fixedWall'))
cell_neighbour_5 = mesh.cell_neighbour_cells(5)
```
## Tutorial
### prepare data of OpenFOAM
We use $FOAM_TUTORIALS/multiphase/interFoam/laminar/damBreak/damBreak for the demo.
```shell
➜ cp $FOAM_TUTORIALS/multiphase/interFoam/laminar/damBreak/damBreak .
➜ cd damBreak
➜ ./Allrun
➜ ls
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1 Allrun log
0.05 0.15 0.25 0.35 0.45 0.55 0.65 0.75 0.85 0.95 Allclean constant system
➜ ls 0.6
alphaPhi0.water alpha.water p phi p_rgh U uniform
```
We use postProcess to generate cell volume data, which is written to file '0/V'
```shell
➜ postProcess -func 'writeCellVolumes' -time 0
➜ ls 0
alpha.water alpha.water.orig p_rgh U V
```
### Use Ofpp to process data
Firstly, use function `parse_internal_field` to parse '0/V' and get cell volume data,
```python
>>> import Ofpp
>>> V=Ofpp.parse_internal_field('0/V')
>>> V.shape
(2268,)
>>> sum(V)
0.0049626061800001099
>>> max(V)
2.6281599999999998e-06
>>> min(V)
1.11212e-06
>>>
```
Parse alpha.water to get water's volume fraction,
```python
>>> W0=Ofpp.parse_internal_field('0/alpha.water')
>>> W0.shape
(2268,)
>>> sum(W0*V)
0.00064609979999999856
>>> W01=Ofpp.parse_internal_field('0.1/alpha.water')
>>> sum(W01*V)
0.00064609986628872621
>>> max(W0)
1.0
>>>
```
Parse alpha.water of all time steps, and calculate water volume of each time to check mass ballance:
```python
>>> import numpy as np
>>> Wa=[]
>>> for t in np.arange(0, 1.01, 0.05):
... Wa.append(Ofpp.parse_internal_field('%.4g/alpha.water'%t))
>>> ["{:.5g}".format(sum(x*V)) for x in Wa]
['0.0006461', '0.0006461', '0.0006461', '0.0006461', '0.0006461', '0.0006461', '0.0006461', '0.00064307', '0.00064047', '0.00063953', '0.00063297', '0.00063171', '0.00063171', '0.00063171', '0.00063171', '0.00063171', '0.00063171', '0.00063171', '0.00063171', '0.00063171', '0.00063171']
>>> import matplotlib.pyplot as pl
>>> pl.plot(np.arange(0, 1.01, 0.05), [sum(x*V) for x in Wa], 's-')
```
Parse velocity field, which is a vector field. And calculate the velocity magnitude,
```python
>>> U01=Ofpp.parse_internal_field('0.1/U')
>>> U01.shape
(2268, 3)
>>> U01[50]
array([ 0.280417 , -0.0783402, 0. ])
>>> v01=(U01[:,0]**2+U01[:,1]**2+U01[:,2]**2)**0.5
>>> v01[50]
0.29115439344966104
```
Noticing that some fields are uniform, eg. initial velocity, whose data is a vector,
```python
>>> U0=Ofpp.parse_internal_field('0/U')
>>> U0
array([ 0., 0., 0.])
>>>
```
### boundary data
Boundary data parsed by Ofpp is a dictionary because there are usually more than one boundary entities. Its keys are boundary names and values are also dictionaries.
```python
>>> b01=Ofpp.parse_boundary_field('0.1/alpha.water')
>>> b01.keys()
dict_keys([b'rightWall', b'atmosphere', b'leftWall', b'lowerWall', b'defaultFaces'])
>>> b01[b'atmosphere'].keys()
dict_keys([b'inletValue', b'value'])
>>> b01[b'atmosphere'][b'inletValue']
0.0
>>> b01[b'atmosphere'][b'value'].shape
(46,)
>>> b01[b'atmosphere'][b'value']
array([ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
0.00000000e+00, 0.00000000e+00, 6.48450000e-54,
1.03531000e-52, 3.02802000e-53, 1.67528000e-53,
9.36177000e-54, 4.89156000e-54, 2.18620000e-54,
5.33282000e-55, 8.91129000e-56, 1.13156000e-56,
1.13522000e-57, 9.31454000e-59, 6.39173000e-60,
3.72975000e-61, 1.85390000e-62, 8.04808000e-64,
3.10349000e-65, 1.01620000e-66, 2.83696000e-68,
6.78134000e-70, 1.35776000e-71, 2.23345000e-73,
2.92040000e-75, 2.88435000e-77, 1.93630000e-79,
5.49169000e-82])
>>>
```
### mesh
Create a FoamMesh object and read mesh file.
```python
>>> mesh = Ofpp.FoamMesh('.')
>>> mesh.num_face
9176
>>> mesh.num_inner_face
4432
>>> mesh.num_cell
2267
>>> mesh.num_point
4746
>>> mesh.boundary
{b'lowerWall': Boundary(type=b'wall', num=62, start=4532, id=-12),
b'rightWall': Boundary(type=b'wall', num=50, start=4482, id=-11),
b'atmosphere': Boundary(type=b'patch', num=46, start=4594, id=-13),
b'defaultFaces': Boundary(type=b'empty', num=4536, start=4640, id=-14),
b'leftWall': Boundary(type=b'wall', num=50, start=4432, id=-10)}
>>>
```
Read outside data for cell volumes, cell centers
```python
>>> mesh.read_cell_volumes('0/V')
>>> mesh.read_cell_centres('0/C')
```
Mesh inquiry:
```python
>>> mesh.cell_neighbour_cells(300)
[281, 299, 301, 319, -14, -14]
>>> mesh.cell_faces[134]
[263, 264, 4797, 4981, 219, 261]
>>> cell_to_wall=list(mesh.boundary_cells(b'leftWall'))
>>> len(cell_to_wall)
50
>>> mesh.is_cell_on_boundary(545)
True
>>> mesh.is_cell_on_boundary(545, b'atmosphere')
False
>>> mesh.is_face_on_boundary(334, b'leftWall')
False
```
## Authors
XU Xianghua <dayigu at gmail dot com>
Jan Drees <jdrees at mail dot uni-paderborn dot de>
Timothy-Edward-Kendon
YuyangL
Raw data
{
"_id": null,
"home_page": "https://www.ccs-labs.org/",
"name": "openfoamparser-mai",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "",
"keywords": "openfoam cfd parser",
"author": "CCS-Labs",
"author_email": "vadim@phygitalism.com",
"download_url": "https://files.pythonhosted.org/packages/3e/d5/51ce4a16465407dcce7e3defe2648c98ce5965cc446c28e568e5b675f0ac/openfoamparser_mai-0.14.tar.gz",
"platform": null,
"description": "# Openfoamparser\nThis is a simple Python library for parsing result or mesh files in OpenFOAM output files to Numpy arrays. Both ascii and binary format are supported.\n\nForked from [AppoloV openfoamparser](https://github.com/ApolloLV/openfoamparser).\n\nMain new feature: bugfix of mesh parsing.\n\n## Installation\n\nInstall with pip:\n\n```shell\npip install openfoamparser_mai\n```\n\nor install with setup.py by:\n\n```shell\npython setup.py install\n```\n\nThis package requires numpy.\n\n## APIs\n\n### parse field data\n\n- parse_internal_field(fn): parse internal field data from file **fn**, and return field data as numpy.array\n- parse_boundary_field(fn): parse boundary field data from file **fn**, return boundary dictionary with boundary name as keys and Numpy.array as values.\n- parse_field_all(fn): parse internal field data and boundary field data from file **fn**.\n\n### parse mesh\n\nClass FoamMesh can parse mesh data (in ascii or binary format) and provide inquiry.\n\n#### instantiation \n\n- FoamMesh(path): initialization of class, read and parse mesh data (points, boundary, owner, neighbour, faces) from path/constant/polyMesh\n\n#### instance variables\n\n- points: Numpy.array, coordinates of points, in order of point id, read from mesh file **points**\n- owner: a list, the owner cell id of each face, in order of face id, read from mesh file **owner**\n- neighbour: a list, the neighbour cell id of each face, read from mesh file **neighbour**. For faces on boudary, their neighbours are boundary's id.\n- faces: list of list, the ids of points composed the face, in order of face id, read from mesh file **faces**\n- boundary: dictionary, with key of boundary name, value of a namedtuple, `namedtuple('Boundary', 'type, num, start, id')`, in which num is face numer, start is the id of start face, id is the boundary id, equals to `-10 - index`.\n- num_point: points number\n- num_face: face number\n- num_inner_face: inner face number\n- num_cell: cell number\n- cell_centres: Numpy.array, cell centre coordinates, read from field file, default is None\n- cell_volumes: Numpy.array, cell volumes, read from field file, None for default\n- face_areas: Numpy.array, face areas, read from field file, None for default\n- cell_neighours: list of list, cell neibour cells' id, in order of cell id\n- cell_faces: list of list, cell's face id, in order of cell id\n\n#### class methods\n\n- parse_points_content(content): parse points data from mesh file's content, in binary mode\n- parse_owner_neighbour_content(content): parse owner or neighbour data from mesh file's content, in binary mode\n- parse_faces_content(content): parse faces data from mesh file's content, in binary mode\n- parse_boundary_content(content): parse boundary data from mesh file's content, in binary mode\n\n#### mesh inquiry interface\n\n- cell_neighbour_cells(i): return cell neighbours' id of cell i, in list\n- boundary_cells(bd): return a generator of cell's id adjacent to boundary **bd**\n- is_cell_on_boundary(i, bd): check if cell i is on boundary **bd**. if **bd** is None, check all boundaries.\n- is_face_on_boundary(i, bd): check if face i is on boundary **bd**. if **bd** is None, check all boundaries.\n\n## Usage\n\n```python\nimport Ofpp\nV = Ofpp.parse_internal_field('0/V')\nwb01 = Ofpp.parse_boundary_field('0.1/alpha.water')\nU02,Ub02 = Ofpp.parse_field_all('0.2/U')\nmesh = Ofpp.FoamMesh('.')\nwall_cells = list(mesh.boundary_cells(b'fixedWall'))\ncell_neighbour_5 = mesh.cell_neighbour_cells(5)\n```\n\n\n\n## Tutorial\n\n### prepare data of OpenFOAM\n\nWe use $FOAM_TUTORIALS/multiphase/interFoam/laminar/damBreak/damBreak for the demo.\n\n```shell\n\u279c cp $FOAM_TUTORIALS/multiphase/interFoam/laminar/damBreak/damBreak .\n\u279c cd damBreak\n\u279c ./Allrun\n\u279c ls\n0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1 Allrun log\n0.05 0.15 0.25 0.35 0.45 0.55 0.65 0.75 0.85 0.95 Allclean constant system\n\u279c ls 0.6\n alphaPhi0.water alpha.water p phi p_rgh U uniform\n```\n\nWe use postProcess to generate cell volume data, which is written to file '0/V'\n\n```shell\n\u279c postProcess -func 'writeCellVolumes' -time 0\n\u279c ls 0\nalpha.water alpha.water.orig p_rgh U V\n```\n\n### Use Ofpp to process data\n\nFirstly, use function `parse_internal_field` to parse '0/V' and get cell volume data,\n\n```python\n>>> import Ofpp\n>>> V=Ofpp.parse_internal_field('0/V')\n>>> V.shape\n(2268,)\n>>> sum(V)\n0.0049626061800001099\n>>> max(V)\n2.6281599999999998e-06\n>>> min(V)\n1.11212e-06\n>>>\n```\n\nParse alpha.water to get water's volume fraction,\n\n```python\n>>> W0=Ofpp.parse_internal_field('0/alpha.water')\n>>> W0.shape\n(2268,)\n>>> sum(W0*V)\n0.00064609979999999856\n>>> W01=Ofpp.parse_internal_field('0.1/alpha.water')\n>>> sum(W01*V)\n0.00064609986628872621\n>>> max(W0)\n1.0\n>>>\n```\n\nParse alpha.water of all time steps, and calculate water volume of each time to check mass ballance: \n\n```python\n>>> import numpy as np\n>>> Wa=[]\n>>> for t in np.arange(0, 1.01, 0.05):\n... Wa.append(Ofpp.parse_internal_field('%.4g/alpha.water'%t))\n>>> [\"{:.5g}\".format(sum(x*V)) for x in Wa]\n['0.0006461', '0.0006461', '0.0006461', '0.0006461', '0.0006461', '0.0006461', '0.0006461', '0.00064307', '0.00064047', '0.00063953', '0.00063297', '0.00063171', '0.00063171', '0.00063171', '0.00063171', '0.00063171', '0.00063171', '0.00063171', '0.00063171', '0.00063171', '0.00063171']\n>>> import matplotlib.pyplot as pl\n>>> pl.plot(np.arange(0, 1.01, 0.05), [sum(x*V) for x in Wa], 's-')\n```\n\nParse velocity field, which is a vector field. And calculate the velocity magnitude,\n\n```python\n>>> U01=Ofpp.parse_internal_field('0.1/U')\n>>> U01.shape\n(2268, 3)\n>>> U01[50]\narray([ 0.280417 , -0.0783402, 0. ])\n>>> v01=(U01[:,0]**2+U01[:,1]**2+U01[:,2]**2)**0.5\n>>> v01[50]\n0.29115439344966104\n```\n\nNoticing that some fields are uniform, eg. initial velocity, whose data is a vector,\n\n```python\n>>> U0=Ofpp.parse_internal_field('0/U')\n>>> U0\narray([ 0., 0., 0.])\n>>>\n```\n\n\n\n### boundary data\n\nBoundary data parsed by Ofpp is a dictionary because there are usually more than one boundary entities. Its keys are boundary names and values are also dictionaries.\n\n```python\n>>> b01=Ofpp.parse_boundary_field('0.1/alpha.water')\n>>> b01.keys()\ndict_keys([b'rightWall', b'atmosphere', b'leftWall', b'lowerWall', b'defaultFaces'])\n>>> b01[b'atmosphere'].keys()\ndict_keys([b'inletValue', b'value'])\n>>> b01[b'atmosphere'][b'inletValue']\n0.0\n>>> b01[b'atmosphere'][b'value'].shape\n(46,)\n>>> b01[b'atmosphere'][b'value']\narray([ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n 0.00000000e+00, 0.00000000e+00, 6.48450000e-54,\n 1.03531000e-52, 3.02802000e-53, 1.67528000e-53,\n 9.36177000e-54, 4.89156000e-54, 2.18620000e-54,\n 5.33282000e-55, 8.91129000e-56, 1.13156000e-56,\n 1.13522000e-57, 9.31454000e-59, 6.39173000e-60,\n 3.72975000e-61, 1.85390000e-62, 8.04808000e-64,\n 3.10349000e-65, 1.01620000e-66, 2.83696000e-68,\n 6.78134000e-70, 1.35776000e-71, 2.23345000e-73,\n 2.92040000e-75, 2.88435000e-77, 1.93630000e-79,\n 5.49169000e-82])\n>>>\n```\n\n### mesh\n\nCreate a FoamMesh object and read mesh file.\n\n```python\n>>> mesh = Ofpp.FoamMesh('.')\n>>> mesh.num_face\n9176\n>>> mesh.num_inner_face\n4432\n>>> mesh.num_cell\n2267\n>>> mesh.num_point\n4746\n>>> mesh.boundary\n{b'lowerWall': Boundary(type=b'wall', num=62, start=4532, id=-12), \n b'rightWall': Boundary(type=b'wall', num=50, start=4482, id=-11), \n b'atmosphere': Boundary(type=b'patch', num=46, start=4594, id=-13), \n b'defaultFaces': Boundary(type=b'empty', num=4536, start=4640, id=-14), \n b'leftWall': Boundary(type=b'wall', num=50, start=4432, id=-10)}\n>>>\n\n```\n\nRead outside data for cell volumes, cell centers\n\n```python\n>>> mesh.read_cell_volumes('0/V')\n>>> mesh.read_cell_centres('0/C')\n \n```\n\nMesh inquiry:\n\n```python\n>>> mesh.cell_neighbour_cells(300)\n[281, 299, 301, 319, -14, -14]\n>>> mesh.cell_faces[134]\n[263, 264, 4797, 4981, 219, 261]\n>>> cell_to_wall=list(mesh.boundary_cells(b'leftWall'))\n>>> len(cell_to_wall)\n50\n>>> mesh.is_cell_on_boundary(545)\nTrue\n>>> mesh.is_cell_on_boundary(545, b'atmosphere')\nFalse\n>>> mesh.is_face_on_boundary(334, b'leftWall')\nFalse\n```\n\n\n\n## Authors\n\nXU Xianghua <dayigu at gmail dot com>\n\nJan Drees <jdrees at mail dot uni-paderborn dot de>\n\nTimothy-Edward-Kendon\n\nYuyangL",
"bugtrack_url": null,
"license": "",
"summary": "Lightweight library to parse OpenFOAM files using Numpy (Ofpp Fork)",
"version": "0.14",
"split_keywords": [
"openfoam",
"cfd",
"parser"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "37e6767d6eb8c1cc531fec524e943184c94b7454bd0fcca1c3882cd07f970ee9",
"md5": "4778da77c186d26058c0f0b614bf5595",
"sha256": "a1393b383bd560e1f592a66bef30c8722de10718f2760634d565a1c3e82b6be5"
},
"downloads": -1,
"filename": "openfoamparser_mai-0.14-py3.8.egg",
"has_sig": false,
"md5_digest": "4778da77c186d26058c0f0b614bf5595",
"packagetype": "bdist_egg",
"python_version": "0.14",
"requires_python": ">=3.7",
"size": 32704,
"upload_time": "2023-04-13T17:21:51",
"upload_time_iso_8601": "2023-04-13T17:21:51.431262Z",
"url": "https://files.pythonhosted.org/packages/37/e6/767d6eb8c1cc531fec524e943184c94b7454bd0fcca1c3882cd07f970ee9/openfoamparser_mai-0.14-py3.8.egg",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "3ed551ce4a16465407dcce7e3defe2648c98ce5965cc446c28e568e5b675f0ac",
"md5": "2a70d84487f483c88874afd9a654963b",
"sha256": "238b0e328050424549553d50f3899316edaacdb65a594de6ba21f230c1712747"
},
"downloads": -1,
"filename": "openfoamparser_mai-0.14.tar.gz",
"has_sig": false,
"md5_digest": "2a70d84487f483c88874afd9a654963b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 15678,
"upload_time": "2023-04-13T17:21:53",
"upload_time_iso_8601": "2023-04-13T17:21:53.326507Z",
"url": "https://files.pythonhosted.org/packages/3e/d5/51ce4a16465407dcce7e3defe2648c98ce5965cc446c28e568e5b675f0ac/openfoamparser_mai-0.14.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-04-13 17:21:53",
"github": false,
"gitlab": false,
"bitbucket": false,
"lcname": "openfoamparser-mai"
}