X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=bin%2Fmg-tetra_hpc.py;fp=bin%2Fmg-tetra_hpc.py;h=b244d131f51a2d5f2104a2c95441d8761c2c035c;hb=f2dd979943d3ec1026c73a9927f2b429002de4fa;hp=30bb1e5b2f3b2d79976c4189858289f1af917961;hpb=e4fe9f86f4133e4010eecc123184cd1939615406;p=plugins%2Fghs3dprlplugin.git diff --git a/bin/mg-tetra_hpc.py b/bin/mg-tetra_hpc.py old mode 100644 new mode 100755 index 30bb1e5..b244d13 --- a/bin/mg-tetra_hpc.py +++ b/bin/mg-tetra_hpc.py @@ -25,9 +25,18 @@ run mg_tetra_hpc.exe or mg_tetra_hpc_mpi.exe example linux usage: -- simple run: - ./mg-tetra_hpc.py --help - ./mg-tetra_hpc.py -n 3 --in /tmp/GHS3DPRL.mesh --out /tmp/GHS3DPRL_out.mesh --gradation 1.05 --min_size 0.001 --max_size 1.1 --multithread no > /tmp/tetrahpc.log +| ./mg-tetra_hpc.py --help +| ./mg-tetra_hpc.py -n 3 --in /tmp/GHS3DPRL.mesh --out /tmp/GHS3DPRL_out.mesh --gradation 1.05 --min_size 0.001 --max_size 1.1 --multithread no > /tmp/tetrahpc.log + +note: +| openmpi environment have to be set, may be as user choice +| example for centos7/redhat7: +| module load mpi/openmpi-x86_64 +| which mpicc +| example without module load (old): +| # may be prefer set before salome launch +| OPENMPI_INSTALL_DIR = ".../openmpi-1.8.4/FROM_nothing/bin" +| export PATH=${OPENMPI_INSTALL_DIR}:${PATH} """ import os @@ -41,14 +50,14 @@ import pprint as PP # pretty print import subprocess as SP # Popen -verbose = False +debug = False -OK = "ok" +OK = "OK" KO = "KO" OKSYS = 0 # for linux KOSYS = 1 # for linux -NB_PROCS = MP.cpu_count() # current cpu number of proc +NB_PROCS = MP.cpu_count() # current cpu number of proc NAME_OS = platform.system() # 'Linux' or 'Windows' @@ -56,8 +65,42 @@ NAME_OS = platform.system() # 'Linux' or 'Windows' # utilities ########################################################################## + +########################################################################## +def log_debug(msg): + if args.verbose: + log_print("DEBUG", msg) + +def log_info(msg): + log_print("INFO", msg) + +def log_warning(msg): + log_print("WARNING", msg) + +def log_error(msg): + log_print("ERROR", msg) + +def log_print(level, msg): + print("%-7s : %s" % (level, indent(msg))) + +def indent(msg, ind='\n | '): + if '\n' in msg: + return msg.replace('\n', ind) + else: + return msg + +def test_log(msg): + log_debug(msg) + log_info(msg) + log_warning(msg) + log_error(msg) + + +########################################################################## def okToSys(aResult, verbose=False): - """to get windows or linux result of script""" + """ + to get windows or linux result of script + """ def extendList(alist): """utility extend list of lists of string results with ok or KO""" @@ -75,25 +118,29 @@ def okToSys(aResult, verbose=False): resList = extendList(aResult) if resList == []: - if verbose: print("WARNING: result no clear: []") + log_error("result no clear with empty list of OK/KO") return KOSYS rr = OK for ri in resList: - if ri[0:2] != OK: - if verbose: print(ri) + if ri[0:2].upper() != OK: + log_debug("KO in '%s'" % ri) rr = KO - if verbose: print(("INFO: result: %s" % rr)) + log_info("result is %s" % rr) if rr == OK: return OKSYS else: return KOSYS + ########################################################################## def getDirAndName(datafile): - path, namefile = os.path.split(os.path.realpath(datafile)) + """ + returns (directory_realpath, os.getcwd(), name_file) + """ rootpath = os.getcwd() + path, namefile = os.path.split(os.path.realpath(datafile)) return (path, rootpath, namefile) @@ -112,74 +159,89 @@ class ArgRange(object): def __repr__(self): return "[%s,%s]" % (self.start, self.end) - ########################################################################## def exec_command(cmd, verbose=False): """Exec ONE command with popen""" time.sleep(3) # wait for (MPI) flush files - if verbose: print(("launch process:\n %s" % cmd)) + log_debug("launch subprocess:\n%s" % cmd) try: - pipe = SP.Popen(cmd, shell=True, stdout=SP.PIPE, stderr=SP.PIPE) + pipe = SP.Popen(cmd, shell=True, stdout=SP.PIPE, stderr=SP.STDOUT) except Exception as e: - result = KO + " ERROR: we have a problem popen on: %s" % PP.pformat(cmd) + log_error("Problem launching subprocess:\n%s" % cmd) + result = "KO Problem launching subprocess" return result (out, error) = pipe.communicate() pipe.wait() - print(out) - print(error) - - result = OK + " INFO: seems final ok for: %s" % PP.pformat(cmd) + log_info("subprocess log:\n%s" % out.decode("utf-8")) time.sleep(3) # wait for (MPI) flush files - return result + if pipe.returncode == 0: # return code of last command + result = "OK subprocess result (of last command)" + log_debug(result) + else: + log_error("KO subprocess result (of last command): %s" % pipe.returncode) + result = "KO for:\n%s" % cmd + + if error is not None: + log_error("KO subprocess stderr:\n%s" % error.decode("utf-8")) + result = "KO for:\n%s" % cmd + return result ########################################################################## def force_DISTENE_LICENSE_FILE(): """ conditionaly overriding/set environ variable DISTENE_LICENSE_FILE, from/if existing FORCE_DISTENE_LICENSE_FILE environ variable - (for test new version MeshGems etc...) - """ - """ - #example: - DISTENE_LICENSE_FILE=Use global envvar: DLIM8VAR - DLIM8VAR=dlim8 1:1:29030@132.166.151.49/84c419b8::87af196ab2a936ab31363624539bff8096fbe1f3c83028c8f6b399b0a904ef85 - overriden by - FORCE_DISTENE_LICENSE_FILE=/export/home/wambeke/essai_meshgems2.3/dlim8.key + (useful when test new version MeshGems with local DISTENE_LICENSE_FILE) + + example: + DISTENE_LICENSE_FILE=Use global envvar: DLIM8VAR + DLIM8VAR=dlim8 1:1:29030@132.166.151.49/84c419b8::87af... etc. + overriden by + FORCE_DISTENE_LICENSE_FILE=/home/$USER/licence_meshgems2.3/dlim8.key """ force = os.getenv("FORCE_DISTENE_LICENSE_FILE") if force != None: os.environ["DISTENE_LICENSE_FILE"] = force os.environ["DLIM8VAR"] = "NOTHING" - """ - #export PATH=/export/home/prerequisites_SALOME_780_LAURENT/openmpi-1.8.4/FROM_nothing/bin:$PATH - #do not work prefer set before salome launch - OPENMPI_INSTALL_DIR = "/export/home/prerequisites_SALOME_780_LAURENT/openmpi-1.8.4/FROM_nothing/bin" - sys.path.insert(0, OPENMPI_INSTALL_DIR) - #INSTALL_DIR = /export/home/prerequisites_SALOME_780_LAURENT/openmpi-1.8.4/FROM_nothing - for i in sys.path[0:10]: print "PATH",i - """ - - ########################################################################## def launchMultithread(args): - if verbose: print(("INFO: launchMultithread for %s" % NAME_OS)) + log_info("launch multithread for %s" % NAME_OS) if NAME_OS == 'Linux': # --out is ONE file: basename_tetra_hpc.mesh - outputMulti = os.path.splitext(args.inputFile)[0] + "_tetra_hpc.mesh" # only one file if Multithread - outputs = os.path.splitext(args.outputFiles)[0] - outputMultiAsMpi = os.path.splitext(args.outputFiles)[0] + ".000001.mesh" # create one output file named as only one from mpi - cmd = "mg-tetra_hpc.exe --max_number_of_threads %i --in %s --gradation %s --max_size %s --min_size %s; cp %s %s; ls -alt %s*; " % \ - (args.number, args.inputFile, args.gradation, args.max_size, args.min_size, outputMulti, outputMultiAsMpi, outputs) + args.outputs = os.path.splitext(args.outputFiles)[0] # use args.__dict__ + args.currentdir = os.path.splitext(args.outputFiles)[0] # use args.__dict__ + + # args.outputMulti = os.path.splitext(args.inputFile)[0] + "_tetra_hpc.mesh" # only one file if mg-tetra_hpc.exe multithread + args.outputMultiAsMpi = os.path.splitext(args.outputFiles)[0] + ".000001.mesh" # create one output file named as mpi (as only one process) + + cmd = """ +set -x + +# mpirun mg-tetra_hpc_mpi.exe + rm %(outputs)s* # clean previous case + mg-tetra_hpc.exe \ +--max_number_of_threads %(number)s \ +--in %(inputFile)s \ +--out %(outputFiles)s \ +--gradation %(gradation)s \ +--max_size %(max_size)s \ +--min_size %(min_size)s + # create force symbolic link as no duplicate multithread output file as MPI output file (as only one process) + ln -sf %(outputFiles)s %(outputMultiAsMpi)s +""" % args.__dict__ + # args.number, args.inputFile, args.gradation, args.max_size, args.min_size, outputMulti, outputMultiAsMpi, outputs else: - return KO + " ERROR: unknown operating system: %s" % NAME_OS + msg = "unknown operating system: %s" % NAME_OS + log_error(msg) + return KO + msg result = exec_command(cmd, verbose=True) return result @@ -188,48 +250,77 @@ def launchMultithread(args): ########################################################################## def launchMpi(args): - if verbose: print(("INFO: launchMpi for %s" % NAME_OS)) + log_info("launch MPI for %s" % NAME_OS) if NAME_OS == 'Linux': - cmd = "" - - """ compile libmeshgems_mpi.so: no needs - COMPILDIR=os.getenv("MESHGEMSHOME") + "/stubs" - TARGETDIR=os.getenv("MESHGEMSHOME") + "/lib/Linux_64" - cmd = "which mg-tetra_hpc_mpi.exe; which mpicc; rm /tmp/GHS3DPRL_out*; " - cmd += "cd %s; mpicc meshgems_mpi.c -DMESHGEMS_LINUX_BUILD -I../include -shared -fPIC -o %s/libmeshgems_mpi.so; " % (COMPILDIR, TARGETDIR) - """ - - outputs = os.path.splitext(args.outputFiles)[0] - cmd += "mpirun -n %i mg-tetra_hpc_mpi.exe --in %s --out %s --gradation %s --max_size %s --min_size %s; ls -alt %s*; " % \ - (args.number, args.inputFile, args.outputFiles, args.gradation, args.max_size, args.min_size, outputs) + args.outputs = os.path.splitext(args.outputFiles)[0] # use args.__dict__ + args.currentdir = os.path.splitext(args.outputFiles)[0] # use args.__dict__ + cmd = """ +set -x + + which mg-tetra_hpc_mpi.exe + if [ $? -ne 0 ] # exit if not found + then + exit 1 + fi + + # needed as openmpi environment have to be set, may be as user or root (for cluster) choice + which mpirun || module load mpi/openmpi-x86_64 # example for centos7/redhat7 + +# compile libmeshgems_mpi.so if needed (i.e. if empty stubs) + mg-tetra_hpc_mpi.exe --help &> /tmp/help_mg-tetra_hpc_mpi_${USER}.txt + if [ $? -ne 0 ] # if empty MPI stubs library, have to compile libmeshgems_mpi.so + then + # SALOME env var MESHGEMSHOME is something like .../INSTALL/MeshGems + MESHGEMSHOME=${MESHGEMSHOME:-/tmp/MeshGems} # default value if unset + COMPILDIR=$MESHGEMSHOME/stubs + TARGETDIR=$MESHGEMSHOME/lib/Linux_64 + cd ${COMPILDIR} + mpicc meshgems_mpi.c -DMESHGEMS_LINUX_BUILD -I../include -shared -fPIC -o ${TARGETDIR}/libmeshgems_mpi.so + fi + +# mpirun mg-tetra_hpc_mpi.exe + rm %(outputs)s* # clean previous case + cd %(outputDir)s + mpirun --n %(number)s mg-tetra_hpc_mpi.exe \ +--in %(inputFile)s \ +--out %(outputFiles)s \ +--gradation %(gradation)s \ +--max_size %(max_size)s \ +--min_size %(min_size)s + # ls -alt %(outputs)s* +""" % args.__dict__ + # args.number, args.inputFile, args.outputFiles, args.gradation, args.max_size, args.min_size, outputs else: - return KO + " ERROR: unknown operating system: %s" % NAME_OS + msg = "unknown operating system: %s" % NAME_OS + log_error(msg) + return KO + msg result = exec_command(cmd, verbose=True) return result ########################################################################## -# main -########################################################################## - -if __name__ == '__main__': - parser = AP.ArgumentParser(description='launch tetra_hpc.exe or tetra_hpc_mpi.exe mesh computation', argument_default=None) - # ./mg-tetra_hpc.py -n 3 --in=/tmp/GHS3DPRL.mesh --out=/tmp/GHS3DPRL_out.mesh --gradation=1.05 --min_size=0.001 --max_size=1.1 --multithread no > /tmp/tetrahpc.log +def getParser(): + parser = AP.ArgumentParser(description='launch tetra_hpc.exe or tetra_hpc_mpi.exe for mesh computation', argument_default=None) parser.add_argument( '-v', '--verbose', help='set verbose, for debug', action='store_true', ) + parser.add_argument( + '-t', '--test', + help='make test, for script debug', + action='store_true', + ) parser.add_argument( '-n', '--number', help='if multithread: number of threads, else distributed: number of processes MPI', choices=[ArgRange(1, 999999)], type=int, metavar='integer >= 0', - default=1, + default=NB_PROCS # as automatic, no more local number of cpu (multithread or MPI) ) parser.add_argument( '-m', '--multithread', @@ -265,15 +356,18 @@ if __name__ == '__main__': '-i', '--inputFile', help='input file name', # nargs='?', - metavar='.../inputFile.mesh' + metavar='.../inputFile.mesh', + default='/tmp/GHS3DPRL.mesh' ) parser.add_argument( '-o', '--outputFiles', help='output basename file(s) name', # nargs='?', - metavar='.../outputFile.mesh' + metavar='.../outputFile.mesh', + default='/tmp/GHS3DPRL_out.mesh' ) """ + # example parser.add_argument( '-x', '--xoneargument', nargs='?', @@ -283,39 +377,72 @@ if __name__ == '__main__': default='0' ) """ + # help(parser) + return parser +########################################################################## +# main +########################################################################## +if __name__ == '__main__': """ - args is Namespace, may use it as global to store - parameters, data, used arrays and results and other... + args is 'Namespace' class, may use it as global to store + parameters, data, used arrays and results, and other... """ + parser = getParser() args = parser.parse_args() verbose = args.verbose - if verbose: print(("INFO: args:\n%s" % PP.pformat(args.__dict__))) + log_debug("%s arguments are:\n%s" % (__file__, PP.pformat(args.__dict__))) if len(sys.argv) == 1: # no args as --help parser.print_help() sys.exit(KOSYS) + if args.test is True: + test_log('one line message') + test_log('first line\nsecond line') + sys.exit(OKSYS) + if args.inputFile == None: - print(("\nERROR: Nothing to do: no input files\n\n%s\n" % PP.pformat(args))) - parser.print_help() + log_error("no --inputFile defined in arguments:\n%s" % PP.pformat(args.__dict__)) + log_info("arguments should be:\n%s" % parser.format_help()) + # parser.print_help() + sys.exit(KOSYS) + + if not os.path.isfile(args.inputFile): + log_error("inexisting input file:\n%s" % os.path.realpath(args.inputFile)) sys.exit(KOSYS) if args.outputFiles == None: tmp, _ = os.path.splitext(args.inputFile) args.outputFiles = tmp + "_out.mesh" - print(("\nWARNING: Default ouput files: %s" % args.outputFiles)) - - force_DISTENE_LICENSE_FILE() - - print(("INFO: mg-tetra_hpc.py assume licence file set:\n DLIM8VAR=%s\n DISTENE_LICENSE_FILE=%s" % \ - (os.getenv("DLIM8VAR"), os.getenv("DISTENE_LICENSE_FILE")))) + + tmp, _ = os.path.split(args.outputFiles) + args.outputDir = os.path.realpath(tmp) + + log_info("output directory:\n%s" % args.outputDir) + + force_DISTENE_LICENSE_FILE() # if FORCE_DISTENE_LICENSE_FILE environ variable exists, manually set by user + + DLIM8VAR = os.getenv("DLIM8VAR") + DISTENE_LICENSE_FILE = os.getenv("DISTENE_LICENSE_FILE") + msg = """\ +%s assume distene licence file set: +DLIM8VAR=%s +DISTENE_LICENSE_FILE=%s +""" % (__file__, DLIM8VAR, DISTENE_LICENSE_FILE) + + if None in [DLIM8VAR, DISTENE_LICENSE_FILE]: + log_error(msg + "Abandon.") + sys.exit(KOSYS) + else: + log_info(msg) if args.multithread == "yes": result = launchMultithread(args) else: result = launchMpi(args) + sys.exit(okToSys(result, verbose=True))