Fix AVX-512 SIMD test for C
[gromacs.git] / src / programs / view / manager.cpp
blob8695978f12271963df28b263c7ca3ac8f67407d6
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015,2016,2017, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
37 #include "gmxpre.h"
39 #include "manager.h"
41 #include "config.h"
43 #include <cctype>
44 #include <cstdio>
45 #include <cstdlib>
46 #include <cstring>
48 #include <string>
50 #ifdef HAVE_UNISTD_H
51 #include <unistd.h> // for usleep()
52 #endif
54 #include "gromacs/fileio/tpxio.h"
55 #include "gromacs/math/utilities.h"
56 #include "gromacs/math/vec.h"
57 #include "gromacs/mdtypes/md_enums.h"
58 #include "gromacs/pbcutil/pbc.h"
59 #include "gromacs/topology/atomprop.h"
60 #include "gromacs/topology/ifunc.h"
61 #include "gromacs/utility/coolstuff.h"
62 #include "gromacs/utility/cstringutil.h"
63 #include "gromacs/utility/fatalerror.h"
64 #include "gromacs/utility/futil.h"
65 #include "gromacs/utility/smalloc.h"
66 #include "gromacs/utility/stringutil.h"
68 #include "3dview.h"
69 #include "nmol.h"
71 static void add_object(t_manager *man, eObject eO, int ai, int aj)
73 srenew(man->obj, ++man->nobj);
74 man->obj[man->nobj-1].eO = eO;
75 man->obj[man->nobj-1].eV = eVNormal;
76 man->obj[man->nobj-1].color = WHITE;
77 man->obj[man->nobj-1].ai = ai;
78 man->obj[man->nobj-1].aj = aj;
79 man->obj[man->nobj-1].z = 0.0;
82 static void add_bonds(t_manager *man, t_functype func[],
83 t_ilist *b, bool bB[])
85 bool *bH = man->bHydro;
86 t_iatom *ia;
87 t_iatom type, ai, aj, ak;
88 int i, delta, ftype;
90 #ifdef DEBUG
91 std::fprintf(stderr, "Going to make bonds from an ilist with %d entries\n", b->nr);
92 #endif
93 ia = b->iatoms;
94 for (i = 0; (i < b->nr); )
96 type = ia[0];
97 ai = ia[1];
98 ftype = func[type];
99 delta = interaction_function[ftype].nratoms;
101 if (ftype == F_SETTLE)
103 aj = ia[2];
104 ak = ia[3];
105 bB[ai] = bB[aj] = bB[ak] = true;
106 add_object(man, eOHBond, ai, aj);
107 add_object(man, eOHBond, ai, ak);
109 else if (IS_CHEMBOND(ftype))
111 aj = ia[2];
112 #ifdef DEBUG
113 std::fprintf(stderr, "Adding bond from %d to %d\n", ai, aj);
114 #endif
115 bB[ai] = bB[aj] = true;
116 if (!(bH[ai] == bH[aj]))
118 add_object(man, eOHBond, ai, aj);
120 else if (!bH[ai] && !bH[aj])
122 add_object(man, eOBond, ai, aj);
125 #ifdef DEBUG
126 std::fprintf(stderr, "Type: %5d, delta: %5d\n", type, delta);
127 #endif
128 ia += delta+1;
129 i += delta+1;
133 static void add_bpl(t_manager *man, t_idef *idef, bool bB[])
135 int ftype;
137 for (ftype = 0; ftype < F_NRE; ftype++)
139 if (IS_CHEMBOND(ftype) || ftype == F_SETTLE)
141 add_bonds(man, idef->functype, &idef->il[ftype], bB);
146 static int which_atom(t_manager *man, int x, int y)
148 #define DELTA 5
149 int i;
150 iv2 *ix = man->ix;
152 for (i = 0; (i < man->natom); i++)
154 if ((std::abs(ix[i][XX]-x) < DELTA) && (std::abs(ix[i][YY]-y) < DELTA))
156 if (man->bVis[i])
158 return (int) i;
162 return -1;
165 static void do_label(t_x11 *x11, t_manager *man, int x, int y, bool bSet)
167 int ai;
168 unsigned long col;
170 if ((ai = which_atom(man, x, y)) != -1)
172 x = man->ix[ai][XX];
173 y = man->ix[ai][YY];
174 if (bSet && !man->bLabel[ai])
176 col = WHITE;
177 man->bLabel[ai] = true;
179 else if (!bSet && man->bLabel[ai])
181 col = BLUE;
182 man->bLabel[ai] = false;
184 else
186 return;
188 XSetForeground(x11->disp, x11->gc, col);
189 XDrawString(x11->disp, man->molw->wd.self, x11->gc, x+2, y-2, man->szLab[ai],
190 std::strlen(man->szLab[ai]));
191 XSetForeground(x11->disp, x11->gc, x11->fg);
195 static void show_label(t_x11 *x11, t_manager *man, int x, int y)
197 do_label(x11, man, x, y, true);
200 static void hide_label(t_x11 *x11, t_manager *man, int x, int y)
202 do_label(x11, man, x, y, false);
205 void set_file(t_x11 *x11, t_manager *man, const char *trajectory,
206 const char *status)
208 gmx_atomprop_t aps;
209 t_tpxheader sh;
210 t_atoms *at;
211 bool *bB;
212 int i;
214 read_tpxheader(status, &sh, true);
215 snew(man->ix, sh.natoms);
216 snew(man->zz, sh.natoms);
217 snew(man->col, sh.natoms);
218 snew(man->size, sh.natoms);
219 snew(man->vdw, sh.natoms);
220 snew(man->bLabel, sh.natoms);
221 snew(man->bVis, sh.natoms);
222 for (i = 0; (i < sh.natoms); i++)
224 man->bVis[i] = false;
227 man->bPbc = false;
229 snew(man->szLab, sh.natoms);
230 snew(man->bHydro, sh.natoms);
231 snew(bB, sh.natoms);
232 read_tpx_top(status, nullptr, man->box, &man->natom, nullptr, nullptr, &man->top);
233 man->gpbc = gmx_rmpbc_init(&man->top.idef, -1, man->natom);
235 man->natom =
236 read_first_x(man->oenv, &man->status, trajectory, &(man->time), &(man->x),
237 man->box);
238 man->trajfile = gmx_strdup(trajectory);
239 if (man->natom > man->top.atoms.nr)
241 gmx_fatal(FARGS, "Topology %s (%d atoms) and trajectory %s (%d atoms) "
242 "do not match", status, man->top.atoms.nr,
243 trajectory, man->natom);
246 man->title.text = gmx_strdup(gmx::formatString("%s: %s", *man->top.name, gmx::getCoolQuote().c_str()).c_str());
247 man->view = init_view(man->box);
248 at = &(man->top.atoms);
249 aps = gmx_atomprop_init();
250 for (i = 0; (i < man->natom); i++)
252 char *aname = *(at->atomname[i]);
253 t_resinfo *ri = &at->resinfo[at->atom[i].resind];
255 man->col[i] = Type2Color(aname);
256 snew(man->szLab[i], 20);
257 if (ri->ic != ' ')
259 std::sprintf(man->szLab[i], "%s%d%c, %s", *ri->name, ri->nr, ri->ic, aname);
261 else
263 std::sprintf(man->szLab[i], "%s%d, %s", *ri->name, ri->nr, aname);
265 man->bHydro[i] = (toupper(aname[0]) == 'H');
266 if (man->bHydro[i])
268 man->vdw[i] = 0;
270 else if (!gmx_atomprop_query(aps, epropVDW, *ri->name, aname, &(man->vdw[i])))
272 man->vdw[i] = 0;
275 gmx_atomprop_destroy(aps);
276 add_bpl(man, &(man->top.idef), bB);
277 for (i = 0; (i < man->natom); i++)
279 if (!bB[i])
281 add_object(man, eOSingle, (int) i, 0);
284 sfree(bB);
286 ExposeWin(x11->disp, man->molw->wd.self);
289 void step_message(t_x11 *x11, t_manager *man)
291 XEvent letter;
293 letter.type = ClientMessage;
294 letter.xclient.display = x11->disp;
295 letter.xclient.window = man->wd.self;
296 letter.xclient.message_type = 0;
297 letter.xclient.format = 32;
298 letter.xclient.data.l[0] = IDSTEP;
299 letter.xclient.data.l[1] = Button1;
300 XSendEvent(x11->disp, letter.xclient.window, True, 0, &letter);
303 static void reset_mols(t_block *mols, matrix box, rvec x[])
305 int i, m0, m1, j, m;
306 rvec xcm, icm;
307 real ix, iy, iz;
309 for (i = 0; (i < mols->nr); i++)
311 m0 = mols->index[i];
312 m1 = mols->index[i+1];
314 clear_rvec(xcm);
315 clear_rvec(icm);
317 for (j = m0; (j < m1); j++)
319 rvec_inc(xcm, x[j]);
321 for (m = 0; (m < DIM); m++)
323 xcm[m] /= (m1-m0);
325 for (m = 0; (m < DIM); m++)
327 if (xcm[m] < 0)
329 icm[m] = box[m][m];
331 else if (xcm[m] >= box[m][m])
333 icm[m] = -box[m][m];
336 ix = icm[XX], iy = icm[YY], iz = icm[ZZ];
338 if ((ix != 0) || (iy != 0) || (iz != 0))
340 for (j = m0; (j < m1); j++)
342 x[j][XX] += ix;
343 x[j][YY] += iy;
344 x[j][ZZ] += iz;
350 static bool step_man(t_manager *man, int *nat)
352 static int ncount = 0;
353 bool bEof;
355 if (!man->natom)
357 std::fprintf(stderr, "Not initiated yet!");
358 std::exit(1);
360 bEof = read_next_x(man->oenv, man->status, &man->time, man->x, man->box);
361 *nat = man->natom;
362 if (ncount == man->nSkip)
364 auto atomsArrayRef = gmx::arrayRefFromArray(reinterpret_cast<gmx::RVec *>(man->x), man->natom);
365 switch (man->molw->boxtype)
367 case esbTri:
368 put_atoms_in_triclinic_unitcell(ecenterDEF, man->box, atomsArrayRef);
369 break;
370 case esbTrunc:
371 put_atoms_in_compact_unitcell(man->molw->ePBC, ecenterDEF, man->box,
372 atomsArrayRef);
373 break;
374 case esbRect:
375 case esbNone:
376 default:
377 break;
379 if (man->bPbc)
381 gmx_rmpbc(man->gpbc, man->natom, man->box, man->x);
382 reset_mols(&(man->top.mols), man->box, man->x);
384 ncount = 0;
386 else
388 if (man->nSkip > 0)
390 ncount++;
391 return step_man(man, nat);
395 return bEof;
398 static void HandleClient(t_x11 *x11, t_manager *man, long data[])
400 int ID, button, x, y;
401 bool bPos;
402 real fac;
404 ID = data[0];
405 button = data[1];
406 x = data[2];
407 y = data[3];
408 bPos = (button == Button1);
409 switch (ID)
411 case IDROTX:
412 case IDROTY:
413 case IDROTZ:
414 rotate_3d(man->view, ID-IDROTX, bPos);
415 draw_mol(x11, man);
416 break;
417 case IDZOOM:
418 if (bPos)
420 fac = 0.8; /* Reduce distance between eye and origin */
422 else
424 fac = 1.25;
427 /* zoom changed to scale by Berk Hess 3-7-96
428 if (zoom_3d(man->view,fac))
429 draw_mol(x11,man); */
430 man->view->sc_x /= fac;
431 man->view->sc_y /= fac;
432 draw_mol(x11, man);
433 break;
434 case IDTRANSX:
435 case IDTRANSY:
436 case IDTRANSZ:
437 translate_view(man->view, ID-IDTRANSX, bPos);
438 draw_mol(x11, man);
439 break;
440 case IDREWIND:
441 if (man->status)
443 rewind_trj(man->status);
444 read_next_x(man->oenv, man->status, &(man->time), man->x,
445 man->box);
446 man->bEof = false;
447 draw_mol(x11, man);
449 break;
450 case IDSTEP:
452 int nat;
454 nat = 0;
455 if (!step_man(man, &nat))
457 man->bEof = true;
458 man->bStop = true;
460 else
462 if (nat > 0)
464 draw_mol(x11, man);
465 usleep(man->nWait*1000);
468 break;
470 case IDFF:
471 man->bStop = false;
472 break;
473 case IDSTOP_ANI:
474 man->bStop = true;
475 break;
476 case IDDRAWMOL:
477 draw_mol(x11, man);
478 break;
479 case IDLABEL:
480 switch (button)
482 case Button1:
483 case Button2:
484 show_label(x11, man, x, y);
485 break;
486 case Button3:
487 hide_label(x11, man, x, y);
488 break;
490 break;
491 default:
492 break;
494 if (man->bAnimate && !man->bEof && !man->bStop)
496 step_message(x11, man);
500 static bool TitleCallBack(t_x11 *x11, XEvent *event, Window /*w*/, void *data)
502 t_windata *wd;
504 wd = static_cast<t_windata *>(data);
505 switch (event->type)
507 case Expose:
508 if (wd->text && (wd->width > 10))
510 XSetForeground(x11->disp, x11->gc, WHITE);
511 TextInWin(x11, wd, wd->text, eXCenter, eYCenter);
512 XDrawLine(x11->disp, wd->self, x11->gc, 0, wd->height,
513 wd->width, wd->height);
515 break;
516 case ConfigureNotify:
517 wd->width = event->xconfigure.width;
518 wd->height = event->xconfigure.height;
519 break;
521 return false;
524 static bool ManCallBack(t_x11 *x11, XEvent *event, Window /*w*/, void *data)
526 t_manager *man;
527 int width, height;
529 man = static_cast<t_manager *>(data);
530 switch (event->type)
532 case ConfigureNotify:
533 width = event->xconfigure.width;
534 height = event->xconfigure.height;
535 if ((width != man->wd.width) || (height != man->wd.height))
537 move_man(x11, man, width, height);
539 break;
540 case ClientMessage:
541 HandleClient(x11, man, event->xclient.data.l);
542 break;
543 default:
544 break;
546 return false;
549 void no_labels(t_x11 *x11, t_manager *man)
551 int i;
553 for (i = 0; (i < man->natom); i++)
555 man->bLabel[i] = false;
557 draw_mol(x11, man);
560 void move_man(t_x11 *x11, t_manager *man, int width, int height)
562 int x0, y0, mw, mh, hb;
563 int th;
565 #ifdef DEBUG
566 std::fprintf(stderr, "Move manager %dx%d\n", width, height);
567 #endif
568 man->wd.width = width;
569 man->wd.height = height;
571 /* Move all subwindows, resize only Mol window */
572 x0 = width-EWIDTH-AIR-4*BORDER; /* Starting of ewin etc. */
573 y0 = AIR;
575 /* Mol Window */
576 mw = x0-2*AIR-4*BORDER;
577 mh = height-y0-AIR-2*BORDER;
578 XMoveResizeWindow(x11->disp, man->molw->wd.self, AIR, y0, mw, mh);
580 /* Title Window */
581 th = XTextHeight(x11->font);
582 XMoveResizeWindow(x11->disp, man->title.self, 0, 0, mw, th+AIR);
584 /* Legend Window */
585 XMoveResizeWindow(x11->disp, man->legw->wd.self, x0, y0, EWIDTH, LEGHEIGHT);
586 y0 += LEGHEIGHT+AIR+2*BORDER;
588 if (y0 > height)
590 std::printf("Error: Windows falling out of main window!\n");
593 /* Button Box */
594 hb = height-y0-AIR-2*BORDER;
595 XMoveResizeWindow(x11->disp, man->bbox->wd.self, x0, y0, EWIDTH, hb);
597 /* Video Box */
598 x0 = (mw-man->vbox->wd.width)/2;
599 y0 = (mh-2-AIR-man->vbox->wd.height);
600 XMoveWindow(x11->disp, man->vbox->wd.self, x0, y0);
603 void map_man(t_x11 *x11, t_manager *man)
605 XMapWindow(x11->disp, man->wd.self);
606 map_mw(x11, man->molw);
607 XMapWindow(x11->disp, man->title.self);
608 map_legw(x11, man->legw);
609 show_but(x11, man->bbox);
612 bool toggle_animate (t_x11 *x11, t_manager *man)
614 if (man->status)
616 man->bAnimate = !man->bAnimate;
617 man->bStop = true;
618 man->bEof = false;
619 if (man->bAnimate)
621 show_but(x11, man->vbox);
623 else
625 hide_but(x11, man->vbox);
628 return man->bAnimate;
631 bool toggle_pbc (t_manager *man)
633 man->bPbc = !man->bPbc;
635 return man->bPbc;
639 t_manager *init_man(t_x11 *x11, Window Parent,
640 int x, int y, int width, int height,
641 unsigned long fg, unsigned long bg,
642 int ePBC, matrix box,
643 gmx_output_env_t *oenv)
645 t_manager *man;
647 snew(man, 1);
648 man->status = nullptr;
649 man->bPlus = true;
650 man->bSort = true;
651 man->oenv = oenv;
652 InitWin(&(man->wd), x, y, width, height, 0, "Manager");
653 man->wd.self = XCreateSimpleWindow(x11->disp, Parent, man->wd.x, man->wd.y,
654 man->wd.width, man->wd.height,
655 man->wd.bwidth, fg, bg);
656 x11->RegisterCallback(x11, man->wd.self, Parent, ManCallBack, man);
657 x11->SetInputMask(x11, man->wd.self, StructureNotifyMask |
658 ExposureMask | ButtonPressMask);
660 /* The order of creating windows is important for the stacking order */
661 /* Mol Window */
662 man->molw = init_mw(x11, man->wd.self, 0, 0, 1, 1, WHITE, BLUE, ePBC, box);
664 /* Title Window */
665 InitWin(&(man->title), 0, 0, 1, 1, 0, nullptr);
666 man->title.self = XCreateSimpleWindow(x11->disp, man->molw->wd.self,
667 man->title.x, man->title.y,
668 man->title.width, man->title.height,
669 man->title.bwidth, WHITE, BLUE);
670 x11->RegisterCallback(x11, man->title.self, man->molw->wd.self,
671 TitleCallBack, &(man->title));
672 x11->SetInputMask(x11, man->title.self, ExposureMask | StructureNotifyMask);
674 /* Button box */
675 man->bbox = init_bbox(x11, man->wd.self, man->wd.self, 1, WHITE, BLUE);
677 /* Legend Window */
678 man->legw = init_legw(x11, man->wd.self, 0, 0, EWIDTH, LEGHEIGHT, WHITE, BLUE);
680 /* Video Box */
681 man->vbox = init_vbox(x11, man->molw->wd.self, man->wd.self, WHITE, BLUE);
683 return man;
686 void done_man(t_x11 *x11, t_manager *man)
688 done_bbox(x11, man->vbox);
689 done_bbox(x11, man->bbox);
690 done_mw(x11, man->molw);
691 done_legw(x11, man->legw);
692 x11->UnRegisterCallback(x11, man->title.self);
693 x11->UnRegisterCallback(x11, man->wd.self);
694 sfree(man->x);
695 sfree(man->obj);
696 sfree(man->bHydro);
697 sfree(man->bLabel);
698 sfree(man->szLab);
699 sfree(man->col);
700 sfree(man);
703 void do_filter(t_x11 *x11, t_manager *man, t_filter *filter)
705 int i;
706 int j;
708 for (i = 0; (i < man->natom); i++)
710 man->bVis[i] = false;
712 for (i = 0; (i < filter->grps->nr); i++)
714 if (filter->bShow[i])
716 for (j = filter->grps->index[i]; (j < filter->grps->index[i+1]); j++)
718 man->bVis[filter->grps->a[j]] = true;
723 ExposeWin(x11->disp, man->wd.self);