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,2018, 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.
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"
51 #include "gromacs/utility/strconvert.h"
52 #include "gromacs/utility/stringutil.h"
54 /************************************************************
56 * S H I F T U T I L I T I E S
58 ************************************************************/
61 /************************************************************
63 * G R A P H G E N E R A T I O N C O D E
65 ************************************************************/
67 static void add_gbond(t_graph *g, int a0, int a1)
73 inda0 = a0 - g->at_start;
74 inda1 = a1 - g->at_start;
76 /* Search for a direct edge between a0 and a1.
77 * All egdes are bidirectional, so we only need to search one way.
79 for (i = 0; (i < g->nedge[inda0] && !bFound); i++)
81 bFound = (g->edge[inda0][i] == a1);
86 g->edge[inda0][g->nedge[inda0]++] = a1;
87 g->edge[inda1][g->nedge[inda1]++] = a0;
91 /* Make the actual graph for an ilist, returns whether an edge was added.
93 * When a non-null part array is supplied with part indices for each atom,
94 * edges are only added when atoms have a different part index.
96 static bool mk_igraph(t_graph *g, int ftype, const t_ilist *il,
97 int at_start, int at_end,
103 bool addedEdge = false;
111 np = interaction_function[ftype].nratoms;
113 if (np > 1 && ia[1] >= at_start && ia[1] < at_end)
115 if (ia[np] >= at_end)
118 "Molecule in topology has atom numbers below and "
119 "above natoms (%d).\n"
120 "You are probably trying to use a trajectory which does "
121 "not match the first %d atoms of the run input file.\n"
122 "You can make a matching run input file with gmx convert-tpr.",
125 if (ftype == F_SETTLE)
127 /* Bond all the atoms in the settle */
128 add_gbond(g, ia[1], ia[2]);
129 add_gbond(g, ia[1], ia[3]);
132 else if (part == nullptr)
134 /* Simply add this bond */
135 for (j = 1; j < np; j++)
137 add_gbond(g, ia[j], ia[j+1]);
143 /* Add this bond when it connects two unlinked parts of the graph */
144 for (j = 1; j < np; j++)
146 if (part[ia[j]] != part[ia[j+1]])
148 add_gbond(g, ia[j], ia[j+1]);
161 [[noreturn]] static void g_error(int line, const char *file)
163 gmx_fatal(FARGS, "Trying to print nonexistent graph (file %s, line %d)",
166 #define GCHECK(g) if ((g) == NULL) g_error(__LINE__, __FILE__)
168 void p_graph(FILE *log, const char *title, t_graph *g)
171 const char *cc[egcolNR] = { "W", "G", "B" };
174 fprintf(log, "graph: %s\n", title);
175 fprintf(log, "nnodes: %d\n", g->nnodes);
176 fprintf(log, "nbound: %d\n", g->nbound);
177 fprintf(log, "start: %d\n", g->at_start);
178 fprintf(log, "end: %d\n", g->at_end);
179 fprintf(log, " atom shiftx shifty shiftz C nedg e1 e2 etc.\n");
180 for (i = 0; (i < g->nnodes); i++)
184 fprintf(log, "%5d%7d%7d%7d %1s%5d", g->at_start+i+1,
185 g->ishift[g->at_start+i][XX],
186 g->ishift[g->at_start+i][YY],
187 g->ishift[g->at_start+i][ZZ],
188 (g->negc > 0) ? cc[g->egc[i]] : " ",
190 for (j = 0; (j < g->nedge[i]); j++)
192 fprintf(log, " %5d", g->edge[i][j]+1);
200 static void calc_1se(t_graph *g, int ftype, const t_ilist *il,
201 int nbond[], int at_start, int at_end)
203 int k, nratoms, end, j;
209 for (j = 0; (j < end); j += nratoms+1, ia += nratoms+1)
211 nratoms = interaction_function[ftype].nratoms;
213 if (ftype == F_SETTLE)
216 if (iaa >= at_start && iaa < at_end)
221 g->at_start = std::min(g->at_start, iaa);
222 g->at_end = std::max(g->at_end, iaa+2+1);
227 for (k = 1; (k <= nratoms); k++)
230 if (iaa >= at_start && iaa < at_end)
232 g->at_start = std::min(g->at_start, iaa);
233 g->at_end = std::max(g->at_end, iaa+1);
234 /* When making the graph we (might) link all atoms in an interaction
235 * sequentially. Therefore the end atoms add 1 to the count,
236 * the middle atoms 2.
238 if (k == 1 || k == nratoms)
252 static int calc_start_end(FILE *fplog, t_graph *g, const t_ilist il[],
253 int at_start, int at_end,
258 g->at_start = at_end;
261 /* First add all the real bonds: they should determine the molecular
264 for (i = 0; (i < F_NRE); i++)
266 if (interaction_function[i].flags & IF_CHEMBOND)
268 calc_1se(g, i, &il[i], nbond, at_start, at_end);
271 /* Then add all the other interactions in fixed lists, but first
272 * check to see what's there already.
274 for (i = 0; (i < F_NRE); i++)
276 if (!(interaction_function[i].flags & IF_CHEMBOND))
278 calc_1se(g, i, &il[i], nbond, at_start, at_end);
284 for (i = g->at_start; (i < g->at_end); i++)
287 nnb = std::max(nnb, nbond[i]);
291 fprintf(fplog, "Max number of connections per atom is %d\n", nnb);
292 fprintf(fplog, "Total number of connections is %d\n", nbtot);
299 static void compact_graph(FILE *fplog, t_graph *g)
301 int i, j, n, max_nedge;
305 for (i = 0; i < g->nnodes; i++)
307 for (j = 0; j < g->nedge[i]; j++)
309 g->edge[0][n++] = g->edge[i][j];
311 max_nedge = std::max(max_nedge, g->nedge[i]);
313 srenew(g->edge[0], n);
314 /* set pointers after srenew because edge[0] might move */
315 for (i = 1; i < g->nnodes; i++)
317 g->edge[i] = g->edge[i-1] + g->nedge[i-1];
322 fprintf(fplog, "Max number of graph edges per atom is %d\n",
324 fprintf(fplog, "Total number of graph edges is %d\n", n);
328 static gmx_bool determine_graph_parts(t_graph *g, int *part)
335 /* Initialize the part array with all entries different */
336 for (at_i = g->at_start; at_i < g->at_end; at_i++)
341 /* Loop over the graph until the part array is fixed */
346 for (i = 0; (i < g->nnodes); i++)
348 at_i = g->at_start + i;
350 for (e = 0; e < g->nedge[i]; e++)
352 /* Set part for both nodes to the minimum */
353 if (part[at_i2[e]] > part[at_i])
355 part[at_i2[e]] = part[at_i];
358 else if (part[at_i2[e]] < part[at_i])
360 part[at_i] = part[at_i2[e]];
364 if (part[at_i] != part[g->at_start])
371 fprintf(debug, "graph part[] nchanged=%d, bMultiPart=%s\n",
372 nchanged, gmx::boolToString(bMultiPart));
375 while (nchanged > 0);
380 void mk_graph_ilist(FILE *fplog,
381 const t_ilist *ilist, int at_start, int at_end,
382 gmx_bool bShakeOnly, gmx_bool bSettle,
389 /* The naming is somewhat confusing, but we need g->at0 and g->at1
390 * for shifthing coordinates to a new array (not in place) when
391 * some atoms are not connected by the graph, which runs from
392 * g->at_start (>= g->at0) to g->at_end (<= g->at1).
396 g->parts = t_graph::BondedParts::Single;
399 nbtot = calc_start_end(fplog, g, ilist, at_start, at_end, nbond);
401 if (g->at_start >= g->at_end)
403 g->at_start = at_start;
410 g->nnodes = g->at_end - g->at_start;
411 snew(g->nedge, g->nnodes);
412 snew(g->edge, g->nnodes);
413 /* Allocate a single array and set pointers into it */
414 snew(g->edge[0], nbtot);
415 for (i = 1; (i < g->nnodes); i++)
417 g->edge[i] = g->edge[i-1] + nbond[g->at_start+i-1];
422 /* First add all the real bonds: they should determine the molecular
425 for (i = 0; (i < F_NRE); i++)
427 if (interaction_function[i].flags & IF_CHEMBOND)
429 mk_igraph(g, i, &(ilist[i]), at_start, at_end, nullptr);
433 /* Determine of which separated parts the IF_CHEMBOND graph consists.
434 * Store the parts in the nbond array.
436 bMultiPart = determine_graph_parts(g, nbond);
440 /* Then add all the other interactions in fixed lists,
441 * but only when they connect parts of the graph
442 * that are not connected through IF_CHEMBOND interactions.
444 bool addedEdge = false;
445 for (i = 0; (i < F_NRE); i++)
447 if (!(interaction_function[i].flags & IF_CHEMBOND))
449 bool addedEdgeForType =
450 mk_igraph(g, i, &(ilist[i]), at_start, at_end, nbond);
451 addedEdge = (addedEdge || addedEdgeForType);
457 g->parts = t_graph::BondedParts::MultipleConnected;
461 g->parts = t_graph::BondedParts::MultipleDisconnected;
465 /* Removed all the unused space from the edge array */
466 compact_graph(fplog, g);
470 /* This is a special thing used in splitter.c to generate shake-blocks */
471 mk_igraph(g, F_CONSTR, &(ilist[F_CONSTR]), at_start, at_end, nullptr);
474 mk_igraph(g, F_SETTLE, &(ilist[F_SETTLE]), at_start, at_end, nullptr);
478 for (i = 0; (i < g->nnodes); i++)
492 snew(g->ishift, g->at1);
496 p_graph(debug, "graph", g);
500 t_graph *mk_graph(FILE *fplog,
501 const t_idef *idef, int at_start, int at_end,
502 gmx_bool bShakeOnly, gmx_bool bSettle)
508 mk_graph_ilist(fplog, idef->il, at_start, at_end, bShakeOnly, bSettle, g);
513 void done_graph(t_graph *g)
526 /************************************************************
528 * S H I F T C A L C U L A T I O N C O D E
530 ************************************************************/
532 static void mk_1shift_tric(int npbcdim, const matrix box, const rvec hbox,
533 const rvec xi, const rvec xj, const int *mi, int *mj)
535 /* Calculate periodicity for triclinic box... */
539 rvec_sub(xi, xj, dx);
542 for (m = npbcdim-1; (m >= 0); m--)
544 /* If dx < hbox, then xj will be reduced by box, so that
545 * xi - xj will be bigger
547 if (dx[m] < -hbox[m])
550 for (d = m-1; d >= 0; d--)
555 else if (dx[m] >= hbox[m])
558 for (d = m-1; d >= 0; d--)
570 static void mk_1shift(int npbcdim, const rvec hbox, const rvec xi, const rvec xj,
571 const int *mi, int *mj)
573 /* Calculate periodicity for rectangular box... */
577 rvec_sub(xi, xj, dx);
580 for (m = 0; (m < npbcdim); m++)
582 /* If dx < hbox, then xj will be reduced by box, so that
583 * xi - xj will be bigger
585 if (dx[m] < -hbox[m])
589 else if (dx[m] >= hbox[m])
600 static void mk_1shift_screw(const matrix box, const rvec hbox,
601 const rvec xi, const rvec xj, const int *mi, int *mj)
603 /* Calculate periodicity for rectangular box... */
607 if ((mi[XX] > 0 && mi[XX] % 2 == 1) ||
608 (mi[XX] < 0 && -mi[XX] % 2 == 1))
617 rvec_sub(xi, xj, dx);
619 if (dx[XX] < -hbox[XX])
623 else if (dx[XX] >= hbox[XX])
631 if (mj[XX] != mi[XX])
634 dx[YY] = xi[YY] - (box[YY][YY] + box[ZZ][YY] - xj[YY]);
635 dx[ZZ] = xi[ZZ] - (box[ZZ][ZZ] - xj[ZZ]);
637 for (m = 1; (m < DIM); m++)
639 /* The signs are taken such that we can first shift x and rotate
640 * and then shift y and z.
642 if (dx[m] < -hbox[m])
644 mj[m] = mi[m] - signi;
646 else if (dx[m] >= hbox[m])
648 mj[m] = mi[m] + signi;
657 static int mk_grey(egCol egc[], t_graph *g, int *AtomI,
658 int npbcdim, const matrix box, const rvec x[], int *nerror)
660 int m, j, ng, ai, aj, g0;
666 for (m = 0; (m < DIM); m++)
668 hbox[m] = box[m][m]*0.5;
670 bTriclinic = TRICLINIC(box);
676 /* Loop over all the bonds */
677 for (j = 0; (j < g->nedge[ai-g0]); j++)
679 aj = g->edge[ai-g0][j];
680 /* If there is a white one, make it grey and set pbc */
683 mk_1shift_screw(box, hbox, x[ai], x[aj], g->ishift[ai], is_aj);
687 mk_1shift_tric(npbcdim, box, hbox, x[ai], x[aj], g->ishift[ai], is_aj);
691 mk_1shift(npbcdim, hbox, x[ai], x[aj], g->ishift[ai], is_aj);
694 if (egc[aj-g0] == egcolWhite)
696 if (aj - g0 < *AtomI)
700 egc[aj-g0] = egcolGrey;
702 copy_ivec(is_aj, g->ishift[aj]);
706 else if ((is_aj[XX] != g->ishift[aj][XX]) ||
707 (is_aj[YY] != g->ishift[aj][YY]) ||
708 (is_aj[ZZ] != g->ishift[aj][ZZ]))
712 set_pbc(&pbc, -1, box);
713 pbc_dx(&pbc, x[ai], x[aj], dx);
714 fprintf(debug, "mk_grey: shifts for atom %d due to atom %d\n"
715 "are (%d,%d,%d), should be (%d,%d,%d)\n"
717 aj+1, ai+1, is_aj[XX], is_aj[YY], is_aj[ZZ],
718 g->ishift[aj][XX], g->ishift[aj][YY], g->ishift[aj][ZZ],
719 dx[XX], dx[YY], dx[ZZ]);
727 static int first_colour(int fC, egCol Col, t_graph *g, const egCol egc[])
728 /* Return the first node with colour Col starting at fC.
729 * return -1 if none found.
734 for (i = fC; (i < g->nnodes); i++)
736 if ((g->nedge[i] > 0) && (egc[i] == Col))
745 /* Returns the maximum length of the graph edges for coordinates x */
746 static real maxEdgeLength(const t_graph g,
753 set_pbc(&pbc, ePBC, box);
755 real maxEdgeLength2 = 0;
757 for (int node = 0; node < g.nnodes; node++)
759 for (int edge = 0; edge < g.nedge[node]; edge++)
761 int nodeJ = g.edge[node][edge];
763 pbc_dx(&pbc, x[g.at0 + node], x[g.at0 + nodeJ], dx);
764 maxEdgeLength2 = std::max(maxEdgeLength2, norm2(dx));
768 return std::sqrt(maxEdgeLength2);
771 void mk_mshift(FILE *log, t_graph *g, int ePBC,
772 const matrix box, const rvec x[])
774 static int nerror_tot = 0;
777 int nW, nG, nB; /* Number of Grey, Black, White */
778 int fW, fG; /* First of each category */
781 g->bScrewPBC = (ePBC == epbcSCREW);
793 /* This puts everything in the central box, that is does not move it
794 * at all. If we return without doing this for a system without bonds
795 * (i.e. only settles) all water molecules are moved to the opposite octant
797 for (i = g->at0; (i < g->at1); i++)
799 g->ishift[i][XX] = g->ishift[i][YY] = g->ishift[i][ZZ] = 0;
808 if (nnodes > g->negc)
811 srenew(g->egc, g->negc);
813 memset(g->egc, 0, static_cast<size_t>(nnodes*sizeof(g->egc[0])));
821 /* We even have a loop invariant:
822 * nW+nG+nB == g->nbound
825 fprintf(log, "Starting W loop\n");
829 /* Find the first white, this will allways be a larger
830 * number than before, because no nodes are made white
833 if ((fW = first_colour(fW, egcolWhite, g, g->egc)) == -1)
835 gmx_fatal(FARGS, "No WHITE nodes found while nW=%d\n", nW);
838 /* Make the first white node grey */
839 g->egc[fW] = egcolGrey;
843 /* Initial value for the first grey */
846 fprintf(log, "Starting G loop (nW=%d, nG=%d, nB=%d, total %d)\n",
847 nW, nG, nB, nW+nG+nB);
851 if ((fG = first_colour(fG, egcolGrey, g, g->egc)) == -1)
853 gmx_fatal(FARGS, "No GREY nodes found while nG=%d\n", nG);
856 /* Make the first grey node black */
857 g->egc[fG] = egcolBlack;
861 /* Make all the neighbours of this black node grey
862 * and set their periodicity
864 ng = mk_grey(g->egc, g, &fG, npbcdim, box, x, &nerror);
865 /* ng is the number of white nodes made grey */
872 /* We use a threshold of 0.25*boxSize for generating a fatal error
873 * to allow removing PBC for systems with periodic molecules.
875 * TODO: Consider a better solution for systems with periodic
876 * molecules. Ideally analysis tools should only ask to make
877 * non-periodic molecules whole in a system with periodic mols.
879 constexpr real c_relativeDistanceThreshold = 0.25;
881 int numPbcDimensions = ePBC2npbcdim(ePBC);
882 GMX_RELEASE_ASSERT(numPbcDimensions > 0, "Expect PBC with graph");
883 real minBoxSize = norm(box[XX]);
884 for (int d = 1; d < numPbcDimensions; d++)
886 minBoxSize = std::min(minBoxSize, norm(box[d]));
888 real maxDistance = maxEdgeLength(*g, ePBC, box, x);
889 if (maxDistance >= c_relativeDistanceThreshold*minBoxSize)
891 std::string mesg = gmx::formatString("There are inconsistent shifts over periodic boundaries in a molecule type consisting of %d atoms. The longest distance involved in such interactions is %.3f nm which is %s half the box length.",
892 g->at1 - g->at0, maxDistance,
893 maxDistance >= 0.5*minBoxSize ? "above" : "close to");
897 case t_graph::BondedParts::MultipleConnected:
898 /* Ideally we should check if the long distances are
899 * actually between the parts, but that would require
900 * a lot of extra code.
902 mesg += " This molecule type consists of muliple parts, e.g. monomers, that are connected by interactions that are not chemical bonds, e.g. restraints. Such systems can not be treated. The only solution is increasing the box size.";
905 mesg += " Either you have excessively large distances between atoms in bonded interactions or your system is exploding.";
907 gmx_fatal(FARGS, "%s", mesg.c_str());
910 /* The most likely reason for arriving here is a periodic molecule. */
913 if (nerror_tot <= 100)
915 fprintf(stderr, "There were %d inconsistent shifts. Check your topology\n",
919 fprintf(log, "There were %d inconsistent shifts. Check your topology\n",
923 if (nerror_tot == 100)
925 fprintf(stderr, "Will stop reporting inconsistent shifts\n");
928 fprintf(log, "Will stop reporting inconsistent shifts\n");
934 /************************************************************
936 * A C T U A L S H I F T C O D E
938 ************************************************************/
940 void shift_x(const t_graph *g, const matrix box, const rvec x[], rvec x_s[])
951 for (j = g->at0; j < g0; j++)
953 copy_rvec(x[j], x_s[j]);
958 for (j = g0; (j < g1); j++)
964 if ((tx > 0 && tx % 2 == 1) ||
965 (tx < 0 && -tx %2 == 1))
967 x_s[j][XX] = x[j][XX] + tx*box[XX][XX];
968 x_s[j][YY] = box[YY][YY] + box[ZZ][YY] - x[j][YY];
969 x_s[j][ZZ] = box[ZZ][ZZ] - x[j][ZZ];
973 x_s[j][XX] = x[j][XX];
975 x_s[j][YY] = x[j][YY] + ty*box[YY][YY] + tz*box[ZZ][YY];
976 x_s[j][ZZ] = x[j][ZZ] + tz*box[ZZ][ZZ];
979 else if (TRICLINIC(box))
981 for (j = g0; (j < g1); j++)
987 x_s[j][XX] = x[j][XX]+tx*box[XX][XX]+ty*box[YY][XX]+tz*box[ZZ][XX];
988 x_s[j][YY] = x[j][YY]+ty*box[YY][YY]+tz*box[ZZ][YY];
989 x_s[j][ZZ] = x[j][ZZ]+tz*box[ZZ][ZZ];
994 for (j = g0; (j < g1); j++)
1000 x_s[j][XX] = x[j][XX]+tx*box[XX][XX];
1001 x_s[j][YY] = x[j][YY]+ty*box[YY][YY];
1002 x_s[j][ZZ] = x[j][ZZ]+tz*box[ZZ][ZZ];
1006 for (j = g1; j < g->at1; j++)
1008 copy_rvec(x[j], x_s[j]);
1012 void shift_self(const t_graph *g, const matrix box, rvec x[])
1020 gmx_incons("screw pbc not implemented for shift_self");
1028 fprintf(stderr, "Shifting atoms %d to %d\n", g0, g0+gn);
1032 for (j = g0; (j < g1); j++)
1038 x[j][XX] = x[j][XX]+tx*box[XX][XX]+ty*box[YY][XX]+tz*box[ZZ][XX];
1039 x[j][YY] = x[j][YY]+ty*box[YY][YY]+tz*box[ZZ][YY];
1040 x[j][ZZ] = x[j][ZZ]+tz*box[ZZ][ZZ];
1045 for (j = g0; (j < g1); j++)
1051 x[j][XX] = x[j][XX]+tx*box[XX][XX];
1052 x[j][YY] = x[j][YY]+ty*box[YY][YY];
1053 x[j][ZZ] = x[j][ZZ]+tz*box[ZZ][ZZ];
1058 void unshift_x(const t_graph *g, const matrix box, rvec x[], const rvec x_s[])
1066 gmx_incons("screw pbc not implemented (yet) for unshift_x");
1073 for (j = g->at0; j < g0; j++)
1075 copy_rvec(x_s[j], x[j]);
1080 for (j = g0; (j < g1); j++)
1086 x[j][XX] = x_s[j][XX]-tx*box[XX][XX]-ty*box[YY][XX]-tz*box[ZZ][XX];
1087 x[j][YY] = x_s[j][YY]-ty*box[YY][YY]-tz*box[ZZ][YY];
1088 x[j][ZZ] = x_s[j][ZZ]-tz*box[ZZ][ZZ];
1093 for (j = g0; (j < g1); j++)
1099 x[j][XX] = x_s[j][XX]-tx*box[XX][XX];
1100 x[j][YY] = x_s[j][YY]-ty*box[YY][YY];
1101 x[j][ZZ] = x_s[j][ZZ]-tz*box[ZZ][ZZ];
1105 for (j = g1; j < g->at1; j++)
1107 copy_rvec(x_s[j], x[j]);
1111 void unshift_self(const t_graph *g, const matrix box, rvec x[])
1119 gmx_incons("screw pbc not implemented for unshift_self");
1128 for (j = g0; (j < g1); j++)
1134 x[j][XX] = x[j][XX]-tx*box[XX][XX]-ty*box[YY][XX]-tz*box[ZZ][XX];
1135 x[j][YY] = x[j][YY]-ty*box[YY][YY]-tz*box[ZZ][YY];
1136 x[j][ZZ] = x[j][ZZ]-tz*box[ZZ][ZZ];
1141 for (j = g0; (j < g1); j++)
1147 x[j][XX] = x[j][XX]-tx*box[XX][XX];
1148 x[j][YY] = x[j][YY]-ty*box[YY][YY];
1149 x[j][ZZ] = x[j][ZZ]-tz*box[ZZ][ZZ];