33#include <boost/algorithm/string.hpp>
50 std::vector<std::string> tempFields;
51 for (
const auto &field : fields) {
52 if (field.at(0) ==
'#') {
55 tempFields.push_back(field);
69 cout <<
"WARNING: The votca lammps data reader is only able to read ";
70 cout <<
"lammps files formatted in the following styles:" << endl;
71 cout <<
"angle" << endl;
72 cout <<
"atom" << endl;
73 cout <<
"bond" << endl;
74 cout <<
"full" << endl;
75 cout <<
"molecule" << endl;
77 cout <<
"These styles use the following formats in the atom block:" << endl;
78 cout <<
"atom-ID molecule-ID atom-type charge x y z" << endl;
79 cout <<
"atom-ID molecule-ID atom-type charge x y z nx ny nz" << endl;
80 cout <<
"atom-ID molecule-ID atom-type x y z" << endl;
81 cout <<
"atom-ID molecule-ID atom-type x y z nx ny nz" << endl;
82 cout <<
"atom-ID atom-type x y z" << endl;
83 cout <<
"atom-ID atom-type x y z nx ny nz" << endl;
90 throw std::ios_base::failure(
"Error on open topology file: " + file);
106 if (!
fl_.is_open()) {
107 throw std::ios_base::failure(
"Error on open trajectory file: " + file);
129 std::vector<std::string> fields =
133 if (fields.size() == 1) {
135 }
else if (fields.size() == 2) {
137 }
else if (fields.size() == 3) {
139 }
else if (fields.size() == 4) {
141 }
else if (fields.size() != 0) {
142 string err =
"Unrecognized line in lammps .data file:\n" + line;
143 throw std::runtime_error(err);
156 std::string longname =
"";
157 std::map<std::string, Index> molname_map;
159 std::string atomname = atom->getName();
160 std::string
element = atomname.substr(0, 1);
161 if (std::islower(atomname[1])) {
169 std::string shortname =
"";
170 for (
auto const &pair : molname_map) {
171 shortname += pair.first + std::to_string(pair.second);
173 return std::make_pair(shortname, longname);
178 std::map<std::string, std::set<std::string>> shortname_longnames;
180 for (
const auto &mol : molecules) {
181 if (mol.getName() ==
"UNKNOWN") {
183 shortname_longnames[names.first].insert(names.second);
187 for (
auto &mol : molecules) {
188 if (mol.getName() ==
"UNKNOWN") {
191 if (shortname_longnames[names.first].size() == 1) {
192 mol.setName(names.first);
199 std::distance(shortname_longnames[names.first].begin(),
200 shortname_longnames[names.first].find(names.second));
201 mol.setName(names.first +
"-" + std::to_string(i));
210 if (fields.at(0) ==
"Masses") {
213 }
else if (fields.at(0) ==
"Atoms") {
215 }
else if (fields.at(0) ==
"Bonds") {
217 }
else if (fields.at(0) ==
"Angles") {
219 }
else if (fields.at(0) ==
"Dihedrals") {
221 }
else if (fields.at(0) ==
"Impropers") {
223 cout <<
"WARNING Impropers are not currently supported, skipping." << endl;
236 string label = fields.at(0) +
" " + fields.at(1);
238 if (fields.at(1) ==
"atoms") {
240 }
else if (fields.at(1) ==
"bonds") {
242 }
else if (fields.at(1) ==
"angles") {
244 }
else if (fields.at(1) ==
"dihedrals") {
246 }
else if (fields.at(1) ==
"impropers") {
248 }
else if (label ==
"Pair Coeffs") {
250 }
else if (label ==
"Bond Coeffs") {
252 }
else if (label ==
"Angle Coeffs") {
254 }
else if (label ==
"Improper Coeffs") {
263 string label = fields.at(1) +
" " + fields.at(2);
264 if (label ==
"atom types") {
266 }
else if (label ==
"bond types") {
268 }
else if (label ==
"angle types") {
270 }
else if (label ==
"dihedral types") {
272 }
else if (label ==
"improper types") {
282 string label = fields.at(2) +
" " + fields.at(3);
283 if (label ==
"xlo xhi") {
292 if (!
data_.count(
"Masses")) {
294 "Masses must first be parsed before the atoms can be read.");
299 for (
const auto &mass :
data_[
"Masses"]) {
301 double mass_atom_bead = std::stod(mass.at(1));
307 cout <<
"Unable to associate mass " << mass.at(1)
308 <<
" with element assuming pseudo atom, assigning name "
309 <<
"Bead" << mass.at(0) <<
" ." << endl;
318 Eigen::Matrix3d m = Eigen::Matrix3d::Zero();
319 m(0, 0) = std::stod(fields.at(1)) - std::stod(fields.at(0));
321 for (
Index i = 1; i < 3; ++i) {
325 if (fields.size() != 4) {
326 throw runtime_error(
"invalid box format in the lammps data file");
329 m(i, i) = std::stod(fields.at(1)) - std::stod(fields.at(0));
339 std::vector<std::vector<std::string>> group;
340 while (!line.empty()) {
357 std::runtime_error(
"Number of beads in topology and trajectory differ");
366 numberOf_[
"angles"] = stoi(fields.at(0));
370 numberOf_[
"dihedrals"] = stoi(fields.at(0));
374 numberOf_[
"impropers"] = stoi(fields.at(0));
382 if (fields.size() == 5 || fields.size() == 8) {
384 }
else if (fields.size() == 6 || fields.size() == 9) {
386 }
else if (fields.size() == 7 || fields.size() == 10) {
390 "You have submitted a lammps data file with an "
391 "unsupported format.");
398 if (
data_.count(
"Masses") == 0) {
400 "You are attempting to read in the atom block before the masses, or "
401 "you have failed to include the masses in the data file.");
409 bool chargeRead =
false;
410 bool moleculeRead =
false;
419 std::map<Index, string> sorted_file;
421 Index startingIndexMolecule = 0;
422 std::istringstream issfirst(line);
423 issfirst >> startingIndex;
425 issfirst >> startingIndexMolecule;
427 sorted_file[startingIndex] = line;
432 Index moleculeId = 0;
433 while (!line.empty()) {
434 std::istringstream iss(line);
439 sorted_file[atomId] = line;
442 if (atomId < startingIndex) {
443 startingIndex = atomId;
445 if (moleculeId < startingIndexMolecule) {
446 startingIndexMolecule = moleculeId;
450 for (
Index atomIndex = startingIndex;
451 static_cast<size_t>(atomIndex - startingIndex) < sorted_file.size();
458 istringstream iss(sorted_file[atomIndex]);
476 moleculeId -= startingIndexMolecule;
493 double mass = std::stod(
data_[
"Masses"].at(atomTypeId).at(1));
495 if (
Index(
data_.at(
"Masses").size()) <= atomTypeId) {
497 "The atom block contains an atom of type " +
498 std::to_string(atomTypeId) +
499 " however, the masses are only specified for atoms up to type " +
500 std::to_string(
data_.at(
"Masses").size() - 1);
501 throw runtime_error(err);
504 Index residue_index = moleculeId;
514 "Unrecognized atomTypeId, the atomtypes map "
515 "may be uninitialized");
518 string bead_type_name =
atomtypes_[atomTypeId];
524 residue_index, mass, charge);
526 mol->
AddBead(b, bead_type_name);
530 b = top.
getBead(atomIndex - startingIndex);
533 Eigen::Vector3d xyz_pos(x, y, z);
539 "The number of atoms read in is not equivalent to the "
540 "number of atoms indicated to exist in the lammps data file. \n"
541 "Number of atoms that should exist " +
542 to_string(
numberOf_[
"atoms"]) +
"\nNumber of atoms that were read in " +
544 throw runtime_error(err);
556 Index atom1Id, atom2Id;
558 Index bond_count = 0;
559 while (!line.empty()) {
562 istringstream iss(line);
576 std::cout <<
"WARNING: Lammps Atoms " + std::to_string(atom1Id + 1) +
577 " and " + std::to_string(atom2Id + 1) +
578 " belong to different molecules (" +
589 auto b = top.
getBead(atom1Index);
593 mi->AddInteraction(ic);
603 "The number of bonds read in is not equivalent to the "
604 "number of bonds indicated to exist in the lammps data file. \n"
605 "Number of bonds that should exist " +
607 "\nNumber of bonds that were read in " + std::to_string(bond_count) +
609 throw runtime_error(err);
621 Index atom1Id, atom2Id, atom3Id;
623 Index angle_count = 0;
625 while (!line.empty()) {
628 std::istringstream iss(line);
648 auto b = top.
getBead(atom1Index);
652 mi->AddInteraction(ic);
661 if (angle_count !=
numberOf_[
"angles"]) {
663 "The number of angles read in is not equivalent to the "
664 "number of angles indicated to exist in the lammps data file. \n"
665 "Number of angles that should exist " +
667 "\nNumber of angles that were read in " + to_string(angle_count) +
"\n";
668 throw runtime_error(err);
676 while (!line.empty()) {
688 Index dihedralTypeId;
689 Index atom1Id, atom2Id, atom3Id, atom4Id;
691 Index dihedral_count = 0;
692 while (!line.empty()) {
695 istringstream iss(line);
697 iss >> dihedralTypeId;
716 new IDihedral(atom1Index, atom2Index, atom3Index, atom4Index);
719 auto b = top.
getBead(atom1Index);
723 mi->AddInteraction(ic);
730 if (dihedral_count !=
numberOf_[
"dihedrals"]) {
732 "The number of dihedrals read in is not equivalent to the "
733 "number of dihedrals indicated to exist in the lammps data file. \n"
734 "Number of dihedrals that should exist " +
736 "\nNumber of dihedrals that were read in " + to_string(dihedral_count) +
738 throw runtime_error(err);
virtual void setPos(const Eigen::Vector3d &bead_position)
void setMoleculeId(const Index &molecule_id) noexcept
assign the bead to a molecule with the provided id
base class for all interactions
void setGroup(const std::string &group)
void setIndex(const Index &index)
void setMolecule(const Index &mol)
void ReadNumOfAtoms_(std::vector< std::string > fields, Topology &top)
lammps_format determineDataFileFormat_(std::string line)
void ReadNumOfDihedrals_(std::vector< std::string > fields)
void ReadBonds_(Topology &top)
void InitializeAtomAndBeadTypes_()
Determines atom and bead types based on masses in lammps files.
void ReadAngles_(Topology &top)
void ReadNumOfAngles_(std::vector< std::string > fields)
bool MatchFourFieldLabels_(std::vector< std::string > fields, Topology &top)
void RenameMolecules(MoleculeContainer &molecules) const
std::map< std::string, Index > numberOfDifferentTypes_
void ReadAtoms_(Topology &top)
bool ReadTopology(std::string file, Topology &top) override
open, read and close topology file
void Close() override
close the topology file
void ReadBox_(std::vector< std::string > fields, Topology &top)
void ReadNumOfImpropers_(std::vector< std::string > fields)
void SortIntoDataGroup_(std::string tag)
void ReadDihedrals_(Topology &top)
bool FirstFrame(Topology &top) override
read in the first frame of trajectory file
std::map< std::string, std::vector< std::vector< std::string > > > data_
std::map< std::string, Index > numberOf_
bool NextFrame(Topology &top) override
read in the next frame of trajectory file
std::map< Index, Index > atomIdToIndex_
void ReadNumTypes_(std::vector< std::string > fields, std::string type)
bool MatchOneFieldLabel_(std::vector< std::string > fields, Topology &top)
std::map< Index, Molecule * > molecules_
std::map< Index, std::string > atomtypes_
@ style_angle_bond_molecule
void ReadNumOfBonds_(std::vector< std::string > fields)
bool MatchThreeFieldLabels_(std::vector< std::string > fields)
std::map< Index, Index > atomIdToMoleculeId_
bool Open(const std::string &file) override
open a trajectory file
bool MatchTwoFieldLabels_(std::vector< std::string > fields, Topology &top)
information about molecules
void AddBead(Bead *bead, const std::string &name)
Add a bead to the molecule.
Index getId() const
get the molecule ID
const std::vector< Bead * > & Beads() const
topology of the whole system
Residue & CreateResidue(std::string name)
Create a new resiude.
void setBox(const Eigen::Matrix3d &box, BoundaryCondition::eBoxtype boxtype=BoundaryCondition::typeAuto)
void Cleanup()
Cleans up all the stored data.
Index ResidueCount() const
bool BeadTypeExist(std::string type) const
Determine if a bead type exists.
Bead * CreateBead(Bead::Symmetry symmetry, std::string name, std::string type, Index resnr, double m, double q)
Creates a new Bead.
void AddBondedInteraction(Interaction *ic)
Molecule * getMolecule(const Index i)
void RegisterBeadType(std::string type)
Register the bead type with the topology object.
Molecule * CreateMolecule(std::string name)
Creates a new molecule.
Bead * getBead(const Index i)
Returns a pointer to the bead with index i.
MoleculeContainer & Molecules()
std::vector< std::string > TrimCommentsFrom_(std::vector< std::string > fields)
reduced_edge_to_edges_map::value_type element
boost::container::deque< Molecule, void, block_molecule_4x_t > MoleculeContainer
std::pair< std::string, std::string > getNames(const Molecule &mol)
base class for all analysis tools