def makeFillet(objs, radius=100, chamfer=False, delete=False):
    """Create a fillet between two lines or edges.

    Parameters
    ----------
    objs : list
        List of two objects of type wire, or edges.
    radius : float, optional
        It defaults to 100 mm. The curvature of the fillet.
    chamfer : bool, optional
        It defaults to `False`. If it is `True` it no longer produces
        a rounded fillet but a chamfer (straight edge)
        with the value of the `radius`.
    delete : bool, optional
        It defaults to `False`. If it is `True` it will delete
        the pair of objects that are used to create the fillet.
        Otherwise, the original objects will still be there.

    Returns
    -------
    Part::Part2DObject
        The object of type `'Fillet'`.
        It returns `None` if it fails producing the object.
    """
    if len(objs) != 2:
        FCC.PrintError("makeFillet: " +
                       translate("draft", "two elements needed") + "\n")
        return None

    e1, e2 = _extract_edges(objs)

    edges = DraftGeomUtils.fillet([e1, e2], radius, chamfer)
    if len(edges) < 3:
        FCC.PrintError("makeFillet: " + translate("draft", "radius too large"))
        FCC.PrintError(", r=" + str(radius) + "\n")
        return None

    _d = translate("draft", "length: ")
    FCC.PrintMessage("e1, " + _d + str(edges[0].Length) + "\n")
    FCC.PrintMessage("e2, " + _d + str(edges[1].Length) + "\n")
    FCC.PrintMessage("e3, " + _d + str(edges[2].Length) + "\n")

    try:
        wire = Part.Wire(edges)
    except Part.OCCError:
        return None

    obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython",
                                           "Fillet")
    Fillet(obj)
    obj.Shape = wire
    obj.Length = wire.Length
    obj.Start = wire.Vertexes[0].Point
    obj.End = wire.Vertexes[-1].Point
    obj.FilletRadius = radius

    if delete:
        FreeCAD.ActiveDocument.removeObject(objs[0].Name)
        FreeCAD.ActiveDocument.removeObject(objs[1].Name)
        _r = translate("draft", "removed original objects")
        FCC.PrintMessage("makeFillet: " + _r + "\n")
    if FreeCAD.GuiUp:
        Draft._ViewProviderWire(obj.ViewObject)
        Draft.formatObject(obj)
        Draft.select(obj)
    return obj
Example #2
0
def get_z88_element_type(
    femmesh,
    femelement_table=None
):
    if not femmesh:
        Console.PrintError("Error: No femmesh.\n")
    if not femelement_table:
        Console.PrintError("The femelement_table need to be calculated.\n")
        femelement_table = meshtools.get_femelement_table(femmesh)
    # in some cases lowest key in femelement_table is not [1]
    for elem in sorted(femelement_table):
        elem_length = len(femelement_table[elem])
        Console.PrintLog("Node count of first element: {}\n".format(elem_length))
        break  # break after the first elem
    if meshtools.is_solid_femmesh(femmesh):
        if femmesh.TetraCount == femmesh.VolumeCount:
            if elem_length == 4:
                return 17
            elif elem_length == 10:
                return 16
            else:
                Console.PrintMessage("Tetra with neither 4 nor 10 nodes.\n")
        elif femmesh.HexaCount == femmesh.VolumeCount:
            if elem_length == 8:
                return 1
            elif elem_length == 20:
                return 10
            else:
                Console.PrintError("Hexa with neither 8 nor 20 nodes.\n")
                return 0
        else:
            Console.PrintError("no tetra, no hexa or Mixed Volume Elements.\n")
    elif meshtools.is_face_femmesh(femmesh):
        if femmesh.TriangleCount == femmesh.FaceCount:
            if elem_length == 3:
                Console.PrintError("tria3mesh, not supported by Z88.\n")
                return 0
            elif elem_length == 6:
                return 24
            else:
                Console.PrintError("Tria with neither 3 nor 6 nodes.\n")
                return 0
        elif femmesh.QuadrangleCount == femmesh.FaceCount:
            if elem_length == 4:
                Console.PrintError("quad4mesh, not supported by Z88.\n")
                return 0
            elif elem_length == 8:
                return 23
            else:
                Console.PrintError("Quad with neither 4 nor 8 nodes.\n")
                return 0
        else:
            Console.PrintError("no tria, no quad\n")
            return 0
    elif meshtools.is_edge_femmesh(femmesh):
        Console.PrintMessage("Edge femmesh will be exported as 3D truss element nr 4.\n")
        return 4
    else:
        Console.PrintError("Neither edge nor face nor solid femmesh.\n")
        return 0
    return 0
Example #3
0
def import_z88_disp(filename, analysis=None, result_name_prefix=None):
    """insert a FreeCAD FEM mechanical result object in the ActiveDocument
    pure usage:
    import feminout.importZ88O2Results as importZ88O2Results
    disp_file = "/pathtofile/z88o2.txt"
    importZ88O2Results.import_z88_disp(disp_file)

    the z888i1.txt FEMMesh file needs to be in the same directory as z88o2.txt
    # ahh, make a new document first ;-)
    """
    import ObjectsFem
    from . import importZ88Mesh
    from . import importToolsFem
    from femresult import resulttools
    if result_name_prefix is None:
        result_name_prefix = ""
    disp_read = read_z88_disp(filename)
    result_mesh_object = None
    if len(disp_read["Nodes"]) > 0:
        if analysis:
            analysis_object = analysis

        # read result mesh
        if filename.endswith("z88o2.txt"):
            mesh_file = filename.replace("o2", "i1")
            mesh_data = importZ88Mesh.read_z88_mesh(mesh_file)
            femmesh = importToolsFem.make_femmesh(mesh_data)
            result_mesh_object = ObjectsFem.makeMeshResult(
                FreeCAD.ActiveDocument, "Result_mesh")
            result_mesh_object.FemMesh = femmesh
        else:
            Console.PrintError("Z88 mesh file z88i1.txt not found.\n")
            return None

        # create result obj
        for result_set in disp_read["Results"]:
            results_name = result_name_prefix + "results"

            res_obj = ObjectsFem.makeResultMechanical(FreeCAD.ActiveDocument,
                                                      results_name)
            res_obj.Mesh = result_mesh_object
            res_obj = importToolsFem.fill_femresult_mechanical(
                res_obj, result_set)
            res_obj = resulttools.add_disp_apps(
                res_obj)  # fill DisplacementLengths
            res_obj = resulttools.fill_femresult_stats(res_obj)  # fill Stats

            if analysis:
                analysis_object.addObject(res_obj)

        if FreeCAD.GuiUp:
            if analysis:
                import FemGui
                FemGui.setActiveAnalysis(analysis_object)
            FreeCAD.ActiveDocument.recompute()

    else:
        Console.PrintError(
            "Problem on Z88 result file import. No nodes found in Z88 result file.\n"
        )
        return None
    return res_obj
