Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2011-2023 The plumed team
3 : (see the PEOPLE file at the root of the distribution for a list of names)
4 :
5 : See http://www.plumed.org for more information.
6 :
7 : This file is part of plumed, version 2.
8 :
9 : plumed 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 : plumed 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 plumed. If not, see <http://www.gnu.org/licenses/>.
21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 : #include "Combine.h"
23 : #include "FunctionTemplateBase.h"
24 : #include "FunctionShortcut.h"
25 : #include "FunctionOfScalar.h"
26 : #include "FunctionOfVector.h"
27 : #include "FunctionOfMatrix.h"
28 : #include "core/ActionRegister.h"
29 :
30 : namespace PLMD {
31 : namespace function {
32 :
33 : //+PLUMEDOC FUNCTION COMBINE
34 : /*
35 : Calculate a polynomial combination of a set of other variables.
36 :
37 : The functional form of this function is
38 : \f[
39 : C=\sum_{i=1}^{N_{arg}} c_i (x_i-a_i)^{p_i}
40 : \f]
41 :
42 : The coefficients c, the parameters a and the powers p are provided as vectors.
43 :
44 : Notice that COMBINE is not able to predict which will be periodic domain
45 : of the computed value automatically. The user is thus forced to specify it
46 : explicitly. Use PERIODIC=NO if the resulting variable is not periodic,
47 : and PERIODIC=A,B where A and B are the two boundaries if the resulting variable
48 : is periodic.
49 :
50 :
51 :
52 : \par Examples
53 :
54 : The following input tells plumed to print the distance between atoms 3 and 5
55 : its square (as computed from the x,y,z components) and the distance
56 : again as computed from the square root of the square.
57 : \plumedfile
58 : DISTANCE LABEL=dist ATOMS=3,5 COMPONENTS
59 : COMBINE LABEL=distance2 ARG=dist.x,dist.y,dist.z POWERS=2,2,2 PERIODIC=NO
60 : COMBINE LABEL=distance ARG=distance2 POWERS=0.5 PERIODIC=NO
61 : PRINT ARG=distance,distance2
62 : \endplumedfile
63 : (See also \ref PRINT and \ref DISTANCE).
64 :
65 : The following input tells plumed to add a restraint on the
66 : cube of a dihedral angle. Notice that since the angle has a
67 : periodic domain
68 : -pi,pi its cube has a domain -pi**3,pi**3.
69 : \plumedfile
70 : t: TORSION ATOMS=1,3,5,7
71 : c: COMBINE ARG=t POWERS=3 PERIODIC=-31.0062766802998,31.0062766802998
72 : RESTRAINT ARG=c KAPPA=10 AT=0
73 : \endplumedfile
74 :
75 :
76 :
77 : */
78 : //+ENDPLUMEDOC
79 :
80 : //+PLUMEDOC FUNCTION COMBINE_SCALAR
81 : /*
82 : Calculate a polynomial combination of a set of other variables.
83 :
84 : \par Examples
85 :
86 : */
87 : //+ENDPLUMEDOC
88 :
89 : //+PLUMEDOC FUNCTION COMBINE_VECTOR
90 : /*
91 : Add together the elements of a set of vectors elementwise
92 :
93 : \par Examples
94 :
95 : */
96 : //+ENDPLUMEDOC
97 :
98 : //+PLUMEDOC COLVAR COMBINE_MATRIX
99 : /*
100 : Calculate the sum of a number of matrices
101 :
102 : \par Examples
103 :
104 : */
105 : //+ENDPLUMEDOC
106 :
107 : typedef FunctionShortcut<Combine> CombineShortcut;
108 : PLUMED_REGISTER_ACTION(CombineShortcut,"COMBINE")
109 : typedef FunctionOfScalar<Combine> ScalarCombine;
110 : PLUMED_REGISTER_ACTION(ScalarCombine,"COMBINE_SCALAR")
111 : typedef FunctionOfVector<Combine> VectorCombine;
112 : PLUMED_REGISTER_ACTION(VectorCombine,"COMBINE_VECTOR")
113 : typedef FunctionOfMatrix<Combine> MatrixCombine;
114 : PLUMED_REGISTER_ACTION(MatrixCombine,"COMBINE_MATRIX")
115 :
116 1069 : void Combine::registerKeywords(Keywords& keys) {
117 1069 : keys.use("PERIODIC");
118 2138 : keys.add("compulsory","COEFFICIENTS","1.0","the coefficients of the arguments in your function");
119 2138 : keys.add("compulsory","PARAMETERS","0.0","the parameters of the arguments in your function");
120 2138 : keys.add("compulsory","POWERS","1.0","the powers to which you are raising each of the arguments in your function");
121 2138 : keys.addFlag("NORMALIZE",false,"normalize all the coefficients so that in total they are equal to one");
122 2138 : keys.setValueDescription("scalar/vector/matrix","a linear compbination");
123 1069 : }
124 :
125 305 : void Combine::read( ActionWithArguments* action ) {
126 305 : coefficients.resize( action->getNumberOfArguments() ); parameters.resize( action->getNumberOfArguments() ); powers.resize( action->getNumberOfArguments() );
127 609 : parseVector(action,"COEFFICIENTS",coefficients);
128 304 : if(coefficients.size()!=static_cast<unsigned>(action->getNumberOfArguments())) action->error("Size of COEFFICIENTS array should be the same as number for arguments");
129 607 : parseVector(action,"PARAMETERS",parameters);
130 303 : if(parameters.size()!=static_cast<unsigned>(action->getNumberOfArguments())) action->error("Size of PARAMETERS array should be the same as number for arguments");
131 605 : parseVector(action,"POWERS",powers); if(powers.size()!=static_cast<unsigned>(action->getNumberOfArguments())) action->error("Size of POWERS array should be the same as number for arguments");
132 :
133 302 : parseFlag(action,"NORMALIZE",normalize);
134 302 : if(normalize) {
135 : double n=0.0;
136 43 : for(unsigned i=0; i<coefficients.size(); i++) n+=coefficients[i];
137 43 : for(unsigned i=0; i<coefficients.size(); i++) coefficients[i]*=(1.0/n);
138 : }
139 :
140 302 : action->log.printf(" with coefficients:");
141 1503 : for(unsigned i=0; i<coefficients.size(); i++) action->log.printf(" %f",coefficients[i]);
142 302 : action->log.printf("\n with parameters:");
143 1503 : for(unsigned i=0; i<parameters.size(); i++) action->log.printf(" %f",parameters[i]);
144 302 : action->log.printf("\n and powers:");
145 1503 : for(unsigned i=0; i<powers.size(); i++) action->log.printf(" %f",powers[i]);
146 302 : action->log.printf("\n");
147 302 : }
148 :
149 4369194 : void Combine::calc( const ActionWithArguments* action, const std::vector<double>& args, std::vector<double>& vals, Matrix<double>& derivatives ) const {
150 4369194 : vals[0]=0.0;
151 10983373 : for(unsigned i=0; i<coefficients.size(); ++i) {
152 6614179 : double cv = action->difference( i, parameters[i], args[i] );
153 6614179 : vals[0] += coefficients[i]*pow( cv, powers[i] );
154 6614179 : derivatives(0,i) = coefficients[i]*powers[i]*pow(cv,powers[i]-1.0);
155 : }
156 4369194 : }
157 :
158 : }
159 : }
160 :
161 :
|