def export( objectslist, filename ): "called when freecad exports an object to vtk" if len(objectslist) > 1: # the case of no selected obj is caught by FreeCAD already FreeCAD.Console.PrintError( "This exporter can only export one object at once\n" ) return obj = objectslist[0] if obj.isDerivedFrom("Fem::FemPostPipeline"): FreeCAD.Console.PrintError( 'Export of a VTK post object to vtk is not yet implemented !\n' ) return elif obj.isDerivedFrom("Fem::FemMeshObject"): FreeCAD.Console.PrintError( 'Use export to FEM mesh formats to export a FEM mesh object to vtk!\n' ) return elif obj.isDerivedFrom("Fem::FemResultObject"): Fem.writeResult(filename, obj) else: FreeCAD.Console.PrintError( 'Selected object is not supported by export to VTK.\n' ) return
def importVTK(filename, analysis=None, result_name_prefix=None): import ObjectsFem if result_name_prefix is None: result_name_prefix = '' if analysis is None: analysis_name = os.path.splitext(os.path.basename(filename))[0] analysis_object = ObjectsFem.makeAnalysis('Analysis') analysis_object.Label = analysis_name else: analysis_object = analysis # if properties can be added in FemVTKTools importCfdResult(), this file can be used for CFD workbench results_name = result_name_prefix + 'results' result_obj = ObjectsFem.makeResultMechanical(results_name) # result_obj = FreeCAD.ActiveDocument.addObject('Fem::FemResultObject', results_name) Fem.readResult(filename, result_obj.Name) # readResult always creates a new femmesh named ResultMesh # workaround for the DisplacementLengths (They should have been calculated by Fem.readResult) if not result_obj.DisplacementLengths: import importToolsFem result_obj.DisplacementLengths = importToolsFem.calculate_disp_abs(result_obj.DisplacementVectors) analysis_object.Member = analysis_object.Member + [result_obj] # FIXME move the ResultMesh in the analysis ''' seams not used at the moment
def importVtkFCResult(filename, resultname, analysis=None, result_name_prefix=None): # only fields from vtk are imported if they exactly named as the FreeCAD result properties # See _getFreeCADMechResultProperties() in FemVTKTools.cpp for the supported names import ObjectsFem from . import importToolsFem if result_name_prefix is None: result_name_prefix = '' if analysis: analysis_object = analysis results_name = result_name_prefix + 'results' result_obj = ObjectsFem.makeResultMechanical(FreeCAD.ActiveDocument, results_name) Fem.readResult(filename, result_obj.Name) # readResult always creates a new femmesh named ResultMesh # workaround for the DisplacementLengths (They should have been calculated by Fem.readResult) if not result_obj.DisplacementLengths: result_obj.DisplacementLengths = importToolsFem.calculate_disp_abs(result_obj.DisplacementVectors) FreeCAD.Console.PrintMessage('Recalculated DisplacementLengths.\n') ''' seems unused at the moment filenamebase = '.'.join(filename.split('.')[:-1]) # pattern: filebase_timestamp.vtk ts = filenamebase.split('_')[-1] try: time_step = float(ts) except: time_step = 0.0 ''' if analysis: analysis_object.addObject(result_obj) result_obj.touch() FreeCAD.ActiveDocument.recompute()
def export(objectslist, filename): "called when freecad exports a fem result object" if len(objectslist) != 1: FreeCAD.Console.PrintError("This exporter can only export one object at once\n") return obj = objectslist[0] if not obj.isDerivedFrom("Fem::FemResultObject"): FreeCAD.Console.PrintError("object selcted is not FemResultObject.\n") return Fem.writeResult(filename, obj)
def test_tetra10_vkt(self): # tetra10 element: reading from and writing to unv mesh file format filetyp = 'vtk' outfile = self.base_outfile + filetyp testfile = self.base_testfile + filetyp # fcc_print(outfile) # fcc_print(testfile) if "BUILD_FEM_VTK" in FreeCAD.__cmake__: self.femmesh.write(outfile) # write the mesh femmesh_outfile = Fem.read(outfile) # read the mesh from written mesh femmesh_testfile = Fem.read(testfile) # read the mesh from test mesh # reading the test mesh self.assertEqual( femmesh_testfile.Nodes, self.expected_nodes['nodes'], "Test writing " + self.elem + " mesh to " + filetyp + " file failed. Nodes are different.\n" ) self.assertEqual( [femmesh_testfile.Volumes[0], femmesh_testfile.getElementNodes(femmesh_outfile.Volumes[0])], self.expected_elem['volumes'], "Test writing " + self.elem + " mesh to " + filetyp + " file failed. Volumes are different.\n" ) # reading the written mesh self.assertEqual( femmesh_outfile.Nodes, self.expected_nodes['nodes'], "Test writing " + self.elem + " mesh to " + filetyp + " file failed. Nodes are different.\n" ) self.assertEqual( [femmesh_outfile.Volumes[0], femmesh_outfile.getElementNodes(femmesh_outfile.Volumes[0])], self.expected_elem['volumes'], "Test writing " + self.elem + " mesh to " + filetyp + " file failed. Volumes are different.\n" ) # both self.assertEqual( femmesh_outfile.Nodes, femmesh_testfile.Nodes, "Test writing " + self.elem + " mesh to " + filetyp + " file failed. Nodes are different.\n" ) self.assertEqual( femmesh_outfile.Volumes, femmesh_testfile.Volumes, "Test writing " + self.elem + " mesh to " + filetyp + " file failed. Volumes are different.\n" ) else: fcc_print('FEM_VTK post processing is disabled.')
def importVtkFemMesh( filename, meshname ): meshobj = FreeCAD.ActiveDocument.addObject("Fem::FemMeshObject", meshname) meshobj.FemMesh = Fem.read(filename) meshobj.touch() FreeCAD.ActiveDocument.recompute() return meshobj
def read_and_set_new_mesh(self): if not self.error: fem_mesh = Fem.read(self.temp_file_mesh) self.mesh_obj.FemMesh = fem_mesh print(' The Part should have a pretty new FEM mesh!') else: print('No mesh was created.') del self.temp_file_geometry del self.temp_file_mesh
def test_tetra10_inp(self): # tetra10 element: reading from and writing to inp mesh file format filetyp = 'inp' outfile = self.base_outfile + filetyp testfile = self.base_testfile + filetyp # fcc_print(outfile) # fcc_print(testfile) self.femmesh.writeABAQUS(outfile, 1, False) # write the mesh femmesh_outfile = Fem.read(outfile) # read the mesh from written mesh femmesh_testfile = Fem.read(testfile) # read the mesh from test mesh # reading the test mesh # fcc_print([femmesh_testfile.Volumes[0], femmesh_testfile.getElementNodes(femmesh_outfile.Volumes[0])]) self.assertEqual( femmesh_testfile.Nodes, self.expected_nodes['nodes'], "Test reading " + self.elem + " mesh to " + filetyp + " file failed. Nodes are different.\n" ) self.assertEqual( [femmesh_testfile.Volumes[0], femmesh_testfile.getElementNodes(femmesh_outfile.Volumes[0])], self.expected_elem['volumes'], "Test reading " + self.elem + " mesh to " + filetyp + " file failed. Volumes are different.\n" ) # reading the written mesh self.assertEqual( femmesh_outfile.Nodes, self.expected_nodes['nodes'], "Test reading " + self.elem + " mesh to " + filetyp + " file failed. Nodes are different.\n" ) self.assertEqual( [femmesh_outfile.Volumes[0], femmesh_outfile.getElementNodes(femmesh_outfile.Volumes[0])], self.expected_elem['volumes'], "Test reading " + self.elem + " mesh to " + filetyp + " file failed. Volumes are different.\n" ) # both self.assertEqual( femmesh_outfile.Nodes, femmesh_testfile.Nodes, "Test writing " + self.elem + " mesh to " + filetyp + " file failed. Nodes are different.\n" ) self.assertEqual( [femmesh_outfile.Volumes[0], femmesh_outfile.getElementNodes(femmesh_outfile.Volumes[0])], [femmesh_testfile.Volumes[0], femmesh_testfile.getElementNodes(femmesh_outfile.Volumes[0])], "Test writing " + self.elem + " mesh to " + filetyp + " file failed. Volumes are different.\n" )
def importVTK(filename, analysis=None, result_name_prefix=None): import ObjectsFem if result_name_prefix is None: result_name_prefix = '' if analysis: analysis_object = analysis # if properties can be added in FemVTKTools importCfdResult(), this file can be used for CFD workbench results_name = result_name_prefix + 'results' result_obj = ObjectsFem.makeResultMechanical(results_name) Fem.readResult(filename, result_obj.Name) # readResult always creates a new femmesh named ResultMesh # workaround for the DisplacementLengths (They should have been calculated by Fem.readResult) if not result_obj.DisplacementLengths: import importToolsFem result_obj.DisplacementLengths = importToolsFem.calculate_disp_abs(result_obj.DisplacementVectors) if analysis: analysis_object.Member = analysis_object.Member + [result_obj] ''' seams not used at the moment
def importVtkFCResult( filename, resultname, analysis=None, result_name_prefix=None ): # only fields from vtk are imported if they exactly named as the FreeCAD result properties # See _getFreeCADMechResultProperties() in FemVTKTools.cpp for the supported names import ObjectsFem if result_name_prefix is None: result_name_prefix = '' if analysis: analysis_object = analysis results_name = result_name_prefix + 'results' result_obj = ObjectsFem.makeResultMechanical(FreeCAD.ActiveDocument, results_name) # readResult always creates a new femmesh named ResultMesh Fem.readResult(filename, result_obj.Name) # add missing DisplacementLengths (They should have been added by Fem.readResult) if not result_obj.DisplacementLengths: import femresult.resulttools as restools result_obj = restools.add_disp_apps(result_obj) # DisplacementLengths ''' seems unused at the moment filenamebase = '.'.join(filename.split('.')[:-1]) # pattern: filebase_timestamp.vtk ts = filenamebase.split('_')[-1] try: time_step = float(ts) except: time_step = 0.0 ''' if analysis: analysis_object.addObject(result_obj) result_obj.touch() FreeCAD.ActiveDocument.recompute() return result_obj
def gmshmesh(compound, NG2D, name=""): ''' export, mesh compound at gmsh, reimport as .unv (3d to be implemented) ''' if name =="": name="m_"+compound.Label # ImportGui.export([FreeCAD.activeDocument().getObject(compound.Name)], "/tmp/tmpNO2c.step") # command="/usr/bin/gmsh /tmp/tmpNO2c.step -2 -format unv -o /tmp/"+name+".unv -algo "+str(NG2D.gmshalgoname)+" -clmax " +str(NG2D.NGParamSetMaxSize)+" -clmin "+str(NG2D.NGParamSetMinSize)+" -string Geometry.OCCSewFaces=1;" #command="/usr/bin/gmsh /tmp/tmpNO2c.step -2 -format unv -o /tmp/Compound019_Mesh.unv -algo auto -string Geometry.OCCSewFaces=1;" #command="g" # #print command output = subprocess.check_output([command, '-1'], shell=True, stderr=subprocess.STDOUT,) FreeCAD.Console.PrintMessage(output) # Fem.insert("/tmp/"+name+".unv", FreeCAD.ActiveDocument.Name) #Fem.insert("/tmp/Compound019_Mesh.unv", FreeCAD.ActiveDocument.Name) femmesh=FreeCAD.ActiveDocument.Objects[len(FreeCAD.ActiveDocument.Objects)-1] FreeCADGui.ActiveDocument.getObject(femmesh.Name).DisplayMode = "Wireframe" return femmesh
def create_new_mesh(self): self.mesh_object = self.active_doc.addObject('Fem::FemMeshObject', mesh_name) self.mesh = Fem.FemMesh() with open(mesh_points_file, 'r') as points_file: reader = csv.reader(points_file) for p in reader: self.mesh.addNode(float(p[1]), float(p[2]), float(p[3]), int(p[0])) with open(mesh_volumes_file, 'r') as volumes_file: reader = csv.reader(volumes_file) for v in reader: self.mesh.addVolume([int(v[2]), int(v[1]), int(v[3]), int(v[4]), int(v[5]), int(v[7]), int(v[6]), int(v[9]), int(v[8]), int(v[10])], int(v[0])) self.mesh_object.FemMesh = self.mesh self.active_doc.recompute()
def test_mesh_seg3_python(self): seg3 = Fem.FemMesh() seg3.addNode(0, 0, 0, 1) seg3.addNode(1, 0, 0, 2) seg3.addNode(2, 0, 0, 3) seg3.addNode(3, 0, 0, 4) seg3.addNode(4, 0, 0, 5) seg3.addEdge([1, 3, 2]) seg3.addEdge([3, 5, 4], 2) node_data = [seg3.NodeCount, seg3.Nodes] edge_data = [seg3.EdgeCount, seg3.Edges[0], seg3.getElementNodes(seg3.Edges[0]), seg3.Edges[1], seg3.getElementNodes(seg3.Edges[1])] expected_nodes = [5, {1: FreeCAD.Vector(0.0, 0.0, 0.0), 2: FreeCAD.Vector(1.0, 0.0, 0.0), 3: FreeCAD.Vector(2.0, 0.0, 0.0), 4: FreeCAD.Vector(3.0, 0.0, 0.0), 5: FreeCAD.Vector(4.0, 0.0, 0.0)}] expected_edges = [2, 1, (1, 3, 2), 2, (3, 5, 4)] self.assertEqual(node_data, expected_nodes, "Nodes of Python created seg3 element are unexpected") self.assertEqual(edge_data, expected_edges, "Edges of Python created seg3 element are unexpected")
def setUp(self): # setUp is executed before every test # new document self.document = FreeCAD.newDocument(self.__class__.__name__) # more inits self.elem = "tetra10" self.base_testfile = join(testtools.get_fem_test_home_dir(), "mesh", (self.elem + "_mesh.")) # 10 node tetrahedron --> tetra10 femmesh = Fem.FemMesh() femmesh.addNode(6, 12, 18, 1) femmesh.addNode(0, 0, 18, 2) femmesh.addNode(12, 0, 18, 3) femmesh.addNode(6, 6, 0, 4) femmesh.addNode(3, 6, 18, 5) femmesh.addNode(6, 0, 18, 6) femmesh.addNode(9, 6, 18, 7) femmesh.addNode(6, 9, 9, 8) femmesh.addNode(3, 3, 9, 9) femmesh.addNode(9, 3, 9, 10) femmesh.addVolume([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) self.femmesh = femmesh self.expected_nodes = { "count": 10, "nodes": { 1: FreeCAD.Vector(6.0, 12.0, 18.0), 2: FreeCAD.Vector(0.0, 0.0, 18.0), 3: FreeCAD.Vector(12.0, 0.0, 18.0), 4: FreeCAD.Vector(6.0, 6.0, 0.0), 5: FreeCAD.Vector(3.0, 6.0, 18.0), 6: FreeCAD.Vector(6.0, 0.0, 18.0), 7: FreeCAD.Vector(9.0, 6.0, 18.0), 8: FreeCAD.Vector(6.0, 9.0, 9.0), 9: FreeCAD.Vector(3.0, 3.0, 9.0), 10: FreeCAD.Vector(9.0, 3.0, 9.0), } } self.expected_elem = { "volcount": 1, "tetcount": 1, "volumes": [1, (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)] } """
def setup_base(doc=None, solvertype="ccxtools"): # setup box base model if doc is None: doc = init_doc() # geometry object geom_obj = doc.addObject("Part::Box", "Box") geom_obj.Height = geom_obj.Width = geom_obj.Length = 10 doc.recompute() if FreeCAD.GuiUp: geom_obj.ViewObject.Document.activeView().viewAxonometric() geom_obj.ViewObject.Document.activeView().fitAll() # analysis analysis = ObjectsFem.makeAnalysis(doc, "Analysis") # material material_object = analysis.addObject( ObjectsFem.makeMaterialSolid(doc, "MechanicalMaterial"))[0] mat = material_object.Material mat["Name"] = "Steel-Generic" mat["YoungsModulus"] = "200000 MPa" mat["PoissonRatio"] = "0.30" mat["Density"] = "7900 kg/m^3" material_object.Material = mat # mesh from .meshes.mesh_boxanalysis_tetra10 import create_nodes, create_elements fem_mesh = Fem.FemMesh() control = create_nodes(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating nodes.\n") control = create_elements(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating elements.\n") femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, mesh_name))[0] femmesh_obj.FemMesh = fem_mesh femmesh_obj.Part = geom_obj femmesh_obj.SecondOrderLinear = False femmesh_obj.CharacteristicLengthMin = "8.0 mm" doc.recompute() return doc
def read_and_set_new_mesh(self): if not self.error: # NOTE: FemMesh does not support multi element stl # fem_mesh = Fem.read(os.path.join(self.meshCaseDir,'mesh_outside.stl')) # This is a temp work around to remove multiple solids, but is not very efficient import Mesh stl = os.path.join(self.meshCaseDir, 'mesh_outside.stl') ast = os.path.join(self.meshCaseDir, 'mesh_outside.ast') mesh = Mesh.Mesh(stl) mesh.write(ast) os.remove(stl) os.rename(ast, stl) fem_mesh = Fem.read(stl) self.mesh_obj.FemMesh = fem_mesh print(' The Part should have a new mesh!') else: print('No mesh was created.')
def importGeometryAndMesh(geo_file, mesh_file): # caller guarant input parameter is valid path and type, each is a tuple of (filename, suffix) docname = FreeCAD.ActiveDocument.Name if geo_file: if isinstance(geo_file, (str, unicode)) and os.path.exists(geo_file): geo_suffix = geo_file.split(u'.')[-1] #if geo_suffix not in [u'iges', u'igs', u'step', u'stp', u'brep', u'fcstd']: # should be done in caller # FreeCAD.Console.PrintError(u"only step, brep, fcstd and iges geometry files are supported, while input file suffix is: {}".format(geo_suffix)) # return False # there must be a document to import objects #FreeCADGui.addModule("Part") #FreeCADGui.doCommand("Part.insert(u'" + geo_file + "','" + docname + "')") import Part Part.insert(geo_file, docname) part_obj = FreeCAD.ActiveDocument.ActiveObject elif geo_file.isDerivedFrom("Part::Feature"): part_obj = geo_file else: FreeCAD.Console.PrintError( "part should be provided as a valid file path or Part::Feature dervied Object" ) mesh_suffix = mesh_file.split(u'.')[-1] #if mesh_suffix not in [u'unv', u'inp', u'vtk', u'vtu', u'med']: # any type supported by FemMesh import # FreeCAD.Console.PrintError(u"input file suffix: {}, is NOT supported for mesh importing".format(geo_suffix)) # return False import Fem fem_mesh = Fem.read(mesh_file) # Fem.insert() gives <Fem::FemMeshObject object> can not add dynamic property # mesh must NOT been scaled to metre, or using LengthUnit property! if fem_mesh: #mesh_obj.isDerivedFrom("Part::FeaturePython"): import CfdObjects mesh_obj = CfdObjects.makeCfdMeshImported() mesh_obj.FemMesh = fem_mesh mesh_obj.Part = part_obj mesh_obj.Imported = True mesh_obj.ImportedMeshPath = mesh_file FreeCAD.Console.PrintMessage( 'The Part should have an FEM mesh imported') return mesh_obj else: FreeCAD.Console.PrintError( 'Mesh importing failed for {}'.format(mesh_file)) return False
def setup_base(doc=None, solvertype="ccxtools"): # setup box base model if doc is None: doc = init_doc() # part box_obj = doc.addObject("Part::Box", "Box") box_obj.Height = box_obj.Width = box_obj.Length = 10 doc.recompute() if FreeCAD.GuiUp: import FreeCADGui FreeCADGui.ActiveDocument.activeView().viewAxonometric() FreeCADGui.SendMsgToActiveView("ViewFit") # analysis analysis = ObjectsFem.makeAnalysis(doc, "Analysis") # material material_object = analysis.addObject( ObjectsFem.makeMaterialSolid(doc, "MechanicalMaterial") )[0] mat = material_object.Material mat["Name"] = "Steel-Generic" mat["YoungsModulus"] = "200000 MPa" mat["PoissonRatio"] = "0.30" mat["Density"] = "7900 kg/m^3" material_object.Material = mat # mesh from .meshes.mesh_boxanalysis_tetra10 import create_nodes, create_elements fem_mesh = Fem.FemMesh() control = create_nodes(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating nodes.\n") control = create_elements(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating elements.\n") femmesh_obj = analysis.addObject( doc.addObject("Fem::FemMeshObject", mesh_name) )[0] femmesh_obj.FemMesh = fem_mesh doc.recompute() return doc
def setup_cantileverhexa20faceload(doc=None, solvertype="ccxtools"): doc = setup_cantileverfaceload(doc, solvertype) # load the hexa20 mesh from .meshes.mesh_canticcx_hexa20 import create_nodes, create_elements fem_mesh = Fem.FemMesh() control = create_nodes(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating nodes.\n") control = create_elements(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating elements.\n") # overwrite mesh with the hexa20 mesh doc.getObject(mesh_name).FemMesh = fem_mesh doc.recompute() return doc
def test_unv_save_load(self): tetra10 = Fem.FemMesh() tetra10.addNode(6, 12, 18, 1) tetra10.addNode(0, 0, 18, 2) tetra10.addNode(12, 0, 18, 3) tetra10.addNode(6, 6, 0, 4) tetra10.addNode(3, 6, 18, 5) tetra10.addNode(6, 0, 18, 6) tetra10.addNode(9, 6, 18, 7) tetra10.addNode(6, 9, 9, 8) tetra10.addNode(3, 3, 9, 9) tetra10.addNode(9, 3, 9, 10) tetra10.addVolume([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) tetra10.write(static_save_unv_file) newmesh = Fem.read(static_save_unv_file) expected = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) self.assertEqual(newmesh.getElementNodes(1), expected, "Nodes order of quadratic volume element is unexpected")
def loadSurfMesh(self): if not self.error: # NOTE: FemMesh does not support multi element stl # fem_mesh = Fem.read(os.path.join(self.meshCaseDir,'mesh_outside.stl')) # This is a temp work around to remove multiple solids, but is not very efficient import Mesh stl = os.path.join(self.meshCaseDir, 'mesh_outside.stl') ast = os.path.join(self.meshCaseDir, 'mesh_outside.ast') mesh = Mesh.Mesh(stl) mesh.write(ast) os.remove(stl) os.rename(ast, stl) fem_mesh = Fem.read(stl) fem_mesh_obj = FreeCAD.ActiveDocument.addObject("Fem::FemMeshObject", self.mesh_obj.Name+"_Surf_Vis") fem_mesh_obj.FemMesh = fem_mesh self.mesh_obj.addObject(fem_mesh_obj) print(' Finished loading mesh.') else: print('No mesh was created.')
def importGeometryAndMesh(geo_file, mesh_file): # caller guarant input parameter is valid path and type, each is a tuple of (filename, suffix) docname = FreeCAD.ActiveDocument.Name if geo_file: if os.path.exists(geo_file): geo_suffix = geo_file.split(u'.')[-1] if geo_suffix not in [u'iges', u'igs', u'step', u'stp', u'brep']: FreeCAD.Console.PrintError(u"only step, brep and iges geometry files are supported, while input file suffix is: {}".format(geo_suffix)) return False # there must be a document to import objects #FreeCADGui.addModule("Part") #FreeCADGui.doCommand("Part.insert(u'" + geo_file + "','" + docname + "')") import Part Part.insert(geo_file , docname) part_obj = FreeCAD.ActiveDocument.ActiveObject elif geo_file.isDerivedFrom("Part::Feature"): part_obj = geo_file else: part_obj = None mesh_suffix = mesh_file.split(u'.')[-1] if mesh_suffix not in [u'unv', u'inp', u'vtk', u'vtu', u'med']: FreeCAD.Console.PrintError(u"input file suffix: {}, is NOT supported for mesh importing".format(geo_suffix)) return False import Fem fem_mesh = Fem.read(mesh_file) #FreeCADGui.addModule("Fem") #FreeCADGui.doCommand("Fem.read(u'" + mesh_file + "')") # Fem.insert() gives <Fem::FemMeshObject object> can not add dynamic property # mesh must NOT been scaled to metre, or using LengthUnit property if fem_mesh: #mesh_obj.isDerivedFrom("Part::FeaturePython"): #FreeCADGui.addModule("CfdObjects") # FemGmsh has been adjusted for CFD like only first order element #FreeCADGui.doCommand("CfdObjects.makeCfdMeshImported('" + mesh_obj_name + "')") import CfdObjects mesh_obj = CfdObjects.makeCfdMeshImported() mesh_obj.FemMesh = fem_mesh mesh_obj.Part = part_obj FreeCAD.Console.PrintMessage('The Part should have an FEM mesh imported') return mesh_obj else: FreeCAD.Console.PrintError('Mesh importing failed for {}'.format(mesh_file))
def mesh_finished(self, exit_code): self.read_output() print("exit code", exit_code) if exit_code == 0: self.console_log("Reading mesh") #Reading stl created by OpenFOAM to display representation of mesh import Mesh import Fem self.meshConverted = True stl = os.path.join(self.meshCaseDir, 'mesh_outside.stl') ast = os.path.join(self.meshCaseDir, 'mesh_outside.ast') mesh = Mesh.Mesh(stl) mesh.write(ast) os.remove(stl) os.rename(ast, stl) fem_mesh = Fem.read(stl) self.meshObj.FemMesh = fem_mesh self.console_log('2D Meshing completed') self.console_log( 'The mesh should now contain only a single element through the thickness.' ) self.console_log( 'Warning: Tetrahedral representation of the mesh is a only a representation.' ) self.console_log( "Please use Paraview to view the new mesh correctly.\n") self.form.paraviewButton.setEnabled(True) self.form.convertButton.setEnabled(True) self.saveInfo() self.form.conversionStatusText.setText( "Mesh converted successfully.") self.form.conversionStatusText.setStyleSheet('color: green') else: print("Meshing error") self.meshConverted = False self.console_log("Meshing exited with error", "#FF0000") self.form.paraviewButton.setEnabled(False) self.form.convertButton.setEnabled(True) self.form.convertButton.setEnabled(True) self.Timer.stop() self.error_message = ''
def setup(doc=None, solvertype="ccxtools"): # init FreeCAD document if doc is None: doc = init_doc() # explanation object # just keep the following line and change text string in get_explanation method manager.add_explanation_obj( doc, get_explanation(manager.get_header(get_information()))) # setup CalculiX cantilever doc = setup_cantilever_base_face(doc, solvertype) femmesh_obj = doc.getObject(get_meshname()) geom_obj = doc.getObject("CanileverPlate") # load the quad8 mesh from .meshes.mesh_canticcx_quad8 import create_nodes, create_elements new_fem_mesh = Fem.FemMesh() control = create_nodes(new_fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating nodes.\n") control = create_elements(new_fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating elements.\n") # overwrite mesh with the quad8 mesh femmesh_obj.FemMesh = new_fem_mesh # set mesh obj parameter femmesh_obj.Part = geom_obj femmesh_obj.SecondOrderLinear = False femmesh_obj.ElementDimension = "2D" femmesh_obj.ElementOrder = "1st" femmesh_obj.CharacteristicLengthMax = "4000.0 mm" femmesh_obj.CharacteristicLengthMin = "4000.0 mm" femmesh_obj.RecombinationAlgorithm = "Blossom full-quad" femmesh_obj.RecombineAll = True doc.recompute() return doc
def _exportToUnv(self, groups, mesh, meshPath): unvGmshFd, unvGmshPath = tempfile.mkstemp(suffix=".unv") brepFd, brepPath = tempfile.mkstemp(suffix=".brep") geoFd, geoPath = tempfile.mkstemp(suffix=".geo") os.close(brepFd) os.close(geoFd) os.close(unvGmshFd) tools = gmshtools.GmshTools(mesh) tools.group_elements = {g: [g] for g in groups} tools.group_nodes_export = False tools.ele_length_map = {} tools.temp_file_geometry = brepPath tools.temp_file_geo = geoPath tools.temp_file_mesh = unvGmshPath tools.get_dimension() tools.get_region_data() tools.get_boundary_layer_data() tools.write_part_file() tools.write_geo() if self.testmode: Console.PrintMessage( "Solver Elmer testmode, Gmsh will not be used. " "It might not be installed.\n") import shutil shutil.copyfile(geoPath, os.path.join(self.directory, "group_mesh.geo")) else: tools.get_gmsh_command() tools.run_gmsh_with_geo() ioMesh = Fem.FemMesh() ioMesh.read(unvGmshPath) ioMesh.write(meshPath) os.remove(brepPath) os.remove(geoPath) os.remove(unvGmshPath)
def test_writeAbaqus_precision( self ): # https://forum.freecadweb.org/viewtopic.php?f=18&t=22759#p176669 # ccx reads only F20.0 (i. e. Fortran floating point field 20 chars wide) # thus precision is set to 13 in writeAbaqus seg2 = Fem.FemMesh() seg2.addNode(0, 0, 0, 1) seg2.addNode( # 3456789012345678901234567 -5000000000000000000.1, -1.123456789123456e-14, -0.1234567890123456789e-101, 2 ) seg2.addEdge([1, 2]) inp_file = testtools.get_fem_test_tmp_dir() + "/seg2_mesh.inp" seg2.writeABAQUS(inp_file, 1, False) read_file = open(inp_file, "r") read_node_line = "line was not found" for ln in read_file: ln = ln.strip() if ln.startswith("2, -5"): read_node_line = ln read_file.close() # 1234567 12345678901234567890 12345678901234567890 expected_win = "2, -5e+018, -1.123456789123e-014, -1.234567890123e-102" expected_lin = "2, -5e+18, -1.123456789123e-14, -1.234567890123e-102" expected = [expected_lin, expected_win] self.assertTrue( True if read_node_line in expected else False, "Problem in test_writeAbaqus_precision, \n{0}\n{1}".format( read_node_line, expected ) )
def test_mesh_seg2_python( self ): seg2 = Fem.FemMesh() seg2.addNode(0, 0, 0, 1) seg2.addNode(2, 0, 0, 2) seg2.addNode(4, 0, 0, 3) seg2.addEdge([1, 2]) seg2.addEdge([2, 3], 2) node_data = [ seg2.NodeCount, seg2.Nodes ] edge_data = [ seg2.EdgeCount, seg2.Edges[0], seg2.getElementNodes(seg2.Edges[0]), seg2.Edges[1], seg2.getElementNodes(seg2.Edges[1]) ] expected_nodes = [ 3, { 1: FreeCAD.Vector(0.0, 0.0, 0.0), 2: FreeCAD.Vector(2.0, 0.0, 0.0), 3: FreeCAD.Vector(4.0, 0.0, 0.0) } ] expected_edges = [2, 1, (1, 2), 2, (2, 3)] self.assertEqual( node_data, expected_nodes, "Nodes of Python created seg2 element are unexpected" ) self.assertEqual( edge_data, expected_edges, "Edges of Python created seg2 element are unexpected" )
def import_csv_mesh(import_points_file, import_volumes_file): import csv the_fem_mesh = Fem.FemMesh() with open(import_points_file, 'r') as points_file: reader = csv.reader(points_file) for p in reader: the_fem_mesh.addNode(float(p[1]), float(p[2]), float(p[3]), int(p[0])) with open(import_volumes_file, 'r') as volumes_file: reader = csv.reader(volumes_file) for v in reader: the_fem_mesh.addVolume([ int(v[2]), int(v[1]), int(v[3]), int(v[4]), int(v[5]), int(v[7]), int(v[6]), int(v[9]), int(v[8]), int(v[10]) ], int(v[0])) return the_fem_mesh
def importFrd(filename, Analysis=None): mstress = [] global displacement displacement = [] m = readResult(filename) MeshObject = None if (len(m) > 0): import Fem if Analysis is None: AnalysisName = os.path.splitext(os.path.basename(filename))[0] AnalysisObject = FreeCAD.ActiveDocument.addObject( 'Fem::FemAnalysis', 'Analysis') AnalysisObject.Label = AnalysisName else: AnalysisObject = Analysis results = FreeCAD.ActiveDocument.addObject('Fem::FemResultObject', 'Results') if ('Tet10Elem' in m) and ('Nodes' in m) and (not Analysis): mesh = Fem.FemMesh() nds = m['Nodes'] for i in nds: n = nds[i] mesh.addNode(n[0], n[1], n[2], i) elms = m['Tet10Elem'] for i in elms: e = elms[i] mesh.addVolume([ e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7], e[8], e[9] ], i) if len(nds) > 0: MeshObject = FreeCAD.ActiveDocument.addObject( 'Fem::FemMeshObject', 'ResultMesh') MeshObject.FemMesh = mesh AnalysisObject.Member = AnalysisObject.Member + [MeshObject] if 'Displacement' in m: disp = m['Displacement'] if len(disp) > 0: results.DisplacementVectors = disp.values() results.ElementNumbers = disp.keys() if (MeshObject): results.Mesh = MeshObject if 'Stress' in m: stress = m['Stress'] if len(stress) > 0: for i in stress.values(): # Von mises stress (http://en.wikipedia.org/wiki/Von_Mises_yield_criterion) s11 = i[0] s22 = i[1] s33 = i[2] s12 = i[3] s23 = i[4] s31 = i[5] s11s22 = pow(s11 - s22, 2) s22s33 = pow(s22 - s33, 2) s33s11 = pow(s33 - s11, 2) s12s23s31 = 6 * (pow(s12, 2) + pow(s23, 2) * pow(s31, 2)) mstress.append( sqrt(0.5 * (s11s22 + s22s33 + s33s11 + s12s23s31))) results.StressValues = mstress if (results.ElementNumbers != 0 and results.ElementNumbers != stress.keys()): print "Inconsistent FEM results: element number for Stress doesn't equal element number for Displacement" results.ElementNumbers = stress.keys() if (MeshObject): results.Mesh = MeshObject l = len(displacement) x_max, y_max, z_max = map(max, zip(*displacement)) x_min, y_min, z_min = map(min, zip(*displacement)) sum_list = map(sum, zip(*displacement)) x_avg, y_avg, z_avg = [i / l for i in sum_list] s_max = max(mstress) s_min = min(mstress) s_avg = sum(mstress) / l disp_abs = [] for d in displacement: disp_abs.append(sqrt(pow(d[0], 2) + pow(d[1], 2) + pow(d[2], 2))) results.DisplacementLengths = disp_abs a_max = max(disp_abs) a_min = min(disp_abs) a_avg = sum(disp_abs) / l results.Stats = [ x_min, x_avg, x_max, y_min, y_avg, y_max, z_min, z_avg, z_max, a_min, a_avg, a_max, s_min, s_avg, s_max ] AnalysisObject.Member = AnalysisObject.Member + [results] if (FreeCAD.GuiUp): import FemGui import FreeCADGui if FreeCADGui.activeWorkbench().name() != 'FemWorkbench': FreeCADGui.activateWorkbench("FemWorkbench") FemGui.setActiveAnalysis(AnalysisObject)
def cleanmeshdoubles(femmesh): ''' find doubles nodes, double edges as they occur after gmsh (2d) unv import -by "checking for double interboundary edges" eleminate edges, nodes and rereference ''' #m=femmesh.FemMesh nodeP=femmesh.FemMesh.Nodes refnodes=[-1]*len(femmesh.FemMesh.Nodes) res=[] #res=[(-1,-1),(-1,-1),-1,-1] resvec=[] edgeE=femmesh.FemMesh.Edges for a1 in edgeE: if res!=[] and len(set([a1]) & set([i[3] for i in res]))!=0: print "double" continue a=femmesh.FemMesh.getElementNodes(a1) a2=femmesh.FemMesh.getNodeById(a[0]) a3=femmesh.FemMesh.getNodeById(a[1]) for a4 in set(femmesh.FemMesh.Edges)-set([a1]): a5=femmesh.FemMesh.getElementNodes(a4) a6=femmesh.FemMesh.getNodeById(a5[0]) a7=femmesh.FemMesh.getNodeById(a5[1]) if [a2,a3]==[a6,a7] or [a3,a2]==[a6,a7]: if a2==a6: doublenode1=a[0] doublenode2=a5[0] doublenode3=a[1] doublenode4=a5[1] else: doublenode1=a[1] doublenode2=a5[0] doublenode3=a[0] doublenode4=a5[1] print "first edge endpoints vectors:" + str(a2) + " " + str(a3)+"double nodes " + str(a) + " " + str(a5) +"first +double edge: " + str(a1) + " " + str(a4) +"\ndoublenodespair1by2: " + str(doublenode1) +" "+ str(doublenode2) +"\ndoublenodespair3by4: " + str(doublenode3) +" "+ str(doublenode4) res.append([a,a5,a1,a4]) resvec.append([[a2,a3]]) #eleminate double edges edgeE=set(edgeE)-set([a4]) #eleminate (hopefully) all double nodes and reference them if doublenode2 in nodeP: del nodeP[doublenode2] refnodes[doublenode2]=doublenode1 if doublenode4 in nodeP: del nodeP[doublenode4] refnodes[doublenode4]=doublenode3 #del nodeP[doublenode4] break #!1find and substitute double nodes in face element nodes facesE=[femmesh.FemMesh.getElementNodes(fac) for fac in list(edgeE.union(femmesh.FemMesh.Faces))] first_n_plain=[resi1 for resi in res for resi1 in resi[0]] double_n_plain=[resi1 for resi in res for resi1 in resi[1]] elenodes=[] for fac in range(len(facesE)): #print "h3" elen=list(set(facesE[fac]) & set(double_n_plain)) #print "h4" if len(elen)>0: #print "h4" factem=facesE[fac] #print "h4.2" for i2 in range(len(elen)): #print "h5" lfac=list(facesE[fac]) #print "h6 " +str(i2) + " " +str(elen) lfac[lfac.index(elen[i2])]=first_n_plain[double_n_plain.index(elen[i2])] #print "h7" facesE[fac]=tuple(lfac) print str(elen) +"mface i with 2 double node:" + str(fac) +"to be substituted by:" + str(first_n_plain[double_n_plain.index(elen[0])]) +" to " +str(facesE[fac])+" from " +str(factem) #elenodes.append(elen) #fac[fac.index(elen)]=first_n_plain[double_n_plain.index(elen)] # if len(elen)==1:print str(elen)+"mface with 1 double node:" + str(fac) #!rebuild mesh import FreeCAD, Fem m = Fem.FemMesh() for n in nodeP.keys(): #print str(n1) + " :" + str(n) n1=nodeP[n] #print str(n1) + " :" + str(n) m.addNode(n1.x, n1.y, n1.z, n) elemN=list(edgeE.union(femmesh.FemMesh.Faces)) for i in range(len(facesE)): #print str(facesE[i]) + "" + str(elemN[i]) #loose id's here if len(facesE[i])==3: m.addFace(facesE[i][0],facesE[i][1],facesE[i][2]) if len(facesE[i])==2: a=m.addEdge(facesE[i][0],facesE[i][1]) Fem.show(m) femmesh2=femmesh1.Document.Objects[len(femmesh1.Document.Objects)-1] return femmesh2
def test_static_analysis(self): fcc_print('--------------- Start of FEM tests ---------------') box = self.active_doc.addObject("Part::Box", "Box") fcc_print('Checking FEM new analysis...') analysis = ObjectsFem.makeAnalysis(self.active_doc, 'Analysis') self.assertTrue(analysis, "FemTest of new analysis failed") fcc_print('Checking FEM new solver...') solver_object = ObjectsFem.makeSolverCalculixCcxTools( self.active_doc, 'CalculiX') solver_object.AnalysisType = 'static' solver_object.GeometricalNonlinearity = 'linear' solver_object.ThermoMechSteadyState = False solver_object.MatrixSolverType = 'default' solver_object.IterationsControlParameterTimeUse = False solver_object.EigenmodesCount = 10 solver_object.EigenmodeHighLimit = 1000000.0 solver_object.EigenmodeLowLimit = 0.0 self.assertTrue(solver_object, "FemTest of new solver failed") analysis.addObject(solver_object) fcc_print('Checking FEM new material...') material_object = ObjectsFem.makeMaterialSolid(self.active_doc, 'MechanicalMaterial') mat = material_object.Material mat['Name'] = "Steel-Generic" mat['YoungsModulus'] = "200000 MPa" mat['PoissonRatio'] = "0.30" mat['Density'] = "7900 kg/m^3" material_object.Material = mat self.assertTrue(material_object, "FemTest of new material failed") analysis.addObject(material_object) fcc_print('Checking FEM new fixed constraint...') fixed_constraint = self.active_doc.addObject("Fem::ConstraintFixed", "FemConstraintFixed") fixed_constraint.References = [(box, "Face1")] self.assertTrue(fixed_constraint, "FemTest of new fixed constraint failed") analysis.addObject(fixed_constraint) fcc_print('Checking FEM new force constraint...') force_constraint = self.active_doc.addObject("Fem::ConstraintForce", "FemConstraintForce") force_constraint.References = [(box, "Face6")] force_constraint.Force = 40000.0 force_constraint.Direction = (box, ["Edge5"]) self.active_doc.recompute() force_constraint.Reversed = True self.active_doc.recompute() self.assertTrue(force_constraint, "FemTest of new force constraint failed") analysis.addObject(force_constraint) fcc_print('Checking FEM new pressure constraint...') pressure_constraint = self.active_doc.addObject( "Fem::ConstraintPressure", "FemConstraintPressure") pressure_constraint.References = [(box, "Face2")] pressure_constraint.Pressure = 1000.0 pressure_constraint.Reversed = False self.assertTrue(pressure_constraint, "FemTest of new pressure constraint failed") analysis.addObject(pressure_constraint) fcc_print('Checking FEM new mesh...') from .testfiles.ccx.cube_mesh import create_nodes_cube from .testfiles.ccx.cube_mesh import create_elements_cube mesh = Fem.FemMesh() ret = create_nodes_cube(mesh) self.assertTrue(ret, "Import of mesh nodes failed") ret = create_elements_cube(mesh) self.assertTrue(ret, "Import of mesh volumes failed") mesh_object = self.active_doc.addObject('Fem::FemMeshObject', self.mesh_name) mesh_object.FemMesh = mesh self.assertTrue(mesh, "FemTest of new mesh failed") analysis.addObject(mesh_object) self.active_doc.recompute() static_analysis_dir = testtools.get_unit_test_tmp_dir( self.temp_dir, 'FEM_ccx_static/') fea = ccxtools.FemToolsCcx(analysis, solver_object, test_mode=True) fcc_print( 'Setting up working directory {}'.format(static_analysis_dir)) fea.setup_working_dir(static_analysis_dir) self.assertTrue( True if fea.working_dir == static_analysis_dir else False, "Setting working directory {} failed".format(static_analysis_dir)) fcc_print('Checking FEM inp file prerequisites for static analysis...') error = fea.check_prerequisites() self.assertFalse( error, "ccxtools check_prerequisites returned error message: {}".format( error)) fcc_print('Checking FEM inp file write...') fcc_print('Writing {}/{}.inp for static analysis'.format( static_analysis_dir, self.mesh_name)) error = fea.write_inp_file() self.assertFalse(error, "Writing failed") static_base_name = 'cube_static' static_analysis_inp_file = self.test_file_dir + static_base_name + '.inp' fcc_print('Comparing {} to {}/{}.inp'.format(static_analysis_inp_file, static_analysis_dir, self.mesh_name)) ret = testtools.compare_inp_files( static_analysis_inp_file, static_analysis_dir + self.mesh_name + '.inp') self.assertFalse( ret, "ccxtools write_inp_file test failed.\n{}".format(ret)) fcc_print( 'Setting up working directory to {} in order to read simulated calculations' .format(self.test_file_dir)) fea.setup_working_dir(self.test_file_dir) self.assertTrue( True if fea.working_dir == self.test_file_dir else False, "Setting working directory {} failed".format(self.test_file_dir)) fcc_print('Setting base name to read test {}.frd file...'.format( 'cube_static')) fea.set_base_name(static_base_name) self.assertTrue( True if fea.base_name == static_base_name else False, "Setting base name to {} failed".format(static_base_name)) fcc_print('Setting inp file name to read test {}.frd file...'.format( 'cube_static')) fea.set_inp_file_name() self.assertTrue( True if fea.inp_file_name == static_analysis_inp_file else False, "Setting inp file name to {} failed".format( static_analysis_inp_file)) fcc_print('Checking FEM frd file read from static analysis...') fea.load_results() self.assertTrue( fea.results_present, "Cannot read results from {}.frd frd file".format(fea.base_name)) fcc_print('Reading stats from result object for static analysis...') static_expected_values = self.test_file_dir + "cube_static_expected_values" ret = testtools.compare_stats(fea, static_expected_values, 'CalculiX_static_results') self.assertFalse(ret, "Invalid results read from .frd file") static_save_fc_file = static_analysis_dir + static_base_name + '.fcstd' fcc_print('Save FreeCAD file for static analysis to {}...'.format( static_save_fc_file)) self.active_doc.saveAs(static_save_fc_file) fcc_print( '--------------- End of FEM tests static and analysis ---------------' )
def test_Flow1D_thermomech_analysis(self): fcc_print('--------------- Start of 1D Flow FEM tests ---------------') import Draft p1 = FreeCAD.Vector(0, 0, 50) p2 = FreeCAD.Vector(0, 0, -50) p3 = FreeCAD.Vector(0, 0, -4300) p4 = FreeCAD.Vector(4950, 0, -4300) p5 = FreeCAD.Vector(5000, 0, -4300) p6 = FreeCAD.Vector(8535.53, 0, -7835.53) p7 = FreeCAD.Vector(8569.88, 0, -7870.88) p8 = FreeCAD.Vector(12105.41, 0, -11406.41) p9 = FreeCAD.Vector(12140.76, 0, -11441.76) p10 = FreeCAD.Vector(13908.53, 0, -13209.53) p11 = FreeCAD.Vector(13943.88, 0, -13244.88) p12 = FreeCAD.Vector(15046.97, 0, -14347.97) p13 = FreeCAD.Vector(15046.97, 0, -7947.97) p14 = FreeCAD.Vector(15046.97, 0, -7847.97) p15 = FreeCAD.Vector(0, 0, 0) p16 = FreeCAD.Vector(0, 0, -2175) p17 = FreeCAD.Vector(2475, 0, -4300) p18 = FreeCAD.Vector(4975, 0, -4300) p19 = FreeCAD.Vector(6767.765, 0, -6067.765) p20 = FreeCAD.Vector(8552.705, 0, -7853.205) p21 = FreeCAD.Vector(10337.645, 0, -9638.645) p22 = FreeCAD.Vector(12123.085, 0, -11424.085) p23 = FreeCAD.Vector(13024.645, 0, -12325.645) p24 = FreeCAD.Vector(13926.205, 0, -13227.205) p25 = FreeCAD.Vector(14495.425, 0, -13796.425) p26 = FreeCAD.Vector(15046.97, 0, -11147.97) p27 = FreeCAD.Vector(15046.97, 0, -7897.97) points = [ p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27 ] line = Draft.makeWire(points, closed=False, face=False, support=None) fcc_print('Checking FEM new analysis...') analysis = ObjectsFem.makeAnalysis(self.active_doc, 'Analysis') self.assertTrue(analysis, "FemTest of new analysis failed") fcc_print('Checking FEM new solver...') solver_object = ObjectsFem.makeSolverCalculixCcxTools( self.active_doc, 'CalculiX') solver_object.AnalysisType = 'thermomech' solver_object.GeometricalNonlinearity = 'linear' solver_object.ThermoMechSteadyState = True solver_object.MatrixSolverType = 'default' solver_object.IterationsThermoMechMaximum = 2000 solver_object.IterationsControlParameterTimeUse = False self.assertTrue(solver_object, "FemTest of new solver failed") analysis.addObject(solver_object) fcc_print('Checking FEM new material...') material_object = ObjectsFem.makeMaterialFluid(self.active_doc, 'FluidMaterial') mat = material_object.Material mat['Name'] = "Water" mat['Density'] = "998 kg/m^3" mat['SpecificHeat'] = "4.182 J/kg/K" mat['DynamicViscosity'] = "1.003e-3 kg/m/s" mat['VolumetricThermalExpansionCoefficient'] = "2.07e-4 m/m/K" mat['ThermalConductivity'] = "0.591 W/m/K" material_object.Material = mat self.assertTrue(material_object, "FemTest of new material failed") analysis.addObject(material_object) fcc_print('Checking FEM Flow1D inlet constraint...') Flow1d_inlet = ObjectsFem.makeElementFluid1D(self.active_doc, "ElementFluid1D") Flow1d_inlet.SectionType = 'Liquid' Flow1d_inlet.LiquidSectionType = 'PIPE INLET' Flow1d_inlet.InletPressure = 0.1 Flow1d_inlet.References = [(line, "Edge1")] self.assertTrue(Flow1d_inlet, "FemTest of new Flow1D inlet constraint failed") analysis.addObject(Flow1d_inlet) fcc_print('Checking FEM new Flow1D entrance constraint...') Flow1d_entrance = ObjectsFem.makeElementFluid1D( self.active_doc, "ElementFluid1D") Flow1d_entrance.SectionType = 'Liquid' Flow1d_entrance.LiquidSectionType = 'PIPE ENTRANCE' Flow1d_entrance.EntrancePipeArea = 31416.00 Flow1d_entrance.EntranceArea = 25133.00 Flow1d_entrance.References = [(line, "Edge2")] self.assertTrue(Flow1d_entrance, "FemTest of new Flow1D entrance constraint failed") analysis.addObject(Flow1d_entrance) fcc_print('Checking FEM new Flow1D manning constraint...') Flow1d_manning = ObjectsFem.makeElementFluid1D(self.active_doc, "ElementFluid1D") Flow1d_manning.SectionType = 'Liquid' Flow1d_manning.LiquidSectionType = 'PIPE MANNING' Flow1d_manning.ManningArea = 31416 Flow1d_manning.ManningRadius = 50 Flow1d_manning.ManningCoefficient = 0.002 Flow1d_manning.References = [(line, "Edge3"), (line, "Edge5")] self.assertTrue(Flow1d_manning, "FemTest of new Flow1D manning constraint failed") analysis.addObject(Flow1d_manning) fcc_print('Checking FEM new Flow1D bend constraint...') Flow1d_bend = ObjectsFem.makeElementFluid1D(self.active_doc, "ElementFluid1D") Flow1d_bend.SectionType = 'Liquid' Flow1d_bend.LiquidSectionType = 'PIPE BEND' Flow1d_bend.BendPipeArea = 31416 Flow1d_bend.BendRadiusDiameter = 1.5 Flow1d_bend.BendAngle = 45 Flow1d_bend.BendLossCoefficient = 0.4 Flow1d_bend.References = [(line, "Edge4")] self.assertTrue(Flow1d_bend, "FemTest of new Flow1D bend constraint failed") analysis.addObject(Flow1d_bend) fcc_print('Checking FEM new Flow1D enlargement constraint...') Flow1d_enlargement = ObjectsFem.makeElementFluid1D( self.active_doc, "ElementFluid1D") Flow1d_enlargement.SectionType = 'Liquid' Flow1d_enlargement.LiquidSectionType = 'PIPE ENLARGEMENT' Flow1d_enlargement.EnlargeArea1 = 31416.00 Flow1d_enlargement.EnlargeArea2 = 70686.00 Flow1d_enlargement.References = [(line, "Edge6")] self.assertTrue(Flow1d_enlargement, "FemTest of new Flow1D enlargement constraint failed") analysis.addObject(Flow1d_enlargement) fcc_print('Checking FEM new Flow1D manning constraint...') Flow1d_manning1 = ObjectsFem.makeElementFluid1D( self.active_doc, "ElementFluid1D") Flow1d_manning1.SectionType = 'Liquid' Flow1d_manning1.LiquidSectionType = 'PIPE MANNING' Flow1d_manning1.ManningArea = 70686.00 Flow1d_manning1.ManningRadius = 75 Flow1d_manning1.ManningCoefficient = 0.002 Flow1d_manning1.References = [(line, "Edge7")] self.assertTrue(Flow1d_manning1, "FemTest of new Flow1D manning constraint failed") analysis.addObject(Flow1d_manning1) fcc_print('Checking FEM new Flow1D contraction constraint...') Flow1d_contraction = ObjectsFem.makeElementFluid1D( self.active_doc, "ElementFluid1D") Flow1d_contraction.SectionType = 'Liquid' Flow1d_contraction.LiquidSectionType = 'PIPE CONTRACTION' Flow1d_contraction.ContractArea1 = 70686 Flow1d_contraction.ContractArea2 = 17671 Flow1d_contraction.References = [(line, "Edge8")] self.assertTrue(Flow1d_contraction, "FemTest of new Flow1D contraction constraint failed") analysis.addObject(Flow1d_contraction) fcc_print('Checking FEM new Flow1D manning constraint...') Flow1d_manning2 = ObjectsFem.makeElementFluid1D( self.active_doc, "ElementFluid1D") Flow1d_manning2.SectionType = 'Liquid' Flow1d_manning2.LiquidSectionType = 'PIPE MANNING' Flow1d_manning2.ManningArea = 17671.00 Flow1d_manning2.ManningRadius = 37.5 Flow1d_manning2.ManningCoefficient = 0.002 Flow1d_manning2.References = [(line, "Edge11"), (line, "Edge9")] self.assertTrue(Flow1d_manning2, "FemTest of new Flow1D manning constraint failed") analysis.addObject(Flow1d_manning2) fcc_print('Checking FEM new Flow1D gate valve constraint...') Flow1d_gate_valve = ObjectsFem.makeElementFluid1D( self.active_doc, "ElementFluid1D") Flow1d_gate_valve.SectionType = 'Liquid' Flow1d_gate_valve.LiquidSectionType = 'PIPE GATE VALVE' Flow1d_gate_valve.GateValvePipeArea = 17671 Flow1d_gate_valve.GateValveClosingCoeff = 0.5 Flow1d_gate_valve.References = [(line, "Edge10")] self.assertTrue(Flow1d_gate_valve, "FemTest of new Flow1D gate valve constraint failed") analysis.addObject(Flow1d_gate_valve) fcc_print('Checking FEM new Flow1D enlargement constraint...') Flow1d_enlargement1 = ObjectsFem.makeElementFluid1D( self.active_doc, "ElementFluid1D") Flow1d_enlargement1.SectionType = 'Liquid' Flow1d_enlargement1.LiquidSectionType = 'PIPE ENLARGEMENT' Flow1d_enlargement1.EnlargeArea1 = 17671 Flow1d_enlargement1.EnlargeArea2 = 1e12 Flow1d_enlargement1.References = [(line, "Edge12")] self.assertTrue(Flow1d_enlargement1, "FemTest of new Flow1D enlargement constraint failed") analysis.addObject(Flow1d_enlargement1) fcc_print('Checking FEM Flow1D outlet constraint...') Flow1d_outlet = ObjectsFem.makeElementFluid1D(self.active_doc, "ElementFluid1D") Flow1d_outlet.SectionType = 'Liquid' Flow1d_outlet.LiquidSectionType = 'PIPE OUTLET' Flow1d_outlet.OutletPressure = 0.1 Flow1d_outlet.References = [(line, "Edge13")] self.assertTrue(Flow1d_outlet, "FemTest of new Flow1D inlet constraint failed") analysis.addObject(Flow1d_outlet) fcc_print('Checking FEM self weight constraint...') Flow1d_self_weight = ObjectsFem.makeConstraintSelfWeight( self.active_doc, "ConstraintSelfWeight") Flow1d_self_weight.Gravity_x = 0.0 Flow1d_self_weight.Gravity_y = 0.0 Flow1d_self_weight.Gravity_z = -1.0 self.assertTrue(Flow1d_outlet, "FemTest of new Flow1D self weight constraint failed") analysis.addObject(Flow1d_self_weight) fcc_print('Checking FEM new mesh...') from .testfiles.ccx.Flow1D_mesh import create_nodes_Flow1D from .testfiles.ccx.Flow1D_mesh import create_elements_Flow1D mesh = Fem.FemMesh() ret = create_nodes_Flow1D(mesh) self.assertTrue(ret, "Import of mesh nodes failed") ret = create_elements_Flow1D(mesh) self.assertTrue(ret, "Import of mesh volumes failed") mesh_object = self.active_doc.addObject('Fem::FemMeshObject', self.mesh_name) mesh_object.FemMesh = mesh self.assertTrue(mesh, "FemTest of new mesh failed") analysis.addObject(mesh_object) self.active_doc.recompute() Flow1D_thermomech_analysis_dir = self.temp_dir + 'FEM_ccx_Flow1D_thermomech/' fea = ccxtools.FemToolsCcx(analysis, test_mode=True) fcc_print('Setting up working directory {}'.format( Flow1D_thermomech_analysis_dir)) fea.setup_working_dir(Flow1D_thermomech_analysis_dir) self.assertTrue( True if fea.working_dir == Flow1D_thermomech_analysis_dir else False, "Setting working directory {} failed".format( Flow1D_thermomech_analysis_dir)) fcc_print( 'Checking FEM inp file prerequisites for thermo-mechanical analysis...' ) error = fea.check_prerequisites() self.assertFalse( error, "ccxtools check_prerequisites returned error message: {}".format( error)) fcc_print('Checking FEM inp file write...') fcc_print('Writing {}/{}.inp for thermomech analysis'.format( Flow1D_thermomech_analysis_dir, self.mesh_name)) error = fea.write_inp_file() self.assertFalse(error, "Writing failed") Flow1D_thermomech_base_name = 'Flow1D_thermomech' Flow1D_thermomech_analysis_inp_file = self.test_file_dir + Flow1D_thermomech_base_name + '.inp' fcc_print('Comparing {} to {}/{}.inp'.format( Flow1D_thermomech_analysis_inp_file, Flow1D_thermomech_analysis_dir, self.mesh_name)) ret = testtools.compare_inp_files( Flow1D_thermomech_analysis_inp_file, Flow1D_thermomech_analysis_dir + self.mesh_name + '.inp') self.assertFalse( ret, "ccxtools write_inp_file test failed.\n{}".format(ret)) fcc_print( 'Setting up working directory to {} in order to read simulated calculations' .format(self.test_file_dir)) fea.setup_working_dir(self.test_file_dir) self.assertTrue( True if fea.working_dir == self.test_file_dir else False, "Setting working directory {} failed".format(self.test_file_dir)) fcc_print('Setting base name to read test {}.frd file...'.format( 'Flow1D_thermomech')) fea.set_base_name(Flow1D_thermomech_base_name) self.assertTrue( True if fea.base_name == Flow1D_thermomech_base_name else False, "Setting base name to {} failed".format( Flow1D_thermomech_base_name)) fcc_print('Setting inp file name to read test {}.frd file...'.format( 'Flow1D_thermomech')) fea.set_inp_file_name() self.assertTrue( True if fea.inp_file_name == Flow1D_thermomech_analysis_inp_file else False, "Setting inp file name to {} failed".format( Flow1D_thermomech_analysis_inp_file)) fcc_print( 'Checking FEM frd file read from Flow1D thermomech analysis...') fea.load_results() self.assertTrue( fea.results_present, "Cannot read results from {}.frd frd file".format(fea.base_name)) fcc_print( 'Reading stats from result object for Flow1D thermomech analysis...' ) Flow1D_thermomech_expected_values = self.test_file_dir + "Flow1D_thermomech_expected_values" stat_types = [ "U1", "U2", "U3", "Uabs", "Sabs", "MaxPrin", "MidPrin", "MinPrin", "MaxShear", "Peeq", "Temp", "MFlow", "NPress" ] ret = testtools.compare_stats(fea, Flow1D_thermomech_expected_values, stat_types, 'CalculiX_thermomech_time_1_0_results') self.assertFalse(ret, "Invalid results read from .frd file") Flow1D_thermomech_save_fc_file = Flow1D_thermomech_analysis_dir + Flow1D_thermomech_base_name + '.fcstd' fcc_print('Save FreeCAD file for thermomech analysis to {}...'.format( Flow1D_thermomech_save_fc_file)) self.active_doc.saveAs(Flow1D_thermomech_save_fc_file) fcc_print( '--------------- End of FEM tests FLow 1D thermomech analysis ---------------' )
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): print("Found: nodes") 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'] print("Found: elements") 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) print( "imported mesh: {} nodes, {} HEXA8, {} PENTA6, {} TETRA4, {} TETRA10, {} PENTA15" .format(len(nds), len(elms_hexa8), len(elms_penta6), len(elms_tetra4), len(elms_tetra10), len(elms_penta15))) print( "imported mesh: {} HEXA20, {} TRIA3, {} TRIA6, {} QUAD4, {} QUAD8, {} SEG2, {} SEG3" .format(len(elms_hexa20), len(elms_tria3), len(elms_tria6), len(elms_quad4), len(elms_quad8), len(elms_seg2), len(elms_seg3))) else: FreeCAD.Console.PrintError("No Elements found!\n") else: FreeCAD.Console.PrintError("No Nodes found!\n") return mesh
def test_thermomech_analysis(self): fcc_print('--------------- Start of FEM tests ---------------') box = self.active_doc.addObject("Part::Box", "Box") box.Height = 25.4 box.Width = 25.4 box.Length = 203.2 fcc_print('Checking FEM new analysis...') analysis = ObjectsFem.makeAnalysis(self.active_doc, 'Analysis') self.assertTrue(analysis, "FemTest of new analysis failed") fcc_print('Checking FEM new solver...') solver_object = ObjectsFem.makeSolverCalculixCcxTools( self.active_doc, 'CalculiX') solver_object.AnalysisType = 'thermomech' solver_object.GeometricalNonlinearity = 'linear' solver_object.ThermoMechSteadyState = True solver_object.MatrixSolverType = 'default' solver_object.IterationsThermoMechMaximum = 2000 solver_object.IterationsControlParameterTimeUse = True self.assertTrue(solver_object, "FemTest of new solver failed") analysis.addObject(solver_object) fcc_print('Checking FEM new material...') material_object = ObjectsFem.makeMaterialSolid(self.active_doc, 'MechanicalMaterial') mat = material_object.Material mat['Name'] = "Steel-Generic" mat['YoungsModulus'] = "200000 MPa" mat['PoissonRatio'] = "0.30" mat['Density'] = "7900 kg/m^3" mat['ThermalConductivity'] = "43.27 W/m/K" # SvdW: Change to Ansys model values mat['ThermalExpansionCoefficient'] = "12 um/m/K" mat['SpecificHeat'] = "500 J/kg/K" # SvdW: Change to Ansys model values material_object.Material = mat self.assertTrue(material_object, "FemTest of new material failed") analysis.addObject(material_object) fcc_print('Checking FEM new fixed constraint...') fixed_constraint = self.active_doc.addObject("Fem::ConstraintFixed", "FemConstraintFixed") fixed_constraint.References = [(box, "Face1")] self.assertTrue(fixed_constraint, "FemTest of new fixed constraint failed") analysis.addObject(fixed_constraint) fcc_print('Checking FEM new initial temperature constraint...') initialtemperature_constraint = self.active_doc.addObject( "Fem::ConstraintInitialTemperature", "FemConstraintInitialTemperature") initialtemperature_constraint.initialTemperature = 300.0 self.assertTrue( initialtemperature_constraint, "FemTest of new initial temperature constraint failed") analysis.addObject(initialtemperature_constraint) fcc_print('Checking FEM new temperature constraint...') temperature_constraint = self.active_doc.addObject( "Fem::ConstraintTemperature", "FemConstraintTemperature") temperature_constraint.References = [(box, "Face1")] temperature_constraint.Temperature = 310.93 self.assertTrue(temperature_constraint, "FemTest of new temperature constraint failed") analysis.addObject(temperature_constraint) fcc_print('Checking FEM new heatflux constraint...') heatflux_constraint = self.active_doc.addObject( "Fem::ConstraintHeatflux", "FemConstraintHeatflux") heatflux_constraint.References = [(box, "Face3"), (box, "Face4"), (box, "Face5"), (box, "Face6")] heatflux_constraint.AmbientTemp = 255.3722 heatflux_constraint.FilmCoef = 5.678 self.assertTrue(heatflux_constraint, "FemTest of new heatflux constraint failed") analysis.addObject(heatflux_constraint) fcc_print('Checking FEM new mesh...') from .testfiles.ccx.spine_mesh import create_nodes_spine from .testfiles.ccx.spine_mesh import create_elements_spine mesh = Fem.FemMesh() ret = create_nodes_spine(mesh) self.assertTrue(ret, "Import of mesh nodes failed") ret = create_elements_spine(mesh) self.assertTrue(ret, "Import of mesh volumes failed") mesh_object = self.active_doc.addObject('Fem::FemMeshObject', self.mesh_name) mesh_object.FemMesh = mesh self.assertTrue(mesh, "FemTest of new mesh failed") analysis.addObject(mesh_object) self.active_doc.recompute() thermomech_analysis_dir = self.temp_dir + 'FEM_ccx_thermomech/' fea = ccxtools.FemToolsCcx(analysis, test_mode=True) fcc_print( 'Setting up working directory {}'.format(thermomech_analysis_dir)) fea.setup_working_dir(thermomech_analysis_dir) self.assertTrue( True if fea.working_dir == thermomech_analysis_dir else False, "Setting working directory {} failed".format( thermomech_analysis_dir)) fcc_print( 'Checking FEM inp file prerequisites for thermo-mechanical analysis...' ) error = fea.check_prerequisites() self.assertFalse( error, "ccxtools check_prerequisites returned error message: {}".format( error)) fcc_print('Checking FEM inp file write...') fcc_print('Writing {}/{}.inp for thermomech analysis'.format( thermomech_analysis_dir, self.mesh_name)) error = fea.write_inp_file() self.assertFalse(error, "Writing failed") thermomech_base_name = 'spine_thermomech' thermomech_analysis_inp_file = self.test_file_dir + thermomech_base_name + '.inp' fcc_print('Comparing {} to {}/{}.inp'.format( thermomech_analysis_inp_file, thermomech_analysis_dir, self.mesh_name)) ret = testtools.compare_inp_files( thermomech_analysis_inp_file, thermomech_analysis_dir + self.mesh_name + '.inp') self.assertFalse( ret, "ccxtools write_inp_file test failed.\n{}".format(ret)) fcc_print( 'Setting up working directory to {} in order to read simulated calculations' .format(self.test_file_dir)) fea.setup_working_dir(self.test_file_dir) self.assertTrue( True if fea.working_dir == self.test_file_dir else False, "Setting working directory {} failed".format(self.test_file_dir)) fcc_print('Setting base name to read test {}.frd file...'.format( 'spine_thermomech')) fea.set_base_name(thermomech_base_name) self.assertTrue( True if fea.base_name == thermomech_base_name else False, "Setting base name to {} failed".format(thermomech_base_name)) fcc_print('Setting inp file name to read test {}.frd file...'.format( 'spine_thermomech')) fea.set_inp_file_name() self.assertTrue( True if fea.inp_file_name == thermomech_analysis_inp_file else False, "Setting inp file name to {} failed".format( thermomech_analysis_inp_file)) fcc_print('Checking FEM frd file read from thermomech analysis...') fea.load_results() self.assertTrue( fea.results_present, "Cannot read results from {}.frd frd file".format(fea.base_name)) fcc_print( 'Reading stats from result object for thermomech analysis...') thermomech_expected_values = self.test_file_dir + "spine_thermomech_expected_values" ret = testtools.compare_stats(fea, thermomech_expected_values, 'CalculiX_thermomech_results') self.assertFalse(ret, "Invalid results read from .frd file") thermomech_save_fc_file = thermomech_analysis_dir + thermomech_base_name + '.fcstd' fcc_print('Save FreeCAD file for thermomech analysis to {}...'.format( thermomech_save_fc_file)) self.active_doc.saveAs(thermomech_save_fc_file) fcc_print( '--------------- End of FEM tests thermomech analysis ---------------' )
def setup(doc=None, solvertype="ccxtools"): # setup model if doc is None: doc = init_doc() # parts # TODO turn circle of upper tube to have the line on the other side # make a boolean fragment of them to be sure there is a mesh point on remesh # but as long as we do not remesh it works without the boolean fragment too # tubes tube_radius = 25 tube_length = 500 sh_lower_circle = Part.Wire(Part.makeCircle(tube_radius)) sh_lower_tube = sh_lower_circle.extrude(FreeCAD.Vector(0, 0, tube_length)) sh_lower_tube.reverse() lower_tube = doc.addObject("Part::Feature", "Lower_tube") lower_tube.Shape = sh_lower_tube sh_upper_circle = Part.Wire(Part.makeCircle(tube_radius)) sh_upper_tube = sh_upper_circle.extrude(FreeCAD.Vector(0, 0, tube_length)) sh_upper_tube.reverse() upper_tube = doc.addObject("Part::Feature", "Upper_tube") upper_tube.Shape = sh_upper_tube upper_tube.Placement = FreeCAD.Placement( FreeCAD.Vector(-25, 51, 475), FreeCAD.Rotation(90, 0, 90), FreeCAD.Vector(0, 0, 0), ) # point for load v_force_pt = FreeCAD.Vector(0, 76, 475) sh_force_point = Part.Vertex(v_force_pt) force_point = doc.addObject("Part::Feature", "Load_place_point") force_point.Shape = sh_force_point if FreeCAD.GuiUp: force_point.ViewObject.PointSize = 10.0 force_point.ViewObject.PointColor = (1.0, 0.0, 0.0) BooleanFrag = BOPTools.SplitFeatures.makeBooleanFragments( name='BooleanFragments') BooleanFrag.Objects = [upper_tube, force_point] if FreeCAD.GuiUp: upper_tube.ViewObject.hide() compound = doc.addObject("Part::Compound", "Compound") compound.Links = [BooleanFrag, lower_tube] # line for load direction sh_load_line = Part.makeLine(v_force_pt, FreeCAD.Vector(0, 150, 475)) load_line = doc.addObject("Part::Feature", "Load_direction_line") load_line.Shape = sh_load_line if FreeCAD.GuiUp: load_line.ViewObject.LineWidth = 5.0 load_line.ViewObject.LineColor = (1.0, 0.0, 0.0) doc.recompute() if FreeCAD.GuiUp: import FreeCADGui FreeCADGui.ActiveDocument.activeView().viewAxonometric() FreeCADGui.SendMsgToActiveView("ViewFit") # analysis analysis = ObjectsFem.makeAnalysis(doc, "Analysis") # solver if solvertype == "calculix": solver_object = analysis.addObject( ObjectsFem.makeSolverCalculix(doc, "SolverCalculiX"))[0] elif solvertype == "ccxtools": solver_object = analysis.addObject( ObjectsFem.makeSolverCalculixCcxTools(doc, "CalculiXccxTools"))[0] solver_object.WorkingDir = u"" if solvertype == "calculix" or solvertype == "ccxtools": solver_object.AnalysisType = "static" solver_object.BeamShellResultOutput3D = True solver_object.GeometricalNonlinearity = "linear" # really? # TODO iterations parameter !!! solver_object.ThermoMechSteadyState = False solver_object.MatrixSolverType = "default" solver_object.IterationsControlParameterTimeUse = False solver_object.SplitInputWriter = False # shell thickness analysis.addObject( ObjectsFem.makeElementGeometry2D(doc, 0.5, 'ShellThickness')) # material material_obj = analysis.addObject( ObjectsFem.makeMaterialSolid(doc, "MechanicalMaterial"))[0] mat = material_obj.Material mat["Name"] = "AlCuMgPb" mat["YoungsModulus"] = "72000 MPa" mat["PoissonRatio"] = "0.30" material_obj.Material = mat analysis.addObject(material_obj) # fixed_constraint fixed_constraint = analysis.addObject( ObjectsFem.makeConstraintFixed(doc, "ConstraintFixed"))[0] fixed_constraint.References = [ (lower_tube, "Edge2"), (upper_tube, "Edge3"), ] # force_constraint force_constraint = doc.Analysis.addObject( ObjectsFem.makeConstraintForce(doc, name="ConstraintForce"))[0] # TODO use point of tube boolean fragment force_constraint.References = [(force_point, "Vertex1")] force_constraint.Force = 5000.0 force_constraint.Direction = (load_line, ["Edge1"]) force_constraint.Reversed = True # contact constraint contact_constraint = doc.Analysis.addObject( ObjectsFem.makeConstraintContact(doc, name="ConstraintContact"))[0] contact_constraint.References = [ (lower_tube, "Face1"), (upper_tube, "Face1"), ] contact_constraint.Friction = 0.0 # contact_constrsh_aint.Slope = "1000000.0 kg/(mm*s^2)" # contact stiffness contact_constraint.Slope = 1000000.0 # should be 1000000.0 kg/(mm*s^2) # mesh from .meshes.mesh_contact_tube_tube_tria3 import create_nodes, create_elements fem_mesh = Fem.FemMesh() control = create_nodes(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating nodes.\n") control = create_elements(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating elements.\n") femmesh_obj = analysis.addObject( doc.addObject("Fem::FemMeshObject", mesh_name))[0] femmesh_obj.FemMesh = fem_mesh doc.recompute() return doc
def setup(doc=None, solvertype="ccxtools"): # init FreeCAD document if doc is None: doc = init_doc() # explanation object # just keep the following line and change text string in get_explanation method manager.add_explanation_obj( doc, get_explanation(manager.get_header(get_information()))) # geometric object # name is important because the other method in this module use obj name l1 = Part.makeLine((-142.5, -142.5, 0), (142.5, -142.5, 0)) l2 = Part.makeLine((142.5, -142.5, 0), (142.5, 142.5, 0)) l3 = Part.makeLine((142.5, 142.5, 0), (-142.5, 142.5, 0)) l4 = Part.makeLine((-142.5, 142.5, 0), (-142.5, -142.5, 0)) wire = Part.Wire([l1, l2, l3, l4]) shape = wire.extrude(Vector(0, 0, 1000)) geom_obj = doc.addObject('Part::Feature', 'SquareTube') geom_obj.Shape = shape doc.recompute() if FreeCAD.GuiUp: geom_obj.ViewObject.Document.activeView().viewAxonometric() geom_obj.ViewObject.Document.activeView().fitAll() # analysis analysis = ObjectsFem.makeAnalysis(doc, "Analysis") # solver if solvertype == "calculix": solver_obj = ObjectsFem.makeSolverCalculix(doc, "SolverCalculiX") elif solvertype == "ccxtools": solver_obj = ObjectsFem.makeSolverCalculixCcxTools( doc, "CalculiXccxTools") solver_obj.WorkingDir = u"" else: FreeCAD.Console.PrintWarning( "Not known or not supported solver type: {}. " "No solver object was created.\n".format(solvertype)) if solvertype == "calculix" or solvertype == "ccxtools": solver_obj.SplitInputWriter = False solver_obj.AnalysisType = "static" solver_obj.GeometricalNonlinearity = "linear" solver_obj.ThermoMechSteadyState = False solver_obj.MatrixSolverType = "default" solver_obj.IterationsControlParameterTimeUse = False analysis.addObject(solver_obj) # shell thickness thickness_obj = ObjectsFem.makeElementGeometry2D(doc, 15.0, "ShellThickness") analysis.addObject(thickness_obj) # material material_obj = ObjectsFem.makeMaterialSolid(doc, "FemMaterial") mat = material_obj.Material mat["Name"] = "Steel-Generic" mat["YoungsModulus"] = "200000 MPa" mat["PoissonRatio"] = "0.30" mat["Density"] = "7900 kg/m^3" material_obj.Material = mat analysis.addObject(material_obj) # constraint fixed con_fixed = ObjectsFem.makeConstraintFixed(doc, "ConstraintFixed") con_fixed.References = [(doc.SquareTube, "Edge4"), (doc.SquareTube, "Edge7"), (doc.SquareTube, "Edge10"), (doc.SquareTube, "Edge12")] analysis.addObject(con_fixed) # con_force1 con_force1 = ObjectsFem.makeConstraintForce(doc, name="ConstraintForce1") con_force1.References = [(geom_obj, "Edge9")] con_force1.Force = 100000.00 con_force1.Direction = (geom_obj, ["Edge9"]) con_force1.Reversed = True analysis.addObject(con_force1) # con_force2 con_force2 = ObjectsFem.makeConstraintForce(doc, name="ConstraintForce2") con_force2.References = [(geom_obj, "Edge3")] con_force2.Force = 100000.00 con_force2.Direction = (geom_obj, ["Edge3"]) con_force2.Reversed = True analysis.addObject(con_force2) # con_force3 con_force3 = ObjectsFem.makeConstraintForce(doc, name="ConstraintForce3") con_force3.References = [(geom_obj, "Edge11")] con_force3.Force = 100000.00 con_force3.Direction = (geom_obj, ["Edge11"]) con_force3.Reversed = True analysis.addObject(con_force3) # con_force4 con_force4 = ObjectsFem.makeConstraintForce(doc, name="ConstraintForce4") con_force4.References = [(geom_obj, "Edge6")] con_force4.Force = 100000.00 con_force4.Direction = (geom_obj, ["Edge6"]) con_force4.Reversed = True analysis.addObject(con_force4) # mesh from .meshes.mesh_square_pipe_end_twisted_tria6 import create_nodes, create_elements fem_mesh = Fem.FemMesh() control = create_nodes(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating nodes.\n") control = create_elements(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating elements.\n") femmesh_obj = analysis.addObject( ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0] femmesh_obj.FemMesh = fem_mesh femmesh_obj.Part = geom_obj femmesh_obj.SecondOrderLinear = False doc.recompute() return doc
def setup(doc=None, solvertype="ccxtools"): # setup model if doc is None: doc = init_doc() # part # create a CompSolid of two Boxes extract the CompSolid # we are able to remesh if needed boxlow = doc.addObject("Part::Box", "BoxLower") boxupp = doc.addObject("Part::Box", "BoxUpper") boxupp.Placement.Base = (0, 0, 10) # for BooleanFragments Occt >=6.9 is needed """ import BOPTools.SplitFeatures bf = BOPTools.SplitFeatures.makeBooleanFragments(name="BooleanFragments") bf.Objects = [boxlow, boxupp] bf.Mode = "CompSolid" self.active_doc.recompute() bf.Proxy.execute(bf) bf.purgeTouched() for obj in bf.ViewObject.Proxy.claimChildren(): obj.ViewObject.hide() self.active_doc.recompute() import CompoundTools.CompoundFilter cf = CompoundTools.CompoundFilter.makeCompoundFilter(name="MultiMatCompSolid") cf.Base = bf cf.FilterType = "window-volume" cf.Proxy.execute(cf) cf.purgeTouched() cf.Base.ViewObject.hide() """ doc.recompute() if FreeCAD.GuiUp: import FreeCADGui FreeCADGui.ActiveDocument.activeView().viewAxonometric() FreeCADGui.SendMsgToActiveView("ViewFit") # analysis analysis = ObjectsFem.makeAnalysis(doc, "Analysis") # solver if solvertype == "calculix": solver_object = analysis.addObject( ObjectsFem.makeSolverCalculix(doc, "SolverCalculiX") )[0] elif solvertype == "ccxtools": solver_object = analysis.addObject( ObjectsFem.makeSolverCalculixCcxTools(doc, "CalculiXccxTools") )[0] solver_object.WorkingDir = u"" if solvertype == "calculix" or solvertype == "ccxtools": solver_object.SplitInputWriter = False solver_object.AnalysisType = "static" solver_object.GeometricalNonlinearity = "linear" solver_object.ThermoMechSteadyState = False solver_object.MatrixSolverType = "default" solver_object.IterationsControlParameterTimeUse = False # material material_object_low = analysis.addObject( ObjectsFem.makeMaterialSolid(doc, "MechanicalMaterialLow") )[0] mat = material_object_low.Material mat["Name"] = "Aluminium-Generic" mat["YoungsModulus"] = "70000 MPa" mat["PoissonRatio"] = "0.35" mat["Density"] = "2700 kg/m^3" material_object_low.Material = mat material_object_low.References = [(boxlow, "Solid1")] analysis.addObject(material_object_low) material_object_upp = analysis.addObject( ObjectsFem.makeMaterialSolid(doc, "MechanicalMaterialUpp") )[0] mat = material_object_upp.Material mat["Name"] = "Steel-Generic" mat["YoungsModulus"] = "200000 MPa" mat["PoissonRatio"] = "0.30" mat["Density"] = "7980 kg/m^3" material_object_upp.Material = mat material_object_upp.References = [(boxupp, "Solid1")] # fixed_constraint fixed_constraint = analysis.addObject( ObjectsFem.makeConstraintFixed(doc, "ConstraintFixed") )[0] # fixed_constraint.References = [(cf, "Face3")] fixed_constraint.References = [(boxlow, "Face5")] # pressure_constraint pressure_constraint = analysis.addObject( ObjectsFem.makeConstraintPressure(doc, "ConstraintPressure") )[0] # pressure_constraint.References = [(cf, "Face3")] pressure_constraint.References = [(boxlow, "Face5")] # pressure_constraint.References = [(cf, "Face9")] pressure_constraint.References = [(boxupp, "Face6")] pressure_constraint.Pressure = 1000.0 pressure_constraint.Reversed = False # mesh from .meshes.mesh_boxes_2_vertikal_tetra10 import create_nodes, create_elements fem_mesh = Fem.FemMesh() control = create_nodes(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating nodes.\n") control = create_elements(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating elements.\n") femmesh_obj = analysis.addObject( doc.addObject("Fem::FemMeshObject", mesh_name) )[0] femmesh_obj.FemMesh = fem_mesh doc.recompute() return doc
def setup_cantileverbase(doc=None, solvertype="ccxtools"): # setup CalculiX cantilever base model if doc is None: doc = init_doc() # geometry object # name is important because the other method in this module use obj name geom_obj = doc.addObject("Part::Box", "Box") geom_obj.Height = geom_obj.Width = 1000 geom_obj.Length = 8000 doc.recompute() if FreeCAD.GuiUp: geom_obj.ViewObject.Document.activeView().viewAxonometric() geom_obj.ViewObject.Document.activeView().fitAll() # analysis analysis = ObjectsFem.makeAnalysis(doc, "Analysis") # solver if solvertype == "calculix": solver_object = analysis.addObject( ObjectsFem.makeSolverCalculix(doc, "SolverCalculiX"))[0] elif solvertype == "ccxtools": solver_object = analysis.addObject( ObjectsFem.makeSolverCalculixCcxTools(doc, "CalculiXccxTools"))[0] solver_object.WorkingDir = u"" elif solvertype == "elmer": analysis.addObject(ObjectsFem.makeSolverElmer(doc, "SolverElmer")) elif solvertype == "z88": analysis.addObject(ObjectsFem.makeSolverZ88(doc, "SolverZ88")) if solvertype == "calculix" or solvertype == "ccxtools": solver_object.SplitInputWriter = False solver_object.AnalysisType = "static" solver_object.GeometricalNonlinearity = "linear" solver_object.ThermoMechSteadyState = False solver_object.MatrixSolverType = "default" solver_object.IterationsControlParameterTimeUse = False # material material_object = analysis.addObject( ObjectsFem.makeMaterialSolid(doc, "FemMaterial"))[0] mat = material_object.Material mat["Name"] = "CalculiX-Steel" mat["YoungsModulus"] = "210000 MPa" mat["PoissonRatio"] = "0.30" mat["Density"] = "7900 kg/m^3" mat["ThermalExpansionCoefficient"] = "0.012 mm/m/K" material_object.Material = mat # fixed_constraint fixed_constraint = analysis.addObject( ObjectsFem.makeConstraintFixed(doc, name="ConstraintFixed"))[0] fixed_constraint.References = [(geom_obj, "Face1")] # mesh from .meshes.mesh_canticcx_tetra10 import create_nodes, create_elements fem_mesh = Fem.FemMesh() control = create_nodes(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating nodes.\n") control = create_elements(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating elements.\n") femmesh_obj = analysis.addObject( doc.addObject("Fem::FemMeshObject", mesh_name))[0] femmesh_obj.FemMesh = fem_mesh doc.recompute() return doc
def setup(doc=None, solvertype="ccxtools"): if doc is None: doc = init_doc() # geometry object # name is important because the other method in this module use obj name # parts face_obj1 = doc.addObject('Part::Plane', 'Face1') face_obj1.Width = 10 face_obj1.Length = 20 face_obj2 = doc.addObject('Part::Plane', 'Face2') face_obj2.Width = 10 face_obj2.Length = 20 face_obj2.Placement.Base = (20, 0, 0) face_obj3 = doc.addObject('Part::Plane', 'Face3') face_obj3.Width = 10 face_obj3.Length = 20 face_obj3.Placement.Base = (40, 0, 0) face_obj4 = doc.addObject('Part::Plane', 'Face4') face_obj4.Width = 10 face_obj4.Length = 20 face_obj4.Placement.Base = (60, 0, 0) face_obj5 = doc.addObject('Part::Plane', 'Face5') face_obj5.Width = 10 face_obj5.Length = 20 face_obj5.Placement.Base = (80, 0, 0) doc.recompute() # make a Shell out of the facees, to be able to remesh with GUI geom_obj = doc.addObject("Part::MultiFuse", "Fusion") geom_obj.Shapes = [face_obj1, face_obj2, face_obj3, face_obj4, face_obj5] if FreeCAD.GuiUp: face_obj1.ViewObject.hide() face_obj2.ViewObject.hide() face_obj3.ViewObject.hide() face_obj4.ViewObject.hide() face_obj5.ViewObject.hide() doc.recompute() if FreeCAD.GuiUp: geom_obj.ViewObject.Document.activeView().viewAxonometric() geom_obj.ViewObject.Document.activeView().fitAll() # analysis analysis = ObjectsFem.makeAnalysis(doc, "Analysis") # solver if solvertype == "calculix": solver_object = analysis.addObject( ObjectsFem.makeSolverCalculix(doc, "SolverCalculiX"))[0] elif solvertype == "ccxtools": solver_object = analysis.addObject( ObjectsFem.makeSolverCalculixCcxTools(doc, "CalculiXccxTools"))[0] solver_object.WorkingDir = u"" else: FreeCAD.Console.PrintWarning( "Not known or not supported solver type: {}. " "No solver object was created.\n".format(solvertype)) if solvertype == "calculix" or solvertype == "ccxtools": solver_object.SplitInputWriter = False solver_object.AnalysisType = "static" solver_object.GeometricalNonlinearity = "linear" solver_object.ThermoMechSteadyState = False solver_object.MatrixSolverType = "default" solver_object.IterationsControlParameterTimeUse = False # shell thickness analysis.addObject( ObjectsFem.makeElementGeometry2D(doc, 10, 'ShellThickness')) # materials # material1 material_object1 = analysis.addObject( ObjectsFem.makeMaterialSolid(doc, 'FemMaterial1'))[0] material_object1.References = [(doc.Face3, "Face1")] mat = material_object1.Material mat['Name'] = "Concrete-Generic" mat['YoungsModulus'] = "32000 MPa" mat['PoissonRatio'] = "0.17" mat['Density'] = "0 kg/m^3" material_object1.Material = mat # material2 material_object2 = analysis.addObject( ObjectsFem.makeMaterialSolid(doc, 'FemMaterial2'))[0] material_object2.References = [(doc.Face2, "Face1"), (doc.Face4, "Face1")] mat = material_object2.Material mat['Name'] = "PLA" mat['YoungsModulus'] = "3640 MPa" mat['PoissonRatio'] = "0.36" mat['Density'] = "0 kg/m^3" material_object2.Material = mat # material3 material_object3 = analysis.addObject( ObjectsFem.makeMaterialSolid(doc, 'FemMaterial3'))[0] material_object3.References = [] mat = material_object3.Material mat['Name'] = "Steel-Generic" mat['YoungsModulus'] = "200000 MPa" mat['PoissonRatio'] = "0.30" mat['Density'] = "7900 kg/m^3" material_object3.Material = mat # fixed_constraint fixed_constraint = analysis.addObject( ObjectsFem.makeConstraintFixed(doc, name="ConstraintFixed"))[0] fixed_constraint.References = [(doc.Face1, "Edge1"), (doc.Face5, "Edge3")] # force_constraint force_constraint = analysis.addObject( ObjectsFem.makeConstraintForce(doc, name="ConstraintForce"))[0] force_constraint.References = [(doc.Face1, "Edge4"), (doc.Face2, "Edge4"), (doc.Face3, "Edge4"), (doc.Face4, "Edge4"), (doc.Face5, "Edge4")] force_constraint.Force = 10000.00 force_constraint.Direction = (doc.Face1, ["Edge1"]) force_constraint.Reversed = True # mesh from .meshes.mesh_multibodybeam_tria6 import create_nodes, create_elements fem_mesh = Fem.FemMesh() control = create_nodes(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating nodes.\n") control = create_elements(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating elements.\n") femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, mesh_name))[0] femmesh_obj.FemMesh = fem_mesh femmesh_obj.Part = geom_obj femmesh_obj.SecondOrderLinear = False doc.recompute() return doc
def setup_cantileverbase(doc=None, solver="ccxtools"): # setup CalculiX cantilever base model if doc is None: doc = init_doc() # part box_obj = doc.addObject("Part::Box", "Box") box_obj.Height = box_obj.Width = 1000 box_obj.Length = 8000 # analysis analysis = ObjectsFem.makeAnalysis(doc, "Analysis") # solver # TODO How to pass multiple solver for one analysis in one doc if solver == "calculix": solver_object = analysis.addObject( ObjectsFem.makeSolverCalculix(doc, "SolverCalculiX") )[0] solver_object.AnalysisType = "static" solver_object.GeometricalNonlinearity = "linear" solver_object.ThermoMechSteadyState = False solver_object.MatrixSolverType = "default" solver_object.IterationsControlParameterTimeUse = False elif solver == "ccxtools": solver_object = analysis.addObject( ObjectsFem.makeSolverCalculixCcxTools(doc, "CalculiXccxTools") )[0] solver_object.AnalysisType = "static" solver_object.GeometricalNonlinearity = "linear" solver_object.ThermoMechSteadyState = False solver_object.MatrixSolverType = "default" solver_object.IterationsControlParameterTimeUse = False solver_object.WorkingDir = u"" elif solver == "elmer": analysis.addObject(ObjectsFem.makeSolverElmer(doc, "SolverElmer")) elif solver == "z88": analysis.addObject(ObjectsFem.makeSolverZ88(doc, "SolverZ88")) # material material_object = analysis.addObject( ObjectsFem.makeMaterialSolid(doc, "FemMaterial") )[0] mat = material_object.Material mat["Name"] = "CalculiX-Steel" mat["YoungsModulus"] = "210000 MPa" mat["PoissonRatio"] = "0.30" mat["Density"] = "7900 kg/m^3" mat["ThermalExpansionCoefficient"] = "0.012 mm/m/K" material_object.Material = mat # fixed_constraint fixed_constraint = analysis.addObject( ObjectsFem.makeConstraintFixed(doc, name="ConstraintFixed") )[0] fixed_constraint.References = [(doc.Box, "Face1")] # mesh from femexamples.meshes.mesh_canticcx_tetra10 import create_nodes, create_elements fem_mesh = Fem.FemMesh() control = create_nodes(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating nodes.\n") control = create_elements(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating elements.\n") femmesh_obj = analysis.addObject( doc.addObject("Fem::FemMeshObject", mesh_name) )[0] femmesh_obj.FemMesh = fem_mesh doc.recompute() return doc
def test_mesh_tetra10(self): # 10 node tetrahedron --> tetra10 elem = 'tetra10' femmesh = Fem.FemMesh() femmesh.addNode(6, 12, 18, 1) femmesh.addNode(0, 0, 18, 2) femmesh.addNode(12, 0, 18, 3) femmesh.addNode(6, 6, 0, 4) femmesh.addNode(3, 6, 18, 5) femmesh.addNode(6, 0, 18, 6) femmesh.addNode(9, 6, 18, 7) femmesh.addNode(6, 9, 9, 8) femmesh.addNode(3, 3, 9, 9) femmesh.addNode(9, 3, 9, 10) femmesh.addVolume([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) node_data = { 'count': femmesh.NodeCount, 'nodes': femmesh.Nodes } elem_data = {'volcount': femmesh.VolumeCount, 'tetcount': femmesh.TetraCount, 'volumes': { femmesh.Volumes[0], femmesh.getElementNodes(femmesh.Volumes[0]), }} expected_nodes = {'count': 10, 'nodes': { 1: FreeCAD.Vector(6.0, 12.0, 18.0), 2: FreeCAD.Vector(0.0, 0.0, 18.0), 3: FreeCAD.Vector(12.0, 0.0, 18.0), 4: FreeCAD.Vector(6.0, 6.0, 0.0), 5: FreeCAD.Vector(3.0, 6.0, 18.0), 6: FreeCAD.Vector(6.0, 0.0, 18.0), 7: FreeCAD.Vector(9.0, 6.0, 18.0), 8: FreeCAD.Vector(6.0, 9.0, 9.0), 9: FreeCAD.Vector(3.0, 3.0, 9.0), 10: FreeCAD.Vector(9.0, 3.0, 9.0), }} expected_elem = {'volcount': 1, 'tetcount': 1, 'volumes': { 1, (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) }} ''' fcc_print('\n') fcc_print(elem_data) fcc_print(expected_elem) fcc_print('\n') ''' self.assertEqual(node_data, expected_nodes, "Nodes of Python created " + elem + "mesh element are unexpected") self.assertEqual(elem_data, expected_elem, "Elements of Python created " + elem + "mesh element are unexpected") ''' obj = doc.addObject("Fem::FemMeshObject" , elem) obj.FemMesh = femmesh obj.Placement.Base = (30,50,0) obj.ViewObject.DisplayMode = "Faces, Wireframe & Nodes" ''' fcc_print(elem + 'export tests.\n') base_outfile = testtools.get_fem_test_tmp_dir() + '/' + elem + '_mesh.' base_testfile = testtools.get_fem_test_home_dir() + 'mesh/' + elem + '_mesh.' filetyp = 'inp' outfile = base_outfile + filetyp testfile = base_testfile + filetyp femmesh.writeABAQUS(outfile, 1, False) import feminout.importToolsFem import feminout.importInpMesh femmesh_outfile = feminout.importToolsFem.make_femmesh(feminout.importInpMesh.read_inp(outfile)) femmesh_testfile = feminout.importToolsFem.make_femmesh(feminout.importInpMesh.read_inp(testfile)) self.assertEqual(femmesh_outfile.Nodes, femmesh_testfile.Nodes, "Test writing " + elem + " mesh to " + filetyp + " file failed. Nodes are different.\n") self.assertEqual(femmesh_outfile.Volumes, femmesh_testfile.Volumes, "Test writing " + elem + " mesh to " + filetyp + " file failed. Volumes are different.\n") filetyp = 'unv' outfile = base_outfile + filetyp testfile = base_testfile + filetyp femmesh.write(outfile) femmesh_outfile = Fem.read(outfile) femmesh_testfile = Fem.read(testfile) self.assertEqual(femmesh_outfile.Nodes, femmesh_testfile.Nodes, "Test writing " + elem + " mesh to " + filetyp + " file failed. Nodes are different.\n") self.assertEqual(femmesh_outfile.Volumes, femmesh_testfile.Volumes, "Test writing " + elem + " mesh to " + filetyp + " file failed. Volumes are different.\n")
def setup_cantileverbase(doc=None, solver='ccxtools'): # setup CalculiX cantilever base model if doc is None: doc = init_doc() # part box_obj = doc.addObject('Part::Box', 'Box') box_obj.Height = box_obj.Width = 1000 box_obj.Length = 8000 # analysis analysis = ObjectsFem.makeAnalysis(doc, 'Analysis') solver # TODO How to pass multiple solver for one analysis in one doc if solver is None: pass # no solver is added elif solver is 'calculix': solver_object = analysis.addObject( ObjectsFem.makeSolverCalculix(doc, 'SolverCalculiX'))[0] solver_object.AnalysisType = 'static' solver_object.GeometricalNonlinearity = 'linear' solver_object.ThermoMechSteadyState = False solver_object.MatrixSolverType = 'default' solver_object.IterationsControlParameterTimeUse = False elif solver is 'ccxtools': solver_object = analysis.addObject( ObjectsFem.makeSolverCalculixCcxTools(doc, 'CalculiXccxTools'))[0] solver_object.AnalysisType = 'static' solver_object.GeometricalNonlinearity = 'linear' solver_object.ThermoMechSteadyState = False solver_object.MatrixSolverType = 'default' solver_object.IterationsControlParameterTimeUse = False solver_object.WorkingDir = u'' elif solver is 'elmer': analysis.addObject(ObjectsFem.makeSolverElmer(doc, 'SolverElmer')) elif solver is 'z88': analysis.addObject(ObjectsFem.makeSolverZ88(doc, 'SolverZ88')) # material material_object = analysis.addObject( ObjectsFem.makeMaterialSolid(doc, 'FemMaterial'))[0] mat = material_object.Material mat['Name'] = "CalculiX-Steel" mat['YoungsModulus'] = "210000 MPa" mat['PoissonRatio'] = "0.30" mat['Density'] = "7900 kg/m^3" mat['ThermalExpansionCoefficient'] = "0.012 mm/m/K" material_object.Material = mat # fixed_constraint fixed_constraint = analysis.addObject( ObjectsFem.makeConstraintFixed(doc, name="ConstraintFixed"))[0] fixed_constraint.References = [(doc.Box, "Face1")] # mesh from femexamples.meshes.mesh_canticcx_tetra10 import create_nodes, create_elements fem_mesh = Fem.FemMesh() control = create_nodes(fem_mesh) if not control: print('ERROR on creating nodes') control = create_elements(fem_mesh) if not control: print('ERROR on creating elements') femmesh_obj = analysis.addObject( doc.addObject('Fem::FemMeshObject', mesh_name))[0] femmesh_obj.FemMesh = fem_mesh doc.recompute() return doc
def start_calculation(self): self.button_add_to_table.setEnabled(False) self.button_select_file.setEnabled(False) self.button_select_output.setEnabled(False) self.button_start_calculation.setEnabled(False) os.chdir(homepath) ##Get values from the GUI if ( os.path.exists(str(self.dirname)) ): os.chdir(homepath) shutil.rmtree(str(self.dirname)) os.mkdir(str(self.dirname)) batch = open(str(self.dirname + "/" + "lcmt_CALCULIX_Calculation_batch.bat"),'wb') batch.write("#!/bin/bash\n") batch.write("export CCX_NPROC=4\n") #Tell calculixs solver spooles how many cpus to use #batch.write("export CCX_NPROC=" + str(self.params.GetInt("NumberCPUs")) + "\n") #If we have a tcsh #batch.write("setenv CCX_NPROC 4\n") #Now do the calculation stuff for each row in the table for job in range (0,self.JobTable.rowCount()): #Extract the data from the table current_file_name = self.JobTable.item(job,0).text() z_offset_from = self.JobTable.item(job,2).data(QtCore.Qt.DisplayRole).toInt()[0] z_offset_to = self.JobTable.item(job,3).data(QtCore.Qt.DisplayRole).toInt()[0] z_offset_intervall = self.JobTable.item(job,4).data(QtCore.Qt.DisplayRole).toInt()[0] x_rot_from = self.JobTable.item(job,5).data(QtCore.Qt.DisplayRole).toInt()[0] x_rot_to = self.JobTable.item(job,6).data(QtCore.Qt.DisplayRole).toInt()[0] x_rot_intervall = self.JobTable.item(job,7).data(QtCore.Qt.DisplayRole).toInt()[0] y_rot_from = self.JobTable.item(job,8).data(QtCore.Qt.DisplayRole).toInt()[0] y_rot_to = self.JobTable.item(job,9).data(QtCore.Qt.DisplayRole).toInt()[0] y_rot_intervall = self.JobTable.item(job,10).data(QtCore.Qt.DisplayRole).toInt()[0] z_rot_from = self.JobTable.item(job,11).data(QtCore.Qt.DisplayRole).toInt()[0] z_rot_to = self.JobTable.item(job,12).data(QtCore.Qt.DisplayRole).toInt()[0] z_rot_intervall = self.JobTable.item(job,13).data(QtCore.Qt.DisplayRole).toInt()[0] young_modulus = self.JobTable.item(job,14).data(QtCore.Qt.DisplayRole).toDouble()[0] poisson_ratio = self.JobTable.item(job,15).data(QtCore.Qt.DisplayRole).toDouble()[0] lc1 = self.JobTable.item(job,16).data(QtCore.Qt.DisplayRole).toDouble()[0] lc2 = self.JobTable.item(job,17).data(QtCore.Qt.DisplayRole).toDouble()[0] lc3 = self.JobTable.item(job,18).data(QtCore.Qt.DisplayRole).toDouble()[0] lc4 = self.JobTable.item(job,19).data(QtCore.Qt.DisplayRole).toDouble()[0] lc5 = self.JobTable.item(job,20).data(QtCore.Qt.DisplayRole).toDouble()[0] lc6 = self.JobTable.item(job,21).data(QtCore.Qt.DisplayRole).toDouble()[0] ltc1 = self.JobTable.item(job,22).data(QtCore.Qt.DisplayRole).toDouble()[0] ltc2 = self.JobTable.item(job,23).data(QtCore.Qt.DisplayRole).toDouble()[0] ltc3 = self.JobTable.item(job,24).data(QtCore.Qt.DisplayRole).toDouble()[0] ltc4 = self.JobTable.item(job,25).data(QtCore.Qt.DisplayRole).toDouble()[0] ltc5 = self.JobTable.item(job,26).data(QtCore.Qt.DisplayRole).toDouble()[0] ltc6 = self.JobTable.item(job,27).data(QtCore.Qt.DisplayRole).toDouble()[0] plate_thickness = self.JobTable.item(job,28).data(QtCore.Qt.DisplayRole).toDouble()[0] filename_without_suffix = self.JobTable.item(job,0).text().split("/").takeLast().split(".")[0] print current_file_name meshobject = Fem.read(str(current_file_name)) #Perform PCA Fem.SMESH_PCA(meshobject) #Do min routine Fem.minBoundingBox(meshobject) #Now get the Node Numbers for the Boundary Conditions node_numbers = [] node_numbers = Fem.getBoundary_Conditions(meshobject) #Now we have set up the initial geometry for the calculations. Lets generate an ABAQUS input file now for each z-level with exactly the same #boundary conditions #1. Lets translate the geometry to the initial desired z-level #2. Generate a Folder for the current calculation z-level and output the ABAQUS Geometry and the boundary_conditions #Lets first generate a subfolder with the current filename os.mkdir(str(self.dirname + "/" + filename_without_suffix)) i = z_offset_from while i <= z_offset_to: j = x_rot_from while j <= x_rot_to: k = y_rot_from while k <= y_rot_to: l = z_rot_from while l <= z_rot_to: rotation_around_x = FreeCAD.Base.Placement(FreeCAD.Base.Vector(0,0,0),FreeCAD.Base.Vector(1,0,0),j) rotation_around_y = FreeCAD.Base.Placement(FreeCAD.Base.Vector(0,0,0),FreeCAD.Base.Vector(0,1,0),k) rotation_around_z = FreeCAD.Base.Placement(FreeCAD.Base.Vector(0,0,0),FreeCAD.Base.Vector(0,0,1),l) translate = FreeCAD.Base.Placement(FreeCAD.Base.Vector(0,0,i),FreeCAD.Base.Vector(0,0,0),0.0) translation = rotation_around_x.multiply(rotation_around_y).multiply(rotation_around_z).multiply(translate) #Now lets check if the part is still in the billet due to the rotation. If not, we directly skip to the next rotation value if(Fem.checkBB(meshobject,translation,plate_thickness)): print "Too heavy rotations" print str(plate_thickness) l= l + z_rot_intervall continue print "it seems that nothing changed" print str(plate_thickness) #Use the placedment as optional argument for the write() method #translated_mesh.setTransform(translation) Case_Dir = str(self.dirname) + "/" + filename_without_suffix + "/" + filename_without_suffix +\ "_"+"x_rot"+ str(int(j))+ \ "_"+"y_rot"+ str(int(k))+ \ "_"+"z_rot"+ str(int(l))+ \ "_"+"z_l"+ str(int(i)) if ( os.path.exists(str(Case_Dir)) ): os.chdir(str(self.dirname)) shutil.rmtree(str(Case_Dir)) os.mkdir(str(Case_Dir)) os.chdir(homepath) #Lets generate a sigini Input Deck for the calculix user subroutine sigini_input = open (str(Case_Dir + "/" + "sigini_input.txt"),'wb') #Write plate thickness to the sigini_file sigini_input.write(str(plate_thickness) + "\n") #Now write the Interpolation coefficients, first the L and then the LC ones sigini_input.write(\ str(lc1) + "," + \ str(lc2) + "," + \ str(lc3) + "," + \ str(lc4) + "," + \ str(lc5) + "," + \ str(lc6) + "\n") sigini_input.write(\ str(ltc1) + "," + \ str(ltc2) + "," + \ str(ltc3) + "," + \ str(ltc4) + "," + \ str(ltc5) + "," + \ str(ltc6) + "\n") sigini_input.close() #Check if the meshobject.writeABAQUS(str(Case_Dir + "/" + "geometry_fe_input.inp"), translation) ApplyingBC_IC(Case_Dir, young_modulus,poisson_ratio,node_numbers[0],node_numbers[1],node_numbers[2]) #Now lets generate a LSF Job-File to be used by the Airbus Clusters #lsf_input = open (str(Case_Dir + "/" + "job.lsf"),"wb") #lsf_input.write("#!/bin/bash\n") #lsf_input.write("export CCX_NPROC=" + str(self.params.GetInt("NumberCPUs")) + "\n") #lsf_input.write("#BSUB -n "+ str(self.params.GetInt("NumberCPUs")) + "\n") #lsf_input.write("#BSUB -W 10:00\n") #lsf_input.write("#BSUB -o %J.out\n") #lsf_input.write("#BSUB -e %J.err\n") #lsf_input.write("#BSUB -J calculix\n") #lsf_input.write("#BSUB -q loc_dev_par\n") #lsf_input.write(str("datadir=\"" + homepath + "/" + self.dirname[str(self.dirname).rfind("/")+1:] + "/" + filename_without_suffix + "/" + filename_without_suffix + #"_"+"x_rot"+ str(int(j))+ #"_"+"y_rot"+ str(int(k))+ #"_"+"z_rot"+ str(int(l))+ #"_"+"z_l"+ str(int(i)) + "\"\n")) #lsf_input.write("cd $datadir\n") #lsf_input.write("ccx -i geometry_fe_input\n") #lsf_input.close() batch.write("cd \"" + str(Case_Dir) + "\"\n") batch.write("ccx -i geometry_fe_input\n") l= l + z_rot_intervall k = k + y_rot_intervall j = j + x_rot_intervall i = i+ z_offset_intervall batch.write("cd \"" + homepath + "\"\n") #batch.write("find \"" + str(self.dirname[str(self.dirname).rfind("/")+1:] + "/") + "\" -name \"sigini_output.txt\" -exec rm -f {} \;\n") #batch.write("find \"" + str(self.dirname[str(self.dirname).rfind("/")+1:] + "/") + "\" -name \"*.out\" -exec rm -f {} \;\n") #batch.write("find \"" + str(self.dirname[str(self.dirname).rfind("/")+1:] + "/") + "\" -name \"*.err\" -exec rm -f {} \;\n") #batch.write("find \"" + str(self.dirname[str(self.dirname).rfind("/")+1:] + "/") + "\" -name \"*.dat\" -exec rm -f {} \;\n") #batch.write("find \"" + str(self.dirname[str(self.dirname).rfind("/")+1:] + "/") + "\" -name \"*.sta\" -exec rm -f {} \;\n") #batch.write("tar cf \"" + str(self.dirname[str(self.dirname).rfind("/")+1:] + ".tar\" \"" + str(self.dirname[str(self.dirname).rfind("/")+1:] + "/") + "\"\n")) #batch.write("rm -rf \"" + str(self.dirname[str(self.dirname).rfind("/")+1:] + "/") + "\"\n") batch.close() os.chdir(homepath) fnull = open(os.devnull, 'w') # #Generate the full tar name: # tarname = homepath + "/" + str(self.dirname)[str(self.dirname).rfind("/")+1:] + ".tar" # #Check if the tar file already exists. If yes, then we have to remove it # if os.path.exists(tarname): # try: # os.remove(tarname) # except Exception,e: # print e # # #tar the whole directory structure now and save the zip file in the temp folder for further processing # commandline = "tar cf \"" + tarname + "\" \"" + str(self.dirname) + "\" \n" # print commandline # result = subprocess.call(commandline, shell = False, stdout = fnull, stderr = fnull) # #somehow we have to check for a false return code! # if not result: # shutil.rmtree(str(self.dirname)) # # #Now send the zip file to the server for calculation # commandline = "scp -r \"" + tarname + "\" " + self.params.GetString("Servername") + ":" + homepath # print commandline # result = subprocess.call(commandline, shell = False, stdout = fnull, stderr = fnull) # # #Now untar, change into the directory and start the batch file # commandline = "ssh " + self.params.GetString("Servername") + " tar -xf \"" + tarname + "\"" # print commandline # result = subprocess.call(commandline, shell = False, stdout = fnull, stderr = fnull) # # commandline = "ssh " + self.params.GetString("Servername") + " chmod +x -R \"" + homepath + "/" + str(self.dirname)[str(self.dirname).rfind("/")+1:] + "\"" # print commandline # result = subprocess.call(commandline, shell = False, stdout = fnull, stderr = fnull) # # #Now we copy the batch file one level ahead as otherwise we cannot delete the calculation folder # commandline = "ssh " + self.params.GetString("Servername") + " mv \"" + homepath + "/" + str(self.dirname)[str(self.dirname).rfind("/")+1:] + "/lcmt_CALCULIX_Calculation_batch.bat\" " + homepath # print commandline # result = subprocess.call(commandline, shell = False, stdout = fnull, stderr = fnull) # #Set proper rights on the batch file commandline = "chmod +x \"" + str(self.dirname) + "/lcmt_CALCULIX_Calculation_batch.bat\"" print commandline result = subprocess.call(commandline, shell = True, stdout = fnull, stderr = fnull) #Start the Batch-File commandline = "\"" + str(self.dirname) + "/lcmt_CALCULIX_Calculation_batch.bat\"" print commandline result = subprocess.call(commandline, shell = True, stdout = fnull, stderr = fnull) # #Now send the zip file to the server for calculation # commandline = FreeCAD.getHomePath() + "bin/pscp -r -l "+ self.params.GetString("Linux User Name") + " -pw " + self.params.GetString("Linux Password") + " " + \ # "\"" + zipname + "\" " + self.params.GetString("Servername") + ":" + self.params.GetString("Linux Home Path") # result = subprocess.call(commandline, shell = False, stdout = fnull, stderr = fnull) # #Now unzip, change into the directory and start the batch file # commandline = FreeCAD.getHomePath() + "bin/plink -batch -l "+ self.params.GetString("Linux User Name") + " -pw " + self.params.GetString("Linux Password") + " " + \ # self.params.GetString("Servername") + " unzip -o \"" + self.params.GetString("Linux Home Path") + "/" + str(self.dirname)[str(self.dirname).rfind("/")+1:] + ".zip\"" # result = subprocess.call(commandline, shell = False, stdout = fnull, stderr = fnull) # commandline = FreeCAD.getHomePath() + "bin/plink -batch -l "+ self.params.GetString("Linux User Name") + " -pw " + self.params.GetString("Linux Password") + " " + \ # self.params.GetString("Servername") + " chmod +x -R \"" + self.params.GetString("Linux Home Path") + "/" + str(self.dirname)[str(self.dirname).rfind("/")+1:] + "\"" # result = subprocess.call(commandline, shell = False, stdout = fnull, stderr = fnull) # commandline = FreeCAD.getHomePath() + "bin/plink -batch -l "+ self.params.GetString("Linux User Name") + " -pw " + self.params.GetString("Linux Password") + " " + \ # self.params.GetString("Servername") + " chmod +x -R \"" + self.params.GetString("Linux Home Path") + "/" + str(self.dirname)[str(self.dirname).rfind("/")+1:] + "\"" # result = subprocess.call(commandline, shell = False, stdout = fnull, stderr = fnull) # #Now we copy the batch file one level ahead as otherwise we cannot delete the calculation folder # commandline = FreeCAD.getHomePath() + "bin/plink -batch -l "+ self.params.GetString("Linux User Name") + " -pw " + self.params.GetString("Linux Password") + " " + \ # self.params.GetString("Servername") + " mv \"" + self.params.GetString("Linux Home Path") + "/" + str(self.dirname)[str(self.dirname).rfind("/")+1:] + "/lcmt_CALCULIX_Calculation_batch.bat\" " + self.params.GetString("Linux Home Path") # result = subprocess.call(commandline, shell = False, stdout = fnull, stderr = fnull) # #Start the Batch-File # commandline = FreeCAD.getHomePath() + "bin/plink -batch -l "+ self.params.GetString("Linux User Name") + " -pw " + self.params.GetString("Linux Password") + " " + \ # self.params.GetString("Servername") + " " + self.params.GetString("Linux Home Path") + "lcmt_CALCULIX_Calculation_batch.bat" # result = subprocess.call(commandline, shell = False, stdout = fnull, stderr = fnull) #commandline = "plink -batch -l UN -pw PW dynabox \'/home/rmjzettl/" + str(self.dirname[str(self.dirname).rfind("/")+1:] + "/") + "lcmt_CALCULIX_Calculation_batch.bat\'" #result = subprocess.call(commandline, shell = False, stdout = fnull, stderr = fnull) #commandline = "pscp -r -l UN -pw PW dynabox:\"/home/rmjzettl/"+ str(self.dirname)[str(self.dirname).rfind("/")+1:] + ".tar\" " + str(self.dirname)[0:3] #result = subprocess.call(commandline, shell = False, stdout = fnull, stderr = fnull) #commandline = "plink -batch -l UN -pw PW dynabox rm -f \"/home/rmjzettl/"+ str(self.dirname)[str(self.dirname).rfind("/")+1:] + ".tar\"" #result = subprocess.call(commandline, shell = False, stdout = fnull, stderr = fnull) #commandline = "plink -batch -l UN -pw PW dynabox rm -f \"/home/rmjzettl/"+ str(self.dirname)[str(self.dirname).rfind("/")+1:] + ".zip\"" #result = subprocess.call(commandline, shell = False, stdout = fnull, stderr = fnull) #commandline = "7z x \"" + str(self.dirname)[0:3] + str(self.dirname)[str(self.dirname).rfind("/")+1:] + ".tar\" -o\"" + str(self.dirname[0:str(self.dirname).rfind("/")]) + "\"" #result = subprocess.call(commandline, shell = False, stdout = fnull, stderr = fnull) #commandline = "del /Q \"" + str(self.dirname)[0:3] + str(self.dirname)[str(self.dirname).rfind("/")+1:] + ".tar\"" #result = subprocess.call(commandline, shell = False, stdout = fnull, stderr = fnull) #commandline = "del /Q \"" + str(self.dirname)[0:3] + str(self.dirname)[str(self.dirname).rfind("/")+1:] + ".zip\"" #result = subprocess.call(commandline, shell = False, stdout = fnull, stderr = fnull) fnull.close() #Reset the GUI os.chdir(homepath) #Reset the table to be fully empty i = self.JobTable.rowCount() while i > 0: print i self.JobTable.removeRow(i-1) i = i-1 print "after" self.JobTable.setHorizontalHeaderLabels( ["Input File","Output Folder","Z-Offset From","Z-Offset To","Z-Intervall","X-Rot From","X-Rot To","X-Rot Intervall", "Y-Rot From","Y-Rot To","Y-Rot Intervall","Z-Rot From","Z-Rot To","Z-Rot Intervall","Young Modulus","Poisson Ratio", "LC1","LC2","LC3","LC4","LC5","LC6","LTC1","LTC2","LTC3","LTC4","LTC5","LTC6","Plate Thickness"]) self.button_select_file.setEnabled(True) self.button_select_output.setEnabled(True)
def setup(doc=None, solvertype="ccxtools"): # init FreeCAD document if doc is None: doc = init_doc() # explanation object # just keep the following line and change text string in get_explanation method manager.add_explanation_obj( doc, get_explanation(manager.get_header(get_information()))) # geometric object geom_obj = doc.addObject("Part::Plane", "Plate") geom_obj.Width = 6000 geom_obj.Length = 8000 doc.recompute() if FreeCAD.GuiUp: geom_obj.ViewObject.Document.activeView().viewAxonometric() geom_obj.ViewObject.Document.activeView().fitAll() # analysis analysis = ObjectsFem.makeAnalysis(doc, "Analysis") # solver if solvertype == "calculix": solver_obj = ObjectsFem.makeSolverCalculix(doc, "SolverCalculiX") elif solvertype == "ccxtools": solver_obj = ObjectsFem.makeSolverCalculixCcxTools( doc, "CalculiXccxTools") solver_obj.WorkingDir = u"" else: FreeCAD.Console.PrintWarning( "Not known or not supported solver type: {}. " "No solver object was created.\n".format(solvertype)) if solvertype == "calculix" or solvertype == "ccxtools": solver_obj.SplitInputWriter = False solver_obj.AnalysisType = "buckling" solver_obj.BucklingFactors = 10 solver_obj.GeometricalNonlinearity = "linear" solver_obj.ThermoMechSteadyState = False solver_obj.MatrixSolverType = "default" solver_obj.IterationsControlParameterTimeUse = False solver_obj.BucklingFactors = 1 analysis.addObject(solver_obj) # shell thickness thickness_obj = ObjectsFem.makeElementGeometry2D(doc, 50, 'Thickness') analysis.addObject(thickness_obj) # material material_obj = ObjectsFem.makeMaterialSolid(doc, "Steel") mat = material_obj.Material mat["Name"] = "CalculiX-Steel" mat["YoungsModulus"] = "210000 MPa" mat["PoissonRatio"] = "0.30" material_obj.Material = mat analysis.addObject(material_obj) # constraints displacement con_disp_x = ObjectsFem.makeConstraintDisplacement( doc, "ConstraintDisplacement_X") con_disp_x.References = [(geom_obj, "Edge1")] con_disp_x.xFix = True con_disp_x.xFree = False analysis.addObject(con_disp_x) con_disp_y = ObjectsFem.makeConstraintDisplacement( doc, "ConstraintDisplacement_Y") con_disp_y.References = [(geom_obj, "Vertex1")] con_disp_y.yFix = True con_disp_y.yFree = False analysis.addObject(con_disp_y) con_disp_z = ObjectsFem.makeConstraintDisplacement( doc, "ConstraintDisplacement_Z") con_disp_z.References = [ (geom_obj, "Edge1"), (geom_obj, "Edge2"), (geom_obj, "Edge3"), (geom_obj, "Edge4"), ] con_disp_z.zFix = True con_disp_z.zFree = False analysis.addObject(con_disp_z) # constraint force con_force = ObjectsFem.makeConstraintForce(doc, "ConstraintForce") con_force.References = [(geom_obj, "Edge3")] con_force.Force = 17162160 # 17'162.16 N con_force.Reversed = True con_force.Direction = (geom_obj, ["Edge2"]) analysis.addObject(con_force) # mesh from .meshes.mesh_buckling_plate_tria6 import create_nodes, create_elements fem_mesh = Fem.FemMesh() control = create_nodes(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating nodes.\n") control = create_elements(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating elements.\n") femmesh_obj = analysis.addObject( ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0] femmesh_obj.FemMesh = fem_mesh femmesh_obj.Part = geom_obj femmesh_obj.SecondOrderLinear = False femmesh_obj.CharacteristicLengthMax = "300.0 mm" femmesh_obj.ElementDimension = "2D" doc.recompute() return doc
def start_calculation(self): self.button_add_to_table.setEnabled(False) self.button_select_file.setEnabled(False) self.button_select_output.setEnabled(False) self.button_start_calculation.setEnabled(False) os.chdir("/") ##Get values from the GUI if ( os.path.exists(str(self.dirname)) ): os.chdir("c:/") shutil.rmtree(str(self.dirname)) os.mkdir(str(self.dirname)) batch = open(str(self.dirname + "/" + "lcmt_CALCULIX_Calculation_batch.bat"),'wb') #Tell calculixs solver spooles how many cpus to use #batch.write("export CCX_NPROC=" + str(self.params.GetInt("NumberCPUs")) + "\n") #If we have a tcsh #batch.write("setenv CCX_NPROC 4\n") #Now do the calculation stuff for each row in the table for job in range (0,self.JobTable.rowCount()): #Extract the data from the table current_file_name = self.JobTable.item(job,0).text() z_offset_from = self.JobTable.item(job,2).data(QtCore.Qt.DisplayRole).toInt()[0] z_offset_to = self.JobTable.item(job,3).data(QtCore.Qt.DisplayRole).toInt()[0] z_offset_intervall = self.JobTable.item(job,4).data(QtCore.Qt.DisplayRole).toInt()[0] x_rot_from = self.JobTable.item(job,5).data(QtCore.Qt.DisplayRole).toInt()[0] x_rot_to = self.JobTable.item(job,6).data(QtCore.Qt.DisplayRole).toInt()[0] x_rot_intervall = self.JobTable.item(job,7).data(QtCore.Qt.DisplayRole).toInt()[0] y_rot_from = self.JobTable.item(job,8).data(QtCore.Qt.DisplayRole).toInt()[0] y_rot_to = self.JobTable.item(job,9).data(QtCore.Qt.DisplayRole).toInt()[0] y_rot_intervall = self.JobTable.item(job,10).data(QtCore.Qt.DisplayRole).toInt()[0] z_rot_from = self.JobTable.item(job,11).data(QtCore.Qt.DisplayRole).toInt()[0] z_rot_to = self.JobTable.item(job,12).data(QtCore.Qt.DisplayRole).toInt()[0] z_rot_intervall = self.JobTable.item(job,13).data(QtCore.Qt.DisplayRole).toInt()[0] young_modulus = self.JobTable.item(job,14).data(QtCore.Qt.DisplayRole).toDouble()[0] poisson_ratio = self.JobTable.item(job,15).data(QtCore.Qt.DisplayRole).toDouble()[0] lc1 = self.JobTable.item(job,16).data(QtCore.Qt.DisplayRole).toDouble()[0] lc2 = self.JobTable.item(job,17).data(QtCore.Qt.DisplayRole).toDouble()[0] lc3 = self.JobTable.item(job,18).data(QtCore.Qt.DisplayRole).toDouble()[0] lc4 = self.JobTable.item(job,19).data(QtCore.Qt.DisplayRole).toDouble()[0] lc5 = self.JobTable.item(job,20).data(QtCore.Qt.DisplayRole).toDouble()[0] lc6 = self.JobTable.item(job,21).data(QtCore.Qt.DisplayRole).toDouble()[0] ltc1 = self.JobTable.item(job,22).data(QtCore.Qt.DisplayRole).toDouble()[0] ltc2 = self.JobTable.item(job,23).data(QtCore.Qt.DisplayRole).toDouble()[0] ltc3 = self.JobTable.item(job,24).data(QtCore.Qt.DisplayRole).toDouble()[0] ltc4 = self.JobTable.item(job,25).data(QtCore.Qt.DisplayRole).toDouble()[0] ltc5 = self.JobTable.item(job,26).data(QtCore.Qt.DisplayRole).toDouble()[0] ltc6 = self.JobTable.item(job,27).data(QtCore.Qt.DisplayRole).toDouble()[0] plate_thickness = self.JobTable.item(job,28).data(QtCore.Qt.DisplayRole).toDouble()[0] filename_without_suffix = self.JobTable.item(job,0).text().split("/").takeLast().split(".")[0] meshobject = Fem.read(str(current_file_name)) #Perform PCA Fem.SMESH_PCA(meshobject) #Do min routine Fem.minBoundingBox(meshobject) #Now get the Node Numbers for the Boundary Conditions node_numbers = [] node_numbers = Fem.getBoundary_Conditions(meshobject) #Now we have set up the initial geometry for the calculations. Lets generate an ABAQUS input file now for each z-level with exactly the same #boundary conditions #1. Lets translate the geometry to the initial desired z-level #2. Generate a Folder for the current calculation z-level and output the ABAQUS Geometry and the boundary_conditions #Lets first generate a subfolder with the current filename os.mkdir(str(self.dirname + "/" + filename_without_suffix)) i = z_offset_from while i <= z_offset_to: j = x_rot_from while j <= x_rot_to: k = y_rot_from while k <= y_rot_to: l = z_rot_from while l <= z_rot_to: rotation_around_x = FreeCAD.Base.Placement(FreeCAD.Base.Vector(0,0,0),FreeCAD.Base.Vector(1,0,0),j) rotation_around_y = FreeCAD.Base.Placement(FreeCAD.Base.Vector(0,0,0),FreeCAD.Base.Vector(0,1,0),k) rotation_around_z = FreeCAD.Base.Placement(FreeCAD.Base.Vector(0,0,0),FreeCAD.Base.Vector(0,0,1),l) translate = FreeCAD.Base.Placement(FreeCAD.Base.Vector(0,0,i),FreeCAD.Base.Vector(0,0,0),0.0) translation = rotation_around_x.multiply(rotation_around_y).multiply(rotation_around_z).multiply(translate) #Now lets check if the part is still in the billet due to the rotation. If not, we directly skip to the next rotation value if(Fem.checkBB(meshobject,translation,plate_thickness)): print "Too heavy rotations" l= l + z_rot_intervall continue print "it seems that nothing changed" #Use the placedment as optional argument for the write() method #translated_mesh.setTransform(translation) Case_Dir = str(self.dirname) + "/" + filename_without_suffix + "/" + filename_without_suffix +\ "_"+"x_rot"+ str(int(j))+ \ "_"+"y_rot"+ str(int(k))+ \ "_"+"z_rot"+ str(int(l))+ \ "_"+"z_l"+ str(int(i)) if ( os.path.exists(str(Case_Dir)) ): os.chdir(str(self.dirname)) shutil.rmtree(str(Case_Dir)) os.mkdir(str(Case_Dir)) os.chdir("c:/") #Lets generate a sigini Input Deck for the calculix user subroutine sigini_input = open (str(Case_Dir + "/" + "sigini_input.txt"),'wb') #Write plate thickness to the sigini_file sigini_input.write(str(plate_thickness) + "\n") #Now write the Interpolation coefficients, first the L and then the LC ones sigini_input.write(\ str(lc1) + "," + \ str(lc2) + "," + \ str(lc3) + "," + \ str(lc4) + "," + \ str(lc5) + "," + \ str(lc6) + "\n") sigini_input.write(\ str(ltc1) + "," + \ str(ltc2) + "," + \ str(ltc3) + "," + \ str(ltc4) + "," + \ str(ltc5) + "," + \ str(ltc6) + "\n") sigini_input.close() #Check if the meshobject.writeABAQUS(str(Case_Dir + "/" + "geometry_fe_input.inp"), translation) ApplyingBC_IC(Case_Dir, young_modulus,poisson_ratio,node_numbers[0],node_numbers[1],node_numbers[2]) #Now lets generate a LSF Job-File to be used by the Airbus Clusters lsf_input = open (str(Case_Dir + "/" + "job.lsf"),"wb") lsf_input.write("#!/bin/bash\n") lsf_input.write("export CCX_NPROC=" + str(self.params.GetInt("NumberCPUs")) + "\n") lsf_input.write("#BSUB -n "+ str(self.params.GetInt("NumberCPUs")) + "\n") lsf_input.write("#BSUB -W 10:00\n") lsf_input.write("#BSUB -o %J.out\n") lsf_input.write("#BSUB -e %J.err\n") lsf_input.write("#BSUB -J calculix\n") lsf_input.write("#BSUB -q loc_all_hiio\n") lsf_input.write(str("datadir=\"" + self.params.GetString("Linux Home Path") + "/" + self.dirname[str(self.dirname).rfind("/")+1:] + "/" + filename_without_suffix + "/" + filename_without_suffix + "_"+"x_rot"+ str(int(j))+ "_"+"y_rot"+ str(int(k))+ "_"+"z_rot"+ str(int(l))+ "_"+"z_l"+ str(int(i)) + "\"\n")) lsf_input.write("cd $datadir\n") lsf_input.write(self.params.GetString("Solver Link") + " -i final_fe_input\n") lsf_input.close() batch.write(str("cd \"" + self.params.GetString("Linux Home Path") + "/" + self.dirname[str(self.dirname).rfind("/")+1:] + "/" + filename_without_suffix + "/" + filename_without_suffix + "_"+"x_rot"+ str(int(j))+ "_"+"y_rot"+ str(int(k))+ "_"+"z_rot"+ str(int(l))+ "_"+"z_l"+ str(int(i)) + "\"\n")) batch.write("job.lsf\n") l= l + z_rot_intervall k = k + y_rot_intervall j = j + x_rot_intervall i = i+ z_offset_intervall print "Ale Schleifen beendet" batch.write("cd \"" + self.params.GetString("Linux Home Path") + "\"\n") batch.write("find \"" + str(self.dirname[str(self.dirname).rfind("/")+1:] + "/") + "\" -name \"sigini_output.txt\" -exec rm -f {} \;\n") batch.write("find \"" + str(self.dirname[str(self.dirname).rfind("/")+1:] + "/") + "\" -name \"*.out\" -exec rm -f {} \;\n") batch.write("find \"" + str(self.dirname[str(self.dirname).rfind("/")+1:] + "/") + "\" -name \"*.err\" -exec rm -f {} \;\n") batch.write("find \"" + str(self.dirname[str(self.dirname).rfind("/")+1:] + "/") + "\" -name \"*.dat\" -exec rm -f {} \;\n") batch.write("find \"" + str(self.dirname[str(self.dirname).rfind("/")+1:] + "/") + "\" -name \"*.sta\" -exec rm -f {} \;\n") batch.write("tar cf \"" + str(self.dirname[str(self.dirname).rfind("/")+1:] + ".tar\" \"" + str(self.dirname[str(self.dirname).rfind("/")+1:] + "/") + "\"\n")) batch.write("rm -rf \"" + str(self.dirname[str(self.dirname).rfind("/")+1:] + "/") + "\"\n") batch.close() os.chdir("c:/") fnull = open(os.devnull, 'w') #Generate the full zip name: zipname = tempfile.gettempdir() + "/" + str(self.dirname)[str(self.dirname).rfind("/")+1:] + ".zip" #Check if the zip file already exists. If yes, then we have to remove it if os.path.exists(zipname): try: os.remove(zipname) except Exception,e: print e
def setup(doc=None, solvertype="ccxtools"): # setup reinfoced wall in 2D if doc is None: doc = init_doc() # part from FreeCAD import Vector as vec import Part from Part import makeLine as ln v1 = vec(0, -2000, 0) v2 = vec(500, -2000, 0) v3 = vec(500, 0, 0) v4 = vec(3500, 0, 0) v5 = vec(3500, -2000, 0) v6 = vec(4000, -2000, 0) v7 = vec(4000, 2000, 0) v8 = vec(0, 2000, 0) l1 = ln(v1, v2) l2 = ln(v2, v3) l3 = ln(v3, v4) l4 = ln(v4, v5) l5 = ln(v5, v6) l6 = ln(v6, v7) l7 = ln(v7, v8) l8 = ln(v8, v1) rcwall = doc.addObject("Part::Feature", "FIB_Wall") rcwall.Shape = Part.Face(Part.Wire([l1, l2, l3, l4, l5, l6, l7, l8])) doc.recompute() if FreeCAD.GuiUp: import FreeCADGui FreeCADGui.ActiveDocument.activeView().viewAxonometric() FreeCADGui.SendMsgToActiveView("ViewFit") # analysis analysis = ObjectsFem.makeAnalysis(doc, "Analysis") # solver if solvertype == "calculix": solver = analysis.addObject( ObjectsFem.makeSolverCalculix(doc, "SolverCalculiX"))[0] elif solvertype == "ccxtools": solver = analysis.addObject( ObjectsFem.makeSolverCalculixCcxTools(doc, "CalculiXccxTools"))[0] solver.WorkingDir = u"" if solvertype == "calculix" or solvertype == "ccxtools": solver.AnalysisType = "static" solver.GeometricalNonlinearity = "linear" solver.ThermoMechSteadyState = False solver.MatrixSolverType = "default" solver.IterationsControlParameterTimeUse = False # shell thickness thickness = analysis.addObject( ObjectsFem.makeElementGeometry2D(doc, 0, "ShellThickness"))[0] thickness.Thickness = 150.0 # material matrixprop = {} matrixprop["Name"] = "Concrete-EN-C35/45" matrixprop["YoungsModulus"] = "32000 MPa" matrixprop["PoissonRatio"] = "0.17" matrixprop["CompressiveStrength"] = "15.75 MPa" # make some hint on the possible angle units in material system matrixprop["AngleOfFriction"] = "30 deg" matrixprop["Density"] = "2500 kg/m^3" reinfoprop = {} reinfoprop["Name"] = "Reinforcement-FIB-B500" reinfoprop["YieldStrength"] = "315 MPa" # not an official FreeCAD material property reinfoprop["ReinforcementRatio"] = "0.0" material_reinforced = analysis.addObject( ObjectsFem.makeMaterialReinforced(doc, "MaterialReinforced"))[0] material_reinforced.Material = matrixprop material_reinforced.Reinforcement = reinfoprop # fixed_constraint fixed_constraint = analysis.addObject( ObjectsFem.makeConstraintFixed(doc, name="ConstraintFixed"))[0] fixed_constraint.References = [(rcwall, "Edge1"), (rcwall, "Edge5")] # force constraint force_constraint = doc.Analysis.addObject( ObjectsFem.makeConstraintForce(doc, name="ConstraintForce"))[0] force_constraint.References = [(rcwall, "Edge7")] force_constraint.Force = 1000000.0 force_constraint.Direction = (rcwall, ["Edge8"]) force_constraint.Reversed = False # displacement_constraint displacement_constraint = doc.Analysis.addObject( ObjectsFem.makeConstraintDisplacement( doc, name="ConstraintDisplacmentPrescribed"))[0] displacement_constraint.References = [(rcwall, "Face1")] displacement_constraint.zFix = True # mesh from .meshes.mesh_rc_wall_2d_tria6 import create_nodes, create_elements fem_mesh = Fem.FemMesh() control = create_nodes(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating nodes.\n") control = create_elements(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating elements.\n") femmesh_obj = analysis.addObject( doc.addObject("Fem::FemMeshObject", mesh_name))[0] femmesh_obj.FemMesh = fem_mesh doc.recompute() return doc
def proceed(self): temp_file = tempfile.mkstemp(suffix='.step')[1] selection = FreeCADGui.Selection.getSelection() if not selection: QtGui.QMessageBox.critical(None, "GMSHMesh macro", "An object has to be selected to run gmsh!") return # Export a part in step format ImportGui.export(selection, temp_file) selection_name = selection[0].Name # Mesh temporaly file file_format = self.cmb_format.currentText() temp_mesh_file = os.path.join(tempfile.tempdir, selection_name + '_Mesh.' + file_format) # OPTIONS GMSH: clmax = self.sb_max_element_size.text() clmin = self.sb_min_element_size.text() cmd_line_opt = self.le_cmd_line_opt.text() algo = self.cmb_algorithm.currentText() mesh_order = self.sb_mesh_order.text() if self.cb_optimized.isChecked(): cmd_optimize = ' -optimize' else: cmd_optimize = '' if self.rb_3D.isChecked(): dim = ' -3 ' if self.rb_2D.isChecked(): dim = ' -2 ' if self.rb_1D.isChecked(): dim = ' -1 ' if self.cb_max_elme_size.isChecked(): max_size = ' -clmax ' + clmax else: max_size = '' if self.cb_min_elme_size.isChecked(): min_size = ' -clmin ' + clmin else: min_size = '' if self.cb_mesh_order.isChecked(): order = ' -order ' + mesh_order else: order = '' options = ' -algo ' + algo + max_size + min_size + cmd_optimize + order + cmd_line_opt # RUN GMSH command = gmsh_bin + ' ' + temp_file + dim + '-format ' + file_format + ' -o ' + temp_mesh_file + '' + options FreeCAD.Console.PrintMessage("Running: \"{}\"\n".format(command)) try: output = subprocess.check_output([command, '-1'], shell=True, stderr=subprocess.STDOUT,) for line in output.split('\n'): if "Error" in line: FreeCAD.Console.PrintError("{}\n".format(line)) elif "Warning" in line: FreeCAD.Console.PrintWarning("{}\n".format(line)) #FreeCAD.Console.PrintMessage("Output: \"{}\"\n".format(output)) if file_format in ('unv', 'med'): Fem.insert(temp_mesh_file, FreeCAD.ActiveDocument.Name) if file_format == 'stl': Mesh.insert(temp_mesh_file, FreeCAD.ActiveDocument.Name) if file_format == 'msh': out_mesh_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), "geometry.msh") shutil.move(temp_mesh_file, out_mesh_file) FreeCAD.Console.PrintMessage("Output file written to: {}\n".format(out_mesh_file)) if self.cb_mec_anal.isChecked(): FMesh = App.activeDocument().ActiveObject MechanicalAnalysis.makeMechanicalAnalysis('MechanicalAnalysis') FemGui.setActiveAnalysis(App.activeDocument().ActiveObject) App.activeDocument().ActiveObject.Member = App.activeDocument().ActiveObject.Member + [FMesh] if self.rb_1D.isChecked(): FMeshG = Gui.ActiveDocument.ActiveObject FMeshG.DisplayMode = "Elements & Nodes" except: FreeCAD.Console.PrintError("Unexpected error in GMSHMesh macro: {} {}\n".format(sys.exc_info()[0], sys.exc_info()[1])) finally: try: del temp_file except: pass try: del temp_mesh_file except: pass