def threadFinished(self, status): if self.thread.task == DOWNLOAD_CFMESH: if status: self.consoleMessage("Download completed") user_dir = self.thread.user_dir self.consoleMessage( "Building cfMesh. Lengthy process - please wait...") if CfdTools.getFoamRuntime() == "BlueCFD": script_name = "buildCfMeshOnBlueCFD.sh" self.consoleMessage("Log file: {}\\log.{}".format( user_dir, script_name)) TemplateBuilder.TemplateBuilder( user_dir, os.path.join(CfdTools.get_module_path(), 'data', 'foamUserDir'), {'cfMeshDirectory': CFMESH_FILE_BASE}) self.install_process = CfdTools.startFoamApplication( "./" + script_name, "$WM_PROJECT_USER_DIR", self.installFinished) else: self.consoleMessage("Log file: {}/{}/log.Allwmake".format( user_dir, CFMESH_FILE_BASE)) self.install_process = CfdTools.startFoamApplication( "./Allwmake", "$WM_PROJECT_USER_DIR/" + CFMESH_FILE_BASE, self.installFinished) # Reset foam dir for now in case the user presses 'Cancel' CfdTools.setFoamDir(self.initial_foam_dir) else: self.consoleMessage("Download unsuccessful") self.thread = None
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 writeCase(self, progressCallback=None): """ writeCase() will collect case settings, and finally build a runnable case. """ cfdMessage("Start to write case to folder {}\n".format( self.working_dir)) if not os.path.exists(self.working_dir): raise IOError("Path " + self.solver_obj.working_dir + " does not exist.") # Perform initialisation here rather than __init__ in case of path changes self.case_folder = os.path.join(self.working_dir, self.solver_obj.InputCaseName) self.case_folder = os.path.expanduser(os.path.abspath( self.case_folder)) self.mesh_file_name = os.path.join(self.case_folder, self.solver_obj.InputCaseName, u".unv") self.template_path = os.path.join(CfdTools.get_module_path(), "data", "defaults") # Collect settings into single dictionary if not self.mesh_obj: raise RuntimeError("No mesh object found in analysis") phys_settings = CfdTools.propsToDict(self.physics_model) # TODO: Make sure boundary labels are unique and valid self.settings = { 'physics': phys_settings, 'fluidProperties': [], # Order is important, so use a list 'initialValues': CfdTools.propsToDict(self.initial_conditions), 'boundaries': dict((b.Label, CfdTools.propsToDict(b)) for b in self.bc_group), 'bafflesPresent': self.bafflesPresent(), 'porousZones': {}, 'porousZonesPresent': False, 'initialisationZones': { o.Label: CfdTools.propsToDict(o) for o in self.initialisationZone_objs }, 'initialisationZonesPresent': len(self.initialisationZone_objs) > 0, 'zones': { o.Label: { 'PartNameList': tuple(r[0] for r in o.References) } for o in self.zone_objs }, 'zonesPresent': len(self.zone_objs) > 0, 'meshType': self.mesh_obj.Proxy.Type, 'meshDimension': self.mesh_obj.ElementDimension, 'meshDir': "../" + self.mesh_obj.CaseName, 'solver': CfdTools.propsToDict(self.solver_obj), 'system': {}, 'runChangeDictionary': False } self.processSystemSettings() self.processSolverSettings() self.processFluidProperties() self.processBoundaryConditions() self.processInitialConditions() self.clearCase() self.exportZoneStlSurfaces() if self.porousZone_objs: self.processPorousZoneProperties() self.processInitialisationZoneProperties() self.settings['createPatchesFromSnappyBaffles'] = False cfdMessage("Matching boundary conditions ...\n") if progressCallback: progressCallback("Matching boundary conditions ...") self.setupPatchNames() TemplateBuilder.TemplateBuilder(self.case_folder, self.template_path, self.settings) # Update Allrun permission - will fail silently on Windows fname = os.path.join(self.case_folder, "Allrun") import stat s = os.stat(fname) os.chmod(fname, s.st_mode | stat.S_IEXEC) cfdMessage("Successfully wrote case to folder {}\n".format( self.working_dir)) return True
def writeCase(self): """ writeCase() will collect case settings, and finally build a runnable case. """ cfdMessage("Start to write case to folder {}\n".format( self.working_dir)) if not os.path.exists(self.working_dir): raise IOError("Path " + self.solver_obj.working_dir + " does not exist.") # Perform initialisation here rather than __init__ in case of path changes self.case_folder = os.path.join(self.working_dir, self.solver_obj.InputCaseName) self.case_folder = os.path.expanduser(os.path.abspath( self.case_folder)) self.mesh_file_name = os.path.join(self.case_folder, self.solver_obj.InputCaseName, u".unv") self.template_path = os.path.join(CfdTools.get_module_path(), "data", "defaults") solverSettingsDict = CfdTools.getSolverSettings(self.solver_obj) # Collect settings into single dictionary if not self.mesh_obj: raise RuntimeError("No mesh object found in analysis") phys_settings = dict( zip(self.physics_model.PropertiesList, (getattr(self.physics_model, prop) for prop in self.physics_model.PropertiesList))) if 'gx' in phys_settings: phys_settings['gx'] = Units.Quantity( phys_settings['gx']).getValueAs('m/s^2') phys_settings['gy'] = Units.Quantity( phys_settings['gy']).getValueAs('m/s^2') phys_settings['gz'] = Units.Quantity( phys_settings['gz']).getValueAs('m/s^2') self.settings = { 'physics': phys_settings, 'fluidProperties': [], # Order is important, so use a list 'initialValues': self.initial_conditions, 'boundaries': dict((b.Label, b.BoundarySettings) for b in self.bc_group), 'bafflesPresent': self.bafflesPresent(), 'porousZones': {}, 'porousZonesPresent': False, 'initialisationZones': { o.Label: o.initialisationZoneProperties for o in self.initialisationZone_objs }, 'initialisationZonesPresent': len(self.initialisationZone_objs) > 0, 'zones': { o.Label: { 'PartNameList': tuple(o.partNameList) } for o in self.zone_objs }, 'zonesPresent': len(self.zone_objs) > 0, 'meshType': self.mesh_obj.Proxy.Type, 'meshDimension': self.mesh_obj.ElementDimension, 'solver': solverSettingsDict, 'system': {}, 'runChangeDictionary': False } self.processSystemSettings() self.processSolverSettings() self.processFluidProperties() self.processBoundaryConditions() self.processInitialConditions() self.clearCase() self.exportZoneStlSurfaces() if self.porousZone_objs: self.processPorousZoneProperties() self.processInitialisationZoneProperties() self.settings['createPatchesFromSnappyBaffles'] = False cfdMessage("Matching boundary conditions ...\n") self.setupPatchNames() TemplateBuilder.TemplateBuilder(self.case_folder, self.template_path, self.settings) self.writeMesh() # Update Allrun permission - will fail silently on Windows fname = os.path.join(self.case_folder, "Allrun") import stat s = os.stat(fname) os.chmod(fname, s.st_mode | stat.S_IEXEC) # Move mesh files, after being edited, to polyMesh.org CfdTools.movePolyMesh(self.case_folder) cfdMessage("Successfully wrote {} case to folder {}\n".format( self.solver_obj.SolverName, self.working_dir)) return True
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")
def write_case(self, updating=False): """ Write_case() will collect case setings, and finally build a runnable case. """ print("Start to write case to folder {}\n".format( self.solver_obj.WorkingDir)) _cwd = os.curdir if not os.path.exists(self.solver_obj.WorkingDir): raise IOError("Path " + self.solver_obj.WorkingDir + " does not exist.") os.chdir( self.solver_obj.WorkingDir ) # pyFoam can not write to cwd if FreeCAD is started NOT from terminal try: # Make sure we restore cwd after exception here # Perform initialisation here rather than __init__ in case of path changes self.case_folder = os.path.join(self.solver_obj.WorkingDir, self.solver_obj.InputCaseName) self.case_folder = os.path.expanduser( os.path.abspath(self.case_folder)) self.mesh_file_name = os.path.join(self.case_folder, self.solver_obj.InputCaseName, u".unv") self.template_path = os.path.join(CfdTools.get_module_path(), "data", "defaults") solverSettingsDict = CfdTools.getSolverSettings(self.solver_obj) # Collect settings into single dictionary if not self.mesh_obj: raise RuntimeError("No mesh object found in analysis") self.settings = { 'physics': self.physics_model, 'fluidProperties': [], # Order is important, so use a list 'initialValues': self.initial_conditions, 'boundaries': dict((b.Label, b.BoundarySettings) for b in self.bc_group), 'bafflesPresent': self.bafflesPresent(), 'porousZones': {}, 'porousZonesPresent': False, 'initialisationZones': { o.Label: o.initialisationZoneProperties for o in self.initialisationZone_objs }, 'initialisationZonesPresent': len(self.initialisationZone_objs) > 0, 'zones': { o.Label: { 'PartNameList': tuple(o.partNameList) } for o in self.zone_objs }, 'zonesPresent': len(self.zone_objs) > 0, 'meshType': self.mesh_obj.Proxy.Type, 'solver': solverSettingsDict, 'system': {} } self.processSystemSettings() self.processSolverSettings() self.processFluidProperties() self.processBoundaryConditions() self.processInitialConditions() self.clearCase() self.exportZoneStlSurfaces() if self.porousZone_objs: self.processPorousZoneProperties() self.processInitialisationZoneProperties() self.settings['createPatchesFromSnappyBaffles'] = False if self.mesh_obj.Proxy.Type == "CfdMeshCart": # Cut-cell Cartesian self.setupPatchNames() TemplateBuilder.TemplateBuilder(self.case_folder, self.template_path, self.settings) self.writeMesh() # Update Allrun permission - will fail silently on Windows fname = os.path.join(self.case_folder, "Allrun") import stat s = os.stat(fname) os.chmod(fname, s.st_mode | stat.S_IEXEC) # Move mesh files, after being edited, to polyMesh.org CfdTools.movePolyMesh(self.case_folder) except: raise finally: os.chdir(_cwd) # Restore working dir print("Successfully wrote {} case to folder {}\n".format( self.solver_obj.SolverName, self.solver_obj.WorkingDir)) return True