Beispiel #1
0
def generate_mesh(fractures_data, max_el_size, file_name, verbose=0):
    r""" Create mesh and write it to a file.

    Parameters
    ----------
    fractures_data : list of FractureData
      Array of objects defining fractures.
    max_el_size : double
      Maximal size of mesh element.
    file_name : str
      File name to write mesh into.
    verbose : {0, 1}
      If set to 1, messages during mesh generation will be printed.
    """
    model = gmsh.model
    factory = model.occ
    gmsh.initialize()
    gmsh.option.setNumber("General.Terminal", verbose)
    model.add("test_api")

    # set options
    gmsh.option.setNumber("Geometry.Tolerance", 0)
    gmsh.option.setNumber("Geometry.ToleranceBoolean", 0)
    gmsh.option.setNumber("Geometry.MatchMeshTolerance", 0)
    gmsh.option.setNumber("Mesh.ToleranceInitialDelaunay", 1e-12)

    # Compute mesh element sizes from values given at geometry points, default value: 1
    gmsh.option.setNumber("Mesh.CharacteristicLengthFromPoints", 1)
    # Automatically compute mesh element sizes from curvature, respects surface curvature, default value: 0
    gmsh.option.setNumber("Mesh.CharacteristicLengthFromCurvature", 0)
    gmsh.option.setNumber("Mesh.CharacteristicLengthExtendFromBoundary", 0)

    # Element size constraint options
    # gmsh.option.setNumber("Mesh.CharacteristicLengthMin", max_el_size*0.01)
    # gmsh.option.setNumber("Mesh.CharacteristicLengthMax", max_el_size)
    # gmsh.option.setNumber("Mesh.MinimumCurvePoints", 5)

    # create fractures (currently we ignore r2 and create circular disks)
    disks = []
    tags = []
    for f in fractures_data:
        pc = factory.addPoint(f.centre[0], f.centre[1], f.centre[2], f.r1)
        axis, angle = f.get_rotation_axis_angle()
        p0 = factory.addPoint(f.centre[0] + f.r1, f.centre[1], f.centre[2],
                              f.r1)
        p1 = factory.addPoint(f.centre[0] + f.r1 * cos(pi * 2 / 3),
                              f.centre[1] + f.r1 * sin(pi * 2 / 3),
                              f.centre[2], f.r1)
        p2 = factory.addPoint(f.centre[0] + f.r1 * cos(pi * 4 / 3),
                              f.centre[1] + f.r1 * sin(pi * 4 / 3),
                              f.centre[2], f.r1)
        factory.rotate([(0, p0), (0, p1), (0, p2)], f.centre[0], f.centre[1],
                       f.centre[2], axis[0], axis[1], axis[2], angle)
        c1 = factory.addCircleArc(p0, pc, p1)
        c2 = factory.addCircleArc(p1, pc, p2)
        c3 = factory.addCircleArc(p2, pc, p0)
        cl = factory.addCurveLoop([c1, c2, c3])
        d = factory.addPlaneSurface([cl])

        disks.append((2, d))
        tags.append(f.tag)

    # fragment fractures
    fractures, fractures_map = factory.fragment(disks, [])
    print('disks = ', disks)
    # List of fracture tuples (dim, tag)
    print('fractures = ', fractures)
    # List of lists of tuples, each sublist contains fragments (dim, tag) from particular fracture
    print('fractures_map = ', fractures_map)
    assert len(fractures_map) == len(disks)

    # set physical id and name of fractures
    fractures_phys_id = model.addPhysicalGroup(2,
                                               [id for dim, id in fractures])
    model.setPhysicalName(2, fractures_phys_id, "fractures")

    # define 3d volume and embed fractures into it
    box = factory.addBox(0, 0, 0, 1, 1, 1)

    factory.synchronize()
    # Embed the model entities of dimension 'dim', and tags 'tag' in the other model entity which is given by
    # dimension (3) and tag (box)
    model.mesh.embed(2, [tag for dim, tag in fractures], 3, box)

    # define physical id of volume and its boundaries
    box_phys_id = model.addPhysicalGroup(3, [box], -1)
    model.setPhysicalName(3, box_phys_id, "box")
    # box_bdry = model.getBoundary([(3,box)], True)
    # box_bdry_left_phys_id = model.addPhysicalGroup(2, [box_bdry[0][1]], -1)
    # box_bdry_right_phys_id = model.addPhysicalGroup(2, [box_bdry[1][1]], -1)
    # model.setPhysicalName(2, box_bdry_left_phys_id, ".left")
    # model.setPhysicalName(2, box_bdry_right_phys_id, ".right")

    # Define fields for mesh refinement
    # Compute the distance from curves, each curve is replaced by NNodesByEdge equidistant nodes
    # and the distance from those nodes is computed.
    model.mesh.field.add("Distance", 1)
    model.mesh.field.setNumber(1, "NNodesByEdge", 100)
    frac_bdry = model.getBoundary(fractures, False, False, False)
    # Set the numerical list option "EdgesList" to list of "frac_bdry" tags for field tag 1.
    model.mesh.field.setNumbers(1, "EdgesList",
                                [tag for dm, tag in frac_bdry if dm == 1])

    # Threshold
    # F = LCMin if Field[IField] <= DistMin,
    # F = LCMax if Field[IField] >= DistMax,
    # F = interpolation between LcMin and LcMax if DistMin < Field[IField] < DistMax
    model.mesh.field.add("Threshold", 2)
    # Index of the field to evaluate (in this case 1 is "Distance")
    model.mesh.field.setNumber(2, "IField", 1)
    # Element size inside DistMin
    model.mesh.field.setNumber(2, "LcMin", max_el_size * 0.03)
    # Element size outside DistMax
    model.mesh.field.setNumber(2, "LcMax", max_el_size)
    # Distance from entity up to which element size will be LcMin, it should depend on particular model
    model.mesh.field.setNumber(2, "DistMin", 0.001)
    # Distance from entity after which element size will be LcMax, it should depend on particular model
    model.mesh.field.setNumber(2, "DistMax", 0.5)

    # Set threshold as the background mesh size field.
    model.mesh.field.setAsBackgroundMesh(2)

    # generate mesh, write to file and output number of entities that produced error
    factory.synchronize()
    gmsh.write(file_name + '.brep')
    model.mesh.generate(3)
    bad_entities = model.mesh.getLastEntityError()
    gmsh.write(file_name)
    gmsh.finalize()

    return len(bad_entities)
Beispiel #2
0
def test_extrude_polygon():
    """
    Test extrusion of an polygon.

    BUG: Currently failing:
    - in this setting (set mesh step directly to nodes of polygon) it generates elements but writes empty mesh
    - when setting mesh step by getting boundary inside make_mesh, it fails
    """

    gmsh.initialize()
    file_name = "extrude_polygon"
    gmsh.model.add(file_name)

    # plane directional vectors vector
    u = np.array([1, 1, 0])
    u = u / np.linalg.norm(u)
    v = np.array([0, 1, 1])
    v = v / np.linalg.norm(v)

    #normal
    n = np.cross(u, v)
    n = n / np.linalg.norm(n)

    # add some points in the plane
    points = []
    points.append(u)
    points.append(2 * u + 1 * v)
    points.append(5 * u + -2 * v)
    points.append(5 * u + 3 * v)
    points.append(4 * u + 5 * v)
    points.append(-2 * u + 3 * v)
    points.append(v)

    point_tags = [gmsh.model.occ.addPoint(*p) for p in points]
    # point_tags = [gmsh.model.occ.addPoint(*p, meshSize=0.2) for p in points]
    lines = [
        gmsh.model.occ.addLine(point_tags[i - 1], point_tags[i])
        for i in range(len(points))
    ]
    cl = gmsh.model.occ.addCurveLoop(lines)
    pol = gmsh.model.occ.addPlaneSurface([cl])

    ext_dimtags = gmsh.model.occ.extrude([(2, pol)], *(3 * n))
    tube_dimtags = [ext_dimtags[1]]

    gmsh.model.occ.synchronize()
    nodes = gmsh.model.getBoundary(tube_dimtags,
                                   combined=False,
                                   oriented=False,
                                   recursive=True)
    print(nodes)
    p_dimtags = [(0, tag) for tag in point_tags]
    gmsh.model.occ.mesh.setSize(p_dimtags, size=0.2)
    gmsh.model.occ.synchronize()
    # generate mesh, write to file and output number of entities that produced error
    # gmsh.option.setNumber("Mesh.CharacteristicLengthFromPoints", 0.2)
    # gmsh.option.setNumber("Mesh.CharacteristicLengthFromCurvature", 0)
    # gmsh.option.setNumber("Mesh.CharacteristicLengthExtendFromBoundary", 1)
    # gmsh.option.setNumber("Mesh.CharacteristicLengthMin", 0.1)
    # gmsh.option.setNumber("Mesh.CharacteristicLengthMax", 1.0)

    gmsh.model.mesh.generate(3)
    gmsh.model.mesh.removeDuplicateNodes()
    bad_entities = gmsh.model.mesh.getLastEntityError()
    print(bad_entities)
    # gmsh.fltk.run()
    gmsh.write(sandbox_fname(file_name, "msh2"))
    gmsh.finalize()
Beispiel #3
0
def generate_mesh():
    gmsh.initialize()
    file_name = "box_wells"
    gmsh.model.add(file_name)

    box = gmsh.model.occ.addBox(-1000, -1000, -1000, 2000, 2000, 2000)
    rec1 = gmsh.model.occ.addRectangle(-800, -800, 0, 1600, 1600)
    rec2 = gmsh.model.occ.addRectangle(-1200, -1200, 0, 2400, 2400)
    rec1_dt = (2, rec1)
    rec2_dt = (2, rec2)
    gmsh.model.occ.rotate([rec2_dt], 0, 0, 0, 0, 1, 0, np.pi / 2)
    rectangle, map = gmsh.model.occ.fragment([rec1_dt, rec2_dt], [])

    box = [(3, box)]

    box_copy = gmsh.model.occ.copy(box)
    dim_tags, map = gmsh.model.occ.intersect(rectangle, box_copy)
    gmsh.model.occ.synchronize()

    dim_tags_copy = gmsh.model.occ.copy(dim_tags)
    box_copy = gmsh.model.occ.copy(box)
    box_cut, map = gmsh.model.occ.fragment(box_copy, dim_tags_copy)
    gmsh.model.occ.removeAllDuplicates()
    gmsh.model.occ.synchronize()

    b = gmsh.model.addPhysicalGroup(3, [tag for dim, tag in box_cut])
    gmsh.model.setPhysicalName(3, b, "box")

    rect = gmsh.model.addPhysicalGroup(2, [tag for dim, tag in dim_tags])
    gmsh.model.setPhysicalName(2, rect, "rectangle")

    bc_tags = gmsh.model.getBoundary(dim_tags, combined=False, oriented=False)
    bc_nodes = gmsh.model.getBoundary(dim_tags,
                                      combined=False,
                                      oriented=False,
                                      recursive=True)
    bc_box_nodes = gmsh.model.getBoundary(box_cut,
                                          combined=False,
                                          oriented=False,
                                          recursive=True)
    bc_rect = gmsh.model.addPhysicalGroup(1, [tag for dim, tag in bc_tags])
    gmsh.model.setPhysicalName(1, bc_rect, ".rectangle")
    gmsh.model.occ.setMeshSize(bc_nodes, 50)

    #gmsh.model.mesh.embed(2, [tag for dim, tag in dim_tags], 3, box_copy[0][1])
    #factory.synchronize()

    model = gmsh.model

    # generate mesh, write to file and output number of entities that produced error
    gmsh.option.setNumber("Mesh.CharacteristicLengthFromPoints", 1)
    gmsh.option.setNumber("Mesh.CharacteristicLengthFromCurvature", 0)
    gmsh.option.setNumber("Mesh.CharacteristicLengthExtendFromBoundary", 1)
    #gmsh.option.setNumber("Mesh.CharacteristicLengthMin", 100)
    gmsh.option.setNumber("Mesh.CharacteristicLengthMax", 300)

    gmsh.write(file_name + '.brep')
    gmsh.write(file_name + '.geo')
    model.mesh.generate(3)
    gmsh.model.mesh.removeDuplicateNodes()
    bad_entities = model.mesh.getLastEntityError()
    print(bad_entities)
    gmsh.write(file_name + ".msh")
    gmsh.fltk.run()
    gmsh.finalize()

    return len(bad_entities)
