24 #include "core/PlumedMain.h"
25 #include "tools/Matrix.h"
79 enum CV_TYPE {RADIUS,
TRACE, GTPC_1, GTPC_2, GTPC_3, ASPHERICITY, ACYLINDRICITY, KAPPA2, GYRATION_3, GYRATION_2, GYRATION_1, TOT};
83 static void registerKeywords(
Keywords& keys);
85 virtual void calculate();
88 PLUMED_REGISTER_ACTION(
Gyration,
"GYRATION")
91 Colvar::registerKeywords(keys);
93 keys.add(
"atoms",
"ATOMS",
"the group of atoms that you are calculating the Gyration Tensor for");
94 keys.add(
"compulsory",
"TYPE",
"RADIUS",
"The type of calculation relative to the Gyration Tensor you want to perform");
95 keys.addFlag(
"NOT_MASS_WEIGHTED",
false,
"set the masses of all the atoms equal to one");
102 std::vector<AtomNumber>
atoms;
104 if(atoms.size()==0)
error(
"no atoms specified");
106 parseFlag(
"NOT_MASS_WEIGHTED",not_use_masses);
123 else error(
"Unknown GYRATION type");
129 case GTPC_1:
log.
printf(
" THE LARGEST PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_1);");
break;
130 case GTPC_2:
log.
printf(
" THE MIDDLE PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_2);");
break;
131 case GTPC_3:
log.
printf(
" THE SMALLEST PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_3);");
break;
134 case KAPPA2:
log.
printf(
" THE RELATIVE SHAPE ANISOTROPY (kappa^2);");
break;
139 if(
rg_type>
TRACE)
log<<
" Bibliography "<<
plumed.cite(
"Jirí Vymetal and Jirí Vondrasek, J. Phys. Chem. A 115, 11455 (2011)");
log<<
"\n";
142 for(
unsigned i=0;i<atoms.size();++i)
log.
printf(
"%d ",atoms[i].serial());
153 double d=0., rgyr=0.;
156 for(
unsigned i=0;i<3;i++)
for(
unsigned j=0;j<3;j++) gyr_tens(i,j)=0.;
175 com = com / totmass + pos0;
186 derivatives[i]=diff*
getMass(i);
202 gyr_tens[0][0]+=
getMass(i)*diff[0]*diff[0];
203 gyr_tens[1][1]+=
getMass(i)*diff[1]*diff[1];
204 gyr_tens[2][2]+=
getMass(i)*diff[2]*diff[2];
205 gyr_tens[0][1]+=
getMass(i)*diff[0]*diff[1];
206 gyr_tens[0][2]+=
getMass(i)*diff[0]*diff[2];
207 gyr_tens[1][2]+=
getMass(i)*diff[1]*diff[2];
212 gyr_tens[0][0]+=diff[0]*diff[0];
213 gyr_tens[1][1]+=diff[1]*diff[1];
214 gyr_tens[2][2]+=diff[2]*diff[2];
215 gyr_tens[0][1]+=diff[0]*diff[1];
216 gyr_tens[0][2]+=diff[0]*diff[2];
217 gyr_tens[1][2]+=diff[1]*diff[2];
226 rgyr=sqrt(rgyr/totmass);
227 double fact=1./(rgyr*totmass);
229 derivatives[i] *= fact;
238 derivatives[i] *= 4.;
246 gyr_tens[1][0] = gyr_tens[0][1];
247 gyr_tens[2][0] = gyr_tens[0][2];
248 gyr_tens[2][1] = gyr_tens[1][2];
251 std::vector<double> princ_comp(3), prefactor(3);
252 prefactor[0]=prefactor[1]=prefactor[2]=0.;
255 diagMat(gyr_tens, princ_comp, ttransf);
258 if (princ_comp[0]<princ_comp[1]){
259 double tmp=princ_comp[0]; princ_comp[0]=princ_comp[1]; princ_comp[1]=tmp;
260 for (
unsigned i=0; i<3; i++){tmp=transf[i][0]; transf[i][0]=transf[i][1]; transf[i][1]=tmp;}
262 if (princ_comp[1]<princ_comp[2]){
263 double tmp=princ_comp[1]; princ_comp[1]=princ_comp[2]; princ_comp[2]=tmp;
264 for (
unsigned i=0; i<3; i++){tmp=transf[i][1]; transf[i][1]=transf[i][2]; transf[i][2]=tmp;}
266 if (princ_comp[0]<princ_comp[1]){
267 double tmp=princ_comp[0]; princ_comp[0]=princ_comp[1]; princ_comp[1]=tmp;
268 for (
unsigned i=0; i<3; i++){tmp=transf[i][0]; transf[i][0]=transf[i][1]; transf[i][1]=tmp;}
272 det = transf[0][0]*transf[1][1]*transf[2][2]+transf[0][1]*transf[1][2]*transf[2][0]+
273 transf[0][2]*transf[1][0]*transf[2][1]-transf[0][2]*transf[1][1]*transf[2][0]-
274 transf[0][1]*transf[1][0]*transf[2][2]-transf[0][0]*transf[1][2]*transf[2][1];
277 for(
unsigned j=0;j<3;j++) transf[j][2]=-transf[j][2];
280 if(fabs(det-1.)>0.0001)
error(
"Plumed Error: Cannot diagonalize gyration tensor\n");
287 rgyr=sqrt(princ_comp[pc_index]/totmass);
288 double rm = rgyr*totmass;
289 if(rm>1e-6) prefactor[pc_index]=1.0/rm;
294 rgyr=sqrt((princ_comp[1]+princ_comp[2])/totmass);
295 double rm = rgyr*totmass;
304 rgyr=sqrt((princ_comp[0]+princ_comp[2])/totmass);
305 double rm = rgyr*totmass;
314 rgyr=sqrt((princ_comp[0]+princ_comp[1])/totmass);
315 double rm = rgyr*totmass;
324 rgyr=sqrt((princ_comp[0]-0.5*(princ_comp[1]+princ_comp[2]))/totmass);
325 double rm = rgyr*totmass;
327 prefactor[0]= 1.0/rm;
328 prefactor[1]=-0.5/rm;
329 prefactor[2]=-0.5/rm;
335 rgyr=sqrt((princ_comp[1]-princ_comp[2])/totmass);
336 double rm = rgyr*totmass;
338 prefactor[1]= 1.0/rm;
339 prefactor[2]=-1.0/rm;
345 double trace = princ_comp[0]+princ_comp[1]+princ_comp[2];
346 double tmp=princ_comp[0]*princ_comp[1]+ princ_comp[1]*princ_comp[2]+ princ_comp[0]*princ_comp[2];
347 rgyr=1.0-3*(tmp/(trace*trace));
349 prefactor[0]= -3*((princ_comp[1]+princ_comp[2])-2*tmp/trace)/(trace*trace) *2;
350 prefactor[1]= -3*((princ_comp[0]+princ_comp[2])-2*tmp/trace)/(trace*trace) *2;
351 prefactor[2]= -3*((princ_comp[0]+princ_comp[1])-2*tmp/trace)/(trace*trace) *2;
361 for(
unsigned j=0;j<3;j++) tX[j]=transf[0][j]*diff[0]+transf[1][j]*diff[1]+transf[2][j]*diff[2];
362 for(
unsigned j=0;j<3;j++) derivatives[i][j]=
getMass(i)*(prefactor[0]*transf[j][0]*tX[0]+
363 prefactor[1]*transf[j][1]*tX[1]+
364 prefactor[2]*transf[j][2]*tX[2]);
372 for(
unsigned j=0;j<3;j++) tX[j]=transf[0][j]*diff[0]+transf[1][j]*diff[1]+transf[2][j]*diff[2];
373 for(
unsigned j=0;j<3;j++) derivatives[i][j]=prefactor[0]*transf[j][0]*tX[0]+
374 prefactor[1]*transf[j][1]*tX[1]+
375 prefactor[2]*transf[j][2]*tX[2];
const Vector & getPosition(int) const
Get position of i-th atom.
void parseFlag(const std::string &key, bool &t)
Parse one keyword as boolean flag.
void setNotPeriodic()
Set your default value to have no periodicity.
Log & log
Reference to the log stream.
double modulo() const
Compute the modulo.
Class implementing fixed size vectors of doubles.
void setAtomsDerivatives(int, const Vector &)
void error(const std::string &msg) const
Crash calculation and print documentation.
void checkRead()
Check if Action was properly read.
void parseAtomList(const std::string &key, std::vector< AtomNumber > &t)
Parse a list of atoms without a numbered keyword.
void addValueWithDerivatives()
Add a value with the name label that has derivatives.
void requestAtoms(const std::vector< AtomNumber > &a)
void zero()
set it to zero
void transpose(const Matrix< T > &A, Matrix< T > &AT)
#define PLUMED_COLVAR_INIT(ao)
virtual void calculate()
Calculate an Action.
void parse(const std::string &key, T &t)
Parse one keyword as generic type.
This class holds the keywords and their documentation.
Provides the keyword GYRATION
This class is used to bring the relevant information to the Action constructor.
int printf(const char *fmt,...)
Formatted output with explicit format - a la printf.
This is the abstract base class to use for implementing new collective variables, within it there is ...
VectorGeneric< n > delta(const VectorGeneric< n > &v1, const VectorGeneric< n > &v2)
void setValue(const double &d)
Set the default value (the one without name)
int diagMat(const Matrix< T > &A, std::vector< double > &eigenvals, Matrix< double > &eigenvecs)
void setBoxDerivativesNoPbc()
Set box derivatives automatically.
unsigned getNumberOfAtoms() const
Get number of available atoms.
double getMass(int i) const
Get mass of i-th atom.