Exemple #1
0
    def mesh_shape(self,
                   shp,
                   size=0.1,
                   order=1,
                   max_dim=3,
                   mesh_algo=8,
                   interactive=False):
        """



        :param shp: ADA shape object
        :param size: Size of mesh
        :param order: Polynomial order
        :param max_dim: Maximum dimensions (1, 2 or 3).
        :param mesh_algo: 2D mesh algorithm (1: MeshAdapt, 2: Automatic, 5: Delaunay, 6: Frontal-Delaunay, 7: BAMG,
                          8: Frontal-Delaunay for Quads, 9: Packing of Parallelograms)
        :param interactive: Enable an interactive session using GMSH GUI.

        :type shp: ada.Shape
        :rtype: ada.FEM
        """
        gmsh.option.setNumber("Mesh.Algorithm", mesh_algo)
        gmsh.option.setNumber("Mesh.ElementOrder", order)
        gmsh.option.setNumber("Mesh.SecondOrderIncomplete", 1)
        gmsh.option.setNumber("Mesh.Smoothing", 3)
        gmsh.option.setNumber("Geometry.Tolerance", 1e-3)

        gmsh.model.add(shp.name)
        shp.to_stp("temp_occ_in", os.path.join(self.work_dir))
        gmsh.open("gmsh/temp_occ_in.stp")

        model = gmsh.model
        factory = model.geo

        factory.synchronize()

        model.mesh.setRecombine(2, 1)
        model.mesh.generate(max_dim)
        model.mesh.removeDuplicateNodes()

        if interactive:
            gmsh.fltk.run()
