2024-05-26 13:04:12 +01:00
// Copyright (C) 2016-2024 CEA, EDF
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
// File : HexahedronTest.cxx
// Module : SMESH
// Purpose: Implement unit tests for StdMeshers_Cartesian_3D_Hexahedron class to reproduce bugs that manifest in integration tests.
2024-07-26 13:46:11 +01:00
// The main difference between this unit test and integration tests is the fine grained control we have over the class methods and the hability to diagnose/solve bugs before the code goes into production enviroment.
2024-05-26 13:04:12 +01:00
// This test class can be used as reference for the development of future tests in other stdMesh algorithms
# include "StdMeshers_Cartesian_3D_Hexahedron.hxx"
# include "StdMeshers_CartesianParameters3D.hxx"
// CPP TEST
# include <cppunit/TestAssert.h>
2024-07-26 13:46:11 +01:00
// OCC
2024-07-11 16:46:22 +01:00
# include <BRep_Builder.hxx>
# include <BRepTools.hxx>
# include <BRepPrimAPI_MakeBox.hxx>
# include <BRepPrimAPI_MakeCylinder.hxx>
# include <BRepPrimAPI_MakeSphere.hxx>
# include <BRepPrimAPI_MakeCone.hxx>
2024-05-26 13:04:12 +01:00
2024-07-11 16:46:22 +01:00
# include <iostream>
2024-05-26 13:04:12 +01:00
# include <memory>
2024-09-04 10:28:43 +01:00
# include <numeric>
2024-05-26 13:04:12 +01:00
2024-07-19 12:53:33 +01:00
using namespace StdMeshers : : Cartesian3D ;
2024-05-26 13:04:12 +01:00
// Helper functions!
// Build Grid
// Require building mesh
2024-07-19 12:53:33 +01:00
// Require building shape.
2024-05-26 13:04:12 +01:00
/*!
* \ brief Mock mesh
*/
struct SMESH_Mesh_Test : public SMESH_Mesh
{
SMESH_Mesh_Test ( ) {
_isShapeToMesh = ( _id = 0 ) ;
_meshDS = new SMESHDS_Mesh ( _id , true ) ;
}
} ;
/*!
* \ brief Mock Hypothesis
*/
struct CartesianHypo : public StdMeshers_CartesianParameters3D
{
2024-07-26 13:46:11 +01:00
CartesianHypo ( ) : StdMeshers_CartesianParameters3D ( 0 /*zero hypoId*/ , nullptr /*NULL generator*/ )
2024-05-26 13:04:12 +01:00
{
}
2024-07-26 13:46:11 +01:00
} ;
2024-05-26 13:04:12 +01:00
/*!
* \ brief Shape loader
*/
void loadBrepShape ( std : : string shapeName , TopoDS_Shape & shape )
{
BRep_Builder b ;
2024-07-26 13:46:11 +01:00
BRepTools : : Read ( shape , shapeName . c_str ( ) , b ) ;
2024-05-26 13:04:12 +01:00
}
2024-07-12 13:29:04 +01:00
/*!
* \ brief Initialize the grid and intesersectors of grid with the geometry
*/
2024-07-19 12:53:33 +01:00
void GridInitAndIntersectWithShape ( Grid & grid ,
2024-07-11 16:46:22 +01:00
double gridSpacing ,
double theSizeThreshold ,
2024-07-26 13:46:11 +01:00
const TopoDS_Shape theShape ,
2024-07-19 12:53:33 +01:00
TEdge2faceIDsMap & edge2faceIDsMap ,
const int theNumOfThreads )
2024-05-26 13:04:12 +01:00
{
// Canonical axes(i,j,k)
2024-07-19 12:53:33 +01:00
double axisDirs [ 9 ] = { 1. , 0. , 0. , 0. , 1. , 0. , 0. , 0. , 1. } ;
2024-05-26 13:04:12 +01:00
std : : vector < std : : string > grdSpace = { std : : to_string ( gridSpacing ) } ;
std : : vector < double > intPnts ;
2024-07-19 12:53:33 +01:00
2024-07-26 13:46:11 +01:00
std : : unique_ptr < CartesianHypo > aHypo ( new CartesianHypo ( ) ) ;
2024-07-19 12:53:33 +01:00
aHypo - > SetAxisDirs ( axisDirs ) ;
aHypo - > SetGridSpacing ( grdSpace , intPnts , 0 ) ; // Spacing in dir 0
aHypo - > SetGridSpacing ( grdSpace , intPnts , 1 ) ; // Spacing in dir 1
aHypo - > SetGridSpacing ( grdSpace , intPnts , 2 ) ; // Spacing in dir 2
aHypo - > SetSizeThreshold ( theSizeThreshold ) ; // set threshold
grid . GridInitAndInterserctWithShape ( theShape , edge2faceIDsMap , aHypo . get ( ) , theNumOfThreads , false ) ;
2024-05-26 13:04:12 +01:00
}
2024-07-12 13:29:04 +01:00
/*!
* \ brief Reproduce conditions of TBPERF_GRIDS_PERF_SMESH_M1 test to detect and solve segfault in unit test .
*/
2024-05-26 13:04:12 +01:00
bool testNRTM1 ( )
{
2024-07-19 12:53:33 +01:00
TopoDS_Shape aShape ;
loadBrepShape ( " data/HexahedronTest/NRTM1.brep " , aShape ) ;
2024-07-26 13:46:11 +01:00
CPPUNIT_ASSERT_MESSAGE ( " Could not load the brep shape! " , ! aShape . IsNull ( ) ) ;
2024-07-19 12:53:33 +01:00
2024-07-12 13:29:04 +01:00
const auto numOfCores = std : : thread : : hardware_concurrency ( ) = = 0 ? 1 : std : : thread : : hardware_concurrency ( ) ;
std : : vector < int > numberOfThreads ( numOfCores ) ;
std : : iota ( std : : begin ( numberOfThreads ) , std : : end ( numberOfThreads ) , 1 ) ;
for ( auto nThreads : numberOfThreads )
2024-05-26 13:04:12 +01:00
{
2024-07-12 13:29:04 +01:00
for ( size_t i = 0 ; i < 10 /*trials*/ ; i + + )
2024-05-26 13:04:12 +01:00
{
2024-07-19 12:53:33 +01:00
std : : unique_ptr < SMESH_Mesh > aMesh ( new SMESH_Mesh_Test ( ) ) ;
aMesh - > ShapeToMesh ( aShape ) ;
SMESH_MesherHelper helper ( * aMesh ) ;
2024-05-26 13:04:12 +01:00
Grid grid ;
grid . _helper = & helper ;
2024-07-19 12:53:33 +01:00
grid . _toAddEdges = false ;
grid . _toCreateFaces = false ;
grid . _toConsiderInternalFaces = false ;
grid . _toUseThresholdForInternalFaces = false ;
grid . _toUseQuanta = false ;
2024-05-26 13:04:12 +01:00
grid . _sizeThreshold = 4.0 ;
2024-07-26 13:46:11 +01:00
2024-07-19 12:53:33 +01:00
TEdge2faceIDsMap edge2faceIDsMap ;
GridInitAndIntersectWithShape ( grid , 1.0 , 4.0 , aShape , edge2faceIDsMap , nThreads ) ;
2024-07-26 13:46:11 +01:00
SMESH_subMesh * aSubMesh = aMesh - > GetSubMesh ( aShape ) ;
aSubMesh - > DependsOn ( ) ; // init sub-meshes
2024-05-26 13:04:12 +01:00
Hexahedron hex ( & grid ) ;
2024-07-12 13:29:04 +01:00
int nbAdded = hex . MakeElements ( helper , edge2faceIDsMap , nThreads ) ;
2024-05-26 13:04:12 +01:00
CPPUNIT_ASSERT_MESSAGE ( " Number of computed elements does not match " , nbAdded = = 1024 ) ;
}
2024-07-26 13:46:11 +01:00
}
2024-05-26 13:04:12 +01:00
return true ;
}
2024-07-12 13:29:04 +01:00
/*!
* \ brief Reproduce conditions of TBPERF_GRIDS_PERF_SMESH_J4 test to detect and solve segfault in unit test .
*/
bool testNRTJ4 ( )
2024-07-11 16:46:22 +01:00
{
2024-07-19 12:53:33 +01:00
TopoDS_Shape aShape ;
loadBrepShape ( " data/HexahedronTest/NRTMJ4.brep " , aShape ) ;
2024-07-26 13:46:11 +01:00
CPPUNIT_ASSERT_MESSAGE ( " Could not load the brep shape! " , ! aShape . IsNull ( ) ) ;
2024-07-19 12:53:33 +01:00
2024-07-12 13:29:04 +01:00
const auto numOfCores = std : : thread : : hardware_concurrency ( ) = = 0 ? 1 : std : : thread : : hardware_concurrency ( ) / 2 ;
std : : vector < int > numberOfThreads ( numOfCores ) ;
std : : iota ( std : : begin ( numberOfThreads ) , std : : end ( numberOfThreads ) , 1 ) ;
2024-07-11 16:46:22 +01:00
2024-07-12 13:29:04 +01:00
// Test with face creation
for ( auto nThreads : numberOfThreads )
{
for ( size_t i = 0 ; i < 10 /*trials*/ ; i + + )
{
2024-07-19 12:53:33 +01:00
std : : unique_ptr < SMESH_Mesh > aMesh ( new SMESH_Mesh_Test ( ) ) ;
aMesh - > ShapeToMesh ( aShape ) ;
SMESH_MesherHelper helper ( * aMesh ) ;
2024-07-12 13:29:04 +01:00
Grid grid ;
grid . _helper = & helper ;
2024-07-19 12:53:33 +01:00
grid . _toAddEdges = false ;
grid . _toConsiderInternalFaces = false ;
grid . _toUseThresholdForInternalFaces = false ;
grid . _toUseQuanta = false ;
2024-07-12 13:29:04 +01:00
double testThreshold = 1.000001 ;
grid . _toCreateFaces = true ;
grid . _sizeThreshold = testThreshold ;
2024-07-26 13:46:11 +01:00
2024-07-19 12:53:33 +01:00
TEdge2faceIDsMap edge2faceIDsMap ;
2024-07-26 13:46:11 +01:00
GridInitAndIntersectWithShape ( grid , 2.0 , testThreshold ,
aShape , edge2faceIDsMap , nThreads ) ;
SMESH_subMesh * aSubMesh = aMesh - > GetSubMesh ( aShape ) ;
aSubMesh - > DependsOn ( ) ; // init sub-meshes
2024-07-12 13:29:04 +01:00
Hexahedron hex ( & grid ) ;
int nbAdded = hex . MakeElements ( helper , edge2faceIDsMap , nThreads ) ;
CPPUNIT_ASSERT_MESSAGE ( " Number of computed elements does not match " , nbAdded = = 35150 ) ;
}
2024-07-26 13:46:11 +01:00
}
2024-07-11 16:46:22 +01:00
return true ;
}
2024-05-26 13:04:12 +01:00
// Entry point for test
int main ( )
{
2024-07-19 12:53:33 +01:00
bool isOK = testNRTM1 ( ) ;
if ( ! testNRTJ4 ( ) )
isOK = false ;
2024-07-11 16:46:22 +01:00
return isOK ? 0 : 1 ;
}