def _generate_mesh_using_symmetry(self, ntheta, nphi, clip_free_surface, mesh_name): if clip_free_surface: if self.geometric_center[2] < -self.radius: # fully immersed theta_max = np.pi elif self.geometric_center[2] < self.radius: theta_max = np.arccos(self.geometric_center[2] / self.radius) else: raise ValueError( "Impossible to mesh the immersed hull of a sphere completely out of the water" ) else: theta_max = np.pi theta = np.linspace(0.0, theta_max, ntheta + 1) points_on_a_meridian = (self.radius * np.stack( [np.sin(theta), np.zeros_like(theta), -np.cos(theta)], axis=1) + self.geometric_center) symmetry_axis = Axis(vector=[0, 0, 1], point=self.geometric_center) return AxialSymmetricMesh.from_profile(points_on_a_meridian, axis=symmetry_axis, nphi=nphi, name=mesh_name)
def _generate_clever_sphere_mesh(self, ntheta=10, nphi=10, clip_free_surface=False, name=None): if clip_free_surface: if self.geometric_center[2] < -self.radius: # fully immersed theta_max = np.pi elif self.geometric_center[2] < self.radius: theta_max = np.arccos(self.geometric_center[2] / self.radius) else: raise Exception("Sphere out of the water") else: theta_max = np.pi theta = np.linspace(0.0, theta_max, ntheta + 1) circle_profile = np.zeros((ntheta + 1, 3), dtype=float) circle_profile[:, 0] = np.sin(theta) circle_profile[:, 2] = -np.cos(theta) circle_profile *= self.radius return AxialSymmetricMesh.from_profile(circle_profile, nphi=nphi, name=f"{name}_mesh")
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)
def __init__(self, length=10.0, radius=1.0, center=(0, 0, 0), nx=10, ntheta=10, nr=2, clever=True, name=None): self.length = length self.radius = radius self.geometric_center = np.asarray(center, dtype=float) if name is None: name = f"cylinder_{next(Mesh._ids)}" open_cylinder = AxialSymmetricMesh.from_profile( lambda z: radius, z_range=np.linspace(-length / 2, length / 2, nx + 1), nphi=ntheta) if nr > 0: top_side = Disk(radius=radius, center=(0, 0, length / 2), axial_symmetry=True, normal=(0, 0, 1), resolution=(nr, ntheta), name=f"top_side_of_{name}").mesh bottom_side = top_side.copy(name=f"bottom_side_of_{name}_mesh") bottom_side.mirror(xOy_Plane) mesh = AxialSymmetricMesh.join_meshes(open_cylinder, top_side, bottom_side) else: mesh = open_cylinder if not clever: mesh = mesh.merged() mesh.merge_duplicates() mesh.heal_triangles() mesh.translate(center) mesh.name = f"{name}_mesh" FloatingBody.__init__(self, mesh=mesh, name=name)
def __init__(self, radius=1.0, resolution=(3, 5), center=(0, 0, 0), normal=(1, 0, 0), reflection_symmetry=False, axial_symmetry=False, name=None): assert radius > 0, "Radius of the disk mesh should be given as a positive value." assert len( resolution ) == 2, "Resolution of a disk should be given as a couple a values." assert all([ h > 0 for h in resolution ]), "Resolution of the disk mesh should be given as positive values." assert all([ i == int(i) for i in resolution ]), "Resolution of a disk should be given as integer values." assert len( center ) == 3, "Position of the center of a disk should be given a 3-ple of values." self.radius = float(radius) self.geometric_center = np.asarray(center, dtype=float) nr, ntheta = resolution if reflection_symmetry and ntheta % 2 == 1: raise ValueError( "To use the reflection symmetry of the mesh, " "it should have an even number of panels in this direction.") if reflection_symmetry and axial_symmetry: raise NotImplementedError( "Disk generators with both symmetries have not been implemented." ) if name is None: name = f"disk_{next(Mesh._ids)}" LOG.debug( f"New disk body of radius {radius} and resolution ({nr}, {ntheta}), named {name}." ) if reflection_symmetry: half_mesh = Disk.generate_disk_mesh(radius=self.radius, theta_max=np.pi / 2, nr=nr, ntheta=ntheta // 2, name=f"half_of_{name}_mesh") mesh = ReflectionSymmetricMesh(half_mesh, plane=xOz_Plane, name=f"{name}_mesh") elif axial_symmetry: mesh_slice = Disk.generate_disk_mesh(radius=self.radius, theta_max=np.pi / ntheta, nr=nr, ntheta=1, name=f"slice_of_{name}_mesh") mesh_slice.rotate_around_center_to_align_vectors( (0, 0, 0), e_x, e_z ) # Convoluted way to avoid a warning message in AxialSymmetry... mesh = AxialSymmetricMesh(mesh_slice, axis=Oz_axis, nb_repetitions=ntheta - 1, name=f"{name}_mesh") mesh.rotate_around_center_to_align_vectors((0, 0, 0), e_z, e_x) else: mesh = Disk.generate_disk_mesh(radius=self.radius, nr=nr, ntheta=ntheta, name=f"{name}_mesh") mesh.rotate_around_center_to_align_vectors( (0, 0, 0), mesh.faces_normals[0], normal) mesh.translate(center) FloatingBody.__init__(self, mesh=mesh, name=name)
def __init__(self, length=10.0, radius=1.0, center=(0, 0, 0), nx=10, ntheta=10, nr=2, clever=True, name=None): """Generate the mesh of a vertical cylinder. Parameters ---------- length : float, optional length of the cylinder radius : float, optional radius of the cylinder center : 3-ple or array of shape (3,), optional position of the geometric center of the cylinder nx : int, optional number of circular slices ntheta : int, optional number of panels along a circular slice of the cylinder nr : int, optional number of panels along a radius on the extremities of the cylinder clever : bool, optional if True, uses the mesh symmetries name : str, optional a string naming the floating body """ self.length = length self.radius = radius self.geometric_center = np.asarray(center, dtype=np.float) if name is None: name = f"cylinder_{next(Mesh._ids)}" open_cylinder = AxialSymmetricMesh.from_profile( lambda z: radius, z_range=np.linspace(-length / 2, length / 2, nx + 1), nphi=ntheta) if nr > 0: top_side = Disk(radius=radius, center=(0, 0, length / 2), axial_symmetry=True, normal=(0, 0, 1), resolution=(nr, ntheta), name=f"top_side_of_{name}").mesh bottom_side = top_side.copy(name=f"bottom_side_of_{name}_mesh") bottom_side.mirror(xOy_Plane) mesh = AxialSymmetricMesh.join_meshes(open_cylinder, top_side, bottom_side) else: mesh = open_cylinder if not clever: mesh = mesh.merged() mesh.merge_duplicates() mesh.heal_triangles() mesh.translate(center) mesh.name = f"{name}_mesh" FloatingBody.__init__(self, mesh=mesh, name=name)