Exemplo n.º 1
0
 def start_logs(self):
     Console.PrintLog("\nGmsh FEM mesh run is being started.\n")
     Console.PrintLog(
         "  Part to mesh: Name --> {},  Label --> {}, ShapeType --> {}\n".
         format(self.part_obj.Name, self.part_obj.Label,
                self.part_obj.Shape.ShapeType))
     Console.PrintLog("  CharacteristicLengthMax: {}\n".format(self.clmax))
     Console.PrintLog("  CharacteristicLengthMin: {}\n".format(self.clmin))
     Console.PrintLog("  ElementOrder: {}\n".format(self.order))
Exemplo n.º 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
Exemplo n.º 3
0
    def Initialize(self):
        """When the workbench is first loaded."""
        # pylint: disable=no-self-use, import-outside-toplevel
        from PySide.QtCore import QT_TRANSLATE_NOOP
        from FreeCAD import Console
        from FreeCADGui import addIconPath, addPreferencePage
        from Render import RENDER_COMMANDS, ICONDIR, PREFPAGE

        commands = RENDER_COMMANDS
        self.appendToolbar(QT_TRANSLATE_NOOP("Workbench", "Render"), commands)
        self.appendMenu(QT_TRANSLATE_NOOP("Workbench", "&Render"), commands)
        addIconPath(ICONDIR)
        addPreferencePage(PREFPAGE, "Render")
        Console.PrintLog("Loading Render module...done\n")
Exemplo n.º 4
0
 def _handleRedifinedConstants(self):
     """
     redefine constants in self.constsdef according constant redefine objects
     """
     permittivity_objs = self._getMember("Fem::ConstantVacuumPermittivity")
     if len(permittivity_objs) == 1:
         Console.PrintLog("Constand permittivity overwriting.\n")
         self._setConstant("PermittivityOfVacuum",
                           permittivity_objs[0].VacuumPermittivity)
     elif len(permittivity_objs) > 1:
         Console.PrintError(
             "More than one permittivity constant overwriting objects ({} objs). "
             "The permittivity constant overwriting is ignored.\n".format(
                 len(permittivity_objs)))
Exemplo n.º 5
0
 def get_dimension(self):
     # Dimension
     # known_element_dimensions = ["From Shape", "1D", "2D", "3D"]
     # if not given, Gmsh uses the highest available.
     # A use case for not "From Shape" would be a surface (2D) mesh of a solid
     if self.dimension == "From Shape":
         shty = self.part_obj.Shape.ShapeType
         if shty == "Solid" or shty == "CompSolid":
             # print("Found: " + shty)
             self.dimension = "3"
         elif shty == "Face" or shty == "Shell":
             # print("Found: " + shty)
             self.dimension = "2"
         elif shty == "Edge" or shty == "Wire":
             # print("Found: " + shty)
             self.dimension = "1"
         elif shty == "Vertex":
             # print("Found: " + shty)
             Console.PrintError("You can not mesh a Vertex.\n")
             self.dimension = "0"
         elif shty == "Compound":
             # print("  Found a " + shty)
             Console.PrintLog(
                 "  Found a Compound. Since it could contain"
                 "any kind of shape dimension 3 is used.\n"
             )
             self.dimension = "3"  # dimension 3 works for 2D and 1d shapes as well
         else:
             self.dimension = "0"
             Console.PrintError(
                 "Could not retrieve Dimension from shape type. Please choose dimension.\n"
             )
     elif self.dimension == "3D":
         self.dimension = "3"
     elif self.dimension == "2D":
         self.dimension = "2"
     elif self.dimension == "1D":
         self.dimension = "1"
     else:
         Console.PrintError("Error in dimension\n")
     Console.PrintMessage("  ElementDimension: " + self.dimension + "\n")
