ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/restraints/RestraintForceManager.cpp
Revision: 1360
Committed: Mon Sep 7 16:31:51 2009 UTC (15 years, 7 months ago) by cli2
File size: 15741 byte(s)
Log Message:
Added new restraint infrastructure
Added MolecularRestraints
Added ObjectRestraints
Added RestraintStamp
Updated thermodynamic integration to use ObjectRestraints
Added Quaternion mathematics for twist swing decompositions
Significantly updated RestWriter and RestReader to use dump-like files
Added selections for x, y, and z coordinates of atoms
Removed monolithic Restraints class
Fixed a few bugs in gradients of Euler angles in DirectionalAtom and RigidBody
Added some rotational capabilities to prinicpalAxisCalculator

File Contents

# User Rev Content
1 cli2 1360 /*
2     * Copyright (c) 2009 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    
42     #include <cmath>
43     #include "restraints/RestraintForceManager.hpp"
44     #include "restraints/MolecularRestraint.hpp"
45     #include "restraints/ObjectRestraint.hpp"
46     #include "io/RestReader.hpp"
47     #include "utils/simError.h"
48     #include "utils/OOPSEConstant.hpp"
49     #include "utils/StringUtils.hpp"
50     #include "selection/SelectionEvaluator.hpp"
51     #include "selection/SelectionManager.hpp"
52     #ifdef IS_MPI
53     #include <mpi.h>
54     #endif
55    
56    
57     namespace oopse {
58    
59     RestraintForceManager::RestraintForceManager(SimInfo* info): ForceManager(info) {
60    
61     // order of affairs:
62     //
63     // 1) create restraints from the restraintStamps found in the MD
64     // file.
65     //
66     // 2) Create RestraintReader to parse the input files for the ideal
67     // structures. This reader will set reference structures, and will
68     // calculate molecular centers of mass, etc.
69     //
70     // 3) sit around and wait for calcForces to be called. When it comes,
71     // call the normal force manager calcForces, then loop through the
72     // restrained objects and do their restraint forces.
73    
74     currSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
75     Globals* simParam = info_->getSimParams();
76    
77     if (simParam->haveStatusTime()){
78     restTime_ = simParam->getStatusTime();
79     } else {
80     sprintf(painCave.errMsg,
81     "Restraint warning: If you use restraints without setting\n",
82     "\tstatusTime, no restraint data will be written to the rest\n",
83     "\tfile.\n");
84     painCave.isFatal = 0;
85     simError();
86     restTime_ = simParam->getRunTime();
87     }
88    
89     int nRestraintStamps = simParam->getNRestraintStamps();
90     std::vector<RestraintStamp*> stamp = simParam->getRestraintStamps();
91    
92     for (int i = 0; i < nRestraintStamps; i++){
93    
94     std::string myType = toUpperCopy(stamp[i]->getType());
95    
96     if (myType.compare("MOLECULAR")==0){
97    
98     int molIndex;
99     std::vector<Vector3d> ref;
100     Vector3d refCom;
101    
102     if (!stamp[i]->haveMolIndex()) {
103     sprintf(painCave.errMsg,
104     "Restraint Error: A molecular restraint was specified\n"
105     "\twithout providing a value for molIndex.\n");
106     painCave.isFatal = 1;
107     simError();
108     } else {
109     molIndex = stamp[i]->getMolIndex();
110     }
111    
112     Molecule* mol = info_->getMoleculeByGlobalIndex(molIndex);
113    
114     if (mol == NULL) {
115     sprintf(painCave.errMsg,
116     "Restraint Error: A molecular restraint was specified, but\n"
117     "\tno molecule was found with global index %d.\n",
118     molIndex);
119     painCave.isFatal = 1;
120     simError();
121     }
122    
123     MolecularRestraint* rest = new MolecularRestraint();
124    
125     std::string restPre("mol_");
126     std::stringstream restName;
127     restName << restPre << molIndex;
128     rest->setRestraintName(restName.str());
129    
130     if (stamp[i]->haveDisplacementSpringConstant()) {
131     rest->setDisplacementForceConstant(stamp[i]->getDisplacementSpringConstant());
132     }
133     if (stamp[i]->haveTwistSpringConstant()) {
134     rest->setTwistForceConstant(stamp[i]->getTwistSpringConstant());
135     }
136     if (stamp[i]->haveSwingXSpringConstant()) {
137     rest->setSwingXForceConstant(stamp[i]->getSwingXSpringConstant());
138     }
139     if (stamp[i]->haveSwingYSpringConstant()) {
140     rest->setSwingYForceConstant(stamp[i]->getSwingYSpringConstant());
141     }
142     if (stamp[i]->haveRestrainedTwistAngle()) {
143     rest->setRestrainedTwistAngle(stamp[i]->getRestrainedTwistAngle() * M_PI/180.0);
144     }
145     if (stamp[i]->haveRestrainedSwingYAngle()) {
146     rest->setRestrainedSwingYAngle(stamp[i]->getRestrainedSwingYAngle() * M_PI/180.0);
147     }
148     if (stamp[i]->haveRestrainedSwingXAngle()) {
149     rest->setRestrainedSwingXAngle(stamp[i]->getRestrainedSwingXAngle() * M_PI/180.0);
150     }
151    
152     restraints_.push_back(rest);
153     mol->addProperty(new RestraintData("Restraint", rest));
154     restrainedMols_.push_back(mol);
155    
156     } else if (myType.compare("OBJECT") == 0) {
157    
158     std::string objectSelection;
159    
160     if (!stamp[i]->haveObjectSelection()) {
161     sprintf(painCave.errMsg,
162     "Restraint Error: An object restraint was specified\n"
163     "\twithout providing a selection script in the\n"
164     "\tobjectSelection variable.\n");
165     painCave.isFatal = 1;
166     simError();
167     } else {
168     objectSelection = stamp[i]->getObjectSelection();
169     }
170    
171     SelectionEvaluator evaluator(info);
172     SelectionManager seleMan(info);
173    
174     evaluator.loadScriptString(objectSelection);
175     seleMan.setSelectionSet(evaluator.evaluate());
176     int selectionCount = seleMan.getSelectionCount();
177    
178     sprintf(painCave.errMsg,
179     "Restraint Info: The specified restraint objectSelection,\n"
180     "\t\t%s\n"
181     "\twill result in %d integrable objects being\n"
182     "\trestrained.\n", objectSelection.c_str(), selectionCount);
183     painCave.isFatal = 0;
184     simError();
185    
186     int selei;
187     StuntDouble* sd;
188    
189     for (sd = seleMan.beginSelected(selei); sd != NULL;
190     sd = seleMan.nextSelected(selei)) {
191    
192     ObjectRestraint* rest = new ObjectRestraint();
193    
194     if (stamp[i]->haveDisplacementSpringConstant()) {
195     rest->setDisplacementForceConstant(stamp[i]->getDisplacementSpringConstant());
196     }
197     if (stamp[i]->haveTwistSpringConstant()) {
198     rest->setTwistForceConstant(stamp[i]->getTwistSpringConstant());
199     }
200     if (stamp[i]->haveSwingXSpringConstant()) {
201     rest->setSwingXForceConstant(stamp[i]->getSwingXSpringConstant());
202     }
203     if (stamp[i]->haveSwingYSpringConstant()) {
204     rest->setSwingYForceConstant(stamp[i]->getSwingYSpringConstant());
205     }
206     if (stamp[i]->haveRestrainedTwistAngle()) {
207     rest->setRestrainedTwistAngle(stamp[i]->getRestrainedTwistAngle());
208     }
209     if (stamp[i]->haveRestrainedSwingXAngle()) {
210     rest->setRestrainedSwingXAngle(stamp[i]->getRestrainedSwingXAngle());
211     }
212     if (stamp[i]->haveRestrainedSwingYAngle()) {
213     rest->setRestrainedSwingYAngle(stamp[i]->getRestrainedSwingYAngle());
214     }
215     restraints_.push_back(rest);
216     sd->addProperty(new RestraintData("Restraint", rest));
217     restrainedObjs_.push_back(sd);
218     }
219    
220     }
221     }
222    
223     // ThermodynamicIntegration subclasses RestraintForceManager, and there
224     // are times when it won't use restraints at all, so only open the
225     // restraint file if we are actually using restraints:
226    
227     if (simParam->getUseRestraints()) {
228     std::string refFile = simParam->getRestraint_file();
229     RestReader* rr = new RestReader(info, refFile);
230    
231     rr->readReferenceStructure();
232     }
233    
234     restOutput_ = getPrefix(info_->getFinalConfigFileName()) + ".rest";
235     restOut = new RestWriter(info_, restOutput_.c_str(), restraints_);
236    
237     if(!restOut){
238     sprintf(painCave.errMsg, "Restraint error: Failed to create RestWriter\n");
239     painCave.isFatal = 1;
240     simError();
241     }
242    
243     // todo: figure out the scale factor. Right now, just scale them all to 1
244     std::vector<Restraint*>::const_iterator resti;
245     for(resti=restraints_.begin(); resti != restraints_.end(); ++resti){
246     (*resti)->setScaleFactor(1.0);
247     }
248     }
249    
250     RestraintForceManager::~RestraintForceManager(){
251     if (restOut)
252     delete restOut;
253     }
254    
255     void RestraintForceManager::init() {
256     currRestTime_ = currSnapshot_->getTime();
257     }
258    
259     void RestraintForceManager::calcForces(bool needPotential, bool needStress){
260    
261     ForceManager::calcForces(needPotential, needStress);
262     RealType restPot_local, restPot;
263    
264     restPot_local = doRestraints(1.0);
265    
266     #ifdef IS_MPI
267     MPI::COMM_WORLD.Allreduce(&restPot_local, &restPot, 1,
268     MPI::REALTYPE, MPI::SUM);
269     #else
270     restPot = restPot_local;
271     #endif
272     currSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
273     currSnapshot_->statData[Stats::LONG_RANGE_POTENTIAL] += restPot;
274     currSnapshot_->statData[Stats::VHARM] = restPot;
275    
276     //write out forces and current positions of restrained molecules
277     if (currSnapshot_->getTime() >= currRestTime_){
278     restOut->writeRest(restInfo_);
279     currRestTime_ += restTime_;
280     }
281     }
282    
283     RealType RestraintForceManager::doRestraints(RealType scalingFactor){
284     std::vector<Molecule*>::const_iterator rm;
285     GenericData* data;
286     Molecule::IntegrableObjectIterator ioi;
287     MolecularRestraint* mRest;
288     StuntDouble* sd;
289     RealType pTot;
290    
291     std::vector<StuntDouble*>::const_iterator ro;
292     ObjectRestraint* oRest;
293    
294     std::map<int, Restraint::RealPair> restInfo;
295    
296     unscaledPotential_ = 0.0;
297    
298     restInfo_.clear();
299    
300     for(rm=restrainedMols_.begin(); rm != restrainedMols_.end(); ++rm){
301    
302     // make sure this molecule (*rm) has a generic data for restraints:
303     data = (*rm)->getPropertyByName("Restraint");
304     if (data != NULL) {
305     // make sure we can reinterpret the generic data as restraint data:
306     RestraintData* restData= dynamic_cast<RestraintData*>(data);
307     if (restData != NULL) {
308     // make sure we can reinterpet the restraint data as a pointer to
309     // an MolecularRestraint:
310     mRest = dynamic_cast<MolecularRestraint*>(restData->getData());
311     if (mRest == NULL) {
312     sprintf( painCave.errMsg,
313     "Can not cast RestraintData to MolecularRestraint\n");
314     painCave.severity = OOPSE_ERROR;
315     painCave.isFatal = 1;
316     simError();
317     }
318     } else {
319     sprintf( painCave.errMsg,
320     "Can not cast GenericData to RestraintData\n");
321     painCave.severity = OOPSE_ERROR;
322     painCave.isFatal = 1;
323     simError();
324     }
325     } else {
326     sprintf( painCave.errMsg, "Can not find Restraint for RestrainedObject\n");
327     painCave.severity = OOPSE_ERROR;
328     painCave.isFatal = 1;
329     simError();
330     }
331    
332     // phew. At this point, we should have the pointer to the
333     // correct MolecularRestraint in the variable mRest.
334    
335     Vector3d molCom = (*rm)->getCom();
336    
337     std::vector<Vector3d> struc;
338     std::vector<Vector3d> forces;
339    
340     for(sd = (*rm)->beginIntegrableObject(ioi); sd != NULL;
341     sd = (*rm)->nextIntegrableObject(ioi)) {
342     struc.push_back(sd->getPos());
343     }
344    
345     mRest->setScaleFactor(scalingFactor);
346     mRest->calcForce(struc, molCom);
347     forces = mRest->getRestraintForces();
348     int index = 0;
349    
350     for(sd = (*rm)->beginIntegrableObject(ioi); sd != NULL;
351     sd = (*rm)->nextIntegrableObject(ioi)) {
352     sd->addFrc(forces[index]);
353     struc.push_back(sd->getPos());
354     index++;
355     }
356    
357     unscaledPotential_ += mRest->getUnscaledPotential();
358    
359     restInfo = mRest->getRestraintInfo();
360     restInfo_.push_back(restInfo);
361     }
362    
363     for(ro=restrainedObjs_.begin(); ro != restrainedObjs_.end(); ++ro){
364     // make sure this object (*ro) has a generic data for restraints:
365     data = (*ro)->getPropertyByName("Restraint");
366     if (data != NULL) {
367     // make sure we can reinterpret the generic data as restraint data:
368     RestraintData* restData= dynamic_cast<RestraintData*>(data);
369     if (restData != NULL) {
370     // make sure we can reinterpet the restraint data as a pointer to
371     // an ObjectRestraint:
372     oRest = dynamic_cast<ObjectRestraint*>(restData->getData());
373     if (oRest == NULL) {
374     sprintf( painCave.errMsg,
375     "Can not cast RestraintData to ObjectRestraint\n");
376     painCave.severity = OOPSE_ERROR;
377     painCave.isFatal = 1;
378     simError();
379     }
380     } else {
381     sprintf( painCave.errMsg,
382     "Can not cast GenericData to RestraintData\n");
383     painCave.severity = OOPSE_ERROR;
384     painCave.isFatal = 1;
385     simError();
386     }
387     } else {
388     sprintf( painCave.errMsg, "Can not find Restraint for RestrainedObject\n");
389     painCave.severity = OOPSE_ERROR;
390     painCave.isFatal = 1;
391     simError();
392     }
393    
394     // phew. At this point, we should have the pointer to the
395     // correct Object restraint in the variable oRest.
396    
397     oRest->setScaleFactor(scalingFactor);
398    
399     Vector3d pos = (*ro)->getPos();
400    
401     if ( (*ro)->isDirectional() ) {
402    
403     // directional objects may have orientational restraints as well
404     // as positional, so get the rotation matrix first:
405    
406     RotMat3x3d A = (*ro)->getA();
407     oRest->calcForce(pos, A);
408     (*ro)->addFrc(oRest->getRestraintForce());
409     (*ro)->addTrq(oRest->getRestraintTorque());
410     } else {
411    
412     // plain vanilla positional restraints:
413    
414     oRest->calcForce(pos);
415     (*ro)->addFrc(oRest->getRestraintForce());
416     }
417    
418     unscaledPotential_ += oRest->getUnscaledPotential();
419    
420     restInfo = oRest->getRestraintInfo();
421     restInfo_.push_back(restInfo);
422     }
423    
424     return unscaledPotential_ * scalingFactor;
425     }
426     }

Properties

Name Value
svn:executable *