Example #1
0
    def get_constraints_pressure_faces(self):
        # TODO see comments in get_constraints_force_nodeloads(), it applies here too. Mhh it applies to all constraints ...
        '''
        # depreciated version
        # get the faces and face numbers
        for femobj in self.pressure_objects:  # femobj --> dict, FreeCAD document object is femobj['Object']
            femobj['PressureFaces'] = FemMeshTools.get_pressure_obj_faces_depreciated(self.femmesh, femobj)
            # print(femobj['PressureFaces'])
        '''

        if not self.femnodes_mesh:
            self.femnodes_mesh = self.femmesh.Nodes
        if not self.femelement_table:
            self.femelement_table = FemMeshTools.get_femelement_table(
                self.femmesh)
        if not self.femnodes_ele_table:
            self.femnodes_ele_table = FemMeshTools.get_femnodes_ele_table(
                self.femnodes_mesh, self.femelement_table)

        for femobj in self.pressure_objects:  # femobj --> dict, FreeCAD document object is femobj['Object']
            print("Constraint pressure: " + femobj['Object'].Name)
            pressure_faces = FemMeshTools.get_pressure_obj_faces(
                self.femmesh, self.femelement_table, self.femnodes_ele_table,
                femobj)
            # print(len(pressure_faces))
            femobj['PressureFaces'] = [(femobj['Object'].Name + ': face load',
                                        pressure_faces)]
            print(femobj['PressureFaces'])
Example #2
0
 def get_material_elements(self):
     # it only works if either Volumes or Shellthicknesses or Beamsections are in the material objects
     # it means it does not work for mixed meshes and multiple materials, this is checked in check_prerequisites
     # the femelement_table is only calculated for the highest dimension in get_femelement_table
     FreeCAD.Console.PrintMessage('Materials\n')
     if self.femmesh.Volumes:
         # we only could do this for volumes, if a mesh contains volumes we're going to use them in the analysis
         # but a mesh could contain the element faces of the volumes as faces and the edges of the faces as edges,
         # there we have to check of some geometric objects
         all_found = False
         if self.femmesh.GroupCount:
             all_found = FemMeshTools.get_femelement_sets_from_group_data(self.femmesh, self.material_objects)
             FreeCAD.Console.PrintMessage(all_found)
             FreeCAD.Console.PrintMessage('\n')
         if all_found is False:
             if not self.femelement_table:
                 self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh)
             # we're going to use the binary search for get_femelements_by_femnodes()
             # thus we need the parameter values self.femnodes_ele_table
             if not self.femnodes_mesh:
                 self.femnodes_mesh = self.femmesh.Nodes
             if not self.femnodes_ele_table:
                 self.femnodes_ele_table = FemMeshTools.get_femnodes_ele_table(self.femnodes_mesh, self.femelement_table)
             control = FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects, self.femnodes_ele_table)
             if (self.femelement_count_test is True) and (control is False):  # we only need to set it, if it is still True
                 self.femelement_count_test = False
     if self.shellthickness_objects:
         if not self.femelement_faces_table:
             self.femelement_faces_table = FemMeshTools.get_femelement_faces_table(self.femmesh)
         FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_faces_table, self.material_objects)
     if self.beamsection_objects or self.fluidsection_objects:
         if not self.femelement_edges_table:
             self.femelement_edges_table = FemMeshTools.get_femelement_edges_table(self.femmesh)
         FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_edges_table, self.material_objects)
