48#include "brains/Thermo.hpp"
58#include "types/FixedChargeAdapter.hpp"
59#include "types/FluctuatingChargeAdapter.hpp"
60#include "types/MultipoleAdapter.hpp"
61#include "utils/Constants.hpp"
62#include "utils/simError.h"
64#include "math/AlphaHull.hpp"
65#include "math/ConvexHull.hpp"
71 Thermo::Thermo(
SimInfo* info) : info_(info) {
72 velField_ = std::make_unique<VelocityField>(info);
73 bool usePeculiarVelocities_ = velField_->isActive();
76 RealType Thermo::getTranslationalKinetic() {
77 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
79 if (!snap->hasTranslationalKineticEnergy) {
80 SimInfo::MoleculeIterator miter;
81 vector<StuntDouble*>::iterator iiter;
87 RealType kinetic(0.0);
89 for (mol = info_->beginMolecule(miter); mol != NULL;
90 mol = info_->nextMolecule(miter)) {
91 for (sd = mol->beginIntegrableObject(iiter); sd != NULL;
92 sd = mol->nextIntegrableObject(iiter)) {
96 if (usePeculiarVelocities_) {
97 ambient = velField_->getVelocity(sd->getPos());
102 mass * (vel[0] * vel[0] + vel[1] * vel[1] + vel[2] * vel[2]);
107 MPI_Allreduce(MPI_IN_PLACE, &kinetic, 1, MPI_REALTYPE, MPI_SUM,
111 kinetic = kinetic * 0.5 / Constants::energyConvert;
113 snap->setTranslationalKineticEnergy(kinetic);
115 return snap->getTranslationalKineticEnergy();
118 RealType Thermo::getRotationalKinetic() {
119 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
121 if (!snap->hasRotationalKineticEnergy) {
122 SimInfo::MoleculeIterator miter;
123 vector<StuntDouble*>::iterator iiter;
126 Vector3d vorticity(0.0);
127 Vector3d J, omegaB, omegaL;
128 Mat3x3d I, A, Atrans;
130 RealType kinetic(0.0);
132 if (usePeculiarVelocities_) {
133 vorticity = velField_->getVorticity();
136 for (mol = info_->beginMolecule(miter); mol != NULL;
137 mol = info_->nextMolecule(miter)) {
138 for (sd = mol->beginIntegrableObject(iiter); sd != NULL;
139 sd = mol->nextIntegrableObject(iiter)) {
140 if (sd->isDirectional()) {
144 Atrans = A.transpose();
146 if (sd->isLinear()) {
147 i = sd->linearAxis();
151 omegaB[j] = J[j] / I(j,j);
152 omegaB[k] = J[k] / I(k,k);
154 omegaB[0] = J[0] / I(0,0);
155 omegaB[1] = J[1] / I(1,1);
156 omegaB[2] = J[2] / I(2,2);
158 omegaL = Atrans * omegaB - vorticity;
161 kinetic +=
dot(omegaB, I * omegaB);
168 MPI_Allreduce(MPI_IN_PLACE, &kinetic, 1, MPI_REALTYPE, MPI_SUM,
172 kinetic = kinetic * 0.5 / Constants::energyConvert ;
174 snap->setRotationalKineticEnergy(kinetic);
176 return snap->getRotationalKineticEnergy();
179 RealType Thermo::getKinetic() {
180 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
182 if (!snap->hasKineticEnergy) {
183 RealType ke = getTranslationalKinetic() + getRotationalKinetic() +
184 getElectronicKinetic();
186 snap->setKineticEnergy(ke);
188 return snap->getKineticEnergy();
191 RealType Thermo::getPotential() {
195 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
196 return snap->getPotentialEnergy();
199 potVec Thermo::getSelectionPotentials() {
203 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
204 return snap->getSelectionPotentials();
207 RealType Thermo::getTotalEnergy() {
208 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
210 if (!snap->hasTotalEnergy) {
211 snap->setTotalEnergy(this->getKinetic() + this->getPotential());
214 return snap->getTotalEnergy();
220 RealType Thermo::getTemperature() {
221 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
223 if (!snap->hasTemperature) {
225 this->getTranslationalKinetic() + this->getRotationalKinetic();
227 RealType temperature {};
232 if (info_->getNdf() > 0)
233 temperature = (2.0 * nuclearKE) / (info_->getNdf() * Constants::kb);
237 snap->setTemperature(temperature);
240 return snap->getTemperature();
243 RealType Thermo::getElectronicKinetic() {
244 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
246 if (!snap->hasElectronicKineticEnergy) {
247 SimInfo::MoleculeIterator miter;
248 vector<Atom*>::iterator iiter;
253 RealType kinetic(0.0);
255 for (mol = info_->beginMolecule(miter); mol != NULL;
256 mol = info_->nextMolecule(miter)) {
257 for (atom = mol->beginFluctuatingCharge(iiter); atom != NULL;
258 atom = mol->nextFluctuatingCharge(iiter)) {
259 cmass = atom->getChargeMass();
260 cvel = atom->getFlucQVel();
261 kinetic += cmass * cvel * cvel;
266 MPI_Allreduce(MPI_IN_PLACE, &kinetic, 1, MPI_REALTYPE, MPI_SUM,
271 snap->setElectronicKineticEnergy(kinetic);
274 return snap->getElectronicKineticEnergy();
277 RealType Thermo::getElectronicTemperature() {
278 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
280 if (!snap->hasElectronicTemperature) {
281 RealType eTemp = (2.0 * this->getElectronicKinetic()) /
282 (info_->getNFluctuatingCharges() * Constants::kb);
284 snap->setElectronicTemperature(eTemp);
287 return snap->getElectronicTemperature();
290 RealType Thermo::getNetCharge() {
291 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
293 if (!snap->hasNetCharge) {
294 SimInfo::MoleculeIterator miter;
295 vector<Atom*>::iterator aiter;
299 RealType netCharge(0.0);
301 for (mol = info_->beginMolecule(miter); mol != NULL;
302 mol = info_->nextMolecule(miter)) {
303 for (atom = mol->beginAtom(aiter); atom != NULL;
304 atom = mol->nextAtom(aiter)) {
307 FixedChargeAdapter fca = FixedChargeAdapter(atom->getAtomType());
308 if (fca.isFixedCharge()) { charge = fca.getCharge(); }
310 FluctuatingChargeAdapter fqa =
311 FluctuatingChargeAdapter(atom->getAtomType());
312 if (fqa.isFluctuatingCharge()) { charge += atom->getFlucQPos(); }
319 MPI_Allreduce(MPI_IN_PLACE, &netCharge, 1, MPI_REALTYPE, MPI_SUM,
323 snap->setNetCharge(netCharge);
326 return snap->getNetCharge();
329 RealType Thermo::getChargeMomentum() {
330 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
332 if (!snap->hasChargeMomentum) {
333 SimInfo::MoleculeIterator miter;
334 vector<Atom*>::iterator iiter;
339 RealType momentum(0.0);
341 for (mol = info_->beginMolecule(miter); mol != NULL;
342 mol = info_->nextMolecule(miter)) {
343 for (atom = mol->beginFluctuatingCharge(iiter); atom != NULL;
344 atom = mol->nextFluctuatingCharge(iiter)) {
345 cmass = atom->getChargeMass();
346 cvel = atom->getFlucQVel();
348 momentum += cmass * cvel;
353 MPI_Allreduce(MPI_IN_PLACE, &momentum, 1, MPI_REALTYPE, MPI_SUM,
357 snap->setChargeMomentum(momentum);
360 return snap->getChargeMomentum();
363 std::vector<Vector3d> Thermo::getCurrentDensity() {
364 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
365 AtomTypeSet simTypes = info_->getSimulatedAtomTypes();
367 SimInfo::MoleculeIterator miter;
368 std::vector<Atom*>::iterator iiter;
369 std::vector<RigidBody*>::iterator ri;
374 AtomTypeSet::iterator at;
377 std::vector<Vector3d> typeJc(simTypes.size(), V3Zero);
379 for (mol = info_->beginMolecule(miter); mol != NULL;
380 mol = info_->nextMolecule(miter)) {
382 for (rb = mol->beginRigidBody(ri); rb != NULL;
383 rb = mol->nextRigidBody(ri)) {
387 for (atom = mol->beginAtom(iiter); atom != NULL;
388 atom = mol->nextAtom(iiter)) {
389 Vector3d v = atom->getVel();
390 if (usePeculiarVelocities_) {
391 ambient = velField_->getVelocity(atom->getPos());
398 atype = atom->getAtomType();
399 FixedChargeAdapter fca = FixedChargeAdapter(atype);
400 if (fca.isFixedCharge()) q = fca.getCharge();
401 FluctuatingChargeAdapter fqa = FluctuatingChargeAdapter(atype);
402 if (fqa.isFluctuatingCharge()) q += atom->getFlucQPos();
405 at = std::find(simTypes.begin(), simTypes.end(), atype);
406 if (at != simTypes.end()) {
407 typeIndex = std::distance(simTypes.begin(), at);
410 if (typeIndex != -1) { typeJc[typeIndex] += q * v; }
416 MPI_Allreduce(MPI_IN_PLACE, &Jc[0], 3, MPI_REALTYPE, MPI_SUM,
418 for (
unsigned int j = 0; j < simTypes.size(); j++) {
419 MPI_Allreduce(MPI_IN_PLACE, &typeJc[j][0], 3, MPI_REALTYPE, MPI_SUM,
424 RealType vol = snap->getVolume();
426 Jc /= (vol * Constants::currentDensityConvert);
427 for (
unsigned int j = 0; j < simTypes.size(); j++) {
428 typeJc[j] /= (vol * Constants::currentDensityConvert);
431 std::vector<Vector3d> result;
434 result.push_back(Jc);
435 for (
unsigned int j = 0; j < simTypes.size(); j++)
436 result.push_back(typeJc[j]);
441 RealType Thermo::getVolume() {
442 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
443 return snap->getVolume();
446 RealType Thermo::getPressure() {
447 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
449 if (!snap->hasPressure) {
455 tensor = getPressureTensor();
457 pressure = Constants::pressureConvert *
458 (tensor(0, 0) + tensor(1, 1) + tensor(2, 2)) / 3.0;
460 snap->setPressure(pressure);
463 return snap->getPressure();
466 RealType Thermo::getPressure(Snapshot* snap) {
467 if (!snap->hasPressure) {
472 tensor = getPressureTensor(snap);
474 pressure = Constants::pressureConvert *
475 (tensor(0, 0) + tensor(1, 1) + tensor(2, 2)) / 3.0;
477 snap->setPressure(pressure);
480 return snap->getPressure();
487 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
489 if (!snap->hasPressureTensor) {
490 Mat3x3d pressureTensor;
496 SimInfo::MoleculeIterator i;
497 vector<StuntDouble*>::iterator j;
500 for (mol = info_->beginMolecule(i); mol != NULL;
501 mol = info_->nextMolecule(i)) {
502 for (sd = mol->beginIntegrableObject(j); sd != NULL;
503 sd = mol->nextIntegrableObject(j)) {
506 if (usePeculiarVelocities_) {
507 ambient = velField_->getVelocity(sd->
getPos());
510 p_tens += mass * outProduct(vcom, vcom);
516 MPI_SUM, MPI_COMM_WORLD);
519 RealType volume = this->getVolume();
520 Mat3x3d virialTensor = snap->getVirialTensor();
523 (p_tens + Constants::energyConvert * virialTensor) / volume;
525 snap->setPressureTensor(pressureTensor);
527 return snap->getPressureTensor();
534 if (!snap->hasPressureTensor) {
535 Mat3x3d pressureTensor;
541 SimInfo::MoleculeIterator i;
542 vector<StuntDouble*>::iterator j;
545 for (mol = info_->beginMolecule(i); mol != NULL;
546 mol = info_->nextMolecule(i)) {
547 for (sd = mol->beginIntegrableObject(j); sd != NULL;
548 sd = mol->nextIntegrableObject(j)) {
551 if (usePeculiarVelocities_) {
552 ambient = velField_->getVelocity(sd->
getPos());
555 p_tens += mass * outProduct(vcom, vcom);
561 MPI_SUM, MPI_COMM_WORLD);
564 RealType volume = this->getVolume();
565 Mat3x3d virialTensor = snap->getVirialTensor();
568 (p_tens + Constants::energyConvert * virialTensor) / volume;
570 snap->setPressureTensor(pressureTensor);
572 return snap->getPressureTensor();
576 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
578 if (!snap->hasSystemDipole) {
579 SimInfo::MoleculeIterator miter;
580 vector<Atom*>::iterator aiter;
585 Vector3d dipoleVector(0.0);
593 RealType chargeToC = 1.60217733e-19;
594 RealType angstromToM = 1.0e-10;
595 RealType debyeToCm = 3.33564095198e-30;
597 for (mol = info_->beginMolecule(miter); mol != NULL;
598 mol = info_->nextMolecule(miter)) {
599 for (atom = mol->beginAtom(aiter); atom != NULL;
600 atom = mol->nextAtom(aiter)) {
604 if (fca.isFixedCharge()) { charge = fca.getCharge(); }
608 if (fqa.isFluctuatingCharge()) { charge += atom->
getFlucQPos(); }
620 }
else if (charge > 0.0) {
626 if (atom->isDipole()) {
627 dipoleVector += atom->
getDipole() * debyeToCm;
633 MPI_Allreduce(MPI_IN_PLACE, &pChg, 1, MPI_REALTYPE, MPI_SUM,
635 MPI_Allreduce(MPI_IN_PLACE, &nChg, 1, MPI_REALTYPE, MPI_SUM,
638 MPI_Allreduce(MPI_IN_PLACE, &pCount, 1, MPI_INTEGER, MPI_SUM,
640 MPI_Allreduce(MPI_IN_PLACE, &nCount, 1, MPI_INTEGER, MPI_SUM,
644 MPI_SUM, MPI_COMM_WORLD);
646 MPI_SUM, MPI_COMM_WORLD);
649 MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
653 Vector3d boxDipole = dipoleVector;
656 RealType chg_value = nChg <= pChg ? nChg : pChg;
659 if (pCount > 0 && nCount > 0) {
665 boxDipole += (pPos - nPos) * chg_value;
666 snap->setSystemDipole(boxDipole);
669 return snap->getSystemDipole();
673 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
675 if (!snap->hasSystemQuadrupole) {
676 SimInfo::MoleculeIterator miter;
677 vector<Atom*>::iterator aiter;
682 Vector3d dipole(0.0);
685 RealType chargeToC = 1.60217733e-19;
686 RealType angstromToM = 1.0e-10;
687 RealType debyeToCm = 3.33564095198e-30;
689 for (mol = info_->beginMolecule(miter); mol != NULL;
690 mol = info_->nextMolecule(miter)) {
691 for (atom = mol->beginAtom(aiter); atom != NULL;
692 atom = mol->nextAtom(aiter)) {
700 if (fca.isFixedCharge()) { charge = fca.getCharge(); }
704 if (fqa.isFluctuatingCharge()) { charge += atom->
getFlucQPos(); }
708 qpole += 0.5 * charge * outProduct(ri, ri);
714 qpole += 0.5 * outProduct(dipole, ri);
715 qpole += 0.5 * outProduct(ri, dipole);
718 if (ma.isQuadrupole()) {
726 MPI_SUM, MPI_COMM_WORLD);
729 snap->setSystemQuadrupole(qpole);
732 return snap->getSystemQuadrupole();
736 Vector3d Thermo::getHeatFlux() {
737 Snapshot* currSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
738 SimInfo::MoleculeIterator miter;
739 vector<StuntDouble*>::iterator iiter;
742 RigidBody::AtomIterator ai;
744 Vector3d vel, omegaB, omegaL;
745 Vector3d ambient, vorticity;
747 Mat3x3d I, A, Atrans;
758 Vector3d heatFluxJc = V3Zero;
760 if (usePeculiarVelocities_) {
761 vorticity = velField_->getVorticity();
765 for (mol = info_->beginMolecule(miter); mol != NULL;
766 mol = info_->nextMolecule(miter)) {
767 for (sd = mol->beginIntegrableObject(iiter); sd != NULL;
768 sd = mol->nextIntegrableObject(iiter)) {
771 if (usePeculiarVelocities_) {
772 ambient = velField_->getVelocity(sd->
getPos());
776 kinetic = mass * (vel[0] * vel[0] + vel[1] * vel[1] + vel[2] * vel[2]);
782 Atrans = A.transpose();
789 omegaB[j] = J[j] / I(j,j);
790 omegaB[k] = J[k] / I(k,k);
792 omegaB[0] = J[0] / I(0,0);
793 omegaB[1] = J[1] / I(1,1);
794 omegaB[2] = J[2] / I(2,2);
796 omegaL = Atrans * omegaB - vorticity;
799 kinetic +=
dot(omegaB, I * omegaB);
805 RigidBody* rb =
dynamic_cast<RigidBody*
>(sd);
806 for (atom = rb->beginAtom(ai); atom != NULL;
807 atom = rb->nextAtom(ai)) {
814 potential *= Constants::energyConvert;
816 eatom = (kinetic + potential) / 2.0;
817 heatFluxJc[0] += eatom * vel[0];
818 heatFluxJc[1] += eatom * vel[1];
819 heatFluxJc[2] += eatom * vel[2];
828 MPI_Allreduce(MPI_IN_PLACE, &heatFluxJc[0], 3, MPI_REALTYPE, MPI_SUM,
834 Vector3d heatFluxJv =
835 currSnapshot->getConductiveHeatFlux() * Constants::energyConvert;
838 return (heatFluxJv + heatFluxJc) / this->getVolume();
842 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
844 if (!snap->hasCOMvel) {
845 SimInfo::MoleculeIterator i;
850 Vector3d comVel(0.0);
851 RealType totalMass(0.0);
853 for (mol = info_->beginMolecule(i); mol != NULL;
854 mol = info_->nextMolecule(i)) {
855 RealType mass = mol->
getMass();
858 if (usePeculiarVelocities_) {
859 ambient = velField_->getVelocity(mol->
getCom());
863 comVel += mass * vel;
867 MPI_Allreduce(MPI_IN_PLACE, &totalMass, 1, MPI_REALTYPE, MPI_SUM,
870 MPI_SUM, MPI_COMM_WORLD);
874 snap->setCOMvel(comVel);
876 return snap->getCOMvel();
880 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
883 SimInfo::MoleculeIterator i;
887 RealType totalMass(0.0);
889 for (mol = info_->beginMolecule(i); mol != NULL;
890 mol = info_->nextMolecule(i)) {
891 RealType mass = mol->
getMass();
893 com += mass * mol->
getCom();
897 MPI_Allreduce(MPI_IN_PLACE, &totalMass, 1, MPI_REALTYPE, MPI_SUM,
900 MPI_SUM, MPI_COMM_WORLD);
906 return snap->getCOM();
914 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
916 if (!(snap->hasCOM && snap->hasCOMvel)) {
917 SimInfo::MoleculeIterator i;
920 RealType totalMass(0.0);
927 for (mol = info_->beginMolecule(i); mol != NULL;
928 mol = info_->nextMolecule(i)) {
929 RealType mass = mol->
getMass();
931 com += mass * mol->
getCom();
934 if (usePeculiarVelocities_) {
935 ambient = velField_->getVelocity(mol->
getCom());
939 comVel += mass * vel;
944 MPI_Allreduce(MPI_IN_PLACE, &totalMass, 1, MPI_REALTYPE, MPI_SUM,
947 MPI_SUM, MPI_COMM_WORLD);
949 MPI_SUM, MPI_COMM_WORLD);
955 snap->setCOMvel(comVel);
957 com = snap->getCOM();
958 comVel = snap->getCOMvel();
973 Vector3d& angularMomentum) {
974 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
975 Molecule::IntegrableObjectIterator j;
978 if (!(snap->hasInertiaTensor && snap->hasCOMw)) {
986 Vector3d comVel(0.0);
990 SimInfo::MoleculeIterator i;
999 for (mol = info_->beginMolecule(i); mol != NULL;
1000 mol = info_->nextMolecule(i)) {
1001 for (sd = mol->beginIntegrableObject(j); sd != NULL;
1002 sd = mol->nextIntegrableObject(j)) {
1004 v = sd->
getVel() - comVel;
1009 xx += r[0] * r[0] * m;
1010 yy += r[1] * r[1] * m;
1011 zz += r[2] * r[2] * m;
1014 xy += r[0] * r[1] * m;
1015 xz += r[0] * r[2] * m;
1016 yz += r[1] * r[2] * m;
1018 angularMomentum +=
cross(r, v) * m;
1021 RotMat3x3d A = sd->
getA();
1022 Itmp += A.transpose() * sd->
getI() * A;
1023 angularMomentum += sd->
getJ();
1028 inertiaTensor(0, 0) = yy + zz;
1029 inertiaTensor(0, 1) = -xy;
1030 inertiaTensor(0, 2) = -xz;
1031 inertiaTensor(1, 0) = -xy;
1032 inertiaTensor(1, 1) = xx + zz;
1033 inertiaTensor(1, 2) = -yz;
1034 inertiaTensor(2, 0) = -xz;
1035 inertiaTensor(2, 1) = -yz;
1036 inertiaTensor(2, 2) = xx + yy;
1038 inertiaTensor += Itmp;
1042 MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
1044 MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
1047 snap->setCOMw(angularMomentum);
1048 snap->setInertiaTensor(inertiaTensor);
1051 angularMomentum = snap->getCOMw();
1052 inertiaTensor = snap->getInertiaTensor();
1058 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
1060 if (!(snap->hasBoundingBox)) {
1061 SimInfo::MoleculeIterator i;
1062 Molecule::RigidBodyIterator ri;
1063 Molecule::AtomIterator ai;
1067 Vector3d pos, bMax, bMin;
1070 for (mol = info_->beginMolecule(i); mol != NULL;
1071 mol = info_->nextMolecule(i)) {
1073 for (rb = mol->beginRigidBody(ri); rb != NULL;
1074 rb = mol->nextRigidBody(ri)) {
1078 for (atom = mol->beginAtom(ai); atom != NULL;
1079 atom = mol->nextAtom(ai)) {
1086 for (
int i = 0; i < 3; i++) {
1087 bMax[i] = max(bMax[i], pos[i]);
1088 bMin[i] = min(bMin[i], pos[i]);
1096 MPI_Allreduce(MPI_IN_PLACE, &bMax[0], 3, MPI_REALTYPE, MPI_MAX,
1099 MPI_Allreduce(MPI_IN_PLACE, &bMin[0], 3, MPI_REALTYPE, MPI_MIN,
1102 Mat3x3d bBox = Mat3x3d(0.0);
1103 for (
int i = 0; i < 3; i++) {
1104 bBox(i, i) = bMax[i] - bMin[i];
1114 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
1116 if (!snap->hasCOMw) {
1118 Vector3d comVel(0.0);
1119 Vector3d angularMomentum(0.0);
1123 SimInfo::MoleculeIterator i;
1126 Vector3d thisr(0.0);
1127 Vector3d thisp(0.0);
1131 for (mol = info_->beginMolecule(i); mol != NULL;
1132 mol = info_->nextMolecule(i)) {
1134 thisr = mol->
getCom() - com;
1135 thisp = (mol->
getComVel() - comVel) * thisMass;
1137 angularMomentum +=
cross(thisr, thisp);
1142 MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
1145 snap->setCOMw(angularMomentum);
1148 return snap->getCOMw();
1160 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
1162 if (!snap->hasGyrationalVolume) {
1165 Vector3d dummyAngMom;
1166 RealType sysconstants;
1170 geomCnst = 3.0 / 2.0;
1176 geomCnst / (RealType)(info_->getNGlobalIntegrableObjects());
1178 4.0 / 3.0 * Constants::PI * pow(sysconstants, geomCnst) * sqrt(det);
1180 snap->setGyrationalVolume(volume);
1182 return snap->getGyrationalVolume();
1186 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
1188 if (!(snap->hasInertiaTensor && snap->hasGyrationalVolume)) {
1190 Vector3d dummyAngMom;
1191 RealType sysconstants;
1194 geomCnst = 3.0 / 2.0;
1200 geomCnst / (RealType)(info_->getNGlobalIntegrableObjects());
1202 4.0 / 3.0 * Constants::PI * pow(sysconstants, geomCnst) * sqrt(detI);
1203 snap->setGyrationalVolume(volume);
1205 volume = snap->getGyrationalVolume();
1211 RealType Thermo::getTaggedAtomPairDistance() {
1212 Snapshot* currSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
1213 Globals* simParams = info_->getSimParams();
1215 if (simParams->haveTaggedAtomPair() &&
1216 simParams->havePrintTaggedPairDistance()) {
1217 if (simParams->getPrintTaggedPairDistance()) {
1218 pair<int, int> tap = simParams->getTaggedAtomPair();
1219 Vector3d pos1, pos2, rab;
1222 int mol1 = info_->getGlobalMolMembership(tap.first);
1223 int mol2 = info_->getGlobalMolMembership(tap.second);
1225 int proc1 = info_->getMolToProc(mol1);
1226 int proc2 = info_->getMolToProc(mol2);
1229 if (proc1 == worldRank) {
1230 StuntDouble* sd1 = info_->getIOIndexToIntegrableObject(tap.first);
1235 MPI_Bcast(data, 3, MPI_REALTYPE, proc1, MPI_COMM_WORLD);
1237 MPI_Bcast(data, 3, MPI_REALTYPE, proc1, MPI_COMM_WORLD);
1238 pos1 = Vector3d(data);
1241 if (proc2 == worldRank) {
1242 StuntDouble* sd2 = info_->getIOIndexToIntegrableObject(tap.second);
1243 pos2 = sd2->getPos();
1247 MPI_Bcast(data, 3, MPI_REALTYPE, proc2, MPI_COMM_WORLD);
1249 MPI_Bcast(data, 3, MPI_REALTYPE, proc2, MPI_COMM_WORLD);
1250 pos2 = Vector3d(data);
1253 StuntDouble* at1 = info_->getIOIndexToIntegrableObject(tap.first);
1254 StuntDouble* at2 = info_->getIOIndexToIntegrableObject(tap.second);
1255 pos1 = at1->getPos();
1256 pos2 = at2->getPos();
1267 RealType Thermo::getHullVolume() {
1269 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
1270 if (!snap->hasHullVolume) {
1273 Globals* simParams = info_->getSimParams();
1274 const std::string ht = simParams->getHULL_Method();
1276 if (ht ==
"Convex") {
1277 surfaceMesh_ =
new ConvexHull();
1278 }
else if (ht ==
"AlphaShape") {
1279 surfaceMesh_ =
new AlphaHull(simParams->getAlpha());
1286 std::vector<StuntDouble*> localSites_;
1289 SimInfo::MoleculeIterator i;
1290 Molecule::IntegrableObjectIterator j;
1292 for (mol = info_->beginMolecule(i); mol != NULL;
1293 mol = info_->nextMolecule(i)) {
1294 for (sd = mol->beginIntegrableObject(j); sd != NULL;
1295 sd = mol->nextIntegrableObject(j)) {
1296 localSites_.push_back(sd);
1301 surfaceMesh_->computeHull(localSites_);
1302 snap->setHullVolume(surfaceMesh_->getVolume());
1304 delete surfaceMesh_;
1307 return snap->getHullVolume();
AtomType * getAtomType()
Returns the AtomType of this Atom.
RealType getMass()
get total mass of this molecule
Vector3d getComVel()
Returns the velocity of center of mass of this molecule.
Vector3d getCom()
Returns the current center of mass position of this molecule.
Real * getArrayPointer()
Returns the pointer of internal array.
void updateAtoms()
update the positions of atoms belong to this rigidbody
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
The Snapshot class is a repository storing dynamic data during a Simulation.
Mat3x3d getBoundingBox()
Returns the Bounding Box.
void setBoundingBox(const Mat3x3d &m)
Sets the Bounding Box.
void wrapVector(Vector3d &v)
Wrapping the vector according to periodic boundary condition.
Real determinant() const
Returns the determinant of this matrix.
"Don't move, or you're dead! Stand up! Captain, we've got them!"
RotMat3x3d getA()
Returns the current rotation matrix of this stuntDouble.
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.
Mat3x3d getQuadrupole()
Returns the current quadrupole tensor 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.
RealType getFlucQPos()
Returns the current fluctuating charge of this stuntDouble.
Vector3d getDipole()
Returns the current dipole vector of this stuntDouble.
RealType getParticlePot()
Returns the current particlePot of this stuntDouble.
bool isRigidBody()
Tests if this stuntDouble is a rigid body.
Vector3d getJ()
Returns the current angular momentum of this stuntDouble (body -fixed).
bool isDirectional()
Tests if this stuntDouble is a directional one.
Mat3x3d getPressureTensor()
gives the pressure tensor in amu*fs^-2*Ang^-1
Vector3d getSystemDipole()
accumulate and return the simulation box dipole moment in C*m
void getComAll(Vector3d &com, Vector3d &comVel)
Returns the center of the mass and Center of Mass velocity of the whole system.
void getInertiaTensor(Mat3x3d &inertiaTensor, Vector3d &angularMomentum)
Returns the inertia tensor and the total angular momentum for for the entire system.
RealType getGyrationalVolume()
Returns volume of system as estimated by an ellipsoid defined by the radii of gyration.
Vector3d getCom()
Returns the center of the mass of the whole system.
Mat3x3d getSystemQuadrupole()
accumulate and return the simulation box dipole moment in debye Angstroms
Vector3d getAngularMomentum()
Returns system angular momentum.
Vector3d getComVel()
Returns the velocity of center of mass of the whole system.
Mat3x3d getBoundingBox()
Returns the Axis-aligned bounding box for the current system.
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.
const Real * getArrayPointer() const
Returns the pointer of internal array.
Real length() const
Returns the length of this vector.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
Vector3< Real > cross(const Vector3< Real > &v1, const Vector3< Real > &v2)
Returns the cross product of two Vectors.
Real dot(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the dot product of two DynamicVectors.