diff --git a/openfoam/run/__main__.py b/openfoam/run/__main__.py
index 83ce039..3c7c0dc 100644
--- a/openfoam/run/__main__.py
+++ b/openfoam/run/__main__.py
@@ -15,8 +15,7 @@ import urllib.error
 
 from .grafana import Silencer
 from .stl import copy_stl
-from .blockmesh import blockmesh
-from .snappyhexmesh import snappyhexmesh
+from .run import run
 
 
 _t0 = time()
@@ -41,6 +40,17 @@ log = logging.getLogger('openfoam')
 
 log.info('Starting program')
 
+
+def step(command, alias=None):
+    if alias == None: alias = command
+    log.info(f'Running {alias}')
+    code = run(command, case_dir, alias)
+    if code != 0:
+        log.error(f'{alias} failed')
+        sys.exit(code)
+    log.info(f'{alias} finished successfully')
+
+
 if config.getboolean('grafana', 'pause', fallback=False):
     log.info('Silencing Grafana alert')
     grafana = Silencer(
@@ -75,20 +85,10 @@ if config.getboolean('stl', 'copy', fallback=False):
     copy_stl(stl_in, case_dir)
 
 if config.getboolean('blockMesh', 'enable', fallback=False):
-    log.info('Running blockMesh')
-    code = blockmesh(case_dir)
-    if code != 0:
-        log.error('blockMesh failed')
-        sys.exit(code)
-    log.info(f'blockMesh finished successfully')
+    step(('blockMesh'))
 
 if config.getboolean('snappyHexMesh', 'enable', fallback=False):
-    log.info('Running snappyHexMesh')
-    code = snappyhexmesh(case_dir)
-    if code != 0:
-        log.error('snappyHexMesh failed')
-        sys.exit(code)
-    log.info(f'snappyHexMesh finished successfully')
+    step(('snappyHexMesh', '-overwrite'), 'snappyHexMesh')
 
 log.info('Copying 0.org -> 0')
 shutil.copytree(
@@ -97,24 +97,7 @@ shutil.copytree(
 )
 
 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')
+    step(('setFields'))
 
 if config.getboolean('olaFlow', 'enable', fallback=False):
     cmd = ('olaFlow')
@@ -124,62 +107,13 @@ if config.getboolean('olaFlow', 'enable', fallback=False):
             '-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')
+        step(('decomposePar'))
 
-    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')
+    step(cmd, 'olaFlow')
 
     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')
+            and config.getboolean('reconstructPar', 'enable', fallback=False):
+        step(('reconstructPar'))
 
         log.info(f'Deleting processor directories')
         for proc_dir in case_dir.glob(r'processor*'):
diff --git a/openfoam/run/blockmesh.py b/openfoam/run/run.py
similarity index 51%
rename from openfoam/run/blockmesh.py
rename to openfoam/run/run.py
index 2f7e99f..0b67026 100644
--- a/openfoam/run/blockmesh.py
+++ b/openfoam/run/run.py
@@ -1,17 +1,18 @@
 import subprocess as sp
 import logging
 
-def blockmesh(case_dir):
-    blockmesh_log = logging.getLogger('blockMesh')
+def run(command, case, alias=None):
+    if alias == None: alias = command
+    log = logging.getLogger(alias)
     proc = sp.Popen(
-        ('blockMesh'),
-        cwd=case_dir,
+        command,
+        cwd=case,
         stdout=sp.PIPE,
         stderr=sp.PIPE,
         text=True,
     )
     for line in proc.stdout:
-        blockmesh_log.info(line[:-1])
+        log.info(line[:-1])
     for line in proc.stderr:
-        blockmesh_log.error(line[:-1])
+        log.info(line[:-1])
     return proc.wait()
