LCOV - code coverage report
Current view: top level - colvar - Puckering.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 252 253 99.6 %
Date: 2018-12-19 07:49:13 Functions: 12 13 92.3 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2015-2018 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 "ActionRegister.h"
      25             : #include "tools/Torsion.h"
      26             : 
      27             : #include <string>
      28             : #include <cmath>
      29             : #include <iostream>
      30             : 
      31             : using namespace std;
      32             : 
      33             : namespace PLMD {
      34             : namespace colvar {
      35             : 
      36             : //+PLUMEDOC COLVAR PUCKERING
      37             : /*
      38             :  Calculate sugar pseudorotation coordinates.
      39             : 
      40             :  This command can be used to calculate ring's pseudorotations in sugars (puckers). It works for both
      41             :  5-membered and 6-membered rings. Notice that there are two different implementations depending if
      42             :  one passes 5 or 6 atoms in the ATOMS keyword.
      43             : 
      44             :  For 5-membered rings the implementation is the one discussed in \cite huang2014improvement .
      45             :  This implementation is simple and can be used in RNA to distinguish C2'-endo and C3'-endo conformations.
      46             :  Both the polar coordinates (phs and amp) and the cartesian coordinates (Zx and Zy) are provided.
      47             :  C2'-endo conformations have negative Zx, whereas C3'-endo conformations have positive Zy.
      48             :  Notation is consistent with \cite huang2014improvement .
      49             :  The five atoms should be provided as C4',O4',C1',C2',C3'.
      50             :  Notice that this is the same order that can be obtained using the \ref MOLINFO syntax (see example below).
      51             : 
      52             :  For 6-membered rings the implementation is the general Cremer-Pople one \cite cremer1975general
      53             :  as also discussed in \cite biarnes2007conformational .
      54             :  This implementation provides both a triplet with Cartesian components (qx, qy, and qz)
      55             :  and a triplet of polar components (amplitude, phi, and theta).
      56             :  Applications of this particular implementation are to be published (paper in preparation).
      57             : 
      58             :  \bug The 6-membered ring implementation distributed with this version of PLUMED leads to
      59             :   qx and qy values that have an opposite sign with respect to those originally defined in \cite cremer1975general.
      60             :   The bug will be fixed in a later version but is here kept to preserve reproducibility.
      61             : 
      62             :  Components of this action are:
      63             : 
      64             :  \par Examples
      65             : 
      66             :  This input tells plumed to print the puckering phase angle of the 3rd nucleotide of a RNA molecule on file COLVAR.
      67             :  \verbatim
      68             :  MOLINFO STRUCTURE=rna.pdb MOLTYPE=rna
      69             :  PUCKERING ATOMS=@sugar-3 LABEL=puck
      70             :  PRINT ARG=puck.phs FILE=COLVAR
      71             :  \endverbatim
      72             : 
      73             : */
      74             : //+ENDPLUMEDOC
      75             : 
      76          30 : class Puckering : public Colvar {
      77             : 
      78             : public:
      79             :   explicit Puckering(const ActionOptions&);
      80             :   virtual void calculate();
      81             :   static void registerKeywords(Keywords& keys);
      82             :   void calculate5m();
      83             :   void calculate6m();
      84             : };
      85             : 
      86        2538 : PLUMED_REGISTER_ACTION(Puckering,"PUCKERING")
      87             : 
      88          16 : void Puckering::registerKeywords(Keywords& keys) {
      89          16 :   Colvar::registerKeywords( keys );
      90          16 :   keys.remove("NOPBC");
      91          16 :   keys.add("atoms","ATOMS","the five or six atoms of the sugar ring in the proper order");
      92          16 :   keys.addOutputComponent("phs","default","Pseudorotation phase (5 membered rings)");
      93          16 :   keys.addOutputComponent("amp","default","Pseudorotation amplitude (5 membered rings)");
      94          16 :   keys.addOutputComponent("Zx","default","Pseudorotation x cartesian component (5 membered rings)");
      95          16 :   keys.addOutputComponent("Zy","default","Pseudorotation y cartesian component (5 membered rings)");
      96          16 :   keys.addOutputComponent("phi","default","Pseudorotation phase (6 membered rings)");
      97          16 :   keys.addOutputComponent("theta","default","Theta angle (6 membered rings)");
      98          16 :   keys.addOutputComponent("amplitude","default","Pseudorotation amplitude (6 membered rings)");
      99          16 :   keys.addOutputComponent("qx","default","Cartesian component x (6 membered rings)");
     100          16 :   keys.addOutputComponent("qy","default","Cartesian component y (6 membered rings)");
     101          16 :   keys.addOutputComponent("qz","default","Cartesian component z (6 membered rings)");
     102          16 : }
     103             : 
     104          15 : Puckering::Puckering(const ActionOptions&ao):
     105          15 :   PLUMED_COLVAR_INIT(ao)
     106             : {
     107          15 :   vector<AtomNumber> atoms;
     108          15 :   parseAtomList("ATOMS",atoms);
     109          15 :   if(atoms.size()!=5 && atoms.size()!=6) error("only for 5 or 6-membered rings");
     110          15 :   checkRead();
     111             : 
     112          15 :   if(atoms.size()==5) {
     113          14 :     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());
     114           1 :   } else if(atoms.size()==6) {
     115           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());
     116           0 :   } else error("ATOMS should specify 5 atoms");
     117             : 
     118          15 :   if(atoms.size()==5) {
     119          14 :     addComponentWithDerivatives("phs"); componentIsPeriodic("phs","-pi","pi");
     120          14 :     addComponentWithDerivatives("amp"); componentIsNotPeriodic("amp");
     121          14 :     addComponentWithDerivatives("Zx"); componentIsNotPeriodic("Zx");
     122          14 :     addComponentWithDerivatives("Zy"); componentIsNotPeriodic("Zy");
     123           1 :   } else if(atoms.size()==6) {
     124           1 :     addComponentWithDerivatives("qx"); componentIsNotPeriodic("qx");
     125           1 :     addComponentWithDerivatives("qy"); componentIsNotPeriodic("qy");
     126           1 :     addComponentWithDerivatives("qz"); componentIsNotPeriodic("qz");
     127           1 :     addComponentWithDerivatives("phi"); componentIsPeriodic("phi","0","2pi");
     128           1 :     addComponentWithDerivatives("theta"); componentIsNotPeriodic("theta");
     129           1 :     addComponentWithDerivatives("amplitude"); componentIsNotPeriodic("amplitude");
     130             :   }
     131             : 
     132          15 :   log<<"  Bibliography ";
     133          15 :   if(atoms.size()==5) log<<plumed.cite("Huang, Giese, Lee, York, J. Chem. Theory Comput. 10, 1538 (2014)");
     134          15 :   if(atoms.size()==6) log<<plumed.cite("Cremer and Pople, J. Am. Chem. Soc. 97, 1354 (1975)");
     135          15 :   log<<"\n";
     136             : 
     137          15 :   requestAtoms(atoms);
     138          15 : }
     139             : 
     140             : // calculator
     141         383 : void Puckering::calculate() {
     142         383 :   makeWhole();
     143         383 :   if(getNumberOfAtoms()==5) calculate5m();
     144         103 :   else calculate6m();
     145         383 : }
     146             : 
     147         280 : void Puckering::calculate5m() {
     148             : 
     149         280 :   Vector d0,d1,d2,d3,d4,d5;
     150         280 :   makeWhole();
     151             : 
     152         280 :   d0=delta(getPosition(2),getPosition(1));
     153         280 :   d1=delta(getPosition(3),getPosition(2));
     154         280 :   d2=delta(getPosition(4),getPosition(3));
     155         280 :   d3=delta(getPosition(4),getPosition(3));
     156         280 :   d4=delta(getPosition(0),getPosition(4));
     157         280 :   d5=delta(getPosition(1),getPosition(0));
     158             : 
     159         280 :   Vector r[5];
     160         280 :   r[0]=getPosition(0);
     161        1400 :   for(unsigned i=1; i<5; i++) {
     162        1120 :     r[i]=r[i-1]+pbcDistance(getPosition(i-1),getPosition(i));
     163             :   }
     164             : 
     165         280 :   Vector dd0,dd1,dd2,dd3,dd4,dd5;
     166             : 
     167             :   PLMD::Torsion t;
     168             : 
     169         280 :   double v1=t.compute(d0,d1,d2,dd0,dd1,dd2);
     170         280 :   double v3=t.compute(d3,d4,d5,dd3,dd4,dd5);
     171             : 
     172         280 :   double Zx=(v1+v3)/(2.0*cos(4.0*pi/5.0));
     173         280 :   double Zy=(v1-v3)/(2.0*sin(4.0*pi/5.0));
     174         280 :   double phase=atan2(Zy,Zx);
     175         280 :   double amplitude=sqrt(Zx*Zx+Zy*Zy);
     176             : 
     177         280 :   Vector dZx_dR[5];
     178         280 :   Vector dZy_dR[5];
     179             : 
     180         280 :   dZx_dR[0]=(dd5-dd4);
     181         280 :   dZx_dR[1]=(dd0-dd5);
     182         280 :   dZx_dR[2]=(dd1-dd0);
     183         280 :   dZx_dR[3]=(dd2+dd3-dd1);
     184         280 :   dZx_dR[4]=(dd4-dd3-dd2);
     185             : 
     186         280 :   dZy_dR[0]=(dd4-dd5);
     187         280 :   dZy_dR[1]=(dd0+dd5);
     188         280 :   dZy_dR[2]=(dd1-dd0);
     189         280 :   dZy_dR[3]=(dd2-dd3-dd1);
     190         280 :   dZy_dR[4]=(dd3-dd4-dd2);
     191             : 
     192         280 :   for(unsigned j=0; j<5; j++) dZx_dR[j]*=(1.0/(2.0*cos(4.0*pi/5.0)));
     193         280 :   for(unsigned j=0; j<5; j++) dZy_dR[j]*=(1.0/(2.0*sin(4.0*pi/5.0)));
     194             : 
     195         280 :   Vector dphase_dR[5];
     196         280 :   for(unsigned j=0; j<5; j++) dphase_dR[j]=(1.0/(Zx*Zx+Zy*Zy))*(-Zy*dZx_dR[j] + Zx*dZy_dR[j]);
     197             : 
     198         280 :   Vector damplitude_dR[5];
     199         280 :   for(unsigned j=0; j<5; j++) damplitude_dR[j]=(1.0/amplitude)*(Zx*dZx_dR[j] + Zy*dZy_dR[j]);
     200             : 
     201         280 :   Value* vzx=getPntrToComponent("Zx");
     202         280 :   vzx->set(Zx);
     203         280 :   setAtomsDerivatives (vzx,0, dZx_dR[0]);
     204         280 :   setAtomsDerivatives (vzx,1, dZx_dR[1]);
     205         280 :   setAtomsDerivatives (vzx,2, dZx_dR[2]);
     206         280 :   setAtomsDerivatives (vzx,3, dZx_dR[3]);
     207         280 :   setAtomsDerivatives (vzx,4, dZx_dR[4]);
     208         280 :   setBoxDerivativesNoPbc(vzx);
     209             : 
     210         280 :   Value* vzy=getPntrToComponent("Zy");
     211         280 :   vzy->set(Zy);
     212         280 :   setAtomsDerivatives (vzy,0, dZy_dR[0]);
     213         280 :   setAtomsDerivatives (vzy,1, dZy_dR[1]);
     214         280 :   setAtomsDerivatives (vzy,2, dZy_dR[2]);
     215         280 :   setAtomsDerivatives (vzy,3, dZy_dR[3]);
     216         280 :   setAtomsDerivatives (vzy,4, dZy_dR[4]);
     217         280 :   setBoxDerivativesNoPbc(vzy);
     218             : 
     219             : 
     220         280 :   Value* vph=getPntrToComponent("phs");
     221         280 :   vph->set(phase);
     222         280 :   setAtomsDerivatives (vph,0, dphase_dR[0]);
     223         280 :   setAtomsDerivatives (vph,1, dphase_dR[1]);
     224         280 :   setAtomsDerivatives (vph,2, dphase_dR[2]);
     225         280 :   setAtomsDerivatives (vph,3, dphase_dR[3]);
     226         280 :   setAtomsDerivatives (vph,4, dphase_dR[4]);
     227         280 :   setBoxDerivativesNoPbc(vph);
     228             : 
     229         280 :   Value* vam=getPntrToComponent("amp");
     230         280 :   vam->set(amplitude);
     231         280 :   setAtomsDerivatives (vam,0, damplitude_dR[0]);
     232         280 :   setAtomsDerivatives (vam,1, damplitude_dR[1]);
     233         280 :   setAtomsDerivatives (vam,2, damplitude_dR[2]);
     234         280 :   setAtomsDerivatives (vam,3, damplitude_dR[3]);
     235         280 :   setAtomsDerivatives (vam,4, damplitude_dR[4]);
     236         280 :   setBoxDerivativesNoPbc(vam);
     237             : 
     238             : 
     239         280 : }
     240             : 
     241         103 : void Puckering::calculate6m() {
     242             : 
     243         103 :   vector<Vector> r(6);
     244         103 :   r[0]=getPosition(0);
     245         618 :   for(unsigned i=1; i<6; i++) {
     246         515 :     r[i]=r[i-1]+pbcDistance(getPosition(i-1),getPosition(i));
     247             :   }
     248             : 
     249         206 :   vector<Vector> R(6);
     250         103 :   Vector center;
     251         103 :   for(unsigned j=0; j<6; j++) center+=r[j]/6.0;
     252         103 :   for(unsigned j=0; j<6; j++) R[j]=(r[j]-center);
     253             : 
     254         103 :   Vector Rp,Rpp;
     255         103 :   for(unsigned j=0; j<6; j++) Rp +=R[j]*sin(2.0/6.0*pi*j);
     256         103 :   for(unsigned j=0; j<6; j++) Rpp+=R[j]*cos(2.0/6.0*pi*j);
     257             : 
     258         103 :   Vector n=crossProduct(Rp,Rpp);
     259         103 :   Vector nhat=n/modulo(n);
     260             : 
     261         103 :   Tensor dn_dRp=dcrossDv1(Rp,Rpp);
     262         103 :   Tensor dn_dRpp=dcrossDv2(Rp,Rpp);
     263             : 
     264         103 :   Tensor dnhat_dn= 1.0/modulo(n)*( Tensor::identity() - extProduct(nhat,nhat));
     265         103 :   Tensor dnhat_dRp=matmul(dnhat_dn,dn_dRp);
     266         103 :   Tensor dnhat_dRpp=matmul(dnhat_dn,dn_dRpp);
     267             : 
     268         206 :   vector<double> z(6);
     269         103 :   for(unsigned j=0; j<6; j++) z[j]=dotProduct(R[j],nhat);
     270             : 
     271         206 :   vector<vector<Vector> > dz_dR(6);
     272         103 :   for(unsigned j=0; j<6; j++) dz_dR[j].resize(6);
     273             : 
     274        3811 :   for(unsigned i=0; i<6; i++) for(unsigned j=0; j<6; j++) {
     275        3708 :       if(i==j) dz_dR[i][j]+=nhat;
     276        3708 :       dz_dR[i][j]+=matmul(R[i],dnhat_dRp)*sin(2.0/6.0*pi*j);
     277        3708 :       dz_dR[i][j]+=matmul(R[i],dnhat_dRpp)*cos(2.0/6.0*pi*j);
     278             :     }
     279             : 
     280         103 :   double B=0.0;
     281         103 :   for(unsigned j=0; j<6; j++) B+=z[j]*cos(4.0/6.0*pi*j);
     282             : 
     283         206 :   vector<Vector> dB_dR(6);
     284        3811 :   for(unsigned i=0; i<6; i++) for(unsigned j=0; j<6; j++) {
     285        3708 :       dB_dR[i]+=dz_dR[j][i]*cos(4.0/6.0*pi*j);
     286             :     }
     287         103 :   Vector Bsum;
     288         103 :   for(unsigned j=0; j<6; j++) Bsum+=dB_dR[j];
     289         103 :   for(unsigned j=0; j<6; j++) dB_dR[j]-=Bsum/6.0;;
     290             : 
     291         103 :   double A=0.0;
     292         103 :   for(unsigned j=0; j<6; j++) A+=z[j]*sin(4.0/6.0*pi*j);
     293             : 
     294         206 :   vector<Vector> dA_dR(6);
     295        3811 :   for(unsigned i=0; i<6; i++) for(unsigned j=0; j<6; j++) {
     296        3708 :       dA_dR[i]+=dz_dR[j][i]*sin(4.0/6.0*pi*j);
     297             :     }
     298         103 :   Vector Asum;
     299         103 :   for(unsigned j=0; j<6; j++) Asum+=dA_dR[j];
     300         103 :   for(unsigned j=0; j<6; j++) dA_dR[j]-=Asum/6.0;;
     301             : 
     302         103 :   double C=0.0;
     303         103 :   for(unsigned j=0; j<6; j++) C+=z[j]*Tools::fastpow(-1.0,(j));
     304             : 
     305         206 :   vector<Vector> dC_dR(6);
     306        3811 :   for(unsigned i=0; i<6; i++) for(unsigned j=0; j<6; j++) {
     307        3708 :       dC_dR[i]+=dz_dR[j][i]*Tools::fastpow(-1.0,(j));
     308             :     }
     309             : 
     310         103 :   Vector Csum;
     311         103 :   for(unsigned j=0; j<6; j++) Csum+=dC_dR[j];
     312         103 :   for(unsigned j=0; j<6; j++) dC_dR[j]-=Csum/6.0;;
     313             : 
     314             : 
     315             : // qx
     316         103 :   double qx = A/sqrt(3);
     317             : 
     318             : // qx derivaties
     319         206 :   vector<Vector> dqx_dR(6);
     320         721 :   for(unsigned j=0; j<6; j++) {
     321         618 :     dqx_dR[j]=1/sqrt(3) * dA_dR[j];
     322             :   }
     323             : 
     324         103 :   Value* vqx=getPntrToComponent("qx");
     325         103 :   vqx->set(qx);
     326         103 :   setAtomsDerivatives (vqx,0, dqx_dR[0] );
     327         103 :   setAtomsDerivatives (vqx,1, dqx_dR[1] );
     328         103 :   setAtomsDerivatives (vqx,2, dqx_dR[2] );
     329         103 :   setAtomsDerivatives (vqx,3, dqx_dR[3] );
     330         103 :   setAtomsDerivatives (vqx,4, dqx_dR[4] );
     331         103 :   setAtomsDerivatives (vqx,5, dqx_dR[5] );
     332         103 :   setBoxDerivativesNoPbc(vqx);
     333             : 
     334             : // qy
     335         103 :   double qy = -B/sqrt(3);
     336             : 
     337             : // qy derivatives
     338         206 :   vector<Vector> dqy_dR(6);
     339         721 :   for(unsigned j=0; j<6; j++) {
     340         618 :     dqy_dR[j]=-1/sqrt(3) * dB_dR[j];
     341             :   }
     342             : 
     343         103 :   Value* vqy=getPntrToComponent("qy");
     344         103 :   vqy->set(qy);
     345         103 :   setAtomsDerivatives (vqy,0, dqy_dR[0] );
     346         103 :   setAtomsDerivatives (vqy,1, dqy_dR[1] );
     347         103 :   setAtomsDerivatives (vqy,2, dqy_dR[2] );
     348         103 :   setAtomsDerivatives (vqy,3, dqy_dR[3] );
     349         103 :   setAtomsDerivatives (vqy,4, dqy_dR[4] );
     350         103 :   setAtomsDerivatives (vqy,5, dqy_dR[5] );
     351         103 :   setBoxDerivativesNoPbc(vqy);
     352             : 
     353             : // qz
     354         103 :   double qz = C/sqrt(6);
     355             : 
     356             : // qz derivatives
     357         206 :   vector<Vector> dqz_dR(6);
     358         721 :   for(unsigned j=0; j<6; j++) {
     359         618 :     dqz_dR[j]=1/sqrt(6) * dC_dR[j];
     360             :   }
     361             : 
     362         103 :   Value* vqz=getPntrToComponent("qz");
     363         103 :   vqz->set(qz);
     364         103 :   setAtomsDerivatives (vqz,0, dqz_dR[0] );
     365         103 :   setAtomsDerivatives (vqz,1, dqz_dR[1] );
     366         103 :   setAtomsDerivatives (vqz,2, dqz_dR[2] );
     367         103 :   setAtomsDerivatives (vqz,3, dqz_dR[3] );
     368         103 :   setAtomsDerivatives (vqz,4, dqz_dR[4] );
     369         103 :   setAtomsDerivatives (vqz,5, dqz_dR[5] );
     370         103 :   setBoxDerivativesNoPbc(vqz);
     371             : 
     372             : 
     373             : // PHASE
     374         103 :   double phi=atan2(-A,B);
     375             : 
     376             : // PHASE DERIVATIVES
     377         206 :   vector<Vector> dphi_dR(6);
     378         721 :   for(unsigned j=0; j<6; j++) {
     379         618 :     dphi_dR[j]=1.0/(A*A+B*B) * (-B*dA_dR[j] + A*dB_dR[j]);
     380             :   }
     381             : 
     382         103 :   Value* vphi=getPntrToComponent("phi");
     383         103 :   vphi->set(phi);
     384         103 :   setAtomsDerivatives (vphi,0, dphi_dR[0] );
     385         103 :   setAtomsDerivatives (vphi,1, dphi_dR[1] );
     386         103 :   setAtomsDerivatives (vphi,2, dphi_dR[2] );
     387         103 :   setAtomsDerivatives (vphi,3, dphi_dR[3] );
     388         103 :   setAtomsDerivatives (vphi,4, dphi_dR[4] );
     389         103 :   setAtomsDerivatives (vphi,5, dphi_dR[5] );
     390         103 :   setBoxDerivativesNoPbc(vphi);
     391             : 
     392             : //  AMPLITUDE
     393         103 :   double amplitude=sqrt((2*(A*A+B*B)+C*C)/6);
     394             : 
     395             : //  AMPLITUDE DERIVATIES
     396         206 :   vector<Vector> damplitude_dR(6);
     397         721 :   for (unsigned j=0; j<6; j++) {
     398         618 :     damplitude_dR[j]=0.5*sqrt(2.0/6.0)/(sqrt(A*A+B*B+0.5*C*C)) * (2*A*dA_dR[j] + 2*B*dB_dR[j] + C*dC_dR[j]);
     399             :   }
     400             : 
     401         103 :   Value* vamplitude=getPntrToComponent("amplitude");
     402         103 :   vamplitude->set(amplitude);
     403         103 :   setAtomsDerivatives (vamplitude,0, damplitude_dR[0] );
     404         103 :   setAtomsDerivatives (vamplitude,1, damplitude_dR[1] );
     405         103 :   setAtomsDerivatives (vamplitude,2, damplitude_dR[2] );
     406         103 :   setAtomsDerivatives (vamplitude,3, damplitude_dR[3] );
     407         103 :   setAtomsDerivatives (vamplitude,4, damplitude_dR[4] );
     408         103 :   setAtomsDerivatives (vamplitude,5, damplitude_dR[5] );
     409         103 :   setBoxDerivativesNoPbc(vamplitude);
     410             : 
     411             : //  THETA
     412         103 :   double theta=acos( C / sqrt(2.*(A*A+B*B) +C*C ) );
     413             : 
     414             : //  THETA DERIVATIVES
     415         206 :   vector<Vector> dtheta_dR(6);
     416         721 :   for(unsigned j=0; j<6; j++) {
     417         618 :     dtheta_dR[j]=1.0/(3.0*sqrt(2)*amplitude*amplitude) * (C/(sqrt(A*A+B*B)) * (A*dA_dR[j] + B*dB_dR[j]) - sqrt(A*A+B*B)*dC_dR[j]);
     418             :   }
     419         103 :   Value* vtheta=getPntrToComponent("theta");
     420         103 :   vtheta->set(theta);
     421         103 :   setAtomsDerivatives (vtheta,0, dtheta_dR[0] );
     422         103 :   setAtomsDerivatives (vtheta,1, dtheta_dR[1] );
     423         103 :   setAtomsDerivatives (vtheta,2, dtheta_dR[2] );
     424         103 :   setAtomsDerivatives (vtheta,3, dtheta_dR[3] );
     425         103 :   setAtomsDerivatives (vtheta,4, dtheta_dR[4] );
     426         103 :   setAtomsDerivatives (vtheta,5, dtheta_dR[5] );
     427         206 :   setBoxDerivativesNoPbc(vtheta);
     428         103 : }
     429             : 
     430             : 
     431             : }
     432        2523 : }
     433             : 
     434             : 
     435             : 

Generated by: LCOV version 1.13