7d67cf00ff21e9e0e5fc66331941fa963edf4fdb
[alexxy/gromacs.git] / src / gromacs / mdlib / broadcaststructs.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
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,2016,2017,2018,2019, 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.
10  *
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.
15  *
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.
20  *
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.
25  *
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.
33  *
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.
36  */
37 /* This file is completely threadsafe - keep it that way! */
38 #include "gmxpre.h"
39
40 #include "broadcaststructs.h"
41
42 #include <cstring>
43
44 #include <memory>
45
46 #include "gromacs/gmxlib/network.h"
47 #include "gromacs/math/vec.h"
48 #include "gromacs/mdlib/tgroup.h"
49 #include "gromacs/mdtypes/awh_params.h"
50 #include "gromacs/mdtypes/commrec.h"
51 #include "gromacs/mdtypes/inputrec.h"
52 #include "gromacs/mdtypes/md_enums.h"
53 #include "gromacs/mdtypes/pull_params.h"
54 #include "gromacs/mdtypes/state.h"
55 #include "gromacs/topology/mtop_util.h"
56 #include "gromacs/topology/symtab.h"
57 #include "gromacs/topology/topology.h"
58 #include "gromacs/utility/fatalerror.h"
59 #include "gromacs/utility/inmemoryserializer.h"
60 #include "gromacs/utility/keyvaluetree.h"
61 #include "gromacs/utility/keyvaluetreeserializer.h"
62 #include "gromacs/utility/smalloc.h"
63
64 static void bc_cstring(const t_commrec *cr, char **s)
65 {
66     int size = 0;
67
68     if (MASTER(cr) && *s != nullptr)
69     {
70         /* Size of the char buffer is string length + 1 for '\0' */
71         size = strlen(*s) + 1;
72     }
73     block_bc(cr, size);
74     if (size > 0)
75     {
76         if (!MASTER(cr))
77         {
78             srenew(*s, size);
79         }
80         nblock_bc(cr, size, *s);
81     }
82     else if (!MASTER(cr) && *s != nullptr)
83     {
84         sfree(*s);
85         *s = nullptr;
86     }
87 }
88
89 static void bc_string(const t_commrec *cr, t_symtab *symtab, char ***s)
90 {
91     int handle;
92
93     if (MASTER(cr))
94     {
95         handle = lookup_symtab(symtab, *s);
96     }
97     block_bc(cr, handle);
98     if (!MASTER(cr))
99     {
100         *s = get_symtab_handle(symtab, handle);
101     }
102 }
103
104 static void bc_strings(const t_commrec *cr, t_symtab *symtab, int nr, char ****nm)
105 {
106     int     i;
107     int    *handle;
108
109     snew(handle, nr);
110     if (MASTER(cr))
111     {
112         for (i = 0; (i < nr); i++)
113         {
114             handle[i] = lookup_symtab(symtab, (*nm)[i]);
115         }
116     }
117     nblock_bc(cr, nr, handle);
118
119     if (!MASTER(cr))
120     {
121         snew_bc(cr, *nm, nr);
122         for (i = 0; (i < nr); i++)
123         {
124             (*nm)[i] = get_symtab_handle(symtab, handle[i]);
125         }
126     }
127     sfree(handle);
128 }
129
130 static void bc_strings_container(const t_commrec      *cr,
131                                  t_symtab             *symtab,
132                                  int                   nr,
133                                  std::vector<char **> *nm)
134 {
135     std::vector<int> handle;
136     if (MASTER(cr))
137     {
138         for (int i = 0; (i < nr); i++)
139         {
140             handle.emplace_back(lookup_symtab(symtab, (*nm)[i]));
141         }
142     }
143     block_bc(cr, nr);
144     nblock_abc(cr, nr, &handle);
145
146     if (!MASTER(cr))
147     {
148         nm->resize(nr);
149         for (int i = 0; (i < nr); i++)
150         {
151             (*nm)[i] = get_symtab_handle(symtab, handle[i]);
152         }
153     }
154 }
155
156 static void bc_strings_resinfo(const t_commrec *cr, t_symtab *symtab,
157                                int nr, t_resinfo *resinfo)
158 {
159     int   i;
160     int  *handle;
161
162     snew(handle, nr);
163     if (MASTER(cr))
164     {
165         for (i = 0; (i < nr); i++)
166         {
167             handle[i] = lookup_symtab(symtab, resinfo[i].name);
168         }
169     }
170     nblock_bc(cr, nr, handle);
171
172     if (!MASTER(cr))
173     {
174         for (i = 0; (i < nr); i++)
175         {
176             resinfo[i].name = get_symtab_handle(symtab, handle[i]);
177         }
178     }
179     sfree(handle);
180 }
181
182 static void bc_symtab(const t_commrec *cr, t_symtab *symtab)
183 {
184     int       i, nr, len;
185     t_symbuf *symbuf;
186
187     block_bc(cr, symtab->nr);
188     nr = symtab->nr;
189     snew_bc(cr, symtab->symbuf, 1);
190     symbuf          = symtab->symbuf;
191     symbuf->bufsize = nr;
192     snew_bc(cr, symbuf->buf, nr);
193     for (i = 0; i < nr; i++)
194     {
195         if (MASTER(cr))
196         {
197             len = strlen(symbuf->buf[i]) + 1;
198         }
199         block_bc(cr, len);
200         snew_bc(cr, symbuf->buf[i], len);
201         nblock_bc(cr, len, symbuf->buf[i]);
202     }
203 }
204
205 static void bc_block(const t_commrec *cr, t_block *block)
206 {
207     block_bc(cr, block->nr);
208     snew_bc(cr, block->index, block->nr+1);
209     nblock_bc(cr, block->nr+1, block->index);
210 }
211
212 static void bc_blocka(const t_commrec *cr, t_blocka *block)
213 {
214     block_bc(cr, block->nr);
215     snew_bc(cr, block->index, block->nr+1);
216     nblock_bc(cr, block->nr+1, block->index);
217     block_bc(cr, block->nra);
218     if (block->nra)
219     {
220         snew_bc(cr, block->a, block->nra);
221         nblock_bc(cr, block->nra, block->a);
222     }
223 }
224
225 static void bc_grps(const t_commrec *cr, gmx::ArrayRef<AtomGroupIndices> grps)
226 {
227     for (auto &group : grps)
228     {
229         int size = group.size();
230         block_bc(cr, size);
231         nblock_abc(cr, size, &group);
232     }
233 }
234
235 static void bc_atoms(const t_commrec *cr, t_symtab *symtab, t_atoms *atoms)
236 {
237     block_bc(cr, atoms->nr);
238     snew_bc(cr, atoms->atom, atoms->nr);
239     nblock_bc(cr, atoms->nr, atoms->atom);
240     bc_strings(cr, symtab, atoms->nr, &atoms->atomname);
241     block_bc(cr, atoms->nres);
242     snew_bc(cr, atoms->resinfo, atoms->nres);
243     nblock_bc(cr, atoms->nres, atoms->resinfo);
244     bc_strings_resinfo(cr, symtab, atoms->nres, atoms->resinfo);
245     /* QMMM requires atomtypes to be known on all nodes as well */
246     bc_strings(cr, symtab, atoms->nr, &atoms->atomtype);
247     bc_strings(cr, symtab, atoms->nr, &atoms->atomtypeB);
248 }
249
250 static void bc_groups(const t_commrec *cr, t_symtab *symtab,
251                       int natoms, SimulationGroups *groups)
252 {
253     int n;
254
255     bc_grps(cr, groups->groups);
256     bc_strings_container(cr, symtab, groups->groupNames.size(), &groups->groupNames);
257     for (auto group : gmx::keysOf(groups->groups))
258     {
259         if (MASTER(cr))
260         {
261             if (!groups->groupNumbers[group].empty())
262             {
263                 n = natoms;
264             }
265             else
266             {
267                 n = 0;
268             }
269         }
270         block_bc(cr, n);
271         if (n != 0)
272         {
273             nblock_abc(cr, n, &groups->groupNumbers[group]);
274         }
275     }
276     if (debug)
277     {
278         fprintf(debug, "after bc_groups\n");
279     }
280 }
281
282 template <typename AllocatorType>
283 static void bcastPaddedRVecVector(const t_commrec *cr, gmx::PaddedVector<gmx::RVec, AllocatorType> *v, int numAtoms)
284 {
285     v->resizeWithPadding(numAtoms);
286     nblock_bc(cr, makeArrayRef(*v));
287 }
288
289 void broadcastStateWithoutDynamics(const t_commrec *cr, t_state *state)
290 {
291     GMX_RELEASE_ASSERT(!DOMAINDECOMP(cr), "broadcastStateWithoutDynamics should only be used for special cases without domain decomposition");
292
293     if (!PAR(cr))
294     {
295         return;
296     }
297
298     /* Broadcasts the state sizes and flags from the master to all ranks
299      * in cr->mpi_comm_mygroup.
300      */
301     block_bc(cr, state->natoms);
302     block_bc(cr, state->flags);
303
304     for (int i = 0; i < estNR; i++)
305     {
306         if (state->flags & (1 << i))
307         {
308             switch (i)
309             {
310                 case estLAMBDA:
311                     nblock_bc(cr, efptNR, state->lambda.data());
312                     break;
313                 case estFEPSTATE:
314                     block_bc(cr, state->fep_state);
315                     break;
316                 case estBOX:
317                     block_bc(cr, state->box);
318                     break;
319                 case estX:
320                     bcastPaddedRVecVector(cr, &state->x, state->natoms);
321                     break;
322                 default:
323                     GMX_RELEASE_ASSERT(false, "The state has a dynamic entry, while no dynamic entries should be present");
324                     break;
325             }
326         }
327     }
328 }
329
330 static void bc_ilists(const t_commrec *cr, InteractionLists *ilist)
331 {
332     int ftype;
333
334     /* Here we only communicate the non-zero length ilists */
335     if (MASTER(cr))
336     {
337         for (ftype = 0; ftype < F_NRE; ftype++)
338         {
339             if ((*ilist)[ftype].size() > 0)
340             {
341                 block_bc(cr, ftype);
342                 int nr = (*ilist)[ftype].size();
343                 block_bc(cr, nr);
344                 nblock_bc(cr, nr, (*ilist)[ftype].iatoms.data());
345             }
346         }
347         ftype = -1;
348         block_bc(cr, ftype);
349     }
350     else
351     {
352         for (ftype = 0; ftype < F_NRE; ftype++)
353         {
354             (*ilist)[ftype].iatoms.clear();
355         }
356         do
357         {
358             block_bc(cr, ftype);
359             if (ftype >= 0)
360             {
361                 int nr;
362                 block_bc(cr, nr);
363                 (*ilist)[ftype].iatoms.resize(nr);
364                 nblock_bc(cr, nr, (*ilist)[ftype].iatoms.data());
365             }
366         }
367         while (ftype >= 0);
368     }
369
370     if (debug)
371     {
372         fprintf(debug, "after bc_ilists\n");
373     }
374 }
375
376 static void bc_cmap(const t_commrec *cr, gmx_cmap_t *cmap_grid)
377 {
378     int ngrid = cmap_grid->cmapdata.size();
379     block_bc(cr, ngrid);
380     block_bc(cr, cmap_grid->grid_spacing);
381
382     int nelem = cmap_grid->grid_spacing * cmap_grid->grid_spacing;
383
384     if (ngrid > 0)
385     {
386         if (!MASTER(cr))
387         {
388             cmap_grid->cmapdata.resize(ngrid);
389         }
390
391         for (int i = 0; i < ngrid; i++)
392         {
393             nblock_abc(cr, 4*nelem, &cmap_grid->cmapdata[i].cmap);
394         }
395     }
396 }
397
398 static void bc_ffparams(const t_commrec *cr, gmx_ffparams_t *ffp)
399 {
400     int numTypes = ffp->numTypes();
401     block_bc(cr, numTypes);
402     block_bc(cr, ffp->atnr);
403     nblock_abc(cr, numTypes, &ffp->functype);
404     nblock_abc(cr, numTypes, &ffp->iparams);
405     block_bc(cr, ffp->reppow);
406     block_bc(cr, ffp->fudgeQQ);
407     bc_cmap(cr, &ffp->cmap_grid);
408 }
409
410 static void bc_grpopts(const t_commrec *cr, t_grpopts *g)
411 {
412     int i, n;
413
414     block_bc(cr, g->ngtc);
415     block_bc(cr, g->ngacc);
416     block_bc(cr, g->ngfrz);
417     block_bc(cr, g->ngener);
418     snew_bc(cr, g->nrdf, g->ngtc);
419     snew_bc(cr, g->tau_t, g->ngtc);
420     snew_bc(cr, g->ref_t, g->ngtc);
421     snew_bc(cr, g->acc, g->ngacc);
422     snew_bc(cr, g->nFreeze, g->ngfrz);
423     snew_bc(cr, g->egp_flags, g->ngener*g->ngener);
424
425     nblock_bc(cr, g->ngtc, g->nrdf);
426     nblock_bc(cr, g->ngtc, g->tau_t);
427     nblock_bc(cr, g->ngtc, g->ref_t);
428     nblock_bc(cr, g->ngacc, g->acc);
429     nblock_bc(cr, g->ngfrz, g->nFreeze);
430     nblock_bc(cr, g->ngener*g->ngener, g->egp_flags);
431     snew_bc(cr, g->annealing, g->ngtc);
432     snew_bc(cr, g->anneal_npoints, g->ngtc);
433     snew_bc(cr, g->anneal_time, g->ngtc);
434     snew_bc(cr, g->anneal_temp, g->ngtc);
435     nblock_bc(cr, g->ngtc, g->annealing);
436     nblock_bc(cr, g->ngtc, g->anneal_npoints);
437     for (i = 0; (i < g->ngtc); i++)
438     {
439         n = g->anneal_npoints[i];
440         if (n > 0)
441         {
442             snew_bc(cr, g->anneal_time[i], n);
443             snew_bc(cr, g->anneal_temp[i], n);
444             nblock_bc(cr, n, g->anneal_time[i]);
445             nblock_bc(cr, n, g->anneal_temp[i]);
446         }
447     }
448
449     /* QMMM stuff, see inputrec */
450     block_bc(cr, g->ngQM);
451     snew_bc(cr, g->QMmethod, g->ngQM);
452     snew_bc(cr, g->QMbasis, g->ngQM);
453     snew_bc(cr, g->QMcharge, g->ngQM);
454     snew_bc(cr, g->QMmult, g->ngQM);
455     snew_bc(cr, g->bSH, g->ngQM);
456     snew_bc(cr, g->CASorbitals, g->ngQM);
457     snew_bc(cr, g->CASelectrons, g->ngQM);
458     snew_bc(cr, g->SAon, g->ngQM);
459     snew_bc(cr, g->SAoff, g->ngQM);
460     snew_bc(cr, g->SAsteps, g->ngQM);
461
462     if (g->ngQM)
463     {
464         nblock_bc(cr, g->ngQM, g->QMmethod);
465         nblock_bc(cr, g->ngQM, g->QMbasis);
466         nblock_bc(cr, g->ngQM, g->QMcharge);
467         nblock_bc(cr, g->ngQM, g->QMmult);
468         nblock_bc(cr, g->ngQM, g->bSH);
469         nblock_bc(cr, g->ngQM, g->CASorbitals);
470         nblock_bc(cr, g->ngQM, g->CASelectrons);
471         nblock_bc(cr, g->ngQM, g->SAon);
472         nblock_bc(cr, g->ngQM, g->SAoff);
473         nblock_bc(cr, g->ngQM, g->SAsteps);
474         /* end of QMMM stuff */
475     }
476 }
477
478 static void bc_awhBias(const t_commrec *cr, gmx::AwhBiasParams *awhBiasParams)
479 {
480     block_bc(cr, *awhBiasParams);
481
482     snew_bc(cr, awhBiasParams->dimParams, awhBiasParams->ndim);
483     nblock_bc(cr, awhBiasParams->ndim, awhBiasParams->dimParams);
484 }
485
486 static void bc_awh(const t_commrec *cr, gmx::AwhParams *awhParams)
487 {
488     int k;
489
490     block_bc(cr, *awhParams);
491     snew_bc(cr, awhParams->awhBiasParams, awhParams->numBias);
492     for (k = 0; k < awhParams->numBias; k++)
493     {
494         bc_awhBias(cr, &awhParams->awhBiasParams[k]);
495     }
496 }
497
498 static void bc_pull_group(const t_commrec *cr, t_pull_group *pgrp)
499 {
500     block_bc(cr, *pgrp);
501     if (pgrp->nat > 0)
502     {
503         snew_bc(cr, pgrp->ind, pgrp->nat);
504         nblock_bc(cr, pgrp->nat, pgrp->ind);
505     }
506     if (pgrp->nweight > 0)
507     {
508         snew_bc(cr, pgrp->weight, pgrp->nweight);
509         nblock_bc(cr, pgrp->nweight, pgrp->weight);
510     }
511 }
512
513 static void bc_pull(const t_commrec *cr, pull_params_t *pull)
514 {
515     int g;
516
517     block_bc(cr, *pull);
518     snew_bc(cr, pull->group, pull->ngroup);
519     for (g = 0; g < pull->ngroup; g++)
520     {
521         bc_pull_group(cr, &pull->group[g]);
522     }
523     snew_bc(cr, pull->coord, pull->ncoord);
524     nblock_bc(cr, pull->ncoord, pull->coord);
525     for (int c = 0; c < pull->ncoord; c++)
526     {
527         if (!MASTER(cr))
528         {
529             pull->coord[c].externalPotentialProvider = nullptr;
530         }
531         if (pull->coord[c].eType == epullEXTERNAL)
532         {
533             bc_cstring(cr, &pull->coord[c].externalPotentialProvider);
534         }
535     }
536 }
537
538 static void bc_rotgrp(const t_commrec *cr, t_rotgrp *rotg)
539 {
540     block_bc(cr, *rotg);
541     if (rotg->nat > 0)
542     {
543         snew_bc(cr, rotg->ind, rotg->nat);
544         nblock_bc(cr, rotg->nat, rotg->ind);
545         snew_bc(cr, rotg->x_ref, rotg->nat);
546         nblock_bc(cr, rotg->nat, rotg->x_ref);
547     }
548 }
549
550 static void bc_rot(const t_commrec *cr, t_rot *rot)
551 {
552     int g;
553
554     block_bc(cr, *rot);
555     snew_bc(cr, rot->grp, rot->ngrp);
556     for (g = 0; g < rot->ngrp; g++)
557     {
558         bc_rotgrp(cr, &rot->grp[g]);
559     }
560 }
561
562 static void bc_imd(const t_commrec *cr, t_IMD *imd)
563 {
564     block_bc(cr, *imd);
565     snew_bc(cr, imd->ind, imd->nat);
566     nblock_bc(cr, imd->nat, imd->ind);
567 }
568
569 static void bc_fepvals(const t_commrec *cr, t_lambda *fep)
570 {
571     int      i;
572
573     block_bc(cr, fep->nstdhdl);
574     block_bc(cr, fep->init_lambda);
575     block_bc(cr, fep->init_fep_state);
576     block_bc(cr, fep->delta_lambda);
577     block_bc(cr, fep->edHdLPrintEnergy);
578     block_bc(cr, fep->n_lambda);
579     if (fep->n_lambda > 0)
580     {
581         snew_bc(cr, fep->all_lambda, efptNR);
582         nblock_bc(cr, efptNR, fep->all_lambda);
583         for (i = 0; i < efptNR; i++)
584         {
585             snew_bc(cr, fep->all_lambda[i], fep->n_lambda);
586             nblock_bc(cr, fep->n_lambda, fep->all_lambda[i]);
587         }
588     }
589     block_bc(cr, fep->sc_alpha);
590     block_bc(cr, fep->sc_power);
591     block_bc(cr, fep->sc_r_power);
592     block_bc(cr, fep->sc_sigma);
593     block_bc(cr, fep->sc_sigma_min);
594     block_bc(cr, fep->bScCoul);
595     nblock_bc(cr, efptNR, &(fep->separate_dvdl[0]));
596     block_bc(cr, fep->dhdl_derivatives);
597     block_bc(cr, fep->dh_hist_size);
598     block_bc(cr, fep->dh_hist_spacing);
599     if (debug)
600     {
601         fprintf(debug, "after bc_fepvals\n");
602     }
603 }
604
605 static void bc_expandedvals(const t_commrec *cr, t_expanded *expand, int n_lambda)
606 {
607     block_bc(cr, expand->nstexpanded);
608     block_bc(cr, expand->elamstats);
609     block_bc(cr, expand->elmcmove);
610     block_bc(cr, expand->elmceq);
611     block_bc(cr, expand->equil_n_at_lam);
612     block_bc(cr, expand->equil_wl_delta);
613     block_bc(cr, expand->equil_ratio);
614     block_bc(cr, expand->equil_steps);
615     block_bc(cr, expand->equil_samples);
616     block_bc(cr, expand->lmc_seed);
617     block_bc(cr, expand->minvar);
618     block_bc(cr, expand->minvar_const);
619     block_bc(cr, expand->c_range);
620     block_bc(cr, expand->bSymmetrizedTMatrix);
621     block_bc(cr, expand->nstTij);
622     block_bc(cr, expand->lmc_repeats);
623     block_bc(cr, expand->lmc_forced_nstart);
624     block_bc(cr, expand->gibbsdeltalam);
625     block_bc(cr, expand->wl_scale);
626     block_bc(cr, expand->wl_ratio);
627     block_bc(cr, expand->init_wl_delta);
628     block_bc(cr, expand->bInit_weights);
629     snew_bc(cr, expand->init_lambda_weights, n_lambda);
630     nblock_bc(cr, n_lambda, expand->init_lambda_weights);
631     block_bc(cr, expand->mc_temp);
632     if (debug)
633     {
634         fprintf(debug, "after bc_expandedvals\n");
635     }
636 }
637
638 static void bc_simtempvals(const t_commrec *cr, t_simtemp *simtemp, int n_lambda)
639 {
640     block_bc(cr, simtemp->simtemp_low);
641     block_bc(cr, simtemp->simtemp_high);
642     block_bc(cr, simtemp->eSimTempScale);
643     snew_bc(cr, simtemp->temperatures, n_lambda);
644     nblock_bc(cr, n_lambda, simtemp->temperatures);
645     if (debug)
646     {
647         fprintf(debug, "after bc_simtempvals\n");
648     }
649 }
650
651
652 static void bc_swapions(const t_commrec *cr, t_swapcoords *swap)
653 {
654     block_bc(cr, *swap);
655
656     /* Broadcast atom indices for split groups, solvent group, and for all user-defined swap groups */
657     snew_bc(cr, swap->grp, swap->ngrp);
658     for (int i = 0; i < swap->ngrp; i++)
659     {
660         t_swapGroup *g = &swap->grp[i];
661
662         block_bc(cr, *g);
663         snew_bc(cr, g->ind, g->nat);
664         nblock_bc(cr, g->nat, g->ind);
665
666         int len = 0;
667         if (MASTER(cr))
668         {
669             len = strlen(g->molname);
670         }
671         block_bc(cr, len);
672         snew_bc(cr, g->molname, len);
673         nblock_bc(cr, len, g->molname);
674     }
675 }
676
677
678 static void bc_inputrec(const t_commrec *cr, t_inputrec *inputrec)
679 {
680     // Make sure to destruct all previously set internal parameters properly
681     // before the block_bc on the inputrec overwrites them.
682     // They are expected to be null anyway, but we can't guarantee this here.
683     if (!SIMMASTER(cr))
684     {
685         // will call destructor on previously set parameters upon leaving this block
686         std::unique_ptr<gmx::KeyValueTreeObject> previouslySetInternalParametersOnNonMaster;
687         inputrec->internalParameters.swap(previouslySetInternalParametersOnNonMaster);
688     }
689     // Note that this overwrites pointers in inputrec, so all pointer fields
690     // Must be initialized separately below.
691     block_bc(cr, *inputrec);
692     if (SIMMASTER(cr))
693     {
694         gmx::InMemorySerializer serializer;
695         gmx::serializeKeyValueTree(*inputrec->params, &serializer);
696         gmx::serializeKeyValueTree(*inputrec->internalParameters, &serializer);
697         std::vector<char>       buffer = serializer.finishAndGetBuffer();
698         size_t                  size   = buffer.size();
699         block_bc(cr, size);
700         nblock_bc(cr, size, buffer.data());
701     }
702     else
703     {
704         // block_bc() of inputrec above overwrites the old pointer, so set it to a
705         // reasonable value in case code below throws.
706         inputrec->params = nullptr;
707         std::vector<char> buffer;
708         size_t            size;
709         block_bc(cr, size);
710         nblock_abc(cr, size, &buffer);
711         gmx::InMemoryDeserializer serializer(buffer, false);
712         inputrec->params = new gmx::KeyValueTreeObject(
713                     gmx::deserializeKeyValueTree(&serializer));
714         // release is required because internalParameters' destructor will fail
715         // if block_bc() of inputrec overwrites the internalParameters pointer with garbage
716         auto gmx_unused releasedGarbagePointer = inputrec->internalParameters.release();
717         inputrec->internalParameters = std::make_unique<gmx::KeyValueTreeObject>(
718                     gmx::deserializeKeyValueTree(&serializer));
719     }
720
721     bc_grpopts(cr, &(inputrec->opts));
722
723     /* even if efep is efepNO, we need to initialize to make sure that
724      * n_lambda is set to zero */
725
726     snew_bc(cr, inputrec->fepvals, 1);
727     if (inputrec->efep != efepNO || inputrec->bSimTemp)
728     {
729         bc_fepvals(cr, inputrec->fepvals);
730     }
731     /* need to initialize this as well because of data checked for in the logic */
732     snew_bc(cr, inputrec->expandedvals, 1);
733     if (inputrec->bExpanded)
734     {
735         bc_expandedvals(cr, inputrec->expandedvals, inputrec->fepvals->n_lambda);
736     }
737     snew_bc(cr, inputrec->simtempvals, 1);
738     if (inputrec->bSimTemp)
739     {
740         bc_simtempvals(cr, inputrec->simtempvals, inputrec->fepvals->n_lambda);
741     }
742     if (inputrec->bPull)
743     {
744         snew_bc(cr, inputrec->pull, 1);
745         bc_pull(cr, inputrec->pull);
746     }
747     if (inputrec->bDoAwh)
748     {
749         snew_bc(cr, inputrec->awhParams, 1);
750         bc_awh(cr, inputrec->awhParams);
751     }
752
753     if (inputrec->bRot)
754     {
755         snew_bc(cr, inputrec->rot, 1);
756         bc_rot(cr, inputrec->rot);
757     }
758     if (inputrec->bIMD)
759     {
760         snew_bc(cr, inputrec->imd, 1);
761         bc_imd(cr, inputrec->imd);
762     }
763     if (inputrec->eSwapCoords != eswapNO)
764     {
765         snew_bc(cr, inputrec->swap, 1);
766         bc_swapions(cr, inputrec->swap);
767     }
768 }
769
770 static void bc_moltype(const t_commrec *cr, t_symtab *symtab,
771                        gmx_moltype_t *moltype)
772 {
773     bc_string(cr, symtab, &moltype->name);
774     bc_atoms(cr, symtab, &moltype->atoms);
775     if (debug)
776     {
777         fprintf(debug, "after bc_atoms\n");
778     }
779
780     bc_ilists(cr, &moltype->ilist);
781     bc_block(cr, &moltype->cgs);
782     bc_blocka(cr, &moltype->excls);
783 }
784
785 static void bc_vector_of_rvec(const t_commrec *cr, std::vector<gmx::RVec> *vec)
786 {
787     int numElements = vec->size();
788     block_bc(cr, numElements);
789     if (!MASTER(cr))
790     {
791         vec->resize(numElements);
792     }
793     if (numElements > 0)
794     {
795         nblock_bc(cr, numElements, as_rvec_array(vec->data()));
796     }
797 }
798
799 static void bc_molblock(const t_commrec *cr, gmx_molblock_t *molb)
800 {
801     block_bc(cr, molb->type);
802     block_bc(cr, molb->nmol);
803     bc_vector_of_rvec(cr, &molb->posres_xA);
804     bc_vector_of_rvec(cr, &molb->posres_xB);
805     if (debug)
806     {
807         fprintf(debug, "after bc_molblock\n");
808     }
809 }
810
811 static void bc_atomtypes(const t_commrec *cr, t_atomtypes *atomtypes)
812 {
813     block_bc(cr, atomtypes->nr);
814 }
815
816 /*! \brief Broadcasts ir and mtop from the master to all nodes in
817  * cr->mpi_comm_mygroup. */
818 static
819 void bcast_ir_mtop(const t_commrec *cr, t_inputrec *inputrec, gmx_mtop_t *mtop)
820 {
821     if (debug)
822     {
823         fprintf(debug, "in bc_data\n");
824     }
825     bc_inputrec(cr, inputrec);
826     if (debug)
827     {
828         fprintf(debug, "after bc_inputrec\n");
829     }
830     bc_symtab(cr, &mtop->symtab);
831     if (debug)
832     {
833         fprintf(debug, "after bc_symtab\n");
834     }
835     bc_string(cr, &mtop->symtab, &mtop->name);
836     if (debug)
837     {
838         fprintf(debug, "after bc_name\n");
839     }
840
841     bc_ffparams(cr, &mtop->ffparams);
842
843     int nmoltype = mtop->moltype.size();
844     block_bc(cr, nmoltype);
845     mtop->moltype.resize(nmoltype);
846     for (gmx_moltype_t &moltype : mtop->moltype)
847     {
848         bc_moltype(cr, &mtop->symtab, &moltype);
849     }
850
851     block_bc(cr, mtop->bIntermolecularInteractions);
852     if (mtop->bIntermolecularInteractions)
853     {
854         if (!MASTER(cr))
855         {
856             mtop->intermolecular_ilist = std::make_unique<InteractionLists>();
857         }
858         bc_ilists(cr, mtop->intermolecular_ilist.get());
859     }
860
861     int nmolblock = mtop->molblock.size();
862     block_bc(cr, nmolblock);
863     mtop->molblock.resize(nmolblock);
864     for (gmx_molblock_t &molblock : mtop->molblock)
865     {
866         bc_molblock(cr, &molblock);
867     }
868
869     block_bc(cr, mtop->natoms);
870
871     bc_atomtypes(cr, &mtop->atomtypes);
872
873     bc_groups(cr, &mtop->symtab, mtop->natoms, &mtop->groups);
874
875     GMX_RELEASE_ASSERT(!MASTER(cr) || mtop->haveMoleculeIndices, "mtop should have valid molecule indices");
876     if (!MASTER(cr))
877     {
878         mtop->haveMoleculeIndices = true;
879
880         gmx_mtop_finalize(mtop);
881     }
882 }
883
884 void init_parallel(t_commrec *cr, t_inputrec *inputrec,
885                    gmx_mtop_t *mtop)
886 {
887     bcast_ir_mtop(cr, inputrec, mtop);
888 }