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 "CoeffsBase.h"
24 : #include "BasisFunctions.h"
25 : #include "VesBias.h"
26 :
27 : #include "tools/Tools.h"
28 : #include "tools/File.h"
29 : #include "tools/Exception.h"
30 : #include "core/Value.h"
31 :
32 : #include <vector>
33 : #include <string>
34 :
35 :
36 : namespace PLMD {
37 : namespace ves {
38 :
39 0 : CoeffsBase::CoeffsBase(
40 : const std::string& label,
41 : const std::vector<std::string>& dimension_labels,
42 : const std::vector<unsigned int>& indices_shape,
43 : const bool use_iteration_counter):
44 : label_(label),
45 : data_label_(label),
46 : coeffs_type_(Generic),
47 : iteration_and_time_active_(use_iteration_counter),
48 : iteration_opt(0),
49 : time_md(-1.0),
50 : active(true),
51 : action_pntr_(NULL),
52 : vesbias_pntr_(NULL),
53 : ndimensions_(0),
54 : indices_shape_(0),
55 : ncoeffs_(0),
56 : coeffs_descriptions_(0),
57 : dimension_labels_(0),
58 : args_(0),
59 : basisf_(0),
60 : multicoeffs_(false),
61 : multicoeffs_args_(0),
62 : multicoeffs_basisf_(0),
63 : field_type_("type"),
64 : field_ndimensions_("ndimensions"),
65 : field_ncoeffs_total_("ncoeffs_total"),
66 : field_shape_prefix_("shape_"),
67 : field_time_("time"),
68 : field_iteration_("iteration"),
69 0 : output_fmt_("%30.16e")
70 : {
71 0 : initializeIndices(indices_shape,dimension_labels);
72 0 : setAllCoeffsDescriptions();
73 0 : }
74 :
75 :
76 293 : CoeffsBase::CoeffsBase(
77 : const std::string& label,
78 : std::vector<Value*>& args,
79 : std::vector<BasisFunctions*>& basisf,
80 : const bool use_iteration_counter):
81 : label_(label),
82 : data_label_(label),
83 : coeffs_type_(LinearBasisSet),
84 : iteration_and_time_active_(use_iteration_counter),
85 : iteration_opt(0),
86 : time_md(-1.0),
87 : active(true),
88 : action_pntr_(NULL),
89 : vesbias_pntr_(NULL),
90 : ndimensions_(0),
91 : indices_shape_(0),
92 : ncoeffs_(0),
93 : coeffs_descriptions_(0),
94 : dimension_labels_(0),
95 : args_(args),
96 : basisf_(basisf),
97 : multicoeffs_(false),
98 : multicoeffs_args_(0),
99 : multicoeffs_basisf_(0),
100 : field_type_("type"),
101 : field_ndimensions_("ndimensions"),
102 : field_ncoeffs_total_("ncoeffs_total"),
103 : field_shape_prefix_("shape_"),
104 : field_time_("time"),
105 : field_iteration_("iteration"),
106 293 : output_fmt_("%30.16e")
107 : {
108 293 : plumed_massert(args_.size()==basisf_.size(),"CoeffsBase: number of arguments do not match number of basis functions");
109 293 : std::vector<std::string> dimension_labels(args_.size());
110 586 : std::vector<unsigned int> indices_shape(args_.size());
111 614 : for(unsigned int i=0; i<args_.size(); i++) {
112 321 : dimension_labels[i]=args_[i]->getName();
113 321 : indices_shape[i]=basisf_[i]->getNumberOfBasisFunctions();
114 : }
115 293 : initializeIndices(indices_shape,dimension_labels);
116 586 : setupBasisFunctionsInfo();
117 293 : }
118 :
119 :
120 0 : CoeffsBase::CoeffsBase(
121 : const std::string& label,
122 : std::vector<std::vector<Value*> >& multicoeffs_args,
123 : std::vector<std::vector<BasisFunctions*> >& multicoeffs_basisf,
124 : const bool use_iteration_counter,
125 : const std::string& multicoeffs_label):
126 : label_(label),
127 : data_label_(label),
128 : coeffs_type_(MultiCoeffs_LinearBasisSet),
129 : iteration_and_time_active_(use_iteration_counter),
130 : iteration_opt(0),
131 : time_md(-1.0),
132 : active(true),
133 : action_pntr_(NULL),
134 : vesbias_pntr_(NULL),
135 : ndimensions_(0),
136 : indices_shape_(0),
137 : ncoeffs_(0),
138 : coeffs_descriptions_(0),
139 : dimension_labels_(0),
140 : args_(0),
141 : basisf_(0),
142 : multicoeffs_(true),
143 : multicoeffs_args_(multicoeffs_args),
144 : multicoeffs_basisf_(multicoeffs_basisf),
145 : field_type_("type"),
146 : field_ndimensions_("ndimensions"),
147 : field_ncoeffs_total_("ncoeffs_total"),
148 : field_shape_prefix_("shape_"),
149 : field_time_("time"),
150 : field_iteration_("iteration"),
151 0 : output_fmt_("%30.16e")
152 : {
153 0 : plumed_massert(multicoeffs_args.size()==multicoeffs_basisf.size(),"Multi Coeffs: number of arguments vectors does not match number of basis functions vectors");
154 0 : unsigned int num_args = multicoeffs_args[0].size();
155 0 : unsigned int dim = num_args+1;
156 0 : std::vector<std::string> dimension_labels(dim);
157 0 : std::vector<unsigned int> indices_shape(dim);
158 0 : for(unsigned int i=0; i<num_args; i++) {
159 0 : std::string ip;
160 0 : Tools::convert(i+1,ip);
161 0 : dimension_labels[i] = "bf" + ip;
162 0 : indices_shape[i] = multicoeffs_basisf[0][i]->getNumberOfBasisFunctions();
163 0 : }
164 0 : indices_shape[dim-1] = multicoeffs_args.size();
165 0 : dimension_labels[dim-1] = multicoeffs_label;
166 0 : for(unsigned int k=0; k<multicoeffs_args.size(); k++) {
167 0 : plumed_massert(multicoeffs_args[k].size()==num_args && multicoeffs_basisf[k].size()==num_args,"Multi Coeffs: arguments and basis functions vectors for each bias should be of the same size");
168 0 : for(unsigned int i=0; i<num_args; i++) {
169 0 : plumed_massert(indices_shape[i]==multicoeffs_basisf[k][i]->getNumberOfBasisFunctions(),"Multi Coeffs: the coeffs shape for each bias should be identical");
170 : }
171 : }
172 0 : initializeIndices(indices_shape,dimension_labels);
173 0 : setupBasisFunctionsInfo();
174 0 : }
175 :
176 :
177 11289 : CoeffsBase::~CoeffsBase() {}
178 :
179 :
180 293 : void CoeffsBase::initializeIndices(const std::vector<unsigned int>& indices_shape, const std::vector<std::string>& dimension_labels) {
181 293 : plumed_massert(indices_shape.size()==dimension_labels.size(),"indices shape and dimension labels must be of the same size");
182 293 : ndimensions_=indices_shape.size();
183 293 : indices_shape_=indices_shape;
184 293 : dimension_labels_=dimension_labels;
185 293 : ncoeffs_=1;
186 614 : for(unsigned int i=0; i<ndimensions_; i++) {
187 321 : ncoeffs_*=indices_shape_[i];
188 : }
189 293 : coeffs_descriptions_.resize(ncoeffs_);
190 293 : }
191 :
192 :
193 0 : void CoeffsBase::reinitializeIndices(const std::vector<unsigned int>& indices_shape_new) {
194 0 : plumed_massert(indices_shape_.size()>0,"indices must have been previously initialized before using this function");
195 0 : plumed_massert(dimension_labels_.size()>0,"indices must have been previously initialized before using this function");
196 0 : plumed_massert(indices_shape_new.size()==numberOfDimensions(),"when resizeing Coeffs the dimension must be constant");
197 0 : indices_shape_=indices_shape_new;
198 0 : ncoeffs_=1;
199 0 : for(unsigned int i=0; i<ndimensions_; i++) {
200 0 : ncoeffs_*=indices_shape_[i];
201 : }
202 0 : coeffs_descriptions_.clear();
203 0 : coeffs_descriptions_.resize(ncoeffs_);
204 0 : }
205 :
206 :
207 293 : void CoeffsBase::setupBasisFunctionsInfo() {
208 293 : plumed_massert(indices_shape_.size()>0,"indices must be initialized before running this function");
209 293 : if(coeffs_type_==LinearBasisSet) {
210 6228 : for(unsigned int i=0; i<numberOfCoeffs(); i++) {
211 5935 : std::vector<unsigned int> indices=getIndices(i);
212 11870 : std::string desc;
213 5935 : desc=basisf_[0]->getBasisFunctionLabel(indices[0]);
214 8607 : for(unsigned int k=1; k<numberOfDimensions(); k++) {
215 2672 : desc+="*"+basisf_[k]->getBasisFunctionLabel(indices[k]);
216 : }
217 5935 : setCoeffDescription(i,desc);
218 5935 : }
219 : }
220 0 : else if(coeffs_type_==MultiCoeffs_LinearBasisSet) {
221 0 : for(unsigned int i=0; i<numberOfCoeffs(); i++) {
222 0 : std::vector<unsigned int> indices=getIndices(i);
223 0 : unsigned int mc_id = indices[ndimensions_-1];
224 0 : std::string mc_idstr;
225 0 : Tools::convert(mc_id,mc_idstr);
226 : // std::string mc_label = getDimensionLabel(ndimensions_-1);
227 0 : std::string postfix = ":" + mc_idstr;
228 0 : std::string desc ="";
229 0 : desc+=multicoeffs_basisf_[mc_id][0]->getBasisFunctionLabel(indices[0]);
230 0 : for(unsigned int k=1; k<(numberOfDimensions()-1); k++) {
231 0 : desc+="*"+multicoeffs_basisf_[mc_id][k]->getBasisFunctionLabel(indices[k]);
232 : }
233 0 : desc+=postfix;
234 0 : setCoeffDescription(i,desc);
235 0 : }
236 : }
237 293 : }
238 :
239 :
240 0 : void CoeffsBase::resizeIndices(const std::vector<unsigned int>& indices_shape_new) {
241 0 : plumed_massert(coeffs_type_==Generic,"Coeffs type must be Generic when resizeing based on a new indices shape vector");
242 0 : reinitializeIndices(indices_shape_new);
243 0 : setAllCoeffsDescriptions();
244 0 : }
245 :
246 :
247 0 : void CoeffsBase::resizeIndices(std::vector<BasisFunctions*>& basisf_new) {
248 0 : plumed_massert(coeffs_type_==LinearBasisSet,"Coeffs type must be LinearBasisSet when resizeing based on a new basis function set");
249 0 : basisf_=basisf_new;
250 0 : std::vector<unsigned int> indices_shape_new(basisf_new.size());
251 0 : for(unsigned int i=0; i<basisf_new.size(); i++) {
252 0 : indices_shape_new[i]=basisf_new[i]->getNumberOfBasisFunctions();
253 : }
254 0 : reinitializeIndices(indices_shape_new);
255 0 : setupBasisFunctionsInfo();
256 0 : }
257 :
258 :
259 6 : bool CoeffsBase::sameShape(const CoeffsBase& coeffsbase_in) const {
260 6 : if(numberOfDimensions()!=coeffsbase_in.numberOfDimensions()) {
261 0 : return false;
262 : }
263 6 : if(numberOfCoeffs()!=coeffsbase_in.numberOfCoeffs()) {
264 0 : return false;
265 : }
266 12 : for(unsigned int k=0; k<numberOfDimensions(); k++) {
267 6 : if(shapeOfIndices(k)!=coeffsbase_in.shapeOfIndices(k)) {
268 0 : return false;
269 : }
270 : }
271 6 : return true;
272 : }
273 :
274 :
275 0 : void CoeffsBase::setLabel(const std::string& label) {
276 0 : label_=label;
277 0 : }
278 :
279 :
280 0 : void CoeffsBase::setDataLabel(const std::string& data_label) {
281 0 : data_label_=data_label;
282 0 : }
283 :
284 :
285 677 : void CoeffsBase::setLabels(const std::string& label) {
286 677 : label_=label;
287 677 : data_label_=label;
288 677 : }
289 :
290 :
291 0 : void CoeffsBase::setLabels(const std::string& label, const std::string& data_label) {
292 0 : label_=label;
293 0 : data_label_=data_label;
294 0 : }
295 :
296 :
297 3188 : std::string CoeffsBase::getTypeStr() const {
298 3188 : std::string type_str="";
299 3188 : if(coeffs_type_==Generic) {
300 0 : type_str = "Generic";
301 : }
302 3188 : else if(coeffs_type_==LinearBasisSet) {
303 3188 : type_str = "LinearBasisSet";
304 : }
305 0 : else if(coeffs_type_==MultiCoeffs_LinearBasisSet) {
306 0 : type_str = "MultiCoeffs_LinearBasisSet";
307 : }
308 3188 : return type_str;
309 : }
310 :
311 :
312 0 : void CoeffsBase::setType(const CoeffsType coeffs_type) {
313 0 : coeffs_type_=coeffs_type;
314 0 : }
315 :
316 :
317 81 : void CoeffsBase::linkVesBias(VesBias* vesbias_pntr_in) {
318 81 : vesbias_pntr_ = vesbias_pntr_in;
319 81 : action_pntr_ = static_cast<Action*>(vesbias_pntr_in);
320 81 : }
321 :
322 :
323 0 : void CoeffsBase::linkAction(Action* action_pntr_in) {
324 0 : action_pntr_ = action_pntr_in;
325 0 : }
326 :
327 :
328 0 : bool CoeffsBase::indicesExist(const std::vector<unsigned int>& indices) const {
329 : plumed_dbg_assert(indices.size()==ndimensions_);
330 0 : for(unsigned int k=0; k<ndimensions_; k++) {
331 0 : if(indices[k]>=indices_shape_[k]) {
332 0 : return false;
333 : }
334 : }
335 0 : return true;
336 : }
337 :
338 :
339 5935 : void CoeffsBase::setCoeffDescription(const size_t index, const std::string& description) {
340 5935 : coeffs_descriptions_[index]=description;
341 5935 : }
342 :
343 :
344 0 : void CoeffsBase::setCoeffDescription(const std::vector<unsigned int>& indices, const std::string& description) {
345 0 : setCoeffDescription(getIndex(indices), description);
346 0 : }
347 :
348 :
349 0 : void CoeffsBase::setAllCoeffsDescriptions(const std::string& description_prefix) {
350 0 : for(size_t i=0; i<numberOfCoeffs(); i++) {
351 0 : std::vector<unsigned int> indices=getIndices(i);
352 0 : std::string is; Tools::convert(indices[0],is);
353 0 : std::string desc=description_prefix+"("+is;
354 0 : for(unsigned int k=1; k<numberOfDimensions(); k++) {
355 0 : Tools::convert(indices[k],is); desc+=","+is;
356 : }
357 0 : desc+=")";
358 0 : coeffs_descriptions_[i]=desc;
359 0 : }
360 0 : }
361 :
362 :
363 0 : void CoeffsBase::setAllCoeffsDescriptions(const std::vector<std::string>& coeffs_descriptions) {
364 0 : plumed_massert(coeffs_descriptions.size()==numberOfCoeffs(),"The coeffs description vector doesn't match the number of coeffs");
365 0 : for(size_t i=0; i<numberOfCoeffs(); i++) {
366 0 : coeffs_descriptions_[i]=coeffs_descriptions[i];
367 : }
368 0 : }
369 :
370 :
371 0 : void CoeffsBase::setDimensionLabel(const unsigned int dim_index, const std::string& label) {
372 0 : plumed_massert(dim_index<numberOfDimensions(),"Trying to set the label of a dimension outside the number of dimensions");
373 0 : dimension_labels_[dim_index]=label;
374 0 : }
375 :
376 :
377 0 : void CoeffsBase::setAllDimensionLabels(const std::string& label_prefix) {
378 0 : for(unsigned int i=0; i<numberOfDimensions(); i++) {
379 0 : std::string is; Tools::convert(i,is);
380 0 : dimension_labels_[i]=label_prefix + is;
381 0 : }
382 0 : }
383 :
384 :
385 0 : void CoeffsBase::setAllDimensionLabels(const std::vector<std::string>& labels) {
386 0 : for(unsigned int i=0; i<numberOfDimensions(); i++) {
387 0 : dimension_labels_[i]=labels[i];
388 : }
389 0 : }
390 :
391 :
392 2820 : void CoeffsBase::writeCoeffsInfoToFile(OFile& ofile) const {
393 2820 : ofile.addConstantField(field_type_).printField(field_type_,getTypeStr());
394 2820 : ofile.addConstantField(field_ndimensions_).printField(field_ndimensions_,(int) numberOfDimensions());
395 2820 : ofile.addConstantField(field_ncoeffs_total_).printField(field_ncoeffs_total_,(int) numberOfCoeffs());
396 6378 : for(unsigned int k=0; k<numberOfDimensions(); k++) {
397 3558 : ofile.addConstantField(field_shape_prefix_+getDimensionLabel(k));
398 3558 : ofile.printField(field_shape_prefix_+getDimensionLabel(k),(int) shapeOfIndices(k));
399 : }
400 2820 : }
401 :
402 :
403 368 : void CoeffsBase::getCoeffsInfoFromFile(IFile& ifile, const bool ignore_coeffs_info) {
404 : int int_tmp;
405 : // label
406 368 : std::string coeffs_type_f;
407 368 : if(ifile.scanField(field_type_,coeffs_type_f)) {
408 : // empty for now
409 : }
410 : else {
411 0 : return;
412 : }
413 : // number of dimensions
414 368 : unsigned int ndimensions_f = 0;
415 368 : if(ifile.scanField(field_ndimensions_,int_tmp)) {
416 368 : ndimensions_f=(unsigned int) int_tmp;
417 : }
418 : else {
419 0 : return;
420 : }
421 : // total number of coeffs
422 368 : size_t ncoeffs_total_f = 0;
423 368 : if(ifile.scanField(field_ncoeffs_total_,int_tmp)) {
424 368 : ncoeffs_total_f=(size_t) int_tmp;
425 : }
426 : else {
427 0 : return;
428 : }
429 : // shape of indices
430 736 : std::vector<unsigned int> indices_shape_f(numberOfDimensions());
431 747 : for(unsigned int k=0; k<numberOfDimensions(); k++) {
432 379 : if(ifile.scanField(field_shape_prefix_+getDimensionLabel(k),int_tmp)) {
433 379 : indices_shape_f[k]=(unsigned int) int_tmp;
434 : }
435 : else {
436 0 : return;
437 : }
438 : }
439 368 : if(!ignore_coeffs_info) {
440 368 : std::string msg_header="Error when reading in coeffs from file " + ifile.getPath() + ": ";
441 368 : checkCoeffsInfo(msg_header, coeffs_type_f, ndimensions_f, ncoeffs_total_f, indices_shape_f);
442 368 : }
443 : }
444 :
445 :
446 368 : void CoeffsBase::checkCoeffsInfo(const std::string& msg_header, const std::string& coeffs_type_f, const unsigned int ndimensions_f, const size_t ncoeffs_total_f, const std::vector<unsigned int>& indices_shape_f) {
447 :
448 368 : if(coeffs_type_f != getTypeStr()) {
449 0 : std::string msg = msg_header + " coeffs type " + coeffs_type_f + " from file doesn't match the defined value " + getTypeStr();
450 0 : plumed_merror(msg);
451 : }
452 368 : if(ndimensions_f != numberOfDimensions() ) {
453 0 : std::string s1; Tools::convert(ndimensions_f,s1);
454 0 : std::string s2; Tools::convert(numberOfDimensions(),s2);
455 0 : std::string msg = msg_header + " the number of dimensions " + s1 + " in file doesn't match the defined value " + s2;
456 0 : plumed_merror(msg);
457 : }
458 368 : if(ncoeffs_total_f != numberOfCoeffs() ) {
459 0 : std::string s1; Tools::convert(ncoeffs_total_f,s1);
460 0 : std::string s2; Tools::convert(numberOfCoeffs(),s2);
461 0 : std::string msg = msg_header + " the number of coeffs " + s1 + " in file doesn't match the defined value " + s2;
462 0 : plumed_merror(msg);
463 : }
464 747 : for(unsigned int k=0; k<numberOfDimensions(); k++) {
465 379 : if(indices_shape_f[k] != shapeOfIndices(k) ) {
466 0 : std::string s1; Tools::convert(indices_shape_f[k],s1);
467 0 : std::string s2; Tools::convert(shapeOfIndices(k),s2);
468 0 : std::string msg = msg_header + " for dimension labeled " + getDimensionLabel(k) + " the shape of indices " + s1 + " in file doesn't match defined value " + s2;
469 0 : plumed_merror(msg);
470 : }
471 : }
472 368 : }
473 :
474 :
475 2608 : void CoeffsBase::writeIterationCounterAndTimeToFile(OFile& ofile) const {
476 2608 : if(time_md>=0.0) {
477 2608 : ofile.fmtField("%f");
478 2608 : ofile.addConstantField(field_time_).printField(field_time_,time_md);
479 2608 : ofile.fmtField();
480 : }
481 2608 : ofile.addConstantField(field_iteration_).printField(field_iteration_,(int) iteration_opt);
482 2608 : }
483 :
484 :
485 406 : bool CoeffsBase::getIterationCounterAndTimeFromFile(IFile& ifile) {
486 406 : bool field_found=false;
487 406 : if(ifile.FieldExist(field_time_)) {
488 368 : field_found=true;
489 : double time_tmp;
490 368 : ifile.scanField(field_time_,time_tmp);
491 368 : time_md=time_tmp;
492 : }
493 406 : if(ifile.FieldExist(field_iteration_)) {
494 368 : field_found=true;
495 : int iter_tmp;
496 368 : ifile.scanField(field_iteration_,iter_tmp);
497 368 : iteration_opt=(unsigned int) iter_tmp;
498 : }
499 406 : return field_found;
500 : }
501 :
502 :
503 : }
504 : }
|