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)
64 attr = sobj.FindAttribute("AttributeName")[1]
67 # Algorithms and hypothesis
68 # =========================
70 # Private class: Mesh_Algorithm
71 # -----------------------------
75 Mother class to define algorithm, recommended to don't use directly
85 If the algorithm is global, return 0
86 else return the submesh associated to this algorithm
90 def GetAlgorithm(self):
92 Return the wrapped mesher
96 def TreatHypoStatus(self, status, hypName, geomName, isAlgo):
98 Private method. Print error message if a hypothesis was not assigned
101 hypType = "algorithm"
103 hypType = "hypothesis"
104 if status == SMESH.HYP_UNKNOWN_FATAL :
105 reason = "for unknown reason"
106 elif status == SMESH.HYP_INCOMPATIBLE :
107 reason = "this hypothesis mismatches algorithm"
108 elif status == SMESH.HYP_NOTCONFORM :
109 reason = "not conform mesh would be built"
110 elif status == SMESH.HYP_ALREADY_EXIST :
111 reason = hypType + " of the same dimension already assigned to this shape"
112 elif status == SMESH.HYP_BAD_DIM :
113 reason = hypType + " mismatches shape"
114 elif status == SMESH.HYP_CONCURENT :
115 reason = "there are concurrent hypotheses on sub-shapes"
116 elif status == SMESH.HYP_BAD_SUBSHAPE :
117 reason = "shape is neither the main one, nor its subshape, nor a valid group"
120 hypName = '"' + hypName + '"'
121 geomName= '"' + geomName+ '"'
122 if status < SMESH.HYP_UNKNOWN_FATAL:
123 print hypName, "was assigned to", geomName,"but", reason
125 print hypName, "was not assigned to",geomName,":", reason
128 def Create(self, mesh, geom, hypo, so="libStdMeshersEngine.so"):
133 raise RuntimeError, "Attemp to create " + hypo + " algoritm on None shape"
138 name = GetName(piece)
143 name = geompy.SubShapeName(geom, piece)
144 geompy.addToStudyInFather(piece, geom, name)
145 self.subm = mesh.mesh.GetSubMesh(geom, hypo)
147 self.algo = smesh.CreateHypothesis(hypo, so)
148 SetName(self.algo, name + "/" + hypo)
149 status = mesh.mesh.AddHypothesis(self.geom, self.algo)
150 self.TreatHypoStatus( status, hypo, name, 1 )
152 def Hypothesis(self, hyp, args=[], so="libStdMeshersEngine.so"):
156 hypo = smesh.CreateHypothesis(hyp, so)
162 a = a + s + str(args[i])
165 name = GetName(self.geom)
166 SetName(hypo, name + "/" + hyp + a)
167 status = self.mesh.mesh.AddHypothesis(self.geom, hypo)
168 self.TreatHypoStatus( status, hyp, name, 0 )
171 # Public class: Mesh_Segment
172 # --------------------------
174 class Mesh_Segment(Mesh_Algorithm):
176 Class to define a segment 1D algorithm for discretization
179 def __init__(self, mesh, geom=0):
183 self.Create(mesh, geom, "Regular_1D")
185 def LocalLength(self, l):
187 Define "LocalLength" hypothesis to cut an edge in several segments with the same length
188 \param l for the length of segments that cut an edge
190 hyp = self.Hypothesis("LocalLength", [l])
194 def NumberOfSegments(self, n, s=[]):
196 Define "NumberOfSegments" hypothesis to cut an edge in several fixed number of segments
197 \param n for the number of segments that cut an edge
198 \param s for the scale factor (optional)
201 hyp = self.Hypothesis("NumberOfSegments", [n])
203 hyp = self.Hypothesis("NumberOfSegments", [n,s])
204 hyp.SetDistrType( 1 )
205 hyp.SetScaleFactor(s)
206 hyp.SetNumberOfSegments(n)
209 def Arithmetic1D(self, start, end):
211 Define "Arithmetic1D" hypothesis to cut an edge in several segments with arithmetic length increasing
212 \param start for the length of the first segment
213 \param end for the length of the last segment
215 hyp = self.Hypothesis("Arithmetic1D", [start, end])
216 hyp.SetLength(start, 1)
217 hyp.SetLength(end , 0)
220 def StartEndLength(self, start, end):
222 Define "StartEndLength" hypothesis to cut an edge in several segments with geometric length increasing
223 \param start for the length of the first segment
224 \param end for the length of the last segment
226 hyp = self.Hypothesis("StartEndLength", [start, end])
227 hyp.SetLength(start, 1)
228 hyp.SetLength(end , 0)
231 def Deflection1D(self, d):
233 Define "Deflection1D" hypothesis
234 \param d for the deflection
236 hyp = self.Hypothesis("Deflection1D", [d])
240 def Propagation(self):
242 Define "Propagation" hypothesis that propagate all other hypothesis on all others edges that are in
243 the opposite side in the case of quadrangular faces
245 return self.Hypothesis("Propagation")
247 def AutomaticLength(self, fineness=0):
249 Define "AutomaticLength" hypothesis
250 \param fineness for the fineness [0-1]
252 hyp = self.Hypothesis("AutomaticLength")
253 hyp.SetFineness( fineness )
256 def QuadraticMesh(self):
258 Define "QuadraticMesh" hypothesis, forcing construction of quadratic edges.
259 If the 2D mesher sees that all boundary edges are quadratic ones,
260 it generates quadratic faces, else it generates linear faces using
261 medium nodes as if they were vertex ones.
262 The 3D mesher generates quadratic volumes only if all boundary faces
263 are quadratic ones, else it fails.
265 hyp = self.Hypothesis("QuadraticMesh")
268 # Public class: Mesh_Segment_Python
269 # ---------------------------------
271 class Mesh_Segment_Python(Mesh_Segment):
273 Class to define a segment 1D algorithm for discretization with python function
276 def __init__(self, mesh, geom=0):
280 import Python1dPlugin
281 self.Create(mesh, geom, "Python_1D", "libPython1dEngine.so")
283 def PythonSplit1D(self, n, func):
285 Define "PythonSplit1D" hypothesis based on the Erwan Adam patch, awaiting equivalent SALOME functionality
286 \param n for the number of segments that cut an edge
287 \param func for the python function that calculate the length of all segments
289 hyp = self.Hypothesis("PythonSplit1D", [n], "libPython1dEngine.so")
290 hyp.SetNumberOfSegments(n)
291 hyp.SetPythonLog10RatioFunction(func)
294 # Public class: Mesh_Triangle
295 # ---------------------------
297 class Mesh_Triangle(Mesh_Algorithm):
299 Class to define a triangle 2D algorithm
302 def __init__(self, mesh, geom=0):
306 self.Create(mesh, geom, "MEFISTO_2D")
308 def MaxElementArea(self, area):
310 Define "MaxElementArea" hypothesis to give the maximun area of each triangles
311 \param area for the maximum area of each triangles
313 hyp = self.Hypothesis("MaxElementArea", [area])
314 hyp.SetMaxElementArea(area)
317 def LengthFromEdges(self):
319 Define "LengthFromEdges" hypothesis to build triangles based on the length of the edges taken from the wire
321 return self.Hypothesis("LengthFromEdges")
323 # Public class: Mesh_Quadrangle
324 # -----------------------------
326 class Mesh_Quadrangle(Mesh_Algorithm):
328 Class to define a quadrangle 2D algorithm
331 def __init__(self, mesh, geom=0):
335 self.Create(mesh, geom, "Quadrangle_2D")
337 def QuadranglePreference(self):
339 Define "QuadranglePreference" hypothesis, forcing construction
340 of quadrangles if the number of nodes on opposite edges is not the same
341 in the case where the global number of nodes on edges is even
343 hyp = self.Hypothesis("QuadranglePreference")
346 # Public class: Mesh_Tetrahedron
347 # ------------------------------
349 class Mesh_Tetrahedron(Mesh_Algorithm):
351 Class to define a tetrahedron 3D algorithm
354 def __init__(self, mesh, algo, geom=0):
359 self.Create(mesh, geom, "NETGEN_3D", "libNETGENEngine.so")
362 self.Create(mesh, geom, "GHS3D_3D" , "libGHS3DEngine.so")
364 def MaxElementVolume(self, vol):
366 Define "MaxElementVolume" hypothesis to give the maximun volume of each tetrahedral
367 \param vol for the maximum volume of each tetrahedral
369 hyp = self.Hypothesis("MaxElementVolume", [vol])
370 hyp.SetMaxElementVolume(vol)
373 # Public class: Mesh_Hexahedron
374 # ------------------------------
376 class Mesh_Hexahedron(Mesh_Algorithm):
378 Class to define a hexahedron 3D algorithm
381 def __init__(self, mesh, geom=0):
385 self.Create(mesh, geom, "Hexa_3D")
387 # Public class: Mesh_Netgen
388 # ------------------------------
390 class Mesh_Netgen(Mesh_Algorithm):
392 Class to define a NETGEN-based 2D or 3D algorithm
393 that need no discrete boundary (i.e. independent)
398 def __init__(self, mesh, is3D, geom=0):
404 self.Create(mesh, geom, "NETGEN_2D3D", "libNETGENEngine.so")
406 self.Create(mesh, geom, "NETGEN_2D", "libNETGENEngine.so")
408 def Parameters(self):
410 Define hypothesis containing parameters of the algorithm
413 hyp = self.Hypothesis("NETGEN_Parameters", [], "libNETGENEngine.so")
415 hyp = self.Hypothesis("NETGEN_Parameters_2D", [], "libNETGENEngine.so")
423 Class to define a mesh
429 def __init__(self, geom, name=0):
433 Creates mesh on the shape \a geom,
434 sets GUI name of this mesh to \a name.
435 \param geom Shape to be meshed
436 \param name Study name of the mesh
439 self.mesh = smesh.CreateMesh(geom)
441 SetName(self.mesh, GetName(geom))
443 SetName(self.mesh, name)
447 Method that returns the mesh
453 Method that returns the shape associated to the mesh
457 def MeshDimension(self):
459 Returns mesh dimension depending on shape one
461 shells = geompy.SubShapeAllIDs( self.geom, geompy.ShapeType["SHELL"] )
462 if len( shells ) > 0 :
464 elif geompy.NumberOfFaces( self.geom ) > 0 :
466 elif geompy.NumberOfEdges( self.geom ) > 0 :
472 def Segment(self, algo=REGULAR, geom=0):
474 Creates a segment discretization 1D algorithm.
475 If the optional \a algo parameter is not sets, this algorithm is REGULAR.
476 If the optional \a geom parameter is not sets, this algorithm is global.
477 Otherwise, this algorithm define a submesh based on \a geom subshape.
478 \param algo values are smesh.REGULAR or smesh.PYTHON for discretization via python function
479 \param geom If defined, subshape to be meshed
481 ## if Segment(geom) is called by mistake
482 if ( isinstance( algo, geompy.GEOM._objref_GEOM_Object)):
483 algo, geom = geom, algo
486 return Mesh_Segment(self, geom)
488 return Mesh_Segment_Python(self, geom)
490 return Mesh_Segment(self, geom)
492 def Triangle(self, geom=0):
494 Creates a triangle 2D algorithm for faces.
495 If the optional \a geom parameter is not sets, this algorithm is global.
496 Otherwise, this algorithm define a submesh based on \a geom subshape.
497 \param geom If defined, subshape to be meshed
499 return Mesh_Triangle(self, geom)
501 def Quadrangle(self, geom=0):
503 Creates a quadrangle 2D algorithm for faces.
504 If the optional \a geom parameter is not sets, this algorithm is global.
505 Otherwise, this algorithm define a submesh based on \a geom subshape.
506 \param geom If defined, subshape to be meshed
508 return Mesh_Quadrangle(self, geom)
510 def Tetrahedron(self, algo, geom=0):
512 Creates a tetrahedron 3D algorithm for solids.
513 The parameter \a algo permits to choice the algorithm: NETGEN or GHS3D
514 If the optional \a geom parameter is not sets, this algorithm is global.
515 Otherwise, this algorithm define a submesh based on \a geom subshape.
516 \param algo values are: smesh.NETGEN, smesh.GHS3D
517 \param geom If defined, subshape to be meshed
519 ## if Tetrahedron(geom) is called by mistake
520 if ( isinstance( algo, geompy.GEOM._objref_GEOM_Object)):
521 algo, geom = geom, algo
523 return Mesh_Tetrahedron(self, algo, geom)
525 def Hexahedron(self, geom=0):
527 Creates a hexahedron 3D algorithm for solids.
528 If the optional \a geom parameter is not sets, this algorithm is global.
529 Otherwise, this algorithm define a submesh based on \a geom subshape.
530 \param geom If defined, subshape to be meshed
532 return Mesh_Hexahedron(self, geom)
534 def Netgen(self, is3D, geom=0):
536 Creates a NETGEN-based 2D or 3D independent algorithm (i.e. needs no
538 If the optional \a geom parameter is not sets, this algorithm is global.
539 Otherwise, this algorithm defines a submesh based on \a geom subshape.
540 \param is3D If 0 then algorithm is 2D, otherwise 3D
541 \param geom If defined, subshape to be meshed
543 return Mesh_Netgen(self, is3D, geom)
547 Compute the mesh and return the status of the computation
549 ok = smesh.Compute(self.mesh, self.geom)
551 errors = smesh.GetAlgoState( self.mesh, self.geom )
559 dim = str(err.algoDim)
560 if err.name == SMESH.MISSING_ALGO:
561 reason = glob + dim + "D algorithm is missing"
562 elif err.name == SMESH.MISSING_HYPO:
563 name = '"' + err.algoName + '"'
564 reason = glob + dim + "D algorithm " + name + " misses " + dim + "D hypothesis"
566 reason = "Global \"Not Conform mesh allowed\" hypothesis is missing"
574 print '"' + GetName(self.mesh) + '"',"not computed:"
578 if salome.sg.hasDesktop():
579 smeshgui = salome.ImportComponentGUI("SMESH")
580 smeshgui.Init(salome.myStudyId)
581 smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), ok )
582 salome.sg.updateObjBrowser(1)
586 def AutomaticTetrahedralization(self, fineness=0):
588 Compute tetrahedral mesh using AutomaticLength + MEFISTO + NETGEN
589 The parameter \a fineness [0.-1.] defines mesh fineness
591 dim = self.MeshDimension()
593 self.RemoveGlobalHypotheses()
594 self.Segment().AutomaticLength(fineness)
596 self.Triangle().LengthFromEdges()
599 self.Tetrahedron(NETGEN)
601 return self.Compute()
603 def AutomaticHexahedralization(self, fineness=0):
605 Compute hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
606 The parameter \a fineness [0.-1.] defines mesh fineness
608 dim = self.MeshDimension()
610 self.RemoveGlobalHypotheses()
611 self.Segment().AutomaticLength(fineness)
618 return self.Compute()
620 def RemoveGlobalHypotheses(self):
622 Removes all global hypotheses
624 current_hyps = self.mesh.GetHypothesisList( self.geom )
625 for hyp in current_hyps:
626 self.mesh.RemoveHypothesis( self.geom, hyp )
630 def Group(self, grp, name=""):
632 Create a mesh group based on geometric object \a grp
633 and give a \a name, if this parameter is not defined
634 the name is the same as the geometric group name
635 \param grp is a geometric group, a vertex, an edge, a face or a solid
636 \param name is the name of the mesh group
642 tgeo = str(grp.GetShapeType())
649 elif tgeo == "SOLID":
651 elif tgeo == "SHELL":
653 elif tgeo == "COMPOUND":
654 if len( geompy.GetObjectIDs( grp )) == 0:
655 print "Mesh.Group: empty geometric group", GetName( grp )
657 tgeo = geompy.GetType(grp)
658 if tgeo == geompy.ShapeType["VERTEX"]:
660 elif tgeo == geompy.ShapeType["EDGE"]:
662 elif tgeo == geompy.ShapeType["FACE"]:
664 elif tgeo == geompy.ShapeType["SOLID"]:
668 print "Mesh.Group: bad first argument: expected a group, a vertex, an edge, a face or a solid"
671 return self.mesh.CreateGroupFromGEOM(type, name, grp)
673 def ExportToMED(self, f, version, opt=0):
675 Export the mesh in a file with the MED format and choice the \a version of MED format
676 \param f is the file name
677 \param version values are SMESH.MED_V2_1, SMESH.MED_V2_2
679 self.mesh.ExportToMED(f, opt, version)
681 def ExportMED(self, f, opt=0):
683 Export the mesh in a file with the MED format
684 \param f is the file name
686 self.mesh.ExportMED(f, opt)
688 def ExportDAT(self, f):
690 Export the mesh in a file with the DAT format
691 \param f is the file name
693 self.mesh.ExportDAT(f)
695 def ExportUNV(self, f):
697 Export the mesh in a file with the UNV format
698 \param f is the file name
700 self.mesh.ExportUNV(f)
702 def ExportSTL(self, f, ascii=1):
704 Export the mesh in a file with the STL format
705 \param f is the file name
706 \param ascii defined the kind of file contents
708 self.mesh.ExportSTL(f, ascii)