import sys import argparse import logging import configparser from pprint import pp from time import time from datetime import timedelta from pathlib import Path from distutils import dir_util import subprocess as sp _t0 = time() parser = argparse.ArgumentParser( description='Run the OpenFoam simulation' ) parser.add_argument('-c', '--config', default='config.ini', type=Path, help='Configuration file (default config.ini)') parser.add_argument('-l', '--log-level', default='INFO', type=str, help='Log level') args = parser.parse_args() config = configparser.ConfigParser() config.read(args.config) logging.basicConfig( filename=config.get('main', 'log_file', fallback=None), level=args.log_level ) log = logging.getLogger('openfoam') log.info('Starting program') input_dir = Path(config.get('main', 'input_dir'), config.get('main', 'case')) work_dir = Path(config.get('main', 'work_dir')) if not work_dir.exists(): log.error(f'Work directory ({work_dir}) not found') sys.exit(1) case_dir = work_dir.joinpath(config.get('main', 'case')) if case_dir.exists(): log.info(f'Deleting case ({case_dir})') dir_util.remove_tree(str(case_dir)) log.info(f'Copying case ({input_dir} -> {case_dir})') dir_util.copy_tree( str(input_dir), str(case_dir), ) if config.getboolean('stl', 'copy', fallback=False): stl_dir = case_dir.joinpath('constant', 'triSurface') if stl_dir.exists(): log.info(f'Deleting stl directory ({stl_dir})') dir_util.remove_tree(str(stl_dir)) stl_in = Path(config.get('stl', 'from')) log.info(f'Copying stl directory ({stl_in} -> {stl_dir})') dir_util.copy_tree( str(stl_in), str(stl_dir), ) if config.getboolean('blockMesh', 'enable', fallback=False): log.info('Running blockMesh') blockmesh_log = logging.getLogger('blockMesh') proc = sp.Popen( ('blockMesh'), cwd=case_dir, stdout=sp.PIPE, stderr=sp.PIPE, text=True, ) for line in proc.stdout: blockmesh_log.info(line[:-1]) for line in proc.stderr: blockmesh_log.error(line[:-1]) code = proc.wait() if code != 0: log.error('blockMesh failed') sys.exit(code) log.info(f'blockMesh finished successfully') if config.getboolean('snappyHexMesh', 'enable', fallback=False): log.info('Running snappyHexMesh') snappy_log = logging.getLogger('snappyHexMesh') proc = sp.Popen( ('snappyHexMesh', '-overwrite'), cwd=case_dir, stdout=sp.PIPE, stderr=sp.PIPE, text=True, ) for line in proc.stdout: snappy_log.info(line[:-1]) for line in proc.stderr: snappy_log.error(line[:-1]) code = proc.wait() if code != 0: log.error('snappyHexMesh failed') sys.exit(code) log.info(f'snappyHexMesh finished successfully') log.info('Copying 0.org -> 0') dir_util.copy_tree( str(case_dir.joinpath('0.org')), str(case_dir.joinpath('0')), ) if config.getboolean('setFields', 'enable', fallback=False): log.info('Running setFields') setfields_log = logging.getLogger('setFields') proc = sp.Popen( ('setFields'), cwd=case_dir, stdout=sp.PIPE, stderr=sp.PIPE, text=True, ) for line in proc.stdout: setfields_log.info(line[:-1]) for line in proc.stderr: setfields_log.info(line[:-1]) code = proc.wait() if code != 0: log.error('setFields failed') sys.exit(code) log.info(f'setFields finished successfully') if config.getboolean('olaFlow', 'enable', fallback=False): cmd = ('olaFlow') if config.getboolean('parallel', 'enable', fallback=False): cmd = ( 'mpirun', '-np', config.get('parallel', 'threads'), 'olaFlow', '-parallel' ) decpar_log = logging.getLogger('decomposePar') proc = sp.Popen( ('decomposePar'), cwd=case_dir, stdout=sp.PIPE, stderr=sp.PIPE, text=True, ) for line in proc.stdout: decpar_log.info(line[:-1]) for line in proc.stderr: decpar_log.error(line[:-1]) code = proc.wait() if code != 0: log.error('decomposePar failed') sys.exit(code) log.info(f'decomposePar finished successfully') log.info('Running olaFlow') olaflow_log = logging.getLogger('olaFlow') proc = sp.Popen( cmd, cwd=case_dir, stdout=sp.PIPE, stderr=sp.PIPE, text=True, ) for line in proc.stdout: olaflow_log.info(line[:-1]) for line in proc.stderr: olaflow_log.error(line[:-1]) code = proc.wait() if code != 0: log.error('olaFlow failed') sys.exit(code) log.info(f'olaFlow finished successfully') if config.getboolean('parallel', 'enable', fallback=False) \ and config.getboolean('reconstructPar', 'enable', fallback=False): recpar_log = logging.getLogger('reconstructPar') proc = sp.Popen( ('reconstructPar'), cwd=case_dir, stdout=sp.PIPE, stderr=sp.PIPE, text=True, ) for line in proc.stdout: recpar_log.info(line[:-1]) for line in proc.stderr: recpar_log.error(line[:-1]) code = proc.wait() if code != 0: log.error('reconstructPar failed') sys.exit(code) log.info(f'reconstructPar finished successfully') log.info(f'Deleting processor directories') for proc_dir in case_dir.glob(r'processor*'): log.info(f'Deleting {proc_dir}') dir_util.remove_tree(str(proc_dir)) _t1 = time() log.info(f'Program ended successfully after {timedelta(seconds=_t1-_t0)}')