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