capytaine.bodies.dofs module

class capytaine.bodies.dofs.AbstractDof[source]

Bases: ABC

The representation of a degree of freedom. It always live within an AbstractBody, next to an AbstractMesh.

How to use a degree of freedom

Four magnitudes can be evaluated for a given dof:

  • the first-order motion, a vector defining how a given location of the mesh is moving, used for pressure integration into forces and radiation problems boundary condition;

  • its gradient (actually Jacobian matrix), used for hydrostatics, forward speed and second-order forces;

  • the second-order motion, the component of the body motion quadratic with respect to the motion amplitude, it depends on a pair of dofs and it is used for second-order hydrostatic forces;

  • its gradient, also used for second-order hydrostatic forces.

The code using these classes is expected to call evaluate_[gradient_of_]motion(mesh, location) or evaluate_[gradient_of_]second_order_motion(other, mesh, location) where location is a string which can be either "faces_centers" (the default), "quadrature_points", or "waterline". The returned array will contain the values of the fields at each chosen type of points of the mesh, that is of shape either (nb_faces, ...), (nb_faces, nb_quad_points, ...) or (nb_edges_waterline, ...), where ... stands for (3,) for motions and (3, 3) for gradients.

How to implement a degree of freedom

CustomDof can be used to turn a first-order motion evaluation function in a subclass of AbstractDof. Defining a custom dof with second-order motion requires defining a subclass of AbstractDof, like explained below.

For most dofs, like the built-in rigid body dofs, it is recommended to implement the low-level methods evaluate_[gradient_of_]motion_at_points which take an array of points of shape (..., 3) as inputs and return the values at these points. Implementing the second-order motion evaluate_[gradient_of_]second_order_motion_at_points is optional (zero is used if none is implemented). These methods are meant to be private, the rest of the code is not supposed to call them, they might be renamed with a leading underscore in a future breaking-change version to mark that.

Alternatively, the public API methods evaluate_[gradient_of_][second_order_]motion can be redefined, like it is done by the DofOnSubmesh class. For a pair of dofs of which only one redefines evaluate_[gradient_of_]second_order_motion, the redefined method is used whatever the order of the pair (the second-order motion is symmetric). For this reason, the *_at_points methods are not @abstractmethod since they are not strictly required.

evaluate_gradient_of_motion(mesh: AbstractMesh, location: str = 'faces_centers') → ndarray[source]

Returns a Jacobian matrix, such that output[…, i_dir, i_deriv_dir] is the derivative with respect to i_deriv_dir of the i_dir component of the motion. In other words, output[…, 0, :] is the gradient of the x-component of the motion at each location and output[…, :, 0] is the derivative with respect to x of the motion vector at each location

evaluate_gradient_of_motion_at_points(points: ndarray) → ndarray[source]
evaluate_gradient_of_second_order_motion(other: AbstractDof, mesh: AbstractMesh, location: str = 'faces_centers') → ndarray[source]

Gradient (Jacobian matrix, with the same conventions as evaluate_gradient_of_motion) of δ²u_kj = dofs[k].evaluate_second_order_motion(dofs[j], mesh). Zero for all pair of builtin dofs, except for some pairs of rotations.

evaluate_gradient_of_second_order_motion_at_points(other: AbstractDof, points: ndarray) → ndarray[source]
evaluate_motion(mesh: AbstractMesh, location: str = 'faces_centers') → ndarray[source]

Return the displacement as a 3 element vector for all location of mesh, that is an array of type (..., 3).

evaluate_motion_at_points(points: ndarray) → ndarray[source]
evaluate_second_order_motion(other: AbstractDof, mesh: AbstractMesh, location: str = 'faces_centers') → ndarray[source]

Generally a motion/deformation of a body can be expanded to second-order with respect to the amplitude of the dofs (q_k) as:

δu_k = dofs[k].evaluate_motion(mesh)
δ²u_kj = dofs[k].evaluate_second_order_motion(dofs[j], mesh)
u = Σ_k q_k δu_k + 1/2 Σ_kj q_k q_j δ²u_kj

δ²u_kj == δ²u_jk is the second order component coupling dof j and dof k.

evaluate_second_order_motion_at_points(other: AbstractDof, points: ndarray) → ndarray[source]
class capytaine.bodies.dofs.CustomDof(motion, gradient_of_motion=None)[source]

Bases: AbstractDof

Defines a custom dof with the same interface as the other AbstractDof. To be used for elastic dofs. Only first-order motion can be defined this way for now.

