1 /*
2 * Copyright 2009-2021 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 <cstddef>
20 #include <iostream>
21 #include <memory>
22 #include <stdexcept>
23 #include <string>
24
25 // Third party includes
26 #include <boost/lexical_cast.hpp>
27
28 // VOTCA includes
29 #include <votca/tools/property.h>
30 #include <votca/tools/tokenizer.h>
31
32 // Local VOTCA includes
33 #include "votca/csg/cgmoleculedef.h"
34 #include "votca/csg/interaction.h"
35 #include "votca/csg/map.h"
36 #include "votca/csg/topology.h"
37
38 namespace votca {
39 namespace csg {
40 class Molecule;
41 class Residue;
42 } // namespace csg
43 } // namespace votca
44
45 namespace votca {
46 namespace csg {
47
48 using namespace std;
49 using boost::lexical_cast;
50
~CGMoleculeDef()51 CGMoleculeDef::~CGMoleculeDef() {
52 for (beaddef_t *def : beads_) {
53 delete def;
54 }
55 beads_.clear();
56 }
57
Load(string filename)58 void CGMoleculeDef::Load(string filename) {
59 options_.LoadFromXML(filename);
60 // parse xml tree
61 name_ = options_.get("cg_molecule.name").as<string>();
62 ident_ = options_.get("cg_molecule.ident").as<string>();
63
64 ParseTopology(options_.get("cg_molecule.topology"));
65 ParseMapping(options_.get("cg_molecule.maps"));
66 }
67
ParseTopology(tools::Property & options)68 void CGMoleculeDef::ParseTopology(tools::Property &options) {
69 ParseBeads(options.get("cg_beads"));
70 if (options.exists("cg_bonded")) {
71 ParseBonded(options.get("cg_bonded"));
72 }
73 }
74
ParseBeads(tools::Property & options)75 void CGMoleculeDef::ParseBeads(tools::Property &options) {
76
77 for (tools::Property *p : options.Select("cg_bead")) {
78 beaddef_t *beaddef = new beaddef_t;
79 beaddef->options_ = p;
80
81 beaddef->name_ = p->get("name").as<string>();
82 beaddef->type_ = p->get("type").as<string>();
83 beaddef->mapping_ = p->get("mapping").as<string>();
84 if (p->exists("symmetry")) {
85 Index sym = p->get("symmetry").as<Index>();
86 if (sym == 1) {
87 beaddef->symmetry_ = Bead::spherical;
88 } else if (sym == 3) {
89 beaddef->symmetry_ = Bead::ellipsoidal;
90 } else {
91 throw std::runtime_error(
92 "Only beads with spherical(1) or ellipsoidal(3) symmetry "
93 "implemented.");
94 }
95 } else {
96 beaddef->symmetry_ = Bead::spherical;
97 }
98
99 if (beads_by_name_.find(beaddef->name_) != beads_by_name_.end()) {
100 throw std::runtime_error(string("bead name ") + beaddef->name_ +
101 " not unique in mapping");
102 }
103 beads_.push_back(beaddef);
104 beads_by_name_[beaddef->name_] = beaddef;
105 }
106 }
107
ParseBonded(tools::Property & options)108 void CGMoleculeDef::ParseBonded(tools::Property &options) {
109 bonded_ = options.Select("*");
110 }
111
ParseMapping(tools::Property & options)112 void CGMoleculeDef::ParseMapping(tools::Property &options) {
113
114 for (tools::Property *p : options.Select("map")) {
115 maps_[p->get("name").as<string>()] = p;
116 }
117 }
CreateMolecule(Topology & top)118 Molecule *CGMoleculeDef::CreateMolecule(Topology &top) {
119 // add the residue names
120 const Residue &res = top.CreateResidue(name_);
121 Molecule *minfo = top.CreateMolecule(name_);
122
123 // create the atoms
124 for (auto &bead_def : beads_) {
125
126 string type = bead_def->type_;
127 if (!top.BeadTypeExist(type)) {
128 top.RegisterBeadType(type);
129 }
130 Bead *bead = top.CreateBead(bead_def->symmetry_, bead_def->name_, type,
131 res.getId(), 0, 0);
132 minfo->AddBead(bead, bead->getName());
133 }
134
135 // create the bonds
136 map<string, string> had_iagroup;
137
138 for (tools::Property *prop : bonded_) {
139 std::list<Index> atoms;
140 string iagroup = prop->get("name").as<string>();
141
142 if (had_iagroup[iagroup] == "yes") {
143 throw runtime_error(
144 string("double occurence of interactions with name ") + iagroup);
145 }
146 had_iagroup[iagroup] = "yes";
147
148 tools::Tokenizer tok(prop->get("beads").value(), " \n\t");
149 for (auto &atom : tok) {
150 Index i = minfo->getBeadIdByName(atom);
151 if (i < 0) {
152 throw runtime_error(
153 string("error while trying to create bonded interaction, "
154 "bead " +
155 atom + " not found"));
156 }
157
158 atoms.push_back(i);
159 }
160
161 Index NrBeads = 1;
162 if (prop->name() == "bond") {
163 NrBeads = 2;
164 } else if (prop->name() == "angle") {
165 NrBeads = 3;
166 } else if (prop->name() == "dihedral") {
167 NrBeads = 4;
168 }
169
170 if ((atoms.size() % NrBeads) != 0) {
171 throw runtime_error("Number of atoms in interaction '" +
172 prop->get("name").as<string>() +
173 "' is not a multiple of " +
174 lexical_cast<string>(NrBeads) + "! Missing beads?");
175 }
176
177 Index index = 0;
178 while (!atoms.empty()) {
179 Interaction *ic;
180
181 if (prop->name() == "bond") {
182 ic = new IBond(atoms);
183 } else if (prop->name() == "angle") {
184 ic = new IAngle(atoms);
185 } else if (prop->name() == "dihedral") {
186 ic = new IDihedral(atoms);
187 } else {
188 throw runtime_error("unknown bonded type in map: " + prop->name());
189 }
190
191 ic->setGroup(iagroup);
192 ic->setIndex(index);
193 ic->setMolecule(minfo->getId());
194 top.AddBondedInteraction(ic);
195 minfo->AddInteraction(ic);
196 index++;
197 }
198 }
199 return minfo;
200 }
201
CreateMap(const Molecule & in,Molecule & out)202 Map CGMoleculeDef::CreateMap(const Molecule &in, Molecule &out) {
203 if (out.BeadCount() != Index(beads_.size())) {
204 throw runtime_error(
205 "number of beads for cg molecule and mapping definition do "
206 "not match, check your molecule naming.");
207 }
208
209 Map map(in, out);
210 for (auto &bead : beads_) {
211
212 Index iout = out.getBeadByName(bead->name_);
213 if (iout < 0) {
214 throw runtime_error(string("mapping error: reference molecule " +
215 bead->name_ + " does not exist"));
216 }
217
218 tools::Property *mdef = getMapByName(bead->mapping_);
219 if (!mdef) {
220 throw runtime_error(string("mapping " + bead->mapping_ + " not found"));
221 }
222
223 /// TODO: change this to factory, do not hardcode!!
224 BeadMap *bmap;
225 switch (bead->symmetry_) {
226 case 1:
227 bmap = map.CreateBeadMap(BeadMapType::Spherical);
228 break;
229 case 3:
230 bmap = map.CreateBeadMap(BeadMapType::Ellipsoidal);
231 break;
232 default:
233 throw runtime_error(string("unknown symmetry in bead definition!"));
234 }
235 ////////////////////////////////////////////////////
236
237 bmap->Initialize(&in, out.getBead(iout), (bead->options_), mdef);
238 }
239 return map;
240 }
241
getBeadByName(const string & name)242 CGMoleculeDef::beaddef_t *CGMoleculeDef::getBeadByName(const string &name) {
243 map<string, beaddef_t *>::iterator iter = beads_by_name_.find(name);
244 if (iter == beads_by_name_.end()) {
245 std::cout << "cannot find: <" << name << "> in " << name_ << "\n";
246 return nullptr;
247 }
248 return (*iter).second;
249 }
250
getMapByName(const string & name)251 tools::Property *CGMoleculeDef::getMapByName(const string &name) {
252 map<string, tools::Property *>::iterator iter = maps_.find(name);
253 if (iter == maps_.end()) {
254 std::cout << "cannot find map " << name << "\n";
255 return nullptr;
256 }
257 return (*iter).second;
258 }
259
260 } // namespace csg
261 } // namespace votca
262