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 { return 0; }
66 0 : void calculate() override {}
67 0 : void apply() override {}
68 : };
69 :
70 : PLUMED_REGISTER_ACTION(Constant,"CONSTANT")
71 :
72 1508 : void Constant::registerKeywords( Keywords& keys ) {
73 1508 : Action::registerKeywords(keys); ActionWithValue::registerKeywords(keys); keys.remove("NUMERICAL_DERIVATIVES");
74 3016 : keys.add("optional","FILE","an input file containing the matrix");
75 3016 : keys.add("compulsory","NROWS","0","the number of rows in your input matrix");
76 3016 : keys.add("compulsory","NCOLS","0","the number of columns in your matrix");
77 3016 : keys.add("optional","VALUE","the single number that you would like to store");
78 3016 : keys.add("optional","VALUES","the numbers that are in your constant value");
79 3016 : keys.addFlag("SCALARS",false,"treat the input list of numbers as a set of scalars");
80 3016 : keys.addFlag("NOLOG",false,"do not report all the read in scalars in the log");
81 3016 : keys.addOutputComponent("v","SCALARS","scalar","the # value");
82 3016 : keys.setValueDescription("scalar/vector/matrix","the constant value that was read from the plumed input");
83 1508 : }
84 :
85 851 : Constant::Constant(const ActionOptions&ao):
86 : Action(ao),
87 851 : ActionWithValue(ao)
88 : {
89 851 : bool nolog=false; parseFlag("NOLOG",nolog);
90 1702 : bool scalars=false; std::string fname, vname; parse("FILE",fname);
91 : std::vector<unsigned> shape; std::vector<double> vals;
92 851 : if( fname.length()>0 ) {
93 3 : IFile mfile; mfile.open(fname);
94 : // Read in first line
95 : std::vector<std::string> words; unsigned nline=0;
96 6 : while( nline==0 ) {
97 3 : Tools::getParsedLine( mfile, words );
98 3 : nline=words.size();
99 : }
100 : std::vector<std::vector<double> > dissimilarities;
101 3 : if( nline==1 ) {
102 0 : shape.resize(1);
103 0 : error("invalid matrix in input file");
104 : }
105 3 : shape.resize(2); shape[1]=nline;
106 3 : std::vector<double> tmpdis( shape[1] );
107 34 : for(unsigned j=0; j<shape[1]; ++j) Tools::convert( words[j], tmpdis[j] );
108 3 : dissimilarities.push_back( tmpdis );
109 :
110 31 : while( Tools::getParsedLine( mfile, words ) ) {
111 28 : if( words.size()!=nline ) error("bad formatting in matrix file");
112 360 : for(unsigned j=0; j<nline; ++j) Tools::convert( words[j], tmpdis[j] );
113 28 : dissimilarities.push_back( tmpdis );
114 : }
115 3 : mfile.close(); shape[0] = dissimilarities.size(); vals.resize(shape[0]);
116 3 : if( shape.size()==2 ) vals.resize( shape[0]*shape[1] );
117 34 : for(unsigned i=0; i<shape[0]; ++i) {
118 394 : for(unsigned j=0; j<nline; ++j) vals[i*nline+j] = dissimilarities[i][j];
119 : }
120 3 : } else {
121 1696 : unsigned nr, nc; parse("NROWS",nr); parse("NCOLS",nc);
122 848 : if( nr>0 && nc>0 ) {
123 73 : shape.resize(2); shape[0]=nr; shape[1]=nc; vals.resize( nr*nc );
124 73 : log.printf(" reading in %d by %d matrix \n", nr, nc );
125 775 : } else if( nr>0 || nc>0 ) error("makes no sense to set only one of NROWS and NCOLS to a non-zero value");
126 2544 : parseVector("VALUES",vals); parseFlag("SCALARS",scalars);
127 848 : if( vals.size()==0 ) {
128 132 : parseVector("VALUE",vals);
129 66 : if( vals.size()!=1 ) error("VALUE keyword should take a single scalar");
130 782 : } else if( vals.size()==1 ) scalars=false;
131 :
132 848 : log.printf(" read in %d values :", vals.size() );
133 26553 : if( !nolog ) { for(unsigned i=0; i<vals.size(); ++i) log.printf(" %f", vals[i] ); }
134 848 : log.printf("\n");
135 848 : if( !scalars && shape.size()==0 && vals.size()>1 ) { shape.resize(1); shape[0] = vals.size(); }
136 : }
137 851 : if( !scalars ) {
138 : // Now set the value
139 850 : addValue( shape ); setNotPeriodic(); getPntrToComponent(0)->setConstant();
140 147242 : for(unsigned i=0; i<vals.size(); ++i) getPntrToComponent(0)->set( i, vals[i] );
141 : } else {
142 3 : for(unsigned i=0; i<vals.size(); i++) {
143 2 : std::string num; Tools::convert(i,num);
144 4 : addComponent("v-"+num); componentIsNotPeriodic("v-"+num);
145 2 : Value* comp=getPntrToComponent("v-"+num);
146 2 : comp->setConstant(); comp->set(vals[i]);
147 : }
148 : }
149 851 : }
150 :
151 : }
152 : }
153 :
|