diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f3c581ce6..fbb41bf93 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,6 +37,7 @@ jobs: - linux clang-12 # - linux nvhpc-22.11 - linux intel + - linux intel-classic - macos include: @@ -102,7 +103,16 @@ jobs: - name : linux intel os: ubuntu-20.04 - compiler: intel-oneapi + compiler: intel + compiler_cc: icx + compiler_cxx: icpx + compiler_fc: ifx + caching: true + coverage: false + + - name : linux intel-classic + os: ubuntu-20.04 + compiler: intel-classic compiler_cc: icc compiler_cxx: icpc compiler_fc: ifort @@ -179,7 +189,7 @@ jobs: ${ATLAS_TOOLS}/install-intel-oneapi.sh source /opt/intel/oneapi/setvars.sh printenv >> $GITHUB_ENV - echo "CACHE_SUFFIX=$(icc -dumpversion)" >> $GITHUB_ENV + echo "CACHE_SUFFIX=$CC-$($CC -dumpversion)" >> $GITHUB_ENV - name: Install MPI shell: bash -eux {0} @@ -220,6 +230,19 @@ jobs: # Add mpirun to path for testing [ -z ${MPI_HOME+x} ] || echo "${MPI_HOME}/bin" >> $GITHUB_PATH + if [[ "${{matrix.compiler}}" == intel-classic ]]; then + echo "CFLAGS=-diag-disable=10441" >> $GITHUB_ENV + echo "CXXFLAGS=-diag-disable=10441" >> $GITHUB_ENV + echo "FCFLAGS=-diag-disable=10441" >> $GITHUB_ENV + echo "FFLAGS=-diag-disable=10441" >> $GITHUB_ENV + fi + + if [[ "${{matrix.compiler}}" == intel ]]; then + echo "CFLAGS=-Rno-debug-disables-optimization" >> $GITHUB_ENV + echo "CXXFLAGS=-Rno-debug-disables-optimization" >> $GITHUB_ENV + fi + + - name: Build & Test id: build-test diff --git a/cmake/atlas_compile_flags.cmake b/cmake/atlas_compile_flags.cmake index 5473f870a..8b334f149 100644 --- a/cmake/atlas_compile_flags.cmake +++ b/cmake/atlas_compile_flags.cmake @@ -24,4 +24,11 @@ endif() if( CMAKE_CXX_COMPILER_ID MATCHES NVHPC ) ecbuild_add_cxx_flags("--diag_suppress declared_but_not_referenced --display_error_number" NAME atlas_cxx_disable_warnings ) # For all the variables with side effects (constructor/dectructor functionality) -endif() \ No newline at end of file +endif() + +if( CMAKE_CXX_COMPILER_ID MATCHES IntelLLVM ) + # Turn off -ffinite-math-only which gets included by some optimisation levels which assumes values can never be NaN. + # Then results in std::isnan(value) always retrun false. + ecbuild_add_cxx_flags("-fno-finite-math-only") +endif() + diff --git a/src/atlas/util/function/MDPI_functions.cc b/src/atlas/util/function/MDPI_functions.cc index 121d2602d..f570ac5b7 100644 --- a/src/atlas/util/function/MDPI_functions.cc +++ b/src/atlas/util/function/MDPI_functions.cc @@ -118,6 +118,21 @@ double MDPI_gulfstream(double lon, double lat) { return background_func + dc * (std::max(1000. * std::sin(0.4 * (0.5 * dr + dth) + 0.007 * std::cos(50. * dth) + 0.37 * M_PI), 999.) - 999.); } +extern "C" { + double atlas__functions__MDPI_sinusoid(double& lon, double& lat) { + return MDPI_sinusoid(lon, lat); + } + double atlas__functions__MDPI_harmonic(double& lon, double& lat) { + return MDPI_harmonic(lon, lat); + } + double atlas__functions__MDPI_vortex(double& lon, double& lat) { + return MDPI_vortex(lon, lat); + } + double atlas__functions__MDPI_gulfstream(double& lon, double& lat) { + return MDPI_gulfstream(lon, lat); + } +} + } // namespace function } // namespace util } // namespace atlas diff --git a/src/atlas/util/function/MDPI_functions.h b/src/atlas/util/function/MDPI_functions.h index b60544536..73ff406ac 100644 --- a/src/atlas/util/function/MDPI_functions.h +++ b/src/atlas/util/function/MDPI_functions.h @@ -30,6 +30,13 @@ double MDPI_harmonic(double lon, double lat); double MDPI_vortex(double lon, double lat); double MDPI_gulfstream(double lon, double lat); +extern "C" { + double atlas__functions__MDPI_sinusoid(double& lon, double& lat); + double atlas__functions__MDPI_harmonic(double& lon, double& lat); + double atlas__functions__MDPI_vortex(double& lon, double& lat); + double atlas__functions__MDPI_gulfstream(double& lon, double& lat); +} + } // namespace function } // namespace util diff --git a/src/atlas_f/CMakeLists.txt b/src/atlas_f/CMakeLists.txt index f1b831e3c..3c3d396e0 100644 --- a/src/atlas_f/CMakeLists.txt +++ b/src/atlas_f/CMakeLists.txt @@ -205,6 +205,7 @@ ecbuild_add_library( TARGET atlas_f SOURCES ${FORTRAN_BINDINGS} atlas_module.F90 + util/atlas_functions_module.F90 util/atlas_kinds_module.F90 util/atlas_JSON_module.F90 util/atlas_Config_module.F90 diff --git a/src/atlas_f/atlas_module.F90 b/src/atlas_f/atlas_module.F90 index 48ffe33ae..975ea4e92 100644 --- a/src/atlas_f/atlas_module.F90 +++ b/src/atlas_f/atlas_module.F90 @@ -150,6 +150,7 @@ module atlas_module & atlas_output_Gmsh use atlas_trace_module, only : & & atlas_Trace +use atlas_functions_module use fckit_log_module, only: atlas_log => fckit_log diff --git a/src/atlas_f/util/atlas_functions_module.F90 b/src/atlas_f/util/atlas_functions_module.F90 new file mode 100644 index 000000000..ee94b80e2 --- /dev/null +++ b/src/atlas_f/util/atlas_functions_module.F90 @@ -0,0 +1,83 @@ +! (C) Copyright 2013 ECMWF. +! +! This software is licensed under the terms of the Apache Licence Version 2.0 +! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. +! In applying this licence, ECMWF does not waive the privileges and immunities +! granted to it by virtue of its status as an intergovernmental organisation nor +! does it submit to any jurisdiction. + +#include "atlas/atlas_f.h" + +module atlas_functions_module + +use, intrinsic :: iso_c_binding + +implicit none + +interface + +pure function atlas__functions__MDPI_sinusoid( lon, lat ) bind(C,name="atlas__functi& + &ons__MDPI_sinusoid") + use iso_c_binding, only: c_double + real(c_double) :: atlas__functions__MDPI_sinusoid + real(c_double), intent(in) :: lon, lat +end function + +pure function atlas__functions__MDPI_harmonic( lon, lat ) bind(C,name="atlas__functi& + &ons__MDPI_harmonic") + use iso_c_binding, only: c_double + real(c_double) :: atlas__functions__MDPI_harmonic + real(c_double), intent(in) :: lon, lat +end function + +pure function atlas__functions__MDPI_vortex( lon, lat ) bind(C,name="atlas__function& + &s__MDPI_vortex") + use iso_c_binding, only: c_double + real(c_double) :: atlas__functions__MDPI_vortex + real(c_double), intent(in) :: lon, lat +end function + +pure function atlas__functions__MDPI_gulfstream( lon, lat ) bind(C,name="atlas__func& + &tions__MDPI_gulfstream") + use iso_c_binding, only: c_double + real(c_double) :: atlas__functions__MDPI_gulfstream + real(c_double), intent(in) :: lon, lat +end function + +end interface + +contains + +elemental function MDPI_sinusoid(lon, lat) result(val) + real(c_double), intent(in) :: lon, lat + real(c_double) :: val + val = atlas__functions__MDPI_sinusoid(lon, lat) +end function MDPI_sinusoid + +! ----------------------------------------------------------------------------- + +elemental function MDPI_harmonic(lon, lat) result(val) + real(c_double), intent(in) :: lon, lat + real(c_double) :: val + val = atlas__functions__MDPI_harmonic(lon, lat) +end function MDPI_harmonic + +! ----------------------------------------------------------------------------- + +elemental function MDPI_vortex(lon, lat) result(val) + real(c_double), intent(in) :: lon, lat + real(c_double) :: val + val = atlas__functions__MDPI_vortex(lon, lat) +end function MDPI_vortex + +! ----------------------------------------------------------------------------- + +elemental function MDPI_gulfstream(lon, lat) result(val) + real(c_double), intent(in) :: lon, lat + real(c_double) :: val + val = atlas__functions__MDPI_gulfstream(lon, lat) +end function MDPI_gulfstream + +! ----------------------------------------------------------------------------- + +end module atlas_functions_module diff --git a/src/tests/functionspace/test_pointcloud_halo_creation.cc b/src/tests/functionspace/test_pointcloud_halo_creation.cc index 2ee1593a1..32e817308 100644 --- a/src/tests/functionspace/test_pointcloud_halo_creation.cc +++ b/src/tests/functionspace/test_pointcloud_halo_creation.cc @@ -28,6 +28,8 @@ using namespace atlas::util; namespace atlas { namespace test { +constexpr double tol = 1.e-12; + //----------------------------------------------------------------------------- CASE("Distributed creation from unstructured grid with halo") { @@ -237,7 +239,7 @@ for (idx_t i=0; i = nullptr> Value castValue(const double& inVal) { + constexpr double eps = 1.e-12; + Value rounded_minus_half = std::round(inVal-0.5); + if (std::abs(rounded_minus_half - (inVal-0.5)) < eps) { + return static_cast(rounded_minus_half); + } return static_cast(std::round(inVal)); } diff --git a/src/tests/util/CMakeLists.txt b/src/tests/util/CMakeLists.txt index f2f15e4df..47d8b6def 100644 --- a/src/tests/util/CMakeLists.txt +++ b/src/tests/util/CMakeLists.txt @@ -9,6 +9,13 @@ if( HAVE_FCTEST ) + add_fctest( TARGET atlas_fctest_functions + LINKER_LANGUAGE Fortran + SOURCES fctest_functions.F90 + LIBS atlas_f + ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} + ) + add_fctest( TARGET atlas_fctest_logging LINKER_LANGUAGE Fortran SOURCES fctest_logging.F90 diff --git a/src/tests/util/fctest_functions.F90 b/src/tests/util/fctest_functions.F90 new file mode 100644 index 000000000..7b2fa94ff --- /dev/null +++ b/src/tests/util/fctest_functions.F90 @@ -0,0 +1,88 @@ +! (C) Copyright 2013 ECMWF. +! This software is licensed under the terms of the Apache Licence Version 2.0 +! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. +! In applying this licence, ECMWF does not waive the privileges and immunities +! granted to it by virtue of its status as an intergovernmental organisation nor +! does it submit to any jurisdiction. + +! This File contains Unit Tests for testing the +! C++ / Fortran Interfaces to the logging facilities +! @author Willem Deconinck + +#include "fckit/fctest.h" + +! ----------------------------------------------------------------------------- + +module fcta_functions_fxt +use atlas_module +use, intrinsic :: iso_c_binding +implicit none +character(len=1024) :: msg + +end module fcta_functions_fxt + +! ----------------------------------------------------------------------------- + +TESTSUITE_WITH_FIXTURE(fctest_atlas_functions,fcta_functions_fxt) + +! ----------------------------------------------------------------------------- +TESTSUITE_INIT + call atlas_library%initialise() +END_TESTSUITE_INIT + +! ----------------------------------------------------------------------------- + +TESTSUITE_FINALIZE + call atlas_library%finalise() +END_TESTSUITE_FINALIZE + +! ----------------------------------------------------------------------------- + +TEST( test_atlas_Functions ) + real(c_double) :: val + val = MDPI_sinusoid(1._c_double, 1._c_double) + FCTEST_CHECK_CLOSE(val, 1.0002115216773033_c_double, 1e-12_c_double) + val = MDPI_harmonic(1._c_double, 1._c_double) + FCTEST_CHECK_CLOSE(val, 2.0000000000000000_c_double, 1e-12_c_double) + val = MDPI_vortex(1._c_double, 1._c_double) + FCTEST_CHECK_CLOSE(val, 2.7267489215500755_c_double, 1e-12_c_double) + val = MDPI_gulfstream(1._c_double, 1._c_double) + FCTEST_CHECK_CLOSE(val, 1.0002115216773033_c_double, 1e-12_c_double) +END_TEST + +TEST( test_atlas_Functions_vector ) + real(c_double), dimension(3) :: val, lon, lat, val_ref + lon = [ 1._c_double, 2._c_double, 3._c_double ] + lat = [ 1._c_double, 2._c_double, 3._c_double ] + val = MDPI_sinusoid(lon, lat) + val_ref = [1.0002115216773033_c_double, 1.0008458683590891_c_double, 1.0019023851484181_c_double] + FCTEST_CHECK_CLOSE(val, val_ref, 1e-12_c_double) + val = MDPI_harmonic(lon, lat) + val_ref = [2.0000000000000000_c_double, 2.0000000000000000_c_double, 2.0000000000000000_c_double] + FCTEST_CHECK_CLOSE(val, val_ref, 1e-12_c_double) + val = MDPI_vortex(lon, lat) + val_ref = [2.7267489215500755_c_double, 2.7520839004022091_c_double, 2.7755506683886928_c_double] + FCTEST_CHECK_CLOSE(val, val_ref, 1e-12_c_double) + val = MDPI_gulfstream(lon, lat) + val_ref = [1.0002115216773033_c_double, 1.0008458683590891_c_double, 1.0019023851484181_c_double] + FCTEST_CHECK_CLOSE(val, val_ref, 1e-12_c_double) +END_TEST + +TEST( test_initialise_field ) + type(atlas_Field) :: field_xy, field_val + real(c_double), dimension(:,:), pointer :: field_xy_v + real(c_double), dimension(:), pointer :: field_val_v + real(c_double), dimension(3) :: field_val_ref + field_xy = atlas_Field(kind=atlas_real(c_double), shape=[2,3]) + field_val = atlas_Field(kind=atlas_real(c_double), shape=[3]) + call field_xy%data(field_xy_v) + field_xy_v = 1._c_double + call field_val%data(field_val_v) + field_val_v = MDPI_sinusoid(field_xy_v(1,:), field_xy_v(2,:)) + field_val_ref = [1.0002115216773033_c_double, 1.0002115216773033_c_double, 1.0002115216773033_c_double] + FCTEST_CHECK_CLOSE(field_val_v, field_val_ref, 1e-12_c_double) +END_TEST + +! ----------------------------------------------------------------------------- + +END_TESTSUITE diff --git a/tools/install-intel-oneapi.sh b/tools/install-intel-oneapi.sh index a954274d8..b6db3853b 100755 --- a/tools/install-intel-oneapi.sh +++ b/tools/install-intel-oneapi.sh @@ -1,5 +1,6 @@ -#!/bin/sh +#!/usr/bin/env bash +version=2023.2.0 KEY=GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB wget https://apt.repos.intel.com/intel-gpg-keys/$KEY sudo apt-key add $KEY @@ -7,8 +8,7 @@ rm $KEY echo "deb https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list sudo apt-get update sudo apt-get install \ - intel-oneapi-compiler-fortran \ - intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic \ - intel-oneapi-mpi \ - intel-oneapi-mpi-devel \ - intel-oneapi-mkl + intel-oneapi-compiler-fortran-$version \ + intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic-$version \ + intel-oneapi-mpi-devel-2021.10.0 \ + intel-oneapi-mkl-$version