Example #1
0
    def __init__(self, half, plane, name=None):
        """Initialize the body.

        Parameters
        ----------
        half: FloatingBody
            a FloatingBody instance describing half of the body
        plane: Plane
            the symmetry plane across which the half body is mirrored
        """
        assert isinstance(half, FloatingBody)
        assert isinstance(plane, Plane)

        half.nb_matrices_to_keep *= 2

        self.plane = plane

        other_half = half.copy()
        other_half.mirror(plane)
        other_half.name = "mirror_of_" + half.name

        CollectionOfFloatingBodies.__init__(self, [half, other_half])

        if name is None:
            self.name = f"ReflectionSymmetry({half.name})"
        else:
            self.name = name
        LOG.info(f"New mirror symmetric body: {self.name}.")

        self.dofs = {}
        for name, dof in half.dofs.items():
            self.dofs['mirrored_' + name] = np.concatenate([dof, dof])
Example #2
0
    def build_matrices(self,
                       other_body,
                       force_full_computation=False,
                       **kwargs):
        """Return the influence matrices of self on other_body."""
        if isinstance(
                other_body, ReflectionSymmetry
        ) and other_body.plane == self.plane and not force_full_computation:
            # Use symmetry to speed up the evaluation of the matrix
            if other_body == self:
                LOG.debug(
                    f"Evaluating matrix of {self.name} on itself using mirror symmetry."
                )
            else:
                LOG.debug(
                    f"Evaluating matrix of {self.name} on {other_body.name} itself using mirror symmetry."
                )

            S_a, V_a = self.subbodies[0].build_matrices(
                other_body.subbodies[0], **kwargs)
            S_b, V_b = self.subbodies[0].build_matrices(
                other_body.subbodies[1], **kwargs)

            return BlockToeplitzMatrix([S_a,
                                        S_b]), BlockToeplitzMatrix([V_a, V_b])

        else:
            return CollectionOfFloatingBodies.build_matrices(
                self, other_body, **kwargs)
Example #3
0
    def __init__(self,
                 body_slice,
                 point_on_rotation_axis=np.zeros(3),
                 nb_repetitions=1,
                 name=None):
        """Initialize the body.

        Parameters
        ----------
        body_slice: FloatingBody
            the pattern that will be repeated to form the whole body
        point_on_rotation_axis: array(3)
            one point on the rotation axis. The axis is supposed to be vertical.
        nb_repetitions: int
            the number of repetitions of the pattern (excluding the original one)
        """
        assert isinstance(body_slice, FloatingBody)
        assert isinstance(nb_repetitions, int)
        assert nb_repetitions >= 1

        point_on_rotation_axis = np.asarray(point_on_rotation_axis)
        assert point_on_rotation_axis.shape == (3, )

        body_slice.nb_matrices_to_keep *= nb_repetitions + 1
        slices = [body_slice]
        for i in range(1, nb_repetitions + 1):
            new_slice = body_slice.copy(
                name=f"rotation_{i}_of_{body_slice.name}")
            new_slice.translate(-point_on_rotation_axis)
            new_slice.rotate_z(2 * i * np.pi / (nb_repetitions + 1))
            new_slice.translate(point_on_rotation_axis)
            new_slice.nb_matrices_to_keep *= nb_repetitions + 1
            slices.append(new_slice)

        CollectionOfFloatingBodies.__init__(self, slices)

        if name is None:
            self.name = f"AxialSymmetry({body_slice.name})"
        else:
            self.name = name
        LOG.info(f"New rotation symmetric body: {self.name}.")

        self.dofs = {}
        for name, dof in body_slice.dofs.items():
            self.dofs["rotated_" + name] = np.concatenate([dof] *
                                                          nb_repetitions)
Example #4
0
    def __init__(self, body_slice, translation, nb_repetitions=1, name=None):
        """Initialize the body.

        Parameters
        ----------
        body_slice: FloatingBody
            the pattern that will be repeated to form the whole body
        translation: array(3)
            the vector of the translation
        nb_repetitions: int
            the number of repetitions of the pattern (excluding the original one)
        """
        assert isinstance(body_slice, FloatingBody)
        assert isinstance(nb_repetitions, int)
        assert nb_repetitions >= 1

        translation = np.asarray(translation)
        assert translation.shape == (3, )

        self.translation = translation

        body_slice.nb_matrices_to_keep *= nb_repetitions + 1
        slices = [body_slice]
        for i in range(1, nb_repetitions + 1):
            new_slice = body_slice.copy(
                name=f"repetition_{i}_of_{body_slice.name}")
            new_slice.translate(i * translation)
            new_slice.nb_matrices_to_keep *= nb_repetitions + 1
            slices.append(new_slice)

        CollectionOfFloatingBodies.__init__(self, slices)

        if name is None:
            self.name = f"TranslationSymmetry({body_slice.name})"
        else:
            self.name = name
        LOG.info(f"New translation symmetric body: {self.name}.")

        self.dofs = {}
        for name, dof in body_slice.dofs.items():
            self.dofs["translated_" + name] = np.concatenate([dof] *
                                                             nb_repetitions)
