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 "BasisFunctions.h"
24 : #include "TargetDistribution.h"
25 :
26 : #include "CoeffsVector.h"
27 : #include "VesTools.h"
28 :
29 : #include "core/ActionRegister.h"
30 : #include "core/ActionSet.h"
31 : #include "core/PlumedMain.h"
32 : #include "core/Value.h"
33 : #include "tools/File.h"
34 : #include "tools/Grid.h"
35 :
36 :
37 : namespace PLMD {
38 : namespace ves {
39 :
40 : //+PLUMEDOC VES_UTILS VES_OUTPUT_BASISFUNCTIONS
41 : /*
42 : Output basis functions to file.
43 :
44 : This action can be used to write out to a grid file the values and derivatives of
45 : given basis functions. This is normally used for debugging when programming new
46 : types of basis functions. For example, it is possible to calculate the
47 : derivatives numerically and compare to the analytically calculated
48 : derivatives.
49 :
50 : This action is normally used through the \ref driver.
51 :
52 : \par Examples
53 :
54 : In the following input we define a Legendre polynomials basis functions
55 : of order 14 over the interval -4.0 to 4.0 and output their values
56 : and derivatives to files called bfL.values.data and bfL.derivs.data.
57 : \plumedfile
58 : BF_LEGENDRE ...
59 : ORDER=14
60 : MINIMUM=-4.0
61 : MAXIMUM=4.0
62 : LABEL=bfL
63 : ... BF_LEGENDRE
64 :
65 : VES_OUTPUT_BASISFUNCTIONS ...
66 : BASIS_FUNCTIONS=bfL
67 : GRID_BINS=200
68 : FORMAT_VALUES_DERIVS=%13.6f
69 : ... VES_OUTPUT_BASISFUNCTIONS
70 : \endplumedfile
71 :
72 : This input should be run through the driver by using a command similar to the
73 : following one where the trajectory/configuration file configuration.gro is needed to
74 : trick the code to exit correctly.
75 : \verbatim
76 : plumed driver --plumed plumed.dat --igro configuration.gro
77 : \endverbatim
78 :
79 : */
80 : //+ENDPLUMEDOC
81 :
82 :
83 249 : class OutputBasisFunctions :
84 : public Action
85 : {
86 : std::vector<BasisFunctions*> bf_pntrs;
87 : public:
88 : explicit OutputBasisFunctions(const ActionOptions&);
89 : TargetDistribution* setupTargetDistPntr(std::string keyword) const;
90 0 : void calculate() {}
91 0 : void apply() {}
92 : static void registerKeywords(Keywords& keys);
93 : };
94 :
95 :
96 7998 : PLUMED_REGISTER_ACTION(OutputBasisFunctions,"VES_OUTPUT_BASISFUNCTIONS")
97 :
98 84 : void OutputBasisFunctions::registerKeywords(Keywords& keys) {
99 84 : Action::registerKeywords(keys);
100 336 : keys.add("compulsory","BASIS_FUNCTIONS","the label of the basis functions that you want to use");
101 336 : keys.add("optional","GRID_BINS","the number of bins used for the grid for writing the basis function values and derivatives. The default value is 1000.");
102 336 : keys.add("optional","GRID_MIN","the minimum of the grid for writing the basis function values and derivatives. By default it is the minimum of the interval on which the basis functions are defined.");
103 336 : keys.add("optional","GRID_MAX","the maximum of the grid for writing the basis function values and derivatives. By default it is the maximum of the interval on which the basis functions are defined.");
104 336 : keys.add("optional","FILE_VALUES","filename of the file on which the basis function values are written. By default it is BF_LABEL.values.data.");
105 336 : keys.add("optional","FILE_DERIVS","filename of the file on which the basis function derivatives are written. By default it is BF_LABEL.derivs.data.");
106 336 : keys.add("optional","FORMAT_VALUES_DERIVS","the numerical format of the basis function values and derivatives written to file. By default it is %15.8f.\n");
107 336 : keys.add("optional","FILE_TARGETDIST_AVERAGES","filename of the file on which the averages over the target distributions are written. By default it is BF_LABEL.targetdist-averages.data.");
108 336 : keys.add("optional","FORMAT_TARGETDIST_AVERAGES","the numerical format of the target distribution averages written to file. By default it is %15.8f.\n");
109 336 : keys.add("optional","FILE_INNER_PRODUCTS","filename of the file on which the inner products of the basis functions are written. By default it is BF_LABEL.inner-products.data.");
110 336 : keys.add("optional","FORMAT_INNER_PRODUCTS","the numerical format of the inner products of the basis functions written to file. By default it is %15.8f.\n");
111 336 : keys.add("optional","FILE_TARGETDIST","filename of the files on which the target distributions are written. By default it is BF_LABEL.targetdist-#.data.");
112 336 : keys.add("numbered","TARGET_DISTRIBUTION","the target distribution to be used.");
113 252 : keys.addFlag("IGNORE_PERIODICITY",false,"if the periodicity of the basis functions should be ignored.");
114 252 : keys.addFlag("NUMERICAL_DERIVATIVES",false,"if the derivatives of the basis functions should be calculated numerically.");
115 84 : }
116 :
117 83 : OutputBasisFunctions::OutputBasisFunctions(const ActionOptions&ao):
118 : Action(ao),
119 83 : bf_pntrs(0)
120 : {
121 83 : std::vector<std::string> basisset_labels(0);
122 166 : parseVector("BASIS_FUNCTIONS",basisset_labels);
123 83 : if(basisset_labels.size()>1) {plumed_merror("Only one basis set label allowed in keyword BASIS_FUNCTIONS of "+getName());}
124 :
125 83 : std::string error_msg = "";
126 249 : bf_pntrs = VesTools::getPointersFromLabels<BasisFunctions*>(basisset_labels,plumed.getActionSet(),error_msg);
127 83 : if(error_msg.size()>0) {plumed_merror("Error in keyword BASIS_FUNCTIONS of "+getName()+": "+error_msg);}
128 :
129 83 : unsigned int nbins = 1000;
130 166 : parse("GRID_BINS",nbins);
131 :
132 83 : std::string min_str = bf_pntrs[0]->intervalMinStr();
133 83 : std::string max_str = bf_pntrs[0]->intervalMaxStr();
134 166 : parse("GRID_MIN",min_str);
135 166 : parse("GRID_MAX",max_str);
136 :
137 83 : std::string fname_values = bf_pntrs[0]->getLabel()+".values.data";
138 166 : parse("FILE_VALUES",fname_values);
139 83 : std::string fname_derives = bf_pntrs[0]->getLabel()+".derivs.data";
140 166 : parse("FILE_DERIVS",fname_derives);
141 83 : std::string fname_targetdist_aver = bf_pntrs[0]->getLabel()+".targetdist-averages.data";
142 166 : parse("FILE_TARGETDIST_AVERAGES",fname_targetdist_aver);
143 83 : std::string fname_targetdist = bf_pntrs[0]->getLabel()+".targetdist-.data";
144 166 : parse("FILE_TARGETDIST",fname_targetdist);
145 83 : std::string fname_innerproducts = bf_pntrs[0]->getLabel()+".inner-products.data";
146 166 : parse("FILE_INNER_PRODUCTS",fname_innerproducts);
147 :
148 83 : std::string fmt_values_derivs = "%15.8f";
149 166 : parse("FORMAT_VALUES_DERIVS",fmt_values_derivs);
150 83 : std::string fmt_targetdist_aver = "%15.8f";
151 166 : parse("FORMAT_TARGETDIST_AVERAGES",fmt_targetdist_aver);
152 83 : std::string fmt_innerproducts = "%15.8f";
153 166 : parse("FORMAT_INNER_PRODUCTS",fmt_innerproducts);
154 :
155 :
156 :
157 83 : bool ignore_periodicity = false;
158 166 : parseFlag("IGNORE_PERIODICITY",ignore_periodicity);
159 :
160 83 : bool numerical_deriv = false;
161 166 : parseFlag("NUMERICAL_DERIVATIVES",numerical_deriv);
162 :
163 : std::vector<TargetDistribution*> targetdist_pntrs;
164 166 : targetdist_pntrs.push_back(NULL);
165 83 : std::string targetdist_label="";
166 150 : for(int i=1;; i++) {
167 466 : if(!parseNumbered("TARGET_DISTRIBUTION",i,targetdist_label)) {break;}
168 150 : std::string error_msg = "";
169 300 : TargetDistribution* pntr_tmp = VesTools::getPointerFromLabel<TargetDistribution*>(targetdist_label,plumed.getActionSet(),error_msg);
170 150 : if(error_msg.size()>0) {plumed_merror("Error in keyword TARGET_DISTRIBUTION of "+getName()+": "+error_msg);}
171 150 : targetdist_pntrs.push_back(pntr_tmp);
172 150 : }
173 83 : checkRead();
174 : //
175 166 : OFile ofile_values;
176 83 : ofile_values.link(*this);
177 83 : ofile_values.enforceBackup();
178 83 : ofile_values.open(fname_values);
179 166 : OFile ofile_derivs;
180 83 : ofile_derivs.link(*this);
181 83 : ofile_derivs.enforceBackup();
182 83 : ofile_derivs.open(fname_derives);
183 166 : bf_pntrs[0]->writeBasisFunctionsToFile(ofile_values,ofile_derivs,min_str,max_str,nbins,ignore_periodicity,fmt_values_derivs,numerical_deriv);
184 83 : ofile_values.close();
185 83 : ofile_derivs.close();
186 : //
187 166 : OFile ofile_innerproducts;
188 83 : ofile_innerproducts.link(*this);
189 83 : ofile_innerproducts.enforceBackup();
190 83 : ofile_innerproducts.open(fname_innerproducts);
191 83 : bf_pntrs[0]->writeInnerProductsToFiles(ofile_innerproducts,fmt_innerproducts);
192 83 : ofile_innerproducts.close();
193 : //
194 332 : std::vector<std::string> grid_min(1); grid_min[0]=bf_pntrs[0]->intervalMinStr();
195 332 : std::vector<std::string> grid_max(1); grid_max[0]=bf_pntrs[0]->intervalMaxStr();
196 166 : std::vector<unsigned int> grid_bins(1); grid_bins[0]=nbins;
197 83 : std::vector<Value*> arguments(1);
198 249 : arguments[0]= new Value(NULL,"arg",false);
199 166 : if(bf_pntrs[0]->arePeriodic() && !ignore_periodicity) {
200 72 : arguments[0]->setDomain(bf_pntrs[0]->intervalMinStr(),bf_pntrs[0]->intervalMaxStr());
201 : }
202 : else {
203 65 : arguments[0]->setNotPeriodic();
204 : }
205 :
206 166 : OFile ofile_targetdist_aver;
207 83 : ofile_targetdist_aver.link(*this);
208 83 : ofile_targetdist_aver.enforceBackup();
209 83 : ofile_targetdist_aver.open(fname_targetdist_aver);
210 :
211 549 : for(unsigned int i=0; i<targetdist_pntrs.size(); i++) {
212 233 : std::string is; Tools::convert(i,is);
213 : //
214 233 : if(targetdist_pntrs[i]!=NULL) {
215 150 : targetdist_pntrs[i]->setupGrids(arguments,grid_min,grid_max,grid_bins);
216 300 : plumed_massert(targetdist_pntrs[i]->getDimension()==1,"the target distribution must be one dimensional");
217 150 : targetdist_pntrs[i]->updateTargetDist();
218 : }
219 : //
220 466 : std::vector<double> bf_integrals = bf_pntrs[0]->getTargetDistributionIntegrals(targetdist_pntrs[i]);
221 699 : CoeffsVector targetdist_averages = CoeffsVector("aver.targetdist-"+is,arguments,bf_pntrs,comm,false);
222 233 : targetdist_averages.setValues(bf_integrals);
223 233 : if(fmt_targetdist_aver.size()>0) {targetdist_averages.setOutputFmt(fmt_targetdist_aver);}
224 233 : targetdist_averages.writeToFile(ofile_targetdist_aver,true);
225 233 : if(targetdist_pntrs[i]!=NULL) {
226 : Grid* targetdist_grid_pntr = targetdist_pntrs[i]->getTargetDistGridPntr();
227 150 : std::string fname = FileBase::appendSuffix(fname_targetdist,is);
228 300 : OFile ofile;
229 150 : ofile.link(*this);
230 150 : ofile.enforceBackup();
231 150 : ofile.open(fname);
232 150 : targetdist_grid_pntr->writeToFile(ofile);
233 150 : ofile.close();
234 : }
235 : }
236 83 : ofile_targetdist_aver.close();
237 166 : delete arguments[0]; arguments.clear();
238 :
239 :
240 :
241 83 : }
242 :
243 :
244 :
245 : }
246 5874 : }
|