Merge branch 'master' of git://git.gromacs.org/gromacs
[gromacs/adressmacs.git] / src / mdlib / nsgrid.c
blobee9a6dca824312d8968d2a1b2d5bc419c433bcc6
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
3 *
4 * This source code is part of
5 *
6 * G R O M A C S
7 *
8 * GROningen MAchine for Chemical Simulations
9 *
10 * VERSION 3.2.0
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
33 * And Hey:
34 * GROwing Monsters And Cloning Shrimps
36 /* This file is completely threadsafe - keep it that way! */
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
41 #include <stdlib.h>
43 #include "sysstuff.h"
44 #include "typedefs.h"
45 #include "macros.h"
46 #include "smalloc.h"
47 #include "nsgrid.h"
48 #include "gmx_fatal.h"
49 #include "vec.h"
50 #include "network.h"
51 #include "domdec.h"
52 #include "partdec.h"
53 #include "pbc.h"
54 #include <stdio.h>
55 #include "futil.h"
56 #include "pdbio.h"
58 /***********************************
59 * Grid Routines
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)
73 dvec s1,s2;
74 int i,d;
76 clear_dvec(s1);
77 clear_dvec(s2);
79 for(i=0; i<n; i++)
81 for(d=0; d<DIM; d++)
83 s1[d] += x[i][d];
84 s2[d] += x[i][d]*x[i][d];
88 dsvmul(1.0/n,s1,s1);
89 dsvmul(1.0/n,s2,s2);
91 for(d=0; d<DIM; d++)
93 av[d] = s1[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,
117 real *gr0,real *gr1)
119 real av,stddev;
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,
130 gmx_domdec_t *dd,
131 matrix box,gmx_ddbox_t *ddbox,rvec *gr0,rvec *gr1,
132 int ncg,rvec *cgcm,
133 rvec grid_x0,rvec grid_x1,
134 real *grid_density)
136 rvec av,stddev;
137 real vol,bdens0,bdens1;
138 int d;
140 if (grid->nboundeddim < DIM)
142 calc_x_av_stddev(ncg,cgcm,av,stddev);
145 vol = 1;
146 for(d=0; d<DIM; d++)
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]);
154 else
156 if (ddbox == NULL)
158 get_nsgrid_boundaries_vac(av[d],stddev[d],
159 &grid_x0[d],&grid_x1[d],
160 &bdens0,&bdens1);
162 else
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]);
171 bdens0 = grid_x0[d];
172 bdens1 = 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];
178 bdens0 = (*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];
184 bdens1 = (*gr1)[d];
186 vol *= (bdens1 - bdens0);
189 if (debug)
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,
201 t_grid *grid,
202 real grid_density)
204 int i,j;
205 gmx_bool bDD,bDDRect;
206 rvec av,stddev;
207 rvec izones_size;
208 real inv_r_ideal,size,add_tric,radd;
210 for(i=0; (i<DIM); i++)
212 if (debug)
214 fprintf(debug,
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;
227 if (debug)
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);
241 if (!bDD)
243 bDDRect = FALSE;
245 else
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]));
253 radd = rlist;
254 if (i >= ddbox->npbcdim &&
255 (rlist == 0 ||
256 izones_x1[i] + radd > ddbox->box0[i] + ddbox->box_size[i]))
258 radd = ddbox->box0[i] + ddbox->box_size[i] - izones_x1[i];
259 if (radd < 0)
261 radd = 0;
265 /* With DD we only need a grid of one DD cell size + rlist */
266 if (bDDRect)
268 size += radd;
270 else
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++)
280 if (box[j][i] != 0)
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];
302 if (box[j][i] < 0)
304 grid->cell_offset[i] += add_tric;
305 size -= add_tric;
307 else
309 size += add_tric;
314 if (!bDDRect)
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);
321 if (grid->n[i] < 2)
323 grid->n[i] = 2;
325 grid->cell_size[i] = size/grid->n[i];
326 grid->ncpddc[i] = 0;
328 else
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)
338 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;
343 if (debug)
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]);
352 if (debug)
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)
361 int d,m;
362 char *ptr;
363 t_grid *grid;
365 snew(grid,1);
367 grid->npbcdim = ePBC2npbcdim(fr->ePBC);
369 if (fr->ePBC == epbcXY && fr->nwall == 2)
371 grid->nboundeddim = 3;
373 else
375 grid->nboundeddim = grid->npbcdim;
378 if (debug)
380 fprintf(debug,"The coordinates are bounded in %d dimensions\n",
381 grid->nboundeddim);
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");
387 if (ptr)
389 sscanf(ptr,"%d",&grid->ncg_ideal);
390 if (fplog)
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");
399 if (debug)
401 fprintf(debug,"Set ncg_ideal to %d\n",grid->ncg_ideal);
404 return grid;
407 void done_grid(t_grid *grid)
409 grid->nr = 0;
410 clear_ivec(grid->n);
411 grid->ncells = 0;
412 sfree(grid->cell_index);
413 sfree(grid->a);
414 sfree(grid->index);
415 sfree(grid->nra);
416 grid->cells_nalloc = 0;
417 sfree(grid->dcx2);
418 sfree(grid->dcy2);
419 sfree(grid->dcz2);
420 grid->dc_nalloc = 0;
422 if (debug)
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 */
435 int ci;
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];
444 *z = ci;
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)
455 int nr_old,i;
457 grid->nr = 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)
473 int i,m;
474 ivec cx;
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);
486 if (fplog)
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);
500 grid->nr = 0;
501 for(i=0; (i<grid->ncells); i++) {
502 grid->nra[i] = 0;
506 static void calc_bor(int cg0,int cg1,int ncg,int CG0[2],int CG1[2])
508 if (cg1 > ncg) {
509 CG0[0]=cg0;
510 CG1[0]=ncg;
511 CG0[1]=0;
512 CG1[1]=cg1-ncg;
514 else {
515 CG0[0]=cg0;
516 CG1[0]=cg1;
517 CG0[1]=0;
518 CG1[1]=0;
520 if (debug) {
521 int m;
523 fprintf(debug,"calc_bor: cg0=%d, cg1=%d, ncg=%d\n",cg0,cg1,ncg);
524 for(m=0; (m<2); m++)
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)
532 int CG0[2],CG1[2];
533 int *cell_index=grid->cell_index;
534 int *nra=grid->nra;
535 int i,m,ncells;
536 int ci,not_used;
538 ncells=grid->ncells;
539 if(ncells<=0)
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);
545 for(m=0; (m<2); m++)
546 for(i=CG0[m]; (i<CG1[m]); i++) {
547 ci = cell_index[i];
548 if (ci != not_used) {
549 range_check_mesg(ci,0,ncells,range_warn);
550 nra[ci]++;
555 void calc_ptrs(t_grid *grid)
557 int *index = grid->index;
558 int *nra = grid->nra;
559 int ix,iy,iz,ci,nr;
560 int nnra,ncells;
562 ncells=grid->ncells;
563 if(ncells<=0)
564 gmx_fatal(FARGS,"Number of grid cells is zero. Probably the system and box collapsed.\n");
566 ci=nr=0;
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);
571 index[ci] = nr;
572 nnra = nra[ci];
573 nr += nnra;
574 nra[ci] = 0;
578 void grid_last(FILE *log,t_grid *grid,int cg0,int cg1,int ncg)
580 int CG0[2],CG1[2];
581 int i,m;
582 int ci,not_used,ind,ncells;
583 int *cell_index = grid->cell_index;
584 int *nra = grid->nra;
585 int *index = grid->index;
586 int *a = grid->a;
588 ncells=grid->ncells;
589 if (ncells <= 0)
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);
595 for(m=0; (m<2); m++)
596 for(i=CG0[m]; (i<CG1[m]); i++) {
597 ci = cell_index[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);
602 a[ind] = i;
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[])
612 int *cell_index;
613 int nrx,nry,nrz;
614 rvec n_box,offset;
615 int zone,ccg0,ccg1,cg,d,not_used;
616 ivec shift0,useall,b0,b1,ind;
617 gmx_bool bUse;
619 if (cg0 == -1)
621 /* We have already filled the grid up to grid->ncg,
622 * continue from there.
624 cg0 = grid->nr;
627 set_grid_ncg(grid,ncg_tot);
629 cell_index = grid->cell_index;
631 /* Initiate cell borders */
632 nrx = grid->n[XX];
633 nry = grid->n[YY];
634 nrz = grid->n[ZZ];
635 for(d=0; d<DIM; d++)
637 if (grid->cell_size[d] > 0)
639 n_box[d] = 1/grid->cell_size[d];
641 else
643 n_box[d] = 0;
646 copy_rvec(grid->cell_offset,offset);
648 if (debug)
650 fprintf(debug,"Filling grid from %d to %d\n",cg0,cg1);
653 debug_gmx();
654 if (dd_zones == NULL)
656 for (cg=cg0; cg<cg1; cg++)
658 for(d=0; d<DIM; d++)
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.
665 if (ind[d] < 0)
667 ind[d] = 0;
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]);
677 else
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)
685 continue;
688 /* Determine the ns grid cell limits for this DD zone */
689 for(d=0; d<DIM; d++)
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)
701 b0[d] = 0;
702 b1[d] = grid->n[d];
704 else
706 if (shift0[d] == 0)
708 b0[d] = 0;
709 b1[d] = grid->ncpddc[d];
711 else
713 /* shift = 1 */
714 b0[d] = grid->ncpddc[d];
715 b1[d] = grid->n[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;
729 continue;
732 bUse = TRUE;
733 for(d=0; d<DIM; d++)
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]) {
745 ind[d] = b0[d];
747 else if (ind[d] >= b1[d])
749 if (useall[d])
751 ind[d] = b1[d] - 1;
753 else
755 /* Charge groups in this DD zone further away than the cut-off
756 * in direction do not participate in non-bonded interactions.
758 bUse = FALSE;
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);
767 if (bUse)
769 cell_index[cg] = xyz2ci(nry,nrz,ind[XX],ind[YY],ind[ZZ]);
771 else
773 cell_index[cg] = not_used;
778 debug_gmx();
782 void check_grid(FILE *log,t_grid *grid)
784 int ix,iy,iz,ci,cci,nra;
786 if(grid->ncells<=0)
787 gmx_fatal(FARGS,"Number of grid cells is zero. Probably the system and box collapsed.\n");
789 ci=0;
790 cci=0;
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++) {
794 if (ci > 0) {
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);
803 if (cci != ci)
804 gmx_fatal(FARGS,"ci = %d, cci = %d",ci,cci);
808 void print_grid(FILE *log,t_grid *grid)
810 int i,nra,index;
811 int ix,iy,iz,ci;
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");
823 ci=0;
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];
828 nra=grid->nra[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]);
832 fprintf(log,"\n");
834 fflush(log);
837 void mv_grid(t_commrec *cr,t_grid *grid)
839 int i,start,nr;
840 int cur=cr->nodeid;
841 int *ci,*cgindex;
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);
858 cur=next;