votca 2024.2-dev
Loading...
Searching...
No Matches
xmltopologyreader.cc
Go to the documentation of this file.
1/*
2 * Copyright 2009-2020 The VOTCA Development Team (http://www.votca.org)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18// Standard includes
19#include <cstdio>
20#include <fstream>
21#include <iostream>
22#include <memory>
23#include <stdexcept>
24
25// Third party includes
26#include <boost/lexical_cast.hpp>
27
28// Local private VOTCA includes
29#include "xmltopologyreader.h"
30
31namespace votca {
32namespace csg {
33
34using namespace std;
35
36bool XMLTopologyReader::ReadTopology(string filename, Topology &top) {
37 top_ = &top;
38
39 tools::Property options;
40 options.LoadFromXML(filename);
41 ParseRoot(options.get("topology"));
42
44 return true;
45}
46
48 std::unique_ptr<TopologyReader> reader = TopReaderFactory().Create(file);
49 if (!reader) {
50 throw runtime_error(file + ": unknown topology format");
51 }
52
53 reader->ReadTopology(file, *top_);
54 // Clean XML molecules and beads.
55}
56
58 has_base_topology_ = false;
59 if (property.hasAttribute("base")) {
60 ReadTopolFile(property.getAttribute<string>("base"));
61 has_base_topology_ = true;
62 }
63
64 // Iterate over keys at first level.
65 for (auto &it : property) {
66 if (it.name() == "h5md_particle_group") {
67 top_->setParticleGroup(it.getAttribute<string>("name"));
68 } else if (it.name() == "molecules") {
69 mol_index_ = 1;
70 bead_index_ = 0;
72 } else if (it.name() == "bonded") {
73 ParseBonded(it);
74 } else if (it.name() == "box") {
75 ParseBox(it);
76 } else if (it.name() == "beadtypes") {
78 } else {
79 throw runtime_error("unknown tag: topology." + it.name());
80 }
81 }
82}
83
85 Eigen::Matrix3d m = Eigen::Matrix3d::Zero();
86 m(0, 0) = p.getAttribute<double>("xx");
87 m(1, 1) = p.getAttribute<double>("yy");
88 m(2, 2) = p.getAttribute<double>("zz");
89 top_->setBox(m);
90}
91
93 for (auto &it : p) {
94 if (it.name() == "clear") {
96 } else if (it.name() == "rename") {
97 string molname = it.getAttribute<string>("name");
98 string range = it.getAttribute<string>("range");
99 top_->RenameMolecules(range, molname);
100 } else if (it.name() == "define" || it.name() == "molecule") {
101 string molname = it.getAttribute<string>("name");
102 Index first = 0;
103 if (it.name() == "define") {
104 first = it.getAttribute<Index>("first");
105 }
106 Index nbeads = it.getAttribute<Index>("nbeads");
107 Index nmols = it.getAttribute<Index>("nmols");
108 if (it.name() == "define" && first < 1) {
109 throw std::runtime_error(
110 "Attribute first is suppose to be > 0, but found " +
111 boost::lexical_cast<string>(it.getAttribute<string>("first")));
112 }
113 if (nbeads < 1) {
114 throw std::runtime_error(
115 "Attribute nbeads is suppose to be > 0, but found " +
116 boost::lexical_cast<string>(it.getAttribute<string>("nbeads")));
117 }
118 if (nmols < 1) {
119 throw std::runtime_error(
120 "Attribute nmols is suppose to be > 0, but found " +
121 boost::lexical_cast<string>(it.getAttribute<string>("nmols")));
122 }
123 if (it.name() == "define") {
124 top_->CreateMoleculesByRange(molname, first, nbeads, nmols);
125 } else {
126 if (has_base_topology_) {
127 throw std::runtime_error(
128 "The defined list of beads only works for pure xml topology, "
129 "without 'base' attribute.");
130 }
131 ParseMolecule(it, molname, nmols);
132 }
133 }
134 }
135}
136
138 Index nmols) {
139 vector<XMLBead *> xmlBeads;
140 vector<Index> xmlResidues;
141 for (auto &it : p) {
142 if (it.name() == "bead") {
143 string atname = it.getAttribute<string>("name");
144 string attype = it.getAttribute<string>("type");
145 double atmass, atq;
146 Index resid;
147 try {
148 atmass = it.getAttribute<double>("mass");
149 } catch (runtime_error &) {
150 atmass = 1.0;
151 }
152 try {
153 atq = it.getAttribute<double>("q");
154 } catch (runtime_error &) {
155 atq = 0.0;
156 }
157 try {
158 resid = it.getAttribute<Index>("resid");
159 if (resid <= 0) {
160 throw std::invalid_argument(
161 "Residue count for beads in topology.molecules.molecule has to "
162 "be greater than zero");
163 }
164 } catch (runtime_error &) {
165 resid = -1;
166 }
167 if (!xmlResidues.empty()) {
168 if (xmlResidues.back() != resid && xmlResidues.back() != resid - 1) {
169 throw std::invalid_argument(
170 "Residue count for beads in topology.molecules.molecule does not "
171 "increase monotonically in steps of 1");
172 }
173 if (xmlResidues.back() != -1 && resid == -1) {
174 throw std::invalid_argument(
175 "Residue count for beads in topology.molecules.molecule has to "
176 "be declared for all beads or for none");
177 }
178 }
179 xmlResidues.push_back(resid);
180 XMLBead *xmlBead = new XMLBead(atname, attype, atmass, atq);
181 xmlBeads.push_back(xmlBead);
182 } else {
183 throw std::runtime_error(
184 "Wrong element under topology.molecules.molecule: " + it.name());
185 }
186 }
187 if (xmlResidues.size() != xmlBeads.size()) {
188 throw std::runtime_error(
189 "Number of elements in bead-vector and residue-vector are not "
190 "identical");
191 }
192 // Create molecule in topology. Replicate data.
193 Index resnr = top_->ResidueCount();
194 if (!xmlResidues.empty()) {
195 if (xmlResidues.front() != resnr + 1 && xmlResidues.front() != -1) {
196 throw std::runtime_error(
197 "Residue count for beads in topology.molecules.molecule has to be "
198 "greater than the number of residues already in the topology");
199 }
200 }
201 for (Index mn = 0; mn < nmols; mn++) {
202 Molecule *mi = top_->CreateMolecule(molname);
203 XMLMolecule *xmlMolecule = new XMLMolecule(molname, nmols);
204 xmlMolecule->pid = mi->getId();
205 xmlMolecule->mi = mi;
206 molecules_.insert(make_pair(molname, xmlMolecule));
207 vector<Index>::iterator resit = xmlResidues.begin();
208 for (vector<XMLBead *>::iterator itb = xmlBeads.begin();
209 itb != xmlBeads.end(); ++itb, ++resit) {
210 stringstream bname;
211 XMLBead &b = **itb;
212 if (*resit != -1) {
213 if (top_->ResidueCount() < *resit) {
214 resnr = *resit - 1;
215 top_->CreateResidue(molname, resnr);
216 }
217 } else {
218 top_->CreateResidue(molname, resnr);
219 }
220
221 if (!top_->BeadTypeExist(b.type)) {
223 }
224 Bead *bead =
225 top_->CreateBead(Bead::spherical, b.name, b.type, resnr, b.mass, b.q);
226 bname << mol_index_ << ":" << molname << ":" << b.name;
227 mi->AddBead(bead, bname.str());
228
229 // Data for bonded terms.
230 XMLBead *b_rep = new XMLBead(b);
231 b_rep->pid = bead_index_;
232 if (xmlMolecule->name2beads.count(b.name) != 0) {
233 throw std::runtime_error("Atom " + b.name + " in molecule " + molname +
234 " already exists.");
235 }
236 xmlMolecule->name2beads.insert(make_pair(b.name, b_rep));
237 bead_index_++;
238 }
239 resnr++;
240 }
241
242 // clean up
243 for (auto &xmlBead : xmlBeads) {
244 delete xmlBead;
245 }
246}
247
249 for (auto &it : el) {
250 if (it.name() == "rename") {
251 string name = it.getAttribute<string>("name");
252 string newname = it.getAttribute<string>("newname");
253 if (name == "" || newname == "") {
254 throw runtime_error("invalid rename tag, name or newname are empty.");
255 }
256 top_->RenameBeadType(name, newname);
257 } else if (it.name() == "mass") {
258 string name = it.getAttribute<string>("name");
259 double value = it.getAttribute<double>("value");
260 top_->SetBeadTypeMass(name, value);
261 } else {
262 throw std::runtime_error("Wrong element under beadtypes: " + it.name());
263 }
264 }
265}
266
268 for (auto &it : el) {
269 if (it.name() == "bond") {
270 ParseBond(it);
271 } else if (it.name() == "angle") {
272 ParseAngle(it);
273 } else if (it.name() == "dihedral") {
274 ParseDihedral(it);
275 } else {
276 throw std::runtime_error("Wrong element under bonded: " + it.name());
277 }
278 }
279}
280
282 string name = p.get("name").as<string>();
283 string beads = p.get("beads").as<string>();
284 vector<string> bead_list = tools::Tokenizer(beads, " \n\t").ToVector();
285 if (bead_list.size() % 2 == 1) {
286 throw runtime_error("Wrong number of beads in bond: " + name);
287 }
288 Interaction *ic = nullptr;
289 typedef pair<MoleculesMap::iterator, MoleculesMap::iterator> MRange;
290 Index b_index = 0;
291 for (vector<string>::iterator it = bead_list.begin();
292 it != bead_list.end();) {
293 BondBead b1(*(it++));
294 BondBead b2(*(it++));
295 if (b1.molname == b2.molname) {
296 // Iterates over molecules and gets atom pids.
297 MRange mRange = molecules_.equal_range(b1.molname);
298 for (MoleculesMap::iterator itm = mRange.first; itm != mRange.second;
299 ++itm) {
300 XMLMolecule &xmlMolecule = *itm->second;
301 XMLBead &xmlBead1 = *xmlMolecule.name2beads[b1.atname];
302 XMLBead &xmlBead2 = *xmlMolecule.name2beads[b2.atname];
303 ic = new IBond(xmlBead1.pid, xmlBead2.pid);
304 ic->setGroup(name);
305 ic->setIndex(b_index);
306 ic->setMolecule(xmlMolecule.pid);
307 xmlMolecule.mi->AddInteraction(ic);
309 b_index++;
310 }
311 } else {
312 throw std::runtime_error(
313 "Beads from different molecules, not supported!");
314 }
315 }
316}
317
319 string name = p.get("name").as<string>();
320 string beads = p.get("beads").as<string>();
321 vector<string> bead_list = tools::Tokenizer(beads, " \n\t").ToVector();
322 if (bead_list.size() % 3 == 1) {
323 throw runtime_error("Wrong number of beads in angle: " + name);
324 }
325 Interaction *ic = nullptr;
326 typedef pair<MoleculesMap::iterator, MoleculesMap::iterator> MRange;
327 Index b_index = 0;
328 for (vector<string>::iterator it = bead_list.begin();
329 it != bead_list.end();) {
330 BondBead b1(*(it++));
331 BondBead b2(*(it++));
332 BondBead b3(*(it++));
333 if ((b1.molname == b2.molname) && (b2.molname == b3.molname)) {
334 // Iterates over molecules and gets atom pids.
335 MRange mRange = molecules_.equal_range(b1.molname);
336 for (MoleculesMap::iterator itm = mRange.first; itm != mRange.second;
337 ++itm) {
338 XMLMolecule &xmlMolecule = *itm->second;
339 XMLBead &xmlBead1 = *xmlMolecule.name2beads[b1.atname];
340 XMLBead &xmlBead2 = *xmlMolecule.name2beads[b2.atname];
341 XMLBead &xmlBead3 = *xmlMolecule.name2beads[b3.atname];
342 ic = new IAngle(xmlBead1.pid, xmlBead2.pid, xmlBead3.pid);
343 ic->setGroup(name);
344 ic->setIndex(b_index);
345 ic->setMolecule(xmlMolecule.pid);
346 xmlMolecule.mi->AddInteraction(ic);
348 b_index++;
349 }
350 } else {
351 throw std::runtime_error(
352 "Beads from different molecules, not supported!");
353 }
354 }
355}
357 string name = p.get("name").as<string>();
358 string beads = p.get("beads").as<string>();
359 vector<string> bead_list = tools::Tokenizer(beads, " \n\t").ToVector();
360 if (bead_list.size() % 4 == 1) {
361 throw runtime_error("Wrong number of beads in dihedral: " + name);
362 }
363 Interaction *ic = nullptr;
364 typedef pair<MoleculesMap::iterator, MoleculesMap::iterator> MRange;
365 Index b_index = 0;
366 for (vector<string>::iterator it = bead_list.begin();
367 it != bead_list.end();) {
368 BondBead b1(*(it++));
369 BondBead b2(*(it++));
370 BondBead b3(*(it++));
371 BondBead b4(*(it++));
372 if ((b1.molname == b2.molname) && (b3.molname == b4.molname) &&
373 (b1.molname == b4.molname)) {
374 // Iterates over molecules and gets atom pids.
375 MRange mRange = molecules_.equal_range(b1.molname);
376 for (MoleculesMap::iterator itm = mRange.first; itm != mRange.second;
377 ++itm) {
378 XMLMolecule &xmlMolecule = *itm->second;
379 XMLBead &xmlBead1 = *xmlMolecule.name2beads[b1.atname];
380 XMLBead &xmlBead2 = *xmlMolecule.name2beads[b2.atname];
381 XMLBead &xmlBead3 = *xmlMolecule.name2beads[b3.atname];
382 XMLBead &xmlBead4 = *xmlMolecule.name2beads[b4.atname];
383 ic = new IDihedral(xmlBead1.pid, xmlBead2.pid, xmlBead3.pid,
384 xmlBead4.pid);
385 ic->setGroup(name);
386 ic->setIndex(b_index);
387 ic->setMolecule(xmlMolecule.pid);
388 xmlMolecule.mi->AddInteraction(ic);
390 b_index++;
391 }
392 } else {
393 throw std::runtime_error(
394 "Beads from different molecules, not supported!");
395 }
396 }
397}
398
400 // Clean molecules_ map
401 for (auto &molecule_ : molecules_) {
402 XMLMolecule *xmlMolecule = molecule_.second;
403 for (auto &bead : xmlMolecule->beads) {
404 delete bead;
405 }
406 xmlMolecule->beads.clear();
407 delete xmlMolecule;
408 }
409}
410
411} // namespace csg
412} // namespace votca
information about a bead
Definition bead.h:50
angle interaction
bond interaction
dihedral interaction
base class for all interactions
Definition interaction.h:40
void setGroup(const std::string &group)
Definition interaction.h:49
void setIndex(const Index &index)
Definition interaction.h:67
void setMolecule(const Index &mol)
Definition interaction.h:76
information about molecules
Definition molecule.h:45
void AddBead(Bead *bead, const std::string &name)
Add a bead to the molecule.
Definition molecule.cc:29
void AddInteraction(Interaction *ic)
Add an interaction to the molecule.
Definition molecule.h:77
Index getId() const
get the molecule ID
Definition molecule.h:48
topology of the whole system
Definition topology.h:81
Residue & CreateResidue(std::string name)
Create a new resiude.
Definition topology.h:462
void setBox(const Eigen::Matrix3d &box, BoundaryCondition::eBoxtype boxtype=BoundaryCondition::typeAuto)
Definition topology.h:272
void CreateMoleculesByRange(std::string name, Index first, Index nbeads, Index nmolecules)
create molecules based on blocks of atoms
Definition topology.cc:72
void RenameMolecules(std::string range, std::string name)
rename all the molecules in range
Definition topology.cc:138
void RenameBeadType(std::string name, std::string newname)
rename all the bead types
Definition topology.cc:150
Index ResidueCount() const
Definition topology.h:156
bool BeadTypeExist(std::string type) const
Determine if a bead type exists.
Definition topology.cc:210
Bead * CreateBead(Bead::Symmetry symmetry, std::string name, std::string type, Index resnr, double m, double q)
Creates a new Bead.
Definition topology.h:441
void AddBondedInteraction(Interaction *ic)
Definition topology.cc:188
void RegisterBeadType(std::string type)
Register the bead type with the topology object.
Definition topology.cc:214
void SetBeadTypeMass(std::string name, double value)
set the mass of all the beads of a certain type
Definition topology.cc:160
Molecule * CreateMolecule(std::string name)
Creates a new molecule.
Definition topology.h:449
void setParticleGroup(std::string particle_group)
Definition topology.h:335
std::vector< XMLBead * > beads
std::map< std::string, XMLBead * > name2beads
void ParseBonded(tools::Property &el)
void ParseBeadTypes(tools::Property &el)
void ParseMolecule(tools::Property &p, std::string molname, Index nmols)
void ParseBond(tools::Property &p)
void ParseMolecules(tools::Property &p)
bool ReadTopology(std::string filename, Topology &top) override
read a topology file
void ParseAngle(tools::Property &p)
void ReadTopolFile(std::string file)
void ParseDihedral(tools::Property &p)
void ParseBox(tools::Property &p)
void ParseRoot(tools::Property &property)
class to manage program options with xml serialization functionality
Definition property.h:55
Property & get(const std::string &key)
get existing property
Definition property.cc:79
T as() const
return value as type
Definition property.h:283
bool hasAttribute(const std::string &attribute) const
return true if an attribute exists
Definition property.cc:118
T getAttribute(const std::string &attribute) const
return attribute as type
Definition property.h:308
void LoadFromXML(std::string filename)
Definition property.cc:238
break string into words
Definition tokenizer.h:72
std::vector< T > ToVector()
store all words in a vector of type T, does type conversion.
Definition tokenizer.h:109
STL namespace.
FileFormatFactory< TopologyReader > & TopReaderFactory()
base class for all analysis tools
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26