diff --git a/components/omega/OmegaBuild.cmake b/components/omega/OmegaBuild.cmake index ca8727522c9a..5c32083605bb 100644 --- a/components/omega/OmegaBuild.cmake +++ b/components/omega/OmegaBuild.cmake @@ -28,6 +28,7 @@ macro(common) option(OMEGA_LOG_FLUSH "Turn on unbuffered logging (default OFF)." OFF) option(OMEGA_TEST_CDASH "Turn on CDash support (default ON)." ON) option(OMEGA_EXTERNAL_PROF "Integration of Omega timers with external profiling tools (default OFF)." OFF) + option(OMEGA_FPEXCEPTS_IN_TESTS "Enable floating-point exceptions in Omega unit tests (default OFF)." OFF) if("${OMEGA_BUILD_TYPE}" STREQUAL "Debug" OR "${OMEGA_BUILD_TYPE}" STREQUAL "DEBUG") set(OMEGA_DEBUG ON) diff --git a/components/omega/doc/devGuide/FloatExcept.md b/components/omega/doc/devGuide/FloatExcept.md new file mode 100644 index 000000000000..0d75a36a2719 --- /dev/null +++ b/components/omega/doc/devGuide/FloatExcept.md @@ -0,0 +1,46 @@ +(omega-dev-float-except)= + +## Floating-point Exceptions + +Omega provides functions that enable or disable selected +floating-point exceptions. Floating-point exception handling depends +on the target architecture, and is not always supported. + +To enable floating-point exceptions `Exceptions` call +```c++ +FloatExceptStatus Status = enableFloatExceptions(Exceptions); +``` +The returned `FloatExceptStatus` struct contains two fields. +`Status.Err` holds an error code indicating success or failure. +On success, `Status.OldExceptions` contains exceptions that were in effect +before the call to the enable function. +`Exceptions` is an integer mask, which can be composed of exception +types defined in ``. They are implementation defined, but +typically include +- `FE_DIVBYZERO` +- `FE_INEXACT` +- `FE_INVALID` +- `FE_OVERFLOW` +- `FE_UNDERFLOW` + +For example, to enable divide-by-zero and underflow exceptions do +```c++ +FloatExceptStatus Status = enableFloatExceptions(FE_DIVBYZERO | FE_UNDERFLOW); +``` + +You can call `enableFloatExceptions` without an argument, which +enables +- `FE_DIVBYZERO` +- `FE_INVALID` +- `FE_OVERFLOW` + +To disable floating-point exceptions `Exceptions` call +```c++ +FloatExceptStatus Status = disableFloatExceptions(Exceptions); +``` +Calling this function without an argument disables all exceptions. + +Omega also provides a helper function `enableFloatExceptionsInTests(Exceptions)`. +This function is used in unit tests to conditionally call +`enableFloatExceptions(Exceptions)` based on the compiler and specified CMake options. +See [User's Guide](#omega-user-float-except) for details. diff --git a/components/omega/doc/index.md b/components/omega/doc/index.md index b16840d3bc5c..5fee9c30e679 100644 --- a/components/omega/doc/index.md +++ b/components/omega/doc/index.md @@ -58,6 +58,7 @@ userGuide/VertAdv userGuide/Forcing userGuide/SfcCoupling userGuide/Analysis +userGuide/FloatExcept ``` ```{toctree} @@ -108,6 +109,7 @@ devGuide/VertAdv devGuide/Forcing devGuide/SfcCoupling devGuide/Analysis +devGuide/FloatExcept ``` ```{toctree} diff --git a/components/omega/doc/userGuide/FloatExcept.md b/components/omega/doc/userGuide/FloatExcept.md new file mode 100644 index 000000000000..57720804e716 --- /dev/null +++ b/components/omega/doc/userGuide/FloatExcept.md @@ -0,0 +1,20 @@ +(omega-user-float-except)= + +## Floating-point exceptions + +Omega has support for enabling floating-point exceptions. In +certain conditions floating-point exceptions may be enabled by +default in Omega unit tests. Currently, this happens only when +the GNU compiler is used. A CMake option `OMEGA_FPEXCEPTS_IN_TESTS` +can be set to enable floating-point exceptions in unit tests with +any compiler. This enables the following exceptions +- divide by zero +- invalid operation +- overflow + +Note that enabling floating-point exceptions in other compilers +may require adjustment to compiler flags. For example, `clang` +has the command-line option `-ffp-exception-behavior` which +defaults to `ignore`. Enabling floating-point exceptions without +changing this flag to either `maytrap` or `strict` can cause +false positives. diff --git a/components/omega/src/CMakeLists.txt b/components/omega/src/CMakeLists.txt index a2f1ae537f58..98266a4f3079 100644 --- a/components/omega/src/CMakeLists.txt +++ b/components/omega/src/CMakeLists.txt @@ -35,6 +35,25 @@ if(OMEGA_SINGLE_PRECISION) ) endif() +include(CheckCXXSymbolExists) +# check if cfenv provides feenableexcept which is a gnu extension for enabling floating-point exceptions +check_cxx_symbol_exists(feenableexcept "cfenv" OMEGA_HAVE_FEENABLEEXCEPT) +if (OMEGA_HAVE_FEENABLEEXCEPT) + target_compile_definitions( + OmegaLibFlags + INTERFACE + OMEGA_HAVE_FEENABLEEXCEPT=1 + ) +endif() + +if(OMEGA_FPEXCEPTS_IN_TESTS) + target_compile_definitions( + OmegaLibFlags + INTERFACE + OMEGA_FPEXCEPTS_IN_TESTS=1 + ) +endif() + target_link_options( OmegaLibFlags diff --git a/components/omega/src/base/IO.cpp b/components/omega/src/base/IO.cpp index ff5613051339..bd2ea9f34c90 100644 --- a/components/omega/src/base/IO.cpp +++ b/components/omega/src/base/IO.cpp @@ -255,6 +255,10 @@ void openFileRead( const std::string &Filename, // [in] name (incl path) of file to open FileFmt InFormat // [in] (optional) file format ) { + // Workaround for HDF5 v1.14.3 raising floating-point exceptions + // Disable fpes in this function and re-enable before exiting + // Remove this workaround after HDF5 is upgraded on every machine + FloatExceptStatus Status = disableFloatExceptions(); int PIOErr = 0; // internal SCORPIO/PIO return call int Format = InFormat; // coerce to integer for PIO calls @@ -264,6 +268,10 @@ void openFileRead( if (PIOErr != PIO_NOERR) ABORT_ERROR("IO::openFile: PIO error opening file {} for read", Filename); + if (Status.Err.isSuccess()) { + enableFloatExceptions(Status.OldExceptions); + } + return; } // End openFileRead diff --git a/components/omega/src/base/IO.h b/components/omega/src/base/IO.h index c18207b9aca8..0e1417a65962 100644 --- a/components/omega/src/base/IO.h +++ b/components/omega/src/base/IO.h @@ -40,6 +40,7 @@ #include "DataTypes.h" #include "Error.h" +#include "FloatExcept.h" #include "mpi.h" #include "pio.h" diff --git a/components/omega/src/infra/FloatExcept.cpp b/components/omega/src/infra/FloatExcept.cpp new file mode 100644 index 000000000000..1325ae26f3e7 --- /dev/null +++ b/components/omega/src/infra/FloatExcept.cpp @@ -0,0 +1,207 @@ +//===-- FloatExcept.cpp - Omega floating-point exception handling implementation +//-*- C++ -*-===// +// +/// \file +/// \brief Utilities for handling floating-point exceptions +/// +/// This file contains the implementation of the floating-point exception +/// handling functions for Omega. +// +//===---------------------------------------------------------------------------------------===// + +#include "FloatExcept.h" +#include "OmegaKokkos.h" +#include +#include + +namespace OMEGA { + +// Floating-point exception handling using the feenableexcept GNU extension +#ifdef OMEGA_HAVE_FEENABLEEXCEPT +static FloatExceptStatus enableFloatExceptionsGnuExtension(int Exceptions) { + FloatExceptStatus Status; + + // Clear previous exceptions + int Clear = std::feclearexcept(FE_ALL_EXCEPT); + if (Clear != 0) { + Status.Err += + Error(ErrorCode::Fail, "Failed to clear previous exceptions"); + return Status; + } + + int EnableVal = feenableexcept(Exceptions); + if (EnableVal == -1) { + Status.Err += + Error(ErrorCode::Fail, "Failed to enable floating-point exceptions"); + } else { + Status.OldExceptions = EnableVal; + } + return Status; +} + +static FloatExceptStatus disableFloatExceptionsGnuExtension(int Exceptions) { + FloatExceptStatus Status; + + int DisableVal = fedisableexcept(Exceptions); + + if (DisableVal == -1) { + Status.Err += + Error(ErrorCode::Fail, "Failed to disable floating-point exceptions"); + } else { + Status.OldExceptions = DisableVal; + } + + return Status; +} +#endif + +// Floating-point exception handling for ARM64 +#ifdef __aarch64__ + +// Exception bits in fpcr are shifted by this amount +static constexpr int FPCRShift = 8; + +static FloatExceptStatus enableFloatExceptionsArm64(int Exceptions) { + FloatExceptStatus Status; + + std::fenv_t env; + if (fegetenv(&env) != 0) { + Status.Err += Error(ErrorCode::Fail, "Failed to get floating-point env"); + return Status; + } + + // Get currently enabled exceptions + Status.OldExceptions = (env.__fpcr >> FPCRShift) & FE_ALL_EXCEPT; + + // Clear all exceptions + env.__fpsr &= ~FE_ALL_EXCEPT; + + // Enable selected exceptions + env.__fpcr |= (Exceptions << FPCRShift); + + if (fesetenv(&env) != 0) { + Status.Err += Error(ErrorCode::Fail, "Failed to set floating-point env"); + } + + return Status; +} + +static FloatExceptStatus disableFloatExceptionsArm64(int Exceptions) { + FloatExceptStatus Status; + + std::fenv_t env; + if (fegetenv(&env) != 0) { + Status.Err += Error(ErrorCode::Fail, "Failed to get floating-point env"); + return Status; + } + + // Get currently enabled exceptions + Status.OldExceptions = (env.__fpcr >> FPCRShift) & FE_ALL_EXCEPT; + + // Disable selected exceptions + env.__fpcr &= ~(Exceptions << FPCRShift); + + if (fesetenv(&env) != 0) { + Status.Err += Error(ErrorCode::Fail, "Failed to set floating-point env"); + } + + return Status; +} +#endif + +// Enable selected floating-point exceptions +// If feenableexcept exists then use it, else +// dispatch based on architecture +FloatExceptStatus enableFloatExceptions(int Exceptions) { + auto EnableLambda = [=]() { +#ifdef OMEGA_HAVE_FEENABLEEXCEPT + return enableFloatExceptionsGnuExtension(Exceptions); +#elif defined __aarch64__ + return enableFloatExceptionsArm64(Exceptions); +#else // unsupported arch + return FloatExceptStatus{Error(ErrorCode::Fail, + "Omega doesn't support enabling floating " + "point exceptions on this architecture")}; +#endif + }; + + // Enable exceptions on the main thread + FloatExceptStatus Status = EnableLambda(); + + // Enable exceptions on threads spawned by Kokkos +#if defined(KOKKOS_ENABLE_OPENMP) || defined(KOKKOS_ENABLE_THREADS) + if (Kokkos::is_initialized()) { + const auto NumThreads = ExecSpace().concurrency(); + // Not using Omege wrappers because we want to always use a static + // schedule + const auto Policy = + Kokkos::RangePolicy>( + 0, NumThreads); + Kokkos::parallel_reduce( + Policy, KOKKOS_LAMBDA(int, Error &Err) { Err += EnableLambda().Err; }, + Status.Err); + } +#endif + + return Status; +} + +// Disable selected floating-point exceptions +// If feenableexcept exists then use it, else +// dispatch based on architecture +FloatExceptStatus disableFloatExceptions(int Exceptions) { + auto DisableLambda = [=]() { +#ifdef OMEGA_HAVE_FEENABLEEXCEPT + return disableFloatExceptionsGnuExtension(Exceptions); +#elif defined __aarch64__ + return disableFloatExceptionsArm64(Exceptions); +#else // unsupported arch + return FloatExceptStatus{Error(ErrorCode::Fail, + "Omega doesn't support disabling floating " + "point exceptions on this architecture")}; +#endif + }; + + // Disable exceptions on the main thread + FloatExceptStatus Status = DisableLambda(); + + // Disable exceptions on threads spawned by Kokkos +#if defined(KOKKOS_ENABLE_OPENMP) || defined(KOKKOS_ENABLE_THREADS) + + if (Kokkos::is_initialized()) { + const auto NumThreads = ExecSpace().concurrency(); + // Not using Omega wrappers because we want to always use a static + // schedule + const auto Policy = + Kokkos::RangePolicy>( + 0, NumThreads); + Kokkos::parallel_reduce( + Policy, + KOKKOS_LAMBDA(int, Error &Err) { Err += DisableLambda().Err; }, + Status.Err); + } +#endif + + return Status; +} + +// A helper function to conditionally enable floating-point exceptions in Omega +// unit tests Floating-point exceptions are enabled when explicitly requested +// using the OMEGA_FPEXCEPTS_IN_TESTS CMake option or when using the GNU +// compiler +FloatExceptStatus enableFloatExceptionsInTests(int Exceptions) { + FloatExceptStatus Status; +// Enable if explicitly requested +#ifdef OMEGA_FPEXCEPTS_IN_TESTS + Status = enableFloatExceptions(Exceptions); +#else + // Enable if using the GNU compiler +#if defined(KOKKOS_COMPILER_GNU) + Status = enableFloatExceptions(Exceptions); +#endif +#endif + return Status; +} + +} // namespace OMEGA +//===----------------------------------------------------------------------===// diff --git a/components/omega/src/infra/FloatExcept.h b/components/omega/src/infra/FloatExcept.h new file mode 100644 index 000000000000..7dba22df856a --- /dev/null +++ b/components/omega/src/infra/FloatExcept.h @@ -0,0 +1,46 @@ +#ifndef OMEGA_FLOATEXCEPT_H +#define OMEGA_FLOATEXCEPT_H +//===-- FloatExcept.h - Omega floating-point exception control --*- C++ -*-===// +// +/// \file +/// \brief Utilities for handling floating-point exceptions +/// +/// This header defines functions for enabling and disabling floating-point +/// exceptions in Omega +// +//===----------------------------------------------------------------------===// + +#include "Error.h" +#include + +namespace OMEGA { + +// Return value for the functions in this module combining error code with +// old exceptions mask +struct FloatExceptStatus { + Error Err{}; + int OldExceptions{}; +}; + +// Enable selected floating-point exceptions +// Returns FloatExceptStatus, which on success contains exceptions mask before +// the call to this function +FloatExceptStatus enableFloatExceptions(int Exceptions = (FE_DIVBYZERO | + FE_INVALID | + FE_OVERFLOW)); + +// Disable selected floating-point exceptions +// Returns FloatExceptStatus, which on success contains exceptions mask before +// the call to this function +FloatExceptStatus disableFloatExceptions(int Exceptions = FE_ALL_EXCEPT); + +// A helper function to conditionally enable floating-point exceptions in Omega +// unit tests Floating-point exceptions are enabled when explicitly requested +// using the OMEGA_FPEXCEPTS_IN_TESTS CMake option or when using the GNU +// compiler +FloatExceptStatus enableFloatExceptionsInTests(int Exceptions = (FE_DIVBYZERO | + FE_INVALID | + FE_OVERFLOW)); +} // namespace OMEGA +//===----------------------------------------------------------------------===// +#endif // OMEGA_FLOATEXCEPT_H diff --git a/components/omega/src/ocn/AuxiliaryState.cpp b/components/omega/src/ocn/AuxiliaryState.cpp index be5f0a946141..68e34c71d1d9 100644 --- a/components/omega/src/ocn/AuxiliaryState.cpp +++ b/components/omega/src/ocn/AuxiliaryState.cpp @@ -211,7 +211,7 @@ void AuxiliaryState::computeMomAux(const OceanState *State, Pacer::start("AuxState:vertexAuxState1", 2); parallelForOuter( "vertexAuxState1", - LaunchConfig({Mesh->NVerticesAll}, + LaunchConfig({Mesh->NVerticesHaloH(2)}, TeamScratch(2 * VCoord->NVertLayers)), KOKKOS_LAMBDA(int IVertex, const TeamMember &Team) { LocVorticityAux.computeVarsOnVertex(Team, IVertex, PseudoThickCell, diff --git a/components/omega/src/ocn/VertAdv.cpp b/components/omega/src/ocn/VertAdv.cpp index 6ea7ec3db610..a8cdffacbd28 100644 --- a/components/omega/src/ocn/VertAdv.cpp +++ b/components/omega/src/ocn/VertAdv.cpp @@ -475,10 +475,10 @@ void VertAdv::computeVerticalPseudoVelocityImpl( OMEGA_SCOPE(LocESOnC, Mesh->EdgeSignOnCell); OMEGA_SCOPE(LocMaxLayerEdgeTop, VCoord->MaxLayerEdgeTop); - // Loop over all cells owned by the task + // Loop over all cells parallelForOuter( "computeVerticalPseudoVelocity", - LaunchConfig({NCellsHalo0}, TeamScratch(NVertLayers)), + LaunchConfig({NCellsAll}, TeamScratch(NVertLayers)), KOKKOS_LAMBDA(int ICell, const TeamMember &Team) { ScratchArray1DReal DivHU(teamScratch(Team), LocNVertLayers); diff --git a/components/omega/test/CMakeLists.txt b/components/omega/test/CMakeLists.txt index 944df2b42102..96bab84dba75 100644 --- a/components/omega/test/CMakeLists.txt +++ b/components/omega/test/CMakeLists.txt @@ -639,3 +639,15 @@ add_omega_test( analysis/AnalysisSystemTest.cpp "-n;8" ) + +################################ +# Floating-point exceptions test +################################ + +add_omega_test( + FLOAT_EXCEPT_TEST + testFloatExcept.exe + infra/FloatExceptTest.cpp + "-n;1" +) +set_tests_properties(FLOAT_EXCEPT_TEST PROPERTIES WILL_FAIL true) diff --git a/components/omega/test/analysis/AnalysisOperatorTest.cpp b/components/omega/test/analysis/AnalysisOperatorTest.cpp index 4735e8e000ac..93838edb1eee 100644 --- a/components/omega/test/analysis/AnalysisOperatorTest.cpp +++ b/components/omega/test/analysis/AnalysisOperatorTest.cpp @@ -9,6 +9,7 @@ #include "AnalysisOpFactory.h" #include "Decomp.h" #include "Field.h" +#include "FloatExcept.h" #include "Forcing.h" #include "Halo.h" #include "HorzMesh.h" @@ -1254,6 +1255,7 @@ int main(int argc, char *argv[]) { int Err = 0; MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); @@ -1288,6 +1290,7 @@ int main(int argc, char *argv[]) { finalizeAnalysisTest(); } + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); MPI_Barrier(MPI_COMM_WORLD); diff --git a/components/omega/test/analysis/AnalysisSystemTest.cpp b/components/omega/test/analysis/AnalysisSystemTest.cpp index 4160fd938665..9e60218fea12 100644 --- a/components/omega/test/analysis/AnalysisSystemTest.cpp +++ b/components/omega/test/analysis/AnalysisSystemTest.cpp @@ -11,6 +11,7 @@ #include "Decomp.h" #include "Eos.h" #include "Field.h" +#include "FloatExcept.h" #include "Forcing.h" #include "Halo.h" #include "HorzMesh.h" @@ -772,6 +773,7 @@ int main(int argc, char *argv[]) { int ErrCode = 0; MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); @@ -820,6 +822,7 @@ int main(int argc, char *argv[]) { finalizeAnalysisSystemTest(); } + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); MPI_Barrier(MPI_COMM_WORLD); diff --git a/components/omega/test/base/BroadcastTest.cpp b/components/omega/test/base/BroadcastTest.cpp index 4685d1960ca2..892587b1056d 100644 --- a/components/omega/test/base/BroadcastTest.cpp +++ b/components/omega/test/base/BroadcastTest.cpp @@ -11,6 +11,7 @@ #include "Broadcast.h" #include "Error.h" +#include "FloatExcept.h" #include "Logging.h" #include "MachEnv.h" #include "mpi.h" @@ -174,6 +175,7 @@ int main(int argc, char *argv[]) { // Initialize the Logging system initLogging(DefEnv); + enableFloatExceptionsInTests(); LOG_INFO("------ Broadcast Unit Tests ------"); // The subset environments create 4-task sub-environments so @@ -213,6 +215,7 @@ int main(int argc, char *argv[]) { // Cleanup MachEnv::removeEnv("Subset"); LOG_INFO("------ Broadcast Unit Tests Successful ------"); + disableFloatExceptions(); // MPI_Status status; MPI_Barrier(MPI_COMM_WORLD); diff --git a/components/omega/test/base/DataTypesTest.cpp b/components/omega/test/base/DataTypesTest.cpp index 3ea77d99719c..09634a88b7bf 100644 --- a/components/omega/test/base/DataTypesTest.cpp +++ b/components/omega/test/base/DataTypesTest.cpp @@ -14,6 +14,7 @@ #include "DataTypes.h" #include "Error.h" +#include "FloatExcept.h" #include "Logging.h" #include "MachEnv.h" #include "OmegaKokkos.h" @@ -26,6 +27,7 @@ int main(int argc, char *argv[]) { // initialize environments MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); @@ -955,6 +957,7 @@ int main(int argc, char *argv[]) { // MPI_Status status; } LOG_INFO("------ DataTypes Unit Tests Successful ------"); + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); MPI_Barrier(MPI_COMM_WORLD); diff --git a/components/omega/test/base/DecompTest.cpp b/components/omega/test/base/DecompTest.cpp index 72c5f2de5eb7..a0e818d01037 100644 --- a/components/omega/test/base/DecompTest.cpp +++ b/components/omega/test/base/DecompTest.cpp @@ -15,6 +15,7 @@ #include "Config.h" #include "DataTypes.h" #include "Error.h" +#include "FloatExcept.h" #include "IO.h" #include "Logging.h" #include "MachEnv.h" @@ -63,6 +64,7 @@ int main(int argc, char *argv[]) { // Initialize the global MPI environment MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); @@ -164,6 +166,7 @@ int main(int argc, char *argv[]) { LOG_INFO("---- DecompTest: Successful completion ----"); } + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); MPI_Barrier(MPI_COMM_WORLD); diff --git a/components/omega/test/base/HaloTest.cpp b/components/omega/test/base/HaloTest.cpp index 511c5551f7e5..a6e006db8b9b 100644 --- a/components/omega/test/base/HaloTest.cpp +++ b/components/omega/test/base/HaloTest.cpp @@ -18,6 +18,7 @@ #include "Config.h" #include "DataTypes.h" #include "Decomp.h" +#include "FloatExcept.h" #include "IO.h" #include "Logging.h" #include "MachEnv.h" @@ -137,6 +138,7 @@ int main(int argc, char *argv[]) { // Initialize global MPI environment and Kokkos MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); @@ -567,6 +569,7 @@ int main(int argc, char *argv[]) { LOG_INFO("HaloTest: Failed"); } } + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); MPI_Barrier(MPI_COMM_WORLD); diff --git a/components/omega/test/base/IOInitParamsTest.cpp b/components/omega/test/base/IOInitParamsTest.cpp index 21054326d2aa..269f45c4b323 100644 --- a/components/omega/test/base/IOInitParamsTest.cpp +++ b/components/omega/test/base/IOInitParamsTest.cpp @@ -17,6 +17,7 @@ #include "Config.h" #include "DataTypes.h" #include "Error.h" +#include "FloatExcept.h" #include "IO.h" #include "Logging.h" #include "MachEnv.h" @@ -34,6 +35,7 @@ int main(int argc, char *argv[]) { // Initialize the global MPI environment MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); @@ -141,6 +143,7 @@ int main(int argc, char *argv[]) { LOG_INFO("IOInitParamsTest: Successful completion"); } + disableFloatExceptions(); LOG_INFO("----- Driver-owned IO Parameters Unit Tests Successful -----"); Pacer::finalize(); diff --git a/components/omega/test/base/IOTest.cpp b/components/omega/test/base/IOTest.cpp index 5ce66da8ea66..c404dff8b7ef 100644 --- a/components/omega/test/base/IOTest.cpp +++ b/components/omega/test/base/IOTest.cpp @@ -13,6 +13,7 @@ #include "Config.h" #include "DataTypes.h" #include "Decomp.h" +#include "FloatExcept.h" #include "Logging.h" #include "MachEnv.h" #include "Pacer.h" @@ -63,6 +64,7 @@ int main(int argc, char *argv[]) { // Initialize the global MPI environment MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); @@ -791,6 +793,7 @@ int main(int argc, char *argv[]) { LOG_INFO("IOTest: Successful completion"); } + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); MPI_Barrier(MPI_COMM_WORLD); diff --git a/components/omega/test/base/MachEnvTest.cpp b/components/omega/test/base/MachEnvTest.cpp index 39fa18b3f4ee..837f68079f8a 100644 --- a/components/omega/test/base/MachEnvTest.cpp +++ b/components/omega/test/base/MachEnvTest.cpp @@ -14,6 +14,7 @@ #include "MachEnv.h" #include "Error.h" +#include "FloatExcept.h" #include "Logging.h" #include "mpi.h" @@ -63,6 +64,7 @@ int main(int argc, char *argv[]) { // Initialize the global MPI environment MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); // Create reference values based on MPI_COMM_WORLD int WorldTask; int WorldSize; @@ -353,6 +355,7 @@ int main(int argc, char *argv[]) { MachEnv::removeAll(); LOG_INFO("------ MachEnv Unit Tests Successful ------"); + disableFloatExceptions(); // MPI_Status status; MPI_Barrier(MPI_COMM_WORLD); diff --git a/components/omega/test/base/ReductionsTest.cpp b/components/omega/test/base/ReductionsTest.cpp index dafc2bb724ce..a8d0f8bd8163 100644 --- a/components/omega/test/base/ReductionsTest.cpp +++ b/components/omega/test/base/ReductionsTest.cpp @@ -14,6 +14,7 @@ #include #include "Error.h" +#include "FloatExcept.h" #include "Logging.h" #include "MachEnv.h" #include "OmegaKokkos.h" @@ -1644,6 +1645,7 @@ int main(int argc, char *argv[]) { // Initialize various environments and utilities MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(); MachEnv::init(MPI_COMM_WORLD); MachEnv *DefEnv = MachEnv::getDefault(); @@ -1664,6 +1666,7 @@ int main(int argc, char *argv[]) { testArrayReductions(); LOG_INFO("------ Global Reductions Unit Tests Sucessful ------"); + disableFloatExceptions(); // clean up MachEnv::removeAll(); diff --git a/components/omega/test/base/TriDiagSolversTest.cpp b/components/omega/test/base/TriDiagSolversTest.cpp index 3738f9afb04d..4085f50c79f1 100644 --- a/components/omega/test/base/TriDiagSolversTest.cpp +++ b/components/omega/test/base/TriDiagSolversTest.cpp @@ -1,5 +1,6 @@ #include "TriDiagSolvers.h" #include "../ocn/OceanTestCommon.h" +#include "FloatExcept.h" using namespace OMEGA; @@ -446,8 +447,16 @@ int testDiffusionStability() { const Real LargeDiffValue = 1e14; UseGeneralSolver = true; + + // This is expected to produce NaNs so disable floating-point exceptions for + // this test + FloatExceptStatus Status = disableFloatExceptions(); const Real NormGeneralLargeDiff = runDiffusionStability(UseGeneralSolver, LargeDiffValue); + // Re-enable exceptions + if (Status.Err.isSuccess()) { + enableFloatExceptions(Status.OldExceptions); + } if (!std::isnan(NormGeneralLargeDiff)) { Err += 1; @@ -596,6 +605,7 @@ int main(int argc, char *argv[]) { int RetVal = 0; MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(argc, argv); if (argc > 1 && std::string(argv[1]) == std::string("--perf")) { @@ -603,6 +613,7 @@ int main(int argc, char *argv[]) { } else { RetVal += tridiagonalTest(); } + disableFloatExceptions(); Kokkos::finalize(); MPI_Barrier(MPI_COMM_WORLD); diff --git a/components/omega/test/drivers/StandaloneDriverTest.cpp b/components/omega/test/drivers/StandaloneDriverTest.cpp index 4f7c850c45d3..86e387cefa4b 100644 --- a/components/omega/test/drivers/StandaloneDriverTest.cpp +++ b/components/omega/test/drivers/StandaloneDriverTest.cpp @@ -11,6 +11,7 @@ // //===-----------------------------------------------------------------------===/ +#include "FloatExcept.h" #include "OceanDriver.h" #include "OmegaKokkos.h" #include "Pacer.h" @@ -28,7 +29,8 @@ int main(int argc, char *argv[]) { OMEGA::I4 ErrFinalize; MPI_Init(&argc, &argv); // initialize MPI - Kokkos::initialize(); // initialize Kokkos + OMEGA::enableFloatExceptionsInTests(); + Kokkos::initialize(); // initialize Kokkos Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); @@ -72,6 +74,8 @@ int main(int argc, char *argv[]) { LOG_INFO("DriverTest: Successful completion"); } + OMEGA::disableFloatExceptions(); + Pacer::print("omega_driver_test", OMEGA::printTimingAllRanks()); Pacer::finalize(); diff --git a/components/omega/test/infra/BuildConfigTest.cpp b/components/omega/test/infra/BuildConfigTest.cpp index 5dd7125d3b75..402d1dfac008 100644 --- a/components/omega/test/infra/BuildConfigTest.cpp +++ b/components/omega/test/infra/BuildConfigTest.cpp @@ -18,6 +18,7 @@ #include "DataTypes.h" #include "Error.h" +#include "FloatExcept.h" #include "Logging.h" #include "MachEnv.h" #include "OmegaKokkos.h" @@ -64,6 +65,7 @@ int main(int argc, char *argv[]) { // Initialize the global MPI environment MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); @@ -144,6 +146,7 @@ int main(int argc, char *argv[]) { LOG_INFO("BuildConfigTest: OMEGA_TARGET_DEVICE = {}", OmegaIsDevice ? "defined" : "not defined"); } + disableFloatExceptions(); LOG_INFO("----- Build Configuration Unit Tests Successful -----"); Pacer::finalize(); diff --git a/components/omega/test/infra/ConfigTest.cpp b/components/omega/test/infra/ConfigTest.cpp index 5a3562682de2..4d3d2ff9aea4 100644 --- a/components/omega/test/infra/ConfigTest.cpp +++ b/components/omega/test/infra/ConfigTest.cpp @@ -14,6 +14,7 @@ #include "Config.h" #include "Broadcast.h" #include "Error.h" +#include "FloatExcept.h" #include "Logging.h" #include "MachEnv.h" #include "Pacer.h" @@ -43,6 +44,7 @@ int main(int argc, char *argv[]) { initLogging(DefEnv); Pacer::initialize(OmegaComm); Pacer::setPrefix("Omega:"); + enableFloatExceptionsInTests(); LOG_INFO("------ Config unit tests ------"); // Define some variables for a reference configuration @@ -699,6 +701,7 @@ int main(int argc, char *argv[]) { CHECK_ERROR(Err, "Config: expected error retrieving removed config - PASS"); // Finalize environments + disableFloatExceptions(); Pacer::finalize(); MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); diff --git a/components/omega/test/infra/DimensionTest.cpp b/components/omega/test/infra/DimensionTest.cpp index fb147b8572ec..daa59975be48 100644 --- a/components/omega/test/infra/DimensionTest.cpp +++ b/components/omega/test/infra/DimensionTest.cpp @@ -13,6 +13,7 @@ #include "DataTypes.h" #include "Decomp.h" #include "Error.h" +#include "FloatExcept.h" #include "IO.h" #include "Logging.h" #include "MachEnv.h" @@ -95,6 +96,7 @@ int main(int argc, char **argv) { // We do not actually use message passing but need to test the // array types and behavior within the distributed environment MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(); { @@ -265,6 +267,7 @@ int main(int argc, char **argv) { if (NDims > 0) ABORT_ERROR("DimensionTest: remove all test - FAIL"); } + disableFloatExceptions(); LOG_INFO("------ Dimension unit tests successful ------"); // Clean up environments diff --git a/components/omega/test/infra/ErrorTest.cpp b/components/omega/test/infra/ErrorTest.cpp index 1cc4ea4e9dd3..9c75b5b4694a 100644 --- a/components/omega/test/infra/ErrorTest.cpp +++ b/components/omega/test/infra/ErrorTest.cpp @@ -11,6 +11,7 @@ //===-----------------------------------------------------------------------===/ #include "Error.h" +#include "FloatExcept.h" #include "Logging.h" #include "MachEnv.h" @@ -82,6 +83,7 @@ int main(int argc, char **argv) { MachEnv *DefEnv = OMEGA::MachEnv::getDefault(); initLogging(DefEnv); + enableFloatExceptionsInTests(); LOG_INFO("------ Error handler test ------"); // Test default constructor and success check Error ErrDefault; @@ -162,6 +164,7 @@ int main(int argc, char **argv) { } else { passError1(TotalError); } + disableFloatExceptions(); // If code reaches here, the critical error test has failed so return a // success code diff --git a/components/omega/test/infra/FieldTest.cpp b/components/omega/test/infra/FieldTest.cpp index 75e78f55f7b7..1f2e16f50019 100644 --- a/components/omega/test/infra/FieldTest.cpp +++ b/components/omega/test/infra/FieldTest.cpp @@ -15,6 +15,7 @@ #include "Decomp.h" #include "Dimension.h" #include "Error.h" +#include "FloatExcept.h" #include "IO.h" #include "Logging.h" #include "MachEnv.h" @@ -432,6 +433,7 @@ int main(int argc, char **argv) { // Initialize the global MPI environment MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(); { // Call initialization to create reference IO field @@ -881,6 +883,7 @@ int main(int argc, char **argv) { FieldExists = Field::exists("Test2DR8"); TstEval("Clear all fields 2DR8", FieldExists, ShouldExist, Err); } + disableFloatExceptions(); CHECK_ERROR_ABORT(Err, "Some Field Unit Tests FAIL"); LOG_INFO("------ Field Unit Tests Successful ------"); diff --git a/components/omega/test/infra/FloatExceptTest.cpp b/components/omega/test/infra/FloatExceptTest.cpp new file mode 100644 index 000000000000..03b2324d9bb1 --- /dev/null +++ b/components/omega/test/infra/FloatExceptTest.cpp @@ -0,0 +1,38 @@ +//===-- Test driver for Omega floating-point exception control ---*- C++ -*-===/ +// +/// \file +/// \brief Test driver for Omega floating-point exception control +/// +/// This driver tests the capabilities of Omega to unmask floating-point +/// exceptions. It intentionally causes an exception and is expected to fail. +// +//===-----------------------------------------------------------------------===/ + +#include "FloatExcept.h" +#include "MachEnv.h" + +using namespace OMEGA; + +void divByZero() { + volatile double D0 = 0.0; + volatile double D1 = 1.0; + volatile double DInf = D1 / D0; +} + +int main(int argc, char **argv) { + MPI_Init(&argc, &argv); + MachEnv::init(MPI_COMM_WORLD); + MachEnv *DefEnv = OMEGA::MachEnv::getDefault(); + initLogging(DefEnv); + + FloatExceptStatus Status = enableFloatExceptions(); + + divByZero(); + + CHECK_ERROR_ABORT(Status.Err, "Floating-point Exceptions Tests FAIL"); + + MPI_Barrier(MPI_COMM_WORLD); + MPI_Finalize(); + + return 0; +} diff --git a/components/omega/test/infra/IOStreamTest.cpp b/components/omega/test/infra/IOStreamTest.cpp index 1e73a1f5e6b5..25d2c59598a7 100644 --- a/components/omega/test/infra/IOStreamTest.cpp +++ b/components/omega/test/infra/IOStreamTest.cpp @@ -19,6 +19,7 @@ #include "Error.h" #include "Field.h" #include "FillValues.h" +#include "FloatExcept.h" #include "Forcing.h" #include "Halo.h" #include "HorzMesh.h" @@ -204,6 +205,7 @@ int main(int argc, char **argv) { // Initialize the global MPI and Kokkos environments MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); @@ -316,6 +318,7 @@ int main(int argc, char **argv) { // Write final output and remove all streams IOStream::finalize(ModelClock); } + disableFloatExceptions(); // Clean up environments TimeStepper::clear(); diff --git a/components/omega/test/infra/LoggingTest.cpp b/components/omega/test/infra/LoggingTest.cpp index 1409959ffb4b..66fe679c56dc 100644 --- a/components/omega/test/infra/LoggingTest.cpp +++ b/components/omega/test/infra/LoggingTest.cpp @@ -12,6 +12,7 @@ #include +#include "FloatExcept.h" #include "Logging.h" #include "MachEnv.h" @@ -248,6 +249,7 @@ int main(int argc, char **argv) { OMEGA::MachEnv *DefEnv = OMEGA::MachEnv::getDefault(); OMEGA::I4 TaskId = DefEnv->getMyTask(); + enableFloatExceptionsInTests(); try { std::string LogFilePath = "tmplog_" + std::to_string(TaskId) + ".log"; @@ -278,6 +280,7 @@ int main(int argc, char **argv) { std::cout << "Unknown: FAIL" << std::endl; RetVal += 1; } + disableFloatExceptions(); // Finalize environments MPI_Barrier(MPI_COMM_WORLD); diff --git a/components/omega/test/infra/OmegaKokkosFlatParTest.cpp b/components/omega/test/infra/OmegaKokkosFlatParTest.cpp index 2193c1a1433a..29793b475162 100644 --- a/components/omega/test/infra/OmegaKokkosFlatParTest.cpp +++ b/components/omega/test/infra/OmegaKokkosFlatParTest.cpp @@ -9,6 +9,7 @@ //===-----------------------------------------------------------------------===/ #include "Error.h" +#include "FloatExcept.h" #include "Logging.h" #include "MachEnv.h" #include "OmegaKokkos.h" @@ -501,6 +502,7 @@ int main(int argc, char **argv) { MachEnv *DefEnv = MachEnv::getDefault(); initLogging(DefEnv); + enableFloatExceptionsInTests(); try { Kokkos::initialize(argc, argv); { @@ -525,6 +527,7 @@ int main(int argc, char **argv) { } catch (...) { Err += Error(ErrorCode::Fail, "Unknown: FAIL"); } + disableFloatExceptions(); CHECK_ERROR_ABORT(Err, "Kokkos Wrappers Unit Tests FAIL"); diff --git a/components/omega/test/infra/OmegaKokkosHiParTest.cpp b/components/omega/test/infra/OmegaKokkosHiParTest.cpp index 5a638d7f6c58..1ae66da50999 100644 --- a/components/omega/test/infra/OmegaKokkosHiParTest.cpp +++ b/components/omega/test/infra/OmegaKokkosHiParTest.cpp @@ -9,6 +9,7 @@ //===-----------------------------------------------------------------------===/ #include "Error.h" +#include "FloatExcept.h" #include "Logging.h" #include "MachEnv.h" #include "OmegaKokkos.h" @@ -847,6 +848,7 @@ int main(int argc, char **argv) { MachEnv *DefEnv = MachEnv::getDefault(); initLogging(DefEnv); + enableFloatExceptionsInTests(); try { Kokkos::initialize(argc, argv); { @@ -890,6 +892,7 @@ int main(int argc, char **argv) { } catch (...) { Err += Error(ErrorCode::Fail, "Unknown: FAIL"); } + disableFloatExceptions(); CHECK_ERROR_ABORT(Err, "Kokkos Wrappers Unit Tests FAIL"); diff --git a/components/omega/test/infra/TimeIntervalParseExtendedFormatsTest.cpp b/components/omega/test/infra/TimeIntervalParseExtendedFormatsTest.cpp index 5f6b5d685d99..c0c1c5d3a738 100644 --- a/components/omega/test/infra/TimeIntervalParseExtendedFormatsTest.cpp +++ b/components/omega/test/infra/TimeIntervalParseExtendedFormatsTest.cpp @@ -10,6 +10,7 @@ #include "DataTypes.h" #include "Error.h" +#include "FloatExcept.h" #include "Logging.h" #include "MachEnv.h" #include "TimeMgr.h" @@ -64,6 +65,7 @@ int main(int argc, char **argv) { MachEnv *defEnv = MachEnv::getDefault(); initLogging(defEnv); + enableFloatExceptionsInTests(); LOG_INFO("----- TimeIntervalParseExtendedFormatsTest -----"); // Desired: HH:MM:SS(.sss) @@ -86,6 +88,7 @@ int main(int argc, char **argv) { // If we made it here, the tests were successful LOG_INFO("----- TimeIntervalParseExtendedFormatsTest Successful -----"); + disableFloatExceptions(); MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); diff --git a/components/omega/test/infra/TimeIntervalParseTest.cpp b/components/omega/test/infra/TimeIntervalParseTest.cpp index 464b66c6e171..d05c5080603f 100644 --- a/components/omega/test/infra/TimeIntervalParseTest.cpp +++ b/components/omega/test/infra/TimeIntervalParseTest.cpp @@ -7,6 +7,7 @@ #include "DataTypes.h" #include "Error.h" +#include "FloatExcept.h" #include "Logging.h" #include "MachEnv.h" #include "TimeMgr.h" @@ -97,6 +98,7 @@ int main(int argc, char **argv) { MachEnv *defEnv = MachEnv::getDefault(); initLogging(defEnv); + enableFloatExceptionsInTests(); LOG_INFO("----- TimeIntervalParseTest -----"); // Currently documented/implemented format is: @@ -118,6 +120,7 @@ int main(int argc, char **argv) { // If we made it here, we are successful LOG_INFO("----- TimeIntervalParseTest Successful -----"); + disableFloatExceptions(); MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); diff --git a/components/omega/test/infra/TimeMgrTest.cpp b/components/omega/test/infra/TimeMgrTest.cpp index add6f126bd99..f53285188dc8 100644 --- a/components/omega/test/infra/TimeMgrTest.cpp +++ b/components/omega/test/infra/TimeMgrTest.cpp @@ -14,6 +14,7 @@ #include "TimeMgr.h" #include "DataTypes.h" #include "Error.h" +#include "FloatExcept.h" #include "Logging.h" #include "MachEnv.h" #include "mpi.h" @@ -3469,6 +3470,7 @@ int main(int argc, char *argv[]) { MachEnv::init(MPI_COMM_WORLD); MachEnv *DefEnv = MachEnv::getDefault(); + enableFloatExceptionsInTests(); // Initialize the Logging system initLogging(DefEnv); @@ -3481,6 +3483,7 @@ int main(int argc, char *argv[]) { // if it made it here, all tests successful LOG_INFO("----- TimeMgr Unit Tests Successful -----"); + disableFloatExceptions(); MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); diff --git a/components/omega/test/infra/TracersTest.cpp.2 b/components/omega/test/infra/TracersTest.cpp.2 deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/components/omega/test/ocn/AuxiliaryStateTest.cpp b/components/omega/test/ocn/AuxiliaryStateTest.cpp index 891f14aa9470..46513fd915a2 100644 --- a/components/omega/test/ocn/AuxiliaryStateTest.cpp +++ b/components/omega/test/ocn/AuxiliaryStateTest.cpp @@ -5,6 +5,7 @@ #include "Dimension.h" #include "Eos.h" #include "Field.h" +#include "FloatExcept.h" #include "GlobalConstants.h" #include "Halo.h" #include "HorzMesh.h" @@ -82,6 +83,8 @@ int initState() { VCoord->MinLayerEdgeTop, VCoord->MaxLayerEdgeBot, ExchangeHalos::Yes, CartProjection::No); + deepCopy(VCoord->SurfacePressure, 0); + return Err; } @@ -369,11 +372,13 @@ int main(int argc, char *argv[]) { int RetVal = 0; MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(argc, argv); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); RetVal += auxStateTest(); + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); diff --git a/components/omega/test/ocn/AuxiliaryVarsTest.cpp b/components/omega/test/ocn/AuxiliaryVarsTest.cpp index 260ae8cbbf87..afe1709d12dc 100644 --- a/components/omega/test/ocn/AuxiliaryVarsTest.cpp +++ b/components/omega/test/ocn/AuxiliaryVarsTest.cpp @@ -3,6 +3,7 @@ #include "Decomp.h" #include "Dimension.h" #include "Field.h" +#include "FloatExcept.h" #include "GlobalConstants.h" #include "Halo.h" #include "HorzMesh.h" @@ -802,11 +803,13 @@ int main(int argc, char *argv[]) { int RetVal = 0; MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(argc, argv); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); RetVal += auxVarsTest(); + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); diff --git a/components/omega/test/ocn/EosTest.cpp b/components/omega/test/ocn/EosTest.cpp index 7b3f4f2fbc2e..2f1dfcbff081 100644 --- a/components/omega/test/ocn/EosTest.cpp +++ b/components/omega/test/ocn/EosTest.cpp @@ -15,6 +15,7 @@ #include "Decomp.h" #include "Dimension.h" #include "Field.h" +#include "FloatExcept.h" #include "IO.h" #include "IOStream.h" #include "Logging.h" @@ -1590,11 +1591,13 @@ void eosTest(const std::string &MeshFile = "OmegaMesh.nc") { int main(int argc, char *argv[]) { MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(argc, argv); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); eosTest(); + disableFloatExceptions(); LOG_INFO("------ EOS Unit Tests Successful ------"); diff --git a/components/omega/test/ocn/FillValueTest.cpp b/components/omega/test/ocn/FillValueTest.cpp index 974f720515c1..9a2dd4a9153c 100644 --- a/components/omega/test/ocn/FillValueTest.cpp +++ b/components/omega/test/ocn/FillValueTest.cpp @@ -28,6 +28,7 @@ #include "Eos.h" #include "Error.h" #include "Field.h" +#include "FloatExcept.h" #include "Halo.h" #include "HorzMesh.h" #include "IO.h" @@ -154,6 +155,7 @@ int main(int argc, char *argv[]) { Error ErrAll; MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); @@ -456,6 +458,7 @@ int main(int argc, char *argv[]) { Decomp::clear(); MachEnv::removeAll(); } + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); int RetVal = ErrAll.isFail() ? 1 : 0; diff --git a/components/omega/test/ocn/ForcingTest.cpp b/components/omega/test/ocn/ForcingTest.cpp index 15afb6eddd1a..1291248591c0 100644 --- a/components/omega/test/ocn/ForcingTest.cpp +++ b/components/omega/test/ocn/ForcingTest.cpp @@ -12,6 +12,7 @@ #include "Dimension.h" #include "Error.h" #include "Field.h" +#include "FloatExcept.h" #include "GlobalConstants.h" #include "Halo.h" #include "HorzMesh.h" @@ -374,11 +375,13 @@ int main(int argc, char *argv[]) { int RetErr = 0; MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(argc, argv); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); RetErr = forcingTest(); + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); diff --git a/components/omega/test/ocn/HorzMeshTest.cpp b/components/omega/test/ocn/HorzMeshTest.cpp index d88c56cbfec8..765cc2eef975 100644 --- a/components/omega/test/ocn/HorzMeshTest.cpp +++ b/components/omega/test/ocn/HorzMeshTest.cpp @@ -15,6 +15,7 @@ #include "Dimension.h" #include "Error.h" #include "Field.h" +#include "FloatExcept.h" #include "GlobalConstants.h" #include "Halo.h" #include "IO.h" @@ -132,6 +133,7 @@ int main(int argc, char *argv[]) { // Initialize the global MPI environment MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); @@ -690,6 +692,7 @@ int main(int argc, char *argv[]) { Decomp::clear(); MachEnv::removeAll(); } + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); diff --git a/components/omega/test/ocn/HorzOperatorsTest.cpp b/components/omega/test/ocn/HorzOperatorsTest.cpp index bab6fc845b6c..8cac05a64787 100644 --- a/components/omega/test/ocn/HorzOperatorsTest.cpp +++ b/components/omega/test/ocn/HorzOperatorsTest.cpp @@ -4,6 +4,7 @@ #include "Decomp.h" #include "Dimension.h" #include "Field.h" +#include "FloatExcept.h" #include "GlobalConstants.h" #include "Halo.h" #include "HorzMesh.h" @@ -1073,11 +1074,13 @@ int main(int argc, char *argv[]) { int RetVal = 0; MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(argc, argv); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); RetVal += operatorsTest(); + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); diff --git a/components/omega/test/ocn/PGradTest.cpp b/components/omega/test/ocn/PGradTest.cpp index 6cf51b4fe2fd..e9f214976d68 100644 --- a/components/omega/test/ocn/PGradTest.cpp +++ b/components/omega/test/ocn/PGradTest.cpp @@ -14,6 +14,7 @@ #include "Eos.h" #include "Error.h" #include "Field.h" +#include "FloatExcept.h" #include "GlobalConstants.h" #include "Halo.h" #include "HorzMesh.h" @@ -95,6 +96,7 @@ int main(int argc, char *argv[]) { int RetVal = 0; MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); @@ -333,6 +335,7 @@ int main(int argc, char *argv[]) { Decomp::clear(); MachEnv::removeAll(); } + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); MPI_Barrier(MPI_COMM_WORLD); diff --git a/components/omega/test/ocn/SfcCouplingTest.cpp b/components/omega/test/ocn/SfcCouplingTest.cpp index cffb037c82cd..282ad4bb116e 100644 --- a/components/omega/test/ocn/SfcCouplingTest.cpp +++ b/components/omega/test/ocn/SfcCouplingTest.cpp @@ -5,6 +5,7 @@ #include "Decomp.h" #include "Eos.h" #include "Field.h" +#include "FloatExcept.h" #include "Forcing.h" #include "GlobalConstants.h" #include "Halo.h" @@ -695,11 +696,13 @@ int main(int argc, char *argv[]) { int RetVal = 0; MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(argc, argv); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); RetVal += sfcCouplingTest(); + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); diff --git a/components/omega/test/ocn/StateTest.cpp b/components/omega/test/ocn/StateTest.cpp index ed722a354fe3..87542c2604bf 100644 --- a/components/omega/test/ocn/StateTest.cpp +++ b/components/omega/test/ocn/StateTest.cpp @@ -16,6 +16,7 @@ #include "Eos.h" #include "Error.h" #include "Field.h" +#include "FloatExcept.h" #include "Forcing.h" #include "Halo.h" #include "HorzMesh.h" @@ -226,6 +227,7 @@ int main(int argc, char *argv[]) { // Initialize the global MPI environment MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); @@ -469,6 +471,7 @@ int main(int argc, char *argv[]) { if (RetVal == 0) LOG_INFO("State: Successful completion"); } + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); MPI_Barrier(MPI_COMM_WORLD); diff --git a/components/omega/test/ocn/TendenciesTest.cpp b/components/omega/test/ocn/TendenciesTest.cpp index c20d9cf8a936..ade72830677d 100644 --- a/components/omega/test/ocn/TendenciesTest.cpp +++ b/components/omega/test/ocn/TendenciesTest.cpp @@ -8,6 +8,7 @@ #include "Eos.h" #include "Error.h" #include "Field.h" +#include "FloatExcept.h" #include "Forcing.h" #include "GlobalConstants.h" #include "Halo.h" @@ -102,6 +103,8 @@ int initState() { VCoord->MinLayerEdgeTop, VCoord->MaxLayerEdgeBot, ExchangeHalos::Yes, CartProjection::No, SetBoundary::Yes); + deepCopy(VCoord->SurfacePressure, 0); + return Err; } @@ -762,11 +765,13 @@ int main(int argc, char *argv[]) { int RetVal = 0; MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(argc, argv); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); RetVal += tendenciesTest(); + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); diff --git a/components/omega/test/ocn/TendencyTermsTest.cpp b/components/omega/test/ocn/TendencyTermsTest.cpp index 8e4624fa09ab..cdce7672a32c 100644 --- a/components/omega/test/ocn/TendencyTermsTest.cpp +++ b/components/omega/test/ocn/TendencyTermsTest.cpp @@ -21,6 +21,7 @@ #include "Dimension.h" #include "Error.h" #include "Field.h" +#include "FloatExcept.h" #include "GlobalConstants.h" #include "Halo.h" #include "HorzMesh.h" @@ -1372,7 +1373,7 @@ int testFCTTracerHorzAdvOnCell(int NVertLayers, int NTracers, Real RTol) { VertAdv::init(); const auto VAdv = VertAdv::getDefault(); deepCopy(VAdv->VerticalPseudoVelocity, 10._Real); - deepCopy(VAdv->TotalVerticalPseudoVelocity, 10._Real); + deepCopy(VAdv->TotalVerticalTransportPseudoVelocity, 10._Real); TracerHorzAdvOnCellTest TrHorzAdvOnC(Mesh, VCoord, VAdv); TrHorzAdvOnC.ForceLowOrder = false; @@ -2027,11 +2028,13 @@ int main(int argc, char *argv[]) { int RetErr = 0; MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(argc, argv); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); RetErr = tendencyTermsTest(); + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); diff --git a/components/omega/test/ocn/TracersTest.cpp b/components/omega/test/ocn/TracersTest.cpp index fad0bc52f757..fefa2b72737c 100644 --- a/components/omega/test/ocn/TracersTest.cpp +++ b/components/omega/test/ocn/TracersTest.cpp @@ -14,6 +14,7 @@ #include "Dimension.h" #include "Error.h" #include "Field.h" +#include "FloatExcept.h" #include "Halo.h" #include "HorzMesh.h" #include "IO.h" @@ -94,6 +95,7 @@ int main(int argc, char *argv[]) { // Initialize the global MPI environment MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); @@ -468,6 +470,7 @@ int main(int argc, char *argv[]) { if (RetVal == 0) LOG_INFO("Tracers: Successful completion"); } + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); MPI_Barrier(MPI_COMM_WORLD); diff --git a/components/omega/test/ocn/VertAdvTest.cpp b/components/omega/test/ocn/VertAdvTest.cpp index 5696da7436fa..4f21eb7e1737 100644 --- a/components/omega/test/ocn/VertAdvTest.cpp +++ b/components/omega/test/ocn/VertAdvTest.cpp @@ -11,6 +11,7 @@ #include "Config.h" #include "DataTypes.h" #include "Decomp.h" +#include "FloatExcept.h" #include "GlobalConstants.h" #include "HorzMesh.h" #include "IO.h" @@ -170,6 +171,7 @@ int main(int argc, char *argv[]) { // Initialize the global MPI environment MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); @@ -446,6 +448,7 @@ int main(int argc, char *argv[]) { finalizeVertAdvTest(); } + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); diff --git a/components/omega/test/ocn/VertCoordTest.cpp b/components/omega/test/ocn/VertCoordTest.cpp index d726066e88df..b8e504bd0931 100644 --- a/components/omega/test/ocn/VertCoordTest.cpp +++ b/components/omega/test/ocn/VertCoordTest.cpp @@ -13,6 +13,7 @@ #include "Dimension.h" #include "Error.h" #include "Field.h" +#include "FloatExcept.h" #include "GlobalConstants.h" #include "Halo.h" #include "HorzMesh.h" @@ -86,6 +87,7 @@ int main(int argc, char *argv[]) { // Initialize the global MPI environment MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); @@ -775,6 +777,7 @@ int main(int argc, char *argv[]) { Decomp::clear(); MachEnv::removeAll(); } + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize(); diff --git a/components/omega/test/ocn/VertMixTest.cpp b/components/omega/test/ocn/VertMixTest.cpp index d60315520819..a328ca2a5c78 100644 --- a/components/omega/test/ocn/VertMixTest.cpp +++ b/components/omega/test/ocn/VertMixTest.cpp @@ -15,6 +15,7 @@ #include "Dimension.h" #include "Field.h" #include "FillValues.h" +#include "FloatExcept.h" #include "HorzMesh.h" #include "IO.h" #include "IOStream.h" @@ -1085,11 +1086,13 @@ void vertMixTest() { int main(int argc, char *argv[]) { MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(argc, argv); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); vertMixTest(); + disableFloatExceptions(); LOG_INFO("------ Vertical Mixing Unit Tests Successful ------"); Kokkos::finalize(); diff --git a/components/omega/test/timeStepping/TimeStepperTest.cpp b/components/omega/test/timeStepping/TimeStepperTest.cpp index d1617f19fe85..ef7ba93c4943 100644 --- a/components/omega/test/timeStepping/TimeStepperTest.cpp +++ b/components/omega/test/timeStepping/TimeStepperTest.cpp @@ -22,6 +22,7 @@ #include "Eos.h" #include "Error.h" #include "Field.h" +#include "FloatExcept.h" #include "Forcing.h" #include "Halo.h" #include "HorzMesh.h" @@ -548,6 +549,7 @@ int main(int argc, char *argv[]) { int RetVal = 0; MPI_Init(&argc, &argv); + enableFloatExceptionsInTests(); Kokkos::initialize(argc, argv); Pacer::initialize(MPI_COMM_WORLD); Pacer::setPrefix("Omega:"); @@ -555,6 +557,7 @@ int main(int argc, char *argv[]) { LOG_INFO("----- Time Stepper Unit Test -----"); RetVal += timeStepperTest("OmegaSphereMesh.nc"); + disableFloatExceptions(); Pacer::finalize(); Kokkos::finalize();