Пример #1
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)
Пример #2
0
def test_problems_from_dataset():
    body = Sphere(center=(0, 0, -4), name="sphere")
    body.add_translation_dof(name="Heave")

    dset = xr.Dataset(coords={'omega': [0.5, 1.0, 1.5],
                              'radiating_dof': ["Heave"],
                              'body_name': ["sphere"],
                              'wave_direction': [0.0],
                              'water_depth': [np.infty]})

    problems = problems_from_dataset(dset, [body])
    assert RadiationProblem(body=body, omega=0.5, radiating_dof="Heave") in problems
    assert len(problems) == 6
    assert len([problem for problem in problems if isinstance(problem, DiffractionProblem)]) == 3

    dset = xr.Dataset(coords={'omega': [0.5, 1.0, 1.5],
                              'wave_direction': [0.0],
                              'body_name': ["cube"]})
    with pytest.raises(AssertionError):
        problems_from_dataset(dset, [body])

    shifted_body = body.translated_y(5.0, name="shifted_sphere")
    dset = xr.Dataset(coords={'omega': [0.5, 1.0, 1.5],
                              'radiating_dof': ["Heave"],
                              'wave_direction': [0.0]})
    problems = problems_from_dataset(dset, [body, shifted_body])
    assert RadiationProblem(body=body, omega=0.5, radiating_dof="Heave") in problems
    assert RadiationProblem(body=shifted_body, omega=0.5, radiating_dof="Heave") in problems
    assert len(problems) == 12
Пример #3
0
def test_floating_sphere_finite_depth():
    """Compare with Nemoh 2.0 for some cases of a heaving sphere at the free surface in finite depth."""
    sphere = Sphere(radius=1.0, ntheta=3, nphi=12, clip_free_surface=True)
    sphere.add_translation_dof(direction=(0, 0, 1), name="Heave")

    # omega = 1, radiation
    problem = RadiationProblem(body=sphere, omega=1.0, radiating_dof="Heave", sea_bottom=-10.0)
    result = solver.solve(problem, keep_details=True)
    assert np.isclose(result.added_masses["Heave"],       1740.6, atol=1e-3*sphere.volume*problem.rho)
    assert np.isclose(result.radiation_dampings["Heave"], 380.46, atol=1e-3*sphere.volume*problem.rho)

    kochin = compute_kochin(result, np.linspace(0, np.pi, 3))
    assert np.allclose(kochin, np.roll(kochin, 1))  # The far field is the same in all directions.
    assert np.isclose(kochin[0], -0.2267+3.49e-3j, rtol=1e-3)

    # omega = 1, diffraction
    problem = DiffractionProblem(body=sphere, omega=1.0, wave_direction=0.0, sea_bottom=-10.0)
    result = solver.solve(problem)
    assert np.isclose(result.forces["Heave"], 1749.4 * np.exp(-2.922j), rtol=1e-3)

    # omega = 2, radiation
    problem = RadiationProblem(body=sphere, omega=2.0, radiating_dof="Heave", sea_bottom=-10.0)
    result = solver.solve(problem)
    assert np.isclose(result.added_masses["Heave"],       1375.0, atol=1e-3*sphere.volume*problem.rho)
    assert np.isclose(result.radiation_dampings["Heave"], 1418.0, atol=1e-3*sphere.volume*problem.rho)

    # omega = 2, diffraction
    problem = DiffractionProblem(body=sphere, omega=2.0, wave_direction=0.0, sea_bottom=-10.0)
    result = solver.solve(problem)
    assert np.isclose(result.forces["Heave"], 5872.8 * np.exp(-2.627j), rtol=1e-3)
