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)
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)
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)
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))
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
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__()
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)
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) """
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])
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")
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
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
# 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)
# 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)
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 = []
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',
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
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()
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(
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 * (