Package: openfoamparser
OpenfoamparserThis 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.InstallationInstall with pip:pipinstallopenfoamparseror install with setup.py by:pythonsetup.pyinstallThis package requires numpy.APIsparse field dataparse_internal_field(fn):  parse internal field data from filefn, and return field data as numpy.arrayparse_boundary_field(fn): parse boundary field data from filefn, 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 filefn.parse meshClass FoamMesh can parse mesh data (in ascii or binary format) and provide inquiry.instantiationFoamMesh(path): initialization of class, read and parse mesh data (points, boundary, owner, neighbour, faces)  from path/constant/polyMeshinstance variablespoints:  Numpy.array, coordinates of points, in order of point id, read from mesh filepointsowner:  a list, the owner cell id of each face, in order of face id, read from mesh fileownerneighbour:  a list, the neighbour cell id of each face, read from mesh fileneighbour. 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 filefacesboundary: 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 numbernum_face: face numbernum_inner_face:  inner face numbernum_cell: cell numbercell_centres: Numpy.array, cell centre coordinates, read from field file, default is Nonecell_volumes: Numpy.array, cell volumes, read from field file, None for defaultface_areas: Numpy.array, face areas, read from field file, None for defaultcell_neighours: list of list, cell neibour cells' id, in order of cell idcell_faces: list of list, cell's face id, in order of cell idclass methodsparse_points_content(content): parse points data from mesh file's content, in binary modeparse_owner_neighbour_content(content): parse owner or neighbour data from mesh file's content, in binary modeparse_faces_content(content): parse faces data from mesh file's content, in binary modeparse_boundary_content(content): parse boundary data from mesh file's content, in binary modemesh inquiry interfacecell_neighbour_cells(i): return cell neighbours' id of cell i, in listboundary_cells(bd): return a generator of cell's id adjacent to boundarybdis_cell_on_boundary(i, bd): check if cell i is on boundarybd. ifbdis None, check all boundaries.is_face_on_boundary(i, bd): check if face i is on boundarybd. ifbdis None, check all boundaries.UsageimportOfppV=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)Tutorialprepare data of OpenFOAMWe use $FOAM_TUTORIALS/multiphase/interFoam/laminar/damBreak/damBreak for the demo.➜cp$FOAM_TUTORIALS/multiphase/interFoam/laminar/damBreak/damBreak.
➜cddamBreak
➜./Allrun
➜ls00.10.20.30.40.50.60.70.80.91Allrunlog0.050.150.250.350.450.550.650.750.850.95Allcleanconstantsystem
➜ls0.6alphaPhi0.wateralpha.waterpphip_rghUuniformWe use postProcess to generate cell volume data, which is written to file '0/V'➜postProcess-func'writeCellVolumes'-time0➜ls0alpha.wateralpha.water.origp_rghUVUse Ofpp to process dataFirstly, use functionparse_internal_fieldto parse '0/V' and get cell volume data,>>>importOfpp>>>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,>>>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:>>>importnumpyasnp>>>Wa=[]>>>fortinnp.arange(0,1.01,0.05):...Wa.append(Ofpp.parse_internal_field('%.4g/alpha.water'%t))>>>["{:.5g}".format(sum(x*V))forxinWa]['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']>>>importmatplotlib.pyplotaspl>>>pl.plot(np.arange(0,1.01,0.05),[sum(x*V)forxinWa],'s-')Parse velocity field, which is a vector field. And calculate the velocity magnitude,>>>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.29115439344966104Noticing that some fields are uniform, eg. initial velocity, whose data is a vector,>>>U0=Ofpp.parse_internal_field('0/U')>>>U0array([0.,0.,0.])>>>boundary dataBoundary 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.>>>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])>>>meshCreate a FoamMesh object and read mesh file.>>>mesh=Ofpp.FoamMesh('.')>>>mesh.num_face9176>>>mesh.num_inner_face4432>>>mesh.num_cell2267>>>mesh.num_point4746>>>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>>>mesh.read_cell_volumes('0/V')>>>mesh.read_cell_centres('0/C')Mesh inquiry:>>>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')FalseAuthorsXU XianghuaJan DreesTimothy-Edward-KendonYuyangL