Example #3
0
    def get_constraints_pressure_faces(self):
        # TODO see comments in get_constraints_force_nodeloads()
        # it applies here too. Mhh it applies to all constraints ...
        """
        # depreciated version
        # get the faces and face numbers
        for femobj in self.pressure_objects:
            # femobj --> dict, FreeCAD document object is femobj["Object"]
            femobj["PressureFaces"] = meshtools.get_pressure_obj_faces_depreciated(
                self.femmesh,
                femobj
            )
            # print(femobj["PressureFaces"])
        """

        if not self.femnodes_mesh:
            self.femnodes_mesh = self.femmesh.Nodes
        if not self.femelement_table:
            self.femelement_table = meshtools.get_femelement_table(
                self.femmesh)
        if not self.femnodes_ele_table:
            self.femnodes_ele_table = meshtools.get_femnodes_ele_table(
                self.femnodes_mesh, self.femelement_table)

        for femobj in self.pressure_objects:
            # femobj --> dict, FreeCAD document object is femobj["Object"]
            FreeCAD.Console.PrintMessage("Constraint pressure: " +
                                         femobj["Object"].Name + "\n")
            pressure_faces = meshtools.get_pressure_obj_faces(
                self.femmesh, self.femelement_table, self.femnodes_ele_table,
                femobj)
            femobj["PressureFaces"] = [(femobj["Object"].Name + ": face load",
                                        pressure_faces)]
            FreeCAD.Console.PrintLog("{}\n".format(femobj["PressureFaces"]))
Example #4
0
 def get_material_elements(self):
     # it only works if either Volumes or Shellthicknesses or Beamsections are in the material objects
     # it means it does not work for mixed meshes and multiple materials, this is checked in check_prerequisites
     print("Materials")
     if self.femmesh.Volumes:
         # we only could do this for volumes, if a mesh contains volumes we're going to use them in the analysis
         # but a mesh could contain the element faces of the volumes as faces and the edges of the faces as edges,
         # there we have to check of some geometric objects
         all_found = False
         if self.femmesh.GroupCount:
             all_found = FemMeshTools.get_femelement_sets_from_group_data(self.femmesh, self.material_objects)
             print(all_found)
         if all_found is False:
             if not self.femelement_table:
                 self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh)
             # we're going to use the binary search for get_femelements_by_femnodes()
             # thus we need the parameter values self.femnodes_ele_table
             if not self.femnodes_mesh:
                 self.femnodes_mesh = self.femmesh.Nodes
             if not self.femnodes_ele_table:
                 self.femnodes_ele_table = FemMeshTools.get_femnodes_ele_table(self.femnodes_mesh, self.femelement_table)
             FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects, self.femnodes_ele_table)
     if self.shellthickness_objects:
         if not self.femelement_table:
             self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh)
         FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects)
     if self.beamsection_objects or self.fluidsection_objects:
         if not self.femelement_table:
             self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh)
         FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects)
Example #5
0
    def get_constraints_pressure_faces(self):
        # TODO see comments in get_constraints_force_nodeloads(), it applies here too. Mhh it applies to all constraints ...

        '''
        # depreciated version
        # get the faces and face numbers
        for femobj in self.pressure_objects:  # femobj --> dict, FreeCAD document object is femobj['Object']
            femobj['PressureFaces'] = FemMeshTools.get_pressure_obj_faces_depreciated(self.femmesh, femobj)
            # print(femobj['PressureFaces'])
        '''

        if not self.femnodes_mesh:
            self.femnodes_mesh = self.femmesh.Nodes
        if not self.femelement_table:
            self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh)
        if not self.femnodes_ele_table:
            self.femnodes_ele_table = FemMeshTools.get_femnodes_ele_table(self.femnodes_mesh, self.femelement_table)

        for femobj in self.pressure_objects:  # femobj --> dict, FreeCAD document object is femobj['Object']
            FreeCAD.Console.PrintMessage("Constraint pressure: " + femobj['Object'].Name + '\n')
            pressure_faces = FemMeshTools.get_pressure_obj_faces(self.femmesh, self.femelement_table, self.femnodes_ele_table, femobj)
            # print(len(pressure_faces))
            femobj['PressureFaces'] = [(femobj['Object'].Name + ': face load', pressure_faces)]
            FreeCAD.Console.PrintMessage(femobj['PressureFaces'])
            FreeCAD.Console.PrintMessage('\n')