Пример #4
0
def test_floating_sphere_finite_freq():
    """Compare with Nemoh 2.0 for some cases of a heaving sphere at the free surface in infinite depth."""
    sphere = Sphere(radius=1.0, ntheta=3, nphi=12, clip_free_surface=True)
    sphere.add_translation_dof(direction=(0, 0, 1), name="Heave")

    # omega = 1, radiation
    problem = RadiationProblem(body=sphere, omega=1.0, sea_bottom=-np.infty)
    result = solver.solve(problem, keep_details=True)
    assert np.isclose(result.added_masses["Heave"],       1819.6, atol=1e-3*sphere.volume*problem.rho)
    assert np.isclose(result.radiation_dampings["Heave"], 379.39, atol=1e-3*sphere.volume*problem.rho)

    # omega = 1, free surface
    free_surface = FreeSurface(x_range=(-62.5, 62.5), nx=5, y_range=(-62.5, 62.5), ny=5)
    eta = solver.get_free_surface_elevation(result, free_surface)
    ref = np.array(
            [[-0.4340802E-02-0.4742809E-03j, -0.7986111E-03+0.4840984E-02j, 0.2214827E-02+0.4700642E-02j, -0.7986111E-03+0.4840984E-02j, -0.4340803E-02-0.4742807E-03j],
             [-0.7986111E-03+0.4840984E-02j, 0.5733187E-02-0.2179381E-02j, 0.9460892E-03-0.7079404E-02j, 0.5733186E-02-0.2179381E-02j, -0.7986110E-03+0.4840984E-02j],
             [0.2214827E-02+0.4700643E-02j, 0.9460892E-03-0.7079403E-02j, -0.1381670E-01+0.6039315E-01j, 0.9460892E-03-0.7079405E-02j, 0.2214827E-02+0.4700643E-02j],
             [-0.7986111E-03+0.4840984E-02j, 0.5733186E-02-0.2179381E-02j, 0.9460891E-03-0.7079404E-02j, 0.5733187E-02-0.2179380E-02j, -0.7986113E-03+0.4840984E-02j],
             [-0.4340803E-02-0.4742807E-03j, -0.7986111E-03+0.4840984E-02j, 0.2214827E-02+0.4700643E-02j, -0.7986113E-03+0.4840983E-02j, -0.4340803E-02-0.4742809E-03j]]
        )
    assert np.allclose(eta.reshape((5, 5)), ref, rtol=1e-4)

    # omega = 1, diffraction
    problem = DiffractionProblem(body=sphere, omega=1.0, sea_bottom=-np.infty)
    result = solver.solve(problem, keep_details=True)
    assert np.isclose(result.forces["Heave"], 1834.9 * np.exp(-2.933j), rtol=1e-3)

    # omega = 1, Kochin function of diffraction problem

    kochin = compute_kochin(result, np.linspace(0, np.pi, 10))

    ref_kochin = np.array([
        0.20229*np.exp(-1.5872j), 0.20369*np.exp(-1.5871j),
        0.20767*np.exp(-1.5868j), 0.21382*np.exp(-1.5863j),
        0.22132*np.exp(-1.5857j), 0.22931*np.exp(-1.5852j),
        0.23680*np.exp(-1.5847j), 0.24291*np.exp(-1.5843j),
        0.24688*np.exp(-1.5841j), 0.24825*np.exp(-1.5840j),
        ])

    assert np.allclose(kochin, ref_kochin, rtol=1e-3)

    # omega = 2, radiation
    problem = RadiationProblem(body=sphere, omega=2.0, sea_bottom=-np.infty)
    result = solver.solve(problem)
    assert np.isclose(result.added_masses["Heave"],       1369.3, atol=1e-3*sphere.volume*problem.rho)
    assert np.isclose(result.radiation_dampings["Heave"], 1425.6, atol=1e-3*sphere.volume*problem.rho)

    # omega = 2, diffraction
    problem = DiffractionProblem(body=sphere, omega=2.0, sea_bottom=-np.infty)
    result = solver.solve(problem)
    assert np.isclose(result.forces["Heave"], 5846.6 * np.exp(-2.623j), rtol=1e-3)
