예제 #1
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")
예제 #2
0
def test_odd_axial_symmetry():
    """Buoy with odd number of slices."""
    def shape(z):
        return 0.1 * (-(z + 1)**2 + 16)

    buoy = FloatingBody(
        AxialSymmetricMesh.from_profile(shape,
                                        z_range=np.linspace(-5.0, 0.0, 9),
                                        nphi=5))
    buoy.add_translation_dof(direction=(0, 0, 1), name="Heave")

    problem = RadiationProblem(body=buoy, omega=2.0)
    result1 = solver_with_sym.solve(problem)

    full_buoy = FloatingBody(buoy.mesh.merged())
    full_buoy.add_translation_dof(direction=(0, 0, 1), name="Heave")
    problem = RadiationProblem(body=full_buoy, omega=2.0)
    result2 = solver_with_sym.solve(problem)

    volume = buoy.mesh.volume
    assert np.isclose(result1.added_masses["Heave"],
                      result2.added_masses["Heave"],
                      atol=1e-4 * volume * problem.rho)
    assert np.isclose(result1.radiation_dampings["Heave"],
                      result2.radiation_dampings["Heave"],
                      atol=1e-4 * volume * problem.rho)
예제 #3
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
예제 #4
0
def test_low_rank_matrices():
    radius = 1.0
    resolution = 2
    perimeter = 2 * np.pi * radius
    buoy = Sphere(radius=radius,
                  center=(0.0, 0.0, 0.0),
                  ntheta=int(perimeter * resolution / 2),
                  nphi=int(perimeter * resolution),
                  clip_free_surface=True,
                  clever=False,
                  name=f"buoy")
    buoy.add_translation_dof(name="Heave")
    two_distant_buoys = FloatingBody.join_bodies(buoy, buoy.translated_x(20))
    two_distant_buoys.mesh._meshes[1].name = "other_buoy_mesh"

    S, V = solver_with_sym.build_matrices(two_distant_buoys.mesh,
                                          two_distant_buoys.mesh)
    assert isinstance(S.all_blocks[0, 1], LowRankMatrix)
    assert isinstance(S.all_blocks[1, 0], LowRankMatrix)
    # S.plot_shape()

    problem = RadiationProblem(body=two_distant_buoys,
                               omega=1.0,
                               radiating_dof="buoy__Heave")
    result = solver_with_sym.solve(problem)
    result2 = solver_without_sym.solve(problem)

    assert np.isclose(result.added_masses['buoy__Heave'],
                      result2.added_masses['buoy__Heave'],
                      atol=10.0)
    assert np.isclose(result.radiation_dampings['buoy__Heave'],
                      result2.radiation_dampings['buoy__Heave'],
                      atol=10.0)
예제 #5
0
def test_LinearPotentialFlowProblem():
    # Without a body
    pb = LinearPotentialFlowProblem(omega=1.0)
    assert pb.omega == 1.0
    assert pb.period == 2 * np.pi
    assert pb.wavenumber == 1.0 / 9.81
    assert pb.wavelength == 9.81 * 2 * np.pi

    assert LinearPotentialFlowProblem(free_surface=np.infty,
                                      sea_bottom=-np.infty).depth == np.infty
    assert LinearPotentialFlowProblem(free_surface=0.0,
                                      sea_bottom=-np.infty).depth == np.infty

    pb = LinearPotentialFlowProblem(free_surface=0.0,
                                    sea_bottom=-1.0,
                                    omega=1.0)
    assert pb.depth == 1.0
    assert np.isclose(pb.omega**2,
                      pb.g * pb.wavenumber * np.tanh(pb.wavenumber * pb.depth))
    assert pb.dimensionless_wavenumber == pb.wavenumber * 1.0

    with pytest.raises(NotImplementedError):
        LinearPotentialFlowProblem(free_surface=2.0)

    with pytest.raises(NotImplementedError):
        LinearPotentialFlowProblem(free_surface=np.infty, sea_bottom=0.0)

    with pytest.raises(ValueError):
        LinearPotentialFlowProblem(free_surface=0.0, sea_bottom=1.0)

    with pytest.raises(TypeError):
        LinearPotentialFlowProblem(wave_direction=1.0)

    with pytest.raises(TypeError):
        LinearPotentialFlowProblem(radiating_dof="Heave")

    with pytest.raises(ValueError):
        LinearPotentialFlowProblem(body=FloatingBody(mesh=Mesh([], [])))

    # With a body
    sphere = Sphere(center=(0, 0, -2.0))
    sphere.add_translation_dof(direction=(0, 0, 1), name="Heave")
    pb = LinearPotentialFlowProblem(body=sphere, omega=1.0)
    pb.boundary_condition = sphere.mesh.faces_normals @ (1, 1, 1)
    assert list(pb.influenced_dofs.keys()) == ['Heave']

    pb2 = LinearPotentialFlowProblem(body=sphere, omega=2.0)
    pb2.boundary_condition = sphere.mesh.faces_normals @ (1, 1, 1)
    assert pb < pb2

    # Test transformation to result class
    res = pb.make_results_container()
    assert isinstance(res, LinearPotentialFlowResult)
    assert res.problem is pb
    assert res.omega == pb.omega
    assert res.period == pb.period
    assert res.body is pb.body
