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

Comparing trunk/OOPSE/libmdtools/NPTi.cpp (file contents):
Revision 577 by gezelter, Wed Jul 9 01:41:11 2003 UTC vs.
Revision 658 by tim, Thu Jul 31 15:35:07 2003 UTC

# Line 1 | Line 1
1 + #include <cmath>
2   #include "Atom.hpp"
3   #include "SRI.hpp"
4   #include "AbstractClasses.hpp"
# Line 19 | Line 20 | NPTi::NPTi ( SimInfo *theInfo, ForceFields* the_ff):
20   //
21   //    Hoover, W. G., 1986, Phys. Rev. A, 34, 2499.
22  
23 < NPTi::NPTi ( SimInfo *theInfo, ForceFields* the_ff):
24 <  Integrator( theInfo, the_ff )
23 > template<typename T> NPTi<T>::NPTi ( SimInfo *theInfo, ForceFields* the_ff):
24 >  T( theInfo, the_ff )
25   {
26    chi = 0.0;
27    eta = 0.0;
# Line 30 | Line 31 | void NPTi::moveA() {
31    have_target_pressure = 0;
32   }
33  
34 < void NPTi::moveA() {
34 > template<typename T> void NPTi<T>::moveA() {
35    
36 <  int i,j,k;
36 <  int atomIndex, aMatIndex;
36 >  int i, j;
37    DirectionalAtom* dAtom;
38 <  double Tb[3];
39 <  double ji[3];
38 >  double Tb[3], ji[3];
39 >  double A[3][3], I[3][3];
40 >  double angle, mass;
41 >  double vel[3], pos[3], frc[3];
42 >
43    double rj[3];
44    double instaTemp, instaPress, instaVol;
45 <  double tt2, tb2;
43 <  double angle;
45 >  double tt2, tb2, scaleFactor;
46  
47    tt2 = tauThermostat * tauThermostat;
48    tb2 = tauBarostat * tauBarostat;
# Line 49 | Line 51 | void NPTi::moveA() {
51    instaPress = tStats->getPressure();
52    instaVol = tStats->getVolume();
53    
54 <  // first evolve chi a half step
54 >   // first evolve chi a half step
55    
56    chi += dt2 * ( instaTemp / targetTemp - 1.0) / tt2;
57 <  eta += dt2 * ( instaVol * (instaPress - targetPressure) / (NkBT*tb2));
57 >  eta += dt2 * ( instaVol * (instaPress - targetPressure) /
58 >                 (p_convert*NkBT*tb2));
59  
60    for( i=0; i<nAtoms; i++ ){
61 <    atomIndex = i * 3;
62 <    aMatIndex = i * 9;
63 <    
61 <    // velocity half step
62 <    for( j=atomIndex; j<(atomIndex+3); j++ )
63 <      vel[j] += dt2 * ((frc[j]/atoms[i]->getMass())*eConvert
64 <                       - vel[j]*(chi+eta));
61 >    atoms[i]->getVel( vel );
62 >    atoms[i]->getPos( pos );
63 >    atoms[i]->getFrc( frc );
64  
65 <    // position whole step    
65 >    mass = atoms[i]->getMass();
66  
67 <    rj[0] = pos[atomIndex];
68 <    rj[1] = pos[atomIndex+1];
69 <    rj[2] = pos[atomIndex+2];
70 <    
67 >    for (j=0; j < 3; j++) {
68 >      vel[j] += dt2 * ((frc[j] / mass ) * eConvert - vel[j]*(chi+eta));
69 >      rj[j] = pos[j];
70 >    }
71 >
72 >    atoms[i]->setVel( vel );
73 >
74      info->wrapVector(rj);
75  
76 <    pos[atomIndex] += dt * (vel[atomIndex] + eta*rj[0]);
77 <    pos[atomIndex+1] += dt * (vel[atomIndex+1] + eta*rj[1]);
78 <    pos[atomIndex+2] += dt * (vel[atomIndex+2] + eta*rj[2]);
79 <  
76 >    for (j = 0; j < 3; j++)
77 >      pos[j] += dt * (vel[j] + eta*rj[j]);
78 >
79 >    atoms[i]->setPos( pos );
80 >
81      if( atoms[i]->isDirectional() ){
82  
83        dAtom = (DirectionalAtom *)atoms[i];
84            
85        // get and convert the torque to body frame
86        
87 <      Tb[0] = dAtom->getTx();
85 <      Tb[1] = dAtom->getTy();
86 <      Tb[2] = dAtom->getTz();
87 <      
87 >      dAtom->getTrq( Tb );
88        dAtom->lab2Body( Tb );
89        
90        // get the angular momentum, and propagate a half step
91  
92 <      ji[0] = dAtom->getJx();
93 <      ji[1] = dAtom->getJy();
94 <      ji[2] = dAtom->getJz();
92 >      dAtom->getJ( ji );
93 >
94 >      for (j=0; j < 3; j++)
95 >        ji[j] += dt2 * (Tb[j] * eConvert - ji[j]*chi);
96        
96      ji[0] += dt2 * (Tb[0] * eConvert - ji[0]*chi);
97      ji[1] += dt2 * (Tb[1] * eConvert - ji[1]*chi);
98      ji[2] += dt2 * (Tb[2] * eConvert - ji[2]*chi);
99      
97        // use the angular velocities to propagate the rotation matrix a
98        // full time step
99 <      
99 >
100 >      dAtom->getA(A);
101 >      dAtom->getI(I);
102 >    
103        // rotate about the x-axis      
104 <      angle = dt2 * ji[0] / dAtom->getIxx();
105 <      this->rotate( 1, 2, angle, ji, &Amat[aMatIndex] );
106 <      
104 >      angle = dt2 * ji[0] / I[0][0];
105 >      this->rotate( 1, 2, angle, ji, A );
106 >
107        // rotate about the y-axis
108 <      angle = dt2 * ji[1] / dAtom->getIyy();
109 <      this->rotate( 2, 0, angle, ji, &Amat[aMatIndex] );
108 >      angle = dt2 * ji[1] / I[1][1];
109 >      this->rotate( 2, 0, angle, ji, A );
110        
111        // rotate about the z-axis
112 <      angle = dt * ji[2] / dAtom->getIzz();
113 <      this->rotate( 0, 1, angle, ji, &Amat[aMatIndex] );
112 >      angle = dt * ji[2] / I[2][2];
113 >      this->rotate( 0, 1, angle, ji, A);
114        
115        // rotate about the y-axis
116 <      angle = dt2 * ji[1] / dAtom->getIyy();
117 <      this->rotate( 2, 0, angle, ji, &Amat[aMatIndex] );
116 >      angle = dt2 * ji[1] / I[1][1];
117 >      this->rotate( 2, 0, angle, ji, A );
118        
119         // rotate about the x-axis
120 <      angle = dt2 * ji[0] / dAtom->getIxx();
121 <      this->rotate( 1, 2, angle, ji, &Amat[aMatIndex] );
120 >      angle = dt2 * ji[0] / I[0][0];
121 >      this->rotate( 1, 2, angle, ji, A );
122        
123 <      dAtom->setJx( ji[0] );
124 <      dAtom->setJy( ji[1] );
125 <      dAtom->setJz( ji[2] );
126 <    }
127 <    
123 >      dAtom->setJ( ji );
124 >      dAtom->setA( A  );    
125 >    }                
126 >
127    }
128 +
129    // Scale the box after all the positions have been moved:
130 +  
131 +  scaleFactor = exp(dt*eta);
132  
133 <  info->scaleBox(exp(dt*eta));
133 >  if ((scaleFactor > 1.1) || (scaleFactor < 0.9)) {
134 >    sprintf( painCave.errMsg,
135 >             "NPTi error: Attempting a Box scaling of more than 10 percent"
136 >             " check your tauBarostat, as it is probably too small!\n"
137 >             " eta = %lf, scaleFactor = %lf\n", eta, scaleFactor
138 >             );
139 >    painCave.isFatal = 1;
140 >    simError();
141 >  } else {        
142 >    info->scaleBox(exp(dt*eta));      
143 >  }
144  
145   }
146  
147 < void NPTi::moveB( void ){
148 <  int i,j,k;
149 <  int atomIndex;
147 > template<typename T> void NPTi<T>::moveB( void ){
148 >
149 >  int i, j;
150    DirectionalAtom* dAtom;
151 <  double Tb[3];
152 <  double ji[3];
151 >  double Tb[3], ji[3];
152 >  double vel[3], frc[3];
153 >  double mass;
154 >
155    double instaTemp, instaPress, instaVol;
156    double tt2, tb2;
157    
# Line 149 | Line 163 | void NPTi::moveB( void ){
163    instaVol = tStats->getVolume();
164  
165    chi += dt2 * ( instaTemp / targetTemp - 1.0) / tt2;
166 <  eta += dt2 * ( instaVol * (instaPress - targetPressure) / (NkBT*tb2));
166 >  eta += dt2 * ( instaVol * (instaPress - targetPressure) /
167 >                 (p_convert*NkBT*tb2));
168    
169    for( i=0; i<nAtoms; i++ ){
170 <    atomIndex = i * 3;
171 <    
170 >
171 >    atoms[i]->getVel( vel );
172 >    atoms[i]->getFrc( frc );
173 >
174 >    mass = atoms[i]->getMass();
175 >
176      // velocity half step
177 <    for( j=atomIndex; j<(atomIndex+3); j++ )
178 <    for( j=atomIndex; j<(atomIndex+3); j++ )
160 <      vel[j] += dt2 * ((frc[j]/atoms[i]->getMass())*eConvert
161 <                       - vel[j]*(chi+eta));
177 >    for (j=0; j < 3; j++)
178 >      vel[j] += dt2 * ((frc[j] / mass ) * eConvert - vel[j]*(chi+eta));
179      
180 +    atoms[i]->setVel( vel );
181 +
182      if( atoms[i]->isDirectional() ){
183 <      
183 >
184        dAtom = (DirectionalAtom *)atoms[i];
185 <      
186 <      // get and convert the torque to body frame
187 <      
188 <      Tb[0] = dAtom->getTx();
170 <      Tb[1] = dAtom->getTy();
171 <      Tb[2] = dAtom->getTz();
172 <      
185 >
186 >      // get and convert the torque to body frame      
187 >
188 >      dAtom->getTrq( Tb );
189        dAtom->lab2Body( Tb );
190 <      
191 <      // get the angular momentum, and complete the angular momentum
192 <      // half step
193 <      
194 <      ji[0] = dAtom->getJx();
195 <      ji[1] = dAtom->getJy();
196 <      ji[2] = dAtom->getJz();
197 <      
198 <      ji[0] += dt2 * (Tb[0] * eConvert - ji[0]*chi);
183 <      ji[1] += dt2 * (Tb[1] * eConvert - ji[1]*chi);
184 <      ji[2] += dt2 * (Tb[2] * eConvert - ji[2]*chi);
185 <      
186 <      dAtom->setJx( ji[0] );
187 <      dAtom->setJy( ji[1] );
188 <      dAtom->setJz( ji[2] );
190 >
191 >      // get the angular momentum, and propagate a half step
192 >
193 >      dAtom->getJ( ji );
194 >
195 >      for (j=0; j < 3; j++)
196 >        ji[j] += dt2 * (Tb[j] * eConvert - ji[j]*chi);    
197 >
198 >      dAtom->setJ( ji );
199      }
200    }
201   }
202  
203 < int NPTi::readyCheck() {
203 > template<typename T> int NPTi<T>::readyCheck() {
204 >
205 >  //check parent's readyCheck() first
206 >  if (T::readyCheck() == -1)
207 >    return -1;
208  
209    // First check to see if we have a target temperature.
210    // Not having one is fatal.

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines