Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2011-2018 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 "core/ActionWithValue.h"
23 : #include "core/ActionRegister.h"
24 : #include "tools/IFile.h"
25 :
26 : //+PLUMEDOC COLVAR CONSTANT
27 : /*
28 : Create a constant value that can be passed to actions
29 :
30 : Useful in combination with functions that
31 : takes in input constants or parameters.
32 :
33 : \par Examples
34 :
35 : The following input instructs plumed to compute the distance
36 : between atoms 1 and 2. If this distance is between 1.0 and 2.0, it is
37 : printed. If it is lower than 1.0 (larger than 2.0), 1.0 (2.0) is printed
38 :
39 : \plumedfile
40 : cn: CONSTANT VALUES=1.0,2.0
41 : dis: DISTANCE ATOMS=1,2
42 : sss: SORT ARG=cn.v-0,dis,cn.v-1
43 : PRINT ARG=sss.2
44 : \endplumedfile
45 :
46 : In case you want to pass a single value you can use VALUE:
47 : \plumedfile
48 : cn: CONSTANT VALUE=1.0
49 : dis: DISTANCE ATOMS=1,2
50 : sss: SORT ARG=cn,dis
51 : PRINT ARG=sss.1
52 : \endplumedfile
53 :
54 : */
55 : //+ENDPLUMEDOC
56 :
57 : namespace PLMD {
58 : namespace generic {
59 :
60 : class Constant : public ActionWithValue {
61 : public:
62 : static void registerKeywords( Keywords& keys );
63 : explicit Constant(const ActionOptions&ao);
64 0 : void clearDerivatives( const bool& force=false ) {}
65 6041 : unsigned getNumberOfDerivatives() override {
66 6041 : return 0;
67 : }
68 0 : void calculate() override {}
69 0 : void apply() override {}
70 : };
71 :
72 : PLUMED_REGISTER_ACTION(Constant,"CONSTANT")
73 :
74 1510 : void Constant::registerKeywords( Keywords& keys ) {
75 1510 : Action::registerKeywords(keys);
76 1510 : ActionWithValue::registerKeywords(keys);
77 1510 : keys.remove("NUMERICAL_DERIVATIVES");
78 3020 : keys.add("optional","FILE","an input file containing the matrix");
79 3020 : keys.add("compulsory","NROWS","0","the number of rows in your input matrix");
80 3020 : keys.add("compulsory","NCOLS","0","the number of columns in your matrix");
81 3020 : keys.add("optional","VALUE","the single number that you would like to store");
82 3020 : keys.add("optional","VALUES","the numbers that are in your constant value");
83 3020 : keys.addFlag("SCALARS",false,"treat the input list of numbers as a set of scalars");
84 3020 : keys.addFlag("NOLOG",false,"do not report all the read in scalars in the log");
85 3020 : keys.addOutputComponent("v","SCALARS","the # value");
86 1510 : keys.setValueDescription("the constant value that was read from the plumed input");
87 1510 : }
88 :
89 851 : Constant::Constant(const ActionOptions&ao):
90 : Action(ao),
91 851 : ActionWithValue(ao) {
92 851 : bool nolog=false;
93 851 : parseFlag("NOLOG",nolog);
94 851 : bool scalars=false;
95 : std::string fname, vname;
96 1702 : parse("FILE",fname);
97 : std::vector<unsigned> shape;
98 : std::vector<double> vals;
99 851 : if( fname.length()>0 ) {
100 3 : IFile mfile;
101 3 : mfile.open(fname);
102 : // Read in first line
103 : std::vector<std::string> words;
104 : unsigned nline=0;
105 6 : while( nline==0 ) {
106 3 : Tools::getParsedLine( mfile, words );
107 3 : nline=words.size();
108 : }
109 : std::vector<std::vector<double> > dissimilarities;
110 3 : if( nline==1 ) {
111 0 : shape.resize(1);
112 0 : error("invalid matrix in input file");
113 : }
114 3 : shape.resize(2);
115 3 : shape[1]=nline;
116 3 : std::vector<double> tmpdis( shape[1] );
117 34 : for(unsigned j=0; j<shape[1]; ++j) {
118 31 : Tools::convert( words[j], tmpdis[j] );
119 : }
120 3 : dissimilarities.push_back( tmpdis );
121 :
122 31 : while( Tools::getParsedLine( mfile, words ) ) {
123 28 : if( words.size()!=nline ) {
124 0 : error("bad formatting in matrix file");
125 : }
126 360 : for(unsigned j=0; j<nline; ++j) {
127 332 : Tools::convert( words[j], tmpdis[j] );
128 : }
129 28 : dissimilarities.push_back( tmpdis );
130 : }
131 3 : mfile.close();
132 3 : shape[0] = dissimilarities.size();
133 3 : vals.resize(shape[0]);
134 3 : if( shape.size()==2 ) {
135 3 : vals.resize( shape[0]*shape[1] );
136 : }
137 34 : for(unsigned i=0; i<shape[0]; ++i) {
138 394 : for(unsigned j=0; j<nline; ++j) {
139 363 : vals[i*nline+j] = dissimilarities[i][j];
140 : }
141 : }
142 3 : } else {
143 : unsigned nr, nc;
144 848 : parse("NROWS",nr);
145 848 : parse("NCOLS",nc);
146 848 : if( nr>0 && nc>0 ) {
147 73 : shape.resize(2);
148 73 : shape[0]=nr;
149 73 : shape[1]=nc;
150 73 : vals.resize( nr*nc );
151 73 : log.printf(" reading in %d by %d matrix \n", nr, nc );
152 775 : } else if( nr>0 || nc>0 ) {
153 0 : error("makes no sense to set only one of NROWS and NCOLS to a non-zero value");
154 : }
155 848 : parseVector("VALUES",vals);
156 1696 : parseFlag("SCALARS",scalars);
157 848 : if( vals.size()==0 ) {
158 132 : parseVector("VALUE",vals);
159 66 : if( vals.size()!=1 ) {
160 0 : error("VALUE keyword should take a single scalar");
161 : }
162 782 : } else if( vals.size()==1 ) {
163 236 : scalars=false;
164 : }
165 :
166 848 : log.printf(" read in %d values :", vals.size() );
167 848 : if( !nolog ) {
168 25705 : for(unsigned i=0; i<vals.size(); ++i) {
169 25112 : log.printf(" %f", vals[i] );
170 : }
171 : }
172 848 : log.printf("\n");
173 848 : if( !scalars && shape.size()==0 && vals.size()>1 ) {
174 472 : shape.resize(1);
175 472 : shape[0] = vals.size();
176 : }
177 : }
178 851 : if( !scalars ) {
179 : // Now set the value
180 850 : addValue( shape );
181 850 : setNotPeriodic();
182 850 : getPntrToComponent(0)->setConstant();
183 147242 : for(unsigned i=0; i<vals.size(); ++i) {
184 146392 : getPntrToComponent(0)->set( i, vals[i] );
185 : }
186 : } else {
187 3 : for(unsigned i=0; i<vals.size(); i++) {
188 : std::string num;
189 2 : Tools::convert(i,num);
190 4 : addComponent("v-"+num);
191 2 : componentIsNotPeriodic("v-"+num);
192 2 : Value* comp=getPntrToComponent("v-"+num);
193 2 : comp->setConstant();
194 2 : comp->set(vals[i]);
195 : }
196 : }
197 851 : }
198 :
199 : }
200 : }
201 :
|