def test_limit_frequencies():
    """Test if how the solver answers when asked for frequency of 0 or ∞."""
    solver = Nemoh()

    solver.solve(RadiationProblem(body=sphere, omega=0.0,
                                  sea_bottom=-np.infty))

    with pytest.raises(NotImplementedError):
        solver.solve(RadiationProblem(body=sphere, omega=0.0, sea_bottom=-1.0))

    solver.solve(
        RadiationProblem(body=sphere, omega=np.infty, sea_bottom=-np.infty))

    with pytest.raises(NotImplementedError):
        solver.solve(
            RadiationProblem(body=sphere, omega=np.infty, sea_bottom=-10))
Пример #6
0
def test_alien_sphere():
    """Compare with Nemoh 2.0 for some cases of a heaving sphere at the free surface in infinite depth
    for a non-usual gravity and density."""
    sphere = Sphere(radius=1.0, ntheta=3, nphi=12, clip_free_surface=True)
    sphere.add_translation_dof(direction=(0, 0, 1), name="Heave")
    sphere.add_translation_dof(direction=(1, 0, 0), name="Surge")

    # radiation
    problem = RadiationProblem(body=sphere,
                               rho=450.0,
                               g=1.625,
                               omega=1.0,
                               radiating_dof="Heave")
    result = solver.solve(problem)
    assert np.isclose(result.added_masses["Heave"],
                      515,
                      atol=1e-3 * sphere.volume * problem.rho)
    assert np.isclose(result.radiation_dampings["Heave"],
                      309,
                      atol=1e-3 * sphere.volume * problem.rho)

    # diffraction
    problem = DiffractionProblem(body=sphere,
                                 rho=450.0,
                                 g=1.625,
                                 omega=1.0,
                                 sea_bottom=-np.infty)
    result = solver.solve(problem)
    assert np.isclose(result.forces["Heave"],
                      548.5 * np.exp(-2.521j),
                      rtol=1e-2)
Пример #7
0
def test_two_distant_spheres_in_finite_depth():
    radius = 0.5
    resolution = 4
    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="buoy")
    other_buoy = buoy.translated_x(20, name="other_buoy")
    both_buoys = buoy.join_bodies(other_buoy)
    both_buoys.add_translation_dof(name="Surge")
    problem = RadiationProblem(body=both_buoys,
                               radiating_dof="Surge",
                               sea_bottom=-10,
                               omega=7.0)
    result = solver.solve(problem)

    total_volume = 2 * 4 / 3 * np.pi * radius**3
    assert np.isclose(result.added_masses['Surge'],
                      124.0,
                      atol=1e-3 * total_volume * problem.rho)
    assert np.isclose(result.radiation_dampings['Surge'],
                      913.3,
                      atol=1e-3 * total_volume * problem.rho)
Пример #8
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)
Пример #9
0
def test_array_of_spheres():
    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="Surge")
    buoy.add_translation_dof(name="Sway")
    buoy.add_translation_dof(name="Heave")

    # Corner case
    dumb_array = buoy.assemble_regular_array(distance=5.0, nb_bodies=(1, 1))
    assert dumb_array.mesh == buoy.mesh

    # Main case
    array = buoy.assemble_regular_array(distance=4.0, nb_bodies=(3, 3))

    assert isinstance(array.mesh, TranslationalSymmetricMesh)
    assert isinstance(array.mesh[0], TranslationalSymmetricMesh)
    assert array.mesh[0][0] == buoy.mesh

    assert len(array.dofs) == 3 * 3 * 3
    assert "2_0__Heave" in array.dofs

    #
    array = buoy.assemble_regular_array(distance=4.0, nb_bodies=(3, 1))

    settings = dict(cache_rankine_matrices=False, matrix_cache_size=0)
    nemoh_without_sym = Nemoh(hierarchical_matrices=False, **settings)
    nemoh_with_sym = Nemoh(hierarchical_matrices=True, **settings)

    fullS, fullV = nemoh_without_sym.build_matrices(array.mesh, array.mesh,
                                                    0.0, -np.infty, 1.0)
    S, V = nemoh_with_sym.build_matrices(array.mesh, array.mesh, 0.0,
                                         -np.infty, 1.0)

    assert isinstance(S, cpt.matrices.block.BlockMatrix)
    assert np.allclose(S.full_matrix(), fullS)
    assert np.allclose(V.full_matrix(), fullV)

    problem = RadiationProblem(body=array,
                               omega=1.0,
                               radiating_dof="2_0__Heave",
                               sea_bottom=-np.infty)

    result = nemoh_with_sym.solve(problem)
    result2 = nemoh_without_sym.solve(problem)

    assert np.isclose(result.added_masses['2_0__Heave'],
                      result2.added_masses['2_0__Heave'],
                      atol=15.0)
    assert np.isclose(result.radiation_dampings['2_0__Heave'],
                      result2.radiation_dampings['2_0__Heave'],
                      atol=15.0)
