Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2024 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 :
23 : #include "CLTool.h"
24 : #include "core/CLToolRegister.h"
25 : #include "tools/Tools.h"
26 : #include "tools/SwitchingFunction.h"
27 : #include <string>
28 : #include <iostream>
29 : #include <iomanip>
30 : #include <limits>
31 :
32 : //+PLUMEDOC TOOLS plotswitch
33 : /*
34 : plotswitch is a tool that takes a the input of a switching function and tabulates the output on the terminal
35 :
36 : The tabulated data is compatible with gnuplot and numpy.loadtxt so you can use this tool to plot any functions that you plan to use with commands like
37 : [LESS_THAN](LESS_THAN.md) or [MORE_THAN](MORE_THAN.md).
38 :
39 : Without options plotswitch will tabulate 50 points between 0 and `R_0`, and then continue in tabulating points with the same step until the value of `D_MAX` is reached. If
40 : `D_MAX is unset then a value of `2R_0` is used in place of `D_MAX`.
41 :
42 : Without options plotswitch will tabulate data calling calculateSqr, since should be the most used option within the various colvars
43 :
44 : Note that if `R_0` happens to be between "from" and "to" the number of steps may not be exacly the number requested as this command forces the value of the function at r0 to be calculated.
45 :
46 : The various `--rational**` options use the special set option for the rational, like in COORDINATION.
47 :
48 : ## Examples
49 :
50 : If this command is called without options like this:
51 :
52 : ```plumed
53 : plumed plotswitch > plot.dat
54 : ```
55 :
56 : The function calculated is:
57 :
58 : $$
59 : f(x) = \frac{1 - x^6}{1 - x^{12}}
60 : $$
61 :
62 : If you want to use a function that is differnt to this one you use the `--switch` keyword as shown below:
63 :
64 : ```plumed
65 : plumed plotswitch --switch="RATIONAL NN=5 MM=9 R_0=1.3" --from=1.29999 --to=1.30001 --steps=100 > plot.dat
66 : ```
67 :
68 : The `--switch` keyword here takes the input for switching functions that is discussed in the documentation for
69 : [LESS_THAN](LESS_THAN.md). Notice also that if you use this command with an older plumed version you will see a discontinuity in dfunc at around 1.3
70 : (if you use gnuplot with "p 'plot.dat' u 1:3 w l t 'dfunc', 'plot.dat' u 1:2 w l axis x1y2 t 'res'")
71 :
72 : The following example shows another way of generating the `plot.dat` that is output by the command above:
73 :
74 : ```plumed
75 : plumed plotswitch --rationalR_0=1.3 --rationalNN=5 --rationalMM=9 --rationalD_0=0 --from=1.29999 --to=1.30001 --steps=100 > plot.dat
76 : ```
77 :
78 : As with [LESS_THAN](LESS_THAN.md), there is a alternative to `--switch` that can be used for sepcifying the parameters of RATIONAL switching function.
79 :
80 : */
81 : //+ENDPLUMEDOC
82 :
83 : namespace PLMD {
84 : namespace cltools {
85 : class SwitchingPlotter : public CLTool {
86 : public:
87 : explicit SwitchingPlotter(const CLToolOptions&);
88 : static void registerKeywords( Keywords& );
89 :
90 : int main( FILE*, FILE*, Communicator& ) override;
91 :
92 : };
93 16259 : PLUMED_REGISTER_CLTOOL(SwitchingPlotter,"plotswitch")
94 :
95 5418 : void SwitchingPlotter::registerKeywords( Keywords& keys ) {
96 5418 : CLTool::registerKeywords( keys );
97 5418 : keys.add("compulsory","--switch",
98 : "RATIONAL NN=6 R_0=1.0","the input to pass to the switching function,"
99 : " please remeber the quotes");
100 5418 : keys.add("compulsory","--steps","50",
101 : "the number of steps between 0 and R_O, or in the specified interval");
102 5418 : keys.add("compulsory","--from","-1",
103 : "the start of the interval, if negative will be set to 0");
104 5418 : keys.add("compulsory","--to","-1",
105 : "the end of the interval, will be D_MAX or 2*R_0 if D_MAX is not set");
106 5418 : keys.add("compulsory","--plotprecision","8",
107 : "the precision to use for the tabulated results");
108 5418 : keys.add("compulsory","--rationalR_0","-1",
109 : "The r_0 parameter of the switching function, this will activate the "
110 : "--rational options, note that this will ignore the --switch option silently");
111 5418 : keys.add("compulsory","--rationalNN","6",
112 : "The n parameter of the switching function");
113 5418 : keys.add("compulsory","--rationalMM","0",
114 : "The m parameter of the switching function; 0 implies 2*NN");
115 5418 : keys.add("compulsory","--rationalD_0","0.0",
116 : "The d_0 parameter of the switching function");
117 5418 : keys.addFlag("--nosquare",false,"use calculate instead of calculateSqr");
118 5418 : keys.add("compulsory","--centerrange","-1",
119 : "centers the visualization in R_0 in a range given epsilons times r_0"
120 : ", note that specifying this will overide all the other range options");
121 5418 : }
122 :
123 5 : SwitchingPlotter::SwitchingPlotter(const CLToolOptions& co ):
124 5 : CLTool(co) {
125 5 : inputdata=commandline;
126 5 : }
127 0 : int SwitchingPlotter::main( FILE*, FILE*, Communicator& ) {
128 : //collecting options:
129 : std::string swInput;
130 0 : parse("--switch",swInput);
131 : bool dontOptimize;
132 0 : parseFlag("--nosquare",dontOptimize);
133 : int Nsteps;
134 0 : parse("--steps",Nsteps);
135 : double lowerLimit;
136 0 : parse("--from",lowerLimit);
137 : double upperLimit;
138 0 : parse("--to",upperLimit);
139 : unsigned plotPrecision;
140 0 : parse("--plotprecision",plotPrecision);
141 : int rationalNN;
142 0 : parse("--rationalNN",rationalNN);
143 : int rationalMM;
144 0 : parse("--rationalMM",rationalMM);
145 : double rationalD_0;
146 0 : parse("--rationalD_0",rationalD_0);
147 : double rationalR_0;
148 0 : parse("--rationalR_0",rationalR_0);
149 : //this works only because we use lepton to parse the numbers
150 : double centerrange;
151 0 : parse("--centerrange",centerrange);
152 : //setting up the switching function
153 0 : PLMD::SwitchingFunction switchingFunction;
154 0 : if (rationalR_0>0) {
155 0 : switchingFunction.set(rationalNN,rationalMM,rationalR_0,rationalD_0);
156 : } else {
157 : std::string errors;
158 0 : switchingFunction.set(swInput,errors);
159 0 : if( errors.length()!=0 ) {
160 0 : error("problem reading SWITCH keyword : " + errors );
161 : }
162 : }
163 :
164 : //setting up the limits:
165 0 : const double r0 = switchingFunction.get_r0();
166 0 : const double dmax = switchingFunction.get_dmax();
167 :
168 0 : if (lowerLimit <0) {
169 0 : lowerLimit=0.0;
170 : }
171 0 : if (upperLimit < 0) {
172 0 : upperLimit = dmax;
173 0 : if (! (upperLimit < std::numeric_limits<double>::max())) {
174 0 : upperLimit = 2*r0;
175 : }
176 : }
177 0 : if(centerrange>0) {
178 0 : upperLimit=(1.0+centerrange*PLMD::epsilon)*r0;
179 0 : lowerLimit=(1.0-centerrange*PLMD::epsilon)*r0;
180 : }
181 0 : const double step = [=]() {
182 0 : if(r0 > lowerLimit && r0< upperLimit) {
183 : //this will make the step pass trough r0
184 0 : double interval = (r0-lowerLimit)/(upperLimit-lowerLimit);
185 0 : return (r0-lowerLimit)/(interval *Nsteps);
186 : }
187 0 : return (upperLimit-lowerLimit)/double(Nsteps);
188 : }
189 0 : ();
190 0 : if (step <0.0) {
191 0 : error("I calculated a negative step");
192 : }
193 :
194 : //finally doing the job
195 : //descriptions starts with the values of "r_0"
196 0 : std::cout <<"#r val dfunc ( r_0="<<switchingFunction.description()<<")\n";
197 0 : double x=lowerLimit;
198 0 : while(x < upperLimit) {
199 0 : double dfunc=0.0;
200 : double res;
201 0 : if(dontOptimize) {
202 0 : res=switchingFunction.calculate(x,dfunc);
203 : } else {
204 0 : res=switchingFunction.calculateSqr(x*x,dfunc);
205 : }
206 0 : std::cout << std::setprecision(plotPrecision) << x << "\t"
207 0 : << std::setprecision(plotPrecision) << res << "\t"
208 0 : << std::setprecision(plotPrecision) << dfunc << '\n';
209 0 : x+=step;
210 : }
211 0 : return 0;
212 : }
213 :
214 : } //namespace cltools
215 : } // namespace PLMD
|