# | Line 1 | Line 1 | |
---|---|---|
1 | /* | |
2 | < | * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved. |
2 | > | * Copyright (c) 2009 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 | |
# | Line 38 | Line 38 | |
38 | * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 24107 (2008). | |
39 | * [4] Vardeman & Gezelter, in progress (2009). | |
40 | */ | |
41 | < | |
42 | < | #include "io/DumpReader.hpp" |
43 | < | #include "io/RestReader.hpp" |
44 | < | #include "primitives/Molecule.hpp" |
41 | > | |
42 | > | |
43 | > | #include <sys/types.h> |
44 | > | #include <sys/stat.h> |
45 | > | |
46 | > | #include <math.h> |
47 | > | #include <string> |
48 | > | #include <sstream> |
49 | > | #include <iostream> |
50 | > | #include <stdio.h> |
51 | > | #include <stdlib.h> |
52 | > | #include <string.h> |
53 | > | |
54 | > | #include "io/RestReader.hpp" |
55 | > | #include "primitives/Molecule.hpp" |
56 | > | #include "utils/simError.h" |
57 | > | #include "utils/MemoryUtils.hpp" |
58 | > | #include "utils/StringTokenizer.hpp" |
59 | #include "restraints/ObjectRestraint.hpp" | |
60 | < | #include "restraints/MolecularRestraint.hpp" |
60 | > | #include "restraints/MolecularRestraint.hpp" |
61 | > | |
62 | > | #ifdef IS_MPI |
63 | > | |
64 | > | #include <mpi.h> |
65 | > | #endif |
66 | ||
67 | namespace OpenMD { | |
68 | + | |
69 | + | void RestReader::scanFile(){ |
70 | + | int lineNo = 0; |
71 | + | std::streampos prevPos; |
72 | + | std::streampos currPos; |
73 | + | |
74 | + | #ifdef IS_MPI |
75 | + | |
76 | + | if (worldRank == 0) { |
77 | + | #endif // is_mpi |
78 | + | |
79 | + | inFile_->clear(); |
80 | + | currPos = inFile_->tellg(); |
81 | + | prevPos = currPos; |
82 | ||
83 | < | void RestReader::readReferenceStructure() { |
83 | > | bool foundOpenSnapshotTag = false; |
84 | > | |
85 | > | while(!foundOpenSnapshotTag && inFile_->getline(buffer, bufferSize)) { |
86 | > | ++lineNo; |
87 | > | |
88 | > | std::string line = buffer; |
89 | > | currPos = inFile_->tellg(); |
90 | > | if (line.find("<Snapshot>")!= std::string::npos) { |
91 | > | foundOpenSnapshotTag = true; |
92 | > | framePos_ = prevPos; |
93 | > | } |
94 | > | prevPos = currPos; |
95 | > | } |
96 | > | |
97 | > | #ifdef IS_MPI |
98 | > | } |
99 | > | MPI_Bcast(&framePos_, 1, MPI_INT, 0, MPI_COMM_WORLD); |
100 | > | #endif // is_mpi |
101 | > | } |
102 | ||
52 | – | // some of this comes directly from DumpReader. |
103 | ||
104 | < | if (!isScanned_) |
105 | < | scanFile(); |
106 | < | |
107 | < | int storageLayout = info_->getSnapshotManager()->getStorageLayout(); |
108 | < | |
109 | < | if (storageLayout & DataStorage::dslPosition) { |
110 | < | needPos_ = true; |
104 | > | void RestReader::readSet(){ |
105 | > | std::string line; |
106 | > | |
107 | > | #ifndef IS_MPI |
108 | > | |
109 | > | inFile_->clear(); |
110 | > | inFile_->seekg(framePos_); |
111 | > | |
112 | > | std::istream& inputStream = *inFile_; |
113 | > | #else |
114 | > | |
115 | > | int masterNode = 0; |
116 | > | std::stringstream sstream; |
117 | > | if (worldRank == masterNode) { |
118 | > | std::string sendBuffer; |
119 | > | |
120 | > | inFile_->clear(); |
121 | > | inFile_->seekg(framePos_); |
122 | > | |
123 | > | while (inFile_->getline(buffer, bufferSize)) { |
124 | > | |
125 | > | line = buffer; |
126 | > | sendBuffer += line; |
127 | > | sendBuffer += '\n'; |
128 | > | if (line.find("</Snapshot>") != std::string::npos) { |
129 | > | break; |
130 | > | } |
131 | > | } |
132 | > | |
133 | > | int sendBufferSize = sendBuffer.size(); |
134 | > | MPI_Bcast(&sendBufferSize, 1, MPI_INT, masterNode, MPI_COMM_WORLD); |
135 | > | MPI_Bcast((void *)sendBuffer.c_str(), sendBufferSize, MPI_CHAR, masterNode, MPI_COMM_WORLD); |
136 | > | |
137 | > | sstream.str(sendBuffer); |
138 | } else { | |
139 | < | needPos_ = false; |
139 | > | int sendBufferSize; |
140 | > | MPI_Bcast(&sendBufferSize, 1, MPI_INT, masterNode, MPI_COMM_WORLD); |
141 | > | char * recvBuffer = new char[sendBufferSize+1]; |
142 | > | assert(recvBuffer); |
143 | > | recvBuffer[sendBufferSize] = '\0'; |
144 | > | MPI_Bcast(recvBuffer, sendBufferSize, MPI_CHAR, masterNode, MPI_COMM_WORLD); |
145 | > | sstream.str(recvBuffer); |
146 | > | delete [] recvBuffer; |
147 | > | } |
148 | > | |
149 | > | std::istream& inputStream = sstream; |
150 | > | #endif |
151 | > | |
152 | > | inputStream.getline(buffer, bufferSize); |
153 | > | |
154 | > | line = buffer; |
155 | > | if (line.find("<Snapshot>") == std::string::npos) { |
156 | > | sprintf(painCave.errMsg, |
157 | > | "RestReader Error: can not find <Snapshot>\n"); |
158 | > | painCave.isFatal = 1; |
159 | > | simError(); |
160 | } | |
161 | < | |
162 | < | needVel_ = false; |
163 | < | |
164 | < | if (storageLayout & DataStorage::dslAmat || storageLayout & DataStorage::dslElectroFrame) { |
165 | < | needQuaternion_ = true; |
166 | < | } else { |
167 | < | needQuaternion_ = false; |
168 | < | } |
161 | > | |
162 | > | //read frameData |
163 | > | readFrameProperties(inputStream); |
164 | > | |
165 | > | //read StuntDoubles |
166 | > | readStuntDoubles(inputStream); |
167 | > | |
168 | > | inputStream.getline(buffer, bufferSize); |
169 | > | line = buffer; |
170 | > | if (line.find("</Snapshot>") == std::string::npos) { |
171 | > | sprintf(painCave.errMsg, |
172 | > | "RestReader Error: can not find </Snapshot>\n"); |
173 | > | painCave.isFatal = 1; |
174 | > | simError(); |
175 | > | } |
176 | > | } |
177 | > | |
178 | > | void RestReader::readReferenceStructure() { |
179 | ||
73 | – | needAngMom_ = false; |
74 | – | |
180 | // We need temporary storage to keep track of all StuntDouble positions | |
181 | // in case some of the restraints are molecular (i.e. if they use | |
182 | // multiple SD positions to determine restrained orientations or positions: | |
183 | ||
184 | all_pos_.clear(); | |
185 | < | all_pos_.resize(info_->getNGlobalIntegrableObjects() ); |
186 | < | |
82 | < | |
185 | > | all_pos_.resize(info_->getNGlobalIntegrableObjects()) ; |
186 | > | |
187 | // Restraint files are just standard dump files, but with the reference | |
188 | // structure stored in the first frame (frame 0). | |
189 | // RestReader overloads readSet and explicitly handles all of the | |
190 | // ObjectRestraints in that method: | |
191 | ||
192 | < | readSet(0); |
193 | < | |
192 | > | scanFile(); |
193 | > | |
194 | > | readSet(); |
195 | > | |
196 | > | |
197 | // all ObjectRestraints have been handled, now we have to worry about | |
198 | // molecular restraints: | |
199 | ||
# | Line 94 | Line 201 | namespace OpenMD { | |
201 | Molecule::IntegrableObjectIterator j; | |
202 | Molecule* mol; | |
203 | StuntDouble* sd; | |
204 | < | |
204 | > | |
205 | // no need to worry about parallel molecules, as molecules are not | |
206 | // split across processor boundaries. Just loop over all molecules | |
207 | // we know about: | |
208 | < | |
208 | > | |
209 | for (mol = info_->beginMolecule(i); mol != NULL; | |
210 | mol = info_->nextMolecule(i)) { | |
211 | < | |
211 | > | |
212 | // is this molecule restrained? | |
213 | GenericData* data = mol->getPropertyByName("Restraint"); | |
214 | ||
215 | if (data != NULL) { | |
216 | < | |
216 | > | |
217 | // make sure we can reinterpret the generic data as restraint data: | |
218 | < | |
218 | > | |
219 | RestraintData* restData= dynamic_cast<RestraintData*>(data); | |
220 | < | |
220 | > | |
221 | if (restData != NULL) { | |
222 | < | |
222 | > | |
223 | // make sure we can reinterpet the restraint data as a | |
224 | // pointer to a MolecularRestraint: | |
225 | < | |
225 | > | |
226 | MolecularRestraint* mRest = dynamic_cast<MolecularRestraint*>(restData->getData()); | |
227 | < | |
227 | > | |
228 | if (mRest != NULL) { | |
229 | < | |
229 | > | |
230 | // now we need to pack the stunt doubles for the reference | |
231 | // structure: | |
232 | < | |
232 | > | |
233 | std::vector<Vector3d> ref; | |
234 | int count = 0; | |
235 | RealType mass, mTot; | |
# | Line 140 | Line 247 | namespace OpenMD { | |
247 | // doubles from the *globally* sorted array of | |
248 | // positions: | |
249 | ||
250 | < | ref.push_back( all_pos_[sd->getGlobalIndex()] ); |
251 | < | |
145 | < | mass = sd->getMass(); |
146 | < | |
250 | > | ref.push_back( all_pos_[sd->getGlobalIntegrableObjectIndex()] ); |
251 | > | mass = sd->getMass(); |
252 | COM = COM + mass * ref[count]; | |
253 | mTot = mTot + mass; | |
254 | count = count + 1; | |
255 | } | |
151 | – | |
256 | COM /= mTot; | |
153 | – | |
257 | mRest->setReferenceStructure(ref, COM); | |
155 | – | |
258 | } | |
259 | } | |
260 | } | |
# | Line 162 | Line 264 | namespace OpenMD { | |
264 | ||
265 | ||
266 | void RestReader::parseDumpLine(const std::string& line) { | |
267 | + | |
268 | StringTokenizer tokenizer(line); | |
269 | int nTokens; | |
270 | ||
# | Line 169 | Line 272 | namespace OpenMD { | |
272 | ||
273 | if (nTokens < 2) { | |
274 | sprintf(painCave.errMsg, | |
275 | < | "DumpReader Error: Not enough Tokens.\n%s\n", line.c_str()); |
275 | > | "RestReader Error: Not enough Tokens.\n%s\n", line.c_str()); |
276 | painCave.isFatal = 1; | |
277 | simError(); | |
278 | } | |
279 | ||
280 | int index = tokenizer.nextTokenAsInt(); | |
281 | < | |
281 | > | |
282 | StuntDouble* integrableObject = info_->getIOIndexToIntegrableObject(index); | |
283 | ||
284 | if (integrableObject == NULL) { | |
285 | return; | |
286 | < | } |
287 | < | |
286 | > | } |
287 | > | |
288 | std::string type = tokenizer.nextToken(); | |
289 | int size = type.size(); | |
290 | + | |
291 | Vector3d pos; | |
188 | – | Vector3d vel; |
292 | Quat4d q; | |
293 | < | Vector3d ji; |
191 | < | Vector3d force; |
192 | < | Vector3d torque; |
193 | < | |
293 | > | |
294 | for(int i = 0; i < size; ++i) { | |
295 | switch(type[i]) { | |
196 | – | |
197 | – | case 'p': { |
198 | – | pos[0] = tokenizer.nextTokenAsDouble(); |
199 | – | pos[1] = tokenizer.nextTokenAsDouble(); |
200 | – | pos[2] = tokenizer.nextTokenAsDouble(); |
201 | – | break; |
202 | – | } |
203 | – | case 'v' : { |
204 | – | vel[0] = tokenizer.nextTokenAsDouble(); |
205 | – | vel[1] = tokenizer.nextTokenAsDouble(); |
206 | – | vel[2] = tokenizer.nextTokenAsDouble(); |
207 | – | break; |
208 | – | } |
296 | ||
297 | < | case 'q' : { |
298 | < | if (integrableObject->isDirectional()) { |
299 | < | |
300 | < | q[0] = tokenizer.nextTokenAsDouble(); |
301 | < | q[1] = tokenizer.nextTokenAsDouble(); |
302 | < | q[2] = tokenizer.nextTokenAsDouble(); |
303 | < | q[3] = tokenizer.nextTokenAsDouble(); |
304 | < | |
305 | < | RealType qlen = q.length(); |
306 | < | if (qlen < OpenMD::epsilon) { //check quaternion is not equal to 0 |
307 | < | |
308 | < | sprintf(painCave.errMsg, |
309 | < | "DumpReader Error: initial quaternion error (q0^2 + q1^2 + q2^2 + q3^2) ~ 0\n"); |
223 | < | painCave.isFatal = 1; |
224 | < | simError(); |
225 | < | |
226 | < | } |
227 | < | |
228 | < | q.normalize(); |
229 | < | } |
230 | < | break; |
231 | < | } |
232 | < | case 'j' : { |
233 | < | if (integrableObject->isDirectional()) { |
234 | < | ji[0] = tokenizer.nextTokenAsDouble(); |
235 | < | ji[1] = tokenizer.nextTokenAsDouble(); |
236 | < | ji[2] = tokenizer.nextTokenAsDouble(); |
237 | < | } |
238 | < | break; |
239 | < | } |
240 | < | case 'f': { |
241 | < | force[0] = tokenizer.nextTokenAsDouble(); |
242 | < | force[1] = tokenizer.nextTokenAsDouble(); |
243 | < | force[2] = tokenizer.nextTokenAsDouble(); |
297 | > | case 'p': { |
298 | > | pos[0] = tokenizer.nextTokenAsDouble(); |
299 | > | pos[1] = tokenizer.nextTokenAsDouble(); |
300 | > | pos[2] = tokenizer.nextTokenAsDouble(); |
301 | > | break; |
302 | > | } |
303 | > | case 'v' : { |
304 | > | Vector3d vel; |
305 | > | vel[0] = tokenizer.nextTokenAsDouble(); |
306 | > | vel[1] = tokenizer.nextTokenAsDouble(); |
307 | > | vel[2] = tokenizer.nextTokenAsDouble(); |
308 | > | break; |
309 | > | } |
310 | ||
311 | < | break; |
311 | > | case 'q' : { |
312 | > | if (integrableObject->isDirectional()) { |
313 | > | |
314 | > | q[0] = tokenizer.nextTokenAsDouble(); |
315 | > | q[1] = tokenizer.nextTokenAsDouble(); |
316 | > | q[2] = tokenizer.nextTokenAsDouble(); |
317 | > | q[3] = tokenizer.nextTokenAsDouble(); |
318 | > | |
319 | > | RealType qlen = q.length(); |
320 | > | if (qlen < OpenMD::epsilon) { //check quaternion is not equal to 0 |
321 | > | |
322 | > | sprintf(painCave.errMsg, |
323 | > | "RestReader Error: initial quaternion error (q0^2 + q1^2 + q2^2 + q3^2) ~ 0\n"); |
324 | > | painCave.isFatal = 1; |
325 | > | simError(); |
326 | > | } |
327 | > | |
328 | > | q.normalize(); |
329 | > | } |
330 | > | break; |
331 | > | } |
332 | > | case 'j' : { |
333 | > | Vector3d ji; |
334 | > | if (integrableObject->isDirectional()) { |
335 | > | ji[0] = tokenizer.nextTokenAsDouble(); |
336 | > | ji[1] = tokenizer.nextTokenAsDouble(); |
337 | > | ji[2] = tokenizer.nextTokenAsDouble(); |
338 | } | |
339 | < | case 't' : { |
340 | < | torque[0] = tokenizer.nextTokenAsDouble(); |
341 | < | torque[1] = tokenizer.nextTokenAsDouble(); |
342 | < | torque[2] = tokenizer.nextTokenAsDouble(); |
339 | > | break; |
340 | > | } |
341 | > | case 'f': { |
342 | > | Vector3d force; |
343 | > | force[0] = tokenizer.nextTokenAsDouble(); |
344 | > | force[1] = tokenizer.nextTokenAsDouble(); |
345 | > | force[2] = tokenizer.nextTokenAsDouble(); |
346 | > | break; |
347 | > | } |
348 | > | case 't' : { |
349 | > | Vector3d torque; |
350 | > | torque[0] = tokenizer.nextTokenAsDouble(); |
351 | > | torque[1] = tokenizer.nextTokenAsDouble(); |
352 | > | torque[2] = tokenizer.nextTokenAsDouble(); |
353 | > | break; |
354 | > | } |
355 | > | default: { |
356 | > | sprintf(painCave.errMsg, |
357 | > | "RestReader Error: %s is an unrecognized type\n", type.c_str()); |
358 | > | painCave.isFatal = 1; |
359 | > | simError(); |
360 | > | break; |
361 | > | } |
362 | > | } |
363 | > | // keep the position in case we need it for a molecular restraint: |
364 | ||
365 | < | break; |
365 | > | all_pos_[index] = pos; |
366 | > | |
367 | > | // is this io restrained? |
368 | > | GenericData* data = integrableObject->getPropertyByName("Restraint"); |
369 | > | ObjectRestraint* oRest; |
370 | > | |
371 | > | if (data != NULL) { |
372 | > | // make sure we can reinterpret the generic data as restraint data: |
373 | > | RestraintData* restData= dynamic_cast<RestraintData*>(data); |
374 | > | if (restData != NULL) { |
375 | > | // make sure we can reinterpet the restraint data as a pointer to |
376 | > | // an ObjectRestraint: |
377 | > | oRest = dynamic_cast<ObjectRestraint*>(restData->getData()); |
378 | > | if (oRest != NULL) { |
379 | > | if (integrableObject->isDirectional()) { |
380 | > | oRest->setReferenceStructure(pos, q.toRotationMatrix3()); |
381 | > | } else { |
382 | > | oRest->setReferenceStructure(pos); |
383 | > | } |
384 | > | } |
385 | } | |
254 | – | default: { |
255 | – | sprintf(painCave.errMsg, |
256 | – | "DumpReader Error: %s is an unrecognized type\n", type.c_str()); |
257 | – | painCave.isFatal = 1; |
258 | – | simError(); |
259 | – | break; |
260 | – | } |
261 | – | |
386 | } | |
387 | } | |
388 | < | |
389 | < | // keep the position in case we need it for a molecular restraint: |
388 | > | } |
389 | > | |
390 | > | void RestReader::readStuntDoubles(std::istream& inputStream) { |
391 | ||
392 | < | all_pos_[index] = pos; |
393 | < | |
394 | < | // is this io restrained? |
395 | < | GenericData* data = integrableObject->getPropertyByName("Restraint"); |
396 | < | ObjectRestraint* oRest; |
397 | < | |
398 | < | if (data != NULL) { |
399 | < | // make sure we can reinterpret the generic data as restraint data: |
400 | < | RestraintData* restData= dynamic_cast<RestraintData*>(data); |
401 | < | if (restData != NULL) { |
402 | < | // make sure we can reinterpet the restraint data as a pointer to |
403 | < | // an ObjectRestraint: |
404 | < | oRest = dynamic_cast<ObjectRestraint*>(restData->getData()); |
405 | < | if (oRest != NULL) { |
406 | < | if (integrableObject->isDirectional()) { |
282 | < | oRest->setReferenceStructure(pos, q.toRotationMatrix3()); |
283 | < | } else { |
284 | < | oRest->setReferenceStructure(pos); |
285 | < | } |
286 | < | } |
392 | > | inputStream.getline(buffer, bufferSize); |
393 | > | std::string line(buffer); |
394 | > | |
395 | > | if (line.find("<StuntDoubles>") == std::string::npos) { |
396 | > | sprintf(painCave.errMsg, |
397 | > | "RestReader Error: Missing <StuntDoubles>\n"); |
398 | > | painCave.isFatal = 1; |
399 | > | simError(); |
400 | > | } |
401 | > | |
402 | > | while(inputStream.getline(buffer, bufferSize)) { |
403 | > | line = buffer; |
404 | > | |
405 | > | if(line.find("</StuntDoubles>") != std::string::npos) { |
406 | > | break; |
407 | } | |
408 | + | |
409 | + | parseDumpLine(line); |
410 | } | |
411 | < | |
411 | > | |
412 | } | |
291 | – | |
413 | ||
414 | < | |
414 | > | |
415 | void RestReader::readFrameProperties(std::istream& inputStream) { | |
416 | inputStream.getline(buffer, bufferSize); | |
417 | std::string line(buffer); | |
418 | ||
419 | if (line.find("<FrameData>") == std::string::npos) { | |
420 | sprintf(painCave.errMsg, | |
421 | < | "DumpReader Error: Missing <FrameData>\n"); |
421 | > | "RestReader Error: Missing <FrameData>\n"); |
422 | painCave.isFatal = 1; | |
423 | simError(); | |
424 | } | |
# | Line 314 | Line 435 | namespace OpenMD { | |
435 | } | |
436 | ||
437 | } | |
438 | < | |
438 | > | |
439 | } | |
440 | ||
441 |
– | Removed lines |
+ | Added lines |
< | Changed lines |
> | Changed lines |