Beispiel #4
0
def draw_GMSH(
    output,
    sym,
    is_antiper=False,
    is_remove_vent=False,
    is_remove_slotS=False,
    is_remove_slotR=False,
    is_lam_only_S=False,
    is_lam_only_R=False,
    kgeo_fineness=1,
    kmesh_fineness=1,
    user_mesh_dict={},
    path_save="GMSH_model.msh",
    is_sliding_band=True,
    transform_list=[],
):
    """Draws a machine mesh in GMSH format

    Parameters
    ----------
    output : Output
        Output object
    is_remove_vent : bool
        True to remove the ventilation ducts (Default value = False)
    is_remove_slotS : bool
        True to solve without slot effect on the Stator (Default value = False)
    is_remove_slotR : bool
        True to solve without slot effect on the Rotor (Default value = False)
    kgeo_fineness : float
        global coefficient to adjust geometry fineness
    kmesh_fineness : float
        global coefficient to adjust mesh fineness
    sym : int
        the symmetry applied on the stator and the rotor (take into account antiperiodicity)
    is_antiper: bool
        To apply antiperiodicity boundary conditions
    is_lam_only_S: bool
        Draw only stator lamination
    is_lam_only_R: bool
        Draw only rotor lamination

    Returns
    -------
    GMSH_dict : dict
        Dictionnary containing the main parameters of GMSH File
    """
    # check some input parameter
    if is_lam_only_S and is_lam_only_R:
        raise InputError(
            "Only 'is_lam_only_S' or 'is_lam_only_R' can be True at the same time"
        )

    # get machine
    machine = output.simu.machine
    mesh_dict = {}
    tol = 1e-6

    # For readibility
    model = gmsh.model
    factory = model.geo

    # Start a new model
    gmsh.initialize(sys.argv)
    gmsh.option.setNumber("General.Terminal", int(True))
    gmsh.option.setNumber("Geometry.CopyMeshingMethod", 1)
    gmsh.option.setNumber("Geometry.PointNumbers", 0)
    gmsh.option.setNumber("Geometry.LineNumbers", 0)
    model.add("Pyleecan")

    rotor_list = list()
    rotor_list.extend(machine.shaft.build_geometry(sym=sym))
    rotor_list.extend(machine.rotor.build_geometry(sym=sym))
    stator_list = list()
    stator_list.extend(machine.stator.build_geometry(sym=sym))

    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,
            },
        }
    }

    # Default rotor mesh element size
    mesh_size = machine.rotor.Rext / 25.0
    nsurf = 0  # number of surfaces
    if not is_lam_only_S:
        for surf in rotor_list:
            nsurf += 1
            gmsh_dict.update({nsurf: {"tag": None, "label": surf.label}})
            if surf.label.find("Lamination_Rotor") != -1:
                gmsh_dict[nsurf]["with_holes"] = True
                lam_rotor_surf_id = nsurf
            else:
                gmsh_dict[nsurf]["with_holes"] = False
            if user_mesh_dict is not None:
                mesh_dict = surf.comp_mesh_dict(element_size=mesh_size)
                mesh_dict.update(user_mesh_dict)
            for line in surf.get_lines():
                # When symmetry is 1 the shaft surface is substrtacted from Rotor Lam instead
                if sym == 1 and line.label == "Lamination_Rotor_Yoke_Radius_Int":
                    continue
                n_elem = mesh_dict.get(line.label)
                n_elem = n_elem if n_elem is not None else 0
                bc_name = get_boundary_condition(line)

                # Gmsh built-in engine does not allow arcs larger than 180deg
                # so arcs are split into two
                if (isinstance(line, Arc)
                        and abs(line.get_angle() * 180.0 / cmath.pi) >= 180.0):
                    rot_dir = 1 if line.is_trigo_direction == True else -1
                    arc1 = Arc2(
                        begin=line.get_begin(),
                        center=line.get_center(),
                        angle=rot_dir * cmath.pi / 2.0,
                        label=line.label,
                    )
                    arc2 = Arc2(
                        begin=arc1.get_end(),
                        center=line.get_center(),
                        angle=rot_dir * cmath.pi / 2.0,
                        label=line.label,
                    )
                    for arc in [arc1, arc2]:
                        _add_line_to_dict(
                            geo=factory,
                            line=arc,
                            d=gmsh_dict,
                            idx=nsurf,
                            mesh_size=mesh_size,
                            n_elements=n_elem,
                            bc=bc_name,
                        )
                elif isinstance(line, Arc) and (abs(
                        line.get_angle() * 180.0 / cmath.pi) <= tol):
                    # Don't draw anything, this is a circle and usually is repeated ?
                    pass
                else:
                    _add_line_to_dict(
                        geo=factory,
                        line=line,
                        d=gmsh_dict,
                        idx=nsurf,
                        mesh_size=mesh_size,
                        n_elements=n_elem,
                        bc=bc_name,
                    )

        lam_and_holes = list()
        ext_lam_loop = None
        for s_id, s_data in gmsh_dict.items():
            lloop = []
            if s_id == 0:
                continue
            for lvalues in s_data.values():
                if type(lvalues) is not dict:
                    continue
                lloop.extend([lvalues["tag"]])
            cloop = factory.addCurveLoop(lloop)
            # search for the holes to substract from rotor lam
            if s_data["label"].find("Lamination_Rotor") != -1:
                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 s_data["label"] == "Shaft":
                        lam_and_holes.extend([cloop])
                else:
                    if sym == 1:
                        lam_and_holes.extend([cloop])
                    elif s_data["label"] != "Shaft":
                        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)
        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()

    # 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
                },
            },
        }
    }

    # Default stator mesh element size
    mesh_size = machine.stator.Rext / 100.0
    # nsurf = 0
    if not is_lam_only_R:
        stator_cloops = []
        for surf in stator_list:
            nsurf += 1
            gmsh_dict.update({nsurf: {"tag": None, "label": surf.label}})
            if surf.label.find("Lamination_Stator") != -1:
                gmsh_dict[nsurf]["with_holes"] = True
            else:
                gmsh_dict[nsurf]["with_holes"] = False
            if user_mesh_dict is not None:
                mesh_dict = surf.comp_mesh_dict(element_size=mesh_size)
                mesh_dict.update(user_mesh_dict)
            for line in surf.get_lines():
                n_elem = mesh_dict.get(line.label)
                n_elem = n_elem if n_elem is not None else 0
                bc_name = get_boundary_condition(line)

                # Gmsh built-in engine does not allow arcs larger than 180deg
                # so arcs are split into two
                if (isinstance(line, Arc)
                        and abs(line.get_angle() * 180.0 / cmath.pi) >= 180.0):
                    rot_dir = 1 if line.is_trigo_direction == True else -1
                    arc1 = Arc2(
                        begin=line.get_begin(),
                        center=line.get_center(),
                        angle=rot_dir * cmath.pi / 2.0,
                        label=line.label,
                    )
                    arc2 = Arc2(
                        begin=arc1.get_end(),
                        center=line.get_center(),
                        angle=rot_dir * cmath.pi / 2.0,
                        label=line.label,
                    )
                    for arc in [arc1, arc2]:
                        _add_line_to_dict(
                            geo=factory,
                            line=arc,
                            d=gmsh_dict,
                            idx=nsurf,
                            mesh_size=mesh_size,
                            n_elements=n_elem,
                            bc=bc_name,
                        )
                else:
                    _add_line_to_dict(
                        geo=factory,
                        line=line,
                        d=gmsh_dict,
                        idx=nsurf,
                        mesh_size=mesh_size,
                        n_elements=n_elem,
                        bc=bc_name,
                    )

        for s_id, s_data in gmsh_dict.items():
            lloop = []
            if s_id == 0:
                continue
            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 (s_data["label"].find("Lamination_Stator") !=
                    -1) 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)

    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 = []

    # Default sliding mesh element size
    mesh_size = 2.0 * cmath.pi * machine.rotor.Rext / 360.0
    # nsurf = 0
    for surf in sb_list:
        nsurf += 1
        gmsh_dict.update({nsurf: {"tag": None, "label": surf.label}})
        for line in surf.get_lines():
            n_elem = mesh_dict.get(line.label)
            n_elem = n_elem if n_elem is not None else 0
            bc_name = get_boundary_condition(line)
            # Gmsh built-in engine does not allow arcs larger than 180deg
            # so arcs are split into two
            if (isinstance(line, Arc)
                    and abs(line.get_angle() * 180.0 / cmath.pi) >= 180.0):
                rot_dir = 1 if line.is_trigo_direction == True else -1
                arc1 = Arc2(
                    begin=line.get_begin(),
                    center=line.get_center(),
                    angle=rot_dir * cmath.pi / 2.0,
                    label=line.label,
                )
                arc2 = Arc2(
                    begin=arc1.get_end(),
                    center=line.get_center(),
                    angle=rot_dir * cmath.pi / 2.0,
                    label=line.label,
                )
                for arc in [arc1, arc2]:
                    _add_agline_to_dict(
                        geo=factory,
                        line=arc,
                        d=gmsh_dict,
                        idx=nsurf,
                        mesh_size=mesh_size,
                        n_elements=n_elem,
                        bc=bc_name,
                    )
            else:
                _add_agline_to_dict(
                    geo=factory,
                    line=line,
                    d=gmsh_dict,
                    idx=nsurf,
                    mesh_size=mesh_size,
                    n_elements=n_elem,
                    bc=bc_name,
                )

    for s_id, s_data in gmsh_dict.items():
        lloop = []
        if s_id == 0:
            continue
        for lvalues in s_data.values():
            if (s_data["label"].find("Airgap") != -1
                    or s_data["label"].find("SlidingBand") != -1):
                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
    bc_master_stator_id = []
    bc_slave_stator_id = []
    bc_master_rotor_id = []
    bc_slave_rotor_id = []
    for propname in boundary_list:
        # propname = boundary_prop[bound_label]
        bc_id = []
        for s_id, s_data in gmsh_dict.items():
            for lid, lvalues in s_data.items():
                if type(lvalues) is not dict:
                    continue
                if lvalues["bc_name"] == propname:
                    if propname == "MASTER_SLAVE_STATOR_BOUNDARY":
                        line_angle = lvalues.get("line_angle", None)
                        print(propname, lvalues["tag"], line_angle)
                        # Assumes Master coincides with x-Axis
                        if line_angle is not None and abs(line_angle) < tol:
                            bc_master_stator_id.extend([abs(lvalues["tag"])])
                        else:
                            bc_slave_stator_id.extend([abs(lvalues["tag"])])
                    elif propname == "MASTER_SLAVE_ROTOR_BOUNDARY":
                        line_angle = lvalues.get("line_angle", None)
                        print(propname, lvalues["tag"], line_angle)
                        # Assumes Master coincides with x-Axis
                        if line_angle is not None and abs(line_angle) < tol:
                            bc_master_rotor_id.extend([abs(lvalues["tag"])])
                        else:
                            bc_slave_rotor_id.extend([abs(lvalues["tag"])])
                    else:
                        bc_id.extend([abs(lvalues["tag"])])
        if bc_id:
            pg = model.addPhysicalGroup(1, bc_id)
            model.setPhysicalName(1, pg, propname)

    if bc_master_stator_id:
        pg = model.addPhysicalGroup(1, bc_master_stator_id)
        model.setPhysicalName(1, pg, "MASTER_SATOR_BOUNDARY")
        print("MASTER_STATOR_BOUNDARY", bc_master_stator_id)
    if bc_slave_stator_id:
        pg = model.addPhysicalGroup(1, bc_slave_stator_id)
        model.setPhysicalName(1, pg, "SLAVE_SATOR_BOUNDARY")
        print("SLAVE_STATOR_BOUNDARY", bc_slave_stator_id)
    if bc_master_rotor_id:
        pg = model.addPhysicalGroup(1, bc_master_rotor_id)
        model.setPhysicalName(1, pg, "MASTER_ROTOR_BOUNDARY")
        print("MASTER_ROTOR_BOUNDARY", bc_master_rotor_id)
    if bc_slave_rotor_id:
        pg = model.addPhysicalGroup(1, bc_slave_rotor_id)
        model.setPhysicalName(1, pg, "SLAVE_ROTOR_BOUNDARY")
        print("SLAVE_ROTOR_BOUNDARY", bc_slave_rotor_id)

    factory.synchronize()
    gmsh.model.mesh.generate(2)

    # Save and close
    gmsh.write(path_save)
    # gmsh.fltk.run()      # Uncomment to launch Gmsh GUI
    gmsh.finalize()

    return gmsh_dict
