Skip to content

Feature request: interface for fvMesh #606

@RamogninoF

Description

@RamogninoF

It would be convenient to integrate some interface for accessing the mesh (perhaps similar to the fvMesh class in OpenFOAM?).

This functionality should be relatively straightforward, since all the core features for parsing are already present, it is just a matter of developing a wrapper to simplify the user interface.

Here is an example of how I use foamlib to parse the mesh when it is located in time/polyMesh.

class PolyMesh(object):
    """
    Class to represent a polygonal mesh with vertices and faces.
    """
    @classmethod
    def from_foam_case(cls, time_folder:str) -> 'PolyMesh':
        poly_mesh_path = Path(time_folder) / "polyMesh"
        if not poly_mesh_path.exists():
            raise FileNotFoundError(f"polyMesh directory not found in {time_folder}")

        # Load points
        points_file = FoamFile(str(poly_mesh_path / "points"))
        points = points_file[None]

        # Load faces
        faces_file = FoamFile(str(poly_mesh_path / "faces"))
        faces = faces_file[None]
        # Check if compactList (binary)
        if isinstance(faces, tuple) and len(faces) == 2:
            # Convert to list of np.ndarrays
            vec1, vec2 = faces
            faces = np.fromiter((vec2[start:stop] for start, stop in zip (vec1[:-1], vec1[1:])), dtype=np.ndarray, count=vec1.size-1)
        
        # Load owners
        owners_file = FoamFile(str(poly_mesh_path / "owner"))
        owners = owners_file[None]

        # Load neighbours
        neighbours_file = FoamFile(str(poly_mesh_path / "neighbour"))
        neighbours = neighbours_file[None]

        # Load boundary
        boundary_file = FoamFile(str(poly_mesh_path / "boundary"))
        boundary = {b:data for b,data in boundary_file[None]}

        return cls(points, faces, owners, neighbours, boundary)

    def __init__(self, points:np.ndarray, faces:np.ndarray[np.ndarray], owners:np.ndarray, neighbours:np.ndarray, boundary:dict[str, dict]) -> None:
        # TODO: Validate inputs
        self.vertices = points.copy()
        self.faces = faces.copy()
        self.owners = owners.copy()
        self.neighbours = neighbours.copy()
        self.boundary = cp.deepcopy(boundary)

This is a rudimentary proof of concept, it still requires some features:

  • The mesh can be either located in the constant or time folder. If in constant, accessing to the mesh in time should link to the one in constant
  • Moving meshes store the mesh in constant and only save the points in the time folder. This should be correctly handled
  • Meshed with topological changes store the mesh in the time folder, but write all the mesh data (points, faces, boundary, etc...) only when the mesh changes topology, while all the following times store only the points (see above). This should be handled properly (lookup last time where everything was saved, but use the points of this folder)
  • Multi-region meshes

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions