d6d41aae34494f8d4b30081a22363b0f20b608df
[alexxy/gromacs.git] / src / programs / mdrun / membed.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2010,2011,2012,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 #include "gmxpre.h"
36
37 #include "config.h"
38
39 #include <signal.h>
40 #include <stdlib.h>
41 #include "gromacs/legacyheaders/typedefs.h"
42 #include "gromacs/legacyheaders/types/commrec.h"
43 #include "gromacs/utility/smalloc.h"
44 #include "gromacs/math/vec.h"
45 #include "gromacs/legacyheaders/macros.h"
46 #include "gromacs/utility/futil.h"
47 #include "gromacs/essentialdynamics/edsam.h"
48 #include "gromacs/topology/index.h"
49 #include "gromacs/legacyheaders/names.h"
50 #include "gromacs/topology/mtop_util.h"
51 #include "gromacs/fileio/tpxio.h"
52 #include "gromacs/utility/cstringutil.h"
53 #include "membed.h"
54 #include "gromacs/pbcutil/pbc.h"
55 #include "gromacs/legacyheaders/readinp.h"
56 #include "gromacs/gmxpreprocess/readir.h"
57
58 /* information about scaling center */
59 typedef struct {
60     rvec      xmin;       /* smallest coordinates of all embedded molecules */
61     rvec      xmax;       /* largest coordinates of all embedded molecules */
62     rvec     *geom_cent;  /* scaling center of each independent molecule to embed */
63     int       pieces;     /* number of molecules to embed independently */
64     int      *nidx;       /* n atoms for every independent embedded molecule (index in subindex) */
65     atom_id **subindex;   /* atomids for independent molecule *
66                            * atoms of piece i run from subindex[i][0] to subindex[i][nidx[i]] */
67 } pos_ins_t;
68
69 /* variables needed in do_md */
70 struct membed {
71     int        it_xy;     /* number of iterations (steps) used to grow something in the xy-plane */
72     int        it_z;      /* same, but for z */
73     real       xy_step;   /* stepsize used during resize in xy-plane */
74     real       z_step;    /* same, but in z */
75     rvec       fac;       /* initial scaling of the molecule to grow into the membrane */
76     rvec      *r_ins;     /* final coordinates of the molecule to grow  */
77     pos_ins_t *pos_ins;   /* scaling center for each piece to embed */
78 };
79
80 /* membrane related variables */
81 typedef struct {
82     char      *name;     /* name of index group to embed molecule into (usually membrane) */
83     t_block    mem_at;   /* list all atoms in membrane */
84     int        nmol;     /* number of membrane molecules overlapping with the molecule to embed */
85     int       *mol_id;   /* list of molecules in membrane that overlap with the molecule to embed */
86     real       lip_area; /* average area per lipid in membrane (only correct for homogeneous bilayers)*/
87     real       zmin;     /* minimum z coordinate of membrane */
88     real       zmax;     /* maximum z coordinate of membrane */
89     real       zmed;     /* median z coordinate of membrane */
90 } mem_t;
91
92 /* Lists all molecules in the membrane that overlap with the molecule to be embedded. *
93  * These will then be removed from the system */
94 typedef struct {
95     int   nr;     /* number of molecules to remove */
96     int  *mol;    /* list of molecule ids to remove */
97     int  *block;  /* id of the molblock that the molecule to remove is part of */
98 } rm_t;
99
100 /* Get the global molecule id, and the corresponding molecule type and id of the *
101  * molblock from the global atom nr. */
102 static int get_mol_id(int at, gmx_mtop_t  *mtop, int *type, int *block)
103 {
104     int                   mol_id = 0;
105     int                   i;
106     int                   atnr_mol;
107     gmx_mtop_atomlookup_t alook;
108
109     alook = gmx_mtop_atomlookup_settle_init(mtop);
110     gmx_mtop_atomnr_to_molblock_ind(alook, at, block, &mol_id, &atnr_mol);
111     for (i = 0; i < *block; i++)
112     {
113         mol_id += mtop->molblock[i].nmol;
114     }
115     *type = mtop->molblock[*block].type;
116
117     gmx_mtop_atomlookup_destroy(alook);
118
119     return mol_id;
120 }
121
122 /* Get the id of the molblock from a global molecule id */
123 static int get_molblock(int mol_id, int nmblock, gmx_molblock_t *mblock)
124 {
125     int i;
126     int nmol = 0;
127
128     for (i = 0; i < nmblock; i++)
129     {
130         nmol += mblock[i].nmol;
131         if (mol_id < nmol)
132         {
133             return i;
134         }
135     }
136
137     gmx_fatal(FARGS, "mol_id %d larger than total number of molecules %d.\n", mol_id, nmol);
138
139     return -1;
140 }
141
142 static int get_tpr_version(const char *infile)
143 {
144     t_tpxheader  header;
145     int          version, generation;
146
147     read_tpxheader(infile, &header, TRUE, &version, &generation);
148
149     return version;
150 }
151
152 /* Get a list of all the molecule types that are present in a group of atoms. *
153  * Because all interaction within the group to embed are removed on the topology *
154  * level, if the same molecule type is found in another part of the system, these *
155  * would also be affected. Therefore we have to check if the embedded and rest group *
156  * share common molecule types. If so, membed will stop with an error. */
157 static int get_mtype_list(t_block *at, gmx_mtop_t *mtop, t_block *tlist)
158 {
159     int      i, j, nr, mol_id;
160     int      type = 0, block = 0;
161     gmx_bool bNEW;
162
163     nr = 0;
164     snew(tlist->index, at->nr);
165     for (i = 0; i < at->nr; i++)
166     {
167         bNEW   = TRUE;
168         mol_id = get_mol_id(at->index[i], mtop, &type, &block);
169         for (j = 0; j < nr; j++)
170         {
171             if (tlist->index[j] == type)
172             {
173                 bNEW = FALSE;
174             }
175         }
176
177         if (bNEW == TRUE)
178         {
179             tlist->index[nr] = type;
180             nr++;
181         }
182     }
183     srenew(tlist->index, nr);
184     return nr;
185 }
186
187 /* Do the actual check of the molecule types between embedded and rest group */
188 static void check_types(t_block *ins_at, t_block *rest_at, gmx_mtop_t *mtop)
189 {
190     t_block        *ins_mtype, *rest_mtype;
191     int             i, j;
192
193     snew(ins_mtype, 1);
194     snew(rest_mtype, 1);
195     ins_mtype->nr  = get_mtype_list(ins_at, mtop, ins_mtype );
196     rest_mtype->nr = get_mtype_list(rest_at, mtop, rest_mtype);
197
198     for (i = 0; i < ins_mtype->nr; i++)
199     {
200         for (j = 0; j < rest_mtype->nr; j++)
201         {
202             if (ins_mtype->index[i] == rest_mtype->index[j])
203             {
204                 gmx_fatal(FARGS, "Moleculetype %s is found both in the group to insert and the rest of the system.\n"
205                           "1. Your *.ndx and *.top do not match\n"
206                           "2. You are inserting some molecules of type %s (for example xray-solvent), while\n"
207                           "the same moleculetype is also used in the rest of the system (solvent box). Because\n"
208                           "we need to exclude all interactions between the atoms in the group to\n"
209                           "insert, the same moleculetype can not be used in both groups. Change the\n"
210                           "moleculetype of the molecules %s in the inserted group. Do not forget to provide\n"
211                           "an appropriate *.itp file", *(mtop->moltype[rest_mtype->index[j]].name),
212                           *(mtop->moltype[rest_mtype->index[j]].name), *(mtop->moltype[rest_mtype->index[j]].name));
213             }
214         }
215     }
216
217     sfree(ins_mtype->index);
218     sfree(rest_mtype->index);
219     sfree(ins_mtype);
220     sfree(rest_mtype);
221 }
222
223 static void get_input(const char *membed_input, real *xy_fac, real *xy_max, real *z_fac, real *z_max,
224                       int *it_xy, int *it_z, real *probe_rad, int *low_up_rm, int *maxwarn,
225                       int *pieces, gmx_bool *bALLOW_ASYMMETRY)
226 {
227     warninp_t  wi;
228     t_inpfile *inp;
229     int        ninp;
230
231     wi = init_warning(TRUE, 0);
232
233     inp = read_inpfile(membed_input, &ninp, wi);
234     ITYPE ("nxy", *it_xy, 1000);
235     ITYPE ("nz", *it_z, 0);
236     RTYPE ("xyinit", *xy_fac, 0.5);
237     RTYPE ("xyend", *xy_max, 1.0);
238     RTYPE ("zinit", *z_fac, 1.0);
239     RTYPE ("zend", *z_max, 1.0);
240     RTYPE ("rad", *probe_rad, 0.22);
241     ITYPE ("ndiff", *low_up_rm, 0);
242     ITYPE ("maxwarn", *maxwarn, 0);
243     ITYPE ("pieces", *pieces, 1);
244     EETYPE("asymmetry", *bALLOW_ASYMMETRY, yesno_names);
245
246     write_inpfile(membed_input, ninp, inp, FALSE, wi);
247 }
248
249 /* Obtain the maximum and minimum coordinates of the group to be embedded */
250 static int init_ins_at(t_block *ins_at, t_block *rest_at, t_state *state, pos_ins_t *pos_ins,
251                        gmx_groups_t *groups, int ins_grp_id, real xy_max)
252 {
253     int        i, gid, c = 0;
254     real       x, xmin, xmax, y, ymin, ymax, z, zmin, zmax;
255     const real min_memthick = 6.0;      /* minimum thickness of the bilayer that will be used to *
256                                          * determine the overlap between molecule to embed and membrane */
257     const real fac_inp_size = 1.000001; /* scaling factor to obtain input_size + 0.000001 (comparing reals) */
258     snew(rest_at->index, state->natoms);
259
260     xmin = xmax = state->x[ins_at->index[0]][XX];
261     ymin = ymax = state->x[ins_at->index[0]][YY];
262     zmin = zmax = state->x[ins_at->index[0]][ZZ];
263
264     for (i = 0; i < state->natoms; i++)
265     {
266         gid = groups->grpnr[egcFREEZE][i];
267         if (groups->grps[egcFREEZE].nm_ind[gid] == ins_grp_id)
268         {
269             x = state->x[i][XX];
270             if (x < xmin)
271             {
272                 xmin = x;
273             }
274             if (x > xmax)
275             {
276                 xmax = x;
277             }
278             y = state->x[i][YY];
279             if (y < ymin)
280             {
281                 ymin = y;
282             }
283             if (y > ymax)
284             {
285                 ymax = y;
286             }
287             z = state->x[i][ZZ];
288             if (z < zmin)
289             {
290                 zmin = z;
291             }
292             if (z > zmax)
293             {
294                 zmax = z;
295             }
296         }
297         else
298         {
299             rest_at->index[c] = i;
300             c++;
301         }
302     }
303
304     rest_at->nr = c;
305     srenew(rest_at->index, c);
306
307     if (xy_max > fac_inp_size)
308     {
309         pos_ins->xmin[XX] = xmin-((xmax-xmin)*xy_max-(xmax-xmin))/2;
310         pos_ins->xmin[YY] = ymin-((ymax-ymin)*xy_max-(ymax-ymin))/2;
311
312         pos_ins->xmax[XX] = xmax+((xmax-xmin)*xy_max-(xmax-xmin))/2;
313         pos_ins->xmax[YY] = ymax+((ymax-ymin)*xy_max-(ymax-ymin))/2;
314     }
315     else
316     {
317         pos_ins->xmin[XX] = xmin;
318         pos_ins->xmin[YY] = ymin;
319
320         pos_ins->xmax[XX] = xmax;
321         pos_ins->xmax[YY] = ymax;
322     }
323
324     if ( (zmax-zmin) < min_memthick)
325     {
326         pos_ins->xmin[ZZ] = zmin+(zmax-zmin)/2.0-0.5*min_memthick;
327         pos_ins->xmax[ZZ] = zmin+(zmax-zmin)/2.0+0.5*min_memthick;
328     }
329     else
330     {
331         pos_ins->xmin[ZZ] = zmin;
332         pos_ins->xmax[ZZ] = zmax;
333     }
334
335     return c;
336 }
337
338 /* Estimate the area of the embedded molecule by projecting all coordinates on a grid in the *
339  * xy-plane and counting the number of occupied grid points */
340 static real est_prot_area(pos_ins_t *pos_ins, rvec *r, t_block *ins_at, mem_t *mem_p)
341 {
342     real x, y, dx = 0.15, dy = 0.15, area = 0.0;
343     real add, memmin, memmax;
344     int  c, at;
345
346     /* min and max membrane coordinate are altered to reduce the influence of the *
347      * boundary region */
348     memmin = mem_p->zmin+0.1*(mem_p->zmax-mem_p->zmin);
349     memmax = mem_p->zmax-0.1*(mem_p->zmax-mem_p->zmin);
350
351     for (x = pos_ins->xmin[XX]; x < pos_ins->xmax[XX]; x += dx)
352     {
353         for (y = pos_ins->xmin[YY]; y < pos_ins->xmax[YY]; y += dy)
354         {
355             c   = 0;
356             add = 0.0;
357             do
358             {
359                 at = ins_at->index[c];
360                 if ( (r[at][XX] >= x) && (r[at][XX] < x+dx) &&
361                      (r[at][YY] >= y) && (r[at][YY] < y+dy) &&
362                      (r[at][ZZ] > memmin) && (r[at][ZZ] < memmax) )
363                 {
364                     add = 1.0;
365                 }
366                 c++;
367             }
368             while ( (c < ins_at->nr) && (add < 0.5) );
369             area += add;
370         }
371     }
372     area = area*dx*dy;
373
374     return area;
375 }
376
377 static int init_mem_at(mem_t *mem_p, gmx_mtop_t *mtop, rvec *r, matrix box, pos_ins_t *pos_ins)
378 {
379     int      i, j, at, mol, nmol, nmolbox, count;
380     t_block *mem_a;
381     real     z, zmin, zmax, mem_area;
382     gmx_bool bNew;
383     atom_id *mol_id;
384     int      type = 0, block = 0;
385
386     nmol  = count = 0;
387     mem_a = &(mem_p->mem_at);
388     snew(mol_id, mem_a->nr);
389     zmin = pos_ins->xmax[ZZ];
390     zmax = pos_ins->xmin[ZZ];
391     for (i = 0; i < mem_a->nr; i++)
392     {
393         at = mem_a->index[i];
394         if ( (r[at][XX] > pos_ins->xmin[XX]) && (r[at][XX] < pos_ins->xmax[XX]) &&
395              (r[at][YY] > pos_ins->xmin[YY]) && (r[at][YY] < pos_ins->xmax[YY]) &&
396              (r[at][ZZ] > pos_ins->xmin[ZZ]) && (r[at][ZZ] < pos_ins->xmax[ZZ]) )
397         {
398             mol  = get_mol_id(at, mtop, &type, &block);
399             bNew = TRUE;
400             for (j = 0; j < nmol; j++)
401             {
402                 if (mol == mol_id[j])
403                 {
404                     bNew = FALSE;
405                 }
406             }
407
408             if (bNew)
409             {
410                 mol_id[nmol] = mol;
411                 nmol++;
412             }
413
414             z = r[at][ZZ];
415             if (z < zmin)
416             {
417                 zmin = z;
418             }
419
420             if (z > zmax)
421             {
422                 zmax = z;
423             }
424
425             count++;
426         }
427     }
428
429     mem_p->nmol = nmol;
430     srenew(mol_id, nmol);
431     mem_p->mol_id = mol_id;
432
433     if ((zmax-zmin) > (box[ZZ][ZZ]-0.5))
434     {
435         gmx_fatal(FARGS, "Something is wrong with your membrane. Max and min z values are %f and %f.\n"
436                   "Maybe your membrane is not centered in the box, but located at the box edge in the z-direction,\n"
437                   "so that one membrane is distributed over two periodic box images. Another possibility is that\n"
438                   "your water layer is not thick enough.\n", zmax, zmin);
439     }
440     mem_p->zmin = zmin;
441     mem_p->zmax = zmax;
442     mem_p->zmed = (zmax-zmin)/2+zmin;
443
444     /*number of membrane molecules in protein box*/
445     nmolbox = count/mtop->molblock[block].natoms_mol;
446     /*membrane area within the box defined by the min and max coordinates of the embedded molecule*/
447     mem_area = (pos_ins->xmax[XX]-pos_ins->xmin[XX])*(pos_ins->xmax[YY]-pos_ins->xmin[YY]);
448     /*rough estimate of area per lipid, assuming there is only one type of lipid in the membrane*/
449     mem_p->lip_area = 2.0*mem_area/(double)nmolbox;
450
451     return mem_p->mem_at.nr;
452 }
453
454 static void init_resize(t_block *ins_at, rvec *r_ins, pos_ins_t *pos_ins, mem_t *mem_p, rvec *r,
455                         gmx_bool bALLOW_ASYMMETRY)
456 {
457     int i, j, at, c, outsidesum, gctr = 0;
458     int idxsum = 0;
459
460     /*sanity check*/
461     for (i = 0; i < pos_ins->pieces; i++)
462     {
463         idxsum += pos_ins->nidx[i];
464     }
465
466     if (idxsum != ins_at->nr)
467     {
468         gmx_fatal(FARGS, "Piecewise sum of inserted atoms not same as size of group selected to insert.");
469     }
470
471     snew(pos_ins->geom_cent, pos_ins->pieces);
472     for (i = 0; i < pos_ins->pieces; i++)
473     {
474         c          = 0;
475         outsidesum = 0;
476         for (j = 0; j < DIM; j++)
477         {
478             pos_ins->geom_cent[i][j] = 0;
479         }
480
481         for (j = 0; j < pos_ins->nidx[i]; j++)
482         {
483             at = pos_ins->subindex[i][j];
484             copy_rvec(r[at], r_ins[gctr]);
485             if ( (r_ins[gctr][ZZ] < mem_p->zmax) && (r_ins[gctr][ZZ] > mem_p->zmin) )
486             {
487                 rvec_inc(pos_ins->geom_cent[i], r_ins[gctr]);
488                 c++;
489             }
490             else
491             {
492                 outsidesum++;
493             }
494             gctr++;
495         }
496
497         if (c > 0)
498         {
499             svmul(1/(double)c, pos_ins->geom_cent[i], pos_ins->geom_cent[i]);
500         }
501
502         if (!bALLOW_ASYMMETRY)
503         {
504             pos_ins->geom_cent[i][ZZ] = mem_p->zmed;
505         }
506
507         fprintf(stderr, "Embedding piece %d with center of geometry: %f %f %f\n",
508                 i, pos_ins->geom_cent[i][XX], pos_ins->geom_cent[i][YY], pos_ins->geom_cent[i][ZZ]);
509     }
510     fprintf(stderr, "\n");
511 }
512
513 /* resize performed in the md loop */
514 static void resize(rvec *r_ins, rvec *r, pos_ins_t *pos_ins, rvec fac)
515 {
516     int i, j, k, at, c = 0;
517     for (k = 0; k < pos_ins->pieces; k++)
518     {
519         for (i = 0; i < pos_ins->nidx[k]; i++)
520         {
521             at = pos_ins->subindex[k][i];
522             for (j = 0; j < DIM; j++)
523             {
524                 r[at][j] = pos_ins->geom_cent[k][j]+fac[j]*(r_ins[c][j]-pos_ins->geom_cent[k][j]);
525             }
526             c++;
527         }
528     }
529 }
530
531 /* generate the list of membrane molecules that overlap with the molecule to be embedded. *
532  * The molecule to be embedded is already reduced in size. */
533 static int gen_rm_list(rm_t *rm_p, t_block *ins_at, t_block *rest_at, t_pbc *pbc, gmx_mtop_t *mtop,
534                        rvec *r, mem_t *mem_p, pos_ins_t *pos_ins, real probe_rad,
535                        int low_up_rm, gmx_bool bALLOW_ASYMMETRY)
536 {
537     int      i, j, k, l, at, at2, mol_id;
538     int      type = 0, block = 0;
539     int      nrm, nupper, nlower;
540     real     r_min_rad, z_lip, min_norm;
541     gmx_bool bRM;
542     rvec     dr, dr_tmp;
543     real    *dist;
544     int     *order;
545
546     r_min_rad = probe_rad*probe_rad;
547     snew(rm_p->mol, mtop->mols.nr);
548     snew(rm_p->block, mtop->mols.nr);
549     nrm    = nupper = 0;
550     nlower = low_up_rm;
551     for (i = 0; i < ins_at->nr; i++)
552     {
553         at = ins_at->index[i];
554         for (j = 0; j < rest_at->nr; j++)
555         {
556             at2 = rest_at->index[j];
557             pbc_dx(pbc, r[at], r[at2], dr);
558
559             if (norm2(dr) < r_min_rad)
560             {
561                 mol_id = get_mol_id(at2, mtop, &type, &block);
562                 bRM    = TRUE;
563                 for (l = 0; l < nrm; l++)
564                 {
565                     if (rm_p->mol[l] == mol_id)
566                     {
567                         bRM = FALSE;
568                     }
569                 }
570
571                 if (bRM)
572                 {
573                     rm_p->mol[nrm]   = mol_id;
574                     rm_p->block[nrm] = block;
575                     nrm++;
576                     z_lip = 0.0;
577                     for (l = 0; l < mem_p->nmol; l++)
578                     {
579                         if (mol_id == mem_p->mol_id[l])
580                         {
581                             for (k = mtop->mols.index[mol_id]; k < mtop->mols.index[mol_id+1]; k++)
582                             {
583                                 z_lip += r[k][ZZ];
584                             }
585                             z_lip /= mtop->molblock[block].natoms_mol;
586                             if (z_lip < mem_p->zmed)
587                             {
588                                 nlower++;
589                             }
590                             else
591                             {
592                                 nupper++;
593                             }
594                         }
595                     }
596                 }
597             }
598         }
599     }
600
601     /*make sure equal number of lipids from upper and lower layer are removed */
602     if ( (nupper != nlower) && (!bALLOW_ASYMMETRY) )
603     {
604         snew(dist, mem_p->nmol);
605         snew(order, mem_p->nmol);
606         for (i = 0; i < mem_p->nmol; i++)
607         {
608             at = mtop->mols.index[mem_p->mol_id[i]];
609             pbc_dx(pbc, r[at], pos_ins->geom_cent[0], dr);
610             if (pos_ins->pieces > 1)
611             {
612                 /*minimum dr value*/
613                 min_norm = norm2(dr);
614                 for (k = 1; k < pos_ins->pieces; k++)
615                 {
616                     pbc_dx(pbc, r[at], pos_ins->geom_cent[k], dr_tmp);
617                     if (norm2(dr_tmp) < min_norm)
618                     {
619                         min_norm = norm2(dr_tmp);
620                         copy_rvec(dr_tmp, dr);
621                     }
622                 }
623             }
624             dist[i] = dr[XX]*dr[XX]+dr[YY]*dr[YY];
625             j       = i-1;
626             while (j >= 0 && dist[i] < dist[order[j]])
627             {
628                 order[j+1] = order[j];
629                 j--;
630             }
631             order[j+1] = i;
632         }
633
634         i = 0;
635         while (nupper != nlower)
636         {
637             mol_id = mem_p->mol_id[order[i]];
638             block  = get_molblock(mol_id, mtop->nmolblock, mtop->molblock);
639             bRM    = TRUE;
640             for (l = 0; l < nrm; l++)
641             {
642                 if (rm_p->mol[l] == mol_id)
643                 {
644                     bRM = FALSE;
645                 }
646             }
647
648             if (bRM)
649             {
650                 z_lip = 0;
651                 for (k = mtop->mols.index[mol_id]; k < mtop->mols.index[mol_id+1]; k++)
652                 {
653                     z_lip += r[k][ZZ];
654                 }
655                 z_lip /= mtop->molblock[block].natoms_mol;
656                 if (nupper > nlower && z_lip < mem_p->zmed)
657                 {
658                     rm_p->mol[nrm]   = mol_id;
659                     rm_p->block[nrm] = block;
660                     nrm++;
661                     nlower++;
662                 }
663                 else if (nupper < nlower && z_lip > mem_p->zmed)
664                 {
665                     rm_p->mol[nrm]   = mol_id;
666                     rm_p->block[nrm] = block;
667                     nrm++;
668                     nupper++;
669                 }
670             }
671             i++;
672
673             if (i > mem_p->nmol)
674             {
675                 gmx_fatal(FARGS, "Trying to remove more lipid molecules than there are in the membrane");
676             }
677         }
678         sfree(dist);
679         sfree(order);
680     }
681
682     rm_p->nr = nrm;
683     srenew(rm_p->mol, nrm);
684     srenew(rm_p->block, nrm);
685
686     return nupper+nlower;
687 }
688
689 /*remove all lipids and waters overlapping and update all important structures (e.g. state and mtop)*/
690 static void rm_group(gmx_groups_t *groups, gmx_mtop_t *mtop, rm_t *rm_p, t_state *state,
691                      t_block *ins_at, pos_ins_t *pos_ins)
692 {
693     int             i, j, k, n, rm, mol_id, at, block;
694     rvec           *x_tmp, *v_tmp;
695     atom_id        *list, *new_mols;
696     unsigned char  *new_egrp[egcNR];
697     gmx_bool        bRM;
698     int             RMmolblock;
699
700     snew(list, state->natoms);
701     n = 0;
702     for (i = 0; i < rm_p->nr; i++)
703     {
704         mol_id = rm_p->mol[i];
705         at     = mtop->mols.index[mol_id];
706         block  = rm_p->block[i];
707         mtop->molblock[block].nmol--;
708         for (j = 0; j < mtop->molblock[block].natoms_mol; j++)
709         {
710             list[n] = at+j;
711             n++;
712         }
713         mtop->mols.index[mol_id] = -1;
714     }
715
716     mtop->mols.nr           -= rm_p->nr;
717     mtop->mols.nalloc_index -= rm_p->nr;
718     snew(new_mols, mtop->mols.nr);
719     for (i = 0; i < mtop->mols.nr+rm_p->nr; i++)
720     {
721         j = 0;
722         if (mtop->mols.index[i] != -1)
723         {
724             new_mols[j] = mtop->mols.index[i];
725             j++;
726         }
727     }
728     sfree(mtop->mols.index);
729     mtop->mols.index = new_mols;
730     mtop->natoms    -= n;
731     state->natoms   -= n;
732     state->nalloc    = state->natoms;
733     snew(x_tmp, state->nalloc);
734     snew(v_tmp, state->nalloc);
735
736     for (i = 0; i < egcNR; i++)
737     {
738         if (groups->grpnr[i] != NULL)
739         {
740             groups->ngrpnr[i] = state->natoms;
741             snew(new_egrp[i], state->natoms);
742         }
743     }
744
745     rm = 0;
746     for (i = 0; i < state->natoms+n; i++)
747     {
748         bRM = FALSE;
749         for (j = 0; j < n; j++)
750         {
751             if (i == list[j])
752             {
753                 bRM = TRUE;
754                 rm++;
755             }
756         }
757
758         if (!bRM)
759         {
760             for (j = 0; j < egcNR; j++)
761             {
762                 if (groups->grpnr[j] != NULL)
763                 {
764                     new_egrp[j][i-rm] = groups->grpnr[j][i];
765                 }
766             }
767             copy_rvec(state->x[i], x_tmp[i-rm]);
768             copy_rvec(state->v[i], v_tmp[i-rm]);
769             for (j = 0; j < ins_at->nr; j++)
770             {
771                 if (i == ins_at->index[j])
772                 {
773                     ins_at->index[j] = i-rm;
774                 }
775             }
776
777             for (j = 0; j < pos_ins->pieces; j++)
778             {
779                 for (k = 0; k < pos_ins->nidx[j]; k++)
780                 {
781                     if (i == pos_ins->subindex[j][k])
782                     {
783                         pos_ins->subindex[j][k] = i-rm;
784                     }
785                 }
786             }
787         }
788     }
789     sfree(state->x);
790     state->x = x_tmp;
791     sfree(state->v);
792     state->v = v_tmp;
793
794     for (i = 0; i < egcNR; i++)
795     {
796         if (groups->grpnr[i] != NULL)
797         {
798             sfree(groups->grpnr[i]);
799             groups->grpnr[i] = new_egrp[i];
800         }
801     }
802
803     /* remove empty molblocks */
804     RMmolblock = 0;
805     for (i = 0; i < mtop->nmolblock; i++)
806     {
807         if (mtop->molblock[i].nmol == 0)
808         {
809             RMmolblock++;
810         }
811         else
812         {
813             mtop->molblock[i-RMmolblock] = mtop->molblock[i];
814         }
815     }
816     mtop->nmolblock -= RMmolblock;
817 }
818
819 /* remove al bonded interactions from mtop for the molecule to be embedded */
820 int rm_bonded(t_block *ins_at, gmx_mtop_t *mtop)
821 {
822     int       i, j, m;
823     int       type, natom, nmol, at, atom1 = 0, rm_at = 0;
824     gmx_bool *bRM, bINS;
825     /*this routine lives dangerously by assuming that all molecules of a given type are in order in the structure*/
826     /*this routine does not live as dangerously as it seems. There is namely a check in init_membed to make *
827      * sure that g_membed exits with a warning when there are molecules of the same type not in the *
828      * ins_at index group. MGWolf 050710 */
829
830
831     snew(bRM, mtop->nmoltype);
832     for (i = 0; i < mtop->nmoltype; i++)
833     {
834         bRM[i] = TRUE;
835     }
836
837     for (i = 0; i < mtop->nmolblock; i++)
838     {
839         /*loop over molecule blocks*/
840         type         = mtop->molblock[i].type;
841         natom        = mtop->molblock[i].natoms_mol;
842         nmol         = mtop->molblock[i].nmol;
843
844         for (j = 0; j < natom*nmol && bRM[type] == TRUE; j++)
845         {
846             /*loop over atoms in the block*/
847             at   = j+atom1; /*atom index = block index + offset*/
848             bINS = FALSE;
849
850             for (m = 0; (m < ins_at->nr) && (bINS == FALSE); m++)
851             {
852                 /*loop over atoms in insertion index group to determine if we're inserting one*/
853                 if (at == ins_at->index[m])
854                 {
855                     bINS = TRUE;
856                 }
857             }
858             bRM[type] = bINS;
859         }
860         atom1 += natom*nmol; /*update offset*/
861         if (bRM[type])
862         {
863             rm_at += natom*nmol; /*increment bonded removal counter by # atoms in block*/
864         }
865     }
866
867     for (i = 0; i < mtop->nmoltype; i++)
868     {
869         if (bRM[i])
870         {
871             for (j = 0; j < F_LJ; j++)
872             {
873                 mtop->moltype[i].ilist[j].nr = 0;
874             }
875
876             for (j = F_POSRES; j <= F_VSITEN; j++)
877             {
878                 mtop->moltype[i].ilist[j].nr = 0;
879             }
880         }
881     }
882     sfree(bRM);
883
884     return rm_at;
885 }
886
887 /* Write a topology where the number of molecules is correct for the system after embedding */
888 static void top_update(const char *topfile, rm_t *rm_p, gmx_mtop_t *mtop)
889 {
890 #define TEMP_FILENM "temp.top"
891     int        bMolecules = 0;
892     FILE      *fpin, *fpout;
893     char       buf[STRLEN], buf2[STRLEN], *temp;
894     int        i, *nmol_rm, nmol, line;
895
896     fpin  = gmx_ffopen(topfile, "r");
897     fpout = gmx_ffopen(TEMP_FILENM, "w");
898
899     snew(nmol_rm, mtop->nmoltype);
900     for (i = 0; i < rm_p->nr; i++)
901     {
902         nmol_rm[rm_p->block[i]]++;
903     }
904
905     line = 0;
906     while (fgets(buf, STRLEN, fpin))
907     {
908         line++;
909         if (buf[0] != ';')
910         {
911             strcpy(buf2, buf);
912             if ((temp = strchr(buf2, '\n')) != NULL)
913             {
914                 temp[0] = '\0';
915             }
916             ltrim(buf2);
917             if (buf2[0] == '[')
918             {
919                 buf2[0] = ' ';
920                 if ((temp = strchr(buf2, '\n')) != NULL)
921                 {
922                     temp[0] = '\0';
923                 }
924                 rtrim(buf2);
925                 if (buf2[strlen(buf2)-1] == ']')
926                 {
927                     buf2[strlen(buf2)-1] = '\0';
928                     ltrim(buf2);
929                     rtrim(buf2);
930                     if (gmx_strcasecmp(buf2, "molecules") == 0)
931                     {
932                         bMolecules = 1;
933                     }
934                 }
935                 fprintf(fpout, "%s", buf);
936             }
937             else if (bMolecules == 1)
938             {
939                 for (i = 0; i < mtop->nmolblock; i++)
940                 {
941                     nmol = mtop->molblock[i].nmol;
942                     sprintf(buf, "%-15s %5d\n", *(mtop->moltype[mtop->molblock[i].type].name), nmol);
943                     fprintf(fpout, "%s", buf);
944                 }
945                 bMolecules = 2;
946             }
947             else if (bMolecules == 2)
948             {
949                 /* print nothing */
950             }
951             else
952             {
953                 fprintf(fpout, "%s", buf);
954             }
955         }
956         else
957         {
958             fprintf(fpout, "%s", buf);
959         }
960     }
961
962     gmx_ffclose(fpout);
963     /* use gmx_ffopen to generate backup of topinout */
964     fpout = gmx_ffopen(topfile, "w");
965     gmx_ffclose(fpout);
966     rename(TEMP_FILENM, topfile);
967 #undef TEMP_FILENM
968 }
969
970 void rescale_membed(int step_rel, gmx_membed_t membed, rvec *x)
971 {
972     /* Set new positions for the group to embed */
973     if (step_rel <= membed->it_xy)
974     {
975         membed->fac[0] += membed->xy_step;
976         membed->fac[1] += membed->xy_step;
977     }
978     else if (step_rel <= (membed->it_xy+membed->it_z))
979     {
980         membed->fac[2] += membed->z_step;
981     }
982     resize(membed->r_ins, x, membed->pos_ins, membed->fac);
983 }
984
985 gmx_membed_t init_membed(FILE *fplog, int nfile, const t_filenm fnm[], gmx_mtop_t *mtop,
986                          t_inputrec *inputrec, t_state *state, t_commrec *cr, real *cpt)
987 {
988     char                     *ins, **gnames;
989     int                       i, rm_bonded_at, fr_id, fr_i = 0, tmp_id, warn = 0;
990     int                       ng, j, max_lip_rm, ins_grp_id, ins_nat, mem_nat, ntype, lip_rm, tpr_version;
991     real                      prot_area;
992     rvec                     *r_ins = NULL;
993     t_block                  *ins_at, *rest_at;
994     pos_ins_t                *pos_ins;
995     mem_t                    *mem_p;
996     rm_t                     *rm_p;
997     gmx_groups_t             *groups;
998     gmx_bool                  bExcl = FALSE;
999     t_atoms                   atoms;
1000     t_pbc                    *pbc;
1001     char                    **piecename = NULL;
1002     gmx_membed_t              membed    = NULL;
1003
1004     /* input variables */
1005     const char *membed_input;
1006     real        xy_fac           = 0.5;
1007     real        xy_max           = 1.0;
1008     real        z_fac            = 1.0;
1009     real        z_max            = 1.0;
1010     int         it_xy            = 1000;
1011     int         it_z             = 0;
1012     real        probe_rad        = 0.22;
1013     int         low_up_rm        = 0;
1014     int         maxwarn          = 0;
1015     int         pieces           = 1;
1016     gmx_bool    bALLOW_ASYMMETRY = FALSE;
1017
1018     /* sanity check constants */         /* Issue a warning when: */
1019     const int  membed_version = 58;        /* tpr version is smaller */
1020     const real min_probe_rad  = 0.2199999; /* A probe radius for overlap between embedded molecule *
1021                                             * and rest smaller than this value is probably too small */
1022     const real min_xy_init    = 0.0999999; /* the initial shrinking of the molecule to embed is smaller */
1023     const int  min_it_xy      = 1000;      /* the number of steps to embed in xy-plane is smaller */
1024     const int  min_it_z       = 100;       /* the number of steps to embed in z is smaller */
1025     const real prot_vs_box    = 7.5;       /* molecule to embed is large (more then prot_vs_box) with respect */
1026     const real box_vs_prot    = 50;        /* to the box size (less than box_vs_prot) */
1027
1028     snew(membed, 1);
1029     snew(ins_at, 1);
1030     snew(pos_ins, 1);
1031
1032     if (MASTER(cr))
1033     {
1034         /* get input data out membed file */
1035         membed_input = opt2fn("-membed", nfile, fnm);
1036         get_input(membed_input, &xy_fac, &xy_max, &z_fac, &z_max, &it_xy, &it_z, &probe_rad, &low_up_rm,
1037                   &maxwarn, &pieces, &bALLOW_ASYMMETRY);
1038
1039         tpr_version = get_tpr_version(ftp2fn(efTPX, nfile, fnm));
1040         if (tpr_version < membed_version)
1041         {
1042             gmx_fatal(FARGS, "Version of *.tpr file to old (%d). "
1043                       "Rerun grompp with GROMACS version 4.0.3 or newer.\n", tpr_version);
1044         }
1045
1046         if (!EI_DYNAMICS(inputrec->eI) )
1047         {
1048             gmx_input("Change integrator to a dynamics integrator in mdp file (e.g. md or sd).");
1049         }
1050
1051         if (PAR(cr))
1052         {
1053             gmx_input("Sorry, parallel g_membed is not yet fully functional.");
1054         }
1055
1056         if (*cpt >= 0)
1057         {
1058             fprintf(stderr, "\nSetting -cpt to -1, because embedding cannot be restarted from cpt-files.\n");
1059             *cpt = -1;
1060         }
1061         groups = &(mtop->groups);
1062         snew(gnames, groups->ngrpname);
1063         for (i = 0; i < groups->ngrpname; i++)
1064         {
1065             gnames[i] = *(groups->grpname[i]);
1066         }
1067
1068         atoms = gmx_mtop_global_atoms(mtop);
1069         snew(mem_p, 1);
1070         fprintf(stderr, "\nSelect a group to embed in the membrane:\n");
1071         get_index(&atoms, opt2fn_null("-mn", nfile, fnm), 1, &(ins_at->nr), &(ins_at->index), &ins);
1072         ins_grp_id = search_string(ins, groups->ngrpname, gnames);
1073         fprintf(stderr, "\nSelect a group to embed %s into (e.g. the membrane):\n", ins);
1074         get_index(&atoms, opt2fn_null("-mn", nfile, fnm), 1, &(mem_p->mem_at.nr), &(mem_p->mem_at.index), &(mem_p->name));
1075
1076         pos_ins->pieces = pieces;
1077         snew(pos_ins->nidx, pieces);
1078         snew(pos_ins->subindex, pieces);
1079         snew(piecename, pieces);
1080         if (pieces > 1)
1081         {
1082             fprintf(stderr, "\nSelect pieces to embed:\n");
1083             get_index(&atoms, opt2fn_null("-mn", nfile, fnm), pieces, pos_ins->nidx, pos_ins->subindex, piecename);
1084         }
1085         else
1086         {
1087             /*use whole embedded group*/
1088             snew(pos_ins->nidx, 1);
1089             snew(pos_ins->subindex, 1);
1090             pos_ins->nidx[0]     = ins_at->nr;
1091             pos_ins->subindex[0] = ins_at->index;
1092         }
1093
1094         if (probe_rad < min_probe_rad)
1095         {
1096             warn++;
1097             fprintf(stderr, "\nWarning %d:\nA probe radius (-rad) smaller than 0.2 nm can result "
1098                     "in overlap between waters and the group to embed, which will result "
1099                     "in Lincs errors etc.\n\n", warn);
1100         }
1101
1102         if (xy_fac < min_xy_init)
1103         {
1104             warn++;
1105             fprintf(stderr, "\nWarning %d:\nThe initial size of %s is probably too smal.\n\n", warn, ins);
1106         }
1107
1108         if (it_xy < min_it_xy)
1109         {
1110             warn++;
1111             fprintf(stderr, "\nWarning %d;\nThe number of steps used to grow the xy-coordinates of %s (%d)"
1112                     " is probably too small.\nIncrease -nxy or.\n\n", warn, ins, it_xy);
1113         }
1114
1115         if ( (it_z < min_it_z) && ( z_fac < 0.99999999 || z_fac > 1.0000001) )
1116         {
1117             warn++;
1118             fprintf(stderr, "\nWarning %d;\nThe number of steps used to grow the z-coordinate of %s (%d)"
1119                     " is probably too small.\nIncrease -nz or maxwarn.\n\n", warn, ins, it_z);
1120         }
1121
1122         if (it_xy+it_z > inputrec->nsteps)
1123         {
1124             warn++;
1125             fprintf(stderr, "\nWarning %d:\nThe number of growth steps (-nxy + -nz) is larger than the "
1126                     "number of steps in the tpr.\n\n", warn);
1127         }
1128
1129         fr_id = -1;
1130         if (inputrec->opts.ngfrz == 1)
1131         {
1132             gmx_fatal(FARGS, "You did not specify \"%s\" as a freezegroup.", ins);
1133         }
1134
1135         for (i = 0; i < inputrec->opts.ngfrz; i++)
1136         {
1137             tmp_id = mtop->groups.grps[egcFREEZE].nm_ind[i];
1138             if (ins_grp_id == tmp_id)
1139             {
1140                 fr_id = tmp_id;
1141                 fr_i  = i;
1142             }
1143         }
1144
1145         if (fr_id == -1)
1146         {
1147             gmx_fatal(FARGS, "\"%s\" not as freezegroup defined in the mdp-file.", ins);
1148         }
1149
1150         for (i = 0; i < DIM; i++)
1151         {
1152             if (inputrec->opts.nFreeze[fr_i][i] != 1)
1153             {
1154                 gmx_fatal(FARGS, "freeze dimensions for %s are not Y Y Y\n", ins);
1155             }
1156         }
1157
1158         ng = groups->grps[egcENER].nr;
1159         if (ng == 1)
1160         {
1161             gmx_input("No energy groups defined. This is necessary for energy exclusion in the freeze group");
1162         }
1163
1164         for (i = 0; i < ng; i++)
1165         {
1166             for (j = 0; j < ng; j++)
1167             {
1168                 if (inputrec->opts.egp_flags[ng*i+j] == EGP_EXCL)
1169                 {
1170                     bExcl = TRUE;
1171                     if ( (groups->grps[egcENER].nm_ind[i] != ins_grp_id) ||
1172                          (groups->grps[egcENER].nm_ind[j] != ins_grp_id) )
1173                     {
1174                         gmx_fatal(FARGS, "Energy exclusions \"%s\" and  \"%s\" do not match the group "
1175                                   "to embed \"%s\"", *groups->grpname[groups->grps[egcENER].nm_ind[i]],
1176                                   *groups->grpname[groups->grps[egcENER].nm_ind[j]], ins);
1177                     }
1178                 }
1179             }
1180         }
1181
1182         if (!bExcl)
1183         {
1184             gmx_input("No energy exclusion groups defined. This is necessary for energy exclusion in "
1185                       "the freeze group");
1186         }
1187
1188         /* Obtain the maximum and minimum coordinates of the group to be embedded */
1189         snew(rest_at, 1);
1190         ins_nat = init_ins_at(ins_at, rest_at, state, pos_ins, groups, ins_grp_id, xy_max);
1191         /* Check that moleculetypes in insertion group are not part of the rest of the system */
1192         check_types(ins_at, rest_at, mtop);
1193
1194         mem_nat = init_mem_at(mem_p, mtop, state->x, state->box, pos_ins);
1195
1196         prot_area = est_prot_area(pos_ins, state->x, ins_at, mem_p);
1197         if ( (prot_area > prot_vs_box) && ( (state->box[XX][XX]*state->box[YY][YY]-state->box[XX][YY]*state->box[YY][XX]) < box_vs_prot) )
1198         {
1199             warn++;
1200             fprintf(stderr, "\nWarning %d:\nThe xy-area is very small compared to the area of the protein.\n"
1201                     "This might cause pressure problems during the growth phase. Just try with\n"
1202                     "current setup (-maxwarn + 1), but if pressure problems occur, lower the\n"
1203                     "compressibility in the mdp-file or use no pressure coupling at all.\n\n", warn);
1204         }
1205
1206         if (warn > maxwarn)
1207         {
1208             gmx_fatal(FARGS, "Too many warnings.\n");
1209         }
1210
1211         printf("The estimated area of the protein in the membrane is %.3f nm^2\n", prot_area);
1212         printf("\nThere are %d lipids in the membrane part that overlaps the protein.\n"
1213                "The area per lipid is %.4f nm^2.\n", mem_p->nmol, mem_p->lip_area);
1214
1215         /* Maximum number of lipids to be removed*/
1216         max_lip_rm = (int)(2*prot_area/mem_p->lip_area);
1217         printf("Maximum number of lipids that will be removed is %d.\n", max_lip_rm);
1218
1219         printf("\nWill resize the protein by a factor of %.3f in the xy plane and %.3f in the z direction.\n"
1220                "This resizing will be done with respect to the geometrical center of all protein atoms\n"
1221                "that span the membrane region, i.e. z between %.3f and %.3f\n\n",
1222                xy_fac, z_fac, mem_p->zmin, mem_p->zmax);
1223
1224         /* resize the protein by xy and by z if necessary*/
1225         snew(r_ins, ins_at->nr);
1226         init_resize(ins_at, r_ins, pos_ins, mem_p, state->x, bALLOW_ASYMMETRY);
1227         membed->fac[0] = membed->fac[1] = xy_fac;
1228         membed->fac[2] = z_fac;
1229
1230         membed->xy_step = (xy_max-xy_fac)/(double)(it_xy);
1231         membed->z_step  = (z_max-z_fac)/(double)(it_z-1);
1232
1233         resize(r_ins, state->x, pos_ins, membed->fac);
1234
1235         /* remove overlapping lipids and water from the membrane box*/
1236         /*mark molecules to be removed*/
1237         snew(pbc, 1);
1238         set_pbc(pbc, inputrec->ePBC, state->box);
1239
1240         snew(rm_p, 1);
1241         lip_rm = gen_rm_list(rm_p, ins_at, rest_at, pbc, mtop, state->x, mem_p, pos_ins,
1242                              probe_rad, low_up_rm, bALLOW_ASYMMETRY);
1243         lip_rm -= low_up_rm;
1244
1245         if (fplog)
1246         {
1247             for (i = 0; i < rm_p->nr; i++)
1248             {
1249                 fprintf(fplog, "rm mol %d\n", rm_p->mol[i]);
1250             }
1251         }
1252
1253         for (i = 0; i < mtop->nmolblock; i++)
1254         {
1255             ntype = 0;
1256             for (j = 0; j < rm_p->nr; j++)
1257             {
1258                 if (rm_p->block[j] == i)
1259                 {
1260                     ntype++;
1261                 }
1262             }
1263             printf("Will remove %d %s molecules\n", ntype, *(mtop->moltype[mtop->molblock[i].type].name));
1264         }
1265
1266         if (lip_rm > max_lip_rm)
1267         {
1268             warn++;
1269             fprintf(stderr, "\nWarning %d:\nTrying to remove a larger lipid area than the estimated "
1270                     "protein area\nTry making the -xyinit resize factor smaller or increase "
1271                     "maxwarn.\n\n", warn);
1272         }
1273
1274         /*remove all lipids and waters overlapping and update all important structures*/
1275         rm_group(groups, mtop, rm_p, state, ins_at, pos_ins);
1276
1277         rm_bonded_at = rm_bonded(ins_at, mtop);
1278         if (rm_bonded_at != ins_at->nr)
1279         {
1280             fprintf(stderr, "Warning: The number of atoms for which the bonded interactions are removed is %d, "
1281                     "while %d atoms are embedded. Make sure that the atoms to be embedded are not in the same"
1282                     "molecule type as atoms that are not to be embedded.\n", rm_bonded_at, ins_at->nr);
1283         }
1284
1285         if (warn > maxwarn)
1286         {
1287             gmx_fatal(FARGS, "Too many warnings.\nIf you are sure these warnings are harmless, "
1288                       "you can increase -maxwarn");
1289         }
1290
1291         if (ftp2bSet(efTOP, nfile, fnm))
1292         {
1293             top_update(opt2fn("-mp", nfile, fnm), rm_p, mtop);
1294         }
1295
1296         sfree(pbc);
1297         sfree(rest_at);
1298         if (pieces > 1)
1299         {
1300             sfree(piecename);
1301         }
1302
1303         membed->it_xy   = it_xy;
1304         membed->it_z    = it_z;
1305         membed->pos_ins = pos_ins;
1306         membed->r_ins   = r_ins;
1307     }
1308
1309     return membed;
1310 }