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
|