Salome HOME
fix bug 12361. In SetName(): there may be no study
[modules/smesh.git] / src / SMESH_SWIG / smesh.py
index 9c0d2baf766753f39159e17804fc89aaeacdb211..6b95891c7b07192fd00a02938010890048c4ab08 100644 (file)
@@ -60,8 +60,9 @@ def GetName(obj):
 def SetName(obj, name):
     ior  = salome.orb.object_to_string(obj)
     sobj = salome.myStudy.FindObjectIOR(ior)
-    attr = sobj.FindAttribute("AttributeName")[1]
-    attr.SetValue(name)
+    if not sobj is None:
+        attr = sobj.FindAttribute("AttributeName")[1]
+        attr.SetValue(name)
 
 # Algorithms and hypothesis
 # =========================
@@ -77,6 +78,7 @@ class Mesh_Algorithm:
     mesh = 0
     geom = 0
     subm = 0
+    algo = 0
 
     def GetSubMesh(self):
         """
@@ -85,10 +87,50 @@ class Mesh_Algorithm:
         """
         return self.subm
 
+    def GetAlgorithm(self):
+        """
+         Return the wrapped mesher
+        """
+        return self.algo
+
+    def TreatHypoStatus(self, status, hypName, geomName, isAlgo):
+        """
+        Private method. Print error message if a hypothesis was not assigned
+        """
+        if isAlgo:
+            hypType = "algorithm"
+        else:
+            hypType = "hypothesis"
+        if status == SMESH.HYP_UNKNOWN_FATAL :
+            reason = "for unknown reason"
+        elif status == SMESH.HYP_INCOMPATIBLE :
+            reason = "this hypothesis mismatches algorithm"
+        elif status == SMESH.HYP_NOTCONFORM :
+            reason = "not conform mesh would be built"
+        elif status == SMESH.HYP_ALREADY_EXIST :
+            reason = hypType + " of the same dimension already assigned to this shape"
+        elif status == SMESH.HYP_BAD_DIM :
+            reason = hypType + " mismatches shape"
+        elif status == SMESH.HYP_CONCURENT :
+            reason = "there are concurrent hypotheses on sub-shapes"
+        elif status == SMESH.HYP_BAD_SUBSHAPE :
+            reason = "shape is neither the main one, nor its subshape, nor a valid group"
+        else:
+            return
+        hypName = '"' + hypName + '"'
+        geomName= '"' + geomName+ '"'
+        if status < SMESH.HYP_UNKNOWN_FATAL:
+            print hypName, "was assigned to",    geomName,"but", reason
+        else:
+            print hypName, "was not assigned to",geomName,":", reason
+        pass
+
     def Create(self, mesh, geom, hypo, so="libStdMeshersEngine.so"):
         """
          Private method
         """
+        if geom is None:
+            raise RuntimeError, "Attemp to create " + hypo + " algoritm on None shape"
         self.mesh = mesh
         piece = mesh.geom
         if geom==0:
@@ -102,9 +144,10 @@ class Mesh_Algorithm:
                 geompy.addToStudyInFather(piece, geom, name)
             self.subm = mesh.mesh.GetSubMesh(geom, hypo)
 
-        algo = smesh.CreateHypothesis(hypo, so)
-        SetName(algo, name + "/" + hypo)
-        mesh.mesh.AddHypothesis(self.geom, algo)
+        self.algo = smesh.CreateHypothesis(hypo, so)
+        SetName(self.algo, name + "/" + hypo)
+        status = mesh.mesh.AddHypothesis(self.geom, self.algo)
+        self.TreatHypoStatus( status, hypo, name, 1 )
 
     def Hypothesis(self, hyp, args=[], so="libStdMeshersEngine.so"):
         """
@@ -119,8 +162,10 @@ class Mesh_Algorithm:
             a = a + s + str(args[i])
             s = ","
             i = i + 1
-        SetName(hypo, GetName(self.geom) + "/" + hyp + a)
-        self.mesh.mesh.AddHypothesis(self.geom, hypo)
+        name = GetName(self.geom)
+        SetName(hypo, name + "/" + hyp + a)
+        status = self.mesh.mesh.AddHypothesis(self.geom, hypo)
+        self.TreatHypoStatus( status, hyp, name, 0 )
         return hypo
 
 # Public class: Mesh_Segment
@@ -156,6 +201,7 @@ class Mesh_Segment(Mesh_Algorithm):
             hyp = self.Hypothesis("NumberOfSegments", [n])
         else:
             hyp = self.Hypothesis("NumberOfSegments", [n,s])
+            hyp.SetDistrType( 1 )
             hyp.SetScaleFactor(s)
         hyp.SetNumberOfSegments(n)
         return hyp
@@ -198,6 +244,27 @@ class Mesh_Segment(Mesh_Algorithm):
         """
         return self.Hypothesis("Propagation")
 
