Source code for fluidsimfoam.invoke.context

"""Extended Invoke Context for OpenFOAM

"""

import os
from pathlib import Path
from shutil import copytree, rmtree
from typing import Optional

import invoke.context

from fluiddyn.util import time_as_str
from fluidsimfoam.util import get_parallel_info, make_hex


[docs]class Context(invoke.context.Context): """Extended Invoke Context for OpenFOAM""" time_as_str = time_as_str() """Time of Invoke call """ def __init__(self, *args, **kwargs): self._set(path_run=Path.cwd()) parallel, nsubdoms = get_parallel_info() self._set(parallel=parallel) self._set(nsubdoms=nsubdoms) if os.environ.get("FOAM_MPI", "") == "msmpi": mpi_command = "mpiexec" else: mpi_command = "mpirun" self._set(mpi_command=mpi_command) super().__init__(*args, **kwargs)
[docs] def run_appl( self, command: str, name_command: Optional[str] = None, suffix_log: Optional[str] = None, ): """Run an OpenFOAM application and save the log""" if name_command is None: name_command = command.split()[0] name_log = f"log.{name_command}" if suffix_log is not None: name_log += "-" + suffix_log path_log = Path(f"logs{self.time_as_str}/{name_log}") path_log.parent.mkdir(exist_ok=True) with open(path_log, "w") as file: try: self.run(command, echo=True, out_stream=file, err_stream=file) except invoke.exceptions.UnexpectedExit: file.flush() print( f"Error for command {command}\n" f"log file content:\n{path_log.read_text()}" )
[docs] def run_appl_once( self, command: str, suffix_log: Optional[str] = None, dict_file: Optional[str] = None, check_dict_file: bool = True, force: bool = False, parallel_if_needed: bool = False, path_decompose_par_dict: Optional[str] = None, nsubdoms: Optional[int] = None, ): """Run an OpenFOAM application only once per simulation""" command_name = command.split()[0] if check_dict_file and not force: if dict_file is None: dict_file = "system/" + command_name + "Dict" path_dict_file = Path(dict_file) if not path_dict_file.exists(): return lock_name = f"{command_name}_called" if command_name != command: lock_name += make_hex(command) path_command_called = Path(f".data_fluidsim/{lock_name}") path_command_called.parent.mkdir(exist_ok=True) if force or not path_command_called.exists(): path_command_called.touch() if not parallel_if_needed: parallel = False else: if path_decompose_par_dict is None: parallel = self.parallel nsubdoms_file = self.nsubdoms else: parallel, nsubdoms_file = get_parallel_info( path_decompose_par_dict ) command += f" -decomposeParDict {path_decompose_par_dict}" name_command = command.split()[0] if parallel: if nsubdoms is None: nsubdoms = nsubdoms_file command = f"{self.mpi_command} -n {nsubdoms} {command} -parallel" self.run_appl( command, name_command=name_command, suffix_log=suffix_log )
[docs] def save_0_dir(self): """Save ``0`` directory in ``O.orig``""" print("Saving 0 to O.orig") copytree("0", "O.orig", dirs_exist_ok=True)
[docs] def restore_0_dir(self): """Restore ``0`` directory from ``O.orig``""" print("Restoring 0 directory") paths_0 = ["0"] paths_0.extend(Path.cwd().glob("processor*/0")) for path0 in paths_0: rmtree(path0, ignore_errors=True) copytree("O.orig", path0)