1 # Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 # CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License.
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 # See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
21 # Author : Francis KLOSS, OCC
43 smesh = salome.lcc.FindOrLoadComponent("FactoryServer", "SMESH")
44 smesh.SetCurrentStudy(salome.myStudy)
52 ior = salome.orb.object_to_string(obj)
53 sobj = salome.myStudy.FindObjectIOR(ior)
57 attr = sobj.FindAttribute("AttributeName")[1]
60 def SetName(obj, name):
61 ior = salome.orb.object_to_string(obj)
62 sobj = salome.myStudy.FindObjectIOR(ior)
63 attr = sobj.FindAttribute("AttributeName")[1]
66 # Algorithms and hypothesis
67 # =========================
69 # Private class: Mesh_Algorithm
70 # -----------------------------
74 Mother class to define algorithm, recommended to don't use directly
84 If the algorithm is global, return 0
85 else return the submesh associated to this algorithm
89 def GetAlgorithm(self):
91 Return the wrapped mesher
95 def TreatHypoStatus(self, status, hypName, geomName, isAlgo):
97 Private method. Print error message if a hypothesis was not assigned
100 hypType = "algorithm"
102 hypType = "hypothesis"
103 if status == SMESH.HYP_UNKNOWN_FATAL :
104 reason = "for unknown reason"
105 elif status == SMESH.HYP_INCOMPATIBLE :
106 reason = "this hypothesis mismatches algorithm"
107 elif status == SMESH.HYP_NOTCONFORM :
108 reason = "not conform mesh would be built"
109 elif status == SMESH.HYP_ALREADY_EXIST :
110 reason = hypType + " of the same dimension already assigned to this shape"
111 elif status == SMESH.HYP_BAD_DIM :
112 reason = hypType + " mismatches shape"
113 elif status == SMESH.HYP_CONCURENT :
114 reason = "there are concurrent hypotheses on sub-shapes"
115 elif status == SMESH.HYP_BAD_SUBSHAPE :
116 reason = "shape is neither the main one, nor its subshape, nor a valid group"
119 hypName = '"' + hypName + '"'
120 geomName= '"' + geomName+ '"'
121 if status < SMESH.HYP_UNKNOWN_FATAL:
122 print hypName, "was assigned to", geomName,"but", reason
124 print hypName, "was not assigned to",geomName,":", reason
127 def Create(self, mesh, geom, hypo, so="libStdMeshersEngine.so"):
132 raise RuntimeError, "Attemp to create " + hypo + " algoritm on None shape"
137 name = GetName(piece)
142 name = geompy.SubShapeName(geom, piece)
143 geompy.addToStudyInFather(piece, geom, name)
144 self.subm = mesh.mesh.GetSubMesh(geom, hypo)
146 self.algo = smesh.CreateHypothesis(hypo, so)
147 SetName(self.algo, name + "/" + hypo)
148 status = mesh.mesh.AddHypothesis(self.geom, self.algo)
149 self.TreatHypoStatus( status, hypo, name, 1 )
151 def Hypothesis(self, hyp, args=[], so="libStdMeshersEngine.so"):
155 hypo = smesh.CreateHypothesis(hyp, so)
161 a = a + s + str(args[i])
164 name = GetName(self.geom)
165 SetName(hypo, name + "/" + hyp + a)
166 status = self.mesh.mesh.AddHypothesis(self.geom, hypo)
167 self.TreatHypoStatus( status, hyp, name, 0 )
170 # Public class: Mesh_Segment
171 # --------------------------
173 class Mesh_Segment(Mesh_Algorithm):
175 Class to define a segment 1D algorithm for discretization
178 def __init__(self, mesh, geom=0):
182 self.Create(mesh, geom, "Regular_1D")
184 def LocalLength(self, l):
186 Define "LocalLength" hypothesis to cut an edge in several segments with the same length
187 \param l for the length of segments that cut an edge
189 hyp = self.Hypothesis("LocalLength", [l])
193 def NumberOfSegments(self, n, s=[]):
195 Define "NumberOfSegments" hypothesis to cut an edge in several fixed number of segments
196 \param n for the number of segments that cut an edge
197 \param s for the scale factor (optional)
200 hyp = self.Hypothesis("NumberOfSegments", [n])
202 hyp = self.Hypothesis("NumberOfSegments", [n,s])
203 hyp.SetDistrType( 1 )
204 hyp.SetScaleFactor(s)
205 hyp.SetNumberOfSegments(n)
208 def Arithmetic1D(self, start, end):
210 Define "Arithmetic1D" hypothesis to cut an edge in several segments with arithmetic length increasing
211 \param start for the length of the first segment
212 \param end for the length of the last segment
214 hyp = self.Hypothesis("Arithmetic1D", [start, end])
215 hyp.SetLength(start, 1)
216 hyp.SetLength(end , 0)
219 def StartEndLength(self, start, end):
221 Define "StartEndLength" hypothesis to cut an edge in several segments with geometric length increasing
222 \param start for the length of the first segment
223 \param end for the length of the last segment
225 hyp = self.Hypothesis("StartEndLength", [start, end])
226 hyp.SetLength(start, 1)
227 hyp.SetLength(end , 0)
230 def Deflection1D(self, d):
232 Define "Deflection1D" hypothesis
233 \param d for the deflection
235 hyp = self.Hypothesis("Deflection1D", [d])
239 def Propagation(self):
241 Define "Propagation" hypothesis that propagate all other hypothesis on all others edges that are in
242 the opposite side in the case of quadrangular faces
244 return self.Hypothesis("Propagation")
246 def AutomaticLength(self, fineness=0):
248 Define "AutomaticLength" hypothesis
249 \param fineness for the fineness [0-1]
251 hyp = self.Hypothesis("AutomaticLength")
252 hyp.SetFineness( fineness )
255 def QuadraticMesh(self):
257 Define "QuadraticMesh" hypothesis, forcing construction of quadratic edges.
258 If the 2D mesher sees that all boundary edges are quadratic ones,
259 it generates quadratic faces, else it generates linear faces using
260 medium nodes as if they were vertex ones.
261 The 3D mesher generates quadratic volumes only if all boundary faces
262 are quadratic ones, else it fails.
264 hyp = self.Hypothesis("QuadraticMesh")
267 # Public class: Mesh_Segment_Python
268 # ---------------------------------
270 class Mesh_Segment_Python(Mesh_Segment):
272 Class to define a segment 1D algorithm for discretization with python function
275 def __init__(self, mesh, geom=0):
279 import Python1dPlugin
280 self.Create(mesh, geom, "Python_1D", "libPython1dEngine.so")
282 def PythonSplit1D(self, n, func):
284 Define "PythonSplit1D" hypothesis based on the Erwan Adam patch, awaiting equivalent SALOME functionality
285 \param n for the number of segments that cut an edge
286 \param func for the python function that calculate the length of all segments
288 hyp = self.Hypothesis("PythonSplit1D", [n], "libPython1dEngine.so")
289 hyp.SetNumberOfSegments(n)
290 hyp.SetPythonLog10RatioFunction(func)
293 # Public class: Mesh_Triangle
294 # ---------------------------
296 class Mesh_Triangle(Mesh_Algorithm):
298 Class to define a triangle 2D algorithm
301 def __init__(self, mesh, geom=0):
305 self.Create(mesh, geom, "MEFISTO_2D")
307 def MaxElementArea(self, area):
309 Define "MaxElementArea" hypothesis to give the maximun area of each triangles
310 \param area for the maximum area of each triangles
312 hyp = self.Hypothesis("MaxElementArea", [area])
313 hyp.SetMaxElementArea(area)
316 def LengthFromEdges(self):
318 Define "LengthFromEdges" hypothesis to build triangles based on the length of the edges taken from the wire
320 return self.Hypothesis("LengthFromEdges")
322 # Public class: Mesh_Quadrangle
323 # -----------------------------
325 class Mesh_Quadrangle(Mesh_Algorithm):
327 Class to define a quadrangle 2D algorithm
330 def __init__(self, mesh, geom=0):
334 self.Create(mesh, geom, "Quadrangle_2D")
336 def QuadranglePreference(self):
338 Define "QuadranglePreference" hypothesis, forcing construction
339 of quadrangles if the number of nodes on opposite edges is not the same
340 in the case where the global number of nodes on edges is even
342 hyp = self.Hypothesis("QuadranglePreference")
345 # Public class: Mesh_Tetrahedron
346 # ------------------------------
348 class Mesh_Tetrahedron(Mesh_Algorithm):
350 Class to define a tetrahedron 3D algorithm
353 def __init__(self, mesh, algo, geom=0):
358 self.Create(mesh, geom, "NETGEN_3D", "libNETGENEngine.so")
361 self.Create(mesh, geom, "GHS3D_3D" , "libGHS3DEngine.so")
363 def MaxElementVolume(self, vol):
365 Define "MaxElementVolume" hypothesis to give the maximun volume of each tetrahedral
366 \param vol for the maximum volume of each tetrahedral
368 hyp = self.Hypothesis("MaxElementVolume", [vol])
369 hyp.SetMaxElementVolume(vol)
372 # Public class: Mesh_Hexahedron
373 # ------------------------------
375 class Mesh_Hexahedron(Mesh_Algorithm):
377 Class to define a hexahedron 3D algorithm
380 def __init__(self, mesh, geom=0):
384 self.Create(mesh, geom, "Hexa_3D")
386 # Public class: Mesh_Netgen
387 # ------------------------------
389 class Mesh_Netgen(Mesh_Algorithm):
391 Class to define a NETGEN-based 2D or 3D algorithm
392 that need no discrete boundary (i.e. independent)
397 def __init__(self, mesh, is3D, geom=0):
403 self.Create(mesh, geom, "NETGEN_2D3D", "libNETGENEngine.so")
405 self.Create(mesh, geom, "NETGEN_2D", "libNETGENEngine.so")
407 def Parameters(self):
409 Define hypothesis containing parameters of the algorithm
412 hyp = self.Hypothesis("NETGEN_Parameters", [], "libNETGENEngine.so")
414 hyp = self.Hypothesis("NETGEN_Parameters_2D", [], "libNETGENEngine.so")
422 Class to define a mesh
428 def __init__(self, geom, name=0):
432 Creates mesh on the shape \a geom,
433 sets GUI name of this mesh to \a name.
434 \param geom Shape to be meshed
435 \param name Study name of the mesh
438 self.mesh = smesh.CreateMesh(geom)
440 SetName(self.mesh, GetName(geom))
442 SetName(self.mesh, name)
446 Method that returns the mesh
452 Method that returns the shape associated to the mesh
456 def MeshDimension(self):
458 Returns mesh dimension depending on shape one
460 shells = geompy.SubShapeAllIDs( self.geom, geompy.ShapeType["SHELL"] )
461 if len( shells ) > 0 :
463 elif geompy.NumberOfFaces( self.geom ) > 0 :
465 elif geompy.NumberOfEdges( self.geom ) > 0 :
471 def Segment(self, algo=REGULAR, geom=0):
473 Creates a segment discretization 1D algorithm.
474 If the optional \a algo parameter is not sets, this algorithm is REGULAR.
475 If the optional \a geom parameter is not sets, this algorithm is global.
476 Otherwise, this algorithm define a submesh based on \a geom subshape.
477 \param algo values are smesh.REGULAR or smesh.PYTHON for discretization via python function
478 \param geom If defined, subshape to be meshed
480 ## if Segment(geom) is called by mistake
481 if ( isinstance( algo, geompy.GEOM._objref_GEOM_Object)):
482 algo, geom = geom, algo
485 return Mesh_Segment(self, geom)
487 return Mesh_Segment_Python(self, geom)
489 return Mesh_Segment(self, geom)
491 def Triangle(self, geom=0):
493 Creates a triangle 2D algorithm for faces.
494 If the optional \a geom parameter is not sets, this algorithm is global.
495 Otherwise, this algorithm define a submesh based on \a geom subshape.
496 \param geom If defined, subshape to be meshed
498 return Mesh_Triangle(self, geom)
500 def Quadrangle(self, geom=0):
502 Creates a quadrangle 2D algorithm for faces.
503 If the optional \a geom parameter is not sets, this algorithm is global.
504 Otherwise, this algorithm define a submesh based on \a geom subshape.
505 \param geom If defined, subshape to be meshed
507 return Mesh_Quadrangle(self, geom)
509 def Tetrahedron(self, algo, geom=0):
511 Creates a tetrahedron 3D algorithm for solids.
512 The parameter \a algo permits to choice the algorithm: NETGEN or GHS3D
513 If the optional \a geom parameter is not sets, this algorithm is global.
514 Otherwise, this algorithm define a submesh based on \a geom subshape.
515 \param algo values are: smesh.NETGEN, smesh.GHS3D
516 \param geom If defined, subshape to be meshed
518 ## if Tetrahedron(geom) is called by mistake
519 if ( isinstance( algo, geompy.GEOM._objref_GEOM_Object)):
520 algo, geom = geom, algo
522 return Mesh_Tetrahedron(self, algo, geom)
524 def Hexahedron(self, geom=0):
526 Creates a hexahedron 3D algorithm for solids.
527 If the optional \a geom parameter is not sets, this algorithm is global.
528 Otherwise, this algorithm define a submesh based on \a geom subshape.
529 \param geom If defined, subshape to be meshed
531 return Mesh_Hexahedron(self, geom)
533 def Netgen(self, is3D, geom=0):
535 Creates a NETGEN-based 2D or 3D independent algorithm (i.e. needs no
537 If the optional \a geom parameter is not sets, this algorithm is global.
538 Otherwise, this algorithm defines a submesh based on \a geom subshape.
539 \param is3D If 0 then algorithm is 2D, otherwise 3D
540 \param geom If defined, subshape to be meshed
542 return Mesh_Netgen(self, is3D, geom)
546 Compute the mesh and return the status of the computation
548 ok = smesh.Compute(self.mesh, self.geom)
550 errors = smesh.GetAlgoState( self.mesh, self.geom )
558 dim = str(err.algoDim)
559 if err.name == SMESH.MISSING_ALGO:
560 reason = glob + dim + "D algorithm is missing"
561 elif err.name == SMESH.MISSING_HYPO:
562 name = '"' + err.algoName + '"'
563 reason = glob + dim + "D algorithm " + name + " misses " + dim + "D hypothesis"
565 reason = "Global \"Not Conform mesh allowed\" hypothesis is missing"
573 print '"' + GetName(self.mesh) + '"',"not computed:"
577 if salome.sg.hasDesktop():
578 smeshgui = salome.ImportComponentGUI("SMESH")
579 smeshgui.Init(salome.myStudyId)
580 smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), ok )
581 salome.sg.updateObjBrowser(1)
585 def AutomaticTetrahedralization(self, fineness=0):
587 Compute tetrahedral mesh using AutomaticLength + MEFISTO + NETGEN
588 The parameter \a fineness [0.-1.] defines mesh fineness
590 dim = self.MeshDimension()
592 self.RemoveGlobalHypotheses()
593 self.Segment().AutomaticLength(fineness)
595 self.Triangle().LengthFromEdges()
598 self.Tetrahedron(NETGEN)
600 return self.Compute()
602 def AutomaticHexahedralization(self, fineness=0):
604 Compute hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
605 The parameter \a fineness [0.-1.] defines mesh fineness
607 dim = self.MeshDimension()
609 self.RemoveGlobalHypotheses()
610 self.Segment().AutomaticLength(fineness)
617 return self.Compute()
619 def RemoveGlobalHypotheses(self):
621 Removes all global hypotheses
623 current_hyps = self.mesh.GetHypothesisList( self.geom )
624 for hyp in current_hyps:
625 self.mesh.RemoveHypothesis( self.geom, hyp )
629 def Group(self, grp, name=""):
631 Create a mesh group based on geometric object \a grp
632 and give a \a name, if this parameter is not defined
633 the name is the same as the geometric group name
634 \param grp is a geometric group, a vertex, an edge, a face or a solid
635 \param name is the name of the mesh group
641 tgeo = str(grp.GetShapeType())
648 elif tgeo == "SOLID":
650 elif tgeo == "SHELL":
652 elif tgeo == "COMPOUND":
653 if len( geompy.GetObjectIDs( grp )) == 0:
654 print "Mesh.Group: empty geometric group", GetName( grp )
656 tgeo = geompy.GetType(grp)
657 if tgeo == geompy.ShapeType["VERTEX"]:
659 elif tgeo == geompy.ShapeType["EDGE"]:
661 elif tgeo == geompy.ShapeType["FACE"]:
663 elif tgeo == geompy.ShapeType["SOLID"]:
667 print "Mesh.Group: bad first argument: expected a group, a vertex, an edge, a face or a solid"
670 return self.mesh.CreateGroupFromGEOM(type, name, grp)
672 def ExportToMED(self, f, version, opt=0):
674 Export the mesh in a file with the MED format and choice the \a version of MED format
675 \param f is the file name
676 \param version values are SMESH.MED_V2_1, SMESH.MED_V2_2
678 self.mesh.ExportToMED(f, opt, version)
680 def ExportMED(self, f, opt=0):
682 Export the mesh in a file with the MED format
683 \param f is the file name
685 self.mesh.ExportMED(f, opt)
687 def ExportDAT(self, f):
689 Export the mesh in a file with the DAT format
690 \param f is the file name
692 self.mesh.ExportDAT(f)
694 def ExportUNV(self, f):
696 Export the mesh in a file with the UNV format
697 \param f is the file name
699 self.mesh.ExportUNV(f)
701 def ExportSTL(self, f, ascii=1):
703 Export the mesh in a file with the STL format
704 \param f is the file name
705 \param ascii defined the kind of file contents
707 self.mesh.ExportSTL(f, ascii)