LCOV - code coverage report
Current view: top level - contour - DistanceFromContourBase.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 75 75 100.0 %
Date: 2024-10-18 13:59:31 Functions: 7 8 87.5 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2016-2023 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 "DistanceFromContourBase.h"
      23             : 
      24             : namespace PLMD {
      25             : namespace contour {
      26             : 
      27           6 : void DistanceFromContourBase::registerKeywords( Keywords& keys ) {
      28           6 :   Action::registerKeywords( keys ); ActionWithValue::registerKeywords( keys );
      29           6 :   ActionAtomistic::registerKeywords( keys ); ActionWithArguments::registerKeywords( keys );
      30           6 :   keys.remove("NUMERICAL_DERIVATIVES");
      31          12 :   keys.addInputKeyword("optional","ARG","vector","the label of the weights to use when constructing the density.  If this keyword is not here the weights are assumed to be one.");
      32          12 :   keys.add("atoms","POSITIONS","the positions of the atoms that we are calculating the contour from");
      33          12 :   keys.add("atoms","ATOM","The atom whose perpendicular distance we are calculating from the contour");
      34          12 :   keys.add("compulsory","BANDWIDTH","the bandwidths for kernel density esimtation");
      35          12 :   keys.add("compulsory","KERNEL","GAUSSIAN","the kernel function you are using.  More details on  the kernels available "
      36             :            "in plumed plumed can be found in \\ref kernelfunctions.");
      37          12 :   keys.add("compulsory","CUTOFF","6.25","the cutoff at which to stop evaluating the kernel functions is set equal to sqrt(2*x)*bandwidth in each direction where x is this number");
      38          12 :   keys.add("compulsory","CONTOUR","the value we would like for the contour");
      39           6 : }
      40             : 
      41           2 : DistanceFromContourBase::DistanceFromContourBase( const ActionOptions& ao ):
      42             :   Action(ao),
      43             :   ActionWithValue(ao),
      44             :   ActionAtomistic(ao),
      45             :   ActionWithArguments(ao),
      46             :   mymin(this),
      47           2 :   nactive(0)
      48             : {
      49           2 :   if( getNumberOfArguments()>1 ) error("should only use one argument for this action");
      50           2 :   if( getNumberOfArguments()==1 ) {
      51           1 :     if( getPntrToArgument(0)->getRank()!=1 ) error("ARG for distance from contour should be rank one");
      52           1 :     getPntrToArgument(0)->buildDataStore();
      53             :   }
      54             :   // Read in the multicolvar/atoms
      55           4 :   std::vector<AtomNumber> atoms; parseAtomList("POSITIONS",atoms);
      56           4 :   std::vector<AtomNumber> origin; parseAtomList("ATOM",origin);
      57           2 :   if( origin.size()!=1 ) error("should only specify one atom for origin keyword");
      58             :   std::vector<AtomNumber> center;
      59           4 :   if( keywords.exists("ORIGIN") ) {
      60           2 :     parseAtomList("ORIGIN",center);
      61           1 :     if( center.size()!=1 ) error("should only specify one atom for center keyword");
      62             :   }
      63             : 
      64           2 :   if( center.size()==1 ) log.printf("  calculating distance between atom %d and contour along vector connecting it to atom %d \n", origin[0].serial(),center[0].serial() );
      65           1 :   else log.printf("  calculating distance between atom %d and contour \n", origin[0].serial() );
      66             : 
      67           2 :   log.printf("  contour is in field constructed from positions of atoms : ");
      68         515 :   for(unsigned i=0; i<atoms.size(); ++i) log.printf("%d ",atoms[i].serial() );
      69           2 :   if( getNumberOfArguments()==1 ) {
      70           1 :     if( getPntrToArgument(0)->getShape()[0]!=atoms.size() ) error("mismatch between number of atoms and size of vector specified using ARG keyword");
      71           1 :     log.printf("\n  and weights from %s \n", getPntrToArgument(0)->getName().c_str() );
      72             :   } else {
      73           1 :     log.printf("\n  all weights are set equal to one \n");
      74             :   }
      75             :   // Request everything we need
      76           2 :   active_list.resize( atoms.size(), 0 );
      77           2 :   std::vector<Value*> args( getArguments() ); atoms.push_back( origin[0] );
      78           2 :   if( center.size()==1 ) atoms.push_back( center[0] );
      79           2 :   requestArguments( args ); requestAtoms( atoms );
      80             :   // Fix to request arguments
      81           2 :   if( args.size()==1 ) addDependency( args[0]->getPntrToAction() );
      82             : 
      83             :   // Read in details of phase field construction
      84           8 :   parseVector("BANDWIDTH",bw); parse("KERNEL",kerneltype); parse("CONTOUR",contour);
      85           4 :   std::string errors; switchingFunction.set( kerneltype + " R_0=1.0 NOSTRETCH", errors );
      86           2 :   if( errors.length()!=0 ) error("problem reading switching function description " + errors);
      87           8 :   double det=1; for(unsigned i=0; i<bw.size(); ++i) det*=bw[i]*bw[i];
      88           2 :   gvol=1.0; if( kerneltype=="GAUSSIAN" ) gvol=pow( 2*pi, 0.5*bw.size() ) * pow( det, 0.5 );
      89           2 :   log.printf("  constructing phase field using %s kernels with bandwidth (%f, %f, %f) \n",kerneltype.c_str(), bw[0], bw[1], bw[2] );
      90             : 
      91             :   // And a cutoff
      92           2 :   std::vector<double> pp( bw.size(),0 );
      93           4 :   double dp2cutoff; parse("CUTOFF",dp2cutoff); double rcut =  sqrt(2*dp2cutoff)*bw[0];
      94           6 :   for(unsigned j=1; j<bw.size(); ++j) {
      95           4 :     if( sqrt(2*dp2cutoff)*bw[j]>rcut ) rcut=sqrt(2*dp2cutoff)*bw[j];
      96             :   }
      97           2 :   rcut2=rcut*rcut;
      98             : 
      99             :   // Create the vector of values that holds the position
     100           2 :   forcesToApply.resize( 3*getNumberOfAtoms() + 9 );
     101           2 : }
     102             : 
     103         154 : void DistanceFromContourBase::lockRequests() {
     104             :   ActionWithArguments::lockRequests();
     105             :   ActionAtomistic::lockRequests();
     106         154 : }
     107             : 
     108         154 : void DistanceFromContourBase::unlockRequests() {
     109             :   ActionWithArguments::unlockRequests();
     110             :   ActionAtomistic::unlockRequests();
     111         154 : }
     112             : 
     113      190081 : double DistanceFromContourBase::evaluateKernel( const Vector& cpos, const Vector& apos, std::vector<double>& der ) const {
     114      190081 :   Vector distance = pbcDistance( getPosition(getNumberOfAtoms()-1), cpos );
     115             :   Vector dist2 = pbcDistance( distance, apos );
     116      760324 :   double dval=0; for(unsigned j=0; j<3; ++j) { der[j] = dist2[j]/bw[j]; dval += der[j]*der[j]; }
     117      190081 :   double dfunc, newval = switchingFunction.calculateSqr( dval, dfunc ) / gvol;
     118      760324 :   double tmp = dfunc / gvol; for(unsigned j=0; j<3; ++j) der[j] *= -tmp;
     119      190081 :   return newval;
     120             : }
     121             : 
     122        3283 : double DistanceFromContourBase::getDifferenceFromContour( const std::vector<double>& x, std::vector<double>& der ) {
     123             :   // Transer the position to the local Vector
     124       13132 :   for(unsigned j=0; j<3; ++j) pval[j] = x[j];
     125             :   // Now find the contour
     126        3283 :   double sumk = 0, sumd = 0; std::vector<double> pp(3), ddd(3,0);
     127      193090 :   for(unsigned i=0; i<nactive; ++i) {
     128      189807 :     double newval = evaluateKernel( getPosition(active_list[i]), pval, ddd );
     129             : 
     130      189807 :     if( getNumberOfArguments()==1 ) {
     131      186966 :       sumk += getPntrToArgument(0)->get(active_list[i])*newval;
     132      186966 :       sumd += newval;
     133        2841 :     } else sumk += newval;
     134             :   }
     135        3283 :   if( getNumberOfArguments()==0 ) return sumk - contour;
     136         442 :   if( fabs(sumk)<epsilon ) return -contour;
     137         195 :   return (sumk/sumd) - contour;
     138             : }
     139             : 
     140         154 : void DistanceFromContourBase::apply() {
     141         154 :   if( !checkForForces() ) return ;
     142         137 :   unsigned ind=0; setForcesOnAtoms( getForcesToApply(), ind );
     143             : }
     144             : 
     145             : }
     146             : }

Generated by: LCOV version 1.16