4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
34 * Green Red Orange Magenta Azure Cyan Skyblue
57 static void low_print_data(FILE *fp
,real time
,rvec x
[],int n
,atom_id
*index
,
62 fprintf(fp
," %g",time
);
67 fprintf(fp
,"\t%g",x
[index
[i
]][d
]);
69 fprintf(fp
,"\t%g",x
[i
][d
]);
73 fprintf(fp
,"\t%g",norm(x
[index
[i
]]));
75 fprintf(fp
,"\t%g",norm(x
[i
]));
81 static void average_data(rvec x
[],rvec xav
[],real
*mass
,
82 int ngrps
,int isize
[],atom_id
**index
)
89 for(g
=0; g
<ngrps
; g
++) {
94 for(i
=0; i
<isize
[g
]; i
++) {
108 xav
[g
][d
] = sum
[d
]/mtot
;
111 xav
[g
][d
] = sum
[d
]/isize
[g
];
116 static void print_data(FILE *fp
,real time
,rvec x
[],real
*mass
,bool bCom
,
117 int ngrps
,int isize
[],atom_id
**index
,bool bDim
[])
119 static rvec
*xav
=NULL
;
124 average_data(x
,xav
,mass
,ngrps
,isize
,index
);
125 low_print_data(fp
,time
,xav
,ngrps
,NULL
,bDim
);
127 low_print_data(fp
,time
,x
,isize
[0],index
[0],bDim
);
130 static void make_legend(FILE *fp
,int ngrps
,int isize
,atom_id index
[],
131 char **name
,bool bCom
,bool bMol
,bool bDim
[])
134 char *dimtxt
[] = { " X", " Y", " Z", "" };
145 for(d
=0; d
<=DIM
; d
++)
149 sprintf(leg
[j
],"mol %d%s",index
[i
]+1,dimtxt
[d
]);
151 sprintf(leg
[j
],"%s%s",name
[i
],dimtxt
[d
]);
153 sprintf(leg
[j
],"atom %d%s",index
[i
]+1,dimtxt
[d
]);
156 xvgr_legend(fp
,j
,leg
);
162 static real
ekrot(rvec x
[],rvec v
[],real mass
[],int isize
,atom_id index
[])
164 static real
**TCM
=NULL
,**L
;
165 real tm
,m0
,lxx
,lxy
,lxz
,lyy
,lyz
,lzz
,ekrot
;
183 for(i
=0; i
<isize
; i
++) {
188 for(m
=0; (m
<DIM
); m
++) {
189 xcm
[m
]+=m0
*x
[j
][m
]; /* c.o.m. position */
190 vcm
[m
]+=m0
*v
[j
][m
]; /* c.o.m. velocity */
191 acm
[m
]+=m0
*a0
[m
]; /* rotational velocity around c.o.m. */
195 for(m
=0; (m
<DIM
); m
++) {
201 lxx
=lxy
=lxz
=lyy
=lyz
=lzz
=0.0;
202 for(i
=0; i
<isize
; i
++) {
205 for(m
=0; (m
<DIM
); m
++)
206 dx
[m
]=x
[j
][m
]-xcm
[m
];
207 lxx
+=dx
[XX
]*dx
[XX
]*m0
;
208 lxy
+=dx
[XX
]*dx
[YY
]*m0
;
209 lxz
+=dx
[XX
]*dx
[ZZ
]*m0
;
210 lyy
+=dx
[YY
]*dx
[YY
]*m0
;
211 lyz
+=dx
[YY
]*dx
[ZZ
]*m0
;
212 lzz
+=dx
[ZZ
]*dx
[ZZ
]*m0
;
225 m_inv_gen(L
,DIM
,TCM
);
227 /* Compute omega (hoeksnelheid) */
230 for(m
=0; (m
<DIM
); m
++) {
231 for(n
=0; (n
<DIM
); n
++)
232 ocm
[m
]+=TCM
[m
][n
]*acm
[n
];
233 ekrot
+=0.5*ocm
[m
]*acm
[m
];
238 static real
ektrans(rvec v
[],real mass
[],int isize
,atom_id index
[])
245 for(i
=0; i
<isize
; i
++) {
248 mvcom
[d
] += mass
[j
]*v
[j
][d
];
252 return norm2(mvcom
)/(mtot
*2);
255 static real
temp(rvec v
[],real mass
[],int isize
,atom_id index
[])
260 for(i
=0; i
<isize
; i
++) {
262 ekin2
+= mass
[j
]*norm2(v
[j
]);
265 return ekin2
/(3*isize
*BOLTZ
);
268 static void remove_jump(matrix box
,int natoms
,rvec xp
[],rvec x
[])
274 hbox
[d
] = 0.5*box
[d
][d
];
275 for(i
=0; i
<natoms
; i
++)
276 for(m
=DIM
-1; m
>=0; m
--) {
277 while (x
[i
][m
]-xp
[i
][m
] <= -hbox
[m
])
279 x
[i
][d
] += box
[m
][d
];
280 while (x
[i
][m
]-xp
[i
][m
] > hbox
[m
])
282 x
[i
][d
] -= box
[m
][d
];
286 static void write_pdb_bfac(char *fname
,char *title
,t_atoms
*atoms
,matrix box
,
287 int isize
,atom_id
*index
,int nfr
,rvec
*x
,rvec
*sum
,
288 bool bDim
[],real scale_factor
)
297 fprintf(stderr
,"No frames found for %s, will not write %s\n",title
,fname
);
299 fprintf(stderr
,"Used %d frames for %s\n",nfr
,title
);
312 for(i
=0; i
<isize
; i
++)
313 svmul(scale
,x
[index
[i
]],x
[index
[i
]]);
316 for(i
=0; i
<isize
; i
++) {
319 if (bDim
[m
] || bDim
[DIM
])
320 len2
+= sqr(sum
[index
[i
]][m
]);
326 if (scale_factor
!= 0) {
327 scale
= scale_factor
;
332 scale
= 10.0/sqrt(max
);
335 fprintf(stdout
,"Maximum %s is %g on atom %d %s, res. %s %d\n",
336 title
,sqrt(max
)/nfr
,maxi
+1,*(atoms
->atomname
[maxi
]),
337 *(atoms
->resname
[atoms
->atom
[maxi
].resnr
]),
338 atoms
->atom
[maxi
].resnr
+1);
340 if (atoms
->pdbinfo
== NULL
)
341 snew(atoms
->pdbinfo
,atoms
->nr
);
343 for(i
=0; i
<isize
; i
++) {
346 if (bDim
[m
] || bDim
[DIM
])
347 len2
+= sqr(sum
[index
[i
]][m
]);
348 atoms
->pdbinfo
[index
[i
]].bfac
= sqrt(len2
)*scale
;
351 for(i
=0; i
<isize
; i
++)
352 atoms
->pdbinfo
[index
[i
]].bfac
= sum
[index
[i
]][onedim
]*scale
;
354 write_sto_conf_indexed(fname
,title
,atoms
,x
,NULL
,box
,isize
,index
);
358 int gmx_traj(int argc
,char *argv
[])
360 static char *desc
[] = {
361 "g_traj plots coordinates, velocities, forces and/or the box.",
362 "With [TT]-com[tt] the coordinates, velocities and forces are",
363 "calculated for the center of mass of each group.",
364 "When [TT]-mol[tt] is set, the numbers in the index file are",
365 "interpreted as molecule numbers and the same procedure as with",
366 "[TT]-com[tt] is used for each molecule.[PAR]",
367 "Option [TT]-ot[tt] plots the temperature of each group,",
368 "provided velocities are present in the trajectory file.",
369 "No corrections are made for constrained degrees of freedom!",
370 "This implies [TT]-com[tt].[PAR]",
371 "Options [TT]-ekt[tt] and [TT]-ekr[tt] plot the translational and",
372 "rotational kinetic energy of each group,",
373 "provided velocities are present in the trajectory file.",
374 "This implies [TT]-com[tt].[PAR]",
375 "Options [TT]-cv[tt] and [TT]-cf[tt] write the average velocities",
376 "and average forces as temperature factors to a pdb file with",
377 "the average coordinates. The temperature factors are scaled such",
378 "that the maximum is 10. The scaling can be changed with the option",
379 "[TT]-scale[tt]. To get the velocities or forces of one",
380 "frame set both [TT]-b[tt] and [TT]-e[tt] to the time of",
381 "desired frame. When averaging over frames you might need to use",
382 "the [TT]-nojump[tt] option to obtain the correct average coordinates."
384 static bool bMol
=FALSE
,bCom
=FALSE
,bNoJump
=FALSE
;
385 static bool bX
=TRUE
,bY
=TRUE
,bZ
=TRUE
,bNorm
=FALSE
;
388 { "-com", FALSE
, etBOOL
, {&bCom
},
389 "Plot data for the com of each group" },
390 { "-mol", FALSE
, etBOOL
, {&bMol
},
391 "Index contains molecule numbers iso atom numbers" },
392 { "-nojump", FALSE
, etBOOL
, {&bNoJump
},
393 "Remove jumps of atoms across the box" },
394 { "-x", FALSE
, etBOOL
, {&bX
},
395 "Plot X-component" },
396 { "-y", FALSE
, etBOOL
, {&bY
},
397 "Plot Y-component" },
398 { "-z", FALSE
, etBOOL
, {&bZ
},
399 "Plot Z-component" },
400 { "-len", FALSE
, etBOOL
, {&bNorm
},
401 "Plot vector length" },
402 { "-scale", FALSE
, etREAL
, {&scale
},
403 "Scale factor for pdb output, 0 is autoscale" }
406 FILE *outx
=NULL
,*outv
=NULL
,*outf
=NULL
,*outb
=NULL
,*outt
=NULL
;
407 FILE *outekt
=NULL
,*outekr
=NULL
;
410 char title
[STRLEN
],*indexfn
;
414 rvec
*sumxv
=NULL
,*sumv
=NULL
,*sumxf
=NULL
,*sumf
=NULL
;
418 int ngrps
,nr_vfr
,nr_ffr
;
421 atom_id
**index0
,**index
;
424 bool bTop
,bOX
,bOV
,bOF
,bOB
,bOT
,bEKT
,bEKR
,bCV
,bCF
,bDim
[4],bDum
[4];
425 char *box_leg
[6] = { "XX", "YY", "ZZ", "YX", "ZX", "ZY" };
428 { efTRX
, "-f", NULL
, ffREAD
},
429 { efTPS
, NULL
, NULL
, ffREAD
},
430 { efNDX
, NULL
, NULL
, ffOPTRD
},
431 { efXVG
, "-ox", "coord.xvg", ffOPTWR
},
432 { efXVG
, "-ov", "veloc.xvg", ffOPTWR
},
433 { efXVG
, "-of", "force.xvg", ffOPTWR
},
434 { efXVG
, "-ob", "box.xvg", ffOPTWR
},
435 { efXVG
, "-ot", "temp.xvg", ffOPTWR
},
436 { efXVG
, "-ekt","ektrans.xvg", ffOPTWR
},
437 { efXVG
, "-ekr","ekrot.xvg", ffOPTWR
},
438 { efPDB
, "-cv", "veloc.pdb", ffOPTWR
},
439 { efPDB
, "-cf", "force.pdb", ffOPTWR
}
441 #define NFILE asize(fnm)
443 CopyRight(stderr
,argv
[0]);
444 parse_common_args(&argc
,argv
,
445 PCA_CAN_TIME
| PCA_TIME_UNIT
| PCA_CAN_VIEW
| PCA_BE_NICE
,
446 NFILE
,fnm
,asize(pa
),pa
,asize(desc
),desc
,0,NULL
);
449 fprintf(stderr
,"Interpreting indexfile entries as molecules.\n"
450 "Using center of mass.\n");
452 bOX
= opt2bSet("-ox",NFILE
,fnm
);
453 bOV
= opt2bSet("-ov",NFILE
,fnm
);
454 bOF
= opt2bSet("-of",NFILE
,fnm
);
455 bOB
= opt2bSet("-ob",NFILE
,fnm
);
456 bOT
= opt2bSet("-ot",NFILE
,fnm
);
457 bEKT
= opt2bSet("-ekt",NFILE
,fnm
);
458 bEKR
= opt2bSet("-ekr",NFILE
,fnm
);
459 bCV
= opt2bSet("-cv",NFILE
,fnm
);
460 bCF
= opt2bSet("-cf",NFILE
,fnm
);
461 if (bMol
|| bOT
|| bEKT
|| bEKR
)
469 bTop
= read_tps_conf(ftp2fn(efTPS
,NFILE
,fnm
),title
,&top
,&xtop
,NULL
,topbox
,
470 bCom
&& (bOX
|| bOV
|| bOT
|| bEKT
|| bEKR
));
472 if ((bMol
|| bCV
|| bCF
) && !bTop
)
473 fatal_error(0,"Need a run input file for option -mol, -cv or -cf");
477 indexfn
= ftp2fn(efNDX
,NFILE
,fnm
);
479 indexfn
= ftp2fn_null(efNDX
,NFILE
,fnm
);
482 fprintf(stderr
,"How many groups do you want to analyze? ");
489 get_index(&(top
.atoms
),indexfn
,ngrps
,isize0
,index0
,grpname
);
492 mols
=&(top
.blocks
[ebMOLS
]);
498 for (i
=0; i
<ngrps
; i
++) {
499 isize
[i
] = atndx
[index0
[0][i
]+1] - atndx
[index0
[0][i
]];
500 snew(index
[i
],isize
[i
]);
501 for(j
=0; j
<isize
[i
]; j
++)
502 index
[i
][j
] = a
[atndx
[index0
[0][i
]]+j
];
509 snew(mass
,top
.atoms
.nr
);
510 for(i
=0; i
<top
.atoms
.nr
; i
++)
511 mass
[i
] = top
.atoms
.atom
[i
].m
;
517 flags
= flags
| TRX_READ_X
;
518 outx
= xvgropen(opt2fn("-ox",NFILE
,fnm
),
519 bCom
? "Center of mass" : "Coordinate",
520 xvgr_tlabel(),"Coordinate (nm)");
521 make_legend(outx
,ngrps
,isize0
[0],index0
[0],grpname
,bCom
,bMol
,bDim
);
524 flags
= flags
| TRX_READ_V
;
525 outv
= xvgropen(opt2fn("-ov",NFILE
,fnm
),
526 bCom
? "Center of mass velocity" : "Velocity",
527 xvgr_tlabel(),"Velocity (nm/ps)");
528 make_legend(outv
,ngrps
,isize0
[0],index0
[0],grpname
,bCom
,bMol
,bDim
);
531 flags
= flags
| TRX_READ_F
;
532 outf
= xvgropen(opt2fn("-of",NFILE
,fnm
),"Force",
533 xvgr_tlabel(),"Force (kJ mol\\S-1\\N nm\\S-1\\N)");
534 make_legend(outf
,ngrps
,isize0
[0],index0
[0],grpname
,bCom
,bMol
,bDim
);
537 outb
= xvgropen(opt2fn("-ob",NFILE
,fnm
),"Box vector elements",
538 xvgr_tlabel(),"(nm)");
540 xvgr_legend(outb
,6,box_leg
);
547 flags
= flags
| TRX_READ_V
;
548 outt
= xvgropen(opt2fn("-ot",NFILE
,fnm
),"Temperature",xvgr_tlabel(),"(K)");
549 make_legend(outt
,ngrps
,isize
[0],index
[0],grpname
,bCom
,bMol
,bDum
);
556 flags
= flags
| TRX_READ_V
;
557 outekt
= xvgropen(opt2fn("-ekt",NFILE
,fnm
),"Center of mass translation",
558 xvgr_tlabel(),"Energy (kJ mol\\S-1\\N)");
559 make_legend(outekt
,ngrps
,isize
[0],index
[0],grpname
,bCom
,bMol
,bDum
);
566 flags
= flags
| TRX_READ_X
| TRX_READ_V
;
567 outekr
= xvgropen(opt2fn("-ekr",NFILE
,fnm
),"Center of mass rotation",
568 xvgr_tlabel(),"Energy (kJ mol\\S-1\\N)");
569 make_legend(outekr
,ngrps
,isize
[0],index
[0],grpname
,bCom
,bMol
,bDum
);
572 flags
= flags
| TRX_READ_X
| TRX_READ_V
;
574 flags
= flags
| TRX_READ_X
| TRX_READ_F
;
575 if (flags
== 0 && !bOB
) {
576 fprintf(stderr
,"Please select one or more output file options\n");
580 read_first_frame(&status
,ftp2fn(efTRX
,NFILE
,fnm
),&fr
,flags
);
583 snew(sumxv
,fr
.natoms
);
584 snew(sumv
,fr
.natoms
);
587 snew(sumxf
,fr
.natoms
);
588 snew(sumf
,fr
.natoms
);
594 time
= convert_time(fr
.time
);
596 if (fr
.bX
&& bNoJump
&& fr
.bBox
) {
598 remove_jump(fr
.box
,fr
.natoms
,xp
,fr
.x
);
601 for(i
=0; i
<fr
.natoms
; i
++)
602 copy_rvec(fr
.x
[i
],xp
[i
]);
606 rm_pbc(&(top
.idef
),fr
.natoms
,fr
.box
,fr
.x
,fr
.x
);
609 print_data(outx
,time
,fr
.x
,mass
,bCom
,ngrps
,isize
,index
,bDim
);
611 print_data(outv
,time
,fr
.v
,mass
,bCom
,ngrps
,isize
,index
,bDim
);
613 print_data(outf
,time
,fr
.f
,NULL
,bCom
,ngrps
,isize
,index
,bDim
);
615 fprintf(outb
,"\t%g\t%g\t%g\t%g\t%g\t%g\t%g\n",fr
.time
,
616 fr
.box
[XX
][XX
],fr
.box
[YY
][YY
],fr
.box
[ZZ
][ZZ
],
617 fr
.box
[YY
][XX
],fr
.box
[ZZ
][XX
],fr
.box
[ZZ
][YY
]);
619 fprintf(outt
," %g",time
);
620 for(i
=0; i
<ngrps
; i
++)
621 fprintf(outt
,"\t%g",temp(fr
.v
,mass
,isize
[i
],index
[i
]));
625 fprintf(outekt
," %g",time
);
626 for(i
=0; i
<ngrps
; i
++)
627 fprintf(outekt
,"\t%g",ektrans(fr
.v
,mass
,isize
[i
],index
[i
]));
628 fprintf(outekt
,"\n");
630 if (bEKR
&& fr
.bX
&& fr
.bV
) {
631 fprintf(outekr
," %g",time
);
632 for(i
=0; i
<ngrps
; i
++)
633 fprintf(outekr
,"\t%g",ekrot(fr
.x
,fr
.v
,mass
,isize
[i
],index
[i
]));
634 fprintf(outekr
,"\n");
636 if (bCV
&& fr
.bX
&& fr
.bV
) {
637 for(i
=0; i
<fr
.natoms
; i
++)
638 rvec_inc(sumxv
[i
],fr
.x
[i
]);
639 for(i
=0; i
<fr
.natoms
; i
++)
640 rvec_inc(sumv
[i
],fr
.v
[i
]);
643 if (bCF
&& fr
.bX
&& fr
.bF
) {
644 for(i
=0; i
<fr
.natoms
; i
++)
645 rvec_inc(sumxf
[i
],fr
.x
[i
]);
646 for(i
=0; i
<fr
.natoms
; i
++)
647 rvec_inc(sumf
[i
],fr
.f
[i
]);
651 } while(read_next_frame(status
,&fr
));
657 if (bOX
) fclose(outx
);
658 if (bOV
) fclose(outv
);
659 if (bOF
) fclose(outf
);
660 if (bOB
) fclose(outb
);
661 if (bOT
) fclose(outt
);
662 if (bEKT
) fclose(outekt
);
663 if (bEKR
) fclose(outekr
);
665 if ((bCV
|| bCF
) && (nr_vfr
>1 || nr_ffr
>1) && !bNoJump
)
666 fprintf(stderr
,"WARNING: More than one frame was used for option -cv or -cf\n"
667 "If atoms jump across the box you should use the -nojump option\n");
670 write_pdb_bfac(opt2fn("-cv",NFILE
,fnm
),"average velocity",&(top
.atoms
),
671 topbox
,isize
[0],index
[0],nr_vfr
,sumxv
,sumv
,bDim
,scale
);
673 write_pdb_bfac(opt2fn("-cf",NFILE
,fnm
),"average force",&(top
.atoms
),
674 topbox
,isize
[0],index
[0],nr_ffr
,sumxf
,sumf
,bDim
,scale
);
677 view_all(NFILE
, fnm
);