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 : 25 : #include "core/ActionRegister.h" 26 : 27 : 28 : namespace PLMD { 29 : namespace ves { 30 : 31 : //+PLUMEDOC VES_BASISF BF_SINE 32 : /* 33 : Fourier sine basis functions. 34 : 35 : Use as basis functions Fourier sine series defined on a periodic interval. 36 : You need to provide the periodic interval \f$[a,b]\f$ 37 : on which the basis functions are to be used, and the order of the 38 : expansion \f$N\f$ (i.e. the highest Fourier sine mode used). 39 : The total number of basis functions is \f$N+1\f$ as 40 : the constant \f$f_{0}(x)=1\f$ is also included. 41 : These basis functions should only be used for periodic CVs. 42 : They can be useful if the periodic function being expanded is an 43 : odd function, i.e. \f$F(-x)=-F(x)\f$. 44 : 45 : The Fourier sine basis functions are given by 46 : \f{align}{ 47 : f_{0}(x) &= 1 \\ 48 : f_{1}(x) &= sin(\frac{2\pi }{P} x) \\ 49 : f_{2}(x) &= sin(2 \cdot \frac{2\pi}{P} x) \\ 50 : f_{3}(x) &= sin(3 \cdot \frac{2\pi}{P} x) \\ 51 : & \vdots \\ 52 : f_{n}(x) &= sin(n \cdot \frac{2\pi}{P} x) \\ 53 : & \vdots \\ 54 : f_{N}(x) &= sin(N \cdot \frac{2\pi}{P} x) \\ 55 : \f} 56 : where \f$P=(b-a)\f$ is the periodicity of the interval. 57 : They are orthogonal over the interval \f$[a,b]\f$ 58 : \f[ 59 : \int_{a}^{b} dx \, f_{n}(x)\, f_{m}(x) = 60 : \begin{cases} 61 : 0 & n \neq m \\ 62 : (b-a) & n = m = 0 \\ 63 : (b-a)/2 & n = m \neq 0 64 : \end{cases}. 65 : \f] 66 : 67 : \par Examples 68 : 69 : Here we employ a Fourier sine expansion of order 10 over the periodic interval 70 : \f$-\pi\f$ to \f$+\pi\f$. 71 : This results in a total number of 11 basis functions. 72 : The label used to identify the basis function action can then be 73 : referenced later on in the input file. 74 : \plumedfile 75 : BF_SINE MINIMUM=-pi MAXIMUM=+pi ORDER=10 LABEL=bfS 76 : \endplumedfile 77 : 78 : \par Examples 79 : 80 : */ 81 : //+ENDPLUMEDOC 82 : 83 : class BF_Sine : public BasisFunctions { 84 : void setupLabels() override; 85 : void setupUniformIntegrals() override; 86 : public: 87 : static void registerKeywords(Keywords&); 88 : explicit BF_Sine(const ActionOptions&); 89 : void getAllValues(const double, double&, bool&, std::vector<double>&, std::vector<double>&) const override; 90 : }; 91 : 92 : 93 10423 : PLUMED_REGISTER_ACTION(BF_Sine,"BF_SINE") 94 : 95 : 96 5 : void BF_Sine::registerKeywords(Keywords& keys) { 97 5 : BasisFunctions::registerKeywords(keys); 98 5 : } 99 : 100 : 101 4 : BF_Sine::BF_Sine(const ActionOptions&ao): 102 4 : PLUMED_VES_BASISFUNCTIONS_INIT(ao) 103 : { 104 4 : setNumberOfBasisFunctions(getOrder()+1); 105 8 : setIntrinsicInterval("-pi","+pi"); 106 : setPeriodic(); 107 : setIntervalBounded(); 108 4 : setType("trigonometric_sin"); 109 4 : setDescription("Sine"); 110 4 : setupBF(); 111 4 : checkRead(); 112 4 : } 113 : 114 : 115 9229 : void BF_Sine::getAllValues(const double arg, double& argT, bool& inside_range, std::vector<double>& values, std::vector<double>& derivs) const { 116 : // plumed_assert(values.size()==numberOfBasisFunctions()); 117 : // plumed_assert(derivs.size()==numberOfBasisFunctions()); 118 9229 : inside_range=true; 119 9229 : argT=translateArgument(arg, inside_range); 120 9229 : values[0]=1.0; 121 9229 : derivs[0]=0.0; 122 101519 : for(unsigned int i=1; i < getOrder()+1; i++) { 123 92290 : double io = i; 124 92290 : double cos_tmp = cos(io*argT); 125 92290 : double sin_tmp = sin(io*argT); 126 92290 : values[i] = sin_tmp; 127 92290 : derivs[i] = io*cos_tmp*intervalDerivf(); 128 : } 129 9229 : if(!inside_range) { 130 960 : for(unsigned int i=0; i<derivs.size(); i++) {derivs[i]=0.0;} 131 : } 132 9229 : } 133 : 134 : 135 4 : void BF_Sine::setupLabels() { 136 4 : setLabel(0,"1"); 137 44 : for(unsigned int i=1; i < getOrder()+1; i++) { 138 40 : std::string is; Tools::convert(i,is); 139 80 : setLabel(i,"sin("+is+"*s)"); 140 : } 141 4 : } 142 : 143 : 144 3 : void BF_Sine::setupUniformIntegrals() { 145 3 : setAllUniformIntegralsToZero(); 146 : setUniformIntegral(0,1.0); 147 3 : } 148 : 149 : 150 : } 151 : }