PageRenderTime 50ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/skeletons/minimd_full/ljs.cpp

https://bitbucket.org/ghendry/sstmacro
C++ | 460 lines | 343 code | 87 blank | 30 comment | 124 complexity | 10903fce117d8a780135cfc8f14fbdea MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-3.0
  1. /* ----------------------------------------------------------------------
  2. miniMD is a simple, parallel molecular dynamics (MD) code. miniMD is
  3. an MD microapplication in the Mantevo project at Sandia National
  4. Laboratories ( http://www.mantevo.org ). The primary
  5. authors of miniMD are Steve Plimpton (sjplimp@sandia.gov) , Paul Crozier
  6. (pscrozi@sandia.gov) and Christian Trott (crtrott@sandia.gov).
  7. Copyright (2008) 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 library is free software; you
  10. can redistribute it and/or modify it under the terms of the GNU Lesser
  11. General Public License as published by the Free Software Foundation;
  12. either version 3 of the License, or (at your option) any later
  13. version.
  14. This library is distributed in the hope that it will be useful, but
  15. WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. Lesser General Public License for more details.
  18. You should have received a copy of the GNU Lesser General Public
  19. License along with this software; if not, write to the Free Software
  20. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  21. USA. See also: http://www.gnu.org/licenses/lgpl.txt .
  22. For questions, contact Paul S. Crozier (pscrozi@sandia.gov) or
  23. Christian Trott (crtrott@sandia.gov).
  24. Please read the accompanying README and LICENSE files.
  25. ---------------------------------------------------------------------- */
  26. #include "stdio.h"
  27. #include "stdlib.h"
  28. #ifdef USING_SSTMAC
  29. #include <sstmac/sstmpi.h>
  30. #else
  31. #include "mpi.h"
  32. #endif
  33. #if defined(_USE_EIGER_MODEL) || defined(_USE_EIGER) || \
  34. defined(_USE_CSV) || defined(_USE_FAKEEIGER)
  35. #include "lwperf.h"
  36. #endif
  37. #include "variant.h"
  38. #include "ljs.h"
  39. #include "atom.h"
  40. #include "neighbor.h"
  41. #include "integrate.h"
  42. #include "thermo.h"
  43. #include "comm.h"
  44. #include "timer.h"
  45. #include "threadData.h"
  46. #include "string.h"
  47. #include "openmp.h"
  48. #include "force_eam.h"
  49. #include "force.h"
  50. #include "force_lj.h"
  51. #define MAXLINE 256
  52. int input(In &, char*);
  53. void create_box(Atom &, int, int, int, double);
  54. int create_atoms(Atom &, int, int, int, double);
  55. void create_velocity(double, Atom &, Thermo &);
  56. void output(In &, Atom &, Force*, Neighbor &, Comm &,
  57. Thermo &, Integrate &, Timer &, int);
  58. int read_lammps_data(Atom &atom, Comm &comm, Neighbor &neighbor, Integrate &integrate, Thermo &thermo, char* file, int units);
  59. #ifdef USING_SSTMAC
  60. int user_skeleton_main(int argc, char **argv)
  61. #else
  62. int main(int argc, char** argv)
  63. #endif
  64. {
  65. In in;
  66. in.datafile = NULL;
  67. int me = 0; //local MPI rank
  68. int nprocs = 1; //number of MPI ranks
  69. int num_threads = 1; //number of OpenMP threads
  70. int num_steps = -1; //number of timesteps (if -1 use value from lj.in)
  71. int system_size = -1; //size of the system (if -1 use value from lj.in)
  72. int check_safeexchange = 0; //if 1 complain if atom moves further than 1 subdomain length between exchanges
  73. int do_safeexchange = 0; //if 1 use safe exchange mode [allows exchange over multiple subdomains]
  74. int use_sse = 0; //setting for SSE variant of miniMD only
  75. int screen_yaml = 0; //print yaml output to screen also
  76. int yaml_output = 0; //print yaml output
  77. int halfneigh = 1; //1: use half neighborlist; 0: use full neighborlist; -1: use original miniMD version half neighborlist force
  78. int numa = 1;
  79. int device = 0;
  80. int neighbor_size = -1;
  81. char* input_file = NULL;
  82. int ghost_newton = 1;
  83. for(int i = 0; i < argc; i++) {
  84. if((strcmp(argv[i], "-i") == 0) || (strcmp(argv[i], "--input_file") == 0)) {
  85. input_file = argv[++i];
  86. continue;
  87. }
  88. }
  89. MPI_Init(&argc, &argv);
  90. MPI_Comm_rank(MPI_COMM_WORLD, &me);
  91. MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
  92. #if defined(_USE_EIGER_MODEL) || defined(_USE_EIGER) || \
  93. defined(_USE_CSV) || defined(_USE_FAKEEIGER)
  94. PERFDECL(PERF::init();)
  95. PERFDECL(PERF::mpiArgs(me,nprocs);)
  96. PERFDECL(PERF::stringOptions("harrenhal","gcc","minimd",LWP_DBNAME,"",".log");)
  97. #endif
  98. int error = 0;
  99. if(input_file == NULL)
  100. error = input(in, "in.lj.miniMD");
  101. else
  102. error = input(in, input_file);
  103. if(error) {
  104. MPI_Finalize();
  105. exit(0);
  106. }
  107. for(int i = 0; i < argc; i++) {
  108. if((strcmp(argv[i], "-t") == 0) || (strcmp(argv[i], "--num_threads") == 0)) {
  109. num_threads = atoi(argv[++i]);
  110. continue;
  111. }
  112. if((strcmp(argv[i], "--numa") == 0)) {
  113. numa = atoi(argv[++i]);
  114. continue;
  115. }
  116. if((strcmp(argv[i], "-n") == 0) || (strcmp(argv[i], "--nsteps") == 0)) {
  117. num_steps = atoi(argv[++i]);
  118. continue;
  119. }
  120. if((strcmp(argv[i], "-s") == 0) || (strcmp(argv[i], "--size") == 0)) {
  121. system_size = atoi(argv[++i]);
  122. continue;
  123. }
  124. if((strcmp(argv[i], "-b") == 0) || (strcmp(argv[i], "--neigh_bins") == 0)) {
  125. neighbor_size = atoi(argv[++i]);
  126. continue;
  127. }
  128. if((strcmp(argv[i], "--half_neigh") == 0)) {
  129. halfneigh = atoi(argv[++i]);
  130. continue;
  131. }
  132. if((strcmp(argv[i], "-sse") == 0)) {
  133. use_sse = atoi(argv[++i]);
  134. continue;
  135. }
  136. if((strcmp(argv[i], "--check_exchange") == 0)) {
  137. check_safeexchange = 1;
  138. continue;
  139. }
  140. if((strcmp(argv[i], "-o") == 0) || (strcmp(argv[i], "--yaml_output") == 0)) {
  141. yaml_output = atoi(argv[++i]);
  142. continue;
  143. }
  144. if((strcmp(argv[i], "--yaml_screen") == 0)) {
  145. screen_yaml = 1;
  146. continue;
  147. }
  148. if((strcmp(argv[i], "-f") == 0) || (strcmp(argv[i], "--data_file") == 0)) {
  149. if(in.datafile == NULL) in.datafile = new char[1000];
  150. strcpy(in.datafile, argv[++i]);
  151. continue;
  152. }
  153. if((strcmp(argv[i], "-u") == 0) || (strcmp(argv[i], "--units") == 0)) {
  154. in.units = strcmp(argv[++i], "metal") == 0 ? 1 : 0;
  155. continue;
  156. }
  157. if((strcmp(argv[i], "-p") == 0) || (strcmp(argv[i], "--force") == 0)) {
  158. in.forcetype = strcmp(argv[++i], "eam") == 0 ? FORCEEAM : FORCELJ;
  159. continue;
  160. }
  161. if((strcmp(argv[i], "-gn") == 0) || (strcmp(argv[i], "--ghost_newton") == 0)) {
  162. ghost_newton = atoi(argv[++i]);
  163. continue;
  164. }
  165. if((strcmp(argv[i], "-h") == 0) || (strcmp(argv[i], "--help") == 0)) {
  166. printf("\n-----------------------------------------------------------------------------------------------------------\n");
  167. printf("-------------" VARIANT_STRING "--------------------\n");
  168. printf("-------------------------------------------------------------------------------------------------------------\n\n");
  169. printf("miniMD is a simple, parallel molecular dynamics (MD) code,\n"
  170. "which is part of the Mantevo project at Sandia National\n"
  171. "Laboratories ( http://www.mantevo.org ).\n"
  172. "The original authors of miniMD are Steve Plimpton (sjplimp@sandia.gov) ,\n"
  173. "Paul Crozier (pscrozi@sandia.gov) with current\n"
  174. "versions written by Christian Trott (crtrott@sandia.gov).\n\n");
  175. printf("Commandline Options:\n");
  176. printf("\n Execution configuration:\n");
  177. printf("\t-t / --num_threads <threads>: set number of threads per MPI rank (default 1)\n");
  178. printf("\t--numa <regions>: set number of numa regions used per MPI rank (default 1)\n"
  179. "\t <threads> must be divisable by <numa>\n");
  180. printf("\t--half_neigh <int>: use half neighborlists (default 1)\n"
  181. "\t 0: full neighborlist\n"
  182. "\t 1: half neighborlist\n"
  183. "\t -1: original miniMD half neighborlist force (not OpenMP safe)\n");
  184. printf("\t-d / --device <int>: choose device to use (only applicable for GPU execution)\n");
  185. printf("\t-dm / --device_map: map devices to MPI ranks\n");
  186. printf("\t-ng / --num_gpus <int>: give number of GPUs per Node (used in conjuction with -dm\n"
  187. "\t to determine device id: 'id=mpi_rank%%ng' (default 2)\n");
  188. printf("\t--skip_gpu <int>: skip the specified gpu when assigning devices to MPI ranks\n"
  189. "\t used in conjunction with -dm (but must come first in arg list)\n");
  190. printf("\t-sse <sse_version>: use explicit sse intrinsics (use miniMD-SSE variant)\n");
  191. printf("\t-gn / --ghost_newton <int>: set usage of newtons third law for ghost atoms\n"
  192. "\t (only applicable with half neighborlists)\n");
  193. printf("\n Simulation setup:\n");
  194. printf("\t-i / --input_file <string>: set input file to be used (default: in.lj.miniMD)\n");
  195. printf("\t-n / --nsteps <int>: set number of timesteps for simulation\n");
  196. printf("\t-s / --size <int>: set linear dimension of systembox\n");
  197. printf("\t-b / --neigh_bins <int>: set linear dimension of neighbor bin grid\n");
  198. printf("\t-u / --units <string>: set units (lj or metal), see LAMMPS documentation\n");
  199. printf("\t-p / --force <string>: set interaction model (lj or eam)\n");
  200. printf("\t-f / --data_file <string>: read configuration from LAMMPS data file\n");
  201. printf("\n Miscelaneous:\n");
  202. printf("\t--check_exchange: check whether atoms moved further than subdomain width\n");
  203. printf("\t--safe_exchange: perform exchange communication with all MPI processes\n"
  204. "\t within rcut_neighbor (outer force cutoff)\n");
  205. printf("\t-o / --yaml_output <int>: level of yaml output (default 1)\n");
  206. printf("\t--yaml_screen: write yaml output also to screen\n");
  207. printf("\t-h / --help: display this help message\n\n");
  208. printf("---------------------------------------------------------\n\n");
  209. exit(0);
  210. }
  211. }
  212. Atom atom;
  213. Neighbor neighbor;
  214. Integrate integrate;
  215. Thermo thermo;
  216. Comm comm;
  217. Timer timer;
  218. ThreadData threads;
  219. Force* force;
  220. if(in.forcetype == FORCEEAM) {
  221. force = (Force*) new ForceEAM();
  222. if(ghost_newton == 1) {
  223. if(me == 0)
  224. printf("# EAM currently requires '--ghost_newton 0'; Changing setting now.\n");
  225. ghost_newton = 0;
  226. }
  227. }
  228. if(in.forcetype == FORCELJ) force = (Force*) new ForceLJ();
  229. threads.mpi_me = me;
  230. threads.mpi_num_threads = nprocs;
  231. threads.omp_me = 0;
  232. threads.omp_num_threads = num_threads;
  233. atom.threads = &threads;
  234. comm.threads = &threads;
  235. force->threads = &threads;
  236. integrate.threads = &threads;
  237. neighbor.threads = &threads;
  238. thermo.threads = &threads;
  239. neighbor.ghost_newton = ghost_newton;
  240. omp_set_num_threads(num_threads);
  241. neighbor.timer = &timer;
  242. force->timer = &timer;
  243. comm.check_safeexchange = check_safeexchange;
  244. comm.do_safeexchange = do_safeexchange;
  245. force->use_sse = use_sse;
  246. neighbor.halfneigh = halfneigh;
  247. if(halfneigh < 0) force->use_oldcompute = 1;
  248. if(use_sse) {
  249. #ifdef VARIANT_REFERENCE
  250. if(me == 0) printf("ERROR: Trying to run with -sse with miniMD reference version. Use SSE variant instead. Exiting.\n");
  251. MPI_Finalize();
  252. exit(0);
  253. #endif
  254. }
  255. if(num_steps > 0) in.ntimes = num_steps;
  256. if(system_size > 0) {
  257. in.nx = system_size;
  258. in.ny = system_size;
  259. in.nz = system_size;
  260. }
  261. if(neighbor_size > 0) {
  262. neighbor.nbinx = neighbor_size;
  263. neighbor.nbiny = neighbor_size;
  264. neighbor.nbinz = neighbor_size;
  265. }
  266. if(neighbor_size < 0 && in.datafile == NULL) {
  267. MMD_float neighscale = 5.0 / 6.0;
  268. neighbor.nbinx = neighscale * in.nx;
  269. neighbor.nbiny = neighscale * in.ny;
  270. neighbor.nbinz = neighscale * in.ny;
  271. }
  272. if(neighbor_size < 0 && in.datafile)
  273. neighbor.nbinx = -1;
  274. if(neighbor.nbinx == 0) neighbor.nbinx = 1;
  275. if(neighbor.nbiny == 0) neighbor.nbiny = 1;
  276. if(neighbor.nbinz == 0) neighbor.nbinz = 1;
  277. integrate.ntimes = in.ntimes;
  278. integrate.dt = in.dt;
  279. neighbor.every = in.neigh_every;
  280. neighbor.cutneigh = in.neigh_cut;
  281. force->cutforce = in.force_cut;
  282. thermo.nstat = in.thermo_nstat;
  283. if(me == 0)
  284. printf("# Create System:\n");
  285. if(in.datafile) {
  286. read_lammps_data(atom, comm, neighbor, integrate, thermo, in.datafile, in.units);
  287. MMD_float volume = atom.box.xprd * atom.box.yprd * atom.box.zprd;
  288. in.rho = 1.0 * atom.natoms / volume;
  289. force->setup();
  290. if(in.forcetype == FORCEEAM) atom.mass = force->mass;
  291. } else {
  292. create_box(atom, in.nx, in.ny, in.nz, in.rho);
  293. comm.setup(neighbor.cutneigh, atom);
  294. neighbor.setup(atom);
  295. integrate.setup();
  296. force->setup();
  297. if(in.forcetype == FORCEEAM) atom.mass = force->mass;
  298. create_atoms(atom, in.nx, in.ny, in.nz, in.rho);
  299. thermo.setup(in.rho, integrate, atom, in.units);
  300. create_velocity(in.t_request, atom, thermo);
  301. }
  302. if(me == 0)
  303. printf("# Done .... \n");
  304. if(me == 0) {
  305. fprintf(stdout, "# " VARIANT_STRING " output ...\n");
  306. fprintf(stdout, "# Systemparameters: \n");
  307. fprintf(stdout, "\t# MPI processes: %i\n", neighbor.threads->mpi_num_threads);
  308. fprintf(stdout, "\t# OpenMP threads: %i\n", neighbor.threads->omp_num_threads);
  309. fprintf(stdout, "\t# Inputfile: %s\n", input_file == 0 ? "in.lj.miniMD" : input_file);
  310. fprintf(stdout, "\t# Datafile: %s\n", in.datafile ? in.datafile : "None");
  311. fprintf(stdout, "\t# ForceStyle: %s\n", in.forcetype == FORCELJ ? "LJ" : "EAM");
  312. fprintf(stdout, "\t# Units: %s\n", in.units == 0 ? "LJ" : "METAL");
  313. fprintf(stdout, "\t# Atoms: %i\n", atom.natoms);
  314. fprintf(stdout, "\t# System size: %2.2lf %2.2lf %2.2lf (unit cells: %i %i %i)\n", atom.box.xprd, atom.box.yprd, atom.box.zprd, in.nx, in.ny, in.nz);
  315. fprintf(stdout, "\t# Density: %lf\n", in.rho);
  316. fprintf(stdout, "\t# Force cutoff: %lf\n", force->cutforce);
  317. fprintf(stdout, "\t# Neigh cutoff: %lf\n", neighbor.cutneigh);
  318. fprintf(stdout, "\t# Half neighborlists: %i\n", neighbor.halfneigh);
  319. fprintf(stdout, "\t# Neighbor bins: %i %i %i\n", neighbor.nbinx, neighbor.nbiny, neighbor.nbinz);
  320. fprintf(stdout, "\t# Neighbor frequency: %i\n", neighbor.every);
  321. fprintf(stdout, "\t# Timestep size: %lf\n", integrate.dt);
  322. fprintf(stdout, "\t# Thermo frequency: %i\n", thermo.nstat);
  323. fprintf(stdout, "\t# Ghost Newton: %i\n", ghost_newton);
  324. fprintf(stdout, "\t# Use SSE intrinsics: %i\n", force->use_sse);
  325. fprintf(stdout, "\t# Do safe exchange: %i\n", comm.do_safeexchange);
  326. fprintf(stdout, "\t# Size of float: %i\n\n", sizeof(MMD_float));
  327. }
  328. comm.exchange(atom);
  329. comm.borders(atom);
  330. neighbor.build(atom);
  331. force->evflag = 1;
  332. force->compute(atom, neighbor, comm, me);
  333. if(neighbor.halfneigh && neighbor.ghost_newton)
  334. comm.reverse_communicate(atom);
  335. if(me == 0) printf("# Starting dynamics ...\n");
  336. if(me == 0) printf("# Timestep T U P Time\n");
  337. thermo.compute(0, atom, neighbor, force, timer, comm);
  338. timer.barrier_start(TIME_TOTAL);
  339. integrate.run(atom, force, neighbor, comm, thermo, timer);
  340. timer.barrier_stop(TIME_TOTAL);
  341. int natoms;
  342. MPI_Allreduce(&atom.nlocal, &natoms, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
  343. force->evflag = 1;
  344. force->compute(atom, neighbor, comm, me);
  345. if(neighbor.halfneigh && neighbor.ghost_newton)
  346. comm.reverse_communicate(atom);
  347. thermo.compute(-1, atom, neighbor, force, timer, comm);
  348. if(me == 0) {
  349. double time_other = timer.array[TIME_TOTAL] - timer.array[TIME_FORCE] - timer.array[TIME_NEIGH] - timer.array[TIME_COMM];
  350. printf("\n\n");
  351. printf("# Performance Summary:\n");
  352. printf("# MPI_proc OMP_threads nsteps natoms t_total t_force t_neigh t_comm t_other performance perf/thread grep_string t_extra\n");
  353. printf("%i %i %i %i %lf %lf %lf %lf %lf %lf %lf PERF_SUMMARY %lf\n\n\n",
  354. nprocs, num_threads, integrate.ntimes, natoms,
  355. timer.array[TIME_TOTAL], timer.array[TIME_FORCE], timer.array[TIME_NEIGH], timer.array[TIME_COMM], time_other,
  356. 1.0 * natoms * integrate.ntimes / timer.array[TIME_TOTAL], 1.0 * natoms * integrate.ntimes / timer.array[TIME_TOTAL] / nprocs / num_threads, timer.array[TIME_TEST]);
  357. }
  358. if(yaml_output)
  359. output(in, atom, force, neighbor, comm, thermo, integrate, timer, screen_yaml);
  360. delete force;
  361. MPI_Barrier(MPI_COMM_WORLD);
  362. MPI_Finalize();
  363. #if defined(_USE_EIGER_MODEL) || defined(_USE_EIGER) || \
  364. defined(_USE_CSV) || defined(_USE_FAKEEIGER)
  365. PERFDECL(PERF::finalize();)
  366. #endif
  367. return 0;
  368. }