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 428 by mmeineke, Thu Mar 27 21:07:14 2003 UTC vs.
Revision 548 by mmeineke, Wed Jun 4 21:06:45 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"
10   #include "simError.h"
11  
10 extern "C"{
11  
12  void v_constrain_a_( double &dt, int &n_atoms, double* mass,
13                       double* Rx, double* Ry, double* Rz,
14                       double* Vx, double* Vy, double* Vz,
15                       double* Fx, double* Fy, double* Fz,
16                       int &n_constrained, double *constr_sqr,
17                       int* constr_i, int* constr_j,
18                       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,
23 <                       double* Fx, double* Fy, double* Fz,
24 <                       double &Kinetic,
25 <                       int &n_constrained, double *constr_sqr,
26 <                       int* constr_i, int* constr_j,
27 <                       double &box_x, double &box_y, double &box_z );
28 < }
29 <
30 <
31 <
32 <
33 < Symplectic::Symplectic( SimInfo* the_entry_plug, ForceFields* the_ff ){
34 <  entry_plug = the_entry_plug;
13 > Integrator::Integrator( SimInfo* theInfo, ForceFields* the_ff ){
14 >  
15 >  info = theInfo;
16    myFF = the_ff;
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  
29 <  mass = new double[entry_plug->n_atoms];
30 <  for(int i = 0; i < entry_plug->n_atoms; i++){
31 <    mass[i] = entry_plug->atoms[i]->getMass();
32 <  }
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 +  checkConstraints();
41 + }
42 +
43 + Integrator::~Integrator() {
44    
45 <
46 <  // check for constraints
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 <  is_constrained = 0;
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 73 | 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 90 | 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 107 | 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;
132 <      constrained_j[i] = temp_con[i].get_b() + 1;
133 <      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  
140 Symplectic::~Symplectic() {
141  
142  if( n_constrained ){
143    delete[] constrained_i;
144    delete[] constrained_j;
145    delete[] constrained_dsqr;
146  }
147  
148 }
156  
157 + void Integrator::integrate( void ){
158  
151 void Symplectic::integrate( void ){
152
153  const double e_convert = 4.184e-4; // converts kcal/mol -> amu*A^2/fs^2
154
159    int i, j;                         // loop counters
156  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 161 | 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 169 | 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;
178  
179 <  double dt          = entry_plug->dt;
180 <  double runTime     = entry_plug->run_time;
181 <  double sampleTime  = entry_plug->sampleTime;
182 <  double statusTime  = entry_plug->statusTime;
183 <  double thermalTime = entry_plug->thermalTime;
179 >  double dt          = info->dt;
180 >  double runTime     = info->run_time;
181 >  double sampleTime  = info->sampleTime;
182 >  double statusTime  = info->statusTime;
183 >  double thermalTime = info->thermalTime;
184  
185    int n_loops  = (int)( runTime / dt );
186    int sample_n = (int)( sampleTime / dt );
187    int status_n = (int)( statusTime / dt );
188    int vel_n    = (int)( thermalTime / dt );
189  
190 <  int calcPot;
190 >  int calcPot, calcStress;
191 >  int isError;
192  
193 <   Thermo *tStats = new Thermo( entry_plug );
193 >  tStats   = new Thermo( info );
194 >  e_out    = new StatWriter( info );
195 >  dump_out = new DumpWriter( info );
196  
197 <  StatWriter*  e_out    = new StatWriter( entry_plug );
191 <  DumpWriter*  dump_out = new DumpWriter( entry_plug );
192 <
193 <  Atom** atoms = entry_plug->atoms;
197 >  Atom** atoms = info->atoms;
198    DirectionalAtom* dAtom;
199    dt2 = 0.5 * dt;
200  
201 <  // initialize the forces the before the first step
201 >  // initialize the forces before the first step
202  
203 <  myFF->doForces(1,0);
203 >  myFF->doForces(1,1);
204    
205 <  if( entry_plug->setTemp ){
205 >  if( info->setTemp ){
206      
207      tStats->velocitize();
208    }
# Line 208 | Line 212 | void Symplectic::integrate( void ){
212    
213    calcPot = 0;
214  
215 <  if( n_constrained ){
215 >  for( tl=0; tl<nLoops; tl++){
216  
217 <    double *Rx = new double[nAtoms];
218 <    double *Ry = new double[nAtoms];
219 <    double *Rz = new double[nAtoms];
217 >    integrateStep( calcPot, calcStress );
218 >      
219 >    time = tl + 1;
220      
221 <    double *Vx = new double[nAtoms];
222 <    double *Vy = new double[nAtoms];
223 <    double *Vz = new double[nAtoms];
224 <    
225 <    double *Fx = new double[nAtoms];
226 <    double *Fy = new double[nAtoms];
227 <    double *Fz = new double[nAtoms];
228 <    
221 >    if( info->setTemp ){
222 >      if( !(time % vel_n) ) tStats->velocitize();
223 >    }
224 >    if( !(time % sample_n) ) dump_out->writeDump( time * dt );
225 >    if( !((time+1) % status_n) ) {
226 >      calcPot = 1;
227 >      calcStress = 1;
228 >    }
229 >    if( !(time % status_n) ){
230 >      e_out->writeStat( time * dt );
231 >      calcPot = 0;
232 >      if (!strcasecmp(info->ensemble, "NPT")) calcStress = 1;
233 >      else calcStress = 0;
234 >    }    
235  
236 <    for( tl=0; tl < n_loops; tl++ ){
237 <      
228 <      for( j=0; j<nAtoms; j++ ){
236 >  
237 >  }
238  
239 <        Rx[j] = atoms[j]->getX();
231 <        Ry[j] = atoms[j]->getY();
232 <        Rz[j] = atoms[j]->getZ();
239 >  dump_out->writeFinal();
240  
241 <        Vx[j] = atoms[j]->get_vx();
242 <        Vy[j] = atoms[j]->get_vy();
243 <        Vz[j] = atoms[j]->get_vz();
237 <
238 <        Fx[j] = atoms[j]->getFx();
239 <        Fy[j] = atoms[j]->getFy();
240 <        Fz[j] = atoms[j]->getFz();
241 >  delete dump_out;
242 >  delete e_out;
243 > }
244  
242      }
243        
244      v_constrain_a_( dt, nAtoms, mass, Rx, Ry, Rz, Vx, Vy, Vz,
245                      Fx, Fy, Fz,
246                      n_constrained, constrained_dsqr,
247                      constrained_i, constrained_j,
248                      entry_plug->box_x,
249                      entry_plug->box_y,
250                      entry_plug->box_z );
251      
252      for( j=0; j<nAtoms; j++ ){
245  
246 <        atoms[j]->setX(Rx[j]);
247 <        atoms[j]->setY(Ry[j]);
248 <        atoms[j]->setZ(Rz[j]);
249 <        
250 <        atoms[j]->set_vx(Vx[j]);
251 <        atoms[j]->set_vy(Vy[j]);
252 <        atoms[j]->set_vz(Vz[j]);
261 <      }
246 > void Integrator::moveA( void ){
247 >  
248 >  int i,j,k;
249 >  int atomIndex, aMatIndex;
250 >  DirectionalAtom* dAtom;
251 >  double Tb[3];
252 >  double ji[3];
253  
254 +  for( i=0; i<nAtoms; i++ ){
255 +    atomIndex = i * 3;
256 +    aMatIndex = i * 9;
257 +    
258 +    // velocity half step
259 +    for( j=atomIndex; j<(atomIndex+3); j++ )
260 +      vel[j] += ( dt2 * frc[j] / atoms[i]->getMass() ) * eConvert;
261  
262 <      for( i=0; i<nAtoms; i++ ){
263 <        if( atoms[i]->isDirectional() ){
264 <                  
265 <          dAtom = (DirectionalAtom *)atoms[i];
262 >    // position whole step    
263 >    for( j=atomIndex; j<(atomIndex+3); j++ )
264 >      pos[j] += dt * vel[j];
265 >
266 >  
267 >    if( atoms[i]->isDirectional() ){
268 >
269 >      dAtom = (DirectionalAtom *)atoms[i];
270            
271 <          // get and convert the torque to body frame
270 <          
271 <          Tb[0] = dAtom->getTx();
272 <          Tb[1] = dAtom->getTy();
273 <          Tb[2] = dAtom->getTz();
274 <          
275 <          dAtom->lab2Body( Tb );
276 <          
277 <          // get the angular momentum, and propagate a half step
278 <          
279 <          ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * e_convert;
280 <          ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * e_convert;
281 <          ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * e_convert;
282 <          
283 <          // get the atom's rotation matrix
284 <          
285 <          A[0][0] = dAtom->getAxx();
286 <          A[0][1] = dAtom->getAxy();
287 <          A[0][2] = dAtom->getAxz();
288 <          
289 <          A[1][0] = dAtom->getAyx();
290 <          A[1][1] = dAtom->getAyy();
291 <          A[1][2] = dAtom->getAyz();
292 <          
293 <          A[2][0] = dAtom->getAzx();
294 <          A[2][1] = dAtom->getAzy();
295 <          A[2][2] = dAtom->getAzz();
296 <          
297 <          
298 <          // use the angular velocities to propagate the rotation matrix a
299 <          // full time step
300 <          
301 <          
302 <          angle = dt2 * ji[0] / dAtom->getIxx();
303 <          this->rotate( 1, 2, angle, ji, A ); // rotate about the x-axis
304 <          
305 <          angle = dt2 * ji[1] / dAtom->getIyy();
306 <          this->rotate( 2, 0, angle, ji, A ); // rotate about the y-axis
307 <          
308 <          angle = dt * ji[2] / dAtom->getIzz();
309 <          this->rotate( 0, 1, angle, ji, A ); // rotate about the z-axis
310 <          
311 <          angle = dt2 * ji[1] / dAtom->getIyy();
312 <          this->rotate( 2, 0, angle, ji, A ); // rotate about the y-axis
313 <          
314 <          angle = dt2 * ji[0] / dAtom->getIxx();
315 <          this->rotate( 1, 2, angle, ji, A ); // rotate about the x-axis
316 <          
317 <          
318 <          dAtom->setA( A );
319 <          dAtom->setJx( ji[0] );
320 <          dAtom->setJy( ji[1] );
321 <          dAtom->setJz( ji[2] );
322 <        }
323 <      }
271 >      // get and convert the torque to body frame
272        
273 <      // calculate the forces
273 >      Tb[0] = dAtom->getTx();
274 >      Tb[1] = dAtom->getTy();
275 >      Tb[2] = dAtom->getTz();
276        
277 <      myFF->doForces(calcPot, 0);
277 >      dAtom->lab2Body( Tb );
278        
279 <      // move b
279 >      // get the angular momentum, and propagate a half step
280 >      
281 >      ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * eConvert;
282 >      ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * eConvert;
283 >      ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * eConvert;
284 >      
285 >      // use the angular velocities to propagate the rotation matrix a
286 >      // full time step
287 >      
288 >      // rotate about the x-axis      
289 >      angle = dt2 * ji[0] / dAtom->getIxx();
290 >      this->rotate( 1, 2, angle, ji, &aMat[aMatIndex] );
291 >      
292 >      // rotate about the y-axis
293 >      angle = dt2 * ji[1] / dAtom->getIyy();
294 >      this->rotate( 2, 0, angle, ji, &aMat[aMatIndex] );
295 >      
296 >      // rotate about the z-axis
297 >      angle = dt * ji[2] / dAtom->getIzz();
298 >      this->rotate( 0, 1, angle, ji, &aMat[aMatIndex] );
299 >      
300 >      // rotate about the y-axis
301 >      angle = dt2 * ji[1] / dAtom->getIyy();
302 >      this->rotate( 2, 0, angle, ji, &aMat[aMatIndex] );
303 >      
304 >       // rotate about the x-axis
305 >      angle = dt2 * ji[0] / dAtom->getIxx();
306 >      this->rotate( 1, 2, angle, ji, &aMat[aMatIndex] );
307 >      
308 >      dAtom->setJx( ji[0] );
309 >      dAtom->setJy( ji[1] );
310 >      dAtom->setJz( ji[2] );
311 >    }
312 >    
313 >  }
314 > }
315  
331      for( j=0; j<nAtoms; j++ ){
316  
317 <        Rx[j] = atoms[j]->getX();
318 <        Ry[j] = atoms[j]->getY();
319 <        Rz[j] = atoms[j]->getZ();
317 > void Integrator::moveB( void ){
318 >  int i,j,k;
319 >  int atomIndex;
320 >  DirectionalAtom* dAtom;
321 >  double Tb[3];
322 >  double ji[3];
323  
324 <        Vx[j] = atoms[j]->get_vx();
325 <        Vy[j] = atoms[j]->get_vy();
339 <        Vz[j] = atoms[j]->get_vz();
324 >  for( i=0; i<nAtoms; i++ ){
325 >    atomIndex = i * 3;
326  
327 <        Fx[j] = atoms[j]->getFx();
328 <        Fy[j] = atoms[j]->getFy();
329 <        Fz[j] = atoms[j]->getFz();
344 <      }
345 <        
346 <      v_constrain_b_( dt, nAtoms, mass, Rx, Ry, Rz, Vx, Vy, Vz,
347 <                      Fx, Fy, Fz,
348 <                      kE, n_constrained, constrained_dsqr,
349 <                      constrained_i, constrained_j,
350 <                      entry_plug->box_x,
351 <                      entry_plug->box_y,
352 <                      entry_plug->box_z );
353 <      
354 <      for( j=0; j<nAtoms; j++ ){
327 >    // velocity half step
328 >    for( j=atomIndex; j<(atomIndex+3); j++ )
329 >      vel[j] += ( dt2 * frc[j] / atoms[i]->getMass() ) * eConvert;
330  
331 <        atoms[j]->setX(Rx[j]);
357 <        atoms[j]->setY(Ry[j]);
358 <        atoms[j]->setZ(Rz[j]);
359 <
360 <        atoms[j]->set_vx(Vx[j]);
361 <        atoms[j]->set_vy(Vy[j]);
362 <        atoms[j]->set_vz(Vz[j]);
363 <      }
331 >    if( atoms[i]->isDirectional() ){
332        
333 <      for( i=0; i< nAtoms; i++ ){
334 <
335 <        if( atoms[i]->isDirectional() ){
336 <
337 <          dAtom = (DirectionalAtom *)atoms[i];
338 <          
339 <          // get and convert the torque to body frame
340 <          
341 <          Tb[0] = dAtom->getTx();
374 <          Tb[1] = dAtom->getTy();
375 <          Tb[2] = dAtom->getTz();
376 <          
377 <          dAtom->lab2Body( Tb );
378 <          
379 <          // get the angular momentum, and complete the angular momentum
380 <          // half step
381 <          
382 <          ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * e_convert;
383 <          ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * e_convert;
384 <          ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * e_convert;
385 <          
386 <          dAtom->setJx( ji[0] );
387 <          dAtom->setJy( ji[1] );
388 <          dAtom->setJz( ji[2] );
389 <        }
390 <      }
391 <    
392 <      time = tl + 1;
333 >      dAtom = (DirectionalAtom *)atoms[i];
334 >      
335 >      // get and convert the torque to body frame
336 >      
337 >      Tb[0] = dAtom->getTx();
338 >      Tb[1] = dAtom->getTy();
339 >      Tb[2] = dAtom->getTz();
340 >      
341 >      dAtom->lab2Body( Tb );
342        
343 <      if( entry_plug->setTemp ){
344 <        if( !(time % vel_n) ) tStats->velocitize();
345 <      }
346 <      if( !(time % sample_n) ) dump_out->writeDump( time * dt );
347 <      if( !((time+1) % status_n) ) calcPot = 1;
348 <      if( !(time % status_n) ){ e_out->writeStat( time * dt ); calcPot = 0; }
343 >      // get the angular momentum, and complete the angular momentum
344 >      // half step
345 >      
346 >      ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * eConvert;
347 >      ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * eConvert;
348 >      ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * eConvert;
349 >      
350 >      jx2 = ji[0] * ji[0];
351 >      jy2 = ji[1] * ji[1];
352 >      jz2 = ji[2] * ji[2];
353 >      
354 >      dAtom->setJx( ji[0] );
355 >      dAtom->setJy( ji[1] );
356 >      dAtom->setJz( ji[2] );
357      }
358    }
402  else{
359  
360 <    for( tl=0; tl<n_loops; tl++ ){
360 > }
361 >
362 > void Integrator::preMove( void ){
363 >  int i;
364 >
365 >  if( nConstrained ){
366 >    if( oldAtoms != nAtoms ){
367        
368 <      kE = 0.0;
407 <      rot_kE= 0.0;
408 <      trans_kE = 0.0;
368 >      // save oldAtoms to check for lode balanceing later on.
369        
370 <      for( i=0; i<nAtoms; i++ ){
411 <        
412 <        // velocity half step
413 <        
414 <        vx = atoms[i]->get_vx() +
415 <          ( dt2 * atoms[i]->getFx() / atoms[i]->getMass() ) * e_convert;
416 <        vy = atoms[i]->get_vy() +
417 <          ( dt2 * atoms[i]->getFy() / atoms[i]->getMass() ) * e_convert;
418 <        vz = atoms[i]->get_vz() +
419 <          ( dt2 * atoms[i]->getFz() / atoms[i]->getMass() ) * e_convert;
420 <        
421 <        // position whole step
422 <        
423 <        rx = atoms[i]->getX() + dt * vx;
424 <        ry = atoms[i]->getY() + dt * vy;
425 <        rz = atoms[i]->getZ() + dt * vz;
426 <        
427 <        atoms[i]->setX( rx );
428 <        atoms[i]->setY( ry );
429 <        atoms[i]->setZ( rz );
430 <        
431 <        atoms[i]->set_vx( vx );
432 <        atoms[i]->set_vy( vy );
433 <        atoms[i]->set_vz( vz );
434 <        
435 <        if( atoms[i]->isDirectional() ){
436 <
437 <          dAtom = (DirectionalAtom *)atoms[i];
438 <          
439 <          // get and convert the torque to body frame
440 <          
441 <          Tb[0] = dAtom->getTx();
442 <          Tb[1] = dAtom->getTy();
443 <          Tb[2] = dAtom->getTz();
444 <          
445 <          dAtom->lab2Body( Tb );
446 <          
447 <          // get the angular momentum, and propagate a half step
448 <          
449 <          ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * e_convert;
450 <          ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * e_convert;
451 <          ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * e_convert;
452 <          
453 <          // get the atom's rotation matrix
454 <          
455 <          A[0][0] = dAtom->getAxx();
456 <          A[0][1] = dAtom->getAxy();
457 <          A[0][2] = dAtom->getAxz();
458 <          
459 <          A[1][0] = dAtom->getAyx();
460 <          A[1][1] = dAtom->getAyy();
461 <          A[1][2] = dAtom->getAyz();
462 <          
463 <          A[2][0] = dAtom->getAzx();
464 <          A[2][1] = dAtom->getAzy();
465 <          A[2][2] = dAtom->getAzz();
466 <          
467 <          
468 <          // use the angular velocities to propagate the rotation matrix a
469 <          // full time step
470 <          
471 <          
472 <          angle = dt2 * ji[0] / dAtom->getIxx();
473 <          this->rotate( 1, 2, angle, ji, A ); // rotate about the x-axis
474 <          
475 <          angle = dt2 * ji[1] / dAtom->getIyy();
476 <          this->rotate( 2, 0, angle, ji, A ); // rotate about the y-axis
477 <          
478 <          angle = dt * ji[2] / dAtom->getIzz();
479 <          this->rotate( 0, 1, angle, ji, A ); // rotate about the z-axis
480 <          
481 <          angle = dt2 * ji[1] / dAtom->getIyy();
482 <          this->rotate( 2, 0, angle, ji, A ); // rotate about the y-axis
483 <          
484 <          angle = dt2 * ji[0] / dAtom->getIxx();
485 <          this->rotate( 1, 2, angle, ji, A ); // rotate about the x-axis
486 <          
487 <          
488 <          dAtom->setA( A );
489 <          dAtom->setJx( ji[0] );
490 <          dAtom->setJy( ji[1] );
491 <          dAtom->setJz( ji[2] );
492 <        }
493 <      }
370 >      oldAtoms = nAtoms;
371        
372 <      // calculate the forces
372 >      delete[] moving;
373 >      delete[] moved;
374 >      delete[] oldPos;
375        
376 <      myFF->doForces(calcPot,0);
376 >      moving = new int[nAtoms];
377 >      moved  = new int[nAtoms];
378        
379 <      for( i=0; i< nAtoms; i++ ){
379 >      oldPos = new double[nAtoms*3];
380 >    }
381 >  
382 >    for(i=0; i<(nAtoms*3); i++) oldPos[i] = pos[i];
383 >  }
384 > }  
385 >
386 > void Integrator::constrainA(){
387 >
388 >  int i,j,k;
389 >  int done;
390 >  double pxab, pyab, pzab;
391 >  double rxab, ryab, rzab;
392 >  int a, b;
393 >  double rma, rmb;
394 >  double dx, dy, dz;
395 >  double rabsq, pabsq, rpabsq;
396 >  double diffsq;
397 >  double gab;
398 >  int iteration;
399 >
400 >
401 >  
402 >  for( i=0; i<nAtoms; i++){
403 >    
404 >    moving[i] = 0;
405 >    moved[i]  = 1;
406 >  }
407 >  
408 >  
409 >  iteration = 0;
410 >  done = 0;
411 >  while( !done && (iteration < maxIteration )){
412 >
413 >    done = 1;
414 >    for(i=0; i<nConstrained; i++){
415 >
416 >      a = constrainedA[i];
417 >      b = constrainedB[i];
418 >    
419 >      if( moved[a] || moved[b] ){
420          
421 <        // complete the velocity half step
422 <        
423 <        vx = atoms[i]->get_vx() +
504 <          ( dt2 * atoms[i]->getFx() / atoms[i]->getMass() ) * e_convert;
505 <        vy = atoms[i]->get_vy() +
506 <          ( dt2 * atoms[i]->getFy() / atoms[i]->getMass() ) * e_convert;
507 <        vz = atoms[i]->get_vz() +
508 <          ( dt2 * atoms[i]->getFz() / atoms[i]->getMass() ) * e_convert;
509 <        
510 <        atoms[i]->set_vx( vx );
511 <        atoms[i]->set_vy( vy );
512 <        atoms[i]->set_vz( vz );
513 <        
514 < //      vx2 = vx * vx;
515 < //      vy2 = vy * vy;
516 < //      vz2 = vz * vz;
517 <        
518 <        if( atoms[i]->isDirectional() ){
421 >        pxab = pos[3*a+0] - pos[3*b+0];
422 >        pyab = pos[3*a+1] - pos[3*b+1];
423 >        pzab = pos[3*a+2] - pos[3*b+2];
424  
425 <          dAtom = (DirectionalAtom *)atoms[i];
426 <          
427 <          // get and convert the torque to body frame
428 <          
429 <          Tb[0] = dAtom->getTx();
430 <          Tb[1] = dAtom->getTy();
431 <          Tb[2] = dAtom->getTz();
432 <          
433 <          dAtom->lab2Body( Tb );
434 <          
435 <          // get the angular momentum, and complete the angular momentum
436 <          // half step
437 <          
438 <          ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * e_convert;
439 <          ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * e_convert;
440 <          ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * e_convert;
425 >        //periodic boundary condition
426 >        pxab = pxab - info->box_x * copysign(1, pxab)
427 >          * int(pxab / info->box_x + 0.5);
428 >        pyab = pyab - info->box_y * copysign(1, pyab)
429 >          * int(pyab / info->box_y + 0.5);
430 >        pzab = pzab - info->box_z * copysign(1, pzab)
431 >          * int(pzab / info->box_z + 0.5);
432 >      
433 >        pabsq = pxab * pxab + pyab * pyab + pzab * pzab;
434 >        rabsq = constraintedDsqr[i];
435 >        diffsq = pabsq - rabsq;
436 >
437 >        // the original rattle code from alan tidesley
438 >        if (fabs(diffsq) > tol*rabsq*2) {
439 >          rxab = oldPos[3*a+0] - oldPos[3*b+0];
440 >          ryab = oldPos[3*a+1] - oldPos[3*b+1];
441 >          rzab = oldPos[3*a+2] - oldPos[3*b+2];
442 >
443 >          rxab = rxab - info->box_x * copysign(1, rxab)
444 >            * int(rxab / info->box_x + 0.5);
445 >          ryab = ryab - info->box_y * copysign(1, ryab)
446 >            * int(ryab / info->box_y + 0.5);
447 >          rzab = rzab - info->box_z * copysign(1, rzab)
448 >            * int(rzab / info->box_z + 0.5);
449 >
450 >          rpab = rxab * pxab + ryab * pyab + rzab * pzab;
451 >          rpabsq = rpab * rpab;
452 >
453 >
454 >          if (rpabsq < (rabsq * -diffsq)){
455 > #ifdef IS_MPI
456 >            a = atoms[a]->getGlobalIndex();
457 >            b = atoms[b]->getGlobalIndex();
458 > #endif //is_mpi
459 >            sprintf( painCave.errMsg,
460 >                     "Constraint failure in constrainA at atom %d and %d\n.",
461 >                     a, b );
462 >            painCave.isFatal = 1;
463 >            simError();
464 >          }
465 >
466 >          rma = 1.0 / atoms[a]->getMass();
467 >          rmb = 1.0 / atoms[b]->getMass();
468            
469 <          jx2 = ji[0] * ji[0];
470 <          jy2 = ji[1] * ji[1];
471 <          jz2 = ji[2] * ji[2];
472 <          
473 <          rot_kE += (jx2 / dAtom->getIxx()) + (jy2 / dAtom->getIyy())
474 <            + (jz2 / dAtom->getIzz());
475 <          
476 <          dAtom->setJx( ji[0] );
477 <          dAtom->setJy( ji[1] );
478 <          dAtom->setJz( ji[2] );
469 >          gab = diffsq / ( 2.0 * ( rma + rmb ) * rpab );
470 >          dx = rxab * gab;
471 >          dy = ryab * gab;
472 >          dz = rzab * gab;
473 >
474 >          pos[3*a+0] += rma * dx;
475 >          pos[3*a+1] += rma * dy;
476 >          pos[3*a+2] += rma * dz;
477 >
478 >          pos[3*b+0] -= rmb * dx;
479 >          pos[3*b+1] -= rmb * dy;
480 >          pos[3*b+2] -= rmb * dz;
481 >
482 >          dx = dx / dt;
483 >          dy = dy / dt;
484 >          dz = dz / dt;
485 >
486 >          vel[3*a+0] += rma * dx;
487 >          vel[3*a+1] += rma * dy;
488 >          vel[3*a+2] += rma * dz;
489 >
490 >          vel[3*b+0] -= rmb * dx;
491 >          vel[3*b+1] -= rmb * dy;
492 >          vel[3*b+2] -= rmb * dz;
493 >
494 >          moving[a] = 1;
495 >          moving[b] = 1;
496 >          done = 0;
497          }
498        }
499 +    }
500 +    
501 +    for(i=0; i<nAtoms; i++){
502        
503 <      time = tl + 1;
503 >      moved[i] = moving[i];
504 >      moving[i] = 0;
505 >    }
506 >
507 >    iteration++;
508 >  }
509 >
510 >  if( !done ){
511 >
512 >    sprintf( painCae.errMsg,
513 >             "Constraint failure in constrainA, too many iterations: %d\n",
514 >             iterations );
515 >    painCave.isFatal = 1;
516 >    simError();
517 >  }
518 >
519 > }
520 >
521 > void Integrator::constrainB( void ){
522 >  
523 >  int i,j,k;
524 >  int done;
525 >  double vxab, vyab, vzab;
526 >  double rxab, ryab, rzab;
527 >  int a, b;
528 >  double rma, rmb;
529 >  double dx, dy, dz;
530 >  double rabsq, pabsq, rvab;
531 >  double diffsq;
532 >  double gab;
533 >  int iteration;
534 >
535 >  for(i=0; i<nAtom; i++){
536 >    moving[i] = 0;
537 >    moved[i] = 1;
538 >  }
539 >
540 >  done = 0;
541 >  while( !done && (iteration < maxIteration ) ){
542 >
543 >    for(i=0; i<nConstrained; i++){
544        
545 <      if( entry_plug->setTemp ){
546 <        if( !(time % vel_n) ) tStats->velocitize();
545 >      a = constrainedA[i];
546 >      b = constrainedB[i];
547 >
548 >      if( moved[a] || moved[b] ){
549 >        
550 >        vxab = vel[3*a+0] - vel[3*b+0];
551 >        vyab = vel[3*a+1] - vel[3*b+1];
552 >        vzab = vel[3*a+2] - vel[3*b+2];
553 >
554 >        rxab = pos[3*a+0] - pos[3*b+0];q
555 >        ryab = pos[3*a+1] - pos[3*b+1];
556 >        rzab = pos[3*a+2] - pos[3*b+2];
557 >        
558 >        rxab = rxab - info->box_x * copysign(1, rxab)
559 >          * int(rxab / info->box_x + 0.5);
560 >        ryab = ryab - info->box_y * copysign(1, ryab)
561 >          * int(ryab / info->box_y + 0.5);
562 >        rzab = rzab - info->box_z * copysign(1, rzab)
563 >          * int(rzab / info->box_z + 0.5);
564 >
565 >        rma = 1.0 / atoms[a]->getMass();
566 >        rmb = 1.0 / atoms[b]->getMass();
567 >
568 >        rvab = rxab * vxab + ryab * vyab + rzab * vzab;
569 >          
570 >        gab = -rvab / ( ( rma + rmb ) * constraintsDsqr[i] );
571 >
572 >        if (fabs(gab) > tol) {
573 >          
574 >          dx = rxab * gab;
575 >          dy = ryab * gab;
576 >          dz = rzab * gab;
577 >          
578 >          vel[3*a+0] += rma * dx;
579 >          vel[3*a+1] += rma * dy;
580 >          vel[3*a+2] += rma * dz;
581 >
582 >          vel[3*b+0] -= rmb * dx;
583 >          vel[3*b+1] -= rmb * dy;
584 >          vel[3*b+2] -= rmb * dz;
585 >          
586 >          moving[a] = 1;
587 >          moving[b] = 1;
588 >          done = 0;
589 >        }
590        }
555      if( !(time % sample_n) ) dump_out->writeDump( time * dt );
556      if( !((time+1) % status_n) ) calcPot = 1;
557      if( !(time % status_n) ){ e_out->writeStat( time * dt ); calcPot = 0; }
591      }
592 +
593 +    for(i=0; i<nAtoms; i++){
594 +      moved[i] = moving[i];
595 +      moving[i] = 0;
596 +    }
597 +    
598 +    iteration++;
599    }
600  
601 <  dump_out->writeFinal();
601 >  if( !done ){
602  
603 <  delete dump_out;
604 <  delete e_out;
603 >  
604 >    sprintf( painCae.errMsg,
605 >             "Constraint failure in constrainB, too many iterations: %d\n",
606 >             iterations );
607 >    painCave.isFatal = 1;
608 >    simError();
609 >  }
610 >
611   }
612  
613 < void Symplectic::rotate( int axes1, int axes2, double angle, double ji[3],
613 >
614 >
615 >
616 >
617 >
618 >
619 > void Integrator::rotate( int axes1, int axes2, double angle, double ji[3],
620                           double A[3][3] ){
621  
622    int i,j,k;
# Line 581 | Line 633 | void Symplectic::rotate( int axes1, int axes2, double
633  
634    for(i=0; i<3; i++){
635      for(j=0; j<3; j++){
636 <      tempA[i][j] = A[i][j];
636 >      tempA[j][i] = A[i][j];
637      }
638    }
639  
# Line 640 | Line 692 | void Symplectic::rotate( int axes1, int axes2, double
692      for(j=0; j<3; j++){
693        A[j][i] = 0.0;
694        for(k=0; k<3; k++){
695 <        A[j][i] += tempA[k][i] * rot[j][k];
695 >        A[j][i] += tempA[i][k] * rot[j][k];
696        }
697      }
698    }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines