def to_meshmagick(self): """Convert the Mesh object as a Mesh object from meshmagick. Mostly for debugging.""" from meshmagick.mesh import Mesh meshmagick_mesh = Mesh(self.vertices, self.faces, name=self.name) meshmagick_mesh.heal_mesh() return meshmagick_mesh
def extract_faces(self, id_faces_to_extract, return_index=False): """Create a new FloatingBody by extracting some faces from the mesh.""" if return_index: new_body, id_v = Mesh.extract_faces(self, id_faces_to_extract, return_index) else: new_body = Mesh.extract_faces(self, id_faces_to_extract, return_index) new_body.__class__ = FloatingBody new_body.nb_matrices_to_keep = self.nb_matrices_to_keep LOG.info(f"Extract floating body from {self.name}.") new_body.dofs = {} for name, dof in self.dofs.items(): new_body.dofs[name] = dof[id_faces_to_extract] if return_index: return new_body, id_v else: return new_body
def test_clipper(): vertices, faces = mmio.load_VTP('meshmagick/tests/data/SEAREV.vtp') searev = Mesh(vertices, faces) plane = Plane() clipper = mc.MeshClipper(searev, plane, assert_closed_boundaries=True, verbose=False) for iter in range(50): thetax, thetay = np.random.rand(2) * 2 * math.pi plane.rotate_normal(thetax, thetay) clipper.plane = plane
def extract_faces(self, id_faces_to_extract, return_index=False, name=None): """ Extracts a new mesh from a selection of faces ids Parameters ---------- id_faces_to_extract : ndarray Indices of faces that have to be extracted return_index: bool, optional Flag to output old indices name: string, optional Name for the new mesh Returns ------- Mesh A new Mesh instance composed of the extracted faces """ nv = self.nb_vertices # Determination of the vertices to keep vertices_mask = np.zeros(nv, dtype=bool) vertices_mask[self._faces[id_faces_to_extract].flatten()] = True id_v = np.arange(nv)[vertices_mask] # Building up the vertex array v_extracted = self._vertices[id_v] new_id__v = np.arange(nv) new_id__v[id_v] = np.arange(len(id_v)) faces_extracted = self._faces[id_faces_to_extract] faces_extracted = new_id__v[faces_extracted.flatten()].reshape( (len(id_faces_to_extract), 4)) extracted_mesh = Mesh(v_extracted, faces_extracted) for prop in self.__internals__: if prop[:4] == "face": extracted_mesh.__internals__[prop] = self.__internals__[prop][ id_faces_to_extract] if name is None: if self.name is not None and self.name.startswith( "mesh_extracted_from_"): extracted_mesh.name = self.name else: extracted_mesh.name = f"mesh_extracted_from_{self.name}" else: extracted_mesh.name = name if return_index: return extracted_mesh, id_v else: return extracted_mesh
def from_set_of_faces(set_of_faces): faces = [] vertices = [] for face in set_of_faces: ids_of_vertices_in_face = [] for vertex in face: if vertex not in vertices: i = len(vertices) vertices.append(vertex) else: i = vertices.index(vertex) ids_of_vertices_in_face.append(i) if len(ids_of_vertices_in_face) == 3: # Add a fourth node identical to the first one ids_of_vertices_in_face.append(ids_of_vertices_in_face[0]) faces.append(ids_of_vertices_in_face) return Mesh(vertices=vertices, faces=faces)
def as_FloatingBody(self, name=None): """Merge the mesh of the bodies of the collection into one mesh.""" if name is None: name = f"union_of_{'_and_'.join((body.name for body in self.subbodies))}" if len(name) > NAME_MAX_LENGTH: name = name[:NAME_MAX_LENGTH - 3] + "..." new_body = self.subbodies[0].as_FloatingBody().copy(name=name) for body in self.subbodies[1:]: new_body = Mesh.__add__(new_body, body.as_FloatingBody()) LOG.debug(f"Add mesh of {body.name} to {name}.") new_body.name = name new_body.merge_duplicates() new_body.heal_triangles() new_body.__class__ = FloatingBody new_body.dofs = self.dofs new_body.nb_matrices_to_keep = 1 LOG.info( f"Merged collection of bodies {self.name} into floating body {new_body.name}." ) return new_body
def read_mesh(self, reader, mesh_path): """This function reads the mesh quantities of the *.hdb5 file. Parameters ---------- reader : string *.hdb5 file. mesh_path : string Path to the mesh folder. """ # Mesh data. nb_vertices = np.array(reader[mesh_path + "/NbVertices"]) vertices = np.array(reader[mesh_path + "/Vertices"]) nb_faces = np.array(reader[mesh_path + "/NbFaces"]) faces = np.array(reader[mesh_path + "/Faces"]) mesh = Mesh(vertices, faces) # Verification of mesh information consistency assert nb_vertices == mesh.nb_vertices assert nb_faces == mesh.nb_faces return mesh
#!/usr/bin/env python # -*- coding: utf-8 -*- import meshmagick.mmio as mmio from meshmagick.mesh import Mesh from math import pi, fabs import pytest vertices, faces = mmio.load_VTP('meshmagick/tests/data/Cylinder.vtp') cylinder = Mesh(vertices, faces) xmin, xmax, ymin, ymax, zmin, zmax = cylinder.axis_aligned_bbox R = (xmax - xmin) / 2. h = zmax - zmin V = pi * R**2 * h Ixx = Iyy = V * (R**2 + h**2 / 3) / 4 Izz = V * R**2 / 2 def test_cylinder_inertia(): inertia = cylinder.eval_plain_mesh_inertias(rho_medium=1.) assert pytest.approx(Ixx, rel=1e-1) == inertia.xx assert pytest.approx(Izz, rel=1e-1) == inertia.zz def test_move_cog(): # parallel axis theorem to find MOI at base of cylinder Ixx_base = Ixx + V * (h / 2)**2 # use meshmagick to find moments of inertia inertia = cylinder.eval_plain_mesh_inertias(rho_medium=1.)
def __init__(self, *args, **kwargs): Mesh.__init__(self, *args, **kwargs) self._compute_radiuses() self.nb_matrices_to_keep = 1 self.dofs = {} LOG.info(f"New floating body: {self.name}.")
def main(): parser = argparse.ArgumentParser( description="""--- max_frequency_bem --- Command line utility to get the maximum frequency allowed by a given mesh discretization for the BEM computations to be accurate. It relies on meshmagick tool for mesh reading """, epilog='-- FRyDoM framework.\nmax_frequency_bem utility', formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument( 'infilename', # TODO : voir pour un typ=file pour tester l'existence help='path of the input mesh file in any supported format', type=str) parser.add_argument( '-ifmt', '--input-format', help="""Input format. Meshmagick will read the input file considering the INPUT_FORMAT rather than using the extension """, type=str) parser.add_argument( '-n', '--nb-faces-by-wavelength', help= 'Specify the number of faces by wavelength that BEM computations should take into account', type=int) parser.add_argument( '-g', '--gravity', help='Acceleration of gravity in m/s**2. Default is 9.81', type=float, default=9.81) parser.add_argument( '-wd', '--water-depth', help='Water depth in meters. Default is infinite (put 0 explicitely)', type=float, default=0.) args, unknown = parser.parse_known_args() if args.input_format is not None: ifmt = args.input_format else: _, ext = os.path.splitext(args.infilename) ifmt = ext[1:].lower() if ifmt == '': raise IOError( 'Unable to determine the input file format from its extension. ' 'Please specify an input format.') # Loading mesh from file if os.path.isfile(args.infilename): vertices, faces = mmio.load_mesh(args.infilename, ifmt) mesh = Mesh(vertices, faces) else: raise IOError('file %s not found' % args.infilename) # Number of faces by wave length necessary to keep accuracy good in BEM computations nb_faces_by_wavelength = args.nb_faces_by_wavelength if nb_faces_by_wavelength is None: nb_faces_by_wavelength = 10 max_edge_length = mesh.max_edge_length wave_length = nb_faces_by_wavelength * max_edge_length wave_number = 2. * pi / wave_length w2 = args.gravity * wave_number depth = fabs(args.water_depth) if depth != 0.: w2 *= tanh(wave_number * depth) w = sqrt(w2) print( '\nBased on the rule of %u faces by wavelength, the specified mesh with maximum edge length of %.3f m \n' 'allows to perform BEM computations until the frequency:\n' % (nb_faces_by_wavelength, max_edge_length)) print('\t\t*****************************') print('\t\t*** Wmax = %.2f rad/s ***' % w) print('\t\t*****************************\n') print('with:') print('\t+ Gravity: %.3f m/s**2' % args.gravity) if depth == 0.: print('\t+ Water depth: INFINITE') else: print('\t+ Water depth: %.3f m (FINITE)' % depth) print('\n')
#!/usr/bin/env python # -*- coding: utf-8 -*- from meshmagick.mmio import load_VTP from meshmagick.mesh import Mesh from meshmagick.inertia import right_circular_cylinder from meshmagick.densities import get_density # Comparaison pour un calcul au cog vertices, faces = load_VTP('meshmagick/tests/data/Cylinder.vtp') cyl_mesh = Mesh(vertices, faces) xmin, xmax, ymin, ymax, zmin, zmax = cyl_mesh.axis_aligned_bbox # Analytique R = (xmax - xmin) / 2. H = zmax - zmin cyl_anal_inertia = right_circular_cylinder(R, H, density=get_density('SALT_WATER')) # print cyl_mesh_inertia # print cyl_anal_inertia.at_cog # On decale cyl_mesh.translate([1, 3, -10]) # cyl_mesh.show() print "Numerique:" print cyl_mesh.eval_plain_mesh_inertias(get_density('SALT_WATER'))
def _read_nemoh_parameters(self, pyHDB, cal_file, test=True): """Reads the Nemoh parameters from the Nemoh.cal file Parameters ---------- pyHDB : object pyHDB object for storing the hydrodynamic database. cal_file : str Path (relative or absolute) to the Nemoh.cal file test : bool, optional If True (default), it will test against consistency between frequencies taken for BEM computations and meshe's discretization """ if not os.path.exists(cal_file): raise IOError("File %s not found" % cal_file) with open(cal_file, 'r') as f: # Getting root directory of the Nemoh computation project abspath = os.path.abspath(cal_file) dirname = os.path.dirname(abspath) self.dirname = dirname def skip_line(): f.readline() # Environment parameters skip_line() skip_line() # Rho_water. skip_line() # Grav. skip_line() # Depth skip_line() # xreff and yreff. # Number of bodies skip_line() skip_line() # nb_bodies. for ibody in range(pyHDB.nb_bodies): skip_line() meshfile = str(f.readline().split()[0]) abs_meshfile = os.path.join(dirname, meshfile) # Instantiating mesh object vertices, faces = load_MAR(abs_meshfile) mesh = Mesh(vertices, faces) nb_vertices, nb_faces = list(map(int, f.readline().split()[:2])) # Verification of mesh information consistency assert nb_vertices == mesh.nb_vertices assert nb_faces == mesh.nb_faces # De-symmetrizing meshes with open(abs_meshfile, 'r') as fmesh: _, isym = fmesh.readline().split() if int(isym) == 1: # Mesh is symmetric mesh.symmetrize(Plane([0, 1, 0])) mesh.name, _ = os.path.splitext(meshfile) # Instantiating BodyDB. body = body_db.BodyDB(ibody, pyHDB.nb_bodies, pyHDB.nb_wave_freq, pyHDB.nb_wave_dir , mesh) # RADIATION. nb_dof = int(f.readline().split()[0]) for idof in range(nb_dof): dof = f.readline().split()[:7] motion_type = int(dof[0]) direction = list(map(float, dof[1:4])) point = list(map(float, dof[4:])) # Center of gravity. body.position = point if motion_type == 1: # Translation. if(direction[0] == 1): body.Motion_mask[0] = 1 elif(direction[1] == 1): body.Motion_mask[1] = 1 elif(direction[2] == 1): body.Motion_mask[2] = 1 else: "The linear motion direction must be a unit vector ex, ey or ez. Generalized modes are not taken into account." exit() elif motion_type == 2: # Rotation. if (direction[0] == 1): body.Motion_mask[3] = 1 elif (direction[1] == 1): body.Motion_mask[4] = 1 elif (direction[2] == 1): body.Motion_mask[5] = 1 else: "The angular motion direction must be a unit vector ex, ey or ez. Generalized modes are not taken into account." exit() else: raise UnknownMotionMode(motion_type, abspath) # INTEGRATION. nb_force = int(f.readline().split()[0]) for iforce in range(nb_force): force = f.readline().split()[:7] force_type = int(force[0]) direction = list(map(float, force[1:4])) point = list(map(float, force[4:])) if force_type == 1: # Pure force if (direction[0] == 1): body.Force_mask[0] = 1 elif (direction[1] == 1): body.Force_mask[1] = 1 elif (direction[2] == 1): body.Force_mask[2] = 1 else: "The force direction must be a unit vector ex, ey or ez. Generalized modes are not taken into account." exit() elif force_type == 2: if (direction[0] == 1): body.Force_mask[3] = 1 body.point[0,:] = point elif (direction[1] == 1): body.Force_mask[4] = 1 body.point[1, :] = point elif (direction[2] == 1): body.Force_mask[5] = 1 body.point[2, :] = point else: "The angular motion direction must be a unit vector ex, ey or ez. Generalized modes are not taken into account." exit() else: raise UnknownForceMode(force_type, abspath) # Skipping additional lines. nb_add_line = int(f.readline().split()[0]) for i_add_line in range(nb_add_line): skip_line() # Add body to pyHDB. pyHDB.append(body) # Reading discretization. skip_line() # Getting frequency discretization. skip_line() # Getting wave directions discretization. skip_line() # Getting post-processing information skip_line() # Impulse response function data = f.readline().split()[:3] # has_irf = bool(int(data[0])) # if has_irf: # self.dt_irf, self.tf_irf = map(float, data[1:]) # TODO: si ok lire -> remettre en place si besoin... # Show pressure skip_line() # self.has_pressure = bool(int(f.readline().split()[0])) # Enlever le skip_line() ci-dessus si décommenté. # Kochin functions. data = f.readline().split()[:3] pyHDB.has_kochin = bool(float(data[0])) if pyHDB.has_kochin: pyHDB.nb_angle_kochin = int(data[0]) pyHDB.min_angle_kochin, pyHDB.max_angle_kochin = list(map(float, data[1:])) pyHDB.set_wave_directions_Kochin() # # TODO: si ok, lire -> remettre en place si besoin... # # Free surface elevation # data = f.readline().split()[:4] # has_fs_elevation = bool(int(data[0])) # if has_fs_elevation: # self.nx_fs, self.ny_fs = map(int, data[:2]) # self.xlim_fs, self.ylim_fs = map(float, data[2:]) if test: self.test_mesh_frequency_consistency(pyHDB)
#!/usr/bin/env python # -*- coding: utf-8 -*- import meshmagick.mmio as mmio import meshmagick.hydrostatics as hs from meshmagick.mesh import Mesh from math import pi, fabs # Importing cylinder mesh vertices, faces = mmio.load_VTP('meshmagick/tests/data/Cylinder.vtp') cylinder = Mesh(vertices, faces) # cylinder.show() hs_cylinder = hs.Hydrostatics(cylinder) vertices, faces = mmio.load_VTP('meshmagick/tests/data/SEAREV.vtp') searev = Mesh(vertices, faces) def test_verbose(): hs_cylinder.verbose hs_cylinder.verbose_off() hs_cylinder.verbose_off() return def test_accessors(): hs_cylinder.gravity hs_cylinder.gravity = 9.81 hs_cylinder.rho_water = 1025. mass = hs_cylinder.mass hs_cylinder.mass = mass