Floating body¶
As described in the Tutorial, a floating body is defined as a mesh with degrees of freedom and optionally a lid mesh and other properties, such as a mass and a center of mass.
Initialization¶
The floating body is set up by initializing the
FloatingBody class:
body = cpt.FloatingBody(mesh=mesh, dofs={})
The above example creates a new body without degrees of freedom.
Mesh¶
The mesh can be a Mesh object, or any of
the variants defined in Capytaine, such as a
ReflectionSymmetricMesh.
Lid mesh¶
For irregular frequencies removal, a second mesh can be provided when defining the body. It is meant to be a mesh of a lid of the part of the free surface that is inside the body. The lid can either on the free surface or slightly below. This mesh is ignored for many computations (such as hydrostatics) and is only used when solving a BEM problem.
It is set as in the following example:
body = cpt.FloatingBody(mesh=mesh, lid_mesh=lid_mesh)
where lid_mesh is a mesh object which can loaded in the same way as the
main mesh (see Mesh initialization) or using the specific methods of
Extracting or generating a lid.
Once a lid mesh has been defined, it is automatically used for irregular
frequencies removal without any other action from the user.
The lid does not need neither to cover the whole interior free surface, nor
to be connected with the hull mesh. (The lid automatically generated by
generate_lid() typically does not.)
Nonetheless, the more interior free surface is covered, the more efficiently
the irregular frequencies will be removed.
For irregular frequencies removal, the lid is expected to have normals going down (towards the fluid, through the body). If the lid appears to be horizontal with normal going up, Capytaine will switch the direction of its normal vectors.
When working with symmetric meshes, the mesh and the lid_mesh should
have the exact same symmetry. If so, the symmetry is used for the resolution.
Otherwise, the symmetry is discarded and a full resolution is done.
Dofs¶
Degrees of freedoms are stored in a Python dictionary associating the name of each dof to the description of the corresponding motion or deformation.
For rigid bodies, the motion is encoded in an ad-hoc Python object of class
TranslationDof or RotationDof.
It is recommended to initialize them in the following way:
body = cpt.FloatingBody(
mesh=mesh,
dofs=cpt.rigid_body_dofs(rotation_center=(0, 0, -1)),
)
If no rotation_center is provided, \((0, 0, 0)\) is used as a default.
Note that all coordinates are in the global reference frame, so \((0, 0,
0)\) is an arbitrary point on the free surface.
The standard names used to refer to the rigid body dofs are:
print(body.dofs.keys())
# dict_keys(['Surge', 'Sway', 'Heave', 'Roll', 'Pitch', 'Yaw'])
If only some dofs are of interest, you can use the following syntax:
body = cpt.FloatingBody(
mesh=mesh,
dofs=cpt.rigid_body_dofs(only=["Heave"], rotation_center=(0, 0, -1))
)
print(body.dofs.keys())
# dict_keys(['Heave'])
Generalized degrees of freedom can be defined with a
CustomDof object, by giving a function
computing the motion of a point on body hull:
body = cpt.FloatingBody(
mesh=mesh,
dofs={
"heave-like": cpt.CustomDof(lambda p: [0, 0, 1]),
"x-shear": cpt.CustomDof(lambda p: [np.cos(np.pi*p[2]/2), 0, 0]),
},
)
The CustomDof object allows to optionally define the derivative of the
motion field. This magnitude is used for hydrostatic stiffness, forward-speed
(m-term) and second-order forces. It is not useful for first-order
radiation-diffraction problems without forward-speed. The derivative is a
Jacobian matrix at each point, such that the first column is the derivative
with respect to \(x\) of the motion, the second column is the derivative
with respect to \(y\) and the third column is the derivative with respect
to \(z\):
body = cpt.FloatingBody(
mesh=mesh,
dofs={
"heave-like": cpt.CustomDof(
motion=lambda p: [0, 0, 1],
gradient_of_motion=lambda p: np.zeros((3, 3)),
),
"x-shear": cpt.CustomDof(
motion=lambda p: [np.cos(np.pi*p[2]/2), 0, 0],
gradient_of_motion=lambda p: [[0, 0, -np.pi/2*np.sin(np.pi*p[2]/2)], [0, 0, 0], [0, 0, 0]],
)
},
)
Alternatively, the legacy way of defining generalized degrees of freedom as a
Numpy array of shape (nb_faces, 3) is still supported in Capytaine v3:
body = cpt.FloatingBody(
mesh=mesh,
dofs={
"heave-like": np.array([(0, 0, 1) for x, y, z in mesh.faces_centers]),
"x-shear": np.array([(np.cos(np.pi*z/2), 0, 0) for x, y, z in mesh.faces_centers])
},
)
Defining a rigid-body-dof as a generalized dof (as in the example above for heave) does not make a difference for first-order hydrodynamics without forward speed. It makes a difference for the hydrostatic stiffness, when the generalized dofs are using a approximate formula, whereas exact values can be returned for rigid body dofs.
Mixing rigid-body dofs and generalized dofs can be done as follows:
body = cpt.FloatingBody(
mesh=mesh,
dofs={
**cpt.rigid_body_dofs(rotation_center=(0, 0, 0)),
"x-shear": cpt.CustomDof(lambda p: [np.cos(np.pi*p[2]/2), 0, 0])
},
)
Other parameters¶
Besides the mandatory mesh and dofs, a floating body can also be
defined with a mass, given a floating point number and a
center_of_mass, given a three coordinates.
These two arguments are required for Hydrostatics but not for
first-order wave-structure interaction.
Finally, as the mesh objects, the floating body can be assigned a name. Names are necessary in multibody setups to distinguish the bodies. Otherwise, they are optional.
Display and animation¶
Assuming a 3D backend is installed, the method
show() can be used to visualise a
body.
Geometric transformations¶
All the geometric transformation defined on meshes in Meshes can also be
applied to FloatingBody. Beside updating the mesh, they also update the
definition of the degrees of freedom and the center of mass (if relevant).