Salome HOME
PR: distributed geom and smesh scripts: first step
[modules/smesh.git] / src / SMESH_SWIG / smesh_algorithm.py
1 # Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
2 #
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU Lesser General Public
5 # License as published by the Free Software Foundation; either
6 # version 2.1 of the License.
7 #
8 # This library is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 # Lesser General Public License for more details.
12 #
13 # You should have received a copy of the GNU Lesser General Public
14 # License along with this library; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 #
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 #
19
20 ## @package smesh_algorithm
21 #  Python API for base Mesh_Algorithm class.
22 #  This package is a part of SALOME %Mesh module Python API
23
24 import salome
25 import geompyDC
26 import SMESH
27
28 ## The base class to define meshing algorithms
29 #
30 #  @note This class should not be used directly, it is supposed to be sub-classed
31 #  for implementing Python API for specific meshing algorithms
32 #
33 #  For each meshing algorithm, a python class inheriting from class %Mesh_Algorithm
34 #  should be defined. This descendant class should have two attributes defining the way
35 #  it is created by class Mesh (see e.g. class @ref StdMeshersDC.StdMeshersDC_Segment "StdMeshersDC_Segment"
36 #  in StdMeshersDC package):
37 #  - @c meshMethod attribute defines name of method of class smesh.Mesh by calling which the
38 #    python class of algorithm is created; this method is dynamically added to the smesh.Mesh class
39 #    in runtime. For example, if in @c class MyPlugin_Algorithm this attribute is defined as
40 #    @code
41 #    meshMethod = "MyAlgorithm"
42 #    @endcode
43 #    then an instance of @c MyPlugin_Algorithm can be created by the direct invokation of the function
44 #    of smesh.Mesh class:
45 #    @code
46 #    my_algo = mesh.MyAlgorithm()
47 #    @endcode
48 #  - @c algoType defines type of algorithm and is used mostly to discriminate
49 #    algorithms that are created by the same method of class smesh.Mesh. For example, if this attribute
50 #    is specified in @c MyPlugin_Algorithm class as
51 #    @code
52 #    algoType = "MyPLUGIN"
53 #    @endcode
54 #    then it's creation code can be:
55 #    @code
56 #    my_algo = mesh.MyAlgorithm(algo="MyPLUGIN")
57 #    @endcode
58 #  @ingroup l2_algorithms
59 class Mesh_Algorithm:
60     
61     ## Private constuctor
62     def __init__(self):
63         self.mesh = None
64         self.geom = None
65         self.subm = None
66         self.algo = None
67         pass
68
69     ## Finds a hypothesis in the study by its type name and parameters.
70     #  Finds only the hypotheses created in smeshpyD engine.
71     #  @return SMESH.SMESH_Hypothesis
72     def FindHypothesis (self, hypname, args, CompareMethod, smeshpyD):
73         study = smeshpyD.GetCurrentStudy()
74         #to do: find component by smeshpyD object, not by its data type
75         scomp = study.FindComponent(smeshpyD.ComponentDataType())
76         if scomp is not None:
77             res,hypRoot = scomp.FindSubObject(SMESH.Tag_HypothesisRoot)
78             # Check if the root label of the hypotheses exists
79             if res and hypRoot is not None:
80                 iter = study.NewChildIterator(hypRoot)
81                 # Check all published hypotheses
82                 while iter.More():
83                     hypo_so_i = iter.Value()
84                     attr = hypo_so_i.FindAttribute("AttributeIOR")[1]
85                     if attr is not None:
86                         anIOR = attr.Value()
87                         hypo_o_i = salome.orb.string_to_object(anIOR)
88                         if hypo_o_i is not None:
89                             # Check if this is a hypothesis
90                             hypo_i = hypo_o_i._narrow(SMESH.SMESH_Hypothesis)
91                             if hypo_i is not None:
92                                 # Check if the hypothesis belongs to current engine
93                                 if smeshpyD.GetObjectId(hypo_i) > 0:
94                                     # Check if this is the required hypothesis
95                                     if hypo_i.GetName() == hypname:
96                                         # Check arguments
97                                         if CompareMethod(hypo_i, args):
98                                             # found!!!
99                                             return hypo_i
100                                         pass
101                                     pass
102                                 pass
103                             pass
104                         pass
105                     iter.Next()
106                     pass
107                 pass
108             pass
109         return None
110
111     ## Finds the algorithm in the study by its type name.
112     #  Finds only the algorithms, which have been created in smeshpyD engine.
113     #  @return SMESH.SMESH_Algo
114     def FindAlgorithm (self, algoname, smeshpyD):
115         study = smeshpyD.GetCurrentStudy()
116         if not study: return None
117         #to do: find component by smeshpyD object, not by its data type
118         scomp = study.FindComponent(smeshpyD.ComponentDataType())
119         if scomp is not None:
120             res,hypRoot = scomp.FindSubObject(SMESH.Tag_AlgorithmsRoot)
121             # Check if the root label of the algorithms exists
122             if res and hypRoot is not None:
123                 iter = study.NewChildIterator(hypRoot)
124                 # Check all published algorithms
125                 while iter.More():
126                     algo_so_i = iter.Value()
127                     attr = algo_so_i.FindAttribute("AttributeIOR")[1]
128                     if attr is not None:
129                         anIOR = attr.Value()
130                         algo_o_i = salome.orb.string_to_object(anIOR)
131                         if algo_o_i is not None:
132                             # Check if this is an algorithm
133                             algo_i = algo_o_i._narrow(SMESH.SMESH_Algo)
134                             if algo_i is not None:
135                                 # Checks if the algorithm belongs to the current engine
136                                 if smeshpyD.GetObjectId(algo_i) > 0:
137                                     # Check if this is the required algorithm
138                                     if algo_i.GetName() == algoname:
139                                         # found!!!
140                                         return algo_i
141                                     pass
142                                 pass
143                             pass
144                         pass
145                     iter.Next()
146                     pass
147                 pass
148             pass
149         return None
150
151     ## If the algorithm is global, returns 0; \n
152     #  else returns the submesh associated to this algorithm.
153     def GetSubMesh(self):
154         return self.subm
155
156     ## Returns the wrapped mesher.
157     def GetAlgorithm(self):
158         return self.algo
159
160     ## Gets the list of hypothesis that can be used with this algorithm
161     def GetCompatibleHypothesis(self):
162         mylist = []
163         if self.algo:
164             mylist = self.algo.GetCompatibleHypothesis()
165         return mylist
166
167     ## Gets the name of the algorithm
168     def GetName(self):
169         from smeshDC import GetName
170         return GetName(self.algo)
171
172     ## Sets the name to the algorithm
173     def SetName(self, name):
174         self.mesh.smeshpyD.SetName(self.algo, name)
175
176     ## Gets the id of the algorithm
177     def GetId(self):
178         return self.algo.GetId()
179
180     ## Private method.
181     def Create(self, mesh, geom, hypo, so="libStdMeshersEngine.so"):
182         if geom is None:
183             raise RuntimeError, "Attemp to create " + hypo + " algoritm on None shape"
184         algo = self.FindAlgorithm(hypo, mesh.smeshpyD)
185         if algo is None:
186             algo = mesh.smeshpyD.CreateHypothesis(hypo, so)
187             pass
188         self.Assign(algo, mesh, geom)
189         return self.algo
190
191     ## Private method
192     def Assign(self, algo, mesh, geom):
193         from smeshDC import AssureGeomPublished, TreatHypoStatus, GetName
194         if geom is None:
195             raise RuntimeError, "Attemp to create " + algo + " algoritm on None shape"
196         self.mesh = mesh
197         name = ""
198         if not geom or geom.IsSame( mesh.geom ):
199             self.geom = mesh.geom
200         else:
201             self.geom = geom
202             AssureGeomPublished( mesh, geom )
203             try:
204                 name = GetName(geom)
205                 pass
206             except:
207                 pass
208             self.subm = mesh.mesh.GetSubMesh(geom, algo.GetName())
209         self.algo = algo
210         status = mesh.mesh.AddHypothesis(self.geom, self.algo)
211         TreatHypoStatus( status, algo.GetName(), name, True )
212         return
213
214     def CompareHyp (self, hyp, args):
215         print "CompareHyp is not implemented for ", self.__class__.__name__, ":", hyp.GetName()
216         return False
217
218     def CompareEqualHyp (self, hyp, args):
219         return True
220
221     ## Private method
222     def Hypothesis (self, hyp, args=[], so="libStdMeshersEngine.so",
223                     UseExisting=0, CompareMethod=""):
224         from smeshDC import TreatHypoStatus, GetName
225         hypo = None
226         if UseExisting:
227             if CompareMethod == "": CompareMethod = self.CompareHyp
228             hypo = self.FindHypothesis(hyp, args, CompareMethod, self.mesh.smeshpyD)
229             pass
230         if hypo is None:
231             hypo = self.mesh.smeshpyD.CreateHypothesis(hyp, so)
232             a = ""
233             s = "="
234             for arg in args:
235                 argStr = str(arg)
236                 if isinstance( arg, geompyDC.GEOM._objref_GEOM_Object ):
237                     argStr = arg.GetStudyEntry()
238                     if not argStr: argStr = "GEOM_Obj_%s", arg.GetEntry()
239                 if len( argStr ) > 10:
240                     argStr = argStr[:7]+"..."
241                     if argStr[0] == '[': argStr += ']'
242                 a = a + s + argStr
243                 s = ","
244                 pass
245             if len(a) > 50:
246                 a = a[:47]+"..."
247             self.mesh.smeshpyD.SetName(hypo, hyp + a)
248             pass
249         geomName=""
250         if self.geom:
251             geomName = GetName(self.geom)
252         status = self.mesh.mesh.AddHypothesis(self.geom, hypo)
253         TreatHypoStatus( status, GetName(hypo), geomName, 0 )
254         return hypo
255
256     ## Returns entry of the shape to mesh in the study
257     def MainShapeEntry(self):
258         if not self.mesh or not self.mesh.GetMesh(): return ""
259         if not self.mesh.GetMesh().HasShapeToMesh(): return ""
260         shape = self.mesh.GetShape()
261         return shape.GetStudyEntry()
262
263     ## Defines "ViscousLayers" hypothesis to give parameters of layers of prisms to build
264     #  near mesh boundary. This hypothesis can be used by several 3D algorithms:
265     #  NETGEN 3D, GHS3D, Hexahedron(i,j,k)
266     #  @param thickness total thickness of layers of prisms
267     #  @param numberOfLayers number of layers of prisms
268     #  @param stretchFactor factor (>1.0) of growth of layer thickness towards inside of mesh
269     #  @param ignoreFaces list of geometrical faces (or their ids) not to generate layers on
270     #  @ingroup l3_hypos_additi
271     def ViscousLayers(self, thickness, numberOfLayers, stretchFactor, ignoreFaces=[]):
272         if not isinstance(self.algo, SMESH._objref_SMESH_3D_Algo):
273             raise TypeError, "ViscousLayers are supported by 3D algorithms only"
274         if not "ViscousLayers" in self.GetCompatibleHypothesis():
275             raise TypeError, "ViscousLayers are not supported by %s"%self.algo.GetName()
276         if ignoreFaces and isinstance( ignoreFaces[0], geompyDC.GEOM._objref_GEOM_Object ):
277             ignoreFaces = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in ignoreFaces ]
278         hyp = self.Hypothesis("ViscousLayers",
279                               [thickness, numberOfLayers, stretchFactor, ignoreFaces])
280         hyp.SetTotalThickness(thickness)
281         hyp.SetNumberLayers(numberOfLayers)
282         hyp.SetStretchFactor(stretchFactor)
283         hyp.SetIgnoreFaces(ignoreFaces)
284         return hyp
285
286     ## Defines "ViscousLayers2D" hypothesis to give parameters of layers of quadrilateral
287     #  elements to build near mesh boundary. This hypothesis can be used by several 2D algorithms:
288     #  NETGEN 2D, NETGEN 1D-2D, Quadrangle (mapping), MEFISTO, BLSURF
289     #  @param thickness total thickness of layers of quadrilaterals
290     #  @param numberOfLayers number of layers
291     #  @param stretchFactor factor (>1.0) of growth of layer thickness towards inside of mesh
292     #  @param ignoreEdges list of geometrical edge (or their ids) not to generate layers on
293     #  @ingroup l3_hypos_additi
294     def ViscousLayers2D(self, thickness, numberOfLayers, stretchFactor, ignoreEdges=[]):
295         if not isinstance(self.algo, SMESH._objref_SMESH_2D_Algo):
296             raise TypeError, "ViscousLayers2D are supported by 2D algorithms only"
297         if not "ViscousLayers2D" in self.GetCompatibleHypothesis():
298             raise TypeError, "ViscousLayers2D are not supported by %s"%self.algo.GetName()
299         if ignoreEdges and isinstance( ignoreEdges[0], geompyDC.GEOM._objref_GEOM_Object ):
300             ignoreEdges = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in ignoreEdges ]
301         hyp = self.Hypothesis("ViscousLayers2D",
302                               [thickness, numberOfLayers, stretchFactor, ignoreEdges])
303         hyp.SetTotalThickness(thickness)
304         hyp.SetNumberLayers(numberOfLayers)
305         hyp.SetStretchFactor(stretchFactor)
306         hyp.SetIgnoreEdges(ignoreEdges)
307         return hyp
308
309     ## Transform a list of ether edges or tuples (edge, 1st_vertex_of_edge)
310     #  into a list acceptable to SetReversedEdges() of some 1D hypotheses
311     #  @ingroup l3_hypos_1dhyps
312     def ReversedEdgeIndices(self, reverseList):
313         from smeshDC import FirstVertexOnCurve
314         resList = []
315         geompy = self.mesh.geompyD
316         for i in reverseList:
317             if isinstance( i, int ):
318                 s = geompy.SubShapes(self.mesh.geom, [i])[0]
319                 if s.GetShapeType() != geompyDC.GEOM.EDGE:
320                     raise TypeError, "Not EDGE index given"
321                 resList.append( i )
322             elif isinstance( i, geompyDC.GEOM._objref_GEOM_Object ):
323                 if i.GetShapeType() != geompyDC.GEOM.EDGE:
324                     raise TypeError, "Not an EDGE given"
325                 resList.append( geompy.GetSubShapeID(self.mesh.geom, i ))
326             elif len( i ) > 1:
327                 e = i[0]
328                 v = i[1]
329                 if not isinstance( e, geompyDC.GEOM._objref_GEOM_Object ) or \
330                    not isinstance( v, geompyDC.GEOM._objref_GEOM_Object ):
331                     raise TypeError, "A list item must be a tuple (edge, 1st_vertex_of_edge)"
332                 if v.GetShapeType() == geompyDC.GEOM.EDGE and \
333                    e.GetShapeType() == geompyDC.GEOM.VERTEX:
334                     v,e = e,v
335                 if e.GetShapeType() != geompyDC.GEOM.EDGE or \
336                    v.GetShapeType() != geompyDC.GEOM.VERTEX:
337                     raise TypeError, "A list item must be a tuple (edge, 1st_vertex_of_edge)"
338                 vFirst = FirstVertexOnCurve( e )
339                 tol    = geompy.Tolerance( vFirst )[-1]
340                 if geompy.MinDistance( v, vFirst ) > 1.5*tol:
341                     resList.append( geompy.GetSubShapeID(self.mesh.geom, e ))
342             else:
343                 raise TypeError, "Item must be either an edge or tuple (edge, 1st_vertex_of_edge)"
344         return resList
345