Merge branch release-4-6
[alexxy/gromacs.git] / src / gromacs / swap / swapcoords.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2013,2014, 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 /*! \internal \file
36  * \brief
37  * Implements functions in swapcoords.h.
38  *
39  * \author Carsten Kutzner <ckutzne@gwdg.de>
40  * \ingroup module_swap
41  */
42 #ifdef HAVE_CONFIG_H
43 #include <config.h>
44 #endif
45
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <time.h>
50 #include "typedefs.h"
51 #include "string2.h"
52 #include "smalloc.h"
53 #include "gromacs/mdlib/groupcoord.h"
54 #include "mtop_util.h"
55 #include "macros.h"
56 #include "vec.h"
57 #include "names.h"
58 #include "network.h"
59 #include "mdrun.h"
60 #include "xvgr.h"
61 #include "copyrite.h"
62 #include "gromacs/fileio/confio.h"
63 #include "gromacs/timing/wallcycle.h"
64 #include "swapcoords.h"
65
66 static char *SwS      = {"SWAP:"};                                           /**< For output that comes from the swap module */
67 static char *SwSEmpty = {"     "};                                           /**< Placeholder for multi-line output */
68 static char* IonString[eIonNR] = {"anion", "cation" };                       /**< Type of ion, used for verbose output */
69 static char* IonStr[eIonNR]    = {"-", "+"      };                           /**< Type of ion, used for short output */
70 static char* CompStr[eCompNR] = {"A", "B" };                                 /**< Compartment name */
71 static char *SwapStr[eSwapTypesNR+1] = { "", "X-", "Y-", "Z-", NULL};        /**< Name for the swap types. */
72 static char *DimStr[DIM+1] = { "X", "Y", "Z", NULL};                         /**< Name for the swap dimension. */
73
74 /* eGrpSplit0 and eGrpSplit1 _must_ be neighbors in this list because
75  * we sometimes loop from eGrpSplit0 to eGrpSplit1 */
76 enum {
77     eGrpIons, eGrpSplit0, eGrpSplit1, eGrpSolvent, eGrpNr
78 };                                                                           /**< Group identifier */
79 static char* GrpString[eGrpNr] = { "ion", "split0", "split1", "solvent" };   /**< Group name */
80
81 /** Keep track of through which channel the ions have passed */
82 enum eChannelHistory {
83     eChHistPassedNone, eChHistPassedCh0, eChHistPassedCh1, eChHistNr
84 };
85 static char* ChannelString[eChHistNr] = { "none", "channel0", "channel1" };  /**< Name for the channels */
86
87 /*! \brief Domain identifier.
88  *
89  * Keeps track of from which compartment the ions came before passing the
90  * channel.
91  */
92 enum eDomain {
93     eDomainNotset, eDomainA, eDomainB, eDomainNr
94 };
95 static char* DomainString[eDomainNr] = { "not_assigned", "Domain_A", "Domain_B" }; /**< Name for the domains */
96
97
98
99 /*! \internal \brief
100  * Structure containing compartment-specific data
101  */
102 typedef struct swap_compartment
103 {
104     int                nat;                   /**< Number of atoms matching the
105                                                  compartment conditions.                         */
106     int                nat_old;               /**< Number of atoms before swapping.              */
107     int                nat_req;               /**< Requested number of atoms.                    */
108     real               nat_av;                /**< Time-averaged number of atoms matching
109                                                    the compartment conditions.                   */
110     int               *nat_past;              /**< Past ion counts for time-averaging.           */
111     int               *ind;                   /**< Indices to coll array of atoms.               */
112     real              *dist;                  /**< Distance of atom to compartment center.       */
113     int                nalloc;                /**< Allocation size for ind array.                */
114     int                inflow_netto;          /**< Net inflow of ions into this compartment.     */
115 } t_compartment;
116
117
118 /*! \internal \brief
119  * This structure contains data needed for each of the groups involved in swapping: ions, water,
120  * and channels
121  */
122 typedef struct swap_group
123 {
124     int               nat;                    /**< Number of atoms in the group                    */
125     int               apm;                    /**< Number of atoms in each molecule                */
126     atom_id          *ind;                    /**< Global atom indices of the group                */
127     atom_id          *ind_loc;                /**< Local atom indices of the group                 */
128     int               nat_loc;                /**< Number of local group atoms                     */
129     int               nalloc_loc;             /**< Allocation size for ind_loc                     */
130     rvec             *xc;                     /**< Collective array of group atom positions        */
131     ivec             *xc_shifts;              /**< Current (collective) shifts                     */
132     ivec             *xc_eshifts;             /**< Extra shifts since last DD step                 */
133     rvec             *xc_old;                 /**< Old (collective) positions                      */
134     real             *qc;                     /**< Collective array of charges                     */
135     int              *c_ind_loc;              /**< Position of local atoms in the
136                                                    collective array, [0..nat_loc]                  */
137     real             *m;                      /**< Masses (can be omitted)                         */
138     unsigned char    *comp_from;              /**< (Collective) Stores from which compartment this
139                                                    atom has come. This way we keep track of through
140                                                    which channel an ion permeates (only used for
141                                                    the ion group)                                  */
142     unsigned char    *comp_now;               /**< In which compartment this ion is now            */
143     unsigned char    *channel_label;          /**< Which channel was passed at last by this ion?   */
144     rvec              center;                 /**< Center of the group; COM if masses are used     */
145 } t_group;
146
147
148 /*! \internal \brief
149  * Main (private) data structure for the position swapping protocol.
150  */
151 typedef struct swap
152 {
153     int               swapdim;                       /**< One of XX, YY, ZZ                               */
154     t_pbc            *pbc;                           /**< Needed to make molecules whole.                 */
155     FILE             *fpout;                         /**< Output file.                                    */
156     t_group           group[eGrpNr];                 /**< Ions, solvent or channels?                      */
157     t_compartment     comp[eCompNR][eIonNR];         /**< Data for a specific compartment and ion type.   */
158     t_compartment     compsol[eCompNR];              /**< Solvent compartments.                           */
159     int               fluxfromAtoB[eChanNR][eIonNR]; /**< Net flux per channels and ion type.             */
160     int               ncyl0ions;                     /**< Number of ions residing in channel 0.           */
161     int               ncyl1ions;                     /**< Same for channel 1.                             */
162     int               cyl0and1;                      /**< Ions assigned to cyl0 and cyl1. Not good.       */
163     int              *fluxleak;                      /**< Pointer to a single int value holding the
164                                                           flux not going through any of the channels.     */
165     real              deltaQ;                        /**< The charge imbalance between the compartments.  */
166 } t_swap;
167
168
169
170 /*! Check whether point is in channel. Channel is a cylinder defined by a disc
171  * with radius r around its center c. The thickness of the cylinder is
172  * d_up - d_down.
173  *
174  * \code
175  *               ^  d_up
176  *               |
177  *     r         |
178  *     <---------c--------->
179  *               |
180  *               v  d_down
181  *
182  * \endcode
183  */
184 static gmx_bool is_in_channel(
185         rvec   point,  /* Point under consideration */
186         rvec   center, /* 'Center' of cylinder */
187         real   d_up,   /* Upper extension */
188         real   d_down, /* Lower extensions */
189         real   r_cyl2, /* Cylinder radius squared */
190         t_pbc *pbc,
191         int    normal) /* The membrane normal direction is typically 3, i.e. ZZ, but can be X or Y also */
192 {
193     rvec dr;
194     int  plane1, plane2; /* Directions tangential to membrane */
195
196
197     plane1 = (normal + 1) % 3; /* typically 0, i.e. XX */
198     plane2 = (normal + 2) % 3; /* typically 1, i.e. YY */
199
200     /* Get the distance vector dr between the point and the center of the cylinder */
201     pbc_dx(pbc, point, center, dr); /* This puts center in the origin */
202
203     /* Check vertical direction */
204     if ( (dr[normal] > d_up) || (dr[normal] < -d_down) )
205     {
206         return FALSE;
207     }
208
209     /* Check radial direction */
210     if ( (dr[plane1]*dr[plane1] + dr[plane2]*dr[plane2]) > r_cyl2)
211     {
212         return FALSE;
213     }
214
215     /* All check passed, this point is in the cylinder */
216     return TRUE;
217 }
218
219
220 /*! Prints to swap output file which ions are in which compartments. */
221 static void print_ionlist(
222         t_swap *s,
223         double  time,
224         char    comment[])
225 {
226     int            itype, icomp, i, j;
227     t_compartment *comp;
228
229
230     fprintf(s->fpout, "%12.5e", time);
231     for (icomp = 0; icomp < eCompNR; icomp++)
232     {
233         for (itype = 0; itype < eIonNR; itype++)
234         {
235             comp = &(s->comp[icomp][itype]);
236             fprintf(s->fpout, "%7d%7.1f%7d", comp->nat, comp->nat_av-comp->nat_req, comp->inflow_netto);
237         }
238     }
239     fprintf(s->fpout, "%12.3e%12.3e",
240             s->group[eGrpSplit0].center[s->swapdim],
241             s->group[eGrpSplit1].center[s->swapdim]);
242
243     for (i = 0; i < eChanNR; i++)
244     {
245         for (j = 0; j < eIonNR; j++)
246         {
247             fprintf(s->fpout, "%12d", s->fluxfromAtoB[i][j]);
248         }
249     }
250
251     /* Also print the number of ions that leaked from A to B: */
252     fprintf(s->fpout, "%12d", *s->fluxleak);
253
254     fprintf(s->fpout, "%s\n", comment);
255 }
256
257
258 /*! Get the center of a group of nat atoms. Since with PBC an atom group might
259  * not be whole, Use the first atom as the reference atom and determine the
260  * center with respect to this reference. */
261 static void get_molecule_center(
262         rvec   x[],
263         int    nat,
264         real  *weights,
265         rvec   center,
266         t_pbc *pbc)
267 {
268     int  i;
269     rvec weightedPBCimage;
270     real wi, wsum;
271     rvec reference, correctPBCimage, dx;
272
273
274     /* Use the first atom as the reference and put other atoms near that one */
275     /* This does not work for large molecules that span > half of the box! */
276     copy_rvec(x[0], reference);
277
278     /* Calculate either the weighted center or simply the center of geometry */
279     wsum = 0.0;
280     clear_rvec(center);
281     for (i = 0; i < nat; i++)
282     {
283         /* PBC distance between position and reference */
284         pbc_dx(pbc, x[i], reference, dx);
285
286         /* Add PBC distance to reference */
287         rvec_add(reference, dx, correctPBCimage);
288
289         /* Take weight into account */
290         if (NULL == weights)
291         {
292             wi = 1.0;
293         }
294         else
295         {
296             wi = weights[i];
297         }
298         wsum += wi;
299         svmul(wi, correctPBCimage, weightedPBCimage);
300
301         /* Add to center */
302         rvec_inc(center, weightedPBCimage);
303     }
304
305     /* Normalize */
306     svmul(1.0/wsum, center, center);
307 }
308
309
310
311 /*! Returns TRUE if x is between (w1+gap) and (w2-gap)
312  *
313  * \code
314  *
315  * ||-----------|--+--|----------o----------|--+--|---------------------||
316  *                w1   ?????????????????????  w2
317  *
318  * \endcode
319  */
320 static gmx_bool compartment_contains_atom(
321         real  w1, /* position of wall atom 1 */
322         real  w2, /* position of wall atom 2 */
323         real  gap,
324         real  x,
325         real  l,  /* length of the box, from || to || in the sketch */
326         real *distance_from_center)
327 {
328     real m, l_2;
329
330
331     /* First set the origin in the middle of w1 and w2 */
332     m   = 0.5 * (w1 + w2);
333     w1 -= m;
334     w2 -= m;
335     x  -= m;
336
337     /* Now choose the PBC image of x that is closest to the origin: */
338     l_2 = 0.5*l;
339     while (x  > l_2)
340     {
341         x -= l;
342     }
343     while (x <= -l_2)
344     {
345         x += l;
346     }
347
348     *distance_from_center = (real)fabs(x);
349
350     /* Return TRUE if we now are in area "????" */
351     if ( (x >= (w1+gap)) &&  (x < (w2-gap)) )
352     {
353         return TRUE;
354     }
355     else
356     {
357         return FALSE;
358     }
359 }
360
361
362 /*! Updates the time-averaged number of ions in a compartment. */
363 static void update_time_window(t_compartment *comp, int values, int replace)
364 {
365     real average;
366     int  i;
367
368
369     /* Put in the new value */
370     if (replace >= 0)
371     {
372         comp->nat_past[replace] = comp->nat;
373     }
374
375     /* Compute the new time-average */
376     average = 0.0;
377     for (i = 0; i < values; i++)
378     {
379         average += comp->nat_past[i];
380     }
381     average     /= values;
382     comp->nat_av = average;
383 }
384
385
386 /*! Add atom with collective index ci to the list 'comp' */
387 static void add_to_list(
388         int            ci,       /* index of this ion in the collective array xc, qc */
389         t_compartment *comp,     /* Compartment to add this atom to */
390         real           distance) /* Shortest distance of this atom to the compartment center */
391 {
392     int nr;
393
394
395     nr = comp->nat;
396
397     if (nr >= comp->nalloc)
398     {
399         comp->nalloc = over_alloc_dd(nr+1);
400         srenew(comp->ind, comp->nalloc);
401         srenew(comp->dist, comp->nalloc);
402     }
403     comp->ind[nr]  = ci;
404     comp->dist[nr] = distance;
405     comp->nat++;
406 }
407
408
409 /*! Determine the compartment boundaries from the channel centers. */
410 static void get_compartment_boundaries(
411         int c,
412         t_swap *s,
413         matrix box,
414         real *left, real *right)
415 {
416     real pos0, pos1;
417     real leftpos, rightpos, leftpos_orig;
418
419
420     if (c >= eCompNR)
421     {
422         gmx_fatal(FARGS, "No compartment %d.", c);
423     }
424
425     pos0 = s->group[eGrpSplit0].center[s->swapdim];
426     pos1 = s->group[eGrpSplit1].center[s->swapdim];
427
428     if (pos0 < pos1)
429     {
430         leftpos  = pos0;
431         rightpos = pos1;
432     }
433     else
434     {
435         leftpos  = pos1;
436         rightpos = pos0;
437     }
438
439     /* This gets us the other compartment: */
440     if (c == eCompB)
441     {
442         leftpos_orig = leftpos;
443         leftpos      = rightpos;
444         rightpos     = leftpos_orig + box[s->swapdim][s->swapdim];
445     }
446
447     *left  = leftpos;
448     *right = rightpos;
449 }
450
451
452 /*! To determine the flux through the individual channels, we
453  * remember the compartment and channel history of each ion. An ion can be
454  * either in channel0 or channel1, or in the remaining volume of compartment
455  * A or B.
456  *
457  * \code
458  *    +-----------------+
459  *    |                 | B
460  *    |                 | B compartment
461  *    ||||||||||0|||||||| bilayer with channel 0
462  *    |                 | A
463  *    |                 | A
464  *    |                 | A compartment
465  *    |                 | A
466  *    |||||1||||||||||||| bilayer with channel 1
467  *    |                 | B
468  *    |                 | B compartment
469  *    +-----------------+
470  *
471  * \endcode
472  */
473 static void detect_flux_per_channel(
474         int             iion,
475         int             comp,
476         int             iontype,
477         rvec            ion_pos,
478         unsigned char  *comp_now,
479         unsigned char  *comp_from,
480         unsigned char  *channel_label,
481         t_swapcoords   *sc,
482         real            cyl0_r2,
483         real            cyl1_r2,
484         gmx_int64_t     step,
485         gmx_bool        bRerun,
486         FILE           *fpout)
487 {
488     gmx_swapcoords_t s;
489     int              sd, chan_nr;
490     gmx_bool         in_cyl0, in_cyl1;
491     char             buf[STRLEN];
492
493
494     s    = sc->si_priv;
495     sd   = s->swapdim;
496
497     /* Check whether ion is inside any of the channels */
498     in_cyl0 = is_in_channel(ion_pos, s->group[eGrpSplit0].center, sc->cyl0u, sc->cyl0l, cyl0_r2, s->pbc, sd);
499     in_cyl1 = is_in_channel(ion_pos, s->group[eGrpSplit1].center, sc->cyl1u, sc->cyl1l, cyl1_r2, s->pbc, sd);
500
501     if (in_cyl0 && in_cyl1)
502     {
503         /* Ion appears to be in both channels. Something is severely wrong! */
504         s->cyl0and1++;
505         *comp_now      = eDomainNotset;
506         *comp_from     = eDomainNotset;
507         *channel_label = eChHistPassedNone;
508     }
509     else if (in_cyl0)
510     {
511         /* Ion is in channel 0 now */
512         *channel_label = eChHistPassedCh0;
513         *comp_now      = eDomainNotset;
514         s->ncyl0ions++;
515     }
516     else if (in_cyl1)
517     {
518         /* Ion is in channel 1 now */
519         *channel_label = eChHistPassedCh1;
520         *comp_now      = eDomainNotset;
521         s->ncyl1ions++;
522     }
523     else
524     {
525         /* Ion is not in any of the channels, so it must be in domain A or B */
526         if (eCompA == comp)
527         {
528             *comp_now = eDomainA;
529         }
530         else
531         {
532             *comp_now = eDomainB;
533         }
534     }
535
536     /* Only take action, if ion is now in domain A or B, and was before
537      * in the other domain!
538      */
539     if (eDomainNotset == *comp_from)
540     {
541         /* Maybe we can set the domain now */
542         *comp_from = *comp_now;               /* Could still be eDomainNotset, though */
543     }
544     else if (  (*comp_now  != eDomainNotset ) /* if in channel */
545                && (*comp_from != *comp_now)  )
546     {
547         /* Obviously the ion changed its domain.
548          * Count this for the channel through which it has passed. */
549         switch (*channel_label)
550         {
551             case eChHistPassedNone:
552                 *s->fluxleak = *s->fluxleak + 1;
553
554                 fprintf(stderr, " %s Warning! Step %s, ion %d (%s) moved from %s to %s\n",
555                         SwS, gmx_step_str(step, buf), iion, IonStr[iontype], DomainString[*comp_from], DomainString[*comp_now]);
556                 if (bRerun)
557                 {
558                     fprintf(stderr, ", possibly due to a swap in the original simulation.\n");
559                 }
560                 else
561                 {
562                     fprintf(stderr, "but did not pass cyl0 or cyl1 as defined in the .mdp file.\n"
563                             "Do you have an ion somewhere within the membrane?\n");
564                     /* Write this info to the CompEL output file: */
565                     fprintf(s->fpout, " # Warning: step %s, ion %d (%s) moved from %s to %s (probably through the membrane)\n",
566                             gmx_step_str(step, buf), iion, IonStr[iontype],
567                             DomainString[*comp_from], DomainString[*comp_now]);
568
569                 }
570                 break;
571             case eChHistPassedCh0:
572             case eChHistPassedCh1:
573                 if (*channel_label == eChHistPassedCh0)
574                 {
575                     chan_nr = 0;
576                 }
577                 else
578                 {
579                     chan_nr = 1;
580                 }
581
582                 if (eDomainA == *comp_from)
583                 {
584                     s->fluxfromAtoB[chan_nr][iontype]++;
585                 }
586                 else
587                 {
588                     s->fluxfromAtoB[chan_nr][iontype]--;
589                 }
590                 fprintf(fpout, "# Atom nr. %d finished passing %s.\n", iion, ChannelString[*channel_label]);
591                 break;
592             default:
593                 gmx_fatal(FARGS, "%s Unknown channel history entry!\n", SwS);
594                 break;
595         }
596
597         /* This ion has moved to the _other_ compartment ... */
598         *comp_from = *comp_now;
599         /* ... and it did not pass any channel yet */
600         *channel_label = eChHistPassedNone;
601     }
602 }
603
604
605 /*! Get the lists of ions for the two compartments */
606 static void compartmentalize_ions(
607         t_commrec      *cr,
608         t_swapcoords   *sc,
609         matrix          box,
610         gmx_int64_t     step,
611         FILE           *fpout,
612         gmx_bool        bRerun)
613 {
614     gmx_swapcoords_t s;
615     int              i, sd, replace;
616     real             left, right;
617     t_group         *iong;
618     real             dist;
619     real             cyl0_r2, cyl1_r2;
620     int              comp, type;
621     int              sum, not_in_comp[eCompNR]; /* consistency check */
622     int              ion_nr_global;
623
624
625     s    = sc->si_priv;
626     iong = &s->group[eGrpIons];
627     sd   = s->swapdim;
628
629     cyl0_r2 = sc->cyl0r * sc->cyl0r;
630     cyl1_r2 = sc->cyl1r * sc->cyl1r;
631
632
633     /* Get us a counter that cycles in the range of [0 ... sc->nAverage[ */
634     replace = (step/sc->nstswap) % sc->nAverage;
635
636     for (comp = eCompA; comp <= eCompB; comp++)
637     {
638         /* Get lists of atoms that match criteria for this compartment */
639         get_compartment_boundaries(comp, sc->si_priv, box, &left, &right);
640
641         /* First clear the ion lists */
642         s->comp[comp][eIonNEG].nat = 0;
643         s->comp[comp][eIonPOS].nat = 0;
644         not_in_comp[comp]          = 0; /* consistency check */
645
646         /* Loop over the IONS */
647         for (i = 0; i < iong->nat; i++)
648         {
649             /* Anion or cation? */
650             type = iong->qc[i] < 0 ? eIonNEG : eIonPOS;
651
652             /* Is this ion in the compartment that we look at? */
653             if (compartment_contains_atom(left, right, 0, iong->xc[i][sd], box[sd][sd], &dist) )
654             {
655                 /* Now put it into the list containing only ions of its type */
656                 add_to_list(i, &s->comp[comp][type], dist);
657
658                 /* Master also checks through which channel each ion has passed */
659                 if (MASTER(cr) && (iong->comp_now != NULL))
660                 {
661                     ion_nr_global = iong->ind[i] + 1; /* PDB index starts at 1 ... */
662                     detect_flux_per_channel(ion_nr_global, comp, type, iong->xc[i],
663                                             &iong->comp_now[i], &iong->comp_from[i], &iong->channel_label[i],
664                                             sc, cyl0_r2, cyl1_r2, step, bRerun, fpout);
665                 }
666             }
667             else
668             {
669                 not_in_comp[comp] += 1;
670             }
671         }
672         /* Correct the time-averaged number of ions in both compartments */
673         update_time_window(&s->comp[comp][eIonNEG], sc->nAverage, replace);
674         update_time_window(&s->comp[comp][eIonPOS], sc->nAverage, replace);
675     }
676
677     /* Flux detection warnings */
678     if (MASTER(cr) )
679     {
680         if (s->cyl0and1 > 0)
681         {
682             fprintf(stderr, "\n"
683                     "%s Warning: %d atoms were detected as being in both channels! Probably your split\n"
684                     "%s          cylinder is way too large, or one compartment has collapsed (step %"GMX_PRId64 ")\n",
685                     SwS, s->cyl0and1, SwS, step);
686
687             fprintf(s->fpout, "Warning: %d atoms were assigned to both channels!\n", s->cyl0and1);
688
689             s->cyl0and1 = 0;
690         }
691     }
692
693
694     /* Consistency checks */
695     if (not_in_comp[eCompA] + not_in_comp[eCompB] != iong->nat)
696     {
697         if (NULL != fpout)
698         {
699             fprintf(fpout, "# Warning: Inconsistency during ion compartmentalization. !inA: %d, !inB: %d, total ions %d\n",
700                     not_in_comp[eCompA], not_in_comp[eCompB], iong->nat);
701             fflush(fpout);
702         }
703         else
704         {
705             fprintf(stderr, "%s node %d: Inconsistency during ion compartmentalization. !inA: %d, !inB: %d, total ions %d\n",
706                     SwS, cr->nodeid, not_in_comp[eCompA], not_in_comp[eCompB], iong->nat);
707
708         }
709     }
710     sum =   s->comp[eCompA][eIonNEG].nat + s->comp[eCompA][eIonPOS].nat
711         + s->comp[eCompB][eIonNEG].nat + s->comp[eCompB][eIonPOS].nat;
712     if (sum != iong->nat)
713     {
714         if (NULL != fpout)
715         {
716             fprintf(fpout, "# Warning: %d atoms are in the ion group, but altogether %d have been assigned to the compartments.\n",
717                     iong->nat, sum);
718             fflush(fpout);
719         }
720         else
721         {
722             fprintf(stderr, "%s node %d: %d atoms are in the ion group, but altogether %d have been assigned to the compartments.\n",
723                     SwS, cr->nodeid, iong->nat, sum);
724         }
725     }
726
727
728 }
729
730
731 /*! Set up the compartments and get lists of solvent atoms in each compartment */
732 static void compartmentalize_solvent(
733         t_commrec    *cr,
734         t_swapcoords *sc,
735         matrix        box,
736         FILE         *fpout)
737 {
738     gmx_swapcoords_t s;
739     int              apm, i, j, sd;
740     real             left, right;
741     t_group         *solg;
742     real             dist;
743     int              comp;
744     int              sum, not_in_comp[eCompNR]; /* consistency check */
745
746
747     s    = sc->si_priv;
748     solg = &s->group[eGrpSolvent];
749     sd   = s->swapdim;
750     apm  = solg->apm;
751
752     for (comp = eCompA; comp <= eCompB; comp++)
753     {
754         /* Get lists of atoms that match criteria for this compartment */
755         get_compartment_boundaries(comp, sc->si_priv, box, &left, &right);
756
757         /* First clear the solvent molecule lists */
758         s->compsol[comp].nat = 0;
759         not_in_comp[comp]    = 0; /* consistency check */
760
761         /* Loop over the solvent MOLECULES */
762         for (i = 0; i < sc->nat_sol; i += apm)
763         {
764             if (compartment_contains_atom(left, right, 0, solg->xc[i][sd], box[sd][sd], &dist))
765             {
766                 /* Add the whole molecule to the list */
767                 for (j = 0; j < apm; j++)
768                 {
769                     add_to_list(i+j, &s->compsol[comp], dist);
770                 }
771             }
772             else
773             {
774                 not_in_comp[comp] += apm;
775             }
776         }
777     }
778
779     if (NULL != fpout)
780     {
781         fprintf(fpout, "# Solv. molecules in comp.%s: %d   comp.%s: %d\n",
782                 CompStr[eCompA], s->compsol[eCompA].nat/apm,
783                 CompStr[eCompB], s->compsol[eCompB].nat/apm);
784     }
785
786     /* Consistency checks */
787     if (not_in_comp[eCompA] + not_in_comp[eCompB] != solg->nat)
788     {
789         if (NULL != fpout)
790         {
791             fprintf(fpout, "# Warning: Inconsistency during solvent compartmentalization. !inA: %d, !inB: %d, solvent atoms %d\n",
792                     not_in_comp[eCompA], not_in_comp[eCompB], solg->nat);
793             fflush(fpout);
794         }
795         else
796         {
797             fprintf(stderr, "%s node %d: Inconsistency during solvent compartmentalization. !inA: %d, !inB: %d, solvent atoms %d\n",
798                     SwS, cr->nodeid, not_in_comp[eCompA], not_in_comp[eCompB], solg->nat);
799         }
800     }
801     sum = s->compsol[eCompA].nat + s->compsol[eCompB].nat;
802     if (sum != solg->nat)
803     {
804         if (NULL != fpout)
805         {
806             fprintf(fpout, "# Warning: %d atoms in solvent group, but %d have been assigned to the compartments.\n",
807                     solg->nat, sum);
808             fflush(fpout);
809         }
810         else
811         {
812             fprintf(stderr, "%s node %d: %d atoms in solvent group, but %d have been assigned to the compartments.\n",
813                     SwS, cr->nodeid, solg->nat, sum);
814         }
815     }
816 }
817
818
819 /*! Find out how many group atoms are in the compartments initially */
820 static void get_initial_ioncounts(
821         t_inputrec       *ir,
822         rvec              x[],   /* the initial positions */
823         matrix            box,
824         t_commrec        *cr,
825         gmx_bool          bRerun)
826 {
827     t_swapcoords *sc;
828     t_swap       *s;
829     int           i, ii, ind, ic;
830     int           req[2], tot[2];
831
832
833     sc = ir->swap;
834     s  = sc->si_priv;
835
836     /* Copy the initial swap group positions to the collective array so
837      * that we can compartmentalize */
838     for (i = 0; i < sc->nat; i++)
839     {
840         ind = sc->ind[i];
841         copy_rvec(x[ind], s->group[eGrpIons].xc[i]);
842     }
843
844     /* Set up the compartments and get lists of atoms in each compartment */
845     compartmentalize_ions(cr, sc, box, 0, s->fpout, bRerun);
846
847     /* Set initial concentrations if requested */
848     for (ic = 0; ic < eCompNR; ic++)
849     {
850         s->comp[ic][eIonPOS].nat_req = sc->ncations[ic];
851         s->comp[ic][eIonNEG].nat_req = sc->nanions[ic];
852     }
853     for (ic = 0; ic < eCompNR; ic++)
854     {
855         for (ii = 0; ii < eIonNR; ii++)
856         {
857             if (s->comp[ic][ii].nat_req < 0)
858             {
859                 s->comp[ic][ii].nat_req = s->comp[ic][ii].nat;
860             }
861         }
862     }
863
864     /* Check whether the number of requested ions adds up to the total number of ions */
865     for (ii = 0; ii < eIonNR; ii++)
866     {
867         req[ii] = s->comp[eCompA][ii].nat_req + s->comp[eCompB][ii].nat_req;
868         tot[ii] = s->comp[eCompA][ii].nat     + s->comp[eCompB][ii].nat;
869     }
870     if ( (req[eCompA] != tot[eCompA]) || (req[eCompB] != tot[eCompB ]) )
871     {
872         gmx_fatal(FARGS, "Mismatch of the number of ions summed over both compartments.\n"
873                   "You requested a total of %d anions and %d cations,\n"
874                   "but there are a total of %d anions and %d cations in the system.\n",
875                   req[eIonNEG], req[eIonPOS],
876                   tot[eIonNEG], tot[eIonPOS]);
877     }
878
879     /* Initialize time-averaging:
880      * Write initial concentrations to all time bins to start with */
881     for (ic = 0; ic < eCompNR; ic++)
882     {
883         for (ii = 0; ii < eIonNR; ii++)
884         {
885             s->comp[ic][ii].nat_av = s->comp[ic][ii].nat;
886             for (i = 0; i < sc->nAverage; i++)
887             {
888                 s->comp[ic][ii].nat_past[i] = s->comp[ic][ii].nat;
889             }
890         }
891     }
892 }
893
894
895 /*! When called, the checkpoint file has already been read in. Here we copy
896  * over the values from .cpt file to the swap data structure.
897  */
898 static void get_initial_ioncounts_from_cpt(
899         t_inputrec *ir, swapstate_t *swapstate,
900         t_commrec *cr, gmx_bool bVerbose)
901 {
902     t_swapcoords *sc;
903     t_swap       *s;
904     int           ic, ii, j;
905
906     sc = ir->swap;
907     s  = sc->si_priv;
908
909     if (MASTER(cr))
910     {
911         /* Copy the past values from the checkpoint values that have been read in already */
912         if (bVerbose)
913         {
914             fprintf(stderr, "%s Copying values from checkpoint\n", SwS);
915         }
916
917         for (ic = 0; ic < eCompNR; ic++)
918         {
919             for (ii = 0; ii < eIonNR; ii++)
920             {
921                 s->comp[ic][ii].nat_req      = swapstate->nat_req[ic][ii];
922                 s->comp[ic][ii].inflow_netto = swapstate->inflow_netto[ic][ii];
923
924                 if (bVerbose)
925                 {
926                     fprintf(stderr, "%s ... Influx netto: %d   Requested: %d   Past values: ", SwS,
927                             s->comp[ic][ii].inflow_netto, s->comp[ic][ii].nat_req);
928                 }
929
930                 for (j = 0; j < sc->nAverage; j++)
931                 {
932                     s->comp[ic][ii].nat_past[j] = swapstate->nat_past[ic][ii][j];
933                     if (bVerbose)
934                     {
935                         fprintf(stderr, "%d ", s->comp[ic][ii].nat_past[j]);
936                     }
937                 }
938                 if (bVerbose)
939                 {
940                     fprintf(stderr, "\n");
941                 }
942             }
943         }
944     }
945 }
946
947
948 /*! Master node lets all other nodes know about the initial ion counts. */
949 static void bc_initial_concentrations(
950         t_commrec    *cr,
951         t_swapcoords *swap)
952 {
953     int     ic, ii;
954     t_swap *s;
955
956     s = swap->si_priv;
957
958     for (ic = 0; ic < eCompNR; ic++)
959     {
960         for (ii = 0; ii < eIonNR; ii++)
961         {
962             gmx_bcast(sizeof(s->comp[ic][ii].nat_req), &(s->comp[ic][ii].nat_req), cr);
963             gmx_bcast(sizeof(s->comp[ic][ii].nat    ), &(s->comp[ic][ii].nat    ), cr);
964             gmx_bcast( swap->nAverage * sizeof(s->comp[ic][ii].nat_past[0]), s->comp[ic][ii].nat_past, cr);
965         }
966     }
967 }
968
969
970 /*! Ensure that each atom belongs to at most one of the swap groups. */
971 static void check_swap_groups(t_swap *s, int nat, gmx_bool bVerbose)
972 {
973     t_group  *g;
974     int       i, j;
975     atom_id  *nGroup    = NULL; /* This array counts for each atom in the MD system to
976                                    how many swap groups it belongs (should be 0 or 1!) */
977     int       ind       = -1;
978     int       nMultiple = 0;    /* Number of atoms belonging to multiple groups */
979
980
981     if (bVerbose)
982     {
983         fprintf(stderr, "%s Making sure each atom belongs to at most one of the swap groups.\n", SwS);
984     }
985
986     /* Add one to the group count of atoms belonging to a swap group: */
987     snew(nGroup, nat);
988     for (i = 0; i < eGrpNr; i++)
989     {
990         g = &s->group[i];
991         for (j = 0; j < g->nat; j++)
992         {
993             /* Get the global index of this atom of this group: */
994             ind = g->ind[j];
995             nGroup[ind]++;
996         }
997     }
998     /* Make sure each atom belongs to at most one swap group: */
999     for (j = 0; j < g->nat; j++)
1000     {
1001         if (nGroup[j] > 1)
1002         {
1003             nMultiple++;
1004         }
1005     }
1006     sfree(nGroup);
1007
1008     if (nMultiple)
1009     {
1010         gmx_fatal(FARGS, "%s Cannot perform swapping since %d atom%s allocated to more than one swap index group.\n"
1011                   "%s Each atom must be allocated to at most one of the split groups, the swap group, or the solvent.\n"
1012                   "%s Check the .mdp file settings regarding the swap index groups or the index groups themselves.\n",
1013                   SwS, nMultiple, (1 == nMultiple) ? " is" : "s are", SwSEmpty, SwSEmpty);
1014     }
1015 }
1016
1017
1018 /*! Get the number of atoms per molecule for this group.
1019  * Also ensure that all the molecules in this group have this number of atoms. */
1020 static int get_group_apm_check(
1021         int                         group,
1022         t_swap                     *s,
1023         gmx_bool                    bVerbose,
1024         const gmx_mtop_atomlookup_t alook,
1025         gmx_mtop_t                 *mtop)
1026 {
1027     int *ind;
1028     int  nat, apm, i;
1029     int  molb, molnr, atnr_mol;
1030
1031
1032     ind = s->group[group].ind;
1033     nat = s->group[group].nat;
1034
1035     /* Determine the number of solvent atoms per solvent molecule from the
1036      * first solvent atom: */
1037     i = 0;
1038     gmx_mtop_atomnr_to_molblock_ind(alook, ind[i], &molb, &molnr, &atnr_mol);
1039     apm = mtop->molblock[molb].natoms_mol;
1040
1041     if (bVerbose)
1042     {
1043         fprintf(stderr, "%s Checking whether all %s molecules consist of %d atom%s\n",
1044                 SwS, GrpString[group], apm, apm > 1 ? "s" : "");
1045     }
1046
1047     /* Check whether this is also true for all other solvent atoms */
1048     for (i = 1; i < nat; i++)
1049     {
1050         gmx_mtop_atomnr_to_molblock_ind(alook, ind[i], &molb, &molnr, &atnr_mol);
1051         if (apm != mtop->molblock[molb].natoms_mol)
1052         {
1053             gmx_fatal(FARGS, "Not all %s group molecules consist of %d atoms.",
1054                       GrpString[group], apm);
1055         }
1056     }
1057
1058     return apm;
1059 }
1060
1061
1062 /*! Print the legend to the swapcoords output file as well as the
1063  * initial ion counts */
1064 static void print_ionlist_legend(t_inputrec *ir, const output_env_t oenv)
1065 {
1066     const char **legend;
1067     int          ic, count, ii;
1068     char         buf[256];
1069     t_swap      *s;
1070
1071
1072     s = ir->swap->si_priv;
1073
1074     snew(legend, eCompNR*eIonNR*3 + 2 + eChanNR*eIonNR + 1);
1075     for (ic = count = 0; ic < eCompNR; ic++)
1076     {
1077         for (ii = 0; ii < eIonNR; ii++)
1078         {
1079             sprintf(buf, "%s %ss", CompStr[ic], IonString[ii]);
1080             legend[count++] = gmx_strdup(buf);
1081             sprintf(buf, "%s av. mismatch to %d%s",
1082                     CompStr[ic], s->comp[ic][ii].nat_req, IonStr[ii]);
1083             legend[count++] = gmx_strdup(buf);
1084             sprintf(buf, "%s netto %s influx", CompStr[ic], IonString[ii]);
1085             legend[count++] = gmx_strdup(buf);
1086         }
1087     }
1088     sprintf(buf, "%scenter of %s of split group 0", SwapStr[ir->eSwapCoords], (NULL != s->group[eGrpSplit0].m) ? "mass" : "geometry");
1089     legend[count++] = gmx_strdup(buf);
1090     sprintf(buf, "%scenter of %s of split group 1", SwapStr[ir->eSwapCoords], (NULL != s->group[eGrpSplit1].m) ? "mass" : "geometry");
1091     legend[count++] = gmx_strdup(buf);
1092
1093     for (ic = 0; ic < eChanNR; ic++)
1094     {
1095         for (ii = 0; ii < eIonNR; ii++)
1096         {
1097             sprintf(buf, "A->ch%d->B %s permeations", ic, IonString[ii]);
1098             legend[count++] = gmx_strdup(buf);
1099         }
1100     }
1101
1102     sprintf(buf, "leakage");
1103     legend[count++] = gmx_strdup(buf);
1104
1105     xvgr_legend(s->fpout, count, legend, oenv);
1106
1107     fprintf(s->fpout, "# Instantaneous ion counts and time-averaged differences to requested numbers\n");
1108     fprintf(s->fpout, "#   time[ps]   A_an   diff   t_in  A_cat   diff   t_in   B_an   diff   t_in  B_cat   diff   t_in ");
1109     fprintf(s->fpout, "   %s-Split0    %s-Split1", DimStr[s->swapdim], DimStr[s->swapdim]);
1110     fprintf(s->fpout, "  A-ch0-B_an A-ch0-B_cat  A-ch1-B_an A-ch1-B_cat ion_leakage\n");
1111     fflush(s->fpout);
1112 }
1113
1114
1115 /*! Initialize arrays that keep track of where the ions come from and where
1116  * they go */
1117 static void detect_flux_per_channel_init(
1118         t_commrec   *cr,
1119         t_swap      *s,
1120         swapstate_t *swapstate,
1121         gmx_bool     bStartFromCpt)
1122 {
1123     int      i, ic, ii;
1124     t_group *g;
1125
1126
1127     g = &(s->group[eGrpIons]);
1128
1129     /* All these flux detection routines run on the master only */
1130     if (!MASTER(cr))
1131     {
1132         g->comp_now      = NULL;
1133         g->comp_from     = NULL;
1134         g->channel_label = NULL;
1135
1136         return;
1137     }
1138
1139     /******************************************************/
1140     /* Channel and domain history for the individual ions */
1141     /******************************************************/
1142     if (bStartFromCpt) /* set the pointers right */
1143     {
1144         g->comp_from     = swapstate->comp_from;
1145         g->channel_label = swapstate->channel_label;
1146     }
1147     else /* allocate memory */
1148     {
1149         snew(g->comp_from, g->nat);
1150         swapstate->comp_from = g->comp_from;
1151         snew(g->channel_label, g->nat);
1152         swapstate->channel_label = g->channel_label;
1153     }
1154     snew(g->comp_now, g->nat);
1155
1156     /* Initialize the channel and domain history counters */
1157     for (i = 0; i < g->nat; i++)
1158     {
1159         g->comp_now[i] = eDomainNotset;
1160         if (!bStartFromCpt)
1161         {
1162             g->comp_from[i]     = eDomainNotset;
1163             g->channel_label[i] = eChHistPassedNone;
1164         }
1165     }
1166
1167     /************************************/
1168     /* Channel fluxes for both channels */
1169     /************************************/
1170     s->ncyl0ions = 0;
1171     s->ncyl1ions = 0;
1172     s->cyl0and1  = 0;
1173
1174     if (bStartFromCpt)
1175     {
1176         fprintf(stderr, "%s Copying channel fluxes from checkpoint file data\n", SwS);
1177     }
1178
1179     for (ic = 0; ic < eChanNR; ic++)
1180     {
1181         fprintf(stderr, "%s Channel %d flux history: ", SwS, ic);
1182         for (ii = 0; ii < eIonNR; ii++)
1183         {
1184             if (bStartFromCpt)
1185             {
1186                 s->fluxfromAtoB[ic][ii] = swapstate->fluxfromAtoB[ic][ii];
1187             }
1188             else
1189             {
1190                 s->fluxfromAtoB[ic][ii] = 0;
1191             }
1192
1193             fprintf(stderr, "%d %s%s   ", s->fluxfromAtoB[ic][ii], IonString[ii], s->fluxfromAtoB[ic][ii] == 1 ? "" : "s");
1194         }
1195         fprintf(stderr, "\n");
1196     }
1197     if (bStartFromCpt)
1198     {
1199         s->fluxleak = swapstate->fluxleak;
1200     }
1201     else
1202     {
1203         snew(s->fluxleak, 1);
1204         *s->fluxleak = 0;
1205         /* Set pointer for checkpoint writing */
1206         swapstate->fluxleak = s->fluxleak;
1207     }
1208
1209     /* Set pointers for checkpoint writing */
1210     for (ic = 0; ic < eChanNR; ic++)
1211     {
1212         for (ii = 0; ii < eIonNR; ii++)
1213         {
1214             swapstate->fluxfromAtoB_p[ic][ii] = &(s->fluxfromAtoB[ic][ii]);
1215         }
1216     }
1217 }
1218
1219
1220 /*! Output the starting structure so that in case of multimeric channels
1221  * the user can check whether we have the correct PBC image for all atoms.
1222  * If this is not correct, the ion counts per channel will be very likely
1223  * wrong. */
1224 static void outputStartStructureIfWanted(gmx_mtop_t *mtop, rvec *x, int ePBC, matrix box)
1225 {
1226     char *env = getenv("GMX_COMPELDUMP");
1227
1228     if (env != NULL)
1229     {
1230         fprintf(stderr, "\n%s Found env.var. GMX_COMPELDUMP, will output CompEL starting structure made whole.\n"
1231                 "%s In case of multimeric channels, please check whether they have the correct PBC representation.\n",
1232                 SwS, SwSEmpty);
1233
1234         write_sto_conf_mtop("CompELAssumedWholeConfiguration.pdb", *mtop->name, mtop, x, NULL, ePBC, box);
1235     }
1236 }
1237
1238
1239 /*! The swapstate struct stores the information we need to make the channels
1240  * whole again after restarts from a checkpoint file. Here we do the following:
1241  * a) If we did not start from .cpt, we prepare the struct for proper .cpt writing,\n
1242  * b) if we did start from .cpt, we copy over the last whole structures from .cpt,\n
1243  * c) in any case, for subsequent checkpoint writing, we set the pointers in\n
1244  * swapstate to the x_old arrays, which contain the correct PBC representation of
1245  * multimeric channels at the last time step. */
1246 static void init_swapstate(
1247         swapstate_t      *swapstate,
1248         t_swapcoords     *sc,
1249         gmx_mtop_t       *mtop,
1250         rvec              x[],      /* the initial positions */
1251         matrix            box,
1252         int               ePBC)
1253 {
1254     int                    i, ig;
1255     rvec                  *x_pbc  = NULL;   /* positions of the whole MD system with molecules made whole */
1256     t_group               *g;
1257     t_swap                *s;
1258
1259
1260     s = sc->si_priv;
1261
1262     /* We always need the last whole positions such that
1263      * in the next time step we can make the channels whole again in PBC */
1264     if (swapstate->bFromCpt)
1265     {
1266         /* Copy the last whole positions of each channel from .cpt */
1267         g = &(s->group[eGrpSplit0]);
1268         for (i = 0; i <  g->nat; i++)
1269         {
1270             copy_rvec(swapstate->xc_old_whole[eChan0][i], g->xc_old[i]);
1271         }
1272         g = &(s->group[eGrpSplit1]);
1273         for (i = 0; i <  g->nat; i++)
1274         {
1275             copy_rvec(swapstate->xc_old_whole[eChan1][i], g->xc_old[i]);
1276         }
1277     }
1278     else
1279     {
1280         /* Extract the initial split group positions. */
1281
1282         /* Remove pbc, make molecule whole. */
1283         snew(x_pbc, mtop->natoms);
1284         m_rveccopy(mtop->natoms, x, x_pbc);
1285
1286         /* This can only make individual molecules whole, not multimers */
1287         do_pbc_mtop(NULL, ePBC, box, mtop, x_pbc);
1288
1289         /* Output the starting structure? */
1290         outputStartStructureIfWanted(mtop, x_pbc, ePBC, box);
1291
1292         /* If this is the first run (i.e. no checkpoint present) we assume
1293          * that the starting positions give us the correct PBC representation */
1294         for (ig = eGrpSplit0; ig <= eGrpSplit1; ig++)
1295         {
1296             g = &(s->group[ig]);
1297             for (i = 0; i < g->nat; i++)
1298             {
1299                 copy_rvec(x_pbc[g->ind[i]], g->xc_old[i]);
1300             }
1301         }
1302         sfree(x_pbc);
1303
1304         /* Prepare swapstate arrays for later checkpoint writing */
1305         swapstate->nat[eChan0] = s->group[eGrpSplit0].nat;
1306         swapstate->nat[eChan1] = s->group[eGrpSplit1].nat;
1307     }
1308
1309     /* For subsequent checkpoint writing, set the swapstate pointers to the xc_old
1310      * arrays that get updated at every swapping step */
1311     swapstate->xc_old_whole_p[eChan0] = &s->group[eGrpSplit0].xc_old;
1312     swapstate->xc_old_whole_p[eChan1] = &s->group[eGrpSplit1].xc_old;
1313 }
1314
1315
1316 extern void init_swapcoords(
1317         FILE              *fplog,
1318         gmx_bool           bVerbose,
1319         t_inputrec        *ir,
1320         const char        *fn,
1321         gmx_mtop_t        *mtop,
1322         rvec               x[],
1323         matrix             box,
1324         swapstate_t       *swapstate,
1325         t_commrec         *cr,
1326         const output_env_t oenv,
1327         unsigned long      Flags)
1328 {
1329     int                    i, ic, ig, ii, j;
1330     t_swapcoords          *sc;
1331     t_swap                *s;
1332     t_atom                *atom;
1333     t_group               *g;
1334     gmx_bool               bAppend, bStartFromCpt, bRerun;
1335     gmx_mtop_atomlookup_t  alook = NULL;
1336
1337
1338     alook = gmx_mtop_atomlookup_init(mtop);
1339
1340     if ( (PAR(cr)) && !DOMAINDECOMP(cr) )
1341     {
1342         gmx_fatal(FARGS, "Position swapping is only implemented for domain decomposition!");
1343     }
1344
1345     bAppend       = Flags & MD_APPENDFILES;
1346     bStartFromCpt = Flags & MD_STARTFROMCPT;
1347     bRerun        = Flags & MD_RERUN;
1348
1349     sc = ir->swap;
1350     snew(sc->si_priv, 1);
1351     s = sc->si_priv;
1352
1353     if (bRerun)
1354     {
1355         if (PAR(cr))
1356         {
1357             gmx_fatal(FARGS, "%s This module does not support reruns in parallel\nPlease request a serial run with -nt 1 / -np 1\n", SwS);
1358         }
1359
1360         fprintf(stderr, "%s Rerun - using every available frame\n", SwS);
1361         sc->nstswap  = 1;
1362         sc->nAverage = 1;  /* averaging makes no sense for reruns */
1363     }
1364
1365     if (MASTER(cr) && !bAppend)
1366     {
1367         fprintf(fplog, "\nInitializing ion/water position exchanges\n");
1368         please_cite(fplog, "Kutzner2011b");
1369     }
1370
1371     switch (ir->eSwapCoords)
1372     {
1373         case eswapX:
1374             s->swapdim = XX;
1375             break;
1376         case eswapY:
1377             s->swapdim = YY;
1378             break;
1379         case eswapZ:
1380             s->swapdim = ZZ;
1381             break;
1382         default:
1383             s->swapdim = -1;
1384             break;
1385     }
1386
1387     /* Copy some data to the group structures for convenience */
1388     /* Number of atoms in the group */
1389     s->group[eGrpIons   ].nat = sc->nat;
1390     s->group[eGrpSplit0 ].nat = sc->nat_split[0];
1391     s->group[eGrpSplit1 ].nat = sc->nat_split[1];
1392     s->group[eGrpSolvent].nat = sc->nat_sol;
1393     /* Pointer to the indices */
1394     s->group[eGrpIons   ].ind = sc->ind;
1395     s->group[eGrpSplit0 ].ind = sc->ind_split[0];
1396     s->group[eGrpSplit1 ].ind = sc->ind_split[1];
1397     s->group[eGrpSolvent].ind = sc->ind_sol;
1398
1399     check_swap_groups(s, mtop->natoms, bVerbose && MASTER(cr));
1400
1401     /* Allocate space for the collective arrays for all groups */
1402     for (ig = 0; ig < eGrpNr; ig++)
1403     {
1404         g = &(s->group[ig]);
1405         snew(g->xc, g->nat);
1406         snew(g->c_ind_loc, g->nat);
1407         /* For the split groups (the channels) we need some extra memory to
1408          * be able to make the molecules whole even if they span more than
1409          * half of the box size. */
1410         if (eGrpSplit0 == ig || eGrpSplit1 == ig)
1411         {
1412             snew(g->xc_shifts, g->nat);
1413             snew(g->xc_eshifts, g->nat);
1414             snew(g->xc_old, g->nat);
1415         }
1416     }
1417
1418     if (MASTER(cr))
1419     {
1420         init_swapstate(swapstate, sc, mtop, x, box, ir->ePBC);
1421     }
1422
1423     /* After init_swapstate we have a set of (old) whole positions for our
1424      * channels. Now transfer that to all nodes */
1425     if (PAR(cr))
1426     {
1427         for (ig = eGrpSplit0; ig <= eGrpSplit1; ig++)
1428         {
1429             g = &(s->group[ig]);
1430             gmx_bcast((g->nat)*sizeof((g->xc_old)[0]), g->xc_old, (cr));
1431         }
1432     }
1433
1434     /* Make sure that all molecules in the ion and solvent groups contain the
1435      * same number of atoms each */
1436     s->group[eGrpIons   ].apm = get_group_apm_check(eGrpIons, s, MASTER(cr) && bVerbose, alook, mtop);
1437     s->group[eGrpSolvent].apm = get_group_apm_check(eGrpSolvent, s, MASTER(cr) && bVerbose, alook, mtop);
1438
1439     /* Save masses where needed */
1440     s->group[eGrpIons   ].m = NULL;
1441     /* We only need enough space to determine a single solvent molecule's
1442      * center at at time */
1443     g = &(s->group[eGrpSolvent]);
1444     snew(g->m, g->apm);
1445
1446     /* Need mass-weighted center of split group? */
1447     for (j = 0, ig = eGrpSplit0; j < eChanNR; ig++, j++)
1448     {
1449         g = &(s->group[ig]);
1450         if (TRUE == sc->massw_split[j])
1451         {
1452             /* Save the split group charges if mass-weighting is requested */
1453             snew(g->m, g->nat);
1454             for (i = 0; i < g->nat; i++)
1455             {
1456                 gmx_mtop_atomnr_to_atom(alook, g->ind[i], &atom);
1457                 g->m[i] = atom->m;
1458             }
1459         }
1460         else
1461         {
1462             g->m = NULL;
1463         }
1464     }
1465
1466     /* Save the ionic charges */
1467     g = &(s->group[eGrpIons]);
1468     snew(g->qc, g->nat);
1469     for (i = 0; i < g->nat; i++)
1470     {
1471         gmx_mtop_atomnr_to_atom(alook, g->ind[i], &atom);
1472         g->qc[i] = atom->q;
1473     }
1474
1475     snew(s->pbc, 1);
1476     set_pbc(s->pbc, -1, box);
1477
1478
1479     if (MASTER(cr))
1480     {
1481         if (bVerbose)
1482         {
1483             fprintf(stderr, "%s Opening output file %s%s\n", SwS, fn, bAppend ? " for appending" : "");
1484         }
1485
1486         s->fpout = gmx_fio_fopen(fn, bAppend ? "a" : "w" );
1487
1488         if (!bAppend)
1489         {
1490             xvgr_header(s->fpout, "Ion counts", "Time (ps)", "counts", exvggtXNY, oenv);
1491
1492             for (ig = 0; ig < eGrpNr; ig++)
1493             {
1494                 g = &(s->group[ig]);
1495                 fprintf(s->fpout, "# %s group contains %d atom%s", GrpString[ig], g->nat, (g->nat > 1) ? "s" : "");
1496                 if (eGrpSolvent == ig || eGrpIons == ig)
1497                 {
1498                     fprintf(s->fpout, " with %d atom%s in each molecule", g->apm, (g->apm > 1) ? "s" : "");
1499                 }
1500                 fprintf(s->fpout, ".\n");
1501             }
1502
1503             fprintf(s->fpout, "#\n# Initial positions of split groups:\n");
1504         }
1505
1506         for (j = 0, ig = eGrpSplit0; j < eChanNR; j++, ig++)
1507         {
1508             g = &(s->group[ig]);
1509             for (i = 0; i < g->nat; i++)
1510             {
1511                 copy_rvec(x[sc->ind_split[j][i]], g->xc[i]);
1512             }
1513             if (eGrpSplit0 == ig || eGrpSplit1 == ig)
1514             {
1515                 /* xc has the correct PBC representation for the two channels, so we do
1516                  * not need to correct for that */
1517                 get_center(g->xc, g->m, g->nat, g->center);
1518             }
1519             else
1520             {
1521                 /* For the water molecules, we need to make the molecules whole */
1522                 get_molecule_center(g->xc, g->nat, g->m, g->center, s->pbc);
1523             }
1524             if (!bAppend)
1525             {
1526                 fprintf(s->fpout, "# %s group %s-center %5f nm\n", GrpString[ig],
1527                         DimStr[s->swapdim], g->center[s->swapdim]);
1528             }
1529         }
1530
1531         if (!bAppend)
1532         {
1533             fprintf(s->fpout, "#\n");
1534             fprintf(s->fpout, "# split0 cylinder radius %f nm, up %f nm, down %f nm\n",
1535                     sc->cyl0r, sc->cyl0u, sc->cyl0l);
1536             fprintf(s->fpout, "# split1 cylinder radius %f nm, up %f nm, down %f nm\n",
1537                     sc->cyl1r, sc->cyl1u, sc->cyl1l);
1538         }
1539
1540         if (!bAppend)
1541         {
1542             fprintf(s->fpout, "#\n");
1543             if (!bRerun)
1544             {
1545                 fprintf(s->fpout, "# Coupling constant (number of swap attempt steps to average over): %d  (translates to %f ps).\n",
1546                         sc->nAverage, sc->nAverage*sc->nstswap*ir->delta_t);
1547                 fprintf(s->fpout, "# Threshold is %f\n", sc->threshold);
1548                 fprintf(s->fpout, "#\n");
1549                 fprintf(s->fpout, "# Remarks about which atoms passed which channel use global atoms numbers starting at one.\n");
1550             }
1551         }
1552     }
1553     else
1554     {
1555         s->fpout = NULL;
1556     }
1557
1558     /* Prepare for parallel or serial run */
1559     if (PAR(cr))
1560     {
1561         for (ig = 0; ig < eGrpNr; ig++)
1562         {
1563             g             = &(s->group[ig]);
1564             g->nat_loc    = 0;
1565             g->nalloc_loc = 0;
1566             g->ind_loc    = NULL;
1567         }
1568     }
1569     else
1570     {
1571         for (ig = 0; ig < eGrpNr; ig++)
1572         {
1573             g          = &(s->group[ig]);
1574             g->nat_loc = g->nat;
1575             g->ind_loc = g->ind;
1576             /* c_ind_loc needs to be set to identity in the serial case */
1577             for (i = 0; i < g->nat; i++)
1578             {
1579                 g->c_ind_loc[i] = i;
1580             }
1581         }
1582     }
1583
1584     /* Allocate memory for the ion counts time window */
1585     for (ic = 0; ic < eCompNR; ic++)
1586     {
1587         for (ii = 0; ii < eIonNR; ii++)
1588         {
1589             snew(s->comp[ic][ii].nat_past, sc->nAverage);
1590         }
1591     }
1592
1593     /* Get the initial ion concentrations and let the other nodes know */
1594     if (MASTER(cr))
1595     {
1596         swapstate->nions = s->group[eGrpIons].nat;
1597
1598         if (bStartFromCpt)
1599         {
1600             get_initial_ioncounts_from_cpt(ir, swapstate, cr, bVerbose);
1601         }
1602         else
1603         {
1604             fprintf(stderr, "%s Determining initial ion counts.\n", SwS);
1605             get_initial_ioncounts(ir, x, box, cr, bRerun);
1606         }
1607
1608         /* Prepare (further) checkpoint writes ... */
1609         if (bStartFromCpt)
1610         {
1611             /* Consistency check */
1612             if (swapstate->nAverage != sc->nAverage)
1613             {
1614                 gmx_fatal(FARGS, "%s Ion count averaging steps mismatch! checkpoint: %d, tpr: %d",
1615                           SwS, swapstate->nAverage, sc->nAverage);
1616             }
1617         }
1618         else
1619         {
1620             swapstate->nAverage = sc->nAverage;
1621         }
1622         fprintf(stderr, "%s Setting pointers for checkpoint writing\n", SwS);
1623         for (ic = 0; ic < eCompNR; ic++)
1624         {
1625             for (ii = 0; ii < eIonNR; ii++)
1626             {
1627                 swapstate->nat_req_p[ic][ii]      = &(s->comp[ic][ii].nat_req);
1628                 swapstate->nat_past_p[ic][ii]     = &(s->comp[ic][ii].nat_past[0]);
1629                 swapstate->inflow_netto_p[ic][ii] = &(s->comp[ic][ii].inflow_netto);
1630             }
1631         }
1632
1633         /* Determine the total charge imbalance */
1634         s->deltaQ =  ( (-1) * s->comp[eCompA][eIonNEG].nat_req + s->comp[eCompA][eIonPOS].nat_req )
1635             - ( (-1) * s->comp[eCompB][eIonNEG].nat_req + s->comp[eCompB][eIonPOS].nat_req );
1636
1637         if (bVerbose)
1638         {
1639             fprintf(stderr, "%s Requested charge imbalance is Q(A) - Q(B) = %gz.\n", SwS, s->deltaQ);
1640         }
1641         if (!bAppend)
1642         {
1643             fprintf(s->fpout, "# Requested charge imbalance is Q(A)-Q(B) = %gz.\n", s->deltaQ);
1644         }
1645     }
1646
1647     if (PAR(cr))
1648     {
1649         bc_initial_concentrations(cr, ir->swap);
1650     }
1651
1652     /* Put the time-averaged number of ions for all compartments */
1653     for (ic = 0; ic < eCompNR; ic++)
1654     {
1655         for (ii = 0; ii < eIonNR; ii++)
1656         {
1657             update_time_window(&(s->comp[ic][ii]), sc->nAverage, -1);
1658         }
1659     }
1660
1661     /* Initialize arrays that keep track of through which channel the ions go */
1662     detect_flux_per_channel_init(cr, s, swapstate, bStartFromCpt);
1663
1664     /* We need to print the legend if we open this file for the first time. */
1665     if (MASTER(cr) && !bAppend)
1666     {
1667         print_ionlist_legend(ir, oenv);
1668     }
1669 }
1670
1671
1672 extern void dd_make_local_swap_groups(gmx_domdec_t *dd, t_swapcoords *sc)
1673 {
1674     t_group *g;
1675     int      ig;
1676
1677
1678     /* Make ion group, split groups and solvent group */
1679     for (ig = 0; ig < eGrpNr; ig++)
1680     {
1681         g = &(sc->si_priv->group[ig]);
1682         dd_make_local_group_indices(dd->ga2la, g->nat, g->ind,
1683                                     &(g->nat_loc), &(g->ind_loc), &(g->nalloc_loc), g->c_ind_loc);
1684     }
1685 }
1686
1687
1688 /*! From the requested and average ion counts we determine whether a swap is needed
1689  * at this time step. */
1690 static gmx_bool need_swap(t_swapcoords *sc)
1691 {
1692     t_swap *s;
1693     int     ic, ii;
1694
1695
1696     s = sc->si_priv;
1697     for (ic = 0; ic < eCompNR; ic++)
1698     {
1699         for (ii = 0; ii < eIonNR; ii++)
1700         {
1701             if (s->comp[ic][ii].nat_req - s->comp[ic][ii].nat_av >= sc->threshold)
1702             {
1703                 return TRUE;
1704             }
1705         }
1706     }
1707     return FALSE;
1708 }
1709
1710
1711 /*! Returns the index of an atom that is far off the compartment boundaries.
1712  * Other atoms of the molecule (if any) will directly follow the returned index
1713  */
1714 static int get_index_of_distant_atom(
1715         t_compartment *comp,
1716         int            apm) /* Atoms per molecule - just return the first atom index of a molecule */
1717 {
1718     int  i, ibest = -1;
1719     real d = GMX_REAL_MAX;
1720
1721
1722     /* comp->nat contains the original number of atoms in this compartment
1723      * prior to doing any swaps. Some of these atoms may already have been
1724      * swapped out, but then they are marked with a distance of GMX_REAL_MAX
1725      */
1726     for (i = 0; i < comp->nat_old; i += apm)
1727     {
1728         if (comp->dist[i] < d)
1729         {
1730             ibest = i;
1731             d     = comp->dist[ibest];
1732         }
1733     }
1734
1735     if (ibest < 0)
1736     {
1737         gmx_fatal(FARGS, "Could not get index of swap atom. Compartment atoms %d before swaps, atoms per molecule %d.",
1738                   comp->nat_old, apm);
1739     }
1740
1741     /* Set the distance of this index to infinity such that it won't get selected again in
1742      * this time step
1743      */
1744     comp->dist[ibest] = GMX_REAL_MAX;
1745
1746     return comp->ind[ibest];
1747 }
1748
1749
1750 /*! Swaps centers of mass and makes molecule whole if broken */
1751 static void translate_positions(
1752         rvec  *x,
1753         int    apm,
1754         rvec   old_com,
1755         rvec   new_com,
1756         t_pbc *pbc)
1757 {
1758     int  i;
1759     rvec reference, dx, correctPBCimage;
1760
1761
1762     /* Use the first atom as the reference for PBC */
1763     copy_rvec(x[0], reference);
1764
1765     for (i = 0; i < apm; i++)
1766     {
1767         /* PBC distance between position and reference */
1768         pbc_dx(pbc, x[i], reference, dx);
1769
1770         /* Add PBC distance to reference */
1771         rvec_add(reference, dx, correctPBCimage);
1772
1773         /* Subtract old_com from correct image and add new_com */
1774         rvec_dec(correctPBCimage, old_com);
1775         rvec_inc(correctPBCimage, new_com);
1776
1777         copy_rvec(correctPBCimage, x[i]);
1778     }
1779 }
1780
1781
1782 /*! Write back the the modified local positions from the collective array to the official coordinates */
1783 static void apply_modified_positions(
1784         t_group *g,
1785         rvec     x[])
1786 {
1787     int l, ii, cind;
1788
1789
1790     for (l = 0; l < g->nat_loc; l++)
1791     {
1792         /* Get the right local index to write to */
1793         ii = g->ind_loc[l];
1794         /* Where is the local atom in the collective array? */
1795         cind = g->c_ind_loc[l];
1796
1797         /* Copy the possibly modified position */
1798         copy_rvec(g->xc[cind], x[ii]);
1799     }
1800 }
1801
1802
1803 extern gmx_bool do_swapcoords(
1804         t_commrec        *cr,
1805         gmx_int64_t       step,
1806         double            t,
1807         t_inputrec       *ir,
1808         gmx_wallcycle_t   wcycle,
1809         rvec              x[],
1810         matrix            box,
1811         gmx_mtop_t       *mtop,
1812         gmx_bool          bVerbose,
1813         gmx_bool          bRerun)
1814 {
1815     t_swapcoords         *sc;
1816     t_swap               *s;
1817     int                   j, ii, ic, ig, im, gmax, nswaps;
1818     gmx_bool              bSwap = FALSE;
1819     t_group              *g;
1820     real                  vacancy[eCompNR][eIonNR];
1821     int                   isol, iion;
1822     rvec                  solvent_center, ion_center;
1823     t_atom               *atom;
1824     gmx_mtop_atomlookup_t alook = NULL;
1825
1826
1827     wallcycle_start(wcycle, ewcSWAP);
1828
1829     sc  = ir->swap;
1830     s   = sc->si_priv;
1831
1832     /* Assemble all the positions of the swap group (ig = 0), the split groups
1833      * (ig = 1,2), and possibly the solvent group (ig = 3) */
1834     gmax = eGrpNr;
1835
1836     for (ig = 0; ig < gmax; ig++)
1837     {
1838         g = &(s->group[ig]);
1839         if (eGrpSplit0 == ig || eGrpSplit1 == ig)
1840         {
1841             /* The split groups, i.e. the channels. Here we need  the full
1842              * communicate_group_positions(), so that we can make the molecules
1843              * whole even in cases where they span more than half of the box in
1844              * any dimension */
1845             communicate_group_positions(cr, g->xc, g->xc_shifts, g->xc_eshifts, TRUE,
1846                                         x, g->nat, g->nat_loc, g->ind_loc, g->c_ind_loc, g->xc_old, box);
1847
1848             get_center(g->xc, g->m, g->nat, g->center); /* center of split groups == channels */
1849         }
1850         else
1851         {
1852             /* Swap group (ions), and solvent group. These molecules are small
1853              * and we can always make them whole with a simple distance check.
1854              * Therefore we pass NULL as third argument. */
1855             communicate_group_positions(cr, g->xc, NULL, NULL, FALSE,
1856                                         x, g->nat, g->nat_loc, g->ind_loc, g->c_ind_loc, NULL, NULL);
1857         }
1858     }
1859
1860     /* Set up the compartments and get lists of atoms in each compartment,
1861      * determine how many ions each compartment contains */
1862     compartmentalize_ions(cr, sc, box, step, s->fpout, bRerun);
1863
1864     /* Output how many ions are in the compartments */
1865     if (MASTER(cr))
1866     {
1867         print_ionlist(s, t, "");
1868     }
1869
1870     /* If we are doing a rerun, we are finished here, since we cannot perform
1871      * swaps anyway */
1872     if (bRerun)
1873     {
1874         return FALSE;
1875     }
1876
1877     /* Do we have to perform a swap? */
1878     bSwap = need_swap(sc);
1879     if (bSwap)
1880     {
1881         g = &(s->group[eGrpSolvent]);
1882         communicate_group_positions(cr, g->xc, NULL, NULL, FALSE,
1883                                     x, g->nat, g->nat_loc, g->ind_loc, g->c_ind_loc, NULL, NULL);
1884
1885         compartmentalize_solvent(cr, sc, box, s->fpout);
1886
1887         /* Determine where ions are missing and where ions are too many */
1888         for (ic = 0; ic < eCompNR; ic++)
1889         {
1890             for (ii = 0; ii < eIonNR; ii++)
1891             {
1892                 vacancy[ic][ii] = s->comp[ic][ii].nat_req - s->comp[ic][ii].nat_av;
1893             }
1894         }
1895
1896         /* Remember the original number of ions per compartment */
1897         for (ic = 0; ic < eCompNR; ic++)
1898         {
1899             s->compsol[ic].nat_old = s->compsol[ic].nat;
1900             for (ii = 0; ii < eIonNR; ii++)
1901             {
1902                 s->comp[ic][ii].nat_old = s->comp[ic][ii].nat;
1903             }
1904         }
1905
1906         /* Now actually correct the number of ions */
1907         g      = &(s->group[eGrpSolvent]);
1908         nswaps = 0;
1909         alook  = gmx_mtop_atomlookup_init(mtop);
1910         for (ic = 0; ic < eCompNR; ic++)
1911         {
1912             for (ii = 0; ii < eIonNR; ii++)
1913             {
1914                 while (vacancy[ic][ii] >= sc->threshold)
1915                 {
1916                     /* Swap in an ion */
1917
1918                     /* Get the xc-index of the first atom of a solvent molecule of this compartment */
1919                     isol = get_index_of_distant_atom(&(s->compsol[ic]), s->group[eGrpSolvent].apm );
1920
1921                     /* Get the xc-index of an ion from the other compartment */
1922                     iion = get_index_of_distant_atom(&(s->comp[(ic+1)%eCompNR][ii]), s->group[eGrpIons].apm );
1923
1924                     /* Get the solvent molecule's center of mass */
1925                     for (im = 0; im < s->group[eGrpSolvent].apm; im++)
1926                     {
1927                         gmx_mtop_atomnr_to_atom(alook, s->group[eGrpSolvent].ind[isol+im], &atom);
1928                         s->group[eGrpSolvent].m[im] = atom->m;
1929                     }
1930                     get_molecule_center(&(s->group[eGrpSolvent].xc[isol]), s->group[eGrpSolvent].apm, s->group[eGrpSolvent].m, solvent_center, s->pbc);
1931                     get_molecule_center(&(s->group[eGrpIons   ].xc[iion]), s->group[eGrpIons   ].apm, NULL, ion_center, s->pbc);
1932
1933                     /* subtract com_solvent and add com_ion */
1934                     translate_positions(&(s->group[eGrpSolvent].xc[isol]), s->group[eGrpSolvent].apm, solvent_center, ion_center, s->pbc);
1935                     /* For the ion, subtract com_ion and add com_solvent */
1936                     translate_positions(&(s->group[eGrpIons   ].xc[iion]), s->group[eGrpIons   ].apm, ion_center, solvent_center, s->pbc);
1937
1938                     vacancy[ic              ][ii]--;
1939                     vacancy[(ic+1) % eCompNR][ii]++;
1940
1941                     /* Keep track of the changes */
1942                     s->comp[ic              ][ii].nat++;
1943                     s->comp[(ic+1) % eCompNR][ii].nat--;
1944                     s->comp[ic              ][ii].inflow_netto++;
1945                     s->comp[(ic+1) % eCompNR][ii].inflow_netto--;
1946                     /* Correct the past time window to still get the right averages from now on */
1947                     s->comp[ic              ][ii].nat_av++;
1948                     s->comp[(ic+1) % eCompNR][ii].nat_av--;
1949                     for (j = 0; j < sc->nAverage; j++)
1950                     {
1951                         s->comp[ic              ][ii].nat_past[j]++;
1952                         s->comp[(ic+1) % eCompNR][ii].nat_past[j]--;
1953                     }
1954                     /* Clear ion history */
1955                     if (MASTER(cr))
1956                     {
1957                         s->group[eGrpIons].channel_label[iion] = eChHistPassedNone;
1958                         s->group[eGrpIons].comp_from[iion]     = eDomainNotset;
1959                     }
1960                     /* That was the swap */
1961                     nswaps++;
1962                 }
1963             }
1964         }
1965         gmx_mtop_atomlookup_destroy(alook);
1966
1967         if (bVerbose)
1968         {
1969             fprintf(stderr, "%s Performed %d swap%s in step %"GMX_PRId64 ".\n", SwS, nswaps, nswaps > 1 ? "s" : "", step);
1970         }
1971         if (s->fpout != NULL)
1972         {
1973             print_ionlist(s, t, "  # after swap");
1974         }
1975
1976         /* Write back the the modified local positions from the collective array to the official coordinates */
1977         apply_modified_positions(&(s->group[eGrpIons   ]), x);
1978         apply_modified_positions(&(s->group[eGrpSolvent]), x);
1979     } /* end of if(bSwap) */
1980
1981     wallcycle_stop(wcycle, ewcSWAP);
1982
1983     return bSwap;
1984 }