votca 2024.2-dev
Loading...
Searching...
No Matches
map.cc
Go to the documentation of this file.
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 <numeric>
20#include <string>
21
22// VOTCA includes
23#include <votca/tools/eigen.h>
25
26// Local VOTCA includes
27#include "votca/csg/bead.h"
28#include "votca/csg/map.h"
29#include "votca/csg/topology.h"
30
31namespace votca {
32namespace csg {
33class Molecule;
34} // namespace csg
35namespace tools {
36class Property;
37} // namespace tools
38} // namespace votca
39
40namespace votca {
41namespace csg {
42using namespace tools;
43using namespace std;
44
45/*******************************************************
46 Linear map for spherical beads
47 *******************************************************/
48class Map_Sphere : public BeadMap {
49 public:
50 Map_Sphere() = default;
51 void Apply(const BoundaryCondition &) override;
52
53 virtual void Initialize(const Molecule *in, Bead *out,
54 tools::Property *opts_bead,
55 tools::Property *opts_map) override;
56
57 protected:
58 void AddElem(const Bead *in, double weight, double force_weight);
59
60 struct element_t {
61 const Bead *in_;
62 double weight_;
64 };
65 std::vector<element_t> matrix_;
66};
67
68void Map_Sphere::AddElem(const Bead *in, double weight, double force_weight) {
69 element_t el;
70 el.in_ = in;
71 el.weight_ = weight;
72 el.force_weight_ = force_weight;
73 matrix_.push_back(el);
74}
75
76/*******************************************************
77 Linear map for ellipsoidal bead
78 *******************************************************/
79class Map_Ellipsoid : public Map_Sphere {
80 public:
81 Map_Ellipsoid() = default;
82 void Apply(const BoundaryCondition &) final;
83};
84
86 for (auto &map_ : maps_) {
87 map_->Apply(bc);
88 }
89}
90
91void Map_Sphere::Initialize(const Molecule *in, Bead *out, Property *opts_bead,
92 Property *opts_map) {
93
94 in_ = in;
95 out_ = out;
96 opts_map_ = opts_map;
97 opts_bead_ = opts_bead;
98
99 vector<double> fweights;
100
101 // get the beads
102 string s(opts_bead_->get("beads").value());
103 vector<string> beads = Tokenizer(s, " \n\t").ToVector();
104
105 // get vector of weights
106 Tokenizer tok_weights(opts_map_->get("weights").value(), " \n\t");
107 vector<double> weights = tok_weights.ToVector<double>();
108
109 // check weather weights and # beads matches
110 if (beads.size() != weights.size()) {
111 throw runtime_error(
112 string("number of subbeads in " + opts_bead->get("name").as<string>() +
113 " and number of weights in map " +
114 opts_map->get("name").as<string>() + " do not match"));
115 }
116
117 // normalize the weights
118 double norm = 1. / std::accumulate(weights.begin(), weights.end(), 0.);
119
120 transform(weights.begin(), weights.end(), weights.begin(),
121 [&norm](double w) { return w * norm; });
122 // get the d vector if exists or initialize same as weights
123 vector<double> d;
124 if (opts_map_->exists("d")) {
125 Tokenizer tok_weights2(opts_map_->get("d").value(), " \n\t");
126 d = tok_weights2.ToVector<double>();
127 // normalize d coefficients
128 norm = 1. / std::accumulate(d.begin(), d.end(), 0.);
129 transform(d.begin(), d.end(), d.begin(),
130 [&norm](double w) { return w * norm; });
131 } else {
132 // initialize force-weights with weights
133 d.resize(weights.size());
134 copy(weights.begin(), weights.end(), d.begin());
135 }
136
137 // check weather number of d coeffs is correct
138 if (beads.size() != d.size()) {
139 throw runtime_error(
140 string("number of subbeads in " + opts_bead->get("name").as<string>() +
141 " and number of d-coefficients in map " +
142 opts_map->get("name").as<string>() + " do not match"));
143 }
144
145 fweights.resize(weights.size());
146 // calculate force weights by d_i/w_i
147 for (size_t i = 0; i < weights.size(); ++i) {
148 if (weights[i] == 0 && d[i] != 0) {
149 throw runtime_error(
150 "A d coefficient is nonzero while weights is zero in mapping " +
151 opts_map->get("name").as<string>());
152 }
153 if (weights[i] != 0) {
154 fweights[i] = d[i] / weights[i];
155 } else {
156 fweights[i] = 0;
157 }
158 }
159
160 for (size_t i = 0; i < beads.size(); ++i) {
161 Index iin = in->getBeadByName(beads[i]);
162 if (iin < 0) {
163 throw std::runtime_error(
164 string("mapping error: molecule " + beads[i] + " does not exist"));
165 }
166 AddElem(in->getBead(iin), weights[i], fweights[i]);
167 }
168}
169
171
172 assert(matrix_.size() > 0 && "Cannot map to sphere there are no beads");
173
174 bool bPos, bVel, bF;
175 bPos = bVel = bF = false;
177
178 // the following is needed for pbc treatment
179 Eigen::Vector3d r0 = Eigen::Vector3d::Zero();
180 string name0;
181 Index id0 = 0;
182 if (matrix_.size() > 0) {
183 if (matrix_.front().in_->HasPos()) {
184 r0 = matrix_.front().in_->getPos();
185 name0 = matrix_.front().in_->getName();
186 id0 = matrix_.front().in_->getId();
187 }
188 }
189
190 double M = 0;
191 Eigen::Vector3d cg = Eigen::Vector3d::Zero();
192 Eigen::Vector3d f = Eigen::Vector3d::Zero();
193 Eigen::Vector3d vel = Eigen::Vector3d::Zero();
194
195 const Bead *bead_max_dist = matrix_.at(0).in_;
196 double max_bead_dist = 0;
197 if (bead_max_dist->HasPos()) {
198 max_bead_dist = bc.BCShortestConnection(r0, bead_max_dist->getPos()).norm();
199 }
200
201 for (const auto &iter : matrix_) {
202 const Bead *bead = iter.in_;
203 out_->AddParentBead(bead->getId());
204 M += bead->getMass();
205 if (bead->HasPos()) {
206 Eigen::Vector3d r = bc.BCShortestConnection(r0, bead->getPos());
207 if (r.norm() > max_bead_dist) {
208 max_bead_dist = r.norm();
209 bead_max_dist = bead;
210 }
211 cg += iter.weight_ * (r + r0);
212 bPos = true;
213 }
214 }
215
219 double max_dist = 0.5 * bc.getShortestBoxDimension();
220 if (max_bead_dist > max_dist) {
221 cout << r0 << " " << bead_max_dist->getPos() << endl;
222 throw std::runtime_error(
223 "coarse-grained bead is bigger than half the box \n "
224 "(atoms " +
225 name0 + " (id " + boost::lexical_cast<string>(id0 + 1) + ")" + ", " +
226 bead_max_dist->getName() + " (id " +
227 boost::lexical_cast<string>(bead_max_dist->getId() + 1) + ")" +
228 +" , molecule " +
229 boost::lexical_cast<string>(bead_max_dist->getMoleculeId() + 1) +
230 ")");
231 }
232 }
233
234 for (const auto &iter : matrix_) {
235 const Bead *bead = iter.in_;
236 if (bead->HasVel()) {
237 vel += iter.weight_ * bead->getVel();
238 bVel = true;
239 }
240 if (bead->HasF()) {
241 f += iter.force_weight_ * bead->getF();
242 bF = true;
243 }
244 }
245 out_->setMass(M);
246 if (bPos) {
247 out_->setPos(cg);
248 }
249 if (bVel) {
250 out_->setVel(vel);
251 }
252 if (bF) {
253 out_->setF(f);
254 }
255}
256
259
260 assert(matrix_.size() > 0 && "Cannot map to ellipsoid there are no beads");
261
262 bool bPos, bVel, bF;
263 bPos = bVel = bF = false;
264
265 // the following is needed for pbc treatment
266 Eigen::Vector3d r0 = Eigen::Vector3d::Zero();
267 string name0;
268 Index id0 = 0;
269 if (matrix_.size() > 0) {
270 if (matrix_.front().in_->HasPos()) {
271 r0 = matrix_.front().in_->getPos();
272 name0 = matrix_.front().in_->getName();
273 id0 = matrix_.front().in_->getId();
274 }
275 }
276 Eigen::Vector3d cg = Eigen::Vector3d::Zero();
277 Eigen::Vector3d c = Eigen::Vector3d::Zero();
278 Eigen::Vector3d f = Eigen::Vector3d::Zero();
279 Eigen::Vector3d vel = Eigen::Vector3d::Zero();
280
281 Index n;
282 n = 0;
284
285 const Bead *bead_max_dist = matrix_.at(0).in_;
286 double max_bead_dist = 0;
287 if (bead_max_dist->HasPos()) {
288 max_bead_dist = bc.BCShortestConnection(r0, bead_max_dist->getPos()).norm();
289 }
290
291 for (const auto &iter : matrix_) {
292 const Bead *bead = iter.in_;
293 out_->AddParentBead(bead->getId());
294 if (bead->HasPos()) {
295 Eigen::Vector3d r = bc.BCShortestConnection(r0, bead->getPos());
296 if (r.norm() > max_bead_dist) {
297 max_bead_dist = r.norm();
298 bead_max_dist = bead;
299 }
300 cg += iter.weight_ * (r + r0);
301 bPos = true;
302 }
303 }
304
308 double max_dist = 0.5 * bc.getShortestBoxDimension();
309 if (max_bead_dist > max_dist) {
310 cout << r0 << " " << bead_max_dist->getPos() << endl;
311 throw std::runtime_error(
312 "coarse-grained bead is bigger than half the box \n "
313 "(atoms " +
314 name0 + " (id " + boost::lexical_cast<string>(id0 + 1) + ")" + ", " +
315 bead_max_dist->getName() + " (id " +
316 boost::lexical_cast<string>(bead_max_dist->getId() + 1) + ")" +
317 +" , molecule " +
318 boost::lexical_cast<string>(bead_max_dist->getMoleculeId() + 1) +
319 ")");
320 }
321 }
322
323 for (const auto &iter : matrix_) {
324 const Bead *bead = iter.in_;
325 if (bead->HasVel() == true) {
326 vel += iter.weight_ * bead->getVel();
327 bVel = true;
328 }
329 if (bead->HasF()) {
332 // f += (*iter). weight_ * in_->getBeadF((*iter). in_);
333 f += iter.force_weight_ * bead->getF();
334 bF = true;
335 }
336
337 if (iter.weight_ > 0 && bead->HasPos()) {
338 c += bead->getPos();
339 n++;
340 }
341 }
342
343 if (bPos) {
344 out_->setPos(cg);
345 }
346 if (bVel) {
347 out_->setVel(vel);
348 }
349 if (bF) {
350 out_->setF(f);
351 }
352
353 if (!matrix_[0].in_->HasPos()) {
354 out_->setU(Eigen::Vector3d::UnitX());
355 out_->setV(Eigen::Vector3d::UnitY());
356 out_->setW(Eigen::Vector3d::UnitZ());
357 return;
358 }
359
360 Eigen::Matrix3d m = Eigen::Matrix3d::Zero();
361 // calculate the tensor of gyration
362 c = c / (double)n;
363 for (auto &iter : matrix_) {
364 if (iter.weight_ == 0) {
365 continue;
366 }
367 const Bead *bead = iter.in_;
368 Eigen::Vector3d v = bead->getPos() - c;
369 // v = vec(1, 0.5, 0) * 0.*(drand48()-0.5)
370 // + vec(0.5, -1, 0) * (drand48()-0.5)
371 // + vec(0, 0, 1) * (drand48()-0.5);
372
373 // Normalize the tensor with 1/number_of_atoms_per_bead
374 m += v * v.transpose() / (double)matrix_.size();
375 }
376
377 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eig;
378 eig.computeDirect(m);
379
380 Eigen::Vector3d u = eig.eigenvectors().col(0);
381 Eigen::Vector3d v = matrix_[1].in_->getPos() - matrix_[0].in_->getPos();
382 v.normalize();
383
384 out_->setV(v);
385
386 Eigen::Vector3d w = matrix_[2].in_->getPos() - matrix_[0].in_->getPos();
387 w.normalize();
388
389 if (v.cross(w).dot(u) < 0) {
390 u = -u;
391 }
392 out_->setU(u);
393
394 // write out w
395 w = u.cross(v);
396 w.normalize();
397 out_->setW(w);
398}
399
401 : in_(map.in_), out_(map.out_), maps_(std::move(map.maps_)) {}
402
404 in_ = map.in_;
405 out_ = map.out_;
406 maps_ = std::move(map.maps_);
407 return *this;
408}
409
411 if (type == BeadMapType::Spherical) {
412 maps_.push_back(std::make_unique<Map_Sphere>());
413 } else {
414 maps_.push_back(std::make_unique<Map_Ellipsoid>());
415 }
416 return maps_.back().get();
417}
418
419} // namespace csg
420} // namespace votca
virtual void setMass(const double &m) noexcept
Definition basebead.h:110
virtual const Eigen::Vector3d & getPos() const
Definition basebead.h:166
std::string getName() const
Gets the name of the bead.
Definition basebead.h:58
virtual void setPos(const Eigen::Vector3d &bead_position)
Definition basebead.h:161
Index getMoleculeId() const noexcept
Get the id of the molecule the bead is a part of, if the molecule id has not been set return topology...
Definition basebead.h:78
virtual const double & getMass() const noexcept
Definition basebead.h:104
bool HasPos() const noexcept
Definition basebead.h:139
Index getId() const noexcept
Gets the id of the bead.
Definition basebead.h:52
tools::Property * opts_map_
Definition map.h:54
Bead * out_
Definition map.h:53
const Molecule * in_
Definition map.h:52
tools::Property * opts_bead_
Definition map.h:55
information about a bead
Definition bead.h:50
const Eigen::Vector3d & getF() const
get the force acting on the bead
Definition bead.h:361
void ClearParentBeads()
Clears out all parent beads.
Definition bead.h:270
void setU(const Eigen::Vector3d &u)
set first orientation (normal vector) vector of bead
Definition bead.h:326
bool HasF() const noexcept
Definition bead.h:235
void setF(const Eigen::Vector3d &bead_force)
Definition bead.h:356
bool HasVel() const noexcept
Definition bead.h:232
void setW(const Eigen::Vector3d &w)
set third orientation vector of bead
Definition bead.h:346
void setVel(const Eigen::Vector3d &r)
Definition bead.h:315
void AddParentBead(Index parent_bead_id)
Adds the id of a parent bead.
Definition bead.h:275
const Eigen::Vector3d & getVel() const
Definition bead.h:320
void setV(const Eigen::Vector3d &v)
set second orientation vector of bead
Definition bead.h:336
Class keeps track of how the boundaries of the system are handled.
double getShortestBoxDimension() const
Self explanatory gets the shortest dimension of the boundary conditions.
virtual Eigen::Vector3d BCShortestConnection(const Eigen::Vector3d &r_i, const Eigen::Vector3d &r_j) const =0
virtual eBoxtype getBoxType() const noexcept=0
void Apply(const BoundaryCondition &) final
Definition map.cc:258
void AddElem(const Bead *in, double weight, double force_weight)
Definition map.cc:68
void Apply(const BoundaryCondition &) override
Definition map.cc:170
std::vector< element_t > matrix_
Definition map.cc:65
virtual void Initialize(const Molecule *in, Bead *out, tools::Property *opts_bead, tools::Property *opts_map) override
Definition map.cc:91
void Apply(const BoundaryCondition &bc)
Definition map.cc:85
BeadMap * CreateBeadMap(const BeadMapType type)
Definition map.cc:410
Map & operator=(Map &&map)
Definition map.cc:403
Molecule out_
Definition map.h:76
Molecule in_
Definition map.h:75
Map(const Molecule &in, Molecule &out)
Definition map.h:63
std::vector< std::unique_ptr< BeadMap > > maps_
Definition map.h:77
information about molecules
Definition molecule.h:45
Bead * getBead(Index bead)
get the id of a bead in the molecule
Definition molecule.h:59
Index getBeadByName(const std::string &name) const
find a bead by it's name
Definition molecule.cc:37
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
std::string & value()
reference to value of property
Definition property.h:153
bool exists(const std::string &key) const
check whether property exists
Definition property.cc:122
T as() const
return value as type
Definition property.h:283
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.
BeadMapType
Definition map.h:37
base class for all analysis tools
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26