diff --git a/cmake/features/ECTRANS.cmake b/cmake/features/ECTRANS.cmake index 20c893852..9d17caf82 100644 --- a/cmake/features/ECTRANS.cmake +++ b/cmake/features/ECTRANS.cmake @@ -14,29 +14,42 @@ if( DEFINED ATLAS_ENABLE_ECTRANS ) set( ENABLE_ECTRANS ${ATLAS_ENABLE_ECTRANS} ) endif() +macro( make_transi_alias target ) + if( NOT TARGET transi ) + if( CMAKE_VERSION VERSION_LESS 3.18 ) + # Before CMake 3.18 it is not possible to alias a non-global imported target + # Make the import global. Warning, this may break further find_package + get_target_property( ${target}_IMPORTED ${target} IMPORTED ) + if( transi_dp_IMPORTED ) + set_target_properties( ${target} PROPERTIES IMPORTED_GLOBAL TRUE) + endif() + endif() + add_library( transi ALIAS ${target} ) + endif() +endmacro() + set( atlas_HAVE_PACKAGE_ECTRANS 0 ) if( atlas_HAVE_ATLAS_FUNCTIONSPACE AND (ENABLE_ECTRANS OR NOT DEFINED ENABLE_ECTRANS) ) find_package( ectrans 1.1 COMPONENTS transi double QUIET ) - if( TARGET transi_dp ) + if( TARGET transi_dp OR TARGET transi_gpu_dp ) set( transi_FOUND TRUE ) - if( NOT TARGET transi ) - if( CMAKE_VERSION VERSION_LESS 3.18 ) - # Before CMake 3.18 it is not possible to alias a non-global imported target - # Make the import global. Warning, this may break further find_package - get_target_property( transi_dp_IMPORTED transi_dp IMPORTED ) - if( transi_dp_IMPORTED ) - set_target_properties( transi_dp PROPERTIES IMPORTED_GLOBAL TRUE) - endif() - endif() - add_library( transi ALIAS transi_dp ) - endif() set( atlas_HAVE_PACKAGE_ECTRANS 1 ) else() find_package( transi 0.8 QUIET ) endif() endif() ecbuild_add_option( FEATURE ECTRANS - DESCRIPTION "Support for IFS spectral transforms" + DESCRIPTION "Support for ectrans spectral transforms" CONDITION atlas_HAVE_ATLAS_FUNCTIONSPACE AND transi_FOUND ) +ecbuild_add_option( FEATURE ECTRANS_GPU DEFAULT OFF + DESCRIPTION "Support for ectrans spectral transforms" + CONDITION HAVE_ECTRANS AND TARGET transi_gpu_dp ) +if( HAVE_ECTRANS_GPU AND TARGET transi_gpu_dp) + ecbuild_warn("ectrans GPU version") + make_transi_alias( transi_gpu_dp ) +elseif( HAVE_ECTRANS AND TARGET transi_dp ) + ecbuild_warn("ectrans CPU version") + make_transi_alias( transi_dp ) +endif() endif() diff --git a/src/tests/functionspace/CMakeLists.txt b/src/tests/functionspace/CMakeLists.txt index cd4e50721..57f815e11 100644 --- a/src/tests/functionspace/CMakeLists.txt +++ b/src/tests/functionspace/CMakeLists.txt @@ -19,7 +19,7 @@ if( HAVE_FCTEST ) LINKER_LANGUAGE Fortran SOURCES fctest_functionspace.F90 LIBS atlas_f - ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} + ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} ATLAS_FINALISES_MPI=1 ) add_fctest( TARGET atlas_fctest_blockstructuredcolumns @@ -28,7 +28,7 @@ if( HAVE_FCTEST ) LINKER_LANGUAGE Fortran SOURCES fctest_blockstructuredcolumns.F90 LIBS atlas_f - ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} + ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} ATLAS_FINALISES_MPI=1 ) endif() diff --git a/src/tests/redistribution/CMakeLists.txt b/src/tests/redistribution/CMakeLists.txt index dcc96c7c0..89a6dce83 100644 --- a/src/tests/redistribution/CMakeLists.txt +++ b/src/tests/redistribution/CMakeLists.txt @@ -14,7 +14,7 @@ if( HAVE_FORTRAN ) LINKER_LANGUAGE Fortran SOURCES fctest_redistribution.F90 LIBS atlas_f - ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} + ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} ATLAS_FINALISES_MPI=1 ) endif() diff --git a/src/tests/trans/CMakeLists.txt b/src/tests/trans/CMakeLists.txt index 92401207d..c980652d8 100644 --- a/src/tests/trans/CMakeLists.txt +++ b/src/tests/trans/CMakeLists.txt @@ -6,6 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation nor # does it submit to any jurisdiction. +list( APPEND ATLAS_TEST_ENVIRONMENT ATLAS_TEST_IGNORE_ECTRANS_NOT_IMPLEMENTED=1 ) if( HAVE_FCTEST ) if( atlas_HAVE_ECTRANS ) @@ -16,7 +17,7 @@ if( HAVE_FCTEST ) LIBS atlas_f CONDITION eckit_HAVE_MPI AND ( transi_HAVE_MPI OR ectrans_HAVE_MPI ) AND MPI_SLOTS GREATER_EQUAL 4 MPI 4 - ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} + ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} ATLAS_FINALISES_MPI=1 ) endif() @@ -25,7 +26,7 @@ if( HAVE_FCTEST ) LINKER_LANGUAGE Fortran SOURCES fctest_trans_invtrans_grad.F90 LIBS atlas_f - ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} + ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} ATLAS_FINALISES_MPI=1 ) endif() diff --git a/src/tests/trans/test_trans.cc b/src/tests/trans/test_trans.cc index 07ca6f779..c99e9a646 100644 --- a/src/tests/trans/test_trans.cc +++ b/src/tests/trans/test_trans.cc @@ -9,6 +9,7 @@ */ #include +#include #include "eckit/exception/Exceptions.h" #include "eckit/filesystem/PathName.h" @@ -48,6 +49,44 @@ #endif #endif +bool ignore_ectrans_not_implemented(std::exception& e) { + static bool ATLAS_TEST_IGNORE_ECTRANS_NOT_IMPLEMENTED = []() -> bool { + const char* env = ::getenv("ATLAS_TEST_IGNORE_ECTRANS_NOT_IMPLEMENTED"); + if (env) { + return std::atoi(env); + } + return false; + }(); + if (ATLAS_TEST_IGNORE_ECTRANS_NOT_IMPLEMENTED == false) { + return false; + } + std::string errstr(e.what()); + for(auto& c : errstr){ c = std::tolower(c); } + std::vector search{"trans", "not", "implemented"}; + return std::all_of(search.begin() ,search.end(),[&](const std::string& s)->bool { + return errstr.find(s) != std::string::npos; + }); +} + +#define ECTRANS_MAYBE_NOT_IMPLEMENTED(expr) \ + do { \ + try { \ + expr; \ + } \ + catch (std::exception & e) { \ + if( ignore_ectrans_not_implemented(e) ) { \ + atlas::Log::error() << "ERROR IGNORED: Not implemented with ectrans code path\n" \ + << "Skipping remainder of test" \ + << std::endl; \ + return; \ + } \ + throw eckit::testing::TestException("Unexpected exception caught: "+std::string(e.what()), Here()); \ + } \ + catch (...) { \ + throw eckit::testing::TestException("Unexpected and unknown exception caught", Here()); \ + } \ + } while (false) + using namespace eckit; using atlas::grid::detail::partitioner::EqualRegionsPartitioner; using atlas::grid::detail::partitioner::TransPartitioner; @@ -166,7 +205,6 @@ CASE("test_trans_options") { Log::info() << "trans_opts = " << opts << std::endl; } -#ifdef TRANS_HAVE_IO CASE("test_write_read_cache") { Log::info() << "test_write_read_cache" << std::endl; using namespace trans; @@ -193,7 +231,6 @@ CASE("test_write_read_cache") { Trans trans_cache_O24(legendre_cache_O24, Grid("O24"), 23, option::flt(false)); } } -#endif CASE("test_distspec") { trans::TransIFS trans(Grid("F80"), 159); @@ -518,9 +555,9 @@ CASE("test_trans_using_functionspace_StructuredColumns") { CASE("test_trans_MIR_lonlat") { Log::info() << "test_trans_MIR_lonlat" << std::endl; - Grid grid("L48"); - trans::Trans trans(grid, 47); + trans::Trans trans; + ECTRANS_MAYBE_NOT_IMPLEMENTED((trans = trans::Trans(grid, 47))); // global fields std::vector spf(trans.spectralCoefficients(), 0.); @@ -561,7 +598,9 @@ CASE("test_trans_VorDivToUV") { std::vector field_U(nfld * nspec2); std::vector field_V(nfld * nspec2); - vordiv_to_UV.execute(nspec2, nfld, field_vor.data(), field_div.data(), field_U.data(), field_V.data()); + ECTRANS_MAYBE_NOT_IMPLEMENTED( + vordiv_to_UV.execute(nspec2, nfld, field_vor.data(), field_div.data(), field_U.data(), field_V.data()); + ); // TODO: do some meaningful checks Log::info() << "Trans library" << std::endl; @@ -580,8 +619,9 @@ CASE("test_trans_VorDivToUV") { std::vector field_U(nfld * nspec2); std::vector field_V(nfld * nspec2); - vordiv_to_UV.execute(nspec2, nfld, field_vor.data(), field_div.data(), field_U.data(), field_V.data()); - + EXPECT_NO_THROW( + vordiv_to_UV.execute(nspec2, nfld, field_vor.data(), field_div.data(), field_U.data(), field_V.data()); + ); // TODO: do some meaningful checks Log::info() << "Local transform" << std::endl; Log::info() << "U: " << std::endl; @@ -593,7 +633,6 @@ CASE("test_trans_VorDivToUV") { } } -#ifdef TRANS_HAVE_IO CASE("ATLAS-256: Legendre coefficient expected unique identifiers") { if (mpi::comm().size() == 1) { util::Config options; @@ -679,13 +718,13 @@ CASE("ATLAS-256: Legendre coefficient expected unique identifiers") { for (auto& domain : domains) { for (int T : spectral_T) { for (auto name : grids) { - Log::info() << "Case name:" << name << ", T:" << T << ", domain:" << domain << ", UID:'" << *uid - << "'" << std::endl; + //Log::info() << "Case name:" << name << ", T:" << T << ", domain:" << domain << ", UID:'" << *uid + // << "'" << std::endl; Grid grid(name, domain); auto test = trans::LegendreCacheCreator(grid, T, options).uid(); - ATLAS_DEBUG_VAR(test); - EXPECT(test == *uid); + //ATLAS_DEBUG_VAR(test); + EXPECT_EQ(test, *uid); uid++; } @@ -693,7 +732,6 @@ CASE("ATLAS-256: Legendre coefficient expected unique identifiers") { } } } -#endif //----------------------------------------------------------------------------- diff --git a/src/tests/trans/test_transgeneral.cc b/src/tests/trans/test_transgeneral.cc index 95489fae7..666aff1f4 100644 --- a/src/tests/trans/test_transgeneral.cc +++ b/src/tests/trans/test_transgeneral.cc @@ -46,6 +46,45 @@ #endif #endif +bool ignore_ectrans_not_implemented(std::exception& e) { + static bool ATLAS_TEST_IGNORE_ECTRANS_NOT_IMPLEMENTED = []() -> bool { + const char* env = ::getenv("ATLAS_TEST_IGNORE_ECTRANS_NOT_IMPLEMENTED"); + if (env) { + std::cout << "ATLAS_TEST_IGNORE_ECTRANS_NOT_IMPLEMENTED=" << env << std::endl; + return std::atoi(env); + } + return false; + }(); + if (ATLAS_TEST_IGNORE_ECTRANS_NOT_IMPLEMENTED == false) { + return false; + } + std::string errstr(e.what()); + for(auto& c : errstr){ c = std::tolower(c); } + std::vector search{"trans", "not", "implemented"}; + return std::all_of(search.begin() ,search.end(),[&](const std::string& s)->bool { + return errstr.find(s) != std::string::npos; + }); +} + +#define ECTRANS_MAYBE_NOT_IMPLEMENTED(expr) \ + do { \ + try { \ + expr; \ + } \ + catch (std::exception & e) { \ + if( ignore_ectrans_not_implemented(e) ) { \ + atlas::Log::error() << "ERROR IGNORED: Not implemented with ectrans code path\n" \ + << "Skipping remainder of test" \ + << std::endl; \ + return; \ + } \ + throw eckit::testing::TestException("Unexpected exception caught: "+std::string(e.what()), Here()); \ + } \ + catch (...) { \ + throw eckit::testing::TestException("Unexpected and unknown exception caught", Here()); \ + } \ + } while (false) + using namespace eckit; using atlas::array::Array; @@ -1578,7 +1617,8 @@ CASE("test_trans_levels") { } #endif - +#if 1 +// ECTRANS GPU VERSION DOES NOT YET SUPPORT THIS #if ATLAS_HAVE_TRANS #if ATLAS_HAVE_ECTRANS || defined(TRANS_HAVE_INVTRANS_ADJ) CASE("test_2level_adjoint_test_with_powerspectrum_convolution") { @@ -1652,7 +1692,7 @@ CASE("test_2level_adjoint_test_with_powerspectrum_convolution") { // transform fields to spectral and view if (test_name[test_type].compare("inverse") == 0) { - transIFS.invtrans_adj(gpf, spf); + ECTRANS_MAYBE_NOT_IMPLEMENTED(transIFS.invtrans_adj(gpf, spf)); } else if (test_name[test_type].compare("direct") == 0) { transIFS.dirtrans(gpf, spf); } @@ -1692,8 +1732,9 @@ CASE("test_2level_adjoint_test_with_powerspectrum_convolution") { if (test_name[test_type].compare("inverse") == 0) { transIFS.invtrans(spf, gpf2); } else if (test_name[test_type].compare("direct") == 0) { - transIFS.dirtrans_adj(spf, gpf2); + ECTRANS_MAYBE_NOT_IMPLEMENTED(transIFS.dirtrans_adj(spf, gpf2)); } + Log::info() << "adjoint test transforms " << test_name[test_type] << std::endl; @@ -1791,7 +1832,7 @@ CASE("test_2level_adjoint_test_with_vortdiv") { } atlas::mpi::comm().allReduceInPlace(adj_value, eckit::mpi::sum()); - transIFS.dirtrans_wind2vordiv_adj(spfvor, spfdiv, gpfuv2); + ECTRANS_MAYBE_NOT_IMPLEMENTED(transIFS.dirtrans_wind2vordiv_adj(spfvor, spfdiv, gpfuv2)); double adj_value2(0.0); for (atlas::idx_t j = gridFS.j_begin(); j < gridFS.j_end(); ++j) { @@ -1811,6 +1852,7 @@ CASE("test_2level_adjoint_test_with_vortdiv") { } #endif #endif +#endif #if 0 CASE( "test_trans_fourier_truncation" ) {