// 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. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- 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 "json.h" #include "lmpfftsettings.h" #include "modify.h" #include "neighbor.h" #include "output.h" #include "pair.h" #include "pair_hybrid.h" #include "region.h" #include "update.h" #include "variable.h" #ifndef FMT_STATIC_THOUSANDS_SEPARATOR #include "fmt/chrono.h" #endif #include #include #include #include #include #ifdef _WIN32 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #define PSAPI_VERSION 1 #include #include #include #else #include #endif #if defined(__linux__) #include #include #include #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, FFT=1<<27, 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; 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 static void print_columns(FILE *fp, std::map *styles); template static bool find_style(const LAMMPS *lmp, std::map *styles, const std::string &name, bool suffix_check); template static std::vector get_style_names(std::map *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",4) == 0) { flags |= COMM; ++idx; } else if (strncmp(arg[idx],"computes",4) == 0) { flags |= COMPUTES; ++idx; } else if (strncmp(arg[idx],"dumps",3) == 0) { flags |= DUMPS; ++idx; } else if (strncmp(arg[idx],"fixes",3) == 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],"fft",3) == 0) { flags |= FFT; ++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: {}",arg[idx]); ++idx; } } if (out == nullptr) return; fputs("\nInfo-Info-Info-Info-Info-Info-Info-Info-Info-Info-Info\n",out); #if defined(FMT_STATIC_THOUSANDS_SEPARATOR) { time_t tv = time(nullptr); struct tm *now = localtime(&tv); utils::print(out, "Printed on {}", asctime(now)); } #else std::tm now = fmt::localtime(std::time(nullptr)); utils::print(out,"Printed on {}", std::asctime(&now)); #endif if (flags & CONFIG) { utils::print(out,"\nLAMMPS version: {} / {}\n", lmp->version, lmp->num_ver); if (LAMMPS::has_git_info()) utils::print(out,"Git info: {} / {} / {}\n", LAMMPS::git_branch(), LAMMPS::git_descriptor(),LAMMPS::git_commit()); utils::print(out,"\nOS information: {}\n\n",platform::os_info()); utils::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); utils::print(out,"\nCompiler: {} with {}\nC++ standard: {}\n", platform::compiler_info(),platform::openmp_standard(),platform::cxx_standard()); fputs(get_fmt_info().c_str(), out); fputs(get_json_info().c_str(), out); 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_curl_support()) fputs("-DLAMMPS_CURL\n",out); if (has_fft_single_support()) fputs("-DFFT_SINGLE\n",out); #if defined(LAMMPS_BIGBIG) fputs("-DLAMMPS_BIGBIG\n",out); #elif defined(LAMMPS_SMALLBIG) fputs("-DLAMMPS_SMALLBIG\n",out); #endif if (has_gzip_support()) utils::print(out,"\n{}\n",platform::compress_info()); int ncword, ncline = 0; fputs("\nInstalled packages:\n\n",out); for (const char **pkg = LAMMPS::installed_packages; *pkg != nullptr; ++pkg) { ncword = strlen(*pkg); if (ncline + ncword > 78) { ncline = 0; fputs("\n",out); } utils::print(out,"{} ",*pkg); ncline += ncword + 1; } fputs("\n",out); } if (flags & ACCELERATOR) { utils::print(out,"\nAccelerator configuration:\n\n{}", get_accelerator_info()); if (Info::has_gpu_device()) utils::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); utils::print(out,"Total dynamically allocated memory: {:.4} Mbyte\n", meminfo[0]); #if defined(_WIN32) utils::print(out,"Non-shared memory use: {:.4} Mbyte\n",meminfo[1]); utils::print(out,"Maximum working set size: {:.4} Mbyte\n",meminfo[2]); #else #if defined(__linux__) utils::print(out,"Current reserved memory pool size: {:.4} Mbyte\n", meminfo[1]); #endif utils::print(out,"Maximum resident set size: {:.4} Mbyte\n",meminfo[2]); #endif } if (flags & COMM) { int major,minor; std::string version = platform::mpi_info(major,minor); utils::print(out,"\nCommunication information:\n" "MPI library level: MPI v{}.{}\n" "MPI version: {}\n",major,minor,version); utils::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) utils::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=0; i < neighbor->ncollections; ++i) { if (comm->cutusermulti) cut = comm->cutusermulti[i]; else cut = 0.0; for (int j=0; j < neighbor->ncollections; ++j) { cut = MAX(cut,sqrt(neighbor->cutcollectionsq[i][j])); } if (comm->cutusermulti) cut = MAX(cut,comm->cutusermulti[i]); utils::print(out,"Communication cutoff for collection {} = {:.8}\n", i, cut); } } if (comm->mode == 2) { fputs("Communication mode = multi/old\n",out); double cut; for (int i=1; i <= atom->ntypes && neighbor->cuttype; ++i) { cut = neighbor->cuttype[i]; if (comm->cutusermultiold) cut = MAX(cut,comm->cutusermultiold[i]); utils::print(out,"Communication cutoff for type {} = {:.8}\n", i, cut); } } } utils::print(out,"Nprocs = {}, Nthreads = {}\n",comm->nprocs,comm->nthreads); if (domain->box_exist) utils::print(out,"Processor grid = {} x {} x {}\n",comm->procgrid[0], comm->procgrid[1], comm->procgrid[2]); } if (flags & FFT) { fputs("\nFFT information:\n",out); fputs(get_fft_info().c_str(),out); } if (flags & SYSTEM) { fputs("\nSystem information:\n",out); utils::print(out,"Units = {}\n", update->unit_style); utils::print(out,"Atom style = {}\n", atom->get_style()); utils::print(out,"Atom map = {}\n", mapstyles[atom->map_style]); if (atom->molecular != Atom::ATOMIC) { const char *msg; msg = (atom->molecular == Atom::TEMPLATE) ? "template" : "standard"; utils::print(out,"Molecule type = {}\n",msg); } utils::print(out,"Atoms = {:12}, types = {:8d}, style = {}\n", atom->natoms, atom->ntypes, force->pair_style); if (atom->tag_enable) utils::print(out,"Atoms with atom IDs\n"); if (atom->molecule) utils::print(out,"Atoms with molecule IDs\n"); if (atom->mass) utils::print(out,"Atoms with per-type masses\n"); if (atom->rmass) utils::print(out,"Atoms with per-atom masses\n"); if (atom->q) utils::print(out,"Atoms with per-atom charges\n"); if (force->pair && utils::strmatch(force->pair_style,"^hybrid")) { auto hybrid = dynamic_cast(force->pair); utils::print(out,"Hybrid sub-styles:"); for (int i=0; i < hybrid->nstyles; ++i) utils::print(out," {}", hybrid->keywords[i]); fputc('\n',out); } if (atom->molecular != Atom::ATOMIC) { const char *msg; msg = force->bond_style ? force->bond_style : "none"; utils::print(out,"Bonds = {:12}, types = {:8}, style = {}\n", atom->nbonds, atom->nbondtypes, msg); msg = force->angle_style ? force->angle_style : "none"; utils::print(out,"Angles = {:12}, types = {:8}, style = {}\n", atom->nangles, atom->nangletypes, msg); msg = force->dihedral_style ? force->dihedral_style : "none"; utils::print(out,"Dihedrals = {:12}, types = {:8}, style = {}\n", atom->ndihedrals, atom->ndihedraltypes, msg); msg = force->improper_style ? force->improper_style : "none"; utils::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; utils::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]); } utils::print(out,"Kspace style = {}\n", force->kspace ? force->kspace_style : "none"); if (domain->box_exist) { utils::print(out,"\nDimensions = {}\n",domain->dimension); utils::print(out,"{} box = {:.8} x {:.8} x {:.8}\n", domain->triclinic ? "Triclinic" : "Orthogonal", domain->xprd, domain->yprd, domain->zprd); utils::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]]); utils::print(out,"xlo, xhi = {:.8}, {:.8}\n", domain->boxlo[0], domain->boxhi[0]); utils::print(out,"ylo, yhi = {:.8}, {:.8}\n", domain->boxlo[1], domain->boxhi[1]); utils::print(out,"zlo, zhi = {:.8}, {:.8}\n", domain->boxlo[2], domain->boxhi[2]); if (domain->triclinic) utils::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); } utils::print(out,"\nCurrent timestep number = {}\n", update->ntimestep); utils::print(out,"Current timestep size = {}\n", update->dt); } if (domain->box_exist && (flags & COEFFS)) { Pair *pair=force->pair; fputs("\nCoeff status information:\n",out); if (pair) utils::print(out,"\nPair coeffs\n{}", get_pair_coeff_status(lmp)); if (force->bond) utils::print(out,"\nBond coeffs\n{}", get_bond_coeff_status(lmp)); if (force->angle) utils::print(out,"\nAngle coeffs\n{}", get_angle_coeff_status(lmp)); if (force->dihedral) utils::print(out,"\nDihedral coeffs\n{}", get_dihedral_coeff_status(lmp)); if (force->improper) utils::print(out,"\nImproper coeffs\n{}", get_improper_coeff_status(lmp)); } 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]) utils::print(out,"Group[{:2d}]: {:16} ({})\n", i, names[i], dynamic[i] ? "dynamic" : "static"); } } if (flags & REGIONS) { fputs("\nRegion information:\n",out); int i=0; for (auto ® : domain->get_region_list()) { utils::print(out,"Region[{:3d}]: {:16} style = {:16} side = {}\n", i, std::string(reg->id)+',', std::string(reg->style)+',', reg->interior ? "in" : "out"); if (reg->bboxflag) utils::print(out," Boundary: lo {:.8} {:.8} {:.8} hi {:.8} {:.8} {:.8}\n", reg->extent_xlo, reg->extent_ylo, reg->extent_zlo, reg->extent_xhi, reg->extent_yhi, reg->extent_zhi); else fputs(" No Boundary\n",out); } } if (flags & COMPUTES) { int i = 0; char **names = group->names; fputs("\nCompute information:\n",out); for (const auto &compute : modify->get_compute_list()) utils::print(out,"Compute[{:3d}]: {:16} style = {:16} group = {}\n", i++, std::string(compute->id)+',',std::string(compute->style)+',', names[compute->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) { utils::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]) { utils::print(out,"every = {}\n", nevery[i]); } else { utils::print(out,"every = {}\n", vnames[i]); } } } if (flags & FIXES) { int i = 0; char **names = group->names; fputs("\nFix information:\n",out); for (const auto &fix : modify->get_fix_list()) utils::print(out, "Fix[{:3d}]: {:16} style = {:16} group = {}\n",i++, std::string(fix->id)+',',std::string(fix->style)+',',names[fix->igroup]); } if (flags & VARIABLES) { int nvar = input->variable->nvar; fputs("\nVariable information:\n",out); for (int i=0; i < nvar; ++i) { auto vinfo = get_variable_info(i); utils::print(out, get_variable_info(i)); } } if (flags & TIME) { double wallclock = platform::walltime() - lmp->initclock; double cpuclock = platform::cputime(); 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; utils::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->get_fix_by_id("package_gpu") != nullptr; } else if (strcmp(name,"intel") == 0) { return modify->get_fix_by_id("package_intel") != nullptr; } else if (strcmp(name,"kokkos") == 0) { return lmp->kokkos && lmp->kokkos->kokkos_exists; } else if (strcmp(name,"omp") == 0) { return modify->get_fix_by_id("package_omp") != nullptr; } else error->all(FLERR,"Unknown name for info package category: {}", name); } 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: {}", name); } 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: {}", name); } 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(): {}", category); 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 != 0; } /* ---------------------------------------------------------------------- */ // 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,"curl") == 0) { return has_curl_support(); } else if (strcmp(name,"fft_single") == 0) { return has_fft_single_support(); } else if (strcmp(name,"exceptions") == 0) { return has_exceptions(); } } else error->all(FLERR,"Unknown category for info is_available(): {}", category); 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) { if (modify->get_compute_by_id(name)) return true; } else if (strcmp(category,"dump") == 0) { if (output->get_dump_by_id(name)) return true; } else if (strcmp(category,"fix") == 0) { if (modify->get_fix_by_id(name)) return true; } else if (strcmp(category,"group") == 0) { if (group->find(name) >= 0) return true; } else if (strcmp(category,"region") == 0) { if (domain->get_region_by_id(name)) return true; } else if (strcmp(category,"variable") == 0) { if (input->variable->find(name) >= 0) return true; } else error->all(FLERR,"Unknown category for info is_defined(): {}", category); 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 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 {}; } template static std::vector get_style_names(std::map *styles) { std::vector 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 static bool find_style(const LAMMPS *lmp, std::map *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 static void print_columns(FILE *fp, std::map *styles) { if (styles->empty()) { fprintf(fp, "\nNone"); return; } // std::map keys are already sorted int pos = 80; for (auto it = styles->begin(); it != styles->end(); ++it) { const std::string &style_name = it->first; // skip "internal" styles if (isupper(style_name[0]) || utils::strmatch(style_name,"/kk/host$") || utils::strmatch(style_name,"/kk/device$")) 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_curl_support() { #ifdef LAMMPS_CURL return true; #else return false; #endif } bool Info::has_fft_single_support() { #ifdef FFT_SINGLE return true; #else return false; #endif } bool Info::has_exceptions() { return true; } 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_compatible_gpu_device(); extern std::string lmp_gpu_device_info(); // we will only report compatible GPUs, i.e. when a GPU device is // available *and* supports the required floating point precision bool Info::has_gpu_device() { return lmp_has_compatible_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") { return setting == "double"; } 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_OPENMP) if (package == "OPENMP") { if (category == "precision") { return setting == "double"; } if (category == "api") { #if defined(_OPENMP) return setting == "openmp"; #else return setting == "serial"; #endif } } #endif #if defined(LMP_INTEL) if (package == "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; } #if defined(LMP_INTEL) #include "intel_preprocess.h" #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"; #if LMP_KOKKOS mesg += fmt::format("\nKokkos library version: {}.{}.{}", KOKKOS_VERSION / 10000, (KOKKOS_VERSION % 10000) / 100, KOKKOS_VERSION % 100); #endif mesg += "\n"; } if ((package.empty() || (package == "OPENMP")) && has_package("OPENMP")) { mesg += "OPENMP package API:"; if (has_accelerator_feature("OPENMP","api","openmp")) mesg += " OpenMP"; if (has_accelerator_feature("OPENMP","api","serial")) mesg += " Serial"; mesg += "\nOPENMP package precision:"; if (has_accelerator_feature("OPENMP","precision","single")) mesg += " single"; if (has_accelerator_feature("OPENMP","precision","mixed")) mesg += " mixed"; if (has_accelerator_feature("OPENMP","precision","double")) mesg += " double"; #if defined(_OPENMP) mesg += "\nOpenMP standard: " + platform::openmp_standard(); #endif mesg += "\n"; } if ((package.empty() || (package == "INTEL")) && has_package("INTEL")) { mesg += "INTEL package API:"; if (has_accelerator_feature("INTEL","api","phi")) mesg += " Phi"; if (has_accelerator_feature("INTEL","api","openmp")) mesg += " OpenMP"; mesg += "\nINTEL package precision:"; if (has_accelerator_feature("INTEL","precision","single")) mesg += " single"; if (has_accelerator_feature("INTEL","precision","mixed")) mesg += " mixed"; if (has_accelerator_feature("INTEL","precision","double")) mesg += " double"; #if defined(LMP_SIMD_COMPILER) mesg += "\nINTEL package SIMD: enabled"; #else mesg += "\nINTEL package SIMD: not enabled"; #endif mesg += "\n"; } return mesg; } /* ---------------------------------------------------------------------- */ std::string Info::get_fft_info() { std::string fft_info; #if defined(FFT_SINGLE) fft_info = "FFT precision = single\n"; #else fft_info = "FFT precision = double\n"; #endif #if defined(FFT_HEFFTE) fft_info += "FFT engine = HeFFTe\n"; #if defined(FFT_HEFFTE_MKL) fft_info += "FFT library = MKL\n"; #elif defined(FFT_HEFFTE_FFTW) fft_info += "FFT library = FFTW\n"; #else fft_info += "FFT library = (builtin)\n"; #endif #else fft_info += "FFT engine = mpiFFT\n"; #if defined(FFT_MKL) #if defined(FFT_MKL_THREADS) fft_info += "FFT library = MKL with threads\n"; #else fft_info += "FFT library = MKL\n"; #endif #elif defined(FFT_MKL_GPU) fft_info += "FFT library = MKL GPU\n"; #elif defined(FFT_NVPL) fft_info += "FFT library = NVPL\n"; #elif defined(FFT_FFTW3) #if defined(FFT_FFTW_THREADS) fft_info += "FFT library = FFTW3 with threads\n"; #else fft_info += "FFT library = FFTW3\n"; #endif #else fft_info += "FFT library = KISS\n"; #endif #endif #if defined(LMP_KOKKOS) fft_info += "KOKKOS FFT engine = mpiFFT\n"; #if defined(FFT_KOKKOS_CUFFT) fft_info += "KOKKOS FFT library = cuFFT\n"; #elif defined(FFT_KOKKOS_HIPFFT) fft_info += "KOKKOS FFT library = hipFFT\n"; #elif defined(FFT_KOKKOS_FFTW3) #if defined(FFT_KOKKOS_FFTW_THREADS) fft_info += "KOKKOS FFT library = FFTW3 with threads\n"; #else fft_info += "KOKKOS FFT library = FFTW3\n"; #endif #elif defined(FFT_KOKKOS_NVPL) fft_info += "KOKKOS FFT library = NVPL\n"; #elif defined(FFT_KOKKOS_MKL) #if defined(FFT_KOKKOS_MKL_THREADS) fft_info += "KOKKOS FFT library = MKL with threads\n"; #else fft_info += "KOKKOS FFT library = MKL\n"; #endif #elif defined(FFT_KOKKOS_MKL_GPU) fft_info += "KOKKOS FFT library = MKL GPU\n"; #else fft_info += "KOKKOS FFT library = KISS\n"; #endif #endif return fft_info; } /* ---------------------------------------------------------------------- */ static constexpr int fmt_ver_major = FMT_VERSION / 10000; static constexpr int fmt_ver_minor = (FMT_VERSION % 10000) / 100; static constexpr int fmt_ver_patch = FMT_VERSION % 100; std::string Info::get_fmt_info() { return fmt::format("Embedded fmt library version: {}.{}.{}\n", fmt_ver_major, fmt_ver_minor, fmt_ver_patch); } /* ---------------------------------------------------------------------- */ std::string Info::get_json_info() { return fmt::format("Embedded JSON class version: {}.{}.{}\n", NLOHMANN_JSON_VERSION_MAJOR, NLOHMANN_JSON_VERSION_MINOR, NLOHMANN_JSON_VERSION_PATCH); } /* ---------------------------------------------------------------------- */ 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__) // __GLIBC_MINOR__ is only defined on real glibc (i.e. not on musl) #if defined(__GLIBC_MINOR__) // newer glibc versions have mallinfo2 #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 // not glibc => may not have mallinfo/mallinfo2 #else meminfo[1] = 0.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; } /* ---------------------------------------------------------------------- */ std::string Info::get_variable_info(int num) { int *style = input->variable->style; char **names = input->variable->names; char ***data = input->variable->data; std::string text; int ndata = 1; text = fmt::format("Variable[{:3d}]: {:16} style = {:16} def =", num, std::string(names[num]) + ',', Variable::varstyles[style[num]] + ','); if (style[num] == Variable::INTERNAL) { text += fmt::format("{:.8}\n",input->variable->dvalue[num]); return text; } if ((style[num] != Variable::LOOP) && (style[num] != Variable::ULOOP)) ndata = input->variable->num[num]; else input->variable->retrieve(names[num]); for (int j=0; j < ndata; ++j) if (data[num][j]) text += fmt::format(" {}",data[num][j]); text += "\n"; return text; } /* ---------------------------------------------------------------------- */ std::string Info::get_pair_coeff_status(const LAMMPS *lmp) { if (!lmp || !lmp->force || !lmp->force->pair || !lmp->force->pair->allocated) return "Pair style not yet initialized\n"; const auto ntypes = lmp->atom->ntypes; const auto setflag = lmp->force->pair->setflag; std::string output = ""; for (int i=1; i <= ntypes; ++i) { for (int j=i; j <= ntypes; ++j) output += fmt::format("{:6d} {:6d}: is{}set\n", i, j, setflag[i][j] ? " " : " not "); } return output; } /* ---------------------------------------------------------------------- */ std::string Info::get_bond_coeff_status(const LAMMPS *lmp) { if (!lmp || !lmp->force || !lmp->force->bond || !lmp->force->bond->allocated) return "Bond style not yet initialized\n"; const auto ntypes = lmp->atom->nbondtypes; const auto setflag = lmp->force->bond->setflag; std::string output = ""; for (int i=1; i <= ntypes; ++i) output += fmt::format("{:6d}: is{}set\n", i, setflag[i] ? " " : " not "); return output; } /* ---------------------------------------------------------------------- */ std::string Info::get_angle_coeff_status(const LAMMPS *lmp) { if (!lmp || !lmp->force || !lmp->force->angle || !lmp->force->angle->allocated) return "Angle style not yet initialized\n"; const auto ntypes = lmp->atom->nangletypes; const auto setflag = lmp->force->angle->setflag; std::string output = ""; for (int i=1; i <= ntypes; ++i) output += fmt::format("{:6d}: is{}set\n", i, setflag[i] ? " " : " not "); return output; } /* ---------------------------------------------------------------------- */ std::string Info::get_dihedral_coeff_status(const LAMMPS *lmp) { if (!lmp || !lmp->force || !lmp->force->dihedral || !lmp->force->dihedral->allocated) return "Dihedral style not yet initialized\n"; const auto ntypes = lmp->atom->ndihedraltypes; const auto setflag = lmp->force->dihedral->setflag; std::string output = ""; for (int i=1; i <= ntypes; ++i) output += fmt::format("{:6d}: is{}set\n", i, setflag[i] ? " " : " not "); return output; } /* ---------------------------------------------------------------------- */ std::string Info::get_improper_coeff_status(const LAMMPS *lmp) { if (!lmp || !lmp->force || !lmp->force->improper || !lmp->force->improper->allocated) return "Improper style not yet initialized\n"; const auto ntypes = lmp->atom->nimpropertypes; const auto setflag = lmp->force->improper->setflag; std::string output = ""; for (int i=1; i <= ntypes; ++i) output += fmt::format("{:6d}: is{}set\n", i, setflag[i] ? " " : " not "); return output; }