Exemple #1
0
 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())
Exemple #2
0
    def downloadHisa(self):
        filename = self.download(self.hisa_url, HISA_FILE_EXT, "HiSA")

        if CfdTools.getFoamRuntime() == "MinGW":
            self.user_dir = None
            self.signals.status.emit("Installing HiSA...")
            CfdTools.runFoamCommand(
                '{{ mkdir -p "$FOAM_APPBIN" && cd "$FOAM_APPBIN" && unzip -o "{}"; }}'
                .format(CfdTools.translatePath(filename)))
        else:
            self.user_dir = CfdTools.runFoamCommand(
                "echo $WM_PROJECT_USER_DIR").rstrip().split('\n')[-1]
            # We can't reverse-translate the path for docker since it sits inside the container. Just report it as such.
            if CfdTools.getFoamRuntime() != 'WindowsDocker':
                self.user_dir = CfdTools.reverseTranslatePath(self.user_dir)

            self.signals.status.emit("Extracting HiSA...")
            if CfdTools.getFoamRuntime() == 'WindowsDocker':
                from zipfile import ZipFile
                with ZipFile(filename, 'r') as zip:
                    with tempfile.TemporaryDirectory() as tempdir:
                        zip.extractall(path=tempdir)
                        CfdTools.runFoamCommand(
                            '{{ mkdir -p "$WM_PROJECT_USER_DIR" && cp -r "{}" "$WM_PROJECT_USER_DIR/"; }}'
                            .format(
                                CfdTools.translatePath(
                                    os.path.join(tempdir, HISA_FILE_BASE))))
            else:
                CfdTools.runFoamCommand(
                    '{{ mkdir -p "$WM_PROJECT_USER_DIR" && cd "$WM_PROJECT_USER_DIR" && ( rm -r {}; unzip -o "{}"; );  }}'
                    .format(HISA_FILE_BASE, CfdTools.translatePath(filename)))
Exemple #3
0
 def threadFinished(self, status):
     if self.thread.task == DOWNLOAD_CFMESH:
         if status:
             self.consoleMessage("Download completed")
             if CfdTools.getFoamRuntime() != "MinGW":
                 user_dir = self.thread.user_dir
                 self.consoleMessage(
                     "Building cfMesh. Lengthy process - please wait...")
                 self.consoleMessage("Log file: {}/{}/log.Allwmake".format(
                     user_dir, CFMESH_FILE_BASE))
                 if CfdTools.getFoamRuntime() == 'WindowsDocker':
                     # There seem to be issues when using multi processors to build in docker
                     self.install_process = CfdTools.startFoamApplication(
                         "export WM_NCOMPPROCS=1; ./Allwmake",
                         "$WM_PROJECT_USER_DIR/" + CFMESH_FILE_BASE,
                         'log.Allwmake', self.installFinished)
                 else:
                     self.install_process = CfdTools.startFoamApplication(
                         "export WM_NCOMPPROCS=`nproc`; ./Allwmake",
                         "$WM_PROJECT_USER_DIR/" + CFMESH_FILE_BASE,
                         'log.Allwmake', self.installFinished)
             # Reset foam dir for now in case the user presses 'Cancel'
             CfdTools.setFoamDir(self.initial_foam_dir)
         else:
             self.consoleMessage("Download unsuccessful")
     elif self.thread.task == DOWNLOAD_HISA:
         if status:
             self.consoleMessage("Download completed")
             if CfdTools.getFoamRuntime() != "MinGW":
                 user_dir = self.thread.user_dir
                 self.consoleMessage("Building HiSA. Please wait...")
                 self.consoleMessage("Log file: {}/{}/log.Allwmake".format(
                     user_dir, HISA_FILE_BASE))
                 if CfdTools.getFoamRuntime() == 'WindowsDocker':
                     # There seem to be issues when using multi processors to build in docker
                     self.install_process = CfdTools.startFoamApplication(
                         "export WM_NCOMPPROCS=1; ./Allwmake",
                         "$WM_PROJECT_USER_DIR/" + HISA_FILE_BASE,
                         'log.Allwmake', self.installFinished)
                 else:
                     self.install_process = CfdTools.startFoamApplication(
                         "export WM_NCOMPPROCS=`nproc`; ./Allwmake",
                         "$WM_PROJECT_USER_DIR/" + HISA_FILE_BASE,
                         'log.Allwmake', 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 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()
Exemple #5
0
 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
Exemple #6
0
    def threadFinished(self, status):
        if self.thread.task == DEPENDENCY_CHECK:
            QApplication.restoreOverrideCursor()

        elif 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))
                    shutil.copy(
                        os.path.join(CfdTools.get_module_path(), 'data',
                                     script_name),
                        os.path.join(user_dir, script_name))
                    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)
            else:
                self.consoleMessage("Download unsuccessful")
Exemple #7
0
    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
Exemple #8
0
    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
Exemple #9
0
    def threadFinished(self, status):
        if self.thread.task == DEPENDENCY_CHECK:
            QApplication.restoreOverrideCursor()

        elif self.thread.task == DOWNLOAD_GNUPLOTPY:
            self.consoleMessage("Attempting to install Gnuplot-py package:")

            if platform.system() == 'Windows':
                python_exe = os.path.join(FreeCAD.getHomePath(), 'bin',
                                          'python.exe')
            else:
                python_exe = 'python'
            cmd = [python_exe, '-u', 'setup.py', 'install']

            working_dir = os.path.join(tempfile.gettempdir(),
                                       GNUPLOTPY_FILE_BASE)
            self.install_process = CfdConsoleProcess.CfdConsoleProcess(
                finishedHook=self.installFinished)
            print("Running {} in {}".format(' '.join(cmd), working_dir))

            self.install_process.start(cmd, working_dir=working_dir)
            if not self.install_process.waitForStarted():
                self.consoleMessage("Unable to run command " + ' '.join(cmd),
                                    '#FF0000')

        elif 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))
                    shutil.copy(
                        os.path.join(CfdTools.get_module_path(), 'data',
                                     script_name),
                        os.path.join(user_dir, script_name))
                    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)
            else:
                self.consoleMessage("Download unsuccessful")
Exemple #10
0
 def testGetRuntime(self, disable_exception=True):
     """ Set the foam dir temporarily and see if we can detect the runtime """
     prefs = CfdTools.getPreferencesLocation()
     prev_foam_dir = FreeCAD.ParamGet(prefs).GetString(
         "InstallationPath", "")
     CfdTools.setFoamDir(self.foam_dir)
     try:
         runtime = CfdTools.getFoamRuntime()
     except IOError as e:
         runtime = None
         if not disable_exception:
             raise
     CfdTools.setFoamDir(prev_foam_dir)
     return runtime
Exemple #11
0
    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()
Exemple #12
0
    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))
Exemple #13
0
    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))