diff --git a/src/Controls/SMESH_Controls.cxx b/src/Controls/SMESH_Controls.cxx index 2753a3a99..940e66a37 100644 --- a/src/Controls/SMESH_Controls.cxx +++ b/src/Controls/SMESH_Controls.cxx @@ -1131,6 +1131,7 @@ double AspectRatio3D::GetValue( const TSequenceOfXYZ& P ) if (nbNodes==10) nbNodes=4; // quadratic tetrahedron else if(nbNodes==13) nbNodes=5; // quadratic pyramid else if(nbNodes==15) nbNodes=6; // quadratic pentahedron + else if(nbNodes==18) nbNodes=6; // bi-quadratic pentahedron else if(nbNodes==20) nbNodes=8; // quadratic hexahedron else if(nbNodes==27) nbNodes=8; // tri-quadratic hexahedron else return aQuality; diff --git a/src/SMDS/SMDS_VolumeTool.cxx b/src/SMDS/SMDS_VolumeTool.cxx index 4475f7a82..5f19510b4 100644 --- a/src/SMDS/SMDS_VolumeTool.cxx +++ b/src/SMDS/SMDS_VolumeTool.cxx @@ -265,26 +265,26 @@ static int QuadPyram_RE [5][9] = { // REVERSED -> FORWARD (EXTERNAL) { 3, 8, 0, 9, 4, 12,3, 4, 4 }}; static int QuadPyram_nbN [] = { 8, 6, 6, 6, 6 }; -/* -// + N4 -// /|\ -// 9/ | \10 -// / | \ -// / | \ -// N3 +----+----+ N5 -// | |11 | -// | | | -// | +13 | QUADRATIC -// | | | PENTAHEDRON -// 12+ | +14 -// | | | -// | | | -// | + N1 | -// | / \ | -// | 6/ \7 | -// | / \ | -// |/ \| -// N0 +---------+ N2 +/* +// + N4 + +// /|\ /|\ +// 9/ | \10 + | + +// / | \ / | \ +// / | \ / | \ +// N3 +----+----+ N5 +----+----+ +// | |11 | | | | +// | | | | | | Central nodes +// | +13 | QUADRATIC | 16 + | of bi-quadratic +// | | | PENTAHEDRON | + | + | PENTAHEDRON +// 12+ | +14 + | 17 + +// | | | | 18| | +// | | | | | | +// | + N1 | | + | +// | / \ | | / \ | +// | 6/ \7 | | + + | +// | / \ | | / \ | +// |/ \| |/ \| +// N0 +---------+ N2 +---------+ // 8 */ static int QuadPenta_F [5][9] = { // FORWARD @@ -301,6 +301,20 @@ static int QuadPenta_RE [5][9] = { // REVERSED -> EXTERNAL { 0, 12,3, 11,5, 14,2, 8, 0 }}; static int QuadPenta_nbN [] = { 6, 6, 8, 8, 8 }; +static int BiQuadPenta_F[5][9] = { // FORWARD + { 0, 6, 1, 7, 2, 8, 0, 0, 0 }, + { 3, 11,5, 10,4, 9, 3, 3, 3 }, + { 0, 12,3, 9, 4, 13,1, 6, 16}, //! + { 1, 13,4, 10,5, 14,2, 7, 17}, //! + { 0, 8, 2, 14,5, 11,3, 12,18} }; //! +static int BiQuadPenta_RE[5][9] = { // REVERSED -> EXTERNAL + { 0, 8, 2, 7, 1, 6, 0, 0, 0 }, + { 3, 9, 4, 10,5, 11,3, 3, 3 }, + { 0, 6, 1, 13,4, 9, 3, 12,17}, //! + { 1, 7, 2, 14,5, 10,4, 13,16}, //! + { 0, 12,3, 11,5, 14,2, 8, 18} }; //! +static int BiQuadPenta_nbN[] = { 6, 6, 9, 9, 9 }; + /* // 13 // N5+-----+-----+N6 +-----+-----+ @@ -634,6 +648,14 @@ void SMDS_VolumeTool::Inverse () SWAP_NODES( myVolumeNodes, 9, 11 ); SWAP_NODES( myVolumeNodes, 13, 14 ); break; + case 18: + SWAP_NODES(myVolumeNodes, 1, 2); + SWAP_NODES(myVolumeNodes, 4, 5); + SWAP_NODES(myVolumeNodes, 6, 8); + SWAP_NODES(myVolumeNodes, 9, 11); + SWAP_NODES(myVolumeNodes, 13, 14); + SWAP_NODES(myVolumeNodes, 16, 17); + break; case 20: SWAP_NODES( myVolumeNodes, 1, 3 ); SWAP_NODES( myVolumeNodes, 5, 7 ); @@ -677,6 +699,7 @@ SMDS_VolumeTool::VolumeType SMDS_VolumeTool::GetVolumeType() const case 10: return QUAD_TETRA; case 13: return QUAD_PYRAM; case 15: return QUAD_PENTA; + case 18: return QUAD_PENTA; case 20: return QUAD_HEXA; case 27: return QUAD_HEXA; default: break; @@ -862,6 +885,8 @@ double SMDS_VolumeTool::GetSize() const myVolumeNodes[ vtab[i][2] ], myVolumeNodes[ vtab[i][3] ]); } + if (!myVolForward && V < 0) + V *= -1; } return V; } @@ -1705,6 +1730,16 @@ int SMDS_VolumeTool::GetCenterNodeIndex( int faceIndex ) const return faceIndex + 19; } } + else if (myAllFacesNbNodes && myVolumeNodes.size() == 18) // element with 18 nodes + { + switch (faceIndex) { + case 2: return 15; + case 3: return 16; + case 4: return 17; + default: + return -2; + } + } return -1; } @@ -1727,6 +1762,7 @@ int SMDS_VolumeTool::GetOppFaceIndex( int faceIndex ) const switch ( myVolumeNodes.size() ) { case 6: case 15: + case 18: if ( faceIndex == 0 || faceIndex == 1 ) ind = 1 - faceIndex; break; @@ -2469,6 +2505,7 @@ bool SMDS_VolumeTool::setFace( int faceIndex ) const myMaxFaceNbNodes = sizeof(QuadPyram_F[0])/sizeof(QuadPyram_F[0][0]); break; case 15: + case 18: myAllFacesNodeIndices_F = &QuadPenta_F [0][0]; //myAllFacesNodeIndices_FE = &QuadPenta_FE[0][0]; myAllFacesNodeIndices_RE = &QuadPenta_RE[0][0]; @@ -2535,7 +2572,8 @@ SMDS_VolumeTool::VolumeType SMDS_VolumeTool::GetType(int nbNodes) case 8: return HEXA; case 10: return QUAD_TETRA; case 13: return QUAD_PYRAM; - case 15: return QUAD_PENTA; + case 15: + case 18: return QUAD_PENTA; case 20: case 27: return QUAD_HEXA; case 12: return HEX_PRISM; diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 125bbaa2e..6d22c14a6 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -9483,7 +9483,8 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, const bool theT case SMDSEntity_TriQuad_Hexa: NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], nodes[5], nodes[6], nodes[7], id, theForce3d); - for ( size_t i = 20; i < nodes.size(); ++i ) // rm central nodes + for (size_t i = 8; i < nodes.size(); ++i) // rm central nodes from each edge + //for (size_t i = 20; i < nodes.size(); ++i) // rm central nodes from each edge if ( nodes[i]->NbInverseElements() == 0 ) GetMeshDS()->RemoveFreeNode( nodes[i], /*sm=*/0, /*fromGroups=*/true ); break; @@ -9496,7 +9497,9 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, const bool theT case SMDSEntity_BiQuad_Penta: NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], nodes[5], id, theForce3d); - for ( size_t i = 15; i < nodes.size(); ++i ) // rm central nodes + + for (size_t i = 6; i < nodes.size(); ++i) // rm central nodes + //for ( size_t i = 15; i < nodes.size(); ++i ) // rm central nodes if ( nodes[i]->NbInverseElements() == 0 ) GetMeshDS()->RemoveFreeNode( nodes[i], /*sm=*/0, /*fromGroups=*/true ); break; @@ -13037,15 +13040,58 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, if (iQuad) for ( inode = 1; inode < nbFaceNodes; inode += 2) nodes.push_back( nn[inode] ); // add medium nodes - int iCenter = vTool.GetCenterNodeIndex(iface); // for HEX27 - if ( iCenter > 0 ) - nodes.push_back( vTool.GetNodes()[ iCenter ] ); - if (const SMDS_MeshElement * f = aMesh->FindElement( nodes, - SMDSAbs_Face, /*noMedium=*/false )) - presentBndElems.push_back( f ); + // for triangle face for Penta18 (BiQuadratic pentahedron) return -2 + // because we haven't center node on triangle side, but it's need for create biquadratic face + int iCenter = vTool.GetCenterNodeIndex(iface); // for HEX27 + + // for triangle faces for Penta18 (BiQuadratic pentahedron) firstly check, exist face or not + // if not - create node in middle face + if (iCenter == -2) + { + SMDS_ElemIteratorPtr itF = nodes[0]->GetInverseElementIterator(SMDSAbs_Face); + bool isFound = false; + while (itF->more()) + { + const SMDS_MeshElement* e = itF->next(); + int nbNodesToCheck = e->NbNodes(); + if (nbNodesToCheck == (int)nodes.size() + 1) + { + for (size_t i = 1; e && i < nodes.size() - 1; ++i) + { + int nodeIndex = e->GetNodeIndex(nodes[i]); + if (nodeIndex < 0 || nodeIndex >= nbNodesToCheck) + e = 0; + } + if (e) + { + presentBndElems.push_back(e); + isFound = true; + } + } + } + + if (!isFound) + { + SMESH_MesherHelper aHelper(*myMesh); + double bc[3]; + vTool.GetFaceBaryCenter(iface, bc[0], bc[1], bc[2]); + auto aNodeC = aHelper.AddNode(bc[0], bc[1], bc[2]); + nodes.push_back(aNodeC); + missingBndElems.push_back(nodes); + } + } else - missingBndElems.push_back( nodes ); + { + if (iCenter > 0) + nodes.push_back(vTool.GetNodes()[iCenter]); + + if (const SMDS_MeshElement* f = aMesh->FindElement(nodes, + SMDSAbs_Face, /*noMedium=*/false)) + presentBndElems.push_back(f); + else + missingBndElems.push_back(nodes); + } if ( targetMesh != myMesh ) {