Merge pull request #3736 from lammps/always-exceptions

Always throw exceptions for errors
This commit is contained in:
Axel Kohlmeyer
2023-08-03 21:00:19 -04:00
committed by GitHub
45 changed files with 101 additions and 316 deletions

View File

@ -384,11 +384,6 @@ if(NOT ${LAMMPS_MEMALIGN} STREQUAL "0")
target_compile_definitions(lammps PRIVATE -DLAMMPS_MEMALIGN=${LAMMPS_MEMALIGN})
endif()
option(LAMMPS_EXCEPTIONS "enable the use of C++ exceptions for error messages (useful for library interface)" ${ENABLE_TESTING})
if(LAMMPS_EXCEPTIONS)
target_compile_definitions(lammps PUBLIC -DLAMMPS_EXCEPTIONS)
endif()
# "hard" dependencies between packages resulting
# in an error instead of skipping over files
pkg_depends(ML-IAP ML-SNAP)

View File

@ -28,9 +28,7 @@ if(MSVC)
add_compile_options(/Zc:__cplusplus)
add_compile_options(/wd4244)
add_compile_options(/wd4267)
if(LAMMPS_EXCEPTIONS)
add_compile_options(/EHsc)
endif()
add_compile_options(/EHsc)
endif()
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif()

View File

@ -44,9 +44,6 @@ if(BUILD_LAMMPS_SHELL)
endif()
find_package(PkgConfig REQUIRED)
pkg_check_modules(READLINE IMPORTED_TARGET REQUIRED readline)
if(NOT LAMMPS_EXCEPTIONS)
message(WARNING "The LAMMPS shell needs LAMMPS_EXCEPTIONS enabled for full functionality")
endif()
# include resource compiler to embed icons into the executable on Windows
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")

View File

@ -459,27 +459,13 @@ those systems:
.. _exceptions:
Exception handling when using LAMMPS as a library
------------------------------------------------------------------
-------------------------------------------------
This setting is useful when external codes drive LAMMPS as a library.
With this option enabled, LAMMPS errors do not kill the calling code.
Instead, the call stack is unwound and control returns to the caller,
e.g. to Python. Of course, the calling code has to be set up to
*catch* exceptions thrown from within LAMMPS.
.. tabs::
.. tab:: CMake build
.. code-block:: bash
-D LAMMPS_EXCEPTIONS=value # yes or no (default)
.. tab:: Traditional make
.. code-block:: make
LMP_INC = -DLAMMPS_EXCEPTIONS <other LMP_INC settings>
LAMMPS errors do not kill the calling code, but throw an exception. In
the C-library interface, the call stack is unwound and control returns
to the caller, e.g. to Python or a code that is coupled to LAMMPS and
the error status can be queried. When using C++ directly, the calling
code has to be set up to *catch* exceptions thrown from within LAMMPS.
.. note::

View File

@ -2278,19 +2278,13 @@ Procedures Bound to the :f:type:`lammps` Derived Type
.. versionadded:: 3Nov2022
In case of an error, LAMMPS will either abort or throw a C++ exception.
The latter has to be :ref:`enabled at compile time <exceptions>`.
This function checks if exceptions were enabled.
When using the library interface with C++ exceptions enabled, the library
interface functions will "catch" them, and the error status can then be
checked by calling :f:func:`has_error`. The most recent error message can be
retrieved via :f:func:`get_last_error_message`.
This can allow one to restart a calculation or delete and recreate
the LAMMPS instance when a C++ exception occurs. One application
of using exceptions this way is the :ref:`lammps_shell`. If C++
exceptions are disabled and an error happens during a call to
LAMMPS or the Fortran API, the application will terminate.
When using the library interface, the library interface functions
will "catch" exceptions, and then the error status can be checked by
calling :f:func:`has_error`. The most recent error message can be
retrieved via :f:func:`get_last_error_message`. This allows to
restart a calculation or delete and recreate the LAMMPS instance when
a C++ exception occurs. One application of using exceptions this way
is the :ref:`lammps_shell`.
:to: :cpp:func:`lammps_config_has_exceptions`
:r has_exceptions:

View File

@ -338,8 +338,6 @@ Some common LAMMPS specific variables
- common compiler flags, for optimization or instrumentation (default:)
* - ``LAMMPS_MACHINE``
- when set to ``name`` the LAMMPS executable and library will be called ``lmp_name`` and ``liblammps_name.a``
* - ``LAMMPS_EXCEPTIONS``
- when set to ``on`` errors will throw a C++ exception instead of aborting (default: ``off``)
* - ``FFT``
- select which FFT library to use: ``FFTW3``, ``MKL``, ``KISS`` (default, unless FFTW3 is found)
* - ``FFT_SINGLE``
@ -412,9 +410,9 @@ interface (``ccmake`` or ``cmake-gui``).
Using a preset to select a compiler package (``clang.cmake``,
``gcc.cmake``, ``intel.cmake``, ``oneapi.cmake``, or ``pgi.cmake``)
are an exception to the mechanism of updating the configuration incrementally,
as they will trigger a reset of cached internal CMake settings and thus
reset settings to their default values.
are an exception to the mechanism of updating the configuration
incrementally, as they will trigger a reset of cached internal CMake
settings and thus reset settings to their default values.
Compilation and build targets
-----------------------------

