48#include "rnemd/SPFForceManager.hpp"
61#include "brains/Snapshot.hpp"
62#include "brains/Thermo.hpp"
65#include "nonbonded/NonBondedInteraction.hpp"
68#include "rnemd/RNEMDParameters.hpp"
69#include "rnemd/SPF.hpp"
70#include "utils/CI_String.hpp"
72namespace OpenMD::RNEMD {
74 SPFForceManager::SPFForceManager(SimInfo* info) :
75 ForceManager {info}, potentialSource_ {}, potentialSink_ {} {
76 thermo_ = std::make_unique<Thermo>(info);
77 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
79 k_ = info_->getSimParams()->getRNEMDParameters()->getSPFScalingPower();
81 int nAtoms = info_->getNAtoms();
82 int nRigidBodies = info_->getNRigidBodies();
83 int nCutoffGroups = info_->getNCutoffGroups();
85 int atomStorageLayout = info_->getSnapshotManager()->getAtomStorageLayout();
87 info_->getSnapshotManager()->getRigidBodyStorageLayout();
89 info_->getSnapshotManager()->getCutoffGroupStorageLayout();
91 bool usePBC = info_->getSimParams()->getUsePeriodicBoundaryConditions();
93 temporarySourceSnapshot_ =
94 new Snapshot(nAtoms, nRigidBodies, nCutoffGroups, atomStorageLayout,
95 rbStorageLayout, cgStorageLayout, usePBC);
97 temporarySinkSnapshot_ =
98 new Snapshot(nAtoms, nRigidBodies, nCutoffGroups, atomStorageLayout,
99 rbStorageLayout, cgStorageLayout, usePBC);
102 SPFForceManager::~SPFForceManager() {
103 delete temporarySourceSnapshot_;
104 delete temporarySinkSnapshot_;
107 void SPFForceManager::calcForces() {
108 std::shared_ptr<SPFData> currentSPFData = currentSnapshot_->getSPFData();
111 setDeltaLambda(spfRNEMD_->spfTarget_);
113 currentSPFData->lambda += deltaLambda_;
120 spfRNEMD_->isValidExchange(v_a, v_b, a, b);
123 ForceManager::calcForces();
124 potentialSource_ = currentSnapshot_->getPotentialEnergy();
126 if (hasSelectedMolecule_) {
127 Vector3d prevSourceCom {}, currentSourceCom {}, delta {};
130 if (selectedMolecule_) {
131 prevSourceCom = selectedMolecule_->getPrevCom();
132 currentSourceCom = selectedMolecule_->getCom();
134 delta = currentSourceCom - prevSourceCom;
137 if (temporarySourceSnapshot_ && currentSnapshot_) {
138 *temporarySourceSnapshot_ = *currentSnapshot_;
141 sourceNeighborList_ = neighborList_;
142 sourcePoint_ = point_;
143 sourceSavedPositions_ = savedPositions_;
145 neighborList_ = sinkNeighborList_;
147 savedPositions_ = sinkSavedPositions_;
149 currentSnapshot_->clearDerivedProperties();
151 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
152 "Either temporarySourceSnapshot or currentSnapshot "
153 "has a null value.\n");
154 painCave.isFatal = 1;
155 painCave.severity = OPENMD_ERROR;
160 if (selectedMolecule_) {
161 currentSPFData->pos += delta;
162 selectedMolecule_->setCom(currentSPFData->pos);
166 int globalSelectedID = currentSPFData->globalID;
168 MPI_Bcast(¤tSPFData->pos[0], 3, MPI_REALTYPE,
169 info_->getMolToProc(globalSelectedID), MPI_COMM_WORLD);
173 ForceManager::calcForces();
174 potentialSink_ = currentSnapshot_->getPotentialEnergy();
176 if (temporarySinkSnapshot_ && currentSnapshot_) {
177 *temporarySinkSnapshot_ = *currentSnapshot_;
180 sinkNeighborList_ = neighborList_;
182 sinkSavedPositions_ = savedPositions_;
184 neighborList_ = sourceNeighborList_;
185 point_ = sourcePoint_;
186 savedPositions_ = sourceSavedPositions_;
188 currentSnapshot_->clearDerivedProperties();
190 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
191 "Either temporarySinkSnapshot or currentSnapshot "
192 "has a null value.\n");
193 painCave.isFatal = 1;
194 painCave.severity = OPENMD_ERROR;
199 if (selectedMolecule_) { selectedMolecule_->setCom(currentSourceCom); }
204 if ((a > 0.999) && (a < 1.001) && (b > 0.999) && (b < 1.001)) {
208 currentSPFData->lambda -= deltaLambda_;
212 spfRNEMD_->failedLastTrial_ = !doExchange;
216 *temporarySourceSnapshot_ = *currentSnapshot_;
217 *temporarySinkSnapshot_ = *currentSnapshot_;
218 potentialSink_ = std::numeric_limits<RealType>::max();
222 void SPFForceManager::setSelectedMolecule(Molecule* selectedMolecule) {
223 if (selectedMolecule) {
224 selectedMolecule_ = selectedMolecule;
226 selectedMolecule_ =
nullptr;
230 void SPFForceManager::setDeltaLambda(RealType spfTarget) {
231 if (hasSelectedMolecule_) {
232 std::shared_ptr<SPFData> currentSPFData = currentSnapshot_->getSPFData();
235 if (currentSPFData->lambda >= 1.0 ||
236 std::fabs(currentSPFData->lambda - 1.0) < 1e-6) {
238 if (selectedMolecule_) {
239 selectedMolecule_->setCom(currentSPFData->pos);
240 selectedMolecule_ =
nullptr;
243 currentSPFData->clear();
246 neighborList_ = sinkNeighborList_;
248 savedPositions_ = sinkSavedPositions_;
250 hasSelectedMolecule_ =
false;
252 spfRNEMD_->selectMolecule();
259 deltaLambda_ = std::fabs(spfTarget);
261 if (currentSPFData->lambda + deltaLambda_ >= 1.0) {
266 deltaLambda_ = 1.0 - currentSPFData->lambda;
271 RealType SPFForceManager::getScaledDeltaU() {
272 std::shared_ptr<SPFData> currentSPFData = currentSnapshot_->getSPFData();
274 RealType lambda = currentSPFData->lambda;
277 if (std::isinf(potentialSink_) || std::isnan(potentialSink_) ||
278 std::isinf(potentialSource_) || std::isnan(potentialSource_)) {
280 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
281 "SPFForceManager detected a numerical error in the potential\n"
282 "\tenergy with a lambda value of %f. Selecting a new molecule.\n",
284 painCave.isFatal = 0;
285 painCave.severity = OPENMD_WARNING;
288 hasSelectedMolecule_ =
false;
289 currentSPFData->clear();
292 if (lambda < 1e-6) {
return 0.0; }
294 return -(f_lambda(lambda) - f_lambda(lambda - deltaLambda_)) *
295 (potentialSink_ - potentialSource_);
298 void SPFForceManager::combineForcesAndTorques() {
300 SimInfo::MoleculeIterator mi;
302 Molecule::IntegrableObjectIterator ii;
305 RealType result = f_lambda(currentSnapshot_->getSPFData()->lambda);
308 for (mol = info_->beginMolecule(mi); mol != NULL;
309 mol = info_->nextMolecule(mi)) {
310 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
311 sd = mol->nextIntegrableObject(ii)) {
312 sd->combineForcesAndTorques(temporarySourceSnapshot_,
313 temporarySinkSnapshot_, 1.0 - result,
319 void SPFForceManager::updatePotentials() {
320 updateLongRangePotentials();
321 updateShortRangePotentials();
322 updateSelfPotentials();
323 updateExcludedPotentials();
324 updateRestraintPotentials();
325 if (doPotentialSelection_) updateSelectionPotentials();
328 void SPFForceManager::updateLongRangePotentials() {
329 potVec longRangePotentials =
330 linearCombination(temporarySourceSnapshot_->getLongRangePotentials(),
331 temporarySinkSnapshot_->getLongRangePotentials());
332 currentSnapshot_->setLongRangePotentials(longRangePotentials);
334 RealType reciprocalPotential =
335 linearCombination(temporarySourceSnapshot_->getReciprocalPotential(),
336 temporarySinkSnapshot_->getReciprocalPotential());
337 currentSnapshot_->setReciprocalPotential(reciprocalPotential);
339 RealType surfacePotential =
340 linearCombination(temporarySourceSnapshot_->getSurfacePotential(),
341 temporarySinkSnapshot_->getSurfacePotential());
342 currentSnapshot_->setSurfacePotential(surfacePotential);
345 void SPFForceManager::updateShortRangePotentials() {
346 RealType bondPotential =
347 linearCombination(temporarySourceSnapshot_->getBondPotential(),
348 temporarySinkSnapshot_->getBondPotential());
349 currentSnapshot_->setBondPotential(bondPotential);
351 RealType bendPotential =
352 linearCombination(temporarySourceSnapshot_->getBendPotential(),
353 temporarySinkSnapshot_->getBendPotential());
354 currentSnapshot_->setBendPotential(bendPotential);
356 RealType torsionPotential =
357 linearCombination(temporarySourceSnapshot_->getTorsionPotential(),
358 temporarySinkSnapshot_->getTorsionPotential());
359 currentSnapshot_->setTorsionPotential(torsionPotential);
361 RealType inversionPotential =
362 linearCombination(temporarySourceSnapshot_->getInversionPotential(),
363 temporarySinkSnapshot_->getInversionPotential());
364 currentSnapshot_->setInversionPotential(inversionPotential);
367 void SPFForceManager::updateSelfPotentials() {
368 potVec selfPotentials =
369 linearCombination(temporarySourceSnapshot_->getSelfPotentials(),
370 temporarySinkSnapshot_->getSelfPotentials());
371 currentSnapshot_->setSelfPotentials(selfPotentials);
374 void SPFForceManager::updateExcludedPotentials() {
375 potVec excludedPotentials =
376 linearCombination(temporarySourceSnapshot_->getExcludedPotentials(),
377 temporarySinkSnapshot_->getExcludedPotentials());
378 currentSnapshot_->setExcludedPotentials(excludedPotentials);
381 void SPFForceManager::updateRestraintPotentials() {
382 RealType restraintPotential =
383 linearCombination(temporarySourceSnapshot_->getRestraintPotential(),
384 temporarySinkSnapshot_->getRestraintPotential());
385 currentSnapshot_->setRestraintPotential(restraintPotential);
388 void SPFForceManager::updateSelectionPotentials() {
389 potVec selectionPotentials =
390 linearCombination(temporarySourceSnapshot_->getSelectionPotentials(),
391 temporarySinkSnapshot_->getSelectionPotentials());
392 currentSnapshot_->setSelectionPotentials(selectionPotentials);
395 void SPFForceManager::updateVirialTensor() {
396 Mat3x3d virialTensor =
397 linearCombination(temporarySourceSnapshot_->getVirialTensor(),
398 temporarySinkSnapshot_->getVirialTensor());
399 currentSnapshot_->setVirialTensor(virialTensor);
401 Mat3x3d pressureTensor =
402 linearCombination(thermo_->getPressureTensor(temporarySourceSnapshot_),
403 thermo_->getPressureTensor(temporarySinkSnapshot_));
404 currentSnapshot_->setPressureTensor(pressureTensor);
407 linearCombination(thermo_->getPressure(temporarySourceSnapshot_),
408 thermo_->getPressure(temporarySinkSnapshot_));
409 currentSnapshot_->setPressure(pressure);