f9c8364336d56f8a0b9c6d684a47c0868cb94c8f
[alexxy/gromacs.git] / src / gromacs / domdec / domdec_constraints.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2006,2007,2008,2009,2010,2012,2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35
36 /*! \internal \file
37  *
38  * \brief This file implements functions for domdec to use
39  * while managing inter-atomic constraints.
40  *
41  * \author Berk Hess <hess@kth.se>
42  * \ingroup module_domdec
43  */
44
45 #include "gmxpre.h"
46
47 #include "domdec_constraints.h"
48
49 #include <cassert>
50
51 #include <algorithm>
52
53 #include "gromacs/compat/make_unique.h"
54 #include "gromacs/domdec/dlbtiming.h"
55 #include "gromacs/domdec/domdec.h"
56 #include "gromacs/domdec/domdec_struct.h"
57 #include "gromacs/domdec/ga2la.h"
58 #include "gromacs/domdec/hashedmap.h"
59 #include "gromacs/math/vec.h"
60 #include "gromacs/mdlib/constr.h"
61 #include "gromacs/mdlib/gmx_omp_nthreads.h"
62 #include "gromacs/mdtypes/commrec.h"
63 #include "gromacs/mdtypes/forcerec.h" // only for GET_CGINFO_*
64 #include "gromacs/pbcutil/ishift.h"
65 #include "gromacs/topology/ifunc.h"
66 #include "gromacs/topology/mtop_lookup.h"
67 #include "gromacs/utility/exceptions.h"
68 #include "gromacs/utility/fatalerror.h"
69 #include "gromacs/utility/gmxassert.h"
70 #include "gromacs/utility/smalloc.h"
71
72 #include "domdec_specatomcomm.h"
73
74 /*! \brief Struct used during constraint setup with domain decomposition */
75 struct gmx_domdec_constraints_t
76 {
77     //! @cond Doxygen_Suppress
78     std::vector<int>  molb_con_offset; /**< Offset in the constraint array for each molblock */
79     std::vector<int>  molb_ncon_mol;   /**< The number of constraints per molecule for each molblock */
80
81     int               ncon;            /**< The fully local and conneced constraints */
82     /* The global constraint number, only required for clearing gc_req */
83     std::vector<int>  con_gl;          /**< Global constraint indices for local constraints */
84     std::vector<int>  con_nlocat;      /**< Number of local atoms (2/1/0) for each constraint */
85
86     std::vector<bool> gc_req;          /**< Boolean that tells if a global constraint index has been requested; note: size global #constraints */
87
88     /* Hash table for keeping track of requests */
89     std::unique_ptr < gmx::HashedMap < int>> ga2la; /**< Global to local communicated constraint atom only index */
90
91     /* Multi-threading stuff */
92     int                  nthread; /**< Number of threads used for DD constraint setup */
93     std::vector<t_ilist> ils;     /**< Constraint ilist working arrays, size \p nthread */
94
95     /* Buffers for requesting atoms */
96     std::vector < std::vector < int>> requestedGlobalAtomIndices; /**< Buffers for requesting global atom indices, one per thread */
97
98     //! @endcond
99 };
100
101 void dd_move_x_constraints(gmx_domdec_t *dd, matrix box,
102                            rvec *x0, rvec *x1, gmx_bool bX1IsCoord)
103 {
104     if (dd->constraint_comm)
105     {
106         dd_move_x_specat(dd, dd->constraint_comm, box, x0, x1, bX1IsCoord);
107
108         ddReopenBalanceRegionCpu(dd);
109     }
110 }
111
112 gmx::ArrayRef<const int> dd_constraints_nlocalatoms(const gmx_domdec_t *dd)
113 {
114     if (dd && dd->constraints)
115     {
116         return dd->constraints->con_nlocat;
117     }
118     else
119     {
120         return gmx::EmptyArrayRef();
121     }
122 }
123
124 void dd_clear_local_constraint_indices(gmx_domdec_t *dd)
125 {
126     gmx_domdec_constraints_t *dc = dd->constraints;
127
128     std::fill(dc->gc_req.begin(), dc->gc_req.end(), false);
129
130     if (dd->constraint_comm)
131     {
132         dc->ga2la->clear();
133     }
134 }
135
136 /*! \brief Walks over the constraints out from the local atoms into the non-local atoms and adds them to a list */
137 static void walk_out(int con, int con_offset, int a, int offset, int nrec,
138                      gmx::ArrayRef<const int> ia1,
139                      gmx::ArrayRef<const int> ia2,
140                      const t_blocka *at2con,
141                      const gmx_ga2la_t &ga2la, gmx_bool bHomeConnect,
142                      gmx_domdec_constraints_t *dc,
143                      gmx_domdec_specat_comm_t *dcc,
144                      t_ilist *il_local,
145                      std::vector<int> *ireq)
146 {
147     int            a1_gl, a2_gl, i, coni, b;
148     const t_iatom *iap;
149
150     if (!dc->gc_req[con_offset + con])
151     {
152         /* Add this non-home constraint to the list */
153         dc->con_gl.push_back(con_offset + con);
154         dc->con_nlocat.push_back(bHomeConnect ? 1 : 0);
155         dc->gc_req[con_offset + con] = true;
156         if (il_local->nr + 3 > il_local->nalloc)
157         {
158             il_local->nalloc = over_alloc_dd(il_local->nr+3);
159             srenew(il_local->iatoms, il_local->nalloc);
160         }
161         iap = constr_iatomptr(ia1, ia2, con);
162         il_local->iatoms[il_local->nr++] = iap[0];
163         a1_gl = offset + iap[1];
164         a2_gl = offset + iap[2];
165         /* The following indexing code can probably be optizimed */
166         if (const int *a_loc = ga2la.findHome(a1_gl))
167         {
168             il_local->iatoms[il_local->nr++] = *a_loc;
169         }
170         else
171         {
172             /* We set this index later */
173             il_local->iatoms[il_local->nr++] = -a1_gl - 1;
174         }
175         if (const int *a_loc = ga2la.findHome(a2_gl))
176         {
177             il_local->iatoms[il_local->nr++] = *a_loc;
178         }
179         else
180         {
181             /* We set this index later */
182             il_local->iatoms[il_local->nr++] = -a2_gl - 1;
183         }
184         dc->ncon++;
185     }
186     /* Check to not ask for the same atom more than once */
187     if (!dc->ga2la->find(offset + a))
188     {
189         assert(dcc);
190         /* Add this non-home atom to the list */
191         ireq->push_back(offset + a);
192         /* Temporarily mark with -2, we get the index later */
193         dc->ga2la->insert(offset + a, -2);
194     }
195
196     if (nrec > 0)
197     {
198         for (i = at2con->index[a]; i < at2con->index[a+1]; i++)
199         {
200             coni = at2con->a[i];
201             if (coni != con)
202             {
203                 /* Walk further */
204                 iap = constr_iatomptr(ia1, ia2, coni);
205                 if (a == iap[1])
206                 {
207                     b = iap[2];
208                 }
209                 else
210                 {
211                     b = iap[1];
212                 }
213                 if (!ga2la.findHome(offset + b))
214                 {
215                     walk_out(coni, con_offset, b, offset, nrec-1,
216                              ia1, ia2, at2con,
217                              ga2la, FALSE, dc, dcc, il_local, ireq);
218                 }
219             }
220         }
221     }
222 }
223
224 /*! \brief Looks up SETTLE constraints for a range of charge-groups */
225 static void atoms_to_settles(gmx_domdec_t *dd,
226                              const gmx_mtop_t *mtop,
227                              const int *cginfo,
228                              gmx::ArrayRef < const std::vector < int>> at2settle_mt,
229                              int cg_start, int cg_end,
230                              t_ilist *ils_local,
231                              std::vector<int> *ireq)
232 {
233     const gmx_ga2la_t &ga2la = *dd->ga2la;
234     int                nral  = NRAL(F_SETTLE);
235
236     int                mb    = 0;
237     for (int cg = cg_start; cg < cg_end; cg++)
238     {
239         if (GET_CGINFO_SETTLE(cginfo[cg]))
240         {
241             for (int a : dd->atomGrouping().block(cg))
242             {
243                 int a_gl = dd->globalAtomIndices[a];
244                 int a_mol;
245                 mtopGetMolblockIndex(mtop, a_gl, &mb, nullptr, &a_mol);
246
247                 const gmx_molblock_t *molb   = &mtop->molblock[mb];
248                 int                   settle = at2settle_mt[molb->type][a_mol];
249
250                 if (settle >= 0)
251                 {
252                     int        offset  = a_gl - a_mol;
253
254                     const int *ia1     = mtop->moltype[molb->type].ilist[F_SETTLE].iatoms.data();
255
256                     int        a_gls[3];
257                     gmx_bool   bAssign = FALSE;
258                     int        nlocal  = 0;
259                     for (int sa = 0; sa < nral; sa++)
260                     {
261                         int a_glsa = offset + ia1[settle*(1+nral)+1+sa];
262                         a_gls[sa]  = a_glsa;
263                         if (ga2la.findHome(a_glsa))
264                         {
265
266                             if (nlocal == 0 && a_gl == a_glsa)
267                             {
268                                 bAssign = TRUE;
269                             }
270                             nlocal++;
271                         }
272                     }
273
274                     if (bAssign)
275                     {
276                         if (ils_local->nr+1+nral > ils_local->nalloc)
277                         {
278                             ils_local->nalloc = over_alloc_dd(ils_local->nr+1+nral);
279                             srenew(ils_local->iatoms, ils_local->nalloc);
280                         }
281
282                         ils_local->iatoms[ils_local->nr++] = ia1[settle*4];
283
284                         for (int sa = 0; sa < nral; sa++)
285                         {
286                             if (const int *a_loc = ga2la.findHome(a_gls[sa]))
287                             {
288                                 ils_local->iatoms[ils_local->nr++] = *a_loc;
289                             }
290                             else
291                             {
292                                 ils_local->iatoms[ils_local->nr++] = -a_gls[sa] - 1;
293                                 /* Add this non-home atom to the list */
294                                 ireq->push_back(a_gls[sa]);
295                                 /* A check on double atom requests is
296                                  * not required for settle.
297                                  */
298                             }
299                         }
300                     }
301                 }
302             }
303         }
304     }
305 }
306
307 /*! \brief Looks up constraint for the local atoms */
308 static void atoms_to_constraints(gmx_domdec_t *dd,
309                                  const gmx_mtop_t *mtop,
310                                  const int *cginfo,
311                                  gmx::ArrayRef<const t_blocka> at2con_mt, int nrec,
312                                  t_ilist *ilc_local,
313                                  std::vector<int> *ireq)
314 {
315     const t_blocka             *at2con;
316     int                         b_lo, offset, b_mol, i, con, con_offset;
317
318     gmx_domdec_constraints_t   *dc     = dd->constraints;
319     gmx_domdec_specat_comm_t   *dcc    = dd->constraint_comm;
320
321     const gmx_ga2la_t          &ga2la  = *dd->ga2la;
322
323     dc->con_gl.clear();
324     dc->con_nlocat.clear();
325
326     int mb    = 0;
327     int nhome = 0;
328     for (int cg = 0; cg < dd->ncg_home; cg++)
329     {
330         if (GET_CGINFO_CONSTR(cginfo[cg]))
331         {
332             for (int a : dd->atomGrouping().block(cg))
333             {
334                 int a_gl = dd->globalAtomIndices[a];
335                 int molnr, a_mol;
336                 mtopGetMolblockIndex(mtop, a_gl, &mb, &molnr, &a_mol);
337
338                 const gmx_molblock_t     &molb = mtop->molblock[mb];
339
340                 gmx::ArrayRef<const int>  ia1 = mtop->moltype[molb.type].ilist[F_CONSTR].iatoms;
341                 gmx::ArrayRef<const int>  ia2 = mtop->moltype[molb.type].ilist[F_CONSTRNC].iatoms;
342
343                 /* Calculate the global constraint number offset for the molecule.
344                  * This is only required for the global index to make sure
345                  * that we use each constraint only once.
346                  */
347                 con_offset =
348                     dc->molb_con_offset[mb] + molnr*dc->molb_ncon_mol[mb];
349
350                 /* The global atom number offset for this molecule */
351                 offset = a_gl - a_mol;
352                 at2con = &at2con_mt[molb.type];
353                 for (i = at2con->index[a_mol]; i < at2con->index[a_mol+1]; i++)
354                 {
355                     con            = at2con->a[i];
356                     const int *iap = constr_iatomptr(ia1, ia2, con);
357                     if (a_mol == iap[1])
358                     {
359                         b_mol = iap[2];
360                     }
361                     else
362                     {
363                         b_mol = iap[1];
364                     }
365                     if (const int *a_loc = ga2la.findHome(offset + b_mol))
366                     {
367                         /* Add this fully home constraint at the first atom */
368                         if (a_mol < b_mol)
369                         {
370                             dc->con_gl.push_back(con_offset + con);
371                             dc->con_nlocat.push_back(2);
372                             if (ilc_local->nr + 3 > ilc_local->nalloc)
373                             {
374                                 ilc_local->nalloc = over_alloc_dd(ilc_local->nr + 3);
375                                 srenew(ilc_local->iatoms, ilc_local->nalloc);
376                             }
377                             b_lo = *a_loc;
378                             ilc_local->iatoms[ilc_local->nr++] = iap[0];
379                             ilc_local->iatoms[ilc_local->nr++] = (a_gl == iap[1] ? a    : b_lo);
380                             ilc_local->iatoms[ilc_local->nr++] = (a_gl == iap[1] ? b_lo : a   );
381                             dc->ncon++;
382                             nhome++;
383                         }
384                     }
385                     else
386                     {
387                         /* We need the nrec constraints coupled to this constraint,
388                          * so we need to walk out of the home cell by nrec+1 atoms,
389                          * since already atom bg is not locally present.
390                          * Therefore we call walk_out with nrec recursions to go
391                          * after this first call.
392                          */
393                         walk_out(con, con_offset, b_mol, offset, nrec,
394                                  ia1, ia2, at2con,
395                                  ga2la, TRUE, dc, dcc, ilc_local, ireq);
396                     }
397                 }
398             }
399         }
400     }
401
402     GMX_ASSERT(dc->con_gl.size() == static_cast<size_t>(dc->ncon), "con_gl size should match the number of constraints");
403     GMX_ASSERT(dc->con_nlocat.size() == static_cast<size_t>(dc->ncon), "con_nlocat size should match the number of constraints");
404
405     if (debug)
406     {
407         fprintf(debug,
408                 "Constraints: home %3d border %3d atoms: %3zu\n",
409                 nhome, dc->ncon-nhome,
410                 dd->constraint_comm ? ireq->size() : 0);
411     }
412 }
413
414 int dd_make_local_constraints(gmx_domdec_t *dd, int at_start,
415                               const struct gmx_mtop_t *mtop,
416                               const int *cginfo,
417                               gmx::Constraints *constr, int nrec,
418                               t_ilist *il_local)
419 {
420     gmx_domdec_constraints_t     *dc;
421     t_ilist                      *ilc_local, *ils_local;
422     std::vector<int>             *ireq;
423     gmx::ArrayRef<const t_blocka> at2con_mt;
424     gmx::HashedMap<int>          *ga2la_specat;
425     int at_end, i, j;
426     t_iatom                      *iap;
427
428     // This code should not be called unless this condition is true,
429     // because that's the only time init_domdec_constraints is
430     // called...
431     GMX_RELEASE_ASSERT(dd->splitConstraints || dd->splitSettles, "dd_make_local_constraints called when there are no local constraints");
432     // ... and init_domdec_constraints always sets
433     // dd->constraint_comm...
434     GMX_RELEASE_ASSERT(dd->constraint_comm, "Invalid use of dd_make_local_constraints before construction of constraint_comm");
435     // ... which static analysis needs to be reassured about, because
436     // otherwise, when dd->splitSettles is
437     // true. dd->constraint_comm is unilaterally dereferenced before
438     // the call to atoms_to_settles.
439
440     dc = dd->constraints;
441
442     ilc_local = &il_local[F_CONSTR];
443     ils_local = &il_local[F_SETTLE];
444
445     dc->ncon      = 0;
446     ilc_local->nr = 0;
447     if (dd->constraint_comm)
448     {
449         // TODO Perhaps gmx_domdec_constraints_t should keep a valid constr?
450         GMX_RELEASE_ASSERT(constr != nullptr, "Must have valid constraints object");
451         at2con_mt = constr->atom2constraints_moltype();
452         ireq      = &dc->requestedGlobalAtomIndices[0];
453         ireq->clear();
454     }
455     else
456     {
457         // Currently unreachable
458         at2con_mt = gmx::EmptyArrayRef();
459         ireq      = nullptr;
460     }
461
462     gmx::ArrayRef < const std::vector < int>> at2settle_mt;
463     /* When settle works inside charge groups, we assigned them already */
464     if (dd->splitSettles)
465     {
466         // TODO Perhaps gmx_domdec_constraints_t should keep a valid constr?
467         GMX_RELEASE_ASSERT(constr != nullptr, "Must have valid constraints object");
468         at2settle_mt  = constr->atom2settle_moltype();
469         ils_local->nr = 0;
470     }
471
472     if (at2settle_mt.empty())
473     {
474         atoms_to_constraints(dd, mtop, cginfo, at2con_mt, nrec,
475                              ilc_local, ireq);
476     }
477     else
478     {
479         int t0_set;
480         int thread;
481
482         /* Do the constraints, if present, on the first thread.
483          * Do the settles on all other threads.
484          */
485         t0_set = ((!at2con_mt.empty() && dc->nthread > 1) ? 1 : 0);
486
487 #pragma omp parallel for num_threads(dc->nthread) schedule(static)
488         for (thread = 0; thread < dc->nthread; thread++)
489         {
490             try
491             {
492                 if (!at2con_mt.empty() && thread == 0)
493                 {
494                     atoms_to_constraints(dd, mtop, cginfo, at2con_mt, nrec,
495                                          ilc_local, ireq);
496                 }
497
498                 if (thread >= t0_set)
499                 {
500                     int        cg0, cg1;
501                     t_ilist   *ilst;
502
503                     /* Distribute the settle check+assignments over
504                      * dc->nthread or dc->nthread-1 threads.
505                      */
506                     cg0 = (dd->ncg_home*(thread-t0_set  ))/(dc->nthread-t0_set);
507                     cg1 = (dd->ncg_home*(thread-t0_set+1))/(dc->nthread-t0_set);
508
509                     if (thread == t0_set)
510                     {
511                         ilst = ils_local;
512                     }
513                     else
514                     {
515                         ilst = &dc->ils[thread];
516                     }
517                     ilst->nr = 0;
518
519                     std::vector<int> &ireqt = dc->requestedGlobalAtomIndices[thread];
520                     if (thread > 0)
521                     {
522                         ireqt.clear();
523                     }
524
525                     atoms_to_settles(dd, mtop, cginfo, at2settle_mt,
526                                      cg0, cg1,
527                                      ilst, &ireqt);
528                 }
529             }
530             GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
531         }
532
533         /* Combine the generate settles and requested indices */
534         for (thread = 1; thread < dc->nthread; thread++)
535         {
536             t_ilist   *ilst;
537             int        ia;
538
539             if (thread > t0_set)
540             {
541                 ilst = &dc->ils[thread];
542                 if (ils_local->nr + ilst->nr > ils_local->nalloc)
543                 {
544                     ils_local->nalloc = over_alloc_large(ils_local->nr + ilst->nr);
545                     srenew(ils_local->iatoms, ils_local->nalloc);
546                 }
547                 for (ia = 0; ia < ilst->nr; ia++)
548                 {
549                     ils_local->iatoms[ils_local->nr+ia] = ilst->iatoms[ia];
550                 }
551                 ils_local->nr += ilst->nr;
552             }
553
554             const std::vector<int> &ireqt = dc->requestedGlobalAtomIndices[thread];
555             ireq->insert(ireq->end(), ireqt.begin(), ireqt.end());
556         }
557
558         if (debug)
559         {
560             fprintf(debug, "Settles: total %3d\n", ils_local->nr/4);
561         }
562     }
563
564     if (dd->constraint_comm)
565     {
566         int nral1;
567
568         at_end =
569             setup_specat_communication(dd, ireq, dd->constraint_comm,
570                                        dd->constraints->ga2la.get(),
571                                        at_start, 2,
572                                        "constraint", " or lincs-order");
573
574         /* Fill in the missing indices */
575         ga2la_specat = dd->constraints->ga2la.get();
576
577         nral1 = 1 + NRAL(F_CONSTR);
578         for (i = 0; i < ilc_local->nr; i += nral1)
579         {
580             iap = ilc_local->iatoms + i;
581             for (j = 1; j < nral1; j++)
582             {
583                 if (iap[j] < 0)
584                 {
585                     const int *a = ga2la_specat->find(-iap[j] - 1);
586                     GMX_ASSERT(a, "We have checked before that this atom index has been set");
587                     iap[j] = *a;
588                 }
589             }
590         }
591
592         nral1 = 1 + NRAL(F_SETTLE);
593         for (i = 0; i < ils_local->nr; i += nral1)
594         {
595             iap = ils_local->iatoms + i;
596             for (j = 1; j < nral1; j++)
597             {
598                 if (iap[j] < 0)
599                 {
600                     const int *a = ga2la_specat->find(-iap[j] - 1);
601                     GMX_ASSERT(a, "We have checked before that this atom index has been set");
602                     iap[j] = *a;
603                 }
604             }
605         }
606     }
607     else
608     {
609         // Currently unreachable
610         at_end = at_start;
611     }
612
613     return at_end;
614 }
615
616 void init_domdec_constraints(gmx_domdec_t     *dd,
617                              const gmx_mtop_t *mtop)
618 {
619     gmx_domdec_constraints_t *dc;
620     const gmx_molblock_t     *molb;
621
622     if (debug)
623     {
624         fprintf(debug, "Begin init_domdec_constraints\n");
625     }
626
627     dd->constraints = new gmx_domdec_constraints_t;
628     dc              = dd->constraints;
629
630     dc->molb_con_offset.resize(mtop->molblock.size());
631     dc->molb_ncon_mol.resize(mtop->molblock.size());
632
633     int ncon = 0;
634     for (size_t mb = 0; mb < mtop->molblock.size(); mb++)
635     {
636         molb                    = &mtop->molblock[mb];
637         dc->molb_con_offset[mb] = ncon;
638         dc->molb_ncon_mol[mb]   =
639             mtop->moltype[molb->type].ilist[F_CONSTR].size()/3 +
640             mtop->moltype[molb->type].ilist[F_CONSTRNC].size()/3;
641         ncon += molb->nmol*dc->molb_ncon_mol[mb];
642     }
643
644     if (ncon > 0)
645     {
646         dc->gc_req.resize(ncon);
647     }
648
649     /* Use a hash table for the global to local index.
650      * The number of keys is a rough estimate, it will be optimized later.
651      */
652     int numKeysEstimate = std::min(mtop->natoms/20,
653                                    mtop->natoms/(2*dd->nnodes));
654     dc->ga2la = gmx::compat::make_unique < gmx::HashedMap < int>>(numKeysEstimate);
655
656     dc->nthread = gmx_omp_nthreads_get(emntDomdec);
657     dc->ils.resize(dc->nthread);
658
659     dd->constraint_comm = new gmx_domdec_specat_comm_t;
660
661     dc->requestedGlobalAtomIndices.resize(dc->nthread);
662 }