Salome HOME
0022104: EDF 2550 SMESH: 2D viscous layer, allow specifying edges with viscous layer
[modules/smesh.git] / src / SMESH_SWIG / smesh_algorithm.py
1 # Copyright (C) 2007-2013  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 from salome.geom import geomBuilder
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 StdMeshersBuilder.StdMeshersBuilder_Segment "StdMeshersBuilder_Segment"
36 #  in StdMeshersBuilder 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         if not study: return None
75         #to do: find component by smeshpyD object, not by its data type
76         scomp = study.FindComponent(smeshpyD.ComponentDataType())
77         if scomp is not None:
78             res,hypRoot = scomp.FindSubObject(SMESH.Tag_HypothesisRoot)
79             # Check if the root label of the hypotheses exists
80             if res and hypRoot is not None:
81                 iter = study.NewChildIterator(hypRoot)
82                 # Check all published hypotheses
83                 while iter.More():
84                     hypo_so_i = iter.Value()
85                     attr = hypo_so_i.FindAttribute("AttributeIOR")[1]
86                     if attr is not None:
87                         anIOR = attr.Value()
88                         hypo_o_i = salome.orb.string_to_object(anIOR)
89                         if hypo_o_i is not None:
90                             # Check if this is a hypothesis
91                             hypo_i = hypo_o_i._narrow(SMESH.SMESH_Hypothesis)
92                             if hypo_i is not None:
93                                 # Check if the hypothesis belongs to current engine
94                                 if smeshpyD.GetObjectId(hypo_i) > 0:
95                                     # Check if this is the required hypothesis
96                                     if hypo_i.GetName() == hypname:
97                                         # Check arguments
98                                         if CompareMethod(hypo_i, args):
99                                             # found!!!
100                                             return hypo_i
101                                         pass
102                                     pass
103                                 pass
104                             pass
105                         pass
106                     iter.Next()
107                     pass
108                 pass
109             pass
110         return None
111
112     ## Finds the algorithm in the study by its type name.
113     #  Finds only the algorithms, which have been created in smeshpyD engine.
114     #  @return SMESH.SMESH_Algo
115     def FindAlgorithm (self, algoname, smeshpyD):
116         study = smeshpyD.GetCurrentStudy()
117         if not study: return None
118         #to do: find component by smeshpyD object, not by its data type
119         scomp = study.FindComponent(smeshpyD.ComponentDataType())
120         if scomp is not None:
121             res,hypRoot = scomp.FindSubObject(SMESH.Tag_AlgorithmsRoot)
122             # Check if the root label of the algorithms exists
123             if res and hypRoot is not None:
124                 iter = study.NewChildIterator(hypRoot)
125                 # Check all published algorithms
126                 while iter.More():
127                     algo_so_i = iter.Value()
128                     attr = algo_so_i.FindAttribute("AttributeIOR")[1]
129                     if attr is not None:
130                         anIOR = attr.Value()
131                         algo_o_i = salome.orb.string_to_object(anIOR)
132                         if algo_o_i is not None:
133                             # Check if this is an algorithm
134                             algo_i = algo_o_i._narrow(SMESH.SMESH_Algo)
135                             if algo_i is not None:
136                                 # Checks if the algorithm belongs to the current engine
137                                 if smeshpyD.GetObjectId(algo_i) > 0:
138                                     # Check if this is the required algorithm
139                                     if algo_i.GetName() == algoname:
140                                         # found!!!
141                                         return algo_i
142                                     pass
143                                 pass
144                             pass
145                         pass
146                     iter.Next()
147                     pass
148                 pass
149             pass
150         return None
151
152     ## If the algorithm is global, returns 0; \n
153     #  else returns the submesh associated to this algorithm.
154     def GetSubMesh(self):
155         return self.subm
156
157     ## Returns the wrapped mesher.
158     def GetAlgorithm(self):
159         return self.algo
160
161     ## Gets the list of hypothesis that can be used with this algorithm
162     def GetCompatibleHypothesis(self):
163         mylist = []
164         if self.algo:
165             mylist = self.algo.GetCompatibleHypothesis()
166         return mylist
167
168     ## Gets the name of the algorithm
169     def GetName(self):
170         from salome.smesh.smeshBuilder import GetName
171         return GetName(self.algo)
172
173     ## Sets the name to the algorithm
174     def SetName(self, name):
175         self.mesh.smeshpyD.SetName(self.algo, name)
176
177     ## Gets the id of the algorithm
178     def GetId(self):
179         return self.algo.GetId()
180
181     ## Private method.
182     def Create(self, mesh, geom, hypo, so="libStdMeshersEngine.so"):
183         if geom is None and mesh.mesh.HasShapeToMesh():
184             raise RuntimeError, "Attemp to create " + hypo + " algoritm on None shape"
185         algo = self.FindAlgorithm(hypo, mesh.smeshpyD)
186         if algo is None:
187             algo = mesh.smeshpyD.CreateHypothesis(hypo, so)
188             pass
189         self.Assign(algo, mesh, geom)
190         return self.algo
191
192     ## Private method
193     def Assign(self, algo, mesh, geom):
194         from salome.smesh.smeshBuilder import AssureGeomPublished, TreatHypoStatus, GetName
195         if geom is None and mesh.mesh.HasShapeToMesh():
196             raise RuntimeError, "Attemp to create " + algo + " algoritm on None shape"
197         self.mesh = mesh
198         name = ""
199         if not geom or geom.IsSame( mesh.geom ):
200             self.geom = mesh.geom
201         else:
202             self.geom = geom
203             AssureGeomPublished( mesh, geom )
204             try:
205                 name = GetName(geom)
206                 pass
207             except:
208                 pass
209             self.subm = mesh.mesh.GetSubMesh(geom, algo.GetName())
210         self.algo = algo
211         status = mesh.mesh.AddHypothesis(self.geom, self.algo)
212         TreatHypoStatus( status, algo.GetName(), name, True )
213         return
214
215     def CompareHyp (self, hyp, args):
216         print "CompareHyp is not implemented for ", self.__class__.__name__, ":", hyp.GetName()
217         return False
218
219     def CompareEqualHyp (self, hyp, args):
220         return True
221
222     ## Private method
223     def Hypothesis (self, hyp, args=[], so="libStdMeshersEngine.so",
224                     UseExisting=0, CompareMethod=""):
225         from salome.smesh.smeshBuilder import TreatHypoStatus, GetName
226         hypo = None
227         if UseExisting:
228             if CompareMethod == "": CompareMethod = self.CompareHyp
229             hypo = self.FindHypothesis(hyp, args, CompareMethod, self.mesh.smeshpyD)
230             pass
231         if hypo is None:
232             hypo = self.mesh.smeshpyD.CreateHypothesis(hyp, so)
233             a = ""
234             s = "="
235             for arg in args:
236                 argStr = str(arg)
237                 if isinstance( arg, geomBuilder.GEOM._objref_GEOM_Object ):
238                     argStr = arg.GetStudyEntry()
239                     if not argStr: argStr = "GEOM_Obj_%s", arg.GetEntry()
240                 if len( argStr ) > 10:
241                     argStr = argStr[:7]+"..."
242                     if argStr[0] == '[': argStr += ']'
243                 a = a + s + argStr
244                 s = ","
245                 pass
246             if len(a) > 50:
247                 a = a[:47]+"..."
248             self.mesh.smeshpyD.SetName(hypo, hyp + a)
249             pass
250         geomName=""
251         if self.geom:
252             geomName = GetName(self.geom)
253         status = self.mesh.mesh.AddHypothesis(self.geom, hypo)
254         TreatHypoStatus( status, GetName(hypo), geomName, 0 )
255         return hypo
256
257     ## Returns entry of the shape to mesh in the study
258     def MainShapeEntry(self):
259         if not self.mesh or not self.mesh.GetMesh(): return ""
260         if not self.mesh.GetMesh().HasShapeToMesh(): return ""
261         shape = self.mesh.GetShape()
262         return shape.GetStudyEntry()
263
264     ## Defines "ViscousLayers" hypothesis to give parameters of layers of prisms to build
265     #  near mesh boundary. This hypothesis can be used by several 3D algorithms:
266     #  NETGEN 3D, GHS3D, Hexahedron(i,j,k)
267     #  @param thickness total thickness of layers of prisms
268     #  @param numberOfLayers number of layers of prisms
269     #  @param stretchFactor factor (>1.0) of growth of layer thickness towards inside of mesh
270     #  @param ignoreFaces list of geometrical faces (or their ids) not to generate layers on
271     #  @ingroup l3_hypos_additi
272     def ViscousLayers(self, thickness, numberOfLayers, stretchFactor, ignoreFaces=[]):
273         if not isinstance(self.algo, SMESH._objref_SMESH_3D_Algo):
274             raise TypeError, "ViscousLayers are supported by 3D algorithms only"
275         if not "ViscousLayers" in self.GetCompatibleHypothesis():
276             raise TypeError, "ViscousLayers are not supported by %s"%self.algo.GetName()
277         if ignoreFaces and isinstance( ignoreFaces[0], geomBuilder.GEOM._objref_GEOM_Object ):
278             ignoreFaces = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in ignoreFaces ]
279         hyp = self.Hypothesis("ViscousLayers",
280                               [thickness, numberOfLayers, stretchFactor, ignoreFaces])
281         hyp.SetTotalThickness(thickness)
282         hyp.SetNumberLayers(numberOfLayers)
283         hyp.SetStretchFactor(stretchFactor)
284         hyp.SetIgnoreFaces(ignoreFaces)
285         return hyp
286
287     ## Defines "ViscousLayers2D" hypothesis to give parameters of layers of quadrilateral
288     #  elements to build near mesh boundary. This hypothesis can be used by several 2D algorithms:
289     #  NETGEN 2D, NETGEN 1D-2D, Quadrangle (mapping), MEFISTO, BLSURF
290     #  @param thickness total thickness of layers of quadrilaterals
291     #  @param numberOfLayers number of layers
292     #  @param stretchFactor factor (>1.0) of growth of layer thickness towards inside of mesh
293     #  @param edges list of geometrical edge (or their ids).
294     #         Viscous layers are either generated on these edges or not, depending on
295     #         the values of \a isEdgesToIgnore parameter.
296     #  @param isEdgesToIgnore if \c True, the Viscous layers are not generated on the
297     #         edges specified by the previous parameter (\a edges).
298     #  @ingroup l3_hypos_additi
299     def ViscousLayers2D(self, thickness, numberOfLayers, stretchFactor,
300                         edges=[], isEdgesToIgnore=True ):
301         if not isinstance(self.algo, SMESH._objref_SMESH_2D_Algo):
302             raise TypeError, "ViscousLayers2D are supported by 2D algorithms only"
303         if not "ViscousLayers2D" in self.GetCompatibleHypothesis():
304             raise TypeError, "ViscousLayers2D are not supported by %s"%self.algo.GetName()
305         if edges and isinstance( edges[0], geomBuilder.GEOM._objref_GEOM_Object ):
306             edges = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in edges ]
307         hyp = self.Hypothesis("ViscousLayers2D",
308                               [thickness, numberOfLayers, stretchFactor,
309                                edges, isEdgesToIgnore])
310         hyp.SetTotalThickness(thickness)
311         hyp.SetNumberLayers(numberOfLayers)
312         hyp.SetStretchFactor(stretchFactor)
313         hyp.SetEdges(edges, isEdgesToIgnore)
314         return hyp
315
316     ## Transform a list of ether edges or tuples (edge, 1st_vertex_of_edge)
317     #  into a list acceptable to SetReversedEdges() of some 1D hypotheses
318     #  @ingroup l3_hypos_1dhyps
319     def ReversedEdgeIndices(self, reverseList):
320         from salome.smesh.smeshBuilder import FirstVertexOnCurve
321         resList = []
322         geompy = self.mesh.geompyD
323         for i in reverseList:
324             if isinstance( i, int ):
325                 s = geompy.SubShapes(self.mesh.geom, [i])[0]
326                 if s.GetShapeType() != geomBuilder.GEOM.EDGE:
327                     raise TypeError, "Not EDGE index given"
328                 resList.append( i )
329             elif isinstance( i, geomBuilder.GEOM._objref_GEOM_Object ):
330                 if i.GetShapeType() != geomBuilder.GEOM.EDGE:
331                     raise TypeError, "Not an EDGE given"
332                 resList.append( geompy.GetSubShapeID(self.mesh.geom, i ))
333             elif len( i ) > 1:
334                 e = i[0]
335                 v = i[1]
336                 if not isinstance( e, geomBuilder.GEOM._objref_GEOM_Object ) or \
337                    not isinstance( v, geomBuilder.GEOM._objref_GEOM_Object ):
338                     raise TypeError, "A list item must be a tuple (edge, 1st_vertex_of_edge)"
339                 if v.GetShapeType() == geomBuilder.GEOM.EDGE and \
340                    e.GetShapeType() == geomBuilder.GEOM.VERTEX:
341                     v,e = e,v
342                 if e.GetShapeType() != geomBuilder.GEOM.EDGE or \
343                    v.GetShapeType() != geomBuilder.GEOM.VERTEX:
344                     raise TypeError, "A list item must be a tuple (edge, 1st_vertex_of_edge)"
345                 vFirst = FirstVertexOnCurve( self.mesh, e )
346                 tol    = geompy.Tolerance( vFirst )[-1]
347                 if geompy.MinDistance( v, vFirst ) > 1.5*tol:
348                     resList.append( geompy.GetSubShapeID(self.mesh.geom, e ))
349             else:
350                 raise TypeError, "Item must be either an edge or tuple (edge, 1st_vertex_of_edge)"
351         return resList
352