Example #6
0
 def get_solid_element_sets(self, femobjs):
     # get element ids and write them into the femobj
     all_found = False
     if self.femmesh.GroupCount:
         all_found = meshtools.get_femelement_sets_from_group_data(
             self.femmesh, femobjs)
         FreeCAD.Console.PrintMessage(all_found)
         FreeCAD.Console.PrintMessage("\n")
     if all_found is False:
         if not self.femelement_table:
             self.femelement_table = meshtools.get_femelement_table(
                 self.femmesh)
         # we're going to use the binary search for get_femelements_by_femnodes()
         # thus we need the parameter values self.femnodes_ele_table
         if not self.femnodes_mesh:
             self.femnodes_mesh = self.femmesh.Nodes
         if not self.femnodes_ele_table:
             self.femnodes_ele_table = meshtools.get_femnodes_ele_table(
                 self.femnodes_mesh, self.femelement_table)
         control = meshtools.get_femelement_sets(self.femmesh,
                                                 self.femelement_table,
                                                 femobjs,
                                                 self.femnodes_ele_table)
         # we only need to set it, if it is still True
         if (self.femelement_count_test is True) and (control is False):
             self.femelement_count_test = False
Example #7
0
 def get_material_elements(self):
     # it only works if either Volumes or Shellthicknesses or Beamsections are in the material objects
     # it means it does not work for mixed meshes and multiple materials, this is checked in check_prerequisites
     # the femelement_table is only calculated for the highest dimension in get_femelement_table
     FreeCAD.Console.PrintMessage('Materials\n')
     if self.femmesh.Volumes:
         # we only could do this for volumes, if a mesh contains volumes we're going to use them in the analysis
         # but a mesh could contain the element faces of the volumes as faces and the edges of the faces as edges,
         # there we have to check of some geometric objects
         all_found = False
         if self.femmesh.GroupCount:
             all_found = FemMeshTools.get_femelement_sets_from_group_data(self.femmesh, self.material_objects)
             FreeCAD.Console.PrintMessage(all_found)
             FreeCAD.Console.PrintMessage('\n')
         if all_found is False:
             if not self.femelement_table:
                 self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh)
             # we're going to use the binary search for get_femelements_by_femnodes()
             # thus we need the parameter values self.femnodes_ele_table
             if not self.femnodes_mesh:
                 self.femnodes_mesh = self.femmesh.Nodes
             if not self.femnodes_ele_table:
                 self.femnodes_ele_table = FemMeshTools.get_femnodes_ele_table(self.femnodes_mesh, self.femelement_table)
             control = FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects, self.femnodes_ele_table)
             if (self.femelement_count_test is True) and (control is False):  # we only need to set it, if it is still True
                 self.femelement_count_test = False
     if self.shellthickness_objects:
         if not self.femelement_faces_table:
             self.femelement_faces_table = FemMeshTools.get_femelement_faces_table(self.femmesh)
         FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_faces_table, self.material_objects)
     if self.beamsection_objects or self.fluidsection_objects:
         if not self.femelement_edges_table:
             self.femelement_edges_table = FemMeshTools.get_femelement_edges_table(self.femmesh)
         FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_edges_table, self.material_objects)
Example #8
0
    def get_constraints_tie_faces(self):
        if not self.femnodes_mesh:
            self.femnodes_mesh = self.femmesh.Nodes
        if not self.femelement_table:
            self.femelement_table = meshtools.get_femelement_table(
                self.femmesh)
        if not self.femnodes_ele_table:
            self.femnodes_ele_table = meshtools.get_femnodes_ele_table(
                self.femnodes_mesh, self.femelement_table)

        for femobj in self.tie_objects:
            # femobj --> dict, FreeCAD document object is femobj["Object"]
            print_obj_info(femobj["Object"])
            slave_faces, master_faces = meshtools.get_tie_obj_faces(
                self.femmesh, self.femelement_table, self.femnodes_ele_table,
                femobj)
            # [ele_id, ele_face_id], [ele_id, ele_face_id], ...]
            # whereas the ele_face_id might be ccx specific
            femobj["TieSlaveFaces"] = slave_faces
            femobj["TieMasterFaces"] = master_faces
