ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/restraints/Restraints.cpp
Revision: 2101
Committed: Thu Mar 10 15:10:24 2005 UTC (19 years, 4 months ago) by chrisfen
File size: 12967 byte(s)
Log Message:
First commit of the new restraints code

File Contents

# User Rev Content
1 chrisfen 2101 /*
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 chrisfen 1534
42 gezelter 1490 #include <stdlib.h>
43     #include <math.h>
44    
45     using namespace std;
46    
47 gezelter 1537 #include "restraints/Restraints.hpp"
48 chrisfen 2101 #include "primitives/Molecule.hpp"
49 gezelter 1537 #include "utils/simError.h"
50 gezelter 1490
51     #define PI 3.14159265359
52     #define TWO_PI 6.28318530718
53    
54 chrisfen 2101 namespace oopse {
55    
56     Restraints::Restraints(SimInfo* info, double lambdaVal, double lambdaExp){
57     info_ = info;
58     Globals* simParam = info_->getSimParams();
59 gezelter 1490
60 chrisfen 2101 lambdaValue = lambdaVal;
61     lambdaK = lambdaExp;
62 gezelter 1490
63 chrisfen 2101 if (simParam->getUseSolidThermInt()) {
64     if (simParam->haveDistSpringConst()) {
65     kDist = simParam->getDistSpringConst();
66 chrisfen 1534 }
67 chrisfen 2101 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 chrisfen 1534 }
78 chrisfen 2101 if (simParam->haveThetaSpringConst()) {
79     kTheta = simParam->getThetaSpringConst();
80 chrisfen 1534 }
81 chrisfen 2101 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 chrisfen 1534 }
92 chrisfen 2101 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 gezelter 1490 }
107 chrisfen 2101
108     // build a RestReader and read in important information
109     restRead_ = new RestReader(info_);
110     restRead_->readIdealCrystal();
111     restRead_->readZangle();
112    
113     delete restRead_;
114     restRead_ = NULL;
115    
116 gezelter 1490 }
117    
118 chrisfen 2101 Restraints::~Restraints(){
119     }
120 gezelter 1490
121 chrisfen 2101 void Restraints::Calc_rVal(Vector3d &position, double refPosition[3]){
122     delRx = position.x() - refPosition[0];
123     delRy = position.y() - refPosition[1];
124     delRz = position.z() - refPosition[2];
125    
126     return;
127     }
128 gezelter 1490
129 chrisfen 2101 void Restraints::Calc_body_thetaVal(RotMat3x3d &matrix, double refUnit[3]){
130     ub0x = matrix(0,0)*refUnit[0] + matrix(0,1)*refUnit[1]
131     + matrix(0,2)*refUnit[2];
132     ub0y = matrix(1,0)*refUnit[0] + matrix(1,1)*refUnit[1]
133     + matrix(1,2)*refUnit[2];
134     ub0z = matrix(2,0)*refUnit[0] + matrix(2,1)*refUnit[1]
135     + matrix(2,2)*refUnit[2];
136    
137     normalize = sqrt(ub0x*ub0x + ub0y*ub0y + ub0z*ub0z);
138     ub0x = ub0x/normalize;
139     ub0y = ub0y/normalize;
140     ub0z = ub0z/normalize;
141    
142     // Theta is the dot product of the reference and new z-axes
143     theta = acos(ub0z);
144    
145     return;
146 gezelter 1490 }
147 chrisfen 2101
148     void Restraints::Calc_body_omegaVal(double zAngle){
149     double zRotator[3][3];
150     double tempOmega;
151     double wholeTwoPis;
152     // Use the omega accumulated from the rotation propagation
153     omega = zAngle;
154    
155     // translate the omega into a range between -PI and PI
156     if (omega < -PI){
157     tempOmega = omega / -TWO_PI;
158     wholeTwoPis = floor(tempOmega);
159     tempOmega = omega + TWO_PI*wholeTwoPis;
160     if (tempOmega < -PI)
161     omega = tempOmega + TWO_PI;
162     else
163     omega = tempOmega;
164 chrisfen 1772 }
165 chrisfen 2101 if (omega > PI){
166     tempOmega = omega / TWO_PI;
167     wholeTwoPis = floor(tempOmega);
168     tempOmega = omega - TWO_PI*wholeTwoPis;
169     if (tempOmega > PI)
170     omega = tempOmega - TWO_PI;
171     else
172     omega = tempOmega;
173 chrisfen 1772 }
174    
175 chrisfen 2101 vb0x = sin(omega);
176     vb0y = cos(omega);
177     vb0z = 0.0;
178    
179     normalize = sqrt(vb0x*vb0x + vb0y*vb0y + vb0z*vb0z);
180     vb0x = vb0x/normalize;
181     vb0y = vb0y/normalize;
182     vb0z = vb0z/normalize;
183    
184     return;
185     }
186    
187     double Restraints::Calc_Restraint_Forces(){
188     SimInfo::MoleculeIterator mi;
189     Molecule* mol;
190     Molecule::IntegrableObjectIterator ii;
191     StuntDouble* integrableObject;
192     Vector3d pos;
193     RotMat3x3d A;
194     double refPos[3];
195     double refVec[3];
196     double tolerance;
197     double tempPotent;
198     double factor;
199     double spaceTrq[3];
200     double omegaPass;
201     GenericData* data;
202     DoubleGenericData* doubleData;
203    
204     tolerance = 5.72957795131e-7;
205    
206     harmPotent = 0.0; // zero out the global harmonic potential variable
207    
208     factor = 1 - pow(lambdaValue, lambdaK);
209    
210     for (mol = info_->beginMolecule(mi); mol != NULL;
211     mol = info_->nextMolecule(mi)) {
212     for (integrableObject = mol->beginIntegrableObject(ii);
213     integrableObject != NULL;
214     integrableObject = mol->nextIntegrableObject(ii)) {
215    
216     // obtain the current and reference positions
217     pos = integrableObject->getPos();
218    
219     data = integrableObject->getPropertyByName("refPosX");
220     if (data){
221     doubleData = dynamic_cast<DoubleGenericData*>(data);
222     if (!doubleData){
223     cerr << "Can't obtain refPosX from StuntDouble\n";
224     return 0.0;
225     }
226     else refPos[0] = doubleData->getData();
227     }
228     data = integrableObject->getPropertyByName("refPosY");
229     if (data){
230     doubleData = dynamic_cast<DoubleGenericData*>(data);
231     if (!doubleData){
232     cerr << "Can't obtain refPosY from StuntDouble\n";
233     return 0.0;
234     }
235     else refPos[1] = doubleData->getData();
236     }
237     data = integrableObject->getPropertyByName("refPosZ");
238     if (data){
239     doubleData = dynamic_cast<DoubleGenericData*>(data);
240     if (!doubleData){
241     cerr << "Can't obtain refPosZ from StuntDouble\n";
242     return 0.0;
243     }
244     else refPos[2] = doubleData->getData();
245     }
246    
247     // calculate the displacement
248     Calc_rVal( pos, refPos );
249    
250     // calculate the derivatives
251     dVdrx = -kDist*delRx;
252     dVdry = -kDist*delRy;
253     dVdrz = -kDist*delRz;
254    
255     // next we calculate the restraint forces
256     restraintFrc[0] = dVdrx;
257     restraintFrc[1] = dVdry;
258     restraintFrc[2] = dVdrz;
259     tempPotent = 0.5*kDist*(delRx*delRx + delRy*delRy + delRz*delRz);
260    
261     // apply the lambda scaling factor to the forces
262     for (j = 0; j < 3; j++) restraintFrc[j] *= factor;
263    
264     // and add the temporary force to the total force
265     integrableObject->addFrc(restraintFrc);
266    
267     // if the particle is directional, we accumulate the rot. restraints
268     if (integrableObject->isDirectional()){
269    
270     // get the current rotation matrix and reference vector
271     A = integrableObject->getA();
272    
273     data = integrableObject->getPropertyByName("refVectorX");
274     if (data){
275     doubleData = dynamic_cast<DoubleGenericData*>(data);
276     if (!doubleData){
277     cerr << "Can't obtain refVectorX from StuntDouble\n";
278     return 0.0;
279     }
280     else refVec[0] = doubleData->getData();
281     }
282     data = integrableObject->getPropertyByName("refVectorY");
283     if (data){
284     doubleData = dynamic_cast<DoubleGenericData*>(data);
285     if (!doubleData){
286     cerr << "Can't obtain refVectorY from StuntDouble\n";
287     return 0.0;
288     }
289     else refVec[1] = doubleData->getData();
290     }
291     data = integrableObject->getPropertyByName("refVectorZ");
292     if (data){
293     doubleData = dynamic_cast<DoubleGenericData*>(data);
294     if (!doubleData){
295     cerr << "Can't obtain refVectorZ from StuntDouble\n";
296     return 0.0;
297     }
298     else refVec[2] = doubleData->getData();
299     }
300    
301     // calculate the theta and omega displacements
302     Calc_body_thetaVal( A, refVec );
303     omegaPass = integrableObject->getZangle();
304     Calc_body_omegaVal( omegaPass );
305    
306     // uTx... and vTx... are the body-fixed z and y unit vectors
307     uTx = 0.0;
308     uTy = 0.0;
309     uTz = 1.0;
310     vTx = 0.0;
311     vTy = 1.0;
312     vTz = 0.0;
313    
314     dVdux = 0.0;
315     dVduy = 0.0;
316     dVduz = 0.0;
317     dVdvx = 0.0;
318     dVdvy = 0.0;
319     dVdvz = 0.0;
320    
321     if (fabs(theta) > tolerance) {
322     dVdux = -(kTheta*theta/sin(theta))*ub0x;
323     dVduy = -(kTheta*theta/sin(theta))*ub0y;
324     dVduz = -(kTheta*theta/sin(theta))*ub0z;
325     }
326    
327     if (fabs(omega) > tolerance) {
328     dVdvx = -(kOmega*omega/sin(omega))*vb0x;
329     dVdvy = -(kOmega*omega/sin(omega))*vb0y;
330     dVdvz = -(kOmega*omega/sin(omega))*vb0z;
331     }
332    
333     // next we calculate the restraint torques
334     restraintTrq[0] = 0.0;
335     restraintTrq[1] = 0.0;
336     restraintTrq[2] = 0.0;
337    
338     if (fabs(omega) > tolerance) {
339     restraintTrq[0] += 0.0;
340     restraintTrq[1] += 0.0;
341     restraintTrq[2] += vTy*dVdvx;
342     tempPotent += 0.5*(kOmega*omega*omega);
343     }
344     if (fabs(theta) > tolerance) {
345     restraintTrq[0] += (uTz*dVduy);
346     restraintTrq[1] += -(uTz*dVdux);
347     restraintTrq[2] += 0.0;
348     tempPotent += 0.5*(kTheta*theta*theta);
349     }
350    
351     // apply the lambda scaling factor to these torques
352     for (j = 0; j < 3; j++) restraintTrq[j] *= factor;
353    
354     // now we need to convert from body-fixed to space-fixed torques
355     spaceTrq[0] = A(0,0)*restraintTrq[0] + A(1,0)*restraintTrq[1]
356     + A(2,0)*restraintTrq[2];
357     spaceTrq[1] = A(0,1)*restraintTrq[0] + A(1,1)*restraintTrq[1]
358     + A(2,1)*restraintTrq[2];
359     spaceTrq[2] = A(0,2)*restraintTrq[0] + A(1,2)*restraintTrq[1]
360     + A(2,2)*restraintTrq[2];
361    
362     // now pass this temporary torque vector to the total torque
363     integrableObject->addTrq(spaceTrq);
364     }
365    
366     // update the total harmonic potential with this object's contribution
367     harmPotent += tempPotent;
368 chrisfen 1772 }
369    
370 gezelter 1490 }
371 chrisfen 2101
372     // we can finish by returning the appropriately scaled potential energy
373     tempPotent = harmPotent * factor;
374    
375     return tempPotent;
376    
377 gezelter 1490 }
378 chrisfen 1772
379 chrisfen 2101 }// end namespace oopse