Source code for pyleecan.Functions.GMSH.draw_GMSH

from ...Classes.Arc import Arc
from ...Classes.Arc2 import Arc2
from ...Classes.MachineSIPMSM import MachineSIPMSM

from ...Functions.labels import (
    HOLEM_LAB_S,
    MAG_LAB,
    short_label,
    LAM_LAB,
    LAM_LAB_S,
    SHAFT_LAB,
    decode_label,
    SLID_LAB,
    AIRGAP_LAB,
    BOT_LAB,
    AIRBOX_LAB,
)
from ...Functions.GMSH import InputError
from ...Functions.GMSH.get_sliding_band import get_sliding_band
from ...Functions.GMSH.get_air_box import get_air_box
from ...Functions.GMSH.get_boundary_condition import get_boundary_condition
from ...Functions.GMSH.draw_surf_line import draw_surf_line
import sys
import gmsh
import cmath

from os import replace
from os.path import splitext

from numpy import pi


[docs]def draw_GMSH( output, sym, boundary_prop, is_lam_only_S=False, is_lam_only_R=False, user_mesh_dict={}, path_save="GMSH_model.msh", is_sliding_band=True, is_airbox=False, is_set_labels=False, is_run=False, ): """Draws a machine mesh in GMSH format Parameters ---------- output : Output Output object sym : int the symmetry applied on the stator and the rotor (take into account antiperiodicity) boundary_prop : dict dictionary to match FEA boundary conditions (dict values) with line boundary property (dict keys) is_lam_only_S: bool Draw only stator lamination is_lam_only_R: bool Draw only rotor lamination user_mesh_dict :dict Dictionary to enforce the mesh size on some surface/lines (key: surface label, value dict:key=line id, value:nb element) path_save : str Path to save the result msh file is_sliding_band : bool True uses sliding band, else airgap (Not implemented yet) is_airbox : bool True to add the airbox is_set_label : bool True to set all line labels as physical groups is_run : bool True to launch Gmsh GUI at the end Returns ------- GMSH_dict : dict dictionary containing the main parameters of GMSH File """ # check some input parameter if is_lam_only_S and is_lam_only_R: raise InputError( "is_lam_only_S and is_lam_only_R can't be True at the same time" ) # get machine machine = output.simu.machine mesh_dict = {} tol = 1e-6 # Default stator mesh element size mesh_size_S = machine.stator.Rext / 100.0 # Stator mesh_size_R = machine.rotor.Rext / 25.0 # Rotor mesh_size_SB = 2.0 * pi * machine.rotor.Rext / 360.0 # Sliding Band mesh_size_AB = machine.stator.Rext / 50.0 # AirBox # For readibility model = gmsh.model factory = model.geo # Start a new model gmsh.initialize() gmsh.option.setNumber("General.Terminal", int(False)) gmsh.option.setNumber("Geometry.CopyMeshingMethod", 1) gmsh.option.setNumber("Geometry.PointNumbers", 0) gmsh.option.setNumber("Geometry.LineNumbers", 0) gmsh.option.setNumber("Mesh.CharacteristicLengthMin", min(mesh_size_S, mesh_size_R)) gmsh.option.setNumber("Mesh.CharacteristicLengthMax", max(mesh_size_S, mesh_size_R)) model.add("Pyleecan") # build geometry alpha = 0 rotor_list = list() if machine.shaft is not None: rotor_list.extend(machine.shaft.build_geometry(sym=sym, alpha=alpha)) rotor_surf = machine.rotor.build_geometry(sym=sym, alpha=alpha) if sym == 1 and machine.shaft is not None: # Remove Rotor internal radius (use shaft one) # first surface is a SurfRing (cf Lamination.build_geometry) rotor_surf[0] = rotor_surf[0].out_surf rotor_list.extend(rotor_surf) stator_list = list() stator_list.extend(machine.stator.build_geometry(sym=sym, alpha=alpha)) ##################### # Adding Rotor ##################### # set origin oo = factory.addPoint(0, 0, 0, 0, tag=-1) gmsh_dict = { 0: { "tag": 0, "label": "origin", "with_holes": False, 1: { "tag": 0, "n_elements": 1, "bc_name": None, "begin": {"tag": oo, "coord": complex(0.0, 0.0)}, "end": {"tag": None, "coord": None}, "cent": {"tag": None, "coord": None}, "arc_angle": None, "line_angle": None, }, } } nsurf = 0 # number of surfaces # Drawing Rotor and Shaft surfaces if not is_lam_only_S: for surf in rotor_list: nsurf += 1 # print(surf.label) gmsh_dict.update( { nsurf: { "tag": None, "label": short_label(surf.label), } } ) if LAM_LAB in decode_label(surf.label)["surf_type"]: gmsh_dict[nsurf]["with_holes"] = True lam_rotor_surf_id = nsurf else: gmsh_dict[nsurf]["with_holes"] = False # comp. number of elements on the lines & override by user values in case mesh_dict = surf.comp_mesh_dict(element_size=mesh_size_R) if user_mesh_dict and surf.label in user_mesh_dict: mesh_dict.update(user_mesh_dict[surf.label]) # Draw the surface draw_surf_line( surf, mesh_dict, boundary_prop, factory, gmsh_dict, nsurf, mesh_size_R, ) lam_and_holes = list() ext_lam_loop = None rotor_cloops = list() # loop though all (surface) entries of the rotor lamination for s_data in gmsh_dict.values(): lloop = [] # skip this surface dataset if it is the origin if s_data["label"] == "origin": continue # build a lineloop of the surfaces lines for lvalues in s_data.values(): if type(lvalues) is not dict: continue lloop.extend([lvalues["tag"]]) cloop = factory.addCurveLoop(lloop) label_dict = decode_label(s_data["label"]) if ( MAG_LAB in label_dict["surf_type"] or HOLEM_LAB_S in label_dict["surf_type"] ): # Surface of Hole Magnet rotor_cloops.extend([cloop]) # search for the holes to substract from rotor lam if LAM_LAB_S in label_dict["surf_type"]: ext_lam_loop = cloop else: # MachineSIPSM does not have holes in rotor lam # only shaft is taken out if symmetry is one if isinstance(machine, MachineSIPMSM): if sym == 1 and SHAFT_LAB in label_dict["surf_type"]: lam_and_holes.extend([cloop]) else: if sym == 1: lam_and_holes.extend([cloop]) elif SHAFT_LAB not in label_dict["surf_type"]: lam_and_holes.extend([cloop]) else: pass # Shaft, magnets and magnet pocket surfaces are created if not is_lam_only_R: s_data["tag"] = factory.addPlaneSurface([cloop], tag=-1) pg = model.addPhysicalGroup(2, [s_data["tag"]]) model.setPhysicalName(2, pg, s_data["label"]) # Finally rotor lamination is built if ext_lam_loop is not None: lam_and_holes.insert(0, ext_lam_loop) if len(lam_and_holes) > 0: gmsh_dict[lam_rotor_surf_id]["tag"] = factory.addPlaneSurface( lam_and_holes, tag=-1 ) pg = model.addPhysicalGroup(2, [gmsh_dict[lam_rotor_surf_id]["tag"]]) model.setPhysicalName(2, pg, gmsh_dict[lam_rotor_surf_id]["label"]) # rotor_cloops = lam_and_holes # store rotor dict rotor_dict = gmsh_dict.copy() ##################### # Adding Stator ##################### # init new dict for stator gmsh_dict = { 0: { "tag": 0, "label": "origin", "with_holes": False, 1: { "tag": 0, "n_elements": 1, "bc_name": None, "begin": {"tag": oo, "coord": complex(0.0, 0.0)}, "end": {"tag": None, "coord": None}, "cent": {"tag": None, "coord": None}, }, } } # nsurf = 0 if not is_lam_only_R: stator_cloops = [] for surf in stator_list: nsurf += 1 gmsh_dict.update( { nsurf: { "tag": None, "label": short_label(surf.label), } } ) if LAM_LAB in decode_label(surf.label)["surf_type"]: gmsh_dict[nsurf]["with_holes"] = True else: gmsh_dict[nsurf]["with_holes"] = False # comp. number of elements on the lines & override by user values in case mesh_dict = surf.comp_mesh_dict(element_size=mesh_size_S) if user_mesh_dict and surf.label in user_mesh_dict: mesh_dict.update(user_mesh_dict[surf.label]) # Draw the surface draw_surf_line( surf, mesh_dict, boundary_prop, factory, gmsh_dict, nsurf, mesh_size_S, ) for s_data in gmsh_dict.values(): lloop = [] # skip this surface dataset if it is the origin if s_data["label"] == "origin": continue # build a lineloop of the surfaces lines for lvalues in s_data.values(): if type(lvalues) is not dict: continue lloop.extend([lvalues["tag"]]) cloop = factory.addCurveLoop(lloop) stator_cloops.append(cloop) # Winding surfaces are created if LAM_LAB_S in decode_label(s_data["label"])["surf_type"] or ( not is_lam_only_S ): s_data["tag"] = factory.addPlaneSurface([cloop], tag=-1) pg = model.addPhysicalGroup(2, [s_data["tag"]]) model.setPhysicalName(2, pg, s_data["label"]) # stator_dict = gmsh_dict.copy() gmsh_dict.update(rotor_dict) ##################### # Adding Sliding Band ##################### if is_sliding_band and (not is_lam_only_R) and (not is_lam_only_S): sb_list = get_sliding_band(sym=sym, machine=machine) else: sb_list = [] # nsurf = 0 for surf in sb_list: nsurf += 1 gmsh_dict.update( { nsurf: { "tag": None, "label": short_label(surf.label), } } ) # comp. number of elements on the lines & override by user values in case mesh_dict = surf.comp_mesh_dict(element_size=mesh_size_SB) if user_mesh_dict and surf.label in user_mesh_dict: mesh_dict.update(user_mesh_dict[surf.label]) # Draw the surface draw_surf_line( surf, mesh_dict, boundary_prop, factory, gmsh_dict, nsurf, mesh_size_SB, ) for s_data in gmsh_dict.values(): lloop = [] label_dict = decode_label(s_data["label"]) # skip this surface dataset if it is the origin if s_data["label"] == "origin" or not ( AIRGAP_LAB in label_dict["surf_type"] or SLID_LAB in label_dict["surf_type"] ): continue # build a lineloop of the surfaces lines for lvalues in s_data.values(): if type(lvalues) is not dict: continue lloop.extend([lvalues["tag"]]) if lloop: cloop = factory.addCurveLoop(lloop) if ( AIRGAP_LAB in label_dict["surf_type"] and BOT_LAB in label_dict["surf_type"] and isinstance(machine, MachineSIPMSM) ): s_data["tag"] = factory.addPlaneSurface([cloop] + rotor_cloops, tag=-1) else: s_data["tag"] = factory.addPlaneSurface([cloop], tag=-1) pg = model.addPhysicalGroup(2, [s_data["tag"]]) model.setPhysicalName(2, pg, s_data["label"]) ################### # Adding Airbox ################### if is_airbox and (not is_lam_only_R) and (not is_lam_only_S): ab_list = get_air_box(sym=sym, machine=machine) else: ab_list = [] # Default airbox mesh element size for surf in ab_list: nsurf += 1 gmsh_dict.update( { nsurf: { "tag": None, "label": short_label(surf.label), } } ) # comp. number of elements on the lines & override by user values in case mesh_dict = surf.comp_mesh_dict(element_size=mesh_size_AB) if user_mesh_dict and surf.label in user_mesh_dict: mesh_dict.update(user_mesh_dict[surf.label]) # Draw the surface draw_surf_line( surf, mesh_dict, boundary_prop, factory, gmsh_dict, nsurf, mesh_size_AB, ) for s_id, s_data in gmsh_dict.items(): lloop = [] if s_id == 0: continue for lvalues in s_data.values(): if AIRBOX_LAB in decode_label(s_data["label"])["surf_type"]: if type(lvalues) is not dict: continue lloop.extend([lvalues["tag"]]) else: continue if lloop: cloop = factory.addCurveLoop(lloop) s_data["tag"] = factory.addPlaneSurface([cloop], tag=-1) pg = model.addPhysicalGroup(2, [s_data["tag"]]) model.setPhysicalName(2, pg, s_data["label"]) # Set boundary conditions in gmsh lines boundary_list = list(set(boundary_prop.values())) for propname in boundary_list: bc_id = [] for s_data in gmsh_dict.values(): for lvalues in s_data.values(): if type(lvalues) is not dict: continue if lvalues["bc_name"] == propname: bc_id.extend([abs(lvalues["tag"])]) if bc_id: pg = model.addPhysicalGroup(1, bc_id) model.setPhysicalName(1, pg, propname) # Set all line labels as physical groups if is_set_labels: groups = {} for s_data in gmsh_dict.values(): for lvalues in s_data.values(): if ( type(lvalues) is not dict or "label" not in lvalues or not lvalues["label"] ): continue if lvalues["label"] not in groups.keys(): groups[lvalues["label"]] = [] groups[lvalues["label"]].append(abs(lvalues["tag"])) for label, tags in groups.items(): pg = model.addPhysicalGroup(1, tags) model.setPhysicalName(1, pg, label) factory.synchronize() # save mesh or geo file depending on file extension filename, file_extension = splitext(path_save) if file_extension == ".geo": gmsh.write(filename + ".geo_unrolled") replace(filename + ".geo_unrolled", filename + file_extension) else: gmsh.model.mesh.generate(2) gmsh.write(path_save) if is_run: gmsh.fltk.run() # Uncomment to launch Gmsh GUI gmsh.finalize() return gmsh_dict