Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2016-2018 The VES code team
3 : (see the PEOPLE-VES file at the root of this folder for a list of names)
4 :
5 : See http://www.ves-code.org for more information.
6 :
7 : This file is part of VES code module.
8 :
9 : The VES code module is free software: you can redistribute it and/or modify
10 : it under the terms of the GNU Lesser General Public License as published by
11 : the Free Software Foundation, either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : The VES code module is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU Lesser General Public License for more details.
18 :
19 : You should have received a copy of the GNU Lesser General Public License
20 : along with the VES code module. If not, see <http://www.gnu.org/licenses/>.
21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 :
23 : #include "TargetDistribution.h"
24 : #include "VesTools.h"
25 :
26 : #include "core/ActionRegister.h"
27 : #include "core/ActionSet.h"
28 : #include "core/PlumedMain.h"
29 : #include "tools/Grid.h"
30 :
31 : namespace PLMD {
32 : namespace ves {
33 :
34 : //+PLUMEDOC VES_TARGETDIST TD_PRODUCT_DISTRIBUTION
35 : /*
36 : Target distribution given by a separable product
37 : of one-dimensional distributions (static or dynamic).
38 :
39 : Employ a target distribution that is a separable product
40 : of one-dimensional distributions, defined as
41 : \f[
42 : p(\mathbf{s}) =
43 : \prod_{k}^{d} p_{k}(s_{k})
44 : \f]
45 : where \f$d\f$ is the number of arguments used and \f$p_{k}(s_{k})\f$ is the
46 : one-dimensional distribution corresponding to the \f$k\f$-th argument.
47 :
48 : Note the difference between this target distribution and the one defined in
49 : \ref TD_PRODUCT_COMBINATION. Here we have a separable distribution given as a
50 : product of one-dimensional distribution \f$p_{k}(s_{k})\f$.
51 :
52 : The labels of the one-dimensional distributions \f$p_{k}(s_{k})\f$ to be
53 : used in the product distribution are given in the DISTRIBUTIONS keyword.
54 : Note that the order of the labels is very important.
55 :
56 : It is assumed that all the distributions to be used in the product distribution
57 : are normalized. If that is not the case you need to
58 : normalize the distributions by using the NORMALIZE keyword.
59 : Here it does not matter if you normalize each distribution separately
60 : or the overall product, it will give the same results.
61 :
62 : The product distribution will be a dynamic target distribution if one or more
63 : of the distributions used is a dynamic distribution. Otherwise it will be a
64 : static distribution.
65 :
66 : \par Examples
67 :
68 : In the following example we employ a uniform distribution for
69 : argument 1 and a Gaussian distribution for argument 2.
70 : \plumedfile
71 : td_uni: TD_UNIFORM
72 :
73 : td_gauss: TD_GAUSSIAN CENTER=-2.0 SIGMA=0.5
74 :
75 : td_pd: TD_PRODUCT_DISTRIBUTION DISTRIBUTIONS=td_uni,td_gauss
76 : \endplumedfile
77 : Note that order of the labels is important, using DISTRIBUTIONS=td_gauss,td_uni
78 : would mean that we would employ a Gaussian distribution for argument 1 and a uniform
79 : distribution for argument 2, which would lead to completely different results.
80 :
81 : */
82 : //+ENDPLUMEDOC
83 :
84 45 : class TD_ProductDistribution: public TargetDistribution {
85 : private:
86 : std::vector<TargetDistribution*> distribution_pntrs_;
87 : std::vector<Grid*> grid_pntrs_;
88 : unsigned int ndist_;
89 : void setupAdditionalGrids(const std::vector<Value*>&, const std::vector<std::string>&, const std::vector<std::string>&, const std::vector<unsigned int>&);
90 : public:
91 : static void registerKeywords(Keywords&);
92 : explicit TD_ProductDistribution(const ActionOptions& ao);
93 : void updateGrid();
94 : double getValue(const std::vector<double>&) const;
95 : //
96 : void linkVesBias(VesBias*);
97 : void linkAction(Action*);
98 : void linkBiasGrid(Grid*);
99 : void linkBiasWithoutCutoffGrid(Grid*);
100 : void linkFesGrid(Grid*);
101 : };
102 :
103 :
104 6467 : PLUMED_REGISTER_ACTION(TD_ProductDistribution,"TD_PRODUCT_DISTRIBUTION")
105 :
106 :
107 16 : void TD_ProductDistribution::registerKeywords(Keywords& keys) {
108 16 : TargetDistribution::registerKeywords(keys);
109 64 : keys.add("compulsory","DISTRIBUTIONS","Labels of the one-dimensional target distribution actions for each argument to be used in the product distribution. Note that order of the labels is important.");
110 32 : keys.use("WELLTEMPERED_FACTOR");
111 32 : keys.use("SHIFT_TO_ZERO");
112 32 : keys.use("NORMALIZE");
113 16 : }
114 :
115 :
116 15 : TD_ProductDistribution::TD_ProductDistribution(const ActionOptions& ao):
117 : PLUMED_VES_TARGETDISTRIBUTION_INIT(ao),
118 : distribution_pntrs_(0),
119 : grid_pntrs_(0),
120 15 : ndist_(0)
121 : {
122 15 : std::vector<std::string> targetdist_labels;
123 30 : parseVector("DISTRIBUTIONS",targetdist_labels);
124 :
125 15 : std::string error_msg = "";
126 45 : distribution_pntrs_ = VesTools::getPointersFromLabels<TargetDistribution*>(targetdist_labels,plumed.getActionSet(),error_msg);
127 15 : if(error_msg.size()>0) {plumed_merror("Error in keyword DISTRIBUTIONS of "+getName()+": "+error_msg);}
128 :
129 120 : for(unsigned int i=0; i<distribution_pntrs_.size(); i++) {
130 60 : if(distribution_pntrs_[i]->isDynamic()) {setDynamic();}
131 60 : if(distribution_pntrs_[i]->fesGridNeeded()) {setFesGridNeeded();}
132 60 : if(distribution_pntrs_[i]->biasGridNeeded()) {setBiasGridNeeded();}
133 : }
134 :
135 15 : ndist_ = distribution_pntrs_.size();
136 30 : grid_pntrs_.assign(ndist_,NULL);
137 15 : setDimension(ndist_);
138 :
139 15 : checkRead();
140 15 : }
141 :
142 :
143 0 : double TD_ProductDistribution::getValue(const std::vector<double>& argument) const {
144 0 : plumed_merror("getValue not implemented for TD_ProductDistribution");
145 : return 0.0;
146 : }
147 :
148 :
149 15 : void TD_ProductDistribution::setupAdditionalGrids(const std::vector<Value*>& arguments, const std::vector<std::string>& min, const std::vector<std::string>& max, const std::vector<unsigned int>& nbins) {
150 75 : for(unsigned int i=0; i<ndist_; i++) {
151 30 : std::vector<Value*> arg1d(1);
152 60 : std::vector<std::string> min1d(1);
153 60 : std::vector<std::string> max1d(1);
154 30 : std::vector<unsigned int> nbins1d(1);
155 60 : arg1d[0]=arguments[i];
156 : min1d[0]=min[i];
157 : max1d[0]=max[i];
158 30 : nbins1d[0]=nbins[i];
159 30 : distribution_pntrs_[i]->setupGrids(arg1d,min1d,max1d,nbins1d);
160 60 : grid_pntrs_[i]=distribution_pntrs_[i]->getTargetDistGridPntr();
161 90 : if(distribution_pntrs_[i]->getDimension()!=1 || grid_pntrs_[i]->getDimension()!=1) {
162 0 : plumed_merror(getName() + ": all target distributions must be one dimensional");
163 : }
164 : }
165 15 : }
166 :
167 :
168 15 : void TD_ProductDistribution::updateGrid() {
169 75 : for(unsigned int i=0; i<ndist_; i++) {
170 60 : distribution_pntrs_[i]->updateTargetDist();
171 : }
172 306045 : for(Grid::index_t l=0; l<targetDistGrid().getSize(); l++) {
173 153015 : std::vector<unsigned int> indices = targetDistGrid().getIndices(l);
174 : double value = 1.0;
175 765075 : for(unsigned int i=0; i<ndist_; i++) {
176 918090 : value *= grid_pntrs_[i]->getValue(indices[i]);
177 : }
178 153015 : targetDistGrid().setValue(l,value);
179 153015 : logTargetDistGrid().setValue(l,-std::log(value));
180 : }
181 15 : logTargetDistGrid().setMinToZero();
182 15 : }
183 :
184 :
185 0 : void TD_ProductDistribution::linkVesBias(VesBias* vesbias_pntr_in) {
186 0 : TargetDistribution::linkVesBias(vesbias_pntr_in);
187 0 : for(unsigned int i=0; i<ndist_; i++) {
188 0 : distribution_pntrs_[i]->linkVesBias(vesbias_pntr_in);
189 : }
190 0 : }
191 :
192 :
193 0 : void TD_ProductDistribution::linkAction(Action* action_pntr_in) {
194 0 : TargetDistribution::linkAction(action_pntr_in);
195 0 : for(unsigned int i=0; i<ndist_; i++) {
196 0 : distribution_pntrs_[i]->linkAction(action_pntr_in);
197 : }
198 0 : }
199 :
200 :
201 0 : void TD_ProductDistribution::linkBiasGrid(Grid* bias_grid_pntr_in) {
202 0 : TargetDistribution::linkBiasGrid(bias_grid_pntr_in);
203 0 : for(unsigned int i=0; i<ndist_; i++) {
204 0 : distribution_pntrs_[i]->linkBiasGrid(bias_grid_pntr_in);
205 : }
206 0 : }
207 :
208 :
209 0 : void TD_ProductDistribution::linkBiasWithoutCutoffGrid(Grid* bias_withoutcutoff_grid_pntr_in) {
210 0 : TargetDistribution::linkBiasWithoutCutoffGrid(bias_withoutcutoff_grid_pntr_in);
211 0 : for(unsigned int i=0; i<ndist_; i++) {
212 0 : distribution_pntrs_[i]->linkBiasWithoutCutoffGrid(bias_withoutcutoff_grid_pntr_in);
213 : }
214 0 : }
215 :
216 :
217 0 : void TD_ProductDistribution::linkFesGrid(Grid* fes_grid_pntr_in) {
218 0 : TargetDistribution::linkFesGrid(fes_grid_pntr_in);
219 0 : for(unsigned int i=0; i<ndist_; i++) {
220 0 : distribution_pntrs_[i]->linkFesGrid(fes_grid_pntr_in);
221 : }
222 0 : }
223 :
224 :
225 : }
226 4839 : }
|