45#include "selection/SelectionEvaluator.hpp"
58#include "types/FixedChargeAdapter.hpp"
59#include "types/FluctuatingChargeAdapter.hpp"
63 SelectionEvaluator::SelectionEvaluator(
SimInfo* si) :
64 info(si), nameFinder(info), distanceFinder(info), hullFinder(info),
65 alphaHullFinder(info), indexFinder(info), isLoaded_(false),
66 hasSurfaceArea_(false), hasVolume_(false) {
67 nObjects.push_back(info->getNGlobalAtoms() + info->getNGlobalRigidBodies());
68 nObjects.push_back(info->getNGlobalBonds());
69 nObjects.push_back(info->getNGlobalBends());
70 nObjects.push_back(info->getNGlobalTorsions());
71 nObjects.push_back(info->getNGlobalInversions());
72 nObjects.push_back(info->getNGlobalMolecules());
75 bool SelectionEvaluator::loadScript(
const std::string& filename,
76 const std::string& script) {
77 clearDefinitionsAndLoadPredefined();
78 this->filename = filename;
79 this->script = script;
80 if (!compiler.compile(filename, script)) {
82 errorMessage = compiler.getErrorMessage();
84 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
85 "SelectionCompiler Error: %s\n", errorMessage.c_str());
86 painCave.severity = OPENMD_ERROR;
93 aatoken = compiler.getAatokenCompiled();
94 linenumbers = compiler.getLineNumbers();
95 lineIndices = compiler.getLineIndices();
97 std::vector<std::vector<Token>>::const_iterator i;
100 for (i = aatoken.begin(); i != aatoken.end(); ++i) {
101 if (containDynamicToken(*i)) {
111 void SelectionEvaluator::clearState() {
116 bool SelectionEvaluator::loadScriptString(
const std::string& script) {
118 return loadScript(
"", script);
121 bool SelectionEvaluator::loadScriptFile(
const std::string& filename) {
123 return loadScriptFileInternal(filename);
126 bool SelectionEvaluator::loadScriptFileInternal(
const std::string& filename) {
128 if (!ifs.is_open()) {
return false; }
130 const int bufferSize = 65535;
131 char buffer[bufferSize];
133 while (ifs.getline(buffer, bufferSize)) {
136 return loadScript(filename, script);
139 void SelectionEvaluator::instructionDispatchLoop(
SelectionSet& bs) {
140 while (pc < aatoken.size()) {
141 statement = aatoken[pc++];
142 statementLength = statement.size();
143 Token token = statement[0];
152 unrecognizedCommand(token);
158 void SelectionEvaluator::instructionDispatchLoop(
SelectionSet& bs,
160 while (pc < aatoken.size()) {
161 statement = aatoken[pc++];
162 statementLength = statement.size();
163 Token token = statement[0];
172 unrecognizedCommand(token);
178 SelectionSet SelectionEvaluator::expression(
const std::vector<Token>& code,
181 std::stack<SelectionSet> stack;
182 vector<int> bsSize = bs.
size();
184 for (
unsigned int pc = pcStart; pc < code.size(); ++pc) {
185 Token instruction = code[pc];
187 switch (instruction.tok) {
188 case Token::expressionBegin:
190 case Token::expressionEnd:
193 bs = allInstruction();
197 bs = createSelectionSets();
214 withinInstruction(instruction, stack.top());
216 case Token::alphahull:
217 stack.push(alphaHullInstruction(instruction));
227 nameInstruction(std::any_cast<std::string>(instruction.value)));
230 stack.push(indexInstruction(instruction.value));
232 case Token::identifier:
233 stack.push(lookupValue(std::any_cast<std::string>(instruction.value)));
241 stack.push(comparatorInstruction(instruction));
244 unrecognizedExpression();
247 if (stack.size() != 1)
248 evalError(
"atom expression compiler error - stack over/underflow");
253 SelectionSet SelectionEvaluator::expression(
const std::vector<Token>& code,
254 int pcStart,
int frame) {
256 std::stack<SelectionSet> stack;
258 for (
unsigned int pc = pcStart; pc < code.size(); ++pc) {
259 Token instruction = code[pc];
261 switch (instruction.tok) {
262 case Token::expressionBegin:
264 case Token::expressionEnd:
267 bs = allInstruction();
288 withinInstruction(instruction, stack.top(), frame);
290 case Token::alphahull:
291 stack.push(alphaHullInstruction(instruction, frame));
294 stack.push(hull(frame));
301 nameInstruction(std::any_cast<std::string>(instruction.value)));
304 stack.push(indexInstruction(instruction.value));
306 case Token::identifier:
307 stack.push(lookupValue(std::any_cast<std::string>(instruction.value)));
315 stack.push(comparatorInstruction(instruction, frame));
318 unrecognizedExpression();
321 if (stack.size() != 1)
322 evalError(
"atom expression compiler error - stack over/underflow");
328 const Token& instruction) {
329 int comparator = instruction.tok;
330 int property = instruction.intValue;
331 float comparisonValue = std::any_cast<float>(instruction.value);
335 SimInfo::MoleculeIterator mi;
337 Molecule::AtomIterator ai;
339 Molecule::RigidBodyIterator rbIter;
344 compareProperty(mol, bs, property, comparator, comparisonValue);
346 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
347 compareProperty(atom, bs, property, comparator, comparisonValue);
350 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
351 rb = mol->nextRigidBody(rbIter)) {
352 compareProperty(rb, bs, property, comparator, comparisonValue);
356 return bs.parallelReduce();
360 const Token& instruction,
int frame) {
361 int comparator = instruction.tok;
362 int property = instruction.intValue;
363 float comparisonValue = std::any_cast<float>(instruction.value);
367 SimInfo::MoleculeIterator mi;
369 Molecule::AtomIterator ai;
371 Molecule::RigidBodyIterator rbIter;
376 compareProperty(mol, bs, property, comparator, comparisonValue, frame);
378 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
379 compareProperty(atom, bs, property, comparator, comparisonValue, frame);
382 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
383 rb = mol->nextRigidBody(rbIter)) {
384 compareProperty(rb, bs, property, comparator, comparisonValue, frame);
388 return bs.parallelReduce();
392 int property,
int comparator,
393 float comparisonValue) {
394 RealType propertyValue = 0.0;
400 Atom* atom =
static_cast<Atom*
>(sd);
409 Atom* atom =
static_cast<Atom*
>(sd);
410 propertyValue = getCharge(atom);
413 RigidBody::AtomIterator ai;
415 for (atom = rb->beginAtom(ai); atom != NULL; atom = rb->nextAtom(ai)) {
416 propertyValue += getCharge(atom);
421 propertyValue = sd->
getPos().
x();
424 propertyValue = sd->
getPos().
y();
427 propertyValue = sd->
getPos().
z();
429 case Token::wrappedX:
432 propertyValue = pos.
x();
434 case Token::wrappedY:
437 propertyValue = pos.
y();
439 case Token::wrappedZ:
442 propertyValue = pos.
z();
448 unrecognizedAtomProperty(property);
452 switch (comparator) {
454 match = propertyValue < comparisonValue;
457 match = propertyValue <= comparisonValue;
460 match = propertyValue >= comparisonValue;
463 match = propertyValue > comparisonValue;
466 match = fabs(propertyValue - comparisonValue) <= OpenMD::epsilon;
469 match = propertyValue != comparisonValue;
477 int property,
int comparator,
478 float comparisonValue) {
479 RealType propertyValue = 0.0;
484 propertyValue = mol->
getMass();
486 case Token::charge: {
487 Molecule::AtomIterator ai;
489 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
490 propertyValue += getCharge(atom);
494 propertyValue = mol->
getCom().
x();
497 propertyValue = mol->
getCom().
y();
500 propertyValue = mol->
getCom().
z();
502 case Token::wrappedX:
505 propertyValue = pos.
x();
507 case Token::wrappedY:
510 propertyValue = pos.
y();
512 case Token::wrappedZ:
515 propertyValue = pos.
z();
521 unrecognizedMoleculeProperty(property);
525 switch (comparator) {
527 match = propertyValue < comparisonValue;
530 match = propertyValue <= comparisonValue;
533 match = propertyValue >= comparisonValue;
536 match = propertyValue > comparisonValue;
539 match = fabs(propertyValue - comparisonValue) <= OpenMD::epsilon;
542 match = propertyValue != comparisonValue;
550 int property,
int comparator,
551 float comparisonValue,
int frame) {
552 RealType propertyValue = 0.0;
556 propertyValue = mol->
getMass();
558 case Token::charge: {
559 Molecule::AtomIterator ai;
561 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
562 propertyValue += getCharge(atom, frame);
566 propertyValue = mol->
getCom(frame).
x();
569 propertyValue = mol->
getCom(frame).
y();
572 propertyValue = mol->
getCom(frame).
z();
574 case Token::wrappedX:
577 propertyValue = pos.
x();
579 case Token::wrappedY:
582 propertyValue = pos.
y();
584 case Token::wrappedZ:
587 propertyValue = pos.
z();
594 unrecognizedMoleculeProperty(property);
598 switch (comparator) {
600 match = propertyValue < comparisonValue;
603 match = propertyValue <= comparisonValue;
606 match = propertyValue >= comparisonValue;
609 match = propertyValue > comparisonValue;
612 match = fabs(propertyValue - comparisonValue) <= OpenMD::epsilon;
615 match = propertyValue != comparisonValue;
621 int property,
int comparator,
622 float comparisonValue,
int frame) {
623 RealType propertyValue = 0.0;
628 Atom* atom =
static_cast<Atom*
>(sd);
637 Atom* atom =
static_cast<Atom*
>(sd);
638 propertyValue = getCharge(atom, frame);
641 RigidBody::AtomIterator ai;
643 for (atom = rb->beginAtom(ai); atom != NULL; atom = rb->nextAtom(ai)) {
644 propertyValue += getCharge(atom, frame);
649 propertyValue = sd->
getPos(frame).
x();
652 propertyValue = sd->
getPos(frame).
y();
655 propertyValue = sd->
getPos(frame).
z();
657 case Token::wrappedX:
660 propertyValue = pos.
x();
662 case Token::wrappedY:
665 propertyValue = pos.
y();
667 case Token::wrappedZ:
670 propertyValue = pos.
z();
677 unrecognizedAtomProperty(property);
681 switch (comparator) {
683 match = propertyValue < comparisonValue;
686 match = propertyValue <= comparisonValue;
689 match = propertyValue >= comparisonValue;
692 match = propertyValue > comparisonValue;
695 match = fabs(propertyValue - comparisonValue) <= OpenMD::epsilon;
698 match = propertyValue != comparisonValue;
704 void SelectionEvaluator::withinInstruction(
const Token& instruction,
706 std::any withinSpec = instruction.value;
708 if (withinSpec.type() ==
typeid(
float)) {
709 distance = std::any_cast<float>(withinSpec);
710 }
else if (withinSpec.type() ==
typeid(
int)) {
711 distance = std::any_cast<int>(withinSpec);
713 evalError(
"casting error in withinInstruction");
717 bs = distanceFinder.find(bs,
distance);
720 void SelectionEvaluator::withinInstruction(
const Token& instruction,
722 std::any withinSpec = instruction.value;
724 if (withinSpec.type() ==
typeid(
float)) {
725 distance = std::any_cast<float>(withinSpec);
726 }
else if (withinSpec.type() ==
typeid(
int)) {
727 distance = std::any_cast<int>(withinSpec);
729 evalError(
"casting error in withinInstruction");
733 bs = distanceFinder.find(bs,
distance, frame);
737 const Token& instruction) {
740 std::any alphaSpec = instruction.value;
742 if (alphaSpec.type() ==
typeid(
float)) {
743 alpha = std::any_cast<float>(alphaSpec);
744 }
else if (alphaSpec.type() ==
typeid(
int)) {
745 alpha = std::any_cast<int>(alphaSpec);
747 evalError(
"casting error in alphaHullInstruction");
751 alphaHullFinder.setAlpha(alpha);
752 bs = alphaHullFinder.findHull();
753 surfaceArea_ = alphaHullFinder.getSurfaceArea();
754 hasSurfaceArea_ =
true;
755 volume_ = alphaHullFinder.getVolume();
758 return bs.parallelReduce();
762 const Token& instruction,
int frame) {
765 std::any alphaSpec = instruction.value;
767 if (alphaSpec.type() ==
typeid(
float)) {
768 alpha = std::any_cast<float>(alphaSpec);
769 }
else if (alphaSpec.type() ==
typeid(
int)) {
770 alpha = std::any_cast<int>(alphaSpec);
772 evalError(
"casting error in alphaHullInstruction");
776 alphaHullFinder.setAlpha(alpha);
777 bs = alphaHullFinder.findHull(frame);
778 surfaceArea_ = alphaHullFinder.getSurfaceArea();
779 hasSurfaceArea_ =
true;
780 volume_ = alphaHullFinder.getVolume();
783 return bs.parallelReduce();
786 void SelectionEvaluator::define() {
787 assert(statement.size() >= 3);
789 std::string variable = std::any_cast<std::string>(statement[1].value);
792 VariablesType::value_type(variable, expression(statement, 2)));
796 void SelectionEvaluator::predefine(
const std::string& script) {
797 if (compiler.compile(
"#predefine", script)) {
798 std::vector<std::vector<Token>> aatoken = compiler.getAatokenCompiled();
799 if (aatoken.size() != 1) {
800 evalError(
"predefinition does not have exactly 1 command:" + script);
803 std::vector<Token> statement = aatoken[0];
804 if (statement.size() > 2) {
805 int tok = statement[1].tok;
806 if (tok == Token::identifier ||
807 (tok & Token::predefinedset) == Token::predefinedset) {
808 std::string variable = std::any_cast<std::string>(statement[1].value);
809 variables.insert(VariablesType::value_type(variable, statement));
812 evalError(
"invalid variable name:" + script);
815 evalError(
"bad predefinition length:" + script);
819 evalError(
"predefined set compile error:" + script +
820 "\ncompile error:" + compiler.getErrorMessage());
825 bs = expression(statement, 1);
828 void SelectionEvaluator::select(
SelectionSet& bs,
int frame) {
829 bs = expression(statement, 1, frame);
832 SelectionSet SelectionEvaluator::lookupValue(
const std::string& variable) {
834 std::map<std::string, std::any>::iterator i = variables.find(variable);
836 if (i != variables.end()) {
838 return std::any_cast<SelectionSet>(i->second);
839 }
else if (i->second.type() ==
typeid(std::vector<Token>)) {
840 bs = expression(std::any_cast<std::vector<Token>>(i->second), 2);
842 return bs.parallelReduce();
845 unrecognizedIdentifier(variable);
848 return bs.parallelReduce();
851 SelectionSet SelectionEvaluator::nameInstruction(
const std::string& name) {
852 return nameFinder.match(name);
855 bool SelectionEvaluator::containDynamicToken(
856 const std::vector<Token>& tokens) {
857 std::vector<Token>::const_iterator i;
858 for (i = tokens.begin(); i != tokens.end(); ++i) {
859 if (i->tok & Token::dynamic) {
return true; }
865 void SelectionEvaluator::clearDefinitionsAndLoadPredefined() {
871 SelectionSet SelectionEvaluator::createSelectionSets() {
880 instructionDispatchLoop(bs);
882 return bs.parallelReduce();
889 instructionDispatchLoop(bs, frame);
891 return bs.parallelReduce();
894 SelectionSet SelectionEvaluator::indexInstruction(
const std::any& value) {
897 if (value.type() ==
typeid(
int)) {
898 int index = std::any_cast<int>(value);
900 index >=
static_cast<int>(bs.bitsets_[
STUNTDOUBLE].size())) {
903 bs = indexFinder.find(index);
905 }
else if (value.type() ==
typeid(std::pair<int, int>)) {
906 std::pair<int, int> indexRange =
907 std::any_cast<std::pair<int, int>>(value);
908 assert(indexRange.first <= indexRange.second);
909 if (indexRange.first < 0 ||
911 static_cast<int>(bs.bitsets_[
STUNTDOUBLE].size())) {
912 invalidIndexRange(indexRange);
914 bs = indexFinder.find(indexRange.first, indexRange.second);
918 return bs.parallelReduce();
924 SimInfo::MoleculeIterator mi;
925 Molecule::AtomIterator ai;
926 Molecule::RigidBodyIterator rbIter;
927 Molecule::BondIterator bondIter;
928 Molecule::BendIterator bendIter;
929 Molecule::TorsionIterator torsionIter;
930 Molecule::InversionIterator inversionIter;
944 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
947 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
948 rb = mol->nextRigidBody(rbIter)) {
951 for (bond = mol->beginBond(bondIter); bond != NULL;
952 bond = mol->nextBond(bondIter)) {
955 for (bend = mol->beginBend(bendIter); bend != NULL;
956 bend = mol->nextBend(bendIter)) {
959 for (torsion = mol->beginTorsion(torsionIter); torsion != NULL;
960 torsion = mol->nextTorsion(torsionIter)) {
963 for (inversion = mol->beginInversion(inversionIter); inversion != NULL;
964 inversion = mol->nextInversion(inversionIter)) {
976 bs = hullFinder.findHull();
977 surfaceArea_ = hullFinder.getSurfaceArea();
978 hasSurfaceArea_ =
true;
979 volume_ = hullFinder.getVolume();
982 return bs.parallelReduce();
988 bs = hullFinder.findHull(frame);
990 return bs.parallelReduce();
993 RealType SelectionEvaluator::getCharge(
Atom* atom) {
994 RealType charge = 0.0;
998 if (fca.isFixedCharge()) { charge = fca.getCharge(); }
1001 if (fqa.isFluctuatingCharge()) { charge += atom->
getFlucQPos(); }
1005 RealType SelectionEvaluator::getCharge(
Atom* atom,
int frame) {
1006 RealType charge = 0.0;
1010 if (fca.isFixedCharge()) { charge = fca.getCharge(); }
1013 if (fqa.isFluctuatingCharge()) { charge += atom->
getFlucQPos(frame); }
AtomType * getAtomType()
Returns the AtomType of this Atom.
AtomType is what OpenMD looks to for unchanging data about an atom.
RealType getMass()
get total mass of this molecule
int getGlobalIndex()
Returns the global index of this molecule.
Vector3d getCom()
Returns the current center of mass position of this molecule.
std::vector< int > size() const
Returns the number of bits of space actually in use by this SelectionSet to represent bit values.
void clearAll()
Sets all of the bits in this SelectionSet to false.
void flip(std::vector< int > bitIndex)
Sets the bit at the specified index to to the complement of its current value.
int getGlobalIndex()
Returns the global index of this ShortRangeInteraction.
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
Molecule * beginMolecule(MoleculeIterator &i)
Returns the first molecule in this SimInfo and intialize the iterator.
Molecule * nextMolecule(MoleculeIterator &i)
Returns the next avaliable Molecule based on the iterator.
SnapshotManager * getSnapshotManager()
Returns the snapshot manager.
void wrapVector(Vector3d &v)
Wrapping the vector according to periodic boundary condition.
Snapshot * getCurrentSnapshot()
Returns the pointer of current snapshot.
"Don't move, or you're dead! Stand up! Captain, we've got them!"
RealType getMass()
Returns the mass of this stuntDouble.
Vector3d getPos()
Returns the current position of this stuntDouble.
RealType getFlucQPos()
Returns the current fluctuating charge of this stuntDouble.
bool isRigidBody()
Tests if this stuntDouble is a rigid body.
int getGlobalIndex()
Returns the global index of this stuntDouble.
bool isAtom()
Tests if this stuntDouble is an atom.
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 length()
Returns the length of this vector.
ifstrstream class provides a stream interface to read data from files.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
@ STUNTDOUBLE
StuntDoubles (Atoms & RigidBodies)
Real distance(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the distance between two DynamicVectors.