Exemplo n.º 6
0
    def Initialize(self):
        """Initialize GUI when the workbench is first loaded (callback).

        This method is called by FreeCAD framework when the workbench is first
        loaded.
        """
        # pylint: disable=no-self-use, import-outside-toplevel
        from PySide.QtCore import QT_TRANSLATE_NOOP
        from FreeCAD import Console
        from FreeCADGui import addIconPath, addPreferencePage, addLanguagePath
        from Render import RENDER_COMMANDS, TRANSDIR, ICONDIR, PREFPAGE

        addLanguagePath(TRANSDIR)
        self.appendToolbar(QT_TRANSLATE_NOOP("Workbench", "Render"),
                           RENDER_COMMANDS)
        self.appendMenu(QT_TRANSLATE_NOOP("Workbench", "&Render"),
                        RENDER_COMMANDS)
        addIconPath(ICONDIR)
        addPreferencePage(PREFPAGE, "Render")
        msg = QT_TRANSLATE_NOOP("Render",
                                "Loading Render module... done") + "\n"
        Console.PrintLog(msg)
Exemplo n.º 7
0
def read_z88_disp(z88_disp_input):
    """
    read a z88 disp file and extract the nodes and elements
    z88 Displacement output file is z88o2.txt
    works with Z88OS14
    """
    nodes = {}
    mode_disp = {}
    mode_results = {}
    results = []

    z88_disp_file = pyopen(z88_disp_input, "r")

    for no, line in enumerate(z88_disp_file):
        lno = no + 1
        linelist = line.split()

        if lno >= 6:
            # disp line
            node_no = int(linelist[0])
            mode_disp_x = float(linelist[1])
            mode_disp_y = float(linelist[2])
            if len(linelist) > 3:
                mode_disp_z = float(linelist[3])
            else:
                mode_disp_z = 0.0
            mode_disp[node_no] = FreeCAD.Vector(mode_disp_x, mode_disp_y,
                                                mode_disp_z)
            nodes[node_no] = node_no

    mode_results["disp"] = mode_disp
    results.append(mode_results)

    for r in results[0]["disp"]:
        Console.PrintLog("{} --> {}\n".format(r, results[0]["disp"][r]))

    z88_disp_file.close()
    return {"Nodes": nodes, "Results": results}
Exemplo n.º 8
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
                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 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 = 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 vonMises
                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 frd 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)

        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
Exemplo n.º 9
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
    }
Exemplo n.º 10
0
def importAvs(filename, analysis=None, result_name_prefix=""):
    import ObjectsFem
    from feminout import importToolsFem

    TUNE = False
    if TUNE:
        import time
        cur = time.time()

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

    m = read_avs_result(filename)

    result_mesh_object = None
    res_obj = None

    if TUNE:
        new = time.time()
        Console.PrintMessage("dtime 1:" + '%8.3f' % (new - cur) + "\n")
        cur = new

    if len(m["Nodes"]) > 0:
        mesh = importToolsFem.make_femmesh(m)
        if TUNE:
            new = time.time()
            Console.PrintMessage("dtime 2:" + '%8.3f' % (new - cur) + "\n")
            cur = new

        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 TUNE:
            new = time.time()
            Console.PrintMessage("dtime 3:" + '%8.3f' % (new - cur) + "\n")
            cur = new
        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))

                if TUNE:
                    new = time.time()
                    Console.PrintMessage("dtime 4:" + '%8.3f' % (new - cur) +
                                         "\n")
                    cur = new
                res_obj = ObjectsFem.makeResultMechanical(doc, results_name)
                res_obj.Mesh = result_mesh_object

                if TUNE:
                    new = time.time()
                    Console.PrintMessage("dtime 5:" + '%8.3f' % (new - cur) +
                                         "\n")
                    cur = new

                res_obj = importToolsFem.fill_femresult_mechanical(
                    res_obj, result_set)
                if analysis:
                    # need to be here, becasause later on, the analysis objs are needed
                    # see fill of principal stresses
                    analysis.addObject(res_obj)
                if TUNE:
                    new = time.time()
                    Console.PrintMessage("dtime 6:" + '%8.3f' % (new - cur) +
                                         "\n")
                    cur = new

                # more result object calculations
                from femresult import resulttools
                from femtools import femutils
                if not res_obj.MassFlowRate:
                    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

                if TUNE:
                    new = time.time()
                    Console.PrintMessage("dtime 7:" + '%8.3f' % (new - cur) +
                                         "\n")
                    cur = new
                # fill DisplacementLengths
                res_obj = resulttools.add_disp_apps(res_obj)

                if TUNE:
                    new = time.time()
                    Console.PrintMessage("dtime 8:" + '%8.3f' % (new - cur) +
                                         "\n")
                    cur = new

                # fill vonMises
                mstress = []
                for nid in res_obj.NodeNumbers:
                    mstress.append(result_set["mises"][nid])
                res_obj.vonMises = mstress

                if TUNE:
                    new = time.time()
                    Console.PrintMessage("dtime 9:" + '%8.3f' % (new - cur) +
                                         "\n")
                    cur = new

                # fill principal stress
                prinstress1 = []
                prinstress2 = []
                prinstress3 = []
                for nid in res_obj.NodeNumbers:
                    pstr = result_set["pstress"][nid]
                    prinstress1.append(pstr[0])
                    prinstress2.append(pstr[1])
                    prinstress3.append(pstr[2])
                res_obj.PrincipalMax = prinstress1
                res_obj.PrincipalMed = prinstress2
                res_obj.PrincipalMin = prinstress3

                # fill Stats
                res_obj = resulttools.fill_femresult_stats(res_obj)

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

        # create a result obj, even if we have no results but a result mesh in avs 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()

        if TUNE:
            new = time.time()
            Console.PrintMessage("dtime11:" + '%8.3f' % (new - cur) + "\n")
            cur = new

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

    return res_obj
Exemplo n.º 11
0
    def read_mesh_block(mesh_block):
        """
            Reading mesh block from XML file.
            The mesh block only contains cells and vertices.
        """
        dim = int(mesh_block.get("dim"))
        cell_type = mesh_block.get("celltype")

        vertex_size = 0

        Console.PrintLog("Mesh dimension: %d\n" % (dim, ))
        Console.PrintLog("Mesh cell type: %s\n" % (cell_type, ))

        # every cell type contains a dict with key=dimension and value=number

        cells_parts_dim = {
            "point": {
                0: 1
            },
            "interval": {
                0: 2,
                1: 1
            },
            "triangle": {
                0: 3,
                1: 3,
                2: 1
            },
            "tetrahedron": {
                0: 4,
                1: 6,
                2: 4,
                3: 1
            },
            "quadrilateral": {
                0: 4,
                1: 4,
                2: 1
            },
            "hexahedron": {
                0: 8,
                1: 12,
                2: 6,
                3: 1
            }
        }

        find_vertices = mesh_block.find("vertices")
        find_cells = mesh_block.find("cells")

        nodes_dict = {}
        cell_dict = {}

        if find_vertices is None:
            Console.PrintWarning("No vertices found!\n")
        else:
            vertex_size = int(find_vertices.attrib.get("size"))
            Console.PrintLog("Reading %d vertices\n" % (vertex_size, ))

            for vertex in find_vertices:
                ind = int(vertex.get("index"))

                if vertex.tag.lower() == "vertex":
                    [node_x, node_y, node_z] = [
                        float(vertex.get(coord, 0.))
                        for coord in ["x", "y", "z"]
                    ]

                    nodes_dict[ind + 1] = FreeCAD.Vector(
                        node_x, node_y, node_z)
                    # increase node index by one, since fenics starts at 0, FreeCAD at 1
                    # print("%d %f %f %f" % (ind, node_x, node_y, node_z))
                else:
                    Console.PrintWarning("found strange vertex tag: %s\n" %
                                         (vertex.tag, ))

        if find_cells is None:
            Console.PrintWarning("No cells found!\n")
        else:
            Console.PrintLog("Reading %d cells\n" %
                             (int(find_cells.attrib.get("size")), ))
            for cell in find_cells:
                ind = int(cell.get("index"))

                if cell.tag.lower() != cell_type.lower():
                    Console.PrintWarning(
                        "Strange mismatch between cell type {} and cell tag {}\n"
                        .format(cell_type, cell.tag.lower()))
                num_vertices = cells_parts_dim[cell_type][0]

                vtupel = tuple([
                    int(cell.get("v" + str(vnum))) + 1
                    for vnum in range(num_vertices)
                ])
                # generate "v0", "v1", ... from dimension lookup table
                # increase numbers by one to match FC numbering convention

                cell_dict[ind + 1] = vtupel

                # valtupel = tuple([ind] + list(vtupel))
                # print(("%d " + ("%d "*len(vtupel))) % valtupel)

        return (nodes_dict, cell_dict, cell_type, dim)
