ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/selection/SelectionEvaluator.cpp
Revision: 1360
Committed: Mon Sep 7 16:31:51 2009 UTC (15 years, 7 months ago) by cli2
File size: 13337 byte(s)
Log Message:
Added new restraint infrastructure
Added MolecularRestraints
Added ObjectRestraints
Added RestraintStamp
Updated thermodynamic integration to use ObjectRestraints
Added Quaternion mathematics for twist swing decompositions
Significantly updated RestWriter and RestReader to use dump-like files
Added selections for x, y, and z coordinates of atoms
Removed monolithic Restraints class
Fixed a few bugs in gradients of Euler angles in DirectionalAtom and RigidBody
Added some rotational capabilities to prinicpalAxisCalculator

File Contents

# Content
1 /*
2 * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3 *
4 * The University of Notre Dame grants you ("Licensee") a
5 * non-exclusive, royalty free, license to use, modify and
6 * redistribute this software in source and binary code form, provided
7 * that the following conditions are met:
8 *
9 * 1. Acknowledgement of the program authors must be made in any
10 * publication of scientific results based in part on use of the
11 * program. An acceptable form of acknowledgement is citation of
12 * the article in which the program was described (Matthew
13 * A. Meineke, Charles F. Vardeman II, Teng Lin, Christopher
14 * J. Fennell and J. Daniel Gezelter, "OOPSE: An Object-Oriented
15 * Parallel Simulation Engine for Molecular Dynamics,"
16 * J. Comput. Chem. 26, pp. 252-271 (2005))
17 *
18 * 2. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * 3. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the
24 * distribution.
25 *
26 * This software is provided "AS IS," without a warranty of any
27 * kind. All express or implied conditions, representations and
28 * warranties, including any implied warranty of merchantability,
29 * fitness for a particular purpose or non-infringement, are hereby
30 * excluded. The University of Notre Dame and its licensors shall not
31 * be liable for any damages suffered by licensee as a result of
32 * using, modifying or distributing the software or its
33 * derivatives. In no event will the University of Notre Dame or its
34 * licensors be liable for any lost revenue, profit or data, or for
35 * direct, indirect, special, consequential, incidental or punitive
36 * damages, however caused and regardless of the theory of liability,
37 * arising out of the use of or inability to use software, even if the
38 * University of Notre Dame has been advised of the possibility of
39 * such damages.
40 */
41
42 #include <stack>
43 #include "selection/SelectionEvaluator.hpp"
44 #include "primitives/Atom.hpp"
45 #include "primitives/DirectionalAtom.hpp"
46 #include "primitives/RigidBody.hpp"
47 #include "primitives/Molecule.hpp"
48
49 namespace oopse {
50
51
52 SelectionEvaluator::SelectionEvaluator(SimInfo* si)
53 : info(si), nameFinder(info), distanceFinder(info), indexFinder(info), isLoaded_(false){
54
55 nStuntDouble = info->getNGlobalAtoms() + info->getNRigidBodies();
56 }
57
58 bool SelectionEvaluator::loadScript(const std::string& filename, const std::string& script) {
59 clearDefinitionsAndLoadPredefined();
60 this->filename = filename;
61 this->script = script;
62 if (! compiler.compile(filename, script)) {
63 error = true;
64 errorMessage = compiler.getErrorMessage();
65 std::cerr << "SelectionCompiler Error: " << errorMessage << std::endl;
66 return false;
67 }
68
69 pc = 0;
70 aatoken = compiler.getAatokenCompiled();
71 linenumbers = compiler.getLineNumbers();
72 lineIndices = compiler.getLineIndices();
73
74 std::vector<std::vector<Token> >::const_iterator i;
75
76 isDynamic_ = false;
77 for (i = aatoken.begin(); i != aatoken.end(); ++i) {
78 if (containDynamicToken(*i)) {
79 isDynamic_ = true;
80 break;
81 }
82 }
83
84 isLoaded_ = true;
85 return true;
86 }
87
88 void SelectionEvaluator::clearState() {
89 error = false;
90 errorMessage = "";
91 }
92
93 bool SelectionEvaluator::loadScriptString(const std::string& script) {
94 clearState();
95 return loadScript("", script);
96 }
97
98 bool SelectionEvaluator::loadScriptFile(const std::string& filename) {
99 clearState();
100 return loadScriptFileInternal(filename);
101 }
102
103 bool SelectionEvaluator::loadScriptFileInternal(const std::string & filename) {
104 std::ifstream ifs(filename.c_str());
105 if (!ifs.is_open()) {
106 return false;
107 }
108
109 const int bufferSize = 65535;
110 char buffer[bufferSize];
111 std::string script;
112 while(ifs.getline(buffer, bufferSize)) {
113 script += buffer;
114 }
115 return loadScript(filename, script);
116 }
117
118 void SelectionEvaluator::instructionDispatchLoop(OOPSEBitSet& bs){
119
120 while ( pc < aatoken.size()) {
121 statement = aatoken[pc++];
122 statementLength = statement.size();
123 Token token = statement[0];
124 switch (token.tok) {
125 case Token::define:
126 define();
127 break;
128 case Token::select:
129 select(bs);
130 break;
131 default:
132 unrecognizedCommand(token);
133 return;
134 }
135 }
136
137 }
138
139 OOPSEBitSet SelectionEvaluator::expression(const std::vector<Token>& code, int pcStart) {
140 OOPSEBitSet bs;
141 std::stack<OOPSEBitSet> stack;
142
143 for (int pc = pcStart; pc < code.size(); ++pc) {
144 Token instruction = code[pc];
145
146 switch (instruction.tok) {
147 case Token::expressionBegin:
148 break;
149 case Token::expressionEnd:
150 break;
151 case Token::all:
152 bs = OOPSEBitSet(nStuntDouble);
153 bs.setAll();
154 stack.push(bs);
155 break;
156 case Token::none:
157 bs = OOPSEBitSet(nStuntDouble);
158 stack.push(bs);
159 break;
160 case Token::opOr:
161 bs = stack.top();
162 stack.pop();
163 stack.top() |= bs;
164 break;
165 case Token::opAnd:
166 bs = stack.top();
167 stack.pop();
168 stack.top() &= bs;
169 break;
170 case Token::opNot:
171 stack.top().flip();
172 break;
173 case Token::within:
174
175 withinInstruction(instruction, stack.top());
176 break;
177 //case Token::selected:
178 // stack.push(getSelectionSet());
179 // break;
180 case Token::name:
181 stack.push(nameInstruction(boost::any_cast<std::string>(instruction.value)));
182 break;
183 case Token::index:
184 stack.push(indexInstruction(instruction.value));
185 break;
186 case Token::identifier:
187 stack.push(lookupValue(boost::any_cast<std::string>(instruction.value)));
188 break;
189 case Token::opLT:
190 case Token::opLE:
191 case Token::opGE:
192 case Token::opGT:
193 case Token::opEQ:
194 case Token::opNE:
195 stack.push(comparatorInstruction(instruction));
196 break;
197 default:
198 unrecognizedExpression();
199 }
200 }
201 if (stack.size() != 1)
202 evalError("atom expression compiler error - stack over/underflow");
203
204 return stack.top();
205 }
206
207
208
209 OOPSEBitSet SelectionEvaluator::comparatorInstruction(const Token& instruction) {
210 int comparator = instruction.tok;
211 int property = instruction.intValue;
212 float comparisonValue = boost::any_cast<float>(instruction.value);
213 float propertyValue;
214 OOPSEBitSet bs(nStuntDouble);
215 bs.clearAll();
216
217 SimInfo::MoleculeIterator mi;
218 Molecule* mol;
219 Molecule::AtomIterator ai;
220 Atom* atom;
221 Molecule::RigidBodyIterator rbIter;
222 RigidBody* rb;
223
224 for (mol = info->beginMolecule(mi); mol != NULL; mol = info->nextMolecule(mi)) {
225
226 for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
227 compareProperty(atom, bs, property, comparator, comparisonValue);
228 }
229
230 for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
231 compareProperty(rb, bs, property, comparator, comparisonValue);
232 }
233 }
234
235 return bs;
236 }
237
238 void SelectionEvaluator::compareProperty(StuntDouble* sd, OOPSEBitSet& bs, int property, int comparator, float comparisonValue) {
239 RealType propertyValue = 0.0;
240 switch (property) {
241 case Token::mass:
242 propertyValue = sd->getMass();
243 break;
244 case Token::charge:
245 if (sd->isAtom()){
246 Atom* atom = static_cast<Atom*>(sd);
247 propertyValue = getCharge(atom);
248 } else if (sd->isRigidBody()) {
249 RigidBody* rb = static_cast<RigidBody*>(sd);
250 RigidBody::AtomIterator ai;
251 Atom* atom;
252 for (atom = rb->beginAtom(ai); atom != NULL; atom = rb->nextAtom(ai)) {
253 propertyValue+= getCharge(atom);
254 }
255 }
256 break;
257 case Token::x:
258 propertyValue = sd->getPos().x();
259 break;
260 case Token::y:
261 propertyValue = sd->getPos().y();
262 break;
263 case Token::z:
264 propertyValue = sd->getPos().z();
265 break;
266 default:
267 unrecognizedAtomProperty(property);
268 }
269
270 bool match = false;
271 switch (comparator) {
272 case Token::opLT:
273 match = propertyValue < comparisonValue;
274 break;
275 case Token::opLE:
276 match = propertyValue <= comparisonValue;
277 break;
278 case Token::opGE:
279 match = propertyValue >= comparisonValue;
280 break;
281 case Token::opGT:
282 match = propertyValue > comparisonValue;
283 break;
284 case Token::opEQ:
285 match = propertyValue == comparisonValue;
286 break;
287 case Token::opNE:
288 match = propertyValue != comparisonValue;
289 break;
290 }
291 if (match)
292 bs.setBitOn(sd->getGlobalIndex());
293
294 }
295
296 void SelectionEvaluator::withinInstruction(const Token& instruction, OOPSEBitSet& bs){
297
298 boost::any withinSpec = instruction.value;
299 float distance;
300 if (withinSpec.type() == typeid(float)){
301 distance = boost::any_cast<float>(withinSpec);
302 } else if (withinSpec.type() == typeid(int)) {
303 distance = boost::any_cast<int>(withinSpec);
304 } else {
305 evalError("casting error in withinInstruction");
306 bs.clearAll();
307 }
308
309 bs = distanceFinder.find(bs, distance);
310 }
311
312 void SelectionEvaluator::define() {
313 assert(statement.size() >= 3);
314
315 std::string variable = boost::any_cast<std::string>(statement[1].value);
316
317 variables.insert(VariablesType::value_type(variable, expression(statement, 2)));
318 }
319
320
321 /** @todo */
322 void SelectionEvaluator::predefine(const std::string& script) {
323
324 if (compiler.compile("#predefine", script)) {
325 std::vector<std::vector<Token> > aatoken = compiler.getAatokenCompiled();
326 if (aatoken.size() != 1) {
327 evalError("predefinition does not have exactly 1 command:"
328 + script);
329 return;
330 }
331 std::vector<Token> statement = aatoken[0];
332 if (statement.size() > 2) {
333 int tok = statement[1].tok;
334 if (tok == Token::identifier || (tok & Token::predefinedset) == Token::predefinedset) {
335 std::string variable = boost::any_cast<std::string>(statement[1].value);
336 variables.insert(VariablesType::value_type(variable, statement));
337
338 } else {
339 evalError("invalid variable name:" + script);
340 }
341 }else {
342 evalError("bad predefinition length:" + script);
343 }
344
345
346 } else {
347 evalError("predefined set compile error:" + script +
348 "\ncompile error:" + compiler.getErrorMessage());
349 }
350
351 }
352
353 void SelectionEvaluator::select(OOPSEBitSet& bs){
354 bs = expression(statement, 1);
355 }
356
357 OOPSEBitSet SelectionEvaluator::lookupValue(const std::string& variable){
358
359 OOPSEBitSet bs(nStuntDouble);
360 std::map<std::string, boost::any>::iterator i = variables.find(variable);
361
362 if (i != variables.end()) {
363 if (i->second.type() == typeid(OOPSEBitSet)) {
364 return boost::any_cast<OOPSEBitSet>(i->second);
365 } else if (i->second.type() == typeid(std::vector<Token>)){
366 bs = expression(boost::any_cast<std::vector<Token> >(i->second), 2);
367 i->second = bs; /**@todo fixme */
368 return bs;
369 }
370 } else {
371 unrecognizedIdentifier(variable);
372 }
373
374 return bs;
375 }
376
377 OOPSEBitSet SelectionEvaluator::nameInstruction(const std::string& name){
378
379 return nameFinder.match(name);
380
381 }
382
383 bool SelectionEvaluator::containDynamicToken(const std::vector<Token>& tokens){
384 std::vector<Token>::const_iterator i;
385 for (i = tokens.begin(); i != tokens.end(); ++i) {
386 if (i->tok & Token::dynamic) {
387 return true;
388 }
389 }
390
391 return false;
392 }
393
394 void SelectionEvaluator::clearDefinitionsAndLoadPredefined() {
395 variables.clear();
396 //load predefine
397 //predefine();
398 }
399
400 OOPSEBitSet SelectionEvaluator::evaluate() {
401 OOPSEBitSet bs(nStuntDouble);
402 if (isLoaded_) {
403 pc = 0;
404 instructionDispatchLoop(bs);
405 }
406
407 return bs;
408 }
409
410 OOPSEBitSet SelectionEvaluator::indexInstruction(const boost::any& value) {
411 OOPSEBitSet bs(nStuntDouble);
412
413 if (value.type() == typeid(int)) {
414 int index = boost::any_cast<int>(value);
415 if (index < 0 || index >= bs.size()) {
416 invalidIndex(index);
417 } else {
418 bs = indexFinder.find(index);
419 }
420 } else if (value.type() == typeid(std::pair<int, int>)) {
421 std::pair<int, int> indexRange= boost::any_cast<std::pair<int, int> >(value);
422 assert(indexRange.first <= indexRange.second);
423 if (indexRange.first < 0 || indexRange.second >= bs.size()) {
424 invalidIndexRange(indexRange);
425 }else {
426 bs = indexFinder.find(indexRange.first, indexRange.second);
427 }
428 }
429
430 return bs;
431 }
432
433
434 RealType SelectionEvaluator::getCharge(Atom* atom) {
435 RealType charge =0.0;
436 AtomType* atomType = atom->getAtomType();
437 if (atomType->isCharge()) {
438 GenericData* data = atomType->getPropertyByName("Charge");
439 if (data != NULL) {
440 DoubleGenericData* doubleData= dynamic_cast<DoubleGenericData*>(data);
441
442 if (doubleData != NULL) {
443 charge = doubleData->getData();
444
445 } else {
446 sprintf( painCave.errMsg,
447 "Can not cast GenericData to DoubleGenericData\n");
448 painCave.severity = OOPSE_ERROR;
449 painCave.isFatal = 1;
450 simError();
451 }
452 }
453 }
454
455 return charge;
456 }
457
458 }