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