Exemplo n.º 12
0
def read_fenics_mesh_xml(xmlfilename):
    """
        Returns element dictionary to be evaluated by make_femmesh later
    """

    Fenics_to_FreeCAD_dict = {
        "triangle": "tria3",
        "tetrahedron": "tetra4",
        "hexahedron": "hexa8",
        "interval": "seg2",
        "quadrilateral": "quad4",
    }

    def read_mesh_block(mesh_block):
        """
            Reading mesh block from XML file.
            The mesh block only contains cells and vertices.
        """
        dim = int(mesh_block.get("dim"))
        cell_type = mesh_block.get("celltype")

        vertex_size = 0

        Console.PrintLog("Mesh dimension: %d\n" % (dim, ))
        Console.PrintLog("Mesh cell type: %s\n" % (cell_type, ))

        # every cell type contains a dict with key=dimension and value=number

        cells_parts_dim = {
            "point": {
                0: 1
            },
            "interval": {
                0: 2,
                1: 1
            },
            "triangle": {
                0: 3,
                1: 3,
                2: 1
            },
            "tetrahedron": {
                0: 4,
                1: 6,
                2: 4,
                3: 1
            },
            "quadrilateral": {
                0: 4,
                1: 4,
                2: 1
            },
            "hexahedron": {
                0: 8,
                1: 12,
                2: 6,
                3: 1
            }
        }

        find_vertices = mesh_block.find("vertices")
        find_cells = mesh_block.find("cells")

        nodes_dict = {}
        cell_dict = {}

        if find_vertices is None:
            Console.PrintWarning("No vertices found!\n")
        else:
            vertex_size = int(find_vertices.attrib.get("size"))
            Console.PrintLog("Reading %d vertices\n" % (vertex_size, ))

            for vertex in find_vertices:
                ind = int(vertex.get("index"))

                if vertex.tag.lower() == "vertex":
                    [node_x, node_y, node_z] = [
                        float(vertex.get(coord, 0.))
                        for coord in ["x", "y", "z"]
                    ]

                    nodes_dict[ind + 1] = FreeCAD.Vector(
                        node_x, node_y, node_z)
                    # increase node index by one, since fenics starts at 0, FreeCAD at 1
                    # print("%d %f %f %f" % (ind, node_x, node_y, node_z))
                else:
                    Console.PrintWarning("found strange vertex tag: %s\n" %
                                         (vertex.tag, ))

        if find_cells is None:
            Console.PrintWarning("No cells found!\n")
        else:
            Console.PrintLog("Reading %d cells\n" %
                             (int(find_cells.attrib.get("size")), ))
            for cell in find_cells:
                ind = int(cell.get("index"))

                if cell.tag.lower() != cell_type.lower():
                    Console.PrintWarning(
                        "Strange mismatch between cell type {} and cell tag {}\n"
                        .format(cell_type, cell.tag.lower()))
                num_vertices = cells_parts_dim[cell_type][0]

                vtupel = tuple([
                    int(cell.get("v" + str(vnum))) + 1
                    for vnum in range(num_vertices)
                ])
                # generate "v0", "v1", ... from dimension lookup table
                # increase numbers by one to match FC numbering convention

                cell_dict[ind + 1] = vtupel

                # valtupel = tuple([ind] + list(vtupel))
                # print(("%d " + ("%d "*len(vtupel))) % valtupel)

        return (nodes_dict, cell_dict, cell_type, dim)

    def generate_lower_dimensional_structures(nodes, cell_dict, cell_type,
                                              dim):
        def correct_volume_det(element_dict):
            """
                Checks whether the cell elements
                all have the same volume (<0?)
                sign (is necessary to avoid negative
                Jacobian errors).
                Works only with tet4 and tri3 elements at the moment
            """
            if dim == 3:
                for (ind, tet) in list(element_dict["tetra4"].items()):
                    v0 = nodes[tet[0]]
                    v1 = nodes[tet[1]]
                    v2 = nodes[tet[2]]
                    v3 = nodes[tet[3]]
                    a = v1 - v0
                    b = v2 - v0
                    c = v3 - v0
                    if a.dot(b.cross(c)) > 0:
                        element_dict["tetra4"][ind] = (tet[1], tet[0], tet[2],
                                                       tet[3])
            if dim == 2:
                nz = FreeCAD.Vector(0., 0., 1.)
                for (ind, tria) in list(element_dict["tria3"].items()):
                    v0 = nodes[tria[0]]
                    v1 = nodes[tria[1]]
                    v2 = nodes[tria[2]]
                    a = v1 - v0
                    b = v2 - v0
                    if nz.dot(a.cross(b)) < 0:
                        element_dict["tria3"][ind] = (tria[1], tria[0],
                                                      tria[2])

        element_dict = {}
        element_counter = {}

        # TODO: remove upper level lookup
        for (key, val) in list(Fenics_to_FreeCAD_dict.items()):
            element_dict[val] = {}
            element_counter[
                key] = 0  # count every distinct element and sub element type

        def addtupletodict(di, tpl, counter):
            sortedtpl = tuple(sorted(tpl))
            if di.get(sortedtpl) is None:
                di[sortedtpl] = counter
                counter += 1
            return counter

        def invertdict(dic):
            invdic = {}
            for (key, it) in list(dic.items()):
                invdic[it] = key
            return invdic

        num_vert_dict = {
            "interval": 2,
            "triangle": 3,
            "tetrahedron": 4,
            "hexahedron": 8,
            "quadrilateral": 4
        }
        lower_dims_dict = {
            "interval": [],
            "triangle": ["interval"],
            "tetrahedron": ["triangle", "interval"],
            "hexahedron": ["quadrilateral", "interval"],
            "quadrilateral": ["interval"]
        }

        # generate cell list from file
        # read vertex list from cells
        # generate lower dimensional objects in mesh from cell

        for (cell_index, cell) in list(cell_dict.items()):
            cell_lower_dims = lower_dims_dict[cell_type]
            element_counter[cell_type] += 1
            element_dict[Fenics_to_FreeCAD_dict[cell_type]][
                cell] = element_counter[cell_type]
            for ld in cell_lower_dims:
                for vertextuple in itertools.combinations(
                        cell, num_vert_dict[ld]):
                    element_counter[ld] = addtupletodict(
                        element_dict[Fenics_to_FreeCAD_dict[ld]], vertextuple,
                        element_counter[ld])

        length_counter = len(nodes)  # maintain distinct counting values
        # print("nodes")
        # print("len & len counter", length_counter)
        for (key, val_dict) in list(element_dict.items()):
            # to ensure distinct indices for FreeCAD
            # print("key: ", key)
            for (vkey, it) in list(val_dict.items()):
                val_dict[
                    vkey] = it + length_counter  # maintain distinct element numbers
            len_val_dict = len(val_dict)
            if len_val_dict > 0:
                length_counter += len_val_dict + 1  # only if preceding list is not empty
            # print("len: ", len_val_dict)
            # print("lencounter: ", length_counter)
            # inverse of the dict (dict[key] = val -> dict[val] = key)
            element_dict[key] = invertdict(val_dict)

        correct_volume_det(element_dict)  # corrects negative determinants

        return element_dict  # returns complete element dictionary

    nodes = {}
    element_dict = {}
    # TODO: remove two times initialization
    for val in list(Fenics_to_FreeCAD_dict.values()):
        element_dict[val] = {}

    tree = ET.parse(xmlfilename)
    root = tree.getroot()

    if root.tag.lower() != "dolfin":
        Console.PrintWarning("Strange root tag, should be dolfin!\n")

    find_mesh = root.find("mesh")
    if find_mesh is not None:  # these are consistency checks of the XML structure
        Console.PrintMessage("Mesh found\n")
        (nodes, cells_dict, cell_type, dim) = read_mesh_block(find_mesh)
        element_dict = generate_lower_dimensional_structures(
            nodes, cells_dict, cell_type, dim)
        Console.PrintMessage("Show min max element dict")
        for (elm, numbers) in list(element_dict.items()):
            lst = sorted(list(numbers.items()), key=lambda x: x[0])
            if lst != []:
                Console.PrintWarning(elm, " min: ", lst[0], " max: ", lst[-1],
                                     "\n")
    else:
        Console.PrintError("No mesh found")

    if root.find("data") is not None:
        Console.PrintLog("Internal mesh data found\n")

    return {
        "Nodes": nodes,
        "Seg2Elem": element_dict["seg2"],
        "Seg3Elem": {},
        "Tria3Elem": element_dict["tria3"],
        "Tria6Elem": {},
        "Quad4Elem": element_dict["quad4"],
        "Quad8Elem": {},
        "Tetra4Elem": element_dict["tetra4"],
        "Tetra10Elem": {},
        "Hexa8Elem": {},
        "Hexa20Elem": {},
        "Penta6Elem": {},
        "Penta15Elem": {}
    }
