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.
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
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 */
71 eCommType_ChargeA
, eCommType_ChargeB
, eCommType_SQRTC6A
, eCommType_SQRTC6B
,
72 eCommType_SigmaA
, eCommType_SigmaB
, eCommType_NR
, eCommType_COORD
,
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
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)
104 /*! \brief Master PP-PME communication data structure */
107 MPI_Comm mpi_comm_mysim
; /**< MPI communicator for this simulation */
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 */
115 /**< Vectors of A- and B-state parameters used to transfer vectors to PME ranks */
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) */
128 /**< Vectors of MPI objects used in non-blocking communication between multiple PP ranks per PME rank */
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 */
146 /*! \brief Used in PME grid tuning */
153 /*! \brief Helper struct for PP-PME communication of virial and energy */
156 /*! \brief Virial, energy, and derivative of potential w.r.t. lambda for charge and Lennard-Jones */
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
;
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
);
184 pme_pp
->flags_charge
= 0;
186 GMX_UNUSED_VALUE(cr
);
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
)
202 MPI_Waitall(dd
->nreq_pme
, dd
->req_pme
, MPI_STATUSES_IGNORE
);
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
,
219 gmx_pme_comm_n_box_t
*cnb
;
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
);
240 if (dd
->pme_receive_vir_ener
)
242 /* Peer PP node: communicate all data */
251 cnb
->maxshift_x
= maxshift_x
;
252 cnb
->maxshift_y
= maxshift_y
;
253 cnb
->lambda_q
= lambda_q
;
254 cnb
->lambda_lj
= lambda_lj
;
256 if (flags
& PP_PME_COORD
)
258 copy_mat(box
, cnb
->box
);
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
++]);
266 else if (flags
& (PP_PME_CHARGE
| PP_PME_SQRTC6
| PP_PME_SIGMA
))
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
++]);
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
);
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
)
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
,
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
,
373 flags
= pme_flags
| PP_PME_COORD
;
376 flags
|= PP_PME_FEP_Q
;
380 flags
|= PP_PME_FEP_LJ
;
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
)
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
)
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
);
422 void gmx_pme_send_resetcounters(t_commrec gmx_unused
*cr
, gmx_int64_t gmx_unused step
)
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
;
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
);
440 int gmx_pme_recv_coeffs_coords(struct gmx_pme_pp
*pme_pp
,
453 gmx_bool
*bFreeEnergy_q
,
454 gmx_bool
*bFreeEnergy_lj
,
468 gmx_pme_comm_n_box_t cnb
;
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
);
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 */
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
;
519 MPI_Irecv(&(pme_pp
->nat
[sender
]), sizeof(pme_pp
->nat
[0]),
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
);
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
++)
574 if (!(cnb
.flags
& (PP_PME_CHARGE
<<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");
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
),
596 pme_pp
->node
[sender
], q
,
597 pme_pp
->mpi_comm_mysim
,
598 &pme_pp
->req
[messages
++]);
599 nat
+= pme_pp
->nat
[sender
];
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
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 */
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
),
654 pme_pp
->node
[sender
], eCommType_COORD
,
655 pme_pp
->mpi_comm_mysim
, &pme_pp
->req
[messages
++]);
656 nat
+= pme_pp
->nat
[sender
];
659 fprintf(debug
, "Received from PP rank %d: %d "
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
);
671 while (!(cnb
.flags
& (PP_PME_COORD
| PP_PME_FINISH
)));
672 status
= ((cnb
.flags
& PP_PME_FINISH
) ? pmerecvqxFINISH
: pmerecvqxX
);
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
);
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
;
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
,
711 gmx_pme_comm_vir_ene_t cve
;
713 if (cr
->dd
->pme_receive_vir_ener
)
718 "PP rank %d receiving from PME rank %d: virial and energy\n",
719 cr
->sim_nodeid
, cr
->dd
->pme_nodeid
);
722 MPI_Recv(&cve
, sizeof(cve
), MPI_BYTE
, cr
->dd
->pme_nodeid
, 1, cr
->mpi_comm_mysim
,
725 memset(&cve
, 0, sizeof(cve
));
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
);
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
,
757 #ifdef GMX_PME_DELAYED_WAIT
758 /* Wait for the x request to finish */
759 gmx_pme_send_coeffs_coords_wait(cr
->dd
);
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
);
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
,
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
,
788 matrix vir_q
, real energy_q
,
789 matrix vir_lj
, real energy_lj
,
790 real dvdlambda_q
, real dvdlambda_lj
,
794 gmx_pme_comm_vir_ene_t cve
;
795 int messages
, ind_start
, ind_end
;
798 /* Now the evaluated forces have to be transferred to the PP nodes */
801 for (int receiver
= 0; receiver
< pme_pp
->nnode
; receiver
++)
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();
827 fprintf(debug
, "PME rank sending to PP rank %d: virial and energy\n",
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
);
837 gmx_call("MPI not enabled");
838 GMX_UNUSED_VALUE(pme_pp
);
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
);