LCOV - code coverage report
Current view: top level - sasa - sasa_HASEL.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 487 599 81.3 %
Date: 2026-03-30 13:16:06 Functions: 14 16 87.5 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             : Copyright (c) 2021, Andrea Arsiccio
       3             : 
       4             : This software is provided 'as-is', without any express or implied
       5             : warranty. In no event will the authors be held liable for any damages
       6             : arising from the use of this software.
       7             : 
       8             : Permission is granted to anyone to use this software for any purpose,
       9             : including commercial applications, and to alter it and redistribute it
      10             : freely, subject to the following restrictions:
      11             : 
      12             : 1. The origin of this software must not be misrepresented; you must not
      13             :    claim that you wrote the original software. If you use this software
      14             :    in a product, an acknowledgment in the product documentation would be
      15             :    appreciated but is not required.
      16             : 2. Altered source versions must be plainly marked as such, and must not be
      17             :    misrepresented as being the original software.
      18             : 3. This notice may not be removed or altered from any source distribution.
      19             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      20             : 
      21             : #include "Sasa.h"
      22             : #include "ActionRegister.h"
      23             : #include "core/PlumedMain.h"
      24             : #include "core/GenericMolInfo.h"
      25             : #include "core/ActionSet.h"
      26             : #include <cstdio>
      27             : #include <iostream>
      28             : #include <string>
      29             : #include <cmath>
      30             : #include <sstream>
      31             : #include <algorithm>
      32             : #include <iterator>
      33             : #include <fstream>
      34             : 
      35             : 
      36             : using namespace std;
      37             : 
      38             : namespace PLMD {
      39             : namespace sasa {
      40             : 
      41             : //+PLUMEDOC SASAMOD_COLVAR SASA_HASEL
      42             : /*
      43             : Calculates the solvent accessible surface area (SASA) of a protein molecule, or other properties related to it.
      44             : 
      45             : The atoms for which the SASA is desired should be indicated with the keyword ATOMS, and a pdb file of the protein must be provided in input with the MOLINFO keyword. The algorithm described in \cite Hasel1988 is used for the calculation. The radius of the solvent is assumed to be 0.14 nm, which is the radius of water molecules. Using the keyword NL_STRIDE it is also possible to specify the frequency with which the neighbor list for the calculation of SASA is updated (the default is every 10 steps).
      46             : 
      47             : Different properties can be calculated and selected using the TYPE keyword:
      48             : 
      49             : 1) the total SASA (TOTAL);
      50             : 
      51             : 2) the free energy of transfer for the protein according to the transfer model (TRANSFER). This keyword can be used, for instance, to compute the transfer of a protein to different temperatures, as detailed in \cite Arsiccio-T-SASA-2021, or to different pressures, as detailed in \cite Arsiccio-P-SASA-2021, or to different osmolyte solutions, as detailed in \cite Arsiccio-C-SASA-2022.
      52             : 
      53             : 
      54             : When the TRANSFER keyword is used, a file with the free energy of transfer values for the sidechains and backbone atoms should be provided (using the keyword DELTAGFILE). Such file should have the following format:
      55             : 
      56             : \verbatim
      57             : 
      58             : ----------------Sample DeltaG.dat file---------------------
      59             : ALA     0.711019999999962
      60             : ARG     -2.24832799999996
      61             : ASN     -2.74838799999999
      62             : ASP     -2.5626376
      63             : CYS     3.89864000000006
      64             : GLN     -1.76192
      65             : GLU     -2.38664400000002
      66             : GLY     0
      67             : HIS     -3.58152799999999
      68             : ILE     2.42634399999986
      69             : LEU     1.77233599999988
      70             : LYS     -1.92576400000002
      71             : MET     -0.262827999999956
      72             : PHE     1.62028800000007
      73             : PRO     -2.15598800000001
      74             : SER     -1.60934800000004
      75             : THR     -0.591559999999987
      76             : TRP     1.22936000000027
      77             : TYR     0.775547999999958
      78             : VAL     2.12779200000011
      79             : BACKBONE        1.00066920000002
      80             : -----------------------------------------------------------
      81             : \endverbatim
      82             : 
      83             : where the second column is the free energy of transfer for each sidechain/backbone, in kJ/mol.
      84             : 
      85             : A Python script for the computation of free energy of transfer values to describe the effect of osmolyte concentration, temperature and pressure (according to \cite Arsiccio-C-SASA-2022, \cite Arsiccio-T-SASA-2021 and \cite Arsiccio-P-SASA-2021) is freely available at https://github.com/andrea-arsiccio/DeltaG-calculation. The script automatically outputs a DeltaG.dat file compatible with this SASA module.
      86             : 
      87             : 
      88             : If the DELTAGFILE is not provided, the program computes the free energy of transfer values as if they had to take into account the effect of temperature according to approaches 2 or 3 in the paper \cite Arsiccio-T-SASA-2021. Please read and cite this paper if using the transfer model for computing the effect of temperature in implicit solvent simulations. For this purpose, the keyword APPROACH should be added, and set to either 2 or 3.
      89             : 
      90             : The SASA usually makes sense when atoms used for the calculation are all part of the same molecule. When running with periodic boundary conditions, the atoms should be in the proper periodic image. This is done automatically since PLUMED 2.2, by considering the ordered list of atoms and rebuilding the broken entities using a procedure that is equivalent to that done in \ref WHOLEMOLECULES. Notice that rebuilding is local to this action. This is different from \ref WHOLEMOLECULES which actually modifies the coordinates stored in PLUMED.
      91             : 
      92             : In case you want to recover the old behavior you should use the NOPBC flag.
      93             : In that case you need to take care that atoms are in the correct periodic image.
      94             : 
      95             : The SASA may also be computed using the SASA_LCPO collective variable, which makes use of the LCPO algorithm \cite Weiser1999. SASA_LCPO is more accurate then SASA_HASEL, but the computation is slower.
      96             : 
      97             : 
      98             : \par Examples
      99             : 
     100             : The following input tells plumed to print the total SASA for atoms 10 to 20 in a protein chain.
     101             : \plumedfile
     102             : SASA_HASEL TYPE=TOTAL ATOMS=10-20 NL_STRIDE=10 LABEL=sasa
     103             : PRINT ARG=sasa STRIDE=1 FILE=colvar
     104             : \endplumedfile
     105             : 
     106             : 
     107             : The following input tells plumed to compute the transfer free energy for the protein chain containing atoms 10 to 20. Such transfer free energy is then used as a bias in the simulation (e.g., implicit solvent simulations). The free energy of transfer values are read from a file called DeltaG.dat.
     108             : 
     109             : \plumedfile
     110             : SASA_HASEL TYPE=TRANSFER ATOMS=10-20 NL_STRIDE=10 DELTAGFILE=DeltaG.dat LABEL=sasa
     111             : 
     112             : bias: BIASVALUE ARG=sasa
     113             : 
     114             : PRINT ARG=sasa,bias.* STRIDE=1 FILE=colvar
     115             : \endplumedfile
     116             : 
     117             : The following input tells plumed to compute the transfer free energy for the protein chain containing atoms 10 to 20. Such transfer free energy is then used as a bias in the simulation (e.g., implicit solvent simulations). The free energy of transfer values are computed according to \cite Arsiccio-T-SASA-2021, and take into account the effect of temperature using approach 2 as described in the paper.
     118             : 
     119             : \plumedfile
     120             : SASA_HASEL TYPE=TRANSFER ATOMS=10-20 NL_STRIDE=10 APPROACH=2 LABEL=sasa
     121             : 
     122             : bias: BIASVALUE ARG=sasa
     123             : 
     124             : PRINT ARG=sasa,bias.* STRIDE=1 FILE=colvar
     125             : \endplumedfile
     126             : 
     127             : */
     128             : //+ENDPLUMEDOC
     129             : 
     130             : class SASA_HASEL : public Colvar {
     131             : private:
     132             :   enum CV_TYPE {TOTAL, TRANSFER};
     133             :   int sasa_type;
     134             :   bool nopbc;
     135             :   double rs;
     136             :   string DeltaGValues;
     137             :   int approach;
     138             :   unsigned stride;
     139             :   unsigned nl_update;
     140             :   int firstStepFlag;
     141             :   double Ti;
     142             :   // cppcheck-suppress duplInheritedMember
     143             :   std::vector<AtomNumber> atoms;
     144             :   vector < vector < std::string > > AtomResidueName;
     145             :   vector < vector < double > > SASAparam;
     146             :   vector < vector < std::string > > CONNECTparam;
     147             :   unsigned natoms;
     148             :   vector < vector < double > > MaxSurf;
     149             :   vector < vector < double > > DeltaG;
     150             :   vector < vector < int > > Nlist;
     151             : public:
     152             :   static void registerKeywords(Keywords& keys);
     153             :   explicit SASA_HASEL(const ActionOptions&);
     154             :   void readPDB();
     155             :   map<string, vector<std::string> > setupHASELparam();
     156             :   void readSASAparam();
     157             :   void calcNlist();
     158             :   map<string, vector<double> > setupMaxSurfMap();
     159             :   void readMaxSurf();
     160             :   void readDeltaG();
     161             :   void computeDeltaG();
     162             :   virtual void calculate();
     163             : };
     164             : 
     165       13789 : PLUMED_REGISTER_ACTION(SASA_HASEL,"SASA_HASEL")
     166             : 
     167           6 : void SASA_HASEL::registerKeywords(Keywords& keys) {
     168           6 :   Colvar::registerKeywords(keys);
     169          12 :   keys.add("atoms","ATOMS","the group of atoms that you are calculating the SASA for");
     170          12 :   keys.add("compulsory","TYPE","TOTAL","The type of calculation you want to perform. Can be TOTAL or TRANSFER");
     171          12 :   keys.add("compulsory", "NL_STRIDE", "The frequency with which the neighbor list for the calculation of SASA is updated.");
     172          12 :   keys.add("optional","DELTAGFILE","a file containing the free energy of transfer values for backbone and sidechains atoms. Necessary only if TYPE = TRANSFER. A Python script for the computation of free energy of transfer values to describe the effect of osmolyte concentration, temperature and pressure is freely available at https://github.com/andrea-arsiccio/DeltaG-calculation. The script automatically outputs a DeltaG.dat file compatible with this SASA module. If TYPE = TRANSFER and no DELTAGFILE is provided, the free energy values are those describing the effect of temperature, and are computed using the temperature value passed by the MD engine");
     173          12 :   keys.add("optional","APPROACH","either approach 2 or 3. Necessary only if TYPE = TRANSFER and no DELTAGFILE is provided. If TYPE = TRANSFER and no DELTAGFILE is provided, the free energy values are those describing the effect of temperature, and the program must know if approach 2 or 3 (as described in Arsiccio and Shea, Protein Cold Denaturation in Implicit Solvent Simulations: A Transfer Free Energy Approach, J. Phys. Chem. B, 2021) needs to be used to compute them");
     174           6 : }
     175             : 
     176             : 
     177           2 : SASA_HASEL::SASA_HASEL(const ActionOptions&ao):
     178             :   PLUMED_COLVAR_INIT(ao),
     179           2 :   nopbc(false),
     180           2 :   stride(10),
     181           2 :   nl_update(0),
     182           4 :   DeltaGValues("absent"),
     183           2 :   Ti(0),
     184           2 :   firstStepFlag(0) {
     185           2 :   rs = 0.14;
     186           2 :   parse("DELTAGFILE",DeltaGValues);
     187           2 :   parse("APPROACH", approach);
     188           4 :   parseAtomList("ATOMS",atoms);
     189           2 :   if(atoms.size()==0) {
     190           0 :     error("no atoms specified");
     191             :   }
     192             :   std::string Type;
     193           2 :   parse("TYPE",Type);
     194           2 :   parse("NL_STRIDE", stride);
     195           2 :   parseFlag("NOPBC",nopbc);
     196           2 :   checkRead();
     197             : 
     198           2 :   if(Type=="TOTAL") {
     199           1 :     sasa_type=TOTAL;
     200           1 :   } else if(Type=="TRANSFER") {
     201           1 :     sasa_type=TRANSFER;
     202             :   } else {
     203           0 :     error("Unknown SASA type");
     204             :   }
     205             : 
     206           2 :   switch(sasa_type) {
     207           1 :   case TOTAL:
     208           1 :     log.printf("  TOTAL SASA;");
     209             :     break;
     210           1 :   case TRANSFER:
     211           1 :     log.printf("  TRANSFER MODEL;");
     212             :     break;
     213             :   }
     214             : 
     215           2 :   log.printf("  atoms involved : ");
     216         242 :   for(unsigned i=0; i<atoms.size(); ++i) {
     217         240 :     if(i%25==0) {
     218          10 :       log<<"\n";
     219             :     }
     220         240 :     log.printf("%d ",atoms[i].serial());
     221             :   }
     222           2 :   log.printf("\n");
     223             : 
     224           2 :   if(nopbc) {
     225           0 :     log<<"  PBC will be ignored\n";
     226             :   } else {
     227           2 :     log<<"  broken molecules will be rebuilt assuming atoms are in the proper order\n";
     228             :   }
     229             : 
     230             : 
     231           2 :   addValueWithDerivatives();
     232           2 :   setNotPeriodic();
     233           2 :   requestAtoms(atoms);
     234             : 
     235           2 :   natoms = getNumberOfAtoms();
     236           2 :   AtomResidueName.resize(2);
     237           2 :   SASAparam.resize(natoms);
     238           2 :   CONNECTparam.resize(natoms);
     239           2 :   MaxSurf.resize(natoms);
     240           2 :   DeltaG.resize(natoms+1);
     241           2 :   Nlist.resize(natoms);
     242             : 
     243             : 
     244           2 : }
     245             : 
     246             : 
     247             : //splits strings into tokens. Used to read into SASA parameters file and into reference pdb file
     248             : template <class Container>
     249          42 : void split(const std::string& str, Container& cont) {
     250          42 :   std::istringstream iss(str);
     251          84 :   std::copy(std::istream_iterator<std::string>(iss),
     252          42 :             std::istream_iterator<std::string>(),
     253             :             std::back_inserter(cont));
     254          42 : }
     255             : 
     256             : 
     257             : //reads input PDB file provided with MOLINFO, and assigns atom and residue names to each atom involved in the CV
     258             : 
     259           2 : void SASA_HASEL::readPDB() {
     260           2 :   auto* moldat = plumed.getActionSet().selectLatest<GenericMolInfo*>(this);
     261           2 :   if( ! moldat ) {
     262           0 :     error("Unable to find MOLINFO in input");
     263             :   }
     264             :   AtomResidueName[0].clear();
     265             :   AtomResidueName[1].clear();
     266             : 
     267         242 :   for(unsigned i=0; i<natoms; i++) {
     268         240 :     string Aname = moldat->getAtomName(atoms[i]);
     269         240 :     string Rname = moldat->getResidueName(atoms[i]);
     270         240 :     AtomResidueName[0].push_back (Aname);
     271         240 :     AtomResidueName[1].push_back (Rname);
     272             :   }
     273             : 
     274           2 : }
     275             : 
     276             : 
     277             : //Hasel et al. parameters database
     278           2 : map<string, vector<std::string> > SASA_HASEL::setupHASELparam() {
     279             :   map<string, vector<std::string> > haselmap;
     280          16 :   haselmap["ALA_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     281          16 :   haselmap["ALA_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     282          16 :   haselmap["ALA_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     283          16 :   haselmap["ALA_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     284          16 :   haselmap["ALA_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     285          16 :   haselmap["ALA_CB"] = { "2.0",  "0.88",  "CA",  "Z",  "Z",  "Z", };
     286          16 :   haselmap["ASP_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     287          16 :   haselmap["ASP_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     288          16 :   haselmap["ASP_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     289          16 :   haselmap["ASP_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     290          16 :   haselmap["ASP_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     291          16 :   haselmap["ASP_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     292          16 :   haselmap["ASP_CG"] = { "1.72",  "1.554",  "CB",  "OD1",  "OD2",  "Z", };
     293          16 :   haselmap["ASP_OD1"] = { "1.5",  "0.926",  "CG",  "Z",  "Z",  "Z", };
     294          16 :   haselmap["ASP_OD2"] = { "1.7",  "0.922",  "CG",  "Z",  "Z",  "Z", };
     295          16 :   haselmap["ASN_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     296          16 :   haselmap["ASN_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     297          16 :   haselmap["ASN_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     298          16 :   haselmap["ASN_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     299          16 :   haselmap["ASN_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     300          16 :   haselmap["ASN_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     301          16 :   haselmap["ASN_CG"] = { "1.7",  "2.149",  "CB",  "OD1",  "ND2",  "Z", };
     302          16 :   haselmap["ASN_OD1"] = { "1.5",  "0.926",  "CG",  "Z",  "Z",  "Z", };
     303          16 :   haselmap["ASN_ND2"] = { "1.6",  "1.215",  "CG",  "1HD2",  "1HD2",  "Z", };
     304          16 :   haselmap["ASN_1HD2"] = { "1.1",  "1.128",  "ND2",  "Z",  "Z",  "Z", };
     305          16 :   haselmap["ASN_2HD2"] = { "1.1",  "1.128",  "ND2",  "Z",  "Z",  "Z", };
     306          16 :   haselmap["ARG_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     307          16 :   haselmap["ARG_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     308          16 :   haselmap["ARG_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     309          16 :   haselmap["ARG_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     310          16 :   haselmap["ARG_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     311          16 :   haselmap["ARG_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     312          16 :   haselmap["ARG_CG"] = { "1.9",  "1.045",  "CB",  "CD",  "Z",  "Z", };
     313          16 :   haselmap["ARG_CD"] = { "1.9",  "1.045",  "CG",  "NE",  "Z",  "Z", };
     314          16 :   haselmap["ARG_NE"] = { "1.55",  "1.028",  "CD",  "HE",  "CZ",  "Z", };
     315          16 :   haselmap["ARG_NH1"] = { "1.55",  "1.028",  "CZ",  "1HH1",  "2HH1",  "Z", };
     316          16 :   haselmap["ARG_NH2"] = { "1.55",  "1.028",  "CZ",  "1HH2",  "2HH2",  "Z", };
     317          16 :   haselmap["ARG_CZ"] = { "1.72",  "1.554",  "NE",  "NH1",  "NH2",  "Z", };
     318          16 :   haselmap["ARG_HE"] = { "1.1",  "1.128",  "NE",  "Z",  "Z",  "Z", };
     319          16 :   haselmap["ARG_1HH2"] = { "1.1",  "1.128",  "NH2",  "Z",  "Z",  "Z", };
     320          16 :   haselmap["ARG_2HH2"] = { "1.1",  "1.128",  "NH2",  "Z",  "Z",  "Z", };
     321          16 :   haselmap["ARG_2HH1"] = { "1.1",  "1.128",  "NH1",  "Z",  "Z",  "Z", };
     322          16 :   haselmap["ARG_1HH1"] = { "1.1",  "1.128",  "NH1",  "Z",  "Z",  "Z", };
     323          16 :   haselmap["CYS_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     324          16 :   haselmap["CYS_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     325          16 :   haselmap["CYS_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     326          16 :   haselmap["CYS_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     327          16 :   haselmap["CYS_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     328          16 :   haselmap["CYS_CB"] = { "1.9",  "1.045",  "CA",  "SG",  "Z",  "Z", };
     329          16 :   haselmap["CYS_SG"] = { "1.8",  "1.121",  "CB",  "HG",  "Z",  "Z", };
     330          16 :   haselmap["CYS_HG"] = { "1.2",  "0.928",  "SG",  "Z",  "Z",  "Z", };
     331          16 :   haselmap["GLU_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     332          16 :   haselmap["GLU_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     333          16 :   haselmap["GLU_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     334          16 :   haselmap["GLU_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     335          16 :   haselmap["GLU_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     336          16 :   haselmap["GLU_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     337          16 :   haselmap["GLU_CG"] = { "1.9",  "1.045",  "CB",  "CD",  "Z",  "Z", };
     338          16 :   haselmap["GLU_CD"] = { "1.72",  "1.554",  "CG",  "OE1",  "OE2",  "Z", };
     339          16 :   haselmap["GLU_OE1"] = { "1.5",  "0.926",  "CD",  "Z",  "Z",  "Z", };
     340          16 :   haselmap["GLU_OE2"] = { "1.7",  "0.922",  "CD",  "Z",  "Z",  "Z", };
     341          16 :   haselmap["GLN_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     342          16 :   haselmap["GLN_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     343          16 :   haselmap["GLN_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     344          16 :   haselmap["GLN_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     345          16 :   haselmap["GLN_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     346          16 :   haselmap["GLN_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     347          16 :   haselmap["GLN_CG"] = { "1.9",  "1.045",  "CB",  "CD",  "Z",  "Z", };
     348          16 :   haselmap["GLN_CD"] = { "1.72",  "1.554",  "CG",  "OE1",  "NE2",  "Z", };
     349          16 :   haselmap["GLN_OE1"] = { "1.5",  "0.926",  "CD",  "Z",  "Z",  "Z", };
     350          16 :   haselmap["GLN_NE2"] = { "1.6",  "1.215",  "CD",  "2HE2",  "1HE2",  "Z", };
     351          16 :   haselmap["GLN_2HE2"] = { "1.1",  "1.128",  "NE2",  "Z",  "Z",  "Z", };
     352          16 :   haselmap["GLN_1HE2"] = { "1.1",  "1.128",  "NE2",  "Z",  "Z",  "Z", };
     353          16 :   haselmap["GLY_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     354          16 :   haselmap["GLY_CA"] = { "1.7",  "2.149",  "N",  "C",  "Z",  "Z", };
     355          16 :   haselmap["GLY_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     356          16 :   haselmap["GLY_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     357          16 :   haselmap["GLY_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     358          16 :   haselmap["HIS_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     359          16 :   haselmap["HIS_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     360          16 :   haselmap["HIS_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     361          16 :   haselmap["HIS_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     362          16 :   haselmap["HIS_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     363          16 :   haselmap["HIS_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     364          16 :   haselmap["HIS_CG"] = { "1.72",  "1.554",  "CB",  "CD2",  "ND1",  "Z", };
     365          16 :   haselmap["HIS_ND1"] = { "1.55",  "1.028",  "CG",  "CE1",  "Z",  "Z", };
     366          16 :   haselmap["HIS_CE1"] = { "1.8",  "1.073",  "ND1",  "NE2",  "Z",  "Z", };
     367          16 :   haselmap["HIS_NE2"] = { "1.55",  "1.413",  "CE1",  "2HE",  "CD2",  "Z", };
     368          16 :   haselmap["HIS_CD2"] = { "1.8",  "1.073",  "NE2",  "CG",  "Z",  "Z", };
     369          16 :   haselmap["HIS_2HE"] = { "1.1",  "1.128",  "NE2",  "Z",  "Z",  "Z", };
     370          16 :   haselmap["ILE_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     371          16 :   haselmap["ILE_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     372          16 :   haselmap["ILE_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     373          16 :   haselmap["ILE_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     374          16 :   haselmap["ILE_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     375          16 :   haselmap["ILE_CB"] = { "1.8",  "1.276",  "CA",  "CG2",  "CG1",  "Z", };
     376          16 :   haselmap["ILE_CG2"] = { "2.0",  "0.88",  "CB",  "Z",  "Z",  "Z", };
     377          16 :   haselmap["ILE_CG1"] = { "1.9",  "1.045",  "CB",  "CD1",  "Z",  "Z", };
     378          16 :   haselmap["ILE_CD1"] = { "2.0",  "0.88",  "CG1",  "Z",  "Z",  "Z", };
     379          16 :   haselmap["LEU_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     380          16 :   haselmap["LEU_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     381          16 :   haselmap["LEU_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     382          16 :   haselmap["LEU_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     383          16 :   haselmap["LEU_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     384          16 :   haselmap["LEU_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     385          16 :   haselmap["LEU_CG"] = { "1.8",  "1.276",  "CB",  "CD1",  "CD2",  "Z", };
     386          16 :   haselmap["LEU_CD1"] = { "2.0",  "0.88",  "CG",  "Z",  "Z",  "Z", };
     387          16 :   haselmap["LEU_CD2"] = { "2.0",  "0.88",  "CG",  "Z",  "Z",  "Z", };
     388          16 :   haselmap["LYS_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     389          16 :   haselmap["LYS_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     390          16 :   haselmap["LYS_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     391          16 :   haselmap["LYS_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     392          16 :   haselmap["LYS_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     393          16 :   haselmap["LYS_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     394          16 :   haselmap["LYS_CG"] = { "1.9",  "1.045",  "CB",  "CD",  "Z",  "Z", };
     395          16 :   haselmap["LYS_CD"] = { "1.9",  "1.045",  "CG",  "CE",  "Z",  "Z", };
     396          16 :   haselmap["LYS_CE"] = { "1.9",  "1.045",  "CD",  "NZ",  "Z",  "Z", };
     397          16 :   haselmap["LYS_NZ"] = { "1.6",  "1.215",  "CE",  "1HZ",  "2HZ",  "3HZ", };
     398          16 :   haselmap["LYS_1HZ"] = { "1.1",  "1.128",  "NZ",  "Z",  "Z",  "Z", };
     399          16 :   haselmap["LYS_2HZ"] = { "1.1",  "1.128",  "NZ",  "Z",  "Z",  "Z", };
     400          16 :   haselmap["LYS_3HZ"] = { "1.1",  "1.128",  "NZ",  "Z",  "Z",  "Z", };
     401          16 :   haselmap["MET_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     402          16 :   haselmap["MET_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     403          16 :   haselmap["MET_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     404          16 :   haselmap["MET_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     405          16 :   haselmap["MET_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     406          16 :   haselmap["MET_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     407          16 :   haselmap["MET_CG"] = { "1.9",  "1.045",  "CB",  "SD",  "Z",  "Z", };
     408          16 :   haselmap["MET_SD"] = { "1.8",  "1.121",  "CG",  "CE",  "Z",  "Z", };
     409          16 :   haselmap["MET_CE"] = { "2.0",  "0.88",  "SD",  "Z",  "Z",  "Z", };
     410          16 :   haselmap["PHE_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     411          16 :   haselmap["PHE_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     412          16 :   haselmap["PHE_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     413          16 :   haselmap["PHE_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     414          16 :   haselmap["PHE_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     415          16 :   haselmap["PHE_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     416          16 :   haselmap["PHE_CG"] = { "1.72",  "1.554",  "CB",  "CD1",  "CD2",  "Z", };
     417          16 :   haselmap["PHE_CD1"] = { "1.8",  "1.073",  "CG",  "CE1",  "Z",  "Z", };
     418          16 :   haselmap["PHE_CE1"] = { "1.8",  "1.073",  "CD1",  "CZ",  "Z",  "Z", };
     419          16 :   haselmap["PHE_CZ"] = { "1.8",  "1.073",  "CE1",  "CE2",  "Z",  "Z", };
     420          16 :   haselmap["PHE_CE2"] = { "1.8",  "1.073",  "CZ",  "CD2",  "Z",  "Z", };
     421          16 :   haselmap["PHE_CD2"] = { "1.8",  "1.073",  "CE2",  "CG",  "Z",  "Z", };
     422          16 :   haselmap["PRO_N"] = { "1.55",  "1.028",  "CD",  "CA",  "Z",  "Z", };
     423          16 :   haselmap["PRO_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     424          16 :   haselmap["PRO_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     425          16 :   haselmap["PRO_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     426          16 :   haselmap["PRO_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     427          16 :   haselmap["PRO_CG"] = { "1.9",  "1.045",  "CB",  "CD",  "Z",  "Z", };
     428          16 :   haselmap["PRO_CD"] = { "1.9",  "1.045",  "CG",  "N",  "Z",  "Z", };
     429          16 :   haselmap["SER_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     430          16 :   haselmap["SER_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     431          16 :   haselmap["SER_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     432          16 :   haselmap["SER_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     433          16 :   haselmap["SER_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     434          16 :   haselmap["SER_CB"] = { "1.9",  "1.045",  "CA",  "OG",  "Z",  "Z", };
     435          16 :   haselmap["SER_OG"] = { "1.52",  "1.08",  "CB",  "HG",  "Z",  "Z", };
     436          16 :   haselmap["SER_HG"] = { "1.0",  "0.944",  "OG",  "Z",  "Z",  "Z", };
     437          16 :   haselmap["THR_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     438          16 :   haselmap["THR_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     439          16 :   haselmap["THR_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     440          16 :   haselmap["THR_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     441          16 :   haselmap["THR_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     442          16 :   haselmap["THR_CB"] = { "1.8",  "1.276",  "CA",  "CG2",  "OG1",  "Z", };
     443          16 :   haselmap["THR_CG2"] = { "2.0",  "0.88",  "CB",  "Z",  "Z",  "Z", };
     444          16 :   haselmap["THR_OG1"] = { "1.52",  "1.08",  "1HG",  "CB",  "Z",  "Z", };
     445          16 :   haselmap["THR_1HG"] = { "1.0",  "0.944",  "OG1",  "Z",  "Z",  "Z", };
     446          16 :   haselmap["TRP_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     447          16 :   haselmap["TRP_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     448          16 :   haselmap["TRP_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     449          16 :   haselmap["TRP_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     450          16 :   haselmap["TRP_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     451          16 :   haselmap["TRP_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     452          16 :   haselmap["TRP_CG"] = { "1.72",  "1.554",  "CB",  "CD2",  "CD1",  "Z", };
     453          16 :   haselmap["TRP_CD1"] = { "1.8",  "1.073",  "CG",  "NE1",  "Z",  "Z", };
     454          16 :   haselmap["TRP_NE1"] = { "1.55",  "1.413",  "CD1",  "CE2",  "1HE",  "Z", };
     455          16 :   haselmap["TRP_CE2"] = { "1.72",  "1.554",  "NE1",  "CD2",  "CZ2",  "Z", };
     456          16 :   haselmap["TRP_CZ2"] = { "1.8",  "1.073",  "CE2",  "CH2",  "Z",  "Z", };
     457          16 :   haselmap["TRP_CH2"] = { "1.8",  "1.073",  "CZ2",  "CZ3",  "Z",  "Z", };
     458          16 :   haselmap["TRP_CZ3"] = { "1.8",  "1.073",  "CH2",  "CE3",  "Z",  "Z", };
     459          16 :   haselmap["TRP_CE3"] = { "1.8",  "1.073",  "CZ3",  "CD2",  "Z",  "Z", };
     460          16 :   haselmap["TRP_CD2"] = { "1.72",  "1.554",  "CE3",  "CE2",  "CG",  "Z", };
     461          16 :   haselmap["TRP_1HE"] = { "1.1",  "1.128",  "NE1",  "Z",  "Z",  "Z", };
     462          16 :   haselmap["TYR_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     463          16 :   haselmap["TYR_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     464          16 :   haselmap["TYR_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     465          16 :   haselmap["TYR_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     466          16 :   haselmap["TYR_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     467          16 :   haselmap["TYR_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     468          16 :   haselmap["TYR_CG"] = { "1.72",  "1.554",  "CB",  "CD1",  "CD2",  "Z", };
     469          16 :   haselmap["TYR_CD1"] = { "1.8",  "1.073",  "CG",  "CE1",  "Z",  "Z", };
     470          16 :   haselmap["TYR_CE1"] = { "1.8",  "1.073",  "CD1",  "CZ",  "Z",  "Z", };
     471          16 :   haselmap["TYR_CZ"] = { "1.72",  "1.554",  "CE1",  "OH",  "CE2",  "Z", };
     472          16 :   haselmap["TYR_OH"] = { "1.52",  "1.08",  "CZ",  "HH",  "Z",  "Z", };
     473          16 :   haselmap["TYR_HH"] = { "1.0",  "0.944",  "OH",  "Z",  "Z",  "Z", };
     474          16 :   haselmap["TYR_CE2"] = { "1.8",  "1.073",  "CZ",  "CD2",  "Z",  "Z", };
     475          16 :   haselmap["TYR_CD2"] = { "1.8",  "1.073",  "CE2",  "CG",  "Z",  "Z", };
     476          16 :   haselmap["VAL_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     477          16 :   haselmap["VAL_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     478          16 :   haselmap["VAL_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     479          16 :   haselmap["VAL_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     480          16 :   haselmap["VAL_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     481          16 :   haselmap["VAL_CB"] = { "1.8",  "1.276",  "CA",  "CG1",  "CG2",  "Z", };
     482          16 :   haselmap["VAL_CG1"] = { "2.0",  "0.88",  "CB",  "Z",  "Z",  "Z", };
     483          16 :   haselmap["VAL_CG2"] = { "2.0",  "0.88",  "CB",  "Z",  "Z",  "Z", };
     484           2 :   return haselmap;
     485             : }
     486             : 
     487             : //assigns SASA parameters to each atom reading from HASEL parameter database
     488           2 : void SASA_HASEL::readSASAparam() {
     489             : 
     490         242 :   for(unsigned i=0; i<natoms; i++) {
     491         240 :     SASAparam[i].clear();
     492             :     CONNECTparam[i].clear();
     493             :   }
     494             : 
     495             :   map<string, vector<std::string> > haselmap;
     496           4 :   haselmap = setupHASELparam();
     497             :   vector<std::string> HASELparamVector;
     498             :   string identifier;
     499             : 
     500             : 
     501         242 :   for(unsigned i=0; i<natoms; i++) {
     502         480 :     identifier = AtomResidueName[1][i]+"_"+AtomResidueName[0][i];
     503         240 :     if (haselmap.find(identifier)!=haselmap.end()) {
     504         144 :       HASELparamVector = haselmap.at(identifier);
     505         144 :       SASAparam[i].push_back (std::atof(HASELparamVector[0].c_str())+rs*10);
     506         144 :       SASAparam[i].push_back (std::atof(HASELparamVector[1].c_str()));
     507         288 :       CONNECTparam[i].push_back (HASELparamVector[2].c_str());
     508         288 :       CONNECTparam[i].push_back (HASELparamVector[3].c_str());
     509         288 :       CONNECTparam[i].push_back (HASELparamVector[4].c_str());
     510         288 :       CONNECTparam[i].push_back (HASELparamVector[5].c_str());
     511             :     }
     512             :   }
     513             : 
     514             : 
     515         242 :   for(unsigned i=0; i<natoms; i++) {
     516         240 :     if (SASAparam[i].size()==0 ) {
     517          96 :       if ((AtomResidueName[0][i][0]=='O') || (AtomResidueName[0][i][0]=='N') || (AtomResidueName[0][i][0]=='C') || (AtomResidueName[0][i][0]=='S')) {
     518           0 :         cout << "Could not find SASA paramaters for atom " << AtomResidueName[0][i] << " of residue " << AtomResidueName[1][i] << endl;
     519           0 :         error ("missing SASA parameters\n");
     520             :       }
     521             :     }
     522             :   }
     523             : 
     524             : 
     525           4 : }
     526             : 
     527             : 
     528             : 
     529             : //Max Surf values, used only if TYPE=TRANSFER
     530           1 : map<string, vector<double> > SASA_HASEL::setupMaxSurfMap() {
     531             :   // Max Surface Area for backbone and sidechain, in nm2
     532             :   map<string, vector<double> > valuemap;
     533           1 :   valuemap ["ALA"]= {0.56425,0.584851,};
     534           1 :   valuemap ["ARG"]= {0.498656,1.808093,};
     535           1 :   valuemap ["ASN"]= {0.473409,0.818394,};
     536           1 :   valuemap ["ASP"]= {0.477057,0.977303,};
     537           1 :   valuemap ["CYS"]= {0.507512,0.791483,};
     538           1 :   valuemap ["GLN"]= {0.485859,1.281534,};
     539           1 :   valuemap ["GLU"]= {0.495054,1.464718,};
     540           1 :   valuemap ["GLY"]= {0.658632,0,};
     541           1 :   valuemap ["HIS"]= {0.48194,1.118851,};
     542           1 :   valuemap ["ILE"]= {0.461283,1.450569,};
     543           1 :   valuemap ["LEU"]= {0.476315,1.498843,};
     544           1 :   valuemap ["LYS"]= {0.493533,1.619731,};
     545           1 :   valuemap ["MET"]= {0.507019,1.631904,};
     546           1 :   valuemap ["PHE"]= {0.457462, 1.275125,};
     547           1 :   valuemap ["PRO"]= {0.315865,0.859456,};
     548           1 :   valuemap ["SER"]= {0.48636,0.627233,};
     549           1 :   valuemap ["THR"]= {0.45064,0.91088,};
     550           1 :   valuemap ["TRP"]= {0.45762,1.366369,};
     551           1 :   valuemap ["TYR"]= {0.461826,1.425822,};
     552           1 :   valuemap ["VAL"]= {0.477054,1.149101,};
     553           1 :   return valuemap;
     554             : }
     555             : 
     556             : 
     557             : 
     558             : //reads maximum surface values per residue type and assigns values to each atom, only used if sasa_type = TRANSFER
     559             : 
     560           1 : void SASA_HASEL::readMaxSurf() {
     561             :   map<string, vector<double> > valuemap;
     562           2 :   valuemap = setupMaxSurfMap();
     563             :   vector<double> MaxSurfVector;
     564             : 
     565         121 :   for(unsigned i=0; i<natoms; i++) {
     566         120 :     MaxSurf[i].clear();
     567         120 :     MaxSurfVector = valuemap.at(AtomResidueName[1][i]);
     568         120 :     MaxSurf[i].push_back (MaxSurfVector[0]*100);
     569         120 :     MaxSurf[i].push_back (MaxSurfVector[1]*100);
     570             :   }
     571           1 : }
     572             : 
     573             : //reads file with free energy values for sidechains and for the backbone, and assigns values to each atom. Only used if sasa_type = TRANSFER
     574             : 
     575           1 : void SASA_HASEL::readDeltaG() {
     576             : 
     577         121 :   for(unsigned i=0; i<natoms; i++) {
     578         120 :     DeltaG[i].clear();
     579             :   }
     580             : 
     581             :   string DeltaGline;
     582           1 :   fstream DeltaGFile;
     583           1 :   DeltaGFile.open(DeltaGValues);
     584           1 :   if (DeltaGFile) {
     585             :     int backboneflag = 0;
     586          23 :     while(getline(DeltaGFile, DeltaGline)) {
     587          22 :       if(!DeltaGline.empty()) {
     588             :         std::vector<std::string> DeltaGtoken;
     589          21 :         split(DeltaGline, DeltaGtoken);
     590        2541 :         for(unsigned i=0; i<natoms; i++) {
     591        2520 :           if (DeltaGtoken[0].compare(AtomResidueName[1][i])==0 ) {
     592         120 :             DeltaG[i].push_back (std::atof(DeltaGtoken[1].c_str()));
     593             :           }
     594             :         }
     595          21 :         if (DeltaGtoken[0].compare("BACKBONE")==0 ) {
     596             :           backboneflag = 1;
     597           1 :           DeltaG[natoms].push_back (std::atof(DeltaGtoken[1].c_str()));
     598             :         }
     599          21 :       }
     600             :     }
     601           1 :     if ( backboneflag == 0) {
     602           0 :       error("Cannot find backbone value in Delta G parameters file\n");
     603             :     }
     604             :   } else {
     605           0 :     error("Cannot open DeltaG file");
     606             :   }
     607             : 
     608         121 :   for(unsigned i=0; i<natoms; i++) {
     609         120 :     if (DeltaG[i].size()==0 ) {
     610           0 :       cout << "Delta G value for residue " << AtomResidueName[1][i] << " not found " << endl;
     611           0 :       error ("missing Delta G parameter\n");
     612             :     }
     613             :   }
     614             : 
     615           2 : }
     616             : 
     617             : //computes free energy values for the sidechains and for the backbone, and assigns values to each atom. Only used if sasa_type = TRANSFER, and if no DELTAGFILE is provided. In this case, the free energy values are those describing the effect of temperature, and the program must know if approach 2 or 3 (as described in Arsiccio and Shea, Protein Cold Denaturation in Implicit Solvent Simulations: A Transfer Free Energy Approach, JPCB, 2021) needs to be used to compute them.
     618             : 
     619           0 : void SASA_HASEL::computeDeltaG() {
     620             : 
     621           0 :   for(unsigned i=0; i<natoms; i++) {
     622           0 :     DeltaG[i].clear();
     623             :   }
     624             : 
     625             :   double T;
     626           0 :   T = plumed.getAtoms().getKbT()/plumed.getAtoms().getKBoltzmann();
     627             : 
     628           0 :   if (T != Ti) {
     629           0 :     for(unsigned i=0; i<natoms; i++) {
     630           0 :       if (approach==2) {
     631           0 :         if (AtomResidueName[1][i].compare("ALA")==0) {
     632           0 :           DeltaG[i].push_back (-2.995/1000*std::pow(T,2)+1.808*T-272.895);
     633             :         }
     634           0 :         if (AtomResidueName[1][i].compare("ARG")==0) {
     635           0 :           DeltaG[i].push_back (-3.182/1000*std::pow(T,2)+1.894*T-282.032);
     636             :         }
     637           0 :         if (AtomResidueName[1][i].compare("ASN")==0) {
     638           0 :           DeltaG[i].push_back (-1.047/1000*std::pow(T,2)+0.6068*T-87.846);
     639             :         }
     640           0 :         if (AtomResidueName[1][i].compare("ASP")==0) {
     641           0 :           DeltaG[i].push_back (-0.1794/1000*std::pow(T,2)+0.1091*T-16.526);
     642             :         }
     643           0 :         if (AtomResidueName[1][i].compare("CYS")==0) {
     644           0 :           DeltaG[i].push_back (-3.09/1000*std::pow(T,2)+1.835*T-272.26);
     645             :         }
     646           0 :         if (AtomResidueName[1][i].compare("GLN")==0) {
     647           0 :           DeltaG[i].push_back (-2.23/1000*std::pow(T,2)+1.335*T-199.707);
     648             :         }
     649           0 :         if (AtomResidueName[1][i].compare("GLU")==0) {
     650           0 :           DeltaG[i].push_back (-1.511/1000*std::pow(T,2)+0.8904*T-131.168);
     651             :         }
     652           0 :         if (AtomResidueName[1][i].compare("GLY")==0) {
     653           0 :           DeltaG[i].push_back (0);
     654             :         }
     655           0 :         if (AtomResidueName[1][i].compare("HIS")==0) {
     656           0 :           DeltaG[i].push_back (-3.482/1000*std::pow(T,2)+2.084*T-311.694);
     657             :         }
     658           0 :         if (AtomResidueName[1][i].compare("ILE")==0) {
     659           0 :           DeltaG[i].push_back (-6.364/1000*std::pow(T,2)+3.8*T-567.444);
     660             :         }
     661           0 :         if (AtomResidueName[1][i].compare("LEU")==0) {
     662           0 :           DeltaG[i].push_back (-7.466/1000*std::pow(T,2)+4.417*T-653.394);
     663             :         }
     664           0 :         if (AtomResidueName[1][i].compare("LYS")==0) {
     665           0 :           DeltaG[i].push_back (-2.091/1000*std::pow(T,2)+1.2458*T-185.549);
     666             :         }
     667           0 :         if (AtomResidueName[1][i].compare("MET")==0) {
     668           0 :           DeltaG[i].push_back (-3.807/1000*std::pow(T,2)+2.272*T-339.007);
     669             :         }
     670           0 :         if (AtomResidueName[1][i].compare("PHE")==0) {
     671           0 :           DeltaG[i].push_back (-7.828/1000*std::pow(T,2)+4.644*T-688.874);
     672             :         }
     673           0 :         if (AtomResidueName[1][i].compare("PRO")==0) {
     674           0 :           DeltaG[i].push_back (-2.347/1000*std::pow(T,2)+1.411*T-212.059);
     675             :         }
     676           0 :         if (AtomResidueName[1][i].compare("SER")==0) {
     677           0 :           DeltaG[i].push_back (1.813/1000*std::pow(T,2)-1.05*T+151.957);
     678             :         }
     679           0 :         if (AtomResidueName[1][i].compare("THR")==0) {
     680           0 :           DeltaG[i].push_back (-2.64/1000*std::pow(T,2)+1.591*T-239.516);
     681             :         }
     682           0 :         if (AtomResidueName[1][i].compare("TRP")==0) {
     683           0 :           DeltaG[i].push_back (-11.66/1000*std::pow(T,2)+6.916*T-1025.293);
     684             :         }
     685           0 :         if (AtomResidueName[1][i].compare("TYR")==0) {
     686           0 :           DeltaG[i].push_back (-7.513/1000*std::pow(T,2)+4.478*T-667.261);
     687             :         }
     688           0 :         if (AtomResidueName[1][i].compare("VAL")==0) {
     689           0 :           DeltaG[i].push_back (-4.902/1000*std::pow(T,2)+2.921*T-435.309);
     690             :         }
     691           0 :         DeltaG[natoms].push_back (-0.6962/1000*std::pow(T,2)+0.4426*T-70.015);
     692             :       }
     693           0 :       if (approach==3) {
     694           0 :         if (AtomResidueName[1][i].compare("ALA")==0) {
     695           0 :           DeltaG[i].push_back (-2.995/1000*std::pow(T,2)+1.808*T-272.105);
     696             :         }
     697           0 :         if (AtomResidueName[1][i].compare("ARG")==0) {
     698           0 :           DeltaG[i].push_back (-3.182/1000*std::pow(T,2)+1.894*T-284.086);
     699             :         }
     700           0 :         if (AtomResidueName[1][i].compare("ASN")==0) {
     701           0 :           DeltaG[i].push_back (-1.047/1000*std::pow(T,2)+0.6068*T-90.597);
     702             :         }
     703           0 :         if (AtomResidueName[1][i].compare("ASP")==0) {
     704           0 :           DeltaG[i].push_back (-0.1794/1000*std::pow(T,2)+0.1091*T-19.143);
     705             :         }
     706           0 :         if (AtomResidueName[1][i].compare("CYS")==0) {
     707           0 :           DeltaG[i].push_back (-3.09/1000*std::pow(T,2)+1.835*T-268.527);
     708             :         }
     709           0 :         if (AtomResidueName[1][i].compare("GLN")==0) {
     710           0 :           DeltaG[i].push_back (-2.23/1000*std::pow(T,2)+1.335*T-201.559);
     711             :         }
     712           0 :         if (AtomResidueName[1][i].compare("GLU")==0) {
     713           0 :           DeltaG[i].push_back (-1.511/1000*std::pow(T,2)+0.8904*T-133.543);
     714             :         }
     715           0 :         if (AtomResidueName[1][i].compare("GLY")==0) {
     716           0 :           DeltaG[i].push_back (0);
     717             :         }
     718           0 :         if (AtomResidueName[1][i].compare("HIS")==0) {
     719           0 :           DeltaG[i].push_back (-3.482/1000*std::pow(T,2)+2.084*T-315.398);
     720             :         }
     721           0 :         if (AtomResidueName[1][i].compare("ILE")==0) {
     722           0 :           DeltaG[i].push_back (-6.364/1000*std::pow(T,2)+3.8*T-564.825);
     723             :         }
     724           0 :         if (AtomResidueName[1][i].compare("LEU")==0) {
     725           0 :           DeltaG[i].push_back (-7.466/1000*std::pow(T,2)+4.417*T-651.483);
     726             :         }
     727           0 :         if (AtomResidueName[1][i].compare("LYS")==0) {
     728           0 :           DeltaG[i].push_back (-2.091/1000*std::pow(T,2)+1.2458*T-187.485);
     729             :         }
     730           0 :         if (AtomResidueName[1][i].compare("MET")==0) {
     731           0 :           DeltaG[i].push_back (-3.807/1000*std::pow(T,2)+2.272*T-339.242);
     732             :         }
     733           0 :         if (AtomResidueName[1][i].compare("PHE")==0) {
     734           0 :           DeltaG[i].push_back (-7.828/1000*std::pow(T,2)+4.644*T-687.134);
     735             :         }
     736           0 :         if (AtomResidueName[1][i].compare("PRO")==0) {
     737           0 :           DeltaG[i].push_back (-2.347/1000*std::pow(T,2)+1.411*T-214.211);
     738             :         }
     739           0 :         if (AtomResidueName[1][i].compare("SER")==0) {
     740           0 :           DeltaG[i].push_back (1.813/1000*std::pow(T,2)-1.05*T+150.289);
     741             :         }
     742           0 :         if (AtomResidueName[1][i].compare("THR")==0) {
     743           0 :           DeltaG[i].push_back (-2.64/1000*std::pow(T,2)+1.591*T-240.267);
     744             :         }
     745           0 :         if (AtomResidueName[1][i].compare("TRP")==0) {
     746           0 :           DeltaG[i].push_back (-11.66/1000*std::pow(T,2)+6.916*T-1024.284);
     747             :         }
     748           0 :         if (AtomResidueName[1][i].compare("TYR")==0) {
     749           0 :           DeltaG[i].push_back (-7.513/1000*std::pow(T,2)+4.478*T-666.484);
     750             :         }
     751           0 :         if (AtomResidueName[1][i].compare("VAL")==0) {
     752           0 :           DeltaG[i].push_back (-4.902/1000*std::pow(T,2)+2.921*T-433.013);
     753             :         }
     754           0 :         DeltaG[natoms].push_back (-0.6927/1000*std::pow(T,2)+0.4404*T-68.724);
     755             :       }
     756             :     }
     757             :   }
     758             : 
     759           0 :   Ti = T;
     760             : 
     761           0 :   if (firstStepFlag ==0) {
     762           0 :     if (approach!=2 && approach!=3) {
     763           0 :       cout << "Unknown approach " << approach << endl;
     764             :     }
     765           0 :     for(unsigned i=0; i<natoms; i++) {
     766           0 :       if (DeltaG[i].size()==0 ) {
     767           0 :         cout << "Delta G value for residue " << AtomResidueName[1][i] << " not found " << endl;
     768           0 :         error ("missing Delta G parameter\n");
     769             :       }
     770             :     }
     771             :   }
     772           0 : }
     773             : 
     774             : 
     775             : //calculates neighbor list
     776          24 : void SASA_HASEL::calcNlist() {
     777          24 :   if(!nopbc) {
     778          24 :     makeWhole();
     779             :   }
     780             : 
     781        2904 :   for(unsigned i = 0; i < natoms; i++) {
     782        2880 :     Nlist[i].clear();
     783             :   }
     784             : 
     785        2904 :   for(unsigned i = 0; i < natoms; i++) {
     786        2880 :     if (SASAparam[i].size()>0) {
     787      103680 :       for (unsigned j = 0; j < i; j++) {
     788      101952 :         if (SASAparam[j].size()>0) {
     789       61344 :           const Vector Delta_ij_vec = delta( getPosition(i), getPosition(j) );
     790       61344 :           double Delta_ij_mod = Delta_ij_vec.modulo()*10;
     791       61344 :           double overlapD = SASAparam[i][0]+SASAparam[j][0];
     792       61344 :           if (Delta_ij_mod < overlapD) {
     793       26748 :             Nlist.at(i).push_back (j);
     794       26748 :             Nlist.at(j).push_back (i);
     795             :           }
     796             :         }
     797             :       }
     798             :     }
     799             :   }
     800          24 : }
     801             : 
     802             : 
     803             : //calculates SASA according to Hasel et al., Tetrahedron Computer Methodology Vol. 1, No. 2, pp. 103-116, 1988
     804          24 : void SASA_HASEL::calculate() {
     805          24 :   if(!nopbc) {
     806          24 :     makeWhole();
     807             :   }
     808             : 
     809          24 :   if(getExchangeStep()) {
     810           0 :     nl_update = 0;
     811             :   }
     812          24 :   if (firstStepFlag ==0) {
     813           2 :     readPDB();
     814           2 :     readSASAparam();
     815             :   }
     816          24 :   if (nl_update == 0) {
     817          24 :     calcNlist();
     818             :   }
     819             : 
     820             : 
     821          24 :   auto* moldat = plumed.getActionSet().selectLatest<GenericMolInfo*>(this);
     822          24 :   if( ! moldat ) {
     823           0 :     error("Unable to find MOLINFO in input");
     824             :   }
     825             :   double Si, sasai, bij;
     826          24 :   double sasa = 0;
     827          24 :   vector<Vector> derivatives( natoms );
     828        2904 :   for(unsigned i = 0; i < natoms; i++) {
     829        2880 :     derivatives[i][0] = 0.;
     830        2880 :     derivatives[i][1] = 0.;
     831        2880 :     derivatives[i][2] = 0.;
     832             :   }
     833             : 
     834          24 :   Tensor virial;
     835          24 :   vector <double> ddij_di(3);
     836          24 :   vector <double> dbij_di(3);
     837          24 :   vector <double> dAijt_di(3);
     838             : 
     839          24 :   if( sasa_type==TOTAL ) {
     840        1452 :     for(unsigned i = 0; i < natoms; i++) {
     841        1440 :       if(SASAparam[i].size() > 0) {
     842         864 :         double ri = SASAparam[i][0];
     843         864 :         Si = 4*M_PI*ri*ri;
     844             :         sasai = 1.0;
     845             : 
     846        1728 :         vector <vector <double> > derTerm( Nlist[i].size(), vector <double>(3));
     847             : 
     848         864 :         dAijt_di[0] = 0;
     849         864 :         dAijt_di[1] = 0;
     850         864 :         dAijt_di[2] = 0;
     851         864 :         int NumRes_i = moldat->getResidueNumber(atoms[i]);
     852             : 
     853       27612 :         for (unsigned j = 0; j < Nlist[i].size(); j++) {
     854             :           double pij = 0.3516;
     855             : 
     856       26748 :           int NumRes_j = moldat->getResidueNumber(atoms[Nlist[i][j]]);
     857       26748 :           if (NumRes_i==NumRes_j) {
     858        4320 :             if (CONNECTparam[i][0].compare(AtomResidueName[0][Nlist[i][j]])==0 || CONNECTparam[i][1].compare(AtomResidueName[0][Nlist[i][j]])==0 || CONNECTparam[i][2].compare(AtomResidueName[0][Nlist[i][j]])==0 || CONNECTparam[i][3].compare(AtomResidueName[0][Nlist[i][j]])==0) {
     859             :               pij = 0.8875;
     860             :             }
     861             :           }
     862       26748 :           if ( abs(NumRes_i-NumRes_j) == 1 ) {
     863       10380 :             if ((AtomResidueName[0][i] == "N"  && AtomResidueName[0][Nlist[i][j]]== "CA") || (AtomResidueName[0][Nlist[i][j]] == "N"  && AtomResidueName[0][i]== "CA")) {
     864             :               pij = 0.8875;
     865             :             }
     866             :           }
     867             : 
     868       26748 :           const Vector d_ij_vec = delta( getPosition(i), getPosition(Nlist[i][j]) );
     869       26748 :           double d_ij = d_ij_vec.modulo()*10;
     870             : 
     871       26748 :           double rj = SASAparam[Nlist[i][j]][0];
     872       26748 :           bij = M_PI*ri*(ri+rj-d_ij)*(1+(rj-ri)/d_ij); //Angstrom2
     873             : 
     874       26748 :           sasai = sasai*(1-SASAparam[i][1]*pij*bij/Si); //nondimensional
     875             : 
     876       26748 :           ddij_di[0] = -10*(getPosition(Nlist[i][j])[0]-getPosition(i)[0])/d_ij; //nondimensional
     877       26748 :           ddij_di[1] = -10*(getPosition(Nlist[i][j])[1]-getPosition(i)[1])/d_ij;
     878       26748 :           ddij_di[2] = -10*(getPosition(Nlist[i][j])[2]-getPosition(i)[2])/d_ij;
     879             : 
     880       26748 :           dbij_di[0] = -M_PI*ri*ddij_di[0]*(1+(ri+rj)*(rj-ri)/(d_ij*d_ij)); //Angstrom
     881       26748 :           dbij_di[1] = -M_PI*ri*ddij_di[1]*(1+(ri+rj)*(rj-ri)/(d_ij*d_ij));
     882       26748 :           dbij_di[2] = -M_PI*ri*ddij_di[2]*(1+(ri+rj)*(rj-ri)/(d_ij*d_ij));
     883             : 
     884       26748 :           dAijt_di[0] += -1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[0]; //Angstrom-1
     885       26748 :           dAijt_di[1] += -1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[1];
     886       26748 :           dAijt_di[2] += -1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[2];
     887             : 
     888       26748 :           derTerm[j][0] = 1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[0]; //Angstrom-1
     889       26748 :           derTerm[j][1] = 1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[1];
     890       26748 :           derTerm[j][2] = 1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[2];
     891             : 
     892             :         }
     893             : 
     894         864 :         sasa += Si*sasai/100; //nm2
     895             : 
     896         864 :         derivatives[i][0] += Si*sasai/10*dAijt_di[0]; //nm
     897         864 :         derivatives[i][1] += Si*sasai/10*dAijt_di[1];
     898         864 :         derivatives[i][2] += Si*sasai/10*dAijt_di[2];
     899             : 
     900       27612 :         for (unsigned j = 0; j < Nlist[i].size(); j++) {
     901       26748 :           derivatives[Nlist[i][j]][0] += Si*sasai/10*derTerm[j][0]; //nm
     902       26748 :           derivatives[Nlist[i][j]][1] += Si*sasai/10*derTerm[j][1];
     903       26748 :           derivatives[Nlist[i][j]][2] += Si*sasai/10*derTerm[j][2];
     904             :         }
     905         864 :       }
     906             :     }
     907             :   }
     908             : 
     909             : 
     910          24 :   if( sasa_type==TRANSFER ) {
     911             : 
     912          12 :     if (firstStepFlag ==0) {
     913           1 :       readMaxSurf();
     914             :     }
     915             : 
     916          12 :     if (firstStepFlag ==0 && DeltaGValues != "absent") {
     917           1 :       readDeltaG();
     918             :     }
     919             : 
     920          12 :     if (DeltaGValues == "absent") {
     921           0 :       computeDeltaG();
     922             :     }
     923             : 
     924             : 
     925        1452 :     for(unsigned i = 0; i < natoms; i++) {
     926             : 
     927             : 
     928             : 
     929        1440 :       if(SASAparam[i].size() > 0) {
     930         864 :         double ri = SASAparam[i][0];
     931         864 :         Si = 4*M_PI*ri*ri;
     932             :         sasai = 1.0;
     933             : 
     934        1728 :         vector <vector <double> > derTerm( Nlist[i].size(), vector <double>(3));
     935             : 
     936         864 :         dAijt_di[0] = 0;
     937         864 :         dAijt_di[1] = 0;
     938         864 :         dAijt_di[2] = 0;
     939         864 :         int NumRes_i = moldat->getResidueNumber(atoms[i]);
     940             : 
     941       27612 :         for (unsigned j = 0; j < Nlist[i].size(); j++) {
     942             :           double pij = 0.3516;
     943             : 
     944       26748 :           int NumRes_j = moldat->getResidueNumber(atoms[Nlist[i][j]]);
     945       26748 :           if (NumRes_i==NumRes_j) {
     946        4320 :             if (CONNECTparam[i][0].compare(AtomResidueName[0][Nlist[i][j]])==0 || CONNECTparam[i][1].compare(AtomResidueName[0][Nlist[i][j]])==0 || CONNECTparam[i][2].compare(AtomResidueName[0][Nlist[i][j]])==0 || CONNECTparam[i][3].compare(AtomResidueName[0][Nlist[i][j]])==0) {
     947             :               pij = 0.8875;
     948             :             }
     949             :           }
     950       26748 :           if ( abs(NumRes_i-NumRes_j) == 1 ) {
     951       10380 :             if ((AtomResidueName[0][i] == "N"  && AtomResidueName[0][Nlist[i][j]]== "CA") || (AtomResidueName[0][Nlist[i][j]] == "N"  && AtomResidueName[0][i]== "CA")) {
     952             :               pij = 0.8875;
     953             :             }
     954             :           }
     955             : 
     956       26748 :           const Vector d_ij_vec = delta( getPosition(i), getPosition(Nlist[i][j]) );
     957       26748 :           double d_ij = d_ij_vec.modulo()*10;
     958             : 
     959       26748 :           double rj = SASAparam[Nlist[i][j]][0];
     960       26748 :           bij = M_PI*ri*(ri+rj-d_ij)*(1+(rj-ri)/d_ij); //Angstrom2
     961             : 
     962       26748 :           sasai = sasai*(1-SASAparam[i][1]*pij*bij/Si); //nondimensional
     963             : 
     964       26748 :           ddij_di[0] = -10*(getPosition(Nlist[i][j])[0]-getPosition(i)[0])/d_ij; //nondimensional
     965       26748 :           ddij_di[1] = -10*(getPosition(Nlist[i][j])[1]-getPosition(i)[1])/d_ij;
     966       26748 :           ddij_di[2] = -10*(getPosition(Nlist[i][j])[2]-getPosition(i)[2])/d_ij;
     967             : 
     968       26748 :           dbij_di[0] = -M_PI*ri*ddij_di[0]*(1+(ri+rj)*(rj-ri)/(d_ij*d_ij)); //Angstrom
     969       26748 :           dbij_di[1] = -M_PI*ri*ddij_di[1]*(1+(ri+rj)*(rj-ri)/(d_ij*d_ij));
     970       26748 :           dbij_di[2] = -M_PI*ri*ddij_di[2]*(1+(ri+rj)*(rj-ri)/(d_ij*d_ij));
     971             : 
     972       26748 :           dAijt_di[0] += -1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[0]; //Angstrom-1
     973       26748 :           dAijt_di[1] += -1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[1];
     974       26748 :           dAijt_di[2] += -1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[2];
     975             : 
     976       26748 :           derTerm[j][0] = 1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[0]; //Angstrom-1
     977       26748 :           derTerm[j][1] = 1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[1];
     978       26748 :           derTerm[j][2] = 1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[2];
     979             : 
     980             :         }
     981             : 
     982        2880 :         if (AtomResidueName[0][i] == "N" || AtomResidueName[0][i] == "CA"  || AtomResidueName[0][i] == "C" || AtomResidueName[0][i] == "O" || AtomResidueName[0][i] == "H") {
     983             : 
     984         720 :           sasa += Si*sasai/MaxSurf[i][0]*DeltaG[natoms][0]; //kJ/mol
     985             : 
     986             : 
     987         720 :           derivatives[i][0] += Si*sasai*dAijt_di[0]/MaxSurf[i][0]*DeltaG[natoms][0]*10; //kJ/mol/nm
     988         720 :           derivatives[i][1] += Si*sasai*dAijt_di[1]/MaxSurf[i][0]*DeltaG[natoms][0]*10;
     989         720 :           derivatives[i][2] += Si*sasai*dAijt_di[2]/MaxSurf[i][0]*DeltaG[natoms][0]*10;
     990             :         }
     991             : 
     992        2880 :         if (AtomResidueName[0][i] != "N" && AtomResidueName[0][i] != "CA"  && AtomResidueName[0][i] != "C" && AtomResidueName[0][i] != "O" && AtomResidueName[0][i] != "H") {
     993         144 :           sasa += Si*sasai/MaxSurf[i][1]*DeltaG[i][0]; //kJ/mol
     994             : 
     995         144 :           derivatives[i][0] += Si*sasai*dAijt_di[0]/MaxSurf[i][1]*DeltaG[i][0]*10; //kJ/mol/nm
     996         144 :           derivatives[i][1] += Si*sasai*dAijt_di[1]/MaxSurf[i][1]*DeltaG[i][0]*10;
     997         144 :           derivatives[i][2] += Si*sasai*dAijt_di[2]/MaxSurf[i][1]*DeltaG[i][0]*10;
     998             :         }
     999             : 
    1000             : 
    1001       27612 :         for (unsigned j = 0; j < Nlist[i].size(); j++) {
    1002       86883 :           if (AtomResidueName[0][i] == "N" || AtomResidueName[0][i] == "CA"  || AtomResidueName[0][i] == "C" || AtomResidueName[0][i] == "O" || AtomResidueName[0][i] == "H") {
    1003       22438 :             derivatives[Nlist[i][j]][0] += Si*sasai*10*derTerm[j][0]/MaxSurf[i][0]*DeltaG[natoms][0]; //kJ/mol/nm
    1004       22438 :             derivatives[Nlist[i][j]][1] += Si*sasai*10*derTerm[j][1]/MaxSurf[i][0]*DeltaG[natoms][0];
    1005       22438 :             derivatives[Nlist[i][j]][2] += Si*sasai*10*derTerm[j][2]/MaxSurf[i][0]*DeltaG[natoms][0];
    1006             :           }
    1007             : 
    1008       86883 :           if (AtomResidueName[0][i] != "N" && AtomResidueName[0][i] != "CA"  && AtomResidueName[0][i] != "C" && AtomResidueName[0][i] != "O" && AtomResidueName[0][i] != "H") {
    1009        4310 :             derivatives[Nlist[i][j]][0] += Si*sasai*10*derTerm[j][0]/MaxSurf[i][1]*DeltaG[i][0]; //kJ/mol/nm
    1010        4310 :             derivatives[Nlist[i][j]][1] += Si*sasai*10*derTerm[j][1]/MaxSurf[i][1]*DeltaG[i][0];
    1011        4310 :             derivatives[Nlist[i][j]][2] += Si*sasai*10*derTerm[j][2]/MaxSurf[i][1]*DeltaG[i][0];
    1012             :           }
    1013             :         }
    1014         864 :       }
    1015             :     }
    1016             :   }
    1017             : 
    1018             : 
    1019        2904 :   for(unsigned i=0; i<natoms; i++) {
    1020        2880 :     setAtomsDerivatives(i,derivatives[i]);
    1021        2880 :     virial -= Tensor(getPosition(i),derivatives[i]);
    1022             :   }
    1023             : 
    1024          24 :   setBoxDerivatives(virial);
    1025          24 :   setValue(sasa);
    1026          24 :   firstStepFlag = 1;
    1027          24 :   ++nl_update;
    1028          24 :   if (nl_update == stride) {
    1029          24 :     nl_update = 0;
    1030             :   }
    1031             : // setBoxDerivativesNoPbc();
    1032          24 : }
    1033             : 
    1034             : }//namespace sasa
    1035             : }//namespace PLMD

Generated by: LCOV version 1.16