2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2012, The GROMACS development team,
6 * check out http://www.gromacs.org for more information.
7 * Copyright (c) 2012,2013, by the GROMACS development team, led by
8 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9 * others, as listed in the AUTHORS file in the top-level source
10 * directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
57 #include "mtop_util.h"
65 /* information about scaling center */
67 rvec xmin; /* smallest coordinates of all embedded molecules */
68 rvec xmax; /* largest coordinates of all embedded molecules */
69 rvec *geom_cent; /* scaling center of each independent molecule to embed */
70 int pieces; /* number of molecules to embed independently */
71 int *nidx; /* n atoms for every independent embedded molecule (index in subindex) */
72 atom_id **subindex; /* atomids for independent molecule *
73 * atoms of piece i run from subindex[i][0] to subindex[i][nidx[i]] */
76 /* variables needed in do_md */
78 int it_xy; /* number of iterations (steps) used to grow something in the xy-plane */
79 int it_z; /* same, but for z */
80 real xy_step; /* stepsize used during resize in xy-plane */
81 real z_step; /* same, but in z */
82 rvec fac; /* initial scaling of the molecule to grow into the membrane */
83 rvec *r_ins; /* final coordinates of the molecule to grow */
84 pos_ins_t *pos_ins; /* scaling center for each piece to embed */
87 /* membrane related variables */
89 char *name; /* name of index group to embed molecule into (usually membrane) */
90 t_block mem_at; /* list all atoms in membrane */
91 int nmol; /* number of membrane molecules overlapping with the molecule to embed */
92 int *mol_id; /* list of molecules in membrane that overlap with the molecule to embed */
93 real lip_area; /* average area per lipid in membrane (only correct for homogeneous bilayers)*/
94 real zmin; /* minimum z coordinate of membrane */
95 real zmax; /* maximum z coordinate of membrane */
96 real zmed; /* median z coordinate of membrane */
99 /* Lists all molecules in the membrane that overlap with the molecule to be embedded. *
100 * These will then be removed from the system */
102 int nr; /* number of molecules to remove */
103 int *mol; /* list of molecule ids to remove */
104 int *block; /* id of the molblock that the molecule to remove is part of */
107 /* Get the global molecule id, and the corresponding molecule type and id of the *
108 * molblock from the global atom nr. */
109 static int get_mol_id(int at, gmx_mtop_t *mtop, int *type, int *block)
114 gmx_mtop_atomlookup_t alook;
116 alook = gmx_mtop_atomlookup_settle_init(mtop);
117 gmx_mtop_atomnr_to_molblock_ind(alook,at,block,&mol_id,&atnr_mol);
118 for(i=0;i<*block;i++)
120 mol_id += mtop->molblock[i].nmol;
122 *type = mtop->molblock[*block].type;
124 gmx_mtop_atomlookup_destroy(alook);
129 /* Get the id of the molblock from a global molecule id */
130 static int get_molblock(int mol_id,int nmblock,gmx_molblock_t *mblock)
135 for(i=0;i<nmblock;i++)
137 nmol+=mblock[i].nmol;
144 gmx_fatal(FARGS,"mol_id %d larger than total number of molecules %d.\n",mol_id,nmol);
149 static int get_tpr_version(const char *infile)
152 int version,generation;
154 read_tpxheader(infile,&header,TRUE,&version,&generation);
159 /* Get a list of all the molecule types that are present in a group of atoms. *
160 * Because all interaction within the group to embed are removed on the topology *
161 * level, if the same molecule type is found in another part of the system, these *
162 * would also be affected. Therefore we have to check if the embedded and rest group *
163 * share common molecule types. If so, membed will stop with an error. */
164 static int get_mtype_list(t_block *at, gmx_mtop_t *mtop, t_block *tlist)
171 snew(tlist->index,at->nr);
172 for (i=0;i<at->nr;i++)
175 mol_id = get_mol_id(at->index[i],mtop,&type,&block);
178 if(tlist->index[j]==type)
186 tlist->index[nr]=type;
190 srenew(tlist->index,nr);
194 /* Do the actual check of the molecule types between embedded and rest group */
195 static void check_types(t_block *ins_at,t_block *rest_at,gmx_mtop_t *mtop)
197 t_block *ins_mtype,*rest_mtype;
202 ins_mtype->nr = get_mtype_list(ins_at , mtop, ins_mtype );
203 rest_mtype->nr = get_mtype_list(rest_at, mtop, rest_mtype);
205 for(i=0;i<ins_mtype->nr;i++)
207 for(j=0;j<rest_mtype->nr;j++)
209 if(ins_mtype->index[i]==rest_mtype->index[j])
211 gmx_fatal(FARGS,"Moleculetype %s is found both in the group to insert and the rest of the system.\n"
212 "1. Your *.ndx and *.top do not match\n"
213 "2. You are inserting some molecules of type %s (for example xray-solvent), while\n"
214 "the same moleculetype is also used in the rest of the system (solvent box). Because\n"
215 "we need to exclude all interactions between the atoms in the group to\n"
216 "insert, the same moleculetype can not be used in both groups. Change the\n"
217 "moleculetype of the molecules %s in the inserted group. Do not forget to provide\n"
218 "an appropriate *.itp file",*(mtop->moltype[rest_mtype->index[j]].name),
219 *(mtop->moltype[rest_mtype->index[j]].name),*(mtop->moltype[rest_mtype->index[j]].name));
224 sfree(ins_mtype->index);
225 sfree(rest_mtype->index);
230 static void get_input(const char *membed_input, real *xy_fac, real *xy_max, real *z_fac, real *z_max,
231 int *it_xy, int *it_z, real *probe_rad, int *low_up_rm, int *maxwarn,
232 int *pieces, gmx_bool *bALLOW_ASYMMETRY)
238 wi = init_warning(TRUE,0);
240 inp = read_inpfile(membed_input, &ninp, NULL, wi);
241 ITYPE ("nxy", *it_xy, 1000);
242 ITYPE ("nz", *it_z, 0);
243 RTYPE ("xyinit", *xy_fac, 0.5);
244 RTYPE ("xyend", *xy_max, 1.0);
245 RTYPE ("zinit", *z_fac, 1.0);
246 RTYPE ("zend", *z_max, 1.0);
247 RTYPE ("rad", *probe_rad, 0.22);
248 ITYPE ("ndiff", *low_up_rm, 0);
249 ITYPE ("maxwarn", *maxwarn, 0);
250 ITYPE ("pieces", *pieces, 1);
251 EETYPE("asymmetry", *bALLOW_ASYMMETRY, yesno_names);
253 write_inpfile(membed_input,ninp,inp,FALSE,wi);
256 /* Obtain the maximum and minimum coordinates of the group to be embedded */
257 static int init_ins_at(t_block *ins_at,t_block *rest_at,t_state *state, pos_ins_t *pos_ins,
258 gmx_groups_t *groups,int ins_grp_id, real xy_max)
261 real x,xmin,xmax,y,ymin,ymax,z,zmin,zmax;
262 const real min_memthick=6.0; /* minimum thickness of the bilayer that will be used to *
263 * determine the overlap between molecule to embed and membrane */
264 const real fac_inp_size=1.000001; /* scaling factor to obtain input_size + 0.000001 (comparing reals) */
265 snew(rest_at->index,state->natoms);
267 xmin=xmax=state->x[ins_at->index[0]][XX];
268 ymin=ymax=state->x[ins_at->index[0]][YY];
269 zmin=zmax=state->x[ins_at->index[0]][ZZ];
271 for(i=0;i<state->natoms;i++)
273 gid = groups->grpnr[egcFREEZE][i];
274 if(groups->grps[egcFREEZE].nm_ind[gid]==ins_grp_id)
294 srenew(rest_at->index,c);
296 if(xy_max>fac_inp_size)
298 pos_ins->xmin[XX]=xmin-((xmax-xmin)*xy_max-(xmax-xmin))/2;
299 pos_ins->xmin[YY]=ymin-((ymax-ymin)*xy_max-(ymax-ymin))/2;
301 pos_ins->xmax[XX]=xmax+((xmax-xmin)*xy_max-(xmax-xmin))/2;
302 pos_ins->xmax[YY]=ymax+((ymax-ymin)*xy_max-(ymax-ymin))/2;
306 pos_ins->xmin[XX]=xmin;
307 pos_ins->xmin[YY]=ymin;
309 pos_ins->xmax[XX]=xmax;
310 pos_ins->xmax[YY]=ymax;
313 if( (zmax-zmin) < min_memthick )
315 pos_ins->xmin[ZZ]=zmin+(zmax-zmin)/2.0-0.5*min_memthick;
316 pos_ins->xmax[ZZ]=zmin+(zmax-zmin)/2.0+0.5*min_memthick;
320 pos_ins->xmin[ZZ]=zmin;
321 pos_ins->xmax[ZZ]=zmax;
327 /* Estimate the area of the embedded molecule by projecting all coordinates on a grid in the *
328 * xy-plane and counting the number of occupied grid points */
329 static real est_prot_area(pos_ins_t *pos_ins,rvec *r,t_block *ins_at, mem_t *mem_p)
331 real x,y,dx=0.15,dy=0.15,area=0.0;
332 real add,memmin,memmax;
335 /* min and max membrane coordinate are altered to reduce the influence of the *
337 memmin=mem_p->zmin+0.1*(mem_p->zmax-mem_p->zmin);
338 memmax=mem_p->zmax-0.1*(mem_p->zmax-mem_p->zmin);
340 for(x=pos_ins->xmin[XX];x<pos_ins->xmax[XX];x+=dx)
342 for(y=pos_ins->xmin[YY];y<pos_ins->xmax[YY];y+=dy)
349 if ( (r[at][XX]>=x) && (r[at][XX]<x+dx) &&
350 (r[at][YY]>=y) && (r[at][YY]<y+dy) &&
351 (r[at][ZZ]>memmin) && (r[at][ZZ]<memmax) )
356 } while ( (c<ins_at->nr) && (add<0.5) );
365 static int init_mem_at(mem_t *mem_p, gmx_mtop_t *mtop, rvec *r, matrix box, pos_ins_t *pos_ins)
367 int i,j,at,mol,nmol,nmolbox,count;
369 real z,zmin,zmax,mem_area;
375 mem_a=&(mem_p->mem_at);
376 snew(mol_id,mem_a->nr);
377 zmin=pos_ins->xmax[ZZ];
378 zmax=pos_ins->xmin[ZZ];
379 for(i=0;i<mem_a->nr;i++)
382 if( (r[at][XX]>pos_ins->xmin[XX]) && (r[at][XX]<pos_ins->xmax[XX]) &&
383 (r[at][YY]>pos_ins->xmin[YY]) && (r[at][YY]<pos_ins->xmax[YY]) &&
384 (r[at][ZZ]>pos_ins->xmin[ZZ]) && (r[at][ZZ]<pos_ins->xmax[ZZ]) )
386 mol = get_mol_id(at,mtop,&type,&block);
419 mem_p->mol_id=mol_id;
421 if((zmax-zmin)>(box[ZZ][ZZ]-0.5))
423 gmx_fatal(FARGS,"Something is wrong with your membrane. Max and min z values are %f and %f.\n"
424 "Maybe your membrane is not centered in the box, but located at the box edge in the z-direction,\n"
425 "so that one membrane is distributed over two periodic box images. Another possibility is that\n"
426 "your water layer is not thick enough.\n",zmax,zmin);
430 mem_p->zmed=(zmax-zmin)/2+zmin;
432 /*number of membrane molecules in protein box*/
433 nmolbox = count/mtop->molblock[block].natoms_mol;
434 /*membrane area within the box defined by the min and max coordinates of the embedded molecule*/
435 mem_area = (pos_ins->xmax[XX]-pos_ins->xmin[XX])*(pos_ins->xmax[YY]-pos_ins->xmin[YY]);
436 /*rough estimate of area per lipid, assuming there is only one type of lipid in the membrane*/
437 mem_p->lip_area = 2.0*mem_area/(double)nmolbox;
439 return mem_p->mem_at.nr;
442 static void init_resize(t_block *ins_at,rvec *r_ins,pos_ins_t *pos_ins,mem_t *mem_p,rvec *r,
443 gmx_bool bALLOW_ASYMMETRY)
445 int i,j,at,c,outsidesum,gctr=0;
449 for (i=0;i<pos_ins->pieces;i++)
451 idxsum+=pos_ins->nidx[i];
454 if (idxsum!=ins_at->nr)
456 gmx_fatal(FARGS,"Piecewise sum of inserted atoms not same as size of group selected to insert.");
459 snew(pos_ins->geom_cent,pos_ins->pieces);
460 for (i=0;i<pos_ins->pieces;i++)
466 pos_ins->geom_cent[i][j]=0;
469 for (j=0;j<pos_ins->nidx[i];j++)
471 at=pos_ins->subindex[i][j];
472 copy_rvec(r[at],r_ins[gctr]);
473 if( (r_ins[gctr][ZZ]<mem_p->zmax) && (r_ins[gctr][ZZ]>mem_p->zmin) )
475 rvec_inc(pos_ins->geom_cent[i],r_ins[gctr]);
487 svmul(1/(double)c,pos_ins->geom_cent[i],pos_ins->geom_cent[i]);
490 if (!bALLOW_ASYMMETRY)
492 pos_ins->geom_cent[i][ZZ]=mem_p->zmed;
495 fprintf(stderr,"Embedding piece %d with center of geometry: %f %f %f\n",
496 i,pos_ins->geom_cent[i][XX],pos_ins->geom_cent[i][YY],pos_ins->geom_cent[i][ZZ]);
498 fprintf(stderr,"\n");
501 /* resize performed in the md loop */
502 static void resize(rvec *r_ins, rvec *r, pos_ins_t *pos_ins,rvec fac)
505 for (k=0;k<pos_ins->pieces;k++)
507 for(i=0;i<pos_ins->nidx[k];i++)
509 at=pos_ins->subindex[k][i];
512 r[at][j]=pos_ins->geom_cent[k][j]+fac[j]*(r_ins[c][j]-pos_ins->geom_cent[k][j]);
519 /* generate the list of membrane molecules that overlap with the molecule to be embedded. *
520 * The molecule to be embedded is already reduced in size. */
521 static int gen_rm_list(rm_t *rm_p,t_block *ins_at,t_block *rest_at,t_pbc *pbc, gmx_mtop_t *mtop,
522 rvec *r, rvec *r_ins, mem_t *mem_p, pos_ins_t *pos_ins, real probe_rad,
523 int low_up_rm, gmx_bool bALLOW_ASYMMETRY)
525 int i,j,k,l,at,at2,mol_id;
527 int nrm,nupper,nlower;
528 real r_min_rad,z_lip,min_norm;
534 r_min_rad=probe_rad*probe_rad;
535 snew(rm_p->mol,mtop->mols.nr);
536 snew(rm_p->block,mtop->mols.nr);
539 for(i=0;i<ins_at->nr;i++)
542 for(j=0;j<rest_at->nr;j++)
544 at2=rest_at->index[j];
545 pbc_dx(pbc,r[at],r[at2],dr);
547 if(norm2(dr)<r_min_rad)
549 mol_id = get_mol_id(at2,mtop,&type,&block);
553 if(rm_p->mol[l]==mol_id)
561 rm_p->mol[nrm]=mol_id;
562 rm_p->block[nrm]=block;
565 for(l=0;l<mem_p->nmol;l++)
567 if(mol_id==mem_p->mol_id[l])
569 for(k=mtop->mols.index[mol_id];k<mtop->mols.index[mol_id+1];k++)
573 z_lip/=mtop->molblock[block].natoms_mol;
574 if(z_lip<mem_p->zmed)
589 /*make sure equal number of lipids from upper and lower layer are removed */
590 if( (nupper!=nlower) && (!bALLOW_ASYMMETRY) )
592 snew(dist,mem_p->nmol);
593 snew(order,mem_p->nmol);
594 for(i=0;i<mem_p->nmol;i++)
596 at = mtop->mols.index[mem_p->mol_id[i]];
597 pbc_dx(pbc,r[at],pos_ins->geom_cent[0],dr);
598 if (pos_ins->pieces>1)
602 for (k=1;k<pos_ins->pieces;k++)
604 pbc_dx(pbc,r[at],pos_ins->geom_cent[k],dr_tmp);
605 if (norm2(dr_tmp) < min_norm)
607 min_norm=norm2(dr_tmp);
608 copy_rvec(dr_tmp,dr);
612 dist[i]=dr[XX]*dr[XX]+dr[YY]*dr[YY];
614 while (j>=0 && dist[i]<dist[order[j]])
623 while(nupper!=nlower)
625 mol_id=mem_p->mol_id[order[i]];
626 block=get_molblock(mol_id,mtop->nmolblock,mtop->molblock);
630 if(rm_p->mol[l]==mol_id)
639 for(k=mtop->mols.index[mol_id];k<mtop->mols.index[mol_id+1];k++)
643 z_lip/=mtop->molblock[block].natoms_mol;
644 if(nupper>nlower && z_lip<mem_p->zmed)
646 rm_p->mol[nrm]=mol_id;
647 rm_p->block[nrm]=block;
651 else if (nupper<nlower && z_lip>mem_p->zmed)
653 rm_p->mol[nrm]=mol_id;
654 rm_p->block[nrm]=block;
663 gmx_fatal(FARGS,"Trying to remove more lipid molecules than there are in the membrane");
671 srenew(rm_p->mol,nrm);
672 srenew(rm_p->block,nrm);
674 return nupper+nlower;
677 /*remove all lipids and waters overlapping and update all important structures (e.g. state and mtop)*/
678 static void rm_group(t_inputrec *ir, gmx_groups_t *groups, gmx_mtop_t *mtop, rm_t *rm_p, t_state *state,
679 t_block *ins_at, pos_ins_t *pos_ins)
681 int i,j,k,n,rm,mol_id,at,block;
683 atom_id *list,*new_mols;
684 unsigned char *new_egrp[egcNR];
688 snew(list,state->natoms);
690 for(i=0;i<rm_p->nr;i++)
693 at=mtop->mols.index[mol_id];
694 block =rm_p->block[i];
695 mtop->molblock[block].nmol--;
696 for(j=0;j<mtop->molblock[block].natoms_mol;j++)
701 mtop->mols.index[mol_id]=-1;
704 mtop->mols.nr-=rm_p->nr;
705 mtop->mols.nalloc_index-=rm_p->nr;
706 snew(new_mols,mtop->mols.nr);
707 for(i=0;i<mtop->mols.nr+rm_p->nr;i++)
710 if(mtop->mols.index[i]!=-1)
712 new_mols[j]=mtop->mols.index[i];
716 sfree(mtop->mols.index);
717 mtop->mols.index=new_mols;
720 state->nalloc=state->natoms;
721 snew(x_tmp,state->nalloc);
722 snew(v_tmp,state->nalloc);
726 if(groups->grpnr[i]!=NULL)
728 groups->ngrpnr[i]=state->natoms;
729 snew(new_egrp[i],state->natoms);
734 for (i=0;i<state->natoms+n;i++)
750 if(groups->grpnr[j]!=NULL)
752 new_egrp[j][i-rm]=groups->grpnr[j][i];
755 copy_rvec(state->x[i],x_tmp[i-rm]);
756 copy_rvec(state->v[i],v_tmp[i-rm]);
757 for(j=0;j<ins_at->nr;j++)
759 if (i==ins_at->index[j])
761 ins_at->index[j]=i-rm;
765 for(j=0;j<pos_ins->pieces;j++)
767 for(k=0;k<pos_ins->nidx[j];k++)
769 if (i==pos_ins->subindex[j][k])
771 pos_ins->subindex[j][k]=i-rm;
784 if(groups->grpnr[i]!=NULL)
786 sfree(groups->grpnr[i]);
787 groups->grpnr[i]=new_egrp[i];
791 /* remove empty molblocks */
793 for (i=0;i<mtop->nmolblock;i++)
795 if(mtop->molblock[i].nmol==0)
801 mtop->molblock[i-RMmolblock]=mtop->molblock[i];
804 mtop->nmolblock-=RMmolblock;
807 /* remove al bonded interactions from mtop for the molecule to be embedded */
808 int rm_bonded(t_block *ins_at, gmx_mtop_t *mtop)
811 int type,natom,nmol,at,atom1=0,rm_at=0;
813 /*this routine lives dangerously by assuming that all molecules of a given type are in order in the structure*/
814 /*this routine does not live as dangerously as it seems. There is namely a check in init_membed to make *
815 *sure that g_membed exits with a warning when there are molecules of the same type not in the *
816 *ins_at index group. MGWolf 050710 */
819 snew(bRM,mtop->nmoltype);
820 for (i=0;i<mtop->nmoltype;i++)
825 for (i=0;i<mtop->nmolblock;i++)
827 /*loop over molecule blocks*/
828 type =mtop->molblock[i].type;
829 natom =mtop->molblock[i].natoms_mol;
830 nmol =mtop->molblock[i].nmol;
832 for(j=0;j<natom*nmol && bRM[type]==TRUE;j++)
834 /*loop over atoms in the block*/
835 at=j+atom1; /*atom index = block index + offset*/
838 for (m=0;(m<ins_at->nr) && (bINS==FALSE);m++)
840 /*loop over atoms in insertion index group to determine if we're inserting one*/
841 if(at==ins_at->index[m])
848 atom1+=natom*nmol; /*update offset*/
851 rm_at+=natom*nmol; /*increment bonded removal counter by # atoms in block*/
855 for(i=0;i<mtop->nmoltype;i++)
861 mtop->moltype[i].ilist[j].nr=0;
864 for(j=F_POSRES;j<=F_VSITEN;j++)
866 mtop->moltype[i].ilist[j].nr=0;
875 /* Write a topology where the number of molecules is correct for the system after embedding */
876 static void top_update(const char *topfile, char *ins, rm_t *rm_p, gmx_mtop_t *mtop)
878 #define TEMP_FILENM "temp.top"
881 char buf[STRLEN],buf2[STRLEN],*temp;
882 int i,*nmol_rm,nmol,line;
884 fpin = ffopen(topfile,"r");
885 fpout = ffopen(TEMP_FILENM,"w");
887 snew(nmol_rm,mtop->nmoltype);
888 for(i=0;i<rm_p->nr;i++)
890 nmol_rm[rm_p->block[i]]++;
894 while(fgets(buf,STRLEN,fpin))
900 if ((temp=strchr(buf2,'\n')) != NULL)
908 if ((temp=strchr(buf2,'\n')) != NULL)
913 if (buf2[strlen(buf2)-1]==']')
915 buf2[strlen(buf2)-1]='\0';
918 if (gmx_strcasecmp(buf2,"molecules")==0)
923 fprintf(fpout,"%s",buf);
925 else if (bMolecules==1)
927 for(i=0;i<mtop->nmolblock;i++)
929 nmol=mtop->molblock[i].nmol;
930 sprintf(buf,"%-15s %5d\n",*(mtop->moltype[mtop->molblock[i].type].name),nmol);
931 fprintf(fpout,"%s",buf);
935 else if (bMolecules==2)
941 fprintf(fpout,"%s",buf);
946 fprintf(fpout,"%s",buf);
951 /* use ffopen to generate backup of topinout */
952 fpout=ffopen(topfile,"w");
954 rename(TEMP_FILENM,topfile);
958 void rescale_membed(int step_rel, gmx_membed_t membed, rvec *x)
960 /* Set new positions for the group to embed */
961 if(step_rel<=membed->it_xy)
963 membed->fac[0]+=membed->xy_step;
964 membed->fac[1]+=membed->xy_step;
966 else if (step_rel<=(membed->it_xy+membed->it_z))
968 membed->fac[2]+=membed->z_step;
970 resize(membed->r_ins,x,membed->pos_ins,membed->fac);
973 gmx_membed_t init_membed(FILE *fplog, int nfile, const t_filenm fnm[], gmx_mtop_t *mtop,
974 t_inputrec *inputrec, t_state *state, t_commrec *cr,real *cpt)
977 int i,rm_bonded_at,fr_id,fr_i=0,tmp_id,warn=0;
978 int ng,j,max_lip_rm,ins_grp_id,ins_nat,mem_nat,ntype,lip_rm,tpr_version;
981 t_block *ins_at,*rest_at;
985 gmx_groups_t *groups;
986 gmx_bool bExcl=FALSE;
989 char **piecename=NULL;
990 gmx_membed_t membed=NULL;
992 /* input variables */
993 const char *membed_input;
1000 real probe_rad = 0.22;
1004 gmx_bool bALLOW_ASYMMETRY=FALSE;
1006 /* sanity check constants */ /* Issue a warning when: */
1007 const int membed_version=58; /* tpr version is smaller */
1008 const real min_probe_rad=0.2199999; /* A probe radius for overlap between embedded molecule *
1009 * and rest smaller than this value is probably too small */
1010 const real min_xy_init=0.0999999; /* the initial shrinking of the molecule to embed is smaller */
1011 const int min_it_xy=1000; /* the number of steps to embed in xy-plane is smaller */
1012 const int min_it_z=100; /* the number of steps to embed in z is smaller */
1013 const real prot_vs_box=7.5; /* molecule to embed is large (more then prot_vs_box) with respect */
1014 const real box_vs_prot=50; /* to the box size (less than box_vs_prot) */
1022 /* get input data out membed file */
1023 membed_input = opt2fn("-membed",nfile,fnm);
1024 get_input(membed_input,&xy_fac,&xy_max,&z_fac,&z_max,&it_xy,&it_z,&probe_rad,&low_up_rm,
1025 &maxwarn,&pieces,&bALLOW_ASYMMETRY);
1027 tpr_version = get_tpr_version(ftp2fn(efTPX,nfile,fnm));
1028 if (tpr_version<membed_version)
1030 gmx_fatal(FARGS,"Version of *.tpr file to old (%d). "
1031 "Rerun grompp with GROMACS version 4.0.3 or newer.\n",tpr_version);
1034 if( !EI_DYNAMICS(inputrec->eI) )
1036 gmx_input("Change integrator to a dynamics integrator in mdp file (e.g. md or sd).");
1041 gmx_input("Sorry, parallel g_membed is not yet fully functional.");
1046 fprintf(stderr,"\nSetting -cpt to -1, because embedding cannot be restarted from cpt-files.\n");
1049 groups=&(mtop->groups);
1050 snew(gnames,groups->ngrpname);
1051 for (i=0; i<groups->ngrpname; i++)
1053 gnames[i] = *(groups->grpname[i]);
1056 atoms=gmx_mtop_global_atoms(mtop);
1058 fprintf(stderr,"\nSelect a group to embed in the membrane:\n");
1059 get_index(&atoms,opt2fn_null("-mn",nfile,fnm),1,&(ins_at->nr),&(ins_at->index),&ins);
1060 ins_grp_id = search_string(ins,groups->ngrpname,gnames);
1061 fprintf(stderr,"\nSelect a group to embed %s into (e.g. the membrane):\n",ins);
1062 get_index(&atoms,opt2fn_null("-mn",nfile,fnm),1,&(mem_p->mem_at.nr),&(mem_p->mem_at.index),&(mem_p->name));
1064 pos_ins->pieces=pieces;
1065 snew(pos_ins->nidx,pieces);
1066 snew(pos_ins->subindex,pieces);
1067 snew(piecename,pieces);
1070 fprintf(stderr,"\nSelect pieces to embed:\n");
1071 get_index(&atoms,opt2fn_null("-mn",nfile,fnm),pieces,pos_ins->nidx,pos_ins->subindex,piecename);
1075 /*use whole embedded group*/
1076 snew(pos_ins->nidx,1);
1077 snew(pos_ins->subindex,1);
1078 pos_ins->nidx[0]=ins_at->nr;
1079 pos_ins->subindex[0]=ins_at->index;
1082 if(probe_rad<min_probe_rad)
1085 fprintf(stderr,"\nWarning %d:\nA probe radius (-rad) smaller than 0.2 nm can result "
1086 "in overlap between waters and the group to embed, which will result "
1087 "in Lincs errors etc.\n\n",warn);
1090 if(xy_fac<min_xy_init)
1093 fprintf(stderr,"\nWarning %d:\nThe initial size of %s is probably too smal.\n\n",warn,ins);
1099 fprintf(stderr,"\nWarning %d;\nThe number of steps used to grow the xy-coordinates of %s (%d)"
1100 " is probably too small.\nIncrease -nxy or.\n\n",warn,ins,it_xy);
1103 if( (it_z<min_it_z) && ( z_fac<0.99999999 || z_fac>1.0000001) )
1106 fprintf(stderr,"\nWarning %d;\nThe number of steps used to grow the z-coordinate of %s (%d)"
1107 " is probably too small.\nIncrease -nz or maxwarn.\n\n",warn,ins,it_z);
1110 if(it_xy+it_z>inputrec->nsteps)
1113 fprintf(stderr,"\nWarning %d:\nThe number of growth steps (-nxy + -nz) is larger than the "
1114 "number of steps in the tpr.\n\n",warn);
1118 if( inputrec->opts.ngfrz==1)
1120 gmx_fatal(FARGS,"You did not specify \"%s\" as a freezegroup.",ins);
1123 for(i=0;i<inputrec->opts.ngfrz;i++)
1125 tmp_id = mtop->groups.grps[egcFREEZE].nm_ind[i];
1126 if(ins_grp_id==tmp_id)
1135 gmx_fatal(FARGS,"\"%s\" not as freezegroup defined in the mdp-file.",ins);
1140 if( inputrec->opts.nFreeze[fr_i][i] != 1)
1142 gmx_fatal(FARGS,"freeze dimensions for %s are not Y Y Y\n",ins);
1146 ng = groups->grps[egcENER].nr;
1149 gmx_input("No energy groups defined. This is necessary for energy exclusion in the freeze group");
1156 if (inputrec->opts.egp_flags[ng*i+j] == EGP_EXCL)
1159 if ( (groups->grps[egcENER].nm_ind[i] != ins_grp_id) ||
1160 (groups->grps[egcENER].nm_ind[j] != ins_grp_id) )
1162 gmx_fatal(FARGS,"Energy exclusions \"%s\" and \"%s\" do not match the group "
1163 "to embed \"%s\"",*groups->grpname[groups->grps[egcENER].nm_ind[i]],
1164 *groups->grpname[groups->grps[egcENER].nm_ind[j]],ins);
1171 gmx_input("No energy exclusion groups defined. This is necessary for energy exclusion in "
1172 "the freeze group");
1175 /* Obtain the maximum and minimum coordinates of the group to be embedded */
1177 ins_nat = init_ins_at(ins_at,rest_at,state,pos_ins,groups,ins_grp_id,xy_max);
1178 /* Check that moleculetypes in insertion group are not part of the rest of the system */
1179 check_types(ins_at,rest_at,mtop);
1181 mem_nat = init_mem_at(mem_p,mtop,state->x,state->box,pos_ins);
1183 prot_area = est_prot_area(pos_ins,state->x,ins_at,mem_p);
1184 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) )
1187 fprintf(stderr,"\nWarning %d:\nThe xy-area is very small compared to the area of the protein.\n"
1188 "This might cause pressure problems during the growth phase. Just try with\n"
1189 "current setup (-maxwarn + 1), but if pressure problems occur, lower the\n"
1190 "compressibility in the mdp-file or use no pressure coupling at all.\n\n",warn);
1195 gmx_fatal(FARGS,"Too many warnings.\n");
1198 printf("The estimated area of the protein in the membrane is %.3f nm^2\n",prot_area);
1199 printf("\nThere are %d lipids in the membrane part that overlaps the protein.\n"
1200 "The area per lipid is %.4f nm^2.\n",mem_p->nmol,mem_p->lip_area);
1202 /* Maximum number of lipids to be removed*/
1203 max_lip_rm=(int)(2*prot_area/mem_p->lip_area);
1204 printf("Maximum number of lipids that will be removed is %d.\n",max_lip_rm);
1206 printf("\nWill resize the protein by a factor of %.3f in the xy plane and %.3f in the z direction.\n"
1207 "This resizing will be done with respect to the geometrical center of all protein atoms\n"
1208 "that span the membrane region, i.e. z between %.3f and %.3f\n\n",
1209 xy_fac,z_fac,mem_p->zmin,mem_p->zmax);
1211 /* resize the protein by xy and by z if necessary*/
1212 snew(r_ins,ins_at->nr);
1213 init_resize(ins_at,r_ins,pos_ins,mem_p,state->x,bALLOW_ASYMMETRY);
1214 membed->fac[0]=membed->fac[1]=xy_fac;
1215 membed->fac[2]=z_fac;
1217 membed->xy_step =(xy_max-xy_fac)/(double)(it_xy);
1218 membed->z_step =(z_max-z_fac)/(double)(it_z-1);
1220 resize(r_ins,state->x,pos_ins,membed->fac);
1222 /* remove overlapping lipids and water from the membrane box*/
1223 /*mark molecules to be removed*/
1225 set_pbc(pbc,inputrec->ePBC,state->box);
1228 lip_rm = gen_rm_list(rm_p,ins_at,rest_at,pbc,mtop,state->x, r_ins, mem_p,pos_ins,
1229 probe_rad,low_up_rm,bALLOW_ASYMMETRY);
1230 lip_rm -= low_up_rm;
1234 for(i=0;i<rm_p->nr;i++)
1236 fprintf(fplog,"rm mol %d\n",rm_p->mol[i]);
1240 for(i=0;i<mtop->nmolblock;i++)
1243 for(j=0;j<rm_p->nr;j++)
1245 if(rm_p->block[j]==i)
1250 printf("Will remove %d %s molecules\n",ntype,*(mtop->moltype[mtop->molblock[i].type].name));
1253 if(lip_rm>max_lip_rm)
1256 fprintf(stderr,"\nWarning %d:\nTrying to remove a larger lipid area than the estimated "
1257 "protein area\nTry making the -xyinit resize factor smaller or increase "
1258 "maxwarn.\n\n",warn);
1261 /*remove all lipids and waters overlapping and update all important structures*/
1262 rm_group(inputrec,groups,mtop,rm_p,state,ins_at,pos_ins);
1264 rm_bonded_at = rm_bonded(ins_at,mtop);
1265 if (rm_bonded_at != ins_at->nr)
1267 fprintf(stderr,"Warning: The number of atoms for which the bonded interactions are removed is %d, "
1268 "while %d atoms are embedded. Make sure that the atoms to be embedded are not in the same"
1269 "molecule type as atoms that are not to be embedded.\n",rm_bonded_at,ins_at->nr);
1274 gmx_fatal(FARGS,"Too many warnings.\nIf you are sure these warnings are harmless, "
1275 "you can increase -maxwarn");
1278 if (ftp2bSet(efTOP,nfile,fnm))
1280 top_update(opt2fn("-mp",nfile,fnm),ins,rm_p,mtop);
1290 membed->it_xy=it_xy;
1292 membed->pos_ins=pos_ins;
1293 membed->r_ins=r_ins;