f49a8745308563d788d45f110d2355ad6b184306
[alexxy/gromacs.git] / src / ngmx / manager.c
1 /*
2  * $Id$
3  * 
4  *       This source code is part of
5  * 
6  *        G   R   O   M   A   C   S
7  * 
8  * GROningen MAchine for Chemical Simulations
9  * 
10  *               VERSION 2.0
11  * 
12  * Copyright (c) 1991-1999
13  * BIOSON Research Institute, Dept. of Biophysical Chemistry
14  * University of Groningen, The Netherlands
15  * 
16  * Please refer to:
17  * GROMACS: A message-passing parallel molecular dynamics implementation
18  * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19  * Comp. Phys. Comm. 91, 43-56 (1995)
20  * 
21  * Also check out our WWW page:
22  * http://md.chem.rug.nl/~gmx
23  * or e-mail to:
24  * gromacs@chem.rug.nl
25  * 
26  * And Hey:
27  * Great Red Oystrich Makes All Chemists Sane
28  */
29 static char *SRCID_manager_c = "$Id$";
30
31 #include <sysstuff.h>
32 #include <string.h>
33 #include <smalloc.h>
34 #include <ctype.h>
35 #include <typedefs.h>
36 #include <smalloc.h>
37 #include <tpxio.h>
38 #include <macros.h>
39 #include <maths.h>
40 #include <atomprop.h>
41 #include <names.h>
42 #include "manager.h"
43 #include "futil.h"
44 #include "pbc.h"
45 #include "nmol.h"
46 #include "copyrite.h"
47 #include "gstat.h"
48 #include "vec.h"
49 #include "statutil.h"
50 #include "string2.h"
51
52 static void add_object(t_manager *man,eObject eO,atom_id ai,atom_id aj)
53 {
54   srenew(man->obj,++man->nobj);
55   man->obj[man->nobj-1].eO    = eO;
56   man->obj[man->nobj-1].eV    = eVNormal;
57   man->obj[man->nobj-1].color = WHITE;
58   man->obj[man->nobj-1].ai    = ai;
59   man->obj[man->nobj-1].aj    = aj;
60   man->obj[man->nobj-1].z     = 0.0;
61 }
62
63 static void add_bonds(t_manager *man,t_functype func[],
64                       t_ilist *b,bool bB[])
65 {
66   bool    *bH=man->bHydro;
67   t_iatom *ia;
68   t_iatom type,ai,aj,ak;
69   int     i,delta,ftype;
70   
71 #ifdef DEBUG
72   fprintf(stderr,"Going to make bonds from an ilist with %d entries\n",b->nr);
73 #endif
74   ia=b->iatoms;
75   for(i=0; (i<b->nr); ) {
76     type  = ia[0];
77     ai    = ia[1];
78     ftype = func[type];
79     delta = interaction_function[ftype].nratoms;
80     
81     if (ftype == F_SETTLE) {
82       aj=ai+1;
83       ak=ai+2;
84       bB[ai]=bB[aj]=bB[ak]=TRUE;
85       add_object(man,eOHBond,ai,aj);
86       add_object(man,eOHBond,ai,ak);
87     }
88     else if ( interaction_function[ftype].flags & IF_CONNECT ) {
89       aj=ia[2];
90 #ifdef DEBUG
91       fprintf(stderr,"Adding bond from %d to %d\n",ai,aj);
92 #endif
93       bB[ai]=bB[aj]=TRUE;
94       if (!(bH[ai] == bH[aj])) 
95         add_object(man,eOHBond,ai,aj);
96       else if (!bH[ai] && !bH[aj]) 
97         add_object(man,eOBond,ai,aj);
98     }
99 #ifdef DEBUG
100     fprintf(stderr,"Type: %5d, delta: %5d\n",type,delta);
101 #endif
102     ia += delta+1;
103     i  += delta+1;
104   }
105 }
106
107 static void add_bpl(t_manager *man,t_idef *idef,bool bB[])
108 {
109   add_bonds(man,idef->functype,&idef->il[F_BONDS],bB);
110   add_bonds(man,idef->functype,&idef->il[F_G96BONDS],bB);
111   add_bonds(man,idef->functype,&idef->il[F_MORSE],bB);
112   add_bonds(man,idef->functype,&idef->il[F_CUBICBONDS],bB);
113   add_bonds(man,idef->functype,&idef->il[F_CONNBONDS],bB);
114   add_bonds(man,idef->functype,&idef->il[F_SHAKE],bB);
115   add_bonds(man,idef->functype,&idef->il[F_SETTLE],bB);
116 }
117  
118 static atom_id which_atom(t_manager *man,int x, int y)
119 {
120 #define DELTA 5
121   int i;
122   iv2 *ix=man->ix;
123
124   for(i=0; (i<man->natom); i++) {
125     if ((abs(ix[i][XX]-x) < DELTA) && (abs(ix[i][YY]-y) < DELTA)) {
126       if (man->bVis[i]) 
127         return (atom_id) i;
128     }
129   }
130   return NO_ATID;
131 }
132
133 static void do_label(t_x11 *x11,t_manager *man,int x,int y,bool bSet)
134 {
135   atom_id ai;
136   unsigned long   col;
137
138   if ((ai=which_atom(man,x,y)) != NO_ATID) {
139     x=man->ix[ai][XX];
140     y=man->ix[ai][YY];
141     if (bSet && !man->bLabel[ai]) {
142       col=WHITE;
143       man->bLabel[ai]=TRUE;
144     }
145     else if (!bSet && man->bLabel[ai]) {
146       col=BLUE;
147       man->bLabel[ai]=FALSE;
148     }
149     else
150       return;
151     XSetForeground(x11->disp,x11->gc,col);
152     XDrawString(x11->disp,man->molw->wd.self,x11->gc,x+2,y-2,man->szLab[ai],
153                 strlen(man->szLab[ai]));
154     XSetForeground(x11->disp,x11->gc,x11->fg);
155   }
156 }
157
158 static void show_label(t_x11 *x11,t_manager *man,int x,int y)
159 {
160   do_label(x11,man,x,y,TRUE);
161 }
162
163 static void hide_label(t_x11 *x11,t_manager *man,int x,int y)
164 {
165   do_label(x11,man,x,y,FALSE);
166 }
167
168 void set_file(t_x11 *x11,t_manager *man,char *trajectory,char *status)
169 {
170   char         buf[256];
171   t_tpxheader  sh;
172   t_atoms      *at;
173   bool         *bB;
174   int          i,idum;
175   real         rdum;
176
177   read_tpxheader(status,&sh);
178   snew(man->ix,sh.natoms);
179   snew(man->zz,sh.natoms);
180   snew(man->col,sh.natoms);
181   snew(man->size,sh.natoms);
182   snew(man->vdw,sh.natoms);
183   snew(man->bLabel,sh.natoms);
184   snew(man->bVis,sh.natoms);
185   for(i=0; (i<sh.natoms); i++)
186     man->bVis[i]=FALSE;
187
188   man->bPbc=FALSE;
189
190   snew(man->szLab,sh.natoms);
191   snew(man->bHydro,sh.natoms);
192   snew(bB,sh.natoms);
193   read_tpx(status,&(man->step),&(man->time),&rdum,NULL,man->box,
194            &man->natom,NULL,NULL,NULL,&man->top);
195   
196   man->natom=
197     read_first_x(&man->status,trajectory,&(man->time),&(man->x),man->box);
198   man->trajfile=strdup(trajectory);
199   if (man->natom > man->top.atoms.nr)
200     fatal_error(0,"Topology %s (%d atoms) and trajectory %s (%d atoms) "
201                 "do not match",status,man->top.atoms.nr,
202                 trajectory,man->natom);
203   
204   sprintf(buf,"%s: %s",*man->top.name,cool_quote());
205   man->title.text = strdup(buf);
206   man->view       = init_view(man->box);
207   at=&(man->top.atoms);
208   for(i=0; (i<man->natom); i++) {
209     char *aname=*(at->atomname[i]);
210     int  resnr=at->atom[i].resnr;
211
212     man->col[i]=Type2Color(aname);
213     snew(man->szLab[i],20);
214     sprintf(man->szLab[i],"%s%d, %s",*(at->resname[resnr]),resnr+1,aname);
215     man->bHydro[i]=(toupper(aname[0])=='H');
216     if ( man->bHydro[i] )
217       man->vdw[i]=0;
218     else
219       man->vdw[i]=get_vdw(*(at->resname[resnr]),aname,0);
220   }
221   add_bpl(man,&(man->top.idef),bB);
222   for(i=0; (i<man->natom); i++)
223     if (!bB[i]) 
224       add_object(man,eOSingle,(atom_id) i,0);
225   sfree(bB);
226
227   ExposeWin(x11->disp,man->molw->wd.self);
228 }
229
230 void step_message(t_x11 *x11,t_manager *man)
231 {
232   XEvent letter;
233
234   letter.type=ClientMessage;
235   letter.xclient.display=x11->disp;
236   letter.xclient.window=man->wd.self;
237   letter.xclient.message_type=0;
238   letter.xclient.format=32;
239   letter.xclient.data.l[0]=IDSTEP;
240   letter.xclient.data.l[1]=Button1;
241   XSendEvent(x11->disp,letter.xclient.window,True,0,&letter);
242 }
243
244 bool ReadMonfile(char *fn,int *nbars, int *bars)
245 {
246   FILE *fp;
247   if ((fp = fopen(fn,"r"))==NULL) 
248     return(FALSE);
249   else {
250     for((*nbars)=0; fscanf(fp,"%d",&bars[*nbars])>0; (*nbars)++)
251       ;
252     fclose(fp);
253     return (TRUE);
254   }
255 }
256
257 static void reset_mols(t_block *mols,matrix box,rvec x[])
258 {
259   int  i,aj,m0,m1,j,m;
260   rvec xcm,icm;
261   real ix,iy,iz;
262   
263   for(i=0; (i<mols->nr); i++) {
264     m0=mols->index[i];
265     m1=mols->index[i+1];
266     
267     clear_rvec(xcm);
268     clear_rvec(icm);
269     
270     for(j=m0; (j<m1); j++) {
271       aj=mols->a[j];
272       rvec_inc(xcm,x[aj]);
273     }
274     for(m=0; (m<DIM); m++)
275       xcm[m]/=(m1-m0);
276     for(m=0; (m<DIM); m++) {
277       if (xcm[m] < 0) 
278         icm[m]=box[m][m];
279       else if (xcm[m] >= box[m][m]) 
280         icm[m]=-box[m][m];
281     }
282     ix=icm[XX],iy=icm[YY],iz=icm[ZZ];
283     
284     if ((ix != 0) || (iy != 0) || (iz != 0)) {
285       for(j=m0; (j<m1); j++) {
286         aj=mols->a[j];
287         x[aj][XX]+=ix;
288         x[aj][YY]+=iy;
289         x[aj][ZZ]+=iz;
290       }
291     }
292   }
293 }
294
295 static bool step_man(t_manager *man,int *nat)
296 {
297   static int  ncount=0;
298   bool        bEof;
299   real        rdum;
300   int         dum;
301
302   if (!man->natom) {
303     fprintf(stderr,"Not initiated yet!");
304     exit(1);
305   }
306   bEof=read_next_x(man->status,&man->time,man->natom,man->x,man->box);
307   *nat=man->natom;
308   if (ncount == man->nSkip) {
309     switch (man->molw->boxtype) {
310     case esbTri:
311       put_atoms_in_triclinic_unitcell(man->box,man->natom,man->x);
312       break;
313     case esbTrunc:
314       put_atoms_in_compact_unitcell(man->box,man->natom,man->x);
315       break;
316     case esbRect:
317     case esbNone:
318     default:
319       break;
320     }
321     if (man->bPbc) {
322       rm_pbc(&(man->top.idef),man->natom,man->box,man->x,man->x);
323       reset_mols(&(man->top.blocks[ebMOLS]),man->box,man->x);
324     }
325     ncount=0;
326   }
327   else {
328     if (man->nSkip > 0) {
329       ncount++;
330       return step_man(man,nat);
331     }
332   }
333
334   return bEof;
335 }
336
337 static void HandleClient(t_x11 *x11,t_manager *man,long data[])
338 {
339   int  ID,button,x,y;
340   bool bPos;
341   real fac;
342
343   ID=data[0];
344   button=data[1];
345   x=data[2];
346   y=data[3];
347   bPos=(button==Button1);
348   switch (ID) {
349   case IDROTX:
350   case IDROTY:
351   case IDROTZ:
352     rotate_3d(man->view,ID-IDROTX,bPos);
353     draw_mol(x11,man);
354     break;
355   case IDZOOM:
356     if (bPos)
357       fac=0.8; /* Reduce distance between eye and origin */
358     else
359       fac=1.25;
360     
361     /*  zoom changed to scale by Berk Hess 3-7-96
362     if (zoom_3d(man->view,fac))
363       draw_mol(x11,man); */
364     man->view->sc_x/=fac;
365     man->view->sc_y/=fac;
366     draw_mol(x11,man);
367     break;
368   case IDTRANSX:
369   case IDTRANSY:
370   case IDTRANSZ:
371     translate_view(man->view,ID-IDTRANSX,bPos);
372     draw_mol(x11,man);
373     break;
374   case IDREWIND:
375     if (man->status != -1) {
376       rewind_trj(man->status);
377       read_next_x(man->status,&(man->time),man->natom,man->x,man->box);
378       man->bEof=FALSE;
379       draw_mol(x11,man);
380     }
381     break;
382   case IDSTEP: {
383     int      nat;
384
385     nat=0;
386     if (!step_man(man,&nat)) {
387       man->bEof=TRUE;
388       man->bStop=TRUE;
389     }
390     else {
391       if (nat > 0) {
392         draw_mol(x11,man);
393         usleep(man->nWait*1000);
394       }
395     }
396     break;
397   }
398   case IDFF:
399     man->bStop=FALSE;
400     break;
401   case IDSTOP_ANI:
402     man->bStop=TRUE;
403     break;
404   case IDDRAWMOL:
405     draw_mol(x11,man);
406     break;
407   case IDLABEL:
408     switch (button) {
409     case Button1:
410     case Button2:
411       show_label(x11,man,x,y);
412       break;
413     case Button3:
414       hide_label(x11,man,x,y);
415       break;
416     }
417     break;
418   default:
419     break;
420   }
421   if (man->bAnimate && !man->bEof && !man->bStop)
422     step_message(x11,man);
423 }
424
425 static bool TitleCallBack(t_x11 *x11,XEvent *event, Window w, void *data)
426 {
427   t_windata *wd;
428
429   wd=(t_windata *)data;
430   switch (event->type) {
431   case Expose:
432     if (wd->text && (wd->width > 10)) {
433       XSetForeground(x11->disp,x11->gc,WHITE);
434       TextInWin(x11,wd,wd->text,eXCenter,eYCenter);
435       XDrawLine(x11->disp,wd->self,x11->gc,0,wd->height,
436                 wd->width,wd->height);
437     }
438     break;
439   case ConfigureNotify:
440     wd->width=event->xconfigure.width;
441     wd->height=event->xconfigure.height;
442     break;
443   }
444   return FALSE;
445 }
446
447 static bool ManCallBack(t_x11 *x11,XEvent *event, Window w, void *data)
448 {
449   t_manager *man;
450   int       width,height;
451
452   man=(t_manager *)data;
453   switch(event->type) {
454   case ConfigureNotify:
455     width=event->xconfigure.width;
456     height=event->xconfigure.height;
457     if ((width!=man->wd.width) || (height!=man->wd.height))
458       move_man(x11,man,width,height);
459     break;
460   case ClientMessage:
461     HandleClient(x11,man,event->xclient.data.l);
462     break;
463   default:
464     break;
465   }
466   return FALSE;
467 }
468
469 void no_labels(t_x11 *x11,t_manager *man)
470 {
471   int i;
472
473   for(i=0; (i<man->natom); i++)
474     man->bLabel[i]=FALSE;
475   draw_mol(x11,man);
476 }
477
478 void move_man(t_x11 *x11,t_manager *man,int width,int height)
479 {
480   int x0,y0,mw,mh,hb;
481   int th;
482   
483 #ifdef DEBUG
484   fprintf(stderr,"Move manager %dx%d\n",width,height);
485 #endif
486   man->wd.width=width;
487   man->wd.height=height;
488
489   /* Move all subwindows, resize only Mol window */
490   x0=width-EWIDTH-AIR-4*BORDER;               /* Starting of ewin etc. */
491   y0=AIR;
492   
493   /* Mol Window */
494   mw=x0-2*AIR-4*BORDER;
495   mh=height-y0-AIR-2*BORDER;
496   XMoveResizeWindow(x11->disp,man->molw->wd.self,AIR,y0,mw,mh);
497
498   /* Title Window */
499   th=XTextHeight(x11->font);
500   XMoveResizeWindow(x11->disp,man->title.self,0,0,mw,th+AIR);
501   
502   /* Legend Window */
503   XMoveResizeWindow(x11->disp,man->legw->wd.self,x0,y0,EWIDTH,LEGHEIGHT);
504   y0+=LEGHEIGHT+AIR+2*BORDER;
505
506   if (y0 > height) 
507     printf("Error: Windows falling out of main window!\n");
508
509   /* Button Box */
510   hb=height-y0-AIR-2*BORDER;
511   XMoveResizeWindow(x11->disp,man->bbox->wd.self,x0,y0,EWIDTH,hb);
512   
513   /* Video Box */
514   x0=(mw-man->vbox->wd.width)/2;
515   y0=(mh-2-AIR-man->vbox->wd.height);
516   XMoveWindow(x11->disp,man->vbox->wd.self,x0,y0);
517 }
518
519 void map_man(t_x11 *x11,t_manager *man)
520 {
521   XMapWindow(x11->disp,man->wd.self);
522   map_mw(x11,man->molw);
523   XMapWindow(x11->disp,man->title.self);
524   map_legw(x11,man->legw);
525   show_but(x11,man->bbox);
526 }
527
528 bool toggle_animate (t_x11 *x11,t_manager *man)
529
530   if (man->status != -1) {
531     man->bAnimate=!man->bAnimate;
532     man->bStop=TRUE;
533     man->bEof=FALSE;
534     if (man->bAnimate)
535       show_but(x11,man->vbox);
536     else
537       hide_but(x11,man->vbox);
538   }
539   return man->bAnimate;
540 }
541
542 bool toggle_pbc (t_manager *man)
543 {
544   man->bPbc=!man->bPbc;
545   
546   return man->bPbc;
547 }
548
549
550 t_manager *init_man(t_x11 *x11,Window Parent,
551                     int x,int y,int width,int height,
552                     unsigned long fg,unsigned long bg,
553                     matrix box)
554 {
555   t_manager *man;
556
557   snew(man,1);
558   man->status=-1;
559   man->bPlus=TRUE;
560   man->bSort=TRUE;
561   InitWin(&(man->wd),x,y,width,height,0,"Manager");
562   man->wd.self=XCreateSimpleWindow(x11->disp,Parent,man->wd.x, man->wd.y, 
563                                    man->wd.width,man->wd.height,
564                                    man->wd.bwidth,fg,bg);
565   x11->RegisterCallback(x11,man->wd.self,Parent,ManCallBack,man);
566   x11->SetInputMask(x11,man->wd.self,StructureNotifyMask | 
567                     ExposureMask | ButtonPressMask);
568
569   /* The order of creating windows is important for the stacking order */
570   /* Mol Window */
571   man->molw=init_mw(x11,man->wd.self,0,0,1,1,WHITE,BLUE,box);
572
573   /* Title Window */
574   InitWin(&(man->title),0,0,1,1,0,NULL);
575   man->title.self=XCreateSimpleWindow(x11->disp,man->molw->wd.self,
576                                       man->title.x,man->title.y,
577                                       man->title.width,man->title.height,
578                                       man->title.bwidth,WHITE,BLUE);
579   x11->RegisterCallback(x11,man->title.self,man->molw->wd.self,
580                         TitleCallBack,&(man->title));
581   x11->SetInputMask(x11,man->title.self,ExposureMask | StructureNotifyMask);
582   
583   /* Button box */
584   man->bbox=init_bbox(x11,man->wd.self,man->wd.self,1,WHITE,BLUE);
585   
586   /* Legend Window */
587   man->legw=init_legw(x11,man->wd.self,0,0,EWIDTH,LEGHEIGHT,WHITE,BLUE);
588
589   /* Video Box */
590   man->vbox=init_vbox(x11,man->molw->wd.self,man->wd.self,WHITE,BLUE);
591   
592   return man;
593 }
594
595 void done_man(t_x11 *x11,t_manager *man)
596 {
597   done_bbox(x11,man->vbox);
598   done_bbox(x11,man->bbox);
599   done_mw(x11,man->molw);
600   done_legw(x11,man->legw);
601   x11->UnRegisterCallback(x11,man->title.self);
602   x11->UnRegisterCallback(x11,man->wd.self);
603   sfree(man->x);
604   sfree(man->obj);
605   sfree(man->bHydro);
606   sfree(man->bLabel);
607   sfree(man->szLab);
608   sfree(man->col);
609   sfree(man);
610 }
611
612 void do_filter(t_x11 *x11,t_manager *man,t_filter *filter)
613 {
614   int      i;
615   atom_id  j;
616
617   for(i=0; (i<man->natom); i++)
618     man->bVis[i]=FALSE;
619   for(i=0; (i<filter->grps->nr); i++) {
620     if (filter->bShow[i])
621       for(j=filter->grps->index[i]; (j<filter->grps->index[i+1]); j++)
622         man->bVis[filter->grps->a[j]]=TRUE;
623   }
624
625   ExposeWin(x11->disp,man->wd.self);
626 }