1522 lines
46 KiB
C++
1522 lines
46 KiB
C++
/* ----------------------------------------------------------------------
|
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
|
https://lammps.sandia.gov/, 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.
|
|
------------------------------------------------------------------------- */
|
|
|
|
/* ----------------------------------------------------------------------
|
|
Contributing authors: Axel Kohlmeyer (Temple U),
|
|
Richard Berger (Temple U)
|
|
------------------------------------------------------------------------- */
|
|
|
|
#include "info.h"
|
|
|
|
#include "accelerator_kokkos.h"
|
|
#include "angle.h"
|
|
#include "atom.h"
|
|
#include "bond.h"
|
|
#include "comm.h"
|
|
#include "compute.h"
|
|
#include "dihedral.h"
|
|
#include "domain.h"
|
|
#include "dump.h"
|
|
#include "error.h"
|
|
#include "fix.h"
|
|
#include "force.h"
|
|
#include "group.h"
|
|
#include "improper.h"
|
|
#include "input.h"
|
|
#include "modify.h"
|
|
#include "neighbor.h"
|
|
#include "output.h"
|
|
#include "pair.h"
|
|
#include "pair_hybrid.h"
|
|
#include "region.h"
|
|
#include "text_file_reader.h"
|
|
#include "update.h"
|
|
#include "variable.h"
|
|
#include "fmt/chrono.h"
|
|
|
|
#include <cctype>
|
|
#include <cmath>
|
|
#include <cstring>
|
|
#include <map>
|
|
|
|
#ifdef _WIN32
|
|
#define PSAPI_VERSION 1
|
|
#include <windows.h>
|
|
#include <cstdint>
|
|
#include <psapi.h>
|
|
#else
|
|
#include <sys/resource.h>
|
|
#include <sys/utsname.h>
|
|
#endif
|
|
|
|
#if defined(__linux__)
|
|
#include <malloc.h>
|
|
#endif
|
|
|
|
namespace LAMMPS_NS {
|
|
|
|
enum {COMPUTES=1<<0,
|
|
DUMPS=1<<1,
|
|
FIXES=1<<2,
|
|
GROUPS=1<<3,
|
|
REGIONS=1<<4,
|
|
CONFIG=1<<5,
|
|
TIME=1<<6,
|
|
MEMORY=1<<7,
|
|
VARIABLES=1<<8,
|
|
SYSTEM=1<<9,
|
|
COMM=1<<10,
|
|
COEFFS=1<<11,
|
|
ATOM_STYLES=1<<12,
|
|
INTEGRATE_STYLES=1<<13,
|
|
MINIMIZE_STYLES=1<<14,
|
|
PAIR_STYLES=1<<15,
|
|
BOND_STYLES=1<<16,
|
|
ANGLE_STYLES=1<<17,
|
|
DIHEDRAL_STYLES=1<<18,
|
|
IMPROPER_STYLES=1<<19,
|
|
KSPACE_STYLES=1<<20,
|
|
FIX_STYLES=1<<21,
|
|
COMPUTE_STYLES=1<<22,
|
|
REGION_STYLES=1<<23,
|
|
DUMP_STYLES=1<<24,
|
|
COMMAND_STYLES=1<<25,
|
|
ACCELERATOR=1<<26,
|
|
ALL=~0};
|
|
|
|
static const int STYLES = ATOM_STYLES | INTEGRATE_STYLES | MINIMIZE_STYLES
|
|
| PAIR_STYLES | BOND_STYLES | ANGLE_STYLES
|
|
| DIHEDRAL_STYLES | IMPROPER_STYLES | KSPACE_STYLES
|
|
| FIX_STYLES | COMPUTE_STYLES | REGION_STYLES
|
|
| DUMP_STYLES | COMMAND_STYLES;
|
|
}
|
|
|
|
using namespace LAMMPS_NS;
|
|
|
|
// must match enumerator in variable.h
|
|
static const char *varstyles[] = {
|
|
"index", "loop", "world", "universe", "uloop", "string", "getenv",
|
|
"file", "atomfile", "format", "equal", "atom", "vector", "python",
|
|
"internal", "(unknown)"};
|
|
|
|
static const char *mapstyles[] = { "none", "array", "hash", "yes" };
|
|
|
|
static const char *commstyles[] = { "brick", "tiled" };
|
|
static const char *commlayout[] = { "uniform", "nonuniform", "irregular" };
|
|
|
|
static const char bstyles[] = "pfsm";
|
|
|
|
template<typename ValueType>
|
|
static void print_columns(FILE *fp, std::map<std::string, ValueType> *styles);
|
|
|
|
template<typename ValueType>
|
|
static bool find_style(const LAMMPS *lmp, std::map<std::string, ValueType> *styles,
|
|
const std::string &name, bool suffix_check);
|
|
|
|
template<typename ValueType>
|
|
static std::vector<std::string> get_style_names(std::map<std::string, ValueType> *styles);
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
void Info::command(int narg, char **arg)
|
|
{
|
|
FILE *out=screen;
|
|
int flags=0;
|
|
|
|
if (comm->me != 0) return;
|
|
|
|
// parse arguments
|
|
int idx = 0;
|
|
|
|
while (idx < narg) {
|
|
if (strncmp(arg[idx],"all",3) == 0) {
|
|
flags |= ALL;
|
|
++idx;
|
|
} else if ((idx+1 < narg) && (strncmp(arg[idx],"out",3) == 0)
|
|
&& (strncmp(arg[idx+1],"screen",3) == 0)) {
|
|
if ((out != screen) && (out != logfile)) fclose(out);
|
|
out = screen;
|
|
idx += 2;
|
|
} else if ((idx+1 < narg) && (strncmp(arg[idx],"out",3) == 0)
|
|
&& (strncmp(arg[idx+1],"log",3) == 0)) {
|
|
if ((out != screen) && (out != logfile)) fclose(out);
|
|
out = logfile;
|
|
idx += 2;
|
|
} else if ((idx+2 < narg) && (strncmp(arg[idx],"out",3) == 0)
|
|
&& (strncmp(arg[idx+1],"append",3) == 0)) {
|
|
if ((out != screen) && (out != logfile)) fclose(out);
|
|
out = fopen(arg[idx+2],"a");
|
|
idx += 3;
|
|
} else if ((idx+2 < narg) && (strncmp(arg[idx],"out",3) == 0)
|
|
&& (strncmp(arg[idx+1],"overwrite",3) == 0)) {
|
|
if ((out != screen) && (out != logfile)) fclose(out);
|
|
out = fopen(arg[idx+2],"w");
|
|
idx += 3;
|
|
} else if (strncmp(arg[idx],"communication",5) == 0) {
|
|
flags |= COMM;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"computes",5) == 0) {
|
|
flags |= COMPUTES;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"dumps",5) == 0) {
|
|
flags |= DUMPS;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"fixes",5) == 0) {
|
|
flags |= FIXES;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"groups",3) == 0) {
|
|
flags |= GROUPS;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"regions",3) == 0) {
|
|
flags |= REGIONS;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"config",3) == 0) {
|
|
flags |= CONFIG;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"time",3) == 0) {
|
|
flags |= TIME;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"memory",3) == 0) {
|
|
flags |= MEMORY;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"variables",3) == 0) {
|
|
flags |= VARIABLES;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"system",3) == 0) {
|
|
flags |= SYSTEM;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"coeffs",3) == 0) {
|
|
flags |= COEFFS;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"accelerator",3) == 0) {
|
|
flags |= ACCELERATOR;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"styles",3) == 0) {
|
|
if (idx+1 < narg) {
|
|
++idx;
|
|
if (strncmp(arg[idx],"all",3) == 0) {
|
|
flags |= STYLES;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"atom",3) == 0) {
|
|
flags |= ATOM_STYLES;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"integrate",3) == 0) {
|
|
flags |= INTEGRATE_STYLES;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"minimize",3) == 0) {
|
|
flags |= MINIMIZE_STYLES;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"pair",3) == 0) {
|
|
flags |= PAIR_STYLES;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"bond",3) == 0) {
|
|
flags |= BOND_STYLES;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"angle",3) == 0) {
|
|
flags |= ANGLE_STYLES;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"dihedral",3) == 0) {
|
|
flags |= DIHEDRAL_STYLES;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"improper",3) == 0) {
|
|
flags |= IMPROPER_STYLES;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"kspace",3) == 0) {
|
|
flags |= KSPACE_STYLES;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"fix",3) == 0) {
|
|
flags |= FIX_STYLES;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"compute",4) == 0) {
|
|
flags |= COMPUTE_STYLES;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"region",3) == 0) {
|
|
flags |= REGION_STYLES;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"dump",3) == 0) {
|
|
flags |= DUMP_STYLES;
|
|
++idx;
|
|
} else if (strncmp(arg[idx],"command",4) == 0) {
|
|
flags |= COMMAND_STYLES;
|
|
++idx;
|
|
} else {
|
|
flags |= STYLES;
|
|
}
|
|
} else {
|
|
flags |= STYLES;
|
|
++idx;
|
|
}
|
|
} else {
|
|
error->warning(FLERR,"Ignoring unknown or incorrect info command flag");
|
|
++idx;
|
|
}
|
|
}
|
|
|
|
if (out == nullptr) return;
|
|
|
|
fputs("\nInfo-Info-Info-Info-Info-Info-Info-Info-Info-Info-Info\n",out);
|
|
std::time_t now = std::time(nullptr);
|
|
fmt::print(out,"Printed on {:%a %b %d %H:%M:%S %Y}\n", fmt::localtime(now));
|
|
|
|
if (flags & CONFIG) {
|
|
fmt::print(out,"\nLAMMPS version: {} / {}\n",
|
|
lmp->version, lmp->num_ver);
|
|
|
|
if (lmp->has_git_info)
|
|
fmt::print(out,"Git info: {} / {} / {}\n",
|
|
lmp->git_branch, lmp->git_descriptor,lmp->git_commit);
|
|
|
|
fmt::print(out,"\nOS information: {}\n\n",get_os_info());
|
|
|
|
fmt::print(out,"sizeof(smallint): {}-bit\n"
|
|
"sizeof(imageint): {}-bit\n"
|
|
"sizeof(tagint): {}-bit\n"
|
|
"sizeof(bigint): {}-bit\n",
|
|
sizeof(smallint)*8, sizeof(imageint)*8,
|
|
sizeof(tagint)*8, sizeof(bigint)*8);
|
|
|
|
fmt::print(out,"\nCompiler: {} with {}\nC++ standard: {}\n",
|
|
get_compiler_info(),get_openmp_info(),get_cxx_info());
|
|
|
|
fputs("\nActive compile time flags:\n\n",out);
|
|
if (has_gzip_support()) fputs("-DLAMMPS_GZIP\n",out);
|
|
if (has_png_support()) fputs("-DLAMMPS_PNG\n",out);
|
|
if (has_jpeg_support()) fputs("-DLAMMPS_JPEG\n",out);
|
|
if (has_ffmpeg_support()) fputs("-DLAMMPS_FFMPEG\n",out);
|
|
if (has_exceptions()) fputs("-DLAMMPS_EXCEPTIONS\n",out);
|
|
|
|
#if defined(LAMMPS_BIGBIG)
|
|
fputs("-DLAMMPS_BIGBIG\n",out);
|
|
#elif defined(LAMMPS_SMALLBIG)
|
|
fputs("-DLAMMPS_SMALLBIG\n",out);
|
|
#else // defined(LAMMPS_SMALLSMALL)
|
|
fputs("-DLAMMPS_SMALLSMALL\n",out);
|
|
#endif
|
|
|
|
int ncword, ncline = 0;
|
|
fputs("\nInstalled packages:\n\n",out);
|
|
for (const char **pkg = lmp->installed_packages; *pkg != nullptr; ++pkg) {
|
|
ncword = strlen(*pkg);
|
|
if (ncline + ncword > 78) {
|
|
ncline = 0;
|
|
fputs("\n",out);
|
|
}
|
|
fmt::print(out,"{} ",*pkg);
|
|
ncline += ncword + 1;
|
|
}
|
|
fputs("\n",out);
|
|
}
|
|
|
|
if (flags & ACCELERATOR) {
|
|
fmt::print(out,"\nAccelerator configuration:\n\n{}",
|
|
get_accelerator_info());
|
|
if (Info::has_gpu_device())
|
|
fmt::print(out,"\nAvailable GPU devices:\n{}\n",get_gpu_device_info());
|
|
}
|
|
|
|
if (flags & MEMORY) {
|
|
double meminfo[3];
|
|
|
|
get_memory_info(meminfo);
|
|
|
|
fputs("\nMemory allocation information (MPI rank 0):\n\n",out);
|
|
fmt::print(out,"Total dynamically allocated memory: {:.4} Mbyte\n",
|
|
meminfo[0]);
|
|
|
|
#if defined(_WIN32)
|
|
fmt::print(out,"Non-shared memory use: {:.4} Mbyte\n",meminfo[1]);
|
|
fmt::print(out,"Maximum working set size: {:.4} Mbyte\n",meminfo[2]);
|
|
#else
|
|
#if defined(__linux__)
|
|
fmt::print(out,"Current reserved memory pool size: {:.4} Mbyte\n",
|
|
meminfo[1]);
|
|
#endif
|
|
fmt::print(out,"Maximum resident set size: {:.4} Mbyte\n",meminfo[2]);
|
|
#endif
|
|
}
|
|
|
|
if (flags & COMM) {
|
|
int major,minor;
|
|
std::string version = get_mpi_info(major,minor);
|
|
|
|
fmt::print(out,"\nCommunication information:\n"
|
|
"MPI library level: MPI v{}.{}\n"
|
|
"MPI version: {}\n",major,minor,version);
|
|
|
|
fmt::print(out,"Comm style = {}, Comm layout = {}\n"
|
|
"Communicate velocities for ghost atoms = {}\n",
|
|
commstyles[comm->style], commlayout[comm->layout],
|
|
comm->ghost_velocity ? "yes" : "no");
|
|
|
|
if (domain->box_exist) {
|
|
if (comm->mode == 0)
|
|
fmt::print(out,"Communication mode = single\n"
|
|
"Communication cutoff = {}\n",
|
|
comm->get_comm_cutoff());
|
|
|
|
if (comm->mode == 1) {
|
|
fputs("Communication mode = multi\n",out);
|
|
double cut;
|
|
for (int i=1; i <= atom->ntypes && neighbor->cuttype; ++i) {
|
|
cut = neighbor->cuttype[i];
|
|
if (comm->cutusermulti) cut = MAX(cut,comm->cutusermulti[i]);
|
|
fmt::print(out,"Communication cutoff for type {} = {:.8}\n", i, cut);
|
|
}
|
|
}
|
|
}
|
|
fmt::print(out,"Nprocs = {}, Nthreads = {}\n",comm->nprocs,comm->nthreads);
|
|
if (domain->box_exist)
|
|
fmt::print(out,"Processor grid = {} x {} x {}\n",comm->procgrid[0],
|
|
comm->procgrid[1], comm->procgrid[2]);
|
|
}
|
|
|
|
if (flags & SYSTEM) {
|
|
fputs("\nSystem information:\n",out);
|
|
fmt::print(out,"Units = {}\n", update->unit_style);
|
|
fmt::print(out,"Atom style = {}\n", atom->atom_style);
|
|
fmt::print(out,"Atom map = {}\n", mapstyles[atom->map_style]);
|
|
if (atom->molecular != Atom::ATOMIC) {
|
|
const char *msg;
|
|
msg = (atom->molecular == Atom::TEMPLATE) ? "template" : "standard";
|
|
fmt::print(out,"Molecule type = {}\n",msg);
|
|
}
|
|
fmt::print(out,"Atoms = {:12}, types = {:8d}, style = {}\n",
|
|
atom->natoms, atom->ntypes, force->pair_style);
|
|
|
|
if (force->pair && utils::strmatch(force->pair_style,"^hybrid")) {
|
|
PairHybrid *hybrid = (PairHybrid *)force->pair;
|
|
fmt::print(out,"Hybrid sub-styles:");
|
|
for (int i=0; i < hybrid->nstyles; ++i)
|
|
fmt::print(out," {}", hybrid->keywords[i]);
|
|
fputc('\n',out);
|
|
}
|
|
if (atom->molecular != Atom::ATOMIC) {
|
|
const char *msg;
|
|
msg = force->bond_style ? force->bond_style : "none";
|
|
fmt::print(out,"Bonds = {:12}, types = {:8}, style = {}\n",
|
|
atom->nbonds, atom->nbondtypes, msg);
|
|
|
|
msg = force->angle_style ? force->angle_style : "none";
|
|
fmt::print(out,"Angles = {:12}, types = {:8}, style = {}\n",
|
|
atom->nangles, atom->nangletypes, msg);
|
|
|
|
msg = force->dihedral_style ? force->dihedral_style : "none";
|
|
fmt::print(out,"Dihedrals = {:12}, types = {:8}, style = {}\n",
|
|
atom->ndihedrals, atom->ndihedraltypes, msg);
|
|
|
|
msg = force->improper_style ? force->improper_style : "none";
|
|
fmt::print(out,"Impropers = {:12}, types = {:8}, style = {}\n",
|
|
atom->nimpropers, atom->nimpropertypes, msg);
|
|
|
|
const double * const special_lj = force->special_lj;
|
|
const double * const special_coul = force->special_coul;
|
|
|
|
fmt::print(out,"Special bond factors lj = {:<8} {:<8} {:<8}\n"
|
|
"Special bond factors coul = {:<8} {:<8} {:<8}\n",
|
|
special_lj[1],special_lj[2],special_lj[3],
|
|
special_coul[1],special_coul[2],special_coul[3]);
|
|
}
|
|
|
|
fmt::print(out,"Kspace style = {}\n",
|
|
force->kspace ? force->kspace_style : "none");
|
|
|
|
if (domain->box_exist) {
|
|
fmt::print(out,"\nDimensions = {}\n",domain->dimension);
|
|
fmt::print(out,"{} box = {:.8} x {:.8} x {:.8}\n",
|
|
domain->triclinic ? "Triclinic" : "Orthogonal",
|
|
domain->xprd, domain->yprd, domain->zprd);
|
|
fmt::print(out,"Boundaries = {},{} {},{} {},{}\n",
|
|
bstyles[domain->boundary[0][0]],bstyles[domain->boundary[0][1]],
|
|
bstyles[domain->boundary[1][0]],bstyles[domain->boundary[1][1]],
|
|
bstyles[domain->boundary[2][0]],bstyles[domain->boundary[2][1]]);
|
|
fmt::print(out,"xlo, xhi = {:.8}, {:.8}\n", domain->boxlo[0], domain->boxhi[0]);
|
|
fmt::print(out,"ylo, yhi = {:.8}, {:.8}\n", domain->boxlo[1], domain->boxhi[1]);
|
|
fmt::print(out,"zlo, zhi = {:.8}, {:.8}\n", domain->boxlo[2], domain->boxhi[2]);
|
|
if (domain->triclinic)
|
|
fmt::print(out,"Xy, xz, yz = {:.8}, {:.8}, {:.8}\n",
|
|
domain->xy, domain->xz, domain->yz);
|
|
} else {
|
|
fputs("\nBox has not yet been created\n",out);
|
|
}
|
|
}
|
|
|
|
if (domain->box_exist && (flags & COEFFS)) {
|
|
Pair *pair=force->pair;
|
|
|
|
fputs("\nCoeff status information:\n",out);
|
|
if (pair) {
|
|
fputs("\nPair Coeffs:\n",out);
|
|
for (int i=1; i <= atom->ntypes; ++i)
|
|
for (int j=i; j <= atom->ntypes; ++j) {
|
|
fmt::print(out,"{:6d} {:6d}:",i,j);
|
|
if (pair->allocated && pair->setflag[i][j]) fputs(" is set\n",out);
|
|
else fputs(" is not set\n",out);
|
|
}
|
|
}
|
|
if (force->bond) {
|
|
Bond *bond=force->bond;
|
|
|
|
if (bond) {
|
|
fputs("\nBond Coeffs:\n",out);
|
|
for (int i=1; i <= atom->nbondtypes; ++i) {
|
|
fmt::print(out,"{:6d}:",i);
|
|
if (bond->allocated && bond->setflag[i]) fputs(" is set\n",out);
|
|
else fputs (" is not set\n",out);
|
|
}
|
|
}
|
|
}
|
|
if (force->angle) {
|
|
Angle *angle=force->angle;
|
|
|
|
if (angle) {
|
|
fputs("\nAngle Coeffs:\n",out);
|
|
for (int i=1; i <= atom->nangletypes; ++i) {
|
|
fmt::print(out,"{:6d}:",i);
|
|
if (angle->allocated && angle->setflag[i]) fputs(" is set\n",out);
|
|
else fputs (" is not set\n",out);
|
|
}
|
|
}
|
|
}
|
|
if (force->dihedral) {
|
|
Dihedral *dihedral=force->dihedral;
|
|
|
|
if (dihedral) {
|
|
fputs("\nDihedral Coeffs:\n",out);
|
|
for (int i=1; i <= atom->ndihedraltypes; ++i) {
|
|
fmt::print(out,"{:6d}:",i);
|
|
if (dihedral->allocated && dihedral->setflag[i]) fputs(" is set\n",out);
|
|
else fputs (" is not set\n",out);
|
|
}
|
|
}
|
|
}
|
|
if (force->improper) {
|
|
Improper *b=force->improper;
|
|
|
|
if (b) {
|
|
fputs("\nImproper Coeffs:\n",out);
|
|
for (int i=1; i <= atom->nimpropertypes; ++i) {
|
|
fmt::print(out,"{:6d}:",i);
|
|
if (b->allocated && b->setflag[i]) fputs(" is set\n",out);
|
|
else fputs (" is not set\n",out);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (flags & GROUPS) {
|
|
int ngroup = group->ngroup;
|
|
char **names = group->names;
|
|
int *dynamic = group->dynamic;
|
|
fputs("\nGroup information:\n",out);
|
|
for (int i=0; i < ngroup; ++i) {
|
|
if (names[i])
|
|
fmt::print(out,"Group[{:2d}]: {:16} ({})\n",
|
|
i, names[i], dynamic[i] ? "dynamic" : "static");
|
|
}
|
|
}
|
|
|
|
if (flags & REGIONS) {
|
|
int nreg = domain->nregion;
|
|
Region **regs = domain->regions;
|
|
fputs("\nRegion information:\n",out);
|
|
for (int i=0; i < nreg; ++i) {
|
|
fmt::print(out,"Region[{:3d}]: {:16} style = {:16} side = {}\n",
|
|
i, std::string(regs[i]->id)+',',
|
|
std::string(regs[i]->style)+',',
|
|
regs[i]->interior ? "in" : "out");
|
|
if (regs[i]->bboxflag)
|
|
fmt::print(out," Boundary: lo {:.8} {:.8} {:.8} hi {:.8} {:.8} {:.8}\n",
|
|
regs[i]->extent_xlo, regs[i]->extent_ylo,
|
|
regs[i]->extent_zlo, regs[i]->extent_xhi,
|
|
regs[i]->extent_yhi, regs[i]->extent_zhi);
|
|
else fputs(" No Boundary\n",out);
|
|
}
|
|
}
|
|
|
|
if (flags & COMPUTES) {
|
|
int ncompute = modify->ncompute;
|
|
Compute **compute = modify->compute;
|
|
char **names = group->names;
|
|
fputs("\nCompute information:\n",out);
|
|
for (int i=0; i < ncompute; ++i) {
|
|
fmt::print(out,"Compute[{:3d}]: {:16} style = {:16} group = {}\n",
|
|
i, std::string(compute[i]->id)+',',
|
|
std::string(compute[i]->style)+',',
|
|
names[compute[i]->igroup]);
|
|
}
|
|
}
|
|
|
|
if (flags & DUMPS) {
|
|
int ndump = output->ndump;
|
|
Dump **dump = output->dump;
|
|
int *nevery = output->every_dump; \
|
|
char **vnames = output->var_dump;
|
|
char **names = group->names;
|
|
fputs("\nDump information:\n",out);
|
|
for (int i=0; i < ndump; ++i) {
|
|
fmt::print(out,"Dump[{:3d}]: {:16} file = {:16} style = {:16} group = {:16} ",
|
|
i, std::string(dump[i]->id)+',',
|
|
std::string(dump[i]->filename)+',',
|
|
std::string(dump[i]->style)+',',
|
|
std::string(names[dump[i]->igroup])+',');
|
|
if (nevery[i]) {
|
|
fmt::print(out,"every = {}\n", nevery[i]);
|
|
} else {
|
|
fmt::print(out,"every = {}\n", vnames[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (flags & FIXES) {
|
|
int nfix = modify->nfix;
|
|
Fix **fix = modify->fix;
|
|
char **names = group->names;
|
|
fputs("\nFix information:\n",out);
|
|
for (int i=0; i < nfix; ++i) {
|
|
fmt::print(out, "Fix[{:3d}]: {:16} style = {:16} group = {}\n",
|
|
i,std::string(fix[i]->id)+',',
|
|
std::string(fix[i]->style)+',',
|
|
names[fix[i]->igroup]);
|
|
}
|
|
}
|
|
|
|
if (flags & VARIABLES) {
|
|
int nvar = input->variable->nvar;
|
|
int *style = input->variable->style;
|
|
char **names = input->variable->names;
|
|
char ***data = input->variable->data;
|
|
fputs("\nVariable information:\n",out);
|
|
for (int i=0; i < nvar; ++i) {
|
|
int ndata = 1;
|
|
fmt::print(out,"Variable[{:3d}]: {:16} style = {:16} def =",
|
|
i,std::string(names[i])+',',
|
|
std::string(varstyles[style[i]])+',');
|
|
if (style[i] == Variable::INTERNAL) {
|
|
fmt::print(out,"{:.8}\n",input->variable->dvalue[i]);
|
|
continue;
|
|
}
|
|
if ((style[i] != Variable::LOOP) && (style[i] != Variable::ULOOP))
|
|
ndata = input->variable->num[i];
|
|
for (int j=0; j < ndata; ++j)
|
|
if (data[i][j]) fmt::print(out," {}",data[i][j]);
|
|
fputs("\n",out);
|
|
}
|
|
}
|
|
|
|
if (flags & TIME) {
|
|
double wallclock = MPI_Wtime() - lmp->initclock;
|
|
double cpuclock = 0.0;
|
|
|
|
#if defined(_WIN32)
|
|
// from MSD docs.
|
|
FILETIME ct,et,kt,ut;
|
|
union { FILETIME ft; uint64_t ui; } cpu;
|
|
if (GetProcessTimes(GetCurrentProcess(),&ct,&et,&kt,&ut)) {
|
|
cpu.ft = ut;
|
|
cpuclock = cpu.ui * 0.0000001;
|
|
}
|
|
#else /* POSIX */
|
|
struct rusage ru;
|
|
if (getrusage(RUSAGE_SELF, &ru) == 0) {
|
|
cpuclock = (double) ru.ru_utime.tv_sec;
|
|
cpuclock += (double) ru.ru_utime.tv_usec * 0.000001;
|
|
}
|
|
#endif /* ! _WIN32 */
|
|
|
|
int cpuh,cpum,cpus,wallh,wallm,walls;
|
|
cpus = fmod(cpuclock,60.0);
|
|
cpuclock = (cpuclock - cpus) / 60.0;
|
|
cpum = fmod(cpuclock,60.0);
|
|
cpuh = (cpuclock - cpum) / 60.0;
|
|
walls = fmod(wallclock,60.0);
|
|
wallclock = (wallclock - walls) / 60.0;
|
|
wallm = fmod(wallclock,60.0);
|
|
wallh = (wallclock - wallm) / 60.0;
|
|
fmt::print(out,"\nTotal time information (MPI rank 0):\n"
|
|
" CPU time: {:4d}:{:02d}:{:02d}\n"
|
|
" Wall time: {:4d}:{:02d}:{:02d}\n",
|
|
cpuh,cpum,cpus,wallh,wallm,walls);
|
|
}
|
|
|
|
if (flags & STYLES) {
|
|
available_styles(out, flags);
|
|
}
|
|
|
|
fputs("\nInfo-Info-Info-Info-Info-Info-Info-Info-Info-Info-Info\n\n",out);
|
|
|
|
// close output file pointer if opened locally thus forcing a hard sync.
|
|
if ((out != screen) && (out != logfile))
|
|
fclose(out);
|
|
}
|
|
|
|
void Info::available_styles(FILE * out, int flags)
|
|
{
|
|
|
|
fputs("\nStyles information:\n",out);
|
|
|
|
if (flags & ATOM_STYLES) atom_styles(out);
|
|
if (flags & INTEGRATE_STYLES) integrate_styles(out);
|
|
if (flags & MINIMIZE_STYLES) minimize_styles(out);
|
|
if (flags & PAIR_STYLES) pair_styles(out);
|
|
if (flags & BOND_STYLES) bond_styles(out);
|
|
if (flags & ANGLE_STYLES) angle_styles(out);
|
|
if (flags & DIHEDRAL_STYLES) dihedral_styles(out);
|
|
if (flags & IMPROPER_STYLES) improper_styles(out);
|
|
if (flags & KSPACE_STYLES) kspace_styles(out);
|
|
if (flags & FIX_STYLES) fix_styles(out);
|
|
if (flags & COMPUTE_STYLES) compute_styles(out);
|
|
if (flags & REGION_STYLES) region_styles(out);
|
|
if (flags & DUMP_STYLES) dump_styles(out);
|
|
if (flags & COMMAND_STYLES) command_styles(out);
|
|
}
|
|
|
|
void Info::atom_styles(FILE *out)
|
|
{
|
|
fputs("\nAtom styles:\n",out);
|
|
print_columns(out, atom->avec_map);
|
|
fputs("\n\n\n",out);
|
|
}
|
|
|
|
void Info::integrate_styles(FILE *out)
|
|
{
|
|
fputs("\nIntegrate styles:\n",out);
|
|
print_columns(out, update->integrate_map);
|
|
fputs("\n\n\n",out);
|
|
}
|
|
|
|
void Info::minimize_styles(FILE *out)
|
|
{
|
|
fputs("\nMinimize styles:\n",out);
|
|
print_columns(out, update->minimize_map);
|
|
fputs("\n\n\n",out);
|
|
}
|
|
|
|
void Info::pair_styles(FILE *out)
|
|
{
|
|
fputs("\nPair styles:\n",out);
|
|
print_columns(out, force->pair_map);
|
|
fputs("\n\n\n",out);
|
|
}
|
|
|
|
void Info::bond_styles(FILE *out)
|
|
{
|
|
fputs("\nBond styles:\n",out);
|
|
print_columns(out, force->bond_map);
|
|
fputs("\n\n\n",out);
|
|
}
|
|
|
|
void Info::angle_styles(FILE *out)
|
|
{
|
|
fputs("\nAngle styles:\n",out);
|
|
print_columns(out, force->angle_map);
|
|
fputs("\n\n\n",out);
|
|
}
|
|
|
|
void Info::dihedral_styles(FILE *out)
|
|
{
|
|
fputs("\nDihedral styles:\n",out);
|
|
print_columns(out, force->dihedral_map);
|
|
fputs("\n\n\n",out);
|
|
}
|
|
|
|
void Info::improper_styles(FILE *out)
|
|
{
|
|
fputs("\nImproper styles:\n",out);
|
|
print_columns(out, force->improper_map);
|
|
fputs("\n\n\n",out);
|
|
}
|
|
|
|
void Info::kspace_styles(FILE *out)
|
|
{
|
|
fputs("\nKSpace styles:\n",out);
|
|
print_columns(out, force->kspace_map);
|
|
fputs("\n\n\n",out);
|
|
}
|
|
|
|
void Info::fix_styles(FILE *out)
|
|
{
|
|
fputs("\nFix styles:\n",out);
|
|
print_columns(out, modify->fix_map);
|
|
fputs("\n\n\n",out);
|
|
}
|
|
|
|
void Info::compute_styles(FILE *out)
|
|
{
|
|
fputs("\nCompute styles:\n",out);
|
|
print_columns(out, modify->compute_map);
|
|
fputs("\n\n\n",out);
|
|
}
|
|
|
|
void Info::region_styles(FILE *out)
|
|
{
|
|
fputs("\nRegion styles:\n",out);
|
|
print_columns(out, domain->region_map);
|
|
fputs("\n\n\n",out);
|
|
}
|
|
|
|
void Info::dump_styles(FILE *out)
|
|
{
|
|
fputs("\nDump styles:\n",out);
|
|
print_columns(out,output->dump_map);
|
|
fputs("\n\n\n",out);
|
|
}
|
|
|
|
void Info::command_styles(FILE *out)
|
|
{
|
|
fputs("\nCommand styles (add-on input script commands):\n",out);
|
|
print_columns(out, input->command_map);
|
|
fputs("\n\n\n",out);
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
// the is_active() function returns true if the selected style or name
|
|
// in the selected category is currently in use.
|
|
|
|
bool Info::is_active(const char *category, const char *name)
|
|
{
|
|
if ((category == nullptr) || (name == nullptr)) return false;
|
|
const char *style = "none";
|
|
|
|
if (strcmp(category,"package") == 0) {
|
|
if (strcmp(name,"gpu") == 0) {
|
|
return (modify->find_fix("package_gpu") >= 0) ? true : false;
|
|
} else if (strcmp(name,"intel") == 0) {
|
|
return (modify->find_fix("package_intel") >= 0) ? true : false;
|
|
} else if (strcmp(name,"kokkos") == 0) {
|
|
return (lmp->kokkos && lmp->kokkos->kokkos_exists) ? true : false;
|
|
} else if (strcmp(name,"omp") == 0) {
|
|
return (modify->find_fix("package_omp") >= 0) ? true : false;
|
|
} else error->all(FLERR,"Unknown name for info package category");
|
|
|
|
} else if (strcmp(category,"newton") == 0) {
|
|
if (strcmp(name,"pair") == 0) return (force->newton_pair != 0);
|
|
else if (strcmp(name,"bond") == 0) return (force->newton_bond != 0);
|
|
else if (strcmp(name,"any") == 0) return (force->newton != 0);
|
|
else error->all(FLERR,"Unknown name for info newton category");
|
|
|
|
} else if (strcmp(category,"pair") == 0) {
|
|
if (force->pair == nullptr) return false;
|
|
if (strcmp(name,"single") == 0) return (force->pair->single_enable != 0);
|
|
else if (strcmp(name,"respa") == 0) return (force->pair->respa_enable != 0);
|
|
else if (strcmp(name,"manybody") == 0) return (force->pair->manybody_flag != 0);
|
|
else if (strcmp(name,"tail") == 0) return (force->pair->tail_flag != 0);
|
|
else if (strcmp(name,"shift") == 0) return (force->pair->offset_flag != 0);
|
|
else error->all(FLERR,"Unknown name for info pair category");
|
|
|
|
} else if (strcmp(category,"comm_style") == 0) {
|
|
style = commstyles[comm->style];
|
|
} else if (strcmp(category,"min_style") == 0) {
|
|
style = update->minimize_style;
|
|
} else if (strcmp(category,"run_style") == 0) {
|
|
style = update->integrate_style;
|
|
} else if (strcmp(category,"atom_style") == 0) {
|
|
style = atom->atom_style;
|
|
} else if (strcmp(category,"pair_style") == 0) {
|
|
style = force->pair_style;
|
|
} else if (strcmp(category,"bond_style") == 0) {
|
|
style = force->bond_style;
|
|
} else if (strcmp(category,"angle_style") == 0) {
|
|
style = force->angle_style;
|
|
} else if (strcmp(category,"dihedral_style") == 0) {
|
|
style = force->dihedral_style;
|
|
} else if (strcmp(category,"improper_style") == 0) {
|
|
style = force->improper_style;
|
|
} else if (strcmp(category,"kspace_style") == 0) {
|
|
style = force->kspace_style;
|
|
} else error->all(FLERR,"Unknown category for info is_active()");
|
|
|
|
int match = 0;
|
|
if (strcmp(style,name) == 0) match = 1;
|
|
|
|
if (!match && lmp->suffix_enable) {
|
|
if (lmp->suffix) {
|
|
std::string name_w_suffix = name + std::string("/") + lmp->suffix;
|
|
if (name_w_suffix == style) match = 1;
|
|
}
|
|
if (!match && lmp->suffix2) {
|
|
std::string name_w_suffix = name + std::string("/") + lmp->suffix2;
|
|
if (name_w_suffix == style) match = 1;
|
|
}
|
|
}
|
|
return match ? true : false;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
// the is_available() function returns true if the selected style
|
|
// or name in the selected category is available for use (but need
|
|
// not be currently active).
|
|
|
|
bool Info::is_available(const char *category, const char *name)
|
|
{
|
|
if ((category == nullptr) || (name == nullptr)) return false;
|
|
|
|
if (has_style(category, name)) {
|
|
return true;
|
|
} else if (strcmp(category,"feature") == 0) {
|
|
if (strcmp(name,"gzip") == 0) {
|
|
return has_gzip_support();
|
|
} else if (strcmp(name,"png") == 0) {
|
|
return has_png_support();
|
|
} else if (strcmp(name,"jpeg") == 0) {
|
|
return has_jpeg_support();
|
|
} else if (strcmp(name,"ffmpeg") == 0) {
|
|
return has_ffmpeg_support();
|
|
} else if (strcmp(name,"exceptions") == 0) {
|
|
return has_exceptions();
|
|
}
|
|
} else error->all(FLERR,"Unknown category for info is_available()");
|
|
|
|
return false;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
// the is_defined() function returns true if a particular ID of the
|
|
// selected category (e.g. fix ID, group ID, region ID etc.) has been
|
|
// defined and thus can be accessed. It does *NOT* check whether a
|
|
// particular ID has a particular style.
|
|
|
|
bool Info::is_defined(const char *category, const char *name)
|
|
{
|
|
if ((category == nullptr) || (name == nullptr)) return false;
|
|
|
|
if (strcmp(category,"compute") == 0) {
|
|
int ncompute = modify->ncompute;
|
|
Compute **compute = modify->compute;
|
|
for (int i=0; i < ncompute; ++i) {
|
|
if (strcmp(compute[i]->id,name) == 0)
|
|
return true;
|
|
}
|
|
} else if (strcmp(category,"dump") == 0) {
|
|
int ndump = output->ndump;
|
|
Dump **dump = output->dump;
|
|
for (int i=0; i < ndump; ++i) {
|
|
if (strcmp(dump[i]->id,name) == 0)
|
|
return true;
|
|
}
|
|
} else if (strcmp(category,"fix") == 0) {
|
|
int nfix = modify->nfix;
|
|
Fix **fix = modify->fix;
|
|
for (int i=0; i < nfix; ++i) {
|
|
if (strcmp(fix[i]->id,name) == 0)
|
|
return true;
|
|
}
|
|
} else if (strcmp(category,"group") == 0) {
|
|
int ngroup = group->ngroup;
|
|
char **names = group->names;
|
|
for (int i=0; i < ngroup; ++i) {
|
|
if (strcmp(names[i],name) == 0)
|
|
return true;
|
|
}
|
|
} else if (strcmp(category,"region") == 0) {
|
|
int nreg = domain->nregion;
|
|
Region **regs = domain->regions;
|
|
for (int i=0; i < nreg; ++i) {
|
|
if (strcmp(regs[i]->id,name) == 0)
|
|
return true;
|
|
}
|
|
} else if (strcmp(category,"variable") == 0) {
|
|
int nvar = input->variable->nvar;
|
|
char **names = input->variable->names;
|
|
|
|
for (int i=0; i < nvar; ++i) {
|
|
if (strcmp(names[i],name) == 0)
|
|
return true;
|
|
}
|
|
} else error->all(FLERR,"Unknown category for info is_defined()");
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Info::has_style(const std::string &category, const std::string &name)
|
|
{
|
|
if (category == "atom") {
|
|
return find_style(lmp, atom->avec_map, name, false);
|
|
} else if (category == "integrate") {
|
|
return find_style(lmp, update->integrate_map, name, true);
|
|
} else if (category == "minimize") {
|
|
return find_style(lmp, update->minimize_map, name, true);
|
|
} else if (category == "pair") {
|
|
return find_style(lmp, force->pair_map, name, true);
|
|
} else if (category == "bond") {
|
|
return find_style(lmp, force->bond_map, name, true);
|
|
} else if (category == "angle") {
|
|
return find_style(lmp, force->angle_map, name, true);
|
|
} else if (category == "dihedral") {
|
|
return find_style(lmp, force->dihedral_map, name, true);
|
|
} else if (category == "improper") {
|
|
return find_style(lmp, force->improper_map, name, true);
|
|
} else if (category == "kspace") {
|
|
return find_style(lmp, force->kspace_map, name, true);
|
|
} else if (category == "fix") {
|
|
return find_style(lmp, modify->fix_map, name, true);
|
|
} else if (category == "compute") {
|
|
return find_style(lmp, modify->compute_map, name, true);
|
|
} else if (category == "region") {
|
|
return find_style(lmp, domain->region_map, name, false);
|
|
} else if (category == "dump") {
|
|
return find_style(lmp, output->dump_map, name, false);
|
|
} else if (category == "command") {
|
|
return find_style(lmp, input->command_map, name, false);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
std::vector<std::string> Info::get_available_styles(const std::string &category)
|
|
{
|
|
if (category == "atom") {
|
|
return get_style_names(atom->avec_map);
|
|
} else if (category == "integrate") {
|
|
return get_style_names(update->integrate_map);
|
|
} else if (category == "minimize") {
|
|
return get_style_names(update->minimize_map);
|
|
} else if (category == "pair") {
|
|
return get_style_names(force->pair_map);
|
|
} else if (category == "bond") {
|
|
return get_style_names(force->bond_map);
|
|
} else if (category == "angle") {
|
|
return get_style_names(force->angle_map);
|
|
} else if (category == "dihedral") {
|
|
return get_style_names(force->dihedral_map);
|
|
} else if (category == "improper") {
|
|
return get_style_names(force->improper_map);
|
|
} else if (category == "kspace") {
|
|
return get_style_names(force->kspace_map);
|
|
} else if (category == "fix") {
|
|
return get_style_names(modify->fix_map);
|
|
} else if (category == "compute") {
|
|
return get_style_names(modify->compute_map);
|
|
} else if (category == "region") {
|
|
return get_style_names(domain->region_map);
|
|
} else if (category == "dump") {
|
|
return get_style_names(output->dump_map);
|
|
} else if (category == "command") {
|
|
return get_style_names(input->command_map);
|
|
}
|
|
return std::vector<std::string>();
|
|
}
|
|
|
|
template<typename ValueType>
|
|
static std::vector<std::string> get_style_names(std::map<std::string, ValueType> *styles)
|
|
{
|
|
std::vector<std::string> names;
|
|
|
|
names.reserve(styles->size());
|
|
for (auto const& kv : *styles) {
|
|
// skip "secret" styles
|
|
if (isupper(kv.first[0])) continue;
|
|
names.push_back(kv.first);
|
|
}
|
|
|
|
return names;
|
|
}
|
|
|
|
template<typename ValueType>
|
|
static bool find_style(const LAMMPS *lmp, std::map<std::string, ValueType> *styles,
|
|
const std::string &name, bool suffix_check)
|
|
{
|
|
if (styles->find(name) != styles->end()) {
|
|
return true;
|
|
}
|
|
|
|
if (suffix_check && lmp->suffix_enable) {
|
|
if (lmp->suffix) {
|
|
std::string name_w_suffix = name + "/" + lmp->suffix;
|
|
if (find_style(lmp, styles, name_w_suffix, false)) {
|
|
return true;
|
|
}
|
|
}
|
|
if (lmp->suffix2) {
|
|
std::string name_w_suffix = name + "/" + lmp->suffix2;
|
|
if (find_style(lmp, styles, name_w_suffix, false)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
template<typename ValueType>
|
|
static void print_columns(FILE *fp, std::map<std::string, ValueType> *styles)
|
|
{
|
|
if (styles->empty()) {
|
|
fprintf(fp, "\nNone");
|
|
return;
|
|
}
|
|
|
|
// std::map keys are already sorted
|
|
int pos = 80;
|
|
for (typename std::map<std::string, ValueType>::iterator it = styles->begin(); it != styles->end(); ++it) {
|
|
const std::string &style_name = it->first;
|
|
|
|
// skip "secret" styles
|
|
if (isupper(style_name[0])) continue;
|
|
|
|
int len = style_name.length();
|
|
if (pos + len > 80) {
|
|
fprintf(fp,"\n");
|
|
pos = 0;
|
|
}
|
|
|
|
if (len < 16) {
|
|
fprintf(fp,"%-16s", style_name.c_str());
|
|
pos += 16;
|
|
} else if (len < 32) {
|
|
fprintf(fp,"%-32s", style_name.c_str());
|
|
pos += 32;
|
|
} else if (len < 48) {
|
|
fprintf(fp,"%-48s", style_name.c_str());
|
|
pos += 48;
|
|
} else if (len < 64) {
|
|
fprintf(fp,"%-64s", style_name.c_str());
|
|
pos += 64;
|
|
} else {
|
|
fprintf(fp,"%-80s", style_name.c_str());
|
|
pos += 80;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool Info::has_gzip_support() {
|
|
#ifdef LAMMPS_GZIP
|
|
return true;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
bool Info::has_png_support() {
|
|
#ifdef LAMMPS_PNG
|
|
return true;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
bool Info::has_jpeg_support() {
|
|
#ifdef LAMMPS_JPEG
|
|
return true;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
bool Info::has_ffmpeg_support() {
|
|
#ifdef LAMMPS_FFMPEG
|
|
return true;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
bool Info::has_exceptions() {
|
|
#ifdef LAMMPS_EXCEPTIONS
|
|
return true;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
bool Info::has_package(const std::string &package_name) {
|
|
for (int i = 0; LAMMPS::installed_packages[i] != nullptr; ++i) {
|
|
if (package_name == LAMMPS::installed_packages[i]) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
#if defined(LMP_GPU)
|
|
extern bool lmp_gpu_config(const std::string &, const std::string &);
|
|
extern bool lmp_has_gpu_device();
|
|
extern std::string lmp_gpu_device_info();
|
|
|
|
bool Info::has_gpu_device()
|
|
{
|
|
return lmp_has_gpu_device();
|
|
}
|
|
|
|
std::string Info::get_gpu_device_info()
|
|
{
|
|
return lmp_gpu_device_info();
|
|
}
|
|
#else
|
|
bool Info::has_gpu_device()
|
|
{
|
|
return false;
|
|
}
|
|
std::string Info::get_gpu_device_info()
|
|
{
|
|
return "";
|
|
}
|
|
#endif
|
|
|
|
#if defined(LMP_KOKKOS)
|
|
#include "Kokkos_Macros.hpp"
|
|
#endif
|
|
|
|
bool Info::has_accelerator_feature(const std::string &package,
|
|
const std::string &category,
|
|
const std::string &setting)
|
|
{
|
|
#if defined(LMP_KOKKOS)
|
|
if (package == "KOKKOS") {
|
|
if (category == "precision") {
|
|
if (setting == "double") return true;
|
|
else return false;
|
|
}
|
|
if (category == "api") {
|
|
#if defined(KOKKOS_ENABLE_OPENMP)
|
|
if (setting == "openmp") return true;
|
|
#endif
|
|
#if defined(KOKKOS_ENABLE_SERIAL)
|
|
if (setting == "serial") return true;
|
|
#endif
|
|
#if defined(KOKKOS_ENABLE_THREADS)
|
|
if (setting == "pthreads") return true;
|
|
#endif
|
|
#if defined(KOKKOS_ENABLE_CUDA)
|
|
if (setting == "cuda") return true;
|
|
#endif
|
|
#if defined(KOKKOS_ENABLE_HIP)
|
|
if (setting == "hip") return true;
|
|
#endif
|
|
#if defined(KOKKOS_ENABLE_SYCL)
|
|
if (setting == "sycl") return true;
|
|
#endif
|
|
return false;
|
|
}
|
|
}
|
|
#endif
|
|
#if defined(LMP_GPU)
|
|
if (package == "GPU") {
|
|
return lmp_gpu_config(category,setting);
|
|
}
|
|
#endif
|
|
#if defined(LMP_USER_OMP)
|
|
if (package == "USER-OMP") {
|
|
if (category == "precision") {
|
|
if (setting == "double") return true;
|
|
else return false;
|
|
}
|
|
if (category == "api") {
|
|
#if defined(_OPENMP)
|
|
if (setting == "openmp") return true;
|
|
#else
|
|
if (setting == "serial") return true;
|
|
#endif
|
|
return false;
|
|
}
|
|
}
|
|
#endif
|
|
#if defined(LMP_USER_INTEL)
|
|
if (package == "USER-INTEL") {
|
|
if (category == "precision") {
|
|
if (setting == "double") return true;
|
|
else if (setting == "mixed") return true;
|
|
else if (setting == "single")return true;
|
|
else return false;
|
|
}
|
|
if (category == "api") {
|
|
#if defined(LMP_INTEL_OFFLOAD)
|
|
if (setting == "phi") return true;
|
|
#elif defined(_OPENMP)
|
|
if (setting == "openmp") return true;
|
|
#else
|
|
if (setting == "serial") return true;
|
|
#endif
|
|
return false;
|
|
}
|
|
}
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
#define _INFOBUF_SIZE 256
|
|
|
|
std::string Info::get_os_info()
|
|
{
|
|
std::string buf;
|
|
|
|
#if defined(_WIN32)
|
|
DWORD fullversion,majorv,minorv,buildv=0;
|
|
|
|
fullversion = GetVersion();
|
|
majorv = (DWORD) (LOBYTE(LOWORD(fullversion)));
|
|
minorv = (DWORD) (HIBYTE(LOWORD(fullversion)));
|
|
if (fullversion < 0x80000000)
|
|
buildv = (DWORD) (HIWORD(fullversion));
|
|
|
|
buf = fmt::format("Windows {}.{} ({}) on ",majorv,minorv,buildv);
|
|
|
|
SYSTEM_INFO si;
|
|
GetSystemInfo(&si);
|
|
|
|
switch (si.wProcessorArchitecture) {
|
|
case PROCESSOR_ARCHITECTURE_AMD64:
|
|
buf += "x86_64";
|
|
break;
|
|
case PROCESSOR_ARCHITECTURE_ARM:
|
|
buf += "arm";
|
|
break;
|
|
case PROCESSOR_ARCHITECTURE_IA64:
|
|
buf += "ia64";
|
|
break;
|
|
case PROCESSOR_ARCHITECTURE_INTEL:
|
|
buf += "i386";
|
|
break;
|
|
default:
|
|
buf += "(unknown)";
|
|
}
|
|
#else
|
|
struct utsname ut;
|
|
uname(&ut);
|
|
|
|
// try to get OS distribution name, if available
|
|
std::string distro = ut.sysname;
|
|
if (utils::file_is_readable("/etc/os-release")) {
|
|
try {
|
|
TextFileReader reader("/etc/os-release","");
|
|
while (1) {
|
|
auto words = reader.next_values(0,"=");
|
|
if ((words.count() > 1) && (words.next_string() == "PRETTY_NAME")) {
|
|
distro += " " + utils::trim(words.next_string());
|
|
break;
|
|
}
|
|
}
|
|
} catch (std::exception &e) {
|
|
; // EOF but keyword not found
|
|
}
|
|
}
|
|
|
|
buf = fmt::format("{} {} on {}", distro, ut.release, ut.machine);
|
|
#endif
|
|
return buf;
|
|
}
|
|
|
|
std::string Info::get_compiler_info()
|
|
{
|
|
std::string buf;
|
|
#if defined(__INTEL_LLVM_COMPILER)
|
|
double version = static_cast<double>(__INTEL_LLVM_COMPILER)*0.01;
|
|
buf = fmt::format("Intel LLVM C++ {:.1f} / {}", version, __VERSION__);
|
|
#elif defined(__clang__)
|
|
buf = fmt::format("Clang C++ {}", __VERSION__);
|
|
#elif defined(__PGI)
|
|
buf = fmt::format("PGI C++ {}.{}",__PGIC__,__PGIC_MINOR__);
|
|
#elif defined(__INTEL_COMPILER)
|
|
double version = static_cast<double>(__INTEL_COMPILER)*0.01;
|
|
buf = fmt::format("Intel Classic C++ {:.2f}.{} / {}", version,
|
|
__INTEL_COMPILER_UPDATE, __VERSION__);
|
|
#elif defined(__GNUC__)
|
|
buf = fmt::format("GNU C++ {}", __VERSION__);
|
|
#else
|
|
buf = "(Unknown)";
|
|
#endif
|
|
return buf;
|
|
}
|
|
|
|
std::string Info::get_openmp_info()
|
|
{
|
|
|
|
#if !defined(_OPENMP)
|
|
return "OpenMP not enabled";
|
|
#else
|
|
|
|
// Supported OpenMP version corresponds to the release date of the
|
|
// specifications as posted at https://www.openmp.org/specifications/
|
|
|
|
#if _OPENMP > 201811
|
|
return "OpenMP newer than version 5.0";
|
|
#elif _OPENMP == 201811
|
|
return "OpenMP 5.0";
|
|
#elif _OPENMP == 201611
|
|
return "OpenMP 5.0 preview 1";
|
|
#elif _OPENMP == 201511
|
|
return "OpenMP 4.5";
|
|
#elif _OPENMP == 201307
|
|
return "OpenMP 4.0";
|
|
#elif _OPENMP == 201107
|
|
return "OpenMP 3.1";
|
|
#elif _OPENMP == 200805
|
|
return "OpenMP 3.0";
|
|
#elif _OPENMP == 200505
|
|
return "OpenMP 2.5";
|
|
#elif _OPENMP == 200203
|
|
return "OpenMP 2.0";
|
|
#else
|
|
return "unknown OpenMP version";
|
|
#endif
|
|
|
|
#endif
|
|
}
|
|
|
|
std::string Info::get_mpi_vendor() {
|
|
#if defined(MPI_STUBS)
|
|
return "MPI STUBS";
|
|
#elif defined(OPEN_MPI)
|
|
return "Open MPI";
|
|
#elif defined(MPICH_NAME)
|
|
return "MPICH";
|
|
#elif defined(I_MPI_VERSION)
|
|
return "Intel MPI";
|
|
#elif defined(PLATFORM_MPI)
|
|
return "Platform MPI";
|
|
#elif defined(HP_MPI)
|
|
return "HP MPI";
|
|
#elif defined(MSMPI_VER)
|
|
return "Microsoft MPI";
|
|
#else
|
|
return "Unknown MPI implementation";
|
|
#endif
|
|
}
|
|
|
|
std::string Info::get_mpi_info(int &major, int &minor)
|
|
{
|
|
int len;
|
|
#if (defined(MPI_VERSION) && (MPI_VERSION > 2)) || defined(MPI_STUBS)
|
|
static char version[MPI_MAX_LIBRARY_VERSION_STRING];
|
|
MPI_Get_library_version(version,&len);
|
|
#else
|
|
static char version[32];
|
|
strcpy(version,get_mpi_vendor().c_str());
|
|
len = strlen(version);
|
|
#endif
|
|
|
|
MPI_Get_version(&major,&minor);
|
|
if (len > 80) {
|
|
char *ptr = strchr(version+80,'\n');
|
|
if (ptr) *ptr = '\0';
|
|
}
|
|
return std::string(version);
|
|
}
|
|
|
|
std::string Info::get_cxx_info()
|
|
{
|
|
#if __cplusplus > 201703L
|
|
return "newer than C++17";
|
|
#elif __cplusplus == 201703L
|
|
return "C++17";
|
|
#elif __cplusplus == 201402L
|
|
return "C++14";
|
|
#elif __cplusplus == 201103L
|
|
return "C++11";
|
|
#elif __cplusplus == 199711L
|
|
return "C++98";
|
|
#else
|
|
return "unknown";
|
|
#endif
|
|
}
|
|
|
|
std::string Info::get_accelerator_info(const std::string &package)
|
|
{
|
|
std::string mesg("");
|
|
if ((package.empty() || (package == "GPU")) && has_package("GPU")) {
|
|
mesg += "GPU package API:";
|
|
if (has_accelerator_feature("GPU","api","cuda")) mesg += " CUDA";
|
|
if (has_accelerator_feature("GPU","api","hip")) mesg += " HIP";
|
|
if (has_accelerator_feature("GPU","api","opencl")) mesg += " OpenCL";
|
|
mesg += "\nGPU package precision:";
|
|
if (has_accelerator_feature("GPU","precision","single")) mesg += " single";
|
|
if (has_accelerator_feature("GPU","precision","mixed")) mesg += " mixed";
|
|
if (has_accelerator_feature("GPU","precision","double")) mesg += " double";
|
|
mesg += "\n";
|
|
}
|
|
if ((package.empty() || (package == "KOKKOS")) && has_package("KOKKOS")) {
|
|
mesg += "KOKKOS package API:";
|
|
if (has_accelerator_feature("KOKKOS","api","cuda")) mesg += " CUDA";
|
|
if (has_accelerator_feature("KOKKOS","api","hip")) mesg += " HIP";
|
|
if (has_accelerator_feature("KOKKOS","api","sycl")) mesg += " SYCL";
|
|
if (has_accelerator_feature("KOKKOS","api","openmp")) mesg += " OpenMP";
|
|
if (has_accelerator_feature("KOKKOS","api","serial")) mesg += " Serial";
|
|
if (has_accelerator_feature("KOKKOS","api","pthreads")) mesg += " Pthreads";
|
|
mesg += "\nKOKKOS package precision:";
|
|
if (has_accelerator_feature("KOKKOS","precision","single")) mesg += " single";
|
|
if (has_accelerator_feature("KOKKOS","precision","mixed")) mesg += " mixed";
|
|
if (has_accelerator_feature("KOKKOS","precision","double")) mesg += " double";
|
|
mesg += "\n";
|
|
}
|
|
if ((package.empty() || (package == "USER-OMP")) && has_package("USER-OMP")) {
|
|
mesg += "USER-OMP package API:";
|
|
if (has_accelerator_feature("USER-OMP","api","openmp")) mesg += " OpenMP";
|
|
if (has_accelerator_feature("USER-OMP","api","serial")) mesg += " Serial";
|
|
mesg += "\nUSER-OMP package precision:";
|
|
if (has_accelerator_feature("USER-OMP","precision","single")) mesg += " single";
|
|
if (has_accelerator_feature("USER-OMP","precision","mixed")) mesg += " mixed";
|
|
if (has_accelerator_feature("USER-OMP","precision","double")) mesg += " double";
|
|
mesg += "\n";
|
|
}
|
|
if ((package.empty() || (package == "USER-INTEL")) && has_package("USER-INTEL")) {
|
|
mesg += "USER-INTEL package API:";
|
|
if (has_accelerator_feature("USER-INTEL","api","phi")) mesg += " Phi";
|
|
if (has_accelerator_feature("USER-INTEL","api","openmp")) mesg += " OpenMP";
|
|
mesg += "\nUSER-INTEL package precision:";
|
|
if (has_accelerator_feature("USER-INTEL","precision","single")) mesg += " single";
|
|
if (has_accelerator_feature("USER-INTEL","precision","mixed")) mesg += " mixed";
|
|
if (has_accelerator_feature("USER-INTEL","precision","double")) mesg += " double";
|
|
mesg += "\n";
|
|
}
|
|
return mesg;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
void Info::get_memory_info(double *meminfo)
|
|
{
|
|
double bytes = 0;
|
|
bytes += atom->memory_usage();
|
|
bytes += neighbor->memory_usage();
|
|
bytes += comm->memory_usage();
|
|
bytes += update->memory_usage();
|
|
bytes += force->memory_usage();
|
|
bytes += modify->memory_usage();
|
|
for (int i = 0; i < output->ndump; i++)
|
|
bytes += output->dump[i]->memory_usage();
|
|
meminfo[0] = bytes/1024.0/1024.0;
|
|
meminfo[1] = 0;
|
|
meminfo[2] = 0;
|
|
|
|
#if defined(_WIN32)
|
|
HANDLE phandle = GetCurrentProcess();
|
|
PROCESS_MEMORY_COUNTERS_EX pmc;
|
|
GetProcessMemoryInfo(phandle,(PROCESS_MEMORY_COUNTERS *)&pmc,sizeof(pmc));
|
|
meminfo[1] = (double)pmc.PrivateUsage/1048576.0;
|
|
meminfo[2] = (double)pmc.PeakWorkingSetSize/1048576.0;
|
|
#else
|
|
#if defined(__linux__)
|
|
#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 33)
|
|
struct mallinfo2 mi;
|
|
mi = mallinfo2();
|
|
#else
|
|
struct mallinfo mi;
|
|
mi = mallinfo();
|
|
#endif
|
|
meminfo[1] = (double)mi.uordblks/1048576.0+(double)mi.hblkhd/1048576.0;
|
|
#endif
|
|
struct rusage ru;
|
|
if (getrusage(RUSAGE_SELF, &ru) == 0)
|
|
meminfo[2] = (double)ru.ru_maxrss/1024.0;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
char **Info::get_variable_names(int &num) {
|
|
num = input->variable->nvar;
|
|
return input->variable->names;
|
|
}
|