LCOV - code coverage report
Current view: top level - colvar - Gyration.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 187 232 80.6 %
Date: 2025-03-25 09:33:27 Functions: 3 4 75.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             : #include "Colvar.h"
      23             : #include "core/ActionRegister.h"
      24             : #include "core/PlumedMain.h"
      25             : 
      26             : namespace PLMD {
      27             : namespace colvar {
      28             : 
      29             : //+PLUMEDOC COLVAR GYRATION
      30             : /*
      31             : Calculate the radius of gyration, or other properties related to it.
      32             : 
      33             : The radius of gyration is calculated using:
      34             : 
      35             : $$
      36             : s_{\rm Gyr}=\Big ( \frac{\sum_i^{n} w_i \vert {r}_i -{r}_{\rm COM} \vert ^2 }{\sum_i^{n} w_i} \Big)^{1/2}
      37             : $$
      38             : 
      39             : with the position of the center ${r}_{\rm COM}$ given by:
      40             : 
      41             : $$
      42             : {r}_{\rm COM}=\frac{\sum_i^{n} {r}_i\ w_i }{\sum_i^{n} w_i}
      43             : $$
      44             : 
      45             : In these expressions $r_i$ indicates the position of atom $i$ and $w_i$ is the weight for atom $i$.  The following input
      46             : shows how you can calculate the expressions for a set of atoms by using PLUMED:
      47             : 
      48             : ```plumed
      49             : w: CONSTANT VALUES=1,2,2,3,4
      50             : g: GYRATION ATOMS=1-5 TYPE=RADIUS WEIGHTS=w
      51             : PRINT ARG=g FILE=colvar
      52             : ```
      53             : 
      54             : In the above input the weights in the expressions above are set equal to the eleemnts of a constant vector, `w`.  A more common
      55             : approach is to use the masses of the atoms as in the input below:
      56             : 
      57             : ```plumed
      58             : g: GYRATION ATOMS=1-5 TYPE=RADIUS MASS_WEIGHTED
      59             : # This input is equivalent
      60             : # g: GYRATION ATOMS=1-5 TYPE=RADIUS WEIGHTS=@Masses
      61             : PRINT ARG=g FILE=colvar
      62             : ```
      63             : 
      64             : or to set all the input weights equal to one as is done in the input below;
      65             : 
      66             : ```plumed
      67             : g: GYRATION ATOMS=1-5 TYPE=RADIUS
      68             : PRINT ARG=g FILE=colvar
      69             : ```
      70             : 
      71             : Notice that in the first input above GYRATION is a shortcut and that in the second two inputs it is not.  This is because there
      72             : is a faster (non-shortcutted) version that can be used for these two more-commonplace inputs.  The shortcut input is still useful
      73             : as it allows one to do less comonplace analyses such as this one where a clustering is performed and the radius of gyration for the
      74             : largest cluster is determined.
      75             : 
      76             : ```plumed
      77             : c1: CONTACT_MATRIX GROUP=1-100 SWITCH={RATIONAL R_0=0.1 D_MAX=0.5}
      78             : dfs: DFSCLUSTERING ARG=c1
      79             : w: CLUSTER_WEIGHTS CLUSTERS=dfs CLUSTER=1
      80             : g: GYRATION ATOMS=1-100 WEIGHTS=w TYPE=RADIUS
      81             : ```
      82             : 
      83             : In calculating the gyration radius you first calculate the [GYRATION_TENSOR](GYRATION_TENSOR.md). Instad of computing the radius from this
      84             : tensor you can instead compute the trace of the tensor by using the following input:
      85             : 
      86             : ```plumed
      87             : w: CONSTANT VALUES=1,2,2,3,4
      88             : g: GYRATION ATOMS=1-5 TYPE=TRACE WEIGHTS=w
      89             : PRINT ARG=g FILE=colvar
      90             : ```
      91             : 
      92             : You can also calculate the largest, middle and smallest principal moments of the tensor:
      93             : 
      94             : ```plumed
      95             : w: CONSTANT VALUES=1,2,2,3,4
      96             : # This computes the largest principal moment
      97             : l: GYRATION ATOMS=1-5 TYPE=GTPC_1 WEIGHTS=w
      98             : # This computes the middle principal moment
      99             : m: GYRATION ATOMS=1-5 TYPE=GTPC_2 WEIGHTS=w
     100             : # This computes the smallest principal moment
     101             : s: GYRATION ATOMS=1-5 TYPE=GTPC_3 WEIGHTS=w
     102             : PRINT ARG=l,m,s FILE=colvar
     103             : ```
     104             : 
     105             : From these principal moments you can calculate the Asphericiry, Acylindricity, or the Relative Shape Anisotropy by using the following input:
     106             : 
     107             : ```plumed
     108             : w: CONSTANT VALUES=1,2,2,3,4
     109             : # This computes the Asphericiry
     110             : l: GYRATION ATOMS=1-5 TYPE=ASPHERICITY WEIGHTS=w
     111             : # This computes the Acylindricity
     112             : m: GYRATION ATOMS=1-5 TYPE=ACYLINDRICITY WEIGHTS=w
     113             : # This computes the Relative Shape Anisotropy
     114             : s: GYRATION ATOMS=1-5 TYPE=KAPPA2 WEIGHTS=w
     115             : PRINT ARG=l,m,s FILE=colvar
     116             : ```
     117             : 
     118             : Lastly, you can calculate the largest, middle and smallest principal radii of gyration by using the following input:
     119             : 
     120             : ```plumed
     121             : w: CONSTANT VALUES=1,2,2,3,4
     122             : # This computes the largest principal radius of gyration
     123             : l: GYRATION ATOMS=1-5 TYPE=RGYR_1 WEIGHTS=w
     124             : # This computes the middle principal radius of gyration
     125             : m: GYRATION ATOMS=1-5 TYPE=RGYR_2 WEIGHTS=w
     126             : # This computes the smallest principal radius of gyration
     127             : s: GYRATION ATOMS=1-5 TYPE=RGYR_3 WEIGHTS=w
     128             : PRINT ARG=l,m,s FILE=colvar
     129             : ```
     130             : 
     131             : By expanding the shortcuts in the inputs above or by reading the papers cited below you can see how these quantities are computed from the [GYRATION_TENSOR](GYRATION_TENSOR.md).
     132             : Notice, however, that as with the radius if you use the masses or a vector of ones as weights a faster implemention of this colvar that
     133             : calculates these quantities directly will be used.
     134             : 
     135             : ## A note on periodic boundary conditions
     136             : 
     137             : Calculating the radius of gyration is normally used to determine the shape of a molecule so all the specified atoms
     138             : would normally be part of the same molecule.  When computing this CV it is important to ensure that the periodic boundaries
     139             : are calculated correctly.  There are two ways that you can manage periodic boundary conditions when using this action.  The
     140             : first and simplest is to reconstruct the molecule similarly to the way that [WHOLEMOLECULES](WHOLEMOLECULES.md) operates.
     141             : This reconstruction of molecules has been done automatically since PLUMED 2.2.  If for some reason you want to turn it off
     142             : you can use the NOPBC flag.
     143             : 
     144             : An alternative approach to handling PBC is to use the PHASES keyword.  This keyword instructs PLUMED to use the PHASES option
     145             : when computing the position of the center using the [CENTER](CENTER.md) command.  Distances of atoms from this center are then
     146             : computed using PBC as usual.
     147             : 
     148             : */
     149             : //+ENDPLUMEDOC
     150             : 
     151             : class Gyration : public Colvar {
     152             : private:
     153             :   enum CV_TYPE {RADIUS, TRACE, GTPC_1, GTPC_2, GTPC_3, ASPHERICITY, ACYLINDRICITY, KAPPA2, GYRATION_3, GYRATION_2, GYRATION_1, TOT};
     154             :   int rg_type;
     155             :   bool use_masses;
     156             :   bool nopbc;
     157             :   std::vector<Vector> derivatives;
     158             : public:
     159             :   static void registerKeywords(Keywords& keys);
     160             :   explicit Gyration(const ActionOptions&);
     161             :   void calculate() override;
     162             : };
     163             : 
     164             : PLUMED_REGISTER_ACTION(Gyration,"GYRATION_FAST")
     165             : 
     166         224 : void Gyration::registerKeywords(Keywords& keys) {
     167         224 :   Colvar::registerKeywords(keys);
     168         448 :   keys.setDisplayName("GYRATION");
     169         224 :   keys.add("atoms","ATOMS","the group of atoms that you are calculating the Gyration Tensor for");
     170         224 :   keys.add("compulsory","TYPE","RADIUS","The type of calculation relative to the Gyration Tensor you want to perform");
     171         224 :   keys.addFlag("MASS_WEIGHTED",false,"set the masses of all the atoms equal to one");
     172         448 :   keys.setValueDescription("scalar","the radius of gyration");
     173         224 : }
     174             : 
     175         112 : Gyration::Gyration(const ActionOptions&ao):
     176             :   PLUMED_COLVAR_INIT(ao),
     177         112 :   use_masses(false),
     178         112 :   nopbc(false) {
     179             :   std::vector<AtomNumber> atoms;
     180         223 :   parseAtomList("ATOMS",atoms);
     181         111 :   if(atoms.size()==0) {
     182           0 :     error("no atoms specified");
     183             :   }
     184         224 :   parseFlag("MASS_WEIGHTED",use_masses);
     185             :   std::string Type;
     186         111 :   parse("TYPE",Type);
     187         111 :   parseFlag("NOPBC",nopbc);
     188         111 :   checkRead();
     189             : 
     190         111 :   if(Type=="RADIUS") {
     191          90 :     rg_type=RADIUS;
     192          21 :   } else if(Type=="TRACE") {
     193           2 :     rg_type=TRACE;
     194          19 :   } else if(Type=="GTPC_1") {
     195           2 :     rg_type=GTPC_1;
     196          17 :   } else if(Type=="GTPC_2") {
     197           2 :     rg_type=GTPC_2;
     198          15 :   } else if(Type=="GTPC_3") {
     199           2 :     rg_type=GTPC_3;
     200          13 :   } else if(Type=="ASPHERICITY") {
     201           2 :     rg_type=ASPHERICITY;
     202          11 :   } else if(Type=="ACYLINDRICITY") {
     203           2 :     rg_type=ACYLINDRICITY;
     204           9 :   } else if(Type=="KAPPA2") {
     205           2 :     rg_type=KAPPA2;
     206           7 :   } else if(Type=="RGYR_3") {
     207           2 :     rg_type=GYRATION_3;
     208           5 :   } else if(Type=="RGYR_2") {
     209           2 :     rg_type=GYRATION_2;
     210           3 :   } else if(Type=="RGYR_1") {
     211           2 :     rg_type=GYRATION_1;
     212             :   } else {
     213           1 :     error("Unknown GYRATION type");
     214             :   }
     215             : 
     216         110 :   switch(rg_type) {
     217          90 :   case RADIUS:
     218          90 :     log.printf("  GYRATION RADIUS (Rg);");
     219             :     break;
     220           2 :   case TRACE:
     221           2 :     log.printf("  TRACE OF THE GYRATION TENSOR;");
     222             :     break;
     223           2 :   case GTPC_1:
     224           2 :     log.printf("  THE LARGEST PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_1);");
     225             :     break;
     226           2 :   case GTPC_2:
     227           2 :     log.printf("  THE MIDDLE PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_2);");
     228             :     break;
     229           2 :   case GTPC_3:
     230           2 :     log.printf("  THE SMALLEST PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_3);");
     231             :     break;
     232           2 :   case ASPHERICITY:
     233           2 :     log.printf("  THE ASPHERICITY (b');");
     234             :     break;
     235           2 :   case ACYLINDRICITY:
     236           2 :     log.printf("  THE ACYLINDRICITY (c');");
     237             :     break;
     238           2 :   case KAPPA2:
     239           2 :     log.printf("  THE RELATIVE SHAPE ANISOTROPY (kappa^2);");
     240             :     break;
     241           2 :   case GYRATION_3:
     242           2 :     log.printf("  THE SMALLEST PRINCIPAL RADIUS OF GYRATION (r_g3);");
     243             :     break;
     244           2 :   case GYRATION_2:
     245           2 :     log.printf("  THE MIDDLE PRINCIPAL RADIUS OF GYRATION (r_g2);");
     246             :     break;
     247           2 :   case GYRATION_1:
     248           2 :     log.printf("  THE LARGEST PRINCIPAL RADIUS OF GYRATION (r_g1);");
     249             :     break;
     250             :   }
     251         110 :   if(rg_type>TRACE) {
     252          36 :     log<<"  Bibliography "<<plumed.cite("Jirí Vymetal and Jirí Vondrasek, J. Phys. Chem. A 115, 11455 (2011)");
     253             :   }
     254         110 :   log<<"\n";
     255             : 
     256         110 :   log.printf("  atoms involved : ");
     257        1023 :   for(unsigned i=0; i<atoms.size(); ++i) {
     258         913 :     log.printf("%d ",atoms[i].serial());
     259             :   }
     260         110 :   log.printf("\n");
     261             : 
     262         110 :   if(nopbc) {
     263           4 :     log<<"  PBC will be ignored\n";
     264             :   } else {
     265         106 :     log<<"  broken molecules will be rebuilt assuming atoms are in the proper order\n";
     266             :   }
     267             : 
     268         111 :   addValueWithDerivatives();
     269         110 :   setNotPeriodic();
     270         110 :   requestAtoms(atoms);
     271         114 : }
     272             : 
     273        1238 : void Gyration::calculate() {
     274             : 
     275        1238 :   if(!nopbc) {
     276         580 :     makeWhole();
     277             :   }
     278             : 
     279        1238 :   Vector com;
     280             :   double totmass = 0.;
     281        1238 :   if( use_masses ) {
     282           0 :     for(unsigned i=0; i<getNumberOfAtoms(); i++) {
     283           0 :       totmass+=getMass(i);
     284           0 :       com+=getMass(i)*getPosition(i);
     285             :     }
     286             :   } else {
     287        1238 :     totmass = static_cast<double>(getNumberOfAtoms());
     288       10803 :     for(unsigned i=0; i<getNumberOfAtoms(); i++) {
     289        9565 :       com+=getPosition(i);
     290             :     }
     291             :   }
     292        1238 :   com /= totmass;
     293             : 
     294        1238 :   double rgyr=0.;
     295        1238 :   derivatives.resize(getNumberOfAtoms());
     296             : 
     297        1238 :   if(rg_type==RADIUS||rg_type==TRACE) {
     298         838 :     if( use_masses ) {
     299           0 :       for(unsigned i=0; i<getNumberOfAtoms(); i++) {
     300           0 :         const Vector diff = delta( com, getPosition(i) );
     301           0 :         rgyr          += getMass(i)*diff.modulo2();
     302           0 :         derivatives[i] = diff*getMass(i);
     303             :       }
     304             :     } else {
     305        8403 :       for(unsigned i=0; i<getNumberOfAtoms(); i++) {
     306        7565 :         const Vector diff = delta( com, getPosition(i) );
     307        7565 :         rgyr          += diff.modulo2();
     308        7565 :         derivatives[i] = diff;
     309             :       }
     310             :     }
     311             :     double fact;
     312         838 :     if(rg_type==RADIUS) {
     313         708 :       rgyr = std::sqrt(rgyr/totmass);
     314         708 :       fact = 1./(rgyr*totmass);
     315             :     } else {
     316         130 :       rgyr = 2.*rgyr;
     317             :       fact = 4;
     318             :     }
     319         838 :     setValue(rgyr);
     320        8403 :     for(unsigned i=0; i<getNumberOfAtoms(); i++) {
     321        7565 :       setAtomsDerivatives(i,fact*derivatives[i]);
     322             :     }
     323         838 :     setBoxDerivativesNoPbc();
     324         838 :     return;
     325             :   }
     326             : 
     327             : 
     328         400 :   Tensor3d gyr_tens;
     329             :   //calculate gyration tensor
     330         400 :   if( use_masses ) {
     331           0 :     for(unsigned i=0; i<getNumberOfAtoms(); i++) {
     332           0 :       const Vector diff=delta( com, getPosition(i) );
     333           0 :       gyr_tens[0][0]+=getMass(i)*diff[0]*diff[0];
     334           0 :       gyr_tens[1][1]+=getMass(i)*diff[1]*diff[1];
     335           0 :       gyr_tens[2][2]+=getMass(i)*diff[2]*diff[2];
     336           0 :       gyr_tens[0][1]+=getMass(i)*diff[0]*diff[1];
     337           0 :       gyr_tens[0][2]+=getMass(i)*diff[0]*diff[2];
     338           0 :       gyr_tens[1][2]+=getMass(i)*diff[1]*diff[2];
     339             :     }
     340             :   } else {
     341        2400 :     for(unsigned i=0; i<getNumberOfAtoms(); i++) {
     342        2000 :       const Vector diff=delta( com, getPosition(i) );
     343        2000 :       gyr_tens[0][0]+=diff[0]*diff[0];
     344        2000 :       gyr_tens[1][1]+=diff[1]*diff[1];
     345        2000 :       gyr_tens[2][2]+=diff[2]*diff[2];
     346        2000 :       gyr_tens[0][1]+=diff[0]*diff[1];
     347        2000 :       gyr_tens[0][2]+=diff[0]*diff[2];
     348        2000 :       gyr_tens[1][2]+=diff[1]*diff[2];
     349             :     }
     350             :   }
     351             : 
     352             :   // first make the matrix symmetric
     353         400 :   gyr_tens[1][0] = gyr_tens[0][1];
     354         400 :   gyr_tens[2][0] = gyr_tens[0][2];
     355         400 :   gyr_tens[2][1] = gyr_tens[1][2];
     356         400 :   Tensor3d ttransf,transf;
     357         400 :   Vector princ_comp,prefactor;
     358             :   //diagonalize gyration tensor
     359         400 :   diagMatSym(gyr_tens, princ_comp, ttransf);
     360         400 :   transf=transpose(ttransf);
     361             :   //sort eigenvalues and eigenvectors
     362         400 :   if (princ_comp[0]<princ_comp[1]) {
     363             :     double tmp=princ_comp[0];
     364         400 :     princ_comp[0]=princ_comp[1];
     365         400 :     princ_comp[1]=tmp;
     366        1600 :     for (unsigned i=0; i<3; i++) {
     367        1200 :       tmp=transf[i][0];
     368        1200 :       transf[i][0]=transf[i][1];
     369        1200 :       transf[i][1]=tmp;
     370             :     }
     371             :   }
     372         400 :   if (princ_comp[1]<princ_comp[2]) {
     373             :     double tmp=princ_comp[1];
     374         400 :     princ_comp[1]=princ_comp[2];
     375         400 :     princ_comp[2]=tmp;
     376        1600 :     for (unsigned i=0; i<3; i++) {
     377        1200 :       tmp=transf[i][1];
     378        1200 :       transf[i][1]=transf[i][2];
     379        1200 :       transf[i][2]=tmp;
     380             :     }
     381             :   }
     382         400 :   if (princ_comp[0]<princ_comp[1]) {
     383             :     double tmp=princ_comp[0];
     384         400 :     princ_comp[0]=princ_comp[1];
     385         400 :     princ_comp[1]=tmp;
     386        1600 :     for (unsigned i=0; i<3; i++) {
     387        1200 :       tmp=transf[i][0];
     388        1200 :       transf[i][0]=transf[i][1];
     389        1200 :       transf[i][1]=tmp;
     390             :     }
     391             :   }
     392             :   //calculate determinant of transformation matrix
     393             :   double det = determinant(transf);
     394             :   // transformation matrix for rotation must have positive determinant, otherwise multiply one column by (-1)
     395         400 :   if(det<0) {
     396        1600 :     for(unsigned j=0; j<3; j++) {
     397        1200 :       transf[j][2]=-transf[j][2];
     398             :     }
     399         400 :     det = -det;
     400             :   }
     401         400 :   if(std::abs(det-1.)>0.0001) {
     402           0 :     error("Plumed Error: Cannot diagonalize gyration tensor\n");
     403             :   }
     404         400 :   switch(rg_type) {
     405         135 :   case GTPC_1:
     406             :   case GTPC_2:
     407             :   case GTPC_3: {
     408         135 :     int pc_index = rg_type-2; //index of principal component
     409         135 :     rgyr=std::sqrt(princ_comp[pc_index]/totmass);
     410         135 :     double rm = rgyr*totmass;
     411         135 :     if(rm>1e-6) {
     412         135 :       prefactor[pc_index]=1.0/rm;  //some parts of derivate
     413             :     }
     414             :     break;
     415             :   }
     416           0 :   case GYRATION_3: {      //the smallest principal radius of gyration
     417           0 :     rgyr=std::sqrt((princ_comp[1]+princ_comp[2])/totmass);
     418           0 :     double rm = rgyr*totmass;
     419           0 :     if (rm>1e-6) {
     420           0 :       prefactor[1]=1.0/rm;
     421           0 :       prefactor[2]=1.0/rm;
     422             :     }
     423             :     break;
     424             :   }
     425         130 :   case GYRATION_2: {     //the midle principal radius of gyration
     426         130 :     rgyr=std::sqrt((princ_comp[0]+princ_comp[2])/totmass);
     427         130 :     double rm = rgyr*totmass;
     428         130 :     if (rm>1e-6) {
     429         130 :       prefactor[0]=1.0/rm;
     430         130 :       prefactor[2]=1.0/rm;
     431             :     }
     432             :     break;
     433             :   }
     434           0 :   case GYRATION_1: {    //the largest principal radius of gyration
     435           0 :     rgyr=std::sqrt((princ_comp[0]+princ_comp[1])/totmass);
     436           0 :     double rm = rgyr*totmass;
     437           0 :     if (rm>1e-6) {
     438           0 :       prefactor[0]=1.0/rm;
     439           0 :       prefactor[1]=1.0/rm;
     440             :     }
     441             :     break;
     442             :   }
     443           5 :   case ASPHERICITY: {
     444           5 :     rgyr=std::sqrt((princ_comp[0]-0.5*(princ_comp[1]+princ_comp[2]))/totmass);
     445           5 :     double rm = rgyr*totmass;
     446           5 :     if (rm>1e-6) {
     447           5 :       prefactor[0]= 1.0/rm;
     448           5 :       prefactor[1]=-0.5/rm;
     449           5 :       prefactor[2]=-0.5/rm;
     450             :     }
     451             :     break;
     452             :   }
     453           0 :   case ACYLINDRICITY: {
     454           0 :     rgyr=std::sqrt((princ_comp[1]-princ_comp[2])/totmass);
     455           0 :     double rm = rgyr*totmass;
     456           0 :     if (rm>1e-6) {  //avoid division by zero
     457           0 :       prefactor[1]= 1.0/rm;
     458           0 :       prefactor[2]=-1.0/rm;
     459             :     }
     460             :     break;
     461             :   }
     462         130 :   case KAPPA2: { // relative shape anisotropy
     463         130 :     double trace = princ_comp[0]+princ_comp[1]+princ_comp[2];
     464         130 :     double tmp=princ_comp[0]*princ_comp[1]+ princ_comp[1]*princ_comp[2]+ princ_comp[0]*princ_comp[2];
     465         130 :     rgyr=1.0-3*(tmp/(trace*trace));
     466         130 :     if (rgyr>1e-6) {
     467         130 :       prefactor[0]= -3*((princ_comp[1]+princ_comp[2])-2*tmp/trace)/(trace*trace) *2;
     468         130 :       prefactor[1]= -3*((princ_comp[0]+princ_comp[2])-2*tmp/trace)/(trace*trace) *2;
     469         130 :       prefactor[2]= -3*((princ_comp[0]+princ_comp[1])-2*tmp/trace)/(trace*trace) *2;
     470             :     }
     471             :     break;
     472             :   }
     473             :   }
     474             : 
     475         400 :   if(use_masses) {
     476           0 :     for(unsigned i=0; i<getNumberOfAtoms(); i++) {
     477           0 :       Vector tX;
     478           0 :       const Vector diff=delta( com,getPosition(i) );
     479             :       //project atomic postional vectors to diagonalized frame
     480           0 :       for(unsigned j=0; j<3; j++) {
     481           0 :         tX[j]=transf[0][j]*diff[0]+transf[1][j]*diff[1]+transf[2][j]*diff[2];
     482             :       }
     483           0 :       for(unsigned j=0; j<3; j++)
     484           0 :         derivatives[i][j]=getMass(i)*(prefactor[0]*transf[j][0]*tX[0]+
     485           0 :                                       prefactor[1]*transf[j][1]*tX[1]+
     486           0 :                                       prefactor[2]*transf[j][2]*tX[2]);
     487           0 :       setAtomsDerivatives(i,derivatives[i]);
     488             :     }
     489             :   } else {
     490        2400 :     for(unsigned i=0; i<getNumberOfAtoms(); i++) {
     491        2000 :       Vector tX;
     492        2000 :       const Vector diff=delta( com,getPosition(i) );
     493             :       //project atomic postional vectors to diagonalized frame
     494        8000 :       for(unsigned j=0; j<3; j++) {
     495        6000 :         tX[j]=transf[0][j]*diff[0]+transf[1][j]*diff[1]+transf[2][j]*diff[2];
     496             :       }
     497        8000 :       for(unsigned j=0; j<3; j++)
     498        6000 :         derivatives[i][j]=prefactor[0]*transf[j][0]*tX[0]+
     499        6000 :                           prefactor[1]*transf[j][1]*tX[1]+
     500        6000 :                           prefactor[2]*transf[j][2]*tX[2];
     501        2000 :       setAtomsDerivatives(i,derivatives[i]);
     502             :     }
     503             :   }
     504             : 
     505         400 :   setValue(rgyr);
     506         400 :   setBoxDerivativesNoPbc();
     507             : }
     508             : 
     509             : }
     510             : }

Generated by: LCOV version 1.16