Пример #10
0
def test_immersed_sphere():
    """Compare with Nemoh 2.0 for a sphere in infinite fluid.

    The test is ran for two degrees of freedom; due to the symmetries of the problem, the results should be the same.
    They are actually slightly different due to the meshing of the sphere.
    """
    sphere = Sphere(radius=1.0, ntheta=10, nphi=40, clip_free_surface=False)
    sphere.add_translation_dof(direction=(1, 0, 0), name="Surge")
    sphere.add_translation_dof(direction=(0, 0, 1), name="Heave")

    problem = RadiationProblem(body=sphere,
                               radiating_dof="Heave",
                               free_surface=np.infty,
                               sea_bottom=-np.infty)
    result = solver.solve(problem)
    assert np.isclose(result.added_masses["Heave"],
                      2187,
                      atol=1e-3 * sphere.volume * problem.rho)
    assert np.isclose(result.added_masses["Surge"],
                      0.0,
                      atol=1e-3 * sphere.volume * problem.rho)
    assert np.isclose(result.radiation_dampings["Heave"],
                      0.0,
                      atol=1e-3 * sphere.volume * problem.rho)
    assert np.isclose(result.radiation_dampings["Surge"],
                      0.0,
                      atol=1e-3 * sphere.volume * problem.rho)

    problem = RadiationProblem(body=sphere,
                               radiating_dof="Surge",
                               free_surface=np.infty,
                               sea_bottom=-np.infty)
    result = solver.solve(problem)
    assert np.isclose(result.added_masses["Surge"],
                      2194,
                      atol=1e-3 * sphere.volume * problem.rho)
    assert np.isclose(result.added_masses["Heave"],
                      0.0,
                      atol=1e-3 * sphere.volume * problem.rho)
    assert np.isclose(result.radiation_dampings["Surge"],
                      0.0,
                      atol=1e-3 * sphere.volume * problem.rho)
    assert np.isclose(result.radiation_dampings["Heave"],
                      0.0,
                      atol=1e-3 * sphere.volume * problem.rho)
Пример #11
0
def problems_from_dataset(dataset: xr.Dataset,
                          bodies: Sequence[FloatingBody],
                          ) -> List[LinearPotentialFlowProblem]:
    """Generate a list of problems from a test matrix.

    Parameters
    ----------
    dataset : xarray Dataset
        Test matrix containing the problems parameters.
    bodies : list of FloatingBody
        The bodies on which the computations of the test matrix will be applied.
        They should all have different names.

    Returns
    -------
    list of LinearPotentialFlowProblem
    """
    assert len(list(set(body.name for body in bodies))) == len(bodies), \
        "All bodies should have different names."

    dataset = _unsqueeze_dimensions(dataset)

    omega_range = dataset['omega'].data if 'omega' in dataset else [_default_parameters['omega']]
    water_depth_range = dataset['water_depth'].data if 'water_depth' in dataset else [_default_parameters['water_depth']]
    rho_range = dataset['rho'].data if 'rho' in dataset else [_default_parameters['rho']]

    wave_direction_range = dataset['wave_direction'].data if 'wave_direction' in dataset else None
    radiating_dofs = dataset['radiating_dof'].data.astype(object) if 'radiating_dof' in dataset else None
    # astype(object) is meant to convert Numpy internal string type numpy.str_ to Python general string type.

    if 'body_name' in dataset:
        assert set(dataset['body_name'].data) <= {body.name for body in bodies}, \
            "Some body named in the dataset was not given as argument to `problems_from_dataset`."
        body_range = {body.name: body for body in bodies if body.name in dataset['body_name'].data}
        # Only the bodies listed in the dataset have been kept
    else:
        body_range = {body.name: body for body in bodies}

    problems = []
    if wave_direction_range is not None:
        for omega, wave_direction, water_depth, body_name, rho \
                in product(omega_range, wave_direction_range, water_depth_range, body_range, rho_range):
            problems.append(
                DiffractionProblem(body=body_range[body_name], omega=omega,
                                   wave_direction=wave_direction, sea_bottom=-water_depth, rho=rho)
            )

    if radiating_dofs is not None:
        for omega, radiating_dof, water_depth, body_name, rho \
                in product(omega_range, radiating_dofs, water_depth_range, body_range, rho_range):
            problems.append(
                RadiationProblem(body=body_range[body_name], omega=omega,
                                 radiating_dof=radiating_dof, sea_bottom=-water_depth, rho=rho)
            )

    return sorted(problems)
