Files
lammps/src/error.cpp

327 lines
11 KiB
C++

// clang-format off
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
LAMMPS development team: developers@lammps.org
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"
#include "update.h"
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), showerror(1)
{
last_error_message.clear();
last_error_type = ERROR_NONE;
}
/* ----------------------------------------------------------------------
called by all procs in universe
close all output, screen, and log files in world and universe
no abort, so ensure 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 &) {
; // do nothing
}
if (showerror && (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);
// 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);
}
/* ----------------------------------------------------------------------
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 (showerror) {
if (universe->uscreen) fputs(mesg.c_str(),universe->uscreen);
if (universe->ulogfile) fputs(mesg.c_str(),universe->ulogfile);
}
utils::flush_buffers(lmp);
// 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);
}
/* ----------------------------------------------------------------------
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 ((maxwarn != 0) && ((numwarn > maxwarn) || (allwarn > maxwarn) || (maxwarn < 0))) return;
if (universe->uscreen)
utils::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
ensure 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, int failed, const std::string &str)
{
MPI_Barrier(world);
// must get rank from communicator since "comm" instance may not yet exist
int me = 0;
MPI_Comm_rank(world, &me);
std::string lastcmd = "(unknown)";
std::string mesg = "ERROR: " + str + fmt::format(" ({}:{})\n", truncpath(file), line);
// add text about the input following the error message
if (failed > NOLASTLINE) mesg += utils::point_to_error(input, failed);
if (failed == ARGZERO) mesg += utils::point_to_error(input, 0);
if (showerror && (me == 0)) utils::logmesg(lmp,mesg);
utils::flush_buffers(lmp);
// 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;
if (universe->nworlds > 1)
throw LAMMPSAbortException(mesg, universe->uworld);
else
throw LAMMPSException(mesg);
}
/* ----------------------------------------------------------------------
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, int failed, const std::string &str)
{
std::string lastcmd = "(unknown)";
// must get rank from communicator since "comm" instance may not yet exist
int me = 0;
MPI_Comm_rank(world, &me);
std::string mesg = fmt::format("ERROR on proc {}: {} ({}:{})\n", me, str, truncpath(file), line);
if (failed > NOPOINTER) mesg += utils::point_to_error(input, failed);
if (failed == ARGZERO) mesg += utils::point_to_error(input, 0);
if (showerror) utils::logmesg(lmp,mesg);
if (showerror && (universe->nworlds > 1)) {
if (universe->uscreen) fputs(mesg.c_str(),universe->uscreen);
if (universe->ulogfile) fputs(mesg.c_str(),universe->ulogfile);
}
utils::flush_buffers(lmp);
// 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);
}
/* ----------------------------------------------------------------------
forward vararg versions to single string version
------------------------------------------------------------------------- */
void Error::_all(const std::string &file, int line, int failed, fmt::string_view format,
fmt::format_args args)
{
try {
all(file, line, failed, fmt::vformat(format, args));
} catch (fmt::format_error &e) {
all(file, line, NOPOINTER, e.what());
}
exit(1); // to trick "smart" compilers into believing this does not return
}
void Error::_one(const std::string &file, int line, int failed, fmt::string_view format,
fmt::format_args args)
{
try {
one(file, line, failed, fmt::vformat(format, args));
} catch (fmt::format_error &e) {
one(file, line, NOPOINTER, 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 ((maxwarn != 0) && ((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 ensure all procs in world call, else will hang
------------------------------------------------------------------------- */
void Error::done(int status)
{
utils::flush_buffers(lmp);
MPI_Barrier(world);
if (output) delete output;
if (screen && screen != stdout) fclose(screen);
if (logfile) fclose(logfile);
KokkosLMP::finalize();
MPI_Finalize();
exit(status);
}
/* ----------------------------------------------------------------------
return the last error message reported by LAMMPS
------------------------------------------------------------------------- */
std::string Error::get_last_error() const
{
return last_error_message;
}
/* ----------------------------------------------------------------------
return the type of the last error reported by LAMMPS
------------------------------------------------------------------------- */
ErrorType Error::get_last_error_type() const
{
return last_error_type;
}
/* ----------------------------------------------------------------------
set the last error message and error type
------------------------------------------------------------------------- */
void Error::set_last_error(const char *msg, ErrorType type)
{
last_error_message = msg;
last_error_type = type;
}
/* ----------------------------------------------------------------------
enable or disable printing error messages. for use with library interface.
if flag = 0 only last error message and type are updated.
returns the previous setting.
------------------------------------------------------------------------- */
int Error::set_show_error(const int flag)
{
int oldflag = showerror;
showerror = flag;
return oldflag;
}