Moved domdec structures out of commrec.h.
[gromacs.git] / src / gromacs / ewald / pme-pp.cpp
blob86945c2934ab2db842057f54c5e02f005200604f
1 /*
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,2015, 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 /*! \internal \file
39 * \brief This file contains function definitions necessary for
40 * managing the offload of long-ranged PME work to separate MPI rank,
41 * for computing energies and forces (Coulomb and LJ).
43 * \author Berk Hess <hess@kth.se>
44 * \ingroup module_ewald
47 #include "gmxpre.h"
49 #include "config.h"
51 #include <math.h>
52 #include <stdio.h>
53 #include <string.h>
55 #include "gromacs/domdec/domdec.h"
56 #include "gromacs/domdec/domdec_struct.h"
57 #include "gromacs/ewald/pme.h"
58 #include "gromacs/gmxlib/network.h"
59 #include "gromacs/gmxlib/sighandler.h"
60 #include "gromacs/legacyheaders/types/commrec.h"
61 #include "gromacs/math/vec.h"
62 #include "gromacs/mdtypes/md_enums.h"
63 #include "gromacs/utility/fatalerror.h"
64 #include "gromacs/utility/gmxmpi.h"
65 #include "gromacs/utility/smalloc.h"
67 #include "pme-internal.h"
69 /*! \brief MPI Tags used to separate communication of different types of quantities */
70 enum {
71 eCommType_ChargeA, eCommType_ChargeB, eCommType_SQRTC6A, eCommType_SQRTC6B,
72 eCommType_SigmaA, eCommType_SigmaB, eCommType_NR, eCommType_COORD,
73 eCommType_CNB
76 //@{
77 /*! \brief Flags used to coordinate PP-PME communication and computation phases
79 * Some parts of the code(gmx_pme_send_q, gmx_pme_recv_q_x) assume
80 * that the six first flags are exactly in this order.
81 * If more PP_PME_...-flags are to be introduced be aware of some of
82 * the PME-specific flags in pme.h. Currently, they are also passed
83 * through here.
86 #define PP_PME_CHARGE (1<<0)
87 #define PP_PME_CHARGEB (1<<1)
88 #define PP_PME_SQRTC6 (1<<2)
89 #define PP_PME_SQRTC6B (1<<3)
90 #define PP_PME_SIGMA (1<<4)
91 #define PP_PME_SIGMAB (1<<5)
92 #define PP_PME_COORD (1<<6)
93 #define PP_PME_FEP_Q (1<<7)
94 #define PP_PME_FEP_LJ (1<<8)
95 #define PP_PME_ENER_VIR (1<<9)
96 #define PP_PME_FINISH (1<<10)
97 #define PP_PME_SWITCHGRID (1<<11)
98 #define PP_PME_RESETCOUNTERS (1<<12)
100 #define PME_PP_SIGSTOP (1<<0)
101 #define PME_PP_SIGSTOPNSS (1<<1)
102 //@}
104 /*! \brief Master PP-PME communication data structure */
105 struct gmx_pme_pp {
106 #ifdef GMX_MPI
107 MPI_Comm mpi_comm_mysim; /**< MPI communicator for this simulation */
108 #endif
109 int nnode; /**< The number of PP node to communicate with */
110 int *node; /**< The PP node ranks */
111 int node_peer; /**< The peer PP node rank */
112 int *nat; /**< The number of atom for each PP node */
113 int flags_charge; /**< The flags sent along with the last charges */
114 //@{
115 /**< Vectors of A- and B-state parameters used to transfer vectors to PME ranks */
116 real *chargeA;
117 real *chargeB;
118 real *sqrt_c6A;
119 real *sqrt_c6B;
120 real *sigmaA;
121 real *sigmaB;
122 //@}
123 rvec *x; /**< Vector of atom coordinates to transfer to PME ranks */
124 rvec *f; /**< Vector of atom forces received from PME ranks */
125 int nalloc; /**< Allocation size of transfer vectors (>= \p nat) */
126 #ifdef GMX_MPI
127 //@{
128 /**< Vectors of MPI objects used in non-blocking communication between multiple PP ranks per PME rank */
129 MPI_Request *req;
130 MPI_Status *stat;
131 //@}
132 #endif
135 /*! \brief Helper struct for PP-PME communication of parameters */
136 struct gmx_pme_comm_n_box_t {
137 int natoms; /**< Number of atoms */
138 matrix box; /**< Box */
139 int maxshift_x; /**< Maximum shift in x direction */
140 int maxshift_y; /**< Maximum shift in y direction */
141 real lambda_q; /**< Free-energy lambda for electrostatics */
142 real lambda_lj; /**< Free-energy lambda for Lennard-Jones */
143 int flags; /**< Control flags */
144 gmx_int64_t step; /**< MD integration step number */
145 //@{
146 /*! \brief Used in PME grid tuning */
147 ivec grid_size;
148 real ewaldcoeff_q;
149 real ewaldcoeff_lj;
150 //@}
153 /*! \brief Helper struct for PP-PME communication of virial and energy */
154 typedef struct {
155 //@{
156 /*! \brief Virial, energy, and derivative of potential w.r.t. lambda for charge and Lennard-Jones */
157 matrix vir_q;
158 matrix vir_lj;
159 real energy_q;
160 real energy_lj;
161 real dvdlambda_q;
162 real dvdlambda_lj;
163 //@}
164 float cycles; /**< Counter of CPU cycles used */
165 gmx_stop_cond_t stop_cond; /**< Flag used in responding to an external signal to terminate */
166 } gmx_pme_comm_vir_ene_t;
168 gmx_pme_pp_t gmx_pme_pp_init(t_commrec *cr)
170 struct gmx_pme_pp *pme_pp;
172 snew(pme_pp, 1);
174 #ifdef GMX_MPI
175 int rank;
177 pme_pp->mpi_comm_mysim = cr->mpi_comm_mysim;
178 MPI_Comm_rank(cr->mpi_comm_mygroup, &rank);
179 get_pme_ddnodes(cr, rank, &pme_pp->nnode, &pme_pp->node, &pme_pp->node_peer);
180 snew(pme_pp->nat, pme_pp->nnode);
181 snew(pme_pp->req, eCommType_NR*pme_pp->nnode);
182 snew(pme_pp->stat, eCommType_NR*pme_pp->nnode);
183 pme_pp->nalloc = 0;
184 pme_pp->flags_charge = 0;
185 #else
186 GMX_UNUSED_VALUE(cr);
187 #endif
189 return pme_pp;
192 /*! \brief Block to wait for communication to PME ranks to complete
194 * This should be faster with a real non-blocking MPI implementation */
195 /* #define GMX_PME_DELAYED_WAIT */
197 static void gmx_pme_send_coeffs_coords_wait(gmx_domdec_t gmx_unused *dd)
199 #ifdef GMX_MPI
200 if (dd->nreq_pme)
202 MPI_Waitall(dd->nreq_pme, dd->req_pme, MPI_STATUSES_IGNORE);
203 dd->nreq_pme = 0;
205 #endif
208 /*! \brief Send data to PME ranks */
209 static void gmx_pme_send_coeffs_coords(t_commrec *cr, int flags,
210 real gmx_unused *chargeA, real gmx_unused *chargeB,
211 real gmx_unused *c6A, real gmx_unused *c6B,
212 real gmx_unused *sigmaA, real gmx_unused *sigmaB,
213 matrix box, rvec gmx_unused *x,
214 real lambda_q, real lambda_lj,
215 int maxshift_x, int maxshift_y,
216 gmx_int64_t step)
218 gmx_domdec_t *dd;
219 gmx_pme_comm_n_box_t *cnb;
220 int n;
222 dd = cr->dd;
223 n = dd->nat_home;
225 if (debug)
227 fprintf(debug, "PP rank %d sending to PME rank %d: %d%s%s%s%s\n",
228 cr->sim_nodeid, dd->pme_nodeid, n,
229 flags & PP_PME_CHARGE ? " charges" : "",
230 flags & PP_PME_SQRTC6 ? " sqrtC6" : "",
231 flags & PP_PME_SIGMA ? " sigma" : "",
232 flags & PP_PME_COORD ? " coordinates" : "");
235 #ifdef GMX_PME_DELAYED_WAIT
236 /* When can not use cnb until pending communication has finished */
237 gmx_pme_send_coeffs_coords_wait(dd);
238 #endif
240 if (dd->pme_receive_vir_ener)
242 /* Peer PP node: communicate all data */
243 if (dd->cnb == NULL)
245 snew(dd->cnb, 1);
247 cnb = dd->cnb;
249 cnb->flags = flags;
250 cnb->natoms = n;
251 cnb->maxshift_x = maxshift_x;
252 cnb->maxshift_y = maxshift_y;
253 cnb->lambda_q = lambda_q;
254 cnb->lambda_lj = lambda_lj;
255 cnb->step = step;
256 if (flags & PP_PME_COORD)
258 copy_mat(box, cnb->box);
260 #ifdef GMX_MPI
261 MPI_Isend(cnb, sizeof(*cnb), MPI_BYTE,
262 dd->pme_nodeid, eCommType_CNB, cr->mpi_comm_mysim,
263 &dd->req_pme[dd->nreq_pme++]);
264 #endif
266 else if (flags & (PP_PME_CHARGE | PP_PME_SQRTC6 | PP_PME_SIGMA))
268 #ifdef GMX_MPI
269 /* Communicate only the number of atoms */
270 MPI_Isend(&n, sizeof(n), MPI_BYTE,
271 dd->pme_nodeid, eCommType_CNB, cr->mpi_comm_mysim,
272 &dd->req_pme[dd->nreq_pme++]);
273 #endif
276 #ifdef GMX_MPI
277 if (n > 0)
279 if (flags & PP_PME_CHARGE)
281 MPI_Isend(chargeA, n*sizeof(real), MPI_BYTE,
282 dd->pme_nodeid, eCommType_ChargeA, cr->mpi_comm_mysim,
283 &dd->req_pme[dd->nreq_pme++]);
285 if (flags & PP_PME_CHARGEB)
287 MPI_Isend(chargeB, n*sizeof(real), MPI_BYTE,
288 dd->pme_nodeid, eCommType_ChargeB, cr->mpi_comm_mysim,
289 &dd->req_pme[dd->nreq_pme++]);
291 if (flags & PP_PME_SQRTC6)
293 MPI_Isend(c6A, n*sizeof(real), MPI_BYTE,
294 dd->pme_nodeid, eCommType_SQRTC6A, cr->mpi_comm_mysim,
295 &dd->req_pme[dd->nreq_pme++]);
297 if (flags & PP_PME_SQRTC6B)
299 MPI_Isend(c6B, n*sizeof(real), MPI_BYTE,
300 dd->pme_nodeid, eCommType_SQRTC6B, cr->mpi_comm_mysim,
301 &dd->req_pme[dd->nreq_pme++]);
303 if (flags & PP_PME_SIGMA)
305 MPI_Isend(sigmaA, n*sizeof(real), MPI_BYTE,
306 dd->pme_nodeid, eCommType_SigmaA, cr->mpi_comm_mysim,
307 &dd->req_pme[dd->nreq_pme++]);
309 if (flags & PP_PME_SIGMAB)
311 MPI_Isend(sigmaB, n*sizeof(real), MPI_BYTE,
312 dd->pme_nodeid, eCommType_SigmaB, cr->mpi_comm_mysim,
313 &dd->req_pme[dd->nreq_pme++]);
315 if (flags & PP_PME_COORD)
317 MPI_Isend(x[0], n*sizeof(rvec), MPI_BYTE,
318 dd->pme_nodeid, eCommType_COORD, cr->mpi_comm_mysim,
319 &dd->req_pme[dd->nreq_pme++]);
323 #ifndef GMX_PME_DELAYED_WAIT
324 /* Wait for the data to arrive */
325 /* We can skip this wait as we are sure x and q will not be modified
326 * before the next call to gmx_pme_send_x_q or gmx_pme_receive_f.
328 gmx_pme_send_coeffs_coords_wait(dd);
329 #endif
330 #endif
333 void gmx_pme_send_parameters(t_commrec *cr,
334 const interaction_const_t *ic,
335 gmx_bool bFreeEnergy_q, gmx_bool bFreeEnergy_lj,
336 real *chargeA, real *chargeB,
337 real *sqrt_c6A, real *sqrt_c6B,
338 real *sigmaA, real *sigmaB,
339 int maxshift_x, int maxshift_y)
341 int flags;
343 flags = 0;
344 if (EEL_PME(ic->eeltype))
346 flags |= PP_PME_CHARGE;
348 if (EVDW_PME(ic->vdwtype))
350 flags |= (PP_PME_SQRTC6 | PP_PME_SIGMA);
352 if (bFreeEnergy_q || bFreeEnergy_lj)
354 /* Assumes that the B state flags are in the bits just above
355 * the ones for the A state. */
356 flags |= (flags << 1);
359 gmx_pme_send_coeffs_coords(cr, flags,
360 chargeA, chargeB,
361 sqrt_c6A, sqrt_c6B, sigmaA, sigmaB,
362 NULL, NULL, 0, 0, maxshift_x, maxshift_y, -1);
365 void gmx_pme_send_coordinates(t_commrec *cr, matrix box, rvec *x,
366 gmx_bool bFreeEnergy_q, gmx_bool bFreeEnergy_lj,
367 real lambda_q, real lambda_lj,
368 gmx_bool bEnerVir, int pme_flags,
369 gmx_int64_t step)
371 int flags;
373 flags = pme_flags | PP_PME_COORD;
374 if (bFreeEnergy_q)
376 flags |= PP_PME_FEP_Q;
378 if (bFreeEnergy_lj)
380 flags |= PP_PME_FEP_LJ;
382 if (bEnerVir)
384 flags |= PP_PME_ENER_VIR;
386 gmx_pme_send_coeffs_coords(cr, flags, NULL, NULL, NULL, NULL, NULL, NULL,
387 box, x, lambda_q, lambda_lj, 0, 0, step);
390 void gmx_pme_send_finish(t_commrec *cr)
392 int flags;
394 flags = PP_PME_FINISH;
396 gmx_pme_send_coeffs_coords(cr, flags, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, -1);
399 void gmx_pme_send_switchgrid(t_commrec gmx_unused *cr,
400 ivec gmx_unused grid_size,
401 real gmx_unused ewaldcoeff_q,
402 real gmx_unused ewaldcoeff_lj)
404 #ifdef GMX_MPI
405 gmx_pme_comm_n_box_t cnb;
407 /* Only let one PP node signal each PME node */
408 if (cr->dd->pme_receive_vir_ener)
410 cnb.flags = PP_PME_SWITCHGRID;
411 copy_ivec(grid_size, cnb.grid_size);
412 cnb.ewaldcoeff_q = ewaldcoeff_q;
413 cnb.ewaldcoeff_lj = ewaldcoeff_lj;
415 /* We send this, uncommon, message blocking to simplify the code */
416 MPI_Send(&cnb, sizeof(cnb), MPI_BYTE,
417 cr->dd->pme_nodeid, eCommType_CNB, cr->mpi_comm_mysim);
419 #endif
422 void gmx_pme_send_resetcounters(t_commrec gmx_unused *cr, gmx_int64_t gmx_unused step)
424 #ifdef GMX_MPI
425 gmx_pme_comm_n_box_t cnb;
427 /* Only let one PP node signal each PME node */
428 if (cr->dd->pme_receive_vir_ener)
430 cnb.flags = PP_PME_RESETCOUNTERS;
431 cnb.step = step;
433 /* We send this, uncommon, message blocking to simplify the code */
434 MPI_Send(&cnb, sizeof(cnb), MPI_BYTE,
435 cr->dd->pme_nodeid, eCommType_CNB, cr->mpi_comm_mysim);
437 #endif
440 int gmx_pme_recv_coeffs_coords(struct gmx_pme_pp *pme_pp,
441 int *natoms,
442 real **chargeA,
443 real **chargeB,
444 real **sqrt_c6A,
445 real **sqrt_c6B,
446 real **sigmaA,
447 real **sigmaB,
448 matrix box,
449 rvec **x,
450 rvec **f,
451 int *maxshift_x,
452 int *maxshift_y,
453 gmx_bool *bFreeEnergy_q,
454 gmx_bool *bFreeEnergy_lj,
455 real *lambda_q,
456 real *lambda_lj,
457 gmx_bool *bEnerVir,
458 int *pme_flags,
459 gmx_int64_t *step,
460 ivec grid_size,
461 real *ewaldcoeff_q,
462 real *ewaldcoeff_lj)
464 int nat = 0, status;
466 *pme_flags = 0;
467 #ifdef GMX_MPI
468 gmx_pme_comm_n_box_t cnb;
469 int messages;
471 cnb.flags = 0;
472 messages = 0;
476 /* Receive the send count, box and time step from the peer PP node */
477 MPI_Recv(&cnb, sizeof(cnb), MPI_BYTE,
478 pme_pp->node_peer, eCommType_CNB,
479 pme_pp->mpi_comm_mysim, MPI_STATUS_IGNORE);
481 if (debug)
483 fprintf(debug, "PME only rank receiving:%s%s%s%s%s\n",
484 (cnb.flags & PP_PME_CHARGE) ? " charges" : "",
485 (cnb.flags & PP_PME_COORD ) ? " coordinates" : "",
486 (cnb.flags & PP_PME_FINISH) ? " finish" : "",
487 (cnb.flags & PP_PME_SWITCHGRID) ? " switch grid" : "",
488 (cnb.flags & PP_PME_RESETCOUNTERS) ? " reset counters" : "");
491 if (cnb.flags & PP_PME_SWITCHGRID)
493 /* Special case, receive the new parameters and return */
494 copy_ivec(cnb.grid_size, grid_size);
495 *ewaldcoeff_q = cnb.ewaldcoeff_q;
496 *ewaldcoeff_lj = cnb.ewaldcoeff_lj;
497 return pmerecvqxSWITCHGRID;
500 if (cnb.flags & PP_PME_RESETCOUNTERS)
502 /* Special case, receive the step and return */
503 *step = cnb.step;
505 return pmerecvqxRESETCOUNTERS;
508 if (cnb.flags & (PP_PME_CHARGE | PP_PME_SQRTC6 | PP_PME_SIGMA))
510 /* Receive the send counts from the other PP nodes */
511 for (int sender = 0; sender < pme_pp->nnode; sender++)
513 if (pme_pp->node[sender] == pme_pp->node_peer)
515 pme_pp->nat[sender] = cnb.natoms;
517 else
519 MPI_Irecv(&(pme_pp->nat[sender]), sizeof(pme_pp->nat[0]),
520 MPI_BYTE,
521 pme_pp->node[sender], eCommType_CNB,
522 pme_pp->mpi_comm_mysim, &pme_pp->req[messages++]);
525 MPI_Waitall(messages, pme_pp->req, pme_pp->stat);
526 messages = 0;
528 nat = 0;
529 for (int sender = 0; sender < pme_pp->nnode; sender++)
531 nat += pme_pp->nat[sender];
534 if (nat > pme_pp->nalloc)
536 pme_pp->nalloc = over_alloc_dd(nat);
537 if (cnb.flags & PP_PME_CHARGE)
539 srenew(pme_pp->chargeA, pme_pp->nalloc);
541 if (cnb.flags & PP_PME_CHARGEB)
543 srenew(pme_pp->chargeB, pme_pp->nalloc);
545 if (cnb.flags & PP_PME_SQRTC6)
547 srenew(pme_pp->sqrt_c6A, pme_pp->nalloc);
549 if (cnb.flags & PP_PME_SQRTC6B)
551 srenew(pme_pp->sqrt_c6B, pme_pp->nalloc);
553 if (cnb.flags & PP_PME_SIGMA)
555 srenew(pme_pp->sigmaA, pme_pp->nalloc);
557 if (cnb.flags & PP_PME_SIGMAB)
559 srenew(pme_pp->sigmaB, pme_pp->nalloc);
561 srenew(pme_pp->x, pme_pp->nalloc);
562 srenew(pme_pp->f, pme_pp->nalloc);
565 /* maxshift is sent when the charges are sent */
566 *maxshift_x = cnb.maxshift_x;
567 *maxshift_y = cnb.maxshift_y;
569 /* Receive the charges in place */
570 for (int q = 0; q < eCommType_NR; q++)
572 real *charge_pp;
574 if (!(cnb.flags & (PP_PME_CHARGE<<q)))
576 continue;
578 switch (q)
580 case eCommType_ChargeA: charge_pp = pme_pp->chargeA; break;
581 case eCommType_ChargeB: charge_pp = pme_pp->chargeB; break;
582 case eCommType_SQRTC6A: charge_pp = pme_pp->sqrt_c6A; break;
583 case eCommType_SQRTC6B: charge_pp = pme_pp->sqrt_c6B; break;
584 case eCommType_SigmaA: charge_pp = pme_pp->sigmaA; break;
585 case eCommType_SigmaB: charge_pp = pme_pp->sigmaB; break;
586 default: gmx_incons("Wrong eCommType");
588 nat = 0;
589 for (int sender = 0; sender < pme_pp->nnode; sender++)
591 if (pme_pp->nat[sender] > 0)
593 MPI_Irecv(charge_pp+nat,
594 pme_pp->nat[sender]*sizeof(real),
595 MPI_BYTE,
596 pme_pp->node[sender], q,
597 pme_pp->mpi_comm_mysim,
598 &pme_pp->req[messages++]);
599 nat += pme_pp->nat[sender];
600 if (debug)
602 fprintf(debug, "Received from PP rank %d: %d %s\n",
603 pme_pp->node[sender], pme_pp->nat[sender],
604 (q == eCommType_ChargeA ||
605 q == eCommType_ChargeB) ? "charges" : "params");
611 pme_pp->flags_charge = cnb.flags;
614 if (cnb.flags & PP_PME_COORD)
616 if (!(pme_pp->flags_charge & (PP_PME_CHARGE | PP_PME_SQRTC6)))
618 gmx_incons("PME-only rank received coordinates before charges and/or C6-values"
622 /* The box, FE flag and lambda are sent along with the coordinates
623 * */
624 copy_mat(cnb.box, box);
625 *bFreeEnergy_q = ((cnb.flags & GMX_PME_DO_COULOMB) &&
626 (cnb.flags & PP_PME_FEP_Q));
627 *bFreeEnergy_lj = ((cnb.flags & GMX_PME_DO_LJ) &&
628 (cnb.flags & PP_PME_FEP_LJ));
629 *lambda_q = cnb.lambda_q;
630 *lambda_lj = cnb.lambda_lj;
631 *bEnerVir = (cnb.flags & PP_PME_ENER_VIR);
632 *pme_flags = cnb.flags;
634 if (*bFreeEnergy_q && !(pme_pp->flags_charge & PP_PME_CHARGEB))
636 gmx_incons("PME-only rank received free energy request, but "
637 "did not receive B-state charges");
640 if (*bFreeEnergy_lj && !(pme_pp->flags_charge & PP_PME_SQRTC6B))
642 gmx_incons("PME-only rank received free energy request, but "
643 "did not receive B-state C6-values");
646 /* Receive the coordinates in place */
647 nat = 0;
648 for (int sender = 0; sender < pme_pp->nnode; sender++)
650 if (pme_pp->nat[sender] > 0)
652 MPI_Irecv(pme_pp->x[nat], pme_pp->nat[sender]*sizeof(rvec),
653 MPI_BYTE,
654 pme_pp->node[sender], eCommType_COORD,
655 pme_pp->mpi_comm_mysim, &pme_pp->req[messages++]);
656 nat += pme_pp->nat[sender];
657 if (debug)
659 fprintf(debug, "Received from PP rank %d: %d "
660 "coordinates\n",
661 pme_pp->node[sender], pme_pp->nat[sender]);
667 /* Wait for the coordinates and/or charges to arrive */
668 MPI_Waitall(messages, pme_pp->req, pme_pp->stat);
669 messages = 0;
671 while (!(cnb.flags & (PP_PME_COORD | PP_PME_FINISH)));
672 status = ((cnb.flags & PP_PME_FINISH) ? pmerecvqxFINISH : pmerecvqxX);
674 *step = cnb.step;
675 #else
676 GMX_UNUSED_VALUE(box);
677 GMX_UNUSED_VALUE(maxshift_x);
678 GMX_UNUSED_VALUE(maxshift_y);
679 GMX_UNUSED_VALUE(bFreeEnergy_q);
680 GMX_UNUSED_VALUE(bFreeEnergy_lj);
681 GMX_UNUSED_VALUE(lambda_q);
682 GMX_UNUSED_VALUE(lambda_lj);
683 GMX_UNUSED_VALUE(bEnerVir);
684 GMX_UNUSED_VALUE(step);
685 GMX_UNUSED_VALUE(grid_size);
686 GMX_UNUSED_VALUE(ewaldcoeff_q);
687 GMX_UNUSED_VALUE(ewaldcoeff_lj);
689 status = pmerecvqxX;
690 #endif
692 *natoms = nat;
693 *chargeA = pme_pp->chargeA;
694 *chargeB = pme_pp->chargeB;
695 *sqrt_c6A = pme_pp->sqrt_c6A;
696 *sqrt_c6B = pme_pp->sqrt_c6B;
697 *sigmaA = pme_pp->sigmaA;
698 *sigmaB = pme_pp->sigmaB;
699 *x = pme_pp->x;
700 *f = pme_pp->f;
702 return status;
704 /*! \brief Receive virial and energy from PME rank */
705 static void receive_virial_energy(t_commrec *cr,
706 matrix vir_q, real *energy_q,
707 matrix vir_lj, real *energy_lj,
708 real *dvdlambda_q, real *dvdlambda_lj,
709 float *pme_cycles)
711 gmx_pme_comm_vir_ene_t cve;
713 if (cr->dd->pme_receive_vir_ener)
715 if (debug)
717 fprintf(debug,
718 "PP rank %d receiving from PME rank %d: virial and energy\n",
719 cr->sim_nodeid, cr->dd->pme_nodeid);
721 #ifdef GMX_MPI
722 MPI_Recv(&cve, sizeof(cve), MPI_BYTE, cr->dd->pme_nodeid, 1, cr->mpi_comm_mysim,
723 MPI_STATUS_IGNORE);
724 #else
725 memset(&cve, 0, sizeof(cve));
726 #endif
728 m_add(vir_q, cve.vir_q, vir_q);
729 m_add(vir_lj, cve.vir_lj, vir_lj);
730 *energy_q = cve.energy_q;
731 *energy_lj = cve.energy_lj;
732 *dvdlambda_q += cve.dvdlambda_q;
733 *dvdlambda_lj += cve.dvdlambda_lj;
734 *pme_cycles = cve.cycles;
736 if (cve.stop_cond != gmx_stop_cond_none)
738 gmx_set_stop_condition(cve.stop_cond);
741 else
743 *energy_q = 0;
744 *energy_lj = 0;
745 *pme_cycles = 0;
749 void gmx_pme_receive_f(t_commrec *cr,
750 rvec f[], matrix vir_q, real *energy_q,
751 matrix vir_lj, real *energy_lj,
752 real *dvdlambda_q, real *dvdlambda_lj,
753 float *pme_cycles)
755 int natoms, i;
757 #ifdef GMX_PME_DELAYED_WAIT
758 /* Wait for the x request to finish */
759 gmx_pme_send_coeffs_coords_wait(cr->dd);
760 #endif
762 natoms = cr->dd->nat_home;
764 if (natoms > cr->dd->pme_recv_f_alloc)
766 cr->dd->pme_recv_f_alloc = over_alloc_dd(natoms);
767 srenew(cr->dd->pme_recv_f_buf, cr->dd->pme_recv_f_alloc);
770 #ifdef GMX_MPI
771 MPI_Recv(cr->dd->pme_recv_f_buf[0],
772 natoms*sizeof(rvec), MPI_BYTE,
773 cr->dd->pme_nodeid, 0, cr->mpi_comm_mysim,
774 MPI_STATUS_IGNORE);
775 #endif
777 for (i = 0; i < natoms; i++)
779 rvec_inc(f[i], cr->dd->pme_recv_f_buf[i]);
783 receive_virial_energy(cr, vir_q, energy_q, vir_lj, energy_lj, dvdlambda_q, dvdlambda_lj, pme_cycles);
786 void gmx_pme_send_force_vir_ener(struct gmx_pme_pp *pme_pp,
787 rvec gmx_unused *f,
788 matrix vir_q, real energy_q,
789 matrix vir_lj, real energy_lj,
790 real dvdlambda_q, real dvdlambda_lj,
791 float cycles)
793 #ifdef GMX_MPI
794 gmx_pme_comm_vir_ene_t cve;
795 int messages, ind_start, ind_end;
796 cve.cycles = cycles;
798 /* Now the evaluated forces have to be transferred to the PP nodes */
799 messages = 0;
800 ind_end = 0;
801 for (int receiver = 0; receiver < pme_pp->nnode; receiver++)
803 ind_start = ind_end;
804 ind_end = ind_start + pme_pp->nat[receiver];
805 if (MPI_Isend(f[ind_start], (ind_end-ind_start)*sizeof(rvec), MPI_BYTE,
806 pme_pp->node[receiver], 0,
807 pme_pp->mpi_comm_mysim, &pme_pp->req[messages++]) != 0)
809 gmx_comm("MPI_Isend failed in do_pmeonly");
813 /* send virial and energy to our last PP node */
814 copy_mat(vir_q, cve.vir_q);
815 copy_mat(vir_lj, cve.vir_lj);
816 cve.energy_q = energy_q;
817 cve.energy_lj = energy_lj;
818 cve.dvdlambda_q = dvdlambda_q;
819 cve.dvdlambda_lj = dvdlambda_lj;
820 /* check for the signals to send back to a PP node */
821 cve.stop_cond = gmx_get_stop_condition();
823 cve.cycles = cycles;
825 if (debug)
827 fprintf(debug, "PME rank sending to PP rank %d: virial and energy\n",
828 pme_pp->node_peer);
830 MPI_Isend(&cve, sizeof(cve), MPI_BYTE,
831 pme_pp->node_peer, 1,
832 pme_pp->mpi_comm_mysim, &pme_pp->req[messages++]);
834 /* Wait for the forces to arrive */
835 MPI_Waitall(messages, pme_pp->req, pme_pp->stat);
836 #else
837 gmx_call("MPI not enabled");
838 GMX_UNUSED_VALUE(pme_pp);
839 GMX_UNUSED_VALUE(f);
840 GMX_UNUSED_VALUE(vir_q);
841 GMX_UNUSED_VALUE(energy_q);
842 GMX_UNUSED_VALUE(vir_lj);
843 GMX_UNUSED_VALUE(energy_lj);
844 GMX_UNUSED_VALUE(dvdlambda_q);
845 GMX_UNUSED_VALUE(dvdlambda_lj);
846 GMX_UNUSED_VALUE(cycles);
847 #endif