355 lines
11 KiB
C++
355 lines
11 KiB
C++
// clang-format off
|
|
/* ----------------------------------------------------------------------
|
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
|
https://www.lammps.org/, Sandia National Laboratories
|
|
Steve Plimpton, sjplimp@sandia.gov
|
|
|
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
|
certain rights in this software. This software is distributed under
|
|
the GNU General Public License.
|
|
|
|
See the README file in the top-level LAMMPS directory.
|
|
------------------------------------------------------------------------- */
|
|
|
|
#include "error.h"
|
|
|
|
#include "accelerator_kokkos.h"
|
|
#include "input.h"
|
|
#include "output.h"
|
|
#include "universe.h"
|
|
|
|
#if defined(LAMMPS_EXCEPTIONS)
|
|
#include "update.h"
|
|
#endif
|
|
|
|
using namespace LAMMPS_NS;
|
|
|
|
// helper function to truncate a string to a segment starting with "src/";
|
|
|
|
static std::string truncpath(const std::string &path)
|
|
{
|
|
std::size_t found = path.find("src/");
|
|
if (found != std::string::npos)
|
|
return path.substr(found);
|
|
else return 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
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
called by all procs in universe
|
|
close all output, screen, and log files in world and universe
|
|
no abort, so insure all procs in universe call, else will hang
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Error::universe_all(const std::string &file, int line, const std::string &str)
|
|
{
|
|
MPI_Barrier(universe->uworld);
|
|
std::string mesg = "ERROR: " + str;
|
|
try {
|
|
mesg += fmt::format(" ({}:{})\n",truncpath(file),line);
|
|
} catch (fmt::format_error &e) {
|
|
}
|
|
if (universe->me == 0) {
|
|
if (universe->uscreen) fputs(mesg.c_str(),universe->uscreen);
|
|
if (universe->ulogfile) fputs(mesg.c_str(),universe->ulogfile);
|
|
}
|
|
|
|
if (output) delete output;
|
|
if (universe->nworlds > 1) {
|
|
if (screen && screen != stdout) fclose(screen);
|
|
if (logfile) fclose(logfile);
|
|
}
|
|
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
|
|
if (lmp->kokkos) Kokkos::finalize();
|
|
MPI_Finalize();
|
|
exit(1);
|
|
#endif
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
called by one proc in universe
|
|
forces abort of entire universe if any proc in universe calls
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Error::universe_one(const std::string &file, int line, const std::string &str)
|
|
{
|
|
std::string mesg = fmt::format("ERROR on proc {}: {} ({}:{})\n",
|
|
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
|
|
MPI_Abort(universe->uworld,1);
|
|
exit(1); // to trick "smart" compilers into believing this does not return
|
|
#endif
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
called by one proc in universe
|
|
prints a warning message to the screen
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Error::universe_warn(const std::string &file, int line, const std::string &str)
|
|
{
|
|
++numwarn;
|
|
if ((numwarn > maxwarn) || (allwarn > maxwarn) || (maxwarn < 0)) return;
|
|
if (universe->uscreen)
|
|
fmt::print(universe->uscreen,"WARNING on proc {}: {} ({}:{})\n",
|
|
universe->me,str,truncpath(file),line);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
called by all procs in one world
|
|
close all output, screen, and log files in world
|
|
insure all procs in world call, else will hang
|
|
force MPI_Abort if running in multi-partition mode
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Error::all(const std::string &file, int line, const std::string &str)
|
|
{
|
|
MPI_Barrier(world);
|
|
|
|
int me;
|
|
std::string lastcmd = "(unknown)";
|
|
|
|
MPI_Comm_rank(world,&me);
|
|
|
|
if (me == 0) {
|
|
std::string mesg = "ERROR: " + str;
|
|
if (input && input->line) lastcmd = input->line;
|
|
try {
|
|
mesg += fmt::format(" ({}:{})\nLast command: {}\n",
|
|
truncpath(file),line,lastcmd);
|
|
} catch (fmt::format_error &e) {
|
|
}
|
|
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);
|
|
|
|
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);
|
|
|
|
if (universe->nworlds > 1) MPI_Abort(universe->uworld,1);
|
|
if (lmp->kokkos) Kokkos::finalize();
|
|
MPI_Finalize();
|
|
exit(1);
|
|
#endif
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
called by one proc in world
|
|
write to world screen only if non-nullptr on this proc
|
|
always write to universe screen
|
|
forces abort of entire world (and universe) if any proc in world calls
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Error::one(const std::string &file, int line, const std::string &str)
|
|
{
|
|
int me;
|
|
std::string lastcmd = "(unknown)";
|
|
MPI_Comm_rank(world,&me);
|
|
|
|
if (input && input->line) lastcmd = input->line;
|
|
std::string mesg = fmt::format("ERROR on proc {}: {} ({}:{})\n",
|
|
me,str,truncpath(file),line,lastcmd);
|
|
utils::logmesg(lmp,mesg);
|
|
|
|
if (universe->nworlds > 1)
|
|
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
|
|
if (screen) fflush(screen);
|
|
if (logfile) fflush(logfile);
|
|
MPI_Abort(world,1);
|
|
exit(1); // to trick "smart" compilers into believing this does not return
|
|
#endif
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
forward vararg version to single string version
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Error::_all(const std::string &file, int line, fmt::string_view format,
|
|
fmt::format_args args)
|
|
{
|
|
try {
|
|
all(file,line,fmt::vformat(format, args));
|
|
} catch (fmt::format_error &e) {
|
|
all(file,line,e.what());
|
|
}
|
|
exit(1); // to trick "smart" compilers into believing this does not return
|
|
}
|
|
|
|
void Error::_one(const std::string &file, int line, fmt::string_view format,
|
|
fmt::format_args args)
|
|
{
|
|
try {
|
|
one(file,line,fmt::vformat(format, args));
|
|
} catch (fmt::format_error &e) {
|
|
one(file,line,e.what());
|
|
}
|
|
exit(1); // to trick "smart" compilers into believing this does not return
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
called by one proc in world
|
|
only write to screen if non-nullptr on this proc since could be file
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Error::warning(const std::string &file, int line, const std::string &str)
|
|
{
|
|
++numwarn;
|
|
if ((numwarn > maxwarn) || (allwarn > maxwarn) || (maxwarn < 0)) return;
|
|
std::string mesg = fmt::format("WARNING: {} ({}:{})\n",
|
|
str,truncpath(file),line);
|
|
if (screen) fputs(mesg.c_str(),screen);
|
|
if (logfile) fputs(mesg.c_str(),logfile);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
forward vararg version to single string version
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Error::_warning(const std::string &file, int line, fmt::string_view format,
|
|
fmt::format_args args)
|
|
{
|
|
try {
|
|
warning(file,line,fmt::vformat(format, args));
|
|
} catch (fmt::format_error &e) {
|
|
warning(file,line,e.what());
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
called by one proc in world, typically proc 0
|
|
write message to screen and logfile (if logflag is set)
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Error::message(const std::string &file, int line, const std::string &str)
|
|
{
|
|
std::string mesg = fmt::format("{} ({}:{})\n",str,truncpath(file),line);
|
|
|
|
if (screen) fputs(mesg.c_str(),screen);
|
|
if (logfile) fputs(mesg.c_str(),logfile);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
forward vararg version to single string version
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Error::_message(const std::string &file, int line, fmt::string_view format,
|
|
fmt::format_args args)
|
|
{
|
|
try {
|
|
message(file,line,fmt::vformat(format, args));
|
|
} catch (fmt::format_error &e) {
|
|
message(file,line,e.what());
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
shutdown LAMMPS
|
|
called by all procs in one world
|
|
close all output, screen, and log files in world
|
|
no abort, so insure all procs in world call, else will hang
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Error::done(int status)
|
|
{
|
|
MPI_Barrier(world);
|
|
|
|
if (output) delete output;
|
|
if (screen && screen != stdout) fclose(screen);
|
|
if (logfile) fclose(logfile);
|
|
|
|
if (lmp->kokkos) Kokkos::finalize();
|
|
MPI_Finalize();
|
|
exit(status);
|
|
}
|
|
|
|
#ifdef LAMMPS_EXCEPTIONS
|
|
/* ----------------------------------------------------------------------
|
|
return the last error message reported by LAMMPS (only used if
|
|
compiled with -DLAMMPS_EXCEPTIONS)
|
|
------------------------------------------------------------------------- */
|
|
|
|
std::string Error::get_last_error() const
|
|
{
|
|
return last_error_message;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
return the type of the last error reported by LAMMPS (only used if
|
|
compiled with -DLAMMPS_EXCEPTIONS)
|
|
------------------------------------------------------------------------- */
|
|
|
|
ErrorType Error::get_last_error_type() const
|
|
{
|
|
return last_error_type;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
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)
|
|
{
|
|
last_error_message = msg;
|
|
last_error_type = type;
|
|
}
|
|
#endif
|