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
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'
# 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"""
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)
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
##########################################################################
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',
'-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='?',
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))