def test_potential():
    sphere = cpt.Sphere(radius=1.0, ntheta=3, nphi=12, clip_free_surface=True)
    sphere.add_translation_dof(name="Heave")
    solver = cpt.BEMSolver()
    result = solver.solve(cpt.RadiationProblem(body=sphere, omega=1.0), keep_details=True)
    free_surface = cpt.FreeSurface(x_range=(-100, 100), nx=5, y_range=(-100, 100), ny=5)
    eta = solver.get_potential_on_mesh(result, free_surface.mesh, chunk_size=3)
Пример #2
0
def test_resolution():
    cylinder = cpt.HorizontalCylinder(
        length=5.0,
        radius=1.0,
        center=(0, 0, -2),
        nr=2,
        nx=10,
        ntheta=5,
    )
    # cylinder.show()
    cylinder.add_translation_dof(name="Heave")

    test_matrix = xr.Dataset(coords={
        "omega": np.linspace(0.5, 3.0, 2),
        "radiating_dof": ["Heave"],
    })

    solver = cpt.BEMSolver()

    cylinder.mesh.compute_quadrature(quadpy.quadrilateral.sommariva_01())
    data_1 = solver.fill_dataset(test_matrix, [cylinder], mesh=True)

    cylinder.mesh.compute_quadrature(quadpy.quadrilateral.sommariva_03())
    data_3 = solver.fill_dataset(test_matrix, [cylinder], mesh=True)

    assert data_1['quadrature_method'] == "Sommariva 1"
    assert data_3['quadrature_method'] == "Sommariva 3"
    assert np.allclose(data_1["added_mass"].data,
                       data_3["added_mass"].data,
                       rtol=1e-2)
Пример #3
0
def test_from_meshio_pygmsh(generate_pygmsh, tmp_path):
    mesh, vol_exp = generate_pygmsh()
    fb = cpt.FloatingBody.from_meshio(mesh)
    fb.mesh.heal_mesh()
    fb.keep_immersed_part()

    vol = fb.mesh.volume
    assert pytest.approx(vol_exp, rel=1e-1) == vol

    fb.add_translation_dof((0, 0, 1))

    test_matrix = xr.Dataset(
        coords={
            'rho': rho_water,
            'water_depth': [np.infty],
            'omega': omega,
            'wave_direction': 0,
            'radiating_dof': list(fb.dofs.keys()),
        })

    solver = cpt.BEMSolver()
    data = solver.fill_dataset(test_matrix,
                               bodies=[fb],
                               hydrostatics=True,
                               mesh=True,
                               wavelength=True,
                               wavenumber=True)
Пример #4
0
    def evaluate_column_modal_response_amplitudes(self):
        """

        """
        bem_solver = cpt.BEMSolver()
        problems = [
            cpt.RadiationProblem(sea_bottom=self.water_depth,
                                 body=self.column_mesh,
                                 radiating_dof=dof,
                                 omega=omega) for dof in self.column_mesh.dofs
            for omega in self.wave_frequencies
        ]
        problems += [
            cpt.DiffractionProblem(sea_bottom=self.water_depth,
                                   body=self.column_mesh,
                                   wave_direction=self.wave_direction,
                                   omega=omega)
            for omega in self.wave_frequencies
        ]
        results = [bem_solver.solve(problem) for problem in problems]
        result_data = cpt.assemble_dataset(results)
        modal_response_amplitude_data = cpt.post_pro.rao(
            result_data, wave_direction=self.wave_direction)

        self.result_data = result_data
        self.modal_response_amplitude_data = modal_response_amplitude_data
def test_fill_dataset_with_kochin_functions():
    sphere = cpt.Sphere(clip_free_surface=True)
    sphere.add_translation_dof(name="Heave")
    solver = cpt.BEMSolver()

    test_matrix = xr.Dataset(coords={
        'omega': [1.0],
        'theta': [0.0, pi / 2],
        'radiating_dof': ["Heave"],
    })
    ds = solver.fill_dataset(test_matrix, [sphere])
    assert 'theta' in ds.coords
    assert 'kochin' in ds
    assert 'kochin_diffraction' not in ds

    # Because of the symmetries of the body
    assert np.isclose(ds['kochin'].sel(radiating_dof="Heave", theta=0.0),
                      ds['kochin'].sel(radiating_dof="Heave", theta=pi / 2))

    test_matrix = xr.Dataset(
        coords={
            'omega': [1.0],
            'radiating_dof': ["Heave"],
            'wave_direction': [-pi / 2, 0.0],
            'theta': [0.0, pi / 2],
        })
    ds = solver.fill_dataset(test_matrix, [sphere])
    assert 'theta' in ds.coords
    assert 'kochin' in ds
    assert 'kochin_diffraction' in ds

    # Because of the symmetries of the body
    assert np.isclose(
        ds['kochin_diffraction'].sel(wave_direction=-pi / 2, theta=0.0),
        ds['kochin_diffraction'].sel(wave_direction=0.0, theta=pi / 2))
Пример #6
0
def capy_solver(wCapy, CoG, headings,ncFName,wDes, body_name, depth, density,
                combo,additional_dofs_dir):
    '''
    call Capytaine for a given mesh, frequency range and wave headings
    This function is modified from David Ogden's work 
    (see https://github.com/mattEhall/FrequencyDomain/blob/b89dd4f4a732fbe4afde56efe2b52c3e32e22d53/FrequencyDomain.py#L842 for the original function).
    
    save the results to a file in Network Common Data Form.

    Returns
    -------
    None
    '''
    problems = xr.Dataset(coords={
        'omega': wCapy,
        'wave_direction': headings,
        'radiating_dof': list(combo.dofs),
        'water_depth': [depth],
        'rho': [density],
        })
    
    solver = cpt.BEMSolver()
    capyData = solver.fill_dataset(problems, [combo], hydrostatics=False)
    
    # # add kochin diffraction results
    # kochin = cpt.io.xarray.kochin_data_array(results, headings)
    # capyData.update(kochin)

    # save to .nc file
    cpt.io.xarray.separate_complex_values(capyData).to_netcdf(ncFName, encoding={'radiating_dof': {'dtype': 'U'}, 'influenced_dof': {'dtype': 'U'}})

    print('\nCapytaine call complete. Data saved to \n' + ncFName +'\n\n')

    return
Пример #7
0
    def run_bem(self, freq=None, wave_dirs=None, post_proc=True):
        
        if freq is None:
            freq = np.arange(1, self.params['num_freq']+1)*self.params['f0']
        assert isinstance(freq, np.ndarray)
        
        if wave_dirs is None:
            wave_dirs = [0]
        else:
            raise NotImplementedError

        assert isinstance(wave_dirs, list)      # TODO check list contains floats
        
        
        solver = cpy.BEMSolver()                # TODO: enable setting this
        test_matrix = xr.Dataset(coords={
            'rho': 1e3,                         # TODO: enable setting this
            'water_depth': [np.infty],          # TODO: enable setting this
            'omega': freq*2*np.pi,
            'wave_direction': wave_dirs,
            'radiating_dof': list(self.fb.dofs.keys()),
            })
        
        data = solver.fill_dataset(test_matrix, [self.fb],
                                   hydrostatics=True,
                                   mesh=True,
                                   wavelength=True,
                                   wavenumber=True)

        data['freq'] = data.omega / (2 * np.pi)
        data['freq'].attrs['units'] = 'Hz'
        data = data.set_coords('freq')

        data['T'] = 1 / data.freq
        data['T'].attrs['units'] = 's'
        data = data.set_coords('T')
        
        self.hydro = data
        self.hydro['displaced_volume'] = self.hsa.hs_data['disp_volume'] # TODO - redundant probably remove
        
        if True:                                                            # TODO
            # Infinite frequency added mass
            inf_test_matrix = xr.Dataset(coords={
                                        'rho': 1e3,                         # TODO
                                        'water_depth': [np.infty],
                                        'omega': [np.infty],
                                        'radiating_dof': list(self.fb.dofs.keys()),
                                        })
            inf_data = solver.fill_dataset(inf_test_matrix, [self.fb])
            self.inf_data = inf_data
            self.hydro['Ainf'] = inf_data.added_mass[0,:,:]
            
        if post_proc:
            self.__post_proc_bem__()
Пример #8
0
def evaluate_buoy_forces(buoy_object):
    # Set up radiation and diffraction problems
    problems = [cpt.RadiationProblem(body=buoy_object, radiating_dof=degree_of_freedom, omega=omega)
                for omega in omega_range]
    problems += [cpt.DiffractionProblem(omega=omega, body=buoy_object, wave_direction=wave_direction)
                 for omega in omega_range]

    # Solve each matrix problem
    solver = cpt.BEMSolver(engine=cpt.HierarchicalToeplitzMatrixEngine())
    results = [solver.solve(pb) for pb in sorted(problems)]

    return cpt.assemble_dataset(results)