Example #4
0
def read_z88_mesh(
    z88_mesh_input
):
    """ reads a z88 mesh file z88i1.txt (Z88OSV14) or z88structure.txt (Z88AuroraV3)
        and extracts the nodes and elements
    """
    nodes = {}
    elements_hexa8 = {}
    elements_penta6 = {}
    elements_tetra4 = {}
    elements_tetra10 = {}
    elements_penta15 = {}
    elements_hexa20 = {}
    elements_tria3 = {}
    elements_tria6 = {}
    elements_quad4 = {}
    elements_quad8 = {}
    elements_seg2 = {}
    elements_seg3 = {}

    input_continues = False
    # elem = -1
    z88_element_type = 0

    z88_mesh_file = pyopen(z88_mesh_input, "r")
    mesh_info = z88_mesh_file.readline().strip().split()

    nodes_dimension = int(mesh_info[0])
    nodes_count = int(mesh_info[1])
    elements_count = int(mesh_info[2])
    kflag = int(mesh_info[4])
    # for non rotational elements ist --> kflag = 0 --> cartesian, kflag = 1 polar coordinates
    if kflag:
        Console.PrintError(
            "KFLAG = 1, Rotational coordinates not supported at the moment\n"
        )
        return {}
    nodes_first_line = 2  # first line is mesh_info
    nodes_last_line = nodes_count + 1
    elemts_first_line = nodes_last_line + 1
    elements_last_line = elemts_first_line - 1 + elements_count * 2

    Console.PrintLog("{}\n".format(nodes_count))
    Console.PrintLog("{}\n".format(elements_count))
    Console.PrintLog("{}\n".format(nodes_last_line))
    Console.PrintLog("{}\n".format(elemts_first_line))
    Console.PrintLog("{}\n".format(elements_last_line))

    z88_mesh_file.seek(0)  # go back to the beginning of the file
    for no, line in enumerate(z88_mesh_file):
        lno = no + 1
        linecolumns = line.split()

        if lno >= nodes_first_line and lno <= nodes_last_line:
            # node line
            node_no = int(linecolumns[0])
            node_x = float(linecolumns[2])
            node_y = float(linecolumns[3])
            if nodes_dimension == 2:
                node_z = 0.0
            elif nodes_dimension == 3:
                node_z = float(linecolumns[4])
            nodes[node_no] = FreeCAD.Vector(node_x, node_y, node_z)

        if lno >= elemts_first_line and lno <= elements_last_line:
            # first element line
            if not input_continues:
                elem_no = int(linecolumns[0])
                z88_element_type = int(linecolumns[1])
                input_continues = True

            # second element line
            elif input_continues:
                # not supported elements
                if z88_element_type == 8:
                    # torus8
                    Console.PrintError(
                        "Z88 Element No. 8, torus8\n"
                    )
                    Console.PrintError(
                        "Rotational elements are not supported at the moment\n"
                    )
                    return {}
                elif z88_element_type == 12:
                    # torus12
                    Console.PrintError(
                        "Z88 Element No. 12, torus12\n"
                    )
                    Console.PrintError(
                        "Rotational elements are not supported at the moment\n"
                    )
                    return {}
                elif z88_element_type == 15:
                    # torus6
                    Console.PrintError(
                        "Z88 Element No. 15, torus6\n"
                    )
                    Console.PrintError(
                        "Rotational elements are not supported at the moment\n"
                    )
                    return {}
                elif z88_element_type == 19:
                    # platte16
                    Console.PrintError(
                        "Z88 Element No. 19, platte16\n"
                    )
                    Console.PrintError(
                        "Not supported at the moment\n"
                    )
                    return {}
                elif z88_element_type == 21:
                    # schale16, mixture made from hexa8 and hexa20 (thickness is linear)
                    Console.PrintError(
                        "Z88 Element No. 21, schale16\n"
                    )
                    Console.PrintError(
                        "Not supported at the moment\n"
                    )
                    return {}
                elif z88_element_type == 22:
                    # schale12, mixtrue made from prism6 and prism15 (thickness is linear)
                    Console.PrintError(
                        "Z88 Element No. 22, schale12\n"
                    )
                    Console.PrintError(
                        "Not supported at the moment\n"
                    )
                    return {}

                # supported elements
                elif z88_element_type == 2 \
                        or z88_element_type == 4 \
                        or z88_element_type == 5 \
                        or z88_element_type == 9 \
                        or z88_element_type == 13 \
                        or z88_element_type == 25:
                    # stab4 or stab5 or welle5 or beam13 or beam25 Z88 --> seg2 FreeCAD
                    # N1, N2
                    nd1 = int(linecolumns[0])
                    nd2 = int(linecolumns[1])
                    elements_seg2[elem_no] = (nd1, nd2)
                    input_continues = False
                elif z88_element_type == 3 or z88_element_type == 14 or z88_element_type == 24:
                    # scheibe3 or scheibe14 or schale24 Z88 --> tria6 FreeCAD
                    # N1, N2, N3, N4, N5, N6
                    nd1 = int(linecolumns[0])
                    nd2 = int(linecolumns[1])
                    nd3 = int(linecolumns[2])
                    nd4 = int(linecolumns[3])
                    nd5 = int(linecolumns[4])
                    nd6 = int(linecolumns[5])
                    elements_tria6[elem_no] = (nd1, nd2, nd3, nd4, nd5, nd6)
                    input_continues = False
                elif z88_element_type == 7 or z88_element_type == 20 or z88_element_type == 23:
                    # scheibe7 or platte20 or schale23 Z88 --> quad8 FreeCAD
                    # N1, N2, N3, N4, N5, N6, N7, N8
                    nd1 = int(linecolumns[0])
                    nd2 = int(linecolumns[1])
                    nd3 = int(linecolumns[2])
                    nd4 = int(linecolumns[3])
                    nd5 = int(linecolumns[4])
                    nd6 = int(linecolumns[5])
                    nd7 = int(linecolumns[6])
                    nd8 = int(linecolumns[7])
                    elements_quad8[elem_no] = (nd1, nd2, nd3, nd4, nd5, nd6, nd7, nd8)
                    input_continues = False
                elif z88_element_type == 17:
                    # volume17 Z88 --> tetra4 FreeCAD
                    # N4, N2, N3, N1
                    nd1 = int(linecolumns[0])
                    nd2 = int(linecolumns[1])
                    nd3 = int(linecolumns[2])
                    nd4 = int(linecolumns[3])
                    elements_tetra4[elem_no] = (nd4, nd2, nd3, nd1)
                    input_continues = False
                elif z88_element_type == 16:
                    # volume16 Z88 --> tetra10 FreeCAD
                    # N1, N2, N4, N3, N5, N8, N10, N7, N6, N9
                    # Z88 to FC is different as FC to Z88
                    nd1 = int(linecolumns[0])
                    nd2 = int(linecolumns[1])
                    nd3 = int(linecolumns[2])
                    nd4 = int(linecolumns[3])
                    nd5 = int(linecolumns[4])
                    nd6 = int(linecolumns[5])
                    nd7 = int(linecolumns[6])
                    nd8 = int(linecolumns[7])
                    nd9 = int(linecolumns[8])
                    nd10 = int(linecolumns[9])
                    elements_tetra10[elem_no] = (
                        nd1, nd2, nd4, nd3, nd5, nd8, nd10, nd7, nd6, nd9
                    )
                    input_continues = False
                elif z88_element_type == 1:
                    # volume1 Z88 --> hexa8 FreeCAD
                    # N1, N2, N3, N4, N5, N6, N7, N8
                    nd1 = int(linecolumns[0])
                    nd2 = int(linecolumns[1])
                    nd3 = int(linecolumns[2])
                    nd4 = int(linecolumns[3])
                    nd5 = int(linecolumns[4])
                    nd6 = int(linecolumns[5])
                    nd7 = int(linecolumns[6])
                    nd8 = int(linecolumns[7])
                    elements_hexa8[elem_no] = (nd1, nd2, nd3, nd4, nd5, nd6, nd7, nd8)
                    input_continues = False
                elif z88_element_type == 10:
                    # volume10 Z88 --> hexa20 FreeCAD
                    # N2, N3, N4, N1, N6, N7, N8, N5, N10, N11
                    # N12, N9,  N14, N15, N16, N13, N18, N19, N20, N17
                    # or turn by 90 degree and they match !
                    # N1, N2, N3, N4, N5, N6, N7, N8, N9, N10
                    # N11, N12, N13, N14, N15, N16, N17, N18, N19, N20
                    nd1 = int(linecolumns[0])
                    nd2 = int(linecolumns[1])
                    nd3 = int(linecolumns[2])
                    nd4 = int(linecolumns[3])
                    nd5 = int(linecolumns[4])
                    nd6 = int(linecolumns[5])
                    nd7 = int(linecolumns[6])
                    nd8 = int(linecolumns[7])
                    nd9 = int(linecolumns[8])
                    nd10 = int(linecolumns[9])
                    nd11 = int(linecolumns[10])
                    nd12 = int(linecolumns[11])
                    nd13 = int(linecolumns[12])
                    nd14 = int(linecolumns[13])
                    nd15 = int(linecolumns[14])
                    nd16 = int(linecolumns[15])
                    nd17 = int(linecolumns[16])
                    nd18 = int(linecolumns[17])
                    nd19 = int(linecolumns[18])
                    nd20 = int(linecolumns[19])
                    elements_hexa20[elem_no] = (
                        nd1, nd2, nd3, nd4, nd5, nd6, nd7, nd8, nd9, nd10,
                        nd11, nd12, nd13, nd14, nd15, nd16, nd17, nd18, nd19, nd20
                    )
                    input_continues = False

                # unknown elements
                # some examples have -1 for some teaching reasons to show some other stuff
                else:
                    Console.PrintError("Unknown element\n")
                    return {}

    for n in nodes:
        Console.PrintLog(str(n) + "  " + str(nodes[n]) + "\n")
    for e in elements_tria6:
        Console.PrintLog(str(e) + "  " + str(elements_tria6[e]) + "\n")
    FreeCAD.Console.PrintLog("\n")

    z88_mesh_file.close()

    return {
        "Nodes": nodes,
        "Seg2Elem": elements_seg2,
        "Seg3Elem": elements_seg3,
        "Tria3Elem": elements_tria3,
        "Tria6Elem": elements_tria6,
        "Quad4Elem": elements_quad4,
        "Quad8Elem": elements_quad8,
        "Tetra4Elem": elements_tetra4,
        "Tetra10Elem": elements_tetra10,
        "Hexa8Elem": elements_hexa8,
        "Hexa20Elem": elements_hexa20,
        "Penta6Elem": elements_penta6,
        "Penta15Elem": elements_penta15
    }
Example #5
0
def write_z88_mesh_to_file(
    femnodes_mesh,
    femelement_table,
    z88_element_type,
    f
):
    node_dimension = 3  # 2 for 2D not supported
    if (
        z88_element_type == 4
        or z88_element_type == 17
        or z88_element_type == 16
        or z88_element_type == 1
        or z88_element_type == 10
    ):
        node_dof = 3
    elif (
        z88_element_type == 23
        or z88_element_type == 24
    ):
        node_dof = 6  # schalenelemente
    else:
        Console.PrintError("Error: wrong z88_element_type.\n")
        return
    node_count = len(femnodes_mesh)
    element_count = len(femelement_table)
    dofs = node_dof * node_count
    unknown_flag = 0
    written_by = "written by FreeCAD"

    # first line, some z88 specific stuff
    f.write("{0} {1} {2} {3} {4} {5}\n".format(
        node_dimension, node_count, element_count, dofs, unknown_flag, written_by)
    )
    # nodes
    for node in femnodes_mesh:
        vec = femnodes_mesh[node]
        f.write(
            "{0} {1} {2:.6f} {3:.6f} {4:.6f}\n"
            .format(node, node_dof, vec.x, vec.y, vec.z)
        )
    # elements
    for element in femelement_table:
        # z88_element_type is checked for every element
        # but mixed elements are not supported up to date
        n = femelement_table[element]
        if (
            z88_element_type == 2
            or z88_element_type == 4
            or z88_element_type == 5
            or z88_element_type == 9
            or z88_element_type == 13
            or z88_element_type == 25
        ):
            # seg2 FreeCAD --> stab4 Z88
            # N1, N2
            f.write("{0} {1}\n".format(element, z88_element_type))
            f.write("{0} {1}\n".format(
                    n[0], n[1]))
        elif z88_element_type == 3 or z88_element_type == 14 or z88_element_type == 24:
            # tria6 FreeCAD --> schale24 Z88
            # N1, N2, N3, N4, N5, N6
            f.write("{0} {1}\n".format(element, z88_element_type))
            f.write("{0} {1} {2} {3} {4} {5}\n".format(
                    n[0], n[1], n[2], n[3], n[4], n[5]))
        elif z88_element_type == 7 or z88_element_type == 20 or z88_element_type == 23:
            # quad8 FreeCAD --> schale23 Z88
            # N1, N2, N3, N4, N5, N6, N7, N8
            f.write("{0} {1}\n".format(element, z88_element_type))
            f.write("{0} {1} {2} {3} {4} {5} {6} {7}\n".format(
                    n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7]))
        elif z88_element_type == 17:
            # tetra4 FreeCAD --> volume17 Z88
            # N4, N2, N3, N1
            f.write("{0} {1}\n".format(element, z88_element_type))
            f.write("{0} {1} {2} {3}\n".format(
                    n[3], n[1], n[2], n[0]))
        elif z88_element_type == 16:
            # tetra10 FreeCAD --> volume16 Z88
            # N1, N2, N4, N3, N5, N9, N8, N6, N10, N7, FC to Z88 is different as Z88 to FC
            f.write("{0} {1}\n".format(element, z88_element_type))
            f.write("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9}\n".format(
                    n[0], n[1], n[3], n[2], n[4], n[8], n[7], n[5], n[9], n[6]))
        elif z88_element_type == 1:
            # hexa8 FreeCAD --> volume1 Z88
            # N1, N2, N3, N4, N5, N6, N7, N8
            f.write("{0} {1}\n".format(element, z88_element_type))
            f.write("{0} {1} {2} {3} {4} {5} {6} {7}\n".format(
                    n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7]))
        elif z88_element_type == 10:
            # hexa20 FreeCAD --> volume10 Z88
            # N2, N3, N4, N1, N6, N7, N8, N5, N10, N11
            # N12, N9,  N14, N15, N16, N13, N18, N19, N20, N17
            # or turn by 90 degree and they match !
            # N1, N2, N3, N4, N5, N6, N7, N8, N9, N10
            # N11, N12, N13, N14, N15, N16, N17, N18, N19, N20
            f.write("{0} {1}\n".format(element, z88_element_type))
            f.write(
                "{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} "
                "{10} {11} {12} {13} {14} {15} {16} {17} {18} {19}\n"
                .format(
                    n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9],
                    n[10], n[11], n[12], n[13], n[14], n[15], n[16], n[17], n[18], n[19]
                )
            )
        else:
            Console.PrintError(
                "Writing of Z88 elementtype {0} not supported.\n".format(z88_element_type)
            )
            # TODO support schale12 (made from prism15) and schale16 (made from hexa20)
            return
