CoMD
A Mini-app for Co-Design of Classical Molecular Dynamics.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
timestep.c
Go to the documentation of this file.
1 /// \file
2 /// Leapfrog time integrator
3 
4 #include "timestep.h"
5 
6 #include "CoMDTypes.h"
7 #include "linkCells.h"
8 #include "parallel.h"
9 #include "performanceTimers.h"
10 
11 static void advanceVelocity(SimFlat* s, int nBoxes, real_t dt);
12 static void advancePosition(SimFlat* s, int nBoxes, real_t dt);
13 
14 
15 /// Advance the simulation time to t+dt using a leap frog method
16 /// (equivalent to velocity verlet).
17 ///
18 /// Forces must be computed before calling the integrator the first time.
19 ///
20 /// - Advance velocities half time step using forces
21 /// - Advance positions full time step using velocities
22 /// - Update link cells and exchange remote particles
23 /// - Compute forces
24 /// - Update velocities half time step using forces
25 ///
26 /// This leaves positions, velocities, and forces at t+dt, with the
27 /// forces ready to perform the half step velocity update at the top of
28 /// the next call.
29 ///
30 /// After nSteps the kinetic energy is computed for diagnostic output.
31 double timestep(SimFlat* s, int nSteps, real_t dt)
32 {
33  for (int ii=0; ii<nSteps; ++ii)
34  {
36  advanceVelocity(s, s->boxes->nLocalBoxes, 0.5*dt);
38 
40  advancePosition(s, s->boxes->nLocalBoxes, dt);
42 
46 
48  computeForce(s);
50 
52  advanceVelocity(s, s->boxes->nLocalBoxes, 0.5*dt);
54  }
55 
56  kineticEnergy(s);
57 
58  return s->ePotential;
59 }
60 
62 {
63  s->pot->force(s);
64 }
65 
66 
67 void advanceVelocity(SimFlat* s, int nBoxes, real_t dt)
68 {
69  for (int iBox=0; iBox<nBoxes; iBox++)
70  {
71  for (int iOff=MAXATOMS*iBox,ii=0; ii<s->boxes->nAtoms[iBox]; ii++,iOff++)
72  {
73  s->atoms->p[iOff][0] += dt*s->atoms->f[iOff][0];
74  s->atoms->p[iOff][1] += dt*s->atoms->f[iOff][1];
75  s->atoms->p[iOff][2] += dt*s->atoms->f[iOff][2];
76  }
77  }
78 }
79 
80 void advancePosition(SimFlat* s, int nBoxes, real_t dt)
81 {
82  for (int iBox=0; iBox<nBoxes; iBox++)
83  {
84  for (int iOff=MAXATOMS*iBox,ii=0; ii<s->boxes->nAtoms[iBox]; ii++,iOff++)
85  {
86  int iSpecies = s->atoms->iSpecies[iOff];
87  real_t invMass = 1.0/s->species[iSpecies].mass;
88  s->atoms->r[iOff][0] += dt*s->atoms->p[iOff][0]*invMass;
89  s->atoms->r[iOff][1] += dt*s->atoms->p[iOff][1]*invMass;
90  s->atoms->r[iOff][2] += dt*s->atoms->p[iOff][2]*invMass;
91  }
92  }
93 }
94 
95 /// Calculates total kinetic and potential energy across all tasks. The
96 /// local potential energy is a by-product of the force routine.
98 {
99  real_t eLocal[2];
100  eLocal[0] = s->ePotential;
101  eLocal[1] = 0;
102  for (int iBox=0; iBox<s->boxes->nLocalBoxes; iBox++)
103  {
104  for (int iOff=MAXATOMS*iBox,ii=0; ii<s->boxes->nAtoms[iBox]; ii++,iOff++)
105  {
106  int iSpecies = s->atoms->iSpecies[iOff];
107  real_t invMass = 0.5/s->species[iSpecies].mass;
108  eLocal[1] += ( s->atoms->p[iOff][0] * s->atoms->p[iOff][0] +
109  s->atoms->p[iOff][1] * s->atoms->p[iOff][1] +
110  s->atoms->p[iOff][2] * s->atoms->p[iOff][2] )*invMass;
111  }
112  }
113 
114  real_t eSum[2];
116  addRealParallel(eLocal, eSum, 2);
118 
119  s->ePotential = eSum[0];
120  s->eKinetic = eSum[1];
121 }
122 
123 /// \details
124 /// This function provides one-stop shopping for the sequence of events
125 /// that must occur for a proper exchange of halo atoms after the atom
126 /// positions have been updated by the integrator.
127 ///
128 /// - updateLinkCells: Since atoms have moved, some may be in the wrong
129 /// link cells.
130 /// - haloExchange (atom version): Sends atom data to remote tasks.
131 /// - sort: Sort the atoms.
132 ///
133 /// \see updateLinkCells
134 /// \see initAtomHaloExchange
135 /// \see sortAtomsInCell
137 {
138  updateLinkCells(sim->boxes, sim->atoms);
139 
141  haloExchange(sim->atomExchange, sim);
143 
144  for (int ii=0; ii<sim->boxes->nTotalBoxes; ++ii)
145  sortAtomsInCell(sim->atoms, sim->boxes, ii);
146 }