Exemplo n.º 13
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))
Exemplo n.º 14
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))
Exemplo n.º 15
0
def importFrame3DD(
    filename,
    analysis=None,
    result_name_prefix=""
):
    from . import importToolsFem
    #from . import Fem.feminout.importToolsFem
    import ObjectsFem

	#import result mesh only
    Console.PrintMessage(
        "Read Frame3DD results from Frame3DD file: {}\n"
        .format(filename)
    )
    Frame3DD_file = pyopen(filename, "r")
    nodes = {}

    elem = -1
    elemType = 0
	
    nDisp=0
	
    numNode =  0
    numFixedNode =  0
    numMember =  0
    numLC =  0
	
    isDebug=0
		
    NodeList = {}
    MemberList = {}                                  
	
    tline=[]
    for line in Frame3DD_file:
        tline.append(line.strip())
		
    for i in range(len(tline)):
	
        #Console.PrintError(tline[i])
        tStrNode="In 2D problems the Y-axis is vertical.  In 3D problems the Z-axis is vertical."	
        if tline[i].strip() == tStrNode:
            #Console.PrintError("FEM: nodes found.\n")
			
            i=i+1
            i=i+1
            data = tline[i].split()
            #12 NODES             12 FIXED NODES       21 FRAME ELEMENTS   2 LOAD CASES   
            numNode =  int(data[0])
            numFixedNode =  int(data[2])
            numMember =  int(data[5])
            numLC =  int(data[8])
	
            i=i+1 # = fp.readline().strip()
            i=i+1 # = fp.readline().strip()
            i=i+1 # = fp.readline().strip()
			
            #print ("")			
            #print ("numNode: "+str(numNode))
            for id in range(numNode): # node
                #1       0.000000       0.000000       0.000000    0.000   1  1  1  1  1  0
                i=i+1
                #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)
                NodeList[id] =  Node(str(id+1), nodes_x, nodes_y, nodes_z )

            i=i+1
            i=i+1
			
            #print ("")			
            #print ("numMember: "+str(numMember))
            for id in range(numMember): # Member
                i=i+1
                #print (tline[i])
                dataNode = tline[i].split()
                elem = int(dataNode[0])
                nd1 = int(dataNode[1])
                nd2 = int(dataNode[2])
                MemberList[id] =  Member(str(id+1) ,nd1, nd2)  

            #print ("")			
            #print ("numFixedNode: "+str(numFixedNode))
            #print ("numLC: "+str(numLC))
		
            femmesh = Fem.FemMesh()
            # nodes
            #print ("Add nodes")
            for id in NodeList: # node
                #femmesh.addNode(NodeList[id].x,NodeList[id].y,NodeList[id].z, int(id)+1 )
                femmesh.addNode(NodeList[id].x,NodeList[id].y,NodeList[id].z, int(id)+1 )
			
            # elements
            for id in MemberList:
                n1 = MemberList[id].n1
                n2 = MemberList[id].n2
                femmesh.addEdge([int(n1), int(n2)], int(id)+1)
				
			
			
    # close Frame3DD file if loop over all lines is finished
    Frame3DD_file.close()

    if not nodes:
        Console.PrintError("FEM: No nodes found in Frame3DD file.\n")
    else:	
	
        #Console.PrintError(tline[i])
        result_mesh_object = None
        #mesh = importToolsFem.make_femmesh(m)
        result_mesh_object = ObjectsFem.makeMeshResult(
            FreeCAD.ActiveDocument,
            "ResultMesh"
        )
        result_mesh_object.FemMesh = femmesh
        res_mesh_is_compacted = False
        nodenumbers_for_compacted_mesh = []
		
		
		

        #import result 
        mm = read_Frame3DD_result(filename)
		
        number_of_increments = len(mm["Results"])
        Console.PrintLog(
            "Increments: " + str(number_of_increments) + "\n"
        )
		
        if len(mm["Results"]) > 0:
		
            res_obj=[]		
            iLC=0
            iModal=0
            results_name="Elastic"
				
            for result_set in mm["Results"]:
                if (iLC<numLC):				
                    results_name="Elastic"
                    res_obj.append(ObjectsFem.makeResultMechanical(FreeCAD.ActiveDocument, results_name+str(iLC)))
                else:
                    results_name="Modal"
                    res_obj.append(ObjectsFem.makeResultMechanical(FreeCAD.ActiveDocument, results_name+str(iModal)))
                    iModal+=1
            				
                res_obj[iLC].Mesh = result_mesh_object
                res_obj[iLC] = importToolsFem.fill_femresult_mechanical(res_obj[iLC], result_set)
                if analysis:
                    analysis.addObject(res_obj[iLC])

                # complementary result object calculations
                import femresult.resulttools as restools
                import femtools.femutils as femutils
                if not res_obj[iLC].MassFlowRate:
                    if res_mesh_is_compacted is False:
                        # first result set, compact FemMesh and NodeNumbers
                        res_obj[iLC] = restools.compact_result(res_obj[iLC])
                        res_mesh_is_compacted = True
                        nodenumbers_for_compacted_mesh = res_obj[iLC].NodeNumbers
                    else:
                        # all other result sets, do not compact FemMesh, only set NodeNumbers
                        res_obj[iLC].NodeNumbers = nodenumbers_for_compacted_mesh

                # fill DisplacementLengths
                res_obj[iLC] = restools.add_disp_apps(res_obj[iLC])
                # fill StressValues
                res_obj[iLC] = restools.add_von_mises(res_obj[iLC])
                if res_obj[iLC].getParentGroup():
                    has_reinforced_mat = False
                    for obj in res_obj[iLC].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[iLC])
                            break
                    if has_reinforced_mat is False:
                        # fill PrincipalMax, PrincipalMed, PrincipalMin, MaxShear
                        res_obj[iLC] = restools.add_principal_stress_std(res_obj[iLC])
                else:
                    # if a pure Frame3DD file was opened no analysis and thus no parent group
                    # fill PrincipalMax, PrincipalMed, PrincipalMin, MaxShear
                    res_obj[iLC] = restools.add_principal_stress_std(res_obj[iLC])
                # fill Stats
                res_obj[iLC] = restools.fill_femresult_stats(res_obj[iLC])
				
                iLC+=1

            return res_obj


        else:
            error_message = (
                "We have nodes only.\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()
Exemplo n.º 16
0
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"
        )
