LCOV - code coverage report
Current view: top level - colvar - GyrationShortcut.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 52 93 55.9 %
Date: 2024-10-18 13:59:31 Functions: 2 3 66.7 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2012-2020 The plumed team
       3             :    (see the PEOPLE file at the root of the distribution for a list of names)
       4             :    See http://www.plumed.org for more information.
       5             :    This file is part of plumed, version 2.
       6             :    plumed is free software: you can redistribute it and/or modify
       7             :    it under the terms of the GNU Lesser General Public License as published by
       8             :    the Free Software Foundation, either version 3 of the License, or
       9             :    (at your option) any later version.
      10             :    plumed is distributed in the hope that it will be useful,
      11             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             :    GNU Lesser General Public License for more details.
      14             :    You should have received a copy of the GNU Lesser General Public License
      15             :    along with plumed.  If not, see <http://www.gnu.org/licenses/>.
      16             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      17             : #include "core/ActionRegister.h"
      18             : #include "core/PlumedMain.h"
      19             : #include "core/ActionSet.h"
      20             : #include "core/ActionWithValue.h"
      21             : #include "core/ActionShortcut.h"
      22             : 
      23             : namespace PLMD {
      24             : namespace colvar {
      25             : 
      26             : //+PLUMEDOC COLVAR GYRATION
      27             : /*
      28             : Calculate the radius of gyration, or other properties related to it.
      29             : 
      30             : With this version of the command you can use any property you so choose to define the weights that are used when computing the average.
      31             : If you use the mass or if all the atoms are ascribed weights of one PLUMED defaults to \ref GYRATION_FAST
      32             : 
      33             : \par Examples
      34             : 
      35             : */
      36             : //+ENDPLUMEDOC
      37             : 
      38             : //+PLUMEDOC MCOLVAR GYRATION_TENSOR
      39             : /*
      40             : Calculate the gyration tensor using a user specified vector of weights
      41             : 
      42             : \par Examples
      43             : 
      44             : */
      45             : //+ENDPLUMEDOC
      46             : 
      47             : class GyrationShortcut : public ActionShortcut {
      48             : public:
      49             :   static void registerKeywords( Keywords& keys );
      50             :   explicit GyrationShortcut(const ActionOptions&);
      51             : };
      52             : 
      53             : PLUMED_REGISTER_ACTION(GyrationShortcut,"GYRATION")
      54             : PLUMED_REGISTER_ACTION(GyrationShortcut,"GYRATION_TENSOR")
      55             : 
      56         122 : void GyrationShortcut::registerKeywords( Keywords& keys ) {
      57         122 :   ActionShortcut::registerKeywords( keys );
      58         244 :   keys.add("atoms","ATOMS","the group of atoms that you are calculating the Gyration Tensor for");
      59         244 :   keys.add("compulsory","TYPE","RADIUS","The type of calculation relative to the Gyration Tensor you want to perform");
      60         244 :   keys.addFlag("NOPBC",false,"ignore the periodic boundary conditions when calculating distances");
      61         244 :   keys.add("optional","WEIGHTS","what weights should be used when calculating the center.  If this keyword is not present the geometric center is computed. "
      62             :            "If WEIGHTS=@Masses is used the center of mass is computed.  If WEIGHTS=@charges the center of charge is computed.  If "
      63             :            "the label of an action is provided PLUMED assumes that that action calculates a list of symmetry functions that can be used "
      64             :            "as weights. Lastly, an explicit list of numbers to use as weights can be provided");
      65         244 :   keys.addFlag("PHASES",false,"use trigonometric phases when computing position of center of mass");
      66         244 :   keys.addFlag("MASS",false,"calculate the center of mass");
      67         244 :   keys.addFlag("MASS_WEIGHTED",false,"set the masses of all the atoms equal to one");
      68         244 :   keys.addFlag("UNORMALIZED",false,"do not divide by the sum of the weights");
      69         360 :   if( keys.getDisplayName()=="GYRATION" ) keys.setValueDescription("scalar","the radius that was computed from the weights");
      70          18 :   else if( keys.getDisplayName()=="GYRATION_TENSOR" ) keys.setValueDescription("matrix","the gyration tensor that was computed from the weights");
      71         366 :   keys.addActionNameSuffix("_FAST"); keys.needsAction("CENTER"); keys.needsAction("CONSTANT");
      72         366 :   keys.needsAction("ONES"); keys.needsAction("MASS"); keys.needsAction("DISTANCE");
      73         244 :   keys.needsAction("COVARIANCE_MATRIX"); keys.needsAction("SELECT_COMPONENTS");
      74         366 :   keys.needsAction("SUM"); keys.needsAction("CUSTOM"); keys.needsAction("DIAGONALIZE");
      75         122 : }
      76             : 
      77         116 : GyrationShortcut::GyrationShortcut(const ActionOptions& ao):
      78             :   Action(ao),
      79         116 :   ActionShortcut(ao)
      80             : {
      81         348 :   bool usemass, phases; parseFlag("MASS",usemass); parseFlag("PHASES",phases);
      82         232 :   std::vector<std::string> str_weights; parseVector("WEIGHTS",str_weights); std::string wflab;
      83         116 :   if( !phases ) {
      84         115 :     if( usemass || str_weights.size()==0 || (str_weights.size()==1 && str_weights[0]=="@Masses") ) {
      85             :       std::string wt_str;
      86         112 :       if( str_weights.size()>0 ) {
      87           0 :         wt_str="WEIGHTS=" + str_weights[0]; for(unsigned i=1; i<str_weights.size(); ++i) wt_str += "," + str_weights[i];
      88             :       }
      89         112 :       if( usemass || (str_weights.size()==1 && str_weights[0]=="@Masses") ) wt_str = "MASS";
      90         232 :       readInputLine( getShortcutLabel() + ": GYRATION_FAST " + wt_str + " " + convertInputLineToString() );
      91             :       return;
      92             :     }
      93             :   }
      94           4 :   if( usemass ) { str_weights.resize(1); str_weights[0]="@Masses"; }
      95          10 :   log<<"  Bibliography "<<plumed.cite("Jirí Vymetal and Jirí Vondrasek, J. Phys. Chem. A 115, 11455 (2011)")<<"\n";
      96             :   // Read in the atoms involved
      97           8 :   std::vector<std::string> atoms; parseVector("ATOMS",atoms); Tools::interpretRanges(atoms);
      98          12 :   std::string gtype, atlist=atoms[0]; for(unsigned i=1; i<atoms.size(); ++i) atlist += "," + atoms[i];
      99           8 :   bool nopbc; parseFlag("NOPBC",nopbc); std::string pbcstr; if(nopbc) pbcstr = " NOPBC";
     100           4 :   std::string phasestr; if(phases) phasestr = " PHASES";
     101             :   // Create the geometric center of the molecule
     102           4 :   std::string weights_str=" WEIGHTS=" + str_weights[0];
     103           8 :   for(unsigned i=1; i<str_weights.size(); ++i) weights_str += "," + str_weights[i];
     104           8 :   readInputLine( getShortcutLabel() + "_cent: CENTER ATOMS=" + atlist + pbcstr + phasestr + weights_str );
     105           4 :   if( str_weights.size()==0 ) {
     106           0 :     wflab = getShortcutLabel() + "_w"; std::string str_natoms; Tools::convert( atoms.size(), str_natoms );
     107           0 :     readInputLine( getShortcutLabel() + "_w: ONES SIZE=" + str_natoms );
     108           6 :   } else if( str_weights.size()==1 && str_weights[0]=="@Masses" ) {
     109           0 :     wflab = getShortcutLabel() + "_m";
     110           0 :     readInputLine( getShortcutLabel() + "_m: MASS ATOMS=" + atlist );
     111           4 :   } else if( str_weights.size()>1 ) {
     112           6 :     std::string vals=str_weights[0]; for(unsigned i=1; i<str_weights.size(); ++i) vals += "," + str_weights[i];
     113           6 :     readInputLine( getShortcutLabel() + "_w: CONSTANT VALUES=" + vals ); wflab=getShortcutLabel() + "_w";
     114             :   } else {
     115           2 :     plumed_assert( str_weights.size()==1 ); wflab = getShortcutLabel() + "_cent_w";
     116           2 :     ActionWithValue* av=plumed.getActionSet().selectWithLabel<ActionWithValue*>( wflab );
     117           2 :     if( !av ) { wflab = str_weights[0]; }
     118             :   }
     119             :   // Check for normalisation
     120           8 :   bool unorm; parseFlag("UNORMALIZED",unorm);
     121             :   // Find out the type
     122           4 :   if( getName()!="GYRATION_TENSOR" ) {
     123           0 :     parse("TYPE",gtype);
     124           0 :     if( gtype!="RADIUS" && gtype!="TRACE" && gtype!="GTPC_1" && gtype!="GTPC_2" && gtype!="GTPC_3" && gtype!="ASPHERICITY" && gtype!="ACYLINDRICITY"
     125           0 :         && gtype!= "KAPPA2" && gtype!="RGYR_1" && gtype!="RGYR_2" && gtype!="RGYR_3" ) error("type " + gtype + " is invalid");
     126             :     // Check if we need to calculate the unormlised radius
     127           0 :     if( gtype=="TRACE" || gtype=="KAPPA2" ) unorm=true;
     128             :   }
     129             :   // Compute all the vectors separating all the positions from the center
     130           4 :   std::string distance_act = getShortcutLabel() + "_dists: DISTANCE COMPONENTS" + pbcstr;
     131          28 :   for(unsigned i=0; i<atoms.size(); ++i) { std::string num; Tools::convert( i+1, num ); distance_act += " ATOMS" + num + "=" + getShortcutLabel() + "_cent," + atoms[i]; }
     132           4 :   readInputLine( distance_act );
     133             :   // And calculate the covariance
     134           4 :   std::string norm_str; if( unorm ) norm_str = " UNORMALIZED";
     135           4 :   if( getName()=="GYRATION_TENSOR" ) {
     136           8 :     readInputLine( getShortcutLabel() + ": COVARIANCE_MATRIX ARG=" + getShortcutLabel() + "_dists.x," + getShortcutLabel() + "_dists.y," + getShortcutLabel() + "_dists.z WEIGHTS=" + wflab + norm_str );
     137             :     return;
     138             :   }
     139           0 :   readInputLine( getShortcutLabel() + "_tensor: COVARIANCE_MATRIX ARG=" + getShortcutLabel() + "_dists.x," + getShortcutLabel() + "_dists.y," + getShortcutLabel() + "_dists.z WEIGHTS=" + wflab + norm_str );
     140             :   // Pick out the diagonal elements
     141           0 :   readInputLine( getShortcutLabel() + "_diag_elements: SELECT_COMPONENTS ARG=" + getShortcutLabel() + "_tensor COMPONENTS=1.1,2.2,3.3");
     142           0 :   if( gtype=="RADIUS") {
     143             :     // And now we need the average trace for the gyration radius
     144           0 :     readInputLine( getShortcutLabel() + "_trace: SUM ARG=" + getShortcutLabel() + "_diag_elements PERIODIC=NO");
     145             :     // Square root the radius
     146           0 :     readInputLine( getShortcutLabel() + ": CUSTOM ARG=" + getShortcutLabel() + "_trace FUNC=sqrt(x) PERIODIC=NO");
     147           0 :   } else if( gtype=="TRACE" ) {
     148             :     // Compte the trace of the gyration tensor
     149           0 :     readInputLine( getShortcutLabel() + "_trace: SUM ARG=" + getShortcutLabel() + "_diag_elements PERIODIC=NO");
     150             :     // And double it
     151           0 :     readInputLine( getShortcutLabel() + ": CUSTOM ARG=" + getShortcutLabel() + "_trace FUNC=2*x PERIODIC=NO");
     152             :   } else {
     153             :     // Diagonalize the gyration tensor
     154           0 :     readInputLine( getShortcutLabel() + "_diag: DIAGONALIZE ARG=" + getShortcutLabel() + "_tensor VECTORS=all" );
     155           0 :     if( gtype.find("GTPC")!=std::string::npos ) {
     156           0 :       std::size_t und=gtype.find_first_of("_"); if( und==std::string::npos ) error( gtype + " is not a valid type for gyration radius");
     157           0 :       std::string num = gtype.substr(und+1); if( num!="1" && num!="2" && num!="3" ) error( gtype + " is not a valid type for gyration radius");
     158             :       // Now get the appropriate eigenvalue
     159           0 :       readInputLine( getShortcutLabel() + ": CUSTOM ARG=" + getShortcutLabel() + "_diag.vals-" + num + " FUNC=sqrt(x) PERIODIC=NO");
     160           0 :     } else if( gtype.find("RGYR")!=std::string::npos ) {
     161           0 :       std::size_t und=gtype.find_first_of("_"); if( und==std::string::npos ) error( gtype + " is not a valid type for gyration radius");
     162           0 :       unsigned ind; Tools::convert( gtype.substr(und+1), ind );
     163             :       // Now get the appropriate quantity
     164           0 :       if( ind==3 ) {
     165           0 :         readInputLine( getShortcutLabel() + ": CUSTOM ARG=" + getShortcutLabel() + "_diag.vals-1," + getShortcutLabel() + "_diag.vals-2 FUNC=sqrt(x+y) PERIODIC=NO");
     166           0 :       } else if( ind==2 ) {
     167           0 :         readInputLine( getShortcutLabel() + ": CUSTOM ARG=" + getShortcutLabel() + "_diag.vals-1," + getShortcutLabel() + "_diag.vals-3 FUNC=sqrt(x+y) PERIODIC=NO");
     168           0 :       } else if( ind==1 ) {
     169           0 :         readInputLine( getShortcutLabel() + ": CUSTOM ARG=" + getShortcutLabel() + "_diag.vals-2," + getShortcutLabel() + "_diag.vals-3 FUNC=sqrt(x+y) PERIODIC=NO");
     170           0 :       } else error( gtype + " is not a valid type for gyration radius");
     171           0 :     } else if( gtype=="ASPHERICITY" ) {
     172           0 :       readInputLine( getShortcutLabel() + ": CUSTOM ARG=" + getShortcutLabel() + "_diag.vals-1," + getShortcutLabel() + "_diag.vals-2," + getShortcutLabel() + "_diag.vals-3 FUNC=sqrt(x-0.5*(y+z)) PERIODIC=NO" );
     173           0 :     } else if( gtype=="ACYLINDRICITY" ) {
     174           0 :       readInputLine( getShortcutLabel() + ": CUSTOM ARG=" + getShortcutLabel() + "_diag.vals-2," + getShortcutLabel() + "_diag.vals-3 FUNC=sqrt(x-y) PERIODIC=NO" );
     175           0 :     } else if( gtype=="KAPPA2" ) {
     176           0 :       readInputLine( getShortcutLabel() + "_numer: CUSTOM ARG=" + getShortcutLabel() + "_diag.vals-1," + getShortcutLabel() + "_diag.vals-2," + getShortcutLabel() + "_diag.vals-3 FUNC=x*y+x*z+y*z PERIODIC=NO" );
     177           0 :       readInputLine( getShortcutLabel() + "_denom: CUSTOM ARG=" + getShortcutLabel() + "_diag.vals-1," + getShortcutLabel() + "_diag.vals-2," + getShortcutLabel() + "_diag.vals-3 FUNC=x+y+z PERIODIC=NO" );
     178           0 :       readInputLine( getShortcutLabel() + ": CUSTOM ARG=" + getShortcutLabel() + "_numer," + getShortcutLabel() + "_denom FUNC=1-3*(x/(y*y)) PERIODIC=NO");
     179           0 :     } else error( gtype + " is not a valid type for gyration radius");
     180             :   }
     181         124 : }
     182             : 
     183             : }
     184             : }

Generated by: LCOV version 1.16