ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Symplectic.cpp
(Generate patch)

Comparing trunk/OOPSE/libmdtools/Symplectic.cpp (file contents):
Revision 466 by gezelter, Mon Apr 7 14:30:36 2003 UTC vs.
Revision 556 by mmeineke, Wed Jun 18 22:20:12 2003 UTC

# Line 1 | Line 1
1   #include <iostream>
2   #include <cstdlib>
3  
4 + #ifdef IS_MPI
5 + #include "mpiSimulation.hpp"
6 + #include <unistd.h>
7 + #endif //is_mpi
8 +
9   #include "Integrator.hpp"
5 #include "Thermo.hpp"
6 #include "ReadWrite.hpp"
7 #include "ForceFields.hpp"
8 #include "ExtendedSystem.hpp"
10   #include "simError.h"
11  
11 extern "C"{
12  
13  void v_constrain_a_( double &dt, int &n_atoms, double* mass,
14                       double* Rx, double* Ry, double* Rz,
15                       double* Vx, double* Vy, double* Vz,
16                       double* Fx, double* Fy, double* Fz,
17                       int &n_constrained, double *constr_sqr,
18                       int* constr_i, int* constr_j,
19                       double &box_x, double &box_y, double &box_z );
12  
13 <  void v_constrain_b_( double &dt, int &n_atoms, double* mass,
14 <                       double* Rx, double* Ry, double* Rz,
15 <                       double* Vx, double* Vy, double* Vz,
24 <                       double* Fx, double* Fy, double* Fz,
25 <                       double &Kinetic,
26 <                       int &n_constrained, double *constr_sqr,
27 <                       int* constr_i, int* constr_j,
28 <                       double &box_x, double &box_y, double &box_z );
29 < }
30 <
31 <
32 <
33 <
34 < Symplectic::Symplectic( SimInfo* the_entry_plug, ForceFields* the_ff,
35 <                        ExtendedSystem* the_es ){
36 <  entry_plug = the_entry_plug;
13 > Integrator::Integrator( SimInfo* theInfo, ForceFields* the_ff ){
14 >  
15 >  info = theInfo;
16    myFF = the_ff;
38  myES = the_es;
17    isFirst = 1;
18  
19 <  molecules = entry_plug->molecules;
20 <  nMols = entry_plug->n_mol;
19 >  molecules = info->molecules;
20 >  nMols = info->n_mol;
21  
22    // give a little love back to the SimInfo object
23    
24 <  if( entry_plug->the_integrator != NULL ) delete entry_plug->the_integrator;
25 <  entry_plug->the_integrator = this;
24 >  if( info->the_integrator != NULL ) delete info->the_integrator;
25 >  info->the_integrator = this;
26  
27 <  // grab the masses
27 >  nAtoms = info->n_atoms;
28  
51  mass = new double[entry_plug->n_atoms];
52  for(int i = 0; i < entry_plug->n_atoms; i++){
53    mass[i] = entry_plug->atoms[i]->getMass();
54  }  
55
29    // check for constraints
30 +  
31 +  constrainedA    = NULL;
32 +  constrainedB    = NULL;
33 +  constrainedDsqr = NULL;
34 +  moving          = NULL;
35 +  moved           = NULL;
36 +  prePos          = NULL;
37 +  
38 +  nConstrained = 0;
39  
40 <  is_constrained = 0;
40 >  checkConstraints();
41 > }
42  
43 + Integrator::~Integrator() {
44 +  
45 +  if( nConstrained ){
46 +    delete[] constrainedA;
47 +    delete[] constrainedB;
48 +    delete[] constrainedDsqr;
49 +    delete[] moving;
50 +    delete[] moved;
51 +    delete[] prePos;
52 + k
53 +  }
54 +  
55 + }
56 +
57 + void Integrator::checkConstraints( void ){
58 +
59 +
60 +  isConstrained = 0;
61 +
62    Constraint *temp_con;
63    Constraint *dummy_plug;
64 <  temp_con = new Constraint[entry_plug->n_SRI];
65 <  n_constrained = 0;
64 >  temp_con = new Constraint[info->n_SRI];
65 >  nConstrained = 0;
66    int constrained = 0;
67    
68    SRI** theArray;
# Line 74 | Line 76 | Symplectic::Symplectic( SimInfo* the_entry_plug, Force
76        if(constrained){
77          
78          dummy_plug = theArray[j]->get_constraint();
79 <        temp_con[n_constrained].set_a( dummy_plug->get_a() );
80 <        temp_con[n_constrained].set_b( dummy_plug->get_b() );
81 <        temp_con[n_constrained].set_dsqr( dummy_plug->get_dsqr() );
79 >        temp_con[nConstrained].set_a( dummy_plug->get_a() );
80 >        temp_con[nConstrained].set_b( dummy_plug->get_b() );
81 >        temp_con[nConstrained].set_dsqr( dummy_plug->get_dsqr() );
82          
83 <        n_constrained++;
83 >        nConstrained++;
84          constrained = 0;
85        }
86      }
# Line 91 | Line 93 | Symplectic::Symplectic( SimInfo* the_entry_plug, Force
93        if(constrained){
94          
95          dummy_plug = theArray[j]->get_constraint();
96 <        temp_con[n_constrained].set_a( dummy_plug->get_a() );
97 <        temp_con[n_constrained].set_b( dummy_plug->get_b() );
98 <        temp_con[n_constrained].set_dsqr( dummy_plug->get_dsqr() );
96 >        temp_con[nConstrained].set_a( dummy_plug->get_a() );
97 >        temp_con[nConstrained].set_b( dummy_plug->get_b() );
98 >        temp_con[nConstrained].set_dsqr( dummy_plug->get_dsqr() );
99          
100 <        n_constrained++;
100 >        nConstrained++;
101          constrained = 0;
102        }
103      }
# Line 108 | Line 110 | Symplectic::Symplectic( SimInfo* the_entry_plug, Force
110        if(constrained){
111          
112          dummy_plug = theArray[j]->get_constraint();
113 <        temp_con[n_constrained].set_a( dummy_plug->get_a() );
114 <        temp_con[n_constrained].set_b( dummy_plug->get_b() );
115 <        temp_con[n_constrained].set_dsqr( dummy_plug->get_dsqr() );
113 >        temp_con[nConstrained].set_a( dummy_plug->get_a() );
114 >        temp_con[nConstrained].set_b( dummy_plug->get_b() );
115 >        temp_con[nConstrained].set_dsqr( dummy_plug->get_dsqr() );
116          
117 <        n_constrained++;
117 >        nConstrained++;
118          constrained = 0;
119        }
120      }
121    }
122  
123 <  if(n_constrained > 0){
123 >  if(nConstrained > 0){
124      
125 <    is_constrained = 1;
126 <    constrained_i = new int[n_constrained];
127 <    constrained_j = new int[n_constrained];
128 <    constrained_dsqr = new double[n_constrained];
125 >    isConstrained = 1;
126 >
127 >    if(constrainedA != NULL )    delete[] constrainedA;
128 >    if(constrainedB != NULL )    delete[] constrainedB;
129 >    if(constrainedDsqr != NULL ) delete[] constrainedDsqr;
130 >
131 >    constrainedA =    new int[nConstrained];
132 >    constrainedB =    new int[nConstrained];
133 >    constrainedDsqr = new double[nConstrained];
134      
135 <    for( int i = 0; i < n_constrained; i++){
135 >    for( int i = 0; i < nConstrained; i++){
136        
137 <      /* add 1 to the index for the fortran arrays. */
138 <
139 <      constrained_i[i] = temp_con[i].get_a() + 1;
133 <      constrained_j[i] = temp_con[i].get_b() + 1;
134 <      constrained_dsqr[i] = temp_con[i].get_dsqr();
137 >      constrainedA[i] = temp_con[i].get_a();
138 >      constrainedB[i] = temp_con[i].get_b();
139 >      constrainedDsqr[i] = temp_con[i].get_dsqr();
140      }
141 +
142 +    
143 +    // save oldAtoms to check for lode balanceing later on.
144 +    
145 +    oldAtoms = nAtoms;
146 +    
147 +    moving = new int[nAtoms];
148 +    moved  = new int[nAtoms];
149 +
150 +    prePos = new double[nAtoms*3];
151    }
152    
153    delete[] temp_con;
154   }
155  
141 Symplectic::~Symplectic() {
142  
143  if( n_constrained ){
144    delete[] constrained_i;
145    delete[] constrained_j;
146    delete[] constrained_dsqr;
147  }
148  
149 }
156  
157 + void Integrator::integrate( void ){
158  
152 void Symplectic::integrate( void ){
153
154  const double e_convert = 4.184e-4; // converts kcal/mol -> amu*A^2/fs^2
155
159    int i, j;                         // loop counters
157  int nAtoms = entry_plug->n_atoms; // the number of atoms
160    double kE = 0.0;                  // the kinetic energy  
161    double rot_kE;
162    double trans_kE;
# Line 162 | Line 164 | void Symplectic::integrate( void ){
164    double dt2;                       // half the dt
165  
166    double vx, vy, vz;    // the velocities
167 < //  double vx2, vy2, vz2; // the square of the velocities
167 >  double vx2, vy2, vz2; // the square of the velocities
168    double rx, ry, rz;    // the postitions
169    
170    double ji[3];   // the body frame angular momentum
# Line 170 | Line 172 | void Symplectic::integrate( void ){
172    double Tb[3];   // torque in the body frame
173    double angle;   // the angle through which to rotate the rotation matrix
174    double A[3][3]; // the rotation matrix
175 +  double press[9];
176  
177 <  int time;
177 >  double dt          = info->dt;
178 >  double runTime     = info->run_time;
179 >  double sampleTime  = info->sampleTime;
180 >  double statusTime  = info->statusTime;
181 >  double thermalTime = info->thermalTime;
182  
183 <  double dt          = entry_plug->dt;
184 <  double runTime     = entry_plug->run_time;
185 <  double sampleTime  = entry_plug->sampleTime;
186 <  double statusTime  = entry_plug->statusTime;
180 <  double thermalTime = entry_plug->thermalTime;
183 >  double currSample;
184 >  double currThermal;
185 >  double currStatus;
186 >  double currTime;
187  
188 <  int n_loops  = (int)( runTime / dt );
189 <  int sample_n = (int)( sampleTime / dt );
184 <  int status_n = (int)( statusTime / dt );
185 <  int vel_n    = (int)( thermalTime / dt );
188 >  int calcPot, calcStress;
189 >  int isError;
190  
191 <  int calcPot;
191 >  tStats   = new Thermo( info );
192 >  e_out    = new StatWriter( info );
193 >  dump_out = new DumpWriter( info );
194  
195 <   Thermo *tStats = new Thermo( entry_plug );
190 <
191 <  StatWriter*  e_out    = new StatWriter( entry_plug );
192 <  DumpWriter*  dump_out = new DumpWriter( entry_plug );
193 <
194 <  Atom** atoms = entry_plug->atoms;
195 >  Atom** atoms = info->atoms;
196    DirectionalAtom* dAtom;
197    dt2 = 0.5 * dt;
198  
199 <  // initialize the forces the before the first step
199 >  // initialize the forces before the first step
200  
201 <  myFF->doForces(1,0);
201 >  myFF->doForces(1,1);
202    
203 <  if( entry_plug->setTemp ){
203 >  if( info->setTemp ){
204      
205      tStats->velocitize();
206    }
# Line 207 | Line 208 | void Symplectic::integrate( void ){
208    dump_out->writeDump( 0.0 );
209    e_out->writeStat( 0.0 );
210    
211 <  calcPot = 0;
211 >  calcPot     = 0;
212 >  calcStress  = 0;
213 >  currSample  = sampleTime;
214 >  currThermal = thermalTime;
215 >  currStatus  = statusTime;
216 >  currTime    = 0.0;;
217  
218 <  if( n_constrained ){
218 >  while( currTime < runTime ){
219  
220 <    double *Rx = new double[nAtoms];
221 <    double *Ry = new double[nAtoms];
222 <    double *Rz = new double[nAtoms];
220 >    if( (currTime+dt) >= currStatus ){
221 >      calcPot = 1;
222 >      calcStress = 1;
223 >    }
224      
225 <    double *Vx = new double[nAtoms];
219 <    double *Vy = new double[nAtoms];
220 <    double *Vz = new double[nAtoms];
221 <    
222 <    double *Fx = new double[nAtoms];
223 <    double *Fy = new double[nAtoms];
224 <    double *Fz = new double[nAtoms];
225 <    
226 <
227 <    for( tl=0; tl < n_loops; tl++ ){
225 >    integrateStep( calcPot, calcStress );
226        
227 <      for( j=0; j<nAtoms; j++ ){
227 >    currTime += dt;
228  
229 <        Rx[j] = atoms[j]->getX();
230 <        Ry[j] = atoms[j]->getY();
231 <        Rz[j] = atoms[j]->getZ();
232 <
235 <        Vx[j] = atoms[j]->get_vx();
236 <        Vy[j] = atoms[j]->get_vy();
237 <        Vz[j] = atoms[j]->get_vz();
238 <
239 <        Fx[j] = atoms[j]->getFx();
240 <        Fy[j] = atoms[j]->getFy();
241 <        Fz[j] = atoms[j]->getFz();
242 <
243 <      }
244 <        
245 <      v_constrain_a_( dt, nAtoms, mass, Rx, Ry, Rz, Vx, Vy, Vz,
246 <                      Fx, Fy, Fz,
247 <                      n_constrained, constrained_dsqr,
248 <                      constrained_i, constrained_j,
249 <                      entry_plug->box_x,
250 <                      entry_plug->box_y,
251 <                      entry_plug->box_z );
252 <      
253 <      for( j=0; j<nAtoms; j++ ){
254 <
255 <        atoms[j]->setX(Rx[j]);
256 <        atoms[j]->setY(Ry[j]);
257 <        atoms[j]->setZ(Rz[j]);
258 <        
259 <        atoms[j]->set_vx(Vx[j]);
260 <        atoms[j]->set_vy(Vy[j]);
261 <        atoms[j]->set_vz(Vz[j]);
229 >    if( info->setTemp ){
230 >      if( currTime >= currThermal ){
231 >        tStats->velocitize();
232 >        currThermal += thermalTime;
233        }
234 +    }
235  
236 +    if( currTime >= currSample ){
237 +      dump_out->writeDump( currTime );
238 +      currSample += sampleTime;
239 +    }
240  
241 <      for( i=0; i<nAtoms; i++ ){
242 <        if( atoms[i]->isDirectional() ){
243 <                  
244 <          dAtom = (DirectionalAtom *)atoms[i];
241 >    if( currTime >= currStatus ){
242 >      e_out->writeStat( time * dt );
243 >      calcPot = 0;
244 >      calcStress = 0;
245 >      currStatus += statusTime;
246 >    }
247 >  }
248 >
249 >  dump_out->writeFinal();
250 >
251 >  delete dump_out;
252 >  delete e_out;
253 > }
254 >
255 > void Integrator::integrateStep( int calcPot, int calcStress ){
256 >
257 >  // Position full step, and velocity half step
258 >
259 >  preMove();
260 >  moveA();
261 >  if( nConstrained ) constrainA();
262 >
263 >  // calc forces
264 >
265 >  myFF->doForces(calcPot,calcStress);
266 >
267 >  // finish the velocity  half step
268 >  
269 >  moveB();
270 >  if( nConstrained ) constrainB();
271 >  
272 > }
273 >
274 >
275 > void Integrator::moveA( void ){
276 >  
277 >  int i,j,k;
278 >  int atomIndex, aMatIndex;
279 >  DirectionalAtom* dAtom;
280 >  double Tb[3];
281 >  double ji[3];
282 >
283 >  for( i=0; i<nAtoms; i++ ){
284 >    atomIndex = i * 3;
285 >    aMatIndex = i * 9;
286 >    
287 >    // velocity half step
288 >    for( j=atomIndex; j<(atomIndex+3); j++ )
289 >      vel[j] += ( dt2 * frc[j] / atoms[i]->getMass() ) * eConvert;
290 >
291 >    // position whole step    
292 >    for( j=atomIndex; j<(atomIndex+3); j++ )
293 >      pos[j] += dt * vel[j];
294 >
295 >  
296 >    if( atoms[i]->isDirectional() ){
297 >
298 >      dAtom = (DirectionalAtom *)atoms[i];
299            
300 <          // get and convert the torque to body frame
271 <          
272 <          Tb[0] = dAtom->getTx();
273 <          Tb[1] = dAtom->getTy();
274 <          Tb[2] = dAtom->getTz();
275 <          
276 <          dAtom->lab2Body( Tb );
277 <          
278 <          // get the angular momentum, and propagate a half step
279 <          
280 <          ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * e_convert;
281 <          ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * e_convert;
282 <          ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * e_convert;
283 <          
284 <          // get the atom's rotation matrix
285 <          
286 <          A[0][0] = dAtom->getAxx();
287 <          A[0][1] = dAtom->getAxy();
288 <          A[0][2] = dAtom->getAxz();
289 <          
290 <          A[1][0] = dAtom->getAyx();
291 <          A[1][1] = dAtom->getAyy();
292 <          A[1][2] = dAtom->getAyz();
293 <          
294 <          A[2][0] = dAtom->getAzx();
295 <          A[2][1] = dAtom->getAzy();
296 <          A[2][2] = dAtom->getAzz();
297 <          
298 <          
299 <          // use the angular velocities to propagate the rotation matrix a
300 <          // full time step
301 <          
302 <          
303 <          angle = dt2 * ji[0] / dAtom->getIxx();
304 <          this->rotate( 1, 2, angle, ji, A ); // rotate about the x-axis
305 <          
306 <          angle = dt2 * ji[1] / dAtom->getIyy();
307 <          this->rotate( 2, 0, angle, ji, A ); // rotate about the y-axis
308 <          
309 <          angle = dt * ji[2] / dAtom->getIzz();
310 <          this->rotate( 0, 1, angle, ji, A ); // rotate about the z-axis
311 <          
312 <          angle = dt2 * ji[1] / dAtom->getIyy();
313 <          this->rotate( 2, 0, angle, ji, A ); // rotate about the y-axis
314 <          
315 <          angle = dt2 * ji[0] / dAtom->getIxx();
316 <          this->rotate( 1, 2, angle, ji, A ); // rotate about the x-axis
317 <          
318 <          
319 <          dAtom->setA( A );
320 <          dAtom->setJx( ji[0] );
321 <          dAtom->setJy( ji[1] );
322 <          dAtom->setJz( ji[2] );
323 <        }
324 <      }
300 >      // get and convert the torque to body frame
301        
302 <      // calculate the forces
302 >      Tb[0] = dAtom->getTx();
303 >      Tb[1] = dAtom->getTy();
304 >      Tb[2] = dAtom->getTz();
305        
306 <      myFF->doForces(calcPot, 0);
306 >      dAtom->lab2Body( Tb );
307        
308 <      // move b
308 >      // get the angular momentum, and propagate a half step
309 >      
310 >      ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * eConvert;
311 >      ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * eConvert;
312 >      ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * eConvert;
313 >      
314 >      // use the angular velocities to propagate the rotation matrix a
315 >      // full time step
316 >      
317 >      // rotate about the x-axis      
318 >      angle = dt2 * ji[0] / dAtom->getIxx();
319 >      this->rotate( 1, 2, angle, ji, &aMat[aMatIndex] );
320 >      
321 >      // rotate about the y-axis
322 >      angle = dt2 * ji[1] / dAtom->getIyy();
323 >      this->rotate( 2, 0, angle, ji, &aMat[aMatIndex] );
324 >      
325 >      // rotate about the z-axis
326 >      angle = dt * ji[2] / dAtom->getIzz();
327 >      this->rotate( 0, 1, angle, ji, &aMat[aMatIndex] );
328 >      
329 >      // rotate about the y-axis
330 >      angle = dt2 * ji[1] / dAtom->getIyy();
331 >      this->rotate( 2, 0, angle, ji, &aMat[aMatIndex] );
332 >      
333 >       // rotate about the x-axis
334 >      angle = dt2 * ji[0] / dAtom->getIxx();
335 >      this->rotate( 1, 2, angle, ji, &aMat[aMatIndex] );
336 >      
337 >      dAtom->setJx( ji[0] );
338 >      dAtom->setJy( ji[1] );
339 >      dAtom->setJz( ji[2] );
340 >    }
341 >    
342 >  }
343 > }
344  
332      for( j=0; j<nAtoms; j++ ){
345  
346 <        Rx[j] = atoms[j]->getX();
347 <        Ry[j] = atoms[j]->getY();
348 <        Rz[j] = atoms[j]->getZ();
346 > void Integrator::moveB( void ){
347 >  int i,j,k;
348 >  int atomIndex;
349 >  DirectionalAtom* dAtom;
350 >  double Tb[3];
351 >  double ji[3];
352  
353 <        Vx[j] = atoms[j]->get_vx();
354 <        Vy[j] = atoms[j]->get_vy();
340 <        Vz[j] = atoms[j]->get_vz();
353 >  for( i=0; i<nAtoms; i++ ){
354 >    atomIndex = i * 3;
355  
356 <        Fx[j] = atoms[j]->getFx();
357 <        Fy[j] = atoms[j]->getFy();
358 <        Fz[j] = atoms[j]->getFz();
345 <      }
346 <        
347 <      v_constrain_b_( dt, nAtoms, mass, Rx, Ry, Rz, Vx, Vy, Vz,
348 <                      Fx, Fy, Fz,
349 <                      kE, n_constrained, constrained_dsqr,
350 <                      constrained_i, constrained_j,
351 <                      entry_plug->box_x,
352 <                      entry_plug->box_y,
353 <                      entry_plug->box_z );
354 <      
355 <      for( j=0; j<nAtoms; j++ ){
356 >    // velocity half step
357 >    for( j=atomIndex; j<(atomIndex+3); j++ )
358 >      vel[j] += ( dt2 * frc[j] / atoms[i]->getMass() ) * eConvert;
359  
360 <        atoms[j]->setX(Rx[j]);
358 <        atoms[j]->setY(Ry[j]);
359 <        atoms[j]->setZ(Rz[j]);
360 <
361 <        atoms[j]->set_vx(Vx[j]);
362 <        atoms[j]->set_vy(Vy[j]);
363 <        atoms[j]->set_vz(Vz[j]);
364 <      }
360 >    if( atoms[i]->isDirectional() ){
361        
362 <      for( i=0; i< nAtoms; i++ ){
367 <
368 <        if( atoms[i]->isDirectional() ){
369 <
370 <          dAtom = (DirectionalAtom *)atoms[i];
371 <          
372 <          // get and convert the torque to body frame
373 <          
374 <          Tb[0] = dAtom->getTx();
375 <          Tb[1] = dAtom->getTy();
376 <          Tb[2] = dAtom->getTz();
377 <          
378 <          dAtom->lab2Body( Tb );
379 <          
380 <          // get the angular momentum, and complete the angular momentum
381 <          // half step
382 <          
383 <          ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * e_convert;
384 <          ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * e_convert;
385 <          ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * e_convert;
386 <          
387 <          dAtom->setJx( ji[0] );
388 <          dAtom->setJy( ji[1] );
389 <          dAtom->setJz( ji[2] );
390 <        }
391 <      }
392 <    
393 <      time = tl + 1;
362 >      dAtom = (DirectionalAtom *)atoms[i];
363        
364 <      if( entry_plug->setTemp ){
365 <        if( !(time % vel_n) ) tStats->velocitize();
366 <      }
367 <      if( !(time % sample_n) ) dump_out->writeDump( time * dt );
368 <      if( !((time+1) % status_n) ) calcPot = 1;
369 <      if( !(time % status_n) ){ e_out->writeStat( time * dt ); calcPot = 0; }
364 >      // get and convert the torque to body frame
365 >      
366 >      Tb[0] = dAtom->getTx();
367 >      Tb[1] = dAtom->getTy();
368 >      Tb[2] = dAtom->getTz();
369 >      
370 >      dAtom->lab2Body( Tb );
371 >      
372 >      // get the angular momentum, and complete the angular momentum
373 >      // half step
374 >      
375 >      ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * eConvert;
376 >      ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * eConvert;
377 >      ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * eConvert;
378 >      
379 >      jx2 = ji[0] * ji[0];
380 >      jy2 = ji[1] * ji[1];
381 >      jz2 = ji[2] * ji[2];
382 >      
383 >      dAtom->setJx( ji[0] );
384 >      dAtom->setJy( ji[1] );
385 >      dAtom->setJz( ji[2] );
386      }
387    }
403  else{
388  
389 <    for( tl=0; tl<n_loops; tl++ ){
389 > }
390 >
391 > void Integrator::preMove( void ){
392 >  int i;
393 >
394 >  if( nConstrained ){
395 >    if( oldAtoms != nAtoms ){
396        
397 <      kE = 0.0;
408 <      rot_kE= 0.0;
409 <      trans_kE = 0.0;
397 >      // save oldAtoms to check for lode balanceing later on.
398        
399 <      for( i=0; i<nAtoms; i++ ){
412 <        
413 <        // velocity half step
414 <        
415 <        vx = atoms[i]->get_vx() +
416 <          ( dt2 * atoms[i]->getFx() / atoms[i]->getMass() ) * e_convert;
417 <        vy = atoms[i]->get_vy() +
418 <          ( dt2 * atoms[i]->getFy() / atoms[i]->getMass() ) * e_convert;
419 <        vz = atoms[i]->get_vz() +
420 <          ( dt2 * atoms[i]->getFz() / atoms[i]->getMass() ) * e_convert;
421 <        
422 <        // position whole step
423 <        
424 <        rx = atoms[i]->getX() + dt * vx;
425 <        ry = atoms[i]->getY() + dt * vy;
426 <        rz = atoms[i]->getZ() + dt * vz;
427 <        
428 <        atoms[i]->setX( rx );
429 <        atoms[i]->setY( ry );
430 <        atoms[i]->setZ( rz );
431 <        
432 <        atoms[i]->set_vx( vx );
433 <        atoms[i]->set_vy( vy );
434 <        atoms[i]->set_vz( vz );
435 <        
436 <        if( atoms[i]->isDirectional() ){
437 <
438 <          dAtom = (DirectionalAtom *)atoms[i];
439 <          
440 <          // get and convert the torque to body frame
441 <          
442 <          Tb[0] = dAtom->getTx();
443 <          Tb[1] = dAtom->getTy();
444 <          Tb[2] = dAtom->getTz();
445 <          
446 <          dAtom->lab2Body( Tb );
447 <          
448 <          // get the angular momentum, and propagate a half step
449 <          
450 <          ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * e_convert;
451 <          ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * e_convert;
452 <          ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * e_convert;
453 <          
454 <          // get the atom's rotation matrix
455 <          
456 <          A[0][0] = dAtom->getAxx();
457 <          A[0][1] = dAtom->getAxy();
458 <          A[0][2] = dAtom->getAxz();
459 <          
460 <          A[1][0] = dAtom->getAyx();
461 <          A[1][1] = dAtom->getAyy();
462 <          A[1][2] = dAtom->getAyz();
463 <          
464 <          A[2][0] = dAtom->getAzx();
465 <          A[2][1] = dAtom->getAzy();
466 <          A[2][2] = dAtom->getAzz();
467 <          
468 <          
469 <          // use the angular velocities to propagate the rotation matrix a
470 <          // full time step
471 <          
472 <          
473 <          angle = dt2 * ji[0] / dAtom->getIxx();
474 <          this->rotate( 1, 2, angle, ji, A ); // rotate about the x-axis
475 <          
476 <          angle = dt2 * ji[1] / dAtom->getIyy();
477 <          this->rotate( 2, 0, angle, ji, A ); // rotate about the y-axis
478 <          
479 <          angle = dt * ji[2] / dAtom->getIzz();
480 <          this->rotate( 0, 1, angle, ji, A ); // rotate about the z-axis
481 <          
482 <          angle = dt2 * ji[1] / dAtom->getIyy();
483 <          this->rotate( 2, 0, angle, ji, A ); // rotate about the y-axis
484 <          
485 <          angle = dt2 * ji[0] / dAtom->getIxx();
486 <          this->rotate( 1, 2, angle, ji, A ); // rotate about the x-axis
487 <          
488 <          
489 <          dAtom->setA( A );
490 <          dAtom->setJx( ji[0] );
491 <          dAtom->setJy( ji[1] );
492 <          dAtom->setJz( ji[2] );
493 <        }
494 <      }
399 >      oldAtoms = nAtoms;
400        
401 <      // calculate the forces
401 >      delete[] moving;
402 >      delete[] moved;
403 >      delete[] oldPos;
404        
405 <      myFF->doForces(calcPot,0);
405 >      moving = new int[nAtoms];
406 >      moved  = new int[nAtoms];
407        
408 <      for( i=0; i< nAtoms; i++ ){
408 >      oldPos = new double[nAtoms*3];
409 >    }
410 >  
411 >    for(i=0; i<(nAtoms*3); i++) oldPos[i] = pos[i];
412 >  }
413 > }  
414 >
415 > void Integrator::constrainA(){
416 >
417 >  int i,j,k;
418 >  int done;
419 >  double pxab, pyab, pzab;
420 >  double rxab, ryab, rzab;
421 >  int a, b;
422 >  double rma, rmb;
423 >  double dx, dy, dz;
424 >  double rabsq, pabsq, rpabsq;
425 >  double diffsq;
426 >  double gab;
427 >  int iteration;
428 >
429 >
430 >  
431 >  for( i=0; i<nAtoms; i++){
432 >    
433 >    moving[i] = 0;
434 >    moved[i]  = 1;
435 >  }
436 >  
437 >  
438 >  iteration = 0;
439 >  done = 0;
440 >  while( !done && (iteration < maxIteration )){
441 >
442 >    done = 1;
443 >    for(i=0; i<nConstrained; i++){
444 >
445 >      a = constrainedA[i];
446 >      b = constrainedB[i];
447 >    
448 >      if( moved[a] || moved[b] ){
449          
450 <        // complete the velocity half step
451 <        
452 <        vx = atoms[i]->get_vx() +
505 <          ( dt2 * atoms[i]->getFx() / atoms[i]->getMass() ) * e_convert;
506 <        vy = atoms[i]->get_vy() +
507 <          ( dt2 * atoms[i]->getFy() / atoms[i]->getMass() ) * e_convert;
508 <        vz = atoms[i]->get_vz() +
509 <          ( dt2 * atoms[i]->getFz() / atoms[i]->getMass() ) * e_convert;
510 <        
511 <        atoms[i]->set_vx( vx );
512 <        atoms[i]->set_vy( vy );
513 <        atoms[i]->set_vz( vz );
514 <        
515 < //      vx2 = vx * vx;
516 < //      vy2 = vy * vy;
517 < //      vz2 = vz * vz;
518 <        
519 <        if( atoms[i]->isDirectional() ){
450 >        pxab = pos[3*a+0] - pos[3*b+0];
451 >        pyab = pos[3*a+1] - pos[3*b+1];
452 >        pzab = pos[3*a+2] - pos[3*b+2];
453  
454 <          dAtom = (DirectionalAtom *)atoms[i];
455 <          
456 <          // get and convert the torque to body frame
454 >        //periodic boundary condition
455 >        pxab = pxab - info->box_x * copysign(1, pxab)
456 >          * int(pxab / info->box_x + 0.5);
457 >        pyab = pyab - info->box_y * copysign(1, pyab)
458 >          * int(pyab / info->box_y + 0.5);
459 >        pzab = pzab - info->box_z * copysign(1, pzab)
460 >          * int(pzab / info->box_z + 0.5);
461 >      
462 >        pabsq = pxab * pxab + pyab * pyab + pzab * pzab;
463 >        rabsq = constraintedDsqr[i];
464 >        diffsq = pabsq - rabsq;
465 >
466 >        // the original rattle code from alan tidesley
467 >        if (fabs(diffsq) > tol*rabsq*2) {
468 >          rxab = oldPos[3*a+0] - oldPos[3*b+0];
469 >          ryab = oldPos[3*a+1] - oldPos[3*b+1];
470 >          rzab = oldPos[3*a+2] - oldPos[3*b+2];
471 >
472 >          rxab = rxab - info->box_x * copysign(1, rxab)
473 >            * int(rxab / info->box_x + 0.5);
474 >          ryab = ryab - info->box_y * copysign(1, ryab)
475 >            * int(ryab / info->box_y + 0.5);
476 >          rzab = rzab - info->box_z * copysign(1, rzab)
477 >            * int(rzab / info->box_z + 0.5);
478 >
479 >          rpab = rxab * pxab + ryab * pyab + rzab * pzab;
480 >          rpabsq = rpab * rpab;
481 >
482 >
483 >          if (rpabsq < (rabsq * -diffsq)){
484 > #ifdef IS_MPI
485 >            a = atoms[a]->getGlobalIndex();
486 >            b = atoms[b]->getGlobalIndex();
487 > #endif //is_mpi
488 >            sprintf( painCave.errMsg,
489 >                     "Constraint failure in constrainA at atom %d and %d\n.",
490 >                     a, b );
491 >            painCave.isFatal = 1;
492 >            simError();
493 >          }
494 >
495 >          rma = 1.0 / atoms[a]->getMass();
496 >          rmb = 1.0 / atoms[b]->getMass();
497            
498 <          Tb[0] = dAtom->getTx();
499 <          Tb[1] = dAtom->getTy();
500 <          Tb[2] = dAtom->getTz();
498 >          gab = diffsq / ( 2.0 * ( rma + rmb ) * rpab );
499 >          dx = rxab * gab;
500 >          dy = ryab * gab;
501 >          dz = rzab * gab;
502 >
503 >          pos[3*a+0] += rma * dx;
504 >          pos[3*a+1] += rma * dy;
505 >          pos[3*a+2] += rma * dz;
506 >
507 >          pos[3*b+0] -= rmb * dx;
508 >          pos[3*b+1] -= rmb * dy;
509 >          pos[3*b+2] -= rmb * dz;
510 >
511 >          dx = dx / dt;
512 >          dy = dy / dt;
513 >          dz = dz / dt;
514 >
515 >          vel[3*a+0] += rma * dx;
516 >          vel[3*a+1] += rma * dy;
517 >          vel[3*a+2] += rma * dz;
518 >
519 >          vel[3*b+0] -= rmb * dx;
520 >          vel[3*b+1] -= rmb * dy;
521 >          vel[3*b+2] -= rmb * dz;
522 >
523 >          moving[a] = 1;
524 >          moving[b] = 1;
525 >          done = 0;
526 >        }
527 >      }
528 >    }
529 >    
530 >    for(i=0; i<nAtoms; i++){
531 >      
532 >      moved[i] = moving[i];
533 >      moving[i] = 0;
534 >    }
535 >
536 >    iteration++;
537 >  }
538 >
539 >  if( !done ){
540 >
541 >    sprintf( painCae.errMsg,
542 >             "Constraint failure in constrainA, too many iterations: %d\n",
543 >             iterations );
544 >    painCave.isFatal = 1;
545 >    simError();
546 >  }
547 >
548 > }
549 >
550 > void Integrator::constrainB( void ){
551 >  
552 >  int i,j,k;
553 >  int done;
554 >  double vxab, vyab, vzab;
555 >  double rxab, ryab, rzab;
556 >  int a, b;
557 >  double rma, rmb;
558 >  double dx, dy, dz;
559 >  double rabsq, pabsq, rvab;
560 >  double diffsq;
561 >  double gab;
562 >  int iteration;
563 >
564 >  for(i=0; i<nAtom; i++){
565 >    moving[i] = 0;
566 >    moved[i] = 1;
567 >  }
568 >
569 >  done = 0;
570 >  while( !done && (iteration < maxIteration ) ){
571 >
572 >    for(i=0; i<nConstrained; i++){
573 >      
574 >      a = constrainedA[i];
575 >      b = constrainedB[i];
576 >
577 >      if( moved[a] || moved[b] ){
578 >        
579 >        vxab = vel[3*a+0] - vel[3*b+0];
580 >        vyab = vel[3*a+1] - vel[3*b+1];
581 >        vzab = vel[3*a+2] - vel[3*b+2];
582 >
583 >        rxab = pos[3*a+0] - pos[3*b+0];q
584 >        ryab = pos[3*a+1] - pos[3*b+1];
585 >        rzab = pos[3*a+2] - pos[3*b+2];
586 >        
587 >        rxab = rxab - info->box_x * copysign(1, rxab)
588 >          * int(rxab / info->box_x + 0.5);
589 >        ryab = ryab - info->box_y * copysign(1, ryab)
590 >          * int(ryab / info->box_y + 0.5);
591 >        rzab = rzab - info->box_z * copysign(1, rzab)
592 >          * int(rzab / info->box_z + 0.5);
593 >
594 >        rma = 1.0 / atoms[a]->getMass();
595 >        rmb = 1.0 / atoms[b]->getMass();
596 >
597 >        rvab = rxab * vxab + ryab * vyab + rzab * vzab;
598            
599 <          dAtom->lab2Body( Tb );
599 >        gab = -rvab / ( ( rma + rmb ) * constraintsDsqr[i] );
600 >
601 >        if (fabs(gab) > tol) {
602            
603 <          // get the angular momentum, and complete the angular momentum
604 <          // half step
603 >          dx = rxab * gab;
604 >          dy = ryab * gab;
605 >          dz = rzab * gab;
606            
607 <          ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * e_convert;
608 <          ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * e_convert;
609 <          ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * e_convert;
607 >          vel[3*a+0] += rma * dx;
608 >          vel[3*a+1] += rma * dy;
609 >          vel[3*a+2] += rma * dz;
610 >
611 >          vel[3*b+0] -= rmb * dx;
612 >          vel[3*b+1] -= rmb * dy;
613 >          vel[3*b+2] -= rmb * dz;
614            
615 <          jx2 = ji[0] * ji[0];
616 <          jy2 = ji[1] * ji[1];
617 <          jz2 = ji[2] * ji[2];
541 <          
542 <          rot_kE += (jx2 / dAtom->getIxx()) + (jy2 / dAtom->getIyy())
543 <            + (jz2 / dAtom->getIzz());
544 <          
545 <          dAtom->setJx( ji[0] );
546 <          dAtom->setJy( ji[1] );
547 <          dAtom->setJz( ji[2] );
615 >          moving[a] = 1;
616 >          moving[b] = 1;
617 >          done = 0;
618          }
619        }
550      
551      time = tl + 1;
552      
553      if( entry_plug->setTemp ){
554        if( !(time % vel_n) ) tStats->velocitize();
555      }
556      if( !(time % sample_n) ) dump_out->writeDump( time * dt );
557      if( !((time+1) % status_n) ) calcPot = 1;
558      if( !(time % status_n) ){ e_out->writeStat( time * dt ); calcPot = 0; }
620      }
621 +
622 +    for(i=0; i<nAtoms; i++){
623 +      moved[i] = moving[i];
624 +      moving[i] = 0;
625 +    }
626 +    
627 +    iteration++;
628    }
629  
630 <  dump_out->writeFinal();
630 >  if( !done ){
631  
632 <  delete dump_out;
633 <  delete e_out;
632 >  
633 >    sprintf( painCae.errMsg,
634 >             "Constraint failure in constrainB, too many iterations: %d\n",
635 >             iterations );
636 >    painCave.isFatal = 1;
637 >    simError();
638 >  }
639 >
640   }
641  
642 < void Symplectic::rotate( int axes1, int axes2, double angle, double ji[3],
642 >
643 >
644 >
645 >
646 >
647 >
648 > void Integrator::rotate( int axes1, int axes2, double angle, double ji[3],
649                           double A[3][3] ){
650  
651    int i,j,k;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines