ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Restraints.cpp
Revision: 1187
Committed: Sat May 22 18:16:18 2004 UTC (20 years, 11 months ago) by chrisfen
File size: 10512 byte(s)
Log Message:
Fixed Thermodynamic integration code.

File Contents

# Content
1 #include <iostream>
2 #include <stdlib.h>
3 #include <cstdio>
4 #include <fstream>
5 #include <iomanip>
6 #include <string>
7 #include <cstring>
8 #include <math.h>
9
10 using namespace std;
11
12 #include "Restraints.hpp"
13 #include "SimInfo.hpp"
14 #include "simError.h"
15
16 #define PI 3.14159265359
17 #define TWO_PI 6.28318530718
18
19 Restraints::Restraints(int nMolInfo, double lambdaVal, double lambdaExp){
20 nMol = nMolInfo;
21 lambdaValue = lambdaVal;
22 lambdaK = lambdaExp;
23
24 const char *jolt = " \t\n;,";
25
26 strcpy(springName, "HarmSpringConsts.txt");
27
28 ifstream springs(springName);
29
30 if (!springs) {
31 sprintf(painCave.errMsg,
32 "Restraints Warning: Unable to open HarmSpringConsts.txt for reading.\n"
33 "\tDefault spring constants will be loaded. If you want to specify\n"
34 "\tspring constants, include a three line HarmSpringConsts.txt file\n"
35 "\tin the current directory.\n");
36 painCave.isFatal = 0;
37 simError();
38
39 // load default spring constants
40 kDist = 6; // spring constant in units of kcal/(mol*ang^2)
41 kTheta = 7.5; // in units of kcal/mol
42 kOmega = 13.5; // in units of kcal/mol
43 return;
44 }
45
46 springs.getline(inLine,999,'\n');
47 springs.getline(inLine,999,'\n');
48 token = strtok(inLine,jolt);
49 token = strtok(NULL,jolt);
50 strcpy(inValue,token);
51 kDist = (atof(inValue));
52 springs.getline(inLine,999,'\n');
53 token = strtok(inLine,jolt);
54 token = strtok(NULL,jolt);
55 strcpy(inValue,token);
56 kTheta = (atof(inValue));
57 springs.getline(inLine,999,'\n');
58 token = strtok(inLine,jolt);
59 token = strtok(NULL,jolt);
60 strcpy(inValue,token);
61 kOmega = (atof(inValue));
62 springs.close();
63
64 cout << "The Spring Constants are:\n\tkDist = " << kDist << "\n\tkTheta = " << kTheta << "\n\tkOmega = " << kOmega << "\n";
65 }
66
67 Restraints::~Restraints(){
68 }
69
70 void Restraints::Calc_rVal(double position[3], int currentMol){
71 delRx = position[0] - cofmPosX[currentMol];
72 delRy = position[1] - cofmPosY[currentMol];
73 delRz = position[2] - cofmPosZ[currentMol];
74
75 return;
76 }
77
78 void Restraints::Calc_body_thetaVal(double matrix[3][3], int currentMol){
79 ub0x = matrix[0][0]*uX0[currentMol] + matrix[0][1]*uY0[currentMol]
80 + matrix[0][2]*uZ0[currentMol];
81 ub0y = matrix[1][0]*uX0[currentMol] + matrix[1][1]*uY0[currentMol]
82 + matrix[1][2]*uZ0[currentMol];
83 ub0z = matrix[2][0]*uX0[currentMol] + matrix[2][1]*uY0[currentMol]
84 + matrix[2][2]*uZ0[currentMol];
85
86 normalize = sqrt(ub0x*ub0x + ub0y*ub0y + ub0z*ub0z);
87 ub0x = ub0x/normalize;
88 ub0y = ub0y/normalize;
89 ub0z = ub0z/normalize;
90
91 // Theta is the dot product of the reference and new z-axes
92 theta = acos(ub0z);
93
94 return;
95 }
96
97 void Restraints::Calc_body_omegaVal(double matrix[3][3], double zAngle){
98 double zRotator[3][3];
99 double tempOmega;
100 double wholeTwoPis;
101 // Use the omega accumulated from the rotation propagation
102 omega = zAngle;
103
104 // translate the omega into a range between -PI and PI
105 if (omega < -PI){
106 tempOmega = omega / -TWO_PI;
107 wholeTwoPis = floor(tempOmega);
108 tempOmega = omega + TWO_PI*wholeTwoPis;
109 if (tempOmega < -PI)
110 omega = tempOmega + TWO_PI;
111 else
112 omega = tempOmega;
113 }
114 if (omega > PI){
115 tempOmega = omega / TWO_PI;
116 wholeTwoPis = floor(tempOmega);
117 tempOmega = omega - TWO_PI*wholeTwoPis;
118 if (tempOmega > PI)
119 omega = tempOmega - TWO_PI;
120 else
121 omega = tempOmega;
122 }
123
124 vb0x = sin(omega);
125 vb0y = cos(omega);
126 vb0z = 0.0;
127
128 normalize = sqrt(vb0x*vb0x + vb0y*vb0y + vb0z*vb0z);
129 vb0x = vb0x/normalize;
130 vb0y = vb0y/normalize;
131 vb0z = vb0z/normalize;
132
133 return;
134 }
135
136 double Restraints::Calc_Restraint_Forces(vector<StuntDouble*> vecParticles){
137 double pos[3];
138 double A[3][3];
139 double tolerance;
140 double tempPotent;
141 double factor;
142 double spaceTrq[3];
143 double omega;
144
145 tolerance = 5.72957795131e-7;
146
147 harmPotent = 0.0; // zero out the global harmonic potential variable
148
149 factor = 1 - pow(lambdaValue, lambdaK);
150
151 for (i=0; i<nMol; i++){
152 if (vecParticles[i]->isDirectional()){
153 vecParticles[i]->getPos(pos);
154 vecParticles[i]->getA(A);
155 Calc_rVal( pos, i );
156 Calc_body_thetaVal( A, i );
157 vecParticles[i]->getZangle(omega);
158 Calc_body_omegaVal( A, omega );
159
160 if (omega > PI || omega < -PI)
161 cout << "oops... " << omega << "\n";
162
163 // first we calculate the derivatives
164 dVdrx = -kDist*delRx;
165 dVdry = -kDist*delRy;
166 dVdrz = -kDist*delRz;
167
168 // uTx... and vTx... are the body-fixed z and y unit vectors
169 uTx = 0.0;
170 uTy = 0.0;
171 uTz = 1.0;
172 vTx = 0.0;
173 vTy = 1.0;
174 vTz = 0.0;
175
176 dVdux = 0;
177 dVduy = 0;
178 dVduz = 0;
179 dVdvx = 0;
180 dVdvy = 0;
181 dVdvz = 0;
182
183 if (fabs(theta) > tolerance) {
184 dVdux = -(kTheta*theta/sin(theta))*ub0x;
185 dVduy = -(kTheta*theta/sin(theta))*ub0y;
186 dVduz = -(kTheta*theta/sin(theta))*ub0z;
187 }
188
189 if (fabs(omega) > tolerance) {
190 dVdvx = -(kOmega*omega/sin(omega))*vb0x;
191 dVdvy = -(kOmega*omega/sin(omega))*vb0y;
192 dVdvz = -(kOmega*omega/sin(omega))*vb0z;
193 }
194
195 // next we calculate the restraint forces and torques
196 restraintFrc[0] = dVdrx;
197 restraintFrc[1] = dVdry;
198 restraintFrc[2] = dVdrz;
199 tempPotent = 0.5*kDist*(delRx*delRx + delRy*delRy + delRz*delRz);
200
201 restraintTrq[0] = 0.0;
202 restraintTrq[1] = 0.0;
203 restraintTrq[2] = 0.0;
204
205 if (fabs(omega) > tolerance) {
206 restraintTrq[0] += 0.0;
207 restraintTrq[1] += 0.0;
208 restraintTrq[2] += vTy*dVdvx;
209 tempPotent += 0.5*(kOmega*omega*omega);
210 }
211 if (fabs(theta) > tolerance) {
212 restraintTrq[0] += (uTz*dVduy);
213 restraintTrq[1] += -(uTz*dVdux);
214 restraintTrq[2] += 0.0;
215 tempPotent += 0.5*(kTheta*theta*theta);
216 }
217
218 for (j = 0; j < 3; j++) {
219 restraintFrc[j] *= factor;
220 restraintTrq[j] *= factor;
221 }
222
223 harmPotent += tempPotent;
224
225 // now we need to convert from body-fixed torques to space-fixed torques
226 spaceTrq[0] = A[0][0]*restraintTrq[0] + A[1][0]*restraintTrq[1]
227 + A[2][0]*restraintTrq[2];
228 spaceTrq[1] = A[0][1]*restraintTrq[0] + A[1][1]*restraintTrq[1]
229 + A[2][1]*restraintTrq[2];
230 spaceTrq[2] = A[0][2]*restraintTrq[0] + A[1][2]*restraintTrq[1]
231 + A[2][2]*restraintTrq[2];
232
233 // now it's time to pass these temporary forces and torques
234 // to the total forces and torques
235 vecParticles[i]->addFrc(restraintFrc);
236 vecParticles[i]->addTrq(spaceTrq);
237 }
238 }
239
240 // and we can return the appropriately scaled potential energy
241 tempPotent = harmPotent * factor;
242 return tempPotent;
243 }
244
245 void Restraints::Store_Init_Info(vector<StuntDouble*> vecParticles){
246 double pos[3];
247 double A[3][3];
248 double RfromQ[3][3];
249 double quat0, quat1, quat2, quat3;
250 double dot;
251 // char *token;
252 // char fileName[200];
253 // char angleName[200];
254 // char inLine[1000];
255 // char inValue[200];
256 const char *delimit = " \t\n;,";
257
258 //open the idealCrystal.in file and zAngle.ang file
259 strcpy(fileName, "idealCrystal.in");
260 strcpy(angleName, "zAngle.ang");
261
262 ifstream crystalIn(fileName);
263 ifstream angleIn(angleName);
264
265 if (!crystalIn) {
266 sprintf(painCave.errMsg,
267 "Restraints Error: Unable to open idealCrystal.in for reading.\n"
268 "\tMake sure a reference crystal file is in the current directory.\n");
269 painCave.isFatal = 1;
270 simError();
271
272 return;
273 }
274
275 if (!angleIn) {
276 sprintf(painCave.errMsg,
277 "Restraints Warning: The lack of a zAngle.ang file is mildly\n"
278 "\tunsettling... This means you arestarting from the idealCrystal.in\n"
279 "\treference configuration, so the omega values will all be set to\n"
280 "\tzero. If this isn't the case, you should question your results.\n");
281 painCave.isFatal = 0;
282 simError();
283 }
284
285 // A rather specific reader for OOPSE .eor files...
286 // Let's read in the perfect crystal file
287 crystalIn.getline(inLine,999,'\n');
288 crystalIn.getline(inLine,999,'\n');
289
290 for (i=0; i<nMol; i++) {
291 crystalIn.getline(inLine,999,'\n');
292 token = strtok(inLine,delimit);
293 token = strtok(NULL,delimit);
294 strcpy(inValue,token);
295 cofmPosX.push_back(atof(inValue));
296 token = strtok(NULL,delimit);
297 strcpy(inValue,token);
298 cofmPosY.push_back(atof(inValue));
299 token = strtok(NULL,delimit);
300 strcpy(inValue,token);
301 cofmPosZ.push_back(atof(inValue));
302 token = strtok(NULL,delimit);
303 token = strtok(NULL,delimit);
304 token = strtok(NULL,delimit);
305 token = strtok(NULL,delimit);
306 strcpy(inValue,token);
307 quat0 = atof(inValue);
308 token = strtok(NULL,delimit);
309 strcpy(inValue,token);
310 quat1 = atof(inValue);
311 token = strtok(NULL,delimit);
312 strcpy(inValue,token);
313 quat2 = atof(inValue);
314 token = strtok(NULL,delimit);
315 strcpy(inValue,token);
316 quat3 = atof(inValue);
317
318 // now build the rotation matrix and find the unit vectors
319 RfromQ[0][0] = quat0*quat0 + quat1*quat1 - quat2*quat2 - quat3*quat3;
320 RfromQ[0][1] = 2*(quat1*quat2 + quat0*quat3);
321 RfromQ[0][2] = 2*(quat1*quat3 - quat0*quat2);
322 RfromQ[1][0] = 2*(quat1*quat2 - quat0*quat3);
323 RfromQ[1][1] = quat0*quat0 - quat1*quat1 + quat2*quat2 - quat3*quat3;
324 RfromQ[1][2] = 2*(quat2*quat3 + quat0*quat1);
325 RfromQ[2][0] = 2*(quat1*quat3 + quat0*quat2);
326 RfromQ[2][1] = 2*(quat2*quat3 - quat0*quat1);
327 RfromQ[2][2] = quat0*quat0 - quat1*quat1 - quat2*quat2 + quat3*quat3;
328
329 normalize = sqrt(RfromQ[2][0]*RfromQ[2][0] + RfromQ[2][1]*RfromQ[2][1]
330 + RfromQ[2][2]*RfromQ[2][2]);
331 uX0.push_back(RfromQ[2][0]/normalize);
332 uY0.push_back(RfromQ[2][1]/normalize);
333 uZ0.push_back(RfromQ[2][2]/normalize);
334
335 normalize = sqrt(RfromQ[1][0]*RfromQ[1][0] + RfromQ[1][1]*RfromQ[1][1]
336 + RfromQ[1][2]*RfromQ[1][2]);
337 vX0.push_back(RfromQ[1][0]/normalize);
338 vY0.push_back(RfromQ[1][1]/normalize);
339 vZ0.push_back(RfromQ[1][2]/normalize);
340 }
341
342 // now we can read in the zAngle.ang file
343 if (angleIn){
344 angleIn.getline(inLine,999,'\n');
345 for (i=0; i<nMol; i++) {
346 angleIn.getline(inLine,999,'\n');
347 token = strtok(inLine,delimit);
348 strcpy(inValue,token);
349 vecParticles[i]->setZangle(atof(inValue));
350 }
351 }
352
353 return;
354 }
355
356 void Restraints::Write_zAngle_File(vector<StuntDouble*> vecParticles){
357
358 char zOutName[200];
359
360 strcpy(zOutName,"zAngle.ang");
361
362 ofstream angleOut(zOutName);
363 angleOut << "This file contains the omega values for the .eor file\n";
364 for (i=0; i<nMol; i++) {
365 angleOut << vecParticles[i]->getZangle() << "\n";
366 }
367 return;
368 }
369
370 double Restraints::getVharm(){
371 return harmPotent;
372 }
373