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 "BasisFunctions.h" 24 : #include "VesTools.h" 25 : 26 : #include "core/ActionRegister.h" 27 : #include "core/ActionSet.h" 28 : #include "core/PlumedMain.h" 29 : 30 : 31 : namespace PLMD { 32 : namespace ves { 33 : 34 : //+PLUMEDOC VES_BASISF BF_COMBINED 35 : /* 36 : Combining other basis functions types 37 : 38 : ##Examples 39 : 40 : Here we define both Fourier cosine and sine expansions of order 10, 41 : each with 11 basis functions, which are combined. This results 42 : in a total number of 21 basis functions as only the constant from 43 : is bf_cos is used. 44 : 45 : ```plumed 46 : bf_cos: BF_COSINE MINIMUM=-pi MAXIMUM=+pi ORDER=10 47 : bf_sin: BF_SINE MINIMUM=-pi MAXIMUM=+pi ORDER=10 48 : bf_comb: BF_COMBINED BASIS_FUNCTIONS=bf_cos,bf_sin 49 : ``` 50 : 51 : In principle this is the same as using BF_FOURIER with 52 : ORDER=10 but with different ordering of the basis functions. 53 : Note that the order used in BASIS_FUNCTIONS matters for the ordering 54 : of the basis functions, using BASIS_FUNCTIONS=bf_sin,bf_cos would 55 : results in a different order of the basis functions. 56 : This should be kept in mind when restarting from previous 57 : coefficients. 58 : 59 : 60 : 61 : 62 : 63 : 64 : */ 65 : //+ENDPLUMEDOC 66 : 67 : class BF_Combined : public BasisFunctions { 68 : std::vector<BasisFunctions*> basisf_pntrs_; 69 : void setupLabels() override; 70 : void setupUniformIntegrals() override; 71 : public: 72 : static void registerKeywords(Keywords&); 73 : explicit BF_Combined(const ActionOptions&); 74 : void getAllValues(const double, double&, bool&, std::vector<double>&, std::vector<double>&) const override; 75 : }; 76 : 77 : 78 : PLUMED_REGISTER_ACTION(BF_Combined,"BF_COMBINED") 79 : 80 : 81 6 : void BF_Combined::registerKeywords(Keywords& keys) { 82 6 : BasisFunctions::registerKeywords(keys); 83 6 : keys.remove("ORDER"); 84 6 : keys.remove("MAXIMUM"); 85 6 : keys.remove("MINIMUM"); 86 6 : keys.remove("NUMERICAL_INTEGRALS"); 87 12 : keys.remove("NGRID_POINTS"); 88 6 : keys.add("compulsory","BASIS_FUNCTIONS","Labels of the basis functions that should be combined. Note that the order used matters for the ordering of the basis functions. This needs to be kept in mind when restarting from previous coefficients."); 89 6 : } 90 : 91 : 92 2 : BF_Combined::BF_Combined(const ActionOptions&ao): 93 : PLUMED_VES_BASISFUNCTIONS_INIT(ao), 94 2 : basisf_pntrs_(0) { 95 2 : std::vector<std::string> basisf_labels; 96 2 : parseVector("BASIS_FUNCTIONS",basisf_labels); 97 4 : addKeywordToList("BASIS_FUNCTIONS",basisf_labels); 98 2 : if(basisf_labels.size()==1) { 99 0 : plumed_merror("using only one basis function in BF_COMBINED does not make sense"); 100 : } 101 2 : std::string error_msg = ""; 102 4 : basisf_pntrs_ = VesTools::getPointersFromLabels<BasisFunctions*>(basisf_labels,plumed.getActionSet(),error_msg); 103 2 : if(error_msg.size()>0) { 104 0 : plumed_merror("Error in keyword BASIS_FUNCTIONS of "+getName()+": "+error_msg); 105 : } 106 : 107 : unsigned int nbasisf_total_ = 1; 108 : bool periodic = true; 109 7 : for(unsigned int i=0; i<basisf_pntrs_.size(); i++) { 110 5 : nbasisf_total_ += basisf_pntrs_[i]->getNumberOfBasisFunctions() - 1; 111 15 : if(basisf_pntrs_[i]->intervalMinStr()!=basisf_pntrs_[0]->intervalMinStr() || basisf_pntrs_[i]->intervalMaxStr()!=basisf_pntrs_[0]->intervalMaxStr()) { 112 0 : plumed_merror("all the basis functions to be combined should have same MINIMUM and MAXIMUM"); 113 : } 114 5 : if(!basisf_pntrs_[i]->arePeriodic()) { 115 : periodic=false; 116 : } 117 : } 118 2 : setOrder(nbasisf_total_-1); 119 2 : setNumberOfBasisFunctions(nbasisf_total_); 120 4 : setInterval(basisf_pntrs_[0]->intervalMinStr(),basisf_pntrs_[0]->intervalMaxStr()); 121 4 : setIntrinsicInterval("-1.0","+1.0"); 122 2 : if(periodic) { 123 : setPeriodic(); 124 : } else { 125 : setNonPeriodic(); 126 : } 127 : setIntervalBounded(); 128 2 : setType("combined"); 129 2 : setDescription("Combined"); 130 2 : setupBF(); 131 2 : checkRead(); 132 2 : } 133 : 134 : 135 : 136 : 137 3616 : void BF_Combined::getAllValues(const double arg, double& argT, bool& inside_range, std::vector<double>& values, std::vector<double>& derivs) const { 138 : // first BF, constant, argT, and inside_range taken from here 139 : unsigned int r=0; 140 3616 : std::vector<double> values_tmp(basisf_pntrs_[0]->numberOfBasisFunctions(),0.0); 141 3616 : std::vector<double> derivs_tmp(basisf_pntrs_[0]->numberOfBasisFunctions(),0.0); 142 3616 : basisf_pntrs_[0]->getAllValues(arg,argT,inside_range,values_tmp,derivs_tmp); 143 43392 : for(unsigned int l=0; l<basisf_pntrs_[0]->numberOfBasisFunctions(); l++) { 144 39776 : values[r] = values_tmp[l]; 145 39776 : derivs[r] = derivs_tmp[l]; 146 39776 : r++; 147 : } 148 : // other BF 149 9043 : for(unsigned int i=1; i<basisf_pntrs_.size(); i++) { 150 5427 : values_tmp.assign(basisf_pntrs_[i]->numberOfBasisFunctions(),0.0); 151 5427 : derivs_tmp.assign(basisf_pntrs_[i]->numberOfBasisFunctions(),0.0); 152 : double dummy_dbl; 153 5427 : bool dummy_bool=true; 154 5427 : basisf_pntrs_[i]->getAllValues(arg,dummy_dbl,dummy_bool,values_tmp,derivs_tmp); 155 59697 : for(unsigned int l=1; l<basisf_pntrs_[i]->numberOfBasisFunctions(); l++) { 156 54270 : values[r] = values_tmp[l]; 157 54270 : derivs[r] = derivs_tmp[l]; 158 54270 : r++; 159 : } 160 : } 161 3616 : } 162 : 163 : 164 2 : void BF_Combined::setupLabels() { 165 2 : setLabel(0,basisf_pntrs_[0]->getBasisFunctionLabel(0)); 166 : unsigned int r=1; 167 7 : for(unsigned int i=0; i<basisf_pntrs_.size(); i++) { 168 55 : for(unsigned int l=1; l<basisf_pntrs_[i]->numberOfBasisFunctions(); l++) { 169 50 : setLabel(r,basisf_pntrs_[i]->getBasisFunctionLabel(l)); 170 50 : r++; 171 : } 172 : } 173 2 : } 174 : 175 : 176 2 : void BF_Combined::setupUniformIntegrals() { 177 2 : setUniformIntegral(0,basisf_pntrs_[0]->getUniformIntegrals()[0]); 178 : unsigned int r=1; 179 7 : for(unsigned int i=0; i<basisf_pntrs_.size(); i++) { 180 5 : std::vector<double> uniform_tmp = basisf_pntrs_[i]->getUniformIntegrals(); 181 55 : for(unsigned int l=1; l<basisf_pntrs_[i]->numberOfBasisFunctions(); l++) { 182 50 : setUniformIntegral(r,uniform_tmp[l]); 183 50 : r++; 184 : } 185 : } 186 2 : } 187 : 188 : 189 : } 190 : }