Example #9
0
    def get_constraints_pressure_faces(self):
        # TODO see comments in get_constraints_force_nodeloads()
        # it applies here too. Mhh it applies to all constraints ...

        """
        # depreciated version
        # get the faces and face numbers
        for femobj in self.pressure_objects:
            # femobj --> dict, FreeCAD document object is femobj["Object"]
            femobj["PressureFaces"] = meshtools.get_pressure_obj_faces_depreciated(
                self.femmesh,
                femobj
            )
            # print(femobj["PressureFaces"])
        """

        if not self.femnodes_mesh:
            self.femnodes_mesh = self.femmesh.Nodes
        if not self.femelement_table:
            self.femelement_table = meshtools.get_femelement_table(self.femmesh)
        if not self.femnodes_ele_table:
            self.femnodes_ele_table = meshtools.get_femnodes_ele_table(
                self.femnodes_mesh,
                self.femelement_table
            )

        for femobj in self.pressure_objects:
            # femobj --> dict, FreeCAD document object is femobj["Object"]
            print_obj_info(femobj["Object"])
            pressure_faces = meshtools.get_pressure_obj_faces(
                self.femmesh,
                self.femelement_table,
                self.femnodes_ele_table, femobj
            )
            # the data model is for compatibility reason with depreciated version
            # get_pressure_obj_faces_depreciated returns the face ids in a tuple per ref_shape
            # some_string was the reference_shape_element_string in depreciated method
            # [(some_string, [ele_id, ele_face_id], [ele_id, ele_face_id], ...])]
            some_string = "{}: face load".format(femobj["Object"].Name)
            femobj["PressureFaces"] = [(some_string, pressure_faces)]
            FreeCAD.Console.PrintLog("{}\n".format(femobj["PressureFaces"]))
Example #10
0
    def get_constraints_contact_faces(self):
        if not self.member.cons_contact:
            return
        if not self.femnodes_mesh:
            self.femnodes_mesh = self.femmesh.Nodes
        if not self.femelement_table:
            self.femelement_table = meshtools.get_femelement_table(
                self.femmesh)
        if not self.femnodes_ele_table:
            self.femnodes_ele_table = meshtools.get_femnodes_ele_table(
                self.femnodes_mesh, self.femelement_table)

        for femobj in self.member.cons_contact:
            # femobj --> dict, FreeCAD document object is femobj["Object"]
            print_obj_info(femobj["Object"])
            contact_slave_faces, contact_master_faces = meshtools.get_contact_obj_faces(
                self.femmesh, self.femelement_table, self.femnodes_ele_table,
                femobj)
            # [ele_id, ele_face_id], [ele_id, ele_face_id], ...]
            # whereas the ele_face_id might be ccx specific
            femobj["ContactSlaveFaces"] = contact_slave_faces
            femobj["ContactMasterFaces"] = contact_master_faces
