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

finished python wrappers for parallel execution

parent d0045300
#!/usr/bin/env python
import os
import sys
import shutil
import argparse
import warnings
......@@ -20,6 +21,7 @@ MPIEXEC_PREFLAG = "@MPIEXEC_PREFLAG@"
MPIEXEC_POSTFLAGS = "@MPIEXEC_POSTFLAGS@"
#
# set some paths
DORIE_EXECUTABLE = os.path.join(DORIEDIR, "dune/dorie/dorie")
PARAMETERDIR = os.path.join(DORIEDIR, "doc/default_files")
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
def run(args):
if not os.path.isfile(args["config"]):
raise IOError("Configuration file {} not found".format(args["config"]))
if args["parallel"] == 1:
subprocess.call([DORIE_EXECUTABLE, args["config"]])
else:
print([MPIRUN(args["parallel"],DORIE_EXECUTABLE) + [args["config"]]])
subprocess.call(MPIRUN(args["parallel"],DORIE_EXECUTABLE,args["config"]))
try:
if args["parallel"] == 1:
subprocess.check_call([DORIE_EXECUTABLE, args["config"]])
else:
subprocess.check_call(MPIRUN(args["parallel"],DORIE_EXECUTABLE,args["config"]))
except subprocess.CalledProcessError:
print("Error while running DORiE")
sys.exit(1)
def create(args):
for f in ("config.ini", "parfield.ini", "2d_infiltr.bcdat", "3d_infiltr.bcdat"):
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"]
if not override:
continue
......@@ -48,9 +53,9 @@ def pfg(args):
if not os.path.isfile(args["config"]):
raise IOError("Configuration file {} not found".format(args["config"]))
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:
raise NotImplementedError
subprocess.call([DORIE_PYTHON, "pf_from_file.py", args["config"], "--parallel", str(args["parallel"])])
def plot(args):
if not os.path.isfile(args["vtk"]):
......@@ -60,10 +65,9 @@ def plot(args):
else:
subprocess.call([DORIE_PYTHON, "plot_vtk.py", "-f", args["vtk"]])
if __name__ == "__main__":
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
# PARSE COMMAND LINE
if __name__ == "__main__": # parse command line and call command handler
try:
with warnings.catch_warnings(record=True) as warn:
parser = argparse.ArgumentParser(description="DORiE command line interface",
epilog="For more information check our online documentation:\n"
"http://dorie-docs.bitballoon.com (password: 'richards')"
......@@ -72,22 +76,23 @@ if __name__ == "__main__":
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('--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.")
parser_run.set_defaults(func=run)
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_pfg = subparsers.add_parser('pfg', help="Start parameter field generator.")
parser_pfg.add_argument('config',
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.")
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.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.set_defaults(func=plot)
......
......@@ -47,6 +47,11 @@ int main(int argc, char** argv)
DUNE_THROW(Dune::IOError,"No parameter file specified!");
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
Dune::ParameterTree inifile;
Dune::ParameterTreeParser ptreeparser;
......
......@@ -335,7 +335,7 @@ namespace Dune {
nNearZero++;
}
if( fielddata.showEV ){
if (fielddata.showEV && my_rank == 0){
std::cout << "Properties of Syy: " << std::endl;
std::cout << alloc_local << " eigenvalues" << std::endl;
std::cout << nPositive << " eigenvalues > 1E-6" << std::endl;
......@@ -374,14 +374,16 @@ namespace Dune {
||
!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();
}
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 ){
std::cout << "New field will be generated due to changed geostatistical data." << std::endl;
} else {
......@@ -660,16 +662,18 @@ namespace Dune {
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;
return false;
}
std::cout << "Found suitable Y-Field characteristics! Load the field from YField.dat"
<< std::endl;
if(my_rank==0)
std::cout << "Found suitable Y-Field characteristics! Load the field from YField.dat"
<< std::endl;
if(comm_size==1){
Vector<UINT> local_count(dim,0);
Vector<UINT> local_offset(dim,0);
......@@ -725,13 +729,15 @@ namespace Dune {
&&
this->load_from_file( ) ) // loads data only if sequential program, in parallel only consistency check
{
std::cout << "Reading existing Y-field."
<< std::endl;
if(my_rank==0)
std::cout << "Reading existing Y-field."
<< std::endl;
}
else
{
std::cout << "Generating new data ..."
<< std::endl;
if(my_rank==0)
std::cout << "Generating new data ..."
<< std::endl;
generate_new = 1;
}
......@@ -818,9 +824,10 @@ namespace Dune {
std::ofstream filestr( filename.c_str(), std::ios::out );
if( filestr.is_open() ) {
std::cout << "Saving Y-Field properties to "
<< filename
<< std::endl;
if(my_rank==0)
std::cout << "Saving Y-Field properties to "
<< filename
<< std::endl;
// DO NOT insert a blank into "dim="
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)
#!/usr/bin/env python
import os
import sys
import argparse
import warnings
import subprocess
import multiprocessing
from dorie.parfield import configparser, pfgerror
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.
"""
# paths set by CMake
RFG_EXEC = "@dorie-rfg_EXEC@"
MPIRUN = "@MPIEXEC@ @MPIEXEC_NUMPROC_FLAG@ {} @MPIEXEC_PREFLAG@ {} @MPIEXEC_POSTFLAGS@"
DORIEDIR = "@CMAKE_BINARY_DIR@"
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__":
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
# PARSE COMMAND LINE
parser = argparse.ArgumentParser()
parser.add_argument('-p','--param',help='The configuration file holding all parameterization information',required=True)
parser.add_argument('--parallel',help='Number of processes to run on',required=False)
parser.add_argument('param',help='The configuration file holding all parameterization information')
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)
args = vars(parser.parse_args())
......@@ -42,12 +52,13 @@ if __name__ == "__main__":
CSVConverter(args["param"])
elif params["generator"] == "fft":
try:
if args["parallel"]:
subprocess.check_call(MPIRUN.format(int(args["parallel"]), RFG_EXEC), args["param"])
else:
if args["parallel"] == 1:
subprocess.check_call([RFG_EXEC,args["param"]])
else:
subprocess.check_call(MPIRUN(args["parallel"], RFG_EXEC, args["param"]))
except subprocess.CalledProcessError:
raise RuntimeError("FFT Field generator failed")
print("FFT Field generator failed")
sys.exit(1)
out_path = cp.get("generator.fft","outputPath")
FFTH5Converter(args["param"], out_path + "/YField.h5")
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