Пример #12
0
def test_multibody():
    """Compare with Nemoh 2.0 for two bodies."""
    sphere = Sphere(radius=1.0, ntheta=5, nphi=20)
    sphere.translate_z(-2.0)
    sphere.add_translation_dof(direction=(1, 0, 0), name="Surge")
    sphere.add_translation_dof(direction=(0, 0, 1), name="Heave")

    cylinder = HorizontalCylinder(length=5.0,
                                  radius=1.0,
                                  nx=10,
                                  nr=1,
                                  ntheta=10)
    cylinder.translate([+1.5, 3.0, -3.0])
    cylinder.add_translation_dof(direction=(1, 0, 0), name="Surge")
    cylinder.add_translation_dof(direction=(0, 0, 1), name="Heave")

    both = cylinder + sphere
    total_volume = cylinder.volume + sphere.volume
    # both.show()

    problems = [
        RadiationProblem(body=both, radiating_dof=dof, omega=1.0)
        for dof in both.dofs
    ]
    problems += [DiffractionProblem(body=both, wave_direction=0.0, omega=1.0)]
    results = [solver.solve(problem) for problem in problems]
    data = assemble_dataset(results)

    data_from_nemoh_2 = np.array([
        [
            3961.86548, 50.0367661, -3.32347107, 6.36901855E-02, 172.704819,
            19.2018471, -5.67303181, -2.98873377
        ],
        [
            -3.08301544, 5.72392941E-02, 14522.1689, 271.796814, 128.413834,
            6.03351116, 427.167358, 64.1587067
        ],
        [
            161.125534, 17.8332844, 126.392113, 5.88006783, 2242.47412,
            7.17850924, 1.29002571, 0.393169671
        ],
        [
            -5.02560759, -2.75930357, 419.927460, 63.3179016, 1.23501396,
            0.416424811, 2341.57593, 15.8266096
        ],
    ])

    dofs_names = list(both.dofs.keys())
    assert np.allclose(data['added_mass'].sel(
        omega=1.0, radiating_dof=dofs_names, influenced_dof=dofs_names).values,
                       data_from_nemoh_2[:, ::2],
                       atol=1e-3 * total_volume * problems[0].rho)
    assert np.allclose(data['radiation_damping'].sel(
        omega=1.0, radiating_dof=dofs_names, influenced_dof=dofs_names).values,
                       data_from_nemoh_2[:, 1::2],
                       atol=1e-3 * total_volume * problems[0].rho)
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)
Пример #14
0
def test_results():
    assert isinstance(LinearPotentialFlowProblem().make_results_container(), LinearPotentialFlowResult)

    pb = DiffractionProblem(g=10, rho=1023, free_surface=np.infty)
    res = DiffractionResult(pb)
    assert res.g == pb.g == 10
    assert "DiffractionResult" in str(res)

    pb = RadiationProblem(g=10, rho=1023, free_surface=np.infty)
    res = RadiationResult(pb)
    assert res.g == pb.g == 10
    assert "RadiationResult" in str(res)
