Skip to content
Snippets Groups Projects
mesh_data.py 3.93 KiB
Newer Older
from abc import ABC, abstractmethod
from collections.abc import Hashable, Sequence
from typing import ClassVar
import numpy as np
import meshmode.mesh.generation as mgen
from meshmode.mesh import Mesh
from meshmode.mesh.io import read_gmsh
class MeshBuilder(ABC):
    resolutions: ClassVar[Sequence[Hashable]]
    ambient_dim: ClassVar[int]
    @abstractmethod
    def get_mesh(
             self,
             resolution: Hashable,
             mesh_order: int | None = None
         ) -> Mesh:
        ...
class _GmshMeshBuilder(MeshBuilder):
    resolutions: ClassVar[Sequence[Hashable]] = [None]
    def __init__(self, filename: str) -> None:
        self._mesh_fn = filename

    def get_mesh(self, resolution, mesh_order=None) -> Mesh:
        assert resolution is None
        assert mesh_order is None
        return read_gmsh(self._mesh_fn, force_ambient_dim=self.ambient_dim)


class GmshMeshBuilder2D(_GmshMeshBuilder):
    ambient_dim = 2

class GmshMeshBuilder3D(_GmshMeshBuilder):
    ambient_dim = 3


class Curve2DMeshBuilder(MeshBuilder):
    ambient_dim = 2
    resolutions: ClassVar[Sequence[Hashable]] = [16, 32, 64, 128]
    def get_mesh(self, resolution, mesh_order=None):
        if mesh_order is None:
            mesh_order = 4
        return mgen.make_curve_mesh(
                self.curve_fn,      # pylint: disable=no-member
                np.linspace(0.0, 1.0, resolution + 1),
                mesh_order)


class EllipseMeshBuilder(Curve2DMeshBuilder):
    def __init__(self, radius=3.1, aspect_ratio=2):
        self.radius = radius
        self.aspect_ratio = aspect_ratio

    @property
    def curve_fn(self):
        return lambda t: self.radius * mgen.ellipse(self.aspect_ratio, t)


class StarfishMeshBuilder(Curve2DMeshBuilder):
    narms = 5
    amplitude = 0.25

    @property
    def curve_fn(self):
        return mgen.NArmedStarfish(self.narms, self.amplitude)


class SphereMeshBuilder(MeshBuilder):
    ambient_dim = 3

    resolutions: ClassVar[Sequence[Hashable]] = [0, 1, 2, 3]
    radius: float

    def __init__(self, radius=1):
        self.radius = radius

    def get_mesh(self, resolution, mesh_order=4):
        from meshmode.mesh.generation import generate_sphere
        return generate_sphere(self.radius, order=mesh_order,
                uniform_refinement_rounds=resolution)


class SpheroidMeshBuilder(MeshBuilder):
    ambient_dim = 3

    resolutions: ClassVar[Sequence[Hashable]] = [0, 1, 2, 3]
    radius: float
    aspect_ratio: float

    def __init__(self, radius=1, aspect_ratio=2):
        self.radius = radius
        self.aspect_ratio = aspect_ratio
    def get_mesh(self, resolution, mesh_order=4):
        from meshmode.mesh.generation import generate_sphere
        mesh = generate_sphere(self.radius, order=mesh_order,
                uniform_refinement_rounds=resolution)

        from meshmode.mesh.processing import affine_map
        return affine_map(mesh, A=np.diag([1.0, 1.0, self.aspect_ratio]))
class _BoxMeshBuilderBase(MeshBuilder):
    resolutions: ClassVar[Sequence[Hashable]] = [4, 8, 16]
    mesh_order = 1

    a = (-0.5, -0.5, -0.5)
    b = (+0.5, +0.5, +0.5)

    def get_mesh(self, resolution, mesh_order=4):
        if not isinstance(resolution, list | tuple):
            resolution = (resolution,) * self.ambient_dim

        return mgen.generate_regular_rect_mesh(
                a=self.a, b=self.b,
class BoxMeshBuilder1D(_BoxMeshBuilderBase):
    ambient_dim = 1


class BoxMeshBuilder2D(_BoxMeshBuilderBase):
    ambient_dim = 2


class BoxMeshBuilder3D(_BoxMeshBuilderBase):
    ambient_dim = 2


class WarpedRectMeshBuilder(MeshBuilder):
    resolutions: ClassVar[Sequence[Hashable]] = [4, 6, 8]

    def __init__(self, dim):
        self.dim = dim

    def get_mesh(self, resolution, mesh_order=4):
        return mgen.generate_warped_rect_mesh(
                dim=self.dim, order=mesh_order, nelements_side=resolution)