def processSystemSettings(self): system_settings = self.settings['system'] system_settings['FoamRuntime'] = CfdTools.getFoamRuntime() system_settings['CasePath'] = self.case_folder system_settings['FoamPath'] = CfdTools.getFoamDir() if CfdTools.getFoamRuntime() != 'WindowsDocker': system_settings['TranslatedFoamPath'] = CfdTools.translatePath(CfdTools.getFoamDir())
def openParaview(self): self.Start = time.time() QApplication.setOverrideCursor(Qt.WaitCursor) script_name = os.path.abspath( os.path.join(self.working_dir, self.solver_object.InputCaseName, "pvScript.py")) paraview_cmd = "paraview" # If using blueCFD, use paraview supplied if CfdTools.getFoamRuntime() == 'BlueCFD': paraview_cmd = '{}\\..\\AddOns\\ParaView\\bin\\paraview.exe'.format( CfdTools.getFoamDir()) # Otherwise, the command 'paraview' must be in the path. Possibly make path user-settable. # Test to see if it exists, as the exception thrown is cryptic on Windows if it doesn't import distutils.spawn if distutils.spawn.find_executable(paraview_cmd) is None: raise IOError("Paraview executable " + paraview_cmd + " not found in path.") arg = '--script={}'.format(script_name) self.consoleMessage("Running " + paraview_cmd + " " + arg) self.open_paraview.start(paraview_cmd, [arg]) if self.open_paraview.waitForStarted(): self.consoleMessage("Paraview started") else: self.consoleMessage("Error starting paraview") QApplication.restoreOverrideCursor()
def __init__(self, analysis=None, solver=None): super(CfdRunnableFoam, self).__init__(analysis, solver) self.writer = CfdCaseWriterFoam.CfdCaseWriterFoam(self.analysis) # Set default windows executable to gnuplot instead of older pgnuplot import platform if platform.system() == 'Windows': Gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot.exe' gnuplot_cmd = Gnuplot.GnuplotOpts.gnuplot_command # For blueCFD, use the supplied Gnuplot if CfdTools.getFoamRuntime() == 'BlueCFD': gnuplot_cmd = CfdTools.getFoamDir() gnuplot_cmd = '{}\\..\\AddOns\\gnuplot\\bin\\gnuplot.exe'.format( gnuplot_cmd) Gnuplot.GnuplotOpts.gnuplot_command = '"{}"'.format(gnuplot_cmd) # Otherwise, the command 'gnuplot' must be in the path. Possibly make path user-settable. # Test to see if it exists, as the exception thrown is cryptic on Windows if it doesn't import distutils.spawn if distutils.spawn.find_executable(gnuplot_cmd) is None: raise IOError("Gnuplot executable " + gnuplot_cmd + " not found in path.") self.g = Gnuplot.Gnuplot() self.UxResiduals = [1] self.UyResiduals = [1] self.UzResiduals = [1] self.pResiduals = [1] self.niter = 0 self.print_next_error_lines = 0 self.print_next_error_file = False
def setDownloadURLs(self): if self.testGetRuntime() == "MinGW": foam_ver = os.path.split(CfdTools.getFoamDir())[-1] self.form.le_cfmesh_url.setText(CFMESH_URL_MINGW.format(foam_ver)) self.form.le_hisa_url.setText(HISA_URL_MINGW.format(foam_ver)) else: self.form.le_cfmesh_url.setText(CFMESH_URL) self.form.le_hisa_url.setText(HISA_URL)
def createMeshScript(self, run_parallel, mesher_name, num_proc, cartMethod): print("Create Allmesh script ") fname = self.meshCaseDir + os.path.sep + "Allmesh" # Replace if os.path.exists(fname): print("Warning: Overwrite existing Allmesh script and log files.") os.remove(os.path.join(self.meshCaseDir, "log.surfaceFeatureEdges")) os.remove(os.path.join(self.meshCaseDir, "log.cartesianMesh")) with open(fname, 'w+') as f: source = "" triSurfaceDir = os.path.join('constant', 'triSurface') if not CfdTools.getFoamRuntime( ) == "BlueCFD": # Runs inside own environment - no need to source source = CfdTools.readTemplate( os.path.join(self.templatePath, "_helperFiles", "AllrunSource"), {"FOAMDIR": CfdTools.translatePath(CfdTools.getFoamDir())}) head = CfdTools.readTemplate( os.path.join(self.templatePath, "_helperFiles", "AllmeshPreamble"), {"SOURCE": source}) f.write(head) if cartMethod == 'cfMesh' and mesher_name == 'cartesianMesh': f.write('# Extract feature edges\n') f.write( 'runCommand surfaceFeatureEdges -angle 60 "{}_Geometry.stl" "{}_Geometry.fms"' '\n'.format( os.path.join(triSurfaceDir, self.part_obj.Name), self.part_obj.Name)) f.write('\n') f.write('runCommand cartesianMesh\n') f.write('\n') elif cartMethod == 'snappyHexMesh': f.write('runCommand blockMesh \n') f.write('runCommand surfaceFeatureExtract \n') f.write('runCommand snappyHexMesh -overwrite\n') f.write('runCommand surfaceToPatch constant/triSurface/' + self.part_obj.Name + '_Geometry.stl \n') # Create stl of FOAM mesh outside (in mm) to view the object in FreeCAD. f.write('runCommand surfaceMeshTriangulate mesh_outside.stl\n') f.write( 'runCommand surfaceTransformPoints -scale "(1000 1000 1000)"' + ' mesh_outside.stl mesh_outside.stl\n') f.write('\n') import stat s = os.stat(fname) os.chmod(fname, s.st_mode | stat.S_IEXEC ) # Update Allmesh permission - will fail silently on windows
def openParaview(self): self.Start = time.time() QApplication.setOverrideCursor(Qt.WaitCursor) paraview_cmd = "paraview" # If using blueCFD, use paraview supplied if CfdTools.getFoamRuntime() == 'BlueCFD': paraview_cmd = '{}\\..\\AddOns\\ParaView\\bin\\paraview.exe'.format(CfdTools.getFoamDir()) # Otherwise, the command 'paraview' must be in the path. Possibly make path user-settable. # Test to see if it exists, as the exception thrown is cryptic on Windows if it doesn't import distutils.spawn if distutils.spawn.find_executable(paraview_cmd) is None: raise IOError("Paraview executable " + paraview_cmd + " not found in path.") self.paraviewScriptName = os.path.join(self.meshCaseDir, 'pvScriptMesh.py') arg = '--script={}'.format(self.paraviewScriptName) self.console_log("Running " + paraview_cmd + " " +arg) self.open_paraview.start(paraview_cmd, [arg]) QApplication.restoreOverrideCursor()
def writeMeshCase(self): """ Collect case settings, and finally build a runnable case. """ CfdTools.cfdMessage( "Populating mesh dictionaries in folder {}\n".format( self.meshCaseDir)) if self.mesh_obj.MeshUtility == "cfMesh": self.cf_settings['ClMax'] = self.clmax * self.scale if len(self.cf_settings['BoundaryLayers']) > 0: self.cf_settings['BoundaryLayerPresent'] = True else: self.cf_settings['BoundaryLayerPresent'] = False if len(self.cf_settings["InternalRegions"]) > 0: self.cf_settings['InternalRefinementRegionsPresent'] = True else: self.cf_settings['InternalRefinementRegionsPresent'] = False elif self.mesh_obj.MeshUtility == "snappyHexMesh": bound_box = self.part_obj.Shape.BoundBox bC = 5 # Number of background mesh buffer cells x_min = (bound_box.XMin - bC * self.clmax) * self.scale x_max = (bound_box.XMax + bC * self.clmax) * self.scale y_min = (bound_box.YMin - bC * self.clmax) * self.scale y_max = (bound_box.YMax + bC * self.clmax) * self.scale z_min = (bound_box.ZMin - bC * self.clmax) * self.scale z_max = (bound_box.ZMax + bC * self.clmax) * self.scale cells_x = int(math.ceil(bound_box.XLength / self.clmax) + 2 * bC) cells_y = int(math.ceil(bound_box.YLength / self.clmax) + 2 * bC) cells_z = int(math.ceil(bound_box.ZLength / self.clmax) + 2 * bC) snappy_settings = self.snappy_settings snappy_settings['BlockMesh'] = { "xMin": x_min, "xMax": x_max, "yMin": y_min, "yMax": y_max, "zMin": z_min, "zMax": z_max, "cellsX": cells_x, "cellsY": cells_y, "cellsZ": cells_z } inside_x = Units.Quantity( self.mesh_obj.PointInMesh.get('x')).Value * self.scale inside_y = Units.Quantity( self.mesh_obj.PointInMesh.get('y')).Value * self.scale inside_z = Units.Quantity( self.mesh_obj.PointInMesh.get('z')).Value * self.scale shape_face_names_list = [] for i in self.mesh_obj.ShapeFaceNames: shape_face_names_list.append(i) snappy_settings['ShapeFaceNames'] = tuple(shape_face_names_list) snappy_settings[ 'EdgeRefinementLevel'] = CfdTools.relLenToRefinementLevel( self.mesh_obj.EdgeRefinement) snappy_settings['PointInMesh'] = { "x": inside_x, "y": inside_y, "z": inside_z } snappy_settings[ 'CellsBetweenLevels'] = self.mesh_obj.CellsBetweenLevels if len(self.snappy_settings["InternalRegions"]) > 0: self.snappy_settings['InternalRefinementRegionsPresent'] = True else: self.snappy_settings[ 'InternalRefinementRegionsPresent'] = False elif self.mesh_obj.MeshUtility == "gmsh": if platform.system() == "Windows": exe = os.path.join(FreeCAD.getHomePath(), 'bin', 'gmsh.exe') else: exe = subprocess.check_output( ["which", "gmsh"], universal_newlines=True).rstrip('\n') self.gmsh_settings['Executable'] = CfdTools.translatePath(exe) self.gmsh_settings['ShapeFile'] = self.temp_file_shape self.gmsh_settings['HasLengthMap'] = False if self.ele_length_map: self.gmsh_settings['HasLengthMap'] = True self.gmsh_settings['LengthMap'] = self.ele_length_map self.gmsh_settings['NodeMap'] = {} for e in self.ele_length_map: ele_nodes = (''.join( (str(n + 1) + ', ') for n in self.ele_node_map[e])).rstrip(', ') self.gmsh_settings['NodeMap'][e] = ele_nodes self.gmsh_settings['ClMax'] = self.clmax self.gmsh_settings['ClMin'] = self.clmin sols = (''.join( (str(n + 1) + ', ') for n in range(len(self.mesh_obj.Part.Shape.Solids))) ).rstrip(', ') self.gmsh_settings['Solids'] = sols self.gmsh_settings['BoundaryFaceMap'] = {} # Write one boundary per face for i in range(len(self.mesh_obj.Part.Shape.Faces)): self.gmsh_settings['BoundaryFaceMap']['face' + str(i)] = i + 1 self.gmsh_settings['MeshFile'] = self.temp_file_mesh # Perform initialisation here rather than __init__ in case of path changes self.template_path = os.path.join(CfdTools.get_module_path(), "data", "defaultsMesh") mesh_region_present = False if self.mesh_obj.MeshUtility == "cfMesh" and len(self.cf_settings['MeshRegions']) > 0 or \ self.mesh_obj.MeshUtility == "snappyHexMesh" and len(self.snappy_settings['MeshRegions']) > 0: mesh_region_present = True self.settings = { 'Name': self.part_obj.Name, 'MeshPath': self.meshCaseDir, 'FoamRuntime': CfdTools.getFoamRuntime(), 'MeshUtility': self.mesh_obj.MeshUtility, 'MeshRegionPresent': mesh_region_present, 'CfSettings': self.cf_settings, 'SnappySettings': self.snappy_settings, 'GmshSettings': self.gmsh_settings, 'TwoDSettings': self.two_d_settings } if CfdTools.getFoamRuntime() != 'WindowsDocker': self.settings['TranslatedFoamPath'] = CfdTools.translatePath( CfdTools.getFoamDir()) if self.mesh_obj.NumberOfProcesses <= 1: self.mesh_obj.NumberOfProcesses = 1 self.settings['ParallelMesh'] = False else: self.settings['ParallelMesh'] = True self.settings['NumberOfProcesses'] = self.mesh_obj.NumberOfProcesses self.settings['NumberOfThreads'] = self.mesh_obj.NumberOfThreads TemplateBuilder.TemplateBuilder(self.meshCaseDir, self.template_path, self.settings) # Update Allmesh permission - will fail silently on Windows fname = os.path.join(self.meshCaseDir, "Allmesh") import stat s = os.stat(fname) os.chmod(fname, s.st_mode | stat.S_IEXEC) CfdTools.cfdMessage( "Successfully wrote meshCase to folder {}\n".format( self.meshCaseDir))
def write_mesh_case(self): """ Write_case() will collect case setings, and finally build a runnable case. """ tmpdir = tempfile.gettempdir() FreeCAD.Console.PrintMessage( "Populating mesh dictionaries in folder {}\n".format(tmpdir)) _cwd = os.curdir # if not os.path.exists(tmpdir = tempfile.gettempdir()): # raise IOError("Path {} does not exist.".format(tmpdir = tempfile.gettempdir())) os.chdir( tmpdir ) # pyFoam can not write to cwd if FreeCAD is started NOT from terminal if self.mesh_obj.MeshUtility == "cfMesh": self.cf_settings['ClMax'] = self.clmax * self.scale if len(self.cf_settings['BoundaryLayers']) > 0: self.cf_settings['BoundaryLayerPresent'] = True else: self.cf_settings['BoundaryLayerPresent'] = False elif self.mesh_obj.MeshUtility == "snappyHexMesh": bound_box = self.part_obj.Shape.BoundBox bC = 5 # Number of background mesh buffer cells x_min = (bound_box.XMin - bC * self.clmax) * self.scale x_max = (bound_box.XMax + bC * self.clmax) * self.scale y_min = (bound_box.YMin - bC * self.clmax) * self.scale y_max = (bound_box.YMax + bC * self.clmax) * self.scale z_min = (bound_box.ZMin - bC * self.clmax) * self.scale z_max = (bound_box.ZMax + bC * self.clmax) * self.scale cells_x = int(math.ceil(bound_box.XLength / self.clmax) + 2 * bC) cells_y = int(math.ceil(bound_box.YLength / self.clmax) + 2 * bC) cells_z = int(math.ceil(bound_box.ZLength / self.clmax) + 2 * bC) snappy_settings = self.snappy_settings snappy_settings['BlockMesh'] = { "xMin": x_min, "xMax": x_max, "yMin": y_min, "yMax": y_max, "zMin": z_min, "zMax": z_max, "cellsX": cells_x, "cellsY": cells_y, "cellsZ": cells_z } inside_x = self.mesh_obj.PointInMesh.get('x') * self.scale inside_y = self.mesh_obj.PointInMesh.get('y') * self.scale inside_z = self.mesh_obj.PointInMesh.get('z') * self.scale shape_face_names_list = [] for i in self.mesh_obj.ShapeFaceNames: shape_face_names_list.append(i) snappy_settings['ShapeFaceNames'] = tuple(shape_face_names_list) snappy_settings[ 'EdgeRefinementLevel'] = self.mesh_obj.EdgeRefinement snappy_settings['PointInMesh'] = { "x": inside_x, "y": inside_y, "z": inside_z } snappy_settings[ 'CellsBetweenLevels'] = self.mesh_obj.CellsBetweenLevels if self.mesh_obj.NumberCores <= 1: self.mesh_obj.NumberCores = 1 snappy_settings['ParallelMesh'] = False else: snappy_settings['ParallelMesh'] = True snappy_settings['NumberCores'] = self.mesh_obj.NumberCores try: # Make sure we restore cwd after exception here # Perform initialisation here rather than __init__ in case of path changes self.template_path = os.path.join(CfdTools.get_module_path(), "data", "defaultsMesh") mesh_region_present = False if len(self.cf_settings['MeshRegions']) > 0 or len( self.snappy_settings['MeshRegions']) > 0: mesh_region_present = True self.settings = { 'Name': self.part_obj.Name, 'MeshPath': self.meshCaseDir, 'FoamRuntime': CfdTools.getFoamRuntime(), 'TranslatedFoamPath': CfdTools.translatePath(CfdTools.getFoamDir()), 'MeshUtility': self.mesh_obj.MeshUtility, 'MeshRegionPresent': mesh_region_present, 'CfSettings': self.cf_settings, 'SnappySettings': self.snappy_settings } TemplateBuilder.TemplateBuilder(self.meshCaseDir, self.template_path, self.settings) # Update Allmesh permission - will fail silently on Windows fname = os.path.join(self.meshCaseDir, "Allmesh") import stat s = os.stat(fname) os.chmod(fname, s.st_mode | stat.S_IEXEC) except: raise finally: os.chdir(_cwd) # Restore working dir FreeCAD.Console.PrintMessage( "Successfully wrote meshCase to folder {}\n".format(tmpdir))
def convertMesh(self): import tempfile import CfdCaseWriterFoam import CfdCartTools import TemplateBuilder import os if not (self.meshConverted): self.Start = time.time() self.Timer.start() self.console_log("Starting 3D to 2D mesh conversion ...") self.frontFaceName = self.form.comboBoxFront.currentText() self.backFaceName = self.form.comboBoxBack.currentText() tmpdir = tempfile.gettempdir() analysis_obj = FemGui.getActiveAnalysis() tmpdir = tempfile.gettempdir() self.meshCaseDir = os.path.join(tmpdir, "meshCase") self.meshObj = CfdTools.getMesh(analysis_obj) solver_obj = CfdTools.getSolver(analysis_obj) gmshMesh = False if self.meshObj.Proxy.Type == "Fem::FemMeshGmsh": # GMSH # Convert GMSH created UNV file to OpenFoam print("Writing GMSH UNV mesh to be converted to 2D mesh") unvMeshFile = self.meshCaseDir + os.path.sep + solver_obj.InputCaseName + u".unv" #try: if not os.path.exists(self.meshCaseDir): os.makedirs(self.meshCaseDir) bc_group = CfdTools.getCfdBoundaryGroup(analysis_obj) self.mesh_generated = CfdTools.write_unv_mesh( self.meshObj, bc_group, unvMeshFile) gmshMesh = True frontFaceList = self.frontFaceName backFaceList = [self.backFaceName] else: case = CfdCaseWriterFoam.CfdCaseWriterFoam(analysis_obj) case.settings = {} case.settings['createPatchesFromSnappyBaffles'] = False case.setupPatchNames() keys = case.settings['createPatches'].keys() frontPatchIndex = keys.index(self.frontFaceName) frontFaceList = case.settings['createPatches'][ keys[frontPatchIndex]]['PatchNamesList'] backPatchIndex = keys.index(self.backFaceName) backFaceList = case.settings['createPatches'][ keys[backPatchIndex]]['PatchNamesList'] template_path = os.path.join(CfdTools.get_module_path(), "data", "defaultsMesh") settings = { 'ConvertTo2D': True, 'gmshMesh': gmshMesh, 'unvFileName': solver_obj.InputCaseName + u".unv", 'FrontFaceList': frontFaceList, 'BackFaceList': backFaceList[0], 'Distance': self.distance / 1000.0, 'TranslatedFoamPath': CfdTools.translatePath(CfdTools.getFoamDir(), ), 'MeshPath': self.meshCaseDir } TemplateBuilder.TemplateBuilder(self.meshCaseDir, template_path, settings) cmd = CfdTools.makeRunCommand('./ConvertMeshTo2D', self.meshCaseDir, source_env=False) #will fail silently in Windows fname = os.path.join(self.meshCaseDir, "ConvertMeshTo2D") import stat s = os.stat(fname) os.chmod(fname, s.st_mode | stat.S_IEXEC) FreeCAD.Console.PrintMessage("Executing: " + ' '.join(cmd) + "\n") env = QtCore.QProcessEnvironment.systemEnvironment() env_vars = CfdTools.getRunEnvironment() for key in env_vars: env.insert(key, env_vars[key]) self.conversion_process.setProcessEnvironment(env) self.conversion_process.start(cmd[0], cmd[1:]) if self.conversion_process.waitForStarted(): self.form.convertButton.setEnabled( False) # Prevent user running a second instance self.form.paraviewButton.setEnabled(False) else: self.console_log("Error starting meshing process", "#FF0000")