48#include "selection/SelectionEvaluator.hpp"
61#include "types/FixedChargeAdapter.hpp"
62#include "types/FluctuatingChargeAdapter.hpp"
66 SelectionEvaluator::SelectionEvaluator(
SimInfo* si) :
67 info(si), nameFinder(info), distanceFinder(info), hullFinder(info),
68 alphaHullFinder(info), indexFinder(info), isLoaded_(false),
69 hasSurfaceArea_(false), hasVolume_(false) {
70 nObjects.push_back(info->getNGlobalAtoms() + info->getNGlobalRigidBodies());
71 nObjects.push_back(info->getNGlobalBonds());
72 nObjects.push_back(info->getNGlobalBends());
73 nObjects.push_back(info->getNGlobalTorsions());
74 nObjects.push_back(info->getNGlobalInversions());
75 nObjects.push_back(info->getNGlobalMolecules());
78 bool SelectionEvaluator::loadScript(
const std::string& filename,
79 const std::string& script) {
80 clearDefinitionsAndLoadPredefined();
81 this->filename = filename;
82 this->script = script;
83 if (!compiler.compile(filename, script)) {
85 errorMessage = compiler.getErrorMessage();
87 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
88 "SelectionCompiler Error: %s\n", errorMessage.c_str());
89 painCave.severity = OPENMD_ERROR;
96 aatoken = compiler.getAatokenCompiled();
97 linenumbers = compiler.getLineNumbers();
98 lineIndices = compiler.getLineIndices();
100 std::vector<std::vector<Token>>::const_iterator i;
103 for (i = aatoken.begin(); i != aatoken.end(); ++i) {
104 if (containDynamicToken(*i)) {
114 void SelectionEvaluator::clearState() {
119 bool SelectionEvaluator::loadScriptString(
const std::string& script) {
121 return loadScript(
"", script);
124 bool SelectionEvaluator::loadScriptFile(
const std::string& filename) {
126 return loadScriptFileInternal(filename);
129 bool SelectionEvaluator::loadScriptFileInternal(
const std::string& filename) {
130 ifstrstream ifs(filename.c_str());
131 if (!ifs.is_open()) {
return false; }
133 const int bufferSize = 65535;
134 char buffer[bufferSize];
136 while (ifs.getline(buffer, bufferSize)) {
139 return loadScript(filename, script);
142 void SelectionEvaluator::instructionDispatchLoop(SelectionSet& bs) {
143 while (pc < aatoken.size()) {
144 statement = aatoken[pc++];
145 statementLength = statement.size();
146 Token token = statement[0];
155 unrecognizedCommand(token);
161 void SelectionEvaluator::instructionDispatchLoop(SelectionSet& bs,
163 while (pc < aatoken.size()) {
164 statement = aatoken[pc++];
165 statementLength = statement.size();
166 Token token = statement[0];
175 unrecognizedCommand(token);
181 SelectionSet SelectionEvaluator::expression(
const std::vector<Token>& code,
183 SelectionSet bs = createSelectionSets();
184 std::stack<SelectionSet> stack;
185 vector<int> bsSize = bs.size();
187 for (
unsigned int pc = pcStart; pc < code.size(); ++pc) {
188 Token instruction = code[pc];
190 switch (instruction.tok) {
191 case Token::expressionBegin:
193 case Token::expressionEnd:
196 bs = allInstruction();
200 bs = createSelectionSets();
217 withinInstruction(instruction, stack.top());
219 case Token::alphahull:
220 stack.push(alphaHullInstruction(instruction));
230 nameInstruction(std::any_cast<std::string>(instruction.value)));
233 stack.push(indexInstruction(instruction.value));
235 case Token::identifier:
236 stack.push(lookupValue(std::any_cast<std::string>(instruction.value)));
244 stack.push(comparatorInstruction(instruction));
247 unrecognizedExpression();
250 if (stack.size() != 1)
251 evalError(
"atom expression compiler error - stack over/underflow");
256 SelectionSet SelectionEvaluator::expression(
const std::vector<Token>& code,
257 int pcStart,
int frame) {
258 SelectionSet bs = createSelectionSets();
259 std::stack<SelectionSet> stack;
261 for (
unsigned int pc = pcStart; pc < code.size(); ++pc) {
262 Token instruction = code[pc];
264 switch (instruction.tok) {
265 case Token::expressionBegin:
267 case Token::expressionEnd:
270 bs = allInstruction();
274 bs = SelectionSet(nObjects);
291 withinInstruction(instruction, stack.top(), frame);
293 case Token::alphahull:
294 stack.push(alphaHullInstruction(instruction, frame));
297 stack.push(hull(frame));
304 nameInstruction(std::any_cast<std::string>(instruction.value)));
307 stack.push(indexInstruction(instruction.value));
309 case Token::identifier:
310 stack.push(lookupValue(std::any_cast<std::string>(instruction.value)));
318 stack.push(comparatorInstruction(instruction, frame));
321 unrecognizedExpression();
324 if (stack.size() != 1)
325 evalError(
"atom expression compiler error - stack over/underflow");
330 SelectionSet SelectionEvaluator::comparatorInstruction(
331 const Token& instruction) {
332 int comparator = instruction.tok;
333 int property = instruction.intValue;
334 float comparisonValue = std::any_cast<float>(instruction.value);
335 SelectionSet bs = createSelectionSets();
338 SimInfo::MoleculeIterator mi;
340 Molecule::AtomIterator ai;
342 Molecule::RigidBodyIterator rbIter;
345 for (mol = info->beginMolecule(mi); mol != NULL;
346 mol = info->nextMolecule(mi)) {
347 compareProperty(mol, bs, property, comparator, comparisonValue);
349 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
350 compareProperty(atom, bs, property, comparator, comparisonValue);
353 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
354 rb = mol->nextRigidBody(rbIter)) {
355 compareProperty(rb, bs, property, comparator, comparisonValue);
359 return bs.parallelReduce();
362 SelectionSet SelectionEvaluator::comparatorInstruction(
363 const Token& instruction,
int frame) {
364 int comparator = instruction.tok;
365 int property = instruction.intValue;
366 float comparisonValue = std::any_cast<float>(instruction.value);
367 SelectionSet bs = createSelectionSets();
370 SimInfo::MoleculeIterator mi;
372 Molecule::AtomIterator ai;
374 Molecule::RigidBodyIterator rbIter;
377 for (mol = info->beginMolecule(mi); mol != NULL;
378 mol = info->nextMolecule(mi)) {
379 compareProperty(mol, bs, property, comparator, comparisonValue, frame);
381 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
382 compareProperty(atom, bs, property, comparator, comparisonValue, frame);
385 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
386 rb = mol->nextRigidBody(rbIter)) {
387 compareProperty(rb, bs, property, comparator, comparisonValue, frame);
391 return bs.parallelReduce();
394 void SelectionEvaluator::compareProperty(StuntDouble* sd, SelectionSet& bs,
395 int property,
int comparator,
396 float comparisonValue) {
397 RealType propertyValue = 0.0;
403 Atom* atom =
static_cast<Atom*
>(sd);
404 propertyValue = atom->getGlobalIndex();
408 propertyValue = sd->getMass();
412 Atom* atom =
static_cast<Atom*
>(sd);
413 propertyValue = getCharge(atom);
414 }
else if (sd->isRigidBody()) {
415 RigidBody* rb =
static_cast<RigidBody*
>(sd);
416 RigidBody::AtomIterator ai;
418 for (atom = rb->beginAtom(ai); atom != NULL; atom = rb->nextAtom(ai)) {
419 propertyValue += getCharge(atom);
424 propertyValue = sd->getPos().x();
427 propertyValue = sd->getPos().y();
430 propertyValue = sd->getPos().z();
432 case Token::wrappedX:
434 info->getSnapshotManager()->getCurrentSnapshot()->wrapVector(pos);
435 propertyValue = pos.x();
437 case Token::wrappedY:
439 info->getSnapshotManager()->getCurrentSnapshot()->wrapVector(pos);
440 propertyValue = pos.y();
442 case Token::wrappedZ:
444 info->getSnapshotManager()->getCurrentSnapshot()->wrapVector(pos);
445 propertyValue = pos.z();
448 propertyValue = sd->getPos().length();
451 unrecognizedAtomProperty(property);
455 switch (comparator) {
457 match = propertyValue < comparisonValue;
460 match = propertyValue <= comparisonValue;
463 match = propertyValue >= comparisonValue;
466 match = propertyValue > comparisonValue;
469 match = fabs(propertyValue - comparisonValue) <= OpenMD::epsilon;
472 match = propertyValue != comparisonValue;
476 if (match) bs.bitsets_[
STUNTDOUBLE].setBitOn(sd->getGlobalIndex());
479 void SelectionEvaluator::compareProperty(Molecule* mol, SelectionSet& bs,
480 int property,
int comparator,
481 float comparisonValue) {
482 RealType propertyValue = 0.0;
487 propertyValue = mol->getMass();
489 case Token::charge: {
490 Molecule::AtomIterator ai;
492 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
493 propertyValue += getCharge(atom);
497 propertyValue = mol->getCom().x();
500 propertyValue = mol->getCom().y();
503 propertyValue = mol->getCom().z();
505 case Token::wrappedX:
507 info->getSnapshotManager()->getCurrentSnapshot()->wrapVector(pos);
508 propertyValue = pos.x();
510 case Token::wrappedY:
512 info->getSnapshotManager()->getCurrentSnapshot()->wrapVector(pos);
513 propertyValue = pos.y();
515 case Token::wrappedZ:
517 info->getSnapshotManager()->getCurrentSnapshot()->wrapVector(pos);
518 propertyValue = pos.z();
521 propertyValue = mol->getCom().length();
524 unrecognizedMoleculeProperty(property);
528 switch (comparator) {
530 match = propertyValue < comparisonValue;
533 match = propertyValue <= comparisonValue;
536 match = propertyValue >= comparisonValue;
539 match = propertyValue > comparisonValue;
542 match = fabs(propertyValue - comparisonValue) <= OpenMD::epsilon;
545 match = propertyValue != comparisonValue;
549 if (match) bs.bitsets_[
MOLECULE].setBitOn(mol->getGlobalIndex());
552 void SelectionEvaluator::compareProperty(Molecule* mol, SelectionSet& bs,
553 int property,
int comparator,
554 float comparisonValue,
int frame) {
555 RealType propertyValue = 0.0;
559 propertyValue = mol->getMass();
561 case Token::charge: {
562 Molecule::AtomIterator ai;
564 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
565 propertyValue += getCharge(atom, frame);
569 propertyValue = mol->getCom(frame).x();
572 propertyValue = mol->getCom(frame).y();
575 propertyValue = mol->getCom(frame).z();
577 case Token::wrappedX:
578 pos = mol->getCom(frame);
579 info->getSnapshotManager()->getSnapshot(frame)->wrapVector(pos);
580 propertyValue = pos.x();
582 case Token::wrappedY:
583 pos = mol->getCom(frame);
584 info->getSnapshotManager()->getSnapshot(frame)->wrapVector(pos);
585 propertyValue = pos.y();
587 case Token::wrappedZ:
588 pos = mol->getCom(frame);
589 info->getSnapshotManager()->getSnapshot(frame)->wrapVector(pos);
590 propertyValue = pos.z();
594 propertyValue = mol->getCom(frame).length();
597 unrecognizedMoleculeProperty(property);
601 switch (comparator) {
603 match = propertyValue < comparisonValue;
606 match = propertyValue <= comparisonValue;
609 match = propertyValue >= comparisonValue;
612 match = propertyValue > comparisonValue;
615 match = fabs(propertyValue - comparisonValue) <= OpenMD::epsilon;
618 match = propertyValue != comparisonValue;
621 if (match) bs.bitsets_[
MOLECULE].setBitOn(mol->getGlobalIndex());
623 void SelectionEvaluator::compareProperty(StuntDouble* sd, SelectionSet& bs,
624 int property,
int comparator,
625 float comparisonValue,
int frame) {
626 RealType propertyValue = 0.0;
631 Atom* atom =
static_cast<Atom*
>(sd);
632 propertyValue = atom->getGlobalIndex();
636 propertyValue = sd->getMass();
640 Atom* atom =
static_cast<Atom*
>(sd);
641 propertyValue = getCharge(atom, frame);
642 }
else if (sd->isRigidBody()) {
643 RigidBody* rb =
static_cast<RigidBody*
>(sd);
644 RigidBody::AtomIterator ai;
646 for (atom = rb->beginAtom(ai); atom != NULL; atom = rb->nextAtom(ai)) {
647 propertyValue += getCharge(atom, frame);
652 propertyValue = sd->getPos(frame).x();
655 propertyValue = sd->getPos(frame).y();
658 propertyValue = sd->getPos(frame).z();
660 case Token::wrappedX:
661 pos = sd->getPos(frame);
662 info->getSnapshotManager()->getSnapshot(frame)->wrapVector(pos);
663 propertyValue = pos.x();
665 case Token::wrappedY:
666 pos = sd->getPos(frame);
667 info->getSnapshotManager()->getSnapshot(frame)->wrapVector(pos);
668 propertyValue = pos.y();
670 case Token::wrappedZ:
671 pos = sd->getPos(frame);
672 info->getSnapshotManager()->getSnapshot(frame)->wrapVector(pos);
673 propertyValue = pos.z();
677 propertyValue = sd->getPos(frame).length();
680 unrecognizedAtomProperty(property);
684 switch (comparator) {
686 match = propertyValue < comparisonValue;
689 match = propertyValue <= comparisonValue;
692 match = propertyValue >= comparisonValue;
695 match = propertyValue > comparisonValue;
698 match = fabs(propertyValue - comparisonValue) <= OpenMD::epsilon;
701 match = propertyValue != comparisonValue;
704 if (match) bs.bitsets_[
STUNTDOUBLE].setBitOn(sd->getGlobalIndex());
707 void SelectionEvaluator::withinInstruction(
const Token& instruction,
709 std::any withinSpec = instruction.value;
711 if (withinSpec.type() ==
typeid(
float)) {
712 distance = std::any_cast<float>(withinSpec);
713 }
else if (withinSpec.type() ==
typeid(
int)) {
714 distance = std::any_cast<int>(withinSpec);
716 evalError(
"casting error in withinInstruction");
720 bs = distanceFinder.find(bs, distance);
723 void SelectionEvaluator::withinInstruction(
const Token& instruction,
724 SelectionSet& bs,
int frame) {
725 std::any withinSpec = instruction.value;
727 if (withinSpec.type() ==
typeid(
float)) {
728 distance = std::any_cast<float>(withinSpec);
729 }
else if (withinSpec.type() ==
typeid(
int)) {
730 distance = std::any_cast<int>(withinSpec);
732 evalError(
"casting error in withinInstruction");
736 bs = distanceFinder.find(bs, distance, frame);
739 SelectionSet SelectionEvaluator::alphaHullInstruction(
740 const Token& instruction) {
741 SelectionSet bs = createSelectionSets();
743 std::any alphaSpec = instruction.value;
745 if (alphaSpec.type() ==
typeid(
float)) {
746 alpha = std::any_cast<float>(alphaSpec);
747 }
else if (alphaSpec.type() ==
typeid(
int)) {
748 alpha = std::any_cast<int>(alphaSpec);
750 evalError(
"casting error in alphaHullInstruction");
754 alphaHullFinder.setAlpha(alpha);
755 bs = alphaHullFinder.findHull();
756 surfaceArea_ = alphaHullFinder.getSurfaceArea();
757 hasSurfaceArea_ =
true;
758 volume_ = alphaHullFinder.getVolume();
761 return bs.parallelReduce();
764 SelectionSet SelectionEvaluator::alphaHullInstruction(
765 const Token& instruction,
int frame) {
766 SelectionSet bs = createSelectionSets();
768 std::any alphaSpec = instruction.value;
770 if (alphaSpec.type() ==
typeid(
float)) {
771 alpha = std::any_cast<float>(alphaSpec);
772 }
else if (alphaSpec.type() ==
typeid(
int)) {
773 alpha = std::any_cast<int>(alphaSpec);
775 evalError(
"casting error in alphaHullInstruction");
779 alphaHullFinder.setAlpha(alpha);
780 bs = alphaHullFinder.findHull(frame);
781 surfaceArea_ = alphaHullFinder.getSurfaceArea();
782 hasSurfaceArea_ =
true;
783 volume_ = alphaHullFinder.getVolume();
786 return bs.parallelReduce();
789 void SelectionEvaluator::define() {
790 assert(statement.size() >= 3);
792 std::string variable = std::any_cast<std::string>(statement[1].value);
795 VariablesType::value_type(variable, expression(statement, 2)));
799 void SelectionEvaluator::predefine(
const std::string& script) {
800 if (compiler.compile(
"#predefine", script)) {
801 std::vector<std::vector<Token>> aatoken = compiler.getAatokenCompiled();
802 if (aatoken.size() != 1) {
803 evalError(
"predefinition does not have exactly 1 command:" + script);
806 std::vector<Token> statement = aatoken[0];
807 if (statement.size() > 2) {
808 int tok = statement[1].tok;
809 if (tok == Token::identifier ||
810 (tok & Token::predefinedset) == Token::predefinedset) {
811 std::string variable = std::any_cast<std::string>(statement[1].value);
812 variables.insert(VariablesType::value_type(variable, statement));
815 evalError(
"invalid variable name:" + script);
818 evalError(
"bad predefinition length:" + script);
822 evalError(
"predefined set compile error:" + script +
823 "\ncompile error:" + compiler.getErrorMessage());
827 void SelectionEvaluator::select(SelectionSet& bs) {
828 bs = expression(statement, 1);
831 void SelectionEvaluator::select(SelectionSet& bs,
int frame) {
832 bs = expression(statement, 1, frame);
835 SelectionSet SelectionEvaluator::lookupValue(
const std::string& variable) {
836 SelectionSet bs = createSelectionSets();
837 std::map<std::string, std::any>::iterator i = variables.find(variable);
839 if (i != variables.end()) {
840 if (i->second.type() ==
typeid(SelectionSet)) {
841 return std::any_cast<SelectionSet>(i->second);
842 }
else if (i->second.type() ==
typeid(std::vector<Token>)) {
843 bs = expression(std::any_cast<std::vector<Token>>(i->second), 2);
845 return bs.parallelReduce();
848 unrecognizedIdentifier(variable);
851 return bs.parallelReduce();
854 SelectionSet SelectionEvaluator::nameInstruction(
const std::string& name) {
855 return nameFinder.match(name);
858 bool SelectionEvaluator::containDynamicToken(
859 const std::vector<Token>& tokens) {
860 std::vector<Token>::const_iterator i;
861 for (i = tokens.begin(); i != tokens.end(); ++i) {
862 if (i->tok & Token::dynamic) {
return true; }
868 void SelectionEvaluator::clearDefinitionsAndLoadPredefined() {
874 SelectionSet SelectionEvaluator::createSelectionSets() {
875 SelectionSet ss(nObjects);
879 SelectionSet SelectionEvaluator::evaluate() {
880 SelectionSet bs = createSelectionSets();
883 instructionDispatchLoop(bs);
885 return bs.parallelReduce();
888 SelectionSet SelectionEvaluator::evaluate(
int frame) {
889 SelectionSet bs = createSelectionSets();
892 instructionDispatchLoop(bs, frame);
894 return bs.parallelReduce();
897 SelectionSet SelectionEvaluator::indexInstruction(
const std::any& value) {
898 SelectionSet bs = createSelectionSets();
900 if (value.type() ==
typeid(
int)) {
901 int index = std::any_cast<int>(value);
903 index >=
static_cast<int>(bs.bitsets_[STUNTDOUBLE].size())) {
906 bs = indexFinder.find(index);
908 }
else if (value.type() ==
typeid(std::pair<int, int>)) {
909 std::pair<int, int> indexRange =
910 std::any_cast<std::pair<int, int>>(value);
911 assert(indexRange.first <= indexRange.second);
912 if (indexRange.first < 0 ||
914 static_cast<int>(bs.bitsets_[STUNTDOUBLE].size())) {
915 invalidIndexRange(indexRange);
917 bs = indexFinder.find(indexRange.first, indexRange.second);
921 return bs.parallelReduce();
924 SelectionSet SelectionEvaluator::allInstruction() {
925 SelectionSet ss = createSelectionSets();
927 SimInfo::MoleculeIterator mi;
928 Molecule::AtomIterator ai;
929 Molecule::RigidBodyIterator rbIter;
930 Molecule::BondIterator bondIter;
931 Molecule::BendIterator bendIter;
932 Molecule::TorsionIterator torsionIter;
933 Molecule::InversionIterator inversionIter;
941 Inversion* inversion;
945 for (mol = info->beginMolecule(mi); mol != NULL;
946 mol = info->nextMolecule(mi)) {
947 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
948 ss.bitsets_[
STUNTDOUBLE].setBitOn(atom->getGlobalIndex());
950 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
951 rb = mol->nextRigidBody(rbIter)) {
952 ss.bitsets_[
STUNTDOUBLE].setBitOn(rb->getGlobalIndex());
954 for (bond = mol->beginBond(bondIter); bond != NULL;
955 bond = mol->nextBond(bondIter)) {
956 ss.bitsets_[
BOND].setBitOn(bond->getGlobalIndex());
958 for (bend = mol->beginBend(bendIter); bend != NULL;
959 bend = mol->nextBend(bendIter)) {
960 ss.bitsets_[
BEND].setBitOn(bend->getGlobalIndex());
962 for (torsion = mol->beginTorsion(torsionIter); torsion != NULL;
963 torsion = mol->nextTorsion(torsionIter)) {
964 ss.bitsets_[
TORSION].setBitOn(torsion->getGlobalIndex());
966 for (inversion = mol->beginInversion(inversionIter); inversion != NULL;
967 inversion = mol->nextInversion(inversionIter)) {
968 ss.bitsets_[
INVERSION].setBitOn(inversion->getGlobalIndex());
970 ss.bitsets_[
MOLECULE].setBitOn(mol->getGlobalIndex());
976 SelectionSet SelectionEvaluator::hull() {
977 SelectionSet bs = createSelectionSets();
979 bs = hullFinder.findHull();
980 surfaceArea_ = hullFinder.getSurfaceArea();
981 hasSurfaceArea_ =
true;
982 volume_ = hullFinder.getVolume();
985 return bs.parallelReduce();
988 SelectionSet SelectionEvaluator::hull(
int frame) {
989 SelectionSet bs = createSelectionSets();
991 bs = hullFinder.findHull(frame);
993 return bs.parallelReduce();
996 RealType SelectionEvaluator::getCharge(Atom* atom) {
997 RealType charge = 0.0;
998 AtomType* atomType = atom->getAtomType();
1000 FixedChargeAdapter fca = FixedChargeAdapter(atomType);
1001 if (fca.isFixedCharge()) { charge = fca.getCharge(); }
1003 FluctuatingChargeAdapter fqa = FluctuatingChargeAdapter(atomType);
1004 if (fqa.isFluctuatingCharge()) { charge += atom->getFlucQPos(); }
1008 RealType SelectionEvaluator::getCharge(Atom* atom,
int frame) {
1009 RealType charge = 0.0;
1010 AtomType* atomType = atom->getAtomType();
1012 FixedChargeAdapter fca = FixedChargeAdapter(atomType);
1013 if (fca.isFixedCharge()) { charge = fca.getCharge(); }
1015 FluctuatingChargeAdapter fqa = FluctuatingChargeAdapter(atomType);
1016 if (fqa.isFluctuatingCharge()) { charge += atom->getFlucQPos(frame); }
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.
@ STUNTDOUBLE
StuntDoubles (Atoms & RigidBodies).
Real distance(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the distance between two DynamicVectors.