45#include "rnemd/Swap.hpp"
60#include "brains/Thermo.hpp"
61#include "io/Globals.hpp"
62#include "math/ConvexHull.hpp"
69#include "rnemd/RNEMD.hpp"
70#include "rnemd/RNEMDParameters.hpp"
71#include "types/FixedChargeAdapter.hpp"
72#include "types/FluctuatingChargeAdapter.hpp"
73#include "utils/Constants.hpp"
75#define HONKING_LARGE_VALUE 1.0e10
77namespace OpenMD::RNEMD {
80 RNEMD {info, forceMan} {
81 rnemdMethodLabel_ =
"Swap";
83 RNEMDParameters* rnemdParams = info->getSimParams()->getRNEMDParameters();
85 bool hasKineticFlux = rnemdParams->haveKineticFlux();
86 bool hasMomentumFlux = rnemdParams->haveMomentumFlux();
88 bool methodFluxMismatch =
false;
89 bool hasCorrectFlux =
false;
91 switch (rnemdFluxType_) {
93 hasCorrectFlux = hasKineticFlux;
98 hasCorrectFlux = hasMomentumFlux;
101 methodFluxMismatch =
true;
105 if (methodFluxMismatch) {
106 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
107 "RNEMD: The current method,\n"
109 "\tcannot be used with the current flux type, %s\n",
110 rnemdFluxTypeLabel_.c_str());
111 painCave.isFatal = 1;
112 painCave.severity = OPENMD_ERROR;
116 if (!hasCorrectFlux) {
117 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
118 "RNEMD: The current method, Swap, and flux type, %s,\n"
119 "\tdid not have the correct flux value specified. Options\n"
120 "\tinclude: kineticFlux and momentumFlux.\n",
121 rnemdFluxTypeLabel_.c_str());
122 painCave.isFatal = 1;
123 painCave.severity = OPENMD_ERROR;
127 if (hasKineticFlux) {
128 setKineticFlux(rnemdParams->getKineticFlux());
133 if (hasMomentumFlux) {
134 RealType momentumFlux = rnemdParams->getMomentumFlux();
135 std::vector<RealType> momentumFluxVector(3);
137 switch (rnemdFluxType_) {
139 momentumFluxVector[0] = momentumFlux;
142 momentumFluxVector[1] = momentumFlux;
145 momentumFluxVector[2] = momentumFlux;
151 setMomentumFluxVector(momentumFluxVector);
157 if (!doRNEMD_)
return;
163 RealType min_val(0.0);
167 RealType max_val(0.0);
177 if (usePeriodicBoundaryConditions_) currentSnap_->wrapVector(pos);
183 switch (rnemdFluxType_) {
196 value += angMom[j] * angMom[j] / I(j, j) +
197 angMom[k] * angMom[k] / I(k, k);
199 value += angMom[0] * angMom[0] / I(0, 0) +
200 angMom[1] * angMom[1] / I(1, 1) +
201 angMom[2] * angMom[2] / I(2, 2);
207 value = mass * vel[0];
210 value = mass * vel[1];
213 value = mass * vel[2];
223 if (max_val < value) {
236 if (usePeriodicBoundaryConditions_) currentSnap_->wrapVector(pos);
242 switch (rnemdFluxType_) {
255 value += angMom[j] * angMom[j] / I(j, j) +
256 angMom[k] * angMom[k] / I(k, k);
258 value += angMom[0] * angMom[0] / I(0, 0) +
259 angMom[1] * angMom[1] / I(1, 1) +
260 angMom[2] * angMom[2] / I(2, 2);
266 value = mass * vel[0];
269 value = mass * vel[1];
272 value = mass * vel[2];
283 if (min_val > value) {
292 MPI_Comm_rank(MPI_COMM_WORLD, &worldRank);
294 int my_min_found = min_found;
295 int my_max_found = max_found;
298 MPI_Allreduce(&my_min_found, &min_found, 1, MPI_INT, MPI_LOR,
301 MPI_Allreduce(&my_max_found, &max_found, 1, MPI_INT, MPI_LOR,
305 if (max_found && min_found) {
310 } max_vals, min_vals;
313 min_vals.val = min_val;
315 min_vals.val = HONKING_LARGE_VALUE;
317 min_vals.rank = worldRank;
320 MPI_Allreduce(&min_vals, &min_vals, 1, MPI_REALTYPE_INT, MPI_MINLOC,
322 min_val = min_vals.val;
325 max_vals.val = max_val;
327 max_vals.val = -HONKING_LARGE_VALUE;
329 max_vals.rank = worldRank;
332 MPI_Allreduce(&max_vals, &max_vals, 1, MPI_REALTYPE_INT, MPI_MAXLOC,
334 max_val = max_vals.val;
337 if (min_val < max_val) {
339 if (max_vals.rank == worldRank && min_vals.rank == worldRank) {
348 switch (rnemdFluxType_) {
355 min_sd->
setJ(max_angMom);
356 max_sd->
setJ(min_angMom);
361 temp_vel = min_vel.
x();
362 min_vel.
x() = max_vel.
x();
363 max_vel.
x() = temp_vel;
368 temp_vel = min_vel.
y();
369 min_vel.
y() = max_vel.
y();
370 max_vel.
y() = temp_vel;
375 temp_vel = min_vel.
z();
376 min_vel.
z() = max_vel.
z();
377 max_vel.
z() = temp_vel;
387 }
else if (max_vals.rank == worldRank) {
397 MPI_REALTYPE, min_vals.rank, 0, MPI_COMM_WORLD, &status);
399 switch (rnemdFluxType_) {
410 MPI_REALTYPE, min_vals.rank, 1, MPI_COMM_WORLD,
413 max_sd->
setJ(min_angMom);
417 max_vel.
x() = min_vel.
x();
421 max_vel.
y() = min_vel.
y();
425 max_vel.
z() = min_vel.
z();
431 }
else if (min_vals.rank == worldRank) {
441 MPI_REALTYPE, max_vals.rank, 0, MPI_COMM_WORLD, &status);
443 switch (rnemdFluxType_) {
454 MPI_REALTYPE, max_vals.rank, 1, MPI_COMM_WORLD,
457 min_sd->
setJ(max_angMom);
461 min_vel.
x() = max_vel.
x();
465 min_vel.
y() = max_vel.
y();
469 min_vel.
z() = max_vel.
z();
478 switch (rnemdFluxType_) {
480 kineticExchange_ += max_val - min_val;
483 momentumExchange_.x() += max_val - min_val;
486 momentumExchange_.y() += max_val - min_val;
489 momentumExchange_.z() += max_val - min_val;
495 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
496 "RNEMD::doSwap exchange NOT performed "
497 "because min_val > max_val\n");
498 painCave.isFatal = 0;
499 painCave.severity = OPENMD_INFO;
504 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
505 "Swap exchange NOT performed because selected object\n"
506 "\twas not present in at least one of the two slabs.\n");
507 painCave.isFatal = 0;
508 painCave.severity = OPENMD_INFO;
ForceManager is responsible for calculating both the short range (bonded) interactions and long range...
StuntDouble * nextSelected(int &i)
Finds the next selected StuntDouble in the selection.
StuntDouble * beginSelected(int &i)
Finds the first selected StuntDouble in the selection.
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
"Don't move, or you're dead! Stand up! Captain, we've got them!"
Vector3d getVel()
Returns the current velocity of this stuntDouble.
int linearAxis()
Returns the linear axis of the rigidbody, atom and directional atom will always return -1.
RealType getMass()
Returns the mass of this stuntDouble.
virtual Mat3x3d getI()=0
Returns the inertia tensor of this stuntDouble.
bool isLinear()
Tests the if this stuntDouble is a linear rigidbody.
Vector3d getPos()
Returns the current position of this stuntDouble.
void setVel(const Vector3d &vel)
Sets the current velocity of this stuntDouble.
Vector3d getJ()
Returns the current angular momentum of this stuntDouble (body -fixed).
bool isDirectional()
Tests if this stuntDouble is a directional one.
void setJ(const Vector3d &angMom)
Sets the current angular momentum of this stuntDouble (body-fixed).
Real & z()
Returns reference of the third element of Vector3.
Real & x()
Returns reference of the first element of Vector3.
Real & y()
Returns reference of the second element of Vector3.
Real * getArrayPointer()
Returns the pointer of internal array.
Real lengthSquare()
Returns the squared length of this vector.