Ejemplo n.º 1
0
    def generate_disk_mesh(radius=1.0,
                           theta_max=np.pi,
                           nr=2,
                           ntheta=4,
                           center=(0, 0, 0),
                           normal=(1, 0, 0),
                           name=None) -> Mesh:
        theta_range = np.linspace(0, 2 * theta_max, ntheta + 1)
        r_range = np.linspace(0.0, radius, nr + 1)

        nodes = np.zeros(((ntheta + 1) * (nr + 1), 3), dtype=float)
        for i, (r, t) in enumerate(product(r_range, theta_range)):
            y = +r * np.sin(t)
            z = -r * np.cos(t)
            nodes[i, :] = (0, y, z)

        panels = np.zeros((ntheta * nr, 4), dtype=int)

        for k, (i, j) in enumerate(product(range(0, nr), range(0, ntheta))):
            panels[k, :] = (j + i * (ntheta + 1), j + 1 + i * (ntheta + 1),
                            j + 1 + (i + 1) * (ntheta + 1),
                            j + (i + 1) * (ntheta + 1))

        mesh = Mesh(nodes, panels, name=name)
        mesh.merge_duplicates()
        mesh.heal_triangles()
        mesh.rotate_around_center_to_align_vectors(
            (0, 0, 0), mesh.faces_normals[0], normal)
        mesh.translate(center)
        return mesh
Ejemplo n.º 2
0
 def merged(self, name=None) -> Mesh:
     """Merge the sub-meshes and return a full mesh.
     If the collection contains other collections, they are merged recursively.
     Optionally, a new name can be given to the resulting mesh."""
     if name is None:
         name = self.name
     merged = Mesh(self.vertices, self.faces, name=name)
     merged.merge_duplicates()
     merged.heal_triangles()
     return merged
Ejemplo n.º 3
0
    def from_profile(profile: Union[Callable, Iterable[float]],
                     z_range: Iterable[float]=np.linspace(-5, 0, 20),
                     axis: Axis=Oz_axis,
                     nphi: int=20,
                     name=None):
        """Return a floating body using the axial symmetry.
        The shape of the body can be defined either with a function defining the profile as [f(z), 0, z] for z in z_range.
        Alternatively, the profile can be defined as a list of points.
        The number of vertices along the vertical direction is len(z_range) in the first case and profile.shape[0] in the second case.

        Parameters
        ----------
        profile : function(float → float)  or  array(N, 3)
            define the shape of the body either as a function or a list of points.
        z_range: array(N), optional
            used only if the profile is defined as a function.
        axis : Axis
            symmetry axis
        nphi : int, optional
            number of vertical slices forming the body
        name : str, optional
            name of the generated body (optional)

        Returns
        -------
        AxialSymmetricMesh
            the generated mesh
        """

        if name is None:
            name = "axisymmetric_mesh"

        if callable(profile):
            z_range = np.asarray(z_range)
            x_values = [profile(z) for z in z_range]
            profile_array = np.stack([x_values, np.zeros(len(z_range)), z_range]).T
        else:
            profile_array = np.asarray(profile)

        assert len(profile_array.shape) == 2
        assert profile_array.shape[1] == 3

        n = profile_array.shape[0]
        angle = 2 * np.pi / nphi

        nodes_slice = np.concatenate([profile_array, axis.rotate_points(profile_array, angle)])
        faces_slice = np.array([[i, i+n, i+n+1, i+1] for i in range(n-1)])
        body_slice = Mesh(nodes_slice, faces_slice, name=f"slice_of_{name}")
        body_slice.merge_duplicates()
        body_slice.heal_triangles()

        return AxialSymmetricMesh(body_slice, axis=axis, nb_repetitions=nphi - 1, name=name)
Ejemplo n.º 4
0
    def _generate_sphere_mesh(self,
                              ntheta,
                              nphi,
                              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)
        phi = np.linspace(-np.pi, np.pi, nphi + 1)

        # Nodes
        nodes = np.zeros(((ntheta + 1) * (nphi + 1), 3), dtype=float)

        for i, (t, p) in enumerate(product(theta, phi)):
            # The sign of theta below is a trick to get the correct orientation of the normal vectors...
            x = +np.sin(t) * np.sin(np.sign(t) * p)
            y = +np.sin(t) * np.cos(np.sign(t) * p)
            z = -np.cos(t)
            nodes[i, :] = (x, y, z)
        nodes *= self.radius

        # Connectivity
        panels = np.zeros((ntheta * nphi, 4), dtype=int)

        for k, (i, j) in enumerate(product(range(0, ntheta), range(0, nphi))):
            panels[k, :] = (j + i * (nphi + 1), j + (i + 1) * (nphi + 1),
                            j + 1 + (i + 1) * (nphi + 1),
                            j + 1 + i * (nphi + 1))

        mesh = Mesh(nodes, panels, name=f"{name}_mesh")
        mesh.merge_duplicates()
        mesh.heal_triangles()

        return mesh