diff --git a/.gitignore b/.gitignore index 14140a23bf24c01df069e7251eeae28ff0834364..a091f8bf52373138593d57914c5d04378cc2c015 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # build/output directories /builddir +/build-tinyxml2 /Documentation/html/ /Documentation/output_snippets/ diff --git a/src/Benchmarks/CMakeLists.txt b/src/Benchmarks/CMakeLists.txt index 50e46776282b3a13845337c26ddb9d83c31751ae..54f61a311fb4f076cda5d4ef2da08fd2abc28320 100644 --- a/src/Benchmarks/CMakeLists.txt +++ b/src/Benchmarks/CMakeLists.txt @@ -1,4 +1,6 @@ -add_subdirectory( HeatEquation ) +#add_subdirectory( HeatEquation ) +add_subdirectory( HeatEquationGrid ) +add_subdirectory( Grid ) add_subdirectory( BLAS ) add_subdirectory( NDArray ) add_subdirectory( SpMV ) @@ -6,5 +8,4 @@ add_subdirectory( DistSpMV ) add_subdirectory( LinearSolvers ) #add_subdirectory( ODESolvers ) add_subdirectory( Sorting ) -add_subdirectory( Traversers ) -add_subdirectory( Mesh ) +#add_subdirectory( Traversers ) diff --git a/src/Benchmarks/Grid/CMakeLists.txt b/src/Benchmarks/Grid/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3b927665152de564e3cce00b2a1e79dcdaa11883 --- /dev/null +++ b/src/Benchmarks/Grid/CMakeLists.txt @@ -0,0 +1,28 @@ + +function(generate_executables HEADER SUFFIX MAIN_FILE_PATH ARGS) +get_filename_component(MODULE_NAME ${HEADER} NAME_WE) + +if (${BUILD_CUDA}) + SET(SUPPORT_FILENAME ${MODULE_NAME}.cu) +else() + SET(SUPPORT_FILENAME ${MODULE_NAME}.cpp) +endif() + +# Targets are separated by suffix provided +set(MODULE_NAME ${MODULE_NAME}_${SUFFIX}) + +if (${BUILD_CUDA}) + CUDA_ADD_EXECUTABLE(${MODULE_NAME} ${HEADER} ${SUPPORT_FILENAME} OPTIONS ${CUDA_TESTS_FLAGS}) + TARGET_LINK_LIBRARIES(${MODULE_NAME} ${TESTS_LIBRARIES}) +else() + ADD_EXECUTABLE(${MODULE_NAME} ${HEADER} ${SUPPORT_FILENAME}) + TARGET_COMPILE_OPTIONS(${MODULE_NAME} PRIVATE ${CXX_TESTS_FLAGS}) +endif() + +endfunction() + +SET(SOME_ARGS "") + +generate_executables(Grid1D.h "OperationBenchmark" "Grid1D.h" SOME_ARGS) +generate_executables(Grid2D.h "OperationBenchmark" "Grid2D.h" SOME_ARGS) +generate_executables(Grid3D.h "OperationBenchmark" "Grid3D.h" SOME_ARGS) diff --git a/src/Benchmarks/Grid/Grid1D.cpp b/src/Benchmarks/Grid/Grid1D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2ffba53d970751a1fe5c31d6e5c07e3065924821 --- /dev/null +++ b/src/Benchmarks/Grid/Grid1D.cpp @@ -0,0 +1,2 @@ + +#include "Grid1D.h" diff --git a/src/Benchmarks/Grid/Grid1D.cu b/src/Benchmarks/Grid/Grid1D.cu new file mode 100644 index 0000000000000000000000000000000000000000..2ffba53d970751a1fe5c31d6e5c07e3065924821 --- /dev/null +++ b/src/Benchmarks/Grid/Grid1D.cu @@ -0,0 +1,2 @@ + +#include "Grid1D.h" diff --git a/src/Benchmarks/Grid/Grid1D.h b/src/Benchmarks/Grid/Grid1D.h new file mode 100644 index 0000000000000000000000000000000000000000..df7cb1c17e3df2865e3a8111de98ac0558888427 --- /dev/null +++ b/src/Benchmarks/Grid/Grid1D.h @@ -0,0 +1,19 @@ + +#pragma once + +#include "GridBenchmark.h" + +#define GRID_DIMENSION 1 + +int main(int argc, char* argv[]) { + GridBenchmark benchmark; + + auto config = GridBenchmark::makeInputConfig(GRID_DIMENSION); + + TNL::Config::ParameterContainer parameters; + + if (!parseCommandLine(argc, argv, config, parameters)) + return EXIT_FAILURE; + + return benchmark.runBenchmark(parameters); +} diff --git a/src/Benchmarks/Grid/Grid2D.cpp b/src/Benchmarks/Grid/Grid2D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6ff75c9621a9f6a8ab5c38f93f8992a423833ac7 --- /dev/null +++ b/src/Benchmarks/Grid/Grid2D.cpp @@ -0,0 +1,2 @@ + +#include "Grid2D.h" diff --git a/src/Benchmarks/Grid/Grid2D.cu b/src/Benchmarks/Grid/Grid2D.cu new file mode 100644 index 0000000000000000000000000000000000000000..6ff75c9621a9f6a8ab5c38f93f8992a423833ac7 --- /dev/null +++ b/src/Benchmarks/Grid/Grid2D.cu @@ -0,0 +1,2 @@ + +#include "Grid2D.h" diff --git a/src/Benchmarks/Grid/Grid2D.h b/src/Benchmarks/Grid/Grid2D.h new file mode 100644 index 0000000000000000000000000000000000000000..9d8488cace2547da9ff8e0b0eff67e395b5fcc99 --- /dev/null +++ b/src/Benchmarks/Grid/Grid2D.h @@ -0,0 +1,19 @@ + +#pragma once + +#include "GridBenchmark.h" + +#define GRID_DIMENSION 2 + +int main(int argc, char* argv[]) { + GridBenchmark benchmark; + + auto config = GridBenchmark::makeInputConfig(GRID_DIMENSION); + + TNL::Config::ParameterContainer parameters; + + if (!parseCommandLine(argc, argv, config, parameters)) + return EXIT_FAILURE; + + return benchmark.runBenchmark(parameters); +} diff --git a/src/Benchmarks/Grid/Grid3D.cpp b/src/Benchmarks/Grid/Grid3D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9fb7d12358b8972d74fa82b4b45c5bb78114fa72 --- /dev/null +++ b/src/Benchmarks/Grid/Grid3D.cpp @@ -0,0 +1,2 @@ + +#include "Grid3D.h" diff --git a/src/Benchmarks/Grid/Grid3D.cu b/src/Benchmarks/Grid/Grid3D.cu new file mode 100644 index 0000000000000000000000000000000000000000..9fb7d12358b8972d74fa82b4b45c5bb78114fa72 --- /dev/null +++ b/src/Benchmarks/Grid/Grid3D.cu @@ -0,0 +1,2 @@ + +#include "Grid3D.h" diff --git a/src/Benchmarks/Grid/Grid3D.h b/src/Benchmarks/Grid/Grid3D.h new file mode 100644 index 0000000000000000000000000000000000000000..a31d17d947809549f78ad0dc9400ff03761fda33 --- /dev/null +++ b/src/Benchmarks/Grid/Grid3D.h @@ -0,0 +1,19 @@ + +#pragma once + +#include "GridBenchmark.h" + +#define GRID_DIMENSION 3 + +int main(int argc, char* argv[]) { + GridBenchmark benchmark; + + auto config = GridBenchmark::makeInputConfig(GRID_DIMENSION); + + TNL::Config::ParameterContainer parameters; + + if (!parseCommandLine(argc, argv, config, parameters)) + return EXIT_FAILURE; + + return benchmark.runBenchmark(parameters); +} diff --git a/src/Benchmarks/Grid/GridBenchmark.h b/src/Benchmarks/Grid/GridBenchmark.h new file mode 100644 index 0000000000000000000000000000000000000000..767f62cacb130b738b157a85f31191c99694c65d --- /dev/null +++ b/src/Benchmarks/Grid/GridBenchmark.h @@ -0,0 +1,197 @@ + +#pragma once + +#include "Operations.h" + +#include + +#include +#include + +#include +#include + +#include + +static std::vector dimensionParameterIds = { "x-dimension", "y-dimension", "z-dimension" }; + +class GridBenchmark { + public: + using Benchmark = typename TNL::Benchmarks::Benchmark<>; + + template + int runBenchmark(const TNL::Config::ParameterContainer& parameters) const { + if (!TNL::Devices::Host::setup( parameters ) || !TNL::Devices::Cuda::setup( parameters ) ) + return EXIT_FAILURE; + + const TNL::String logFileName = parameters.getParameter( "log-file" ); + const TNL::String outputMode = parameters.getParameter( "output-mode" ); + const TNL::String precision = parameters.getParameter( "precision" ); + const TNL::String device = parameters.getParameter("device"); + + const int verbose = parameters.getParameter< int >("verbose"); + const int loops = parameters.getParameter< int >("loops"); + + auto mode = std::ios::out; + + if( outputMode == "append" ) + mode |= std::ios::app; + + std::ofstream logFile( logFileName.getString(), mode ); + + Benchmark benchmark(logFile, loops, verbose); + + // write global metadata into a separate file + std::map< std::string, std::string > metadata = TNL::Benchmarks::getHardwareMetadata(); + TNL::Benchmarks::writeMapAsJson( metadata, logFileName, ".metadata.json" ); + + if (device == "host" || device == "all") { + if (precision == "all" || precision == "float") + time(benchmark, parameters); + if (precision == "all" || precision == "double") + time(benchmark, parameters); + } + + #ifdef HAVE_CUDA + if (device == "cuda" || device == "all") { + if (precision == "all" || precision == "float") + time(benchmark, parameters); + if (precision == "all" || precision == "double") + time(benchmark, parameters); + } + #endif + + return 0; + } + + template + void time(Benchmark& benchmark, const TNL::Config::ParameterContainer& parameters) const { + using Grid = typename TNL::Meshes::Grid; + using Coordinate = typename Grid::Coordinate; + + Coordinate dimensions; + + for (int i = 0; i < GridDimension; i++) + dimensions[i] = parameters.getParameter(dimensionParameterIds[i]); + + Grid grid; + + grid.setDimensions(dimensions); + + auto forEachEntityDimension = [&](const auto entityDimension) { + using Entity = TNL::Meshes::GridEntity; + + timeTraverse(benchmark, grid); + + timeTraverse(benchmark, grid); + timeTraverse(benchmark, grid); + timeTraverse(benchmark, grid); + timeTraverse(benchmark, grid); + timeTraverse(benchmark, grid); + + timeTraverse(benchmark, grid); + timeTraverse(benchmark, grid); + timeTraverse(benchmark, grid); + }; + + TNL::Meshes::Templates::DescendingFor::exec(forEachEntityDimension); + } + + static TNL::Config::ConfigDescription makeInputConfig(int gridDimension) { + TNL_ASSERT_LE(gridDimension, 3, "Only support for grids with dimension less or equal 3"); + TNL::Config::ConfigDescription config; + + config.addDelimiter("Benchmark settings:"); + config.addEntry("id", "Identifier of the run", "unknown"); + config.addEntry("log-file", "Log file name.", "output.log"); + config.addEntry("output-mode", "Mode for opening the log file.", "overwrite"); + config.addEntryEnum("append"); + config.addEntryEnum("overwrite"); + + config.addEntry("device", "Device the computation will run on.", "cuda"); + config.addEntryEnum("all"); + config.addEntryEnum("host"); + + #ifdef HAVE_CUDA + config.addEntryEnum("cuda"); + #endif + + config.addEntry("precision", "Precision of the arithmetics.", "double"); + config.addEntryEnum("float"); + config.addEntryEnum("double"); + config.addEntryEnum("all"); + + config.addEntry("loops", "Number of iterations for every computation.", 10); + config.addEntry("verbose", "Verbose mode.", 1); + + for (int i = 0; i < gridDimension; i++) + config.addEntry(dimensionParameterIds[i], "The " + dimensionParameterIds[i] + " of grid:", 100); + + config.addDelimiter("Device settings:"); + TNL::Devices::Host::configSetup( config ); + + #ifdef HAVE_CUDA + TNL::Devices::Cuda::configSetup( config ); + #endif + + return config; + } + + template + void timeTraverse(Benchmark& benchmark, const Grid& grid) const { + auto exec = [] __cuda_callable__ (typename Grid::EntityType& entity) mutable { + Operation::exec(entity); + }; + + auto device = TNL::getType(); + auto operation = TNL::getType(); + + const Benchmark::MetadataColumns columns = { + { "operation_id", operation }, + { "dimensions", TNL::convertToString(grid.getDimensions()) }, + { "entity_dimension", TNL::convertToString(EntityDimension) }, + { "entitiesCounts", TNL::convertToString(grid.getEntitiesCount(EntityDimension)) } + }; + + Benchmark::MetadataColumns forAllColumns = { + { "traverse_id", "forAll" } + }; + + forAllColumns.insert(forAllColumns.end(), columns.begin(), columns.end()); + benchmark.setMetadataColumns(forAllColumns); + + auto measureAll = [=]() { + grid.template forAll(exec); + }; + + benchmark.time(device, measureAll); + + + Benchmark::MetadataColumns forInteriorColumns = { + { "traverse_id", "forInterior" } + }; + + forInteriorColumns.insert(forInteriorColumns.end(), columns.begin(), columns.end()); + benchmark.setMetadataColumns(forInteriorColumns); + + auto measureInterior = [=]() { + grid.template forInterior(exec); + }; + + benchmark.time(device, measureInterior); + + + Benchmark::MetadataColumns forBoundaryColumns = { + { "traverse_id", "forBoundary" } + }; + + forBoundaryColumns.insert(forBoundaryColumns.end(), columns.begin(), columns.end()); + benchmark.setMetadataColumns(forInteriorColumns); + + auto measureBoundary = [=]() { + grid.template forBoundary(exec); + }; + + benchmark.time(device, measureBoundary); + } +}; diff --git a/src/Benchmarks/Grid/Operations.h b/src/Benchmarks/Grid/Operations.h new file mode 100644 index 0000000000000000000000000000000000000000..ec3f6426a3af1048dd3d555844fe17e0f8ad8038 --- /dev/null +++ b/src/Benchmarks/Grid/Operations.h @@ -0,0 +1,102 @@ + +#pragma once + +#include +#include + + +struct VoidOperation { + public: + + template + __cuda_callable__ inline + static void exec(Entity& entity) {} +}; + + +struct GetEntityIsBoundaryOperation { + public: + template + __cuda_callable__ inline + static void exec(Entity& entity) { + bool isBoundary = entity.isBoundary(); + + if (isBoundary) + isBoundary = false; + } +}; + +struct GetEntityCoordinateOperation { + public: + template + __cuda_callable__ inline + static void exec(Entity& entity) { + typename Entity::GridType::Coordinate coordinate = entity.getCoordinates(); + + coordinate.x() += 1; + } +}; + +struct GetEntityIndexOperation { + public: + template + __cuda_callable__ inline + static void exec(Entity& entity) { + int index = entity.getIndex(); + + index += 1; + } +}; + +struct GetEntityBasisOperation { + public: + template + __cuda_callable__ inline + static void exec(Entity& entity) { + typename Entity::GridType::Coordinate coordinate = entity.getBasis(); + + coordinate.x() += 1; + } +}; + +struct RefreshEntityOperation { + public: + template + __cuda_callable__ inline + static void exec(Entity& entity) { + entity.refresh(); + } +}; + +struct GetMeshDimensionOperation { + public: + template + __cuda_callable__ inline + static void exec(Entity& entity) { + typename Entity::GridType::Coordinate coordinate = entity.getMesh().getDimensions(); + + coordinate.x() += 1; + } +}; + +struct GetOriginOperation { + public: + template + __cuda_callable__ inline + static void exec(Entity& entity) { + typename Entity::GridType::Point coordinate = entity.getMesh().getOrigin(); + + coordinate.x() += 1; + } +}; + +struct GetEntitiesCountsOperation { + public: + template + __cuda_callable__ inline + static void exec(Entity& entity) { + typename Entity::GridType::EntitiesCounts coordinate = entity.getMesh().getEntitiesCounts(); + + coordinate.x() += 1; + } +}; diff --git a/src/Benchmarks/HeatEquation/CMakeLists.txt b/src/Benchmarks/HeatEquation/CMakeLists.txt index 64a5d9fbe0b3c5c3d06b6f6d28f04f532be53e07..616ab6658de45581e227025aff4529302128d4b8 100644 --- a/src/Benchmarks/HeatEquation/CMakeLists.txt +++ b/src/Benchmarks/HeatEquation/CMakeLists.txt @@ -12,7 +12,7 @@ ENDIF() INSTALL( TARGETS -# tnl-benchmark-heat-equation + tnl-benchmark-heat-equation tnl-benchmark-simple-heat-equation RUNTIME DESTINATION bin ) @@ -20,4 +20,7 @@ if( BUILD_CUDA ) INSTALL( TARGETS tnl-benchmark-simple-heat-equation-bug RUNTIME DESTINATION bin ) -endif() \ No newline at end of file +endif() + + + diff --git a/src/Benchmarks/HeatEquation/tnlTestGrid2D.h b/src/Benchmarks/HeatEquation/tnlTestGrid2D.h index b589e5a6582d11edb9dbd2e22405d075108da694..705d3ea2783110a6cafcd8b2ba219d4ddf7cf0b1 100644 --- a/src/Benchmarks/HeatEquation/tnlTestGrid2D.h +++ b/src/Benchmarks/HeatEquation/tnlTestGrid2D.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once @@ -21,8 +21,6 @@ class Grid : public tnlObject //#include //#include - -#include #include #include #include @@ -45,25 +43,25 @@ class Meshes::Grid< 2, Real, Device, Index > : public tnlObject typedef Index IndexType; typedef Containers::StaticVector< 2, Real > PointType; typedef Containers::StaticVector< 2, Index > CoordinatesType; - + static const int meshDimension = 2; - //template< int EntityDimension, + //template< int EntityDimension, // typename Config = GridEntityNoStencilStorage >//CrossStencilStorage< 1 > > //using MeshEntity = GridEntity< ThisType, EntityDimension, Config >; - + //typedef MeshEntity< meshDimension, GridEntityCrossStencilStorage< 1 > > Cell; //typedef MeshEntity< meshDimension - 1, GridEntityNoStencilStorage > Face; //typedef MeshEntity< 0 > Point; - + // TODO: remove this - template< int EntityDimension, + template< int EntityDimension, typename Config = GridEntityNoStencilStorage >//CrossStencilStorage< 1 > > using TestMeshEntity = tnlTestGridEntity< ThisType, EntityDimension, Config >; typedef TestMeshEntity< meshDimension, GridEntityCrossStencilStorage< 1 > > TestCell; ///// - + static constexpr int getMeshDimension() { return meshDimension; }; Grid(); @@ -90,11 +88,11 @@ class Meshes::Grid< 2, Real, Device, Index > : public tnlObject template< typename EntityType > __cuda_callable__ inline IndexType getEntitiesCount() const; - + template< typename EntityType > __cuda_callable__ inline EntityType getEntity( const IndexType& entityIndex ) const; - + template< typename EntityType > __cuda_callable__ inline Index getEntityIndex( const EntityType& entity ) const; @@ -102,21 +100,21 @@ class Meshes::Grid< 2, Real, Device, Index > : public tnlObject template< typename EntityType > __cuda_callable__ RealType getEntityMeasure( const EntityType& entity ) const; - + __cuda_callable__ RealType getCellMeasure() const; - + __cuda_callable__ inline PointType getSpaceSteps() const; template< int xPow, int yPow > __cuda_callable__ inline const RealType& getSpaceStepsProducts() const; - + __cuda_callable__ inline RealType getSmallestSpaceStep() const; - + template< typename GridFunction > typename GridFunction::RealType getAbsMax( const GridFunction& f ) const; @@ -159,16 +157,16 @@ class Meshes::Grid< 2, Real, Device, Index > : public tnlObject void computeSpaceSteps(); CoordinatesType dimensions; - + IndexType numberOfCells, numberOfNxFaces, numberOfNyFaces, numberOfFaces, numberOfVertices; PointType origin, proportions; - + PointType spaceSteps; - + RealType spaceStepsProducts[ 5 ][ 5 ]; - - template< typename, typename, int > + + template< typename, typename, int > friend class GridEntityGetter; }; @@ -225,9 +223,9 @@ void Meshes::Grid< 2, Real, Device, Index > :: computeSpaceSteps() { this->spaceSteps.x() = this->proportions.x() / ( Real ) this->getDimensions().x(); this->spaceSteps.y() = this->proportions.y() / ( Real ) this->getDimensions().y(); - const RealType& hx = this->spaceSteps.x(); + const RealType& hx = this->spaceSteps.x(); const RealType& hy = this->spaceSteps.y(); - + Real auxX, auxY; for( int i = 0; i < 5; i++ ) { @@ -269,7 +267,7 @@ void Meshes::Grid< 2, Real, Device, Index > :: computeSpaceSteps() auxY = hy * hy; break; } - this->spaceStepsProducts[ i ][ j ] = auxX * auxY; + this->spaceStepsProducts[ i ][ j ] = auxX * auxY; } } } @@ -325,7 +323,7 @@ void Meshes::Grid< 2, Real, Device, Index > :: setDomain( const PointType& origi template< typename Real, typename Device, typename Index > -__cuda_callable__ inline +__cuda_callable__ inline const typename Meshes::Grid< 2, Real, Device, Index >::PointType& Meshes::Grid< 2, Real, Device, Index >::getOrigin() const { @@ -335,7 +333,7 @@ Meshes::Grid< 2, Real, Device, Index >::getOrigin() const template< typename Real, typename Device, typename Index > -__cuda_callable__ inline +__cuda_callable__ inline const typename Meshes::Grid< 2, Real, Device, Index > :: PointType& Meshes::Grid< 2, Real, Device, Index > :: getProportions() const { @@ -346,23 +344,23 @@ template< typename Real, typename Device, typename Index > template< typename EntityType > -__cuda_callable__ inline +__cuda_callable__ inline Index -Meshes::Grid< 2, Real, Device, Index >:: +Meshes::Grid< 2, Real, Device, Index >:: getEntitiesCount() const { static_assert( EntityType::entityDimension <= 2 && EntityType::entityDimension >= 0, "Wrong grid entity dimension." ); - + switch( EntityType::entityDimension ) { case 2: return this->numberOfCells; case 1: - return this->numberOfFaces; + return this->numberOfFaces; case 0: return this->numberOfVertices; - } + } return -1; } @@ -370,14 +368,14 @@ template< typename Real, typename Device, typename Index > template< typename EntityType > -__cuda_callable__ inline +__cuda_callable__ inline EntityType Meshes::Grid< 2, Real, Device, Index >:: getEntity( const IndexType& entityIndex ) const { static_assert( EntityType::entityDimension <= 2 && EntityType::entityDimension >= 0, "Wrong grid entity dimension." ); - + return GridEntityGetter< ThisType, EntityType >::getEntity( *this, entityIndex ); } @@ -385,14 +383,14 @@ template< typename Real, typename Device, typename Index > template< typename EntityType > -__cuda_callable__ inline +__cuda_callable__ inline Index Meshes::Grid< 2, Real, Device, Index >:: getEntityIndex( const EntityType& entity ) const { static_assert( EntityType::entityDimension <= 2 && EntityType::entityDimension >= 0, "Wrong grid entity dimension." ); - + return GridEntityGetter< ThisType, EntityType >::getEntityIndex( *this, entity ); } @@ -435,14 +433,14 @@ template< typename Real, typename Device, typename Index > template< int xPow, int yPow > -__cuda_callable__ inline -const Real& +__cuda_callable__ inline +const Real& Meshes::Grid< 2, Real, Device, Index >:: getSpaceStepsProducts() const { - tnlTNL_ASSERT( xPow >= -2 && xPow <= 2, + tnlTNL_ASSERT( xPow >= -2 && xPow <= 2, std::cerr << " xPow = " << xPow ); - tnlTNL_ASSERT( yPow >= -2 && yPow <= 2, + tnlTNL_ASSERT( yPow >= -2 && yPow <= 2, std::cerr << " yPow = " << yPow ); return this->spaceStepsProducts[ yPow + 2 ][ xPow + 2 ]; @@ -714,8 +712,8 @@ bool Meshes::Grid< 2, Real, Device, Index > :: write( const MeshFunction& functi { if( this->template getEntitiesCount< Cell >() != function. getSize() ) { - std::cerr << "The size ( " << function. getSize() - << " ) of a mesh function does not agree with the DOFs ( " + std::cerr << "The size ( " << function. getSize() + << " ) of a mesh function does not agree with the DOFs ( " << this->template getEntitiesCount< Cell >() << " ) of a mesh." < : public tnlObject typedef Index IndexType; typedef Containers::StaticVector< 2, Real > PointType; typedef Containers::StaticVector< 2, Index > CoordinatesType; - + static const int meshDimension = 2; - /*template< int EntityDimension, + /*template< int EntityDimension, typename Config = GridEntityNoStencilStorage >//CrossStencilStorage< 1 > > using MeshEntity = GridEntity< ThisType, EntityDimension, Config >; - + typedef MeshEntity< meshDimension, GridEntityCrossStencilStorage< 1 > > Cell; typedef MeshEntity< meshDimension - 1, GridEntityNoStencilStorage > Face; typedef MeshEntity< 0 > Point;*/ - + // TODO: remove this - template< int EntityDimension, + template< int EntityDimension, typename Config = GridEntityNoStencilStorage >//CrossStencilStorage< 1 > > using TestMeshEntity = tnlTestGridEntity< ThisType, EntityDimension, Config >; typedef TestMeshEntity< meshDimension, GridEntityCrossStencilStorage< 1 > > Cell; ///// - + static constexpr int getMeshDimension() { return meshDimension; }; Grid(); @@ -843,11 +841,11 @@ class Meshes::Grid< 2, Real, Device, Index > : public tnlObject template< typename EntityType > __cuda_callable__ inline IndexType getEntitiesCount() const; - + template< typename EntityType > __cuda_callable__ inline EntityType getEntity( const IndexType& entityIndex ) const; - + template< typename EntityType > __cuda_callable__ inline Index getEntityIndex( const EntityType& entity ) const; @@ -855,21 +853,21 @@ class Meshes::Grid< 2, Real, Device, Index > : public tnlObject template< typename EntityType > __cuda_callable__ RealType getEntityMeasure( const EntityType& entity ) const; - + __cuda_callable__ RealType getCellMeasure() const; - + __cuda_callable__ inline PointType getSpaceSteps() const; template< int xPow, int yPow > __cuda_callable__ inline const RealType& getSpaceStepsProducts() const; - + __cuda_callable__ inline RealType getSmallestSpaceStep() const; - + template< typename GridFunction > typename GridFunction::RealType getAbsMax( const GridFunction& f ) const; @@ -912,16 +910,16 @@ class Meshes::Grid< 2, Real, Device, Index > : public tnlObject void computeSpaceSteps(); CoordinatesType dimensions; - + IndexType numberOfCells, numberOfNxFaces, numberOfNyFaces, numberOfFaces, numberOfVertices; PointType origin, proportions; - + PointType spaceSteps; - + RealType spaceStepsProducts[ 5 ][ 5 ]; - - template< typename, typename, int > + + template< typename, typename, int > friend class GridEntityGetter; }; @@ -967,9 +965,9 @@ void Meshes::Grid< 2, Real, Device, Index > :: computeSpaceSteps() { this->spaceSteps.x() = this->proportions.x() / ( Real ) this->getDimensions().x(); this->spaceSteps.y() = this->proportions.y() / ( Real ) this->getDimensions().y(); - const RealType& hx = this->spaceSteps.x(); + const RealType& hx = this->spaceSteps.x(); const RealType& hy = this->spaceSteps.y(); - + Real auxX, auxY; for( int i = 0; i < 5; i++ ) { @@ -1011,7 +1009,7 @@ void Meshes::Grid< 2, Real, Device, Index > :: computeSpaceSteps() auxY = hy * hy; break; } - this->spaceStepsProducts[ i ][ j ] = auxX * auxY; + this->spaceStepsProducts[ i ][ j ] = auxX * auxY; } } } @@ -1067,7 +1065,7 @@ void Meshes::Grid< 2, Real, Device, Index > :: setDomain( const PointType& origi template< typename Real, typename Device, typename Index > -__cuda_callable__ inline +__cuda_callable__ inline const typename Meshes::Grid< 2, Real, Device, Index >::PointType& Meshes::Grid< 2, Real, Device, Index >::getOrigin() const { @@ -1077,7 +1075,7 @@ Meshes::Grid< 2, Real, Device, Index >::getOrigin() const template< typename Real, typename Device, typename Index > -__cuda_callable__ inline +__cuda_callable__ inline const typename Meshes::Grid< 2, Real, Device, Index > :: PointType& Meshes::Grid< 2, Real, Device, Index > :: getProportions() const { @@ -1088,23 +1086,23 @@ template< typename Real, typename Device, typename Index > template< typename EntityType > -__cuda_callable__ inline +__cuda_callable__ inline Index -Meshes::Grid< 2, Real, Device, Index >:: +Meshes::Grid< 2, Real, Device, Index >:: getEntitiesCount() const { static_assert( EntityType::entityDimension <= 2 && EntityType::entityDimension >= 0, "Wrong grid entity dimension." ); - + switch( EntityType::entityDimension ) { case 2: return this->numberOfCells; case 1: - return this->numberOfFaces; + return this->numberOfFaces; case 0: return this->numberOfVertices; - } + } return -1; } @@ -1112,14 +1110,14 @@ template< typename Real, typename Device, typename Index > template< typename EntityType > -__cuda_callable__ inline +__cuda_callable__ inline EntityType Meshes::Grid< 2, Real, Device, Index >:: getEntity( const IndexType& entityIndex ) const { static_assert( EntityType::entityDimension <= 2 && EntityType::entityDimension >= 0, "Wrong grid entity dimension." ); - + return GridEntityGetter< ThisType, EntityType >::getEntity( *this, entityIndex ); } @@ -1127,14 +1125,14 @@ template< typename Real, typename Device, typename Index > template< typename EntityType > -__cuda_callable__ inline +__cuda_callable__ inline Index Meshes::Grid< 2, Real, Device, Index >:: getEntityIndex( const EntityType& entity ) const { static_assert( EntityType::entityDimension <= 2 && EntityType::entityDimension >= 0, "Wrong grid entity dimension." ); - + return GridEntityGetter< ThisType, EntityType >::getEntityIndex( *this, entity ); } @@ -1177,14 +1175,14 @@ template< typename Real, typename Device, typename Index > template< int xPow, int yPow > -__cuda_callable__ inline -const Real& +__cuda_callable__ inline +const Real& Meshes::Grid< 2, Real, Device, Index >:: getSpaceStepsProducts() const { - tnlTNL_ASSERT( xPow >= -2 && xPow <= 2, + tnlTNL_ASSERT( xPow >= -2 && xPow <= 2, std::cerr << " xPow = " << xPow ); - tnlTNL_ASSERT( yPow >= -2 && yPow <= 2, + tnlTNL_ASSERT( yPow >= -2 && yPow <= 2, std::cerr << " yPow = " << yPow ); return this->spaceStepsProducts[ yPow + 2 ][ xPow + 2 ]; @@ -1456,8 +1454,8 @@ bool Meshes::Grid< 2, Real, Device, Index > :: write( const MeshFunction& functi { if( this->template getEntitiesCount< Cell >() != function. getSize() ) { - std::cerr << "The size ( " << function. getSize() - << " ) of a mesh function does not agree with the DOFs ( " + std::cerr << "The size ( " << function. getSize() + << " ) of a mesh function does not agree with the DOFs ( " << this->template getEntitiesCount< Cell >() << " ) of a mesh." << std::endl; return false; } @@ -1503,7 +1501,3 @@ writeProlog( tnlLogger& logger ) logger.writeParameter( "Space steps:", this->getSpaceSteps() ); } #endif - - - - diff --git a/src/Benchmarks/HeatEquationGrid/Base/HeatmapSolver.h b/src/Benchmarks/HeatEquationGrid/Base/HeatmapSolver.h new file mode 100644 index 0000000000000000000000000000000000000000..d65ffd3363b0d2efb6e512efd98aac6e75268100 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/Base/HeatmapSolver.h @@ -0,0 +1,123 @@ + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +template +class HeatmapSolver +{ +public: + class Parameters + { + public: + const int xSize, ySize; + const Real xDomainSize, yDomainSize; + const Real alpha, beta, gamma; + const Real timeStep, finalTime; + const bool outputData; + const bool verbose; + + Parameters(const TNL::Config::ParameterContainer ¶meters); + Parameters(const int xSize, const int ySize, + const Real xDomainSize, const Real yDomainSize, + const Real alpha, const Real beta, const Real gamma, + const Real timeStep, const Real finalTime, + const bool outputData, + const bool verbose): + xSize(xSize), ySize(ySize), + xDomainSize(xDomainSize), yDomainSize(yDomainSize), + alpha(alpha), beta(beta), gamma(gamma), + timeStep(timeStep), finalTime(finalTime), + outputData(outputData), verbose(verbose) {} + + static TNL::Config::ConfigDescription makeInputConfig(); + }; + + template + bool solve(const Parameters ¶meters) const; +private: + template + bool writeGNUPlot(const std::string &filename, + const Parameters ¶meters, + const TNL::Containers::Array &map) const; +}; + +template +TNL::Config::ConfigDescription HeatmapSolver::Parameters::makeInputConfig() +{ + TNL::Config::ConfigDescription config; + + config.addEntry("device", "Device the computation will run on.", "cuda"); + config.addEntryEnum("host"); + +#ifdef HAVE_CUDA + config.addEntryEnum("cuda"); +#endif + config.addEntry("grid-x-size", "Grid size along x-axis.", 200); + config.addEntry("grid-y-size", "Grid size along y-axis.", 200); + + config.addEntry("domain-x-size", "Domain size along x-axis.", 4.0); + config.addEntry("domain-y-size", "Domain size along y-axis.", 4.0); + + config.addDelimiter( "Initial condition settings ( (x^2/alpha + y^2/beta) + gamma)):" ); + config.addEntry< double >( "alpha", "Alpha value in initial condition", -0.05 ); + config.addEntry< double >( "beta", "Beta value in initial condition", -0.05 ); + config.addEntry< double >( "gamma", "Gamma key in initial condition", 15 ); + + config.addEntry("time-step", "Time step. By default it is proportional to one over space step square.", 0.000005); + config.addEntry("final-time", "Final time of the simulation.", 0.36); + config.addEntry("verbose", "Verbose mode.", true); + + return config; +} + +template +HeatmapSolver::Parameters::Parameters(const TNL::Config::ParameterContainer ¶meters) : xSize(parameters.getParameter("grid-x-size")), + ySize(parameters.getParameter("grid-y-size")), + xDomainSize(parameters.getParameter("domain-x-size")), + yDomainSize(parameters.getParameter("domain-y-size")), + alpha(parameters.getParameter("alpha")), + beta(parameters.getParameter("beta")), + gamma(parameters.getParameter("gamma")), + timeStep(parameters.getParameter("time-step")), + finalTime(parameters.getParameter("final-time")), + outputData(parameters.getParameter("outputData")), + verbose(parameters.getParameter("verbose")) {} + +template +template +bool HeatmapSolver::writeGNUPlot(const std::string &filename, + const HeatmapSolver::Parameters ¶ms, + const TNL::Containers::Array &map) const { + if (std::is_same::value) { + TNL::Containers::Array host(map); + + return writeGNUPlot(filename, params, host); + } + + if (!params.outputData) + return true; + + std::ofstream out(filename, std::ios::out); + + if (!out.is_open()) + return false; + + const Real hx = params.xDomainSize / (Real)params.xSize; + const Real hy = params.yDomainSize / (Real)params.ySize; + + for (int j = 0; j < params.ySize; j++) + for (int i = 0; i < params.xSize; i++) + out << i * hx - params.xDomainSize / 2. << " " + << j * hy - params.yDomainSize / 2. << " " + << map.getElement( j * params.xSize + i ) << std::endl; + + return out.good(); +} diff --git a/src/Benchmarks/HeatEquationGrid/Base/HeatmapSolverBenchmark.h b/src/Benchmarks/HeatEquationGrid/Base/HeatmapSolverBenchmark.h new file mode 100644 index 0000000000000000000000000000000000000000..c47944ef3399cce87d6407b278130690f47aec10 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/Base/HeatmapSolverBenchmark.h @@ -0,0 +1,210 @@ + +#include + +#include +#include + +#include + +#include "HeatmapSolver.h" + +#pragma once + +class HeatmapSolverBenchmark { + public: + template + void exec(const typename HeatmapSolver::Parameters& params) const; + + template + void runBenchmark(TNL::Benchmarks::Benchmark<> & benchmark, + const std::size_t minXDimension, + const std::size_t maxXDimension, + const std::size_t xStepSizeFactor, + const std::size_t minYDimension, + const std::size_t maxYDimension, + const std::size_t yStepSizeFactor, + const TNL::Config::ParameterContainer& parameters) const; + + static TNL::Config::ConfigDescription makeInputConfig(); +}; + +TNL::Config::ConfigDescription HeatmapSolverBenchmark::makeInputConfig() { + TNL::Config::ConfigDescription config; + + config.addDelimiter("Benchmark settings:"); + config.addEntry("id", "Identifier of the run", "unknown"); + config.addEntry("log-file", "Log file name.", "tnl-benchmark-heatmap.log"); + config.addEntry("output-mode", "Mode for opening the log file.", "overwrite"); + config.addEntryEnum("append"); + config.addEntryEnum("overwrite"); + + config.addEntry("device", "Device the computation will run on.", "cuda"); + config.addEntryEnum("all"); + config.addEntryEnum("host"); + +#ifdef HAVE_CUDA + config.addEntryEnum("cuda"); +#endif + + config.addEntry("precision", "Precision of the arithmetics.", "double"); + config.addEntryEnum("float"); + config.addEntryEnum("double"); + config.addEntryEnum("all"); + + config.addEntry("min-x-dimension", "Minimum dimension over x axis used in the benchmark.", 100); + config.addEntry("max-x-dimension", "Maximum dimension over x axis used in the benchmark.", 200); + config.addEntry("x-size-step-factor", "Factor determining the dimension grows over x axis. First size is min-x-dimension and each following size is stepFactor*previousSize, up to max-x-dimension.", 2); + + config.addEntry("min-y-dimension", "Minimum dimension over x axis used in the benchmark.", 100); + config.addEntry("max-y-dimension", "Maximum dimension over x axis used in the benchmark.", 200); + config.addEntry("y-size-step-factor", "Factor determining the dimension grows over y axis. First size is min-y-dimension and each following size is stepFactor*previousSize, up to max-y-dimension.", 2); + + config.addEntry("loops", "Number of iterations for every computation.", 10); + + config.addEntry("verbose", "Verbose mode.", 1); + + config.addDelimiter("Problem settings:"); + config.addEntry("domain-x-size", "Domain size along x-axis.", 2.0); + config.addEntry("domain-y-size", "Domain size along y-axis.", 2.0); + + config.addDelimiter( "Initial condition settings ( (x^2/alpha + y^2/beta) + gamma)):" ); + config.addEntry< double >( "alpha", "Alpha value in initial condition", -0.05 ); + config.addEntry< double >( "beta", "Beta value in initial condition", -0.05 ); + config.addEntry< double >( "gamma", "Gamma key in initial condition", 15 ); + + config.addEntry("sigma", "Sigma in exponential initial condition.", 1.0); + + config.addEntry("time-step", "Time step. By default it is proportional to one over space step square.", 0.000001); + config.addEntry("final-time", "Final time of the simulation.", 0.01); + + config.addDelimiter("Device settings:"); + TNL::Devices::Host::configSetup( config ); + TNL::Devices::Cuda::configSetup( config ); + + return config; +} + +template +void HeatmapSolverBenchmark::exec(const typename HeatmapSolver::Parameters& params) const { + HeatmapSolver solver; + + auto result = solver.template solve(params); + + if (!result) + printf("Fail to solve for grid size (%d,%d)", params.xSize, params.ySize); +} + +template +void HeatmapSolverBenchmark::runBenchmark(TNL::Benchmarks::Benchmark<>& benchmark, + const std::size_t minXDimension, + const std::size_t maxXDimension, + const std::size_t xStepSizeFactor, + const std::size_t minYDimension, + const std::size_t maxYDimension, + const std::size_t yStepSizeFactor, + const TNL::Config::ParameterContainer& parameters) const { + Real xDomainSize = parameters.getParameter("domain-x-size"); + Real yDomainSize = parameters.getParameter("domain-y-size"); + Real alpha = parameters.getParameter("alpha"); + Real beta = parameters.getParameter("beta"); + Real gamma = parameters.getParameter("gamma"); + Real timeStep = parameters.getParameter("time-step"); + Real finalTime = parameters.getParameter("final-time"); + + auto precision = TNL::getType(), device = TNL::getType(); + + std::cout << "Heatmap grid with (" + precision + ", host allocator " + device + ")" << std::endl; + + for(std::size_t xSize = minXDimension; xSize <= maxXDimension; xSize *= xStepSizeFactor) { + for(std::size_t ySize = minXDimension; ySize <= maxXDimension; ySize *= yStepSizeFactor) { + benchmark.setMetadataColumns( TNL::Benchmarks::Benchmark<>::MetadataColumns({ + { "precision", precision }, + { "xSize", TNL::convertToString(xSize) }, + { "ySize", TNL::convertToString(ySize) }, + { "id", parameters.getParameter("id") } + })); + + benchmark.setDatasetSize(xSize * ySize); + + auto lambda = [=]() { + typename HeatmapSolver::Parameters params(xSize, ySize, xDomainSize, yDomainSize, alpha, beta, gamma, timeStep, finalTime, false, false); + + exec(params); + }; + + benchmark.time(device, lambda); + } + } +} + +int main(int argc, char* argv[]) { + HeatmapSolverBenchmark solver; + + auto config = HeatmapSolverBenchmark::makeInputConfig(); + + TNL::Config::ParameterContainer parameters; + + if (!parseCommandLine(argc, argv, config, parameters)) + return EXIT_FAILURE; + + if (!TNL::Devices::Host::setup( parameters ) || !TNL::Devices::Cuda::setup( parameters ) ) + return EXIT_FAILURE; + + const TNL::String logFileName = parameters.getParameter( "log-file" ); + const TNL::String outputMode = parameters.getParameter( "output-mode" ); + const TNL::String precision = parameters.getParameter( "precision" ); + + const std::size_t minXDimension = parameters.getParameter("min-x-dimension"); + const std::size_t maxXDimension = parameters.getParameter("max-x-dimension"); + const std::size_t xSizeStepFactor = parameters.getParameter("x-size-step-factor"); + + if(xSizeStepFactor <= 1) { + std::cerr << "The value of --x-size-step-factor must be greater than 1." << std::endl; + return EXIT_FAILURE; + } + + const std::size_t minYDimension = parameters.getParameter("min-y-dimension"); + const std::size_t maxYDimension = parameters.getParameter("max-y-dimension"); + const std::size_t ySizeStepFactor = parameters.getParameter("y-size-step-factor"); + + const int loops = parameters.getParameter< int >("loops"); + const int verbose = parameters.getParameter< int >("verbose"); + + if(ySizeStepFactor <= 1) { + std::cerr << "The value of --y-size-step-factor must be greater than 1." << std::endl; + return EXIT_FAILURE; + } + + auto mode = std::ios::out; + + if( outputMode == "append" ) + mode |= std::ios::app; + + std::ofstream logFile( logFileName.getString(), mode ); + + TNL::Benchmarks::Benchmark<> benchmark(logFile, loops, verbose); + + // write global metadata into a separate file + std::map< std::string, std::string > metadata = TNL::Benchmarks::getHardwareMetadata(); + TNL::Benchmarks::writeMapAsJson( metadata, logFileName, ".metadata.json" ); + + auto device = parameters.getParameter("device"); + + if (device == "host" || device == "all") { + if(precision == "all" || precision == "float") + solver.runBenchmark(benchmark, minXDimension, maxXDimension, xSizeStepFactor, minYDimension, maxYDimension, ySizeStepFactor, parameters); + if(precision == "all" || precision == "double") + solver.runBenchmark(benchmark, minXDimension, maxXDimension, xSizeStepFactor, minYDimension, maxYDimension, ySizeStepFactor, parameters); + } + +#ifdef HAVE_CUDA + if (device == "cuda" || device == "all") { + if( precision == "all" || precision == "float" ) + solver.runBenchmark(benchmark, minXDimension, maxXDimension, xSizeStepFactor, minYDimension, maxYDimension, ySizeStepFactor, parameters); + if( precision == "all" || precision == "double" ) + solver.runBenchmark(benchmark, minXDimension, maxXDimension, xSizeStepFactor, minYDimension, maxYDimension, ySizeStepFactor, parameters); + } +#endif + + return EXIT_SUCCESS; +} diff --git a/src/Benchmarks/HeatEquationGrid/CMakeLists.txt b/src/Benchmarks/HeatEquationGrid/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..aadec614b021ec6d247f9988d5ba90a728837770 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/CMakeLists.txt @@ -0,0 +1,4 @@ +ADD_SUBDIRECTORY( HeatmapParallelFor ) +ADD_SUBDIRECTORY( HeatmapNDimGrid ) +ADD_SUBDIRECTORY( HeatmapTNLGrid ) +ADD_SUBDIRECTORY( HeatmapTNLGridWithMemoryLoad ) diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/CMakeLists.txt b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..58c97ef0d44b742043c4005d632847dd547c15ee --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/CMakeLists.txt @@ -0,0 +1,2 @@ +ADD_SUBDIRECTORY( benchmark ) +ADD_SUBDIRECTORY( solution ) diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/benchmark/CMakeLists.txt b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/benchmark/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..b52b3909d50511a2b5fac608b4ca1272dd3a9a32 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/benchmark/CMakeLists.txt @@ -0,0 +1,5 @@ +if (BUILD_CUDA) + CUDA_ADD_EXECUTABLE( heat_n_dim_grid_benchmark ../implementation.h ../../Base/HeatmapSolver.h ../../Base/HeatmapSolverBenchmark.h main.h main.cu ) +ELSE() + add_executable( heat_n_dim_grid_benchmark ../implementation.h ../../Base/HeatmapSolver.h ../../Base/HeatmapSolverBenchmark.h main.h main.cpp ) +ENDIF() diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/benchmark/main.cpp b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/benchmark/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a7a28956b887a99bcb3c646b18d0bef52c9d320 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/benchmark/main.cpp @@ -0,0 +1,2 @@ + +#include "main.h" diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/benchmark/main.cu b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/benchmark/main.cu new file mode 100644 index 0000000000000000000000000000000000000000..7a7a28956b887a99bcb3c646b18d0bef52c9d320 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/benchmark/main.cu @@ -0,0 +1,2 @@ + +#include "main.h" diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/benchmark/main.h b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/benchmark/main.h new file mode 100644 index 0000000000000000000000000000000000000000..24eb97da82bf5bbd553d20b9965f22e9ec74d75c --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/benchmark/main.h @@ -0,0 +1,6 @@ + +#include "../../Base/HeatmapSolver.h" +#include "../../Base/HeatmapSolverBenchmark.h" +#include "../implementation.h" + +#pragma once diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/implementation.h b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/implementation.h new file mode 100644 index 0000000000000000000000000000000000000000..6c9864b998935f51d1c3a61ddf6f3ba0a31604d7 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/implementation.h @@ -0,0 +1,428 @@ + +#include +#include +#include +#include +#include +#include + +#include "../Base/HeatmapSolver.h" + +#include +#include +#include +#include +#include + +#pragma once + +template struct bool_pack {}; + +template +using conjunction = std::is_same, bool_pack>; + +template 0)>, + typename = std::enable_if_t::value>> +using Container = TNL::Containers::StaticArray; + +template 0)>, + typename = std::enable_if_t::value>> +class GridEntity { + public: + __cuda_callable__ + inline explicit GridEntity(const Index& vertexIndex, + const Container& coordinates, + const Container& direction) : + vertexIndex(vertexIndex), + coordinates(coordinates), + direction(direction) {}; + + __cuda_callable__ + ~GridEntity() {}; + + __cuda_callable__ + inline Container getCoordinates() const noexcept { + return coordinates; + } + + __cuda_callable__ + inline Index getIndex() const noexcept { + return vertexIndex; + } + private: + const Index vertexIndex; + const Container coordinates; + const Container direction; +}; + +template 0)>> +class Grid { + public: + Grid() {} + ~Grid() {} + + /** + * @brief - Specifies dimensions of the grid + * @param[in] dimensions - A parameter pack, which specifies points count in the specific dimension. + * Most significant dimension is in the beginning of the list. + * Least significant dimension is in the end of the list + */ + template ::value...>::value>, + typename = std::enable_if_t> + void setDimensions(Dimensions... dimensions) noexcept { + Index i = 0; + + for (auto x: { dimensions... }) { + TNL_ASSERT_GT(x, 0, "Dimension must be positive"); + this -> dimensions[i] = x; + i++; + } + + refreshDimensionMaps(); + } + /** + * @param[in] index - index of dimension + */ + inline __cuda_callable__ Index getDimension(Index index) const noexcept { + TNL_ASSERT_GE(index, 0, "Index must be greater than zero"); + TNL_ASSERT_LT(index, Dimension, "Index must be less than Dimension"); + + return dimensions[index]; + } + /** + * @param[in] indices - A dimension index pack + */ + template ::value...>::value>, + typename = std::enable_if_t<(sizeof...(DimensionIndex) > 0)>> + Container getDimensions(DimensionIndex... indices) const noexcept { + Container result{indices...}; + + for (std::size_t i = 0; i < sizeof...(DimensionIndex); i++) + result[i] = this -> getDimension(result[i]); + + return result; + } + /** + * @param[in] index - index of dimension + */ + inline __cuda_callable__ Index getEntitiesCount(Index index) const noexcept { + TNL_ASSERT_GE(index, 0, "Index must be greater than zero"); + TNL_ASSERT_LE(index, Dimension, "Index must be less than or equal to Dimension"); + + return cumulativeDimensionMap(index); + } + /** + * @brief - Returns the number of entities of specific dimension + */ + template ::value...>::value>, + typename = std::enable_if_t<(sizeof...(DimensionIndex) > 0)>> + Container getEntitiesCounts(DimensionIndex... indices) const noexcept { + Container result{indices...}; + + for (std::size_t i = 0; i < sizeof...(DimensionIndex); i++) + result[i] = this -> getEntitiesCount(result[i]); + + return result; + } + /** + * @param[in] index - index of dimension + */ + inline __cuda_callable__ Index getEndIndex(Index index) const noexcept { + TNL_ASSERT_GE(index, 0, "Index must be greater than zero"); + TNL_ASSERT_LT(index, Dimension, "Index must be less than or equal to Dimension"); + + return this -> getDimension(index) - 1; + } + /** + * @brief - Returns the last index of specific dimensions + */ + template ::value...>::value>, + typename = std::enable_if_t<(sizeof...(DimensionIndex) > 0)>> + Container getEndIndices(DimensionIndex... indices) const noexcept { + Container result{ indices... }; + + for (std::size_t i = 0; i < sizeof...(DimensionIndex); i++) + result[i] = this->getEndIndex(result[i]); + + return result; + } + /** + * @brief - Traversers all elements in the grid + */ + template + void traverseAll(Function function, FunctionArgs... args) const noexcept { + auto lambda = [=] __cuda_callable__(const Index index, FunctionArgs... args) mutable { + function(index, args...); + }; + + TNL::Algorithms::ParallelFor::exec(0, cumulativeDimensionMap[0], lambda, args...); + } + /** + * @brief - Traverses a grid from start index to end index. + * + * @param[in] start - a start index of point + * @param[in] end - an end index of point + * @param[in] directions - A pack of boolean vector flags with the size of the dimension. + * For example, let's have the 3-dimensional grid. + * A pack {false, false, false} will call function for all points + * A pack {true, false, false} will call function for edges directed over dimension at index of true + * A pack {true, true, false} will call function for faces directed over dimension at index of true + * A pack {true, true, true} will call function for cells directed over + * + */ + template + void traverse(const Container& firstVertex, + const Container& secondVertex, + const TNL::Containers::Array, Device>& directions, + Function function, + FunctionArgs... args) const noexcept { + Index verticesCount = 1; + Container traverseRectOrigin, traverseRectDimensions, + dimensionsProducts, traverseRectDimensionsProducts; + + for (Index i = 0; i < Dimension; i++) { + traverseRectDimensions[i] = abs(secondVertex[i] - firstVertex[i]) + 1; + verticesCount *= traverseRectDimensions[i]; + traverseRectOrigin[i] = std::min(firstVertex[i], secondVertex[i]); + + TNL_ASSERT_LT(firstVertex[i], dimensions[i], "End index must be in dimensions range"); + TNL_ASSERT_LT(secondVertex[i], dimensions[i], "Start index must be in dimensions range"); + } + + dimensionsProducts = getDimensionProducts(dimensions); + traverseRectDimensionsProducts = getDimensionProducts(traverseRectDimensions); + + auto outerFunction = [=] __cuda_callable__(Index offset, + const Container& traverseRectOrigin, + const Container& traverseRectDimensions, + const Container& traverseRectDimensionsProducts, + const Container& dimensionsProducts, + FunctionArgs... args) mutable { + auto entity = this -> makeEntitity(offset, + traverseRectOrigin, traverseRectDimensions, + traverseRectDimensionsProducts, dimensionsProducts); + + function(entity, args...); + }; + + Index lowerBound = 0, upperBound = verticesCount; + + for (Index i = 0; i < directions.getSize(); i++) { + TNL::Algorithms::ParallelFor::exec(lowerBound, upperBound, outerFunction, + traverseRectOrigin, + traverseRectDimensions, + traverseRectDimensionsProducts, + dimensionsProducts, + args...); + } + } + private: + Container dimensions; + /** + * @brief - A dimension map is a store for dimension limits over all combinations of basis. + * First, (n choose 0) elements will contain the count of 0 dimension elements + * Second, (n choose 1) elements will contain the count of 1-dimension elements + * .... + * + * For example, let's have a 3-d grid, then the map indexing will be the next: + * 0 - 0 - count of vertices + * 1, 2, 3 - count of edges in x, y, z plane + * 4, 5, 6 - count of faces in xy, yz, zy plane + * 7 - count of cells in z y x plane + * + * @warning - The ordering of is lexigraphical. + */ + Container<1 << Dimension, Index> dimensionMap; + /** + * @brief - A cumulative map over dimensions. + */ + Container cumulativeDimensionMap; + /** + * @brief - Fills dimensions map for N-dimensional Grid. + * + * @complexity - O(2 ^ Dimension) + */ + void refreshDimensionMaps() noexcept { + std::array combinationBuffer = {}; + std::size_t j = 0; + + for (std::size_t i = 0; i < Dimension + 1; i++) + cumulativeDimensionMap[i] = 0; + + for (std::size_t i = 0; i <= Dimension; i++) { + std::fill(combinationBuffer.begin(), combinationBuffer.end(), false); + std::fill(combinationBuffer.end() - i, combinationBuffer.end(), true); + + do { + int result = 1; + + for (std::size_t k = 0; k < combinationBuffer.size(); k++) + result *= combinationBuffer[k] ? dimensions[Dimension - k - 1] - 1 : dimensions[Dimension - k - 1]; + + dimensionMap[j] = result; + cumulativeDimensionMap[i] += result; + + j++; + } while (std::next_permutation(combinationBuffer.begin(), combinationBuffer.end())); + } + } + + __cuda_callable__ inline + GridEntity makeEntitity(const Index& index, + const Container& traverseRectOrigin, + const Container& traverseRectDimensions, + const Container& traverseRectDimensionsProducts, + const Container& dimensionsProducts) const { + //Container traverseCoordinates = 0; + Container traverseCoordinates = getCoordinates(index, traverseRectDimensions); + Container globalCoordinates = 0; + + for (Index i = 0; i < Dimension; i++) + globalCoordinates[i] = traverseRectOrigin[i] + traverseCoordinates[i]; + + const auto globalIndex = getIndex(globalCoordinates, dimensionsProducts); + + return GridEntity(globalIndex, globalCoordinates, {}); + } + /** + * Calculates position in the specific boundaries + */ + __cuda_callable__ inline + Container getCoordinates(const Index& index, + const Container &dimensions) const { + Container coordinates = 0; + Index tmpIndex = index; + + Index dimensionIndex = 0; + + while (tmpIndex && dimensionIndex < Dimension) { + Index dimension = dimensions[dimensionIndex], + quotient = tmpIndex / dimension, + reminder = tmpIndex - (dimension * quotient); + + coordinates[dimensionIndex] = reminder; + tmpIndex = quotient; + + dimensionIndex += 1; + } + + return coordinates; + } + /** + * Calculates product matrix based on the dimension + */ + __cuda_callable__ inline + Container getDimensionProducts(const Container& dimensions) const noexcept { + Container products = 0; + + products[0] = 1; + + for (Index i = 1; i < Dimension; i++) + products[i] = dimensions[i - 1] * products[i - 1]; + + return products; + } + /** + * Calculates index based on the dimension + */ + __cuda_callable__ inline + Index getIndex(const Container& coordinates, + const Container& dimensionProducts) const { + Index index = 0; + + for (Index i = 0; i < Dimension; i++) + index += coordinates[i] * dimensionProducts[i]; + + return index; + } + +}; + +template +template +bool HeatmapSolver::solve(const HeatmapSolver::Parameters ¶ms) const { + Grid<2, int, Device> grid; + + grid.setDimensions(params.xSize, params.ySize); + + const Real hx = params.xDomainSize / (Real)grid.getDimension(0); + const Real hy = params.yDomainSize / (Real)grid.getDimension(1); + const Real hx_inv = 1. / (hx * hx); + const Real hy_inv = 1. / (hy * hy); + + auto entitiesCount = grid.getEntitiesCount(0); + auto timestep = params.timeStep ? params.timeStep : std::min(hx * hx, hy * hy); + auto xDomainSize = params.xDomainSize; + auto yDomainSize = params.yDomainSize; + + auto alpha = params.alpha; + auto beta = params.beta; + auto gamma = params.gamma; + + TNL::Containers::Array ux(entitiesCount), // data at step u + aux(entitiesCount);// data at step u + 1 + + auto uxView = ux.getView(), auxView = aux.getView(); + + // Invalidate ux/aux + ux = 0; + aux = 0; + + auto init = [=] __cuda_callable__(const GridEntity<2, int>& entity) mutable { + auto position = entity.getCoordinates(); + auto index = entity.getIndex(); + + auto x = position[0] * hx - xDomainSize / 2; + auto y = position[1] * hx - yDomainSize / 2; + + uxView[index] = TNL::max((x * x / alpha) + (y * y / beta) + gamma, 0); + }; + + const Container<2, bool> direction{ false, false }; + + grid.traverse({ 1, 1 }, + { grid.getEndIndex(0) - 1, grid.getEndIndex(1) - 1 }, + { direction }, + init); + + if (!writeGNUPlot("data.txt", params, ux)) + return false; + + auto xDimension = grid.getDimension(0); + + auto next = [=] __cuda_callable__(const GridEntity<2, int>& entity) mutable { + auto index = entity.getIndex(); + auto element = uxView[index]; + auto center = 2 * element; + + auxView[index] = element + ((uxView[index - 1] - center + uxView[index + 1]) * hx_inv + + (uxView[index - xDimension] - center + uxView[index + xDimension]) * hy_inv) * timestep; + }; + + Real start = 0; + + while (start < params.finalTime) { + grid.traverse({ 1, 1 }, + { grid.getEndIndex(0) - 1, grid.getEndIndex(1) - 1 }, + { direction }, + next); + + uxView = aux.getView(); + auxView = ux.getView(); + + start += timestep; + } + + return writeGNUPlot("data_final.txt", params, ux); +}; diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/solution/CMakeLists.txt b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/solution/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5ab54f05ab86c43f566476f46f68038c4f6a1d8a --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/solution/CMakeLists.txt @@ -0,0 +1,5 @@ +if (BUILD_CUDA) + CUDA_ADD_EXECUTABLE( heat_n_dim_grid ../implementation.h ../../Base/HeatmapSolver.h main.h main.cu ) +ELSE() + add_executable( heat_n_dim_grid ../implementation.h ../../Base/HeatmapSolver.h main.h main.cpp ) +ENDIF() diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/solution/main.cpp b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/solution/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a7a28956b887a99bcb3c646b18d0bef52c9d320 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/solution/main.cpp @@ -0,0 +1,2 @@ + +#include "main.h" diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/solution/main.cu b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/solution/main.cu new file mode 100644 index 0000000000000000000000000000000000000000..7a7a28956b887a99bcb3c646b18d0bef52c9d320 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/solution/main.cu @@ -0,0 +1,2 @@ + +#include "main.h" diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/solution/main.h b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/solution/main.h new file mode 100644 index 0000000000000000000000000000000000000000..54d0c86f0d3b1c093152aee294e6d8396e9344cf --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapNDimGrid/solution/main.h @@ -0,0 +1,38 @@ + +#include +#include +#include +#include +#include +#include + +#include "../../Base/HeatmapSolver.h" +#include "../implementation.h" + +int main(int argc, char* argv[]) { + using Real = double; + + auto config = HeatmapSolver::Parameters::makeInputConfig(); + + TNL::Config::ParameterContainer parameters; + if (!parseCommandLine(argc, argv, config, parameters)) + return EXIT_FAILURE; + + auto device = parameters.getParameter("device"); + + parameters.addParameter("outputData", true); + + auto params = HeatmapSolver::Parameters(parameters); + + HeatmapSolver solver; + + if (device == "host" && !solver.solve(params)) + return EXIT_FAILURE; + +#ifdef HAVE_CUDA + if (device == "cuda" && !solver.solve(params)) + return EXIT_FAILURE; +#endif + + return EXIT_SUCCESS; +} diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/CMakeLists.txt b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..58c97ef0d44b742043c4005d632847dd547c15ee --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/CMakeLists.txt @@ -0,0 +1,2 @@ +ADD_SUBDIRECTORY( benchmark ) +ADD_SUBDIRECTORY( solution ) diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/benchmark/CMakeLists.txt b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/benchmark/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..364b4a99f0d172d0c59e335df8653a86986a5323 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/benchmark/CMakeLists.txt @@ -0,0 +1,5 @@ +if (BUILD_CUDA) + CUDA_ADD_EXECUTABLE( heat_parallel_for_grid_benchmark ../implementation.h ../../Base/HeatmapSolver.h ../../Base/HeatmapSolverBenchmark.h main.h main.cu ) +ELSE() + add_executable( heat_parallel_for_grid_benchmark ../implementation.h ../../Base/HeatmapSolver.h ../../Base/HeatmapSolverBenchmark.h main.h main.cpp ) +ENDIF() diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/benchmark/main.cpp b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/benchmark/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a7a28956b887a99bcb3c646b18d0bef52c9d320 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/benchmark/main.cpp @@ -0,0 +1,2 @@ + +#include "main.h" diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/benchmark/main.cu b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/benchmark/main.cu new file mode 100644 index 0000000000000000000000000000000000000000..7a7a28956b887a99bcb3c646b18d0bef52c9d320 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/benchmark/main.cu @@ -0,0 +1,2 @@ + +#include "main.h" diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/benchmark/main.h b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/benchmark/main.h new file mode 100644 index 0000000000000000000000000000000000000000..64defc7d172ae4f2864ec73d4716dbe863b0db54 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/benchmark/main.h @@ -0,0 +1,5 @@ +#include "../../Base/HeatmapSolver.h" +#include "../../Base/HeatmapSolverBenchmark.h" +#include "../implementation.h" + +#pragma once diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/implementation.h b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/implementation.h new file mode 100644 index 0000000000000000000000000000000000000000..854357352adebe831e58ac7a8cddcf61088bc6ce --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/implementation.h @@ -0,0 +1,97 @@ + +#include +#include + +#include + +#include "../Base/HeatmapSolver.h" + +#pragma once + +/*** + * Grid parameters: + * + * ySize-1|j (ySize - 1) * xSize + xSize - 1 + * |------------------------------------------------------ + * | + * | + * | + * | + * | + * | + * | + * | + * | + * |------------------------------------------------------> + * + * 0 xSize-1|i + * + * j * xSize + i + ***/ +template +template +bool HeatmapSolver::solve(const HeatmapSolver::Parameters ¶ms) const +{ + TNL::Containers::Array ux(params.xSize * params.ySize); // data at step u + TNL::Containers::Array aux(params.xSize * params.ySize);// data at step u + 1 + + // Invalidate ux/aux + ux = 0; + aux = 0; + + const Real hx = params.xDomainSize / (Real)params.xSize; + const Real hy = params.yDomainSize / (Real)params.ySize; + const Real hx_inv = 1. / (hx * hx); + const Real hy_inv = 1. / (hy * hy); + + auto timestep = params.timeStep ? params.timeStep : std::min(hx * hx, hy * hy); + + auto uxView = ux.getView(), auxView = aux.getView(); + + auto xSize = params.xSize; + auto xDomainSize = params.xDomainSize; + auto yDomainSize = params.yDomainSize; + + auto alpha = params.alpha; + auto beta = params.beta; + auto gamma = params.gamma; + + auto init = [=] __cuda_callable__(int i, int j) mutable + { + auto index = j * xSize + i; + + auto x = i * hx - xDomainSize / 2.; + auto y = j * hy - yDomainSize / 2.; + + uxView[index] = TNL::max((x * x / alpha) + (y * y / beta) + gamma, 0); + }; + + TNL::Algorithms::ParallelFor2D::exec(1, 1, params.xSize - 1, params.ySize - 1, init); + + if (!writeGNUPlot("data.txt", params, ux)) + return false; + + auto next = [=] __cuda_callable__(int i, int j) mutable + { + auto index = j * xSize + i; + auto element = uxView[index]; + auto center = 2 * element; + + auxView[index] = element + ((uxView[index - 1] - center + uxView[index + 1]) * hx_inv + + (uxView[index - xSize] - center + uxView[index + xSize]) * hy_inv) * timestep; + }; + + Real start = 0; + + while (start < params.finalTime) + { + TNL::Algorithms::ParallelFor2D::exec(1, 1, params.xSize - 1, params.ySize - 1, next); + + uxView = aux.getView(); + auxView = ux.getView(); + + start += timestep; + } + + return writeGNUPlot("data_final.txt", params, ux); +} diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/solution/CMakeLists.txt b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/solution/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..8cc2bdf69d424e9e992a47889c52cc522bcc3930 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/solution/CMakeLists.txt @@ -0,0 +1,5 @@ +if (BUILD_CUDA) + CUDA_ADD_EXECUTABLE( heat_parallel_for_grid ../implementation.h ../../Base/HeatmapSolver.h main.h main.cu ) +ELSE() + add_executable( heat_parallel_for_grid ../implementation.h ../../Base/HeatmapSolver.h main.h main.cpp ) +ENDIF() diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/solution/main.cpp b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/solution/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a7a28956b887a99bcb3c646b18d0bef52c9d320 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/solution/main.cpp @@ -0,0 +1,2 @@ + +#include "main.h" diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/solution/main.cu b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/solution/main.cu new file mode 100644 index 0000000000000000000000000000000000000000..7a7a28956b887a99bcb3c646b18d0bef52c9d320 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/solution/main.cu @@ -0,0 +1,2 @@ + +#include "main.h" diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/solution/main.h b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/solution/main.h new file mode 100644 index 0000000000000000000000000000000000000000..31c5ded3a8d6f14e47dc63b53c7a3e1380a87400 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapParallelFor/solution/main.h @@ -0,0 +1,37 @@ + +#include +#include +#include +#include +#include +#include + +#include "../../Base/HeatmapSolver.h" +#include "../implementation.h" + +int main(int argc, char *argv[]) { + using Real = double; + + auto config = HeatmapSolver::Parameters::makeInputConfig(); + + TNL::Config::ParameterContainer parameters; + if (!parseCommandLine(argc, argv, config, parameters)) + return EXIT_FAILURE; + + parameters.addParameter("outputData", true); + + auto device = parameters.getParameter("device"); + auto params = HeatmapSolver::Parameters(parameters); + + HeatmapSolver solver; + + if (device == "host" && !solver.template solve(params)) + return EXIT_FAILURE; + +#ifdef HAVE_CUDA + if (device == "cuda" && !solver.template solve(params)) + return EXIT_FAILURE; +#endif + + return EXIT_SUCCESS; +} diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/CMakeLists.txt b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..58c97ef0d44b742043c4005d632847dd547c15ee --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/CMakeLists.txt @@ -0,0 +1,2 @@ +ADD_SUBDIRECTORY( benchmark ) +ADD_SUBDIRECTORY( solution ) diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/benchmark/CMakeLists.txt b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/benchmark/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f8f5f4e5f14a0c5b15dab357f1324390b6fd2017 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/benchmark/CMakeLists.txt @@ -0,0 +1,5 @@ +if (BUILD_CUDA) + CUDA_ADD_EXECUTABLE( heat_tnl_grid_benchmark ../implementation.h ../../Base/HeatmapSolver.h ../../Base/HeatmapSolverBenchmark.h main.h main.cu ) +ELSE() + add_executable( heat_tnl_grid_benchmark ../implementation.h ../../Base/HeatmapSolver.h ../../Base/HeatmapSolverBenchmark.h main.h main.cpp ) +ENDIF() diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/benchmark/main.cpp b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/benchmark/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a7a28956b887a99bcb3c646b18d0bef52c9d320 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/benchmark/main.cpp @@ -0,0 +1,2 @@ + +#include "main.h" diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/benchmark/main.cu b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/benchmark/main.cu new file mode 100644 index 0000000000000000000000000000000000000000..7a7a28956b887a99bcb3c646b18d0bef52c9d320 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/benchmark/main.cu @@ -0,0 +1,2 @@ + +#include "main.h" diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/benchmark/main.h b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/benchmark/main.h new file mode 100644 index 0000000000000000000000000000000000000000..64defc7d172ae4f2864ec73d4716dbe863b0db54 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/benchmark/main.h @@ -0,0 +1,5 @@ +#include "../../Base/HeatmapSolver.h" +#include "../../Base/HeatmapSolverBenchmark.h" +#include "../implementation.h" + +#pragma once diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/implementation.h b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/implementation.h new file mode 100644 index 0000000000000000000000000000000000000000..c0b9b93bb4be4f56f73021a7666c3b2336631cd2 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/implementation.h @@ -0,0 +1,81 @@ +#pragma once + +#include "TNL/Meshes/Grid.h" +#include "../Base/HeatmapSolver.h" + +template +template +bool HeatmapSolver::solve(const HeatmapSolver::Parameters& params) const { + using Grid2D = TNL::Meshes::Grid<2, Real, Device, int>; + + Grid2D grid; + + // Grid implementation defines its dimensions in the amount of edges. + // To align it size to all other benchmarks substract 1 + grid.setDimensions(params.xSize - 1, params.ySize - 1); + grid.setDomain({0., 0.}, { params.xDomainSize, params.yDomainSize }); + + auto verticesCount = grid.template getEntitiesCount<0>(); + + TNL::Containers::Array ux(verticesCount), // data at step u + aux(verticesCount);// data at step u + 1 + + // Invalidate ux/aux + ux = 0; + aux = 0; + + const Real hx = grid.template getSpaceStepsProducts<1, 0>(); + const Real hy = grid.template getSpaceStepsProducts<0, 1>(); + const Real hx_inv = grid.template getSpaceStepsProducts<-2, 0>(); + const Real hy_inv = grid.template getSpaceStepsProducts<0, -2>(); + + auto timestep = params.timeStep ? + params.timeStep : std::min(grid.template getSpaceStepsProducts<2, 0>(), grid.template getSpaceStepsProducts<0, 2>()); + + auto uxView = ux.getView(), + auxView = aux.getView(); + + auto xDomainSize = params.xDomainSize; + auto yDomainSize = params.yDomainSize; + + auto alpha = params.alpha; + auto beta = params.beta; + auto gamma = params.gamma; + + auto init = [=] __cuda_callable__(const typename Grid2D::EntityType<0> &entity) mutable { + auto index = entity.getIndex(); + + auto x = entity.getCoordinates().x() * hx - xDomainSize / 2.; + auto y = entity.getCoordinates().y() * hy - yDomainSize / 2.; + + uxView[index] = TNL::max((x * x / alpha) + (y * y / beta) + gamma, 0); + }; + + grid.template forInterior<0>(init); + + if (!writeGNUPlot("data.txt", params, ux)) + return false; + + auto width = grid.getDimensions().x() + 1; + auto next = [=] __cuda_callable__(const typename Grid2D::EntityType<0>&entity) mutable { + auto index = entity.getIndex(); + auto element = uxView[index]; + auto center = 2 * element; + + auxView[index] = element + ((uxView[index - 1] - center + uxView[index + 1]) * hx_inv + + (uxView[index - width] - center + uxView[index + width]) * hy_inv) * timestep; + }; + + Real start = 0; + + while (start < params.finalTime) { + grid.template forInterior<0>(next); + + uxView = aux.getView(); + auxView = ux.getView(); + + start += timestep; + } + + return writeGNUPlot("data_final.txt", params, ux); +} diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/solution/CMakeLists.txt b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/solution/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..d5efbfc814d5f52a9f79adceef709cedeb677b00 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/solution/CMakeLists.txt @@ -0,0 +1,5 @@ +if (BUILD_CUDA) + CUDA_ADD_EXECUTABLE( heat_tnl_grid ../implementation.h ../../Base/HeatmapSolver.h main.h main.cu ) +ELSE() + add_executable( heat_tnl_grid ../implementation.h ../../Base/HeatmapSolver.h main.h main.cpp ) +ENDIF() diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/solution/main.cpp b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/solution/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a7a28956b887a99bcb3c646b18d0bef52c9d320 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/solution/main.cpp @@ -0,0 +1,2 @@ + +#include "main.h" diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/solution/main.cu b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/solution/main.cu new file mode 100644 index 0000000000000000000000000000000000000000..7a7a28956b887a99bcb3c646b18d0bef52c9d320 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/solution/main.cu @@ -0,0 +1,2 @@ + +#include "main.h" diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/solution/main.h b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/solution/main.h new file mode 100644 index 0000000000000000000000000000000000000000..6d888d753a03c071b54f0e86b947708564b2ed5e --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGrid/solution/main.h @@ -0,0 +1,37 @@ + +#include +#include +#include +#include +#include +#include + +#include "../../Base/HeatmapSolver.h" +#include "../implementation.h" + +int main(int argc, char *argv[]) { + using Real = double; + + auto config = HeatmapSolver::Parameters::makeInputConfig(); + + TNL::Config::ParameterContainer parameters; + if (!parseCommandLine(argc, argv, config, parameters)) + return EXIT_FAILURE; + + parameters.addParameter("outputData", true); + + auto device = parameters.getParameter("device"); + auto params = HeatmapSolver::Parameters(parameters); + + HeatmapSolver solver; + + if (device == "host" && !solver.solve(params)) + return EXIT_FAILURE; + +#ifdef HAVE_CUDA + if (device == "cuda" && !solver.solve(params)) + return EXIT_FAILURE; +#endif + + return EXIT_SUCCESS; +} diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/CMakeLists.txt b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..58c97ef0d44b742043c4005d632847dd547c15ee --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/CMakeLists.txt @@ -0,0 +1,2 @@ +ADD_SUBDIRECTORY( benchmark ) +ADD_SUBDIRECTORY( solution ) diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/benchmark/CMakeLists.txt b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/benchmark/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..d7f695bc71309739b018a74e4a1f50654ffed883 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/benchmark/CMakeLists.txt @@ -0,0 +1,5 @@ +if (BUILD_CUDA) + CUDA_ADD_EXECUTABLE( heat_parallel_for_with_memory_load_benchmark ../implementation.h ../../Base/HeatmapSolver.h ../../Base/HeatmapSolverBenchmark.h main.h main.cu ) +ELSE() + add_executable( heat_parallel_for_with_memory_load_benchmark ../implementation.h ../../Base/HeatmapSolver.h ../../Base/HeatmapSolverBenchmark.h main.h main.cpp ) +ENDIF() diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/benchmark/main.cpp b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/benchmark/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a7a28956b887a99bcb3c646b18d0bef52c9d320 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/benchmark/main.cpp @@ -0,0 +1,2 @@ + +#include "main.h" diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/benchmark/main.cu b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/benchmark/main.cu new file mode 100644 index 0000000000000000000000000000000000000000..7a7a28956b887a99bcb3c646b18d0bef52c9d320 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/benchmark/main.cu @@ -0,0 +1,2 @@ + +#include "main.h" diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/benchmark/main.h b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/benchmark/main.h new file mode 100644 index 0000000000000000000000000000000000000000..64defc7d172ae4f2864ec73d4716dbe863b0db54 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/benchmark/main.h @@ -0,0 +1,5 @@ +#include "../../Base/HeatmapSolver.h" +#include "../../Base/HeatmapSolverBenchmark.h" +#include "../implementation.h" + +#pragma once diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/implementation.h b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/implementation.h new file mode 100644 index 0000000000000000000000000000000000000000..fc01fbdfc0c998290b4a8cd4d94dabff81c390c6 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/implementation.h @@ -0,0 +1,151 @@ + +#include +#include +#include + +#include "../Base/HeatmapSolver.h" + +#pragma once + +template +class Entity; + +template +constexpr size_t pow() { + size_t result = 1; + + for (size_t i = 0; i < Power; i++) { + result *= Value; + } + + return result; +} + +constexpr int spaceStepsPowers = 5; + +template +class Grid { + public: + Grid() = default; + + __cuda_callable__ inline + Entity getEntity(Index i, Index j) const { + Entity entity(*this); + + entity.i = i; + entity.j = j; + + return entity; + } + + TNL::Containers::StaticVector dimensions; + TNL::Containers::StaticVector<1 << Size, Index> entitiesCountAlongBases; + TNL::Containers::StaticVector cumulativeEntitiesCountAlongBases; + + TNL::Containers::StaticVector origin, proportions, spaceSteps; + + TNL::Containers::StaticVector()>::value, Real> spaceProducts; +}; + +template +class Entity { + public: + __cuda_callable__ inline + Entity(const Grid& grid): grid(grid) {}; + + const Grid& grid; + + Index i, j; + Index index; + Index orientation; + TNL::Containers::StaticVector coordinates, basis; +}; + +/*** + * Grid parameters: + * + * ySize-1|j (ySize - 1) * xSize + xSize - 1 + * |------------------------------------------------------ + * | + * | + * | + * | + * | + * | + * | + * | + * | + * |------------------------------------------------------> + * + * 0 xSize-1|i + * + * j * xSize + i + ***/ +template +template +bool HeatmapSolver::solve(const HeatmapSolver::Parameters ¶ms) const { + TNL::Containers::Array ux(params.xSize * params.ySize), // data at step u + aux(params.xSize * params.ySize); // data at step u + 1 + + // Invalidate ux/aux + ux = 0; + aux = 0; + + const Real hx = params.xDomainSize / (Real)params.xSize; + const Real hy = params.yDomainSize / (Real)params.ySize; + const Real hx_inv = 1. / (hx * hx); + const Real hy_inv = 1. / (hy * hy); + + auto timestep = params.timeStep ? params.timeStep : std::min(hx * hx, hy * hy); + + auto uxView = ux.getView(), auxView = aux.getView(); + + auto xSize = params.xSize; + auto xDomainSize = params.xDomainSize; + auto yDomainSize = params.yDomainSize; + + auto alpha = params.alpha; + auto beta = params.beta; + auto gamma = params.gamma; + + Grid<2, int, Real> grid; + + auto init = [=] __cuda_callable__(int i, int j) mutable { + auto entity = grid.getEntity(i, j); + + auto index = entity.j * xSize + entity.i; + + auto x = entity.i * hx - xDomainSize / 2.; + auto y = entity.j * hy - yDomainSize / 2.; + + uxView[index] = TNL::max((x * x / alpha) + (y * y / beta) + gamma, 0); + }; + + TNL::Algorithms::ParallelFor2D::exec(1, 1, params.xSize - 1, params.ySize - 1, init); + + if (!writeGNUPlot("data.txt", params, ux)) return false; + + auto next = [=] __cuda_callable__(int i, int j) mutable { + auto entity = grid.getEntity(i, j); + + auto index = entity.j * xSize + entity.i; + auto element = uxView[index]; + auto center = 2 * element; + + auxView[index] = element + ((uxView[index - 1] - center + uxView[index + 1]) * hx_inv + + (uxView[index - xSize] - center + uxView[index + xSize]) * hy_inv) * timestep; + }; + + Real start = 0; + + while (start < params.finalTime) { + TNL::Algorithms::ParallelFor2D::exec(1, 1, params.xSize - 1, params.ySize - 1, next); + + uxView = aux.getView(); + auxView = ux.getView(); + + start += timestep; + } + + return writeGNUPlot("data_final.txt", params, ux); +} diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/solution/CMakeLists.txt b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/solution/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..1ebdec4d60838706643e03f45320bbc590bef63a --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/solution/CMakeLists.txt @@ -0,0 +1,5 @@ +if (BUILD_CUDA) + CUDA_ADD_EXECUTABLE( heat_parallel_for_with_memory_load ../implementation.h ../../Base/HeatmapSolver.h main.h main.cu ) +ELSE() + add_executable( heat_parallel_for_with_memory_load ../implementation.h ../../Base/HeatmapSolver.h main.h main.cpp ) +ENDIF() diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/solution/main.cpp b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/solution/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a7a28956b887a99bcb3c646b18d0bef52c9d320 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/solution/main.cpp @@ -0,0 +1,2 @@ + +#include "main.h" diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/solution/main.cu b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/solution/main.cu new file mode 100644 index 0000000000000000000000000000000000000000..7a7a28956b887a99bcb3c646b18d0bef52c9d320 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/solution/main.cu @@ -0,0 +1,2 @@ + +#include "main.h" diff --git a/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/solution/main.h b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/solution/main.h new file mode 100644 index 0000000000000000000000000000000000000000..31c5ded3a8d6f14e47dc63b53c7a3e1380a87400 --- /dev/null +++ b/src/Benchmarks/HeatEquationGrid/HeatmapTNLGridWithMemoryLoad/solution/main.h @@ -0,0 +1,37 @@ + +#include +#include +#include +#include +#include +#include + +#include "../../Base/HeatmapSolver.h" +#include "../implementation.h" + +int main(int argc, char *argv[]) { + using Real = double; + + auto config = HeatmapSolver::Parameters::makeInputConfig(); + + TNL::Config::ParameterContainer parameters; + if (!parseCommandLine(argc, argv, config, parameters)) + return EXIT_FAILURE; + + parameters.addParameter("outputData", true); + + auto device = parameters.getParameter("device"); + auto params = HeatmapSolver::Parameters(parameters); + + HeatmapSolver solver; + + if (device == "host" && !solver.template solve(params)) + return EXIT_FAILURE; + +#ifdef HAVE_CUDA + if (device == "cuda" && !solver.template solve(params)) + return EXIT_FAILURE; +#endif + + return EXIT_SUCCESS; +} diff --git a/src/Python/pytnl/tnl/Grid.h b/src/Python/pytnl/tnl/Grid.h index c0b7c89c06f39d8784b172e0f5a41a0d85ec085a..c9643cb13e431b7eb55e2820e8ce96f58e36d108 100644 --- a/src/Python/pytnl/tnl/Grid.h +++ b/src/Python/pytnl/tnl/Grid.h @@ -20,8 +20,7 @@ void export_GridEntity( PyGrid & scope, const char* name ) py::return_value_policy::reference_internal ) .def( py::init< typename GridEntity::GridType, typename GridEntity::CoordinatesType, - typename GridEntity::EntityOrientationType, - typename GridEntity::EntityBasisType >(), + typename GridEntity::EntityOrientationType >(), py::return_value_policy::reference_internal ) .def("getEntityDimension", &GridEntity::getEntityDimension) .def("getMeshDimension", &GridEntity::getMeshDimension) @@ -34,9 +33,6 @@ void export_GridEntity( PyGrid & scope, const char* name ) // FIXME: some templates return reference, others value // .def("getOrientation", &GridEntity::getOrientation, py::return_internal_reference<>(), py::return_value_policy()) .def("setOrientation", &GridEntity::setOrientation) - // FIXME: some templates return reference, others value -// .def("getBasis", &GridEntity::getBasis, py::return_internal_reference<>(), py::return_value_policy()) - .def("setBasis", &GridEntity::setBasis) // TODO: getNeighbourEntities .def("isBoundaryEntity", &GridEntity::isBoundaryEntity) .def("getCenter", &GridEntity::getCenter) diff --git a/src/TNL/Algorithms/reduce.h b/src/TNL/Algorithms/reduce.h index 95beb098f85a27037d25956717c52af3b3987d34..67056343764c9eff901f4e446dc47e043e83b3fe 100644 --- a/src/TNL/Algorithms/reduce.h +++ b/src/TNL/Algorithms/reduce.h @@ -16,7 +16,6 @@ namespace TNL { namespace Algorithms { - /** * \brief \e reduce implements [(parallel) reduction](https://en.wikipedia.org/wiki/Reduce_(parallel_pattern)) * for vectors and arrays. diff --git a/src/TNL/Benchmarks/Utils.h b/src/TNL/Benchmarks/Utils.h index 371a20af3ad84014dee7b07665cfba11b797be6c..0027dc81107eba973efc52f8fe2a89e782d2e8de 100644 --- a/src/TNL/Benchmarks/Utils.h +++ b/src/TNL/Benchmarks/Utils.h @@ -74,7 +74,7 @@ timeFunction( ComputeFunction compute, ResetFunction reset, int maxLoops, const #endif timer.stop(); - results[ loops ] = timer.getRealTime(); + results[ loops ] = timer.getCPUTime(); } const double mean = sum( results ) / (double) loops; diff --git a/src/TNL/Containers/StaticArray.h b/src/TNL/Containers/StaticArray.h index 50c11b34248618e65189b9ec2e70c46ba4fcf948..26a89c3918574517d31f29ae5c0165de631b7405 100644 --- a/src/TNL/Containers/StaticArray.h +++ b/src/TNL/Containers/StaticArray.h @@ -62,7 +62,7 @@ public: * \param v Reference to a value. */ __cuda_callable__ - StaticArray( const Value& v ); + constexpr StaticArray( const Value& v ); /** * \brief Copy constructor. @@ -90,7 +90,7 @@ public: * \param v2 Value of the second array component. */ __cuda_callable__ - StaticArray( const Value& v1, const Value& v2 ); + constexpr StaticArray( const Value& v1, const Value& v2 ); /** * \brief Constructor that sets components of arrays with Size = 3. @@ -100,7 +100,18 @@ public: * \param v3 Value of the third array component. */ __cuda_callable__ - StaticArray( const Value& v1, const Value& v2, const Value& v3 ); + constexpr StaticArray( const Value& v1, const Value& v2, const Value& v3 ); + + /** + * \brief Constructor that sets components of arrays with Size = 4. + * + * \param v1 Value of the first array component. + * \param v2 Value of the second array component. + * \param v3 Value of the third array component. + * \param v4 Value of the forth array component. + */ + __cuda_callable__ + constexpr StaticArray( const Value& v1, const Value& v2, const Value& v3, const Value& v4 ); /** * \brief Gets pointer to data of this static array. @@ -122,7 +133,7 @@ public: * \param i Index position of an element. */ __cuda_callable__ - const Value& + constexpr const Value& operator[]( int i ) const; /** @@ -131,7 +142,7 @@ public: * \param i Index position of an element. */ __cuda_callable__ - Value& + constexpr Value& operator[]( int i ); /** @@ -140,7 +151,7 @@ public: * Equivalent to \ref operator[]. */ __cuda_callable__ - const Value& + constexpr const Value& operator()( int i ) const; /** @@ -149,50 +160,50 @@ public: * Equivalent to \ref operator[]. */ __cuda_callable__ - Value& + constexpr Value& operator()( int i ); /** * \brief Returns reference to the first coordinate. */ __cuda_callable__ - Value& - x(); + constexpr + Value& x(); /** * \brief Returns constant reference to the first coordinate. */ __cuda_callable__ - const Value& - x() const; + constexpr const + Value& x() const; /** * \brief Returns reference to the second coordinate for arrays with Size >= 2. */ __cuda_callable__ - Value& - y(); + constexpr + Value& y(); /** * \brief Returns constant reference to the second coordinate for arrays with Size >= 2. */ __cuda_callable__ - const Value& - y() const; + constexpr const + Value& y() const; /** * \brief Returns reference to the third coordinate for arrays with Size >= 3. */ __cuda_callable__ - Value& - z(); + constexpr + Value& z(); /** * \brief Returns constant reference to the third coordinate for arrays with Size >= 3. */ __cuda_callable__ - const Value& - z() const; + constexpr const + Value& z() const; /** * \brief Assigns another static \e array to this array. @@ -223,7 +234,7 @@ public: */ template< typename Array > __cuda_callable__ - bool + constexpr bool operator==( const Array& array ) const; /** @@ -233,7 +244,7 @@ public: */ template< typename Array > __cuda_callable__ - bool + constexpr bool operator!=( const Array& array ) const; /** diff --git a/src/TNL/Containers/StaticArray.hpp b/src/TNL/Containers/StaticArray.hpp index 683346812581fe64fd030b9430883498d27753c8..d93d1cc2017c65b8d514026e4ac304d449b4c41d 100644 --- a/src/TNL/Containers/StaticArray.hpp +++ b/src/TNL/Containers/StaticArray.hpp @@ -107,7 +107,7 @@ StaticArray< Size, Value >::StaticArray( const Value v[ Size ] ) template< int Size, typename Value > __cuda_callable__ -StaticArray< Size, Value >::StaticArray( const Value& v ) +constexpr StaticArray< Size, Value >::StaticArray( const Value& v ) { Algorithms::unrolledFor< int, 0, Size >( [ & ]( int i ) mutable @@ -137,8 +137,8 @@ StaticArray< Size, Value >::StaticArray( const std::initializer_list< Value >& e } template< int Size, typename Value > -__cuda_callable__ -StaticArray< Size, Value >::StaticArray( const Value& v1, const Value& v2 ) + __cuda_callable__ +constexpr StaticArray< Size, Value >::StaticArray( const Value& v1, const Value& v2 ) { static_assert( Size == 2, "This constructor can be called only for arrays with Size = 2." ); data[ 0 ] = v1; @@ -146,8 +146,8 @@ StaticArray< Size, Value >::StaticArray( const Value& v1, const Value& v2 ) } template< int Size, typename Value > -__cuda_callable__ -StaticArray< Size, Value >::StaticArray( const Value& v1, const Value& v2, const Value& v3 ) + __cuda_callable__ +constexpr StaticArray< Size, Value >::StaticArray( const Value& v1, const Value& v2, const Value& v3 ) { static_assert( Size == 3, "This constructor can be called only for arrays with Size = 3." ); data[ 0 ] = v1; @@ -155,6 +155,17 @@ StaticArray< Size, Value >::StaticArray( const Value& v1, const Value& v2, const data[ 2 ] = v3; } +template< int Size, typename Value > + __cuda_callable__ +constexpr StaticArray< Size, Value >::StaticArray( const Value& v1, const Value& v2, const Value& v3, const Value& v4 ) +{ + static_assert( Size == 4, "This constructor can be called only for arrays with Size = 4." ); + data[ 0 ] = v1; + data[ 1 ] = v2; + data[ 2 ] = v3; + data[ 3 ] = v4; +} + template< int Size, typename Value > __cuda_callable__ Value* @@ -173,8 +184,7 @@ StaticArray< Size, Value >::getData() const template< int Size, typename Value > __cuda_callable__ -const Value& -StaticArray< Size, Value >::operator[]( int i ) const +constexpr const Value& StaticArray< Size, Value >::operator[]( int i ) const { TNL_ASSERT_GE( i, 0, "Element index must be non-negative." ); TNL_ASSERT_LT( i, Size, "Element index is out of bounds." ); @@ -183,8 +193,7 @@ StaticArray< Size, Value >::operator[]( int i ) const template< int Size, typename Value > __cuda_callable__ -Value& -StaticArray< Size, Value >::operator[]( int i ) +constexpr Value& StaticArray< Size, Value >::operator[]( int i ) { TNL_ASSERT_GE( i, 0, "Element index must be non-negative." ); TNL_ASSERT_LT( i, Size, "Element index is out of bounds." ); @@ -193,40 +202,35 @@ StaticArray< Size, Value >::operator[]( int i ) template< int Size, typename Value > __cuda_callable__ -const Value& -StaticArray< Size, Value >::operator()( int i ) const +constexpr const Value& StaticArray< Size, Value >::operator()( int i ) const { return operator[]( i ); } template< int Size, typename Value > __cuda_callable__ -Value& -StaticArray< Size, Value >::operator()( int i ) +constexpr Value& StaticArray< Size, Value >::operator()( int i ) { return operator[]( i ); } template< int Size, typename Value > __cuda_callable__ -Value& -StaticArray< Size, Value >::x() +constexpr Value& StaticArray< Size, Value >::x() { return data[ 0 ]; } template< int Size, typename Value > __cuda_callable__ -const Value& -StaticArray< Size, Value >::x() const +constexpr const Value& StaticArray< Size, Value >::x() const { return data[ 0 ]; } template< int Size, typename Value > __cuda_callable__ -Value& -StaticArray< Size, Value >::y() +constexpr Value& StaticArray< Size, Value >::y() { static_assert( Size > 1, "Cannot call StaticArray< Size, Value >::y() for arrays with Size < 2." ); return data[ 1 ]; @@ -234,8 +238,7 @@ StaticArray< Size, Value >::y() template< int Size, typename Value > __cuda_callable__ -const Value& -StaticArray< Size, Value >::y() const +constexpr const Value& StaticArray< Size, Value >::y() const { static_assert( Size > 1, "Cannot call StaticArray< Size, Value >::y() for arrays with Size < 2." ); return data[ 1 ]; @@ -243,8 +246,7 @@ StaticArray< Size, Value >::y() const template< int Size, typename Value > __cuda_callable__ -Value& -StaticArray< Size, Value >::z() +constexpr Value& StaticArray< Size, Value >::z() { static_assert( Size > 1, "Cannot call StaticArray< Size, Value >::z() for arrays with Size < 3." ); return data[ 2 ]; @@ -252,8 +254,7 @@ StaticArray< Size, Value >::z() template< int Size, typename Value > __cuda_callable__ -const Value& -StaticArray< Size, Value >::z() const +constexpr const Value& StaticArray< Size, Value >::z() const { static_assert( Size > 1, "Cannot call StaticArray< Size, Value >::z() for arrays with Size < 3." ); return data[ 2 ]; @@ -285,8 +286,7 @@ StaticArray< Size, Value >::operator=( const T& v ) template< int Size, typename Value > template< typename Array > __cuda_callable__ -bool -StaticArray< Size, Value >::operator==( const Array& array ) const +constexpr bool StaticArray< Size, Value >::operator==( const Array& array ) const { return detail::StaticArrayComparator< Size, Value, typename Array::ValueType, 0 >::EQ( *this, array ); } @@ -294,8 +294,7 @@ StaticArray< Size, Value >::operator==( const Array& array ) const template< int Size, typename Value > template< typename Array > __cuda_callable__ -bool -StaticArray< Size, Value >::operator!=( const Array& array ) const +constexpr bool StaticArray< Size, Value >::operator!=( const Array& array ) const { return ! this->operator==( array ); } diff --git a/src/TNL/Functions/MeshFunctionGnuplotWriter.h b/src/TNL/Functions/MeshFunctionGnuplotWriter.h index 8a6aa84f8d2c6ab0f604ad708540cf023755f1a1..68be9e6a7a79d4995327e2ff86cb5c98e23b27ad 100644 --- a/src/TNL/Functions/MeshFunctionGnuplotWriter.h +++ b/src/TNL/Functions/MeshFunctionGnuplotWriter.h @@ -101,7 +101,7 @@ public: write( const MeshFunction& function, std::ostream& str ) { const MeshType& grid = function.getMesh(); - EntityType entity( grid ); + EntityType entity( grid, { 0, 0 } ); auto& c = entity.getCoordinates(); for( c.y() = 0; c.y() < grid.getDimensions().y(); c.y()++ ) { for( c.x() = 0; c.x() < grid.getDimensions().x(); c.x()++ ) { @@ -131,7 +131,7 @@ public: write( const MeshFunction& function, std::ostream& str ) { const MeshType& grid = function.getMesh(); - EntityType entity( grid ); + EntityType entity( grid, { 0, 0 }); auto& c = entity.getCoordinates(); for( c.z() = 0; c.z() < grid.getDimensions().z(); c.z()++ ) for( c.y() = 0; c.y() < grid.getDimensions().y(); c.y()++ ) { diff --git a/src/TNL/Images/DicomSeries_impl.h b/src/TNL/Images/DicomSeries_impl.h index a645ee187d581e546a41d21d50bcaa3d52addc68..ec367fe16528c3704fa0be414dd7632e04519241 100644 --- a/src/TNL/Images/DicomSeries_impl.h +++ b/src/TNL/Images/DicomSeries_impl.h @@ -76,7 +76,7 @@ DicomSeries::getImage( const int imageIdx, #ifdef HAVE_DCMTK_H const Uint16* imageData = this->getData( imageIdx ); using GridType = Meshes::Grid< 2, Real, Device, Index >; - typename GridType::Cell cell( grid ); + typename GridType::Cell cell( grid, { 0, 0 }); Index i, j; int position( 0 ); diff --git a/src/TNL/Images/JPEGImage_impl.h b/src/TNL/Images/JPEGImage_impl.h index a8c7335898deceb853b84121e030cbd332294894..7fac4b60a52cb46096981941f44641105995057d 100644 --- a/src/TNL/Images/JPEGImage_impl.h +++ b/src/TNL/Images/JPEGImage_impl.h @@ -94,7 +94,7 @@ JPEGImage< Index >::read( const RegionOfInterest< Index > roi, #ifdef HAVE_JPEG_H using GridType = Meshes::Grid< 2, Real, Device, Index >; const GridType& grid = function.getMesh(); - typename GridType::Cell cell( grid ); + typename GridType::Cell cell( grid, { 0, 0 }); /*** * Prepare the long jump back from libjpeg. @@ -202,7 +202,7 @@ bool JPEGImage< Index >::write( const Meshes::Grid< 2, Real, Device, Index >& grid, Vector& vector ) { using GridType = Meshes::Grid< 2, Real, Device, Index >; - typename GridType::Cell cell( grid ); + typename GridType::Cell cell( grid, { 0, 0 } ); #ifdef HAVE_JPEG_H Index i( 0 ), j; @@ -238,7 +238,7 @@ JPEGImage< Index >::write( const Functions::MeshFunction< Meshes::Grid< 2, MeshR { using GridType = Meshes::Grid< 2, Real, Device, Index >; const GridType& grid = function.getMesh(); - typename GridType::Cell cell( grid ); + typename GridType::Cell cell( grid, { 0, 0 }); #ifdef HAVE_JPEG_H Index i( 0 ), j; diff --git a/src/TNL/Images/PGMImage_impl.h b/src/TNL/Images/PGMImage_impl.h index d14575925d6b9a9251f7bf1a1943c332e43090c0..84e6fb17fb0c053175ab391e64d17af8a2f154f9 100644 --- a/src/TNL/Images/PGMImage_impl.h +++ b/src/TNL/Images/PGMImage_impl.h @@ -75,7 +75,7 @@ PGMImage< Index >::read( const RegionOfInterest< Index > roi, { using GridType = Meshes::Grid< 2, Real, Device, Index >; const GridType& grid = function.getMesh(); - typename GridType::Cell cell( grid ); + typename GridType::Cell cell( grid, { 0, 0 } ); Index i, j; for( i = 0; i < this->height; i++ ) @@ -139,7 +139,7 @@ bool PGMImage< Index >::write( const Meshes::Grid< 2, Real, Device, Index >& grid, Vector& vector ) { using GridType = Meshes::Grid< 2, Real, Device, Index >; - typename GridType::Cell cell( grid ); + typename GridType::Cell cell( grid, { 0, 0 } ); Index i, j; for( i = 0; i < grid.getDimensions().y(); i++ ) { @@ -173,7 +173,7 @@ PGMImage< Index >::write( const Functions::MeshFunction< Meshes::Grid< 2, MeshRe { using GridType = Meshes::Grid< 2, Real, Device, Index >; const GridType& grid = function.getMesh(); - typename GridType::Cell cell( grid ); + typename GridType::Cell cell( grid, { 0, 0 } ); Index i, j; for( i = 0; i < grid.getDimensions().y(); i++ ) { diff --git a/src/TNL/Images/PNGImage_impl.h b/src/TNL/Images/PNGImage_impl.h index 3b946ff8276f5ea798f92dad5039adedd7417a73..d50bc425007bc1a5e88dea43e9d26db03a42f190 100644 --- a/src/TNL/Images/PNGImage_impl.h +++ b/src/TNL/Images/PNGImage_impl.h @@ -103,7 +103,7 @@ PNGImage< Index >::read( const RegionOfInterest< Index > roi, #ifdef HAVE_PNG_H using GridType = Meshes::Grid< 2, MeshReal, Device, Index >; const GridType& grid = function.getMesh(); - typename GridType::Cell cell( grid ); + typename GridType::Cell cell( grid, { 0, 0 } ); /*** * Prepare the long jump back from libpng. @@ -250,7 +250,7 @@ PNGImage< Index >::write( const Meshes::Grid< 2, Real, Device, Index >& grid, Ve { #ifdef HAVE_PNG_H using GridType = Meshes::Grid< 2, Real, Device, Index >; - typename GridType::Cell cell( grid ); + typename GridType::Cell cell( grid, { 0, 0 } ); /*** * Prepare the long jump back from libpng. diff --git a/src/TNL/Meshes/Geometry/getEntityCenter.h b/src/TNL/Meshes/Geometry/getEntityCenter.h index 5cd2909a1ec8a79b1670ae13b7299e6100c1d555..19cf3fcea3cdce8a53a10b7ea6a6a5b9ef4eba6c 100644 --- a/src/TNL/Meshes/Geometry/getEntityCenter.h +++ b/src/TNL/Meshes/Geometry/getEntityCenter.h @@ -15,10 +15,10 @@ namespace TNL { namespace Meshes { // compatibility wrapper -template< typename Grid, int EntityDimension, typename Config > +template< typename Grid, int EntityDimension > __cuda_callable__ typename Grid::PointType -getEntityCenter( const Grid& grid, const GridEntity< Grid, EntityDimension, Config >& entity ) +getEntityCenter( const Grid& grid, const GridEntity< Grid, EntityDimension >& entity ) { return entity.getCenter(); } diff --git a/src/TNL/Meshes/Geometry/getEntityMeasure.h b/src/TNL/Meshes/Geometry/getEntityMeasure.h index 34ed01fdc5e4cacd27198750c2ad39786e755035..2d96536bef2ba294ed77c3f4d4d099953e68fbda 100644 --- a/src/TNL/Meshes/Geometry/getEntityMeasure.h +++ b/src/TNL/Meshes/Geometry/getEntityMeasure.h @@ -25,10 +25,10 @@ namespace TNL { namespace Meshes { -template< typename Grid, typename Config > +template< typename Grid > __cuda_callable__ typename Grid::RealType -getEntityMeasure( const Grid& grid, const GridEntity< Grid, 0, Config >& entity ) +getEntityMeasure( const Grid& grid, const GridEntity< Grid, 0 >& entity ) { // entity.getMeasure() returns 0.0 !!! return 1.0; @@ -37,7 +37,7 @@ getEntityMeasure( const Grid& grid, const GridEntity< Grid, 0, Config >& entity template< typename Grid, int EntityDimension, typename Config > __cuda_callable__ typename Grid::RealType -getEntityMeasure( const Grid& grid, const GridEntity< Grid, EntityDimension, Config >& entity ) +getEntityMeasure( const Grid& grid, const GridEntity< Grid, EntityDimension >& entity ) { return entity.getMeasure(); } diff --git a/src/TNL/Meshes/Geometry/getOutwardNormalVector.h b/src/TNL/Meshes/Geometry/getOutwardNormalVector.h index 1b473ff40cb075c3f335b14f6cf8629b150c9f76..b67c70cbaf8af5bb7715c368a0742798e6e877c7 100644 --- a/src/TNL/Meshes/Geometry/getOutwardNormalVector.h +++ b/src/TNL/Meshes/Geometry/getOutwardNormalVector.h @@ -12,10 +12,10 @@ namespace TNL { namespace Meshes { -template< typename Grid, typename Config > +template< typename Grid > __cuda_callable__ typename Grid::PointType -getOutwardNormalVector( const Grid& grid, const GridEntity< Grid, 0, Config >& face, const typename Grid::PointType cellCenter ) +getOutwardNormalVector( const Grid& grid, const GridEntity< Grid, 0 >& face, const typename Grid::PointType cellCenter ) { static_assert( Grid::getMeshDimension() == 1, "getOutwardNormalVector can be used only with faces." ); const typename Grid::PointType faceCenter = getEntityCenter( grid, face ); @@ -25,10 +25,10 @@ getOutwardNormalVector( const Grid& grid, const GridEntity< Grid, 0, Config >& f return { -1 }; } -template< typename Grid, typename Config > +template< typename Grid > __cuda_callable__ typename Grid::PointType -getOutwardNormalVector( const Grid& grid, const GridEntity< Grid, 1, Config >& face, const typename Grid::PointType cellCenter ) +getOutwardNormalVector( const Grid& grid, const GridEntity< Grid, 1 >& face, const typename Grid::PointType cellCenter ) { static_assert( Grid::getMeshDimension() == 2, "getOutwardNormalVector can be used only with faces." ); const typename Grid::PointType faceCenter = getEntityCenter( grid, face ); @@ -48,10 +48,10 @@ getOutwardNormalVector( const Grid& grid, const GridEntity< Grid, 1, Config >& f } } -template< typename Grid, typename Config > +template< typename Grid > __cuda_callable__ typename Grid::PointType -getOutwardNormalVector( const Grid& grid, const GridEntity< Grid, 2, Config >& face, const typename Grid::PointType cellCenter ) +getOutwardNormalVector( const Grid& grid, const GridEntity< Grid, 2 >& face, const typename Grid::PointType cellCenter ) { static_assert( Grid::getMeshDimension() == 3, "getOutwardNormalVector can be used only with faces." ); const typename Grid::PointType faceCenter = getEntityCenter( grid, face ); diff --git a/src/TNL/Meshes/Grid.h b/src/TNL/Meshes/Grid.h index 4ad322f308f23c769d229cf2323e22a001d7f032..beff25a32e9edfaee3883a0e34110bbc4303e96b 100644 --- a/src/TNL/Meshes/Grid.h +++ b/src/TNL/Meshes/Grid.h @@ -6,13 +6,26 @@ #pragma once -#include +#include +#include namespace TNL { namespace Meshes { template< int Dimension, typename Real = double, typename Device = Devices::Host, typename Index = int > -class Grid; +class Grid : public NDimGrid< Dimension, Real, Device, Index > +{}; + +template< int Dimension, typename Real, typename Device, typename Index > +std::ostream& +operator<<( std::ostream& str, const Grid< Dimension, Real, Device, Index >& grid ) +{ + TNL::Logger logger( 100, str ); + + grid.writeProlog( logger ); + + return str; +} template< int Dimension, typename Real, typename Device, typename Index > bool @@ -29,20 +42,6 @@ operator!=( const Grid< Dimension, Real, Device, Index >& lhs, const Grid< Dimen return ! ( lhs == rhs ); } -template< int Dimension, typename Real, typename Device, typename Index > -std::ostream& -operator<<( std::ostream& str, const Grid< Dimension, Real, Device, Index >& grid ) -{ - str << "Grid dimensions: " << grid.getDimensions() << std::endl; - str << " origin: " << grid.getOrigin() << std::endl; - str << " proportions: " << grid.getProportions() << std::endl; - str << " localBegin: " << grid.getLocalBegin() << std::endl; - str << " localEnd: " << grid.getLocalEnd() << std::endl; - str << " interiorBegin: " << grid.getInteriorBegin() << std::endl; - str << " interiorEnd: " << grid.getInteriorEnd() << std::endl; - return str; -} - } // namespace Meshes } // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/BasisGetter.h b/src/TNL/Meshes/GridDetails/BasisGetter.h new file mode 100644 index 0000000000000000000000000000000000000000..38fc1c5198bb847a3f4965879552a3ec0c3ccf42 --- /dev/null +++ b/src/TNL/Meshes/GridDetails/BasisGetter.h @@ -0,0 +1,52 @@ + +#pragma once + +#include +#include +#include + +namespace TNL { +namespace Meshes { + +template< typename Index, Index EntityDimension, Index GridDimension > +struct BasisGetter +{ +public: + using Coordinate = TNL::Containers::StaticVector< GridDimension, Index >; + using OrientationBasesContainer = + TNL::Containers::StaticVector< Templates::combination( EntityDimension, GridDimension ), Coordinate >; + using Permutations = + Templates::make_int_permutations< GridDimension, + Templates::build_ones_pack< GridDimension - EntityDimension, GridDimension > >; + + template< + int Orientation, + std::enable_if_t< + Templates::isInLeftClosedRightOpenInterval( 0, Orientation, Templates::combination( EntityDimension, GridDimension ) ), + bool > = true > + constexpr static Coordinate + getBasis() + { + using Value = Templates::get< Orientation, Permutations >; + + return BuildBasis< Value >::build(); + } + +private: + template< class > + struct BuildBasis; + + template< int... Values > + struct BuildBasis< TNL::Meshes::Templates::int_pack< Values... > > + { + public: + constexpr static Coordinate + build() + { + return Coordinate( Values... ); + } + }; +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/BoundaryGridEntityChecker.h b/src/TNL/Meshes/GridDetails/BoundaryGridEntityChecker.h index 6a4d798b23cf985e5249d9fde1ed3fa6d707b8bb..f855523cf4fcbe9db1ed1739e15c759ee6a4fcdd 100644 --- a/src/TNL/Meshes/GridDetails/BoundaryGridEntityChecker.h +++ b/src/TNL/Meshes/GridDetails/BoundaryGridEntityChecker.h @@ -9,186 +9,13 @@ namespace TNL { namespace Meshes { -template< typename GridEntity > -class BoundaryGridEntityChecker -{}; +template< class, int > +class GridEntity; -/*** - * 1D grids - */ -template< typename Real, typename Device, typename Index, typename Config > -class BoundaryGridEntityChecker< GridEntity< Meshes::Grid< 1, Real, Device, Index >, 1, Config > > -{ -public: - using GridType = Meshes::Grid< 1, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, 1, Config >; - - __cuda_callable__ - inline static bool - isBoundaryEntity( const GridEntityType& entity ) - { - return ( entity.getCoordinates().x() == 0 || entity.getCoordinates().x() == entity.getMesh().getDimensions().x() - 1 ); - } -}; - -template< typename Real, typename Device, typename Index, typename Config > -class BoundaryGridEntityChecker< GridEntity< Meshes::Grid< 1, Real, Device, Index >, 0, Config > > -{ -public: - using GridType = Meshes::Grid< 1, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, 0, Config >; - - __cuda_callable__ - inline static bool - isBoundaryEntity( const GridEntityType& entity ) - { - return ( entity.getCoordinates().x() == 0 || entity.getCoordinates().x() == entity.getMesh().getDimensions().x() ); - } -}; - -/**** - * 2D grids - */ -template< typename Real, typename Device, typename Index, typename Config > -class BoundaryGridEntityChecker< GridEntity< Meshes::Grid< 2, Real, Device, Index >, 2, Config > > -{ -public: - using GridType = Meshes::Grid< 2, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, 2, Config >; - - __cuda_callable__ - inline static bool - isBoundaryEntity( const GridEntityType& entity ) - { - return ( entity.getCoordinates().x() == 0 || entity.getCoordinates().y() == 0 - || entity.getCoordinates().x() == entity.getMesh().getDimensions().x() - 1 - || entity.getCoordinates().y() == entity.getMesh().getDimensions().y() - 1 ); - } -}; - -template< typename Real, typename Device, typename Index, typename Config > -class BoundaryGridEntityChecker< GridEntity< Meshes::Grid< 2, Real, Device, Index >, 1, Config > > -{ -public: - using GridType = Meshes::Grid< 2, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, 1, Config >; - - __cuda_callable__ - inline static bool - isBoundaryEntity( const GridEntityType& entity ) - { - return ( - ( entity.getOrientation().x() - && ( entity.getCoordinates().x() == 0 || entity.getCoordinates().x() == entity.getMesh().getDimensions().x() ) ) - || ( entity.getOrientation().y() - && ( entity.getCoordinates().y() == 0 - || entity.getCoordinates().y() == entity.getMesh().getDimensions().y() ) ) ); - } -}; - -template< typename Real, typename Device, typename Index, typename Config > -class BoundaryGridEntityChecker< GridEntity< Meshes::Grid< 2, Real, Device, Index >, 0, Config > > -{ -public: - using GridType = Meshes::Grid< 2, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, 0, Config >; - - __cuda_callable__ - inline static bool - isBoundaryEntity( const GridEntityType& entity ) - { - return ( entity.getCoordinates().x() == 0 || entity.getCoordinates().y() == 0 - || entity.getCoordinates().x() == entity.getMesh().getDimensions().x() - || entity.getCoordinates().y() == entity.getMesh().getDimensions().y() ); - } -}; - -/*** - * 3D grid - */ -template< typename Real, typename Device, typename Index, typename Config > -class BoundaryGridEntityChecker< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 3, Config > > -{ -public: - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, 3, Config >; - - __cuda_callable__ - inline static bool - isBoundaryEntity( const GridEntityType& entity ) - { - return ( entity.getCoordinates().x() == 0 || entity.getCoordinates().y() == 0 || entity.getCoordinates().z() == 0 - || entity.getCoordinates().x() == entity.getMesh().getDimensions().x() - 1 - || entity.getCoordinates().y() == entity.getMesh().getDimensions().y() - 1 - || entity.getCoordinates().z() == entity.getMesh().getDimensions().z() - 1 ); - } -}; - -template< typename Real, typename Device, typename Index, typename Config > -class BoundaryGridEntityChecker< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 2, Config > > -{ -public: - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, 2, Config >; - - __cuda_callable__ - inline static bool - isBoundaryEntity( const GridEntityType& entity ) - { - return ( - ( entity.getOrientation().x() - && ( entity.getCoordinates().x() == 0 || entity.getCoordinates().x() == entity.getMesh().getDimensions().x() ) ) - || ( entity.getOrientation().y() - && ( entity.getCoordinates().y() == 0 || entity.getCoordinates().y() == entity.getMesh().getDimensions().y() ) ) - || ( entity.getOrientation().z() - && ( entity.getCoordinates().z() == 0 - || entity.getCoordinates().z() == entity.getMesh().getDimensions().z() ) ) ); - } -}; - -template< typename Real, typename Device, typename Index, typename Config > -class BoundaryGridEntityChecker< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 1, Config > > -{ -public: - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, 1, Config >; - - __cuda_callable__ - inline static bool - isBoundaryEntity( const GridEntityType& entity ) - { - return ( - ( entity.getOrientation().x() - && ( entity.getCoordinates().y() == 0 || entity.getCoordinates().y() == entity.getMesh().getDimensions().y() - || entity.getCoordinates().z() == 0 || entity.getCoordinates().z() == entity.getMesh().getDimensions().z() ) ) - || ( entity.getOrientation().y() - && ( entity.getCoordinates().x() == 0 || entity.getCoordinates().x() == entity.getMesh().getDimensions().x() - || entity.getCoordinates().z() == 0 - || entity.getCoordinates().z() == entity.getMesh().getDimensions().z() ) ) - || ( entity.getOrientation().z() - && ( entity.getCoordinates().x() == 0 || entity.getCoordinates().x() == entity.getMesh().getDimensions().x() - || entity.getCoordinates().y() == 0 - || entity.getCoordinates().y() == entity.getMesh().getDimensions().y() ) ) ); - } -}; - -template< typename Real, typename Device, typename Index, typename Config > -class BoundaryGridEntityChecker< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 0, Config > > -{ -public: - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, 0, Config >; - - __cuda_callable__ - inline static bool - isBoundaryEntity( const GridEntityType& entity ) - { - return ( entity.getCoordinates().x() == 0 || entity.getCoordinates().y() == 0 || entity.getCoordinates().z() == 0 - || entity.getCoordinates().x() == entity.getMesh().getDimensions().x() - || entity.getCoordinates().y() == entity.getMesh().getDimensions().y() - || entity.getCoordinates().z() == entity.getMesh().getDimensions().z() ); - } -}; +template< class > +class BoundaryGridEntityChecker; } // namespace Meshes } // namespace TNL + +#include diff --git a/src/TNL/Meshes/GridDetails/Grid1D.h b/src/TNL/Meshes/GridDetails/Grid1D.h index cf3bc8337f36ee23b1d56b7a136e3cd9ecf54131..fb95758e40742895c23a95cae89d95af600d1b04 100644 --- a/src/TNL/Meshes/GridDetails/Grid1D.h +++ b/src/TNL/Meshes/GridDetails/Grid1D.h @@ -6,162 +6,31 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include +#include namespace TNL { namespace Meshes { +template< class, int > +class GridEntity; + template< typename Real, typename Device, typename Index > -class Grid< 1, Real, Device, Index > +class Grid< 1, Real, Device, Index > : public NDimGrid< 1, Real, Device, Index > { public: - using RealType = Real; - using DeviceType = Device; - using GlobalIndexType = Index; - using PointType = Containers::StaticVector< 1, Real >; - using CoordinatesType = Containers::StaticVector< 1, Index >; - - // TODO: deprecated and to be removed (GlobalIndexType shall be used instead) - using IndexType = Index; - - /** - * \brief Returns number of this mesh grid dimensions. - */ - static constexpr int - getMeshDimension() - { - return 1; - }; - - template< int EntityDimension, typename Config = GridEntityCrossStencilStorage< 1 > > - using EntityType = GridEntity< Grid, EntityDimension, Config >; - - using Cell = EntityType< getMeshDimension(), GridEntityCrossStencilStorage< 1 > >; - using Face = EntityType< 0 >; - using Vertex = EntityType< 0 >; - - /** - * \brief Basic constructor. - */ - Grid() = default; - - Grid( Index xSize ); - - // empty destructor is needed only to avoid crappy nvcc warnings - ~Grid() = default; - - /** - * \brief Sets the size of dimensions. - * \param xSize Size of dimesion x. - */ - void - setDimensions( Index xSize ); - - /** - * \brief Sets the number of dimensions. - * \param dimensions Number of dimensions. - */ - void - setDimensions( const CoordinatesType& dimensions ); - - __cuda_callable__ - const CoordinatesType& - getDimensions() const; - - void - setLocalBegin( const CoordinatesType& begin ); - - __cuda_callable__ - const CoordinatesType& - getLocalBegin() const; - - void - setLocalEnd( const CoordinatesType& end ); - - __cuda_callable__ - const CoordinatesType& - getLocalEnd() const; - - void - setInteriorBegin( const CoordinatesType& begin ); - - __cuda_callable__ - const CoordinatesType& - getInteriorBegin() const; - - void - setInteriorEnd( const CoordinatesType& end ); - - __cuda_callable__ - const CoordinatesType& - getInteriorEnd() const; - - /** - * \brief Sets the origin. - * \param origin Starting point of this grid. - */ - void - setOrigin( const PointType& origin ); - - /** - * \brief Sets the origin and proportions of this grid. - * \param origin Point where this grid starts. - * \param proportions Total length of this grid. - */ - void - setDomain( const PointType& origin, const PointType& proportions ); - - /** - * \brief Returns the origin. - * \param origin Starting point of this grid. - */ - __cuda_callable__ - inline const PointType& - getOrigin() const; - - /** - * \brief Gets length of one entity of this grid. - */ - __cuda_callable__ - inline const PointType& - getProportions() const; - - /** - * \brief Gets number of entities in this grid. - * \tparam EntityDimension Integer specifying dimension of the entity. - */ template< int EntityDimension > - __cuda_callable__ - IndexType - getEntitiesCount() const; + using EntityType = GridEntity< Grid, EntityDimension >; - /** - * \brief Gets number of entities in this grid. - * \tparam Entity Type of the entity. - */ - template< typename Entity > - __cuda_callable__ - IndexType - getEntitiesCount() const; + using Base = NDimGrid< 1, Real, Device, Index >; + using Coordinate = typename Base::Coordinate; + using Point = typename Base::Point; + using EntitiesCounts = typename Base::EntitiesCounts; - /** - * \brief Gets entity type using entity index. - * \param entityIndex Index of entity. - * \tparam Entity Type of the entity. - */ - template< typename Entity > - __cuda_callable__ - inline Entity - getEntity( const IndexType& entityIndex ) const; + Grid() = default; + Grid( const Index xSize ); /** - * \brief Gets entity index using entity type. + * @brief Gets entity index using entity type. * \param entity Type of entity. * \tparam Entity Type of the entity. */ @@ -171,72 +40,55 @@ public: getEntityIndex( const Entity& entity ) const; /** - * \brief Returns the length of one step. + * @brief Traverser all elements in rect */ - __cuda_callable__ - inline const PointType& - getSpaceSteps() const; + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + forAll( Func func, FuncArgs... args ) const; /** - * \brief Sets the length of steps. - * \param steps Length of one step. + * @brief Traverser all elements in rect + * @param from - bottom left anchor of traverse rect + * @param to - top right anchor of traverse rect */ + template< int EntityDimension, typename Func, typename... FuncArgs > inline void - setSpaceSteps( const PointType& steps ); + forAll( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const; /** - * \brief Returns product of space steps to the xPow. - * \tparam xPow Exponent. + * @brief Traverser interior elements in rect */ - template< int xPow > - __cuda_callable__ - const RealType& - getSpaceStepsProducts() const; + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + forInterior( Func func, FuncArgs... args ) const; /** - * \breif Returns the measure (length) of a cell in this grid. + * @brief Traverser interior elements + * @param from - bottom left anchor of traverse rect + * @param to - top right anchor of traverse rect */ - __cuda_callable__ - inline const RealType& - getCellMeasure() const; + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + forInterior( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const; /** - * \brief Returns the smallest length of step out of all coordinates (axes). + * @brief Traverser boundary elements in rect */ - __cuda_callable__ - inline RealType - getSmallestSpaceStep() const; - - void - writeProlog( Logger& logger ) const; - -protected: - void - computeProportions(); - - void - computeSpaceStepPowers(); - - void - computeSpaceSteps(); - - CoordinatesType dimensions = { 0 }; - CoordinatesType localBegin = { 0 }; - CoordinatesType localEnd = { 0 }; - CoordinatesType interiorBegin = { 0 }; - CoordinatesType interiorEnd = { 0 }; - - IndexType numberOfCells = 0; - IndexType numberOfVertices = 0; - - PointType origin = { 0 }; - PointType proportions = { 0 }; - PointType spaceSteps = { 0 }; + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + forBoundary( Func func, FuncArgs... args ) const; - RealType spaceStepsProducts[ 5 ]; + /** + * @brief Traverser boundary elements in rect + * @param from - bottom left anchor of traverse rect + * @param to - top right anchor of traverse rect + */ + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + forBoundary( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const; }; } // namespace Meshes } // namespace TNL -#include +#include diff --git a/src/TNL/Meshes/GridDetails/Grid1D_impl.h b/src/TNL/Meshes/GridDetails/Grid1D_impl.h deleted file mode 100644 index 7deb52e22b8ce8e5c350b747b2bead7ddb19c161..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/Grid1D_impl.h +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -namespace TNL { -namespace Meshes { - -template< typename Real, typename Device, typename Index > -Grid< 1, Real, Device, Index >::Grid( Index xSize ) -{ - this->setDimensions( xSize ); -} - -template< typename Real, typename Device, typename Index > -void -Grid< 1, Real, Device, Index >::computeSpaceSteps() -{ - if( this->getDimensions().x() != 0 ) { - this->spaceSteps.x() = this->proportions.x() / (Real) this->getDimensions().x(); - this->computeSpaceStepPowers(); - } -} - -template< typename Real, typename Device, typename Index > -void -Grid< 1, Real, Device, Index >::computeSpaceStepPowers() -{ - const RealType& hx = this->spaceSteps.x(); - this->spaceStepsProducts[ 0 ] = 1.0 / ( hx * hx ); - this->spaceStepsProducts[ 1 ] = 1.0 / hx; - this->spaceStepsProducts[ 2 ] = 1.0; - this->spaceStepsProducts[ 3 ] = hx; - this->spaceStepsProducts[ 4 ] = hx * hx; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 1, Real, Device, Index >::computeProportions() -{ - this->proportions.x() = this->dimensions.x() * this->spaceSteps.x(); -} - -template< typename Real, typename Device, typename Index > -void -Grid< 1, Real, Device, Index >::setOrigin( const PointType& origin ) -{ - this->origin = origin; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 1, Real, Device, Index >::setDimensions( Index xSize ) -{ - TNL_ASSERT_GE( xSize, 0, "Grid size must be non-negative." ); - this->dimensions.x() = xSize; - this->numberOfCells = xSize; - this->numberOfVertices = xSize + 1; - computeSpaceSteps(); - - // only default behaviour, DistributedGrid must use the setters explicitly after setDimensions - localBegin = 0; - interiorBegin = 1; - localEnd = dimensions; - interiorEnd = dimensions - 1; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 1, Real, Device, Index >::setDimensions( const CoordinatesType& dimensions ) -{ - this->setDimensions( dimensions.x() ); -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -inline const typename Grid< 1, Real, Device, Index >::CoordinatesType& -Grid< 1, Real, Device, Index >::getDimensions() const -{ - return this->dimensions; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 1, Real, Device, Index >::setLocalBegin( const CoordinatesType& begin ) -{ - localBegin = begin; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -const typename Grid< 1, Real, Device, Index >::CoordinatesType& -Grid< 1, Real, Device, Index >::getLocalBegin() const -{ - return localBegin; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 1, Real, Device, Index >::setLocalEnd( const CoordinatesType& end ) -{ - localEnd = end; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -const typename Grid< 1, Real, Device, Index >::CoordinatesType& -Grid< 1, Real, Device, Index >::getLocalEnd() const -{ - return localEnd; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 1, Real, Device, Index >::setInteriorBegin( const CoordinatesType& begin ) -{ - interiorBegin = begin; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -const typename Grid< 1, Real, Device, Index >::CoordinatesType& -Grid< 1, Real, Device, Index >::getInteriorBegin() const -{ - return interiorBegin; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 1, Real, Device, Index >::setInteriorEnd( const CoordinatesType& end ) -{ - interiorEnd = end; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -const typename Grid< 1, Real, Device, Index >::CoordinatesType& -Grid< 1, Real, Device, Index >::getInteriorEnd() const -{ - return interiorEnd; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 1, Real, Device, Index >::setDomain( const PointType& origin, const PointType& proportions ) -{ - this->origin = origin; - this->proportions = proportions; - computeSpaceSteps(); -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -inline const typename Grid< 1, Real, Device, Index >::PointType& -Grid< 1, Real, Device, Index >::getOrigin() const -{ - return this->origin; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -inline const typename Grid< 1, Real, Device, Index >::PointType& -Grid< 1, Real, Device, Index >::getProportions() const -{ - return this->proportions; -} - -template< typename Real, typename Device, typename Index > -template< int EntityDimension > -__cuda_callable__ -inline Index -Grid< 1, Real, Device, Index >::getEntitiesCount() const -{ - static_assert( EntityDimension <= 1 && EntityDimension >= 0, "Wrong grid entity dimensions." ); - - switch( EntityDimension ) { - case 1: - return this->numberOfCells; - case 0: - return this->numberOfVertices; - } - return -1; -} - -template< typename Real, typename Device, typename Index > -template< typename Entity > -__cuda_callable__ -inline Index -Grid< 1, Real, Device, Index >::getEntitiesCount() const -{ - return getEntitiesCount< Entity::getEntityDimension() >(); -} - -template< typename Real, typename Device, typename Index > -template< typename Entity > -__cuda_callable__ -inline Entity -Grid< 1, Real, Device, Index >::getEntity( const IndexType& entityIndex ) const -{ - static_assert( Entity::getEntityDimension() <= 1 && Entity::getEntityDimension() >= 0, "Wrong grid entity dimensions." ); - - return GridEntityGetter< Grid, Entity >::getEntity( *this, entityIndex ); -} - -template< typename Real, typename Device, typename Index > -template< typename Entity > -__cuda_callable__ -inline Index -Grid< 1, Real, Device, Index >::getEntityIndex( const Entity& entity ) const -{ - static_assert( Entity::getEntityDimension() <= 1 && Entity::getEntityDimension() >= 0, "Wrong grid entity dimensions." ); - - return GridEntityGetter< Grid, Entity >::getEntityIndex( *this, entity ); -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -inline const typename Grid< 1, Real, Device, Index >::PointType& -Grid< 1, Real, Device, Index >::getSpaceSteps() const -{ - return this->spaceSteps; -} - -template< typename Real, typename Device, typename Index > -inline void -Grid< 1, Real, Device, Index >::setSpaceSteps( const typename Grid< 1, Real, Device, Index >::PointType& steps ) -{ - this->spaceSteps = steps; - computeSpaceStepPowers(); - computeProportions(); -} - -template< typename Real, typename Device, typename Index > -template< int xPow > -__cuda_callable__ -inline const Real& -Grid< 1, Real, Device, Index >::getSpaceStepsProducts() const -{ - static_assert( xPow >= -2 && xPow <= 2, "unsupported value of xPow" ); - return this->spaceStepsProducts[ xPow + 2 ]; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -const Real& -Grid< 1, Real, Device, Index >::getCellMeasure() const -{ - return this->template getSpaceStepsProducts< 1 >(); -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -inline Real -Grid< 1, Real, Device, Index >::getSmallestSpaceStep() const -{ - return this->spaceSteps.x(); -} - -template< typename Real, typename Device, typename Index > -void -Grid< 1, Real, Device, Index >::writeProlog( Logger& logger ) const -{ - logger.writeParameter( "Dimension:", getMeshDimension() ); - logger.writeParameter( "Domain origin:", this->origin ); - logger.writeParameter( "Domain proportions:", this->proportions ); - logger.writeParameter( "Domain dimensions:", this->dimensions ); - logger.writeParameter( "Space steps:", this->getSpaceSteps() ); - logger.writeParameter( "Number of cells:", getEntitiesCount< Cell >() ); - logger.writeParameter( "Number of vertices:", getEntitiesCount< Vertex >() ); -} - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Grid2D.h b/src/TNL/Meshes/GridDetails/Grid2D.h index 17eb80837d582678e4f1f28c90cd2c7a68def34c..8453cd121354466e161099fa651962dc78597108 100644 --- a/src/TNL/Meshes/GridDetails/Grid2D.h +++ b/src/TNL/Meshes/GridDetails/Grid2D.h @@ -6,153 +6,34 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include +#include namespace TNL { namespace Meshes { +template< class, int > +class GridEntity; + template< typename Real, typename Device, typename Index > -class Grid< 2, Real, Device, Index > +class Grid< 2, Real, Device, Index > : public NDimGrid< 2, Real, Device, Index > { public: - using RealType = Real; - using DeviceType = Device; - using GlobalIndexType = Index; - using PointType = Containers::StaticVector< 2, Real >; - using CoordinatesType = Containers::StaticVector< 2, Index >; - - // TODO: deprecated and to be removed (GlobalIndexType shall be used instead) - using IndexType = Index; - - static constexpr int - getMeshDimension() - { - return 2; - }; + template< int EntityDimension > + using EntityType = GridEntity< Grid, EntityDimension >; - template< int EntityDimension, typename Config = GridEntityCrossStencilStorage< 1 > > - using EntityType = GridEntity< Grid, EntityDimension, Config >; + using Base = NDimGrid< 2, Real, Device, Index >; + using Coordinate = typename Base::Coordinate; + using Point = typename Base::Point; + using EntitiesCounts = typename Base::EntitiesCounts; - using Cell = EntityType< getMeshDimension(), GridEntityCrossStencilStorage< 1 > >; - using Face = EntityType< getMeshDimension() - 1 >; - using Vertex = EntityType< 0 >; + ///////////////////////////// + // Compatability with meshes + using Vertex = EntityType<0>; + using Cell = EntityType<2>; + ///////////////////////////// - /** - * \brief See Grid1D::Grid(). - */ Grid() = default; - - Grid( Index xSize, Index ySize ); - - // empty destructor is needed only to avoid crappy nvcc warnings - ~Grid() = default; - - /** - * \brief Sets the size of dimensions. - * \param xSize Size of dimension x. - * \param ySize Size of dimension y. - */ - void - setDimensions( Index xSize, Index ySize ); - - /** - * \brief See Grid1D::setDimensions( const CoordinatesType& dimensions ). - */ - void - setDimensions( const CoordinatesType& dimensions ); - - /** - * \brief See Grid1D::getDimensions(). - */ - __cuda_callable__ - const CoordinatesType& - getDimensions() const; - - void - setLocalBegin( const CoordinatesType& begin ); - - __cuda_callable__ - const CoordinatesType& - getLocalBegin() const; - - void - setLocalEnd( const CoordinatesType& end ); - - __cuda_callable__ - const CoordinatesType& - getLocalEnd() const; - - void - setInteriorBegin( const CoordinatesType& begin ); - - __cuda_callable__ - const CoordinatesType& - getInteriorBegin() const; - - void - setInteriorEnd( const CoordinatesType& end ); - - __cuda_callable__ - const CoordinatesType& - getInteriorEnd() const; - - /** - * \brief See Grid1D::setDomain(). - */ - void - setDomain( const PointType& origin, const PointType& proportions ); - - /** - * \brief See Grid1D::setOrigin() - */ - void - setOrigin( const PointType& origin ); - - /** - * \brief See Grid1D::getOrigin(). - */ - __cuda_callable__ - inline const PointType& - getOrigin() const; - - /** - * \brief See Grid1D::getProportions(). - */ - __cuda_callable__ - inline const PointType& - getProportions() const; - - /** - * \brief Gets number of entities in this grid. - * \tparam EntityDimension Integer specifying dimension of the entity. - */ - template< int EntityDimension > - __cuda_callable__ - IndexType - getEntitiesCount() const; - - /** - * \brief Gets number of entities in this grid. - * \tparam Entity Type of the entity. - */ - template< typename Entity > - __cuda_callable__ - inline IndexType - getEntitiesCount() const; - - /** - * \brief See Grid1D::getEntity(). - */ - template< typename Entity > - __cuda_callable__ - inline Entity - getEntity( const IndexType& entityIndex ) const; + Grid( const Index xSize, const Index ySize ); /** * \brief See Grid1D::getEntityIndex(). @@ -163,87 +44,55 @@ public: getEntityIndex( const Entity& entity ) const; /** - * \brief See Grid1D::getSpaceSteps(). + * @brief Traverser all elements in rect */ - __cuda_callable__ - inline const PointType& - getSpaceSteps() const; + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + forAll( Func func, FuncArgs... args ) const; /** - * \brief See Grid1D::setSpaceSteps(). + * @brief Traverser all elements in rect + * @param from - bottom left anchor of traverse rect + * @param to - top right anchor of traverse rect */ + template< int EntityDimension, typename Func, typename... FuncArgs > inline void - setSpaceSteps( const PointType& steps ); + forAll( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const; /** - * \brief Returns product of space steps to the xPow. - * \tparam xPow Exponent for dimension x. - * \tparam yPow Exponent for dimension y. + * @brief Traverser interior elements in rect */ - template< int xPow, int yPow > - __cuda_callable__ - const RealType& - getSpaceStepsProducts() const; + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + forInterior( Func func, FuncArgs... args ) const; /** - * \brief Returns the number of x-normal faces. + * @brief Traverser interior elements + * @param from - bottom left anchor of traverse rect + * @param to - top right anchor of traverse rect */ - __cuda_callable__ - IndexType - getNumberOfNxFaces() const; + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + forInterior( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const; /** - * \breif Returns the measure (area) of a cell in this grid. + * @brief Traverser boundary elements in rect */ - __cuda_callable__ - inline const RealType& - getCellMeasure() const; + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + forBoundary( Func func, FuncArgs... args ) const; /** - * \brief See Grid1D::getSmallestSpaceStep(). + * @brief Traverser boundary elements in rect + * @param from - bottom left anchor of traverse rect + * @param to - top right anchor of traverse rect */ - __cuda_callable__ - inline RealType - getSmallestSpaceStep() const; - - void - writeProlog( Logger& logger ) const; - -protected: - void - computeProportions(); - - __cuda_callable__ - void - computeSpaceStepPowers(); - - __cuda_callable__ - void - computeSpaceSteps(); - - CoordinatesType dimensions = { 0, 0 }; - CoordinatesType localBegin = { 0, 0 }; - CoordinatesType localEnd = { 0, 0 }; - CoordinatesType interiorBegin = { 0, 0 }; - CoordinatesType interiorEnd = { 0, 0 }; - - IndexType numberOfCells = 0; - IndexType numberOfNxFaces = 0; - IndexType numberOfNyFaces = 0; - IndexType numberOfFaces = 0; - IndexType numberOfVertices = 0; - - PointType origin = { 0, 0 }; - PointType proportions = { 0, 0 }; - PointType spaceSteps = { 0, 0 }; - - RealType spaceStepsProducts[ 5 ][ 5 ]; - - template< typename, typename, int > - friend class GridEntityGetter; + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + forBoundary( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const; }; } // namespace Meshes } // namespace TNL -#include +#include diff --git a/src/TNL/Meshes/GridDetails/Grid2D_impl.h b/src/TNL/Meshes/GridDetails/Grid2D_impl.h deleted file mode 100644 index 91b45bec83dee72f2f519b63af3fb243930e28f6..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/Grid2D_impl.h +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -namespace TNL { -namespace Meshes { - -template< typename Real, typename Device, typename Index > -Grid< 2, Real, Device, Index >::Grid( Index xSize, Index ySize ) -{ - this->setDimensions( xSize, ySize ); -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -void -Grid< 2, Real, Device, Index >::computeSpaceSteps() -{ - if( this->getDimensions().x() > 0 && this->getDimensions().y() > 0 ) { - this->spaceSteps.x() = this->proportions.x() / (Real) this->getDimensions().x(); - this->spaceSteps.y() = this->proportions.y() / (Real) this->getDimensions().y(); - this->computeSpaceStepPowers(); - } -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -void -Grid< 2, Real, Device, Index >::computeSpaceStepPowers() -{ - const RealType& hx = this->spaceSteps.x(); - const RealType& hy = this->spaceSteps.y(); - - Real auxX; - Real auxY; - for( int i = 0; i < 5; i++ ) { - switch( i ) { - case 0: - auxX = 1.0 / ( hx * hx ); - break; - case 1: - auxX = 1.0 / hx; - break; - case 2: - auxX = 1.0; - break; - case 3: - auxX = hx; - break; - case 4: - auxX = hx * hx; - break; - } - for( int j = 0; j < 5; j++ ) { - switch( j ) { - case 0: - auxY = 1.0 / ( hy * hy ); - break; - case 1: - auxY = 1.0 / hy; - break; - case 2: - auxY = 1.0; - break; - case 3: - auxY = hy; - break; - case 4: - auxY = hy * hy; - break; - } - this->spaceStepsProducts[ i ][ j ] = auxX * auxY; - } - } -} - -template< typename Real, typename Device, typename Index > -void -Grid< 2, Real, Device, Index >::computeProportions() -{ - this->proportions.x() = this->dimensions.x() * this->spaceSteps.x(); - this->proportions.y() = this->dimensions.y() * this->spaceSteps.y(); -} - -template< typename Real, typename Device, typename Index > -void -Grid< 2, Real, Device, Index >::setDimensions( Index xSize, Index ySize ) -{ - TNL_ASSERT_GE( xSize, 0, "Grid size must be non-negative." ); - TNL_ASSERT_GE( ySize, 0, "Grid size must be non-negative." ); - - this->dimensions.x() = xSize; - this->dimensions.y() = ySize; - this->numberOfCells = xSize * ySize; - this->numberOfNxFaces = ySize * ( xSize + 1 ); - this->numberOfNyFaces = xSize * ( ySize + 1 ); - this->numberOfFaces = this->numberOfNxFaces + this->numberOfNyFaces; - this->numberOfVertices = ( xSize + 1 ) * ( ySize + 1 ); - computeSpaceSteps(); - - // only default behaviour, DistributedGrid must use the setters explicitly after setDimensions - localBegin = 0; - interiorBegin = 1; - localEnd = dimensions; - interiorEnd = dimensions - 1; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 2, Real, Device, Index >::setDimensions( const CoordinatesType& dimensions ) -{ - return this->setDimensions( dimensions.x(), dimensions.y() ); -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -inline const typename Grid< 2, Real, Device, Index >::CoordinatesType& -Grid< 2, Real, Device, Index >::getDimensions() const -{ - return this->dimensions; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 2, Real, Device, Index >::setLocalBegin( const CoordinatesType& begin ) -{ - localBegin = begin; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -const typename Grid< 2, Real, Device, Index >::CoordinatesType& -Grid< 2, Real, Device, Index >::getLocalBegin() const -{ - return localBegin; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 2, Real, Device, Index >::setLocalEnd( const CoordinatesType& end ) -{ - localEnd = end; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -const typename Grid< 2, Real, Device, Index >::CoordinatesType& -Grid< 2, Real, Device, Index >::getLocalEnd() const -{ - return localEnd; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 2, Real, Device, Index >::setInteriorBegin( const CoordinatesType& begin ) -{ - interiorBegin = begin; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -const typename Grid< 2, Real, Device, Index >::CoordinatesType& -Grid< 2, Real, Device, Index >::getInteriorBegin() const -{ - return interiorBegin; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 2, Real, Device, Index >::setInteriorEnd( const CoordinatesType& end ) -{ - interiorEnd = end; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -const typename Grid< 2, Real, Device, Index >::CoordinatesType& -Grid< 2, Real, Device, Index >::getInteriorEnd() const -{ - return interiorEnd; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 2, Real, Device, Index >::setDomain( const PointType& origin, const PointType& proportions ) -{ - this->origin = origin; - this->proportions = proportions; - computeSpaceSteps(); -} - -template< typename Real, typename Device, typename Index > -void -Grid< 2, Real, Device, Index >::setOrigin( const PointType& origin ) -{ - this->origin = origin; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -inline const typename Grid< 2, Real, Device, Index >::PointType& -Grid< 2, Real, Device, Index >::getOrigin() const -{ - return this->origin; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -inline const typename Grid< 2, Real, Device, Index >::PointType& -Grid< 2, Real, Device, Index >::getProportions() const -{ - return this->proportions; -} - -template< typename Real, typename Device, typename Index > -template< int EntityDimension > -__cuda_callable__ -inline Index -Grid< 2, Real, Device, Index >::getEntitiesCount() const -{ - static_assert( EntityDimension <= 2 && EntityDimension >= 0, "Wrong grid entity dimensions." ); - - switch( EntityDimension ) { - case 2: - return this->numberOfCells; - case 1: - return this->numberOfFaces; - case 0: - return this->numberOfVertices; - } - return -1; -} - -template< typename Real, typename Device, typename Index > -template< typename Entity > -__cuda_callable__ -inline Index -Grid< 2, Real, Device, Index >::getEntitiesCount() const -{ - return getEntitiesCount< Entity::getEntityDimension() >(); -} - -template< typename Real, typename Device, typename Index > -template< typename Entity > -__cuda_callable__ -inline Entity -Grid< 2, Real, Device, Index >::getEntity( const IndexType& entityIndex ) const -{ - static_assert( Entity::getEntityDimension() <= 2 && Entity::getEntityDimension() >= 0, "Wrong grid entity dimensions." ); - - return GridEntityGetter< Grid, Entity >::getEntity( *this, entityIndex ); -} - -template< typename Real, typename Device, typename Index > -template< typename Entity > -__cuda_callable__ -inline Index -Grid< 2, Real, Device, Index >::getEntityIndex( const Entity& entity ) const -{ - static_assert( Entity::getEntityDimension() <= 2 && Entity::getEntityDimension() >= 0, "Wrong grid entity dimensions." ); - - return GridEntityGetter< Grid, Entity >::getEntityIndex( *this, entity ); -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -inline const typename Grid< 2, Real, Device, Index >::PointType& -Grid< 2, Real, Device, Index >::getSpaceSteps() const -{ - return this->spaceSteps; -} - -template< typename Real, typename Device, typename Index > -inline void -Grid< 2, Real, Device, Index >::setSpaceSteps( const typename Grid< 2, Real, Device, Index >::PointType& steps ) -{ - this->spaceSteps = steps; - computeSpaceStepPowers(); - computeProportions(); -} - -template< typename Real, typename Device, typename Index > -template< int xPow, int yPow > -__cuda_callable__ -inline const Real& -Grid< 2, Real, Device, Index >::getSpaceStepsProducts() const -{ - static_assert( xPow >= -2 && xPow <= 2, "unsupported value of xPow" ); - static_assert( yPow >= -2 && yPow <= 2, "unsupported value of yPow" ); - return this->spaceStepsProducts[ xPow + 2 ][ yPow + 2 ]; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -Index -Grid< 2, Real, Device, Index >::getNumberOfNxFaces() const -{ - return numberOfNxFaces; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -const Real& -Grid< 2, Real, Device, Index >::getCellMeasure() const -{ - return this->template getSpaceStepsProducts< 1, 1 >(); -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -inline Real -Grid< 2, Real, Device, Index >::getSmallestSpaceStep() const -{ - return min( this->spaceSteps.x(), this->spaceSteps.y() ); -} - -template< typename Real, typename Device, typename Index > -void -Grid< 2, Real, Device, Index >::writeProlog( Logger& logger ) const -{ - logger.writeParameter( "Dimension:", getMeshDimension() ); - logger.writeParameter( "Domain origin:", this->origin ); - logger.writeParameter( "Domain proportions:", this->proportions ); - logger.writeParameter( "Domain dimensions:", this->dimensions ); - logger.writeParameter( "Space steps:", this->getSpaceSteps() ); - logger.writeParameter( "Number of cells:", getEntitiesCount< Cell >() ); - logger.writeParameter( "Number of faces:", getEntitiesCount< Face >() ); - logger.writeParameter( "Number of vertices:", getEntitiesCount< Vertex >() ); -} - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Grid3D.h b/src/TNL/Meshes/GridDetails/Grid3D.h index 0ec5144f62f788624837ee15bfb20acb03240c65..75319a5e69060d85400b3ae1a16d9da893dce80c 100644 --- a/src/TNL/Meshes/GridDetails/Grid3D.h +++ b/src/TNL/Meshes/GridDetails/Grid3D.h @@ -6,263 +6,89 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include +#include namespace TNL { namespace Meshes { +template< class, int > +class GridEntity; + template< typename Real, typename Device, typename Index > -class Grid< 3, Real, Device, Index > +class Grid< 3, Real, Device, Index > : public NDimGrid< 3, Real, Device, Index > { public: - using RealType = Real; - using DeviceType = Device; - using GlobalIndexType = Index; - using PointType = Containers::StaticVector< 3, Real >; - using CoordinatesType = Containers::StaticVector< 3, Index >; - - // TODO: deprecated and to be removed (GlobalIndexType shall be used instead) - using IndexType = Index; - - static constexpr int - getMeshDimension() - { - return 3; - }; - - template< int EntityDimension, typename Config = GridEntityCrossStencilStorage< 1 > > - using EntityType = GridEntity< Grid, EntityDimension, Config >; + template< int EntityDimension > + using EntityType = GridEntity< Grid, EntityDimension >; - using Cell = EntityType< getMeshDimension(), GridEntityCrossStencilStorage< 1 > >; - using Face = EntityType< getMeshDimension() - 1 >; - using Edge = EntityType< 1 >; - using Vertex = EntityType< 0 >; + using Base = NDimGrid< 3, Real, Device, Index >; + using Coordinate = typename Base::Coordinate; + using Point = typename Base::Point; + using EntitiesCounts = typename Base::EntitiesCounts; - /** - * \brief See Grid1D::Grid(). - */ Grid() = default; - - Grid( Index xSize, Index ySize, Index zSize ); - - // empty destructor is needed only to avoid crappy nvcc warnings - ~Grid() = default; - - /** - * \brief Sets the size of dimensions. - * \param xSize Size of dimesion x. - * \param ySize Size of dimesion y. - * \param zSize Size of dimesion z. - */ - void - setDimensions( Index xSize, Index ySize, Index zSize ); - - /** - * \brief See Grid1D::setDimensions( const CoordinatesType& dimensions ). - */ - void - setDimensions( const CoordinatesType& dimensions ); - - /** - * \brief See Grid1D::getDimensions(). - */ - __cuda_callable__ - const CoordinatesType& - getDimensions() const; - - void - setLocalBegin( const CoordinatesType& begin ); - - __cuda_callable__ - const CoordinatesType& - getLocalBegin() const; - - void - setLocalEnd( const CoordinatesType& end ); - - __cuda_callable__ - const CoordinatesType& - getLocalEnd() const; - - void - setInteriorBegin( const CoordinatesType& begin ); - - __cuda_callable__ - const CoordinatesType& - getInteriorBegin() const; - - void - setInteriorEnd( const CoordinatesType& end ); - - __cuda_callable__ - const CoordinatesType& - getInteriorEnd() const; - - /** - * \brief See Grid1D::setDomain(). - */ - void - setDomain( const PointType& origin, const PointType& proportions ); - - /** - * \brief See Grid1D::setOrigin() - */ - void - setOrigin( const PointType& origin ); - - /** - * \brief See Grid1D::getOrigin(). - */ - __cuda_callable__ - inline const PointType& - getOrigin() const; - - /** - * \brief See Grid1D::getProportions(). - */ - __cuda_callable__ - inline const PointType& - getProportions() const; + Grid( const Index xSize, const Index ySize, const Index zSize ); /** - * \brief Gets number of entities in this grid. - * \tparam EntityDimension Integer specifying dimension of the entity. - */ - template< int EntityDimension > - __cuda_callable__ - IndexType - getEntitiesCount() const; - - /** - * \brief Gets number of entities in this grid. + * @brief Gets entity index using entity type. + * \param entity Type of entity. * \tparam Entity Type of the entity. */ template< typename Entity > __cuda_callable__ - IndexType - getEntitiesCount() const; - - /** - * \brief See Grid1D::getEntity(). - */ - template< typename Entity > - __cuda_callable__ - inline Entity - getEntity( const IndexType& entityIndex ) const; - - /** - * \brief See Grid1D::getEntityIndex(). - */ - template< typename Entity > - __cuda_callable__ inline Index getEntityIndex( const Entity& entity ) const; /** - * \brief See Grid1D::getSpaceSteps(). - */ - __cuda_callable__ - inline const PointType& - getSpaceSteps() const; - - /** - * \brief See Grid1D::setSpaceSteps(). + * @brief Traverser all elements in rect */ + template< int EntityDimension, typename Func, typename... FuncArgs > inline void - setSpaceSteps( const PointType& steps ); + forAll( Func func, FuncArgs... args ) const; /** - * \brief Returns product of space steps to the xPow. - * \tparam xPow Exponent for dimension x. - * \tparam yPow Exponent for dimension y. - * \tparam zPow Exponent for dimension z. + * @brief Traverser all elements in rect + * @param from - bottom left anchor of traverse rect + * @param to - top right anchor of traverse rect */ - template< int xPow, int yPow, int zPow > - __cuda_callable__ - const RealType& - getSpaceStepsProducts() const; + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + forAll( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const; /** - * \brief Returns the number of x-normal faces. + * @brief Traverser interior elements in rect */ - __cuda_callable__ - IndexType - getNumberOfNxFaces() const; + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + forInterior( Func func, FuncArgs... args ) const; /** - * \brief Returns the number of x-normal and y-normal faces. + * @brief Traverser interior elements + * @param from - bottom left anchor of traverse rect + * @param to - top right anchor of traverse rect */ - __cuda_callable__ - IndexType - getNumberOfNxAndNyFaces() const; + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + forInterior( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const; /** - * \breif Returns the measure (volume) of a cell in this grid. + * @brief Traverser boundary elements in rect */ - __cuda_callable__ - inline const RealType& - getCellMeasure() const; + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + forBoundary( Func func, FuncArgs... args ) const; /** - * \brief See Grid1D::getSmallestSpaceStep(). + * @brief Traverser boundary elements in rect + * @param from - bottom left anchor of traverse rect + * @param to - top right anchor of traverse rect */ - __cuda_callable__ - RealType - getSmallestSpaceStep() const; - - void - writeProlog( Logger& logger ) const; - -protected: - void - computeProportions(); - - void - computeSpaceStepPowers(); - - void - computeSpaceSteps(); - - CoordinatesType dimensions = { 0, 0, 0 }; - CoordinatesType localBegin = { 0, 0, 0 }; - CoordinatesType localEnd = { 0, 0, 0 }; - CoordinatesType interiorBegin = { 0, 0, 0 }; - CoordinatesType interiorEnd = { 0, 0, 0 }; - - IndexType numberOfCells = 0; - IndexType numberOfNxFaces = 0; - IndexType numberOfNyFaces = 0; - IndexType numberOfNzFaces = 0; - IndexType numberOfNxAndNyFaces = 0; - IndexType numberOfFaces = 0; - IndexType numberOfDxEdges = 0; - IndexType numberOfDyEdges = 0; - IndexType numberOfDzEdges = 0; - IndexType numberOfDxAndDyEdges = 0; - IndexType numberOfEdges = 0; - IndexType numberOfVertices = 0; - IndexType cellZNeighborsStep = 0; - - PointType origin = { 0, 0, 0 }; - PointType proportions = { 0, 0, 0 }; - PointType spaceSteps = { 0, 0, 0 }; - - RealType spaceStepsProducts[ 5 ][ 5 ][ 5 ]; - - template< typename, typename, int > - friend class GridEntityGetter; - - template< typename, int, typename > - friend class NeighborGridEntityGetter; + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + forBoundary( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const; }; } // namespace Meshes } // namespace TNL -#include +#include diff --git a/src/TNL/Meshes/GridDetails/Grid3D_impl.h b/src/TNL/Meshes/GridDetails/Grid3D_impl.h deleted file mode 100644 index 671afcf4e80c2e11a6abfbc7ba1903bbd14151cc..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/Grid3D_impl.h +++ /dev/null @@ -1,389 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -namespace TNL { -namespace Meshes { - -template< typename Real, typename Device, typename Index > -Grid< 3, Real, Device, Index >::Grid( Index xSize, Index ySize, Index zSize ) -{ - this->setDimensions( xSize, ySize, zSize ); -} - -template< typename Real, typename Device, typename Index > -void -Grid< 3, Real, Device, Index >::computeSpaceSteps() -{ - if( this->getDimensions().x() > 0 && this->getDimensions().y() > 0 && this->getDimensions().z() > 0 ) { - this->spaceSteps.x() = this->proportions.x() / (Real) this->getDimensions().x(); - this->spaceSteps.y() = this->proportions.y() / (Real) this->getDimensions().y(); - this->spaceSteps.z() = this->proportions.z() / (Real) this->getDimensions().z(); - - this->computeSpaceStepPowers(); - } -}; - -template< typename Real, typename Device, typename Index > -void -Grid< 3, Real, Device, Index >::computeSpaceStepPowers() -{ - const RealType& hx = this->spaceSteps.x(); - const RealType& hy = this->spaceSteps.y(); - const RealType& hz = this->spaceSteps.z(); - - Real auxX; - Real auxY; - Real auxZ; - for( int i = 0; i < 5; i++ ) { - switch( i ) { - case 0: - auxX = 1.0 / ( hx * hx ); - break; - case 1: - auxX = 1.0 / hx; - break; - case 2: - auxX = 1.0; - break; - case 3: - auxX = hx; - break; - case 4: - auxX = hx * hx; - break; - } - for( int j = 0; j < 5; j++ ) { - switch( j ) { - case 0: - auxY = 1.0 / ( hy * hy ); - break; - case 1: - auxY = 1.0 / hy; - break; - case 2: - auxY = 1.0; - break; - case 3: - auxY = hy; - break; - case 4: - auxY = hy * hy; - break; - } - for( int k = 0; k < 5; k++ ) { - switch( k ) { - case 0: - auxZ = 1.0 / ( hz * hz ); - break; - case 1: - auxZ = 1.0 / hz; - break; - case 2: - auxZ = 1.0; - break; - case 3: - auxZ = hz; - break; - case 4: - auxZ = hz * hz; - break; - } - this->spaceStepsProducts[ i ][ j ][ k ] = auxX * auxY * auxZ; - } - } - } -} - -template< typename Real, typename Device, typename Index > -void -Grid< 3, Real, Device, Index >::computeProportions() -{ - this->proportions.x() = this->dimensions.x() * this->spaceSteps.x(); - this->proportions.y() = this->dimensions.y() * this->spaceSteps.y(); - this->proportions.z() = this->dimensions.z() * this->spaceSteps.z(); -} - -template< typename Real, typename Device, typename Index > -void -Grid< 3, Real, Device, Index >::setOrigin( const PointType& origin ) -{ - this->origin = origin; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 3, Real, Device, Index >::setSpaceSteps( const PointType& steps ) -{ - this->spaceSteps = steps; - computeSpaceStepPowers(); - computeProportions(); -} - -template< typename Real, typename Device, typename Index > -void -Grid< 3, Real, Device, Index >::setDimensions( Index xSize, Index ySize, Index zSize ) -{ - TNL_ASSERT_GE( xSize, 0, "Grid size must be non-negative." ); - TNL_ASSERT_GE( ySize, 0, "Grid size must be non-negative." ); - TNL_ASSERT_GE( zSize, 0, "Grid size must be non-negative." ); - - this->dimensions.x() = xSize; - this->dimensions.y() = ySize; - this->dimensions.z() = zSize; - this->numberOfCells = xSize * ySize * zSize; - this->numberOfNxFaces = ( xSize + 1 ) * ySize * zSize; - this->numberOfNyFaces = xSize * ( ySize + 1 ) * zSize; - this->numberOfNzFaces = xSize * ySize * ( zSize + 1 ); - this->numberOfNxAndNyFaces = this->numberOfNxFaces + this->numberOfNyFaces; - this->numberOfFaces = this->numberOfNxFaces + this->numberOfNyFaces + this->numberOfNzFaces; - this->numberOfDxEdges = xSize * ( ySize + 1 ) * ( zSize + 1 ); - this->numberOfDyEdges = ( xSize + 1 ) * ySize * ( zSize + 1 ); - this->numberOfDzEdges = ( xSize + 1 ) * ( ySize + 1 ) * zSize; - this->numberOfDxAndDyEdges = this->numberOfDxEdges + this->numberOfDyEdges; - this->numberOfEdges = this->numberOfDxEdges + this->numberOfDyEdges + this->numberOfDzEdges; - this->numberOfVertices = ( xSize + 1 ) * ( ySize + 1 ) * ( zSize + 1 ); - - this->cellZNeighborsStep = xSize * ySize; - - computeSpaceSteps(); - - // only default behaviour, DistributedGrid must use the setters explicitly after setDimensions - localBegin = 0; - interiorBegin = 1; - localEnd = dimensions; - interiorEnd = dimensions - 1; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 3, Real, Device, Index >::setDimensions( const CoordinatesType& dimensions ) -{ - return this->setDimensions( dimensions.x(), dimensions.y(), dimensions.z() ); -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -inline const typename Grid< 3, Real, Device, Index >::CoordinatesType& -Grid< 3, Real, Device, Index >::getDimensions() const -{ - return this->dimensions; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 3, Real, Device, Index >::setLocalBegin( const CoordinatesType& begin ) -{ - localBegin = begin; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -const typename Grid< 3, Real, Device, Index >::CoordinatesType& -Grid< 3, Real, Device, Index >::getLocalBegin() const -{ - return localBegin; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 3, Real, Device, Index >::setLocalEnd( const CoordinatesType& end ) -{ - localEnd = end; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -const typename Grid< 3, Real, Device, Index >::CoordinatesType& -Grid< 3, Real, Device, Index >::getLocalEnd() const -{ - return localEnd; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 3, Real, Device, Index >::setInteriorBegin( const CoordinatesType& begin ) -{ - interiorBegin = begin; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -const typename Grid< 3, Real, Device, Index >::CoordinatesType& -Grid< 3, Real, Device, Index >::getInteriorBegin() const -{ - return interiorBegin; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 3, Real, Device, Index >::setInteriorEnd( const CoordinatesType& end ) -{ - interiorEnd = end; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -const typename Grid< 3, Real, Device, Index >::CoordinatesType& -Grid< 3, Real, Device, Index >::getInteriorEnd() const -{ - return interiorEnd; -} - -template< typename Real, typename Device, typename Index > -void -Grid< 3, Real, Device, Index >::setDomain( const PointType& origin, const PointType& proportions ) -{ - this->origin = origin; - this->proportions = proportions; - computeSpaceSteps(); -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -inline const typename Grid< 3, Real, Device, Index >::PointType& -Grid< 3, Real, Device, Index >::getOrigin() const -{ - return this->origin; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -inline const typename Grid< 3, Real, Device, Index >::PointType& -Grid< 3, Real, Device, Index >::getProportions() const -{ - return this->proportions; -} - -template< typename Real, typename Device, typename Index > -template< int EntityDimension > -__cuda_callable__ -inline Index -Grid< 3, Real, Device, Index >::getEntitiesCount() const -{ - static_assert( EntityDimension <= 3 && EntityDimension >= 0, "Wrong grid entity dimensions." ); - - switch( EntityDimension ) { - case 3: - return this->numberOfCells; - case 2: - return this->numberOfFaces; - case 1: - return this->numberOfEdges; - case 0: - return this->numberOfVertices; - } - return -1; -} - -template< typename Real, typename Device, typename Index > -template< typename Entity > -__cuda_callable__ -inline Index -Grid< 3, Real, Device, Index >::getEntitiesCount() const -{ - return getEntitiesCount< Entity::getEntityDimension() >(); -} - -template< typename Real, typename Device, typename Index > -template< typename Entity > -__cuda_callable__ -inline Entity -Grid< 3, Real, Device, Index >::getEntity( const IndexType& entityIndex ) const -{ - static_assert( Entity::getEntityDimension() <= 3 && Entity::getEntityDimension() >= 0, "Wrong grid entity dimensions." ); - - return GridEntityGetter< Grid, Entity >::getEntity( *this, entityIndex ); -} - -template< typename Real, typename Device, typename Index > -template< typename Entity > -__cuda_callable__ -inline Index -Grid< 3, Real, Device, Index >::getEntityIndex( const Entity& entity ) const -{ - static_assert( Entity::getEntityDimension() <= 3 && Entity::getEntityDimension() >= 0, "Wrong grid entity dimensions." ); - - return GridEntityGetter< Grid, Entity >::getEntityIndex( *this, entity ); -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -inline const typename Grid< 3, Real, Device, Index >::PointType& -Grid< 3, Real, Device, Index >::getSpaceSteps() const -{ - return this->spaceSteps; -} - -template< typename Real, typename Device, typename Index > -template< int xPow, int yPow, int zPow > -__cuda_callable__ -inline const Real& -Grid< 3, Real, Device, Index >::getSpaceStepsProducts() const -{ - static_assert( xPow >= -2 && xPow <= 2, "unsupported value of xPow" ); - static_assert( yPow >= -2 && yPow <= 2, "unsupported value of yPow" ); - static_assert( zPow >= -2 && zPow <= 2, "unsupported value of zPow" ); - return this->spaceStepsProducts[ xPow + 2 ][ yPow + 2 ][ zPow + 2 ]; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -Index -Grid< 3, Real, Device, Index >::getNumberOfNxFaces() const -{ - return numberOfNxFaces; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -Index -Grid< 3, Real, Device, Index >::getNumberOfNxAndNyFaces() const -{ - return numberOfNxAndNyFaces; -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -const Real& -Grid< 3, Real, Device, Index >::getCellMeasure() const -{ - return this->template getSpaceStepsProducts< 1, 1, 1 >(); -} - -template< typename Real, typename Device, typename Index > -__cuda_callable__ -inline Real -Grid< 3, Real, Device, Index >::getSmallestSpaceStep() const -{ - return min( this->spaceSteps.x(), min( this->spaceSteps.y(), this->spaceSteps.z() ) ); -} - -template< typename Real, typename Device, typename Index > -void -Grid< 3, Real, Device, Index >::writeProlog( Logger& logger ) const -{ - logger.writeParameter( "Dimension:", getMeshDimension() ); - logger.writeParameter( "Domain origin:", this->origin ); - logger.writeParameter( "Domain proportions:", this->proportions ); - logger.writeParameter( "Domain dimensions:", this->dimensions ); - logger.writeParameter( "Space steps:", this->getSpaceSteps() ); - logger.writeParameter( "Number of cells:", getEntitiesCount< Cell >() ); - logger.writeParameter( "Number of faces:", getEntitiesCount< Face >() ); - logger.writeParameter( "Number of vertices:", getEntitiesCount< Vertex >() ); -} - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/GridEntityCenterGetter.h b/src/TNL/Meshes/GridDetails/GridEntityCenterGetter.h index af30ce8f97d8cca270232d34acb5f1be43405393..d50a69625049e5559196f4be9ce36423543aa546 100644 --- a/src/TNL/Meshes/GridDetails/GridEntityCenterGetter.h +++ b/src/TNL/Meshes/GridDetails/GridEntityCenterGetter.h @@ -9,165 +9,13 @@ namespace TNL { namespace Meshes { -template< typename GridEntity > -class GridEntityCenterGetter -{}; +template< class, int > +class GridEntity; -/*** - * 1D grids - */ -template< typename Real, typename Device, typename Index, typename Config > -class GridEntityCenterGetter< GridEntity< Meshes::Grid< 1, Real, Device, Index >, 1, Config > > -{ -public: - using GridType = Meshes::Grid< 1, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, 1, Config >; - using PointType = typename GridType::PointType; - - __cuda_callable__ - inline static PointType - getEntityCenter( const GridEntityType& entity ) - { - const GridType& grid = entity.getMesh(); - return PointType( grid.getOrigin().x() + ( entity.getCoordinates().x() + 0.5 ) * grid.getSpaceSteps().x() ); - } -}; - -template< typename Real, typename Device, typename Index, typename Config > -class GridEntityCenterGetter< GridEntity< Meshes::Grid< 1, Real, Device, Index >, 0, Config > > -{ -public: - using GridType = Meshes::Grid< 1, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, 0, Config >; - using PointType = typename GridType::PointType; - - __cuda_callable__ - inline static PointType - getEntityCenter( const GridEntityType& entity ) - { - const GridType& grid = entity.getMesh(); - return PointType( grid.getOrigin().x() + ( entity.getCoordinates().x() ) * grid.getSpaceSteps().x() ); - } -}; - -/**** - * 2D grids - */ -template< typename Real, typename Device, typename Index, typename Config > -class GridEntityCenterGetter< GridEntity< Meshes::Grid< 2, Real, Device, Index >, 2, Config > > -{ -public: - using GridType = Meshes::Grid< 2, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, 2, Config >; - using PointType = typename GridType::PointType; - - __cuda_callable__ - inline static PointType - getEntityCenter( const GridEntityType& entity ) - { - const GridType& grid = entity.getMesh(); - return PointType( grid.getOrigin().x() + ( entity.getCoordinates().x() + 0.5 ) * grid.getSpaceSteps().x(), - grid.getOrigin().y() + ( entity.getCoordinates().y() + 0.5 ) * grid.getSpaceSteps().y() ); - } -}; - -template< typename Real, typename Device, typename Index, typename Config > -class GridEntityCenterGetter< GridEntity< Meshes::Grid< 2, Real, Device, Index >, 1, Config > > -{ -public: - using GridType = Meshes::Grid< 2, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, 1, Config >; - using PointType = typename GridType::PointType; - - __cuda_callable__ - inline static PointType - getEntityCenter( const GridEntityType& entity ) - { - const GridType& grid = entity.getMesh(); - return PointType( - grid.getOrigin().x() + ( entity.getCoordinates().x() + 0.5 * entity.getBasis().x() ) * grid.getSpaceSteps().x(), - grid.getOrigin().y() + ( entity.getCoordinates().y() + 0.5 * entity.getBasis().y() ) * grid.getSpaceSteps().y() ); - } -}; - -template< typename Real, typename Device, typename Index, typename Config > -class GridEntityCenterGetter< GridEntity< Meshes::Grid< 2, Real, Device, Index >, 0, Config > > -{ -public: - using GridType = Meshes::Grid< 2, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, 0, Config >; - using PointType = typename GridType::PointType; - - __cuda_callable__ - inline static PointType - getEntityCenter( const GridEntityType& entity ) - { - const GridType& grid = entity.getMesh(); - return PointType( grid.getOrigin().x() + entity.getCoordinates().x() * grid.getSpaceSteps().x(), - grid.getOrigin().y() + entity.getCoordinates().y() * grid.getSpaceSteps().y() ); - } -}; - -/*** - * 3D grid - */ -template< typename Real, typename Device, typename Index, int EntityDimension, typename Config > -class GridEntityCenterGetter< GridEntity< Meshes::Grid< 3, Real, Device, Index >, EntityDimension, Config > > -{ -public: - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using PointType = typename GridType::PointType; - - __cuda_callable__ - inline static PointType - getEntityCenter( const GridEntityType& entity ) - { - const GridType& grid = entity.getMesh(); - return PointType( - grid.getOrigin().x() + ( entity.getCoordinates().x() + 0.5 * entity.getBasis().x() ) * grid.getSpaceSteps().x(), - grid.getOrigin().y() + ( entity.getCoordinates().y() + 0.5 * entity.getBasis().y() ) * grid.getSpaceSteps().y(), - grid.getOrigin().z() + ( entity.getCoordinates().z() + 0.5 * entity.getBasis().z() ) * grid.getSpaceSteps().z() ); - } -}; - -template< typename Real, typename Device, typename Index, typename Config > -class GridEntityCenterGetter< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 3, Config > > -{ -public: - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, 3, Config >; - using PointType = typename GridType::PointType; - - __cuda_callable__ - inline static PointType - getEntityCenter( const GridEntityType& entity ) - { - const GridType& grid = entity.getMesh(); - return PointType( grid.getOrigin().x() + ( entity.getCoordinates().x() + 0.5 ) * grid.getSpaceSteps().x(), - grid.getOrigin().y() + ( entity.getCoordinates().y() + 0.5 ) * grid.getSpaceSteps().y(), - grid.getOrigin().z() + ( entity.getCoordinates().z() + 0.5 ) * grid.getSpaceSteps().z() ); - } -}; - -template< typename Real, typename Device, typename Index, typename Config > -class GridEntityCenterGetter< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 0, Config > > -{ -public: - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, 0, Config >; - using PointType = typename GridType::PointType; - - __cuda_callable__ - inline static PointType - getEntityCenter( const GridEntityType& entity ) - { - const GridType& grid = entity.getMesh(); - return PointType( grid.getOrigin().x() + ( entity.getCoordinates().x() ) * grid.getSpaceSteps().x(), - grid.getOrigin().y() + ( entity.getCoordinates().y() ) * grid.getSpaceSteps().y(), - grid.getOrigin().z() + ( entity.getCoordinates().z() ) * grid.getSpaceSteps().z() ); - } -}; +template< typename > +class GridEntityCenterGetter; } // namespace Meshes } // namespace TNL + +#include diff --git a/src/TNL/Meshes/GridDetails/GridEntityGetter.h b/src/TNL/Meshes/GridDetails/GridEntityGetter.h index 72008111212132b33c31c6644ca9a1772f97d0ea..bfc1da233cf04238dc7c189f9869bdb3d4d2fba9 100644 --- a/src/TNL/Meshes/GridDetails/GridEntityGetter.h +++ b/src/TNL/Meshes/GridDetails/GridEntityGetter.h @@ -6,18 +6,18 @@ #pragma once +#include + namespace TNL { namespace Meshes { -template< typename Grid, typename GridEntity, int EntityDimension = GridEntity::getEntityDimension() > -class GridEntityGetter -{ - // static_assert( false, "Wrong mesh type or entity topology." ); -}; +template< class, int > +class GridEntity; -/*** - * The main code is in template specializations in GridEntityIndexer.h - */ +template< typename, int > +class GridEntityGetter; } // namespace Meshes } // namespace TNL + +#include diff --git a/src/TNL/Meshes/GridDetails/GridEntityGetter_impl.h b/src/TNL/Meshes/GridDetails/GridEntityGetter_impl.h deleted file mode 100644 index b4914a1b7ade6e45028f3895d2b52b4dc0305d53..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/GridEntityGetter_impl.h +++ /dev/null @@ -1,409 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include -#include -#include - -namespace TNL { -namespace Meshes { - -/**** - * 1D grid - */ -template< typename Real, typename Device, typename Index, typename GridEntity, int EntityDimension > -class GridEntityGetter< Meshes::Grid< 1, Real, Device, Index >, GridEntity, EntityDimension > -{ -public: - static constexpr int entityDimension = EntityDimension; - - using GridType = Meshes::Grid< 1, Real, Device, Index >; - using IndexType = typename GridType::IndexType; - using CoordinatesType = typename GridType::CoordinatesType; - // typedef typename GridType::template GridEntity< entityDimension > GridEntity; - - __cuda_callable__ - inline static GridEntity - getEntity( const GridType& grid, const IndexType& index ) - { - TNL_ASSERT_GE( index, 0, "Index must be non-negative." ); - TNL_ASSERT_LT( index, grid.template getEntitiesCount< GridEntity >(), "Index is out of bounds." ); - return GridEntity( grid, - CoordinatesType( index ), - typename GridEntity::EntityOrientationType( 0 ), - typename GridEntity::EntityBasisType( EntityDimension ) ); - } - - __cuda_callable__ - inline static IndexType - getEntityIndex( const GridType& grid, const GridEntity& entity ) - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( - entity.getCoordinates(), grid.getDimensions() + CoordinatesType( 1 - entityDimension ), "wrong coordinates" ); - return entity.getCoordinates().x(); - } -}; - -/**** - * 2D grid - */ -template< typename Real, typename Device, typename Index, typename GridEntity > -class GridEntityGetter< Meshes::Grid< 2, Real, Device, Index >, GridEntity, 2 > -{ -public: - static constexpr int entityDimension = 2; - - using GridType = Meshes::Grid< 2, Real, Device, Index >; - using IndexType = typename GridType::IndexType; - using CoordinatesType = typename GridType::CoordinatesType; - // typedef typename GridType::template GridEntity< entityDimension > GridEntity; - - __cuda_callable__ - inline static GridEntity - getEntity( const GridType& grid, const IndexType& index ) - { - TNL_ASSERT_GE( index, 0, "Index must be non-negative." ); - TNL_ASSERT_LT( index, grid.template getEntitiesCount< GridEntity >(), "Index is out of bounds." ); - - const CoordinatesType& dimensions = grid.getDimensions(); - - return GridEntity( grid, - CoordinatesType( index % dimensions.x(), index / dimensions.x() ), - typename GridEntity::EntityOrientationType( 0, 0 ), - typename GridEntity::EntityBasisType( 1, 1 ) ); - } - - __cuda_callable__ - inline static IndexType - getEntityIndex( const GridType& grid, const GridEntity& entity ) - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), grid.getDimensions(), "wrong coordinates" ); - - // const CoordinatesType coordinates = entity.getCoordinates(); - // const CoordinatesType dimensions = grid.getDimensions(); - - return entity.getCoordinates().y() * grid.getDimensions().x() + entity.getCoordinates().x(); - } -}; - -template< typename Real, typename Device, typename Index, typename GridEntity > -class GridEntityGetter< Meshes::Grid< 2, Real, Device, Index >, GridEntity, 1 > -{ -public: - static constexpr int entityDimension = 1; - - using GridType = Meshes::Grid< 2, Real, Device, Index >; - using IndexType = typename GridType::IndexType; - using CoordinatesType = typename GridType::CoordinatesType; - // typedef typename GridType::template GridEntity< entityDimension, EntityConfig > GridEntity; - - __cuda_callable__ - inline static GridEntity - getEntity( const GridType& grid, const IndexType& index ) - { - TNL_ASSERT_GE( index, 0, "Index must be non-negative." ); - TNL_ASSERT_LT( index, grid.template getEntitiesCount< GridEntity >(), "Index is out of bounds." ); - - const CoordinatesType dimensions = grid.getDimensions(); - - if( index < grid.numberOfNxFaces ) { - const IndexType aux = dimensions.x() + 1; - return GridEntity( grid, - CoordinatesType( index % aux, index / aux ), - typename GridEntity::EntityOrientationType( 1, 0 ), - typename GridEntity::EntityBasisType( 0, 1 ) ); - } - const IndexType i = index - grid.numberOfNxFaces; - const IndexType& aux = dimensions.x(); - return GridEntity( grid, - CoordinatesType( i % aux, i / aux ), - typename GridEntity::EntityOrientationType( 0, 1 ), - typename GridEntity::EntityBasisType( 1, 0 ) ); - } - - __cuda_callable__ - inline static IndexType - getEntityIndex( const GridType& grid, const GridEntity& entity ) - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), grid.getDimensions() + abs( entity.getOrientation() ), "wrong coordinates" ); - - const CoordinatesType coordinates = entity.getCoordinates(); - const CoordinatesType dimensions = grid.getDimensions(); - - if( entity.getOrientation().x() ) - return coordinates.y() * ( dimensions.x() + 1 ) + coordinates.x(); - return grid.numberOfNxFaces + coordinates.y() * dimensions.x() + coordinates.x(); - } -}; - -template< typename Real, typename Device, typename Index, typename GridEntity > -class GridEntityGetter< Meshes::Grid< 2, Real, Device, Index >, GridEntity, 0 > -{ -public: - static constexpr int entityDimension = 0; - - using GridType = Meshes::Grid< 2, Real, Device, Index >; - using IndexType = typename GridType::IndexType; - using CoordinatesType = typename GridType::CoordinatesType; - // typedef typename GridType::template GridEntity< entityDimension > GridEntity; - - __cuda_callable__ - inline static GridEntity - getEntity( const GridType& grid, const IndexType& index ) - { - TNL_ASSERT_GE( index, 0, "Index must be non-negative." ); - TNL_ASSERT_LT( index, grid.template getEntitiesCount< GridEntity >(), "Index is out of bounds." ); - - const CoordinatesType& dimensions = grid.getDimensions(); - - const IndexType aux = dimensions.x() + 1; - return GridEntity( grid, - CoordinatesType( index % aux, index / aux ), - typename GridEntity::EntityOrientationType( 0, 0 ), - typename GridEntity::EntityBasisType( 0, 0 ) ); - } - - __cuda_callable__ - inline static IndexType - getEntityIndex( const GridType& grid, const GridEntity& entity ) - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LE( entity.getCoordinates(), grid.getDimensions(), "wrong coordinates" ); - - const CoordinatesType& coordinates = entity.getCoordinates(); - const CoordinatesType& dimensions = grid.getDimensions(); - - return coordinates.y() * ( dimensions.x() + 1 ) + coordinates.x(); - } -}; - -/**** - * 3D grid - */ -template< typename Real, typename Device, typename Index, typename GridEntity > -class GridEntityGetter< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 3 > -{ -public: - static constexpr int entityDimension = 3; - - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using IndexType = typename GridType::IndexType; - using CoordinatesType = typename GridType::CoordinatesType; - // typedef typename GridType::template GridEntity< entityDimension > GridEntity; - - __cuda_callable__ - inline static GridEntity - getEntity( const GridType& grid, const IndexType& index ) - { - TNL_ASSERT_GE( index, 0, "Index must be non-negative." ); - TNL_ASSERT_LT( index, grid.template getEntitiesCount< GridEntity >(), "Index is out of bounds." ); - - const CoordinatesType& dimensions = grid.getDimensions(); - - return GridEntity( grid, - CoordinatesType( index % dimensions.x(), - ( index / dimensions.x() ) % dimensions.y(), - index / ( dimensions.x() * dimensions.y() ) ), - typename GridEntity::EntityOrientationType( 0, 0, 0 ), - typename GridEntity::EntityBasisType( 1, 1, 1 ) ); - } - - __cuda_callable__ - inline static IndexType - getEntityIndex( const GridType& grid, const GridEntity& entity ) - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), grid.getDimensions(), "wrong coordinates" ); - - const CoordinatesType& coordinates = entity.getCoordinates(); - const CoordinatesType& dimensions = grid.getDimensions(); - - return ( coordinates.z() * dimensions.y() + coordinates.y() ) * dimensions.x() + coordinates.x(); - } -}; - -template< typename Real, typename Device, typename Index, typename GridEntity > -class GridEntityGetter< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 2 > -{ -public: - static constexpr int entityDimension = 2; - - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using IndexType = typename GridType::IndexType; - using CoordinatesType = typename GridType::CoordinatesType; - // typedef typename GridType::template GridEntity< entityDimension > GridEntity; - - __cuda_callable__ - inline static GridEntity - getEntity( const GridType& grid, const IndexType& index ) - { - TNL_ASSERT_GE( index, 0, "Index must be non-negative." ); - TNL_ASSERT_LT( index, grid.template getEntitiesCount< GridEntity >(), "Index is out of bounds." ); - - const CoordinatesType dimensions = grid.getDimensions(); - - if( index < grid.numberOfNxFaces ) { - const IndexType aux = dimensions.x() + 1; - return GridEntity( grid, - CoordinatesType( index % aux, ( index / aux ) % dimensions.y(), index / ( aux * dimensions.y() ) ), - typename GridEntity::EntityOrientationType( 1, 0, 0 ), - typename GridEntity::EntityBasisType( 0, 1, 1 ) ); - } - if( index < grid.numberOfNxAndNyFaces ) { - const IndexType i = index - grid.numberOfNxFaces; - const IndexType aux = dimensions.y() + 1; - return GridEntity( grid, - CoordinatesType( i % dimensions.x(), ( i / dimensions.x() ) % aux, i / ( aux * dimensions.x() ) ), - typename GridEntity::EntityOrientationType( 0, 1, 0 ), - typename GridEntity::EntityBasisType( 1, 0, 1 ) ); - } - const IndexType i = index - grid.numberOfNxAndNyFaces; - return GridEntity( grid, - CoordinatesType( i % dimensions.x(), - ( i / dimensions.x() ) % dimensions.y(), - i / ( dimensions.x() * dimensions.y() ) ), - typename GridEntity::EntityOrientationType( 0, 0, 1 ), - typename GridEntity::EntityBasisType( 1, 1, 0 ) ); - } - - __cuda_callable__ - inline static IndexType - getEntityIndex( const GridType& grid, const GridEntity& entity ) - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), grid.getDimensions() + abs( entity.getOrientation() ), "wrong coordinates" ); - - const CoordinatesType coordinates = entity.getCoordinates(); - const CoordinatesType dimensions = grid.getDimensions(); - - if( entity.getOrientation().x() ) { - return ( coordinates.z() * dimensions.y() + coordinates.y() ) * ( dimensions.x() + 1 ) + coordinates.x(); - } - if( entity.getOrientation().y() ) { - return grid.numberOfNxFaces + ( coordinates.z() * ( dimensions.y() + 1 ) + coordinates.y() ) * dimensions.x() - + coordinates.x(); - } - return grid.numberOfNxAndNyFaces + ( coordinates.z() * dimensions.y() + coordinates.y() ) * dimensions.x() - + coordinates.x(); - } -}; - -template< typename Real, typename Device, typename Index, typename GridEntity > -class GridEntityGetter< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 1 > -{ -public: - static constexpr int entityDimension = 1; - - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using IndexType = typename GridType::IndexType; - using CoordinatesType = typename GridType::CoordinatesType; - // typedef typename GridType::template GridEntity< entityDimension > GridEntity; - - __cuda_callable__ - inline static GridEntity - getEntity( const GridType& grid, const IndexType& index ) - { - TNL_ASSERT_GE( index, 0, "Index must be non-negative." ); - TNL_ASSERT_LT( index, grid.template getEntitiesCount< GridEntity >(), "Index is out of bounds." ); - - const CoordinatesType dimensions = grid.getDimensions(); - - if( index < grid.numberOfDxEdges ) { - const IndexType aux = dimensions.y() + 1; - return GridEntity( - grid, - CoordinatesType( index % dimensions.x(), ( index / dimensions.x() ) % aux, index / ( dimensions.x() * aux ) ), - typename GridEntity::EntityOrientationType( 0, 0, 0 ), - typename GridEntity::EntityBasisType( 1, 0, 0 ) ); - } - if( index < grid.numberOfDxAndDyEdges ) { - const IndexType i = index - grid.numberOfDxEdges; - const IndexType aux = dimensions.x() + 1; - return GridEntity( grid, - CoordinatesType( i % aux, ( i / aux ) % dimensions.y(), i / ( aux * dimensions.y() ) ), - typename GridEntity::EntityOrientationType( 0, 0, 0 ), - typename GridEntity::EntityBasisType( 0, 1, 0 ) ); - } - const IndexType i = index - grid.numberOfDxAndDyEdges; - const IndexType aux1 = dimensions.x() + 1; - const IndexType aux2 = dimensions.y() + 1; - return GridEntity( grid, - CoordinatesType( i % aux1, ( i / aux1 ) % aux2, i / ( aux1 * aux2 ) ), - typename GridEntity::EntityOrientationType( 0, 0, 0 ), - typename GridEntity::EntityBasisType( 0, 0, 1 ) ); - } - - __cuda_callable__ - inline static IndexType - getEntityIndex( const GridType& grid, const GridEntity& entity ) - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( - entity.getCoordinates(), grid.getDimensions() + CoordinatesType( 1, 1, 1 ) - entity.getBasis(), "wrong coordinates" ); - - const CoordinatesType coordinates = entity.getCoordinates(); - const CoordinatesType dimensions = grid.getDimensions(); - - if( entity.getBasis().x() ) - return ( coordinates.z() * ( dimensions.y() + 1 ) + coordinates.y() ) * dimensions.x() + coordinates.x(); - if( entity.getBasis().y() ) - return grid.numberOfDxEdges + ( coordinates.z() * dimensions.y() + coordinates.y() ) * ( dimensions.x() + 1 ) - + coordinates.x(); - return grid.numberOfDxAndDyEdges + ( coordinates.z() * ( dimensions.y() + 1 ) + coordinates.y() ) * ( dimensions.x() + 1 ) - + coordinates.x(); - } -}; - -template< typename Real, typename Device, typename Index, typename GridEntity > -class GridEntityGetter< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 0 > -{ -public: - static constexpr int entityDimension = 0; - - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using IndexType = typename GridType::IndexType; - using CoordinatesType = typename GridType::CoordinatesType; - // typedef typename GridType::template GridEntity< entityDimension > GridEntity; - - __cuda_callable__ - inline static GridEntity - getEntity( const GridType& grid, const IndexType& index ) - { - TNL_ASSERT_GE( index, 0, "Index must be non-negative." ); - TNL_ASSERT_LT( index, grid.template getEntitiesCount< GridEntity >(), "Index is out of bounds." ); - - const CoordinatesType& dimensions = grid.getDimensions(); - - const IndexType auxX = dimensions.x() + 1; - const IndexType auxY = dimensions.y() + 1; - return GridEntity( grid, - CoordinatesType( index % auxX, ( index / auxX ) % auxY, index / ( auxX * auxY ) ), - typename GridEntity::EntityOrientationType( 0, 0, 0 ), - typename GridEntity::EntityBasisType( 0, 0, 0 ) ); - } - - __cuda_callable__ - inline static IndexType - getEntityIndex( const GridType& grid, const GridEntity& entity ) - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LE( entity.getCoordinates(), grid.getDimensions(), "wrong coordinates" ); - - const CoordinatesType& coordinates = entity.getCoordinates(); - const CoordinatesType& dimensions = grid.getDimensions(); - - return ( coordinates.z() * ( dimensions.y() + 1 ) + coordinates.y() ) * ( dimensions.x() + 1 ) + coordinates.x(); - } -}; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/GridEntityMeasureGetter.h b/src/TNL/Meshes/GridDetails/GridEntityMeasureGetter.h index 539c6e247db04fcff32f5ed75a0825cbcf0853a6..cff295e5360bd8368258d32fea29e3b4a88b701a 100644 --- a/src/TNL/Meshes/GridDetails/GridEntityMeasureGetter.h +++ b/src/TNL/Meshes/GridDetails/GridEntityMeasureGetter.h @@ -4,145 +4,17 @@ // // SPDX-License-Identifier: MIT +#include + #pragma once namespace TNL { namespace Meshes { template< typename Grid, int EntityDimension > -class GridEntityMeasureGetter -{}; - -/*** - * Common implementation for vertices - */ -template< int Dimension, typename Real, typename Device, typename Index > -class GridEntityMeasureGetter< Meshes::Grid< Dimension, Real, Device, Index >, 0 > -{ -public: - using GridType = Meshes::Grid< Dimension, Real, Device, Index >; - - template< typename EntityType > - __cuda_callable__ - inline static Real - getMeasure( const GridType& grid, const EntityType& entity ) - { - return 0.0; - } -}; - -/**** - * 1D grid - */ - -template< typename Real, typename Device, typename Index > -class GridEntityMeasureGetter< Meshes::Grid< 1, Real, Device, Index >, 1 > -{ -public: - using GridType = Meshes::Grid< 1, Real, Device, Index >; - - template< typename EntityType > - __cuda_callable__ - inline static const Real& - getMeasure( const GridType& grid, const EntityType& entity ) - { - return grid.template getSpaceStepsProducts< 1 >(); - } -}; - -/**** - * 2D grid - */ -template< typename Real, typename Device, typename Index > -class GridEntityMeasureGetter< Meshes::Grid< 2, Real, Device, Index >, 2 > -{ -public: - using GridType = Meshes::Grid< 2, Real, Device, Index >; - - template< typename EntityType > - __cuda_callable__ - inline static const Real& - getMeasure( const GridType& grid, const EntityType& entity ) - { - return grid.template getSpaceStepsProducts< 1, 1 >(); - } -}; - -template< typename Real, typename Device, typename Index > -class GridEntityMeasureGetter< Meshes::Grid< 2, Real, Device, Index >, 1 > -{ -public: - using GridType = Meshes::Grid< 2, Real, Device, Index >; - - template< typename EntityType > - __cuda_callable__ - inline static const Real& - getMeasure( const GridType& grid, const EntityType& entity ) - { - if( entity.getOrientation().x() ) - return grid.template getSpaceStepsProducts< 0, 1 >(); - else - return grid.template getSpaceStepsProducts< 1, 0 >(); - } -}; - -/**** - * 3D grid - */ -template< typename Real, typename Device, typename Index > -class GridEntityMeasureGetter< Meshes::Grid< 3, Real, Device, Index >, 3 > -{ -public: - using GridType = Meshes::Grid< 3, Real, Device, Index >; - - template< typename EntityType > - __cuda_callable__ - inline static const Real& - getMeasure( const GridType& grid, const EntityType& entity ) - { - return grid.template getSpaceStepsProducts< 1, 1, 1 >(); - } -}; - -template< typename Real, typename Device, typename Index > -class GridEntityMeasureGetter< Meshes::Grid< 3, Real, Device, Index >, 2 > -{ -public: - using GridType = Meshes::Grid< 3, Real, Device, Index >; - - template< typename EntityType > - __cuda_callable__ - inline static const Real& - getMeasure( const GridType& grid, const EntityType& entity ) - { - if( entity.getOrientation().x() ) - return grid.template getSpaceStepsProducts< 0, 1, 1 >(); - if( entity.getOrientation().y() ) - return grid.template getSpaceStepsProducts< 1, 0, 1 >(); - else - return grid.template getSpaceStepsProducts< 1, 1, 0 >(); - } -}; - -template< typename Real, typename Device, typename Index > -class GridEntityMeasureGetter< Meshes::Grid< 3, Real, Device, Index >, 1 > -{ -public: - using GridType = Meshes::Grid< 3, Real, Device, Index >; - - template< typename EntityType > - __cuda_callable__ - inline static const Real& - getMeasure( const GridType& grid, const EntityType& entity ) - { - if( entity.getBasis().x() ) - return grid.template getSpaceStepsProducts< 1, 0, 0 >(); - if( entity.getBasis().y() ) - return grid.template getSpaceStepsProducts< 0, 1, 0 >(); - else - return grid.template getSpaceStepsProducts< 0, 0, 1 >(); - } -}; +class GridEntityMeasureGetter; } // namespace Meshes } // namespace TNL + +#include diff --git a/src/TNL/Meshes/GridDetails/GridEntityTopology.h b/src/TNL/Meshes/GridDetails/GridEntityTopology.h deleted file mode 100644 index 3f4d0baaec08e9df184dbcd0502a18f69e8cd3d1..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/GridEntityTopology.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -namespace TNL { -namespace Meshes { - -template< typename Grid, int EntityDimension, typename EntityOrientation_, typename EntityProportions_ > -class GridEntityTopology -{ -public: - using GridType = Grid; - - static constexpr int meshDimension = GridType::getMeshDimension(); - - static constexpr int entityDimension = EntityDimension; - - using EntityOrientation = EntityOrientation_; - - using EntityProportions = EntityProportions_; - - // TODO: restore when CUDA allows it - // static_assert( meshDimension == EntityOrientation_::size, - // "Entity orientation is not a proper static multiindex." ); -}; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/GridEntity_impl.h b/src/TNL/Meshes/GridDetails/GridEntity_impl.h deleted file mode 100644 index 6fdb0a85f886ecf1bae952a8582576e670d6d805..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/GridEntity_impl.h +++ /dev/null @@ -1,453 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include -#include -#include - -namespace TNL { -namespace Meshes { - -/*template< int Dimension, - typename Real, - typename Device, - typename Index, typename Config, - int EntityDimension > -__cuda_callable__ inline -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension >:: -GridEntity() -{ -}*/ - -template< int Dimension, typename Real, typename Device, typename Index, int EntityDimension, typename Config > -__cuda_callable__ -inline GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::GridEntity( - const Meshes::Grid< Dimension, Real, Device, Index >& grid ) -: grid( grid ), entityIndex( -1 ), coordinates( 0 ), orientation( 0 ), basis( 0 ), neighborEntitiesStorage( *this ) -{} - -template< int Dimension, typename Real, typename Device, typename Index, int EntityDimension, typename Config > -__cuda_callable__ -inline GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::GridEntity( - const Meshes::Grid< Dimension, Real, Device, Index >& grid, - const CoordinatesType& coordinates, - const EntityOrientationType& orientation, - const EntityBasisType& basis ) -: grid( grid ), entityIndex( -1 ), coordinates( coordinates ), orientation( orientation ), basis( basis ), - neighborEntitiesStorage( *this ) -{} - -template< int Dimension, typename Real, typename Device, typename Index, int EntityDimension, typename Config > -__cuda_callable__ -inline const typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::CoordinatesType& -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::getCoordinates() const -{ - return this->coordinates; -} - -template< int Dimension, typename Real, typename Device, typename Index, int EntityDimension, typename Config > -__cuda_callable__ -inline typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::CoordinatesType& -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::getCoordinates() -{ - return this->coordinates; -} - -template< int Dimension, typename Real, typename Device, typename Index, int EntityDimension, typename Config > -__cuda_callable__ -inline void -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::setCoordinates( - const CoordinatesType& coordinates ) -{ - this->coordinates = coordinates; -} - -template< int Dimension, typename Real, typename Device, typename Index, int EntityDimension, typename Config > -__cuda_callable__ -inline void -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::refresh() -{ - this->entityIndex = this->grid.getEntityIndex( *this ); - this->neighborEntitiesStorage.refresh( this->grid, this->entityIndex ); -} - -template< int Dimension, typename Real, typename Device, typename Index, int EntityDimension, typename Config > -__cuda_callable__ -inline Index -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::getIndex() const -{ - using GridType = Meshes::Grid< Dimension, Real, Device, Index >; - using EntityType = typename GridType::template EntityType< EntityDimension >; - TNL_ASSERT_GE( this->entityIndex, 0, "Entity index is not non-negative." ); - TNL_ASSERT_LT( this->entityIndex, grid.template getEntitiesCount< EntityDimension >(), "Entity index is out of bounds." ); - TNL_ASSERT_EQ( this->entityIndex, grid.getEntityIndex( *this ), "Wrong value of stored index." ); - return this->entityIndex; -} - -template< int Dimension, typename Real, typename Device, typename Index, int EntityDimension, typename Config > -__cuda_callable__ -inline const typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >:: - EntityOrientationType& - GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::getOrientation() const -{ - return this->orientation; -} - -template< int Dimension, typename Real, typename Device, typename Index, int EntityDimension, typename Config > -__cuda_callable__ -inline void -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::setOrientation( - const EntityOrientationType& orientation ) -{ - this->orientation = orientation; - this->basis = EntityBasisType( 1 ) - abs( orientation ); -} - -template< int Dimension, typename Real, typename Device, typename Index, int EntityDimension, typename Config > -__cuda_callable__ -inline const typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::EntityBasisType& -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::getBasis() const -{ - return this->basis; -} - -template< int Dimension, typename Real, typename Device, typename Index, int EntityDimension, typename Config > -__cuda_callable__ -inline void -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::setBasis( const EntityBasisType& basis ) -{ - this->basis = basis; - this->orientation = EntityOrientationType( 1 ) - abs( basis ); -} - -template< int Dimension, typename Real, typename Device, typename Index, int EntityDimension, typename Config > -template< int NeighborEntityDimension > -__cuda_callable__ -inline const typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >:: - template NeighborEntities< NeighborEntityDimension >& - GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::getNeighborEntities() const -{ - return neighborEntitiesStorage.template getNeighborEntities< NeighborEntityDimension >(); -} - -template< int Dimension, typename Real, typename Device, typename Index, int EntityDimension, typename Config > -__cuda_callable__ -inline bool -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::isBoundaryEntity() const -{ - return BoundaryGridEntityChecker< GridEntity >::isBoundaryEntity( *this ); -} - -template< int Dimension, typename Real, typename Device, typename Index, int EntityDimension, typename Config > -__cuda_callable__ -inline typename Meshes::Grid< Dimension, Real, Device, Index >::PointType -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::getCenter() const -{ - return GridEntityCenterGetter< GridEntity >::getEntityCenter( *this ); -} - -template< int Dimension, typename Real, typename Device, typename Index, int EntityDimension, typename Config > -__cuda_callable__ -inline const typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::RealType& -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::getMeasure() const -{ - return GridEntityMeasureGetter< GridType, EntityDimension >::getMeasure( this->getMesh(), *this ); -} - -template< int Dimension, typename Real, typename Device, typename Index, int EntityDimension, typename Config > -__cuda_callable__ -inline const typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::GridType& -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >::getMesh() const -{ - return this->grid; -} - -/**** - * Specialization for cells - */ -/*template< int Dimension, - typename Real, - typename Device, - typename Index > -__cuda_callable__ inline -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension >:: -GridEntity() -{ -}*/ - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::GridEntity( const GridType& grid ) -: grid( grid ), entityIndex( -1 ), neighborEntitiesStorage( *this ) -{ - this->coordinates = CoordinatesType( (Index) 0 ); -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::GridEntity( - const GridType& grid, - const CoordinatesType& coordinates, - const EntityOrientationType& orientation, - const EntityBasisType& basis ) -: grid( grid ), entityIndex( -1 ), coordinates( coordinates ), neighborEntitiesStorage( *this ) -{} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline const typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::CoordinatesType& -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::getCoordinates() const -{ - return this->coordinates; -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::CoordinatesType& -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::getCoordinates() -{ - return this->coordinates; -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline void -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::setCoordinates( - const CoordinatesType& coordinates ) -{ - this->coordinates = coordinates; -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline void -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::refresh() -{ - this->entityIndex = this->grid.getEntityIndex( *this ); - this->neighborEntitiesStorage.refresh( this->grid, this->entityIndex ); -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline Index -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::getIndex() const -{ - TNL_ASSERT_GE( this->entityIndex, 0, "Entity index is not non-negative." ); - TNL_ASSERT_LT( this->entityIndex, grid.template getEntitiesCount< Dimension >(), "Entity index is out of bounds." ); - TNL_ASSERT_EQ( this->entityIndex, grid.getEntityIndex( *this ), "Wrong value of stored index." ); - return this->entityIndex; -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline const typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::EntityOrientationType -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::getOrientation() const -{ - return EntityOrientationType( (IndexType) 0 ); -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline const typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::EntityBasisType -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::getBasis() const -{ - return EntityBasisType( (IndexType) 1 ); -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -template< int NeighborEntityDimension > -__cuda_callable__ -inline const typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >:: - template NeighborEntities< NeighborEntityDimension >& - GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::getNeighborEntities() const -{ - return neighborEntitiesStorage.template getNeighborEntities< NeighborEntityDimension >(); -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline bool -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::isBoundaryEntity() const -{ - return BoundaryGridEntityChecker< GridEntity >::isBoundaryEntity( *this ); -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline typename Meshes::Grid< Dimension, Real, Device, Index >::PointType -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::getCenter() const -{ - return GridEntityCenterGetter< GridEntity >::getEntityCenter( *this ); -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline const typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::RealType& -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::getMeasure() const -{ - return this->getMesh().getCellMeasure(); -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline const typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::PointType& -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::getEntityProportions() const -{ - return grid.getSpaceSteps(); -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline const typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::GridType& -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >::getMesh() const -{ - return this->grid; -} - -/**** - * Specialization for vertices - */ -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::GridEntity( const GridType& grid ) -: grid( grid ), entityIndex( -1 ), coordinates( 0 ), neighborEntitiesStorage( *this ) -{} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::GridEntity( - const GridType& grid, - const CoordinatesType& coordinates, - const EntityOrientationType& orientation, - const EntityBasisType& basis ) -: grid( grid ), entityIndex( -1 ), coordinates( coordinates ), neighborEntitiesStorage( *this ) -{} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline const typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::CoordinatesType& -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::getCoordinates() const -{ - return this->coordinates; -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::CoordinatesType& -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::getCoordinates() -{ - return this->coordinates; -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline void -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::setCoordinates( const CoordinatesType& coordinates ) -{ - this->coordinates = coordinates; -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline void -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::refresh() -{ - this->entityIndex = this->grid.getEntityIndex( *this ); - this->neighborEntitiesStorage.refresh( this->grid, this->entityIndex ); -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline Index -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::getIndex() const -{ - using GridType = Meshes::Grid< Dimension, Real, Device, Index >; - using Vertex = typename GridType::Vertex; - TNL_ASSERT_GE( this->entityIndex, 0, "Entity index is not non-negative." ); - TNL_ASSERT_LT( this->entityIndex, grid.template getEntitiesCount< 0 >(), "Entity index is out of bounds." ); - TNL_ASSERT_EQ( this->entityIndex, grid.getEntityIndex( *this ), "Wrong value of stored index." ); - return this->entityIndex; -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline const typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::EntityOrientationType -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::getOrientation() const -{ - return EntityOrientationType( (IndexType) 0 ); -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline const typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::EntityBasisType -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::getBasis() const -{ - return EntityBasisType( (IndexType) 0 ); -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -template< int NeighborEntityDimension > -__cuda_callable__ -inline const typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::template NeighborEntities< - NeighborEntityDimension >& -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::getNeighborEntities() const -{ - return neighborEntitiesStorage.template getNeighborEntities< NeighborEntityDimension >(); -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline bool -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::isBoundaryEntity() const -{ - return BoundaryGridEntityChecker< GridEntity >::isBoundaryEntity( *this ); -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline typename Meshes::Grid< Dimension, Real, Device, Index >::PointType -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::getCenter() const -{ - return GridEntityCenterGetter< GridEntity >::getEntityCenter( *this ); -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline typename Meshes::Grid< Dimension, Real, Device, Index >::PointType -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::getPoint() const -{ - return getCenter(); -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline const typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::RealType -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::getMeasure() const -{ - return 0.0; -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::PointType -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::getEntityProportions() const -{ - return PointType( 0.0 ); -} - -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -__cuda_callable__ -inline const typename GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::GridType& -GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::getMesh() const -{ - return this->grid; -} - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/GridTraverser.h b/src/TNL/Meshes/GridDetails/GridTraverser.h deleted file mode 100644 index 3077328eb9e36b365606f27447e4acfb19f93796..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/GridTraverser.h +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include - -namespace TNL { -namespace Meshes { - -/**** - * This is only a helper class for Traverser specializations for Grid. - */ -template< typename Grid > -class GridTraverser -{}; - -enum GridTraverserMode -{ - synchronousMode, - asynchronousMode -}; - -/**** - * 1D grid, Devices::Host - */ -template< typename Real, typename Index > -class GridTraverser< Meshes::Grid< 1, Real, Devices::Host, Index > > -{ -public: - using GridType = Meshes::Grid< 1, Real, Devices::Host, Index >; - using GridPointer = Pointers::SharedPointer< GridType >; - using RealType = Real; - using DeviceType = Devices::Host; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - - template< typename GridEntity, typename EntitiesProcessor, typename UserData, bool processOnlyBoundaryEntities > - static void - processEntities( const GridPointer& gridPointer, - const CoordinatesType& begin, - const CoordinatesType& end, - UserData& userData, - GridTraverserMode mode = synchronousMode, - const int& stream = 0 ); -}; - -/**** - * 1D grid, Devices::Cuda - */ -template< typename Real, typename Index > -class GridTraverser< Meshes::Grid< 1, Real, Devices::Cuda, Index > > -{ -public: - using GridType = Meshes::Grid< 1, Real, Devices::Cuda, Index >; - using GridPointer = Pointers::SharedPointer< GridType >; - using RealType = Real; - using DeviceType = Devices::Cuda; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - - template< typename GridEntity, typename EntitiesProcessor, typename UserData, bool processOnlyBoundaryEntities > - static void - processEntities( const GridPointer& gridPointer, - const CoordinatesType& begin, - const CoordinatesType& end, - UserData& userData, - GridTraverserMode mode = synchronousMode, - const int& stream = 0 ); -}; - -/**** - * 2D grid, Devices::Host - */ -template< typename Real, typename Index > -class GridTraverser< Meshes::Grid< 2, Real, Devices::Host, Index > > -{ -public: - using GridType = Meshes::Grid< 2, Real, Devices::Host, Index >; - using GridPointer = Pointers::SharedPointer< GridType >; - using RealType = Real; - using DeviceType = Devices::Host; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - - template< typename GridEntity, - typename EntitiesProcessor, - typename UserData, - bool processOnlyBoundaryEntities, - int XOrthogonalBoundary = 1, - int YOrthogonalBoundary = 1, - typename... GridEntityParameters > - static void - processEntities( const GridPointer& gridPointer, - const CoordinatesType& begin, - const CoordinatesType& end, - UserData& userData, - // FIXME: hack around nvcc bug (error: default argument not at end of parameter list) - // GridTraverserMode mode = synchronousMode, - GridTraverserMode mode, - // const int& stream = 0, - const int& stream, - // gridEntityParameters are passed to GridEntity's constructor - // (i.e. orientation and basis for faces) - const GridEntityParameters&... gridEntityParameters ); -}; - -/**** - * 2D grid, Devices::Cuda - */ -template< typename Real, typename Index > -class GridTraverser< Meshes::Grid< 2, Real, Devices::Cuda, Index > > -{ -public: - using GridType = Meshes::Grid< 2, Real, Devices::Cuda, Index >; - using GridPointer = Pointers::SharedPointer< GridType >; - using RealType = Real; - using DeviceType = Devices::Cuda; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - - template< typename GridEntity, - typename EntitiesProcessor, - typename UserData, - bool processOnlyBoundaryEntities, - int XOrthogonalBoundary = 1, - int YOrthogonalBoundary = 1, - typename... GridEntityParameters > - static void - processEntities( const GridPointer& gridPointer, - const CoordinatesType& begin, - const CoordinatesType& end, - UserData& userData, - // FIXME: hack around nvcc bug (error: default argument not at end of parameter list) - // GridTraverserMode mode = synchronousMode, - GridTraverserMode mode, - // const int& stream = 0, - const int& stream, - // gridEntityParameters are passed to GridEntity's constructor - // (i.e. orientation and basis for faces) - const GridEntityParameters&... gridEntityParameters ); -}; - -/**** - * 3D grid, Devices::Host - */ -template< typename Real, typename Index > -class GridTraverser< Meshes::Grid< 3, Real, Devices::Host, Index > > -{ -public: - using GridType = Meshes::Grid< 3, Real, Devices::Host, Index >; - using GridPointer = Pointers::SharedPointer< GridType >; - using RealType = Real; - using DeviceType = Devices::Host; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - - template< typename GridEntity, - typename EntitiesProcessor, - typename UserData, - bool processOnlyBoundaryEntities, - int XOrthogonalBoundary = 1, - int YOrthogonalBoundary = 1, - int ZOrthogonalBoundary = 1, - typename... GridEntityParameters > - static void - processEntities( const GridPointer& gridPointer, - const CoordinatesType& begin, - const CoordinatesType& end, - UserData& userData, - // FIXME: hack around nvcc bug (error: default argument not at end of parameter list) - // GridTraverserMode mode = synchronousMode, - GridTraverserMode mode, - // const int& stream = 0, - const int& stream, - // gridEntityParameters are passed to GridEntity's constructor - // (i.e. orientation and basis for faces and edges) - const GridEntityParameters&... gridEntityParameters ); -}; - -/**** - * 3D grid, Devices::Cuda - */ -template< typename Real, typename Index > -class GridTraverser< Meshes::Grid< 3, Real, Devices::Cuda, Index > > -{ -public: - using GridType = Meshes::Grid< 3, Real, Devices::Cuda, Index >; - using GridPointer = Pointers::SharedPointer< GridType >; - using RealType = Real; - using DeviceType = Devices::Cuda; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - - template< typename GridEntity, - typename EntitiesProcessor, - typename UserData, - bool processOnlyBoundaryEntities, - int XOrthogonalBoundary = 1, - int YOrthogonalBoundary = 1, - int ZOrthogonalBoundary = 1, - typename... GridEntityParameters > - static void - processEntities( const GridPointer& gridPointer, - const CoordinatesType& begin, - const CoordinatesType& end, - UserData& userData, - // FIXME: hack around nvcc bug (error: default argument not at end of parameter list) - // GridTraverserMode mode = synchronousMode, - GridTraverserMode mode, - // const int& stream = 0, - const int& stream, - // gridEntityParameters are passed to GridEntity's constructor - // (i.e. orientation and basis for faces and edges) - const GridEntityParameters&... gridEntityParameters ); -}; - -} // namespace Meshes -} // namespace TNL - -#include -#include -#include diff --git a/src/TNL/Meshes/GridDetails/GridTraverser_1D.hpp b/src/TNL/Meshes/GridDetails/GridTraverser_1D.hpp deleted file mode 100644 index b71c2a6ac0e3a37748d5785e9c2c321a7cb8e1ac..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/GridTraverser_1D.hpp +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -// Implemented by: Tomas Oberhuber, -// Jakub Klinkovsky, -// Vit Hanousek - -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace TNL { -namespace Meshes { - -/**** - * 1D traverser, host - */ -template< typename Real, typename Index > -template< typename GridEntity, typename EntitiesProcessor, typename UserData, bool processOnlyBoundaryEntities > -void -GridTraverser< Meshes::Grid< 1, Real, Devices::Host, Index > >::processEntities( const GridPointer& gridPointer, - const CoordinatesType& begin, - const CoordinatesType& end, - UserData& userData, - GridTraverserMode mode, - const int& stream ) -{ - GridEntity entity( *gridPointer ); - if( processOnlyBoundaryEntities ) { - GridEntity entity( *gridPointer ); - - entity.getCoordinates() = begin; - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - entity.getCoordinates() = end - 1; - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - } - else { -#ifdef HAVE_OPENMP - if( Devices::Host::isOMPEnabled() && end.x() - begin.x() > 512 ) { - #pragma omp parallel firstprivate( begin, end ) - { - GridEntity entity( *gridPointer ); - #pragma omp for - // TODO: g++ 5.5 crashes when coding this loop without auxiliary x as bellow - for( IndexType x = begin.x(); x < end.x(); x++ ) { - entity.getCoordinates().x() = x; - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - } - } - } - else { - GridEntity entity( *gridPointer ); - for( entity.getCoordinates().x() = begin.x(); entity.getCoordinates().x() < end.x(); entity.getCoordinates().x()++ ) { - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - } - } -#else - GridEntity entity( *gridPointer ); - for( entity.getCoordinates().x() = begin.x(); entity.getCoordinates().x() < end.x(); entity.getCoordinates().x()++ ) { - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - } -#endif - } -} - -/**** - * 1D traverser, CUDA - */ -#ifdef HAVE_CUDA -template< typename Real, typename Index, typename GridEntity, typename UserData, typename EntitiesProcessor > -__global__ -void -GridTraverser1D( const Meshes::Grid< 1, Real, Devices::Cuda, Index >* grid, - UserData userData, - const typename GridEntity::CoordinatesType begin, - const typename GridEntity::CoordinatesType end, - const Index gridIdx ) -{ - typedef Real RealType; - typedef Index IndexType; - typedef Meshes::Grid< 1, Real, Devices::Cuda, Index > GridType; - typename GridType::CoordinatesType coordinates; - - coordinates.x() = begin.x() + ( gridIdx * Cuda::getMaxGridSize() + blockIdx.x ) * blockDim.x + threadIdx.x; - if( coordinates < end ) { - GridEntity entity( *grid, coordinates ); - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - } -} - -template< typename Real, typename Index, typename GridEntity, typename UserData, typename EntitiesProcessor > -__global__ -void -GridBoundaryTraverser1D( const Meshes::Grid< 1, Real, Devices::Cuda, Index >* grid, - UserData userData, - const typename GridEntity::CoordinatesType begin, - const typename GridEntity::CoordinatesType end ) -{ - typedef Real RealType; - typedef Index IndexType; - typedef Meshes::Grid< 1, Real, Devices::Cuda, Index > GridType; - typename GridType::CoordinatesType coordinates; - - if( threadIdx.x == 0 ) { - coordinates.x() = begin.x(); - GridEntity entity( *grid, coordinates ); - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - } - if( threadIdx.x == 1 ) { - coordinates.x() = end.x() - 1; - GridEntity entity( *grid, coordinates ); - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - } -} - -#endif - -template< typename Real, typename Index > -template< typename GridEntity, typename EntitiesProcessor, typename UserData, bool processOnlyBoundaryEntities > -void -GridTraverser< Meshes::Grid< 1, Real, Devices::Cuda, Index > >::processEntities( const GridPointer& gridPointer, - const CoordinatesType& begin, - const CoordinatesType& end, - UserData& userData, - GridTraverserMode mode, - const int& stream ) -{ -#ifdef HAVE_CUDA - auto& pool = Cuda::StreamPool::getInstance(); - const cudaStream_t& s = pool.getStream( stream ); - - Pointers::synchronizeSmartPointersOnDevice< Devices::Cuda >(); - if( processOnlyBoundaryEntities ) { - dim3 cudaBlockSize( 2 ); - dim3 cudaBlocks( 1 ); - GridBoundaryTraverser1D< Real, Index, GridEntity, UserData, EntitiesProcessor > <<< cudaBlocks, - cudaBlockSize, 0, s >>>( &gridPointer.template getData< Devices::Cuda >(), userData, begin, end ); - } - else { - dim3 blockSize( 256 ), blocksCount, gridsCount; - Cuda::setupThreads( blockSize, blocksCount, gridsCount, end.x() - begin.x() ); - dim3 gridIdx; - for( gridIdx.x = 0; gridIdx.x < gridsCount.x; gridIdx.x++ ) { - dim3 gridSize; - Cuda::setupGrid( blocksCount, gridsCount, gridIdx, gridSize ); - GridTraverser1D< Real, Index, GridEntity, UserData, EntitiesProcessor > <<< blocksCount, blockSize, 0, - s >>>( &gridPointer.template getData< Devices::Cuda >(), userData, begin, end, gridIdx.x ); - } - - /*dim3 cudaBlockSize( 256 ); - dim3 cudaBlocks; - cudaBlocks.x = Cuda::getNumberOfBlocks( end.x() - begin.x(), cudaBlockSize.x ); - const IndexType cudaXGrids = Cuda::getNumberOfGrids( cudaBlocks.x ); - - for( IndexType gridXIdx = 0; gridXIdx < cudaXGrids; gridXIdx ++ ) - GridTraverser1D< Real, Index, GridEntity, UserData, EntitiesProcessor > - <<< cudaBlocks, cudaBlockSize, 0, s >>> - ( &gridPointer.template getData< Devices::Cuda >(), - userData, - begin, - end, - gridXIdx );*/ - } - - #ifdef NDEBUG - if( mode == synchronousMode ) { - cudaStreamSynchronize( s ); - TNL_CHECK_CUDA_DEVICE; - } - #else - cudaStreamSynchronize( s ); - TNL_CHECK_CUDA_DEVICE; - #endif - -#else - throw Exceptions::CudaSupportMissing(); -#endif -} - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/GridTraverser_2D.hpp b/src/TNL/Meshes/GridDetails/GridTraverser_2D.hpp deleted file mode 100644 index 77171e24cf978507408956c8263c19bbdbb6f4e6..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/GridTraverser_2D.hpp +++ /dev/null @@ -1,524 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include -#include -#include -#include - -namespace TNL { -namespace Meshes { - -//#define GRID_TRAVERSER_USE_STREAMS - -/**** - * 2D traverser, host - */ -template< typename Real, typename Index > -template< typename GridEntity, - typename EntitiesProcessor, - typename UserData, - bool processOnlyBoundaryEntities, - int XOrthogonalBoundary, - int YOrthogonalBoundary, - typename... GridEntityParameters > -void -GridTraverser< Meshes::Grid< 2, Real, Devices::Host, Index > >::processEntities( - const GridPointer& gridPointer, - const CoordinatesType& begin, - const CoordinatesType& end, - UserData& userData, - GridTraverserMode mode, - const int& stream, - const GridEntityParameters&... gridEntityParameters ) -{ - if( processOnlyBoundaryEntities ) { - GridEntity entity( *gridPointer, begin, gridEntityParameters... ); - - if( YOrthogonalBoundary ) - for( entity.getCoordinates().x() = begin.x(); entity.getCoordinates().x() < end.x(); entity.getCoordinates().x()++ ) { - entity.getCoordinates().y() = begin.y(); - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - entity.getCoordinates().y() = end.y() - 1; - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - } - if( XOrthogonalBoundary ) - for( entity.getCoordinates().y() = begin.y(); entity.getCoordinates().y() < end.y(); entity.getCoordinates().y()++ ) { - entity.getCoordinates().x() = begin.x(); - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - entity.getCoordinates().x() = end.x() - 1; - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - } - } - else { -#ifdef HAVE_OPENMP - if( Devices::Host::isOMPEnabled() ) { - #pragma omp parallel firstprivate( begin, end ) - { - GridEntity entity( *gridPointer, begin, gridEntityParameters... ); - #pragma omp for - // TODO: g++ 5.5 crashes when coding this loop without auxiliary x and y as bellow - for( IndexType y = begin.y(); y < end.y(); y++ ) - for( IndexType x = begin.x(); x < end.x(); x++ ) { - entity.getCoordinates().x() = x; - entity.getCoordinates().y() = y; - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - } - } - } - else { - GridEntity entity( *gridPointer, begin, gridEntityParameters... ); - for( entity.getCoordinates().y() = begin.y(); entity.getCoordinates().y() < end.y(); entity.getCoordinates().y()++ ) - for( entity.getCoordinates().x() = begin.x(); entity.getCoordinates().x() < end.x(); entity.getCoordinates().x()++ ) - { - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - } - } -#else - GridEntity entity( *gridPointer, begin, gridEntityParameters... ); - for( entity.getCoordinates().y() = begin.y(); entity.getCoordinates().y() < end.y(); entity.getCoordinates().y()++ ) - for( entity.getCoordinates().x() = begin.x(); entity.getCoordinates().x() < end.x(); entity.getCoordinates().x()++ ) { - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - } -#endif - } -} - -/**** - * 2D traverser, CUDA - */ -#ifdef HAVE_CUDA -template< typename Real, - typename Index, - typename GridEntity, - typename UserData, - typename EntitiesProcessor, - bool processOnlyBoundaryEntities, - typename... GridEntityParameters > -__global__ -void -GridTraverser2D( const Meshes::Grid< 2, Real, Devices::Cuda, Index >* grid, - UserData userData, - const typename GridEntity::CoordinatesType begin, - const typename GridEntity::CoordinatesType end, - const dim3 gridIdx, - const GridEntityParameters... gridEntityParameters ) -{ - typedef Meshes::Grid< 2, Real, Devices::Cuda, Index > GridType; - typename GridType::CoordinatesType coordinates; - - coordinates.x() = begin.x() + Cuda::getGlobalThreadIdx_x( gridIdx ); - coordinates.y() = begin.y() + Cuda::getGlobalThreadIdx_y( gridIdx ); - - if( coordinates < end ) { - GridEntity entity( *grid, coordinates, gridEntityParameters... ); - entity.refresh(); - if( ! processOnlyBoundaryEntities || entity.isBoundaryEntity() ) { - EntitiesProcessor::processEntity( *grid, userData, entity ); - } - } -} - -// Boundary traverser using streams -template< typename Real, - typename Index, - typename GridEntity, - typename UserData, - typename EntitiesProcessor, - bool processOnlyBoundaryEntities, - typename... GridEntityParameters > -__global__ -void -GridTraverser2DBoundaryAlongX( const Meshes::Grid< 2, Real, Devices::Cuda, Index >* grid, - UserData userData, - const Index beginX, - const Index endX, - const Index fixedY, - const dim3 gridIdx, - const GridEntityParameters... gridEntityParameters ) -{ - typedef Meshes::Grid< 2, Real, Devices::Cuda, Index > GridType; - typename GridType::CoordinatesType coordinates; - - coordinates.x() = beginX + Cuda::getGlobalThreadIdx_x( gridIdx ); - coordinates.y() = fixedY; - - if( coordinates.x() < endX ) { - GridEntity entity( *grid, coordinates, gridEntityParameters... ); - entity.refresh(); - EntitiesProcessor::processEntity( *grid, userData, entity ); - } -} - -// Boundary traverser using streams -template< typename Real, - typename Index, - typename GridEntity, - typename UserData, - typename EntitiesProcessor, - bool processOnlyBoundaryEntities, - typename... GridEntityParameters > -__global__ -void -GridTraverser2DBoundaryAlongY( const Meshes::Grid< 2, Real, Devices::Cuda, Index >* grid, - UserData userData, - const Index beginY, - const Index endY, - const Index fixedX, - const dim3 gridIdx, - const GridEntityParameters... gridEntityParameters ) -{ - typedef Meshes::Grid< 2, Real, Devices::Cuda, Index > GridType; - typename GridType::CoordinatesType coordinates; - - coordinates.x() = fixedX; - coordinates.y() = beginY + Cuda::getGlobalThreadIdx_x( gridIdx ); - - if( coordinates.y() < endY ) { - GridEntity entity( *grid, coordinates, gridEntityParameters... ); - entity.refresh(); - EntitiesProcessor::processEntity( *grid, userData, entity ); - } -} - -template< typename Real, - typename Index, - typename GridEntity, - typename UserData, - typename EntitiesProcessor, - bool processOnlyBoundaryEntities, - typename... GridEntityParameters > -__global__ -void -GridTraverser2DBoundary( const Meshes::Grid< 2, Real, Devices::Cuda, Index >* grid, - UserData userData, - const Index beginX, - const Index endX, - const Index beginY, - const Index endY, - const Index blocksPerFace, - const dim3 gridIdx, - const GridEntityParameters... gridEntityParameters ) -{ - using GridType = Meshes::Grid< 2, Real, Devices::Cuda, Index >; - using CoordinatesType = typename GridType::CoordinatesType; - - const Index faceIdx = blockIdx.x / blocksPerFace; - const Index faceBlockIdx = blockIdx.x % blocksPerFace; - const Index threadId = faceBlockIdx * blockDim.x + threadIdx.x; - if( faceIdx < 2 ) { - const Index entitiesAlongX = endX - beginX; - if( threadId < entitiesAlongX ) { - GridEntity entity( - *grid, CoordinatesType( beginX + threadId, faceIdx == 0 ? beginY : endY - 1 ), gridEntityParameters... ); - // printf( "faceIdx %d Thread %d -> %d %d \n ", faceIdx, threadId, entity.getCoordinates().x(), - // entity.getCoordinates().y() ); - entity.refresh(); - EntitiesProcessor::processEntity( *grid, userData, entity ); - } - } - else { - const Index entitiesAlongY = endY - beginY; - if( threadId < entitiesAlongY ) { - GridEntity entity( - *grid, CoordinatesType( faceIdx == 2 ? beginX : endX - 1, beginY + threadId + 1 ), gridEntityParameters... ); - // printf( "faceIdx %d Thread %d -> %d %d \n ", faceIdx, threadId, entity.getCoordinates().x(), - // entity.getCoordinates().y() ); - entity.refresh(); - EntitiesProcessor::processEntity( *grid, userData, entity ); - } - } - - /*const Index aux = max( entitiesAlongX, entitiesAlongY ); - const Index& warpSize = Cuda::getWarpSize(); - const Index threadsPerAxis = warpSize * ( aux / warpSize + ( aux % warpSize != 0 ) ); - - Index threadId = Cuda::getGlobalThreadIdx_x( gridIdx ); - GridEntity entity( *grid, - CoordinatesType( 0, 0 ), - gridEntityParameters... ); - CoordinatesType& coordinates = entity.getCoordinates(); - const Index axisIndex = threadId / threadsPerAxis; - //printf( "axisIndex %d, threadId %d thradsPerAxis %d \n", axisIndex, threadId, threadsPerAxis ); - threadId -= axisIndex * threadsPerAxis; - switch( axisIndex ) - { - case 1: - coordinates = CoordinatesType( beginX + threadId, beginY ); - if( threadId < entitiesAlongX ) - { - //printf( "X1: Thread %d -> %d %d \n ", threadId, coordinates.x(), coordinates.y() ); - entity.refresh(); - EntitiesProcessor::processEntity( *grid, userData, entity ); - } - break; - case 2: - coordinates = CoordinatesType( beginX + threadId, endY - 1 ); - if( threadId < entitiesAlongX ) - { - //printf( "X2: Thread %d -> %d %d \n ", threadId, coordinates.x(), coordinates.y() ); - entity.refresh(); - EntitiesProcessor::processEntity( *grid, userData, entity ); - } - break; - case 3: - coordinates = CoordinatesType( beginX, beginY + threadId + 1 ); - if( threadId < entitiesAlongY ) - { - //printf( "Y1: Thread %d -> %d %d \n ", threadId, coordinates.x(), coordinates.y() ); - entity.refresh(); - EntitiesProcessor::processEntity( *grid, userData, entity ); - } - break; - case 4: - coordinates = CoordinatesType( endX - 1, beginY + threadId + 1 ); - if( threadId < entitiesAlongY ) - { - //printf( "Y2: Thread %d -> %d %d \n ", threadId, coordinates.x(), coordinates.y() ); - entity.refresh(); - EntitiesProcessor::processEntity( *grid, userData, entity ); - } - break; - }*/ - - /*if( threadId < entitiesAlongX ) - { - GridEntity entity( *grid, - CoordinatesType( beginX + threadId, beginY ), - gridEntityParameters... ); - //printf( "X1: Thread %d -> %d %d x %d %d \n ", threadId, - // entity.getCoordinates().x(), entity.getCoordinates().y(), - // grid->getDimensions().x(), grid->getDimensions().y() ); - entity.refresh(); - EntitiesProcessor::processEntity( *grid, userData, entity ); - } - else if( ( threadId -= entitiesAlongX ) < entitiesAlongX && threadId >= 0 ) - { - GridEntity entity( *grid, - CoordinatesType( beginX + threadId, endY - 1 ), - gridEntityParameters... ); - entity.refresh(); - //printf( "X2: Thread %d -> %d %d \n ", threadId, entity.getCoordinates().x(), entity.getCoordinates().y() ); - EntitiesProcessor::processEntity( *grid, userData, entity ); - } - else if( ( ( threadId -= entitiesAlongX ) < entitiesAlongY - 1 ) && threadId >= 0 ) - { - GridEntity entity( *grid, - CoordinatesType( beginX, beginY + threadId + 1 ), - gridEntityParameters... ); - entity.refresh(); - //printf( "Y1: Thread %d -> %d %d \n ", threadId, entity.getCoordinates().x(), entity.getCoordinates().y() ); - EntitiesProcessor::processEntity( *grid, userData, entity ); - } - else if( ( ( threadId -= entitiesAlongY - 1 ) < entitiesAlongY - 1 ) && threadId >= 0 ) - { - GridEntity entity( *grid, - CoordinatesType( endX - 1, beginY + threadId + 1 ), - gridEntityParameters... ); - entity.refresh(); - //printf( "Y2: Thread %d -> %d %d \n ", threadId, entity.getCoordinates().x(), entity.getCoordinates().y() ); - EntitiesProcessor::processEntity( *grid, userData, entity ); - }*/ -} - -#endif // HAVE_CUDA - -template< typename Real, typename Index > -template< typename GridEntity, - typename EntitiesProcessor, - typename UserData, - bool processOnlyBoundaryEntities, - int XOrthogonalBoundary, - int YOrthogonalBoundary, - typename... GridEntityParameters > -void -GridTraverser< Meshes::Grid< 2, Real, Devices::Cuda, Index > >::processEntities( - const GridPointer& gridPointer, - const CoordinatesType& begin, - const CoordinatesType& end, - UserData& userData, - GridTraverserMode mode, - const int& stream, - const GridEntityParameters&... gridEntityParameters ) -{ -#ifdef HAVE_CUDA - if( processOnlyBoundaryEntities && ( GridEntity::getEntityDimension() == 2 || GridEntity::getEntityDimension() == 0 ) ) { - #ifdef GRID_TRAVERSER_USE_STREAMS - dim3 cudaBlockSize( 256 ); - dim3 cudaBlocksCountAlongX, cudaGridsCountAlongX, cudaBlocksCountAlongY, cudaGridsCountAlongY; - Cuda::setupThreads( cudaBlockSize, cudaBlocksCountAlongX, cudaGridsCountAlongX, end.x() - begin.x() ); - Cuda::setupThreads( cudaBlockSize, cudaBlocksCountAlongY, cudaGridsCountAlongY, end.y() - begin.y() - 2 ); - - auto& pool = Cuda::StreamPool::getInstance(); - Pointers::synchronizeSmartPointersOnDevice< Devices::Cuda >(); - - const cudaStream_t& s1 = pool.getStream( stream ); - const cudaStream_t& s2 = pool.getStream( stream + 1 ); - dim3 gridIdx, cudaGridSize; - for( gridIdx.x = 0; gridIdx.x < cudaGridsCountAlongX.x; gridIdx.x++ ) { - Cuda::setupGrid( cudaBlocksCountAlongX, cudaGridsCountAlongX, gridIdx, cudaGridSize ); - // Cuda::printThreadsSetup( cudaBlockSize, cudaBlocksCountAlongX, cudaGridSize, cudaGridsCountAlongX ); - GridTraverser2DBoundaryAlongX< Real, - Index, - GridEntity, - UserData, - EntitiesProcessor, - processOnlyBoundaryEntities, - GridEntityParameters... > - <<< cudaGridSize, cudaBlockSize, 0, - s1 >>>( &gridPointer.template getData< Devices::Cuda >(), - userData, - begin.x(), - end.x(), - begin.y(), - gridIdx, - gridEntityParameters... ); - GridTraverser2DBoundaryAlongX< Real, - Index, - GridEntity, - UserData, - EntitiesProcessor, - processOnlyBoundaryEntities, - GridEntityParameters... > - <<< cudaGridSize, cudaBlockSize, 0, - s2 >>>( &gridPointer.template getData< Devices::Cuda >(), - userData, - begin.x(), - end.x(), - end.y(), - gridIdx, - gridEntityParameters... ); - } - const cudaStream_t& s3 = pool.getStream( stream + 2 ); - const cudaStream_t& s4 = pool.getStream( stream + 3 ); - for( gridIdx.x = 0; gridIdx.x < cudaGridsCountAlongY.x; gridIdx.x++ ) { - Cuda::setupGrid( cudaBlocksCountAlongY, cudaGridsCountAlongY, gridIdx, cudaGridSize ); - GridTraverser2DBoundaryAlongY< Real, - Index, - GridEntity, - UserData, - EntitiesProcessor, - processOnlyBoundaryEntities, - GridEntityParameters... > - <<< cudaGridSize, cudaBlockSize, 0, - s3 >>>( &gridPointer.template getData< Devices::Cuda >(), - userData, - begin.y() + 1, - end.y() - 1, - begin.x(), - gridIdx, - gridEntityParameters... ); - GridTraverser2DBoundaryAlongY< Real, - Index, - GridEntity, - UserData, - EntitiesProcessor, - processOnlyBoundaryEntities, - GridEntityParameters... > - <<< cudaGridSize, cudaBlockSize, 0, - s4 >>>( &gridPointer.template getData< Devices::Cuda >(), - userData, - begin.y() + 1, - end.y() - 1, - end.x(), - gridIdx, - gridEntityParameters... ); - } - cudaStreamSynchronize( s1 ); - cudaStreamSynchronize( s2 ); - cudaStreamSynchronize( s3 ); - cudaStreamSynchronize( s4 ); - #else // not defined GRID_TRAVERSER_USE_STREAMS - dim3 cudaBlockSize( 256 ); - dim3 cudaBlocksCount, cudaGridsCount; - const IndexType entitiesAlongX = end.x() - begin.x(); - const IndexType entitiesAlongY = end.x() - begin.x() - 2; - const IndexType maxFaceSize = max( entitiesAlongX, entitiesAlongY ); - const IndexType blocksPerFace = maxFaceSize / cudaBlockSize.x + ( maxFaceSize % cudaBlockSize.x != 0 ); - IndexType cudaThreadsCount = 4 * cudaBlockSize.x * blocksPerFace; - Cuda::setupThreads( cudaBlockSize, cudaBlocksCount, cudaGridsCount, cudaThreadsCount ); - // std::cerr << "blocksPerFace = " << blocksPerFace << "Threads count = " << cudaThreadsCount - // << "cudaBlockCount = " << cudaBlocksCount.x << std::endl; - dim3 gridIdx, cudaGridSize; - Pointers::synchronizeSmartPointersOnDevice< Devices::Cuda >(); - for( gridIdx.x = 0; gridIdx.x < cudaGridsCount.x; gridIdx.x++ ) { - Cuda::setupGrid( cudaBlocksCount, cudaGridsCount, gridIdx, cudaGridSize ); - // Cuda::printThreadsSetup( cudaBlockSize, cudaBlocksCountAlongX, cudaGridSize, cudaGridsCountAlongX ); - GridTraverser2DBoundary< Real, - Index, - GridEntity, - UserData, - EntitiesProcessor, - processOnlyBoundaryEntities, - GridEntityParameters... > - <<< cudaGridSize, cudaBlockSize >>>( &gridPointer.template getData< Devices::Cuda >(), - userData, - begin.x(), - end.x(), - begin.y(), - end.y(), - blocksPerFace, - gridIdx, - gridEntityParameters... ); - } - #endif // GRID_TRAVERSER_USE_STREAMS - // getchar(); - TNL_CHECK_CUDA_DEVICE; - } - else { - dim3 cudaBlockSize( 16, 16 ); - dim3 cudaBlocksCount, cudaGridsCount; - Cuda::setupThreads( cudaBlockSize, cudaBlocksCount, cudaGridsCount, end.x() - begin.x(), end.y() - begin.y() ); - - auto& pool = Cuda::StreamPool::getInstance(); - const cudaStream_t& s = pool.getStream( stream ); - - Pointers::synchronizeSmartPointersOnDevice< Devices::Cuda >(); - dim3 gridIdx, cudaGridSize; - for( gridIdx.y = 0; gridIdx.y < cudaGridsCount.y; gridIdx.y++ ) - for( gridIdx.x = 0; gridIdx.x < cudaGridsCount.x; gridIdx.x++ ) { - Cuda::setupGrid( cudaBlocksCount, cudaGridsCount, gridIdx, cudaGridSize ); - // Cuda::printThreadsSetup( cudaBlockSize, cudaBlocksCount, cudaGridSize, cudaGridsCount ); - GridTraverser2D< Real, - Index, - GridEntity, - UserData, - EntitiesProcessor, - processOnlyBoundaryEntities, - GridEntityParameters... > - <<< cudaGridSize, cudaBlockSize, 0, - s >>>( - &gridPointer.template getData< Devices::Cuda >(), userData, begin, end, gridIdx, gridEntityParameters... ); - } - - #ifdef NDEBUG - if( mode == synchronousMode ) { - cudaStreamSynchronize( s ); - TNL_CHECK_CUDA_DEVICE; - } - #else - cudaStreamSynchronize( s ); - TNL_CHECK_CUDA_DEVICE; - #endif - } - -#else - throw Exceptions::CudaSupportMissing(); -#endif -} - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/GridTraverser_3D.hpp b/src/TNL/Meshes/GridDetails/GridTraverser_3D.hpp deleted file mode 100644 index 332360080a5afbf8559f9220760665dc1884c8fc..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/GridTraverser_3D.hpp +++ /dev/null @@ -1,463 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace TNL { -namespace Meshes { - -/**** - * 3D traverser, host - */ -template< typename Real, typename Index > -template< typename GridEntity, - typename EntitiesProcessor, - typename UserData, - bool processOnlyBoundaryEntities, - int XOrthogonalBoundary, - int YOrthogonalBoundary, - int ZOrthogonalBoundary, - typename... GridEntityParameters > -void -GridTraverser< Meshes::Grid< 3, Real, Devices::Host, Index > >::processEntities( - const GridPointer& gridPointer, - const CoordinatesType& begin, - const CoordinatesType& end, - UserData& userData, - GridTraverserMode mode, - const int& stream, - const GridEntityParameters&... gridEntityParameters ) -{ - if( processOnlyBoundaryEntities ) { - GridEntity entity( *gridPointer, begin, gridEntityParameters... ); - - if( ZOrthogonalBoundary ) - for( entity.getCoordinates().y() = begin.y(); entity.getCoordinates().y() < end.y(); entity.getCoordinates().y()++ ) - for( entity.getCoordinates().x() = begin.x(); entity.getCoordinates().x() < end.x(); entity.getCoordinates().x()++ ) - { - entity.getCoordinates().z() = begin.z(); - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - entity.getCoordinates().z() = end.z() - 1; - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - } - if( YOrthogonalBoundary ) - for( entity.getCoordinates().z() = begin.z(); entity.getCoordinates().z() < end.z(); entity.getCoordinates().z()++ ) - for( entity.getCoordinates().x() = begin.x(); entity.getCoordinates().x() < end.x(); entity.getCoordinates().x()++ ) - { - entity.getCoordinates().y() = begin.y(); - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - entity.getCoordinates().y() = end.y() - 1; - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - } - if( XOrthogonalBoundary ) - for( entity.getCoordinates().z() = begin.z(); entity.getCoordinates().z() < end.z(); entity.getCoordinates().z()++ ) - for( entity.getCoordinates().y() = begin.y(); entity.getCoordinates().y() < end.y(); entity.getCoordinates().y()++ ) - { - entity.getCoordinates().x() = begin.x(); - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - entity.getCoordinates().x() = end.x() - 1; - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - } - } - else { -#ifdef HAVE_OPENMP - if( Devices::Host::isOMPEnabled() ) { - #pragma omp parallel firstprivate( begin, end ) - { - GridEntity entity( *gridPointer, begin, gridEntityParameters... ); - #pragma omp for - // TODO: g++ 5.5 crashes when coding this loop without auxiliary x and y as bellow - for( IndexType z = begin.z(); z < end.z(); z++ ) - for( IndexType y = begin.y(); y < end.y(); y++ ) - for( IndexType x = begin.x(); x < end.x(); x++ ) { - entity.getCoordinates().x() = x; - entity.getCoordinates().y() = y; - entity.getCoordinates().z() = z; - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - } - } - } - else { - GridEntity entity( *gridPointer, begin, gridEntityParameters... ); - for( entity.getCoordinates().z() = begin.z(); entity.getCoordinates().z() < end.z(); entity.getCoordinates().z()++ ) - for( entity.getCoordinates().y() = begin.y(); entity.getCoordinates().y() < end.y(); entity.getCoordinates().y()++ ) - for( entity.getCoordinates().x() = begin.x(); entity.getCoordinates().x() < end.x(); - entity.getCoordinates().x()++ ) { - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - } - } -#else - GridEntity entity( *gridPointer, begin, gridEntityParameters... ); - for( entity.getCoordinates().z() = begin.z(); entity.getCoordinates().z() < end.z(); entity.getCoordinates().z()++ ) - for( entity.getCoordinates().y() = begin.y(); entity.getCoordinates().y() < end.y(); entity.getCoordinates().y()++ ) - for( entity.getCoordinates().x() = begin.x(); entity.getCoordinates().x() < end.x(); entity.getCoordinates().x()++ ) - { - entity.refresh(); - EntitiesProcessor::processEntity( entity.getMesh(), userData, entity ); - } -#endif - } -} - -/**** - * 3D traverser, CUDA - */ -#ifdef HAVE_CUDA -template< typename Real, - typename Index, - typename GridEntity, - typename UserData, - typename EntitiesProcessor, - bool processOnlyBoundaryEntities, - typename... GridEntityParameters > -__global__ -void -GridTraverser3D( const Meshes::Grid< 3, Real, Devices::Cuda, Index >* grid, - UserData userData, - const typename GridEntity::CoordinatesType begin, - const typename GridEntity::CoordinatesType end, - const dim3 gridIdx, - const GridEntityParameters... gridEntityParameters ) -{ - typedef Meshes::Grid< 3, Real, Devices::Cuda, Index > GridType; - typename GridType::CoordinatesType coordinates; - - coordinates.x() = begin.x() + Cuda::getGlobalThreadIdx_x( gridIdx ); - coordinates.y() = begin.y() + Cuda::getGlobalThreadIdx_y( gridIdx ); - coordinates.z() = begin.z() + Cuda::getGlobalThreadIdx_z( gridIdx ); - - if( coordinates < end ) { - GridEntity entity( *grid, coordinates, gridEntityParameters... ); - entity.refresh(); - if( ! processOnlyBoundaryEntities || entity.isBoundaryEntity() ) { - EntitiesProcessor::processEntity( *grid, userData, entity ); - } - } -} - -template< typename Real, - typename Index, - typename GridEntity, - typename UserData, - typename EntitiesProcessor, - bool processOnlyBoundaryEntities, - typename... GridEntityParameters > -__global__ -void -GridTraverser3DBoundaryAlongXY( const Meshes::Grid< 3, Real, Devices::Cuda, Index >* grid, - UserData userData, - const Index beginX, - const Index endX, - const Index beginY, - const Index endY, - const Index fixedZ, - const dim3 gridIdx, - const GridEntityParameters... gridEntityParameters ) -{ - typedef Meshes::Grid< 3, Real, Devices::Cuda, Index > GridType; - typename GridType::CoordinatesType coordinates; - - coordinates.x() = beginX + Cuda::getGlobalThreadIdx_x( gridIdx ); - coordinates.y() = beginY + Cuda::getGlobalThreadIdx_y( gridIdx ); - coordinates.z() = fixedZ; - - if( coordinates.x() < endX && coordinates.y() < endY ) { - GridEntity entity( *grid, coordinates, gridEntityParameters... ); - entity.refresh(); - EntitiesProcessor::processEntity( *grid, userData, entity ); - } -} - -template< typename Real, - typename Index, - typename GridEntity, - typename UserData, - typename EntitiesProcessor, - bool processOnlyBoundaryEntities, - typename... GridEntityParameters > -__global__ -void -GridTraverser3DBoundaryAlongXZ( const Meshes::Grid< 3, Real, Devices::Cuda, Index >* grid, - UserData userData, - const Index beginX, - const Index endX, - const Index beginZ, - const Index endZ, - const Index fixedY, - const dim3 gridIdx, - const GridEntityParameters... gridEntityParameters ) -{ - typedef Meshes::Grid< 3, Real, Devices::Cuda, Index > GridType; - typename GridType::CoordinatesType coordinates; - - coordinates.x() = beginX + Cuda::getGlobalThreadIdx_x( gridIdx ); - coordinates.y() = fixedY; - coordinates.z() = beginZ + Cuda::getGlobalThreadIdx_y( gridIdx ); - - if( coordinates.x() < endX && coordinates.z() < endZ ) { - GridEntity entity( *grid, coordinates, gridEntityParameters... ); - entity.refresh(); - EntitiesProcessor::processEntity( *grid, userData, entity ); - } -} - -template< typename Real, - typename Index, - typename GridEntity, - typename UserData, - typename EntitiesProcessor, - bool processOnlyBoundaryEntities, - typename... GridEntityParameters > -__global__ -void -GridTraverser3DBoundaryAlongYZ( const Meshes::Grid< 3, Real, Devices::Cuda, Index >* grid, - UserData userData, - const Index beginY, - const Index endY, - const Index beginZ, - const Index endZ, - const Index fixedX, - const dim3 gridIdx, - const GridEntityParameters... gridEntityParameters ) -{ - typedef Meshes::Grid< 3, Real, Devices::Cuda, Index > GridType; - typename GridType::CoordinatesType coordinates; - - coordinates.x() = fixedX; - coordinates.y() = beginY + Cuda::getGlobalThreadIdx_x( gridIdx ); - coordinates.z() = beginZ + Cuda::getGlobalThreadIdx_y( gridIdx ); - - if( coordinates.y() < endY && coordinates.z() < endZ ) { - GridEntity entity( *grid, coordinates, gridEntityParameters... ); - entity.refresh(); - EntitiesProcessor::processEntity( *grid, userData, entity ); - } -} -#endif - -template< typename Real, typename Index > -template< typename GridEntity, - typename EntitiesProcessor, - typename UserData, - bool processOnlyBoundaryEntities, - int XOrthogonalBoundary, - int YOrthogonalBoundary, - int ZOrthogonalBoundary, - typename... GridEntityParameters > -void -GridTraverser< Meshes::Grid< 3, Real, Devices::Cuda, Index > >::processEntities( - const GridPointer& gridPointer, - const CoordinatesType& begin, - const CoordinatesType& end, - UserData& userData, - GridTraverserMode mode, - const int& stream, - const GridEntityParameters&... gridEntityParameters ) -{ -#ifdef HAVE_CUDA - if( processOnlyBoundaryEntities && ( GridEntity::getEntityDimension() == 3 || GridEntity::getEntityDimension() == 0 ) ) { - dim3 cudaBlockSize( 16, 16 ); - const IndexType entitiesAlongX = end.x() - begin.x(); - const IndexType entitiesAlongY = end.y() - begin.y(); - const IndexType entitiesAlongZ = end.z() - begin.z(); - - dim3 cudaBlocksCountAlongXY, cudaBlocksCountAlongXZ, cudaBlocksCountAlongYZ, cudaGridsCountAlongXY, cudaGridsCountAlongXZ, - cudaGridsCountAlongYZ; - - Cuda::setupThreads( cudaBlockSize, cudaBlocksCountAlongXY, cudaGridsCountAlongXY, entitiesAlongX, entitiesAlongY ); - Cuda::setupThreads( cudaBlockSize, cudaBlocksCountAlongXZ, cudaGridsCountAlongXZ, entitiesAlongX, entitiesAlongZ - 2 ); - Cuda::setupThreads( - cudaBlockSize, cudaBlocksCountAlongYZ, cudaGridsCountAlongYZ, entitiesAlongY - 2, entitiesAlongZ - 2 ); - - auto& pool = Cuda::StreamPool::getInstance(); - Pointers::synchronizeSmartPointersOnDevice< Devices::Cuda >(); - - const cudaStream_t& s1 = pool.getStream( stream ); - const cudaStream_t& s2 = pool.getStream( stream + 1 ); - const cudaStream_t& s3 = pool.getStream( stream + 2 ); - const cudaStream_t& s4 = pool.getStream( stream + 3 ); - const cudaStream_t& s5 = pool.getStream( stream + 4 ); - const cudaStream_t& s6 = pool.getStream( stream + 5 ); - - dim3 gridIdx, gridSize; - for( gridIdx.y = 0; gridIdx.y < cudaGridsCountAlongXY.y; gridIdx.y++ ) - for( gridIdx.x = 0; gridIdx.x < cudaGridsCountAlongXY.x; gridIdx.x++ ) { - Cuda::setupGrid( cudaBlocksCountAlongXY, cudaGridsCountAlongXY, gridIdx, gridSize ); - GridTraverser3DBoundaryAlongXY< Real, - Index, - GridEntity, - UserData, - EntitiesProcessor, - processOnlyBoundaryEntities, - GridEntityParameters... > - <<< cudaBlocksCountAlongXY, cudaBlockSize, 0, - s1 >>>( &gridPointer.template getData< Devices::Cuda >(), - userData, - begin.x(), - end.x(), - begin.y(), - end.y(), - begin.z(), - gridIdx, - gridEntityParameters... ); - GridTraverser3DBoundaryAlongXY< Real, - Index, - GridEntity, - UserData, - EntitiesProcessor, - processOnlyBoundaryEntities, - GridEntityParameters... > - <<< cudaBlocksCountAlongXY, cudaBlockSize, 0, - s2 >>>( &gridPointer.template getData< Devices::Cuda >(), - userData, - begin.x(), - end.x(), - begin.y(), - end.y(), - end.z(), - gridIdx, - gridEntityParameters... ); - } - for( gridIdx.y = 0; gridIdx.y < cudaGridsCountAlongXZ.y; gridIdx.y++ ) - for( gridIdx.x = 0; gridIdx.x < cudaGridsCountAlongXZ.x; gridIdx.x++ ) { - Cuda::setupGrid( cudaBlocksCountAlongXZ, cudaGridsCountAlongXZ, gridIdx, gridSize ); - GridTraverser3DBoundaryAlongXZ< Real, - Index, - GridEntity, - UserData, - EntitiesProcessor, - processOnlyBoundaryEntities, - GridEntityParameters... > - <<< cudaBlocksCountAlongXZ, cudaBlockSize, 0, - s3 >>>( &gridPointer.template getData< Devices::Cuda >(), - userData, - begin.x(), - end.x(), - begin.z() + 1, - end.z() - 1, - begin.y(), - gridIdx, - gridEntityParameters... ); - GridTraverser3DBoundaryAlongXZ< Real, - Index, - GridEntity, - UserData, - EntitiesProcessor, - processOnlyBoundaryEntities, - GridEntityParameters... > - <<< cudaBlocksCountAlongXZ, cudaBlockSize, 0, - s4 >>>( &gridPointer.template getData< Devices::Cuda >(), - userData, - begin.x(), - end.x(), - begin.z() + 1, - end.z() - 1, - end.y(), - gridIdx, - gridEntityParameters... ); - } - for( gridIdx.y = 0; gridIdx.y < cudaGridsCountAlongYZ.y; gridIdx.y++ ) - for( gridIdx.x = 0; gridIdx.x < cudaGridsCountAlongYZ.x; gridIdx.x++ ) { - Cuda::setupGrid( cudaBlocksCountAlongYZ, cudaGridsCountAlongYZ, gridIdx, gridSize ); - GridTraverser3DBoundaryAlongYZ< Real, - Index, - GridEntity, - UserData, - EntitiesProcessor, - processOnlyBoundaryEntities, - GridEntityParameters... > - <<< cudaBlocksCountAlongYZ, cudaBlockSize, 0, - s5 >>>( &gridPointer.template getData< Devices::Cuda >(), - userData, - begin.y() + 1, - end.y() - 1, - begin.z() + 1, - end.z() - 1, - begin.x(), - gridIdx, - gridEntityParameters... ); - GridTraverser3DBoundaryAlongYZ< Real, - Index, - GridEntity, - UserData, - EntitiesProcessor, - processOnlyBoundaryEntities, - GridEntityParameters... > - <<< cudaBlocksCountAlongYZ, cudaBlockSize, 0, - s6 >>>( &gridPointer.template getData< Devices::Cuda >(), - userData, - begin.y() + 1, - end.y() - 1, - begin.z() + 1, - end.z() - 1, - end.x(), - gridIdx, - gridEntityParameters... ); - } - cudaStreamSynchronize( s1 ); - cudaStreamSynchronize( s2 ); - cudaStreamSynchronize( s3 ); - cudaStreamSynchronize( s4 ); - cudaStreamSynchronize( s5 ); - cudaStreamSynchronize( s6 ); - TNL_CHECK_CUDA_DEVICE; - } - else { - dim3 cudaBlockSize( 8, 8, 8 ); - dim3 cudaBlocksCount, cudaGridsCount; - - Cuda::setupThreads( - cudaBlockSize, cudaBlocksCount, cudaGridsCount, end.x() - begin.x(), end.y() - begin.y(), end.z() - begin.z() ); - - auto& pool = Cuda::StreamPool::getInstance(); - const cudaStream_t& s = pool.getStream( stream ); - - Pointers::synchronizeSmartPointersOnDevice< Devices::Cuda >(); - dim3 gridIdx, gridSize; - for( gridIdx.z = 0; gridIdx.z < cudaGridsCount.z; gridIdx.z++ ) - for( gridIdx.y = 0; gridIdx.y < cudaGridsCount.y; gridIdx.y++ ) - for( gridIdx.x = 0; gridIdx.x < cudaGridsCount.x; gridIdx.x++ ) { - Cuda::setupGrid( cudaBlocksCount, cudaGridsCount, gridIdx, gridSize ); - GridTraverser3D< Real, - Index, - GridEntity, - UserData, - EntitiesProcessor, - processOnlyBoundaryEntities, - GridEntityParameters... > - <<< gridSize, cudaBlockSize, 0, - s >>>( - &gridPointer.template getData< Devices::Cuda >(), userData, begin, end, gridIdx, gridEntityParameters... ); - } - - // only launches into the stream 0 are synchronized - if( stream == 0 ) { - cudaStreamSynchronize( s ); - TNL_CHECK_CUDA_DEVICE; - } - } -#else - throw Exceptions::CudaSupportMissing(); -#endif -} - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Implementations/BoundaryGridEntityChecker.hpp b/src/TNL/Meshes/GridDetails/Implementations/BoundaryGridEntityChecker.hpp new file mode 100644 index 0000000000000000000000000000000000000000..61415aafb53089a4f048718c6163288b92d51768 --- /dev/null +++ b/src/TNL/Meshes/GridDetails/Implementations/BoundaryGridEntityChecker.hpp @@ -0,0 +1,181 @@ +/*************************************************************************** + BoundaryGridEntityChecker.h - description + ------------------- + begin : Dec 2, 2015 + copyright : (C) 2015 by Tomas Oberhuber + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include + +namespace TNL { +namespace Meshes { + +/*** + * 1D grids + */ +template< typename Real, typename Device, typename Index > +class BoundaryGridEntityChecker< GridEntity< Meshes::Grid< 1, Real, Device, Index >, 1 > > +{ +public: + using Entity = GridEntity< Meshes::Grid< 1, Real, Device, Index >, 1 >; + + __cuda_callable__ + inline static bool + isBoundaryEntity( const Entity& entity ) + { + return ( entity.getCoordinates().x() == 0 || entity.getCoordinates().x() == entity.getMesh().getDimensions().x() - 1 ); + } +}; + +template< typename Real, typename Device, typename Index > +class BoundaryGridEntityChecker< GridEntity< Meshes::Grid< 1, Real, Device, Index >, 0 > > +{ +public: + using Entity = GridEntity< Meshes::Grid< 1, Real, Device, Index >, 0 >; + + __cuda_callable__ + inline static bool + isBoundaryEntity( const Entity& entity ) + { + return ( entity.getCoordinates().x() == 0 || entity.getCoordinates().x() == entity.getMesh().getDimensions().x() ); + } +}; + +/**** + * 2D grids + */ +template< typename Real, typename Device, typename Index > +class BoundaryGridEntityChecker< GridEntity< Meshes::Grid< 2, Real, Device, Index >, 2 > > +{ +public: + using Entity = GridEntity< Meshes::Grid< 2, Real, Device, Index >, 2 >; + + __cuda_callable__ + inline static bool + isBoundaryEntity( const Entity& entity ) + { + return ( entity.getCoordinates().x() == 0 || entity.getCoordinates().y() == 0 + || entity.getCoordinates().x() == entity.getMesh().getDimensions().x() - 1 + || entity.getCoordinates().y() == entity.getMesh().getDimensions().y() - 1 ); + } +}; + +template< typename Real, typename Device, typename Index > +class BoundaryGridEntityChecker< GridEntity< Meshes::Grid< 2, Real, Device, Index >, 1 > > +{ +public: + using Entity = GridEntity< Meshes::Grid< 2, Real, Device, Index >, 1 >; + + __cuda_callable__ + inline static bool + isBoundaryEntity( const Entity& entity ) + { + return ( + ( entity.getBasis().x() + && ( entity.getCoordinates().x() == 0 || entity.getCoordinates().x() == entity.getMesh().getDimensions().x() ) ) + || ( entity.getBasis().y() + && ( entity.getCoordinates().y() == 0 + || entity.getCoordinates().y() == entity.getMesh().getDimensions().y() ) ) ); + } +}; + +template< typename Real, typename Device, typename Index > +class BoundaryGridEntityChecker< GridEntity< Meshes::Grid< 2, Real, Device, Index >, 0 > > +{ +public: + using Entity = GridEntity< Meshes::Grid< 2, Real, Device, Index >, 0 >; + + __cuda_callable__ + inline static bool + isBoundaryEntity( const Entity& entity ) + { + return ( entity.getCoordinates().x() == 0 || entity.getCoordinates().x() == entity.getMesh().getDimensions().x() ) + || ( entity.getCoordinates().y() == 0 || entity.getCoordinates().y() == entity.getMesh().getDimensions().y() ); + } +}; + +/*** + * 3D grid + */ +template< typename Real, typename Device, typename Index > +class BoundaryGridEntityChecker< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 3 > > +{ +public: + using Entity = GridEntity< Meshes::Grid< 3, Real, Device, Index >, 3 >; + + __cuda_callable__ + inline static bool + isBoundaryEntity( const Entity& entity ) + { + return ( entity.getCoordinates().x() == 0 || entity.getCoordinates().y() == 0 || entity.getCoordinates().z() == 0 + || entity.getCoordinates().x() == entity.getMesh().getDimensions().x() - 1 + || entity.getCoordinates().y() == entity.getMesh().getDimensions().y() - 1 + || entity.getCoordinates().z() == entity.getMesh().getDimensions().z() - 1 ); + } +}; + +template< typename Real, typename Device, typename Index > +class BoundaryGridEntityChecker< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 2 > > +{ +public: + using Entity = GridEntity< Meshes::Grid< 3, Real, Device, Index >, 2 >; + + __cuda_callable__ + inline static bool + isBoundaryEntity( const Entity& entity ) + { + return ( + ( entity.getBasis().x() + && ( entity.getCoordinates().x() == 0 || entity.getCoordinates().x() == entity.getMesh().getDimensions().x() ) ) + || ( entity.getBasis().y() + && ( entity.getCoordinates().y() == 0 || entity.getCoordinates().y() == entity.getMesh().getDimensions().y() ) ) + || ( entity.getBasis().z() + && ( entity.getCoordinates().z() == 0 + || entity.getCoordinates().z() == entity.getMesh().getDimensions().z() ) ) ); + } +}; + +template< typename Real, typename Device, typename Index > +class BoundaryGridEntityChecker< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 1 > > +{ +public: + using Entity = GridEntity< Meshes::Grid< 3, Real, Device, Index >, 1 >; + + __cuda_callable__ + inline static bool + isBoundaryEntity( const Entity& entity ) + { + return ( + ( entity.getBasis().x() + && ( entity.getCoordinates().x() == 0 || entity.getCoordinates().x() == entity.getMesh().getDimensions().x() ) ) + || ( entity.getBasis().y() + && ( entity.getCoordinates().y() == 0 || entity.getCoordinates().y() == entity.getMesh().getDimensions().y() ) ) + || ( entity.getBasis().z() + && ( entity.getCoordinates().z() == 0 + || entity.getCoordinates().z() == entity.getMesh().getDimensions().z() ) ) ); + } +}; + +template< typename Real, typename Device, typename Index > +class BoundaryGridEntityChecker< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 0 > > +{ +public: + using Entity = GridEntity< Meshes::Grid< 3, Real, Device, Index >, 0 >; + + __cuda_callable__ + inline static bool + isBoundaryEntity( const Entity& entity ) + { + return ( entity.getCoordinates().x() == 0 || entity.getCoordinates().x() == entity.getMesh().getDimensions().x() ) + || ( entity.getCoordinates().y() == 0 || entity.getCoordinates().y() == entity.getMesh().getDimensions().y() ) + || ( entity.getCoordinates().z() == 0 || entity.getCoordinates().z() == entity.getMesh().getDimensions().z() ); + } +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Implementations/Grid1D.hpp b/src/TNL/Meshes/GridDetails/Implementations/Grid1D.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3acdfa0e374a8fb15cef133e35431e0264221a8c --- /dev/null +++ b/src/TNL/Meshes/GridDetails/Implementations/Grid1D.hpp @@ -0,0 +1,151 @@ +// Copyright (c) 2004-2022 Tomáš Oberhuber et al. +// +// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include +#include + +namespace TNL { +namespace Meshes { + +#define __GRID_1D_TEMPLATE__ template< typename Real, typename Device, typename Index > +#define __GRID_1D_PREFIX__ Grid< 1, Real, Device, Index > + +__GRID_1D_TEMPLATE__ +__GRID_1D_PREFIX__::Grid( const Index xSize ) +{ + this->setDimensions( xSize ); +} + +__GRID_1D_TEMPLATE__ +template< typename Entity > +__cuda_callable__ +inline Index +__GRID_1D_PREFIX__::getEntityIndex( const Entity& entity ) const +{ + static_assert( Templates::isInClosedInterval( 0, Entity::entityDimension, 1 ), "Wrong grid entity dimensions." ); + + return GridEntityGetter< Grid, Entity::entityDimension >::getEntityIndex( *this, entity ); +} + +__GRID_1D_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__GRID_1D_PREFIX__::forAll( Func func, FuncArgs... args ) const +{ + auto exec = [ = ] __cuda_callable__( const Coordinate& coordinate, + const Coordinate& basis, + const Index orientation, + const Grid& grid, + FuncArgs... args ) mutable + { + EntityType< EntityDimension > entity( grid, coordinate, basis, orientation ); + + func( entity, args... ); + }; + + this->template traverseAll< EntityDimension >( exec, *this, args... ); +} + +__GRID_1D_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__GRID_1D_PREFIX__::forAll( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const +{ + auto exec = [ = ] __cuda_callable__( const Coordinate& coordinate, + const Coordinate& basis, + const Index orientation, + const Grid& grid, + FuncArgs... args ) mutable + { + EntityType< EntityDimension > entity( grid, coordinate, basis, orientation ); + + func( entity, args... ); + }; + + this->template traverseAll< EntityDimension >( from, to, exec, *this, args... ); +} + +__GRID_1D_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__GRID_1D_PREFIX__::forBoundary( Func func, FuncArgs... args ) const +{ + auto exec = [ = ] __cuda_callable__( const Coordinate& coordinate, + const Coordinate& basis, + const Index orientation, + const Grid& grid, + FuncArgs... args ) mutable + { + EntityType< EntityDimension > entity( grid, coordinate, basis, orientation ); + + func( entity, args... ); + }; + + this->template traverseBoundary< EntityDimension >( exec, *this, args... ); +} + +__GRID_1D_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__GRID_1D_PREFIX__::forBoundary( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const +{ + auto exec = [ = ] __cuda_callable__( const Coordinate& coordinate, + const Coordinate& basis, + const Index orientation, + const Grid& grid, + FuncArgs... args ) mutable + { + EntityType< EntityDimension > entity( grid, coordinate, basis, orientation ); + + func( entity, args... ); + }; + + this->template traverseBoundary< EntityDimension >( from, to, exec, *this, args... ); +} + +__GRID_1D_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__GRID_1D_PREFIX__::forInterior( Func func, FuncArgs... args ) const +{ + auto exec = [ = ] __cuda_callable__( const Coordinate& coordinate, + const Coordinate& basis, + const Index orientation, + const Grid& grid, + FuncArgs... args ) mutable + { + EntityType< EntityDimension > entity( grid, coordinate, basis, orientation ); + + func( entity, args... ); + }; + + this->template traverseInterior< EntityDimension >( exec, *this, args... ); +} + +__GRID_1D_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__GRID_1D_PREFIX__::forInterior( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const +{ + auto exec = [ = ] __cuda_callable__( const Coordinate& coordinate, + const Coordinate& basis, + const Index orientation, + const Grid& grid, + FuncArgs... args ) mutable + { + EntityType< EntityDimension > entity( grid, coordinate, basis, orientation ); + + func( entity, args... ); + }; + + this->template traverseInterior< EntityDimension >( from, to, exec, *this, args... ); +} + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Implementations/Grid2D.hpp b/src/TNL/Meshes/GridDetails/Implementations/Grid2D.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6100d8a1439cb276a6223f6e55d555fba12081a5 --- /dev/null +++ b/src/TNL/Meshes/GridDetails/Implementations/Grid2D.hpp @@ -0,0 +1,151 @@ +// Copyright (c) 2004-2022 Tomáš Oberhuber et al. +// +// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include +#include + +namespace TNL { +namespace Meshes { + +#define __GRID_2D_TEMPLATE__ template< typename Real, typename Device, typename Index > +#define __GRID_2D_PREFIX__ Grid< 2, Real, Device, Index > + +__GRID_2D_TEMPLATE__ +__GRID_2D_PREFIX__::Grid( const Index xSize, const Index ySize ) +{ + this->setDimensions( xSize, ySize ); +} + +__GRID_2D_TEMPLATE__ +template< typename Entity > +__cuda_callable__ +inline Index +__GRID_2D_PREFIX__::getEntityIndex( const Entity& entity ) const +{ + static_assert( Entity::entityDimension <= 2 && Entity::entityDimension >= 0, "Wrong grid entity dimensions." ); + + return GridEntityGetter< Grid, Entity::entityDimension >::getEntityIndex( *this, entity ); +} + +__GRID_2D_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__GRID_2D_PREFIX__::forAll( Func func, FuncArgs... args ) const +{ + auto exec = [ = ] __cuda_callable__( const Coordinate& coordinate, + const Coordinate& basis, + const Index orientation, + const Grid& grid, + FuncArgs... args ) mutable + { + EntityType< EntityDimension > entity( grid, coordinate, basis, orientation ); + + func( entity, args... ); + }; + + this->template traverseAll< EntityDimension >( exec, *this, args... ); +} + +__GRID_2D_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__GRID_2D_PREFIX__::forAll( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const +{ + auto exec = [ = ] __cuda_callable__( const Coordinate& coordinate, + const Coordinate& basis, + const Index orientation, + const Grid& grid, + FuncArgs... args ) mutable + { + EntityType< EntityDimension > entity( grid, coordinate, basis, orientation ); + + func( entity, args... ); + }; + + this->template traverseAll< EntityDimension >( from, to, exec, *this, args... ); +} + +__GRID_2D_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__GRID_2D_PREFIX__::forInterior( Func func, FuncArgs... args ) const +{ + auto exec = [ = ] __cuda_callable__( const Coordinate& coordinate, + const Coordinate& basis, + const Index orientation, + const Grid& grid, + FuncArgs... args ) mutable + { + EntityType< EntityDimension > entity( grid, coordinate, basis, orientation ); + + func( entity, args... ); + }; + + this->template traverseInterior< EntityDimension >( exec, *this, args... ); +} + +__GRID_2D_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__GRID_2D_PREFIX__::forInterior( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const +{ + auto exec = [ = ] __cuda_callable__( const Coordinate& coordinate, + const Coordinate& basis, + const Index orientation, + const Grid& grid, + FuncArgs... args ) mutable + { + EntityType< EntityDimension > entity( grid, coordinate, basis, orientation ); + + func( entity, args... ); + }; + + this->template traverseInterior< EntityDimension >( from, to, exec, *this, args... ); +} + +__GRID_2D_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__GRID_2D_PREFIX__::forBoundary( Func func, FuncArgs... args ) const +{ + auto exec = [ = ] __cuda_callable__( const Coordinate& coordinate, + const Coordinate& basis, + const Index orientation, + const Grid& grid, + FuncArgs... args ) mutable + { + EntityType< EntityDimension > entity( grid, coordinate, basis, orientation ); + + func( entity, args... ); + }; + + this->template traverseBoundary< EntityDimension >( exec, *this, args... ); +} + +__GRID_2D_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__GRID_2D_PREFIX__::forBoundary( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const +{ + auto exec = [ = ] __cuda_callable__( const Coordinate& coordinate, + const Coordinate& basis, + const Index orientation, + const Grid& grid, + FuncArgs... args ) mutable + { + EntityType< EntityDimension > entity( grid, coordinate, basis, orientation ); + + func( entity, args... ); + }; + + this->template traverseBoundary< EntityDimension >( from, to, exec, *this, args... ); +} + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Implementations/Grid3D.hpp b/src/TNL/Meshes/GridDetails/Implementations/Grid3D.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d4daefe8bc5a7a94d2ba2da67277dca2ebc3e97c --- /dev/null +++ b/src/TNL/Meshes/GridDetails/Implementations/Grid3D.hpp @@ -0,0 +1,155 @@ +/*************************************************************************** + Grid3D_impl.h - description + ------------------- + begin : Jan 16, 2013 + copyright : (C) 2013 by Tomas Oberhuber + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include +#include +#include + +namespace TNL { +namespace Meshes { + +#define __GRID_3D_TEMPLATE__ template< typename Real, typename Device, typename Index > +#define __GRID_3D_PREFIX__ Grid< 3, Real, Device, Index > + +__GRID_3D_TEMPLATE__ +__GRID_3D_PREFIX__::Grid( const Index xSize, const Index ySize, const Index zSize ) +{ + this->setDimensions( xSize, ySize, zSize ); +} + +__GRID_3D_TEMPLATE__ +template< typename Entity > +__cuda_callable__ +inline Index +__GRID_3D_PREFIX__::getEntityIndex( const Entity& entity ) const +{ + static_assert( Entity::entityDimension <= 3 && Entity::entityDimension >= 0, "Wrong grid entity dimensions." ); + + return GridEntityGetter< Grid, Entity::entityDimension >::getEntityIndex( *this, entity ); +} + +__GRID_3D_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__GRID_3D_PREFIX__::forAll( Func func, FuncArgs... args ) const +{ + auto exec = [ = ] __cuda_callable__( const Coordinate& coordinate, + const Coordinate& basis, + const Index orientation, + const Grid& grid, + FuncArgs... args ) mutable + { + EntityType< EntityDimension > entity( grid, coordinate, basis, orientation ); + + func( entity, args... ); + }; + + this->template traverseAll< EntityDimension >( exec, *this, args... ); +} + +__GRID_3D_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__GRID_3D_PREFIX__::forAll( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const +{ + auto exec = [ = ] __cuda_callable__( const Coordinate& coordinate, + const Coordinate& basis, + const Index orientation, + const Grid& grid, + FuncArgs... args ) mutable + { + EntityType< EntityDimension > entity( grid, coordinate, basis, orientation ); + + func( entity, args... ); + }; + + this->template traverseAll< EntityDimension >( from, to, exec, *this, args... ); +} + +__GRID_3D_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__GRID_3D_PREFIX__::forInterior( Func func, FuncArgs... args ) const +{ + auto exec = [ = ] __cuda_callable__( const Coordinate& coordinate, + const Coordinate& basis, + const Index orientation, + const Grid& grid, + FuncArgs... args ) mutable + { + EntityType< EntityDimension > entity( grid, coordinate, basis, orientation ); + + func( entity, args... ); + }; + + this->template traverseInterior< EntityDimension >( exec, *this, args... ); +} + +__GRID_3D_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__GRID_3D_PREFIX__::forInterior( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const +{ + auto exec = [ = ] __cuda_callable__( const Coordinate& coordinate, + const Coordinate& basis, + const Index orientation, + const Grid& grid, + FuncArgs... args ) mutable + { + EntityType< EntityDimension > entity( grid, coordinate, basis, orientation ); + + func( entity, args... ); + }; + + this->template traverseInterior< EntityDimension >( from, to, exec, *this, args... ); +} + +__GRID_3D_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__GRID_3D_PREFIX__::forBoundary( Func func, FuncArgs... args ) const +{ + auto exec = [ = ] __cuda_callable__( const Coordinate& coordinate, + const Coordinate& basis, + const Index orientation, + const Grid& grid, + FuncArgs... args ) mutable + { + EntityType< EntityDimension > entity( grid, coordinate, basis, orientation ); + + func( entity, args... ); + }; + + this->template traverseBoundary< EntityDimension >( exec, *this, args... ); +} + +__GRID_3D_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__GRID_3D_PREFIX__::forBoundary( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const +{ + auto exec = [ = ] __cuda_callable__( const Coordinate& coordinate, + const Coordinate& basis, + const Index orientation, + const Grid& grid, + FuncArgs... args ) mutable + { + EntityType< EntityDimension > entity( grid, coordinate, basis, orientation ); + + func( entity, args... ); + }; + + this->template traverseBoundary< EntityDimension >( from, to, exec, *this, args... ); +} + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Implementations/GridEntity.hpp b/src/TNL/Meshes/GridDetails/Implementations/GridEntity.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1bbc8918f3238ffddb1a748a21479480f19c2423 --- /dev/null +++ b/src/TNL/Meshes/GridDetails/Implementations/GridEntity.hpp @@ -0,0 +1,177 @@ +// Copyright (c) 2004-2022 Tomáš Oberhuber et al. +// +// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include +#include +#include +#include + +namespace TNL { +namespace Meshes { + +#define __GRID_ENTITY_TEMPLATE__ template< class Grid, int EntityDimension > +#define __GRID_ENTITY_PREFIX__ GridEntity< Grid, EntityDimension > + +__GRID_ENTITY_TEMPLATE__ +__cuda_callable__ +inline const typename __GRID_ENTITY_PREFIX__::Coordinate& +__GRID_ENTITY_PREFIX__::getCoordinates() const +{ + return this->coordinates; +} + +__GRID_ENTITY_TEMPLATE__ +__cuda_callable__ +inline typename __GRID_ENTITY_PREFIX__::Coordinate& +__GRID_ENTITY_PREFIX__::getCoordinates() +{ + return this->coordinates; +} + +__GRID_ENTITY_TEMPLATE__ +__cuda_callable__ +inline void +__GRID_ENTITY_PREFIX__::setCoordinates( const Coordinate& coordinates ) +{ + this->coordinates = coordinates; + refresh(); +} + +__GRID_ENTITY_TEMPLATE__ +__cuda_callable__ +inline void +__GRID_ENTITY_PREFIX__::refresh() +{ + this->index = this->grid.getEntityIndex( *this ); +} + +__GRID_ENTITY_TEMPLATE__ +__cuda_callable__ +inline typename __GRID_ENTITY_PREFIX__::Index +__GRID_ENTITY_PREFIX__::getIndex() const +{ + TNL_ASSERT_GE( this->index, 0, "Entity index is not non-negative." ); + TNL_ASSERT_LT( this->index, grid.template getEntitiesCount< EntityDimension >(), "Entity index is out of bounds." ); + TNL_ASSERT_EQ( this->index, grid.getEntityIndex( *this ), "Wrong value of stored index." ); + + return this->index; +} + +__GRID_ENTITY_TEMPLATE__ +__cuda_callable__ +inline bool +__GRID_ENTITY_PREFIX__::isBoundary() const +{ + return BoundaryGridEntityChecker< GridEntity >::isBoundaryEntity( *this ); +} + +__GRID_ENTITY_TEMPLATE__ +__cuda_callable__ +inline const typename __GRID_ENTITY_PREFIX__::Point +__GRID_ENTITY_PREFIX__::getCenter() const +{ + return GridEntityCenterGetter< GridEntity >::getEntityCenter( *this ); +} + +__GRID_ENTITY_TEMPLATE__ +__cuda_callable__ +inline typename __GRID_ENTITY_PREFIX__::Real +__GRID_ENTITY_PREFIX__::getMeasure() const +{ + return GridEntityMeasureGetter< Grid, EntityDimension >::getMeasure( this->getMesh(), *this ); +} + +__GRID_ENTITY_TEMPLATE__ +__cuda_callable__ +inline const Grid& +__GRID_ENTITY_PREFIX__::getMesh() const +{ + return this->grid; +} + +__GRID_ENTITY_TEMPLATE__ +__cuda_callable__ +inline typename __GRID_ENTITY_PREFIX__::Coordinate +__GRID_ENTITY_PREFIX__::getBasis() const +{ + return this->basis; +} + +__GRID_ENTITY_TEMPLATE__ +__cuda_callable__ +inline void +__GRID_ENTITY_PREFIX__::setBasis( const Coordinate& basis ) +{ + this->basis = basis; +} + +__GRID_ENTITY_TEMPLATE__ +__cuda_callable__ +inline typename __GRID_ENTITY_PREFIX__::Index +__GRID_ENTITY_PREFIX__::getOrientation() const +{ + return this->orientation; +} + +__GRID_ENTITY_TEMPLATE__ +__cuda_callable__ +inline void +__GRID_ENTITY_PREFIX__::setOrientation( const Index orientation ) { + this->orientation = orientation; +} + +__GRID_ENTITY_TEMPLATE__ +template< int Dimension, int... Steps, std::enable_if_t< sizeof...( Steps ) == Grid::getMeshDimension(), bool > > +__cuda_callable__ +inline GridEntity< Grid, Dimension > +__GRID_ENTITY_PREFIX__::getNeighbourEntity() const +{ + using Getter = NeighbourGridEntityGetter< meshDimension, entityDimension, Dimension >; + + return Getter::template getEntity< Grid, Steps... >( *this ); +} + +__GRID_ENTITY_TEMPLATE__ +template< int Dimension, + int Orientation, + int... Steps, + std::enable_if_t< sizeof...( Steps ) == Grid::getMeshDimension(), bool > > +__cuda_callable__ +inline GridEntity< Grid, Dimension > +__GRID_ENTITY_PREFIX__::getNeighbourEntity() const +{ + using Getter = NeighbourGridEntityGetter< meshDimension, entityDimension, Dimension >; + + return Getter::template getEntity< Grid, Orientation, Steps... >( *this ); +} + +__GRID_ENTITY_TEMPLATE__ +template< int Dimension > +__cuda_callable__ +inline GridEntity< Grid, Dimension > +__GRID_ENTITY_PREFIX__::getNeighbourEntity( const Coordinate& offset ) const +{ + using Getter = NeighbourGridEntityGetter< meshDimension, entityDimension, Dimension >; + + return Getter::template getEntity< Grid >( *this, offset ); +} + +__GRID_ENTITY_TEMPLATE__ +template< int Dimension, int Orientation > +__cuda_callable__ +inline GridEntity< Grid, Dimension > +__GRID_ENTITY_PREFIX__::getNeighbourEntity( const Coordinate& offset ) const +{ + using Getter = NeighbourGridEntityGetter< meshDimension, entityDimension, Dimension >; + + return Getter::template getEntity< Grid, Orientation >( *this, offset ); +} + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Implementations/GridEntityCenterGetter.hpp b/src/TNL/Meshes/GridDetails/Implementations/GridEntityCenterGetter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..28baa74ee41bfb6640228052cfbe0a934766f759 --- /dev/null +++ b/src/TNL/Meshes/GridDetails/Implementations/GridEntityCenterGetter.hpp @@ -0,0 +1,165 @@ + +#pragma once + +#include + +namespace TNL { +namespace Meshes { +/*** + * 1D grids + */ +template< typename Real, typename Device, typename Index > +class GridEntityCenterGetter< GridEntity< Meshes::Grid< 1, Real, Device, Index >, 1 > > +{ +public: + using Grid = Meshes::Grid< 1, Real, Device, Index >; + using Entity = GridEntity< Grid, 1 >; + using Point = typename Grid::Point; + + __cuda_callable__ + inline static Point + getEntityCenter( const Entity& entity ) + { + const Grid& grid = entity.getMesh(); + return Point( grid.getOrigin().x() + ( entity.getCoordinates().x() + 0.5 ) * grid.getSpaceSteps().x() ); + } +}; + +template< typename Real, typename Device, typename Index > +class GridEntityCenterGetter< GridEntity< Meshes::Grid< 1, Real, Device, Index >, 0 > > +{ +public: + using Grid = Meshes::Grid< 1, Real, Device, Index >; + using Entity = GridEntity< Grid, 0 >; + using Point = typename Grid::Point; + + __cuda_callable__ + inline static Point + getEntityCenter( const Entity& entity ) + { + const Grid& grid = entity.getMesh(); + return Point( grid.getOrigin().x() + ( entity.getCoordinates().x() ) * grid.getSpaceSteps().x() ); + } +}; + +/**** + * 2D grids + */ +template< typename Real, typename Device, typename Index > +class GridEntityCenterGetter< GridEntity< Meshes::Grid< 2, Real, Device, Index >, 2 > > +{ +public: + using Grid = Meshes::Grid< 2, Real, Device, Index >; + using Entity = GridEntity< Grid, 2 >; + using Point = typename Grid::Point; + + __cuda_callable__ + inline static Point + getEntityCenter( const Entity& entity ) + { + const Grid& grid = entity.getMesh(); + return Point( grid.getOrigin().x() + ( entity.getCoordinates().x() + 0.5 ) * grid.getSpaceSteps().x(), + grid.getOrigin().y() + ( entity.getCoordinates().y() + 0.5 ) * grid.getSpaceSteps().y() ); + } +}; + +template< typename Real, typename Device, typename Index > +class GridEntityCenterGetter< GridEntity< Meshes::Grid< 2, Real, Device, Index >, 1 > > +{ +public: + using Grid = Meshes::Grid< 2, Real, Device, Index >; + using Entity = GridEntity< Grid, 1 >; + using Point = typename Grid::Point; + + __cuda_callable__ + inline static Point + getEntityCenter( const Entity& entity ) + { + const Grid& grid = entity.getMesh(); + return Point( + grid.getOrigin().x() + ( entity.getCoordinates().x() + 0.5 * ! entity.getBasis().x() ) * grid.getSpaceSteps().x(), + grid.getOrigin().y() + ( entity.getCoordinates().y() + 0.5 * ! entity.getBasis().y() ) * grid.getSpaceSteps().y() ); + } +}; + +template< typename Real, typename Device, typename Index > +class GridEntityCenterGetter< GridEntity< Meshes::Grid< 2, Real, Device, Index >, 0 > > +{ +public: + using Grid = Meshes::Grid< 2, Real, Device, Index >; + using Entity = GridEntity< Grid, 0 >; + using Point = typename Grid::Point; + + __cuda_callable__ + inline static Point + getEntityCenter( const Entity& entity ) + { + const Grid& grid = entity.getMesh(); + return Point( grid.getOrigin().x() + entity.getCoordinates().x() * grid.getSpaceSteps().x(), + grid.getOrigin().y() + entity.getCoordinates().y() * grid.getSpaceSteps().y() ); + } +}; + +/*** + * 3D grid + */ +template< typename Real, typename Device, typename Index, int EntityDimension > +class GridEntityCenterGetter< GridEntity< Meshes::Grid< 3, Real, Device, Index >, EntityDimension > > +{ +public: + using Grid = Meshes::Grid< 3, Real, Device, Index >; + using Entity = GridEntity< Grid, EntityDimension >; + using Point = typename Grid::Point; + + __cuda_callable__ + inline static Point + getEntityCenter( const Entity& entity ) + { + const Grid& grid = entity.getMesh(); + return Point( + grid.getOrigin().x() + ( entity.getCoordinates().x() + 0.5 * ! entity.getBasis().x() ) * grid.getSpaceSteps().x(), + grid.getOrigin().y() + ( entity.getCoordinates().y() + 0.5 * ! entity.getBasis().y() ) * grid.getSpaceSteps().y(), + grid.getOrigin().z() + ( entity.getCoordinates().z() + 0.5 * ! entity.getBasis().z() ) * grid.getSpaceSteps().z() ); + } +}; + +template< typename Real, typename Device, typename Index > +class GridEntityCenterGetter< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 3 > > +{ +public: + using Grid = Meshes::Grid< 3, Real, Device, Index >; + using Entity = GridEntity< Grid, 3 >; + using Point = typename Grid::Point; + + __cuda_callable__ + inline static Point + getEntityCenter( const Entity& entity ) + { + const Grid& grid = entity.getMesh(); + return Point( grid.getOrigin().x() + ( entity.getCoordinates().x() + 0.5 ) * grid.getSpaceSteps().x(), + grid.getOrigin().y() + ( entity.getCoordinates().y() + 0.5 ) * grid.getSpaceSteps().y(), + grid.getOrigin().z() + ( entity.getCoordinates().z() + 0.5 ) * grid.getSpaceSteps().z() ); + } +}; + +template< typename Real, typename Device, typename Index > +class GridEntityCenterGetter< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 0 > > +{ +public: + using Grid = Meshes::Grid< 3, Real, Device, Index >; + using Entity = GridEntity< Grid, 0 >; + using Point = typename Grid::Point; + + __cuda_callable__ + inline static Point + getEntityCenter( const Entity& entity ) + { + const Grid& grid = entity.getMesh(); + return Point( grid.getOrigin().x() + ( entity.getCoordinates().x() ) * grid.getSpaceSteps().x(), + grid.getOrigin().y() + ( entity.getCoordinates().y() ) * grid.getSpaceSteps().y(), + grid.getOrigin().z() + ( entity.getCoordinates().z() ) * grid.getSpaceSteps().z() ); + } +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Implementations/GridEntityGetter.hpp b/src/TNL/Meshes/GridDetails/Implementations/GridEntityGetter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..277595701de12b407f3f138820e2dba04e2213a5 --- /dev/null +++ b/src/TNL/Meshes/GridDetails/Implementations/GridEntityGetter.hpp @@ -0,0 +1,224 @@ + +#pragma once + +#include + +namespace TNL { +namespace Meshes { + +/**** + * 1D grid + */ +template< typename Real, typename Device, typename Index, int EntityDimension > +class GridEntityGetter< Meshes::Grid< 1, Real, Device, Index >, EntityDimension > +{ +public: + static constexpr int entityDimension = EntityDimension; + + using Grid = Meshes::Grid< 1, Real, Device, Index >; + using Entity = GridEntity< Grid, EntityDimension >; + using Coordinate = typename Grid::Coordinate; + + __cuda_callable__ + inline static Index + getEntityIndex( const Grid& grid, const Entity& entity ) + { + TNL_ASSERT_GE( entity.getCoordinates(), Coordinate( 0 ), "wrong coordinates" ); + TNL_ASSERT_LT( entity.getCoordinates(), grid.getDimensions() + entity.getBasis(), "wrong coordinates" ); + + return entity.getCoordinates().x(); + } +}; + +/**** + * 2D grid + */ +template< typename Real, typename Device, typename Index > +class GridEntityGetter< Meshes::Grid< 2, Real, Device, Index >, 2 > +{ +public: + static constexpr int entityDimension = 2; + + using Grid = Meshes::Grid< 2, Real, Device, Index >; + using Entity = GridEntity< Grid, entityDimension >; + using Coordinate = typename Grid::Coordinate; + + __cuda_callable__ + inline static Index + getEntityIndex( const Grid& grid, const Entity& entity ) + { + TNL_ASSERT_GE( entity.getCoordinates(), Coordinate( 0, 0 ), "wrong coordinates" ); + TNL_ASSERT_LT( entity.getCoordinates(), grid.getDimensions() + entity.getBasis(), "wrong coordinates" ); + + return entity.getCoordinates().y() * grid.getDimensions().x() + entity.getCoordinates().x(); + } +}; + +template< typename Real, typename Device, typename Index > +class GridEntityGetter< Meshes::Grid< 2, Real, Device, Index >, 1 > +{ +public: + static constexpr int entityDimension = 1; + + using Grid = Meshes::Grid< 2, Real, Device, Index >; + using Entity = GridEntity< Grid, entityDimension >; + using Coordinate = typename Grid::Coordinate; + + __cuda_callable__ + inline static Index + getEntityIndex( const Grid& grid, const Entity& entity ) + { + TNL_ASSERT_GE( entity.getCoordinates(), Coordinate( 0, 0 ), "wrong coordinates" ); + TNL_ASSERT_LT( entity.getCoordinates(), grid.getDimensions() + entity.getBasis(), "wrong coordinates" ); + + const Coordinate& coordinates = entity.getCoordinates(); + const Coordinate& dimensions = grid.getDimensions(); + + if( entity.getOrientation() == 0 ) + return coordinates.y() * ( dimensions.x() ) + coordinates.x(); + + return grid.template getOrientedEntitiesCount< 1, 0 >() + coordinates.y() * ( dimensions.x() + 1 ) + coordinates.x(); + } +}; + +template< typename Real, typename Device, typename Index > +class GridEntityGetter< Meshes::Grid< 2, Real, Device, Index >, 0 > +{ +public: + static constexpr int entityDimension = 0; + + using Grid = Meshes::Grid< 2, Real, Device, Index >; + using Entity = GridEntity< Grid, entityDimension >; + using Coordinate = typename Grid::Coordinate; + + __cuda_callable__ + inline static Index + getEntityIndex( const Grid& grid, const Entity& entity ) + { + TNL_ASSERT_GE( entity.getCoordinates(), Coordinate( 0, 0 ), "wrong coordinates" ); + TNL_ASSERT_LT( entity.getCoordinates(), grid.getDimensions() + entity.getBasis(), "wrong coordinates" ); + + const Coordinate& coordinates = entity.getCoordinates(); + const Coordinate& dimensions = grid.getDimensions(); + + return coordinates.y() * ( dimensions.x() + 1 ) + coordinates.x(); + } +}; + +/**** + * 3D grid + */ +template< typename Real, typename Device, typename Index > +class GridEntityGetter< Meshes::Grid< 3, Real, Device, Index >, 3 > +{ +public: + static constexpr int entityDimension = 3; + + using Grid = Meshes::Grid< 3, Real, Device, Index >; + using Entity = GridEntity< Grid, entityDimension >; + using Coordinate = typename Grid::Coordinate; + + __cuda_callable__ + inline static Index + getEntityIndex( const Grid& grid, const Entity& entity ) + { + TNL_ASSERT_GE( entity.getCoordinates(), Coordinate( 0, 0, 0 ), "wrong coordinates" ); + TNL_ASSERT_LT( entity.getCoordinates(), grid.getDimensions() + entity.getBasis(), "wrong coordinates" ); + + const Coordinate coordinates = entity.getCoordinates(); + const Coordinate dimensions = grid.getDimensions(); + + return ( coordinates.z() * dimensions.y() + coordinates.y() ) * dimensions.x() + coordinates.x(); + } +}; + +template< typename Real, typename Device, typename Index > +class GridEntityGetter< Meshes::Grid< 3, Real, Device, Index >, 2 > +{ +public: + static constexpr int entityDimension = 2; + + using Grid = Meshes::Grid< 3, Real, Device, Index >; + using Entity = GridEntity< Grid, entityDimension >; + using Coordinate = typename Grid::Coordinate; + + __cuda_callable__ + inline static Index + getEntityIndex( const Grid& grid, const Entity& entity ) + { + TNL_ASSERT_GE( entity.getCoordinates(), Coordinate( 0, 0, 0 ), "wrong coordinates" ); + TNL_ASSERT_LT( entity.getCoordinates(), grid.getDimensions() + entity.getBasis(), "wrong coordinates" ); + + const Coordinate& coordinates = entity.getCoordinates(); + const Coordinate& dimensions = grid.getDimensions(); + + if( entity.getOrientation() == 0 ) + return ( coordinates.z() * dimensions.y() + coordinates.y() ) * ( dimensions.x() ) + coordinates.x(); + + if( entity.getOrientation() == 1 ) + return grid.template getOrientedEntitiesCount< 2, 0 >() + + ( coordinates.z() * ( dimensions.y() + 1 ) + coordinates.y() ) * dimensions.x() + coordinates.x(); + + return grid.template getOrientedEntitiesCount< 2, 1 >() + grid.template getOrientedEntitiesCount< 2, 0 >() + + ( coordinates.z() * dimensions.y() + coordinates.y() ) * ( dimensions.x() + 1 ) + coordinates.x(); + } +}; + +template< typename Real, typename Device, typename Index > +class GridEntityGetter< Meshes::Grid< 3, Real, Device, Index >, 1 > +{ +public: + static constexpr int entityDimension = 1; + + using Grid = Meshes::Grid< 3, Real, Device, Index >; + using Entity = GridEntity< Grid, entityDimension >; + using Coordinate = typename Grid::Coordinate; + + __cuda_callable__ + inline static Index + getEntityIndex( const Grid& grid, const Entity& entity ) + { + TNL_ASSERT_GE( entity.getCoordinates(), Coordinate( 0, 0, 0 ), "wrong coordinates" ); + TNL_ASSERT_LT( entity.getCoordinates(), grid.getDimensions() + entity.getBasis(), "wrong coordinates" ); + + const Coordinate& coordinates = entity.getCoordinates(); + const Coordinate& dimensions = grid.getDimensions(); + + if( entity.getOrientation() == 0 ) + return ( coordinates.z() * ( dimensions.y() + 1 ) + coordinates.y() ) * dimensions.x() + coordinates.x(); + + if( entity.getOrientation() == 1 ) + return grid.template getOrientedEntitiesCount< 1, 0 >() + + ( coordinates.z() * dimensions.y() + coordinates.y() ) * ( dimensions.x() + 1 ) + coordinates.x(); + + return grid.template getOrientedEntitiesCount< 1, 1 >() + grid.template getOrientedEntitiesCount< 1, 0 >() + + ( coordinates.z() * ( dimensions.y() + 1 ) + coordinates.y() ) * ( dimensions.x() + 1 ) + coordinates.x(); + } +}; + +template< typename Real, typename Device, typename Index > +class GridEntityGetter< Meshes::Grid< 3, Real, Device, Index >, 0 > +{ +public: + static constexpr int entityDimension = 0; + + using Grid = Meshes::Grid< 3, Real, Device, Index >; + using Entity = GridEntity< Grid, entityDimension >; + using Coordinate = typename Grid::Coordinate; + + __cuda_callable__ + inline static Index + getEntityIndex( const Grid& grid, const Entity& entity ) + { + TNL_ASSERT_GE( entity.getCoordinates(), Coordinate( 0, 0, 0 ), "wrong coordinates" ); + TNL_ASSERT_LT( entity.getCoordinates(), grid.getDimensions() + entity.getBasis(), "wrong coordinates" ); + + const Coordinate coordinates = entity.getCoordinates(); + const Coordinate dimensions = grid.getDimensions(); + + return ( coordinates.z() * ( dimensions.y() + 1 ) + coordinates.y() ) * ( dimensions.x() + 1 ) + coordinates.x(); + } +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Implementations/GridEntityMeasureGetter.hpp b/src/TNL/Meshes/GridDetails/Implementations/GridEntityMeasureGetter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..fdfb971d0c79b9b15db7de8fda5e7f54ed05983e --- /dev/null +++ b/src/TNL/Meshes/GridDetails/Implementations/GridEntityMeasureGetter.hpp @@ -0,0 +1,143 @@ + +#pragma once + +#include + +namespace TNL { +namespace Meshes { + +/*** + * Common implementation for vertices + */ +template< int Dimension, typename Real, typename Device, typename Index > +class GridEntityMeasureGetter< Meshes::Grid< Dimension, Real, Device, Index >, 0 > +{ +public: + using GridType = Grid< Dimension, Real, Device, Index >; + + template< typename EntityType > + __cuda_callable__ + inline static Real + getMeasure( const GridType& grid, const EntityType& entity ) + { + return 0.0; + } +}; + +/**** + * 1D grid + */ + +template< typename Real, typename Device, typename Index > +class GridEntityMeasureGetter< Meshes::Grid< 1, Real, Device, Index >, 1 > +{ +public: + using GridType = Grid< 1, Real, Device, Index >; + + template< typename EntityType > + __cuda_callable__ + inline static Real + getMeasure( const GridType& grid, const EntityType& entity ) + { + return grid.template getSpaceStepsProducts< 1 >(); + } +}; + +/**** + * 2D grid + */ +template< typename Real, typename Device, typename Index > +class GridEntityMeasureGetter< Meshes::Grid< 2, Real, Device, Index >, 2 > +{ +public: + using GridType = Grid< 2, Real, Device, Index >; + + template< typename EntityType > + __cuda_callable__ + inline static Real + getMeasure( const GridType& grid, const EntityType& entity ) + { + return grid.template getSpaceStepsProducts< 1, 1 >(); + } +}; + +template< typename Real, typename Device, typename Index > +class GridEntityMeasureGetter< Meshes::Grid< 2, Real, Device, Index >, 1 > +{ +public: + using GridType = Grid< 2, Real, Device, Index >; + + template< typename EntityType > + __cuda_callable__ + inline static Real + getMeasure( const GridType& grid, const EntityType& entity ) + { + if( entity.getOrientation() == 0 ) + return grid.template getSpaceStepsProducts< 1, 0 >(); + + return grid.template getSpaceStepsProducts< 0, 1 >(); + } +}; + +/**** + * 3D grid + */ +template< typename Real, typename Device, typename Index > +class GridEntityMeasureGetter< Meshes::Grid< 3, Real, Device, Index >, 3 > +{ +public: + using GridType = Grid< 3, Real, Device, Index >; + + template< typename EntityType > + __cuda_callable__ + inline static Real + getMeasure( const GridType& grid, const EntityType& entity ) + { + return grid.template getSpaceStepsProducts< 1, 1, 1 >(); + } +}; + +template< typename Real, typename Device, typename Index > +class GridEntityMeasureGetter< Meshes::Grid< 3, Real, Device, Index >, 2 > +{ +public: + using GridType = Grid< 3, Real, Device, Index >; + + template< typename EntityType > + __cuda_callable__ + inline static Real + getMeasure( const GridType& grid, const EntityType& entity ) + { + if( entity.getOrientation() == 0 ) + return grid.template getSpaceStepsProducts< 1, 1, 0 >(); + + if( entity.getOrientation() == 1 ) + return grid.template getSpaceStepsProducts< 1, 0, 1 >(); + + return grid.template getSpaceStepsProducts< 0, 1, 1 >(); + } +}; + +template< typename Real, typename Device, typename Index > +class GridEntityMeasureGetter< Meshes::Grid< 3, Real, Device, Index >, 1 > +{ +public: + using GridType = Grid< 3, Real, Device, Index >; + + template< typename EntityType > + __cuda_callable__ + inline static Real + getMeasure( const GridType& grid, const EntityType& entity ) + { + if( entity.getOrientation() == 0 ) + return grid.template getSpaceStepsProducts< 1, 0, 0 >(); + + if( entity.getOrientation() == 1 ) + return grid.template getSpaceStepsProducts< 0, 1, 0 >(); + + return grid.template getSpaceStepsProducts< 0, 0, 1 >(); + } +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Implementations/NDimGrid.hpp b/src/TNL/Meshes/GridDetails/Implementations/NDimGrid.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e2fbe57616ccba4cd33f758bc348ed75006a8304 --- /dev/null +++ b/src/TNL/Meshes/GridDetails/Implementations/NDimGrid.hpp @@ -0,0 +1,585 @@ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace TNL { +namespace Meshes { + +#define __NDIMGRID_TEMPLATE__ template< int Dimension, typename Real, typename Device, typename Index > +#define __NDIM_PREFIX__ NDimGrid< Dimension, Real, Device, Index > + +__NDIMGRID_TEMPLATE__ +constexpr Index +__NDIM_PREFIX__::getEntityOrientationsCount( const Index entityDimension ) +{ + const Index dimension = Dimension; + + return Templates::combination< Index >( entityDimension, dimension ); +} + +__NDIMGRID_TEMPLATE__ +template< typename... Dimensions, + std::enable_if_t< Templates::conjunction_v< std::is_convertible< Index, Dimensions >... >, bool >, + std::enable_if_t< sizeof...( Dimensions ) == Dimension, bool > > +void +__NDIM_PREFIX__::setDimensions( Dimensions... dimensions ) +{ + this->dimensions = Coordinate( dimensions... ); + + TNL_ASSERT_GE( this->dimensions, Coordinate( 0 ), "Dimension must be positive" ); + + fillEntitiesCount(); + fillSpaceSteps(); +} + +__NDIMGRID_TEMPLATE__ +void +__NDIM_PREFIX__::setDimensions( const typename __NDIM_PREFIX__::Coordinate& dimensions ) +{ + this->dimensions = dimensions; + + TNL_ASSERT_GE( this->dimensions, Coordinate( 0 ), "Dimension must be positive" ); + + fillEntitiesCount(); + fillSpaceSteps(); +} + +__NDIMGRID_TEMPLATE__ +__cuda_callable__ +inline Index +__NDIM_PREFIX__::getDimension( const Index index ) const +{ + TNL_ASSERT_GE( index, 0, "Index must be greater or equal to zero" ); + TNL_ASSERT_LT( index, Dimension, "Index must be less than Dimension" ); + + return dimensions[ index ]; +} + +__NDIMGRID_TEMPLATE__ +template< typename... DimensionIndex, + std::enable_if_t< Templates::conjunction_v< std::is_convertible< Index, DimensionIndex >... >, bool >, + std::enable_if_t< ( sizeof...( DimensionIndex ) > 0 ), bool > > +__cuda_callable__ +inline typename __NDIM_PREFIX__::template Container< sizeof...( DimensionIndex ), Index > +__NDIM_PREFIX__::getDimensions( DimensionIndex... indices ) const noexcept +{ + Container< sizeof...( DimensionIndex ), Index > result{ indices... }; + + for( std::size_t i = 0; i < sizeof...( DimensionIndex ); i++ ) + result[ i ] = this->getDimension( result[ i ] ); + + return result; +} + +__NDIMGRID_TEMPLATE__ +__cuda_callable__ +inline const typename __NDIM_PREFIX__::template Container< Dimension, Index >& +__NDIM_PREFIX__::getDimensions() const noexcept +{ + return this->dimensions; +} + +__NDIMGRID_TEMPLATE__ +__cuda_callable__ +inline Index +__NDIM_PREFIX__::getEntitiesCount( const Index index ) const +{ + TNL_ASSERT_GE( index, 0, "Index must be greater than zero" ); + TNL_ASSERT_LE( index, Dimension, "Index must be less than or equal to Dimension" ); + + return this->cumulativeEntitiesCountAlongBases( index ); +} + +__NDIMGRID_TEMPLATE__ +template< int EntityDimension, std::enable_if_t< Templates::isInClosedInterval( 0, EntityDimension, Dimension ), bool > > +__cuda_callable__ +inline Index +__NDIM_PREFIX__::getEntitiesCount() const noexcept +{ + return this->cumulativeEntitiesCountAlongBases( EntityDimension ); +} + +__NDIMGRID_TEMPLATE__ +template< typename... DimensionIndex, + std::enable_if_t< Templates::conjunction_v< std::is_convertible< Index, DimensionIndex >... >, bool >, + std::enable_if_t< ( sizeof...( DimensionIndex ) > 0 ), bool > > +__cuda_callable__ +inline typename __NDIM_PREFIX__::template Container< sizeof...( DimensionIndex ), Index > +__NDIM_PREFIX__::getEntitiesCounts( DimensionIndex... indices ) const +{ + Container< sizeof...( DimensionIndex ), Index > result{ indices... }; + + for( std::size_t i = 0; i < sizeof...( DimensionIndex ); i++ ) + result[ i ] = this->cumulativeEntitiesCountAlongBases( result[ i ] ); + + return result; +} + +__NDIMGRID_TEMPLATE__ +__cuda_callable__ +inline const typename __NDIM_PREFIX__::EntitiesCounts& +__NDIM_PREFIX__::getEntitiesCounts() const noexcept +{ + return this->cumulativeEntitiesCountAlongBases; +} + +__NDIMGRID_TEMPLATE__ +void +__NDIM_PREFIX__::setOrigin( const typename __NDIM_PREFIX__::Point& origin ) noexcept +{ + this->origin = origin; +} + +__NDIMGRID_TEMPLATE__ +template< typename... Coordinates, + std::enable_if_t< Templates::conjunction_v< std::is_convertible< Real, Coordinates >... >, bool >, + std::enable_if_t< sizeof...( Coordinates ) == Dimension, bool > > +void +__NDIM_PREFIX__::setOrigin( Coordinates... coordinates ) noexcept +{ + this->origin = Point( coordinates... ); +} + +__NDIMGRID_TEMPLATE__ +__cuda_callable__ +inline Index +__NDIM_PREFIX__::getOrientedEntitiesCount( const Index dimension, const Index orientation ) const +{ + TNL_ASSERT_GE( dimension, 0, "Dimension must be greater than zero" ); + TNL_ASSERT_LE( dimension, Dimension, "Requested dimension must be less than or equal to Dimension" ); + + if( dimension == 0 || dimension == Dimension ) + return this->getEntitiesCount( dimension ); + + Index index = Templates::firstKCombinationSum( dimension, Dimension ) + orientation; + + return this->entitiesCountAlongBases[ index ]; +} + +__NDIMGRID_TEMPLATE__ +template< int EntityDimension > +__cuda_callable__ +inline typename __NDIM_PREFIX__::Coordinate +__NDIM_PREFIX__::getBasis( Index orientation ) const noexcept +{ + constexpr Index index = Templates::firstKCombinationSum( EntityDimension, Dimension ); + + return this->bases( index + orientation ); +} + +__NDIMGRID_TEMPLATE__ +template< int EntityDimension, + int EntityOrientation, + std::enable_if_t< Templates::isInClosedInterval( 0, EntityDimension, Dimension ), bool >, + std::enable_if_t< Templates::isInClosedInterval( 0, EntityOrientation, Dimension ), bool > > +__cuda_callable__ +inline Index +__NDIM_PREFIX__::getOrientedEntitiesCount() const noexcept +{ + if( EntityDimension == 0 || EntityDimension == Dimension ) + return this->getEntitiesCount( EntityDimension ); + + constexpr Index index = Templates::firstKCombinationSum( EntityDimension, Dimension ) + EntityOrientation; + + return this->entitiesCountAlongBases[ index ]; +} + +__NDIMGRID_TEMPLATE__ +__cuda_callable__ +inline const typename __NDIM_PREFIX__::Point& +__NDIM_PREFIX__::getOrigin() const noexcept +{ + return this->origin; +} + +__NDIMGRID_TEMPLATE__ +void +__NDIM_PREFIX__::setDomain( const typename __NDIM_PREFIX__::Point& origin, const typename __NDIM_PREFIX__::Point& proportions ) +{ + this->origin = origin; + this->proportions = proportions; + + this->fillSpaceSteps(); +} + +__NDIMGRID_TEMPLATE__ +void +__NDIM_PREFIX__::setSpaceSteps( const typename __NDIM_PREFIX__::Point& spaceSteps ) noexcept +{ + this->spaceSteps = spaceSteps; + + fillSpaceStepsPowers(); + fillProportions(); +} + +__NDIMGRID_TEMPLATE__ +template< typename... Steps, + std::enable_if_t< Templates::conjunction_v< std::is_convertible< Real, Steps >... >, bool >, + std::enable_if_t< sizeof...( Steps ) == Dimension, bool > > +void +__NDIM_PREFIX__::setSpaceSteps( Steps... spaceSteps ) noexcept +{ + this->spaceSteps = Point( spaceSteps... ); + + fillSpaceStepsPowers(); + fillProportions(); +} + +__NDIMGRID_TEMPLATE__ +__cuda_callable__ +inline const typename __NDIM_PREFIX__::Point& +__NDIM_PREFIX__::getSpaceSteps() const noexcept +{ + return this->spaceSteps; +} + +__NDIMGRID_TEMPLATE__ +__cuda_callable__ +inline const typename __NDIM_PREFIX__::Point& +__NDIM_PREFIX__::getProportions() const noexcept +{ + return this->proportions; +} + +__NDIMGRID_TEMPLATE__ +template< typename... Powers, + std::enable_if_t< Templates::conjunction_v< std::is_convertible< Index, Powers >... >, bool >, + std::enable_if_t< sizeof...( Powers ) == Dimension, bool > > +__cuda_callable__ +inline Real +__NDIM_PREFIX__::getSpaceStepsProducts( Powers... powers ) const +{ + int index = Templates::makeCollapsedIndex( this->spaceStepsPowersSize, Coordinate( powers... ) ); + + return this->spaceStepsProducts( index ); +} + +__NDIMGRID_TEMPLATE__ +__cuda_callable__ +inline Real +__NDIM_PREFIX__::getSpaceStepsProducts( const Coordinate& powers ) const +{ + int index = Templates::makeCollapsedIndex( this->spaceStepsPowersSize, powers ); + + return this->spaceStepsProducts( index ); +} + +__NDIMGRID_TEMPLATE__ +template< Index... Powers, std::enable_if_t< sizeof...( Powers ) == Dimension, bool > > +__cuda_callable__ +inline Real +__NDIM_PREFIX__::getSpaceStepsProducts() const noexcept +{ + constexpr int index = Templates::makeCollapsedIndex< Index, Powers... >( spaceStepsPowersSize ); + + return this->spaceStepsProducts( index ); +} + +__NDIMGRID_TEMPLATE__ +__cuda_callable__ +inline Real +__NDIM_PREFIX__::getSmallestSpaceStep() const noexcept +{ + Real minStep = this->spaceSteps[ 0 ]; + Index i = 1; + + while( i != Dimension ) + minStep = min( minStep, this->spaceSteps[ i++ ] ); + + return minStep; +} + +__NDIMGRID_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__NDIM_PREFIX__::traverseAll( Func func, FuncArgs... args ) const +{ + this->traverseAll< EntityDimension >( Coordinate( 0 ), this->getDimensions(), func, args... ); +} + +__NDIMGRID_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__NDIM_PREFIX__::traverseAll( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const +{ + TNL_ASSERT_GE( from, Coordinate( 0 ), "Traverse rect must be in the grid dimensions" ); + TNL_ASSERT_LE( to, this->getDimensions(), "Traverse rect be in the grid dimensions" ); + TNL_ASSERT_LE( from, to, "Traverse rect must be defined from leading bottom anchor to trailing top anchor" ); + + auto exec = [ & ]( const Index orientation, const Coordinate& basis ) + { + Templates::ParallelFor< Dimension, Device, Index >::exec( from, to + basis, func, basis, orientation, args... ); + }; + + Templates::ForEachOrientation< Index, EntityDimension, Dimension >::exec( exec ); +} + +__NDIMGRID_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__NDIM_PREFIX__::traverseInterior( Func func, FuncArgs... args ) const +{ + this->traverseInterior< EntityDimension >( Coordinate( 0 ), this->getDimensions(), func, args... ); +} + +__NDIMGRID_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__NDIM_PREFIX__::traverseInterior( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const +{ + TNL_ASSERT_GE( from, Coordinate( 0 ), "Traverse rect must be in the grid dimensions" ); + TNL_ASSERT_LE( to, this->getDimensions(), "Traverse rect be in the grid dimensions" ); + TNL_ASSERT_LE( from, to, "Traverse rect must be defined from leading bottom anchor to trailing top anchor" ); + + auto exec = [ & ]( const Index orientation, const Coordinate& basis ) + { + switch( EntityDimension ) { + case 0: + { + Templates::ParallelFor< Dimension, Device, Index >::exec( + from + Coordinate( 1 ), to, func, basis, orientation, args... ); + break; + } + case Dimension: + { + Templates::ParallelFor< Dimension, Device, Index >::exec( + from + Coordinate( 1 ), to - Coordinate( 1 ), func, basis, orientation, args... ); + break; + } + default: + { + Templates::ParallelFor< Dimension, Device, Index >::exec( from + basis, to, func, basis, orientation, args... ); + break; + } + } + }; + + Templates::ForEachOrientation< Index, EntityDimension, Dimension >::exec( exec ); +} + +__NDIMGRID_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__NDIM_PREFIX__::traverseBoundary( Func func, FuncArgs... args ) const +{ + this->traverseBoundary< EntityDimension >( Coordinate( 0 ), this->getDimensions(), func, args... ); +} + +__NDIMGRID_TEMPLATE__ +template< int EntityDimension, typename Func, typename... FuncArgs > +inline void +__NDIM_PREFIX__::traverseBoundary( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const +{ + // Boundaries of the grid are formed by the entities of Dimension - 1. + // We need to traverse each orientation independently. + constexpr int orientationsCount = getEntityOrientationsCount( Dimension - 1 ); + constexpr bool isDirectedEntity = EntityDimension != 0 && EntityDimension != Dimension; + constexpr bool isAnyBoundaryIntersects = EntityDimension != Dimension - 1; + + Container< orientationsCount, Index > isBoundaryTraversed( 0 ); + + auto forBoundary = [ & ]( const auto orthogonalOrientation, const auto orientation, const Coordinate& basis ) + { + Coordinate start = from; + Coordinate end = to + basis; + + if( isAnyBoundaryIntersects ) { +#pragma unroll + for( Index i = 0; i < Dimension; i++ ) { + start[ i ] = ( ! isDirectedEntity || basis[ i ] ) && isBoundaryTraversed[ i ] ? 1 : 0; + end[ i ] = end[ i ] - ( ( ! isDirectedEntity || basis[ i ] ) && isBoundaryTraversed[ i ] ? 1 : 0 ); + } + } + + start[ orthogonalOrientation ] = end[ orthogonalOrientation ] - 1; + + Templates::ParallelFor< Dimension, Device, Index >::exec( start, end, func, basis, orientation, args... ); + + // Skip entities defined only once + if( ! start[ orthogonalOrientation ] && end[ orthogonalOrientation ] ) + return; + + start[ orthogonalOrientation ] = 0; + end[ orthogonalOrientation ] = 1; + + Templates::ParallelFor< Dimension, Device, Index >::exec( start, end, func, basis, orientation, args... ); + }; + + if( ! isAnyBoundaryIntersects ) { + auto exec = [ & ]( const auto orientation, const Coordinate& basis ) + { + constexpr int orthogonalOrientation = EntityDimension - orientation; + + forBoundary( orthogonalOrientation, orientation, basis ); + }; + + Templates::ForEachOrientation< Index, EntityDimension, Dimension >::exec( exec ); + return; + } + + auto exec = [ & ]( const auto orthogonalOrientation ) + { + auto exec = [ & ]( const auto orientation, const Coordinate& basis ) + { + forBoundary( orthogonalOrientation, orientation, basis ); + }; + + if( EntityDimension == 0 || EntityDimension == Dimension ) { + Templates::ForEachOrientation< Index, EntityDimension, Dimension >::exec( exec ); + } + else { + Templates::ForEachOrientation< Index, EntityDimension, Dimension, orthogonalOrientation >::exec( exec ); + } + + isBoundaryTraversed[ orthogonalOrientation ] = 1; + }; + + Templates::DescendingFor< orientationsCount - 1 >::exec( exec ); +} + +__NDIMGRID_TEMPLATE__ +void +__NDIM_PREFIX__::writeProlog( TNL::Logger& logger ) const noexcept +{ + logger.writeParameter( "Dimensions:", this->dimensions ); + + logger.writeParameter( "Origin:", this->origin ); + logger.writeParameter( "Proportions:", this->proportions ); + logger.writeParameter( "Space steps:", this->spaceSteps ); + + for( Index i = 0; i <= Dimension; i++ ) { + TNL::String tmp = TNL::String( "Entities count along dimension " ) + TNL::convertToString( i ) + ":"; + + logger.writeParameter( tmp, this->cumulativeEntitiesCountAlongBases[ i ] ); + } +} + +__NDIMGRID_TEMPLATE__ +void +__NDIM_PREFIX__::fillEntitiesCount() +{ + for( Index i = 0; i < Dimension + 1; i++ ) + cumulativeEntitiesCountAlongBases[ i ] = 0; + + // In case, if some dimension is zero. Clear all counts + for( Index i = 0; i < Dimension; i++ ) { + if( dimensions[ i ] == 0 ) { + for( Index k = 0; k < (Index) entitiesCountAlongBases.getSize(); k++ ) + entitiesCountAlongBases[ k ] = 0; + + return; + } + } + + for( Index i = 0, j = 0; i <= Dimension; i++ ) { + for( Index n = 0; n < this->getEntityOrientationsCount( i ); n++, j++ ) { + int result = 1; + auto basis = bases[ j ]; + + for( Index k = 0; k < (Index) basis.getSize(); k++ ) + result *= dimensions[ k ] + basis[ k ]; + + entitiesCountAlongBases[ j ] = result; + cumulativeEntitiesCountAlongBases[ i ] += result; + } + } +} + +__NDIMGRID_TEMPLATE__ +void +__NDIM_PREFIX__::fillProportions() +{ + Index i = 0; + + while( i != Dimension ) { + this->proportions[ i ] = this->spaceSteps[ i ] * this->dimensions[ i ]; + i++; + } +} + +__NDIMGRID_TEMPLATE__ +void +__NDIM_PREFIX__::fillSpaceSteps() +{ + bool hasAnyInvalidDimension = false; + + for( Index i = 0; i < Dimension; i++ ) { + if( this->dimensions[ i ] <= 0 ) { + hasAnyInvalidDimension = true; + break; + } + } + + if( ! hasAnyInvalidDimension ) { + for( Index i = 0; i < Dimension; i++ ) + this->spaceSteps[ i ] = this->proportions[ i ] / this->dimensions[ i ]; + + fillSpaceStepsPowers(); + } +} + +__NDIMGRID_TEMPLATE__ +void +__NDIM_PREFIX__::fillSpaceStepsPowers() +{ + Container< spaceStepsPowersSize * Dimension, Real > powers; + + for( Index i = 0; i < Dimension; i++ ) { + Index power = -( this->spaceStepsPowersSize >> 1 ); + + for( Index j = 0; j < spaceStepsPowersSize; j++ ) { + powers[ i * spaceStepsPowersSize + j ] = pow( this->spaceSteps[ i ], power ); + power++; + } + } + + for( Index i = 0; i < this->spaceStepsProducts.getSize(); i++ ) { + Real product = 1; + Index index = i; + + for( Index j = 0; j < Dimension; j++ ) { + Index residual = index % this->spaceStepsPowersSize; + + index /= this->spaceStepsPowersSize; + + product *= powers[ j * spaceStepsPowersSize + residual ]; + } + + spaceStepsProducts[ i ] = product; + } +} + +__NDIMGRID_TEMPLATE__ +void +__NDIM_PREFIX__::fillBases() +{ + OrientationBasesContainer container; + + int index = container.getSize() - 1; + + auto forEachEntityDimension = [ & ]( const auto entityDimension ) + { + constexpr Index dimension = entityDimension(); + constexpr Index combinationsCount = getEntityOrientationsCount( dimension ); + + auto forEachOrientation = [ & ]( const auto orientation, const auto entityDimension ) + { + container[ index-- ] = BasisGetter< Index, entityDimension, Dimension >::template getBasis< orientation >(); + }; + + Templates::DescendingFor< combinationsCount - 1 >::exec( forEachOrientation, entityDimension ); + }; + + Templates::DescendingFor< Dimension >::exec( forEachEntityDimension ); + + this->bases = container; +} + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Implementations/NeighbourGridEntityGetter.hpp b/src/TNL/Meshes/GridDetails/Implementations/NeighbourGridEntityGetter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1ce56f40e2469d6a7d2845ca97ae06aab70f8f93 --- /dev/null +++ b/src/TNL/Meshes/GridDetails/Implementations/NeighbourGridEntityGetter.hpp @@ -0,0 +1,108 @@ + +#pragma once + +#include +#include + +namespace TNL { +namespace Meshes { + +template< int GridDimension, int ParentEntityDimension, int NeighbourEntityDimension > +class NeighbourGridEntityGetter +{ +public: + template< class Grid > + static __cuda_callable__ + inline GridEntity< Grid, NeighbourEntityDimension > + getEntity( const GridEntity< Grid, ParentEntityDimension >& entity, const typename Grid::Coordinate& offset ) + { + using BasisGetterType = BasisGetter< typename Grid::IndexType, NeighbourEntityDimension, GridDimension >; + using Coordinate = typename Grid::Coordinate; + + constexpr int orientationsCount = Templates::combination( NeighbourEntityDimension, GridDimension ); + + const Coordinate coordinate = entity.getCoordinates() + offset; + const int orientation = TNL::min( orientationsCount - 1, entity.getOrientation() ); + const Coordinate basis = orientation == entity.getOrientation() && ParentEntityDimension == NeighbourEntityDimension + ? entity.getBasis() + : entity.getMesh().template getBasis< NeighbourEntityDimension >( orientation ); + + TNL_ASSERT_GE( coordinate, Coordinate( 0 ), "wrong coordinate" ); + TNL_ASSERT_LT( coordinate, entity.getMesh().getDimensions() + basis, "wrong coordinate" ); + + return { entity.getMesh(), coordinate, basis, orientation }; + } + + template< class Grid, int... Steps, std::enable_if_t< sizeof...( Steps ) == Grid::getMeshDimension(), bool > = true > + static __cuda_callable__ + inline GridEntity< Grid, NeighbourEntityDimension > + getEntity( const GridEntity< Grid, ParentEntityDimension >& entity ) + { + using BasisGetterType = BasisGetter< typename Grid::IndexType, NeighbourEntityDimension, GridDimension >; + using Coordinate = typename Grid::Coordinate; + + constexpr int orientationsCount = Templates::combination( NeighbourEntityDimension, GridDimension ); + + const Coordinate coordinate = entity.getCoordinates() + Coordinate( Steps... ); + const int orientation = TNL::min( orientationsCount - 1, entity.getOrientation() ); + const Coordinate basis = orientation == entity.getOrientation() && ParentEntityDimension == NeighbourEntityDimension + ? entity.getBasis() + : entity.getMesh().template getBasis< NeighbourEntityDimension >( orientation ); + + TNL_ASSERT_GE( coordinate, Coordinate( 0 ), "wrong coordinate" ); + TNL_ASSERT_LT( coordinate, entity.getMesh().getDimensions() + basis, "wrong coordinate" ); + + return { entity.getMesh(), coordinate, basis, orientation }; + } + + template< class Grid, + int Orientation, + std::enable_if_t< Templates::isInLeftClosedRightOpenInterval( + 0, + Orientation, + Templates::combination( NeighbourEntityDimension, GridDimension ) ), + bool > = true > + static __cuda_callable__ + inline GridEntity< Grid, NeighbourEntityDimension > + getEntity( const GridEntity< Grid, ParentEntityDimension >& entity, const typename Grid::Coordinate& offset ) + { + using BasisGetterType = BasisGetter< typename Grid::IndexType, NeighbourEntityDimension, GridDimension >; + using Coordinate = typename Grid::Coordinate; + + const Coordinate coordinate = entity.getCoordinates() + offset; + const Coordinate basis = BasisGetterType::template getBasis< Orientation >(); + + TNL_ASSERT_GE( coordinate, Coordinate( 0 ), "wrong coordinate" ); + TNL_ASSERT_LT( coordinate, entity.getMesh().getDimensions() + basis, "wrong coordinate" ); + + return { entity.getMesh(), coordinate, basis, Orientation }; + } + + template< class Grid, + int Orientation, + int... Steps, + std::enable_if_t< ( sizeof...( Steps ) == Grid::getMeshDimension() ), bool > = true, + std::enable_if_t< Templates::isInLeftClosedRightOpenInterval( + 0, + Orientation, + Templates::combination( NeighbourEntityDimension, GridDimension ) ), + bool > = true > + static __cuda_callable__ + inline GridEntity< Grid, NeighbourEntityDimension > + getEntity( const GridEntity< Grid, ParentEntityDimension >& entity ) + { + using BasisGetterType = BasisGetter< typename Grid::IndexType, NeighbourEntityDimension, GridDimension >; + using Coordinate = typename Grid::Coordinate; + + const Coordinate coordinate = entity.getCoordinates() + Coordinate( Steps... ); + const Coordinate basis{ BasisGetterType::template getBasis< Orientation >() }; + + TNL_ASSERT_GE( coordinate, Coordinate( 0 ), "wrong coordinate" ); + TNL_ASSERT_LT( coordinate, entity.getMesh().getDimensions() + basis, "wrong coordinate" ); + + return { entity.getMesh(), coordinate, basis, Orientation }; + } +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/NDimGrid.h b/src/TNL/Meshes/GridDetails/NDimGrid.h new file mode 100644 index 0000000000000000000000000000000000000000..7fdc99faa313b9b2397c0f7390a0a1bc24aebba7 --- /dev/null +++ b/src/TNL/Meshes/GridDetails/NDimGrid.h @@ -0,0 +1,318 @@ + +#pragma once + +#include +#include +#include +#include + +#include + +namespace TNL { +namespace Meshes { + +template< int Dimension, typename Real, typename Device, typename Index > +class NDimGrid +{ +public: + template< int ContainerDimension, typename ContainerValue, std::enable_if_t< ( ContainerDimension > 0 ), bool > = true > + using Container = TNL::Containers::StaticVector< ContainerDimension, ContainerValue >; + + using IndexType = Index; + using DeviceType = Device; + using RealType = Real; + + using Coordinate = Container< Dimension, Index >; + using Point = Container< Dimension, Real >; + + /////////////////////////////// + // Compatability with meshes + using CoordinatesType = Container< Dimension, Index >; + using PointType = Container< Dimension, Real >; + using GlobalIndexType = Index; + /////////////////////////////// + + using EntitiesCounts = Container< Dimension + 1, Index >; + + using OrientationBasesContainer = Container< 1 << Dimension, Coordinate >; + + /** + * @brief Returns the dimension of grid + */ + static constexpr int + getMeshDimension() + { + return Dimension; + }; + /** + * @brief Returns the coefficient powers size. + */ + static constexpr int spaceStepsPowersSize = 5; + + using SpaceProductsContainer = + Container< std::integral_constant< Index, Templates::pow( spaceStepsPowersSize, Dimension ) >::value, Real >; + + NDimGrid() + { + Coordinate zero = 0; + setDimensions( zero ); + + Point zeroPoint = 0; + proportions = zeroPoint; + spaceSteps = zeroPoint; + origin = zeroPoint; + + fillBases(); + } + + /** + * @brief Returns the number of orientations for entity dimension. + * For example in 2-D Grid the edge can be vertical or horizontal. + */ + static constexpr Index + getEntityOrientationsCount( const Index entityDimension ); + + template< typename... Dimensions, + std::enable_if_t< Templates::conjunction_v< std::is_convertible< Index, Dimensions >... >, bool > = true, + std::enable_if_t< sizeof...( Dimensions ) == Dimension, bool > = true > + void + setDimensions( Dimensions... dimensions ); + + void + setDimensions( const Container< Dimension, Index >& dimensions ); + + /** + * @brief - Returns dimensions as a count of edges along each axis + * @param[in] index - Index of dimension + */ + __cuda_callable__ + inline Index + getDimension( const Index index ) const; + /** + * @brief - Returns dimensions as a count of edges along each axis + * @param[in] indices - A list of indices + */ + template< typename... DimensionIndex, + std::enable_if_t< Templates::conjunction_v< std::is_convertible< Index, DimensionIndex >... >, bool > = true, + std::enable_if_t< ( sizeof...( DimensionIndex ) > 0 ), bool > = true > + __cuda_callable__ + inline Container< sizeof...( DimensionIndex ), Index > + getDimensions( DimensionIndex... indices ) const noexcept; + /** + * @brief - Returns dimensions as a count of edges along each axis + */ + __cuda_callable__ + inline const Coordinate& + getDimensions() const noexcept; + /** + * @brief - Returns count of entities of specific dimension + */ + __cuda_callable__ + inline Index + getEntitiesCount( const Index index ) const; + /** + * @brief - Returns count of entities of specific dimension + */ + template< int EntityDimension, + std::enable_if_t< Templates::isInClosedInterval( 0, EntityDimension, Dimension ), bool > = true > + __cuda_callable__ + inline Index + getEntitiesCount() const noexcept; + /** + * @brief - Returns count of entities of specific dimension + */ + template< typename... DimensionIndex, + std::enable_if_t< Templates::conjunction_v< std::is_convertible< Index, DimensionIndex >... >, bool > = true, + std::enable_if_t< ( sizeof...( DimensionIndex ) > 0 ), bool > = true > + __cuda_callable__ + inline Container< sizeof...( DimensionIndex ), Index > + getEntitiesCounts( DimensionIndex... indices ) const; + /** + * @brief - Returns count of entities of specific dimension + */ + __cuda_callable__ + inline const EntitiesCounts& + getEntitiesCounts() const noexcept; + /** + * @brief - Returns count of entities of specific dimension and orientation + * + * @param[in] dimension + * @param[in] orientation - orientation of the entity + */ + __cuda_callable__ + inline Index + getOrientedEntitiesCount( const Index dimension, const Index orientation ) const; + /** + * @brief - Returns count of entities of specific dimension and orientation + * + * @param[in] dimension + * @param[in] orientation - orientation of the entity + */ + template< int EntityDimension, + int EntityOrientation, + std::enable_if_t< Templates::isInClosedInterval( 0, EntityDimension, Dimension ), bool > = true, + std::enable_if_t< Templates::isInClosedInterval( 0, EntityOrientation, Dimension ), bool > = true > + __cuda_callable__ + inline Index + getOrientedEntitiesCount() const noexcept; + /** + * @brief - Returns basis of the entity with the specific orientation + * + * @param[in] dimension + * @param[in] orientation - orientation of the entity + */ + template< int EntityDimension > + __cuda_callable__ + inline Coordinate + getBasis( Index orientation ) const noexcept; + /** + * \brief Sets the origin and proportions of this grid. + * + * \param origin Point where this grid starts. + * \param proportions Total length of this grid. + */ + void + setDomain( const Point& origin, const Point& proportions ); + /** + * @brief Set the Origin of the grid + */ + void + setOrigin( const Point& origin ) noexcept; + /** + * @brief Set the Origin of the grid + */ + template< typename... Coordinates, + std::enable_if_t< Templates::conjunction_v< std::is_convertible< Real, Coordinates >... >, bool > = true, + std::enable_if_t< sizeof...( Coordinates ) == Dimension, bool > = true > + void + setOrigin( Coordinates... coordinates ) noexcept; + /** + * @brief - Returns the origin of the grid + */ + __cuda_callable__ + inline const Point& + getOrigin() const noexcept; + /** + * @brief Set the Space Steps along each dimension of the grid + */ + void + setSpaceSteps( const Point& steps ) noexcept; + /** + * @brief - Specifies space steps of the grid + */ + template< typename... Steps, + std::enable_if_t< Templates::conjunction_v< std::is_convertible< Real, Steps >... >, bool > = true, + std::enable_if_t< sizeof...( Steps ) == Dimension, bool > = true > + void + setSpaceSteps( Steps... spaceSteps ) noexcept; + /** + * @brief - Returns the space staps of the grid + */ + __cuda_callable__ + inline const Point& + getSpaceSteps() const noexcept; + /** + * @brief Returns product of space steps + */ + template< typename... Powers, + std::enable_if_t< Templates::conjunction_v< std::is_convertible< Index, Powers >... >, bool > = true, + std::enable_if_t< sizeof...( Powers ) == Dimension, bool > = true > + __cuda_callable__ + inline Real + getSpaceStepsProducts( Powers... powers ) const; + /** + * @brief Returns product of space steps + */ + __cuda_callable__ + inline Real + getSpaceStepsProducts( const Coordinate& powers ) const; + /** + * @brief Returns product of space step + */ + template< Index... Powers, std::enable_if_t< sizeof...( Powers ) == Dimension, bool > = true > + __cuda_callable__ + inline Real + getSpaceStepsProducts() const noexcept; + /** + * @brief Get the Smalles Space Steps object + */ + __cuda_callable__ + inline Real + getSmallestSpaceStep() const noexcept; + /** + * @brief Get the proportions of the Grid + */ + __cuda_callable__ + inline const Point& + getProportions() const noexcept; + /** + * @brief Writes info about the grid + */ + void + writeProlog( TNL::Logger& logger ) const noexcept; + +protected: + Coordinate dimensions; + /** + * @brief - A list of elements count along specific directions. + * First, (n choose 0) elements will contain the count of 0 + * dimension elements Second, (n choose 1) elements will contain the count + * of 1-dimension elements.... + * + * For example, let's have a 3-d grid, then the map indexing will + * be the next: 0 - 0 - count of vertices 1, 2, 3 - count of edges in x, y, + * z plane 4, 5, 6 - count of faces in xy, yz, zy plane 7 - count of cells + * in z y x plane + * + * @warning - The ordering of is lexigraphical. + */ + Container< 1 << Dimension, Index > entitiesCountAlongBases; + /** + * @brief - A cumulative map over dimensions. + */ + Container< Dimension + 1, Index > cumulativeEntitiesCountAlongBases; + + Point origin, proportions, spaceSteps; + + OrientationBasesContainer bases; + SpaceProductsContainer spaceStepsProducts; + + void + fillEntitiesCount(); + void + fillSpaceSteps(); + void + fillSpaceStepsPowers(); + void + fillProportions(); + void + fillBases(); + + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + traverseAll( Func func, FuncArgs... args ) const; + + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + traverseAll( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const; + + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + traverseInterior( Func func, FuncArgs... args ) const; + + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + traverseInterior( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const; + + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + traverseBoundary( Func func, FuncArgs... args ) const; + + template< int EntityDimension, typename Func, typename... FuncArgs > + inline void + traverseBoundary( const Coordinate& from, const Coordinate& to, Func func, FuncArgs... args ) const; +}; +} // namespace Meshes +} // namespace TNL + +#include diff --git a/src/TNL/Meshes/GridDetails/NeighborGridEntitiesStorage.h b/src/TNL/Meshes/GridDetails/NeighborGridEntitiesStorage.h deleted file mode 100644 index ffd68c334580793e3972f70d3593dda28364c337..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/NeighborGridEntitiesStorage.h +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include -#include -#include - -namespace TNL { -namespace Meshes { - -template< typename GridEntity, - int NeighborEntityDimension, - typename GridEntityConfig, - bool storage = GridEntityConfig::template neighborEntityStorage< GridEntity >( NeighborEntityDimension ) > -class NeighborGridEntityLayer : public NeighborGridEntityLayer< GridEntity, NeighborEntityDimension - 1, GridEntityConfig > -{ -public: - using BaseType = NeighborGridEntityLayer< GridEntity, NeighborEntityDimension - 1, GridEntityConfig >; - using NeighborEntityGetterType = NeighborGridEntityGetter< GridEntity, NeighborEntityDimension >; - - using BaseType::getNeighborEntities; - - __cuda_callable__ - NeighborGridEntityLayer( const GridEntity& entity ) : BaseType( entity ), neighborEntities( entity ) {} - - __cuda_callable__ - const NeighborEntityGetterType& - getNeighborEntities( const DimensionTag< NeighborEntityDimension >& tag ) const - { - return this->neighborEntities; - } - - __cuda_callable__ - void - refresh( const typename GridEntity::GridType& grid, const typename GridEntity::GridType::IndexType& entityIndex ) - { - BaseType::refresh( grid, entityIndex ); - neighborEntities.refresh( grid, entityIndex ); - } - -protected: - NeighborEntityGetterType neighborEntities; -}; - -template< typename GridEntity, typename GridEntityConfig, bool storage > -class NeighborGridEntityLayer< GridEntity, 0, GridEntityConfig, storage > -{ -public: - using NeighborEntityGetterType = NeighborGridEntityGetter< GridEntity, 0 >; - - __cuda_callable__ - NeighborGridEntityLayer( const GridEntity& entity ) : neighborEntities( entity ) {} - - __cuda_callable__ - const NeighborEntityGetterType& - getNeighborEntities( const DimensionTag< 0 >& tag ) const - { - return this->neighborEntities; - } - - __cuda_callable__ - void - refresh( const typename GridEntity::GridType& grid, const typename GridEntity::GridType::IndexType& entityIndex ) - { - neighborEntities.refresh( grid, entityIndex ); - } - -protected: - NeighborEntityGetterType neighborEntities; -}; - -template< typename GridEntity, typename GridEntityConfig > -class NeighborGridEntitiesStorage -: public NeighborGridEntityLayer< GridEntity, GridEntity::getMeshDimension(), GridEntityConfig > -{ - using BaseType = NeighborGridEntityLayer< GridEntity, GridEntity::getMeshDimension(), GridEntityConfig >; - -public: - using BaseType::getNeighborEntities; - using BaseType::refresh; - - __cuda_callable__ - NeighborGridEntitiesStorage( const GridEntity& entity ) : BaseType( entity ) {} - - template< int EntityDimension > - __cuda_callable__ - const NeighborGridEntityGetter< GridEntity, EntityDimension >& - getNeighborEntities() const - { - return BaseType::getNeighborEntities( DimensionTag< EntityDimension >() ); - } -}; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/NeighborGridEntityGetter.h b/src/TNL/Meshes/GridDetails/NeighborGridEntityGetter.h deleted file mode 100644 index b597751fda5abafcc47a6a293e989b7a2b72f9f7..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/NeighborGridEntityGetter.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include -#include - -namespace TNL { -namespace Meshes { - -template< typename GridEntity, - int NeighborEntityDimension, - typename EntityStencilTag = GridEntityStencilStorageTag< - GridEntity::ConfigType::template neighborEntityStorage< GridEntity >( NeighborEntityDimension ) > > -class NeighborGridEntityGetter -{ -public: - // TODO: not all specializations are implemented yet - - __cuda_callable__ - NeighborGridEntityGetter( const GridEntity& entity ) - { - // TNL_ASSERT( false, ); - } - - __cuda_callable__ - void - refresh( const typename GridEntity::GridType& grid, const typename GridEntity::IndexType& entityIndex ) - { - // TNL_ASSERT( false, ); - } -}; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/NeighborGridEntityGetter1D_impl.h b/src/TNL/Meshes/GridDetails/NeighborGridEntityGetter1D_impl.h deleted file mode 100644 index c9db445e6d938d2384f5cf7fc43e827eb5ba9cc3..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/NeighborGridEntityGetter1D_impl.h +++ /dev/null @@ -1,417 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include -#include -#include -#include - -namespace TNL { -namespace Meshes { - -/**** - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stored Stencil | - * +-----------------+---------------------------+-------------------+ - * | 1 | 1 | ---- | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 1, Real, Device, Index >, 1, Config >, - 1, - GridEntityStencilStorageTag< GridEntityNoStencil > > -{ -public: - static constexpr int EntityDimension = 1; - static constexpr int NeighborEntityDimension = 1; - using GridType = Meshes::Grid< 1, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - template< int step > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates() + CoordinatesType( step ) >= CoordinatesType( 0 ) - && entity.getCoordinates() + CoordinatesType( step ) < entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() = " << entity.getCoordinates() << " entity.getMesh().getDimensions() = " - << entity.getMesh().getDimensions() << " EntityDimension = " << EntityDimension ); - return NeighborGridEntity( CoordinatesType( entity.getCoordinates().x() + step ) ); - } - - template< int step > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates() + CoordinatesType( step ) >= CoordinatesType( 0 ) - && entity.getCoordinates() + CoordinatesType( step ) < entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() = " << entity.getCoordinates() << " entity.getMesh().getDimensions() = " - << entity.getMesh().getDimensions() << " EntityDimension = " << EntityDimension ); - return this->entity.getIndex() + step; - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ){}; - -protected: - const GridEntityType& entity; -}; - -/**** - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stored Stencil | - * +-----------------+---------------------------+-------------------+ - * | 1 | 1 | Cross/Full | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config, typename StencilStorage > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 1, Real, Device, Index >, 1, Config >, 1, StencilStorage > -{ -public: - static constexpr int EntityDimension = 1; - static constexpr int NeighborEntityDimension = 1; - using GridType = Meshes::Grid< 1, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - - static constexpr int stencilSize = Config::getStencilSize(); - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - template< int step > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates() + CoordinatesType( step ) >= CoordinatesType( 0 ) - && entity.getCoordinates() + CoordinatesType( step ) < entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() = " << entity.getCoordinates() << " entity.getMesh().getDimensions() = " - << entity.getMesh().getDimensions() << " EntityDimension = " << EntityDimension ); - return NeighborGridEntityType( this->entity.getMesh(), CoordinatesType( entity.getCoordinates().x() + step ) ); - } - - template< int step > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates() + CoordinatesType( step ) >= CoordinatesType( 0 ) - && entity.getCoordinates() + CoordinatesType( step ) < entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() = " << entity.getCoordinates() << " entity.getMesh().getDimensions() = " - << entity.getMesh().getDimensions() << " EntityDimension = " << EntityDimension ); -#ifndef HAVE_CUDA // TODO: fix it -- does not work with nvcc - if( step < -stencilSize || step > stencilSize ) - return this->entity.getIndex() + step; - return stencil[ stencilSize + step ]; -#else - return this->entity.getIndex() + step; -#endif - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ) - { -#ifndef HAVE_CUDA // TODO: fix it -- does not work with nvcc - Algorithms::staticFor< IndexType, -stencilSize, stencilSize + 1 >( - [ & ]( auto index ) - { - stencil[ index + stencilSize ] = entityIndex + index; - } ); -#endif - }; - -protected: - const GridEntityType& entity; - - IndexType stencil[ 2 * stencilSize + 1 ]; -}; - -/**** - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stored Stencil | - * +-----------------+---------------------------+-------------------+ - * | 1 | 0 | None | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 1, Real, Device, Index >, 1, Config >, - 0, - GridEntityStencilStorageTag< GridEntityNoStencil > > -{ -public: - static constexpr int EntityDimension = 1; - static constexpr int NeighborEntityDimension = 0; - using GridType = Meshes::Grid< 1, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - template< int step > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates().x() + step + ( step < 0 ) >= CoordinatesType( 0 ) - && entity.getCoordinates().x() + step + ( step < 0 ) <= entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() = " << entity.getCoordinates() << " entity.getMesh().getDimensions() = " - << entity.getMesh().getDimensions() << " EntityDimension = " << EntityDimension ); - return NeighborGridEntity( CoordinatesType( entity.getCoordinates().x() + step + ( step < 0 ) ) ); - } - - template< int step > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates().x() + step + ( step < 0 ) >= CoordinatesType( 0 ).x() - && entity.getCoordinates().x() + step + ( step < 0 ) <= entity.getMesh().getDimensions().x(), - std::cerr << "entity.getCoordinates() = " << entity.getCoordinates() << " entity.getMesh().getDimensions() = " - << entity.getMesh().getDimensions() << " EntityDimension = " << EntityDimension ); - return this->entity.getIndex() + step + ( step < 0 ); - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ){}; - -protected: - const GridEntityType& entity; - - // NeighborGridEntityGetter(){}; -}; - -/**** - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stored Stencil | - * +-----------------+---------------------------+-------------------+ - * | 0 | 1 | None | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config, typename StencilStorage > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 1, Real, Device, Index >, 0, Config >, - 1, - StencilStorage > // GridEntityStencilStorageTag< GridEntityNoStencil > > -{ -public: - static constexpr int EntityDimension = 0; - static constexpr int NeighborEntityDimension = 1; - using GridType = Meshes::Grid< 1, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - void - test() const - { - std::cerr << "***" << std::endl; - }; - - template< int step > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0 ), "wrong coordinates" ); - TNL_ASSERT_LE( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates().x() + step - ( step > 0 ) >= CoordinatesType( 0 ) - && entity.getCoordinates().x() + step - ( step > 0 ) < entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() = " << entity.getCoordinates() << " entity.getMesh().getDimensions() = " - << entity.getMesh().getDimensions() << " EntityDimension = " << EntityDimension ); - return NeighborGridEntity( CoordinatesType( entity.getCoordinates().x() + step - ( step > 0 ) ) ); - } - - template< int step > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0 ), "wrong coordinates" ); - TNL_ASSERT_LE( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates().x() + step - ( step > 0 ) >= 0 - && entity.getCoordinates().x() + step - ( step > 0 ) < entity.getMesh().getDimensions().x(), - std::cerr << "entity.getCoordinates() = " << entity.getCoordinates() << " entity.getMesh().getDimensions() = " - << entity.getMesh().getDimensions() << " EntityDimension = " << EntityDimension ); - return this->entity.getIndex() + step - ( step > 0 ); - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ){}; - -protected: - const GridEntityType& entity; -}; - -/**** TODO: Implement this, now it is only a copy of specialization for none stencil storage - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stored Stencil | - * +-----------------+---------------------------+-------------------+ - * | 0 | 1 | Cross | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 1, Real, Device, Index >, 0, Config >, - 1, - GridEntityStencilStorageTag< GridEntityCrossStencil > > -{ -public: - static constexpr int EntityDimension = 0; - static constexpr int NeighborEntityDimension = 1; - using GridType = Meshes::Grid< 1, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - template< int step > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0 ), "wrong coordinates" ); - TNL_ASSERT_LE( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates().x() + step - ( step > 0 ) >= CoordinatesType( 0 ) - && entity.getCoordinates().x() + step - ( step > 0 ) < entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() = " << entity.getCoordinates() << " entity.getMesh().getDimensions() = " - << entity.getMesh().getDimensions() << " EntityDimension = " << EntityDimension ); - return NeighborGridEntity( CoordinatesType( entity.getCoordinates().x() + step - ( step > 0 ) ) ); - } - - template< int step > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0 ), "wrong coordinates" ); - TNL_ASSERT_LE( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates().x() + step - ( step > 0 ) >= CoordinatesType( 0 ) - && entity.getCoordinates().x() + step - ( step > 0 ) < entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() = " << entity.getCoordinates() << " entity.getMesh().getDimensions() = " - << entity.getMesh().getDimensions() << " EntityDimension = " << EntityDimension ); - return this->entity.getIndex() + step - ( step > 0 ); - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ){}; - -protected: - const GridEntityType& entity; -}; - -/**** - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stored Stencil | - * +-----------------+---------------------------+-------------------+ - * | 0 | 0 | None | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 1, Real, Device, Index >, 0, Config >, - 0, - GridEntityStencilStorageTag< GridEntityNoStencil > > -{ -public: - static constexpr int EntityDimension = 0; - static constexpr int NeighborEntityDimension = 0; - using GridType = Meshes::Grid< 1, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - template< int step > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0 ), "wrong coordinates" ); - TNL_ASSERT_LE( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates().x() + step >= CoordinatesType( 0 ) - && entity.getCoordinates().x() + step <= entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() = " << entity.getCoordinates() << " entity.getMesh().getDimensions() = " - << entity.getMesh().getDimensions() << " EntityDimension = " << EntityDimension ); - return NeighborGridEntity( CoordinatesType( entity.getCoordinates().x() + step ) ); - } - - template< int step > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0 ), "wrong coordinates" ); - TNL_ASSERT_LE( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates().x() + step >= CoordinatesType( 0 ) - && entity.getCoordinates().x() + step <= entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() = " << entity.getCoordinates() << " entity.getMesh().getDimensions() = " - << entity.getMesh().getDimensions() << " EntityDimension = " << EntityDimension ); - - return this->entity.getIndex() + step; - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ){}; - -protected: - const GridEntityType& entity; -}; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/NeighborGridEntityGetter2D_impl.h b/src/TNL/Meshes/GridDetails/NeighborGridEntityGetter2D_impl.h deleted file mode 100644 index dde6019d9f68bb08f8b709b33f56c5f4fa90339f..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/NeighborGridEntityGetter2D_impl.h +++ /dev/null @@ -1,455 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include -#include -#include -#include - -namespace TNL { -namespace Meshes { - -/**** - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stencil Storage | - * +-----------------+---------------------------+-------------------+ - * | 2 | 2 | No specialization | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config, typename StencilStorage > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 2, Real, Device, Index >, 2, Config >, 2, StencilStorage > -{ -public: - static constexpr int EntityDimension = 2; - static constexpr int NeighborEntityDimension = 2; - using GridType = Meshes::Grid< 2, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - template< int stepX, int stepY > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates() + CoordinatesType( stepX, stepY ) >= CoordinatesType( 0, 0 ) - && entity.getCoordinates() + CoordinatesType( stepX, stepY ) < entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX, stepY ) = " - << entity.getCoordinates() + CoordinatesType( stepX, stepY ) - << " entity.getMesh().getDimensions() = " << entity.getMesh().getDimensions() - << " EntityDimension = " << EntityDimension ); - return NeighborGridEntityType( - this->entity.getMesh(), CoordinatesType( entity.getCoordinates().x() + stepX, entity.getCoordinates().y() + stepY ) ); - } - - template< int stepX, int stepY > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates() + CoordinatesType( stepX, stepY ) >= CoordinatesType( 0, 0 ) - && entity.getCoordinates() + CoordinatesType( stepX, stepY ) < entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX, stepY ) = " - << entity.getCoordinates() + CoordinatesType( stepX, stepY ) - << " entity.getMesh().getDimensions() = " << entity.getMesh().getDimensions() - << " EntityDimension = " << EntityDimension ); - return this->entity.getIndex() + stepY * entity.getMesh().getDimensions().x() + stepX; - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ){}; - -protected: - const GridEntityType& entity; - - // NeighborGridEntityGetter(){}; -}; - -/**** - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stencil Storage | - * +-----------------+---------------------------+-------------------+ - * | 2 | 2 | Cross | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 2, Real, Device, Index >, 2, Config >, - 2, - GridEntityStencilStorageTag< GridEntityCrossStencil > > -{ -public: - static constexpr int EntityDimension = 2; - static constexpr int NeighborEntityDimension = 2; - using GridType = Meshes::Grid< 2, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - using StencilStorage = GridEntityStencilStorageTag< GridEntityCrossStencil >; - - static constexpr int stencilSize = Config::getStencilSize(); - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - template< int stepX, int stepY > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates() + CoordinatesType( stepX, stepY ) >= CoordinatesType( 0, 0 ) - && entity.getCoordinates() + CoordinatesType( stepX, stepY ) < entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX, stepY ) = " - << entity.getCoordinates() + CoordinatesType( stepX, stepY ) - << " entity.getMesh().getDimensions() = " << entity.getMesh().getDimensions() - << " EntityDimension = " << EntityDimension ); - return NeighborGridEntityType( - this->entity.getMesh(), CoordinatesType( entity.getCoordinates().x() + stepX, entity.getCoordinates().y() + stepY ) ); - } - - template< int stepX, int stepY > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates() + CoordinatesType( stepX, stepY ) >= CoordinatesType( 0, 0 ) - && entity.getCoordinates() + CoordinatesType( stepX, stepY ) < entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX, stepY ) = " - << entity.getCoordinates() + CoordinatesType( stepX, stepY ) - << " entity.getMesh().getDimensions() = " << entity.getMesh().getDimensions() - << " EntityDimension = " << EntityDimension ); -#ifndef HAVE_CUDA // TODO: fix this to work with CUDA - if( ( stepX != 0 && stepY != 0 ) - || ( stepX < -stencilSize || stepX > stencilSize || stepY < -stencilSize || stepY > stencilSize ) ) - return this->entity.getIndex() + stepY * entity.getMesh().getDimensions().x() + stepX; - if( stepY == 0 ) - return stencilX[ stepX + stencilSize ]; - return stencilY[ stepY + stencilSize ]; -#else - return this->entity.getIndex() + stepY * entity.getMesh().getDimensions().x() + stepX; -#endif - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ) - { -#ifndef HAVE_CUDA // TODO: fix this to work with CUDA - auto stencilXRefresher = [ & ]( auto index ) - { - stencilX[ index + stencilSize ] = entityIndex + index; - }; - auto stencilYRefresher = [ & ]( auto index ) - { - stencilY[ index + stencilSize ] = entityIndex + index * entity.getMesh().getDimensions().x(); - }; - Algorithms::staticFor< IndexType, -stencilSize, 0 >( stencilYRefresher ); - Algorithms::staticFor< IndexType, 1, stencilSize + 1 >( stencilYRefresher ); - Algorithms::staticFor< IndexType, -stencilSize, stencilSize + 1 >( stencilXRefresher ); -#endif - }; - -protected: - const GridEntityType& entity; - - IndexType stencilX[ 2 * stencilSize + 1 ]; - IndexType stencilY[ 2 * stencilSize + 1 ]; - - // NeighborGridEntityGetter(){}; -}; - -/**** - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stencil Storage | - * +-----------------+---------------------------+-------------------+ - * | 2 | 1 | None | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config, typename StencilStorage > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 2, Real, Device, Index >, 2, Config >, 1, StencilStorage > -{ -public: - static constexpr int EntityDimension = 2; - static constexpr int NeighborEntityDimension = 1; - using GridType = Meshes::Grid< 2, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - using EntityOrientationType = typename GridEntityType::EntityOrientationType; - using EntityBasisType = typename GridEntityType::EntityBasisType; - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - template< int stepX, int stepY > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - static_assert( ! stepX + ! stepY == 1, "Only one of the steps can be non-zero." ); - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ) ) - >= CoordinatesType( 0, 0 ) - && entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ) ) - < entity.getMesh().getDimensions() + CoordinatesType( ( stepX > 0 ), ( stepY > 0 ) ), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ) ) = " - << entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ) ) - << " entity.getMesh().getDimensions() = " << entity.getMesh().getDimensions() - << " EntityDimension = " << EntityDimension ); - return NeighborGridEntityType( - this->entity.getMesh(), - CoordinatesType( entity.getCoordinates().x() + stepX + ( stepX < 0 ), - entity.getCoordinates().y() + stepY + ( stepY < 0 ) ), - EntityOrientationType( stepX ? ( stepX > 0 ? 1 : -1 ) : 0, stepY ? ( stepY > 0 ? 1 : -1 ) : 0 ), - EntityBasisType( ! stepX, ! stepY ) ); - } - - template< int stepX, int stepY > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - return GridEntityGetterType::getEntityIndex( this->entity.getMesh(), this->template getEntity< stepX, stepY >() ); - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ){}; - -protected: - const GridEntityType& entity; -}; - -/**** - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stencil Storage | - * +-----------------+---------------------------+-------------------+ - * | 2 | 0 | None | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config, typename StencilStorage > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 2, Real, Device, Index >, 2, Config >, 0, StencilStorage > -{ -public: - static constexpr int EntityDimension = 2; - static constexpr int NeighborEntityDimension = 0; - using GridType = Meshes::Grid< 2, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - template< int stepX, int stepY > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - TNL_ASSERT( stepX != 0 && stepY != 0, std::cerr << " stepX = " << stepX << " stepY = " << stepY ); - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ) ) - >= CoordinatesType( 0, 0 ) - && entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ) ) - < entity.getMesh().getDimensions() + CoordinatesType( ( stepX > 0 ), ( stepY > 0 ) ), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ) ) = " - << entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ) ) - << " entity.getMesh().getDimensions() + CoordinatesType( sign( stepX ), sign( stepY ) ) = " - << entity.getMesh().getDimensions() + CoordinatesType( sign( stepX ), sign( stepY ) ) - << " EntityDimension = " << EntityDimension ); - return NeighborGridEntityType( this->entity.getMesh(), - CoordinatesType( entity.getCoordinates().x() + stepX + ( stepX < 0 ), - entity.getCoordinates().y() + stepY + ( stepY < 0 ) ) ); - } - - template< int stepX, int stepY > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - return GridEntityGetterType::getEntityIndex( this->entity.getMesh(), this->template getEntity< stepX, stepY >() ); - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ){}; - -protected: - const GridEntityType& entity; - - // NeighborGridEntityGetter(){}; -}; - -/**** - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stencil Storage | - * +-----------------+---------------------------+-------------------+ - * | 1 | 2 | None | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config, typename StencilStorage > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 2, Real, Device, Index >, 1, Config >, 2, StencilStorage > -{ -public: - static constexpr int EntityDimension = 1; - static constexpr int NeighborEntityDimension = 2; - using GridType = Meshes::Grid< 2, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - template< int stepX, int stepY > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - /*TNL_ASSERT( ( ( !! stepX ) == ( !! entity.getOrientation().x() ) ) && - ( ( !! stepY ) == ( !! entity.getOrientation().y() ) ), - std::cerr << "( stepX, stepY ) cannot be perpendicular to entity coordinates: stepX = " << stepX << " stepY = " - << stepY - << " entity.getOrientation() = " << entity.getOrientation() );*/ - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( - entity.getCoordinates(), entity.getMesh().getDimensions() + TNL::abs( entity.getOrientation() ), "wrong coordinates" ); - TNL_ASSERT( - entity.getCoordinates() - + CoordinatesType( stepX - ( stepX > 0 ) * ( entity.getOrientation().x() != 0.0 ), - stepY - ( stepY > 0 ) * ( entity.getOrientation().y() != 0.0 ) ) - >= CoordinatesType( 0, 0 ) - && entity.getCoordinates() - + CoordinatesType( stepX - ( stepX > 0 ) * ( entity.getOrientation().x() != 0.0 ), - stepY - ( stepY > 0 ) * ( entity.getOrientation().y() != 0.0 ) ) - < entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ) * ( entity.getOrientation().x() != " - "0.0 ), stepY + ( stepY < 0 ) * ( entity.getOrientation().y() != 0.0 ) ) = " - << entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ) ) - << " entity.getMesh().getDimensions() = " << entity.getMesh().getDimensions() - << " EntityDimension = " << EntityDimension ); - return NeighborGridEntityType( - this->entity.getMesh(), - CoordinatesType( entity.getCoordinates().x() + stepX - ( stepX > 0 ) * ( entity.getOrientation().x() != 0.0 ), - entity.getCoordinates().y() + stepY - ( stepY > 0 ) * ( entity.getOrientation().y() != 0.0 ) ) ); - } - - template< int stepX, int stepY > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - return GridEntityGetterType::getEntityIndex( this->entity.getMesh(), this->template getEntity< stepX, stepY >() ); - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ){}; - -protected: - const GridEntityType& entity; -}; - -/**** - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stencil Storage | - * +-----------------+---------------------------+-------------------+ - * | 0 | 0 | None | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config, typename StencilStorage > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 2, Real, Device, Index >, 0, Config >, 0, StencilStorage > -{ -public: - static constexpr int EntityDimension = 0; - static constexpr int NeighborEntityDimension = 0; - using GridType = Meshes::Grid< 2, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - template< int stepX, int stepY > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LE( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates() + CoordinatesType( stepX, stepY ) >= CoordinatesType( 0, 0 ) - && entity.getCoordinates() + CoordinatesType( stepX, stepY ) <= entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX, stepY ) = " - << entity.getCoordinates() + CoordinatesType( stepX, stepY ) - << " entity.getMesh().getDimensions() = " << entity.getMesh().getDimensions() - << " EntityDimension = " << EntityDimension ); - return NeighborGridEntityType( - this->entity.getMesh(), CoordinatesType( entity.getCoordinates().x() + stepX, entity.getCoordinates().y() + stepY ) ); - } - - template< int stepX, int stepY > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LE( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates() + CoordinatesType( stepX, stepY ) >= CoordinatesType( 0, 0 ) - && entity.getCoordinates() + CoordinatesType( stepX, stepY ) <= entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX, stepY ) = " - << entity.getCoordinates() + CoordinatesType( stepX, stepY ) - << " entity.getMesh().getDimensions() = " << entity.getMesh().getDimensions() - << " EntityDimension = " << EntityDimension ); - return this->entity.getIndex() + stepY * ( entity.getMesh().getDimensions().x() + 1 ) + stepX; - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ){}; - -protected: - const GridEntityType& entity; - - // NeighborGridEntityGetter(){}; -}; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/NeighborGridEntityGetter3D_impl.h b/src/TNL/Meshes/GridDetails/NeighborGridEntityGetter3D_impl.h deleted file mode 100644 index 405184a32096e1b96994a3310a02b47b5784a472..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/NeighborGridEntityGetter3D_impl.h +++ /dev/null @@ -1,655 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include -#include -#include -#include - -namespace TNL { -namespace Meshes { - -/**** - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stored Stencil | - * +-----------------+---------------------------+-------------------+ - * | 3 | 3 | None | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 3, Config >, - 3, - GridEntityStencilStorageTag< GridEntityNoStencil > > -{ -public: - static constexpr int EntityDimension = 3; - static constexpr int NeighborEntityDimension = 3; - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - template< int stepX, int stepY, int stepZ > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates() + CoordinatesType( stepX, stepY ) >= CoordinatesType( 0, 0, 0 ) - && entity.getCoordinates() + CoordinatesType( stepX, stepY ) < entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX, stepY ) = " - << entity.getCoordinates() + CoordinatesType( stepX, stepY ) - << " entity.getMesh().getDimensions() = " << entity.getMesh().getDimensions() - << " EntityDimension = " << EntityDimension ); - return NeighborGridEntityType( this->entity.getMesh(), - CoordinatesType( entity.getCoordinates().x() + stepX, - entity.getCoordinates().y() + stepY, - entity.getCoordinates().z() + stepZ ) ); - } - - template< int stepX, int stepY, int stepZ > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates() + CoordinatesType( stepX, stepY, stepZ ) >= CoordinatesType( 0, 0, 0 ) - && entity.getCoordinates() + CoordinatesType( stepX, stepY, stepZ ) < entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX, stepY, stepZ ) = " - << entity.getCoordinates() + CoordinatesType( stepX, stepY, stepZ ) - << " entity.getMesh().getDimensions() = " << entity.getMesh().getDimensions() - << " EntityDimension = " << EntityDimension ); - return this->entity.getIndex() - + ( stepZ * entity.getMesh().getDimensions().y() + stepY ) * entity.getMesh().getDimensions().x() + stepX; - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ){}; - -protected: - const GridEntityType& entity; - - // NeighborGridEntityGetter(){}; -}; - -/**** - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stored Stencil | - * +-----------------+---------------------------+-------------------+ - * | 3 | 3 | Cross | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 3, Config >, - 3, - GridEntityStencilStorageTag< GridEntityCrossStencil > > -{ -public: - static constexpr int EntityDimension = 3; - static constexpr int NeighborEntityDimension = 3; - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - using StencilStorage = GridEntityStencilStorageTag< GridEntityCrossStencil >; - - static constexpr int stencilSize = Config::getStencilSize(); - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - template< int stepX, int stepY, int stepZ > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates() + CoordinatesType( stepX, stepY, stepZ ) >= CoordinatesType( 0, 0, 0 ) - && entity.getCoordinates() + CoordinatesType( stepX, stepY, stepZ ) < entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX, stepY ) = " - << entity.getCoordinates() + CoordinatesType( stepX, stepY, stepZ ) - << " entity.getMesh().getDimensions() = " << entity.getMesh().getDimensions() - << " EntityDimension = " << EntityDimension ); - return NeighborGridEntityType( this->entity.getMesh(), - CoordinatesType( entity.getCoordinates().x() + stepX, - entity.getCoordinates().y() + stepY, - entity.getCoordinates().z() + stepZ ) ); - } - - template< int stepX, int stepY, int stepZ > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates() + CoordinatesType( stepX, stepY, stepZ ) >= CoordinatesType( 0, 0, 0 ) - && entity.getCoordinates() + CoordinatesType( stepX, stepY, stepZ ) < entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX, stepY, stepZ ) = " - << entity.getCoordinates() + CoordinatesType( stepX, stepY, stepZ ) - << " entity.getMesh().getDimensions() = " << entity.getMesh().getDimensions() - << " EntityDimension = " << EntityDimension ); -#ifndef HAVE_CUDA // TODO: fix this to work with CUDA - if( ( stepX != 0 && stepY != 0 ) || ( stepX != 0 && stepZ != 0 ) || ( stepY != 0 && stepZ != 0 ) - || ( stepX < -stencilSize || stepX > stencilSize || stepY < -stencilSize || stepY > stencilSize - || stepZ < -stencilSize || stepZ > stencilSize ) ) - return this->entity.getIndex() - + ( stepZ * entity.getMesh().getDimensions().y() + stepY ) * entity.getMesh().getDimensions().x() + stepX; - if( stepY == 0 && stepZ == 0 ) - return stencilX[ stepX + stencilSize ]; - if( stepZ == 0 ) - return stencilY[ stepY + stencilSize ]; - return stencilZ[ stepZ + stencilSize ]; -#else - return this->entity.getIndex() - + ( stepZ * entity.getMesh().getDimensions().y() + stepY ) * entity.getMesh().getDimensions().x() + stepX; -#endif - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ) - { -#ifndef HAVE_CUDA // TODO: fix this to work with CUDA - auto stencilXRefresher = [ & ]( auto index ) - { - stencilX[ index + stencilSize ] = entityIndex + index; - }; - auto stencilYRefresher = [ & ]( auto index ) - { - stencilY[ index + stencilSize ] = entityIndex + index * entity.getMesh().getDimensions().x(); - }; - auto stencilZRefresher = [ & ]( auto index ) - { - stencilZ[ index + stencilSize ] = entityIndex + index * entity.getMesh().cellZNeighborsStep; - }; - Algorithms::staticFor< IndexType, -stencilSize, 0 >( stencilZRefresher ); - Algorithms::staticFor< IndexType, 1, stencilSize + 1 >( stencilZRefresher ); - Algorithms::staticFor< IndexType, -stencilSize, 0 >( stencilYRefresher ); - Algorithms::staticFor< IndexType, 1, stencilSize + 1 >( stencilYRefresher ); - Algorithms::staticFor< IndexType, -stencilSize, stencilSize + 1 >( stencilXRefresher ); -#endif - }; - -protected: - const GridEntityType& entity; - - IndexType stencilX[ 2 * stencilSize + 1 ]; - IndexType stencilY[ 2 * stencilSize + 1 ]; - IndexType stencilZ[ 2 * stencilSize + 1 ]; - - // NeighborGridEntityGetter(){}; -}; - -/**** - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stored Stencil | - * +-----------------+---------------------------+-------------------+ - * | 3 | 2 | None | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 3, Config >, - 2, - GridEntityStencilStorageTag< GridEntityNoStencil > > -{ -public: - static constexpr int EntityDimension = 3; - static constexpr int NeighborEntityDimension = 2; - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - using EntityOrientationType = typename GridEntityType::EntityOrientationType; - using EntityBasisType = typename GridEntityType::EntityBasisType; - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - template< int stepX, int stepY, int stepZ > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - static_assert( ! stepX + ! stepY + ! stepZ == 2, "Only one of the steps can be non-zero." ); - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( - entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ), stepZ + ( stepZ < 0 ) ) - >= CoordinatesType( 0, 0, 0 ) - && entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ), stepZ + ( stepZ < 0 ) ) - < entity.getMesh().getDimensions() + CoordinatesType( ( stepX > 0 ), ( stepY > 0 ), ( stepZ > 0 ) ), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ), stepZ + ( " - "stepZ < 0 ) ) = " - << entity.getCoordinates() - + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ), stepZ + ( stepZ < 0 ) ) - << " entity.getMesh().getDimensions() = " << entity.getMesh().getDimensions() - << " EntityDimension = " << EntityDimension ); - return NeighborGridEntityType( this->entity.getMesh(), - CoordinatesType( entity.getCoordinates().x() + stepX + ( stepX < 0 ), - entity.getCoordinates().y() + stepY + ( stepY < 0 ), - entity.getCoordinates().z() + stepZ + ( stepZ < 0 ) ), - EntityOrientationType( stepX ? ( stepX > 0 ? 1 : -1 ) : 0, - stepY ? ( stepY > 0 ? 1 : -1 ) : 0, - stepZ ? ( stepZ > 0 ? 1 : -1 ) : 0 ), - EntityBasisType( ! stepX, ! stepY, ! stepZ ) ); - } - - template< int stepX, int stepY, int stepZ > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - return GridEntityGetterType::getEntityIndex( this->entity.getMesh(), getEntity< stepX, stepY, stepZ >() ); - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ){}; - -protected: - const GridEntityType& entity; - - // NeighborGridEntityGetter(){}; -}; - -/**** TODO: Finish it, knonw it is only a copy of specialization for none stored stencil - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stored Stencil | - * +-----------------+---------------------------+-------------------+ - * | 3 | 2 | Cross | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 3, Config >, - 2, - GridEntityStencilStorageTag< GridEntityCrossStencil > > -{ -public: - static constexpr int EntityDimension = 3; - static constexpr int NeighborEntityDimension = 2; - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - using EntityOrientationType = typename GridEntityType::EntityOrientationType; - using EntityBasisType = typename GridEntityType::EntityBasisType; - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - template< int stepX, int stepY, int stepZ > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - static_assert( ! stepX + ! stepY + ! stepZ == 2, "Only one of the steps can be non-zero." ); - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( - entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ), stepZ + ( stepZ < 0 ) ) - >= CoordinatesType( 0, 0, 0 ) - && entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ), stepZ + ( stepZ < 0 ) ) - < entity.getMesh().getDimensions() + CoordinatesType( ( stepX > 0 ), ( stepY > 0 ), ( stepZ > 0 ) ), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ), stepZ + ( " - "stepZ < 0 ) ) = " - << entity.getCoordinates() - + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ), stepZ + ( stepZ < 0 ) ) - << " entity.getMesh().getDimensions() = " << entity.getMesh().getDimensions() - << " EntityDimension = " << EntityDimension ); - return NeighborGridEntityType( this->entity.getMesh(), - CoordinatesType( entity.getCoordinates().x() + stepX + ( stepX < 0 ), - entity.getCoordinates().y() + stepY + ( stepY < 0 ), - entity.getCoordinates().z() + stepZ + ( stepZ < 0 ) ), - EntityOrientationType( stepX ? ( stepX > 0 ? 1 : -1 ) : 0, - stepY ? ( stepY > 0 ? 1 : -1 ) : 0, - stepZ ? ( stepZ > 0 ? 1 : -1 ) : 0 ), - EntityBasisType( ! stepX, ! stepY, ! stepZ ) ); - } - - template< int stepX, int stepY, int stepZ > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - return GridEntityGetterType::getEntityIndex( this->entity.getMesh(), getEntity< stepX, stepY, stepZ >() ); - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ){}; - -protected: - const GridEntityType& entity; - - // NeighborGridEntityGetter(){}; -}; - -/**** - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stored Stencil | - * +-----------------+---------------------------+-------------------+ - * | 3 | 1 | None | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 3, Config >, - 1, - GridEntityStencilStorageTag< GridEntityNoStencil > > -{ -public: - static constexpr int EntityDimension = 3; - static constexpr int NeighborEntityDimension = 1; - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - using EntityOrientationType = typename GridEntityType::EntityOrientationType; - using EntityBasisType = typename GridEntityType::EntityBasisType; - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - template< int stepX, int stepY, int stepZ > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - static_assert( ! stepX + ! stepY + ! stepZ == 1, "Exactly two of the steps must be non-zero." ); - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( - entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ), stepZ + ( stepZ < 0 ) ) - >= CoordinatesType( 0, 0, 0 ) - && entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ), stepZ + ( stepZ < 0 ) ) - < entity.getMesh().getDimensions() + CoordinatesType( ( stepX > 0 ), ( stepY > 0 ), ( stepZ > 0 ) ), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ), stepZ + ( " - "stepZ < 0 ) ) = " - << entity.getCoordinates() - + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ), stepZ + ( stepZ < 0 ) ) - << " entity.getMesh().getDimensions() = " << entity.getMesh().getDimensions() - << " EntityDimension = " << EntityDimension ); - return NeighborGridEntityType( this->entity.getMesh(), - CoordinatesType( entity.getCoordinates().x() + stepX + ( stepX < 0 ), - entity.getCoordinates().y() + stepY + ( stepY < 0 ), - entity.getCoordinates().z() + stepZ + ( stepZ < 0 ) ), - EntityOrientationType( ! ! stepX, ! ! stepY, ! ! stepZ ), - EntityBasisType( ! stepX, ! stepY, ! stepZ ) ); - } - - template< int stepX, int stepY, int stepZ > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - return GridEntityGetterType::getEntityIndex( this->entity.getMesh(), getEntity< stepX, stepY, stepZ >() ); - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ){}; - -protected: - const GridEntityType& entity; - - // NeighborGridEntityGetter(){}; -}; - -/**** - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stored Stencil | - * +-----------------+---------------------------+-------------------+ - * | 3 | 0 | None | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 3, Config >, - 0, - GridEntityStencilStorageTag< GridEntityNoStencil > > -{ -public: - static constexpr int EntityDimension = 3; - static constexpr int NeighborEntityDimension = 0; - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - template< int stepX, int stepY, int stepZ > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - TNL_ASSERT( stepX != 0 && stepY != 0 && stepZ != 0, - std::cerr << " stepX = " << stepX << " stepY = " << stepY << " stepZ = " << stepZ ); - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( - entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ), stepZ + ( stepZ < 0 ) ) - >= CoordinatesType( 0, 0, 0 ) - && entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ), stepZ + ( stepZ < 0 ) ) - < entity.getMesh().getDimensions() + CoordinatesType( ( stepX > 0 ), ( stepY > 0 ), ( stepZ > 0 ) ), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ), stepZ + ( " - "stepZ < 0 ) ) = " - << entity.getCoordinates() - + CoordinatesType( stepX + ( stepX < 0 ), stepY + ( stepY < 0 ), stepZ + ( stepZ < 0 ) ) - << " entity.getMesh().getDimensions() + CoordinatesType( sign( stepX ), sign( stepY ), sign( stepZ ) ) = " - << entity.getMesh().getDimensions() + CoordinatesType( sign( stepX ), sign( stepY ), sign( stepZ ) ) - << " EntityDimension = " << EntityDimension ); - return NeighborGridEntityType( this->entity.getMesh(), - CoordinatesType( entity.getCoordinates().x() + stepX + ( stepX < 0 ), - entity.getCoordinates().y() + stepY + ( stepY < 0 ), - entity.getCoordinates().z() + stepZ + ( stepZ < 0 ) ) ); - } - - template< int stepX, int stepY, int stepZ > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - return GridEntityGetterType::getEntityIndex( entity.getMesh(), getEntity< stepX, stepY, stepZ >() ); - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ){}; - -protected: - const GridEntityType& entity; - - // NeighborGridEntityGetter(){}; -}; - -/**** - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stored Stencil | - * +-----------------+---------------------------+-------------------+ - * | 2 | 3 | None | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 2, Config >, - 3, - GridEntityStencilStorageTag< GridEntityNoStencil > > -{ -public: - static constexpr int EntityDimension = 2; - static constexpr int NeighborEntityDimension = 3; - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - template< int stepX, int stepY, int stepZ > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - /*TNL_ASSERT( ( ( !! stepX ) == ( !! entity.getOrientation().x() ) ) && - ( ( !! stepY ) == ( !! entity.getOrientation().y() ) ) && - ( ( !! stepZ ) == ( !! entity.getOrientation().z() ) ), - std::cerr << "( stepX, stepY, stepZ ) cannot be perpendicular to entity coordinates: stepX = " << stepX - << " stepY = " << stepY << " stepZ = " << stepZ - << " entity.getOrientation() = " << entity.getOrientation() );*/ - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LT( - entity.getCoordinates(), entity.getMesh().getDimensions() + TNL::abs( entity.getOrientation() ), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates() - + CoordinatesType( stepX - ( stepX > 0 ) * ( entity.getOrientation().x() != 0.0 ), - stepY - ( stepY > 0 ) * ( entity.getOrientation().y() != 0.0 ), - stepZ - ( stepZ > 0 ) * ( entity.getOrientation().z() != 0.0 ) ) - >= CoordinatesType( 0, 0, 0 ) - && entity.getCoordinates() - + CoordinatesType( stepX - ( stepX > 0 ) * ( entity.getOrientation().x() != 0.0 ), - stepY - ( stepY > 0 ) * ( entity.getOrientation().y() != 0.0 ), - stepZ - ( stepZ > 0 ) * ( entity.getOrientation().z() != 0.0 ) ) - < entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX + ( stepX < 0 ) * ( " - "entity.getOrientation().x() != 0.0 ), stepY + ( stepY < 0 ) * ( entity.getOrientation().y() != " - "0.0 ), stepZ + ( stepZ < 0 ) * ( entity.getOrientation().z() != 0.0 ) ) = " - << entity.getCoordinates() - + CoordinatesType( stepX + ( stepX < 0 ) * ( entity.getOrientation().x() != 0.0 ), - stepY + ( stepY < 0 ) * ( entity.getOrientation().y() != 0.0 ), - stepZ + ( stepZ < 0 ) * ( entity.getOrientation().z() != 0.0 ) ) - << " entity.getMesh().getDimensions() = " << entity.getMesh().getDimensions() - << " EntityDimension = " << EntityDimension ); - return NeighborGridEntityType( - this->entity.getMesh(), - CoordinatesType( entity.getCoordinates().x() + stepX - ( stepX > 0 ) * ( entity.getOrientation().x() != 0.0 ), - entity.getCoordinates().y() + stepY - ( stepY > 0 ) * ( entity.getOrientation().y() != 0.0 ), - entity.getCoordinates().z() + stepZ - ( stepZ > 0 ) * ( entity.getOrientation().z() != 0.0 ) ) ); - } - - template< int stepX, int stepY, int stepZ > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - return GridEntityGetterType::getEntityIndex( entity.getMesh(), getEntity< stepX, stepY, stepZ >() ); - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ){}; - -protected: - const GridEntityType& entity; - - // NeighborGridEntityGetter(){}; -}; - -/**** - * +-----------------+---------------------------+-------------------+ - * | EntityDimenions | NeighborEntityDimension | Stored Stencil | - * +-----------------+---------------------------+-------------------+ - * | 0 | 0 | None | - * +-----------------+---------------------------+-------------------+ - */ -template< typename Real, typename Device, typename Index, typename Config > -class NeighborGridEntityGetter< GridEntity< Meshes::Grid< 3, Real, Device, Index >, 0, Config >, - 0, - GridEntityStencilStorageTag< GridEntityNoStencil > > -{ -public: - static constexpr int EntityDimension = 0; - static constexpr int NeighborEntityDimension = 0; - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using GridEntityType = GridEntity< GridType, EntityDimension, Config >; - using NeighborGridEntityType = GridEntity< GridType, NeighborEntityDimension, Config >; - using RealType = Real; - using IndexType = Index; - using CoordinatesType = typename GridType::CoordinatesType; - using GridEntityGetterType = GridEntityGetter< GridType, NeighborGridEntityType >; - - __cuda_callable__ - inline NeighborGridEntityGetter( const GridEntityType& entity ) : entity( entity ) {} - - template< int stepX, int stepY, int stepZ > - __cuda_callable__ - inline NeighborGridEntityType - getEntity() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LE( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates() + CoordinatesType( stepX, stepY, stepZ ) >= CoordinatesType( 0, 0, 0 ) - && entity.getCoordinates() + CoordinatesType( stepX, stepY, stepZ ) <= entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX, stepY, stepZ ) = " - << entity.getCoordinates() + CoordinatesType( stepX, stepY, stepZ ) - << " entity.getMesh().getDimensions() = " << entity.getMesh().getDimensions() - << " EntityDimension = " << EntityDimension ); - return NeighborGridEntityType( this->entity.getMesh(), - CoordinatesType( entity.getCoordinates().x() + stepX, - entity.getCoordinates().y() + stepY, - entity.getCoordinates().z() + stepZ ) ); - } - - template< int stepX, int stepY, int stepZ > - __cuda_callable__ - inline IndexType - getEntityIndex() const - { - TNL_ASSERT_GE( entity.getCoordinates(), CoordinatesType( 0, 0, 0 ), "wrong coordinates" ); - TNL_ASSERT_LE( entity.getCoordinates(), entity.getMesh().getDimensions(), "wrong coordinates" ); - TNL_ASSERT( entity.getCoordinates() + CoordinatesType( stepX, stepY, stepZ ) >= CoordinatesType( 0, 0, 0 ) - && entity.getCoordinates() + CoordinatesType( stepX, stepY, stepZ ) <= entity.getMesh().getDimensions(), - std::cerr << "entity.getCoordinates() + CoordinatesType( stepX, stepY, stepZ ) = " - << entity.getCoordinates() + CoordinatesType( stepX, stepY, stepZ ) - << " entity.getMesh().getDimensions() = " << entity.getMesh().getDimensions() - << " EntityDimension = " << EntityDimension ); - return this->entity.getIndex() - + stepZ * ( entity.getMesh().getDimensions().y() + 1 + stepY ) * ( entity.getMesh().getDimensions().x() + 1 ) - + stepX; - } - - __cuda_callable__ - void - refresh( const GridType& grid, const IndexType& entityIndex ){}; - -protected: - const GridEntityType& entity; - - // NeighborGridEntityGetter(){}; -}; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/NeighbourGridEntityGetter.h b/src/TNL/Meshes/GridDetails/NeighbourGridEntityGetter.h new file mode 100644 index 0000000000000000000000000000000000000000..e02b5723def2d77616560823fc1fc5363f47b5e3 --- /dev/null +++ b/src/TNL/Meshes/GridDetails/NeighbourGridEntityGetter.h @@ -0,0 +1,25 @@ +/*************************************************************************** + NeighbourGridEntityGetter.h - description + ------------------- + begin : Nov 23, 2015 + copyright : (C) 2015 by Tomas Oberhuber + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +namespace TNL { +namespace Meshes { + +template< class, int > +class GridEntity; + +template< int GridDimension, int ParentEntityDimension, int NeighbourEntityDimension > +class NeighbourGridEntityGetter; + +} // namespace Meshes +} // namespace TNL + +#include diff --git a/src/TNL/Meshes/GridDetails/Templates/BooleanOperations.h b/src/TNL/Meshes/GridDetails/Templates/BooleanOperations.h new file mode 100644 index 0000000000000000000000000000000000000000..cc6c570aa86035438a4a5141d4d4f2a5daa57536 --- /dev/null +++ b/src/TNL/Meshes/GridDetails/Templates/BooleanOperations.h @@ -0,0 +1,54 @@ + +#pragma once + +#include + +namespace TNL { +namespace Meshes { +namespace Templates { + +/** + * One of the possible implementation of the conjuction operator. + * + * This one is taken from https://en.cppreference.com/w/cpp/types/conjunction + */ + +template< class... > +struct conjuction : std::true_type +{}; + +template< class Type > +struct conjuction< Type > : Type +{}; + +template< class Head, class... Tail > +struct conjuction< Head, Tail... > : std::conditional_t< bool( Head::value ), conjuction< Tail... >, Head > +{}; + +template< class... Types > +constexpr bool conjunction_v = conjuction< Types... >::value; + +/** + * One of the possible implementation of the conjuction operator. + * + * This one is taken from https://en.cppreference.com/w/cpp/types/disjunction + */ + +template< class... > +struct disjunction : std::false_type +{}; + +template< class Type > +struct disjunction< Type > : Type +{}; + +template< class Head, class... Tail > +struct disjunction< Head, Tail... > : std::conditional_t< bool( Head::value ), Head, disjunction< Tail... > > +{}; + +template< class... Types > +constexpr bool disjunction_v = disjunction< Types... >::value; + +} // namespace Templates +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Templates/DescendingFor.h b/src/TNL/Meshes/GridDetails/Templates/DescendingFor.h new file mode 100644 index 0000000000000000000000000000000000000000..dda83ae5a3aa39d88e8b82d6b25a1e955b1da8a5 --- /dev/null +++ b/src/TNL/Meshes/GridDetails/Templates/DescendingFor.h @@ -0,0 +1,47 @@ + +#pragma once + +#include + +namespace TNL { +namespace Meshes { +namespace Templates { + +/* + * A compiler-friendly implementation of the templated for-cycle, because + * the template specializations count is O(Value) bounded. + */ +template< int > +struct DescendingFor; + +template< int Value > +struct DescendingFor +{ +public: + template< typename Func, typename... FuncArgs > + inline static void + exec( Func&& func, FuncArgs&&... args ) + { + static_assert( Value > 0, "Couldn't descend for negative values" ); + + func( std::integral_constant< int, Value >(), std::forward< FuncArgs >( args )... ); + + DescendingFor< Value - 1 >::exec( std::forward< Func >( func ), std::forward< FuncArgs >( args )... ); + } +}; + +template<> +struct DescendingFor< 0 > +{ +public: + template< typename Func, typename... FuncArgs > + inline static void + exec( Func&& func, FuncArgs&&... args ) + { + func( std::integral_constant< int, 0 >(), std::forward< FuncArgs >( args )... ); + } +}; + +} // namespace Templates +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Templates/ForEachOrientation.h b/src/TNL/Meshes/GridDetails/Templates/ForEachOrientation.h new file mode 100644 index 0000000000000000000000000000000000000000..c0e0b9d25dac23bc9b599222324313e3fc2b9332 --- /dev/null +++ b/src/TNL/Meshes/GridDetails/Templates/ForEachOrientation.h @@ -0,0 +1,67 @@ + +#pragma once + +#include + +namespace TNL { +namespace Meshes { +namespace Templates { + +template< typename Index, int Orientation, int EntityDimension, int Dimension, int SkipValue > +struct _ForEachOrientationMain; + +template< typename Index, int Orientation, int EntityDimension, int Dimension, int SkipValue > +struct _ForEachOrientationSupport +{ + using BasisGetterType = BasisGetter< Index, EntityDimension, Dimension >; + +public: + template< typename Func > + inline static void + exec( Func func ) + { + func( std::integral_constant< int, Orientation >(), BasisGetterType::template getBasis< Orientation >() ); + + _ForEachOrientationMain< Index, Orientation - 1, EntityDimension, Dimension, SkipValue >::exec( func ); + } +}; + +template< typename Index, int EntityDimension, int Dimension, int SkipValue > +struct _ForEachOrientationSupport< Index, 0, EntityDimension, Dimension, SkipValue > +{ +public: + using BasisGetterType = BasisGetter< Index, EntityDimension, Dimension >; + + template< typename Func > + inline static void + exec( Func func ) + { + func( std::integral_constant< int, 0 >(), BasisGetterType::template getBasis< 0 >() ); + } +}; + +template< typename Index, int EntityDimension, int Dimension > +struct _ForEachOrientationSupport< Index, 0, EntityDimension, Dimension, 0 > +{ +public: + template< typename Func > + inline static void + exec( Func func ) + {} +}; + +template< typename Index, int Orientation, int EntityDimension, int Dimension, int SkipValue > +struct _ForEachOrientationMain +: std::conditional_t< + Orientation == SkipValue, + _ForEachOrientationSupport< Index, ( Orientation <= 1 ? 0 : Orientation - 1 ), EntityDimension, Dimension, SkipValue >, + _ForEachOrientationSupport< Index, Orientation, EntityDimension, Dimension, SkipValue > > +{}; + +template< typename Index, int EntityDimension, int Dimension, int skipOrientation = -1 > +struct ForEachOrientation +: _ForEachOrientationMain< Index, combination( EntityDimension, Dimension ) - 1, EntityDimension, Dimension, skipOrientation > +{}; +} // namespace Templates +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Templates/Functions.h b/src/TNL/Meshes/GridDetails/Templates/Functions.h new file mode 100644 index 0000000000000000000000000000000000000000..2e95866571fa898910f2cf02509af747b3b4dbb6 --- /dev/null +++ b/src/TNL/Meshes/GridDetails/Templates/Functions.h @@ -0,0 +1,116 @@ + +#pragma once + +#include +#include + +namespace TNL { +namespace Meshes { +namespace Templates { + +constexpr size_t +pow( size_t Value, size_t Power ) +{ + size_t result = 1; + + for( size_t i = 0; i < Power; i++ ) + result *= Value; + + return result; +} + +template< typename Index > +constexpr Index +product( Index from, Index to ) +{ + Index result = 1; + + if( from <= to ) + for( Index i = from; i <= to; i++ ) + result *= i; + + return result; +} + +template< typename Index > +constexpr Index +combination( Index k, Index n ) +{ + return product< Index >( k + 1, n ) / product< Index >( 1, n - k ); +} + +/** + * @brief A help method to calculate collapsed index the next way: + * base ^ 0 * (power_0 + base/2) + base ^ 1 * (power_1 + base/2) + * + * @tparam Powers + * @param base - base value of the series + * @param powers - powers values + * @return constexpr int + */ +template< typename Index, int Size > +constexpr Index +makeCollapsedIndex( const Index base, const TNL::Containers::StaticVector< Size, Index > powers ) +{ + Index index = 0; + Index currentBase = 1; + Index halfBase = base >> 1; + + for( Index i = 0; i < powers.getSize(); i++ ) { + index += ( powers[ i ] + halfBase ) * currentBase; + currentBase *= base; + } + + return index; +} + +template< typename Index, Index... Powers > +constexpr Index +makeCollapsedIndex( const int base ) +{ + Index index = 0; + Index currentBase = 1; + Index halfBase = base >> 1; + + for( const auto x : { Powers... } ) { + index += ( x + halfBase ) * currentBase; + currentBase *= base; + } + + return index; +} + +template< typename Index > +constexpr Index +firstKCombinationSum( Index k, Index n ) +{ + if( k == 0 ) + return 0; + + if( k == n ) + return ( 1 << n ) - 1; + + Index result = 0; + + // Fraction simplification of k-combination + for( Index i = 0; i < k; i++ ) + result += combination( i, n ); + + return result; +} + +constexpr bool +isInClosedInterval( int lower, int value, int upper ) +{ + return lower <= value && value <= upper; +} + +constexpr bool +isInLeftClosedRightOpenInterval( int lower, int value, int upper ) +{ + return lower <= value && value < upper; +} + +} // namespace Templates +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Templates/ParallelFor.h b/src/TNL/Meshes/GridDetails/Templates/ParallelFor.h new file mode 100644 index 0000000000000000000000000000000000000000..0ab3c4d87c1f2a60bdbf5775030c32e5dfb2e6b6 --- /dev/null +++ b/src/TNL/Meshes/GridDetails/Templates/ParallelFor.h @@ -0,0 +1,80 @@ + +#pragma once + +#include +#include + +namespace TNL { +namespace Meshes { +namespace Templates { + +/** + * A dimension-based interface of ParallelFor algorithm + */ +template< int, typename, typename > +struct ParallelFor; + +template< typename Device, typename Index > +struct ParallelFor< 1, Device, Index > +{ +public: + template< typename Func, typename... FuncArgs > + inline static void + exec( const TNL::Containers::StaticVector< 1, Index >& from, + const TNL::Containers::StaticVector< 1, Index >& to, + Func func, + FuncArgs... args ) + { + auto groupIndex = [ = ] __cuda_callable__( Index i, FuncArgs... args ) mutable + { + func( TNL::Containers::StaticVector< 1, Index >( i ), args... ); + }; + + TNL::Algorithms::ParallelFor< Device >::exec( from.x(), to.x(), groupIndex, args... ); + } +}; + +template< typename Device, typename Index > +struct ParallelFor< 2, Device, Index > +{ +public: + template< typename Func, typename... FuncArgs > + inline static void + exec( const TNL::Containers::StaticVector< 2, Index >& from, + const TNL::Containers::StaticVector< 2, Index >& to, + Func func, + FuncArgs... args ) + { + auto groupIndex = [ = ] __cuda_callable__( Index i, Index j, FuncArgs... args ) mutable + { + func( TNL::Containers::StaticVector< 2, Index >( i, j ), args... ); + }; + + TNL::Algorithms::ParallelFor2D< Device >::exec( from.x(), from.y(), to.x(), to.y(), groupIndex, args... ); + } +}; + +template< typename Device, typename Index > +struct ParallelFor< 3, Device, Index > +{ +public: + template< typename Func, typename... FuncArgs > + inline static void + exec( const TNL::Containers::StaticVector< 3, Index >& from, + const TNL::Containers::StaticVector< 3, Index >& to, + Func func, + FuncArgs... args ) + { + auto groupIndex = [ = ] __cuda_callable__( Index i, Index j, Index k, FuncArgs... args ) mutable + { + func( TNL::Containers::StaticVector< 3, Index >( i, j, k ), args... ); + }; + + TNL::Algorithms::ParallelFor3D< Device >::exec( + from.x(), from.y(), from.z(), to.x(), to.y(), to.z(), groupIndex, args... ); + } +}; + +} // namespace Templates +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Templates/Permutations.h b/src/TNL/Meshes/GridDetails/Templates/Permutations.h new file mode 100644 index 0000000000000000000000000000000000000000..201960d570483f011d10b5e4e10e81e634cc3d2a --- /dev/null +++ b/src/TNL/Meshes/GridDetails/Templates/Permutations.h @@ -0,0 +1,302 @@ + +#pragma once + +#include +#include + +namespace TNL { +namespace Meshes { +namespace Templates { + +/* + * A pack of type and its count + */ +template< class, size_t > +struct counted_pack +{}; + +/* + * A pack of types + */ +template< class... > +struct pack +{}; + +/* + * A pack of int values + */ +template< int... > +struct int_pack +{}; + +/** + * A merge operation between to packs. + * + * Merge -> type + * Merge, pack> -> pack + * Merge, int_pack> -> int_pack + * Merge, pack, ..., pack> -> pack + * Merge, int_pack, ..., int_pack> -> int_pack + */ + +template< class... Packs > +struct Merge; + +template< class P > +struct Merge< P > +{ +public: + using type = P; +}; + +template< class... LHS, class... RHS > +struct Merge< pack< LHS... >, pack< RHS... > > +{ +public: + using type = pack< LHS..., RHS... >; +}; + +template< int... LHS, int... RHS > +struct Merge< int_pack< LHS... >, int_pack< RHS... > > +{ +public: + using type = int_pack< LHS..., RHS... >; +}; + +template< class LHS, class... RHS > +struct Merge< LHS, RHS... > : Merge< LHS, typename Merge< RHS... >::type > +{}; + +template< class... types > +using merge = typename Merge< types... >::type; + +/** + * Prepends a type to a parameter pack + */ + +template< class, class > +struct Prepend +{}; + +template< class Type, class... Types > +struct Prepend< Type, pack< Types... > > +{ + using type = pack< Type, Types... >; +}; + +template< typename Type, class Pack > +using prepend = typename Prepend< Type, Pack >::type; + +/** + * Pushes type to the CountedTypes pack. + * + * If type exists in the CountedTypes pack, then will increment a count of type. + * Otherwise appends a type to the CountedTypes pack. + */ + +template< class, class > +struct Push; + +template< class Type, class... Types, size_t... Counts > +struct Push< Type, pack< counted_pack< Types, Counts >... > > +{ +public: + using type = std::conditional_t< disjunction< std::is_same< Types, Type >... >::value, + pack< counted_pack< Types, Counts + ( std::is_same< Types, Type >::value ? 1 : 0 ) >... >, + pack< counted_pack< Types, Counts >..., counted_pack< Type, 1 > > >; +}; + +template< class Type, class CountedTypes > +using push = typename Push< Type, CountedTypes >::type; + +/** + * Removes first occurance of type in the pack + */ + +template< class, class > +struct RemoveFirst; + +template< class Type > +struct RemoveFirst< Type, pack<> > +{ +public: + using type = pack<>; +}; + +template< class Type, class CountedType > +using remove_first = typename RemoveFirst< Type, CountedType >::type; + +template< class Type, class Head, class... Tail > +struct RemoveFirst< Type, pack< Head, Tail... > > +{ +public: + using type = std::conditional_t< std::is_same< Type, Head >::value, + pack< Tail... >, + prepend< Head, remove_first< Type, pack< Tail... > > > >; +}; + +/* + * Pops type out of the CountedTypes pack. + * + * If type exists in the CountedTypes pack, then decrease it count by one. + * If the count of type in the CountedTypes pack is zero, then pop it. + */ +template< class, class > +struct Pop; + +template< class T, class... Types, std::size_t... Indices > +struct Pop< T, pack< counted_pack< Types, Indices >... > > +{ + using type = remove_first< counted_pack< T, 0 >, + pack< counted_pack< Types, Indices - ( std::is_same< Types, T >::value ? 1 : 0 ) >... > >; +}; + +template< class Type, class CountedType > +using pop = typename Pop< Type, CountedType >::type; + +/* + * Builds CountedTypes pack by counting the occurances of the types in input. + */ +template< class Pack, class CountedTypes = pack<> > +struct CountTypes +{ + using type = CountedTypes; +}; + +template< class CountedTypes, class Head, class... Tail > +struct CountTypes< pack< Head, Tail... >, CountedTypes > : CountTypes< pack< Tail... >, push< Head, CountedTypes > > +{}; + +// For int_pack count every int value as a separate type (push) +template< class CountedTypes, int Head, int... Tail > +struct CountTypes< int_pack< Head, Tail... >, CountedTypes > +: CountTypes< int_pack< Tail... >, push< int_pack< Head >, CountedTypes > > +{}; + +template< class Pack > +using count_types = typename CountTypes< Pack >::type; + +/* + * An identity type + */ +template< class T > +struct identity +{ + using type = T; +}; + +/** + * Generates all permutations with repetitions of length N from the pack of types. + * + * Thanks for idea: https://stackoverflow.com/questions/36465889/permutation-pn-r-of-types-in-compile-time + */ + +template< std::size_t, class, class = pack<> > +struct MakePermutations; + +// Workaround for GCC's partial ordering failure +template< std::size_t, class, class > +struct MakePermutationsImpl; + +template< std::size_t N, class... Types, std::size_t... Counts, class... Current > +struct MakePermutationsImpl< N, pack< counted_pack< Types, Counts >... >, pack< Current... > > +{ + // The next item can be anything in Types... + // We append it to Current... and pop it from the list of types, then + // recursively generate the remaining items + // Do this for every type in Types..., and concatenate the result. + using type = merge< typename MakePermutations< N - 1, + pop< Types, pack< counted_pack< Types, Counts >... > >, + pack< Current..., Types > >::type... >; +}; + +template< std::size_t N, class... Types, std::size_t... Counts, class... Current > +struct MakePermutations< N, pack< counted_pack< Types, Counts >... >, pack< Current... > > +{ + // Note that we don't attempt to evaluate MakePermutationsImpl<...>::type + // until we are sure that N > 0 + using type = typename std::conditional_t< + N == 0, + identity< pack< pack< Current... > > >, + MakePermutationsImpl< N, pack< counted_pack< Types, Counts >... >, pack< Current... > > >::type; +}; + +template< std::size_t N, typename Pack > +using make_permutations = typename MakePermutations< N, count_types< Pack > >::type; + +/* + * Recursively goes through pack tree and merges specified level. + */ + +template< std::size_t, class... > +struct GroupLevel +{}; + +template< std::size_t N, class... Types > +struct GroupLevel< N, pack< Types... > > +{ + using type = pack< typename GroupLevel< N - 1, Types >::type... >; +}; + +template< class... Types > +struct GroupLevel< 0, pack< Types... > > +{ + using type = merge< Types... >; +}; + +template< std::size_t N, class... Types > +using group_level = typename GroupLevel< N, Types... >::type; + +/* + * A support for the int_pack permutations. + * The result of make_permutations is pack, int_pack<>...>, ...>, that's why we merge the 1 level. + */ +template< std::size_t N, typename Pack > +using make_int_permutations = group_level< 1, make_permutations< N, Pack > >; + +/** + * Builds the pack with k ones at the end. + */ +template< int, int, class = int_pack<> > +struct BuildOnesPack; + +template< int OnesCount, int Size, int... Values > +struct BuildOnesPack< OnesCount, Size, int_pack< Values... > > +: std::conditional_t< OnesCount == 0, + BuildOnesPack< 0, Size - 1, int_pack< 0, Values... > >, + BuildOnesPack< OnesCount - 1, Size - 1, int_pack< 1, Values... > > > +{}; + +template< int Value, int... Values > +struct BuildOnesPack< Value, 0, int_pack< Values... > > +{ +public: + using type = int_pack< Values... >; +}; + +template< int OnesCount, int Size > +using build_ones_pack = typename BuildOnesPack< OnesCount, Size >::type; + +/* + * Gets specific element from the parameter pack + */ +template< int, class > +struct Get; + +template< int Index, class Head, class... Tail > +struct Get< Index, pack< Head, Tail... > > : Get< Index - 1, pack< Tail... > > +{}; + +template< class Head, class... Tail > +struct Get< 0, pack< Head, Tail... > > +{ +public: + using type = Head; +}; + +template< int N, class Pack > +using get = typename Get< N, Pack >::type; + +} // namespace Templates +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Traverser_Grid1D.h b/src/TNL/Meshes/GridDetails/Traverser_Grid1D.h deleted file mode 100644 index 67b7cc619a4d601a4113358d5c9f8916488ffc76..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/Traverser_Grid1D.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include - -namespace TNL { -namespace Meshes { - -template< typename Real, typename Device, typename Index, typename GridEntity > -class Traverser< Meshes::Grid< 1, Real, Device, Index >, GridEntity, 1 > -{ -public: - using GridType = Meshes::Grid< 1, Real, Device, Index >; - using GridPointer = Pointers::SharedPointer< GridType >; - using CoordinatesType = typename GridType::CoordinatesType; - - template< typename EntitiesProcessor, typename UserData > - void - processBoundaryEntities( const GridPointer& gridPointer, UserData& userData ) const; - - template< typename EntitiesProcessor, typename UserData > - void - processInteriorEntities( const GridPointer& gridPointer, UserData& userData ) const; - - template< typename EntitiesProcessor, typename UserData > - void - processAllEntities( const GridPointer& gridPointer, UserData& userData ) const; -}; - -template< typename Real, typename Device, typename Index, typename GridEntity > -class Traverser< Meshes::Grid< 1, Real, Device, Index >, GridEntity, 0 > -{ -public: - using GridType = Meshes::Grid< 1, Real, Device, Index >; - using GridPointer = Pointers::SharedPointer< GridType >; - using CoordinatesType = typename GridType::CoordinatesType; - - template< typename EntitiesProcessor, typename UserData > - void - processBoundaryEntities( const GridPointer& gridPointer, UserData& userData ) const; - - template< typename EntitiesProcessor, typename UserData > - void - processInteriorEntities( const GridPointer& gridPointer, UserData& userData ) const; - - template< typename EntitiesProcessor, typename UserData > - void - processAllEntities( const GridPointer& gridPointer, UserData& userData ) const; -}; - -} // namespace Meshes -} // namespace TNL - -#include diff --git a/src/TNL/Meshes/GridDetails/Traverser_Grid1D_impl.h b/src/TNL/Meshes/GridDetails/Traverser_Grid1D_impl.h deleted file mode 100644 index 2ddfbffcee8a65ea9555123d5992150de85cddc6..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/Traverser_Grid1D_impl.h +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include - -namespace TNL { -namespace Meshes { - -/**** - * Grid 1D, cells - */ -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 1, Real, Device, Index >, GridEntity, 1 >::processBoundaryEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * Boundary cells - */ - static_assert( GridEntity::getEntityDimension() == 1, "The entity has wrong dimensions." ); - - if( gridPointer->getLocalBegin() < gridPointer->getInteriorBegin() - && gridPointer->getInteriorEnd() < gridPointer->getLocalEnd() ) - { - // 2 boundaries (left and right) - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, true >( - gridPointer, gridPointer->getInteriorBegin() - 1, gridPointer->getInteriorEnd() + 1, userData, asynchronousMode ); - } - else if( gridPointer->getLocalBegin() < gridPointer->getInteriorBegin() ) { - // 1 boundary (left) - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, gridPointer->getInteriorBegin() - 1, gridPointer->getInteriorBegin(), userData, asynchronousMode ); - } - else if( gridPointer->getInteriorEnd() < gridPointer->getLocalEnd() ) { - // 1 boundary (right) - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, gridPointer->getInteriorEnd(), gridPointer->getInteriorEnd() + 1, userData, asynchronousMode ); - } -} - -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 1, Real, Device, Index >, GridEntity, 1 >::processInteriorEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * Interior cells - */ - static_assert( GridEntity::getEntityDimension() == 1, "The entity has wrong dimension." ); - - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, gridPointer->getInteriorBegin(), gridPointer->getInteriorEnd(), userData, asynchronousMode ); -} - -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 1, Real, Device, Index >, GridEntity, 1 >::processAllEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * All cells - */ - static_assert( GridEntity::getEntityDimension() == 1, "The entity has wrong dimensions." ); - - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, gridPointer->getLocalBegin(), gridPointer->getLocalEnd(), userData, asynchronousMode ); -} - -/**** - * Grid 1D, vertices - */ -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 1, Real, Device, Index >, GridEntity, 0 >::processBoundaryEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * Boundary vertices - */ - static_assert( GridEntity::getEntityDimension() == 0, "The entity has wrong dimension." ); - - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, true >( - gridPointer, CoordinatesType( 0 ), gridPointer->getDimensions() + 1, userData, asynchronousMode ); -} - -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 1, Real, Device, Index >, GridEntity, 0 >::processInteriorEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * Interior vertices - */ - static_assert( GridEntity::getEntityDimension() == 0, "The entity has wrong dimension." ); - - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, CoordinatesType( 1 ), gridPointer->getDimensions(), userData, asynchronousMode ); -} - -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 1, Real, Device, Index >, GridEntity, 0 >::processAllEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * All vertices - */ - static_assert( GridEntity::getEntityDimension() == 0, "The entity has wrong dimension." ); - - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, CoordinatesType( 0 ), gridPointer->getDimensions() + 1, userData, asynchronousMode ); -} - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Traverser_Grid2D.h b/src/TNL/Meshes/GridDetails/Traverser_Grid2D.h deleted file mode 100644 index 0473c1236b8b219ab655789abaade6d941b8ebac..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/Traverser_Grid2D.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include - -namespace TNL { -namespace Meshes { - -template< typename Real, typename Device, typename Index, typename GridEntity > -class Traverser< Meshes::Grid< 2, Real, Device, Index >, GridEntity, 2 > -{ -public: - using GridType = Meshes::Grid< 2, Real, Device, Index >; - using GridPointer = Pointers::SharedPointer< GridType >; - using CoordinatesType = typename GridType::CoordinatesType; - - template< typename EntitiesProcessor, typename UserData > - void - processBoundaryEntities( const GridPointer& gridPointer, UserData& userData ) const; - - template< typename EntitiesProcessor, typename UserData > - void - processInteriorEntities( const GridPointer& gridPointer, UserData& userData ) const; - template< typename EntitiesProcessor, typename UserData > - void - processAllEntities( const GridPointer& gridPointer, UserData& userData ) const; -}; - -template< typename Real, typename Device, typename Index, typename GridEntity > -class Traverser< Meshes::Grid< 2, Real, Device, Index >, GridEntity, 1 > -{ -public: - using GridType = Meshes::Grid< 2, Real, Device, Index >; - using GridPointer = Pointers::SharedPointer< GridType >; - using CoordinatesType = typename GridType::CoordinatesType; - - template< typename EntitiesProcessor, typename UserData > - void - processBoundaryEntities( const GridPointer& gridPointer, UserData& userData ) const; - - template< typename EntitiesProcessor, typename UserData > - void - processInteriorEntities( const GridPointer& gridPointer, UserData& userData ) const; - - template< typename EntitiesProcessor, typename UserData > - void - processAllEntities( const GridPointer& gridPointer, UserData& userData ) const; -}; - -template< typename Real, typename Device, typename Index, typename GridEntity > -class Traverser< Meshes::Grid< 2, Real, Device, Index >, GridEntity, 0 > -{ -public: - using GridType = Meshes::Grid< 2, Real, Device, Index >; - using GridPointer = Pointers::SharedPointer< GridType >; - using CoordinatesType = typename GridType::CoordinatesType; - - template< typename EntitiesProcessor, typename UserData > - void - processBoundaryEntities( const GridPointer& gridPointer, UserData& userData ) const; - - template< typename EntitiesProcessor, typename UserData > - void - processInteriorEntities( const GridPointer& gridPointer, UserData& userData ) const; - - template< typename EntitiesProcessor, typename UserData > - void - processAllEntities( const GridPointer& gridPointer, UserData& userData ) const; -}; - -} // namespace Meshes -} // namespace TNL - -#include diff --git a/src/TNL/Meshes/GridDetails/Traverser_Grid2D_impl.h b/src/TNL/Meshes/GridDetails/Traverser_Grid2D_impl.h deleted file mode 100644 index 56740c4c964ae78b6bf36a9ef7ef694283e64e2c..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/Traverser_Grid2D_impl.h +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include - -namespace TNL { -namespace Meshes { - -/**** - * Grid 2D, cells - */ -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 2, Real, Device, Index >, GridEntity, 2 >::processBoundaryEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * Boundary cells - */ - static_assert( GridEntity::getEntityDimension() == 2, "The entity has wrong dimension." ); - - if( gridPointer->getLocalBegin() < gridPointer->getInteriorBegin() - && gridPointer->getInteriorEnd() < gridPointer->getLocalEnd() ) - { - // 4 boundaries (left, right, down, up) - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, true, 1, 1 >( - gridPointer, gridPointer->getInteriorBegin() - 1, gridPointer->getInteriorEnd() + 1, userData, asynchronousMode, 0 ); - } - else { - const CoordinatesType begin = gridPointer->getLocalBegin(); - const CoordinatesType end = gridPointer->getLocalEnd(); - const CoordinatesType skipBegin = gridPointer->getInteriorBegin(); - const CoordinatesType skipEnd = gridPointer->getInteriorEnd(); - - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, begin, CoordinatesType( end.x(), skipBegin.y() ), userData, asynchronousMode, 0 ); - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, CoordinatesType( begin.x(), skipEnd.y() ), end, userData, asynchronousMode, 0 ); - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, - CoordinatesType( begin.x(), skipBegin.y() ), - CoordinatesType( skipBegin.x(), skipEnd.y() ), - userData, - asynchronousMode, - 0 ); - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, - CoordinatesType( skipEnd.x(), skipBegin.y() ), - CoordinatesType( end.x(), skipEnd.y() ), - userData, - asynchronousMode, - 0 ); - } -} - -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 2, Real, Device, Index >, GridEntity, 2 >::processInteriorEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * Interior cells - */ - static_assert( GridEntity::getEntityDimension() == 2, "The entity has wrong dimensions." ); - - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, gridPointer->getInteriorBegin(), gridPointer->getInteriorEnd(), userData, asynchronousMode, 0 ); -} - -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 2, Real, Device, Index >, GridEntity, 2 >::processAllEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * All cells - */ - static_assert( GridEntity::getEntityDimension() == 2, "The entity has wrong dimension." ); - - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, gridPointer->getLocalBegin(), gridPointer->getLocalEnd(), userData, asynchronousMode, 0 ); -} - -/**** - * Grid 2D, faces - */ -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 2, Real, Device, Index >, GridEntity, 1 >::processBoundaryEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * Boundary faces - */ - static_assert( GridEntity::getEntityDimension() == 1, "The entity has wrong dimension." ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, true, 1, 0, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 1, 0 ), - userData, - asynchronousMode, - 1, - CoordinatesType( 1, 0 ), - CoordinatesType( 0, 1 ) ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, true, 0, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 0, 1 ), - userData, - asynchronousMode, - 0, - CoordinatesType( 0, 1 ), - CoordinatesType( 1, 0 ) ); -} - -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 2, Real, Device, Index >, GridEntity, 1 >::processInteriorEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * Interior faces - */ - static_assert( GridEntity::getEntityDimension() == 1, "The entity has wrong dimension." ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, false, 1, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 1, 0 ), - gridPointer->getDimensions(), - userData, - asynchronousMode, - 1, - CoordinatesType( 1, 0 ), - CoordinatesType( 0, 1 ) ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, false, 1, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 1 ), - gridPointer->getDimensions(), - userData, - asynchronousMode, - 0, - CoordinatesType( 0, 1 ), - CoordinatesType( 1, 0 ) ); -} - -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 2, Real, Device, Index >, GridEntity, 1 >::processAllEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * All faces - */ - static_assert( GridEntity::getEntityDimension() == 1, "The entity has wrong dimension." ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, false, 1, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 1, 0 ), - userData, - asynchronousMode, - 1, - CoordinatesType( 1, 0 ), - CoordinatesType( 0, 1 ) ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, false, 1, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 0, 1 ), - userData, - asynchronousMode, - 0, - CoordinatesType( 0, 1 ), - CoordinatesType( 1, 0 ) ); -} - -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 2, Real, Device, Index >, GridEntity, 0 >::processBoundaryEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * Boundary vertices - */ - static_assert( GridEntity::getEntityDimension() == 0, "The entity has wrong dimension." ); - - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, true, 1, 1 >( - gridPointer, - CoordinatesType( 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 1, 1 ), - userData, - asynchronousMode, - 0 ); -} - -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 2, Real, Device, Index >, GridEntity, 0 >::processInteriorEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * Interior vertices - */ - static_assert( GridEntity::getEntityDimension() == 0, "The entity has wrong dimension." ); - - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, CoordinatesType( 1, 1 ), gridPointer->getDimensions(), userData, asynchronousMode, 0 ); -} - -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 2, Real, Device, Index >, GridEntity, 0 >::processAllEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * All vertices - */ - static_assert( GridEntity::getEntityDimension() == 0, "The entity has wrong dimension." ); - - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, - CoordinatesType( 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 1, 1 ), - userData, - asynchronousMode, - 0 ); -} - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Traverser_Grid3D.h b/src/TNL/Meshes/GridDetails/Traverser_Grid3D.h deleted file mode 100644 index 002f63203e27649ab5280ccd40a05cd20fa49b96..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/Traverser_Grid3D.h +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include - -namespace TNL { -namespace Meshes { - -template< typename Real, typename Device, typename Index, typename GridEntity > -class Traverser< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 3 > -{ -public: - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using GridPointer = Pointers::SharedPointer< GridType >; - using CoordinatesType = typename GridType::CoordinatesType; - - template< typename EntitiesProcessor, typename UserData > - void - processBoundaryEntities( const GridPointer& gridPointer, UserData& userData ) const; - - template< typename EntitiesProcessor, typename UserData > - void - processInteriorEntities( const GridPointer& gridPointer, UserData& userData ) const; - template< typename EntitiesProcessor, typename UserData > - void - processAllEntities( const GridPointer& gridPointer, UserData& userData ) const; -}; - -template< typename Real, typename Device, typename Index, typename GridEntity > -class Traverser< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 2 > -{ -public: - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using GridPointer = Pointers::SharedPointer< GridType >; - using CoordinatesType = typename GridType::CoordinatesType; - - template< typename EntitiesProcessor, typename UserData > - void - processBoundaryEntities( const GridPointer& gridPointer, UserData& userData ) const; - - template< typename EntitiesProcessor, typename UserData > - void - processInteriorEntities( const GridPointer& gridPointer, UserData& userData ) const; - template< typename EntitiesProcessor, typename UserData > - void - processAllEntities( const GridPointer& gridPointer, UserData& userData ) const; -}; - -template< typename Real, typename Device, typename Index, typename GridEntity > -class Traverser< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 1 > -{ -public: - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using GridPointer = Pointers::SharedPointer< GridType >; - using CoordinatesType = typename GridType::CoordinatesType; - - template< typename EntitiesProcessor, typename UserData > - void - processBoundaryEntities( const GridPointer& gridPointer, UserData& userData ) const; - - template< typename EntitiesProcessor, typename UserData > - void - processInteriorEntities( const GridPointer& gridPointer, UserData& userData ) const; - - template< typename EntitiesProcessor, typename UserData > - void - processAllEntities( const GridPointer& gridPointer, UserData& userData ) const; -}; - -template< typename Real, typename Device, typename Index, typename GridEntity > -class Traverser< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 0 > -{ -public: - using GridType = Meshes::Grid< 3, Real, Device, Index >; - using GridPointer = Pointers::SharedPointer< GridType >; - using CoordinatesType = typename GridType::CoordinatesType; - - template< typename EntitiesProcessor, typename UserData > - void - processBoundaryEntities( const GridPointer& gridPointer, UserData& userData ) const; - - template< typename EntitiesProcessor, typename UserData > - void - processInteriorEntities( const GridPointer& gridPointer, UserData& userData ) const; - - template< typename EntitiesProcessor, typename UserData > - void - processAllEntities( const GridPointer& gridPointer, UserData& userData ) const; -}; - -} // namespace Meshes -} // namespace TNL - -#include diff --git a/src/TNL/Meshes/GridDetails/Traverser_Grid3D_impl.h b/src/TNL/Meshes/GridDetails/Traverser_Grid3D_impl.h deleted file mode 100644 index f00b4dec391dbc7b3f865c166378329cc61e5139..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridDetails/Traverser_Grid3D_impl.h +++ /dev/null @@ -1,441 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include - -#include "Traverser_Grid3D.h" - -namespace TNL { -namespace Meshes { - -/**** - * Grid 3D, cells - */ -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 3 >::processBoundaryEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * Boundary cells - */ - static_assert( GridEntity::getEntityDimension() == 3, "The entity has wrong dimension." ); - - if( gridPointer->getLocalBegin() < gridPointer->getInteriorBegin() - && gridPointer->getInteriorEnd() < gridPointer->getLocalEnd() ) - { - // 6 boundaries (left, right, down, up, front, back) - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, true, 1, 1, 1 >( - gridPointer, gridPointer->getInteriorBegin() - 1, gridPointer->getInteriorEnd() + 1, userData, asynchronousMode, 0 ); - } - else { - const CoordinatesType begin = gridPointer->getLocalBegin(); - const CoordinatesType end = gridPointer->getLocalEnd(); - const CoordinatesType skipBegin = gridPointer->getInteriorBegin(); - const CoordinatesType skipEnd = gridPointer->getInteriorEnd(); - - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, begin, CoordinatesType( end.x(), end.y(), skipBegin.z() ), userData, asynchronousMode, 0 ); - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, CoordinatesType( begin.x(), begin.y(), skipEnd.z() ), end, userData, asynchronousMode, 0 ); - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, - CoordinatesType( begin.x(), begin.y(), skipBegin.z() ), - CoordinatesType( end.x(), skipBegin.y(), skipEnd.z() ), - userData, - asynchronousMode, - 0 ); - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, - CoordinatesType( begin.x(), skipEnd.y(), skipBegin.z() ), - CoordinatesType( end.x(), end.y(), skipEnd.z() ), - userData, - asynchronousMode, - 0 ); - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, - CoordinatesType( begin.x(), skipBegin.y(), skipBegin.z() ), - CoordinatesType( skipBegin.x(), skipEnd.y(), skipEnd.z() ), - userData, - asynchronousMode, - 0 ); - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, - CoordinatesType( skipEnd.x(), skipBegin.y(), skipBegin.z() ), - CoordinatesType( end.x(), skipEnd.y(), skipEnd.z() ), - userData, - asynchronousMode, - 0 ); - } -} - -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 3 >::processInteriorEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * Interior cells - */ - static_assert( GridEntity::getEntityDimension() == 3, "The entity has wrong dimension." ); - - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, gridPointer->getInteriorBegin(), gridPointer->getInteriorEnd(), userData, asynchronousMode, 0 ); -} - -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 3 >::processAllEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * All cells - */ - static_assert( GridEntity::getEntityDimension() == 3, "The entity has wrong dimension." ); - - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, gridPointer->getLocalBegin(), gridPointer->getLocalEnd(), userData, asynchronousMode, 0 ); -} - -/**** - * Grid 3D, faces - */ -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 2 >::processBoundaryEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * Boundary faces - */ - static_assert( GridEntity::getEntityDimension() == 2, "The entity has wrong dimension." ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, true, 1, 0, 0, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 1, 0, 0 ), - userData, - asynchronousMode, - 2, - CoordinatesType( 1, 0, 0 ), - CoordinatesType( 0, 1, 1 ) ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, true, 0, 1, 0, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 0, 1, 0 ), - userData, - asynchronousMode, - 1, - CoordinatesType( 0, 1, 0 ), - CoordinatesType( 1, 0, 1 ) ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, true, 0, 0, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 0, 0, 1 ), - userData, - asynchronousMode, - 0, - CoordinatesType( 0, 0, 1 ), - CoordinatesType( 1, 1, 0 ) ); -} - -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 2 >::processInteriorEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * Interior faces - */ - static_assert( GridEntity::getEntityDimension() == 2, "The entity has wrong dimension." ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, false, 1, 1, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 1, 0, 0 ), - gridPointer->getDimensions(), - userData, - asynchronousMode, - 2, - CoordinatesType( 1, 0, 0 ), - CoordinatesType( 0, 1, 1 ) ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, false, 1, 1, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 1, 0 ), - gridPointer->getDimensions(), - userData, - asynchronousMode, - 1, - CoordinatesType( 0, 1, 0 ), - CoordinatesType( 1, 0, 1 ) ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, false, 1, 1, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 0, 1 ), - gridPointer->getDimensions(), - userData, - asynchronousMode, - 0, - CoordinatesType( 0, 0, 1 ), - CoordinatesType( 1, 1, 0 ) ); -} - -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 2 >::processAllEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * All faces - */ - static_assert( GridEntity::getEntityDimension() == 2, "The entity has wrong dimension." ); - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, false, 1, 1, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 1, 0, 0 ), - userData, - asynchronousMode, - 2, - CoordinatesType( 1, 0, 0 ), - CoordinatesType( 0, 1, 1 ) ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, false, 1, 1, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 0, 1, 0 ), - userData, - asynchronousMode, - 1, - CoordinatesType( 0, 1, 0 ), - CoordinatesType( 1, 0, 1 ) ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, false, 1, 1, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 0, 0, 1 ), - userData, - asynchronousMode, - 0, - CoordinatesType( 0, 0, 1 ), - CoordinatesType( 1, 1, 0 ) ); -} - -/**** - * Grid 3D, edges - */ -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 1 >::processBoundaryEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * Boundary edges - */ - static_assert( GridEntity::getEntityDimension() == 1, "The entity has wrong dimension." ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, true, 0, 1, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 0, 1, 1 ), - userData, - asynchronousMode, - 2, - CoordinatesType( 0, 1, 1 ), - CoordinatesType( 1, 0, 0 ) ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, true, 1, 0, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 1, 0, 1 ), - userData, - asynchronousMode, - 1, - CoordinatesType( 1, 0, 1 ), - CoordinatesType( 0, 1, 0 ) ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, true, 1, 1, 0, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 1, 1, 0 ), - userData, - asynchronousMode, - 0, - CoordinatesType( 1, 1, 0 ), - CoordinatesType( 0, 0, 1 ) ); -} - -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 1 >::processInteriorEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * Interior edges - */ - static_assert( GridEntity::getEntityDimension() == 1, "The entity has wrong dimension." ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, false, 1, 1, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 1, 1 ), - gridPointer->getDimensions() + CoordinatesType( 1, 0, 0 ), - userData, - asynchronousMode, - 2, - CoordinatesType( 0, 1, 1 ), - CoordinatesType( 1, 0, 0 ) ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, false, 1, 1, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 1, 0, 1 ), - gridPointer->getDimensions() + CoordinatesType( 0, 1, 0 ), - userData, - asynchronousMode, - 1, - CoordinatesType( 1, 0, 1 ), - CoordinatesType( 0, 1, 0 ) ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, false, 1, 1, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 1, 1, 0 ), - gridPointer->getDimensions() + CoordinatesType( 0, 0, 1 ), - userData, - asynchronousMode, - 0, - CoordinatesType( 1, 1, 0 ), - CoordinatesType( 0, 0, 1 ) ); -} - -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 1 >::processAllEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * All edges - */ - static_assert( GridEntity::getEntityDimension() == 1, "The entity has wrong dimension." ); - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, false, 1, 1, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 0, 1, 1 ), - userData, - asynchronousMode, - 2, - CoordinatesType( 0, 1, 1 ), - CoordinatesType( 1, 0, 0 ) ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, false, 1, 1, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 1, 0, 1 ), - userData, - asynchronousMode, - 1, - CoordinatesType( 1, 0, 1 ), - CoordinatesType( 0, 1, 0 ) ); - - GridTraverser< GridType >:: - template processEntities< GridEntity, EntitiesProcessor, UserData, false, 1, 1, 1, CoordinatesType, CoordinatesType >( - gridPointer, - CoordinatesType( 0, 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 1, 1, 0 ), - userData, - asynchronousMode, - 0, - CoordinatesType( 1, 1, 0 ), - CoordinatesType( 0, 0, 1 ) ); -} - -/**** - * Grid 3D, vertices - */ -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 0 >::processBoundaryEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * Boundary vertices - */ - static_assert( GridEntity::getEntityDimension() == 0, "The entity has wrong dimension." ); - - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, true, 1, 1, 1 >( - gridPointer, - CoordinatesType( 0, 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 1, 1, 1 ), - userData, - asynchronousMode, - 0 ); -} - -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 0 >::processInteriorEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * Interior vertices - */ - static_assert( GridEntity::getEntityDimension() == 0, "The entity has wrong dimension." ); - - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, CoordinatesType( 1, 1, 1 ), gridPointer->getDimensions(), userData, asynchronousMode, 0 ); -} - -template< typename Real, typename Device, typename Index, typename GridEntity > -template< typename EntitiesProcessor, typename UserData > -void -Traverser< Meshes::Grid< 3, Real, Device, Index >, GridEntity, 0 >::processAllEntities( const GridPointer& gridPointer, - UserData& userData ) const -{ - /**** - * All vertices - */ - static_assert( GridEntity::getEntityDimension() == 0, "The entity has wrong dimension." ); - - GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >( - gridPointer, - CoordinatesType( 0, 0, 0 ), - gridPointer->getDimensions() + CoordinatesType( 1, 1, 1 ), - userData, - asynchronousMode, - 0 ); -} - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/GridEntity.h b/src/TNL/Meshes/GridEntity.h index a7c863db5445a2b162445fbf5a0ddd975ece88ae..238a926aa3e1043493e65172616c8f8a0e9d049d 100644 --- a/src/TNL/Meshes/GridEntity.h +++ b/src/TNL/Meshes/GridEntity.h @@ -6,415 +6,194 @@ #pragma once -#include -#include +#include namespace TNL { namespace Meshes { -template< typename GridEntity, int NeighborEntityDimension, typename StencilStorage > -class NeighborGridEntityGetter; +template< int, int, int > +class NeighbourGridEntityGetter; -template< typename GridEntityType > +template< class > class BoundaryGridEntityChecker; -template< typename GridEntityType > +template< class > class GridEntityCenterGetter; -template< typename Grid, int EntityDimension, typename Config > +template< class Grid, int EntityDimension > class GridEntity -{}; - -template< int Dimension, typename Real, typename Device, typename Index, int EntityDimension, typename Config > -class GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config > { public: - using GridType = Meshes::Grid< Dimension, Real, Device, Index >; - using MeshType = GridType; - using RealType = typename GridType::RealType; - using IndexType = typename GridType::IndexType; - using CoordinatesType = typename GridType::CoordinatesType; - using ConfigType = Config; - - constexpr static int - getMeshDimension() - { - return GridType::getMeshDimension(); - }; - - constexpr static int - getEntityDimension() - { - return EntityDimension; - }; - - using EntityOrientationType = Containers::StaticVector< getMeshDimension(), IndexType >; - using EntityBasisType = Containers::StaticVector< getMeshDimension(), IndexType >; - using PointType = typename GridType::PointType; - - using NeighborGridEntitiesStorageType = NeighborGridEntitiesStorage< GridEntity, Config >; - - template< int NeighborEntityDimension = getEntityDimension() > - using NeighborEntities = - NeighborGridEntityGetter< GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, EntityDimension, Config >, - NeighborEntityDimension >; - - __cuda_callable__ - inline GridEntity( const GridType& grid ); - - __cuda_callable__ - inline GridEntity( const GridType& grid, - const CoordinatesType& coordinates, - const EntityOrientationType& orientation, - const EntityBasisType& basis ); + using GridType = Grid; + using Index = typename Grid::IndexType; + using Device = typename Grid::DeviceType; + using Real = typename Grid::RealType; - __cuda_callable__ - inline const CoordinatesType& - getCoordinates() const; + using Coordinate = typename Grid::Coordinate; + using Point = typename Grid::Point; - __cuda_callable__ - inline CoordinatesType& - getCoordinates(); + constexpr static int meshDimension = Grid::getMeshDimension(); + constexpr static int entityDimension = EntityDimension; - __cuda_callable__ - inline void - setCoordinates( const CoordinatesType& coordinates ); + ///////////////////////////// + // Compatability with meshes + constexpr static int getEntityDimension() { + return entityDimension; + } + ///////////////////////////// - /*** - * Call this method every time the coordinates are changed - * to recompute the mesh entity index. The reason for this strange - * mechanism is a performance. - */ __cuda_callable__ - inline - // void setIndex( IndexType entityIndex ); - void + inline GridEntity( const Grid& grid, const Coordinate& coordinates ) + : grid( grid ), coordinates( coordinates ) + { + basis = grid.template getBasis(0); + orientation = 0; refresh(); + } __cuda_callable__ - inline Index - getIndex() const; - - __cuda_callable__ - inline const EntityOrientationType& - getOrientation() const; - - __cuda_callable__ - inline void - setOrientation( const EntityOrientationType& orientation ); - - __cuda_callable__ - inline const EntityBasisType& - getBasis() const; - - __cuda_callable__ - inline void - setBasis( const EntityBasisType& basis ); - - template< int NeighborEntityDimension = getEntityDimension() > - __cuda_callable__ - inline const NeighborEntities< NeighborEntityDimension >& - getNeighborEntities() const; - - __cuda_callable__ - inline bool - isBoundaryEntity() const; - - __cuda_callable__ - inline PointType - getCenter() const; - - __cuda_callable__ - inline const RealType& - getMeasure() const; - - __cuda_callable__ - inline const GridType& - getMesh() const; - -protected: - const GridType& grid; - - IndexType entityIndex; - - CoordinatesType coordinates; - - EntityOrientationType orientation; - - EntityBasisType basis; - - NeighborGridEntitiesStorageType neighborEntitiesStorage; - - //__cuda_callable__ inline - // GridEntity(); - - friend class BoundaryGridEntityChecker< GridEntity >; - - friend class GridEntityCenterGetter< GridEntity >; -}; - -/**** - * Specializations for cells - */ -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -class GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config > -{ -public: - using GridType = Meshes::Grid< Dimension, Real, Device, Index >; - using MeshType = GridType; - using RealType = typename GridType::RealType; - using IndexType = typename GridType::IndexType; - using CoordinatesType = typename GridType::CoordinatesType; - using PointType = typename GridType::PointType; - using ConfigType = Config; - - constexpr static int - getMeshDimension() - { - return GridType::getMeshDimension(); - }; - - constexpr static int - getEntityDimension() + inline GridEntity( const Grid& grid, const Coordinate& coordinates, const Coordinate& basis, const Index orientation ) + : grid( grid ), coordinates( coordinates ), basis( basis ), orientation( orientation ) { - return getMeshDimension(); - }; - - using EntityOrientationType = Containers::StaticVector< getMeshDimension(), IndexType >; - using EntityBasisType = Containers::StaticVector< getMeshDimension(), IndexType >; - using NeighborGridEntitiesStorageType = NeighborGridEntitiesStorage< GridEntity, Config >; - - template< int NeighborEntityDimension = getEntityDimension() > - using NeighborEntities = - NeighborGridEntityGetter< GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, Dimension, Config >, - NeighborEntityDimension >; - - __cuda_callable__ - inline GridEntity( const GridType& grid ); - - __cuda_callable__ - inline GridEntity( const GridType& grid, - const CoordinatesType& coordinates, - const EntityOrientationType& orientation = EntityOrientationType( (Index) 0 ), - const EntityBasisType& basis = EntityBasisType( (Index) 1 ) ); + refresh(); + } __cuda_callable__ - inline const CoordinatesType& + inline const Coordinate& getCoordinates() const; __cuda_callable__ - inline CoordinatesType& + inline Coordinate& getCoordinates(); __cuda_callable__ inline void - setCoordinates( const CoordinatesType& coordinates ); + setCoordinates( const Coordinate& coordinates ); /*** - * Call this method every time the coordinates are changed - * to recompute the mesh entity index. The reason for this strange - * mechanism is a performance. + * @brief - Recalculates entity index. + * + * @warning - Call this method every time the coordinates are changed */ __cuda_callable__ - inline - // void setIndex( IndexType entityIndex ); - void - refresh(); + inline void + refresh(); + /** + * @brief Get the entity index in global grid + */ __cuda_callable__ inline Index getIndex() const; - __cuda_callable__ - inline const EntityOrientationType - getOrientation() const; - - __cuda_callable__ - inline void - setOrientation( const EntityOrientationType& orientation ){}; - - __cuda_callable__ - inline const EntityBasisType - getBasis() const; - - __cuda_callable__ - inline void - setBasis( const EntityBasisType& basis ){}; - - template< int NeighborEntityDimension = Dimension > - __cuda_callable__ - inline const NeighborEntities< NeighborEntityDimension >& - getNeighborEntities() const; - + /** + * @brief Tells, if entity is boundary + */ __cuda_callable__ inline bool - isBoundaryEntity() const; + isBoundary() const; + /** + * @brief Returns, the center of the entity + */ __cuda_callable__ - inline PointType + inline const Point getCenter() const; + /** + * @brief Returns, the measure (volume) of the entity + */ __cuda_callable__ - inline const RealType& + inline Real getMeasure() const; __cuda_callable__ - inline const PointType& - getEntityProportions() const; - - __cuda_callable__ - inline const GridType& + inline const Grid& getMesh() const; -protected: - const GridType& grid; - - IndexType entityIndex; - - CoordinatesType coordinates; - - NeighborGridEntitiesStorageType neighborEntitiesStorage; - - //__cuda_callable__ inline - // GridEntity(); - - friend class BoundaryGridEntityChecker< GridEntity >; - - friend class GridEntityCenterGetter< GridEntity >; -}; - -/**** - * Specialization for vertices - */ -template< int Dimension, typename Real, typename Device, typename Index, typename Config > -class GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config > -{ -public: - using GridType = Meshes::Grid< Dimension, Real, Device, Index >; - using MeshType = GridType; - using RealType = typename GridType::RealType; - using IndexType = typename GridType::IndexType; - using CoordinatesType = typename GridType::CoordinatesType; - using PointType = typename GridType::PointType; - using ConfigType = Config; - - constexpr static int - getMeshDimension() - { - return GridType::getMeshDimension(); - }; - - constexpr static int - getEntityDimension() - { - return 0; - }; - - using EntityOrientationType = Containers::StaticVector< getMeshDimension(), IndexType >; - using EntityBasisType = Containers::StaticVector< getMeshDimension(), IndexType >; - using NeighborGridEntitiesStorageType = NeighborGridEntitiesStorage< GridEntity, Config >; - - template< int NeighborEntityDimension = getEntityDimension() > - using NeighborEntities = NeighborGridEntityGetter< GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >, - NeighborEntityDimension >; - - __cuda_callable__ - inline GridEntity( const GridType& grid ); - - __cuda_callable__ - inline GridEntity( const GridType& grid, - const CoordinatesType& coordinates, - const EntityOrientationType& orientation = EntityOrientationType( (Index) 0 ), - const EntityBasisType& basis = EntityOrientationType( (Index) 0 ) ); - - __cuda_callable__ - inline const CoordinatesType& - getCoordinates() const; - - __cuda_callable__ - inline CoordinatesType& - getCoordinates(); - __cuda_callable__ inline void - setCoordinates( const CoordinatesType& coordinates ); + setBasis( const Coordinate& orientation ); - /*** - * Call this method every time the coordinates are changed - * to recompute the mesh entity index. The reason for this strange - * mechanism is a performance. + /** + * @brief Returns, the entity basis */ __cuda_callable__ - inline - // void setIndex( IndexType entityIndex ); - void - refresh(); + inline Coordinate + getBasis() const; + /** + * @brief Returns, the entity orientation + * + * Orientation is always paired with the basis. In other words, if orientations, entityDimensions and dimensions are equal, + * then bases are equal also. + */ __cuda_callable__ inline Index - getIndex() const; - - __cuda_callable__ - inline const EntityOrientationType getOrientation() const; __cuda_callable__ inline void - setOrientation( const EntityOrientationType& orientation ){}; - - __cuda_callable__ - inline const EntityBasisType - getBasis() const; - - __cuda_callable__ - inline void - setBasis( const EntityBasisType& basis ){}; - - template< int NeighborEntityDimension = getEntityDimension() > - __cuda_callable__ - inline const NeighborEntities< NeighborEntityDimension >& - getNeighborEntities() const; - - __cuda_callable__ - inline bool - isBoundaryEntity() const; - - __cuda_callable__ - inline PointType - getCenter() const; - - // compatibility with meshes, equivalent to getCenter + setOrientation( const Index orientation ); + /** + * @brief Returns, the neighbour entity + * + * @warning - In case, if the parent entity orientation is greater than possible orientations of neighbour entity, + * then orientation is reduces. For example, 3-d cell neighbour of edge with orientaiton 1, will have + * orientation 0 + * @warning - You should refresh index manually + */ + template< int Dimension, int... Steps, std::enable_if_t< sizeof...( Steps ) == Grid::getMeshDimension(), bool > = true > __cuda_callable__ - inline PointType - getPoint() const; - - __cuda_callable__ - inline const RealType - getMeasure() const; + inline GridEntity< Grid, Dimension > + getNeighbourEntity() const; + /** + * @brief Returns, the neighbour entity + * + * @warning - You should refresh index manually + */ + template< int Dimension, + int Orientation, + int... Steps, + std::enable_if_t< sizeof...( Steps ) == Grid::getMeshDimension(), bool > = true > + __cuda_callable__ + inline GridEntity< Grid, Dimension > + getNeighbourEntity() const; + + /** + * @brief Returns, the neighbour entity + * + * @warning - In case, if the parent entity orientation is greater than possible orientations of neighbour entity, + * then orientation is reduces. For example, 3-d cell neighbour of edge with orientaiton 1, will have + * orientation 0 + * @warning - You should refresh index manually + */ + template< int Dimension > __cuda_callable__ - inline PointType - getEntityProportions() const; + inline GridEntity< Grid, Dimension > + getNeighbourEntity( const Coordinate& offset ) const; + /** + * @brief Returns, the neighbour entity + * + * @warning - You should refresh index manually + */ + template< int Dimension, int Orientation > __cuda_callable__ - inline const GridType& - getMesh() const; + inline GridEntity< Grid, Dimension > + getNeighbourEntity( const Coordinate& offset ) const; protected: - const GridType& grid; - - IndexType entityIndex; - - CoordinatesType coordinates; - - NeighborGridEntitiesStorageType neighborEntitiesStorage; - - friend class BoundaryGridEntityChecker< GridEntity >; + const Grid& grid; - friend class GridEntityCenterGetter< GridEntity >; + Index index; + Coordinate coordinates; + Coordinate basis; + Index orientation; }; } // namespace Meshes } // namespace TNL -#include +#include diff --git a/src/TNL/Meshes/GridEntityConfig.h b/src/TNL/Meshes/GridEntityConfig.h deleted file mode 100644 index ba08dffb6a16580c9504026bf204702db98fa763..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/GridEntityConfig.h +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) 2004-2022 Tomáš Oberhuber et al. -// -// This file is part of TNL - Template Numerical Library (https://tnl-project.org/) -// -// SPDX-License-Identifier: MIT - -#pragma once - -namespace TNL { -namespace Meshes { - -enum GridEntityStencilStorage -{ - GridEntityNoStencil = 0, - GridEntityCrossStencil, - GridEntityFullStencil -}; - -template< int storage > -class GridEntityStencilStorageTag -{ -public: - static constexpr int stencilStorage = storage; -}; - -/**** - * This class says what neighbor grid entity indexes shall be pre-computed and stored in the - * grid entity structure. If neighborEntityStorage() returns false, nothing is stored. - * Otherwise, if neighbor entity storage is enabled, we may store either only neighbor entities in a cross like this - * - * X - * X X - * XOX or XXOXX etc. - * X X - * X - * - * or all neighbor entities like this - * - * XXXXX - * XXX XXXXX - * XOX or XXOXX etc. - * XXX XXXXX - * XXXXX - */ - -class GridEntityNoStencilStorage -{ -public: - template< typename GridEntity > - constexpr static bool - neighborEntityStorage( int neighborEntityStorage ) - { - return false; - } - - constexpr static int - getStencilSize() - { - return 0; - } -}; - -template< int stencilSize = 1 > -class GridEntityCrossStencilStorage -{ -public: - template< typename GridEntity > - constexpr static bool - neighborEntityStorage( const int neighborEntityDimension ) - { - return ( GridEntity::getEntityDimension() == GridEntity::GridType::getMeshDimension() - && neighborEntityDimension == GridEntity::GridType::getMeshDimension() ); - } - - constexpr static int - getStencilSize() - { - return stencilSize; - } -}; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/Traverser.h b/src/TNL/Meshes/Traverser.h index f1aa1887c3dbe7199a7e728f052f8329dc9872cd..bd4a44cc0cf36797c7486b10ffba78e32cc5cb2e 100644 --- a/src/TNL/Meshes/Traverser.h +++ b/src/TNL/Meshes/Traverser.h @@ -49,6 +49,3 @@ public: } // namespace TNL #include -#include -#include -#include diff --git a/src/TNL/Meshes/GridDetails/GnuplotWriter.h b/src/TNL/Meshes/Writers/GnuplotWriter.h similarity index 100% rename from src/TNL/Meshes/GridDetails/GnuplotWriter.h rename to src/TNL/Meshes/Writers/GnuplotWriter.h diff --git a/src/Tools/tnl-dicom-reader.cpp b/src/Tools/tnl-dicom-reader.cpp index 179b1a2387bc622054356989144aaed148b8e155..a3a59348c8b869f6abbda39c1b8e1cc31aa15a36 100644 --- a/src/Tools/tnl-dicom-reader.cpp +++ b/src/Tools/tnl-dicom-reader.cpp @@ -51,7 +51,7 @@ bool processDicomSeries( const Config::ParameterContainer& parameters ) if( ! roi.setup( parameters, &dicomSeries ) ) return false; roi.setGrid( grid, verbose ); - vector.setSize( grid.template getEntitiesCount< typename GridType::Cell >() ); + vector.setSize( grid.template getEntitiesCount< 2 >() ); std::cout << "Writing grid to file " << meshFile << std::endl; using Writer = Meshes::Writers::VTIWriter< GridType >; std::ofstream file( meshFile ); diff --git a/src/UnitTests/CMakeLists.txt b/src/UnitTests/CMakeLists.txt index 84b2ceeaae2e37540e3a34618c5c5f19e07e6497..da229a8efa55b0fd55e6644a9052014d0843bc26 100644 --- a/src/UnitTests/CMakeLists.txt +++ b/src/UnitTests/CMakeLists.txt @@ -1,7 +1,7 @@ ADD_SUBDIRECTORY( Algorithms ) ADD_SUBDIRECTORY( Arithmetics ) ADD_SUBDIRECTORY( Containers ) -ADD_SUBDIRECTORY( Functions ) +#ADD_SUBDIRECTORY( Functions ) # Matrices are included from src/CMakeLists.txt ADD_SUBDIRECTORY( Meshes ) ADD_SUBDIRECTORY( MPI ) diff --git a/src/UnitTests/Containers/CMakeLists.txt b/src/UnitTests/Containers/CMakeLists.txt index b2d0994dd9bd3e6105a202afc6ee1d938179310f..cddfb958e4177ea642624378a38bfe1117f4eaf3 100644 --- a/src/UnitTests/Containers/CMakeLists.txt +++ b/src/UnitTests/Containers/CMakeLists.txt @@ -15,9 +15,9 @@ set( CPP_TESTS VectorOfStaticVectorsTest ) set( CUDA_TESTS - ArrayTestCuda + # ArrayTestCuda ArrayViewTestCuda - VectorTestCuda + # VectorTestCuda VectorEvaluateAndReduceTestCuda VectorBinaryOperationsTestCuda VectorUnaryOperationsTestCuda diff --git a/src/UnitTests/Meshes/CMakeLists.txt b/src/UnitTests/Meshes/CMakeLists.txt index c8e71e9552977a7a4898d47a1f224fc2ceceac7a..68e44fa04e5fd9f9b3347f44cb4ca2c2f1531544 100644 --- a/src/UnitTests/Meshes/CMakeLists.txt +++ b/src/UnitTests/Meshes/CMakeLists.txt @@ -1,4 +1,5 @@ ADD_SUBDIRECTORY( DistributedMeshes ) +ADD_SUBDIRECTORY( GridTests ) ADD_EXECUTABLE( EntityTagsTest EntityTagsTest.cpp ) TARGET_COMPILE_OPTIONS( EntityTagsTest PRIVATE ${CXX_TESTS_FLAGS} ) diff --git a/src/UnitTests/Meshes/DistributedMeshes/CMakeLists.txt b/src/UnitTests/Meshes/DistributedMeshes/CMakeLists.txt index 1d7aaadaa46ff057be9a1463d8389494b122847a..d5160f6752cf91714d183c639e838a4ce76551d1 100644 --- a/src/UnitTests/Meshes/DistributedMeshes/CMakeLists.txt +++ b/src/UnitTests/Meshes/DistributedMeshes/CMakeLists.txt @@ -3,10 +3,10 @@ ADD_EXECUTABLE( DirectionsTest DirectionsTest.cpp ) TARGET_LINK_LIBRARIES( DirectionsTest ${TESTS_LIBRARIES} ) target_link_options( DirectionsTest PRIVATE ${TESTS_LINKER_FLAGS} ) -ADD_EXECUTABLE( CopyEntitesTest CopyEntitiesTest.cpp ) - TARGET_COMPILE_OPTIONS( CopyEntitesTest PRIVATE ${CXX_TESTS_FLAGS} ) - TARGET_LINK_LIBRARIES( CopyEntitesTest ${TESTS_LIBRARIES} ) - target_link_options( CopyEntitesTest PRIVATE ${TESTS_LINKER_FLAGS} ) +# ADD_EXECUTABLE( CopyEntitesTest CopyEntitiesTest.cpp ) +# TARGET_COMPILE_OPTIONS( CopyEntitesTest PRIVATE ${CXX_TESTS_FLAGS} ) +# TARGET_LINK_LIBRARIES( CopyEntitesTest ${TESTS_LIBRARIES} ) +# target_link_options( CopyEntitesTest PRIVATE ${TESTS_LINKER_FLAGS} ) # FIXME: DistributedGrid refucktoring #ADD_EXECUTABLE( CutMeshFunctionTest CutMeshFunctionTest.cpp ) @@ -15,79 +15,78 @@ ADD_EXECUTABLE( CopyEntitesTest CopyEntitiesTest.cpp ) # target_link_options( CutMeshFunctionTest PRIVATE ${TESTS_LINKER_FLAGS} ) ADD_TEST( NAME DirectionsTest COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DirectionsTest${CMAKE_EXECUTABLE_SUFFIX} ) -ADD_TEST( NAME CopyEntitesTest COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CopyEntitesTest${CMAKE_EXECUTABLE_SUFFIX} ) +#ADD_TEST( NAME CopyEntitesTest COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CopyEntitesTest${CMAKE_EXECUTABLE_SUFFIX} ) #ADD_TEST( NAME CutMeshFunctionTest COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CutMeshFunctionTest${CMAKE_EXECUTABLE_SUFFIX} ) if( BUILD_MPI ) -ADD_EXECUTABLE( DistributedGridTest_1D DistributedGridTest_1D.cpp ) - TARGET_COMPILE_OPTIONS( DistributedGridTest_1D PRIVATE ${CXX_TESTS_FLAGS} ) - TARGET_LINK_LIBRARIES( DistributedGridTest_1D ${TESTS_LIBRARIES} ) - target_link_options( DistributedGridTest_1D PRIVATE ${TESTS_LINKER_FLAGS} ) - -ADD_EXECUTABLE( DistributedGridTest_2D DistributedGridTest_2D.cpp ) - TARGET_COMPILE_OPTIONS( DistributedGridTest_2D PRIVATE ${CXX_TESTS_FLAGS} ) - TARGET_LINK_LIBRARIES( DistributedGridTest_2D ${TESTS_LIBRARIES} ) - target_link_options( DistributedGridTest_2D PRIVATE ${TESTS_LINKER_FLAGS} ) - -ADD_EXECUTABLE( DistributedGridTest_3D DistributedGridTest_3D.cpp ) - TARGET_COMPILE_OPTIONS( DistributedGridTest_3D PRIVATE ${CXX_TESTS_FLAGS} ) - TARGET_LINK_LIBRARIES( DistributedGridTest_3D ${TESTS_LIBRARIES} ) - target_link_options( DistributedGridTest_3D PRIVATE ${TESTS_LINKER_FLAGS} ) - -ADD_EXECUTABLE( CutDistributedGridTest CutDistributedGridTest.cpp ) - TARGET_COMPILE_OPTIONS( CutDistributedGridTest PRIVATE ${CXX_TESTS_FLAGS} ) - TARGET_LINK_LIBRARIES( CutDistributedGridTest ${TESTS_LIBRARIES} ) - target_link_options( CutDistributedGridTest PRIVATE ${TESTS_LINKER_FLAGS} ) +# ADD_EXECUTABLE( DistributedGridTest_1D DistributedGridTest_1D.cpp ) +# TARGET_COMPILE_OPTIONS( DistributedGridTest_1D PRIVATE ${CXX_TESTS_FLAGS} ) +# TARGET_LINK_LIBRARIES( DistributedGridTest_1D ${TESTS_LIBRARIES} ) +# target_link_options( DistributedGridTest_1D PRIVATE ${TESTS_LINKER_FLAGS} ) + +# ADD_EXECUTABLE( DistributedGridTest_2D DistributedGridTest_2D.cpp ) +# TARGET_COMPILE_OPTIONS( DistributedGridTest_2D PRIVATE ${CXX_TESTS_FLAGS} ) +# TARGET_LINK_LIBRARIES( DistributedGridTest_2D ${TESTS_LIBRARIES} ) +# target_link_options( DistributedGridTest_2D PRIVATE ${TESTS_LINKER_FLAGS} ) + +# ADD_EXECUTABLE( DistributedGridTest_3D DistributedGridTest_3D.cpp ) +# TARGET_COMPILE_OPTIONS( DistributedGridTest_3D PRIVATE ${CXX_TESTS_FLAGS} ) +# TARGET_LINK_LIBRARIES( DistributedGridTest_3D ${TESTS_LIBRARIES} ) +# target_link_options( DistributedGridTest_3D PRIVATE ${TESTS_LINKER_FLAGS} ) + +# ADD_EXECUTABLE( CutDistributedGridTest CutDistributedGridTest.cpp ) +# TARGET_COMPILE_OPTIONS( CutDistributedGridTest PRIVATE ${CXX_TESTS_FLAGS} ) +# TARGET_LINK_LIBRARIES( CutDistributedGridTest ${TESTS_LIBRARIES} ) +# target_link_options( CutDistributedGridTest PRIVATE ${TESTS_LINKER_FLAGS} ) #ADD_EXECUTABLE( CutDistributedMeshFunctionTest CutDistributedMeshFunctionTest.cpp ) # TARGET_COMPILE_OPTIONS( CutDistributedMeshFunctionTest PRIVATE ${CXX_TESTS_FLAGS} ) # TARGET_LINK_LIBRARIES( CutDistributedMeshFunctionTest ${TESTS_LIBRARIES} ) # target_link_options( CutDistributedMeshFunctionTest PRIVATE ${TESTS_LINKER_FLAGS} ) -if( BUILD_CUDA ) - cuda_add_executable( DistributedMeshTest DistributedMeshTest.cu OPTIONS ${CUDA_TESTS_FLAGS}) -else() - add_executable( DistributedMeshTest DistributedMeshTest.cpp ) - target_compile_options( DistributedMeshTest PRIVATE ${CXX_TESTS_FLAGS} ) -endif() -target_link_libraries( DistributedMeshTest ${TESTS_LIBRARIES} ) -target_link_options( DistributedMeshTest PRIVATE ${TESTS_LINKER_FLAGS} ) - +# if( BUILD_CUDA ) +# cuda_add_executable( DistributedMeshTest DistributedMeshTest.cu OPTIONS ${CUDA_TESTS_FLAGS}) +# else() +# add_executable( DistributedMeshTest DistributedMeshTest.cpp ) +# target_compile_options( DistributedMeshTest PRIVATE ${CXX_TESTS_FLAGS} ) +# endif() +# target_link_libraries( DistributedMeshTest ${TESTS_LIBRARIES} ) +# target_link_options( DistributedMeshTest PRIVATE ${TESTS_LINKER_FLAGS} ) # external libraries for tests which use mesh readers find_package( ZLIB ) find_package( tinyxml2 QUIET ) if( ZLIB_FOUND AND tinyxml2_FOUND ) - foreach( target IN ITEMS DistributedGridTest_1D DistributedGridTest_2D DistributedGridTest_3D DistributedMeshTest ) - target_compile_definitions(${target} PUBLIC "-DHAVE_ZLIB") - target_include_directories(${target} PUBLIC ${ZLIB_INCLUDE_DIRS}) - target_link_libraries(${target} ${ZLIB_LIBRARIES}) - - target_compile_definitions(${target} PUBLIC "-DHAVE_TINYXML2") - target_link_libraries(${target} tinyxml2::tinyxml2) - endforeach() + # foreach( target IN ITEMS DistributedGridTest_1D DistributedGridTest_2D DistributedGridTest_3D DistributedMeshTest ) + # target_compile_definitions(${target} PUBLIC "-DHAVE_ZLIB") + # target_include_directories(${target} PUBLIC ${ZLIB_INCLUDE_DIRS}) + # target_link_libraries(${target} ${ZLIB_LIBRARIES}) + + # target_compile_definitions(${target} PUBLIC "-DHAVE_TINYXML2") + # target_link_libraries(${target} tinyxml2::tinyxml2) + # endforeach() endif() -SET (mpi_test_parameters_1d -np 4 -H localhost:4 "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DistributedGridTest_1D${CMAKE_EXECUTABLE_SUFFIX}") -ADD_TEST( NAME DistributedGridTest_1D COMMAND "mpirun" ${mpi_test_parameters_1d}) +# SET (mpi_test_parameters_1d -np 4 -H localhost:4 "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DistributedGridTest_1D${CMAKE_EXECUTABLE_SUFFIX}") +# ADD_TEST( NAME DistributedGridTest_1D COMMAND "mpirun" ${mpi_test_parameters_1d}) -SET (mpi_test_parameters_2d -np 9 -H localhost:9 "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DistributedGridTest_2D${CMAKE_EXECUTABLE_SUFFIX}") -ADD_TEST( NAME DistributedGridTest_2D COMMAND "mpirun" ${mpi_test_parameters_2d}) +# SET (mpi_test_parameters_2d -np 9 -H localhost:9 "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DistributedGridTest_2D${CMAKE_EXECUTABLE_SUFFIX}") +# ADD_TEST( NAME DistributedGridTest_2D COMMAND "mpirun" ${mpi_test_parameters_2d}) -SET (mpi_test_parameters_3d -np 27 -H localhost:27 "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DistributedGridTest_3D${CMAKE_EXECUTABLE_SUFFIX}") -ADD_TEST( NAME DistributedGridTest_3D COMMAND "mpirun" ${mpi_test_parameters_3d}) +# SET (mpi_test_parameters_3d -np 27 -H localhost:27 "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DistributedGridTest_3D${CMAKE_EXECUTABLE_SUFFIX}") +# ADD_TEST( NAME DistributedGridTest_3D COMMAND "mpirun" ${mpi_test_parameters_3d}) -SET (mpi_test_parameters_CutDistributedGridTest -np 12 -H localhost:12 "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CutDistributedGridTest${CMAKE_EXECUTABLE_SUFFIX}") -ADD_TEST( NAME CutDistributedGridTest COMMAND "mpirun" ${mpi_test_parameters_CutDistributedGridTest}) +# SET (mpi_test_parameters_CutDistributedGridTest -np 12 -H localhost:12 "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CutDistributedGridTest${CMAKE_EXECUTABLE_SUFFIX}") +# ADD_TEST( NAME CutDistributedGridTest COMMAND "mpirun" ${mpi_test_parameters_CutDistributedGridTest}) # TODO: Fix #SET (mpi_test_parameters_CutDistributedMeshFunctionTest -np 12 -H localhost:12 "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CutDistributedMeshFunctionTest${CMAKE_EXECUTABLE_SUFFIX}") #ADD_TEST( NAME CutDistributedMeshFunctionTest COMMAND "mpirun" ${mpi_test_parameters_CutDistributedMeshFunctionTest}) -add_test( NAME DistributedMeshTest_2x2 COMMAND mpirun -np 4 -H localhost:4 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DistributedMeshTest${CMAKE_EXECUTABLE_SUFFIX} ) -add_test( NAME DistributedMeshTest_3x3 COMMAND mpirun -np 9 -H localhost:9 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DistributedMeshTest${CMAKE_EXECUTABLE_SUFFIX} ) -add_test( NAME DistributedMeshTest_4x4 COMMAND mpirun -np 16 -H localhost:16 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DistributedMeshTest${CMAKE_EXECUTABLE_SUFFIX} ) +# add_test( NAME DistributedMeshTest_2x2 COMMAND mpirun -np 4 -H localhost:4 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DistributedMeshTest${CMAKE_EXECUTABLE_SUFFIX} ) +# add_test( NAME DistributedMeshTest_3x3 COMMAND mpirun -np 9 -H localhost:9 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DistributedMeshTest${CMAKE_EXECUTABLE_SUFFIX} ) +# add_test( NAME DistributedMeshTest_4x4 COMMAND mpirun -np 16 -H localhost:16 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DistributedMeshTest${CMAKE_EXECUTABLE_SUFFIX} ) endif() diff --git a/src/UnitTests/Meshes/DistributedMeshes/CopyEntitiesTest.cpp b/src/UnitTests/Meshes/DistributedMeshes/CopyEntitiesTest.cpp index 740d5fa5f616687a1b3b6837c7beafc1bcd9a963..c6ad3137fab90816c39a9e92f202a8cf32850371 100644 --- a/src/UnitTests/Meshes/DistributedMeshes/CopyEntitiesTest.cpp +++ b/src/UnitTests/Meshes/DistributedMeshes/CopyEntitiesTest.cpp @@ -2,7 +2,7 @@ #include -#ifdef HAVE_GTEST +#ifdef HAVE_GTEST #include #include "../../Functions/Functions.h" @@ -47,10 +47,10 @@ class TestMovedMeshfunction for(int i=0;i { entity.getCoordinates().x()=i; entity.getCoordinates().y()=j; - entity.getCoordinates().z()=k; + entity.getCoordinates().z()=k; entity.refresh(); EXPECT_EQ( meshFunction.getData()[entity.getIndex()], 100*(k+1)+10*(j+1)+(i+1)) << "Copy entities Failed for: "<< i; - } + } }; }; @@ -109,10 +109,10 @@ class EvalMeshFunction for(int i=0;i { entity.getCoordinates().x()=i; entity.getCoordinates().y()=j; - entity.getCoordinates().z()=k; + entity.getCoordinates().z()=k; entity.refresh(); meshFunction.getData()[entity.getIndex()]=100*k+10*j+i; - } + } }; }; @@ -150,7 +150,7 @@ class TestCopyEntities typedef MeshFunctionView MeshFunctionType; typedef Vector DofType; - typedef typename MeshType::PointType PointType; + typedef typename MeshType::PointType PointType; typedef typename MeshType::CoordinatesType CoordinatesType; typedef typename MeshType::Cell Cell; @@ -163,12 +163,12 @@ class TestCopyEntities gridptr->setDimensions(proportions); gridptr->setDomain(origin,proportions); - + DofType inputDof(gridptr-> template getEntitiesCount< Cell >()); MeshFunctionType inputMeshFunction; - inputMeshFunction.bind(gridptr,inputDof); - + inputMeshFunction.bind(gridptr,inputDof); + EvalMeshFunction :: Eval(inputMeshFunction); @@ -176,14 +176,14 @@ class TestCopyEntities PointType proportionsOut; Pointers::SharedPointer gridOutPtr; - originOut.setValue(0.5); - proportionsOut.setValue(8); + originOut.setValue(0.5); + proportionsOut.setValue(8); gridOutPtr->setDimensions(proportionsOut); gridOutPtr->setDomain(originOut,proportionsOut); DofType outDof(gridOutPtr-> template getEntitiesCount< Cell >()); MeshFunctionType outputMeshFunction; - outputMeshFunction.bind(gridOutPtr,outDof); + outputMeshFunction.bind(gridOutPtr,outDof); CoordinatesType zero; zero.setValue(0); diff --git a/src/UnitTests/Meshes/DistributedMeshes/CutDistributedGridTest.cpp b/src/UnitTests/Meshes/DistributedMeshes/CutDistributedGridTest.cpp index a0f79550ea3a0461a5259091f4b8439eea50399d..408b019c72d90f06899ead2be14fb30ed4e821ea 100644 --- a/src/UnitTests/Meshes/DistributedMeshes/CutDistributedGridTest.cpp +++ b/src/UnitTests/Meshes/DistributedMeshes/CutDistributedGridTest.cpp @@ -1,3 +1,4 @@ + #ifdef HAVE_GTEST #include diff --git a/src/UnitTests/Meshes/DistributedMeshes/DistributedGridTest_3D.cpp b/src/UnitTests/Meshes/DistributedMeshes/DistributedGridTest_3D.cpp index d8225229e4d56d62c38a262c5bf3ca9946ef6edc..5672b868a4e243eea4281122a5962014c9503345 100644 --- a/src/UnitTests/Meshes/DistributedMeshes/DistributedGridTest_3D.cpp +++ b/src/UnitTests/Meshes/DistributedMeshes/DistributedGridTest_3D.cpp @@ -1,3 +1,4 @@ + #ifdef HAVE_GTEST #include diff --git a/src/UnitTests/Meshes/GridTests/Accessors/CMakeLists.txt b/src/UnitTests/Meshes/GridTests/Accessors/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..7a840747a92dd4351f1279e2aff72019fd27bb32 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Accessors/CMakeLists.txt @@ -0,0 +1,7 @@ +include("../CMakeSupport.cmake") + +SET(SOME_ARGS "") + +generate_executables(Grid1DTest.h "Accessors" "../../../main.h" SOME_ARGS) +generate_executables(Grid2DTest.h "Accessors" "../../../main.h" SOME_ARGS) +generate_executables(Grid3DTest.h "Accessors" "../../../main.h" SOME_ARGS) diff --git a/src/UnitTests/Meshes/GridTests/Accessors/Grid1DTest.cpp b/src/UnitTests/Meshes/GridTests/Accessors/Grid1DTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..73c81a9543d24b2200a95b5328128f353eb6da2b --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Accessors/Grid1DTest.cpp @@ -0,0 +1,3 @@ + +#include "Grid1DTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Accessors/Grid1DTest.cu b/src/UnitTests/Meshes/GridTests/Accessors/Grid1DTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..73c81a9543d24b2200a95b5328128f353eb6da2b --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Accessors/Grid1DTest.cu @@ -0,0 +1,3 @@ + +#include "Grid1DTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Accessors/Grid1DTest.h b/src/UnitTests/Meshes/GridTests/Accessors/Grid1DTest.h new file mode 100644 index 0000000000000000000000000000000000000000..a3f616a0442e0d09209da5e83f1d064053ef5ec8 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Accessors/Grid1DTest.h @@ -0,0 +1,117 @@ + +#pragma once + +#ifdef HAVE_GTEST + +#include + +#include + +#include "support.h" + +#ifdef HAVE_CUDA +using Implementations = ::testing::Types< + TNL::Meshes::NDimGrid<1, double, TNL::Devices::Host, int>, + TNL::Meshes::NDimGrid<1, float, TNL::Devices::Host, int>, + TNL::Meshes::NDimGrid<1, double, TNL::Devices::Cuda, int>, + TNL::Meshes::NDimGrid<1, float, TNL::Devices::Cuda, int>, + TNL::Meshes::Grid<1, double, TNL::Devices::Host, int>, + TNL::Meshes::Grid<1, float, TNL::Devices::Host, int>, + TNL::Meshes::Grid<1, double, TNL::Devices::Cuda, int>, + TNL::Meshes::Grid<1, float, TNL::Devices::Cuda, int> +>; +#else +using Implementations = ::testing::Types< + TNL::Meshes::NDimGrid<1, double, TNL::Devices::Host, int>, + TNL::Meshes::NDimGrid<1, float, TNL::Devices::Host, int>, + TNL::Meshes::Grid<1, double, TNL::Devices::Host, int>, + TNL::Meshes::Grid<1, float, TNL::Devices::Host, int> +>; +#endif + +template +class GridTestSuite: public ::testing::Test { + protected: + GridType grid; + +#ifndef HAVE_CUDA + void SetUp() override { + if (std::is_same::value) { + GTEST_SKIP() << "No CUDA available on host. Try to compile with CUDA instead"; + } + } +#endif +}; + +TYPED_TEST_SUITE(GridTestSuite, Implementations); + +TYPED_TEST(GridTestSuite, TestMeshDimensionGetter) { + EXPECT_EQ(TypeParam::getMeshDimension(), 1) << "All grids must have dimension 1"; +} + +TYPED_TEST(GridTestSuite, TestSetWithParameterPack) { + testDimensionSetByIndex(this->grid, 0); + testDimensionSetByIndex(this->grid, 1); + testDimensionSetByIndex(this->grid, 2); + testDimensionSetByIndex(this->grid, 11211); + testDimensionSetByIndex(this->grid, 232121); + testDimensionSetByIndex(this->grid, 434343); +} + +TYPED_TEST(GridTestSuite, TestSetWithCoordinates) { + testDimensionSetByCoordinate(this -> grid, { 0 }); + testDimensionSetByCoordinate(this -> grid, { 1 }); + testDimensionSetByCoordinate(this -> grid, { 2 }); + testDimensionSetByCoordinate(this -> grid, { 10232 }); + testDimensionSetByCoordinate(this -> grid, { 45235423 }); + testDimensionSetByCoordinate(this -> grid, { 3231312 }); +} + +TYPED_TEST(GridTestSuite, TestEntitiesCount) { + // GridType, Edges, Vertices | Edges + testEntitiesCounts(this -> grid, { 0 }, { 0, 0 }); + testEntitiesCounts(this -> grid, { 1 }, { 2, 1 }); + testEntitiesCounts(this -> grid, { 2 }, { 3, 2 }); + + testEntitiesCounts(this -> grid, { 100 }, { 101, 100 }); +} + +TYPED_TEST(GridTestSuite, TestOriginSet) { + testOriginSetByCoordinate(this -> grid, { 0.6 }); + testOriginSetByCoordinate(this -> grid, { 1. }); + testOriginSetByCoordinate(this -> grid, { 2. }); + testOriginSetByCoordinate(this -> grid, { 0.4 }); + testOriginSetByCoordinate(this -> grid, { 3. }); + + testOriginSetByIndex(this -> grid, 0.6); + testOriginSetByIndex(this -> grid, 1.); + testOriginSetByIndex(this -> grid, 2.); + testOriginSetByIndex(this -> grid, 0.4); + testOriginSetByIndex(this -> grid, 3.); +} + +TYPED_TEST(GridTestSuite, TestSpaceStepsGetter) { + const int spaceStepsPowersSize = TypeParam::spaceStepsPowersSize; + + testSpaceStepsSetByCoordinate(this -> grid, spaceStepsPowersSize, { 0.6 }); + testSpaceStepsSetByCoordinate(this -> grid, spaceStepsPowersSize, { 1 }); + testSpaceStepsSetByCoordinate(this -> grid, spaceStepsPowersSize, { 4 }); + testSpaceStepsSetByCoordinate(this -> grid, spaceStepsPowersSize, { 0.1 }); + testSpaceStepsSetByCoordinate(this -> grid, spaceStepsPowersSize, { 4 }); + + testSpaceStepsSetByIndex(this -> grid, spaceStepsPowersSize, 0.6); + testSpaceStepsSetByIndex(this -> grid, spaceStepsPowersSize, 1); + testSpaceStepsSetByIndex(this -> grid, spaceStepsPowersSize, 4); + testSpaceStepsSetByIndex(this -> grid, spaceStepsPowersSize, 0.1); + testSpaceStepsSetByIndex(this -> grid, spaceStepsPowersSize, 4); +} + +TYPED_TEST(GridTestSuite, TestSpaceStepsPowersValues) { + const int spaceStepsPowersSize = TypeParam::spaceStepsPowersSize; + + testSpaceStepsPowerValues(this -> grid, spaceStepsPowersSize, { 0. }); + testSpaceStepsPowerValues(this -> grid, spaceStepsPowersSize, { 1. }); + testSpaceStepsPowerValues(this -> grid, spaceStepsPowersSize, { 2. }); +} + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Accessors/Grid2DTest.cpp b/src/UnitTests/Meshes/GridTests/Accessors/Grid2DTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..63738765a8730089d970d0ee219d88e68e8851bf --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Accessors/Grid2DTest.cpp @@ -0,0 +1,3 @@ + +#include "Grid2DTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Accessors/Grid2DTest.cu b/src/UnitTests/Meshes/GridTests/Accessors/Grid2DTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..63738765a8730089d970d0ee219d88e68e8851bf --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Accessors/Grid2DTest.cu @@ -0,0 +1,3 @@ + +#include "Grid2DTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Accessors/Grid2DTest.h b/src/UnitTests/Meshes/GridTests/Accessors/Grid2DTest.h new file mode 100644 index 0000000000000000000000000000000000000000..b41f8eca79bbbb48a8868f698f81630386e2561e --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Accessors/Grid2DTest.h @@ -0,0 +1,129 @@ + +#pragma once + +#ifdef HAVE_GTEST + +#include + +#include + +#include "support.h" + +#ifdef HAVE_CUDA +using Implementations = ::testing::Types< + TNL::Meshes::NDimGrid<2, double, TNL::Devices::Host, int>, + TNL::Meshes::NDimGrid<2, float, TNL::Devices::Host, int>, + TNL::Meshes::NDimGrid<2, double, TNL::Devices::Cuda, int>, + TNL::Meshes::NDimGrid<2, float, TNL::Devices::Cuda, int>, + TNL::Meshes::Grid<2, double, TNL::Devices::Host, int>, + TNL::Meshes::Grid<2, float, TNL::Devices::Host, int>, + TNL::Meshes::Grid<2, double, TNL::Devices::Cuda, int>, + TNL::Meshes::Grid<2, float, TNL::Devices::Cuda, int> +>; +#else +using Implementations = ::testing::Types< + TNL::Meshes::NDimGrid<2, double, TNL::Devices::Host, int>, + TNL::Meshes::NDimGrid<2, float, TNL::Devices::Host, int>, + TNL::Meshes::Grid<2, double, TNL::Devices::Host, int>, + TNL::Meshes::Grid<2, float, TNL::Devices::Host, int> +>; +#endif + +template +class GridTestSuite: public ::testing::Test { + protected: + GridType grid; + +#ifndef HAVE_CUDA + void SetUp() override { + if (std::is_same::value) { + GTEST_SKIP() << "No CUDA available on host. Try to compile with CUDA instead"; + } + } +#endif +}; + +TYPED_TEST_SUITE(GridTestSuite, Implementations); + +TYPED_TEST(GridTestSuite, TestMeshDimensionGetter) { + EXPECT_EQ(TypeParam::getMeshDimension(), 2) << "All grids must have dimension 2"; +} + +TYPED_TEST(GridTestSuite, TestSetWithParameterPack) { + testDimensionSetByIndex(this -> grid, 0, 0); + testDimensionSetByIndex(this -> grid, 0, 1); + testDimensionSetByIndex(this -> grid, 0, 2); + testDimensionSetByIndex(this -> grid, 1, 11211); + testDimensionSetByIndex(this -> grid, 232121, 21); + testDimensionSetByIndex(this -> grid, 54544, 434343); +} + +TYPED_TEST(GridTestSuite, TestSetWithCoordinates) { + testDimensionSetByCoordinate(this -> grid, { 0, 0 }); + testDimensionSetByCoordinate(this -> grid, { 0, 1 }); + testDimensionSetByCoordinate(this -> grid, { 0, 2 }); + testDimensionSetByCoordinate(this -> grid, { 1, 11211 }); + testDimensionSetByCoordinate(this -> grid, { 232121, 21 }); + testDimensionSetByCoordinate(this -> grid, { 54544, 434343 }); +} + +TYPED_TEST(GridTestSuite, TestEntitiesCount) { + // GridType, Edges, Vertices | Edges + testEntitiesCounts(this -> grid, { 0, 0 }, { 0, 0, 0 }); + + testEntitiesCounts(this -> grid, { 1, 0 }, { 0, 0, 0 }); + testEntitiesCounts(this -> grid, { 0, 1 }, { 0, 0, 0 }); + + testEntitiesCounts(this -> grid, { 1, 1 }, { 4, 4, 1 }); + + testEntitiesCounts(this -> grid, { 2, 1 }, { 6, 7, 2 }); + testEntitiesCounts(this -> grid, { 1, 2 }, { 6, 7, 2 }); + + testEntitiesCounts(this -> grid, { 2, 2 }, { 9, 12, 4 }); + + testEntitiesCounts(this -> grid, { 2, 3 }, { 12, 17, 6 }); + testEntitiesCounts(this -> grid, { 3, 2 }, { 12, 17, 6 }); + + testEntitiesCounts(this -> grid, { 50, 50 }, { 51 * 51, 51 * 50 + 50 * 51, 50 * 50 }); + testEntitiesCounts(this -> grid, { 50, 100 }, { 51 * 101, 51 * 100 + 50 * 101, 50 * 100 }); +} + +TYPED_TEST(GridTestSuite, TestOriginSet) { + testOriginSetByCoordinate(this -> grid, { 0.6, 1.2 }); + testOriginSetByCoordinate(this -> grid, { -1, 23232 }); + testOriginSetByCoordinate(this -> grid, { 100, -12132 }); + testOriginSetByCoordinate(this -> grid, { -100000, 32112 }); + testOriginSetByCoordinate(this -> grid, { 323121, -100312 }); + + testOriginSetByIndex(this -> grid, 0.6, 1.2); + testOriginSetByIndex(this -> grid, -1, 23232); + testOriginSetByIndex(this -> grid, 100, -12132); + testOriginSetByIndex(this -> grid, -100000, 32112); + testOriginSetByIndex(this -> grid, 323121, -100312); +} + +TYPED_TEST(GridTestSuite, TestSpaceStepsGetter) { + const int spaceStepsPowersSize = TypeParam::spaceStepsPowersSize; + + testSpaceStepsSetByCoordinate(this -> grid, spaceStepsPowersSize, { 0.6, 1.2 }); + testSpaceStepsSetByCoordinate(this -> grid, spaceStepsPowersSize, { 1, 2 }); + testSpaceStepsSetByCoordinate(this -> grid, spaceStepsPowersSize, { 4, 3 }); + testSpaceStepsSetByCoordinate(this -> grid, spaceStepsPowersSize, { 0.1, 10 }); + testSpaceStepsSetByCoordinate(this -> grid, spaceStepsPowersSize, { 4, 5 }); + + testSpaceStepsSetByIndex(this -> grid, spaceStepsPowersSize, 0.6, 1.2); + testSpaceStepsSetByIndex(this -> grid, spaceStepsPowersSize, 1, 2); + testSpaceStepsSetByIndex(this -> grid, spaceStepsPowersSize, 4, 3); + testSpaceStepsSetByIndex(this -> grid, spaceStepsPowersSize, 0.1, 10); + testSpaceStepsSetByIndex(this -> grid, spaceStepsPowersSize, 4, 5); +} + +TYPED_TEST(GridTestSuite, TestSpaceStepsPowersValues) { + const int spaceStepsPowersSize = TypeParam::spaceStepsPowersSize; + + testSpaceStepsPowerValues(this -> grid, spaceStepsPowersSize, { 1., 1. }); + testSpaceStepsPowerValues(this -> grid, spaceStepsPowersSize, { 0., 2. }); + testSpaceStepsPowerValues(this -> grid, spaceStepsPowersSize, { 2., 3. }); +} + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Accessors/Grid3DTest.cpp b/src/UnitTests/Meshes/GridTests/Accessors/Grid3DTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4f9bb7cd1339c087bc35ba2c189c0f57087f60e9 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Accessors/Grid3DTest.cpp @@ -0,0 +1,3 @@ + +#include "Grid3DTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Accessors/Grid3DTest.cu b/src/UnitTests/Meshes/GridTests/Accessors/Grid3DTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..4f9bb7cd1339c087bc35ba2c189c0f57087f60e9 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Accessors/Grid3DTest.cu @@ -0,0 +1,3 @@ + +#include "Grid3DTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Accessors/Grid3DTest.h b/src/UnitTests/Meshes/GridTests/Accessors/Grid3DTest.h new file mode 100644 index 0000000000000000000000000000000000000000..8b614a21fc93cdd80ade528b3d078f68b134fcb6 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Accessors/Grid3DTest.h @@ -0,0 +1,156 @@ + +#pragma once + +#ifdef HAVE_GTEST + +#include + +#include + +#include "support.h" + +#ifdef HAVE_CUDA +using Implementations = ::testing::Types< + TNL::Meshes::NDimGrid<3, double, TNL::Devices::Host, int>, + TNL::Meshes::NDimGrid<3, float, TNL::Devices::Host, int>, + TNL::Meshes::NDimGrid<3, double, TNL::Devices::Cuda, int>, + TNL::Meshes::NDimGrid<3, float, TNL::Devices::Cuda, int>, + TNL::Meshes::Grid<3, double, TNL::Devices::Host, int>, + TNL::Meshes::Grid<3, float, TNL::Devices::Host, int>, + TNL::Meshes::Grid<3, double, TNL::Devices::Cuda, int>, + TNL::Meshes::Grid<3, float, TNL::Devices::Cuda, int> +>; +#else +using Implementations = ::testing::Types< + TNL::Meshes::NDimGrid<3, double, TNL::Devices::Host, int>, + TNL::Meshes::NDimGrid<3, float, TNL::Devices::Host, int>, + TNL::Meshes::Grid<3, double, TNL::Devices::Host, int>, + TNL::Meshes::Grid<3, float, TNL::Devices::Host, int> +>; +#endif + +template +class GridTestSuite: public ::testing::Test { + protected: + GridType grid; + +#ifndef HAVE_CUDA + void SetUp() override { + if (std::is_same::value) { + GTEST_SKIP() << "No CUDA available on host. Try to compile with CUDA instead"; + } + } +#endif +}; + +TYPED_TEST_SUITE(GridTestSuite, Implementations); + +TYPED_TEST(GridTestSuite, TestMeshDimensionGetter) { + EXPECT_EQ(TypeParam::getMeshDimension(), 3) << "All grids must have dimension 3"; +} + +TYPED_TEST(GridTestSuite, TestSetWithParameterPack) { + testDimensionSetByIndex(this -> grid, 0, 0, 0); + + testDimensionSetByIndex(this -> grid, 0, 0, 1); + testDimensionSetByIndex(this -> grid, 0, 1, 0); + testDimensionSetByIndex(this -> grid, 1, 0, 0); + + testDimensionSetByIndex(this -> grid, 0, 2, 2); + testDimensionSetByIndex(this -> grid, 2, 0, 2); + testDimensionSetByIndex(this -> grid, 2, 2, 0); + + testDimensionSetByIndex(this -> grid, 3, 3, 3); + + testDimensionSetByIndex(this -> grid, 1, 1, 11211); + testDimensionSetByIndex(this -> grid, 232121, 21, 20); + testDimensionSetByIndex(this -> grid, 54544, 434343, 321341); +} + +TYPED_TEST(GridTestSuite, TestSetWithCoordinates) { + testDimensionSetByCoordinate(this -> grid, { 0, 0, 0 }); + + testDimensionSetByCoordinate(this -> grid, { 0, 0, 1 }); + testDimensionSetByCoordinate(this -> grid, { 0, 1, 0 }); + testDimensionSetByCoordinate(this -> grid, { 1, 0, 0 }); + + testDimensionSetByCoordinate(this -> grid, { 0, 2, 2 }); + testDimensionSetByCoordinate(this -> grid, { 2, 0, 2 }); + testDimensionSetByCoordinate(this -> grid, { 2, 2, 0 }); + + testDimensionSetByCoordinate(this -> grid, { 3, 3, 3 }); + + testDimensionSetByCoordinate(this -> grid, { 1, 1, 11211 }); + testDimensionSetByCoordinate(this -> grid, { 232121, 21, 20 }); + testDimensionSetByCoordinate(this -> grid, { 54544, 434343, 321343 }); +} + +TYPED_TEST(GridTestSuite, TestEntitiesCount) { + // GridType, Edges, Vertices | Edges + testEntitiesCounts(this -> grid, { 0, 0, 0 }, { 0, 0, 0, 0 }); + + testEntitiesCounts(this -> grid, { 1, 0, 0 }, { 0, 0, 0, 0 }); + testEntitiesCounts(this -> grid, { 0, 1, 0 }, { 0, 0, 0, 0 }); + testEntitiesCounts(this -> grid, { 0, 0, 1 }, { 0, 0, 0, 0 }); + + testEntitiesCounts(this -> grid, { 1, 1, 1 }, { 8, 12, 6, 1 }); + + testEntitiesCounts(this -> grid, { 2, 1, 1 }, { 12, 20, 11, 2 }); + testEntitiesCounts(this -> grid, { 1, 2, 1 }, { 12, 20, 11, 2 }); + testEntitiesCounts(this -> grid, { 1, 1, 2 }, { 12, 20, 11, 2 }); + + testEntitiesCounts(this -> grid, { 2, 2, 2 }, { 27, 54, 36, 8 }); + + testEntitiesCounts(this -> grid, { 2, 2, 3 }, { 36, 75, 52, 12 }); + testEntitiesCounts(this -> grid, { 2, 3, 2 }, { 36, 75, 52, 12 }); + testEntitiesCounts(this -> grid, { 3, 2, 2 }, { 36, 75, 52, 12 }); + + testEntitiesCounts(this -> grid, { 50, 50, 50 }, { 51 * 51 * 51, + 51 * 51 * 50 + 51 * 50 * 51 + 50 * 51 * 51, + 51 * 50 * 50 + 50 * 51 * 50 + 50 * 50 * 51, + 50 * 50 * 50 }); + testEntitiesCounts(this -> grid, { 50, 100, 150 }, { 51 * 101 * 151, + 51 * 101 * 150 + 51 * 100 * 151 + 50 * 101 * 151, + 51 * 100 * 150 + 50 * 101 * 150 + 50 * 100 * 151, + 50 * 100 * 150 }); +} + +TYPED_TEST(GridTestSuite, TestOriginSet) { + testOriginSetByCoordinate(this -> grid, { 0.6, 1.2, 1.8 }); + testOriginSetByCoordinate(this -> grid, { -1, 23232, -1 }); + testOriginSetByCoordinate(this -> grid, { 100, -12132, 1231 }); + testOriginSetByCoordinate(this -> grid, { -100000, 32112, 123 }); + testOriginSetByCoordinate(this -> grid, { 323121, -100312, 1341231 }); + + testOriginSetByIndex(this -> grid, 0.6, 1.2, 1.8); + testOriginSetByIndex(this -> grid, -1, 23232, -1); + testOriginSetByIndex(this -> grid, 100, -12132, 1231); + testOriginSetByIndex(this -> grid, -100000, 32112, 123); + testOriginSetByIndex(this -> grid, 323121, -100312, 1341231); +} + +TYPED_TEST(GridTestSuite, TestSpaceStepsGetter) { + const int spaceStepsPowersSize = TypeParam::spaceStepsPowersSize; + + testSpaceStepsSetByCoordinate(this -> grid, spaceStepsPowersSize, { 0.6, 1.2, 1.8 }); + testSpaceStepsSetByCoordinate(this -> grid, spaceStepsPowersSize, { 1, 2, 1 }); + testSpaceStepsSetByCoordinate(this -> grid, spaceStepsPowersSize, { 0.5, 3, 2 }); + testSpaceStepsSetByCoordinate(this -> grid, spaceStepsPowersSize, { 5, 4, 3 }); + testSpaceStepsSetByCoordinate(this -> grid, spaceStepsPowersSize, { 3, 2, 1 }); + + testSpaceStepsSetByIndex(this -> grid, spaceStepsPowersSize, 0.6, 1.2, 1.8); + testSpaceStepsSetByIndex(this -> grid, spaceStepsPowersSize, 1, 2, 1 ); + testSpaceStepsSetByIndex(this -> grid, spaceStepsPowersSize, 0.5, 3, 2 ); + testSpaceStepsSetByIndex(this -> grid, spaceStepsPowersSize, 5, 4, 3); + testSpaceStepsSetByIndex(this -> grid, spaceStepsPowersSize, 3, 2, 1); +} + +TYPED_TEST(GridTestSuite, TestSpaceStepsPowersValues) { + const int spaceStepsPowersSize = TypeParam::spaceStepsPowersSize; + + testSpaceStepsPowerValues(this -> grid, spaceStepsPowersSize, { 1., 1., 1.}); + testSpaceStepsPowerValues(this -> grid, spaceStepsPowersSize, { 0., 2., 4.}); + testSpaceStepsPowerValues(this -> grid, spaceStepsPowersSize, { 1., 2., 3.}); +} + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Accessors/support.h b/src/UnitTests/Meshes/GridTests/Accessors/support.h new file mode 100644 index 0000000000000000000000000000000000000000..8aad3e1f3fe64cefe9621e1cf7a6dbad76bc1e9a --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Accessors/support.h @@ -0,0 +1,452 @@ +#pragma once + +#ifdef HAVE_GTEST +#include +#include + +#include "../CoordinateIterator.h" + +template +class GridAccessorsTestCaseInterface { + public: + template + void verifyDimensionGetters(const Grid& grid, const typename Grid::Coordinate& coordinates) const { FAIL() << "Expect to be specialized"; } + + template + void verifyEntitiesCountGetters(const Grid& grid, const typename Grid::template Container& entitiesCount) const { FAIL() << "Expect to be specialized"; } + + template + void verifyOriginGetters(const Grid& grid, const typename Grid::Point& coordinates) const { FAIL() << "Expect to be specialized"; } + + template + void verifySpaceStepsGetter(const Grid& grid, const typename Grid::Point& spaceSteps) const { FAIL() << "Expect to be specialized"; } + + + template + void verifyDimensionByCoordinateGetter(const Grid& grid, const typename Grid::Coordinate& dimensions) const { FAIL() << "Expect to be specialized"; } + + template + void verifyDimensionByIndexGetter(const Grid& grid, const typename Grid::Coordinate& dimensions) const { FAIL() << "Expect to be specialized"; } + + template + void verifyDimensionByIndiciesGetter(const Grid& grid, const typename Grid::Coordinate& dimensions) const { FAIL() << "Expect to be specialized"; } + + + template + void verifyEntitiesCountByContainerGetter(const Grid& grid, const typename Grid::template Container& entitiesCounts) const { FAIL() << "Expect to be specialized"; } + + template + void verifyEntitiesCountByIndexGetter(const Grid& grid, const typename Grid::template Container& entitiesCounts) const { FAIL() << "Expect to be specialized"; } + + template + void verifyEntitiesCountByIndiciesGetter(const Grid& grid, const typename Grid::template Container& entitiesCounts) const { FAIL() << "Expect to be specialized"; } + + + template + void verifySpaceStepsValues(const Grid& grid, const int spaceStepsSize, const typename Grid::Point& spaceSteps) { + using Real = typename Grid::RealType; + using Coordinate = typename Grid::Coordinate; + + Coordinate start, end; + + for (int i = 0; i < start.getSize(); i++) { + start[i] = -(spaceStepsSize >> 1); + end[i] = (spaceStepsSize >> 1); + } + + CoordinateIterator iterator(start, end); + + do { + auto coordinate = iterator.getCoordinate(); + Real product = 1.; + + for (typename Grid::IndexType i = 0; i < start.getSize(); i++) product *= pow(spaceSteps[i], coordinate[i]); + + if (std::is_same::value) { + EXPECT_FLOAT_EQ(grid.getSpaceStepsProducts(coordinate), product) << "Expect the step size products are the same"; + continue; + } + + if (std::is_same::value) { + EXPECT_DOUBLE_EQ(grid.getSpaceStepsProducts(coordinate), product) << "Expect the step size products are the same"; + continue; + } + + FAIL() << "Unknown type as real was provided for comparison: " << TNL::getType(); + } while (!iterator.next()); + } +}; + + +template +class GridAccessorsTestCase: public GridAccessorsTestCaseInterface {}; + +template<> +class GridAccessorsTestCase: public GridAccessorsTestCaseInterface { + public: + template + void verifyDimensionGetters(const Grid& grid, const typename Grid::Coordinate& dimensions) const { + this->verifyDimensionByCoordinateGetter(grid, dimensions); + this->verifyDimensionByIndexGetter(grid, dimensions); + this->verifyDimensionByIndiciesGetter(grid, dimensions); + } + + template + void verifyEntitiesCountGetters(const Grid& grid, const typename Grid::template Container& entitiesCounts) const { + this->verifyEntitiesCountByContainerGetter(grid, entitiesCounts); + this->verifyEntitiesCountByIndexGetter(grid, entitiesCounts); + this->verifyEntitiesCountByIndiciesGetter(grid, entitiesCounts); + } + + template + void verifyOriginGetter(const Grid& grid, const typename Grid::Point& coordinates) const { + auto result = grid.getOrigin(); + + EXPECT_EQ(coordinates, result) << "Verify, that the origin was correctly set"; + } + + template + void verifySpaceStepsGetter(const Grid& grid, const typename Grid::Point& spaceSteps) const { + auto result = grid.getSpaceSteps(); + + EXPECT_EQ(spaceSteps, result) << "Verify, that space steps were correctly set"; + } + + template + void verifyDimensionByCoordinateGetter(const Grid& grid, const typename Grid::Coordinate& dimensions) const { + auto result = grid.getDimensions(); + + EXPECT_EQ(dimensions, result) << "Verify, that dimension container accessor returns valid dimension"; + } + + template + void verifyDimensionByIndexGetter(const Grid& grid, const typename Grid::Coordinate& dimensions) const { + for (typename Grid::IndexType i = 0; i < dimensions.getSize(); i++) + EXPECT_EQ(grid.getDimension(i), dimensions[i]) << "Verify, that index access is correct"; + } + + template + void verifyDimensionByIndiciesGetter(const Grid& grid, const typename Grid::Coordinate& dimensions) const { + for (typename Grid::IndexType i = 0; i < dimensions.getSize(); i++) { + auto repeatedDimensions = grid.getDimensions(i, i, i, i, i, i, i, i, i, i); + + EXPECT_EQ(repeatedDimensions.getSize(), 10) << "Verify, that all dimension indices are returned"; + + for (typename Grid::IndexType j = 0; j < repeatedDimensions.getSize(); j++) + EXPECT_EQ(repeatedDimensions[j], dimensions[i]) << "Verify, that it is possible to request the same dimension multiple times"; + } + } + + template + void verifyEntitiesCountByContainerGetter(const Grid& grid, const typename Grid::template Container& entitiesCounts) const { + auto result = grid.getEntitiesCounts(); + + EXPECT_EQ(entitiesCounts, result) << "Verify, that returns expected entities counts"; + } + + template + void verifyEntitiesCountByIndexGetter(const Grid& grid, const typename Grid::template Container& entitiesCounts) const { + for (typename Grid::IndexType i = 0; i < entitiesCounts.getSize(); i++) + EXPECT_EQ(grid.getEntitiesCount(i), entitiesCounts[i]) << "Verify, that index access is correct"; + } + + template + void verifyEntitiesCountByIndiciesGetter(const Grid& grid, const typename Grid::template Container& entitiesCounts) const { + for (typename Grid::IndexType i = 0; i < entitiesCounts.getSize(); i++) { + auto repeated = grid.getEntitiesCounts(i, i, i, i, i, i, i, i, i, i); + + EXPECT_EQ(repeated.getSize(), 10) << "Verify, that all dimension indices are returned"; + + for (typename Grid::IndexType j = 0; j < repeated.getSize(); j++) + EXPECT_EQ(repeated[j], entitiesCounts[i]) << "Verify, that it is possible to request the same dimension multiple times"; + } + } +}; +#ifdef HAVE_CUDA + +template<> +class GridAccessorsTestCase: public GridAccessorsTestCaseInterface { + public: + template + void verifyDimensionGetters(const Grid& grid, const typename Grid::Coordinate& dimensions) const { + this->verifyDimensionByCoordinateGetter(grid, dimensions); + this->verifyDimensionByIndexGetter(grid, dimensions); + this->verifyDimensionByIndiciesGetter(grid, dimensions); + } + + template + void verifyEntitiesCountGetters(const Grid& grid, const typename Grid::template Container& entitiesCount) const { + this->verifyEntitiesCountByContainerGetter(grid, entitiesCount); + this->verifyEntitiesCountByIndexGetter(grid, entitiesCount); + this->verifyEntitiesCountByIndiciesGetter(grid, entitiesCount); + } + + template + void verifyOriginGetter(const Grid& grid, const typename Grid::Point& coordinates) const { + auto gridDimension = grid.getMeshDimension(); + + auto update = [=] __device__ (const int index, typename Grid::RealType& reference) mutable { + reference = grid.getOrigin()[index % gridDimension]; + }; + + auto verify = [=] __cuda_callable__ (const int index, const typename Grid::RealType& reference) mutable { + EXPECT_EQ(reference, coordinates[index % gridDimension]); + }; + + this->executeFromDevice(update, verify); + } + + template + void verifySpaceStepsGetter(const Grid& grid, const typename Grid::Point& spaceSteps) const { + auto gridDimension = grid.getMeshDimension(); + + auto update = [=] __device__ (const int index, typename Grid::RealType& reference) mutable { + reference = grid.getSpaceSteps()[index % gridDimension]; + }; + + auto verify = [=] __cuda_callable__ (const int index, const typename Grid::RealType& reference) mutable { + EXPECT_EQ(reference, spaceSteps[index % gridDimension]); + }; + + this->executeFromDevice(update, verify); + } + + template + void executeFromDevice(Updater&& updater, Verifier&& verifier) const { + TNL::Containers::Array container(100 * 100); + + container.forAllElements(updater); + + TNL::Containers::Array result(container); + + result.forAllElements(verifier); + } + + + template + void verifyDimensionByCoordinateGetter(const Grid& grid, const typename Grid::Coordinate& dimensions) const { + auto gridDimension = grid.getMeshDimension(); + + auto update = [=] __device__ (const int index, typename Grid::IndexType& reference) mutable { + reference = grid.getDimensions()[index % gridDimension]; + }; + + auto verify = [=] __cuda_callable__ (const int index, const typename Grid::IndexType& reference) mutable { + EXPECT_EQ(reference, dimensions[index % gridDimension]); + }; + + this->executeFromDevice(update, verify); + } + + template + void verifyDimensionByIndexGetter(const Grid& grid, const typename Grid::Coordinate& dimensions) const { + auto gridDimension = grid.getMeshDimension(); + + auto update = [=] __device__ (const int index, typename Grid::IndexType& reference) mutable { + reference = grid.getDimension(index % gridDimension); + }; + + auto verify = [=] __cuda_callable__ (const int index, const typename Grid::IndexType& reference) mutable { + EXPECT_EQ(reference, dimensions[index % gridDimension]); + }; + + this->executeFromDevice(update, verify); + } + + template + void verifyDimensionByIndiciesGetter(const Grid& grid, const typename Grid::Coordinate& dimensions) const { + auto gridDimension = grid.getMeshDimension(); + + auto update = [=] __device__ (const int index, typename Grid::IndexType& reference) mutable { + reference = grid.getDimensions(index % gridDimension)[0]; + }; + + auto verify = [=] __cuda_callable__ (const int index, const typename Grid::IndexType& reference) mutable { + EXPECT_EQ(reference, dimensions[index % gridDimension]); + }; + + this -> executeFromDevice(update, verify); + } + + + template + void verifyEntitiesCountByContainerGetter(const Grid& grid, const typename Grid::template Container& entitiesCounts) const { + auto size = entitiesCounts.getSize(); + + auto update = [=] __device__ (const int index, typename Grid::IndexType& reference) mutable { + reference = grid.getEntitiesCounts()[index % size]; + }; + + auto verify = [=] __cuda_callable__ (const int index, const typename Grid::IndexType& reference) mutable { + EXPECT_EQ(reference, entitiesCounts[index % size]); + }; + + this -> executeFromDevice(update, verify); + } + + template + void verifyEntitiesCountByIndexGetter(const Grid& grid, const typename Grid::template Container& entitiesCounts) const { + auto size = entitiesCounts.getSize(); + + auto update = [=] __device__ (const int index, typename Grid::IndexType& reference) mutable { + reference = grid.getEntitiesCount(index % size); + }; + + auto verify = [=] __cuda_callable__ (const int index, const typename Grid::IndexType& reference) mutable { + EXPECT_EQ(reference, entitiesCounts[index % size]); + }; + + this -> executeFromDevice(update, verify); + } + + template + void verifyEntitiesCountByIndiciesGetter(const Grid& grid, const typename Grid::template Container& entitiesCounts) const { + auto size = entitiesCounts.getSize(); + + auto update = [=] __device__ (const int index, typename Grid::IndexType& reference) mutable { + reference = grid.getEntitiesCounts(index % size)[0]; + }; + + auto verify = [=] __cuda_callable__ (const int index, const typename Grid::IndexType& reference) mutable { + EXPECT_EQ(reference, entitiesCounts[index % size]); + }; + + this -> executeFromDevice(update, verify); + } +}; + +#endif + +template +std::string makeString(Parameters... parameters) { + std::ostringstream s; + + for (const auto x: { parameters... }) + s << x << ", "; + + return s.str(); +} + +template +void testDimensionSetByIndex(Grid& grid, T... dimensions) { + auto paramString = makeString(dimensions...); + + EXPECT_NO_THROW(grid.setDimensions(dimensions...)) << "Verify, that the set of" << paramString << " doesn't cause assert"; + + SCOPED_TRACE("Test dimension set by index"); + SCOPED_TRACE("Dimension: " + TNL::convertToString(typename Grid::Coordinate(dimensions...))); + SCOPED_TRACE("Grid Dimension: " + TNL::convertToString(grid.getDimensions())); + + GridAccessorsTestCase support; + + support.template verifyDimensionGetters(grid, typename Grid::Coordinate(dimensions...)); +} + +template +void testDimensionSetByCoordinate(Grid& grid, const typename Grid::Coordinate& dimensions) { + EXPECT_NO_THROW(grid.setDimensions(dimensions)) << "Verify, that the set of" << dimensions << " doesn't cause assert"; + + SCOPED_TRACE("Test dimension set by coordinate"); + SCOPED_TRACE("Dimension: " + TNL::convertToString(dimensions)); + SCOPED_TRACE("Grid Dimension: " + TNL::convertToString(grid.getDimensions())); + + GridAccessorsTestCase support; + + support.template verifyDimensionGetters(grid, dimensions); +} + +template +void testEntitiesCounts(Grid& grid, + const typename Grid::Coordinate& dimensions, + const typename Grid::template Container& entitiesCounts) { + EXPECT_NO_THROW(grid.setDimensions(dimensions)) << "Verify, that the set of" << dimensions << " doesn't cause assert"; + + SCOPED_TRACE("Test entities count"); + SCOPED_TRACE("Dimension: " + TNL::convertToString(dimensions)); + SCOPED_TRACE("Grid Entities Counts: " + TNL::convertToString(grid.getEntitiesCounts())); + SCOPED_TRACE("Expected Entities Counts:: " + TNL::convertToString(entitiesCounts)); + + GridAccessorsTestCase support; + + support.template verifyEntitiesCountGetters(grid, entitiesCounts); +} + +template...>, bool> = true> +void testOriginSetByIndex(Grid& grid, T... coordinates) { + auto paramString = makeString(coordinates...); + + EXPECT_NO_THROW(grid.setOrigin(coordinates...)) << "Verify, that the set of" << paramString << " doesn't cause assert"; + + SCOPED_TRACE("Test origin set by coordinate"); + SCOPED_TRACE("Coordinates: " + TNL::convertToString(typename Grid::Coordinate(coordinates...))); + SCOPED_TRACE("Grid origin: " + TNL::convertToString(grid.getOrigin())); + + GridAccessorsTestCase support; + + support.template verifyOriginGetter(grid, typename Grid::Point(coordinates...)); +} + +template +void testOriginSetByCoordinate(Grid& grid, const typename Grid::Point& coordinates) { + EXPECT_NO_THROW(grid.setOrigin(coordinates)) << "Verify, that the set of " << coordinates << " doesn't cause assert"; + + SCOPED_TRACE("Test origin set by index"); + SCOPED_TRACE("Coordinates: " + TNL::convertToString(coordinates)); + SCOPED_TRACE("Grid origin: " + TNL::convertToString(grid.getOrigin())); + + GridAccessorsTestCase support; + + support.template verifyOriginGetter(grid, coordinates); +} + +template +void testSpaceStepsSetByCoordinate(Grid& grid, const int spaceStepsSize, const typename Grid::Point& spaceSteps) { + EXPECT_NO_THROW(grid.setSpaceSteps(spaceSteps)) << "Verify, that the set of " << spaceSteps << " doesn't cause assert"; + + SCOPED_TRACE("Test space steps set by coordinate"); + SCOPED_TRACE("Space steps: " + TNL::convertToString(spaceSteps)); + SCOPED_TRACE("Grid space steps: " + TNL::convertToString(grid.getSpaceSteps())); + + GridAccessorsTestCase support; + + support.template verifySpaceStepsGetter(grid, spaceSteps); + support.template verifySpaceStepsValues(grid, spaceStepsSize, spaceSteps); +} + +template...>, bool> = true> +void testSpaceStepsSetByIndex(Grid& grid, const int spaceStepsSize, T... spaceSteps) { + typename Grid::Point spaceStepsContainer(spaceSteps...); + + EXPECT_NO_THROW(grid.setSpaceSteps(spaceSteps...)) << "Verify, that the set of " << spaceStepsContainer << " doesn't cause assert"; + + SCOPED_TRACE("Test space steps set by index"); + SCOPED_TRACE("Space steps: " + TNL::convertToString(spaceStepsContainer)); + SCOPED_TRACE("Grid space steps: " + TNL::convertToString(grid.getSpaceSteps())); + + GridAccessorsTestCase support; + + support.template verifySpaceStepsGetter(grid, spaceStepsContainer); + support.template verifySpaceStepsValues(grid, spaceStepsSize, spaceStepsContainer); +} + +template +void testSpaceStepsPowerValues(Grid& grid, const int spaceStepsSize, const typename Grid::Point& spaceSteps) { + if (spaceStepsSize <= 0) + GTEST_SKIP() << "Negative space steps sizes are not supported"; + + EXPECT_NO_THROW(grid.setSpaceSteps(spaceSteps)) << "Verify, that the set of " << spaceSteps << " doesn't cause assert"; + + SCOPED_TRACE("Test space steps set by index"); + SCOPED_TRACE("Space steps: " + TNL::convertToString(spaceSteps)); + SCOPED_TRACE("Grid space steps: " + TNL::convertToString(grid.getSpaceSteps())); + + GridAccessorsTestCase support; + + support.template verifySpaceStepsValues(grid, spaceStepsSize, spaceSteps); +} + +#endif diff --git a/src/UnitTests/Meshes/GridTests/CMakeLists.txt b/src/UnitTests/Meshes/GridTests/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..38a299184ed44145a43e11d53b6f30d1e0767dcd --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(Accessors) +add_subdirectory(Traverse) +add_subdirectory(Neighbours) +add_subdirectory(Utils) diff --git a/src/UnitTests/Meshes/GridTests/CMakeSupport.cmake b/src/UnitTests/Meshes/GridTests/CMakeSupport.cmake new file mode 100644 index 0000000000000000000000000000000000000000..e86cfa4c2da08a176d52c9356d9b2645588e6499 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/CMakeSupport.cmake @@ -0,0 +1,43 @@ + +function(generate_executables HEADER SUFFIX MAIN_FILE_PATH ARGS) + get_filename_component(MODULE_NAME ${HEADER} NAME_WE) + + if (${BUILD_CUDA}) + SET(SUPPORT_FILENAME ${MODULE_NAME}.cu) + else() + SET(SUPPORT_FILENAME ${MODULE_NAME}.cpp) + endif() + + SET(TEMPLATE_CONTENT +" +#include \"${HEADER}\" +#include \"${MAIN_FILE_PATH}\" +") + + get_filename_component(ABSOLUTE_SUPPORT_PATH ${SUPPORT_FILENAME} ABSOLUTE) + + if(NOT EXISTS ${ABSOLUTE_SUPPORT_PATH}) + FILE(WRITE ${ABSOLUTE_SUPPORT_PATH} "") + endif() + + FILE(READ ${SUPPORT_FILENAME} SOURCE_FILE_CONTENT) + + if ( NOT "${SOURCE_FILE_CONTENT}" STREQUAL "${TEMPLATE_CONTENT}" ) + FILE(WRITE ${SUPPORT_FILENAME} "${TEMPLATE_CONTENT}") + endif() + + # Targets are separated by suffix provided + set(MODULE_NAME ${MODULE_NAME}_${SUFFIX}) + + if (${BUILD_CUDA}) + CUDA_ADD_EXECUTABLE(${MODULE_NAME} ${HEADER} ${SUPPORT_FILENAME} OPTIONS ${CUDA_TESTS_FLAGS}) + TARGET_LINK_LIBRARIES(${MODULE_NAME} ${TESTS_LIBRARIES}) + else() + ADD_EXECUTABLE(${MODULE_NAME} ${HEADER} ${SUPPORT_FILENAME}) + TARGET_COMPILE_OPTIONS(${MODULE_NAME} PRIVATE ${CXX_TESTS_FLAGS}) + endif() + + TARGET_LINK_LIBRARIES(${MODULE_NAME} ${TESTS_LIBRARIES} ) + target_link_options(${MODULE_NAME} PRIVATE ${TESTS_LINKER_FLAGS}) + ADD_TEST(${MODULE_NAME} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${MODULE_NAME}${CMAKE_EXECUTABLE_SUFFIX} ) +endfunction() diff --git a/src/UnitTests/Meshes/GridTests/CoordinateIterator.h b/src/UnitTests/Meshes/GridTests/CoordinateIterator.h new file mode 100644 index 0000000000000000000000000000000000000000..9604518c9568a1f3fc497847afb5017fff2ac9a0 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/CoordinateIterator.h @@ -0,0 +1,47 @@ + +#pragma once + +#include + +template +class CoordinateIterator { + public: + using Coordinate = TNL::Containers::StaticVector; + + CoordinateIterator(const Coordinate& start, const Coordinate& end): start(start), current(start), end(end) {} + + Coordinate getCoordinate() const { return current; } + + bool next() { + current[0] += 1; + + Index carry = 0; + + bool isEnded = false; + + for (Index i = 0; i < current.getSize(); i++) { + current[i] += carry; + + if (current[i] == end[i]) { + carry = 1; + current[i] = start[i]; + + isEnded = i == current.getSize() - 1; + continue; + } + + break; + } + + return isEnded; + } + + bool canIterate() { + for (Index i = 0; i < current.getSize(); i++) + if (current[i] >= end[i]) return false; + + return true; + } + protected: + Coordinate start, current, end; +}; diff --git a/src/UnitTests/Meshes/GridTests/EntityDataStore.h b/src/UnitTests/Meshes/GridTests/EntityDataStore.h new file mode 100644 index 0000000000000000000000000000000000000000..60fd1db6aac9b238e9aa8b7ccaf566e034862150 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/EntityDataStore.h @@ -0,0 +1,207 @@ + +#pragma once + +#include +#include + +template +struct EntityPrototype { + public: + using Coordinate = TNL::Containers::StaticVector; + using Point = TNL::Containers::StaticVector; + + EntityPrototype(const Coordinate& coordinate, + const Coordinate& basis, + const Index index, + const Index calls, + const Index orientation, + const bool isBoundary, + const Point& center, + const Real& measure): coordinate(coordinate), basis(basis), index(index), calls(calls), orientation(orientation), isBoundary(isBoundary), center(center), measure(measure) {} + + const Coordinate coordinate; + const Coordinate basis; + const Index index; + const Index calls; + const Index orientation; + const bool isBoundary; + const Point center; + const Real measure; + + template + friend std::ostream & operator << (std::ostream & os, const EntityPrototype& entity); +}; + +template +std::ostream & operator << (std::ostream & os, const EntityPrototype& entity) { + os << "Coordinate: " << entity.coordinate << std::endl; + os << "Basis: " << entity.basis << std::endl; + os << "Index: " << entity.index << std::endl; + os << "Calls: " << entity.calls << std::endl; + os << "Orientation: " << entity.orientation << std::endl; + os << "Is boundary: " << entity.isBoundary << std::endl; + os << "Center: " << entity.center << std::endl; + os << "Measure: " << entity.measure << std::endl; + + return os; +} + +template +struct EntityDataStore { + public: + using Coordinate = TNL::Containers::StaticVector; + using Point = TNL::Containers::StaticVector; + + template + using Container = TNL::Containers::Array; + + struct View { + View(typename Container::ViewType calls, + typename Container::ViewType indices, + typename Container::ViewType coordinates, + typename Container::ViewType basis, + typename Container::ViewType orientations, + typename Container::ViewType isBoundary, + typename Container::ViewType center, + typename Container::ViewType measure): calls(calls), indices(indices), coordinates(coordinates), basis(basis), orientations(orientations), isBoundary(isBoundary), center(center), measure(measure) {} + + template + __cuda_callable__ void store(const Entity entity) { + this -> store(entity, entity.getIndex()); + } + + template + __cuda_callable__ void store(const Entity entity, const Index index) { + calls[index] += 1; + indices[index] = entity.getIndex(); + isBoundary[index] = entity.isBoundary(); + orientations[index] = entity.getOrientation(); + measure[index] = entity.getMeasure(); + + auto coordinates = entity.getCoordinates(); + auto basis = entity.getBasis(); + auto center = entity.getCenter(); + + for (Index i = 0; i < GridDimension; i++) { + Index containerIndex = index * GridDimension + i; + + this->coordinates[containerIndex] = coordinates[i]; + this->basis[containerIndex] = basis[i]; + this->center[containerIndex] = center[i]; + } + } + + template + __cuda_callable__ void clear(const Entity entity) { + auto index = entity.getIndex(); + + clear(index); + } + + __cuda_callable__ void clear(const Index index) { + calls[index] = 0; + indices[index] = 0; + isBoundary[index] = 0; + orientations[index] = 0; + measure[index] = 0; + + for (Index i = 0; i < GridDimension; i++) { + Index containerIndex = index * GridDimension + i; + + coordinates[containerIndex] = 0; + basis[containerIndex] = 0; + center[containerIndex] = 0; + } + } + + EntityPrototype getEntity(const Index index) { + Coordinate coordinates, basis; + Point center; + + for (Index i = 0; i < GridDimension; i++) { + Index containerIndex = index * GridDimension + i; + + coordinates[i] = this -> coordinates[containerIndex]; + basis[i] = this -> basis[containerIndex]; + center[i] = this -> center[containerIndex]; + } + + return { coordinates, basis, indices[index], calls[index], orientations[index], isBoundary[index] > 0, center, measure[index] }; + } + + protected: + typename Container::ViewType calls, indices, coordinates, basis, orientations, isBoundary; + typename Container::ViewType center, measure; + }; + + EntityDataStore(const Index& entitiesCount): entitiesCount(entitiesCount) { + calls.resize(entitiesCount); + indices.resize(entitiesCount); + isBoundary.resize(entitiesCount); + orientations.resize(entitiesCount); + + measure.resize(entitiesCount); + + coordinates.resize(GridDimension * entitiesCount); + basis.resize(GridDimension * entitiesCount); + center.resize(GridDimension * entitiesCount); + + calls = 0; + indices = 0; + isBoundary = 0; + orientations = 0; + coordinates = 0; + basis = 0; + center = 0; + measure = 0; + } + + EntityDataStore(const Index& entitiesCount, + const Container& calls, + const Container& indices, + const Container& coordinates, + const Container& basis, + const Container& orientations, + const Container& isBoundary, + const Container& center, + const Container& measure) + : entitiesCount(entitiesCount), + calls(calls), + indices(indices), + coordinates(coordinates), + orientations(orientations), + basis(basis), + isBoundary(isBoundary), + center(center), + measure(measure) {} + + View getView() { + return { calls.getView(), indices.getView(), coordinates.getView(), basis.getView(), orientations.getView(), isBoundary.getView(), center.getView(), measure.getView() }; + } + + template + EntityDataStore move() const { + using NewIndexContainer = TNL::Containers::Array; + using NewRealContainer = TNL::Containers::Array; + + EntityDataStore newContainer(this -> entitiesCount, + NewIndexContainer(this -> calls), + NewIndexContainer(this -> indices), + NewIndexContainer(this -> coordinates), + NewIndexContainer(this -> basis), + NewIndexContainer(this -> orientations), + NewIndexContainer(this -> isBoundary), + NewRealContainer(this -> center), + NewRealContainer(this -> measure)); + + return newContainer; + }; + + typename Container::ViewType getCallsView() { return calls.getView(); } + private: + Index entitiesCount; + + Container calls, indices, coordinates, orientations, basis, isBoundary; + Container center, measure; + +}; diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/1D/CMakeLists.txt b/src/UnitTests/Meshes/GridTests/Neighbours/1D/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..12417750b74566e19d03d2051d04b3e68978a7f0 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/1D/CMakeLists.txt @@ -0,0 +1,6 @@ +include("../../CMakeSupport.cmake") + +SET(SOME_ARGS "") + +generate_executables(Grid1D_0DTest.h "Neighbours" "../../../../main.h" SOME_ARGS) +generate_executables(Grid1D_1DTest.h "Neighbours" "../../../../main.h" SOME_ARGS) diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1DTestSuite.h b/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1DTestSuite.h new file mode 100644 index 0000000000000000000000000000000000000000..a550096c6ff23ca1cafb99cd886980fbbe30a492 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1DTestSuite.h @@ -0,0 +1,76 @@ + +#pragma once + +#ifdef HAVE_GTEST + +#include + +#include + +#include "../support.h" + +using Implementations = ::testing::Types< + TNL::Meshes::Grid<1, double, TNL::Devices::Host, int>, + TNL::Meshes::Grid<1, float, TNL::Devices::Host, int>, + TNL::Meshes::Grid<1, double, TNL::Devices::Cuda, int>, + TNL::Meshes::Grid<1, float, TNL::Devices::Cuda, int> +>; + +template +class GridTestSuite: public ::testing::Test { + protected: + GridType grid; + + std::vector dimensions = { + { 1 }, + { 2 }, + { 4 }, + { 8 }, + { 9 } +#if defined(HAVE_CUDA) || defined(HAVE_OPENMP) + , + { 127 }, + { 1024 } +#endif + }; + +#ifndef HAVE_CUDA + void SetUp() override { + if (std::is_same::value) { + GTEST_SKIP() << "No CUDA available on host. Try to compile with CUDA instead"; + } + } +#endif +}; + +template +void testStaticNeighbourEntityGetterForAllStencils(Grid& grid, const typename Grid::Coordinate& dimension) { + auto loop = [&](const auto i){ + testStaticNeighbourEntityGetter(grid, dimension); + }; + + TNL::Meshes::Templates::DescendingFor<2>::exec(loop); +} + +template +void testStaticNeighbourEntityGetterForAllStencils(Grid& grid, const typename Grid::Coordinate& dimension) { + auto loop = [&](const auto i){ + testStaticNeighbourEntityGetter(grid, dimension); + }; + + TNL::Meshes::Templates::DescendingFor<2>::exec(loop); +} + +template +void testDynamicNeighbourEntityGetterForAllStencils(Grid& grid, const typename Grid::Coordinate& dimension, const int scale = 1) { + for (int i = -1 * scale; i < 1 * scale; i++) + testDynamicNeighbourEntityGetter(grid, dimension, typename Grid::Coordinate(i)); +} + +template +void testDynamicNeighbourEntityGetterForAllStencils(Grid& grid, const typename Grid::Coordinate& dimension, const int scale = 1) { + for (int i = -1 * scale; i < 1 * scale; i++) + testDynamicNeighbourEntityGetter(grid, dimension, typename Grid::Coordinate(i)); +} + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1D_0DTest.cpp b/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1D_0DTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6d0e49360c9891ba628cb6e2ea88c0e29ab653f0 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1D_0DTest.cpp @@ -0,0 +1,3 @@ + +#include "Grid1D_0DTest.h" +#include "../../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1D_0DTest.cu b/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1D_0DTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..6d0e49360c9891ba628cb6e2ea88c0e29ab653f0 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1D_0DTest.cu @@ -0,0 +1,3 @@ + +#include "Grid1D_0DTest.h" +#include "../../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1D_0DTest.h b/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1D_0DTest.h new file mode 100644 index 0000000000000000000000000000000000000000..074eed95a34641cc56caaa3cd6b9e28ac8f684fb --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1D_0DTest.h @@ -0,0 +1,47 @@ + +#pragma once + +#ifdef HAVE_GTEST + +#include "Grid1DTestSuite.h" +#include + +TYPED_TEST_SUITE(GridTestSuite, Implementations); + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_0D_Entity_TO_0D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_0D_Entity_TO_1D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_0D_Entity_TO_0D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_0D_Entity_TO_1D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1D_1DTest.cpp b/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1D_1DTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..42ff530d2f00976dcab98bad76d662194a2ecf2c --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1D_1DTest.cpp @@ -0,0 +1,3 @@ + +#include "Grid1D_1DTest.h" +#include "../../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1D_1DTest.cu b/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1D_1DTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..42ff530d2f00976dcab98bad76d662194a2ecf2c --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1D_1DTest.cu @@ -0,0 +1,3 @@ + +#include "Grid1D_1DTest.h" +#include "../../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1D_1DTest.h b/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1D_1DTest.h new file mode 100644 index 0000000000000000000000000000000000000000..46f049e78ab31e648300c06b342b02b203e64547 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/1D/Grid1D_1DTest.h @@ -0,0 +1,47 @@ + +#pragma once + +#ifdef HAVE_GTEST + +#include "Grid1DTestSuite.h" +#include + +TYPED_TEST_SUITE(GridTestSuite, Implementations); + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_1D_Entity_TO_0D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_1D_Entity_TO_1D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_1D_Entity_TO_0D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_1D_Entity_TO_1D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/2D/CMakeLists.txt b/src/UnitTests/Meshes/GridTests/Neighbours/2D/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..698ae9e0c463f07c8abcdde0d623ffb57fad3be9 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/2D/CMakeLists.txt @@ -0,0 +1,7 @@ +include("../../CMakeSupport.cmake") + +SET(SOME_ARGS "") + +generate_executables(Grid2D_0DTest.h "Neighbours" "../../../../main.h" SOME_ARGS) +generate_executables(Grid2D_1DTest.h "Neighbours" "../../../../main.h" SOME_ARGS) +generate_executables(Grid2D_2DTest.h "Neighbours" "../../../../main.h" SOME_ARGS) diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2DTestSuite.h b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2DTestSuite.h new file mode 100644 index 0000000000000000000000000000000000000000..b764dd50ee09ce6913776ed2aa41a75dae65f80b --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2DTestSuite.h @@ -0,0 +1,88 @@ + +#pragma once + +#ifdef HAVE_GTEST + +#include + +#include + +#include "../support.h" + +using Implementations = ::testing::Types< + TNL::Meshes::Grid<2, double, TNL::Devices::Host, int>, + TNL::Meshes::Grid<2, float, TNL::Devices::Host, int>, + TNL::Meshes::Grid<2, double, TNL::Devices::Cuda, int>, + TNL::Meshes::Grid<2, float, TNL::Devices::Cuda, int> +>; + +template +class GridTestSuite: public ::testing::Test { + protected: + GridType grid; + + std::vector dimensions = { + { 1, 1 }, + { 2, 1 }, + { 1, 2 }, + { 2, 2 }, + { 3, 3 } +#if HAVE_CUDA || HAVE_OPENMP + , + { 100, 1 }, + { 1, 100 }, + { 100, 100 } +#endif + }; + +#ifndef HAVE_CUDA + void SetUp() override { + if (std::is_same::value) { + GTEST_SKIP() << "No CUDA available on host. Try to compile with CUDA instead"; + } + } +#endif +}; + + +template +void testStaticNeighbourEntityGetterForAllStencils(Grid& grid, const typename Grid::Coordinate& dimension) { + auto firstLoop = [&](const auto i){ + auto secondLoop = [&](const auto i, const auto j) { + testStaticNeighbourEntityGetter(grid, dimension); + }; + + TNL::Meshes::Templates::DescendingFor<2>::exec(secondLoop, i); + }; + + TNL::Meshes::Templates::DescendingFor<2>::exec(firstLoop); +} + +template +void testStaticNeighbourEntityGetterForAllStencils(Grid& grid, const typename Grid::Coordinate& dimension) { + auto firstLoop = [&](const auto i){ + auto secondLoop = [&](const auto i, const auto j) { + testStaticNeighbourEntityGetter(grid, dimension); + }; + + TNL::Meshes::Templates::DescendingFor<2>::exec(secondLoop, i); + }; + + TNL::Meshes::Templates::DescendingFor<2>::exec(firstLoop); +} + +template +void testDynamicNeighbourEntityGetterForAllStencils(Grid& grid, const typename Grid::Coordinate& dimension, const int scale = 1) { + for (int i = -1 * scale; i < 1 * scale; i++) + for (int j = -1 * scale; j < 1 * scale; j++) + testDynamicNeighbourEntityGetter(grid, dimension, typename Grid::Coordinate(i, j)); +} + +template +void testDynamicNeighbourEntityGetterForAllStencils(Grid& grid, const typename Grid::Coordinate& dimension, const int scale = 1) { + for (int i = -1 * scale; i < 1 * scale; i++) + for (int j = -1 * scale; j < 1 * scale; j++) + testDynamicNeighbourEntityGetter(grid, dimension, typename Grid::Coordinate(i, j)); +} + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_0DTest.cpp b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_0DTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f64459116d204572fcdc810a6e114a921fd2456f --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_0DTest.cpp @@ -0,0 +1,3 @@ + +#include "Grid2D_0DTest.h" +#include "../../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_0DTest.cu b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_0DTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..f64459116d204572fcdc810a6e114a921fd2456f --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_0DTest.cu @@ -0,0 +1,3 @@ + +#include "Grid2D_0DTest.h" +#include "../../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_0DTest.h b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_0DTest.h new file mode 100644 index 0000000000000000000000000000000000000000..c8b84ef376cc26a19a4eccfead3733cc27ad7f31 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_0DTest.h @@ -0,0 +1,66 @@ + +#pragma once + +#ifdef HAVE_GTEST + +#include "Grid2DTestSuite.h" +#include + +TYPED_TEST_SUITE(GridTestSuite, Implementations); + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_0D_Entity_TO_0D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_0D_Entity_TO_1D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_0D_Entity_TO_2D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_0D_Entity_TO_0D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_0D_Entity_TO_1D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_0D_Entity_TO_2D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_1DTest.cpp b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_1DTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..26c1e25926679ccb7d6959ad501ad46dcba8f07f --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_1DTest.cpp @@ -0,0 +1,3 @@ + +#include "Grid2D_1DTest.h" +#include "../../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_1DTest.cu b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_1DTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..26c1e25926679ccb7d6959ad501ad46dcba8f07f --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_1DTest.cu @@ -0,0 +1,3 @@ + +#include "Grid2D_1DTest.h" +#include "../../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_1DTest.h b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_1DTest.h new file mode 100644 index 0000000000000000000000000000000000000000..ad179b32b87c6da97c12f37fcc037535945e5133 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_1DTest.h @@ -0,0 +1,66 @@ + +#pragma once + +#ifdef HAVE_GTEST + +#include "Grid2DTestSuite.h" +#include + +TYPED_TEST_SUITE(GridTestSuite, Implementations); + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_1D_Entity_TO_0D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_1D_Entity_TO_1D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_1D_Entity_TO_2D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_1D_Entity_TO_0D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_1D_Entity_TO_1D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_1D_Entity_TO_2D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_2DTest.cpp b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_2DTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..230a808feb1bedc1bcd29fd87ddb17f0a7a16019 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_2DTest.cpp @@ -0,0 +1,3 @@ + +#include "Grid2D_2DTest.h" +#include "../../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_2DTest.cu b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_2DTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..230a808feb1bedc1bcd29fd87ddb17f0a7a16019 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_2DTest.cu @@ -0,0 +1,3 @@ + +#include "Grid2D_2DTest.h" +#include "../../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_2DTest.h b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_2DTest.h new file mode 100644 index 0000000000000000000000000000000000000000..850647df873ee35f1d7b5238d3957567e84ac280 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/2D/Grid2D_2DTest.h @@ -0,0 +1,66 @@ + +#pragma once + +#ifdef HAVE_GTEST + +#include "Grid2DTestSuite.h" +#include + +TYPED_TEST_SUITE(GridTestSuite, Implementations); + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_2D_Entity_TO_0D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_2D_Entity_TO_1D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_2D_Entity_TO_2D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_2D_Entity_TO_0D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_2D_Entity_TO_1D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_2D_Entity_TO_2D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/3D/CMakeLists.txt b/src/UnitTests/Meshes/GridTests/Neighbours/3D/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f29499185eb1b4e59c643785691d7a29ee3f3408 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/3D/CMakeLists.txt @@ -0,0 +1,8 @@ +include("../../CMakeSupport.cmake") + +SET(SOME_ARGS "") + +generate_executables(Grid3D_0DTest.h "Neighbours" "../../../../main.h" SOME_ARGS) +generate_executables(Grid3D_1DTest.h "Neighbours" "../../../../main.h" SOME_ARGS) +generate_executables(Grid3D_2DTest.h "Neighbours" "../../../../main.h" SOME_ARGS) +generate_executables(Grid3D_3DTest.h "Neighbours" "../../../../main.h" SOME_ARGS) diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3DTestSuite.h b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3DTestSuite.h new file mode 100644 index 0000000000000000000000000000000000000000..c7688b5cb404fcbfebd48af18f3ad1bcd8bd0015 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3DTestSuite.h @@ -0,0 +1,110 @@ + +#pragma once + +#ifdef HAVE_GTEST + +#include + +#include + +#include "../support.h" + +using Implementations = ::testing::Types< + TNL::Meshes::Grid<3, double, TNL::Devices::Host, int>, + TNL::Meshes::Grid<3, float, TNL::Devices::Host, int>, + TNL::Meshes::Grid<3, double, TNL::Devices::Cuda, int>, + TNL::Meshes::Grid<3, float, TNL::Devices::Cuda, int> +>; + +template +class GridTestSuite: public ::testing::Test { + protected: + GridType grid; + + std::vector dimensions = { + { 1, 1, 1 }, + { 2, 1, 1 }, + { 1, 2, 1 }, + { 1, 1, 2 }, + { 2, 2, 2 }, + { 3, 3, 3 }, + { 10, 1, 1 }, + { 1, 10, 1 }, + { 1, 1, 10 } +#if defined(HAVE_CUDA) || defined(HAVE_OPENMP) + , + { 10, 10, 1 }, + { 1, 10, 10 }, + { 10, 1, 10 }, + { 10, 10, 10 } +#endif + }; + +#ifndef HAVE_CUDA + void SetUp() override { + if (std::is_same::value) { + GTEST_SKIP() << "No CUDA available on host. Try to compile with CUDA instead"; + } + } +#endif +}; + +template +void testStaticNeighbourEntityGetterForAllStencils(Grid& grid, const typename Grid::Coordinate& dimension) { + testStaticNeighbourEntityGetter(grid, dimension); + + // Uncomment, if you want to test for all instances. Note, that it may take a lot of time to compile. + // + // auto firstLoop = [&](const auto i){ + // auto secondLoop = [&](const auto i, const auto j) { + // auto thirdLoop = [&](const auto i, const auto j, const auto k) { + // testStaticNeighbourEntityGetter(grid, dimension); + // }; + + // TNL::Meshes::Templates::DescendingFor<2>::exec(thirdLoop, i, j); + // }; + + // TNL::Meshes::Templates::DescendingFor<2>::exec(secondLoop, i); + // }; + + // TNL::Meshes::Templates::DescendingFor<2>::exec(firstLoop); +} + +template +void testStaticNeighbourEntityGetterForAllStencils(Grid& grid, const typename Grid::Coordinate& dimension) { + testStaticNeighbourEntityGetter(grid, dimension); + + // Uncomment, if you want to test for all instances. Note, that it may take a lot of time to compile. + // + // auto firstLoop = [&](const auto i){ + // auto secondLoop = [&](const auto i, const auto j) { + // auto thirdLoop = [&](const auto i, const auto j, const auto k) { + // testStaticNeighbourEntityGetter(grid, dimension); + // }; + + // TNL::Meshes::Templates::DescendingFor<2>::exec(thirdLoop, i, j); + // }; + + // TNL::Meshes::Templates::DescendingFor<2>::exec(secondLoop, i); + // }; + + // TNL::Meshes::Templates::DescendingFor<2>::exec(firstLoop); +} + +template +void testDynamicNeighbourEntityGetterForAllStencils(Grid& grid, const typename Grid::Coordinate& dimension, const int scale = 1) { + for (int i = -1 * scale; i < 1 * scale; i++) + for (int j = -1 * scale; j < 1 * scale; j++) + for (int k = -1 * scale; k < 1 * scale; k++) + testDynamicNeighbourEntityGetter(grid, dimension, typename Grid::Coordinate(i, j, k)); +} + +template +void testDynamicNeighbourEntityGetterForAllStencils(Grid& grid, const typename Grid::Coordinate& dimension, const int scale = 1) { + for (int i = -1 * scale; i < 1 * scale; i++) + for (int j = -1 * scale; j < 1 * scale; j++) + for (int k = -1 * scale; k < 1 * scale; k++) + testDynamicNeighbourEntityGetter(grid, dimension, typename Grid::Coordinate(i, j, k)); +} + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_0DTest.cpp b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_0DTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7b9753a2246c6052c7f3f0a2a76643b30aa0fa7a --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_0DTest.cpp @@ -0,0 +1,3 @@ + +#include "Grid3D_0DTest.h" +#include "../../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_0DTest.cu b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_0DTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..7b9753a2246c6052c7f3f0a2a76643b30aa0fa7a --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_0DTest.cu @@ -0,0 +1,3 @@ + +#include "Grid3D_0DTest.h" +#include "../../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_0DTest.h b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_0DTest.h new file mode 100644 index 0000000000000000000000000000000000000000..27a722396b46fd2f41b70c5deb6362de4e5aced3 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_0DTest.h @@ -0,0 +1,87 @@ + +#pragma once + +#ifdef HAVE_GTEST + +#include "Grid3DTestSuite.h" +#include + +TYPED_TEST_SUITE(GridTestSuite, Implementations); + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_0D_Entity_TO_0D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_0D_Entity_TO_1D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_0D_Entity_TO_2D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_0D_Entity_TO_3D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_0D_Entity_TO_0D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_0D_Entity_TO_1D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_0D_Entity_TO_2D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_0D_Entity_TO_3D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_1DTest.cpp b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_1DTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5d5ac9984180cd9533c8ff470a6ab8e2cc839e08 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_1DTest.cpp @@ -0,0 +1,3 @@ + +#include "Grid3D_1DTest.h" +#include "../../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_1DTest.cu b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_1DTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..5d5ac9984180cd9533c8ff470a6ab8e2cc839e08 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_1DTest.cu @@ -0,0 +1,3 @@ + +#include "Grid3D_1DTest.h" +#include "../../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_1DTest.h b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_1DTest.h new file mode 100644 index 0000000000000000000000000000000000000000..d7a090d1273aca610ab3174703ec144514b831cc --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_1DTest.h @@ -0,0 +1,87 @@ + +#pragma once + +#ifdef HAVE_GTEST + +#include "Grid3DTestSuite.h" +#include + +TYPED_TEST_SUITE(GridTestSuite, Implementations); + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_1D_Entity_TO_0D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_1D_Entity_TO_1D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_1D_Entity_TO_2D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_1D_Entity_TO_3D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_1D_Entity_TO_0D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_1D_Entity_TO_1D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_1D_Entity_TO_2D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_1D_Entity_TO_3D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_2DTest.cpp b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_2DTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac02aaace95343d8019143a19018529be6c606ff --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_2DTest.cpp @@ -0,0 +1,3 @@ + +#include "Grid3D_2DTest.h" +#include "../../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_2DTest.cu b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_2DTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..ac02aaace95343d8019143a19018529be6c606ff --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_2DTest.cu @@ -0,0 +1,3 @@ + +#include "Grid3D_2DTest.h" +#include "../../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_2DTest.h b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_2DTest.h new file mode 100644 index 0000000000000000000000000000000000000000..bd244b19fbc5734ccae5c5defc07b2c5f51779bd --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_2DTest.h @@ -0,0 +1,88 @@ + +#pragma once + +#ifdef HAVE_GTEST + +#include "Grid3DTestSuite.h" +#include + +TYPED_TEST_SUITE(GridTestSuite, Implementations); + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_2D_Entity_TO_0D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_2D_Entity_TO_1D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_2D_Entity_TO_2D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_2D_Entity_TO_3D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_2D_Entity_TO_0D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientationation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_2D_Entity_TO_1D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientationation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_2D_Entity_TO_2D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_2D_Entity_TO_3D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_3DTest.cpp b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_3DTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3cf7b3a449c4ce8c77c895c672267582444ab49d --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_3DTest.cpp @@ -0,0 +1,3 @@ + +#include "Grid3D_3DTest.h" +#include "../../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_3DTest.cu b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_3DTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..3cf7b3a449c4ce8c77c895c672267582444ab49d --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_3DTest.cu @@ -0,0 +1,3 @@ + +#include "Grid3D_3DTest.h" +#include "../../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_3DTest.h b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_3DTest.h new file mode 100644 index 0000000000000000000000000000000000000000..ef0719b336c2717d20521402de2a9b12285acf77 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/3D/Grid3D_3DTest.h @@ -0,0 +1,87 @@ + +#pragma once + +#ifdef HAVE_GTEST + +#include "Grid3DTestSuite.h" +#include + +TYPED_TEST_SUITE(GridTestSuite, Implementations); + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_3D_Entity_TO_0D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Offseett + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_3D_Entity_TO_1D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_3D_Entity_TO_2D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_3D_Entity_TO_3D_By_StaticGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testStaticNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_3D_Entity_TO_0D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_3D_Entity_TO_1D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_3D_Entity_TO_2D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +TYPED_TEST(GridTestSuite, TestNeighbour_OF_3D_Entity_TO_3D_By_DynamicGetter) { + // EntityDimension | NeighbourEntityDimension | Orientation + for (const auto& dimension : this->dimensions) { + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + testDynamicNeighbourEntityGetterForAllStencils(this -> grid, dimension); + } +} + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/CMakeLists.txt b/src/UnitTests/Meshes/GridTests/Neighbours/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..bb8f4c36de7f734c161b83be5289e53b57477aee --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(1D) +add_subdirectory(2D) +add_subdirectory(3D) diff --git a/src/UnitTests/Meshes/GridTests/Neighbours/support.h b/src/UnitTests/Meshes/GridTests/Neighbours/support.h new file mode 100644 index 0000000000000000000000000000000000000000..2309141e38970f219bcc14507c392ad19793b80e --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Neighbours/support.h @@ -0,0 +1,286 @@ +#pragma once + +#ifdef HAVE_GTEST + +#include "../EntityDataStore.h" +#include "../CoordinateIterator.h" +#include + +template +class NeighbourGridEntityGetterTestCase { + public: + using Index = typename Grid::IndexType; + using Real = typename Grid::RealType; + using Coordinate = typename Grid::Coordinate; + using DataStore = EntityDataStore; + using HostDataStore = EntityDataStore; + + template + void storeByStaticAccessor(const Grid& grid, DataStore& store) { + SCOPED_TRACE("Store using static accessor without"); + + constexpr int neighbourOrientationsCount = Grid::getEntityOrientationsCount(NeighbourEntityDimension); + + auto view = store.getView(); + auto update = [=] __cuda_callable__ (const typename Grid::template EntityType& entity) mutable { + int neighbourEntityOrientation = TNL::min(entity.getOrientation(), neighbourOrientationsCount - 1); + Coordinate alignedCoordinate = entity.getCoordinates() + Coordinate(Steps...); + Coordinate boundary = grid.getDimensions() + grid.template getBasis(neighbourEntityOrientation); + + if (alignedCoordinate >= 0 && alignedCoordinate < boundary) { + auto neighbour = entity.template getNeighbourEntity(); + + neighbour.refresh(); + + view.store(neighbour, entity.getIndex()); + } + }; + + grid.template forAll(update); + } + + template + void storeByStaticAccessorWithOrientation(const Grid& grid, DataStore& store) { + SCOPED_TRACE("Store using static accessor with orientation"); + + auto view = store.getView(); + auto update = [=] __cuda_callable__ (const typename Grid::template EntityType& entity) mutable { + Coordinate alignedCoordinate = entity.getCoordinates() + Coordinate(Steps...); + Coordinate boundary = grid.getDimensions() + grid.template getBasis(NeighbourEntityOrientation); + + if ((alignedCoordinate >= 0 && alignedCoordinate < boundary)) { + auto neighbour = entity.template getNeighbourEntity(); + + neighbour.refresh(); + + view.store(neighbour, entity.getIndex()); + } + }; + + grid.template forAll(update); + } + + void storeByDynamicAccessor(const Grid& grid, DataStore& store, const Coordinate& offset) { + SCOPED_TRACE("Store using dynamic accessor without orientation"); + + constexpr int neighbourOrientationsCount = Grid::getEntityOrientationsCount(NeighbourEntityDimension); + + auto view = store.getView(); + auto update = [=] __cuda_callable__(const typename Grid::template EntityType& entity) mutable { + int neighbourEntityOrientation = TNL::min(entity.getOrientation(), neighbourOrientationsCount - 1); + Coordinate alignedCoordinate = entity.getCoordinates() + offset; + Coordinate boundary = grid.getDimensions() + grid.template getBasis(neighbourEntityOrientation); + + if ((alignedCoordinate >= 0 && alignedCoordinate < boundary)) { + auto neighbour = entity.template getNeighbourEntity(offset); + + neighbour.refresh(); + + view.store(neighbour, entity.getIndex()); + } + }; + + grid.template forAll(update); + } + + template + void storeByDynamicAccessorWithOrientation(const Grid& grid, DataStore& store, const Coordinate& offset) { + SCOPED_TRACE("Store using dynamic accessor with orientation"); + + auto view = store.getView(); + auto update = [=] __cuda_callable__(const typename Grid::template EntityType& entity) mutable { + Coordinate alignedCoordinate = entity.getCoordinates() + offset; + Coordinate boundary = grid.getDimensions() + grid.template getBasis(NeighbourEntityOrientation); + + if ((alignedCoordinate >= 0 && alignedCoordinate < boundary)) { + auto neighbour = entity.template getNeighbourEntity(offset); + + neighbour.refresh(); + + view.store(neighbour, entity.getIndex()); + } + }; + + grid.template forAll(update); + } + + void verify(const Grid& grid, DataStore& store, const Coordinate& offset, const int entityOrientation) { + auto hostStore = store.template move(); + auto hostStoreView = hostStore.getView(); + + constexpr int orientationsCount = Grid::getEntityOrientationsCount(EntityDimension); + constexpr int neighbourEntityOrientationsCount = Grid::getEntityOrientationsCount(NeighbourEntityDimension); + + auto verify = [&](const auto orientation) { + GridCoordinateIterator iterator(grid.getDimensions()); + + if (!iterator.canIterate()) { + SCOPED_TRACE("Skip iteration"); + EXPECT_EQ(hostStore.getCallsView().getSize(), 0) << "Expect, that we can't iterate, when grid is empty"; + return; + } + + int neighbourEntityOrientation = 0; + + if (entityOrientation == -1) { + int tmp = orientation; + neighbourEntityOrientation = TNL::min(tmp, neighbourEntityOrientationsCount - 1); + } else { + neighbourEntityOrientation = entityOrientation; + } + + const Coordinate neighbourEntityBasis = grid.template getBasis(neighbourEntityOrientation); + + do { + Index parentEntityIndex = iterator.getIndex(grid); + auto neighbourEntity = hostStoreView.getEntity(parentEntityIndex); + + Coordinate alignedCoordinate = iterator.getCoordinate() + offset; + + // Unable to get entity out of bounds + bool expectCall = alignedCoordinate >= Coordinate(0) && alignedCoordinate < grid.getDimensions() + neighbourEntityBasis; + + EXPECT_EQ(expectCall, neighbourEntity.calls == 1) << + "Expect, that the parent entity was called"; + EXPECT_EQ(expectCall ? alignedCoordinate : Coordinate(0), neighbourEntity.coordinate) << + "Expect, that the coordinate is updated"; + EXPECT_EQ(expectCall ? neighbourEntityBasis : Coordinate(0), neighbourEntity.basis) << + "Expect, that the basis is updated"; + EXPECT_EQ(expectCall ? neighbourEntityOrientation : 0, neighbourEntity.orientation) << + "Expect, that the parent entity was called"; + } while (!iterator.next()); + }; + + TNL::Meshes::Templates::DescendingFor::exec(verify); + } + protected: + template + class GridCoordinateIterator: public CoordinateIterator { + public: + using Base = CoordinateIterator; + using EntityBasis = TNL::Meshes::BasisGetter; + + GridCoordinateIterator(const Coordinate& end): Base(Coordinate(0), end + EntityBasis::template getBasis()) { + for (Index i = 0; i < this -> current.getSize(); i++) { + this -> start[i] = 0; + this -> current[i] = 0; + } + } + + Coordinate getCoordinate() const { + return this -> current; + } + + Index getIndex(const Grid& grid) const { + Index result = 0; + + for (Index i = 0; i < this->current.getSize(); i++) { + if (i == 0) { + result += this->current[i]; + } else { + Index offset = 1; + + for (Index j = 0; j < i; j++) offset *= this->end[j]; + + result += this->current[i] * offset; + } + } + + for (Index i = 0; i < Orientation; i++) result += grid.getOrientedEntitiesCount(EntityDimension, i); + + return result; + } + }; +}; + +template = true> +void testStaticNeighbourEntityGetter(Grid& grid, const typename Grid::Coordinate& dimensions) { + SCOPED_TRACE("Grid Dimension: " + TNL::convertToString(Grid::getMeshDimension())); + SCOPED_TRACE("Entity Dimension: " + TNL::convertToString(EntityDimension)); + SCOPED_TRACE("Neighbour Entity Dimension: " + TNL::convertToString(NeighbourEntityDimension)); + SCOPED_TRACE("Dimension: " + TNL::convertToString(dimensions)); + + EXPECT_NO_THROW(grid.setDimensions(dimensions)) << "Verify, that the set of" << dimensions << " doesn't cause assert"; + + using Test = NeighbourGridEntityGetterTestCase; + + Test test; + typename Test::DataStore store(grid.getEntitiesCount(EntityDimension)); + + test.template storeByStaticAccessor(grid, store); + test.verify(grid, store, typename Grid::Coordinate(Steps...), -1); +} + +template = true> +void testStaticNeighbourEntityGetter(Grid& grid, const typename Grid::Coordinate& dimensions) { + SCOPED_TRACE("Grid Dimension: " + TNL::convertToString(Grid::getMeshDimension())); + SCOPED_TRACE("Entity Dimension: " + TNL::convertToString(EntityDimension)); + SCOPED_TRACE("Neighbour Entity Dimension: " + TNL::convertToString(NeighbourEntityDimension)); + SCOPED_TRACE("Neighbour Entity Orientation: " + TNL::convertToString(NeighbourEntityOrientation)); + SCOPED_TRACE("Dimension: " + TNL::convertToString(dimensions)); + + EXPECT_NO_THROW(grid.setDimensions(dimensions)) << "Verify, that the set of" << dimensions << " doesn't cause assert"; + + using Test = NeighbourGridEntityGetterTestCase; + + Test test; + typename Test::DataStore store(grid.getEntitiesCount(EntityDimension)); + + test.template storeByStaticAccessorWithOrientation(grid, store); + test.verify(grid, store, typename Grid::Coordinate(Steps...), NeighbourEntityOrientation); +} + + +template +void testDynamicNeighbourEntityGetter(Grid& grid, const typename Grid::Coordinate& dimensions, const typename Grid::Coordinate& offset) { + SCOPED_TRACE("Grid Dimension: " + TNL::convertToString(Grid::getMeshDimension())); + SCOPED_TRACE("Entity Dimension: " + TNL::convertToString(EntityDimension)); + SCOPED_TRACE("Neighbour Entity Dimension: " + TNL::convertToString(NeighbourEntityDimension)); + SCOPED_TRACE("Dimension: " + TNL::convertToString(dimensions)); + + EXPECT_NO_THROW(grid.setDimensions(dimensions)) << "Verify, that the set of" << dimensions << " doesn't cause assert"; + + using Test = NeighbourGridEntityGetterTestCase; + + Test test; + typename Test::DataStore store(grid.getEntitiesCount(EntityDimension)); + + test.storeByDynamicAccessor(grid, store, offset); + test.verify(grid, store, offset, -1); +} + +template +void testDynamicNeighbourEntityGetter(Grid& grid, const typename Grid::Coordinate& dimensions, const typename Grid::Coordinate& offset) { + SCOPED_TRACE("Grid Dimension: " + TNL::convertToString(Grid::getMeshDimension())); + SCOPED_TRACE("Entity Dimension: " + TNL::convertToString(EntityDimension)); + SCOPED_TRACE("Neighbour Entity Dimension: " + TNL::convertToString(NeighbourEntityDimension)); + SCOPED_TRACE("Neighbour Entity Orientation: " + TNL::convertToString(NeighbourEntityOrientation)); + SCOPED_TRACE("Dimension: " + TNL::convertToString(dimensions)); + + EXPECT_NO_THROW(grid.setDimensions(dimensions)) << "Verify, that the set of" << dimensions << " doesn't cause assert"; + + using Test = NeighbourGridEntityGetterTestCase; + + Test test; + typename Test::DataStore store(grid.getEntitiesCount(EntityDimension)); + + test.template storeByDynamicAccessorWithOrientation(grid, store, offset); + test.verify(grid, store, offset, NeighbourEntityOrientation); +} + + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Traverse/CMakeLists.txt b/src/UnitTests/Meshes/GridTests/Traverse/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..9bb78a2ab135dbaee02d3f5f72c5fcce2f47d0a3 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Traverse/CMakeLists.txt @@ -0,0 +1,8 @@ +include("../CMakeSupport.cmake") + +SET(SOME_ARGS "") + +generate_executables(Grid1DTest.h "Traversers" "../../../main.h" SOME_ARGS) +generate_executables(Grid2DTest.h "Traversers" "../../../main.h" SOME_ARGS) +generate_executables(Grid3DTest.h "Traversers" "../../../main.h" SOME_ARGS) +generate_executables(GridCoordinateIteratorTest.h "Traversers" "../../../main.h" SOME_ARGS) \ No newline at end of file diff --git a/src/UnitTests/Meshes/GridTests/Traverse/Grid1DTest.cpp b/src/UnitTests/Meshes/GridTests/Traverse/Grid1DTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..73c81a9543d24b2200a95b5328128f353eb6da2b --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Traverse/Grid1DTest.cpp @@ -0,0 +1,3 @@ + +#include "Grid1DTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Traverse/Grid1DTest.cu b/src/UnitTests/Meshes/GridTests/Traverse/Grid1DTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..73c81a9543d24b2200a95b5328128f353eb6da2b --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Traverse/Grid1DTest.cu @@ -0,0 +1,3 @@ + +#include "Grid1DTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Traverse/Grid1DTest.h b/src/UnitTests/Meshes/GridTests/Traverse/Grid1DTest.h new file mode 100644 index 0000000000000000000000000000000000000000..1cd6aa7e6c5d025fe8783aec4d22412aad6e158f --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Traverse/Grid1DTest.h @@ -0,0 +1,136 @@ + +#pragma once + +#ifdef HAVE_GTEST + +#include + +#include + +#include "support.h" + +#ifdef HAVE_CUDA +using Implementations = ::testing::Types< + TNL::Meshes::Grid<1, double, TNL::Devices::Host, int>, + TNL::Meshes::Grid<1, float, TNL::Devices::Host, int>, + TNL::Meshes::Grid<1, double, TNL::Devices::Cuda, int>, + TNL::Meshes::Grid<1, float, TNL::Devices::Cuda, int> +>; +#else +using Implementations = ::testing::Types< + TNL::Meshes::Grid<1, double, TNL::Devices::Host, int>, + TNL::Meshes::Grid<1, float, TNL::Devices::Host, int> +>; +#endif + +template +class GridTestSuite: public ::testing::Test { + protected: + GridType grid; + + std::vector dimensions = { + { 1 }, + { 2 }, + { 4 }, + { 8 }, + { 9 } +#if defined(HAVE_CUDA) || defined(HAVE_OPENMP) + , + { 127 }, + { 1024 } +#endif + }; + + std::vector origins = { + { 1 }, + { -10 }, + { 0.1 }, + { 1 }, + { 1 }, + { -2 } + }; + + std::vector spaceSteps = { + { 0.1 }, + { 2 }, + { 0.1 }, + { 1 }, + { 12 } + }; + +#ifndef HAVE_CUDA + void SetUp() override { + if (std::is_same::value) { + GTEST_SKIP() << "No CUDA available on host. Try to compile with CUDA instead"; + } + } +#endif +}; + +TYPED_TEST_SUITE(GridTestSuite, Implementations); + +TYPED_TEST(GridTestSuite, TestForAllTraverse_0D_Entity) { + for (const auto& dimension: this->dimensions) + for (const auto& origin: this->origins) + for (const auto& spaceStep: this->spaceSteps) + testForAllTraverse(this->grid, dimension, origin, spaceStep); +} + +TYPED_TEST(GridTestSuite, TestForAllTraverse_1D_Entity) { + for (const auto& dimension: this->dimensions) + for (const auto& origin: this->origins) + for (const auto& spaceStep: this->spaceSteps) + testForAllTraverse(this->grid, dimension, origin, spaceStep); +} + +TYPED_TEST(GridTestSuite, TestForInteriorTraverse_0D_Entity) { + for (const auto& dimension : this -> dimensions) + testForInteriorTraverse(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestForInteriorTraverse_1D_Entity) { + for (const auto& dimension : this -> dimensions) + testForInteriorTraverse(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestForBoundaryTraverse_0D_Entity) { + for (const auto& dimension : this -> dimensions) + testForBoundaryTraverse(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestForBoundaryTraverse_1D_Entity) { + for (const auto& dimension : this -> dimensions) + testForBoundaryTraverse(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestBoundaryUnionInteriorEqualAllProperty_0D_Entity) { + for (const auto& dimension : this -> dimensions) + testBoundaryUnionInteriorEqualAllProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestBoundaryUnionInteriorEqualAllProperty_1D_Entity) { + for (const auto& dimension : this -> dimensions) + testBoundaryUnionInteriorEqualAllProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestAllMinusBoundaryEqualInteriorProperty_0D_Entity) { + for (const auto& dimension : this -> dimensions) + testAllMinusBoundaryEqualInteriorProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestAllMinusBoundaryEqualInteriorProperty_1D_Entity) { + for (const auto& dimension : this -> dimensions) + testAllMinusBoundaryEqualInteriorProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestAllMinusInteriorEqualBoundaryProperty_0D_Entity) { + for (const auto& dimension : this -> dimensions) + testAllMinusInteriorEqualBoundaryProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestAllMinusInteriorEqualBoundaryProperty_1D_Entity) { + for (const auto& dimension : this -> dimensions) + testAllMinusInteriorEqualBoundaryProperty(this -> grid, dimension); +} + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Traverse/Grid2DTest.cpp b/src/UnitTests/Meshes/GridTests/Traverse/Grid2DTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..63738765a8730089d970d0ee219d88e68e8851bf --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Traverse/Grid2DTest.cpp @@ -0,0 +1,3 @@ + +#include "Grid2DTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Traverse/Grid2DTest.cu b/src/UnitTests/Meshes/GridTests/Traverse/Grid2DTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..63738765a8730089d970d0ee219d88e68e8851bf --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Traverse/Grid2DTest.cu @@ -0,0 +1,3 @@ + +#include "Grid2DTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Traverse/Grid2DTest.h b/src/UnitTests/Meshes/GridTests/Traverse/Grid2DTest.h new file mode 100644 index 0000000000000000000000000000000000000000..964220a7ca9d3876291245744a52f1062dabb8bd --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Traverse/Grid2DTest.h @@ -0,0 +1,169 @@ + +#pragma once + +#ifdef HAVE_GTEST + +#include + +#include + +#include "support.h" + +#ifdef HAVE_CUDA +using Implementations = ::testing::Types< + TNL::Meshes::Grid<2, double, TNL::Devices::Host, int>, + TNL::Meshes::Grid<2, float, TNL::Devices::Host, int>, + TNL::Meshes::Grid<2, double, TNL::Devices::Cuda, int>, + TNL::Meshes::Grid<2, float, TNL::Devices::Cuda, int> +>; +#else +using Implementations = ::testing::Types< + TNL::Meshes::Grid<2, double, TNL::Devices::Host, int>, + TNL::Meshes::Grid<2, float, TNL::Devices::Host, int> +>; +#endif + +template +class GridTestSuite: public ::testing::Test { + protected: + GridType grid; + + std::vector dimensions = { + { 1, 1 }, + { 2, 1 }, + { 1, 2 }, + { 2, 2 }, + { 3, 3 }, + { 100, 1 }, + { 1, 100 } +#if defined(HAVE_CUDA) || defined(HAVE_OPENMP) + , + { 100, 100 } +#endif + }; + + std::vector origins = { + { 1, 1 }, + { -10, -10 }, + { 0.1, 0.1 }, + { 1, 0.2 }, + { 1, -1 }, + { -2, -2 } + }; + + std::vector spaceSteps = { + { 0.1, 0.1 }, + { 2, 2.4 }, + { 0.1, 3.1 }, + { 1, 4 }, + { 12, 2 } + }; + +#ifndef HAVE_CUDA + void SetUp() override { + if (std::is_same::value) { + GTEST_SKIP() << "No CUDA available on host. Try to compile with CUDA instead"; + } + } +#endif +}; + +TYPED_TEST_SUITE(GridTestSuite, Implementations); + +TYPED_TEST(GridTestSuite, TestForAllTraverse_0D_Entity) { + for (const auto& dimension: this->dimensions) + for (const auto& origin: this->origins) + for (const auto& spaceStep: this->spaceSteps) + testForAllTraverse(this -> grid, dimension, origin, spaceStep); +} + +TYPED_TEST(GridTestSuite, TestForAllTraverse_1D_Entity) { + for (const auto& dimension: this->dimensions) + for (const auto& origin: this->origins) + for (const auto& spaceStep: this->spaceSteps) + testForAllTraverse(this -> grid, dimension, origin, spaceStep); +} + +TYPED_TEST(GridTestSuite, TestForAllTraverse_2D_Entity) { + for (const auto& dimension: this->dimensions) + for (const auto& origin: this->origins) + for (const auto& spaceStep: this->spaceSteps) + testForAllTraverse(this -> grid, dimension, origin, spaceStep); +} + +TYPED_TEST(GridTestSuite, TestForInteriorTraverse_0D_Entity) { + for (const auto& dimension : this -> dimensions) + testForInteriorTraverse(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestForInteriorTraverse_1D_Entity) { + for (const auto& dimension : this -> dimensions) + testForInteriorTraverse(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestForInteriorTraverse_2D_Entity) { + for (const auto& dimension : this -> dimensions) + testForInteriorTraverse(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestForBoundaryTraverse_0D_Entity) { + for (const auto& dimension : this -> dimensions) + testForBoundaryTraverse(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestForBoundaryTraverse_1D_Entity) { + for (const auto& dimension : this -> dimensions) + testForBoundaryTraverse(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestForBoundaryTraverse_2D_Entity) { + for (const auto& dimension : this -> dimensions) + testForBoundaryTraverse(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestBoundaryUnionInternalEqualAllProperty_0D_Entity) { + for (const auto& dimension : this -> dimensions) + testBoundaryUnionInteriorEqualAllProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestBoundaryUnionInternalEqualAllProperty_1D_Entity) { + for (const auto& dimension : this -> dimensions) + testBoundaryUnionInteriorEqualAllProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestBoundaryUnionInternalEqualAllProperty_2D_Entity) { + for (const auto& dimension : this -> dimensions) + testBoundaryUnionInteriorEqualAllProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestAllMinusBoundaryEqualInteriorProperty_0D_Entity) { + for (const auto& dimension : this -> dimensions) + testAllMinusBoundaryEqualInteriorProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestAllMinusBoundaryEqualInteriorProperty_1D_Entity) { + for (const auto& dimension : this -> dimensions) + testAllMinusBoundaryEqualInteriorProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestAllMinusBoundaryEqualInteriorProperty_2D_Entity) { + for (const auto& dimension : this -> dimensions) + testAllMinusBoundaryEqualInteriorProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestAllMinusInteriorEqualBoundaryProperty_0D_Entity) { + for (const auto& dimension : this -> dimensions) + testAllMinusInteriorEqualBoundaryProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestAllMinusInteriorEqualBoundaryProperty_1D_Entity) { + for (const auto& dimension : this -> dimensions) + testAllMinusInteriorEqualBoundaryProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestAllMinusInteriorEqualBoundaryProperty_2D_Entity) { + for (const auto& dimension : this -> dimensions) + testAllMinusInteriorEqualBoundaryProperty(this -> grid, dimension); +} + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Traverse/Grid3DTest.cpp b/src/UnitTests/Meshes/GridTests/Traverse/Grid3DTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4f9bb7cd1339c087bc35ba2c189c0f57087f60e9 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Traverse/Grid3DTest.cpp @@ -0,0 +1,3 @@ + +#include "Grid3DTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Traverse/Grid3DTest.cu b/src/UnitTests/Meshes/GridTests/Traverse/Grid3DTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..4f9bb7cd1339c087bc35ba2c189c0f57087f60e9 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Traverse/Grid3DTest.cu @@ -0,0 +1,3 @@ + +#include "Grid3DTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Traverse/Grid3DTest.h b/src/UnitTests/Meshes/GridTests/Traverse/Grid3DTest.h new file mode 100644 index 0000000000000000000000000000000000000000..138b30a770e5446a6c8f7e6828681f4f3a11cea2 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Traverse/Grid3DTest.h @@ -0,0 +1,205 @@ + +#pragma once + +#ifdef HAVE_GTEST + +#include + +#include +#include "support.h" + +#ifdef HAVE_CUDA +using Implementations = ::testing::Types< + TNL::Meshes::Grid<3, double, TNL::Devices::Host, int>, + TNL::Meshes::Grid<3, float, TNL::Devices::Host, int>, + TNL::Meshes::Grid<3, double, TNL::Devices::Cuda, int>, + TNL::Meshes::Grid<3, float, TNL::Devices::Cuda, int> +>; +#else +using Implementations = ::testing::Types< + TNL::Meshes::Grid<3, double, TNL::Devices::Host, int>, + TNL::Meshes::Grid<3, float, TNL::Devices::Host, int> +>; +#endif + +template +class GridTestSuite: public ::testing::Test { + protected: + GridType grid; + + std::vector dimensions = { + { 1, 1, 1 }, + { 2, 1, 1 }, + { 1, 2, 1 }, + { 1, 1, 2 }, + { 2, 2, 2 }, + { 3, 3, 3 }, + { 10, 1, 1 }, + { 1, 10, 1 }, + { 1, 1, 10 } +#if defined(HAVE_CUDA) || defined(HAVE_OPENMP) + , + { 10, 10, 1 }, + { 1, 10, 10 }, + { 10, 1, 10 }, + { 10, 10, 10 } +#endif + }; + + std::vector origins = { + { 1, 1, 1 }, + { -10, -10, 2 }, + { 0.1, 0.1, 0.1 }, + { 1, 0.2, 1 }, + { 1, -1, 2 }, + { -2, -2, -2 } + }; + + std::vector spaceSteps = { + { 0.1, 0.1, 0.1 }, + { 2, 2.4, 2 }, + { 0.1, 3.1, 1 }, + { 1, 4, 2 }, + { 12, 2, 1 } + }; + +#ifndef HAVE_CUDA + void SetUp() override { + if (std::is_same::value) { + GTEST_SKIP() << "No CUDA available on host. Try to compile with CUDA instead"; + } + } +#endif +}; + +TYPED_TEST_SUITE(GridTestSuite, Implementations); + +TYPED_TEST(GridTestSuite, TestForAllTraverse_0D_Entity) { + for (const auto& dimension: this->dimensions) + for (const auto& origin: this->origins) + for (const auto& spaceStep: this->spaceSteps) + testForAllTraverse(this->grid, dimension, origin, spaceStep); +} + +TYPED_TEST(GridTestSuite, TestForAllTraverse_1D_Entity) { + for (const auto& dimension: this->dimensions) + for (const auto& origin: this->origins) + for (const auto& spaceStep: this->spaceSteps) + testForAllTraverse(this->grid, dimension, origin, spaceStep); +} + +TYPED_TEST(GridTestSuite, TestForAllTraverse_2D_Entity) { + for (const auto& dimension: this->dimensions) + for (const auto& origin: this->origins) + for (const auto& spaceStep: this->spaceSteps) + testForAllTraverse(this->grid, dimension, origin, spaceStep); +} + +TYPED_TEST(GridTestSuite, TestForAllTraverse_3D_Entity) { + for (const auto& dimension: this->dimensions) + for (const auto& origin: this->origins) + for (const auto& spaceStep: this->spaceSteps) + testForAllTraverse(this->grid, dimension, origin, spaceStep); +} + +TYPED_TEST(GridTestSuite, TestForInteriorTraverse_0D_Entity) { + for (const auto& dimension : this->dimensions) + testForInteriorTraverse(this->grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestForInteriorTraverse_1D_Entity) { + for (const auto& dimension : this->dimensions) + testForInteriorTraverse(this->grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestForInteriorTraverse_2D_Entity) { + for (const auto& dimension : this->dimensions) + testForInteriorTraverse(this->grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestForInteriorTraverse_3D_Entity) { + for (const auto& dimension : this->dimensions) + testForInteriorTraverse(this->grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestForBoundaryTraverse_0D_Entity) { + for (const auto& dimension : this->dimensions) + testForBoundaryTraverse(this->grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestForBoundaryTraverse_1D_Entity) { + for (const auto& dimension : this->dimensions) + testForBoundaryTraverse(this->grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestForBoundaryTraverse_2D_Entity) { + for (const auto& dimension : this->dimensions) + testForBoundaryTraverse(this->grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestForBoundaryTraverse_3D_Entity) { + for (const auto& dimension : this->dimensions) + testForBoundaryTraverse(this->grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestBoundaryUnionInternalEqualAllProperty_0D_Entity) { + for (const auto& dimension : this -> dimensions) + testBoundaryUnionInteriorEqualAllProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestBoundaryUnionInternalEqualAllProperty_1D_Entity) { + for (const auto& dimension : this -> dimensions) + testBoundaryUnionInteriorEqualAllProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestBoundaryUnionInternalEqualAllProperty_2D_Entity) { + for (const auto& dimension : this -> dimensions) + testBoundaryUnionInteriorEqualAllProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestBoundaryUnionInternalEqualAllProperty_3D_Entity) { + for (const auto& dimension : this -> dimensions) + testBoundaryUnionInteriorEqualAllProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestAllMinusBoundaryEqualInteriorProperty_0D_Entity) { + for (const auto& dimension : this -> dimensions) + testAllMinusBoundaryEqualInteriorProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestAllMinusBoundaryEqualInteriorProperty_1D_Entity) { + for (const auto& dimension : this -> dimensions) + testAllMinusBoundaryEqualInteriorProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestAllMinusBoundaryEqualInteriorProperty_2D_Entity) { + for (const auto& dimension : this -> dimensions) + testAllMinusBoundaryEqualInteriorProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestAllMinusBoundaryEqualInteriorProperty_3D_Entity) { + for (const auto& dimension : this -> dimensions) + testAllMinusBoundaryEqualInteriorProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestAllMinusInteriorEqualBoundaryProperty_0D_Entity) { + for (const auto& dimension : this -> dimensions) + testAllMinusInteriorEqualBoundaryProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestAllMinusInteriorEqualBoundaryProperty_1D_Entity) { + for (const auto& dimension : this -> dimensions) + testAllMinusInteriorEqualBoundaryProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestAllMinusInteriorEqualBoundaryProperty_2D_Entity) { + for (const auto& dimension : this -> dimensions) + testAllMinusInteriorEqualBoundaryProperty(this -> grid, dimension); +} + +TYPED_TEST(GridTestSuite, TestAllMinusInteriorEqualBoundaryProperty_3D_Entity) { + for (const auto& dimension : this -> dimensions) + testAllMinusInteriorEqualBoundaryProperty(this -> grid, dimension); +} + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Traverse/GridCoordinateIteratorTest.cpp b/src/UnitTests/Meshes/GridTests/Traverse/GridCoordinateIteratorTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e33038c2ff8b60c0944f1be755ffc7ed88173b5f --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Traverse/GridCoordinateIteratorTest.cpp @@ -0,0 +1,3 @@ + +#include "GridCoordinateIteratorTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Traverse/GridCoordinateIteratorTest.cu b/src/UnitTests/Meshes/GridTests/Traverse/GridCoordinateIteratorTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..e33038c2ff8b60c0944f1be755ffc7ed88173b5f --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Traverse/GridCoordinateIteratorTest.cu @@ -0,0 +1,3 @@ + +#include "GridCoordinateIteratorTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Traverse/GridCoordinateIteratorTest.h b/src/UnitTests/Meshes/GridTests/Traverse/GridCoordinateIteratorTest.h new file mode 100644 index 0000000000000000000000000000000000000000..44b15b6c142b3196e7e733de52708b53d47ca9b1 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Traverse/GridCoordinateIteratorTest.h @@ -0,0 +1,508 @@ + +#pragma once + +#ifdef HAVE_GTEST + + #include + #include "support.h" + #include + +using Index = int; +using Real = float; +using Device = TNL::Devices::Host; + +template< typename Grid, typename Iterator > +void +test( Iterator& iterator, + Grid& grid, + typename Grid::Coordinate coordinate, + typename Grid::Coordinate basis, + typename Grid::Point center, + bool isBoundary, + typename Iterator::Index index, + typename Iterator::Real measure, + bool next ) +{ + static Real precision = 9e-5; + + EXPECT_EQ( coordinate, iterator.getCoordinate() ) << coordinate; + EXPECT_EQ( basis, iterator.getBasis() ) << coordinate; + EXPECT_EQ( isBoundary, iterator.isBoundary( grid ) ) << coordinate; + EXPECT_EQ( index, iterator.getIndex( grid ) ) << coordinate; + + EXPECT_NEAR( measure, iterator.getMeasure( grid ), precision ) << coordinate; + + typename Grid::Point iteratorCenter = iterator.getCenter( grid ); + + for( Index i = 0; i < center.getSize(); i++ ) + EXPECT_NEAR( center[ i ], iteratorCenter[ i ], precision ) << coordinate << " " << iteratorCenter; + + EXPECT_EQ( next, iterator.next() ) << coordinate; +} + +TEST( GridCoordinateIteratorTest, Grid1DEntity0DOrientation0Test ) +{ + constexpr int Dimension = 1; + constexpr int EntityDimension = 0; + constexpr int Orientation = 0; + using Grid = TNL::Meshes::Grid< Dimension, Real, Device, Index >; + using Iterator = GridCoordinateIterator< Grid, EntityDimension, Orientation >; + + Grid grid; + grid.setDimensions( 3 ); + grid.setSpaceSteps( 1. ); + + Iterator iterator( grid.getDimensions() ); + + test( iterator, grid, { 0 }, { 1 }, { 0. }, true, 0, 0., false ); + test( iterator, grid, { 1 }, { 1 }, { 1. }, false, 1, 0., false ); + test( iterator, grid, { 2 }, { 1 }, { 2. }, false, 2, 0., false ); + test( iterator, grid, { 3 }, { 1 }, { 3. }, true, 3, 0., true ); +} + +TEST( GridCoordinateIteratorTest, Grid1DEntity1DOrientation0Test ) +{ + constexpr int Dimension = 1; + constexpr int EntityDimension = 1; + constexpr int Orientation = 0; + using Grid = TNL::Meshes::Grid< Dimension, Real, Device, Index >; + using Iterator = GridCoordinateIterator< Grid, EntityDimension, Orientation >; + + Grid grid; + grid.setDimensions( 3 ); + grid.setSpaceSteps( 1. ); + + Iterator iterator( grid.getDimensions() ); + + test( iterator, grid, { 0 }, { 0 }, { 0.5 }, true, 0, 1., false ); + test( iterator, grid, { 1 }, { 0 }, { 1.5 }, false, 1, 1., false ); + test( iterator, grid, { 2 }, { 0 }, { 2.5 }, true, 2, 1., true ); +} + +TEST( GridCoordinateIteratorTest, Grid2DEntity0DOrientation0Test ) +{ + constexpr int Dimension = 2; + constexpr int EntityDimension = 0; + constexpr int Orientation = 0; + using Grid = TNL::Meshes::Grid< Dimension, Real, Device, Index >; + using Iterator = GridCoordinateIterator< Grid, EntityDimension, Orientation >; + + Grid grid; + grid.setDimensions( 3, 3 ); + grid.setSpaceSteps( 1., 1. ); + grid.setOrigin( 0., 0. ); + + Iterator iterator( grid.getDimensions() ); + + test( iterator, grid, { 0, 0 }, { 1, 1 }, { 0., 0. }, true, 0, 0., false ); + test( iterator, grid, { 1, 0 }, { 1, 1 }, { 1., 0. }, true, 1, 0., false ); + test( iterator, grid, { 2, 0 }, { 1, 1 }, { 2., 0. }, true, 2, 0., false ); + test( iterator, grid, { 3, 0 }, { 1, 1 }, { 3., 0. }, true, 3, 0., false ); + + test( iterator, grid, { 0, 1 }, { 1, 1 }, { 0., 1. }, true, 4, 0., false ); + test( iterator, grid, { 1, 1 }, { 1, 1 }, { 1., 1. }, false, 5, 0., false ); + test( iterator, grid, { 2, 1 }, { 1, 1 }, { 2., 1. }, false, 6, 0., false ); + test( iterator, grid, { 3, 1 }, { 1, 1 }, { 3., 1. }, true, 7, 0., false ); + + test( iterator, grid, { 0, 2 }, { 1, 1 }, { 0., 2. }, true, 8, 0., false ); + test( iterator, grid, { 1, 2 }, { 1, 1 }, { 1., 2. }, false, 9, 0., false ); + test( iterator, grid, { 2, 2 }, { 1, 1 }, { 2., 2. }, false, 10, 0., false ); + test( iterator, grid, { 3, 2 }, { 1, 1 }, { 3., 2. }, true, 11, 0., false ); + + test( iterator, grid, { 0, 3 }, { 1, 1 }, { 0., 3. }, true, 12, 0., false ); + test( iterator, grid, { 1, 3 }, { 1, 1 }, { 1., 3. }, true, 13, 0., false ); + test( iterator, grid, { 2, 3 }, { 1, 1 }, { 2., 3. }, true, 14, 0., false ); + test( iterator, grid, { 3, 3 }, { 1, 1 }, { 3., 3. }, true, 15, 0., true ); + +} + +TEST( GridCoordinateIteratorTest, Grid2DEntity1DOrientation0Test ) +{ + constexpr int Dimension = 2; + constexpr int EntityDimension = 1; + constexpr int Orientation = 0; + using Grid = TNL::Meshes::Grid< Dimension, Real, Device, Index >; + using Iterator = GridCoordinateIterator< Grid, EntityDimension, Orientation >; + + Grid grid; + grid.setDimensions( 3, 3 ); + grid.setSpaceSteps( 1., 1. ); + + Iterator iterator( grid.getDimensions() ); + + test( iterator, grid, { 0, 0 }, { 0, 1 }, { 0.5, 0. }, true, 0, 1., false ); + test( iterator, grid, { 1, 0 }, { 0, 1 }, { 1.5, 0. }, true, 1, 1., false ); + test( iterator, grid, { 2, 0 }, { 0, 1 }, { 2.5, 0. }, true, 2, 1., false ); + + test( iterator, grid, { 0, 1 }, { 0, 1 }, { 0.5, 1. }, false, 3, 1., false ); + test( iterator, grid, { 1, 1 }, { 0, 1 }, { 1.5, 1. }, false, 4, 1., false ); + test( iterator, grid, { 2, 1 }, { 0, 1 }, { 2.5, 1. }, false, 5, 1., false ); + + test( iterator, grid, { 0, 2 }, { 0, 1 }, { 0.5, 2. }, false, 6, 1., false ); + test( iterator, grid, { 1, 2 }, { 0, 1 }, { 1.5, 2. }, false, 7, 1., false ); + test( iterator, grid, { 2, 2 }, { 0, 1 }, { 2.5, 2. }, false, 8, 1., false ); + + test( iterator, grid, { 0, 3 }, { 0, 1 }, { 0.5, 3. }, true, 9, 1., false ); + test( iterator, grid, { 1, 3 }, { 0, 1 }, { 1.5, 3. }, true, 10, 1., false ); + test( iterator, grid, { 2, 3 }, { 0, 1 }, { 2.5, 3. }, true, 11, 1., true ); +} + +TEST( GridCoordinateIteratorTest, Grid2DEntity1DOrientation1Test ) +{ + constexpr int Dimension = 2; + constexpr int EntityDimension = 1; + constexpr int Orientation = 1; + using Grid = TNL::Meshes::Grid< Dimension, Real, Device, Index >; + using Iterator = GridCoordinateIterator< Grid, EntityDimension, Orientation >; + + Grid grid; + grid.setDimensions( 3, 3 ); + grid.setSpaceSteps( 1., 1. ); + + Iterator iterator( grid.getDimensions() ); + + test( iterator, grid, { 0, 0 }, { 1, 0 }, { 0., 0.5 }, true, 12, 1., false ); + test( iterator, grid, { 1, 0 }, { 1, 0 }, { 1., 0.5 }, false, 13, 1., false ); + test( iterator, grid, { 2, 0 }, { 1, 0 }, { 2., 0.5 }, false, 14, 1., false ); + test( iterator, grid, { 3, 0 }, { 1, 0 }, { 3., 0.5 }, true, 15, 1., false ); + + test( iterator, grid, { 0, 1 }, { 1, 0 }, { 0., 1.5 }, true, 16, 1., false ); + test( iterator, grid, { 1, 1 }, { 1, 0 }, { 1., 1.5 }, false, 17, 1., false ); + test( iterator, grid, { 2, 1 }, { 1, 0 }, { 2., 1.5 }, false, 18, 1., false ); + test( iterator, grid, { 3, 1 }, { 1, 0 }, { 3., 1.5 }, true, 19, 1., false ); + + test( iterator, grid, { 0, 2 }, { 1, 0 }, { 0., 2.5 }, true, 20, 1., false ); + test( iterator, grid, { 1, 2 }, { 1, 0 }, { 1., 2.5 }, false, 21, 1., false ); + test( iterator, grid, { 2, 2 }, { 1, 0 }, { 2., 2.5 }, false, 22, 1., false ); + test( iterator, grid, { 3, 2 }, { 1, 0 }, { 3., 2.5 }, true, 23, 1., true ); +} + +TEST( GridCoordinateIteratorTest, Grid2DEntity2DOrientation0Test ) +{ + constexpr int Dimension = 2; + constexpr int EntityDimension = 2; + constexpr int Orientation = 0; + using Grid = TNL::Meshes::Grid< Dimension, Real, Device, Index >; + using Iterator = GridCoordinateIterator< Grid, EntityDimension, Orientation >; + + Grid grid; + grid.setDimensions( 3, 3 ); + grid.setSpaceSteps( 1., 1. ); + + Iterator iterator( grid.getDimensions() ); + + test( iterator, grid, { 0, 0 }, { 0, 0 }, { 0.5, 0.5 }, true, 0, 1., false ); + test( iterator, grid, { 1, 0 }, { 0, 0 }, { 1.5, 0.5 }, true, 1, 1., false ); + test( iterator, grid, { 2, 0 }, { 0, 0 }, { 2.5, 0.5 }, true, 2, 1., false ); + + test( iterator, grid, { 0, 1 }, { 0, 0 }, { 0.5, 1.5 }, true, 3, 1., false ); + test( iterator, grid, { 1, 1 }, { 0, 0 }, { 1.5, 1.5 }, false, 4, 1., false ); + test( iterator, grid, { 2, 1 }, { 0, 0 }, { 2.5, 1.5 }, true, 5, 1., false ); + + test( iterator, grid, { 0, 2 }, { 0, 0 }, { 0.5, 2.5 }, true, 6, 1., false ); + test( iterator, grid, { 1, 2 }, { 0, 0 }, { 1.5, 2.5 }, true, 7, 1., false ); + test( iterator, grid, { 2, 2 }, { 0, 0 }, { 2.5, 2.5 }, true, 8, 1., true ); +} + +TEST( GridCoordinateIteratorTest, Grid3DEntity0DOrientation0Test ) +{ + constexpr int Dimension = 3; + constexpr int EntityDimension = 0; + constexpr int Orientation = 0; + using Grid = TNL::Meshes::Grid< Dimension, Real, Device, Index >; + using Iterator = GridCoordinateIterator< Grid, EntityDimension, Orientation >; + + Grid grid; + grid.setDimensions( 2, 2, 2 ); + grid.setSpaceSteps( 1., 1., 1. ); + grid.setOrigin( 0., 0., 0.); + + Iterator iterator( grid.getDimensions() ); + + test( iterator, grid, { 0, 0, 0 }, { 1, 1, 1 }, { 0., 0., 0. }, true, 0, 0., false ); + test( iterator, grid, { 1, 0, 0 }, { 1, 1, 1 }, { 1., 0., 0. }, true, 1, 0., false ); + test( iterator, grid, { 2, 0, 0 }, { 1, 1, 1 }, { 2., 0., 0. }, true, 2, 0., false ); + + test( iterator, grid, { 0, 1, 0 }, { 1, 1, 1 }, { 0., 1., 0. }, true, 3, 0., false ); + test( iterator, grid, { 1, 1, 0 }, { 1, 1, 1 }, { 1., 1., 0. }, true, 4, 0., false ); + test( iterator, grid, { 2, 1, 0 }, { 1, 1, 1 }, { 2., 1., 0. }, true, 5, 0., false ); + + test( iterator, grid, { 0, 2, 0 }, { 1, 1, 1 }, { 0., 2., 0. }, true, 6, 0., false ); + test( iterator, grid, { 1, 2, 0 }, { 1, 1, 1 }, { 1., 2., 0. }, true, 7, 0., false ); + test( iterator, grid, { 2, 2, 0 }, { 1, 1, 1 }, { 2., 2., 0. }, true, 8, 0., false ); + + + test( iterator, grid, { 0, 0, 1 }, { 1, 1, 1 }, { 0., 0., 1. }, true, 9, 0., false ); + test( iterator, grid, { 1, 0, 1 }, { 1, 1, 1 }, { 1., 0., 1. }, true, 10, 0., false ); + test( iterator, grid, { 2, 0, 1 }, { 1, 1, 1 }, { 2., 0., 1. }, true, 11, 0., false ); + + test( iterator, grid, { 0, 1, 1 }, { 1, 1, 1 }, { 0., 1., 1. }, true, 12, 0., false ); + test( iterator, grid, { 1, 1, 1 }, { 1, 1, 1 }, { 1., 1., 1. }, false, 13, 0., false ); + test( iterator, grid, { 2, 1, 1 }, { 1, 1, 1 }, { 2., 1., 1. }, true, 14, 0., false ); + + test( iterator, grid, { 0, 2, 1 }, { 1, 1, 1 }, { 0., 2., 1. }, true, 15, 0., false ); + test( iterator, grid, { 1, 2, 1 }, { 1, 1, 1 }, { 1., 2., 1. }, true, 16, 0., false ); + test( iterator, grid, { 2, 2, 1 }, { 1, 1, 1 }, { 2., 2., 1. }, true, 17, 0., false ); + + + test( iterator, grid, { 0, 0, 2 }, { 1, 1, 1 }, { 0., 0., 2. }, true, 18, 0., false ); + test( iterator, grid, { 1, 0, 2 }, { 1, 1, 1 }, { 1., 0., 2. }, true, 19, 0., false ); + test( iterator, grid, { 2, 0, 2 }, { 1, 1, 1 }, { 2., 0., 2. }, true, 20, 0., false ); + + test( iterator, grid, { 0, 1, 2 }, { 1, 1, 1 }, { 0., 1., 2. }, true, 21, 0., false ); + test( iterator, grid, { 1, 1, 2 }, { 1, 1, 1 }, { 1., 1., 2. }, true, 22, 0., false ); + test( iterator, grid, { 2, 1, 2 }, { 1, 1, 1 }, { 2., 1., 2. }, true, 23, 0., false ); + + test( iterator, grid, { 0, 2, 2 }, { 1, 1, 1 }, { 0., 2., 2. }, true, 24, 0., false ); + test( iterator, grid, { 1, 2, 2 }, { 1, 1, 1 }, { 1., 2., 2. }, true, 25, 0., false ); + test( iterator, grid, { 2, 2, 2 }, { 1, 1, 1 }, { 2., 2., 2. }, true, 26, 0., true ); +} + +TEST( GridCoordinateIteratorTest, Grid3DEntity1DOrientation0Test ) +{ + constexpr int Dimension = 3; + constexpr int EntityDimension = 1; + constexpr int Orientation = 0; + using Grid = TNL::Meshes::Grid< Dimension, Real, Device, Index >; + using Iterator = GridCoordinateIterator< Grid, EntityDimension, Orientation >; + + Grid grid; + grid.setDimensions( 2, 2, 2 ); + grid.setSpaceSteps( 1., 1., 1. ); + + Iterator iterator( grid.getDimensions() ); + + test( iterator, grid, { 0, 0, 0 }, { 0, 1, 1 }, { 0.5, 0., 0. }, true, 0, 1., false ); + test( iterator, grid, { 1, 0, 0 }, { 0, 1, 1 }, { 1.5, 0., 0. }, true, 1, 1., false ); + + test( iterator, grid, { 0, 1, 0 }, { 0, 1, 1 }, { 0.5, 1., 0. }, true, 2, 1., false ); + test( iterator, grid, { 1, 1, 0 }, { 0, 1, 1 }, { 1.5, 1., 0. }, true, 3, 1., false ); + + test( iterator, grid, { 0, 2, 0 }, { 0, 1, 1 }, { 0.5, 2., 0. }, true, 4, 1., false ); + test( iterator, grid, { 1, 2, 0 }, { 0, 1, 1 }, { 1.5, 2., 0. }, true, 5, 1., false ); + + + test( iterator, grid, { 0, 0, 1 }, { 0, 1, 1 }, { 0.5, 0., 1. }, true, 6, 1., false ); + test( iterator, grid, { 1, 0, 1 }, { 0, 1, 1 }, { 1.5, 0., 1. }, true, 7, 1., false ); + + test( iterator, grid, { 0, 1, 1 }, { 0, 1, 1 }, { 0.5, 1., 1. }, false, 8, 1., false ); + test( iterator, grid, { 1, 1, 1 }, { 0, 1, 1 }, { 1.5, 1., 1. }, false, 9, 1., false ); + + test( iterator, grid, { 0, 2, 1 }, { 0, 1, 1 }, { 0.5, 2., 1. }, true, 10, 1., false ); + test( iterator, grid, { 1, 2, 1 }, { 0, 1, 1 }, { 1.5, 2., 1. }, true, 11, 1., false ); + + + test( iterator, grid, { 0, 0, 2 }, { 0, 1, 1 }, { 0.5, 0., 2. }, true, 12, 1., false ); + test( iterator, grid, { 1, 0, 2 }, { 0, 1, 1 }, { 1.5, 0., 2. }, true, 13, 1., false ); + + test( iterator, grid, { 0, 1, 2 }, { 0, 1, 1 }, { 0.5, 1., 2. }, true, 14, 1., false ); + test( iterator, grid, { 1, 1, 2 }, { 0, 1, 1 }, { 1.5, 1., 2. }, true, 15, 1., false ); + + test( iterator, grid, { 0, 2, 2 }, { 0, 1, 1 }, { 0.5, 2., 2. }, true, 16, 1., false ); + test( iterator, grid, { 1, 2, 2 }, { 0, 1, 1 }, { 1.5, 2., 2. }, true, 17, 1., true ); +} + +TEST( GridCoordinateIteratorTest, Grid3DEntity1DOrientation1Test ) +{ + constexpr int Dimension = 3; + constexpr int EntityDimension = 1; + constexpr int Orientation = 1; + using Grid = TNL::Meshes::Grid< Dimension, Real, Device, Index >; + using Iterator = GridCoordinateIterator< Grid, EntityDimension, Orientation >; + + Grid grid; + grid.setDimensions( 2, 2, 2 ); + grid.setSpaceSteps( 1., 1., 1. ); + + Iterator iterator( grid.getDimensions() ); + + test( iterator, grid, { 0, 0, 0 }, { 1, 0, 1 }, { 0., 0.5, 0. }, true, 18, 1., false ); + test( iterator, grid, { 1, 0, 0 }, { 1, 0, 1 }, { 1., 0.5, 0. }, true, 19, 1., false ); + test( iterator, grid, { 2, 0, 0 }, { 1, 0, 1 }, { 2., 0.5, 0. }, true, 20, 1., false ); + + test( iterator, grid, { 0, 1, 0 }, { 1, 0, 1 }, { 0., 1.5, 0. }, true, 21, 1., false ); + test( iterator, grid, { 1, 1, 0 }, { 1, 0, 1 }, { 1., 1.5, 0. }, true, 22, 1., false ); + test( iterator, grid, { 2, 1, 0 }, { 1, 0, 1 }, { 2., 1.5, 0. }, true, 23, 1., false ); + + test( iterator, grid, { 0, 0, 1 }, { 1, 0, 1 }, { 0., 0.5, 1. }, true, 24, 1., false ); + test( iterator, grid, { 1, 0, 1 }, { 1, 0, 1 }, { 1., 0.5, 1. }, false, 25, 1., false ); + test( iterator, grid, { 2, 0, 1 }, { 1, 0, 1 }, { 2., 0.5, 1. }, true, 26, 1., false ); + + test( iterator, grid, { 0, 1, 1 }, { 1, 0, 1 }, { 0., 1.5, 1. }, true, 27, 1., false ); + test( iterator, grid, { 1, 1, 1 }, { 1, 0, 1 }, { 1., 1.5, 1. }, false, 28, 1., false ); + test( iterator, grid, { 2, 1, 1 }, { 1, 0, 1 }, { 2., 1.5, 1. }, true, 29, 1., false ); + + test( iterator, grid, { 0, 0, 2 }, { 1, 0, 1 }, { 0., 0.5, 2. }, true, 30, 1., false ); + test( iterator, grid, { 1, 0, 2 }, { 1, 0, 1 }, { 1., 0.5, 2. }, true, 31, 1., false ); + test( iterator, grid, { 2, 0, 2 }, { 1, 0, 1 }, { 2., 0.5, 2. }, true, 32, 1., false ); + + test( iterator, grid, { 0, 1, 2 }, { 1, 0, 1 }, { 0., 1.5, 2. }, true, 33, 1., false ); + test( iterator, grid, { 1, 1, 2 }, { 1, 0, 1 }, { 1., 1.5, 2. }, true, 34, 1., false ); + test( iterator, grid, { 2, 1, 2 }, { 1, 0, 1 }, { 2., 1.5, 2. }, true, 35, 1., true ); +} + +TEST( GridCoordinateIteratorTest, Grid3DEntity1DOrientation2Test ) +{ + constexpr int Dimension = 3; + constexpr int EntityDimension = 1; + constexpr int Orientation = 2; + using Grid = TNL::Meshes::Grid< Dimension, Real, Device, Index >; + using Iterator = GridCoordinateIterator< Grid, EntityDimension, Orientation >; + + Grid grid; + grid.setDimensions( 2, 2, 2 ); + grid.setSpaceSteps( 1., 1., 1. ); + + Iterator iterator( grid.getDimensions() ); + + test( iterator, grid, { 0, 0, 0 }, { 1, 1, 0 }, { 0., 0., 0.5 }, true, 36, 1., false ); + test( iterator, grid, { 1, 0, 0 }, { 1, 1, 0 }, { 1., 0., 0.5 }, true, 37, 1., false ); + test( iterator, grid, { 2, 0, 0 }, { 1, 1, 0 }, { 2., 0., 0.5 }, true, 38, 1., false ); + + test( iterator, grid, { 0, 1, 0 }, { 1, 1, 0 }, { 0., 1., 0.5 }, true, 39, 1., false ); + test( iterator, grid, { 1, 1, 0 }, { 1, 1, 0 }, { 1., 1., 0.5 }, false, 40, 1., false ); + test( iterator, grid, { 2, 1, 0 }, { 1, 1, 0 }, { 2., 1., 0.5 }, true, 41, 1., false ); + + test( iterator, grid, { 0, 2, 0 }, { 1, 1, 0 }, { 0., 2., 0.5 }, true, 42, 1., false ); + test( iterator, grid, { 1, 2, 0 }, { 1, 1, 0 }, { 1., 2., 0.5 }, true, 43, 1., false ); + test( iterator, grid, { 2, 2, 0 }, { 1, 1, 0 }, { 2., 2., 0.5 }, true, 44, 1., false ); + + + test( iterator, grid, { 0, 0, 1 }, { 1, 1, 0 }, { 0., 0., 1.5 }, true, 45, 1., false ); + test( iterator, grid, { 1, 0, 1 }, { 1, 1, 0 }, { 1., 0., 1.5 }, true, 46, 1., false ); + test( iterator, grid, { 2, 0, 1 }, { 1, 1, 0 }, { 2., 0., 1.5 }, true, 47, 1., false ); + + test( iterator, grid, { 0, 1, 1 }, { 1, 1, 0 }, { 0., 1., 1.5 }, true, 48, 1., false ); + test( iterator, grid, { 1, 1, 1 }, { 1, 1, 0 }, { 1., 1., 1.5 }, false, 49, 1., false ); + test( iterator, grid, { 2, 1, 1 }, { 1, 1, 0 }, { 2., 1., 1.5 }, true, 50, 1., false ); + + test( iterator, grid, { 0, 2, 1 }, { 1, 1, 0 }, { 0., 2., 1.5 }, true, 51, 1., false ); + test( iterator, grid, { 1, 2, 1 }, { 1, 1, 0 }, { 1., 2., 1.5 }, true, 52, 1., false ); + test( iterator, grid, { 2, 2, 1 }, { 1, 1, 0 }, { 2., 2., 1.5 }, true, 53, 1., true ); +} + +TEST( GridCoordinateIteratorTest, Grid3DEntity2DOrientation0Test ) +{ + constexpr int Dimension = 3; + constexpr int EntityDimension = 2; + constexpr int Orientation = 0; + using Grid = TNL::Meshes::Grid< Dimension, Real, Device, Index >; + using Iterator = GridCoordinateIterator< Grid, EntityDimension, Orientation >; + + Grid grid; + grid.setDimensions( 2, 2, 2 ); + grid.setSpaceSteps( 1., 1., 1. ); + + Iterator iterator( grid.getDimensions() ); + + test( iterator, grid, { 0, 0, 0 }, { 0, 0, 1 }, { 0.5, 0.5, 0. }, true, 0, 1., false ); + test( iterator, grid, { 1, 0, 0 }, { 0, 0, 1 }, { 1.5, 0.5, 0. }, true, 1, 1., false ); + + test( iterator, grid, { 0, 1, 0 }, { 0, 0, 1 }, { 0.5, 1.5, 0. }, true, 2, 1., false ); + test( iterator, grid, { 1, 1, 0 }, { 0, 0, 1 }, { 1.5, 1.5, 0. }, true, 3, 1., false ); + + test( iterator, grid, { 0, 0, 1 }, { 0, 0, 1 }, { 0.5, 0.5, 1. }, false, 4, 1., false ); + test( iterator, grid, { 1, 0, 1 }, { 0, 0, 1 }, { 1.5, 0.5, 1. }, false, 5, 1., false ); + + test( iterator, grid, { 0, 1, 1 }, { 0, 0, 1 }, { 0.5, 1.5, 1. }, false, 6, 1., false ); + test( iterator, grid, { 1, 1, 1 }, { 0, 0, 1 }, { 1.5, 1.5, 1. }, false, 7, 1., false ); + + test( iterator, grid, { 0, 0, 2 }, { 0, 0, 1 }, { 0.5, 0.5, 2. }, true, 8, 1., false ); + test( iterator, grid, { 1, 0, 2 }, { 0, 0, 1 }, { 1.5, 0.5, 2. }, true, 9, 1., false ); + + test( iterator, grid, { 0, 1, 2 }, { 0, 0, 1 }, { 0.5, 1.5, 2. }, true, 10, 1., false ); + test( iterator, grid, { 1, 1, 2 }, { 0, 0, 1 }, { 1.5, 1.5, 2. }, true, 11, 1., true ); +} + +TEST( GridCoordinateIteratorTest, Grid3DEntity2DOrientation1Test ) +{ + constexpr int Dimension = 3; + constexpr int EntityDimension = 2; + constexpr int Orientation = 1; + using Grid = TNL::Meshes::Grid< Dimension, Real, Device, Index >; + using Iterator = GridCoordinateIterator< Grid, EntityDimension, Orientation >; + + Grid grid; + grid.setDimensions( 2, 2, 2 ); + grid.setSpaceSteps( 1., 1., 1. ); + + Iterator iterator( grid.getDimensions() ); + + test( iterator, grid, { 0, 0, 0 }, { 0, 1, 0 }, { 0.5, 0., 0.5 }, true, 12, 1., false ); + test( iterator, grid, { 1, 0, 0 }, { 0, 1, 0 }, { 1.5, 0., 0.5 }, true, 13, 1., false ); + + test( iterator, grid, { 0, 1, 0 }, { 0, 1, 0 }, { 0.5, 1., 0.5 }, false, 14, 1., false ); + test( iterator, grid, { 1, 1, 0 }, { 0, 1, 0 }, { 1.5, 1., 0.5 }, false, 15, 1., false ); + + test( iterator, grid, { 0, 2, 0 }, { 0, 1, 0 }, { 0.5, 2., 0.5 }, true, 16, 1., false ); + test( iterator, grid, { 1, 2, 0 }, { 0, 1, 0 }, { 1.5, 2., 0.5 }, true, 17, 1., false ); + + test( iterator, grid, { 0, 0, 1 }, { 0, 1, 0 }, { 0.5, 0., 1.5 }, true, 18, 1., false ); + test( iterator, grid, { 1, 0, 1 }, { 0, 1, 0 }, { 1.5, 0., 1.5 }, true, 19, 1., false ); + + test( iterator, grid, { 0, 1, 1 }, { 0, 1, 0 }, { 0.5, 1., 1.5 }, false, 20, 1., false ); + test( iterator, grid, { 1, 1, 1 }, { 0, 1, 0 }, { 1.5, 1., 1.5 }, false, 21, 1., false ); + + test( iterator, grid, { 0, 2, 1 }, { 0, 1, 0 }, { 0.5, 2., 1.5 }, true, 22, 1., false ); + test( iterator, grid, { 1, 2, 1 }, { 0, 1, 0 }, { 1.5, 2., 1.5 }, true, 23, 1., true ); +} + +TEST( GridCoordinateIteratorTest, Grid3DEntity2DOrientation2Test ) +{ + constexpr int Dimension = 3; + constexpr int EntityDimension = 2; + constexpr int Orientation = 2; + using Grid = TNL::Meshes::Grid< Dimension, Real, Device, Index >; + using Iterator = GridCoordinateIterator< Grid, EntityDimension, Orientation >; + + Grid grid; + grid.setDimensions( 2, 2, 2 ); + grid.setSpaceSteps( 1., 1., 1. ); + + Iterator iterator( grid.getDimensions() ); + + test( iterator, grid, { 0, 0, 0 }, { 1, 0, 0 }, { 0., 0.5, 0.5 }, true, 24, 1., false ); + test( iterator, grid, { 1, 0, 0 }, { 1, 0, 0 }, { 1., 0.5, 0.5 }, false, 25, 1., false ); + test( iterator, grid, { 2, 0, 0 }, { 1, 0, 0 }, { 2., 0.5, 0.5 }, true, 26, 1., false ); + + test( iterator, grid, { 0, 1, 0 }, { 1, 0, 0 }, { 0., 1.5, 0.5 }, true, 27, 1., false ); + test( iterator, grid, { 1, 1, 0 }, { 1, 0, 0 }, { 1., 1.5, 0.5 }, false, 28, 1., false ); + test( iterator, grid, { 2, 1, 0 }, { 1, 0, 0 }, { 2., 1.5, 0.5 }, true, 29, 1., false ); + + test( iterator, grid, { 0, 0, 1 }, { 1, 0, 0 }, { 0., 0.5, 1.5 }, true, 30, 1., false ); + test( iterator, grid, { 1, 0, 1 }, { 1, 0, 0 }, { 1., 0.5, 1.5 }, false, 31, 1., false ); + test( iterator, grid, { 2, 0, 1 }, { 1, 0, 0 }, { 2., 0.5, 1.5 }, true, 32, 1., false ); + + test( iterator, grid, { 0, 1, 1 }, { 1, 0, 0 }, { 0., 1.5, 1.5 }, true, 33, 1., false ); + test( iterator, grid, { 1, 1, 1 }, { 1, 0, 0 }, { 1., 1.5, 1.5 }, false, 34, 1., false ); + test( iterator, grid, { 2, 1, 1 }, { 1, 0, 0 }, { 2., 1.5, 1.5 }, true, 35, 1., true ); +} + +TEST( GridCoordinateIteratorTest, Grid3DEntity3DOrientation0Test ) +{ + constexpr int Dimension = 3; + constexpr int EntityDimension = 3; + constexpr int Orientation = 0; + using Grid = TNL::Meshes::Grid< Dimension, Real, Device, Index >; + using Iterator = GridCoordinateIterator< Grid, EntityDimension, Orientation >; + + Grid grid; + grid.setDimensions( 2, 2, 2 ); + grid.setSpaceSteps( 1., 1., 1. ); + + Iterator iterator( grid.getDimensions() ); + + test( iterator, grid, { 0, 0, 0 }, { 0, 0, 0 }, { 0.5, 0.5, 0.5 }, true, 0, 1., false ); + test( iterator, grid, { 1, 0, 0 }, { 0, 0, 0 }, { 1.5, 0.5, 0.5 }, true, 1, 1., false ); + + test( iterator, grid, { 0, 1, 0 }, { 0, 0, 0 }, { 0.5, 1.5, 0.5 }, true, 2, 1., false ); + test( iterator, grid, { 1, 1, 0 }, { 0, 0, 0 }, { 1.5, 1.5, 0.5 }, true, 3, 1., false ); + + test( iterator, grid, { 0, 0, 1 }, { 0, 0, 0 }, { 0.5, 0.5, 1.5 }, true, 4, 1., false ); + test( iterator, grid, { 1, 0, 1 }, { 0, 0, 0 }, { 1.5, 0.5, 1.5 }, true, 5, 1., false ); + + test( iterator, grid, { 0, 1, 1 }, { 0, 0, 0 }, { 0.5, 1.5, 1.5 }, true, 6, 1., false ); + test( iterator, grid, { 1, 1, 1 }, { 0, 0, 0 }, { 1.5, 1.5, 1.5 }, true, 7, 1., true ); +} + +#endif \ No newline at end of file diff --git a/src/UnitTests/Meshes/GridTests/Traverse/support.h b/src/UnitTests/Meshes/GridTests/Traverse/support.h new file mode 100644 index 0000000000000000000000000000000000000000..648c9cd17f2c433a64ee0c756c3a899f451e5918 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Traverse/support.h @@ -0,0 +1,505 @@ +#pragma once + +#ifdef HAVE_GTEST + +#include +#include + +#include +#include + +#include "../CoordinateIterator.h" +#include "../EntityDataStore.h" + +namespace Templates { +/* + * A compiler-friendly implementation of the templated for-cycle, because + * the template specializations count is O(Value) bounded. + */ +template +struct DescendingFor; + +template +struct DescendingFor { + public: + template + static void exec(Func func, FuncArgs&&... args) { + static_assert(Value > 0, "Couldn't descend for negative values"); + + func(std::integral_constant(), std::forward(args)...); + + DescendingFor::exec(std::forward(func), std::forward(args)...); + } +}; + +template <> +struct DescendingFor<0> { + public: + template + static void exec(Func func, FuncArgs&&... args) { + func(std::integral_constant(), std::forward(args)...); + } +}; + +} // namespace Templates + +template< typename Grid, int EntityDimension, int Orientation > +class GridCoordinateIterator : public CoordinateIterator< typename Grid::IndexType, Grid::getMeshDimension() > +{ +public: + using Coordinate = typename Grid::Coordinate; + using Point = typename Grid::Point; + using Index = typename Grid::IndexType; + using Real = typename Grid::RealType; + using Base = CoordinateIterator< Index, Grid::getMeshDimension() >; + using EntityBasis = TNL::Meshes::BasisGetter< Index, EntityDimension, Grid::getMeshDimension() >; + + GridCoordinateIterator( const typename Grid::Coordinate& end ) + : Base( Coordinate( 0 ), end + EntityBasis::template getBasis< Orientation >() ) + { + for( Index i = 0; i < this->current.getSize(); i++ ) { + this->start[ i ] = 0; + this->current[ i ] = 0; + } + } + + bool + isBoundary( const Grid& grid ) const + { + switch( EntityDimension ) { + case Grid::getMeshDimension(): + for( Index i = 0; i < this->current.getSize(); i++ ) + if( this->current[ i ] == 0 || this->current[ i ] == grid.getDimension( i ) - 1 ) + return true; + + break; + default: + for( Index i = 0; i < this->current.getSize(); i++ ) + if( getBasis()[ i ] && ( this->current[ i ] == 0 || this->current[ i ] == grid.getDimension( i ) ) ) + return true; + break; + } + + return false; + } + + Coordinate + getCoordinate() const + { + return this->current; + } + + Index + getIndex( const Grid& grid ) const + { + Index result = 0; + + for( Index i = 0; i < this->current.getSize(); i++ ) { + if( i == 0 ) { + result += this->current[ i ]; + } + else { + Index offset = 1; + + for( Index j = 0; j < i; j++ ) + offset *= this->end[ j ]; + + result += this->current[ i ] * offset; + } + } + + for( Index i = 0; i < Orientation; i++ ) + result += grid.getOrientedEntitiesCount( EntityDimension, i ); + + return result; + } + + Coordinate + getBasis() const + { + return EntityBasis::template getBasis< Orientation >(); + } + + Point + getCenter( const Grid& grid ) const + { + Point origin = grid.getOrigin(), center, spaceSteps = grid.getSpaceSteps(); + + Coordinate basis = getBasis(); + + for( Index i = 0; i < this->current.getSize(); i++ ) + center[ i ] = origin[ i ] + ( this->current[ i ] + (Real) ( 0.5 * ! basis[ i ] ) ) * spaceSteps[ i ]; + + return center; + } + + Real + getMeasure( const Grid& grid ) const + { + if( EntityDimension == 0 ) { + return 0.0; + } + + Coordinate basis = getBasis(), powers; + + for( Index i = 0; i < this->current.getSize(); i++ ) + powers[ i ] = ! basis[ i ]; + + return grid.getSpaceStepsProducts( powers ); + } +}; + +template +class GridTraverseTestCase { + public: + using Index = typename Grid::IndexType; + using Real = typename Grid::RealType; + using Coordinate = typename Grid::Coordinate; + using Point = typename Grid::Point; + using DataStore = EntityDataStore; + using HostDataStore = EntityDataStore; + + template + using Iterator = GridCoordinateIterator; + + // NVCC is incapable of deducing generic lambda + using UpdateFunctionType = std::function&)>; + + void storeAll(const Grid& grid, DataStore& store) const { + SCOPED_TRACE("Store all"); + + auto view = store.getView(); + + auto update = [=] __cuda_callable__ (const typename Grid::template EntityType& entity) mutable { + view.store(entity); + }; + + grid.template forAll(update); + } + void storeBoundary(const Grid& grid, DataStore& store) const { + SCOPED_TRACE("Store boundary"); + + auto view = store.getView(); + + auto update = [=] __cuda_callable__ (const typename Grid::template EntityType& entity) mutable { + view.store(entity); + }; + + grid.template forBoundary(update); + } + void storeInterior(const Grid& grid, DataStore& store) const { + SCOPED_TRACE("Store interior"); + + auto view = store.getView(); + + auto update = [=] __cuda_callable__ (const typename Grid::template EntityType& entity) mutable { + view.store(entity); + }; + + grid.template forInterior(update); + } + void clearAll(const Grid& grid, DataStore& store) const { + SCOPED_TRACE("Clear all"); + + auto view = store.getView(); + + auto update = [=] __cuda_callable__ (const typename Grid::template EntityType& entity) mutable { + view.clear(entity); + }; + + grid.template forAll(update); + } + void clearBoundary(const Grid& grid, DataStore& store) const { + SCOPED_TRACE("Clear boundary"); + + auto view = store.getView(); + + auto update = [=] __cuda_callable__ (const typename Grid::template EntityType& entity) mutable { + view.clear(entity); + }; + + grid.template forBoundary(update); + } + void clearInterior(const Grid& grid, DataStore& store) const { + SCOPED_TRACE("Clear interior"); + + auto view = store.getView(); + + auto update = [=] __cuda_callable__ (const typename Grid::template EntityType& entity) mutable { + view.clear(entity); + }; + + grid.template forInterior(update); + } + + void verifyAll(const Grid& grid, const DataStore& store) const { + auto hostStore = store.template move(); + auto hostStoreView = hostStore.getView(); + + constexpr int orientationsCount = Grid::getEntityOrientationsCount(EntityDimension); + + SCOPED_TRACE("Verifying forAll"); + SCOPED_TRACE("Orientations Count: " + TNL::convertToString(orientationsCount)); + + ASSERT_GT(orientationsCount, 0) << "Every entity must have at least one orientation"; + + auto callsView = hostStore.getCallsView(); + + for (Index i = 0; i < callsView.getSize(); i++) + EXPECT_EQ(callsView[i], 1) << "Expect each index to be called only once"; + + auto verify = [&](const auto orientation) { + Iterator iterator(grid.getDimensions()); + + if (!iterator.canIterate()) { + SCOPED_TRACE("Skip iteration"); + EXPECT_EQ(callsView.getSize(), 0) << "Expect, that we can't iterate, when grid is empty"; + return; + } + + do { + verifyEntity(grid, iterator, hostStoreView, true); + } while (!iterator.next()); + }; + + Templates::DescendingFor::exec(verify); + } + void verifyBoundary(const Grid& grid, const DataStore& store) const { + auto hostStore = store.template move(); + auto hostStoreView = hostStore.getView(); + + constexpr int orientationsCount = Grid::getEntityOrientationsCount(EntityDimension); + + SCOPED_TRACE("Verifying forBoundary"); + SCOPED_TRACE("Orientations Count: " + TNL::convertToString(orientationsCount)); + + ASSERT_GT(orientationsCount, 0) << "Every entity must have at least one orientation"; + + auto verify = [&](const auto orientation) { + Iterator iterator(grid.getDimensions()); + + if (!iterator.canIterate()) { + SCOPED_TRACE("Skip iteration"); + EXPECT_EQ(hostStore.getCallsView().getSize(), 0) << "Expect, that we can't iterate, when grid is empty"; + return; + } + + do { + verifyEntity(grid, iterator, hostStoreView, iterator.isBoundary(grid)); + } while (!iterator.next()); + }; + + Templates::DescendingFor::exec(verify); + } + void verifyInterior(const Grid& grid, const DataStore& store) const { + auto hostStore = store.template move(); + auto hostStoreView = hostStore.getView(); + + constexpr int orientationsCount = Grid::getEntityOrientationsCount(EntityDimension); + + SCOPED_TRACE("Verifying forInterior"); + SCOPED_TRACE("Orientations Count: " + TNL::convertToString(orientationsCount)); + + ASSERT_GT(orientationsCount, 0) << "Every entity must have at least one orientation"; + + auto verify = [&](const auto orientation) { + Iterator iterator(grid.getDimensions()); + + if (!iterator.canIterate()) { + SCOPED_TRACE("Skip iteration"); + EXPECT_EQ(hostStore.getCallsView().getSize(), 0) << "Expect, that we can't iterate, when grid is empty"; + return; + } + + do { + verifyEntity(grid, iterator, hostStoreView, !iterator.isBoundary(grid)); + } while (!iterator.next()); + }; + + Templates::DescendingFor::exec(verify); + } + private: + template + void verifyEntity(const Grid& grid, + const Iterator& iterator, + typename HostDataStore::View& dataStore, + bool expectCall) const { + static Real precision = 9e-5; + + auto index = iterator.getIndex(grid); + auto entity = dataStore.getEntity(index); + + SCOPED_TRACE("Entity: " + TNL::convertToString(entity)); + + EXPECT_EQ(entity.calls, expectCall ? 1 : 0) << "Expect the index to be called once"; + EXPECT_EQ(entity.index, expectCall ? index : 0) << "Expect the index was correctly set"; + EXPECT_EQ(entity.isBoundary, expectCall ? iterator.isBoundary(grid) : 0) << "Expect the index was correctly set" ; + + Coordinate coordinate = expectCall ? iterator.getCoordinate() : Coordinate(0); + Coordinate basis = expectCall ? iterator.getBasis() : Coordinate(0); + Point center = expectCall ? iterator.getCenter(grid) : Point(0); + + EXPECT_EQ(entity.coordinate, coordinate) + << "Expect the coordinates are the same on the same index. "; + EXPECT_EQ(entity.basis, basis) + << "Expect the bases are the same on the same index. "; + + // CUDA calculates floating points differently. + EXPECT_NEAR(expectCall ? iterator.getMeasure(grid) : 0.0, entity.measure, precision) + << "Expect the measure was correctly calculated. "; + + for (Index i = 0; i < Grid::getMeshDimension(); i++) + EXPECT_NEAR(entity.center[i], center[i], precision) + << "Expect the centers are the same on the same index. " << entity.center << " " << center; + } +}; + +template +void testForAllTraverse(Grid& grid, + const typename Grid::Coordinate& dimensions, + const typename Grid::Point& origin = typename Grid::Point(0), + const typename Grid::Point& spaceSteps = typename Grid::Point(1)) { + SCOPED_TRACE("Grid Dimension: " + TNL::convertToString(Grid::getMeshDimension())); + SCOPED_TRACE("Entity Dimension: " + TNL::convertToString(EntityDimension)); + SCOPED_TRACE("Dimension: " + TNL::convertToString(dimensions)); + SCOPED_TRACE("Origin:" + TNL::convertToString(origin)); + SCOPED_TRACE("Space steps:" + TNL::convertToString(spaceSteps)); + + EXPECT_NO_THROW(grid.setDimensions(dimensions)) << "Verify, that the set of" << dimensions << " doesn't cause assert"; + EXPECT_NO_THROW(grid.setOrigin(origin)) << "Verify, that the set of" << origin << "doesn't cause assert"; + EXPECT_NO_THROW(grid.setSpaceSteps(spaceSteps)) << "Verify, that the set of" << spaceSteps << "doesn't cause assert"; + + using Test = GridTraverseTestCase; + + Test test; + typename Test::DataStore store(grid.getEntitiesCount(EntityDimension)); + + test.storeAll(grid, store); + test.verifyAll(grid, store); +} + +template +void testForInteriorTraverse(Grid& grid, + const typename Grid::Coordinate& dimensions, + const typename Grid::Point& origin = typename Grid::Point(0), + const typename Grid::Point& spaceSteps = typename Grid::Point(1)) { + SCOPED_TRACE("Grid Dimension: " + TNL::convertToString(Grid::getMeshDimension())); + SCOPED_TRACE("Entity Dimension: " + TNL::convertToString(EntityDimension)); + SCOPED_TRACE("Dimension: " + TNL::convertToString(dimensions)); + SCOPED_TRACE("Origin:" + TNL::convertToString(origin)); + SCOPED_TRACE("Space steps:" + TNL::convertToString(spaceSteps)); + + EXPECT_NO_THROW(grid.setDimensions(dimensions)) << "Verify, that the set of" << dimensions << " doesn't cause assert"; + EXPECT_NO_THROW(grid.setOrigin(origin)) << "Verify, that the set of" << origin << "doesn't cause assert"; + EXPECT_NO_THROW(grid.setSpaceSteps(spaceSteps)) << "Verify, that the set of" << spaceSteps << "doesn't cause assert"; + + using Test = GridTraverseTestCase; + + Test test; + typename Test::DataStore store(grid.getEntitiesCount(EntityDimension)); + + test.storeInterior(grid, store); + test.verifyInterior(grid, store); +} + +template +void testForBoundaryTraverse(Grid& grid, + const typename Grid::Coordinate& dimensions, + const typename Grid::Point& origin = typename Grid::Point(0), + const typename Grid::Point& spaceSteps = typename Grid::Point(1)) { + SCOPED_TRACE("Grid Dimension: " + TNL::convertToString(Grid::getMeshDimension())); + SCOPED_TRACE("Entity Dimension: " + TNL::convertToString(EntityDimension)); + SCOPED_TRACE("Dimension: " + TNL::convertToString(dimensions)); + SCOPED_TRACE("Origin:" + TNL::convertToString(origin)); + SCOPED_TRACE("Space steps:" + TNL::convertToString(spaceSteps)); + + EXPECT_NO_THROW(grid.setDimensions(dimensions)) << "Verify, that the set of" << dimensions << " doesn't cause assert"; + EXPECT_NO_THROW(grid.setOrigin(origin)) << "Verify, that the set of" << origin << "doesn't cause assert"; + EXPECT_NO_THROW(grid.setSpaceSteps(spaceSteps)) << "Verify, that the set of" << spaceSteps << "doesn't cause assert"; + + using Test = GridTraverseTestCase; + + Test test; + typename Test::DataStore store(grid.getEntitiesCount(EntityDimension)); + + test.storeBoundary(grid, store); + test.verifyBoundary(grid, store); +} + +template +void testBoundaryUnionInteriorEqualAllProperty(Grid& grid, + const typename Grid::Coordinate& dimensions, + const typename Grid::Point& origin = typename Grid::Point(0), + const typename Grid::Point& spaceSteps = typename Grid::Point(1)) { + SCOPED_TRACE("Grid Dimension: " + TNL::convertToString(Grid::getMeshDimension())); + SCOPED_TRACE("Entity Dimension: " + TNL::convertToString(EntityDimension)); + SCOPED_TRACE("Dimension: " + TNL::convertToString(dimensions)); + SCOPED_TRACE("Origin:" + TNL::convertToString(origin)); + SCOPED_TRACE("Space steps:" + TNL::convertToString(spaceSteps)); + + EXPECT_NO_THROW(grid.setDimensions(dimensions)) << "Verify, that the set of" << dimensions << " doesn't cause assert"; + EXPECT_NO_THROW(grid.setOrigin(origin)) << "Verify, that the set of" << origin << "doesn't cause assert"; + EXPECT_NO_THROW(grid.setSpaceSteps(spaceSteps)) << "Verify, that the set of" << spaceSteps << "doesn't cause assert"; + + using Test = GridTraverseTestCase; + + Test test; + typename Test::DataStore store(grid.getEntitiesCount(EntityDimension)); + + test.storeBoundary(grid, store); + test.storeInterior(grid, store); + test.verifyAll(grid, store); +} + +template +void testAllMinusBoundaryEqualInteriorProperty(Grid& grid, + const typename Grid::Coordinate& dimensions, + const typename Grid::Point& origin = typename Grid::Point(0), + const typename Grid::Point& spaceSteps = typename Grid::Point(1)) { + SCOPED_TRACE("Grid Dimension: " + TNL::convertToString(Grid::getMeshDimension())); + SCOPED_TRACE("Entity Dimension: " + TNL::convertToString(EntityDimension)); + SCOPED_TRACE("Dimension: " + TNL::convertToString(dimensions)); + SCOPED_TRACE("Origin:" + TNL::convertToString(origin)); + SCOPED_TRACE("Space steps:" + TNL::convertToString(spaceSteps)); + + EXPECT_NO_THROW(grid.setDimensions(dimensions)) << "Verify, that the set of" << dimensions << " doesn't cause assert"; + EXPECT_NO_THROW(grid.setOrigin(origin)) << "Verify, that the set of" << origin << "doesn't cause assert"; + EXPECT_NO_THROW(grid.setSpaceSteps(spaceSteps)) << "Verify, that the set of" << spaceSteps << "doesn't cause assert"; + + using Test = GridTraverseTestCase; + + Test test; + typename Test::DataStore store(grid.getEntitiesCount(EntityDimension)); + + test.storeAll(grid, store); + test.clearBoundary(grid, store); + test.verifyInterior(grid, store); +} + +template +void testAllMinusInteriorEqualBoundaryProperty(Grid& grid, + const typename Grid::Coordinate& dimensions, + const typename Grid::Point& origin = typename Grid::Point(0), + const typename Grid::Point& spaceSteps = typename Grid::Point(1)) { + SCOPED_TRACE("Grid Dimension: " + TNL::convertToString(Grid::getMeshDimension())); + SCOPED_TRACE("Entity Dimension: " + TNL::convertToString(EntityDimension)); + SCOPED_TRACE("Dimension: " + TNL::convertToString(dimensions)); + SCOPED_TRACE("Origin:" + TNL::convertToString(origin)); + SCOPED_TRACE("Space steps:" + TNL::convertToString(spaceSteps)); + + EXPECT_NO_THROW(grid.setDimensions(dimensions)) << "Verify, that the set of" << dimensions << " doesn't cause assert"; + EXPECT_NO_THROW(grid.setOrigin(origin)) << "Verify, that the set of" << origin << "doesn't cause assert"; + EXPECT_NO_THROW(grid.setSpaceSteps(spaceSteps)) << "Verify, that the set of" << spaceSteps << "doesn't cause assert"; + + using Test = GridTraverseTestCase; + + Test test; + typename Test::DataStore store(grid.getEntitiesCount(EntityDimension)); + + test.storeAll(grid, store); + test.clearInterior(grid, store); + test.verifyBoundary(grid, store); +} + + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Utils/CMakeLists.txt b/src/UnitTests/Meshes/GridTests/Utils/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..fcdcf2db50f8fdef0f766d76bf1bff501c6a3f71 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Utils/CMakeLists.txt @@ -0,0 +1,8 @@ +include("../CMakeSupport.cmake") + +SET(SOME_ARGS "") + +generate_executables(GridBasisTest.h "Utils" "../../../main.h" SOME_ARGS) +generate_executables(GridTemplatesTest.h "Utils" "../../../main.h" SOME_ARGS) +generate_executables(EntityDataStoreTest.h "Utils" "../../../main.h" SOME_ARGS) +generate_executables(CoordinateIteratorTest.h "Utils" "../../../main.h" SOME_ARGS) \ No newline at end of file diff --git a/src/UnitTests/Meshes/GridTests/Utils/CoordinateIteratorTest.cpp b/src/UnitTests/Meshes/GridTests/Utils/CoordinateIteratorTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6af619802e6b940e4742511554e9f5dfe5827779 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Utils/CoordinateIteratorTest.cpp @@ -0,0 +1,3 @@ + +#include "CoordinateIteratorTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Utils/CoordinateIteratorTest.cu b/src/UnitTests/Meshes/GridTests/Utils/CoordinateIteratorTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..6af619802e6b940e4742511554e9f5dfe5827779 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Utils/CoordinateIteratorTest.cu @@ -0,0 +1,3 @@ + +#include "CoordinateIteratorTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Utils/CoordinateIteratorTest.h b/src/UnitTests/Meshes/GridTests/Utils/CoordinateIteratorTest.h new file mode 100644 index 0000000000000000000000000000000000000000..629b5b9d7429b4d5b80eaff02bdb5e4e4ae0668a --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Utils/CoordinateIteratorTest.h @@ -0,0 +1,84 @@ + +#pragma once + +#ifdef HAVE_GTEST + +#include +#include "../CoordinateIterator.h" + +template +void test(Iterator& iterator, const typename Iterator::Coordinate& coordinate, bool canIterate, bool next) { + SCOPED_TRACE("Coordinate: " + TNL::convertToString(coordinate)); + SCOPED_TRACE("Can iterate: " + TNL::convertToString(canIterate)); + SCOPED_TRACE("Next: " + TNL::convertToString(next)); + + EXPECT_EQ(iterator.getCoordinate(), coordinate); + EXPECT_EQ(iterator.canIterate(), canIterate); + EXPECT_EQ(iterator.next(), next); +} + +TEST(CoordinateIteratorTest, ZeroStartIterator1D) { + CoordinateIterator iterator({ 0 }, { 3 }); + + test(iterator, { 0 }, true, false); + test(iterator, { 1 }, true, false); + test(iterator, { 2 }, true, true); +} + +TEST(CoordinateIteratorTest, ZeroStartIterator2D) { + CoordinateIterator iterator({ 0, 0 }, { 3, 3 }); + + test(iterator, { 0, 0 }, true, false); + test(iterator, { 1, 0 }, true, false); + test(iterator, { 2, 0 }, true, false); + test(iterator, { 0, 1 }, true, false); + test(iterator, { 1, 1 }, true, false); + test(iterator, { 2, 1 }, true, false); + test(iterator, { 0, 2 }, true, false); + test(iterator, { 1, 2 }, true, false); + test(iterator, { 2, 2 }, true, true); +} + +TEST(CoordinateIteratorTest, ZeroStartIterator3D) { + CoordinateIterator iterator({ 0, 0, 0 }, { 2, 2, 2 }); + + test(iterator, { 0, 0, 0 }, true, false); + test(iterator, { 1, 0, 0 }, true, false); + test(iterator, { 0, 1, 0 }, true, false); + test(iterator, { 1, 1, 0 }, true, false); + test(iterator, { 0, 0, 1 }, true, false); + test(iterator, { 1, 0, 1 }, true, false); + test(iterator, { 0, 1, 1 }, true, false); + test(iterator, { 1, 1, 1 }, true, true); +} + +TEST(CoordinateIteratorTest, SomeStartIterator1D) { + CoordinateIterator iterator({ 1 }, { 3 }); + + test(iterator, { 1 }, true, false); + test(iterator, { 2 }, true, true); +} + +TEST(CoordinateIteratorTest, SomeStartIterator2D) { + CoordinateIterator iterator({ 1, 1 }, { 3, 3 }); + + test(iterator, { 1, 1 }, true, false); + test(iterator, { 2, 1 }, true, false); + test(iterator, { 1, 2 }, true, false); + test(iterator, { 2, 2 }, true, true); +} + +TEST(CoordinateIteratorTest, SomeStartIterator3D) { + CoordinateIterator iterator({ 1, 1, 1 }, { 3, 3, 3 }); + + test(iterator, { 1, 1, 1 }, true, false); + test(iterator, { 2, 1, 1 }, true, false); + test(iterator, { 1, 2, 1 }, true, false); + test(iterator, { 2, 2, 1 }, true, false); + test(iterator, { 1, 1, 2 }, true, false); + test(iterator, { 2, 1, 2 }, true, false); + test(iterator, { 1, 2, 2 }, true, false); + test(iterator, { 2, 2, 2 }, true, true); +} + +#endif \ No newline at end of file diff --git a/src/UnitTests/Meshes/GridTests/Utils/EntityDataStoreTest.cpp b/src/UnitTests/Meshes/GridTests/Utils/EntityDataStoreTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..edf4c276c16ba05463c38fa897cde2391f68b4af --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Utils/EntityDataStoreTest.cpp @@ -0,0 +1,3 @@ + +#include "EntityDataStoreTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Utils/EntityDataStoreTest.cu b/src/UnitTests/Meshes/GridTests/Utils/EntityDataStoreTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..edf4c276c16ba05463c38fa897cde2391f68b4af --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Utils/EntityDataStoreTest.cu @@ -0,0 +1,3 @@ + +#include "EntityDataStoreTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Utils/EntityDataStoreTest.h b/src/UnitTests/Meshes/GridTests/Utils/EntityDataStoreTest.h new file mode 100644 index 0000000000000000000000000000000000000000..f2934c432580076a91ced62a5f4b27be5cea66f0 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Utils/EntityDataStoreTest.h @@ -0,0 +1,132 @@ +#pragma once + +#ifdef HAVE_GTEST + +#include +#include + +#include "../EntityDataStore.h" + +using Index = int; +using Real = float; +using Device = TNL::Devices::Host; + +template +void testTraverse(const Grid& grid, DataStore& dataStore, int entitiesCount ) { + auto view = dataStore.getView(); + + auto exec = [ & ]( const auto orientation, const typename Grid::Coordinate& basis ) { + for(typename Grid::IndexType i = 0; i < entitiesCount; i++) { + typename Grid::Coordinate coordinate; + + coordinate = i; + + GridEntity entity(grid, coordinate, basis, orientation); + + view.store(entity, i); + + auto prototype = view.getEntity(i); + + SCOPED_TRACE("Prototype: " + TNL::convertToString(prototype)); + + EXPECT_EQ(1, prototype.calls); + EXPECT_EQ(entity.getCoordinates(), prototype.coordinate); + EXPECT_EQ(entity.getBasis(), prototype.basis); + EXPECT_EQ(entity.getIndex(), prototype.index); + EXPECT_EQ(entity.getOrientation(), prototype.orientation); + EXPECT_EQ(entity.isBoundary(), prototype.isBoundary); + EXPECT_EQ(entity.getCenter(), prototype.center); + EXPECT_EQ(entity.getMeasure(), prototype.measure); + + view.clear(i); + + auto emptyPrototype = view.getEntity(i); + + typename Grid::Coordinate zeroCoordinate = 0; + typename Grid::Point zeroPoint = 0; + + EXPECT_EQ(0, emptyPrototype.calls); + EXPECT_EQ(zeroCoordinate, emptyPrototype.coordinate); + EXPECT_EQ(zeroCoordinate, emptyPrototype.basis); + EXPECT_EQ(0, emptyPrototype.index); + EXPECT_EQ(0, emptyPrototype.orientation); + EXPECT_EQ(false, emptyPrototype.isBoundary); + EXPECT_EQ(zeroPoint, emptyPrototype.center); + EXPECT_EQ(0., emptyPrototype.measure); + } + }; + + TNL::Meshes::Templates::ForEachOrientation< + Index, GridEntity::entityDimension, Grid::getMeshDimension() + >::exec( exec ); +} + +TEST(EntityDataStoreTest, DataStore1DTest) { + constexpr int Dimension = 1; + using Grid = TNL::Meshes::Grid; + using DataStore = EntityDataStore; + + using ZeroDimensionEntity = TNL::Meshes::GridEntity; + using OneDimensionEntity = TNL::Meshes::GridEntity; + + Index entitiesCount = 10; + + Grid grid; + grid.setDimensions(entitiesCount + 1); + grid.setSpaceSteps(1.); + + DataStore store(entitiesCount); + + testTraverse(grid, store, entitiesCount); + testTraverse(grid, store, entitiesCount); +} + +TEST(EntityDataStoreTest, DataStore2DTest) { + constexpr int Dimension = 2; + + using Grid = TNL::Meshes::Grid; + using DataStore = EntityDataStore; + + using ZeroDimensionEntity = TNL::Meshes::GridEntity; + using OneDimensionEntity = TNL::Meshes::GridEntity; + using TwoDimensionEntity = TNL::Meshes::GridEntity; + + Index entitiesCount = 10; + + Grid grid; + grid.setDimensions(entitiesCount + 1, entitiesCount + 1); + grid.setSpaceSteps(1., 1.); + + DataStore store(entitiesCount); + + testTraverse(grid, store, entitiesCount); + testTraverse(grid, store, entitiesCount); + testTraverse(grid, store, entitiesCount); +} + +TEST(EntityDataStoreTest, DataStore3DTest) { + constexpr int Dimension = 3; + + using Grid = TNL::Meshes::Grid; + using DataStore = EntityDataStore; + + using ZeroDimensionEntity = TNL::Meshes::GridEntity; + using OneDimensionEntity = TNL::Meshes::GridEntity; + using TwoDimensionEntity = TNL::Meshes::GridEntity; + using ThreeDimensionEntity = TNL::Meshes::GridEntity; + + Index entitiesCount = 10; + + Grid grid; + grid.setDimensions(entitiesCount + 1, entitiesCount + 1, entitiesCount + 1); + grid.setSpaceSteps(1., 1., 1.); + + DataStore store(entitiesCount); + + testTraverse(grid, store, entitiesCount); + testTraverse(grid, store, entitiesCount); + testTraverse(grid, store, entitiesCount); + testTraverse(grid, store, entitiesCount); +} + +#endif \ No newline at end of file diff --git a/src/UnitTests/Meshes/GridTests/Utils/GridBasisTest.cpp b/src/UnitTests/Meshes/GridTests/Utils/GridBasisTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f8c12abefcef57d6b55af455ec82970c627d506d --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Utils/GridBasisTest.cpp @@ -0,0 +1,3 @@ + +#include "GridBasisTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Utils/GridBasisTest.cu b/src/UnitTests/Meshes/GridTests/Utils/GridBasisTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..f8c12abefcef57d6b55af455ec82970c627d506d --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Utils/GridBasisTest.cu @@ -0,0 +1,3 @@ + +#include "GridBasisTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Utils/GridBasisTest.h b/src/UnitTests/Meshes/GridTests/Utils/GridBasisTest.h new file mode 100644 index 0000000000000000000000000000000000000000..1e51178aa8d009109046263858974a6272ba6eb1 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Utils/GridBasisTest.h @@ -0,0 +1,75 @@ +#pragma once + +#ifdef HAVE_GTEST + +#include + +#include +#include + +template +void compare(const TNL::Containers::StaticVector& expectation) { + auto basis = TNL::Meshes::BasisGetter::template getBasis(); + + EXPECT_EQ(basis, expectation) << "Grid Dimension: [" << GridDimension << "], " + << "Entity Orientation: [" << EntityOrientation << "], " + << "Entity Dimension: [" << EntityDimension << "]"; +} + +TEST(BasisTestSuite, Basis1DTest) { + // Grid Dimension, EntityOrientation, EntityDimension + compare<1, 0, 0>({ 1 }); + compare<1, 0, 1>({ 0 }); +} + +TEST(BasisTestSuite, Basis2DTest) { + // Grid Dimension, EntityOrientation, EntityDimension + compare<2, 0, 0>({ 1, 1 }); + + compare<2, 0, 1>({ 0, 1 }); + compare<2, 1, 1>({ 1, 0 }); + + compare<2, 0, 2>({ 0, 0 }); +} + +TEST(BasisTestSuite, Basis3DTest) { + // Grid Dimension, EntityOrientation, EntityDimension + compare<3, 0, 0>({ 1, 1, 1 }); + + compare<3, 0, 1>({ 0, 1, 1 }); + compare<3, 1, 1>({ 1, 0, 1 }); + compare<3, 2, 1>({ 1, 1, 0 }); + + compare<3, 0, 2>({ 0, 0, 1 }); + compare<3, 1, 2>({ 0, 1, 0 }); + compare<3, 2, 2>({ 1, 0, 0 }); + + compare<3, 0, 3>({ 0, 0, 0 }); +} + +TEST(BasisTestSuite, Basis4DTest) { + // Grid Dimension, EntityOrientation, EntityDimension + compare<4, 0, 0>({ 1, 1, 1, 1 }); + + compare<4, 0, 1>({ 0, 1, 1, 1 }); + compare<4, 1, 1>({ 1, 0, 1, 1 }); + compare<4, 2, 1>({ 1, 1, 0, 1 }); + compare<4, 3, 1>({ 1, 1, 1, 0 }); + + compare<4, 0, 2>({ 0, 0, 1, 1 }); + compare<4, 1, 2>({ 0, 1, 0, 1 }); + compare<4, 2, 2>({ 0, 1, 1, 0 }); + compare<4, 3, 2>({ 1, 0, 0, 1 }); + compare<4, 4, 2>({ 1, 0, 1, 0 }); + compare<4, 5, 2>({ 1, 1, 0, 0 }); + + compare<4, 0, 3>({ 0, 0, 0, 1 }); + compare<4, 1, 3>({ 0, 0, 1, 0 }); + compare<4, 2, 3>({ 0, 1, 0, 0 }); + compare<4, 3, 3>({ 1, 0, 0, 0 }); + + compare<4, 0, 4>({ 0, 0, 0, 0 }); +} + + +#endif diff --git a/src/UnitTests/Meshes/GridTests/Utils/GridTemplatesTest.cpp b/src/UnitTests/Meshes/GridTests/Utils/GridTemplatesTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..130914e228890a2ce95532c9083aed0d07810239 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Utils/GridTemplatesTest.cpp @@ -0,0 +1,3 @@ + +#include "GridTemplatesTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Utils/GridTemplatesTest.cu b/src/UnitTests/Meshes/GridTests/Utils/GridTemplatesTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..130914e228890a2ce95532c9083aed0d07810239 --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Utils/GridTemplatesTest.cu @@ -0,0 +1,3 @@ + +#include "GridTemplatesTest.h" +#include "../../../main.h" diff --git a/src/UnitTests/Meshes/GridTests/Utils/GridTemplatesTest.h b/src/UnitTests/Meshes/GridTests/Utils/GridTemplatesTest.h new file mode 100644 index 0000000000000000000000000000000000000000..bfec227cb45e8f5107d93b990d1c240d5af3b92d --- /dev/null +++ b/src/UnitTests/Meshes/GridTests/Utils/GridTemplatesTest.h @@ -0,0 +1,122 @@ +#pragma once + +#ifdef HAVE_GTEST + +#include + +#include +#include "../CoordinateIterator.h" + +void testCombination(const int k, const int n, const int expectation) { + EXPECT_EQ(TNL::Meshes::Templates::combination(k, n), expectation) << k << " " << n; +} + +TEST(TemplatesTestSuite, CombinationsTest) { + testCombination(0, 1, 1); + testCombination(1, 1, 1); + + testCombination(0, 2, 1); + testCombination(1, 2, 2); + testCombination(2, 2, 1); + + testCombination(0, 3, 1); + testCombination(1, 3, 3); + testCombination(2, 3, 3); + testCombination(3, 3, 1); + + testCombination(0, 4, 1); + testCombination(1, 4, 4); + testCombination(2, 4, 6); + testCombination(3, 4, 4); + testCombination(4, 4, 1); +} + +void testCombinationSum(const int k, const int n, const int expectation) { + EXPECT_EQ(TNL::Meshes::Templates::firstKCombinationSum(k, n), expectation) << k << " " << n; +} + +TEST(TemplatesTestSuite, FirstKCombinationsTest) { + testCombinationSum(0, 1, 0); + testCombinationSum(1, 1, 1); + + testCombinationSum(0, 2, 0); + testCombinationSum(1, 2, 1); + testCombinationSum(2, 2, 3); + + testCombinationSum(0, 3, 0); + testCombinationSum(1, 3, 1); + testCombinationSum(2, 3, 4); + testCombinationSum(3, 3, 7); + + testCombinationSum(0, 4, 0); + testCombinationSum(1, 4, 1); + testCombinationSum(2, 4, 5); + testCombinationSum(3, 4, 11); + testCombinationSum(4, 4, 15); +} + +template +using Coordinate = TNL::Containers::StaticVector; + +template +void testIndexCollapse(const int base) { + SCOPED_TRACE("Coordinate size: " + TNL::convertToString(Size)); + SCOPED_TRACE("Base: " + TNL::convertToString(base)); + + const int halfBase = base >> 1; + Coordinate start, end; + + for (int i = 0; i < Size; i++) { + start[i] = -halfBase; + // Want to traverse + end[i] = halfBase + 1; + } + + CoordinateIterator iterator(start, end); + + int index = 0; + + do { + EXPECT_EQ(TNL::Meshes::Templates::makeCollapsedIndex(base, iterator.getCoordinate()), index) + << base << " " << index << " " << iterator.getCoordinate(); + index++; + } while (!iterator.next()); +} + +TEST(TemplatesTestSuite, IndexCollapseTest) { + testIndexCollapse<1>(3); + testIndexCollapse<2>(3); + testIndexCollapse<3>(3); + testIndexCollapse<4>(3); + + testIndexCollapse<1>(5); + testIndexCollapse<2>(5); + testIndexCollapse<3>(5); + testIndexCollapse<4>(5); +} + +void testPower(const size_t value, const size_t power, const size_t expectation) { + EXPECT_EQ(TNL::Meshes::Templates::pow(value, power), expectation) << value<< " " << power; +} + +TEST(TemplatesTestSuite, PowerTest) { + testPower(0, 1, 0); + testPower(1, 1, 1); + + testPower(0, 2, 0); + testPower(1, 2, 1); + testPower(2, 2, 4); + + testPower(0, 3, 0); + testPower(1, 3, 1); + testPower(2, 3, 8); + testPower(3, 3, 27); + + testPower(0, 4, 0); + testPower(1, 4, 1); + testPower(2, 4, 16); + testPower(3, 4, 81); + testPower(4, 4, 256); +} + +#endif diff --git a/src/UnitTests/Meshes/VTIReaderTest.cpp b/src/UnitTests/Meshes/VTIReaderTest.cpp index b0c6847ba48997ddd98b62135b52cb66ce59cafc..d51fb102c5671601cd1e6196877ec3ef1ea30414 100644 --- a/src/UnitTests/Meshes/VTIReaderTest.cpp +++ b/src/UnitTests/Meshes/VTIReaderTest.cpp @@ -1,3 +1,4 @@ + #ifdef HAVE_GTEST #include @@ -34,8 +35,8 @@ template<> struct GridRealTag< MyConfigTag, long double > { static constexpr boo TEST( VTIReaderTest, Grid1D ) { using GridType = Grid< 1, double, TNL::Devices::Host, short int >; - using PointType = GridType::PointType; - using CoordinatesType = GridType::CoordinatesType; + using PointType = GridType::Point; + using CoordinatesType = GridType::Coordinate; GridType grid; grid.setDomain( PointType( 1 ), PointType( 2 ) ); @@ -50,8 +51,8 @@ TEST( VTIReaderTest, Grid1D ) TEST( VTIReaderTest, Grid2D ) { using GridType = Grid< 2, double, TNL::Devices::Host, int >; - using PointType = GridType::PointType; - using CoordinatesType = GridType::CoordinatesType; + using PointType = GridType::Point; + using CoordinatesType = GridType::Coordinate; GridType grid; grid.setDomain( PointType( 1, 2 ), PointType( 3, 4 ) ); @@ -66,8 +67,8 @@ TEST( VTIReaderTest, Grid2D ) TEST( VTIReaderTest, Grid3D ) { using GridType = Grid< 3, double, TNL::Devices::Host, long int >; - using PointType = GridType::PointType; - using CoordinatesType = GridType::CoordinatesType; + using PointType = GridType::Point; + using CoordinatesType = GridType::Coordinate; GridType grid; grid.setDomain( PointType( 1, 2, 3 ), PointType( 4, 5, 6 ) );