Version: 6.3.1

src/StdMeshers/StdMeshers_Hexa_3D.cxx

Go to the documentation of this file.
00001 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 //  SMESH SMESH : implementaion of SMESH idl descriptions
00024 //  File   : StdMeshers_Hexa_3D.cxx
00025 //           Moved here from SMESH_Hexa_3D.cxx
00026 //  Author : Paul RASCLE, EDF
00027 //  Module : SMESH
00028 //
00029 #include "StdMeshers_Hexa_3D.hxx"
00030 
00031 #include "StdMeshers_CompositeHexa_3D.hxx"
00032 #include "StdMeshers_FaceSide.hxx"
00033 #include "StdMeshers_HexaFromSkin_3D.hxx"
00034 #include "StdMeshers_Penta_3D.hxx"
00035 #include "StdMeshers_Prism_3D.hxx"
00036 #include "StdMeshers_Quadrangle_2D.hxx"
00037 #include "StdMeshers_ViscousLayers.hxx"
00038 
00039 #include "SMESH_Comment.hxx"
00040 #include "SMESH_Gen.hxx"
00041 #include "SMESH_Mesh.hxx"
00042 #include "SMESH_MesherHelper.hxx"
00043 #include "SMESH_subMesh.hxx"
00044 
00045 #include "SMDS_MeshElement.hxx"
00046 #include "SMDS_MeshNode.hxx"
00047 #include "SMDS_FacePosition.hxx"
00048 #include "SMDS_VolumeTool.hxx"
00049 #include "SMDS_VolumeOfNodes.hxx"
00050 
00051 #include <TopExp.hxx>
00052 #include <TopExp_Explorer.hxx>
00053 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
00054 #include <TopTools_ListIteratorOfListOfShape.hxx>
00055 #include <TopTools_ListOfShape.hxx>
00056 #include <TopTools_SequenceOfShape.hxx>
00057 #include <TopTools_MapOfShape.hxx>
00058 #include <TopoDS.hxx>
00059 #include <gp_Pnt2d.hxx>
00060 
00061 #include "utilities.h"
00062 #include "Utils_ExceptHandlers.hxx"
00063 
00064 typedef SMESH_Comment TComm;
00065 
00066 using namespace std;
00067 
00068 static SMESH_ComputeErrorPtr ComputePentahedralMesh(SMESH_Mesh &,
00069                                                     const TopoDS_Shape &,
00070                                                     SMESH_ProxyMesh* proxyMesh=0);
00071 
00072 static bool EvaluatePentahedralMesh(SMESH_Mesh &, const TopoDS_Shape &,
00073                                     MapShapeNbElems &);
00074 
00075 //=============================================================================
00079 //=============================================================================
00080 
00081 StdMeshers_Hexa_3D::StdMeshers_Hexa_3D(int hypId, int studyId, SMESH_Gen * gen)
00082   :SMESH_3D_Algo(hypId, studyId, gen)
00083 {
00084   MESSAGE("StdMeshers_Hexa_3D::StdMeshers_Hexa_3D");
00085   _name = "Hexa_3D";
00086   _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);       // 1 bit /shape type
00087   _requireShape = false;
00088   _compatibleHypothesis.push_back("ViscousLayers");
00089 }
00090 
00091 //=============================================================================
00095 //=============================================================================
00096 
00097 StdMeshers_Hexa_3D::~StdMeshers_Hexa_3D()
00098 {
00099   MESSAGE("StdMeshers_Hexa_3D::~StdMeshers_Hexa_3D");
00100 }
00101 
00102 //=============================================================================
00106 //=============================================================================
00107 
00108 bool StdMeshers_Hexa_3D::CheckHypothesis
00109                          (SMESH_Mesh&                          aMesh,
00110                           const TopoDS_Shape&                  aShape,
00111                           SMESH_Hypothesis::Hypothesis_Status& aStatus)
00112 {
00113   // check nb of faces in the shape
00114 /*  PAL16229
00115   aStatus = SMESH_Hypothesis::HYP_BAD_GEOMETRY;
00116   int nbFaces = 0;
00117   for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next())
00118     if ( ++nbFaces > 6 )
00119       break;
00120   if ( nbFaces != 6 )
00121     return false;
00122 */
00123 
00124   _viscousLayersHyp = NULL;
00125 
00126   const list<const SMESHDS_Hypothesis*>& hyps =
00127     GetUsedHypothesis(aMesh, aShape, /*ignoreAuxiliary=*/false);
00128   list <const SMESHDS_Hypothesis* >::const_iterator h = hyps.begin();
00129   if ( h == hyps.end())
00130   {
00131     aStatus = SMESH_Hypothesis::HYP_OK;
00132     return true;
00133   }
00134 
00135   aStatus = HYP_OK;
00136   for ( ; h != hyps.end(); ++h )
00137   {
00138     string hypName = (*h)->GetName();
00139     if ( find( _compatibleHypothesis.begin(),_compatibleHypothesis.end(),hypName )
00140          != _compatibleHypothesis.end() )
00141     {
00142       _viscousLayersHyp = dynamic_cast< const StdMeshers_ViscousLayers*> ( *h );
00143     }
00144     else
00145     {
00146       aStatus = HYP_INCOMPATIBLE;
00147     }
00148   }
00149 
00150   if ( !_viscousLayersHyp )
00151     aStatus = HYP_INCOMPATIBLE;
00152 
00153   return aStatus == HYP_OK;
00154 }
00155 
00156 namespace
00157 {
00158   //=============================================================================
00159 
00160   typedef boost::shared_ptr< FaceQuadStruct > FaceQuadStructPtr;
00161 
00162   // symbolic names of box sides
00163   enum EBoxSides{ B_BOTTOM=0, B_RIGHT, B_TOP, B_LEFT, B_FRONT, B_BACK, B_NB_SIDES };
00164 
00165   // symbolic names of sides of quadrangle
00166   enum EQuadSides{ Q_BOTTOM=0, Q_RIGHT, Q_TOP, Q_LEFT, Q_NB_SIDES };
00167 
00168   //=============================================================================
00172   struct _FaceGrid
00173   {
00174     // face sides
00175     FaceQuadStructPtr _quad;
00176 
00177     // map of (node parameter on EDGE) to (column (vector) of nodes)
00178     TParam2ColumnMap _u2nodesMap;
00179 
00180     // node column's taken form _u2nodesMap taking into account sub-shape orientation
00181     vector<TNodeColumn> _columns;
00182 
00183     // geometry of a cube side
00184     TopoDS_Face _sideF;
00185 
00186     const SMDS_MeshNode* GetNode(int iCol, int iRow) const
00187     {
00188       return _columns[iCol][iRow];
00189     }
00190     gp_XYZ GetXYZ(int iCol, int iRow) const
00191     {
00192       return SMESH_TNodeXYZ( GetNode( iCol, iRow ));
00193     }
00194   };
00195 
00196   //================================================================================
00200   struct _Indexer
00201   {
00202     int _xSize, _ySize;
00203     _Indexer( int xSize, int ySize ): _xSize(xSize), _ySize(ySize) {}
00204     int size() const { return _xSize * _ySize; }
00205     int operator()(const int x, const int y) const { return y * _xSize + x; }
00206   };
00207 
00208   //================================================================================
00212   template< class TMapIterator >
00213   void append( TParam2ColumnMap& toMap, TMapIterator from, TMapIterator to )
00214   {
00215     const SMDS_MeshNode* lastNode = toMap.rbegin()->second[0];
00216     const SMDS_MeshNode* firstNode = from->second[0];
00217     if ( lastNode == firstNode )
00218       from++;
00219     double u = toMap.rbegin()->first;
00220     for (; from != to; ++from )
00221     {
00222       u += 1;
00223       TParam2ColumnMap::iterator u2nn = toMap.insert( toMap.end(), make_pair ( u, TNodeColumn()));
00224       u2nn->second.swap( from->second );
00225     }
00226   }
00227 
00228   //================================================================================
00233   FaceQuadStructPtr getQuadWithBottom( StdMeshers_FaceSide* side,
00234                                        FaceQuadStructPtr    quad[ 6 ])
00235   {
00236     FaceQuadStructPtr foundQuad;
00237     for ( int i = 1; i < 6; ++i )
00238     {
00239       if ( !quad[i] ) continue;
00240       for ( unsigned iS = 0; iS < quad[i]->side.size(); ++iS )
00241       {
00242         const StdMeshers_FaceSide* side2 = quad[i]->side[iS];
00243         if (( side->FirstVertex().IsSame( side2->FirstVertex() ) ||
00244               side->FirstVertex().IsSame( side2->LastVertex() ))
00245             &&
00246             ( side->LastVertex().IsSame( side2->FirstVertex() ) ||
00247               side->LastVertex().IsSame( side2->LastVertex() ))
00248             )
00249         {
00250           if ( iS != Q_BOTTOM )
00251           {
00252             vector< StdMeshers_FaceSide*> newSides;
00253             for ( unsigned j = iS; j < quad[i]->side.size(); ++j )
00254               newSides.push_back( quad[i]->side[j] );
00255             for ( unsigned j = 0; j < iS; ++j )
00256               newSides.push_back( quad[i]->side[j] );
00257             quad[i]->side.swap( newSides );
00258           }
00259           foundQuad.swap(quad[i]);
00260           return foundQuad;
00261         }
00262       }
00263     }
00264     return foundQuad;
00265   }
00266 }
00267 
00268 //=============================================================================
00276 //=============================================================================
00277 
00278 bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh &         aMesh,
00279                                  const TopoDS_Shape & aShape)// throw(SALOME_Exception)
00280 {
00281   // PAL14921. Enable catching std::bad_alloc and Standard_OutOfMemory outside
00282   //Unexpect aCatch(SalomeException);
00283   MESSAGE("StdMeshers_Hexa_3D::Compute");
00284   SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
00285 
00286   // Shape verification
00287   // ----------------------
00288 
00289   // shape must be a solid (or a shell) with 6 faces
00290   TopExp_Explorer exp(aShape,TopAbs_SHELL);
00291   if ( !exp.More() )
00292     return error(COMPERR_BAD_SHAPE, "No SHELL in the geometry");
00293   if ( exp.Next(), exp.More() )
00294     return error(COMPERR_BAD_SHAPE, "More than one SHELL in the geometry");
00295 
00296   TopTools_IndexedMapOfShape FF;
00297   TopExp::MapShapes( aShape, TopAbs_FACE, FF);
00298   if ( FF.Extent() != 6)
00299   {
00300     static StdMeshers_CompositeHexa_3D compositeHexa(_gen->GetANewId(), 0, _gen);
00301     if ( !compositeHexa.Compute( aMesh, aShape ))
00302       return error( compositeHexa.GetComputeError() );
00303     return true;
00304   }
00305 
00306   // Find sides of a cube
00307   // ---------------------
00308   
00309   FaceQuadStructPtr quad[ 6 ];
00310   StdMeshers_Quadrangle_2D quadAlgo( _gen->GetANewId(), GetStudyId(), _gen);
00311   for ( int i = 0; i < 6; ++i )
00312   {
00313     if ( !( quad[i] = FaceQuadStructPtr( quadAlgo.CheckNbEdges( aMesh, FF( i+1 )))))
00314       return error( quadAlgo.GetComputeError() );
00315     if ( quad[i]->side.size() != 4 )
00316       return error( COMPERR_BAD_SHAPE, "Not a quadrangular box side" );
00317   }
00318 
00319   _FaceGrid aCubeSide[ 6 ];
00320 
00321   swap( aCubeSide[B_BOTTOM]._quad, quad[0] );
00322   swap( aCubeSide[B_BOTTOM]._quad->side[ Q_RIGHT],// direct the normal of bottom quad inside cube
00323         aCubeSide[B_BOTTOM]._quad->side[ Q_LEFT ] );
00324 
00325   aCubeSide[B_FRONT]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_BOTTOM], quad );
00326   aCubeSide[B_RIGHT]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_RIGHT ], quad );
00327   aCubeSide[B_BACK ]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_TOP   ], quad );
00328   aCubeSide[B_LEFT ]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_LEFT  ], quad );
00329   if ( aCubeSide[B_FRONT ]._quad )
00330     aCubeSide[B_TOP  ]._quad = getQuadWithBottom( aCubeSide[B_FRONT ]._quad->side[Q_TOP ], quad );
00331 
00332   for ( int i = 1; i < 6; ++i )
00333     if ( !aCubeSide[i]._quad )
00334       return error( COMPERR_BAD_SHAPE );
00335 
00336   // Make viscous layers
00337   // --------------------
00338 
00339   SMESH_ProxyMesh::Ptr proxymesh;
00340   if ( _viscousLayersHyp )
00341   {
00342     proxymesh = _viscousLayersHyp->Compute( aMesh, aShape, /*makeN2NMap=*/ true );
00343     if ( !proxymesh )
00344       return false;
00345   }
00346 
00347   // Check if there are triangles on cube sides
00348   // -------------------------------------------
00349 
00350   if ( aMesh.NbTriangles() > 0 )
00351   {
00352     for ( int i = 0; i < 6; ++i )
00353     {
00354       const TopoDS_Face& sideF = aCubeSide[i]._quad->face;
00355       if ( SMESHDS_SubMesh* smDS = meshDS->MeshElements( sideF ))
00356       {
00357         bool isAllQuad = true;
00358         SMDS_ElemIteratorPtr fIt = smDS->GetElements();
00359         while ( fIt->more() && isAllQuad )
00360         {
00361           const SMDS_MeshElement* f = fIt->next();
00362           isAllQuad = ( f->NbCornerNodes() == 4 );
00363         }
00364         if ( !isAllQuad )
00365         {
00366           SMESH_ComputeErrorPtr err = ComputePentahedralMesh(aMesh, aShape, proxymesh.get());
00367           return error( err );
00368         }
00369       }
00370     }
00371   }
00372 
00373   // Check presence of regular grid mesh on FACEs of the cube
00374   // ------------------------------------------------------------
00375 
00376   // tool creating quadratic elements if needed
00377   SMESH_MesherHelper helper (aMesh);
00378   _quadraticMesh = helper.IsQuadraticSubMesh(aShape);
00379 
00380   for ( int i = 0; i < 6; ++i )
00381   {
00382     const TopoDS_Face& F = aCubeSide[i]._quad->face;
00383     StdMeshers_FaceSide* baseQuadSide = aCubeSide[i]._quad->side[ Q_BOTTOM ];
00384     vector< TopAbs_Orientation > eOri( baseQuadSide->NbEdges() );
00385 
00386     for ( int iE = 0; iE < baseQuadSide->NbEdges(); ++iE )
00387     {
00388       const TopoDS_Edge& baseE = baseQuadSide->Edge( iE );
00389       eOri[ iE ] = baseE.Orientation();
00390 
00391       // assure correctness of node positions on baseE:
00392       // helper.GetNodeU() will fix positions if they are wrong
00393       if ( SMESHDS_SubMesh* smDS = meshDS->MeshElements( baseE ))
00394       {
00395         bool ok;
00396         helper.SetSubShape( baseE );
00397         SMDS_ElemIteratorPtr eIt = smDS->GetElements();
00398         while ( eIt->more() )
00399         {
00400           const SMDS_MeshElement* e = eIt->next();
00401           helper.GetNodeU( baseE, e->GetNode(0), e->GetNode(1), &ok);
00402           helper.GetNodeU( baseE, e->GetNode(1), e->GetNode(0), &ok);
00403         }
00404       }
00405 
00406       // load grid
00407       TParam2ColumnMap u2nodesMap;
00408       if ( !helper.LoadNodeColumns( u2nodesMap, F, baseE, meshDS, proxymesh.get() ))
00409       {
00410         SMESH_ComputeErrorPtr err = ComputePentahedralMesh(aMesh, aShape, proxymesh.get());
00411         return error( err );
00412       }
00413       // store u2nodesMap
00414       if ( iE == 0 )
00415       {
00416         aCubeSide[i]._u2nodesMap.swap( u2nodesMap );
00417       }
00418       else // unite 2 maps
00419       {
00420         if ( eOri[0] == eOri[iE] )
00421           append( aCubeSide[i]._u2nodesMap, u2nodesMap.begin(), u2nodesMap.end());
00422         else
00423           append( aCubeSide[i]._u2nodesMap, u2nodesMap.rbegin(), u2nodesMap.rend());
00424       }
00425     }
00426     // check if the loaded grid corresponds to nb of quadrangles
00427     const SMESHDS_SubMesh* faceSubMesh =
00428       proxymesh ? proxymesh->GetSubMesh( F ) : meshDS->MeshElements( F );
00429     const int nbQuads = faceSubMesh->NbElements();
00430     const int nbHor = aCubeSide[i]._u2nodesMap.size() - 1;
00431     const int nbVer = aCubeSide[i]._u2nodesMap.begin()->second.size() - 1;
00432     if ( nbQuads != nbHor * nbVer )
00433     {
00434       SMESH_ComputeErrorPtr err = ComputePentahedralMesh(aMesh, aShape, proxymesh.get());
00435       return error( err );
00436     }
00437   }
00438 
00439   // Orient loaded grids of cube sides along axis of the unitary cube coord system
00440   for ( int i = 0; i < 6; ++i )
00441   {
00442     bool reverse = false;
00443     if ( helper.GetSubShapeOri( aShape.Oriented( TopAbs_FORWARD ),
00444                                 aCubeSide[i]._quad->face ) == TopAbs_REVERSED )
00445       reverse = !reverse;
00446 
00447     if ( helper.GetSubShapeOri( aCubeSide[i]._quad->face.Oriented( TopAbs_FORWARD ),
00448                                 aCubeSide[i]._quad->side[0]->Edge(0) ) == TopAbs_REVERSED )
00449       reverse = !reverse;
00450 
00451     if ( i == B_BOTTOM ||
00452          i == B_LEFT   ||
00453          i == B_BACK )
00454       reverse = !reverse;
00455 
00456     aCubeSide[i]._columns.resize( aCubeSide[i]._u2nodesMap.size() );
00457 
00458     int iFwd = 0, iRev = aCubeSide[i]._columns.size()-1;
00459     int* pi = reverse ? &iRev : &iFwd;
00460     TParam2ColumnMap::iterator u2nn = aCubeSide[i]._u2nodesMap.begin();
00461     for ( ; iFwd < aCubeSide[i]._columns.size(); --iRev, ++iFwd, ++u2nn )
00462       aCubeSide[i]._columns[ *pi ].swap( u2nn->second );
00463 
00464     aCubeSide[i]._u2nodesMap.clear();
00465   }
00466   
00467   if ( proxymesh )
00468     for ( int i = 0; i < 6; ++i )
00469       for ( unsigned j = 0; j < aCubeSide[i]._columns.size(); ++j)
00470         for ( unsigned k = 0; k < aCubeSide[i]._columns[j].size(); ++k)
00471         {
00472           const SMDS_MeshNode* & n = aCubeSide[i]._columns[j][k];
00473           n = proxymesh->GetProxyNode( n );
00474         }
00475 
00476   // 4) Create internal nodes of the cube
00477   // -------------------------------------
00478 
00479   helper.SetSubShape( aShape );
00480   helper.SetElementsOnShape(true);
00481 
00482   // shortcuts to sides
00483   _FaceGrid* fBottom = & aCubeSide[ B_BOTTOM ];
00484   _FaceGrid* fRight  = & aCubeSide[ B_RIGHT  ];
00485   _FaceGrid* fTop    = & aCubeSide[ B_TOP    ];
00486   _FaceGrid* fLeft   = & aCubeSide[ B_LEFT   ];
00487   _FaceGrid* fFront  = & aCubeSide[ B_FRONT  ];
00488   _FaceGrid* fBack   = & aCubeSide[ B_BACK   ];
00489 
00490   // cube size measured in nb of nodes
00491   int x, xSize = fBottom->_columns.size() , X = xSize - 1;
00492   int y, ySize = fLeft->_columns.size()   , Y = ySize - 1;
00493   int z, zSize = fLeft->_columns[0].size(), Z = zSize - 1;
00494 
00495   // columns of internal nodes "rising" from nodes of fBottom
00496   _Indexer colIndex( xSize, ySize );
00497   vector< vector< const SMDS_MeshNode* > > columns( colIndex.size() );
00498 
00499   // fill node columns by front and back box sides
00500   for ( x = 0; x < xSize; ++x ) {
00501     vector< const SMDS_MeshNode* >& column0 = columns[ colIndex( x, 0 )];
00502     vector< const SMDS_MeshNode* >& column1 = columns[ colIndex( x, Y )];
00503     column0.resize( zSize );
00504     column1.resize( zSize );
00505     for ( z = 0; z < zSize; ++z ) {
00506       column0[ z ] = fFront->GetNode( x, z );
00507       column1[ z ] = fBack ->GetNode( x, z );
00508     }
00509   }
00510   // fill node columns by left and right box sides
00511   for ( y = 1; y < ySize-1; ++y ) {
00512     vector< const SMDS_MeshNode* >& column0 = columns[ colIndex( 0, y )];
00513     vector< const SMDS_MeshNode* >& column1 = columns[ colIndex( X, y )];
00514     column0.resize( zSize );
00515     column1.resize( zSize );
00516     for ( z = 0; z < zSize; ++z ) {
00517       column0[ z ] = fLeft ->GetNode( y, z );
00518       column1[ z ] = fRight->GetNode( y, z );
00519     }
00520   }
00521   // get nodes from top and bottom box sides
00522   for ( x = 1; x < xSize-1; ++x ) {
00523     for ( y = 1; y < ySize-1; ++y ) {
00524       vector< const SMDS_MeshNode* >& column = columns[ colIndex( x, y )];
00525       column.resize( zSize );
00526       column.front() = fBottom->GetNode( x, y );
00527       column.back()  = fTop   ->GetNode( x, y );
00528     }
00529   }
00530 
00531   // projection points of the internal node on cube sub-shapes by which
00532   // coordinates of the internal node are computed
00533   vector<gp_XYZ> pointsOnShapes( SMESH_Block::ID_Shell );
00534 
00535   // projections on vertices are constant
00536   pointsOnShapes[ SMESH_Block::ID_V000 ] = fBottom->GetXYZ( 0, 0 );
00537   pointsOnShapes[ SMESH_Block::ID_V100 ] = fBottom->GetXYZ( X, 0 );
00538   pointsOnShapes[ SMESH_Block::ID_V010 ] = fBottom->GetXYZ( 0, Y );
00539   pointsOnShapes[ SMESH_Block::ID_V110 ] = fBottom->GetXYZ( X, Y );
00540   pointsOnShapes[ SMESH_Block::ID_V001 ] = fTop->GetXYZ( 0, 0 );
00541   pointsOnShapes[ SMESH_Block::ID_V101 ] = fTop->GetXYZ( X, 0 );
00542   pointsOnShapes[ SMESH_Block::ID_V011 ] = fTop->GetXYZ( 0, Y );
00543   pointsOnShapes[ SMESH_Block::ID_V111 ] = fTop->GetXYZ( X, Y );
00544 
00545   for ( x = 1; x < xSize-1; ++x )
00546   {
00547     gp_XYZ params; // normalized parameters of internal node within a unit box
00548     params.SetCoord( 1, x / double(X) );
00549     for ( y = 1; y < ySize-1; ++y )
00550     {
00551       params.SetCoord( 2, y / double(Y) );
00552       // a column to fill in during z loop
00553       vector< const SMDS_MeshNode* >& column = columns[ colIndex( x, y )];
00554       // projection points on horizontal edges
00555       pointsOnShapes[ SMESH_Block::ID_Ex00 ] = fBottom->GetXYZ( x, 0 );
00556       pointsOnShapes[ SMESH_Block::ID_Ex10 ] = fBottom->GetXYZ( x, Y );
00557       pointsOnShapes[ SMESH_Block::ID_E0y0 ] = fBottom->GetXYZ( 0, y );
00558       pointsOnShapes[ SMESH_Block::ID_E1y0 ] = fBottom->GetXYZ( X, y );
00559       pointsOnShapes[ SMESH_Block::ID_Ex01 ] = fTop->GetXYZ( x, 0 );
00560       pointsOnShapes[ SMESH_Block::ID_Ex11 ] = fTop->GetXYZ( x, Y );
00561       pointsOnShapes[ SMESH_Block::ID_E0y1 ] = fTop->GetXYZ( 0, y );
00562       pointsOnShapes[ SMESH_Block::ID_E1y1 ] = fTop->GetXYZ( X, y );
00563       // projection points on horizontal faces
00564       pointsOnShapes[ SMESH_Block::ID_Fxy0 ] = fBottom->GetXYZ( x, y );
00565       pointsOnShapes[ SMESH_Block::ID_Fxy1 ] = fTop   ->GetXYZ( x, y );
00566       for ( z = 1; z < zSize-1; ++z ) // z loop
00567       {
00568         params.SetCoord( 3, z / double(Z) );
00569         // projection points on vertical edges
00570         pointsOnShapes[ SMESH_Block::ID_E00z ] = fFront->GetXYZ( 0, z );    
00571         pointsOnShapes[ SMESH_Block::ID_E10z ] = fFront->GetXYZ( X, z );    
00572         pointsOnShapes[ SMESH_Block::ID_E01z ] = fBack->GetXYZ( 0, z );    
00573         pointsOnShapes[ SMESH_Block::ID_E11z ] = fBack->GetXYZ( X, z );
00574         // projection points on vertical faces
00575         pointsOnShapes[ SMESH_Block::ID_Fx0z ] = fFront->GetXYZ( x, z );    
00576         pointsOnShapes[ SMESH_Block::ID_Fx1z ] = fBack ->GetXYZ( x, z );    
00577         pointsOnShapes[ SMESH_Block::ID_F0yz ] = fLeft ->GetXYZ( y, z );    
00578         pointsOnShapes[ SMESH_Block::ID_F1yz ] = fRight->GetXYZ( y, z );
00579 
00580         // compute internal node coordinates
00581         gp_XYZ coords;
00582         SMESH_Block::ShellPoint( params, pointsOnShapes, coords );
00583         column[ z ] = helper.AddNode( coords.X(), coords.Y(), coords.Z() );
00584 
00585       }
00586     }
00587   }
00588 
00589   // side data no more needed, free memory
00590   for ( int i = 0; i < 6; ++i )
00591     aCubeSide[i]._columns.clear();
00592 
00593   // 5) Create hexahedrons
00594   // ---------------------
00595 
00596   for ( x = 0; x < xSize-1; ++x ) {
00597     for ( y = 0; y < ySize-1; ++y ) {
00598       vector< const SMDS_MeshNode* >& col00 = columns[ colIndex( x, y )];
00599       vector< const SMDS_MeshNode* >& col10 = columns[ colIndex( x+1, y )];
00600       vector< const SMDS_MeshNode* >& col01 = columns[ colIndex( x, y+1 )];
00601       vector< const SMDS_MeshNode* >& col11 = columns[ colIndex( x+1, y+1 )];
00602       for ( z = 0; z < zSize-1; ++z )
00603       {
00604         // bottom face normal of a hexa mush point outside the volume
00605         helper.AddVolume(col00[z],   col01[z],   col11[z],   col10[z],
00606                          col00[z+1], col01[z+1], col11[z+1], col10[z+1]);
00607       }
00608     }
00609   }
00610   return true;
00611 }
00612 
00613 //=============================================================================
00617 //=============================================================================
00618 
00619 bool StdMeshers_Hexa_3D::Evaluate(SMESH_Mesh & aMesh,
00620                                   const TopoDS_Shape & aShape,
00621                                   MapShapeNbElems& aResMap)
00622 {
00623   vector < SMESH_subMesh * >meshFaces;
00624   TopTools_SequenceOfShape aFaces;
00625   for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) {
00626     aFaces.Append(exp.Current());
00627     SMESH_subMesh *aSubMesh = aMesh.GetSubMeshContaining(exp.Current());
00628     ASSERT(aSubMesh);
00629     meshFaces.push_back(aSubMesh);
00630   }
00631   if (meshFaces.size() != 6) {
00632     //return error(COMPERR_BAD_SHAPE, TComm(meshFaces.size())<<" instead of 6 faces in a block");
00633     static StdMeshers_CompositeHexa_3D compositeHexa(-10, 0, aMesh.GetGen());
00634     return compositeHexa.Evaluate(aMesh, aShape, aResMap);
00635   }
00636   
00637   int i = 0;
00638   for(; i<6; i++) {
00639     //TopoDS_Shape aFace = meshFaces[i]->GetSubShape();
00640     TopoDS_Shape aFace = aFaces.Value(i+1);
00641     SMESH_Algo *algo = _gen->GetAlgo(aMesh, aFace);
00642     if( !algo ) {
00643       std::vector<int> aResVec(SMDSEntity_Last);
00644       for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
00645       SMESH_subMesh * sm = aMesh.GetSubMesh(aShape);
00646       aResMap.insert(std::make_pair(sm,aResVec));
00647       SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
00648       smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this));
00649       return false;
00650     }
00651     string algoName = algo->GetName();
00652     bool isAllQuad = false;
00653     if (algoName == "Quadrangle_2D") {
00654       MapShapeNbElemsItr anIt = aResMap.find(meshFaces[i]);
00655       if( anIt == aResMap.end() ) continue;
00656       std::vector<int> aVec = (*anIt).second;
00657       int nbtri = Max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]);
00658       if( nbtri == 0 )
00659         isAllQuad = true;
00660     }
00661     if ( ! isAllQuad ) {
00662       return EvaluatePentahedralMesh(aMesh, aShape, aResMap);
00663     }
00664   }
00665   
00666   // find number of 1d elems for 1 face
00667   int nb1d = 0;
00668   TopTools_MapOfShape Edges1;
00669   bool IsQuadratic = false;
00670   bool IsFirst = true;
00671   for (TopExp_Explorer exp(aFaces.Value(1), TopAbs_EDGE); exp.More(); exp.Next()) {
00672     Edges1.Add(exp.Current());
00673     SMESH_subMesh *sm = aMesh.GetSubMesh(exp.Current());
00674     if( sm ) {
00675       MapShapeNbElemsItr anIt = aResMap.find(sm);
00676       if( anIt == aResMap.end() ) continue;
00677       std::vector<int> aVec = (*anIt).second;
00678       nb1d += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]);
00679       if(IsFirst) {
00680         IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]);
00681         IsFirst = false;
00682       }
00683     }
00684   }
00685   // find face opposite to 1 face
00686   int OppNum = 0;
00687   for(i=2; i<=6; i++) {
00688     bool IsOpposite = true;
00689     for(TopExp_Explorer exp(aFaces.Value(i), TopAbs_EDGE); exp.More(); exp.Next()) {
00690       if( Edges1.Contains(exp.Current()) ) {
00691         IsOpposite = false;
00692         break;
00693       }
00694     }
00695     if(IsOpposite) {
00696       OppNum = i;
00697       break;
00698     }
00699   }
00700   // find number of 2d elems on side faces
00701   int nb2d = 0;
00702   for(i=2; i<=6; i++) {
00703     if( i == OppNum ) continue;
00704     MapShapeNbElemsItr anIt = aResMap.find( meshFaces[i-1] );
00705     if( anIt == aResMap.end() ) continue;
00706     std::vector<int> aVec = (*anIt).second;
00707     nb2d += Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
00708   }
00709   
00710   MapShapeNbElemsItr anIt = aResMap.find( meshFaces[0] );
00711   std::vector<int> aVec = (*anIt).second;
00712   int nb2d_face0 = Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
00713   int nb0d_face0 = aVec[SMDSEntity_Node];
00714 
00715   std::vector<int> aResVec(SMDSEntity_Last);
00716   for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
00717   if(IsQuadratic) {
00718     aResVec[SMDSEntity_Quad_Hexa] = nb2d_face0 * ( nb2d/nb1d );
00719     int nb1d_face0_int = ( nb2d_face0*4 - nb1d ) / 2;
00720     aResVec[SMDSEntity_Node] = nb0d_face0 * ( 2*nb2d/nb1d - 1 ) - nb1d_face0_int * nb2d/nb1d;
00721   }
00722   else {
00723     aResVec[SMDSEntity_Node] = nb0d_face0 * ( nb2d/nb1d - 1 );
00724     aResVec[SMDSEntity_Hexa] = nb2d_face0 * ( nb2d/nb1d );
00725   }
00726   SMESH_subMesh * sm = aMesh.GetSubMesh(aShape);
00727   aResMap.insert(std::make_pair(sm,aResVec));
00728 
00729   return true;
00730 }
00731 
00732 //================================================================================
00736 //================================================================================
00737 
00738 bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh, SMESH_MesherHelper* aHelper)
00739 {
00740   static StdMeshers_HexaFromSkin_3D * algo = 0;
00741   if ( !algo ) {
00742     SMESH_Gen* gen = aMesh.GetGen();
00743     algo = new StdMeshers_HexaFromSkin_3D( gen->GetANewId(), 0, gen );
00744   }
00745   algo->InitComputeError();
00746   algo->Compute( aMesh, aHelper );
00747   return error( algo->GetComputeError());
00748 }
00749 
00750 //=======================================================================
00751 //function : ComputePentahedralMesh
00752 //purpose  : 
00753 //=======================================================================
00754 
00755 SMESH_ComputeErrorPtr ComputePentahedralMesh(SMESH_Mesh &          aMesh,
00756                                              const TopoDS_Shape &  aShape,
00757                                              SMESH_ProxyMesh*      proxyMesh)
00758 {
00759   SMESH_ComputeErrorPtr err = SMESH_ComputeError::New();
00760   if ( proxyMesh )
00761   {
00762     err->myName = COMPERR_BAD_INPUT_MESH;
00763     err->myComment = "Can't build pentahedral mesh on viscous layers";
00764     return err;
00765   }
00766   bool bOK;
00767   StdMeshers_Penta_3D anAlgo;
00768   //
00769   bOK=anAlgo.Compute(aMesh, aShape);
00770   //
00771   err = anAlgo.GetComputeError();
00772   //
00773   if ( !bOK && anAlgo.ErrorStatus() == 5 )
00774   {
00775     static StdMeshers_Prism_3D * aPrism3D = 0;
00776     if ( !aPrism3D ) {
00777       SMESH_Gen* gen = aMesh.GetGen();
00778       aPrism3D = new StdMeshers_Prism_3D( gen->GetANewId(), 0, gen );
00779     }
00780     SMESH_Hypothesis::Hypothesis_Status aStatus;
00781     if ( aPrism3D->CheckHypothesis( aMesh, aShape, aStatus ) ) {
00782       aPrism3D->InitComputeError();
00783       bOK = aPrism3D->Compute( aMesh, aShape );
00784       err = aPrism3D->GetComputeError();
00785     }
00786   }
00787   return err;
00788 }
00789 
00790 
00791 //=======================================================================
00792 //function : EvaluatePentahedralMesh
00793 //purpose  : 
00794 //=======================================================================
00795 
00796 bool EvaluatePentahedralMesh(SMESH_Mesh & aMesh,
00797                              const TopoDS_Shape & aShape,
00798                              MapShapeNbElems& aResMap)
00799 {
00800   StdMeshers_Penta_3D anAlgo;
00801   bool bOK = anAlgo.Evaluate(aMesh, aShape, aResMap);
00802 
00803   //err = anAlgo.GetComputeError();
00804   //if ( !bOK && anAlgo.ErrorStatus() == 5 )
00805   if( !bOK ) {
00806     static StdMeshers_Prism_3D * aPrism3D = 0;
00807     if ( !aPrism3D ) {
00808       SMESH_Gen* gen = aMesh.GetGen();
00809       aPrism3D = new StdMeshers_Prism_3D( gen->GetANewId(), 0, gen );
00810     }
00811     SMESH_Hypothesis::Hypothesis_Status aStatus;
00812     if ( aPrism3D->CheckHypothesis( aMesh, aShape, aStatus ) ) {
00813       return aPrism3D->Evaluate(aMesh, aShape, aResMap);
00814     }
00815   }
00816 
00817   return bOK;
00818 }
Copyright © 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
Copyright © 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS