1 // Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // SMESH SMESH : implementaion of SMESH idl descriptions
24 // File : StdMeshers_Hexa_3D.cxx
25 // Moved here from SMESH_Hexa_3D.cxx
26 // Author : Paul RASCLE, EDF
29 #include "StdMeshers_Hexa_3D.hxx"
31 #include "StdMeshers_CompositeHexa_3D.hxx"
32 #include "StdMeshers_FaceSide.hxx"
33 #include "StdMeshers_HexaFromSkin_3D.hxx"
34 #include "StdMeshers_Penta_3D.hxx"
35 #include "StdMeshers_Prism_3D.hxx"
36 #include "StdMeshers_Quadrangle_2D.hxx"
37 #include "StdMeshers_ViscousLayers.hxx"
39 #include "SMESH_Comment.hxx"
40 #include "SMESH_Gen.hxx"
41 #include "SMESH_Mesh.hxx"
42 #include "SMESH_MesherHelper.hxx"
43 #include "SMESH_subMesh.hxx"
45 #include "SMDS_MeshNode.hxx"
48 #include <TopExp_Explorer.hxx>
49 #include <TopTools_SequenceOfShape.hxx>
50 #include <TopTools_MapOfShape.hxx>
53 #include "utilities.h"
54 #include "Utils_ExceptHandlers.hxx"
56 typedef SMESH_Comment TComm;
60 static SMESH_ComputeErrorPtr ComputePentahedralMesh(SMESH_Mesh &,
62 SMESH_ProxyMesh* proxyMesh=0);
64 static bool EvaluatePentahedralMesh(SMESH_Mesh &, const TopoDS_Shape &,
67 //=============================================================================
71 //=============================================================================
73 StdMeshers_Hexa_3D::StdMeshers_Hexa_3D(int hypId, int studyId, SMESH_Gen * gen)
74 :SMESH_3D_Algo(hypId, studyId, gen)
76 MESSAGE("StdMeshers_Hexa_3D::StdMeshers_Hexa_3D");
78 _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID); // 1 bit /shape type
79 _requireShape = false;
80 _compatibleHypothesis.push_back("ViscousLayers");
83 //=============================================================================
87 //=============================================================================
89 StdMeshers_Hexa_3D::~StdMeshers_Hexa_3D()
91 MESSAGE("StdMeshers_Hexa_3D::~StdMeshers_Hexa_3D");
94 //=============================================================================
96 * Retrieves defined hypotheses
98 //=============================================================================
100 bool StdMeshers_Hexa_3D::CheckHypothesis
102 const TopoDS_Shape& aShape,
103 SMESH_Hypothesis::Hypothesis_Status& aStatus)
105 // check nb of faces in the shape
107 aStatus = SMESH_Hypothesis::HYP_BAD_GEOMETRY;
109 for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next())
116 _viscousLayersHyp = NULL;
118 const list<const SMESHDS_Hypothesis*>& hyps =
119 GetUsedHypothesis(aMesh, aShape, /*ignoreAuxiliary=*/false);
120 list <const SMESHDS_Hypothesis* >::const_iterator h = hyps.begin();
121 if ( h == hyps.end())
123 aStatus = SMESH_Hypothesis::HYP_OK;
128 for ( ; h != hyps.end(); ++h )
130 string hypName = (*h)->GetName();
131 if ( find( _compatibleHypothesis.begin(),_compatibleHypothesis.end(),hypName )
132 != _compatibleHypothesis.end() )
134 _viscousLayersHyp = dynamic_cast< const StdMeshers_ViscousLayers*> ( *h );
138 aStatus = HYP_INCOMPATIBLE;
142 if ( !_viscousLayersHyp )
143 aStatus = HYP_INCOMPATIBLE;
145 return aStatus == HYP_OK;
150 //=============================================================================
152 typedef boost::shared_ptr< FaceQuadStruct > FaceQuadStructPtr;
154 // symbolic names of box sides
155 enum EBoxSides{ B_BOTTOM=0, B_RIGHT, B_TOP, B_LEFT, B_FRONT, B_BACK, B_NB_SIDES };
157 // symbolic names of sides of quadrangle
158 enum EQuadSides{ Q_BOTTOM=0, Q_RIGHT, Q_TOP, Q_LEFT, Q_NB_SIDES };
160 //=============================================================================
162 * \brief Container of nodes of structured mesh on a qudrangular geom FACE
167 FaceQuadStructPtr _quad;
169 // map of (node parameter on EDGE) to (column (vector) of nodes)
170 TParam2ColumnMap _u2nodesMap;
172 // node column's taken form _u2nodesMap taking into account sub-shape orientation
173 vector<TNodeColumn> _columns;
175 // geometry of a cube side
178 const SMDS_MeshNode* GetNode(int iCol, int iRow) const
180 return _columns[iCol][iRow];
182 gp_XYZ GetXYZ(int iCol, int iRow) const
184 return SMESH_TNodeXYZ( GetNode( iCol, iRow ));
188 //================================================================================
190 * \brief Convertor of a pair of integers to a sole index
195 _Indexer( int xSize, int ySize ): _xSize(xSize), _ySize(ySize) {}
196 int size() const { return _xSize * _ySize; }
197 int operator()(const int x, const int y) const { return y * _xSize + x; }
200 //================================================================================
202 * \brief Appends a range of node columns from a map to another map
204 template< class TMapIterator >
205 void append( TParam2ColumnMap& toMap, TMapIterator from, TMapIterator to )
207 const SMDS_MeshNode* lastNode = toMap.rbegin()->second[0];
208 const SMDS_MeshNode* firstNode = from->second[0];
209 if ( lastNode == firstNode )
211 double u = toMap.rbegin()->first;
212 for (; from != to; ++from )
215 TParam2ColumnMap::iterator u2nn = toMap.insert( toMap.end(), make_pair ( u, TNodeColumn()));
216 u2nn->second.swap( from->second );
220 //================================================================================
222 * \brief Finds FaceQuadStruct having a side equal to a given one and rearranges
223 * the found FaceQuadStruct::side to have the given side at a Q_BOTTOM place
225 FaceQuadStructPtr getQuadWithBottom( StdMeshers_FaceSide* side,
226 FaceQuadStructPtr quad[ 6 ])
228 FaceQuadStructPtr foundQuad;
229 for ( int i = 1; i < 6; ++i )
231 if ( !quad[i] ) continue;
232 for ( unsigned iS = 0; iS < quad[i]->side.size(); ++iS )
234 const StdMeshers_FaceSide* side2 = quad[i]->side[iS];
235 if (( side->FirstVertex().IsSame( side2->FirstVertex() ) ||
236 side->FirstVertex().IsSame( side2->LastVertex() ))
238 ( side->LastVertex().IsSame( side2->FirstVertex() ) ||
239 side->LastVertex().IsSame( side2->LastVertex() ))
242 if ( iS != Q_BOTTOM )
244 vector< StdMeshers_FaceSide*> newSides;
245 for ( unsigned j = iS; j < quad[i]->side.size(); ++j )
246 newSides.push_back( quad[i]->side[j] );
247 for ( unsigned j = 0; j < iS; ++j )
248 newSides.push_back( quad[i]->side[j] );
249 quad[i]->side.swap( newSides );
251 foundQuad.swap(quad[i]);
258 //================================================================================
260 * \brief Returns true if the 1st base node of sideGrid1 belongs to sideGrid2
262 //================================================================================
264 bool beginsAtSide( const _FaceGrid& sideGrid1, const _FaceGrid& sideGrid2 )
266 const SMDS_MeshNode* n00 = (sideGrid1._u2nodesMap.begin()->second)[0];
267 const TNodeColumn& col0 = sideGrid2._u2nodesMap.begin()->second;
268 const TNodeColumn& col1 = sideGrid2._u2nodesMap.rbegin()->second;
269 return ( n00 == col0.front() || n00 == col0.back() ||
270 n00 == col1.front() || n00 == col1.back() );
274 //=============================================================================
276 * Generates hexahedron mesh on hexaedron like form using algorithm from
277 * "Application de l'interpolation transfinie à la création de maillages
278 * C0 ou G1 continus sur des triangles, quadrangles, tetraedres, pentaedres
279 * et hexaedres déformés."
280 * Alain PERONNET - 8 janvier 1999
282 //=============================================================================
284 bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh,
285 const TopoDS_Shape & aShape)// throw(SALOME_Exception)
287 // PAL14921. Enable catching std::bad_alloc and Standard_OutOfMemory outside
288 //Unexpect aCatch(SalomeException);
289 MESSAGE("StdMeshers_Hexa_3D::Compute");
290 SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
292 // Shape verification
293 // ----------------------
295 // shape must be a solid (or a shell) with 6 faces
296 TopExp_Explorer exp(aShape,TopAbs_SHELL);
298 return error(COMPERR_BAD_SHAPE, "No SHELL in the geometry");
299 if ( exp.Next(), exp.More() )
300 return error(COMPERR_BAD_SHAPE, "More than one SHELL in the geometry");
302 TopTools_IndexedMapOfShape FF;
303 TopExp::MapShapes( aShape, TopAbs_FACE, FF);
304 if ( FF.Extent() != 6)
306 static StdMeshers_CompositeHexa_3D compositeHexa(_gen->GetANewId(), 0, _gen);
307 if ( !compositeHexa.Compute( aMesh, aShape ))
308 return error( compositeHexa.GetComputeError() );
312 // Find sides of a cube
313 // ---------------------
315 FaceQuadStructPtr quad[ 6 ];
316 StdMeshers_Quadrangle_2D quadAlgo( _gen->GetANewId(), GetStudyId(), _gen);
317 for ( int i = 0; i < 6; ++i )
319 if ( !( quad[i] = FaceQuadStructPtr( quadAlgo.CheckNbEdges( aMesh, FF( i+1 )))))
320 return error( quadAlgo.GetComputeError() );
321 if ( quad[i]->side.size() != 4 )
322 return error( COMPERR_BAD_SHAPE, "Not a quadrangular box side" );
325 _FaceGrid aCubeSide[ 6 ];
327 swap( aCubeSide[B_BOTTOM]._quad, quad[0] );
328 swap( aCubeSide[B_BOTTOM]._quad->side[ Q_RIGHT],// direct the normal of bottom quad inside cube
329 aCubeSide[B_BOTTOM]._quad->side[ Q_LEFT ] );
331 aCubeSide[B_FRONT]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_BOTTOM], quad );
332 aCubeSide[B_RIGHT]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_RIGHT ], quad );
333 aCubeSide[B_BACK ]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_TOP ], quad );
334 aCubeSide[B_LEFT ]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_LEFT ], quad );
335 if ( aCubeSide[B_FRONT ]._quad )
336 aCubeSide[B_TOP]._quad = getQuadWithBottom( aCubeSide[B_FRONT ]._quad->side[Q_TOP ], quad );
338 for ( int i = 1; i < 6; ++i )
339 if ( !aCubeSide[i]._quad )
340 return error( COMPERR_BAD_SHAPE );
342 // Make viscous layers
343 // --------------------
345 SMESH_ProxyMesh::Ptr proxymesh;
346 if ( _viscousLayersHyp )
348 proxymesh = _viscousLayersHyp->Compute( aMesh, aShape, /*makeN2NMap=*/ true );
353 // Check if there are triangles on cube sides
354 // -------------------------------------------
356 if ( aMesh.NbTriangles() > 0 )
358 for ( int i = 0; i < 6; ++i )
360 const TopoDS_Face& sideF = aCubeSide[i]._quad->face;
361 if ( SMESHDS_SubMesh* smDS = meshDS->MeshElements( sideF ))
363 bool isAllQuad = true;
364 SMDS_ElemIteratorPtr fIt = smDS->GetElements();
365 while ( fIt->more() && isAllQuad )
367 const SMDS_MeshElement* f = fIt->next();
368 isAllQuad = ( f->NbCornerNodes() == 4 );
372 SMESH_ComputeErrorPtr err = ComputePentahedralMesh(aMesh, aShape, proxymesh.get());
379 // Check presence of regular grid mesh on FACEs of the cube
380 // ------------------------------------------------------------
382 // tool creating quadratic elements if needed
383 SMESH_MesherHelper helper (aMesh);
384 _quadraticMesh = helper.IsQuadraticSubMesh(aShape);
386 for ( int i = 0; i < 6; ++i )
388 const TopoDS_Face& F = aCubeSide[i]._quad->face;
389 StdMeshers_FaceSide* baseQuadSide = aCubeSide[i]._quad->side[ Q_BOTTOM ];
390 list<TopoDS_Edge> baseEdges( baseQuadSide->Edges().begin(), baseQuadSide->Edges().end() );
392 // assure correctness of node positions on baseE:
393 // helper.GetNodeU() will fix positions if they are wrong
394 for ( int iE = 0; iE < baseQuadSide->NbEdges(); ++iE )
396 const TopoDS_Edge& baseE = baseQuadSide->Edge( iE );
397 if ( SMESHDS_SubMesh* smDS = meshDS->MeshElements( baseE ))
400 helper.SetSubShape( baseE );
401 SMDS_ElemIteratorPtr eIt = smDS->GetElements();
402 while ( eIt->more() )
404 const SMDS_MeshElement* e = eIt->next();
405 // expect problems on a composite side
406 try { helper.GetNodeU( baseE, e->GetNode(0), e->GetNode(1), &ok); }
408 try { helper.GetNodeU( baseE, e->GetNode(1), e->GetNode(0), &ok); }
416 helper.LoadNodeColumns( aCubeSide[i]._u2nodesMap, F, baseEdges, meshDS, proxymesh.get());
419 // check if the loaded grid corresponds to nb of quadrangles on the FACE
420 const SMESHDS_SubMesh* faceSubMesh =
421 proxymesh ? proxymesh->GetSubMesh( F ) : meshDS->MeshElements( F );
422 const int nbQuads = faceSubMesh->NbElements();
423 const int nbHor = aCubeSide[i]._u2nodesMap.size() - 1;
424 const int nbVer = aCubeSide[i]._u2nodesMap.begin()->second.size() - 1;
425 ok = ( nbQuads == nbHor * nbVer );
429 SMESH_ComputeErrorPtr err = ComputePentahedralMesh(aMesh, aShape, proxymesh.get());
434 // Orient loaded grids of cube sides along axis of the unitary cube coord system
436 isReverse[B_BOTTOM] = beginsAtSide( aCubeSide[B_BOTTOM], aCubeSide[B_RIGHT ] );
437 isReverse[B_TOP ] = beginsAtSide( aCubeSide[B_TOP ], aCubeSide[B_RIGHT ] );
438 isReverse[B_FRONT ] = beginsAtSide( aCubeSide[B_FRONT ], aCubeSide[B_RIGHT ] );
439 isReverse[B_BACK ] = beginsAtSide( aCubeSide[B_BACK ], aCubeSide[B_RIGHT ] );
440 isReverse[B_LEFT ] = beginsAtSide( aCubeSide[B_LEFT ], aCubeSide[B_BACK ] );
441 isReverse[B_RIGHT ] = beginsAtSide( aCubeSide[B_RIGHT ], aCubeSide[B_BACK ] );
442 for ( int i = 0; i < 6; ++i )
444 aCubeSide[i]._columns.resize( aCubeSide[i]._u2nodesMap.size() );
446 int iFwd = 0, iRev = aCubeSide[i]._columns.size()-1;
447 int* pi = isReverse[i] ? &iRev : &iFwd;
448 TParam2ColumnMap::iterator u2nn = aCubeSide[i]._u2nodesMap.begin();
449 for ( ; iFwd < aCubeSide[i]._columns.size(); --iRev, ++iFwd, ++u2nn )
450 aCubeSide[i]._columns[ *pi ].swap( u2nn->second );
452 aCubeSide[i]._u2nodesMap.clear();
456 for ( int i = 0; i < 6; ++i )
457 for ( unsigned j = 0; j < aCubeSide[i]._columns.size(); ++j)
458 for ( unsigned k = 0; k < aCubeSide[i]._columns[j].size(); ++k)
460 const SMDS_MeshNode* & n = aCubeSide[i]._columns[j][k];
461 n = proxymesh->GetProxyNode( n );
464 // 4) Create internal nodes of the cube
465 // -------------------------------------
467 helper.SetSubShape( aShape );
468 helper.SetElementsOnShape(true);
470 // shortcuts to sides
471 _FaceGrid* fBottom = & aCubeSide[ B_BOTTOM ];
472 _FaceGrid* fRight = & aCubeSide[ B_RIGHT ];
473 _FaceGrid* fTop = & aCubeSide[ B_TOP ];
474 _FaceGrid* fLeft = & aCubeSide[ B_LEFT ];
475 _FaceGrid* fFront = & aCubeSide[ B_FRONT ];
476 _FaceGrid* fBack = & aCubeSide[ B_BACK ];
478 // cube size measured in nb of nodes
479 int x, xSize = fBottom->_columns.size() , X = xSize - 1;
480 int y, ySize = fLeft->_columns.size() , Y = ySize - 1;
481 int z, zSize = fLeft->_columns[0].size(), Z = zSize - 1;
483 // columns of internal nodes "rising" from nodes of fBottom
484 _Indexer colIndex( xSize, ySize );
485 vector< vector< const SMDS_MeshNode* > > columns( colIndex.size() );
487 // fill node columns by front and back box sides
488 for ( x = 0; x < xSize; ++x ) {
489 vector< const SMDS_MeshNode* >& column0 = columns[ colIndex( x, 0 )];
490 vector< const SMDS_MeshNode* >& column1 = columns[ colIndex( x, Y )];
491 column0.resize( zSize );
492 column1.resize( zSize );
493 for ( z = 0; z < zSize; ++z ) {
494 column0[ z ] = fFront->GetNode( x, z );
495 column1[ z ] = fBack ->GetNode( x, z );
498 // fill node columns by left and right box sides
499 for ( y = 1; y < ySize-1; ++y ) {
500 vector< const SMDS_MeshNode* >& column0 = columns[ colIndex( 0, y )];
501 vector< const SMDS_MeshNode* >& column1 = columns[ colIndex( X, y )];
502 column0.resize( zSize );
503 column1.resize( zSize );
504 for ( z = 0; z < zSize; ++z ) {
505 column0[ z ] = fLeft ->GetNode( y, z );
506 column1[ z ] = fRight->GetNode( y, z );
509 // get nodes from top and bottom box sides
510 for ( x = 1; x < xSize-1; ++x ) {
511 for ( y = 1; y < ySize-1; ++y ) {
512 vector< const SMDS_MeshNode* >& column = columns[ colIndex( x, y )];
513 column.resize( zSize );
514 column.front() = fBottom->GetNode( x, y );
515 column.back() = fTop ->GetNode( x, y );
519 // projection points of the internal node on cube sub-shapes by which
520 // coordinates of the internal node are computed
521 vector<gp_XYZ> pointsOnShapes( SMESH_Block::ID_Shell );
523 // projections on vertices are constant
524 pointsOnShapes[ SMESH_Block::ID_V000 ] = fBottom->GetXYZ( 0, 0 );
525 pointsOnShapes[ SMESH_Block::ID_V100 ] = fBottom->GetXYZ( X, 0 );
526 pointsOnShapes[ SMESH_Block::ID_V010 ] = fBottom->GetXYZ( 0, Y );
527 pointsOnShapes[ SMESH_Block::ID_V110 ] = fBottom->GetXYZ( X, Y );
528 pointsOnShapes[ SMESH_Block::ID_V001 ] = fTop->GetXYZ( 0, 0 );
529 pointsOnShapes[ SMESH_Block::ID_V101 ] = fTop->GetXYZ( X, 0 );
530 pointsOnShapes[ SMESH_Block::ID_V011 ] = fTop->GetXYZ( 0, Y );
531 pointsOnShapes[ SMESH_Block::ID_V111 ] = fTop->GetXYZ( X, Y );
533 for ( x = 1; x < xSize-1; ++x )
535 gp_XYZ params; // normalized parameters of internal node within a unit box
536 params.SetCoord( 1, x / double(X) );
537 for ( y = 1; y < ySize-1; ++y )
539 params.SetCoord( 2, y / double(Y) );
540 // a column to fill in during z loop
541 vector< const SMDS_MeshNode* >& column = columns[ colIndex( x, y )];
542 // projection points on horizontal edges
543 pointsOnShapes[ SMESH_Block::ID_Ex00 ] = fBottom->GetXYZ( x, 0 );
544 pointsOnShapes[ SMESH_Block::ID_Ex10 ] = fBottom->GetXYZ( x, Y );
545 pointsOnShapes[ SMESH_Block::ID_E0y0 ] = fBottom->GetXYZ( 0, y );
546 pointsOnShapes[ SMESH_Block::ID_E1y0 ] = fBottom->GetXYZ( X, y );
547 pointsOnShapes[ SMESH_Block::ID_Ex01 ] = fTop->GetXYZ( x, 0 );
548 pointsOnShapes[ SMESH_Block::ID_Ex11 ] = fTop->GetXYZ( x, Y );
549 pointsOnShapes[ SMESH_Block::ID_E0y1 ] = fTop->GetXYZ( 0, y );
550 pointsOnShapes[ SMESH_Block::ID_E1y1 ] = fTop->GetXYZ( X, y );
551 // projection points on horizontal faces
552 pointsOnShapes[ SMESH_Block::ID_Fxy0 ] = fBottom->GetXYZ( x, y );
553 pointsOnShapes[ SMESH_Block::ID_Fxy1 ] = fTop ->GetXYZ( x, y );
554 for ( z = 1; z < zSize-1; ++z ) // z loop
556 params.SetCoord( 3, z / double(Z) );
557 // projection points on vertical edges
558 pointsOnShapes[ SMESH_Block::ID_E00z ] = fFront->GetXYZ( 0, z );
559 pointsOnShapes[ SMESH_Block::ID_E10z ] = fFront->GetXYZ( X, z );
560 pointsOnShapes[ SMESH_Block::ID_E01z ] = fBack->GetXYZ( 0, z );
561 pointsOnShapes[ SMESH_Block::ID_E11z ] = fBack->GetXYZ( X, z );
562 // projection points on vertical faces
563 pointsOnShapes[ SMESH_Block::ID_Fx0z ] = fFront->GetXYZ( x, z );
564 pointsOnShapes[ SMESH_Block::ID_Fx1z ] = fBack ->GetXYZ( x, z );
565 pointsOnShapes[ SMESH_Block::ID_F0yz ] = fLeft ->GetXYZ( y, z );
566 pointsOnShapes[ SMESH_Block::ID_F1yz ] = fRight->GetXYZ( y, z );
568 // compute internal node coordinates
570 SMESH_Block::ShellPoint( params, pointsOnShapes, coords );
571 column[ z ] = helper.AddNode( coords.X(), coords.Y(), coords.Z() );
577 // side data no more needed, free memory
578 for ( int i = 0; i < 6; ++i )
579 aCubeSide[i]._columns.clear();
581 // 5) Create hexahedrons
582 // ---------------------
584 for ( x = 0; x < xSize-1; ++x ) {
585 for ( y = 0; y < ySize-1; ++y ) {
586 vector< const SMDS_MeshNode* >& col00 = columns[ colIndex( x, y )];
587 vector< const SMDS_MeshNode* >& col10 = columns[ colIndex( x+1, y )];
588 vector< const SMDS_MeshNode* >& col01 = columns[ colIndex( x, y+1 )];
589 vector< const SMDS_MeshNode* >& col11 = columns[ colIndex( x+1, y+1 )];
590 for ( z = 0; z < zSize-1; ++z )
592 // bottom face normal of a hexa mush point outside the volume
593 helper.AddVolume(col00[z], col01[z], col11[z], col10[z],
594 col00[z+1], col01[z+1], col11[z+1], col10[z+1]);
601 //=============================================================================
605 //=============================================================================
607 bool StdMeshers_Hexa_3D::Evaluate(SMESH_Mesh & aMesh,
608 const TopoDS_Shape & aShape,
609 MapShapeNbElems& aResMap)
611 vector < SMESH_subMesh * >meshFaces;
612 TopTools_SequenceOfShape aFaces;
613 for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) {
614 aFaces.Append(exp.Current());
615 SMESH_subMesh *aSubMesh = aMesh.GetSubMeshContaining(exp.Current());
617 meshFaces.push_back(aSubMesh);
619 if (meshFaces.size() != 6) {
620 //return error(COMPERR_BAD_SHAPE, TComm(meshFaces.size())<<" instead of 6 faces in a block");
621 static StdMeshers_CompositeHexa_3D compositeHexa(-10, 0, aMesh.GetGen());
622 return compositeHexa.Evaluate(aMesh, aShape, aResMap);
627 //TopoDS_Shape aFace = meshFaces[i]->GetSubShape();
628 TopoDS_Shape aFace = aFaces.Value(i+1);
629 SMESH_Algo *algo = _gen->GetAlgo(aMesh, aFace);
631 std::vector<int> aResVec(SMDSEntity_Last);
632 for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
633 SMESH_subMesh * sm = aMesh.GetSubMesh(aShape);
634 aResMap.insert(std::make_pair(sm,aResVec));
635 SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
636 smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this));
639 string algoName = algo->GetName();
640 bool isAllQuad = false;
641 if (algoName == "Quadrangle_2D") {
642 MapShapeNbElemsItr anIt = aResMap.find(meshFaces[i]);
643 if( anIt == aResMap.end() ) continue;
644 std::vector<int> aVec = (*anIt).second;
645 int nbtri = Max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]);
650 return EvaluatePentahedralMesh(aMesh, aShape, aResMap);
654 // find number of 1d elems for 1 face
656 TopTools_MapOfShape Edges1;
657 bool IsQuadratic = false;
659 for (TopExp_Explorer exp(aFaces.Value(1), TopAbs_EDGE); exp.More(); exp.Next()) {
660 Edges1.Add(exp.Current());
661 SMESH_subMesh *sm = aMesh.GetSubMesh(exp.Current());
663 MapShapeNbElemsItr anIt = aResMap.find(sm);
664 if( anIt == aResMap.end() ) continue;
665 std::vector<int> aVec = (*anIt).second;
666 nb1d += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]);
668 IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]);
673 // find face opposite to 1 face
675 for(i=2; i<=6; i++) {
676 bool IsOpposite = true;
677 for(TopExp_Explorer exp(aFaces.Value(i), TopAbs_EDGE); exp.More(); exp.Next()) {
678 if( Edges1.Contains(exp.Current()) ) {
688 // find number of 2d elems on side faces
690 for(i=2; i<=6; i++) {
691 if( i == OppNum ) continue;
692 MapShapeNbElemsItr anIt = aResMap.find( meshFaces[i-1] );
693 if( anIt == aResMap.end() ) continue;
694 std::vector<int> aVec = (*anIt).second;
695 nb2d += Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
698 MapShapeNbElemsItr anIt = aResMap.find( meshFaces[0] );
699 std::vector<int> aVec = (*anIt).second;
700 int nb2d_face0 = Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
701 int nb0d_face0 = aVec[SMDSEntity_Node];
703 std::vector<int> aResVec(SMDSEntity_Last);
704 for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
706 aResVec[SMDSEntity_Quad_Hexa] = nb2d_face0 * ( nb2d/nb1d );
707 int nb1d_face0_int = ( nb2d_face0*4 - nb1d ) / 2;
708 aResVec[SMDSEntity_Node] = nb0d_face0 * ( 2*nb2d/nb1d - 1 ) - nb1d_face0_int * nb2d/nb1d;
711 aResVec[SMDSEntity_Node] = nb0d_face0 * ( nb2d/nb1d - 1 );
712 aResVec[SMDSEntity_Hexa] = nb2d_face0 * ( nb2d/nb1d );
714 SMESH_subMesh * sm = aMesh.GetSubMesh(aShape);
715 aResMap.insert(std::make_pair(sm,aResVec));
720 //================================================================================
722 * \brief Computes hexahedral mesh from 2D mesh of block
724 //================================================================================
726 bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh, SMESH_MesherHelper* aHelper)
728 static StdMeshers_HexaFromSkin_3D * algo = 0;
730 SMESH_Gen* gen = aMesh.GetGen();
731 algo = new StdMeshers_HexaFromSkin_3D( gen->GetANewId(), 0, gen );
733 algo->InitComputeError();
734 algo->Compute( aMesh, aHelper );
735 return error( algo->GetComputeError());
738 //=======================================================================
739 //function : ComputePentahedralMesh
741 //=======================================================================
743 SMESH_ComputeErrorPtr ComputePentahedralMesh(SMESH_Mesh & aMesh,
744 const TopoDS_Shape & aShape,
745 SMESH_ProxyMesh* proxyMesh)
747 SMESH_ComputeErrorPtr err = SMESH_ComputeError::New();
750 err->myName = COMPERR_BAD_INPUT_MESH;
751 err->myComment = "Can't build pentahedral mesh on viscous layers";
755 StdMeshers_Penta_3D anAlgo;
757 bOK=anAlgo.Compute(aMesh, aShape);
759 err = anAlgo.GetComputeError();
761 if ( !bOK && anAlgo.ErrorStatus() == 5 )
763 static StdMeshers_Prism_3D * aPrism3D = 0;
765 SMESH_Gen* gen = aMesh.GetGen();
766 aPrism3D = new StdMeshers_Prism_3D( gen->GetANewId(), 0, gen );
768 SMESH_Hypothesis::Hypothesis_Status aStatus;
769 if ( aPrism3D->CheckHypothesis( aMesh, aShape, aStatus ) ) {
770 aPrism3D->InitComputeError();
771 bOK = aPrism3D->Compute( aMesh, aShape );
772 err = aPrism3D->GetComputeError();
779 //=======================================================================
780 //function : EvaluatePentahedralMesh
782 //=======================================================================
784 bool EvaluatePentahedralMesh(SMESH_Mesh & aMesh,
785 const TopoDS_Shape & aShape,
786 MapShapeNbElems& aResMap)
788 StdMeshers_Penta_3D anAlgo;
789 bool bOK = anAlgo.Evaluate(aMesh, aShape, aResMap);
791 //err = anAlgo.GetComputeError();
792 //if ( !bOK && anAlgo.ErrorStatus() == 5 )
794 static StdMeshers_Prism_3D * aPrism3D = 0;
796 SMESH_Gen* gen = aMesh.GetGen();
797 aPrism3D = new StdMeshers_Prism_3D( gen->GetANewId(), 0, gen );
799 SMESH_Hypothesis::Hypothesis_Status aStatus;
800 if ( aPrism3D->CheckHypothesis( aMesh, aShape, aStatus ) ) {
801 return aPrism3D->Evaluate(aMesh, aShape, aResMap);