+    def AutomaticLength(self, fineness=0):
+        """
+         Define "AutomaticLength" hypothesis
+         \param fineness for the fineness [0-1]
+        """
+        hyp = self.Hypothesis("AutomaticLength")
+        hyp.SetFineness( fineness )
+        return hyp
+
+    def QuadraticMesh(self):
+        """
+         Define "QuadraticMesh" hypothesis, forcing construction of quadratic edges.
+         If the 2D mesher sees that all boundary edges are quadratic ones,
+         it generates quadratic faces, else it generates linear faces using
+         medium nodes as if they were vertex ones.
+         The 3D mesher generates quadratic volumes only if all boundary faces
+         are quadratic ones, else it fails.
+        """
+        hyp = self.Hypothesis("QuadraticMesh")
+        return hyp
+
 # Public class: Mesh_Segment_Python
 # ---------------------------------
 
@@ -267,6 +334,15 @@ class Mesh_Quadrangle(Mesh_Algorithm):
         """
         self.Create(mesh, geom, "Quadrangle_2D")
 
+    def QuadranglePreference(self):
+        """
+         Define "QuadranglePreference" hypothesis, forcing construction
+         of quadrangles if the number of nodes on opposite edges is not the same
+         in the case where the global number of nodes on edges is even
+        """
+        hyp = self.Hypothesis("QuadranglePreference")
+        return hyp
+
 # Public class: Mesh_Tetrahedron
 # ------------------------------
 
@@ -308,6 +384,37 @@ class Mesh_Hexahedron(Mesh_Algorithm):
         """
         self.Create(mesh, geom, "Hexa_3D")
 
+# Public class: Mesh_Netgen
+# ------------------------------
+
+class Mesh_Netgen(Mesh_Algorithm):
+    """
+    Class to define a NETGEN-based 2D or 3D algorithm
+    that need no discrete boundary (i.e. independent)
+    """
+
+    is3D = 0
+
+    def __init__(self, mesh, is3D, geom=0):
+        """
+         Private constructor
+        """
+        self.is3D = is3D
+        if is3D:
+            self.Create(mesh, geom, "NETGEN_2D3D", "libNETGENEngine.so")
+        else:
+            self.Create(mesh, geom, "NETGEN_2D", "libNETGENEngine.so")
+
+    def Parameters(self):
+        """
+         Define hypothesis containing parameters of the algorithm
+        """
+        if self.is3D:
+            hyp = self.Hypothesis("NETGEN_Parameters", [], "libNETGENEngine.so")
+        else:
+            hyp = self.Hypothesis("NETGEN_Parameters_2D", [], "libNETGENEngine.so")
+        return hyp
+
 # Public class: Mesh
 # ==================
 
@@ -347,6 +454,21 @@ class Mesh:
         """
         return self.geom
 
+    def MeshDimension(self):
+        """
+        Returns mesh dimension depending on shape one
+        """
+        shells = geompy.SubShapeAllIDs( self.geom, geompy.ShapeType["SHELL"] )
+        if len( shells ) > 0 :
+            return 3
+        elif geompy.NumberOfFaces( self.geom ) > 0 :
+            return 2
+        elif geompy.NumberOfEdges( self.geom ) > 0 :
+            return 1
+        else:
+            return 0;
+        pass
+
     def Segment(self, algo=REGULAR, geom=0):
         """
          Creates a segment discretization 1D algorithm.
@@ -356,12 +478,16 @@ class Mesh:
          \param algo values are smesh.REGULAR or smesh.PYTHON for discretization via python function
          \param geom If defined, subshape to be meshed
         """
+        ## if Segment(geom) is called by mistake
+        if ( isinstance( algo, geompy.GEOM._objref_GEOM_Object)):
+            algo, geom = geom, algo
+            pass
         if algo == REGULAR:
             return Mesh_Segment(self, geom)
         elif algo == PYTHON:
             return Mesh_Segment_Python(self, geom)
         else:
-            return Mesh_Segment(self, algo)
+            return Mesh_Segment(self, geom)
 
     def Triangle(self, geom=0):
         """
@@ -390,6 +516,10 @@ class Mesh:
          \param algo values are: smesh.NETGEN, smesh.GHS3D
          \param geom If defined, subshape to be meshed
         """
+        ## if Tetrahedron(geom) is called by mistake
+        if ( isinstance( algo, geompy.GEOM._objref_GEOM_Object)):
+            algo, geom = geom, algo
+            pass
         return Mesh_Tetrahedron(self, algo, geom)
 
     def Hexahedron(self, geom=0):
@@ -401,17 +531,101 @@ class Mesh:
         """
         return Mesh_Hexahedron(self, geom)
 
