00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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);
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
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 _viscousLayersHyp = NULL;
00125
00126 const list<const SMESHDS_Hypothesis*>& hyps =
00127 GetUsedHypothesis(aMesh, aShape, 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
00163 enum EBoxSides{ B_BOTTOM=0, B_RIGHT, B_TOP, B_LEFT, B_FRONT, B_BACK, B_NB_SIDES };
00164
00165
00166 enum EQuadSides{ Q_BOTTOM=0, Q_RIGHT, Q_TOP, Q_LEFT, Q_NB_SIDES };
00167
00168
00172 struct _FaceGrid
00173 {
00174
00175 FaceQuadStructPtr _quad;
00176
00177
00178 TParam2ColumnMap _u2nodesMap;
00179
00180
00181 vector<TNodeColumn> _columns;
00182
00183
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)
00280 {
00281
00282
00283 MESSAGE("StdMeshers_Hexa_3D::Compute");
00284 SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
00285
00286
00287
00288
00289
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
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],
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
00337
00338
00339 SMESH_ProxyMesh::Ptr proxymesh;
00340 if ( _viscousLayersHyp )
00341 {
00342 proxymesh = _viscousLayersHyp->Compute( aMesh, aShape, true );
00343 if ( !proxymesh )
00344 return false;
00345 }
00346
00347
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
00374
00375
00376
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
00392
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
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
00414 if ( iE == 0 )
00415 {
00416 aCubeSide[i]._u2nodesMap.swap( u2nodesMap );
00417 }
00418 else
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
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
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
00477
00478
00479 helper.SetSubShape( aShape );
00480 helper.SetElementsOnShape(true);
00481
00482
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
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
00496 _Indexer colIndex( xSize, ySize );
00497 vector< vector< const SMDS_MeshNode* > > columns( colIndex.size() );
00498
00499
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
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
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
00532
00533 vector<gp_XYZ> pointsOnShapes( SMESH_Block::ID_Shell );
00534
00535
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;
00548 params.SetCoord( 1, x / double(X) );
00549 for ( y = 1; y < ySize-1; ++y )
00550 {
00551 params.SetCoord( 2, y / double(Y) );
00552
00553 vector< const SMDS_MeshNode* >& column = columns[ colIndex( x, y )];
00554
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
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 )
00567 {
00568 params.SetCoord( 3, z / double(Z) );
00569
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
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
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
00590 for ( int i = 0; i < 6; ++i )
00591 aCubeSide[i]._columns.clear();
00592
00593
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
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
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
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
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
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
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
00752
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
00793
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
00804
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 }