Example #6
0
def importFrd(filename, analysis=None, result_name_prefix=""):
    from . import importToolsFem
    import ObjectsFem

    if analysis:
        doc = analysis.Document
    else:
        doc = FreeCAD.ActiveDocument

    m = read_frd_result(filename)
    result_mesh_object = None
    res_obj = None

    if len(m["Nodes"]) > 0:
        mesh = importToolsFem.make_femmesh(m)
        result_mesh_object = ObjectsFem.makeMeshResult(doc, "ResultMesh")
        result_mesh_object.FemMesh = mesh
        res_mesh_is_compacted = False
        nodenumbers_for_compacted_mesh = []

        number_of_increments = len(m["Results"])
        Console.PrintLog("Increments: " + str(number_of_increments) + "\n")
        if len(m["Results"]) > 0:
            for result_set in m["Results"]:
                if "number" in result_set:
                    eigenmode_number = result_set["number"]
                else:
                    eigenmode_number = 0
                step_time = result_set["time"]
                step_time = round(step_time, 2)
                if eigenmode_number > 0:
                    results_name = ("{}Mode{}_Results".format(
                        result_name_prefix, eigenmode_number))
                elif number_of_increments > 1:
                    results_name = ("{}Time{}_Results".format(
                        result_name_prefix, step_time))
                else:
                    results_name = ("{}Results".format(result_name_prefix))

                res_obj = ObjectsFem.makeResultMechanical(doc, results_name)
                res_obj.Mesh = result_mesh_object
                res_obj = importToolsFem.fill_femresult_mechanical(
                    res_obj, result_set)
                if analysis:
                    analysis.addObject(res_obj)

                # complementary result object calculations
                from femresult import resulttools
                from femtools import femutils
                if not res_obj.MassFlowRate:
                    # information 1:
                    # only compact result if not Flow 1D results
                    # compact result object, workaround for bug 2873
                    # https://www.freecadweb.org/tracker/view.php?id=2873
                    # information 2:
                    # if the result data has multiple result sets there will be multiple result objs
                    # they all will use one mesh obj
                    # on the first res obj fill the mesh obj will be compacted, thus
                    # it does not need to be compacted on further result sets
                    # but NodeNumbers need to be compacted for every result set (res object fill)
                    # example frd file: https://forum.freecadweb.org/viewtopic.php?t=32649#p274291
                    if res_mesh_is_compacted is False:
                        # first result set, compact FemMesh and NodeNumbers
                        res_obj = resulttools.compact_result(res_obj)
                        res_mesh_is_compacted = True
                        nodenumbers_for_compacted_mesh = res_obj.NodeNumbers
                    else:
                        # all other result sets, do not compact FemMesh, only set NodeNumbers
                        res_obj.NodeNumbers = nodenumbers_for_compacted_mesh

                # fill DisplacementLengths
                res_obj = resulttools.add_disp_apps(res_obj)
                # fill vonMises
                res_obj = resulttools.add_von_mises(res_obj)
                if res_obj.getParentGroup():
                    has_reinforced_mat = False
                    for obj in res_obj.getParentGroup().Group:
                        if obj.isDerivedFrom("App::MaterialObjectPython") \
                                and femutils.is_of_type(obj, "Fem::MaterialReinforced"):
                            has_reinforced_mat = True
                            resulttools.add_principal_stress_reinforced(
                                res_obj)
                            break
                    if has_reinforced_mat is False:
                        # fill PrincipalMax, PrincipalMed, PrincipalMin, MaxShear
                        res_obj = resulttools.add_principal_stress_std(res_obj)
                else:
                    # if a pure frd file was opened no analysis and thus no parent group
                    # fill PrincipalMax, PrincipalMed, PrincipalMin, MaxShear
                    res_obj = resulttools.add_principal_stress_std(res_obj)
                # fill Stats
                res_obj = resulttools.fill_femresult_stats(res_obj)

        else:
            error_message = (
                "Nodes, but no results found in frd file. "
                "It means there only is a mesh but no results in frd file. "
                "Usually this happens for: \n"
                "- analysis type 'NOANALYSIS'\n"
                "- if CalculiX returned no results "
                "(happens on nonpositive jacobian determinant in at least one element)\n"
                "- just no frd results where requestet in input file "
                "(neither 'node file' nor 'el file' in output section')\n")
            Console.PrintMessage(error_message)

        # create a result obj, even if we have no results but a result mesh in frd file
        # see error message above for more information
        if not res_obj:
            if result_name_prefix:
                results_name = ("{}_Results".format(result_name_prefix))
            else:
                results_name = ("Results".format(result_name_prefix))
            res_obj = ObjectsFem.makeResultMechanical(doc, results_name)
            res_obj.Mesh = result_mesh_object
            # TODO, node numbers in result obj could be set
            if analysis:
                analysis.addObject(res_obj)

        if FreeCAD.GuiUp:
            if analysis:
                import FemGui
                FemGui.setActiveAnalysis(analysis)
            doc.recompute()

    else:
        Console.PrintError(
            "Problem on frd file import. No nodes found in frd file.\n")
        # None will be returned
        # or would it be better to raise an exception if there are not even nodes in frd file

    return res_obj
Example #7
0
def write_fenics_mesh_codim_xdmf(fem_mesh_obj,
                                 topologynode,
                                 nodes_dict,
                                 codim=0,
                                 encoding=ENCODING_ASCII):
    mesh_dimension = get_FemMeshObjectDimension(fem_mesh_obj)

    element_types = get_FemMeshObjectElementTypes(
        fem_mesh_obj, remove_zero_element_entries=True)
    element_order = get_FemMeshObjectOrder(fem_mesh_obj)
    # we get all elements from mesh to decide which one to write by selection of codim
    """
    nodeindices = [(
        nodes_dict[ind] for ind in fem_mesh_obj.FemMesh.getElementNodes(fc_volume_ind)
    ) for (fen_ind, fc_volume_ind) in enumerate(fc_cells)]
    """
    writeout_element_dimension = mesh_dimension - codim

    (num_topo, name_topo, dim_topo) = (0, "", 0)
    for (num, name, dim) in element_types:
        if writeout_element_dimension == dim:
            (num_topo, name_topo, dim_topo) = (num, name, dim)

    (topology_type,
     nodes_per_element) = FreeCAD_to_Fenics_XDMF_dict[(name_topo,
                                                       element_order)]

    topologynode.set("TopologyType", topology_type)
    topologynode.set("NumberOfElements", str(num_topo))
    topologynode.set("NodesPerElement", str(nodes_per_element))

    if dim_topo == 3:
        fc_topo = fem_mesh_obj.FemMesh.Volumes
    elif dim_topo == 2:
        fc_topo = fem_mesh_obj.FemMesh.Faces
    elif dim_topo == 1:
        fc_topo = fem_mesh_obj.FemMesh.Edges
    elif dim_topo == 0:
        fc_topo = fem_mesh_obj.FemMesh.Nodes
    else:
        fc_topo = []
        Console.PrintError(
            "Dimension of mesh incompatible with export XDMF function: %d\n" %
            (dim_topo, ))

    nodeindices = [
        (nodes_dict[ind]
         for ind in fem_mesh_obj.FemMesh.getElementNodes(fc_topo_ind))
        for (fen_ind, fc_topo_ind) in enumerate(fc_topo)
    ]

    if encoding == ENCODING_ASCII:
        dataitem = ET.SubElement(topologynode,
                                 "DataItem",
                                 NumberType="UInt",
                                 Dimensions="%d %d" %
                                 (num_topo, nodes_per_element),
                                 Format="XML")
        dataitem.text = numpy_array_to_str(
            tuples_to_numpy(nodeindices, nodes_per_element))
    elif encoding == ENCODING_HDF5:
        pass

    return fc_topo
