예제 #1
0
class SimpleBlockMeshGenerator:
    def __init__(self,
                 mesh_config: SimpleBlockMeshConfig,
                 fragmentation_config: FragmentationConfig,
                 execution_config: ExecutionConfig = ExecutionConfig()):
        self.mesh_config = mesh_config
        self.fragmentation_config = fragmentation_config
        self.exec_config = execution_config
        self.out_file = "system/blockMeshDict"

        if self.exec_config is not None:
            self.out_file = os.path.join(execution_config.execution_folder,
                                         self.out_file)

        self._profiler = Profiler(enable_profiler)

    def __del__(self):
        self._profiler.print_report()

    def create(self, custom_out_file=None):
        _logger.info("\n\n===== Run geometry generating")
        self._profiler.start("Geometry creating")
        self._print_configuration()

        self._calculate_points()
        self._calculate_fragmentation()
        self._calculate_boundary()

        text = self._format_text()

        file_to_write = self.out_file
        if custom_out_file != 0 and (custom_out_file
                                     is not None) and (len(custom_out_file)):
            file_to_write = custom_out_file
        if custom_out_file == 0:
            file_to_write = 0

        self.save_geometry(text, file_to_write)
        self._profiler.stop("Geometry creating")
        _logger.info("===== End geometry generating\n\n")

    def generate(self):
        _logger.info("\n\n===== Run block mesh generating")
        self._profiler.start("Mesh generating")
        self.generate_mesh()
        self._profiler.stop("Mesh generating")
        # Just because there a lots of logs from blockMesh command
        _logger.info("===== End block mesh generating\n\n")

    def _print_configuration(self):
        _logger.log(LogLvl.LOG_INFO, "Generate mesh with size:")
        _logger.log(
            LogLvl.LOG_INFO,
            "width_mm: {}\theight_mm: {}\tlength_mm: {}".format(
                self.mesh_config.width_mm, self.mesh_config.height_mm,
                self.mesh_config.length_mm))

        _logger.log(LogLvl.LOG_INFO, "Generate mesh with fragmentation:")
        _logger.log(
            LogLvl.LOG_INFO, "{:>25}{:>25}{:>25}\n".format(
                "width_fragmentation: " + str(self.fragmentation_config.width),
                "height_fragmentation: " +
                str(self.fragmentation_config.height),
                "length_fragmentation: " +
                str(self.fragmentation_config.length)))

    def _calculate_points(self):
        # TODO add check, that convertToMeters is 0.001 (m to mm)
        width_mm = self.mesh_config.width_mm
        height_mm = self.mesh_config.height_mm
        length_mm = self.mesh_config.length_mm

        p1 = [0, 0, 0]
        p2 = [width_mm, 0, 0]
        p3 = [width_mm, height_mm, 0]
        p4 = [0, height_mm, 0]
        p5 = [0, 0, length_mm]
        p6 = [width_mm, 0, length_mm]
        p7 = [width_mm, height_mm, length_mm]
        p8 = [0, height_mm, length_mm]

        arr = [p1, p2, p3, p4, p5, p6, p7, p8]
        self.points = ""
        for i in range(len(arr)):
            self.points += "    ({} {} {})".format(arr[i][0], arr[i][1],
                                                   arr[i][2])
            if i + 1 != len(arr):
                self.points += "\n"

    def _calculate_fragmentation(self):
        mesh_elem_size_mm = self.fragmentation_config.elem_size_mm
        assert (self.mesh_config.width_mm >= mesh_elem_size_mm)
        assert (self.mesh_config.height_mm >= mesh_elem_size_mm)
        assert (self.mesh_config.length_mm >= mesh_elem_size_mm)

        # TODO enable dynamic fragmentation
        # length_fragmentation = int(float(length_mm) / mesh_elem_size_mm)
        # height_fragmentation = int(float(height_mm) / mesh_elem_size_mm)
        # width_fragmentation = int(float(width_mm) / mesh_elem_size_mm)
        # TODO try to use 6 2 1 (default in tutorial)

        # x - width, y - height, z - length
        self.fragmentation = "    hex (0 1 2 3 4 5 6 7) ({} {} {}) simpleGrading (1.0 1.0 1.0)".format(
            self.fragmentation_config.width, self.fragmentation_config.height,
            self.fragmentation_config.length)

    def _calculate_boundary(self):
        _logger.error("Not implemented")

    def _format_text(self):
        t = Template(MESH_FILE_TEMPLATE)
        boundary = """    topSurface
    {
        type patch;
        faces
        (
            (2 3 7 6)
        );
    }

    bottomSurface
    {
        type patch;
        faces
        (
            (0 1 5 4)
        );
    }

    rearFixedEnd
    {
        type patch;
        faces
        (
            (4 5 6 7)
        );
    }

    frontTractionEnd
    {
        type patch;
        faces
        (
            (0 1 2 3)
        );
    }

    leftSurface
    {
        type patch;
        faces
        (
            (0 3 7 4)
        );
    }
    
    rightSurface
    {
        type patch;
        faces
        (
            (1 2 6 5)
        );
    }"""
        return t.substitute(points=self.points,
                            fragmentation=self.fragmentation,
                            boundary=boundary)

    @staticmethod
    def save_geometry(text, filename):
        if filename != 0:
            _logger.debug("Save file to: {}".format(filename))
            f = open(filename, "w+")
            f.writelines(text)
            f.close()
        else:
            print(text)

    def generate_mesh(self):
        # FIXME temporary solution
        # FIXME Not check that is not None
        openfoam_folder = "OPENFOAM FOLDER NOT SPECIFIED"
        if self.exec_config is not None:
            if self.exec_config.openfoam_folder is not None:
                openfoam_folder = self.exec_config.openfoam_folder

        env_script = "ENV SCRIPT NOT SPECIFIED"
        if self.exec_config is not None:
            if self.exec_config.prepare_env_script is not None:
                env_script = self.exec_config.prepare_env_script

        # Make sure script have commented lines, where FOAM_INST_DIR is set
        prepare_call = "export FOAM_INST_DIR=" + openfoam_folder
        prepare_call += "; "
        prepare_call += ". " + env_script
        prepare_call += "; "
        prepare_call += "cd " + self.exec_config.execution_folder
        try:
            command = "{}; {}".format(prepare_call, "blockMesh")
            _logger.info(command)
            if _logger.log_lvl == LogLvl.LOG_DEBUG or print_mesh_stats:
                subprocess.call("{}".format(command), shell=True)
            else:
                subprocess.call("{} > /dev/null".format(command), shell=True)
        except OSError:
            raise OSError(
                "blockMesh not found. Please check that you have prepared OpenFOAM environment"
            )
