Commit 1192e62b authored by Ján Bobot's avatar Ján Bobot
Browse files

Added tools for mesh triangulation and planar correction and modified their unit tests

parent 1113a1a5
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -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
@@ -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 };
@@ -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 {
@@ -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
@@ -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 };
@@ -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 {
@@ -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;
}
+10 −10
Original line number Diff line number Diff line
@@ -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 };
@@ -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 );
@@ -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
@@ -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;
}
@@ -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 };
@@ -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 );
@@ -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
@@ -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 );
@@ -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
@@ -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;
}
+6 −2
Original line number Diff line number Diff line
@@ -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 )
@@ -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})
@@ -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()
@@ -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
+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 );
}
+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