Example #8
0
    def get_boundary_layer_data(self):
        # mesh boundary layer
        # currently only one boundary layer setting object is allowed
        # but multiple boundary can be selected
        # Mesh.CharacteristicLengthMin, must be zero
        # or a value less than first inflation layer height
        if not self.mesh_obj.MeshBoundaryLayerList:
            # print("  No mesh boundary layer setting document object.")
            pass
        else:
            Console.PrintMessage(
                "  Mesh boundary layers, we need to get the elements.\n")
            if self.part_obj.Shape.ShapeType == "Compound":
                # see http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&start=40#p149467 and
                # http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&p=149520#p149520
                err = (
                    "Gmsh could return unexpected meshes for a boolean split tools Compound. "
                    "It is strongly recommended to extract the shape to mesh "
                    "from the Compound and use this one.")
                Console.PrintError(err + "\n")
            for mr_obj in self.mesh_obj.MeshBoundaryLayerList:
                if mr_obj.MinimumThickness and Units.Quantity(
                        mr_obj.MinimumThickness).Value > 0:
                    if mr_obj.References:
                        belem_list = []
                        for sub in mr_obj.References:
                            # print(sub[0])  # Part the elements belongs to
                            # check if the shape of the mesh boundary_layer is an
                            # element of the Part to mesh
                            # if not try to find the element in the shape to mesh
                            search_ele_in_shape_to_mesh = False
                            if not self.part_obj.Shape.isSame(sub[0].Shape):
                                Console.PrintLog(
                                    "  One element of the mesh boundary layer {} is "
                                    "not an element of the Part to mesh.\n"
                                    "But we are going to try to find it in "
                                    "the Shape to mesh :-)\n".format(
                                        mr_obj.Name))
                                search_ele_in_shape_to_mesh = True
                            for elems in sub[1]:
                                # print(elems)  # elems --> element
                                if search_ele_in_shape_to_mesh:
                                    # we try to find the element it in the Shape to mesh
                                    # and use the found element as elems
                                    # the method getElement(element) does not return Solid elements
                                    ele_shape = geomtools.get_element(
                                        sub[0], elems)
                                    found_element = geomtools.find_element_in_shape(
                                        self.part_obj.Shape, ele_shape)
                                    if found_element:  # also
                                        elems = found_element
                                    else:
                                        Console.PrintError(
                                            "One element of the mesh boundary layer {} could "
                                            "not be found in the Part to mesh. "
                                            "It will be ignored.\n".format(
                                                mr_obj.Name))
                                # print(elems)  # element
                                if elems not in self.bl_boundary_list:
                                    # fetch settings in DocumentObject
                                    # fan setting is not implemented
                                    belem_list.append(elems)
                                    self.bl_boundary_list.append(elems)
                                else:
                                    Console.PrintError(
                                        "The element {} of the mesh boundary "
                                        "layer {} has been added "
                                        "to another mesh boundary layer.\n".
                                        format(elems, mr_obj.Name))
                        setting = {}
                        setting["hwall_n"] = Units.Quantity(
                            mr_obj.MinimumThickness).Value
                        setting["ratio"] = mr_obj.GrowthRate
                        setting["thickness"] = sum([
                            setting["hwall_n"] * setting["ratio"]**i
                            for i in range(mr_obj.NumberOfLayers)
                        ])
                        # setting["hwall_n"] * 5 # tangential cell dimension
                        setting["hwall_t"] = setting["thickness"]

                        # hfar: cell dimension outside boundary
                        # should be set later if some character length is set
                        if self.clmax > setting["thickness"] * 0.8 \
                                and self.clmax < setting["thickness"] * 1.6:
                            setting["hfar"] = self.clmax
                        else:
                            # set a value for safety, it may works as background mesh cell size
                            setting["hfar"] = setting["thickness"]
                        # from face name -> face id is done in geo file write up
                        # TODO: fan angle setup is not implemented yet
                        if self.dimension == "2":
                            setting["EdgesList"] = belem_list
                        elif self.dimension == "3":
                            setting["FacesList"] = belem_list
                        else:
                            Console.PrintError(
                                "boundary layer is only supported for 2D and 3D mesh.\n"
                            )
                        self.bl_setting_list.append(setting)
                    else:
                        Console.PrintError(
                            "The mesh boundary layer: {} is not used to create "
                            "the mesh because the reference list is empty.\n".
                            format(mr_obj.Name))
                else:
                    Console.PrintError(
                        "The mesh boundary layer: {} is not used to create "
                        "the mesh because the min thickness is 0.0 mm.\n".
                        format(mr_obj.Name))
            Console.PrintMessage("  {}\n".format(self.bl_setting_list))
