From: cconopoima Date: Wed, 8 Nov 2023 15:36:01 +0000 (+0000) Subject: [bos #38521][EDF] Split Polyhedron with more than one volume. X-Git-Tag: V9_12_0b1^0 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=refs%2Ftlpr%2F24%2Fhead;p=modules%2Fsmesh.git [bos #38521][EDF] Split Polyhedron with more than one volume. Improve comment and add bother volumes to mesh body. . Change typo of counters to avoid compilation warnings. --- diff --git a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx index 1223736d0..48796921b 100644 --- a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx +++ b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx @@ -938,6 +938,7 @@ namespace TGeomID _solidID; double _size; const SMDS_MeshElement* _volume; // new volume + std::vector _brotherVolume; // produced due to poly split vector< SMESH_Block::TShapeID > _names; // name of side a polygon originates from @@ -1069,6 +1070,10 @@ namespace bool isInHole() const; bool hasStrangeEdge() const; bool checkPolyhedronSize( bool isCutByInternalFace, double & volSize ) const; + int checkPolyhedronValidity( _volumeDef* volDef, std::vector>& splitQuantities, + std::vector>& splitNodes ); + const SMDS_MeshElement* addPolyhedronToMesh( _volumeDef* volDef, SMESH_MesherHelper& helper, const std::vector& nodes, + const std::vector& quantities ); bool addHexa (); bool addTetra(); bool addPenta(); @@ -3556,7 +3561,6 @@ namespace _volumeDefs._nodes.clear(); _volumeDefs._quantities.clear(); _volumeDefs._names.clear(); - // create a classic cell if possible int nbPolygons = 0; @@ -4851,26 +4855,27 @@ namespace } // loop to get nodes const SMDS_MeshElement* v = 0; + if ( !volDef->_quantities.empty() ) - { - v = helper.AddPolyhedralVolume( nodes, volDef->_quantities ); - volDef->_size = SMDS_VolumeTool( v ).GetSize(); - if ( volDef->_size < 0 ) // invalid polyhedron + { + // split polyhedrons of with disjoint volumes + std::vector> splitQuantities; + std::vector > splitNodes; + if ( checkPolyhedronValidity( volDef, splitQuantities, splitNodes ) == 1 ) { - if ( ! SMESH_MeshEditor( helper.GetMesh() ).Reorient( v ) || // try to fix - SMDS_VolumeTool( v ).GetSize() < 0 ) + v = addPolyhedronToMesh( volDef, helper, nodes, volDef->_quantities ); + } + else + { + int counter = -1; + for (size_t id = 0; id < splitQuantities.size(); id++) { - helper.GetMeshDS()->RemoveFreeElement( v, /*sm=*/nullptr, /*fromGroups=*/false ); - v = nullptr; - //_hasTooSmall = true; - - if (SALOME::VerbosityActivated()) - { - std::cout << "Remove INVALID polyhedron, _cellID = " << _cellID - << " ijk = ( " << _i << " " << _j << " " << _k << " ) " - << " solid " << volDef->_solidID << std::endl; - } + v = addPolyhedronToMesh( volDef, helper, splitNodes[ id ], splitQuantities[ id ] ); + if ( id < splitQuantities.size()-1 ) + volDef->_brotherVolume.push_back( v ); + counter++; } + nbAdded += counter; } } else @@ -4928,6 +4933,10 @@ namespace if ( volDef->_volume ) { helper.GetMeshDS()->SetMeshElementOnShape( volDef->_volume, volDef->_solidID ); + for (auto broVol : volDef->_brotherVolume ) + { + helper.GetMeshDS()->SetMeshElementOnShape( broVol, volDef->_solidID ); + } } } @@ -5077,6 +5086,159 @@ namespace return volume > initVolume / _grid->_sizeThreshold; } + + //================================================================================ + /*! + * \brief Check that all faces in polyhedron are connected so a unique volume is defined. + * We test that it is possible to go from any node to all nodes in the polyhedron. + * The set of nodes that can be visit within then defines a unique element. + * In case more than one polyhedron is detected. The function return the set of quantities and nodes defining separates elements. + * Reference to issue #bos[38521][EDF] Generate polyhedron with separate volume. + */ + int Hexahedron::checkPolyhedronValidity( _volumeDef* volDef, std::vector>& splitQuantities, + std::vector>& splitNodes ) + { + int mySet = 1; + std::map numberOfSets; // define set id with the number of faces associated! + if ( !volDef->_quantities.empty() ) + { + auto connectivity = volDef->_quantities; + int accum = 0; + std::vector allFaces( connectivity.size(), false ); + std::set elementSet; + allFaces[ 0 ] = true; // the first node below to the first face + size_t connectedFaces = 1; + // Start filling the set with the nodes of the first face + splitQuantities.push_back( { connectivity[ 0 ] } ); + splitNodes.push_back( { volDef->_nodes[ 0 ].Node() } ); + elementSet.insert( volDef->_nodes[ 0 ].Node()->GetID() ); + for (int n = 1; n < connectivity[ 0 ]; n++) + { + elementSet.insert( volDef->_nodes[ n ].Node()->GetID() ); + splitNodes.back().push_back( volDef->_nodes[ n ].Node() ); + } + + numberOfSets.insert( std::pair(mySet,1) ); + while ( connectedFaces != allFaces.size() ) + { + for (size_t innerId = 1; innerId < connectivity.size(); innerId++) + { + if ( innerId == 1 ) + accum = connectivity[ 0 ]; + + if ( !allFaces[ innerId ] ) + { + int faceCounter = 0; + for (int n = 0; n < connectivity[ innerId ]; n++) + { + int nodeId = volDef->_nodes[ accum + n ].Node()->GetID(); + if ( elementSet.count( nodeId ) != 0 ) + faceCounter++; + } + if ( faceCounter >= 2 ) // found coincidences nodes + { + for (int n = 0; n < connectivity[ innerId ]; n++) + { + int nodeId = volDef->_nodes[ accum + n ].Node()->GetID(); + // insert new nodes so other faces can be identified as belowing to the element + splitNodes.back().push_back( volDef->_nodes[ accum + n ].Node() ); + elementSet.insert( nodeId ); + } + allFaces[ innerId ] = true; + splitQuantities.back().push_back( connectivity[ innerId ] ); + numberOfSets[ mySet ]++; + connectedFaces++; + innerId = 0; // to restart searching! + } + } + accum += connectivity[ innerId ]; + } + + if ( connectedFaces != allFaces.size() ) + { + // empty the set, and fill it with nodes of a unvisited face! + elementSet.clear(); + accum = connectivity[ 0 ]; + for (size_t faceId = 1; faceId < connectivity.size(); faceId++) + { + if ( !allFaces[ faceId ] ) + { + splitNodes.push_back( { volDef->_nodes[ accum ].Node() } ); + elementSet.insert( volDef->_nodes[ accum ].Node()->GetID() ); + for (int n = 1; n < connectivity[ faceId ]; n++) + { + elementSet.insert( volDef->_nodes[ accum + n ].Node()->GetID() ); + splitNodes.back().push_back( volDef->_nodes[ accum + n ].Node() ); + } + + splitQuantities.push_back( { connectivity[ faceId ] } ); + allFaces[ faceId ] = true; + connectedFaces++; + break; + } + accum += connectivity[ faceId ]; + } + mySet++; + numberOfSets.insert( std::pair(mySet,1) ); + } + } + + if ( numberOfSets.size() > 1 ) + { + bool allMoreThan2Faces = true; + for( auto k : numberOfSets ) + { + if ( k.second <= 2 ) + allMoreThan2Faces &= false; + } + + if ( allMoreThan2Faces ) + { + // The separate objects are suspect to be closed + return numberOfSets.size(); + } + else + { + // Have to index the last face nodes to the final set + // contrary case return as it were a valid polyhedron for backward compatibility + return 1; + } + } + } + return numberOfSets.size(); + } + + + //================================================================================ + /*! + * \brief add original or separated polyhedrons to the mesh + */ + const SMDS_MeshElement* Hexahedron::addPolyhedronToMesh( _volumeDef* volDef, SMESH_MesherHelper& helper, const std::vector& nodes, + const std::vector& quantities ) + { + const SMDS_MeshElement* v = helper.AddPolyhedralVolume( nodes, quantities ); + + volDef->_size = SMDS_VolumeTool( v ).GetSize(); + if ( volDef->_size < 0 ) // invalid polyhedron + { + if ( ! SMESH_MeshEditor( helper.GetMesh() ).Reorient( v ) || // try to fix + SMDS_VolumeTool( v ).GetSize() < 0 ) + { + helper.GetMeshDS()->RemoveFreeElement( v, /*sm=*/nullptr, /*fromGroups=*/false ); + v = nullptr; + //_hasTooSmall = true; + + if (SALOME::VerbosityActivated()) + { + std::cout << "Remove INVALID polyhedron, _cellID = " << _cellID + << " ijk = ( " << _i << " " << _j << " " << _k << " ) " + << " solid " << volDef->_solidID << std::endl; + } + } + } + return v; + } + //================================================================================ /*! * \brief Tries to create a hexahedron @@ -5817,6 +5979,14 @@ namespace for ( size_t iN = 0; iN < volDef->_nodes.size(); ++iN ) volDef->_nodes[iN].Node()->setIsMarked( false ); } + if ( volDef->_brotherVolume.size() > 0 ) + { + for (auto _bro : volDef->_brotherVolume ) + { + _bro->setIsMarked( true ); + boundaryElems.push_back( _bro ); + } + } } }