def test_floating_sphere(depth, omega):
    """Comparison of the added mass and radiation damping
    for a heaving sphere described using several symmetries
    in finite and infinite depth.
    """
    reso = 2

    full_sphere = Sphere(radius=1.0, ntheta=reso, nphi=4*reso, axial_symmetry=False, clip_free_surface=True)
    full_sphere.add_translation_dof(direction=(0, 0, 1), name="Heave")
    problem = RadiationProblem(body=full_sphere, omega=omega, sea_bottom=-depth)
    result1 = solver_with_sym.solve(problem)

    half_sphere_mesh = full_sphere.mesh.extract_faces(
        np.where(full_sphere.mesh.faces_centers[:, 1] > 0)[0],
        name="half_sphere_mesh")
    two_halves_sphere = FloatingBody(ReflectionSymmetricMesh(half_sphere_mesh, xOz_Plane))
    two_halves_sphere.add_translation_dof(direction=(0, 0, 1), name="Heave")
    problem = RadiationProblem(body=two_halves_sphere, omega=omega, sea_bottom=-depth)
    result2 = solver_with_sym.solve(problem)

    quarter_sphere_mesh = half_sphere_mesh.extract_faces(
        np.where(half_sphere_mesh.faces_centers[:, 0] > 0)[0],
        name="quarter_sphere_mesh")
    four_quarter_sphere = FloatingBody(ReflectionSymmetricMesh(ReflectionSymmetricMesh(quarter_sphere_mesh, yOz_Plane), xOz_Plane))
    assert 'None' not in four_quarter_sphere.mesh.tree_view()
    four_quarter_sphere.add_translation_dof(direction=(0, 0, 1), name="Heave")
    problem = RadiationProblem(body=four_quarter_sphere, omega=omega, sea_bottom=-depth)
    result3 = solver_with_sym.solve(problem)

    clever_sphere = Sphere(radius=1.0, ntheta=reso, nphi=4*reso, axial_symmetry=True, clip_free_surface=True)
    clever_sphere.add_translation_dof(direction=(0, 0, 1), name="Heave")
    problem = RadiationProblem(body=clever_sphere, omega=omega, sea_bottom=-depth)
    result4 = solver_with_sym.solve(problem)

    # (quarter_sphere + half_sphere + full_sphere + clever_sphere).show()

    volume = 4/3*np.pi
    assert np.isclose(result1.added_masses["Heave"], result2.added_masses["Heave"], atol=1e-4*volume*problem.rho)
    assert np.isclose(result1.added_masses["Heave"], result3.added_masses["Heave"], atol=1e-4*volume*problem.rho)
    assert np.isclose(result1.added_masses["Heave"], result4.added_masses["Heave"], atol=1e-4*volume*problem.rho)
    assert np.isclose(result1.radiation_dampings["Heave"], result2.radiation_dampings["Heave"], atol=1e-4*volume*problem.rho)
    assert np.isclose(result1.radiation_dampings["Heave"], result3.radiation_dampings["Heave"], atol=1e-4*volume*problem.rho)
    assert np.isclose(result1.radiation_dampings["Heave"], result4.radiation_dampings["Heave"], atol=1e-4*volume*problem.rho)
예제 #7
0
def test_two_vertical_cylinders():
    distance = 5

    buoy = VerticalCylinder(length=3,
                            radius=0.5,
                            center=(-distance / 2, -1, 0),
                            nx=8,
                            nr=3,
                            ntheta=8)
    buoy.mesh = buoy.mesh.merged()
    buoy.mesh = buoy.mesh.keep_immersed_part()
    buoy.add_translation_dof(name="Sway")

    two_buoys = FloatingBody.join_bodies(buoy, buoy.translated_x(distance))
    two_buoys.mesh = buoy.mesh.symmetrized(
        yOz_Plane)  # Use a ReflectionSymmetry as mesh...

    problems = [
        RadiationProblem(body=two_buoys, omega=1.0, radiating_dof=dof)
        for dof in two_buoys.dofs
    ]

    results = assemble_dataset(solver_without_sym.solve_all(problems))
    # Check that the resulting matrix is symmetric
    assert np.isclose(results['added_mass'].data[0, 0, 0],
                      results['added_mass'].data[0, 1, 1])
    assert np.isclose(results['added_mass'].data[0, 1, 0],
                      results['added_mass'].data[0, 0, 1])
    assert np.isclose(results['radiation_damping'].data[0, 0, 0],
                      results['radiation_damping'].data[0, 1, 1])
    assert np.isclose(results['radiation_damping'].data[0, 1, 0],
                      results['radiation_damping'].data[0, 0, 1])

    results_with_sym = assemble_dataset(solver_with_sym.solve_all(problems))
    assert np.allclose(results['added_mass'].data,
                       results_with_sym['added_mass'].data)
    assert np.allclose(results['radiation_damping'].data,
                       results_with_sym['radiation_damping'].data)
예제 #8
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