Parameters:
  • motion (Callable) – A function returning the motion at a given location. Required. The function is expected to take a 3-element vector as input (location in space) and return a 3-element vector (displacement at this location).

  • gradient_of_motion (Callable, optional) – A function returning the gradient (actually jacobian matrix) of the motion The function is expected to take a 3-element vector as input (location in space) and return a 3×3-matrix (jacobian of the displacement at this location). If none is provided, zero value is used, which makes no difference for first-order hydrodynamics, but loses some accuracy for hydrostatics and second-order forces.

evaluate_gradient_of_motion_at_points(points: ndarray) → ndarray[source]
evaluate_motion_at_points(points: ndarray) → ndarray[source]
class capytaine.bodies.dofs.DofOnSubmesh(dof: AbstractDof, faces)[source]

Bases: AbstractDof

Defines a dof that is zeros everywhere except on a given set of faces on which another dof object is used for the definition.

It is only defined on the mesh it has been built for, and can only be evaluated with the methods taking this mesh (evaluate_motion(mesh), …), not at arbitrary points (evaluate_motion_at_points is not implemented).

Parameters:
  • dof (AbstractDof) – Some other dof

  • faces (boolean array) – Boolean array of size nb_faces, the total number of faces of the mesh on which this dof is defined, True on the faces on which dof should be evaluated.

evaluate_gradient_of_motion(mesh: AbstractMesh, location: str = 'faces_centers') → ndarray[source]

Returns a Jacobian matrix, such that output[…, i_dir, i_deriv_dir] is the derivative with respect to i_deriv_dir of the i_dir component of the motion. In other words, output[…, 0, :] is the gradient of the x-component of the motion at each location and output[…, :, 0] is the derivative with respect to x of the motion vector at each location

evaluate_gradient_of_second_order_motion(other: AbstractDof, mesh: AbstractMesh, location: str = 'faces_centers') → ndarray[source]

Gradient (Jacobian matrix, with the same conventions as evaluate_gradient_of_motion) of δ²u_kj = dofs[k].evaluate_second_order_motion(dofs[j], mesh). Zero for all pair of builtin dofs, except for some pairs of rotations.

evaluate_motion(mesh: AbstractMesh, location: str = 'faces_centers') → ndarray[source]

Return the displacement as a 3 element vector for all location of mesh, that is an array of type (..., 3).

evaluate_second_order_motion(other: AbstractDof, mesh: AbstractMesh, location: str = 'faces_centers') → ndarray[source]

Generally a motion/deformation of a body can be expanded to second-order with respect to the amplitude of the dofs (q_k) as:

δu_k = dofs[k].evaluate_motion(mesh)
δ²u_kj = dofs[k].evaluate_second_order_motion(dofs[j], mesh)
u = Σ_k q_k δu_k + 1/2 Σ_kj q_k q_j δ²u_kj

δ²u_kj == δ²u_jk is the second order component coupling dof j and dof k.

class capytaine.bodies.dofs.RotationDof(rotation_center, direction)[source]

Bases: AbstractDof

evaluate_gradient_of_motion_at_points(points: ndarray) → ndarray[source]
evaluate_gradient_of_second_order_motion_at_points(other: AbstractDof, points: ndarray) → ndarray[source]
evaluate_motion_at_points(points: ndarray) → ndarray[source]
evaluate_second_order_motion_at_points(other: AbstractDof, points: ndarray) → ndarray[source]
class capytaine.bodies.dofs.TranslationDof(direction)[source]

Bases: AbstractDof

evaluate_gradient_of_motion_at_points(points: ndarray) → ndarray[source]
evaluate_motion_at_points(points: ndarray) → ndarray[source]
capytaine.bodies.dofs.add_dofs_labels_to_matrix(dof_names, matrix)[source]

Helper function turning a bare matrix into a matrix labelled by the name of the dofs, to be used for instance for the computation of RAO.

capytaine.bodies.dofs.add_dofs_labels_to_vector(dof_names, vector)[source]

Helper function turning a bare vector into a vector labelled by the name of the dofs, to be used for instance for the computation of RAO.

capytaine.bodies.dofs.normalize_name(name)[source]
capytaine.bodies.dofs.rigid_body_dofs(only=None, rotation_center=None)[source]

Pass this to FloatingBody initializer to give it rigid body dofs.

Parameters:
  • only (sequence of str, optional) – list of the name of the rigid body dofs to be included. By default: all six of them

  • rotation_center (np.array, optional) – the center for the definition of the rotations