Salome HOME
71051056f0a986e1ab2f58e64e7bb2dec6585513
[modules/smesh.git] / src / SMESH_SWIG / smesh.py
1 #  Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 #  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 #
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.
8 #
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.
13 #
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
17 #
18 #  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
19 #
20 #  File   : smesh.py
21 #  Author : Francis KLOSS, OCC
22 #  Module : SMESH
23
24 """
25  \namespace smesh
26  \brief Module smesh
27 """
28
29 import salome
30 import geompy
31 import StdMeshers
32 import SMESH
33
34 # Public variables
35 # ----------------
36
37 REGULAR = 1
38 PYTHON  = 2
39
40 NETGEN  = 3
41 GHS3D   = 4
42
43 smesh = salome.lcc.FindOrLoadComponent("FactoryServer", "SMESH")
44 smesh.SetCurrentStudy(salome.myStudy)
45
46 # Private functions
47 # -----------------
48
49 NO_NAME = "NoName"
50
51 def GetName(obj):
52     ior  = salome.orb.object_to_string(obj)
53     sobj = salome.myStudy.FindObjectIOR(ior)
54     if sobj is None:
55         return NO_NAME
56     else:
57         attr = sobj.FindAttribute("AttributeName")[1]
58         return attr.Value()
59
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]
64     attr.SetValue(name)
65
66 # Algorithms and hypothesis
67 # =========================
68
69 # Private class: Mesh_Algorithm
70 # -----------------------------
71
72 class Mesh_Algorithm:
73     """
74     Mother class to define algorithm, recommended to don't use directly
75     """
76
77     mesh = 0
78     geom = 0
79     subm = 0
80     algo = 0
81
82     def GetSubMesh(self):
83         """
84          If the algorithm is global, return 0
85          else return the submesh associated to this algorithm
86         """
87         return self.subm
88
89     def GetAlgorithm(self):
90         """
91          Return the wrapped mesher
92         """
93         return self.algo
94
95     def Create(self, mesh, geom, hypo, so="libStdMeshersEngine.so"):
96         """
97          Private method
98         """
99         self.mesh = mesh
100         piece = mesh.geom
101         if geom==0:
102             self.geom = piece
103             name = GetName(piece)
104         else:
105             self.geom = geom
106             name = GetName(geom)
107             if name==NO_NAME:
108                 name = geompy.SubShapeName(geom, piece)
109                 geompy.addToStudyInFather(piece, geom, name)
110             self.subm = mesh.mesh.GetSubMesh(geom, hypo)
111
112         self.algo = smesh.CreateHypothesis(hypo, so)
113         SetName(self.algo, name + "/" + hypo)
114         mesh.mesh.AddHypothesis(self.geom, self.algo)
115
116     def Hypothesis(self, hyp, args=[], so="libStdMeshersEngine.so"):
117         """
118          Private method
119         """
120         hypo = smesh.CreateHypothesis(hyp, so)
121         a = ""
122         s = "="
123         i = 0
124         n = len(args)
125         while i<n:
126             a = a + s + str(args[i])
127             s = ","
128             i = i + 1
129         SetName(hypo, GetName(self.geom) + "/" + hyp + a)
130         self.mesh.mesh.AddHypothesis(self.geom, hypo)
131         return hypo
132
133 # Public class: Mesh_Segment
134 # --------------------------
135
136 class Mesh_Segment(Mesh_Algorithm):
137     """
138     Class to define a segment 1D algorithm for discretization
139     """
140
141     def __init__(self, mesh, geom=0):
142         """
143          Private constructor
144         """
145         self.Create(mesh, geom, "Regular_1D")
146
147     def LocalLength(self, l):
148         """
149          Define "LocalLength" hypothesis to cut an edge in several segments with the same length
150          \param l for the length of segments that cut an edge
151         """
152         hyp = self.Hypothesis("LocalLength", [l])
153         hyp.SetLength(l)
154         return hyp
155
156     def NumberOfSegments(self, n, s=[]):
157         """
158          Define "NumberOfSegments" hypothesis to cut an edge in several fixed number of segments
159          \param n for the number of segments that cut an edge
160          \param s for the scale factor (optional)
161         """
162         if s == []:
163             hyp = self.Hypothesis("NumberOfSegments", [n])
164         else:
165             hyp = self.Hypothesis("NumberOfSegments", [n,s])
166             hyp.SetDistrType( 1 )
167             hyp.SetScaleFactor(s)
168         hyp.SetNumberOfSegments(n)
169         return hyp
170
171     def Arithmetic1D(self, start, end):
172         """
173          Define "Arithmetic1D" hypothesis to cut an edge in several segments with arithmetic length increasing
174          \param start for the length of the first segment
175          \param end   for the length of the last  segment
176         """
177         hyp = self.Hypothesis("Arithmetic1D", [start, end])
178         hyp.SetLength(start, 1)
179         hyp.SetLength(end  , 0)
180         return hyp
181
182     def StartEndLength(self, start, end):
183         """
184          Define "StartEndLength" hypothesis to cut an edge in several segments with geometric length increasing
185          \param start for the length of the first segment
186          \param end   for the length of the last  segment
187         """
188         hyp = self.Hypothesis("StartEndLength", [start, end])
189         hyp.SetLength(start, 1)
190         hyp.SetLength(end  , 0)
191         return hyp
192
193     def Deflection1D(self, d):
194         """
195          Define "Deflection1D" hypothesis
196          \param d for the deflection
197         """
198         hyp = self.Hypothesis("Deflection1D", [d])
199         hyp.SetDeflection(d)
200         return hyp
201
202     def Propagation(self):
203         """
204          Define "Propagation" hypothesis that propagate all other hypothesis on all others edges that are in
205          the opposite side in the case of quadrangular faces
206         """
207         return self.Hypothesis("Propagation")
208
209     def AutomaticLength(self, fineness):
210         """
211          Define "AutomaticLength" hypothesis
212          \param fineness for the fineness [0-1]
213         """
214         hyp = self.Hypothesis("AutomaticLength")
215         hyp.SetFineness( fineness )
216         return hyp
217
218     def QuadraticMesh(self):
219         """
220          Define "QuadraticMesh" hypothesis, forcing construction of quadratic edges.
221          If the 2D mesher sees that all boundary edges are quadratic ones,
222          it generates quadratic faces, else it generates linear faces using
223          medium nodes as if they were vertex ones.
224          The 3D mesher generates quadratic volumes only if all boundary faces
225          are quadratic ones, else it fails.
226         """
227         hyp = self.Hypothesis("QuadraticMesh")
228         return hyp
229
230 # Public class: Mesh_Segment_Python
231 # ---------------------------------
232
233 class Mesh_Segment_Python(Mesh_Segment):
234     """
235     Class to define a segment 1D algorithm for discretization with python function
236     """
237
238     def __init__(self, mesh, geom=0):
239         """
240          Private constructor
241         """
242         import Python1dPlugin
243         self.Create(mesh, geom, "Python_1D", "libPython1dEngine.so")
244
245     def PythonSplit1D(self, n, func):
246         """
247          Define "PythonSplit1D" hypothesis based on the Erwan Adam patch, awaiting equivalent SALOME functionality
248          \param n for the number of segments that cut an edge
249          \param func for the python function that calculate the length of all segments
250         """
251         hyp = self.Hypothesis("PythonSplit1D", [n], "libPython1dEngine.so")
252         hyp.SetNumberOfSegments(n)
253         hyp.SetPythonLog10RatioFunction(func)
254         return hyp
255
256 # Public class: Mesh_Triangle
257 # ---------------------------
258
259 class Mesh_Triangle(Mesh_Algorithm):
260     """
261     Class to define a triangle 2D algorithm
262     """
263
264     def __init__(self, mesh, geom=0):
265         """
266          Private constructor
267         """
268         self.Create(mesh, geom, "MEFISTO_2D")
269
270     def MaxElementArea(self, area):
271         """
272          Define "MaxElementArea" hypothesis to give the maximun area of each triangles
273          \param area for the maximum area of each triangles
274         """
275         hyp = self.Hypothesis("MaxElementArea", [area])
276         hyp.SetMaxElementArea(area)
277         return hyp
278
279     def LengthFromEdges(self):
280         """
281          Define "LengthFromEdges" hypothesis to build triangles based on the length of the edges taken from the wire
282         """
283         return self.Hypothesis("LengthFromEdges")
284
285 # Public class: Mesh_Quadrangle
286 # -----------------------------
287
288 class Mesh_Quadrangle(Mesh_Algorithm):
289     """
290     Class to define a quadrangle 2D algorithm
291     """
292
293     def __init__(self, mesh, geom=0):
294         """
295          Private constructor
296         """
297         self.Create(mesh, geom, "Quadrangle_2D")
298
299     def QuadranglePreference(self):
300         """
301          Define "QuadranglePreference" hypothesis, forcing construction
302          of quadrangles if the number of nodes on opposite edges is not the same
303          in the case where the global number of nodes on edges is even
304         """
305         hyp = self.Hypothesis("QuadranglePreference")
306         return hyp
307
308 # Public class: Mesh_Tetrahedron
309 # ------------------------------
310
311 class Mesh_Tetrahedron(Mesh_Algorithm):
312     """
313     Class to define a tetrahedron 3D algorithm
314     """
315
316     def __init__(self, mesh, algo, geom=0):
317         """
318          Private constructor
319         """
320         if algo == NETGEN:
321             self.Create(mesh, geom, "NETGEN_3D", "libNETGENEngine.so")
322         elif algo == GHS3D:
323             import GHS3DPlugin
324             self.Create(mesh, geom, "GHS3D_3D" , "libGHS3DEngine.so")
325
326     def MaxElementVolume(self, vol):
327         """
328          Define "MaxElementVolume" hypothesis to give the maximun volume of each tetrahedral
329          \param vol for the maximum volume of each tetrahedral
330         """
331         hyp = self.Hypothesis("MaxElementVolume", [vol])
332         hyp.SetMaxElementVolume(vol)
333         return hyp
334
335 # Public class: Mesh_Hexahedron
336 # ------------------------------
337
338 class Mesh_Hexahedron(Mesh_Algorithm):
339     """
340     Class to define a hexahedron 3D algorithm
341     """
342
343     def __init__(self, mesh, geom=0):
344         """
345          Private constructor
346         """
347         self.Create(mesh, geom, "Hexa_3D")
348
349 # Public class: Mesh
350 # ==================
351
352 class Mesh:
353     """
354     Class to define a mesh
355     """
356
357     geom = 0
358     mesh = 0
359
360     def __init__(self, geom, name=0):
361         """
362          Constructor
363
364          Creates mesh on the shape \a geom,
365          sets GUI name of this mesh to \a name.
366          \param geom Shape to be meshed
367          \param name Study name of the mesh
368         """
369         self.geom = geom
370         self.mesh = smesh.CreateMesh(geom)
371         if name == 0:
372             SetName(self.mesh, GetName(geom))
373         else:
374             SetName(self.mesh, name)
375
376     def GetMesh(self):
377         """
378          Method that returns the mesh
379         """
380         return self.mesh
381
382     def GetShape(self):
383         """
384          Method that returns the shape associated to the mesh
385         """
386         return self.geom
387
388     def MeshDimension(self):
389         """
390         Returns mesh dimension depending on shape one
391         """
392         shells = geompy.SubShapeAllIDs( self.geom, geompy.ShapeType["SHELL"] )
393         if len( shells ) > 0 :
394             return 3
395         elif geompy.NumberOfFaces( self.geom ) > 0 :
396             return 2
397         elif geompy.NumberOfEdges( self.geom ) > 0 :
398             return 1
399         else:
400             return 0;
401         pass
402
403     def Segment(self, algo=REGULAR, geom=0):
404         """
405          Creates a segment discretization 1D algorithm.
406          If the optional \a algo parameter is not sets, this algorithm is REGULAR.
407          If the optional \a geom parameter is not sets, this algorithm is global.
408          Otherwise, this algorithm define a submesh based on \a geom subshape.
409          \param algo values are smesh.REGULAR or smesh.PYTHON for discretization via python function
410          \param geom If defined, subshape to be meshed
411         """
412         ## if Segment(geom) is called by mistake
413         if ( isinstance( algo, geompy.GEOM._objref_GEOM_Object)):
414             algo, geom = geom, algo
415             pass
416         if algo == REGULAR:
417             return Mesh_Segment(self, geom)
418         elif algo == PYTHON:
419             return Mesh_Segment_Python(self, geom)
420         else:
421             return Mesh_Segment(self, geom)
422
423     def Triangle(self, geom=0):
424         """
425          Creates a triangle 2D algorithm for faces.
426          If the optional \a geom parameter is not sets, this algorithm is global.
427          Otherwise, this algorithm define a submesh based on \a geom subshape.
428          \param geom If defined, subshape to be meshed
429         """
430         return Mesh_Triangle(self, geom)
431
432     def Quadrangle(self, geom=0):
433         """
434          Creates a quadrangle 2D algorithm for faces.
435          If the optional \a geom parameter is not sets, this algorithm is global.
436          Otherwise, this algorithm define a submesh based on \a geom subshape.
437          \param geom If defined, subshape to be meshed
438         """
439         return Mesh_Quadrangle(self, geom)
440
441     def Tetrahedron(self, algo, geom=0):
442         """
443          Creates a tetrahedron 3D algorithm for solids.
444          The parameter \a algo permits to choice the algorithm: NETGEN or GHS3D
445          If the optional \a geom parameter is not sets, this algorithm is global.
446          Otherwise, this algorithm define a submesh based on \a geom subshape.
447          \param algo values are: smesh.NETGEN, smesh.GHS3D
448          \param geom If defined, subshape to be meshed
449         """
450         ## if Tetrahedron(geom) is called by mistake
451         if ( isinstance( algo, geompy.GEOM._objref_GEOM_Object)):
452             algo, geom = geom, algo
453             pass
454         return Mesh_Tetrahedron(self, algo, geom)
455
456     def Hexahedron(self, geom=0):
457         """
458          Creates a hexahedron 3D algorithm for solids.
459          If the optional \a geom parameter is not sets, this algorithm is global.
460          Otherwise, this algorithm define a submesh based on \a geom subshape.
461          \param geom If defined, subshape to be meshed
462         """
463         return Mesh_Hexahedron(self, geom)
464
465     def Compute(self):
466         """
467          Compute the mesh and return the status of the computation
468         """
469         b = smesh.Compute(self.mesh, self.geom)
470         if salome.sg.hasDesktop():
471             smeshgui = salome.ImportComponentGUI("SMESH")
472             smeshgui.Init(salome.myStudyId)
473             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), b )
474             salome.sg.updateObjBrowser(1)
475         return b
476
477     def AutomaticTetrahedralization(self):
478         """
479         Compute tetrahedral mesh using AutomaticLength + MEFISTO + NETGEN
480         """
481         dim = self.MeshDimension()
482         # assign hypotheses
483         self.RemoveGlobalHypotheses()
484         self.Segment().AutomaticLength()
485         if dim > 1 :
486             self.Triangle().LengthFromEdges()
487             pass
488         if dim > 2 :
489             self.Tetrahedron(NETGEN)
490             pass
491         return self.Compute()
492
493     def AutomaticHexahedralization(self):
494         """
495         Compute hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
496         """
497         dim = self.MeshDimension()
498         # assign hypotheses
499         self.RemoveGlobalHypotheses()
500         self.Segment().AutomaticLength()
501         if dim > 1 :
502             self.Quadrangle()
503             pass
504         if dim > 2 :
505             self.Hexahedron()            
506             pass
507         return self.Compute()
508
509     def RemoveGlobalHypotheses(self):
510         """
511         Removes all global hypotheses
512         """
513         current_hyps = self.mesh.GetHypothesisList( self.geom )
514         for hyp in current_hyps:
515             self.mesh.RemoveHypothesis( self.geom, hyp )
516             pass
517         pass
518
519     def Group(self, grp, name=""):
520         """
521          Create a mesh group based on geometric object \a grp
522          and give a \a name, if this parameter is not defined
523          the name is the same as the geometric group name
524          \param grp  is a geometric group, a vertex, an edge, a face or a solid
525          \param name is the name of the mesh group
526         """
527         if name == "":
528             name = grp.GetName()
529
530         type = []
531         tgeo = str(grp.GetShapeType())
532         if tgeo == "VERTEX":
533             type = SMESH.NODE
534         elif tgeo == "EDGE":
535             type = SMESH.EDGE
536         elif tgeo == "FACE":
537             type = SMESH.FACE
538         elif tgeo == "SOLID":
539             type = SMESH.VOLUME
540         elif tgeo == "SHELL":
541             type = SMESH.VOLUME
542         elif tgeo == "COMPOUND":
543             tgeo = geompy.GetType(grp)
544             if tgeo == geompy.ShapeType["VERTEX"]:
545                 type = SMESH.NODE
546             elif tgeo == geompy.ShapeType["EDGE"]:
547                 type = SMESH.EDGE
548             elif tgeo == geompy.ShapeType["FACE"]:
549                 type = SMESH.FACE
550             elif tgeo == geompy.ShapeType["SOLID"]:
551                 type = SMESH.VOLUME
552
553         if type == []:
554             print "Mesh.Group: bad first argument: expected a group, a vertex, an edge, a face or a solid"
555             return 0
556         else:
557             return self.mesh.CreateGroupFromGEOM(type, name, grp)
558
559     def ExportToMED(self, f, version, opt=0):
560         """
561          Export the mesh in a file with the MED format and choice the \a version of MED format
562          \param f is the file name
563          \param version values are smesh.MED_V2_1, smesh.MED_V2_2
564         """
565         self.mesh.ExportToMED(f, opt, version)
566
567     def ExportMED(self, f, opt=0):
568         """
569          Export the mesh in a file with the MED format
570          \param f is the file name
571         """
572         self.mesh.ExportMED(f, opt)
573
574     def ExportDAT(self, f):
575         """
576          Export the mesh in a file with the DAT format
577          \param f is the file name
578         """
579         self.mesh.ExportDAT(f)
580
581     def ExportUNV(self, f):
582         """
583          Export the mesh in a file with the UNV format
584          \param f is the file name
585         """
586         self.mesh.ExportUNV(f)
587
588     def ExportSTL(self, f, ascii=1):
589         """
590          Export the mesh in a file with the STL format
591          \param f is the file name
592          \param ascii defined the kind of file contents
593         """
594         self.mesh.ExportSTL(f, ascii)