Salome HOME
ok mpi and multithread, see example/ghs3dprh_multithread_cube_one_face.py
authorChristian Van Wambeke <christian.van-wambeke@cea.fr>
Wed, 26 Feb 2020 09:07:01 +0000 (10:07 +0100)
committerChristian Van Wambeke <christian.van-wambeke@cea.fr>
Wed, 26 Feb 2020 09:07:01 +0000 (10:07 +0100)
bin/mg-tetra_hpc.py [changed mode: 0644->0755]
doc/help_mg-tetra_hpc_mpi.txt [new file with mode: 0644]
example/ghs3dprh_multithread_cube_one_face.py [new file with mode: 0644]
src/GHS3DPRLPlugin/GHS3DPRLPlugin_GHS3DPRL.cxx
src/tepal2med/ghs3dprl_mesh_wrap.cxx
src/tepal2med/ghs3dprl_mesh_wrap.h
src/tepal2med/tetrahpc2med.cxx

old mode 100644 (file)
new mode 100755 (executable)
index 30bb1e5..b244d13
 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
@@ -41,14 +50,14 @@ import pprint as PP  # pretty print
 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'
 
 
@@ -56,8 +65,42 @@ 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"""
@@ -75,25 +118,29 @@ def okToSys(aResult, verbose=False):
 
   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)
 
 
@@ -112,74 +159,89 @@ class ArgRange(object):
   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
@@ -188,48 +250,77 @@ def launchMultithread(args):
 
 ##########################################################################
 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',
@@ -265,15 +356,18 @@ if __name__ == '__main__':
     '-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='?',
@@ -283,39 +377,72 @@ if __name__ == '__main__':
     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))
 
diff --git a/doc/help_mg-tetra_hpc_mpi.txt b/doc/help_mg-tetra_hpc_mpi.txt
new file mode 100644 (file)
index 0000000..638deef
--- /dev/null
@@ -0,0 +1 @@
+ You are using an empty MPI stubs library. Please read the documentation
diff --git a/example/ghs3dprh_multithread_cube_one_face.py b/example/ghs3dprh_multithread_cube_one_face.py
new file mode 100644 (file)
index 0000000..5899c3a
--- /dev/null
@@ -0,0 +1,100 @@
+#!/usr/bin/env python
+
+###
+### This file is generated automatically by SALOME v9.4.0 with dump python functionality
+###
+
+import sys
+import salome
+
+salome.salome_init()
+import salome_notebook
+notebook = salome_notebook.NoteBook()
+sys.path.insert(0, r'/volatile2/wambeke/SALOME-master-CO7-SRC')
+
+###
+### GEOM component
+###
+
+import GEOM
+from salome.geom import geomBuilder
+import math
+import SALOMEDS
+
+
+geompy = geomBuilder.New()
+
+O = geompy.MakeVertex(0, 0, 0)
+OX = geompy.MakeVectorDXDYDZ(1, 0, 0)
+OY = geompy.MakeVectorDXDYDZ(0, 1, 0)
+OZ = geompy.MakeVectorDXDYDZ(0, 0, 1)
+Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200)
+Group_1 = geompy.CreateGroup(Box_1, geompy.ShapeType["FACE"])
+geompy.UnionIDs(Group_1, [13])
+[Group_1] = geompy.GetExistingSubObjects(Box_1, False)
+geompy.addToStudy( O, 'O' )
+geompy.addToStudy( OX, 'OX' )
+geompy.addToStudy( OY, 'OY' )
+geompy.addToStudy( OZ, 'OZ' )
+geompy.addToStudy( Box_1, 'Box_1' )
+geompy.addToStudyInFather( Box_1, Group_1, 'Group_1' )
+
+###
+### SMESH component
+###
+
+import  SMESH, SALOMEDS
+from salome.smesh import smeshBuilder
+
+smesh = smeshBuilder.New()
+#smesh.SetEnablePublish( False ) # Set to False to avoid publish in study if not needed or in some particular situations:
+                                 # multiples meshes built in parallel, complex and numerous mesh edition (performance)
+
+Mesh_1 = smesh.Mesh(Box_1)
+NETGEN_1D_2D = Mesh_1.Triangle(algo=smeshBuilder.NETGEN_1D2D)
+NETGEN_2D_Simple_Parameters_1 = NETGEN_1D_2D.Parameters(smeshBuilder.SIMPLE)
+NETGEN_2D_Simple_Parameters_1.SetNumberOfSegments( 8 )
+NETGEN_2D_Simple_Parameters_1.SetMaxElementArea( 1200 )
+NETGEN_2D_Simple_Parameters_1.SetAllowQuadrangles( 0 )
+MG_Tetra_HPC = Mesh_1.Tetrahedron(algo=smeshBuilder.MG_Tetra_Parallel)
+MG_Tetra_HPC_Parameters_1 = MG_Tetra_HPC.Parameters()
+MG_Tetra_HPC_Parameters_1.SetMEDName( 'DOMAIN' )
+MG_Tetra_HPC_Parameters_1.SetNbPart( 4 )
+MG_Tetra_HPC_Parameters_1.SetKeepFiles( 1 )
+MG_Tetra_HPC_Parameters_1.SetBackground( 0 )
+MG_Tetra_HPC_Parameters_1.SetMultithread( 1 )
+MG_Tetra_HPC_Parameters_1.SetGradation( 1.05 )
+MG_Tetra_HPC_Parameters_1.SetMinSize( 0 )
+MG_Tetra_HPC_Parameters_1.SetMaxSize( 0 )
+Group_1_1 = Mesh_1.GroupOnGeom(Group_1,'Group_1',SMESH.FACE)
+isDone = Mesh_1.Compute()
+[ Group_1_1 ] = Mesh_1.GetGroups()
+([SKIN_INITIAL], status) = smesh.CreateMeshesFromMED(r'/tmp/DOMAIN_skin.med')
+[ Group_1_2, Group_Of_All_Faces, Group_Of_All_Edges, Group_Of_All_Nodes ] = SKIN_INITIAL.GetGroups()
+([DOMAIN_1], status) = smesh.CreateMeshesFromMED(r'/tmp/DOMAIN_1.med')
+[ All_Faces, Group_1_3, Skin_Group_Of_All_Faces, New_Tetrahedra, All_Nodes, New_Nodes ] = DOMAIN_1.GetGroups()
+
+
+## Set names of Mesh objects
+smesh.SetName(Group_Of_All_Edges, 'Group_Of_All_Edges')
+smesh.SetName(All_Nodes, 'All_Nodes')
+smesh.SetName(New_Nodes, 'New_Nodes')
+smesh.SetName(NETGEN_1D_2D.GetAlgorithm(), 'NETGEN 1D-2D')
+smesh.SetName(MG_Tetra_HPC.GetAlgorithm(), 'MG-Tetra_HPC')
+smesh.SetName(Group_Of_All_Nodes, 'Group_Of_All_Nodes')
+smesh.SetName(MG_Tetra_HPC_Parameters_1, 'MG-Tetra_HPC Parameters_1')
+smesh.SetName(NETGEN_2D_Simple_Parameters_1, 'NETGEN 2D Simple Parameters_1')
+smesh.SetName(Group_1_1, 'Group_1')
+smesh.SetName(Mesh_1.GetMesh(), 'Mesh_1')
+smesh.SetName(DOMAIN_1.GetMesh(), 'DOMAIN_1')
+smesh.SetName(SKIN_INITIAL.GetMesh(), 'SKIN_INITIAL')
+smesh.SetName(New_Tetrahedra, 'New_Tetrahedra')
+smesh.SetName(Group_1_3, 'Group_1')
+smesh.SetName(Skin_Group_Of_All_Faces, 'Skin_Group_Of_All_Faces')
+smesh.SetName(All_Faces, 'All_Faces')
+smesh.SetName(Group_Of_All_Faces, 'Group_Of_All_Faces')
+smesh.SetName(Group_1_2, 'Group_1')
+
+
+if salome.sg.hasDesktop():
+  salome.sg.updateObjBrowser()
index 6e6b0e06e4a9b7554a0906857af984c2cb5816f8..cc1fe0e7a8974b99707eebe159e7d2caa6ed1778 100644 (file)
@@ -261,6 +261,7 @@ bool GHS3DPRLPlugin_GHS3DPRL::Compute(SMESH_Mesh&         theMesh,
     fileskinmesh(""),
     path,
     casenamemed;  //_MEDName.c_str());
+  int res = 0;    // 0 is OK 
 
   casenamemed += (char *)_MEDName.c_str();
   int n=casenamemed.SearchFromEnd('/');
@@ -363,13 +364,20 @@ bool GHS3DPRLPlugin_GHS3DPRL::Compute(SMESH_Mesh&         theMesh,
   //sometimes it is better to wait flushing files on slow filesystem...
   system( "sleep 3" );
   //launch tetrahpc2med which launch mg-tetra_hpc.py which launch mg-tetra_hpc(_mpi?).exe
-  system( run_GHS3DPRL.ToCString() );
+  res = system( run_GHS3DPRL.ToCString() );
+  if (res > 0) 
+  {
+    pluginerror = pluginerror + "PROBLEM tetrahpc2med command";
+    cout<<pluginerror<<endl;
+    error(COMPERR_ALGO_FAILED, pluginerror.ToCString());
+    return false; //but it is not a problem but if true my message is overwritten
+  }
   system( "sleep 3" );
 
   if (_Background) {
     pluginerror = pluginerror + "backgrounding... plugin is not waiting for output files "+ casenamemed + "_*.med";
     cout<<pluginerror<<endl;
-    error(COMPERR_ALGO_FAILED, pluginerror.ToCString());
+    error(COMPERR_NO_MESH_ON_SHAPE, pluginerror.ToCString());
     return false; //but it is not a problem but if true my message is overwritten
     //return true; //but it is not a problem,
   }
@@ -380,9 +388,9 @@ bool GHS3DPRLPlugin_GHS3DPRL::Compute(SMESH_Mesh&         theMesh,
     Ok = false; //but it is not a problem but if true my message is overwritten
     fclose(aResultFile);
     cout<<"GHS3DPRL OK output master file "<<casenamemed<<".xml exist !\n\n";
-    pluginerror = pluginerror + "new tetraedra not in memory, but stored in files "+ casenamemed + "_*.med";
+    pluginerror = pluginerror + "MG-tetra_hpc mesh(es) not loaded in memory, are stored in files "+ casenamemed + "_*.med";
     cout<<pluginerror<<endl;
-    error(COMPERR_ALGO_FAILED, pluginerror.ToCString());
+    error(COMPERR_NO_MESH_ON_SHAPE, pluginerror.ToCString());
     if (!_KeepFiles) system( run_nokeep_files.ToCString() );
   }
   else{
index 9fe011766d41a68bf95b8abf6691bd71e75d4466..c9bf196f4109a0d4e577c3a56fef56b87c89bf4b 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2019  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2020 CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -666,15 +666,19 @@ bool ghs3dprl_mesh_wrap::ReadFileGLOBAL(const QString FileName)
    CVWtab *montab;
    bool ok;
    
-   if (verbose>=6)std::cout<<"Read file '"<<FileName.toLatin1().constData()<<std::endl;
-   if (!Ff.is_open()){
-      std::cerr<<"Problem file '"<<FileName.toLatin1().constData()<<"' not open\n"<<std::endl;
+   if (verbose>=6) std::cout<<"Read file '"<<FileName.toLatin1().constData()<<std::endl;
+   if (!Ff.is_open())
+   {
+      std::cerr<<"Problem file '"<<FileName.toLatin1().constData()<<"' not open"<<std::endl;
+      // std::cout<<"Default global numerotation nb verts "<<vert<<" nb edges "<<edge<<" nb trias "<<tria<<" nb tetras "<<tetr<<std::endl;
       return false;
    }
-   
-   //Lit les donnees :
-   Ff>>vert>>edge>>tria>>tetr;
-   std::cout<<"First line "<<vert<<" "<<edge<<" "<<tria<<" "<<tetr<<std::endl;
+   else
+   {
+     //Lit les donnees :
+     Ff>>vert>>edge>>tria>>tetr;
+     std::cout<<"Global numerotation nb verts "<<vert<<" nb edges "<<edge<<" nb trias "<<tria<<" nb tetras "<<tetr<<std::endl;
+   }
    
    if (vert<0)
    {
@@ -702,8 +706,8 @@ bool ghs3dprl_mesh_wrap::ReadFileGLOBAL(const QString FileName)
 
    count=vert;
    tmint=new med_int[count];
-   for (int i=0; i<count; i++) Ff>>tmint[i];
-   if (verbose>4) std::cout<<"Vertices ("<<count<<" ) "<<tmint[0]<<" "<<tmint[1]<<"... "<<tmint[count-1]<<std::endl;
+   for (long i=0; i<count; i++) Ff>>tmint[i];
+   if (verbose>4) std::cout<<"Vertices ("<<count<<") "<<tmint[0]<<" "<<tmint[1]<<"... "<<tmint[count-1]<<std::endl;
 
    montab=new CVWtab(count,tmint);
    tmp=tmp.sprintf("GL%ld VE",this->nofile);
@@ -711,7 +715,7 @@ bool ghs3dprl_mesh_wrap::ReadFileGLOBAL(const QString FileName)
 
    count=edge;
    tmint=new med_int[count];
-   for (int i=0; i<count; i++) Ff>>tmint[i];
+   for (long i=0; i<count; i++) Ff>>tmint[i];
    if (verbose>4) std::cout<<"Edges ("<<count<<") "<<tmint[0]<<" "<<tmint[1]<<"... "<<tmint[count-1]<<std::endl;
 
    montab=new CVWtab(count,tmint);
@@ -720,7 +724,7 @@ bool ghs3dprl_mesh_wrap::ReadFileGLOBAL(const QString FileName)
 
    count=tria;
    tmint=new med_int[count];
-   for (int i=0; i<count; i++) Ff>>tmint[i];
+   for (long i=0; i<count; i++) Ff>>tmint[i];
    if (verbose>4) std::cout<<"Triangles ("<<count<<") "<<tmint[0]<<" "<<tmint[1]<<"... "<<tmint[count-1]<<std::endl;
 
    montab=new CVWtab(count,tmint);
@@ -729,7 +733,7 @@ bool ghs3dprl_mesh_wrap::ReadFileGLOBAL(const QString FileName)
 
    count=tetr;
    tmint=new med_int[count];
-   for (int i=0; i<count; i++) Ff>>tmint[i];
+   for (long i=0; i<count; i++) Ff>>tmint[i];
    if (verbose>4) std::cout<<"Tetrahedra ("<<count<<") "<<tmint[0]<<" "<<tmint[1]<<"... "<<tmint[count-1]<<std::endl;
 
    montab=new CVWtab(count,tmint);
@@ -742,6 +746,58 @@ bool ghs3dprl_mesh_wrap::ReadFileGLOBAL(const QString FileName)
    return true;
 }
 
+///************************************
+bool ghs3dprl_mesh_wrap::ReadFileDefaultGLOBAL(long vert, long edge, long tria, long tetr)
+//default like read file .global ascii (no xml) when inexisting when multithread
+{
+   QString tmp;
+   long count=0;
+   med_int *tmint;
+   CVWtab *montab;
+   bool ok;
+   
+   //Simule les donnees :
+   std::cout<<"Default Global numerotation nb verts "<<vert<<" nb edges "<<edge<<" nb trias "<<tria<<" nb tetras "<<tetr<<std::endl;
+   
+   count=vert;
+   tmint=new med_int[count];
+   for (long i=0; i<count; i++) tmint[i] = i+1;
+   if (verbose>4) std::cout<<"Default Vertices ("<<count<<") "<<tmint[0]<<" "<<tmint[1]<<"... "<<tmint[count-1]<<std::endl;
+
+   montab=new CVWtab(count,tmint);
+   tmp=tmp.sprintf("GL%ld VE",this->nofile);
+   ok=this->insert_key(tmp,montab);
+
+   count=edge;
+   tmint=new med_int[count];
+   for (long i=0; i<count; i++) tmint[i] = i+1;
+   if (verbose>4) std::cout<<"Default Edges ("<<count<<") "<<tmint[0]<<" "<<tmint[1]<<"... "<<tmint[count-1]<<std::endl;
+
+   montab=new CVWtab(count,tmint);
+   tmp=tmp.sprintf("GL%ld ED",this->nofile);
+   ok=this->insert_key(tmp,montab);
+
+   count=tria;
+   tmint=new med_int[count];
+   for (long i=0; i<count; i++) tmint[i] = i+1;
+   if (verbose>4) std::cout<<"Default Triangles ("<<count<<") "<<tmint[0]<<" "<<tmint[1]<<"... "<<tmint[count-1]<<std::endl;
+
+   montab=new CVWtab(count,tmint);
+   tmp=tmp.sprintf("GL%ld FA",this->nofile);
+   ok=this->insert_key(tmp,montab);
+
+   count=tetr;
+   tmint=new med_int[count];
+   for (long i=0; i<count; i++) tmint[i] = i+1;
+   if (verbose>4) std::cout<<"Default Tetrahedra ("<<count<<") "<<tmint[0]<<" "<<tmint[1]<<"... "<<tmint[count-1]<<std::endl;
+
+   montab=new CVWtab(count,tmint);
+   tmp=tmp.sprintf("GL%ld EL",this->nofile);
+   ok=this->insert_key(tmp,montab);
+
+   return true;
+}
+
 //************************************
 bool ghs3dprl_mesh_wrap::ReadFileFACES(const QString FileName)
 //read file .faces (wrap)
@@ -871,42 +927,47 @@ bool ghs3dprl_mesh_wrap::ReadFileMESH(const QString FileName)
 
    getline(Ff,line);
    getline(Ff,line);
+  
+   getline(Ff,line); // get Edges or Triangle, because sometimes Edges absent
    
-   if (!(getline(Ff,line) && (line.find("Edges")==0)))
-   {
-      std::cerr<<"Problem on line 'Edges' of file '"<<FileName.toLatin1().constData()<<"' :found '"<<line<<"' instead"<<std::endl;
-      return false;
-   }
-   if (getline(Ff,line))
-   {
-      tmp=line.c_str();
-      Medge=tmp.toLong(&ok);
-   }
-   else
+   if (!line.find("Edges")==0)
    {
-      std::cerr<<"Problem on line 'Edges' of file: a positive integer is expected"<<std::endl;
-      return false;
+      std::cerr<<"absent line 'Edges' of file '"<<FileName.toLatin1().constData()<<"' :found '"<<line<<"' instead"<<std::endl;
    }
-   if (Medge<=0)
+   else 
    {
-      std::cerr<<"Problem on line 'Edges' of file: a positive integer is expected"<<std::endl;
-      return false;
-   }
+     if (getline(Ff,line))
+     {
+        tmp=line.c_str();
+        Medge=tmp.toLong(&ok);
+     }
+     else
+     {
+        std::cerr<<"Problem on line 'Edges' of file: a positive integer is expected"<<std::endl;
+        return false;
+     }
+     if (Medge<=0)
+     {
+        std::cerr<<"Problem on line 'Edges' of file: a positive integer is expected"<<std::endl;
+        return false;
+     }
 
-   count=Medge;
-   tmint=new med_int[count*2]; //*3
-   for (int i=0; i<count*2; i=i+2) {
-     Ff>>tmint[i]>>tmint[i+1]>>garbage;
+     count=Medge;
+     tmint=new med_int[count*2]; //*3
+     for (int i=0; i<count*2; i=i+2) {
+       Ff>>tmint[i]>>tmint[i+1]>>garbage;
+     }
+     if (verbose>4) std::cout<<"Edges ("<<count<<") "<<tmint[0]<<" "<<tmint[1]<<"... "<<tmint[count*2-1]<<std::endl;
+     montab=new CVWtab(count*2,tmint);
+     tmp=tmp.sprintf("NB%ld ED",this->nofile); //TODO see if it could serve
+     ok=this->insert_key(tmp,montab);
+     
+     getline(Ff,line);
+     getline(Ff,line);
+     getline(Ff,line);
    }
-   if (verbose>4) std::cout<<"Edges ("<<count<<") "<<tmint[0]<<" "<<tmint[1]<<"... "<<tmint[count*2-1]<<std::endl;
-   montab=new CVWtab(count*2,tmint);
-   tmp=tmp.sprintf("NB%ld ED",this->nofile); //TODO see if it could serve
-   ok=this->insert_key(tmp,montab);
-   
-   getline(Ff,line);
-   getline(Ff,line);
 
-   if (!(getline(Ff,line) && (line.find("Triangles")==0)))
+   if (!line.find("Triangles")==0)
    {
       std::cerr<<"Problem on line 'Triangles' of file '"<<FileName.toLatin1().constData()<<"' :found '"<<line<<"' instead"<<std::endl;
       return false;
@@ -974,6 +1035,11 @@ bool ghs3dprl_mesh_wrap::ReadFileMESH(const QString FileName)
       std::cout<<"MeshNumberOfTetrahedra="<<Mtetra<<std::endl;
    }
 
+   this->nbvert=Mvert; // for current idom
+   this->nbedge=Medge; 
+   this->nbtria=Mtria; 
+   this->nbtetr=Mtetra; 
+
    count=Mtetra;
    tmint=new med_int[count*4];
    for (int i=0; i<count*4; i=i+4) Ff>>tmint[i]>>tmint[i+1]>>tmint[i+2]>>tmint[i+3]>>garbage;
@@ -1550,6 +1616,7 @@ bool ghs3dprl_mesh_wrap::test_vertices_wrap()
    //for (int ifile=1; ifile <= this->nbfiles; ifile++)
    //for (int ineig=ifile+1; ineig <= this->nbfiles; ineig++)
    bool swap=false;
+   if (verbose>4)std::cout<<"test_vertices_wrap on nb files "<<this->nbfiles<<std::endl;
    for (int ifile=this->nbfiles; ifile >= 1; ifile--)
    for (int ineig=this->nbfiles; ineig >= ifile+1; ineig--)
    {
@@ -1702,7 +1769,7 @@ bool ghs3dprl_mesh_wrap::Write_masterxmlMEDfile()
 {
    QString tmp;
 
-   //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!first call
+   //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!first call create xml doc node
    if (idom==1)
    {
    //define master file (.xml) in memory
@@ -1721,7 +1788,7 @@ bool ghs3dprl_mesh_wrap::Write_masterxmlMEDfile()
    med_int majeur,mineur,release;
    //Quelle version de MED est utilisee
    MEDlibraryNumVersion(&majeur,&mineur,&release);
-   if (verbose>0) fprintf(stdout,"Files write with MED V%d.%d.%d\n",majeur,mineur,release);
+   if (verbose>0) fprintf(stdout,"File write %s with MED V%d.%d.%d\n",filemaster.c_str(),majeur,mineur,release);
    node = xmlNewChild(root_node, 0, BAD_CAST "version",0);
    //xmlNewProp(node, BAD_CAST "maj", BAD_CAST int2string2(majeur).c_str());
    xmlNewProp(node, BAD_CAST "maj", BAD_CAST i2a(majeur).c_str());
@@ -1730,7 +1797,8 @@ bool ghs3dprl_mesh_wrap::Write_masterxmlMEDfile()
 
    //Description tag
    node = xmlNewChild(root_node,0, BAD_CAST "description",0);
-   xmlNewProp(node, BAD_CAST "what", BAD_CAST "tetrahedral mesh by MeshGems-Tetra-hpc (formerly tepal)");
+   // .../INSTALL/MeshGems/include/meshgems/meshgems.h:11:#define MESHGEMS_VERSION_LONG "2.9-6"
+   xmlNewProp(node, BAD_CAST "what", BAD_CAST "tetrahedral mesh by MeshGems-Tetra-hpc 2.9-6 2019");
 #ifdef WIN32
   SYSTEMTIME  present;
   GetLocalTime ( &present );
@@ -1770,12 +1838,14 @@ bool ghs3dprl_mesh_wrap::Write_masterxmlMEDfile()
    xmlNewProp(mesh_node, BAD_CAST "name", BAD_CAST domainname.c_str());
    }
 
-   //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!all calls
+   //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!all calls add xml idom node
    {
+   fprintf(stdout,"Xml node write %s idom %d\n",filemaster.c_str(), idom);
    char *hostname = getenv("HOSTNAME");
    node = xmlNewChild(files_node,0,BAD_CAST "subfile",0);
    xmlNewProp(node, BAD_CAST "id", BAD_CAST i2a(idom).c_str());
    node2 = xmlNewChild(node, 0, BAD_CAST "name", BAD_CAST distfilename);
+   
    if (hostname == NULL)
       node2 = xmlNewChild(node, 0, BAD_CAST "machine",BAD_CAST "localhost");
    else
@@ -1801,14 +1871,17 @@ bool ghs3dprl_mesh_wrap::Write_masterxmlMEDfile()
    //xmlNewProp(node2, BAD_CAST "number", BAD_CAST i2a(nbtetra4).c_str());
 
    //tepal2med_info about joints of one subdomain
-   xmlAddChild(node,joints_node);
+   fprintf(stdout,"MeshGems 2.9-6 tetra-hpc joints are not implemented\n");  //MeshGems 2.9-6 Salome 9.5.0 jan 2020
+   // not implemented ... empty joints ... does NOT work ... xmlAddChild(node,joints_node);
    //tepal2med_info about groups and families of one subdomain
    xmlAddChild(node,families.xml_groups());
    }
 
    //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!last call
+   fprintf(stdout,"xml node idom %d/%d nb tetras total %d\n", idom, nbfilestot, nbtetrastotal);
    if (idom==nbfilestot)
    {
+   fprintf(stdout,"File write %s as last idom nb tetras total %d\n",filemaster.c_str(), nbtetrastotal);
    node2 = xmlNewChild(info_node, 0, BAD_CAST "global",0);
    xmlNewProp(node2, BAD_CAST "tetrahedra_number", BAD_CAST i2a(nbtetrastotal).c_str());
    //save masterfile
@@ -1926,11 +1999,19 @@ bool ghs3dprl_mesh_wrap::Write_MEDfiles_v2(bool deletekeys)
    //for (idom=1; idom<=nbfilestot; idom++) {
    if (for_multithread) {
      nbfilestot=1;
-     std::cout<<"\nset Number0fFiles as multithread="<<nbfilestot<<std::endl;
+     std::cout<<"\nset NumberOfFiles only one domain file as multithread="<<nbfilestot<<std::endl;
    }
-   if (verbose>6) std::cout<<"\nNumber0fFiles="<<nbfilestot<<std::endl;
+
+   // if (verbose>6) 
+   std::cout<<"\nNumberOfFiles="<<nbfilestot<<std::endl;
+
    for (idom=1; idom<=nbfilestot; idom++) {
    
+      this->nbvert=0;  // will be set for current loop idom
+      this->nbedge=0;
+      this->nbtria=0;
+      this->nbtetr=0;
+
       this->nofile=idom;
       //restore initial context of families
       if (idom>1) families=intermediatesfamilies;
@@ -1941,8 +2022,8 @@ bool ghs3dprl_mesh_wrap::Write_MEDfiles_v2(bool deletekeys)
       //std::cout<<"<"<<distfilename<<">"<<std::endl;
       fid=MEDfileOpen(distfilename,MED_ACC_CREAT);
       if (fid<0) {std::cerr<<"Problem MEDfileOpen "<<distfilename<<std::endl; goto erreur;}
-      if (verbose>0){
-         if (verbose>2) std::cout<<std::endl;
+      if (verbose>2) {
+         std::cout<<std::endl;
          std::cout<<"CreateMEDFile "<<idom<<" <"<<distfilename<<">\n";
       }
  
@@ -1964,20 +2045,24 @@ bool ghs3dprl_mesh_wrap::Write_MEDfiles_v2(bool deletekeys)
       if (verbose>4) std::cout<<"\nEnd of Faces ***\n"<<std::endl;
       if (!idom_tetras()) {std::cerr<<"Problem on tetrahedra"<<std::endl; goto erreur;}
       if (verbose>4) std::cout<<"\nEnd of Tetrahedra ***\n"<<std::endl;
+      
       //non existing files msg mh-tetra_hpc v2.1.11
       //if (!idom_joints()) {std::cerr<<"Problem on Joints"<<std::endl; goto erreur;}
 
-      if (!for_multithread) {
+      // if (!for_multithread) 
+      {
         if (verbose>6){std::cout<<"\nFinalsFamilies\n"; families.write();}
         //for nodes families
         nb=create_families(fid,1);
-        if (verbose>5)std::cout<<"NumberOfFamiliesNodes="<<nb<<std::endl;
+        if (verbose>5)std::cout<<"NumberOfFamiliesNodes="<<nb<<" name "<<nomfinal<<std::endl;
 
-        err=MEDmeshEntityFamilyNumberWr(fid,nomfinal,MED_NO_DT,MED_NO_IT,MED_NODE,MED_UNDEF_GEOMETRY_TYPE,nbnodes,famnodes);
         if (verbose>8)
           std::cout<<"MEDmeshEntityFamilyNumberWr nodes "<<nbnodes<<":"<<
                 famnodes[0]<<"..."<<famnodes[nbnodes-1]<<" "<<std::endl;
+
+        err=MEDmeshEntityFamilyNumberWr(fid,nomfinal,MED_NO_DT,MED_NO_IT,MED_NODE,MED_UNDEF_GEOMETRY_TYPE,nbnodes,famnodes);
         delete[] famnodes;
+        
         if (err<0) std::cerr<<"Problem MEDmeshEntityFamilyNumberWr nodes"<<std::endl;
 
         //for others families
@@ -2001,7 +2086,7 @@ bool ghs3dprl_mesh_wrap::Write_MEDfiles_v2(bool deletekeys)
     
       MEDfileClose(fid); //no error
       //master.xml writings
-      //oktmp=Write_masterxmlMEDfile();
+      oktmp=Write_masterxmlMEDfile();
       continue;       //and loop on others domains
 
       erreur:         //error
@@ -2038,6 +2123,9 @@ bool ghs3dprl_mesh_wrap::idom_nodes()
          if (for_tetrahpc) {
             tmp=pathini+casename+"_out"+tmp.sprintf(format_tetra.toLatin1().constData(),idom)+".mesh";
             ok=this->ReadFileMESH(tmp);
+            if (for_multithread) { // inexisting file GHS3DPRL_out.000001.global
+               this->ReadFileDefaultGLOBAL(this->nbvert, this->nbedge, this->nbtria, this->nbtetr);
+            }
          }
          tab=this->restore_key(key); //tab1=this->mestab[key1];
          if (!tab) return false;
@@ -2045,7 +2133,8 @@ bool ghs3dprl_mesh_wrap::idom_nodes()
       tmp=tmp.sprintf("NB%d SN",idom);
       //qt3 xx=this->remove_key_mesh_wrap(QRegExp(tmp,true,true));
       xx=this->remove_key_mesh_wrap(QRegExp(tmp,Qt::CaseSensitive,QRegExp::RegExp));
-      nbnodes=tab->size/3;
+      nbnodes=this->nbvert; // for current idom
+      
       err=MEDmeshNodeCoordinateWr(fid,nomfinal,MED_NO_DT,MED_NO_IT,0.,MED_FULL_INTERLACE,nbnodes,tab->tmflo);
       if (err<0) {std::cerr<<"Problem MEDmeshNodeCoordinateWr"<<std::endl; return false;}
       if (verbose>4) std::cout<<"NumberOfNodes="<<nbnodes<<std::endl;
@@ -2057,7 +2146,8 @@ bool ghs3dprl_mesh_wrap::idom_nodes()
       delete[] arrayi;
       if (err<0) {std::cerr<<"Problem MEDmeshEntityNumberWr of nodes"<<std::endl; return false;}
 
-    if (!for_multithread) {
+    // if (!for_multithread) 
+    {
       key1=key1.sprintf("GL%d VE",idom); //global numerotation 
       tab1=this->restore_key(key1); //tab1=this->mestab[key1];
       if (!tab1) {
@@ -2206,6 +2296,7 @@ bool ghs3dprl_mesh_wrap::idom_edges()
    bool ok=true;
    QString tmp;
    nbseg2=0;
+   this->nbedge=0;
    return ok;
 }
 
@@ -2228,6 +2319,8 @@ bool ghs3dprl_mesh_wrap::idom_faces()
          if (!tab1) return false;
       }
       nbtria3=tab1->size/3;
+      this->nbtria=nbtria3; // for current idom
+
       if (verbose>4) std::cout<<"NumberOfTriangles="<<nbtria3<<std::endl;
       //arrayi=new med_int[nbtria3*3];
       //ii=0,i=0 ;
@@ -2253,7 +2346,8 @@ bool ghs3dprl_mesh_wrap::idom_faces()
       if (err<0){std::cerr<<"Problem MEDmeshEntityNumberWr of triangles"<<std::endl; return false;}
 
       //GLx FA=files.GLo FAces
-      if (!for_multithread) {
+      // if (!for_multithread) 
+      {
         key1=key1.sprintf("GL%d FA",idom);
         tab1=this->restore_key(key1); //tab1=this->mestab[key1];
         if (nbtria3!=tab1->size){std::cerr<<"Problem size GLi FA!=nbtria3!"<<std::endl; return false;}
@@ -2399,7 +2493,7 @@ bool ghs3dprl_mesh_wrap::idom_joints()
 
          key=key.sprintf("NB%d VC",idom); //files.NoBoite Vertex Coordinates
          tab=this->restore_key(key); //tab1=this->mestab[key1];
-         //nbnodes=tab->size/3;
+         nbnodes=tab->size/3;
 
          //writing correspondence nodes-nodes
          //two indices for one correspondence
@@ -2598,6 +2692,8 @@ bool ghs3dprl_mesh_wrap::idom_tetras()
       key1=key1.sprintf("NB%d EV",idom); //files.NoBoite Elements Vertices (tetra only)
       tab1=this->restore_key(key1); //tab1=this->mestab[key1];
       nbtetra4=tab1->size/4;
+      this->nbtetr=nbtetra4; // for current idom
+
       nbtetrastotal=nbtetrastotal + nbtetra4;
       if (verbose>5)std::cout<<"NumberOftetrahedra="<<nbtetra4<<std::endl;
       err=MEDmeshElementConnectivityWr(fid,nomfinal,MED_NO_DT,MED_NO_IT,0.,MED_CELL,MED_TETRA4,MED_NODAL,MED_FULL_INTERLACE,nbtetra4,tab1->tmint);
@@ -2614,7 +2710,8 @@ bool ghs3dprl_mesh_wrap::idom_tetras()
       famtetra4=new med_int[nbtetra4];
       for (i=0; i<nbtetra4 ; i++) famtetra4[i]=famnewtetra4;
 
-      if (!for_multithread) {
+      // if (!for_multithread) 
+      {
         //writing tetrahedra global numbering
         //GLx EL=files.GLo ELements
         key1=key1.sprintf("GL%d EL",idom);
index 81834ff0e5f890eb53865cfc6dbfc7d1c98aa0cc..f09a69d35f46a1f759ab1948e57b701999c38496 100644 (file)
@@ -98,6 +98,7 @@ public:
       nbtetrastotal,
       nofile,nbfiles,nbfilestot,
       nbelem_limit_swap,
+      nbvert, nbedge, nbtria, nbtetr, // for current idom
       verbose;
    med_err err;
    med_idt fid,fidjoint;
@@ -160,6 +161,7 @@ public:
    bool TestExistingFileMESHnew(const QString FileName);
    bool ReadFileGLO(const QString FileName);
    bool ReadFileGLOBAL(const QString FileName); //mg-tetra v2.1.11
+   bool ReadFileDefaultGLOBAL(long vert, long edge, long tria, long tetr); //as default when multithread as one output 
    bool ReadFileFACES(const QString FileName);
    bool ReadFileMESH(const QString FileName);
    bool ReadFileNOBOITE(const QString FileName);
index f24388855691a8408f9cf68f6f49070f0f654108..b20a70d2afb4ee8ed8cd0a0eefc629d27c024876 100644 (file)
@@ -471,9 +471,9 @@ if (mymailw->verbose>3){
 /*
 mg-tetra_hpc_mpi.exe --help
 
-    =================================================
-    MG-Tetra_HPC -- MeshGems 2.1-11 (September, 2015)
-    =================================================
+    =============================================
+    MG-Tetra_HPC -- MeshGems 2.9-6 (August, 2019)
+    =============================================
 
         Distene SAS
            Campus Teratec
@@ -483,11 +483,11 @@ mg-tetra_hpc_mpi.exe --help
         Phone: +33(0)970-650-219   Fax: +33(0)169-269-033
         EMail: <support@distene.com>
 
-        Running MG-Tetra_HPC (Copyright 2014 by Distene SAS)
-           date of run: 31-May-2016 AT 09:05:29
-           running on : Linux 2.6.32-431.11.2.el6.centos.plus.x86_64 x86_64
+        Running MG-Tetra_HPC (Copyright 2014-2019 by Distene SAS)
+           date of run: 25-Feb-2020 AT 08:47:20
+           running on : Linux 3.10.0-1062.9.1.el7.x86_64 x86_64
            using modules: 
-                MeshGems-Core 2.1-11
+                MeshGems-Core 2.9-6
 
         MeshGems is a Registered Trademark of Distene SAS
 
@@ -503,6 +503,14 @@ Options:
    |   |   /
    v   v  v
 
+     --components <components>
+          Selects which mesh components to process.
+          If <components> is:
+              all : all components are to be meshed.
+              outside_components : only the main (outermost) component is to be
+          meshed.
+                    Default: all
+
      --gradation <g>
           Sets the size gradation value.
           <gradation> is the desired maximum ratio between 2 adjacent
@@ -510,39 +518,128 @@ Options:
           will be.
           Default: 1.05
 
+     --gradation_mode <mode>
+          Sets the gradation behaviour.
+          Possible values for <mode> are :
+              without_size: apply gradation only when no size is provided by
+          the input sizemap(s)
+              always: always apply the gradation. This can partially smooth the
+          provided input sizemap(s)
+          Default: without_size
+
      --help
           Prints this help.
-          
+
      --in <input mesh file name>
           Sets the input file.
           (MANDATORY)
 
+     --max_edge_length <maximum edge length>
+          Sets the desired maximum accepted edge length.
+          Default: 0 (no maximum length).
+
      --max_size <maximum size>
           Sets the desired maximum cell size value.
           Default: 0 (no maximum size).
 
+     --metric <type>
+          Sets the type of metric governing the mesh generation.
+          Possible values for <type> are :
+              isotropic: the metric induces the same size in all directions.
+              anisotropic: the metric induces different sizes depending on the
+          directions.
+          Default: isotropic
+
+     --min_edge_length <minimum edge length>
+          Sets the desired minimum accepted edge length.
+          Default: 0 (no minimum length).
+
      --min_size <minimum size>
-          Default: 0 (no minimum size).
           Sets the desired minimum cell size value.
+          Default: 0 (no minimum size).
+
+     --optimisation <boolean>
+          Sets whether to optimise mesh quality or not.
+          Default: yes.
+
+     --optimisation_level <level>
+          Sets the desired optimisation level for mesh quality.
+          Possible values for <level> are (in increasing order of quality vs
+          speed ratio): light, standard, strong
+          Default: standard.
 
      --out <output mesh file name>
           Sets the output file.
+          Using an existing file is not allowed.
+          Using the same file as --in is not allowed.
           If unset, _tetra_hpc is appended to the input file basename.
-          Using an existing file is forbidden.
-          Using the same file as --in is forbidden.
           
+     --parallel_strategy <strategy>
+          Sets the desired parallel strategy, influencing the level of
+          reproducibility of the result and the potential performances.
+          Possible values for <strategy> are (in decreasing order for
+          reproducibility and increasing order for performances):
+              reproducible: result is entirely reproducible but performances
+          may not be optimal.
+              aggressive: result may not be reproducible but all parallel
+          optimizations are allowed.
+          Default: reproducible.
+
+     --sizemap <input sizemap file name>
+          Sets the optional input sizemap file. The sizemap must provide the
+          requested size at the input surface or volume mesh vertices.
+                    Default : none.
+
+     --split_overconstrained_edges <boolean>
+          Sets whether to split over-constrained edges or not. An edge is
+          considered as over-constrained when its two vertices belong to the
+          surface.
+          If <boolean> is:
+              yes: correction is applied upon mesh generation/optimisation
+              no: no correction is applied.
+          Default: no
+
+     --split_overconstrained_elements <boolean>
+          Sets whether to split over-constrained elements or not. An edge is
+          considered as over-constrained when its two vertices belong to the
+          surface. A tetrahedron is considered as over-constrained  when at
+          least two of its faces belong to the surface.
+          If <boolean> is:
+              yes: correction is applied upon mesh generation/optimisation
+              no: no correction is applied.
+          Default: no
+
+     --split_overconstrained_tetrahedra <boolean>
+          Sets whether to split over-constrained tetrahedra or not. A
+          tetrahedron is considered as over-constrained  when at least two of
+          its faces belong to the surface.
+          If <boolean> is:
+              yes: correction is applied upon mesh generation/optimisation
+              no: no correction is applied.
+          Default: no
+
      --verbose <verbose>
           Set the verbosity level, increasing from 0 to 10.
-           <verbose> values are increasing from 0 to 10 :
-             0 : no details
-            10 : very detailed
-          Default: 3
+          Possible <verbose> values are increasing from 0 to 10 :
+             0 : no details.
+            10 : very detailed.
+          Default: 3.
+
+     --volume_proximity_layers <minimum number of layers>
+          Sets the desired minimum number of tetrahedra layers inside the
+          volume.
+          Default: 0 (no minimum).
+
+     --write_sizemap <output sizemap file name>
+          Sets the optional output sizemap file.
+          Using an existing file is not allowed.
+          If unset, the output sizemap will not be written.
 
 
 ================================================================================
-               MG-Tetra_HPC -- MeshGems 2.1-11 (September, 2015)
-         END OF SESSION - MG-Tetra_HPC (Copyright 2014 by Distene SAS)
-                   compiled Sep  3 2015 12:50:47 on Linux_64
+                 MG-Tetra_HPC -- MeshGems 2.9-6 (August, 2019)
+       END OF SESSION - MG-Tetra_HPC (Copyright 2014-2019 by Distene SAS)
+                   compiled Sep  2 2019 09:58:40 on Linux_64
                MeshGems is a Registered Trademark of Distene SAS
 ================================================================================
        ( Distene SAS
@@ -555,7 +652,7 @@ Options:
 int main(int argc, char *argv[])
 {
    bool ok;
-   int i,nb,nbfiles,limit_swap,nbelem_limit_swap,limit_swap_defaut,verbose;
+   int i,nb,nbfiles,limit_swap,nbelem_limit_swap,limit_swap_defaut,verbose,res;
    float gradation,min_size,max_size;
    QString path,pathini,casename,casenamemed,fileskinmed,
            tmp,cmd,format,format_tetra,
@@ -785,7 +882,7 @@ int main(int argc, char *argv[])
          
    if (launchtetra=="yes"){
      
-      //call tetra_hpc.py is pthon script which assumes mpirun or else if no multithread
+      //call tetra_hpc.py is python script which assumes mpirun or else if no multithread
       //after compilation openmpi or else acrobatic DISTENE_LICENCE change...
       
       cmd="mg-tetra_hpc.py --number=" + QString::number(nbfiles)+
@@ -828,7 +925,12 @@ int main(int argc, char *argv[])
    if (launchtetra=="yes"){
       //sometimes it is better to wait flushing files on slow filesystem...
       system("sleep 3");
-      system(cmd.toLatin1().constData()); // run
+      res = system(cmd.toLatin1().constData()); // run
+      if (res>0) 
+      {
+        std::cout<<std::endl<<"===end KO PROBLEM of "<<argv[0]<<"==="<<std::endl;
+        return res; // KO
+      }
       system("sleep 3");
    }
    ghs3dprl_mesh_wrap *mymailw=new ghs3dprl_mesh_wrap;
@@ -882,31 +984,32 @@ int main(int argc, char *argv[])
       if (verbose>0)std::cout<<"Initial skin file <"<<fileskinmed.toLatin1().constData()<<"> does not exist\n"; }
    
 
-//if test quickly read all files before (or only small files)
- if (test=="yes"){
-   if (verbose>0) std::cout<<"\nReading output files of tetrahpc as input files of tetrahpc2med...\n";
-   //only read beginning of files .xxxxx.mesh
-   //supposed big files big arrays so only see first lines
-   mymailw->nbfiles=0;
-   for (int i=1; i<=nbfiles; i++){
-      mymailw->nofile=i;
-      tmp=pathini+casename+tmp.sprintf(format_tetra.toLatin1().constData(),i)+".mesh";
-      if (verbose>0) std::cout<<"FileName="<<tmp.toLatin1().constData()<<std::endl;
-      ok=mymailw->TestExistingFileMESHnew(tmp);
-   }
-   if (verbose>0)
-      std::cout<<"NumberOfFilesMESHTested="<<mymailw->nbfiles<<": ok\n\n";
-   if (mymailw->nbfiles != nbfiles){
-      std::cerr<<"NumberOfFiles != NumberOfFilesTested is unexpected\n\n";
-      return 1;
-   }
- }  //end if test
+   //if test quickly read all files before (or only small files)
  if (test=="yes"){
+     if (verbose>0) std::cout<<"\nReading output files of tetrahpc as input files of tetrahpc2med...\n";
+     //only read beginning of files .xxxxx.mesh
+     //supposed big files big arrays so only see first lines
+     mymailw->nbfiles=0;
+     for (int i=1; i<=nbfiles; i++){
+        mymailw->nofile=i;
+        tmp=pathini+casename+tmp.sprintf(format_tetra.toLatin1().constData(),i)+".mesh";
+        if (verbose>0) std::cout<<"FileName="<<tmp.toLatin1().constData()<<std::endl;
+        ok=mymailw->TestExistingFileMESHnew(tmp);
+     }
+     if (verbose>0)
+        std::cout<<"NumberOfFilesMESHTested="<<mymailw->nbfiles<<": ok\n\n";
+     if (mymailw->nbfiles != nbfiles){
+        std::cerr<<"NumberOfFiles != NumberOfFilesTested is unexpected\n\n";
+        return 1;
+     }
  }  //end if test
  
    ok=mymailw->Write_MEDfiles_v2(true); //deletekeys=true
    
    nb=mymailw->remove_all_keys_mesh_wrap();
    if (verbose>3)std::cout<<"***remove_all_key_mesh_wrap*** "<<nb<<" keys removed\n";
-   if (verbose>0)std::cout<<std::endl<<"===end of "<<argv[0]<<"==="<<std::endl;
+
+   if (verbose>=0)std::cout<<std::endl<<"===end OK of "<<argv[0]<<"==="<<std::endl;
 
    //for debug
    //int res=dumpMED("/home/wambeke/tmp/DOMAIN_1.med",1);