From a33b1ed60ee2ef17a8bb2bd0d58d1b7fffbbc8d5 Mon Sep 17 00:00:00 2001 From: cconopoima Date: Tue, 31 Oct 2023 06:45:26 +0000 Subject: [PATCH] [bos #38045][bos #38046] New SA versions of NETGEN and GMSH. Add netgen_runner_test for 1D2D3D add test for gmsh_runner Improve test for netgen and gmsh. Add new versions in option mesher_launcher.py Add test for Netgen2D SA version. Test for Netgen 2D SA version. Code cleanup. Adapt mesher_launcher and add creating_parallel_gmsh_mesh.py test for Remote version of 3D GMSH. test for parallel mesh for 2D using new netgen SA/Remote version. Add the possibility to export Mesh1D.med in SMESH_Gen.cxx at method parallelComputeSubMeshes. Modify the constructor of ParallelMesh class in smeshBuilder to handle 2D meshing in parallel. --- doc/examples/creating_parallel_2D_mesh.py | 105 +++++++++ doc/examples/creating_parallel_gmsh_mesh.py | 95 ++++++++ doc/examples/tests.set | 4 +- src/SMESH/SMESH_Gen.cxx | 6 +- src/SMESH_SWIG/mesher_launcher.py | 10 +- src/SMESH_SWIG/smeshBuilder.py | 53 +++-- test/gmsh_runner.py | 238 ++++++++++++++++++++ test/netgen_runner.py | 14 +- test/netgen_runner_1D2D3D.py | 187 +++++++++++++++ test/netgen_runner_2D.py | 182 +++++++++++++++ test/tests.set | 3 + 11 files changed, 871 insertions(+), 26 deletions(-) create mode 100644 doc/examples/creating_parallel_2D_mesh.py create mode 100644 doc/examples/creating_parallel_gmsh_mesh.py create mode 100644 test/gmsh_runner.py create mode 100644 test/netgen_runner_1D2D3D.py create mode 100644 test/netgen_runner_2D.py diff --git a/doc/examples/creating_parallel_2D_mesh.py b/doc/examples/creating_parallel_2D_mesh.py new file mode 100644 index 000000000..a351bfc77 --- /dev/null +++ b/doc/examples/creating_parallel_2D_mesh.py @@ -0,0 +1,105 @@ +# contains function to compute a mesh in parallel +import salome + +salome.salome_init() +import salome_notebook +notebook = salome_notebook.NoteBook() + +### +### GEOM component +### + +import GEOM +from salome.geom import geomBuilder +from salome.smesh import smeshBuilder +import SALOMEDS + +import numpy as np + +geompy = geomBuilder.New() + + +nbox = 2 +boxsize = 100 +offset = 0 +# Create 3D faces +boxes = [] +# First creating all the boxes +# for i in range(nbox): +# for j in range(nbox): +# for k in range(nbox): + +# x_orig = i*(boxsize+offset) +# y_orig = j*(boxsize+offset) +# z_orig = k*(boxsize+offset) + +# tmp_box = geompy.MakeBoxDXDYDZ(boxsize, boxsize, boxsize) + +# if not i == j == k == 0: +# box = geompy.MakeTranslation(tmp_box, x_orig, +# y_orig, z_orig) +# else: +# box = tmp_box + +# geompy.addToStudy(box, 'box_{}:{}:{}'.format(i, j, k)) + +# boxes.append(box) + +#With 6 boxes works +#But simplify for 2 boxes to also Test possibility of rewritting the +# input mesh from other parallel tests. In that case this test will break +# because the input mesh will not match the exported/imported box geometry. +for i in range(nbox): + for j in range(1): + for k in range(1): + + x_orig = i*(boxsize+offset) + y_orig = j*(boxsize+offset) + z_orig = k*(boxsize+offset) + + tmp_box = geompy.MakeBoxDXDYDZ(boxsize, boxsize, boxsize) + + if not i == j == k == 0: + box = geompy.MakeTranslation(tmp_box, x_orig, + y_orig, z_orig) + else: + box = tmp_box + + geompy.addToStudy(box, 'box_{}:{}:{}'.format(i, j, k)) + + boxes.append(box) + +# Create fuse of all boxes +all_boxes = geompy.MakeCompound(boxes) +geompy.addToStudy(all_boxes, 'Compound_1') + +# Removing duplicates faces and edges +all_boxes = geompy.MakeGlueFaces(all_boxes, 1e-07) +geompy.addToStudy(all_boxes, 'Glued_Faces_1') + +rubik_cube = geompy.MakeGlueEdges(all_boxes, 1e-07) +geompy.addToStudy(all_boxes, 'rubik_cube') + + +smesh = smeshBuilder.New() +print("Creating Parallel Mesh") +par_mesh = smesh.ParallelMesh(rubik_cube, name="par_mesh", mesher2D="NETGEN_2D_Remote") + +print("Setting parallelism method") +par_mesh.SetParallelismMethod(smeshBuilder.MULTITHREAD) + +print("Setting parallelism options") +param = par_mesh.GetParallelismSettings() +param.SetNbThreads(6) + +print("Starting parallel compute") +is_done = par_mesh.Compute() +if not is_done: + raise Exception("Error when computing Mesh") + +print(" Triangle: ", par_mesh.NbTriangles()) +print(" edge: ", par_mesh.NbEdges()) + +assert par_mesh.NbTetras() == 0 +assert par_mesh.NbTriangles() > 0 +assert par_mesh.NbEdges() > 0 diff --git a/doc/examples/creating_parallel_gmsh_mesh.py b/doc/examples/creating_parallel_gmsh_mesh.py new file mode 100644 index 000000000..8b30c841e --- /dev/null +++ b/doc/examples/creating_parallel_gmsh_mesh.py @@ -0,0 +1,95 @@ +# contains function to compute a mesh in parallel +import salome + +salome.salome_init() +import salome_notebook +notebook = salome_notebook.NoteBook() + +### +### GEOM component +### + +import GEOM +from salome.geom import geomBuilder +from salome.smesh import smeshBuilder +import SALOMEDS + +import numpy as np + +geompy = geomBuilder.New() + + +nbox = 2 +boxsize = 100 +offset = 0 +# Create 3D faces +boxes = [] +# First creating all the boxes +for i in range(nbox): + for j in range(nbox): + for k in range(nbox): + + x_orig = i*(boxsize+offset) + y_orig = j*(boxsize+offset) + z_orig = k*(boxsize+offset) + + tmp_box = geompy.MakeBoxDXDYDZ(boxsize, boxsize, boxsize) + + if not i == j == k == 0: + box = geompy.MakeTranslation(tmp_box, x_orig, + y_orig, z_orig) + else: + box = tmp_box + + geompy.addToStudy(box, 'box_{}:{}:{}'.format(i, j, k)) + + boxes.append(box) + +# Create fuse of all boxes +all_boxes = geompy.MakeCompound(boxes) +geompy.addToStudy(all_boxes, 'Compound_1') + +# Removing duplicates faces and edges +all_boxes = geompy.MakeGlueFaces(all_boxes, 1e-07) +geompy.addToStudy(all_boxes, 'Glued_Faces_1') + +rubik_cube = geompy.MakeGlueEdges(all_boxes, 1e-07) +geompy.addToStudy(all_boxes, 'rubik_cube') + +smesh = smeshBuilder.New() +print("Creating Parallel Mesh") +par_mesh = smesh.ParallelMesh(rubik_cube, name="par_mesh", mesher3D="GMSH") + +print("Creating hypoehtesis for netgen") +NETGEN_3D_Parameters_1 = smesh.CreateHypothesisByAverageLength( 'NETGEN_Parameters', + 'NETGENEngine', 34.641, 0 ) +print("Adding hypothesis") +par_mesh.AddGlobalHypothesis(NETGEN_3D_Parameters_1, mesher="GMSH" ) + +#Set here particular mesh parameters in 3D +for algo3d in par_mesh._algo3d: + param3d = algo3d.Parameters() + param3d.Set2DAlgo(0) + param3d.Set3DAlgo(0) + param3d.SetSmouthSteps(2) + param3d.SetSizeFactor(1.1) + +print("Setting parallelism method") +par_mesh.SetParallelismMethod(smeshBuilder.MULTITHREAD) + +print("Setting parallelism options") +param = par_mesh.GetParallelismSettings() +param.SetNbThreads(6) + +print("Starting parallel compute") +is_done = par_mesh.Compute() +if not is_done: + raise Exception("Error when computing Mesh") + +print(" Tetrahedron: ", par_mesh.NbTetras()) +print(" Triangle: ", par_mesh.NbTriangles()) +print(" edge: ", par_mesh.NbEdges()) + +assert par_mesh.NbTetras() > 0 +assert par_mesh.NbTriangles() > 0 +assert par_mesh.NbEdges() > 0 diff --git a/doc/examples/tests.set b/doc/examples/tests.set index 883044711..b70ce3bed 100644 --- a/doc/examples/tests.set +++ b/doc/examples/tests.set @@ -133,7 +133,9 @@ SET(BAD_TESTS viewing_meshes_ex01.py radial_prism_3d_algo.py create_dual_mesh.py - creating_parallel_mesh.py + creating_parallel_mesh.py + creating_parallel_gmsh_mesh.py + creating_parallel_2D_mesh.py ) IF(NOT WIN32) LIST(APPEND BAD_TESTS diff --git a/src/SMESH/SMESH_Gen.cxx b/src/SMESH/SMESH_Gen.cxx index 48fc0da2f..9f75ddfa5 100644 --- a/src/SMESH/SMESH_Gen.cxx +++ b/src/SMESH/SMESH_Gen.cxx @@ -407,9 +407,9 @@ bool SMESH_Gen::parallelComputeSubMeshes( case TopAbs_FACE: file_name = "Mesh2D.med"; break; - //case TopAbs_EDGE: - // file_name = "Mesh1D.med"; - // break; + case TopAbs_EDGE: + file_name = "Mesh1D.med"; + break; //case TopAbs_VERTEX: // file_name = "Mesh0D.med"; // break; diff --git a/src/SMESH_SWIG/mesher_launcher.py b/src/SMESH_SWIG/mesher_launcher.py index 3794016df..8ca70494c 100644 --- a/src/SMESH_SWIG/mesher_launcher.py +++ b/src/SMESH_SWIG/mesher_launcher.py @@ -30,7 +30,7 @@ from argparse import ArgumentParser import pydefx import pylauncher -MESHER_HANDLED = ["NETGEN3D"] +MESHER_HANDLED = ["NETGEN3D","NETGEN2D","NETGEN1D","NETGEN1D2D","NETGEN1D2D","GMSH3D"] CMD_TEMPLATE = \ """{runner} {mesher} {mesh_file} {shape_file} {param_file} {elem_orientation_file} {new_element_file} {output_mesh_file} > {log_file} 2>&1""" @@ -94,11 +94,16 @@ def get_runner(mesher): else: ext = "" - if mesher in ['NETGEN3D']: + if mesher in ['NETGEN3D','NETGEN2D','NETGEN1D','NETGEN1D2D','NETGEN1D2D']: exe_path = path.join("${NETGENPLUGIN_ROOT_DIR}", "bin", "salome", "NETGENPlugin_Runner"+ext) + elif mesher in ['GMSH3D']: + exe_path = path.join("${GMSHPLUGIN_ROOT_DIR}", + "bin", + "salome", + "GMSHPlugin_Runner"+ext) else: raise Exception("Mesher {mesher} is not handled".format(mesher=mesher)) @@ -106,7 +111,6 @@ def get_runner(mesher): def run_local(args): """ Simple Local run """ - print("Local run") #TODO: Check on how to handle log for windows (through sp.check_output) cmd = CMD_TEMPLATE.format(\ runner=get_runner(args.mesher), diff --git a/src/SMESH_SWIG/smeshBuilder.py b/src/SMESH_SWIG/smeshBuilder.py index 781137a69..0bd3de6a4 100644 --- a/src/SMESH_SWIG/smeshBuilder.py +++ b/src/SMESH_SWIG/smeshBuilder.py @@ -462,7 +462,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): obj,name = name,obj return Mesh(self, self.geompyD, obj, name) - def ParallelMesh(self, obj, name=0, split_geom=True): + def ParallelMesh(self, obj, name=0, split_geom=True, mesher2D="NETGEN", mesher3D="NETGEN"): """ Create a parallel mesh. @@ -476,7 +476,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): an instance of class :class:`ParallelMesh`. """ return ParallelMesh(self, self.geompyD, obj, - split_geom=split_geom, name=name) + split_geom=split_geom, name=name, mesher2D=mesher2D, mesher3D=mesher3D ) def RemoveMesh( self, mesh ): """ @@ -7546,6 +7546,10 @@ class Mesh(metaclass = MeshMeta): pass # end of Mesh class +def _copy_gmsh_param(dim, local_param, global_param): + if dim==3: + local_param.SetMaxSize(global_param.GetMaxSize()) + local_param.SetMinSize(global_param.GetMinSize()) def _copy_netgen_param(dim, local_param, global_param): """ @@ -7780,7 +7784,7 @@ class ParallelMesh(Mesh): """ Surcharge on Mesh for parallel computation of a mesh """ - def __init__(self, smeshpyD, geompyD, geom, split_geom=True, name=0): + def __init__(self, smeshpyD, geompyD, geom, split_geom=True, name=0, mesher2D="NETGEN", mesher3D="NETGEN"): """ Create a parallel mesh. @@ -7815,14 +7819,31 @@ class ParallelMesh(Mesh): self._all_faces, self._solids = _split_geom(geompyD, geom_obj) order = [] - self._algo2d = self.Triangle(geom=geom_obj, algo="NETGEN_2D") - self._algo3d = [] - for solid_id, solid in enumerate(self._solids): - name = "Solid_{}".format(solid_id) - algo3d = self.Tetrahedron(geom=solid, algo="NETGEN_3D_Remote") - self._algo3d.append(algo3d) + if ( mesher2D == "NETGEN" ): #Default 2D mesher + self._algo2d = self.Triangle(geom=geom_obj, algo="NETGEN_2D") + + if ( mesher2D != "NETGEN" ): + #Means that we want to mesh face of solids in parallel and not the volume + self._algo2d = [] + #For the moment use AutomaticLength based on finesse + self._algo1d = self.Segment().AutomaticLength(0.1) + for solid_id, solid in enumerate(self._solids): + name = "Solid_{}".format(solid_id) + algo2d = self.Triangle(geom=solid, algo="NETGEN_2D_Remote") + self._algo2d.append(algo2d) + else: + self._algo3d = [] + for solid_id, solid in enumerate(self._solids): + name = "Solid_{}".format(solid_id) + if ( mesher3D == "NETGEN" ): + algo3d = self.Tetrahedron(geom=solid, algo="NETGEN_3D_Remote") + self._algo3d.append(algo3d) + elif ( mesher3D == "GMSH" ): + algo3d = self.Tetrahedron(geom=solid, algo="GMSH_3D_Remote") + self._algo3d.append(algo3d) + self._param = None @@ -7856,7 +7877,7 @@ class ParallelMesh(Mesh): raise Exception("You need to set Parallelism method first (SetParallelismMethod)") return self._param - def AddGlobalHypothesis(self, hyp): + def AddGlobalHypothesis(self, hyp, mesher="NETGEN"): """ Split hypothesis to apply it to all the submeshes: - the 1D+2D @@ -7868,14 +7889,16 @@ class ParallelMesh(Mesh): """ if not isinstance(hyp, NETGENPlugin._objref_NETGENPlugin_Hypothesis): raise ValueError("param must come from NETGENPlugin") - - param2d = self._algo2d.Parameters() + + param2d = self._algo2d.Parameters() _copy_netgen_param(2, param2d, hyp) - + for algo3d in self._algo3d: - param3d = algo3d.Parameters() - _copy_netgen_param(3, param3d, hyp) + if ( mesher == "NETGEN" ): + _copy_netgen_param(3, param3d, hyp) + elif( mesher == "GMSH" ): + _copy_gmsh_param(3, param3d, hyp) pass # End of ParallelMesh diff --git a/test/gmsh_runner.py b/test/gmsh_runner.py new file mode 100644 index 000000000..abbe92cd1 --- /dev/null +++ b/test/gmsh_runner.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python +import sys +import salome + +salome.salome_init() + +import time +from os import path +import tempfile +import subprocess + +import GEOM, SMESH, SALOMEDS + +from salome.geom import geomBuilder +from salome.smesh import smeshBuilder + +import math + +smesh = smeshBuilder.New() +geompy = geomBuilder.New() + +import medcoupling as mc + +def create_gmsh_empty_param_file(param_file): + """ Create a parameter file for runner """ + param = """0""" + with open(param_file, "w") as ffile: + ffile.write(param) + +def create_gmsh_param_file(param_file): + """ Create a parameter file for runner """ + param = """1 +0 +0 +0 +0 +0 +0 +2 +1.0 +0.0 +1e22 +0.0 +0 +0 +0""" + with open(param_file, "w") as ffile: + ffile.write(param) + + +def runTheMesher( mesh_2d, geo, emptyParam=False ): + nb_tetras = 0 + nb_points = 0 + nb_triangles = 0 + nb_segments = 0 + with tempfile.TemporaryDirectory() as tmp_dir: + mesh_file = path.join(tmp_dir, "mesh.med") + shape_file = path.join(tmp_dir, "shape.brep") + param_file = path.join(tmp_dir, "gmsh_param.txt") + new_elementsbinary = path.join(tmp_dir, "nodesAndElements.bin") + output_mesh = path.join(tmp_dir, "mesh3D.med") + + print("Running in folder: ", tmp_dir) + if not ( emptyParam ): + create_gmsh_param_file(param_file) + else: + create_gmsh_empty_param_file(param_file) + mesh_2d.ExportMED(mesh_file, 0, 41, 1, mesh_2d, 1, [], '', -1, 1) + geompy.ExportBREP( geo, shape_file ) + + runner = path.join("${GMSHPLUGIN_ROOT_DIR}", + "bin", + "salome", + "GMSHPlugin_Runner") + + if sys.platform == 'win32': + runner += ".exe" + + cmd = "{runner} GMSH3D {mesh_file} {shape_file} "\ + "{param_file} NONE {new_elementsbinary} {output_mesh}"\ + .format(runner=runner, + mesh_file=mesh_file, + shape_file=shape_file, + param_file=param_file, + new_elementsbinary=new_elementsbinary, + output_mesh=output_mesh) + print(cmd) + subprocess.check_call(cmd, shell=True) + + mesh_read = mc.ReadUMeshFromFile(output_mesh, "MESH", 0) + + nb_tetras = mesh_read.getNumberOfCellsWithType(mc.NORM_TETRA4) + nb_points = mesh_read.getNumberOfNodes() + + mesh_read = mc.ReadUMeshFromFile(output_mesh, "MESH", -1) + nb_triangles = mesh_read.getNumberOfCellsWithType(mc.NORM_TRI3) + + mesh_read = mc.ReadUMeshFromFile(output_mesh, "MESH", -2) + nb_segments = mesh_read.getNumberOfCellsWithType(mc.NORM_SEG2) + + return [nb_points, nb_segments, nb_triangles, nb_tetras] + +def test_gmsh3dDefault(): + """ Test gmsh3d """ + # Building geometry + box = geompy.MakeBoxDXDYDZ(200, 200, 200) + + geompy.ExtractShapes(box, geompy.ShapeType["FACE"], True) + groupe_1 = geompy.CreateGroup(box, geompy.ShapeType["FACE"] ) + geompy.UnionIDs(groupe_1, [3, 13, 23, 27, 31, 33]) + + [_, _, _, _, _, _, groupe_1] = geompy.GetExistingSubObjects(box, False) + + shape_faces = geompy.SubShapeAllSorted(box, geompy.ShapeType["FACE"]) + + mesh_2d = smesh.Mesh(box, 'Maillage_1') + + mesh_2d.Triangle(algo=smeshBuilder.NETGEN_1D2D) + isDone = mesh_2d.Compute() + premeshedTriangles = mesh_2d.NbFaces() + premeshedTetras = mesh_2d.NbVolumes() + + if not isDone: + raise Exception("Error when computing Mesh") + + smesh.SetName(mesh_2d, 'Maillage_1') + + [nb_points, nb_segments, nb_triangles, nb_tetras] = runTheMesher( mesh_2d, box ) + + + print("Nb Tetras:", nb_tetras) + print("Nb Triangles:", nb_triangles) + print("Nb Segments:", nb_segments) + print("Nb Points:", nb_points) + + assert premeshedTetras == 0 + assert nb_triangles == premeshedTriangles + assert nb_tetras == 6 # number of tetras for normalized 2D premesh (update if default 2D netgen change!) + assert nb_points == 8 # one node in each vertex of the cube + assert nb_segments > 0 + +def test_gmsh3d(): + """ Test gmsh3d """ + # Building geometry + box = geompy.MakeBoxDXDYDZ(200, 200, 200) + + geompy.ExtractShapes(box, geompy.ShapeType["FACE"], True) + groupe_1 = geompy.CreateGroup(box, geompy.ShapeType["FACE"] ) + geompy.UnionIDs(groupe_1, [3, 13, 23, 27, 31, 33]) + + [_, _, _, _, _, _, groupe_1] = geompy.GetExistingSubObjects(box, False) + + shape_faces = geompy.SubShapeAllSorted(box, geompy.ShapeType["FACE"]) + + # Creating 2D mesh + netgen_2d_parameters_1 = smesh.CreateHypothesisByAverageLength( + 'NETGEN_Parameters_2D', 'NETGENEngine', 34.641, 0 ) + + mesh_2d = smesh.Mesh(box, 'Maillage_1') + mesh_2d.AddHypothesis(box, netgen_2d_parameters_1) + + mesh_2d.Triangle(algo=smeshBuilder.NETGEN_1D2D) + isDone = mesh_2d.Compute() + premeshedTriangles = mesh_2d.NbFaces() + premeshedTetras = mesh_2d.NbVolumes() + + if not isDone: + raise Exception("Error when computing Mesh") + + smesh.SetName(mesh_2d, 'Maillage_1') + + [nb_points, nb_segments, nb_triangles, nb_tetras] = runTheMesher( mesh_2d, box ) + + + print("Nb Tetras:", nb_tetras) + print("Nb Triangles:", nb_triangles) + print("Nb Segments:", nb_segments) + print("Nb Points:", nb_points) + + assert premeshedTetras == 0 + assert nb_triangles == premeshedTriangles + assert nb_tetras > 6 + assert nb_points > 8 + assert nb_segments > 0 + +def test_gmsh3d_empty_parameters(): + """ Test gmsh3d """ + # Building geometry + box = geompy.MakeBoxDXDYDZ(200, 200, 200) + + geompy.ExtractShapes(box, geompy.ShapeType["FACE"], True) + groupe_1 = geompy.CreateGroup(box, geompy.ShapeType["FACE"] ) + geompy.UnionIDs(groupe_1, [3, 13, 23, 27, 31, 33]) + + [_, _, _, _, _, _, groupe_1] = geompy.GetExistingSubObjects(box, False) + + shape_faces = geompy.SubShapeAllSorted(box, geompy.ShapeType["FACE"]) + + # Creating 2D mesh + netgen_2d_parameters_1 = smesh.CreateHypothesisByAverageLength( + 'NETGEN_Parameters_2D', 'NETGENEngine', 34.641, 0 ) + + mesh_2d = smesh.Mesh(box, 'Maillage_1') + mesh_2d.AddHypothesis(box, netgen_2d_parameters_1) + + mesh_2d.Triangle(algo=smeshBuilder.NETGEN_1D2D) + isDone = mesh_2d.Compute() + premeshedTriangles = mesh_2d.NbFaces() + premeshedTetras = mesh_2d.NbVolumes() + + if not isDone: + raise Exception("Error when computing Mesh") + + smesh.SetName(mesh_2d, 'Maillage_1') + + [nb_points, nb_segments, nb_triangles, nb_tetras] = runTheMesher( mesh_2d, box, True ) + + + print("Nb Tetras:", nb_tetras) + print("Nb Triangles:", nb_triangles) + print("Nb Segments:", nb_segments) + print("Nb Points:", nb_points) + + assert premeshedTetras == 0 + assert nb_triangles == premeshedTriangles + assert nb_tetras > 6 + assert nb_points > 8 + assert nb_segments > 0 + +if __name__ == "__main__": + if sys.platform == "win32": + print("Disabled on windows") + sys.exit(0) + + test_gmsh3dDefault() + test_gmsh3d() + test_gmsh3d_empty_parameters() + diff --git a/test/netgen_runner.py b/test/netgen_runner.py index 4f0ffbd65..9e61dc747 100644 --- a/test/netgen_runner.py +++ b/test/netgen_runner.py @@ -59,18 +59,24 @@ def test_netgen3d(): box = geompy.MakeBoxDXDYDZ(200, 200, 200) geompy.ExtractShapes(box, geompy.ShapeType["FACE"], True) - groupe_1 = geompy.CreateGroup(box, geompy.ShapeType["FACE"]) + groupe_1 = geompy.CreateGroup(box, geompy.ShapeType["FACE"] ) geompy.UnionIDs(groupe_1, [3, 13, 23, 27, 31, 33]) [_, _, _, _, _, _, groupe_1] = geompy.GetExistingSubObjects(box, False) + + shape_faces = geompy.SubShapeAllSorted(box, geompy.ShapeType["FACE"]) + oneFace = shape_faces[0] # Creating 2D mesh netgen_2d_parameters_1 = smesh.CreateHypothesisByAverageLength( 'NETGEN_Parameters_2D', 'NETGENEngine', 34.641, 0) - mesh_2d = smesh.Mesh(groupe_1, 'Maillage_1') - mesh_2d.AddHypothesis(groupe_1, netgen_2d_parameters_1) + + mesh_2d = smesh.Mesh(box, 'Maillage_1') + mesh_2d.AddHypothesis(box, netgen_2d_parameters_1) + mesh_2d.Triangle(algo=smeshBuilder.NETGEN_1D2D) isDone = mesh_2d.Compute() + if not isDone: raise Exception("Error when computing Mesh") @@ -131,4 +137,4 @@ if __name__ == "__main__": if sys.platform == "win32": print("Disabled on windows") sys.exit(0) - test_netgen3d() + test_netgen3d() \ No newline at end of file diff --git a/test/netgen_runner_1D2D3D.py b/test/netgen_runner_1D2D3D.py new file mode 100644 index 000000000..4db491221 --- /dev/null +++ b/test/netgen_runner_1D2D3D.py @@ -0,0 +1,187 @@ +#!/usr/bin/env python +import sys +import salome + +salome.salome_init() + +from os import path +import tempfile +import subprocess + +import GEOM, SMESH, SALOMEDS + +from salome.geom import geomBuilder +from salome.smesh import smeshBuilder + +import math + +smesh = smeshBuilder.New() +geompy = geomBuilder.New() + +import medcoupling as mc + +def create_simple2d_param_file_1D(param_file,segments,segLenght,maxArea): + """ Create a parameter file for runner """ + param = """1 +{} +{} +{} +0""".format(segments,segLenght,maxArea) + with open(param_file, "w") as ffile: + ffile.write(param) + +def create_simple2d3d_param_file_1D(param_file,segments,segLenght,maxArea,maxVolume): + """ Create a parameter file for runner """ + param = """1 +{} +{} +{} +{} +0""".format(segments,segLenght,maxArea,maxVolume) + + with open(param_file, "w") as ffile: + ffile.write(param) + +def CommonFunction(netgen,case,segments,segLenght,maxArea,maxVolume): + # Building geometry + box = geompy.MakeBoxDXDYDZ(200, 200, 200) + + # Create 1D regular elements + mesh_1d = smesh.Mesh(box, 'Maillage_1') + mesh_1d.Segment().NumberOfSegments(1) + isDone = mesh_1d.Compute() + + if not isDone: + raise Exception("Error when computing Mesh") + + smesh.SetName(mesh_1d, 'Maillage_1') + nb_points = 0 + nb_segments = 0 + nb_triangles = 0 + nb_tetras = 0 + with tempfile.TemporaryDirectory() as tmp_dir: + mesh_file = path.join(tmp_dir, "mesh.med") + shape_file = path.join(tmp_dir, "shape.brep") + if ( case <= 2 ): + param_file = path.join(tmp_dir, "param_simple2D.txt") + else: + param_file = path.join(tmp_dir, "param_simple3D.txt") + + output_mesh = path.join(tmp_dir, "meshout.med") + + print("Running in folder: ", tmp_dir) + + if ( case <= 2 ): + create_simple2d_param_file_1D(param_file, segments, segLenght, maxArea ) + else: + create_simple2d3d_param_file_1D(param_file, segments, segLenght, maxArea, maxVolume ) + + mesh_1d.ExportMED(mesh_file, 0, 41, 1, mesh_1d, 1, [], '', -1, 1) + geompy.ExportBREP( box, shape_file ) + + runner = path.join("${NETGENPLUGIN_ROOT_DIR}", + "bin", + "salome", + "NETGENPlugin_Runner") + + if sys.platform == 'win32': + runner += ".exe" + + cmd = "{runner} {NETGEN} {mesh_file} {shape_file} "\ + "{param_file} NONE NONE {output_mesh}"\ + .format(runner=runner, + NETGEN=netgen, + mesh_file=mesh_file, + shape_file=shape_file, + param_file=param_file, + output_mesh=output_mesh) + print(cmd) + subprocess.check_call(cmd, shell=True) + mesh_read = mc.ReadUMeshFromFile(output_mesh, "MESH", 0) + nb_points = mesh_read.getNumberOfNodes() + if (case == 1): + nb_segments = mesh_read.getNumberOfCellsWithType(mc.NORM_SEG2) + if (case == 2): + nb_triangles = mesh_read.getNumberOfCellsWithType(mc.NORM_TRI3) + mesh_read = mc.ReadUMeshFromFile(output_mesh, "MESH", -1) + nb_segments = mesh_read.getNumberOfCellsWithType(mc.NORM_SEG2) + if (case == 3): + nb_tetras = mesh_read.getNumberOfCellsWithType(mc.NORM_TETRA4) + mesh_read = mc.ReadUMeshFromFile(output_mesh, "MESH", -1) + nb_triangles = mesh_read.getNumberOfCellsWithType(mc.NORM_TRI3) + mesh_read = mc.ReadUMeshFromFile(output_mesh, "MESH", -2) + nb_segments = mesh_read.getNumberOfCellsWithType(mc.NORM_SEG2) + + return [nb_points,nb_segments,nb_triangles,nb_tetras] + +def test_netgen1d(): + [nb_points,nb_segments,nb_triangles,nb_tetras] = CommonFunction( "NETGEN1D", 1, 1, 200, 0.0, 0.0 ) + + print("Nb Points:", nb_points) + print("Nb Segments:", nb_segments) + assert nb_points > 0 + assert nb_segments > 0 + + +def test_netgen1d2d(): + """ Test netgen1d2d mesher """ + [nb_points,nb_segments,nb_triangles,nb_tetras] = CommonFunction( "NETGEN1D2D", 2, 1, 200, 0.0, 0.0 ) + + print("Nb Triangles:", nb_triangles) + print("Nb Segments:", nb_segments) + print("Nb Points:", nb_points) + + assert nb_triangles == 12 + assert nb_points > 0 + assert nb_segments > 0 + +def test_netgen1d2dMaxArea(): + """ Test netgen1d2d mesher """ + [nb_points,nb_segments,nb_triangles, nb_tetras] = CommonFunction( "NETGEN1D2D", 2, 5, 200, 50.0, 0.0 ) + + print("Nb Triangles:", nb_triangles) + print("Nb Segments:", nb_segments) + print("Nb Points:", nb_points) + + assert nb_triangles > 12 + assert nb_points > 0 + assert nb_segments > 0 + + +def test_netgen1d2d3d(): + """ Test netgen1d2d mesher """ + [nb_points,nb_segments,nb_triangles,nb_tetras] = CommonFunction( "NETGEN1D2D3D", 3, 1, 200, 0.0, 0.0 ) + + print("Nb Tetras:", nb_tetras) + print("Nb Triangles:", nb_triangles) + print("Nb Segments:", nb_segments) + print("Nb Points:", nb_points) + + assert nb_triangles == 12 + assert nb_tetras == 5 + assert nb_points > 0 + assert nb_segments > 0 + +def test_netgen1d2dMaxVolume(): + """ Test netgen1d2d mesher """ + [nb_points,nb_segments,nb_triangles,nb_tetras] = CommonFunction( "NETGEN1D2D3D", 3, 1, 200, 500.0, 500.0 ) + + print("Nb Tetras:", nb_tetras) + print("Nb Triangles:", nb_triangles) + print("Nb Segments:", nb_segments) + print("Nb Points:", nb_points) + + assert nb_triangles > 12 + assert nb_tetras > 5 + assert nb_points > 0 + assert nb_segments > 0 + +if __name__ == "__main__": + if sys.platform == "win32": + print("Disabled on windows") + sys.exit(0) + test_netgen1d() + test_netgen1d2d() + test_netgen1d2d3d() + test_netgen1d2dMaxArea() + test_netgen1d2dMaxVolume() diff --git a/test/netgen_runner_2D.py b/test/netgen_runner_2D.py new file mode 100644 index 000000000..36be1b717 --- /dev/null +++ b/test/netgen_runner_2D.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python +import sys +import salome + +salome.salome_init() + +from os import path +import tempfile +import subprocess + +import GEOM, SMESH, SALOMEDS + +from salome.geom import geomBuilder +from salome.smesh import smeshBuilder + +import math + +smesh = smeshBuilder.New() +geompy = geomBuilder.New() + +import medcoupling as mc + +def create_param_file(param_file): + """ Create a parameter file for runner """ + param = """1 +34.641 +0.14 +16 +0.15 +1.5 +0 +0 +1 +5 +1 +1 +-1 +3 +3 +0.2 +2 +1 +0 +0 +2 +2 +0 + +0 +0 +0""" + with open(param_file, "w") as ffile: + ffile.write(param) + +def create_maxarea_param_file_2D(param_file,maxArea): + """ Create a parameter file for runner """ + param = """1 +{} +""".format(maxArea) + with open(param_file, "w") as ffile: + ffile.write(param) + +def create_lenghtFromEdges_param_file_2D(param_file): + """ Create a parameter file for runner """ + param = """1 +""" + + with open(param_file, "w") as ffile: + ffile.write(param) + +def CommonFunction(netgen,case,numberOfEdges1D,hypo,maxArea): + # Building geometry + geometry = geompy.MakeBoxDXDYDZ(200, 200, 200) + # Create 1D regular elements + mesh_1d = smesh.Mesh(geometry, 'Maillage_1') + mesh_1d.Segment().NumberOfSegments(numberOfEdges1D) + isDone = mesh_1d.Compute() + + if not isDone: + raise Exception("Error when computing Mesh") + + smesh.SetName(mesh_1d, 'Maillage_1') + nb_points = 0 + nb_segments = 0 + nb_triangles = 0 + nb_tetras = 0 + with tempfile.TemporaryDirectory() as tmp_dir: + mesh_file = path.join(tmp_dir, "mesh.med") + shape_file = path.join(tmp_dir, "shape.brep") + + if ( hypo == 0 ): + param_file = path.join(tmp_dir, "param.txt") + create_param_file(param_file ) + + if ( hypo == 1 ): + param_file = path.join(tmp_dir, "param_lenghtfromedge.txt") + create_lenghtFromEdges_param_file_2D(param_file ) + + if ( hypo == 2 ): + param_file = path.join(tmp_dir, "param_maxarea.txt") + create_maxarea_param_file_2D(param_file,maxArea) + + bin_file = path.join(tmp_dir, "mesh.bin") + output_mesh = path.join(tmp_dir, "meshout.med") + + print("Running in folder: ", tmp_dir) + + mesh_1d.ExportMED(mesh_file, 0, 41, 1, mesh_1d, 1, [], '', -1, 1) + geompy.ExportBREP( geometry, shape_file ) + + runner = path.join("${NETGENPLUGIN_ROOT_DIR}", + "bin", + "salome", + "NETGENPlugin_Runner") + + if sys.platform == 'win32': + runner += ".exe" + + cmd = "{runner} {NETGEN} {mesh_file} {shape_file} "\ + "{param_file} NONE {bin_file} {output_mesh}"\ + .format(runner=runner, + NETGEN=netgen, + mesh_file=mesh_file, + shape_file=shape_file, + param_file=param_file, + bin_file=bin_file, + output_mesh=output_mesh) + print(cmd) + subprocess.check_call(cmd, shell=True) + mesh_read = mc.ReadUMeshFromFile(output_mesh, "MESH", 0) + nb_points = mesh_read.getNumberOfNodes() + if (case == 2): + nb_triangles = mesh_read.getNumberOfCellsWithType(mc.NORM_TRI3) + mesh_read = mc.ReadUMeshFromFile(output_mesh, "MESH", -1) + nb_segments = mesh_read.getNumberOfCellsWithType(mc.NORM_SEG2) + + return [nb_points,nb_segments,nb_triangles,nb_tetras] + + +def test_netgen2d(): + """ Test netgen2d mesher """ + [nb_points,nb_segments,nb_triangles,nb_tetras] = CommonFunction( "NETGEN2D", 2, 3, 0, 0.0 ) + + print("Nb Triangles:", nb_triangles) + print("Nb Segments:", nb_segments) + print("Nb Points:", nb_points) + + assert nb_triangles > 12 + assert nb_points > 8 + assert nb_segments > 12 + +def test_netgen2dMaxArea(): + """ Test netgen2d mesher """ + [nb_points,nb_segments,nb_triangles,nb_tetras] = CommonFunction( "NETGEN2D", 2, 3, 2, 75.0 ) + + print("Nb Triangles:", nb_triangles) + print("Nb Segments:", nb_segments) + print("Nb Points:", nb_points) + + assert nb_triangles > 12 + assert nb_points > 8 + assert nb_segments > 12 + +def test_netgen2dLenghtFromEdge(): + """ Test netgen2d mesher """ + [nb_points,nb_segments,nb_triangles,nb_tetras] = CommonFunction( "NETGEN2D", 2, 1, 1, 0.0 ) + + print("Nb Triangles:", nb_triangles) + print("Nb Segments:", nb_segments) + print("Nb Points:", nb_points) + + assert nb_triangles == 12 + assert nb_points == 8 + assert nb_segments == 12 + +if __name__ == "__main__": + if sys.platform == "win32": + print("Disabled on windows") + sys.exit(0) + test_netgen2d() + test_netgen2dMaxArea() + test_netgen2dLenghtFromEdge() diff --git a/test/tests.set b/test/tests.set index ff3dede4c..f3e7e6c75 100644 --- a/test/tests.set +++ b/test/tests.set @@ -68,6 +68,9 @@ SET(BAD_TESTS SMESH_create_dual_mesh_adapt.py SMESH_create_dual_mesh_tpipe.py netgen_runner.py + netgen_runner_2D.py + netgen_runner_1D2D3D.py + gmsh_runner.py test_import_1D2D_with_tetras_and_pyras.py ) -- 2.39.2