View File

@ -53,10 +53,10 @@ System-wide Installation
Step 1: Building LAMMPS as a shared library
"""""""""""""""""""""""""""""""""""""""""""
To use LAMMPS inside of Python it has to be compiled as shared library. This
library is then loaded by the Python interface. In this example we enable the
MOLECULE package and compile LAMMPS with C++ exceptions, PNG, JPEG and FFMPEG
output support enabled.
To use LAMMPS inside of Python it has to be compiled as shared
library. This library is then loaded by the Python interface. In this
example we enable the MOLECULE package and compile LAMMPS with PNG, JPEG
and FFMPEG output support enabled.
Step 1a: For the CMake based build system, the steps are:
@ -66,7 +66,7 @@ Step 1a: For the CMake based build system, the steps are:
cd $LAMMPS_DIR/build-shared
# MPI, PNG, Jpeg, FFMPEG are auto-detected
cmake ../cmake -DPKG_MOLECULE=yes -DLAMMPS_EXCEPTIONS=yes -DBUILD_LIB=yes -DBUILD_SHARED_LIBS=yes
cmake ../cmake -DPKG_MOLECULE=yes -DBUILD_LIB=yes -DBUILD_SHARED_LIBS=yes
make
Step 1b: For the legacy, make based build system, the steps are:
@ -79,7 +79,7 @@ Step 1b: For the legacy, make based build system, the steps are:
make yes-MOLECULE
# compile shared library using Makefile
make mpi mode=shlib LMP_INC="-DLAMMPS_PNG -DLAMMPS_JPEG -DLAMMPS_FFMPEG -DLAMMPS_EXCEPTIONS" JPG_LIB="-lpng -ljpeg"
make mpi mode=shlib LMP_INC="-DLAMMPS_PNG -DLAMMPS_JPEG -DLAMMPS_FFMPEG" JPG_LIB="-lpng -ljpeg"
Step 2: Installing the LAMMPS Python package
""""""""""""""""""""""""""""""""""""""""""""
@ -356,18 +356,16 @@ Together with matplotlib plotting data out of LAMMPS becomes simple:
Error handling with PyLammps
----------------------------
Compiling the shared library with C++ exception support provides a better error
handling experience. Without exceptions the LAMMPS code will terminate the
current Python process with an error message. C++ exceptions allow capturing
them on the C++ side and rethrowing them on the Python side. This way you
can handle LAMMPS errors through the Python exception handling mechanism.
Using C++ exceptions in LAMMPS for errors allows capturing them on the
C++ side and rethrowing them on the Python side. This way you can handle
LAMMPS errors through the Python exception handling mechanism.
.. warning::
Capturing a LAMMPS exception in Python can still mean that the
current LAMMPS process is in an illegal state and must be terminated. It is
advised to save your data and terminate the Python instance as quickly as
possible.
current LAMMPS process is in an illegal state and must be
terminated. It is advised to save your data and terminate the Python
instance as quickly as possible.
Using PyLammps in IPython notebooks and Jupyter
-----------------------------------------------

View File

@ -1,11 +1,11 @@
Handling LAMMPS errors
*******************************
**********************
Compiling the shared library with :ref:`C++ exception support <exceptions>` provides a better error
handling experience. Without exceptions the LAMMPS code will terminate the
current Python process with an error message. C++ exceptions allow capturing
them on the C++ side and rethrowing them on the Python side. This way
LAMMPS errors can be handled through the Python exception handling mechanism.
The shared library is compiled with :ref:`C++ exception support
<exceptions>` to provide a better error handling experience. C++
exceptions allow capturing errors on the C++ side and rethrowing them on
the Python side. This way LAMMPS errors can be handled through the
Python exception handling mechanism.
.. code-block:: python
@ -31,6 +31,6 @@ LAMMPS errors can be handled through the Python exception handling mechanism.
.. warning::
Capturing a LAMMPS exception in Python can still mean that the
current LAMMPS process is in an illegal state and must be terminated. It is
advised to save your data and terminate the Python instance as quickly as
possible.
current LAMMPS process is in an illegal state and must be
terminated. It is advised to save your data and terminate the Python
instance as quickly as possible when running in parallel with MPI.

View File

