ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/restraints/Restraints.cpp
Revision: 1537
Committed: Wed Oct 6 21:27:21 2004 UTC (19 years, 9 months ago) by gezelter
File size: 13758 byte(s)
Log Message:
Chris doesn't know about the OOPSE-2.0 directory structure yet

File Contents

# User Rev Content
1 chrisfen 1534 // Thermodynamic integration is not multiprocessor friendly right now
2    
3 gezelter 1490 #include <iostream>
4     #include <stdlib.h>
5     #include <cstdio>
6     #include <fstream>
7     #include <iomanip>
8     #include <string>
9     #include <cstring>
10     #include <math.h>
11    
12     using namespace std;
13    
14 gezelter 1537 #include "restraints/Restraints.hpp"
15     #include "brains/SimInfo.hpp"
16     #include "utils/simError.h"
17 gezelter 1490
18     #define PI 3.14159265359
19     #define TWO_PI 6.28318530718
20    
21     Restraints::Restraints(double lambdaVal, double lambdaExp){
22     lambdaValue = lambdaVal;
23     lambdaK = lambdaExp;
24 chrisfen 1534 vector<double> resConsts;
25 gezelter 1490 const char *jolt = " \t\n;,";
26    
27     #ifdef IS_MPI
28     if(worldRank == 0 ){
29     #endif // is_mpi
30    
31     strcpy(springName, "HarmSpringConsts.txt");
32    
33     ifstream springs(springName);
34    
35     if (!springs) {
36     sprintf(painCave.errMsg,
37 chrisfen 1534 "Unable to open HarmSpringConsts.txt for reading, so the\n"
38     "\tdefault spring constants will be loaded. If you want\n"
39     "\tto specify spring constants, include a three line\n"
40     "\tHarmSpringConsts.txt file in the execution directory.\n");
41 gezelter 1490 painCave.severity = OOPSE_WARNING;
42     painCave.isFatal = 0;
43     simError();
44    
45     // load default spring constants
46     kDist = 6; // spring constant in units of kcal/(mol*ang^2)
47     kTheta = 7.5; // in units of kcal/mol
48     kOmega = 13.5; // in units of kcal/mol
49     } else {
50    
51     springs.getline(inLine,999,'\n');
52 chrisfen 1534 // the file is blank!
53     if (springs.eof()){
54     sprintf(painCave.errMsg,
55     "HarmSpringConsts.txt file is not valid.\n"
56     "\tThe file should contain four rows, the last three containing\n"
57     "\ta label and the spring constant value. They should be listed\n"
58     "\tin the following order: kDist (positional restrant), kTheta\n"
59     "\t(rot. restraint: deflection of z-axis), and kOmega (rot.\n"
60     "\trestraint: rotation about the z-axis).\n");
61     painCave.severity = OOPSE_ERROR;
62     painCave.isFatal = 1;
63     simError();
64     }
65     // read in spring constants and check to make sure it is a valid file
66 gezelter 1490 springs.getline(inLine,999,'\n');
67 chrisfen 1534 while (!springs.eof()){
68     if (NULL != inLine){
69     token = strtok(inLine,jolt);
70     token = strtok(NULL,jolt);
71     if (NULL != token){
72     strcpy(inValue,token);
73     resConsts.push_back(atof(inValue));
74     }
75     }
76     springs.getline(inLine,999,'\n');
77     }
78     if (resConsts.size() == 3){
79     kDist = resConsts[0];
80     kTheta = resConsts[1];
81     kOmega = resConsts[2];
82     }
83     else {
84     sprintf(painCave.errMsg,
85     "HarmSpringConsts.txt file is not valid.\n"
86     "\tThe file should contain four rows, the last three containing\n"
87     "\ta label and the spring constant value. They should be listed\n"
88     "\tin the following order: kDist (positional restrant), kTheta\n"
89     "\t(rot. restraint: deflection of z-axis), and kOmega (rot.\n"
90     "\trestraint: rotation about the z-axis).\n");
91     painCave.severity = OOPSE_ERROR;
92     painCave.isFatal = 1;
93     simError();
94     }
95 gezelter 1490 }
96     #ifdef IS_MPI
97     }
98    
99     MPI_Bcast(&kDist, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
100     MPI_Bcast(&kTheta, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
101     MPI_Bcast(&kOmega, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
102    
103     sprintf( checkPointMsg,
104     "Sucessfully opened and read spring file.\n");
105     MPIcheckPoint();
106    
107     #endif // is_mpi
108    
109     sprintf(painCave.errMsg,
110     "The spring constants for thermodynamic integration are:\n"
111     "\tkDist = %lf\n"
112     "\tkTheta = %lf\n"
113     "\tkOmega = %lf\n", kDist, kTheta, kOmega);
114     painCave.severity = OOPSE_INFO;
115     painCave.isFatal = 0;
116     simError();
117     }
118    
119     Restraints::~Restraints(){
120     }
121    
122     void Restraints::Calc_rVal(double position[3], int currentMol){
123     delRx = position[0] - cofmPosX[currentMol];
124     delRy = position[1] - cofmPosY[currentMol];
125     delRz = position[2] - cofmPosZ[currentMol];
126    
127     return;
128     }
129    
130     void Restraints::Calc_body_thetaVal(double matrix[3][3], int currentMol){
131     ub0x = matrix[0][0]*uX0[currentMol] + matrix[0][1]*uY0[currentMol]
132     + matrix[0][2]*uZ0[currentMol];
133     ub0y = matrix[1][0]*uX0[currentMol] + matrix[1][1]*uY0[currentMol]
134     + matrix[1][2]*uZ0[currentMol];
135     ub0z = matrix[2][0]*uX0[currentMol] + matrix[2][1]*uY0[currentMol]
136     + matrix[2][2]*uZ0[currentMol];
137    
138     normalize = sqrt(ub0x*ub0x + ub0y*ub0y + ub0z*ub0z);
139     ub0x = ub0x/normalize;
140     ub0y = ub0y/normalize;
141     ub0z = ub0z/normalize;
142    
143     // Theta is the dot product of the reference and new z-axes
144     theta = acos(ub0z);
145    
146     return;
147     }
148    
149     void Restraints::Calc_body_omegaVal(double matrix[3][3], double zAngle){
150     double zRotator[3][3];
151     double tempOmega;
152     double wholeTwoPis;
153     // Use the omega accumulated from the rotation propagation
154     omega = zAngle;
155    
156     // translate the omega into a range between -PI and PI
157     if (omega < -PI){
158     tempOmega = omega / -TWO_PI;
159     wholeTwoPis = floor(tempOmega);
160     tempOmega = omega + TWO_PI*wholeTwoPis;
161     if (tempOmega < -PI)
162     omega = tempOmega + TWO_PI;
163     else
164     omega = tempOmega;
165     }
166     if (omega > PI){
167     tempOmega = omega / TWO_PI;
168     wholeTwoPis = floor(tempOmega);
169     tempOmega = omega - TWO_PI*wholeTwoPis;
170     if (tempOmega > PI)
171     omega = tempOmega - TWO_PI;
172     else
173     omega = tempOmega;
174     }
175    
176     vb0x = sin(omega);
177     vb0y = cos(omega);
178     vb0z = 0.0;
179    
180     normalize = sqrt(vb0x*vb0x + vb0y*vb0y + vb0z*vb0z);
181     vb0x = vb0x/normalize;
182     vb0y = vb0y/normalize;
183     vb0z = vb0z/normalize;
184    
185     return;
186     }
187    
188     double Restraints::Calc_Restraint_Forces(vector<StuntDouble*> vecParticles){
189     double pos[3];
190     double A[3][3];
191     double tolerance;
192     double tempPotent;
193     double factor;
194     double spaceTrq[3];
195     double omegaPass;
196    
197     tolerance = 5.72957795131e-7;
198    
199     harmPotent = 0.0; // zero out the global harmonic potential variable
200    
201     factor = 1 - pow(lambdaValue, lambdaK);
202    
203     for (i=0; i<vecParticles.size(); i++){
204     if (vecParticles[i]->isDirectional()){
205     vecParticles[i]->getPos(pos);
206     vecParticles[i]->getA(A);
207     Calc_rVal( pos, i );
208     Calc_body_thetaVal( A, i );
209     omegaPass = vecParticles[i]->getZangle();
210     Calc_body_omegaVal( A, omegaPass );
211    
212     // first we calculate the derivatives
213     dVdrx = -kDist*delRx;
214     dVdry = -kDist*delRy;
215     dVdrz = -kDist*delRz;
216    
217     // uTx... and vTx... are the body-fixed z and y unit vectors
218     uTx = 0.0;
219     uTy = 0.0;
220     uTz = 1.0;
221     vTx = 0.0;
222     vTy = 1.0;
223     vTz = 0.0;
224    
225     dVdux = 0;
226     dVduy = 0;
227     dVduz = 0;
228     dVdvx = 0;
229     dVdvy = 0;
230     dVdvz = 0;
231    
232     if (fabs(theta) > tolerance) {
233     dVdux = -(kTheta*theta/sin(theta))*ub0x;
234     dVduy = -(kTheta*theta/sin(theta))*ub0y;
235     dVduz = -(kTheta*theta/sin(theta))*ub0z;
236     }
237    
238     if (fabs(omega) > tolerance) {
239     dVdvx = -(kOmega*omega/sin(omega))*vb0x;
240     dVdvy = -(kOmega*omega/sin(omega))*vb0y;
241     dVdvz = -(kOmega*omega/sin(omega))*vb0z;
242     }
243    
244     // next we calculate the restraint forces and torques
245     restraintFrc[0] = dVdrx;
246     restraintFrc[1] = dVdry;
247     restraintFrc[2] = dVdrz;
248     tempPotent = 0.5*kDist*(delRx*delRx + delRy*delRy + delRz*delRz);
249    
250     restraintTrq[0] = 0.0;
251     restraintTrq[1] = 0.0;
252     restraintTrq[2] = 0.0;
253    
254     if (fabs(omega) > tolerance) {
255     restraintTrq[0] += 0.0;
256     restraintTrq[1] += 0.0;
257     restraintTrq[2] += vTy*dVdvx;
258     tempPotent += 0.5*(kOmega*omega*omega);
259     }
260     if (fabs(theta) > tolerance) {
261     restraintTrq[0] += (uTz*dVduy);
262     restraintTrq[1] += -(uTz*dVdux);
263     restraintTrq[2] += 0.0;
264     tempPotent += 0.5*(kTheta*theta*theta);
265     }
266    
267     for (j = 0; j < 3; j++) {
268     restraintFrc[j] *= factor;
269     restraintTrq[j] *= factor;
270     }
271    
272     harmPotent += tempPotent;
273    
274     // now we need to convert from body-fixed torques to space-fixed torques
275     spaceTrq[0] = A[0][0]*restraintTrq[0] + A[1][0]*restraintTrq[1]
276     + A[2][0]*restraintTrq[2];
277     spaceTrq[1] = A[0][1]*restraintTrq[0] + A[1][1]*restraintTrq[1]
278     + A[2][1]*restraintTrq[2];
279     spaceTrq[2] = A[0][2]*restraintTrq[0] + A[1][2]*restraintTrq[1]
280     + A[2][2]*restraintTrq[2];
281    
282     // now it's time to pass these temporary forces and torques
283     // to the total forces and torques
284     vecParticles[i]->addFrc(restraintFrc);
285     vecParticles[i]->addTrq(spaceTrq);
286     }
287     }
288    
289     // and we can return the appropriately scaled potential energy
290     tempPotent = harmPotent * factor;
291     return tempPotent;
292     }
293    
294     void Restraints::Store_Init_Info(vector<StuntDouble*> vecParticles){
295 chrisfen 1534 int idealSize;
296 gezelter 1490 double pos[3];
297     double A[3][3];
298     double RfromQ[3][3];
299     double quat0, quat1, quat2, quat3;
300     double dot;
301 chrisfen 1534 vector<double> tempZangs;
302 gezelter 1490 const char *delimit = " \t\n;,";
303    
304     //open the idealCrystal.in file and zAngle.ang file
305     strcpy(fileName, "idealCrystal.in");
306     strcpy(angleName, "zAngle.ang");
307    
308     ifstream crystalIn(fileName);
309     ifstream angleIn(angleName);
310    
311 chrisfen 1534 // check to see if these files are present in the execution directory
312 gezelter 1490 if (!crystalIn) {
313     sprintf(painCave.errMsg,
314     "Restraints Error: Unable to open idealCrystal.in for reading.\n"
315 chrisfen 1534 "\tMake sure a ref. crystal file is in the working directory.\n");
316     painCave.severity = OOPSE_ERROR;
317 gezelter 1490 painCave.isFatal = 1;
318     simError();
319     }
320    
321 chrisfen 1534 // it's not fatal to lack a zAngle.ang file, it just means you're starting
322     // from the ideal crystal state
323 gezelter 1490 if (!angleIn) {
324     sprintf(painCave.errMsg,
325     "Restraints Warning: The lack of a zAngle.ang file is mildly\n"
326     "\tunsettling... This means the simulation is starting from the\n"
327     "\tidealCrystal.in reference configuration, so the omega values\n"
328 chrisfen 1534 "\twill all be set to zero. If this is not the case, the energy\n"
329     "\tcalculations will be wrong.\n");
330     painCave.severity = OOPSE_WARNING;
331 gezelter 1490 painCave.isFatal = 0;
332     simError();
333     }
334    
335     // A rather specific reader for OOPSE .eor files...
336     // Let's read in the perfect crystal file
337     crystalIn.getline(inLine,999,'\n');
338 chrisfen 1534 // check to see if the crystal file is the same length as starting config.
339     token = strtok(inLine,delimit);
340     strcpy(inValue,token);
341     idealSize = atoi(inValue);
342     if (idealSize != vecParticles.size()) {
343     sprintf(painCave.errMsg,
344     "Restraints Error: Reference crystal file is not valid.\n"
345     "\tMake sure the idealCrystal.in file is the same size as the\n"
346     "\tstarting configuration. Using an incompatable crystal will\n"
347     "\tlead to energy calculation failures.\n");
348     painCave.severity = OOPSE_ERROR;
349     painCave.isFatal = 1;
350     simError();
351     }
352     // else, the file is okay... let's continue
353 gezelter 1490 crystalIn.getline(inLine,999,'\n');
354    
355     for (i=0; i<vecParticles.size(); i++) {
356     crystalIn.getline(inLine,999,'\n');
357     token = strtok(inLine,delimit);
358     token = strtok(NULL,delimit);
359     strcpy(inValue,token);
360     cofmPosX.push_back(atof(inValue));
361     token = strtok(NULL,delimit);
362     strcpy(inValue,token);
363     cofmPosY.push_back(atof(inValue));
364     token = strtok(NULL,delimit);
365     strcpy(inValue,token);
366     cofmPosZ.push_back(atof(inValue));
367     token = strtok(NULL,delimit);
368     token = strtok(NULL,delimit);
369     token = strtok(NULL,delimit);
370     token = strtok(NULL,delimit);
371     strcpy(inValue,token);
372     quat0 = atof(inValue);
373     token = strtok(NULL,delimit);
374     strcpy(inValue,token);
375     quat1 = atof(inValue);
376     token = strtok(NULL,delimit);
377     strcpy(inValue,token);
378     quat2 = atof(inValue);
379     token = strtok(NULL,delimit);
380     strcpy(inValue,token);
381     quat3 = atof(inValue);
382    
383     // now build the rotation matrix and find the unit vectors
384     RfromQ[0][0] = quat0*quat0 + quat1*quat1 - quat2*quat2 - quat3*quat3;
385     RfromQ[0][1] = 2*(quat1*quat2 + quat0*quat3);
386     RfromQ[0][2] = 2*(quat1*quat3 - quat0*quat2);
387     RfromQ[1][0] = 2*(quat1*quat2 - quat0*quat3);
388     RfromQ[1][1] = quat0*quat0 - quat1*quat1 + quat2*quat2 - quat3*quat3;
389     RfromQ[1][2] = 2*(quat2*quat3 + quat0*quat1);
390     RfromQ[2][0] = 2*(quat1*quat3 + quat0*quat2);
391     RfromQ[2][1] = 2*(quat2*quat3 - quat0*quat1);
392     RfromQ[2][2] = quat0*quat0 - quat1*quat1 - quat2*quat2 + quat3*quat3;
393    
394     normalize = sqrt(RfromQ[2][0]*RfromQ[2][0] + RfromQ[2][1]*RfromQ[2][1]
395     + RfromQ[2][2]*RfromQ[2][2]);
396     uX0.push_back(RfromQ[2][0]/normalize);
397     uY0.push_back(RfromQ[2][1]/normalize);
398     uZ0.push_back(RfromQ[2][2]/normalize);
399    
400     normalize = sqrt(RfromQ[1][0]*RfromQ[1][0] + RfromQ[1][1]*RfromQ[1][1]
401     + RfromQ[1][2]*RfromQ[1][2]);
402     vX0.push_back(RfromQ[1][0]/normalize);
403     vY0.push_back(RfromQ[1][1]/normalize);
404     vZ0.push_back(RfromQ[1][2]/normalize);
405     }
406 chrisfen 1534 crystalIn.close();
407 gezelter 1490
408 chrisfen 1534 // now we read in the zAngle.ang file
409 gezelter 1490 if (angleIn){
410     angleIn.getline(inLine,999,'\n');
411 chrisfen 1534 angleIn.getline(inLine,999,'\n');
412     while (!angleIn.eof()) {
413 gezelter 1490 token = strtok(inLine,delimit);
414     strcpy(inValue,token);
415 chrisfen 1534 tempZangs.push_back(atof(inValue));
416     angleIn.getline(inLine,999,'\n');
417 gezelter 1490 }
418 chrisfen 1534
419     // test to make sure the zAngle.ang file is the proper length
420     if (tempZangs.size() == vecParticles.size())
421     for (i=0; i<vecParticles.size(); i++)
422     vecParticles[i]->setZangle(tempZangs[i]);
423     else {
424     sprintf(painCave.errMsg,
425     "Restraints Error: the supplied zAngle file is not valid.\n"
426     "\tMake sure the zAngle.ang file matches with the initial\n"
427     "\tconfiguration (i.e. they're the same length). Using the wrong\n"
428     "\tzAngle file will lead to errors in the energy calculations.\n");
429     painCave.severity = OOPSE_ERROR;
430     painCave.isFatal = 1;
431     simError();
432     }
433 gezelter 1490 }
434 chrisfen 1534 angleIn.close();
435 gezelter 1490
436     return;
437     }
438    
439     void Restraints::Write_zAngle_File(vector<StuntDouble*> vecParticles){
440    
441     char zOutName[200];
442    
443     strcpy(zOutName,"zAngle.ang");
444    
445     ofstream angleOut(zOutName);
446     angleOut << "This file contains the omega values for the .eor file\n";
447     for (i=0; i<vecParticles.size(); i++) {
448     angleOut << vecParticles[i]->getZangle() << "\n";
449     }
450     return;
451     }
452    
453     double Restraints::getVharm(){
454     return harmPotent;
455     }
456