示例#1
0
def test_bodies():
    body = Sphere(name="sphere", clever=False)
    assert str(body) == "sphere"
    repr(body)
    assert np.allclose(body.geometric_center, (0, 0, 0))
    body.add_translation_dof(name="Surge")
    body.add_translation_dof(name="Heave")

    # Extract faces
    body.extract_faces(np.where(body.mesh.faces_centers[:, 2] < 0)[0])

    # Clipping
    body.keep_immersed_part(inplace=False)

    # Mirror of the dofs
    mirrored = body.mirrored(Plane(point=(1, 0, 0), normal=(1, 0, 0)))
    assert np.allclose(mirrored.geometric_center, np.array([2, 0, 0]))
    assert np.allclose(body.dofs['Surge'], -mirrored.dofs['Surge'])

    # Rotation of the dofs
    sideways = body.rotated(Axis(point=(0, 0, 0), vector=(0, 1, 0)), np.pi/2)
    assert np.allclose(sideways.dofs['Heave'][0], np.array([1, 0, 0]))

    upside_down = body.rotated(Axis(point=(0, 0, 0), vector=(0, 1, 0)), np.pi)
    assert np.allclose(body.dofs['Heave'], -upside_down.dofs['Heave'])

    # Copy of the body
    copy_of_body = body.copy(name="copy_of_sphere")
    copy_of_body.translate_x(10.0)
    copy_of_body.add_translation_dof(name="Heave")

    # Join bodies
    both = body.join_bodies(copy_of_body)
    assert set(both.dofs) == {'sphere__Surge', 'copy_of_sphere__Surge', 'sphere__Heave', 'copy_of_sphere__Heave'}
示例#2
0
    def __init__(self,
                 mesh_slice: Union[Mesh, CollectionOfMeshes],
                 axis: Axis = Oz_axis,
                 nb_repetitions: int = 1,
                 name=None):
        assert isinstance(mesh_slice, Mesh) or isinstance(
            mesh_slice, CollectionOfMeshes)
        assert isinstance(nb_repetitions, int)
        assert nb_repetitions >= 1
        assert isinstance(axis, Axis)

        slices = [mesh_slice]
        for i in range(1, nb_repetitions + 1):
            slices.append(
                mesh_slice.rotated(axis,
                                   angle=2 * i * np.pi / (nb_repetitions + 1),
                                   name=f"rotation_{i}_of_{mesh_slice.name}"))

        super().__init__(slices, name=name)

        if not axis.is_parallel_to(Oz_axis):
            LOG.warning(
                f"{self.name} is an axi-symmetric mesh along a non vertical axis."
            )

        self.axis = axis.copy()

        if self.name is not None:
            LOG.debug(f"New rotation symmetric mesh: {self.name}.")
        else:
            LOG.debug(f"New rotation symmetric mesh.")
示例#3
0
def test_dof():
    nodes = np.array([[0, 0, 0], [0, 0, 1], [1, 0, 1], [1, 0, 0]])
    faces = np.array([[0, 1, 2, 3]])
    body = FloatingBody(Mesh(nodes, faces), name="one_face")
    assert body.dofs == {}

    body.add_translation_dof(direction=(1.0, 0.0, 0.0), name="1")
    assert np.allclose(body.dofs["1"], np.array([1.0, 0.0, 0.0]))

    body.add_translation_dof(direction=(0.0, 1.0, 0.0), name="2")
    assert np.allclose(body.dofs["2"], np.array([0.0, 1.0, 0.0]))

    body.add_rotation_dof(Axis(vector=(0.0, 0.0, 1.0)), name="3")
    body.add_rotation_dof(Axis(point=(0.5, 0, 0), vector=(0.0, 0.0, 1.0)), name="4")
def test_plane_transformations():
    # TRANSLATIONS
    translated_plane = xOz_Plane.translate(vector=(1, 0, 0), inplace=False)
    assert xOz_Plane is not translated_plane
    assert xOz_Plane == translated_plane

    assert yOz_Plane.translated_x(10).rotated_y(np.pi / 8).c == 10

    translated_plane = xOz_Plane.translate(vector=(0, 1, 0), inplace=False)
    assert translated_plane.c == 1
    assert np.all(translated_plane.normal == xOz_Plane.normal)

    # ROTATIONS
    rotated_plane = xOz_Plane.rotate(Oy_axis, angle=np.pi / 12, inplace=False)
    assert rotated_plane == xOz_Plane.rotated(Oy_axis, angle=np.pi / 12)
    assert xOz_Plane is not rotated_plane
    assert xOz_Plane == rotated_plane

    rotated_plane = xOz_Plane.rotate(Ox_axis, angle=np.pi / 2, inplace=False)
    assert rotated_plane == xOy_Plane

    # MIRRORED BY ITSELF
    plane = Plane(normal=(1, 0, 0), point=(0.3, 0.2, 0.6))
    assert plane.mirrored(plane) != plane
    assert plane.mirrored(plane) == Plane(normal=(-1, 0, 0),
                                          point=(0.3, 0.2, 0.6))

    flipped_plane = plane.rotate(Axis(point=plane.point, vector=(0, 1, 0)),
                                 np.pi)
    assert flipped_plane == plane.mirror(plane)
