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
37 :
38 : Without options plotswitch will tabulate 50 points between 0 and R_0, and then continue in tabulating points with the same step until 2*R_0 or if D_MAX is set, D_MAX
39 :
40 : Without options plotswitch will tabulate data calling calculateSqr, since should be the most used option within the various colvars
41 :
42 : Note that if R_0 happen to be between "from" and "to" the number of steps may not be exacly the number requested in order to force r0 to be computed.
43 :
44 : The various --rational** options use the special set option for the rational, like in COORDINATION.
45 :
46 : \par Examples
47 :
48 : Without option will plot the NN=6 MM=12 rational
49 : \verbatim
50 : plumed plotswitch > plot.dat
51 : \endverbatim
52 :
53 : \verbatim
54 : plumed plotswitch --switch="RATIONAL NN=5 MM=9 R_0=1.3" --from=1.29999 --to=1.30001 --steps=100> plot.dat
55 : \endverbatim
56 : If you use this with a older plumed version you will see the discontinuity in dfunc around 1.3
57 : (i use gnuplot with "p 'plot.dat' u 1:3 w l t 'dfunc', 'plot.dat' u 1:2 w l axis x1y2 t 'res'")
58 : */
59 : //+ENDPLUMEDOC
60 :
61 : namespace PLMD {
62 : namespace cltools {
63 : class SwitchingPlotter : public CLTool {
64 : public:
65 : explicit SwitchingPlotter(const CLToolOptions&);
66 : static void registerKeywords( Keywords& );
67 :
68 : int main( FILE*, FILE*, Communicator& ) override;
69 :
70 : };
71 15952 : PLUMED_REGISTER_CLTOOL(SwitchingPlotter,"plotswitch")
72 :
73 5316 : void SwitchingPlotter::registerKeywords( Keywords& keys ) {
74 5316 : CLTool::registerKeywords( keys );
75 10632 : keys.add("compulsory","--switch",
76 : "RATIONAL NN=6 R_0=1.0","the input to pass to the switching function,"
77 : " please remeber the quotes");
78 10632 : keys.add("compulsory","--steps","50",
79 : "the number of steps between 0 and R_O, or in the specified interval");
80 10632 : keys.add("compulsory","--from","-1",
81 : "the start of the interval, if negative will be set to 0");
82 10632 : keys.add("compulsory","--to","-1",
83 : "the end of the interval, will be D_MAX or 2*R_0 if D_MAX is not set");
84 10632 : keys.add("compulsory","--plotprecision","8",
85 : "the precision to use for the tabulated results");
86 10632 : keys.add("compulsory","--rationalR_0","-1",
87 : "The r_0 parameter of the switching function, this will activate the "
88 : "--rational options, note that this will ignore the --switch option silently");
89 10632 : keys.add("compulsory","--rationalNN","6",
90 : "The n parameter of the switching function");
91 10632 : keys.add("compulsory","--rationalMM","0",
92 : "The m parameter of the switching function; 0 implies 2*NN");
93 10632 : keys.add("compulsory","--rationalD_0","0.0",
94 : "The d_0 parameter of the switching function");
95 10632 : keys.addFlag("--nosquare",false,"use calculate instead of calculateSqr");
96 10632 : keys.add("compulsory","--centerrange","-1",
97 : "centers the visualization in R_0 in a range given epsilons times r_0"
98 : ", note that specifying this will overide all the other range options");
99 5316 : }
100 :
101 4 : SwitchingPlotter::SwitchingPlotter(const CLToolOptions& co ):
102 4 : CLTool(co) {
103 4 : inputdata=commandline;
104 4 : }
105 0 : int SwitchingPlotter::main( FILE*, FILE*, Communicator& ) {
106 : //collecting options:
107 : std::string swInput;
108 0 : parse("--switch",swInput);
109 : bool dontOptimize;
110 0 : parseFlag("--nosquare",dontOptimize);
111 : int Nsteps;
112 0 : parse("--steps",Nsteps);
113 : double lowerLimit;
114 0 : parse("--from",lowerLimit);
115 : double upperLimit;
116 0 : parse("--to",upperLimit);
117 : unsigned plotPrecision;
118 0 : parse("--plotprecision",plotPrecision);
119 : int rationalNN;
120 0 : parse("--rationalNN",rationalNN);
121 : int rationalMM;
122 0 : parse("--rationalMM",rationalMM);
123 : double rationalD_0;
124 0 : parse("--rationalD_0",rationalD_0);
125 : double rationalR_0;
126 0 : parse("--rationalR_0",rationalR_0);
127 : //this works only because we use lepton to parse the numbers
128 : double centerrange;
129 0 : parse("--centerrange",centerrange);
130 : //setting up the switching function
131 0 : PLMD::SwitchingFunction switchingFunction;
132 0 : if (rationalR_0>0) {
133 0 : switchingFunction.set(rationalNN,rationalMM,rationalR_0,rationalD_0);
134 : } else {
135 : std::string errors;
136 0 : switchingFunction.set(swInput,errors);
137 0 : if( errors.length()!=0 ) {
138 0 : error("problem reading SWITCH keyword : " + errors );
139 : }
140 : }
141 :
142 : //setting up the limits:
143 0 : const double r0 = switchingFunction.get_r0();
144 0 : const double dmax = switchingFunction.get_dmax();
145 :
146 0 : if (lowerLimit <0) {
147 0 : lowerLimit=0.0;
148 : }
149 0 : if (upperLimit < 0) {
150 0 : upperLimit = dmax;
151 0 : if (! (upperLimit < std::numeric_limits<double>::max())) {
152 0 : upperLimit = 2*r0;
153 : }
154 : }
155 0 : if(centerrange>0) {
156 0 : upperLimit=(1.0+centerrange*PLMD::epsilon)*r0;
157 0 : lowerLimit=(1.0-centerrange*PLMD::epsilon)*r0;
158 : }
159 0 : const double step = [=]() {
160 0 : if(r0 > lowerLimit && r0< upperLimit) {
161 : //this will make the step pass trough r0
162 0 : double interval = (r0-lowerLimit)/(upperLimit-lowerLimit);
163 0 : return (r0-lowerLimit)/(interval *Nsteps);
164 : }
165 0 : return (upperLimit-lowerLimit)/double(Nsteps);
166 0 : }();
167 0 : if (step <0.0) {
168 0 : error("I calculated a negative step");
169 : }
170 :
171 : //finally doing the job
172 : //descriptions starts with the values of "r_0"
173 0 : std::cout <<"#r val dfunc ( r_0="<<switchingFunction.description()<<")\n";
174 0 : double x=lowerLimit;
175 0 : while(x < upperLimit) {
176 0 : double dfunc=0.0;
177 : double res;
178 0 : if(dontOptimize) {
179 0 : res=switchingFunction.calculate(x,dfunc);
180 : } else {
181 0 : res=switchingFunction.calculateSqr(x*x,dfunc);
182 : }
183 0 : std::cout << std::setprecision(plotPrecision) << x << "\t"
184 0 : << std::setprecision(plotPrecision) << res << "\t"
185 0 : << std::setprecision(plotPrecision) << dfunc << '\n';
186 0 : x+=step;
187 : }
188 0 : return 0;
189 : }
190 :
191 : } //namespace cltools
192 : } // namespace PLMD
|