Exemplo n.º 17
0
def make_femmesh(mesh_data):
    """ makes an FreeCAD FEM Mesh object from FEM Mesh data
    """
    import Fem
    mesh = Fem.FemMesh()
    m = mesh_data
    if ("Nodes" in m) and (len(m["Nodes"]) > 0):
        FreeCAD.Console.PrintLog("Found: nodes\n")
        if (("Seg2Elem" in m) or ("Seg3Elem" in m) or ("Tria3Elem" in m)
                or ("Tria6Elem" in m) or ("Quad4Elem" in m)
                or ("Quad8Elem" in m) or ("Tetra4Elem" in m)
                or ("Tetra10Elem" in m) or ("Penta6Elem" in m)
                or ("Penta15Elem" in m) or ("Hexa8Elem" in m)
                or ("Hexa20Elem" in m)):

            nds = m["Nodes"]
            FreeCAD.Console.PrintLog("Found: elements\n")
            for i in nds:
                n = nds[i]
                mesh.addNode(n[0], n[1], n[2], i)
            elms_hexa8 = m["Hexa8Elem"]
            for i in elms_hexa8:
                e = elms_hexa8[i]
                mesh.addVolume(
                    [e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7]], i)
            elms_penta6 = m["Penta6Elem"]
            for i in elms_penta6:
                e = elms_penta6[i]
                mesh.addVolume([e[0], e[1], e[2], e[3], e[4], e[5]], i)
            elms_tetra4 = m["Tetra4Elem"]
            for i in elms_tetra4:
                e = elms_tetra4[i]
                mesh.addVolume([e[0], e[1], e[2], e[3]], i)
            elms_tetra10 = m["Tetra10Elem"]
            for i in elms_tetra10:
                e = elms_tetra10[i]
                mesh.addVolume([
                    e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7], e[8], e[9]
                ], i)
            elms_penta15 = m["Penta15Elem"]
            for i in elms_penta15:
                e = elms_penta15[i]
                mesh.addVolume([
                    e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7], e[8], e[9],
                    e[10], e[11], e[12], e[13], e[14]
                ], i)
            elms_hexa20 = m["Hexa20Elem"]
            for i in elms_hexa20:
                e = elms_hexa20[i]
                mesh.addVolume([
                    e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7], e[8], e[9],
                    e[10], e[11], e[12], e[13], e[14], e[15], e[16], e[17],
                    e[18], e[19]
                ], i)
            elms_tria3 = m["Tria3Elem"]
            for i in elms_tria3:
                e = elms_tria3[i]
                mesh.addFace([e[0], e[1], e[2]], i)
            elms_tria6 = m["Tria6Elem"]
            for i in elms_tria6:
                e = elms_tria6[i]
                mesh.addFace([e[0], e[1], e[2], e[3], e[4], e[5]], i)
            elms_quad4 = m["Quad4Elem"]
            for i in elms_quad4:
                e = elms_quad4[i]
                mesh.addFace([e[0], e[1], e[2], e[3]], i)
            elms_quad8 = m["Quad8Elem"]
            for i in elms_quad8:
                e = elms_quad8[i]
                mesh.addFace([e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7]],
                             i)
            elms_seg2 = m["Seg2Elem"]
            for i in elms_seg2:
                e = elms_seg2[i]
                mesh.addEdge([e[0], e[1]], i)
            elms_seg3 = m["Seg3Elem"]
            for i in elms_seg3:
                e = elms_seg3[i]
                mesh.addEdge([e[0], e[1], e[2]], i)
            Console.PrintLog(
                "imported mesh: {} nodes, {} HEXA8, {} PENTA6, {} TETRA4, {} TETRA10, {} PENTA15\n"
                .format(len(nds), len(elms_hexa8), len(elms_penta6),
                        len(elms_tetra4), len(elms_tetra10),
                        len(elms_penta15)))
            Console.PrintLog(
                "imported mesh: {} "
                "HEXA20, {} TRIA3, {} TRIA6, {} QUAD4, {} QUAD8, {} SEG2, {} SEG3\n"
                .format(len(elms_hexa20), len(elms_tria3), len(elms_tria6),
                        len(elms_quad4), len(elms_quad8), len(elms_seg2),
                        len(elms_seg3)))
        else:
            Console.PrintError("No Elements found!\n")
    else:
        Console.PrintError("No Nodes found!\n")
    return mesh