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 * GROwing Monsters And Cloning Shrimps
36 /* This file is completely threadsafe - keep it that way! */
48 #include "gmx_fatal.h"
58 /***********************************
60 ***********************************/
62 const char *range_warn
=
63 "Explanation: During neighborsearching, we assign each particle to a grid\n"
64 "based on its coordinates. If your system contains collisions or parameter\n"
65 "errors that give particles very high velocities you might end up with some\n"
66 "coordinates being +-Infinity or NaN (not-a-number). Obviously, we cannot\n"
67 "put these on a grid, so this is usually where we detect those errors.\n"
68 "Make sure your system is properly energy-minimized and that the potential\n"
69 "energy seems reasonable before trying again.";
71 static void calc_x_av_stddev(int n
,rvec
*x
,rvec av
,rvec stddev
)
84 s2
[d
] += x
[i
][d
]*x
[i
][d
];
94 stddev
[d
] = sqrt(s2
[d
] - s1
[d
]*s1
[d
]);
98 void get_nsgrid_boundaries_vac(real av
,real stddev
,
99 real
*bound0
,real
*bound1
,
100 real
*bdens0
,real
*bdens1
)
102 /* Set the grid to 2 times the standard deviation of
103 * the charge group centers in both directions.
104 * For a uniform bounded distribution the width is sqrt(3)*stddev,
105 * so all charge groups fall within the width.
106 * For a sphere stddev is r/sqrt(5): 99.2% falls within the width.
107 * For a Gaussian distribution 98% fall within the width.
109 *bound0
= av
- NSGRID_STDDEV_FAC
*stddev
;
110 *bound1
= av
+ NSGRID_STDDEV_FAC
*stddev
;
112 *bdens0
= av
- GRID_STDDEV_FAC
*stddev
;
113 *bdens1
= av
+ GRID_STDDEV_FAC
*stddev
;
116 static void dd_box_bounds_to_ns_bounds(real box0
,real box_size
,
121 /* Redetermine av and stddev from the DD box boundaries */
122 av
= box0
+ 0.5*box_size
;
123 stddev
= 0.5*box_size
/GRID_STDDEV_FAC
;
125 *gr0
= av
- NSGRID_STDDEV_FAC
*stddev
;
126 *gr1
= av
+ NSGRID_STDDEV_FAC
*stddev
;
129 void get_nsgrid_boundaries(t_grid
*grid
,
131 matrix box
,gmx_ddbox_t
*ddbox
,rvec
*gr0
,rvec
*gr1
,
133 rvec grid_x0
,rvec grid_x1
,
137 real vol
,bdens0
,bdens1
;
140 if (grid
->nboundeddim
< DIM
)
142 calc_x_av_stddev(ncg
,cgcm
,av
,stddev
);
148 if (d
< grid
->nboundeddim
)
150 grid_x0
[d
] = (gr0
!= NULL
? (*gr0
)[d
] : 0);
151 grid_x1
[d
] = (gr1
!= NULL
? (*gr1
)[d
] : box
[d
][d
]);
152 vol
*= (grid_x1
[d
] - grid_x0
[d
]);
158 get_nsgrid_boundaries_vac(av
[d
],stddev
[d
],
159 &grid_x0
[d
],&grid_x1
[d
],
164 /* Temporary fix which uses global ddbox boundaries
165 * for unbounded dimensions.
166 * Should be replaced by local boundaries, which makes
167 * the ns grid smaller and does not require global comm.
169 dd_box_bounds_to_ns_bounds(ddbox
->box0
[d
],ddbox
->box_size
[d
],
170 &grid_x0
[d
],&grid_x1
[d
]);
174 /* Check for a DD cell not at a lower edge */
175 if (dd
!= NULL
&& gr0
!= NULL
&& dd
->ci
[d
] > 0)
177 grid_x0
[d
] = (*gr0
)[d
];
180 /* Check for a DD cell not at a higher edge */
181 if (dd
!= NULL
&& gr1
!= NULL
&& dd
->ci
[d
] < dd
->nc
[d
]-1)
183 grid_x1
[d
] = (*gr1
)[d
];
186 vol
*= (bdens1
- bdens0
);
191 fprintf(debug
,"Set grid boundaries dim %d: %f %f\n",
192 d
,grid_x0
[d
],grid_x1
[d
]);
196 *grid_density
= ncg
/vol
;
199 static void set_grid_sizes(matrix box
,rvec izones_x0
,rvec izones_x1
,real rlist
,
200 const gmx_domdec_t
*dd
,const gmx_ddbox_t
*ddbox
,
205 gmx_bool bDD
,bDDRect
;
208 real inv_r_ideal
,size
,add_tric
,radd
;
210 for(i
=0; (i
<DIM
); i
++)
215 "set_grid_sizes, i-zone bounds for dim %d: %6.3f %6.3f\n",
216 i
,izones_x0
[i
],izones_x1
[i
]);
218 izones_size
[i
] = izones_x1
[i
] - izones_x0
[i
];
221 /* Use the ideal number of cg's per cell to set the ideal cell size */
222 inv_r_ideal
= pow(grid_density
/grid
->ncg_ideal
,1.0/3.0);
223 if (rlist
> 0 && inv_r_ideal
*rlist
< 1)
225 inv_r_ideal
= 1/rlist
;
229 fprintf(debug
,"CG density %f ideal ns cell size %f\n",
230 grid_density
,1/inv_r_ideal
);
233 clear_rvec(grid
->cell_offset
);
234 for(i
=0; (i
<DIM
); i
++)
236 /* Initial settings, for DD might change below */
237 grid
->cell_offset
[i
] = izones_x0
[i
];
238 size
= izones_size
[i
];
240 bDD
= dd
&& (dd
->nc
[i
] > 1);
247 /* With DD grid cell jumps only the first decomposition
248 * direction has uniform DD cell boundaries.
250 bDDRect
= !(ddbox
->tric_dir
[i
] ||
251 (dd
->bGridJump
&& i
!= dd
->dim
[0]));
254 if (i
>= ddbox
->npbcdim
&&
256 izones_x1
[i
] + radd
> ddbox
->box0
[i
] + ddbox
->box_size
[i
]))
258 radd
= ddbox
->box0
[i
] + ddbox
->box_size
[i
] - izones_x1
[i
];
265 /* With DD we only need a grid of one DD cell size + rlist */
272 size
+= radd
/ddbox
->skew_fac
[i
];
275 /* Check if the cell boundary in this direction is
276 * perpendicular to the Cartesian axis.
278 for(j
=i
+1; j
<grid
->npbcdim
; j
++)
282 /* Correct the offset for the home cell location */
283 grid
->cell_offset
[i
] += izones_x0
[j
]*box
[j
][i
]/box
[j
][j
];
285 /* Correct the offset and size for the off-diagonal
286 * displacement of opposing DD cell corners.
288 /* Without rouding we would need to add:
289 * box[j][i]*rlist/(dd->skew_fac[i]*box[j][j])
291 /* Determine the shift for the corners of the triclinic box */
292 add_tric
= izones_size
[j
]*box
[j
][i
]/box
[j
][j
];
293 if (dd
&& dd
->ndim
== 1 && j
== ZZ
)
295 /* With 1D domain decomposition the cg's are not in
296 * the triclinic box, but trilinic x-y and rectangular y-z.
297 * Therefore we need to add the shift from the trilinic
298 * corner to the corner at y=0.
300 add_tric
+= -box
[YY
][XX
]*box
[ZZ
][YY
]/box
[YY
][YY
];
304 grid
->cell_offset
[i
] += add_tric
;
316 /* No DD or the box is triclinic is this direction:
317 * we will use the normal grid ns that checks all cells
318 * that are within cut-off distance of the i-particle.
320 grid
->n
[i
] = (int)(size
*inv_r_ideal
+ 0.5);
325 grid
->cell_size
[i
] = size
/grid
->n
[i
];
330 /* We use grid->ncpddc[i] such that all particles
331 * in one ns cell belong to a single DD cell only.
332 * We can then beforehand exclude certain ns grid cells
333 * for non-home i-particles.
335 grid
->ncpddc
[i
] = (int)(izones_size
[i
]*inv_r_ideal
+ 0.5);
336 if (grid
->ncpddc
[i
] < 2)
340 grid
->cell_size
[i
] = izones_size
[i
]/grid
->ncpddc
[i
];
341 grid
->n
[i
] = grid
->ncpddc
[i
] + (int)(radd
/grid
->cell_size
[i
]) + 1;
345 fprintf(debug
,"grid dim %d size %d x %f: %f - %f\n",
346 i
,grid
->n
[i
],grid
->cell_size
[i
],
347 grid
->cell_offset
[i
],
348 grid
->cell_offset
[i
]+grid
->n
[i
]*grid
->cell_size
[i
]);
354 fprintf(debug
,"CG ncg ideal %d, actual density %.1f\n",
355 grid
->ncg_ideal
,grid_density
*grid
->cell_size
[XX
]*grid
->cell_size
[YY
]*grid
->cell_size
[ZZ
]);
359 t_grid
*init_grid(FILE *fplog
,t_forcerec
*fr
)
367 grid
->npbcdim
= ePBC2npbcdim(fr
->ePBC
);
369 if (fr
->ePBC
== epbcXY
&& fr
->nwall
== 2)
371 grid
->nboundeddim
= 3;
375 grid
->nboundeddim
= grid
->npbcdim
;
380 fprintf(debug
,"The coordinates are bounded in %d dimensions\n",
384 /* The ideal number of cg's per ns grid cell seems to be 10 */
385 grid
->ncg_ideal
= 10;
386 ptr
= getenv("GMX_NSCELL_NCG");
389 sscanf(ptr
,"%d",&grid
->ncg_ideal
);
392 fprintf(fplog
,"Set ncg_ideal to %d\n",grid
->ncg_ideal
);
394 if (grid
->ncg_ideal
<= 0)
396 gmx_fatal(FARGS
,"The number of cg's per cell should be > 0");
401 fprintf(debug
,"Set ncg_ideal to %d\n",grid
->ncg_ideal
);
407 void done_grid(t_grid
*grid
)
412 sfree(grid
->cell_index
);
416 grid
->cells_nalloc
= 0;
423 fprintf(debug
,"Successfully freed memory for grid pointers.");
426 int xyz2ci_(int nry
,int nrz
,int x
,int y
,int z
)
427 /* Return the cell index */
429 return (nry
*nrz
*x
+nrz
*y
+z
);
432 void ci2xyz(t_grid
*grid
, int i
, int *x
, int *y
, int *z
)
433 /* Return x,y and z from the cell index */
437 range_check_mesg(i
,0,grid
->nr
,range_warn
);
439 ci
= grid
->cell_index
[i
];
440 *x
= ci
/ (grid
->n
[YY
]*grid
->n
[ZZ
]);
441 ci
-= (*x
)*grid
->n
[YY
]*grid
->n
[ZZ
];
442 *y
= ci
/ grid
->n
[ZZ
];
443 ci
-= (*y
)*grid
->n
[ZZ
];
447 static int ci_not_used(ivec n
)
449 /* Return an improbable value */
450 return xyz2ci(n
[YY
],n
[ZZ
],3*n
[XX
],3*n
[YY
],3*n
[ZZ
]);
453 static void set_grid_ncg(t_grid
*grid
,int ncg
)
458 if (grid
->nr
+1 > grid
->nr_alloc
) {
459 nr_old
= grid
->nr_alloc
;
460 grid
->nr_alloc
= over_alloc_dd(grid
->nr
) + 1;
461 srenew(grid
->cell_index
,grid
->nr_alloc
);
462 for(i
=nr_old
; i
<grid
->nr_alloc
; i
++)
463 grid
->cell_index
[i
] = 0;
464 srenew(grid
->a
,grid
->nr_alloc
);
468 void grid_first(FILE *fplog
,t_grid
*grid
,
469 gmx_domdec_t
*dd
,const gmx_ddbox_t
*ddbox
,
470 int ePBC
,matrix box
,rvec izones_x0
,rvec izones_x1
,
471 real rlistlong
,real grid_density
)
476 set_grid_sizes(box
,izones_x0
,izones_x1
,rlistlong
,dd
,ddbox
,grid
,grid_density
);
478 grid
->ncells
= grid
->n
[XX
]*grid
->n
[YY
]*grid
->n
[ZZ
];
480 if (grid
->ncells
+1 > grid
->cells_nalloc
) {
481 /* Allocate double the size so we have some headroom */
482 grid
->cells_nalloc
= 2*grid
->ncells
;
483 srenew(grid
->nra
, grid
->cells_nalloc
+1);
484 srenew(grid
->index
,grid
->cells_nalloc
+1);
487 fprintf(fplog
,"Grid: %d x %d x %d cells\n",
488 grid
->n
[XX
],grid
->n
[YY
],grid
->n
[ZZ
]);
491 m
= max(grid
->n
[XX
],max(grid
->n
[YY
],grid
->n
[ZZ
]));
492 if (m
> grid
->dc_nalloc
) {
493 /* Allocate with double the initial size for box scaling */
494 grid
->dc_nalloc
= 2*m
;
495 srenew(grid
->dcx2
,grid
->dc_nalloc
);
496 srenew(grid
->dcy2
,grid
->dc_nalloc
);
497 srenew(grid
->dcz2
,grid
->dc_nalloc
);
501 for(i
=0; (i
<grid
->ncells
); i
++) {
506 static void calc_bor(int cg0
,int cg1
,int ncg
,int CG0
[2],int CG1
[2])
523 fprintf(debug
,"calc_bor: cg0=%d, cg1=%d, ncg=%d\n",cg0
,cg1
,ncg
);
525 fprintf(debug
,"CG0[%d]=%d, CG1[%d]=%d\n",m
,CG0
[m
],m
,CG1
[m
]);
530 void calc_elemnr(FILE *fplog
,t_grid
*grid
,int cg0
,int cg1
,int ncg
)
533 int *cell_index
=grid
->cell_index
;
540 gmx_fatal(FARGS
,"Number of grid cells is zero. Probably the system and box collapsed.\n");
542 not_used
= ci_not_used(grid
->n
);
544 calc_bor(cg0
,cg1
,ncg
,CG0
,CG1
);
546 for(i
=CG0
[m
]; (i
<CG1
[m
]); i
++) {
548 if (ci
!= not_used
) {
549 range_check_mesg(ci
,0,ncells
,range_warn
);
555 void calc_ptrs(t_grid
*grid
)
557 int *index
= grid
->index
;
558 int *nra
= grid
->nra
;
564 gmx_fatal(FARGS
,"Number of grid cells is zero. Probably the system and box collapsed.\n");
567 for(ix
=0; (ix
< grid
->n
[XX
]); ix
++)
568 for(iy
=0; (iy
< grid
->n
[YY
]); iy
++)
569 for(iz
=0; (iz
< grid
->n
[ZZ
]); iz
++,ci
++) {
570 range_check_mesg(ci
,0,ncells
,range_warn
);
578 void grid_last(FILE *log
,t_grid
*grid
,int cg0
,int cg1
,int ncg
)
582 int ci
,not_used
,ind
,ncells
;
583 int *cell_index
= grid
->cell_index
;
584 int *nra
= grid
->nra
;
585 int *index
= grid
->index
;
590 gmx_fatal(FARGS
,"Number of grid cells is zero. Probably the system and box collapsed.\n");
592 not_used
= ci_not_used(grid
->n
);
594 calc_bor(cg0
,cg1
,ncg
,CG0
,CG1
);
596 for(i
=CG0
[m
]; (i
<CG1
[m
]); i
++) {
598 if (ci
!= not_used
) {
599 range_check_mesg(ci
,0,ncells
,range_warn
);
600 ind
= index
[ci
]+nra
[ci
]++;
601 range_check_mesg(ind
,0,grid
->nr
,range_warn
);
607 void fill_grid(FILE *log
,
608 gmx_domdec_zones_t
*dd_zones
,
609 t_grid
*grid
,int ncg_tot
,
610 int cg0
,int cg1
,rvec cg_cm
[])
615 int zone
,ccg0
,ccg1
,cg
,d
,not_used
;
616 ivec shift0
,useall
,b0
,b1
,ind
;
621 /* We have already filled the grid up to grid->ncg,
622 * continue from there.
627 set_grid_ncg(grid
,ncg_tot
);
629 cell_index
= grid
->cell_index
;
631 /* Initiate cell borders */
637 if (grid
->cell_size
[d
] > 0)
639 n_box
[d
] = 1/grid
->cell_size
[d
];
646 copy_rvec(grid
->cell_offset
,offset
);
650 fprintf(debug
,"Filling grid from %d to %d\n",cg0
,cg1
);
654 if (dd_zones
== NULL
)
656 for (cg
=cg0
; cg
<cg1
; cg
++)
660 ind
[d
] = (cg_cm
[cg
][d
] - offset
[d
])*n_box
[d
];
661 /* With pbc we should be done here.
662 * Without pbc cg's outside the grid
663 * should be assigned to the closest grid cell.
669 else if (ind
[d
] >= grid
->n
[d
])
671 ind
[d
] = grid
->n
[d
] - 1;
674 cell_index
[cg
] = xyz2ci(nry
,nrz
,ind
[XX
],ind
[YY
],ind
[ZZ
]);
679 for(zone
=0; zone
<dd_zones
->n
; zone
++)
681 ccg0
= dd_zones
->cg_range
[zone
];
682 ccg1
= dd_zones
->cg_range
[zone
+1];
683 if (ccg1
<= cg0
|| ccg0
>= cg1
)
688 /* Determine the ns grid cell limits for this DD zone */
691 shift0
[d
] = dd_zones
->shift
[zone
][d
];
692 useall
[d
] = (shift0
[d
] == 0 || d
>= grid
->npbcdim
);
693 /* Check if we need to do normal or optimized grid assignments.
694 * Normal is required for dims without DD or triclinic dims.
695 * DD edge cell on dims without pbc will be automatically
696 * be correct, since the shift=0 zones with have b0 and b1
697 * set to the grid boundaries and there are no shift=1 zones.
699 if (grid
->ncpddc
[d
] == 0)
709 b1
[d
] = grid
->ncpddc
[d
];
714 b0
[d
] = grid
->ncpddc
[d
];
720 not_used
= ci_not_used(grid
->n
);
722 /* Put all the charge groups of this DD zone on the grid */
723 for(cg
=ccg0
; cg
<ccg1
; cg
++)
725 if (cell_index
[cg
] == -1)
727 /* This cg has moved to another node */
728 cell_index
[cg
] = 4*grid
->ncells
;
735 ind
[d
] = (cg_cm
[cg
][d
] - offset
[d
])*n_box
[d
];
736 /* Here we have to correct for rounding problems,
737 * as this cg_cm to cell index operation is not necessarily
738 * binary identical to the operation for the DD zone assignment
739 * and therefore a cg could end up in an unused grid cell.
740 * For dimensions without pbc we need to check
741 * for cells on the edge if charge groups are beyond
742 * the grid and if so, store them in the closest cell.
744 if (ind
[d
] < b0
[d
]) {
747 else if (ind
[d
] >= b1
[d
])
755 /* Charge groups in this DD zone further away than the cut-off
756 * in direction do not participate in non-bonded interactions.
762 if (cg
> grid
->nr_alloc
)
764 fprintf(stderr
,"WARNING: nra_alloc %d cg0 %d cg1 %d cg %d\n",
765 grid
->nr_alloc
,cg0
,cg1
,cg
);
769 cell_index
[cg
] = xyz2ci(nry
,nrz
,ind
[XX
],ind
[YY
],ind
[ZZ
]);
773 cell_index
[cg
] = not_used
;
782 void check_grid(FILE *log
,t_grid
*grid
)
784 int ix
,iy
,iz
,ci
,cci
,nra
;
787 gmx_fatal(FARGS
,"Number of grid cells is zero. Probably the system and box collapsed.\n");
791 for(ix
=0; (ix
<grid
->n
[XX
]); ix
++)
792 for(iy
=0; (iy
<grid
->n
[YY
]); iy
++)
793 for(iz
=0; (iz
<grid
->n
[ZZ
]); iz
++,ci
++) {
795 nra
=grid
->index
[ci
]-grid
->index
[cci
];
796 if (nra
!= grid
->nra
[cci
])
797 gmx_fatal(FARGS
,"nra=%d, grid->nra=%d, cci=%d",
798 nra
,grid
->nra
[cci
],cci
);
800 cci
=xyz2ci(grid
->n
[YY
],grid
->n
[ZZ
],ix
,iy
,iz
);
801 range_check_mesg(cci
,0,grid
->ncells
,range_warn
);
804 gmx_fatal(FARGS
,"ci = %d, cci = %d",ci
,cci
);
808 void print_grid(FILE *log
,t_grid
*grid
)
813 fprintf(log
,"nr: %d\n",grid
->nr
);
814 fprintf(log
,"nrx: %d\n",grid
->n
[XX
]);
815 fprintf(log
,"nry: %d\n",grid
->n
[YY
]);
816 fprintf(log
,"nrz: %d\n",grid
->n
[ZZ
]);
817 fprintf(log
,"ncg_ideal: %d\n",grid
->ncg_ideal
);
818 fprintf(log
," i cell_index\n");
819 for(i
=0; (i
<grid
->nr
); i
++)
820 fprintf(log
,"%5d %5d\n",i
,grid
->cell_index
[i
]);
821 fprintf(log
,"cells\n");
822 fprintf(log
," ix iy iz nr index cgs...\n");
824 for(ix
=0; (ix
<grid
->n
[XX
]); ix
++)
825 for(iy
=0; (iy
<grid
->n
[YY
]); iy
++)
826 for(iz
=0; (iz
<grid
->n
[ZZ
]); iz
++,ci
++) {
827 index
=grid
->index
[ci
];
829 fprintf(log
,"%3d%3d%3d%5d%5d",ix
,iy
,iz
,nra
,index
);
830 for(i
=0; (i
<nra
); i
++)
831 fprintf(log
,"%5d",grid
->a
[index
+i
]);
837 void mv_grid(t_commrec
*cr
,t_grid
*grid
)
842 #define next ((cur+1) % (cr->nnodes-cr->npmenodes))
844 ci
= grid
->cell_index
;
845 cgindex
= pd_cgindex(cr
);
846 for(i
=0; (i
<cr
->nnodes
-1); i
++) {
847 start
= cgindex
[cur
];
848 nr
= cgindex
[cur
+1] - start
;
849 gmx_tx(cr
,GMX_LEFT
,&(ci
[start
]),nr
*sizeof(*ci
));
851 start
= cgindex
[next
];
852 nr
= cgindex
[next
+1] - start
;
853 gmx_rx(cr
,GMX_RIGHT
,&(ci
[start
]),nr
*sizeof(*ci
));
855 gmx_tx_wait(cr
, GMX_LEFT
);
856 gmx_rx_wait(cr
, GMX_RIGHT
);