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 378 : CoeffsBase::CoeffsBase(
76 : const std::string& label,
77 : const std::vector<Value*>& args,
78 : std::vector<BasisFunctions*>& basisf,
79 378 : const bool use_iteration_counter):
80 378 : label_(label),
81 378 : data_label_(label),
82 378 : coeffs_type_(LinearBasisSet),
83 378 : iteration_and_time_active_(use_iteration_counter),
84 378 : iteration_opt(0),
85 378 : time_md(-1.0),
86 378 : active(true),
87 378 : action_pntr_(NULL),
88 378 : vesbias_pntr_(NULL),
89 378 : ndimensions_(0),
90 378 : indices_shape_(0),
91 378 : ncoeffs_(0),
92 378 : coeffs_descriptions_(0),
93 378 : dimension_labels_(0),
94 378 : args_(args),
95 378 : basisf_(basisf),
96 378 : multicoeffs_(false),
97 378 : multicoeffs_args_(0),
98 378 : multicoeffs_basisf_(0),
99 378 : field_type_("type"),
100 378 : field_ndimensions_("ndimensions"),
101 378 : field_ncoeffs_total_("ncoeffs_total"),
102 378 : field_shape_prefix_("shape_"),
103 378 : field_time_("time"),
104 378 : field_iteration_("iteration"),
105 378 : output_fmt_("%30.16e") {
106 378 : plumed_massert(args_.size()==basisf_.size(),"CoeffsBase: number of arguments do not match number of basis functions");
107 378 : std::vector<std::string> dimension_labels(args_.size());
108 378 : std::vector<unsigned int> indices_shape(args_.size());
109 791 : for(unsigned int i=0; i<args_.size(); i++) {
110 413 : dimension_labels[i]=args_[i]->getName();
111 413 : indices_shape[i]=basisf_[i]->getNumberOfBasisFunctions();
112 : }
113 378 : initializeIndices(indices_shape,dimension_labels);
114 378 : setupBasisFunctionsInfo();
115 378 : }
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 1026417 : CoeffsBase::~CoeffsBase() {}
175 :
176 :
177 378 : void CoeffsBase::initializeIndices(const std::vector<unsigned int>& indices_shape, const std::vector<std::string>& dimension_labels) {
178 378 : plumed_massert(indices_shape.size()==dimension_labels.size(),"indices shape and dimension labels must be of the same size");
179 378 : ndimensions_=indices_shape.size();
180 378 : indices_shape_=indices_shape;
181 378 : dimension_labels_=dimension_labels;
182 378 : ncoeffs_=1;
183 791 : for(unsigned int i=0; i<ndimensions_; i++) {
184 413 : ncoeffs_*=indices_shape_[i];
185 : }
186 378 : coeffs_descriptions_.resize(ncoeffs_);
187 378 : }
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 378 : void CoeffsBase::setupBasisFunctionsInfo() {
205 378 : plumed_massert(indices_shape_.size()>0,"indices must be initialized before running this function");
206 378 : if(coeffs_type_==LinearBasisSet) {
207 9310 : for(unsigned int i=0; i<numberOfCoeffs(); i++) {
208 8932 : std::vector<unsigned int> indices=getIndices(i);
209 : std::string desc;
210 8932 : desc=basisf_[0]->getBasisFunctionLabel(indices[0]);
211 13413 : for(unsigned int k=1; k<numberOfDimensions(); k++) {
212 8962 : desc+="*"+basisf_[k]->getBasisFunctionLabel(indices[k]);
213 : }
214 8932 : 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 0 : std::string postfix = ":" + mc_idstr;
223 0 : std::string desc ="";
224 0 : desc+=multicoeffs_basisf_[mc_id][0]->getBasisFunctionLabel(indices[0]);
225 0 : for(unsigned int k=1; k<(numberOfDimensions()-1); k++) {
226 0 : desc+="*"+multicoeffs_basisf_[mc_id][k]->getBasisFunctionLabel(indices[k]);
227 : }
228 : desc+=postfix;
229 0 : setCoeffDescription(i,desc);
230 : }
231 : }
232 378 : }
233 :
234 :
235 0 : void CoeffsBase::resizeIndices(const std::vector<unsigned int>& indices_shape_new) {
236 0 : plumed_massert(coeffs_type_==Generic,"Coeffs type must be Generic when resizeing based on a new indices shape vector");
237 0 : reinitializeIndices(indices_shape_new);
238 0 : setAllCoeffsDescriptions();
239 0 : }
240 :
241 :
242 0 : void CoeffsBase::resizeIndices(std::vector<BasisFunctions*>& basisf_new) {
243 0 : plumed_massert(coeffs_type_==LinearBasisSet,"Coeffs type must be LinearBasisSet when resizeing based on a new basis function set");
244 0 : basisf_=basisf_new;
245 0 : std::vector<unsigned int> indices_shape_new(basisf_new.size());
246 0 : for(unsigned int i=0; i<basisf_new.size(); i++) {
247 0 : indices_shape_new[i]=basisf_new[i]->getNumberOfBasisFunctions();
248 : }
249 0 : reinitializeIndices(indices_shape_new);
250 0 : setupBasisFunctionsInfo();
251 0 : }
252 :
253 :
254 6 : bool CoeffsBase::sameShape(const CoeffsBase& coeffsbase_in) const {
255 6 : if(numberOfDimensions()!=coeffsbase_in.numberOfDimensions()) {
256 : return false;
257 : }
258 6 : if(numberOfCoeffs()!=coeffsbase_in.numberOfCoeffs()) {
259 : return false;
260 : }
261 12 : for(unsigned int k=0; k<numberOfDimensions(); k++) {
262 6 : if(shapeOfIndices(k)!=coeffsbase_in.shapeOfIndices(k)) {
263 : return false;
264 : }
265 : }
266 : return true;
267 : }
268 :
269 :
270 0 : void CoeffsBase::setLabel(const std::string& label) {
271 0 : label_=label;
272 0 : }
273 :
274 :
275 0 : void CoeffsBase::setDataLabel(const std::string& data_label) {
276 0 : data_label_=data_label;
277 0 : }
278 :
279 :
280 759 : void CoeffsBase::setLabels(const std::string& label) {
281 759 : label_=label;
282 759 : data_label_=label;
283 759 : }
284 :
285 :
286 0 : void CoeffsBase::setLabels(const std::string& label, const std::string& data_label) {
287 0 : label_=label;
288 0 : data_label_=data_label;
289 0 : }
290 :
291 :
292 3377 : std::string CoeffsBase::getTypeStr() const {
293 3377 : std::string type_str="";
294 3377 : if(coeffs_type_==Generic) {
295 : type_str = "Generic";
296 3377 : } else if(coeffs_type_==LinearBasisSet) {
297 : type_str = "LinearBasisSet";
298 0 : } else if(coeffs_type_==MultiCoeffs_LinearBasisSet) {
299 : type_str = "MultiCoeffs_LinearBasisSet";
300 : }
301 3377 : return type_str;
302 : }
303 :
304 :
305 0 : void CoeffsBase::setType(const CoeffsType coeffs_type) {
306 0 : coeffs_type_=coeffs_type;
307 0 : }
308 :
309 :
310 91 : void CoeffsBase::linkVesBias(VesBias* vesbias_pntr_in) {
311 91 : vesbias_pntr_ = vesbias_pntr_in;
312 91 : action_pntr_ = static_cast<Action*>(vesbias_pntr_in);
313 91 : }
314 :
315 :
316 0 : void CoeffsBase::linkAction(Action* action_pntr_in) {
317 0 : action_pntr_ = action_pntr_in;
318 0 : }
319 :
320 :
321 0 : bool CoeffsBase::indicesExist(const std::vector<unsigned int>& indices) const {
322 : plumed_dbg_assert(indices.size()==ndimensions_);
323 0 : for(unsigned int k=0; k<ndimensions_; k++) {
324 0 : if(indices[k]>=indices_shape_[k]) {
325 : return false;
326 : }
327 : }
328 : return true;
329 : }
330 :
331 :
332 8932 : void CoeffsBase::setCoeffDescription(const size_t index, const std::string& description) {
333 : coeffs_descriptions_[index]=description;
334 8932 : }
335 :
336 :
337 0 : void CoeffsBase::setCoeffDescription(const std::vector<unsigned int>& indices, const std::string& description) {
338 0 : setCoeffDescription(getIndex(indices), description);
339 0 : }
340 :
341 :
342 0 : void CoeffsBase::setAllCoeffsDescriptions(const std::string& description_prefix) {
343 0 : for(size_t i=0; i<numberOfCoeffs(); i++) {
344 0 : std::vector<unsigned int> indices=getIndices(i);
345 : std::string is;
346 0 : Tools::convert(indices[0],is);
347 0 : std::string desc=description_prefix+"("+is;
348 0 : for(unsigned int k=1; k<numberOfDimensions(); k++) {
349 0 : Tools::convert(indices[k],is);
350 0 : desc+=","+is;
351 : }
352 : desc+=")";
353 : coeffs_descriptions_[i]=desc;
354 : }
355 0 : }
356 :
357 :
358 0 : void CoeffsBase::setAllCoeffsDescriptions(const std::vector<std::string>& coeffs_descriptions) {
359 0 : plumed_massert(coeffs_descriptions.size()==numberOfCoeffs(),"The coeffs description vector doesn't match the number of coeffs");
360 0 : for(size_t i=0; i<numberOfCoeffs(); i++) {
361 : coeffs_descriptions_[i]=coeffs_descriptions[i];
362 : }
363 0 : }
364 :
365 :
366 0 : void CoeffsBase::setDimensionLabel(const unsigned int dim_index, const std::string& label) {
367 0 : plumed_massert(dim_index<numberOfDimensions(),"Trying to set the label of a dimension outside the number of dimensions");
368 0 : dimension_labels_[dim_index]=label;
369 0 : }
370 :
371 :
372 0 : void CoeffsBase::setAllDimensionLabels(const std::string& label_prefix) {
373 0 : for(unsigned int i=0; i<numberOfDimensions(); i++) {
374 : std::string is;
375 0 : Tools::convert(i,is);
376 0 : dimension_labels_[i]=label_prefix + is;
377 : }
378 0 : }
379 :
380 :
381 0 : void CoeffsBase::setAllDimensionLabels(const std::vector<std::string>& labels) {
382 0 : for(unsigned int i=0; i<numberOfDimensions(); i++) {
383 0 : dimension_labels_[i]=labels[i];
384 : }
385 0 : }
386 :
387 :
388 3008 : void CoeffsBase::writeCoeffsInfoToFile(OFile& ofile) const {
389 3008 : ofile.addConstantField(field_type_).printField(field_type_,getTypeStr());
390 3008 : ofile.addConstantField(field_ndimensions_).printField(field_ndimensions_,(int) numberOfDimensions());
391 3008 : ofile.addConstantField(field_ncoeffs_total_).printField(field_ncoeffs_total_,(int) numberOfCoeffs());
392 6780 : for(unsigned int k=0; k<numberOfDimensions(); k++) {
393 7544 : ofile.addConstantField(field_shape_prefix_+getDimensionLabel(k));
394 7544 : ofile.printField(field_shape_prefix_+getDimensionLabel(k),(int) shapeOfIndices(k));
395 : }
396 3008 : }
397 :
398 :
399 369 : void CoeffsBase::getCoeffsInfoFromFile(IFile& ifile, const bool ignore_coeffs_info) {
400 : int int_tmp;
401 : // label
402 : std::string coeffs_type_f;
403 369 : if(ifile.scanField(field_type_,coeffs_type_f)) {
404 : // empty for now
405 : } else {
406 : return;
407 : }
408 : // number of dimensions
409 : unsigned int ndimensions_f = 0;
410 369 : if(ifile.scanField(field_ndimensions_,int_tmp)) {
411 369 : ndimensions_f=(unsigned int) int_tmp;
412 : } else {
413 : return;
414 : }
415 : // total number of coeffs
416 : size_t ncoeffs_total_f = 0;
417 369 : if(ifile.scanField(field_ncoeffs_total_,int_tmp)) {
418 369 : ncoeffs_total_f=(size_t) int_tmp;
419 : } else {
420 : return;
421 : }
422 : // shape of indices
423 369 : std::vector<unsigned int> indices_shape_f(numberOfDimensions());
424 749 : for(unsigned int k=0; k<numberOfDimensions(); k++) {
425 760 : if(ifile.scanField(field_shape_prefix_+getDimensionLabel(k),int_tmp)) {
426 380 : indices_shape_f[k]=(unsigned int) int_tmp;
427 : } else {
428 : return;
429 : }
430 : }
431 369 : if(!ignore_coeffs_info) {
432 369 : std::string msg_header="Error when reading in coeffs from file " + ifile.getPath() + ": ";
433 369 : checkCoeffsInfo(msg_header, coeffs_type_f, ndimensions_f, ncoeffs_total_f, indices_shape_f);
434 : }
435 : }
436 :
437 :
438 369 : 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) {
439 :
440 369 : if(coeffs_type_f != getTypeStr()) {
441 0 : std::string msg = msg_header + " coeffs type " + coeffs_type_f + " from file doesn't match the defined value " + getTypeStr();
442 0 : plumed_merror(msg);
443 : }
444 369 : if(ndimensions_f != numberOfDimensions() ) {
445 : std::string s1;
446 0 : Tools::convert(ndimensions_f,s1);
447 : std::string s2;
448 0 : Tools::convert(numberOfDimensions(),s2);
449 0 : std::string msg = msg_header + " the number of dimensions " + s1 + " in file doesn't match the defined value " + s2;
450 0 : plumed_merror(msg);
451 : }
452 369 : if(ncoeffs_total_f != numberOfCoeffs() ) {
453 : std::string s1;
454 0 : Tools::convert(ncoeffs_total_f,s1);
455 : std::string s2;
456 0 : Tools::convert(numberOfCoeffs(),s2);
457 0 : std::string msg = msg_header + " the number of coeffs " + s1 + " in file doesn't match the defined value " + s2;
458 0 : plumed_merror(msg);
459 : }
460 749 : for(unsigned int k=0; k<numberOfDimensions(); k++) {
461 380 : if(indices_shape_f[k] != shapeOfIndices(k) ) {
462 : std::string s1;
463 0 : Tools::convert(indices_shape_f[k],s1);
464 : std::string s2;
465 0 : Tools::convert(shapeOfIndices(k),s2);
466 0 : std::string msg = msg_header + " for dimension labeled " + getDimensionLabel(k) + " the shape of indices " + s1 + " in file doesn't match defined value " + s2;
467 0 : plumed_merror(msg);
468 : }
469 : }
470 369 : }
471 :
472 :
473 2721 : void CoeffsBase::writeIterationCounterAndTimeToFile(OFile& ofile) const {
474 2721 : if(time_md>=0.0) {
475 2721 : ofile.fmtField("%f");
476 2721 : ofile.addConstantField(field_time_).printField(field_time_,time_md);
477 2721 : ofile.fmtField();
478 : }
479 2721 : ofile.addConstantField(field_iteration_).printField(field_iteration_,(int) iteration_opt);
480 2721 : }
481 :
482 :
483 408 : bool CoeffsBase::getIterationCounterAndTimeFromFile(IFile& ifile) {
484 : bool field_found=false;
485 408 : if(ifile.FieldExist(field_time_)) {
486 : field_found=true;
487 : double time_tmp;
488 368 : ifile.scanField(field_time_,time_tmp);
489 368 : time_md=time_tmp;
490 : }
491 408 : if(ifile.FieldExist(field_iteration_)) {
492 : field_found=true;
493 : int iter_tmp;
494 368 : ifile.scanField(field_iteration_,iter_tmp);
495 368 : iteration_opt=(unsigned int) iter_tmp;
496 : }
497 408 : return field_found;
498 : }
499 :
500 :
501 : // replace string in Label, if old string was not found simply add the new string to the label
502 5 : void CoeffsBase::replaceLabelString(const std::string& oldstring, const std::string& newstring) {
503 : std::string label = getLabel();
504 5 : if(label.find(oldstring)!=std::string::npos) {
505 8 : label.replace(label.find(oldstring), std::string(oldstring).length(), newstring);
506 : } else {
507 2 : label += "_" + newstring;
508 : }
509 5 : setLabels(label);
510 5 : }
511 :
512 :
513 : }
514 : }
|