The issue is that PolyhedronToFaces and PolyhedronOffsets can easily be splitted in partition but it is less obvious for the PolygonOffsets (or FaceOffsets) and PolygonConnectivity (or FaceConnectivity).
@Charles_Gueunet Yes it was a typo.
PolyhedronOffsets is an array that provide the position of a polyhedron start in the PolyhedronToFaces array as well as the number of face of a polyhedron.
It is sized following the number of unstructured cells meaning it stores useless information about non polyhedral cells (They have a zero size). Maybe it could be sized along a NumberOfPolyhedronCells to keep only relevant data and minimize disk space but then it will need a bit of computation on CPU side during write and load to build a mapping.
The behavor mimics the Connectivity + Offsets.
Yes the new field should be DataSet for transient data.
I don’t have a preference about the naming and it sounds good to use FaceOffsets/Connectivity like in the API.
I learned that the storing of polyhedron data is in the implementation phase. Maybe I am in time to suggest an additional space reducing format for polyhedra.
In our code we are storing the polyhedron topology information in two CSR array combinations.
The first array contains the offsets and the vertices of the faces, the second array stores the offsets and the reference to the faces in the first array.
In a simple example with two hexahedra it looks like this
The face connectivity would look like the
0 3 2 1 #Face 0
0 1 5 4 #Face 1
1 2 6 5 #Face 2
2 3 7 6 #Face 3
0 4 7 3 #Face 5
4 5 6 7 # Face 6
8 0 1 9 #Face 7
8 9 11 10 #Face 8
9 1 5 11 #Face 9
0 8 10 4 # Face 10
10 11 5 4 #Face 11
The offsets would be
0,4,8,12 …
The faces of the polyhedra would be
0 1 2 3 4 5 6 # Hexahedron 1
7 8 9 -1 10 11 # Hexadron 2
The offsets would be
0 6 12
A negative face index indicate a face in negative orientation. The advantage is that connecting faces are stored only once.
Is it possible to consider this type of storage (or something similar) in VTKHDF?
We converged to the design proposed by @MicK7 but AFAIK nobody currently implement it, so design suggestions/improvements are always welcome
IMO there is no limitation in your use case for VTKHDF, regarding polyhedron itself I’m not an expert on such cell type, but @Charles_Gueunet and/or @MicK7 may have some inputs.
@Dieke Thanks for your suggestion.
Your proposal make a lot of sense and cleverly optimize disk space.
In vtk case we start the numbering of faces at 0 for the polyhedron.
This mean that face 0 can have only one orientation according
to your scheme and the orientation is undefined.
This could be solved by managing a 1 offset after/before (un)signing the face during reading/writing.
For the writing, the issue is that we will need to compute the connected faces and sort them out before storing the data. This could be costly for huge simulation as vtk does not have the connection information already. Or it is well hidden…
@Charles_Gueunet any idea how vtk can handle shared or connected faces ?
Thanks for the quick answer and considering my idea. We are using a 1-based scheme so negative numbers are no problem. My mistake to translate in a 0-based world
I like the idea of using the sign to handle the orientation of the face. It make a clever use of the full range of value available. We do really need to clearly document that though, because for people inspecting files with an external tool, the shift between 0 and 1 numbering only for polyhedron may be confusing.
For the writing, the issue is that we will need to compute the connected faces and sort them out before storing the data. This could be costly for huge simulation as vtk does not have the connection information already. Or it is well hidden…
VTK does not store this information indeed. We can compute this information using a costly call to GetCellNeighbors.
I do not see this as a blocking point. We can use this syntax even if the VTK provided writer create duplicates faces at first. Simulation will still be able to benefits from lighter files as the most important part here is the reader. Ideally, the writer may have an advanced parameter to enable this optimization during write.
I am still enthusiastic about your prompt and positive reply. I expect that our (ParaView-) users would benefit a lot from a new unstructured grid format.
As in many finite volume codes we are storing data in the cell centers and the centers of the internal (those with a positive and negative number in my example) and the external(boundary) faces.
Thus the boundary data will need less storage than the data on the internal faces.
This could be reflecte by using something like face sections.
My idea would be something like :
/VTKHDF (Attribute Type UnstructuredGrid, Version )
/NumberOfCells
/NumberOfCellSides
/NumberOfPoints
/NumberOfFaces
/NumberOfFaceVertices
/NumberOfFaceSections
/Connectivity
/Faces
/Vertices
/Offsets
/Cells
/OneBasedFaceIDs
/Offsets
/FaceSection attribute name = "family1" attribute boundaryCondition = "bc1"
either /SectionRange Start,End
or /FaceList list of face indicators
/FaceSection attribute name = "family2"
either /SectionRange Start,End
or /FaceList list of face indicators attribute boundaryCondition = "bc1"
/Points
/CellData
/PointData
/FaceData
/FaceSectionData name="family1"
/FaceSectionData name="family2"
In this way, the all the data would be stored in a very compact way. Ideally, the /Cells /Faces and /FaceSection sections would be selectable similar to the “Extract Block” filter in ParaView.
If the 1 based faceIds are posing a problem, it would be possible to put the boundary faces in the beginning of the face list since their orientation would be always positive. A dummy face would do the trick as well.
Another idea to have a compact storage would be to add a “Parent” 2d array that for each face will store at first the cell owner and at second the cell neighbor. For the cell owner the face will be correctly oriented while for the neighbor it will be needed to flip it.
If a Face is a boundary it will not have a neighbor (thus value will be -1 for neighbor).
This is like a FaceToCell relationship reverse to the current CellToFace storage.
This is done by solvers like openfoam to store polyMesh.
I agree with Mickael that this is also a good and very disk space aware of storing the data. If we store the internal faces and the (external) boundaries in separate sections for each family we could also leave out the neighbor cell information for the boundaries. This would save even more space.
When designing the output file please make the field and the separate boundary families accessible by using a multi-block like approach. This would make ParaView even more usable for out team.
After some thinking, I agree with your proposal. We should have an option in the Writer to support a COMPACT format.
The compact format will store the Polyhedron face list in sorted order meaning
that first we will store the boundaries’ faces and then the internal faces.
The polyhedron can then used a signed face indexing to get the orientation of internal faces. As by design we have boundary faces we are guaranteed that signing the faces in the polyhedron indexing will not lead to issues with the “0” index.
For the /FaceSection or FaceSelection proposed by Dieke Hafermann, it should be nicely added later while taking care of creating corresponding structures in vtkUnstructuredGrid.
The compact storage + FaceSelection/FaceSection could lead to some benefit in the rendering process as we could harness the fact that the boundaries are sorted first to do something similar to the FastSurfaceMultiblockRepresentation at a lower level.
So the idea,
Add current proposal
Improve with Compact storage (option in Writer)
Add SurfaceSection/SurfaceSelection to vtkUnstructuredGrid
On a long term, rework the Surface Representation to get a speedup or create a new representation for polyhedron boundaries.