Salome HOME
Porting to Python 3
[plugins/ghs3dprlplugin.git] / bin / mg-tetra_hpc.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 # %% LICENSE_SALOME_CEA_BEGIN
5 # Copyright (C) 2008-2016  CEA/DEN
6 #
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2.1 of the License, or (at your option) any later version.
11 #
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 # Lesser General Public License for more details.
16 #
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this library; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #
21 # See http://www.salome-platform.org or email : webmaster.salome@opencascade.com
22 # %% LICENSE_END
23
24
25 """
26 run mg_tetra_hpc.exe or mg_tetra_hpc_mpi.exe
27
28 example linux usage:
29 - simple run:
30   ./mg-tetra_hpc.py --help
31   ./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
32 """
33
34 import os
35 import platform
36 import sys
37 import time
38
39 import argparse as AP
40 import multiprocessing as MP  # cpu_count
41 import pprint as PP  # pretty print
42 import subprocess as SP  # Popen
43
44
45 verbose = False
46
47 OK = "ok"
48 KO = "KO"
49 OKSYS = 0  # for linux
50 KOSYS = 1  # for linux
51
52 NB_PROCS = MP.cpu_count()  # current cpu number of proc
53 NAME_OS = platform.system()  # 'Linux' or 'Windows'
54
55
56 ##########################################################################
57 # utilities
58 ##########################################################################
59
60 def okToSys(aResult, verbose=False):
61   """to get windows or linux result of script"""
62
63   def extendList(alist):
64     """utility extend list of lists of string results with ok or KO"""
65     # bad: list(itertools.chain.from_list(alist)) iterate on str
66     res = []
67     if type(alist) != list:
68       return [alist]
69     else:
70       for i in alist:
71         if type(i) == str:
72            res.append(i)
73         else:
74            res.extend(extendList(i))
75     return res
76
77   resList = extendList(aResult)
78   if resList == []:
79     if verbose: print("WARNING: result no clear: []")
80     return KOSYS
81
82   rr = OK
83   for ri in resList:
84     if ri[0:2] != OK:
85       if verbose: print(ri)
86       rr = KO
87
88   if verbose: print(("INFO: result: %s" % rr))
89   if rr == OK:
90     return OKSYS
91   else:
92     return KOSYS
93
94 ##########################################################################
95 def getDirAndName(datafile):
96   path, namefile = os.path.split(os.path.realpath(datafile))
97   rootpath = os.getcwd()
98   return (path, rootpath, namefile)
99
100
101 ##########################################################################
102 class ArgRange(object):
103   """
104   ArgumentParser utility for range float or in in arguments
105   """
106   def __init__(self, start, end):
107     self.start = start
108     self.end = end
109
110   def __eq__(self, other):
111     return self.start <= other <= self.end
112
113   def __repr__(self):
114     return "[%s,%s]" % (self.start, self.end)
115
116
117 ##########################################################################
118 def exec_command(cmd, verbose=False):
119   """Exec ONE command with popen"""
120
121   time.sleep(3)  # wait for (MPI) flush files
122   if verbose: print(("launch process:\n  %s" % cmd))
123   try:
124     pipe = SP.Popen(cmd, shell=True, stdout=SP.PIPE, stderr=SP.PIPE)
125   except Exception as e:
126     result = KO + " ERROR: we have a problem popen on: %s" % PP.pformat(cmd)
127     return result
128
129   (out, error) = pipe.communicate()
130   pipe.wait()
131
132   print(out)
133   print(error)
134
135   result = OK + " INFO: seems final ok for: %s" % PP.pformat(cmd)
136   time.sleep(3)  # wait for (MPI) flush files
137   return result
138
139
140
141 ##########################################################################
142 def force_DISTENE_LICENSE_FILE():
143   """
144   conditionaly overriding/set environ variable DISTENE_LICENSE_FILE,
145   from/if existing FORCE_DISTENE_LICENSE_FILE environ variable
146   (for test new version MeshGems etc...)
147   """
148   """
149   #example:
150   DISTENE_LICENSE_FILE=Use global envvar: DLIM8VAR
151   DLIM8VAR=dlim8 1:1:29030@132.166.151.49/84c419b8::87af196ab2a936ab31363624539bff8096fbe1f3c83028c8f6b399b0a904ef85
152   overriden by
153   FORCE_DISTENE_LICENSE_FILE=/export/home/wambeke/essai_meshgems2.3/dlim8.key
154   """
155   force = os.getenv("FORCE_DISTENE_LICENSE_FILE")
156   if force != None:
157     os.environ["DISTENE_LICENSE_FILE"] = force
158     os.environ["DLIM8VAR"] = "NOTHING"
159     """
160     #export PATH=/export/home/prerequisites_SALOME_780_LAURENT/openmpi-1.8.4/FROM_nothing/bin:$PATH
161     #do not work prefer set before salome launch
162     OPENMPI_INSTALL_DIR = "/export/home/prerequisites_SALOME_780_LAURENT/openmpi-1.8.4/FROM_nothing/bin"
163     sys.path.insert(0, OPENMPI_INSTALL_DIR)
164     #INSTALL_DIR = /export/home/prerequisites_SALOME_780_LAURENT/openmpi-1.8.4/FROM_nothing
165     for i in sys.path[0:10]: print "PATH",i
166     """
167
168
169
170
171 ##########################################################################
172 def launchMultithread(args):
173   if verbose: print(("INFO: launchMultithread for %s" % NAME_OS))
174
175   if NAME_OS == 'Linux':
176     # --out is ONE file: basename_tetra_hpc.mesh
177     outputMulti = os.path.splitext(args.inputFile)[0] + "_tetra_hpc.mesh"  # only one file if Multithread
178     outputs = os.path.splitext(args.outputFiles)[0]
179     outputMultiAsMpi = os.path.splitext(args.outputFiles)[0] + ".000001.mesh"  # create one output file named as only one from mpi
180     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*; " % \
181           (args.number, args.inputFile, args.gradation, args.max_size, args.min_size, outputMulti, outputMultiAsMpi, outputs)
182   else:
183     return KO + " ERROR: unknown operating system: %s" % NAME_OS
184
185   result = exec_command(cmd, verbose=True)
186   return result
187
188
189
190 ##########################################################################
191 def launchMpi(args):
192   if verbose: print(("INFO: launchMpi for %s" % NAME_OS))
193
194   if NAME_OS == 'Linux':
195     cmd = ""
196
197     """ compile libmeshgems_mpi.so: no needs
198     COMPILDIR=os.getenv("MESHGEMSHOME") + "/stubs"
199     TARGETDIR=os.getenv("MESHGEMSHOME") + "/lib/Linux_64"
200     cmd  = "which mg-tetra_hpc_mpi.exe; which mpicc; rm /tmp/GHS3DPRL_out*; "
201     cmd += "cd %s; mpicc meshgems_mpi.c -DMESHGEMS_LINUX_BUILD -I../include -shared -fPIC -o %s/libmeshgems_mpi.so; " % (COMPILDIR, TARGETDIR)
202     """
203
204     outputs = os.path.splitext(args.outputFiles)[0]
205     cmd += "mpirun -n %i mg-tetra_hpc_mpi.exe --in %s --out %s --gradation %s --max_size %s --min_size %s; ls -alt %s*; " % \
206           (args.number, args.inputFile, args.outputFiles, args.gradation, args.max_size, args.min_size, outputs)
207   else:
208     return KO + " ERROR: unknown operating system: %s" % NAME_OS
209
210   result = exec_command(cmd, verbose=True)
211   return result
212
213
214 ##########################################################################
215 # main
216 ##########################################################################
217
218 if __name__ == '__main__':
219   parser = AP.ArgumentParser(description='launch tetra_hpc.exe or tetra_hpc_mpi.exe mesh computation', argument_default=None)
220   # ./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
221
222   parser.add_argument(
223     '-v', '--verbose',
224     help='set verbose, for debug',
225     action='store_true',
226   )
227   parser.add_argument(
228     '-n', '--number',
229     help='if multithread: number of threads, else distributed: number of processes MPI',
230     choices=[ArgRange(1, 999999)],
231     type=int,
232     metavar='integer >= 0',
233     default=1,
234   )
235   parser.add_argument(
236     '-m', '--multithread',
237     help='launch tetra_hpc multithread instead tetra_hpc distributed (MPI)',
238     choices=["no", "yes"],
239     default='no',
240   )
241   parser.add_argument(
242     '-g', '--gradation',
243     help='size ratio adjacent cell, default 0 is 1.05',
244     type=float,
245     choices=[ArgRange(0.0, 3.0)],
246     metavar='float in [0.,3]',
247     default='0'
248   )
249   parser.add_argument(
250     '-si', '--min_size',
251     help='min size cell, default 0 is no constraint',
252     type=float,
253     choices=[ArgRange(0.0, 9e99)],
254     metavar='float >= 0',
255     default='0'
256   )
257   parser.add_argument(
258     '-sa', '--max_size',
259     help='max size cell, default 0 is no constraint',
260     type=float,
261     choices=[ArgRange(0.0, 9e99)],
262     metavar='float >= 0',
263     default='0'
264   )
265   parser.add_argument(
266     '-i', '--inputFile',
267     help='input file name',
268     # nargs='?',
269     metavar='.../inputFile.mesh'
270   )
271   parser.add_argument(
272     '-o', '--outputFiles',
273     help='output basename file(s) name',
274     # nargs='?',
275     metavar='.../outputFile.mesh'
276   )
277   """
278   parser.add_argument(
279     '-x', '--xoneargument',
280     nargs='?',
281     metavar='0|1',
282     choices=['0', '1'],
283     help='one argument, for example',
284     default='0'
285   )
286   """
287
288
289   """
290   args is Namespace, may use it as global to store
291   parameters, data, used arrays and results and other...
292   """
293   args = parser.parse_args()
294
295   verbose = args.verbose
296   if verbose: print(("INFO: args:\n%s" % PP.pformat(args.__dict__)))
297
298   if len(sys.argv) == 1:  # no args as --help
299     parser.print_help()
300     sys.exit(KOSYS)
301
302   if args.inputFile == None:
303     print(("\nERROR: Nothing to do: no input files\n\n%s\n" % PP.pformat(args)))
304     parser.print_help()
305     sys.exit(KOSYS)
306
307   if args.outputFiles == None:
308     tmp, _ = os.path.splitext(args.inputFile)
309     args.outputFiles = tmp + "_out.mesh"
310     print(("\nWARNING: Default ouput files: %s" % args.outputFiles))
311
312   force_DISTENE_LICENSE_FILE()
313
314   print(("INFO: mg-tetra_hpc.py assume licence file set:\n  DLIM8VAR=%s\n  DISTENE_LICENSE_FILE=%s" % \
315        (os.getenv("DLIM8VAR"), os.getenv("DISTENE_LICENSE_FILE"))))
316
317   if args.multithread == "yes":
318     result = launchMultithread(args)
319   else:
320     result = launchMpi(args)
321   sys.exit(okToSys(result, verbose=True))
322