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