364 lines
11 KiB
Python
364 lines
11 KiB
Python
# SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Final, overload
|
|
|
|
from Base.Metadata import constmethod, export
|
|
from Base.Vector import Vector
|
|
from Base.Placement import Placement
|
|
from App.ComplexGeoData import ComplexGeoData
|
|
from Part.App.TopoShape import TopoShape
|
|
from Part.App.TopoShapeFace import TopoShapeFace
|
|
from Part.App.TopoShapeEdge import TopoShapeEdge
|
|
from Part.App.TopoShapeSolid import TopoShapeSolid
|
|
from Part.App.TopoShapeVertex import TopoShapeVertex
|
|
|
|
@export(
|
|
Include="Mod/Fem/App/FemMesh.h",
|
|
Namespace="Fem",
|
|
FatherInclude="App/ComplexGeoDataPy.h",
|
|
FatherNamespace="Data",
|
|
Constructor=True,
|
|
)
|
|
class FemMesh(ComplexGeoData):
|
|
"""
|
|
FemMesh class
|
|
|
|
Author: Juergen Riegel (Juergen.Riegel@web.de)
|
|
License: LGPL-2.1-or-later
|
|
"""
|
|
|
|
def setShape(self, shape: TopoShape, /) -> None:
|
|
"""Set the Part shape to mesh"""
|
|
...
|
|
|
|
def compute(self) -> None:
|
|
"""Update the internal mesh structure"""
|
|
...
|
|
|
|
def addHypothesis(self, hypothesis: object, shape: TopoShape, /) -> None:
|
|
"""Add hypothesis"""
|
|
...
|
|
|
|
def setStandardHypotheses(self) -> None:
|
|
"""Set some standard hypotheses for the whole shape"""
|
|
...
|
|
|
|
def addNode(self, x: float, y: float, z: float, elem_id: int | None = None, /) -> int:
|
|
"""Add a node by setting (x,y,z)."""
|
|
...
|
|
|
|
@overload
|
|
def addEdge(self, n1: int, n2: int, /) -> int: ...
|
|
|
|
@overload
|
|
def addEdge(self, nodes: list[int], elem_id: int | None = None, /) -> int: ...
|
|
|
|
def addEdge(self, *args) -> int:
|
|
"""Add an edge by setting two node indices."""
|
|
...
|
|
|
|
def addEdgeList(self, nodes: list[int], np: list[int], /) -> list[int]:
|
|
"""Add list of edges by list of node indices and list of nodes per edge."""
|
|
...
|
|
|
|
@overload
|
|
def addFace(self, n1: int, n2: int, n3: int, /) -> int: ...
|
|
|
|
@overload
|
|
def addFace(self, nodes: list[int], elem_id: int | None = None, /) -> int: ...
|
|
|
|
def addFace(self) -> Any:
|
|
"""Add a face by setting three node indices."""
|
|
...
|
|
|
|
def addFaceList(self, nodes: list[int], np: list[int], /) -> list[int]:
|
|
"""Add list of faces by list of node indices and list of nodes per face."""
|
|
...
|
|
|
|
def addQuad(self, n1: int, n2: int, n3: int, n4: int, /) -> int:
|
|
"""Add a quad by setting four node indices."""
|
|
...
|
|
|
|
@overload
|
|
def addVolume(self, n1: int, n2: int, n3: int, n4: int, /) -> int: ...
|
|
|
|
@overload
|
|
def addVolume(self, nodes: list[int], elem_id: int | None = None, /) -> int: ...
|
|
|
|
def addVolume(self, *args) -> int:
|
|
"""Add a volume by setting an arbitrary number of node indices."""
|
|
...
|
|
|
|
def addVolumeList(self, nodes: list[int], np: list[int], /) -> list[int]:
|
|
"""Add list of volumes by list of node indices and list of nodes per volume."""
|
|
...
|
|
|
|
def read(self, file_name: str, /) -> None:
|
|
"""
|
|
Read in a various FEM mesh file formats.
|
|
|
|
|
|
Supported formats: DAT, INP, MED, STL, UNV, VTK, Z88
|
|
"""
|
|
...
|
|
|
|
@constmethod
|
|
def write(self, file_name: str, /) -> None:
|
|
"""
|
|
Write out various FEM mesh file formats.
|
|
|
|
Supported formats: BDF, DAT, INP, MED, STL, UNV, VTK, Z88
|
|
"""
|
|
...
|
|
|
|
@constmethod
|
|
def writeABAQUS(
|
|
self,
|
|
fileName: str,
|
|
elemParam: int,
|
|
groupParam: bool,
|
|
volVariant: str = "standard",
|
|
faceVariant: str = "shell",
|
|
edgeVariant: str = "beam") -> None:
|
|
"""
|
|
Write out as ABAQUS inp.
|
|
|
|
elemParam:
|
|
0: All elements
|
|
1: Highest elements only
|
|
2: FEM elements only (only edges not belonging to faces and faces not belonging to volumes)
|
|
|
|
groupParam:
|
|
True: Write group data
|
|
False: Do not write group data
|
|
|
|
volVariant: Volume elements
|
|
"standard": Tetra4 -> C3D4, Penta6 -> C3D6, Hexa8 -> C3D8, Tetra10 -> C3D10, Penta15 -> C3D15, Hexa20 -> C3D20
|
|
"reduced": Hexa8 -> C3D8R, Hexa20 -> C3D20R
|
|
"incompatible": Hexa8 -> C3D8I
|
|
"modified": Tetra10 -> C3D10T
|
|
"fluid": Tetra4 -> F3D4, Penta6 -> F3D6, Hexa8 -> F3D8
|
|
|
|
faceVariant: Face elements
|
|
"shell": Tria3 -> S3, Quad4 -> S4, Tria6 -> S6, Quad8 -> S8
|
|
"shell reduced": Tria3 -> S3, Quad4 -> S4R, Tria6 -> S6, Quad8 -> S8R
|
|
"membrane": Tria3 -> M3D3, Quad4 -> M3D4, Tria6 -> M3D6, Quad8 -> M3D8
|
|
"membrane reduced": Tria3 -> M3D3, Quad4 -> M3D4R, Tria6 -> M3D6, Quad8 -> M3D8R
|
|
"stress": Tria3 -> CPS3, Quad4 -> CPS4, Tria6 -> CPS6, Quad8 -> CPS8
|
|
"stress reduced": Tria3 -> CPS3, Quad4 -> CPS4R, Tria6 -> CPS6, Quad8 -> CPS8R
|
|
"strain": Tria3 -> CPE3, Quad4 -> CPE4, Tria6 -> CPE6, Quad8 -> CPE8
|
|
"strain reduced": Tria3 -> CPE3, Quad4 -> CPE4R, Tria6 -> CPE6, Quad8 -> CPE8R
|
|
"axisymmetric": Tria3 -> CAX3, Quad4 -> CAX4, Tria6 -> CAX6, Quad8 -> CAX8
|
|
"axisymmetric reduced": Tria3 -> CAX3, Quad4 -> CAX4R, Tria6 -> CAX6, Quad8 -> CAX8R
|
|
|
|
edgeVariant: Edge elements
|
|
"beam": Seg2 -> B31, Seg3 -> B32
|
|
"beam reduced": Seg2 -> B31R, Seg3 -> B32R
|
|
"truss": Seg2 -> T3D2, eg3 -> T3D3
|
|
"network": Seg3 -> D
|
|
|
|
Elements are selected according to CalculiX availability.
|
|
For example if volume variant "modified" is selected, Tetra10 mesh
|
|
elements are assigned to C3D10T and remain elements uses "standard".
|
|
Axisymmetric, plane strain and plane stress elements expect nodes in the plane z=0.
|
|
"""
|
|
...
|
|
|
|
def setTransform(self, placement: Placement, /) -> None:
|
|
"""Use a Placement object to perform a translation or rotation"""
|
|
...
|
|
|
|
@constmethod
|
|
def copy(self) -> FemMesh:
|
|
"""Make a copy of this FEM mesh."""
|
|
...
|
|
|
|
@constmethod
|
|
def getFacesByFace(self, face: TopoShapeFace, /) -> list[int]:
|
|
"""Return a list of face IDs which belong to a TopoFace"""
|
|
...
|
|
|
|
@constmethod
|
|
def getEdgesByEdge(self, edge: TopoShapeEdge, /) -> list[int]:
|
|
"""Return a list of edge IDs which belong to a TopoEdge"""
|
|
...
|
|
|
|
@constmethod
|
|
def getVolumesByFace(self, face: TopoShapeFace, /) -> list[tuple[int, int]]:
|
|
"""Return a list of tuples of volume IDs and face IDs which belong to a TopoFace"""
|
|
...
|
|
|
|
@constmethod
|
|
def getccxVolumesByFace(self, face: TopoShapeFace, /) -> list[tuple[int, int]]:
|
|
"""Return a list of tuples of volume IDs and ccx face numbers which belong to a TopoFace"""
|
|
...
|
|
|
|
@constmethod
|
|
def getNodeById(self, node_id: int, /) -> Vector:
|
|
"""Get the node position vector by a Node-ID"""
|
|
...
|
|
|
|
@constmethod
|
|
def getNodesBySolid(self, shape: TopoShapeSolid, /) -> list[int]:
|
|
"""Return a list of node IDs which belong to a TopoSolid"""
|
|
...
|
|
|
|
@constmethod
|
|
def getNodesByFace(self, face: TopoShapeFace, /) -> list[int]:
|
|
"""Return a list of node IDs which belong to a TopoFace"""
|
|
...
|
|
|
|
@constmethod
|
|
def getNodesByEdge(self, edge: TopoShapeEdge, /) -> list[int]:
|
|
"""Return a list of node IDs which belong to a TopoEdge"""
|
|
...
|
|
|
|
@constmethod
|
|
def getNodesByVertex(self, vertex: TopoShapeVertex, /) -> list[int]:
|
|
"""Return a list of node IDs which belong to a TopoVertex"""
|
|
...
|
|
|
|
@constmethod
|
|
def getElementNodes(self, elem_id: int, /) -> tuple[int, ...]:
|
|
"""Return a tuple of node IDs to a given element ID"""
|
|
...
|
|
|
|
@constmethod
|
|
def getNodeElements(self, elem_id: int, elem_type: str = "All", /) -> tuple[int, ...]:
|
|
"""Return a tuple of specific element IDs associated to a given node ID"""
|
|
...
|
|
|
|
@constmethod
|
|
def getGroupName(self, elem_id: int, /) -> str:
|
|
"""Return a string of group name to a given group ID"""
|
|
...
|
|
|
|
@constmethod
|
|
def getGroupElementType(self, elem_id: int, /) -> str:
|
|
"""Return a string of group element type to a given group ID"""
|
|
...
|
|
|
|
@constmethod
|
|
def getGroupElements(self, elem_id: int, /) -> tuple[int, ...]:
|
|
"""Return a tuple of ElementIDs to a given group ID"""
|
|
...
|
|
|
|
@constmethod
|
|
def addGroup(self, name: str, group_type: str, group_id: int = -1, /) -> None:
|
|
"""
|
|
Add a group to mesh with specific name and type
|
|
|
|
name: string
|
|
group_type: "All", "Node", "Edge", "Face", "Volume", "0DElement", "Ball"
|
|
group_id: int
|
|
Optional group_id is used to force specific id for group, but does
|
|
not work, yet.
|
|
"""
|
|
...
|
|
|
|
@constmethod
|
|
def addGroupElements(self, group_id: int, elements: list[int], /) -> None:
|
|
"""
|
|
Add a tuple of ElementIDs to a given group ID
|
|
|
|
group_id: int
|
|
elements: list of int
|
|
Notice that the elements have to be in the mesh.
|
|
"""
|
|
...
|
|
|
|
@constmethod
|
|
def removeGroup(self, group_id: int, /) -> bool:
|
|
"""
|
|
Remove a group with a given group ID
|
|
removeGroup(groupid)
|
|
groupid: int
|
|
Returns boolean."""
|
|
...
|
|
|
|
@constmethod
|
|
def renameGroup(self) -> Any:
|
|
"""Rename a group with a given group ID
|
|
renameGroup(id, name)
|
|
groupid: int
|
|
name: string"""
|
|
...
|
|
|
|
@constmethod
|
|
def getElementType(self, elem_id: int, /) -> str:
|
|
"""Return the element type of a given ID"""
|
|
...
|
|
|
|
@constmethod
|
|
def getIdByElementType(self, elem_type: str, /) -> tuple[int, ...]:
|
|
"""Return a tuple of IDs to a given element type"""
|
|
...
|
|
|
|
Nodes: Final[dict]
|
|
"""Dictionary of Nodes by ID (int ID:Vector())"""
|
|
|
|
NodeCount: Final[int]
|
|
"""Number of nodes in the Mesh."""
|
|
|
|
Edges: Final[tuple]
|
|
"""Tuple of edge IDs"""
|
|
|
|
EdgesOnly: Final[tuple]
|
|
"""Tuple of edge IDs which does not belong to any face (and thus not belong to any volume too)"""
|
|
|
|
EdgeCount: Final[int]
|
|
"""Number of edges in the Mesh."""
|
|
|
|
Faces: Final[tuple]
|
|
"""Tuple of face IDs"""
|
|
|
|
FacesOnly: Final[tuple]
|
|
"""Tuple of face IDs which does not belong to any volume"""
|
|
|
|
FaceCount: Final[int]
|
|
"""Number of Faces in the Mesh."""
|
|
|
|
TriangleCount: Final[int]
|
|
"""Number of Triangles in the Mesh."""
|
|
|
|
QuadrangleCount: Final[int]
|
|
"""Number of Quadrangles in the Mesh."""
|
|
|
|
PolygonCount: Final[int]
|
|
"""Number of Quadrangles in the Mesh."""
|
|
|
|
Volumes: Final[tuple]
|
|
"""Tuple of volume IDs"""
|
|
|
|
VolumeCount: Final[int]
|
|
"""Number of Volumes in the Mesh."""
|
|
|
|
TetraCount: Final[int]
|
|
"""Number of Tetras in the Mesh."""
|
|
|
|
HexaCount: Final[int]
|
|
"""Number of Hexas in the Mesh."""
|
|
|
|
PyramidCount: Final[int]
|
|
"""Number of Pyramids in the Mesh."""
|
|
|
|
PrismCount: Final[int]
|
|
"""Number of Prisms in the Mesh."""
|
|
|
|
PolyhedronCount: Final[int]
|
|
"""Number of Polyhedrons in the Mesh."""
|
|
|
|
SubMeshCount: Final[int]
|
|
"""Number of SubMeshs in the Mesh."""
|
|
|
|
GroupCount: Final[int]
|
|
"""Number of Groups in the Mesh."""
|
|
|
|
Groups: Final[tuple]
|
|
"""Tuple of Group IDs."""
|
|
|
|
Volume: Final[Any]
|
|
"""Volume of the mesh."""
|