Salome HOME
Porting to Python 3
[plugins/ghs3dprlplugin.git] / src / tools / testMesh.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 coherency tests on one and some mesh.
27 initially used for test output(s) mg_tetra_hpc_mpi.exe
28
29 WARNING: is for small meshes, obviously no optimisation.
30 WARNING: printing and .mesh indices are 1 to n when stored list python 0 to n-1
31
32 example linux usage:
33 - simple run:
34   ./testMesh.py --verbose --testall --files ./GHS3DPRL_out.000001.mesh ./GHS3DPRL_out.000002.mesh
35   ./testMesh.py -a -f /tmp/GHS3DPRL_out.00000?.mesh
36 """
37
38 import os
39 import sys
40
41 import argparse as AP
42 import pprint as PP  # pretty print
43
44
45 verbose = False
46
47 OK = "ok"
48 KO = "KO"
49 OKSYS = 0  # for linux
50 KOSYS = 1  # for linux
51
52
53 #########################################
54 # utilities
55
56 def okToSys(aResult, verbose=False):
57   """to get windows or linux result of script"""
58
59   def extendList(alist):
60     """utility extend list of lists of string results with ok or KO"""
61     # bad: list(itertools.chain.from_list(alist)) iterate on str
62     res = []
63     if type(alist) != list:
64       return [alist]
65     else:
66       for i in alist:
67         if type(i) == str:
68            res.append(i)
69         else:
70            res.extend(extendList(i))
71     return res
72
73   resList = extendList(aResult)
74   if resList == []:
75     if verbose: print("WARNING: result no clear: []")
76     return KOSYS
77
78   rr = OK
79   for ri in resList:
80     if ri[0:2] != OK:
81       if verbose: print(ri)
82       rr = KO
83
84   if verbose: print("INFO: result: %s" % rr)
85   if rr == OK:
86     return OKSYS
87   else:
88     return KOSYS
89
90 def getDirAndName(datafile):
91   path, namefile = os.path.split(os.path.realpath(datafile))
92   rootpath = os.getcwd()
93   return (path, rootpath, namefile)
94
95 def resumeList(aList):
96   if len(aList) == 0:
97     return []
98   if len(aList) < 3:
99     return aList
100   res = [aList[0], "...", aList[-1]]
101   return res
102
103 def resumeLines(aList, ilines):
104   if verbose: print("INFO: resumeLines", ilines)
105   if len(aList) == 0:
106     return []
107   if len(aList) < 3:
108     return aList
109   res = []
110   for i in ilines:
111     if i != None:  # if not existing tetrahedra for example
112       resi = [ii.strip("\n") for ii in aList[i:i + 4]]
113       resi.append("...")
114       res.append(resi)
115   return res
116
117
118 #########################################
119 class XXVert:
120   """Vertices, Nodes"""
121   def __init__(self, x, y, z, color=0, indexglobal=0):
122     self.x = x
123     self.y = y
124     self.z = z
125     self.color = color
126     self.indexglobal = indexglobal
127
128   def compare(self, vb, args, withAll=True):
129     if self.x != vb.x: return False
130     if self.y != vb.y: return False
131     if self.z != vb.z: return False
132     if withAll:
133       if args.withColor:
134         if self.color != vb.color: return False
135       if args.withIndex:
136         if self.indexglobal != vb.indexglobal: return False
137     return True
138
139   def __eq__(self, vb):
140     """equality test without color or indexglobal"""
141     # print "vertice equality"
142     if self.x != vb.x: return False
143     if self.y != vb.y: return False
144     if self.z != vb.z: return False
145     return True
146
147   def __ne__(self, vb):
148     """inequality test without color or indexglobal"""
149     # print "vertice inequality"
150     if self.x == vb.x and self.y == vb.y and self.z != vb.z:
151       return True
152     return False
153
154   def __repr__(self):
155     return "XXVert(%.4f %.4f %.4f (%i %i))" % \
156            (self.x, self.y, self.z, self.color, self.indexglobal)
157
158   def __str__(self):
159     return "(%s %s %s (%i %i))" % \
160            (self.x, self.y, self.z, self.color, self.indexglobal)
161
162   def dist(self, vb):
163     res = (self.x - vb.x) ** 2 + (self.y - vb.y) ** 2 + (self.z - vb.z) ** 2
164     return res ** .5
165
166
167 #########################################
168 class XXEdge:
169   """Edges, 2 Nodes"""
170   def __init__(self, a, b, color=0, indexglobal=0):
171     self.a = a
172     self.b = b
173     self.color = color
174     self.indexglobal = indexglobal
175
176   def compare(self, eb, args):
177     res = self.a.compare(eb.a, args) and \
178           self.b.compare(eb.b, args)
179     if res:
180       if args.withColor:
181         if self.color != eb.color: return False
182       if args.withIndex:
183         if self.indexglobal != eb.indexglobal: return False
184     return res
185
186   def __repr__(self):
187     return "XXEdge(%i %i (%i %i))" % \
188            (self.a, self.b, self.color, self.indexglobal)
189
190   def __str__(self):
191     return "(%i %i (%i %i))" % \
192            (self.a, self.b, self.color, self.indexglobal)
193
194   def inTria(self, tria, args):
195     t = [tria.a, tria.b, tria.c]
196     if not self.a in t: return False
197     if not self.b in t: return False
198     return True
199
200   def getVertices(self, mesh):
201     v1 = mesh.verts[self.a - 1]
202     v2 = mesh.verts[self.b - 1]
203     return [v1, v2]
204
205
206 #########################################
207 class XXTria:
208   """Triangles, Faces, 3 nodes"""
209   def __init__(self, a, b, c, color=0, indexglobal=0):
210     self.a = a
211     self.b = b
212     self.c = c
213     self.color = color
214     self.indexglobal = indexglobal
215
216   def compare(self, trb, args):
217     res = self.a.compare(trb.a, args) and \
218           self.b.compare(trb.b, args) and \
219           self.c.compare(trb.c, args)
220     if res:
221       if args.withColor:
222         if self.color != trb.color: return False
223       if args.withIndex:
224         if self.indexglobal != trb.indexglobal: return False
225     return res
226
227   def __repr__(self):
228     return "XXTria(%i %i %i (%i %i))" % \
229            (self.a, self.b, self.c, self.color, self.indexglobal)
230
231   def __str__(self):
232     return "(%i %i %i (%i %i))" % \
233            (self.a, self.b, self.c, self.color, self.indexglobal)
234
235   def inTetra(self, tetra, args):
236     t = [tetra.a, tetra.b, tetra.c, tetra.d]
237     if not self.a in t: return False
238     if not self.b in t: return False
239     if not self.c in t: return False
240     return True
241
242   def getVertices(self, mesh):
243     v1 = mesh.verts[self.a - 1]
244     v2 = mesh.verts[self.b - 1]
245     v3 = mesh.verts[self.c - 1]
246     return [v1, v2, v3]
247
248
249 #########################################
250 class XXTetra:
251   """Tetra, 4 nodes"""
252   def __init__(self, a, b, c, d, color=0, indexglobal=0):
253     self.a = a
254     self.b = b
255     self.c = c
256     self.d = d
257     self.color = color
258     self.indexglobal = indexglobal
259
260   def compare(self, teb, args):
261     res = self.a.compare(teb.a, args) and \
262           self.b.compare(teb.b, args) and \
263           self.c.compare(teb.c, args) and \
264           self.d.compare(teb.d, args)
265     if res:
266       if args.withColor:
267         if self.color != teb.color: return False
268       if args.withIndex:
269         if self.indexglobal != teb.indexglobal: return False
270     return res
271
272   def __repr__(self):
273     return "XXTetra(%i %i %i %i (%i %i))" % \
274            (self.a, self.b, self.c, self.d, self.color, self.indexglobal)
275
276   def __str__(self):
277     return "(%i %i %i %i (%i %i))" % \
278            (self.a, self.b, self.c, self.d, self.color, self.indexglobal)
279
280   def getVertices(self, mesh):
281     v1 = mesh.verts[self.a - 1]
282     v2 = mesh.verts[self.b - 1]
283     v3 = mesh.verts[self.c - 1]
284     v4 = mesh.verts[self.d - 1]
285     return [v1, v2, v3, v4]
286
287
288 #########################################
289 class XXMesh:
290   """Mesh: vertices, edges, triangles, tetrahedra"""
291   def __init__(self):
292     self.nameFile = ""
293     self.verts = []
294     self.edges = []
295     self.trias = []
296     self.tetras = []
297
298   def initFromFileMesh(self, fileName, args, withGlobal=True):
299     if not os.path.isfile(fileName):
300       raise Exception("ERROR: inexisting file '%s'" % fileName)
301     with open(fileName, "r") as f:
302       lines = f.readlines()
303     iverts, iedges, itrias, itetras = self.getIndexInMeshFile(lines)
304     self.verts = self.getMeshVerts(lines, iverts)
305     self.edges = self.getMeshEdges(lines, iedges)
306     self.trias = self.getMeshTrias(lines, itrias)
307     self.tetras = self.getMeshTetras(lines, itetras)
308     self.nameFile = fileName
309     if args.globalNumerotation == True and withGlobal == True:
310       self.initFromFileGlobal(fileName, args)
311     if verbose:
312       print("\nINFO: initFromFileMesh: read file: %s" % str(self))
313       print(self.strResume())
314       print(PP.pformat(resumeLines(lines, [iverts, iedges, itrias, itetras])))
315
316   def initFromFileGlobal(self, fileNameMeshOrGlobal, args):
317     shortname, extension = os.path.splitext(fileNameMeshOrGlobal)
318     if extension == ".mesh":
319       fileName = shortname + ".global"
320     elif extension == "global":
321       fileName = fileNameMeshOrGlobal
322     else:
323       raise Exception("ERROR: initFromFileGlobal: unexpected file '%s'" % fileName)
324     if not os.path.isfile(fileName):
325       raise Exception("ERROR: initFromFileGlobal: inexisting file '%s'" % fileName)
326
327     with open(fileName, "r") as f:
328       lines = f.readlines()
329     nbverts, nbedges, nbtrias, nbtetras = [int(i) for i in lines[0].split()]
330     if verbose:
331       print("\nINFO: initFromFileGlobal: read file: %s" % str(self))
332       print("  nbverts %i\n  nbedges %i\n  nbtrias %i\n  nbtetras %i" % (nbverts, nbedges, nbtrias, nbtetras))
333     if nbverts != len(self.verts):
334       raise Exception("ERROR: in file '%s' unexpected number of Vertices %i<>%i" % (fileName, nbverts, len(self.verts)))
335     if nbedges != len(self.edges):
336       raise Exception("ERROR: in file '%s' unexpected number of Edges %i<>%i" % (fileName, nbedges, len(self.edges)))
337     if nbtrias != len(self.trias):
338       raise Exception("ERROR: in file '%s' unexpected number of Triangles %i<>%i" % (fileName, nbtrias, len(self.trias)))
339     if nbtetras != len(self.tetras):
340       raise Exception("ERROR: in file '%s' unexpected number of Tetrahedra %i<>%i" % (fileName, nbtetras, len(self.tetras)))
341     i = 1  # begin index line 1
342     for ii in range(nbverts):
343       self.verts[ii].indexglobal = int(lines[i])
344       i += 1
345     for ii in range(nbedges):
346       self.edges[ii].indexglobal = int(lines[i])
347       i += 1
348     for ii in range(nbtrias):
349       self.trias[ii].indexglobal = int(lines[i])
350       i += 1
351     for ii in range(nbtetras):
352       self.tetras[ii].indexglobal = int(lines[i])
353       i += 1
354
355
356   def __repr__(self):
357     return "XXMesh(nameFile='%s', nbverts=%i, nbedges=%i, nbtrias=%i, nbtetras=%i)" % \
358            (self.nameFile, len(self.verts), len(self.edges), len(self.trias), len(self.tetras))
359
360   def strResume(self):
361     res = str(self)
362     contents = {
363       "Vertices": resumeList(self.verts),
364       "Edges": resumeList(self.edges),
365       "Triangles": resumeList(self.trias),
366       "Tetrahedra": resumeList(self.tetras),
367     }
368     res = res + "\n" + PP.pformat(contents)
369     return res
370
371   def getIndexInMeshFile(self, lines):
372     res = []
373     for s in ["Vertices", "Edges", "Triangles", "Tetrahedra"]:
374       try:
375         i = lines.index(s + "\n")
376       except:
377         i = None
378       res.append(i)
379     return res
380
381   def getMeshVerts(self, lines, i):
382     res = []
383     try:
384       idep = i + 2
385       ilen = int(lines[i + 1])
386       ifin = idep + ilen
387       for line in lines[idep:ifin]:
388         li = line.split(" ")
389         x, y, z, color = float(li[0]), float(li[1]), float(li[2]), int(li[3])
390         res.append(XXVert(x, y, z, color))
391       return res
392     except:
393       return res
394
395   def getMeshEdges(self, lines, i):
396     res = []
397     try:
398       idep = i + 2
399       ilen = int(lines[i + 1])
400       ifin = idep + ilen
401       for line in lines[idep:ifin]:
402         li = line.split(" ")
403         a, b, color = int(li[0]), int(li[1]), int(li[2])
404         res.append(XXEdge(a, b, color))
405       return res
406     except:
407       return res
408
409   def getMeshTrias(self, lines, i):
410     res = []
411     try:
412       idep = i + 2
413       ilen = int(lines[i + 1])
414       ifin = idep + ilen
415       for line in lines[idep:ifin]:
416         li = line.split(" ")
417         a, b, c, color = int(li[0]), int(li[1]), int(li[2]), int(li[3])
418         res.append(XXTria(a, b, c, color))
419       return res
420     except:
421       return res
422
423   def getMeshTetras(self, lines, i):
424     res = []
425     try:
426       idep = i + 2
427       ilen = int(lines[i + 1])
428       ifin = idep + ilen
429       for line in lines[idep:ifin]:
430         li = line.split(" ")
431         a, b, c, d, color = int(li[0]), int(li[1]), int(li[2]), int(li[3]), int(li[4])
432         res.append(XXTetra(a, b, c, d, color))
433       return res
434     except:
435       return res
436
437   def haveVertsDistinct(self, args):
438     """stop a first KO"""
439     i = 0
440     verts = self.verts
441     for v1 in verts[:-1]:
442       i += 1
443       j = i
444       for v2 in verts[i:]:
445         j += 1
446         if v1.compare(v2, args):
447           # printing indices 1 to n
448           print("ERROR: %s vert[%i] equal vert[%i]: v1=%s v2=%s" % (self.nameFile, i, j, v1, v2))
449           return KO + " ERROR: %s some equal vertices" % self.nameFile  # stop a first KO
450     return OK + " INFO: no equal vertices"
451
452   def getVertices(self, elem):
453     """functionnal raccourci to XXElem.getVertices(XXMesh)"""
454     return elem.getVertices(self)
455
456   def compareListOfVertices(self, v1s, v2s, ordered=False):
457     """not ordered for now"""
458     if ordered:
459       res = [i for i, j in zip(v1s, v2s) if i == j]
460       return len(res) == len(v1s)
461     else:
462       res = 0
463       for i in v1s:
464         for j in v2s:
465           if i == j:
466             res += 1
467             break
468       return res == len(v1s)
469
470
471   def getCommonVerts(self, mesh, args):
472     res = []
473     for v1 in self.verts:
474       for v2 in mesh.verts:
475         if v1.compare(v2, args, withAll=False):
476           res.append((v1, v2))
477     return res
478
479   def getCommonEdges(self, mesh, args):
480     res = []
481     for e1 in self.edges:
482       v1s = self.getVertices(e1)
483       for e2 in mesh.edges:
484         v2s = mesh.getVertices(e2)
485         if self.compareListOfVertices(v1s, v2s):
486           res.append((e1, e2))
487     return res
488
489   def getCommonTriangles(self, mesh, args):
490     res = []
491     for e1 in self.trias:
492       v1s = self.getVertices(e1)
493       for e2 in mesh.trias:
494         v2s = mesh.getVertices(e2)
495         if self.compareListOfVertices(v1s, v2s):
496           res.append((e1, e2))
497     return res
498
499   def getCommonTetras(self, mesh, args):
500     res = []
501     for e1 in self.tetras:
502       v1s = self.getVertices(e1)
503       for e2 in mesh.tetras:
504         v2s = mesh.getVertices(e2)
505         if self.compareListOfVertices(v1s, v2s):
506           res.append((e1, e2))
507     return res
508
509   def areEdgesInTrias(self, args):
510     """stop a first KO"""
511     done = False
512     i = 0
513     edges = self.edges
514     trias = self.trias
515     res = OK + " INFO: %s all edges in trias" % self.nameFile
516     for e in edges:
517       i += 1
518       j = 0
519       found = False
520       for t in trias:
521         j += 1
522         if e.inTria(t, args):
523           # if verbose: print("INFO: %s edges[%i] in trias[%i]: edge=%s tria=%s" % (self.nameFile, i, j, e, t))
524           found = True
525           break
526       if not found:
527         print("ERROR: %s edges[%i] not in trias: edge=%s" % (self.nameFile, i, e))
528         if verbose and not done:
529           print("Triangles:\n%s" % PP.pformat(self.trias))
530           done = True
531         res = KO + " ERROR: %s some edges not in trias" % (self.nameFile)
532     return res
533
534
535   def areTriasInTetras(self, args):
536     """no stop a first KO"""
537     done = False
538     i = 0
539     trias = self.trias
540     tetras = self.tetras
541     if tetras == []:  # supposed skin without tetrahedra
542       res = OK + " WARNING: %s no tetrahedra in mesh" % (self.nameFile)
543       return res
544     res = OK + " INFO: %s all trias in tetras" % self.nameFile
545     for t in trias:
546       i += 1
547       j = 0
548       found = False
549       for h in tetras:
550         j += 1
551         if t.inTetra(h, args):
552           # if verbose: print("INFO: %s trias[%i] in tetras[%i]: tria=%s tetra=%s" % (self.nameFile, i, j, t, h))
553           found = True
554           break
555       if not found:
556         if verbose: print("ERROR: %s trias[%i] not in tetras: tria=%s" % (self.nameFile, i, t))
557         if verbose and not done:
558           print("INFO: Tetrahedra:\n%s" % PP.pformat(self.tetras))
559           done = True
560         res = KO + " ERROR: %s some trias not in tetras" % (self.nameFile)
561     return res
562
563   def testIntersection(self, mesh, args):
564     """intersection coherency between self and mesh"""
565
566     def storeAndInfoIntersection():
567       """used as macro: avoid duplicate code"""
568       # store info in args to use later...
569       args.intersections[title + name] = commons
570       if commons == []:
571         res.append(OK + " INFO: no %s" % title + name)
572       else:
573         res.append(OK + " INFO: existing %s" % title + name)
574       return
575
576     res = []
577     name = "%s<->%s" % (self.nameFile, mesh.nameFile)
578
579     title = "Vertices intersection: "
580     commons = self.getCommonVerts(mesh, args)
581     storeAndInfoIntersection()
582
583     title = "Edges intersection: "
584     commons = self.getCommonEdges(mesh, args)
585     storeAndInfoIntersection()
586
587     title = "Triangles intersection: "
588     commons = self.getCommonTriangles(mesh, args)
589     storeAndInfoIntersection()
590
591     title = "Tetrahedra intersection: "
592     commons = self.getCommonTetras(mesh, args)
593     storeAndInfoIntersection()
594
595     return res
596
597   def testIndexGlobal(self, mesh, args):
598     """global index coherency between self and mesh"""
599
600     def storeAndInfoIndexGlobal():
601       """used as macro: avoid duplicate code"""
602       # store info in args to use later...
603       args.indexglobal[title + name] = problems
604       if verbose: print("\nINFO: %s\n%s" % (title + name, PP.pformat(problems)))
605       if problems == []:
606         res.append(OK + " INFO: coherent %s" % title + name)
607       else:
608         res.append(KO + " ERROR: some problems %s" % title + name)
609       return
610
611     def testIndexGlobal():
612       """used as macro: avoid duplicate code"""
613       nameElem = title.split(' ')[0]
614       # something like 'Vertices intersection: /tmp/GHS3DPRL_out.000002.mesh<->/tmp/GHS3DPRL_out.000003.mesh'
615       commonsTitle = nameElem + " intersection: " + name
616       # if verbose: print "testIndexGlobal",title,commonsTitle
617       try:
618         intersection = args.intersections[commonsTitle]
619       except:
620         intersection = []
621       problems = []
622       for ii, jj in intersection:
623         if ii.indexglobal != jj.indexglobal:
624           problems.append((ii, jj))
625       return problems
626
627     res = []
628     name = "%s<->%s" % (self.nameFile, mesh.nameFile)
629
630     title = "Vertices indexglobal: "
631     problems = testIndexGlobal()
632     storeAndInfoIndexGlobal()
633
634     title = "Edges indexglobal: "
635     problems = testIndexGlobal()
636     storeAndInfoIndexGlobal()
637
638     title = "Triangles indexglobal: "
639     problems = testIndexGlobal()
640     storeAndInfoIndexGlobal()
641
642     title = "Tetrahedra indexglobal: "
643     problems = testIndexGlobal()
644     storeAndInfoIndexGlobal()
645
646     return res
647
648
649 #########################################
650 # tests
651
652 def testAll(args):
653   """test all on meshes from tetra_hpc_mpi"""
654   res = []
655   if verbose: print("\n*****testAll*****\n")
656   args.skinMesh = None
657   if args.skinInputFile != None:
658     args.skinMesh = XXMesh()
659     # a priori no global numerotation file.global for input tetra_hpc_mpi mesh
660     args.skinMesh.initFromFileMesh(args.skinInputFile, args, withGlobal=False)
661     res.append(testStandaloneMesh(args.skinMesh, args))
662     print("\nINFO: testAll skin input file:\n%s" % (PP.pformat(args.skinMesh)))
663
664   meshes = []
665   for fileName in args.files:
666     xxmesh = XXMesh()
667     xxmesh.initFromFileMesh(fileName, args)
668     meshes.append(xxmesh)
669   print("\nINFO: testAll ouput files:\n%s\n" % (PP.pformat(meshes)))
670   # test coherence of one by one meshes
671   for mesh in meshes:
672     res.append(testStandaloneMesh(mesh, args))
673   # test coherence of intersections an global numerotation of tetra_hpc_mpi output meshes
674   res.append(testParallelMesh(meshes, args))
675   res.append(testParallelMeshAndSkin(meshes, args))
676   res.append(testParallelMeshAndSkinColor(meshes, args))
677   return res
678
679
680 def testStandaloneMesh(mesh, args):
681   """test coherence of one mesh alone"""
682   if verbose: print("\nINFO: testStandaloneMesh:\n%s" % PP.pformat(mesh))
683   res = []
684   res.append(mesh.haveVertsDistinct(args))
685   res.append(mesh.areEdgesInTrias(args))
686   res.append(mesh.areTriasInTetras(args))
687   return res
688
689
690 def testParallelMesh(meshes, args):
691   """test intersection and overriding in tetra_hpc_mpi outputs GHS3DPRL_out.00000?.mesh"""
692   i = 0
693   res = []
694   args.intersections = {}
695   args.indexglobal = {}
696   for m1 in meshes[:-1]:
697     i += 1
698     for m2 in meshes[i:]:
699       res.append(m1.testIntersection(m2, args))
700       res.append(m1.testIndexGlobal(m2, args))
701   if verbose:
702     print("\nINFO: intersections\n%s" % PP.pformat(args.intersections))
703     print("\nINFO: indexglobal\n%s" % PP.pformat(args.indexglobal))
704   return res
705
706 def testParallelMeshAndSkin(meshes, args):
707   """test coherency between input skin and tetra_hpc_mpi outputs GHS3DPRL_out.00000?.mesh"""
708   res = []
709   if args.skinMesh == None:
710     print("INFO: no skin Mesh for testing intersectionsSkin\n")
711     res = OK + "INFO: no skin Mesh for testing intersectionsSkin"
712     return res
713   nbtriasskin = len(args.skinMesh.trias)
714   for m1 in meshes:
715     res.append(args.skinMesh.testIntersection(m1, args))
716     res.append(args.skinMesh.testIndexGlobal(m1, args))
717
718   # test total Triangles in output parallel meshes vs input skin mesh
719   if True:
720     kk = {}
721     nbtriaspara = 0
722     for k in list(args.intersections.keys()):
723       if args.skinMesh.nameFile in k:
724         ll = len(args.intersections[k])
725         if "Triangles intersection" in k:
726           nbtriaspara += ll
727         kk[k] = len(args.intersections[k])
728     print("INFO: skin intersections\n%s\n" % PP.pformat(kk))
729     if nbtriaspara < nbtriasskin:
730       res.append(KO + " ERROR: problem all skin triangles not in parallel meshes: %i<->%i" % (nbtriasskin, nbtriaspara))
731   return res
732
733 def testParallelMeshAndSkinColor(meshes, args):
734   """test coherency between color input skin and tetra_hpc_mpi outputs GHS3DPRL_out.00000?.mesh"""
735   res = []
736   if args.color == True:
737     res.append(KO + " ERROR: test color TODO!!!")
738   else:
739     res.append(OK + " WARNING: test color not done")
740   return res
741
742 if __name__ == '__main__':
743   parser = AP.ArgumentParser(description='launch test(s) on tetra_hpc_mpi mesh(es)', argument_default=None)
744   parser.add_argument(
745     '-a', '--testAll',
746     help='test all on all meshes',
747     action='store_true',
748   )
749   parser.add_argument(
750     '-v', '--verbose',
751     help='set verbose, for deep debug',
752     action='store_true',
753   )
754   parser.add_argument(
755     '-g', '--globalNumerotation',
756     help='read and set files .global, if associated',
757     action='store_true',
758   )
759   parser.add_argument(
760     '-c', '--color',
761     help='read and test with color',
762     action='store_true',
763   )
764   parser.add_argument(
765     '-f', '--files',
766     help='launch test(s) on file(s)',
767     nargs='*',
768     metavar='.../file.mesh'
769   )
770   parser.add_argument(
771     '-s', '--skinInputFile',
772     help='launch test(s) on tetra_hpc_mpi input file',
773     nargs='?',
774     metavar='.../skinInputFile.mesh'
775   )
776   """
777   parser.add_argument(
778     '-x', '--xoneargument',
779     nargs='?',
780     metavar='0|1',
781     choices=['0', '1'],
782     help='one argument, for example',
783     default='0'
784   )
785   """
786
787
788   """
789   args is Namespace, use it as global to store
790   parameters, data, used arrays and results and other...
791   """
792   args = parser.parse_args()
793
794   verbose = args.verbose
795   if verbose: print("INFO: args:\n%s" % PP.pformat(args))
796
797   if len(sys.argv) == 1:  # no args as --help
798     parser.print_help()
799     sys.exit(KOSYS)
800
801   if args.files == None:
802     print("\nERROR: Nothing to do: no files\n%s" % PP.pformat(args))
803     parser.print_help()
804     sys.exit(KOSYS)
805
806   if args.testAll:
807     result = testAll(args)
808   else:
809     result = KO
810     print("\nERROR: Nothing to do:\n%s" % PP.pformat(args))
811   sys.exit(okToSys(result, verbose=True))
812