source: CIVL/examples/omp/c_md.c@ 7d77e64

main test-branch
Last change on this file since 7d77e64 was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 9.3 KB
Line 
1/* ***********************************************************************
2 This program is part of the
3 OpenMP Source Code Repository
4
5 http://www.pcg.ull.es/ompscr/
6 e-mail: ompscr@etsii.ull.es
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 (LICENSE file) along with this program; if not, write to
20 the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
21 Boston, MA 02111-1307 USA
22
23 FILE: c_md.c
24 VERSION: 1.0
25 DATE: May 2004
26 AUTHOR: Bill Magro, Kuck and Associates, Inc. (KAI), 1998
27 COMMENTS TO: sande@csi.ull.es
28 DESCRIPTION: This program implements a simple molecular dynamics simulation,
29 using the velocity Verlet time integration scheme.
30 The particles interact with a central pair potential.
31 COMMENTS:
32 REFERENCES: W. C. Swope and H. C. Andersen and P. H. Berens and K. R. Wilson
33 A Computer Simulation Method for the Calculation of
34 Equilibrium Constants for the Formation of Physical
35 Clusters of Molecules: Application to Small Water Clusters
36 Journal of Chemical Physics, 1982 vol. 76 pg 637-649
37 BASIC PRAGMAS: parallel for
38 USAGE: ./c_md.par 8192 10
39 INPUT: Number of particles
40 Number of simulation steps
41 OUTPUT: -
42 FILE FORMATS: -
43 RESTRICTIONS: -
44 REVISION HISTORY:
45**************************************************************************/
46//#include "OmpSCR.h"
47#include <math.h>
48#include <omp.h>
49
50// following added by sfsiegel due to use of "calloc":
51#include <stdlib.h>
52// following added by sfsiegel due to use of "printf":
53#include <stdio.h>
54
55#ifndef RAND_MAX
56#define RAND_MAX 0x7fff
57#endif
58
59#ifndef M_PI_2
60#define M_PI_2 1.57079632679489661923 /* pi/2 */
61#endif
62
63#define NUM_ARGS 2
64#define NUM_TIMERS 1
65#define DEFAULT_NPARTS 8192
66#define DEFAULT_NSTEPS 10
67#define USAGE_STR "NPARTS NSTEPS"
68#define NDIM 3
69
70#define NPARTSINIT 10
71#define NSTEPSINIT 4
72
73int NPARTS; /* No. of particles */
74int NSTEPS; /* No. of simulation steps */
75
76typedef double vnd_t[NDIM];
77
78/* -----------------------------------------------------------------------
79 PROTOTYPES
80 * ----------------------------------------------------------------------- */
81
82double v(double x);
83double dv(double x);
84void initialize(int np, int nd, vnd_t box, vnd_t *pos, vnd_t *vel, vnd_t *acc);
85double dist(int nd, vnd_t r1, vnd_t r2, vnd_t dr);
86double dot_prod(int n, vnd_t x,vnd_t y);
87void compute(int np, int nd, vnd_t *pos, vnd_t *vel, double mass, vnd_t *f, double *pot_p, double *kin_p);
88void update(int np, int nd, vnd_t *pos, vnd_t *vel, vnd_t *f, vnd_t *a, double mass, double dt);
89int main (int argc, char **argv);
90
91/* -----------------------------------------------------------------------
92 IMPLEMENTATION
93 * ----------------------------------------------------------------------- */
94/* -----------------------------------------------------------------------
95 statement function for the pair potential.
96 This potential is a harmonic well which smoothly saturates to a
97 maximum value at PI/2.
98 * ----------------------------------------------------------------------- */
99double v(double x) {
100 if (x < M_PI_2)
101 return pow(sin(x), 2.0);
102 else
103 return 1.0;
104}
105/* -----------------------------------------------------------------------
106 statement function for the derivative of the pair potential
107 * ----------------------------------------------------------------------- */
108double dv(double x) {
109 if (x < M_PI_2)
110 return 2.0 * sin(x) * cos(x);
111 else
112 return 0.0;
113}
114/* -----------------------------------------------------------------------
115 Initialize the positions, velocities, and accelerations.
116 * ----------------------------------------------------------------------- */
117void initialize(int np, int nd, vnd_t box, vnd_t *pos, vnd_t *vel, vnd_t *acc) {
118 int i, j;
119 double x;
120
121 //srand(4711L);
122 int r = 42; // REPLACE RANDOM NUMBER GENERATION
123 for (i = 0; i < np; i++) {
124 for (j = 0; j < nd; j++) {
125 x = (r++) % 10000 / (double)10000.0;
126 pos[i][j] = box[j] * x;
127 vel[i][j] = 0.0;
128 acc[i][j] = 0.0;
129 }
130 }
131}
132/* -----------------------------------------------------------------------
133 Compute the displacement vector (and its norm) between two particles.
134 * ----------------------------------------------------------------------- */
135double dist(int nd, vnd_t r1, vnd_t r2, vnd_t dr) {
136 int i;
137 double d;
138
139 d = 0.0;
140 for (i = 0; i < nd; i++) {
141 dr[i] = r1[i] - r2[i];
142 d += dr[i] * dr[i];
143 }
144 return sqrt(d);
145}
146/* -----------------------------------------------------------------------
147 Return the dot product between two vectors of type double and length n
148 * ----------------------------------------------------------------------- */
149double dot_prod(int n, vnd_t x, vnd_t y) {
150 int i;
151 double t = 0.0;
152
153 for (i = 0; i < n; i++) {
154 t += x[i] * y[i];
155 }
156 return t;
157}
158/* -----------------------------------------------------------------------
159 Compute the forces and energies, given positions, masses,
160 and velocities
161 * ----------------------------------------------------------------------- */
162void compute(int np, int nd, vnd_t *pos, vnd_t *vel,
163 double mass, vnd_t *f, double *pot_p, double *kin_p) {
164 int i, j, k;
165 vnd_t rij;
166 double d;
167 double pot, kin;
168
169 pot = 0.0;
170 kin = 0.0;
171 /* The computation of forces and energies is fully parallel. */
172#pragma omp parallel for default(shared) private(i, j, k, rij, d) reduction(+ : pot, kin)
173 for (i = 0; i < np; i++) {
174 /* compute potential energy and forces */
175 for (j = 0; j < nd; j++)
176 f[i][j] = 0.0;
177 for (j = 0; j < np; j++) {
178 if (i != j) {
179 d = dist(nd, pos[i], pos[j], rij);
180 /* attribute half of the potential energy to particle 'j' */
181 pot = pot + 0.5 * v(d);
182 for (k = 0; k < nd; k++) {
183 f[i][k] = f[i][k] - rij[k]* dv(d) /d;
184 }
185 }
186 }
187 /* compute kinetic energy */
188 kin = kin + dot_prod(nd, vel[i], vel[j]);
189 }
190 kin = kin * 0.5 * mass;
191 *pot_p = pot;
192 *kin_p = kin;
193}
194/* -----------------------------------------------------------------------
195 Perform the time integration, using a velocity Verlet algorithm
196 * ----------------------------------------------------------------------- */
197void update(int np, int nd, vnd_t *pos, vnd_t *vel, vnd_t *f, vnd_t *a, double mass, double dt) {
198 int i, j;
199 double rmass;
200
201 rmass = 1.0/mass;
202 /* The time integration is fully parallel */
203#pragma omp parallel for default(shared) private(i, j) firstprivate(rmass, dt)
204 for (i = 0; i < np; i++) {
205 for (j = 0; j < nd; j++) {
206 pos[i][j] = pos[i][j] + vel[i][j]*dt + 0.5*dt*dt*a[i][j];
207 vel[i][j] = vel[i][j] + 0.5*dt*(f[i][j]*rmass + a[i][j]);
208 a[i][j] = f[i][j]*rmass;
209 }
210 }
211}
212/* ----------------------------------------------------------------------- */
213int main (int argc, char **argv) {
214 /* simulation parameters */
215 double mass = 1.0;
216 double dt = 1.0e-4;
217 vnd_t box;
218 vnd_t *position;
219 vnd_t *velocity;
220 vnd_t *force;
221 vnd_t *accel;
222 double potential, kinetic, E0;
223 int i;
224 int NUMTHREADS;
225 double total_time;
226 char *PARAM_NAMES[NUM_ARGS] = {"Nparts", "Nsteps"};
227 char *TIMERS_NAMES[NUM_TIMERS] = {"Total_time" };
228 char *DEFAULT_VALUES[NUM_ARGS] = {"8192", "10"};
229
230
231 NUMTHREADS = 1; //omp_get_num_threads();
232 //OSCR_init (NUMTHREADS, "Molecular dynamic simulation", "Use md <Nparts> <Nsteps>", NUM_ARGS,
233 // PARAM_NAMES, DEFAULT_VALUES , NUM_TIMERS, NUM_TIMERS, TIMERS_NAMES,
234 //argc, argv);
235
236
237 NPARTS = NPARTSINIT; //OSCR_getarg_int(1);
238 NSTEPS = NSTEPSINIT; //OSCR_getarg_int(2);
239 /* Default: DEFAULT_NPARTS, DEFAULT_NSTEPS */
240
241 /* Memory allocation */
242 position = calloc(NPARTS, sizeof(vnd_t));
243 velocity = calloc(NPARTS, sizeof(vnd_t));
244 force = calloc(NPARTS, sizeof(vnd_t));
245 accel = calloc(NPARTS, sizeof(vnd_t));
246
247 NUMTHREADS = 1; //omp_get_num_threads();
248 for (i = 0; i < NDIM; i++)
249 box[i] = 10.0;
250 /* set initial positions, velocities, and accelerations */
251 initialize(NPARTS, NDIM, box, position, velocity, accel);
252 //OSCR_timer_start(0);
253 /* compute the forces and energies */
254 compute(NPARTS, NDIM, position, velocity, mass, force, &potential, &kinetic);
255 E0 = potential + kinetic;
256 /* This is the main time stepping loop */
257 for (i = 0; i < NSTEPS; i++) {
258 compute(NPARTS, NDIM, position, velocity, mass, force, &potential, &kinetic);
259#if 0
260 printf("%17.9e %17.9e %17.9e\n", potential, kinetic, (potential + kinetic - E0) / E0);
261#endif
262 update(NPARTS, NDIM, position, velocity, force, accel, mass, dt);
263 }
264 //OSCR_timer_stop(0);
265 total_time = 1; //OSCR_timer_read(0);
266 //OSCR_report(1, TIMERS_NAMES);
267 printf("\n \t# THREADS \tTIME (secs.) \n");
268 printf("\t %d \t\t%14.6lf\n", NUMTHREADS, total_time);
269
270 return 0;
271}
272
273
274/*
275 * vim:ts=2:sw=2:
276 */
Note: See TracBrowser for help on using the repository browser.