Esempio n. 1
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
Esempio n. 2
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))
Esempio n. 3
0
    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
Esempio n. 4
0
    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
Esempio n. 5
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))
Esempio n. 6
0
    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")
Esempio n. 7
0
    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