Exemple #2
0
def load_gmsh_nodes(gmshpath, entity):
    '''
    Given a fullpath to some .msh file
    load in the mesh nodes IDs, triangles and coordinates.

    gmshpath -- path to gmsh file
    dimtag   -- tuple specifying the (dimensionality,tagID) being loaded


    If entity=(dim,tag) not provided then pull the first entity and return
    '''

    gmsh.initialize()
    gmsh.open(gmshpath)
    nodes, coords, params = gmsh.model.mesh.getNodes(entity[0], entity[1])
    coords = np.array(coords).reshape((len(coords) // 3, 3))
    gmsh.clear()

    return nodes - 1, coords, params
Exemple #3
0
def test(meanFSIIt):

    name = [file for file in os.listdir() if ('solid' in file)]
    time = [float(file[8:-4]) for file in name]
    lastFile = name[np.argmax(time)]

    import gmsh
    gmsh.initialize()
    gmsh.option.setNumber('General.Terminal', 0)
    gmsh.open(lastFile)
    coord = gmsh.model.mesh.getNode(57)[0]
    gmsh.finalize()

    tests = CTests()
    tests.add(CTest('Middle bar coordinate X', coord[0], 0.5, 0.05, False))
    tests.add(
        CTest('Middle bar coordinate Y', coord[1], -0.049748, 0.05, False))
    tests.add(
        CTest('Mean number of ISI iterations', meanFSIIt, 1.749875, 0.05,
              False))
    tests.run()
Exemple #4
0
    def ImportMesh(self, mesh):
        mesh = os.path.abspath(mesh)
        print('Loading {} ...'.format(mesh))
        assert os.path.exists(mesh), "Cannot read '{}'".format(mesh)

        try:
            gmsh.finalize()
        except:
            pass
        finally:
            gmsh.initialize()

        gmsh.open(mesh)

        mesh = gmsh.model.mesh
        self.Model = gmsh.model
        print('Model ' + gmsh.model.getCurrent() + ' (' +
              str(gmsh.model.getDimension()) + 'D)')
        self.GetGroups()
        self.ImportMeshElements(mesh)
        self.LoadElemsAttr()
Exemple #5
0
def LaG_from_msh(archivo):
    ''' Obtiene la matriz de interconexión nodal (LaG) que contiene la malla de
        EF a trabajar, a partir del archivo .msh exportado por el programa GMSH.
        
        Retorna: Matriz LaG_mat, donde la primera columna representa la super-
        ficie a la que pertenece cada elemento finito (ordenadas de forma
        ascendente desde 0), de tal manera que diferencie elementos finitos con
        propiedades distintas
    '''
    gmsh.initialize()
    gmsh.open(archivo)

    LaG = np.array([])  # Matriz de interconexión nodal
    elems = np.array([])  # vector de elementos finitos
    mats = np.array([])  # Vector de materiales al que pertenece cada EF
    material = 0  # Se inicializa el material

    for ent in gmsh.model.getEntities(2):
        dim, tag = ent
        tipo, efs, nodos = gmsh.model.mesh.getElements(dim, tag)
        if tipo.size == 1:
            nodos = nodos[0]
            elems = np.append(elems, efs[0]).astype(int)
            LaG = np.append(LaG, nodos).astype(int)
            mats = np.append(mats, np.tile(material, efs[0].size)).astype(int)
            material += 1
        else:
            raise ValueError('La malla tiene varios tipos de elementos '
                             'finitos 2D.')

    nef = elems.size
    LaG = LaG.reshape((nef, -1)) - 1
    LaG_mat = np.c_[mats, LaG]
    gmsh.finalize()

    return LaG_mat
    meshio.write_points_cells(
        filename,
        points,
        centerline_cells,
        # Optional
        # point_data=point_data,
        # cell_data=cell_data,
    )


create_line_mesh(centerline_points, cells_array,
                 output_filename + "_centerline_mesh.msh")

### ------------ Remove duplicates if any (GMSH API) ----------- ###
gmsh.initialize()
gmsh.open(output_filename + "_centerline_mesh.msh")
# Node tags
initial_node_tags = np.array(gmsh.model.mesh.getNodes()[0])
# Node coords (re-arranged as numpy array [ [x1,x2,x3]_1, ..., [x2,x3,x3]_N])
initial_node_coords = np.array(gmsh.model.mesh.getNodes()[1])
initial_node_coords = np.split(initial_node_coords,
                               len(initial_node_coords) / 3.0)
# Removing duplicate nodes
gmsh.model.mesh.removeDuplicateNodes()
# Updated node tags
node_tags = np.array(gmsh.model.mesh.getNodes()[0])
# Updated node coords (re-arranged as numpy array [ [x1,x2,x3]_1, ..., [x2,x3,x3]_N])
node_coords = np.array(gmsh.model.mesh.getNodes()[1])
node_coords = np.split(node_coords, len(node_coords) / 3.0)
# Getting array of removed nodes to update centerline data
_, common_idx_init, _ = np.intersect1d(initial_node_tags,
Exemple #7
0
def load_gmsh(file_name, gmsh_args=None):
    """
    Returns a surface mesh from CAD model in Open Cascade
    Breap (.brep), Step (.stp or .step) and Iges formats
    Or returns a surface mesh from 3D volume mesh using gmsh.

    For a list of possible options to pass to GMSH, check:
    http://gmsh.info/doc/texinfo/gmsh.html

    An easy way to install the GMSH SDK is through the `gmsh-sdk`
    package on PyPi, which downloads and sets up gmsh:
        >>> pip install gmsh-sdk

    Parameters
    --------------
    file_name : str
      Location of the file to be imported
    gmsh_args : (n, 2) list
      List of (parameter, value) pairs to be passed to
      gmsh.option.setNumber
    max_element : float or None
      Maximum length of an element in the volume mesh

    Returns
    ------------
    mesh : trimesh.Trimesh
      Surface mesh of input geometry
    """
    # use STL as an intermediate format
    from ..exchange.stl import load_stl
    # do import here to avoid very occasional segfaults
    import gmsh

    # start with default args for the meshing step
    # Mesh.Algorithm=2 MeshAdapt/Delaunay, there are others but they may include quads
    # With this planes are meshed using Delaunay and cylinders are meshed
    # using MeshAdapt
    args = [("Mesh.Algorithm", 2),
            ("Mesh.CharacteristicLengthFromCurvature", 1),
            ("Mesh.MinimumCirclePoints", 32)]
    # add passed argument tuples last so we can override defaults
    if gmsh_args is not None:
        args.extend(gmsh_args)

    # formats GMSH can load
    supported = [
        '.brep', '.stp', '.step', '.igs', '.iges', '.bdf', '.msh', '.inp',
        '.diff', '.mesh'
    ]

    # check extensions to make sure it is supported format
    if file_name is not None:
        if not any(file_name.lower().endswith(e) for e in supported):
            raise ValueError(
                'Supported formats are: BREP (.brep), STEP (.stp or .step), ' +
                'IGES (.igs or .iges), Nastran (.bdf), Gmsh (.msh), Abaqus (*.inp), '
                + 'Diffpack (*.diff), Inria Medit (*.mesh)')
    else:
        raise ValueError('No import since no file was provided!')

    # if we initialize with sys.argv it could be anything
    gmsh.initialize()
    gmsh.option.setNumber("General.Terminal", 1)
    gmsh.model.add('Surface_Mesh_Generation')
    gmsh.open(file_name)

    # create a temporary file for the results
    out_data = tempfile.NamedTemporaryFile(suffix='.stl', delete=False)
    # windows gets mad if two processes try to open the same file
    out_data.close()

    # we have to mesh the surface as these are analytic BREP formats
    if any(file_name.lower().endswith(e)
           for e in ['.brep', '.stp', '.step', '.igs', '.iges']):
        gmsh.model.geo.synchronize()
        # loop through our numbered args which do things, stuff
        for arg in args:
            gmsh.option.setNumber(*arg)
        # generate the mesh
        gmsh.model.mesh.generate(2)
        # write to the temporary file
        gmsh.write(out_data.name)
    else:
        gmsh.plugin.run("NewView")
        gmsh.plugin.run("Skin")
        gmsh.view.write(1, out_data.name)

    # load the data from the temporary outfile
    with open(out_data.name, 'rb') as f:
        kwargs = load_stl(f)

    return kwargs
Exemple #8
0
import gmsh

gmsh.initialize()
gmsh.option.setNumber('General.Terminal', 1)
# load step file
gmsh.open('as1-tu-203.stp')

# get all model entities
ent = gmsh.model.getEntities()

gmsh.model.occ.healShapes()

gmsh.model.occ.synchronize()

gmsh.finalize()

#gmsh.fltk.run()
"""using gmsh generate surface mesh for vn calculation"""
import gmsh

gmsh.initialize()

gmsh.open(r'/home/hao/ShapeOPT/TestDev2/Vn/NACA0012_original.igs')

gmsh.model.addPhysicalGroup(2, [1], 1)
gmsh.model.setPhysicalName(2, 1, r'fluid')
gmsh.model.addPhysicalGroup(1, [1, 2], 1)
gmsh.model.setPhysicalName(1, 1, r'farfield')
gmsh.model.addPhysicalGroup(1, [3, 4], 2)
gmsh.model.setPhysicalName(1, 2, r'airfoil')

gmsh.model.mesh.setTransfiniteCurve(1, 36)
gmsh.model.mesh.setTransfiniteCurve(2, 36)
gmsh.model.mesh.setTransfiniteCurve(3, 120, r'Bump', 0.05)
gmsh.model.mesh.setTransfiniteCurve(4, 120, r'Bump', 0.05)

gmsh.model.geo.synchronize()

gmsh.model.mesh.generate(1)
gmsh.model.mesh.generate(2)

gmsh.write(r'/home/hao/ShapeOPT/TestDev2/NACA0012.su2')

gmsh.finalize()
Exemple #10
0
def read_gmsh(mesh, **kwargs):

    model = gmsh.model
    factory = model.geo

    gmsh.initialize()

    gmsh.open(mesh)

    logger.info('Analyze grid')

    nodeTags, coord, parametricCoord = gmsh.model.mesh.getNodes()

    nodes = pd.DataFrame(coord.reshape(-1, 3), columns=['x', 'y', 'z'])

    elementTags2, nodeTags2 = gmsh.model.mesh.getElementsByType(2)

    elems = nodeTags2.reshape(-1, 3)

    tria = pd.DataFrame(elems - 1, columns=['a', 'b', 'c'])

    # boundaries

    bounds = []

    bgs = gmsh.model.getPhysicalGroups()

    bgs = pd.DataFrame(bgs[:-1], columns=['dim', 'tag'])

    #open boundaries
    logger.info('open boundaries')

    obs = bgs.loc[bgs.tag < 1000]

    for row in obs.itertuples(index=True, name='Pandas'):
        onodes, xyz = gmsh.model.mesh.getNodesForPhysicalGroup(
            dim=getattr(row, "dim"), tag=getattr(row, "tag"))

        db = pd.DataFrame({'node': onodes - 1})
        db['type'] = np.nan
        db['id'] = getattr(row, "Index") + 1

        bounds.append(db)

    #land boundaries type
    logger.info('land boundaries')

    lbs = bgs.loc[(bgs.tag > 1000) & (bgs.tag < 2000)]
    lbs.reset_index(inplace=True, drop=True)

    for row in lbs.itertuples(index=True, name='Pandas'):
        lnodes, xyz = gmsh.model.mesh.getNodesForPhysicalGroup(
            dim=getattr(row, "dim"), tag=getattr(row, "tag"))

        db = pd.DataFrame({'node': lnodes - 1})
        db['type'] = 0
        db['id'] = -(getattr(row, "Index") + 1)

        bounds.append(db)

    if lbs.empty:  #Store max index from land boundaries
        itag = 0
    else:
        itag = lbs.tag.max() - 1000

    #islands
    logger.info('islands')

    ibs = bgs.loc[bgs.tag > 2000]
    ibs.reset_index(inplace=True, drop=True)
    ibs.index = ibs.index + itag  #set index

    for row in ibs.itertuples(index=True, name='Pandas'):

        inodes, xyz = gmsh.model.mesh.getNodesForPhysicalGroup(
            dim=getattr(row, "dim"), tag=getattr(row, "tag"))
        db = pd.DataFrame({'node': inodes - 1})
        db['type'] = -1
        db['id'] = -(getattr(row, "Index") + 1)

        bounds.append(db)

    if bounds != []:
        bnodes = pd.concat(bounds).reset_index(drop=True)

        bnodes.index.name = 'bnodes'

        bnodes = bnodes.drop_duplicates('node')

        bnodes['id'] = bnodes.id.astype(int)

    else:
        bnodes = pd.DataFrame({})

    #check if global and reproject
    sproj = kwargs.get('gglobal', False)
    if sproj:  # convert to lat/lon
        xd, yd = to_lat_lon(nodes.x, nodes.y)
        nodes['x'] = xd
        nodes['y'] = yd

    grid = pd.DataFrame({'lon': nodes.x, 'lat': nodes.y})

    tri3 = tria.values

    logger.info('Finalize Dataset')

    ## make dataset
    els = xr.DataArray(
        tri3,
        dims=['nSCHISM_hgrid_face', 'nMaxSCHISM_hgrid_face_nodes'],
        name='SCHISM_hgrid_face_nodes')

    nod = grid.loc[:, ['lon', 'lat']].to_xarray().rename({
        'index':
        'nSCHISM_hgrid_node',
        'lon':
        'SCHISM_hgrid_node_x',
        'lat':
        'SCHISM_hgrid_node_y'
    })
    nod = nod.drop_vars('nSCHISM_hgrid_node')

    dep = xr.Dataset({
        'depth':
        (['nSCHISM_hgrid_node'], np.zeros(nod.nSCHISM_hgrid_node.shape[0]))
    })

    gr = xr.merge([nod, els, dep, bnodes.to_xarray()])

    gmsh.finalize()

    return gr
Exemple #11
0
def mesh_model(model, max_size=1e-5, tolerance=1e-7, repair=False, terminal=1):
    # In/Output definitions
    fil = model.split("/")[-1][:-5]
    folder = "/".join(model.split("/")[:-1])
    scale_factor = 1000.0
    verts = []
    norms = []
    faces = []
    curvs = []
    vert_map = {}
    d1_feats = []
    d2_feats = []
    t_curves = []
    #norm_map = {}
    with fileinput.FileInput(model, inplace=True) as fi:
        for line in fi:
            print(line.replace(
                "UNCERTAINTY_MEASURE_WITH_UNIT( LENGTH_MEASURE( 1.00000000000000E-06 )",
                "UNCERTAINTY_MEASURE_WITH_UNIT( LENGTH_MEASURE( 1.00000000000000E-17 )"
            ),
                  end='')

    stats = {}

    # OCC definitions
    occ_steps = read_step_file(model)
    stats["#parts"] = len(occ_steps)
    stats["model"] = model
    print("Reading step %s with %i parts." % (model, len(occ_steps)))
    #tot = 0
    #for s in occ_steps:
    #    occ_topo = TopologyExplorer(s)
    #    print(s)
    #    print(len(list(occ_topo.edges())))
    #    tot += len(list(occ_topo.edges()))
    occ_cnt = 0
    bbox = get_boundingbox(occ_steps[occ_cnt], use_mesh=True)
    diag = np.sqrt(bbox[6]**2 + bbox[7]**2 + bbox[8]**2)
    max_length = diag * max_size  #, 9e-06
    tolerance = diag * tolerance
    #print(fil, diag, max_length, tolerance)
    stats["bbox"] = bbox
    stats["max_length"] = float(max_length)
    stats["tolerance"] = float(tolerance)
    stats["diag"] = float(diag)

    occ_topo = TopologyExplorer(occ_steps[occ_cnt])
    occ_top = Topo(occ_steps[occ_cnt])
    occ_props = GProp_GProps()
    occ_brt = BRep_Tool()

    # Gmsh definitions
    gmsh.initialize()
    gmsh.clear()
    gmsh.option.setNumber("General.Terminal", terminal)
    gmsh.option.setNumber("Geometry.Tolerance", tolerance)
    gmsh.option.setNumber("Geometry.OCCFixDegenerated", 0)
    gmsh.option.setNumber("Geometry.OCCFixSmallEdges", 0)
    gmsh.option.setNumber("Geometry.OCCFixSmallFaces", 0)
    gmsh.option.setNumber("Geometry.OCCSewFaces", 0)
    gmsh.option.setNumber("Mesh.CharacteristicLengthMax", max_length)
    gmsh.open(model)

    # Gmsh meshing
    #gmsh.model.mesh.generate(1)
    #gmsh.model.mesh.refine()
    #gmsh.model.mesh.refine()
    gmsh.model.mesh.generate(2)
    #gmsh.write("results/" + file + ".stl")
    gmsh_edges = gmsh.model.getEntities(1)
    gmsh_surfs = gmsh.model.getEntities(2)
    #print("O", tot, "G", len(gmsh_edges))
    #continue
    gmsh_entities = gmsh.model.getEntities()
    #gmsh.model.occ.synchronize()
    #print(dir(gmsh.model.occ))
    total_edges = 0
    total_surfs = 0
    for l in range(len(occ_steps)):
        topo = TopologyExplorer(occ_steps[l])
        total_edges += len(list(topo.edges()))
        total_surfs += len(list(topo.faces()))

        vol = brepgprop_VolumeProperties(occ_steps[l], occ_props, tolerance)
        #print(dir(occ_props), dir(occ_props.PrincipalProperties()), dir(occ_props.volume()), occ_props.Mass())
        sur = brepgprop_SurfaceProperties(occ_steps[l], occ_props, tolerance)
        #print(vol, "Test", sur)

    stats["#edges"] = total_edges
    stats["#surfs"] = total_surfs
    stats["volume"] = vol
    stats["surface"] = sur
    stats["curves"] = []
    stats["surfs"] = []
    stats["#points"] = 0
    print("Number of surfaces: %i, Number of curves: %i" %
          (total_surfs, total_edges))
    #print(total_edges, total_surfs, len(gmsh_edges), len(gmsh_surfs))
    if not total_edges == len(gmsh_edges):
        print("Skipping due to wrong EDGES", model)
        return
    if not total_surfs == len(gmsh_surfs):
        print("Skipping due to wrong SURFS", model)
        return

    #print("Reading curvature")
    v_cnt = 1
    v_nodes = []
    occ_offset = 0
    invalid_model = False
    c_cnt = 0

    #v_cont_cnt = 0
    #print(len(list(occ_topo.edges())), len(list(occ_topo.solids())), len(list(occ_topo.faces())), len(list(occ_topo.vertices())))
    for e in gmsh_entities[:]:
        #print(e)
        nodeTags, nodeCoords, nodeParams = gmsh.model.mesh.getNodes(
            e[0], e[1], True)
        elemTypes, elemTags, elemNodeTags = gmsh.model.mesh.getElements(
            e[0], e[1])
        n_id = e[1] - occ_offset
        #print(e, occ_offset, n_id)
        #print(e, nodeTags, nodeCoords, nodeParams, gmsh.model.getType(e[0], e[1]), elemTypes, elemTags, elemNodeTags)
        if e[0] == 0:  # Process points
            #print(e[1], nodeCoords)
            vert_map[e[1]] = v_cnt
            verts.append([
                nodeCoords[0] * 1000.0, nodeCoords[1] * 1000.0,
                nodeCoords[2] * 1000.0
            ])
            v_cnt += 1
            stats["#points"] += 1

            #pass
        if e[0] == 1:  # Process contours
            if n_id - 1 == len(list(occ_topo.edges())):
                #print("CNT", occ_cnt)
                occ_cnt += 1
                occ_offset = e[1] - 1
                n_id = 1
                occ_topo = TopologyExplorer(occ_steps[occ_cnt])
                occ_top = Topo(occ_steps[occ_cnt])
                #print("Defunct curve", n_id, len(list(occ_topo.edges())))
                #continue
            #print(n_id)
            curve = BRepAdaptor_Curve(list(occ_topo.edges())[n_id - 1])
            # Add type and parametric nodes/indices
            #print("type", edge_map[curve.GetType()])
            if gmsh.model.getType(e[0], e[1]) == "Unknown":
                #print("Skipping OtherCurve", nodeTags)
                continue

            for i, n in enumerate(nodeTags):
                if n >= v_cnt:
                    vert_map[n] = v_cnt
                    verts.append([
                        nodeCoords[i * 3] * 1000.0,
                        nodeCoords[i * 3 + 1] * 1000.0,
                        nodeCoords[i * 3 + 2] * 1000.0
                    ])
                    v_cnt += 1
                else:
                    print(n, v_cnt)

            #print(v_ind, type(v_ind), v_par, type(v_par))
            stats["curves"].append(edge_map[curve.GetType()])
            #print(n_id, edge_map[curve.GetType()], gmsh.model.getType(e[0], e[1]))
            #print(list(occ_topo.edges()), n_id-1)
            c_type = edge_map[curve.GetType()]  #gmsh.model.getType(e[0], e[1])
            if not gmsh.model.getType(e[0], e[1]) == edge_map[curve.GetType()]:
                print("Skipped due to non matching edges ", model,
                      gmsh.model.getType(e[0], e[1]),
                      edge_map[curve.GetType()])
                #invalid_model = True
                #break

            d1_feat = convert_curve(curve)

            edg = list(occ_topo.edges())[n_id - 1]

            for f in occ_top.faces_from_edge(edg):
                #ee = (e)
                #print(dir(ee))
                #d1_feat = {}
                su = BRepAdaptor_Surface(f)
                c = BRepAdaptor_Curve2d(edg, f)
                t_curve = {
                    "surface": f,
                    "3dcurve": c_cnt,
                    "2dcurve": convert_2dcurve(c)
                }
                #print(edge_map[c.GetType()], surf_map[su.GetType()], edge_map[curve.GetType()])
                #d1f = convert_2dcurve(c)
                #print(d1f)
                #ccnt += 1
                #print(d1_feat)
                t_curves.append(t_curve)

            if len(elemNodeTags) > 0:
                #v_ind = [int(elemNodeTags[0][0]) - 1] # first vertex
                v_ind = [int(nodeTags[-2]) - 1]
                for no in nodeTags[:-2]:
                    v_ind.append(int(no) - 1)  # interior vertices
                v_ind.append(int(nodeTags[-1]) - 1)
                #v_ind.append(int(elemNodeTags[0][-1]) - 1) # last vertex
                d1_feat["vert_indices"] = v_ind
                #v_par = [float(curve.FirstParameter())] # first param
                v_par = [float(nodeParams[-2] * scale_factor)]
                for no in nodeParams[:-2]:
                    v_par.append(float(no * scale_factor))  # interior params
                v_par.append(float(nodeParams[-1] * scale_factor))
                #v_par.append(float(curve.LastParameter())) # last param
                d1_feat["vert_parameters"] = v_par
            else:
                print("No nodetags", edge_map[curve.GetType()], elemNodeTags)

            #print("VERTS", len(d1_feat["vert_indices"]), len(d1_feat["vert_parameters"]))
            d1_feats.append(d1_feat)
            c_cnt += 1
            #t_curve = curve.Trim(curve.FirstParameter(), curve.LastParameter(), 0.0001).GetObject()
            #print(curve.FirstParameter(), curve.LastParameter())

    #print("Processing surfaces")
    gmsh_entities = gmsh.model.getEntities(2)
    n_cnt = 1
    occ_offset = 0
    occ_cnt = 0
    occ_topo = TopologyExplorer(occ_steps[occ_cnt])
    occ_top = Topo(occ_steps[occ_cnt])
    f_cnt = 0
    f_sum = 0
    first_face = True
    mean_curv = 0.0
    curv_cnt = 0
    gaus_curv = 0.0
    s_cnt = 0

    for e in gmsh_entities[:]:
        #print(e)
        nodeTags, nodeCoords, nodeParams = gmsh.model.mesh.getNodes(
            e[0], e[1], True)
        elemTypes, elemTags, elemNodeTags = gmsh.model.mesh.getElements(
            e[0], e[1])
        n_id = e[1] - occ_offset
        #print(e, occ_offset, n_id)
        #print(e, nodeTags, nodeCoords, nodeParams, gmsh.model.getType(e[0], e[1]), elemTypes, elemTags, elemNodeTags)
        if e[0] == 2:
            #print(e, gmsh.model.getType(e[0], e[1]), elemTypes)
            if n_id - 1 == len(list(occ_topo.faces())):
                #print("CNT", occ_cnt)
                occ_cnt += 1
                occ_offset = e[1] - 1
                n_id = 1
                occ_topo = TopologyExplorer(occ_steps[occ_cnt])
                occ_top = Topo(occ_steps[occ_cnt])
            if "getNormals" in dir(gmsh.model):
                nls = gmsh.model.getNormals(e[1], nodeParams)
            else:
                nls = gmsh.model.getNormal(e[1], nodeParams)
            curvMax, curvMin, dirMax, dirMin = gmsh.model.getPrincipalCurvatures(
                e[1], nodeParams)
            #surf = BRepAdaptor_Surface(list(occ_topo.faces())[n_id-1])
            norm_map = {}
            for i, n in enumerate(nodeTags):
                norms.append([nls[i * 3], nls[i * 3 + 1], nls[i * 3 + 2]])
                curvs.append([
                    curvMin[i], curvMax[i], dirMin[i * 3], dirMin[i * 3 + 1],
                    dirMin[i * 3 + 2], dirMax[i * 3], dirMax[i * 3 + 1],
                    dirMax[i * 3 + 2]
                ])
                curv_cnt += 1
                mean_curv += (curvMin[i] + curvMax[i]) / 2.0
                gaus_curv += (curvMin[i] * curvMax[i])
                norm_map[n] = n_cnt
                n_cnt += 1
                if n in vert_map.keys():
                    v = verts[vert_map[n] - 1]
                    #print("Vert contained", n)
                    #v_cont_cnt += 1
                    #                    assert(v[0] == nodeCoords[i*3] * 1000.0 and v[1] == nodeCoords[i*3+1] * 1000.0 and v[2] == nodeCoords[i*3+2] * 1000.0)
                    continue
                else:
                    vert_map[n] = v_cnt
                #occ_node = surf.Value(nodeParams[i], nodeParams[i+1])
                #vertices.append([occ_node.X(), occ_node.Y(), occ_node.Z()])
                verts.append([
                    nodeCoords[i * 3] * 1000.0, nodeCoords[i * 3 + 1] * 1000.0,
                    nodeCoords[i * 3 + 2] * 1000.0
                ])
                #print("S", occ_node.Coord(), [nodeCoords[i*3]*1000, nodeCoords[i*3+1]*1000, nodeCoords[i*3+2]*1000])
                #print(occ_node.Coord(), nodeCoords[i*3:(i+1)*3])
                v_cnt += 1

            d2_faces = []
            for i, t in enumerate(elemTypes):
                for j in range(len(elemTags[i])):
                    faces.append([
                        vert_map[elemNodeTags[i][j * 3]],
                        vert_map[elemNodeTags[i][j * 3 + 1]],
                        vert_map[elemNodeTags[i][j * 3 + 2]],
                        norm_map[elemNodeTags[i][j * 3]],
                        norm_map[elemNodeTags[i][j * 3 + 1]],
                        norm_map[elemNodeTags[i][j * 3 + 2]]
                    ])
                    d2_faces.append(f_cnt)
                    f_cnt += 1
            #print(len(list(occ_topo.faces())), n_id-1)
            surf = BRepAdaptor_Surface(list(occ_topo.faces())[n_id - 1])
            #print("type", edge_map[curve.GetType()])
            #if gmsh.model.getType(e[0], e[1]) == "Unknown":
            #    print("Skipping OtherCurve", nodeTags)
            #    continue
            #print(surf)
            g_type = gmsh_map[gmsh.model.getType(e[0], e[1])]
            if g_type != "Other" and not g_type == surf_map[surf.GetType()]:
                print("Skipped due to non matching surfaces ", model, g_type,
                      surf_map[surf.GetType()])
                #invalid_model = True
                #break

            stats["surfs"].append(surf_map[surf.GetType()])

            d2_feat = convert_surface(surf)
            d2_feat["face_indices"] = d2_faces

            for tc in t_curves:
                if tc["surface"] == list(occ_topo.faces())[n_id - 1]:
                    tc["surface"] = s_cnt

            if len(elemNodeTags) > 0:
                #print(len(elemNodeTags[0]), len(nodeTags), len(nodeParams))
                v_ind = []  #int(elemNodeTags[0][0])] # first vertex
                for no in nodeTags:
                    v_ind.append(int(no) - 1)  # interior vertices
                #v_ind.append(int(elemNodeTags[0][-1])) # last vertex
                d2_feat["vert_indices"] = v_ind
                v_par = []  #float(surf.FirstParameter())] # first param
                for io in range(int(len(nodeParams) / 2)):
                    v_par.append([
                        float(nodeParams[io * 2] * scale_factor),
                        float(nodeParams[io * 2 + 1] * scale_factor)
                    ])  # interior params
                #v_par.append(float(surf.LastParameter())) # last param
                d2_feat["vert_parameters"] = v_par
            else:
                print("No nodetags", edge_map[curve.GetType()], elemNodeTags)

            f_sum += len(d2_feat["face_indices"])
            d2_feats.append(d2_feat)
            s_cnt += 1

    if invalid_model:
        return

    stats["#sharp"] = 0
    stats["gaus_curv"] = float(gaus_curv / curv_cnt)
    stats["mean_curv"] = float(mean_curv / curv_cnt)

    if not f_sum == len(faces):
        print("Skipping due to wrong FACES", model)
        return
    if True:
        vert2norm = {}
        for f in faces:
            #print(f)
            for fii in range(3):
                if f[fii] in vert2norm:
                    vert2norm[f[fii]].append(f[fii + 3])
                else:
                    vert2norm[f[fii]] = [f[fii + 3]]
        for d1f in d1_feats:
            sharp = True
            for vi in d1f["vert_indices"][1:-1]:
                #print(vi, vert2norm.keys())
                nos = list(set(vert2norm[vi + 1]))
                if len(nos) == 2:
                    n0 = np.array(norms[nos[0]])
                    n1 = np.array(norms[nos[1]])
                    #print(np.linalg.norm(n0), np.linalg.norm(n1))
                    if np.abs(n0.dot(n1)) > 0.95:
                        sharp = False
                        #break
                else:
                    sharp = False
            if sharp:
                stats["#sharp"] += 1
            d1f["sharp"] = sharp

    stats["#verts"] = len(verts)
    stats["#faces"] = len(faces)
    stats["#norms"] = len(norms)

    #with open("results/" + file + ".json", "w") as fil:
    #    json.dump(d1_feats, fil, sort_keys=True, indent=2)
    #with open("results/" + file + "_faces.json", "w") as fil:
    #   json.dump(d2_feats, fil, sort_keys=True, indent=2)

    features = {"curves": d1_feats, "surfaces": d2_feats, "trim": t_curves}
    if True:
        res_path = folder.replace("/step/", "/feat/")
        fip = fil.replace("_step_", "_features_")
        print("%s/%s.yml" % (res_path, fip))
        with open("%s/%s.yml" % (res_path, fip), "w") as fili:
            yaml.dump(features, fili, indent=2)

        res_path = folder.replace("/step/", "/stat/")
        fip = fil.replace("_step_", "_stats_")
        with open("%s/%s.yml" % (res_path, fip), "w") as fili:
            yaml.dump(stats, fili, indent=2)

        print("Generated model with %i vertices and %i faces." %
              (len(verts), len(faces)))
        res_path = folder.replace("/step/", "/obj/")
        fip = fil.replace("_step_", "_trimesh_")
        with open("%s/%s.obj" % (res_path, fip), "w") as fili:
            for v in verts:
                fili.write("v %f %f %f\n" % (v[0], v[1], v[2]))
            for vn in norms:
                #print(np.linalg.norm(vn))
                fili.write("vn %f %f %f\n" % (vn[0], vn[1], vn[2]))
            for vn in curvs:
                fili.write(
                    "vc %f %f %f %f %f %f %f %f\n" %
                    (vn[0], vn[1], vn[2], vn[3], vn[4], vn[5], vn[6], vn[7]))
            for f in faces:
                fili.write("f %i//%i %i//%i %i//%i\n" %
                           (f[0], f[3], f[1], f[4], f[2], f[5]))

        faces = np.array(faces)
        face_indices = faces[:, :3] - 1
        norm_indices = faces[:, 3:] - 1
    gmsh.clear()
    gmsh.finalize()
    #print(curvs)
    return {
        "statistics": stats,
        "features": features,
        "vertices": np.array(verts),
        "normals": np.array(norms),
        "curvatures": np.array(curvs),
        "face_indices": face_indices,
        "normal_indices": norm_indices,
        "trim": t_curves
    }
Exemple #12
0
import gmsh
import math
import sys

# This example shows how to implement a simple interactive pre-processor for a
# finite element solver; in particular, it shows how boundary conditions,
# material properties, etc., can be specified on parts of the model.

gmsh.initialize(sys.argv)
if len(sys.argv) > 1:
    gmsh.open(sys.argv[1])

# For Gmsh to know which types of boundary conditions, materials, etc., are
# available, you should define "template" ONELAB parameters with names
# containing the following substrings:
#
# - "ONELAB Context/Point Template/"
# - "ONELAB Context/Curve Template/"
# - "ONELAB Context/Surface Template/"
# - "ONELAB Context/Volume Template/"
#
# Double-clicking on an entity in the GUI will then pop-up a context window
# where instances of these variables for the given entity can be edited. For
# example, if the "ONELAB Context/Curve Template/0Boundary condition" exists,
# double-clicking on curve 123 in the model (or in the visibility browser) will
# create "ONELAB Context/Curve 123/0Boundary condition" (or "ONELAB
# Context/Physical Curve 1000/0Boundary condition" depending on the choice in
# the context window, if curve 123 belongs to the physical curve 1000). The
# context window is also shown automatically when a new physical group is
# created in the GUI.
#
Exemple #13
0
def read_gmsh(mesh, **kwargs):

    model = gmsh.model
    factory = model.geo

    gmsh.initialize()

    gmsh.open(mesh)

    logger.info("Analyze grid")

    nodeTags, coord, parametricCoord = gmsh.model.mesh.getNodes()

    nodes = pd.DataFrame(coord.reshape(-1, 3), columns=["x", "y", "z"])

    elementTags2, nodeTags2 = gmsh.model.mesh.getElementsByType(2)

    elems = nodeTags2.reshape(-1, 3)

    tria = pd.DataFrame(elems - 1, columns=["a", "b", "c"])

    # boundaries

    bounds = []

    bgs = gmsh.model.getPhysicalGroups()

    bgs = pd.DataFrame(bgs[:-1], columns=["dim", "tag"])

    # open boundaries
    logger.info("open boundaries")

    obs = bgs.loc[bgs.tag < 1000]

    for row in obs.itertuples(index=True, name="Pandas"):
        onodes, xyz = gmsh.model.mesh.getNodesForPhysicalGroup(
            dim=getattr(row, "dim"), tag=getattr(row, "tag"))

        db = pd.DataFrame({"node": onodes - 1})
        db["type"] = np.nan
        db["id"] = getattr(row, "Index") + 1

        bounds.append(db)

    # land boundaries type
    logger.info("land boundaries")

    lbs = bgs.loc[(bgs.tag > 1000) & (bgs.tag < 2000)]
    lbs.reset_index(inplace=True, drop=True)

    for row in lbs.itertuples(index=True, name="Pandas"):
        lnodes, xyz = gmsh.model.mesh.getNodesForPhysicalGroup(
            dim=getattr(row, "dim"), tag=getattr(row, "tag"))

        db = pd.DataFrame({"node": lnodes - 1})
        db["type"] = 0
        db["id"] = -(getattr(row, "Index") + 1)

        bounds.append(db)

    if lbs.empty:  # Store max index from land boundaries
        itag = 0
    else:
        itag = lbs.tag.max() - 1000

    # islands
    logger.info("islands")

    ibs = bgs.loc[bgs.tag > 2000]
    ibs.reset_index(inplace=True, drop=True)
    ibs.index = ibs.index + itag  # set index

    for row in ibs.itertuples(index=True, name="Pandas"):

        inodes, xyz = gmsh.model.mesh.getNodesForPhysicalGroup(
            dim=getattr(row, "dim"), tag=getattr(row, "tag"))
        db = pd.DataFrame({"node": inodes - 1})
        db["type"] = -1
        db["id"] = -(getattr(row, "Index") + 1)

        bounds.append(db)

    if bounds != []:
        bnodes = pd.concat(bounds).reset_index(drop=True)

        bnodes.index.name = "bnodes"

        bnodes = bnodes.drop_duplicates("node")

        bnodes["id"] = bnodes.id.astype(int)

    else:
        bnodes = pd.DataFrame({})

    # check if global and reproject
    sproj = kwargs.get("gglobal", False)
    if sproj:  # convert to lat/lon
        xd, yd = to_lat_lon(nodes.x, nodes.y)
        nodes["x"] = xd
        nodes["y"] = yd

    grid = pd.DataFrame({"lon": nodes.x, "lat": nodes.y})

    tri3 = tria.values

    logger.info("Finalize Dataset")

    ## make dataset
    els = xr.DataArray(
        tri3,
        dims=["nSCHISM_hgrid_face", "nMaxSCHISM_hgrid_face_nodes"],
        name="SCHISM_hgrid_face_nodes")

    nod = (grid.loc[:, ["lon", "lat"]].to_xarray().rename({
        "index":
        "nSCHISM_hgrid_node",
        "lon":
        "SCHISM_hgrid_node_x",
        "lat":
        "SCHISM_hgrid_node_y"
    }))
    nod = nod.drop_vars("nSCHISM_hgrid_node")

    dep = xr.Dataset({
        "depth":
        (["nSCHISM_hgrid_node"], np.zeros(nod.nSCHISM_hgrid_node.shape[0]))
    })

    gr = xr.merge([nod, els, dep, bnodes.to_xarray()])

    gmsh.finalize()

    return gr
Exemple #14
0
import gmsh
import sys

import numpy as np

gmsh.initialize(sys.argv)
gmsh.option.setNumber("General.Terminal", 1)
print(gmsh.option.getNumber("Mesh.Algorithm"))

gmsh.open("cube2d.msh")

model = gmsh.model

print("Nodes")
tags, coord, _ = model.mesh.getNodes(2, -1)
print(tags)
print(coord)

coord2 = np.asarray(coord)
coord2 = np.reshape(coord2, (np.int32(coord2.shape[0]) / 3, 3))

print(coord2)

gmsh.finalize()

import matplotlib.pyplot as plt
plt.figure(0)
plt.plot(coord2[:, 0], coord2[:, 1], 'b.')
plt.show()
Exemple #15
0
    def gmsh_to_mesh(self, filename):
        """Initialize self.points, self.segments and self.triangles with mesh
        stored in filename.

        Parameters
        ----------
        filename : str
            the file name
        """
        self.filename = filename
        gmsh.open(filename)

        # Fill self.points
        nodeTags, nodeCoords, _ = gmsh.model.mesh.getNodes()
        X = nodeCoords[0::3]
        Y = nodeCoords[1::3]
        for (tag, x, y) in zip(nodeTags, X, Y):
            point = Point(np.array([x, y]), tag)
            self.points.append(point)

        # Set number of points of mesh
        self.nbPoints = len(X)

        # Fill self.segments, self.triangles
        for dim, physical_tag in gmsh.model.getPhysicalGroups():
            for entity_tag in gmsh.model.getEntitiesForPhysicalGroup(
                    dim, physical_tag):
                elmType, elmTags, nodeTags = gmsh.model.mesh.getElements(
                    dim, entity_tag)

                # Segment
                if dim == 1:
                    for j in range(len(elmTags[0])):
                        ids = [nodeTags[0][2 * j], nodeTags[0][2 * j + 1]]
                        pts = [
                            point for point in self.points if point.id in ids
                        ]
                        segment = Segment(pts, physical_tag)
                        self.segments.append(segment)

                # Triangle
                elif dim == 2:
                    for j in range(len(elmTags[0])):
                        ids = [
                            nodeTags[0][3 * j], nodeTags[0][3 * j + 1],
                            nodeTags[0][3 * j + 2]
                        ]
                        points = [
                            point for point in self.points if point.tag in ids
                        ]
                        try:
                            triangle = Triangle(points, physical_tag)
                            self.triangles.append(triangle)
                        except Exception as e:
                            print("[WARNING] `Mesh.gmsh_to_mesh`:", e)
                            print("Points are:", [point.X for point in points])
                # Others
                else:
                    print(
                        f"[WARNING] `Mesh.gmsh_to_mesh`: Unknown element type '{dim}'."
                    )
Exemple #16
0
import gmsh
import sys

gmsh.initialize(sys.argv)
gmsh.option.setNumber("General.Terminal", 1)
print(gmsh.option.getNumber("Mesh.Algorithm"))

gmsh.open("square.msh")

model = gmsh.model

model.add("square")
factory = model.geo
factory.addPoint(0,0,0,0.1,1)
factory.addPoint(1,0,0,0.1,2)
factory.addPoint(1,1,0,0.1,3)
factory.addPoint(0,1,0,0.1,4)
factory.addLine(1,2,1)
factory.addLine(2,3,2)
factory.addLine(3,4,3)
line4 = factory.addLine(4,1)
print("line4 received tag ", line4)
factory.addCurveLoop([1,2,3,line4],1)
factory.addPlaneSurface([1],6)
factory.synchronize()

ptag = model.addPhysicalGroup(1,[1,2,3,4])
ent = model.getEntitiesForPhysicalGroup(1,ptag)
print("new physical group ",ptag,":",ent, type(ent))

model.addPhysicalGroup(2,[6])
Exemple #17
0
def get_plate_particles():
    gmsh.initialize()
    gmsh.open('t.msh')
    # Launch the GUI to see the results:
    # if '-nopopup' not in sys.argv:
    #     gmsh.fltk.run()

    nodeTags, nodesCoord, parametricCoord = gmsh.model.mesh.getNodes()
    liquid_x = nodesCoord[1::3]
    liquid_y = nodesCoord[2::3]
    liquid_z = nodesCoord[0::3]
    liquid_y = liquid_y + abs(min(liquid_y))
    liquid_x = liquid_x + abs(min(liquid_x))

    liquid_x = liquid_x[0::5] * 1e-3 - 0.002
    liquid_y = liquid_y[0::5] * 1e-3 - 0.1
    liquid_z = liquid_z[0::5] * 1e-3 - 0.005

    print('%d Target particles' % len(liquid_x))

    hf = numpy.ones_like(liquid_x) * h
    mf = numpy.ones_like(liquid_x) * dx * dy * dz * ro1
    rhof = numpy.ones_like(liquid_x) * ro1
    csf = numpy.ones_like(liquid_x) * cs1
    pa = plate = get_particle_array(name="plate",
                                    x=liquid_x,
                                    y=liquid_y,
                                    z=liquid_z,
                                    h=hf,
                                    m=mf,
                                    rho=rhof,
                                    cs=csf)

    # add requisite properties
    # sound speed etc.
    add_properties(pa, 'e')

    # velocity gradient properties
    add_properties(pa, 'v00', 'v01', 'v02', 'v10', 'v11', 'v12', 'v20', 'v21',
                   'v22')

    # artificial stress properties
    add_properties(pa, 'r00', 'r01', 'r02', 'r11', 'r12', 'r22')

    # deviatoric stress components
    add_properties(pa, 's00', 's01', 's02', 's11', 's12', 's22')

    # deviatoric stress accelerations
    add_properties(pa, 'as00', 'as01', 'as02', 'as11', 'as12', 'as22')

    # deviatoric stress initial values
    add_properties(pa, 's000', 's010', 's020', 's110', 's120', 's220')

    # standard acceleration variables
    add_properties(pa, 'arho', 'au', 'av', 'aw', 'ax', 'ay', 'az', 'ae')

    # initial values
    add_properties(pa, 'rho0', 'u0', 'v0', 'w0', 'x0', 'y0', 'z0', 'e0')

    pa.add_constant('G', G1)
    pa.add_constant('n', 4)

    kernel = Gaussian(dim=3)
    wdeltap = kernel.kernel(rij=dx, h=hdx * dx)
    pa.add_constant('wdeltap', wdeltap)
    # load balancing properties
    pa.set_lb_props(list(pa.properties.keys()))

    # removed S_00 and similar components
    plate.v[:] = 0.0
    return plate
def refine_mesh(
        in_file: str, out_file: str, dim: int,
        network: Union[pp.FractureNetwork3d, pp.FractureNetwork2d],
        num_refinements: int = 1,
) -> List[pp.GridBucket]:
    """ Refine a mesh by splitting, using gmsh

    Parameters
    ----------
    in_file : str
        path to .geo file to read
    out_file : str
        path to new .msh file to store mesh in, excluding the ending '.msh'.
    dim : int {2, 3}
        Dimension of domain to mesh
    network : Union[pp.FractureNetwork2d, pp.FractureNetwork3d]
        PorePy class defining the fracture network that is described by the .geo in_file
    num_refinements : int : Optional. Default = 1
        Number of refinements
    """

    try:
        import gmsh
    except ModuleNotFoundError:
        raise ModuleNotFoundError(
            "To run gmsh python api on your system, "
            "download the relevant gmsh*-sdk.* from http://gmsh.info/bin/. "
            "Then, Add the 'lib' directory from the SDK to PYTHONPATH: \n"
            "export PYTHONPATH=${PYTHONPATH}:path/to/gmsh*-sdk.*/lib"
        )

    from porepy.fracs.simplex import tetrahedral_grid_from_gmsh
    from porepy.fracs.meshing import grid_list_to_grid_bucket

    assert os.path.isfile(in_file)

    # Run gmsh
    gmsh.initialize()
    gmsh.open(in_file)
    gmsh.model.mesh.generate(dim=dim)
    if out_file[-4:] == ".msh":
        out_file = out_file[:-4]

    # Save coarsest grid
    fname = f"{out_file}_0.msh"
    gmsh.write(fname)
    grid_list_ref = tetrahedral_grid_from_gmsh(network=network, file_name=fname)
    gb_list = [grid_list_to_grid_bucket(grid_list_ref)]

    for i in range(num_refinements):
        gmsh.model.mesh.refine()  # Refined grid

        fname = f"{out_file}_{i+1}.msh"
        gmsh.write(fname)

        # Create grid bucket from refined grid output
        grid_list_ref = tetrahedral_grid_from_gmsh(network=network, file_name=fname)
        gb_ref = grid_list_to_grid_bucket(grid_list_ref)
        gb_list.append(gb_ref.copy())

    gmsh.finalize()
    return gb_list
Exemple #19
0
    def create(self, is3D=False):
        '''
        Meshes a surface or volume defined by the geometry in geoData.
        Parameters:
        is3D - Optional parameter that only needs to be set if geometry
               is loaded from a geo-file, i.e. if geoData is a path string.
               Default False.

        Returns:

            coords          Node coordinates

                            [[n0_x, n0_y, n0_z],
                            [   ...           ],
                            [nn_x, nn_y, nn_z]]

            edof            Element topology

                            [[el0_dof1, ..., el0_dofn],
                            [          ...          ],
                            [eln_dof1, ..., eln_dofn]]

            dofs            Node dofs

                            [[n0_dof1, ..., n0_dofn],
                            [         ...         ],
                            [nn_dof1, ..., nn_dofn]]

            bdofs           Boundary dofs. Dictionary containing lists of dofs for
                            each boundary marker. Dictionary key = marker id.

            elementmarkers  List of integer markers. Row i contains the marker of
                            element i. Markers are similar to boundary markers and
                            can be used to identify in which region an element lies.

            boundaryElements  (optional) returned if self.return_boundary_elements is true.
                              Contains dictionary with boundary elements. The keys are markers
                              and the values are lists of elements for that marker.

        Running this function also creates object variables:

            nodesOnCurve    Dictionary containing lists of node-indices. Key is a 
                            curve-ID and the value is a list of indices of all nodes
                            on that curve, including its end points.

            nodesOnSurface  Dictionary containing lists of node-indices. Key is a
                            surface-ID and the value is a list of indices of the nodes
                            on that surface, including its boundary.

            nodesOnVolume   Dictionary containing lists of node-indices. Key is a
                            volume-ID and the value is a list of indices of the nodes
                            in that volume, including its surface. 
        '''
        # Nodes per element for different element types:
        # (taken from Chapter 9, page 89 of the gmsh manual)
        nodesPerElmDict = {1: 2,   2: 3,   3: 4,   4: 4,   5: 8,
                           6: 6,   7: 5,   8: 3,   9: 6,  10: 9,
                           11: 10, 12: 27, 13: 18, 14: 14, 15: 1,
                           16: 8,  17: 20, 18: 15, 19: 13, 20: 9,
                           21: 10, 22: 12, 23: 15, 24: 15, 25: 21,
                           26: 4,  27: 5,  28: 6,  29: 20, 30: 35,
                           31: 56, 92: 64, 93: 125}
        nodesPerElement = nodesPerElmDict[self.el_type]

        # Check for GMSH executable 
        # 
        # Consider using the gmsh_extension module

        if not self.use_gmsh_module:
            gmshExe = self.gmsh_exec_path
            if gmshExe == None:
                gmshExe = None
                if sys.platform == "win32":
                    gmshExe = which("gmsh.bat")
                    if gmshExe == None:
                        gmshExe = which("gmsh.exe")
                else:
                    gmshExe = which("gmsh")
            else:
                if not os.path.exists(gmshExe):
                    gmshExe = os.path.join(
                        os.getcwd(), self.gmsh_exec_path)  # Try relative path
                    if not os.path.exists(gmshExe):
                        gmshExe = None  # Relative path didnt work either

            if gmshExe == None:
                raise IOError(
                    "Error: Could not find GMSH. Please make sure that the \GMSH executable is available on the search path (PATH).")
            else:
                print("Info    : GMSH -> %s" % gmshExe)
        else:
            print("Info    : GMSH -> Python-module")

        # Create a temporary directory for GMSH

        oldStyleTempDir = False

        if self.mesh_dir != "":
            tempMeshDir = self.mesh_dir
            if not os.path.exists(tempMeshDir):
                os.mkdir(tempMeshDir)
        else:
            tempMeshDir = tempfile.mkdtemp()

        # If geometry data is given as a .geo file we will just pass it on to gmsh later.

        if type(self.geometry) is str:
            geoFilePath = self.geometry

            # In this case geoData is a path string, so the dimension must be supplied by the user.

            dim = 3 if is3D else 2
            if not os.path.exists(geoFilePath):
                geoFilePath = os.path.join(
                    os.getcwd(), geoFilePath)  # Try relative path
                if not os.path.exists(geoFilePath):
                    raise IOError(
                        "Error: Could not find geo-file " + geoFilePath)
        else:

            # Get the dimension of the model from geoData.

            dim = 3 if self.geometry.is3D else 2

            if oldStyleTempDir:
                if not os.path.exists("./gmshMeshTemp"):
                    os.mkdir("./gmshMeshTemp")
                geoFilePath = os.path.normpath(os.path.join(
                    os.getcwd(), "gmshMeshTemp/tempGeometry.geo"))  # "gmshMeshTemp/tempGeometry.geo"
            else:
                geoFilePath = os.path.normpath(
                    os.path.join(tempMeshDir, 'tempGeometry.geo'))

            with open(geoFilePath, "w") as self.geofile:
                self._writeGeoFile()  # Write geoData to file

        if oldStyleTempDir:

            # Filepath to the msh-file that will be generated.

            mshFileName = os.path.normpath(os.path.join(
                os.getcwd(), 'gmshMeshTemp/meshFile.msh'))
        else:
            mshFileName = os.path.normpath(
                os.path.join(tempMeshDir, 'meshFile.msh'))

        # construct options string:

        options = ""
        options += ' -' + str(dim)
        options += ' -clscale ' + str(self.el_size_factor)  # scale factor
        options += ' -o \"%s\"' % mshFileName
        options += ' -clcurv' if self.clcurv else ''
        options += ' -clmin ' + \
            str(self.min_size) if self.min_size is not None else ''
        options += ' -clmax ' + \
            str(self.max_size) if self.max_size is not None else ''
        options += ' -algo ' + self.meshing_algorithm if self.meshing_algorithm is not None else ''
        options += ' -order 2' if self.el_type in self._2ndOrderElms else ''
        options += ' -format msh22'
        options += ' -v 5'
        options += ' ' + self.additional_options

        # Execute gmsh

        if self.use_gmsh_module:

            # Meshing using gmsh extension module

            if self.initialize_gmsh:
                gmsh.initialize(sys.argv)

            # This is a hack to enable the use of gmsh in 
            # a separate thread.

            if self.remove_gmsh_signal_handler:
                gmsh.oldsig = None

            # Load .geo file

            gmsh.open(geoFilePath)
            gmsh.model.geo.synchronize()

            # Set meshing options

            if self.el_type in self._2ndOrderElms:
                gmsh.option.setNumber("Mesh.ElementOrder", 2)
            
            if self.meshing_algorithm is not None:
                gmsh.option.setString(self.meshing_algorithm)
            
            gmsh.option.setNumber("Mesh.MshFileVersion", 2.2)
            gmsh.option.setNumber("Mesh.MeshSizeFactor", self.el_size_factor)

            if self.clcurv is not None:
                gmsh.option.setNumber("Mesh.MeshSizeFromCurvature", self.clcurv)

            if self.min_size is not None:
                gmsh.option.setNumber('Mesh.MeshSizeMin', self.min_size)
            if self.max_size is not None:
                gmsh.option.setNumber('Mesh.MeshSizeMax', self.max_size)

            # Generate mesh

            gmsh.model.mesh.generate(2)

            # Write .msh file

            gmsh.write(mshFileName)

            # Close extension module

            if self.initialize_gmsh:
                gmsh.finalize()            
        else:
            gmshExe = os.path.normpath(gmshExe)
            info("GMSH binary: "+gmshExe)

            output = subprocess.Popen(r'"%s" "%s" %s' % (
                gmshExe, geoFilePath, options), shell=True, stdout=subprocess.PIPE).stdout.read()
        
        # Read generated msh file:
        # print("Opening msh file " + mshFileName)#TEMP

        with open(mshFileName, 'r') as mshFile:

            info("Mesh file  : "+mshFileName)

            # print("Reading msh file...")

            ln = mshFile.readline()
            while(ln != '$Nodes\n'):  # Read until we find the nodes
                ln = mshFile.readline()
            nbrNodes = int(mshFile.readline())
            allNodes = np.zeros([nbrNodes, dim], 'd')
            for i in range(nbrNodes):
                line = list(map(float, mshFile.readline().split()))

                # Grab the coordinates (1:3 if 2D, 1:4 if 3D)

                allNodes[i, :] = line[1:dim+1]

            while(mshFile.readline() != '$Elements\n'):  # Read until we find the elements
                pass

            # The nbr of elements (including marker elements).

            nbrElements = int(mshFile.readline())
            elements = []
            elementmarkers = []

            # temp dictionary of sets. Key:MarkerID. Value:Set. The sets will be converted to lists.

            bdofs = {}
            boundaryElements = {}

            # nodeOnPoint = {}  #dictionary pointID : nodeNumber

            self.nodesOnCurve = {}  # dictionary lineID  : set of [nodeNumber]
            self.nodesOnSurface = {}  # dictionary surfID  : set of [nodeNumber]
            self.nodesOnVolume = {}  # dictionary volID   : set of [nodeNumber]

            # Read all elements (points, surfaces, etc):

            for i in range(nbrElements):
                line = list(map(int, mshFile.readline().split()))
                eType = line[1]  # second int is the element type.
                nbrTags = line[2]  # Third int is the nbr of tags on this element.
                marker = line[3]  # Fourth int (first tag) is the marker.

                # Fifth int  is the ID of the geometric entity (points, curves, etc) that the element belongs to

                entityID = line[4]

                # The rest after tags are node indices.

                nodes = line[3+nbrTags: len(line)]

                # If the element type is the kind of element we are looking for:

                if(eType == self.el_type):

                    # Add the nodes of the elements to the list.

                    elements.append(nodes)

                    # Add element marker. It is used for keeping track of elements (thickness, heat-production and such)

                    elementmarkers.append(marker)
                else:  # If the element is not a "real" element we store its node at marker in bdof instead:
                    _insertInSetDict(bdofs, marker, nodes)

                    # We also store the full information as 'boundary elements'

                    _insertBoundaryElement(boundaryElements, eType, marker, nodes)

                # if eType == 15: #If point. Commmented away because points only make elements if they have non-zero markers, so nodeOnPoint is not very useful.
                #    nodeOnPoint[entityID-1] = nodes[0] #insert node into nodeOnPoint. (ID-1 because we want 0-based indices)

                if eType in [1, 8, 26, 27, 28]:  # If line

                    # insert nodes into nodesOnCurve

                    _insertInSetDict(self.nodesOnCurve, entityID -
                                    1, _offsetIndices(nodes, -1))
                elif eType in [2, 3, 9, 10, 16, 20, 21, 22, 23, 24, 25]:  # If surfaceelement

                    # insert nodes into nodesOnSurface

                    _insertInSetDict(self.nodesOnSurface, entityID -
                                    1, _offsetIndices(nodes, -1))
                else:  
                    
                    # if volume element.

                    _insertInSetDict(self.nodesOnVolume, entityID -
                                    1, _offsetIndices(nodes, -1))

            elements = np.array(elements)
            for key in bdofs.keys():  # Convert the sets of boundary nodes to lists.
                bdofs[key] = list(bdofs[key])
            for key in self.nodesOnCurve.keys():  # Convert set to list
                self.nodesOnCurve[key] = list(self.nodesOnCurve[key])
            for key in self.nodesOnSurface.keys():  # Convert set to list
                self.nodesOnSurface[key] = list(self.nodesOnSurface[key])
            for key in self.nodesOnVolume.keys():  # Convert set to list
                self.nodesOnVolume[key] = list(self.nodesOnVolume[key])

        # Remove temporary mesh directory if not explicetly specified.

        if self.mesh_dir == "":
            shutil.rmtree(tempMeshDir)

        dofs = createdofs(np.size(allNodes, 0), self.dofs_per_node)

        if self.dofs_per_node > 1:  # This if-chunk copied from pycalfem_utils.py
            self.topo = elements
            expandedElements = np.zeros(
                (np.size(elements, 0), nodesPerElement*self.dofs_per_node), 'i')
            elIdx = 0
            for elementTopo in elements:
                for i in range(nodesPerElement):
                    expandedElements[elIdx, i*self.dofs_per_node:(
                        i*self.dofs_per_node+self.dofs_per_node)] = dofs[elementTopo[i]-1, :]
                elIdx += 1

            for keyID in bdofs.keys():
                bVerts = bdofs[keyID]
                bVertsNew = []
                for i in range(len(bVerts)):
                    for j in range(self.dofs_per_node):
                        bVertsNew.append(dofs[bVerts[i]-1][j])
                bdofs[keyID] = bVertsNew

            if self.return_boundary_elements:
                return allNodes, np.asarray(expandedElements), dofs, bdofs, elementmarkers, boundaryElements
            return allNodes, np.asarray(expandedElements), dofs, bdofs, elementmarkers

        if self.return_boundary_elements:
            return allNodes, elements, dofs, bdofs, elementmarkers, boundaryElements
        return allNodes, elements, dofs, bdofs, elementmarkers
Exemple #20
0
if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument("-m", "--mesh_file", action='store', default="mesh.msh", help="def = 'mesh.msh'")
    parser.add_argument("-n", "--group_name", action='store', default="reticle_FS", help="def = 'reticle_FS'")
    parser.add_argument("-dx", action='store', default=None, help="x boundaries of area of interest; format 'lhs rhs' [def=None - no restriction]")
    parser.add_argument("-dy", action='store', default=None, help="y boundaries of area of interest; format 'lhs rhs' [def=None - no restriction]")
    parser.add_argument("-dz", action='store', default=None, help="z boundaries of area of interest; format 'lhs rhs' [def=None - no restriction]")
    args = parser.parse_args()
    
    x_bnd = get_boundary(args.dx)
    y_bnd = get_boundary(args.dy)
    z_bnd = get_boundary(args.dz)
        
    gmsh.initialize()
    gmsh.open(args.mesh_file)
    dim_tag = get_phys_group_dim_tag(args.group_name)
    entity_data = download_elements(dim_tag)
    print("Finished with entity data")
    area = calculate_area(entity_data, x_bnd, y_bnd, z_bnd)
    gmsh.finalize()
    
    print("Area = %.6e cm^2" % area)    
    
    
    
    
    
    
    
    
Exemple #21
0
def meshFromParametricGeometry(filepath, outputdir='autogen/', meshtype='Surface', **kwargs):
        """
        generate a tetrahedron and/or a surface mesh from the provided file and store the 
        result in a volumetric (vtk) or surfacic file (stl, etc.). The path to the file is returned. 
           
        :param str filepath: 
            The path to the file (including extension) to the parametric mesh.
        :param str outputdir:
            The path to the directory where the meshed file will be stored.
        :param str meshtype:
            This accepts the values 'Surface' or 'Volumetric', i.e. the type of mesh to generate from the source
        
        :param dict **kwargs:
          
            This function accepts through the kwargs all options that can be set in Gmsh as found in the documentation:
            http://gmsh.info/doc/texinfo/gmsh.html. The options in the referenced documentation are sorted into categories ("Mesh", "Geometry", etc.) and separated by a point, e.g. "Mesh.CharacteristicLengthFactor". 
            The same option passed as kwarg is separated by an underscore, e.g. "Mesh_CharacteristicLengthFactor=0.8". See example below.
        """ 
        import splib.caching.cacher as cch
        import gmsh      
        import os
        import numpy as np
        #import locale        
        #locale.setlocale(locale.LC_ALL, "C")
        
        with LocaleManager('C'):       
            # Set options from kwargs           
            OptionsStrings, Values = cch.extractOptions(kwargs)        
            
            gmsh.initialize()
            for i in range(0, len(OptionsStrings)):            
                SplitStr = OptionsStrings[i].split('_')
                Category = SplitStr[0]
                Option = SplitStr[1]
                GmshOptionStr = Category+'.'+Option 
                if isinstance(Values[i], str):  # need to be careful to call the correct function according to the type of value (string or numerical)
                    gmsh.option.setString(GmshOptionStr, Values[i])
                else:
                    gmsh.option.setNumber(GmshOptionStr, Values[i])                
                
            Refresh = False
            OutputFilePath = ''        
            FileNameWithExt = os.path.split(filepath)[1]
            FileNameNoExt = os.path.splitext(FileNameWithExt)[0]                
            
            #Refresh, OutputFilePath = casher(filepath, outputdir, '.stl', kwargs, FileNameNoExt)
                        
            if meshtype == 'Surface':            
                Refresh, OutputFilePath = cch.cacher(filepath, outputdir, '.stl', kwargs, FileNameNoExt)
            elif meshtype == 'Volumetric':            
                Refresh, OutputFilePath = cch.cacher(filepath, outputdir, '.vtk', kwargs, FileNameNoExt)
            
    
            if Refresh:
                logging.info(' Beginning meshing ' + str(filepath) + ' ...')
                gmsh.initialize()
                gmsh.open(filepath)
                if meshtype == 'Surface':
                    gmsh.model.mesh.generate(2)
                elif meshtype == 'Volumetric':
                    gmsh.model.mesh.generate(3)    
                gmsh.write(OutputFilePath)
                logging.info(' Finished meshing.')   
    
            gmsh.finalize()
            return OutputFilePath
Exemple #22
0
def tag_mesh_entities(input_mesh, boundary_files, roi_labels, scale_ratio=1.0, \
    duplicate=False, output_mesh=None, interactive=False):
    """Tag mesh entities
    Args:
        input_mesh: path to a GMSH mesh
        boundary_mesh_files: A list of file locations to surface meshes whose combinations define
        the ROI boundaries.
        roi_labels: A dict of [ROI_ID : ROI_SIGNATURES] pairs.
        scale_ratio: scale conversion factor between stl and msh
        duplicate: allow duplication of tets tagged multiple times
        interactive: to visualize the mesh using the graphical UI provide by gmsh API
        output_mesh: in-place edit if None, path to output mesh otherwise
    """

    gmsh.option.setNumber("General.Terminal", 1)

    # Open file
    gmsh.open(input_mesh)
    if gmsh.model.getDimension() < 0:
        print("Could not find " + input_mesh, file=sys.stderr)
        exit()

    # Print the model name and dimension:
    print('Model ' + gmsh.model.getCurrent() + ' (' +
          str(gmsh.model.getDimension()) + 'D)')

    # Create spatial index
    spatial_index = gen_tet_spatial_index(gmsh.model.mesh)

    # Tag ROIs
    ROIs = add_tet_ROIs(gmsh.model.mesh, scale_ratio, spatial_index, \
        boundary_files, roi_labels)
    print("Found: ", len(ROIs), "ROIs")

    # Get element ids and node ids in mesh from element type
    ele_ids, node_ids = gmsh.model.mesh.getElementsByType(tet_t.etype)
    nTets = len(ele_ids)
    print("Number of tets in original mesh: ", nTets)

    # Save old entities
    old_ent = gmsh.model.getEntities(dim=tet_t.dim)
    nEntities_old = len(old_ent)
    print("Number of entities in original mesh: ", nEntities_old)

    # Save old phys groups and names (only 3D)
    old_grp = gmsh.model.getPhysicalGroups(dim=tet_t.dim)
    old_grp_names = list()
    for grp in old_grp:
        old_grp_names.append(gmsh.model.getPhysicalName(grp[0], grp[1]))

    # Select tets based on ROI list
    nROIs = len(ROIs)
    nEntities = nROIs + nEntities_old  # ROIs plus original volumes
    tets_select = [[] for _ in range(nEntities)]  # selected elements
    nodes_select = [[] for _ in range(nEntities)]  # correspoding nodes
    nodes_coords = [[] for _ in range(nEntities)]  # nodes coordinates

    for i in range(nTets):
        is_in_ROIs = False
        # Loop over ROIs to select tag
        for id_roi in range(nROIs):
            for t in ROIs[id_roi]:
                if t == i:
                    if is_in_ROIs and not duplicate:
                        raise Exception(
                            "ROIs overlap detected, you need to enable dublication of tets"
                        )

                    is_in_ROIs = True
                    id_entity = id_roi + nEntities_old
                    tets_select[id_entity].extend([ele_ids[i]])
                    nodes_select[id_entity].extend(node_ids[tet_t.nnodes*i:\
                        tet_t.nnodes*i+tet_t.nnodes])
                    for n in range(tet_t.nnodes):
                        node = node_ids[i * tet_t.nnodes + n]
                        # Get coordinates (and parametric coor if available) from node id
                        node_coo = gmsh.model.mesh.getNode(node)[0]
                        nodes_coords[id_entity].extend(node_coo)

        if not is_in_ROIs:
            # Not in a ROI, check to which entity it used to belong
            id_entity = -1
            ent_count = 0
            for dont_care, ent_tag in old_ent:
                elementTags, nodeTags = gmsh.model.mesh.getElementsByType(
                    tet_t.etype, tag=ent_tag)
                if np.isin(elementTags, ele_ids[i]).any():
                    id_entity = ent_count
                ent_count += 1
            # Did we find the tet
            if id_entity < 0:
                raise "cannot find entity fot tet"
            tets_select[id_entity].extend([ele_ids[i]])
            nodes_select[id_entity].extend(node_ids[tet_t.nnodes*i:\
                tet_t.nnodes*i+tet_t.nnodes])
            for n in range(tet_t.nnodes):
                node = node_ids[i * tet_t.nnodes + n]
                # Get coordinates (and parametric coor if available) from node id
                node_coo = gmsh.model.mesh.getNode(node)[0]
                nodes_coords[id_entity].extend(node_coo)

    # Clear mesh and model
    if (output_mesh == None):
        output_mesh = gmsh.model.getCurrent() + ".msh"
    gmsh.clear()

    # Add new discrete entities: old entities + ROIs based entities
    if old_grp:
        # get last old tag
        base_tag = old_grp[-1][1]
    else:
        # only untagged tets were present
        base_tag = 1
    roi_names = list(roi_labels.keys())
    for i in range(nEntities):
        vnew = gmsh.model.addDiscreteEntity(tet_t.dim)
        gmsh.model.mesh.addNodes(tet_t.dim, vnew, nodes_select[i],
                                 nodes_coords[i])
        gmsh.model.mesh.removeDuplicateNodes()
        gmsh.model.mesh.addElementsByType(vnew, tet_t.etype, tets_select[i],
                                          nodes_select[i])

        if i < nEntities_old:
            if old_grp:
                volume_tag = old_grp[i][1]
            else:
                volume_tag = base_tag
            gmsh.model.addPhysicalGroup(dim=tet_t.dim,
                                        tags=[vnew],
                                        tag=volume_tag)
            if old_grp_names:
                ent_tag = old_grp_names[i]
                gmsh.model.setPhysicalName(dim=tet_t.dim,
                                           tag=volume_tag,
                                           name=ent_tag)

        else:
            volume_tag = base_tag + i - nEntities_old + 1
            gmsh.model.addPhysicalGroup(dim=tet_t.dim,
                                        tags=[vnew],
                                        tag=volume_tag)
            gmsh.model.setPhysicalName(dim=tet_t.dim,
                                       tag=volume_tag,
                                       name=roi_names[i - nEntities_old])

    # Get element ids and node ids in mesh from element type (check nTets)
    ele_ids, node_ids = gmsh.model.mesh.getElementsByType(tet_t.etype)
    nTets = len(ele_ids)
    print("Number of tets in new mesh: ", nTets)

    # To visualize the model we can run the graphical user interface from gmsh
    if interactive:
        gmsh.fltk.run()

    gmsh.write(output_mesh)
Exemple #23
0
    def __init__(self,
                 AP,
                 path_to_geo,
                 S=None,
                 R=None,
                 fmax=1000,
                 num_freq=6,
                 scale=1,
                 order=1,
                 plot=False):

        self.R = R
        self.S = S
        self.path_to_geo = path_to_geo
        self.fmax = fmax
        self.num_freq = num_freq
        self.scale = scale
        self.order = order

        self.c0 = np.real(AP.c0)

        import meshio
        import gmsh
        import sys
        import os
        filename, file_extension = os.path.splitext(path_to_geo)
        if path_to_geo == '.geo' or '.brep':
            gmsh.initialize(sys.argv)
            gmsh.open(self.path_to_geo)  # Open msh

            # dT = gmsh.model.getEntities()
            # gmsh.model.occ.dilate(dT,0,0,0,1/scale,1/scale,1/scale)
            gmsh.option.setNumber("Mesh.MeshSizeMax", (self.c0 * self.scale) /
                                  self.fmax / self.num_freq)
            gmsh.option.setNumber(
                "Mesh.MeshSizeMin",
                0.1 * (self.c0 * self.scale) / self.fmax / self.num_freq)

            lc = 0  #(self.c0*self.scale)/self.fmax/self.num_freq
            tg = gmsh.model.occ.getEntities(3)
            # tg2 = gmsh.model.occ.getEntities(2)
            if self.R != None:
                for i in range(len(self.R.coord)):
                    it = gmsh.model.occ.addPoint(self.R.coord[i, 0],
                                                 self.R.coord[i, 1],
                                                 self.R.coord[i, 2], lc, -1)
                    gmsh.model.occ.synchronize()
                    gmsh.model.mesh.embed(0, [it], 3, tg[0][1])

            if self.S != None:
                for i in range(len(self.S.coord)):
                    it = gmsh.model.occ.addPoint(self.S.coord[i, 0],
                                                 self.S.coord[i, 1],
                                                 self.S.coord[i, 2], lc, -1)
                    gmsh.model.occ.synchronize()
                    gmsh.model.mesh.embed(0, [it], 3, tg[0][1])

            # gmsh.model.mesh.embed(0, [15000], 3, tg[0][1])
            gmsh.model.mesh.generate(3)
            gmsh.model.mesh.setOrder(self.order)
            # gmsh.model.mesh.optimize(method='Relocate3D',force=False)
            if self.order == 1:
                elemTy, elemTa, nodeTags = gmsh.model.mesh.getElements(3)
                self.elem_vol = np.array(nodeTags, dtype=int).reshape(-1,
                                                                      4) - 1

                elemTys, elemTas, nodeTagss = gmsh.model.mesh.getElements(2)
                self.elem_surf = np.array(nodeTagss, dtype=int).reshape(-1,
                                                                        3) - 1
                vtags, vxyz, _ = gmsh.model.mesh.getNodes()
                self.nos = vxyz.reshape((-1, 3)) / scale

            if self.order == 2:
                elemTy, elemTa, nodeTags = gmsh.model.mesh.getElements(3)
                self.elem_vol = np.array(nodeTags, dtype=int).reshape(-1,
                                                                      10) - 1

                elemTys, elemTas, nodeTagss = gmsh.model.mesh.getElements(2)
                self.elem_surf = np.array(nodeTagss, dtype=int).reshape(-1,
                                                                        6) - 1
                vtags, vxyz, _ = gmsh.model.mesh.getNodes()
                self.nos = vxyz.reshape((-1, 3)) / scale

            pg = gmsh.model.getPhysicalGroups(2)
            va = []
            vpg = []
            for i in range(len(pg)):
                v = gmsh.model.getEntitiesForPhysicalGroup(2, pg[i][1])
                for ii in range(len(v)):
                    # print(v[ii])
                    vvv = gmsh.model.mesh.getElements(2, v[ii])[1][0]
                    pgones = np.ones_like(vvv) * pg[i][1]
                    va = np.hstack((va, vvv))
                    # print(pgones)
                    vpg = np.hstack((vpg, pgones))

            vas = np.argsort(va)
            self.domain_index_surf = vpg[vas]

            pgv = gmsh.model.getPhysicalGroups(3)

            vav = []
            vpgv = []
            for i in range(len(pgv)):
                vv = gmsh.model.getEntitiesForPhysicalGroup(3, pgv[i][1])
                for ii in range(len(vv)):
                    # print(v[ii])
                    vvv = gmsh.model.mesh.getElements(3, vv[ii])[1][0]
                    pgones = np.ones_like(vvv) * pgv[i][1]
                    vavsv = np.hstack((vav, vvv))
                    # print(pgones)
                    vpgv = np.hstack((vpgv, pgones))

            vasv = np.argsort(vavsv)
            self.domain_index_vol = vpgv[vasv]
            # gmsh.model.mesh.optimize()
            gmsh.model.occ.synchronize()

            if plot:
                gmsh.fltk.run()
            # gmsh.fltk.run()
            path_name = os.path.dirname(self.path_to_geo)

            gmsh.write(path_name + '/current_mesh2.vtk')
            self.model = gmsh.model
            gmsh.finalize()

            msh = meshio.read(path_name + '/current_mesh2.vtk')
        elif file_extension == '.msh' or 'vtk':
            msh = meshio.read(path_to_geo)

            self.msh = msh
            # os.remove(path_name+'/current_mesh.msh')

            if order == 1:
                self.nos = msh.points / scale
                self.elem_surf = msh.cells_dict["triangle"]
                self.elem_vol = msh.cells_dict["tetra"]

                self.domain_index_surf = msh.cell_data_dict["CellEntityIds"][
                    "triangle"]
                self.domain_index_vol = msh.cell_data_dict["CellEntityIds"][
                    "tetra"]
                # self.domain_index_surf = msh.cell_data_dict["gmsh:physical"]["triangle"]
                # self.domain_index_vol = msh.cell_data_dict["gmsh:physical"]["tetra"]
            # elif order == 2:
            #     self.elem_surf = msh.cells_dict["triangle6"]
            #     self.elem_vol = msh.cells_dict["tetra10"]

            #     self.domain_index_surf = msh.cell_data_dict["gmsh:physical"]["triangle6"]
            #     self.domain_index_vol = msh.cell_data_dict["gmsh:physical"]["tetra10"]

            elif order == 2:
                # self.elem_surf = msh.cells_dict["triangle6"]
                # self.elem_vol = msh.cells_dict["tetra10"]

                self.domain_index_surf = msh.cell_data_dict["CellEntityIds"][
                    "triangle6"]
                self.domain_index_vol = msh.cell_data_dict["CellEntityIds"][
                    "tetra10"]

        self.number_ID_faces = np.unique(self.domain_index_surf)
        self.number_ID_vol = np.unique(self.domain_index_vol)

        self.NumNosC = len(self.nos)
        self.NumElemC = len(self.elem_vol)
Exemple #24
0
def read_msh(filename, **kwargs):

    model = gmsh.model
    factory = model.geo

    gmsh.initialize()

    gmsh.open(filename)

    logger.info("Analyze grid")

    nodeTags, coord, parametricCoord = gmsh.model.mesh.getNodes()

    nodes = pd.DataFrame(coord.reshape(-1, 3), columns=["x", "y", "z"])

    elementTags2, nodeTags2 = gmsh.model.mesh.getElementsByType(2)

    elems = nodeTags2.reshape(-1, 3)

    tria = pd.DataFrame(elems - 1, columns=["a", "b", "c"])

    # boundaries

    bounds = []

    bgs = gmsh.model.getPhysicalGroups()

    bgs = pd.DataFrame(bgs[:-1], columns=["dim", "tag"])

    # open boundaries
    logger.info("open boundaries")

    obs = bgs.loc[bgs.tag < 1000]

    for row in obs.itertuples(index=True, name="Pandas"):
        onodes, xyz = gmsh.model.mesh.getNodesForPhysicalGroup(
            dim=getattr(row, "dim"), tag=getattr(row, "tag"))

        db = pd.DataFrame({"node": onodes - 1})
        db["type"] = "open"
        db["id"] = getattr(row, "Index") + 1

        bounds.append(db)

    # land boundaries type
    logger.info("land boundaries")

    lbs = bgs.loc[(bgs.tag > 1000) & (bgs.tag < 2000)]
    lbs.reset_index(inplace=True, drop=True)

    for row in lbs.itertuples(index=True, name="Pandas"):
        lnodes, xyz = gmsh.model.mesh.getNodesForPhysicalGroup(
            dim=getattr(row, "dim"), tag=getattr(row, "tag"))

        db = pd.DataFrame({"node": lnodes - 1})
        db["type"] = "land"
        db["id"] = 1000 + (getattr(row, "Index") + 1)

        bounds.append(db)

    # islands
    logger.info("islands")

    ibs = bgs.loc[bgs.tag > 2000]
    ibs.reset_index(inplace=True, drop=True)

    for row in ibs.itertuples(index=True, name="Pandas"):

        inodes, xyz = gmsh.model.mesh.getNodesForPhysicalGroup(
            dim=getattr(row, "dim"), tag=getattr(row, "tag"))
        db = pd.DataFrame({"node": inodes - 1})
        db["type"] = "island"
        db["id"] = -(getattr(row, "Index") + 1)

        bounds.append(db)

    if bounds != []:
        bnodes = pd.concat(bounds).reset_index(drop=True)

        bnodes.index.name = "bnodes"

        bnodes = bnodes.drop_duplicates("node")

        bnodes["id"] = bnodes.id.astype(int)

    else:
        bnodes = pd.DataFrame({})

    gglobal = kwargs.get("gglobal", False)
    if gglobal:
        use_bindings = kwargs.get("use_bindings", True)
        if not use_bindings:
            bnodes["type"] = "island"  # Fix for binary run and GLOBAL. CHECK
            bnodes["id"] = -bnodes.id.values

        bnodes = bnodes.sort_values(["type", "id",
                                     "node"]).reset_index(drop=True)  # sort
        bnodes.index.name = "bnodes"

        # check orientation
        if use_bindings:
            nodes, tria = orient(nodes, tria, x="x", y="y")
        else:
            bgmesh = kwargs.get("bgmesh", None)
            if not bgmesh:
                tria = tria.reindex(columns=["a", "c", "b"])

    # check if global and reproject
    sproj = kwargs.get("gglobal", False)
    if sproj:  # convert to lat/lon
        if nodes.z.any() != 0:
            xd, yd = to_lat_lon(nodes.x, nodes.y, nodes.z)
            nodes["x"] = xd
            nodes["y"] = yd
        else:
            xd, yd = to_lat_lon(nodes.x, nodes.y)
            nodes["x"] = xd
            nodes["y"] = yd

    grid = pd.DataFrame({"lon": nodes.x, "lat": nodes.y})

    tri3 = tria.values

    logger.info("Finalize Dataset")

    ## make dataset
    els = xr.DataArray(
        tri3,
        dims=["nSCHISM_hgrid_face", "nMaxSCHISM_hgrid_face_nodes"],
        name="SCHISM_hgrid_face_nodes",
    )

    nod = (grid.loc[:, ["lon", "lat"]].to_xarray().rename({
        "index":
        "nSCHISM_hgrid_node",
        "lon":
        "SCHISM_hgrid_node_x",
        "lat":
        "SCHISM_hgrid_node_y",
    }))
    nod = nod.drop_vars("nSCHISM_hgrid_node")

    dep = xr.Dataset({
        "depth":
        (["nSCHISM_hgrid_node"], np.zeros(nod.nSCHISM_hgrid_node.shape[0]))
    })

    gr = xr.merge([nod, els, dep, bnodes.to_xarray()])

    gmsh.finalize()

    return gr
Exemple #25
0
def run_gmsh(in_file: Union[str, Path], out_file: Union[str, Path],
             dim: int) -> None:
    """Convenience function to run gmsh.

    Parameters:
        in_file : str or pathlib.Path
            Name of (or path to) gmsh configuration file (.geo)
        out_file : str or pathlib.Path
            Name of (or path to) output file for gmsh (.msh)
        dim : int
            Number of dimensions gmsh should grid. If dims is less than
            the geometry dimensions, gmsh will grid all lower-dimensional
            objects described in in_file (e.g. all surfaces embedded in a 3D
            geometry).

    """

    # Helper functions

    def _dump_gmsh_log(_log: List[str], in_file_name: Path) -> Path:
        """Write a gmsh log to file.

        Takes in the entire log and path to the in_file (from outer scope)
        Return name of the log file
        """
        debug_file_name = in_file_name.with_name(
            f"gmsh_log_{in_file_name.stem}.dbg")
        with debug_file_name.open(mode="w") as f:
            for _line in _log:
                f.write(_line + "\n")

        return debug_file_name

    # Ensure that in_file has extension .geo, out_file extension .msh
    in_file = Path(in_file).with_suffix(".geo")
    out_file = Path(out_file).with_suffix(".msh")

    if not in_file.is_file():
        raise FileNotFoundError(f"file {in_file!r} not found.")

    gmsh.initialize()

    # Experimentation indicated that the gmsh api failed to raise error values when
    # passed corrupted .geo files. To catch errors we therefore read the gmsh log, and
    # look for error messages.
    gmsh.logger.start()
    gmsh.open(str(in_file))

    # Look for errors
    log = gmsh.logger.get()
    for line in log:
        if "Error:" in line:
            fn = _dump_gmsh_log(log, in_file)
            raise ValueError(f"""Error when reading gmsh file {in_file}.
                        Gmsh log written to file {fn}""")

    # Generate the mesh
    gmsh.model.mesh.generate(dim=dim)

    # Look for errors
    log = gmsh.logger.get()
    for line in log:
        if "Error:" in line:
            fn = _dump_gmsh_log(log, in_file)
            raise ValueError(
                f"Error in gmsh when generating mesh for {in_file}\n"
                f"Gmsh log written to file {fn}")

    # The gmsh write should be safe for errors
    gmsh.write(str(out_file))
    # Done
    gmsh.finalize()
 main_box_coors, component_boxes = split_boxes(boxes_to_params,
                                               config_data["main_box_mark"])
 #get brep file translations
 component_to_translation = get_component_translations(
     name_to_brep, GEO_FILE)
 #apply brep file translations and subtract files --> bounding boxes for all surfaces
 component_to_bnd_box = get_surfaces_for_components(
     component_to_fancy, component_boxes, brep_to_name,
     component_to_translation, main_box_coors)
 plane_compon_to_bnd_box, vol_compon_to_bnd_box = split_components_bnd_box(
     component_to_bnd_box, component_to_fancy, config_data["surface_names"],
     config_data["volume_names"])
 #Load gmsh geometry for calculations
 imitate_gmsh_reload(GEO_FILE)
 gmsh.initialize()
 gmsh.open(GEO_FILE)
 geo_planes, geo_vols = download_geo_entities()
 gmsh.finalize()
 #paint stuff
 print("Searching for surfaces")
 marked_planes = []
 fancy_name_to_plane_tag = get_empty_key_dict(
     config_data["surface_names"])  #dictionary name --> tag
 for plane in geo_planes:
     component_it_belongs = find_component_for_plane(
         plane, plane_compon_to_bnd_box, config_data["match_precision"])
     if component_it_belongs:
         name = component_to_fancy[component_it_belongs]
         fancy_name_to_plane_tag[name].append(plane[0])
         if plane[0] in marked_planes:
             raise Warning(
Exemple #27
0
def process_mesh(self,
                 file_in,
                 file_out,
                 is_get_lam=True,
                 is_get_magnet=False,
                 is_hole_air=True):
    """Preprocess the GMSH model, i.e. remove unused parts, rename boundaries, ..."""
    # TODO utilize 'translation' dict

    gmsh.initialize()
    gmsh.open(file_in)
    gmsh.model.geo.removeAllDuplicates()

    # remove unused model parts
    sta_lam = (STATOR_LAB_S + "-0_" + LAM_LAB_S).lower()  # Stator Lamination
    sta_wind = (STATOR_LAB_S + "-0_" + WIND_LAB_S).lower()  # Stator Winding
    _remove_entities(gmsh, labels=[sta_lam, sta_wind])

    # get group names
    grps = gmsh.model.getPhysicalGroups(-1)
    grp_names = [gmsh.model.getPhysicalName(*grp) for grp in grps]

    # get lists of some surfaces by name
    magnet_list = []
    for grp, name in zip(grps, grp_names):
        label_dict = decode_label(name)
        if HOLEM_LAB_S in label_dict["surf_type"]:
            entities = gmsh.model.getEntitiesForPhysicalGroup(*grp)
            if grp[0] == 2:
                magnet_list.extend(entities.tolist())

    if True:  # is_get_lam:
        lam_list = []
        for grp, name in zip(grps, grp_names):
            label_dict = decode_label(name)
            if (ROTOR_LAB_S in label_dict["lam_type"]
                    and LAM_LAB_S in label_dict["surf_type"]):
                entities = gmsh.model.getEntitiesForPhysicalGroup(*grp)
                if grp[0] == 2:
                    lam_list.extend(entities.tolist())

        lam_lines = []
        for lam in lam_list:
            lam_lines.extend(gmsh.model.getBoundary([(2, lam)],
                                                    oriented=False))
        lam_lines = list(set([lam[1] for lam in lam_lines]))  # unique

        hole_lines = []
        for line in lam_lines:
            names = _get_names_physical(
                gmsh,
                dimtag=[
                    1,
                    line,
                ],
            )
            if any([
                    HOLEV_LAB_S in decode_label(name)["surf_type"]
                    for name in names
            ]):
                hole_lines.append(line)

    if is_get_lam and not is_get_magnet:
        ext = "Master"
    else:
        ext = "Slave"

    # setup dict to store physical groups, key: group name, value: list of tags
    groups_dict = {}

    # get lines of magnets for processing their physical groups
    for id, magnet in enumerate(magnet_list):
        lines = gmsh.model.getBoundary([(2, magnet)])
        # store new group names in 'groups_dict' to set it later
        for line in lines:
            names = _get_names_physical(
                gmsh,
                dimtag=[
                    1,
                    abs(line[1]),
                ],
            )
            if not names:
                print(
                    f"Warning: Found magnet line without label - line {line[1]}"
                )

            if is_get_magnet or (is_get_lam and line[1] in lam_lines):
                for name in names:
                    label_dict = decode_label(name)
                    if HOLEM_LAB_S in label_dict["surf_type"]:
                        if (line[1] in lam_lines
                            ):  # only lines with direct contact for now
                            # replace number and add 'Slave'
                            s = name.split("_")
                            s.append(ext)  # add extension
                            s[2] = str(id)  # renumber
                            key = "_".join(s)  # new name
                            if key not in groups_dict.keys():
                                groups_dict[key] = []
                            groups_dict[key].append(line)

            # Test if other lines (with 'Hole' phy. group) and same phy. group ext.
            # ('Left', ...) share the same points to add them as well
            # TODO if not used with direct contact (see above),
            #      but I will keep it for Contact Simulation
            # if is_get_lam:
            #     # get the name of the magnets line
            #     s = None
            #     for name in names:
            #         if "Magnet" in name:
            #             s = name.split('_')
            #     # basic check of magnet line name
            #     if s is not None and len(s) >= 3:
            #         for hline in hole_lines:
            #             if hline != abs(line[1]): # skip if hole line == magnet line
            #                 # test for same extension ('Left', 'Right', ...)
            #                 names = _get_names_physical(gmsh, dimtag=[1, hline])
            #                 if any([s[2] in name for name in names]):
            #                     p1 = [x[1] for x in gmsh.model.getBoundary([line])]
            #                     p2 = [x[1] for x in gmsh.model.getBoundary([(1, hline)])]
            #                     pt = [p for p in p1 if p in p2]
            #                     if pt:
            #                         if len(s) == 3:
            #                             s.append('Master') # add extension
            #                         s[1] = str(id) # renumber
            #                         key = "_".join(s) # new name
            #                         if key not in groups_dict.keys():
            #                             groups_dict[key] = []
            #                         groups_dict[key].append((1, hline))
            #         if not is_hole_air:
            #             pass # TODO implement

        if is_get_magnet:
            # store new magnet body name
            s = "Magnet_" + str(id) + "_Body"
            groups_dict[s] = [
                (2, magnet),
            ]

    if is_get_lam:
        # store new lamination body name
        for id, lam in enumerate(lam_list):
            s = "Lamination_" + str(id) + "_Body"
            if s not in groups_dict:
                groups_dict[s] = []
            groups_dict[s].append((2, lam))

        # store hole if not air
        if not is_hole_air:
            pass  # TODO

    # add symmetry boundaries to keeper dict 'groups_dict'
    if is_get_lam:
        keeper_list = [
            "MASTER_ROTOR_BOUNDARY",
            "SLAVE_ROTOR_BOUNDARY",
            "Rotor_Tangential_Bridge",
            "Rotor_Radial_Bridge",
            "ROTOR_BORE_CURVE",
        ]

        for line in lam_lines:
            names = _get_names_physical(gmsh, dimtag=[1, line])
            for key in keeper_list:
                if any([key in name for name in names]):
                    if key not in groups_dict:
                        groups_dict[key] = []
                    groups_dict[key].append((1, line))

    # update group names
    grps = gmsh.model.getPhysicalGroups(-1)
    grp_names = [gmsh.model.getPhysicalName(*grp) for grp in grps]

    # delete unused surfaces
    RL = ROTOR_LAB_S + "-0_"
    del_list = [SHAFT_LAB, RL + HOLEV_LAB_S]
    if not is_get_magnet:
        del_list.append(RL + HOLEM_LAB_S)

    if not is_get_lam:
        rot_lam = (RL + LAM_LAB_S).lower()  # Rotor Lamination
        del_list.append(rot_lam)

    for grp, name in zip(grps, grp_names):
        if any([n in name.lower() for n in del_list]):
            entities = gmsh.model.getEntitiesForPhysicalGroup(*grp).tolist()
            for entity in entities:
                if grp[0] == 2:
                    gmsh.model.geo.remove([(2, entity)], recursive=False)

    # set new physical group names after removing all 'old' physical groups
    gmsh.model.removePhysicalGroups(dimTags=[])
    for name in grp_names:
        gmsh.model.removePhysicalName(name)

    for key, values in groups_dict.items():
        # lines
        tags = [abs(dimtag[1]) for dimtag in values if dimtag[0] == 1]
        tags = list(set(tags))
        if tags:
            print(f"Add physical group {key} with lines {tags}")
            pg = gmsh.model.addPhysicalGroup(1, tags, tag=-1)
            gmsh.model.setPhysicalName(1, pg, key)
        # surfaces
        tags = [abs(dimtag[1]) for dimtag in values if dimtag[0] == 2]
        tags = list(set(tags))
        if tags:
            print(f"Add physical group {key} with surface {tags}")
            pg = gmsh.model.addPhysicalGroup(2, tags, tag=-1)
            gmsh.model.setPhysicalName(2, pg, key)

    # cleanup
    # get all entities
    gmsh.model.geo.synchronize()
    entities_all = gmsh.model.getEntities(dim=-1)
    surf_list = gmsh.model.getEntities(dim=2)
    print(surf_list)

    # get lines of surfaces
    line_list = []
    for surf in surf_list:
        line_list.extend(gmsh.model.getBoundary([surf]))
    line_list = [(line[0], abs(line[1])) for line in line_list]

    # remove all lines that are not part of the surfaces
    for entity in entities_all:
        if (entity[0], abs(entity[1])) not in line_list and entity[0] == 1:
            gmsh.model.geo.remove([entity], recursive=False)

    # entities_all = gmsh.model.getEntities(dim=-1)

    # remove unknown/unused physical groups
    # TODO

    # save
    gmsh.model.geo.synchronize()

    # gmsh.model.geo.mesh.setTransfiniteSurface(tag)
    for surf in surf_list:
        gmsh.model.mesh.setRecombine(2, surf[1])

    # gmsh.option.setNumber("Mesh.RecombinationAlgorithm", 1)

    gmsh.model.mesh.generate(2)
    # gmsh.model.mesh.recombine()
    gmsh.model.mesh.refine()
    # gmsh.model.mesh.refine()
    # gmsh.model.mesh.recombine()
    # gmsh.model.mesh.refine()

    # save mesh or geo file depending on file extension
    filename, file_extension = splitext(file_out)

    if file_extension == ".geo":
        gmsh.write(filename + ".geo_unrolled")
        replace(filename + ".geo_unrolled", filename + file_extension)
    else:
        gmsh.model.mesh.generate(2)
        gmsh.write(file_out)

    # gmsh.fltk.run()      # Uncomment to launch Gmsh GUI

    # update group names once again
    grps = gmsh.model.getPhysicalGroups(-1)
    grp_names = [gmsh.model.getPhysicalName(*grp) for grp in grps]

    gmsh.finalize()

    return gmsh, grps, grp_names
def imitate_gmsh_reload(fname):
    gmsh.initialize()
    gmsh.open(fname)
    gmsh.finalize()
    return 0
Exemple #29
0
def refine_mesh_by_splitting(
    in_file: Union[str, Path],
    out_file: Union[str, Path],
    dim: int,
    gb_set_projections: bool = True,
) -> Generator[pp.GridBucket, None, None]:
    """ Refine a mesh by splitting using gmsh

    The method generates refinements on the fly
    by yielding GridBuckets as desired.

    Note:
    When the desired number of refinements is reached,
    you should call
        refine_mesh_by_splitting.close()
    so that gmsh.finalize() is called.

    Parameters
    ----------
    in_file : Union[str, Path]
        path to .geo file to read
    out_file : Union[str, Path]
        path to new .msh file to store mesh in,
        excluding the ending '.msh'.
    dim : int {2, 3}
        Dimension of domain to mesh
    gb_set_projections : bool (Default: True)
        Call pp.contact_conditions.set_projections(gb)
        before yielding result
    Returns
    -------
    Generator[gb]
        A generator for the refined grid buckets, starting with the coarsest.
    """
    # Ensure that in- and out paths are formatted correctly.
    assert Path(in_file).is_file()
    out_file = Path(out_file)
    out_file = out_file.parent / out_file.stem

    try:
        import gmsh
    except ModuleNotFoundError:
        raise ModuleNotFoundError(
            "To run gmsh python api on your system, "
            "download the relevant gmsh*-sdk.* from http://gmsh.info/bin/. "
            "Then, Add the 'lib' directory from the SDK to PYTHONPATH: \n"
            "export PYTHONPATH=${PYTHONPATH}:path/to/gmsh*-sdk.*/lib"
        )

    # gmsh must always be finalized after it has be initialized
    # (see 'finally' clause).
    # Therefore, we wrap the entire function body in a try-finally context.
    try:
        # Initialize gmsh and generate the first (coarsest) mesh
        gmsh.initialize()
        gmsh.open(in_file)
        gmsh.model.mesh.generate(dim=dim)

        num_refinements = 0

        # Enter an infinite loop
        while True:
            out_file_name = f"{out_file}_{num_refinements}.msh"

            # The first mesh is already done.
            # Start refining all subsequent meshes.
            if num_refinements > 0:
                gmsh.model.mesh.refine()  # Refine the mesh

            gmsh.write(out_file_name)  # Write the result to '.msh' file
            # Generate List[pp.Grid]
            grids = tetrahedral_grid_from_gmsh(file_name=out_file_name)
            # Convert List[pp.Grid] to pp.GridBucket
            gb = grid_list_to_grid_bucket(grids)

            # Set projection operators for mixed-dimensional grids
            if gb_set_projections:
                pp.contact_conditions.set_projections(gb)

            # yield the resulting grid bucket
            yield gb

            # finally, prepare the next iteration
            num_refinements += 1
    finally:
        # When refine_mesh_by_splitting.close() is called, we get here.
        gmsh.finalize()
Exemple #30
0
def _initialize_gmsh(path):
    gmsh.initialize('', False)
    gmsh.open(path)