Loading src/TNL/Meshes/Geometry/getDecomposedMesh.h +8 −6 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ struct TriangleConfig: public ParentConfig }; template< EntityDecomposerVersion DecomposerVersion, EntityDecomposerVersion SubdecomposerVersion = EntityDecomposerVersion::ConnectEdgesToPoint, typename MeshConfig, std::enable_if_t< std::is_same< typename MeshConfig::CellTopology, Topologies::Polygon >::value, bool > = true > auto // returns MeshBuilder Loading Loading @@ -53,7 +54,7 @@ decomposeMesh( const Mesh< MeshConfig, Devices::Host >& inMesh ) const auto cell = inMesh.template getEntity< CellDimension >( i ); indeces[ i ] = EntityDecomposer::getExtraPointsAndEntitiesCount( cell ); }; ParallelFor< Devices::Host >::exec( 0, inCellsCount, setCounts ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, setCounts ); indeces[ inCellsCount ] = { 0, 0 }; // extend exclusive prefix sum by one element to also get result of reduce at the same time auto reduction = [] ( const IndexPair& a, const IndexPair& b ) -> IndexPair { return { a.first + b.first, a.second + b.second }; Loading @@ -68,7 +69,7 @@ decomposeMesh( const Mesh< MeshConfig, Devices::Host >& inMesh ) auto copyPoint = [&] ( GlobalIndexType i ) mutable { meshBuilder.setPoint( i, inMesh.getPoint( i ) ); }; ParallelFor< Devices::Host >::exec( 0, inPointsCount, copyPoint ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inPointsCount, copyPoint ); // Decompose each cell auto decomposeCell = [&] ( GlobalIndexType i ) mutable { Loading @@ -94,12 +95,13 @@ decomposeMesh( const Mesh< MeshConfig, Devices::Host >& inMesh ) EntityDecomposer::decompose( cell, addPoint, addCell ); }; ParallelFor< Devices::Host >::exec( 0, inCellsCount, decomposeCell ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, decomposeCell ); return meshBuilder; } template< EntityDecomposerVersion DecomposerVersion, EntityDecomposerVersion SubdecomposerVersion = EntityDecomposerVersion::ConnectEdgesToPoint, typename MeshConfig, std::enable_if_t< std::is_same< typename MeshConfig::CellTopology, Topologies::Polygon >::value, bool > = true > auto // returns Mesh Loading Loading @@ -154,7 +156,7 @@ decomposeMesh( const Mesh< MeshConfig, Devices::Host >& inMesh ) const auto cell = inMesh.template getEntity< CellDimension >( i ); indeces[ i ] = EntityDecomposer::getExtraPointsAndEntitiesCount( cell ); }; ParallelFor< Devices::Host >::exec( 0, inCellsCount, setCounts ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, setCounts ); indeces[ inCellsCount ] = { 0, 0 }; // extend exclusive prefix sum by one element to also get result of reduce at the same time auto reduction = [] ( const IndexPair& a, const IndexPair& b ) -> IndexPair { return { a.first + b.first, a.second + b.second }; Loading @@ -169,7 +171,7 @@ decomposeMesh( const Mesh< MeshConfig, Devices::Host >& inMesh ) auto copyPoint = [&] ( GlobalIndexType i ) mutable { meshBuilder.setPoint( i, inMesh.getPoint( i ) ); }; ParallelFor< Devices::Host >::exec( 0, inPointsCount, copyPoint ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inPointsCount, copyPoint ); // Decompose each cell auto decomposeCell = [&] ( GlobalIndexType i ) mutable { Loading @@ -196,7 +198,7 @@ decomposeMesh( const Mesh< MeshConfig, Devices::Host >& inMesh ) EntityDecomposer::decompose( cell, addPoint, addCell ); }; ParallelFor< Devices::Host >::exec( 0, inCellsCount, decomposeCell ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, decomposeCell ); return meshBuilder; } Loading src/TNL/Meshes/Geometry/getPlanarMesh.h +10 −10 Original line number Diff line number Diff line Loading @@ -58,7 +58,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) indeces[ i ] = EntityDecomposer::getExtraPointsAndEntitiesCount( cell ); } }; ParallelFor< Devices::Host >::exec( 0, inCellsCount, setCounts ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, setCounts ); indeces[ inCellsCount ] = { 0, 0 }; // extend exclusive prefix sum by one element to also get result of reduce at the same time auto reduction = [] ( const IndexPair& a, const IndexPair& b ) -> IndexPair { return { a.first + b.first, a.second + b.second }; Loading @@ -73,7 +73,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) auto copyPoint = [&] ( GlobalIndexType i ) mutable { meshBuilder.setPoint( i, inMesh.getPoint( i ) ); }; ParallelFor< Devices::Host >::exec( 0, inPointsCount, copyPoint ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inPointsCount, copyPoint ); // set corner counts for cells NeighborCountsArray cellCornersCounts( outCellsCount ); Loading @@ -93,7 +93,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) } } }; ParallelFor< Devices::Host >::exec( 0, inCellsCount, setCornersCount ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, setCornersCount ); meshBuilder.setCellCornersCounts( std::move( cellCornersCounts ) ); // Decompose non-planar cells and copy the rest Loading Loading @@ -131,7 +131,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) EntityDecomposer::decompose( cell, addPoint, addCell ); } }; ParallelFor< Devices::Host >::exec( 0, inCellsCount, decomposeCell ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, decomposeCell ); return meshBuilder; } Loading Loading @@ -179,7 +179,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) indeces[ i ] = EntityDecomposer::getExtraPointsAndEntitiesCount( face ); } }; ParallelFor< Devices::Host >::exec( 0, inFacesCount, setCounts ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inFacesCount, setCounts ); indeces[ inFacesCount ] = { 0, 0 }; // extend exclusive prefix sum by one element to also get result of reduce at the same time auto reduction = [] ( const IndexPair& a, const IndexPair& b ) -> IndexPair { return { a.first + b.first, a.second + b.second }; Loading @@ -195,7 +195,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) auto copyPoint = [&] ( GlobalIndexType i ) mutable { meshBuilder.setPoint( i, inMesh.getPoint( i ) ); }; ParallelFor< Devices::Host >::exec( 0, inPointsCount, copyPoint ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inPointsCount, copyPoint ); // set corner counts for cells NeighborCountsArray cellCornersCounts( outCellsCount ); Loading @@ -212,7 +212,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) cellCornersCounts[ i ] = cornersCount; }; ParallelFor< Devices::Host >::exec( 0, inCellsCount, setCellCornersCount ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, setCellCornersCount ); meshBuilder.setCellCornersCounts( std::move( cellCornersCounts ) ); // Set corner ids for cells Loading @@ -228,7 +228,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) } } }; ParallelFor< Devices::Host >::exec( 0, inCellsCount, setCellCornersIds ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, setCellCornersIds ); // set corner counts for faces NeighborCountsArray faceCornersCounts( outFacesCount ); Loading @@ -247,7 +247,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) } } }; ParallelFor< Devices::Host >::exec( 0, inFacesCount, setFaceCornersCount ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inFacesCount, setFaceCornersCount ); meshBuilder.setFaceCornersCounts( std::move( faceCornersCounts ) ); // Decompose non-planar faces and copy the rest Loading Loading @@ -285,7 +285,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) EntityDecomposer::decompose( face, addPoint, addFace ); } }; ParallelFor< Devices::Host >::exec( 0, inFacesCount, decomposeFace ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inFacesCount, decomposeFace ); return meshBuilder; } Loading src/Tools/CMakeLists.txt +6 −2 Original line number Diff line number Diff line Loading @@ -4,6 +4,8 @@ ADD_EXECUTABLE(tnl-decompose-grid tnl-decompose-grid.cpp ) ADD_EXECUTABLE(tnl-grid-setup tnl-grid-setup.cpp ) ADD_EXECUTABLE(tnl-grid-to-mesh tnl-grid-to-mesh.cpp ) ADD_EXECUTABLE(tnl-mesh-converter tnl-mesh-converter.cpp ) ADD_EXECUTABLE(tnl-triangulate-mesh tnl-triangulate-mesh.cpp ) ADD_EXECUTABLE(tnl-planar-correct-mesh tnl-planar-correct-mesh.cpp ) ADD_EXECUTABLE(tnl-game-of-life tnl-game-of-life.cpp ) if( BUILD_CUDA ) CUDA_ADD_EXECUTABLE(tnl-test-distributed-mesh tnl-test-distributed-mesh.cu ) Loading @@ -28,7 +30,7 @@ endif() find_package( ZLIB ) if( ZLIB_FOUND ) foreach( target IN ITEMS tnl-init tnl-diff tnl-decompose-grid tnl-grid-to-mesh tnl-mesh-converter tnl-game-of-life tnl-test-distributed-mesh ) foreach( target IN ITEMS tnl-init tnl-diff tnl-decompose-grid tnl-grid-to-mesh tnl-mesh-converter tnl-triangulate-mesh tnl-planar-correct-mesh tnl-game-of-life tnl-test-distributed-mesh ) target_compile_definitions(${target} PUBLIC "-DHAVE_ZLIB") target_include_directories(${target} PUBLIC ${ZLIB_INCLUDE_DIRS}) target_link_libraries(${target} ${ZLIB_LIBRARIES}) Loading @@ -37,7 +39,7 @@ endif() find_package( tinyxml2 QUIET ) if( tinyxml2_FOUND ) foreach( target IN ITEMS tnl-init tnl-diff tnl-decompose-grid tnl-grid-to-mesh tnl-mesh-converter tnl-game-of-life tnl-test-distributed-mesh ) foreach( target IN ITEMS tnl-init tnl-diff tnl-decompose-grid tnl-grid-to-mesh tnl-mesh-converter tnl-triangulate-mesh tnl-planar-correct-mesh tnl-game-of-life tnl-test-distributed-mesh ) target_compile_definitions(${target} PUBLIC "-DHAVE_TINYXML2") target_link_libraries(${target} tinyxml2::tinyxml2) endforeach() Loading Loading @@ -72,6 +74,8 @@ INSTALL( TARGETS tnl-init tnl-grid-setup tnl-grid-to-mesh tnl-mesh-converter tnl-triangulate-mesh tnl-planar-correct-mesh tnl-game-of-life tnl-test-distributed-mesh tnl-dicom-reader Loading src/Tools/tnl-planar-correct-mesh.cpp 0 → 100644 +174 −0 Original line number Diff line number Diff line #include <TNL/Config/parseCommandLine.h> #include <TNL/Meshes/TypeResolver/resolveMeshType.h> #include <TNL/Meshes/Writers/VTKWriter.h> #include <TNL/Meshes/Writers/FPMAWriter.h> #include <TNL/Meshes/Geometry/getPlanarMesh.h> using namespace TNL; struct MeshPlanarCorrectConfigTag {}; namespace TNL { namespace Meshes { namespace BuildConfigTags { /**** * Turn off all grids. */ template<> struct GridRealTag< MeshPlanarCorrectConfigTag, float > { enum { enabled = false }; }; template<> struct GridRealTag< MeshPlanarCorrectConfigTag, double > { enum { enabled = false }; }; template<> struct GridRealTag< MeshPlanarCorrectConfigTag, long double > { enum { enabled = false }; }; /**** * Unstructured meshes. */ template<> struct MeshCellTopologyTag< MeshPlanarCorrectConfigTag, Topologies::Polygon > { enum { enabled = true }; }; template<> struct MeshCellTopologyTag< MeshPlanarCorrectConfigTag, Topologies::Polyhedron > { enum { enabled = true }; }; // Meshes are enabled only for the world dimension equal to 3 template< typename CellTopology, int WorldDimension > struct MeshWorldDimensionTag< MeshPlanarCorrectConfigTag, CellTopology, WorldDimension > { enum { enabled = ( WorldDimension == 3 ) }; }; // Meshes are enabled only for types explicitly listed below. template<> struct MeshRealTag< MeshPlanarCorrectConfigTag, float > { enum { enabled = true }; }; template<> struct MeshRealTag< MeshPlanarCorrectConfigTag, double > { enum { enabled = true }; }; template<> struct MeshGlobalIndexTag< MeshPlanarCorrectConfigTag, long int > { enum { enabled = true }; }; template<> struct MeshGlobalIndexTag< MeshPlanarCorrectConfigTag, int > { enum { enabled = true }; }; template<> struct MeshLocalIndexTag< MeshPlanarCorrectConfigTag, short int > { enum { enabled = true }; }; // Config tag specifying the MeshConfig template to use. template<> struct MeshConfigTemplateTag< MeshPlanarCorrectConfigTag > { template< typename Cell, int WorldDimension = Cell::dimension, typename Real = float, typename GlobalIndex = int, typename LocalIndex = short int > struct MeshConfig { using CellTopology = Cell; using RealType = Real; using GlobalIndexType = GlobalIndex; using LocalIndexType = LocalIndex; static constexpr int worldDimension = WorldDimension; static constexpr int meshDimension = Cell::dimension; template< typename EntityTopology > static constexpr bool subentityStorage( EntityTopology, int SubentityDimension ) { return (SubentityDimension == 0 && EntityTopology::dimension == meshDimension) || (SubentityDimension == meshDimension - 1 && EntityTopology::dimension == meshDimension ) || (SubentityDimension == 0 && EntityTopology::dimension == meshDimension - 1 ); } template< typename EntityTopology > static constexpr bool superentityStorage( EntityTopology, int SuperentityDimension ) { return false; } template< typename EntityTopology > static constexpr bool entityTagsStorage( EntityTopology ) { return false; } static constexpr bool dualGraphStorage() { return false; } }; }; } // namespace BuildConfigTags } // namespace Meshes } // namespace TNL using namespace TNL::Meshes; template< typename Mesh > auto getPlanarMeshHelper( const Mesh& mesh, const String& decompositionType ) { using namespace TNL::Meshes; if( decompositionType[0] == 'c' ) { return getPlanarMesh< EntityDecomposerVersion::ConnectEdgesToCentroid >( mesh ); } else { // decompositionType[0] == 'p' return getPlanarMesh< EntityDecomposerVersion::ConnectEdgesToPoint >( mesh ); } } template< typename Topology > struct PlanarMeshWriter; template<> struct PlanarMeshWriter< Topologies::Polygon > { template< typename Mesh > static void exec( const Mesh& mesh, const String& outputFileName ) { using Writer = Meshes::Writers::VTKWriter< Mesh >; std::ofstream file( outputFileName ); Writer writer( file ); writer.template writeEntities< Mesh::getMeshDimension() >( mesh ); } }; template<> struct PlanarMeshWriter< Topologies::Polyhedron > { template< typename Mesh > static void exec( const Mesh& mesh, const String& outputFileName ) { using Writer = Meshes::Writers::FPMAWriter< Mesh >; std::ofstream file( outputFileName ); Writer writer( file ); writer.writeEntities( mesh ); } }; template< typename Mesh > bool triangulateMesh( const Mesh& mesh, const String& outputFileName, const String& decompositionType ) { const auto planarMesh = getPlanarMeshHelper( mesh, decompositionType ); using PlanarMesh = decltype( planarMesh ); using CellTopology = typename PlanarMesh::Cell::EntityTopology; PlanarMeshWriter< CellTopology >::exec( planarMesh, outputFileName ); return true; } void configSetup( Config::ConfigDescription& config ) { config.addDelimiter( "General settings:" ); config.addRequiredEntry< String >( "input-file", "Input file with the mesh." ); config.addRequiredEntry< String >( "output-file", "Output mesh file path." ); config.addRequiredEntry< String >( "decomposition-type", "Type of decomposition to use for non-planar polygons." ); config.addEntryEnum( "c" ); config.addEntryEnum( "p" ); } int main( int argc, char* argv[] ) { Config::ParameterContainer parameters; Config::ConfigDescription conf_desc; configSetup( conf_desc ); if( ! parseCommandLine( argc, argv, conf_desc, parameters ) ) return EXIT_FAILURE; const String inputFileName = parameters.getParameter< String >( "input-file" ); const String inputFileFormat = "auto"; const String outputFileName = parameters.getParameter< String >( "output-file" ); const String decompositionType = parameters.getParameter< String >( "decomposition-type" ); auto wrapper = [&] ( auto& reader, auto&& mesh ) -> bool { return triangulateMesh( mesh, outputFileName, decompositionType ); }; return ! Meshes::resolveAndLoadMesh< MeshPlanarCorrectConfigTag, Devices::Host >( wrapper, inputFileName, inputFileFormat ); } src/Tools/tnl-triangulate-mesh.cpp 0 → 100644 +174 −0 Original line number Diff line number Diff line #include <TNL/Config/parseCommandLine.h> #include <TNL/Meshes/TypeResolver/resolveMeshType.h> #include <TNL/Meshes/Writers/VTKWriter.h> #include <TNL/Meshes/Writers/VTUWriter.h> #include <TNL/Meshes/Geometry/getDecomposedMesh.h> using namespace TNL; struct MeshTriangulatorConfigTag {}; namespace TNL { namespace Meshes { namespace BuildConfigTags { /**** * Turn off all grids. */ template<> struct GridRealTag< MeshTriangulatorConfigTag, float > { enum { enabled = false }; }; template<> struct GridRealTag< MeshTriangulatorConfigTag, double > { enum { enabled = false }; }; template<> struct GridRealTag< MeshTriangulatorConfigTag, long double > { enum { enabled = false }; }; /**** * Unstructured meshes. */ template<> struct MeshCellTopologyTag< MeshTriangulatorConfigTag, Topologies::Polygon > { enum { enabled = true }; }; template<> struct MeshCellTopologyTag< MeshTriangulatorConfigTag, Topologies::Polyhedron > { enum { enabled = true }; }; // Meshes are enabled only for the world dimension equal to the cell dimension. template< typename CellTopology, int WorldDimension > struct MeshWorldDimensionTag< MeshTriangulatorConfigTag, CellTopology, WorldDimension > { enum { enabled = ( WorldDimension == CellTopology::dimension ) }; }; // Meshes are enabled only for types explicitly listed below. template<> struct MeshRealTag< MeshTriangulatorConfigTag, float > { enum { enabled = true }; }; template<> struct MeshRealTag< MeshTriangulatorConfigTag, double > { enum { enabled = true }; }; template<> struct MeshGlobalIndexTag< MeshTriangulatorConfigTag, long int > { enum { enabled = true }; }; template<> struct MeshGlobalIndexTag< MeshTriangulatorConfigTag, int > { enum { enabled = true }; }; template<> struct MeshLocalIndexTag< MeshTriangulatorConfigTag, short int > { enum { enabled = true }; }; // Config tag specifying the MeshConfig template to use. template<> struct MeshConfigTemplateTag< MeshTriangulatorConfigTag > { template< typename Cell, int WorldDimension = Cell::dimension, typename Real = float, typename GlobalIndex = int, typename LocalIndex = short int > struct MeshConfig { using CellTopology = Cell; using RealType = Real; using GlobalIndexType = GlobalIndex; using LocalIndexType = LocalIndex; static constexpr int worldDimension = WorldDimension; static constexpr int meshDimension = Cell::dimension; template< typename EntityTopology > static constexpr bool subentityStorage( EntityTopology, int SubentityDimension ) { return (SubentityDimension == 0 && EntityTopology::dimension == meshDimension) || (SubentityDimension == meshDimension - 1 && EntityTopology::dimension == meshDimension ) || (SubentityDimension == 0 && EntityTopology::dimension == meshDimension - 1 ); } template< typename EntityTopology > static constexpr bool superentityStorage( EntityTopology, int SuperentityDimension ) { return false; } template< typename EntityTopology > static constexpr bool entityTagsStorage( EntityTopology ) { return false; } static constexpr bool dualGraphStorage() { return false; } }; }; } // namespace BuildConfigTags } // namespace Meshes } // namespace TNL template< typename Mesh > auto getDecomposedMeshHelper( const Mesh& mesh, const String& decompositionType ) { using namespace TNL::Meshes; if( decompositionType[0] == 'c' ) { if( decompositionType[1] == 'c' ) { return getDecomposedMesh< EntityDecomposerVersion::ConnectEdgesToCentroid, EntityDecomposerVersion::ConnectEdgesToCentroid >( mesh ); } else { // decompositionType[1] == 'p' return getDecomposedMesh< EntityDecomposerVersion::ConnectEdgesToCentroid, EntityDecomposerVersion::ConnectEdgesToPoint >( mesh ); } } else { // decompositionType[0] == 'p' if( decompositionType[1] == 'c' ) { return getDecomposedMesh< EntityDecomposerVersion::ConnectEdgesToPoint, EntityDecomposerVersion::ConnectEdgesToCentroid >( mesh ); } else { // decompositionType[1] == 'p' return getDecomposedMesh< EntityDecomposerVersion::ConnectEdgesToPoint, EntityDecomposerVersion::ConnectEdgesToPoint >( mesh ); } } } template< typename Mesh > bool triangulateMesh( const Mesh& mesh, const String& outputFileName, const String& outputFormat, const String& decompositionType ) { const auto decomposedMesh = getDecomposedMeshHelper( mesh, decompositionType ); if( outputFormat == "vtk" ) { using Writer = Meshes::Writers::VTKWriter< decltype( decomposedMesh ) >; std::ofstream file( outputFileName ); Writer writer( file ); writer.template writeEntities< Mesh::getMeshDimension() >( decomposedMesh ); } else if( outputFormat == "vtu" ) { using Writer = Meshes::Writers::VTUWriter< decltype( decomposedMesh ) >; std::ofstream file( outputFileName ); Writer writer( file ); writer.template writeEntities< Mesh::getMeshDimension() >( decomposedMesh ); } return true; } void configSetup( Config::ConfigDescription& config ) { config.addDelimiter( "General settings:" ); config.addRequiredEntry< String >( "input-file", "Input file with the mesh." ); config.addRequiredEntry< String >( "output-file", "Output mesh file path." ); config.addRequiredEntry< String >( "output-file-format", "Output mesh file format." ); config.addEntryEnum( "vtk" ); config.addEntryEnum( "vtu" ); config.addRequiredEntry< String >( "decomposition-type", "Type of decomposition to use." ); config.addEntryEnum( "cc" ); config.addEntryEnum( "cp" ); config.addEntryEnum( "pc" ); config.addEntryEnum( "pp" ); } int main( int argc, char* argv[] ) { Config::ParameterContainer parameters; Config::ConfigDescription conf_desc; configSetup( conf_desc ); if( ! parseCommandLine( argc, argv, conf_desc, parameters ) ) return EXIT_FAILURE; const String inputFileName = parameters.getParameter< String >( "input-file" ); const String inputFileFormat = "auto"; const String outputFileName = parameters.getParameter< String >( "output-file" ); const String outputFileFormat = parameters.getParameter< String >( "output-file-format" ); const String decompositionType = parameters.getParameter< String >( "decomposition-type" ); auto wrapper = [&] ( auto& reader, auto&& mesh ) -> bool { return triangulateMesh( mesh, outputFileName, outputFileFormat, decompositionType ); }; return ! Meshes::resolveAndLoadMesh< MeshTriangulatorConfigTag, Devices::Host >( wrapper, inputFileName, inputFileFormat ); } Loading
src/TNL/Meshes/Geometry/getDecomposedMesh.h +8 −6 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ struct TriangleConfig: public ParentConfig }; template< EntityDecomposerVersion DecomposerVersion, EntityDecomposerVersion SubdecomposerVersion = EntityDecomposerVersion::ConnectEdgesToPoint, typename MeshConfig, std::enable_if_t< std::is_same< typename MeshConfig::CellTopology, Topologies::Polygon >::value, bool > = true > auto // returns MeshBuilder Loading Loading @@ -53,7 +54,7 @@ decomposeMesh( const Mesh< MeshConfig, Devices::Host >& inMesh ) const auto cell = inMesh.template getEntity< CellDimension >( i ); indeces[ i ] = EntityDecomposer::getExtraPointsAndEntitiesCount( cell ); }; ParallelFor< Devices::Host >::exec( 0, inCellsCount, setCounts ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, setCounts ); indeces[ inCellsCount ] = { 0, 0 }; // extend exclusive prefix sum by one element to also get result of reduce at the same time auto reduction = [] ( const IndexPair& a, const IndexPair& b ) -> IndexPair { return { a.first + b.first, a.second + b.second }; Loading @@ -68,7 +69,7 @@ decomposeMesh( const Mesh< MeshConfig, Devices::Host >& inMesh ) auto copyPoint = [&] ( GlobalIndexType i ) mutable { meshBuilder.setPoint( i, inMesh.getPoint( i ) ); }; ParallelFor< Devices::Host >::exec( 0, inPointsCount, copyPoint ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inPointsCount, copyPoint ); // Decompose each cell auto decomposeCell = [&] ( GlobalIndexType i ) mutable { Loading @@ -94,12 +95,13 @@ decomposeMesh( const Mesh< MeshConfig, Devices::Host >& inMesh ) EntityDecomposer::decompose( cell, addPoint, addCell ); }; ParallelFor< Devices::Host >::exec( 0, inCellsCount, decomposeCell ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, decomposeCell ); return meshBuilder; } template< EntityDecomposerVersion DecomposerVersion, EntityDecomposerVersion SubdecomposerVersion = EntityDecomposerVersion::ConnectEdgesToPoint, typename MeshConfig, std::enable_if_t< std::is_same< typename MeshConfig::CellTopology, Topologies::Polygon >::value, bool > = true > auto // returns Mesh Loading Loading @@ -154,7 +156,7 @@ decomposeMesh( const Mesh< MeshConfig, Devices::Host >& inMesh ) const auto cell = inMesh.template getEntity< CellDimension >( i ); indeces[ i ] = EntityDecomposer::getExtraPointsAndEntitiesCount( cell ); }; ParallelFor< Devices::Host >::exec( 0, inCellsCount, setCounts ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, setCounts ); indeces[ inCellsCount ] = { 0, 0 }; // extend exclusive prefix sum by one element to also get result of reduce at the same time auto reduction = [] ( const IndexPair& a, const IndexPair& b ) -> IndexPair { return { a.first + b.first, a.second + b.second }; Loading @@ -169,7 +171,7 @@ decomposeMesh( const Mesh< MeshConfig, Devices::Host >& inMesh ) auto copyPoint = [&] ( GlobalIndexType i ) mutable { meshBuilder.setPoint( i, inMesh.getPoint( i ) ); }; ParallelFor< Devices::Host >::exec( 0, inPointsCount, copyPoint ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inPointsCount, copyPoint ); // Decompose each cell auto decomposeCell = [&] ( GlobalIndexType i ) mutable { Loading @@ -196,7 +198,7 @@ decomposeMesh( const Mesh< MeshConfig, Devices::Host >& inMesh ) EntityDecomposer::decompose( cell, addPoint, addCell ); }; ParallelFor< Devices::Host >::exec( 0, inCellsCount, decomposeCell ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, decomposeCell ); return meshBuilder; } Loading
src/TNL/Meshes/Geometry/getPlanarMesh.h +10 −10 Original line number Diff line number Diff line Loading @@ -58,7 +58,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) indeces[ i ] = EntityDecomposer::getExtraPointsAndEntitiesCount( cell ); } }; ParallelFor< Devices::Host >::exec( 0, inCellsCount, setCounts ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, setCounts ); indeces[ inCellsCount ] = { 0, 0 }; // extend exclusive prefix sum by one element to also get result of reduce at the same time auto reduction = [] ( const IndexPair& a, const IndexPair& b ) -> IndexPair { return { a.first + b.first, a.second + b.second }; Loading @@ -73,7 +73,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) auto copyPoint = [&] ( GlobalIndexType i ) mutable { meshBuilder.setPoint( i, inMesh.getPoint( i ) ); }; ParallelFor< Devices::Host >::exec( 0, inPointsCount, copyPoint ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inPointsCount, copyPoint ); // set corner counts for cells NeighborCountsArray cellCornersCounts( outCellsCount ); Loading @@ -93,7 +93,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) } } }; ParallelFor< Devices::Host >::exec( 0, inCellsCount, setCornersCount ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, setCornersCount ); meshBuilder.setCellCornersCounts( std::move( cellCornersCounts ) ); // Decompose non-planar cells and copy the rest Loading Loading @@ -131,7 +131,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) EntityDecomposer::decompose( cell, addPoint, addCell ); } }; ParallelFor< Devices::Host >::exec( 0, inCellsCount, decomposeCell ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, decomposeCell ); return meshBuilder; } Loading Loading @@ -179,7 +179,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) indeces[ i ] = EntityDecomposer::getExtraPointsAndEntitiesCount( face ); } }; ParallelFor< Devices::Host >::exec( 0, inFacesCount, setCounts ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inFacesCount, setCounts ); indeces[ inFacesCount ] = { 0, 0 }; // extend exclusive prefix sum by one element to also get result of reduce at the same time auto reduction = [] ( const IndexPair& a, const IndexPair& b ) -> IndexPair { return { a.first + b.first, a.second + b.second }; Loading @@ -195,7 +195,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) auto copyPoint = [&] ( GlobalIndexType i ) mutable { meshBuilder.setPoint( i, inMesh.getPoint( i ) ); }; ParallelFor< Devices::Host >::exec( 0, inPointsCount, copyPoint ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inPointsCount, copyPoint ); // set corner counts for cells NeighborCountsArray cellCornersCounts( outCellsCount ); Loading @@ -212,7 +212,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) cellCornersCounts[ i ] = cornersCount; }; ParallelFor< Devices::Host >::exec( 0, inCellsCount, setCellCornersCount ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, setCellCornersCount ); meshBuilder.setCellCornersCounts( std::move( cellCornersCounts ) ); // Set corner ids for cells Loading @@ -228,7 +228,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) } } }; ParallelFor< Devices::Host >::exec( 0, inCellsCount, setCellCornersIds ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, setCellCornersIds ); // set corner counts for faces NeighborCountsArray faceCornersCounts( outFacesCount ); Loading @@ -247,7 +247,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) } } }; ParallelFor< Devices::Host >::exec( 0, inFacesCount, setFaceCornersCount ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inFacesCount, setFaceCornersCount ); meshBuilder.setFaceCornersCounts( std::move( faceCornersCounts ) ); // Decompose non-planar faces and copy the rest Loading Loading @@ -285,7 +285,7 @@ planarCorrection( const Mesh< MeshConfig, Devices::Host >& inMesh ) EntityDecomposer::decompose( face, addPoint, addFace ); } }; ParallelFor< Devices::Host >::exec( 0, inFacesCount, decomposeFace ); ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inFacesCount, decomposeFace ); return meshBuilder; } Loading
src/Tools/CMakeLists.txt +6 −2 Original line number Diff line number Diff line Loading @@ -4,6 +4,8 @@ ADD_EXECUTABLE(tnl-decompose-grid tnl-decompose-grid.cpp ) ADD_EXECUTABLE(tnl-grid-setup tnl-grid-setup.cpp ) ADD_EXECUTABLE(tnl-grid-to-mesh tnl-grid-to-mesh.cpp ) ADD_EXECUTABLE(tnl-mesh-converter tnl-mesh-converter.cpp ) ADD_EXECUTABLE(tnl-triangulate-mesh tnl-triangulate-mesh.cpp ) ADD_EXECUTABLE(tnl-planar-correct-mesh tnl-planar-correct-mesh.cpp ) ADD_EXECUTABLE(tnl-game-of-life tnl-game-of-life.cpp ) if( BUILD_CUDA ) CUDA_ADD_EXECUTABLE(tnl-test-distributed-mesh tnl-test-distributed-mesh.cu ) Loading @@ -28,7 +30,7 @@ endif() find_package( ZLIB ) if( ZLIB_FOUND ) foreach( target IN ITEMS tnl-init tnl-diff tnl-decompose-grid tnl-grid-to-mesh tnl-mesh-converter tnl-game-of-life tnl-test-distributed-mesh ) foreach( target IN ITEMS tnl-init tnl-diff tnl-decompose-grid tnl-grid-to-mesh tnl-mesh-converter tnl-triangulate-mesh tnl-planar-correct-mesh tnl-game-of-life tnl-test-distributed-mesh ) target_compile_definitions(${target} PUBLIC "-DHAVE_ZLIB") target_include_directories(${target} PUBLIC ${ZLIB_INCLUDE_DIRS}) target_link_libraries(${target} ${ZLIB_LIBRARIES}) Loading @@ -37,7 +39,7 @@ endif() find_package( tinyxml2 QUIET ) if( tinyxml2_FOUND ) foreach( target IN ITEMS tnl-init tnl-diff tnl-decompose-grid tnl-grid-to-mesh tnl-mesh-converter tnl-game-of-life tnl-test-distributed-mesh ) foreach( target IN ITEMS tnl-init tnl-diff tnl-decompose-grid tnl-grid-to-mesh tnl-mesh-converter tnl-triangulate-mesh tnl-planar-correct-mesh tnl-game-of-life tnl-test-distributed-mesh ) target_compile_definitions(${target} PUBLIC "-DHAVE_TINYXML2") target_link_libraries(${target} tinyxml2::tinyxml2) endforeach() Loading Loading @@ -72,6 +74,8 @@ INSTALL( TARGETS tnl-init tnl-grid-setup tnl-grid-to-mesh tnl-mesh-converter tnl-triangulate-mesh tnl-planar-correct-mesh tnl-game-of-life tnl-test-distributed-mesh tnl-dicom-reader Loading
src/Tools/tnl-planar-correct-mesh.cpp 0 → 100644 +174 −0 Original line number Diff line number Diff line #include <TNL/Config/parseCommandLine.h> #include <TNL/Meshes/TypeResolver/resolveMeshType.h> #include <TNL/Meshes/Writers/VTKWriter.h> #include <TNL/Meshes/Writers/FPMAWriter.h> #include <TNL/Meshes/Geometry/getPlanarMesh.h> using namespace TNL; struct MeshPlanarCorrectConfigTag {}; namespace TNL { namespace Meshes { namespace BuildConfigTags { /**** * Turn off all grids. */ template<> struct GridRealTag< MeshPlanarCorrectConfigTag, float > { enum { enabled = false }; }; template<> struct GridRealTag< MeshPlanarCorrectConfigTag, double > { enum { enabled = false }; }; template<> struct GridRealTag< MeshPlanarCorrectConfigTag, long double > { enum { enabled = false }; }; /**** * Unstructured meshes. */ template<> struct MeshCellTopologyTag< MeshPlanarCorrectConfigTag, Topologies::Polygon > { enum { enabled = true }; }; template<> struct MeshCellTopologyTag< MeshPlanarCorrectConfigTag, Topologies::Polyhedron > { enum { enabled = true }; }; // Meshes are enabled only for the world dimension equal to 3 template< typename CellTopology, int WorldDimension > struct MeshWorldDimensionTag< MeshPlanarCorrectConfigTag, CellTopology, WorldDimension > { enum { enabled = ( WorldDimension == 3 ) }; }; // Meshes are enabled only for types explicitly listed below. template<> struct MeshRealTag< MeshPlanarCorrectConfigTag, float > { enum { enabled = true }; }; template<> struct MeshRealTag< MeshPlanarCorrectConfigTag, double > { enum { enabled = true }; }; template<> struct MeshGlobalIndexTag< MeshPlanarCorrectConfigTag, long int > { enum { enabled = true }; }; template<> struct MeshGlobalIndexTag< MeshPlanarCorrectConfigTag, int > { enum { enabled = true }; }; template<> struct MeshLocalIndexTag< MeshPlanarCorrectConfigTag, short int > { enum { enabled = true }; }; // Config tag specifying the MeshConfig template to use. template<> struct MeshConfigTemplateTag< MeshPlanarCorrectConfigTag > { template< typename Cell, int WorldDimension = Cell::dimension, typename Real = float, typename GlobalIndex = int, typename LocalIndex = short int > struct MeshConfig { using CellTopology = Cell; using RealType = Real; using GlobalIndexType = GlobalIndex; using LocalIndexType = LocalIndex; static constexpr int worldDimension = WorldDimension; static constexpr int meshDimension = Cell::dimension; template< typename EntityTopology > static constexpr bool subentityStorage( EntityTopology, int SubentityDimension ) { return (SubentityDimension == 0 && EntityTopology::dimension == meshDimension) || (SubentityDimension == meshDimension - 1 && EntityTopology::dimension == meshDimension ) || (SubentityDimension == 0 && EntityTopology::dimension == meshDimension - 1 ); } template< typename EntityTopology > static constexpr bool superentityStorage( EntityTopology, int SuperentityDimension ) { return false; } template< typename EntityTopology > static constexpr bool entityTagsStorage( EntityTopology ) { return false; } static constexpr bool dualGraphStorage() { return false; } }; }; } // namespace BuildConfigTags } // namespace Meshes } // namespace TNL using namespace TNL::Meshes; template< typename Mesh > auto getPlanarMeshHelper( const Mesh& mesh, const String& decompositionType ) { using namespace TNL::Meshes; if( decompositionType[0] == 'c' ) { return getPlanarMesh< EntityDecomposerVersion::ConnectEdgesToCentroid >( mesh ); } else { // decompositionType[0] == 'p' return getPlanarMesh< EntityDecomposerVersion::ConnectEdgesToPoint >( mesh ); } } template< typename Topology > struct PlanarMeshWriter; template<> struct PlanarMeshWriter< Topologies::Polygon > { template< typename Mesh > static void exec( const Mesh& mesh, const String& outputFileName ) { using Writer = Meshes::Writers::VTKWriter< Mesh >; std::ofstream file( outputFileName ); Writer writer( file ); writer.template writeEntities< Mesh::getMeshDimension() >( mesh ); } }; template<> struct PlanarMeshWriter< Topologies::Polyhedron > { template< typename Mesh > static void exec( const Mesh& mesh, const String& outputFileName ) { using Writer = Meshes::Writers::FPMAWriter< Mesh >; std::ofstream file( outputFileName ); Writer writer( file ); writer.writeEntities( mesh ); } }; template< typename Mesh > bool triangulateMesh( const Mesh& mesh, const String& outputFileName, const String& decompositionType ) { const auto planarMesh = getPlanarMeshHelper( mesh, decompositionType ); using PlanarMesh = decltype( planarMesh ); using CellTopology = typename PlanarMesh::Cell::EntityTopology; PlanarMeshWriter< CellTopology >::exec( planarMesh, outputFileName ); return true; } void configSetup( Config::ConfigDescription& config ) { config.addDelimiter( "General settings:" ); config.addRequiredEntry< String >( "input-file", "Input file with the mesh." ); config.addRequiredEntry< String >( "output-file", "Output mesh file path." ); config.addRequiredEntry< String >( "decomposition-type", "Type of decomposition to use for non-planar polygons." ); config.addEntryEnum( "c" ); config.addEntryEnum( "p" ); } int main( int argc, char* argv[] ) { Config::ParameterContainer parameters; Config::ConfigDescription conf_desc; configSetup( conf_desc ); if( ! parseCommandLine( argc, argv, conf_desc, parameters ) ) return EXIT_FAILURE; const String inputFileName = parameters.getParameter< String >( "input-file" ); const String inputFileFormat = "auto"; const String outputFileName = parameters.getParameter< String >( "output-file" ); const String decompositionType = parameters.getParameter< String >( "decomposition-type" ); auto wrapper = [&] ( auto& reader, auto&& mesh ) -> bool { return triangulateMesh( mesh, outputFileName, decompositionType ); }; return ! Meshes::resolveAndLoadMesh< MeshPlanarCorrectConfigTag, Devices::Host >( wrapper, inputFileName, inputFileFormat ); }
src/Tools/tnl-triangulate-mesh.cpp 0 → 100644 +174 −0 Original line number Diff line number Diff line #include <TNL/Config/parseCommandLine.h> #include <TNL/Meshes/TypeResolver/resolveMeshType.h> #include <TNL/Meshes/Writers/VTKWriter.h> #include <TNL/Meshes/Writers/VTUWriter.h> #include <TNL/Meshes/Geometry/getDecomposedMesh.h> using namespace TNL; struct MeshTriangulatorConfigTag {}; namespace TNL { namespace Meshes { namespace BuildConfigTags { /**** * Turn off all grids. */ template<> struct GridRealTag< MeshTriangulatorConfigTag, float > { enum { enabled = false }; }; template<> struct GridRealTag< MeshTriangulatorConfigTag, double > { enum { enabled = false }; }; template<> struct GridRealTag< MeshTriangulatorConfigTag, long double > { enum { enabled = false }; }; /**** * Unstructured meshes. */ template<> struct MeshCellTopologyTag< MeshTriangulatorConfigTag, Topologies::Polygon > { enum { enabled = true }; }; template<> struct MeshCellTopologyTag< MeshTriangulatorConfigTag, Topologies::Polyhedron > { enum { enabled = true }; }; // Meshes are enabled only for the world dimension equal to the cell dimension. template< typename CellTopology, int WorldDimension > struct MeshWorldDimensionTag< MeshTriangulatorConfigTag, CellTopology, WorldDimension > { enum { enabled = ( WorldDimension == CellTopology::dimension ) }; }; // Meshes are enabled only for types explicitly listed below. template<> struct MeshRealTag< MeshTriangulatorConfigTag, float > { enum { enabled = true }; }; template<> struct MeshRealTag< MeshTriangulatorConfigTag, double > { enum { enabled = true }; }; template<> struct MeshGlobalIndexTag< MeshTriangulatorConfigTag, long int > { enum { enabled = true }; }; template<> struct MeshGlobalIndexTag< MeshTriangulatorConfigTag, int > { enum { enabled = true }; }; template<> struct MeshLocalIndexTag< MeshTriangulatorConfigTag, short int > { enum { enabled = true }; }; // Config tag specifying the MeshConfig template to use. template<> struct MeshConfigTemplateTag< MeshTriangulatorConfigTag > { template< typename Cell, int WorldDimension = Cell::dimension, typename Real = float, typename GlobalIndex = int, typename LocalIndex = short int > struct MeshConfig { using CellTopology = Cell; using RealType = Real; using GlobalIndexType = GlobalIndex; using LocalIndexType = LocalIndex; static constexpr int worldDimension = WorldDimension; static constexpr int meshDimension = Cell::dimension; template< typename EntityTopology > static constexpr bool subentityStorage( EntityTopology, int SubentityDimension ) { return (SubentityDimension == 0 && EntityTopology::dimension == meshDimension) || (SubentityDimension == meshDimension - 1 && EntityTopology::dimension == meshDimension ) || (SubentityDimension == 0 && EntityTopology::dimension == meshDimension - 1 ); } template< typename EntityTopology > static constexpr bool superentityStorage( EntityTopology, int SuperentityDimension ) { return false; } template< typename EntityTopology > static constexpr bool entityTagsStorage( EntityTopology ) { return false; } static constexpr bool dualGraphStorage() { return false; } }; }; } // namespace BuildConfigTags } // namespace Meshes } // namespace TNL template< typename Mesh > auto getDecomposedMeshHelper( const Mesh& mesh, const String& decompositionType ) { using namespace TNL::Meshes; if( decompositionType[0] == 'c' ) { if( decompositionType[1] == 'c' ) { return getDecomposedMesh< EntityDecomposerVersion::ConnectEdgesToCentroid, EntityDecomposerVersion::ConnectEdgesToCentroid >( mesh ); } else { // decompositionType[1] == 'p' return getDecomposedMesh< EntityDecomposerVersion::ConnectEdgesToCentroid, EntityDecomposerVersion::ConnectEdgesToPoint >( mesh ); } } else { // decompositionType[0] == 'p' if( decompositionType[1] == 'c' ) { return getDecomposedMesh< EntityDecomposerVersion::ConnectEdgesToPoint, EntityDecomposerVersion::ConnectEdgesToCentroid >( mesh ); } else { // decompositionType[1] == 'p' return getDecomposedMesh< EntityDecomposerVersion::ConnectEdgesToPoint, EntityDecomposerVersion::ConnectEdgesToPoint >( mesh ); } } } template< typename Mesh > bool triangulateMesh( const Mesh& mesh, const String& outputFileName, const String& outputFormat, const String& decompositionType ) { const auto decomposedMesh = getDecomposedMeshHelper( mesh, decompositionType ); if( outputFormat == "vtk" ) { using Writer = Meshes::Writers::VTKWriter< decltype( decomposedMesh ) >; std::ofstream file( outputFileName ); Writer writer( file ); writer.template writeEntities< Mesh::getMeshDimension() >( decomposedMesh ); } else if( outputFormat == "vtu" ) { using Writer = Meshes::Writers::VTUWriter< decltype( decomposedMesh ) >; std::ofstream file( outputFileName ); Writer writer( file ); writer.template writeEntities< Mesh::getMeshDimension() >( decomposedMesh ); } return true; } void configSetup( Config::ConfigDescription& config ) { config.addDelimiter( "General settings:" ); config.addRequiredEntry< String >( "input-file", "Input file with the mesh." ); config.addRequiredEntry< String >( "output-file", "Output mesh file path." ); config.addRequiredEntry< String >( "output-file-format", "Output mesh file format." ); config.addEntryEnum( "vtk" ); config.addEntryEnum( "vtu" ); config.addRequiredEntry< String >( "decomposition-type", "Type of decomposition to use." ); config.addEntryEnum( "cc" ); config.addEntryEnum( "cp" ); config.addEntryEnum( "pc" ); config.addEntryEnum( "pp" ); } int main( int argc, char* argv[] ) { Config::ParameterContainer parameters; Config::ConfigDescription conf_desc; configSetup( conf_desc ); if( ! parseCommandLine( argc, argv, conf_desc, parameters ) ) return EXIT_FAILURE; const String inputFileName = parameters.getParameter< String >( "input-file" ); const String inputFileFormat = "auto"; const String outputFileName = parameters.getParameter< String >( "output-file" ); const String outputFileFormat = parameters.getParameter< String >( "output-file-format" ); const String decompositionType = parameters.getParameter< String >( "decomposition-type" ); auto wrapper = [&] ( auto& reader, auto&& mesh ) -> bool { return triangulateMesh( mesh, outputFileName, outputFileFormat, decompositionType ); }; return ! Meshes::resolveAndLoadMesh< MeshTriangulatorConfigTag, Devices::Host >( wrapper, inputFileName, inputFileFormat ); }