import sys import argparse import logging import configparser from pprint import pp from time import time from datetime import timedelta from pathlib import Path 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'))\ .expanduser() work_dir = Path(config.get('main', 'work_dir')).expanduser() 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})') cp = sp.Popen( ('cp', '-r', stl_in, stl_dir), stderr=sp.PIPE, text=True, ) code = cp.wait() if cp.returncode != 0: log.error(f'Error while copying stl ({stl_in} -> {stl_dir})') log.error(cp.stderr.read()[:-1]) sys.exit(code) rm = sp.Popen( ('rm', '-r', case_dir), stdout=sp.PIPE, stderr=sp.PIPE, text=True, ) code = rm.wait() if code != 0: log.error(f'Error while deleting case ({case_dir})') log.error(rm.stderr) sys.exit(code) log.info(f'Copying case ({input_dir} -> {case_dir})') cp = sp.run( ('cp', '-r', input_dir, case_dir), capture_output=False, ) if cp.returncode != 0: log.error(f'Error while copying case ({input_dir} -> {case_dir})') log.error(cp.stderr) sys.exit(cp.returncode) 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})') rm = sp.Popen( ('rm', '-r', stl_dir), stdout=sp.PIPE, stderr=sp.PIPE, text=True, ) code = rm.wait() if code != 0: log.error(f'Error while deleting stl ({stl_dir})') log.error(rm.stderr.read()) sys.exit(code) stl_in = Path(config.get('stl', 'from')).expanduser() log.info(f'Copying stl directory ({stl_in} -> {stl_dir})') cp = sp.Popen( ('cp', '-r', stl_in, stl_dir), stderr=sp.PIPE, text=True, ) code = cp.wait() if cp.returncode != 0: log.error(f'Error while copying stl ({stl_in} -> {stl_dir})') log.error(cp.stderr.read()[:-1]) sys.exit(code) 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') cp = sp.run( ('cp', '-r', case_dir.joinpath('0.org'), case_dir.joinpath('0'), ), capture_output=False, ) if cp.returncode != 0: log.error(f'Error while copying 0.org -> 0') log.error(cp.stderr) sys.exit(cp.returncode) 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}') rm = sp.run( ('rm', '-r', proc_dir), capture_output=False, ) if rm.returncode != 0: log.error(f'Error while deleting processor ({proc_dir})') log.error(rm.stderr) sys.exit(rm.returncode) _t1 = time() log.info(f'Program ended successfully after {timedelta(seconds=_t1-_t0)}')