示例#5
0
    def _generate_mesh_using_symmetry(self, ntheta, nphi, clip_free_surface,
                                      mesh_name):
        if clip_free_surface:
            if self.geometric_center[2] < -self.radius:  # fully immersed
                theta_max = np.pi
            elif self.geometric_center[2] < self.radius:
                theta_max = np.arccos(self.geometric_center[2] / self.radius)
            else:
                raise ValueError(
                    "Impossible to mesh the immersed hull of a sphere completely out of the water"
                )
        else:
            theta_max = np.pi

        theta = np.linspace(0.0, theta_max, ntheta + 1)
        points_on_a_meridian = (self.radius * np.stack(
            [np.sin(theta),
             np.zeros_like(theta), -np.cos(theta)], axis=1) +
                                self.geometric_center)

        symmetry_axis = Axis(vector=[0, 0, 1], point=self.geometric_center)
        return AxialSymmetricMesh.from_profile(points_on_a_meridian,
                                               axis=symmetry_axis,
                                               nphi=nphi,
                                               name=mesh_name)
示例#6
0
    def from_profile(profile: Union[Callable, Iterable[float]],
                     z_range: Iterable[float]=np.linspace(-5, 0, 20),
                     axis: Axis=Oz_axis,
                     nphi: int=20,
                     name=None):
        """Return a floating body using the axial symmetry.
        The shape of the body can be defined either with a function defining the profile as [f(z), 0, z] for z in z_range.
        Alternatively, the profile can be defined as a list of points.
        The number of vertices along the vertical direction is len(z_range) in the first case and profile.shape[0] in the second case.

        Parameters
        ----------
        profile : function(float → float)  or  array(N, 3)
            define the shape of the body either as a function or a list of points.
        z_range: array(N), optional
            used only if the profile is defined as a function.
        axis : Axis
            symmetry axis
        nphi : int, optional
            number of vertical slices forming the body
        name : str, optional
            name of the generated body (optional)

        Returns
        -------
        AxialSymmetricMesh
            the generated mesh
        """

        if name is None:
            name = "axisymmetric_mesh"

        if callable(profile):
            z_range = np.asarray(z_range)
            x_values = [profile(z) for z in z_range]
            profile_array = np.stack([x_values, np.zeros(len(z_range)), z_range]).T
        else:
            profile_array = np.asarray(profile)

        assert len(profile_array.shape) == 2
        assert profile_array.shape[1] == 3

        n = profile_array.shape[0]
        angle = 2 * np.pi / nphi

        nodes_slice = np.concatenate([profile_array, axis.rotate_points(profile_array, angle)])
        faces_slice = np.array([[i, i+n, i+n+1, i+1] for i in range(n-1)])
        body_slice = Mesh(nodes_slice, faces_slice, name=f"slice_of_{name}")
        body_slice.merge_duplicates()
        body_slice.heal_triangles()

        return AxialSymmetricMesh(body_slice, axis=axis, nb_repetitions=nphi - 1, name=name)
示例#7
0
def fb_array():
    
    sphere = Sphere(
                    radius=r,            # Dimension
                    center=(0, 0, 0),    # Position
                    nphi=4, ntheta=10,   # Fineness of the mesh
    )
    my_axis = Axis((0, 1, 0), 
                   point=(0,0,0))
    sphere.add_rotation_dof(axis=my_axis)
    sphere.keep_immersed_part()
    
    return sphere.assemble_arbitrary_array(locations)
示例#8
0
def test_clipping_of_dofs(z_center, collection_of_meshes):
    """Check that clipping a body with a dof is the same as clipping the body ant then adding the dof."""
    full_sphere = Sphere(center=(0, 0, z_center), name="sphere", clever=collection_of_meshes, clip_free_surface=False)
    axis = Axis(point=(1, 0, 0), vector=(1, 0, 0))

    full_sphere.add_rotation_dof(axis, name="test_dof")
    clipped_sphere = full_sphere.keep_immersed_part(free_surface=0.0, sea_bottom=-np.infty, inplace=False)

    other_clipped_sphere = FloatingBody(mesh=clipped_sphere.mesh, name="other_sphere")
    other_clipped_sphere.add_rotation_dof(axis, name="test_dof")

    if clipped_sphere.mesh.nb_faces > 0:
        assert np.allclose(clipped_sphere.dofs['test_dof'], other_clipped_sphere.dofs['test_dof'])
    else:
        assert len(clipped_sphere.dofs['test_dof']) == 0
