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, 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.
37 /* This file is completely threadsafe - keep it that way! */
53 #include "gromacs/random/random.h"
54 #include "mtop_util.h"
58 typedef struct gmx_partdec_constraint
60 int left_range_receive;
61 int right_range_receive;
69 gmx_partdec_constraint_t;
72 typedef struct gmx_partdec {
73 int neighbor[2]; /* The nodeids of left and right neighb */
74 int *cgindex; /* The charge group boundaries, */
76 /* only allocated with particle decomp. */
77 int *index; /* The home particle boundaries, */
79 /* only allocated with particle decomp. */
80 int shift, bshift; /* Coordinates are shifted left for */
81 /* 'shift' systolic pulses, and right */
82 /* for 'bshift' pulses. Forces are */
83 /* shifted right for 'shift' pulses */
84 /* and left for 'bshift' pulses */
85 /* This way is not necessary to shift */
86 /* the coordinates over the entire ring */
87 rvec *vbuf; /* Buffer for summing the forces */
89 MPI_Request mpi_req_rx; /* MPI reqs for async transfers */
90 MPI_Request mpi_req_tx;
92 gmx_partdec_constraint_t * constraints;
96 void gmx_tx(const t_commrec gmx_unused *cr, int gmx_unused dir, void gmx_unused *buf, int gmx_unused bufsize)
105 nodeid = cr->pd->neighbor[dir];
108 fprintf(stderr, "gmx_tx: nodeid=%d, buf=%x, bufsize=%d\n",
109 nodeid, buf, bufsize);
112 /* workaround for crashes encountered with MPI on IRIX 6.5 */
113 if (cr->pd->mpi_req_tx != MPI_REQUEST_NULL)
115 MPI_Test(&cr->pd->mpi_req_tx, &flag, &status);
118 fprintf(stdlog, "gmx_tx called before previous send was complete: nodeid=%d, buf=%x, bufsize=%d\n",
119 nodeid, buf, bufsize);
125 if (MPI_Isend(buf, bufsize, MPI_BYTE, RANK(cr, nodeid), tag, cr->mpi_comm_mygroup, &cr->pd->mpi_req_tx) != 0)
127 gmx_comm("MPI_Isend Failed");
132 void gmx_tx_wait(const t_commrec gmx_unused *cr)
135 gmx_call("gmx_tx_wait");
140 if ((mpi_result = MPI_Wait(&cr->pd->mpi_req_tx, &status)) != 0)
142 gmx_fatal(FARGS, "MPI_Wait: result=%d", mpi_result);
147 void gmx_rx(const t_commrec gmx_unused *cr, int gmx_unused dir, void gmx_unused *buf, int gmx_unused bufsize)
155 nodeid = cr->pd->neighbor[dir];
157 fprintf(stderr, "gmx_rx: nodeid=%d, buf=%x, bufsize=%d\n",
158 nodeid, buf, bufsize);
161 if (MPI_Irecv( buf, bufsize, MPI_BYTE, RANK(cr, nodeid), tag, cr->mpi_comm_mygroup, &cr->pd->mpi_req_rx) != 0)
163 gmx_comm("MPI_Recv Failed");
168 void gmx_rx_wait(const t_commrec gmx_unused *cr)
171 gmx_call("gmx_rx_wait");
176 if ((mpi_result = MPI_Wait(&cr->pd->mpi_req_rx, &status)) != 0)
178 gmx_fatal(FARGS, "MPI_Wait: result=%d", mpi_result);
183 void gmx_tx_rx_real(const t_commrec gmx_unused *cr,
184 int gmx_unused send_dir, real gmx_unused *send_buf, int gmx_unused send_bufsize,
185 int gmx_unused recv_dir, real gmx_unused *recv_buf, int gmx_unused recv_bufsize)
188 gmx_call("gmx_tx_rx_real");
190 int send_nodeid, recv_nodeid;
191 int tx_tag = 0, rx_tag = 0;
194 send_nodeid = cr->pd->neighbor[send_dir];
195 recv_nodeid = cr->pd->neighbor[recv_dir];
198 #define mpi_type MPI_DOUBLE
200 #define mpi_type MPI_FLOAT
203 if (send_bufsize > 0 && recv_bufsize > 0)
205 MPI_Sendrecv(send_buf, send_bufsize, mpi_type, RANK(cr, send_nodeid), tx_tag,
206 recv_buf, recv_bufsize, mpi_type, RANK(cr, recv_nodeid), rx_tag,
207 cr->mpi_comm_mygroup, &stat);
209 else if (send_bufsize > 0)
211 MPI_Send(send_buf, send_bufsize, mpi_type, RANK(cr, send_nodeid), tx_tag,
212 cr->mpi_comm_mygroup);
214 else if (recv_bufsize > 0)
216 MPI_Recv(recv_buf, recv_bufsize, mpi_type, RANK(cr, recv_nodeid), rx_tag,
217 cr->mpi_comm_mygroup, &stat);
224 void gmx_tx_rx_void(const t_commrec gmx_unused *cr,
225 int gmx_unused send_dir, void gmx_unused *send_buf, int gmx_unused send_bufsize,
226 int gmx_unused recv_dir, void gmx_unused *recv_buf, int gmx_unused recv_bufsize)
229 gmx_call("gmx_tx_rx_void");
231 int send_nodeid, recv_nodeid;
232 int tx_tag = 0, rx_tag = 0;
235 send_nodeid = cr->pd->neighbor[send_dir];
236 recv_nodeid = cr->pd->neighbor[recv_dir];
239 MPI_Sendrecv(send_buf, send_bufsize, MPI_BYTE, RANK(cr, send_nodeid), tx_tag,
240 recv_buf, recv_bufsize, MPI_BYTE, RANK(cr, recv_nodeid), rx_tag,
241 cr->mpi_comm_mygroup, &stat);
247 /*void gmx_wait(int dir_send,int dir_recv)*/
249 void gmx_wait(const t_commrec gmx_unused *cr)
252 gmx_call("gmx_wait");
259 static void set_left_right(t_commrec *cr)
261 cr->pd->neighbor[GMX_LEFT] = (cr->nnodes + cr->nodeid - 1) % cr->nnodes;
262 cr->pd->neighbor[GMX_RIGHT] = (cr->nodeid + 1) % cr->nnodes;
265 void pd_move_f(const t_commrec *cr, rvec f[], t_nrnb *nrnb)
267 move_f(cr, f, cr->pd->vbuf, nrnb);
270 int *pd_cgindex(const t_commrec *cr)
272 return cr->pd->cgindex;
275 int *pd_index(const t_commrec *cr)
277 return cr->pd->index;
280 int pd_shift(const t_commrec *cr)
282 return cr->pd->shift;
285 int pd_bshift(const t_commrec *cr)
287 return cr->pd->bshift;
290 void pd_cg_range(const t_commrec *cr, int *cg0, int *cg1)
292 *cg0 = cr->pd->cgindex[cr->nodeid];
293 *cg1 = cr->pd->cgindex[cr->nodeid+1];
296 void pd_at_range(const t_commrec *cr, int *at0, int *at1)
298 *at0 = cr->pd->index[cr->nodeid];
299 *at1 = cr->pd->index[cr->nodeid+1];
303 pd_get_constraint_range(gmx_partdec_p_t pd, int *start, int *natoms)
305 *start = pd->constraints->left_range_receive;
306 *natoms = pd->constraints->right_range_receive-pd->constraints->left_range_receive;
310 pd_constraints_nlocalatoms(gmx_partdec_p_t pd)
314 if (NULL != pd && NULL != pd->constraints)
316 rc = pd->constraints->nlocalatoms;
328 /* This routine is used to communicate the non-home-atoms needed for constrains.
329 * We have already calculated this range of atoms during setup, and stored in the
330 * partdec constraints structure.
332 * When called, we send/receive left_range_send/receive atoms to our left (lower)
333 * node neighbor, and similar to the right (higher) node.
335 * This has not been tested for periodic molecules...
338 pd_move_x_constraints(t_commrec gmx_unused *cr,
344 gmx_partdec_constraint_t *pdc;
351 int sendcnt, recvcnt;
354 pdc = pd->constraints;
361 thisnode = cr->nodeid;
363 /* First pulse to right */
365 recvcnt = 3*(pd->index[thisnode]-pdc->left_range_receive);
366 sendcnt = 3*(cr->pd->index[thisnode+1]-cr->pd->constraints->right_range_send);
370 /* Assemble temporary array with both x0 & x1 */
371 recvptr = pdc->recvbuf;
372 sendptr = pdc->sendbuf;
375 for (i = pdc->right_range_send; i < pd->index[thisnode+1]; i++)
377 copy_rvec(x0[i], sendptr[cnt++]);
379 for (i = pdc->right_range_send; i < pd->index[thisnode+1]; i++)
381 copy_rvec(x1[i], sendptr[cnt++]);
388 recvptr = x0 + pdc->left_range_receive;
389 sendptr = x0 + pdc->right_range_send;
393 GMX_RIGHT, (real *)sendptr, sendcnt,
394 GMX_LEFT, (real *)recvptr, recvcnt);
398 /* copy back to x0/x1 */
400 for (i = pdc->left_range_receive; i < pd->index[thisnode]; i++)
402 copy_rvec(recvptr[cnt++], x0[i]);
404 for (i = pdc->left_range_receive; i < pd->index[thisnode]; i++)
406 copy_rvec(recvptr[cnt++], x1[i]);
410 /* And pulse to left */
411 sendcnt = 3*(pdc->left_range_send-pd->index[thisnode]);
412 recvcnt = 3*(pdc->right_range_receive-pd->index[thisnode+1]);
417 for (i = cr->pd->index[thisnode]; i < pdc->left_range_send; i++)
419 copy_rvec(x0[i], sendptr[cnt++]);
421 for (i = cr->pd->index[thisnode]; i < pdc->left_range_send; i++)
423 copy_rvec(x1[i], sendptr[cnt++]);
430 sendptr = x0 + pd->index[thisnode];
431 recvptr = x0 + pd->index[thisnode+1];
435 GMX_LEFT, (real *)sendptr, sendcnt,
436 GMX_RIGHT, (real *)recvptr, recvcnt);
438 /* Final copy back from buffers */
441 /* First copy received data back into x0 & x1 */
443 for (i = pd->index[thisnode+1]; i < pdc->right_range_receive; i++)
445 copy_rvec(recvptr[cnt++], x0[i]);
447 for (i = pd->index[thisnode+1]; i < pdc->right_range_receive; i++)
449 copy_rvec(recvptr[cnt++], x1[i]);
455 static int home_cpu(int nnodes, gmx_partdec_t *pd, int atomid)
459 for (k = 0; (k < nnodes); k++)
461 if (atomid < pd->index[k+1])
466 gmx_fatal(FARGS, "Atomid %d is larger than number of atoms (%d)",
467 atomid+1, pd->index[nnodes]+1);
472 static void calc_nsbshift(FILE *fp, int nnodes, gmx_partdec_t *pd, t_idef *idef)
475 int lastcg, targetcg, nshift, naaj;
479 for (i = 1; (i < nnodes); i++)
481 targetcg = pd->cgindex[i];
482 for (nshift = i; (nshift > 0) && (pd->cgindex[nshift] > targetcg); nshift--)
486 pd->bshift = max(pd->bshift, i-nshift);
489 pd->shift = (nnodes + 1)/2;
490 for (i = 0; (i < nnodes); i++)
492 lastcg = pd->cgindex[i+1]-1;
493 naaj = calc_naaj(lastcg, pd->cgindex[nnodes]);
494 targetcg = (lastcg+naaj) % pd->cgindex[nnodes];
496 /* Search until we find the target charge group */
498 (nshift < nnodes) && (targetcg > pd->cgindex[nshift+1]);
503 /* Now compute the shift, that is the difference in node index */
504 nshift = ((nshift - i + nnodes) % nnodes);
508 fprintf(fp, "CPU=%3d, lastcg=%5d, targetcg=%5d, myshift=%5d\n",
509 i, lastcg, targetcg, nshift);
512 /* It's the largest shift that matters */
513 pd->shift = max(nshift, pd->shift);
515 /* Now for the bonded forces */
516 for (i = 0; (i < F_NRE); i++)
518 if (interaction_function[i].flags & IF_BOND)
520 int nratoms = interaction_function[i].nratoms;
521 for (j = 0; (j < idef->il[i].nr); j += nratoms+1)
523 for (k = 1; (k <= nratoms); k++)
525 homeid[k-1] = home_cpu(nnodes, pd, idef->il[i].iatoms[j+k]);
527 for (k = 1; (k < nratoms); k++)
529 pd->shift = max(pd->shift, abs(homeid[k]-homeid[0]));
536 fprintf(fp, "pd->shift = %3d, pd->bshift=%3d\n",
537 pd->shift, pd->bshift);
543 init_partdec_constraint(t_commrec *cr,
548 gmx_partdec_t * pd = cr->pd;
549 gmx_partdec_constraint_t *pdc;
551 int ai, aj, nodei, nodej;
556 cr->pd->constraints = pdc;
562 /* Setup LINCS communication ranges */
563 pdc->left_range_receive = left_range[nodeid];
564 pdc->right_range_receive = right_range[nodeid]+1;
565 pdc->left_range_send = (nodeid > 0) ? right_range[nodeid-1]+1 : 0;
566 pdc->right_range_send = (nodeid < cr->nnodes-1) ? left_range[nodeid+1] : pd->index[cr->nnodes];
568 snew(pdc->nlocalatoms, idef->il[F_CONSTR].nr);
569 nratoms = interaction_function[F_CONSTR].nratoms;
571 for (i = 0, cnt = 0; i < idef->il[F_CONSTR].nr; i += nratoms+1, cnt++)
573 ai = idef->il[F_CONSTR].iatoms[i+1];
574 aj = idef->il[F_CONSTR].iatoms[i+2];
576 while (ai >= pd->index[nodei+1])
581 while (aj >= pd->index[nodej+1])
585 pdc->nlocalatoms[cnt] = 0;
588 pdc->nlocalatoms[cnt]++;
592 pdc->nlocalatoms[cnt]++;
595 pdc->nconstraints = cnt;
597 snew(pdc->sendbuf, max(6*(pd->index[cr->nodeid+1]-pd->constraints->right_range_send), 6*(pdc->left_range_send-pd->index[cr->nodeid])));
598 snew(pdc->recvbuf, max(6*(pd->index[cr->nodeid]-pdc->left_range_receive), 6*(pdc->right_range_receive-pd->index[cr->nodeid+1])));
602 static void init_partdec(FILE *fp, t_commrec *cr, t_block *cgs, int *multinr,
617 gmx_fatal(FARGS, "Internal error in init_partdec: multinr = NULL");
619 snew(pd->index, cr->nnodes+1);
620 snew(pd->cgindex, cr->nnodes+1);
623 for (i = 0; (i < cr->nnodes); i++)
625 pd->cgindex[i+1] = multinr[i];
626 pd->index[i+1] = cgs->index[multinr[i]];
628 calc_nsbshift(fp, cr->nnodes, pd, idef);
629 /* This is a hack to do with bugzilla 148 */
630 /*pd->shift = cr->nnodes-1;
633 /* Allocate a buffer of size natoms of the whole system
634 * for summing the forces over the nodes.
636 snew(pd->vbuf, cgs->index[cgs->nr]);
637 pd->constraints = NULL;
640 pd->mpi_req_tx = MPI_REQUEST_NULL;
641 pd->mpi_req_rx = MPI_REQUEST_NULL;
645 static void print_partdec(FILE *fp, const char *title,
646 int nnodes, gmx_partdec_t *pd)
650 fprintf(fp, "%s\n", title);
651 fprintf(fp, "nnodes: %5d\n", nnodes);
652 fprintf(fp, "pd->shift: %5d\n", pd->shift);
653 fprintf(fp, "pd->bshift: %5d\n", pd->bshift);
655 fprintf(fp, "Nodeid atom0 #atom cg0 #cg\n");
656 for (i = 0; (i < nnodes); i++)
658 fprintf(fp, "%6d%8d%8d%8d%10d\n",
660 pd->index[i], pd->index[i+1]-pd->index[i],
661 pd->cgindex[i], pd->cgindex[i+1]-pd->cgindex[i]);
666 static void pr_idef_division(FILE *fp, t_idef *idef, int nnodes, int **multinr)
668 int i, ftype, nr, nra, m0, m1;
670 fprintf(fp, "Division of bonded forces over processors\n");
671 fprintf(fp, "%-12s", "CPU");
672 for (i = 0; (i < nnodes); i++)
674 fprintf(fp, " %5d", i);
678 for (ftype = 0; (ftype < F_NRE); ftype++)
680 if (idef->il[ftype].nr > 0)
682 nr = idef->il[ftype].nr;
683 nra = 1+interaction_function[ftype].nratoms;
684 fprintf(fp, "%-12s", interaction_function[ftype].name);
685 /* Loop over processors */
686 for (i = 0; (i < nnodes); i++)
688 m0 = (i == 0) ? 0 : multinr[ftype][i-1]/nra;
689 m1 = multinr[ftype][i]/nra;
690 fprintf(fp, " %5d", m1-m0);
697 static void select_my_ilist(t_ilist *il, int *multinr, t_commrec *cr)
700 int i, start, end, nr;
708 start = multinr[cr->nodeid-1];
710 end = multinr[cr->nodeid];
715 gmx_fatal(FARGS, "Negative number of atoms (%d) on node %d\n"
716 "You have probably not used the same value for -np with grompp"
722 for (i = 0; (i < nr); i++)
724 ia[i] = il->iatoms[start+i];
733 static void select_my_idef(t_idef *idef, int **multinr, t_commrec *cr)
737 for (i = 0; (i < F_NRE); i++)
739 select_my_ilist(&idef->il[i], multinr[i], cr);
743 gmx_localtop_t *split_system(FILE *log,
744 gmx_mtop_t *mtop, t_inputrec *inputrec,
749 double tcap = 0, cap;
750 int *multinr_cgs, **multinr_nre;
756 /* Time to setup the division of charge groups over processors */
757 npp = cr->nnodes-cr->npmenodes;
759 cap_env = getenv("GMX_CAPACITY");
762 for (i = 0; (i < npp-1); i++)
764 capacity[i] = 1.0/(double)npp;
767 /* Take care that the sum of capacities is 1.0 */
768 capacity[npp-1] = 1.0 - tcap;
774 for (i = 0; i < npp; i++)
777 sscanf(cap_env+nn, "%lf%n", &cap, &n);
780 gmx_fatal(FARGS, "Incorrect entry or number of entries in GMX_CAPACITY='%s'", cap_env);
786 for (i = 0; i < npp; i++)
792 /* Convert the molecular topology to a fully listed topology */
793 top = gmx_mtop_generate_local_top(mtop, inputrec);
795 snew(multinr_cgs, npp);
796 snew(multinr_nre, F_NRE);
797 for (i = 0; i < F_NRE; i++)
799 snew(multinr_nre[i], npp);
803 snew(left_range, cr->nnodes);
804 snew(right_range, cr->nnodes);
806 /* This computes which entities can be placed on processors */
807 split_top(log, npp, top, inputrec, &mtop->mols, capacity, multinr_cgs, multinr_nre, left_range, right_range);
810 init_partdec(log, cr, &(top->cgs), multinr_cgs, &(top->idef));
812 /* This should be fine */
813 /*split_idef(&(top->idef),cr->nnodes-cr->npmenodes);*/
815 select_my_idef(&(top->idef), multinr_nre, cr);
817 if (top->idef.il[F_CONSTR].nr > 0)
819 init_partdec_constraint(cr, &(top->idef), left_range, right_range);
824 pr_idef_division(log, &(top->idef), npp, multinr_nre);
827 for (i = 0; i < F_NRE; i++)
829 sfree(multinr_nre[i]);
839 print_partdec(log, "Workload division", cr->nnodes, cr->pd);
846 add_to_vsitelist(int **list, int *nitem, int *nalloc, int newitem)
853 for (i = 0; i < idx && !found; i++)
855 found = (newitem == (*list)[i]);
860 srenew(*list, *nalloc);
861 (*list)[idx++] = newitem;
866 gmx_bool setup_parallel_vsites(t_idef *idef, t_commrec *cr,
867 t_comm_vsites *vsitecomm)
876 int nalloc_left_construct, nalloc_right_construct;
877 int sendbuf[2], recvbuf[2];
878 int bufsize, leftbuf, rightbuf;
882 i0 = pd->index[cr->nodeid];
883 i1 = pd->index[cr->nodeid+1];
885 vsitecomm->left_import_construct = NULL;
886 vsitecomm->left_import_nconstruct = 0;
887 nalloc_left_construct = 0;
889 vsitecomm->right_import_construct = NULL;
890 vsitecomm->right_import_nconstruct = 0;
891 nalloc_right_construct = 0;
893 for (ftype = 0; (ftype < F_NRE); ftype++)
895 if (!(interaction_function[ftype].flags & IF_VSITE) )
900 nra = interaction_function[ftype].nratoms;
901 ia = idef->il[ftype].iatoms;
903 for (i = 0; i < idef->il[ftype].nr; i += nra+1)
905 for (j = 2; j < 1+nra; j++)
907 iconstruct = ia[i+j];
910 add_to_vsitelist(&vsitecomm->left_import_construct,
911 &vsitecomm->left_import_nconstruct,
912 &nalloc_left_construct, iconstruct);
914 else if (iconstruct >= i1)
916 add_to_vsitelist(&vsitecomm->right_import_construct,
917 &vsitecomm->right_import_nconstruct,
918 &nalloc_right_construct, iconstruct);
924 /* Pre-communicate the array lengths */
926 GMX_RIGHT, (void *)&vsitecomm->right_import_nconstruct, sizeof(int),
927 GMX_LEFT, (void *)&vsitecomm->left_export_nconstruct, sizeof(int));
929 GMX_LEFT, (void *)&vsitecomm->left_import_nconstruct, sizeof(int),
930 GMX_RIGHT, (void *)&vsitecomm->right_export_nconstruct, sizeof(int));
932 snew(vsitecomm->left_export_construct, vsitecomm->left_export_nconstruct);
933 snew(vsitecomm->right_export_construct, vsitecomm->right_export_nconstruct);
935 /* Communicate the construcing atom index arrays */
937 GMX_RIGHT, (void *)vsitecomm->right_import_construct, vsitecomm->right_import_nconstruct*sizeof(int),
938 GMX_LEFT, (void *)vsitecomm->left_export_construct, vsitecomm->left_export_nconstruct*sizeof(int));
940 /* Communicate the construcing atom index arrays */
942 GMX_LEFT, (void *)vsitecomm->left_import_construct, vsitecomm->left_import_nconstruct*sizeof(int),
943 GMX_RIGHT, (void *)vsitecomm->right_export_construct, vsitecomm->right_export_nconstruct*sizeof(int));
945 leftbuf = max(vsitecomm->left_export_nconstruct, vsitecomm->left_import_nconstruct);
946 rightbuf = max(vsitecomm->right_export_nconstruct, vsitecomm->right_import_nconstruct);
948 bufsize = max(leftbuf, rightbuf);
950 do_comm = (bufsize > 0);
952 snew(vsitecomm->send_buf, 2*bufsize);
953 snew(vsitecomm->recv_buf, 2*bufsize);
958 t_state *partdec_init_local_state(t_commrec gmx_unused *cr, t_state *state_global)
961 t_state *state_local;
963 snew(state_local, 1);
965 /* Copy all the contents */
966 *state_local = *state_global;
967 snew(state_local->lambda, efptNR);
968 /* local storage for lambda */
969 for (i = 0; i < efptNR; i++)
971 state_local->lambda[i] = state_global->lambda[i];
973 if (state_global->nrngi > 1)
975 /* With stochastic dynamics we need local storage for the random state */
976 if (state_local->flags & (1<<estLD_RNG))
978 state_local->nrng = gmx_rng_n();
979 snew(state_local->ld_rng, state_local->nrng);
983 MPI_Scatter(state_global->ld_rng,
984 state_local->nrng*sizeof(state_local->ld_rng[0]), MPI_BYTE,
986 state_local->nrng*sizeof(state_local->ld_rng[0]), MPI_BYTE,
987 MASTERRANK(cr), cr->mpi_comm_mygroup);
991 if (state_local->flags & (1<<estLD_RNGI))
993 snew(state_local->ld_rngi, 1);
997 MPI_Scatter(state_global->ld_rngi,
998 sizeof(state_local->ld_rngi[0]), MPI_BYTE,
999 state_local->ld_rngi,
1000 sizeof(state_local->ld_rngi[0]), MPI_BYTE,
1001 MASTERRANK(cr), cr->mpi_comm_mygroup);