Salome HOME
Integration improvements 0020310 and 0020431.
[modules/smesh.git] / src / StdMeshers / StdMeshers_Hexa_3D.cxx
index 3320a4ee94809eb43fc31c7cbed4f4527c8ace49..1300bf9b11f6264da599946dce858a360d6ec515 100644 (file)
@@ -48,6 +48,8 @@
 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 #include <TopTools_ListOfShape.hxx>
+#include <TopTools_SequenceOfShape.hxx>
+#include <TopTools_MapOfShape.hxx>
 #include <TopoDS.hxx>
 #include <gp_Pnt2d.hxx>
 
@@ -58,7 +60,11 @@ typedef SMESH_Comment TComm;
 
 using namespace std;
 
-static SMESH_ComputeErrorPtr ComputePentahedralMesh(SMESH_Mesh &, const TopoDS_Shape &);
+static SMESH_ComputeErrorPtr ComputePentahedralMesh(SMESH_Mesh &,
+                                                   const TopoDS_Shape &);
+
+static bool EvaluatePentahedralMesh(SMESH_Mesh &, const TopoDS_Shape &,
+                                   MapShapeNbElems &);
 
 //=============================================================================
 /*!
@@ -736,6 +742,127 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh &         aMesh,
   return ClearAndReturn( aQuads, true );
 }
 
+
+//=============================================================================
+/*!
+ *  Evaluate
+ */
+//=============================================================================
+
+bool StdMeshers_Hexa_3D::Evaluate(SMESH_Mesh & aMesh,
+                                 const TopoDS_Shape & aShape,
+                                 MapShapeNbElems& aResMap)
+{
+  vector < SMESH_subMesh * >meshFaces;
+  TopTools_SequenceOfShape aFaces;
+  for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) {
+    aFaces.Append(exp.Current());
+    SMESH_subMesh *aSubMesh = aMesh.GetSubMeshContaining(exp.Current());
+    ASSERT(aSubMesh);
+    meshFaces.push_back(aSubMesh);
+  }
+  if (meshFaces.size() != 6) {
+    //return error(COMPERR_BAD_SHAPE, TComm(meshFaces.size())<<" instead of 6 faces in a block");
+    static StdMeshers_CompositeHexa_3D compositeHexa(-10, 0, aMesh.GetGen());
+    return compositeHexa.Evaluate(aMesh, aShape, aResMap);
+  }
+  
+  int i = 0;
+  for(; i<6; i++) {
+    //TopoDS_Shape aFace = meshFaces[i]->GetSubShape();
+    TopoDS_Shape aFace = aFaces.Value(i+1);
+    SMESH_Algo *algo = _gen->GetAlgo(aMesh, aFace);
+    if( !algo ) {
+      std::vector<int> aResVec(SMDSEntity_Last);
+      for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
+      SMESH_subMesh * sm = aMesh.GetSubMesh(aShape);
+      aResMap.insert(std::make_pair(sm,aResVec));
+      SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
+      smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this));
+      return false;
+    }
+    string algoName = algo->GetName();
+    bool isAllQuad = false;
+    if (algoName == "Quadrangle_2D") {
+      MapShapeNbElemsItr anIt = aResMap.find(meshFaces[i]);
+      if( anIt == aResMap.end() ) continue;
+      std::vector<int> aVec = (*anIt).second;
+      int nbtri = Max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]);
+      if( nbtri == 0 )
+       isAllQuad = true;
+    }
+    if ( ! isAllQuad ) {
+      return EvaluatePentahedralMesh(aMesh, aShape, aResMap);
+    }
+  }
+  
+  // find number of 1d elems for 1 face
+  int nb1d = 0;
+  TopTools_MapOfShape Edges1;
+  bool IsQuadratic = false;
+  bool IsFirst = true;
+  for (TopExp_Explorer exp(aFaces.Value(1), TopAbs_EDGE); exp.More(); exp.Next()) {
+    Edges1.Add(exp.Current());
+    SMESH_subMesh *sm = aMesh.GetSubMesh(exp.Current());
+    if( sm ) {
+      MapShapeNbElemsItr anIt = aResMap.find(sm);
+      if( anIt == aResMap.end() ) continue;
+      std::vector<int> aVec = (*anIt).second;
+      nb1d += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]);
+      if(IsFirst) {
+       IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]);
+       IsFirst = false;
+      }
+    }
+  }
+  // find face opposite to 1 face
+  int OppNum = 0;
+  for(i=2; i<=6; i++) {
+    bool IsOpposite = true;
+    for(TopExp_Explorer exp(aFaces.Value(i), TopAbs_EDGE); exp.More(); exp.Next()) {
+      if( Edges1.Contains(exp.Current()) ) {
+       IsOpposite = false;
+       break;
+      }
+    }
+    if(IsOpposite) {
+      OppNum = i;
+      break;
+    }
+  }
+  // find number of 2d elems on side faces
+  int nb2d = 0;
+  for(i=2; i<=6; i++) {
+    if( i == OppNum ) continue;
+    MapShapeNbElemsItr anIt = aResMap.find( meshFaces[i-1] );
+    if( anIt == aResMap.end() ) continue;
+    std::vector<int> aVec = (*anIt).second;
+    nb2d += Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
+  }
+  
+  MapShapeNbElemsItr anIt = aResMap.find( meshFaces[0] );
+  std::vector<int> aVec = (*anIt).second;
+  int nb2d_face0 = Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
+  int nb0d_face0 = aVec[SMDSEntity_Node];
+
+  std::vector<int> aResVec(SMDSEntity_Last);
+  for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
+  if(IsQuadratic) {
+    aResVec[SMDSEntity_Quad_Hexa] = nb2d_face0 * ( nb2d/nb1d );
+    int nb1d_face0_int = ( nb2d_face0*4 - nb1d ) / 2;
+    aResVec[SMDSEntity_Node] = nb0d_face0 * ( 2*nb2d/nb1d - 1 ) - nb1d_face0_int * nb2d/nb1d;
+  }
+  else {
+    aResVec[SMDSEntity_Node] = nb0d_face0 * ( nb2d/nb1d - 1 );
+    aResVec[SMDSEntity_Hexa] = nb2d_face0 * ( nb2d/nb1d );
+  }
+  SMESH_subMesh * sm = aMesh.GetSubMesh(aShape);
+  aResMap.insert(std::make_pair(sm,aResVec));
+
+  return true;
+}
+
+
 //=============================================================================
 /*!
  *  
@@ -1047,6 +1174,7 @@ SMESH_ComputeErrorPtr ComputePentahedralMesh(SMESH_Mesh &         aMesh,
     }
     SMESH_Hypothesis::Hypothesis_Status aStatus;
     if ( aPrism3D->CheckHypothesis( aMesh, aShape, aStatus ) ) {
+      aPrism3D->InitComputeError();
       bOK = aPrism3D->Compute( aMesh, aShape );
       err = aPrism3D->GetComputeError();
     }
@@ -1055,3 +1183,33 @@ SMESH_ComputeErrorPtr ComputePentahedralMesh(SMESH_Mesh &         aMesh,
 }
 
 
+//=======================================================================
+//function : EvaluatePentahedralMesh
+//purpose  : 
+//=======================================================================
+
+bool EvaluatePentahedralMesh(SMESH_Mesh & aMesh,
+                            const TopoDS_Shape & aShape,
+                            MapShapeNbElems& aResMap)
+{
+  StdMeshers_Penta_3D anAlgo;
+  bool bOK = anAlgo.Evaluate(aMesh, aShape, aResMap);
+
+  //err = anAlgo.GetComputeError();
+  //if ( !bOK && anAlgo.ErrorStatus() == 5 )
+  if( !bOK ) {
+    static StdMeshers_Prism_3D * aPrism3D = 0;
+    if ( !aPrism3D ) {
+      SMESH_Gen* gen = aMesh.GetGen();
+      aPrism3D = new StdMeshers_Prism_3D( gen->GetANewId(), 0, gen );
+    }
+    SMESH_Hypothesis::Hypothesis_Status aStatus;
+    if ( aPrism3D->CheckHypothesis( aMesh, aShape, aStatus ) ) {
+      return aPrism3D->Evaluate(aMesh, aShape, aResMap);
+    }
+  }
+
+  return bOK;
+}
+
+