Spaces:
Sleeping
Sleeping
| from typing import Union | |
| from enum import Enum | |
| import warp as wp | |
| import warp.codegen | |
| import warp.context | |
| from warp.fem.geometry import ( | |
| Element, | |
| Geometry, | |
| GeometryPartition, | |
| WholeGeometryPartition, | |
| ) | |
| GeometryOrPartition = Union[Geometry, GeometryPartition] | |
| class GeometryDomain: | |
| """Interface class for domains, i.e. (partial) views of elements in a Geometry""" | |
| class ElementKind(Enum): | |
| """Possible kinds of elements contained in a domain""" | |
| CELL = 0 | |
| SIDE = 1 | |
| def __init__(self, geometry: GeometryOrPartition): | |
| if isinstance(geometry, GeometryPartition): | |
| self.geometry_partition = geometry | |
| else: | |
| self.geometry_partition = WholeGeometryPartition(geometry) | |
| self.geometry = self.geometry_partition.geometry | |
| def name(self) -> str: | |
| return f"{self.geometry_partition.name}_{self.__class__.__name__}" | |
| def __str__(self) -> str: | |
| return self.name | |
| def __eq__(self, other) -> bool: | |
| return self.__class__ == other.__class__ and self.geometry_partition == other.geometry_partition | |
| def element_kind(self) -> ElementKind: | |
| """Kind of elements that this domain contains (cells or sides)""" | |
| raise NotImplementedError | |
| def dimension(self) -> int: | |
| """Dimension of the elements of the domain""" | |
| raise NotImplementedError | |
| def element_count(self) -> int: | |
| """Number of elements in the domain""" | |
| raise NotImplementedError | |
| def geometry_element_count(self) -> int: | |
| """Number of elements in the underlying geometry""" | |
| return self.geometry.cell_count() | |
| def reference_element(self) -> Element: | |
| """Protypical element""" | |
| raise NotImplementedError | |
| def element_index_arg_value(self, device: warp.context.Devicelike) -> warp.codegen.StructInstance: | |
| """Value of the argument to be passed to device functions""" | |
| raise NotImplementedError | |
| def element_arg_value(self, device: warp.context.Devicelike) -> warp.codegen.StructInstance: | |
| """Value of the argument to be passed to device functions""" | |
| raise NotImplementedError | |
| ElementIndexArg: warp.codegen.Struct | |
| """Structure containing arguments to be passed to device functions computing element indices""" | |
| element_index: wp.Function | |
| """Device function for retrieving an ElementIndex from a linearized index""" | |
| ElementArg: warp.codegen.Struct | |
| """Structure containing arguments to be passed to device functions computing element geometry""" | |
| element_measure: wp.Function | |
| """Device function returning the measure determinant (e.g. volume, area) at a given point""" | |
| element_measure_ratio: wp.Function | |
| """Device function returning the ratio of the measure of a side to that of its neighbour cells""" | |
| element_position: wp.Function | |
| """Device function returning the element position at a sample point""" | |
| element_deformation_gradient: wp.Function | |
| """Device function returning the gradient of the position with respect to the element's reference space""" | |
| element_normal: wp.Function | |
| """Device function returning the element normal at a sample point""" | |
| element_lookup: wp.Function | |
| """Device function returning the sample point corresponding to a world position""" | |
| class Cells(GeometryDomain): | |
| """A Domain containing all cells of the geometry or geometry partition""" | |
| def __init__(self, geometry: GeometryOrPartition): | |
| super().__init__(geometry) | |
| def element_kind(self) -> GeometryDomain.ElementKind: | |
| return GeometryDomain.ElementKind.CELL | |
| def dimension(self) -> int: | |
| return self.geometry.dimension | |
| def reference_element(self) -> Element: | |
| return self.geometry.reference_cell() | |
| def element_count(self) -> int: | |
| return self.geometry_partition.cell_count() | |
| def geometry_element_count(self) -> int: | |
| return self.geometry.cell_count() | |
| def ElementIndexArg(self) -> warp.codegen.Struct: | |
| return self.geometry_partition.CellArg | |
| def element_index_arg_value(self, device: warp.context.Devicelike) -> warp.codegen.StructInstance: | |
| return self.geometry_partition.cell_arg_value(device) | |
| def element_index(self) -> wp.Function: | |
| return self.geometry_partition.cell_index | |
| def element_arg_value(self, device: warp.context.Devicelike) -> warp.codegen.StructInstance: | |
| return self.geometry.cell_arg_value(device) | |
| def ElementArg(self) -> warp.codegen.Struct: | |
| return self.geometry.CellArg | |
| def element_position(self) -> wp.Function: | |
| return self.geometry.cell_position | |
| def element_deformation_gradient(self) -> wp.Function: | |
| return self.geometry.cell_deformation_gradient | |
| def element_measure(self) -> wp.Function: | |
| return self.geometry.cell_measure | |
| def element_measure_ratio(self) -> wp.Function: | |
| return self.geometry.cell_measure_ratio | |
| def eval_normal(self) -> wp.Function: | |
| return self.geometry.cell_normal | |
| def element_lookup(self) -> wp.Function: | |
| return self.geometry.cell_lookup | |
| class Sides(GeometryDomain): | |
| """A Domain containing all (interior and boundary) sides of the geometry or geometry partition""" | |
| def __init__(self, geometry: GeometryOrPartition): | |
| self.geometry = geometry | |
| super().__init__(geometry) | |
| def element_kind(self) -> GeometryDomain.ElementKind: | |
| return GeometryDomain.ElementKind.SIDE | |
| def dimension(self) -> int: | |
| return self.geometry.dimension - 1 | |
| def reference_element(self) -> Element: | |
| return self.geometry.reference_side() | |
| def element_count(self) -> int: | |
| return self.geometry_partition.side_count() | |
| def geometry_element_count(self) -> int: | |
| return self.geometry.side_count() | |
| def ElementIndexArg(self) -> warp.codegen.Struct: | |
| return self.geometry_partition.SideArg | |
| def element_index_arg_value(self, device: warp.context.Devicelike) -> warp.codegen.StructInstance: | |
| return self.geometry_partition.side_arg_value(device) | |
| def element_index(self) -> wp.Function: | |
| return self.geometry_partition.side_index | |
| def ElementArg(self) -> warp.codegen.Struct: | |
| return self.geometry.SideArg | |
| def element_arg_value(self, device: warp.context.Devicelike) -> warp.codegen.StructInstance: | |
| return self.geometry.side_arg_value(device) | |
| def element_position(self) -> wp.Function: | |
| return self.geometry.side_position | |
| def element_deformation_gradient(self) -> wp.Function: | |
| return self.geometry.side_deformation_gradient | |
| def element_measure(self) -> wp.Function: | |
| return self.geometry.side_measure | |
| def element_measure_ratio(self) -> wp.Function: | |
| return self.geometry.side_measure_ratio | |
| def eval_normal(self) -> wp.Function: | |
| return self.geometry.side_normal | |
| class BoundarySides(Sides): | |
| """A Domain containing boundary sides of the geometry or geometry partition""" | |
| def __init__(self, geometry: GeometryOrPartition): | |
| super().__init__(geometry) | |
| def element_count(self) -> int: | |
| return self.geometry_partition.boundary_side_count() | |
| def geometry_element_count(self) -> int: | |
| return self.geometry.boundary_side_count() | |
| def element_index(self) -> wp.Function: | |
| return self.geometry_partition.boundary_side_index | |
| class FrontierSides(Sides): | |
| """A Domain containing frontier sides of the geometry partition (sides shared with at least another partition)""" | |
| def __init__(self, geometry: GeometryOrPartition): | |
| super().__init__(geometry) | |
| def element_count(self) -> int: | |
| return self.geometry_partition.frontier_side_count() | |
| def geometry_element_count(self) -> int: | |
| raise RuntimeError("Frontier sides not defined at the geometry level") | |
| def element_index(self) -> wp.Function: | |
| return self.geometry_partition.frontier_side_index | |