ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/restraints/Restraints.cpp
(Generate patch)

Comparing trunk/OOPSE-4/src/restraints/Restraints.cpp (file contents):
Revision 1537 by gezelter, Wed Oct 6 21:27:21 2004 UTC vs.
Revision 2115 by chrisfen, Fri Mar 11 00:43:19 2005 UTC

# Line 1 | Line 1
1 < // Thermodynamic integration is not multiprocessor friendly right now
1 > /*
2 > * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3 > *
4 > * The University of Notre Dame grants you ("Licensee") a
5 > * non-exclusive, royalty free, license to use, modify and
6 > * redistribute this software in source and binary code form, provided
7 > * that the following conditions are met:
8 > *
9 > * 1. Acknowledgement of the program authors must be made in any
10 > *    publication of scientific results based in part on use of the
11 > *    program.  An acceptable form of acknowledgement is citation of
12 > *    the article in which the program was described (Matthew
13 > *    A. Meineke, Charles F. Vardeman II, Teng Lin, Christopher
14 > *    J. Fennell and J. Daniel Gezelter, "OOPSE: An Object-Oriented
15 > *    Parallel Simulation Engine for Molecular Dynamics,"
16 > *    J. Comput. Chem. 26, pp. 252-271 (2005))
17 > *
18 > * 2. Redistributions of source code must retain the above copyright
19 > *    notice, this list of conditions and the following disclaimer.
20 > *
21 > * 3. Redistributions in binary form must reproduce the above copyright
22 > *    notice, this list of conditions and the following disclaimer in the
23 > *    documentation and/or other materials provided with the
24 > *    distribution.
25 > *
26 > * This software is provided "AS IS," without a warranty of any
27 > * kind. All express or implied conditions, representations and
28 > * warranties, including any implied warranty of merchantability,
29 > * fitness for a particular purpose or non-infringement, are hereby
30 > * excluded.  The University of Notre Dame and its licensors shall not
31 > * be liable for any damages suffered by licensee as a result of
32 > * using, modifying or distributing the software or its
33 > * derivatives. In no event will the University of Notre Dame or its
34 > * licensors be liable for any lost revenue, profit or data, or for
35 > * direct, indirect, special, consequential, incidental or punitive
36 > * damages, however caused and regardless of the theory of liability,
37 > * arising out of the use of or inability to use software, even if the
38 > * University of Notre Dame has been advised of the possibility of
39 > * such damages.
40 > */
41  
3 #include <iostream>
42   #include <stdlib.h>
5 #include <cstdio>
6 #include <fstream>
7 #include <iomanip>
8 #include <string>
9 #include <cstring>
43   #include <math.h>
44  
45   using namespace std;
46  
47   #include "restraints/Restraints.hpp"
48 < #include "brains/SimInfo.hpp"
48 > #include "primitives/Molecule.hpp"
49   #include "utils/simError.h"
50  
51   #define PI 3.14159265359
52   #define TWO_PI 6.28318530718
53  
54 < Restraints::Restraints(double lambdaVal, double lambdaExp){
55 <  lambdaValue = lambdaVal;
56 <  lambdaK = lambdaExp;
57 <  vector<double> resConsts;
58 <  const char *jolt = " \t\n;,";
54 > namespace oopse {
55 >  
56 >  Restraints::Restraints(SimInfo* info, double lambdaVal, double lambdaExp){
57 >    info_ = info;
58 >    Globals* simParam = info_->getSimParams();
59  
60 < #ifdef IS_MPI
61 <  if(worldRank == 0 ){
29 < #endif // is_mpi
30 <
31 <    strcpy(springName, "HarmSpringConsts.txt");
60 >    lambdaValue = lambdaVal;
61 >    lambdaK = lambdaExp;
62      
63 <    ifstream springs(springName);
64 <    
65 <    if (!springs) {
36 <      sprintf(painCave.errMsg,
37 <              "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 <      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 <      // 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();  
63 >    if (simParam->getUseSolidThermInt()) {
64 >      if (simParam->haveDistSpringConst()) {
65 >        kDist = simParam->getDistSpringConst();
66        }
67 <      // read in spring constants and check to make sure it is a valid file
68 <      springs.getline(inLine,999,'\n');
69 <      while (!springs.eof()){
70 <        if (NULL != inLine){
71 <          token = strtok(inLine,jolt);
72 <          token = strtok(NULL,jolt);
73 <          if (NULL != token){
74 <            strcpy(inValue,token);
75 <            resConsts.push_back(atof(inValue));
76 <          }
75 <        }
76 <        springs.getline(inLine,999,'\n');
67 >      else{
68 >        kDist = 6.0;
69 >        sprintf(painCave.errMsg,
70 >                "ThermoIntegration Warning: the spring constant for the\n"
71 >                "\ttranslational restraint was not specified. OOPSE will use\n"
72 >                "\ta default value of %f. To set it to something else, use\n"
73 >                "\tthe thermIntDistSpringConst variable.\n",
74 >                kDist);
75 >        painCave.isFatal = 0;
76 >        simError();
77        }
78 <      if (resConsts.size() == 3){
79 <        kDist = resConsts[0];
80 <        kTheta = resConsts[1];
81 <        kOmega = resConsts[2];
78 >      if (simParam->haveThetaSpringConst()) {
79 >        kTheta = simParam->getThetaSpringConst();
80        }
81 <      else {
82 <        sprintf(painCave.errMsg,
83 <                "HarmSpringConsts.txt file is not valid.\n"
84 <                "\tThe file should contain four rows, the last three containing\n"
85 <                "\ta label and the spring constant value. They should be listed\n"
86 <                "\tin the following order: kDist (positional restrant), kTheta\n"
87 <                "\t(rot. restraint: deflection of z-axis), and kOmega (rot.\n"
88 <                "\trestraint: rotation about the z-axis).\n");
89 <        painCave.severity = OOPSE_ERROR;
90 <        painCave.isFatal = 1;
93 <        simError();  
81 >      else{
82 >        kTheta = 7.5;
83 >        sprintf(painCave.errMsg,
84 >                "ThermoIntegration Warning: the spring constant for the\n"
85 >                "\tdeflection orientational restraint was not specified.\n"
86 >                "\tOOPSE will use a default value of %f. To set it to\n"
87 >                "\tsomething else, use the thermIntThetaSpringConst variable.\n",
88 >                kTheta);
89 >        painCave.isFatal = 0;
90 >        simError();
91        }
92 +      if (simParam->haveOmegaSpringConst()) {
93 +        kOmega = simParam->getOmegaSpringConst();
94 +      }
95 +      else{
96 +        kOmega = 13.5;
97 +        sprintf(painCave.errMsg,
98 +                "ThermoIntegration Warning: the spring constant for the\n"
99 +                "\tspin orientational restraint was not specified. OOPSE\n"
100 +                "\twill use a default value of %f. To set it to something\n"
101 +                "\telse, use the thermIntOmegaSpringConst variable.\n",
102 +                kOmega);
103 +        painCave.isFatal = 0;
104 +        simError();
105 +      }
106      }
107 < #ifdef IS_MPI
107 >    
108 >    // build a RestReader and read in important information
109 >    
110 >    restRead_ = new RestReader(info_);
111 >    restRead_->readIdealCrystal();
112 >    restRead_->readZangle();
113 >    
114 >    delete restRead_;
115 >    restRead_ = NULL;
116 >    
117    }
118    
119 <  MPI_Bcast(&kDist, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
120 <  MPI_Bcast(&kTheta, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
101 <  MPI_Bcast(&kOmega, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
119 >  Restraints::~Restraints(){
120 >  }
121    
122 <  sprintf( checkPointMsg,
123 <           "Sucessfully opened and read spring file.\n");
124 <  MPIcheckPoint();
125 <
126 < #endif // is_mpi
122 >  void Restraints::Calc_rVal(Vector3d &position, double refPosition[3]){
123 >    delRx = position.x() - refPosition[0];
124 >    delRy = position.y() - refPosition[1];
125 >    delRz = position.z() - refPosition[2];
126 >    
127 >    return;
128 >  }
129    
130 <  sprintf(painCave.errMsg,
131 <          "The spring constants for thermodynamic integration are:\n"
132 <          "\tkDist = %lf\n"
133 <          "\tkTheta = %lf\n"
134 <          "\tkOmega = %lf\n", kDist, kTheta, kOmega);
135 <  painCave.severity = OOPSE_INFO;
136 <  painCave.isFatal = 0;
137 <  simError();  
138 < }
139 <
140 < Restraints::~Restraints(){
141 < }
142 <
143 < void Restraints::Calc_rVal(double position[3], int currentMol){
144 <  delRx = position[0] - cofmPosX[currentMol];
145 <  delRy = position[1] - cofmPosY[currentMol];
146 <  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;
130 >  void Restraints::Calc_body_thetaVal(RotMat3x3d &matrix, double refUnit[3]){
131 >    ub0x = matrix(0,0)*refUnit[0] + matrix(0,1)*refUnit[1]
132 >    + matrix(0,2)*refUnit[2];
133 >    ub0y = matrix(1,0)*refUnit[0] + matrix(1,1)*refUnit[1]
134 >      + matrix(1,2)*refUnit[2];
135 >    ub0z = matrix(2,0)*refUnit[0] + matrix(2,1)*refUnit[1]
136 >      + matrix(2,2)*refUnit[2];
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 <  if (omega > PI){
149 <    tempOmega = omega / TWO_PI;
150 <    wholeTwoPis = floor(tempOmega);
151 <    tempOmega = omega - TWO_PI*wholeTwoPis;
152 <    if (tempOmega > PI)
153 <      omega = tempOmega - TWO_PI;  
154 <    else
155 <      omega = tempOmega;
148 >  
149 >  void Restraints::Calc_body_omegaVal(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 <  vb0x = sin(omega);
189 <  vb0y = cos(omega);
190 <  vb0z = 0.0;
191 <
192 <  normalize = sqrt(vb0x*vb0x + vb0y*vb0y + vb0z*vb0z);
193 <  vb0x = vb0x/normalize;
194 <  vb0y = vb0y/normalize;
195 <  vb0z = vb0z/normalize;
196 <
197 <  return;
198 < }
199 <
200 < double Restraints::Calc_Restraint_Forces(vector<StuntDouble*> vecParticles){
201 <  double pos[3];
202 <  double A[3][3];
203 <  double tolerance;
204 <  double tempPotent;
205 <  double factor;
206 <  double spaceTrq[3];
207 <  double omegaPass;
208 <
209 <  tolerance = 5.72957795131e-7;
210 <
211 <  harmPotent = 0.0;  // zero out the global harmonic potential variable
212 <
213 <  factor = 1 - pow(lambdaValue, lambdaK);
214 <
215 <  for (i=0; i<vecParticles.size(); i++){
216 <    if (vecParticles[i]->isDirectional()){
217 <      vecParticles[i]->getPos(pos);
218 <      vecParticles[i]->getA(A);
219 <      Calc_rVal( pos, i );
220 <      Calc_body_thetaVal( A, i );
221 <      omegaPass = vecParticles[i]->getZangle();
222 <      Calc_body_omegaVal( A, omegaPass );
223 <
224 <      // first we calculate the derivatives
225 <      dVdrx = -kDist*delRx;
226 <      dVdry = -kDist*delRy;
227 <      dVdrz = -kDist*delRz;
228 <
229 <      // uTx... and vTx... are the body-fixed z and y unit vectors
230 <      uTx = 0.0;
231 <      uTy = 0.0;
232 <      uTz = 1.0;
233 <      vTx = 0.0;
234 <      vTy = 1.0;
235 <      vTz = 0.0;
236 <
237 <      dVdux = 0;
238 <      dVduy = 0;
239 <      dVduz = 0;
240 <      dVdvx = 0;
241 <      dVdvy = 0;
242 <      dVdvz = 0;
243 <
244 <      if (fabs(theta) > tolerance) {
245 <        dVdux = -(kTheta*theta/sin(theta))*ub0x;
246 <        dVduy = -(kTheta*theta/sin(theta))*ub0y;
247 <        dVduz = -(kTheta*theta/sin(theta))*ub0z;
248 <      }
249 <
250 <      if (fabs(omega) > tolerance) {
251 <        dVdvx = -(kOmega*omega/sin(omega))*vb0x;
252 <        dVdvy = -(kOmega*omega/sin(omega))*vb0y;
253 <        dVdvz = -(kOmega*omega/sin(omega))*vb0z;
187 >  
188 >  double Restraints::Calc_Restraint_Forces(){
189 >    SimInfo::MoleculeIterator mi;
190 >    Molecule* mol;
191 >    Molecule::IntegrableObjectIterator ii;
192 >    StuntDouble* integrableObject;
193 >    Vector3d pos;
194 >    RotMat3x3d A;
195 >    double refPos[3];
196 >    double refVec[3];
197 >    double tolerance;
198 >    double tempPotent;
199 >    double factor;
200 >    double spaceTrq[3];
201 >    double omegaPass;
202 >    GenericData* data;
203 >    DoubleGenericData* doubleData;
204 >    
205 >    tolerance = 5.72957795131e-7;
206 >    
207 >    harmPotent = 0.0;  // zero out the global harmonic potential variable
208 >    
209 >    factor = 1 - pow(lambdaValue, lambdaK);
210 >    
211 >    for (mol = info_->beginMolecule(mi); mol != NULL;
212 >         mol = info_->nextMolecule(mi)) {
213 >      for (integrableObject = mol->beginIntegrableObject(ii);
214 >           integrableObject != NULL;
215 >           integrableObject = mol->nextIntegrableObject(ii)) {
216 >        
217 >        // obtain the current and reference positions
218 >        pos = integrableObject->getPos();
219 >        
220 >        data = integrableObject->getPropertyByName("refPosX");
221 >        if (data){
222 >          doubleData = dynamic_cast<DoubleGenericData*>(data);
223 >          if (!doubleData){
224 >            cerr << "Can't obtain refPosX from StuntDouble\n";
225 >            return 0.0;
226 >          }
227 >          else refPos[0] = doubleData->getData();
228 >        }
229 >        data = integrableObject->getPropertyByName("refPosY");
230 >        if (data){
231 >          doubleData = dynamic_cast<DoubleGenericData*>(data);
232 >          if (!doubleData){
233 >            cerr << "Can't obtain refPosY from StuntDouble\n";
234 >            return 0.0;
235 >          }
236 >          else refPos[1] = doubleData->getData();
237 >        }
238 >        data = integrableObject->getPropertyByName("refPosZ");
239 >        if (data){
240 >          doubleData = dynamic_cast<DoubleGenericData*>(data);
241 >          if (!doubleData){
242 >            cerr << "Can't obtain refPosZ from StuntDouble\n";
243 >            return 0.0;
244 >          }
245 >          else refPos[2] = doubleData->getData();
246 >        }
247 >        
248 >        // calculate the displacement
249 >        Calc_rVal( pos, refPos );
250 >        
251 >        // calculate the derivatives
252 >        dVdrx = -kDist*delRx;
253 >        dVdry = -kDist*delRy;
254 >        dVdrz = -kDist*delRz;
255 >        
256 >        // next we calculate the restraint forces
257 >        restraintFrc[0] = dVdrx;
258 >        restraintFrc[1] = dVdry;
259 >        restraintFrc[2] = dVdrz;
260 >        tempPotent = 0.5*kDist*(delRx*delRx + delRy*delRy + delRz*delRz);
261 >        
262 >        // apply the lambda scaling factor to the forces
263 >        for (j = 0; j < 3; j++) restraintFrc[j] *= factor;
264 >        
265 >        // and add the temporary force to the total force
266 >        integrableObject->addFrc(restraintFrc);
267 >        
268 >        // if the particle is directional, we accumulate the rot. restraints
269 >        if (integrableObject->isDirectional()){
270 >          
271 >          // get the current rotation matrix and reference vector
272 >          A = integrableObject->getA();
273 >          
274 >          data = integrableObject->getPropertyByName("refVectorX");
275 >          if (data){
276 >            doubleData = dynamic_cast<DoubleGenericData*>(data);
277 >            if (!doubleData){
278 >              cerr << "Can't obtain refVectorX from StuntDouble\n";
279 >              return 0.0;
280 >            }
281 >            else refVec[0] = doubleData->getData();
282 >          }
283 >          data = integrableObject->getPropertyByName("refVectorY");
284 >          if (data){
285 >            doubleData = dynamic_cast<DoubleGenericData*>(data);
286 >            if (!doubleData){
287 >              cerr << "Can't obtain refVectorY from StuntDouble\n";
288 >              return 0.0;
289 >            }
290 >            else refVec[1] = doubleData->getData();
291 >          }
292 >          data = integrableObject->getPropertyByName("refVectorZ");
293 >          if (data){
294 >            doubleData = dynamic_cast<DoubleGenericData*>(data);
295 >            if (!doubleData){
296 >              cerr << "Can't obtain refVectorZ from StuntDouble\n";
297 >              return 0.0;
298 >            }
299 >            else refVec[2] = doubleData->getData();
300 >          }
301 >          
302 >          // calculate the theta and omega displacements
303 >          Calc_body_thetaVal( A, refVec );
304 >          omegaPass = integrableObject->getZangle();
305 >          Calc_body_omegaVal( omegaPass );
306 >          
307 >          // uTx... and vTx... are the body-fixed z and y unit vectors
308 >          uTx = 0.0;
309 >          uTy = 0.0;
310 >          uTz = 1.0;
311 >          vTx = 0.0;
312 >          vTy = 1.0;
313 >          vTz = 0.0;
314 >          
315 >          dVdux = 0.0;
316 >          dVduy = 0.0;
317 >          dVduz = 0.0;
318 >          dVdvx = 0.0;
319 >          dVdvy = 0.0;
320 >          dVdvz = 0.0;
321 >          
322 >          if (fabs(theta) > tolerance) {
323 >            dVdux = -(kTheta*theta/sin(theta))*ub0x;
324 >            dVduy = -(kTheta*theta/sin(theta))*ub0y;
325 >            dVduz = -(kTheta*theta/sin(theta))*ub0z;
326 >          }
327 >          
328 >          if (fabs(omega) > tolerance) {
329 >            dVdvx = -(kOmega*omega/sin(omega))*vb0x;
330 >            dVdvy = -(kOmega*omega/sin(omega))*vb0y;
331 >            dVdvz = -(kOmega*omega/sin(omega))*vb0z;
332 >          }
333 >          
334 >          // next we calculate the restraint torques
335 >          restraintTrq[0] = 0.0;
336 >          restraintTrq[1] = 0.0;
337 >          restraintTrq[2] = 0.0;
338 >          
339 >          if (fabs(omega) > tolerance) {
340 >            restraintTrq[0] += 0.0;
341 >            restraintTrq[1] += 0.0;
342 >            restraintTrq[2] += vTy*dVdvx;
343 >            tempPotent += 0.5*(kOmega*omega*omega);
344 >          }
345 >          if (fabs(theta) > tolerance) {
346 >            restraintTrq[0] += (uTz*dVduy);
347 >            restraintTrq[1] += -(uTz*dVdux);
348 >            restraintTrq[2] += 0.0;
349 >            tempPotent += 0.5*(kTheta*theta*theta);
350 >          }
351 >          
352 >          // apply the lambda scaling factor to these torques
353 >          for (j = 0; j < 3; j++) restraintTrq[j] *= factor;
354 >          
355 >          // now we need to convert from body-fixed to space-fixed torques
356 >          spaceTrq[0] = A(0,0)*restraintTrq[0] + A(1,0)*restraintTrq[1]
357 >            + A(2,0)*restraintTrq[2];
358 >          spaceTrq[1] = A(0,1)*restraintTrq[0] + A(1,1)*restraintTrq[1]
359 >            + A(2,1)*restraintTrq[2];
360 >          spaceTrq[2] = A(0,2)*restraintTrq[0] + A(1,2)*restraintTrq[1]
361 >            + A(2,2)*restraintTrq[2];
362 >          
363 >          // now pass this temporary torque vector to the total torque
364 >          integrableObject->addTrq(spaceTrq);
365 >        }
366 >        
367 >        // update the total harmonic potential with this object's contribution
368 >        harmPotent += tempPotent;
369        }
370 <
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);
370 >      
371      }
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  int idealSize;
296  double pos[3];
297  double A[3][3];
298  double RfromQ[3][3];
299  double quat0, quat1, quat2, quat3;
300  double dot;
301  vector<double> tempZangs;
302  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  // check to see if these files are present in the execution directory
312  if (!crystalIn) {
313    sprintf(painCave.errMsg,
314            "Restraints Error: Unable to open idealCrystal.in for reading.\n"
315            "\tMake sure a ref. crystal file is in the working directory.\n");
316    painCave.severity = OOPSE_ERROR;
317    painCave.isFatal = 1;
318    simError();  
319  }
320
321  // it's not fatal to lack a zAngle.ang file, it just means you're starting
322  // from the ideal crystal state
323  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            "\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    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  // 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  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;
372      
373 <    normalize = sqrt(RfromQ[2][0]*RfromQ[2][0] + RfromQ[2][1]*RfromQ[2][1]
374 <                     + RfromQ[2][2]*RfromQ[2][2]);
375 <    uX0.push_back(RfromQ[2][0]/normalize);
376 <    uY0.push_back(RfromQ[2][1]/normalize);
377 <    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);
373 >    // we can finish by returning the appropriately scaled potential energy
374 >    tempPotent = harmPotent * factor;
375 >    
376 >    return tempPotent;
377 >    
378    }
379 <  crystalIn.close();
380 <
408 <  // now we read in the zAngle.ang file
409 <  if (angleIn){
410 <    angleIn.getline(inLine,999,'\n');
411 <    angleIn.getline(inLine,999,'\n');
412 <    while (!angleIn.eof()) {
413 <      token = strtok(inLine,delimit);
414 <      strcpy(inValue,token);
415 <      tempZangs.push_back(atof(inValue));
416 <      angleIn.getline(inLine,999,'\n');
417 <    }
418 <
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 <  }
434 <  angleIn.close();
435 <
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 <
379 >  
380 > }// end namespace oopse

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines