PageRenderTime 37ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/skeletons/minimd_full/ljs.cpp

https://bitbucket.org/mdrohmann/sstmacro
C++ | 459 lines | 342 code | 87 blank | 30 comment | 124 complexity | cbf43e3068641eafa0388f0207664b2d 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("harrenhal","minimd",LWP_DBNAME,"",".log");)
  95. PERFDECL(PERF::mpiArgs(me,nprocs);)
  96. #endif
  97. int error = 0;
  98. if(input_file == NULL)
  99. error = input(in, "in.lj.miniMD");
  100. else
  101. error = input(in, input_file);
  102. if(error) {
  103. MPI_Finalize();
  104. exit(0);
  105. }
  106. for(int i = 0; i < argc; i++) {
  107. if((strcmp(argv[i], "-t") == 0) || (strcmp(argv[i], "--num_threads") == 0)) {
  108. num_threads = atoi(argv[++i]);
  109. continue;
  110. }
  111. if((strcmp(argv[i], "--numa") == 0)) {
  112. numa = atoi(argv[++i]);
  113. continue;
  114. }
  115. if((strcmp(argv[i], "-n") == 0) || (strcmp(argv[i], "--nsteps") == 0)) {
  116. num_steps = atoi(argv[++i]);
  117. continue;
  118. }
  119. if((strcmp(argv[i], "-s") == 0) || (strcmp(argv[i], "--size") == 0)) {
  120. system_size = atoi(argv[++i]);
  121. continue;
  122. }
  123. if((strcmp(argv[i], "-b") == 0) || (strcmp(argv[i], "--neigh_bins") == 0)) {
  124. neighbor_size = atoi(argv[++i]);
  125. continue;
  126. }
  127. if((strcmp(argv[i], "--half_neigh") == 0)) {
  128. halfneigh = atoi(argv[++i]);
  129. continue;
  130. }
  131. if((strcmp(argv[i], "-sse") == 0)) {
  132. use_sse = atoi(argv[++i]);
  133. continue;
  134. }
  135. if((strcmp(argv[i], "--check_exchange") == 0)) {
  136. check_safeexchange = 1;
  137. continue;
  138. }
  139. if((strcmp(argv[i], "-o") == 0) || (strcmp(argv[i], "--yaml_output") == 0)) {
  140. yaml_output = atoi(argv[++i]);
  141. continue;
  142. }
  143. if((strcmp(argv[i], "--yaml_screen") == 0)) {
  144. screen_yaml = 1;
  145. continue;
  146. }
  147. if((strcmp(argv[i], "-f") == 0) || (strcmp(argv[i], "--data_file") == 0)) {
  148. if(in.datafile == NULL) in.datafile = new char[1000];
  149. strcpy(in.datafile, argv[++i]);
  150. continue;
  151. }
  152. if((strcmp(argv[i], "-u") == 0) || (strcmp(argv[i], "--units") == 0)) {
  153. in.units = strcmp(argv[++i], "metal") == 0 ? 1 : 0;
  154. continue;
  155. }
  156. if((strcmp(argv[i], "-p") == 0) || (strcmp(argv[i], "--force") == 0)) {
  157. in.forcetype = strcmp(argv[++i], "eam") == 0 ? FORCEEAM : FORCELJ;
  158. continue;
  159. }
  160. if((strcmp(argv[i], "-gn") == 0) || (strcmp(argv[i], "--ghost_newton") == 0)) {
  161. ghost_newton = atoi(argv[++i]);
  162. continue;
  163. }
  164. if((strcmp(argv[i], "-h") == 0) || (strcmp(argv[i], "--help") == 0)) {
  165. printf("\n-----------------------------------------------------------------------------------------------------------\n");
  166. printf("-------------" VARIANT_STRING "--------------------\n");
  167. printf("-------------------------------------------------------------------------------------------------------------\n\n");
  168. printf("miniMD is a simple, parallel molecular dynamics (MD) code,\n"
  169. "which is part of the Mantevo project at Sandia National\n"
  170. "Laboratories ( http://www.mantevo.org ).\n"
  171. "The original authors of miniMD are Steve Plimpton (sjplimp@sandia.gov) ,\n"
  172. "Paul Crozier (pscrozi@sandia.gov) with current\n"
  173. "versions written by Christian Trott (crtrott@sandia.gov).\n\n");
  174. printf("Commandline Options:\n");
  175. printf("\n Execution configuration:\n");
  176. printf("\t-t / --num_threads <threads>: set number of threads per MPI rank (default 1)\n");
  177. printf("\t--numa <regions>: set number of numa regions used per MPI rank (default 1)\n"
  178. "\t <threads> must be divisable by <numa>\n");
  179. printf("\t--half_neigh <int>: use half neighborlists (default 1)\n"
  180. "\t 0: full neighborlist\n"
  181. "\t 1: half neighborlist\n"
  182. "\t -1: original miniMD half neighborlist force (not OpenMP safe)\n");
  183. printf("\t-d / --device <int>: choose device to use (only applicable for GPU execution)\n");
  184. printf("\t-dm / --device_map: map devices to MPI ranks\n");
  185. printf("\t-ng / --num_gpus <int>: give number of GPUs per Node (used in conjuction with -dm\n"
  186. "\t to determine device id: 'id=mpi_rank%%ng' (default 2)\n");
  187. printf("\t--skip_gpu <int>: skip the specified gpu when assigning devices to MPI ranks\n"
  188. "\t used in conjunction with -dm (but must come first in arg list)\n");
  189. printf("\t-sse <sse_version>: use explicit sse intrinsics (use miniMD-SSE variant)\n");
  190. printf("\t-gn / --ghost_newton <int>: set usage of newtons third law for ghost atoms\n"
  191. "\t (only applicable with half neighborlists)\n");
  192. printf("\n Simulation setup:\n");
  193. printf("\t-i / --input_file <string>: set input file to be used (default: in.lj.miniMD)\n");
  194. printf("\t-n / --nsteps <int>: set number of timesteps for simulation\n");
  195. printf("\t-s / --size <int>: set linear dimension of systembox\n");
  196. printf("\t-b / --neigh_bins <int>: set linear dimension of neighbor bin grid\n");
  197. printf("\t-u / --units <string>: set units (lj or metal), see LAMMPS documentation\n");
  198. printf("\t-p / --force <string>: set interaction model (lj or eam)\n");
  199. printf("\t-f / --data_file <string>: read configuration from LAMMPS data file\n");
  200. printf("\n Miscelaneous:\n");
  201. printf("\t--check_exchange: check whether atoms moved further than subdomain width\n");
  202. printf("\t--safe_exchange: perform exchange communication with all MPI processes\n"
  203. "\t within rcut_neighbor (outer force cutoff)\n");
  204. printf("\t-o / --yaml_output <int>: level of yaml output (default 1)\n");
  205. printf("\t--yaml_screen: write yaml output also to screen\n");
  206. printf("\t-h / --help: display this help message\n\n");
  207. printf("---------------------------------------------------------\n\n");
  208. exit(0);
  209. }
  210. }
  211. Atom atom;
  212. Neighbor neighbor;
  213. Integrate integrate;
  214. Thermo thermo;
  215. Comm comm;
  216. Timer timer;
  217. ThreadData threads;
  218. Force* force;
  219. if(in.forcetype == FORCEEAM) {
  220. force = (Force*) new ForceEAM();
  221. if(ghost_newton == 1) {
  222. if(me == 0)
  223. printf("# EAM currently requires '--ghost_newton 0'; Changing setting now.\n");
  224. ghost_newton = 0;
  225. }
  226. }
  227. if(in.forcetype == FORCELJ) force = (Force*) new ForceLJ();
  228. threads.mpi_me = me;
  229. threads.mpi_num_threads = nprocs;
  230. threads.omp_me = 0;
  231. threads.omp_num_threads = num_threads;
  232. atom.threads = &threads;
  233. comm.threads = &threads;
  234. force->threads = &threads;
  235. integrate.threads = &threads;
  236. neighbor.threads = &threads;
  237. thermo.threads = &threads;
  238. neighbor.ghost_newton = ghost_newton;
  239. omp_set_num_threads(num_threads);
  240. neighbor.timer = &timer;
  241. force->timer = &timer;
  242. comm.check_safeexchange = check_safeexchange;
  243. comm.do_safeexchange = do_safeexchange;
  244. force->use_sse = use_sse;
  245. neighbor.halfneigh = halfneigh;
  246. if(halfneigh < 0) force->use_oldcompute = 1;
  247. if(use_sse) {
  248. #ifdef VARIANT_REFERENCE
  249. if(me == 0) printf("ERROR: Trying to run with -sse with miniMD reference version. Use SSE variant instead. Exiting.\n");
  250. MPI_Finalize();
  251. exit(0);
  252. #endif
  253. }
  254. if(num_steps > 0) in.ntimes = num_steps;
  255. if(system_size > 0) {
  256. in.nx = system_size;
  257. in.ny = system_size;
  258. in.nz = system_size;
  259. }
  260. if(neighbor_size > 0) {
  261. neighbor.nbinx = neighbor_size;
  262. neighbor.nbiny = neighbor_size;
  263. neighbor.nbinz = neighbor_size;
  264. }
  265. if(neighbor_size < 0 && in.datafile == NULL) {
  266. MMD_float neighscale = 5.0 / 6.0;
  267. neighbor.nbinx = neighscale * in.nx;
  268. neighbor.nbiny = neighscale * in.ny;
  269. neighbor.nbinz = neighscale * in.ny;
  270. }
  271. if(neighbor_size < 0 && in.datafile)
  272. neighbor.nbinx = -1;
  273. if(neighbor.nbinx == 0) neighbor.nbinx = 1;
  274. if(neighbor.nbiny == 0) neighbor.nbiny = 1;
  275. if(neighbor.nbinz == 0) neighbor.nbinz = 1;
  276. integrate.ntimes = in.ntimes;
  277. integrate.dt = in.dt;
  278. neighbor.every = in.neigh_every;
  279. neighbor.cutneigh = in.neigh_cut;
  280. force->cutforce = in.force_cut;
  281. thermo.nstat = in.thermo_nstat;
  282. if(me == 0)
  283. printf("# Create System:\n");
  284. if(in.datafile) {
  285. read_lammps_data(atom, comm, neighbor, integrate, thermo, in.datafile, in.units);
  286. MMD_float volume = atom.box.xprd * atom.box.yprd * atom.box.zprd;
  287. in.rho = 1.0 * atom.natoms / volume;
  288. force->setup();
  289. if(in.forcetype == FORCEEAM) atom.mass = force->mass;
  290. } else {
  291. create_box(atom, in.nx, in.ny, in.nz, in.rho);
  292. comm.setup(neighbor.cutneigh, atom);
  293. neighbor.setup(atom);
  294. integrate.setup();
  295. force->setup();
  296. if(in.forcetype == FORCEEAM) atom.mass = force->mass;
  297. create_atoms(atom, in.nx, in.ny, in.nz, in.rho);
  298. thermo.setup(in.rho, integrate, atom, in.units);
  299. create_velocity(in.t_request, atom, thermo);
  300. }
  301. if(me == 0)
  302. printf("# Done .... \n");
  303. if(me == 0) {
  304. fprintf(stdout, "# " VARIANT_STRING " output ...\n");
  305. fprintf(stdout, "# Systemparameters: \n");
  306. fprintf(stdout, "\t# MPI processes: %i\n", neighbor.threads->mpi_num_threads);
  307. fprintf(stdout, "\t# OpenMP threads: %i\n", neighbor.threads->omp_num_threads);
  308. fprintf(stdout, "\t# Inputfile: %s\n", input_file == 0 ? "in.lj.miniMD" : input_file);
  309. fprintf(stdout, "\t# Datafile: %s\n", in.datafile ? in.datafile : "None");
  310. fprintf(stdout, "\t# ForceStyle: %s\n", in.forcetype == FORCELJ ? "LJ" : "EAM");
  311. fprintf(stdout, "\t# Units: %s\n", in.units == 0 ? "LJ" : "METAL");
  312. fprintf(stdout, "\t# Atoms: %i\n", atom.natoms);
  313. 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);
  314. fprintf(stdout, "\t# Density: %lf\n", in.rho);
  315. fprintf(stdout, "\t# Force cutoff: %lf\n", force->cutforce);
  316. fprintf(stdout, "\t# Neigh cutoff: %lf\n", neighbor.cutneigh);
  317. fprintf(stdout, "\t# Half neighborlists: %i\n", neighbor.halfneigh);
  318. fprintf(stdout, "\t# Neighbor bins: %i %i %i\n", neighbor.nbinx, neighbor.nbiny, neighbor.nbinz);
  319. fprintf(stdout, "\t# Neighbor frequency: %i\n", neighbor.every);
  320. fprintf(stdout, "\t# Timestep size: %lf\n", integrate.dt);
  321. fprintf(stdout, "\t# Thermo frequency: %i\n", thermo.nstat);
  322. fprintf(stdout, "\t# Ghost Newton: %i\n", ghost_newton);
  323. fprintf(stdout, "\t# Use SSE intrinsics: %i\n", force->use_sse);
  324. fprintf(stdout, "\t# Do safe exchange: %i\n", comm.do_safeexchange);
  325. fprintf(stdout, "\t# Size of float: %i\n\n", sizeof(MMD_float));
  326. }
  327. comm.exchange(atom);
  328. comm.borders(atom);
  329. neighbor.build(atom);
  330. force->evflag = 1;
  331. force->compute(atom, neighbor, comm, me);
  332. if(neighbor.halfneigh && neighbor.ghost_newton)
  333. comm.reverse_communicate(atom);
  334. if(me == 0) printf("# Starting dynamics ...\n");
  335. if(me == 0) printf("# Timestep T U P Time\n");
  336. thermo.compute(0, atom, neighbor, force, timer, comm);
  337. timer.barrier_start(TIME_TOTAL);
  338. integrate.run(atom, force, neighbor, comm, thermo, timer);
  339. timer.barrier_stop(TIME_TOTAL);
  340. int natoms;
  341. MPI_Allreduce(&atom.nlocal, &natoms, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
  342. force->evflag = 1;
  343. force->compute(atom, neighbor, comm, me);
  344. if(neighbor.halfneigh && neighbor.ghost_newton)
  345. comm.reverse_communicate(atom);
  346. thermo.compute(-1, atom, neighbor, force, timer, comm);
  347. if(me == 0) {
  348. double time_other = timer.array[TIME_TOTAL] - timer.array[TIME_FORCE] - timer.array[TIME_NEIGH] - timer.array[TIME_COMM];
  349. printf("\n\n");
  350. printf("# Performance Summary:\n");
  351. 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");
  352. printf("%i %i %i %i %lf %lf %lf %lf %lf %lf %lf PERF_SUMMARY %lf\n\n\n",
  353. nprocs, num_threads, integrate.ntimes, natoms,
  354. timer.array[TIME_TOTAL], timer.array[TIME_FORCE], timer.array[TIME_NEIGH], timer.array[TIME_COMM], time_other,
  355. 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]);
  356. }
  357. if(yaml_output)
  358. output(in, atom, force, neighbor, comm, thermo, integrate, timer, screen_yaml);
  359. delete force;
  360. MPI_Barrier(MPI_COMM_WORLD);
  361. MPI_Finalize();
  362. #if defined(_USE_EIGER_MODEL) || defined(_USE_EIGER) || \
  363. defined(_USE_CSV) || defined(_USE_FAKEEIGER)
  364. PERFDECL(PERF::finalize();)
  365. #endif
  366. return 0;
  367. }