LCOV - code coverage report
Current view: top level - function - Moments.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 38 48 79.2 %
Date: 2024-10-18 14:00:25 Functions: 5 7 71.4 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2011-2017 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 "FunctionShortcut.h"
      23             : #include "FunctionOfScalar.h"
      24             : #include "FunctionOfVector.h"
      25             : #include "core/ActionRegister.h"
      26             : #include "FunctionTemplateBase.h"
      27             : 
      28             : #include <cmath>
      29             : 
      30             : namespace PLMD {
      31             : namespace function {
      32             : 
      33             : //+PLUMEDOC FUNCTION MOMENTS
      34             : /*
      35             : Calculate the moments of the distribution of input quantities
      36             : 
      37             : \par Examples
      38             : 
      39             : */
      40             : //+ENDPLUMEDOC
      41             : 
      42             : //+PLUMEDOC FUNCTION MOMENTS_SCALAR
      43             : /*
      44             : Calculate the moments of the distribution of input quantities
      45             : 
      46             : \par Examples
      47             : 
      48             : */
      49             : //+ENDPLUMEDOC
      50             : 
      51             : //+PLUMEDOC FUNCTION MOMENTS_VECTOR
      52             : /*
      53             : Calculate the moments of the distribution of input vectors
      54             : 
      55             : \par Examples
      56             : 
      57             : */
      58             : //+ENDPLUMEDOC
      59             : 
      60          56 : class Moments : public FunctionTemplateBase {
      61             :   bool isperiodic, scalar_out;
      62             :   double min, max, pfactor;
      63             :   std::vector<int> powers;
      64             : public:
      65             :   void registerKeywords(Keywords& keys) override;
      66             :   void read( ActionWithArguments* action ) override;
      67           7 :   bool zeroRank() const override { return scalar_out; }
      68         221 :   bool doWithTasks() const override { return !scalar_out; }
      69             :   std::vector<std::string> getComponentsPerLabel() const override ;
      70             :   void setPeriodicityForOutputs( ActionWithValue* action ) override;
      71             :   void calc( const ActionWithArguments* action, const std::vector<double>& args, std::vector<double>& vals, Matrix<double>& derivatives ) const override;
      72             : };
      73             : 
      74             : typedef FunctionShortcut<Moments> MomentsShortcut;
      75             : PLUMED_REGISTER_ACTION(MomentsShortcut,"MOMENTS")
      76             : typedef FunctionOfScalar<Moments> ScalarMoments;
      77             : PLUMED_REGISTER_ACTION(ScalarMoments,"MOMENTS_SCALAR")
      78             : typedef FunctionOfVector<Moments> VectorMoments;
      79             : PLUMED_REGISTER_ACTION(VectorMoments,"MOMENTS_VECTOR")
      80             : 
      81          27 : void Moments::registerKeywords(Keywords& keys) {
      82          54 :   keys.add("compulsory","POWERS","calculate the central moments of the distribution of collective variables. "
      83             :            "The \\f$m\\f$th central moment of a distribution is calculated using \\f$\\frac{1}{N} \\sum_{i=1}^N ( s_i - \\overline{s} )^m \\f$, where \\f$\\overline{s}\\f$ is "
      84             :            "the average for the distribution. The POWERS keyword takes a lists of integers as input or a range. Each integer is a value of \\f$m\\f$. The final "
      85             :            "calculated values can be referenced using moment-\\f$m\\f$.");
      86          54 :   keys.addOutputComponent("moment","default","the central moments of the distribution of values. The second central moment "
      87             :                           "would be referenced elsewhere in the input file using "
      88             :                           "<em>label</em>.moment-2, the third as <em>label</em>.moment-3, etc.");
      89          27 : }
      90             : 
      91           5 : void Moments::read( ActionWithArguments* action ) {
      92           5 :   scalar_out = action->getNumberOfArguments()==1;
      93           5 :   if( scalar_out && action->getPntrToArgument(0)->getRank()==0 ) action->error("cannot calculate moments if only given one variable");
      94             : 
      95           5 :   isperiodic = (action->getPntrToArgument(0))->isPeriodic();
      96           5 :   if( isperiodic ) {
      97           0 :     std::string str_min, str_max; (action->getPntrToArgument(0))->getDomain( str_min, str_max );
      98           0 :     for(unsigned i=1; i<action->getNumberOfArguments(); ++i) {
      99           0 :       if( !(action->getPntrToArgument(i))->isPeriodic() ) action->error("cannot mix periodic and non periodic variables when calculating moments");
     100           0 :       std::string str_min2, str_max2; (action->getPntrToArgument(i))->getDomain( str_min2, str_max2);
     101           0 :       if( str_min!=str_min2 || str_max!=str_max2 ) action->error("all input arguments should have same domain when calculating moments");
     102             :     }
     103           0 :     Tools::convert(str_min,min); Tools::convert(str_max,max); pfactor = 2*pi / ( max-min );
     104             :   } else {
     105          14 :     for(unsigned i=1; i<action->getNumberOfArguments(); ++i) {
     106           9 :       if( (action->getPntrToArgument(i))->isPeriodic() ) action->error("cannot mix periodic and non periodic variables when calculating moments");
     107             :     }
     108             :   }
     109             : 
     110           5 :   parseVector(action,"POWERS",powers);
     111          13 :   for(unsigned i=0; i<powers.size(); ++i) {
     112           8 :     if( powers[i]<2 ) action->error("first central moment is zero do you really need to calculate that");
     113           8 :     action->log.printf("  computing %dth central moment of distribution of input cvs \n", powers[i]);
     114             :   }
     115           5 : }
     116             : 
     117           5 : std::vector<std::string> Moments::getComponentsPerLabel() const {
     118             :   std::vector<std::string> comp; std::string num;
     119          13 :   for(unsigned i=0; i<powers.size(); ++i) {
     120          16 :     Tools::convert(powers[i],num); comp.push_back( "-" + num );
     121             :   }
     122           5 :   return comp;
     123           0 : }
     124             : 
     125           5 : void Moments::setPeriodicityForOutputs( ActionWithValue* action ) {
     126          13 :   for(unsigned i=0; i<powers.size(); ++i) { std::string num; Tools::convert(powers[i],num); action->componentIsNotPeriodic("moment-" + num); }
     127           5 : }
     128             : 
     129         222 : void Moments::calc( const ActionWithArguments* action, const std::vector<double>& args, std::vector<double>& vals, Matrix<double>& derivatives ) const {
     130         222 :   double mean=0; double inorm = 1.0 / static_cast<double>( args.size() );
     131         222 :   if( isperiodic ) {
     132             :     double sinsum=0, cossum=0, val;
     133           0 :     for(unsigned i=0; i<args.size(); ++i) { val=pfactor*( args[i] - min ); sinsum+=sin(val); cossum+=cos(val); }
     134           0 :     mean = 0.5 + atan2( inorm*sinsum, inorm*cossum ) / (2*pi);
     135           0 :     mean = min + (max-min)*mean;
     136             :   } else {
     137        1758 :     for(unsigned i=0; i<args.size(); ++i) mean+=args[i];
     138         222 :     mean *= inorm;
     139             :   }
     140             : 
     141             :   Value* arg0 = action->getPntrToArgument(0);
     142         656 :   for(unsigned npow=0; npow<powers.size(); ++npow) {
     143             :     double dev1=0;
     144        3406 :     for(unsigned i=0; i<args.size(); ++i) dev1+=pow( arg0->difference( mean, args[i] ), powers[npow] - 1 );
     145         434 :     dev1*=inorm; vals[npow] = 0; double prefactor = powers[npow]*inorm;
     146        3406 :     for(unsigned i=0; i<args.size(); ++i) {
     147        2972 :       double tmp=arg0->difference( mean, args[i] ); vals[npow] += inorm*pow( tmp, powers[npow] );
     148        2972 :       derivatives(npow,i) = prefactor*(pow( tmp, powers[npow] - 1 ) - dev1);
     149             :     }
     150             :   }
     151         222 : }
     152             : 
     153             : }
     154             : }
     155             : 
     156             : 

Generated by: LCOV version 1.16