LCOV - code coverage report
Current view: top level - cltools - SwitchingPlotter.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 19 68 27.9 %
Date: 2025-04-08 21:11:17 Functions: 5 7 71.4 %

          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

Generated by: LCOV version 1.16