48#include "restraints/RestraintForceModifier.hpp"
59#include "brains/ForceModifier.hpp"
61#include "restraints/MolecularRestraint.hpp"
62#include "restraints/ObjectRestraint.hpp"
63#include "selection/SelectionEvaluator.hpp"
64#include "selection/SelectionManager.hpp"
65#include "utils/Constants.hpp"
68#include "utils/simError.h"
72 RestraintForceModifier::RestraintForceModifier(
SimInfo* info) :
87 Globals* simParam = info_->getSimParams();
88 currSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
90 currRestTime_ = currSnapshot_->getTime();
92 if (simParam->haveStatusTime()) {
93 restTime_ = simParam->getStatusTime();
95 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
96 "Restraint warning: If you use restraints without setting\n"
97 "\tstatusTime, no restraint data will be written to the rest\n"
101 restTime_ = simParam->getRunTime();
104 int nRestraintStamps = simParam->getNRestraintStamps();
105 std::vector<RestraintStamp*> stamp = simParam->getRestraintStamps();
107 std::vector<int> stuntDoubleIndex;
109 for (
int i = 0; i < nRestraintStamps; i++) {
110 std::string myType = toUpperCopy(stamp[i]->getType());
112 if (myType.compare(
"MOLECULAR") == 0) {
116 if (!stamp[i]->haveMolIndex()) {
117 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
118 "Restraint Error: A molecular restraint was specified\n"
119 "\twithout providing a value for molIndex.\n");
120 painCave.isFatal = 1;
123 molIndex = stamp[i]->getMolIndex();
127 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
128 "Restraint Error: A molecular restraint was specified\n"
129 "\twith a molIndex that was less than 0\n");
130 painCave.isFatal = 1;
133 if (molIndex >= info_->getNGlobalMolecules()) {
134 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
135 "Restraint Error: A molecular restraint was specified with\n"
136 "\ta molIndex that was greater than the total number of "
138 painCave.isFatal = 1;
142 Molecule* mol = info_->getMoleculeByGlobalIndex(molIndex);
151 MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
153 if (info_->getMolToProc(molIndex) == myrank) {
158 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
159 "Restraint Error: A molecular restraint was specified, but\n"
160 "\tno molecule was found with global index %d.\n",
162 painCave.isFatal = 1;
174 MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
175 if (info_->getMolToProc(molIndex) == myrank) {
178 MolecularRestraint* rest =
new MolecularRestraint();
180 std::string restPre(
"mol_");
181 std::stringstream restName;
182 restName << restPre << molIndex;
183 rest->setRestraintName(restName.str());
185 if (stamp[i]->haveDisplacementSpringConstant()) {
186 rest->setDisplacementForceConstant(
187 stamp[i]->getDisplacementSpringConstant());
189 if (stamp[i]->haveDisplacementXSpringConstant()) {
190 rest->setDisplacementXForceConstant(
191 stamp[i]->getDisplacementXSpringConstant());
193 if (stamp[i]->haveDisplacementYSpringConstant()) {
194 rest->setDisplacementYForceConstant(
195 stamp[i]->getDisplacementYSpringConstant());
197 if (stamp[i]->haveDisplacementZSpringConstant()) {
198 rest->setDisplacementZForceConstant(
199 stamp[i]->getDisplacementZSpringConstant());
201 if (stamp[i]->haveAbsoluteSpringConstant()) {
202 rest->setAbsoluteForceConstant(
203 stamp[i]->getAbsoluteSpringConstant());
205 if (stamp[i]->haveTwistSpringConstant()) {
206 rest->setTwistForceConstant(stamp[i]->getTwistSpringConstant());
208 if (stamp[i]->haveSwingXSpringConstant()) {
209 rest->setSwingXForceConstant(stamp[i]->getSwingXSpringConstant());
211 if (stamp[i]->haveSwingYSpringConstant()) {
212 rest->setSwingYForceConstant(stamp[i]->getSwingYSpringConstant());
214 if (stamp[i]->haveAbsolutePositionZ()) {
215 rest->setAbsolutePositionZ(stamp[i]->getAbsolutePositionZ());
217 if (stamp[i]->haveRestrainedTwistAngle()) {
218 rest->setRestrainedTwistAngle(stamp[i]->getRestrainedTwistAngle() *
219 Constants::PI / 180.0);
221 if (stamp[i]->haveRestrainedSwingYAngle()) {
222 rest->setRestrainedSwingYAngle(
223 stamp[i]->getRestrainedSwingYAngle() * Constants::PI / 180.0);
225 if (stamp[i]->haveRestrainedSwingXAngle()) {
226 rest->setRestrainedSwingXAngle(
227 stamp[i]->getRestrainedSwingXAngle() * Constants::PI / 180.0);
229 if (stamp[i]->havePrint()) {
230 rest->setPrintRestraint(stamp[i]->getPrint());
233 restraints_.push_back(rest);
234 mol->addProperty(std::make_shared<RestraintData>(
"Restraint", rest));
235 restrainedMols_.push_back(mol);
239 }
else if (myType.compare(
"OBJECT") == 0) {
240 std::string objectSelection;
242 if (!stamp[i]->haveObjectSelection()) {
243 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
244 "Restraint Error: An object restraint was specified\n"
245 "\twithout providing a selection script in the\n"
246 "\tobjectSelection variable.\n");
247 painCave.isFatal = 1;
250 objectSelection = stamp[i]->getObjectSelection();
253 SelectionEvaluator evaluator(info);
254 SelectionManager seleMan(info);
256 evaluator.loadScriptString(objectSelection);
257 seleMan.setSelectionSet(evaluator.evaluate());
258 int selectionCount = seleMan.getSelectionCount();
261 MPI_Allreduce(MPI_IN_PLACE, &selectionCount, 1, MPI_INT, MPI_SUM,
265 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
266 "Restraint Info: The specified restraint objectSelection,\n"
268 "\twill result in %d integrable objects being\n"
270 objectSelection.c_str(), selectionCount);
271 painCave.severity = OPENMD_INFO;
272 painCave.isFatal = 0;
278 for (sd = seleMan.beginSelected(selei); sd != NULL;
279 sd = seleMan.nextSelected(selei)) {
280 stuntDoubleIndex.push_back(sd->getGlobalIntegrableObjectIndex());
282 ObjectRestraint* rest =
new ObjectRestraint();
284 if (stamp[i]->haveDisplacementSpringConstant()) {
285 rest->setDisplacementForceConstant(
286 stamp[i]->getDisplacementSpringConstant());
288 if (stamp[i]->haveDisplacementXSpringConstant()) {
289 rest->setDisplacementXForceConstant(
290 stamp[i]->getDisplacementXSpringConstant());
292 if (stamp[i]->haveDisplacementYSpringConstant()) {
293 rest->setDisplacementYForceConstant(
294 stamp[i]->getDisplacementYSpringConstant());
296 if (stamp[i]->haveDisplacementZSpringConstant()) {
297 rest->setDisplacementZForceConstant(
298 stamp[i]->getDisplacementZSpringConstant());
300 if (stamp[i]->haveAbsoluteSpringConstant()) {
301 rest->setAbsoluteForceConstant(
302 stamp[i]->getAbsoluteSpringConstant());
304 if (stamp[i]->haveTwistSpringConstant()) {
305 rest->setTwistForceConstant(stamp[i]->getTwistSpringConstant());
307 if (stamp[i]->haveSwingXSpringConstant()) {
308 rest->setSwingXForceConstant(stamp[i]->getSwingXSpringConstant());
310 if (stamp[i]->haveSwingYSpringConstant()) {
311 rest->setSwingYForceConstant(stamp[i]->getSwingYSpringConstant());
313 if (stamp[i]->haveAbsolutePositionZ()) {
314 rest->setAbsolutePositionZ(stamp[i]->getAbsolutePositionZ());
316 if (stamp[i]->haveRestrainedTwistAngle()) {
317 rest->setRestrainedTwistAngle(stamp[i]->getRestrainedTwistAngle());
319 if (stamp[i]->haveRestrainedSwingXAngle()) {
320 rest->setRestrainedSwingXAngle(
321 stamp[i]->getRestrainedSwingXAngle());
323 if (stamp[i]->haveRestrainedSwingYAngle()) {
324 rest->setRestrainedSwingYAngle(
325 stamp[i]->getRestrainedSwingYAngle());
327 if (stamp[i]->havePrint()) {
328 rest->setPrintRestraint(stamp[i]->getPrint());
331 restraints_.push_back(rest);
332 sd->addProperty(std::make_shared<RestraintData>(
"Restraint", rest));
333 restrainedObjs_.push_back(sd);
341 if (simParam->getUseRestraints()) {
342 std::string refFile = simParam->getRestraint_file();
343 RestReader* rr =
new RestReader(info, refFile, stuntDoubleIndex);
344 rr->readReferenceStructure();
348 restOutput_ =
getPrefix(info_->getFinalConfigFileName()) +
".rest";
349 restOut =
new RestWriter(info_, restOutput_.c_str(), restraints_);
351 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
352 "Restraint error: Failed to create RestWriter\n");
353 painCave.isFatal = 1;
358 std::vector<Restraint*>::const_iterator resti;
359 for (resti = restraints_.begin(); resti != restraints_.end(); ++resti) {
360 (*resti)->setScaleFactor(1.0);
364 RestraintForceModifier::~RestraintForceModifier() {
365 Utils::deletePointers(restraints_);
370 void RestraintForceModifier::modifyForces() {
371 RealType restPot(0.0);
373 restPot = doRestraints(1.0);
376 MPI_Allreduce(MPI_IN_PLACE, &restPot, 1, MPI_REALTYPE, MPI_SUM,
380 currSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
381 RealType rp = currSnapshot_->getRestraintPotential();
382 currSnapshot_->setRestraintPotential(rp + restPot);
384 RealType pe = currSnapshot_->getPotentialEnergy();
385 currSnapshot_->setRawPotential(pe);
386 currSnapshot_->setPotentialEnergy(pe + restPot);
389 if (currSnapshot_->getTime() >= currRestTime_) {
390 restOut->writeRest(restInfo_);
391 currRestTime_ += restTime_;
395 RealType RestraintForceModifier::doRestraints(RealType scalingFactor) {
396 std::vector<Molecule*>::const_iterator rm;
397 std::shared_ptr<GenericData> data;
398 Molecule::IntegrableObjectIterator ioi;
399 MolecularRestraint* mRest = NULL;
400 ObjectRestraint* oRest = NULL;
403 std::vector<StuntDouble*>::const_iterator ro;
405 std::map<int, Restraint::RealPair> restInfo;
407 unscaledPotential_ = 0.0;
411 for (rm = restrainedMols_.begin(); rm != restrainedMols_.end(); ++rm) {
413 data = (*rm)->getPropertyByName(
"Restraint");
414 if (data !=
nullptr) {
416 std::shared_ptr<RestraintData> restData =
417 std::dynamic_pointer_cast<RestraintData>(data);
418 if (restData !=
nullptr) {
421 mRest =
dynamic_cast<MolecularRestraint*
>(restData->getData());
423 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
424 "Can not cast RestraintData to MolecularRestraint\n");
425 painCave.severity = OPENMD_ERROR;
426 painCave.isFatal = 1;
430 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
431 "Can not cast GenericData to RestraintData\n");
432 painCave.severity = OPENMD_ERROR;
433 painCave.isFatal = 1;
437 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
438 "Can not find Restraint for RestrainedObject\n");
439 painCave.severity = OPENMD_ERROR;
440 painCave.isFatal = 1;
447 Vector3d molCom = (*rm)->getCom();
449 std::vector<Vector3d> struc;
450 std::vector<Vector3d> forces;
452 for (sd = (*rm)->beginIntegrableObject(ioi); sd != NULL;
453 sd = (*rm)->nextIntegrableObject(ioi)) {
454 struc.push_back(sd->getPos());
457 mRest->setScaleFactor(scalingFactor);
458 mRest->calcForce(struc, molCom);
459 forces = mRest->getRestraintForces();
462 for (sd = (*rm)->beginIntegrableObject(ioi); sd != NULL;
463 sd = (*rm)->nextIntegrableObject(ioi)) {
464 sd->addFrc(forces[index]);
465 struc.push_back(sd->getPos());
469 unscaledPotential_ += mRest->getUnscaledPotential();
472 if (mRest->getPrintRestraint()) {
473 restInfo = mRest->getRestraintInfo();
474 restInfo_.push_back(restInfo);
478 for (ro = restrainedObjs_.begin(); ro != restrainedObjs_.end(); ++ro) {
480 data = (*ro)->getPropertyByName(
"Restraint");
483 std::shared_ptr<RestraintData> restData =
484 std::dynamic_pointer_cast<RestraintData>(data);
485 if (restData !=
nullptr) {
488 oRest =
dynamic_cast<ObjectRestraint*
>(restData->getData());
490 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
491 "Can not cast RestraintData to ObjectRestraint\n");
492 painCave.severity = OPENMD_ERROR;
493 painCave.isFatal = 1;
497 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
498 "Can not cast GenericData to RestraintData\n");
499 painCave.severity = OPENMD_ERROR;
500 painCave.isFatal = 1;
504 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
505 "Can not find Restraint for RestrainedObject\n");
506 painCave.severity = OPENMD_ERROR;
507 painCave.isFatal = 1;
513 oRest->setScaleFactor(scalingFactor);
515 Vector3d pos = (*ro)->getPos();
517 if ((*ro)->isDirectional()) {
521 RotMat3x3d A = (*ro)->getA();
522 oRest->calcForce(pos, A);
523 (*ro)->addFrc(oRest->getRestraintForce());
524 (*ro)->addTrq(oRest->getRestraintTorque());
529 oRest->calcForce(pos);
530 (*ro)->addFrc(oRest->getRestraintForce());
533 unscaledPotential_ += oRest->getUnscaledPotential();
536 if (oRest->getPrintRestraint()) {
537 restInfo = oRest->getRestraintInfo();
538 restInfo_.push_back(restInfo);
542 return unscaledPotential_ * scalingFactor;
Abstract class for external ForceModifier classes.
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
std::string getPrefix(const std::string &str)