Example #9
0
def read_frd_result(frd_input):
    Console.PrintMessage(
        "Read ccx results from frd file: {}\n".format(frd_input))
    inout_nodes = []
    inout_nodes_file = frd_input.rsplit(".", 1)[0] + "_inout_nodes.txt"
    if os.path.exists(inout_nodes_file):
        Console.PrintMessage(
            "Read special 1DFlow nodes data form: {}\n".format(
                inout_nodes_file))
        f = pyopen(inout_nodes_file, "r")
        lines = f.readlines()
        for line in lines:
            a = line.split(",")
            inout_nodes.append(a)
        f.close()
        Console.PrintMessage("{}\n".format(inout_nodes))
    frd_file = pyopen(frd_input, "r")
    nodes = {}
    elements_hexa8 = {}
    elements_penta6 = {}
    elements_tetra4 = {}
    elements_tetra10 = {}
    elements_penta15 = {}
    elements_hexa20 = {}
    elements_tria3 = {}
    elements_tria6 = {}
    elements_quad4 = {}
    elements_quad8 = {}
    elements_seg2 = {}
    elements_seg3 = {}
    results = []
    mode_results = {}
    mode_results["number"] = float("NaN")
    mode_results["time"] = float("NaN")
    mode_disp = {}
    mode_stress = {}
    mode_strain = {}
    mode_peeq = {}
    mode_temp = {}
    mode_massflow = {}
    mode_networkpressure = {}

    nodes_found = False
    elements_found = False
    mode_time_found = False
    mode_disp_found = False
    mode_stress_found = False
    mode_strain_found = False
    mode_peeq_found = False
    mode_temp_found = False
    mode_massflow_found = False
    mode_networkpressure_found = False
    end_of_section_found = False
    end_of_frd_data_found = False
    input_continues = False
    mode_eigen_changed = False
    mode_time_changed = False

    eigenmode = 0
    eigentemp = 0
    elem = -1
    elemType = 0
    timestep = 0
    timetemp = 0

    for line in frd_file:

        # Check if we found nodes section
        if line[4:6] == "2C":
            nodes_found = True
        if nodes_found and (line[1:3] == "-1"):
            # we found a nodes line, lets extract the node and coordinate data
            elem = int(line[4:13])
            nodes_x = float(line[13:25])
            nodes_y = float(line[25:37])
            nodes_z = float(line[37:49])
            nodes[elem] = FreeCAD.Vector(nodes_x, nodes_y, nodes_z)

        # Check if we found elements section
        if line[4:6] == "3C":
            elements_found = True
        if elements_found and (line[1:3] == "-1"):
            # we found a first element line, lets extract element number
            elem = int(line[4:13])
            elemType = int(line[14:18])
        if elements_found and (line[1:3] == "-2"):
            # we found a second element line, lets extract the elements
            # node order fits with node order in writeAbaqus() in FemMesh.cpp
            if elemType == 1:
                # C3D8 CalculiX --> hexa8 FreeCAD
                # N6, N7, N8, N5, N2, N3, N4, N1
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                nd4 = int(line[33:43])
                nd5 = int(line[43:53])
                nd6 = int(line[53:63])
                nd7 = int(line[63:73])
                nd8 = int(line[73:83])
                elements_hexa8[elem] = (nd6, nd7, nd8, nd5, nd2, nd3, nd4, nd1)
            elif elemType == 2:
                # C3D6 Calculix --> penta6 FreeCAD
                # N5, N6, N4, N2, N3, N1
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                nd4 = int(line[33:43])
                nd5 = int(line[43:53])
                nd6 = int(line[53:63])
                elements_penta6[elem] = (nd5, nd6, nd4, nd2, nd3, nd1)
            elif elemType == 3:
                # C3D4 Calculix --> tetra4 FreeCAD
                # N2, N1, N3, N4
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                nd4 = int(line[33:43])
                elements_tetra4[elem] = (nd2, nd1, nd3, nd4)
            elif elemType == 4 and input_continues is False:
                # first line
                # C3D20 Calculix --> hexa20 FreeCAD
                # N6, N7, N8, N5, N2, N3, N4, N1, N14, N15
                # N16, N13, N10, N11, N12, N9, N18, N19, N20, N17
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                nd4 = int(line[33:43])
                nd5 = int(line[43:53])
                nd6 = int(line[53:63])
                nd7 = int(line[63:73])
                nd8 = int(line[73:83])
                nd9 = int(line[83:93])
                nd10 = int(line[93:103])
                input_continues = True
            elif elemType == 4 and input_continues is True:
                # second line
                nd11 = int(line[3:13])
                nd12 = int(line[13:23])
                nd13 = int(line[23:33])
                nd14 = int(line[33:43])
                nd15 = int(line[43:53])
                nd16 = int(line[53:63])
                nd17 = int(line[63:73])
                nd18 = int(line[73:83])
                nd19 = int(line[83:93])
                nd20 = int(line[93:103])
                input_continues = False
                """
                CalculiX uses a different node order in
                input file *.inp and result file *.frd for hexa20 (C3D20)
                according to Guido (the developer of ccx):
                see note in in first line of cgx manuel part element types
                ccx (and thus the *.inp) follows the ABAQUS convention
                documented in the ccx-documentation
                cgx (and thus the *.frd) follows the FAM2 convention
                documented in the cgx-documentation
                FAM32 is from the company FEGS limited
                maybe this company does not exist any more
                elements_hexa20[elem] = (
                    nd6, nd7, nd8, nd5, nd2, nd3, nd4, nd1, nd14, nd15,
                    nd16, nd13, nd10, nd11, nd12, nd9, nd18, nd19, nd20, nd17
                )
                elements_hexa20[elem] = (
                    nd6, nd7, nd8, nd5, nd2, nd3, nd4, nd1, nd14, nd15,
                    nd16, nd13, nd18, nd19, nd20, nd17, nd10, nd11, nd12, nd9
                )
                hexa20 import works with the following frd file node assignment
                """
                elements_hexa20[elem] = (nd8, nd5, nd6, nd7, nd4, nd1, nd2,
                                         nd3, nd20, nd17, nd18, nd19, nd12,
                                         nd9, nd10, nd11, nd16, nd13, nd14,
                                         nd15)
            elif elemType == 5 and input_continues is False:
                # first line
                # C3D15 Calculix --> penta15 FreeCAD
                # N5, N6, N4, N2, N3, N1, N11, N12, N10, N8, N9, N7, N14, N15, N13
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                nd4 = int(line[33:43])
                nd5 = int(line[43:53])
                nd6 = int(line[53:63])
                nd7 = int(line[63:73])
                nd8 = int(line[73:83])
                nd9 = int(line[83:93])
                nd10 = int(line[93:103])
                input_continues = True
            elif elemType == 5 and input_continues is True:
                # second line
                nd11 = int(line[3:13])
                nd12 = int(line[13:23])
                nd13 = int(line[23:33])
                nd14 = int(line[33:43])
                nd15 = int(line[43:53])
                input_continues = False
                """
                CalculiX uses a different node order in
                input file *.inp and result file *.frd for penta15 (C3D15)
                see notes at hexa20
                elements_penta15[elem] = (
                    nd5, nd6, nd4, nd2, nd3, nd1, nd11, nd12, nd10, nd8,
                    nd9, nd7, nd14, nd15, nd13
                )  # order of the *.inp file
                """
                elements_penta15[elem] = (nd5, nd6, nd4, nd2, nd3, nd1, nd14,
                                          nd15, nd13, nd8, nd9, nd7, nd11,
                                          nd12, nd10)
            elif elemType == 6:
                # C3D10 Calculix --> tetra10 FreeCAD
                # N2, N1, N3, N4, N5, N7, N6, N9, N8, N10
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                nd4 = int(line[33:43])
                nd5 = int(line[43:53])
                nd6 = int(line[53:63])
                nd7 = int(line[63:73])
                nd8 = int(line[73:83])
                nd9 = int(line[83:93])
                nd10 = int(line[93:103])
                elements_tetra10[elem] = (nd2, nd1, nd3, nd4, nd5, nd7, nd6,
                                          nd9, nd8, nd10)
            elif elemType == 7:
                # S3 Calculix --> tria3 FreeCAD
                # N1, N2, N3
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                elements_tria3[elem] = (nd1, nd2, nd3)
            elif elemType == 8:
                # S6 CalculiX --> tria6 FreeCAD
                # N1, N2, N3, N4, N5, N6
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                nd4 = int(line[33:43])
                nd5 = int(line[43:53])
                nd6 = int(line[53:63])
                elements_tria6[elem] = (nd1, nd2, nd3, nd4, nd5, nd6)
            elif elemType == 9:
                # S4 CalculiX --> quad4 FreeCAD
                # N1, N2, N3, N4
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                nd4 = int(line[33:43])
                elements_quad4[elem] = (nd1, nd2, nd3, nd4)
            elif elemType == 10:
                # S8 CalculiX --> quad8 FreeCAD
                # N1, N2, N3, N4, N5, N6, N7, N8
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                nd4 = int(line[33:43])
                nd5 = int(line[43:53])
                nd6 = int(line[53:63])
                nd7 = int(line[63:73])
                nd8 = int(line[73:83])
                elements_quad8[elem] = (nd1, nd2, nd3, nd4, nd5, nd6, nd7, nd8)
            elif elemType == 11:
                # B31 CalculiX --> seg2 FreeCAD
                # N1, N2
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                elements_seg2[elem] = (nd1, nd2)
            elif elemType == 12:
                # B32 CalculiX --> seg3 FreeCAD
                # Also D element element number
                # CalculiX uses a different node order in
                # input file *.inp and result file *.frd for seg3 (B32)
                # see notes at hexa20
                # N1, N2 ,N3
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                if inout_nodes:
                    for i in range(len(inout_nodes)):
                        if nd1 == int(inout_nodes[i][1]):
                            # fluid inlet node numbering
                            elements_seg3[elem] = (int(inout_nodes[i][2]), nd3,
                                                   nd1)
                        elif nd3 == int(inout_nodes[i][1]):
                            # fluid outlet node numbering
                            elements_seg3[elem] = (nd1, int(inout_nodes[i][2]),
                                                   nd3)
                else:
                    # normal node numbering for D, B32 elements
                    elements_seg3[elem] = (nd1, nd2, nd3)

        # Check if we found new eigenmode line
        if line[5:10] == "PMODE":
            eigentemp = int(line[30:36])
            if eigentemp > eigenmode:
                eigenmode = eigentemp
                mode_eigen_changed = True

        # Check if we found new time step
        if line[4:10] == "1PSTEP":
            mode_time_found = True
        if mode_time_found and (line[2:7] == "100CL"):
            # we found the new time step line
            # !!! be careful here, there is timetemp and timestep!
            # TODO: use more differ names
            timetemp = float(line[13:25])
            if timetemp > timestep:
                timestep = timetemp
                mode_time_changed = True

        # Check if we found displacement section
        if line[5:9] == "DISP":
            mode_disp_found = True
        if mode_disp_found and (line[1:3] == "-1"):
            # we found a displacement line
            elem = int(line[4:13])
            mode_disp_x = float(line[13:25])
            mode_disp_y = float(line[25:37])
            mode_disp_z = float(line[37:49])
            mode_disp[elem] = FreeCAD.Vector(mode_disp_x, mode_disp_y,
                                             mode_disp_z)

        # Check if we found stress section
        if line[5:11] == "STRESS":
            mode_stress_found = True
        if mode_stress_found and (line[1:3] == "-1"):
            # we found a stress line
            elem = int(line[4:13])
            stress_1 = float(line[13:25])
            stress_2 = float(line[25:37])
            stress_3 = float(line[37:49])
            stress_4 = float(line[49:61])
            stress_5 = float(line[61:73])
            stress_6 = float(line[73:85])
            # CalculiX frd files: (Sxx, Syy, Szz, Sxy, Syz, Szx)
            # FreeCAD:            (Sxx, Syy, Szz, Sxy, Sxz, Syz)
            # thus exchange the last two entries
            mode_stress[elem] = (stress_1, stress_2, stress_3, stress_4,
                                 stress_6, stress_5)

        # Check if we found strain section
        if line[5:13] == "TOSTRAIN":
            mode_strain_found = True
        if mode_strain_found and (line[1:3] == "-1"):
            # we found a strain line in the frd file
            elem = int(line[4:13])
            strain_1 = float(line[13:25])
            strain_2 = float(line[25:37])
            strain_3 = float(line[37:49])
            strain_4 = float(line[49:61])
            strain_5 = float(line[61:73])
            strain_6 = float(line[73:85])
            # CalculiX frd files: (Exx, Eyy, Ezz, Exy, Eyz, Ezx)
            # FreeCAD:            (Exx, Eyy, Ezz, Exy, Exz, Eyz)
            # thus exchange the last two entries
            mode_strain[elem] = (strain_1, strain_2, strain_3, strain_4,
                                 strain_6, strain_5)

        # Check if we found an equivalent plastic strain section
        if line[5:7] == "PE":
            mode_peeq_found = True
        if mode_peeq_found and (line[1:3] == "-1"):
            # we found an equivalent plastic strain line
            elem = int(line[4:13])
            peeq = float(line[13:25])
            mode_peeq[elem] = (peeq)

        # Check if we found a temperature section
        if line[5:11] == "NDTEMP":
            mode_temp_found = True
        if mode_temp_found and (line[1:3] == "-1"):
            # we found a temperature line
            elem = int(line[4:13])
            temperature = float(line[13:25])
            mode_temp[elem] = (temperature)

        # Check if we found a mass flow section
        if line[5:11] == "MAFLOW":
            mode_massflow_found = True
        if mode_massflow_found and (line[1:3] == "-1"):
            # we found a mass flow line
            elem = int(line[4:13])
            massflow = float(line[13:25])
            mode_massflow[elem] = (massflow * 1000
                                   )  # convert units to kg/s from t/s
            if inout_nodes:
                for i in range(len(inout_nodes)):
                    if elem == int(inout_nodes[i][1]):
                        node = int(inout_nodes[i][2])
                        # convert units to kg/s from t/s
                        mode_massflow[node] = (massflow * 1000)

        # Check if we found a network pressure section
        if line[5:11] == "STPRES":
            mode_networkpressure_found = True
        if mode_networkpressure_found and (line[1:3] == "-1"):
            # we found a network pressure line
            elem = int(line[4:13])
            networkpressure = float(line[13:25])
            mode_networkpressure[elem] = (networkpressure)
            if inout_nodes:
                for i in range(len(inout_nodes)):
                    if elem == int(inout_nodes[i][1]):
                        node = int(inout_nodes[i][2])
                        mode_networkpressure[node] = (networkpressure)

        # Check if we found the end of a section
        if line[1:3] == "-3":
            end_of_section_found = True

            if nodes_found:
                nodes_found = False
                node_element_section = True

            if elements_found:
                elements_found = False
                node_element_section = True

            if mode_disp_found:
                mode_results["disp"] = mode_disp
                mode_disp = {}
                mode_disp_found = False
                node_element_section = False

            if mode_stress_found:
                mode_results["stress"] = mode_stress
                mode_stress = {}
                mode_stress_found = False
                node_element_section = False

            if mode_strain_found:
                mode_results["strain"] = mode_strain

                mode_strain = {}
                mode_strain_found = False
                node_element_section = False

            if mode_peeq_found:
                mode_results["peeq"] = mode_peeq
                mode_peeq = {}
                mode_peeq_found = False
                node_element_section = False

            if mode_temp_found:
                mode_results["temp"] = mode_temp
                mode_temp = {}
                mode_temp_found = False
                node_element_section = False

            if mode_massflow_found:
                mode_results["mflow"] = mode_massflow
                mode_massflow = {}
                mode_massflow_found = False
                node_element_section = False

            if mode_networkpressure_found:
                mode_results["npressure"] = mode_networkpressure
                mode_networkpressure_found = False
                mode_networkpressure = {}
                node_element_section = False
            """
            print("---- End of Section --> Mode_Results may be changed ----")
            for key in sorted(mode_results.keys()):
                if key is "number" or key is "time":
                    print(key + " --> " + str(mode_results[key]))
                else:
                    print(key + " --> " + str(len(mode_results[key])))
            print("----Mode_Results----\n")
            """

        # Check if we found the end of frd data
        if line[1:5] == "9999":
            end_of_frd_data_found = True

        if (mode_eigen_changed or mode_time_changed or end_of_frd_data_found) \
                and end_of_section_found \
                and not node_element_section:
            """
            print("\n\n----Append mode_results to results")
            print(line)
            for key in sorted(mode_results.keys()):
                if key is "number" or key is "time":
                    print(key + " --> " + str(mode_results[key]))
                else:
                    print(key + " --> " + str(len(mode_results[key])))
            print("----Append Mode_Results----\n")
            """

            # append mode_results to results and reset mode_result
            results.append(mode_results)
            mode_results = {}
            # https://forum.freecadweb.org/viewtopic.php?f=18&t=32649&start=10#p274686
            mode_results["number"] = float("NaN")
            mode_results["time"] = float("NaN")
            end_of_section_found = False

        # on changed --> write changed values in mode_result
        # will be the first to do on an empty mode_result
        if mode_eigen_changed:
            mode_results["number"] = eigenmode
            mode_eigen_changed = False

        if mode_time_changed:
            mode_results["time"] = timestep
            # mode_results["time"] = 0  # Don't return time if static  # Why?
            mode_time_found = False
            mode_time_changed = False

        # here we are in the indent of loop for every line in frd file
        # do not add a print here :-)

    # close frd file if loop over all lines is finished
    frd_file.close()
    """
    # debug prints and checks with the read data
    print("\n\n----RESULTS values begin----")
    print(len(results))
    # print("\n")
    # print(results)
    print("----RESULTS values end----\n\n")
    """

    if not inout_nodes:
        if results:
            if "mflow" in results[0] or "npressure" in results[0]:
                Console.PrintError(
                    "We have mflow or npressure, but no inout_nodes file.\n")
    if not nodes:
        Console.PrintError("FEM: No nodes found in Frd file.\n")

    return {
        "Nodes": nodes,
        "Seg2Elem": elements_seg2,
        "Seg3Elem": elements_seg3,
        "Tria3Elem": elements_tria3,
        "Tria6Elem": elements_tria6,
        "Quad4Elem": elements_quad4,
        "Quad8Elem": elements_quad8,
        "Tetra4Elem": elements_tetra4,
        "Tetra10Elem": elements_tetra10,
        "Hexa8Elem": elements_hexa8,
        "Hexa20Elem": elements_hexa20,
        "Penta6Elem": elements_penta6,
        "Penta15Elem": elements_penta15,
        "Results": results
    }