Пример #15
0
def test_radiation_problem(caplog):
    sphere = Sphere(radius=1.0, ntheta=20, nphi=40, clip_free_surface=True)

    # with pytest.raises(ValueError):
    #     RadiationProblem(body=sphere)

    sphere.add_translation_dof(direction=(0, 0, 1), name="Heave")
    pb = RadiationProblem(body=sphere)
    assert len(pb.boundary_condition) == sphere.mesh.nb_faces

    sphere.add_translation_dof(direction=(1, 0, 0), name="Surge")
    pb2 = RadiationProblem(body=sphere, radiating_dof="Heave")
    assert np.all(pb.boundary_condition == pb2.boundary_condition)

    assert "RadiationProblem" in str(RadiationProblem(g=10, rho=1025, free_surface=np.infty))

    res = pb.make_results_container()
    assert isinstance(res, RadiationResult)
    assert 'forces' not in res.__dict__
    assert res.added_masses == {}
    assert res.radiation_dampings == {}
def test_horizontal_cylinder(depth):
    cylinder = HorizontalCylinder(length=10.0, radius=1.0, reflection_symmetry=False, translation_symmetry=False, nr=2, ntheta=10, nx=10)
    assert isinstance(cylinder.mesh, Mesh)
    cylinder.translate_z(-3.0)
    cylinder.add_translation_dof(direction=(0, 0, 1), name="Heave")
    problem = RadiationProblem(body=cylinder, omega=1.0, sea_bottom=-depth)
    result1 = solver_with_sym.solve(problem)

    trans_cylinder = HorizontalCylinder(length=10.0, radius=1.0, reflection_symmetry=False, translation_symmetry=True, nr=2, ntheta=10, nx=10)
    assert isinstance(trans_cylinder.mesh, CollectionOfMeshes)
    assert isinstance(trans_cylinder.mesh[0], TranslationalSymmetricMesh)
    trans_cylinder.translate_z(-3.0)
    trans_cylinder.add_translation_dof(direction=(0, 0, 1), name="Heave")
    problem = RadiationProblem(body=trans_cylinder, omega=1.0, sea_bottom=-depth)
    result2 = solver_with_sym.solve(problem)

    # S, V = solver_with_sym.build_matrices(trans_cylinder.mesh, trans_cylinder.mesh)
    # S.plot_shape()

    assert np.isclose(result1.added_masses["Heave"], result2.added_masses["Heave"], atol=1e-4*cylinder.volume*problem.rho)
    assert np.isclose(result1.radiation_dampings["Heave"], result2.radiation_dampings["Heave"], atol=1e-4*cylinder.volume*problem.rho)
Пример #17
0
def test_assemble_dataset():
    body = Sphere(center=(0, 0, -4), name="sphere")
    body.add_translation_dof(name="Heave")

    pb_1 = DiffractionProblem(body=body, wave_direction=1.0, omega=1.0)
    res_1 = solver.solve(pb_1)
    ds1 = assemble_dataset([res_1])
    assert "Froude_Krylov_force" in ds1

    pb_2 = RadiationProblem(body=body, radiating_dof="Heave", omega=1.0)
    res_2 = solver.solve(pb_2)
    ds2 = assemble_dataset([res_2])
    assert "added_mass" in ds2

    ds12 = assemble_dataset([res_1, res_2])
    assert "Froude_Krylov_force" in ds12
    assert "added_mass" in ds12
Пример #18
0
def test_custom_linear_solver():
    """Solve a simple problem with a custom linear solver."""
    problem = RadiationProblem(body=sphere, omega=1.0, sea_bottom=-np.infty)

    reference_solver = BEMSolver(
        engine=BasicMatrixEngine(linear_solver="gmres", matrix_cache_size=0))
    reference_result = reference_solver.solve(problem)

    def my_linear_solver(A, b):
        """A dumb solver for testing."""
        return np.linalg.inv(A) @ b

    my_bem_solver = BEMSolver(engine=BasicMatrixEngine(
        linear_solver=my_linear_solver, matrix_cache_size=0))
    assert 'my_linear_solver' in my_bem_solver.exportable_settings[
        'linear_solver']

    result = my_bem_solver.solve(problem)
    assert np.isclose(reference_result.added_masses['Surge'],
                      result.added_masses['Surge'])
