1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
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 * GROningen Mixture of Alchemy and Childrens' Stories
49 #include "gmx_fatal.h"
52 #include "gmx_omp_nthreads.h"
54 /* Skip 0 so we have more chance of detecting if we forgot to call set_pbc. */
56 epbcdxRECTANGULAR = 1, epbcdxTRICLINIC,
57 epbcdx2D_RECT, epbcdx2D_TRIC,
58 epbcdx1D_RECT, epbcdx1D_TRIC,
59 epbcdxSCREW_RECT, epbcdxSCREW_TRIC,
60 epbcdxNOPBC, epbcdxUNSUPPORTED
63 /* Margin factor for error message and correction if the box is too skewed */
64 #define BOX_MARGIN 1.0010
65 #define BOX_MARGIN_CORRECT 1.0005
67 int ePBC2npbcdim(int ePBC)
73 case epbcXYZ: npbcdim = 3; break;
74 case epbcXY: npbcdim = 2; break;
75 case epbcSCREW: npbcdim = 3; break;
76 case epbcNONE: npbcdim = 0; break;
77 default: gmx_fatal(FARGS, "Unknown ePBC=%d in ePBC2npbcdim", ePBC);
83 int inputrec2nboundeddim(t_inputrec *ir)
85 if (ir->nwall == 2 && ir->ePBC == epbcXY)
91 return ePBC2npbcdim(ir->ePBC);
95 void dump_pbc(FILE *fp, t_pbc *pbc)
99 fprintf(fp, "ePBCDX = %d\n", pbc->ePBCDX);
100 pr_rvecs(fp, 0, "box", pbc->box, DIM);
101 pr_rvecs(fp, 0, "fbox_diag", &pbc->fbox_diag, 1);
102 pr_rvecs(fp, 0, "hbox_diag", &pbc->hbox_diag, 1);
103 pr_rvecs(fp, 0, "mhbox_diag", &pbc->mhbox_diag, 1);
104 rvec_add(pbc->hbox_diag, pbc->mhbox_diag, sum_box);
105 pr_rvecs(fp, 0, "sum of the above two", &sum_box, 1);
106 fprintf(fp, "max_cutoff2 = %g\n", pbc->max_cutoff2);
107 fprintf(fp, "bLimitDistance = %s\n", EBOOL(pbc->bLimitDistance));
108 fprintf(fp, "limit_distance2 = %g\n", pbc->limit_distance2);
109 fprintf(fp, "ntric_vec = %d\n", pbc->ntric_vec);
110 if (pbc->ntric_vec > 0)
112 pr_ivecs(fp, 0, "tric_shift", pbc->tric_shift, pbc->ntric_vec, FALSE);
113 pr_rvecs(fp, 0, "tric_vec", pbc->tric_vec, pbc->ntric_vec);
117 const char *check_box(int ePBC, matrix box)
123 ePBC = guess_ePBC(box);
126 if (ePBC == epbcNONE)
131 if ((box[XX][YY] != 0) || (box[XX][ZZ] != 0) || (box[YY][ZZ] != 0))
133 ptr = "Only triclinic boxes with the first vector parallel to the x-axis and the second vector in the xy-plane are supported.";
135 else if (ePBC == epbcSCREW && (box[YY][XX] != 0 || box[ZZ][XX] != 0))
137 ptr = "The unit cell can not have off-diagonal x-components with screw pbc";
139 else if (fabs(box[YY][XX]) > BOX_MARGIN*0.5*box[XX][XX] ||
141 (fabs(box[ZZ][XX]) > BOX_MARGIN*0.5*box[XX][XX] ||
142 fabs(box[ZZ][YY]) > BOX_MARGIN*0.5*box[YY][YY])))
144 ptr = "Triclinic box is too skewed.";
154 real max_cutoff2(int ePBC, matrix box)
156 real min_hv2, min_ss;
158 /* Physical limitation of the cut-off
159 * by half the length of the shortest box vector.
161 min_hv2 = min(0.25*norm2(box[XX]), 0.25*norm2(box[YY]));
164 min_hv2 = min(min_hv2, 0.25*norm2(box[ZZ]));
167 /* Limitation to the smallest diagonal element due to optimizations:
168 * checking only linear combinations of single box-vectors (2 in x)
169 * in the grid search and pbc_dx is a lot faster
170 * than checking all possible combinations.
174 min_ss = min(box[XX][XX], box[YY][YY]);
178 min_ss = min(box[XX][XX], min(box[YY][YY]-fabs(box[ZZ][YY]), box[ZZ][ZZ]));
181 return min(min_hv2, min_ss*min_ss);
184 /* this one is mostly harmless... */
185 static gmx_bool bWarnedGuess = FALSE;
187 int guess_ePBC(matrix box)
191 if (box[XX][XX] > 0 && box[YY][YY] > 0 && box[ZZ][ZZ] > 0)
195 else if (box[XX][XX] > 0 && box[YY][YY] > 0 && box[ZZ][ZZ] == 0)
199 else if (box[XX][XX] == 0 && box[YY][YY] == 0 && box[ZZ][ZZ] == 0)
207 fprintf(stderr, "WARNING: Unsupported box diagonal %f %f %f, "
208 "will not use periodic boundary conditions\n\n",
209 box[XX][XX], box[YY][YY], box[ZZ][ZZ]);
217 fprintf(debug, "Guessed pbc = %s from the box matrix\n", epbc_names[ePBC]);
223 static int correct_box_elem(FILE *fplog, int step, tensor box, int v, int d)
225 int shift, maxshift = 10;
229 /* correct elem d of vector v with vector d */
230 while (box[v][d] > BOX_MARGIN_CORRECT*0.5*box[d][d])
234 fprintf(fplog, "Step %d: correcting invalid box:\n", step);
235 pr_rvecs(fplog, 0, "old box", box, DIM);
237 rvec_dec(box[v], box[d]);
241 pr_rvecs(fplog, 0, "new box", box, DIM);
243 if (shift <= -maxshift)
246 "Box was shifted at least %d times. Please see log-file.",
250 while (box[v][d] < -BOX_MARGIN_CORRECT*0.5*box[d][d])
254 fprintf(fplog, "Step %d: correcting invalid box:\n", step);
255 pr_rvecs(fplog, 0, "old box", box, DIM);
257 rvec_inc(box[v], box[d]);
261 pr_rvecs(fplog, 0, "new box", box, DIM);
263 if (shift >= maxshift)
266 "Box was shifted at least %d times. Please see log-file.",
274 gmx_bool correct_box(FILE *fplog, int step, tensor box, t_graph *graph)
279 /* check if the box still obeys the restrictions, if not, correct it */
280 zy = correct_box_elem(fplog, step, box, ZZ, YY);
281 zx = correct_box_elem(fplog, step, box, ZZ, XX);
282 yx = correct_box_elem(fplog, step, box, YY, XX);
284 bCorrected = (zy || zx || yx);
286 if (bCorrected && graph)
288 /* correct the graph */
289 for (i = graph->at_start; i < graph->at_end; i++)
291 graph->ishift[i][YY] -= graph->ishift[i][ZZ]*zy;
292 graph->ishift[i][XX] -= graph->ishift[i][ZZ]*zx;
293 graph->ishift[i][XX] -= graph->ishift[i][YY]*yx;
300 int ndof_com(t_inputrec *ir)
311 n = (ir->nwall == 0 ? 3 : 2);
317 gmx_incons("Unknown pbc in calc_nrdf");
323 static void low_set_pbc(t_pbc *pbc, int ePBC, ivec *dd_nc, matrix box)
325 int order[5] = {0, -1, 1, -2, 2};
326 int ii, jj, kk, i, j, k, d, dd, jc, kc, npbcdim, shift;
328 real d2old, d2new, d2new_c;
334 pbc->ndim_ePBC = ePBC2npbcdim(ePBC);
336 copy_mat(box, pbc->box);
337 pbc->bLimitDistance = FALSE;
338 pbc->max_cutoff2 = 0;
341 for (i = 0; (i < DIM); i++)
343 pbc->fbox_diag[i] = box[i][i];
344 pbc->hbox_diag[i] = pbc->fbox_diag[i]*0.5;
345 pbc->mhbox_diag[i] = -pbc->hbox_diag[i];
348 ptr = check_box(ePBC, box);
349 if (ePBC == epbcNONE)
351 pbc->ePBCDX = epbcdxNOPBC;
355 fprintf(stderr, "Warning: %s\n", ptr);
356 pr_rvecs(stderr, 0, " Box", box, DIM);
357 fprintf(stderr, " Can not fix pbc.\n");
358 pbc->ePBCDX = epbcdxUNSUPPORTED;
359 pbc->bLimitDistance = TRUE;
360 pbc->limit_distance2 = 0;
364 if (ePBC == epbcSCREW && dd_nc)
366 /* This combinated should never appear here */
367 gmx_incons("low_set_pbc called with screw pbc and dd_nc != NULL");
371 for (i = 0; i < DIM; i++)
373 if ((dd_nc && (*dd_nc)[i] > 1) || (ePBC == epbcXY && i == ZZ))
386 /* 1D pbc is not an mdp option and it is therefore only used
387 * with single shifts.
389 pbc->ePBCDX = epbcdx1D_RECT;
390 for (i = 0; i < DIM; i++)
397 for (i = 0; i < pbc->dim; i++)
399 if (pbc->box[pbc->dim][i] != 0)
401 pbc->ePBCDX = epbcdx1D_TRIC;
406 pbc->ePBCDX = epbcdx2D_RECT;
407 for (i = 0; i < DIM; i++)
414 for (i = 0; i < DIM; i++)
418 for (j = 0; j < i; j++)
420 if (pbc->box[i][j] != 0)
422 pbc->ePBCDX = epbcdx2D_TRIC;
429 if (ePBC != epbcSCREW)
433 pbc->ePBCDX = epbcdxTRICLINIC;
437 pbc->ePBCDX = epbcdxRECTANGULAR;
442 pbc->ePBCDX = (box[ZZ][YY] == 0 ? epbcdxSCREW_RECT : epbcdxSCREW_TRIC);
443 if (pbc->ePBCDX == epbcdxSCREW_TRIC)
446 "Screw pbc is not yet implemented for triclinic boxes.\n"
447 "Can not fix pbc.\n");
448 pbc->ePBCDX = epbcdxUNSUPPORTED;
453 gmx_fatal(FARGS, "Incorrect number of pbc dimensions with DD: %d",
456 pbc->max_cutoff2 = max_cutoff2(ePBC, box);
458 if (pbc->ePBCDX == epbcdxTRICLINIC ||
459 pbc->ePBCDX == epbcdx2D_TRIC ||
460 pbc->ePBCDX == epbcdxSCREW_TRIC)
464 pr_rvecs(debug, 0, "Box", box, DIM);
465 fprintf(debug, "max cutoff %.3f\n", sqrt(pbc->max_cutoff2));
468 /* We will only use single shifts, but we will check a few
469 * more shifts to see if there is a limiting distance
470 * above which we can not be sure of the correct distance.
472 for (kk = 0; kk < 5; kk++)
475 if (!bPBC[ZZ] && k != 0)
479 for (jj = 0; jj < 5; jj++)
482 if (!bPBC[YY] && j != 0)
486 for (ii = 0; ii < 3; ii++)
489 if (!bPBC[XX] && i != 0)
493 /* A shift is only useful when it is trilinic */
494 if (j != 0 || k != 0)
498 for (d = 0; d < DIM; d++)
500 trial[d] = i*box[XX][d] + j*box[YY][d] + k*box[ZZ][d];
501 /* Choose the vector within the brick around 0,0,0 that
502 * will become the shortest due to shift try.
513 pos[d] = min( pbc->hbox_diag[d], -trial[d]);
517 pos[d] = max(-pbc->hbox_diag[d], -trial[d]);
520 d2old += sqr(pos[d]);
521 d2new += sqr(pos[d] + trial[d]);
523 if (BOX_MARGIN*d2new < d2old)
525 if (j < -1 || j > 1 || k < -1 || k > 1)
527 /* Check if there is a single shift vector
528 * that decreases this distance even more.
541 for (d = 0; d < DIM; d++)
543 d2new_c += sqr(pos[d] + trial[d]
544 - jc*box[YY][d] - kc*box[ZZ][d]);
546 if (d2new_c > BOX_MARGIN*d2new)
548 /* Reject this shift vector, as there is no a priori limit
549 * to the number of shifts that decrease distances.
551 if (!pbc->bLimitDistance || d2new < pbc->limit_distance2)
553 pbc->limit_distance2 = d2new;
555 pbc->bLimitDistance = TRUE;
560 /* Check if shifts with one box vector less do better */
562 for (dd = 0; dd < DIM; dd++)
564 shift = (dd == 0 ? i : (dd == 1 ? j : k));
568 for (d = 0; d < DIM; d++)
570 d2new_c += sqr(pos[d] + trial[d] - shift*box[dd][d]);
572 if (d2new_c <= BOX_MARGIN*d2new)
580 /* Accept this shift vector. */
581 if (pbc->ntric_vec >= MAX_NTRICVEC)
583 fprintf(stderr, "\nWARNING: Found more than %d triclinic correction vectors, ignoring some.\n"
584 " There is probably something wrong with your box.\n", MAX_NTRICVEC);
585 pr_rvecs(stderr, 0, " Box", box, DIM);
589 copy_rvec(trial, pbc->tric_vec[pbc->ntric_vec]);
590 pbc->tric_shift[pbc->ntric_vec][XX] = i;
591 pbc->tric_shift[pbc->ntric_vec][YY] = j;
592 pbc->tric_shift[pbc->ntric_vec][ZZ] = k;
599 fprintf(debug, " tricvec %2d = %2d %2d %2d %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f\n",
600 pbc->ntric_vec, i, j, k,
601 sqrt(d2old), sqrt(d2new),
602 trial[XX], trial[YY], trial[ZZ],
603 pos[XX], pos[YY], pos[ZZ]);
614 void set_pbc(t_pbc *pbc, int ePBC, matrix box)
618 ePBC = guess_ePBC(box);
621 low_set_pbc(pbc, ePBC, NULL, box);
624 t_pbc *set_pbc_dd(t_pbc *pbc, int ePBC,
625 gmx_domdec_t *dd, gmx_bool bSingleDir, matrix box)
636 if (ePBC == epbcSCREW && dd->nc[XX] > 1)
638 /* The rotation has been taken care of during coordinate communication */
642 for (i = 0; i < DIM; i++)
644 if (dd->nc[i] <= (bSingleDir ? 1 : 2))
647 if (!(ePBC == epbcXY && i == ZZ))
661 low_set_pbc(pbc, ePBC, npbcdim < DIM ? &nc2 : NULL, box);
664 return (npbcdim > 0 ? pbc : NULL);
667 void pbc_dx(const t_pbc *pbc, const rvec x1, const rvec x2, rvec dx)
670 rvec dx_start, trial;
674 rvec_sub(x1, x2, dx);
678 case epbcdxRECTANGULAR:
679 for (i = 0; i < DIM; i++)
681 while (dx[i] > pbc->hbox_diag[i])
683 dx[i] -= pbc->fbox_diag[i];
685 while (dx[i] <= pbc->mhbox_diag[i])
687 dx[i] += pbc->fbox_diag[i];
691 case epbcdxTRICLINIC:
692 for (i = DIM-1; i >= 0; i--)
694 while (dx[i] > pbc->hbox_diag[i])
696 for (j = i; j >= 0; j--)
698 dx[j] -= pbc->box[i][j];
701 while (dx[i] <= pbc->mhbox_diag[i])
703 for (j = i; j >= 0; j--)
705 dx[j] += pbc->box[i][j];
709 /* dx is the distance in a rectangular box */
711 if (d2min > pbc->max_cutoff2)
713 copy_rvec(dx, dx_start);
715 /* Now try all possible shifts, when the distance is within max_cutoff
716 * it must be the shortest possible distance.
719 while ((d2min > pbc->max_cutoff2) && (i < pbc->ntric_vec))
721 rvec_add(dx_start, pbc->tric_vec[i], trial);
722 d2trial = norm2(trial);
725 copy_rvec(trial, dx);
733 for (i = 0; i < DIM; i++)
737 while (dx[i] > pbc->hbox_diag[i])
739 dx[i] -= pbc->fbox_diag[i];
741 while (dx[i] <= pbc->mhbox_diag[i])
743 dx[i] += pbc->fbox_diag[i];
750 for (i = DIM-1; i >= 0; i--)
754 while (dx[i] > pbc->hbox_diag[i])
756 for (j = i; j >= 0; j--)
758 dx[j] -= pbc->box[i][j];
761 while (dx[i] <= pbc->mhbox_diag[i])
763 for (j = i; j >= 0; j--)
765 dx[j] += pbc->box[i][j];
768 d2min += dx[i]*dx[i];
771 if (d2min > pbc->max_cutoff2)
773 copy_rvec(dx, dx_start);
775 /* Now try all possible shifts, when the distance is within max_cutoff
776 * it must be the shortest possible distance.
779 while ((d2min > pbc->max_cutoff2) && (i < pbc->ntric_vec))
781 rvec_add(dx_start, pbc->tric_vec[i], trial);
783 for (j = 0; j < DIM; j++)
787 d2trial += trial[j]*trial[j];
792 copy_rvec(trial, dx);
799 case epbcdxSCREW_RECT:
800 /* The shift definition requires x first */
802 while (dx[XX] > pbc->hbox_diag[XX])
804 dx[XX] -= pbc->fbox_diag[XX];
807 while (dx[XX] <= pbc->mhbox_diag[XX])
809 dx[XX] += pbc->fbox_diag[YY];
814 /* Rotate around the x-axis in the middle of the box */
815 dx[YY] = pbc->box[YY][YY] - x1[YY] - x2[YY];
816 dx[ZZ] = pbc->box[ZZ][ZZ] - x1[ZZ] - x2[ZZ];
818 /* Normal pbc for y and z */
819 for (i = YY; i <= ZZ; i++)
821 while (dx[i] > pbc->hbox_diag[i])
823 dx[i] -= pbc->fbox_diag[i];
825 while (dx[i] <= pbc->mhbox_diag[i])
827 dx[i] += pbc->fbox_diag[i];
832 case epbcdxUNSUPPORTED:
835 gmx_fatal(FARGS, "Internal error in pbc_dx, set_pbc has not been called");
840 int pbc_dx_aiuc(const t_pbc *pbc, const rvec x1, const rvec x2, rvec dx)
843 rvec dx_start, trial;
845 ivec ishift, ishift_start;
847 rvec_sub(x1, x2, dx);
852 case epbcdxRECTANGULAR:
853 for (i = 0; i < DIM; i++)
855 if (dx[i] > pbc->hbox_diag[i])
857 dx[i] -= pbc->fbox_diag[i];
860 else if (dx[i] <= pbc->mhbox_diag[i])
862 dx[i] += pbc->fbox_diag[i];
867 case epbcdxTRICLINIC:
868 /* For triclinic boxes the performance difference between
869 * if/else and two while loops is negligible.
870 * However, the while version can cause extreme delays
871 * before a simulation crashes due to large forces which
872 * can cause unlimited displacements.
873 * Also allowing multiple shifts would index fshift beyond bounds.
875 for (i = DIM-1; i >= 1; i--)
877 if (dx[i] > pbc->hbox_diag[i])
879 for (j = i; j >= 0; j--)
881 dx[j] -= pbc->box[i][j];
885 else if (dx[i] <= pbc->mhbox_diag[i])
887 for (j = i; j >= 0; j--)
889 dx[j] += pbc->box[i][j];
894 /* Allow 2 shifts in x */
895 if (dx[XX] > pbc->hbox_diag[XX])
897 dx[XX] -= pbc->fbox_diag[XX];
899 if (dx[XX] > pbc->hbox_diag[XX])
901 dx[XX] -= pbc->fbox_diag[XX];
905 else if (dx[XX] <= pbc->mhbox_diag[XX])
907 dx[XX] += pbc->fbox_diag[XX];
909 if (dx[XX] <= pbc->mhbox_diag[XX])
911 dx[XX] += pbc->fbox_diag[XX];
915 /* dx is the distance in a rectangular box */
917 if (d2min > pbc->max_cutoff2)
919 copy_rvec(dx, dx_start);
920 copy_ivec(ishift, ishift_start);
922 /* Now try all possible shifts, when the distance is within max_cutoff
923 * it must be the shortest possible distance.
926 while ((d2min > pbc->max_cutoff2) && (i < pbc->ntric_vec))
928 rvec_add(dx_start, pbc->tric_vec[i], trial);
929 d2trial = norm2(trial);
932 copy_rvec(trial, dx);
933 ivec_add(ishift_start, pbc->tric_shift[i], ishift);
941 for (i = 0; i < DIM; i++)
945 if (dx[i] > pbc->hbox_diag[i])
947 dx[i] -= pbc->fbox_diag[i];
950 else if (dx[i] <= pbc->mhbox_diag[i])
952 dx[i] += pbc->fbox_diag[i];
960 for (i = DIM-1; i >= 1; i--)
964 if (dx[i] > pbc->hbox_diag[i])
966 for (j = i; j >= 0; j--)
968 dx[j] -= pbc->box[i][j];
972 else if (dx[i] <= pbc->mhbox_diag[i])
974 for (j = i; j >= 0; j--)
976 dx[j] += pbc->box[i][j];
980 d2min += dx[i]*dx[i];
985 /* Allow 2 shifts in x */
986 if (dx[XX] > pbc->hbox_diag[XX])
988 dx[XX] -= pbc->fbox_diag[XX];
990 if (dx[XX] > pbc->hbox_diag[XX])
992 dx[XX] -= pbc->fbox_diag[XX];
996 else if (dx[XX] <= pbc->mhbox_diag[XX])
998 dx[XX] += pbc->fbox_diag[XX];
1000 if (dx[XX] <= pbc->mhbox_diag[XX])
1002 dx[XX] += pbc->fbox_diag[XX];
1006 d2min += dx[XX]*dx[XX];
1008 if (d2min > pbc->max_cutoff2)
1010 copy_rvec(dx, dx_start);
1011 copy_ivec(ishift, ishift_start);
1012 /* Now try all possible shifts, when the distance is within max_cutoff
1013 * it must be the shortest possible distance.
1016 while ((d2min > pbc->max_cutoff2) && (i < pbc->ntric_vec))
1018 rvec_add(dx_start, pbc->tric_vec[i], trial);
1020 for (j = 0; j < DIM; j++)
1024 d2trial += trial[j]*trial[j];
1027 if (d2trial < d2min)
1029 copy_rvec(trial, dx);
1030 ivec_add(ishift_start, pbc->tric_shift[i], ishift);
1039 if (dx[i] > pbc->hbox_diag[i])
1041 dx[i] -= pbc->fbox_diag[i];
1044 else if (dx[i] <= pbc->mhbox_diag[i])
1046 dx[i] += pbc->fbox_diag[i];
1052 if (dx[i] > pbc->hbox_diag[i])
1054 rvec_dec(dx, pbc->box[i]);
1057 else if (dx[i] <= pbc->mhbox_diag[i])
1059 rvec_inc(dx, pbc->box[i]);
1063 case epbcdxSCREW_RECT:
1064 /* The shift definition requires x first */
1065 if (dx[XX] > pbc->hbox_diag[XX])
1067 dx[XX] -= pbc->fbox_diag[XX];
1070 else if (dx[XX] <= pbc->mhbox_diag[XX])
1072 dx[XX] += pbc->fbox_diag[XX];
1075 if (ishift[XX] == 1 || ishift[XX] == -1)
1077 /* Rotate around the x-axis in the middle of the box */
1078 dx[YY] = pbc->box[YY][YY] - x1[YY] - x2[YY];
1079 dx[ZZ] = pbc->box[ZZ][ZZ] - x1[ZZ] - x2[ZZ];
1081 /* Normal pbc for y and z */
1082 for (i = YY; i <= ZZ; i++)
1084 if (dx[i] > pbc->hbox_diag[i])
1086 dx[i] -= pbc->fbox_diag[i];
1089 else if (dx[i] <= pbc->mhbox_diag[i])
1091 dx[i] += pbc->fbox_diag[i];
1097 case epbcdxUNSUPPORTED:
1100 gmx_fatal(FARGS, "Internal error in pbc_dx_aiuc, set_pbc_dd or set_pbc has not been called");
1104 is = IVEC2IS(ishift);
1107 range_check_mesg(is, 0, SHIFTS, "PBC shift vector index range check.");
1113 void pbc_dx_d(const t_pbc *pbc, const dvec x1, const dvec x2, dvec dx)
1116 dvec dx_start, trial;
1117 double d2min, d2trial;
1120 dvec_sub(x1, x2, dx);
1122 switch (pbc->ePBCDX)
1124 case epbcdxRECTANGULAR:
1126 for (i = 0; i < DIM; i++)
1130 while (dx[i] > pbc->hbox_diag[i])
1132 dx[i] -= pbc->fbox_diag[i];
1134 while (dx[i] <= pbc->mhbox_diag[i])
1136 dx[i] += pbc->fbox_diag[i];
1141 case epbcdxTRICLINIC:
1144 for (i = DIM-1; i >= 0; i--)
1148 while (dx[i] > pbc->hbox_diag[i])
1150 for (j = i; j >= 0; j--)
1152 dx[j] -= pbc->box[i][j];
1155 while (dx[i] <= pbc->mhbox_diag[i])
1157 for (j = i; j >= 0; j--)
1159 dx[j] += pbc->box[i][j];
1162 d2min += dx[i]*dx[i];
1165 if (d2min > pbc->max_cutoff2)
1167 copy_dvec(dx, dx_start);
1168 /* Now try all possible shifts, when the distance is within max_cutoff
1169 * it must be the shortest possible distance.
1172 while ((d2min > pbc->max_cutoff2) && (i < pbc->ntric_vec))
1174 for (j = 0; j < DIM; j++)
1176 trial[j] = dx_start[j] + pbc->tric_vec[i][j];
1179 for (j = 0; j < DIM; j++)
1183 d2trial += trial[j]*trial[j];
1186 if (d2trial < d2min)
1188 copy_dvec(trial, dx);
1195 case epbcdxSCREW_RECT:
1196 /* The shift definition requires x first */
1198 while (dx[XX] > pbc->hbox_diag[XX])
1200 dx[XX] -= pbc->fbox_diag[XX];
1203 while (dx[XX] <= pbc->mhbox_diag[XX])
1205 dx[XX] += pbc->fbox_diag[YY];
1210 /* Rotate around the x-axis in the middle of the box */
1211 dx[YY] = pbc->box[YY][YY] - x1[YY] - x2[YY];
1212 dx[ZZ] = pbc->box[ZZ][ZZ] - x1[ZZ] - x2[ZZ];
1214 /* Normal pbc for y and z */
1215 for (i = YY; i <= ZZ; i++)
1217 while (dx[i] > pbc->hbox_diag[i])
1219 dx[i] -= pbc->fbox_diag[i];
1221 while (dx[i] <= pbc->mhbox_diag[i])
1223 dx[i] += pbc->fbox_diag[i];
1228 case epbcdxUNSUPPORTED:
1231 gmx_fatal(FARGS, "Internal error in pbc_dx, set_pbc has not been called");
1236 gmx_bool image_rect(ivec xi, ivec xj, ivec box_size, real rlong2, int *shift, real *r2)
1244 for (m = 0; (m < DIM); m++)
1276 gmx_bool image_cylindric(ivec xi, ivec xj, ivec box_size, real rlong2,
1277 int *shift, real *r2)
1285 for (m = 0; (m < DIM); m++)
1321 void calc_shifts(matrix box, rvec shift_vec[])
1323 int k, l, m, d, n, test;
1326 for (m = -D_BOX_Z; m <= D_BOX_Z; m++)
1328 for (l = -D_BOX_Y; l <= D_BOX_Y; l++)
1330 for (k = -D_BOX_X; k <= D_BOX_X; k++, n++)
1332 test = XYZ2IS(k, l, m);
1335 gmx_incons("inconsistent shift numbering");
1337 for (d = 0; d < DIM; d++)
1339 shift_vec[n][d] = k*box[XX][d] + l*box[YY][d] + m*box[ZZ][d];
1346 void calc_box_center(int ecenter, matrix box, rvec box_center)
1350 clear_rvec(box_center);
1354 for (m = 0; (m < DIM); m++)
1356 for (d = 0; d < DIM; d++)
1358 box_center[d] += 0.5*box[m][d];
1363 for (d = 0; d < DIM; d++)
1365 box_center[d] = 0.5*box[d][d];
1371 gmx_fatal(FARGS, "Unsupported value %d for ecenter", ecenter);
1375 void calc_triclinic_images(matrix box, rvec img[])
1379 /* Calculate 3 adjacent images in the xy-plane */
1380 copy_rvec(box[0], img[0]);
1381 copy_rvec(box[1], img[1]);
1384 svmul(-1, img[1], img[1]);
1386 rvec_sub(img[1], img[0], img[2]);
1388 /* Get the next 3 in the xy-plane as mirror images */
1389 for (i = 0; i < 3; i++)
1391 svmul(-1, img[i], img[3+i]);
1394 /* Calculate the first 4 out of xy-plane images */
1395 copy_rvec(box[2], img[6]);
1398 svmul(-1, img[6], img[6]);
1400 for (i = 0; i < 3; i++)
1402 rvec_add(img[6], img[i+1], img[7+i]);
1405 /* Mirror the last 4 from the previous in opposite rotation */
1406 for (i = 0; i < 4; i++)
1408 svmul(-1, img[6 + (2+i) % 4], img[10+i]);
1412 void calc_compact_unitcell_vertices(int ecenter, matrix box, rvec vert[])
1414 rvec img[NTRICIMG], box_center;
1415 int n, i, j, tmp[4], d;
1417 calc_triclinic_images(box, img);
1420 for (i = 2; i <= 5; i += 3)
1433 for (j = 0; j < 4; j++)
1435 for (d = 0; d < DIM; d++)
1437 vert[n][d] = img[i][d]+img[tmp[j]][d]+img[tmp[(j+1)%4]][d];
1442 for (i = 7; i <= 13; i += 6)
1455 for (j = 0; j < 4; j++)
1457 for (d = 0; d < DIM; d++)
1459 vert[n][d] = img[i][d]+img[tmp[j]][d]+img[tmp[(j+1)%4]][d];
1464 for (i = 9; i <= 11; i += 2)
1484 for (j = 0; j < 4; j++)
1486 for (d = 0; d < DIM; d++)
1488 vert[n][d] = img[i][d]+img[tmp[j]][d]+img[tmp[(j+1)%4]][d];
1494 calc_box_center(ecenter, box, box_center);
1495 for (i = 0; i < NCUCVERT; i++)
1497 for (d = 0; d < DIM; d++)
1499 vert[i][d] = vert[i][d]*0.25+box_center[d];
1504 int *compact_unitcell_edges()
1506 /* this is an index in vert[] (see calc_box_vertices) */
1507 /*static int edge[NCUCEDGE*2];*/
1509 static const int hexcon[24] = {
1510 0, 9, 1, 19, 2, 15, 3, 21,
1511 4, 17, 5, 11, 6, 23, 7, 13,
1512 8, 20, 10, 18, 12, 16, 14, 22
1515 gmx_bool bFirst = TRUE;
1517 snew(edge, NCUCEDGE*2);
1522 for (i = 0; i < 6; i++)
1524 for (j = 0; j < 4; j++)
1526 edge[e++] = 4*i + j;
1527 edge[e++] = 4*i + (j+1) % 4;
1530 for (i = 0; i < 12*2; i++)
1532 edge[e++] = hexcon[i];
1541 void put_atoms_in_box_omp(int ePBC, matrix box, int natoms, rvec x[])
1544 nth = gmx_omp_nthreads_get(emntDefault);
1546 #pragma omp parallel for num_threads(nth) schedule(static)
1547 for (t = 0; t < nth; t++)
1551 offset = (natoms*t )/nth;
1552 len = (natoms*(t + 1))/nth - offset;
1553 put_atoms_in_box(ePBC, box, len, x + offset);
1557 void put_atoms_in_box(int ePBC, matrix box, int natoms, rvec x[])
1559 int npbcdim, i, m, d;
1561 if (ePBC == epbcSCREW)
1563 gmx_fatal(FARGS, "Sorry, %s pbc is not yet supported", epbc_names[ePBC]);
1577 for (i = 0; (i < natoms); i++)
1579 for (m = npbcdim-1; m >= 0; m--)
1583 for (d = 0; d <= m; d++)
1585 x[i][d] += box[m][d];
1588 while (x[i][m] >= box[m][m])
1590 for (d = 0; d <= m; d++)
1592 x[i][d] -= box[m][d];
1600 for (i = 0; i < natoms; i++)
1602 for (d = 0; d < npbcdim; d++)
1606 x[i][d] += box[d][d];
1608 while (x[i][d] >= box[d][d])
1610 x[i][d] -= box[d][d];
1617 void put_atoms_in_triclinic_unitcell(int ecenter, matrix box,
1618 int natoms, rvec x[])
1620 rvec box_center, shift_center;
1621 real shm01, shm02, shm12, shift;
1624 calc_box_center(ecenter, box, box_center);
1626 /* The product of matrix shm with a coordinate gives the shift vector
1627 which is required determine the periodic cell position */
1628 shm01 = box[1][0]/box[1][1];
1629 shm02 = (box[1][1]*box[2][0] - box[2][1]*box[1][0])/(box[1][1]*box[2][2]);
1630 shm12 = box[2][1]/box[2][2];
1632 clear_rvec(shift_center);
1633 for (d = 0; d < DIM; d++)
1635 rvec_inc(shift_center, box[d]);
1637 svmul(0.5, shift_center, shift_center);
1638 rvec_sub(box_center, shift_center, shift_center);
1640 shift_center[0] = shm01*shift_center[1] + shm02*shift_center[2];
1641 shift_center[1] = shm12*shift_center[2];
1642 shift_center[2] = 0;
1644 for (i = 0; (i < natoms); i++)
1646 for (m = DIM-1; m >= 0; m--)
1648 shift = shift_center[m];
1651 shift += shm01*x[i][1] + shm02*x[i][2];
1655 shift += shm12*x[i][2];
1657 while (x[i][m]-shift < 0)
1659 for (d = 0; d <= m; d++)
1661 x[i][d] += box[m][d];
1664 while (x[i][m]-shift >= box[m][m])
1666 for (d = 0; d <= m; d++)
1668 x[i][d] -= box[m][d];
1676 put_atoms_in_compact_unitcell(int ePBC, int ecenter, matrix box,
1677 int natoms, rvec x[])
1680 rvec box_center, dx;
1683 set_pbc(&pbc, ePBC, box);
1684 calc_box_center(ecenter, box, box_center);
1685 for (i = 0; i < natoms; i++)
1687 pbc_dx(&pbc, x[i], box_center, dx);
1688 rvec_add(box_center, dx, x[i]);
1691 return pbc.bLimitDistance ?
1692 "WARNING: Could not put all atoms in the compact unitcell\n"