1 // clang-format off
2 /* ----------------------------------------------------------------------
3 LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
4 https://www.lammps.org/, Sandia National Laboratories
5 Steve Plimpton, sjplimp@sandia.gov
6
7 Copyright (2003) Sandia Corporation. Under the terms of Contract
8 DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
9 certain rights in this software. This software is distributed under
10 the GNU General Public License.
11
12 See the README file in the top-level LAMMPS directory.
13 ------------------------------------------------------------------------- */
14
15 /* ----------------------------------------------------------------------
16 Contributing authors: Axel Kohlmeyer (Temple U),
17 Richard Berger (Temple U)
18 ------------------------------------------------------------------------- */
19
20 #include "info.h"
21
22 #include "accelerator_kokkos.h"
23 #include "angle.h"
24 #include "atom.h"
25 #include "bond.h"
26 #include "comm.h"
27 #include "compute.h"
28 #include "dihedral.h"
29 #include "domain.h"
30 #include "dump.h"
31 #include "error.h"
32 #include "fix.h"
33 #include "force.h"
34 #include "group.h"
35 #include "improper.h"
36 #include "input.h"
37 #include "modify.h"
38 #include "neighbor.h"
39 #include "output.h"
40 #include "pair.h"
41 #include "pair_hybrid.h"
42 #include "region.h"
43 #include "text_file_reader.h"
44 #include "update.h"
45 #include "variable.h"
46 #include "fmt/chrono.h"
47
48 #include <cctype>
49 #include <cmath>
50 #include <cstring>
51 #include <ctime>
52 #include <exception>
53 #include <map>
54
55 #ifdef _WIN32
56 #ifndef WIN32_LEAN_AND_MEAN
57 #define WIN32_LEAN_AND_MEAN
58 #endif
59 #define PSAPI_VERSION 1
60 #include <windows.h>
61 #include <cstdint>
62 #include <psapi.h>
63 #else
64 #include <sys/resource.h>
65 #include <sys/utsname.h>
66 #endif
67
68 #if defined(__linux__)
69 #include <malloc.h>
70 #endif
71
72 namespace LAMMPS_NS {
73
74 enum {COMPUTES=1<<0,
75 DUMPS=1<<1,
76 FIXES=1<<2,
77 GROUPS=1<<3,
78 REGIONS=1<<4,
79 CONFIG=1<<5,
80 TIME=1<<6,
81 MEMORY=1<<7,
82 VARIABLES=1<<8,
83 SYSTEM=1<<9,
84 COMM=1<<10,
85 COEFFS=1<<11,
86 ATOM_STYLES=1<<12,
87 INTEGRATE_STYLES=1<<13,
88 MINIMIZE_STYLES=1<<14,
89 PAIR_STYLES=1<<15,
90 BOND_STYLES=1<<16,
91 ANGLE_STYLES=1<<17,
92 DIHEDRAL_STYLES=1<<18,
93 IMPROPER_STYLES=1<<19,
94 KSPACE_STYLES=1<<20,
95 FIX_STYLES=1<<21,
96 COMPUTE_STYLES=1<<22,
97 REGION_STYLES=1<<23,
98 DUMP_STYLES=1<<24,
99 COMMAND_STYLES=1<<25,
100 ACCELERATOR=1<<26,
101 ALL=~0};
102
103 static const int STYLES = ATOM_STYLES | INTEGRATE_STYLES | MINIMIZE_STYLES
104 | PAIR_STYLES | BOND_STYLES | ANGLE_STYLES
105 | DIHEDRAL_STYLES | IMPROPER_STYLES | KSPACE_STYLES
106 | FIX_STYLES | COMPUTE_STYLES | REGION_STYLES
107 | DUMP_STYLES | COMMAND_STYLES;
108 }
109
110 using namespace LAMMPS_NS;
111
112 // must match enumerator in variable.h
113 static const char *varstyles[] = {
114 "index", "loop", "world", "universe", "uloop", "string", "getenv",
115 "file", "atomfile", "format", "equal", "atom", "vector", "python",
116 "internal", "(unknown)"};
117
118 static const char *mapstyles[] = { "none", "array", "hash", "yes" };
119
120 static const char *commstyles[] = { "brick", "tiled" };
121 static const char *commlayout[] = { "uniform", "nonuniform", "irregular" };
122
123 static const char bstyles[] = "pfsm";
124
125 template<typename ValueType>
126 static void print_columns(FILE *fp, std::map<std::string, ValueType> *styles);
127
128 template<typename ValueType>
129 static bool find_style(const LAMMPS *lmp, std::map<std::string, ValueType> *styles,
130 const std::string &name, bool suffix_check);
131
132 template<typename ValueType>
133 static std::vector<std::string> get_style_names(std::map<std::string, ValueType> *styles);
134
135 /* ---------------------------------------------------------------------- */
136
command(int narg,char ** arg)137 void Info::command(int narg, char **arg)
138 {
139 FILE *out=screen;
140 int flags=0;
141
142 if (comm->me != 0) return;
143
144 // parse arguments
145 int idx = 0;
146
147 while (idx < narg) {
148 if (strncmp(arg[idx],"all",3) == 0) {
149 flags |= ALL;
150 ++idx;
151 } else if ((idx+1 < narg) && (strncmp(arg[idx],"out",3) == 0)
152 && (strncmp(arg[idx+1],"screen",3) == 0)) {
153 if ((out != screen) && (out != logfile)) fclose(out);
154 out = screen;
155 idx += 2;
156 } else if ((idx+1 < narg) && (strncmp(arg[idx],"out",3) == 0)
157 && (strncmp(arg[idx+1],"log",3) == 0)) {
158 if ((out != screen) && (out != logfile)) fclose(out);
159 out = logfile;
160 idx += 2;
161 } else if ((idx+2 < narg) && (strncmp(arg[idx],"out",3) == 0)
162 && (strncmp(arg[idx+1],"append",3) == 0)) {
163 if ((out != screen) && (out != logfile)) fclose(out);
164 out = fopen(arg[idx+2],"a");
165 idx += 3;
166 } else if ((idx+2 < narg) && (strncmp(arg[idx],"out",3) == 0)
167 && (strncmp(arg[idx+1],"overwrite",3) == 0)) {
168 if ((out != screen) && (out != logfile)) fclose(out);
169 out = fopen(arg[idx+2],"w");
170 idx += 3;
171 } else if (strncmp(arg[idx],"communication",5) == 0) {
172 flags |= COMM;
173 ++idx;
174 } else if (strncmp(arg[idx],"computes",5) == 0) {
175 flags |= COMPUTES;
176 ++idx;
177 } else if (strncmp(arg[idx],"dumps",5) == 0) {
178 flags |= DUMPS;
179 ++idx;
180 } else if (strncmp(arg[idx],"fixes",5) == 0) {
181 flags |= FIXES;
182 ++idx;
183 } else if (strncmp(arg[idx],"groups",3) == 0) {
184 flags |= GROUPS;
185 ++idx;
186 } else if (strncmp(arg[idx],"regions",3) == 0) {
187 flags |= REGIONS;
188 ++idx;
189 } else if (strncmp(arg[idx],"config",3) == 0) {
190 flags |= CONFIG;
191 ++idx;
192 } else if (strncmp(arg[idx],"time",3) == 0) {
193 flags |= TIME;
194 ++idx;
195 } else if (strncmp(arg[idx],"memory",3) == 0) {
196 flags |= MEMORY;
197 ++idx;
198 } else if (strncmp(arg[idx],"variables",3) == 0) {
199 flags |= VARIABLES;
200 ++idx;
201 } else if (strncmp(arg[idx],"system",3) == 0) {
202 flags |= SYSTEM;
203 ++idx;
204 } else if (strncmp(arg[idx],"coeffs",3) == 0) {
205 flags |= COEFFS;
206 ++idx;
207 } else if (strncmp(arg[idx],"accelerator",3) == 0) {
208 flags |= ACCELERATOR;
209 ++idx;
210 } else if (strncmp(arg[idx],"styles",3) == 0) {
211 if (idx+1 < narg) {
212 ++idx;
213 if (strncmp(arg[idx],"all",3) == 0) {
214 flags |= STYLES;
215 ++idx;
216 } else if (strncmp(arg[idx],"atom",3) == 0) {
217 flags |= ATOM_STYLES;
218 ++idx;
219 } else if (strncmp(arg[idx],"integrate",3) == 0) {
220 flags |= INTEGRATE_STYLES;
221 ++idx;
222 } else if (strncmp(arg[idx],"minimize",3) == 0) {
223 flags |= MINIMIZE_STYLES;
224 ++idx;
225 } else if (strncmp(arg[idx],"pair",3) == 0) {
226 flags |= PAIR_STYLES;
227 ++idx;
228 } else if (strncmp(arg[idx],"bond",3) == 0) {
229 flags |= BOND_STYLES;
230 ++idx;
231 } else if (strncmp(arg[idx],"angle",3) == 0) {
232 flags |= ANGLE_STYLES;
233 ++idx;
234 } else if (strncmp(arg[idx],"dihedral",3) == 0) {
235 flags |= DIHEDRAL_STYLES;
236 ++idx;
237 } else if (strncmp(arg[idx],"improper",3) == 0) {
238 flags |= IMPROPER_STYLES;
239 ++idx;
240 } else if (strncmp(arg[idx],"kspace",3) == 0) {
241 flags |= KSPACE_STYLES;
242 ++idx;
243 } else if (strncmp(arg[idx],"fix",3) == 0) {
244 flags |= FIX_STYLES;
245 ++idx;
246 } else if (strncmp(arg[idx],"compute",4) == 0) {
247 flags |= COMPUTE_STYLES;
248 ++idx;
249 } else if (strncmp(arg[idx],"region",3) == 0) {
250 flags |= REGION_STYLES;
251 ++idx;
252 } else if (strncmp(arg[idx],"dump",3) == 0) {
253 flags |= DUMP_STYLES;
254 ++idx;
255 } else if (strncmp(arg[idx],"command",4) == 0) {
256 flags |= COMMAND_STYLES;
257 ++idx;
258 } else {
259 flags |= STYLES;
260 }
261 } else {
262 flags |= STYLES;
263 ++idx;
264 }
265 } else {
266 error->warning(FLERR,"Ignoring unknown or incorrect info command flag");
267 ++idx;
268 }
269 }
270
271 if (out == nullptr) return;
272
273 fputs("\nInfo-Info-Info-Info-Info-Info-Info-Info-Info-Info-Info\n",out);
274 std::time_t now = std::time(nullptr);
275 fmt::print(out,"Printed on {:%a %b %d %H:%M:%S %Y}\n", fmt::localtime(now));
276
277 if (flags & CONFIG) {
278 fmt::print(out,"\nLAMMPS version: {} / {}\n",
279 lmp->version, lmp->num_ver);
280
281 if (lmp->has_git_info)
282 fmt::print(out,"Git info: {} / {} / {}\n",
283 lmp->git_branch, lmp->git_descriptor,lmp->git_commit);
284
285 fmt::print(out,"\nOS information: {}\n\n",get_os_info());
286
287 fmt::print(out,"sizeof(smallint): {}-bit\n"
288 "sizeof(imageint): {}-bit\n"
289 "sizeof(tagint): {}-bit\n"
290 "sizeof(bigint): {}-bit\n",
291 sizeof(smallint)*8, sizeof(imageint)*8,
292 sizeof(tagint)*8, sizeof(bigint)*8);
293
294 fmt::print(out,"\nCompiler: {} with {}\nC++ standard: {}\n",
295 get_compiler_info(),get_openmp_info(),get_cxx_info());
296
297 fputs("\nActive compile time flags:\n\n",out);
298 if (has_gzip_support()) fputs("-DLAMMPS_GZIP\n",out);
299 if (has_png_support()) fputs("-DLAMMPS_PNG\n",out);
300 if (has_jpeg_support()) fputs("-DLAMMPS_JPEG\n",out);
301 if (has_ffmpeg_support()) fputs("-DLAMMPS_FFMPEG\n",out);
302 if (has_exceptions()) fputs("-DLAMMPS_EXCEPTIONS\n",out);
303
304 #if defined(LAMMPS_BIGBIG)
305 fputs("-DLAMMPS_BIGBIG\n",out);
306 #elif defined(LAMMPS_SMALLBIG)
307 fputs("-DLAMMPS_SMALLBIG\n",out);
308 #else // defined(LAMMPS_SMALLSMALL)
309 fputs("-DLAMMPS_SMALLSMALL\n",out);
310 #endif
311
312 int ncword, ncline = 0;
313 fputs("\nInstalled packages:\n\n",out);
314 for (const char **pkg = lmp->installed_packages; *pkg != nullptr; ++pkg) {
315 ncword = strlen(*pkg);
316 if (ncline + ncword > 78) {
317 ncline = 0;
318 fputs("\n",out);
319 }
320 fmt::print(out,"{} ",*pkg);
321 ncline += ncword + 1;
322 }
323 fputs("\n",out);
324 }
325
326 if (flags & ACCELERATOR) {
327 fmt::print(out,"\nAccelerator configuration:\n\n{}",
328 get_accelerator_info());
329 if (Info::has_gpu_device())
330 fmt::print(out,"\nAvailable GPU devices:\n{}\n",get_gpu_device_info());
331 }
332
333 if (flags & MEMORY) {
334 double meminfo[3];
335
336 get_memory_info(meminfo);
337
338 fputs("\nMemory allocation information (MPI rank 0):\n\n",out);
339 fmt::print(out,"Total dynamically allocated memory: {:.4} Mbyte\n",
340 meminfo[0]);
341
342 #if defined(_WIN32)
343 fmt::print(out,"Non-shared memory use: {:.4} Mbyte\n",meminfo[1]);
344 fmt::print(out,"Maximum working set size: {:.4} Mbyte\n",meminfo[2]);
345 #else
346 #if defined(__linux__)
347 fmt::print(out,"Current reserved memory pool size: {:.4} Mbyte\n",
348 meminfo[1]);
349 #endif
350 fmt::print(out,"Maximum resident set size: {:.4} Mbyte\n",meminfo[2]);
351 #endif
352 }
353
354 if (flags & COMM) {
355 int major,minor;
356 std::string version = get_mpi_info(major,minor);
357
358 fmt::print(out,"\nCommunication information:\n"
359 "MPI library level: MPI v{}.{}\n"
360 "MPI version: {}\n",major,minor,version);
361
362 fmt::print(out,"Comm style = {}, Comm layout = {}\n"
363 "Communicate velocities for ghost atoms = {}\n",
364 commstyles[comm->style], commlayout[comm->layout],
365 comm->ghost_velocity ? "yes" : "no");
366
367 if (domain->box_exist) {
368 if (comm->mode == 0)
369 fmt::print(out,"Communication mode = single\n"
370 "Communication cutoff = {}\n",
371 comm->get_comm_cutoff());
372
373 if (comm->mode == 1) {
374 fputs("Communication mode = multi\n",out);
375 double cut;
376 for (int i=0; i < neighbor->ncollections; ++i) {
377 if (comm->cutusermulti) cut = comm->cutusermulti[i];
378 else cut = 0.0;
379 for (int j=0; j < neighbor->ncollections; ++j) {
380 cut = MAX(cut,sqrt(neighbor->cutcollectionsq[i][j]));
381 }
382
383 if (comm->cutusermulti) cut = MAX(cut,comm->cutusermulti[i]);
384 fmt::print(out,"Communication cutoff for collection {} = {:.8}\n", i, cut);
385 }
386 }
387
388 if (comm->mode == 2) {
389 fputs("Communication mode = multi/old\n",out);
390 double cut;
391 for (int i=1; i <= atom->ntypes && neighbor->cuttype; ++i) {
392 cut = neighbor->cuttype[i];
393 if (comm->cutusermultiold) cut = MAX(cut,comm->cutusermultiold[i]);
394 fmt::print(out,"Communication cutoff for type {} = {:.8}\n", i, cut);
395 }
396 }
397 }
398 fmt::print(out,"Nprocs = {}, Nthreads = {}\n",comm->nprocs,comm->nthreads);
399 if (domain->box_exist)
400 fmt::print(out,"Processor grid = {} x {} x {}\n",comm->procgrid[0],
401 comm->procgrid[1], comm->procgrid[2]);
402 }
403
404 if (flags & SYSTEM) {
405 fputs("\nSystem information:\n",out);
406 fmt::print(out,"Units = {}\n", update->unit_style);
407 fmt::print(out,"Atom style = {}\n", atom->atom_style);
408 fmt::print(out,"Atom map = {}\n", mapstyles[atom->map_style]);
409 if (atom->molecular != Atom::ATOMIC) {
410 const char *msg;
411 msg = (atom->molecular == Atom::TEMPLATE) ? "template" : "standard";
412 fmt::print(out,"Molecule type = {}\n",msg);
413 }
414 fmt::print(out,"Atoms = {:12}, types = {:8d}, style = {}\n",
415 atom->natoms, atom->ntypes, force->pair_style);
416
417 if (force->pair && utils::strmatch(force->pair_style,"^hybrid")) {
418 PairHybrid *hybrid = (PairHybrid *)force->pair;
419 fmt::print(out,"Hybrid sub-styles:");
420 for (int i=0; i < hybrid->nstyles; ++i)
421 fmt::print(out," {}", hybrid->keywords[i]);
422 fputc('\n',out);
423 }
424 if (atom->molecular != Atom::ATOMIC) {
425 const char *msg;
426 msg = force->bond_style ? force->bond_style : "none";
427 fmt::print(out,"Bonds = {:12}, types = {:8}, style = {}\n",
428 atom->nbonds, atom->nbondtypes, msg);
429
430 msg = force->angle_style ? force->angle_style : "none";
431 fmt::print(out,"Angles = {:12}, types = {:8}, style = {}\n",
432 atom->nangles, atom->nangletypes, msg);
433
434 msg = force->dihedral_style ? force->dihedral_style : "none";
435 fmt::print(out,"Dihedrals = {:12}, types = {:8}, style = {}\n",
436 atom->ndihedrals, atom->ndihedraltypes, msg);
437
438 msg = force->improper_style ? force->improper_style : "none";
439 fmt::print(out,"Impropers = {:12}, types = {:8}, style = {}\n",
440 atom->nimpropers, atom->nimpropertypes, msg);
441
442 const double * const special_lj = force->special_lj;
443 const double * const special_coul = force->special_coul;
444
445 fmt::print(out,"Special bond factors lj = {:<8} {:<8} {:<8}\n"
446 "Special bond factors coul = {:<8} {:<8} {:<8}\n",
447 special_lj[1],special_lj[2],special_lj[3],
448 special_coul[1],special_coul[2],special_coul[3]);
449 }
450
451 fmt::print(out,"Kspace style = {}\n",
452 force->kspace ? force->kspace_style : "none");
453
454 if (domain->box_exist) {
455 fmt::print(out,"\nDimensions = {}\n",domain->dimension);
456 fmt::print(out,"{} box = {:.8} x {:.8} x {:.8}\n",
457 domain->triclinic ? "Triclinic" : "Orthogonal",
458 domain->xprd, domain->yprd, domain->zprd);
459 fmt::print(out,"Boundaries = {},{} {},{} {},{}\n",
460 bstyles[domain->boundary[0][0]],bstyles[domain->boundary[0][1]],
461 bstyles[domain->boundary[1][0]],bstyles[domain->boundary[1][1]],
462 bstyles[domain->boundary[2][0]],bstyles[domain->boundary[2][1]]);
463 fmt::print(out,"xlo, xhi = {:.8}, {:.8}\n", domain->boxlo[0], domain->boxhi[0]);
464 fmt::print(out,"ylo, yhi = {:.8}, {:.8}\n", domain->boxlo[1], domain->boxhi[1]);
465 fmt::print(out,"zlo, zhi = {:.8}, {:.8}\n", domain->boxlo[2], domain->boxhi[2]);
466 if (domain->triclinic)
467 fmt::print(out,"Xy, xz, yz = {:.8}, {:.8}, {:.8}\n",
468 domain->xy, domain->xz, domain->yz);
469 } else {
470 fputs("\nBox has not yet been created\n",out);
471 }
472 }
473
474 if (domain->box_exist && (flags & COEFFS)) {
475 Pair *pair=force->pair;
476
477 fputs("\nCoeff status information:\n",out);
478 if (pair) {
479 fputs("\nPair Coeffs:\n",out);
480 for (int i=1; i <= atom->ntypes; ++i)
481 for (int j=i; j <= atom->ntypes; ++j) {
482 fmt::print(out,"{:6d} {:6d}:",i,j);
483 if (pair->allocated && pair->setflag[i][j]) fputs(" is set\n",out);
484 else fputs(" is not set\n",out);
485 }
486 }
487 if (force->bond) {
488 Bond *bond=force->bond;
489
490 if (bond) {
491 fputs("\nBond Coeffs:\n",out);
492 for (int i=1; i <= atom->nbondtypes; ++i) {
493 fmt::print(out,"{:6d}:",i);
494 if (bond->allocated && bond->setflag[i]) fputs(" is set\n",out);
495 else fputs (" is not set\n",out);
496 }
497 }
498 }
499 if (force->angle) {
500 Angle *angle=force->angle;
501
502 if (angle) {
503 fputs("\nAngle Coeffs:\n",out);
504 for (int i=1; i <= atom->nangletypes; ++i) {
505 fmt::print(out,"{:6d}:",i);
506 if (angle->allocated && angle->setflag[i]) fputs(" is set\n",out);
507 else fputs (" is not set\n",out);
508 }
509 }
510 }
511 if (force->dihedral) {
512 Dihedral *dihedral=force->dihedral;
513
514 if (dihedral) {
515 fputs("\nDihedral Coeffs:\n",out);
516 for (int i=1; i <= atom->ndihedraltypes; ++i) {
517 fmt::print(out,"{:6d}:",i);
518 if (dihedral->allocated && dihedral->setflag[i]) fputs(" is set\n",out);
519 else fputs (" is not set\n",out);
520 }
521 }
522 }
523 if (force->improper) {
524 Improper *b=force->improper;
525
526 if (b) {
527 fputs("\nImproper Coeffs:\n",out);
528 for (int i=1; i <= atom->nimpropertypes; ++i) {
529 fmt::print(out,"{:6d}:",i);
530 if (b->allocated && b->setflag[i]) fputs(" is set\n",out);
531 else fputs (" is not set\n",out);
532 }
533 }
534 }
535 }
536
537 if (flags & GROUPS) {
538 int ngroup = group->ngroup;
539 char **names = group->names;
540 int *dynamic = group->dynamic;
541 fputs("\nGroup information:\n",out);
542 for (int i=0; i < ngroup; ++i) {
543 if (names[i])
544 fmt::print(out,"Group[{:2d}]: {:16} ({})\n",
545 i, names[i], dynamic[i] ? "dynamic" : "static");
546 }
547 }
548
549 if (flags & REGIONS) {
550 int nreg = domain->nregion;
551 Region **regs = domain->regions;
552 fputs("\nRegion information:\n",out);
553 for (int i=0; i < nreg; ++i) {
554 fmt::print(out,"Region[{:3d}]: {:16} style = {:16} side = {}\n",
555 i, std::string(regs[i]->id)+',',
556 std::string(regs[i]->style)+',',
557 regs[i]->interior ? "in" : "out");
558 if (regs[i]->bboxflag)
559 fmt::print(out," Boundary: lo {:.8} {:.8} {:.8} hi {:.8} {:.8} {:.8}\n",
560 regs[i]->extent_xlo, regs[i]->extent_ylo,
561 regs[i]->extent_zlo, regs[i]->extent_xhi,
562 regs[i]->extent_yhi, regs[i]->extent_zhi);
563 else fputs(" No Boundary\n",out);
564 }
565 }
566
567 if (flags & COMPUTES) {
568 int ncompute = modify->ncompute;
569 Compute **compute = modify->compute;
570 char **names = group->names;
571 fputs("\nCompute information:\n",out);
572 for (int i=0; i < ncompute; ++i) {
573 fmt::print(out,"Compute[{:3d}]: {:16} style = {:16} group = {}\n",
574 i, std::string(compute[i]->id)+',',
575 std::string(compute[i]->style)+',',
576 names[compute[i]->igroup]);
577 }
578 }
579
580 if (flags & DUMPS) {
581 int ndump = output->ndump;
582 Dump **dump = output->dump;
583 int *nevery = output->every_dump; \
584 char **vnames = output->var_dump;
585 char **names = group->names;
586 fputs("\nDump information:\n",out);
587 for (int i=0; i < ndump; ++i) {
588 fmt::print(out,"Dump[{:3d}]: {:16} file = {:16} style = {:16} group = {:16} ",
589 i, std::string(dump[i]->id)+',',
590 std::string(dump[i]->filename)+',',
591 std::string(dump[i]->style)+',',
592 std::string(names[dump[i]->igroup])+',');
593 if (nevery[i]) {
594 fmt::print(out,"every = {}\n", nevery[i]);
595 } else {
596 fmt::print(out,"every = {}\n", vnames[i]);
597 }
598 }
599 }
600
601 if (flags & FIXES) {
602 int nfix = modify->nfix;
603 Fix **fix = modify->fix;
604 char **names = group->names;
605 fputs("\nFix information:\n",out);
606 for (int i=0; i < nfix; ++i) {
607 fmt::print(out, "Fix[{:3d}]: {:16} style = {:16} group = {}\n",
608 i,std::string(fix[i]->id)+',',
609 std::string(fix[i]->style)+',',
610 names[fix[i]->igroup]);
611 }
612 }
613
614 if (flags & VARIABLES) {
615 int nvar = input->variable->nvar;
616 int *style = input->variable->style;
617 char **names = input->variable->names;
618 char ***data = input->variable->data;
619 fputs("\nVariable information:\n",out);
620 for (int i=0; i < nvar; ++i) {
621 int ndata = 1;
622 fmt::print(out,"Variable[{:3d}]: {:16} style = {:16} def =",
623 i,std::string(names[i])+',',
624 std::string(varstyles[style[i]])+',');
625 if (style[i] == Variable::INTERNAL) {
626 fmt::print(out,"{:.8}\n",input->variable->dvalue[i]);
627 continue;
628 }
629 if ((style[i] != Variable::LOOP) && (style[i] != Variable::ULOOP))
630 ndata = input->variable->num[i];
631 for (int j=0; j < ndata; ++j)
632 if (data[i][j]) fmt::print(out," {}",data[i][j]);
633 fputs("\n",out);
634 }
635 }
636
637 if (flags & TIME) {
638 double wallclock = MPI_Wtime() - lmp->initclock;
639 double cpuclock = 0.0;
640
641 #if defined(_WIN32)
642 // from MSD docs.
643 FILETIME ct,et,kt,ut;
644 union { FILETIME ft; uint64_t ui; } cpu;
645 if (GetProcessTimes(GetCurrentProcess(),&ct,&et,&kt,&ut)) {
646 cpu.ft = ut;
647 cpuclock = cpu.ui * 0.0000001;
648 }
649 #else /* POSIX */
650 struct rusage ru;
651 if (getrusage(RUSAGE_SELF, &ru) == 0) {
652 cpuclock = (double) ru.ru_utime.tv_sec;
653 cpuclock += (double) ru.ru_utime.tv_usec * 0.000001;
654 }
655 #endif /* ! _WIN32 */
656
657 int cpuh,cpum,cpus,wallh,wallm,walls;
658 cpus = fmod(cpuclock,60.0);
659 cpuclock = (cpuclock - cpus) / 60.0;
660 cpum = fmod(cpuclock,60.0);
661 cpuh = (cpuclock - cpum) / 60.0;
662 walls = fmod(wallclock,60.0);
663 wallclock = (wallclock - walls) / 60.0;
664 wallm = fmod(wallclock,60.0);
665 wallh = (wallclock - wallm) / 60.0;
666 fmt::print(out,"\nTotal time information (MPI rank 0):\n"
667 " CPU time: {:4d}:{:02d}:{:02d}\n"
668 " Wall time: {:4d}:{:02d}:{:02d}\n",
669 cpuh,cpum,cpus,wallh,wallm,walls);
670 }
671
672 if (flags & STYLES) {
673 available_styles(out, flags);
674 }
675
676 fputs("\nInfo-Info-Info-Info-Info-Info-Info-Info-Info-Info-Info\n\n",out);
677
678 // close output file pointer if opened locally thus forcing a hard sync.
679 if ((out != screen) && (out != logfile))
680 fclose(out);
681 }
682
available_styles(FILE * out,int flags)683 void Info::available_styles(FILE * out, int flags)
684 {
685
686 fputs("\nStyles information:\n",out);
687
688 if (flags & ATOM_STYLES) atom_styles(out);
689 if (flags & INTEGRATE_STYLES) integrate_styles(out);
690 if (flags & MINIMIZE_STYLES) minimize_styles(out);
691 if (flags & PAIR_STYLES) pair_styles(out);
692 if (flags & BOND_STYLES) bond_styles(out);
693 if (flags & ANGLE_STYLES) angle_styles(out);
694 if (flags & DIHEDRAL_STYLES) dihedral_styles(out);
695 if (flags & IMPROPER_STYLES) improper_styles(out);
696 if (flags & KSPACE_STYLES) kspace_styles(out);
697 if (flags & FIX_STYLES) fix_styles(out);
698 if (flags & COMPUTE_STYLES) compute_styles(out);
699 if (flags & REGION_STYLES) region_styles(out);
700 if (flags & DUMP_STYLES) dump_styles(out);
701 if (flags & COMMAND_STYLES) command_styles(out);
702 }
703
atom_styles(FILE * out)704 void Info::atom_styles(FILE *out)
705 {
706 fputs("\nAtom styles:\n",out);
707 print_columns(out, atom->avec_map);
708 fputs("\n\n\n",out);
709 }
710
integrate_styles(FILE * out)711 void Info::integrate_styles(FILE *out)
712 {
713 fputs("\nIntegrate styles:\n",out);
714 print_columns(out, update->integrate_map);
715 fputs("\n\n\n",out);
716 }
717
minimize_styles(FILE * out)718 void Info::minimize_styles(FILE *out)
719 {
720 fputs("\nMinimize styles:\n",out);
721 print_columns(out, update->minimize_map);
722 fputs("\n\n\n",out);
723 }
724
pair_styles(FILE * out)725 void Info::pair_styles(FILE *out)
726 {
727 fputs("\nPair styles:\n",out);
728 print_columns(out, force->pair_map);
729 fputs("\n\n\n",out);
730 }
731
bond_styles(FILE * out)732 void Info::bond_styles(FILE *out)
733 {
734 fputs("\nBond styles:\n",out);
735 print_columns(out, force->bond_map);
736 fputs("\n\n\n",out);
737 }
738
angle_styles(FILE * out)739 void Info::angle_styles(FILE *out)
740 {
741 fputs("\nAngle styles:\n",out);
742 print_columns(out, force->angle_map);
743 fputs("\n\n\n",out);
744 }
745
dihedral_styles(FILE * out)746 void Info::dihedral_styles(FILE *out)
747 {
748 fputs("\nDihedral styles:\n",out);
749 print_columns(out, force->dihedral_map);
750 fputs("\n\n\n",out);
751 }
752
improper_styles(FILE * out)753 void Info::improper_styles(FILE *out)
754 {
755 fputs("\nImproper styles:\n",out);
756 print_columns(out, force->improper_map);
757 fputs("\n\n\n",out);
758 }
759
kspace_styles(FILE * out)760 void Info::kspace_styles(FILE *out)
761 {
762 fputs("\nKSpace styles:\n",out);
763 print_columns(out, force->kspace_map);
764 fputs("\n\n\n",out);
765 }
766
fix_styles(FILE * out)767 void Info::fix_styles(FILE *out)
768 {
769 fputs("\nFix styles:\n",out);
770 print_columns(out, modify->fix_map);
771 fputs("\n\n\n",out);
772 }
773
compute_styles(FILE * out)774 void Info::compute_styles(FILE *out)
775 {
776 fputs("\nCompute styles:\n",out);
777 print_columns(out, modify->compute_map);
778 fputs("\n\n\n",out);
779 }
780
region_styles(FILE * out)781 void Info::region_styles(FILE *out)
782 {
783 fputs("\nRegion styles:\n",out);
784 print_columns(out, domain->region_map);
785 fputs("\n\n\n",out);
786 }
787
dump_styles(FILE * out)788 void Info::dump_styles(FILE *out)
789 {
790 fputs("\nDump styles:\n",out);
791 print_columns(out,output->dump_map);
792 fputs("\n\n\n",out);
793 }
794
command_styles(FILE * out)795 void Info::command_styles(FILE *out)
796 {
797 fputs("\nCommand styles (add-on input script commands):\n",out);
798 print_columns(out, input->command_map);
799 fputs("\n\n\n",out);
800 }
801
802
803 /* ---------------------------------------------------------------------- */
804
805 // the is_active() function returns true if the selected style or name
806 // in the selected category is currently in use.
807
is_active(const char * category,const char * name)808 bool Info::is_active(const char *category, const char *name)
809 {
810 if ((category == nullptr) || (name == nullptr)) return false;
811 const char *style = "none";
812
813 if (strcmp(category,"package") == 0) {
814 if (strcmp(name,"gpu") == 0) {
815 return (modify->find_fix("package_gpu") >= 0) ? true : false;
816 } else if (strcmp(name,"intel") == 0) {
817 return (modify->find_fix("package_intel") >= 0) ? true : false;
818 } else if (strcmp(name,"kokkos") == 0) {
819 return (lmp->kokkos && lmp->kokkos->kokkos_exists) ? true : false;
820 } else if (strcmp(name,"omp") == 0) {
821 return (modify->find_fix("package_omp") >= 0) ? true : false;
822 } else error->all(FLERR,"Unknown name for info package category: {}", name);
823
824 } else if (strcmp(category,"newton") == 0) {
825 if (strcmp(name,"pair") == 0) return (force->newton_pair != 0);
826 else if (strcmp(name,"bond") == 0) return (force->newton_bond != 0);
827 else if (strcmp(name,"any") == 0) return (force->newton != 0);
828 else error->all(FLERR,"Unknown name for info newton category: {}", name);
829
830 } else if (strcmp(category,"pair") == 0) {
831 if (force->pair == nullptr) return false;
832 if (strcmp(name,"single") == 0) return (force->pair->single_enable != 0);
833 else if (strcmp(name,"respa") == 0) return (force->pair->respa_enable != 0);
834 else if (strcmp(name,"manybody") == 0) return (force->pair->manybody_flag != 0);
835 else if (strcmp(name,"tail") == 0) return (force->pair->tail_flag != 0);
836 else if (strcmp(name,"shift") == 0) return (force->pair->offset_flag != 0);
837 else error->all(FLERR,"Unknown name for info pair category: {}", name);
838
839 } else if (strcmp(category,"comm_style") == 0) {
840 style = commstyles[comm->style];
841 } else if (strcmp(category,"min_style") == 0) {
842 style = update->minimize_style;
843 } else if (strcmp(category,"run_style") == 0) {
844 style = update->integrate_style;
845 } else if (strcmp(category,"atom_style") == 0) {
846 style = atom->atom_style;
847 } else if (strcmp(category,"pair_style") == 0) {
848 style = force->pair_style;
849 } else if (strcmp(category,"bond_style") == 0) {
850 style = force->bond_style;
851 } else if (strcmp(category,"angle_style") == 0) {
852 style = force->angle_style;
853 } else if (strcmp(category,"dihedral_style") == 0) {
854 style = force->dihedral_style;
855 } else if (strcmp(category,"improper_style") == 0) {
856 style = force->improper_style;
857 } else if (strcmp(category,"kspace_style") == 0) {
858 style = force->kspace_style;
859 } else error->all(FLERR,"Unknown category for info is_active(): {}", category);
860
861 int match = 0;
862 if (strcmp(style,name) == 0) match = 1;
863
864 if (!match && lmp->suffix_enable) {
865 if (lmp->suffix) {
866 std::string name_w_suffix = name + std::string("/") + lmp->suffix;
867 if (name_w_suffix == style) match = 1;
868 }
869 if (!match && lmp->suffix2) {
870 std::string name_w_suffix = name + std::string("/") + lmp->suffix2;
871 if (name_w_suffix == style) match = 1;
872 }
873 }
874 return match ? true : false;
875 }
876
877 /* ---------------------------------------------------------------------- */
878
879 // the is_available() function returns true if the selected style
880 // or name in the selected category is available for use (but need
881 // not be currently active).
882
is_available(const char * category,const char * name)883 bool Info::is_available(const char *category, const char *name)
884 {
885 if ((category == nullptr) || (name == nullptr)) return false;
886
887 if (has_style(category, name)) {
888 return true;
889 } else if (strcmp(category,"feature") == 0) {
890 if (strcmp(name,"gzip") == 0) {
891 return has_gzip_support();
892 } else if (strcmp(name,"png") == 0) {
893 return has_png_support();
894 } else if (strcmp(name,"jpeg") == 0) {
895 return has_jpeg_support();
896 } else if (strcmp(name,"ffmpeg") == 0) {
897 return has_ffmpeg_support();
898 } else if (strcmp(name,"exceptions") == 0) {
899 return has_exceptions();
900 }
901 } else error->all(FLERR,"Unknown category for info is_available(): {}", category);
902
903 return false;
904 }
905
906 /* ---------------------------------------------------------------------- */
907
908 // the is_defined() function returns true if a particular ID of the
909 // selected category (e.g. fix ID, group ID, region ID etc.) has been
910 // defined and thus can be accessed. It does *NOT* check whether a
911 // particular ID has a particular style.
912
is_defined(const char * category,const char * name)913 bool Info::is_defined(const char *category, const char *name)
914 {
915 if ((category == nullptr) || (name == nullptr)) return false;
916
917 if (strcmp(category,"compute") == 0) {
918 int ncompute = modify->ncompute;
919 Compute **compute = modify->compute;
920 for (int i=0; i < ncompute; ++i) {
921 if (strcmp(compute[i]->id,name) == 0)
922 return true;
923 }
924 } else if (strcmp(category,"dump") == 0) {
925 int ndump = output->ndump;
926 Dump **dump = output->dump;
927 for (int i=0; i < ndump; ++i) {
928 if (strcmp(dump[i]->id,name) == 0)
929 return true;
930 }
931 } else if (strcmp(category,"fix") == 0) {
932 int nfix = modify->nfix;
933 Fix **fix = modify->fix;
934 for (int i=0; i < nfix; ++i) {
935 if (strcmp(fix[i]->id,name) == 0)
936 return true;
937 }
938 } else if (strcmp(category,"group") == 0) {
939 int ngroup = group->ngroup;
940 char **names = group->names;
941 for (int i=0; i < ngroup; ++i) {
942 if (strcmp(names[i],name) == 0)
943 return true;
944 }
945 } else if (strcmp(category,"region") == 0) {
946 int nreg = domain->nregion;
947 Region **regs = domain->regions;
948 for (int i=0; i < nreg; ++i) {
949 if (strcmp(regs[i]->id,name) == 0)
950 return true;
951 }
952 } else if (strcmp(category,"variable") == 0) {
953 int nvar = input->variable->nvar;
954 char **names = input->variable->names;
955
956 for (int i=0; i < nvar; ++i) {
957 if (strcmp(names[i],name) == 0)
958 return true;
959 }
960 } else error->all(FLERR,"Unknown category for info is_defined(): {}", category);
961
962 return false;
963 }
964
has_style(const std::string & category,const std::string & name)965 bool Info::has_style(const std::string &category, const std::string &name)
966 {
967 if (category == "atom") {
968 return find_style(lmp, atom->avec_map, name, false);
969 } else if (category == "integrate") {
970 return find_style(lmp, update->integrate_map, name, true);
971 } else if (category == "minimize") {
972 return find_style(lmp, update->minimize_map, name, true);
973 } else if (category == "pair") {
974 return find_style(lmp, force->pair_map, name, true);
975 } else if (category == "bond") {
976 return find_style(lmp, force->bond_map, name, true);
977 } else if (category == "angle") {
978 return find_style(lmp, force->angle_map, name, true);
979 } else if (category == "dihedral") {
980 return find_style(lmp, force->dihedral_map, name, true);
981 } else if (category == "improper") {
982 return find_style(lmp, force->improper_map, name, true);
983 } else if (category == "kspace") {
984 return find_style(lmp, force->kspace_map, name, true);
985 } else if (category == "fix") {
986 return find_style(lmp, modify->fix_map, name, true);
987 } else if (category == "compute") {
988 return find_style(lmp, modify->compute_map, name, true);
989 } else if (category == "region") {
990 return find_style(lmp, domain->region_map, name, false);
991 } else if (category == "dump") {
992 return find_style(lmp, output->dump_map, name, false);
993 } else if (category == "command") {
994 return find_style(lmp, input->command_map, name, false);
995 }
996 return false;
997 }
998
get_available_styles(const std::string & category)999 std::vector<std::string> Info::get_available_styles(const std::string &category)
1000 {
1001 if (category == "atom") {
1002 return get_style_names(atom->avec_map);
1003 } else if (category == "integrate") {
1004 return get_style_names(update->integrate_map);
1005 } else if (category == "minimize") {
1006 return get_style_names(update->minimize_map);
1007 } else if (category == "pair") {
1008 return get_style_names(force->pair_map);
1009 } else if (category == "bond") {
1010 return get_style_names(force->bond_map);
1011 } else if (category == "angle") {
1012 return get_style_names(force->angle_map);
1013 } else if (category == "dihedral") {
1014 return get_style_names(force->dihedral_map);
1015 } else if (category == "improper") {
1016 return get_style_names(force->improper_map);
1017 } else if (category == "kspace") {
1018 return get_style_names(force->kspace_map);
1019 } else if (category == "fix") {
1020 return get_style_names(modify->fix_map);
1021 } else if (category == "compute") {
1022 return get_style_names(modify->compute_map);
1023 } else if (category == "region") {
1024 return get_style_names(domain->region_map);
1025 } else if (category == "dump") {
1026 return get_style_names(output->dump_map);
1027 } else if (category == "command") {
1028 return get_style_names(input->command_map);
1029 }
1030 return std::vector<std::string>();
1031 }
1032
1033 template<typename ValueType>
get_style_names(std::map<std::string,ValueType> * styles)1034 static std::vector<std::string> get_style_names(std::map<std::string, ValueType> *styles)
1035 {
1036 std::vector<std::string> names;
1037
1038 names.reserve(styles->size());
1039 for (auto const& kv : *styles) {
1040 // skip "secret" styles
1041 if (isupper(kv.first[0])) continue;
1042 names.push_back(kv.first);
1043 }
1044
1045 return names;
1046 }
1047
1048 template<typename ValueType>
find_style(const LAMMPS * lmp,std::map<std::string,ValueType> * styles,const std::string & name,bool suffix_check)1049 static bool find_style(const LAMMPS *lmp, std::map<std::string, ValueType> *styles,
1050 const std::string &name, bool suffix_check)
1051 {
1052 if (styles->find(name) != styles->end()) {
1053 return true;
1054 }
1055
1056 if (suffix_check && lmp->suffix_enable) {
1057 if (lmp->suffix) {
1058 std::string name_w_suffix = name + "/" + lmp->suffix;
1059 if (find_style(lmp, styles, name_w_suffix, false)) {
1060 return true;
1061 }
1062 }
1063 if (lmp->suffix2) {
1064 std::string name_w_suffix = name + "/" + lmp->suffix2;
1065 if (find_style(lmp, styles, name_w_suffix, false)) {
1066 return true;
1067 }
1068 }
1069 }
1070 return false;
1071 }
1072
1073 template<typename ValueType>
print_columns(FILE * fp,std::map<std::string,ValueType> * styles)1074 static void print_columns(FILE *fp, std::map<std::string, ValueType> *styles)
1075 {
1076 if (styles->empty()) {
1077 fprintf(fp, "\nNone");
1078 return;
1079 }
1080
1081 // std::map keys are already sorted
1082 int pos = 80;
1083 for (typename std::map<std::string, ValueType>::iterator it = styles->begin(); it != styles->end(); ++it) {
1084 const std::string &style_name = it->first;
1085
1086 // skip "secret" styles
1087 if (isupper(style_name[0])) continue;
1088
1089 int len = style_name.length();
1090 if (pos + len > 80) {
1091 fprintf(fp,"\n");
1092 pos = 0;
1093 }
1094
1095 if (len < 16) {
1096 fprintf(fp,"%-16s", style_name.c_str());
1097 pos += 16;
1098 } else if (len < 32) {
1099 fprintf(fp,"%-32s", style_name.c_str());
1100 pos += 32;
1101 } else if (len < 48) {
1102 fprintf(fp,"%-48s", style_name.c_str());
1103 pos += 48;
1104 } else if (len < 64) {
1105 fprintf(fp,"%-64s", style_name.c_str());
1106 pos += 64;
1107 } else {
1108 fprintf(fp,"%-80s", style_name.c_str());
1109 pos += 80;
1110 }
1111 }
1112 }
1113
has_gzip_support()1114 bool Info::has_gzip_support() {
1115 #ifdef LAMMPS_GZIP
1116 return true;
1117 #else
1118 return false;
1119 #endif
1120 }
1121
has_png_support()1122 bool Info::has_png_support() {
1123 #ifdef LAMMPS_PNG
1124 return true;
1125 #else
1126 return false;
1127 #endif
1128 }
1129
has_jpeg_support()1130 bool Info::has_jpeg_support() {
1131 #ifdef LAMMPS_JPEG
1132 return true;
1133 #else
1134 return false;
1135 #endif
1136 }
1137
has_ffmpeg_support()1138 bool Info::has_ffmpeg_support() {
1139 #ifdef LAMMPS_FFMPEG
1140 return true;
1141 #else
1142 return false;
1143 #endif
1144 }
1145
has_exceptions()1146 bool Info::has_exceptions() {
1147 #ifdef LAMMPS_EXCEPTIONS
1148 return true;
1149 #else
1150 return false;
1151 #endif
1152 }
1153
has_package(const std::string & package_name)1154 bool Info::has_package(const std::string &package_name) {
1155 for (int i = 0; LAMMPS::installed_packages[i] != nullptr; ++i) {
1156 if (package_name == LAMMPS::installed_packages[i]) {
1157 return true;
1158 }
1159 }
1160 return false;
1161 }
1162
1163 #if defined(LMP_GPU)
1164 extern bool lmp_gpu_config(const std::string &, const std::string &);
1165 extern bool lmp_has_gpu_device();
1166 extern std::string lmp_gpu_device_info();
1167
has_gpu_device()1168 bool Info::has_gpu_device()
1169 {
1170 return lmp_has_gpu_device();
1171 }
1172
get_gpu_device_info()1173 std::string Info::get_gpu_device_info()
1174 {
1175 return lmp_gpu_device_info();
1176 }
1177 #else
has_gpu_device()1178 bool Info::has_gpu_device()
1179 {
1180 return false;
1181 }
get_gpu_device_info()1182 std::string Info::get_gpu_device_info()
1183 {
1184 return "";
1185 }
1186 #endif
1187
1188 #if defined(LMP_KOKKOS)
1189 #include "Kokkos_Macros.hpp"
1190 #endif
1191
has_accelerator_feature(const std::string & package,const std::string & category,const std::string & setting)1192 bool Info::has_accelerator_feature(const std::string &package,
1193 const std::string &category,
1194 const std::string &setting)
1195 {
1196 #if defined(LMP_KOKKOS)
1197 if (package == "KOKKOS") {
1198 if (category == "precision") {
1199 if (setting == "double") return true;
1200 else return false;
1201 }
1202 if (category == "api") {
1203 #if defined(KOKKOS_ENABLE_OPENMP)
1204 if (setting == "openmp") return true;
1205 #endif
1206 #if defined(KOKKOS_ENABLE_SERIAL)
1207 if (setting == "serial") return true;
1208 #endif
1209 #if defined(KOKKOS_ENABLE_THREADS)
1210 if (setting == "pthreads") return true;
1211 #endif
1212 #if defined(KOKKOS_ENABLE_CUDA)
1213 if (setting == "cuda") return true;
1214 #endif
1215 #if defined(KOKKOS_ENABLE_HIP)
1216 if (setting == "hip") return true;
1217 #endif
1218 #if defined(KOKKOS_ENABLE_SYCL)
1219 if (setting == "sycl") return true;
1220 #endif
1221 return false;
1222 }
1223 }
1224 #endif
1225 #if defined(LMP_GPU)
1226 if (package == "GPU") {
1227 return lmp_gpu_config(category,setting);
1228 }
1229 #endif
1230 #if defined(LMP_OPENMP)
1231 if (package == "OPENMP") {
1232 if (category == "precision") {
1233 if (setting == "double") return true;
1234 else return false;
1235 }
1236 if (category == "api") {
1237 #if defined(_OPENMP)
1238 if (setting == "openmp") return true;
1239 #else
1240 if (setting == "serial") return true;
1241 #endif
1242 return false;
1243 }
1244 }
1245 #endif
1246 #if defined(LMP_INTEL)
1247 if (package == "INTEL") {
1248 if (category == "precision") {
1249 if (setting == "double") return true;
1250 else if (setting == "mixed") return true;
1251 else if (setting == "single")return true;
1252 else return false;
1253 }
1254 if (category == "api") {
1255 #if defined(LMP_INTEL_OFFLOAD)
1256 if (setting == "phi") return true;
1257 #elif defined(_OPENMP)
1258 if (setting == "openmp") return true;
1259 #else
1260 if (setting == "serial") return true;
1261 #endif
1262 return false;
1263 }
1264 }
1265 #endif
1266 return false;
1267 }
1268
1269 /* ---------------------------------------------------------------------- */
1270 #define _INFOBUF_SIZE 256
1271
get_os_info()1272 std::string Info::get_os_info()
1273 {
1274 std::string buf;
1275
1276 #if defined(_WIN32)
1277 DWORD fullversion,majorv,minorv,buildv=0;
1278
1279 fullversion = GetVersion();
1280 majorv = (DWORD) (LOBYTE(LOWORD(fullversion)));
1281 minorv = (DWORD) (HIBYTE(LOWORD(fullversion)));
1282 if (fullversion < 0x80000000)
1283 buildv = (DWORD) (HIWORD(fullversion));
1284
1285 buf = fmt::format("Windows {}.{} ({}) on ",majorv,minorv,buildv);
1286
1287 SYSTEM_INFO si;
1288 GetSystemInfo(&si);
1289
1290 switch (si.wProcessorArchitecture) {
1291 case PROCESSOR_ARCHITECTURE_AMD64:
1292 buf += "x86_64";
1293 break;
1294 case PROCESSOR_ARCHITECTURE_ARM:
1295 buf += "arm";
1296 break;
1297 case PROCESSOR_ARCHITECTURE_IA64:
1298 buf += "ia64";
1299 break;
1300 case PROCESSOR_ARCHITECTURE_INTEL:
1301 buf += "i386";
1302 break;
1303 default:
1304 buf += "(unknown)";
1305 }
1306 #else
1307 struct utsname ut;
1308 uname(&ut);
1309
1310 // try to get OS distribution name, if available
1311 std::string distro = ut.sysname;
1312 if (utils::file_is_readable("/etc/os-release")) {
1313 try {
1314 TextFileReader reader("/etc/os-release","");
1315 while (1) {
1316 auto words = reader.next_values(0,"=");
1317 if ((words.count() > 1) && (words.next_string() == "PRETTY_NAME")) {
1318 distro += " " + utils::trim(words.next_string());
1319 break;
1320 }
1321 }
1322 } catch (std::exception &e) {
1323 ; // EOF but keyword not found
1324 }
1325 }
1326
1327 buf = fmt::format("{} {} on {}", distro, ut.release, ut.machine);
1328 #endif
1329 return buf;
1330 }
1331
get_compiler_info()1332 std::string Info::get_compiler_info()
1333 {
1334 std::string buf;
1335 #if defined(__INTEL_LLVM_COMPILER)
1336 constexpr double version = static_cast<double>(__INTEL_LLVM_COMPILER)*0.01;
1337 buf = fmt::format("Intel LLVM C++ {:.1f} / {}", version, __VERSION__);
1338 #elif defined(__ibmxl__)
1339 buf = fmt::format("IBM XL C/C++ (Clang) {}.{}.{}",
1340 __ibmxl_version__, __ibmxl_release__, __ibmxl_modification__);
1341 #elif defined(__clang__)
1342 buf = fmt::format("Clang C++ {}", __VERSION__);
1343 #elif defined(__PGI)
1344 buf = fmt::format("PGI C++ {}.{}",__PGIC__, __PGIC_MINOR__);
1345 #elif defined(__INTEL_COMPILER)
1346 double version = static_cast<double>(__INTEL_COMPILER)*0.01;
1347 buf = fmt::format("Intel Classic C++ {:.2f}.{} / {}", version,
1348 __INTEL_COMPILER_UPDATE, __VERSION__);
1349 #elif defined(__MINGW64__)
1350 buf = fmt::format("MinGW-w64 64bit {}.{} / GNU C++ {}", __MINGW64_VERSION_MAJOR,
1351 __MINGW64_VERSION_MINOR, __VERSION__);
1352 #elif defined(__MINGW32__)
1353 buf = fmt::format("MinGW-w64 32bit {}.{} / GNU C++ {}", __MINGW32_MAJOR_VERSION,
1354 __MINGW32_MINOR_VERSION, __VERSION__);
1355 #elif defined(__GNUC__)
1356 buf = fmt::format("GNU C++ {}", __VERSION__);
1357 #elif defined(_MSC_VER) && (_MSC_VER > 1920) && (_MSC_VER < 2000)
1358 constexpr int major = _MSC_VER / 100;
1359 constexpr int minor = _MSC_VER - major *100;
1360 buf = fmt::format("Microsoft Visual Studio 20{}, C/C++ {}.{}", major, major-5, minor);
1361 #else
1362 buf = "(Unknown)";
1363 #endif
1364 return buf;
1365 }
1366
get_openmp_info()1367 std::string Info::get_openmp_info()
1368 {
1369
1370 #if !defined(_OPENMP)
1371 return "OpenMP not enabled";
1372 #else
1373
1374 // Supported OpenMP version corresponds to the release date of the
1375 // specifications as posted at https://www.openmp.org/specifications/
1376
1377 #if _OPENMP > 202011
1378 return "OpenMP newer than version 5.1";
1379 #elif _OPENMP == 202011
1380 return "OpenMP 5.1";
1381 #elif _OPENMP == 201811
1382 return "OpenMP 5.0";
1383 #elif _OPENMP == 201611
1384 return "OpenMP 5.0 preview 1";
1385 #elif _OPENMP == 201511
1386 return "OpenMP 4.5";
1387 #elif _OPENMP == 201307
1388 return "OpenMP 4.0";
1389 #elif _OPENMP == 201107
1390 return "OpenMP 3.1";
1391 #elif _OPENMP == 200805
1392 return "OpenMP 3.0";
1393 #elif _OPENMP == 200505
1394 return "OpenMP 2.5";
1395 #elif _OPENMP == 200203
1396 return "OpenMP 2.0";
1397 #else
1398 return "unknown OpenMP version";
1399 #endif
1400
1401 #endif
1402 }
1403
get_mpi_vendor()1404 std::string Info::get_mpi_vendor() {
1405 #if defined(MPI_STUBS)
1406 return "MPI STUBS";
1407 #elif defined(OPEN_MPI)
1408 return "Open MPI";
1409 #elif defined(MPICH_NAME)
1410 return "MPICH";
1411 #elif defined(I_MPI_VERSION)
1412 return "Intel MPI";
1413 #elif defined(PLATFORM_MPI)
1414 return "Platform MPI";
1415 #elif defined(HP_MPI)
1416 return "HP MPI";
1417 #elif defined(MSMPI_VER)
1418 return "Microsoft MPI";
1419 #else
1420 return "Unknown MPI implementation";
1421 #endif
1422 }
1423
get_mpi_info(int & major,int & minor)1424 std::string Info::get_mpi_info(int &major, int &minor)
1425 {
1426 int len;
1427 #if (defined(MPI_VERSION) && (MPI_VERSION > 2)) || defined(MPI_STUBS)
1428 static char version[MPI_MAX_LIBRARY_VERSION_STRING];
1429 MPI_Get_library_version(version,&len);
1430 #else
1431 static char version[32];
1432 strcpy(version,get_mpi_vendor().c_str());
1433 len = strlen(version);
1434 #endif
1435
1436 MPI_Get_version(&major,&minor);
1437 if (len > 80) {
1438 char *ptr = strchr(version+80,'\n');
1439 if (ptr) *ptr = '\0';
1440 }
1441 return std::string(version);
1442 }
1443
get_cxx_info()1444 std::string Info::get_cxx_info()
1445 {
1446 #if __cplusplus > 202002L
1447 return "newer than C++20";
1448 #elif __cplusplus == 202002L
1449 return "C++20";
1450 #elif __cplusplus == 201703L
1451 return "C++17";
1452 #elif __cplusplus == 201402L
1453 return "C++14";
1454 #elif __cplusplus == 201103L
1455 return "C++11";
1456 #elif __cplusplus == 199711L
1457 return "C++98";
1458 #else
1459 return "unknown";
1460 #endif
1461 }
1462
get_accelerator_info(const std::string & package)1463 std::string Info::get_accelerator_info(const std::string &package)
1464 {
1465 std::string mesg("");
1466 if ((package.empty() || (package == "GPU")) && has_package("GPU")) {
1467 mesg += "GPU package API:";
1468 if (has_accelerator_feature("GPU","api","cuda")) mesg += " CUDA";
1469 if (has_accelerator_feature("GPU","api","hip")) mesg += " HIP";
1470 if (has_accelerator_feature("GPU","api","opencl")) mesg += " OpenCL";
1471 mesg += "\nGPU package precision:";
1472 if (has_accelerator_feature("GPU","precision","single")) mesg += " single";
1473 if (has_accelerator_feature("GPU","precision","mixed")) mesg += " mixed";
1474 if (has_accelerator_feature("GPU","precision","double")) mesg += " double";
1475 mesg += "\n";
1476 }
1477 if ((package.empty() || (package == "KOKKOS")) && has_package("KOKKOS")) {
1478 mesg += "KOKKOS package API:";
1479 if (has_accelerator_feature("KOKKOS","api","cuda")) mesg += " CUDA";
1480 if (has_accelerator_feature("KOKKOS","api","hip")) mesg += " HIP";
1481 if (has_accelerator_feature("KOKKOS","api","sycl")) mesg += " SYCL";
1482 if (has_accelerator_feature("KOKKOS","api","openmp")) mesg += " OpenMP";
1483 if (has_accelerator_feature("KOKKOS","api","serial")) mesg += " Serial";
1484 if (has_accelerator_feature("KOKKOS","api","pthreads")) mesg += " Pthreads";
1485 mesg += "\nKOKKOS package precision:";
1486 if (has_accelerator_feature("KOKKOS","precision","single")) mesg += " single";
1487 if (has_accelerator_feature("KOKKOS","precision","mixed")) mesg += " mixed";
1488 if (has_accelerator_feature("KOKKOS","precision","double")) mesg += " double";
1489 mesg += "\n";
1490 }
1491 if ((package.empty() || (package == "OPENMP")) && has_package("OPENMP")) {
1492 mesg += "OPENMP package API:";
1493 if (has_accelerator_feature("OPENMP","api","openmp")) mesg += " OpenMP";
1494 if (has_accelerator_feature("OPENMP","api","serial")) mesg += " Serial";
1495 mesg += "\nOPENMP package precision:";
1496 if (has_accelerator_feature("OPENMP","precision","single")) mesg += " single";
1497 if (has_accelerator_feature("OPENMP","precision","mixed")) mesg += " mixed";
1498 if (has_accelerator_feature("OPENMP","precision","double")) mesg += " double";
1499 mesg += "\n";
1500 }
1501 if ((package.empty() || (package == "INTEL")) && has_package("INTEL")) {
1502 mesg += "INTEL package API:";
1503 if (has_accelerator_feature("INTEL","api","phi")) mesg += " Phi";
1504 if (has_accelerator_feature("INTEL","api","openmp")) mesg += " OpenMP";
1505 mesg += "\nINTEL package precision:";
1506 if (has_accelerator_feature("INTEL","precision","single")) mesg += " single";
1507 if (has_accelerator_feature("INTEL","precision","mixed")) mesg += " mixed";
1508 if (has_accelerator_feature("INTEL","precision","double")) mesg += " double";
1509 mesg += "\n";
1510 }
1511 return mesg;
1512 }
1513
1514 /* ---------------------------------------------------------------------- */
1515
get_memory_info(double * meminfo)1516 void Info::get_memory_info(double *meminfo)
1517 {
1518 double bytes = 0;
1519 bytes += atom->memory_usage();
1520 bytes += neighbor->memory_usage();
1521 bytes += comm->memory_usage();
1522 bytes += update->memory_usage();
1523 bytes += force->memory_usage();
1524 bytes += modify->memory_usage();
1525 for (int i = 0; i < output->ndump; i++)
1526 bytes += output->dump[i]->memory_usage();
1527 meminfo[0] = bytes/1024.0/1024.0;
1528 meminfo[1] = 0;
1529 meminfo[2] = 0;
1530
1531 #if defined(_WIN32)
1532 HANDLE phandle = GetCurrentProcess();
1533 PROCESS_MEMORY_COUNTERS_EX pmc;
1534 GetProcessMemoryInfo(phandle,(PROCESS_MEMORY_COUNTERS *)&pmc,sizeof(pmc));
1535 meminfo[1] = (double)pmc.PrivateUsage/1048576.0;
1536 meminfo[2] = (double)pmc.PeakWorkingSetSize/1048576.0;
1537 #else
1538 #if defined(__linux__)
1539 #if defined(__GLIBC__) && __GLIBC_PREREQ(2, 33)
1540 struct mallinfo2 mi;
1541 mi = mallinfo2();
1542 #else
1543 struct mallinfo mi;
1544 mi = mallinfo();
1545 #endif
1546 meminfo[1] = (double)mi.uordblks/1048576.0+(double)mi.hblkhd/1048576.0;
1547 #endif
1548 struct rusage ru;
1549 if (getrusage(RUSAGE_SELF, &ru) == 0)
1550 meminfo[2] = (double)ru.ru_maxrss/1024.0;
1551 #endif
1552 }
1553
1554 /* ---------------------------------------------------------------------- */
1555
get_variable_names(int & num)1556 char **Info::get_variable_names(int &num) {
1557 num = input->variable->nvar;
1558 return input->variable->names;
1559 }
1560