Пример #9
0
def solve_sim(sims, omegas):
    """Solve for all the directions of a single period
    """
    bem_solver = cpt.BEMSolver()
    i_sim = 0
    for j, omega in enumerate(omegas):
        radiation = [
            bem_solver.solve(sims[i_sim + i]) for i in range(len(DOFS))]
        i_sim += len(DOFS)
        for i, d in enumerate(DIRS):
            results = radiation[:]
            results.append(bem_solver.solve(sims[i_sim]))
            i_sim += 1
            dataset = cpt.assemble_dataset(results)
            yield i, j, cpt.post_pro.rao(dataset, wave_direction=d)
    """
Пример #10
0
def test_xarray_dataset_with_more_data():
    # Store some mesh data when several bodies in dataset
    bodies = [
        cpt.Sphere(radius=1, ntheta=3, nphi=3, name="sphere_1"),
        cpt.Sphere(radius=2, ntheta=5, nphi=3, name="sphere_2"),
        cpt.Sphere(radius=3, ntheta=7, nphi=3, name="sphere_3"),
    ]
    for body in bodies:
        body.keep_immersed_part()
        body.add_translation_dof(name="Heave")

    problems = [cpt.RadiationProblem(body=b, radiating_dof="Heave", omega=1.0) for b in bodies]
    results = cpt.BEMSolver().solve_all(problems)

    ds = cpt.assemble_dataset(results, mesh=True)
    assert 'nb_faces' in ds.coords
    assert set(ds.coords['nb_faces'].values) == set([b.mesh.nb_faces for b in bodies])
Пример #11
0
def test_showmatplotlib_with_colors(tmp_path):
    cylinder = cpt.HorizontalCylinder(
        length=5.0, radius=1.0, center=(0, 0, -2), nr=5, nx=20, ntheta=20,
    )

    problem = cpt.DiffractionProblem(body=cylinder, wave_direction=0.0, omega=1.0)
    solver = cpt.BEMSolver()
    results = solver.solve(problem)

    cylinder.show_matplotlib(saveas=tmp_path / "showmpl.png")

    fig = plt.figure()
    ax = fig.add_subplot(111,projection='3d')
    import matplotlib.cm as cm
    colormap = cm.get_cmap('cividis')
    cylinder.show_matplotlib(color_field=np.abs(results.potential),
                             ax=ax, cbar_label=r'$\phi (m^2/s)$')
    ax.set_title('Potential distribution')
    plt.savefig(tmp_path / "showmpl_with_color_field.png")
Пример #12
0
    def solve_tube_hydrodynamics(self):
        """

        """
        #print('\tSolving tube hydrodynamics.')

        solver = cpt.BEMSolver()
        problems = [
            cpt.RadiationProblem(omega=omega,
                                 body=self.tube,
                                 radiating_dof=dof,
                                 rho=self.rho,
                                 sea_bottom=self.water_depth)
            for dof in self.tube.dofs for omega in self.wave_frequencies
        ]
        problems += [
            cpt.DiffractionProblem(omega=omega,
                                   body=self.tube,
                                   wave_direction=self.wave_direction,
                                   rho=self.rho,
                                   sea_bottom=self.water_depth)
            for omega in self.wave_frequencies
        ]
        results = solver.solve_all(problems, keep_details=False)
        result_data = cpt.assemble_dataset(results)

        if self.save_results:
            from capytaine.io.xarray import separate_complex_values
            save_file_name = 'flexible_tube_results__rs_le_zs__{:.2f}_{:.1f}_{:.2f}__with_{}_cells.nc' \
                                .format(self.static_radius, self.length, self.submergence, self.tube.mesh.nb_faces)
            separate_complex_values(result_data).to_netcdf(
                save_file_name,
                encoding={
                    'radiating_dof': {
                        'dtype': 'U'
                    },
                    'influenced_dof': {
                        'dtype': 'U'
                    }
                })

        self.result_data = result_data
    def solve_beam_hydrodynamics(self, save_results):
        """

        """
        bem_solver = cpt.BEMSolver()
        problems = [
            cpt.RadiationProblem(sea_bottom=self.water_depth,
                                 body=self.beam_mesh,
                                 radiating_dof=dof,
                                 omega=omega) for dof in self.beam_mesh.dofs
            for omega in self.wave_frequencies
        ]
        problems += [
            cpt.DiffractionProblem(sea_bottom=self.water_depth,
                                   body=self.beam_mesh,
                                   wave_direction=self.wave_direction,
                                   omega=omega)
            for omega in self.wave_frequencies
        ]
        results = [bem_solver.solve(problem) for problem in problems]
        result_data = cpt.assemble_dataset(results)

        if save_results:
            from capytaine.io.xarray import separate_complex_values
            separate_complex_values(result_data).to_netcdf(
                'beam_hydrodynamics_results.nc',
                encoding={
                    'radiating_dof': {
                        'dtype': 'U'
                    },
                    'influenced_dof': {
                        'dtype': 'U'
                    }
                })

        return result_data
Пример #14
0
def call_capy(meshFName,
              wCapy,
              CoG=([0, 0, 0], ),
              headings=[0.0],
              ncFName=None,
              wDes=None,
              body_name=('', ),
              depth=np.infty,
              density=1025.0):
    '''
    call Capytaine for a given mesh, frequency range and wave headings
    This function is modified from David Ogden's work 
    (see https://github.com/mattEhall/FrequencyDomain/blob/b89dd4f4a732fbe4afde56efe2b52c3e32e22d53/FrequencyDomain.py#L842 for the original function).
    
    May be called with multiple bodies (automatically implements B2B). In this case, 
    the meshFName, CoG, body_name should be a tuple of the values for each body
    
    Parameters
    ----------
    meshFName : tuple of strings
        Tuple containing a string for the path to each body's hydrodynamic mesh.
        mesh must be cropped at waterline (OXY plane) and have no lid
    wCapy: array
        array of frequency points to be computed by Capytaine
    CoG: tuple of lists
        tuple contains a 3x1 list of each body's CoG
    headings: list
        list of wave headings to compute
    ncFName: str
        name of .nc file
    wDes: array
        array of desired frequency points
        (for interpolation of wCapy-based Capytaine data)
    body_name: tuple of strings
        Tuple containing strings. Strings are the names of each body. 
        Prevent the body name from being a long file path
    depth: float
        Water depth. Should be positive downwards. Use decimal value to prevent 
        Capytaine outputting int32 types. Default is -np.infty
    density: float
        Water density. Use decimal value to prevent Capytaine outputting int32 
        types. Default 1025.0

    Returns
    -------
    hydrodynamic coefficients; as computed or interpolated

    Notes
    -----
    TODO:
    - expand to generalized body modes using an additional_dof parameter
    '''

    # Create Capytaine floating bodies form each mesh file and calculate
    # additional body properties (cg, dofs, hydrostatics).
    # body_dict = {}
    # for i in np.arange(0, len(meshFName)):
    #     body_dict["body{0}".format(i)] = cpt.FloatingBody.from_file(meshFName[i])
    #     body_dict["body{0}".format(i)].center_of_mass = CoG[i]
    #     body_dict["body{0}".format(i)].keep_immersed_part()
    #     if body_name != '':
    #         body_dict["body{0}".format(i)].name = body_name[i]
    #     body_dict["body{0}".format(i)].add_all_rigid_body_dofs()
    # bodies = list(body_dict.values())

    bodies = []
    for i in np.arange(0, len(meshFName)):
        bodies.append(cpt.FloatingBody.from_file(meshFName[i]))
        bodies[i].center_of_mass = CoG[i]
        bodies[i].keep_immersed_part()
        if body_name[i] != '':
            bodies[i].name = body_name[i]
        bodies[i].add_all_rigid_body_dofs()

    # output hydrostatics data to KH.dat and Hydrostatics.dat files
    path, tmp = os.path.split(ncFName)
    path += os.path.sep
    body_hydrostatics(bodies, path)

    # add gbm dofs here or before

    # combine all bodies to account for B2B interactions
    combo = bodies[0]
    for i in np.arange(1, len(bodies), 1):
        combo += bodies[i]

    # call Capytaine solver
    print(f'\n-------------------------------\n'
          f'Calling Capytaine BEM solver...\n'
          f'-------------------------------\n'
          f'mesh = {meshFName}\n'
          f'w range = {wCapy[0]:.3f} - {wCapy[-1]:.3f} rad/s\n'
          f'dw = {(wCapy[1]-wCapy[0]):.3f} rad/s\n'
          f'no of headings = {len(headings)}\n'
          # f'no of radiation & diffraction problems = {len(problems)}\n'
          f'-------------------------------\n')

    #    Create a dataset of parameters.
    #    'fill_dataset()' automatically creates problems and solves them.
    problems = xr.Dataset(
        coords={
            'omega': wCapy,
            'wave_direction': headings,
            'radiating_dof': list(combo.dofs),
            'water_depth': [depth],
            'rho': [density],
        })

    # define default Capytaine solver
    solver = cpt.BEMSolver()

    # Solve datset of problems. Hydrostatics off because they're saved
    # externally in Nemoh format
    capyData = solver.fill_dataset(problems, [combo], hydrostatics=False)

    # add kochin diffraction results
    # kochin = cpt.io.xarray.kochin_data_array(results, headings)
    # capyData.update(kochin)

    # use to test read_capytaine_v1() ability to catch and reorder dofs
    # sorted_idofs = ["Heave", "Sway", "Pitch", "Surge", "Yaw", "Roll"]
    # sorted_rdofs = ["Sway", "Heave", "Surge", "Roll", "Pitch", "Yaw"]
    # capyData = capyData.sel(radiating_dof=sorted_idofs, influenced_dof=sorted_rdofs)

    # save to .nc file
    cpt.io.xarray.separate_complex_values(capyData).to_netcdf(ncFName)

    print('\n\nCapytaine call complete. Data saved to \n' + ncFName)

    return capyData, problems
Пример #15
0
                        # Below, we take a rough approximation.
                        S[j, i] = -area / (4 * pi) * 3
                        K[j, i] = -area / (4 * pi) * 3

            if mesh1 is mesh2:
                for i in range(mesh1.nb_faces):
                    K[i, i] += 1 / 2

            return S, K

        else:
            raise NotImplementedError


# Define a solver using the Green function above.
solver = cpt.BEMSolver(green_function=MyGreenFunction())

# Example of a problem
sphere = cpt.Sphere(
    radius=1.0,  # Dimension
    center=(0, 0, -2),  # Position
    nphi=4,
    ntheta=4,  # Fineness of the mesh
)
sphere.add_translation_dof(name="Heave")
problem = cpt.RadiationProblem(body=sphere,
                               free_surface=np.infty,
                               sea_bottom=-np.infty,
                               radiating_dof='Heave')

result = solver.solve(problem)
Пример #16
0
                        # Below, we take a rough approximation.
                        S[j, i] = -area / (4 * pi) * 3
                        K[j, i] = -area / (4 * pi) * 3

            if mesh1 is mesh2:
                for i in range(mesh1.nb_faces):
                    K[i, i] += 1 / 2

            return S, K

        else:
            raise NotImplementedError


# Define a solver using the Green function above.
solver = cpt.BEMSolver(green_function=MyAbstractGreenFunction())

# Example of a problem
sphere = cpt.Sphere(
    radius=1.0,  # Dimension
    center=(0, 0, -2),  # Position
    nphi=4,
    ntheta=4,  # Fineness of the mesh
)
sphere.add_translation_dof(name="Heave")
problem = cpt.RadiationProblem(body=sphere,
                               free_surface=np.infty,
                               sea_bottom=-np.infty,
                               radiating_dof='Heave')

result = solver.solve(problem)
Пример #17
0
    def solve_hydrodynamics(self):
        if MPI:
            n_cores = MPI.COMM_WORLD.Get_size()
            max_cores = min(n_cores, self.max_cores)
            rank = MPI.COMM_WORLD.Get_rank()
        else:
            n_cores = 1
            max_cores = 1
            rank = 0

        solver = cpt.BEMSolver()
        problems = self.problems
        results = []

        if rank == 0:
            idx = 0
            ldx = len(problems)
            for pb in problems:
                idx += 1
                pdx = float(idx)/float(ldx)*100.0
                result = solver.solve(pb)
                r = result.records
                results.append(r)
                print(
                    '%4.0f percent completed.' % pdx,
                    end="\r", flush=True
                )
        else:
            for pb in problems:
                result = solver.solve(pb)
                r = result.records
                results.append(r)

        if MPI:
            MPI.COMM_WORLD.barrier()
            results = MPI.COMM_WORLD.gather(results, root=0)
            
        # Store data
        if rank == 0:
            if MPI:
                results = [item for it in results for item in it]
            results = [item for it in results for item in it]
            
            omega_range = self.omega_range
            if self.zero_frequency:
                omega_range = np.append(0.0, omega_range)
            if self.inf_frequency:
                omega_range = np.append(omega_range, np.inf)
            wave_dir_range = self.wave_dir_range
            dofs = ['Surge', 'Sway', 'Heave', 'Roll', 'Pitch', 'Yaw']
            
            rad_dims = ('omega', 'radiating_dof', 'influenced_dof')
            rad_dimz = np.zeros((omega_range.shape[0], len(dofs), len(dofs)), dtype=float)
            RadiationResults = xr.Dataset(
                data_vars = {
                    'added_mass': (rad_dims, rad_dimz),
                    'radiation_damping': (rad_dims, rad_dimz)
                },
                coords = {
                    rad_dims[0]: omega_range,
                    rad_dims[1]: dofs,
                    rad_dims[2]: dofs
                }
            )
            
            dif_dims = ('omega', 'wave_direction', 'influenced_dof')
            dif_dimz = np.zeros((omega_range.shape[0], wave_dir_range.shape[0], len(dofs)), dtype=float)
            DiffractionResults = xr.Dataset(
                data_vars = {
                    'diffraction_force': (dif_dims, dif_dimz),
                    'Froude_Krylov_force': (dif_dims, dif_dimz)
                },
                coords = {
                    dif_dims[0]: omega_range,
                    dif_dims[1]: wave_dir_range,
                    dif_dims[2]: dofs
                }
            )
            
            for case in results:
                if 'radiating_dof' in case:
                    RadiationResults['added_mass'] = xr.where(
                        (RadiationResults.coords['omega'] == case['omega'])
                        & (RadiationResults.coords['radiating_dof'] == case['radiating_dof'])
                        & (RadiationResults.coords['influenced_dof'] == case['influenced_dof']),
                        case['added_mass'],
                        RadiationResults['added_mass']
                    )
                    RadiationResults['radiation_damping'] = xr.where(
                        (RadiationResults.coords['omega'] == case['omega'])
                        & (RadiationResults.coords['radiating_dof'] == case['radiating_dof'])
                        & (RadiationResults.coords['influenced_dof'] == case['influenced_dof']),
                        case['radiation_damping'],
                        RadiationResults['radiation_damping']
                    )
                    
                elif 'wave_direction' in case:
                    DiffractionResults['diffraction_force'] = xr.where(
                        (DiffractionResults.coords['omega'] == case['omega'])
                        & (DiffractionResults.coords['wave_direction'] == case['wave_direction'])
                        & (DiffractionResults.coords['influenced_dof'] == case['influenced_dof']),
                        case['diffraction_force'],
                        DiffractionResults['diffraction_force']
                    )
                    DiffractionResults['Froude_Krylov_force'] = xr.where(
                        (DiffractionResults.coords['omega'] == case['omega'])
                        & (DiffractionResults.coords['wave_direction'] == case['wave_direction'])
                        & (DiffractionResults.coords['influenced_dof'] == case['influenced_dof']),
                        case['Froude_Krylov_force'],
                        DiffractionResults['Froude_Krylov_force']
                    )
            
            self._RadiationResults = RadiationResults
            self._DiffractionResults = DiffractionResults
            
        else:
            self._RadiationResults = []
            self._DiffractionResults = []
Пример #18
0
    return 0.1*(-(z+1)**2 + 16)

# Generate the mesh and display it with VTK.
buoy = cpt.FloatingBody(
    cpt.AxialSymmetricMesh.from_profile(shape, z_range=np.linspace(-5, 0, 30), nphi=40)
)
buoy.add_translation_dof(name="Heave")
buoy.show()

# Set up problems
omega_range = np.linspace(0.1, 5.0, 60)
problems = [cpt.RadiationProblem(body=buoy, radiating_dof='Heave', omega=omega)
            for omega in omega_range]

# Solve the problems using the axial symmetry
solver = cpt.BEMSolver(engine=cpt.HierarchicalToeplitzMatrixEngine())
results = [solver.solve(pb) for pb in sorted(problems)]
dataset = capytaine.io.xarray.assemble_dataset(results)

# Plot results
import matplotlib.pyplot as plt
plt.figure()
plt.plot(
    omega_range,
    dataset['added_mass'].sel(radiating_dof='Heave',
                              influenced_dof='Heave'),
    label="Added mass",
)
plt.plot(
    omega_range,
    dataset['radiation_damping'].sel(radiating_dof='Heave',
Пример #19
0
def call_capy(meshFName,
              wCapy,
              CoG=([0, 0, 0], ),
              headings=[0.0],
              ncFName=None,
              wDes=None,
              body_name=('', ),
              depth=np.infty,
              density=1025.0,
              additional_dofs_dir=None):
    '''
    call Capytaine for a given mesh, frequency range and wave headings
    This function is modified from David Ogden's work 
    (see https://github.com/mattEhall/FrequencyDomain/blob/b89dd4f4a732fbe4afde56efe2b52c3e32e22d53/FrequencyDomain.py#L842 for the original function).
    
    May be called with multiple bodies (automatically implements B2B). 
    In this case, the meshFName, CoG, body_name should be a tuple of the
    values for each body.
    
    Also has the ability to add generalized body modes by inputting the path to
    a 'gbm_dofs.py' file (see RM3 example).
    
    Parameters
    ----------
    meshFName : tuple of strings
        Tuple containing a string for the path to each body's hydrodynamic mesh.
        mesh must be cropped at waterline (OXY plane) and have no lid
    wCapy: array
        array of frequency points to be computed by Capytaine
    CoG: tuple of lists
        tuple contains a 3x1 list of each body's CoG
    headings: list
        list of wave headings to compute
    saveNc: Bool
        save results to .nc file
    ncFName: str
        name of .nc file
    wDes: array
        array of desired frequency points
        (for interpolation of wCapy-based Capytaine data)
    body_name: tuple of strings
        Tuple containing strings. Strings are the names of each body. 
        Prevent the body name from being a long file path
    depth: float
        Water depth. Should be positive downwards. Use decimal value to prevent 
        Capytaine outputting int32 types. Default is -np.infty
    density: float
        Water density. Use decimal value to prevent Capytaine outputting int32 
        types. Default 1025.0
    additional_dofs: string
        path to a gbm_dofs.py file that returns GBM dofs to this function
    
    Returns
    -------
    capyData: xarray Dataset
        Hydrodynamic coefficients as computed
    problems: list
        capytaine Problems that were solved
    '''

    bodies = []
    for i in np.arange(0, len(meshFName)):
        bodies.append(cpt.FloatingBody.from_file(meshFName[i]))
        bodies[i].center_of_mass = CoG[i]
        bodies[i].keep_immersed_part()
        if body_name[i] != '':
            bodies[i].name = body_name[i]
        bodies[i].add_all_rigid_body_dofs()

    # calculate hydrostatics and output to KH.dat and Hydrostatics.dat files
    path, tmp = os.path.split(ncFName)
    path += os.path.sep
    hydrostatics(bodies, path)

    # add gbm dofs
    # 1. pass gbm_dofs.py path to call_capy
    # 2. Here: pass mesh to a local gbm_dofs.py script
    # 3. in the gbm_dofs.py script, create dofs based on body mesh that is passed in
    # 4. pass dof dict back to call_capy and continue adding to body
    if additional_dofs_dir is not None:
        old_dir = os.getcwd()
        os.chdir(additional_dofs_dir)
        import gbm_dofs
        additional_dofs = gbm_dofs.new_dofs(bodies)

        for i in np.arange(0, len(meshFName)):
            if body_name[i] in additional_dofs:
                for k, v in additional_dofs[body_name[i]].items():
                    bodies[i].dofs[k] = v
        os.chdir(old_dir)

    # combine all bodies to account for B2B interactions
    combo = bodies[0]
    for i in np.arange(1, len(bodies), 1):
        combo += bodies[i]

    # call Capytaine solver
    print(
        f'\n-------------------------------\n'
        f'Calling Capytaine BEM solver...\n'
        f'-------------------------------\n'
        f'mesh = {meshFName}\n'
        f'w range = {wCapy[0]:.3f} - {wCapy[-1]:.3f} rad/s\n'
        f'dw = {(wCapy[1]-wCapy[0]):.3f} rad/s\n'
        f'no of headings = {len(headings)}\n'
        f'no of radiation & diffraction problems = {len(wCapy)*(len(headings) + len(combo.dofs))}\n'
        f'-------------------------------\n')

    # Create a dataset of parameters.
    #     'fill_dataset()' automatically creates problems and solves them.
    problems = xr.Dataset(
        coords={
            'omega': wCapy,
            'wave_direction': headings,
            'radiating_dof': list(combo.dofs),
            'water_depth': [depth],
            'rho': [density],
        })

    solver = cpt.BEMSolver()
    capyData = solver.fill_dataset(problems, [combo], hydrostatics=False)

    # # add kochin diffraction results
    # kochin = cpt.io.xarray.kochin_data_array(results, headings)
    # capyData.update(kochin)

    # save to .nc file
    cpt.io.xarray.separate_complex_values(capyData).to_netcdf(
        ncFName,
        encoding={
            'radiating_dof': {
                'dtype': 'U'
            },
            'influenced_dof': {
                'dtype': 'U'
            }
        })

    print('\n\nCapytaine call complete. Data saved to \n' + ncFName)

    return capyData, problems
Пример #20
0
logging.basicConfig(level=logging.INFO,
                    format="%(levelname)s:\t%(message)s")

# Generate body
body = cpt.HorizontalCylinder(
    length=3.0, radius=1.0,  # Dimensions
    center=(0, 0, -1.01),     # Position
    nr=5, nx=15, ntheta=30,   # Fineness of the mesh
)
body.add_translation_dof(name="Heave")

test_matrix = xr.Dataset(coords={
    'omega': np.linspace(0.5, 4, 40),
    'radiating_dof': list(body.dofs.keys()),
})

ds2 = cpt.BEMSolver(green_function=cpt.XieDelhommeau()).fill_dataset(test_matrix, body)
ds1 = cpt.BEMSolver(green_function=cpt.Delhommeau()).fill_dataset(test_matrix, body)

plt.figure()
ds1['added_mass'].plot(x='omega', label='Delhommeau')
ds2['added_mass'].plot(x='omega', label='XieDelhommeau')
plt.legend()

plt.figure()
ds1['radiation_damping'].plot(x='omega', label='Delhommeau')
ds2['radiation_damping'].plot(x='omega', label='XieDelhommeau')
plt.legend()

plt.show()
Пример #21
0
                         omega=w,
                         sea_bottom=-np.infty,
                         g=9.81,
                         rho=1000.0) for dof in body.dofs for w in freq
]
problems += [
    cpt.DiffractionProblem(body=body,
                           omega=w,
                           wave_direction=heading,
                           sea_bottom=-np.infty,
                           g=9.81,
                           rho=1000.0) for w in freq for heading in directions
]

# 3. Define the BEM solver to be used.
solver = cpt.BEMSolver()

# 4. Loop through the problems and solve each
results = [
    solver.solve(problem, keep_details=True) for problem in sorted(problems)
]

# 5. Create a dataset using the list of results and any hydrostatics output
capyData = cpt.assemble_dataset(results, hydrostatics=False)

###############################################################################
# ** Alternate method to 2-5
#    Create a dataset of parameters.
#    'fill_dataset()' automatically creates problems and solves them.
#    This method is easy and clean, but has less control on the problem details
test_matrix = xr.Dataset(
Пример #22
0
if show_mesh:
    buoy.show()

# Set up radiation and diffraction problems
omega_range = np.linspace(0.3, 5.0, 60)
problems = [
    cpt.RadiationProblem(body=buoy, radiating_dof='Heave', omega=omega)
    for omega in omega_range
]
problems += [
    cpt.DiffractionProblem(omega=omega, body=buoy, wave_direction=0.0)
    for omega in omega_range
]

# Solve the problems using the axial symmetry
solver = cpt.BEMSolver(engine=cpt.HierarchicalToeplitzMatrixEngine()
                       )  # TODO: investigate why this engine is uses
results = [solver.solve(pb) for pb in sorted(problems)]
*radiation_results, diffraction_result = results
dataset = cpt.assemble_dataset(results)

# Assemble needed values for control algorithm
added_mass = dataset['added_mass'].sel(radiating_dof='Heave',
                                       influenced_dof='Heave')
radiation_damping = dataset['radiation_damping'].sel(radiating_dof='Heave',
                                                     influenced_dof='Heave')
dataset['excitation_force'] = dataset['Froude_Krylov_force'] + dataset[
    'diffraction_force']
excitation_force = dataset['excitation_force'].sel(wave_direction=0.0)

# Control algorithm  # TODO: get this working : )
intrinsic_impedance = radiation_damping + 1.0j * omega_range * (