def checkSupported(self, allSupported): for m in self.analysis.Group: if FemUtils.is_of_type(m, "Fem::Constraint"): supported = False for sc in allSupported: if FemUtils.is_of_type(m, *sc): supported = True if not supported: self.report.warning( "Ignored unsupported constraint: %s" % m.Label) return True
def result_mesh_present(self): result_mesh = False analysis_members = FemGui.getActiveAnalysis().Group for o in analysis_members: if femutils.is_of_type(o, 'Fem::FemMeshResult'): result_mesh = True return result_mesh
def find_solver_analysis(self): # get the analysis the solver is in if self.solver.getParentGroup(): obj = self.solver.getParentGroup() if femutils.is_of_type(obj, "Fem::FemAnalysis"): self.analysis = obj if FreeCAD.GuiUp: FemGui.setActiveAnalysis(self.analysis)
def checkMeshType(self): mesh = femutils.get_single_member(self.analysis, "Fem::FemMeshObject") if not femutils.is_of_type(mesh, "Fem::FemMeshGmsh"): self.report.error( "Unsupported type of mesh. " "Mesh must be created with gmsh.") self.fail() return False return True
def _handleFluxsolver(self): activeIn = [] for equation in self.solver.Group: if femutils.is_of_type(equation, "Fem::FemEquationElmerFluxsolver"): if equation.References: activeIn = equation.References[0][1] else: activeIn = self._getAllBodies() solverSection = self._getFluxsolverSolver(equation) for body in activeIn: self._addSolver(body, solverSection)
def purge_results(analysis): for m in analysis.Group: if (m.isDerivedFrom('Fem::FemResultObject')): if m.Mesh and hasattr(m.Mesh, "Proxy") and m.Mesh.Proxy.Type == "Fem::FemMeshResult": analysis.Document.removeObject(m.Mesh.Name) analysis.Document.removeObject(m.Name) FreeCAD.ActiveDocument.recompute() # if analysis typ check is used result mesh without result obj is created in the analysis # we could run into trouble in one loop because we will delete objects and try to access them later for m in analysis.Group: if femutils.is_of_type(m, 'Fem::FemMeshResult'): analysis.Document.removeObject(m.Name) FreeCAD.ActiveDocument.recompute()
def find_analysis(self): import FemGui self.analysis = FemGui.getActiveAnalysis() if self.analysis: return found_analysis = False for m in FreeCAD.ActiveDocument.Objects: if femutils.is_of_type(m, "Fem::FemAnalysis"): if not found_analysis: self.analysis = m found_analysis = True else: self.analysis = None if self.analysis: FemGui.setActiveAnalysis(self.analysis)
def find_solver(self): found_solver_for_use = False for m in self.analysis.Group: if femutils.is_of_type(m, "Fem::FemSolverCalculixCcxTools"): # we are going to explicitly check for the ccx tools solver type only, # thus it is possible to have lots of framework solvers inside the analysis anyway # for some methods no solver is needed (purge_results) --> solver could be none # analysis has one solver and no solver was set --> use the one solver # analysis has more than one solver and no solver was set --> use solver none # analysis has no solver --> use solver none if not found_solver_for_use: # no solver was found before self.solver = m found_solver_for_use = True else: self.solver = None
def _handleHeat(self): activeIn = [] for equation in self.solver.Group: if FemUtils.is_of_type(equation, "Fem::FemEquationElmerHeat"): if equation.References: activeIn = equation.References[0][1] else: activeIn = self._getAllBodies() solverSection = self._getHeatSolver(equation) for body in activeIn: self._addSolver(body, solverSection) if activeIn: self._handleHeatConstants() self._handleHeatBndConditions() self._handleHeatInitial(activeIn) self._handleHeatBodyForces(activeIn) self._handleHeatMaterial(activeIn)
def _handleElectrostatic(self): activeIn = [] for equation in self.solver.Group: if FemUtils.is_of_type(equation, "Fem::FemEquationElmerElectrostatic"): if equation.References: activeIn = equation.References[0][1] else: activeIn = self._getAllBodies() solverSection = self._getElectrostaticSolver(equation) for body in activeIn: self._addSolver(body, solverSection) if activeIn: self._handleElectrostaticConstants() self._handleElectrostaticBndConditions() # self._handleElectrostaticInitial(activeIn) # self._handleElectrostaticBodyForces(activeIn) self._handleElectrostaticMaterial(activeIn)
def _handleElasticity(self): activeIn = [] for equation in self.solver.Group: if femutils.is_of_type(equation, "Fem::FemEquationElmerElasticity"): if equation.References: activeIn = equation.References[0][1] else: activeIn = self._getAllBodies() solverSection = self._getElasticitySolver(equation) for body in activeIn: self._addSolver(body, solverSection) if activeIn: self._handleElasticityConstants() self._handleElasticityBndConditions() self._handleElasticityInitial(activeIn) self._handleElasticityBodyForces(activeIn) self._handleElasticityMaterial(activeIn)
def _handleFlow(self): activeIn = [] for equation in self.solver.Group: if femutils.is_of_type(equation, "Fem::FemEquationElmerFlow"): if equation.References: activeIn = equation.References[0][1] else: activeIn = self._getAllBodies() solverSection = self._getFlowSolver(equation) for body in activeIn: self._addSolver(body, solverSection) if activeIn: self._handleFlowConstants() self._handleFlowBndConditions() self._handleFlowInitialVelocity(activeIn) # self._handleFlowInitial(activeIn) # self._handleFlowBodyForces(activeIn) self._handleFlowMaterial(activeIn) self._handleFlowEquation(activeIn)
def Activated(self): import feminout.importToolsFem as toolsFem import ObjectsFem analysis=None path = FreeCAD.getHomePath()+"/bin/" fName = path+'hFrame3DDfc.out' NodeList = {} MemberList = {} DisplacementList = {} NodeEndList = {} MemberEndList = {} ProjectDescription = '' nodes = {} results = [] mode_results = {} mode_disp = {} iFilled=[] nDisp=0 mDisp=0 numNode = 0 isDebug=1 #factor = 25.42 factor = 1 factorZoom = 100 #000000000000000000000000000000000000000000000000000000000000000000 femmesh = Fem.FemMesh() #femResult = Fem.FemResultObject() fp = open(fName) Frame3DD_file=fp.readlines() fp.close() tline=[] for line in Frame3DD_file: tline.append(line.strip()) for i in range(len(tline)): 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]) for id in range(numNode): # node iFilled.append(0) i=i+1 # = fp.readline().strip() i=i+1 # = fp.readline().strip() i=i+1 # = fp.readline().strip() if isDebug==1: 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 if isDebug==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) #if isDebug==1: # print ("") # print ("numFixedNode: "+str(numFixedNode)) if isDebug==1: print ("") 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) result_mesh_object = None result_mesh_object = ObjectsFem.makeMeshResult( FreeCAD.ActiveDocument, "ResultMesh" ) result_mesh_object.FemMesh = femmesh res_mesh_is_compacted = False nodenumbers_for_compacted_mesh = [] isElastic=0 isModal=0 for i in range(len(tline)): tStrDis="E L A S T I C S T I F F N E S S A N A L Y S I S via L D L' decomposition" if tline[i].strip() == tStrDis: #Console.PrintError("FEM: displacement found.\n") isElastic=1 if (isElastic==1 and isModal==0): tStrDis="Node X-dsp Y-dsp Z-dsp X-rot Y-rot Z-rot" if tline[i].strip() == tStrDis: #Console.PrintError("FEM: displacement found.\n") print ("") print ("Displacement"+str(nDisp)) for id in range(numNode): # node iFilled[id]=0 for id in range(numNode): # node #Node X-dsp Y-dsp Z-dsp X-rot Y-rot Z-rot #1 0.0 0.0 0.0 0.0 0.0 -0.001254 i=i+1 #print (tline[i]) dataNode = tline[i].split() #print (dataNode[0]+" "+str(numNode)) if (dataNode[0].isdigit()): elem = int(dataNode[0]) iFilled[elem-1] = 1 mode_disp_x = float(dataNode[1]) mode_disp_y = float(dataNode[2]) mode_disp_z = float(dataNode[3]) mode_disp[elem] = FreeCAD.Vector(mode_disp_x, mode_disp_y, mode_disp_z) else: break for id in range(numNode): # node if (iFilled[id] == 0): mode_disp[id+1] = FreeCAD.Vector(0., 0., 0.) #print (str(id)+" "+str(iFilled[id])) #mode_results["disp"+str(nDisp)] = mode_disp mode_results["disp"] = mode_disp mode_disp = {} nDisp+=1 # append mode_results to results and reset mode_result results.append(mode_results) mode_results = {} #mode shapes tStrDis="M O D A L A N A L Y S I S R E S U L T S" if tline[i].strip() == tStrDis: #Console.PrintError("FEM: displacement found.\n") isModal=1 if (isModal==1): tStrDis="Node X-dsp Y-dsp Z-dsp X-rot Y-rot Z-rot" if tline[i].strip() == tStrDis: #Console.PrintError("FEM: displacement found.\n") print ("") print ("Modal Displacement"+str(mDisp)) for id in range(numNode): # node iFilled[id]=0 for id in range(numNode): # node #Node X-dsp Y-dsp Z-dsp X-rot Y-rot Z-rot #1 0.0 0.0 0.0 0.0 0.0 -0.001254 #" %11.3e" #1 -1.#IOe+000 -1.#IOe+000 -1.#IOe+000 -1.#IOe+000 -1.#IOe+000 -1.#IOe+000 i=i+1 #print (tline[i]) dataNode = tline[i].split() #print (dataNode[0]+" "+str(numNode)) if (dataNode[0].isdigit()): elem = int(dataNode[0]) iFilled[elem-1] = 1 mode_disp_x = float(dataNode[1]) mode_disp_y = float(dataNode[2]) mode_disp_z = float(dataNode[3]) mode_disp[elem] = FreeCAD.Vector(mode_disp_x, mode_disp_y, mode_disp_z) else: break for id in range(numNode): # node if (iFilled[id] == 0): mode_disp[id+1] = FreeCAD.Vector(0., 0., 0.) #print (str(id)+" "+str(iFilled[id])) #mode_results["disp"+str(nDisp)] = mode_disp mode_results["disp"] = mode_disp mode_disp = {} mDisp+=1 # append mode_results to results and reset mode_result results.append(mode_results) mode_results = {} res_obj=[] iLC=0 iModal=0 results_name="Elastic" for result_set in 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) res_obj[iLC] = toolsFem.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
def update_objects(self): # [{'Object':materials_linear}, {}, ...] # [{'Object':materials_nonlinear}, {}, ...] # [{'Object':fixed_constraints, 'NodeSupports':bool}, {}, ...] # [{'Object':force_constraints, 'NodeLoad':value}, {}, ... # [{'Object':pressure_constraints, 'xxxxxxxx':value}, {}, ...] # [{'Object':temerature_constraints, 'xxxxxxxx':value}, {}, ...] # [{'Object':heatflux_constraints, 'xxxxxxxx':value}, {}, ...] # [{'Object':initialtemperature_constraints, 'xxxxxxxx':value}, {}, ...] # [{'Object':beam_sections, 'xxxxxxxx':value}, {}, ...] # [{'Object':beam_rotations, 'xxxxxxxx':value}, {}, ...] # [{'Object':fluid_sections, 'xxxxxxxx':value}, {}, ...] # [{'Object':shell_thicknesses, 'xxxxxxxx':value}, {}, ...] # [{'Object':contact_constraints, 'xxxxxxxx':value}, {}, ...] ## @var mesh # mesh of the analysis. Used to generate .inp file and to show results self.mesh = None ## @var materials_linear # list of linear materials from the analysis. Updated with update_objects self.materials_linear = self._get_several_member('Fem::Material') ## @var materials_nonlinear # list of nonlinear materials from the analysis. Updated with update_objects self.materials_nonlinear = self._get_several_member( 'Fem::MaterialMechanicalNonlinear') ## @var fixed_constraints # list of fixed constraints from the analysis. Updated with update_objects self.fixed_constraints = self._get_several_member( 'Fem::ConstraintFixed') ## @var selfweight_constraints # list of selfweight constraints from the analysis. Updated with update_objects self.selfweight_constraints = self._get_several_member( 'Fem::ConstraintSelfWeight') ## @var force_constraints # list of force constraints from the analysis. Updated with update_objects self.force_constraints = self._get_several_member( 'Fem::ConstraintForce') ## @var pressure_constraints # list of pressure constraints from the analysis. Updated with update_objects self.pressure_constraints = self._get_several_member( 'Fem::ConstraintPressure') ## @var beam_sections # list of beam sections from the analysis. Updated with update_objects self.beam_sections = self._get_several_member( 'Fem::FemElementGeometry1D') ## @var beam_rotations # list of beam rotations from the analysis. Updated with update_objects self.beam_rotations = self._get_several_member( 'Fem::FemElementRotation1D') ## @var fluid_sections # list of fluid sections from the analysis. Updated with update_objects self.fluid_sections = self._get_several_member( 'Fem::FemElementFluid1D') ## @var shell_thicknesses # list of shell thicknesses from the analysis. Updated with update_objects self.shell_thicknesses = self._get_several_member( 'Fem::FemElementGeometry2D') ## @var displacement_constraints # list of displacements for the analysis. Updated with update_objects self.displacement_constraints = self._get_several_member( 'Fem::ConstraintDisplacement') ## @var temperature_constraints # list of temperatures for the analysis. Updated with update_objects self.temperature_constraints = self._get_several_member( 'Fem::ConstraintTemperature') ## @var heatflux_constraints # list of heatflux constraints for the analysis. Updated with update_objects self.heatflux_constraints = self._get_several_member( 'Fem::ConstraintHeatflux') ## @var initialtemperature_constraints # list of initial temperatures for the analysis. Updated with update_objects self.initialtemperature_constraints = self._get_several_member( 'Fem::ConstraintInitialTemperature') ## @var planerotation_constraints # list of plane rotation constraints from the analysis. Updated with update_objects self.planerotation_constraints = self._get_several_member( 'Fem::ConstraintPlaneRotation') ## @var contact_constraints # list of contact constraints from the analysis. Updated with update_objects self.contact_constraints = self._get_several_member( 'Fem::ConstraintContact') ## @var transform_constraints # list of transform constraints from the analysis. Updated with update_objects self.transform_constraints = self._get_several_member( 'Fem::ConstraintTransform') found_solver_for_use = False for m in self.analysis.Group: if femutils.is_of_type(m, "Fem::FemSolverCalculixCcxTools"): # we are going to explicitly check for the ccx tools solver type only, # thus it is possible to have lots of framework solvers inside the analysis anyway # for some methods no solver is needed (purge_results) --> solver could be none # analysis has one solver and no solver was set --> use the one solver # analysis has more than one solver and no solver was set --> use solver none # analysis has no solver --> use solver none if not found_solver_for_use and not self.solver: # no solver was found before and no solver was set by constructor self.solver = m found_solver_for_use = True elif found_solver_for_use: self.solver = None # another solver was found --> We have more than one solver # we do not know which one to use, so we use none ! # FreeCAD.Console.PrintMessage('FEM: More than one solver in the analysis and no solver given to analyze. No solver is set!\n') elif m.isDerivedFrom("Fem::FemMeshObject"): if not self.mesh: self.mesh = m else: message = 'FEM: Multiple mesh in analysis not yet supported!' if FreeCAD.GuiUp: QtGui.QMessageBox.critical(None, "Missing prerequisite", message) raise Exception(message + '\n')
def Activated(self): import feminout.importToolsFem as toolsFem import ObjectsFem numNode = 0 numMember = 0 analysis = None iHfc = FreeCAD.ActiveDocument.getObject('hfc') if iHfc == None: ininame = "Mod/hfcMystran/hfcMystran.ini" inifile = FreeCAD.getHomePath() + ininame if os.path.exists(inifile): iniF = open(inifile, "r") path = iniF.readline() iniF.close() else: inipath = FreeCAD.getHomePath() try: filename = QFileDialog.getOpenFileName( None, QString.fromLocal8Bit("Read a Mystarn's neu file"), path, "*.neu") # PyQt4 except Exception: filename, Filter = PySide.QtGui.QFileDialog.getOpenFileName( None, "Read a Mystran's neu file", path, "*.neu") #PySide data = filename.split("/") n = len(data) path = "" for i in range(n - 1): path = path + data[i] + "/" fn = data[n - 1].split('.') filenameDat = path + fn[0] + '.dat' inifileOut = FreeCAD.getHomePath() + ininame iniFout = open(inifileOut, "w") iniFout.writelines(path) iniFout.close() else: path = iHfc.DatPath filenameDat = iHfc.DatFile filename = filenameDat[:len(filenameDat) - 3] + 'neu' print("Result: " + filename) #print (path) #fNameDat = path+'hfcMystran.dat' nodes_x = [] nodes_y = [] nodes_z = [] NodeList = {} MemberList = {} DisplacementList = {} NodeEndList = {} MemberEndList = {} ProjectDescription = '' nodes = {} results = [] mode_results = {} mode_disp = {} iFilled = [] mode_disp_id = [] mode_disp_x = [] mode_disp_y = [] mode_disp_z = [] nDisp = 0 mDisp = 0 isDebug = 1 #factor = 25.42 factor = 1 factorZoom = 100 #000000000000000000000000000000000000000000000000000000000000000000 fpDat = open(filenameDat) tline = [] for line in fpDat: aline = line.strip() if len(aline) == 0 or aline[0] == '$': continue else: tline.append(line.strip()) fpDat.close() for id in range(len(tline)): aline = tline[id].strip() data = aline.split() data1 = aline.split(",") #GRID 3004 0.750 0.500 0.000 126 if data[0] == 'GRID': #Fixed format # id cp x1 #GRID 10101 0 0.000 0.000 0.000 0 is8Byte = 1 if is8Byte == 1: tid = aline[8:16].strip() #cp=aline[17:24].strip() x = aline[24:32].strip() y = aline[32:40].strip() z = aline[40:48].strip() NodeList[tid] = Node(tid, float(x), float(y), float(z)) elif len(aline) == 48: tid = aline[6:24].strip() #print (tid) #x datax = aline[25:32].strip() #56-41=15 if len(datax) == 15: dataf = datax[1:12] datab = datax[13:15] x = dataf + 'E' + datab #56-41=15 else: x = datax #56-41=15 #print (x) #y datay = aline[33:40].strip() #56-41=15 if len(datay) == 15: dataf = datay[1:12] datab = datay[13:15] y = dataf + 'E' + datab #56-41=15 else: y = datax #56-41=15 #print (y) #z dataz = aline[40:48].strip() #56-41=15 #print (dataz) tsign = dataz[len(dataz) - 2] #print (tsign) if tsign == '-': dataf = dataz[:len(dataz) - 1 - 1] datab = dataz[len(dataz) - 1 - 1:] z = dataf + 'E' + datab #56-41=15 else: z = dataz #56-41=15 #print (str(id)+" "+str(x)+" "+str(y)+" "+str(z)) NodeList[tid] = Node(tid, float(x), float(y), float(z)) else: #NodeList[data[1].strip()] = Node(data[1].strip(), float(data[2].strip()), float(data[3].strip()), float(data[4].strip())) print('Grid') numNode = numNode + 1 #GRID* 1 0.00000E+00 0.00000E+00 if data[0] == 'GRID*': NodeList[data[1]] = Node(data[1], float(data[2]), float(data[3]), 0.0) numNode = numNode + 1 # Member 333333333333333333333333333333333333333 #CBAR 201 2 11 21 0.0 0.0 1.0 if data[0] == 'CBAR': MemberList[data[1].strip()] = MemberCBAR( data[1].strip(), data[3], data[4], data[0].strip()) numMember += 1 #CBEAM 9400 9401 9401 9402 0. 0. 1. if data[0] == 'CBEAM': MemberList[data[1].strip()] = MemberCBEAM( data[1].strip(), data[3], data[4], data[0].strip()) numMember += 1 #CROD, 418,418,8,3 if data[0] == 'CROD': MemberList[data[1].strip()] = MemberCROD( data[1].strip(), data[3], data[4], data[0].strip()) numMember += 1 #CROD, 418,418,8,3 if data1[0] == 'CROD': MemberList[data1[1].strip()] = MemberCROD( data1[1].strip(), data1[3], data1[4], data1[0].strip()) numMember += 1 #CTRIA3 24 91 1033 1032 1023 if data[0] == 'CTRIA3': MemberList[data[1].strip()] = MemberCTRIA3( data[1].strip(), data[3], data[4], data[5], data[0].strip()) numMember += 1 #CQUAD4 1001 1 1001 1002 2002 2001 if data[0] == 'CQUAD4': MemberList[data[1].strip()] = MemberCQUAD4( data[1].strip(), data[3], data[4], data[5], data[6], data[0].strip()) numMember += 1 #CQUAD8 16004 1 16007 16009 18009 18007 16008 17009 #18008 17007 if data[0] == 'CQUAD8': MemberList[data[1].strip()] = MemberCQUAD8( data[1].strip(), data[3], data[4], data[5], data[6], data[0].strip()) numMember += 1 #CTETRA 1 1 8 13 67 33 if data[0] == 'CTETRA': MemberList[data[1].strip()] = MemberCQUAD4( data[1].strip(), data[3], data[4], data[5], data[6], data[0].strip()) numMember += 1 # #CHEXA 10101 100 10101 10103 10303 10301 30101 30103+E 1 #+E 1 30303 30301 if data[0] == 'CHEXA': bline = tline[id + 1].strip() if len(aline) == 80: eid = aline[9:16].strip() pid = aline[17:24].strip() g1 = aline[25:32].strip() g2 = aline[33:40].strip() g3 = aline[41:48].strip() g4 = aline[49:56].strip() g5 = aline[57:64].strip() g6 = aline[65:72].strip() if aline[73:80] == bline[1:8]: g7 = bline[9:16].strip() g8 = bline[17:24].strip() #print (eid+" "+g1+" "+g2+" "+g3+" "+g4+" "+g5+" "+g6+" "+g7+" "+g8) MemberList[eid] = MemberCHEXA(eid, g1, g2, g3, g4, g5, g6, g7, g8, data[0].strip()) numMember += 1 #print (NodeList) #print (MemberList) 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)) # elements for id in MemberList: mtype = MemberList[id].mtype if mtype == 'CROD': n1 = int(MemberList[id].n1) n2 = int(MemberList[id].n2) femmesh.addEdge([n1, n2]) elif mtype == 'CBAR': n1 = int(MemberList[id].n1) n2 = int(MemberList[id].n2) femmesh.addEdge([n1, n2]) elif mtype == 'CBEAM': n1 = int(MemberList[id].n1) n2 = int(MemberList[id].n2) femmesh.addEdge([n1, n2]) elif mtype == 'CTRIA3': n1 = int(MemberList[id].n1) n2 = int(MemberList[id].n2) n3 = int(MemberList[id].n3) femmesh.addEdge([n1, n2]) femmesh.addEdge([n2, n3]) femmesh.addEdge([n3, n1]) #femmesh.addFace([n1,n2,n3]) elif mtype == 'CQUAD4': n1 = int(MemberList[id].n1) n2 = int(MemberList[id].n2) n3 = int(MemberList[id].n3) n4 = int(MemberList[id].n4) #print (str(n1)+" "+str(n2)+" "+str(n3)+" "+str(n4)) femmesh.addEdge([n1, n2]) femmesh.addEdge([n2, n3]) femmesh.addEdge([n3, n4]) femmesh.addEdge([n4, n1]) #femmesh.addFace([n1,n2,n3,n4]) elif mtype == 'CQUAD8': n1 = int(MemberList[id].n1) n2 = int(MemberList[id].n2) n3 = int(MemberList[id].n3) n4 = int(MemberList[id].n4) femmesh.addEdge([n1, n2]) femmesh.addEdge([n2, n3]) femmesh.addEdge([n3, n4]) femmesh.addEdge([n4, n1]) #femmesh.addFace([n1,n2,n3,n4]) elif mtype == 'CTETRA': n1 = int(MemberList[id].n1) n2 = int(MemberList[id].n2) n3 = int(MemberList[id].n3) n4 = int(MemberList[id].n4) femmesh.addEdge([n1, n2]) femmesh.addEdge([n2, n3]) femmesh.addEdge([n3, n4]) femmesh.addEdge([n4, n1]) #femmesh.addVolume([n1,n2,n3,n4]) elif mtype == 'CHEXA': n1 = int(MemberList[id].n1) n2 = int(MemberList[id].n2) n3 = int(MemberList[id].n3) n4 = int(MemberList[id].n4) n5 = int(MemberList[id].n5) n6 = int(MemberList[id].n6) n7 = int(MemberList[id].n7) n8 = int(MemberList[id].n8) femmesh.addEdge([n1, n2]) femmesh.addEdge([n2, n3]) femmesh.addEdge([n3, n4]) femmesh.addEdge([n4, n1]) femmesh.addEdge([n5, n6]) femmesh.addEdge([n6, n7]) femmesh.addEdge([n7, n8]) femmesh.addEdge([n8, n5]) femmesh.addEdge([n1, n5]) femmesh.addEdge([n2, n6]) femmesh.addEdge([n3, n7]) femmesh.addEdge([n4, n8]) #femmesh.addVolume([n1,n2,n3,n4,n5,n6,n7,n8]) else: print(mtype + ' Not supported yet') result_mesh_object = None result_mesh_object = ObjectsFem.makeMeshResult(FreeCAD.ActiveDocument, "ResultMesh") result_mesh_object.FemMesh = femmesh res_mesh_is_compacted = False nodenumbers_for_compacted_mesh = [] #femResult = Fem.FemResultObject() #-------------------------------------- fp = open(filename) tline = [] for line in fp: aline = line.strip() if len(aline) == 0 or aline[0] == '$': continue else: tline.append(line.strip()) fp.close() tStrDis1 = "T1 translation" tStrDis2 = "T2 translation" tStrDis3 = "T3 translation" for i in range(len(tline)): if tline[i].strip() == tStrDis1: #T1 translation # 0.000000E+00, 1.800000E-04, 1.800000E-04, # 10002, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 1, 7, 1, 7, # 1, 1, 1 i = i + 6 for id in range(numNode): # node #print (tline[i]) #1, 0.000000E+00, dataNode = tline[i].split(",") #print (dataNode[0]+" "+str(numNode)) mode_disp_id.append(int(dataNode[0])) mode_disp_x.append(float(dataNode[1])) i = i + 1 if tline[i].strip() == tStrDis2: #T1 translation # 0.000000E+00, 1.800000E-04, 1.800000E-04, # 10002, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 1, 7, 1, 7, # 1, 1, 1 i = i + 6 for id in range(numNode): # node #print (tline[i]) #1, 0.000000E+00, dataNode = tline[i].split(",") #print (dataNode[0]+" "+str(numNode)) mode_disp_y.append(float(dataNode[1])) i = i + 1 if tline[i].strip() == tStrDis3: #T1 translation # 0.000000E+00, 1.800000E-04, 1.800000E-04, # 10002, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 1, 7, 1, 7, # 1, 1, 1 i = i + 6 for id in range(numNode): # node #print (tline[i]) #1, 0.000000E+00, dataNode = tline[i].split(",") #print (dataNode[0]+" "+str(numNode)) mode_disp_z.append(float(dataNode[1])) i = i + 1 for id in range(numNode): # node #print (str(id)+" "+str(mode_disp_x[id])+" "+ str(mode_disp_y[id])+" "+str(mode_disp_z[id])) mode_disp[mode_disp_id[id]] = FreeCAD.Vector( mode_disp_x[id], mode_disp_y[id], mode_disp_z[id]) #mode_results["disp"+str(nDisp)] = mode_disp mode_results["disp"] = mode_disp mode_disp = {} #nDisp+=1 res_obj = [] iLC = 0 results_name = "Displacement" # append mode_results to results and reset mode_result results.append(mode_results) mode_results = {} for result_set in results: res_obj.append( ObjectsFem.makeResultMechanical(FreeCAD.ActiveDocument, results_name + str(iLC))) res_obj[iLC].Mesh = result_mesh_object #res_obj[iLC] = importToolsFem.fill_femresult_mechanical(res_obj[iLC], result_set) res_obj[iLC] = toolsFem.fill_femresult_mechanical( res_obj[iLC], result_set) # complementary result object calculations import femresult.resulttools as restools import femtools.femutils as femutils # 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]) #res_obj[iLC].ViewObject.DisplayMode = 'Uabs' FreeCAD.ActiveDocument.recompute() FreeCADGui.activeDocument().activeView().viewAxonometric() FreeCADGui.SendMsgToActiveView("ViewFit")
def purge_results(self): for m in membertools.get_member(self.analysis, "Fem::FemResultObject"): if femutils.is_of_type(m.Mesh, "Fem::FemMeshResult"): self.analysis.Document.removeObject(m.Mesh.Name) self.analysis.Document.removeObject(m.Name) FreeCAD.ActiveDocument.recompute()
def add_principal_stress_reinforced(res_obj): # # HarryvL: determine concrete / non-concrete nodes # ic = get_concrete_nodes(res_obj) # # calculate principal and max Shear and fill them in res_obj # prinstress1 = [] prinstress2 = [] prinstress3 = [] shearstress = [] ps1v = [] ps2v = [] ps3v = [] # # HarryvL: additional arrays to hold reinforcement ratios # and mohr coulomb stress # rhx = [] rhy = [] rhz = [] moc = [] # material parameter for obj in res_obj.getParentGroup().Group: if is_of_type(obj, "Fem::MaterialReinforced"): matrix_af = float( FreeCAD.Units.Quantity(obj.Material["AngleOfFriction"]).getValueAs("rad") ) matrix_cs = float( FreeCAD.Units.Quantity(obj.Material["CompressiveStrength"]).getValueAs("MPa") ) reinforce_yield = float( FreeCAD.Units.Quantity(obj.Reinforcement["YieldStrength"]).getValueAs("MPa") ) # print(matrix_af) # print(matrix_cs) # print(reinforce_yield) iterator = zip( res_obj.NodeStressXX, res_obj.NodeStressYY, res_obj.NodeStressZZ, res_obj.NodeStressXY, res_obj.NodeStressXZ, res_obj.NodeStressYZ ) for isv, stress_tensor in enumerate(iterator): rhox = 0. rhoy = 0. rhoz = 0. mc = 0. if ic[isv] == 1: # # HarryvL: for concrete scxx etc. are affected by # reinforcement (see calculate_rho(stress_tensor)). for all other # materials scxx etc. are the original stresses # rhox, rhoy, rhoz = calculate_rho( stress_tensor, reinforce_yield ) prin1, prin2, prin3, shear, psv = calculate_principal_stress_reinforced( stress_tensor ) prinstress1.append(prin1) prinstress2.append(prin2) prinstress3.append(prin3) shearstress.append(shear) ps1v.append(psv[0]) ps2v.append(psv[1]) ps3v.append(psv[2]) # # reinforcement ratios and mohr coulomb criterion # rhx.append(rhox) rhy.append(rhoy) rhz.append(rhoz) if ic[isv] == 1: mc = calculate_mohr_coulomb(prin1, prin3, matrix_af, matrix_cs) moc.append(mc) res_obj.PrincipalMax = prinstress1 res_obj.PrincipalMed = prinstress2 res_obj.PrincipalMin = prinstress3 res_obj.MaxShear = shearstress # # HarryvL: additional concrete and principal stress plot # results for use in _ViewProviderFemResultMechanical # res_obj.ReinforcementRatio_x = rhx res_obj.ReinforcementRatio_y = rhy res_obj.ReinforcementRatio_z = rhz res_obj.MohrCoulomb = moc res_obj.PS1Vector = ps1v res_obj.PS2Vector = ps2v res_obj.PS3Vector = ps3v FreeCAD.Console.PrintMessage( "Added principal stress and max shear values as well as" "reinforcment rations, Mohr Coloumb values.\n" ) return res_obj
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 from femtools import femutils if not res_obj.MassFlowRate: # information 1: # only compact result if not Flow 1D results # compact result object, workaround for bug 2873 # https://www.freecadweb.org/tracker/view.php?id=2873 # information 2: # if the result data has multiple result sets there will be multiple result objs # they all will use one mesh obj # on the first res obj fill the mesh obj will be compacted, thus # it does not need to be compacted on further result sets # but NodeNumbers need to be compacted for every result set (res object fill) # example frd file: https://forum.freecadweb.org/viewtopic.php?t=32649#p274291 if res_mesh_is_compacted is False: # first result set, compact FemMesh and NodeNumbers res_obj = 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
def update_objects(self): # [{'Object':materials_linear}, {}, ...] # [{'Object':materials_nonlinear}, {}, ...] # [{'Object':fixed_constraints, 'NodeSupports':bool}, {}, ...] # [{'Object':force_constraints, 'NodeLoad':value}, {}, ... # [{'Object':pressure_constraints, 'xxxxxxxx':value}, {}, ...] # [{'Object':temerature_constraints, 'xxxxxxxx':value}, {}, ...] # [{'Object':heatflux_constraints, 'xxxxxxxx':value}, {}, ...] # [{'Object':initialtemperature_constraints, 'xxxxxxxx':value}, {}, ...] # [{'Object':beam_sections, 'xxxxxxxx':value}, {}, ...] # [{'Object':beam_rotations, 'xxxxxxxx':value}, {}, ...] # [{'Object':fluid_sections, 'xxxxxxxx':value}, {}, ...] # [{'Object':shell_thicknesses, 'xxxxxxxx':value}, {}, ...] # [{'Object':contact_constraints, 'xxxxxxxx':value}, {}, ...] ## @var mesh # mesh of the analysis. Used to generate .inp file and to show results self.mesh = None ## @var materials_linear # list of linear materials from the analysis. Updated with update_objects self.materials_linear = self._get_several_member('Fem::Material') ## @var materials_nonlinear # list of nonlinear materials from the analysis. Updated with update_objects self.materials_nonlinear = self._get_several_member('Fem::MaterialMechanicalNonlinear') ## @var fixed_constraints # list of fixed constraints from the analysis. Updated with update_objects self.fixed_constraints = self._get_several_member('Fem::ConstraintFixed') ## @var selfweight_constraints # list of selfweight constraints from the analysis. Updated with update_objects self.selfweight_constraints = self._get_several_member('Fem::ConstraintSelfWeight') ## @var force_constraints # list of force constraints from the analysis. Updated with update_objects self.force_constraints = self._get_several_member('Fem::ConstraintForce') ## @var pressure_constraints # list of pressure constraints from the analysis. Updated with update_objects self.pressure_constraints = self._get_several_member('Fem::ConstraintPressure') ## @var beam_sections # list of beam sections from the analysis. Updated with update_objects self.beam_sections = self._get_several_member('Fem::FemElementGeometry1D') ## @var beam_rotations # list of beam rotations from the analysis. Updated with update_objects self.beam_rotations = self._get_several_member('Fem::FemElementRotation1D') ## @var fluid_sections # list of fluid sections from the analysis. Updated with update_objects self.fluid_sections = self._get_several_member('Fem::FemElementFluid1D') ## @var shell_thicknesses # list of shell thicknesses from the analysis. Updated with update_objects self.shell_thicknesses = self._get_several_member('Fem::FemElementGeometry2D') ## @var displacement_constraints # list of displacements for the analysis. Updated with update_objects self.displacement_constraints = self._get_several_member('Fem::ConstraintDisplacement') ## @var temperature_constraints # list of temperatures for the analysis. Updated with update_objects self.temperature_constraints = self._get_several_member('Fem::ConstraintTemperature') ## @var heatflux_constraints # list of heatflux constraints for the analysis. Updated with update_objects self.heatflux_constraints = self._get_several_member('Fem::ConstraintHeatflux') ## @var initialtemperature_constraints # list of initial temperatures for the analysis. Updated with update_objects self.initialtemperature_constraints = self._get_several_member('Fem::ConstraintInitialTemperature') ## @var planerotation_constraints # list of plane rotation constraints from the analysis. Updated with update_objects self.planerotation_constraints = self._get_several_member('Fem::ConstraintPlaneRotation') ## @var contact_constraints # list of contact constraints from the analysis. Updated with update_objects self.contact_constraints = self._get_several_member('Fem::ConstraintContact') ## @var transform_constraints # list of transform constraints from the analysis. Updated with update_objects self.transform_constraints = self._get_several_member('Fem::ConstraintTransform') found_solver_for_use = False for m in self.analysis.Group: if femutils.is_of_type(m, "Fem::FemSolverCalculixCcxTools"): # we are going to explicitly check for the ccx tools solver type only, # thus it is possible to have lots of framework solvers inside the analysis anyway # for some methods no solver is needed (purge_results) --> solver could be none # analysis has one solver and no solver was set --> use the one solver # analysis has more than one solver and no solver was set --> use solver none # analysis has no solver --> use solver none if not found_solver_for_use and not self.solver: # no solver was found before and no solver was set by constructor self.solver = m found_solver_for_use = True elif found_solver_for_use: self.solver = None # another solver was found --> We have more than one solver # we do not know which one to use, so we use none ! # FreeCAD.Console.PrintMessage('FEM: More than one solver in the analysis and no solver given to analyze. No solver is set!\n') elif m.isDerivedFrom("Fem::FemMeshObject"): if not self.mesh: self.mesh = m else: message = 'FEM: Multiple mesh in analysis not yet supported!' if FreeCAD.GuiUp: QtGui.QMessageBox.critical(None, "Missing prerequisite", message) raise Exception(message + '\n')
def test_femobjects_isoftype(self): doc = self.active_doc from femtools.femutils import is_of_type self.assertTrue( is_of_type(ObjectsFem.makeAnalysis(doc), 'Fem::FemAnalysis')) self.assertTrue( is_of_type(ObjectsFem.makeConstraintBearing(doc), 'Fem::ConstraintBearing')) self.assertTrue( is_of_type(ObjectsFem.makeConstraintBodyHeatSource(doc), 'Fem::ConstraintBodyHeatSource')) self.assertTrue( is_of_type(ObjectsFem.makeConstraintContact(doc), 'Fem::ConstraintContact')) self.assertTrue( is_of_type(ObjectsFem.makeConstraintDisplacement(doc), 'Fem::ConstraintDisplacement')) self.assertTrue( is_of_type(ObjectsFem.makeConstraintElectrostaticPotential(doc), 'Fem::ConstraintElectrostaticPotential')) self.assertTrue( is_of_type(ObjectsFem.makeConstraintFixed(doc), 'Fem::ConstraintFixed')) self.assertTrue( is_of_type(ObjectsFem.makeConstraintFlowVelocity(doc), 'Fem::ConstraintFlowVelocity')) self.assertTrue( is_of_type(ObjectsFem.makeConstraintFluidBoundary(doc), 'Fem::ConstraintFluidBoundary')) self.assertTrue( is_of_type(ObjectsFem.makeConstraintForce(doc), 'Fem::ConstraintForce')) self.assertTrue( is_of_type(ObjectsFem.makeConstraintGear(doc), 'Fem::ConstraintGear')) self.assertTrue( is_of_type(ObjectsFem.makeConstraintHeatflux(doc), 'Fem::ConstraintHeatflux')) self.assertTrue( is_of_type(ObjectsFem.makeConstraintInitialFlowVelocity(doc), 'Fem::ConstraintInitialFlowVelocity')) self.assertTrue( is_of_type(ObjectsFem.makeConstraintInitialTemperature(doc), 'Fem::ConstraintInitialTemperature')) self.assertTrue( is_of_type(ObjectsFem.makeConstraintPlaneRotation(doc), 'Fem::ConstraintPlaneRotation')) self.assertTrue( is_of_type(ObjectsFem.makeConstraintPressure(doc), 'Fem::ConstraintPressure')) self.assertTrue( is_of_type(ObjectsFem.makeConstraintPulley(doc), 'Fem::ConstraintPulley')) self.assertTrue( is_of_type(ObjectsFem.makeConstraintSelfWeight(doc), 'Fem::ConstraintSelfWeight')) self.assertTrue( is_of_type(ObjectsFem.makeConstraintTemperature(doc), 'Fem::ConstraintTemperature')) self.assertTrue( is_of_type(ObjectsFem.makeConstraintTransform(doc), 'Fem::ConstraintTransform')) self.assertTrue( is_of_type(ObjectsFem.makeElementFluid1D(doc), 'Fem::FemElementFluid1D')) self.assertTrue( is_of_type(ObjectsFem.makeElementGeometry1D(doc), 'Fem::FemElementGeometry1D')) self.assertTrue( is_of_type(ObjectsFem.makeElementGeometry2D(doc), 'Fem::FemElementGeometry2D')) self.assertTrue( is_of_type(ObjectsFem.makeElementRotation1D(doc), 'Fem::FemElementRotation1D')) materialsolid = ObjectsFem.makeMaterialSolid(doc) self.assertTrue( is_of_type(ObjectsFem.makeMaterialFluid(doc), 'Fem::Material')) self.assertTrue(is_of_type(materialsolid, 'Fem::Material')) self.assertTrue( is_of_type( ObjectsFem.makeMaterialMechanicalNonlinear(doc, materialsolid), 'Fem::MaterialMechanicalNonlinear')) mesh = ObjectsFem.makeMeshGmsh(doc) self.assertTrue(is_of_type(mesh, 'Fem::FemMeshGmsh')) self.assertTrue( is_of_type(ObjectsFem.makeMeshBoundaryLayer(doc, mesh), 'Fem::FemMeshBoundaryLayer')) self.assertTrue( is_of_type(ObjectsFem.makeMeshGroup(doc, mesh), 'Fem::FemMeshGroup')) self.assertTrue( is_of_type(ObjectsFem.makeMeshRegion(doc, mesh), 'Fem::FemMeshRegion')) self.assertTrue( is_of_type(ObjectsFem.makeMeshNetgen(doc), 'Fem::FemMeshShapeNetgenObject')) self.assertTrue( is_of_type(ObjectsFem.makeMeshResult(doc), 'Fem::FemMeshResult')) self.assertTrue( is_of_type(ObjectsFem.makeResultMechanical(doc), 'Fem::FemResultMechanical')) solverelmer = ObjectsFem.makeSolverElmer(doc) self.assertTrue( is_of_type(ObjectsFem.makeSolverCalculixCcxTools(doc), 'Fem::FemSolverCalculixCcxTools')) self.assertTrue( is_of_type(ObjectsFem.makeSolverCalculix(doc), 'Fem::FemSolverObjectCalculix')) self.assertTrue(is_of_type(solverelmer, 'Fem::FemSolverObjectElmer')) self.assertTrue( is_of_type(ObjectsFem.makeSolverZ88(doc), 'Fem::FemSolverObjectZ88')) self.assertTrue( is_of_type(ObjectsFem.makeEquationElasticity(doc, solverelmer), 'Fem::FemEquationElmerElasticity')) self.assertTrue( is_of_type(ObjectsFem.makeEquationElectrostatic(doc, solverelmer), 'Fem::FemEquationElmerElectrostatic')) self.assertTrue( is_of_type(ObjectsFem.makeEquationFlow(doc, solverelmer), 'Fem::FemEquationElmerFlow')) self.assertTrue( is_of_type(ObjectsFem.makeEquationFluxsolver(doc, solverelmer), 'Fem::FemEquationElmerFluxsolver')) self.assertTrue( is_of_type(ObjectsFem.makeEquationHeat(doc, solverelmer), 'Fem::FemEquationElmerHeat'))
def purge_results(self): for m in femutils.get_member(self.analysis, "Fem::FemResultObject"): if femutils.is_of_type(m.Mesh, "Fem::FemMeshResult"): self.analysis.Document.removeObject(m.Mesh.Name) self.analysis.Document.removeObject(m.Name) FreeCAD.ActiveDocument.recompute()
def importFrd(filename, analysis=None, result_name_prefix=None): from . import importToolsFem import ObjectsFem if result_name_prefix is None: result_name_prefix = '' m = read_frd_result(filename) result_mesh_object = None if len(m['Nodes']) > 0: if analysis: analysis_object = analysis 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']) FreeCAD.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_object.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 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 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 = ( "We have nodes but no results in frd file, " "which means we only have a mesh in frd file. " "Usually this happens for analysis type 'NOANALYSIS' " "or if CalculiX returned no results because " "of nonpositive jacobian determinant in at least one element.\n" ) FreeCAD.Console.PrintMessage(error_message) if analysis: analysis_object.addObject(result_mesh_object) if FreeCAD.GuiUp: if analysis: import FemGui FemGui.setActiveAnalysis(analysis_object) FreeCAD.ActiveDocument.recompute() else: FreeCAD.Console.PrintError( 'Problem on frd file import. No nodes found in frd file.\n') return res_obj
def test_femobjects_isoftype(self): doc = self.active_doc from femtools.femutils import is_of_type self.assertTrue(is_of_type(ObjectsFem.makeAnalysis(doc), 'Fem::FemAnalysis')) self.assertTrue(is_of_type(ObjectsFem.makeConstraintBearing(doc), 'Fem::ConstraintBearing')) self.assertTrue(is_of_type(ObjectsFem.makeConstraintBodyHeatSource(doc), 'Fem::ConstraintBodyHeatSource')) self.assertTrue(is_of_type(ObjectsFem.makeConstraintContact(doc), 'Fem::ConstraintContact')) self.assertTrue(is_of_type(ObjectsFem.makeConstraintDisplacement(doc), 'Fem::ConstraintDisplacement')) self.assertTrue(is_of_type(ObjectsFem.makeConstraintElectrostaticPotential(doc), 'Fem::ConstraintElectrostaticPotential')) self.assertTrue(is_of_type(ObjectsFem.makeConstraintFixed(doc), 'Fem::ConstraintFixed')) self.assertTrue(is_of_type(ObjectsFem.makeConstraintFlowVelocity(doc), 'Fem::ConstraintFlowVelocity')) self.assertTrue(is_of_type(ObjectsFem.makeConstraintFluidBoundary(doc), 'Fem::ConstraintFluidBoundary')) self.assertTrue(is_of_type(ObjectsFem.makeConstraintForce(doc), 'Fem::ConstraintForce')) self.assertTrue(is_of_type(ObjectsFem.makeConstraintGear(doc), 'Fem::ConstraintGear')) self.assertTrue(is_of_type(ObjectsFem.makeConstraintHeatflux(doc), 'Fem::ConstraintHeatflux')) self.assertTrue(is_of_type(ObjectsFem.makeConstraintInitialFlowVelocity(doc), 'Fem::ConstraintInitialFlowVelocity')) self.assertTrue(is_of_type(ObjectsFem.makeConstraintInitialTemperature(doc), 'Fem::ConstraintInitialTemperature')) self.assertTrue(is_of_type(ObjectsFem.makeConstraintPlaneRotation(doc), 'Fem::ConstraintPlaneRotation')) self.assertTrue(is_of_type(ObjectsFem.makeConstraintPressure(doc), 'Fem::ConstraintPressure')) self.assertTrue(is_of_type(ObjectsFem.makeConstraintPulley(doc), 'Fem::ConstraintPulley')) self.assertTrue(is_of_type(ObjectsFem.makeConstraintSelfWeight(doc), 'Fem::ConstraintSelfWeight')) self.assertTrue(is_of_type(ObjectsFem.makeConstraintTemperature(doc), 'Fem::ConstraintTemperature')) self.assertTrue(is_of_type(ObjectsFem.makeConstraintTransform(doc), 'Fem::ConstraintTransform')) self.assertTrue(is_of_type(ObjectsFem.makeElementFluid1D(doc), 'Fem::FemElementFluid1D')) self.assertTrue(is_of_type(ObjectsFem.makeElementGeometry1D(doc), 'Fem::FemElementGeometry1D')) self.assertTrue(is_of_type(ObjectsFem.makeElementGeometry2D(doc), 'Fem::FemElementGeometry2D')) self.assertTrue(is_of_type(ObjectsFem.makeElementRotation1D(doc), 'Fem::FemElementRotation1D')) materialsolid = ObjectsFem.makeMaterialSolid(doc) self.assertTrue(is_of_type(ObjectsFem.makeMaterialFluid(doc), 'Fem::Material')) self.assertTrue(is_of_type(materialsolid, 'Fem::Material')) self.assertTrue(is_of_type(ObjectsFem.makeMaterialMechanicalNonlinear(doc, materialsolid), 'Fem::MaterialMechanicalNonlinear')) mesh = ObjectsFem.makeMeshGmsh(doc) self.assertTrue(is_of_type(mesh, 'Fem::FemMeshGmsh')) self.assertTrue(is_of_type(ObjectsFem.makeMeshBoundaryLayer(doc, mesh), 'Fem::FemMeshBoundaryLayer')) self.assertTrue(is_of_type(ObjectsFem.makeMeshGroup(doc, mesh), 'Fem::FemMeshGroup')) self.assertTrue(is_of_type(ObjectsFem.makeMeshRegion(doc, mesh), 'Fem::FemMeshRegion')) self.assertTrue(is_of_type(ObjectsFem.makeMeshNetgen(doc), 'Fem::FemMeshShapeNetgenObject')) self.assertTrue(is_of_type(ObjectsFem.makeMeshResult(doc), 'Fem::FemMeshResult')) self.assertTrue(is_of_type(ObjectsFem.makeResultMechanical(doc), 'Fem::FemResultMechanical')) solverelmer = ObjectsFem.makeSolverElmer(doc) self.assertTrue(is_of_type(ObjectsFem.makeSolverCalculixCcxTools(doc), 'Fem::FemSolverCalculixCcxTools')) self.assertTrue(is_of_type(ObjectsFem.makeSolverCalculix(doc), 'Fem::FemSolverObjectCalculix')) self.assertTrue(is_of_type(solverelmer, 'Fem::FemSolverObjectElmer')) self.assertTrue(is_of_type(ObjectsFem.makeSolverZ88(doc), 'Fem::FemSolverObjectZ88')) self.assertTrue(is_of_type(ObjectsFem.makeEquationElasticity(doc, solverelmer), 'Fem::FemEquationElmerElasticity')) self.assertTrue(is_of_type(ObjectsFem.makeEquationElectrostatic(doc, solverelmer), 'Fem::FemEquationElmerElectrostatic')) self.assertTrue(is_of_type(ObjectsFem.makeEquationFlow(doc, solverelmer), 'Fem::FemEquationElmerFlow')) self.assertTrue(is_of_type(ObjectsFem.makeEquationFluxsolver(doc, solverelmer), 'Fem::FemEquationElmerFluxsolver')) self.assertTrue(is_of_type(ObjectsFem.makeEquationHeat(doc, solverelmer), 'Fem::FemEquationElmerHeat'))
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))