votca 2024.2-dev
Loading...
Searching...
No Matches
csg_stat_imc.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 <fstream>
20#include <iomanip>
21#include <iostream>
22#include <memory>
23#include <numeric>
24
25// Third party includes
26#include <boost/lexical_cast.hpp>
27
28// VOTCA includes
30
31// Local VOTCA includes
32#include "votca/csg/beadlist.h"
33#include "votca/csg/imcio.h"
36
37// Local private VOTCA includes
38#include "csg_stat_imc.h"
39
40namespace votca {
41namespace csg {
42
43using namespace std;
44
45// begin the coarse graining process
46// here the data structures are prepared to handle all the data
48 // do some output
49 if (do_imc_) {
50 cout << "begin to calculate inverse monte carlo parameters\n";
51 if (include_intra_) {
52 throw runtime_error("error, can not have --do-imc and --include-intra");
53 }
54 } else {
55 cout << "begin to calculate distribution functions\n";
56 }
57 cout << "# of bonded interactions: " << bonded_.size() << endl;
58 cout << "# of non-bonded interactions: " << nonbonded_.size() << endl;
59
60 if (bonded_.size() + nonbonded_.size() == 0) {
61 throw std::runtime_error(
62 "No interactions defined in options xml-file - nothing to be done");
63 }
64
65 // initialize non-bonded structures
66 for (tools::Property *prop : nonbonded_) {
67 bool bonded = false;
68 AddInteraction(prop, bonded);
69 }
70
71 // initialize bonded structures
72 for (tools::Property *prop : bonded_) {
73 bool bonded = true;
74 AddInteraction(prop, bonded);
75 }
76
77 // initialize the group structures
78 if (do_imc_) {
80 }
81}
82
84 // we didn't process any frames so far
85 nframes_ = 0;
86 nblock_ = 0;
88
89 // initialize non-bonded structures
90 for (tools::Property *prop : nonbonded_) {
91 string name = prop->get("name").value();
92
93 interaction_t &i = *interactions_[name];
94
95 // Preliminary: Quickest way to incorporate 3 body correlations
96 if (i.threebody_) {
97
98 // generate the bead lists
99 BeadList beads1, beads2, beads3;
100
101 beads1.Generate(*top, prop->get("type1").value());
102 beads2.Generate(*top, prop->get("type2").value());
103 beads3.Generate(*top, prop->get("type3").value());
104
105 if (beads1.size() == 0) {
106 throw std::runtime_error(
107 "Topology does not have beads of type \"" +
108 prop->get("type1").value() +
109 "\"\n"
110 "This was specified in type1 of interaction \"" +
111 name + "\"");
112 }
113 if (beads2.size() == 0) {
114 throw std::runtime_error(
115 "Topology does not have beads of type \"" +
116 prop->get("type2").value() +
117 "\"\n"
118 "This was specified in type2 of interaction \"" +
119 name + "\"");
120 }
121 if (beads3.size() == 0) {
122 throw std::runtime_error(
123 "Topology does not have beads of type \"" +
124 prop->get("type3").value() +
125 "\"\n"
126 "This was specified in type3 of interaction \"" +
127 name + "\"");
128 }
129 }
130 // 2body
131 if (!i.threebody_) {
132
133 double max_dist = 0.5 * top->ShortestBoxSize();
134 double max = i.average_.getMax();
135 if (max > max_dist) {
136 throw std::runtime_error("The max of interaction \"" + name +
137 "\" bigger is than half the box.");
138 }
139
140 // generate the bead lists
141 BeadList beads1, beads2;
142
143 beads1.Generate(*top, prop->get("type1").value());
144 beads2.Generate(*top, prop->get("type2").value());
145
146 if (beads1.size() == 0) {
147 throw std::runtime_error(
148 "Topology does not have beads of type \"" +
149 prop->get("type1").value() +
150 "\"\n"
151 "This was specified in type1 of interaction \"" +
152 name + "\"");
153 }
154 if (beads2.size() == 0) {
155 throw std::runtime_error(
156 "Topology does not have beads of type \"" +
157 prop->get("type2").value() +
158 "\"\n"
159 "This was specified in type2 of interaction \"" +
160 name + "\"");
161 }
162
163 // calculate normalization factor for rdf
164 if (prop->get("type1").value() == prop->get("type2").value()) {
165 i.norm_ = 2. / (double)(beads1.size() * beads2.size());
166 } else {
167 i.norm_ = 1. / (double)(beads1.size() * beads2.size());
168 }
169 }
170 }
171
172 for (tools::Property *prop : bonded_) {
173 string name = prop->get("name").value();
174 std::vector<Interaction *> vec = top->InteractionsInGroup(name);
175 if (vec.empty()) {
176 throw std::runtime_error(
177 "Bonded interaction '" + name +
178 "' defined in options xml-file, but not in topology - check name "
179 "definition in the mapping file again");
180 }
181 }
182}
183
184// create an entry for interactions
186 string name = p->get("name").value();
187 string group;
188 if (do_imc_) {
189 group = p->get("inverse.imc.group").value();
190 } else {
191 group = "none";
192 }
193
194 votca::Index index = Index(interactions_.size());
195 auto success = interactions_.insert(
196 std::make_pair(name, std::make_unique<interaction_t>()));
197 interaction_t *i = success.first->second.get();
198 i->index_ = index;
199 if (group != "none") {
200 getGroup(group)->interactions_.push_back(i);
201 }
202
203 i->is_bonded_ = is_bonded;
204 i->step_ = p->get("step").as<double>();
205 i->min_ = p->get("min").as<double>();
206 i->max_ = p->get("max").as<double>();
207 if (include_intra_ && (!i->is_bonded_)) {
208 i->max_ = p->get("max_intra").as<double>();
209 } else {
210 i->max_ = p->get("max").as<double>();
211 }
212
213 i->norm_ = 1.0;
214 i->p_ = p;
215
216 // if option threebody does not exist, replace it by default of 0
217 i->threebody_ = p->ifExistsReturnElseReturnDefault<bool>("threebody", 0);
218
219 // if option force does not exist, replace it by default of 0
220 i->force_ = p->ifExistsReturnElseReturnDefault<bool>("force", 0);
221
222 // if option cut does not exist, replace it by default of 0.37 nm
223 i->cut_ = p->ifExistsReturnElseReturnDefault<double>("cut", 0.37);
224
225 // initialize the current and average histogram
226 votca::Index n =
227 static_cast<votca::Index>((i->max_ - i->min_) / i->step_ + 1.000000001);
228
229 i->average_.Initialize(i->min_, i->max_, n);
230 if (i->force_) {
231 i->average_force_.Initialize(i->min_, i->max_, n);
232 }
233
234 return i;
235}
236
237// end of trajectory, post processing data
239 if (nframes_ > 0) {
240 if (block_length_ == 0) {
241 string suffix = string(".") + extension_;
242 WriteDist(suffix);
243 if (do_imc_) {
244 WriteIMCData();
245 }
246 }
247 }
248 // clear interactions and groups
249 interactions_.clear();
250 groups_.clear();
252 throw std::runtime_error(
253 "no frames were processed. Please check your input");
254 }
255}
256
257// load options from xml file
258void Imc::LoadOptions(const string &file) {
259 options_.LoadFromXML(file);
260 bonded_ = options_.Select("cg.bonded");
261 nonbonded_ = options_.Select("cg.non-bonded");
262}
263
264// evaluate current conformation
266
267 cur_vol_ = top->BoxVolume();
268 // process non-bonded interactions
269 DoNonbonded(top);
270 // process bonded interactions
271 DoBonded(top);
272}
273
275 nframes_ = 0;
276
277 for (auto &inter : interactions_) {
278 inter.second->average_.Clear();
279 if (inter.second->force_) {
280 inter.second->average_force_.Clear();
281 }
282 }
283 for (auto &group : groups_) {
284 group.second->corr_.setZero();
285 }
286}
287
289 public:
291 : hist_(*hist) {}
292
294
295 bool FoundPair(Bead *, Bead *, const Eigen::Vector3d &, const double dist) {
296 hist_.Process(dist);
297 return false;
298 }
299};
300
301// process non-bonded interactions for current frame
303 for (tools::Property *prop : imc_->nonbonded_) {
304 string name = prop->get("name").value();
305
306 interaction_t &i = *imc_->interactions_[name];
307
308 // clear the current histogram
309 current_hists_[i.index_].Clear();
310 current_hists_force_[i.index_].Clear();
311
312 bool gridsearch = true;
313
314 if (imc_->options_.exists("cg.nbsearch")) {
315 if (imc_->options_.get("cg.nbsearch").as<string>() == "grid") {
316 gridsearch = true;
317 } else if (imc_->options_.get("cg.nbsearch").as<string>() == "simple") {
318 gridsearch = false;
319 } else {
320 throw std::runtime_error("cg.nbsearch invalid, can be grid or simple");
321 }
322 }
323
324 // Preleminary: Quickest way to incorporate 3 body correlations
325 if (i.threebody_) {
326
327 // generate the bead lists
328 BeadList beads1, beads2, beads3;
329
330 beads1.Generate(*top, prop->get("type1").value());
331 beads2.Generate(*top, prop->get("type2").value());
332 beads3.Generate(*top, prop->get("type3").value());
333
334 // generate the neighbour list
335 std::unique_ptr<NBList_3Body> nb;
336
337 if (gridsearch) {
338 nb = std::unique_ptr<NBList_3Body>(new NBListGrid_3Body());
339 } else {
340 nb = std::make_unique<NBList_3Body>();
341 }
342
343 nb->setCutoff(i.cut_); // implement different cutoffs for different
344 // interactions!
345 // Here, a is the distance between two beads of a triple, where the 3-body
346 // interaction is zero
347
348 // check if type2 and type3 are the same
349 if (prop->get("type2").value() == prop->get("type3").value()) {
350 // if then type2 and type1 are the same, all three types are the same
351 // use the Generate function for this case
352 if (prop->get("type1").value() == prop->get("type2").value()) {
353 nb->Generate(beads1, true);
354 }
355 // else use the Generate function for type2 being equal to type3 (and
356 // type1 being different)
357 if (prop->get("type1").value() != prop->get("type2").value()) {
358 nb->Generate(beads1, beads2, true);
359 }
360 }
361 // If type2 and type3 are not the same, use the Generate function for
362 // three different bead types (Even if type1 and type2 or type1 and type3
363 // are the same, the Generate function for two different beadtypes is only
364 // applicable for the case that type2 is equal to type3
365 if (prop->get("type2").value() != prop->get("type3").value()) {
366 nb->Generate(beads1, beads2, beads3, true);
367 }
368
369 for (auto &triple : *nb) {
370 Eigen::Vector3d rij = triple->r12();
371 Eigen::Vector3d rik = triple->r13();
372 double var = std::acos(rij.dot(rik) /
373 sqrt(rij.squaredNorm() * rik.squaredNorm()));
374 current_hists_[i.index_].Process(var);
375 }
376 }
377 // 2body interaction
378 if (!i.threebody_) {
379
380 // generate the bead lists
381 BeadList beads1, beads2;
382
383 beads1.Generate(*top, prop->get("type1").value());
384 beads2.Generate(*top, prop->get("type2").value());
385
386 {
387 // generate the neighbour list
388 std::unique_ptr<NBList> nb;
389 if (gridsearch) {
390 nb = std::unique_ptr<NBList>(new NBListGrid());
391 } else {
392 nb = std::unique_ptr<NBList>(new NBListGrid());
393 }
394
395 nb->setCutoff(i.max_ + i.step_);
396
397 IMCNBSearchHandler h(&(current_hists_[i.index_]));
398
399 nb->SetMatchFunction(&h, &IMCNBSearchHandler::FoundPair);
400
401 // is it same types or different types?
402 if (prop->get("type1").value() == prop->get("type2").value()) {
403 nb->Generate(beads1, !(imc_->include_intra_));
404 } else {
405 nb->Generate(beads1, beads2, !(imc_->include_intra_));
406 }
407 }
408
409 // if one wants to calculate the mean force
410 if (i.force_) {
411 std::unique_ptr<NBList> nb_force;
412 if (gridsearch) {
413 nb_force = std::unique_ptr<NBList>(new NBListGrid());
414 } else {
415 nb_force = std::unique_ptr<NBList>(new NBListGrid());
416 }
417
418 nb_force->setCutoff(i.max_ + i.step_);
419
420 // is it same types or different types?
421 if (prop->get("type1").value() == prop->get("type2").value()) {
422 nb_force->Generate(beads1);
423 } else {
424 nb_force->Generate(beads1, beads2);
425 }
426
427 // process all pairs to calculate the projection of the
428 // mean force on bead 1 on the pair distance: F1 * r12
429 for (auto &pair : *nb_force) {
430 Eigen::Vector3d F2 = pair->second()->getF();
431 Eigen::Vector3d F1 = pair->first()->getF();
432 Eigen::Vector3d r12 = pair->r();
433 r12.normalize();
434 double var = pair->dist();
435 double scale = 0.5 * (F2 - F1).dot(r12);
436 current_hists_force_[i.index_].Process(var, scale);
437 }
438 }
439 }
440 }
441}
442
443// process non-bonded interactions for current frame
445 for (tools::Property *prop : imc_->bonded_) {
446 string name = prop->get("name").value();
447
448 interaction_t &i = *imc_->interactions_[name];
449
450 // clear the current histogram
451 current_hists_[i.index_].Clear();
452
453 // now fill with new data
454 for (Interaction *ic : top->InteractionsInGroup(name)) {
455 double v = ic->EvaluateVar(*top);
456 current_hists_[i.index_].Process(v);
457 }
458 }
459}
460
461// returns a group, creates it if doesn't exist
462Imc::group_t *Imc::getGroup(const string &name) {
463 map<string, std::unique_ptr<group_t> >::iterator iter;
464 iter = groups_.find(name);
465 if (iter == groups_.end()) {
466 auto success =
467 groups_.insert(std::make_pair(name, std::make_unique<group_t>()));
468 return success.first->second.get();
469 }
470 return (*iter).second.get();
471}
472
473// initialize the groups after interactions are added
475 if (!do_imc_) {
476 return;
477 }
478 map<string, group_t *>::iterator group_iter;
479
480 // clear all the pairs
481
482 // iterator over all groups
483 for (auto &group : groups_) {
484 auto &grp = group.second;
485 grp->pairs_.clear();
486
487 auto &interactions = grp->interactions_;
488 // count number of bins needed in matrix
489 votca::Index n = std::accumulate(interactions.begin(), interactions.end(),
490 0, [](votca::Index j, interaction_t *i) {
491 return j + i->average_.getNBins();
492 });
493
494 // handy access to matrix
495 group_matrix &M = grp->corr_;
496
497 // initialize matrix with zeroes
498 M = Eigen::MatrixXd::Zero(n, n);
499
500 // now create references to the sub matrices and offsets
501 votca::Index offset_i = 0;
502 votca::Index offset_j = 0;
503 // iterate over all possible cominations of pairs
504 for (votca::Index i = 0; i < votca::Index(interactions.size()); i++) {
505 votca::Index n1 = interactions[i]->average_.getNBins();
506 offset_j = offset_i;
507 for (votca::Index j = i; j < votca::Index(interactions.size()); j++) {
508 votca::Index n2 = interactions[j]->average_.getNBins();
509 // create matrix proxy with sub-matrix
510 pair_matrix corr = M.block(offset_i, offset_j, n1, n2);
511 // add the pair
512 grp->pairs_.push_back(
513 pair_t(interactions[i], interactions[j], offset_i, offset_j, corr));
514 offset_j += n2;
515 }
516 offset_i += n1;
517 }
518 }
519}
520
521// update the correlation matrix
523 if (!do_imc_) {
524 return;
525 }
526
527 for (auto &group : groups_) {
528 auto &grp = group.second;
529 // update correlation for all pairs
530 for (auto &pair : grp->pairs_) {
531 Eigen::VectorXd &a = worker->current_hists_[pair.i1_->index_].data().y();
532 Eigen::VectorXd &b = worker->current_hists_[pair.i2_->index_].data().y();
533 pair_matrix &M = pair.corr_;
534
535 M = ((((double)nframes_ - 1.0) * M) + a * b.transpose()) /
536 (double)nframes_;
537 }
538 }
539}
540
541// write the distribution function
542void Imc::WriteDist(const string &suffix) {
543 map<string, interaction_t *>::iterator iter;
544
545 cout << std::endl; // Cosmetic, put \n before printing names of distribution
546 // files.
547 // for all interactions
548 for (auto &pair : interactions_) {
549 // calculate the rdf
550 auto &interaction = pair.second;
551 votca::tools::Table &t = interaction->average_.data();
552
553 // if no average force calculation, dummy table
555 // if average force calculation, table force contains force data
556 if (interaction->force_) {
557 force = interaction->average_force_.data();
558 }
559
560 votca::tools::Table dist(t);
561 if (!interaction->is_bonded_) {
562 // Quickest way to incorporate 3 body correlations
563 if (interaction->threebody_) {
564 // \TODO normalize bond and angle differently....
565 double norm = dist.y().cwiseAbs().sum();
566 if (norm > 0) {
567 dist.y() =
568 interaction->norm_ * dist.y() / (norm * interaction->step_);
569 }
570 }
571
572 // 2body
573 if (!interaction->threebody_) {
574 // force normalization
575 // normalize by number of pairs found at a specific distance
576 for (votca::Index i = 0; i < force.y().size(); ++i) {
577 // check if any number of pairs has been found at this distance, then
578 // normalize
579 if (dist.y()[i] != 0) {
580 force.y()[i] /= dist.y()[i];
581 }
582 // else set to zero
583 else {
584 force.y()[i] = 0;
585 }
586 }
587
588 // normalization is calculated using exact shell volume (difference of
589 // spheres)
590 for (votca::Index i = 0; i < dist.y().size(); ++i) {
591 double x1 = dist.x()[i] - 0.5 * interaction->step_;
592 double x2 = x1 + interaction->step_;
593 if (x1 < 0) {
594 dist.y()[i] = 0;
595 } else {
596 dist.y()[i] = avg_vol_.getAvg() * interaction->norm_ * dist.y()[i] /
597 (4. / 3. * M_PI * (x2 * x2 * x2 - x1 * x1 * x1));
598 }
599 }
600 }
601
602 } else {
603 // \TODO normalize bond and angle differently....
604 double norm = dist.y().cwiseAbs().sum();
605 if (norm > 0) {
606 dist.y() = interaction->norm_ * dist.y() / (norm * interaction->step_);
607 }
608 }
609
610 dist.Save((pair.first) + suffix);
611 cout << "written " << (pair.first) + suffix << "\n";
612
613 // preliminary
614 if (interaction->force_) {
615 force.Save((pair.first) + ".force.new");
616 cout << "written " << (pair.first) + ".force.new"
617 << "\n";
618 }
619 }
620}
621
628void Imc::WriteIMCData(const string &suffix) {
629 if (!do_imc_) {
630 return;
631 }
632 // map<string, interaction_t *>::iterator ic_iter;
633 map<string, group_t *>::iterator group_iter;
634
635 // iterate over all groups
636 for (auto &group : groups_) {
637 auto &grp = group.second;
638 string grp_name = group.first;
639
640 // number of total bins for all interactions in group is matrix dimension
641 votca::Index n = grp->corr_.rows();
642
643 // build full set of equations + copy some data to make
644 // code better to read
645 group_matrix gmc(grp->corr_);
646 tools::Table dS;
647 dS.resize(n);
648 // the next two variables are to later extract the individual parts
649 // from the whole data after solving equations
650 vector<std::pair<std::string, votca::tools::RangeParser> >
651 ranges; // names of the interactions & sizes of the individual
652 // interactions
653
654 // copy all averages+r of group to one vector
655 n = 0;
656 votca::Index begin = 1;
657 for (interaction_t *ic : grp->interactions_) {
658
659 // sub vector for dS
660 Eigen::VectorBlock<Eigen::VectorXd> sub_dS =
661 dS.y().segment(n, ic->average_.getNBins());
662
663 // sub vector for r
664 Eigen::VectorBlock<Eigen::VectorXd> sub_r =
665 dS.x().segment(n, ic->average_.getNBins());
666
667 // read in target and calculate dS
668 CalcDeltaS(ic, sub_dS);
669
670 // copy r
671 sub_r = ic->average_.data().x();
672
673 // save size
675 votca::Index end = begin + ic->average_.getNBins() - 1;
676 rp.Add(begin, end);
677 ranges.push_back(std::pair<std::string, votca::tools::RangeParser>(
678 ic->p_->get("name").as<string>(), rp));
679 begin = end + 1;
680 // save name
681
682 // shift subrange by size of current
683 n += ic->average_.getNBins();
684 }
685
686 // now we need to calculate the
687 // A_ij = <S_i*S_j> - <S_i>*<S_j>
688 for (pair_t &pair : grp->pairs_) {
689 interaction_t *i1 = pair.i1_;
690 interaction_t *i2 = pair.i2_;
691
692 // make reference to <S_i>
693 Eigen::VectorXd &a = i1->average_.data().y();
694 // make reference to <S_j>
695 Eigen::VectorXd &b = i2->average_.data().y();
696
697 votca::Index i = pair.offset_i_;
698 votca::Index j = pair.offset_j_;
699 votca::Index n1 = i1->average_.getNBins();
700 votca::Index n2 = i2->average_.getNBins();
701
702 pair_matrix M = gmc.block(i, j, n1, n2);
703 M = -(M - a * b.transpose());
704 // matrix is symmetric
705 gmc.block(j, i, n2, n1) = M.transpose().eval();
706 }
707
708 imcio_write_dS(grp_name + suffix + ".imc", dS);
709 imcio_write_matrix(grp_name + suffix + ".gmc", gmc);
710 imcio_write_index(grp_name + suffix + ".idx", ranges);
711 }
712}
713
714// calculate deviation from target vectors
716 Eigen::VectorBlock<Eigen::VectorXd> &dS) {
717 const string &name = interaction->p_->get("name").as<string>();
718
719 tools::Table target;
720 target.Load(name + ".dist.tgt");
721
722 if (!interaction->is_bonded_) {
723 for (votca::Index i = 0; i < target.y().size(); ++i) {
724 double x1 = target.x()[i] - 0.5 * interaction->step_;
725 double x2 = x1 + interaction->step_;
726 if (x1 < 0) {
727 x1 = x2 = 0;
728 }
729 target.y()[i] = 1. / (avg_vol_.getAvg() * interaction->norm_) *
730 target.y()[i] *
731 (4. / 3. * M_PI * (x2 * x2 * x2 - x1 * x1 * x1));
732 }
733 } else {
734 target.y() = (1.0 / interaction->norm_) * target.y();
735 }
736 if (target.y().size() != interaction->average_.data().y().size()) {
737 throw std::runtime_error(
738 "number of grid points in target does not match the grid");
739 }
740
741 dS = interaction->average_.data().y() - target.y();
742}
743
744void Imc::WriteIMCBlock(const string &suffix) {
745
746 if (!do_imc_) {
747 return;
748 }
749
750 // iterate over all groups
751 for (auto &group : groups_) {
752 auto &grp = group.second;
753 string grp_name = group.first;
754 list<interaction_t *>::iterator iter;
755
756 // number of total bins for all interactions in group is matrix dimension
757 votca::Index n = grp->corr_.rows();
758
759 // build full set of equations + copy some data to make code better to read
760 group_matrix gmc(grp->corr_);
761 Eigen::VectorXd dS(n);
762 Eigen::VectorXd r(n);
763 // the next two variables are to later extract the individual parts
764 // from the whole data after solving equations
765 vector<votca::Index> sizes; // sizes of the individual interactions
766 vector<string> names; // names of the interactions
767
768 // copy all averages+r of group to one vector
769 n = 0;
770 for (interaction_t *ic : grp->interactions_) {
771 // sub vector for dS
772 Eigen::VectorBlock<Eigen::VectorXd> sub_dS =
773 dS.segment(n, ic->average_.getNBins());
774
775 // sub vector for r
776 Eigen::VectorBlock<Eigen::VectorXd> sub_r =
777 r.segment(n, ic->average_.getNBins());
778
779 // read in target and calculate dS
780 sub_dS = ic->average_.data().y();
781 // copy r
782 sub_r = ic->average_.data().x();
783 // save size
784 sizes.push_back(ic->average_.getNBins());
785 // save name
786 names.push_back(ic->p_->get("name").as<string>());
787
788 // shift subrange by size of current
789 n += ic->average_.getNBins();
790 }
791
792 // write the dS
793 ofstream out_dS;
794 string name_dS = grp_name + suffix + ".S";
795 out_dS.open(name_dS);
796 out_dS << setprecision(8);
797 if (!out_dS) {
798 throw runtime_error(string("error, cannot open file ") + name_dS);
799 }
800
801 for (votca::Index i = 0; i < dS.size(); ++i) {
802 out_dS << r[i] << " " << dS[i] << endl;
803 }
804
805 out_dS.close();
806 cout << "written " << name_dS << endl;
807
808 // write the correlations
809 ofstream out_cor;
810 string name_cor = grp_name + suffix + ".cor";
811 out_cor.open(name_cor);
812 out_cor << setprecision(8);
813
814 if (!out_cor) {
815 throw runtime_error(string("error, cannot open file ") + name_cor);
816 }
817
818 for (votca::Index i = 0; i < grp->corr_.rows(); ++i) {
819 for (votca::Index j = 0; j < grp->corr_.cols(); ++j) {
820 out_cor << grp->corr_(i, j) << " ";
821 }
822 out_cor << endl;
823 }
824 out_cor.close();
825 cout << "written " << name_cor << endl;
826 }
827}
828
829std::unique_ptr<CsgApplication::Worker> Imc::ForkWorker() {
830
831 auto worker = std::make_unique<Imc::Worker>();
832 worker->current_hists_.resize(interactions_.size());
833 worker->current_hists_force_.resize(interactions_.size());
834 worker->imc_ = this;
835
836 for (auto &interaction : interactions_) {
837 auto &i = interaction.second;
838 worker->current_hists_[i->index_].Initialize(
839 i->average_.getMin(), i->average_.getMax(), i->average_.getNBins());
840 // preliminary
841 if (interaction.second->force_) {
842 worker->current_hists_force_[i->index_].Initialize(
843 i->average_force_.getMin(), i->average_force_.getMax(),
844 i->average_force_.getNBins());
845 }
846 }
847 return worker;
848}
849
852 Imc::Worker *worker = dynamic_cast<Imc::Worker *>(worker_);
853 // update the average
854 map<string, interaction_t *>::iterator ic_iter;
855 // map<string, group_t *>::iterator group_iter;
856
857 ++nframes_;
858 avg_vol_.Process(worker->cur_vol_);
859 for (auto &interaction : interactions_) {
860 auto &i = interaction.second;
861 i->average_.data().y() =
862 (((double)nframes_ - 1.0) * i->average_.data().y() +
863 worker->current_hists_[i->index_].data().y()) /
864 (double)nframes_;
865 // preliminary
866 if (i->force_) {
867 i->average_force_.data().y() =
868 (((double)nframes_ - 1.0) * i->average_force_.data().y() +
869 worker->current_hists_force_[i->index_].data().y()) /
870 (double)nframes_;
871 }
872 }
873
874 // update correlation matrices
875 if (do_imc_) {
876 DoCorrelations(worker);
877 }
878
879 if (block_length_ != 0) {
880 if ((nframes_ % block_length_) == 0) {
881 nblock_++;
882 string suffix = string("_") + boost::lexical_cast<string>(nblock_) +
883 string(".") + extension_;
884 WriteDist(suffix);
885 WriteIMCData(suffix);
886 WriteIMCBlock(suffix);
888 }
889 }
890}
891
892} // namespace csg
893} // namespace votca
Index Generate(Topology &top, const std::string &select)
Select all beads of type "select".
Definition beadlist.cc:30
Index size() const
Definition beadlist.h:52
information about a bead
Definition bead.h:50
Worker, derived from Thread, does the work.
bool FoundPair(Bead *, Bead *, const Eigen::Vector3d &, const double dist)
votca::tools::HistogramNew & hist_
bool FoundPair(Bead *b1, Bead *, const Eigen::Vector3d &, const double dist)
IMCNBSearchHandler(votca::tools::HistogramNew *hist)
void EvalConfiguration(Topology *top, Topology *top_atom) override
evaluate current conformation
std::vector< tools::HistogramNew > current_hists_
void DoNonbonded(Topology *top)
process non-bonded interactions for given frame
std::vector< tools::HistogramNew > current_hists_force_
void DoBonded(Topology *top)
process bonded interactions for given frame
Eigen::MatrixXd group_matrix
interaction_t * AddInteraction(tools::Property *p, bool is_bonded)
create a new interaction entry based on given options
votca::Index block_length_
std::unique_ptr< CsgApplication::Worker > ForkWorker()
void WriteIMCData(const std::string &suffix="")
void EndEvaluate()
end coarse graining a trajectory
tools::Average< double > avg_vol_
tools::Property options_
the options parsed from cg definition file
void InitializeGroups()
initializes the group structs after interactions were added
std::map< std::string, std::unique_ptr< group_t > > groups_
map group-name to group
std::vector< tools::Property * > nonbonded_
list of non-bonded interactions
std::string extension_
std::map< std::string, std::unique_ptr< interaction_t > > interactions_
map interaction-name to interaction
votca::Index nblock_
void MergeWorker(CsgApplication::Worker *worker_)
void DoCorrelations(Imc::Worker *worker)
update the correlations after interations were processed
void Initialize(void)
bool processed_some_frames_
votca::Index nframes_
std::vector< tools::Property * > bonded_
list of bonded interactions
void WriteDist(const std::string &suffix="")
void BeginEvaluate(Topology *top, Topology *top_atom)
begin coarse graining a trajectory
void CalcDeltaS(interaction_t *interaction, Eigen::VectorBlock< Eigen::VectorXd > &dS)
void WriteIMCBlock(const std::string &suffix)
void LoadOptions(const std::string &file)
load cg definitions file
Eigen::Block< group_matrix > pair_matrix
group_t * getGroup(const std::string &name)
get group by name, creates one if it doesn't exist
base class for all interactions
Definition interaction.h:40
topology of the whole system
Definition topology.h:81
std::vector< Interaction * > InteractionsInGroup(const std::string &group)
Definition topology.cc:201
double ShortestBoxSize() const
return the shortest box size
Definition topology.cc:268
double BoxVolume() const
Definition topology.cc:248
void Process(const T &value)
Definition average.h:48
const T & getAvg() const
Definition average.h:83
class to generate histograms
double getMax() const
get the upper bound of the histogram intervaö
Index getNBins() const
Get number of grid points.
Table & data()
get access to content of histogram
void Initialize(double min, double max, Index nbins)
Initialize the HistogramNew.
void Process(const double &v, double scale=1.0)
process a data point
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
T as() const
return value as type
Definition property.h:283
T ifExistsReturnElseReturnDefault(const std::string &key, T defaultvalue) const
Definition property.h:321
std::vector< Property * > Select(const std::string &filter)
select property based on a filter
Definition property.cc:185
void LoadFromXML(std::string filename)
Definition property.cc:238
void Add(Index begin, Index end, Index stride=1)
Definition rangeparser.h:86
class to store tables like rdfs, tabulated potentials, etc
Definition table.h:36
double & x(Index i)
Definition table.h:44
void Load(std::string filename)
Definition table.cc:47
void resize(Index N)
Definition table.cc:38
double & y(Index i)
Definition table.h:45
void Save(std::string filename) const
Definition table.cc:59
STL namespace.
void imcio_write_dS(const std::string &file, const tools::Table &dS, const std::list< Index > *list=nullptr)
Definition imcio.cc:42
void imcio_write_index(const std::string &file, const std::vector< std::pair< std::string, tools::RangeParser > > &ranges)
Definition imcio.cc:95
void imcio_write_matrix(const std::string &file, const Eigen::MatrixXd &gmc, const std::list< Index > *list=nullptr)
Definition imcio.cc:66
base class for all analysis tools
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26
struct to store collected information for groups (e.g. crosscorrelations)
std::vector< interaction_t * > interactions_
struct to store collected information for interactions
tools::HistogramNew average_
tools::HistogramNew average_force_