예제 #2
0
class Executor:
    # openfoam_solver = "solidEquilibriumDisplacementFoamMod"
    openfoam_solver = "solidDisplacementFoamMod"

    def __init__(self, exec_conf: ExecutionConfig, mesh_conf, fragmentation_conf: FragmentationConfig):
        self._profiler = Profiler(enable_profiler)
        _logger.info("Solver: {}".format(self.openfoam_solver))
        self.exec_config = exec_conf
        self.result_dir = exec_conf.output_dir
        files.create_directory(self.result_dir)
        self.results = {}
        result_file_geom_prefix = None
        if type(mesh_conf) is SimpleBlockMeshConfig:
            result_file_geom_prefix = "gw{}_gh{}_gl{}".format(
                mesh_conf.width_mm,
                mesh_conf.height_mm,
                mesh_conf.length_mm)
            self.geom_values = "{}\t{}\t{}".format(
                mesh_conf.width_mm,
                mesh_conf.height_mm,
                mesh_conf.length_mm)
            self.geom_titles = "Geometry width\tGeometry height\tGeometry length"
        else:
            result_file_geom_prefix = ""
            self.geom_values = ""
            self.geom_titles = ""

            for line_idx in range(len(mesh_conf.width_lines)):
                result_file_geom_prefix += "w{}={}_".format(line_idx, mesh_conf.width_lines[line_idx])
                self.geom_titles += "{} {}\t".format("Width line", line_idx)
                self.geom_values += "{}\t".format(mesh_conf.width_lines[line_idx])

            for line_idx in range(len(mesh_conf.height_distance)):
                result_file_geom_prefix += "h{}={}_".format(line_idx, mesh_conf.height_distance[line_idx])
                self.geom_titles += "{} {}\t".format("Height line", line_idx)
                self.geom_values += "{}\t".format(mesh_conf.height_distance[line_idx])

            result_file_geom_prefix += "l={}".format(mesh_conf.length)
            self.geom_titles += "{}".format("Length")
            self.geom_values += "{}".format(mesh_conf.length)

        _logger.debug(result_file_geom_prefix)
        _logger.debug(self.geom_values)

        fragmentation_options_line = "fw{}_fh{}_fl{}".format(
            fragmentation_conf.width,
            fragmentation_conf.height,
            fragmentation_conf.length)
        self.fragmentation_values = "{}\t{}\t{}".format(
            fragmentation_conf.width,
            fragmentation_conf.height,
            fragmentation_conf.length)

        result_file_name = "result_{}_{}.txt".format(result_file_geom_prefix, fragmentation_options_line)
        self.result_file = os.path.join(self.result_dir, result_file_name)
        self.parsed_name = datetime.datetime.now().strftime("%Y-%m-%d-%H.txt")

    def __del__(self):
        self._profiler.print_report()

    def run(self):
        _logger.info("\n\n===== Run calculation")
        self.__run_execution()
        _logger.info("===== End calculation\n\n")

        _logger.info("\n\n===== Run result parsing")
        self._profiler.start("Parse results")
        self.__parse_output_from_file("sigmaEq")
        self.__parse_output_from_file("D")
        self.__parse_output_from_file("Time")
        self._profiler.stop("Parse results")
        _logger.info("===== End result parsing\n\n")

    def __run_execution(self):
        self._profiler.start("Run solver")
        # FIXME no check if none
        prepare_call = "export FOAM_INST_DIR=" + self.exec_config.openfoam_folder
        prepare_call += "; "
        prepare_call += ". " + "$HOME/prog/OpenFOAM/OpenFOAM-dev/etc/bashrc_modified"
        prepare_call += "; "
        prepare_call += "cd " + self.exec_config.execution_folder
        try:
            subprocess.call(["{}; {} > {}".format(prepare_call, self.openfoam_solver, self.result_file)], shell=True)
        except OSError:
            _logger.error("{} not found.".format(self.openfoam_solver))
            _logger.error("Please make sure you are using modified version of OpenFOAM and env is prepared")
        self._profiler.stop("Run solver")

    def __parse_time(self, text):
        found_exec = re.findall(r'ExecutionTime = (\d+.?\d*) s', text)[-1]
        found_clock = re.findall(r'ClockTime = (\d+.?\d*) s', text)[-1]
        exec_time = float(found_exec)
        clock_time = float(found_clock)

        # Save result to file
        file_parsed_name = "{}-{}".format("time", self.parsed_name)
        file_parsed_result = os.path.join(self.result_dir, file_parsed_name)
        formatted_result = "{geometry}\t{fragmentation}\t{exec_time}\t{clock_time}\n".format(
            geometry=self.geom_values,
            fragmentation=self.fragmentation_values,
            exec_time=exec_time, clock_time=clock_time)

        with open(file_parsed_result, "a") as log_file:
            if os.stat(file_parsed_result).st_size == 0:
                log_file.write("{}"
                               "\tFragmentation width\tFragmentation height\tFragmentation length"
                               "\t{}\t{}\n".format(self.geom_titles, "Execution time", "Clock time"))
            log_file.write(formatted_result)

    def __parse_output(self, param_to_parse, text):
        _logger.debug("Parse: {}".format(param_to_parse))

        start_index = text.rfind("Max {} = ".format(param_to_parse))
        len = text[start_index:].find('\n')

        _logger.debug(text[start_index:start_index + len])

        # (.123 250000 1.00009e+06 160325 7.29635e-10 2.36271e+06 0 -2.40131e-45 5.12455e-06 2.01673e-06 1.18136e-05)
        p = re.compile(r'[-+]?[0-9]*\.?[0-9]+[eE]?[-+]?[0-9]*')
        values = p.findall(text[start_index:start_index + len])

        _logger.debug("Found values: {}".format(values))

        float_val = []
        for val in values:
            float_val.append(float(val))

        _logger.debug("Values as float: {}".format(float_val))

        max_value = -1.
        # FIXME Workaround for cantilever beam to use D which is with -D flag
        if param_to_parse == "sigmaEq":
            max_value = max(float_val)
        elif param_to_parse == "D":
            max_value = abs(max(float_val, key=abs))

        _logger.info("Max (Min) {}: {}".format(param_to_parse, max_value))
        # Save to map
        self.results[param_to_parse] = max_value

        # Save result to file
        file_parsed_name = "{}-{}".format(param_to_parse, self.parsed_name)
        file_parsed_result = os.path.join(self.result_dir, file_parsed_name)
        formatted_result = "{geometry}\t{fragmentation}\t{value}\n".format(geometry=self.geom_values,
                                                                           fragmentation=self.fragmentation_values,
                                                                           value=max_value)

        with open(file_parsed_result, "a") as log_file:
            if os.stat(file_parsed_result).st_size == 0:
                log_file.write("{}"
                               "\tFragmentation width\tFragmentation height\tFragmentation length"
                               "\t{}\n".format(self.geom_titles, param_to_parse))
            log_file.write(formatted_result)

    def __parse_output_from_file(self, param_to_parse):
        with open(self.result_file, 'rt') as file:
            contents = file.read()

        # TODO yeaah, custom call for "time"!
        if param_to_parse == "Time":
            self.__parse_time(contents)
        else:
            self.__parse_output(param_to_parse, contents)

    def get_results(self):
        return self.results