Example #10
0
 def get_region_data(self):
     # mesh regions
     if not self.mesh_obj.MeshRegionList:
         # print("  No mesh regions.")
         pass
     else:
         Console.PrintMessage(
             "  Mesh regions, we need to get the elements.\n")
         # by the use of MeshRegion object and a BooleanSplitCompound
         # there could be problems with node numbers see
         # http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&start=40#p149467
         # http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&p=149520#p149520
         part = self.part_obj
         if (self.mesh_obj.MeshRegionList
                 and part.Shape.ShapeType == "Compound"
                 and (femutils.is_of_type(part, "FeatureBooleanFragments")
                      or femutils.is_of_type(part, "FeatureSlice")
                      or femutils.is_of_type(part, "FeatureXOR"))):
             error_message = (
                 "  The mesh to shape is a boolean split tools Compound "
                 "and the mesh has mesh region list. "
                 "Gmsh could return unexpected meshes in such circumstances. "
                 "It is strongly recommended to extract the shape to mesh "
                 "from the Compound and use this one.")
             Console.PrintError(error_message + "\n")
             # TODO: no gui popup because FreeCAD will be in a endless output loop
             #       as long as the pop up is on --> maybe find a better solution for
             #       either of both --> thus the pop up is in task panel
         for mr_obj in self.mesh_obj.MeshRegionList:
             # print(mr_obj.Name)
             # print(mr_obj.CharacteristicLength)
             # print(Units.Quantity(mr_obj.CharacteristicLength).Value)
             if mr_obj.CharacteristicLength:
                 if mr_obj.References:
                     for sub in mr_obj.References:
                         # print(sub[0])  # Part the elements belongs to
                         # check if the shape of the mesh region
                         # is an element of the Part to mesh
                         # if not try to find the element in the shape to mesh
                         search_ele_in_shape_to_mesh = False
                         if not self.part_obj.Shape.isSame(sub[0].Shape):
                             Console.PrintLog(
                                 "  One element of the meshregion {} is "
                                 "not an element of the Part to mesh.\n"
                                 "But we are going to try to find it in "
                                 "the Shape to mesh :-)\n".format(
                                     mr_obj.Name))
                             search_ele_in_shape_to_mesh = True
                         for elems in sub[1]:
                             # print(elems)  # elems --> element
                             if search_ele_in_shape_to_mesh:
                                 # we're going to try to find the element in the
                                 # Shape to mesh and use the found element as elems
                                 # the method getElement(element)
                                 # does not return Solid elements
                                 ele_shape = geomtools.get_element(
                                     sub[0], elems)
                                 found_element = geomtools.find_element_in_shape(
                                     self.part_obj.Shape, ele_shape)
                                 if found_element:
                                     elems = found_element
                                 else:
                                     Console.PrintError(
                                         "One element of the meshregion {} could not be found "
                                         "in the Part to mesh. It will be ignored.\n"
                                         .format(mr_obj.Name))
                             # print(elems)  # element
                             if elems not in self.ele_length_map:
                                 self.ele_length_map[
                                     elems] = Units.Quantity(
                                         mr_obj.CharacteristicLength).Value
                             else:
                                 Console.PrintError(
                                     "The element {} of the meshregion {} has "
                                     "been added to another mesh region.\n".
                                     format(elems, mr_obj.Name))
                 else:
                     Console.PrintError(
                         "The meshregion: {} is not used to create the mesh "
                         "because the reference list is empty.\n".format(
                             mr_obj.Name))
             else:
                 Console.PrintError(
                     "The meshregion: {} is not used to create the "
                     "mesh because the CharacteristicLength is 0.0 mm.\n".
                     format(mr_obj.Name))
         for eleml in self.ele_length_map:
             # the method getElement(element) does not return Solid elements
             ele_shape = geomtools.get_element(self.part_obj, eleml)
             ele_vertexes = geomtools.get_vertexes_by_element(
                 self.part_obj.Shape, ele_shape)
             self.ele_node_map[eleml] = ele_vertexes
         Console.PrintMessage("  {}\n".format(self.ele_length_map))
         Console.PrintMessage("  {}\n".format(self.ele_node_map))
Example #11
0
    def __init__(self, gmsh_mesh_obj, analysis=None):

        # mesh obj
        self.mesh_obj = gmsh_mesh_obj

        # analysis
        if analysis:
            self.analysis = analysis
        else:
            self.analysis = None

        # part to mesh
        self.part_obj = self.mesh_obj.Part

        # clmax, CharacteristicLengthMax: float, 0.0 = 1e+22
        self.clmax = Units.Quantity(
            self.mesh_obj.CharacteristicLengthMax).Value
        if self.clmax == 0.0:
            self.clmax = 1e+22

        # clmin, CharacteristicLengthMin: float
        self.clmin = Units.Quantity(
            self.mesh_obj.CharacteristicLengthMin).Value

        # geotol, GeometryTolerance: float, 0.0 = 1e-08
        self.geotol = self.mesh_obj.GeometryTolerance
        if self.geotol == 0.0:
            self.geotol = 1e-08

        # order
        # known_element_orders = ["1st", "2nd"]
        self.order = self.mesh_obj.ElementOrder
        if self.order == "1st":
            self.order = "1"
        elif self.order == "2nd":
            self.order = "2"
        else:
            Console.PrintError("Error in order\n")

        # dimension
        self.dimension = self.mesh_obj.ElementDimension

        # Algorithm2D
        algo2D = self.mesh_obj.Algorithm2D
        if algo2D == "Automatic":
            self.algorithm2D = "2"
        elif algo2D == "MeshAdapt":
            self.algorithm2D = "1"
        elif algo2D == "Delaunay":
            self.algorithm2D = "5"
        elif algo2D == "Frontal":
            self.algorithm2D = "6"
        elif algo2D == "BAMG":
            self.algorithm2D = "7"
        elif algo2D == "DelQuad":
            self.algorithm2D = "8"
        elif algo2D == "Packing Parallelograms":
            self.algorithm2D = "9"
        else:
            self.algorithm2D = "2"

        # Algorithm3D
        algo3D = self.mesh_obj.Algorithm3D
        if algo3D == "Automatic":
            self.algorithm3D = "1"
        elif algo3D == "Delaunay":
            self.algorithm3D = "1"
        elif algo3D == "New Delaunay":
            self.algorithm3D = "2"
        elif algo3D == "Frontal":
            self.algorithm3D = "4"
        elif algo3D == "MMG3D":
            self.algorithm3D = "7"
        elif algo3D == "R-tree":
            self.algorithm3D = "9"
        elif algo3D == "HXT":
            self.algorithm3D = "10"
        else:
            self.algorithm3D = "1"

        # RecombinationAlgorithm
        algoRecombo = self.mesh_obj.RecombinationAlgorithm
        if algoRecombo == "Simple":
            self.RecombinationAlgorithm = "0"
        elif algoRecombo == "Blossom":
            self.RecombinationAlgorithm = "1"
        elif algoRecombo == "Simple full-quad":
            self.RecombinationAlgorithm = "2"
        elif algoRecombo == "Blossom full-quad":
            self.RecombinationAlgorithm = "3"
        else:
            self.algoRecombo = "0"

        # HighOrderOptimize
        optimizers = self.mesh_obj.HighOrderOptimize
        if optimizers == "None":
            self.HighOrderOptimize = "0"
        elif optimizers == "Optimization":
            self.HighOrderOptimize = "1"
        elif optimizers == "Elastic+Optimization":
            self.HighOrderOptimize = "2"
        elif optimizers == "Elastic":
            self.HighOrderOptimize = "3"
        elif optimizers == "Fast Curving":
            self.HighOrderOptimize = "4"
        else:
            self.HighOrderOptimize = "0"

        # mesh groups
        if self.mesh_obj.GroupsOfNodes is True:
            self.group_nodes_export = True
        else:
            self.group_nodes_export = False
        self.group_elements = {}

        # mesh regions
        self.ele_length_map = {}  # { "ElementString" : element length }
        self.ele_node_map = {}  # { "ElementString" : [element nodes] }

        # mesh boundary layer
        self.bl_setting_list = [
        ]  # list of dict, each item map to MeshBoundaryLayer object
        self.bl_boundary_list = [
        ]  # to remove duplicated boundary edge or faces

        # other initializations
        self.temp_file_geometry = ""
        self.temp_file_mesh = ""
        self.temp_file_geo = ""
        self.mesh_name = ""
        self.gmsh_bin = ""
        self.error = False
def importFrame3DDCase(filename, analysis=None, result_name_prefix=""):
    from . import importToolsFem
    import ObjectsFem

    m = read_Frame3DD_case(filename)
    result_mesh_object = None
    if len(m["Nodes"]) > 0:
        mesh = importToolsFem.make_femmesh(m)
        result_mesh_object = ObjectsFem.makeMeshResult(FreeCAD.ActiveDocument,
                                                       "ResultMesh")
        result_mesh_object.FemMesh = mesh
        res_mesh_is_compacted = False
        nodenumbers_for_compacted_mesh = []

        number_of_increments = len(m["Results"])
        Console.PrintLog("Increments: " + str(number_of_increments) + "\n")
        if len(m["Results"]) > 0:
            for result_set in m["Results"]:
                if "number" in result_set:
                    eigenmode_number = result_set["number"]
                else:
                    eigenmode_number = 0
                step_time = result_set["time"]
                step_time = round(step_time, 2)
                if eigenmode_number > 0:
                    results_name = ("{}Mode{}_Results".format(
                        result_name_prefix, eigenmode_number))
                elif number_of_increments > 1:
                    results_name = ("{}Time{}_Results".format(
                        result_name_prefix, step_time))
                else:
                    results_name = ("{}Results".format(result_name_prefix))

                res_obj = ObjectsFem.makeResultMechanical(
                    FreeCAD.ActiveDocument, results_name)
                res_obj.Mesh = result_mesh_object
                res_obj = importToolsFem.fill_femresult_mechanical(
                    res_obj, result_set)
                if analysis:
                    analysis.addObject(res_obj)

                # complementary result object calculations
                import femresult.resulttools as restools
                import femtools.femutils as femutils
                if not res_obj.MassFlowRate:
                    # information 1:
                    # only compact result if not Flow 1D results
                    # compact result object, workaround for bug 2873
                    # https://www.freecadweb.org/tracker/view.php?id=2873
                    # information 2:
                    # if the result data has multiple result sets there will be multiple result objs
                    # they all will use one mesh obj
                    # on the first res obj fill the mesh obj will be compacted, thus
                    # it does not need to be compacted on further result sets
                    # but NodeNumbers need to be compacted for every result set (res object fill)
                    # example Frame3DD file: https://forum.freecadweb.org/viewtopic.php?t=32649#p274291
                    if res_mesh_is_compacted is False:
                        # first result set, compact FemMesh and NodeNumbers
                        res_obj = restools.compact_result(res_obj)
                        res_mesh_is_compacted = True
                        nodenumbers_for_compacted_mesh = res_obj.NodeNumbers
                    else:
                        # all other result sets, do not compact FemMesh, only set NodeNumbers
                        res_obj.NodeNumbers = nodenumbers_for_compacted_mesh

                # fill DisplacementLengths
                res_obj = restools.add_disp_apps(res_obj)
                # fill StressValues
                res_obj = restools.add_von_mises(res_obj)
                if res_obj.getParentGroup():
                    has_reinforced_mat = False
                    for obj in res_obj.getParentGroup().Group:
                        if obj.isDerivedFrom("App::MaterialObjectPython") \
                                and femutils.is_of_type(obj, "Fem::MaterialReinforced"):
                            has_reinforced_mat = True
                            restools.add_principal_stress_reinforced(res_obj)
                            break
                    if has_reinforced_mat is False:
                        # fill PrincipalMax, PrincipalMed, PrincipalMin, MaxShear
                        res_obj = restools.add_principal_stress_std(res_obj)
                else:
                    # if a pure Frame3DD file was opened no analysis and thus no parent group
                    # fill PrincipalMax, PrincipalMed, PrincipalMin, MaxShear
                    res_obj = restools.add_principal_stress_std(res_obj)
                # fill Stats
                res_obj = restools.fill_femresult_stats(res_obj)
                return res_obj

        else:
            error_message = (
                "We have nodes but no results in Frame3DD file, "
                "which means we only have a mesh in Frame3DD file. "
                "Usually this happens for analysis type 'NOANALYSIS' "
                "or if Frame3DD returned no results because "
                "of nonpositive jacobian determinant in at least one element.\n"
            )
            Console.PrintMessage(error_message)
            if analysis:
                analysis.addObject(result_mesh_object)

        if FreeCAD.GuiUp:
            if analysis:
                import FemGui
                FemGui.setActiveAnalysis(analysis)
            FreeCAD.ActiveDocument.recompute()

    else:
        Console.PrintError(
            "Problem on Frame3DD file import. No nodes found in Frame3DD file.\n"
        )
