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

Generated by: LCOV version 1.16