LCOV - code coverage report
Current view: top level - colvar - Puckering.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 270 271 99.6 %
Date: 2025-03-25 09:33:27 Functions: 5 6 83.3 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2015-2023 The plumed team
       3             :    (see the PEOPLE file at the root of the distribution for a list of names)
       4             : 
       5             :    See http://www.plumed.org for more information.
       6             : 
       7             :    This file is part of plumed, version 2.
       8             : 
       9             :    plumed is free software: you can redistribute it and/or modify
      10             :    it under the terms of the GNU Lesser General Public License as published by
      11             :    the Free Software Foundation, either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    plumed is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU Lesser General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU Lesser General Public License
      20             :    along with plumed.  If not, see <http://www.gnu.org/licenses/>.
      21             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      22             : #include "Colvar.h"
      23             : #include "core/PlumedMain.h"
      24             : #include "core/ActionRegister.h"
      25             : #include "tools/Torsion.h"
      26             : 
      27             : namespace PLMD {
      28             : namespace colvar {
      29             : 
      30             : //+PLUMEDOC COLVAR PUCKERING
      31             : /*
      32             : Calculate sugar pseudorotation coordinates.
      33             : 
      34             : This command can be used to calculate pseudorotations for the rings in sugars (puckers). It works for both
      35             : 5-membered and 6-membered rings. Notice that there are two different implementations depending if
      36             : one passes 5 or 6 atoms in the ATOMS keyword. This input tells plumed to print the puckering phase angle of the
      37             :  second nucleotide of a RNA molecule on file COLVAR.
      38             : 
      39             : ```plumed
      40             : #SETTINGS MOLFILE=regtest/basic/rt65/AA.pdb
      41             : MOLINFO STRUCTURE=regtest/basic/rt65/AA.pdb MOLTYPE=rna
      42             : puck: PUCKERING ATOMS=@sugar-2
      43             : PRINT ARG=puck.phs FILE=COLVAR
      44             : ```
      45             : 
      46             : For 5-membered rings the implementation is the one discussed in the first of the papers in the bibliography below.
      47             : This implementation is simple and can be used in RNA to distinguish C2'-endo and C3'-endo conformations.
      48             : Both the polar coordinates (phs and amp) and the Cartesian coordinates (Zx and Zy) are provided.
      49             : C2'-endo conformations have negative Zx, whereas C3'-endo conformations have positive Zy.
      50             : The notation is consistent with the notation in that first paper.
      51             : The five atoms should be provided as C4',O4',C1',C2',C3'.
      52             : Notice that this is the same order that can be obtained using the [MOLINFO](MOLINFO.md) syntax (see example below).
      53             : 
      54             : For 6-membered rings the implementation is the general Cremer-Pople one that is discussed in the second and third
      55             : papers in the bibliography.
      56             : This implementation provides both a triplet with Cartesian components (qx, qy, and qz)
      57             : and a triplet of polar components (amplitude, phi, and theta).
      58             : Applications of this particular implementation are yet to be published (paper in preparation).
      59             : 
      60             : > [!NOTE]
      61             : > The 6-membered ring implementation distributed with previous versions of PLUMED lead to
      62             : > qx and qy values that had an opposite sign with respect to those originally defined in the
      63             : > thid reference in the bibliograph below.  The bug was fixed in version 2.5.
      64             : 
      65             : */
      66             : //+ENDPLUMEDOC
      67             : 
      68             : class Puckering : public Colvar {
      69             : 
      70             : public:
      71             :   explicit Puckering(const ActionOptions&);
      72             :   void calculate() override;
      73             :   static void registerKeywords(Keywords& keys);
      74             :   void calculate5m();
      75             :   void calculate6m();
      76             : };
      77             : 
      78             : PLUMED_REGISTER_ACTION(Puckering,"PUCKERING")
      79             : 
      80          58 : void Puckering::registerKeywords(Keywords& keys) {
      81          58 :   Colvar::registerKeywords( keys );
      82         116 :   keys.remove("NOPBC");
      83          58 :   keys.add("atoms","ATOMS","the five or six atoms of the sugar ring in the proper order");
      84         116 :   keys.addOutputComponent("phs","default","scalar","Pseudorotation phase (5 membered rings)");
      85         116 :   keys.addOutputComponent("amp","default","scalar","Pseudorotation amplitude (5 membered rings)");
      86         116 :   keys.addOutputComponent("Zx","default","scalar","Pseudorotation x Cartesian component (5 membered rings)");
      87         116 :   keys.addOutputComponent("Zy","default","scalar","Pseudorotation y Cartesian component (5 membered rings)");
      88         116 :   keys.addOutputComponent("phi","default","scalar","Pseudorotation phase (6 membered rings)");
      89         116 :   keys.addOutputComponent("theta","default","scalar","Theta angle (6 membered rings)");
      90         116 :   keys.addOutputComponent("amplitude","default","scalar","Pseudorotation amplitude (6 membered rings)");
      91         116 :   keys.addOutputComponent("qx","default","scalar","Cartesian component x (6 membered rings)");
      92         116 :   keys.addOutputComponent("qy","default","scalar","Cartesian component y (6 membered rings)");
      93         116 :   keys.addOutputComponent("qz","default","scalar","Cartesian component z (6 membered rings)");
      94          58 :   keys.addDOI("10.1021/ct401013s");
      95          58 :   keys.addDOI("10.1021/ja00839a011");
      96          58 :   keys.addDOI("10.1021/ja068411o");
      97          58 : }
      98             : 
      99          56 : Puckering::Puckering(const ActionOptions&ao):
     100          56 :   PLUMED_COLVAR_INIT(ao) {
     101             :   std::vector<AtomNumber> atoms;
     102         112 :   parseAtomList("ATOMS",atoms);
     103          56 :   if(atoms.size()!=5 && atoms.size()!=6) {
     104           1 :     error("only for 5 or 6-membered rings");
     105             :   }
     106          55 :   checkRead();
     107             : 
     108          55 :   if(atoms.size()==5) {
     109          54 :     log.printf("  between atoms %d %d %d %d %d\n",atoms[0].serial(),atoms[1].serial(),atoms[2].serial(),atoms[3].serial(),atoms[4].serial());
     110           1 :   } else if(atoms.size()==6) {
     111           1 :     log.printf("  between atoms %d %d %d %d %d %d\n",atoms[0].serial(),atoms[1].serial(),atoms[2].serial(),atoms[3].serial(),atoms[4].serial(),atoms[5].serial());
     112             :   } else {
     113           0 :     error("ATOMS should specify 5 atoms");
     114             :   }
     115             : 
     116          55 :   if(atoms.size()==5) {
     117         108 :     addComponentWithDerivatives("phs");
     118         108 :     componentIsPeriodic("phs","-pi","pi");
     119         108 :     addComponentWithDerivatives("amp");
     120         108 :     componentIsNotPeriodic("amp");
     121         108 :     addComponentWithDerivatives("Zx");
     122         108 :     componentIsNotPeriodic("Zx");
     123         108 :     addComponentWithDerivatives("Zy");
     124         108 :     componentIsNotPeriodic("Zy");
     125           1 :   } else if(atoms.size()==6) {
     126           2 :     addComponentWithDerivatives("qx");
     127           2 :     componentIsNotPeriodic("qx");
     128           2 :     addComponentWithDerivatives("qy");
     129           2 :     componentIsNotPeriodic("qy");
     130           2 :     addComponentWithDerivatives("qz");
     131           2 :     componentIsNotPeriodic("qz");
     132           2 :     addComponentWithDerivatives("phi");
     133           2 :     componentIsPeriodic("phi","0","2pi");
     134           2 :     addComponentWithDerivatives("theta");
     135           2 :     componentIsNotPeriodic("theta");
     136           2 :     addComponentWithDerivatives("amplitude");
     137           2 :     componentIsNotPeriodic("amplitude");
     138             :   }
     139             : 
     140          55 :   log<<"  Bibliography ";
     141          55 :   if(atoms.size()==5) {
     142         108 :     log<<plumed.cite("Huang, Giese, Lee, York, J. Chem. Theory Comput. 10, 1538 (2014)");
     143             :   }
     144          55 :   if(atoms.size()==6) {
     145           3 :     log<<plumed.cite("Cremer and Pople, J. Am. Chem. Soc. 97, 1354 (1975)");
     146             :   }
     147          55 :   log<<"\n";
     148             : 
     149          55 :   requestAtoms(atoms);
     150          57 : }
     151             : 
     152             : // calculator
     153         397 : void Puckering::calculate() {
     154         397 :   makeWhole();
     155         397 :   if(getNumberOfAtoms()==5) {
     156         294 :     calculate5m();
     157             :   } else {
     158         103 :     calculate6m();
     159             :   }
     160         397 : }
     161             : 
     162         294 : void Puckering::calculate5m() {
     163             : 
     164         294 :   Vector d0,d1,d2,d3,d4,d5;
     165             : 
     166         294 :   d0=delta(getPosition(2),getPosition(1));
     167         294 :   d1=delta(getPosition(3),getPosition(2));
     168         294 :   d2=delta(getPosition(4),getPosition(3));
     169         294 :   d3=delta(getPosition(4),getPosition(3));
     170         294 :   d4=delta(getPosition(0),getPosition(4));
     171         294 :   d5=delta(getPosition(1),getPosition(0));
     172             : 
     173         294 :   Vector dd0,dd1,dd2,dd3,dd4,dd5;
     174             : 
     175             :   PLMD::Torsion t;
     176             : 
     177         294 :   double v1=t.compute(d0,d1,d2,dd0,dd1,dd2);
     178         294 :   double v3=t.compute(d3,d4,d5,dd3,dd4,dd5);
     179             : 
     180         294 :   double Zx=(v1+v3)/(2.0*std::cos(4.0*pi/5.0));
     181         294 :   double Zy=(v1-v3)/(2.0*std::sin(4.0*pi/5.0));
     182         294 :   double phase=std::atan2(Zy,Zx);
     183         294 :   double amplitude=std::sqrt(Zx*Zx+Zy*Zy);
     184             : 
     185        1764 :   Vector dZx_dR[5];
     186        1764 :   Vector dZy_dR[5];
     187             : 
     188         294 :   dZx_dR[0]=(dd5-dd4);
     189         294 :   dZx_dR[1]=(dd0-dd5);
     190         294 :   dZx_dR[2]=(dd1-dd0);
     191         294 :   dZx_dR[3]=(dd2+dd3-dd1);
     192         294 :   dZx_dR[4]=(dd4-dd3-dd2);
     193             : 
     194         294 :   dZy_dR[0]=(dd4-dd5);
     195         294 :   dZy_dR[1]=(dd0+dd5);
     196         294 :   dZy_dR[2]=(dd1-dd0);
     197         294 :   dZy_dR[3]=(dd2-dd3-dd1);
     198         294 :   dZy_dR[4]=(dd3-dd4-dd2);
     199             : 
     200        1764 :   for(unsigned j=0; j<5; j++) {
     201        1470 :     dZx_dR[j]*=(1.0/(2.0*std::cos(4.0*pi/5.0)));
     202             :   }
     203        1764 :   for(unsigned j=0; j<5; j++) {
     204        1470 :     dZy_dR[j]*=(1.0/(2.0*std::sin(4.0*pi/5.0)));
     205             :   }
     206             : 
     207        1764 :   Vector dphase_dR[5];
     208        1764 :   for(unsigned j=0; j<5; j++) {
     209        1470 :     dphase_dR[j]=(1.0/(Zx*Zx+Zy*Zy))*(-Zy*dZx_dR[j] + Zx*dZy_dR[j]);
     210             :   }
     211             : 
     212        1764 :   Vector damplitude_dR[5];
     213        1764 :   for(unsigned j=0; j<5; j++) {
     214        1470 :     damplitude_dR[j]=(1.0/amplitude)*(Zx*dZx_dR[j] + Zy*dZy_dR[j]);
     215             :   }
     216             : 
     217         588 :   Value* vzx=getPntrToComponent("Zx");
     218             :   vzx->set(Zx);
     219         294 :   setAtomsDerivatives (vzx,0, dZx_dR[0]);
     220         294 :   setAtomsDerivatives (vzx,1, dZx_dR[1]);
     221         294 :   setAtomsDerivatives (vzx,2, dZx_dR[2]);
     222         294 :   setAtomsDerivatives (vzx,3, dZx_dR[3]);
     223         294 :   setAtomsDerivatives (vzx,4, dZx_dR[4]);
     224         294 :   setBoxDerivativesNoPbc(vzx);
     225             : 
     226         588 :   Value* vzy=getPntrToComponent("Zy");
     227             :   vzy->set(Zy);
     228         294 :   setAtomsDerivatives (vzy,0, dZy_dR[0]);
     229         294 :   setAtomsDerivatives (vzy,1, dZy_dR[1]);
     230         294 :   setAtomsDerivatives (vzy,2, dZy_dR[2]);
     231         294 :   setAtomsDerivatives (vzy,3, dZy_dR[3]);
     232         294 :   setAtomsDerivatives (vzy,4, dZy_dR[4]);
     233         294 :   setBoxDerivativesNoPbc(vzy);
     234             : 
     235             : 
     236         588 :   Value* vph=getPntrToComponent("phs");
     237             :   vph->set(phase);
     238         294 :   setAtomsDerivatives (vph,0, dphase_dR[0]);
     239         294 :   setAtomsDerivatives (vph,1, dphase_dR[1]);
     240         294 :   setAtomsDerivatives (vph,2, dphase_dR[2]);
     241         294 :   setAtomsDerivatives (vph,3, dphase_dR[3]);
     242         294 :   setAtomsDerivatives (vph,4, dphase_dR[4]);
     243         294 :   setBoxDerivativesNoPbc(vph);
     244             : 
     245         588 :   Value* vam=getPntrToComponent("amp");
     246             :   vam->set(amplitude);
     247         294 :   setAtomsDerivatives (vam,0, damplitude_dR[0]);
     248         294 :   setAtomsDerivatives (vam,1, damplitude_dR[1]);
     249         294 :   setAtomsDerivatives (vam,2, damplitude_dR[2]);
     250         294 :   setAtomsDerivatives (vam,3, damplitude_dR[3]);
     251         294 :   setAtomsDerivatives (vam,4, damplitude_dR[4]);
     252         294 :   setBoxDerivativesNoPbc(vam);
     253             : 
     254             : 
     255         294 : }
     256             : 
     257         103 : void Puckering::calculate6m() {
     258             : 
     259         103 :   std::vector<Vector> r(6);
     260         721 :   for(unsigned i=0; i<6; i++) {
     261         618 :     r[i]=getPosition(i);
     262             :   }
     263             : 
     264         103 :   std::vector<Vector> R(6);
     265         103 :   Vector center;
     266         721 :   for(unsigned j=0; j<6; j++) {
     267         618 :     center+=r[j]/6.0;
     268             :   }
     269         721 :   for(unsigned j=0; j<6; j++) {
     270         618 :     R[j]=(r[j]-center);
     271             :   }
     272             : 
     273         103 :   Vector Rp,Rpp;
     274         721 :   for(unsigned j=0; j<6; j++) {
     275         618 :     Rp +=R[j]*std::sin(2.0/6.0*pi*j);
     276             :   }
     277         721 :   for(unsigned j=0; j<6; j++) {
     278         618 :     Rpp+=R[j]*std::cos(2.0/6.0*pi*j);
     279             :   }
     280             : 
     281         103 :   Vector n=crossProduct(Rp,Rpp);
     282         103 :   Vector nhat=n/modulo(n);
     283             : 
     284         103 :   Tensor dn_dRp=dcrossDv1(Rp,Rpp);
     285         103 :   Tensor dn_dRpp=dcrossDv2(Rp,Rpp);
     286             : 
     287         103 :   Tensor dnhat_dn= 1.0/modulo(n)*( Tensor::identity() - extProduct(nhat,nhat));
     288         103 :   Tensor dnhat_dRp=matmul(dnhat_dn,dn_dRp);
     289         103 :   Tensor dnhat_dRpp=matmul(dnhat_dn,dn_dRpp);
     290             : 
     291         103 :   std::vector<double> z(6);
     292         721 :   for(unsigned j=0; j<6; j++) {
     293         618 :     z[j]=dotProduct(R[j],nhat);
     294             :   }
     295             : 
     296         103 :   std::vector<std::vector<Vector> > dz_dR(6);
     297         721 :   for(unsigned j=0; j<6; j++) {
     298         618 :     dz_dR[j].resize(6);
     299             :   }
     300             : 
     301         721 :   for(unsigned i=0; i<6; i++)
     302        4326 :     for(unsigned j=0; j<6; j++) {
     303        3708 :       if(i==j) {
     304         618 :         dz_dR[i][j]+=nhat;
     305             :       }
     306        3708 :       dz_dR[i][j]+=matmul(R[i],dnhat_dRp)*std::sin(2.0/6.0*pi*j);
     307        3708 :       dz_dR[i][j]+=matmul(R[i],dnhat_dRpp)*std::cos(2.0/6.0*pi*j);
     308             :     }
     309             : 
     310             :   double B=0.0;
     311         721 :   for(unsigned j=0; j<6; j++) {
     312         618 :     B+=z[j]*std::cos(4.0/6.0*pi*j);
     313             :   }
     314             : 
     315         103 :   std::vector<Vector> dB_dR(6);
     316         721 :   for(unsigned i=0; i<6; i++)
     317        4326 :     for(unsigned j=0; j<6; j++) {
     318        3708 :       dB_dR[i]+=dz_dR[j][i]*std::cos(4.0/6.0*pi*j);
     319             :     }
     320         103 :   Vector Bsum;
     321         721 :   for(unsigned j=0; j<6; j++) {
     322         618 :     Bsum+=dB_dR[j];
     323             :   }
     324         721 :   for(unsigned j=0; j<6; j++) {
     325         618 :     dB_dR[j]-=Bsum/6.0;
     326             :   };
     327             : 
     328             :   double A=0.0;
     329         721 :   for(unsigned j=0; j<6; j++) {
     330         618 :     A+=z[j]*std::sin(4.0/6.0*pi*j);
     331             :   }
     332             : 
     333         103 :   std::vector<Vector> dA_dR(6);
     334         721 :   for(unsigned i=0; i<6; i++)
     335        4326 :     for(unsigned j=0; j<6; j++) {
     336        3708 :       dA_dR[i]+=dz_dR[j][i]*std::sin(4.0/6.0*pi*j);
     337             :     }
     338         103 :   Vector Asum;
     339         721 :   for(unsigned j=0; j<6; j++) {
     340         618 :     Asum+=dA_dR[j];
     341             :   }
     342         721 :   for(unsigned j=0; j<6; j++) {
     343         618 :     dA_dR[j]-=Asum/6.0;
     344             :   };
     345             : 
     346             :   double C=0.0;
     347         721 :   for(unsigned j=0; j<6; j++) {
     348         618 :     C+=z[j]*Tools::fastpow(-1.0,(j));
     349             :   }
     350             : 
     351         103 :   std::vector<Vector> dC_dR(6);
     352         721 :   for(unsigned i=0; i<6; i++)
     353        4326 :     for(unsigned j=0; j<6; j++) {
     354        3708 :       dC_dR[i]+=dz_dR[j][i]*Tools::fastpow(-1.0,(j));
     355             :     }
     356             : 
     357         103 :   Vector Csum;
     358         721 :   for(unsigned j=0; j<6; j++) {
     359         618 :     Csum+=dC_dR[j];
     360             :   }
     361         721 :   for(unsigned j=0; j<6; j++) {
     362         618 :     dC_dR[j]-=Csum/6.0;
     363             :   };
     364             : 
     365             : 
     366             : // qx
     367         103 :   double qx = -A/std::sqrt(3);
     368             : 
     369             : // qx derivaties
     370         103 :   std::vector<Vector> dqx_dR(6);
     371         721 :   for(unsigned j=0; j<6; j++) {
     372         618 :     dqx_dR[j]=-1/std::sqrt(3) * dA_dR[j];
     373             :   }
     374             : 
     375         206 :   Value* vqx=getPntrToComponent("qx");
     376             :   vqx->set(qx);
     377         103 :   setAtomsDerivatives (vqx,0, dqx_dR[0] );
     378         103 :   setAtomsDerivatives (vqx,1, dqx_dR[1] );
     379         103 :   setAtomsDerivatives (vqx,2, dqx_dR[2] );
     380         103 :   setAtomsDerivatives (vqx,3, dqx_dR[3] );
     381         103 :   setAtomsDerivatives (vqx,4, dqx_dR[4] );
     382         103 :   setAtomsDerivatives (vqx,5, dqx_dR[5] );
     383         103 :   setBoxDerivativesNoPbc(vqx);
     384             : 
     385             : // qy
     386         103 :   double qy = B/std::sqrt(3);
     387             : 
     388             : // qy derivatives
     389         103 :   std::vector<Vector> dqy_dR(6);
     390         721 :   for(unsigned j=0; j<6; j++) {
     391         618 :     dqy_dR[j]=1/std::sqrt(3) * dB_dR[j];
     392             :   }
     393             : 
     394         206 :   Value* vqy=getPntrToComponent("qy");
     395             :   vqy->set(qy);
     396         103 :   setAtomsDerivatives (vqy,0, dqy_dR[0] );
     397         103 :   setAtomsDerivatives (vqy,1, dqy_dR[1] );
     398         103 :   setAtomsDerivatives (vqy,2, dqy_dR[2] );
     399         103 :   setAtomsDerivatives (vqy,3, dqy_dR[3] );
     400         103 :   setAtomsDerivatives (vqy,4, dqy_dR[4] );
     401         103 :   setAtomsDerivatives (vqy,5, dqy_dR[5] );
     402         103 :   setBoxDerivativesNoPbc(vqy);
     403             : 
     404             : // qz
     405         103 :   double qz = C/std::sqrt(6);
     406             : 
     407             : // qz derivatives
     408         103 :   std::vector<Vector> dqz_dR(6);
     409         721 :   for(unsigned j=0; j<6; j++) {
     410         618 :     dqz_dR[j]=1/std::sqrt(6) * dC_dR[j];
     411             :   }
     412             : 
     413         206 :   Value* vqz=getPntrToComponent("qz");
     414             :   vqz->set(qz);
     415         103 :   setAtomsDerivatives (vqz,0, dqz_dR[0] );
     416         103 :   setAtomsDerivatives (vqz,1, dqz_dR[1] );
     417         103 :   setAtomsDerivatives (vqz,2, dqz_dR[2] );
     418         103 :   setAtomsDerivatives (vqz,3, dqz_dR[3] );
     419         103 :   setAtomsDerivatives (vqz,4, dqz_dR[4] );
     420         103 :   setAtomsDerivatives (vqz,5, dqz_dR[5] );
     421         103 :   setBoxDerivativesNoPbc(vqz);
     422             : 
     423             : 
     424             : // PHASE
     425         103 :   double phi=std::atan2(-A,B);
     426             : 
     427             : // PHASE DERIVATIVES
     428         103 :   std::vector<Vector> dphi_dR(6);
     429         721 :   for(unsigned j=0; j<6; j++) {
     430         618 :     dphi_dR[j]=1.0/(A*A+B*B) * (-B*dA_dR[j] + A*dB_dR[j]);
     431             :   }
     432             : 
     433         206 :   Value* vphi=getPntrToComponent("phi");
     434             :   vphi->set(phi);
     435         103 :   setAtomsDerivatives (vphi,0, dphi_dR[0] );
     436         103 :   setAtomsDerivatives (vphi,1, dphi_dR[1] );
     437         103 :   setAtomsDerivatives (vphi,2, dphi_dR[2] );
     438         103 :   setAtomsDerivatives (vphi,3, dphi_dR[3] );
     439         103 :   setAtomsDerivatives (vphi,4, dphi_dR[4] );
     440         103 :   setAtomsDerivatives (vphi,5, dphi_dR[5] );
     441         103 :   setBoxDerivativesNoPbc(vphi);
     442             : 
     443             : //  AMPLITUDE
     444         103 :   double amplitude=std::sqrt((2*(A*A+B*B)+C*C)/6);
     445             : 
     446             : //  AMPLITUDE DERIVATIES
     447         103 :   std::vector<Vector> damplitude_dR(6);
     448         721 :   for (unsigned j=0; j<6; j++) {
     449         618 :     damplitude_dR[j]=0.5*std::sqrt(2.0/6.0)/(std::sqrt(A*A+B*B+0.5*C*C)) * (2*A*dA_dR[j] + 2*B*dB_dR[j] + C*dC_dR[j]);
     450             :   }
     451             : 
     452         206 :   Value* vamplitude=getPntrToComponent("amplitude");
     453             :   vamplitude->set(amplitude);
     454         103 :   setAtomsDerivatives (vamplitude,0, damplitude_dR[0] );
     455         103 :   setAtomsDerivatives (vamplitude,1, damplitude_dR[1] );
     456         103 :   setAtomsDerivatives (vamplitude,2, damplitude_dR[2] );
     457         103 :   setAtomsDerivatives (vamplitude,3, damplitude_dR[3] );
     458         103 :   setAtomsDerivatives (vamplitude,4, damplitude_dR[4] );
     459         103 :   setAtomsDerivatives (vamplitude,5, damplitude_dR[5] );
     460         103 :   setBoxDerivativesNoPbc(vamplitude);
     461             : 
     462             : //  THETA
     463         103 :   double theta=std::acos( C / std::sqrt(2.*(A*A+B*B) +C*C ) );
     464             : 
     465             : //  THETA DERIVATIVES
     466         103 :   std::vector<Vector> dtheta_dR(6);
     467         721 :   for(unsigned j=0; j<6; j++) {
     468         618 :     dtheta_dR[j]=1.0/(3.0*std::sqrt(2)*amplitude*amplitude) * (C/(std::sqrt(A*A+B*B)) * (A*dA_dR[j] + B*dB_dR[j]) - std::sqrt(A*A+B*B)*dC_dR[j]);
     469             :   }
     470         206 :   Value* vtheta=getPntrToComponent("theta");
     471             :   vtheta->set(theta);
     472         103 :   setAtomsDerivatives (vtheta,0, dtheta_dR[0] );
     473         103 :   setAtomsDerivatives (vtheta,1, dtheta_dR[1] );
     474         103 :   setAtomsDerivatives (vtheta,2, dtheta_dR[2] );
     475         103 :   setAtomsDerivatives (vtheta,3, dtheta_dR[3] );
     476         103 :   setAtomsDerivatives (vtheta,4, dtheta_dR[4] );
     477         103 :   setAtomsDerivatives (vtheta,5, dtheta_dR[5] );
     478         103 :   setBoxDerivativesNoPbc(vtheta);
     479         206 : }
     480             : 
     481             : 
     482             : }
     483             : }
     484             : 
     485             : 
     486             : 

Generated by: LCOV version 1.16