1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
4 * This file is part of Gromacs Copyright (c) 1991-2008
5 * David van der Spoel, Erik Lindahl, Berk Hess, University of Groningen.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * To help us fund GROMACS development, we humbly ask that you cite
13 * the research papers on the package. Check out http://www.gromacs.org
16 * Gnomes, ROck Monsters And Chili Sauce
28 #include "domdec_network.h"
29 #include "mtop_util.h"
30 #include "gmx_ga2la.h"
32 #include "gmx_omp_nthreads.h"
47 typedef struct gmx_domdec_specat_comm {
48 /* The number of indices to receive during the setup */
50 /* The atoms to send */
51 gmx_specatsend_t spas[DIM][2];
61 /* The range in the local buffer(s) for received atoms */
65 /* The atom indices we need from the surrounding cells.
66 * We can gather the indices over nthread threads.
70 } gmx_domdec_specat_comm_t;
72 typedef struct gmx_domdec_constraints {
75 /* The fully local and connected constraints */
77 /* The global constraint number, only required for clearing gc_req */
81 /* Boolean that tells if a global constraint index has been requested */
83 /* Global to local communicated constraint atom only index */
86 /* Multi-threading stuff */
89 } gmx_domdec_constraints_t;
92 static void dd_move_f_specat(gmx_domdec_t *dd,gmx_domdec_specat_comm_t *spac,
95 gmx_specatsend_t *spas;
97 int n,n0,n1,d,dim,dir,i;
100 gmx_bool bPBC,bScrew;
103 for(d=dd->ndim-1; d>=0; d--)
108 /* Pulse the grid forward and backward */
109 spas = spac->spas[d];
114 /* Send and receive the coordinates */
115 dd_sendrecv2_rvec(dd,d,
116 f+n+n1,n0,vbuf ,spas[0].nsend,
117 f+n ,n1,vbuf+spas[0].nsend,spas[1].nsend);
118 for(dir=0; dir<2; dir++)
120 bPBC = ((dir == 0 && dd->ci[dim] == 0) ||
121 (dir == 1 && dd->ci[dim] == dd->nc[dim]-1));
122 bScrew = (bPBC && dd->bScrewPBC && dim == XX);
124 spas = &spac->spas[d][dir];
125 /* Sum the buffer into the required forces */
126 if (!bPBC || (!bScrew && fshift == NULL))
128 for(i=0; i<spas->nsend; i++)
130 rvec_inc(f[spas->a[i]],*vbuf);
137 vis[dim] = (dir==0 ? 1 : -1);
141 /* Sum and add to shift forces */
142 for(i=0; i<spas->nsend; i++)
144 rvec_inc(f[spas->a[i]],*vbuf);
145 rvec_inc(fshift[is],*vbuf);
151 /* Rotate the forces */
152 for(i=0; i<spas->nsend; i++)
154 f[spas->a[i]][XX] += (*vbuf)[XX];
155 f[spas->a[i]][YY] -= (*vbuf)[YY];
156 f[spas->a[i]][ZZ] -= (*vbuf)[ZZ];
159 rvec_inc(fshift[is],*vbuf);
169 /* Two cells, so we only need to communicate one way */
170 spas = &spac->spas[d][0];
172 /* Send and receive the coordinates */
173 dd_sendrecv_rvec(dd,d,dddirForward,
174 f+n,spas->nrecv,spac->vbuf,spas->nsend);
175 /* Sum the buffer into the required forces */
176 if (dd->bScrewPBC && dim == XX &&
178 dd->ci[dim] == dd->nc[dim]-1))
180 for(i=0; i<spas->nsend; i++)
182 /* Rotate the force */
183 f[spas->a[i]][XX] += spac->vbuf[i][XX];
184 f[spas->a[i]][YY] -= spac->vbuf[i][YY];
185 f[spas->a[i]][ZZ] -= spac->vbuf[i][ZZ];
190 for(i=0; i<spas->nsend; i++)
192 rvec_inc(f[spas->a[i]],spac->vbuf[i]);
199 void dd_move_f_vsites(gmx_domdec_t *dd,rvec *f,rvec *fshift)
203 dd_move_f_specat(dd,dd->vsite_comm,f,fshift);
207 void dd_clear_f_vsites(gmx_domdec_t *dd,rvec *f)
213 for(i=dd->vsite_comm->at_start; i<dd->vsite_comm->at_end; i++)
220 static void dd_move_x_specat(gmx_domdec_t *dd,gmx_domdec_specat_comm_t *spac,
221 matrix box,rvec *x0,rvec *x1)
223 gmx_specatsend_t *spas;
225 int nvec,v,n,nn,ns0,ns1,nr0,nr1,nr,d,dim,dir,i;
226 gmx_bool bPBC,bScrew=FALSE;
236 for(d=0; d<dd->ndim; d++)
241 /* Pulse the grid forward and backward */
243 for(dir=0; dir<2; dir++)
245 if (dir == 0 && dd->ci[dim] == 0)
248 bScrew = (dd->bScrewPBC && dim == XX);
249 copy_rvec(box[dim],shift);
251 else if (dir == 1 && dd->ci[dim] == dd->nc[dim]-1)
254 bScrew = (dd->bScrewPBC && dim == XX);
257 shift[i] = -box[dim][i];
265 spas = &spac->spas[d][dir];
266 for(v=0; v<nvec; v++)
268 x = (v == 0 ? x0 : x1);
269 /* Copy the required coordinates to the send buffer */
273 for(i=0; i<spas->nsend; i++)
275 copy_rvec(x[spas->a[i]],*vbuf);
281 /* Shift coordinates */
282 for(i=0; i<spas->nsend; i++)
284 rvec_add(x[spas->a[i]],shift,*vbuf);
290 /* Shift and rotate coordinates */
291 for(i=0; i<spas->nsend; i++)
293 (*vbuf)[XX] = x[spas->a[i]][XX] + shift[XX];
294 (*vbuf)[YY] = box[YY][YY] - x[spas->a[i]][YY] + shift[YY];
295 (*vbuf)[ZZ] = box[ZZ][ZZ] - x[spas->a[i]][ZZ] + shift[ZZ];
301 /* Send and receive the coordinates */
302 spas = spac->spas[d];
309 dd_sendrecv2_rvec(dd,d,
310 spac->vbuf+ns0,ns1,x0+n ,nr1,
311 spac->vbuf ,ns0,x0+n+nr1,nr0);
315 /* Communicate both vectors in one buffer */
317 dd_sendrecv2_rvec(dd,d,
318 spac->vbuf+2*ns0,2*ns1,rbuf ,2*nr1,
319 spac->vbuf ,2*ns0,rbuf+2*nr1,2*nr0);
320 /* Split the buffer into the two vectors */
322 for(dir=1; dir>=0; dir--)
324 nr = spas[dir].nrecv;
327 x = (v == 0 ? x0 : x1);
330 copy_rvec(*rbuf,x[nn+i]);
341 spas = &spac->spas[d][0];
342 /* Copy the required coordinates to the send buffer */
344 for(v=0; v<nvec; v++)
346 x = (v == 0 ? x0 : x1);
347 if (dd->bScrewPBC && dim == XX &&
348 (dd->ci[XX] == 0 || dd->ci[XX] == dd->nc[XX]-1))
350 /* Here we only perform the rotation, the rest of the pbc
351 * is handled in the constraint or viste routines.
353 for(i=0; i<spas->nsend; i++)
355 (*vbuf)[XX] = x[spas->a[i]][XX];
356 (*vbuf)[YY] = box[YY][YY] - x[spas->a[i]][YY];
357 (*vbuf)[ZZ] = box[ZZ][ZZ] - x[spas->a[i]][ZZ];
363 for(i=0; i<spas->nsend; i++)
365 copy_rvec(x[spas->a[i]],*vbuf);
370 /* Send and receive the coordinates */
373 dd_sendrecv_rvec(dd,d,dddirBackward,
374 spac->vbuf,spas->nsend,x0+n,spas->nrecv);
378 /* Communicate both vectors in one buffer */
380 dd_sendrecv_rvec(dd,d,dddirBackward,
381 spac->vbuf,2*spas->nsend,rbuf,2*spas->nrecv);
382 /* Split the buffer into the two vectors */
386 x = (v == 0 ? x0 : x1);
389 copy_rvec(*rbuf,x[n+i]);
399 void dd_move_x_constraints(gmx_domdec_t *dd,matrix box,rvec *x0,rvec *x1)
401 if (dd->constraint_comm)
403 dd_move_x_specat(dd,dd->constraint_comm,box,x0,x1);
407 void dd_move_x_vsites(gmx_domdec_t *dd,matrix box,rvec *x)
411 dd_move_x_specat(dd,dd->vsite_comm,box,x,NULL);
415 int *dd_constraints_nlocalatoms(gmx_domdec_t *dd)
419 return dd->constraints->con_nlocat;
427 void dd_clear_local_constraint_indices(gmx_domdec_t *dd)
429 gmx_domdec_constraints_t *dc;
432 dc = dd->constraints;
434 for(i=0; i<dc->ncon; i++)
436 dc->gc_req[dc->con_gl[i]] = 0;
439 if (dd->constraint_comm)
441 gmx_hash_clear_and_optimize(dc->ga2la);
445 void dd_clear_local_vsite_indices(gmx_domdec_t *dd)
451 gmx_hash_clear_and_optimize(dd->ga2la_vsite);
455 static int setup_specat_communication(gmx_domdec_t *dd,
457 gmx_domdec_specat_comm_t *spac,
458 gmx_hash_t ga2la_specat,
461 const char *specat_type,
464 int nsend[2],nlast,nsend_zero[2]={0,0},*nsend_ptr;
465 int d,dim,ndir,dir,nr,ns,i,nrecv_local,n0,start,indr,ind,buf[2];
466 int nat_tot_specat,nat_tot_prev,nalloc_old;
467 gmx_bool bPBC,bFirst;
468 gmx_specatsend_t *spas;
472 fprintf(debug,"Begin setup_specat_communication for %s\n",specat_type);
475 /* nsend[0]: the number of atoms requested by this node only,
476 * we communicate this for more efficients checks
477 * nsend[1]: the total number of requested atoms
482 for(d=dd->ndim-1; d>=0; d--)
484 /* Pulse the grid forward and backward */
486 bPBC = (dim < dd->npbcdim);
487 if (dd->nc[dim] == 2)
489 /* Only 2 cells, so we only need to communicate once */
496 for(dir=0; dir<ndir; dir++)
500 ((dir == 0 && dd->ci[dim] == dd->nc[dim] - 1) ||
501 (dir == 1 && dd->ci[dim] == 0)))
503 /* No pbc: the fist/last cell should not request atoms */
504 nsend_ptr = nsend_zero;
510 /* Communicate the number of indices */
511 dd_sendrecv_int(dd,d,dir==0 ? dddirForward : dddirBackward,
512 nsend_ptr,2,spac->nreq[d][dir],2);
513 nr = spac->nreq[d][dir][1];
514 if (nlast+nr > ireq->nalloc)
516 ireq->nalloc = over_alloc_dd(nlast+nr);
517 srenew(ireq->ind,ireq->nalloc);
519 /* Communicate the indices */
520 dd_sendrecv_int(dd,d,dir==0 ? dddirForward : dddirBackward,
521 ireq->ind,nsend_ptr[1],ireq->ind+nlast,nr);
528 fprintf(debug,"Communicated the counts\n");
531 /* Search for the requested atoms and communicate the indices we have */
532 nat_tot_specat = at_start;
534 for(d=0; d<dd->ndim; d++)
537 /* Pulse the grid forward and backward */
538 if (dd->dim[d] >= dd->npbcdim || dd->nc[dd->dim[d]] > 2)
546 nat_tot_prev = nat_tot_specat;
547 for(dir=ndir-1; dir>=0; dir--)
549 if (nat_tot_specat > spac->bSendAtom_nalloc)
551 nalloc_old = spac->bSendAtom_nalloc;
552 spac->bSendAtom_nalloc = over_alloc_dd(nat_tot_specat);
553 srenew(spac->bSendAtom,spac->bSendAtom_nalloc);
554 for(i=nalloc_old; i<spac->bSendAtom_nalloc; i++)
556 spac->bSendAtom[i] = FALSE;
559 spas = &spac->spas[d][dir];
560 n0 = spac->nreq[d][dir][0];
561 nr = spac->nreq[d][dir][1];
564 fprintf(debug,"dim=%d, dir=%d, searching for %d atoms\n",
572 indr = ireq->ind[start+i];
574 /* Check if this is a home atom and if so ind will be set */
575 if (!ga2la_get_home(dd->ga2la,indr,&ind))
577 /* Search in the communicated atoms */
578 ind = gmx_hash_get_minone(ga2la_specat,indr);
582 if (i < n0 || !spac->bSendAtom[ind])
584 if (spas->nsend+1 > spas->a_nalloc)
586 spas->a_nalloc = over_alloc_large(spas->nsend+1);
587 srenew(spas->a,spas->a_nalloc);
589 /* Store the local index so we know which coordinates
592 spas->a[spas->nsend] = ind;
593 spac->bSendAtom[ind] = TRUE;
594 if (spas->nsend+1 > spac->ibuf_nalloc)
596 spac->ibuf_nalloc = over_alloc_large(spas->nsend+1);
597 srenew(spac->ibuf,spac->ibuf_nalloc);
599 /* Store the global index so we can send it now */
600 spac->ibuf[spas->nsend] = indr;
610 /* Clear the local flags */
611 for(i=0; i<spas->nsend; i++)
613 spac->bSendAtom[spas->a[i]] = FALSE;
615 /* Send and receive the number of indices to communicate */
616 nsend[1] = spas->nsend;
617 dd_sendrecv_int(dd,d,dir==0 ? dddirBackward : dddirForward,
621 fprintf(debug,"Send to node %d, %d (%d) indices, "
622 "receive from node %d, %d (%d) indices\n",
623 dd->neighbor[d][1-dir],nsend[1],nsend[0],
624 dd->neighbor[d][dir],buf[1],buf[0]);
627 for(i=0; i<spas->nsend; i++)
629 fprintf(debug," %d",spac->ibuf[i]+1);
634 nrecv_local += buf[0];
635 spas->nrecv = buf[1];
636 if (nat_tot_specat + spas->nrecv > dd->gatindex_nalloc)
638 dd->gatindex_nalloc =
639 over_alloc_dd(nat_tot_specat + spas->nrecv);
640 srenew(dd->gatindex,dd->gatindex_nalloc);
642 /* Send and receive the indices */
643 dd_sendrecv_int(dd,d,dir==0 ? dddirBackward : dddirForward,
644 spac->ibuf,spas->nsend,
645 dd->gatindex+nat_tot_specat,spas->nrecv);
646 nat_tot_specat += spas->nrecv;
649 /* Allocate the x/f communication buffers */
650 ns = spac->spas[d][0].nsend;
651 nr = spac->spas[d][0].nrecv;
654 ns += spac->spas[d][1].nsend;
655 nr += spac->spas[d][1].nrecv;
657 if (vbuf_fac*ns > spac->vbuf_nalloc)
659 spac->vbuf_nalloc = over_alloc_dd(vbuf_fac*ns);
660 srenew(spac->vbuf,spac->vbuf_nalloc);
662 if (vbuf_fac == 2 && vbuf_fac*nr > spac->vbuf2_nalloc)
664 spac->vbuf2_nalloc = over_alloc_dd(vbuf_fac*nr);
665 srenew(spac->vbuf2,spac->vbuf2_nalloc);
668 /* Make a global to local index for the communication atoms */
669 for(i=nat_tot_prev; i<nat_tot_specat; i++)
671 gmx_hash_change_or_set(ga2la_specat,dd->gatindex[i],i);
675 /* Check that in the end we got the number of atoms we asked for */
676 if (nrecv_local != ireq->n)
680 fprintf(debug,"Requested %d, received %d (tot recv %d)\n",
681 ireq->n,nrecv_local,nat_tot_specat-at_start);
684 for(i=0; i<ireq->n; i++)
686 ind = gmx_hash_get_minone(ga2la_specat,ireq->ind[i]);
687 fprintf(debug," %s%d",
688 (ind >= 0) ? "" : "!",
694 fprintf(stderr,"\nDD cell %d %d %d: Neighboring cells do not have atoms:",
695 dd->ci[XX],dd->ci[YY],dd->ci[ZZ]);
696 for(i=0; i<ireq->n; i++)
698 if (gmx_hash_get_minone(ga2la_specat,ireq->ind[i]) < 0)
700 fprintf(stderr," %d",ireq->ind[i]+1);
703 fprintf(stderr,"\n");
704 gmx_fatal(FARGS,"DD cell %d %d %d could only obtain %d of the %d atoms that are connected via %ss from the neighboring cells. This probably means your %s lengths are too long compared to the domain decomposition cell size. Decrease the number of domain decomposition grid cells%s%s.",
705 dd->ci[XX],dd->ci[YY],dd->ci[ZZ],
706 nrecv_local,ireq->n,specat_type,
708 dd->bGridJump ? " or use the -rcon option of mdrun" : "");
711 spac->at_start = at_start;
712 spac->at_end = nat_tot_specat;
716 fprintf(debug,"Done setup_specat_communication\n");
719 return nat_tot_specat;
722 static void walk_out(int con,int con_offset,int a,int offset,int nrec,
723 int ncon1,const t_iatom *ia1,const t_iatom *ia2,
724 const t_blocka *at2con,
725 const gmx_ga2la_t ga2la,gmx_bool bHomeConnect,
726 gmx_domdec_constraints_t *dc,
727 gmx_domdec_specat_comm_t *dcc,
731 int a1_gl,a2_gl,a_loc,i,coni,b;
734 if (dc->gc_req[con_offset+con] == 0)
736 /* Add this non-home constraint to the list */
737 if (dc->ncon+1 > dc->con_nalloc)
739 dc->con_nalloc = over_alloc_large(dc->ncon+1);
740 srenew(dc->con_gl,dc->con_nalloc);
741 srenew(dc->con_nlocat,dc->con_nalloc);
743 dc->con_gl[dc->ncon] = con_offset + con;
744 dc->con_nlocat[dc->ncon] = (bHomeConnect ? 1 : 0);
745 dc->gc_req[con_offset+con] = 1;
746 if (il_local->nr + 3 > il_local->nalloc)
748 il_local->nalloc = over_alloc_dd(il_local->nr+3);
749 srenew(il_local->iatoms,il_local->nalloc);
751 iap = constr_iatomptr(ncon1,ia1,ia2,con);
752 il_local->iatoms[il_local->nr++] = iap[0];
753 a1_gl = offset + iap[1];
754 a2_gl = offset + iap[2];
755 /* The following indexing code can probably be optizimed */
756 if (ga2la_get_home(ga2la,a1_gl,&a_loc))
758 il_local->iatoms[il_local->nr++] = a_loc;
762 /* We set this index later */
763 il_local->iatoms[il_local->nr++] = -a1_gl - 1;
765 if (ga2la_get_home(ga2la,a2_gl,&a_loc))
767 il_local->iatoms[il_local->nr++] = a_loc;
771 /* We set this index later */
772 il_local->iatoms[il_local->nr++] = -a2_gl - 1;
776 /* Check to not ask for the same atom more than once */
777 if (gmx_hash_get_minone(dc->ga2la,offset+a) == -1)
780 /* Add this non-home atom to the list */
781 if (ireq->n+1 > ireq->nalloc)
783 ireq->nalloc = over_alloc_large(ireq->n+1);
784 srenew(ireq->ind,ireq->nalloc);
786 ireq->ind[ireq->n++] = offset + a;
787 /* Temporarily mark with -2, we get the index later */
788 gmx_hash_set(dc->ga2la,offset+a,-2);
793 for(i=at2con->index[a]; i<at2con->index[a+1]; i++)
799 iap = constr_iatomptr(ncon1,ia1,ia2,coni);
808 if (!ga2la_get_home(ga2la,offset+b,&a_loc))
810 walk_out(coni,con_offset,b,offset,nrec-1,
811 ncon1,ia1,ia2,at2con,
812 ga2la,FALSE,dc,dcc,il_local,ireq);
819 static void atoms_to_settles(gmx_domdec_t *dd,
820 const gmx_mtop_t *mtop,
822 const int **at2settle_mt,
823 int cg_start,int cg_end,
828 gmx_mtop_atomlookup_t alook;
831 int cg,a,a_gl,a_glsa,a_gls[3],a_locs[3];
832 int mb,molnr,a_mol,offset;
833 const gmx_molblock_t *molb;
841 alook = gmx_mtop_atomlookup_settle_init(mtop);
843 nral = NRAL(F_SETTLE);
845 for(cg=cg_start; cg<cg_end; cg++)
847 if (GET_CGINFO_SETTLE(cginfo[cg]))
849 for(a=dd->cgindex[cg]; a<dd->cgindex[cg+1]; a++)
851 a_gl = dd->gatindex[a];
853 gmx_mtop_atomnr_to_molblock_ind(alook,a_gl,&mb,&molnr,&a_mol);
854 molb = &mtop->molblock[mb];
856 settle = at2settle_mt[molb->type][a_mol];
860 offset = a_gl - a_mol;
862 ia1 = mtop->moltype[molb->type].ilist[F_SETTLE].iatoms;
866 for(sa=0; sa<nral; sa++)
868 a_glsa = offset + ia1[settle*(1+nral)+1+sa];
870 a_home[sa] = ga2la_get_home(ga2la,a_glsa,&a_locs[sa]);
873 if (nlocal == 0 && a_gl == a_glsa)
883 if (ils_local->nr+1+nral > ils_local->nalloc)
885 ils_local->nalloc = over_alloc_dd(ils_local->nr+1+nral);
886 srenew(ils_local->iatoms,ils_local->nalloc);
889 ils_local->iatoms[ils_local->nr++] = ia1[settle*4];
891 for(sa=0; sa<nral; sa++)
893 if (ga2la_get_home(ga2la,a_gls[sa],&a_locs[sa]))
895 ils_local->iatoms[ils_local->nr++] = a_locs[sa];
899 ils_local->iatoms[ils_local->nr++] = -a_gls[sa] - 1;
900 /* Add this non-home atom to the list */
901 if (ireq->n+1 > ireq->nalloc)
903 ireq->nalloc = over_alloc_large(ireq->n+1);
904 srenew(ireq->ind,ireq->nalloc);
906 ireq->ind[ireq->n++] = a_gls[sa];
907 /* A check on double atom requests is
908 * not required for settle.
918 gmx_mtop_atomlookup_destroy(alook);
921 static void atoms_to_constraints(gmx_domdec_t *dd,
922 const gmx_mtop_t *mtop,
924 const t_blocka *at2con_mt,int nrec,
928 const t_blocka *at2con;
930 gmx_mtop_atomlookup_t alook;
932 gmx_molblock_t *molb;
933 t_iatom *ia1,*ia2,*iap;
934 int nhome,cg,a,a_gl,a_mol,a_loc,b_lo,offset,mb,molnr,b_mol,i,con,con_offset;
935 gmx_domdec_constraints_t *dc;
936 gmx_domdec_specat_comm_t *dcc;
938 dc = dd->constraints;
939 dcc = dd->constraint_comm;
943 alook = gmx_mtop_atomlookup_init(mtop);
946 for(cg=0; cg<dd->ncg_home; cg++)
948 if (GET_CGINFO_CONSTR(cginfo[cg]))
950 for(a=dd->cgindex[cg]; a<dd->cgindex[cg+1]; a++)
952 a_gl = dd->gatindex[a];
954 gmx_mtop_atomnr_to_molblock_ind(alook,a_gl,&mb,&molnr,&a_mol);
955 molb = &mtop->molblock[mb];
957 ncon1 = mtop->moltype[molb->type].ilist[F_CONSTR].nr/NRAL(F_SETTLE);
959 ia1 = mtop->moltype[molb->type].ilist[F_CONSTR].iatoms;
960 ia2 = mtop->moltype[molb->type].ilist[F_CONSTRNC].iatoms;
962 /* Calculate the global constraint number offset for the molecule.
963 * This is only required for the global index to make sure
964 * that we use each constraint only once.
967 dc->molb_con_offset[mb] + molnr*dc->molb_ncon_mol[mb];
969 /* The global atom number offset for this molecule */
970 offset = a_gl - a_mol;
971 at2con = &at2con_mt[molb->type];
972 for(i=at2con->index[a_mol]; i<at2con->index[a_mol+1]; i++)
975 iap = constr_iatomptr(ncon1,ia1,ia2,con);
984 if (ga2la_get_home(ga2la,offset+b_mol,&a_loc))
986 /* Add this fully home constraint at the first atom */
989 if (dc->ncon+1 > dc->con_nalloc)
991 dc->con_nalloc = over_alloc_large(dc->ncon+1);
992 srenew(dc->con_gl,dc->con_nalloc);
993 srenew(dc->con_nlocat,dc->con_nalloc);
995 dc->con_gl[dc->ncon] = con_offset + con;
996 dc->con_nlocat[dc->ncon] = 2;
997 if (ilc_local->nr + 3 > ilc_local->nalloc)
999 ilc_local->nalloc = over_alloc_dd(ilc_local->nr + 3);
1000 srenew(ilc_local->iatoms,ilc_local->nalloc);
1003 ilc_local->iatoms[ilc_local->nr++] = iap[0];
1004 ilc_local->iatoms[ilc_local->nr++] = (a_gl == iap[1] ? a : b_lo);
1005 ilc_local->iatoms[ilc_local->nr++] = (a_gl == iap[1] ? b_lo : a );
1012 /* We need the nrec constraints coupled to this constraint,
1013 * so we need to walk out of the home cell by nrec+1 atoms,
1014 * since already atom bg is not locally present.
1015 * Therefore we call walk_out with nrec recursions to go
1016 * after this first call.
1018 walk_out(con,con_offset,b_mol,offset,nrec,
1019 ncon1,ia1,ia2,at2con,
1020 dd->ga2la,TRUE,dc,dcc,ilc_local,ireq);
1027 gmx_mtop_atomlookup_destroy(alook);
1032 "Constraints: home %3d border %3d atoms: %3d\n",
1033 nhome,dc->ncon-nhome,
1034 dd->constraint_comm ? ireq->n : 0);
1038 int dd_make_local_constraints(gmx_domdec_t *dd,int at_start,
1039 const gmx_mtop_t *mtop,
1041 gmx_constr_t constr,int nrec,
1044 gmx_domdec_constraints_t *dc;
1045 t_ilist *ilc_local,*ils_local;
1047 const t_blocka *at2con_mt;
1048 const int **at2settle_mt;
1049 gmx_hash_t ga2la_specat;
1053 dc = dd->constraints;
1055 ilc_local = &il_local[F_CONSTR];
1056 ils_local = &il_local[F_SETTLE];
1060 if (dd->constraint_comm)
1062 at2con_mt = atom2constraints_moltype(constr);
1063 ireq = &dd->constraint_comm->ireq[0];
1072 if (dd->bInterCGsettles)
1074 at2settle_mt = atom2settle_moltype(constr);
1079 /* Settle works inside charge groups, we assigned them already */
1080 at2settle_mt = NULL;
1083 if (at2settle_mt == NULL)
1085 atoms_to_constraints(dd,mtop,cginfo,at2con_mt,nrec,
1093 /* Do the constraints, if present, on the first thread.
1094 * Do the settles on all other threads.
1096 t0_set = ((at2con_mt != NULL && dc->nthread > 1) ? 1 : 0);
1098 #pragma omp parallel for num_threads(dc->nthread) schedule(static)
1099 for(thread=0; thread<dc->nthread; thread++)
1101 if (at2con_mt && thread == 0)
1103 atoms_to_constraints(dd,mtop,cginfo,at2con_mt,nrec,
1107 if (thread >= t0_set)
1113 /* Distribute the settle check+assignments over
1114 * dc->nthread or dc->nthread-1 threads.
1116 cg0 = (dd->ncg_home*(thread-t0_set ))/(dc->nthread-t0_set);
1117 cg1 = (dd->ncg_home*(thread-t0_set+1))/(dc->nthread-t0_set);
1119 if (thread == t0_set)
1125 ilst = &dc->ils[thread];
1129 ireqt = &dd->constraint_comm->ireq[thread];
1135 atoms_to_settles(dd,mtop,cginfo,at2settle_mt,
1141 /* Combine the generate settles and requested indices */
1142 for(thread=1; thread<dc->nthread; thread++)
1148 if (thread > t0_set)
1150 ilst = &dc->ils[thread];
1151 if (ils_local->nr + ilst->nr > ils_local->nalloc)
1153 ils_local->nalloc = over_alloc_large(ils_local->nr + ilst->nr);
1154 srenew(ils_local->iatoms,ils_local->nalloc);
1156 for(ia=0; ia<ilst->nr; ia++)
1158 ils_local->iatoms[ils_local->nr+ia] = ilst->iatoms[ia];
1160 ils_local->nr += ilst->nr;
1163 ireqt = &dd->constraint_comm->ireq[thread];
1164 if (ireq->n+ireqt->n > ireq->nalloc)
1166 ireq->nalloc = over_alloc_large(ireq->n+ireqt->n);
1167 srenew(ireq->ind,ireq->nalloc);
1169 for(ia=0; ia<ireqt->n; ia++)
1171 ireq->ind[ireq->n+ia] = ireqt->ind[ia];
1173 ireq->n += ireqt->n;
1178 fprintf(debug,"Settles: total %3d\n",ils_local->nr/4);
1182 if (dd->constraint_comm) {
1186 setup_specat_communication(dd,ireq,dd->constraint_comm,
1187 dd->constraints->ga2la,
1189 "constraint"," or lincs-order");
1191 /* Fill in the missing indices */
1192 ga2la_specat = dd->constraints->ga2la;
1194 nral1 = 1 + NRAL(F_CONSTR);
1195 for(i=0; i<ilc_local->nr; i+=nral1)
1197 iap = ilc_local->iatoms + i;
1198 for(j=1; j<nral1; j++)
1202 iap[j] = gmx_hash_get_minone(ga2la_specat,-iap[j]-1);
1207 nral1 = 1 + NRAL(F_SETTLE);
1208 for(i=0; i<ils_local->nr; i+=nral1)
1210 iap = ils_local->iatoms + i;
1211 for(j=1; j<nral1; j++)
1215 iap[j] = gmx_hash_get_minone(ga2la_specat,-iap[j]-1);
1228 int dd_make_local_vsites(gmx_domdec_t *dd,int at_start,t_ilist *lil)
1230 gmx_domdec_specat_comm_t *spac;
1232 gmx_hash_t ga2la_specat;
1233 int ftype,nral,i,j,gat,a;
1238 spac = dd->vsite_comm;
1239 ireq = &spac->ireq[0];
1240 ga2la_specat = dd->ga2la_vsite;
1243 /* Loop over all the home vsites */
1244 for(ftype=0; ftype<F_NRE; ftype++)
1246 if (interaction_function[ftype].flags & IF_VSITE)
1250 for(i=0; i<lilf->nr; i+=1+nral)
1252 iatoms = lilf->iatoms + i;
1253 /* Check if we have the other atoms */
1254 for(j=1; j<1+nral; j++)
1256 if (iatoms[j] < 0) {
1257 /* This is not a home atom,
1258 * we need to ask our neighbors.
1261 /* Check to not ask for the same atom more than once */
1262 if (gmx_hash_get_minone(dd->ga2la_vsite,a) == -1)
1264 /* Add this non-home atom to the list */
1265 if (ireq->n+1 > ireq->nalloc)
1267 ireq->nalloc = over_alloc_large(ireq->n+1);
1268 srenew(ireq->ind,ireq->nalloc);
1270 ireq->ind[ireq->n++] = a;
1271 /* Temporarily mark with -2,
1272 * we get the index later.
1274 gmx_hash_set(ga2la_specat,a,-2);
1282 at_end = setup_specat_communication(dd,ireq,dd->vsite_comm,ga2la_specat,
1283 at_start,1,"vsite","");
1285 /* Fill in the missing indices */
1286 for(ftype=0; ftype<F_NRE; ftype++)
1288 if (interaction_function[ftype].flags & IF_VSITE)
1292 for(i=0; i<lilf->nr; i+=1+nral)
1294 iatoms = lilf->iatoms + i;
1295 for(j=1; j<1+nral; j++)
1299 iatoms[j] = gmx_hash_get_minone(ga2la_specat,-iatoms[j]-1);
1309 static gmx_domdec_specat_comm_t *specat_comm_init(int nthread)
1311 gmx_domdec_specat_comm_t *spac;
1314 spac->nthread = nthread;
1315 snew(spac->ireq,spac->nthread);
1320 void init_domdec_constraints(gmx_domdec_t *dd,
1322 gmx_constr_t constr)
1324 gmx_domdec_constraints_t *dc;
1325 gmx_molblock_t *molb;
1330 fprintf(debug,"Begin init_domdec_constraints\n");
1333 snew(dd->constraints,1);
1334 dc = dd->constraints;
1336 snew(dc->molb_con_offset,mtop->nmolblock);
1337 snew(dc->molb_ncon_mol,mtop->nmolblock);
1340 for(mb=0; mb<mtop->nmolblock; mb++)
1342 molb = &mtop->molblock[mb];
1343 dc->molb_con_offset[mb] = ncon;
1344 dc->molb_ncon_mol[mb] =
1345 mtop->moltype[molb->type].ilist[F_CONSTR].nr/3 +
1346 mtop->moltype[molb->type].ilist[F_CONSTRNC].nr/3;
1347 ncon += molb->nmol*dc->molb_ncon_mol[mb];
1352 snew(dc->gc_req,ncon);
1353 for(c=0; c<ncon; c++)
1359 /* Use a hash table for the global to local index.
1360 * The number of keys is a rough estimate, it will be optimized later.
1362 dc->ga2la = gmx_hash_init(min(mtop->natoms/20,
1363 mtop->natoms/(2*dd->nnodes)));
1365 dc->nthread = gmx_omp_nthreads_get(emntDomdec);
1366 snew(dc->ils,dc->nthread);
1368 dd->constraint_comm = specat_comm_init(dc->nthread);
1371 void init_domdec_vsites(gmx_domdec_t *dd,int n_intercg_vsite)
1374 gmx_domdec_constraints_t *dc;
1378 fprintf(debug,"Begin init_domdec_vsites\n");
1381 /* Use a hash table for the global to local index.
1382 * The number of keys is a rough estimate, it will be optimized later.
1384 dd->ga2la_vsite = gmx_hash_init(min(n_intercg_vsite/20,
1385 n_intercg_vsite/(2*dd->nnodes)));
1387 dd->vsite_comm = specat_comm_init(1);