votca 2025.1-dev
Loading...
Searching...
No Matches
csg_stat_imc.cc
Go to the documentation of this file.
1/*
2 * Copyright 2009-2025 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
288class IMCNBSearchHandler {
289 public:
291
293
294 bool FoundPair(Bead *, Bead *, const Eigen::Vector3d &, const double dist) {
295 hist_.Process(dist);
296 return false;
297 }
298};
299
300// process non-bonded interactions for current frame
302 for (tools::Property *prop : imc_->nonbonded_) {
303 string name = prop->get("name").value();
304
305 interaction_t &i = *imc_->interactions_[name];
306
307 // clear the current histogram
308 current_hists_[i.index_].Clear();
309 current_hists_force_[i.index_].Clear();
310
311 bool gridsearch = true;
312
313 if (imc_->options_.exists("cg.nbsearch")) {
314 if (imc_->options_.get("cg.nbsearch").as<string>() == "grid") {
315 gridsearch = true;
316 } else if (imc_->options_.get("cg.nbsearch").as<string>() == "simple") {
317 gridsearch = false;
318 } else {
319 throw std::runtime_error("cg.nbsearch invalid, can be grid or simple");
320 }
321 }
322
323 // Preleminary: Quickest way to incorporate 3 body correlations
324 if (i.threebody_) {
325
326 // generate the bead lists
327 BeadList beads1, beads2, beads3;
328
329 beads1.Generate(*top, prop->get("type1").value());
330 beads2.Generate(*top, prop->get("type2").value());
331 beads3.Generate(*top, prop->get("type3").value());
332
333 // generate the neighbour list
334 std::unique_ptr<NBList_3Body> nb;
335
336 if (gridsearch) {
337 nb = std::unique_ptr<NBList_3Body>(new NBListGrid_3Body());
338 } else {
339 nb = std::make_unique<NBList_3Body>();
340 }
341
342 nb->setCutoff(i.cut_); // implement different cutoffs for different
343 // interactions!
344 // Here, a is the distance between two beads of a triple, where the 3-body
345 // interaction is zero
346
347 // check if type2 and type3 are the same
348 if (prop->get("type2").value() == prop->get("type3").value()) {
349 // if then type2 and type1 are the same, all three types are the same
350 // use the Generate function for this case
351 if (prop->get("type1").value() == prop->get("type2").value()) {
352 nb->Generate(beads1, true);
353 }
354 // else use the Generate function for type2 being equal to type3 (and
355 // type1 being different)
356 if (prop->get("type1").value() != prop->get("type2").value()) {
357 nb->Generate(beads1, beads2, true);
358 }
359 }
360 // If type2 and type3 are not the same, use the Generate function for
361 // three different bead types (Even if type1 and type2 or type1 and type3
362 // are the same, the Generate function for two different beadtypes is only
363 // applicable for the case that type2 is equal to type3
364 if (prop->get("type2").value() != prop->get("type3").value()) {
365 nb->Generate(beads1, beads2, beads3, true);
366 }
367
368 for (auto &triple : *nb) {
369 Eigen::Vector3d rij = triple->r12();
370 Eigen::Vector3d rik = triple->r13();
371 double var = std::acos(rij.dot(rik) /
372 sqrt(rij.squaredNorm() * rik.squaredNorm()));
373 current_hists_[i.index_].Process(var);
374 }
375 }
376 // 2body interaction
377 if (!i.threebody_) {
378
379 // generate the bead lists
380 BeadList beads1, beads2;
381
382 beads1.Generate(*top, prop->get("type1").value());
383 beads2.Generate(*top, prop->get("type2").value());
384
385 {
386 // generate the neighbour list
387 std::unique_ptr<NBList> nb;
388 if (gridsearch) {
389 nb = std::unique_ptr<NBList>(new NBListGrid());
390 } else {
391 nb = std::unique_ptr<NBList>(new NBListGrid());
392 }
393
394 nb->setCutoff(i.max_ + i.step_);
395
397
398 nb->SetMatchFunction(&h, &IMCNBSearchHandler::FoundPair);
399
400 // is it same types or different types?
401 if (prop->get("type1").value() == prop->get("type2").value()) {
402 nb->Generate(beads1, !(imc_->include_intra_));
403 } else {
404 nb->Generate(beads1, beads2, !(imc_->include_intra_));
405 }
406 }
407
408 // if one wants to calculate the mean force
409 if (i.force_) {
410 std::unique_ptr<NBList> nb_force;
411 if (gridsearch) {
412 nb_force = std::unique_ptr<NBList>(new NBListGrid());
413 } else {
414 nb_force = std::unique_ptr<NBList>(new NBListGrid());
415 }
416
417 nb_force->setCutoff(i.max_ + i.step_);
418
419 // is it same types or different types?
420 if (prop->get("type1").value() == prop->get("type2").value()) {
421 nb_force->Generate(beads1);
422 } else {
423 nb_force->Generate(beads1, beads2);
424 }
425
426 // process all pairs to calculate the projection of the
427 // mean force on bead 1 on the pair distance: F1 * r12
428 for (auto &pair : *nb_force) {
429 Eigen::Vector3d F2 = pair->second()->getF();
430 Eigen::Vector3d F1 = pair->first()->getF();
431 Eigen::Vector3d r12 = pair->r();
432 r12.normalize();
433 double var = pair->dist();
434 double scale = 0.5 * (F2 - F1).dot(r12);
435 current_hists_force_[i.index_].Process(var, scale);
436 }
437 }
438 }
439 }
440}
441
442// process non-bonded interactions for current frame
444 for (tools::Property *prop : imc_->bonded_) {
445 string name = prop->get("name").value();
446
447 interaction_t &i = *imc_->interactions_[name];
448
449 // clear the current histogram
450 current_hists_[i.index_].Clear();
451
452 // now fill with new data
453 for (Interaction *ic : top->InteractionsInGroup(name)) {
454 double v = ic->EvaluateVar(*top);
455 current_hists_[i.index_].Process(v);
456 }
457 }
458}
459
460// returns a group, creates it if doesn't exist
461Imc::group_t *Imc::getGroup(const string &name) {
462 map<string, std::unique_ptr<group_t> >::iterator iter;
463 iter = groups_.find(name);
464 if (iter == groups_.end()) {
465 auto success =
466 groups_.insert(std::make_pair(name, std::make_unique<group_t>()));
467 return success.first->second.get();
468 }
469 return (*iter).second.get();
470}
471
472// initialize the groups after interactions are added
474 if (!do_imc_) {
475 return;
476 }
477 map<string, group_t *>::iterator group_iter;
478
479 // clear all the pairs
480
481 // iterator over all groups
482 for (auto &group : groups_) {
483 auto &grp = group.second;
484 grp->pairs_.clear();
485
486 auto &interactions = grp->interactions_;
487 // count number of bins needed in matrix
488 votca::Index n = std::accumulate(interactions.begin(), interactions.end(),
489 0, [](votca::Index j, interaction_t *i) {
490 return j + i->average_.getNBins();
491 });
492
493 // handy access to matrix
494 group_matrix &M = grp->corr_;
495
496 // initialize matrix with zeroes
497 M = Eigen::MatrixXd::Zero(n, n);
498
499 // now create references to the sub matrices and offsets
500 votca::Index offset_i = 0;
501 votca::Index offset_j = 0;
502 // iterate over all possible cominations of pairs
503 for (votca::Index i = 0; i < votca::Index(interactions.size()); i++) {
504 votca::Index n1 = interactions[i]->average_.getNBins();
505 offset_j = offset_i;
506 for (votca::Index j = i; j < votca::Index(interactions.size()); j++) {
507 votca::Index n2 = interactions[j]->average_.getNBins();
508 // create matrix proxy with sub-matrix
509 pair_matrix corr = M.block(offset_i, offset_j, n1, n2);
510 // add the pair
511 grp->pairs_.push_back(
512 pair_t(interactions[i], interactions[j], offset_i, offset_j, corr));
513 offset_j += n2;
514 }
515 offset_i += n1;
516 }
517 }
518}
519
520// update the correlation matrix
522 if (!do_imc_) {
523 return;
524 }
525
526 for (auto &group : groups_) {
527 auto &grp = group.second;
528 // update correlation for all pairs
529 for (auto &pair : grp->pairs_) {
530 Eigen::VectorXd &a = worker->current_hists_[pair.i1_->index_].data().y();
531 Eigen::VectorXd &b = worker->current_hists_[pair.i2_->index_].data().y();
532 pair_matrix &M = pair.corr_;
533
534 M = ((((double)nframes_ - 1.0) * M) + a * b.transpose()) /
535 (double)nframes_;
536 }
537 }
538}
539
540// write the distribution function
541void Imc::WriteDist(const string &suffix) {
542 map<string, interaction_t *>::iterator iter;
543
544 cout << std::endl; // Cosmetic, put \n before printing names of distribution
545 // files.
546 // for all interactions
547 for (auto &pair : interactions_) {
548 // calculate the rdf
549 auto &interaction = pair.second;
550 votca::tools::Table &t = interaction->average_.data();
551
552 // if no average force calculation, dummy table
554 // if average force calculation, table force contains force data
555 if (interaction->force_) {
556 force = interaction->average_force_.data();
557 }
558
559 votca::tools::Table dist(t);
560 if (!interaction->is_bonded_) {
561 // Quickest way to incorporate 3 body correlations
562 if (interaction->threebody_) {
563 // \TODO normalize bond and angle differently....
564 double norm = dist.y().cwiseAbs().sum();
565 if (norm > 0) {
566 dist.y() =
567 interaction->norm_ * dist.y() / (norm * interaction->step_);
568 }
569 }
570
571 // 2body
572 if (!interaction->threebody_) {
573 // force normalization
574 // normalize by number of pairs found at a specific distance
575 for (votca::Index i = 0; i < force.y().size(); ++i) {
576 // check if any number of pairs has been found at this distance, then
577 // normalize
578 if (dist.y()[i] != 0) {
579 force.y()[i] /= dist.y()[i];
580 }
581 // else set to zero
582 else {
583 force.y()[i] = 0;
584 }
585 }
586
587 // normalization is calculated using exact shell volume (difference of
588 // spheres)
589 for (votca::Index i = 0; i < dist.y().size(); ++i) {
590 double x1 = dist.x()[i] - 0.5 * interaction->step_;
591 double x2 = x1 + interaction->step_;
592 if (x1 < 0) {
593 dist.y()[i] = 0;
594 } else {
595 dist.y()[i] = avg_vol_.getAvg() * interaction->norm_ * dist.y()[i] /
596 (4. / 3. * M_PI * (x2 * x2 * x2 - x1 * x1 * x1));
597 }
598 }
599 }
600
601 } else {
602 // \TODO normalize bond and angle differently....
603 double norm = dist.y().cwiseAbs().sum();
604 if (norm > 0) {
605 dist.y() = interaction->norm_ * dist.y() / (norm * interaction->step_);
606 }
607 }
608
609 dist.Save((pair.first) + suffix);
610 cout << "written " << (pair.first) + suffix << "\n";
611
612 // preliminary
613 if (interaction->force_) {
614 force.Save((pair.first) + ".force.new");
615 cout << "written " << (pair.first) + ".force.new" << "\n";
616 }
617 }
618}
619
626void Imc::WriteIMCData(const string &suffix) {
627 if (!do_imc_) {
628 return;
629 }
630 // map<string, interaction_t *>::iterator ic_iter;
631 map<string, group_t *>::iterator group_iter;
632
633 // iterate over all groups
634 for (auto &group : groups_) {
635 auto &grp = group.second;
636 string grp_name = group.first;
637
638 // number of total bins for all interactions in group is matrix dimension
639 votca::Index n = grp->corr_.rows();
640
641 // build full set of equations + copy some data to make
642 // code better to read
643 group_matrix gmc(grp->corr_);
644 tools::Table dS;
645 dS.resize(n);
646 // the next two variables are to later extract the individual parts
647 // from the whole data after solving equations
648 vector<std::pair<std::string, votca::tools::RangeParser> >
649 ranges; // names of the interactions & sizes of the individual
650 // interactions
651
652 // copy all averages+r of group to one vector
653 n = 0;
654 votca::Index begin = 1;
655 for (interaction_t *ic : grp->interactions_) {
656
657 // sub vector for dS
658 Eigen::VectorBlock<Eigen::VectorXd> sub_dS =
659 dS.y().segment(n, ic->average_.getNBins());
660
661 // sub vector for r
662 Eigen::VectorBlock<Eigen::VectorXd> sub_r =
663 dS.x().segment(n, ic->average_.getNBins());
664
665 // read in target and calculate dS
666 CalcDeltaS(ic, sub_dS);
667
668 // copy r
669 sub_r = ic->average_.data().x();
670
671 // save size
673 votca::Index end = begin + ic->average_.getNBins() - 1;
674 rp.Add(begin, end);
675 ranges.push_back(std::pair<std::string, votca::tools::RangeParser>(
676 ic->p_->get("name").as<string>(), rp));
677 begin = end + 1;
678 // save name
679
680 // shift subrange by size of current
681 n += ic->average_.getNBins();
682 }
683
684 // now we need to calculate the
685 // A_ij = <S_i*S_j> - <S_i>*<S_j>
686 for (pair_t &pair : grp->pairs_) {
687 interaction_t *i1 = pair.i1_;
688 interaction_t *i2 = pair.i2_;
689
690 // make reference to <S_i>
691 Eigen::VectorXd &a = i1->average_.data().y();
692 // make reference to <S_j>
693 Eigen::VectorXd &b = i2->average_.data().y();
694
695 votca::Index i = pair.offset_i_;
696 votca::Index j = pair.offset_j_;
697 votca::Index n1 = i1->average_.getNBins();
698 votca::Index n2 = i2->average_.getNBins();
699
700 pair_matrix M = gmc.block(i, j, n1, n2);
701 M = -(M - a * b.transpose());
702 // matrix is symmetric
703 gmc.block(j, i, n2, n1) = M.transpose().eval();
704 }
705
706 imcio_write_dS(grp_name + suffix + ".imc", dS);
707 imcio_write_matrix(grp_name + suffix + ".gmc", gmc);
708 imcio_write_index(grp_name + suffix + ".idx", ranges);
709 }
710}
711
712// calculate deviation from target vectors
714 Eigen::VectorBlock<Eigen::VectorXd> &dS) {
715 const string &name = interaction->p_->get("name").as<string>();
716
717 tools::Table target;
718 target.Load(name + ".dist.tgt");
719
720 if (!interaction->is_bonded_) {
721 for (votca::Index i = 0; i < target.y().size(); ++i) {
722 double x1 = target.x()[i] - 0.5 * interaction->step_;
723 double x2 = x1 + interaction->step_;
724 if (x1 < 0) {
725 x1 = x2 = 0;
726 }
727 target.y()[i] = 1. / (avg_vol_.getAvg() * interaction->norm_) *
728 target.y()[i] *
729 (4. / 3. * M_PI * (x2 * x2 * x2 - x1 * x1 * x1));
730 }
731 } else {
732 target.y() = (1.0 / interaction->norm_) * target.y();
733 }
734 if (target.y().size() != interaction->average_.data().y().size()) {
735 throw std::runtime_error(
736 "number of grid points in target does not match the grid");
737 }
738
739 dS = interaction->average_.data().y() - target.y();
740}
741
742void Imc::WriteIMCBlock(const string &suffix) {
743
744 if (!do_imc_) {
745 return;
746 }
747
748 // iterate over all groups
749 for (auto &group : groups_) {
750 auto &grp = group.second;
751 string grp_name = group.first;
752 list<interaction_t *>::iterator iter;
753
754 // number of total bins for all interactions in group is matrix dimension
755 votca::Index n = grp->corr_.rows();
756
757 // build full set of equations + copy some data to make code better to read
758 group_matrix gmc(grp->corr_);
759 Eigen::VectorXd dS(n);
760 Eigen::VectorXd r(n);
761 // the next two variables are to later extract the individual parts
762 // from the whole data after solving equations
763 vector<votca::Index> sizes; // sizes of the individual interactions
764 vector<string> names; // names of the interactions
765
766 // copy all averages+r of group to one vector
767 n = 0;
768 for (interaction_t *ic : grp->interactions_) {
769 // sub vector for dS
770 Eigen::VectorBlock<Eigen::VectorXd> sub_dS =
771 dS.segment(n, ic->average_.getNBins());
772
773 // sub vector for r
774 Eigen::VectorBlock<Eigen::VectorXd> sub_r =
775 r.segment(n, ic->average_.getNBins());
776
777 // read in target and calculate dS
778 sub_dS = ic->average_.data().y();
779 // copy r
780 sub_r = ic->average_.data().x();
781 // save size
782 sizes.push_back(ic->average_.getNBins());
783 // save name
784 names.push_back(ic->p_->get("name").as<string>());
785
786 // shift subrange by size of current
787 n += ic->average_.getNBins();
788 }
789
790 // write the dS
791 ofstream out_dS;
792 string name_dS = grp_name + suffix + ".S";
793 out_dS.open(name_dS);
794 out_dS << setprecision(8);
795 if (!out_dS) {
796 throw runtime_error(string("error, cannot open file ") + name_dS);
797 }
798
799 for (votca::Index i = 0; i < dS.size(); ++i) {
800 out_dS << r[i] << " " << dS[i] << endl;
801 }
802
803 out_dS.close();
804 cout << "written " << name_dS << endl;
805
806 // write the correlations
807 ofstream out_cor;
808 string name_cor = grp_name + suffix + ".cor";
809 out_cor.open(name_cor);
810 out_cor << setprecision(8);
811
812 if (!out_cor) {
813 throw runtime_error(string("error, cannot open file ") + name_cor);
814 }
815
816 for (votca::Index i = 0; i < grp->corr_.rows(); ++i) {
817 for (votca::Index j = 0; j < grp->corr_.cols(); ++j) {
818 out_cor << grp->corr_(i, j) << " ";
819 }
820 out_cor << endl;
821 }
822 out_cor.close();
823 cout << "written " << name_cor << endl;
824 }
825}
826
827std::unique_ptr<CsgApplication::Worker> Imc::ForkWorker() {
828
829 auto worker = std::make_unique<Imc::Worker>();
830 worker->current_hists_.resize(interactions_.size());
831 worker->current_hists_force_.resize(interactions_.size());
832 worker->imc_ = this;
833
834 for (auto &interaction : interactions_) {
835 auto &i = interaction.second;
836 worker->current_hists_[i->index_].Initialize(
837 i->average_.getMin(), i->average_.getMax(), i->average_.getNBins());
838 // preliminary
839 if (interaction.second->force_) {
840 worker->current_hists_force_[i->index_].Initialize(
841 i->average_force_.getMin(), i->average_force_.getMax(),
842 i->average_force_.getNBins());
843 }
844 }
845 return worker;
846}
847
850 Imc::Worker *worker = dynamic_cast<Imc::Worker *>(worker_);
851 // update the average
852 map<string, interaction_t *>::iterator ic_iter;
853 // map<string, group_t *>::iterator group_iter;
854
855 ++nframes_;
856 avg_vol_.Process(worker->cur_vol_);
857 for (auto &interaction : interactions_) {
858 auto &i = interaction.second;
859 i->average_.data().y() =
860 (((double)nframes_ - 1.0) * i->average_.data().y() +
861 worker->current_hists_[i->index_].data().y()) /
862 (double)nframes_;
863 // preliminary
864 if (i->force_) {
865 i->average_force_.data().y() =
866 (((double)nframes_ - 1.0) * i->average_force_.data().y() +
867 worker->current_hists_force_[i->index_].data().y()) /
868 (double)nframes_;
869 }
870 }
871
872 // update correlation matrices
873 if (do_imc_) {
874 DoCorrelations(worker);
875 }
876
877 if (block_length_ != 0) {
878 if ((nframes_ % block_length_) == 0) {
879 nblock_++;
880 string suffix = string("_") + boost::lexical_cast<string>(nblock_) +
881 string(".") + extension_;
882 WriteDist(suffix);
883 WriteIMCData(suffix);
884 WriteIMCBlock(suffix);
886 }
887 }
888}
889
890} // namespace csg
891} // 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)
bool FoundPair(Bead *b1, Bead *, const Eigen::Vector3d &, const double dist)
IMCNBSearchHandler(votca::tools::Histogram *hist)
std::vector< tools::Histogram > current_hists_force_
void EvalConfiguration(Topology *top, Topology *top_atom) override
evaluate current conformation
void DoNonbonded(Topology *top)
process non-bonded interactions for given frame
std::vector< tools::Histogram > current_hists_
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
class to generate histograms
Definition histogram.h:77
double getMax() const
get the upper bound of the histogram intervaö
Definition histogram.h:111
Table & data()
get access to content of histogram
Definition histogram.h:157
Index getNBins() const
Get number of grid points.
Definition histogram.h:117
void Initialize(double min, double max, Index nbins)
Initialize the Histogram.
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
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
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
Provides a means for comparing floating point numbers.
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::Histogram average_force_