@ -23,9 +23,7 @@ endif()
# and prints lots of pointless warnings about "unsafe" functions
if(MSVC)
if(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
if(LAMMPS_EXCEPTIONS)
add_compile_options(/EHsc)
endif()
add_compile_options(/EHsc)
endif()
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif()

View File

@ -18,9 +18,7 @@ endif()
# and prints lots of pointless warnings about "unsafe" functions
if(MSVC)
if(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
if(LAMMPS_EXCEPTIONS)
add_compile_options(/EHsc)
endif()
add_compile_options(/EHsc)
endif()
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif()

View File

@ -36,9 +36,7 @@ else()
add_compile_options(/Zc:__cplusplus)
add_compile_options(/wd4244)
add_compile_options(/wd4267)
if(LAMMPS_EXCEPTIONS)
add_compile_options(/EHsc)
endif()
add_compile_options(/EHsc)
endif()
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif()

View File

@ -18,10 +18,7 @@
#include "input.h"
#include "output.h"
#include "universe.h"
#if defined(LAMMPS_EXCEPTIONS)
#include "update.h"
#endif
using namespace LAMMPS_NS;
@ -40,10 +37,8 @@ static std::string truncpath(const std::string &path)
Error::Error(LAMMPS *lmp)
: Pointers(lmp), numwarn(0), maxwarn(100), allwarn(0)
{
#ifdef LAMMPS_EXCEPTIONS
last_error_message.clear();
last_error_type = ERROR_NONE;
#endif
}
/* ----------------------------------------------------------------------
@ -73,19 +68,11 @@ void Error::universe_all(const std::string &file, int line, const std::string &s
}
if (universe->ulogfile) fclose(universe->ulogfile);
#ifdef LAMMPS_EXCEPTIONS
// allow commands if an exception was caught in a run
// update may be a null pointer when catching command line errors
if (update) update->whichflag = 0;
throw LAMMPSException(mesg);
#else
KokkosLMP::finalize();
MPI_Finalize();
exit(1);
#endif
}
/* ----------------------------------------------------------------------
@ -99,19 +86,11 @@ void Error::universe_one(const std::string &file, int line, const std::string &s
universe->me,str,truncpath(file),line);
if (universe->uscreen) fputs(mesg.c_str(),universe->uscreen);
#ifdef LAMMPS_EXCEPTIONS
// allow commands if an exception was caught in a run
// update may be a null pointer when catching command line errors
if (update) update->whichflag = 0;
throw LAMMPSAbortException(mesg, universe->uworld);
#else
KokkosLMP::finalize();
MPI_Abort(universe->uworld,1);
exit(1); // to trick "smart" compilers into believing this does not return
#endif
}
/* ----------------------------------------------------------------------
@ -155,31 +134,17 @@ void Error::all(const std::string &file, int line, const std::string &str)
utils::logmesg(lmp,mesg);
}
#ifdef LAMMPS_EXCEPTIONS
// allow commands if an exception was caught in a run
// update may be a null pointer when catching command line errors
if (update) update->whichflag = 0;
std::string msg = fmt::format("ERROR: {} ({}:{})\n",
str, truncpath(file), line);
std::string msg = fmt::format("ERROR: {} ({}:{})\n", str, truncpath(file), line);
if (universe->nworlds > 1) {
if (universe->nworlds > 1)
throw LAMMPSAbortException(msg, universe->uworld);
}
throw LAMMPSException(msg);
#else
if (output) delete output;
if (screen && screen != stdout) fclose(screen);
if (logfile) fclose(logfile);
KokkosLMP::finalize();
if (universe->nworlds > 1) MPI_Abort(universe->uworld,1);
MPI_Finalize();
exit(1);
#endif
else
throw LAMMPSException(msg);
}
/* ----------------------------------------------------------------------
@ -204,20 +169,11 @@ void Error::one(const std::string &file, int line, const std::string &str)
if (universe->uscreen)
fputs(mesg.c_str(),universe->uscreen);
#ifdef LAMMPS_EXCEPTIONS
// allow commands if an exception was caught in a run
// update may be a null pointer when catching command line errors
if (update) update->whichflag = 0;
throw LAMMPSAbortException(mesg, world);
#else
utils::flush_buffers(lmp);
KokkosLMP::finalize();
MPI_Abort(world,1);
exit(1); // to trick "smart" compilers into believing this does not return
#endif
}
/* ----------------------------------------------------------------------
@ -322,10 +278,8 @@ void Error::done(int status)
exit(status);
}
#ifdef LAMMPS_EXCEPTIONS
/* ----------------------------------------------------------------------
return the last error message reported by LAMMPS (only used if
compiled with -DLAMMPS_EXCEPTIONS)
return the last error message reported by LAMMPS
------------------------------------------------------------------------- */
std::string Error::get_last_error() const
@ -334,8 +288,7 @@ std::string Error::get_last_error() const
}
/* ----------------------------------------------------------------------
return the type of the last error reported by LAMMPS (only used if
compiled with -DLAMMPS_EXCEPTIONS)
return the type of the last error reported by LAMMPS
------------------------------------------------------------------------- */
ErrorType Error::get_last_error_type() const
@ -345,12 +298,10 @@ ErrorType Error::get_last_error_type() const
/* ----------------------------------------------------------------------
set the last error message and error type
(only used if compiled with -DLAMMPS_EXCEPTIONS)
------------------------------------------------------------------------- */
void Error::set_last_error(const std::string &msg, ErrorType type)
void Error::set_last_error(const char *msg, ErrorType type)
{
last_error_message = msg;
last_error_type = type;
}
#endif

View File

@ -15,10 +15,7 @@
#define LMP_ERROR_H
#include "pointers.h"
#ifdef LAMMPS_EXCEPTIONS
#include "exceptions.h"
#endif
namespace LAMMPS_NS {
@ -65,17 +62,14 @@ class Error : protected Pointers {
void set_maxwarn(int val) { maxwarn = val; }
void set_allwarn(int val) { allwarn = val; }
#ifdef LAMMPS_EXCEPTIONS
std::string get_last_error() const;
ErrorType get_last_error_type() const;
void set_last_error(const std::string &msg, ErrorType type = ERROR_NORMAL);
void set_last_error(const char *msg, ErrorType type = ERROR_NORMAL);
private:
std::string last_error_message;
ErrorType last_error_type;
#endif
private:
int numwarn, maxwarn, allwarn;
// internal versions that accept explicit fmtlib arguments
[[noreturn]] void _all(const std::string &, int, fmt::string_view, fmt::format_args args);

View File

@ -22,21 +22,23 @@ namespace LAMMPS_NS {
class LAMMPSException : public std::exception {
public:
std::string message;
LAMMPSException(const std::string &msg) : message(msg) {}
const char *what() const noexcept override { return message.c_str(); }
protected:
std::string message;
};
class LAMMPSAbortException : public LAMMPSException {
public:
MPI_Comm universe;
LAMMPSAbortException(const std::string &msg, MPI_Comm _universe) :
LAMMPSException(msg), universe(_universe)
{
}
MPI_Comm get_universe() const { return universe; }
protected:
MPI_Comm universe;
};
enum ErrorType { ERROR_NONE = 0, ERROR_NORMAL = 1, ERROR_ABORT = 2 };

View File

@ -298,7 +298,6 @@ void Info::command(int narg, char **arg)
if (has_jpeg_support()) fputs("-DLAMMPS_JPEG\n",out);
if (has_ffmpeg_support()) fputs("-DLAMMPS_FFMPEG\n",out);
if (has_fft_single_support()) fputs("-DFFT_SINGLE\n",out);
if (has_exceptions()) fputs("-DLAMMPS_EXCEPTIONS\n",out);
#if defined(LAMMPS_BIGBIG)
fputs("-DLAMMPS_BIGBIG\n",out);
@ -1096,11 +1095,7 @@ bool Info::has_fft_single_support() {
}
bool Info::has_exceptions() {
#ifdef LAMMPS_EXCEPTIONS
return true;
#else
return false;
#endif
}
bool Info::has_package(const std::string &package_name) {

View File

@ -1437,7 +1437,6 @@ void LAMMPS::print_config(FILE *fp)
if (Info::has_jpeg_support()) fputs("-DLAMMPS_JPEG\n",fp);
if (Info::has_ffmpeg_support()) fputs("-DLAMMPS_FFMPEG\n",fp);
if (Info::has_fft_single_support()) fputs("-DFFT_SINGLE\n",fp);
if (Info::has_exceptions()) fputs("-DLAMMPS_EXCEPTIONS\n",fp);
#if defined(LAMMPS_BIGBIG)
fputs("-DLAMMPS_BIGBIG\n",fp);
#elif defined(LAMMPS_SMALLBIG)

View File

@ -27,6 +27,7 @@
#include "domain.h"
#include "dump.h"
#include "error.h"
#include "exceptions.h"
#include "fix.h"
#include "fix_external.h"
#include "force.h"
@ -53,10 +54,6 @@
#include <cstring>
#if defined(LAMMPS_EXCEPTIONS)
#include "exceptions.h"
#endif
#if defined(LMP_PYTHON)
#include <Python.h>
#endif
@ -96,7 +93,6 @@ static void ptr_argument_warning()
END_CAPTURE
------------------------------------------------------------------------- */
#ifdef LAMMPS_EXCEPTIONS
#define BEGIN_CAPTURE \
Error *error = lmp->error; \
try
@ -104,20 +100,16 @@ static void ptr_argument_warning()
#define END_CAPTURE \
catch(LAMMPSAbortException &ae) { \
int nprocs = 0; \
MPI_Comm_size(ae.universe, &nprocs ); \
MPI_Comm_size(ae.get_universe(), &nprocs ); \
\
if (nprocs > 1) { \
error->set_last_error(ae.message, ERROR_ABORT); \
error->set_last_error(ae.what(), ERROR_ABORT); \
} else { \
error->set_last_error(ae.message, ERROR_NORMAL); \
error->set_last_error(ae.what(), ERROR_NORMAL); \
} \
} catch(LAMMPSException &e) { \
error->set_last_error(e.message, ERROR_NORMAL); \
error->set_last_error(e.what(), ERROR_NORMAL); \
}
#else
#define BEGIN_CAPTURE
#define END_CAPTURE
#endif
// ----------------------------------------------------------------------
// Library functions to create/destroy an instance of LAMMPS
@ -179,23 +171,20 @@ void *lammps_open(int argc, char **argv, MPI_Comm comm, void **ptr)
lammps_mpi_init();
if (ptr) ptr_argument_warning();
#ifdef LAMMPS_EXCEPTIONS
try
{
try {
lammps_last_global_errormessage.clear();
lmp = new LAMMPS(argc, argv, comm);
if (ptr) *ptr = (void *) lmp;
}
catch(LAMMPSException &e) {
lammps_last_global_errormessage = e.message;
} catch (fmt::format_error &fe) {
lammps_last_global_errormessage = fe.what();
fprintf(stderr, "fmt::format_error: %s\n", fe.what());
if (ptr) *ptr = nullptr;
} catch(LAMMPSException &e) {
lammps_last_global_errormessage = e.what();
fmt::print(stderr, "LAMMPS Exception: {}", e.message);
fmt::print(stderr, "LAMMPS Exception: {}", e.what());
if (ptr) *ptr = nullptr;
}
#else
lmp = new LAMMPS(argc, argv, comm);
if (ptr) *ptr = (void *) lmp;
#endif
return (void *) lmp;
}
@ -490,7 +479,6 @@ void lammps_error(void *handle, int error_type, const char *error_text)
}
END_CAPTURE
#if defined(LAMMPS_EXCEPTIONS)
// with enabled exceptions the above code will simply throw an
// exception and record the error message. So we have to explicitly
// stop here like we do in main.cpp
@ -506,7 +494,6 @@ void lammps_error(void *handle, int error_type, const char *error_text)
exit(1);
}
}
#endif
}
// ----------------------------------------------------------------------
@ -2345,9 +2332,7 @@ void *lammps_extract_variable(void *handle, const char *name, const char *group)
}
}
END_CAPTURE
#if defined(LAMMPS_EXCEPTIONS)
return nullptr;
#endif
}
/* ---------------------------------------------------------------------- */
@ -5483,6 +5468,13 @@ int lammps_config_has_ffmpeg_support() {
/** Check whether LAMMPS errors will throw C++ exceptions.
*
\verbatim embed:rst
.. deprecated:: TBD
LAMMPS has now exceptions always enabled, so this function
will now always return 1 and can be removed from applications
using the library interface.
In case of an error, LAMMPS will either abort or throw a C++ exception.
The latter has to be :ref:`enabled at compile time <exceptions>`.
This function checks if exceptions were enabled.
@ -6516,8 +6508,8 @@ has thrown a :ref:`C++ exception <exceptions>`.
* \param handle pointer to a previously created LAMMPS instance cast to ``void *`` or NULL
* \return 0 on no error, 1 on error.
*/
int lammps_has_error(void *handle) {
#ifdef LAMMPS_EXCEPTIONS
int lammps_has_error(void *handle)
{
if (handle) {
LAMMPS *lmp = (LAMMPS *) handle;
Error *error = lmp->error;
@ -6525,9 +6517,6 @@ int lammps_has_error(void *handle) {
} else {
return lammps_last_global_errormessage.empty() ? 0 : 1;
}
#else
return 0;
#endif
}
/* ---------------------------------------------------------------------- */
@ -6569,8 +6558,8 @@ the failing MPI ranks to send messages.
* \param buf_size size of the provided string buffer
* \return 1 when all ranks had the error, 2 on a single rank error. */
int lammps_get_last_error_message(void *handle, char *buffer, int buf_size) {
#ifdef LAMMPS_EXCEPTIONS
int lammps_get_last_error_message(void *handle, char *buffer, int buf_size)
{
if (handle) {
LAMMPS *lmp = (LAMMPS *) handle;
Error *error = lmp->error;
@ -6591,7 +6580,6 @@ int lammps_get_last_error_message(void *handle, char *buffer, int buf_size) {
return 1;
}
}
#endif
return 0;
}

View File

@ -13,13 +13,10 @@
#include "lammps.h"
#include "exceptions.h"
#include "input.h"
#include "library.h"
#if defined(LAMMPS_EXCEPTIONS)
#include "exceptions.h"
#endif
#include <cstdlib>
#include <mpi.h>
@ -75,14 +72,13 @@ int main(int argc, char **argv)
feenableexcept(FE_OVERFLOW);
#endif
#ifdef LAMMPS_EXCEPTIONS
try {
auto lammps = new LAMMPS(argc, argv, lammps_comm);
lammps->input->file();
delete lammps;
} catch (LAMMPSAbortException &ae) {
finalize();
MPI_Abort(ae.universe, 1);
MPI_Abort(ae.get_universe(), 1);
} catch (LAMMPSException &) {
finalize();
MPI_Barrier(lammps_comm);
@ -99,18 +95,6 @@ int main(int argc, char **argv)
MPI_Abort(MPI_COMM_WORLD, 1);
exit(1);
}
#else
try {
auto lammps = new LAMMPS(argc, argv, lammps_comm);
lammps->input->file();
delete lammps;
} catch (fmt::format_error &fe) {
fprintf(stderr, "fmt::format_error: %s\n", fe.what());
finalize();
MPI_Abort(MPI_COMM_WORLD, 1);
exit(1);
}
#endif
finalize();
MPI_Barrier(lammps_comm);
MPI_Finalize();

View File

@ -13,9 +13,6 @@ option(LAMMPS_GUI_USE_PLUGIN "Load LAMMPS library dynamically at runtime" OFF)
mark_as_advanced(LAMMPS_GUI_USE_PLUGIN)
# checks
if(NOT LAMMPS_EXCEPTIONS)
message(FATAL_ERROR "Must enable LAMMPS_EXCEPTIONS for building the LAMMPS GUI")
endif()
if(BUILD_MPI)
message(FATAL_ERROR "Must disable BUILD_MPI for building the LAMMPS GUI")
endif()

View File

@ -46,13 +46,6 @@ else()
endif()
list(APPEND TEST_CONFIG_DEFS -DLAMMPS_HAS_MPI=${HAS_MPI})
if(LAMMPS_EXCEPTIONS)
set(HAS_EXCEPTIONS 1)
else()
set(HAS_EXCEPTIONS 0)
endif()
list(APPEND TEST_CONFIG_DEFS -DLAMMPS_HAS_EXCEPTIONS=${HAS_EXCEPTIONS})
foreach(WITH "JPEG" "PNG" "GZIP" "FFMPEG")
if(WITH_${WITH})
set(HAS_${WITH} 1)

View File

@ -195,7 +195,7 @@ TEST_F(LibraryConfig, force_timeout)
TEST(LAMMPSConfig, exceptions)
{
EXPECT_EQ(lammps_config_has_exceptions(), LAMMPS_HAS_EXCEPTIONS);
EXPECT_EQ(lammps_config_has_exceptions(), 1);
};
TEST(LAMMPSConfig, mpi_support)

View File

@ -518,9 +518,6 @@ TEST_F(LibraryProperties, neighlist)
TEST_F(LibraryProperties, has_error)
{
// need errors to throw exceptions to be able to intercept them.
if (!lammps_config_has_exceptions()) GTEST_SKIP();
EXPECT_EQ(lammps_has_error(lmp), 0);
// trigger an error, but hide output

View File

@ -402,9 +402,6 @@ int main(int argc, char **argv)
MPI_Init(&argc, &argv);
::testing::InitGoogleMock(&argc, argv);
if (LAMMPS_NS::platform::mpi_vendor() == "Open MPI" && !Info::has_exceptions())
std::cout << "Warning: using OpenMPI without exceptions. Death tests will be skipped\n";
// handle arguments passed via environment variable
if (const char *var = getenv("TEST_ARGS")) {
std::vector<std::string> env = LAMMPS_NS::utils::split_words(var);

View File

@ -393,9 +393,6 @@ int main(int argc, char **argv)
MPI_Init(&argc, &argv);
::testing::InitGoogleMock(&argc, argv);
if (LAMMPS_NS::platform::mpi_vendor() == "Open MPI" && !Info::has_exceptions())
std::cout << "Warning: using OpenMPI without exceptions. Death tests will be skipped\n";
// handle arguments passed via environment variable
if (const char *var = getenv("TEST_ARGS")) {
std::vector<std::string> env = LAMMPS_NS::utils::split_words(var);

View File

@ -161,9 +161,6 @@ int main(int argc, char **argv)
MPI_Init(&argc, &argv);
::testing::InitGoogleMock(&argc, argv);
if (LAMMPS_NS::platform::mpi_vendor() == "Open MPI" && !Info::has_exceptions())
std::cout << "Warning: using OpenMPI without exceptions. Death tests will be skipped\n";
// handle arguments passed via environment variable
if (const char *var = getenv("TEST_ARGS")) {
std::vector<std::string> env = LAMMPS_NS::utils::split_words(var);

View File

@ -469,9 +469,6 @@ int main(int argc, char **argv)
MPI_Init(&argc, &argv);
::testing::InitGoogleMock(&argc, argv);
if (LAMMPS_NS::platform::mpi_vendor() == "Open MPI" && !Info::has_exceptions())
std::cout << "Warning: using OpenMPI without exceptions. Death tests will be skipped\n";
// handle arguments passed via environment variable
if (const char *var = getenv("TEST_ARGS")) {
std::vector<std::string> env = LAMMPS_NS::utils::split_words(var);

View File

@ -683,9 +683,6 @@ int main(int argc, char **argv)
MPI_Init(&argc, &argv);
::testing::InitGoogleMock(&argc, argv);
if (LAMMPS_NS::platform::mpi_vendor() == "Open MPI" && !Info::has_exceptions())
std::cout << "Warning: using OpenMPI without exceptions. Death tests will be skipped\n";
// handle arguments passed via environment variable
if (const char *var = getenv("TEST_ARGS")) {
std::vector<std::string> env = LAMMPS_NS::utils::split_words(var);

View File

@ -299,9 +299,6 @@ int main(int argc, char **argv)
MPI_Init(&argc, &argv);
::testing::InitGoogleMock(&argc, argv);
if (LAMMPS_NS::platform::mpi_vendor() == "Open MPI" && !Info::has_exceptions())
std::cout << "Warning: using OpenMPI without exceptions. Death tests will be skipped\n";
// handle arguments passed via environment variable
if (const char *var = getenv("TEST_ARGS")) {
std::vector<std::string> env = LAMMPS_NS::utils::split_words(var);

View File

@ -632,9 +632,6 @@ int main(int argc, char **argv)
MPI_Init(&argc, &argv);
::testing::InitGoogleMock(&argc, argv);
if (LAMMPS_NS::platform::mpi_vendor() == "Open MPI" && !Info::has_exceptions())
std::cout << "Warning: using OpenMPI without exceptions. Death tests will be skipped\n";
// handle arguments passed via environment variable
if (const char *var = getenv("TEST_ARGS")) {
std::vector<std::string> env = LAMMPS_NS::utils::split_words(var);

View File

@ -285,9 +285,6 @@ int main(int argc, char **argv)
MPI_Init(&argc, &argv);
::testing::InitGoogleMock(&argc, argv);
if (LAMMPS_NS::platform::mpi_vendor() == "Open MPI" && !Info::has_exceptions())
std::cout << "Warning: using OpenMPI without exceptions. Death tests will be skipped\n";
// handle arguments passed via environment variable
if (const char *var = getenv("TEST_ARGS")) {
std::vector<std::string> env = LAMMPS_NS::utils::split_words(var);

View File

@ -806,9 +806,6 @@ int main(int argc, char **argv)
MPI_Init(&argc, &argv);
::testing::InitGoogleMock(&argc, argv);
if (LAMMPS_NS::platform::mpi_vendor() == "Open MPI" && !Info::has_exceptions())
std::cout << "Warning: using OpenMPI without exceptions. Death tests will be skipped\n";
// handle arguments passed via environment variable
if (const char *var = getenv("TEST_ARGS")) {
std::vector<std::string> env = LAMMPS_NS::utils::split_words(var);

View File

@ -460,9 +460,6 @@ int main(int argc, char **argv)
MPI_Init(&argc, &argv);
::testing::InitGoogleMock(&argc, argv);
if (LAMMPS_NS::platform::mpi_vendor() == "Open MPI" && !Info::has_exceptions())
std::cout << "Warning: using OpenMPI without exceptions. Death tests will be skipped\n";
// handle arguments passed via environment variable
if (const char *var = getenv("TEST_ARGS")) {
std::vector<std::string> env = LAMMPS_NS::utils::split_words(var);

View File

@ -560,9 +560,6 @@ int main(int argc, char **argv)
MPI_Init(&argc, &argv);
::testing::InitGoogleMock(&argc, argv);
if (LAMMPS_NS::platform::mpi_vendor() == "Open MPI" && !Info::has_exceptions())
std::cout << "Warning: using OpenMPI without exceptions. Death tests will be skipped\n";
// handle arguments passed via environment variable
if (const char *var = getenv("TEST_ARGS")) {
std::vector<std::string> env = LAMMPS_NS::utils::split_words(var);

View File

@ -774,9 +774,6 @@ int main(int argc, char **argv)
MPI_Init(&argc, &argv);
::testing::InitGoogleMock(&argc, argv);
if (LAMMPS_NS::platform::mpi_vendor() == "Open MPI" && !Info::has_exceptions())
std::cout << "Warning: using OpenMPI without exceptions. Death tests will be skipped\n";
// handle arguments passed via environment variable
if (const char *var = getenv("TEST_ARGS")) {
std::vector<std::string> env = LAMMPS_NS::utils::split_words(var);

View File

@ -224,9 +224,6 @@ int main(int argc, char **argv)
MPI_Init(&argc, &argv);
::testing::InitGoogleMock(&argc, argv);
if (LAMMPS_NS::platform::mpi_vendor() == "Open MPI" && !Info::has_exceptions())
std::cout << "Warning: using OpenMPI without exceptions. Death tests will be skipped\n";
// handle arguments passed via environment variable
if (const char *var = getenv("TEST_ARGS")) {
std::vector<std::string> env = LAMMPS_NS::utils::split_words(var);

View File

@ -125,9 +125,6 @@ int main(int argc, char **argv)
MPI_Init(&argc, &argv);
::testing::InitGoogleMock(&argc, argv);
if (LAMMPS_NS::platform::mpi_vendor() == "Open MPI" && !Info::has_exceptions())
std::cout << "Warning: using OpenMPI without exceptions. Death tests will be skipped\n";
// handle arguments passed via environment variable
if (const char *var = getenv("TEST_ARGS")) {
std::vector<std::string> env = LAMMPS_NS::utils::split_words(var);

View File

@ -618,9 +618,6 @@ int main(int argc, char **argv)
MPI_Init(&argc, &argv);
::testing::InitGoogleMock(&argc, argv);
if (platform::mpi_vendor() == "Open MPI" && !Info::has_exceptions())
std::cout << "Warning: using OpenMPI without exceptions. Death tests will be skipped\n";
// handle arguments passed via environment variable
if (const char *var = getenv("TEST_ARGS")) {
std::vector<std::string> env = split_words(var);

View File

@ -409,9 +409,6 @@ int main(int argc, char **argv)
MPI_Init(&argc, &argv);
::testing::InitGoogleMock(&argc, argv);
if (platform::mpi_vendor() == "Open MPI" && !Info::has_exceptions())
std::cout << "Warning: using OpenMPI without exceptions. Death tests will be skipped\n";
// handle arguments passed via environment variable
if (const char *var = getenv("TEST_ARGS")) {
std::vector<std::string> env = split_words(var);

View File

@ -323,9 +323,6 @@ int main(int argc, char **argv)
MPI_Init(&argc, &argv);
::testing::InitGoogleMock(&argc, argv);
if (platform::mpi_vendor() == "Open MPI" && !Info::has_exceptions())
std::cout << "Warning: using OpenMPI without exceptions. Death tests will be skipped\n";
// handle arguments passed via environment variable
if (const char *var = getenv("TEST_ARGS")) {
std::vector<std::string> env = split_words(var);

View File

@ -166,9 +166,6 @@ int main(int argc, char **argv)
MPI_Init(&argc, &argv);
::testing::InitGoogleMock(&argc, argv);
if (platform::mpi_vendor() == "Open MPI" && !Info::has_exceptions())
std::cout << "Warning: using OpenMPI without exceptions. Death tests will be skipped\n";
// handle arguments passed via environment variable
if (const char *var = getenv("TEST_ARGS")) {
std::vector<std::string> env = split_words(var);

View File

@ -123,9 +123,6 @@ TEST_F(LAMMPS_properties, extract_setting)
TEST_F(LAMMPS_properties, has_error)
{
// need errors to throw exceptions to be able to intercept them.
if (!lammps_config_has_exceptions()) GTEST_SKIP();
EXPECT_EQ(f_lammps_has_error(), lammps_has_error(lmp));
EXPECT_EQ(f_lammps_has_error(), 0);

View File

@ -86,13 +86,10 @@ if(Python_EXECUTABLE)
WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
set_tests_properties(PythonOpen PROPERTIES ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT}")
# some of the tests in this file will fail without exceptions enabled
if(LAMMPS_EXCEPTIONS)
add_test(NAME PythonCommands
COMMAND ${PYTHON_TEST_RUNNER} ${CMAKE_CURRENT_SOURCE_DIR}/python-commands.py -v
WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
set_tests_properties(PythonCommands PROPERTIES ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT}")
endif()
add_test(NAME PythonCommands
COMMAND ${PYTHON_TEST_RUNNER} ${CMAKE_CURRENT_SOURCE_DIR}/python-commands.py -v
WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
set_tests_properties(PythonCommands PROPERTIES ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT}")
add_test(NAME PythonNumpy
COMMAND ${PYTHON_TEST_RUNNER} ${CMAKE_CURRENT_SOURCE_DIR}/python-numpy.py -v

View File

@ -4,7 +4,7 @@ from lammps import lammps
has_mpi=False
has_mpi4py=False
has_exceptions=False
try:
from mpi4py import __version__ as mpi4py_version
# tested to work with mpi4py versions 2 and 3
@ -19,7 +19,6 @@ try:
machine = ""
lmp = lammps(name=machine)
has_mpi = lmp.has_mpi_support
has_exceptions = lmp.has_exceptions
lmp.close()
except:
pass
@ -79,7 +78,6 @@ class PythonOpen(unittest.TestCase):
self.assertEqual(lmp.opened,1)
lmp.close()
@unittest.skipIf(not has_exceptions,"Skipping death test since LAMMPS isn't compiled with exception support")
def testUnknownCommand(self):
lmp = lammps(name=self.machine)
@ -88,7 +86,6 @@ class PythonOpen(unittest.TestCase):
lmp.close()
@unittest.skipIf(not has_exceptions,"Skipping death test since LAMMPS isn't compiled with exception support")
def testUnknownCommandInList(self):
lmp = lammps(name=self.machine)
@ -97,7 +94,6 @@ class PythonOpen(unittest.TestCase):
lmp.close()
@unittest.skipIf(not has_exceptions,"Skipping death test since LAMMPS isn't compiled with exception support")
def testUnknownCommandInString(self):
lmp = lammps(name=self.machine)

View File

@ -32,21 +32,12 @@ using LAMMPS_NS::LAMMPSException;
using ::testing::ContainsRegex;
#define TEST_FAILURE(errmsg, ...) \
if (Info::has_exceptions()) { \
::testing::internal::CaptureStdout(); \
ASSERT_ANY_THROW({__VA_ARGS__}); \
auto mesg = ::testing::internal::GetCapturedStdout(); \
ASSERT_THAT(mesg, ContainsRegex(errmsg)); \
} else { \
if (LAMMPS_NS::platform::mpi_vendor() != "Open MPI") { \
::testing::internal::CaptureStdout(); \
ASSERT_DEATH({__VA_ARGS__}, ""); \
auto mesg = ::testing::internal::GetCapturedStdout(); \
ASSERT_THAT(mesg, ContainsRegex(errmsg)); \
} else { \
std::cerr << "[ ] [ INFO ] Skipping death test (no exception support) \n"; \
} \
#define TEST_FAILURE(errmsg, ...) \
{ \
::testing::internal::CaptureStdout(); \
ASSERT_ANY_THROW({__VA_ARGS__}); \
auto mesg = ::testing::internal::GetCapturedStdout(); \
ASSERT_THAT(mesg, ContainsRegex(errmsg)); \
}
// whether to print verbose output (i.e. not capturing LAMMPS screen output).

View File

@ -73,16 +73,14 @@ TEST_F(LeptonUtilsTest, substitute)
lmp->update->reset_timestep(100LL, false);
ASSERT_THAT(LeptonUtils::substitute("(2.5/v_pre)", lmp), StrEq("(2.5/0.1)"));
if (LAMMPS_NS::Info::has_exceptions()) {
bool caught = false;
try {
LeptonUtils::substitute("v_none", lmp);
} catch (std::exception &e) {
ASSERT_THAT(e.what(), StrEq("Variable none in expression v_none does not exist"));
caught = true;
}
ASSERT_TRUE(caught);
bool caught = false;
try {
LeptonUtils::substitute("v_none", lmp);
} catch (std::exception &e) {
ASSERT_THAT(e.what(), StrEq("Variable none in expression v_none does not exist"));
caught = true;
}
ASSERT_TRUE(caught);
}
// zbl() custom function