Mesh symmetries¶
Defining a symmetric mesh¶
Mesh symmetries can be used to speed up the computation. Four kind of symmetries are supported by Capytaine:
Single plane symmetry with respect to the \(x = 0\) or \(y = 0\) plane. This is the symmetry of most ship hulls and is thus implemented in almost all linear sea-keeping codes.
A mesh with such a symmetry is stored by Capytaine with the
ReflectionSymmetricMeshclass. It is defined with an other mesh of the half and a plane (and optionally a name like the usual meshes):half_mesh = cpt.load_mesh(...) mesh = cpt.ReflectionSymmetricMesh(half_mesh, plane="xOz", name="my full mesh")
When loading a file in a format that support defining a symmetry (gdf, hst, mar, pnl), the
ReflectionSymmetricMeshis returned automatically byload_mesh.Two plane symmetries with respect to both the \(x = 0\) and \(y = 0\) plane.
Two vertical plane symmetries can be nested to be used by Capytaine (assuming that the two planes are orthogonal):
quarter_mesh = cpt.load_mesh(...) half_mesh = cpt.ReflectionSymmetricMesh(half_mesh, plane="yOz") mesh = cpt.ReflectionSymmetricMesh(half_mesh, plane="x0z")
Rotation symmetry of a shape repeated by rotation around the \(z\)-axis any number of times.
It can be defined either from the repetition of an existing mesh:
wedge_mesh = cpt.load_mesh(...) mesh = cpt.RotationSymmetricMesh(wedge=wedge_mesh, n=4)
or for an axysymmetric geometry from a list of points along a “meridian” of the shape:
meridian_points = np.array([(np.sqrt(1-z**2), 0.0, z) for z in np.linspace(-1.0, 1.0, 10)]) sphere = cpt.RotationSymmetricMesh.from_profile_points(meridian_points, n=10)
Manipulating a symmetric mesh¶
All the methods defined in the Meshes section can be used on the ReflectionSymmetricMesh and RotationSymmetricMesh.
It the resulting object is not symmetric anymore, the symmetry is lost and a bar Mesh of the whole surface is returned:
mesh = cpt.ReflectionSymmetricMesh(..., plane="xOz")
x_translated_mesh = mesh.translated_x(1.0)
print(x_translated_mesh.__class__) # ReflectionSymmetricMesh
y_translated_mesh = mesh.translated_y(1.0)
print(y_translated_mesh.__class__) # Mesh
In particular, joining meshes with + or join_meshes conserves the symmetry assuming all meshes have the same symmetry.
Clipping the part of the mesh above the free surface with immersed_part should always conserve the symmetry.
Using a symmetric mesh to define a floating body¶
The symmetric mesh can be used to setup a floating body:
mesh = cpt.ReflectionSymmetricMesh(..., plane="xOz")
lid_mesh = cpt.ReflectionSymmetricMesh(..., plane="xOz")
body = cpt.FloatingBody(
mesh=mesh,
lid_mesh=lid_mesh,
dofs=cpt.rigid_body_dofs()
)
Warning
When using a lid mesh for irregular frequencies removal, the lid mesh and
the hull mesh should have the same symmetry, otherwise the symmetry will be
ignored when solving the BEM problem.
The methods generate_lid and extract_lid preserve the symmetry,
although the generated lid might not be optimal when the stub of the
symmetric mesh is small.
Note
For all the symmetries described above, the mesh (and the lid mesh) needs to be symmetric, but the full problem might not be. In other word, even when working with a symmetric mesh, it is possible to consider incoming waves from any directions, or generalized degrees of freedom that are not symmetric.
Expected performance gain¶
Asymptotically for large problems:
Symmetry |
Resolution time |
RAM usage |
1 plane symmetry 2 plane symmetries n rotation symmetry |
1/2 1/4 1/n |
1/2 1/4 1/n |
Note that the theoretical performance gain described above might not be reached in practice, especially for smaller problems. For instance, the threading parallelisation is currently less efficient on highly symmetric meshes.