LCOV - code coverage report
Current view: top level - colvar - Gyration.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 212 228 93.0 %
Date: 2026-11-05 10:19:04 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2012-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             : #ifndef __PLUMED_colvar_Gyration_h
      23             : #define __PLUMED_colvar_Gyration_h
      24             : #include "Colvar.h"
      25             : #include "ColvarInput.h"
      26             : #include "MultiColvarTemplate.h"
      27             : #include "core/PlumedMain.h"
      28             : 
      29             : namespace PLMD {
      30             : namespace colvar {
      31             : 
      32             : template <typename T=double>
      33             : class Gyration : public Colvar {
      34             : private:
      35             : // The number of types of gyration are defined here
      36             : // The enum then contains double the number of types defined here as you can do every one of them with
      37             : // masses as weights or with unit weights
      38             :   static constexpr unsigned NUMBER_OF_GYRATION_TYPES = 11;
      39             :   enum CV_TYPE:unsigned {RADIUS=0, TRACE=1, GTPC_1=2, GTPC_2=3, GTPC_3=4, ASPHERICITY=5, ACYLINDRICITY=6, KAPPA2=7, GYRATION_3=8, GYRATION_2=9, GYRATION_1=10,
      40             :                          RADIUS_MASS=NUMBER_OF_GYRATION_TYPES+RADIUS,TRACE_MASS=NUMBER_OF_GYRATION_TYPES+TRACE,
      41             :                          GTPC_1_MASS=NUMBER_OF_GYRATION_TYPES+GTPC_1, GTPC_2_MASS=NUMBER_OF_GYRATION_TYPES+GTPC_2, GTPC_3_MASS=NUMBER_OF_GYRATION_TYPES+GTPC_3,
      42             :                          ASPHERICITY_MASS=NUMBER_OF_GYRATION_TYPES+ASPHERICITY, ACYLINDRICITY_MASS=NUMBER_OF_GYRATION_TYPES+ACYLINDRICITY, KAPPA2_MASS=NUMBER_OF_GYRATION_TYPES+KAPPA2,
      43             :                          GYRATION_3_MASS=NUMBER_OF_GYRATION_TYPES+GYRATION_3, GYRATION_2_MASS=NUMBER_OF_GYRATION_TYPES+GYRATION_2, GYRATION_1_MASS=NUMBER_OF_GYRATION_TYPES+GYRATION_1
      44             :                         } rg_type{RADIUS};
      45             :   bool nopbc;
      46             :   std::vector<T> value;
      47             :   std::vector<T> derivs;
      48             : public:
      49             :   //move this on top of the class so that the two vectors above will know what precision is
      50             :   using precision = T;
      51             :   static void registerKeywords(Keywords& keys);
      52             :   explicit Gyration(const ActionOptions&);
      53             :   static void parseAtomList( const int& num,
      54             :                              std::vector<AtomNumber>& t,
      55             :                              ActionAtomistic* aa );
      56             :   static unsigned getModeAndSetupValues( ActionWithValue* av );
      57             :   void calculate() override;
      58             :   static void calculateCV( const ColvarInput<T>& cvin, ColvarOutput<T>& cvout );
      59             : };
      60             : 
      61             : template <typename T>
      62         290 : void Gyration<T>::registerKeywords(Keywords& keys) {
      63         290 :   Colvar::registerKeywords(keys);
      64         580 :   keys.setDisplayName("GYRATION");
      65         290 :   keys.add("atoms","ATOMS","the group of atoms that you are calculating the Gyration Tensor for");
      66         290 :   keys.add("compulsory","TYPE","RADIUS","The type of calculation relative to the Gyration Tensor you want to perform");
      67         290 :   keys.addFlag("MASS_WEIGHTED",false,"use the masses of the atoms as the weights when calculating the gyration tensor");
      68         290 :   keys.add("hidden","NO_ACTION_LOG","suppresses printing from action on the log");
      69         580 :   keys.setValueDescription("scalar","the radius of gyration");
      70         290 : }
      71             : 
      72             : template <typename T>
      73         141 : Gyration<T>::Gyration(const ActionOptions&ao):
      74             :   PLUMED_COLVAR_INIT(ao),
      75         141 :   nopbc(false),
      76         141 :   value(1) {
      77         141 :   std::vector<AtomNumber> atoms;
      78         141 :   parseAtomList(-1,atoms,this);
      79         141 :   if(atoms.size()==0) {
      80           1 :     error("no atoms specified");
      81             :   }
      82             : 
      83         140 :   parseFlag("NOPBC",nopbc);
      84             : 
      85         140 :   rg_type = static_cast<CV_TYPE>( getModeAndSetupValues(this) );
      86         139 :   checkRead();
      87             : 
      88         139 :   log.printf("  atoms involved : ");
      89        1255 :   for(unsigned i=0; i<atoms.size(); ++i) {
      90        1116 :     log.printf("%d ",atoms[i].serial());
      91             :   }
      92         139 :   log.printf("\n");
      93             : 
      94         139 :   if(nopbc) {
      95           7 :     log<<"  PBC will be ignored\n";
      96             :   } else {
      97         132 :     log<<"  broken molecules will be rebuilt assuming atoms are in the proper order\n";
      98             :   }
      99             : 
     100         139 :   requestAtoms(atoms);
     101         145 : }
     102             : 
     103             : template <typename T>
     104         145 : void Gyration<T>::parseAtomList( const int& num,
     105             :                                  std::vector<AtomNumber>& t,
     106             :                                  ActionAtomistic* aa ) {
     107         145 :   aa->parseAtomList("ATOMS",num,t);
     108         145 : }
     109             : 
     110             : template <typename T>
     111         141 : unsigned Gyration<T>::getModeAndSetupValues( ActionWithValue* av ) {
     112             :   bool use_masses;
     113         282 :   av->parseFlag("MASS_WEIGHTED",use_masses);
     114             :   std::string Type;
     115         141 :   av->parse("TYPE",Type);
     116             :   unsigned rg_type;
     117             : 
     118         141 :   if(Type=="RADIUS") {
     119             :     rg_type=CV_TYPE::RADIUS;
     120          41 :   } else if(Type=="TRACE") {
     121             :     rg_type=CV_TYPE::TRACE;
     122          37 :   } else if(Type=="GTPC_1") {
     123             :     rg_type=CV_TYPE::GTPC_1;
     124          33 :   } else if(Type=="GTPC_2") {
     125             :     rg_type=CV_TYPE::GTPC_2;
     126          29 :   } else if(Type=="GTPC_3") {
     127             :     rg_type=CV_TYPE::GTPC_3;
     128          25 :   } else if(Type=="ASPHERICITY") {
     129             :     rg_type=CV_TYPE::ASPHERICITY;
     130          21 :   } else if(Type=="ACYLINDRICITY") {
     131             :     rg_type=CV_TYPE::ACYLINDRICITY;
     132          17 :   } else if(Type=="KAPPA2") {
     133             :     rg_type=CV_TYPE::KAPPA2;
     134          13 :   } else if(Type=="RGYR_3") {
     135             :     rg_type=CV_TYPE::GYRATION_3;
     136           9 :   } else if(Type=="RGYR_2") {
     137             :     rg_type=CV_TYPE::GYRATION_2;
     138           5 :   } else if(Type=="RGYR_1") {
     139             :     rg_type=CV_TYPE::GYRATION_1;
     140             :   } else {
     141           1 :     av->error("Unknown GYRATION type");
     142             :   }
     143         140 :   if( use_masses ) {
     144          22 :     rg_type=static_cast<CV_TYPE>( rg_type + NUMBER_OF_GYRATION_TYPES );
     145          22 :     av->log.printf("  computing mass weighted averages \n");
     146             :   } else {
     147         118 :     av->log.printf("  atomic positions all have unit weights in averages \n");
     148             :   }
     149             : 
     150         140 :   switch(rg_type) {
     151         100 :   case CV_TYPE::RADIUS:
     152             :   case CV_TYPE::RADIUS_MASS:
     153         100 :     av->log.printf("  GYRATION RADIUS (Rg);");
     154             :     break;
     155           4 :   case CV_TYPE::TRACE:
     156             :   case CV_TYPE::TRACE_MASS:
     157           4 :     av->log.printf("  TRACE OF THE GYRATION TENSOR;");
     158             :     break;
     159           4 :   case CV_TYPE::GTPC_1:
     160             :   case CV_TYPE::GTPC_1_MASS:
     161           4 :     av->log.printf("  THE LARGEST PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_1);");
     162             :     break;
     163           4 :   case CV_TYPE::GTPC_2:
     164             :   case CV_TYPE::GTPC_2_MASS:
     165           4 :     av->log.printf("  THE MIDDLE PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_2);");
     166             :     break;
     167           4 :   case CV_TYPE::GTPC_3:
     168             :   case CV_TYPE::GTPC_3_MASS:
     169           4 :     av->log.printf("  THE SMALLEST PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_3);");
     170             :     break;
     171           4 :   case CV_TYPE::ASPHERICITY:
     172             :   case CV_TYPE::ASPHERICITY_MASS:
     173           4 :     av->log.printf("  THE ASPHERICITY (b');");
     174             :     break;
     175           4 :   case CV_TYPE::ACYLINDRICITY:
     176             :   case CV_TYPE::ACYLINDRICITY_MASS:
     177           4 :     av->log.printf("  THE ACYLINDRICITY (c');");
     178             :     break;
     179           4 :   case CV_TYPE::KAPPA2:
     180             :   case CV_TYPE::KAPPA2_MASS:
     181           4 :     av->log.printf("  THE RELATIVE SHAPE ANISOTROPY (kappa^2);");
     182             :     break;
     183           4 :   case CV_TYPE::GYRATION_3:
     184             :   case CV_TYPE::GYRATION_3_MASS:
     185           4 :     av->log.printf("  THE SMALLEST PRINCIPAL RADIUS OF GYRATION (r_g3);");
     186             :     break;
     187           4 :   case CV_TYPE::GYRATION_2:
     188             :   case CV_TYPE::GYRATION_2_MASS:
     189           4 :     av->log.printf("  THE MIDDLE PRINCIPAL RADIUS OF GYRATION (r_g2);");
     190             :     break;
     191           4 :   case CV_TYPE::GYRATION_1:
     192             :   case CV_TYPE::GYRATION_1_MASS:
     193           4 :     av->log.printf("  THE LARGEST PRINCIPAL RADIUS OF GYRATION (r_g1);");
     194             :     break;
     195             :   }
     196         140 :   av->log<<"\n";
     197         141 :   av->addValueWithDerivatives();
     198         140 :   av->setNotPeriodic();
     199         140 :   return rg_type;
     200             : }
     201             : 
     202             : template <typename T>
     203        1962 : void Gyration<T>::calculate() {
     204             : 
     205        1962 :   if(!nopbc) {
     206        1171 :     makeWhole();
     207             :   }
     208             :   using CVInput= ColvarInput<double>;
     209             :   using CVOutput=ColvarOutput<double>;
     210        1962 :   auto cvout =  CVOutput::createColvarOutput(value, derivs, this);
     211        1962 :   Gyration<double>::calculateCV( CVInput::createColvarInput( rg_type, getPositions(), this ), cvout );
     212       17510 :   for(unsigned i=0; i<getNumberOfAtoms(); ++i) {
     213       15548 :     setAtomsDerivatives(i,cvout.getAtomDerivatives(0,i) );
     214             :   }
     215        1962 :   setBoxDerivatives(cvout.virial[0]);
     216        1962 :   setValue           (value[0]);
     217        1962 : }
     218             : 
     219             : template <typename T>
     220        1992 : void Gyration<T>::calculateCV( const ColvarInput<T>& cvin, ColvarOutput<T>& cvout ) {
     221             : 
     222             :   VectorTyped<T,3> com;
     223             :   T totmass = 0.;
     224        1992 :   if( cvin.mode>=NUMBER_OF_GYRATION_TYPES ) {
     225        3960 :     for(unsigned i=0; i<cvin.pos.size(); i++) {
     226        3300 :       totmass+=cvin.mass[i];
     227        3300 :       com+=cvin.mass[i]*VectorTyped<T,3>(cvin.pos[i][0],cvin.pos[i][1],cvin.pos[i][2]);
     228             :     }
     229             :   } else {
     230        1332 :     totmass = static_cast<T>(cvin.pos.size());
     231       13760 :     for(unsigned i=0; i<cvin.pos.size(); i++) {
     232       12428 :       com+=VectorTyped<T,3>(cvin.pos[i][0],cvin.pos[i][1],cvin.pos[i][2]);
     233             :     }
     234             :   }
     235             :   com /= totmass;
     236             : 
     237             :   T rgyr=0.;
     238             : 
     239        1992 :   if(cvin.mode==CV_TYPE::RADIUS||cvin.mode==CV_TYPE::TRACE||cvin.mode==CV_TYPE::RADIUS_MASS||cvin.mode==CV_TYPE::TRACE_MASS) {
     240        1192 :     if( cvin.mode>=NUMBER_OF_GYRATION_TYPES ) {
     241        1560 :       for(unsigned i=0; i<cvin.pos.size(); i++) {
     242        1300 :         auto diff = delta( com, VectorTyped<T,3>(cvin.pos[i][0],cvin.pos[i][1],cvin.pos[i][2]) );
     243        1300 :         rgyr          += cvin.mass[i]*diff.modulo2();
     244             :         cvout.derivs[0][i] = cvin.mass[i]*diff;
     245             :       }
     246             :     } else {
     247       11360 :       for(unsigned i=0; i<cvin.pos.size(); i++) {
     248       10428 :         const VectorTyped<T,3> diff = delta( com, VectorTyped<T,3>(cvin.pos[i][0],cvin.pos[i][1],cvin.pos[i][2]) );
     249       10428 :         rgyr          += diff.modulo2();
     250             :         cvout.derivs[0][i] = diff;
     251             :       }
     252             :     }
     253             :     T fact;
     254        1192 :     if(cvin.mode==CV_TYPE::RADIUS||cvin.mode==CV_TYPE::RADIUS_MASS) {
     255         932 :       rgyr = std::sqrt(rgyr/totmass);
     256         932 :       fact = 1./(rgyr*totmass);
     257             :     } else {
     258         260 :       rgyr = 2.*rgyr;
     259             :       fact = 4;
     260             :     }
     261        1192 :     cvout.values[0]=rgyr;
     262       12920 :     for(unsigned i=0; i<cvin.pos.size(); i++) {
     263       46912 :       for(unsigned j=0; j<3; ++j) {
     264       35184 :         cvout.derivs[0][i][j] = fact*cvout.derivs[0][i][j];
     265             :       }
     266             :     }
     267        1192 :     ColvarInput<T>::setBoxDerivativesNoPbc( cvin, cvout );
     268        1192 :     return;
     269             :   }
     270             : 
     271             : 
     272         800 :   TensorTyped<T,3,3> gyr_tens;
     273             :   //calculate gyration tensor
     274         800 :   if( cvin.mode>=NUMBER_OF_GYRATION_TYPES ) {
     275        2400 :     for(unsigned i=0; i<cvin.pos.size(); i++) {
     276        2000 :       const VectorTyped<T,3> diff=delta( com, VectorTyped<T,3>(cvin.pos[i][0],cvin.pos[i][1],cvin.pos[i][2]) );
     277        2000 :       gyr_tens[0][0]+=cvin.mass[i]*diff[0]*diff[0];
     278        2000 :       gyr_tens[1][1]+=cvin.mass[i]*diff[1]*diff[1];
     279        2000 :       gyr_tens[2][2]+=cvin.mass[i]*diff[2]*diff[2];
     280        2000 :       gyr_tens[0][1]+=cvin.mass[i]*diff[0]*diff[1];
     281        2000 :       gyr_tens[0][2]+=cvin.mass[i]*diff[0]*diff[2];
     282        2000 :       gyr_tens[1][2]+=cvin.mass[i]*diff[1]*diff[2];
     283             :     }
     284             :   } else {
     285        2400 :     for(unsigned i=0; i<cvin.pos.size(); i++) {
     286        2000 :       const VectorTyped<T,3> diff=delta( com, VectorTyped<T,3>(cvin.pos[i][0],cvin.pos[i][1],cvin.pos[i][2]) );
     287        2000 :       gyr_tens[0][0]+=diff[0]*diff[0];
     288        2000 :       gyr_tens[1][1]+=diff[1]*diff[1];
     289        2000 :       gyr_tens[2][2]+=diff[2]*diff[2];
     290        2000 :       gyr_tens[0][1]+=diff[0]*diff[1];
     291        2000 :       gyr_tens[0][2]+=diff[0]*diff[2];
     292        2000 :       gyr_tens[1][2]+=diff[1]*diff[2];
     293             :     }
     294             :   }
     295             : 
     296             :   // first make the matrix symmetric
     297         800 :   gyr_tens[1][0] = gyr_tens[0][1];
     298         800 :   gyr_tens[2][0] = gyr_tens[0][2];
     299         800 :   gyr_tens[2][1] = gyr_tens[1][2];
     300         800 :   TensorTyped<T,3,3> ttransf,transf;
     301         800 :   VectorTyped<T,3> princ_comp,prefactor;
     302             :   //diagonalize gyration tensor
     303         800 :   diagMatSym(gyr_tens, princ_comp, ttransf);
     304         800 :   transf=transpose(ttransf);
     305             :   //sort eigenvalues and eigenvectors
     306         800 :   if (princ_comp[0]<princ_comp[1]) {
     307             :     T tmp=princ_comp[0];
     308         800 :     princ_comp[0]=princ_comp[1];
     309         800 :     princ_comp[1]=tmp;
     310        3200 :     for (unsigned i=0; i<3; i++) {
     311        2400 :       tmp=transf[i][0];
     312        2400 :       transf[i][0]=transf[i][1];
     313        2400 :       transf[i][1]=tmp;
     314             :     }
     315             :   }
     316         800 :   if (princ_comp[1]<princ_comp[2]) {
     317             :     T tmp=princ_comp[1];
     318         800 :     princ_comp[1]=princ_comp[2];
     319         800 :     princ_comp[2]=tmp;
     320        3200 :     for (unsigned i=0; i<3; i++) {
     321        2400 :       tmp=transf[i][1];
     322        2400 :       transf[i][1]=transf[i][2];
     323        2400 :       transf[i][2]=tmp;
     324             :     }
     325             :   }
     326         800 :   if (princ_comp[0]<princ_comp[1]) {
     327             :     T tmp=princ_comp[0];
     328         800 :     princ_comp[0]=princ_comp[1];
     329         800 :     princ_comp[1]=tmp;
     330        3200 :     for (unsigned i=0; i<3; i++) {
     331        2400 :       tmp=transf[i][0];
     332        2400 :       transf[i][0]=transf[i][1];
     333        2400 :       transf[i][1]=tmp;
     334             :     }
     335             :   }
     336             :   //calculate determinant of transformation matrix
     337             :   T det = determinant(transf);
     338             :   // transformation matrix for rotation must have positive determinant, otherwise multiply one column by (-1)
     339         800 :   if(det<0) {
     340        3200 :     for(unsigned j=0; j<3; j++) {
     341        2400 :       transf[j][2]=-transf[j][2];
     342             :     }
     343         800 :     det = -det;
     344             :   }
     345         800 :   if(std::abs(det-1.)>0.0001) {
     346           0 :     plumed_merror("Plumed Error: Cannot diagonalize gyration tensor\n");
     347             :   }
     348         800 :   switch(cvin.mode) {
     349             :   case RADIUS:
     350             :   case RADIUS_MASS:
     351             :   case TRACE:
     352             :   case TRACE_MASS: {
     353             :     break;
     354             :   }
     355         270 :   case GTPC_1:
     356             :   case GTPC_2:
     357             :   case GTPC_3:
     358             :   case GTPC_1_MASS:
     359             :   case GTPC_2_MASS:
     360             :   case GTPC_3_MASS: {
     361         270 :     unsigned pc_index = cvin.mode-2; //index of principal component
     362         270 :     if( pc_index>=NUMBER_OF_GYRATION_TYPES ) {
     363         135 :       pc_index = pc_index - NUMBER_OF_GYRATION_TYPES;
     364             :     }
     365         270 :     rgyr=std::sqrt(princ_comp[pc_index]/totmass);
     366         270 :     T rm = rgyr*totmass;
     367         270 :     if(rm>1e-6) {
     368         270 :       prefactor[pc_index]=1.0/rm;  //some parts of derivate
     369             :     }
     370             :     break;
     371             :   }
     372             :   case GYRATION_3:
     373             :   case GYRATION_3_MASS: {      //the smallest principal radius of gyration
     374           0 :     rgyr=std::sqrt((princ_comp[1]+princ_comp[2])/totmass);
     375           0 :     T rm = rgyr*totmass;
     376           0 :     if (rm>1e-6) {
     377           0 :       prefactor[1]=1.0/rm;
     378           0 :       prefactor[2]=1.0/rm;
     379             :     }
     380             :     break;
     381             :   }
     382             :   case GYRATION_2:
     383             :   case GYRATION_2_MASS: {     //the midle principal radius of gyration
     384         260 :     rgyr=std::sqrt((princ_comp[0]+princ_comp[2])/totmass);
     385         260 :     T rm = rgyr*totmass;
     386         260 :     if (rm>1e-6) {
     387         260 :       prefactor[0]=1.0/rm;
     388         260 :       prefactor[2]=1.0/rm;
     389             :     }
     390             :     break;
     391             :   }
     392             :   case GYRATION_1:
     393             :   case GYRATION_1_MASS: {    //the largest principal radius of gyration
     394           0 :     rgyr=std::sqrt((princ_comp[0]+princ_comp[1])/totmass);
     395           0 :     T rm = rgyr*totmass;
     396           0 :     if (rm>1e-6) {
     397           0 :       prefactor[0]=1.0/rm;
     398           0 :       prefactor[1]=1.0/rm;
     399             :     }
     400             :     break;
     401             :   }
     402             :   case ASPHERICITY:
     403             :   case ASPHERICITY_MASS: {
     404          10 :     rgyr=std::sqrt((princ_comp[0]-0.5*(princ_comp[1]+princ_comp[2]))/totmass);
     405          10 :     T rm = rgyr*totmass;
     406          10 :     if (rm>1e-6) {
     407          10 :       prefactor[0]= 1.0/rm;
     408          10 :       prefactor[1]=-0.5/rm;
     409          10 :       prefactor[2]=-0.5/rm;
     410             :     }
     411             :     break;
     412             :   }
     413             :   case ACYLINDRICITY:
     414             :   case ACYLINDRICITY_MASS: {
     415           0 :     rgyr=std::sqrt((princ_comp[1]-princ_comp[2])/totmass);
     416           0 :     T rm = rgyr*totmass;
     417           0 :     if (rm>1e-6) {  //avoid division by zero
     418           0 :       prefactor[1]= 1.0/rm;
     419           0 :       prefactor[2]=-1.0/rm;
     420             :     }
     421             :     break;
     422             :   }
     423             :   case KAPPA2:
     424             :   case KAPPA2_MASS: { // relative shape anisotropy
     425         260 :     T trace = princ_comp[0]+princ_comp[1]+princ_comp[2];
     426         260 :     T tmp=princ_comp[0]*princ_comp[1]+ princ_comp[1]*princ_comp[2]+ princ_comp[0]*princ_comp[2];
     427         260 :     rgyr=1.0-3*(tmp/(trace*trace));
     428         260 :     if (rgyr>1e-6) {
     429         260 :       prefactor[0]= -3*((princ_comp[1]+princ_comp[2])-2*tmp/trace)/(trace*trace) *2;
     430         260 :       prefactor[1]= -3*((princ_comp[0]+princ_comp[2])-2*tmp/trace)/(trace*trace) *2;
     431         260 :       prefactor[2]= -3*((princ_comp[0]+princ_comp[1])-2*tmp/trace)/(trace*trace) *2;
     432             :     }
     433             :     break;
     434             :   }
     435             :   }
     436             : 
     437         800 :   if( cvin.mode>=NUMBER_OF_GYRATION_TYPES ) {
     438        2400 :     for(unsigned i=0; i<cvin.pos.size(); i++) {
     439        2000 :       VectorTyped<T,3> tX;
     440        2000 :       const VectorTyped<T,3> diff=delta( com,VectorTyped<T,3>(cvin.pos[i][0],cvin.pos[i][1],cvin.pos[i][2]) );
     441             :       //project atomic positional vectors to diagonalized frame
     442        8000 :       for(unsigned j=0; j<3; j++) {
     443        6000 :         tX[j]=transf[0][j]*diff[0]+transf[1][j]*diff[1]+transf[2][j]*diff[2];
     444             :       }
     445        8000 :       for(unsigned j=0; j<3; j++)
     446        6000 :         cvout.derivs[0][i][j]=cvin.mass[i]*(prefactor[0]*transf[j][0]*tX[0]+
     447        6000 :                                             prefactor[1]*transf[j][1]*tX[1]+
     448        6000 :                                             prefactor[2]*transf[j][2]*tX[2]);
     449             :     }
     450             :   } else {
     451        2400 :     for(unsigned i=0; i<cvin.pos.size(); i++) {
     452        2000 :       VectorTyped<T,3> tX;
     453        2000 :       const VectorTyped<T,3> diff=delta( com, VectorTyped<T,3>(cvin.pos[i][0],cvin.pos[i][1],cvin.pos[i][2]) );
     454             :       //project atomic positional vectors to diagonalized frame
     455        8000 :       for(unsigned j=0; j<3; j++) {
     456        6000 :         tX[j]=transf[0][j]*diff[0]+transf[1][j]*diff[1]+transf[2][j]*diff[2];
     457             :       }
     458        8000 :       for(unsigned j=0; j<3; j++)
     459        6000 :         cvout.derivs[0][i][j]=prefactor[0]*transf[j][0]*tX[0]+
     460        6000 :                               prefactor[1]*transf[j][1]*tX[1]+
     461        6000 :                               prefactor[2]*transf[j][2]*tX[2];
     462             :     }
     463             :   }
     464             : 
     465         800 :   cvout.values[0]=rgyr;
     466         800 :   ColvarInput<T>::setBoxDerivativesNoPbc( cvin, cvout );
     467             : }
     468             : 
     469             : }
     470             : }
     471             : #endif

Generated by: LCOV version 1.16