Commit 67f24e46 authored by Dion Haefner's avatar Dion Haefner

finished python wrappers for parallel execution

parent d0045300
#!/usr/bin/env python #!/usr/bin/env python
import os import os
import sys
import shutil import shutil
import argparse import argparse
import warnings import warnings
...@@ -20,6 +21,7 @@ MPIEXEC_PREFLAG = "@MPIEXEC_PREFLAG@" ...@@ -20,6 +21,7 @@ MPIEXEC_PREFLAG = "@MPIEXEC_PREFLAG@"
MPIEXEC_POSTFLAGS = "@MPIEXEC_POSTFLAGS@" MPIEXEC_POSTFLAGS = "@MPIEXEC_POSTFLAGS@"
# #
# set some paths
DORIE_EXECUTABLE = os.path.join(DORIEDIR, "dune/dorie/dorie") DORIE_EXECUTABLE = os.path.join(DORIEDIR, "dune/dorie/dorie")
PARAMETERDIR = os.path.join(DORIEDIR, "doc/default_files") PARAMETERDIR = os.path.join(DORIEDIR, "doc/default_files")
DORIE_PYTHON = os.path.join(DORIEDIR, "dune-env") DORIE_PYTHON = os.path.join(DORIEDIR, "dune-env")
...@@ -28,16 +30,19 @@ MPIRUN = lambda nproc, exe, *args: [k for k in [MPIEXEC,MPIEXEC_NUMPROC_FLAG,str ...@@ -28,16 +30,19 @@ MPIRUN = lambda nproc, exe, *args: [k for k in [MPIEXEC,MPIEXEC_NUMPROC_FLAG,str
def run(args): def run(args):
if not os.path.isfile(args["config"]): if not os.path.isfile(args["config"]):
raise IOError("Configuration file {} not found".format(args["config"])) raise IOError("Configuration file {} not found".format(args["config"]))
if args["parallel"] == 1: try:
subprocess.call([DORIE_EXECUTABLE, args["config"]]) if args["parallel"] == 1:
else: subprocess.check_call([DORIE_EXECUTABLE, args["config"]])
print([MPIRUN(args["parallel"],DORIE_EXECUTABLE) + [args["config"]]]) else:
subprocess.call(MPIRUN(args["parallel"],DORIE_EXECUTABLE,args["config"])) subprocess.check_call(MPIRUN(args["parallel"],DORIE_EXECUTABLE,args["config"]))
except subprocess.CalledProcessError:
print("Error while running DORiE")
sys.exit(1)
def create(args): def create(args):
for f in ("config.ini", "parfield.ini", "2d_infiltr.bcdat", "3d_infiltr.bcdat"): for f in ("config.ini", "parfield.ini", "2d_infiltr.bcdat", "3d_infiltr.bcdat"):
newfile = os.path.join(os.getcwd(),f) newfile = os.path.join(os.getcwd(),f)
if os.path.exists(newfile): if os.path.exists(newfile) and not args["force"]:
override = (input("File {} exists. Override? [Y/n] ".format(f)) or "Y") in ["Y","y"] override = (input("File {} exists. Override? [Y/n] ".format(f)) or "Y") in ["Y","y"]
if not override: if not override:
continue continue
...@@ -48,9 +53,9 @@ def pfg(args): ...@@ -48,9 +53,9 @@ def pfg(args):
if not os.path.isfile(args["config"]): if not os.path.isfile(args["config"]):
raise IOError("Configuration file {} not found".format(args["config"])) raise IOError("Configuration file {} not found".format(args["config"]))
if args["parallel"] == 1: if args["parallel"] == 1:
subprocess.call([DORIE_PYTHON, "pf_from_file.py", "--param", args["config"]]) subprocess.call([DORIE_PYTHON, "pf_from_file.py", args["config"]])
else: else:
raise NotImplementedError subprocess.call([DORIE_PYTHON, "pf_from_file.py", args["config"], "--parallel", str(args["parallel"])])
def plot(args): def plot(args):
if not os.path.isfile(args["vtk"]): if not os.path.isfile(args["vtk"]):
...@@ -60,10 +65,9 @@ def plot(args): ...@@ -60,10 +65,9 @@ def plot(args):
else: else:
subprocess.call([DORIE_PYTHON, "plot_vtk.py", "-f", args["vtk"]]) subprocess.call([DORIE_PYTHON, "plot_vtk.py", "-f", args["vtk"]])
if __name__ == "__main__": if __name__ == "__main__": # parse command line and call command handler
try: # catch all exceptions we we can output an error message try:
with warnings.catch_warnings(record=True) as warn: # catch all warnings so we can count them with warnings.catch_warnings(record=True) as warn:
# PARSE COMMAND LINE
parser = argparse.ArgumentParser(description="DORiE command line interface", parser = argparse.ArgumentParser(description="DORiE command line interface",
epilog="For more information check our online documentation:\n" epilog="For more information check our online documentation:\n"
"http://dorie-docs.bitballoon.com (password: 'richards')" "http://dorie-docs.bitballoon.com (password: 'richards')"
...@@ -72,22 +76,23 @@ if __name__ == "__main__": ...@@ -72,22 +76,23 @@ if __name__ == "__main__":
parser_run = subparsers.add_parser('run',help="start dorie") parser_run = subparsers.add_parser('run',help="start dorie")
parser_run.add_argument('config',help="DORiE configuration file. Can be created with 'dorie create'.") parser_run.add_argument('config',help="DORiE configuration file. Can be created with 'dorie create'.")
parser_run.add_argument('--parallel', metavar='N', nargs='?', default=1, const=multiprocessing.cpu_count(), type=int, required=False, parser_run.add_argument('-p','--parallel', metavar='N', nargs='?', default=1, const=multiprocessing.cpu_count(), type=int, required=False,
help="Run in parallel on N processes. If N is not specified, run on all available CPU threads.") help="Run in parallel on N processes. If N is not specified, run on all available CPU threads.")
parser_run.set_defaults(func=run) parser_run.set_defaults(func=run)
parser_create = subparsers.add_parser('create', help="Copy example configuration to current folder.") parser_create = subparsers.add_parser('create', help="Copy example configuration to current folder.")
parser_create.add_argument('-f','--force', help="Override existing files.", action="store_true")
parser_create.set_defaults(func=create) parser_create.set_defaults(func=create)
parser_pfg = subparsers.add_parser('pfg', help="Start parameter field generator.") parser_pfg = subparsers.add_parser('pfg', help="Start parameter field generator.")
parser_pfg.add_argument('config', parser_pfg.add_argument('config',
help="Configuration file for the parameter field generator. Can be created with 'dorie create'.") help="Configuration file for the parameter field generator. Can be created with 'dorie create'.")
parser_pfg.add_argument('--parallel', metavar='N', nargs='?', default=1, const=multiprocessing.cpu_count(), type=int, required=False, parser_pfg.add_argument('-p','--parallel', metavar='N', nargs='?', default=1, const=multiprocessing.cpu_count(), type=int, required=False,
help="Run in parallel on N processes. If N is not specified, run on all available CPU threads.") help="Run in parallel on N processes. If N is not specified, run on all available CPU threads.")
parser_pfg.set_defaults(func=pfg) parser_pfg.set_defaults(func=pfg)
parser_plot = subparsers.add_parser('plot', help="Plot a preview of a VTK file created by DORiE.") parser_plot = subparsers.add_parser('plot', help="Plot a preview of a VTK file created by DORiE.")
parser_plot.add_argument('vtk', help="Input VTK file") parser_plot.add_argument('vtk', help="Input VTK file.")
parser_plot.add_argument('--var', nargs='*', required=False) parser_plot.add_argument('--var', nargs='*', required=False)
parser_plot.set_defaults(func=plot) parser_plot.set_defaults(func=plot)
......
...@@ -47,6 +47,11 @@ int main(int argc, char** argv) ...@@ -47,6 +47,11 @@ int main(int argc, char** argv)
DUNE_THROW(Dune::IOError,"No parameter file specified!"); DUNE_THROW(Dune::IOError,"No parameter file specified!");
const std::string inifilename = argv[1]; const std::string inifilename = argv[1];
#if !(HDF5_PARALLEL)
if (helper.size() > 1)
DUNE_THROW(Dune::Exception,"Parallel HDF5 library is needed to run in parallel");
#endif
// Read ini file // Read ini file
Dune::ParameterTree inifile; Dune::ParameterTree inifile;
Dune::ParameterTreeParser ptreeparser; Dune::ParameterTreeParser ptreeparser;
......
...@@ -335,7 +335,7 @@ namespace Dune { ...@@ -335,7 +335,7 @@ namespace Dune {
nNearZero++; nNearZero++;
} }
if( fielddata.showEV ){ if (fielddata.showEV && my_rank == 0){
std::cout << "Properties of Syy: " << std::endl; std::cout << "Properties of Syy: " << std::endl;
std::cout << alloc_local << " eigenvalues" << std::endl; std::cout << alloc_local << " eigenvalues" << std::endl;
std::cout << nPositive << " eigenvalues > 1E-6" << std::endl; std::cout << nPositive << " eigenvalues > 1E-6" << std::endl;
...@@ -374,14 +374,16 @@ namespace Dune { ...@@ -374,14 +374,16 @@ namespace Dune {
|| ||
!load_yfield_properties( fielddata.location + "/YField.dat", my_rank ) !load_yfield_properties( fielddata.location + "/YField.dat", my_rank )
) { ) {
std::cout << "New geostatistical data: compute eigenvalues of the circulant matrix." << std::endl; if(my_rank == 0)
std::cout << "New geostatistical data: compute eigenvalues of the circulant matrix." << std::endl;
generate_eigenvalues(); generate_eigenvalues();
} }
else else
std::cout << "Given geostatistical data match existing field." << std::endl; if(my_rank == 0)
std::cout << "Given geostatistical data match existing field." << std::endl;
if( my_rank == 0 ){ if(my_rank == 0){
if( !bNewField ){ if( !bNewField ){
std::cout << "New field will be generated due to changed geostatistical data." << std::endl; std::cout << "New field will be generated due to changed geostatistical data." << std::endl;
} else { } else {
...@@ -660,16 +662,18 @@ namespace Dune { ...@@ -660,16 +662,18 @@ namespace Dune {
if( !bFileExists( fielddata.location + "/YField.h5" ) ) if( !bFileExists( fielddata.location + "/YField.h5" ) )
{ {
std::cout << "Warning: File is missing: YField.h5" if(my_rank==0)
std::cout << "Warning: File is missing: YField.h5"
<< std::endl; << std::endl;
return false; return false;
} }
std::cout << "Found suitable Y-Field characteristics! Load the field from YField.dat" if(my_rank==0)
<< std::endl; std::cout << "Found suitable Y-Field characteristics! Load the field from YField.dat"
<< std::endl;
if(comm_size==1){ if(comm_size==1){
Vector<UINT> local_count(dim,0); Vector<UINT> local_count(dim,0);
Vector<UINT> local_offset(dim,0); Vector<UINT> local_offset(dim,0);
...@@ -725,13 +729,15 @@ namespace Dune { ...@@ -725,13 +729,15 @@ namespace Dune {
&& &&
this->load_from_file( ) ) // loads data only if sequential program, in parallel only consistency check this->load_from_file( ) ) // loads data only if sequential program, in parallel only consistency check
{ {
std::cout << "Reading existing Y-field." if(my_rank==0)
<< std::endl; std::cout << "Reading existing Y-field."
<< std::endl;
} }
else else
{ {
std::cout << "Generating new data ..." if(my_rank==0)
<< std::endl; std::cout << "Generating new data ..."
<< std::endl;
generate_new = 1; generate_new = 1;
} }
...@@ -818,9 +824,10 @@ namespace Dune { ...@@ -818,9 +824,10 @@ namespace Dune {
std::ofstream filestr( filename.c_str(), std::ios::out ); std::ofstream filestr( filename.c_str(), std::ios::out );
if( filestr.is_open() ) { if( filestr.is_open() ) {
std::cout << "Saving Y-Field properties to " if(my_rank==0)
<< filename std::cout << "Saving Y-Field properties to "
<< std::endl; << filename
<< std::endl;
// DO NOT insert a blank into "dim=" // DO NOT insert a blank into "dim="
filestr << "dim= " << dim << std::endl; filestr << "dim= " << dim << std::endl;
......
get_property(dorie-rfg_EXEC TARGET dorie-rfg PROPERTY LOCATION)
configure_file(pf_from_file.py.in ${CMAKE_CURRENT_SOURCE_DIR}/pf_from_file.py) configure_file(pf_from_file.py.in ${CMAKE_CURRENT_SOURCE_DIR}/pf_from_file.py)
#!/usr/bin/env python #!/usr/bin/env python
import os import os
import sys
import argparse import argparse
import warnings import warnings
import subprocess import subprocess
import multiprocessing
from dorie.parfield import configparser, pfgerror from dorie.parfield import configparser, pfgerror
from dorie.parfield.converter import ImageConverter, CSVConverter, H5Converter, FFTH5Converter from dorie.parfield.converter import ImageConverter, CSVConverter, H5Converter, FFTH5Converter
...@@ -13,16 +15,24 @@ Script invoking the image to h5 converter on a file given via command line. ...@@ -13,16 +15,24 @@ Script invoking the image to h5 converter on a file given via command line.
""" """
# paths set by CMake # paths set by CMake
RFG_EXEC = "@dorie-rfg_EXEC@" DORIEDIR = "@CMAKE_BINARY_DIR@"
MPIRUN = "@MPIEXEC@ @MPIEXEC_NUMPROC_FLAG@ {} @MPIEXEC_PREFLAG@ {} @MPIEXEC_POSTFLAGS@" MPIEXEC = "@MPIEXEC@"
MPIEXEC_NUMPROC_FLAG = "@MPIEXEC_NUMPROC_FLAG@"
MPIEXEC_PREFLAG = "@MPIEXEC_PREFLAG@"
MPIEXEC_POSTFLAGS = "@MPIEXEC_POSTFLAGS@"
#
RFG_EXEC = os.path.join(DORIEDIR, "dune/dorie-rfg/dorie-rfg")
MPIRUN = lambda nproc, exe, *args: [k for k in [MPIEXEC,MPIEXEC_NUMPROC_FLAG,str(nproc),MPIEXEC_PREFLAG,str(exe),MPIEXEC_POSTFLAGS] + list(args) if k]
if __name__ == "__main__": if __name__ == "__main__":
try: # catch all exceptions we we can output an error message try: # catch all exceptions we we can output an error message
with warnings.catch_warnings(record=True) as warn: # catch all warnings so we can count them with warnings.catch_warnings(record=True) as warn: # catch all warnings so we can count them
# PARSE COMMAND LINE # PARSE COMMAND LINE
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('-p','--param',help='The configuration file holding all parameterization information',required=True) parser.add_argument('param',help='The configuration file holding all parameterization information')
parser.add_argument('--parallel',help='Number of processes to run on',required=False) parser.add_argument('-p','--parallel', metavar='N', nargs='?', default=1, const=multiprocessing.cpu_count(), type=int, required=False,
help="Run in parallel on N processes. If N is not specified, run on all available CPU threads.")
parser.add_argument('--debug',help='Display warnings',action='store_true',required=False) parser.add_argument('--debug',help='Display warnings',action='store_true',required=False)
args = vars(parser.parse_args()) args = vars(parser.parse_args())
...@@ -42,12 +52,13 @@ if __name__ == "__main__": ...@@ -42,12 +52,13 @@ if __name__ == "__main__":
CSVConverter(args["param"]) CSVConverter(args["param"])
elif params["generator"] == "fft": elif params["generator"] == "fft":
try: try:
if args["parallel"]: if args["parallel"] == 1:
subprocess.check_call(MPIRUN.format(int(args["parallel"]), RFG_EXEC), args["param"])
else:
subprocess.check_call([RFG_EXEC,args["param"]]) subprocess.check_call([RFG_EXEC,args["param"]])
else:
subprocess.check_call(MPIRUN(args["parallel"], RFG_EXEC, args["param"]))
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
raise RuntimeError("FFT Field generator failed") print("FFT Field generator failed")
sys.exit(1)
out_path = cp.get("generator.fft","outputPath") out_path = cp.get("generator.fft","outputPath")
FFTH5Converter(args["param"], out_path + "/YField.h5") FFTH5Converter(args["param"], out_path + "/YField.h5")
elif params["generator"] == "hdf5": elif params["generator"] == "hdf5":
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment