Renamed entropy.* to thermochemistry.*
[gromacs.git] / src / gromacs / pbcutil / mshift.cpp
blob236848fcdc3523976f855406a3b23cd67eebf9a1
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 "mshift.h"
41 #include <string.h>
43 #include <algorithm>
45 #include "gromacs/math/vec.h"
46 #include "gromacs/pbcutil/pbc.h"
47 #include "gromacs/topology/idef.h"
48 #include "gromacs/topology/ifunc.h"
49 #include "gromacs/utility/fatalerror.h"
50 #include "gromacs/utility/smalloc.h"
52 /************************************************************
54 * S H I F T U T I L I T I E S
56 ************************************************************/
59 /************************************************************
61 * G R A P H G E N E R A T I O N C O D E
63 ************************************************************/
65 static void add_gbond(t_graph *g, int a0, int a1)
67 int i;
68 int inda0, inda1;
69 gmx_bool bFound;
71 inda0 = a0 - g->at_start;
72 inda1 = a1 - g->at_start;
73 bFound = FALSE;
74 /* Search for a direct edge between a0 and a1.
75 * All egdes are bidirectional, so we only need to search one way.
77 for (i = 0; (i < g->nedge[inda0] && !bFound); i++)
79 bFound = (g->edge[inda0][i] == a1);
82 if (!bFound)
84 g->edge[inda0][g->nedge[inda0]++] = a1;
85 g->edge[inda1][g->nedge[inda1]++] = a0;
89 static void mk_igraph(t_graph *g, int ftype, const t_ilist *il,
90 int at_start, int at_end,
91 int *part)
93 t_iatom *ia;
94 int i, j, np;
95 int end;
97 end = il->nr;
98 ia = il->iatoms;
100 i = 0;
101 while (i < end)
103 np = interaction_function[ftype].nratoms;
105 if (ia[1] >= at_start && ia[1] < at_end)
107 if (ia[np] >= at_end)
109 gmx_fatal(FARGS,
110 "Molecule in topology has atom numbers below and "
111 "above natoms (%d).\n"
112 "You are probably trying to use a trajectory which does "
113 "not match the first %d atoms of the run input file.\n"
114 "You can make a matching run input file with gmx convert-tpr.",
115 at_end, at_end);
117 if (ftype == F_SETTLE)
119 /* Bond all the atoms in the settle */
120 add_gbond(g, ia[1], ia[2]);
121 add_gbond(g, ia[1], ia[3]);
123 else if (part == nullptr)
125 /* Simply add this bond */
126 for (j = 1; j < np; j++)
128 add_gbond(g, ia[j], ia[j+1]);
131 else
133 /* Add this bond when it connects two unlinked parts of the graph */
134 for (j = 1; j < np; j++)
136 if (part[ia[j]] != part[ia[j+1]])
138 add_gbond(g, ia[j], ia[j+1]);
143 ia += np+1;
144 i += np+1;
148 gmx_noreturn static void g_error(int line, const char *file)
150 gmx_fatal(FARGS, "Trying to print nonexistent graph (file %s, line %d)",
151 file, line);
153 #define GCHECK(g) if (g == NULL) g_error(__LINE__, __FILE__)
155 void p_graph(FILE *log, const char *title, t_graph *g)
157 int i, j;
158 const char *cc[egcolNR] = { "W", "G", "B" };
160 GCHECK(g);
161 fprintf(log, "graph: %s\n", title);
162 fprintf(log, "nnodes: %d\n", g->nnodes);
163 fprintf(log, "nbound: %d\n", g->nbound);
164 fprintf(log, "start: %d\n", g->at_start);
165 fprintf(log, "end: %d\n", g->at_end);
166 fprintf(log, " atom shiftx shifty shiftz C nedg e1 e2 etc.\n");
167 for (i = 0; (i < g->nnodes); i++)
169 if (g->nedge[i] > 0)
171 fprintf(log, "%5d%7d%7d%7d %1s%5d", g->at_start+i+1,
172 g->ishift[g->at_start+i][XX],
173 g->ishift[g->at_start+i][YY],
174 g->ishift[g->at_start+i][ZZ],
175 (g->negc > 0) ? cc[g->egc[i]] : " ",
176 g->nedge[i]);
177 for (j = 0; (j < g->nedge[i]); j++)
179 fprintf(log, " %5d", g->edge[i][j]+1);
181 fprintf(log, "\n");
184 fflush(log);
187 static void calc_1se(t_graph *g, int ftype, const t_ilist *il,
188 int nbond[], int at_start, int at_end)
190 int k, nratoms, end, j;
191 t_iatom *ia, iaa;
193 end = il->nr;
195 ia = il->iatoms;
196 for (j = 0; (j < end); j += nratoms+1, ia += nratoms+1)
198 nratoms = interaction_function[ftype].nratoms;
200 if (ftype == F_SETTLE)
202 iaa = ia[1];
203 if (iaa >= at_start && iaa < at_end)
205 nbond[iaa] += 2;
206 nbond[ia[2]] += 1;
207 nbond[ia[3]] += 1;
208 g->at_start = std::min(g->at_start, iaa);
209 g->at_end = std::max(g->at_end, iaa+2+1);
212 else
214 for (k = 1; (k <= nratoms); k++)
216 iaa = ia[k];
217 if (iaa >= at_start && iaa < at_end)
219 g->at_start = std::min(g->at_start, iaa);
220 g->at_end = std::max(g->at_end, iaa+1);
221 /* When making the graph we (might) link all atoms in an interaction
222 * sequentially. Therefore the end atoms add 1 to the count,
223 * the middle atoms 2.
225 if (k == 1 || k == nratoms)
227 nbond[iaa] += 1;
229 else
231 nbond[iaa] += 2;
239 static int calc_start_end(FILE *fplog, t_graph *g, const t_ilist il[],
240 int at_start, int at_end,
241 int nbond[])
243 int i, nnb, nbtot;
245 g->at_start = at_end;
246 g->at_end = 0;
248 /* First add all the real bonds: they should determine the molecular
249 * graph.
251 for (i = 0; (i < F_NRE); i++)
253 if (interaction_function[i].flags & IF_CHEMBOND)
255 calc_1se(g, i, &il[i], nbond, at_start, at_end);
258 /* Then add all the other interactions in fixed lists, but first
259 * check to see what's there already.
261 for (i = 0; (i < F_NRE); i++)
263 if (!(interaction_function[i].flags & IF_CHEMBOND))
265 calc_1se(g, i, &il[i], nbond, at_start, at_end);
269 nnb = 0;
270 nbtot = 0;
271 for (i = g->at_start; (i < g->at_end); i++)
273 nbtot += nbond[i];
274 nnb = std::max(nnb, nbond[i]);
276 if (fplog)
278 fprintf(fplog, "Max number of connections per atom is %d\n", nnb);
279 fprintf(fplog, "Total number of connections is %d\n", nbtot);
281 return nbtot;
286 static void compact_graph(FILE *fplog, t_graph *g)
288 int i, j, n, max_nedge;
290 max_nedge = 0;
291 n = 0;
292 for (i = 0; i < g->nnodes; i++)
294 for (j = 0; j < g->nedge[i]; j++)
296 g->edge[0][n++] = g->edge[i][j];
298 max_nedge = std::max(max_nedge, g->nedge[i]);
300 srenew(g->edge[0], n);
301 /* set pointers after srenew because edge[0] might move */
302 for (i = 1; i < g->nnodes; i++)
304 g->edge[i] = g->edge[i-1] + g->nedge[i-1];
307 if (fplog)
309 fprintf(fplog, "Max number of graph edges per atom is %d\n",
310 max_nedge);
311 fprintf(fplog, "Total number of graph edges is %d\n", n);
315 static gmx_bool determine_graph_parts(t_graph *g, int *part)
317 int i, e;
318 int nchanged;
319 int at_i, *at_i2;
320 gmx_bool bMultiPart;
322 /* Initialize the part array with all entries different */
323 for (at_i = g->at_start; at_i < g->at_end; at_i++)
325 part[at_i] = at_i;
328 /* Loop over the graph until the part array is fixed */
331 bMultiPart = FALSE;
332 nchanged = 0;
333 for (i = 0; (i < g->nnodes); i++)
335 at_i = g->at_start + i;
336 at_i2 = g->edge[i];
337 for (e = 0; e < g->nedge[i]; e++)
339 /* Set part for both nodes to the minimum */
340 if (part[at_i2[e]] > part[at_i])
342 part[at_i2[e]] = part[at_i];
343 nchanged++;
345 else if (part[at_i2[e]] < part[at_i])
347 part[at_i] = part[at_i2[e]];
348 nchanged++;
351 if (part[at_i] != part[g->at_start])
353 bMultiPart = TRUE;
356 if (debug)
358 fprintf(debug, "graph part[] nchanged=%d, bMultiPart=%d\n",
359 nchanged, bMultiPart);
362 while (nchanged > 0);
364 return bMultiPart;
367 void mk_graph_ilist(FILE *fplog,
368 const t_ilist *ilist, int at_start, int at_end,
369 gmx_bool bShakeOnly, gmx_bool bSettle,
370 t_graph *g)
372 int *nbond;
373 int i, nbtot;
374 gmx_bool bMultiPart;
376 /* The naming is somewhat confusing, but we need g->at0 and g->at1
377 * for shifthing coordinates to a new array (not in place) when
378 * some atoms are not connected by the graph, which runs from
379 * g->at_start (>= g->at0) to g->at_end (<= g->at1).
381 g->at0 = at_start;
382 g->at1 = at_end;
384 snew(nbond, at_end);
385 nbtot = calc_start_end(fplog, g, ilist, at_start, at_end, nbond);
387 if (g->at_start >= g->at_end)
389 g->at_start = at_start;
390 g->at_end = at_end;
391 g->nnodes = 0;
392 g->nbound = 0;
394 else
396 g->nnodes = g->at_end - g->at_start;
397 snew(g->nedge, g->nnodes);
398 snew(g->edge, g->nnodes);
399 /* Allocate a single array and set pointers into it */
400 snew(g->edge[0], nbtot);
401 for (i = 1; (i < g->nnodes); i++)
403 g->edge[i] = g->edge[i-1] + nbond[g->at_start+i-1];
406 if (!bShakeOnly)
408 /* First add all the real bonds: they should determine the molecular
409 * graph.
411 for (i = 0; (i < F_NRE); i++)
413 if (interaction_function[i].flags & IF_CHEMBOND)
415 mk_igraph(g, i, &(ilist[i]), at_start, at_end, nullptr);
419 /* Determine of which separated parts the IF_CHEMBOND graph consists.
420 * Store the parts in the nbond array.
422 bMultiPart = determine_graph_parts(g, nbond);
424 if (bMultiPart)
426 /* Then add all the other interactions in fixed lists,
427 * but only when they connect parts of the graph
428 * that are not connected through IF_CHEMBOND interactions.
430 for (i = 0; (i < F_NRE); i++)
432 if (!(interaction_function[i].flags & IF_CHEMBOND))
434 mk_igraph(g, i, &(ilist[i]), at_start, at_end, nbond);
439 /* Removed all the unused space from the edge array */
440 compact_graph(fplog, g);
442 else
444 /* This is a special thing used in splitter.c to generate shake-blocks */
445 mk_igraph(g, F_CONSTR, &(ilist[F_CONSTR]), at_start, at_end, nullptr);
446 if (bSettle)
448 mk_igraph(g, F_SETTLE, &(ilist[F_SETTLE]), at_start, at_end, nullptr);
451 g->nbound = 0;
452 for (i = 0; (i < g->nnodes); i++)
454 if (g->nedge[i] > 0)
456 g->nbound++;
461 g->negc = 0;
462 g->egc = nullptr;
464 sfree(nbond);
466 snew(g->ishift, g->at1);
468 if (gmx_debug_at)
470 p_graph(debug, "graph", g);
474 t_graph *mk_graph(FILE *fplog,
475 const t_idef *idef, int at_start, int at_end,
476 gmx_bool bShakeOnly, gmx_bool bSettle)
478 t_graph *g;
480 snew(g, 1);
482 mk_graph_ilist(fplog, idef->il, at_start, at_end, bShakeOnly, bSettle, g);
484 return g;
487 void done_graph(t_graph *g)
489 GCHECK(g);
490 if (g->nnodes > 0)
492 sfree(g->nedge);
493 sfree(g->edge[0]);
494 sfree(g->edge);
495 sfree(g->egc);
497 sfree(g->ishift);
500 /************************************************************
502 * S H I F T C A L C U L A T I O N C O D E
504 ************************************************************/
506 static void mk_1shift_tric(int npbcdim, const matrix box, const rvec hbox,
507 const rvec xi, const rvec xj, int *mi, int *mj)
509 /* Calculate periodicity for triclinic box... */
510 int m, d;
511 rvec dx;
513 rvec_sub(xi, xj, dx);
515 mj[ZZ] = 0;
516 for (m = npbcdim-1; (m >= 0); m--)
518 /* If dx < hbox, then xj will be reduced by box, so that
519 * xi - xj will be bigger
521 if (dx[m] < -hbox[m])
523 mj[m] = mi[m]-1;
524 for (d = m-1; d >= 0; d--)
526 dx[d] += box[m][d];
529 else if (dx[m] >= hbox[m])
531 mj[m] = mi[m]+1;
532 for (d = m-1; d >= 0; d--)
534 dx[d] -= box[m][d];
537 else
539 mj[m] = mi[m];
544 static void mk_1shift(int npbcdim, const rvec hbox, const rvec xi, const rvec xj,
545 int *mi, int *mj)
547 /* Calculate periodicity for rectangular box... */
548 int m;
549 rvec dx;
551 rvec_sub(xi, xj, dx);
553 mj[ZZ] = 0;
554 for (m = 0; (m < npbcdim); m++)
556 /* If dx < hbox, then xj will be reduced by box, so that
557 * xi - xj will be bigger
559 if (dx[m] < -hbox[m])
561 mj[m] = mi[m]-1;
563 else if (dx[m] >= hbox[m])
565 mj[m] = mi[m]+1;
567 else
569 mj[m] = mi[m];
574 static void mk_1shift_screw(const matrix box, const rvec hbox,
575 const rvec xi, const rvec xj, int *mi, int *mj)
577 /* Calculate periodicity for rectangular box... */
578 int signi, m;
579 rvec dx;
581 if ((mi[XX] > 0 && mi[XX] % 2 == 1) ||
582 (mi[XX] < 0 && -mi[XX] % 2 == 1))
584 signi = -1;
586 else
588 signi = 1;
591 rvec_sub(xi, xj, dx);
593 if (dx[XX] < -hbox[XX])
595 mj[XX] = mi[XX] - 1;
597 else if (dx[XX] >= hbox[XX])
599 mj[XX] = mi[XX] + 1;
601 else
603 mj[XX] = mi[XX];
605 if (mj[XX] != mi[XX])
607 /* Rotate */
608 dx[YY] = xi[YY] - (box[YY][YY] + box[ZZ][YY] - xj[YY]);
609 dx[ZZ] = xi[ZZ] - (box[ZZ][ZZ] - xj[ZZ]);
611 for (m = 1; (m < DIM); m++)
613 /* The signs are taken such that we can first shift x and rotate
614 * and then shift y and z.
616 if (dx[m] < -hbox[m])
618 mj[m] = mi[m] - signi;
620 else if (dx[m] >= hbox[m])
622 mj[m] = mi[m] + signi;
624 else
626 mj[m] = mi[m];
631 static int mk_grey(egCol egc[], t_graph *g, int *AtomI,
632 int npbcdim, const matrix box, const rvec x[], int *nerror)
634 int m, j, ng, ai, aj, g0;
635 rvec dx, hbox;
636 gmx_bool bTriclinic;
637 ivec is_aj;
638 t_pbc pbc;
640 for (m = 0; (m < DIM); m++)
642 hbox[m] = box[m][m]*0.5;
644 bTriclinic = TRICLINIC(box);
646 g0 = g->at_start;
647 ng = 0;
648 ai = g0 + *AtomI;
650 /* Loop over all the bonds */
651 for (j = 0; (j < g->nedge[ai-g0]); j++)
653 aj = g->edge[ai-g0][j];
654 /* If there is a white one, make it grey and set pbc */
655 if (g->bScrewPBC)
657 mk_1shift_screw(box, hbox, x[ai], x[aj], g->ishift[ai], is_aj);
659 else if (bTriclinic)
661 mk_1shift_tric(npbcdim, box, hbox, x[ai], x[aj], g->ishift[ai], is_aj);
663 else
665 mk_1shift(npbcdim, hbox, x[ai], x[aj], g->ishift[ai], is_aj);
668 if (egc[aj-g0] == egcolWhite)
670 if (aj - g0 < *AtomI)
672 *AtomI = aj - g0;
674 egc[aj-g0] = egcolGrey;
676 copy_ivec(is_aj, g->ishift[aj]);
678 ng++;
680 else if ((is_aj[XX] != g->ishift[aj][XX]) ||
681 (is_aj[YY] != g->ishift[aj][YY]) ||
682 (is_aj[ZZ] != g->ishift[aj][ZZ]))
684 if (gmx_debug_at)
686 set_pbc(&pbc, -1, box);
687 pbc_dx(&pbc, x[ai], x[aj], dx);
688 fprintf(debug, "mk_grey: shifts for atom %d due to atom %d\n"
689 "are (%d,%d,%d), should be (%d,%d,%d)\n"
690 "dx = (%g,%g,%g)\n",
691 aj+1, ai+1, is_aj[XX], is_aj[YY], is_aj[ZZ],
692 g->ishift[aj][XX], g->ishift[aj][YY], g->ishift[aj][ZZ],
693 dx[XX], dx[YY], dx[ZZ]);
695 (*nerror)++;
698 return ng;
701 static int first_colour(int fC, egCol Col, t_graph *g, egCol egc[])
702 /* Return the first node with colour Col starting at fC.
703 * return -1 if none found.
706 int i;
708 for (i = fC; (i < g->nnodes); i++)
710 if ((g->nedge[i] > 0) && (egc[i] == Col))
712 return i;
716 return -1;
719 void mk_mshift(FILE *log, t_graph *g, int ePBC,
720 const matrix box, const rvec x[])
722 static int nerror_tot = 0;
723 int npbcdim;
724 int ng, nnodes, i;
725 int nW, nG, nB; /* Number of Grey, Black, White */
726 int fW, fG; /* First of each category */
727 int nerror = 0;
729 g->bScrewPBC = (ePBC == epbcSCREW);
731 if (ePBC == epbcXY)
733 npbcdim = 2;
735 else
737 npbcdim = 3;
740 GCHECK(g);
741 /* This puts everything in the central box, that is does not move it
742 * at all. If we return without doing this for a system without bonds
743 * (i.e. only settles) all water molecules are moved to the opposite octant
745 for (i = g->at0; (i < g->at1); i++)
747 g->ishift[i][XX] = g->ishift[i][YY] = g->ishift[i][ZZ] = 0;
750 if (!g->nbound)
752 return;
755 nnodes = g->nnodes;
756 if (nnodes > g->negc)
758 g->negc = nnodes;
759 srenew(g->egc, g->negc);
761 memset(g->egc, 0, (size_t)(nnodes*sizeof(g->egc[0])));
763 nW = g->nbound;
764 nG = 0;
765 nB = 0;
767 fW = 0;
769 /* We even have a loop invariant:
770 * nW+nG+nB == g->nbound
772 #ifdef DEBUG2
773 fprintf(log, "Starting W loop\n");
774 #endif
775 while (nW > 0)
777 /* Find the first white, this will allways be a larger
778 * number than before, because no nodes are made white
779 * in the loop
781 if ((fW = first_colour(fW, egcolWhite, g, g->egc)) == -1)
783 gmx_fatal(FARGS, "No WHITE nodes found while nW=%d\n", nW);
786 /* Make the first white node grey */
787 g->egc[fW] = egcolGrey;
788 nG++;
789 nW--;
791 /* Initial value for the first grey */
792 fG = fW;
793 #ifdef DEBUG2
794 fprintf(log, "Starting G loop (nW=%d, nG=%d, nB=%d, total %d)\n",
795 nW, nG, nB, nW+nG+nB);
796 #endif
797 while (nG > 0)
799 if ((fG = first_colour(fG, egcolGrey, g, g->egc)) == -1)
801 gmx_fatal(FARGS, "No GREY nodes found while nG=%d\n", nG);
804 /* Make the first grey node black */
805 g->egc[fG] = egcolBlack;
806 nB++;
807 nG--;
809 /* Make all the neighbours of this black node grey
810 * and set their periodicity
812 ng = mk_grey(g->egc, g, &fG, npbcdim, box, x, &nerror);
813 /* ng is the number of white nodes made grey */
814 nG += ng;
815 nW -= ng;
818 if (nerror > 0)
820 nerror_tot++;
821 if (nerror_tot <= 100)
823 fprintf(stderr, "There were %d inconsistent shifts. Check your topology\n",
824 nerror);
825 if (log)
827 fprintf(log, "There were %d inconsistent shifts. Check your topology\n",
828 nerror);
831 if (nerror_tot == 100)
833 fprintf(stderr, "Will stop reporting inconsistent shifts\n");
834 if (log)
836 fprintf(log, "Will stop reporting inconsistent shifts\n");
842 /************************************************************
844 * A C T U A L S H I F T C O D E
846 ************************************************************/
848 void shift_x(const t_graph *g, const matrix box, const rvec x[], rvec x_s[])
850 ivec *is;
851 int g0, g1;
852 int j, tx, ty, tz;
854 GCHECK(g);
855 g0 = g->at_start;
856 g1 = g->at_end;
857 is = g->ishift;
859 for (j = g->at0; j < g0; j++)
861 copy_rvec(x[j], x_s[j]);
864 if (g->bScrewPBC)
866 for (j = g0; (j < g1); j++)
868 tx = is[j][XX];
869 ty = is[j][YY];
870 tz = is[j][ZZ];
872 if ((tx > 0 && tx % 2 == 1) ||
873 (tx < 0 && -tx %2 == 1))
875 x_s[j][XX] = x[j][XX] + tx*box[XX][XX];
876 x_s[j][YY] = box[YY][YY] + box[ZZ][YY] - x[j][YY];
877 x_s[j][ZZ] = box[ZZ][ZZ] - x[j][ZZ];
879 else
881 x_s[j][XX] = x[j][XX];
883 x_s[j][YY] = x[j][YY] + ty*box[YY][YY] + tz*box[ZZ][YY];
884 x_s[j][ZZ] = x[j][ZZ] + tz*box[ZZ][ZZ];
887 else if (TRICLINIC(box))
889 for (j = g0; (j < g1); j++)
891 tx = is[j][XX];
892 ty = is[j][YY];
893 tz = is[j][ZZ];
895 x_s[j][XX] = x[j][XX]+tx*box[XX][XX]+ty*box[YY][XX]+tz*box[ZZ][XX];
896 x_s[j][YY] = x[j][YY]+ty*box[YY][YY]+tz*box[ZZ][YY];
897 x_s[j][ZZ] = x[j][ZZ]+tz*box[ZZ][ZZ];
900 else
902 for (j = g0; (j < g1); j++)
904 tx = is[j][XX];
905 ty = is[j][YY];
906 tz = is[j][ZZ];
908 x_s[j][XX] = x[j][XX]+tx*box[XX][XX];
909 x_s[j][YY] = x[j][YY]+ty*box[YY][YY];
910 x_s[j][ZZ] = x[j][ZZ]+tz*box[ZZ][ZZ];
914 for (j = g1; j < g->at1; j++)
916 copy_rvec(x[j], x_s[j]);
920 void shift_self(const t_graph *g, const matrix box, rvec x[])
922 ivec *is;
923 int g0, g1;
924 int j, tx, ty, tz;
926 if (g->bScrewPBC)
928 gmx_incons("screw pbc not implemented for shift_self");
931 g0 = g->at_start;
932 g1 = g->at_end;
933 is = g->ishift;
935 #ifdef DEBUG
936 fprintf(stderr, "Shifting atoms %d to %d\n", g0, g0+gn);
937 #endif
938 if (TRICLINIC(box))
940 for (j = g0; (j < g1); j++)
942 tx = is[j][XX];
943 ty = is[j][YY];
944 tz = is[j][ZZ];
946 x[j][XX] = x[j][XX]+tx*box[XX][XX]+ty*box[YY][XX]+tz*box[ZZ][XX];
947 x[j][YY] = x[j][YY]+ty*box[YY][YY]+tz*box[ZZ][YY];
948 x[j][ZZ] = x[j][ZZ]+tz*box[ZZ][ZZ];
951 else
953 for (j = g0; (j < g1); j++)
955 tx = is[j][XX];
956 ty = is[j][YY];
957 tz = is[j][ZZ];
959 x[j][XX] = x[j][XX]+tx*box[XX][XX];
960 x[j][YY] = x[j][YY]+ty*box[YY][YY];
961 x[j][ZZ] = x[j][ZZ]+tz*box[ZZ][ZZ];
966 void unshift_x(const t_graph *g, const matrix box, rvec x[], const rvec x_s[])
968 ivec *is;
969 int g0, g1;
970 int j, tx, ty, tz;
972 if (g->bScrewPBC)
974 gmx_incons("screw pbc not implemented (yet) for unshift_x");
977 g0 = g->at_start;
978 g1 = g->at_end;
979 is = g->ishift;
981 for (j = g->at0; j < g0; j++)
983 copy_rvec(x_s[j], x[j]);
986 if (TRICLINIC(box))
988 for (j = g0; (j < g1); j++)
990 tx = is[j][XX];
991 ty = is[j][YY];
992 tz = is[j][ZZ];
994 x[j][XX] = x_s[j][XX]-tx*box[XX][XX]-ty*box[YY][XX]-tz*box[ZZ][XX];
995 x[j][YY] = x_s[j][YY]-ty*box[YY][YY]-tz*box[ZZ][YY];
996 x[j][ZZ] = x_s[j][ZZ]-tz*box[ZZ][ZZ];
999 else
1001 for (j = g0; (j < g1); j++)
1003 tx = is[j][XX];
1004 ty = is[j][YY];
1005 tz = is[j][ZZ];
1007 x[j][XX] = x_s[j][XX]-tx*box[XX][XX];
1008 x[j][YY] = x_s[j][YY]-ty*box[YY][YY];
1009 x[j][ZZ] = x_s[j][ZZ]-tz*box[ZZ][ZZ];
1013 for (j = g1; j < g->at1; j++)
1015 copy_rvec(x_s[j], x[j]);
1019 void unshift_self(const t_graph *g, const matrix box, rvec x[])
1021 ivec *is;
1022 int g0, g1;
1023 int j, tx, ty, tz;
1025 if (g->bScrewPBC)
1027 gmx_incons("screw pbc not implemented for unshift_self");
1030 g0 = g->at_start;
1031 g1 = g->at_end;
1032 is = g->ishift;
1034 if (TRICLINIC(box))
1036 for (j = g0; (j < g1); j++)
1038 tx = is[j][XX];
1039 ty = is[j][YY];
1040 tz = is[j][ZZ];
1042 x[j][XX] = x[j][XX]-tx*box[XX][XX]-ty*box[YY][XX]-tz*box[ZZ][XX];
1043 x[j][YY] = x[j][YY]-ty*box[YY][YY]-tz*box[ZZ][YY];
1044 x[j][ZZ] = x[j][ZZ]-tz*box[ZZ][ZZ];
1047 else
1049 for (j = g0; (j < g1); j++)
1051 tx = is[j][XX];
1052 ty = is[j][YY];
1053 tz = is[j][ZZ];
1055 x[j][XX] = x[j][XX]-tx*box[XX][XX];
1056 x[j][YY] = x[j][YY]-ty*box[YY][YY];
1057 x[j][ZZ] = x[j][ZZ]-tz*box[ZZ][ZZ];
1061 #undef GCHECK