diff --git a/src/Python/pytnl/tnl/Array.h b/src/Python/pytnl/tnl/Array.h index b92f22f0d76be53a73037475a60e44e802aaf51f..b39fe6b0e7ee750aa6cd845e93984bb914e3563e 100644 --- a/src/Python/pytnl/tnl/Array.h +++ b/src/Python/pytnl/tnl/Array.h @@ -8,6 +8,21 @@ namespace py = pybind11; #include <TNL/Containers/Array.h> + +// pybind11 should actually take care of this inside py::format_descriptor, but apparently it does not work... +// see https://github.com/pybind/pybind11/issues/2135 +template< typename T, typename = void > +struct underlying_type +{ + using type = T; +}; +template< typename T > +struct underlying_type< T, std::enable_if_t< std::is_enum< T >::value > > +{ + using type = std::underlying_type_t< T >; +}; + + template< typename ArrayType > void export_Array(py::module & m, const char* name) { @@ -49,7 +64,9 @@ void export_Array(py::module & m, const char* name) // Size of one scalar sizeof( typename ArrayType::ValueType ), // Python struct-style format descriptor - py::format_descriptor< typename ArrayType::ValueType >::format(), + py::format_descriptor< + typename underlying_type< typename ArrayType::ValueType >::type + >::format(), // Number of dimensions 1, // Buffer dimensions diff --git a/src/TNL/Assert.h b/src/TNL/Assert.h index 630abd09fd04272144c47e4bbfeff17f2d6442a4..99f833d24ee251c18e6c6bea16863a8b4dc0a829 100644 --- a/src/TNL/Assert.h +++ b/src/TNL/Assert.h @@ -121,7 +121,6 @@ #include <stdio.h> #include <TNL/Cuda/CudaCallable.h> -#include <TNL/Debugging/StackBacktrace.h> namespace TNL { /** @@ -164,8 +163,6 @@ printDiagnosticsHost( const char* assertion, << "Line: " << line << "\n" << "Diagnostics:\n" << diagnostics << std::endl; - PrintStackBacktrace; - throw AssertionError( str.str() ); } @@ -186,8 +183,6 @@ printDiagnosticsHost( const char* assertion, << "Function: " << function << "\n" << "Line: " << line << "\n" << "Diagnostics:\n" << diagnostics << std::endl; - - PrintStackBacktrace; } #endif // TNL_THROW_ASSERTION_ERROR diff --git a/src/TNL/Communicators/MPIPrint.h b/src/TNL/Communicators/MPIPrint.h index 825ae239f92487358a3eeae71479a8624025fc5e..6d78eafaf8c67c1c770faf01fa879d4b31b4032a 100644 --- a/src/TNL/Communicators/MPIPrint.h +++ b/src/TNL/Communicators/MPIPrint.h @@ -24,8 +24,8 @@ else std::stringstream __tnl_mpi_print_stream_; \ __tnl_mpi_print_stream_ << "Node " << TNL::Communicators::MpiCommunicator::GetRank() << " of " \ << TNL::Communicators::MpiCommunicator::GetSize() << " : " << message << std::endl; \ - TNL::String __tnl_mpi_print_string_( __tnl_mpi_print_stream_.str().c_str() ); \ - mpiSend( __tnl_mpi_print_string_, 0, std::numeric_limits< int >::max() ); \ + TNL::String __tnl_mpi_print_string_( __tnl_mpi_print_stream_.str() ); \ + mpiSend( __tnl_mpi_print_string_, 0, std::numeric_limits< int >::max() ); \ } \ else \ { \ @@ -35,7 +35,7 @@ else __tnl_mpi_print_j++ ) \ { \ TNL::String __tnl_mpi_print_string_; \ - mpiReceive( __tnl_mpi_print_string_, __tnl_mpi_print_j, std::numeric_limits< int >::max() ); \ + mpiReceive( __tnl_mpi_print_string_, __tnl_mpi_print_j, std::numeric_limits< int >::max() ); \ std::cerr << __tnl_mpi_print_string_; \ } \ } \ @@ -77,8 +77,8 @@ else std::stringstream __tnl_mpi_print_stream_; \ __tnl_mpi_print_stream_ << "Node " << TNL::Communicators::MpiCommunicator::GetRank() << " of " \ << TNL::Communicators::MpiCommunicator::GetSize() << " : " << message << std::endl; \ - TNL::String __tnl_mpi_print_string_( __tnl_mpi_print_stream_.str().c_str() ); \ - mpiSsend( __tnl_mpi_print_string_, 0, std::numeric_limits< int >::max() ); \ + TNL::String __tnl_mpi_print_string_( __tnl_mpi_print_stream_.str() ); \ + mpiSend( __tnl_mpi_print_string_, 0, std::numeric_limits< int >::max() ); \ } \ } \ else \ @@ -94,7 +94,7 @@ else if( __tnl_mpi_print_cond ) \ { \ TNL::String __tnl_mpi_print_string_; \ - mpiReceive( __tnl_mpi_print_string_, __tnl_mpi_print_j, std::numeric_limits< int >::max() ); \ + mpiReceive( __tnl_mpi_print_string_, __tnl_mpi_print_j, std::numeric_limits< int >::max() ); \ std::cerr << __tnl_mpi_print_string_; \ } \ } \ @@ -103,4 +103,4 @@ else #else #define TNL_MPI_PRINT_COND( condition, message ) \ std::cerr << message << std::endl; -#endif \ No newline at end of file +#endif diff --git a/src/TNL/Containers/Multimaps/EllpackIndexMultimap.hpp b/src/TNL/Containers/Multimaps/EllpackIndexMultimap.hpp index 6fb1f4b26d5a4c3b8447e1156c89641118be3c32..c75250029ec0bdd0dc1db06b89681c9ae9f1190e 100644 --- a/src/TNL/Containers/Multimaps/EllpackIndexMultimap.hpp +++ b/src/TNL/Containers/Multimaps/EllpackIndexMultimap.hpp @@ -80,10 +80,12 @@ allocate( const LocalIndexType& maxValuesCount ) const IndexType ldSize = getAllocationKeysRange( this->getKeysRange() ); this->values.setSize( ldSize * this->maxValuesCount ); this->valuesCounts.setSize( this->getKeysRange() ); - this->valuesCounts.setValue( maxValuesCount ); + if( this->valuesCounts.getSize() > 0 ) + this->valuesCounts.setValue( maxValuesCount ); // extra cost at initialization, which allows to have much simpler operator== - values.setValue( 0 ); + if( this->values.getSize() > 0 ) + values.setValue( 0 ); } template< typename Index, @@ -108,7 +110,8 @@ allocate( const ValuesAllocationVectorType& valuesCounts ) this->valuesCounts = valuesCounts; // extra cost at initialization, which allows to have much simpler operator== - values.setValue( 0 ); + if( this->values.getSize() > 0 ) + values.setValue( 0 ); } template< typename Index, @@ -128,7 +131,8 @@ setLike( const EllpackIndexMultimap< Index, Device_, LocalIndex, SliceSize_ >& o maxValuesCount = other.maxValuesCount; // extra cost at initialization, which allows to have much simpler operator== - values.setValue( 0 ); + if( this->values.getSize() > 0 ) + values.setValue( 0 ); } template< typename Index, diff --git a/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap.hpp b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap.hpp index 3e03f9e03a5c22cad10e242b93dff20151a37598..7af150615a682a5a215e448b4e7e0f85efd0079a 100644 --- a/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap.hpp +++ b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap.hpp @@ -82,7 +82,8 @@ allocate() values.setSize( ldSize * ValuesCount ); // extra cost at initialization, which allows to have much simpler operator== - values.setValue( 0 ); + if( ldSize > 0 ) + values.setValue( 0 ); } template< int ValuesCount, @@ -99,7 +100,8 @@ setLike( const StaticEllpackIndexMultimap< ValuesCount, Index, Device_, LocalInd values.setSize( ldSize * ValuesCount ); // extra cost at initialization, which allows to have much simpler operator== - values.setValue( 0 ); + if( ldSize > 0 ) + values.setValue( 0 ); keysRange = other.keysRange; } diff --git a/src/TNL/Matrices/DistributedSpMV.h b/src/TNL/Matrices/DistributedSpMV.h index a4711dce0e5b1a0a984966a7f997ae6549c0b3e4..01e9c286ffdadca8138c1020cc2e8a8da598ef00 100644 --- a/src/TNL/Matrices/DistributedSpMV.h +++ b/src/TNL/Matrices/DistributedSpMV.h @@ -153,12 +153,14 @@ public: updateCommunicationPattern( localMatrix, group ); // prepare buffers - commRequests.clear(); globalBuffer.init( Partitioner::getOffset( localMatrix.getColumns(), rank, nproc ), inVector.getConstLocalView(), localMatrix.getColumns() - Partitioner::getOffset( localMatrix.getColumns(), rank, nproc ) - inVector.getConstLocalView().getSize() ); const auto globalBufferView = globalBuffer.getConstView(); + // buffer for asynchronous communication requests + std::vector< typename CommunicatorType::Request > commRequests; + // send our data to all processes that need it for( int i = 0; i < commPatternStarts.getRows(); i++ ) { if( i == rank ) @@ -231,21 +233,17 @@ public: commPatternEnds.reset(); localOnlySpan.first = localOnlySpan.second = 0; globalBuffer.reset(); - commRequests.clear(); } protected: // communication pattern - Matrices::Dense< IndexType, Devices::Host, int, true, Allocators::Host< IndexType > > commPatternStarts, commPatternEnds; + Matrices::Dense< IndexType, Devices::Host, int > commPatternStarts, commPatternEnds; // span of rows with only block-diagonal entries std::pair< IndexType, IndexType > localOnlySpan; // global buffer for non-local elements of the vector __DistributedSpMV_impl::ThreePartVector< RealType, DeviceType, IndexType > globalBuffer; - - // buffer for asynchronous communication requests - std::vector< typename CommunicatorType::Request > commRequests; }; } // namespace Matrices diff --git a/src/TNL/Meshes/DistributedMeshes/DistributedGridSynchronizer.h b/src/TNL/Meshes/DistributedMeshes/DistributedGridSynchronizer.h index 1347683fd049d5fdec7b1f80cd04a15ac24b6fd5..dfe572deaef83426094525835f656ce4ae40b8a7 100644 --- a/src/TNL/Meshes/DistributedMeshes/DistributedGridSynchronizer.h +++ b/src/TNL/Meshes/DistributedMeshes/DistributedGridSynchronizer.h @@ -15,6 +15,7 @@ #include <TNL/Meshes/DistributedMeshes/BufferEntitiesHelper.h> #include <TNL/Meshes/DistributedMeshes/Directions.h> #include <TNL/Communicators/MPIPrint.h> +#include <TNL/Pointers/SharedPointer.h> namespace TNL { namespace Functions{ diff --git a/src/TNL/Solvers/PDE/ExplicitUpdater.h b/src/TNL/Solvers/PDE/ExplicitUpdater.h index 74c9952294d0e9f7e4fd8231cf45283380f378cf..16a661d225e66a89fb3a9ca79cdaed4afd422139 100644 --- a/src/TNL/Solvers/PDE/ExplicitUpdater.h +++ b/src/TNL/Solvers/PDE/ExplicitUpdater.h @@ -18,11 +18,6 @@ #include <TNL/Meshes/GridDetails/Traverser_Grid2D.h> #include <TNL/Meshes/GridDetails/Traverser_Grid3D.h> -#ifdef USE_MPI - #include <TNL/Meshes/DistributedGridSynchronizer.h> -#endif - - namespace TNL { namespace Solvers { namespace PDE { diff --git a/src/TNL/String.h b/src/TNL/String.h index 228cb5bcb18d07cdf493ff9fdbc36c9539baef63..b0fb6644ceb6e88f79e87f05d2011436a0a19db2 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -342,6 +342,16 @@ class String * \include StringExampleSplit.out */ std::vector< String > split( const char separator = ' ', SplitSkip skipEmpty = SplitSkip::NoSkip ) const; + + /** + * \brief Checks if the string starts with given prefix. + */ + bool startsWith( const String& prefix ) const; + + /** + * \brief Checks if the string ends with given suffix. + */ + bool endsWith( const String& suffix ) const; }; /** diff --git a/src/TNL/String.hpp b/src/TNL/String.hpp index 3c38fe6b0ca24a58242461788b2b417a94ab6a1e..64fae92cd575115bd7d9c8f8f7303cd252f8e583 100644 --- a/src/TNL/String.hpp +++ b/src/TNL/String.hpp @@ -223,6 +223,22 @@ String::split( const char separator, SplitSkip skip ) const return parts; } +inline bool +String::startsWith( const String& prefix ) const +{ + if( prefix.getSize() > getSize()) + return false; + return std::equal( prefix.begin(), prefix.end(), begin() ); +} + +inline bool +String::endsWith( const String& suffix ) const +{ + if( suffix.getSize() > getSize()) + return false; + return std::equal( suffix.rbegin(), suffix.rend(), rbegin() ); +} + inline String operator+( char string1, const String& string2 ) { return convertToString( string1 ) + string2; diff --git a/src/UnitTests/StringTest.cpp b/src/UnitTests/StringTest.cpp index aa2a64a19f4e94c6b83cc2193f1330a279d37f03..7447c1e6c2182a52be6a5ff7d2cee4b665eaf55b 100644 --- a/src/UnitTests/StringTest.cpp +++ b/src/UnitTests/StringTest.cpp @@ -317,7 +317,63 @@ TEST( StringTest, SaveLoad ) EXPECT_EQ( str1, str2 ); EXPECT_EQ( std::remove( TEST_FILE_NAME ), 0 ); -}; +} + +TEST( StringTest, startsWith ) +{ + String str( "abracadabra" ); + EXPECT_TRUE( str.startsWith( "a" ) ); + EXPECT_TRUE( str.startsWith( "ab" ) ); + EXPECT_TRUE( str.startsWith( "abr" ) ); + EXPECT_TRUE( str.startsWith( "abra" ) ); + EXPECT_TRUE( str.startsWith( "abrac" ) ); + EXPECT_TRUE( str.startsWith( "abraca" ) ); + EXPECT_TRUE( str.startsWith( "abracad" ) ); + EXPECT_TRUE( str.startsWith( "abracada" ) ); + EXPECT_TRUE( str.startsWith( "abracadab" ) ); + EXPECT_TRUE( str.startsWith( "abracadabr" ) ); + EXPECT_TRUE( str.startsWith( "abracadabra" ) ); + EXPECT_FALSE( str.startsWith( "b" ) ); + EXPECT_FALSE( str.startsWith( "aa" ) ); + EXPECT_FALSE( str.startsWith( "aba" ) ); + EXPECT_FALSE( str.startsWith( "abrb" ) ); + EXPECT_FALSE( str.startsWith( "abrad" ) ); + EXPECT_FALSE( str.startsWith( "abracb" ) ); + EXPECT_FALSE( str.startsWith( "abracaa" ) ); + EXPECT_FALSE( str.startsWith( "abracadb" ) ); + EXPECT_FALSE( str.startsWith( "abracadaa" ) ); + EXPECT_FALSE( str.startsWith( "abracadaba" ) ); + EXPECT_FALSE( str.startsWith( "abracadabrb" ) ); + EXPECT_FALSE( str.startsWith( "abracadabrab" ) ); +} + +TEST( StringTest, endsWith ) +{ + String str( "abracadabra" ); + EXPECT_TRUE( str.endsWith( "a" ) ); + EXPECT_TRUE( str.endsWith( "ra" ) ); + EXPECT_TRUE( str.endsWith( "bra" ) ); + EXPECT_TRUE( str.endsWith( "abra" ) ); + EXPECT_TRUE( str.endsWith( "dabra" ) ); + EXPECT_TRUE( str.endsWith( "adabra" ) ); + EXPECT_TRUE( str.endsWith( "cadabra" ) ); + EXPECT_TRUE( str.endsWith( "acadabra" ) ); + EXPECT_TRUE( str.endsWith( "racadabra" ) ); + EXPECT_TRUE( str.endsWith( "bracadabra" ) ); + EXPECT_TRUE( str.endsWith( "abracadabra" ) ); + EXPECT_FALSE( str.endsWith( "b" ) ); + EXPECT_FALSE( str.endsWith( "ba" ) ); + EXPECT_FALSE( str.endsWith( "ara" ) ); + EXPECT_FALSE( str.endsWith( "bbra" ) ); + EXPECT_FALSE( str.endsWith( "babra" ) ); + EXPECT_FALSE( str.endsWith( "bdabra" ) ); + EXPECT_FALSE( str.endsWith( "badabra" ) ); + EXPECT_FALSE( str.endsWith( "bcadabra" ) ); + EXPECT_FALSE( str.endsWith( "aacadabra" ) ); + EXPECT_FALSE( str.endsWith( "aracadabra" ) ); + EXPECT_FALSE( str.endsWith( "bbracadabra" ) ); + EXPECT_FALSE( str.endsWith( "babracadabra" ) ); +} #endif #include "main.h"