48#include "FluctuatingChargeConstraints.hpp"
58 FluctuatingChargeConstraints::FluctuatingChargeConstraints(
SimInfo* info) :
59 info_(info), initialized_(false), hasFlucQ_(false),
60 constrainRegions_(false) {}
62 void FluctuatingChargeConstraints::initialize() {
63 if (info_->usesFluctuatingCharges()) {
64 if (info_->getNFluctuatingCharges() > 0) { hasFlucQ_ =
true; }
69 void FluctuatingChargeConstraints::setConstrainRegions(
bool cr) {
70 constrainRegions_ = cr;
72 if (!initialized_) initialize();
77 regionCharges_.clear();
79 if (constrainRegions_) {
80 std::vector<int> localRegions = info_->getRegions();
84 MPI_Comm_size(MPI_COMM_WORLD, &size);
85 int mylen = localRegions.size();
87 std::vector<int> counts;
88 std::vector<int> displs;
90 counts.resize(size, 0);
91 displs.resize(size, 0);
93 MPI_Allgather(&mylen, 1, MPI_INT, &counts[0], 1, MPI_INT, MPI_COMM_WORLD);
95 int total = counts[0];
97 for (
int i = 1; i < size; i++) {
99 displs[i] = displs[i - 1] + counts[i - 1];
102 std::vector<int> globalRegions(total, 0);
104 MPI_Allgatherv(&localRegions[0], mylen, MPI_INT, &globalRegions[0],
105 &counts[0], &displs[0], MPI_INT, MPI_COMM_WORLD);
107 localRegions = globalRegions;
110 std::set<int> regions;
111 std::vector<int>::iterator iter;
112 for (iter = localRegions.begin(); iter != localRegions.end(); ++iter) {
113 if (*iter >= 0) regions.insert(*iter);
117 regionKeys_.resize(*(regions.end()));
119 for (std::set<int>::iterator r = regions.begin(); r != regions.end();
121 regionKeys_[(*r)] = which;
124 regionForce_.resize(regionKeys_.size());
125 regionCMom_.resize(regionKeys_.size());
126 regionCharges_.resize(regionKeys_.size());
127 regionChargeMass_.resize(regionKeys_.size());
131 void FluctuatingChargeConstraints::applyConstraints() {
132 if (!initialized_) initialize();
133 if (!hasFlucQ_)
return;
135 SimInfo::MoleculeIterator i;
136 Molecule::FluctuatingChargeIterator j;
140 RealType frc, systemFrc, molFrc, regionFrc;
149 if (constrainRegions_) {
150 std::fill(regionForce_.begin(), regionForce_.end(), 0.0);
151 std::fill(regionCharges_.begin(), regionCharges_.end(), 0);
154 for (mol = info_->beginMolecule(i); mol != NULL;
155 mol = info_->nextMolecule(i)) {
156 if (!mol->constrainTotalCharge()) {
157 int region = mol->getRegion();
159 for (atom = mol->beginFluctuatingCharge(j); atom != NULL;
160 atom = mol->nextFluctuatingCharge(j)) {
161 frc = atom->getFlucQFrc();
162 if (constrainRegions_ && region >= 0) {
163 regionForce_[regionKeys_[region]] += frc;
164 regionCharges_[regionKeys_[region]] += 1;
176 MPI_Allreduce(MPI_IN_PLACE, &systemFrc, 1, MPI_REALTYPE, MPI_SUM,
178 MPI_Allreduce(MPI_IN_PLACE, &systemCharges, 1, MPI_INT, MPI_SUM,
181 if (constrainRegions_) {
182 MPI_Allreduce(MPI_IN_PLACE, ®ionForce_[0], regionForce_.size(),
183 MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
184 MPI_Allreduce(MPI_IN_PLACE, ®ionCharges_[0], regionCharges_.size(),
185 MPI_INT, MPI_SUM, MPI_COMM_WORLD);
191 systemFrc /= systemCharges;
194 if (constrainRegions_) {
195 for (
unsigned int i = 0; i < regionForce_.size(); ++i) {
196 regionForce_[i] /= regionCharges_[i];
200 for (mol = info_->beginMolecule(i); mol != NULL;
201 mol = info_->nextMolecule(i)) {
204 if (mol->constrainTotalCharge()) {
205 for (atom = mol->beginFluctuatingCharge(j); atom != NULL;
206 atom = mol->nextFluctuatingCharge(j)) {
207 molFrc += atom->getFlucQFrc();
209 molFrc /= mol->getNFluctuatingCharges();
211 for (atom = mol->beginFluctuatingCharge(j); atom != NULL;
212 atom = mol->nextFluctuatingCharge(j)) {
213 frc = atom->getFlucQFrc() - molFrc;
214 atom->setFlucQFrc(frc);
217 int region = mol->getRegion();
220 if (constrainRegions_ && region >= 0) {
221 regionFrc = regionForce_[regionKeys_[region]];
223 for (atom = mol->beginFluctuatingCharge(j); atom != NULL;
224 atom = mol->nextFluctuatingCharge(j)) {
225 frc = atom->getFlucQFrc() - regionFrc;
226 atom->setFlucQFrc(frc);
229 for (atom = mol->beginFluctuatingCharge(j); atom != NULL;
230 atom = mol->nextFluctuatingCharge(j)) {
231 frc = atom->getFlucQFrc() - systemFrc;
232 atom->setFlucQFrc(frc);
239 void FluctuatingChargeConstraints::applyConstraintsOnChargeVelocities() {
240 if (!initialized_) initialize();
241 if (!hasFlucQ_)
return;
243 SimInfo::MoleculeIterator i;
244 Molecule::FluctuatingChargeIterator j;
248 RealType flucqP, systemCMom, regionCMom, molCMom, molFlucQMass, flucqW;
249 RealType systemChargeMass;
256 systemChargeMass = 0.0;
257 if (constrainRegions_) {
258 std::fill(regionCMom_.begin(), regionCMom_.end(), 0.0);
259 std::fill(regionChargeMass_.begin(), regionChargeMass_.end(), 0);
262 for (mol = info_->beginMolecule(i); mol != NULL;
263 mol = info_->nextMolecule(i)) {
264 if (!mol->constrainTotalCharge()) {
265 int region = mol->getRegion();
267 for (atom = mol->beginFluctuatingCharge(j); atom != NULL;
268 atom = mol->nextFluctuatingCharge(j)) {
269 flucqP = atom->getFlucQVel() * atom->getChargeMass();
270 if (constrainRegions_ && region >= 0) {
271 regionCMom_[regionKeys_[region]] += flucqP;
272 regionChargeMass_[regionKeys_[region]] += atom->getChargeMass();
274 systemCMom += flucqP;
275 systemChargeMass += atom->getChargeMass();
284 MPI_Allreduce(MPI_IN_PLACE, &systemCMom, 1, MPI_REALTYPE, MPI_SUM,
286 MPI_Allreduce(MPI_IN_PLACE, &systemChargeMass, 1, MPI_REALTYPE, MPI_SUM,
289 if (constrainRegions_) {
290 MPI_Allreduce(MPI_IN_PLACE, ®ionCMom_[0], regionCMom_.size(),
291 MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
292 MPI_Allreduce(MPI_IN_PLACE, ®ionChargeMass_[0],
293 regionChargeMass_.size(), MPI_REALTYPE, MPI_SUM,
299 systemCMom /= systemChargeMass;
302 if (constrainRegions_) {
303 for (
unsigned int i = 0; i < regionCMom_.size(); ++i) {
304 regionCMom_[i] /= regionChargeMass_[i];
308 for (mol = info_->beginMolecule(i); mol != NULL;
309 mol = info_->nextMolecule(i)) {
313 if (mol->constrainTotalCharge()) {
314 for (atom = mol->beginFluctuatingCharge(j); atom != NULL;
315 atom = mol->nextFluctuatingCharge(j)) {
316 molCMom += atom->getFlucQVel() * atom->getChargeMass();
317 molFlucQMass += atom->getChargeMass();
319 molCMom /= molFlucQMass;
321 for (atom = mol->beginFluctuatingCharge(j); atom != NULL;
322 atom = mol->nextFluctuatingCharge(j)) {
323 flucqW = atom->getFlucQVel() - molCMom;
324 atom->setFlucQVel(flucqW);
327 int region = mol->getRegion();
330 if (constrainRegions_ && region >= 0) {
331 regionCMom = regionCMom_[regionKeys_[region]];
333 for (atom = mol->beginFluctuatingCharge(j); atom != NULL;
334 atom = mol->nextFluctuatingCharge(j)) {
335 flucqW = atom->getFlucQVel() - regionCMom;
336 atom->setFlucQVel(flucqW);
339 for (atom = mol->beginFluctuatingCharge(j); atom != NULL;
340 atom = mol->nextFluctuatingCharge(j)) {
341 flucqW = atom->getFlucQVel() - systemCMom;
342 atom->setFlucQVel(flucqW);
349 int FluctuatingChargeConstraints::getNumberOfFlucQConstraints() {
350 int nConstraints = 0;
351 if (!initialized_) initialize();
352 if (!hasFlucQ_)
return 0;
353 SimInfo::MoleculeIterator i;
355 int systemConstrain = 0;
356 for (mol = info_->beginMolecule(i); mol != NULL;
357 mol = info_->nextMolecule(i)) {
358 if (mol->constrainTotalCharge()) {
361 int region = mol->getRegion();
362 if (!constrainRegions_ || region < 0) { systemConstrain = 1; }
365 return nConstraints + regionCMom_.size() + systemConstrain;
368 int FluctuatingChargeConstraints::getNumberOfFlucQAtoms() {
370 if (!initialized_) initialize();
371 if (!hasFlucQ_)
return 0;
372 SimInfo::MoleculeIterator i;
373 Molecule::FluctuatingChargeIterator j;
376 for (mol = info_->beginMolecule(i); mol != NULL;
377 mol = info_->nextMolecule(i)) {
378 if (mol->constrainTotalCharge()) {
379 nFlucq += mol->getNFluctuatingCharges();
381 int region = mol->getRegion();
382 if (constrainRegions_ && region >= 0) {
383 for (atom = mol->beginFluctuatingCharge(j); atom != NULL;
384 atom = mol->nextFluctuatingCharge(j)) {
388 for (atom = mol->beginFluctuatingCharge(j); atom != NULL;
389 atom = mol->nextFluctuatingCharge(j)) {
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.