def read_Frame3DD_case(Frame3DD_input):
    Console.PrintMessage(
        "Read Frame3DD results from Frame3DD file: {}\n".format(
            Frame3DD_input))
    inout_nodes = []
    inout_nodes_file = Frame3DD_input.rsplit(".", 1)[0] + "_inout_nodes.txt"
    if os.path.exists(inout_nodes_file):
        Console.PrintMessage(
            "Read special 1DFlow nodes data form: {}\n".format(
                inout_nodes_file))
        f = pyopen(inout_nodes_file, "r")
        lines = f.readlines()
        for line in lines:
            a = line.split(",")
            inout_nodes.append(a)
        f.close()
        Console.PrintMessage("{}\n".format(inout_nodes))
    Frame3DD_file = pyopen(Frame3DD_input, "r")
    nodes = {}
    elements_hexa8 = {}
    elements_penta6 = {}
    elements_tetra4 = {}
    elements_tetra10 = {}
    elements_penta15 = {}
    elements_hexa20 = {}
    elements_tria3 = {}
    elements_tria6 = {}
    elements_quad4 = {}
    elements_quad8 = {}
    elements_seg2 = {}
    elements_seg3 = {}
    results = []
    mode_results = {}
    mode_results["number"] = float("NaN")
    mode_results["time"] = float("NaN")
    mode_disp = {}
    mode_stress = {}
    mode_strain = {}
    mode_peeq = {}
    mode_temp = {}
    mode_massflow = {}
    mode_networkpressure = {}

    nodes_found = False
    elements_found = False
    mode_time_found = False
    mode_disp_found = False
    mode_stress_found = False
    mode_strain_found = False
    mode_peeq_found = False
    mode_temp_found = False
    mode_massflow_found = False
    mode_networkpressure_found = False
    end_of_section_found = False
    end_of_Frame3DD_data_found = False
    input_continues = False
    mode_eigen_changed = False
    mode_time_changed = False

    eigenmode = 0
    eigentemp = 0
    elem = -1
    elemType = 0
    timestep = 0
    timetemp = 0

    tline = []
    for line in Frame3DD_file:
        tline.append(line.strip())

    i = 1
    #Console.PrintError(tline[i]+'\n')

    #node 1111111111111111111111111111111111111111111111111111111
    while 1:
        i = i + 1
        #print (tline[i])
        if len(tline[i]) == 0 or tline[i][0] == '#':
            continue
        else:
            break

    print("")
    data = tline[i].split()
    numNode = int(data[0])
    print("numNode: " + str(numNode))

    while 1:
        i = i + 1
        #print (tline[i])
        if len(tline[i]) == 0 or tline[i][0] == '#':
            continue
        else:
            break

    print(tline[i])
    dataNode = tline[i].split()

    elem = int(dataNode[0])
    nodes_x = float(dataNode[1])
    nodes_y = float(dataNode[2])
    nodes_z = float(dataNode[3])
    nodes[elem] = FreeCAD.Vector(nodes_x, nodes_y, nodes_z)

    for id in range(1, numNode):  # node
        #1       0.000000       0.000000       0.000000    0.000   1  1  1  1  1  0
        while 1:
            i = i + 1
            #print (tline[i])
            if len(tline[i]) == 0 or tline[i][0] == '#':
                continue
            else:
                break
        print(tline[i])
        dataNode = tline[i].split()

        elem = int(dataNode[0])
        nodes_x = float(dataNode[1])
        nodes_y = float(dataNode[2])
        nodes_z = float(dataNode[3])
        nodes[elem] = FreeCAD.Vector(nodes_x, nodes_y, nodes_z)

    #number of nodes with reactions 22222222222222222222222222222222222222222
    while 1:
        i = i + 1
        #print (tline[i])
        if len(tline[i]) == 0 or tline[i][0] == '#':
            continue
        else:
            break

    print("")
    data = tline[i].split()
    numReaction = int(data[0])
    print("numReaction: " + str(numReaction))

    if (numReaction > 0):
        while 1:
            i = i + 1
            #print (tline[i])
            if len(tline[i]) == 0 or tline[i][0] == '#':
                continue
            else:
                break

        print(tline[i])
        dataReaction = tline[i].split()

        #elem = int(dataReaction[0])
        #nodes_x = float(dataReaction[1])
        #nodes_y = float(dataReaction[2])
        #nodes_z = float(dataReaction[3])
        #nodes[elem] = FreeCAD.Vector(nodes_x, nodes_y, nodes_z)

        for id in range(1, numReaction):  # node
            #1       0.000000       0.000000       0.000000    0.000   1  1  1  1  1  0
            #i=i+1
            while 1:
                i = i + 1
                #print (tline[i])
                if len(tline[i]) == 0 or tline[i][0] == '#':
                    continue
                else:
                    break
            print(tline[i])
            #dataNode = tline[i].split()

            #elem = int(dataNode[0])
            #nodes_x = float(dataNode[1])
            #nodes_y = float(dataNode[2])
            #nodes_z = float(dataNode[3])
            #nodes[elem] = FreeCAD.Vector(nodes_x, nodes_y, nodes_z)

    #Member 333333333333333333333333333333333333333333333333333333
    while 1:
        i = i + 1
        #print (tline[i])
        if len(tline[i]) == 0 or tline[i][0] == '#':
            continue
        else:
            break

    print("")
    data = tline[i].split()
    numMember = int(data[0])
    print("numMember: " + str(numMember))

    while 1:
        i = i + 1
        #print (tline[i])
        if len(tline[i]) == 0 or tline[i][0] == '#':
            continue
        else:
            break

    print(tline[i])
    dataNode = tline[i].split()
    elem = int(dataNode[0])
    nd1 = int(dataNode[1])
    nd2 = int(dataNode[2])
    elements_seg2[elem] = (nd1, nd2)
    for id in range(1, numMember):  # Member
        #i=i+1
        while 1:
            i = i + 1
            #print (tline[i])
            if len(tline[i]) == 0 or tline[i][0] == '#':
                continue
            else:
                break
        print(tline[i])
        dataNode = tline[i].split()
        elem = int(dataNode[0])
        nd1 = int(dataNode[1])
        nd2 = int(dataNode[2])
        elements_seg2[elem] = (nd1, nd2)

        # here we are in the indent of loop for every line in Frame3DD file
        # do not add a print here :-)

    # close Frame3DD file if loop over all lines is finished
    Frame3DD_file.close()
    """
    # debug prints and checks with the read data
    print("\n\n----RESULTS values begin----")
    print(len(results))
    # print("\n")
    # print(results)
    print("----RESULTS values end----\n\n")
    """

    if not inout_nodes:
        if results:
            if "mflow" in results[0] or "npressure" in results[0]:
                Console.PrintError(
                    "We have mflow or npressure, but no inout_nodes file.\n")
    if not nodes:
        Console.PrintError("FEM: No nodes found in Frame3DD file.\n")

    return {
        "Nodes": nodes,
        "Seg2Elem": elements_seg2,
        "Seg3Elem": elements_seg3,
        "Tria3Elem": elements_tria3,
        "Tria6Elem": elements_tria6,
        "Quad4Elem": elements_quad4,
        "Quad8Elem": elements_quad8,
        "Tetra4Elem": elements_tetra4,
        "Tetra10Elem": elements_tetra10,
        "Hexa8Elem": elements_hexa8,
        "Hexa20Elem": elements_hexa20,
        "Penta6Elem": elements_penta6,
        "Penta15Elem": elements_penta15,
        "Results": results
    }