def test_axis():
    assert np.allclose(Axis(vector=(1, 1, 1)).vector, np.sqrt(3)/3 * np.ones((3,)))

    assert Axis(vector=(1, 1, 1), point=(0, 0, 0)) == Axis(vector=(1, 1, 1), point=(2, 2, 2))
    assert Axis(vector=(0, 0, 1), point=(0, 0, 0)) == Axis(vector=(2e-16, 3e-16, 1), point=(0,  0,  1.5))
    assert Axis(vector=(1, 1, 1), point=(0, 0, 0)) != Axis(vector=(1, 1, 1), point=(2, 2, 0))

    assert (2, 0, 0) in Ox_axis
    assert (0, 1, 0) not in Ox_axis

    assert Ox_axis.is_orthogonal_to(yOz_Plane)
    assert not Ox_axis.is_orthogonal_to((1, 1, 1))

    assert Ox_axis.angle_with_respect_to(Oy_axis) == np.pi/2
    assert Oy_axis.angle_with_respect_to(Ox_axis) == np.pi/2
示例#10
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 _ in range(nb_bodies):
            cal_file.readline()  # Unused line.
            mesh_file = cal_file.readline().split()[0].strip()
            mesh_file = os.path.join(
                os.path.dirname(filepath),
                mesh_file)  # mesh path are relative to Nemoh.cal
            cal_file.readline()  # Number of points, number of panels (unused)

            if os.path.splitext(mesh_file)[1] == '.py':
                from importlib.util import spec_from_file_location, module_from_spec
                spec = spec_from_file_location("body_initialization_module",
                                               mesh_file)
                body_initialization = module_from_spec(spec)
                spec.loader.exec_module(body_initialization)
                body = body_initialization.body
            else:
                body = FloatingBody.from_file(mesh_file)

            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(vector=direction, 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 generalized 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)

        if nb_bodies > 1:
            bodies = FloatingBody.join_bodies(*bodies)
        else:
            bodies = bodies[0]

        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]))
        direction_range = np.pi / 180 * direction_range  # conversion from degrees to radians.

        # 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(wave_direction=direction,
                                   omega=omega,
                                   **env_args))
        for dof in bodies.dofs:
            problems.append(
                RadiationProblem(radiating_dof=dof, omega=omega, **env_args))

    return problems
示例#11
0
 def rotate(self, axis: Axis, angle: float):
     self.translation = axis.rotation_matrix(angle) @ self.translation
     CollectionOfMeshes.rotate(self, axis, angle)
     return self
示例#12
0
def test_rotation_non_reference_axis():
    axis = Axis(vector=(0, 0, 1), point=(1, 0, 0))
    point = [[1.0, 0.0, 0.0]]
    rotated_point = axis.rotate_points(point, np.pi)
    assert np.allclose(rotated_point, point)
示例#13
0
def test_axis_transformation():
    assert Ox_axis.translated_x(10) == Ox_axis
    assert Ox_axis.translated_y(10) == Axis(vector=(1, 0, 0), point=(0, 10, 0))

    assert Ox_axis.rotated(Ox_axis, angle=np.pi / 2) == Ox_axis
    assert Ox_axis.rotated(Oy_axis, angle=-np.pi / 2) == Oz_axis

    assert Ox_axis.mirrored(plane=yOz_Plane) == Ox_axis
    assert Ox_axis.mirrored(plane=xOz_Plane.translated_y(2)) == Axis(
        vector=(1, 0, 0), point=(0, 4, 0))

    axis1 = Axis(vector=(1, 1, 1), point=(0, 0, 0))
    axis2 = Axis(vector=(1, 2, 3), point=(0, 0, 0))
    assert axis1.rotated_around_center_to_align_vectors(
        axis1.point, axis1.vector, axis2.vector) == axis2
    axis1.rotate(axis2, np.pi)
    assert axis1.rotated_around_center_to_align_vectors(
        axis1.point, axis1.vector, axis2.vector) == axis2
    axis1.vector *= -1
    assert axis1.rotated_around_center_to_align_vectors(
        axis1.point, axis1.vector, axis2.vector) == axis2

    axis1 = Axis(vector=(1, 1, 1), point=(1, 2, 0))
    axis2 = Axis(vector=(2, 2, 2), point=(0, 0, 0))
    assert axis1.translated_point_to_point(axis1.point, axis2.point) == axis2
示例#14
0
 def rotate(self, axis: Axis, angle: float):
     self.translation = axis.rotate_vector([self.translation], angle)[0, :]
     CollectionOfMeshes.rotate(self, axis, angle)
     return self