Example #5
0
    def build_matrices(self,
                       other_body,
                       force_full_computation=False,
                       **kwargs):
        """Compute the influence matrix of `self` on `other_body`.

        Parameters
        ----------
        other_body: FloatingBody
            the body interacting with `self`
        force_full_computation: boolean
            if True, do not use the symmetry (for debugging).
        """

        if other_body == self and not force_full_computation:
            # Use symmetry to speed up the evaluation of the matrix
            LOG.debug(
                f"Evaluating matrix of {self.name} on itself using rotation symmetry."
            )

            S_list, V_list = [], []
            for body in self.subbodies[:self.nb_subbodies // 2 + 1]:
                S, V = self.subbodies[0].build_matrices(body, **kwargs)
                S_list.append(S)
                V_list.append(V)

            if self.nb_subbodies % 2 == 0:
                return BlockCirculantMatrix(
                    S_list, size=self.nb_subbodies), BlockCirculantMatrix(
                        V_list, size=self.nb_subbodies)
            else:
                return BlockCirculantMatrix(
                    S_list, size=self.nb_subbodies), BlockCirculantMatrix(
                        V_list, size=self.nb_subbodies)

        else:
            return CollectionOfFloatingBodies.build_matrices(
                self, other_body, **kwargs)
Example #6
0
    def build_matrices(self,
                       other_body,
                       force_full_computation=False,
                       **kwargs):
        """Compute the influence matrix of `self` on `other_body`.

        Parameters
        ----------
        body: FloatingBody
            the body interacting with `self`
        force_full_computation: boolean
            if True, do not use the symmetry (for debugging).
        """

        if (isinstance(other_body, TranslationalSymmetry)
                and np.allclose(other_body.translation, self.translation)
                and other_body.nb_subbodies == self.nb_subbodies
                and not force_full_computation):
            # Use symmetry to speed up the evaluation of the matrix
            if other_body == self:
                LOG.debug(
                    f"Evaluating matrix of {self.name} on itself using translation symmetry."
                )
            else:
                LOG.debug(
                    f"Evaluating matrix of {self.name} on {other_body.name} itself using translation symmetry."
                )

            S_list, V_list = [], []
            for body in other_body.subbodies:
                S, V = self.subbodies[0].build_matrices(body, **kwargs)
                S_list.append(S)
                V_list.append(V)
            return BlockToeplitzMatrix(S_list), BlockToeplitzMatrix(V_list)

        else:
            return CollectionOfFloatingBodies.build_matrices(
                self, other_body, **kwargs)
Example #7
0
def import_cal_file(filepath):
    """
    Read a Nemoh.cal file and return a list of problems.
    """

    with open(filepath, 'r') as cal_file:

        cal_file.readline() # Unused line.
        rho = float(cal_file.readline().split()[0])
        g = float(cal_file.readline().split()[0])
        depth = float(cal_file.readline().split()[0])
        if depth == 0.0:
            sea_bottom = -np.infty
        else:
            sea_bottom = -depth
        xeff, yeff = (float(x) for x in cal_file.readline().split()[0:2])

        bodies = []

        cal_file.readline() # Unused line.
        nb_bodies = int(cal_file.readline().split()[0])
        for i_body in range(nb_bodies):
            cal_file.readline() # Unused line.
            mesh_file = cal_file.readline().split()[0].strip()
            cal_file.readline() # Number of points, number of panels (unused)

            body = FloatingBody.from_file(
                os.path.join(os.path.dirname(filepath), mesh_file), # mesh path are relative to Nemoh.cal
                'mar')

            nb_dofs = int(cal_file.readline().split()[0])
            for i_dof in range(nb_dofs):
                dof_data = cal_file.readline().split()
                if int(dof_data[0]) == 1:
                    direction = np.array([float(x) for x in dof_data[1:4]])
                    body.add_translation_dof(direction=direction)
                elif int(dof_data[0]) == 2:
                    direction = np.array([float(x) for x in dof_data[1:4]])
                    center_of_mass = np.array([float(x) for x in dof_data[4:7]])
                    body.add_rotation_dof(axis_direction=direction, axis_point=center_of_mass)

            nb_forces = int(cal_file.readline().split()[0])
            for i_force in range(nb_forces):
                force_data = cal_file.readline().split()
                if int(force_data[0]) == 1:
                    direction = np.array([float(x) for x in force_data[1:4]])
                elif int(force_data[0]) == 2:
                    direction = np.array([float(x) for x in force_data[1:4]])
                    center_of_mass = np.array([float(x) for x in force_data[4:7]])
            # TODO: use the generalize forces.

            nb_additional_lines = int(cal_file.readline().split()[0])
            for _ in range(nb_additional_lines):
                cal_file.readline() # The additional lines are just ignored.

            bodies.append(body)

        bodies = CollectionOfFloatingBodies(bodies)

        cal_file.readline() # Unused line.
        frequency_data = cal_file.readline().split()
        omega_range = np.linspace(float(frequency_data[1]), float(frequency_data[2]), int(frequency_data[0]))

        direction_data = cal_file.readline().split()
        direction_range = np.linspace(float(direction_data[1]), float(direction_data[2]), int(direction_data[0]))

        # The options below are not implemented yet.

        cal_file.readline() # Unused line.
        irf_data = cal_file.readline()
        show_pressure = cal_file.readline().split()[0] == "1"
        kochin_data = cal_file.readline().split()
        kochin_range = np.linspace(float(kochin_data[1]), float(kochin_data[2]), int(kochin_data[0]))
        free_surface_data = cal_file.readline().split()

    # Generate Capytaine's problem objects
    env_args = dict(body=bodies, rho=rho, sea_bottom=sea_bottom, g=g)
    problems = []
    for omega in omega_range:
        for direction in direction_range:
            problems.append(DiffractionProblem(angle=direction, omega=omega, **env_args))
        if bodies.nb_dofs > 0:
            problems.append(RadiationProblem(omega=omega, **env_args))

    return problems
Example #8
0
 def __add__(self, body_to_add):
     """Create a new CollectionOfFloatingBody from the combination of two of them."""
     from capytaine.bodies_collection import CollectionOfFloatingBodies
     return CollectionOfFloatingBodies([self, body_to_add])
Example #9
0
 def __add__(self, body_to_add):
     return CollectionOfFloatingBodies([self, body_to_add])