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 : {
71 0 : initializeIndices(indices_shape,dimension_labels);
72 0 : setAllCoeffsDescriptions();
73 0 : }
74 :
75 :
76 377 : CoeffsBase::CoeffsBase(
77 : const std::string& label,
78 : const std::vector<Value*>& args,
79 : std::vector<BasisFunctions*>& basisf,
80 377 : const bool use_iteration_counter):
81 377 : label_(label),
82 377 : data_label_(label),
83 377 : coeffs_type_(LinearBasisSet),
84 377 : iteration_and_time_active_(use_iteration_counter),
85 377 : iteration_opt(0),
86 377 : time_md(-1.0),
87 377 : active(true),
88 377 : action_pntr_(NULL),
89 377 : vesbias_pntr_(NULL),
90 377 : ndimensions_(0),
91 377 : indices_shape_(0),
92 377 : ncoeffs_(0),
93 377 : coeffs_descriptions_(0),
94 377 : dimension_labels_(0),
95 377 : args_(args),
96 377 : basisf_(basisf),
97 377 : multicoeffs_(false),
98 377 : multicoeffs_args_(0),
99 377 : multicoeffs_basisf_(0),
100 377 : field_type_("type"),
101 377 : field_ndimensions_("ndimensions"),
102 377 : field_ncoeffs_total_("ncoeffs_total"),
103 377 : field_shape_prefix_("shape_"),
104 377 : field_time_("time"),
105 377 : field_iteration_("iteration"),
106 377 : output_fmt_("%30.16e")
107 : {
108 377 : plumed_massert(args_.size()==basisf_.size(),"CoeffsBase: number of arguments do not match number of basis functions");
109 377 : std::vector<std::string> dimension_labels(args_.size());
110 377 : std::vector<unsigned int> indices_shape(args_.size());
111 789 : for(unsigned int i=0; i<args_.size(); i++) {
112 412 : dimension_labels[i]=args_[i]->getName();
113 412 : indices_shape[i]=basisf_[i]->getNumberOfBasisFunctions();
114 : }
115 377 : initializeIndices(indices_shape,dimension_labels);
116 377 : setupBasisFunctionsInfo();
117 377 : }
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 0 : const std::string& multicoeffs_label):
126 0 : label_(label),
127 0 : data_label_(label),
128 0 : coeffs_type_(MultiCoeffs_LinearBasisSet),
129 0 : iteration_and_time_active_(use_iteration_counter),
130 0 : iteration_opt(0),
131 0 : time_md(-1.0),
132 0 : active(true),
133 0 : action_pntr_(NULL),
134 0 : vesbias_pntr_(NULL),
135 0 : ndimensions_(0),
136 0 : indices_shape_(0),
137 0 : ncoeffs_(0),
138 0 : coeffs_descriptions_(0),
139 0 : dimension_labels_(0),
140 0 : args_(0),
141 0 : basisf_(0),
142 0 : multicoeffs_(true),
143 0 : multicoeffs_args_(multicoeffs_args),
144 0 : multicoeffs_basisf_(multicoeffs_basisf),
145 0 : field_type_("type"),
146 0 : field_ndimensions_("ndimensions"),
147 0 : field_ncoeffs_total_("ncoeffs_total"),
148 0 : field_shape_prefix_("shape_"),
149 0 : field_time_("time"),
150 0 : 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 : 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 : }
164 0 : indices_shape[dim-1] = multicoeffs_args.size();
165 : 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 1026402 : CoeffsBase::~CoeffsBase() {}
178 :
179 :
180 377 : void CoeffsBase::initializeIndices(const std::vector<unsigned int>& indices_shape, const std::vector<std::string>& dimension_labels) {
181 377 : plumed_massert(indices_shape.size()==dimension_labels.size(),"indices shape and dimension labels must be of the same size");
182 377 : ndimensions_=indices_shape.size();
183 377 : indices_shape_=indices_shape;
184 377 : dimension_labels_=dimension_labels;
185 377 : ncoeffs_=1;
186 789 : for(unsigned int i=0; i<ndimensions_; i++) {
187 412 : ncoeffs_*=indices_shape_[i];
188 : }
189 377 : coeffs_descriptions_.resize(ncoeffs_);
190 377 : }
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 377 : void CoeffsBase::setupBasisFunctionsInfo() {
208 377 : plumed_massert(indices_shape_.size()>0,"indices must be initialized before running this function");
209 377 : if(coeffs_type_==LinearBasisSet) {
210 9305 : for(unsigned int i=0; i<numberOfCoeffs(); i++) {
211 8928 : std::vector<unsigned int> indices=getIndices(i);
212 : std::string desc;
213 8928 : desc=basisf_[0]->getBasisFunctionLabel(indices[0]);
214 13409 : for(unsigned int k=1; k<numberOfDimensions(); k++) {
215 8962 : desc+="*"+basisf_[k]->getBasisFunctionLabel(indices[k]);
216 : }
217 8928 : setCoeffDescription(i,desc);
218 : }
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 : 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 : desc+=postfix;
234 0 : setCoeffDescription(i,desc);
235 : }
236 : }
237 377 : }
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 : return false;
262 : }
263 6 : if(numberOfCoeffs()!=coeffsbase_in.numberOfCoeffs()) {
264 : return false;
265 : }
266 12 : for(unsigned int k=0; k<numberOfDimensions(); k++) {
267 6 : if(shapeOfIndices(k)!=coeffsbase_in.shapeOfIndices(k)) {
268 : return false;
269 : }
270 : }
271 : 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 754 : void CoeffsBase::setLabels(const std::string& label) {
286 754 : label_=label;
287 754 : data_label_=label;
288 754 : }
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 3376 : std::string CoeffsBase::getTypeStr() const {
298 3376 : std::string type_str="";
299 3376 : if(coeffs_type_==Generic) {
300 : type_str = "Generic";
301 : }
302 3376 : else if(coeffs_type_==LinearBasisSet) {
303 : type_str = "LinearBasisSet";
304 : }
305 0 : else if(coeffs_type_==MultiCoeffs_LinearBasisSet) {
306 : type_str = "MultiCoeffs_LinearBasisSet";
307 : }
308 3376 : 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 90 : void CoeffsBase::linkVesBias(VesBias* vesbias_pntr_in) {
318 90 : vesbias_pntr_ = vesbias_pntr_in;
319 90 : action_pntr_ = static_cast<Action*>(vesbias_pntr_in);
320 90 : }
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 : return false;
333 : }
334 : }
335 : return true;
336 : }
337 :
338 :
339 8928 : void CoeffsBase::setCoeffDescription(const size_t index, const std::string& description) {
340 : coeffs_descriptions_[index]=description;
341 8928 : }
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 : desc+=")";
358 : coeffs_descriptions_[i]=desc;
359 : }
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 : 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 : }
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 3008 : void CoeffsBase::writeCoeffsInfoToFile(OFile& ofile) const {
393 3008 : ofile.addConstantField(field_type_).printField(field_type_,getTypeStr());
394 3008 : ofile.addConstantField(field_ndimensions_).printField(field_ndimensions_,(int) numberOfDimensions());
395 3008 : ofile.addConstantField(field_ncoeffs_total_).printField(field_ncoeffs_total_,(int) numberOfCoeffs());
396 6780 : for(unsigned int k=0; k<numberOfDimensions(); k++) {
397 7544 : ofile.addConstantField(field_shape_prefix_+getDimensionLabel(k));
398 7544 : ofile.printField(field_shape_prefix_+getDimensionLabel(k),(int) shapeOfIndices(k));
399 : }
400 3008 : }
401 :
402 :
403 368 : void CoeffsBase::getCoeffsInfoFromFile(IFile& ifile, const bool ignore_coeffs_info) {
404 : int int_tmp;
405 : // label
406 : std::string coeffs_type_f;
407 368 : if(ifile.scanField(field_type_,coeffs_type_f)) {
408 : // empty for now
409 : }
410 : else {
411 : return;
412 : }
413 : // number of dimensions
414 : 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 : return;
420 : }
421 : // total number of coeffs
422 : 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 : return;
428 : }
429 : // shape of indices
430 368 : std::vector<unsigned int> indices_shape_f(numberOfDimensions());
431 747 : for(unsigned int k=0; k<numberOfDimensions(); k++) {
432 758 : if(ifile.scanField(field_shape_prefix_+getDimensionLabel(k),int_tmp)) {
433 379 : indices_shape_f[k]=(unsigned int) int_tmp;
434 : }
435 : else {
436 : return;
437 : }
438 : }
439 368 : if(!ignore_coeffs_info) {
440 736 : 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 : }
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 736 : 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 2721 : void CoeffsBase::writeIterationCounterAndTimeToFile(OFile& ofile) const {
476 2721 : if(time_md>=0.0) {
477 2721 : ofile.fmtField("%f");
478 2721 : ofile.addConstantField(field_time_).printField(field_time_,time_md);
479 2721 : ofile.fmtField();
480 : }
481 2721 : ofile.addConstantField(field_iteration_).printField(field_iteration_,(int) iteration_opt);
482 2721 : }
483 :
484 :
485 406 : bool CoeffsBase::getIterationCounterAndTimeFromFile(IFile& ifile) {
486 : bool field_found=false;
487 406 : if(ifile.FieldExist(field_time_)) {
488 : 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 : 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 : // replace string in Label, if old string was not found simply add the new string to the label
504 5 : void CoeffsBase::replaceLabelString(const std::string& oldstring, const std::string& newstring) {
505 : std::string label = getLabel();
506 5 : if(label.find(oldstring)!=std::string::npos) {
507 8 : label.replace(label.find(oldstring), std::string(oldstring).length(), newstring);
508 : }
509 : else {
510 2 : label += "_" + newstring;
511 : }
512 5 : setLabels(label);
513 5 : }
514 :
515 :
516 : }
517 : }
|