Beispiel #5
0
def _finalize_gmsh():
    gmsh.finalize()
Beispiel #6
0
    # Origin, width, inside, outside sizes
    fid = 1

    field = model.mesh.field
    # Refine close to left
    field.add('Box', fid)
    field.setNumber(fid, 'XMin', 0)
    field.setNumber(fid, 'XMax', 0.1 * geometry_parameters['X'])
    field.setNumber(fid, 'YMin', 0)
    field.setNumber(fid, 'YMax', geometry_parameters['Y'])
    field.setNumber(fid, 'VIn', 0.05)
    field.setNumber(fid, 'VOut', 0.2)

    field.setAsBackgroundMesh(fid)

    model.occ.synchronize()

    # gmsh.fltk.initialize()
    # gmsh.fltk.run()

    h5_filename = './test/square_domain.h5'
    mesh_model2d(model, tags, h5_filename)

    mesh, markers, lookup = load_mesh2d(h5_filename)
    cell_f, facet_f = markers

    gmsh.finalize()

    df.File('./test/square_cells.pvd') << cell_f
    df.File('./test/square_facets.pvd') << facet_f
Beispiel #7
0
def draw_GMSH(
    output,
    sym,
    is_antiper=False,
    is_remove_vent=False,
    is_remove_slotS=False,
    is_remove_slotR=False,
    is_lam_only_S=False,
    is_lam_only_R=False,
    kgeo_fineness=1,
    kmesh_fineness=1,
    user_mesh_dict={},
    path_save="GMSH_model.msh",
    is_sliding_band=True,
    transform_list=[],
):
    """Draws a machine mesh in GMSH format

    Parameters
    ----------
    output : Output
        Output object
    is_remove_vent : bool
        True to remove the ventilation ducts (Default value = False)
    is_remove_slotS : bool
        True to solve without slot effect on the Stator (Default value = False)
    is_remove_slotR : bool
        True to solve without slot effect on the Rotor (Default value = False)
    kgeo_fineness : float
        global coefficient to adjust geometry fineness
    kmesh_fineness : float
        global coefficient to adjust mesh fineness
    sym : int
        the symmetry applied on the stator and the rotor (take into account antiperiodicity)
    is_antiper: bool
        To apply antiperiodicity boundary conditions
    is_lam_only_S: bool
        Draw only stator lamination
    is_lam_only_R: bool
        Draw only rotor lamination

    Returns
    -------
    GMSH_dict : dict
        Dictionnary containing the main parameters of GMSH File
        """

    machine = output.simu.machine
    mesh_dict = {}
    tol = 1e-6
    # For readibility
    model = gmsh.model
    factory = model.geo

    # Start a new model
    gmsh.initialize(sys.argv)
    gmsh.option.setNumber("General.Terminal", int(True))
    gmsh.option.setNumber("Geometry.CopyMeshingMethod", 1)
    gmsh.option.setNumber("Geometry.PointNumbers", 0)
    gmsh.option.setNumber("Geometry.LineNumbers", 0)
    model.add("Pyleecan")

    rotor_list = list()
    rotor_list.extend(machine.shaft.build_geometry(sym=sym))
    rotor_list.extend(machine.rotor.build_geometry(sym=sym))
    stator_list = list()
    stator_list.extend(machine.stator.build_geometry(sym=sym))
    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,
                "begin": {
                    "tag": oo,
                    "coord": complex(0.0, 0.0)
                },
                "end": {
                    "tag": None,
                    "coord": None
                },
                "cent": {
                    "tag": None,
                    "coord": None
                },
            },
        }
    }

    # Default rotor mesh element size
    mesh_size = machine.rotor.Rext / 25.0
    nsurf = 0
    for surf in rotor_list:
        nsurf += 1
        gmsh_dict.update({nsurf: {"tag": None, "label": surf.label}})
        if surf.label.find("Lamination_Rotor") != -1:
            gmsh_dict[nsurf]["with_holes"] = True
            lam_rotor_surf_id = nsurf
        else:
            gmsh_dict[nsurf]["with_holes"] = False
        if user_mesh_dict is not None:
            mesh_dict = surf.comp_mesh_dict(element_size=mesh_size)
            mesh_dict.update(user_mesh_dict)
        for line in surf.get_lines():
            # When symmetry is 1 the shaft surface is substrtacted from Rotor Lam instead
            if sym == 1 and line.label == "Lamination_Rotor_Yoke_Radius_Int":
                continue
            n_elem = mesh_dict.get(line.label)
            if (isinstance(line, Arc)
                    and abs(line.get_angle() * 180.0 / cmath.pi) >= 180.0):
                if line.is_trigo_direction == True:
                    arc1 = Arc2(
                        begin=line.get_begin(),
                        center=line.get_center(),
                        angle=cmath.pi / 2.0,
                        label=line.label,
                    )
                    arc2 = Arc2(
                        begin=arc1.get_end(),
                        center=line.get_center(),
                        angle=cmath.pi / 2.0,
                        label=line.label,
                    )
                else:
                    arc1 = Arc2(
                        begin=line.get_begin(),
                        center=line.get_center(),
                        angle=-cmath.pi / 2.0,
                        label=line.label,
                    )
                    arc2 = Arc2(
                        begin=arc1.get_end(),
                        center=line.get_center(),
                        angle=-cmath.pi / 2.0,
                        label=line.label,
                    )
                if n_elem is not None:
                    _add_line_to_dict(
                        geo=factory,
                        line=arc1,
                        d=gmsh_dict,
                        idx=nsurf,
                        n_elements=n_elem,
                    )
                    _add_line_to_dict(
                        geo=factory,
                        line=arc2,
                        d=gmsh_dict,
                        idx=nsurf,
                        n_elements=n_elem,
                    )
                else:
                    _add_line_to_dict(
                        geo=factory,
                        line=arc1,
                        d=gmsh_dict,
                        idx=nsurf,
                        mesh_size=mesh_size,
                    )
                    _add_line_to_dict(
                        geo=factory,
                        line=arc2,
                        d=gmsh_dict,
                        idx=nsurf,
                        mesh_size=mesh_size,
                    )
            elif isinstance(
                    line,
                    Arc) and (abs(line.get_angle() * 180.0 / cmath.pi) <= tol):
                # Don't draw anything, this is a circle and usually is repeated ?
                pass
            else:
                if n_elem is not None:
                    _add_line_to_dict(
                        geo=factory,
                        line=line,
                        d=gmsh_dict,
                        idx=nsurf,
                        n_elements=n_elem,
                    )
                else:
                    _add_line_to_dict(
                        geo=factory,
                        line=line,
                        d=gmsh_dict,
                        idx=nsurf,
                        mesh_size=mesh_size,
                    )

    lam_and_holes = list()
    ext_lam_loop = None
    for s_id, s_data in gmsh_dict.items():
        lloop = []
        if s_id == 0:
            continue
        for lid, lvalues in s_data.items():
            if type(lvalues) is not dict:
                continue
            lloop.extend([lvalues["tag"]])
        cloop = factory.addCurveLoop(lloop)
        # search for the holes to substract from rotor lam
        if s_data["label"].find("Lamination_Rotor") != -1:
            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 s_data["label"] == "Shaft":
                    lam_and_holes.extend([cloop])
            else:
                if sym == 1:
                    lam_and_holes.extend([cloop])
                elif s_data["label"] != "Shaft":
                    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)
    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"])

    # Default rotor mesh element size
    mesh_size = machine.stator.Rext / 100.0
    nsurf = 0
    for surf in stator_list:
        nsurf += 1
        gmsh_dict.update({nsurf: {"tag": None, "label": surf.label}})
        if surf.label.find("Lamination_Stator") != -1:
            gmsh_dict[nsurf]["with_holes"] = True
        else:
            gmsh_dict[nsurf]["with_holes"] = False
        if user_mesh_dict is not None:
            mesh_dict = surf.comp_mesh_dict(element_size=mesh_size)
            mesh_dict.update(user_mesh_dict)
        for line in surf.get_lines():
            n_elem = mesh_dict.get(line.label)
            # Gmsh built-in engine does not allow arcs larger than 180deg
            # so arcs are split into two
            if (isinstance(line, Arc)
                    and abs(line.get_angle() * 180.0 / cmath.pi) == 180.0):
                if line.is_trigo_direction == True:
                    arc1 = Arc2(
                        begin=line.get_begin(),
                        center=line.get_center(),
                        angle=cmath.pi / 2.0,
                        label=line.label,
                    )
                    arc2 = Arc2(
                        begin=arc1.get_end(),
                        center=line.get_center(),
                        angle=cmath.pi / 2.0,
                        label=line.label,
                    )
                else:
                    arc1 = Arc2(
                        begin=line.get_begin(),
                        center=line.get_center(),
                        angle=-cmath.pi / 2.0,
                        label=line.label,
                    )
                    arc2 = Arc2(
                        begin=arc1.get_end(),
                        center=line.get_center(),
                        angle=-cmath.pi / 2.0,
                        label=line.label,
                    )
                if n_elem is not None:
                    _add_line_to_dict(
                        geo=factory,
                        line=arc1,
                        d=gmsh_dict,
                        idx=nsurf,
                        n_elements=n_elem,
                    )
                    _add_line_to_dict(
                        geo=factory,
                        line=arc2,
                        d=gmsh_dict,
                        idx=nsurf,
                        n_elements=n_elem,
                    )
                else:
                    _add_line_to_dict(
                        geo=factory,
                        line=arc1,
                        d=gmsh_dict,
                        idx=nsurf,
                        mesh_size=mesh_size,
                    )
                    _add_line_to_dict(
                        geo=factory,
                        line=arc2,
                        d=gmsh_dict,
                        idx=nsurf,
                        mesh_size=mesh_size,
                    )
            else:
                if n_elem is not None:
                    _add_line_to_dict(
                        geo=factory,
                        line=line,
                        d=gmsh_dict,
                        idx=nsurf,
                        n_elements=n_elem,
                    )
                else:
                    _add_line_to_dict(
                        geo=factory,
                        line=line,
                        d=gmsh_dict,
                        idx=nsurf,
                        mesh_size=mesh_size,
                    )

    for s_id, s_data in gmsh_dict.items():
        lloop = []
        if s_id == 0:
            continue
        for lid, lvalues in s_data.items():
            if type(lvalues) is not dict:
                continue
            lloop.extend([lvalues["tag"]])
        cloop = factory.addCurveLoop(lloop)
        # Winding surfaces are created
        if s_data["label"].find("Lamination_Stator") != -1:
            s_data["tag"] = factory.addPlaneSurface([cloop], tag=-1)
            pg = model.addPhysicalGroup(2, [s_data["tag"]])
            model.setPhysicalName(2, pg, s_data["label"])
        else:
            # Stator lamination is built
            if 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"])

    factory.synchronize()
    gmsh.model.mesh.generate(2)

    # Save and close
    gmsh.write(path_save)
    # gmsh.fltk.run()      # Uncomment to launch Gmsh GUI
    gmsh.finalize()

    return gmsh_dict
Beispiel #8
0
def create_mesh(r, w, l1, l2, n):
    gmsh.initialize()
    gmsh.option.setNumber("General.Terminal", 0)

    gmsh.model.add("fork")
    lc = 0

    gmsh.model.occ.addPoint(0, 0, 0, lc, 1)
    gmsh.model.occ.addPoint(-r, 0, 0, lc, 2)
    gmsh.model.occ.addPoint(-(r + w), 0, 0, lc, 3)
    gmsh.model.occ.addPoint(+r, 0, 0, lc, 4)
    gmsh.model.occ.addPoint(+(r + w), 0, 0, lc, 5)

    gmsh.model.occ.addPoint(-(r + w), +l1, 0, lc, 6)
    gmsh.model.occ.addPoint(+(r + w), +l1, 0, lc, 7)

    gmsh.model.occ.addPoint(-r, +l1, 0, lc, 8)
    gmsh.model.occ.addPoint(+r, +l1, 0, lc, 9)

    x1 = w / 2
    y1 = math.sqrt((r + w) * (r + w) - (w / 2) * (w / 2))
    a = x1 / y1
    y2 = math.sqrt(r * r / (1 + a * a))
    x2 = a * y2

    gmsh.model.occ.addPoint(-x1, -y1, lc, 10)
    gmsh.model.occ.addPoint(-x2, -y2, lc, 11)
    gmsh.model.occ.addPoint(+x1, -y1, lc, 12)
    gmsh.model.occ.addPoint(+x2, -y2, lc, 13)

    gmsh.model.occ.addPoint(-w / 2, -l2, lc, 14)
    gmsh.model.occ.addPoint(+w / 2, -l2, lc, 15)

    gmsh.model.occ.addLine(14, 10, 1)
    gmsh.model.occ.addLine(10, 11, 2)
    gmsh.model.occ.addLine(14, 15, 3)
    gmsh.model.occ.addLine(15, 12, 4)
    gmsh.model.occ.addLine(12, 13, 5)
    gmsh.model.occ.addLine(3, 6, 6)
    gmsh.model.occ.addLine(6, 8, 7)
    gmsh.model.occ.addLine(8, 2, 8)
    gmsh.model.occ.addLine(2, 3, 9)
    gmsh.model.occ.addLine(4, 9, 10)
    gmsh.model.occ.addLine(9, 7, 11)
    gmsh.model.occ.addLine(7, 5, 12)
    gmsh.model.occ.addLine(5, 4, 13)

    gmsh.model.occ.addCircleArc(2, 1, 11, 14)
    gmsh.model.occ.addCircleArc(11, 1, 13, 15)
    gmsh.model.occ.addCircleArc(13, 1, 4, 16)
    gmsh.model.occ.addCircleArc(3, 1, 10, 17)
    gmsh.model.occ.addCircleArc(10, 1, 12, 18)
    gmsh.model.occ.addCircleArc(12, 1, 5, 19)

    gmsh.model.occ.addCurveLoop([3, 4, -18, -1], 1)
    gmsh.model.occ.addCurveLoop([18, 5, -15, -2], 2)
    gmsh.model.occ.addCurveLoop([19, 13, -16, -5], 3)
    gmsh.model.occ.addCurveLoop([14, -2, -17, -9], 4)
    gmsh.model.occ.addCurveLoop([13, 10, 11, 12], 5)
    gmsh.model.occ.addCurveLoop([8, 9, 6, 7], 6)

    gmsh.model.occ.addPlaneSurface([1], 1)
    gmsh.model.occ.addPlaneSurface([2], 2)
    gmsh.model.occ.addPlaneSurface([3], 3)
    gmsh.model.occ.addPlaneSurface([4], 4)
    gmsh.model.occ.addPlaneSurface([5], 5)
    gmsh.model.occ.addPlaneSurface([6], 6)

    gmsh.model.occ.synchronize()

    gmsh.model.mesh.setTransfiniteCurve(3, n + 1)
    gmsh.model.mesh.setTransfiniteCurve(18, n + 1)
    gmsh.model.mesh.setTransfiniteCurve(15, n + 1)
    gmsh.model.mesh.setTransfiniteCurve(5, n + 1)
    gmsh.model.mesh.setTransfiniteCurve(2, n + 1)
    gmsh.model.mesh.setTransfiniteCurve(9, n + 1)
    gmsh.model.mesh.setTransfiniteCurve(13, n + 1)
    gmsh.model.mesh.setTransfiniteCurve(11, n + 1)
    gmsh.model.mesh.setTransfiniteCurve(7, n + 1)

    gmsh.model.mesh.setTransfiniteCurve(6, 12 * n + 1)
    gmsh.model.mesh.setTransfiniteCurve(8, 12 * n + 1)
    gmsh.model.mesh.setTransfiniteCurve(10, 12 * n + 1)
    gmsh.model.mesh.setTransfiniteCurve(12, 12 * n + 1)

    gmsh.model.mesh.setTransfiniteCurve(14, 3 * n + 1)
    gmsh.model.mesh.setTransfiniteCurve(17, 3 * n + 1)
    gmsh.model.mesh.setTransfiniteCurve(16, 3 * n + 1)
    gmsh.model.mesh.setTransfiniteCurve(19, 3 * n + 1)

    gmsh.model.mesh.setTransfiniteCurve(1, 8 * n + 1)
    gmsh.model.mesh.setTransfiniteCurve(4, 8 * n + 1)

    gmsh.model.mesh.setTransfiniteSurface(1)
    gmsh.model.mesh.setTransfiniteSurface(2)
    gmsh.model.mesh.setTransfiniteSurface(3)
    gmsh.model.mesh.setTransfiniteSurface(4)
    gmsh.model.mesh.setTransfiniteSurface(5)
    gmsh.model.mesh.setTransfiniteSurface(6)

    gmsh.model.occ.extrude([(2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (2, 6)], 0,
                           0, w, [int(n)], [], True)

    gmsh.model.occ.synchronize()

    gmsh.model.addPhysicalGroup(3, [1, 2, 3, 4, 5, 6], 1)
    gmsh.model.setPhysicalName(3, 1, "bulk")

    gmsh.model.addPhysicalGroup(2, [7], 2)
    gmsh.model.setPhysicalName(2, 2, "base")

    gmsh.model.occ.synchronize()

    gmsh.option.setNumber("Mesh.RecombineAll", 1)
    gmsh.option.setNumber("Mesh.ElementOrder", 2)
    gmsh.model.mesh.generate(3)
    nodes, coord, parametric_coord = gmsh.model.mesh.getNodes()
    gmsh.write("fork.msh")

    gmsh.model.remove()
    #gmsh.fltk.run()

    gmsh.finalize()
    return len(nodes)
Beispiel #9
0
def optimize_mesh(in_file,
                  out_file=None,
                  method="",
                  force=False,
                  dim_tags=[],
                  dim=3):
    """ Optimize a mesh using an optimizer

    See: https://gitlab.onelab.info/gmsh/gmsh/-/blob/master/api/gmsh.py#L1444

    Parameters
    ----------
    in_file : Path or str
        path to .geo file to be optimized
        Note: You are unable to optimize .msh-files.
        Therefore, only .geo files can be passed.
    out_file : Path or str
        output file. By default, in_file+"optimized"
    method : str
        name of optimizer.
        Default: '' (gmsh default tetrahedral optimizer)
        Other options:
            'Netgen': Netgen optimizer
            'HighOrder': direct high-order mesh optimizer
            'HighOrderElastic': high-order elastic smoother
            'HighOrderFastCurving': fast curving algorithm
            'Laplace2D': Laplace smoothing
            'Relocate2D': Node relocation, 2d
            'Relocate3D': Node relocation, 3d
    force : bool
        If set, apply the optimization also to discrete entities
    dim_tags : List
        If supplied, only apply the optimizer to the given entities
    dim : int
        Which dimension to mesh. Defaults to 3D.

    """
    # Check in- and out-file paths
    in_file = Path(in_file)
    out_file = Path(out_file)
    assert in_file.is_file()
    assert in_file.suffix == ".geo"
    out_file.parent.mkdir(exist_ok=True, parents=True)
    out_file.with_suffix(".msh")

    print(out_file)
    # Optimize the mesh.
    import gmsh

    gmsh.initialize()

    # Mesh Statistics
    gmsh.option.setNumber("General.Terminal", 1)
    # gmsh.option.setNumber("Print.PostGamma", 1)
    # gmsh.option.setNumber("Print.PostEta", 1)
    # gmsh.option.setNumber("Print.PostSICN", 1)
    # gmsh.option.setNumber("Print.PostSIGE", 1)

    gmsh.open(str(in_file))

    gmsh.model.mesh.generate(dim=dim)
    gmsh.model.mesh.optimize(method=method, force=force, dimTags=dim_tags)

    # Write to .msh and close gmsh
    gmsh.write(str(out_file))
    gmsh.finalize()
Beispiel #10
0
 def _finalize_gmsh(self):
     gmsh.finalize()
Beispiel #11
0
 def __exit__(self, *a):
     # TODO remove once gmsh 4.7.0 is out
     # <https://gitlab.onelab.info/gmsh/gmsh/-/issues/1001>
     gmsh.option.setNumber("Mesh.CharacteristicLengthMin", 0.0)
     gmsh.option.setNumber("Mesh.CharacteristicLengthMax", 1.0e22)
     gmsh.finalize()
Beispiel #12
0
 def __exit__(self, *a):
     gmsh.finalize()
Beispiel #13
0
def PVSbrain_simulation(args):
    """ Test case for simple diffusion from PVS to the brain. 
    Outputs :
    - a logfile with information about the simulation
    - .pvd files at specified args.toutput time period with the u, p and c fields in stokes domain and u, p , q, phi and c fields in Biot domain
    - .csv files of u, p, c 1D array of the u, p, c fields on the middle line of the PVS 
    - .csv files of the total mass in the domain, mass flux from the brain to sas, brain to PVS, PVS to SAS

    """

    # output folder name
    outputfolder = args.output_folder + '/' + args.job_name + '/'

    if not os.path.exists(outputfolder):
        os.makedirs(outputfolder)

    if not os.path.exists(outputfolder + '/fields'):
        os.makedirs(outputfolder + '/fields')

    # Create output files
    #pvd files
    c_out = File(outputfolder + 'fields' + '/c.pvd')

    facets_out_fluid = File(outputfolder + 'fields' + '/facets_fluid.pvd')
    facets_out_solid = File(outputfolder + 'fields' + '/facets_solid.pvd')

    # Create logger
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)

    # log to a file
    now = datetime.now().strftime("%Y%m%d_%H%M%S")
    filename = os.path.join(outputfolder + '/', 'PVSBrain_info.log')
    file_handler = logging.FileHandler(filename, mode='w')
    file_handler.setLevel(logging.INFO)
    #formatter = logging.Formatter("%(asctime)s %(filename)s, %(lineno)d, %(funcName)s: %(message)s")
    #file_handler.setFormatter(formatter)
    logger.addHandler(file_handler)

    # log to the console
    console_handler = logging.StreamHandler()
    level = logging.INFO
    console_handler.setLevel(level)
    logger.addHandler(console_handler)

    # initialise logging

    logging.info(
        title1(
            "Test case of simple diffusion from PVS to the brain using the diffusion-advection solver"
        ))

    logging.info("Date and time:" +
                 datetime.now().strftime("%m/%d/%Y, %H:%M:%S"))

    logging.info('Job name : ' + args.job_name)

    logging.debug('logging initialized')

    # Set parameters

    logging.info(title1("Parameters"))

    # Geometry params
    logging.info('\n * Geometry')
    Rv = args.radius_vessel  # centimeters
    Rpvs = args.radius_pvs  # centimeters
    Rbrain = args.radius_brain  # centimeters
    L = args.length  # centimeters

    logging.info('Vessel radius : %e cm' % Rv)
    logging.info('PVS radius : %e cm' % Rpvs)
    logging.info('Brain radius : %e cm' % Rbrain)
    logging.info('length : %e cm' % L)

    #Mesh
    logging.info('\n * Mesh')
    #number of cells in the radial direction fluid domain
    Nr = args.N_radial_fluid
    #number of cells in the radial direction biot domain
    Nr_biot = args.N_radial_biot
    s_biot = args.biot_progression

    DR = (Rpvs - Rv) / Nr
    #number of cells in the axial direction
    if args.N_axial:
        Nl = args.N_axial
    else:
        Nl = round(L / DR)

    DY = L / Nl

    logging.info('N axial: %i' % Nl)
    logging.info('N radial PVS: %e' % Nr)
    logging.info('N radial Biot: %e' % Nr_biot)
    logging.info('progression parameter in biot: %e' % s_biot)

    #time parameters
    logging.info('\n * Time')
    toutput = args.toutput
    tfinal = args.tend
    dt = args.time_step

    logging.info('final time: %e s' % tfinal)
    logging.info('output period : %e s' % toutput)
    logging.info('time step : %e s' % dt)

    dt_advdiff = dt

    logging.info('\n* Tracer properties')
    D = args.diffusion_coef
    sigma_gauss = args.sigma
    logging.info('Free diffusion coef: %e cm2/s' % D)
    logging.info('STD of initial gaussian profile: %e ' % sigma_gauss)
    xi_gauss = args.initial_pos
    logging.info('Initial position: %e cm2' % xi_gauss)

    logging.info('\n * Porous medium properties')

    porosity_0 = args.biot_porosity
    tortuosity = args.biot_tortuosity

    dt_solid = dt

    logging.info('initial porosity: %e ' % porosity_0)
    logging.info('tortuosity: %e ' % tortuosity)

    ## The tracer is solver in the full domain, so it has two subdomains
    # 1 for solid
    # 0 for fluid

    tracer_parameters = {
        'kappa_0': D,
        'kappa_1': D * tortuosity,
        'dt': dt_advdiff,
        'nsteps': 1
    }

    # Mesh
    logging.info(title1('Meshing'))

    meshing = args.mesh_method

    ##### Meshing method : regular

    if meshing == 'regular':
        # Create a mesh using Rectangle mesh : all the cells are regulars but this means a lot of cells

        logging.info('cell size : %e cm' % (np.sqrt(DR**2 + DY**2)))

        # Create a rectangle mesh with Nr + Nsolid cells in the radias direction and Nl cells in the axial direction
        # the geometrical progression for the solid mesh is s

        #Creation of the uniform mesh
        Rext = 1 + Nr_biot / Nr
        mesh = RectangleMesh(Point(0, 0), Point(L, Rext), Nl, Nr + Nr_biot)
        x = mesh.coordinates()[:, 0]
        y = mesh.coordinates()[:, 1]

        #Deformation of the mesh

        def deform_mesh(x, y):
            transform_fluid = Rv + (Rpvs - Rv) * y
            transform_solid = Rpvs + (Rbrain - Rpvs) * ((y - 1) /
                                                        (Rext - 1))**s_biot
            yp = np.where(y <= 1, transform_fluid, transform_solid)
            return [x, yp]

        x_bar, y_bar = deform_mesh(x, y)
        xy_bar_coor = np.array([x_bar, y_bar]).transpose()
        mesh.coordinates()[:] = xy_bar_coor
        mesh.bounding_box_tree().build(mesh)

    else:

        ##### Meshing method : gmsh with box for refinement

        from sleep.mesh import mesh_model2d, load_mesh2d, set_mesh_size
        import sys

        gmsh.initialize(['', '-format', 'msh2'])

        model = gmsh.model

        import math
        Apvs0 = math.pi * Rpvs**2
        Av0 = math.pi * Rv**2
        A0 = Apvs0 - Av0

        # progressive mesh
        factory = model.occ
        a = factory.addPoint(0, Rv, 0)
        b = factory.addPoint(L, Rv, 0)
        c = factory.addPoint(L, Rpvs, 0)
        d = factory.addPoint(0, Rpvs, 0)
        e = factory.addPoint(L, Rbrain, 0)
        f = factory.addPoint(0, Rbrain, 0)

        fluid_lines = [
            factory.addLine(*p) for p in ((a, b), (b, c), (c, d), (d, a))
        ]
        named_lines = dict(
            zip(('bottom', 'pvs_right', 'interface', 'pvs_left'), fluid_lines))

        fluid_loop = factory.addCurveLoop(fluid_lines)
        fluid = factory.addPlaneSurface([fluid_loop])

        solid_lines = [
            factory.addLine(*p) for p in ((d, c), (c, e), (e, f), (f, d))
        ]
        named_lines.update(
            dict(
                zip(('interface', 'brain_right', 'brain_top', 'brain_left'),
                    solid_lines)))

        solid_loop = factory.addCurveLoop(solid_lines)
        solid = factory.addPlaneSurface([solid_loop])

        factory.synchronize()

        tags = {'cell': {'F': 1, 'S': 2}, 'facet': {}}

        model.addPhysicalGroup(2, [fluid], 1)
        model.addPhysicalGroup(2, [solid], 2)

        for name in named_lines:
            tag = named_lines[name]
            model.addPhysicalGroup(1, [tag], tag)

        # boxes for mesh refinement
        cell_size = DR * (Rpvs - Rv) / (Rpvs - Rv)
        boxes = []
        # add box on the PVS for mesh
        field = model.mesh.field

        fid = 1
        field.add('Box', fid)
        field.setNumber(fid, 'XMin', 0)
        field.setNumber(fid, 'XMax', L)
        field.setNumber(fid, 'YMin', Rv)
        field.setNumber(fid, 'YMax', Rpvs)
        field.setNumber(fid, 'VIn', cell_size * 2)
        field.setNumber(fid, 'VOut', DR * 50)
        field.setNumber(fid, 'Thickness', (Rpvs - Rv) / 4)

        boxes.append(fid)

        # Combine
        field.add('Min', fid + 1)
        field.setNumbers(fid + 1, 'FieldsList', boxes)
        field.setAsBackgroundMesh(fid + 1)

        model.occ.synchronize()

        h5_filename = outputfolder + '/mesh.h5'

        mesh_model2d(model, tags, h5_filename)

        mesh, markers, lookup = load_mesh2d(h5_filename)

        from IPython import embed
        embed()

        gmsh.finalize()

    ## Define subdomains

    x = mesh.coordinates()[:, 0]
    y = mesh.coordinates()[:, 1]

    tol = 1e-7

    class Omega_0(SubDomain):
        def inside(self, x, on_boundary):
            return x[1] < Rpvs + tol

    class Omega_1(SubDomain):
        def inside(self, x, on_boundary):
            return x[1] > Rpvs - tol

    subdomains = MeshFunction("size_t", mesh, mesh.topology().dim(), 0)

    subdomain_0 = Omega_0()
    subdomain_1 = Omega_1()
    subdomain_0.mark(subdomains, 0)
    subdomain_1.mark(subdomains, 1)

    mesh_f = EmbeddedMesh(subdomains, 0)
    mesh_s = EmbeddedMesh(subdomains, 1)

    ## Define boundaries
    solid_bdries = MeshFunction("size_t", mesh_s,
                                mesh_s.topology().dim() - 1, 0)
    fluid_bdries = MeshFunction("size_t", mesh_f,
                                mesh_f.topology().dim() - 1, 0)
    full_bdries = MeshFunction("size_t", mesh, mesh.topology().dim() - 1, 0)

    # Label facets

    class Boundary_left_fluid(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and near(x[0], 0, tol) and (x[1] <= Rpvs + tol
                                                           )  #left fluid

    class Boundary_right_fluid(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and near(x[0], L, tol) and (x[1] <= Rpvs + tol
                                                           )  # right fluid

    class Boundary_left_solid(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and near(x[0], 0, tol) and (x[1] >= Rpvs - tol
                                                           )  #left solid

    class Boundary_right_solid(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and near(x[0], L, tol) and (x[1] >= Rpvs - tol
                                                           )  # right solid

    class Boundary_bottom(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and near(x[1], Rv, tol)  #bottom

    class Boundary_top(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and near(x[1], Rbrain, tol)  #top

    class Boundary_interface(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and near(x[1], Rpvs, tol)  #interface

    #todo : keep separate F and S for right and left in the full bdries

    btop = Boundary_top()
    bbottom = Boundary_bottom()
    bleft_fluid = Boundary_left_fluid()
    bright_fluid = Boundary_right_fluid()
    bleft_solid = Boundary_left_solid()
    bright_solid = Boundary_right_solid()
    binterface = Boundary_interface()

    bbottom.mark(fluid_bdries, 2)
    binterface.mark(fluid_bdries, 4)
    bleft_fluid.mark(fluid_bdries, 1)
    bright_fluid.mark(fluid_bdries, 3)

    binterface.mark(solid_bdries, 4)
    bright_solid.mark(solid_bdries, 5)
    btop.mark(solid_bdries, 6)
    bleft_solid.mark(solid_bdries, 7)

    bleft_fluid.mark(full_bdries, 1)
    bleft_solid.mark(full_bdries, 7)
    bbottom.mark(full_bdries, 2)
    bright_fluid.mark(full_bdries, 3)
    bright_solid.mark(full_bdries, 5)
    btop.mark(full_bdries, 6)

    facet_lookup = {
        'F_left': 1,
        'F_bottom': 2,
        'F_right': 3,
        'Interface': 4,
        'S_left': 7,
        'S_top': 6,
        'S_right': 5
    }

    facets_out_fluid << fluid_bdries

    facets_out_solid << solid_bdries

    # define the domain specific parameters for the tracer
    # NOTE: Here we do P0 projection
    dx = Measure('dx', domain=mesh, subdomain_data=subdomains)
    CoefSpace = FunctionSpace(mesh, 'DG', 0)
    q = TestFunction(CoefSpace)

    # Remove
    coef = 'kappa'

    fluid_coef = tracer_parameters.pop('%s_0' % coef)
    solid_coef = tracer_parameters.pop('%s_1' % coef)

    form = ((1 / CellVolume(mesh)) * fluid_coef * q * dx(0) +
            (1 / CellVolume(mesh)) * solid_coef * q * dx(1))

    tracer_parameters[coef] = Function(CoefSpace, assemble(form))

    #FEM space

    logging.info(title1("Set FEM spaces"))

    logging.info('\n * Tracer')
    #### Todo : I would like to be able to have discontinuous concentration when we will have the membrane
    #### Beter to solve in two domains or one domain with discontinuous lagrange element ?
    Ct_elm = FiniteElement('Lagrange', triangle, 1)
    Ct = FunctionSpace(mesh, Ct_elm)
    logging.info('Concentration : "Lagrange", triangle, 1')

    #Advection velocity
    FS_advvel = VectorFunctionSpace(mesh, 'CG', 2)

    # Setup of boundary conditions
    logging.info(title1("Boundary conditions"))

    ## to do : allow zero concentration if fluid BC is free on the right
    logging.info('\n * Tracer concentration')

    bcs_tracer = {
        'concentration': [(facet_lookup['S_top'], Constant(0))],
        'flux': [
            (facet_lookup['S_left'], Constant(0)),
            (facet_lookup['S_right'], Constant(0)),
            (facet_lookup['F_right'], Constant(0)),
            (facet_lookup['F_left'], Constant(0)),
            (facet_lookup['F_bottom'], Constant(0)),
        ]
    }

    # Initialisation :

    # 1 in the PVS
    cf_0 = Expression('x[1]<= Rpvs ? 1 : 0 ',
                      degree=2,
                      a=1 / 2 / sigma_gauss**2,
                      b=xi_gauss,
                      Rv=Rv,
                      Rpvs=Rpvs)

    c_n = project(cf_0, Ct)  #

    File('initial_reg.pvd') << c_n
    exit()

    #Initial deformation of the fluid domain
    # We start at a time shift
    tshift = 0  #

    c_n.rename("c", "tmp")
    c_out << (c_n, 0)

    ############# RUN ############3

    logging.info(title1("Run"))

    # Time loop
    time = tshift
    timestep = 0

    # Here I dont know if there will be several dt for advdiff and fluid solver
    while time < tfinal + tshift:

        time += dt
        timestep += 1
        print('time', time - tshift)

        # Solve tracer problem

        tracer_parameters["T0"] = time

        advection_velocity = project(Constant((0, 0)), FS_advvel)

        c_, T0 = solve_adv_diff(Ct,
                                velocity=advection_velocity,
                                phi=Constant(0.2),
                                f=Constant(0),
                                c_0=c_n,
                                phi_0=Constant(0.2),
                                bdries=full_bdries,
                                bcs=bcs_tracer,
                                parameters=tracer_parameters)

        # Update current solution

        c_n.assign(c_)

        # Save output
        if (timestep % int(toutput / dt) == 0):

            logging.info("\n*** save output time %e s" % (time - tshift))
            logging.info("number of time steps %i" % timestep)

            # may report Courant number or other important values that indicate how is doing the run

            c_n.rename("c", "tmp")
            c_out << (c_n, time - tshift)

            advection_velocity.rename("adv_vel", "tmp")
            File(outputfolder + 'fields' +
                 '/adv_vel.pvd') << (advection_velocity, time - tshift)
Beispiel #14
0
def draw_GMSH(
    output,
    sym,
    boundary_prop,
    boundary_list,
    surface_label,
    is_antiper=False,
    is_remove_vent=False,
    is_remove_slotS=False,
    is_remove_slotR=False,
    is_lam_only_S=False,
    is_lam_only_R=False,
    kgeo_fineness=1,
    kmesh_fineness=1,
    user_mesh_dict={},
    path_save="GMSH_model.msh",
    is_sliding_band=False,
    is_airbox=False,
    transform_list=[],
    is_set_labels=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 labels (dict keys) that are set in the build_geometry methods
    boundary_list : list
        list of boundary condition names
    surface_label : dict
        dict for the translation of the actual surface labels into FEA software compatible labels
    is_remove_vent : bool
        True to remove the ventilation ducts (Default value = False)
    is_remove_slotS : bool
        True to solve without slot effect on the Stator (Default value = False)
    is_remove_slotR : bool
        True to solve without slot effect on the Rotor (Default value = False)
    kgeo_fineness : float
        global coefficient to adjust geometry fineness
    kmesh_fineness : float
        global coefficient to adjust mesh fineness
    is_antiper: bool
        To apply antiperiodicity boundary conditions
    is_lam_only_S: bool
        Draw only stator lamination
    is_lam_only_R: bool
        Draw only rotor lamination

    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(
            "Only 'is_lam_only_S' or 'is_lam_only_R' can 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
    mesh_size_R = machine.rotor.Rext / 25.0

    # 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()
    rotor_list.extend(machine.shaft.build_geometry(sym=sym, alpha=alpha))
    rotor_list.extend(machine.rotor.build_geometry(sym=sym, alpha=alpha))
    stator_list = list()
    stator_list.extend(machine.stator.build_geometry(sym=sym, alpha=alpha))

    # 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
    if not is_lam_only_S:
        for surf in rotor_list:
            nsurf += 1
            # print(surf.label)
            gmsh_dict.update({
                nsurf: {
                    "tag": None,
                    "label": surface_label.get(surf.label, "UNKNOWN"),
                }
            })
            if "Lamination_Rotor" in surf.label:
                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:  # check if dict is not None nor empty
                mesh_dict.update(user_mesh_dict)

            # add all lines of the current surface to the gmsh_dict
            for line in surf.get_lines():
                # When symmetry is 1 the shaft surface is substrtacted from Rotor Lam instead
                if sym == 1 and line.label == "Lamination_Rotor_Yoke_Radius_Int":
                    continue
                n_elem = mesh_dict.get(line.label)
                n_elem = n_elem if n_elem is not None else 0
                bc_name = get_boundary_condition(line, boundary_prop)

                # Gmsh built-in engine does not allow arcs larger than 180deg
                # so arcs are split into two
                if (isinstance(line, Arc)
                        and abs(line.get_angle() * 180.0 / cmath.pi) >= 180.0):
                    rot_dir = 1 if line.is_trigo_direction == True else -1
                    arc1 = Arc2(
                        begin=line.get_begin(),
                        center=line.get_center(),
                        angle=rot_dir * cmath.pi / 2.0,
                        label=line.label,
                    )
                    arc2 = Arc2(
                        begin=arc1.get_end(),
                        center=line.get_center(),
                        angle=rot_dir * cmath.pi / 2.0,
                        label=line.label,
                    )
                    for arc in [arc1, arc2]:
                        _add_line_to_dict(
                            geo=factory,
                            line=arc,
                            d=gmsh_dict,
                            idx=nsurf,
                            mesh_size=mesh_size_R,
                            n_elements=n_elem,
                            bc=bc_name,
                        )
                elif isinstance(line, Arc) and (abs(
                        line.get_angle() * 180.0 / cmath.pi) <= tol):
                    # Don't draw anything, this is a circle and usually is repeated ?
                    pass
                else:
                    _add_line_to_dict(
                        geo=factory,
                        line=line,
                        d=gmsh_dict,
                        idx=nsurf,
                        mesh_size=mesh_size_R,
                        n_elements=n_elem,
                        bc=bc_name,
                    )

        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)
            if "MAGNET" in s_data["label"]:
                rotor_cloops.extend([cloop])

            # search for the holes to substract from rotor lam
            if "ROTOR_LAM" in s_data["label"]:
                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 s_data["label"] == "SHAFT":
                        lam_and_holes.extend([cloop])
                else:
                    if sym == 1:
                        lam_and_holes.extend([cloop])
                    elif s_data["label"] != "SHAFT":
                        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()

    # 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": surface_label.get(surf.label, "UNKNOWN"),
                }
            })
            if surf.label.find("Lamination_Stator") != -1:
                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:  # check if dict is not None nor empty
                mesh_dict.update(user_mesh_dict)

            # add all lines of the current surface to the gmsh_dict
            for line in surf.get_lines():
                n_elem = mesh_dict.get(line.label)
                n_elem = n_elem if n_elem is not None else 0
                bc_name = get_boundary_condition(line, boundary_prop)

                # Gmsh built-in engine does not allow arcs larger than 180deg
                # so arcs are split into two
                if (isinstance(line, Arc)
                        and abs(line.get_angle() * 180.0 / cmath.pi) >= 180.0):
                    rot_dir = 1 if line.is_trigo_direction == True else -1
                    arc1 = Arc2(
                        begin=line.get_begin(),
                        center=line.get_center(),
                        angle=rot_dir * cmath.pi / 2.0,
                        label=line.label,
                    )
                    arc2 = Arc2(
                        begin=arc1.get_end(),
                        center=line.get_center(),
                        angle=rot_dir * cmath.pi / 2.0,
                        label=line.label,
                    )
                    for arc in [arc1, arc2]:
                        _add_line_to_dict(
                            geo=factory,
                            line=arc,
                            d=gmsh_dict,
                            idx=nsurf,
                            mesh_size=mesh_size_S,
                            n_elements=n_elem,
                            bc=bc_name,
                        )
                else:
                    _add_line_to_dict(
                        geo=factory,
                        line=line,
                        d=gmsh_dict,
                        idx=nsurf,
                        mesh_size=mesh_size_S,
                        n_elements=n_elem,
                        bc=bc_name,
                    )

        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 (s_data["label"].find("STATOR_LAM") !=
                    -1) 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)

    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 = []

    # Default sliding mesh element size
    mesh_size = 2.0 * cmath.pi * machine.rotor.Rext / 360.0
    # nsurf = 0
    for surf in sb_list:
        nsurf += 1
        gmsh_dict.update({
            nsurf: {
                "tag": None,
                "label": surface_label.get(surf.label, "UNKNOWN"),
            }
        })
        for line in surf.get_lines():
            n_elem = mesh_dict.get(line.label)
            n_elem = n_elem if n_elem is not None else 0
            bc_name = get_boundary_condition(line, boundary_prop)
            # Gmsh built-in engine does not allow arcs larger than 180deg
            # so arcs are split into two
            if (isinstance(line, Arc)
                    and abs(line.get_angle() * 180.0 / cmath.pi) >= 180.0):
                rot_dir = 1 if line.is_trigo_direction == True else -1
                arc1 = Arc2(
                    begin=line.get_begin(),
                    center=line.get_center(),
                    angle=rot_dir * cmath.pi / 2.0,
                    label=line.label,
                )
                arc2 = Arc2(
                    begin=arc1.get_end(),
                    center=line.get_center(),
                    angle=rot_dir * cmath.pi / 2.0,
                    label=line.label,
                )
                for arc in [arc1, arc2]:
                    _add_agline_to_dict(
                        geo=factory,
                        line=arc,
                        d=gmsh_dict,
                        idx=nsurf,
                        mesh_size=mesh_size,
                        n_elements=n_elem,
                        bc=bc_name,
                    )
            else:
                _add_agline_to_dict(
                    geo=factory,
                    line=line,
                    d=gmsh_dict,
                    idx=nsurf,
                    mesh_size=mesh_size,
                    n_elements=n_elem,
                    bc=bc_name,
                )

    for s_data in gmsh_dict.values():
        lloop = []
        # skip this surface dataset if it is the origin
        if s_data["label"] == "origin" or not ("AG_" in s_data["label"]
                                               or "SB_" in s_data["label"]):
            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 "AG_INT" in s_data["label"] 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"])

    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
    mesh_size = machine.stator.Rext / 50.0
    for surf in ab_list:
        nsurf += 1
        gmsh_dict.update({
            nsurf: {
                "tag": None,
                "label": surface_label.get(surf.label, "UNKNOWN"),
            }
        })
        for line in surf.get_lines():
            n_elem = mesh_dict.get(line.label)
            n_elem = n_elem if n_elem is not None else 0
            bc_name = get_boundary_condition(line, boundary_prop)

            # Gmsh built-in engine does not allow arcs larger than 180deg
            # so arcs are split into two
            if (isinstance(line, Arc)
                    and abs(line.get_angle() * 180.0 / cmath.pi) >= 180.0):

                rot_dir = 1 if line.get_angle() > 0 else -1
                arc1 = Arc2(
                    begin=line.get_begin(),
                    center=line.get_center(),
                    angle=rot_dir * cmath.pi / 2.0,
                    label=line.label,
                )
                arc2 = Arc2(
                    begin=arc1.get_end(),
                    center=line.get_center(),
                    angle=rot_dir * cmath.pi / 2.0,
                    label=line.label,
                )
                for arc in [arc1, arc2]:
                    _add_line_to_dict(
                        geo=factory,
                        line=arc,
                        d=gmsh_dict,
                        idx=nsurf,
                        mesh_size=mesh_size,
                        n_elements=n_elem,
                        bc=bc_name,
                    )
            else:
                _add_line_to_dict(
                    geo=factory,
                    line=line,
                    d=gmsh_dict,
                    idx=nsurf,
                    mesh_size=mesh_size,
                    n_elements=n_elem,
                    bc=bc_name,
                )

    for s_id, s_data in gmsh_dict.items():
        lloop = []
        if s_id == 0:
            continue
        for lvalues in s_data.values():
            if s_data["label"].find("AIRBOX") != -1:
                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
    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)

    # gmsh.fltk.run()      # Uncomment to launch Gmsh GUI
    gmsh.finalize()
    return gmsh_dict
Beispiel #15
0
    def chain(self, maxElementSize=None):
        """Get a polygonal chain representing the speaker membrane."""
        # check if cached polygonal chain is still good
        if not (maxElementSize is None
                or maxElementSize == self.maxElementSize):
            self.maxElementSize = maxElementSize
            self.aVertex = None
            self.aSegment = None
            self.nOpenElements = -1
        if self.aVertex is None or self.aSegment is None or self.nOpenElements == -1:
            gmsh.initialize()
            gmsh.option.setNumber("General.Terminal", 1)
            gmsh.model.add("Cone Speaker")
            gmsh.model.geo.addPoint(0.0, 0.0, 0.0, self.maxElementSize, 1)
            gmsh.model.geo.addPoint(*self.coneEdge(), self.maxElementSize, 2)
            gmsh.model.geo.addPoint(*self.capEdge(), self.maxElementSize, 3)
            gmsh.model.geo.addPoint(*self.capSphereCenter(),
                                    self.maxElementSize, 4)
            gmsh.model.geo.addPoint(*self.capCenter(), self.maxElementSize, 5)

            gmsh.model.geo.addLine(1, 2, 1)
            gmsh.model.addPhysicalGroup(1, [1], 1)
            gmsh.model.setPhysicalName(1, 1, "Interface")

            gmsh.model.geo.addLine(2, 3, 2)
            gmsh.model.geo.addCircleArc(3, 4, 5, 3)

            gmsh.model.addPhysicalGroup(1, [2, 3], 2)
            gmsh.model.setPhysicalName(1, 2, "Speaker Cone")
            gmsh.model.geo.synchronize()

            gmsh.model.mesh.generate(1)
            nodeTags, coord, parametricCoord = gmsh.model.mesh.getNodes(
                1, -1, True)
            self.aVertex = np.asarray(coord, dtype=np.float32).reshape(
                len(nodeTags), 3)
            # build reordering dictionary
            nodeTagToIdx = dict()
            for i, t in enumerate(nodeTags):
                nodeTagToIdx[t] = i
            aNodeTags = []
            # extract "open elements" or "Interface" first
            elementTypes, elementTags, nodeTags = gmsh.model.mesh.getElements(
                1, 1)
            assert len(elementTypes
                       ) == 1 and elementTypes[0] == 1  # only line segments
            assert len(elementTags) == 1
            assert len(nodeTags) == 1 and len(
                nodeTags[0]) == len(elementTags[0]) * 2
            aNodeTags.extend(nodeTags[0])  # extract line segment node tags
            self.nOpenElements = len(elementTags[0])

            # extract speaker elements
            elementTypes, elementTags, nodeTags = gmsh.model.mesh.getElements(
                1, 2)
            assert len(elementTypes
                       ) == 1 and elementTypes[0] == 1  # only line segments
            assert len(elementTags) == 1
            assert len(nodeTags) == 1 and len(
                nodeTags[0]) == len(elementTags[0]) * 2
            aNodeTags.extend(nodeTags[0])  # extract line segment node tags

            elementTypes, elementTags, nodeTags = gmsh.model.mesh.getElements(
                1, 3)
            assert len(elementTypes
                       ) == 1 and elementTypes[0] == 1  # only line segments
            assert len(elementTags) == 1
            assert len(nodeTags) == 1 and len(
                nodeTags[0]) == len(elementTags[0]) * 2
            aNodeTags.extend(nodeTags[0])  # extract line segment node tags

            # relabel node tags with index into vertex array
            aTempNodeTags = np.empty(len(aNodeTags), dtype=np.int32)
            for i, t in enumerate(aNodeTags):
                aTempNodeTags[i] = nodeTagToIdx[t]
            self.aSegment = aTempNodeTags.reshape(len(aNodeTags) // 2, 2)
            gmsh.finalize()

            self.oGeometry = Chain(self.aVertex.shape[0],
                                   self.aSegment.shape[0])
            self.oGeometry.aVertex = self.aVertex[:, 1:3]
            self.oGeometry.aEdge = self.aSegment
            self.oGeometry.namedPartition['interface'] = (0,
                                                          self.nOpenElements)
            self.oGeometry.namedPartition['cavity'] = (self.nOpenElements,
                                                       self.aSegment.shape[0])

        return self.oGeometry
Beispiel #16
0
def create_plate_mesh(plate,
                      geom_repr="solid",
                      max_size=0.1,
                      order=1,
                      algo=8,
                      tol=1e-3,
                      fem=None,
                      interactive=False,
                      gmsh_session=None):
    """

    :param plate:
    :param gmsh_session:
    :param geom_repr:
    :param max_size:
    :param order:
    :param algo: Mesh algorithm
    :param tol: Maximum geometry tolerance
    :param fem:
    :param interactive:

    :type plate: ada.Plate
    :type fem: ada.fem.FEM
    :type gmsh_session: gmsh
    """
    temp_dir = _Settings.temp_dir
    if gmsh_session is None:
        gmsh_session = _init_gmsh_session()

    option = gmsh_session.option
    model = gmsh_session.model

    option.setNumber("Mesh.Algorithm", algo)
    option.setNumber("Mesh.MeshSizeFromCurvature", True)
    option.setNumber("Mesh.MinimumElementsPerTwoPi", 12)
    option.setNumber("Mesh.MeshSizeMax", max_size)
    option.setNumber("Mesh.ElementOrder", order)
    option.setNumber("Mesh.SecondOrderIncomplete", 1)
    option.setNumber("Mesh.Smoothing", 3)

    option.setNumber("Geometry.Tolerance", tol)
    option.setNumber("Geometry.OCCImportLabels", 1)  # import colors from STEP

    if geom_repr == "solid":
        option.setNumber("Geometry.OCCMakeSolids", 1)

    name = f"temp_{create_guid()}"
    plate.to_stp(temp_dir / name, geom_repr=geom_repr)
    gmsh_session.merge(str(temp_dir / f"{name}.stp"))

    factory = model.geo

    factory.synchronize()

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

    if interactive:
        gmsh_session.fltk.run()

    if fem is None:
        gmsh_session.write(str(temp_dir / f"{name}.msh"))
        m = meshio.read(str(temp_dir / f"{name}.msh"))
        m.write(temp_dir / f"{name}.xdmf")
        gmsh.finalize()
        return None

    fem_set_name = f"{plate.name}_all"
    get_nodes_and_elements(gmsh_session, fem, fem_set_name=fem_set_name)

    femset = fem.elsets[fem_set_name]
    if geom_repr == "solid":
        fem_sec = FemSection(
            f"{plate.name}_sec",
            "solid",
            femset,
            plate.material,
        )
    else:  # geom_repr == "shell":
        fem_sec = FemSection(f"{plate.name}_sec",
                             "shell",
                             femset,
                             plate.material,
                             local_z=plate.n,
                             thickness=plate.t,
                             int_points=5)
    fem.add_section(fem_sec)
Beispiel #17
0
    def discretize(self, g, data):

        # Get the dictionaries for storage of data and discretization matrices
        parameter_dictionary = data[pp.PARAMETERS][self.keyword]
        matrix_dictionary = data[pp.DISCRETIZATION_MATRICES][self.keyword]
        # The the local mesh arguments
        local_mesh_args = data.get("local_mesh_args", None)

        micro_network = parameter_dictionary[self.network_keyword]
        num_processes = parameter_dictionary.get("num_processes", 1)
        discr_ig = partial(
            self._discretize_interaction_region,
            g,
            micro_network,
            parameter_dictionary,
            local_mesh_args,
        )
        if num_processes == 1:
            # run the code in serial, useful also for debug
            out = []
            for reg in self._interaction_regions(g):
                out.append(discr_ig(reg))
        else:
            # run the code in parallel
            with mp.Pool(processes=num_processes) as p:
                out = p.map(discr_ig, list(self._interaction_regions(g)))

        # Finalize gmsh now that we're done with the discretization.
        gmsh.finalize()
        # Also inform the Gmsh writer we have finalized gmsh.
        pp.fracs.gmsh_interface.GmshWriter.gmsh_initialized = False

        # Data structures to build up the flux discretization as a sparse coo-matrix
        rows_flux, cols_flux, data_flux = [], [], []

        # Data structures for the discretization of boundary conditions
        rows_bound, cols_bound, data_bound = [], [], []

        # data structures for discretization of pressure trace operator on macro boundaries
        rows_cell_trace, cols_cell_trace, data_cell_trace = [], [], []
        rows_face_trace, cols_face_trace, data_face_trace = [], [], []

        # unpack all the values
        for reg_values in out:
            cell, bound, cell_trace, face_trace = reg_values
            cols_flux += cell[0]
            rows_flux += cell[1]
            data_flux += cell[2]

            cols_bound += bound[0]
            rows_bound += bound[1]
            data_bound += bound[2]

            cols_cell_trace += cell_trace[0]
            rows_cell_trace += cell_trace[1]
            data_cell_trace += cell_trace[2]

            cols_face_trace += face_trace[0]
            rows_face_trace += face_trace[1]
            data_face_trace += face_trace[2]

        # Construct the global matrix
        flux = sps.coo_matrix((data_flux, (rows_flux, cols_flux)),
                              shape=(g.num_faces, g.num_cells)).tocsr()

        # Construct the global flux matrix
        bound_flux = sps.coo_matrix((data_bound, (rows_bound, cols_bound)),
                                    shape=(g.num_faces, g.num_faces)).tocsr()

        bound_pressure_cell = sps.coo_matrix(
            (data_cell_trace, (rows_cell_trace, cols_cell_trace)),
            shape=(g.num_faces, g.num_cells),
        ).tocsr()

        bound_pressure_face = sps.coo_matrix(
            (data_face_trace, (rows_face_trace, cols_face_trace)),
            shape=(g.num_faces, g.num_faces),
        ).tocsr()

        # For Neumann boundaries, we should not use the flux discretization (the flux
        # is known). The boundary discretization is modified to simply reuse the flux.
        bc = parameter_dictionary["bc"]
        neumann_faces = np.where(bc.is_neu)[0]
        pp.fvutils.zero_out_sparse_rows(flux, neumann_faces)

        # Set sign of Neumann faces according to the divergence operator. This will
        # counteract minus signs in the divergence during assembly.
        sgn, _ = g.signs_and_cells_of_boundary_faces(neumann_faces)
        # Here we also zero out non-diagonal terms, but these should be zero anyhow
        # (by construction of the coarse problems), but better safe than sorry
        bound_flux = pp.fvutils.zero_out_sparse_rows(bound_flux,
                                                     neumann_faces,
                                                     diag=sgn)

        matrix_dictionary[self.flux_matrix_key] = flux
        matrix_dictionary[self.bound_flux_matrix_key] = bound_flux
        matrix_dictionary[
            self.bound_pressure_cell_matrix_key] = bound_pressure_cell
        matrix_dictionary[
            self.bound_pressure_face_matrix_key] = bound_pressure_face

        # Empty discretization of vector sources - we will not provide this for the
        # foreseeable future.
        matrix_dictionary[self.vector_source_matrix_key] = sps.csc_matrix(
            (g.num_faces, g.num_cells * g.dim))
        matrix_dictionary[
            self.bound_pressure_vector_source_matrix_key] = sps.csc_matrix(
                (g.num_faces, g.num_cells * g.dim))
Beispiel #18
0
def generalized_mesher(elements,
                       fem,
                       geom_repr="solid",
                       max_size=0.1,
                       order=1,
                       algo=8,
                       tol=1e-3,
                       interactive=False,
                       gmsh_session=None):
    """
    :param elements:
    :param gmsh_session:
    :param geom_repr:
    :param max_size:
    :param order:
    :param algo: Mesh algorithm
    :param tol: Maximum geometry tolerance
    :param interactive:
    :type elements: list
    :type fem: ada.fem.FEM
    :type gmsh_session: gmsh
    """
    from ada import Beam

    if gmsh_session is None:
        gmsh_session = _init_gmsh_session()

    temp_dir = _Settings.temp_dir
    name = fem.parent.name.replace("/", "") + f"_{create_guid()}"
    option = gmsh_session.option
    model = gmsh_session.model

    option.setNumber("Mesh.Algorithm", algo)
    option.setNumber("Mesh.MeshSizeFromCurvature", True)
    option.setNumber("Mesh.MinimumElementsPerTwoPi", 12)
    option.setNumber("Mesh.MeshSizeMax", max_size)
    option.setNumber("Mesh.ElementOrder", order)
    option.setNumber("Mesh.SecondOrderIncomplete", 1)
    option.setNumber("Mesh.Smoothing", 3)

    option.setNumber("Geometry.Tolerance", tol)
    option.setNumber("Geometry.OCCImportLabels", 1)  # import colors from STEP

    if geom_repr == "solid":
        option.setNumber("Geometry.OCCMakeSolids", 1)

    model.add(name)
    p = Part("DummyPart") / elements
    if geom_repr in ["shell", "solid"]:
        p.to_stp(temp_dir / name, geom_repr=geom_repr)
        gmsh_session.open(str(temp_dir / f"{name}.stp"))
    else:  # beam
        for el in elements:
            if type(el) is Beam:
                p1, p2 = el.n1.p, el.n2.p
                s = get_point(p1, gmsh_session)
                e = get_point(p2, gmsh_session)
                if len(s) == 0:
                    s = [(0, model.geo.addPoint(*p1.tolist(), max_size))]
                if len(e) == 0:
                    e = [(0, model.geo.addPoint(*p2.tolist(), max_size))]

                # line = model.geo.addLine(s[0][1], e[0][1])

    model.geo.synchronize()
    model.mesh.setRecombine(3, 1)
    model.mesh.generate(3)
    model.mesh.removeDuplicateNodes()

    if interactive:
        gmsh_session.fltk.run()

    get_nodes_and_elements(gmsh_session, fem, name)

    if fem is None:
        gmsh_session.write(str(temp_dir / f"{name}.msh"))
        m = meshio.read(str(temp_dir / f"{name}.msh"))
        m.write(temp_dir / f"{name}.xdmf")
        gmsh.finalize()
        return None

    # TODO: Identify which part of cross section the entities belong to and add physical group to assign section props
    # Alternatively it might be more simple to just build the geometries from scratch.
    # p1, p2 = beam.n1.p, beam.n2.p
    if geom_repr == "solid":
        NotImplementedError("")
    elif geom_repr == "shell":
        # Get element section properties
        ents = gmsh.model.occ.getEntities(2)
        for dim, ent in ents:
            r = model.occ.getCenterOfMass(2, ent)
            for el in elements:
                if type(el) is Beam:
                    elname = el.name.replace("/", "")
                    t, n, c = eval_thick_normal_from_cog_of_beam_plate(el, r)
                    name = model.getEntityName(dim, ent)
                    tags, coord, param = model.mesh.getNodes(2, ent, True)
                    # get surface normal on all nodes, i.e. including on the geometrical
                    # singularities (edges/points)
                    # normals = gmsh.model.getNormal(ent, param)
                    # curv = gmsh.model.getCurvature(2, ent, param)
                    # print(ent, r)
                    elemTypes, elemTags, elemNodeTags = model.mesh.getElements(
                        2, ent)
                    femset = FemSet(f"{elname}_ent{ent}", [
                        fem.elements.from_id(x)
                        for x in chain.from_iterable(elemTags)
                    ], "elset")
                    fem.add_set(femset)
                    fem_sec = FemSection(
                        f"{elname}_{c}_{ent}",
                        "shell",
                        femset,
                        el.material,
                        local_z=n,
                        thickness=t,
                        int_points=5,
                    )
                    fem.add_section(fem_sec)
    else:  # geom_repr == "beam":
        raise NotImplementedError()

    gmsh.finalize()
Beispiel #19
0
for i in range(1, 11):
    factory.addPoint(i, math.sin(i/9.*2.*math.pi), 0, 0.1, i)

factory.addSpline(range(1, 11), 1)
factory.addBSpline(range(1, 11), 2)
factory.addBezier(range(1, 11), 3)

factory.addPoint(0.2,-1.6,0,0.1, 101) 
factory.addPoint(1.2,-1.6,0,0.1, 102) 
factory.addPoint(1.2,-1.1,0,0.1, 103) 
factory.addPoint(0.3,-1.1,0,0.1, 104) 
factory.addPoint(0.7,-1,0,0.1, 105) 

# periodic bspline through the control points
factory.addSpline([103,102,101,104,105,103], 100)

# periodic bspline from given control points and default parameters - will
# create a new vertex
factory.addBSpline([103,102,101,104,105,103], 101)

# general bspline with explicit degree, knots and multiplicities
factory.addPoint(0,-2,0,0.1,201)
factory.addPoint(1,-2,0,0.1,202)
factory.addPoint(1,-3,0,0.1,203)
factory.addPoint(0,-3,0,0.1,204)
factory.addBSpline([201,202,203,204], 200, 2, [], [0,0.5,1], [3,1,3])

factory.synchronize()
gmsh.fltk.run()
gmsh.finalize()
Beispiel #20
0
def mesh_w_tube(mesh_params, mesh_name):
    filename_stem = __file__.split(".")[0]
    case_stem = f"{filename_stem}_{mesh_name}"

    gmsh.initialize()
    model.add(case_stem)

    inner_radius = physical_params.r - physical_params.thickness
    outer_radius = physical_params.r

    # 1

    origin = -physical_params.R, 0.0, 0.0
    axis_dir = 0.0, 1.0, 0.0

    center_of_rot = 0.0, 0.0, 0.0
    rot_normal = 0.0, 0.0, -1.0

    make_elbow(origin, axis_dir, inner_radius, outer_radius, center_of_rot,
               rot_normal, mesh_params.n_rings, mesh_params.n_sectors,
               mesh_params.n_axial)

    # 2

    origin = physical_params.R, -physical_params.l1, 0.0
    axis_dir = 0.0, 1.0, 0.0
    height = physical_params.l1

    make_tube(origin, axis_dir, inner_radius, outer_radius, height,
              mesh_params.n_rings, mesh_params.n_sectors,
              mesh_params.n_layers_2_3)

    # 3

    origin = -physical_params.R, -physical_params.l1, 0.0
    axis_dir = 0.0, 1.0, 0.0
    height = physical_params.l1

    make_tube(origin, axis_dir, inner_radius, outer_radius, height,
              mesh_params.n_rings, mesh_params.n_sectors,
              mesh_params.n_layers_2_3)

    # 4

    origin = -3.0 * physical_params.R, -physical_params.l1, 0.0
    axis_dir = 0.0, 1.0, 0.0

    center_of_rot = -2.0 * physical_params.R, -physical_params.l1, 0.0
    rot_normal = 0.0, 0.0, 1.0

    make_elbow(origin, axis_dir, inner_radius, outer_radius, center_of_rot,
               rot_normal, mesh_params.n_rings, mesh_params.n_sectors,
               mesh_params.n_axial)

    # 5

    origin = 3.0 * physical_params.R, -physical_params.l1, 0.0
    axis_dir = 0.0, 1.0, 0.0

    center_of_rot = 2.0 * physical_params.R, -physical_params.l1, 0.0
    rot_normal = 0.0, 0.0, -1.0

    make_elbow(origin, axis_dir, inner_radius, outer_radius, center_of_rot,
               rot_normal, mesh_params.n_rings, mesh_params.n_sectors,
               mesh_params.n_axial)

    # 6

    origin = 3.0 * physical_params.R, physical_params.l2, 0.0
    axis_dir = 0.0, -1.0, 0.0
    height = physical_params.l1 + physical_params.l2
    make_tube(origin, axis_dir, inner_radius, outer_radius, height,
              mesh_params.n_rings, mesh_params.n_sectors,
              mesh_params.n_layers_6_7)

    # 7

    origin = -3.0 * physical_params.R, physical_params.l2, 0.0
    axis_dir = 0.0, -1.0, 0.0
    height = physical_params.l1 + physical_params.l2
    make_tube(origin, axis_dir, inner_radius, outer_radius, height,
              mesh_params.n_rings, mesh_params.n_sectors,
              mesh_params.n_layers_6_7)

    model.geo.synchronize()
    model.mesh.generate(3)

    gmsh.write(f"{case_stem}.msh")
    gmsh.finalize()