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: 2025-03-25 09:33:27 Functions: 11 13 84.6 %

          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 "core/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 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             : PLUMED_REGISTER_ACTION(SASA_HASEL,"SASA_HASEL")
     166             : 
     167           4 : void SASA_HASEL::registerKeywords(Keywords& keys) {
     168           4 :   Colvar::registerKeywords(keys);
     169           4 :   keys.add("atoms","ATOMS","the group of atoms that you are calculating the SASA for");
     170           4 :   keys.add("compulsory","TYPE","TOTAL","The type of calculation you want to perform. Can be TOTAL or TRANSFER");
     171           4 :   keys.add("compulsory", "NL_STRIDE", "The frequency with which the neighbor list for the calculation of SASA is updated.");
     172           4 :   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           4 :   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           8 :   keys.setValueDescription("scalar","the solvent accessible surface area (SASA) of the molecule");
     175           4 : }
     176             : 
     177             : 
     178           2 : SASA_HASEL::SASA_HASEL(const ActionOptions&ao):
     179             :   PLUMED_COLVAR_INIT(ao),
     180           2 :   nopbc(false),
     181           2 :   stride(10),
     182           2 :   nl_update(0),
     183           4 :   DeltaGValues("absent"),
     184           2 :   Ti(0),
     185           2 :   firstStepFlag(0) {
     186           2 :   rs = 0.14;
     187           2 :   parse("DELTAGFILE",DeltaGValues);
     188           2 :   parse("APPROACH", approach);
     189           4 :   parseAtomList("ATOMS",atoms);
     190           2 :   if(atoms.size()==0) {
     191           0 :     error("no atoms specified");
     192             :   }
     193             :   std::string Type;
     194           2 :   parse("TYPE",Type);
     195           2 :   parse("NL_STRIDE", stride);
     196           2 :   parseFlag("NOPBC",nopbc);
     197           2 :   checkRead();
     198             : 
     199           2 :   if(Type=="TOTAL") {
     200           1 :     sasa_type=TOTAL;
     201           1 :   } else if(Type=="TRANSFER") {
     202           1 :     sasa_type=TRANSFER;
     203             :   } else {
     204           0 :     error("Unknown SASA type");
     205             :   }
     206             : 
     207           2 :   switch(sasa_type) {
     208           1 :   case TOTAL:
     209           1 :     log.printf("  TOTAL SASA;");
     210             :     break;
     211           1 :   case TRANSFER:
     212           1 :     log.printf("  TRANSFER MODEL;");
     213             :     break;
     214             :   }
     215             : 
     216           2 :   log.printf("  atoms involved : ");
     217         242 :   for(unsigned i=0; i<atoms.size(); ++i) {
     218         240 :     if(i%25==0) {
     219          10 :       log<<"\n";
     220             :     }
     221         240 :     log.printf("%d ",atoms[i].serial());
     222             :   }
     223           2 :   log.printf("\n");
     224             : 
     225           2 :   if(nopbc) {
     226           0 :     log<<"  PBC will be ignored\n";
     227             :   } else {
     228           2 :     log<<"  broken molecules will be rebuilt assuming atoms are in the proper order\n";
     229             :   }
     230             : 
     231             : 
     232           2 :   addValueWithDerivatives();
     233           2 :   setNotPeriodic();
     234           2 :   requestAtoms(atoms);
     235             : 
     236           2 :   natoms = getNumberOfAtoms();
     237           2 :   AtomResidueName.resize(2);
     238           2 :   SASAparam.resize(natoms);
     239           2 :   CONNECTparam.resize(natoms);
     240           2 :   MaxSurf.resize(natoms);
     241           2 :   DeltaG.resize(natoms+1);
     242           2 :   Nlist.resize(natoms);
     243             : 
     244             : 
     245           2 : }
     246             : 
     247             : 
     248             : //splits strings into tokens. Used to read into SASA parameters file and into reference pdb file
     249             : template <class Container>
     250          42 : void split(const std::string& str, Container& cont) {
     251          42 :   std::istringstream iss(str);
     252          84 :   std::copy(std::istream_iterator<std::string>(iss),
     253          42 :             std::istream_iterator<std::string>(),
     254             :             std::back_inserter(cont));
     255          42 : }
     256             : 
     257             : 
     258             : //reads input PDB file provided with MOLINFO, and assigns atom and residue names to each atom involved in the CV
     259             : 
     260           2 : void SASA_HASEL::readPDB() {
     261           2 :   auto* moldat = plumed.getActionSet().selectLatest<GenericMolInfo*>(this);
     262           2 :   if( ! moldat ) {
     263           0 :     error("Unable to find MOLINFO in input");
     264             :   }
     265             :   AtomResidueName[0].clear();
     266             :   AtomResidueName[1].clear();
     267             : 
     268         242 :   for(unsigned i=0; i<natoms; i++) {
     269         240 :     string Aname = moldat->getAtomName(atoms[i]);
     270         240 :     string Rname = moldat->getResidueName(atoms[i]);
     271         240 :     AtomResidueName[0].push_back (Aname);
     272         240 :     AtomResidueName[1].push_back (Rname);
     273             :   }
     274             : 
     275           2 : }
     276             : 
     277             : 
     278             : //Hasel et al. parameters database
     279           2 : map<string, vector<std::string> > SASA_HASEL::setupHASELparam() {
     280             :   map<string, vector<std::string> > haselmap;
     281          16 :   haselmap["ALA_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     282          16 :   haselmap["ALA_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     283          16 :   haselmap["ALA_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     284          16 :   haselmap["ALA_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     285          16 :   haselmap["ALA_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     286          16 :   haselmap["ALA_CB"] = { "2.0",  "0.88",  "CA",  "Z",  "Z",  "Z", };
     287          16 :   haselmap["ASP_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     288          16 :   haselmap["ASP_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     289          16 :   haselmap["ASP_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     290          16 :   haselmap["ASP_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     291          16 :   haselmap["ASP_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     292          16 :   haselmap["ASP_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     293          16 :   haselmap["ASP_CG"] = { "1.72",  "1.554",  "CB",  "OD1",  "OD2",  "Z", };
     294          16 :   haselmap["ASP_OD1"] = { "1.5",  "0.926",  "CG",  "Z",  "Z",  "Z", };
     295          16 :   haselmap["ASP_OD2"] = { "1.7",  "0.922",  "CG",  "Z",  "Z",  "Z", };
     296          16 :   haselmap["ASN_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     297          16 :   haselmap["ASN_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     298          16 :   haselmap["ASN_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     299          16 :   haselmap["ASN_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     300          16 :   haselmap["ASN_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     301          16 :   haselmap["ASN_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     302          16 :   haselmap["ASN_CG"] = { "1.7",  "2.149",  "CB",  "OD1",  "ND2",  "Z", };
     303          16 :   haselmap["ASN_OD1"] = { "1.5",  "0.926",  "CG",  "Z",  "Z",  "Z", };
     304          16 :   haselmap["ASN_ND2"] = { "1.6",  "1.215",  "CG",  "1HD2",  "1HD2",  "Z", };
     305          16 :   haselmap["ASN_1HD2"] = { "1.1",  "1.128",  "ND2",  "Z",  "Z",  "Z", };
     306          16 :   haselmap["ASN_2HD2"] = { "1.1",  "1.128",  "ND2",  "Z",  "Z",  "Z", };
     307          16 :   haselmap["ARG_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     308          16 :   haselmap["ARG_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     309          16 :   haselmap["ARG_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     310          16 :   haselmap["ARG_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     311          16 :   haselmap["ARG_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     312          16 :   haselmap["ARG_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     313          16 :   haselmap["ARG_CG"] = { "1.9",  "1.045",  "CB",  "CD",  "Z",  "Z", };
     314          16 :   haselmap["ARG_CD"] = { "1.9",  "1.045",  "CG",  "NE",  "Z",  "Z", };
     315          16 :   haselmap["ARG_NE"] = { "1.55",  "1.028",  "CD",  "HE",  "CZ",  "Z", };
     316          16 :   haselmap["ARG_NH1"] = { "1.55",  "1.028",  "CZ",  "1HH1",  "2HH1",  "Z", };
     317          16 :   haselmap["ARG_NH2"] = { "1.55",  "1.028",  "CZ",  "1HH2",  "2HH2",  "Z", };
     318          16 :   haselmap["ARG_CZ"] = { "1.72",  "1.554",  "NE",  "NH1",  "NH2",  "Z", };
     319          16 :   haselmap["ARG_HE"] = { "1.1",  "1.128",  "NE",  "Z",  "Z",  "Z", };
     320          16 :   haselmap["ARG_1HH2"] = { "1.1",  "1.128",  "NH2",  "Z",  "Z",  "Z", };
     321          16 :   haselmap["ARG_2HH2"] = { "1.1",  "1.128",  "NH2",  "Z",  "Z",  "Z", };
     322          16 :   haselmap["ARG_2HH1"] = { "1.1",  "1.128",  "NH1",  "Z",  "Z",  "Z", };
     323          16 :   haselmap["ARG_1HH1"] = { "1.1",  "1.128",  "NH1",  "Z",  "Z",  "Z", };
     324          16 :   haselmap["CYS_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     325          16 :   haselmap["CYS_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     326          16 :   haselmap["CYS_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     327          16 :   haselmap["CYS_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     328          16 :   haselmap["CYS_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     329          16 :   haselmap["CYS_CB"] = { "1.9",  "1.045",  "CA",  "SG",  "Z",  "Z", };
     330          16 :   haselmap["CYS_SG"] = { "1.8",  "1.121",  "CB",  "HG",  "Z",  "Z", };
     331          16 :   haselmap["CYS_HG"] = { "1.2",  "0.928",  "SG",  "Z",  "Z",  "Z", };
     332          16 :   haselmap["GLU_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     333          16 :   haselmap["GLU_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     334          16 :   haselmap["GLU_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     335          16 :   haselmap["GLU_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     336          16 :   haselmap["GLU_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     337          16 :   haselmap["GLU_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     338          16 :   haselmap["GLU_CG"] = { "1.9",  "1.045",  "CB",  "CD",  "Z",  "Z", };
     339          16 :   haselmap["GLU_CD"] = { "1.72",  "1.554",  "CG",  "OE1",  "OE2",  "Z", };
     340          16 :   haselmap["GLU_OE1"] = { "1.5",  "0.926",  "CD",  "Z",  "Z",  "Z", };
     341          16 :   haselmap["GLU_OE2"] = { "1.7",  "0.922",  "CD",  "Z",  "Z",  "Z", };
     342          16 :   haselmap["GLN_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     343          16 :   haselmap["GLN_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     344          16 :   haselmap["GLN_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     345          16 :   haselmap["GLN_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     346          16 :   haselmap["GLN_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     347          16 :   haselmap["GLN_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     348          16 :   haselmap["GLN_CG"] = { "1.9",  "1.045",  "CB",  "CD",  "Z",  "Z", };
     349          16 :   haselmap["GLN_CD"] = { "1.72",  "1.554",  "CG",  "OE1",  "NE2",  "Z", };
     350          16 :   haselmap["GLN_OE1"] = { "1.5",  "0.926",  "CD",  "Z",  "Z",  "Z", };
     351          16 :   haselmap["GLN_NE2"] = { "1.6",  "1.215",  "CD",  "2HE2",  "1HE2",  "Z", };
     352          16 :   haselmap["GLN_2HE2"] = { "1.1",  "1.128",  "NE2",  "Z",  "Z",  "Z", };
     353          16 :   haselmap["GLN_1HE2"] = { "1.1",  "1.128",  "NE2",  "Z",  "Z",  "Z", };
     354          16 :   haselmap["GLY_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     355          16 :   haselmap["GLY_CA"] = { "1.7",  "2.149",  "N",  "C",  "Z",  "Z", };
     356          16 :   haselmap["GLY_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     357          16 :   haselmap["GLY_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     358          16 :   haselmap["GLY_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     359          16 :   haselmap["HIS_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     360          16 :   haselmap["HIS_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     361          16 :   haselmap["HIS_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     362          16 :   haselmap["HIS_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     363          16 :   haselmap["HIS_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     364          16 :   haselmap["HIS_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     365          16 :   haselmap["HIS_CG"] = { "1.72",  "1.554",  "CB",  "CD2",  "ND1",  "Z", };
     366          16 :   haselmap["HIS_ND1"] = { "1.55",  "1.028",  "CG",  "CE1",  "Z",  "Z", };
     367          16 :   haselmap["HIS_CE1"] = { "1.8",  "1.073",  "ND1",  "NE2",  "Z",  "Z", };
     368          16 :   haselmap["HIS_NE2"] = { "1.55",  "1.413",  "CE1",  "2HE",  "CD2",  "Z", };
     369          16 :   haselmap["HIS_CD2"] = { "1.8",  "1.073",  "NE2",  "CG",  "Z",  "Z", };
     370          16 :   haselmap["HIS_2HE"] = { "1.1",  "1.128",  "NE2",  "Z",  "Z",  "Z", };
     371          16 :   haselmap["ILE_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     372          16 :   haselmap["ILE_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     373          16 :   haselmap["ILE_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     374          16 :   haselmap["ILE_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     375          16 :   haselmap["ILE_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     376          16 :   haselmap["ILE_CB"] = { "1.8",  "1.276",  "CA",  "CG2",  "CG1",  "Z", };
     377          16 :   haselmap["ILE_CG2"] = { "2.0",  "0.88",  "CB",  "Z",  "Z",  "Z", };
     378          16 :   haselmap["ILE_CG1"] = { "1.9",  "1.045",  "CB",  "CD1",  "Z",  "Z", };
     379          16 :   haselmap["ILE_CD1"] = { "2.0",  "0.88",  "CG1",  "Z",  "Z",  "Z", };
     380          16 :   haselmap["LEU_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     381          16 :   haselmap["LEU_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     382          16 :   haselmap["LEU_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     383          16 :   haselmap["LEU_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     384          16 :   haselmap["LEU_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     385          16 :   haselmap["LEU_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     386          16 :   haselmap["LEU_CG"] = { "1.8",  "1.276",  "CB",  "CD1",  "CD2",  "Z", };
     387          16 :   haselmap["LEU_CD1"] = { "2.0",  "0.88",  "CG",  "Z",  "Z",  "Z", };
     388          16 :   haselmap["LEU_CD2"] = { "2.0",  "0.88",  "CG",  "Z",  "Z",  "Z", };
     389          16 :   haselmap["LYS_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     390          16 :   haselmap["LYS_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     391          16 :   haselmap["LYS_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     392          16 :   haselmap["LYS_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     393          16 :   haselmap["LYS_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     394          16 :   haselmap["LYS_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     395          16 :   haselmap["LYS_CG"] = { "1.9",  "1.045",  "CB",  "CD",  "Z",  "Z", };
     396          16 :   haselmap["LYS_CD"] = { "1.9",  "1.045",  "CG",  "CE",  "Z",  "Z", };
     397          16 :   haselmap["LYS_CE"] = { "1.9",  "1.045",  "CD",  "NZ",  "Z",  "Z", };
     398          16 :   haselmap["LYS_NZ"] = { "1.6",  "1.215",  "CE",  "1HZ",  "2HZ",  "3HZ", };
     399          16 :   haselmap["LYS_1HZ"] = { "1.1",  "1.128",  "NZ",  "Z",  "Z",  "Z", };
     400          16 :   haselmap["LYS_2HZ"] = { "1.1",  "1.128",  "NZ",  "Z",  "Z",  "Z", };
     401          16 :   haselmap["LYS_3HZ"] = { "1.1",  "1.128",  "NZ",  "Z",  "Z",  "Z", };
     402          16 :   haselmap["MET_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     403          16 :   haselmap["MET_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     404          16 :   haselmap["MET_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     405          16 :   haselmap["MET_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     406          16 :   haselmap["MET_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     407          16 :   haselmap["MET_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     408          16 :   haselmap["MET_CG"] = { "1.9",  "1.045",  "CB",  "SD",  "Z",  "Z", };
     409          16 :   haselmap["MET_SD"] = { "1.8",  "1.121",  "CG",  "CE",  "Z",  "Z", };
     410          16 :   haselmap["MET_CE"] = { "2.0",  "0.88",  "SD",  "Z",  "Z",  "Z", };
     411          16 :   haselmap["PHE_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     412          16 :   haselmap["PHE_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     413          16 :   haselmap["PHE_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     414          16 :   haselmap["PHE_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     415          16 :   haselmap["PHE_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     416          16 :   haselmap["PHE_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     417          16 :   haselmap["PHE_CG"] = { "1.72",  "1.554",  "CB",  "CD1",  "CD2",  "Z", };
     418          16 :   haselmap["PHE_CD1"] = { "1.8",  "1.073",  "CG",  "CE1",  "Z",  "Z", };
     419          16 :   haselmap["PHE_CE1"] = { "1.8",  "1.073",  "CD1",  "CZ",  "Z",  "Z", };
     420          16 :   haselmap["PHE_CZ"] = { "1.8",  "1.073",  "CE1",  "CE2",  "Z",  "Z", };
     421          16 :   haselmap["PHE_CE2"] = { "1.8",  "1.073",  "CZ",  "CD2",  "Z",  "Z", };
     422          16 :   haselmap["PHE_CD2"] = { "1.8",  "1.073",  "CE2",  "CG",  "Z",  "Z", };
     423          16 :   haselmap["PRO_N"] = { "1.55",  "1.028",  "CD",  "CA",  "Z",  "Z", };
     424          16 :   haselmap["PRO_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     425          16 :   haselmap["PRO_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     426          16 :   haselmap["PRO_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     427          16 :   haselmap["PRO_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     428          16 :   haselmap["PRO_CG"] = { "1.9",  "1.045",  "CB",  "CD",  "Z",  "Z", };
     429          16 :   haselmap["PRO_CD"] = { "1.9",  "1.045",  "CG",  "N",  "Z",  "Z", };
     430          16 :   haselmap["SER_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     431          16 :   haselmap["SER_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     432          16 :   haselmap["SER_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     433          16 :   haselmap["SER_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     434          16 :   haselmap["SER_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     435          16 :   haselmap["SER_CB"] = { "1.9",  "1.045",  "CA",  "OG",  "Z",  "Z", };
     436          16 :   haselmap["SER_OG"] = { "1.52",  "1.08",  "CB",  "HG",  "Z",  "Z", };
     437          16 :   haselmap["SER_HG"] = { "1.0",  "0.944",  "OG",  "Z",  "Z",  "Z", };
     438          16 :   haselmap["THR_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     439          16 :   haselmap["THR_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     440          16 :   haselmap["THR_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     441          16 :   haselmap["THR_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     442          16 :   haselmap["THR_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     443          16 :   haselmap["THR_CB"] = { "1.8",  "1.276",  "CA",  "CG2",  "OG1",  "Z", };
     444          16 :   haselmap["THR_CG2"] = { "2.0",  "0.88",  "CB",  "Z",  "Z",  "Z", };
     445          16 :   haselmap["THR_OG1"] = { "1.52",  "1.08",  "1HG",  "CB",  "Z",  "Z", };
     446          16 :   haselmap["THR_1HG"] = { "1.0",  "0.944",  "OG1",  "Z",  "Z",  "Z", };
     447          16 :   haselmap["TRP_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     448          16 :   haselmap["TRP_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     449          16 :   haselmap["TRP_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     450          16 :   haselmap["TRP_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     451          16 :   haselmap["TRP_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     452          16 :   haselmap["TRP_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     453          16 :   haselmap["TRP_CG"] = { "1.72",  "1.554",  "CB",  "CD2",  "CD1",  "Z", };
     454          16 :   haselmap["TRP_CD1"] = { "1.8",  "1.073",  "CG",  "NE1",  "Z",  "Z", };
     455          16 :   haselmap["TRP_NE1"] = { "1.55",  "1.413",  "CD1",  "CE2",  "1HE",  "Z", };
     456          16 :   haselmap["TRP_CE2"] = { "1.72",  "1.554",  "NE1",  "CD2",  "CZ2",  "Z", };
     457          16 :   haselmap["TRP_CZ2"] = { "1.8",  "1.073",  "CE2",  "CH2",  "Z",  "Z", };
     458          16 :   haselmap["TRP_CH2"] = { "1.8",  "1.073",  "CZ2",  "CZ3",  "Z",  "Z", };
     459          16 :   haselmap["TRP_CZ3"] = { "1.8",  "1.073",  "CH2",  "CE3",  "Z",  "Z", };
     460          16 :   haselmap["TRP_CE3"] = { "1.8",  "1.073",  "CZ3",  "CD2",  "Z",  "Z", };
     461          16 :   haselmap["TRP_CD2"] = { "1.72",  "1.554",  "CE3",  "CE2",  "CG",  "Z", };
     462          16 :   haselmap["TRP_1HE"] = { "1.1",  "1.128",  "NE1",  "Z",  "Z",  "Z", };
     463          16 :   haselmap["TYR_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     464          16 :   haselmap["TYR_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     465          16 :   haselmap["TYR_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     466          16 :   haselmap["TYR_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     467          16 :   haselmap["TYR_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     468          16 :   haselmap["TYR_CB"] = { "1.9",  "1.045",  "CA",  "CG",  "Z",  "Z", };
     469          16 :   haselmap["TYR_CG"] = { "1.72",  "1.554",  "CB",  "CD1",  "CD2",  "Z", };
     470          16 :   haselmap["TYR_CD1"] = { "1.8",  "1.073",  "CG",  "CE1",  "Z",  "Z", };
     471          16 :   haselmap["TYR_CE1"] = { "1.8",  "1.073",  "CD1",  "CZ",  "Z",  "Z", };
     472          16 :   haselmap["TYR_CZ"] = { "1.72",  "1.554",  "CE1",  "OH",  "CE2",  "Z", };
     473          16 :   haselmap["TYR_OH"] = { "1.52",  "1.08",  "CZ",  "HH",  "Z",  "Z", };
     474          16 :   haselmap["TYR_HH"] = { "1.0",  "0.944",  "OH",  "Z",  "Z",  "Z", };
     475          16 :   haselmap["TYR_CE2"] = { "1.8",  "1.073",  "CZ",  "CD2",  "Z",  "Z", };
     476          16 :   haselmap["TYR_CD2"] = { "1.8",  "1.073",  "CE2",  "CG",  "Z",  "Z", };
     477          16 :   haselmap["VAL_N"] = { "1.55",  "1.028",  "H",  "CA",  "Z",  "Z", };
     478          16 :   haselmap["VAL_CA"] = { "1.7",  "2.149",  "N",  "C",  "CB",  "Z", };
     479          16 :   haselmap["VAL_C"] = { "1.72",  "1.554",  "CA",  "O",  "Z",  "Z", };
     480          16 :   haselmap["VAL_O"] = { "1.5",  "0.926",  "C",  "Z",  "Z",  "Z", };
     481          16 :   haselmap["VAL_H"] = { "1.1",  "1.128",  "N",  "Z",  "Z",  "Z", };
     482          16 :   haselmap["VAL_CB"] = { "1.8",  "1.276",  "CA",  "CG1",  "CG2",  "Z", };
     483          16 :   haselmap["VAL_CG1"] = { "2.0",  "0.88",  "CB",  "Z",  "Z",  "Z", };
     484          16 :   haselmap["VAL_CG2"] = { "2.0",  "0.88",  "CB",  "Z",  "Z",  "Z", };
     485           2 :   return haselmap;
     486             : }
     487             : 
     488             : //assigns SASA parameters to each atom reading from HASEL parameter database
     489           2 : void SASA_HASEL::readSASAparam() {
     490             : 
     491         242 :   for(unsigned i=0; i<natoms; i++) {
     492         240 :     SASAparam[i].clear();
     493             :     CONNECTparam[i].clear();
     494             :   }
     495             : 
     496             :   map<string, vector<std::string> > haselmap;
     497           4 :   haselmap = setupHASELparam();
     498             :   vector<std::string> HASELparamVector;
     499             :   string identifier;
     500             : 
     501             : 
     502         242 :   for(unsigned i=0; i<natoms; i++) {
     503         480 :     identifier = AtomResidueName[1][i]+"_"+AtomResidueName[0][i];
     504         240 :     if (haselmap.find(identifier)!=haselmap.end()) {
     505         144 :       HASELparamVector = haselmap.at(identifier);
     506         144 :       SASAparam[i].push_back (std::atof(HASELparamVector[0].c_str())+rs*10);
     507         144 :       SASAparam[i].push_back (std::atof(HASELparamVector[1].c_str()));
     508         288 :       CONNECTparam[i].push_back (HASELparamVector[2].c_str());
     509         288 :       CONNECTparam[i].push_back (HASELparamVector[3].c_str());
     510         288 :       CONNECTparam[i].push_back (HASELparamVector[4].c_str());
     511         288 :       CONNECTparam[i].push_back (HASELparamVector[5].c_str());
     512             :     }
     513             :   }
     514             : 
     515             : 
     516         242 :   for(unsigned i=0; i<natoms; i++) {
     517         240 :     if (SASAparam[i].size()==0 ) {
     518          96 :       if ((AtomResidueName[0][i][0]=='O') || (AtomResidueName[0][i][0]=='N') || (AtomResidueName[0][i][0]=='C') || (AtomResidueName[0][i][0]=='S')) {
     519           0 :         cout << "Could not find SASA paramaters for atom " << AtomResidueName[0][i] << " of residue " << AtomResidueName[1][i] << endl;
     520           0 :         error ("missing SASA parameters\n");
     521             :       }
     522             :     }
     523             :   }
     524             : 
     525             : 
     526           4 : }
     527             : 
     528             : 
     529             : 
     530             : //Max Surf values, used only if TYPE=TRANSFER
     531           1 : map<string, vector<double> > SASA_HASEL::setupMaxSurfMap() {
     532             :   // Max Surface Area for backbone and sidechain, in nm2
     533             :   map<string, vector<double> > valuemap;
     534           1 :   valuemap ["ALA"]= {0.56425,0.584851,};
     535           1 :   valuemap ["ARG"]= {0.498656,1.808093,};
     536           1 :   valuemap ["ASN"]= {0.473409,0.818394,};
     537           1 :   valuemap ["ASP"]= {0.477057,0.977303,};
     538           1 :   valuemap ["CYS"]= {0.507512,0.791483,};
     539           1 :   valuemap ["GLN"]= {0.485859,1.281534,};
     540           1 :   valuemap ["GLU"]= {0.495054,1.464718,};
     541           1 :   valuemap ["GLY"]= {0.658632,0,};
     542           1 :   valuemap ["HIS"]= {0.48194,1.118851,};
     543           1 :   valuemap ["ILE"]= {0.461283,1.450569,};
     544           1 :   valuemap ["LEU"]= {0.476315,1.498843,};
     545           1 :   valuemap ["LYS"]= {0.493533,1.619731,};
     546           1 :   valuemap ["MET"]= {0.507019,1.631904,};
     547           1 :   valuemap ["PHE"]= {0.457462, 1.275125,};
     548           1 :   valuemap ["PRO"]= {0.315865,0.859456,};
     549           1 :   valuemap ["SER"]= {0.48636,0.627233,};
     550           1 :   valuemap ["THR"]= {0.45064,0.91088,};
     551           1 :   valuemap ["TRP"]= {0.45762,1.366369,};
     552           1 :   valuemap ["TYR"]= {0.461826,1.425822,};
     553           1 :   valuemap ["VAL"]= {0.477054,1.149101,};
     554           1 :   return valuemap;
     555             : }
     556             : 
     557             : 
     558             : 
     559             : //reads maximum surface values per residue type and assigns values to each atom, only used if sasa_type = TRANSFER
     560             : 
     561           1 : void SASA_HASEL::readMaxSurf() {
     562             :   map<string, vector<double> > valuemap;
     563           2 :   valuemap = setupMaxSurfMap();
     564             :   vector<double> MaxSurfVector;
     565             : 
     566         121 :   for(unsigned i=0; i<natoms; i++) {
     567         120 :     MaxSurf[i].clear();
     568         120 :     MaxSurfVector = valuemap.at(AtomResidueName[1][i]);
     569         120 :     MaxSurf[i].push_back (MaxSurfVector[0]*100);
     570         120 :     MaxSurf[i].push_back (MaxSurfVector[1]*100);
     571             :   }
     572           1 : }
     573             : 
     574             : //reads file with free energy values for sidechains and for the backbone, and assigns values to each atom. Only used if sasa_type = TRANSFER
     575             : 
     576           1 : void SASA_HASEL::readDeltaG() {
     577             : 
     578         121 :   for(unsigned i=0; i<natoms; i++) {
     579         120 :     DeltaG[i].clear();
     580             :   }
     581             : 
     582             :   string DeltaGline;
     583           1 :   fstream DeltaGFile;
     584           1 :   DeltaGFile.open(DeltaGValues);
     585           1 :   if (DeltaGFile) {
     586             :     int backboneflag = 0;
     587          23 :     while(getline(DeltaGFile, DeltaGline)) {
     588          22 :       if(!DeltaGline.empty()) {
     589             :         std::vector<std::string> DeltaGtoken;
     590          21 :         split(DeltaGline, DeltaGtoken);
     591        2541 :         for(unsigned i=0; i<natoms; i++) {
     592        2520 :           if (DeltaGtoken[0].compare(AtomResidueName[1][i])==0 ) {
     593         120 :             DeltaG[i].push_back (std::atof(DeltaGtoken[1].c_str()));
     594             :           }
     595             :         }
     596          21 :         if (DeltaGtoken[0].compare("BACKBONE")==0 ) {
     597             :           backboneflag = 1;
     598           1 :           DeltaG[natoms].push_back (std::atof(DeltaGtoken[1].c_str()));
     599             :         }
     600          21 :       }
     601             :     }
     602           1 :     if ( backboneflag == 0) {
     603           0 :       error("Cannot find backbone value in Delta G parameters file\n");
     604             :     }
     605             :   } else {
     606           0 :     error("Cannot open DeltaG file");
     607             :   }
     608             : 
     609         121 :   for(unsigned i=0; i<natoms; i++) {
     610         120 :     if (DeltaG[i].size()==0 ) {
     611           0 :       cout << "Delta G value for residue " << AtomResidueName[1][i] << " not found " << endl;
     612           0 :       error ("missing Delta G parameter\n");
     613             :     }
     614             :   }
     615             : 
     616           2 : }
     617             : 
     618             : //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.
     619             : 
     620           0 : void SASA_HASEL::computeDeltaG() {
     621             : 
     622           0 :   for(unsigned i=0; i<natoms; i++) {
     623           0 :     DeltaG[i].clear();
     624             :   }
     625             : 
     626             :   double T;
     627           0 :   T = getkBT()/getKBoltzmann();
     628             : 
     629           0 :   if (T != Ti) {
     630           0 :     for(unsigned i=0; i<natoms; i++) {
     631           0 :       if (approach==2) {
     632           0 :         if (AtomResidueName[1][i].compare("ALA")==0) {
     633           0 :           DeltaG[i].push_back (-2.995/1000*std::pow(T,2)+1.808*T-272.895);
     634             :         }
     635           0 :         if (AtomResidueName[1][i].compare("ARG")==0) {
     636           0 :           DeltaG[i].push_back (-3.182/1000*std::pow(T,2)+1.894*T-282.032);
     637             :         }
     638           0 :         if (AtomResidueName[1][i].compare("ASN")==0) {
     639           0 :           DeltaG[i].push_back (-1.047/1000*std::pow(T,2)+0.6068*T-87.846);
     640             :         }
     641           0 :         if (AtomResidueName[1][i].compare("ASP")==0) {
     642           0 :           DeltaG[i].push_back (-0.1794/1000*std::pow(T,2)+0.1091*T-16.526);
     643             :         }
     644           0 :         if (AtomResidueName[1][i].compare("CYS")==0) {
     645           0 :           DeltaG[i].push_back (-3.09/1000*std::pow(T,2)+1.835*T-272.26);
     646             :         }
     647           0 :         if (AtomResidueName[1][i].compare("GLN")==0) {
     648           0 :           DeltaG[i].push_back (-2.23/1000*std::pow(T,2)+1.335*T-199.707);
     649             :         }
     650           0 :         if (AtomResidueName[1][i].compare("GLU")==0) {
     651           0 :           DeltaG[i].push_back (-1.511/1000*std::pow(T,2)+0.8904*T-131.168);
     652             :         }
     653           0 :         if (AtomResidueName[1][i].compare("GLY")==0) {
     654           0 :           DeltaG[i].push_back (0);
     655             :         }
     656           0 :         if (AtomResidueName[1][i].compare("HIS")==0) {
     657           0 :           DeltaG[i].push_back (-3.482/1000*std::pow(T,2)+2.084*T-311.694);
     658             :         }
     659           0 :         if (AtomResidueName[1][i].compare("ILE")==0) {
     660           0 :           DeltaG[i].push_back (-6.364/1000*std::pow(T,2)+3.8*T-567.444);
     661             :         }
     662           0 :         if (AtomResidueName[1][i].compare("LEU")==0) {
     663           0 :           DeltaG[i].push_back (-7.466/1000*std::pow(T,2)+4.417*T-653.394);
     664             :         }
     665           0 :         if (AtomResidueName[1][i].compare("LYS")==0) {
     666           0 :           DeltaG[i].push_back (-2.091/1000*std::pow(T,2)+1.2458*T-185.549);
     667             :         }
     668           0 :         if (AtomResidueName[1][i].compare("MET")==0) {
     669           0 :           DeltaG[i].push_back (-3.807/1000*std::pow(T,2)+2.272*T-339.007);
     670             :         }
     671           0 :         if (AtomResidueName[1][i].compare("PHE")==0) {
     672           0 :           DeltaG[i].push_back (-7.828/1000*std::pow(T,2)+4.644*T-688.874);
     673             :         }
     674           0 :         if (AtomResidueName[1][i].compare("PRO")==0) {
     675           0 :           DeltaG[i].push_back (-2.347/1000*std::pow(T,2)+1.411*T-212.059);
     676             :         }
     677           0 :         if (AtomResidueName[1][i].compare("SER")==0) {
     678           0 :           DeltaG[i].push_back (1.813/1000*std::pow(T,2)-1.05*T+151.957);
     679             :         }
     680           0 :         if (AtomResidueName[1][i].compare("THR")==0) {
     681           0 :           DeltaG[i].push_back (-2.64/1000*std::pow(T,2)+1.591*T-239.516);
     682             :         }
     683           0 :         if (AtomResidueName[1][i].compare("TRP")==0) {
     684           0 :           DeltaG[i].push_back (-11.66/1000*std::pow(T,2)+6.916*T-1025.293);
     685             :         }
     686           0 :         if (AtomResidueName[1][i].compare("TYR")==0) {
     687           0 :           DeltaG[i].push_back (-7.513/1000*std::pow(T,2)+4.478*T-667.261);
     688             :         }
     689           0 :         if (AtomResidueName[1][i].compare("VAL")==0) {
     690           0 :           DeltaG[i].push_back (-4.902/1000*std::pow(T,2)+2.921*T-435.309);
     691             :         }
     692           0 :         DeltaG[natoms].push_back (-0.6962/1000*std::pow(T,2)+0.4426*T-70.015);
     693             :       }
     694           0 :       if (approach==3) {
     695           0 :         if (AtomResidueName[1][i].compare("ALA")==0) {
     696           0 :           DeltaG[i].push_back (-2.995/1000*std::pow(T,2)+1.808*T-272.105);
     697             :         }
     698           0 :         if (AtomResidueName[1][i].compare("ARG")==0) {
     699           0 :           DeltaG[i].push_back (-3.182/1000*std::pow(T,2)+1.894*T-284.086);
     700             :         }
     701           0 :         if (AtomResidueName[1][i].compare("ASN")==0) {
     702           0 :           DeltaG[i].push_back (-1.047/1000*std::pow(T,2)+0.6068*T-90.597);
     703             :         }
     704           0 :         if (AtomResidueName[1][i].compare("ASP")==0) {
     705           0 :           DeltaG[i].push_back (-0.1794/1000*std::pow(T,2)+0.1091*T-19.143);
     706             :         }
     707           0 :         if (AtomResidueName[1][i].compare("CYS")==0) {
     708           0 :           DeltaG[i].push_back (-3.09/1000*std::pow(T,2)+1.835*T-268.527);
     709             :         }
     710           0 :         if (AtomResidueName[1][i].compare("GLN")==0) {
     711           0 :           DeltaG[i].push_back (-2.23/1000*std::pow(T,2)+1.335*T-201.559);
     712             :         }
     713           0 :         if (AtomResidueName[1][i].compare("GLU")==0) {
     714           0 :           DeltaG[i].push_back (-1.511/1000*std::pow(T,2)+0.8904*T-133.543);
     715             :         }
     716           0 :         if (AtomResidueName[1][i].compare("GLY")==0) {
     717           0 :           DeltaG[i].push_back (0);
     718             :         }
     719           0 :         if (AtomResidueName[1][i].compare("HIS")==0) {
     720           0 :           DeltaG[i].push_back (-3.482/1000*std::pow(T,2)+2.084*T-315.398);
     721             :         }
     722           0 :         if (AtomResidueName[1][i].compare("ILE")==0) {
     723           0 :           DeltaG[i].push_back (-6.364/1000*std::pow(T,2)+3.8*T-564.825);
     724             :         }
     725           0 :         if (AtomResidueName[1][i].compare("LEU")==0) {
     726           0 :           DeltaG[i].push_back (-7.466/1000*std::pow(T,2)+4.417*T-651.483);
     727             :         }
     728           0 :         if (AtomResidueName[1][i].compare("LYS")==0) {
     729           0 :           DeltaG[i].push_back (-2.091/1000*std::pow(T,2)+1.2458*T-187.485);
     730             :         }
     731           0 :         if (AtomResidueName[1][i].compare("MET")==0) {
     732           0 :           DeltaG[i].push_back (-3.807/1000*std::pow(T,2)+2.272*T-339.242);
     733             :         }
     734           0 :         if (AtomResidueName[1][i].compare("PHE")==0) {
     735           0 :           DeltaG[i].push_back (-7.828/1000*std::pow(T,2)+4.644*T-687.134);
     736             :         }
     737           0 :         if (AtomResidueName[1][i].compare("PRO")==0) {
     738           0 :           DeltaG[i].push_back (-2.347/1000*std::pow(T,2)+1.411*T-214.211);
     739             :         }
     740           0 :         if (AtomResidueName[1][i].compare("SER")==0) {
     741           0 :           DeltaG[i].push_back (1.813/1000*std::pow(T,2)-1.05*T+150.289);
     742             :         }
     743           0 :         if (AtomResidueName[1][i].compare("THR")==0) {
     744           0 :           DeltaG[i].push_back (-2.64/1000*std::pow(T,2)+1.591*T-240.267);
     745             :         }
     746           0 :         if (AtomResidueName[1][i].compare("TRP")==0) {
     747           0 :           DeltaG[i].push_back (-11.66/1000*std::pow(T,2)+6.916*T-1024.284);
     748             :         }
     749           0 :         if (AtomResidueName[1][i].compare("TYR")==0) {
     750           0 :           DeltaG[i].push_back (-7.513/1000*std::pow(T,2)+4.478*T-666.484);
     751             :         }
     752           0 :         if (AtomResidueName[1][i].compare("VAL")==0) {
     753           0 :           DeltaG[i].push_back (-4.902/1000*std::pow(T,2)+2.921*T-433.013);
     754             :         }
     755           0 :         DeltaG[natoms].push_back (-0.6927/1000*std::pow(T,2)+0.4404*T-68.724);
     756             :       }
     757             :     }
     758             :   }
     759             : 
     760           0 :   Ti = T;
     761             : 
     762           0 :   if (firstStepFlag ==0) {
     763           0 :     if (approach!=2 && approach!=3) {
     764           0 :       cout << "Unknown approach " << approach << endl;
     765             :     }
     766           0 :     for(unsigned i=0; i<natoms; i++) {
     767           0 :       if (DeltaG[i].size()==0 ) {
     768           0 :         cout << "Delta G value for residue " << AtomResidueName[1][i] << " not found " << endl;
     769           0 :         error ("missing Delta G parameter\n");
     770             :       }
     771             :     }
     772             :   }
     773           0 : }
     774             : 
     775             : 
     776             : //calculates neighbor list
     777          24 : void SASA_HASEL::calcNlist() {
     778          24 :   if(!nopbc) {
     779          24 :     makeWhole();
     780             :   }
     781             : 
     782        2904 :   for(unsigned i = 0; i < natoms; i++) {
     783        2880 :     Nlist[i].clear();
     784             :   }
     785             : 
     786        2904 :   for(unsigned i = 0; i < natoms; i++) {
     787        2880 :     if (SASAparam[i].size()>0) {
     788      103680 :       for (unsigned j = 0; j < i; j++) {
     789      101952 :         if (SASAparam[j].size()>0) {
     790       61344 :           const Vector Delta_ij_vec = delta( getPosition(i), getPosition(j) );
     791       61344 :           double Delta_ij_mod = Delta_ij_vec.modulo()*10;
     792       61344 :           double overlapD = SASAparam[i][0]+SASAparam[j][0];
     793       61344 :           if (Delta_ij_mod < overlapD) {
     794       26748 :             Nlist.at(i).push_back (j);
     795       26748 :             Nlist.at(j).push_back (i);
     796             :           }
     797             :         }
     798             :       }
     799             :     }
     800             :   }
     801          24 : }
     802             : 
     803             : 
     804             : //calculates SASA according to Hasel et al., Tetrahedron Computer Methodology Vol. 1, No. 2, pp. 103-116, 1988
     805          24 : void SASA_HASEL::calculate() {
     806          24 :   if(!nopbc) {
     807          24 :     makeWhole();
     808             :   }
     809             : 
     810          24 :   if(getExchangeStep()) {
     811           0 :     nl_update = 0;
     812             :   }
     813          24 :   if (firstStepFlag ==0) {
     814           2 :     readPDB();
     815           2 :     readSASAparam();
     816             :   }
     817          24 :   if (nl_update == 0) {
     818          24 :     calcNlist();
     819             :   }
     820             : 
     821             : 
     822          24 :   auto* moldat = plumed.getActionSet().selectLatest<GenericMolInfo*>(this);
     823          24 :   if( ! moldat ) {
     824           0 :     error("Unable to find MOLINFO in input");
     825             :   }
     826             :   double Si, sasai, bij;
     827          24 :   double sasa = 0;
     828          24 :   vector<Vector> derivatives( natoms );
     829        2904 :   for(unsigned i = 0; i < natoms; i++) {
     830        2880 :     derivatives[i][0] = 0.;
     831        2880 :     derivatives[i][1] = 0.;
     832        2880 :     derivatives[i][2] = 0.;
     833             :   }
     834             : 
     835          24 :   Tensor virial;
     836          24 :   vector <double> ddij_di(3);
     837          24 :   vector <double> dbij_di(3);
     838          24 :   vector <double> dAijt_di(3);
     839             : 
     840          24 :   if( sasa_type==TOTAL ) {
     841        1452 :     for(unsigned i = 0; i < natoms; i++) {
     842        1440 :       if(SASAparam[i].size() > 0) {
     843         864 :         double ri = SASAparam[i][0];
     844         864 :         Si = 4*M_PI*ri*ri;
     845             :         sasai = 1.0;
     846             : 
     847        1728 :         vector <vector <double> > derTerm( Nlist[i].size(), vector <double>(3));
     848             : 
     849         864 :         dAijt_di[0] = 0;
     850         864 :         dAijt_di[1] = 0;
     851         864 :         dAijt_di[2] = 0;
     852         864 :         int NumRes_i = moldat->getResidueNumber(atoms[i]);
     853             : 
     854       27612 :         for (unsigned j = 0; j < Nlist[i].size(); j++) {
     855             :           double pij = 0.3516;
     856             : 
     857       26748 :           int NumRes_j = moldat->getResidueNumber(atoms[Nlist[i][j]]);
     858       26748 :           if (NumRes_i==NumRes_j) {
     859        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) {
     860             :               pij = 0.8875;
     861             :             }
     862             :           }
     863       26748 :           if ( abs(NumRes_i-NumRes_j) == 1 ) {
     864       10380 :             if ((AtomResidueName[0][i] == "N"  && AtomResidueName[0][Nlist[i][j]]== "CA") || (AtomResidueName[0][Nlist[i][j]] == "N"  && AtomResidueName[0][i]== "CA")) {
     865             :               pij = 0.8875;
     866             :             }
     867             :           }
     868             : 
     869       26748 :           const Vector d_ij_vec = delta( getPosition(i), getPosition(Nlist[i][j]) );
     870       26748 :           double d_ij = d_ij_vec.modulo()*10;
     871             : 
     872       26748 :           double rj = SASAparam[Nlist[i][j]][0];
     873       26748 :           bij = M_PI*ri*(ri+rj-d_ij)*(1+(rj-ri)/d_ij); //Angstrom2
     874             : 
     875       26748 :           sasai = sasai*(1-SASAparam[i][1]*pij*bij/Si); //nondimensional
     876             : 
     877       26748 :           ddij_di[0] = -10*(getPosition(Nlist[i][j])[0]-getPosition(i)[0])/d_ij; //nondimensional
     878       26748 :           ddij_di[1] = -10*(getPosition(Nlist[i][j])[1]-getPosition(i)[1])/d_ij;
     879       26748 :           ddij_di[2] = -10*(getPosition(Nlist[i][j])[2]-getPosition(i)[2])/d_ij;
     880             : 
     881       26748 :           dbij_di[0] = -M_PI*ri*ddij_di[0]*(1+(ri+rj)*(rj-ri)/(d_ij*d_ij)); //Angstrom
     882       26748 :           dbij_di[1] = -M_PI*ri*ddij_di[1]*(1+(ri+rj)*(rj-ri)/(d_ij*d_ij));
     883       26748 :           dbij_di[2] = -M_PI*ri*ddij_di[2]*(1+(ri+rj)*(rj-ri)/(d_ij*d_ij));
     884             : 
     885       26748 :           dAijt_di[0] += -1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[0]; //Angstrom-1
     886       26748 :           dAijt_di[1] += -1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[1];
     887       26748 :           dAijt_di[2] += -1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[2];
     888             : 
     889       26748 :           derTerm[j][0] = 1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[0]; //Angstrom-1
     890       26748 :           derTerm[j][1] = 1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[1];
     891       26748 :           derTerm[j][2] = 1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[2];
     892             : 
     893             :         }
     894             : 
     895         864 :         sasa += Si*sasai/100; //nm2
     896             : 
     897         864 :         derivatives[i][0] += Si*sasai/10*dAijt_di[0]; //nm
     898         864 :         derivatives[i][1] += Si*sasai/10*dAijt_di[1];
     899         864 :         derivatives[i][2] += Si*sasai/10*dAijt_di[2];
     900             : 
     901       27612 :         for (unsigned j = 0; j < Nlist[i].size(); j++) {
     902       26748 :           derivatives[Nlist[i][j]][0] += Si*sasai/10*derTerm[j][0]; //nm
     903       26748 :           derivatives[Nlist[i][j]][1] += Si*sasai/10*derTerm[j][1];
     904       26748 :           derivatives[Nlist[i][j]][2] += Si*sasai/10*derTerm[j][2];
     905             :         }
     906         864 :       }
     907             :     }
     908             :   }
     909             : 
     910             : 
     911          24 :   if( sasa_type==TRANSFER ) {
     912             : 
     913          12 :     if (firstStepFlag ==0) {
     914           1 :       readMaxSurf();
     915             :     }
     916             : 
     917          12 :     if (firstStepFlag ==0 && DeltaGValues != "absent") {
     918           1 :       readDeltaG();
     919             :     }
     920             : 
     921          12 :     if (DeltaGValues == "absent") {
     922           0 :       computeDeltaG();
     923             :     }
     924             : 
     925             : 
     926        1452 :     for(unsigned i = 0; i < natoms; i++) {
     927             : 
     928             : 
     929             : 
     930        1440 :       if(SASAparam[i].size() > 0) {
     931         864 :         double ri = SASAparam[i][0];
     932         864 :         Si = 4*M_PI*ri*ri;
     933             :         sasai = 1.0;
     934             : 
     935        1728 :         vector <vector <double> > derTerm( Nlist[i].size(), vector <double>(3));
     936             : 
     937         864 :         dAijt_di[0] = 0;
     938         864 :         dAijt_di[1] = 0;
     939         864 :         dAijt_di[2] = 0;
     940         864 :         int NumRes_i = moldat->getResidueNumber(atoms[i]);
     941             : 
     942       27612 :         for (unsigned j = 0; j < Nlist[i].size(); j++) {
     943             :           double pij = 0.3516;
     944             : 
     945       26748 :           int NumRes_j = moldat->getResidueNumber(atoms[Nlist[i][j]]);
     946       26748 :           if (NumRes_i==NumRes_j) {
     947        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) {
     948             :               pij = 0.8875;
     949             :             }
     950             :           }
     951       26748 :           if ( abs(NumRes_i-NumRes_j) == 1 ) {
     952       10380 :             if ((AtomResidueName[0][i] == "N"  && AtomResidueName[0][Nlist[i][j]]== "CA") || (AtomResidueName[0][Nlist[i][j]] == "N"  && AtomResidueName[0][i]== "CA")) {
     953             :               pij = 0.8875;
     954             :             }
     955             :           }
     956             : 
     957       26748 :           const Vector d_ij_vec = delta( getPosition(i), getPosition(Nlist[i][j]) );
     958       26748 :           double d_ij = d_ij_vec.modulo()*10;
     959             : 
     960       26748 :           double rj = SASAparam[Nlist[i][j]][0];
     961       26748 :           bij = M_PI*ri*(ri+rj-d_ij)*(1+(rj-ri)/d_ij); //Angstrom2
     962             : 
     963       26748 :           sasai = sasai*(1-SASAparam[i][1]*pij*bij/Si); //nondimensional
     964             : 
     965       26748 :           ddij_di[0] = -10*(getPosition(Nlist[i][j])[0]-getPosition(i)[0])/d_ij; //nondimensional
     966       26748 :           ddij_di[1] = -10*(getPosition(Nlist[i][j])[1]-getPosition(i)[1])/d_ij;
     967       26748 :           ddij_di[2] = -10*(getPosition(Nlist[i][j])[2]-getPosition(i)[2])/d_ij;
     968             : 
     969       26748 :           dbij_di[0] = -M_PI*ri*ddij_di[0]*(1+(ri+rj)*(rj-ri)/(d_ij*d_ij)); //Angstrom
     970       26748 :           dbij_di[1] = -M_PI*ri*ddij_di[1]*(1+(ri+rj)*(rj-ri)/(d_ij*d_ij));
     971       26748 :           dbij_di[2] = -M_PI*ri*ddij_di[2]*(1+(ri+rj)*(rj-ri)/(d_ij*d_ij));
     972             : 
     973       26748 :           dAijt_di[0] += -1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[0]; //Angstrom-1
     974       26748 :           dAijt_di[1] += -1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[1];
     975       26748 :           dAijt_di[2] += -1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[2];
     976             : 
     977       26748 :           derTerm[j][0] = 1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[0]; //Angstrom-1
     978       26748 :           derTerm[j][1] = 1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[1];
     979       26748 :           derTerm[j][2] = 1/(Si/(SASAparam[i][1]*pij)-bij)*dbij_di[2];
     980             : 
     981             :         }
     982             : 
     983        2880 :         if (AtomResidueName[0][i] == "N" || AtomResidueName[0][i] == "CA"  || AtomResidueName[0][i] == "C" || AtomResidueName[0][i] == "O" || AtomResidueName[0][i] == "H") {
     984             : 
     985         720 :           sasa += Si*sasai/MaxSurf[i][0]*DeltaG[natoms][0]; //kJ/mol
     986             : 
     987             : 
     988         720 :           derivatives[i][0] += Si*sasai*dAijt_di[0]/MaxSurf[i][0]*DeltaG[natoms][0]*10; //kJ/mol/nm
     989         720 :           derivatives[i][1] += Si*sasai*dAijt_di[1]/MaxSurf[i][0]*DeltaG[natoms][0]*10;
     990         720 :           derivatives[i][2] += Si*sasai*dAijt_di[2]/MaxSurf[i][0]*DeltaG[natoms][0]*10;
     991             :         }
     992             : 
     993        2880 :         if (AtomResidueName[0][i] != "N" && AtomResidueName[0][i] != "CA"  && AtomResidueName[0][i] != "C" && AtomResidueName[0][i] != "O" && AtomResidueName[0][i] != "H") {
     994         144 :           sasa += Si*sasai/MaxSurf[i][1]*DeltaG[i][0]; //kJ/mol
     995             : 
     996         144 :           derivatives[i][0] += Si*sasai*dAijt_di[0]/MaxSurf[i][1]*DeltaG[i][0]*10; //kJ/mol/nm
     997         144 :           derivatives[i][1] += Si*sasai*dAijt_di[1]/MaxSurf[i][1]*DeltaG[i][0]*10;
     998         144 :           derivatives[i][2] += Si*sasai*dAijt_di[2]/MaxSurf[i][1]*DeltaG[i][0]*10;
     999             :         }
    1000             : 
    1001             : 
    1002       27612 :         for (unsigned j = 0; j < Nlist[i].size(); j++) {
    1003       86883 :           if (AtomResidueName[0][i] == "N" || AtomResidueName[0][i] == "CA"  || AtomResidueName[0][i] == "C" || AtomResidueName[0][i] == "O" || AtomResidueName[0][i] == "H") {
    1004       22438 :             derivatives[Nlist[i][j]][0] += Si*sasai*10*derTerm[j][0]/MaxSurf[i][0]*DeltaG[natoms][0]; //kJ/mol/nm
    1005       22438 :             derivatives[Nlist[i][j]][1] += Si*sasai*10*derTerm[j][1]/MaxSurf[i][0]*DeltaG[natoms][0];
    1006       22438 :             derivatives[Nlist[i][j]][2] += Si*sasai*10*derTerm[j][2]/MaxSurf[i][0]*DeltaG[natoms][0];
    1007             :           }
    1008             : 
    1009       86883 :           if (AtomResidueName[0][i] != "N" && AtomResidueName[0][i] != "CA"  && AtomResidueName[0][i] != "C" && AtomResidueName[0][i] != "O" && AtomResidueName[0][i] != "H") {
    1010        4310 :             derivatives[Nlist[i][j]][0] += Si*sasai*10*derTerm[j][0]/MaxSurf[i][1]*DeltaG[i][0]; //kJ/mol/nm
    1011        4310 :             derivatives[Nlist[i][j]][1] += Si*sasai*10*derTerm[j][1]/MaxSurf[i][1]*DeltaG[i][0];
    1012        4310 :             derivatives[Nlist[i][j]][2] += Si*sasai*10*derTerm[j][2]/MaxSurf[i][1]*DeltaG[i][0];
    1013             :           }
    1014             :         }
    1015         864 :       }
    1016             :     }
    1017             :   }
    1018             : 
    1019             : 
    1020        2904 :   for(unsigned i=0; i<natoms; i++) {
    1021        2880 :     setAtomsDerivatives(i,derivatives[i]);
    1022        2880 :     virial -= Tensor(getPosition(i),derivatives[i]);
    1023             :   }
    1024             : 
    1025          24 :   setBoxDerivatives(virial);
    1026          24 :   setValue(sasa);
    1027          24 :   firstStepFlag = 1;
    1028          24 :   ++nl_update;
    1029          24 :   if (nl_update == stride) {
    1030          24 :     nl_update = 0;
    1031             :   }
    1032             : // setBoxDerivativesNoPbc();
    1033          24 : }
    1034             : 
    1035             : }//namespace sasa
    1036             : }//namespace PLMD

Generated by: LCOV version 1.16