OpenMPCD
VTFSnapshotFile.cpp
2 
4 #include <OpenMPCD/Types.hpp>
5 
6 #include <boost/filesystem/fstream.hpp>
7 #include <boost/filesystem/operations.hpp>
8 #include <boost/lexical_cast.hpp>
9 #include <boost/regex.hpp>
10 #include <boost/tokenizer.hpp>
11 
12 #include <iomanip> // std::setprecision
13 #include <limits>
14 #include <sstream>
15 #include <iostream>
16 
17 using namespace OpenMPCD;
18 
19 VTFSnapshotFile::VTFSnapshotFile(const std::string& path)
20  : structureBlockProcessed(false),
21  primarySimulationVolumeSizeSet(false),
22  primarySimulationVolumeSize(0, 0, 0)
23 {
24  std::ios_base::openmode openmode;
25 
26  if(boost::filesystem::is_regular_file(path))
27  {
28  writeModeFlag = false;
29  openmode = std::ios_base::in;
30  }
31  else
32  {
33  writeModeFlag = true;
34  openmode = std::ios_base::out;
35 
36  (boost::filesystem::ofstream(path)); //create file
37  }
38 
39  file.open(path.c_str(), openmode);
40 
41  if(file.fail())
42  {
43  std::string msg = "Failed to open snapshot file: ";
44  msg += path;
45 
47  }
48 
49  if(isInWriteMode())
50  {
51  file.precision(std::numeric_limits<FP>::digits10 + 2);
52  }
53  else
54  {
55  readStructureBlock();
56  }
57 }
58 
60 {
61  if(isInWriteMode() && !structureBlockProcessed)
62  writeStructureBlock();
63 }
64 
66  const FP& x, const FP& y, const FP& z)
67 {
68  assertWriteMode();
69  assertStructureBlockNotProcessed();
70 
71  primarySimulationVolumeSize.setX(x);
72  primarySimulationVolumeSize.setY(y);
73  primarySimulationVolumeSize.setZ(z);
74 
75  primarySimulationVolumeSizeSet = true;
76 }
77 
78 const std::pair<std::size_t, std::size_t>
79 VTFSnapshotFile::declareAtoms(const std::size_t count)
80 {
81  assertWriteMode();
82  assertStructureBlockNotProcessed();
83 
84  if(count == 0)
85  return std::pair<std::size_t, std::size_t>(0, 0);
86 
87  AtomRange range;
88  range.first = getNumberOfAtoms();
89  range.last = range.first + count - 1;
90  range.properties = defaultAtomProperties;
91 
92  atomRanges.push_back(range);
93 
94  return std::make_pair(range.first, range.last);
95 }
96 
97 const std::pair<std::size_t, std::size_t>
99  const std::size_t count, const FP radius,
100  const std::string& name, const std::string& type)
101 {
102  assertWriteMode();
103  assertStructureBlockNotProcessed();
104 
105  if(count == 0)
106  return std::pair<std::size_t, std::size_t>(0, 0);
107 
108  if(radius < 0 && radius != -1)
109  OPENMPCD_THROW(InvalidArgumentException, "Invalid radius given");
110 
111  if(name.size() > 16)
112  OPENMPCD_THROW(InvalidArgumentException, "`name` too long");
113 
114  if(type.size() > 16)
115  OPENMPCD_THROW(InvalidArgumentException, "`type` too long");
116 
117  AtomRange range;
118 
119  range.first = getNumberOfAtoms();
120  range.last = range.first + count - 1;
121  range.properties = defaultAtomProperties;
122 
123  if(radius != -1)
124  range.properties.radius = radius;
125 
126  if(!name.empty())
127  range.properties.name = name;
128 
129  if(!type.empty())
130  range.properties.type = type;
131 
132  atomRanges.push_back(range);
133 
134  return std::make_pair(range.first, range.last);
135 }
136 
138  VTFSnapshotFile::getAtomProperties(const std::size_t atomID) const
139 {
140  typedef std::list<AtomRange>::const_iterator It;
141  for(It it = atomRanges.begin(); it != atomRanges.end(); ++it)
142  {
143  if(atomID > it->last)
144  continue;
145 
146  return it->properties;
147  }
148 
149  OPENMPCD_THROW(OutOfBoundsException, "Invalid atom ID given.");
150 }
151 
152 void VTFSnapshotFile::declareBond(std::size_t atom1, std::size_t atom2)
153 {
154  assertWriteMode();
155  assertStructureBlockNotProcessed();
156 
157  if(!isValidAtomID(atom1) || !isValidAtomID(atom2))
158  OPENMPCD_THROW(OutOfBoundsException, "Invalid atom ID given.");
159 
160  if(atom1 == atom2)
161  OPENMPCD_THROW(InvalidArgumentException, "atom1 == atom2");
162 
163  if(atom2 < atom1)
164  std::swap(atom1, atom2);
165 
166  const std::pair<std::size_t, std::size_t> bond(atom1, atom2);
167 
168  if(bonds.count(bond))
169  OPENMPCD_THROW(InvalidArgumentException, "Bond declared already.");
170 
171  bonds.insert(bond);
172 }
173 
174 bool VTFSnapshotFile::hasBond(std::size_t atom1, std::size_t atom2) const
175 {
176  if(!isValidAtomID(atom1) || !isValidAtomID(atom2))
177  OPENMPCD_THROW(OutOfBoundsException, "Invalid atom ID given.");
178 
179  if(atom1 == atom2)
180  OPENMPCD_THROW(InvalidArgumentException, "atom1 == atom2");
181 
182  if(atom2 < atom1)
183  std::swap(atom1, atom2);
184 
185  const std::pair<std::size_t, std::size_t> bond(atom1, atom2);
186 
187  return bonds.count(bond);
188 }
189 
191  const FP* const positions, const FP* const velocities)
192 {
193  assertWriteMode();
194 
195  if(!structureBlockProcessed)
196  writeStructureBlock();
197 
198  if(!positions)
199  OPENMPCD_THROW(NULLPointerException, "positions");
200 
201  file << "timestep\n";
202 
203  for(std::size_t i=0; i<getNumberOfAtoms(); ++i)
204  {
205  file << positions[3*i + 0] << " ";
206  file << positions[3*i + 1] << " ";
207  file << positions[3*i + 2];
208 
209  if(velocities)
210  {
211  file << " " << velocities[3*i + 0];
212  file << " " << velocities[3*i + 1];
213  file << " " << velocities[3*i + 2];
214  }
215 
216  file << "\n";
217  }
218 }
219 
221  FP* const positions,
222  FP* const velocities,
223  bool* const velocitiesEncountered)
224 {
225  assertReadMode();
226 
227  const boost::char_separator<char> separator(" \t");
228  typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
229  typedef Tokenizer::iterator TokenIt;
230 
231  {
232  std::string line;
233  do
234  {
235  if(file.eof())
236  return false;
237  line = getLine(true);
238  } while(line.empty());
239 
240  Tokenizer tokenizer(line, separator);
241 
242  TokenIt it = tokenizer.begin();
243  const std::string firstToken = *it;
244  ++it;
245 
246  if( firstToken == "t" || firstToken == "timestep" ||
247  firstToken == "c" || firstToken == "coordinates")
248  {
249  if(it != tokenizer.end())
250  {
251  const std::string secondToken = *it;
252  ++it;
253 
254  if(it != tokenizer.end())
255  OPENMPCD_THROW(MalformedFileException, "Too many tokens.");
256 
257  if(secondToken == "i" || secondToken == "indexed")
260  "Only ordered timestep blocks are supported.");
261 
262  if(secondToken != "o" && secondToken != "ordered")
263  OPENMPCD_THROW(MalformedFileException, "Bad second token.");
264  }
265  }
266  }
267 
268  if(getNumberOfAtoms() == 0)
269  return true;
270 
271  bool lineWithVelocitiesEncountered = false;
272  bool lineWithoutVelocitiesEncountered = false;
273  std::size_t atom = 0;
274  while(atom < getNumberOfAtoms())
275  {
276  if(file.eof())
277  break;
278 
279  const std::string line = getLine(true);
280 
281  if(line.empty())
282  continue;
283 
284  Tokenizer tokenizer(line, separator);
285 
286  unsigned int token = 0;
287  for(TokenIt it = tokenizer.begin(); it != tokenizer.end(); ++it)
288  {
289  if(token < 3 && positions)
290  positions[3 * atom + token] = lexicalCast<FP>(*it);
291 
292  if(token >= 3 && token < 6 && velocities)
293  velocities[3 * atom + token - 3] = lexicalCast<FP>(*it);
294 
295  ++token;
296  }
297 
298  if(token == 3)
299  {
300  lineWithoutVelocitiesEncountered = true;
301  }
302  else if(token == 6)
303  {
304  lineWithVelocitiesEncountered = true;
305  }
306  else
307  {
308  OPENMPCD_THROW(MalformedFileException, "Bad number of positions.");
309  }
310 
311  ++atom;
312  }
313 
314  if(velocitiesEncountered)
315  *velocitiesEncountered = lineWithVelocitiesEncountered;
316 
317  if(atom == 0)
318  return false;
319 
320  if(lineWithVelocitiesEncountered && lineWithoutVelocitiesEncountered)
321  {
324  "Some lines contained velocity information, while others did not.");
325  }
326 
327  if(atom != getNumberOfAtoms())
328  OPENMPCD_THROW(MalformedFileException, "Incomplete timestep block.");
329 
330  return true;
331 }
332 
333 void VTFSnapshotFile::assertWriteMode() const
334 {
335  if(!isInWriteMode())
338  "Tried to change snapshot in read mode.");
339 }
340 
341 void VTFSnapshotFile::assertReadMode() const
342 {
343  if(!isInReadMode())
346  "Instance is not in read mode.");
347 }
348 
349 void VTFSnapshotFile::assertStructureBlockNotProcessed() const
350 {
351  if(structureBlockProcessed)
354  "The structure block has been processed already.");
355 }
356 
357 void VTFSnapshotFile::writeStructureBlock()
358 {
359  assertWriteMode();
360  assertStructureBlockNotProcessed();
361 
363  {
364  file << "pbc ";
365  file << primarySimulationVolumeSize.getX() << " ";
366  file << primarySimulationVolumeSize.getY() << " ";
367  file << primarySimulationVolumeSize.getZ() << "\n";
368  }
369 
370  writeAtomLines();
371 
372  writeBondLines();
373 
374  structureBlockProcessed = true;
375 }
376 
377 void VTFSnapshotFile::readStructureBlock()
378 {
379  assertReadMode();
380  assertStructureBlockNotProcessed();
381 
382  while(file.good())
383  {
384  const std::string line = getLine(false);
385 
386  if(line.empty())
387  {
388  //empty line; do nothing
389  }
390  else if(line[0] == '#')
391  {
392  //comment line; do nothing
393  }
394  else if(line[0] == 'b')
395  {
396  readBondLine(line);
397  }
398  else if(line[0] == 'p' || line[0] == 'u')
399  {
400  readUnitcellLine(line);
401  }
402  else if(
403  line[0] == 't' || line[0] == 'c' ||
404  line[0] == 'i' || line[0] == 'o')
405  {
406  //timestep line; do not extract it from the file stream,
407  //and stop reading structure block
408  break;
409  }
410  else
411  {
412  readAtomLine(line);
413  }
414 
415  getLine(true); //consume line from input stream
416  }
417 
418  structureBlockProcessed = true;
419 }
420 
421 void VTFSnapshotFile::readUnitcellLine(const std::string& line)
422 {
423  assertReadMode();
424  assertStructureBlockNotProcessed();
425 
426  //start of the line contains the line type indicator
427  std::string regexString = "(?:(?:p|pbc)|(?:u|unitcell))";
428 
429  //then, three numbers follow: a, b, and c
430  for(unsigned int i=0; i<3; ++i)
431  regexString += "\\s+(\\S+)";
432 
433  //then, another three numbers may follow: alpha, beta, and gamma
434  regexString += "(?:";
435  for(unsigned int i=0; i<3; ++i)
436  regexString += "\\s+(\\S+)";
437  regexString += ")?";
438 
439  //end of string may contain whitespace
440  regexString+= "\\s*";
441 
442  const boost::regex re(regexString);
443  boost::cmatch captures;
444 
445  if(!boost::regex_match(line.c_str(), captures, re))
446  OPENMPCD_THROW(MalformedFileException, "Malformed line:\n" + line);
447 
448  OPENMPCD_DEBUG_ASSERT(captures.size() == 1 + 6);
449  OPENMPCD_DEBUG_ASSERT(captures[1].matched);
450  OPENMPCD_DEBUG_ASSERT(captures[2].matched);
451  OPENMPCD_DEBUG_ASSERT(captures[3].matched);
452 
453  primarySimulationVolumeSize.setX(lexicalCast<FP>(captures.str(1)));
454  primarySimulationVolumeSize.setY(lexicalCast<FP>(captures.str(2)));
455  primarySimulationVolumeSize.setZ(lexicalCast<FP>(captures.str(3)));
456 
457  primarySimulationVolumeSizeSet = true;
458 }
459 
460 void VTFSnapshotFile::writeAtomLines()
461 {
462  assertWriteMode();
463  assertStructureBlockNotProcessed();
464 
465  typedef std::list<AtomRange>::const_iterator It;
466  for(It it = atomRanges.begin(); it != atomRanges.end(); ++it)
467  {
468  file << "atom " << it->first;
469  if(it->first != it->last)
470  file << ":" << it->last;
471 
472  if(it->properties.name.is_initialized())
473  file << " name " << it->properties.name.get();
474 
475  if(it->properties.type.is_initialized())
476  file << " type " << it->properties.type.get();
477 
478  if(it->properties.radius.is_initialized())
479  file << " radius " << it->properties.radius.get();
480 
481  file << "\n";
482  }
483 }
484 
485 void VTFSnapshotFile::readAtomLine(const std::string& line_)
486 {
487  assertReadMode();
488  assertStructureBlockNotProcessed();
489 
490  const boost::regex commaRegex("\\s*,\\s*");
491  const std::string line = boost::regex_replace(line_, commaRegex, ", ");
492 
493  const boost::char_separator<char> separator(" \t");
494  typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
495  Tokenizer tokenizer(line, separator);
496 
497  const boost::regex aidRegex("([0-9]+)(?::([0-9]+))?(,)?");
498  const boost::regex aidDefaultRegex("default(,)?");
499 
500  AtomProperties properties = defaultAtomProperties;
501  std::vector<std::pair<std::size_t, std::size_t> > newRanges;
502  std::string optionName;
503  bool isNewDefault = false;
504  bool expectAID = true;
505  for(Tokenizer::iterator it = tokenizer.begin(); it != tokenizer.end(); ++it)
506  {
507  if(it == tokenizer.begin() && (*it == "a" || *it == "atom"))
508  continue;
509 
510  using boost::regex_match;
511 
512  boost::cmatch capturesDefault;
513  if(expectAID &&
514  regex_match(it->c_str(), capturesDefault, aidDefaultRegex))
515  {
516  OPENMPCD_DEBUG_ASSERT(capturesDefault.size() == 1 + 1);
517 
518  if(!capturesDefault[1].matched)
519  expectAID = false;
520 
521  isNewDefault = true;
522 
523  continue;
524  }
525 
526  boost::cmatch captures;
527  if(expectAID && regex_match(it->c_str(), captures, aidRegex))
528  {
529  OPENMPCD_DEBUG_ASSERT(captures.size() == 1 + 3);
530  OPENMPCD_DEBUG_ASSERT(captures[1].matched);
531 
532  const std::size_t first = lexicalCast<std::size_t>(captures.str(1));
533  const std::size_t last =
534  captures[2].matched ?
535  lexicalCast<std::size_t>(captures.str(2)) : first;
536 
537  if(last < first)
539  MalformedFileException, "Malformed line:\n" + line);
540 
541  newRanges.push_back(std::make_pair(first, last));
542 
543  if(!captures[3].matched)
544  expectAID = false;
545 
546  continue;
547  }
548 
549  if(expectAID)
550  OPENMPCD_THROW(MalformedFileException, "Malformed line:\n" + line);
551 
552  //next is either an option name or an option value
553  if(optionName.empty())
554  {
555  //expect option name next
556  if(*it == "n" || *it == "name")
557  {
558  optionName = "name";
559  }
560  else if(*it == "t" || *it == "type")
561  {
562  optionName = "type";
563  }
564  else if(*it == "r" || *it == "radius")
565  {
566  optionName = "radius";
567  }
568  else
569  {
571  MalformedFileException, "Unknown option: " + *it);
572  }
573  }
574  else
575  {
576  //expect option value
577  if(optionName == "name")
578  {
579  if(it->size() > 16)
581  MalformedFileException, "Name too long: " + *it);
582 
583  properties.name = *it;
584  }
585  else if(optionName == "type")
586  {
587  if(it->size() > 16)
589  MalformedFileException, "Type too long: " + *it);
590 
591  properties.type = *it;
592  }
593  else if(optionName == "radius")
594  {
595  properties.radius = lexicalCast<FP>(*it);
596 
597  if(properties.radius.get() < 0)
598  OPENMPCD_THROW(MalformedFileException, "Bad radius: " + *it);
599  }
600  else
601  {
603  UnimplementedException, "Unknown option: " + *it);
604  }
605 
606  optionName.clear();
607  }
608  }
609 
610  if(!optionName.empty())
611  OPENMPCD_THROW(MalformedFileException, "Malformed atom line:\n" + line);
612 
613  if(isNewDefault)
614  defaultAtomProperties = properties;
615 
616  for(std::size_t i=0; i<newRanges.size(); ++i)
617  {
618  AtomRange newRange;
619  newRange.first = newRanges[i].first;
620  newRange.last = newRanges[i].second;
621  newRange.properties = properties;
622  setAtomRange(newRange);
623  }
624 }
625 
626 void VTFSnapshotFile::setAtomRange(const AtomRange& range)
627 {
628  assertAtomRangesContiguous();
629  OPENMPCD_DEBUG_ASSERT(range.first <= range.last);
630 
631  if(atomRanges.empty())
632  {
633  if(range.first != 0)
634  {
635  AtomRange newRange;
636  newRange.first = 0;
637  newRange.last = range.first - 1;
638  newRange.properties = defaultAtomProperties;
639 
640  atomRanges.push_back(newRange);
641  }
642 
643  atomRanges.push_back(range);
644  }
645 
646  typedef std::list<AtomRange>::iterator It;
647  for(It it = atomRanges.begin(); it != atomRanges.end(); ++it)
648  {
649  if(range.first > it->last)
650  continue;
651 
652  OPENMPCD_DEBUG_ASSERT(range.first >= it->first);
653 
654  if(range.first > it->first)
655  {
656  AtomRange prefix = *it;
657  prefix.last = range.first - 1;
658  atomRanges.insert(it, prefix);
659 
660  it->first = range.first;
661  }
662 
663  OPENMPCD_DEBUG_ASSERT(range.first == it->first);
664 
665  while(range.last >= it->last)
666  {
667  it = atomRanges.erase(it);
668 
669  if(it == atomRanges.end())
670  {
671  atomRanges.push_back(range);
672  return;
673  }
674  }
675 
676  OPENMPCD_DEBUG_ASSERT(range.first <= it->first);
677  OPENMPCD_DEBUG_ASSERT(range.last >= it->first);
678  OPENMPCD_DEBUG_ASSERT(range.last < it->last);
679 
680  it->first = range.last + 1;
681 
682  OPENMPCD_DEBUG_ASSERT(range.last < it->last);
683 
684  atomRanges.insert(it, range);
685  return;
686  }
687 
688  const std::size_t lastAtomID = getNumberOfAtoms() - 1;
689  if(lastAtomID + 1 < range.first)
690  {
691  AtomRange newRange;
692  newRange.first = lastAtomID + 1;
693  newRange.last = range.first - 1;
694  newRange.properties = defaultAtomProperties;
695 
696  atomRanges.push_back(newRange);
697  }
698 
699  atomRanges.push_back(range);
700 }
701 
702 void VTFSnapshotFile::assertAtomRangesContiguous() const
703 {
704  std::size_t nextFirst = 0;
705  typedef std::list<AtomRange>::const_iterator It;
706  for(It it = atomRanges.begin(); it != atomRanges.end(); ++it)
707  {
708  if(it->first != nextFirst)
709  OPENMPCD_THROW(Exception, "Atom ranges not contiguous");
710 
711  if(it->first > it->last)
712  OPENMPCD_THROW(Exception, "Atom range inverted");
713 
714  nextFirst = it->last + 1;
715  }
716 }
717 
718 void VTFSnapshotFile::writeBondLines()
719 {
720  assertWriteMode();
721  assertStructureBlockNotProcessed();
722 
723  typedef std::set<std::pair<std::size_t, std::size_t> > Set;
724  for(Set::const_iterator it = bonds.begin(); it != bonds.end(); ++it)
725  file << "bond " << it->first << ":" << it->second << "\n";
726 }
727 
728 void VTFSnapshotFile::readBondLine(const std::string& line_)
729 {
730  assertReadMode();
731  assertStructureBlockNotProcessed();
732 
733  const boost::regex commaRegex("\\s*,\\s*");
734  const std::string line = boost::regex_replace(line_, commaRegex, ", ");
735 
736  const boost::char_separator<char> separator(" \t");
737  typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
738  Tokenizer tokenizer(line, separator);
739 
740  const boost::regex bondSpecifierRegex("([0-9]+)(::?)([0-9]+)(,)?");
741 
742  bool expectBondSpecifier = true;
743  for(Tokenizer::iterator it = tokenizer.begin(); it != tokenizer.end(); ++it)
744  {
745  if(it == tokenizer.begin() && (*it == "b" || *it == "bond"))
746  continue;
747 
748  if(!expectBondSpecifier)
749  OPENMPCD_THROW(MalformedFileException, "Malformed line:\n" + line);
750 
751  using boost::regex_match;
752 
753  boost::cmatch captures;
754  if(!regex_match(it->c_str(), captures, bondSpecifierRegex))
755  OPENMPCD_THROW(MalformedFileException, "Malformed line:\n" + line);
756 
757  OPENMPCD_DEBUG_ASSERT(captures.size() == 1 + 4);
758  OPENMPCD_DEBUG_ASSERT(captures[1].matched);
759  OPENMPCD_DEBUG_ASSERT(captures[2].matched);
760  OPENMPCD_DEBUG_ASSERT(captures[3].matched);
761 
762  const std::size_t first = lexicalCast<std::size_t>(captures.str(1));
763  const std::size_t last =
764  captures[3].matched ?
765  lexicalCast<std::size_t>(captures.str(3)) : first;
766 
767  if(last <= first)
769  MalformedFileException, "Malformed line:\n" + line);
770 
771  if(!isValidAtomID(first) || !isValidAtomID(last))
773  MalformedFileException, "Malformed line:\n" + line);
774 
775 
777  captures.str(2) == ":" || captures.str(2) == "::");
778 
779  const bool isBondChain = captures.str(2).length() == 2;
780 
781 
782  if(isBondChain)
783  {
784  for(std::size_t current = first; current < last; ++current)
785  {
786  const std::pair<std::size_t, std::size_t>
787  bond(current, current + 1);
788 
789  if(bonds.count(bond))
790  {
791  std::stringstream ss;
792  ss << "Bond declared twice: ";
793  ss << first << ":" << last << "\n";
794  ss << "In line: " << line;
796  }
797 
798  bonds.insert(bond);
799  }
800  }
801  else
802  {
803  const std::pair<std::size_t, std::size_t> bond(first, last);
804 
805  if(bonds.count(bond))
806  {
807  std::stringstream ss;
808  ss << "Bond declared twice: ";
809  ss << first << ":" << last << "\n";
810  ss << "In line: " << line;
812  }
813 
814  bonds.insert(bond);
815  }
816 
817 
818  if(!captures[4].matched)
819  expectBondSpecifier = false;
820  }
821 }
822 
823 const std::string VTFSnapshotFile::getLine(const bool extract)
824 {
825  assertReadMode();
826 
827  if(!file.good())
828  return "";
829 
830  if(file.peek() == std::char_traits<std::fstream::char_type>::eof())
831  {
832  //necessary workaround, since `std::getline` would set `failbit`
833  //otherwise
834  file.clear();
835  file.setstate(std::ios_base::eofbit);
836  return "";
837  }
838 
839  std::string line;
840 
841  if(extract)
842  {
843  std::getline(file, line);
844  return stripLeadingWhitespace(line);
845  }
846 
847  const std::fstream::pos_type position = file.tellg();
848  if(position == std::fstream::pos_type(-1))
849  OPENMPCD_THROW(IOException, "Failed to read line.");
850 
851  std::getline(file, line);
852 
853  if(file.fail())
854  OPENMPCD_THROW(IOException, "Failed to read line.");
855 
856  file.clear();
857  file.seekg(position);
858 
859  if(file.fail())
860  OPENMPCD_THROW(IOException, "Failed to read line.");
861 
862  return stripLeadingWhitespace(line);
863 }
864 
865 const std::string VTFSnapshotFile::stripLeadingWhitespace(
866  const std::string& str)
867 {
868  const std::string::size_type firstNonWhitespace =
869  str.find_first_not_of(" \t\n");
870 
871  if(firstNonWhitespace == std::string::npos)
872  return "";
873 
874  return str.substr(firstNonWhitespace);
875 }
OpenMPCD::VTFSnapshotFile::~VTFSnapshotFile
virtual ~VTFSnapshotFile()
The destructor.
Definition: VTFSnapshotFile.cpp:59
OpenMPCD::InvalidCallException
Exception for a forbidden function call.
Definition: Exceptions.hpp:144
OpenMPCD::Vector3D::getZ
OPENMPCD_CUDA_HOST_AND_DEVICE T getZ() const
Returns the z coordinate.
Definition: Vector3D.hpp:119
OPENMPCD_THROW
#define OPENMPCD_THROW(ExceptionType, message)
Throws the given ExceptionType, passing the given message along with file and line number information...
Definition: Exceptions.hpp:22
OpenMPCD::UnimplementedException
Exception for unimplemented functionality.
Definition: Exceptions.hpp:192
OpenMPCD::VTFSnapshotFile::writeTimestepBlock
void writeTimestepBlock(const FP *const positions, const FP *const velocities=NULL)
Starts a new timestep block, and writes the atom coordinates given.
Definition: VTFSnapshotFile.cpp:190
OpenMPCD::Vector3D::getX
OPENMPCD_CUDA_HOST_AND_DEVICE T getX() const
Returns the x coordinate.
Definition: Vector3D.hpp:61
OpenMPCD::VTFSnapshotFile::getNumberOfAtoms
std::size_t getNumberOfAtoms() const
Returns the number of atoms that have been declared.
Definition: VTFSnapshotFile.hpp:200
OPENMPCD_DEBUG_ASSERT
#define OPENMPCD_DEBUG_ASSERT(assertion)
Asserts that the given expression evaluates to true, but only if OPENMPCD_DEBUG is defined.
Definition: OPENMPCD_DEBUG_ASSERT.hpp:88
OpenMPCD::VTFSnapshotFile::VTFSnapshotFile
VTFSnapshotFile(const std::string &path_)
The constructor.
Definition: VTFSnapshotFile.cpp:19
OpenMPCD::VTFSnapshotFile::declareAtoms
const std::pair< std::size_t, std::size_t > declareAtoms(const std::size_t count)
Declares a number of atoms.
Definition: VTFSnapshotFile.cpp:79
VTFSnapshotFile.hpp
OpenMPCD::VTFSnapshotFile::AtomProperties
Collection of properties of atoms.
Definition: VTFSnapshotFile.hpp:55
OpenMPCD::IOException
Error on IO.
Definition: Exceptions.hpp:160
OpenMPCD::Vector3D::getY
OPENMPCD_CUDA_HOST_AND_DEVICE T getY() const
Returns the y coordinate.
Definition: Vector3D.hpp:90
OpenMPCD::VTFSnapshotFile::AtomProperties::radius
boost::optional< FP > radius
The radius of the atom.
Definition: VTFSnapshotFile.hpp:57
OpenMPCD::VTFSnapshotFile::getAtomProperties
const AtomProperties & getAtomProperties(const std::size_t atomID) const
Returns the properties of the given atomID.
Definition: VTFSnapshotFile.cpp:138
OpenMPCD::VTFSnapshotFile::declareBond
void declareBond(std::size_t atom1, std::size_t atom2)
Declares a bond between the two given atoms.
Definition: VTFSnapshotFile.cpp:152
OPENMPCD_DEBUG_ASSERT.hpp
OpenMPCD::MalformedFileException
Represents an exception that signals a malformed file.
Definition: Exceptions.hpp:224
OpenMPCD::FP
double FP
Default floating point type.
Definition: Types.hpp:13
OpenMPCD::VTFSnapshotFile::readTimestepBlock
bool readTimestepBlock(FP *const positions, FP *const velocities=NULL, bool *const velocitiesEncountered=NULL)
Reads the next timestep block.
Definition: VTFSnapshotFile.cpp:220
Types.hpp
OpenMPCD::VTFSnapshotFile::setPrimarySimulationVolumeSize
void setPrimarySimulationVolumeSize(const FP &x, const FP &y, const FP &z)
Sets the size of the primary simulation volume.
Definition: VTFSnapshotFile.cpp:65
OpenMPCD::Vector3D::setX
OPENMPCD_CUDA_HOST_AND_DEVICE void setX(const T val)
Sets the x coordinate.
Definition: Vector3D.hpp:71
OpenMPCD::VTFSnapshotFile::isInWriteMode
bool isInWriteMode() const
Returns whether the instance is in write mode.
Definition: VTFSnapshotFile.hpp:88
OpenMPCD::Vector3D::setY
OPENMPCD_CUDA_HOST_AND_DEVICE void setY(const T val)
Sets the y coordinate.
Definition: Vector3D.hpp:100
OpenMPCD::Exception
The base exception class for OpenMPCD.
Definition: Exceptions.hpp:37
OpenMPCD::VTFSnapshotFile::primarySimulationVolumeSizeIsSet
bool primarySimulationVolumeSizeIsSet() const
Returns whether the size of the primary simulation volume is set.
Definition: VTFSnapshotFile.hpp:133
OpenMPCD::OutOfBoundsException
Exception for out-of-bounds access.
Definition: Exceptions.hpp:112
OpenMPCD::VTFSnapshotFile::hasBond
bool hasBond(std::size_t atom1, std::size_t atom2) const
Returns whether the two given atoms share a bond.
Definition: VTFSnapshotFile.cpp:174
OpenMPCD::VTFSnapshotFile::isValidAtomID
bool isValidAtomID(const std::size_t atomID) const
Returns whether the given number is a valid atom ID, i.e.
Definition: VTFSnapshotFile.hpp:214
OpenMPCD::NULLPointerException
NULL-pointer exception.
Definition: Exceptions.hpp:96
OpenMPCD::InvalidArgumentException
Invalid argument exception.
Definition: Exceptions.hpp:128
OpenMPCD::VTFSnapshotFile::isInReadMode
bool isInReadMode() const
Returns whether the instance is in read mode.
Definition: VTFSnapshotFile.hpp:96
OpenMPCD::Vector3D::setZ
OPENMPCD_CUDA_HOST_AND_DEVICE void setZ(const T val)
Sets the z coordinate.
Definition: Vector3D.hpp:129