LCOV - code coverage report
Current view: top level - sasa - sasa_LCPO.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 544 660 82.4 %
Date: 2026-11-05 10:19:04 Functions: 10 13 76.9 %

          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_LCPO
      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 LCPO algorithm is used for the calculation (please, read and cite the first paper cited below). 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 the 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             : \verbatim
      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             : \endverbatim
      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)
      85             : is freely available [here](https://github.com/andrea-arsiccio/DeltaG-calculation). The script automatically outputs a DeltaG.dat file compatible with this SASA module.
      86             : 
      87             : 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.
      88             : 
      89             : 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.
      90             : 
      91             : In case you want to recover the old behavior you should use the NOPBC flag.
      92             : In that case you need to take care that atoms are in the correct periodic image.
      93             : 
      94             : The SASA may also be computed using the SASA_HASEL collective variable, which makes use of the algorithm described in the third paper cited below. SASA_HASEL is less accurate then SASA_LCPO, but the computation is faster.
      95             : 
      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_LCPO 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_LCPO 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 blow, and take into account the effect of temperature using approach 2 as described in the paper.
     118             : 
     119             : ```plumed
     120             : SASA_LCPO 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_LCPO : 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 > > LCPOparam;
     146             :   unsigned natoms;
     147             :   vector < vector < double > > MaxSurf;
     148             :   vector < vector < double > > DeltaG;
     149             :   vector < vector < int > > Nlist;
     150             : public:
     151             :   static void registerKeywords(Keywords& keys);
     152             :   explicit SASA_LCPO(const ActionOptions&);
     153             :   void readPDB();
     154             :   map<string, vector<double> > setupLCPOparam();
     155             :   void readLCPOparam();
     156             :   void calcNlist();
     157             :   map<string, vector<double> > setupMaxSurfMap();
     158             :   void readMaxSurf();
     159             :   void readDeltaG();
     160             :   void computeDeltaG();
     161             :   virtual void calculate();
     162             : };
     163             : 
     164             : PLUMED_REGISTER_ACTION(SASA_LCPO,"SASA_LCPO")
     165             : 
     166           6 : void SASA_LCPO::registerKeywords(Keywords& keys) {
     167           6 :   Colvar::registerKeywords(keys);
     168           6 :   keys.add("atoms","ATOMS","the group of atoms that you are calculating the SASA for");
     169           6 :   keys.add("compulsory","TYPE","TOTAL","The type of calculation you want to perform. Can be TOTAL or TRANSFER");
     170           6 :   keys.add("compulsory", "NL_STRIDE", "The frequency with which the neighbor list is updated.");
     171           6 :   keys.add("optional","DELTAGFILE","a file containing the free energy values for backbone and sidechains. 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");
     172           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");
     173          12 :   keys.setValueDescription("scalar","the solvent accessible surface area (SASA) of the molecule");
     174           6 :   keys.addDOI("10.1002/(SICI)1096-987X(19990130)20:2<217::AID-JCC4>3.0.CO;2-A");
     175           6 :   keys.addDOI("10.1021/acs.jpcb.1c01694");
     176           6 :   keys.addDOI("10.1021/acs.jpcb.2c00889");
     177           6 :   keys.addDOI("10.1021/acs.jpcb.1c04398");
     178           6 :   keys.addDOI("10.1016/0898-5529(88)90015-2");
     179           6 : }
     180             : 
     181             : 
     182           2 : SASA_LCPO::SASA_LCPO(const ActionOptions&ao):
     183             :   PLUMED_COLVAR_INIT(ao),
     184           2 :   nopbc(false),
     185           4 :   DeltaGValues("absent"),
     186           2 :   stride(10),
     187           2 :   nl_update(0),
     188           2 :   firstStepFlag(0),
     189           2 :   Ti(0) {
     190           2 :   rs = 0.14;
     191           2 :   parse("DELTAGFILE",DeltaGValues);
     192           2 :   parse("APPROACH", approach);
     193           4 :   parseAtomList("ATOMS",atoms);
     194           2 :   if(atoms.size()==0) {
     195           0 :     error("no atoms specified");
     196             :   }
     197             :   std::string Type;
     198           2 :   parse("TYPE",Type);
     199           2 :   parse("NL_STRIDE", stride);
     200           2 :   parseFlag("NOPBC",nopbc);
     201           2 :   checkRead();
     202             : 
     203           2 :   if(Type=="TOTAL") {
     204           1 :     sasa_type=TOTAL;
     205           1 :   } else if(Type=="TRANSFER") {
     206           1 :     sasa_type=TRANSFER;
     207             :   } else {
     208           0 :     error("Unknown SASA type");
     209             :   }
     210             : 
     211           2 :   switch(sasa_type) {
     212           1 :   case TOTAL:
     213           1 :     log.printf("  TOTAL SASA;");
     214             :     break;
     215           1 :   case TRANSFER:
     216           1 :     log.printf("  TRANSFER MODEL;");
     217             :     break;
     218             :   }
     219             : 
     220           2 :   log.printf("  atoms involved : ");
     221         242 :   for(unsigned i=0; i<atoms.size(); ++i) {
     222         240 :     if(i%25==0) {
     223          10 :       log<<"\n";
     224             :     }
     225         240 :     log.printf("%d ",atoms[i].serial());
     226             :   }
     227           2 :   log.printf("\n");
     228             : 
     229           2 :   if(nopbc) {
     230           0 :     log<<"  PBC will be ignored\n";
     231             :   } else {
     232           2 :     log<<"  broken molecules will be rebuilt assuming atoms are in the proper order\n";
     233             :   }
     234             : 
     235             : 
     236           2 :   addValueWithDerivatives();
     237           2 :   setNotPeriodic();
     238           2 :   requestAtoms(atoms);
     239             : 
     240           2 :   natoms = getNumberOfAtoms();
     241           2 :   AtomResidueName.resize(2);
     242           2 :   LCPOparam.resize(natoms);
     243           2 :   MaxSurf.resize(natoms);
     244           2 :   DeltaG.resize(natoms+1);
     245           2 :   Nlist.resize(natoms);
     246             : 
     247             : 
     248           2 : }
     249             : 
     250             : 
     251             : //splits strings into tokens. Used to read into LCPO parameters file and into reference pdb file
     252             : template <class Container>
     253           0 : void split(const std::string& str, Container& cont) {
     254           0 :   std::istringstream iss(str);
     255           0 :   std::copy(std::istream_iterator<std::string>(iss),
     256           0 :             std::istream_iterator<std::string>(),
     257             :             std::back_inserter(cont));
     258           0 : }
     259             : 
     260             : 
     261             : //reads input PDB file provided with MOLINFO, and assigns atom and residue names to each atom involved in the CV
     262             : 
     263           2 : void SASA_LCPO::readPDB() {
     264           2 :   auto* moldat = plumed.getActionSet().selectLatest<GenericMolInfo*>(this);
     265           2 :   if( ! moldat ) {
     266           0 :     error("Unable to find MOLINFO in input");
     267             :   }
     268           2 :   AtomResidueName[0].clear();
     269           2 :   AtomResidueName[1].clear();
     270             : 
     271         242 :   for(unsigned i=0; i<natoms; i++) {
     272         240 :     string Aname = moldat->getAtomName(atoms[i]);
     273         240 :     string Rname = moldat->getResidueName(atoms[i]);
     274         240 :     AtomResidueName[0].push_back (Aname);
     275         240 :     AtomResidueName[1].push_back (Rname);
     276             :   }
     277             : 
     278           2 : }
     279             : 
     280             : //LCPO parameters database
     281           2 : map<string, vector<double> > SASA_LCPO::setupLCPOparam() {
     282             :   map<string, vector<double> > lcpomap;
     283           2 :   lcpomap["ALA_N"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     284           2 :   lcpomap["ALA_CA"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     285           2 :   lcpomap["ALA_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     286           2 :   lcpomap["ALA_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     287           2 :   lcpomap["ALA_CB"] = { 1.7,  0.77887,  -0.28063,  -0.0012968,  0.00039328};
     288           2 :   lcpomap["ASP_N"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     289           2 :   lcpomap["ASP_CA"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     290           2 :   lcpomap["ASP_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     291           2 :   lcpomap["ASP_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     292           2 :   lcpomap["ASP_CB"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     293           2 :   lcpomap["ASP_CG"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     294           2 :   lcpomap["ASP_OD1"] = { 1.6,  0.77914,  -0.25262,  -0.0016056,  0.00035071};
     295           2 :   lcpomap["ASP_OD2"] = { 1.6,  0.77914,  -0.25262,  -0.0016056,  0.00035071};
     296           2 :   lcpomap["ASN_N"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     297           2 :   lcpomap["ASN_CA"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     298           2 :   lcpomap["ASN_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     299           2 :   lcpomap["ASN_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     300           2 :   lcpomap["ASN_CB"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     301           2 :   lcpomap["ASN_CG"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     302           2 :   lcpomap["ASN_OD1"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     303           2 :   lcpomap["ASN_ND2"] = { 1.65,  0.73511,  -0.22116,  -0.00089148,  0.0002523};
     304           2 :   lcpomap["ARG_N"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     305           2 :   lcpomap["ARG_CA"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     306           2 :   lcpomap["ARG_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     307           2 :   lcpomap["ARG_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     308           2 :   lcpomap["ARG_CB"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     309           2 :   lcpomap["ARG_CG"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     310           2 :   lcpomap["ARG_CD"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     311           2 :   lcpomap["ARG_NE"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     312           2 :   lcpomap["ARG_NH1"] = { 1.65,  0.73511,  -0.22116,  -0.00089148,  0.0002523};
     313           2 :   lcpomap["ARG_NH2"] = { 1.65,  0.73511,  -0.22116,  -0.00089148,  0.0002523};
     314           2 :   lcpomap["ARG_CZ"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     315           2 :   lcpomap["CYS_N"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     316           2 :   lcpomap["CYS_CA"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     317           2 :   lcpomap["CYS_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     318           2 :   lcpomap["CYS_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     319           2 :   lcpomap["CYS_CB"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     320           2 :   lcpomap["CYS_SG"] = { 1.9,  0.54581,  -0.19477,  -0.0012873,  0.00029247};
     321           2 :   lcpomap["GLU_N"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     322           2 :   lcpomap["GLU_CA"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     323           2 :   lcpomap["GLU_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     324           2 :   lcpomap["GLU_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     325           2 :   lcpomap["GLU_CB"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     326           2 :   lcpomap["GLU_CG"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     327           2 :   lcpomap["GLU_CD"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     328           2 :   lcpomap["GLU_OE1"] = { 1.6,  0.77914,  -0.25262,  -0.0016056,  0.00035071};
     329           2 :   lcpomap["GLU_OE2"] = { 1.6,  0.77914,  -0.25262,  -0.0016056,  0.00035071};
     330           2 :   lcpomap["GLN_N"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     331           2 :   lcpomap["GLN_CA"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     332           2 :   lcpomap["GLN_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     333           2 :   lcpomap["GLN_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     334           2 :   lcpomap["GLN_CB"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     335           2 :   lcpomap["GLN_CG"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     336           2 :   lcpomap["GLN_CD"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     337           2 :   lcpomap["GLN_OE1"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     338           2 :   lcpomap["GLN_NE2"] = { 1.65,  0.73511,  -0.22116,  -0.00089148,  0.0002523};
     339           2 :   lcpomap["GLY_N"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     340           2 :   lcpomap["GLY_CA"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     341           2 :   lcpomap["GLY_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     342           2 :   lcpomap["GLY_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     343           2 :   lcpomap["HIS_N"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     344           2 :   lcpomap["HIS_CA"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     345           2 :   lcpomap["HIS_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     346           2 :   lcpomap["HIS_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     347           2 :   lcpomap["HIS_CB"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     348           2 :   lcpomap["HIS_CG"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     349           2 :   lcpomap["HIS_ND1"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     350           2 :   lcpomap["HIS_CE1"] = { 1.7,  0.51245,  -0.15966,  -0.00019781,  0.00016392};
     351           2 :   lcpomap["HIS_NE2"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     352           2 :   lcpomap["HIS_CD2"] = { 1.7,  0.51245,  -0.15966,  -0.00019781,  0.00016392};
     353           2 :   lcpomap["ILE_N"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     354           2 :   lcpomap["ILE_CA"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     355           2 :   lcpomap["ILE_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     356           2 :   lcpomap["ILE_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     357           2 :   lcpomap["ILE_CB"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     358           2 :   lcpomap["ILE_CG2"] = { 1.7,  0.77887,  -0.28063,  -0.0012968,  0.00039328};
     359           2 :   lcpomap["ILE_CG1"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     360           2 :   lcpomap["ILE_CD1"] = { 1.7,  0.77887,  -0.28063,  -0.0012968,  0.00039328};
     361           2 :   lcpomap["LEU_N"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     362           2 :   lcpomap["LEU_CA"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     363           2 :   lcpomap["LEU_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     364           2 :   lcpomap["LEU_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     365           2 :   lcpomap["LEU_CB"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     366           2 :   lcpomap["LEU_CG"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     367           2 :   lcpomap["LEU_CD1"] = { 1.7,  0.77887,  -0.28063,  -0.0012968,  0.00039328};
     368           2 :   lcpomap["LEU_CD2"] = { 1.7,  0.77887,  -0.28063,  -0.0012968,  0.00039328};
     369           2 :   lcpomap["LYS_N"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     370           2 :   lcpomap["LYS_CA"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     371           2 :   lcpomap["LYS_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     372           2 :   lcpomap["LYS_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     373           2 :   lcpomap["LYS_CB"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     374           2 :   lcpomap["LYS_CG"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     375           2 :   lcpomap["LYS_CD"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     376           2 :   lcpomap["LYS_CE"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     377           2 :   lcpomap["LYS_NZ"] = { 1.65,  0.73511,  -0.22116,  -0.00089148,  0.0002523};
     378           2 :   lcpomap["MET_N"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     379           2 :   lcpomap["MET_CA"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     380           2 :   lcpomap["MET_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     381           2 :   lcpomap["MET_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     382           2 :   lcpomap["MET_CB"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     383           2 :   lcpomap["MET_CG"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     384           2 :   lcpomap["MET_SD"] = { 1.9,  0.54581,  -0.19477,  -0.0012873,  0.00029247};
     385           2 :   lcpomap["MET_CE"] = { 1.7,  0.77887,  -0.28063,  -0.0012968,  0.00039328};
     386           2 :   lcpomap["PHE_N"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     387           2 :   lcpomap["PHE_CA"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     388           2 :   lcpomap["PHE_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     389           2 :   lcpomap["PHE_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     390           2 :   lcpomap["PHE_CB"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     391           2 :   lcpomap["PHE_CG"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     392           2 :   lcpomap["PHE_CD1"] = { 1.7,  0.51245,  -0.15966,  -0.00019781,  0.00016392};
     393           2 :   lcpomap["PHE_CE1"] = { 1.7,  0.51245,  -0.15966,  -0.00019781,  0.00016392};
     394           2 :   lcpomap["PHE_CZ"] = { 1.7,  0.51245,  -0.15966,  -0.00019781,  0.00016392};
     395           2 :   lcpomap["PHE_CE2"] = { 1.7,  0.51245,  -0.15966,  -0.00019781,  0.00016392};
     396           2 :   lcpomap["PHE_CD2"] = { 1.7,  0.51245,  -0.15966,  -0.00019781,  0.00016392};
     397           2 :   lcpomap["PRO_N"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     398           2 :   lcpomap["PRO_CA"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     399           2 :   lcpomap["PRO_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     400           2 :   lcpomap["PRO_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     401           2 :   lcpomap["PRO_CB"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     402           2 :   lcpomap["PRO_CG"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     403           2 :   lcpomap["PRO_CD"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     404           2 :   lcpomap["SER_N"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     405           2 :   lcpomap["SER_CA"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     406           2 :   lcpomap["SER_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     407           2 :   lcpomap["SER_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     408           2 :   lcpomap["SER_CB"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     409           2 :   lcpomap["SER_OG"] = { 1.6,  0.77914,  -0.25262,  -0.0016056,  0.00035071};
     410           2 :   lcpomap["THR_N"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     411           2 :   lcpomap["THR_CA"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     412           2 :   lcpomap["THR_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     413           2 :   lcpomap["THR_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     414           2 :   lcpomap["THR_CB"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     415           2 :   lcpomap["THR_CG2"] = { 1.7,  0.77887,  -0.28063,  -0.0012968,  0.00039328};
     416           2 :   lcpomap["THR_OG1"] = { 1.6,  0.77914,  -0.25262,  -0.0016056,  0.00035071};
     417           2 :   lcpomap["TRP_N"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     418           2 :   lcpomap["TRP_CA"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     419           2 :   lcpomap["TRP_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     420           2 :   lcpomap["TRP_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     421           2 :   lcpomap["TRP_CB"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     422           2 :   lcpomap["TRP_CG"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     423           2 :   lcpomap["TRP_CD1"] = { 1.7,  0.51245,  -0.15966,  -0.00019781,  0.00016392};
     424           2 :   lcpomap["TRP_NE1"] = { 1.65,  0.41102,  -0.12254,  -7.5448e-05,  0.00011804};
     425           2 :   lcpomap["TRP_CE2"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     426           2 :   lcpomap["TRP_CZ2"] = { 1.7,  0.51245,  -0.15966,  -0.00019781,  0.00016392};
     427           2 :   lcpomap["TRP_CH2"] = { 1.7,  0.51245,  -0.15966,  -0.00019781,  0.00016392};
     428           2 :   lcpomap["TRP_CZ3"] = { 1.7,  0.51245,  -0.15966,  -0.00019781,  0.00016392};
     429           2 :   lcpomap["TRP_CE3"] = { 1.7,  0.51245,  -0.15966,  -0.00019781,  0.00016392};
     430           2 :   lcpomap["TRP_CD2"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     431           2 :   lcpomap["TYR_N"] = { 1.65,  0.062577,  -0.017874,  -8.312e-05,  1.9849e-05};
     432           2 :   lcpomap["TYR_CA"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     433           2 :   lcpomap["TYR_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     434           2 :   lcpomap["TYR_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     435           2 :   lcpomap["TYR_CB"] = { 1.7,  0.56482,  -0.19608,  -0.0010219,  0.0002658};
     436           2 :   lcpomap["TYR_CG"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     437           2 :   lcpomap["TYR_CD1"] = { 1.7,  0.51245,  -0.15966,  -0.00019781,  0.00016392};
     438           2 :   lcpomap["TYR_CE1"] = { 1.7,  0.51245,  -0.15966,  -0.00019781,  0.00016392};
     439           2 :   lcpomap["TYR_CZ"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     440           2 :   lcpomap["TYR_OH"] = { 1.6,  0.77914,  -0.25262,  -0.0016056,  0.00035071};
     441           2 :   lcpomap["TYR_CE2"] = { 1.7,  0.51245,  -0.15966,  -0.00019781,  0.00016392};
     442           2 :   lcpomap["TYR_CD2"] = { 1.7,  0.51245,  -0.15966,  -0.00019781,  0.00016392};
     443           2 :   lcpomap["VAL_N"] = { 1.65,  0.062577,  -0.017874,  -8.312e-05,  1.9849e-05};
     444           2 :   lcpomap["VAL_CA"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     445           2 :   lcpomap["VAL_C"] = { 1.7,  0.070344,  -0.019015,  -2.2009e-05,  1.6875e-05};
     446           2 :   lcpomap["VAL_O"] = { 1.6,  0.68563,  -0.1868,  -0.00135573,  0.00023743};
     447           2 :   lcpomap["VAL_CB"] = { 1.7,  0.23348,  -0.072627,  -0.00020079,  7.967e-05};
     448           2 :   lcpomap["VAL_CG1"] = { 1.7,  0.77887,  -0.28063,  -0.0012968,  0.00039328};
     449           2 :   lcpomap["VAL_CG2"] = { 1.7,  0.77887,  -0.28063,  -0.0012968,  0.00039328};
     450           2 :   return lcpomap;
     451             : }
     452             : 
     453             : //assigns LCPO parameters to each atom reading from database
     454           2 : void SASA_LCPO::readLCPOparam() {
     455             : 
     456         242 :   for(unsigned i=0; i<natoms; i++) {
     457         240 :     LCPOparam[i].clear();
     458             :   }
     459             : 
     460             :   map<string, vector<double> > lcpomap;
     461           2 :   lcpomap = setupLCPOparam();
     462           2 :   vector<double> LCPOparamVector;
     463             :   string identifier;
     464         242 :   for(unsigned i=0; i<natoms; i++) {
     465         240 :     if ((AtomResidueName[0][i][0]=='O') || (AtomResidueName[0][i][0]=='N') || (AtomResidueName[0][i][0]=='C') || (AtomResidueName[0][i][0]=='S')) {
     466         120 :       identifier = AtomResidueName[1][i]+"_"+AtomResidueName[0][i];
     467         120 :       LCPOparamVector = lcpomap.at(identifier);
     468         120 :       LCPOparam[i].push_back (LCPOparamVector[0]+rs*10);
     469         120 :       LCPOparam[i].push_back (LCPOparamVector[1]);
     470         120 :       LCPOparam[i].push_back (LCPOparamVector[2]);
     471         120 :       LCPOparam[i].push_back (LCPOparamVector[3]);
     472         120 :       LCPOparam[i].push_back (LCPOparamVector[4]);
     473             :     }
     474             :   }
     475             : 
     476             : 
     477         242 :   for(unsigned i=0; i<natoms; i++) {
     478         240 :     if (LCPOparam[i].size()==0 ) {
     479         120 :       if ((AtomResidueName[0][i][0]=='O') || (AtomResidueName[0][i][0]=='N') || (AtomResidueName[0][i][0]=='C') || (AtomResidueName[0][i][0]=='S')) {
     480           0 :         cout << "Could not find LCPO parameters for atom " << AtomResidueName[0][i] << " of residue " << AtomResidueName[1][i] << endl;
     481           0 :         error ("missing LCPO parameters\n");
     482             :       }
     483             :     }
     484             :   }
     485             : 
     486           2 :   if (AtomResidueName[0][0] == "N") {
     487           2 :     LCPOparam[0][1] = 7.3511e-01;
     488           2 :     LCPOparam[0][2] = -2.2116e-01;
     489           2 :     LCPOparam[0][3] = -8.9148e-04;
     490           2 :     LCPOparam[0][4] = 2.5230e-04;
     491             :   }
     492             : 
     493           2 :   if (AtomResidueName[0][natoms-1] == "O") {
     494           2 :     LCPOparam[natoms-1][1] = 8.8857e-01;
     495           2 :     LCPOparam[natoms-1][2] = -3.3421e-01;
     496           2 :     LCPOparam[natoms-1][3] = -1.8683e-03;
     497           2 :     LCPOparam[natoms-1][4] = 4.9372e-04;
     498             :   }
     499           4 : }
     500             : 
     501             : 
     502             : //Max Surf values, used only if TYPE=TRANSFER
     503           1 : map<string, vector<double> > SASA_LCPO::setupMaxSurfMap() {
     504             :   // Max Surface Area for backbone and sidechain, in nm2
     505             :   map<string, vector<double> > valuemap;
     506           1 :   valuemap ["ALA"]= {0.671446,0.420263,};
     507           1 :   valuemap ["ARG"]= {0.578582,1.95454,};
     508           1 :   valuemap ["ASN"]= {0.559411,1.07102,};
     509           1 :   valuemap ["ASP"]= {0.558363,1.03971,};
     510           1 :   valuemap ["CYS"]= {0.609271,0.657612,};
     511           1 :   valuemap ["GLN"]= {0.565651,1.433031,};
     512           1 :   valuemap ["GLU"]= {0.572399,1.41848,};
     513           1 :   valuemap ["GLY"]= {0.861439,0,};
     514           1 :   valuemap ["HIS"]= {0.559929,1.143827,};
     515           1 :   valuemap ["ILE"]= {0.553491,1.25334,};
     516           1 :   valuemap ["LEU"]= {0.570103,1.260459,};
     517           1 :   valuemap ["LYS"]= {0.580304,1.687487,};
     518           1 :   valuemap ["MET"]= {0.5856,1.498954,};
     519           1 :   valuemap ["PHE"]= {0.54155,1.394861,};
     520           1 :   valuemap ["PRO"]= {0.456048,0.849461,};
     521           1 :   valuemap ["SER"]= {0.59074,0.714538,};
     522           1 :   valuemap ["THR"]= {0.559116,0.951644,};
     523           1 :   valuemap ["TRP"]= {0.55536,1.59324,};
     524           1 :   valuemap ["TYR"]= {0.451171,1.566918,};
     525           1 :   valuemap ["VAL"]= {0.454809,0.928685,};
     526           1 :   return valuemap;
     527             : }
     528             : 
     529             : 
     530             : 
     531             : //reads maximum surface values per residue type and assigns values to each atom, only used if sasa_type = TRANSFER
     532             : 
     533           1 : void SASA_LCPO::readMaxSurf() {
     534             :   map<string, vector<double> > valuemap;
     535           1 :   valuemap = setupMaxSurfMap();
     536           1 :   vector<double> MaxSurfVector;
     537             : 
     538         121 :   for(unsigned i=0; i<natoms; i++) {
     539         120 :     MaxSurf[i].clear();
     540         120 :     MaxSurfVector = valuemap.at(AtomResidueName[1][i]);
     541         120 :     MaxSurf[i].push_back (MaxSurfVector[0]*100);
     542         120 :     MaxSurf[i].push_back (MaxSurfVector[1]*100);
     543             :   }
     544           2 : }
     545             : 
     546             : //reads file with free energy values for sidechains and for the backbone, and assigns values to each atom. Only used if sasa_type = TRANSFER
     547             : 
     548           1 : void SASA_LCPO::readDeltaG() {
     549             : 
     550         121 :   for(unsigned i=0; i<natoms; i++) {
     551         120 :     DeltaG[i].clear();
     552             :   }
     553             : 
     554             :   string DeltaGline;
     555           1 :   fstream DeltaGFile;
     556           1 :   DeltaGFile.open(DeltaGValues);
     557           1 :   if (DeltaGFile) {
     558             :     int backboneflag = 0;
     559          23 :     while(getline(DeltaGFile, DeltaGline)) {
     560          22 :       if(!DeltaGline.empty()) {
     561          21 :         std::vector<std::string> DeltaGtoken;
     562          21 :         split(DeltaGline, DeltaGtoken);
     563        2541 :         for(unsigned i=0; i<natoms; i++) {
     564        2520 :           if (DeltaGtoken[0].compare(AtomResidueName[1][i])==0 ) {
     565         120 :             DeltaG[i].push_back (std::atof(DeltaGtoken[1].c_str()));
     566             :           }
     567             :         }
     568          21 :         if (DeltaGtoken[0].compare("BACKBONE")==0 ) {
     569             :           backboneflag = 1;
     570           1 :           DeltaG[natoms].push_back (std::atof(DeltaGtoken[1].c_str()));
     571             :         }
     572          21 :       }
     573             :     }
     574           1 :     if ( backboneflag == 0) {
     575           0 :       error("Cannot find backbone value in Delta G parameters file\n");
     576             :     }
     577             :   } else {
     578           0 :     error("Cannot open DeltaG file");
     579             :   }
     580             : 
     581         121 :   for(unsigned i=0; i<natoms; i++) {
     582         120 :     if (DeltaG[i].size()==0 ) {
     583           0 :       cout << "Delta G value for residue " << AtomResidueName[1][i] << " not found " << endl;
     584           0 :       error ("missing Delta G parameter\n");
     585             :     }
     586             :   }
     587             : 
     588           2 : }
     589             : 
     590             : //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.
     591             : 
     592           0 : void SASA_LCPO::computeDeltaG() {
     593             : 
     594           0 :   for(unsigned i=0; i<natoms; i++) {
     595           0 :     DeltaG[i].clear();
     596             :   }
     597             : 
     598             :   double T;
     599           0 :   T = getkBT()/getKBoltzmann();
     600             : 
     601           0 :   if (T != Ti) {
     602           0 :     for(unsigned i=0; i<natoms; i++) {
     603           0 :       if (approach==2) {
     604           0 :         if (AtomResidueName[1][i].compare("ALA")==0) {
     605           0 :           DeltaG[i].push_back (-2.995/1000*std::pow(T,2)+1.808*T-272.895);
     606             :         }
     607           0 :         if (AtomResidueName[1][i].compare("ARG")==0) {
     608           0 :           DeltaG[i].push_back (-3.182/1000*std::pow(T,2)+1.894*T-282.032);
     609             :         }
     610           0 :         if (AtomResidueName[1][i].compare("ASN")==0) {
     611           0 :           DeltaG[i].push_back (-1.047/1000*std::pow(T,2)+0.6068*T-87.846);
     612             :         }
     613           0 :         if (AtomResidueName[1][i].compare("ASP")==0) {
     614           0 :           DeltaG[i].push_back (-0.1794/1000*std::pow(T,2)+0.1091*T-16.526);
     615             :         }
     616           0 :         if (AtomResidueName[1][i].compare("CYS")==0) {
     617           0 :           DeltaG[i].push_back (-3.09/1000*std::pow(T,2)+1.835*T-272.26);
     618             :         }
     619           0 :         if (AtomResidueName[1][i].compare("GLN")==0) {
     620           0 :           DeltaG[i].push_back (-2.23/1000*std::pow(T,2)+1.335*T-199.707);
     621             :         }
     622           0 :         if (AtomResidueName[1][i].compare("GLU")==0) {
     623           0 :           DeltaG[i].push_back (-1.511/1000*std::pow(T,2)+0.8904*T-131.168);
     624             :         }
     625           0 :         if (AtomResidueName[1][i].compare("GLY")==0) {
     626           0 :           DeltaG[i].push_back (0);
     627             :         }
     628           0 :         if (AtomResidueName[1][i].compare("HIS")==0) {
     629           0 :           DeltaG[i].push_back (-3.482/1000*std::pow(T,2)+2.084*T-311.694);
     630             :         }
     631           0 :         if (AtomResidueName[1][i].compare("ILE")==0) {
     632           0 :           DeltaG[i].push_back (-6.364/1000*std::pow(T,2)+3.8*T-567.444);
     633             :         }
     634           0 :         if (AtomResidueName[1][i].compare("LEU")==0) {
     635           0 :           DeltaG[i].push_back (-7.466/1000*std::pow(T,2)+4.417*T-653.394);
     636             :         }
     637           0 :         if (AtomResidueName[1][i].compare("LYS")==0) {
     638           0 :           DeltaG[i].push_back (-2.091/1000*std::pow(T,2)+1.2458*T-185.549);
     639             :         }
     640           0 :         if (AtomResidueName[1][i].compare("MET")==0) {
     641           0 :           DeltaG[i].push_back (-3.807/1000*std::pow(T,2)+2.272*T-339.007);
     642             :         }
     643           0 :         if (AtomResidueName[1][i].compare("PHE")==0) {
     644           0 :           DeltaG[i].push_back (-7.828/1000*std::pow(T,2)+4.644*T-688.874);
     645             :         }
     646           0 :         if (AtomResidueName[1][i].compare("PRO")==0) {
     647           0 :           DeltaG[i].push_back (-2.347/1000*std::pow(T,2)+1.411*T-212.059);
     648             :         }
     649           0 :         if (AtomResidueName[1][i].compare("SER")==0) {
     650           0 :           DeltaG[i].push_back (1.813/1000*std::pow(T,2)-1.05*T+151.957);
     651             :         }
     652           0 :         if (AtomResidueName[1][i].compare("THR")==0) {
     653           0 :           DeltaG[i].push_back (-2.64/1000*std::pow(T,2)+1.591*T-239.516);
     654             :         }
     655           0 :         if (AtomResidueName[1][i].compare("TRP")==0) {
     656           0 :           DeltaG[i].push_back (-11.66/1000*std::pow(T,2)+6.916*T-1025.293);
     657             :         }
     658           0 :         if (AtomResidueName[1][i].compare("TYR")==0) {
     659           0 :           DeltaG[i].push_back (-7.513/1000*std::pow(T,2)+4.478*T-667.261);
     660             :         }
     661           0 :         if (AtomResidueName[1][i].compare("VAL")==0) {
     662           0 :           DeltaG[i].push_back (-4.902/1000*std::pow(T,2)+2.921*T-435.309);
     663             :         }
     664           0 :         DeltaG[natoms].push_back (-0.6962/1000*std::pow(T,2)+0.4426*T-70.015);
     665             :       }
     666           0 :       if (approach==3) {
     667           0 :         if (AtomResidueName[1][i].compare("ALA")==0) {
     668           0 :           DeltaG[i].push_back (-2.995/1000*std::pow(T,2)+1.808*T-272.105);
     669             :         }
     670           0 :         if (AtomResidueName[1][i].compare("ARG")==0) {
     671           0 :           DeltaG[i].push_back (-3.182/1000*std::pow(T,2)+1.894*T-284.086);
     672             :         }
     673           0 :         if (AtomResidueName[1][i].compare("ASN")==0) {
     674           0 :           DeltaG[i].push_back (-1.047/1000*std::pow(T,2)+0.6068*T-90.597);
     675             :         }
     676           0 :         if (AtomResidueName[1][i].compare("ASP")==0) {
     677           0 :           DeltaG[i].push_back (-0.1794/1000*std::pow(T,2)+0.1091*T-19.143);
     678             :         }
     679           0 :         if (AtomResidueName[1][i].compare("CYS")==0) {
     680           0 :           DeltaG[i].push_back (-3.09/1000*std::pow(T,2)+1.835*T-268.527);
     681             :         }
     682           0 :         if (AtomResidueName[1][i].compare("GLN")==0) {
     683           0 :           DeltaG[i].push_back (-2.23/1000*std::pow(T,2)+1.335*T-201.559);
     684             :         }
     685           0 :         if (AtomResidueName[1][i].compare("GLU")==0) {
     686           0 :           DeltaG[i].push_back (-1.511/1000*std::pow(T,2)+0.8904*T-133.543);
     687             :         }
     688           0 :         if (AtomResidueName[1][i].compare("GLY")==0) {
     689           0 :           DeltaG[i].push_back (0);
     690             :         }
     691           0 :         if (AtomResidueName[1][i].compare("HIS")==0) {
     692           0 :           DeltaG[i].push_back (-3.482/1000*std::pow(T,2)+2.084*T-315.398);
     693             :         }
     694           0 :         if (AtomResidueName[1][i].compare("ILE")==0) {
     695           0 :           DeltaG[i].push_back (-6.364/1000*std::pow(T,2)+3.8*T-564.825);
     696             :         }
     697           0 :         if (AtomResidueName[1][i].compare("LEU")==0) {
     698           0 :           DeltaG[i].push_back (-7.466/1000*std::pow(T,2)+4.417*T-651.483);
     699             :         }
     700           0 :         if (AtomResidueName[1][i].compare("LYS")==0) {
     701           0 :           DeltaG[i].push_back (-2.091/1000*std::pow(T,2)+1.2458*T-187.485);
     702             :         }
     703           0 :         if (AtomResidueName[1][i].compare("MET")==0) {
     704           0 :           DeltaG[i].push_back (-3.807/1000*std::pow(T,2)+2.272*T-339.242);
     705             :         }
     706           0 :         if (AtomResidueName[1][i].compare("PHE")==0) {
     707           0 :           DeltaG[i].push_back (-7.828/1000*std::pow(T,2)+4.644*T-687.134);
     708             :         }
     709           0 :         if (AtomResidueName[1][i].compare("PRO")==0) {
     710           0 :           DeltaG[i].push_back (-2.347/1000*std::pow(T,2)+1.411*T-214.211);
     711             :         }
     712           0 :         if (AtomResidueName[1][i].compare("SER")==0) {
     713           0 :           DeltaG[i].push_back (1.813/1000*std::pow(T,2)-1.05*T+150.289);
     714             :         }
     715           0 :         if (AtomResidueName[1][i].compare("THR")==0) {
     716           0 :           DeltaG[i].push_back (-2.64/1000*std::pow(T,2)+1.591*T-240.267);
     717             :         }
     718           0 :         if (AtomResidueName[1][i].compare("TRP")==0) {
     719           0 :           DeltaG[i].push_back (-11.66/1000*std::pow(T,2)+6.916*T-1024.284);
     720             :         }
     721           0 :         if (AtomResidueName[1][i].compare("TYR")==0) {
     722           0 :           DeltaG[i].push_back (-7.513/1000*std::pow(T,2)+4.478*T-666.484);
     723             :         }
     724           0 :         if (AtomResidueName[1][i].compare("VAL")==0) {
     725           0 :           DeltaG[i].push_back (-4.902/1000*std::pow(T,2)+2.921*T-433.013);
     726             :         }
     727           0 :         DeltaG[natoms].push_back (-0.6927/1000*std::pow(T,2)+0.4404*T-68.724);
     728             :       }
     729             :     }
     730             :   }
     731             : 
     732           0 :   Ti = T;
     733             : 
     734           0 :   if (firstStepFlag ==0) {
     735           0 :     if (approach!=2 && approach!=3) {
     736           0 :       cout << "Unknown approach " << approach << endl;
     737             :     }
     738           0 :     for(unsigned i=0; i<natoms; i++) {
     739           0 :       if (DeltaG[i].size()==0 ) {
     740           0 :         cout << "Delta G value for residue " << AtomResidueName[1][i] << " not found " << endl;
     741           0 :         error ("missing Delta G parameter\n");
     742             :       }
     743             :     }
     744             :   }
     745           0 : }
     746             : 
     747             : 
     748             : //calculates neighbor list
     749          24 : void SASA_LCPO::calcNlist() {
     750          24 :   if(!nopbc) {
     751          24 :     makeWhole();
     752             :   }
     753             : 
     754        2904 :   for(unsigned i = 0; i < natoms; i++) {
     755        2880 :     Nlist[i].clear();
     756             :   }
     757             : 
     758        2904 :   for(unsigned i = 0; i < natoms; i++) {
     759        2880 :     if (LCPOparam[i].size()>0) {
     760       87264 :       for (unsigned j = 0; j < i; j++) {
     761       85824 :         if (LCPOparam[j].size()>0) {
     762       42480 :           const Vector Delta_ij_vec = delta( getPosition(i), getPosition(j) );
     763       42480 :           double Delta_ij_mod = Delta_ij_vec.modulo()*10;
     764       42480 :           double overlapD = LCPOparam[i][0]+LCPOparam[j][0];
     765       42480 :           if (Delta_ij_mod < overlapD) {
     766       19030 :             Nlist.at(i).push_back (j);
     767       19030 :             Nlist.at(j).push_back (i);
     768             :           }
     769             :         }
     770             :       }
     771             :     }
     772             :   }
     773          24 : }
     774             : 
     775             : 
     776             : //calculates SASA according to LCPO algorithm
     777          24 : void SASA_LCPO::calculate() {
     778          24 :   if(!nopbc) {
     779          24 :     makeWhole();
     780             :   }
     781             : 
     782          24 :   if(getExchangeStep()) {
     783           0 :     nl_update = 0;
     784             :   }
     785          24 :   if (firstStepFlag ==0) {
     786           2 :     readPDB();
     787           2 :     readLCPOparam();
     788             :   }
     789          24 :   if (nl_update == 0) {
     790          24 :     calcNlist();
     791             :   }
     792             : 
     793             : 
     794             : 
     795             :   double S1, Aij, Ajk, Aijk, Aijt, Ajkt, Aikt;
     796             :   double dAdd;
     797          24 :   double sasa = 0;
     798          24 :   vector<Vector> derivatives( natoms );
     799          24 :   Tensor virial;
     800          24 :   vector <double> dAijdc_2t(3);
     801          24 :   vector <double> dSASA_2_neigh_dc(3);
     802          24 :   vector <double> ddij_di(3);
     803          24 :   vector <double> ddik_di(3);
     804             : 
     805          24 :   if( sasa_type==TOTAL ) {
     806        1452 :     for(unsigned i = 0; i < natoms; i++) {
     807        1440 :       derivatives[i][0] = 0.;
     808        1440 :       derivatives[i][1] = 0.;
     809        1440 :       derivatives[i][2] = 0.;
     810        1440 :       if ( LCPOparam[i].size()>1) {
     811         720 :         if (LCPOparam[i][1]>0.0) {
     812             :           Aij = 0.0;
     813             :           Aijk = 0.0;
     814             :           Ajk = 0.0;
     815         720 :           double ri = LCPOparam[i][0];
     816         720 :           S1 = 4*M_PI*ri*ri;
     817         720 :           vector <double> dAijdc_2(3, 0);
     818         720 :           vector <double> dAijdc_4(3, 0);
     819             : 
     820             : 
     821       19750 :           for (unsigned j = 0; j < Nlist[i].size(); j++) {
     822       19030 :             const Vector d_ij_vec = delta( getPosition(i), getPosition(Nlist[i][j]) );
     823       19030 :             double d_ij = d_ij_vec.modulo()*10;
     824             : 
     825       19030 :             double rj = LCPOparam[Nlist[i][j]][0];
     826       19030 :             Aijt = (2*M_PI*ri*(ri-d_ij/2-((ri*ri-rj*rj)/(2*d_ij))));
     827       19030 :             double sji = (2*M_PI*rj*(rj-d_ij/2+((ri*ri-rj*rj)/(2*d_ij))));
     828             : 
     829       19030 :             dAdd = M_PI*rj*(-(ri*ri-rj*rj)/(d_ij*d_ij)-1);
     830             : 
     831       19030 :             ddij_di[0] = -10*(getPosition(Nlist[i][j])[0]-getPosition(i)[0])/d_ij;
     832       19030 :             ddij_di[1] = -10*(getPosition(Nlist[i][j])[1]-getPosition(i)[1])/d_ij;
     833       19030 :             ddij_di[2] = -10*(getPosition(Nlist[i][j])[2]-getPosition(i)[2])/d_ij;
     834             : 
     835             :             Ajkt = 0.0;
     836             :             Aikt = 0.0;
     837             : 
     838       19030 :             vector <double> dSASA_3_neigh_dc(3, 0.0);
     839       19030 :             vector <double> dSASA_4_neigh_dc(3, 0.0);
     840       19030 :             vector <double> dSASA_3_neigh_dc2(3, 0.0);
     841       19030 :             vector <double> dSASA_4_neigh_dc2(3, 0.0);
     842             : 
     843       19030 :             dSASA_2_neigh_dc[0] = dAdd * ddij_di[0];
     844       19030 :             dSASA_2_neigh_dc[1] = dAdd * ddij_di[1];
     845       19030 :             dSASA_2_neigh_dc[2] = dAdd * ddij_di[2];
     846             : 
     847       19030 :             dAdd = M_PI*ri*((ri*ri-rj*rj)/(d_ij*d_ij)-1);
     848             : 
     849             : 
     850       19030 :             dAijdc_2t[0] = dAdd * ddij_di[0];
     851       19030 :             dAijdc_2t[1] = dAdd * ddij_di[1];
     852       19030 :             dAijdc_2t[2] = dAdd * ddij_di[2];
     853             : 
     854      560038 :             for (unsigned k = 0; k < Nlist[Nlist[i][j]].size(); k++) {
     855      541008 :               if (std::find (Nlist[i].begin(), Nlist[i].end(), Nlist[Nlist[i][j]][k]) !=  Nlist[i].end()) {
     856      370872 :                 const Vector d_jk_vec = delta( getPosition(Nlist[i][j]), getPosition(Nlist[Nlist[i][j]][k]) );
     857             :                 const Vector d_ik_vec = delta( getPosition(i), getPosition(Nlist[Nlist[i][j]][k]) );
     858             : 
     859      370872 :                 double d_jk = d_jk_vec.modulo()*10;
     860      370872 :                 double d_ik = d_ik_vec.modulo()*10;
     861             : 
     862      370872 :                 double rk = LCPOparam[Nlist[Nlist[i][j]][k]][0];
     863      370872 :                 double sjk =  (2*M_PI*rj*(rj-d_jk/2-((rj*rj-rk*rk)/(2*d_jk))));
     864      370872 :                 Ajkt += sjk;
     865      370872 :                 Aikt += (2*M_PI*ri*(ri-d_ik/2-((ri*ri-rk*rk)/(2*d_ik))));
     866             : 
     867      370872 :                 dAdd = M_PI*ri*((ri*ri-rk*rk)/(d_ik*d_ik)-1);
     868             : 
     869      370872 :                 ddik_di[0] = -10*(getPosition(Nlist[Nlist[i][j]][k])[0]-getPosition(i)[0])/d_ik;
     870      370872 :                 ddik_di[1] = -10*(getPosition(Nlist[Nlist[i][j]][k])[1]-getPosition(i)[1])/d_ik;
     871      370872 :                 ddik_di[2] = -10*(getPosition(Nlist[Nlist[i][j]][k])[2]-getPosition(i)[2])/d_ik;
     872             : 
     873             : 
     874      370872 :                 dSASA_3_neigh_dc[0] += dAdd*ddik_di[0];
     875      370872 :                 dSASA_3_neigh_dc[1] += dAdd*ddik_di[1];
     876      370872 :                 dSASA_3_neigh_dc[2] += dAdd*ddik_di[2];
     877             : 
     878      370872 :                 dAdd = M_PI*rk*(-(ri*ri-rk*rk)/(d_ik*d_ik)-1);
     879             : 
     880      370872 :                 dSASA_3_neigh_dc2[0] += dAdd*ddik_di[0];
     881      370872 :                 dSASA_3_neigh_dc2[1] += dAdd*ddik_di[1];
     882      370872 :                 dSASA_3_neigh_dc2[2] += dAdd*ddik_di[2];
     883             : 
     884      370872 :                 dSASA_4_neigh_dc2[0] += sjk*dAdd*ddik_di[0];
     885      370872 :                 dSASA_4_neigh_dc2[1] += sjk*dAdd*ddik_di[1];
     886      370872 :                 dSASA_4_neigh_dc2[2] += sjk*dAdd*ddik_di[2];
     887             : 
     888             :               }
     889             :             }
     890       19030 :             dSASA_4_neigh_dc[0] = sji*dSASA_3_neigh_dc[0] + dSASA_4_neigh_dc2[0];
     891       19030 :             dSASA_4_neigh_dc[1] = sji*dSASA_3_neigh_dc[1] + dSASA_4_neigh_dc2[1];
     892       19030 :             dSASA_4_neigh_dc[2] = sji*dSASA_3_neigh_dc[2] + dSASA_4_neigh_dc2[2];
     893             : 
     894       19030 :             dSASA_3_neigh_dc[0] += dSASA_3_neigh_dc2[0];
     895       19030 :             dSASA_3_neigh_dc[1] += dSASA_3_neigh_dc2[1];
     896       19030 :             dSASA_3_neigh_dc[2] += dSASA_3_neigh_dc2[2];
     897             : 
     898       19030 :             dSASA_4_neigh_dc[0] += dSASA_2_neigh_dc[0] * Aikt;
     899       19030 :             dSASA_4_neigh_dc[1] += dSASA_2_neigh_dc[1] * Aikt;
     900       19030 :             dSASA_4_neigh_dc[2] += dSASA_2_neigh_dc[2] * Aikt;
     901             : 
     902             : 
     903       19030 :             derivatives[i][0] += (dSASA_2_neigh_dc[0]*LCPOparam[Nlist[i][j]][2] + dSASA_3_neigh_dc[0]*LCPOparam[Nlist[i][j]][3]+dSASA_4_neigh_dc[0]*LCPOparam[Nlist[i][j]][4])/10;
     904       19030 :             derivatives[i][1] += (dSASA_2_neigh_dc[1]*LCPOparam[Nlist[i][j]][2] + dSASA_3_neigh_dc[1]*LCPOparam[Nlist[i][j]][3]+dSASA_4_neigh_dc[1]*LCPOparam[Nlist[i][j]][4])/10;
     905       19030 :             derivatives[i][2] += (dSASA_2_neigh_dc[2]*LCPOparam[Nlist[i][j]][2] + dSASA_3_neigh_dc[2]*LCPOparam[Nlist[i][j]][3]+dSASA_4_neigh_dc[2]*LCPOparam[Nlist[i][j]][4])/10;
     906             : 
     907             : 
     908       19030 :             Aijk += (Aijt * Ajkt);
     909       19030 :             Aij += Aijt;
     910       19030 :             Ajk += Ajkt;
     911             : 
     912       19030 :             dAijdc_2[0] += dAijdc_2t[0];
     913       19030 :             dAijdc_2[1] += dAijdc_2t[1];
     914       19030 :             dAijdc_2[2] += dAijdc_2t[2];
     915             : 
     916             : 
     917       19030 :             dAijdc_4[0] += Ajkt*dAijdc_2t[0];
     918       19030 :             dAijdc_4[1] += Ajkt*dAijdc_2t[1];
     919       19030 :             dAijdc_4[2] += Ajkt*dAijdc_2t[2];
     920             : 
     921             : 
     922       19030 :           }
     923         720 :           double sasai = (LCPOparam[i][1]*S1+LCPOparam[i][2]*Aij+LCPOparam[i][3]*Ajk+LCPOparam[i][4]*Aijk);
     924         720 :           if (sasai > 0 ) {
     925         715 :             sasa += sasai/100;
     926             :           }
     927         720 :           derivatives[i][0] += (dAijdc_2[0]*LCPOparam[i][2]+dAijdc_4[0]*LCPOparam[i][4])/10;
     928         720 :           derivatives[i][1] += (dAijdc_2[1]*LCPOparam[i][2]+dAijdc_4[1]*LCPOparam[i][4])/10;
     929         720 :           derivatives[i][2] += (dAijdc_2[2]*LCPOparam[i][2]+dAijdc_4[2]*LCPOparam[i][4])/10;
     930         720 :         }
     931             :       }
     932        2880 :       virial -= Tensor(getPosition(i),derivatives[i]);
     933             :     }
     934             :   }
     935             : 
     936             : 
     937             : 
     938          24 :   if( sasa_type==TRANSFER ) {
     939             : 
     940          12 :     if (firstStepFlag ==0) {
     941           1 :       readMaxSurf();
     942             :     }
     943             : 
     944          12 :     if (firstStepFlag ==0 && DeltaGValues != "absent") {
     945           1 :       readDeltaG();
     946             :     }
     947             : 
     948          12 :     if (DeltaGValues == "absent") {
     949           0 :       computeDeltaG();
     950             :     }
     951             : 
     952             : 
     953        1452 :     for(unsigned i = 0; i < natoms; i++) {
     954             : 
     955             : 
     956             : 
     957        1440 :       derivatives[i][0] = 0.;
     958        1440 :       derivatives[i][1] = 0.;
     959        1440 :       derivatives[i][2] = 0.;
     960             : 
     961        1440 :       if ( LCPOparam[i].size()>1) {
     962         720 :         if (LCPOparam[i][1]>0.0) {
     963             :           Aij = 0.0;
     964             :           Aijk = 0.0;
     965             :           Ajk = 0.0;
     966         720 :           double ri = LCPOparam[i][0];
     967         720 :           S1 = 4*M_PI*ri*ri;
     968         720 :           vector <double> dAijdc_2(3, 0);
     969         720 :           vector <double> dAijdc_4(3, 0);
     970             : 
     971             : 
     972       19750 :           for (unsigned j = 0; j < Nlist[i].size(); j++) {
     973       19030 :             const Vector d_ij_vec = delta( getPosition(i), getPosition(Nlist[i][j]) );
     974       19030 :             double d_ij = d_ij_vec.modulo()*10;
     975             : 
     976       19030 :             double rj = LCPOparam[Nlist[i][j]][0];
     977       19030 :             Aijt = (2*M_PI*ri*(ri-d_ij/2-((ri*ri-rj*rj)/(2*d_ij))));
     978       19030 :             double sji = (2*M_PI*rj*(rj-d_ij/2+((ri*ri-rj*rj)/(2*d_ij))));
     979             : 
     980       19030 :             dAdd = M_PI*rj*(-(ri*ri-rj*rj)/(d_ij*d_ij)-1);
     981       19030 :             ddij_di[0] = -10*(getPosition(Nlist[i][j])[0]-getPosition(i)[0])/d_ij;
     982       19030 :             ddij_di[1] = -10*(getPosition(Nlist[i][j])[1]-getPosition(i)[1])/d_ij;
     983       19030 :             ddij_di[2] = -10*(getPosition(Nlist[i][j])[2]-getPosition(i)[2])/d_ij;
     984             : 
     985             :             Ajkt = 0.0;
     986             :             Aikt = 0.0;
     987             : 
     988       19030 :             vector <double> dSASA_3_neigh_dc(3, 0.0);
     989       19030 :             vector <double> dSASA_4_neigh_dc(3, 0.0);
     990       19030 :             vector <double> dSASA_3_neigh_dc2(3, 0.0);
     991       19030 :             vector <double> dSASA_4_neigh_dc2(3, 0.0);
     992             : 
     993       19030 :             dSASA_2_neigh_dc[0] = dAdd * ddij_di[0];
     994       19030 :             dSASA_2_neigh_dc[1] = dAdd * ddij_di[1];
     995       19030 :             dSASA_2_neigh_dc[2] = dAdd * ddij_di[2];
     996             : 
     997       19030 :             dAdd = M_PI*ri*((ri*ri-rj*rj)/(d_ij*d_ij)-1);
     998             : 
     999       19030 :             dAijdc_2t[0] = dAdd * ddij_di[0];
    1000       19030 :             dAijdc_2t[1] = dAdd * ddij_di[1];
    1001       19030 :             dAijdc_2t[2] = dAdd * ddij_di[2];
    1002             : 
    1003      560038 :             for (unsigned k = 0; k < Nlist[Nlist[i][j]].size(); k++) {
    1004      541008 :               if (std::find (Nlist[i].begin(), Nlist[i].end(), Nlist[Nlist[i][j]][k]) !=  Nlist[i].end()) {
    1005      370872 :                 const Vector d_jk_vec = delta( getPosition(Nlist[i][j]), getPosition(Nlist[Nlist[i][j]][k]) );
    1006             :                 const Vector d_ik_vec = delta( getPosition(i), getPosition(Nlist[Nlist[i][j]][k]) );
    1007             : 
    1008      370872 :                 double d_jk = d_jk_vec.modulo()*10;
    1009      370872 :                 double d_ik = d_ik_vec.modulo()*10;
    1010             : 
    1011      370872 :                 double rk = LCPOparam[Nlist[Nlist[i][j]][k]][0];
    1012      370872 :                 double sjk =  (2*M_PI*rj*(rj-d_jk/2-((rj*rj-rk*rk)/(2*d_jk))));
    1013      370872 :                 Ajkt += sjk;
    1014      370872 :                 Aikt += (2*M_PI*ri*(ri-d_ik/2-((ri*ri-rk*rk)/(2*d_ik))));
    1015             : 
    1016      370872 :                 dAdd = M_PI*ri*((ri*ri-rk*rk)/(d_ik*d_ik)-1);
    1017             : 
    1018      370872 :                 ddik_di[0] = -10*(getPosition(Nlist[Nlist[i][j]][k])[0]-getPosition(i)[0])/d_ik;
    1019      370872 :                 ddik_di[1] = -10*(getPosition(Nlist[Nlist[i][j]][k])[1]-getPosition(i)[1])/d_ik;
    1020      370872 :                 ddik_di[2] = -10*(getPosition(Nlist[Nlist[i][j]][k])[2]-getPosition(i)[2])/d_ik;
    1021             : 
    1022             : 
    1023      370872 :                 dSASA_3_neigh_dc[0] += dAdd*ddik_di[0];
    1024      370872 :                 dSASA_3_neigh_dc[1] += dAdd*ddik_di[1];
    1025      370872 :                 dSASA_3_neigh_dc[2] += dAdd*ddik_di[2];
    1026             : 
    1027      370872 :                 dAdd = M_PI*rk*(-(ri*ri-rk*rk)/(d_ik*d_ik)-1);
    1028             : 
    1029      370872 :                 dSASA_3_neigh_dc2[0] += dAdd*ddik_di[0];
    1030      370872 :                 dSASA_3_neigh_dc2[1] += dAdd*ddik_di[1];
    1031      370872 :                 dSASA_3_neigh_dc2[2] += dAdd*ddik_di[2];
    1032             : 
    1033      370872 :                 dSASA_4_neigh_dc2[0] += sjk*dAdd*ddik_di[0];
    1034      370872 :                 dSASA_4_neigh_dc2[1] += sjk*dAdd*ddik_di[1];
    1035      370872 :                 dSASA_4_neigh_dc2[2] += sjk*dAdd*ddik_di[2];
    1036             : 
    1037             :               }
    1038             :             }
    1039       19030 :             dSASA_4_neigh_dc[0] = sji*dSASA_3_neigh_dc[0] + dSASA_4_neigh_dc2[0];
    1040       19030 :             dSASA_4_neigh_dc[1] = sji*dSASA_3_neigh_dc[1] + dSASA_4_neigh_dc2[1];
    1041       19030 :             dSASA_4_neigh_dc[2] = sji*dSASA_3_neigh_dc[2] + dSASA_4_neigh_dc2[2];
    1042             : 
    1043       19030 :             dSASA_3_neigh_dc[0] += dSASA_3_neigh_dc2[0];
    1044       19030 :             dSASA_3_neigh_dc[1] += dSASA_3_neigh_dc2[1];
    1045       19030 :             dSASA_3_neigh_dc[2] += dSASA_3_neigh_dc2[2];
    1046             : 
    1047       19030 :             dSASA_4_neigh_dc[0] += dSASA_2_neigh_dc[0] * Aikt;
    1048       19030 :             dSASA_4_neigh_dc[1] += dSASA_2_neigh_dc[1] * Aikt;
    1049       19030 :             dSASA_4_neigh_dc[2] += dSASA_2_neigh_dc[2] * Aikt;
    1050             : 
    1051       19030 :             if (AtomResidueName[0][Nlist[i][j]] == "N" || AtomResidueName[0][Nlist[i][j]] == "CA"  || AtomResidueName[0][Nlist[i][j]] == "C" || AtomResidueName[0][Nlist[i][j]] == "O") {
    1052       15720 :               derivatives[i][0] += ((dSASA_2_neigh_dc[0]*LCPOparam[Nlist[i][j]][2] + dSASA_3_neigh_dc[0]*LCPOparam[Nlist[i][j]][3]+dSASA_4_neigh_dc[0]*LCPOparam[Nlist[i][j]][4])/MaxSurf[Nlist[i][j]][0]*DeltaG[natoms][0])*10;
    1053       15720 :               derivatives[i][1] += ((dSASA_2_neigh_dc[1]*LCPOparam[Nlist[i][j]][2] + dSASA_3_neigh_dc[1]*LCPOparam[Nlist[i][j]][3]+dSASA_4_neigh_dc[1]*LCPOparam[Nlist[i][j]][4])/MaxSurf[Nlist[i][j]][0]*DeltaG[natoms][0])*10;
    1054       15720 :               derivatives[i][2] += ((dSASA_2_neigh_dc[2]*LCPOparam[Nlist[i][j]][2] + dSASA_3_neigh_dc[2]*LCPOparam[Nlist[i][j]][3]+dSASA_4_neigh_dc[2]*LCPOparam[Nlist[i][j]][4])/MaxSurf[Nlist[i][j]][0]*DeltaG[natoms][0])*10;
    1055             :             }
    1056             : 
    1057       19030 :             if (AtomResidueName[0][Nlist[i][j]] != "N" && AtomResidueName[0][Nlist[i][j]] != "CA"  && AtomResidueName[0][Nlist[i][j]] != "C" && AtomResidueName[0][Nlist[i][j]] != "O") {
    1058        3310 :               derivatives[i][0] += ((dSASA_2_neigh_dc[0]*LCPOparam[Nlist[i][j]][2] + dSASA_3_neigh_dc[0]*LCPOparam[Nlist[i][j]][3]+dSASA_4_neigh_dc[0]*LCPOparam[Nlist[i][j]][4])/MaxSurf[Nlist[i][j]][1]*DeltaG[Nlist[i][j]][0])*10;
    1059        3310 :               derivatives[i][1] += ((dSASA_2_neigh_dc[1]*LCPOparam[Nlist[i][j]][2] + dSASA_3_neigh_dc[1]*LCPOparam[Nlist[i][j]][3]+dSASA_4_neigh_dc[1]*LCPOparam[Nlist[i][j]][4])/MaxSurf[Nlist[i][j]][1]*DeltaG[Nlist[i][j]][0])*10;
    1060        3310 :               derivatives[i][2] += ((dSASA_2_neigh_dc[2]*LCPOparam[Nlist[i][j]][2] + dSASA_3_neigh_dc[2]*LCPOparam[Nlist[i][j]][3]+dSASA_4_neigh_dc[2]*LCPOparam[Nlist[i][j]][4])/MaxSurf[Nlist[i][j]][1]*DeltaG[Nlist[i][j]][0])*10;
    1061             :             }
    1062             : 
    1063       19030 :             Aijk += (Aijt * Ajkt);
    1064       19030 :             Aij += Aijt;
    1065       19030 :             Ajk += Ajkt;
    1066             : 
    1067       19030 :             dAijdc_2[0] += dAijdc_2t[0];
    1068       19030 :             dAijdc_2[1] += dAijdc_2t[1];
    1069       19030 :             dAijdc_2[2] += dAijdc_2t[2];
    1070             : 
    1071       19030 :             dAijdc_4[0] += Ajkt*dAijdc_2t[0];
    1072       19030 :             dAijdc_4[1] += Ajkt*dAijdc_2t[1];
    1073       19030 :             dAijdc_4[2] += Ajkt*dAijdc_2t[2];
    1074             : 
    1075       19030 :           }
    1076         720 :           double sasai = (LCPOparam[i][1]*S1+LCPOparam[i][2]*Aij+LCPOparam[i][3]*Ajk+LCPOparam[i][4]*Aijk);
    1077             : 
    1078         720 :           if (AtomResidueName[0][i] == "N" || AtomResidueName[0][i] == "CA"  || AtomResidueName[0][i] == "C" || AtomResidueName[0][i] == "O") {
    1079         576 :             if (sasai > 0 ) {
    1080         571 :               sasa += (sasai/MaxSurf[i][0]*DeltaG[natoms][0]);
    1081             :             }
    1082         576 :             derivatives[i][0] += ((dAijdc_2[0]*LCPOparam[i][2]+dAijdc_4[0]*LCPOparam[i][4])/MaxSurf[i][0]*DeltaG[natoms][0])*10;
    1083         576 :             derivatives[i][1] += ((dAijdc_2[1]*LCPOparam[i][2]+dAijdc_4[1]*LCPOparam[i][4])/MaxSurf[i][0]*DeltaG[natoms][0])*10;
    1084         576 :             derivatives[i][2] += ((dAijdc_2[2]*LCPOparam[i][2]+dAijdc_4[2]*LCPOparam[i][4])/MaxSurf[i][0]*DeltaG[natoms][0])*10;
    1085             :           }
    1086             : 
    1087         720 :           if (AtomResidueName[0][i] != "N" && AtomResidueName[0][i] != "CA"  && AtomResidueName[0][i] != "C" && AtomResidueName[0][i] != "O") {
    1088         144 :             if (sasai > 0. ) {
    1089         144 :               sasa += (sasai/MaxSurf[i][1]*DeltaG[i][0]);
    1090             :             }
    1091         144 :             derivatives[i][0] += ((dAijdc_2[0]*LCPOparam[i][2]+dAijdc_4[0]*LCPOparam[i][4])/MaxSurf[i][1]*DeltaG[i][0])*10;
    1092         144 :             derivatives[i][1] += ((dAijdc_2[1]*LCPOparam[i][2]+dAijdc_4[1]*LCPOparam[i][4])/MaxSurf[i][1]*DeltaG[i][0])*10;
    1093         144 :             derivatives[i][2] += ((dAijdc_2[2]*LCPOparam[i][2]+dAijdc_4[2]*LCPOparam[i][4])/MaxSurf[i][1]*DeltaG[i][0])*10;
    1094             :           }
    1095         720 :         }
    1096             :       }
    1097        2880 :       virial -= Tensor(getPosition(i),derivatives[i]);
    1098             :     }
    1099             :   }
    1100             : 
    1101             : 
    1102        2904 :   for(unsigned i=0; i<natoms; i++) {
    1103        2880 :     setAtomsDerivatives(i,derivatives[i]);
    1104             :   }
    1105          24 :   setBoxDerivatives(virial);
    1106          24 :   setValue(sasa);
    1107          24 :   firstStepFlag = 1;
    1108          24 :   ++nl_update;
    1109          24 :   if (nl_update == stride) {
    1110          24 :     nl_update = 0;
    1111             :   }
    1112          48 : }
    1113             : 
    1114             : }//namespace sasa
    1115             : }//namespace PLMD

Generated by: LCOV version 1.16