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