-    def Compute(self):
+    def Netgen(self, is3D, geom=0):
+        """
+         Creates a NETGEN-based 2D or 3D independent algorithm (i.e. needs no
+         discrete boundary).
+         If the optional \a geom parameter is not sets, this algorithm is global.
+         Otherwise, this algorithm defines a submesh based on \a geom subshape.
+         \param is3D If 0 then algorithm is 2D, otherwise 3D
+         \param geom If defined, subshape to be meshed
         """
-         Compute the mesh and return the status of the computation
+        return Mesh_Netgen(self, is3D, geom)
+
+    def Compute(self):
         """
-        b = smesh.Compute(self.mesh, self.geom)
+        Compute the mesh and return the status of the computation
+        """
+        ok = smesh.Compute(self.mesh, self.geom)
+        if not ok:
+            errors = smesh.GetAlgoState( self.mesh, self.geom )
+            allReasons = ""
+            for err in errors:
+                if err.isGlobalAlgo:
+                    glob = " global "
+                else:
+                    glob = " local "
+                    pass
+                dim = str(err.algoDim)
+                if err.name == SMESH.MISSING_ALGO:
+                    reason = glob + dim + "D algorithm is missing"
+                elif err.name == SMESH.MISSING_HYPO:
+                    name = '"' + err.algoName + '"'
+                    reason = glob + dim + "D algorithm " + name + " misses " + dim + "D hypothesis"
+                else:
+                    reason = "Global \"Not Conform mesh allowed\" hypothesis is missing"
+                    pass
+                if allReasons != "":
+                    allReasons += "\n"
+                    pass
+                allReasons += reason
+                pass
+            if allReasons != "":
+                print '"' + GetName(self.mesh) + '"',"not computed:"
+                print allReasons
+                pass
+            pass
         if salome.sg.hasDesktop():
             smeshgui = salome.ImportComponentGUI("SMESH")
             smeshgui.Init(salome.myStudyId)
-            smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), b )
+            smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), ok )
             salome.sg.updateObjBrowser(1)
-        return b
+            pass
+        return ok
+
+    def AutomaticTetrahedralization(self, fineness=0):
+        """
+        Compute tetrahedral mesh using AutomaticLength + MEFISTO + NETGEN
+        The parameter \a fineness [0.-1.] defines mesh fineness
+        """
+        dim = self.MeshDimension()
+        # assign hypotheses
+        self.RemoveGlobalHypotheses()
+        self.Segment().AutomaticLength(fineness)
+        if dim > 1 :
+            self.Triangle().LengthFromEdges()
+            pass
+        if dim > 2 :
+            self.Tetrahedron(NETGEN)
+            pass
+        return self.Compute()
+
+    def AutomaticHexahedralization(self, fineness=0):
+        """
+        Compute hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
+        The parameter \a fineness [0.-1.] defines mesh fineness
+        """
+        dim = self.MeshDimension()
+        # assign hypotheses
+        self.RemoveGlobalHypotheses()
+        self.Segment().AutomaticLength(fineness)
+        if dim > 1 :
+            self.Quadrangle()
+            pass
+        if dim > 2 :
+            self.Hexahedron()            
+            pass
+        return self.Compute()
+
+    def RemoveGlobalHypotheses(self):
+        """
+        Removes all global hypotheses
+        """
+        current_hyps = self.mesh.GetHypothesisList( self.geom )
+        for hyp in current_hyps:
+            self.mesh.RemoveHypothesis( self.geom, hyp )
+            pass
+        pass
 
     def Group(self, grp, name=""):
         """
@@ -437,6 +651,9 @@ class Mesh:
         elif tgeo == "SHELL":
             type = SMESH.VOLUME
         elif tgeo == "COMPOUND":
+            if len( geompy.GetObjectIDs( grp )) == 0:
+                print "Mesh.Group: empty geometric group", GetName( grp )
+                return 0
             tgeo = geompy.GetType(grp)
             if tgeo == geompy.ShapeType["VERTEX"]:
                 type = SMESH.NODE
@@ -457,7 +674,7 @@ class Mesh:
         """
          Export the mesh in a file with the MED format and choice the \a version of MED format
          \param f is the file name
-         \param version values are smesh.MED_V2_1, smesh.MED_V2_2
+         \param version values are SMESH.MED_V2_1, SMESH.MED_V2_2
         """
         self.mesh.ExportToMED(f, opt, version)