Example #14
0
def read_inp(file_name):
    """read .inp file """

    # ATM only mesh reading is supported (no boundary conditions)

    class elements():

        tria3 = {}
        tria6 = {}
        quad4 = {}
        quad8 = {}
        tetra4 = {}
        tetra10 = {}
        hexa8 = {}
        hexa20 = {}
        penta6 = {}
        penta15 = {}
        seg2 = {}
        seg3 = {}

    error_seg3 = False  # to print "not supported"
    nodes = {}
    model_definition = True

    f = pyopen(file_name, "r")
    line = "\n"
    include = ""
    f_include = None
    while line != "":
        if include:
            line = f_include.readline()
            if line == "":
                f_include.close()
                include = ""
                line = f.readline()
        else:
            line = f.readline()
        if line.strip() == "":
            continue
        elif line[0] == "*":  # start/end of a reading set
            if line[0:2] == "**":  # comments
                continue
            if line[:8].upper() == "*INCLUDE":
                start = 1 + line.index("=")
                include = line[start:].strip().strip('"')
                include_path = os.path.normpath(include)
                if os.path.isfile(include_path) is True:
                    f_include = pyopen(include_path, "r")
                else:
                    path_start = os.path.split(file_name)[0]
                    include_full_path = os.path.join(path_start, include_path)
                    f_include = pyopen(include_full_path, "r")
                continue
            read_node = False
            elm_category = []
            elm_2nd_line = False

        # reading nodes
        if (line[:5].upper() == "*NODE") and (model_definition is True):
            read_node = True
        elif read_node is True:
            line_list = line.split(",")
            number = int(line_list[0])
            x = float(line_list[1])
            y = float(line_list[2])
            z = float(line_list[3])
            nodes[number] = [x, y, z]

        # reading elements
        elif line[:8].upper() == "*ELEMENT":
            line_list = line[8:].upper().split(",")
            for line_part in line_list:
                if line_part.lstrip()[:4] == "TYPE":
                    elm_type = line_part.split("=")[1].strip()

            if elm_type in ["S3", "CPS3", "CPE3", "CAX3"]:
                elm_category = elements.tria3
                number_of_nodes = 3
            elif elm_type in ["S6", "CPS6", "CPE6", "CAX6"]:
                elm_category = elements.tria6
                number_of_nodes = 6
            elif elm_type in [
                    "S4", "S4R", "CPS4", "CPS4R", "CPE4", "CPE4R", "CAX4",
                    "CAX4R"
            ]:
                elm_category = elements.quad4
                number_of_nodes = 4
            elif elm_type in [
                    "S8", "S8R", "CPS8", "CPS8R", "CPE8", "CPE8R", "CAX8",
                    "CAX8R"
            ]:
                elm_category = elements.quad8
                number_of_nodes = 8
            elif elm_type == "C3D4":
                elm_category = elements.tetra4
                number_of_nodes = 4
            elif elm_type == "C3D10":
                elm_category = elements.tetra10
                number_of_nodes = 10
            elif elm_type in ["C3D8", "C3D8R", "C3D8I"]:
                elm_category = elements.hexa8
                number_of_nodes = 8
            elif elm_type in ["C3D20", "C3D20R", "C3D20RI"]:
                elm_category = elements.hexa20
                number_of_nodes = 20
            elif elm_type == "C3D6":
                elm_category = elements.penta6
                number_of_nodes = 6
            elif elm_type == "C3D15":
                elm_category = elements.penta15
                number_of_nodes = 15
            elif elm_type in ["B31", "B31R", "T3D2"]:
                elm_category = elements.seg2
                number_of_nodes = 2
            elif elm_type in ["B32", "B32R", "T3D3"]:
                elm_category = elements.seg3
                number_of_nodes = 3
                error_seg3 = True  # to print "not supported"

        elif elm_category != []:
            line_list = line.split(",")
            if elm_2nd_line is False:
                number = int(line_list[0])
                elm_category[number] = []
                pos = 1
            else:
                pos = 0
                elm_2nd_line = False
            for en in range(pos,
                            pos + number_of_nodes - len(elm_category[number])):
                try:
                    enode = int(line_list[en])
                    elm_category[number].append(enode)
                except:
                    elm_2nd_line = True
                    break

        elif line[:5].upper() == "*STEP":
            model_definition = False
    if error_seg3 is True:  # to print "not supported"
        Console.PrintError(
            "Error: seg3 (3-node beam element type) not supported, yet.\n")
    f.close()

    # switch from the CalculiX node numbering to the FreeCAD node numbering
    # numbering do not change: tria3, tria6, quad4, quad8, seg2
    for en in elements.tetra4:
        n = elements.tetra4[en]
        elements.tetra4[en] = [n[1], n[0], n[2], n[3]]
    for en in elements.tetra10:
        n = elements.tetra10[en]
        elements.tetra10[en] = [
            n[1], n[0], n[2], n[3], n[4], n[6], n[5], n[8], n[7], n[9]
        ]
    for en in elements.hexa8:
        n = elements.hexa8[en]
        elements.hexa8[en] = [n[5], n[6], n[7], n[4], n[1], n[2], n[3], n[0]]
    for en in elements.hexa20:
        n = elements.hexa20[en]
        elements.hexa20[en] = [
            n[5], n[6], n[7], n[4], n[1], n[2], n[3], n[0], n[13], n[14],
            n[15], n[12], n[9], n[10], n[11], n[8], n[17], n[18], n[19], n[16]
        ]
    for en in elements.penta6:
        n = elements.penta6[en]
        elements.penta6[en] = [n[4], n[5], n[3], n[1], n[2], n[0]]
    for en in elements.penta15:
        n = elements.penta15[en]
        elements.penta15[en] = [
            n[4], n[5], n[3], n[1], n[2], n[0], n[10], n[11], n[9], n[7], n[8],
            n[6], n[13], n[14], n[12]
        ]
    for en in elements.seg3:
        n = elements.seg3[en]
        elements.seg3[en] = [n[0], n[2], n[1]]

    return {
        "Nodes": nodes,
        "Seg2Elem": elements.seg2,
        "Seg3Elem": elements.seg3,
        "Tria3Elem": elements.tria3,
        "Tria6Elem": elements.tria6,
        "Quad4Elem": elements.quad4,
        "Quad8Elem": elements.quad8,
        "Tetra4Elem": elements.tetra4,
        "Tetra10Elem": elements.tetra10,
        "Hexa8Elem": elements.hexa8,
        "Hexa20Elem": elements.hexa20,
        "Penta6Elem": elements.penta6,
        "Penta15Elem": elements.penta15
    }
Example #15
0
def process(filename):
    """Process the filename and create a Draft Wire from the data.

    The common airfoil dat format has many flavors.
    This code should work with almost every dialect.

    Parameters
    ----------
    filename : str
        The path to the filename to be opened.

    Returns
    -------
    Part::Part2DObject or None.
        The created Draft Wire object or None if the file contains less
        than 3 points.
    """
    # Regex to identify data rows and throw away unused metadata
    xval = r'(?P<xval>\-?\s*\d*\.*\d*([Ee]\-?\d+)?)'
    yval = r'(?P<yval>\-?\s*\d*\.*\d*([Ee]\-?\d+)?)'
    _regex = r'^\s*' + xval + r'\,?\s*' + yval + r'\s*$'

    regex = re.compile(_regex)
    afile = pythonopen(filename, 'r')
    # read the airfoil name which is always at the first line
    airfoilname = afile.readline().strip()

    coords = []
    # upside = True
    # last_x = None

    # Collect the data
    for lin in afile:
        curdat = regex.match(lin)
        if (curdat is not None
                and curdat.group("xval")
                and curdat.group("yval")):
            x = float(curdat.group("xval"))
            y = float(curdat.group("yval"))

            # Some files specify the number of upper and lower points on the 2nd line:
            # "       67.       72."
            # See: http://airfoiltools.com/airfoil
            # This line must be skipped:
            if x < 2 and y < 2:
                # the normal processing
                coords.append(Vector(x, y, 0))

    afile.close()

    if len(coords) < 3:
        FCC.PrintError(translate("ImportAirfoilDAT", "Did not find enough coordinates") + "\n")
        return None

    # sometimes coords are divided in upper an lower side
    # so that x-coordinate begin new from leading or trailing edge
    # check for start coordinates in the middle of list
    if coords[0:-1].count(coords[0]) > 1:
        flippoint = coords.index(coords[0], 1)
        upper = coords[0:flippoint]
        lower = coords[flippoint+1:]
        lower.reverse()
        for i in lower:
            upper.append(i)
        coords = upper

    # do we use the parametric Draft Wire?
    if useDraftWire:
        obj = Draft.make_wire(coords, True)
        # obj.label = airfoilname
    else:
        # alternate solution, uses common Part Faces
        lines = []
        first_v = None
        last_v = None
        for v in coords:
            if first_v is None:
                first_v = v

            # Line between v and last_v if they're not equal
            if (last_v is not None) and (last_v != v):
                lines.append(Part.makeLine(last_v, v))

            # The new last_v
            last_v = v

        # close the wire if needed
        if last_v != first_v:
            lines.append(Part.makeLine(last_v, first_v))

        wire = Part.Wire(lines)
        face = Part.Face(wire)
        obj = FreeCAD.ActiveDocument.addObject('Part::Feature', airfoilname)
        obj.Shape = face

    return obj
Example #16
0
def get_parameters(source_arc, as_dict=True):
    """
    Given a minimum of existing parameters, return a fully-described arc
    """

    _result = Arc(source_arc)

    #Vector order:
    #Radius in / out, Tangent in / out, Middle, and Chord
    points = [_result.start, _result.end, _result.center, _result.pi]

    point_count = len([_v for _v in points if _v])

    #define the curve start at the origin if none is provided
    if point_count == 0:
        points[0] = Vector()

    vecs = [
        support.safe_sub(_result.start, _result.center, True),
        support.safe_sub(_result.end, _result.center, True),
        support.safe_sub(_result.pi, _result.start, True),
        support.safe_sub(_result.end, _result.pi, True),
        support.safe_sub(_result.pi, _result.center, True),
        support.safe_sub(_result.end, _result.start, True)
    ]

    mat = get_scalar_matrix(vecs)
    _p = get_lengths(_result, mat)

    if not _p:
        Console.PrintError("""
        Invalid curve definition: cannot determine radius / tangent lengths.
        Arc:
        """ + str(_result))

        _result.radius = 0.0
        return _result

    _result.update(_p)
    _p = get_delta(_result, mat)

    if not _p:
        Console.PrintError(
            'Invalid curve definition: cannot determine central angle.' +
            '\nArc:\n' + str(_result))
        return None

    _result.update(_p)
    _p = get_rotation(_result, vecs)

    if not _p:
        Console.PrintError(
            'Invalid curve definition: cannot determine curve direction.' +
            '\nArc:\n' + str(_result))
        return None

    _result.update(_p)
    _p = get_bearings(_result, mat, _result.get('Delta'),
                      _result.get('Direction'))

    if not _p:
        Console.PrintError(
            'Invalid curve definition: cannot determine curve bearings.' +
            '\nArc:\n' + str(_result))
        return None

    _result.update(_p)
    _p = get_missing_parameters(_result, _result, points)

    if not _p:
        Console.PrintError(
            'Invalid curve definition: cannot calculate all parameters.' +
            '\nArc:\n' + str(_result))
        return None

    _result.update(_p)
    _p = get_coordinates(_result, points)

    if not _p:
        Console.PrintError(
            'Invalid curve definition: cannot calculate coordinates' +
            '\nArc:\n' + str(_result))
        return None

    _result.update(_p)

    #get rid of the Bearings dict since we're done using it
    #_result.pop('Bearings')

    #merge the _result with the original dict to preserve other values

    if as_dict:
        return _result.to_dict()

    return _result