Example #11
0
def setUpInput(doc, mesh, analysis):

    analysis = doc.getObject("Analysis")

    # create connextivity array elnodes for mapping local node number -> global node number
    elnodes = np.array([mesh.getElementNodes(el) for el in mesh.Volumes
                        ])  # elnodes[elementIndex] = [node1,...,Node10]
    elo = dict(zip(mesh.Volumes, range(len(
        mesh.Volumes))))  # elo : {elementNumber : elementIndex}

    # create nodal coordinate array nocoord for node number -> (x,y,z)
    nocoord = np.asarray(mesh.Nodes.values()
                         )  # nocoord[nodeIndex] = [x-coord, y-coord, z-coord]

    # create element material array: materialbyElement maps element number -> E, nu
    materials_lin = gsm(analysis, 'Fem::Material')
    fiwc = iw(analysis, doc.CalculiXccxTools, doc.FEMMeshGmsh, materials_lin,
              None, None, None, None, None, None, None, None, None, None, None,
              None, None, None, None, None, None)
    fiwc.get_material_elements()
    materialbyElement = []
    po_keys = []  # parentobject[el] = parent material object for element el
    po_values = []
    counter = 0
    for object in fiwc.material_objects:
        E = float(
            App.Units.Quantity(
                object['Object'].Material['YoungsModulus']).getValueAs('MPa'))
        Nu = float(object['Object'].Material['PoissonRatio'])
        for el in object['FEMElements']:
            po_keys.append(el)
            po_values.append(object['Object'].Name)
            counter += 1
            materialbyElement.append([
                el, E, Nu
            ])  # materialbyElement[elementIndex] = [elementNumber, E, Nu]
    parentobject = dict(zip(po_keys, po_values))

    # determine elements connected to a node using FC API
    fet = mt.get_femelement_table(
        mesh
    )  # fet is dictionary: { elementid : [ nodeid, nodeid, ... , nodeid ] }
    net = mt.get_femnodes_ele_table(
        mesh.Nodes, fet
    )  # net is dictionary: {nodeID : [[eleID, NodePosition], [], ...], nodeID : [[], [], ...], ...}

    # set up interface element connectivity
    nodecount = len(nocoord)
    twins = {}  # twins : {oldnode : [newnode, face number]}
    interface_elements = []
    for obj in App.ActiveDocument.Objects:
        if obj.Name == "BooleanFragments":
            num_BF_els = len(App.ActiveDocument.BooleanFragments.Objects)
            num_Mat_obs = len(fiwc.material_objects)
            if num_BF_els != num_Mat_obs:
                print(
                    "Each BooleanFragment element needs its own material object"
                )
                raise SystemExit()
            shapecontacts = []
            tk = []
            tv = []
            contactnum = 0  # number of contact faces between BooleanFragment elements
            for index, obj1 in enumerate(obj.Objects):
                for obj1face in obj1.Shape.Faces:
                    el1faces = np.asarray(mesh.getFacesByFace(obj1face))
                    for obj2 in obj.Objects[index + 1:]:
                        for obj2face in obj2.Shape.Faces:
                            el2faces = np.asarray(
                                mesh.getFacesByFace(obj2face))
                            contact = np.intersect1d(
                                el1faces, el2faces
                            )  # all volume element contact faces between obj1 and obj2
                            if contact != []:
                                contactnum += 1
                                npflist = []
                                shapecontacts.append(
                                    contact
                                )  # all volume element contact faces
                                for contactface in contact:
                                    npflist.append(
                                        mesh.getElementNodes(contactface)
                                    )  # all nodes at the contact between obj1 and obj2
                                # flatten npflist and remove duplicate nodes
                                cn = list(
                                    set([
                                        node for npf in npflist for node in npf
                                    ]))
                                cn.sort()
                                for node in cn:
                                    if node not in tk:
                                        nodecount += 1
                                        tk.append(
                                            int(node)
                                        )  # add an existing contact node to interface dict
                                        tv.append(
                                            [nodecount, contactnum]
                                        )  # add a new contact node (nodecount) to interface dict and the contact (contactnum) it is a member of
                                        nocoord = np.append(
                                            nocoord, [nocoord[node - 1]],
                                            axis=0
                                        )  # add coordinates for new nodes

            twins = dict(zip(tk,
                             tv))  # twins : {oldnode : [newnode, face number]}
            print("\nInterface twins: {}".format(twins))

            for facecontacts in shapecontacts:
                for face in facecontacts:
                    nodeset1 = list(mesh.getElementNodes(face))
                    nodeset2 = []
                    for node in mesh.getElementNodes(face):
                        nodeset2.append(twins[node][0])
                    interface_elements.append(
                        nodeset1 + nodeset2
                    )  # interface_elements[index] = [oldnode1,..,oldnode6, newnode1,..,newnode6]

            interface_elements = np.asarray(
                interface_elements
            )  # add interface elements for the face between obj1 and obj2

    print("number of interface elements: {}".format(len(interface_elements)))
    for ie in interface_elements:
        print(ie)

    # reconnect volume elements to new interface nodes
    if interface_elements != []:
        membership = [""] * contactnum
        shiftelements = []  # reconnected elements
        for node in twins:
            if membership[twins[node][1] - 1] == "":
                membership[twins[node][1] - 1] = parentobject[net[node][0][
                    0]]  # elements that will stay with old nodes are in membership material object
            for element in net[node]:
                elnum = element[0]  # element number
                if parentobject[elnum] != membership[
                        twins[node][1] - 1]:  # reconnect element to new nodes
                    nonum = int(
                        math.log(element[1], 2)
                    )  # local node number from binary node number net[node][1]
                    shiftelements.append(elo[elnum])
                    elnodes[elo[elnum]][nonum] = twins[node][
                        0]  # connect element to new nodes

    noce = np.zeros((len(nocoord)), dtype=np.int16)
    for inno in range(len(nocoord)):
        i, j = np.where(elnodes == inno + 1)
        noce[inno] = len(i)

    # create boundary condition array dispfaces
    dispfaces = []
    for obj in App.ActiveDocument.Objects:
        if obj.isDerivedFrom('Fem::ConstraintDisplacement'):
            bcnodes = []
            bctype = [obj.xFree, obj.yFree, obj.zFree]
            bcvalue = [obj.xDisplacement, obj.yDisplacement, obj.zDisplacement]
            for part, boundaries in obj.References:
                for boundary in boundaries:
                    ref = part.Shape.getElement(boundary)
                    if type(ref) == Part.Vertex:
                        bc = mesh.getNodesByVertex(ref)
                        for bcn in bc:
                            bcnodes.append(bcn)
                    elif type(ref) == Part.Edge:
                        bc = mesh.getNodesByEdge(ref)
                        for bcn in bc:
                            bcnodes.append(bcn)
                    elif type(ref) == Part.Face:
                        bc = mesh.getNodesByFace(ref)
                        for bcn in bc:
                            if bcn not in twins:
                                bcnodes.append(bcn)
                    else:
                        print("No Boundaries Found")
                    edge = list(set(bc) & set(twins))
                    interior = list(set(bc) - set(twins))
                    #print("\nset(bc) {}, \nset(twins) {}, \nedge of boundary: {}, \ninterior of boundary: {}".format(bc, twins, edge, interior))
                    for node in edge:
                        for elem in net[node]:
                            elnum = elo[elem[0]]
                            if list(set(elnodes[elnum]) & set(interior)) != []:
                                if elnum in shiftelements:
                                    bcnodes.append(twins[node][0])
                                else:
                                    bcnodes.append(node)

            bcnodes = list(
                dict.fromkeys(bcnodes))  #remove duplicates in bcnodes
            if bcnodes != []: dispfaces.append([bcnodes, bctype, bcvalue])

    # create loaded faces and their global node numbers
    loadfaces_keys = []
    loadfaces_values = []
    for obj in App.ActiveDocument.Objects:
        if obj.isDerivedFrom('Fem::ConstraintPressure'):
            if obj.Reversed:
                sign = 1
            else:
                sign = -1
            for part, boundaries in obj.References:
                for boundary in boundaries:
                    ref = part.Shape.getElement(boundary)
                    if type(ref) == Part.Face:
                        for faceID in mesh.getFacesByFace(ref):
                            loadfaces_keys.append(faceID)
                            loadfaces_values.append([
                                list(mesh.getElementNodes(faceID)),
                                sign * obj.Pressure
                            ])
                    else:
                        print("No Faces with Pressure Loads")
    loadfaces = dict(zip(loadfaces_keys, loadfaces_values))

    # re-order element nodes
    for el in elnodes:
        temp = el[1]
        el[1] = el[2]
        el[2] = temp
        temp = el[4]
        el[4] = el[6]
        el[6] = temp
        temp = el[8]
        el[8] = el[9]
        el[9] = temp

    return elnodes, nocoord, dispfaces, loadfaces, materialbyElement, interface_elements, noce