Пример #19
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)
Пример #20
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
Пример #21
0
def problems_from_dataset(dataset: xr.Dataset,
                          bodies: Union[FloatingBody, Sequence[FloatingBody]],
                          ) -> List[LinearPotentialFlowProblem]:
    """Generate a list of problems from a test matrix.

    Parameters
    ----------
    dataset : xarray Dataset
        Test matrix containing the problems parameters.
    bodies : FloatingBody or list of FloatingBody
        The bodies on which the computations of the test matrix will be applied.
        They should all have different names.

    Returns
    -------
    list of LinearPotentialFlowProblem

    Raises
    ------
    ValueError
        if required fields are missing in the dataset
    """
    if isinstance(bodies, FloatingBody):
        bodies = [bodies]

    # SANITY CHECKS
    assert len(list(set(body.name for body in bodies))) == len(bodies), \
        "All bodies should have different names."

    # Warn user in case of key with unrecognized name (e.g. mispells)
    keys_in_dataset = set(dataset.keys()) | set(dataset.coords.keys())
    accepted_keys = {'wave_direction', 'radiating_dof', 'body_name', 'omega', 'water_depth', 'rho', 'g'}
    unrecognized_keys = keys_in_dataset.difference(accepted_keys)
    if len(unrecognized_keys) > 0:
        LOG.warning(f"Unrecognized key(s) in dataset: {unrecognized_keys}")

    if ("radiating_dof" not in keys_in_dataset) and ("wave_direction" not in keys_in_dataset):
        raise ValueError("Neither 'radiating_dof' nor 'wave_direction' has been provided in the dataset. "
                "No linear potential flow problem can be inferred.")
    # END SANITY CHECKS

    dataset = _unsqueeze_dimensions(dataset)

    omega_range = dataset['omega'].data if 'omega' in dataset else [_default_parameters['omega']]
    water_depth_range = dataset['water_depth'].data if 'water_depth' in dataset else [_default_parameters['water_depth']]
    rho_range = dataset['rho'].data if 'rho' in dataset else [_default_parameters['rho']]
    g_range = dataset['g'].data if 'g' in dataset else [_default_parameters['g']]

    wave_direction_range = dataset['wave_direction'].data if 'wave_direction' in dataset else None
    radiating_dofs = dataset['radiating_dof'].data.astype(object) if 'radiating_dof' in dataset else None
    # astype(object) is meant to convert Numpy internal string type numpy.str_ to Python general string type.

    if 'body_name' in dataset:
        assert set(dataset['body_name'].data) <= {body.name for body in bodies}, \
            "Some body named in the dataset was not given as argument to `problems_from_dataset`."
        body_range = {body.name: body for body in bodies if body.name in dataset['body_name'].data}
        # Only the bodies listed in the dataset have been kept
    else:
        body_range = {body.name: body for body in bodies}

    problems = []
    if wave_direction_range is not None:
        for omega, wave_direction, water_depth, body_name, rho, g \
                in product(omega_range, wave_direction_range, water_depth_range, body_range, rho_range, g_range):
            problems.append(
                DiffractionProblem(body=body_range[body_name], omega=omega,
                                   wave_direction=wave_direction, sea_bottom=-water_depth, rho=rho, g=g)
            )

    if radiating_dofs is not None:
        for omega, radiating_dof, water_depth, body_name, rho, g \
                in product(omega_range, radiating_dofs, water_depth_range, body_range, rho_range, g_range):
            problems.append(
                RadiationProblem(body=body_range[body_name], omega=omega,
                                 radiating_dof=radiating_dof, sea_bottom=-water_depth, rho=rho, g=g)
            )

    return sorted(problems)