changed reading hint
[gromacs/adressmacs.git] / src / kernel / dum_parm.c
blob9bd84f818b7b0eb4ce48b835b6736e872e23dcd5
1 /*
2 * $Id$
3 *
4 * This source code is part of
5 *
6 * G R O M A C S
7 *
8 * GROningen MAchine for Chemical Simulations
9 *
10 * VERSION 2.0
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
16 * Please refer to:
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
23 * or e-mail to:
24 * gromacs@chem.rug.nl
26 * And Hey:
27 * GRowing Old MAkes el Chrono Sweat
29 static char *SRCID_dum_parm_c = "$Id$";
31 #include <stdio.h>
32 #include <math.h>
33 #include <string.h>
34 #include "assert.h"
35 #include "dum_parm.h"
36 #include "smalloc.h"
37 #include "resall.h"
38 #include "add_par.h"
39 #include "vec.h"
40 #include "toputil.h"
41 #include "physics.h"
42 #include "index.h"
43 #include "names.h"
44 #include "fatal.h"
46 typedef struct {
47 t_iatom a[4];
48 real c;
49 } t_mybonded;
51 static void enter_bonded(int nratoms, int *nrbonded, t_mybonded **bondeds,
52 t_param param)
54 int j;
56 srenew(*bondeds, *nrbonded+1);
58 /* copy atom numbers */
59 for(j=0; j<nratoms; j++)
60 (*bondeds)[*nrbonded].a[j] = param.a[j];
61 /* copy parameter */
62 (*bondeds)[*nrbonded].c = param.C0;
64 (*nrbonded)++;
67 static void get_bondeds(int nrat, t_iatom atoms[],
68 t_params plist[],
69 int *nrbond, t_mybonded **bonds,
70 int *nrang, t_mybonded **angles,
71 int *nridih, t_mybonded **idihs )
73 int i,j,k,ftype;
74 int nra,nrd,tp,nrcheck;
75 t_iatom *ia,adum;
76 bool bCheck;
77 t_param param;
79 if (debug) {
80 fprintf(debug,"getting bondeds for %u (nr=%d):",atoms[0]+1,nrat);
81 for(k=1; k<nrat; k++)
82 fprintf(debug," %u",atoms[k]+1);
83 fprintf(debug,"\n");
85 for(ftype=0; (ftype<F_NRE); ftype++) {
86 if (interaction_function[ftype].flags & (IF_BTYPE | IF_CONSTRAINT))
87 /* this is a bond or a constraint */
88 nrcheck = 2;
89 else if ( interaction_function[ftype].flags & IF_ATYPE )
90 /* this is an angle */
91 nrcheck = 3;
92 else {
93 switch(ftype) {
94 case F_IDIHS:
95 /* this is an improper dihedral */
96 nrcheck = 4;
97 break;
98 default:
99 /* ignore this */
100 nrcheck = 0;
101 } /* case */
102 } /* else */
104 if (nrcheck)
105 for(i=0; (i<plist[ftype].nr); i++) {
106 /* now we have something, check includes one of atoms[*] */
107 bCheck=FALSE;
108 for(j=0; j<nrcheck && !bCheck; j++)
109 for(k=0; k<nrat; k++)
110 bCheck = bCheck || (plist[ftype].param[i].a[j]==atoms[k]);
112 if (bCheck)
113 /* abuse nrcheck to see if we're adding bond, angle or idih */
114 switch (nrcheck) {
115 case 2:
116 enter_bonded(nrcheck,nrbond,bonds, plist[ftype].param[i]);
117 break;
118 case 3:
119 enter_bonded(nrcheck,nrang, angles,plist[ftype].param[i]);
120 break;
121 case 4:
122 enter_bonded(nrcheck,nridih,idihs, plist[ftype].param[i]);
123 break;
124 } /* case */
125 } /* for i */
126 } /* for ftype */
129 /* for debug */
130 static void print_bad(FILE *fp,
131 int nrbond, t_mybonded *bonds,
132 int nrang, t_mybonded *angles,
133 int nridih, t_mybonded *idihs )
135 int i;
137 if (nrbond) {
138 fprintf(fp,"bonds:");
139 for(i=0; i<nrbond; i++)
140 fprintf(fp," %u-%u (%g)",
141 bonds[i].AI+1, bonds[i].AJ+1, bonds[i].c);
142 fprintf(fp,"\n");
144 if (nrang) {
145 fprintf(fp,"angles:");
146 for(i=0; i<nrang; i++)
147 fprintf(fp," %u-%u-%u (%g)",
148 angles[i].AI+1, angles[i].AJ+1,
149 angles[i].AK+1, angles[i].c);
150 fprintf(fp,"\n");
152 if (nridih) {
153 fprintf(fp,"idihs:");
154 for(i=0; i<nridih; i++)
155 fprintf(fp," %u-%u-%u-%u (%g)",
156 idihs[i].AI+1, idihs[i].AJ+1,
157 idihs[i].AK+1, idihs[i].AL+1, idihs[i].c);
158 fprintf(fp,"\n");
162 static void print_param(FILE *fp, int ftype, int i, t_param *param)
164 static int pass = 0;
165 static int prev_ftype= NOTSET;
166 static int prev_i = NOTSET;
167 int j;
169 if ( (ftype!=prev_ftype) || (i!=prev_i) ) {
170 pass = 0;
171 prev_ftype= ftype;
172 prev_i = i;
174 fprintf(fp,"(%d) plist[%s].param[%d]",
175 pass,interaction_function[ftype].name,i);
176 for(j=0; j<NRFP(ftype); j++)
177 fprintf(fp,".c[%d]=%g ",j,param->c[j]);
178 fprintf(fp,"\n");
179 pass++;
182 static real get_bond_length(int nrbond, t_mybonded bonds[],
183 t_iatom ai, t_iatom aj)
185 int i;
186 real bondlen;
188 bondlen=NOTSET;
189 for (i=0; i < nrbond && (bondlen==NOTSET); i++) {
190 /* check both ways */
191 if ( ( (ai == bonds[i].AI) && (aj == bonds[i].AJ) ) ||
192 ( (ai == bonds[i].AJ) && (aj == bonds[i].AI) ) )
193 bondlen = bonds[i].c; /* note: bonds[i].c might be NOTSET */
195 return bondlen;
198 static real get_angle(int nrang, t_mybonded angles[],
199 t_iatom ai, t_iatom aj, t_iatom ak)
201 int i;
202 real angle;
204 angle=NOTSET;
205 for (i=0; i < nrang && (angle==NOTSET); i++) {
206 /* check both ways */
207 if ( ( (ai==angles[i].AI) && (aj==angles[i].AJ) && (ak==angles[i].AK) ) ||
208 ( (ai==angles[i].AK) && (aj==angles[i].AJ) && (ak==angles[i].AI) ) )
209 angle = DEG2RAD*angles[i].c;
211 return angle;
214 static bool calc_dum3_param(t_atomtype *atype,
215 t_param *param, t_atoms *at,
216 int nrbond, t_mybonded *bonds,
217 int nrang, t_mybonded *angles )
219 /* i = dummy atom | ,k
220 * j = 1st bonded heavy atom | i-j
221 * k,l = 2nd bonded atoms | `l
224 bool bXH3,bError;
225 real bjk,bjl,a=-1,b=-1;
226 /* check if this is part of a NH3 or CH3 group,
227 * i.e. if atom k and l are dummy masses (MNH3 or MCH3) */
228 if (debug) {
229 int i;
230 for (i=0; i<4; i++)
231 fprintf(debug,"atom %u type %s ",
232 param->a[i]+1,type2nm(at->atom[param->a[i]].type,atype));
233 fprintf(debug,"\n");
235 bXH3 =
236 ( (strcasecmp(type2nm(at->atom[param->AK].type,atype),"MNH3")==0) &&
237 (strcasecmp(type2nm(at->atom[param->AL].type,atype),"MNH3")==0) ) ||
238 ( (strcasecmp(type2nm(at->atom[param->AK].type,atype),"MCH3")==0) &&
239 (strcasecmp(type2nm(at->atom[param->AL].type,atype),"MCH3")==0) );
241 bjk = get_bond_length(nrbond, bonds, param->AJ, param->AK);
242 bjl = get_bond_length(nrbond, bonds, param->AJ, param->AL);
243 bError = (bjk==NOTSET) || (bjl==NOTSET);
244 if (bXH3) {
245 /* now we get some XH3 group specific construction */
246 /* note: we call the heavy atom 'C' and the X atom 'N' */
247 real bMM,bCM,bCN,bNH,aCNH,dH,rH,dM,rM;
248 int aN;
250 /* check if bonds from heavy atom (j) to dummy masses (k,l) are equal: */
251 bError = bError || (bjk!=bjl);
253 /* the X atom (C or N) in the XH3 group is the first after the masses: */
254 aN = max(param->AK,param->AL)+1;
256 /* get common bonds */
257 bMM = get_bond_length(nrbond, bonds, param->AK, param->AL);
258 bCM = bjk;
259 bCN = get_bond_length(nrbond, bonds, param->AJ, aN);
260 bError = bError || (bMM==NOTSET) || (bCN==NOTSET);
262 /* calculate common things */
263 rM = 0.5*bMM;
264 dM = sqrt( sqr(bCM) - sqr(rM) );
266 /* are we dealing with the X atom? */
267 if ( param->AI == aN ) {
268 /* this is trivial */
269 a = b = 0.5 * bCN/dM;
271 } else {
272 /* get other bondlengths and angles: */
273 bNH = get_bond_length(nrbond, bonds, aN, param->AI);
274 aCNH= get_angle (nrang, angles, param->AJ, aN, param->AI);
275 bError = bError || (bNH==NOTSET) || (aCNH==NOTSET);
277 /* calculate */
278 dH = bCN - bNH * cos(aCNH);
279 rH = bNH * sin(aCNH);
281 a = 0.5 * ( dH/dM + rH/rM );
282 b = 0.5 * ( dH/dM - rH/rM );
284 } else
285 fatal_error(0,"calc_dum3_param not implemented for the general case "
286 "(atom %d)",param->AI+1);
288 param->C0 = a;
289 param->C1 = b;
291 if (debug)
292 fprintf(debug,"params for dummy3 %u: %g %g\n",
293 param->AI+1,param->C0,param->C1);
295 return bError;
298 static bool calc_dum3fd_param(t_param *param,
299 int nrbond, t_mybonded *bonds,
300 int nrang, t_mybonded *angles)
302 /* i = dummy atom | ,k
303 * j = 1st bonded heavy atom | i-j
304 * k,l = 2nd bonded atoms | `l
307 bool bError;
308 real bij,bjk,bjl,aijk,aijl,rk,rl;
310 bij = get_bond_length(nrbond, bonds, param->AI, param->AJ);
311 bjk = get_bond_length(nrbond, bonds, param->AJ, param->AK);
312 bjl = get_bond_length(nrbond, bonds, param->AJ, param->AL);
313 aijk= get_angle (nrang, angles, param->AI, param->AJ, param->AK);
314 aijl= get_angle (nrang, angles, param->AI, param->AJ, param->AL);
315 bError = (bij==NOTSET) || (bjk==NOTSET) || (bjl==NOTSET) ||
316 (aijk==NOTSET) || (aijl==NOTSET);
318 rk = bjk * sin(aijk);
319 rl = bjl * sin(aijl);
320 param->C0 = rk / (rk + rl);
321 param->C1 = -bij; /* 'bond'-length for fixed distance dummy */
323 if (debug)
324 fprintf(debug,"params for dummy3fd %u: %g %g\n",
325 param->AI+1,param->C0,param->C1);
326 return bError;
329 static bool calc_dum3fad_param(t_param *param,
330 int nrbond, t_mybonded *bonds,
331 int nrang, t_mybonded *angles)
333 /* i = dummy atom |
334 * j = 1st bonded heavy atom | i-j
335 * k = 2nd bonded heavy atom | `k-l
336 * l = 3d bonded heavy atom |
339 bool bSwapParity,bError;
340 real bij,aijk;
342 bSwapParity = ( param->C1 == -1 );
344 bij = get_bond_length(nrbond, bonds, param->AI, param->AJ);
345 aijk = get_angle (nrang, angles, param->AI, param->AJ, param->AK);
346 bError = (bij==NOTSET) || (aijk==NOTSET);
348 param->C1 = bij; /* 'bond'-length for fixed distance dummy */
349 param->C0 = RAD2DEG*aijk; /* 'bond'-angle for fixed angle dummy */
351 if (bSwapParity)
352 param->C0 = 360 - param->C0;
354 if (debug)
355 fprintf(debug,"params for dummy3fad %u: %g %g\n",
356 param->AI+1,param->C0,param->C1);
357 return bError;
360 static bool calc_dum3out_param(t_atomtype *atype,
361 t_param *param, t_atoms *at,
362 int nrbond, t_mybonded *bonds,
363 int nrang, t_mybonded *angles)
365 /* i = dummy atom | ,k
366 * j = 1st bonded heavy atom | i-j
367 * k,l = 2nd bonded atoms | `l
368 * NOTE: i is out of the j-k-l plane!
371 bool bXH3,bError,bSwapParity;
372 real bij,bjk,bjl,aijk,aijl,akjl,pijk,pijl,a,b,c;
374 /* check if this is part of a NH3 or CH3 group,
375 * i.e. if atom k and l are dummy masses (MNH3 or MCH3) */
376 if (debug) {
377 int i;
378 for (i=0; i<4; i++)
379 fprintf(debug,"atom %u type %s ",
380 param->a[i]+1,type2nm(at->atom[param->a[i]].type,atype));
381 fprintf(debug,"\n");
383 bXH3 =
384 ( (strcasecmp(type2nm(at->atom[param->AK].type,atype),"MNH3")==0) &&
385 (strcasecmp(type2nm(at->atom[param->AL].type,atype),"MNH3")==0) ) ||
386 ( (strcasecmp(type2nm(at->atom[param->AK].type,atype),"MCH3")==0) &&
387 (strcasecmp(type2nm(at->atom[param->AL].type,atype),"MCH3")==0) );
389 /* check if construction parity must be swapped */
390 bSwapParity = ( param->C1 == -1 );
392 bjk = get_bond_length(nrbond, bonds, param->AJ, param->AK);
393 bjl = get_bond_length(nrbond, bonds, param->AJ, param->AL);
394 bError = (bjk==NOTSET) || (bjl==NOTSET);
395 if (bXH3) {
396 /* now we get some XH3 group specific construction */
397 /* note: we call the heavy atom 'C' and the X atom 'N' */
398 real bMM,bCM,bCN,bNH,aCNH,dH,rH,rHx,rHy,dM,rM;
399 int aN;
401 /* check if bonds from heavy atom (j) to dummy masses (k,l) are equal: */
402 bError = bError || (bjk!=bjl);
404 /* the X atom (C or N) in the XH3 group is the first after the masses: */
405 aN = max(param->AK,param->AL)+1;
407 /* get all bondlengths and angles: */
408 bMM = get_bond_length(nrbond, bonds, param->AK, param->AL);
409 bCM = bjk;
410 bCN = get_bond_length(nrbond, bonds, param->AJ, aN);
411 bNH = get_bond_length(nrbond, bonds, aN, param->AI);
412 aCNH= get_angle (nrang, angles, param->AJ, aN, param->AI);
413 bError = bError ||
414 (bMM==NOTSET) || (bCN==NOTSET) || (bNH==NOTSET) || (aCNH==NOTSET);
416 /* calculate */
417 dH = bCN - bNH * cos(aCNH);
418 rH = bNH * sin(aCNH);
419 /* we assume the H's are symmetrically distributed */
420 rHx = rH*cos(DEG2RAD*30);
421 rHy = rH*sin(DEG2RAD*30);
422 rM = 0.5*bMM;
423 dM = sqrt( sqr(bCM) - sqr(rM) );
424 a = 0.5*( (dH/dM) - (rHy/rM) );
425 b = 0.5*( (dH/dM) + (rHy/rM) );
426 c = rHx / (2*dM*rM);
428 } else {
429 /* this is the general construction */
431 bij = get_bond_length(nrbond, bonds, param->AI, param->AJ);
432 aijk= get_angle (nrang, angles, param->AI, param->AJ, param->AK);
433 aijl= get_angle (nrang, angles, param->AI, param->AJ, param->AL);
434 akjl= get_angle (nrang, angles, param->AK, param->AJ, param->AL);
435 bError = bError ||
436 (bij==NOTSET) || (aijk==NOTSET) || (aijl==NOTSET) || (akjl==NOTSET);
438 pijk = cos(aijk)*bij;
439 pijl = cos(aijl)*bij;
440 a = ( pijk + (pijk*cos(akjl)-pijl) * cos(akjl) / sqr(sin(akjl)) ) / bjk;
441 b = ( pijl + (pijl*cos(akjl)-pijk) * cos(akjl) / sqr(sin(akjl)) ) / bjl;
442 c = - sqrt( sqr(bij) -
443 ( sqr(pijk) - 2*pijk*pijl*cos(akjl) + sqr(pijl) )
444 / sqr(sin(akjl)) )
445 / ( bjk*bjl*sin(akjl) );
448 param->C0 = a;
449 param->C1 = b;
450 if (bSwapParity)
451 param->C2 = -c;
452 else
453 param->C2 = c;
454 if (debug)
455 fprintf(debug,"params for dummy3out %u: %g %g %g\n",
456 param->AI+1,param->C0,param->C1,param->C2);
457 return bError;
460 static bool calc_dum4fd_param(t_param *param,
461 int nrbond, t_mybonded *bonds,
462 int nrang, t_mybonded *angles)
464 /* i = dummy atom | ,k
465 * j = 1st bonded heavy atom | i-j-m
466 * k,l,m = 2nd bonded atoms | `l
469 bool bError;
470 real bij,bjk,bjl,bjm,aijk,aijl,aijm,akjm,akjl;
471 real pk,pl,pm,cosakl,cosakm,sinakl,sinakm,cl,cm;
473 bij = get_bond_length(nrbond, bonds, param->AI, param->AJ);
474 bjk = get_bond_length(nrbond, bonds, param->AJ, param->AK);
475 bjl = get_bond_length(nrbond, bonds, param->AJ, param->AL);
476 bjm = get_bond_length(nrbond, bonds, param->AJ, param->AM);
477 aijk= get_angle (nrang, angles, param->AI, param->AJ, param->AK);
478 aijl= get_angle (nrang, angles, param->AI, param->AJ, param->AL);
479 aijm= get_angle (nrang, angles, param->AI, param->AJ, param->AM);
480 akjm= get_angle (nrang, angles, param->AK, param->AJ, param->AM);
481 akjl= get_angle (nrang, angles, param->AK, param->AJ, param->AL);
482 bError = (bij==NOTSET) || (bjk==NOTSET) || (bjl==NOTSET) || (bjm==NOTSET) ||
483 (aijk==NOTSET) || (aijl==NOTSET) || (aijm==NOTSET) || (akjm==NOTSET) ||
484 (akjl==NOTSET);
486 pk = bjk*sin(aijk);
487 pl = bjl*sin(aijl);
488 pm = bjm*sin(aijm);
489 cosakl = (cos(akjl) - cos(aijk)*cos(aijl)) / (sin(aijk)*sin(aijl));
490 cosakm = (cos(akjm) - cos(aijk)*cos(aijm)) / (sin(aijk)*sin(aijm));
491 if ( cosakl < -1 || cosakl > 1 || cosakm < -1 || cosakm > 1 )
492 fatal_error(0,"invalid construction in calc_dum4fd for atom %u: "
493 "cosakl=%g cosakm=%g\n",param->AI+1,cosakl,cosakm);
494 sinakl = sqrt(1-sqr(cosakl));
495 sinakm = sqrt(1-sqr(cosakm));
497 /* note: there is a '+' because of the way the sines are calculated */
498 cl = -pk / ( pl*cosakl - pk + pl*sinakl*(pm*cosakm-pk)/(pm*sinakm) );
499 cm = -pk / ( pm*cosakm - pk + pm*sinakm*(pl*cosakl-pk)/(pl*sinakl) );
501 param->C0 = cl;
502 param->C1 = cm;
503 param->C2 = -bij;
504 if (debug)
505 fprintf(debug,"params for dummy4fd %u: %g %g %g\n",
506 param->AI+1,param->C0,param->C1,param->C2);
508 return bError;
511 int set_dummies(bool bVerbose, t_atoms *atoms, t_atomtype atype,
512 t_params plist[])
514 int i,j,ftype;
515 int ndum,nrbond,nrang,nridih,nrset;
516 bool bFirst,bSet,bERROR;
517 t_mybonded *bonds;
518 t_mybonded *angles;
519 t_mybonded *idihs;
521 bFirst = TRUE;
522 bERROR = TRUE;
523 ndum=0;
524 if (debug)
525 fprintf(debug, "\nCalculating parameters for dummy atoms\n");
526 for(ftype=0; (ftype<F_NRE); ftype++)
527 if (interaction_function[ftype].flags & IF_DUMMY) {
528 nrset=0;
529 ndum+=plist[ftype].nr;
530 for(i=0; (i<plist[ftype].nr); i++) {
531 /* check if all parameters are set */
532 bSet=TRUE;
533 for(j=0; j<NRFP(ftype) && bSet; j++)
534 bSet = plist[ftype].param[i].c[j]!=NOTSET;
536 if (debug) {
537 fprintf(debug,"bSet=%s ",bool_names[bSet]);
538 print_param(debug,ftype,i,&plist[ftype].param[i]);
540 if (!bSet) {
541 if (bVerbose && bFirst) {
542 fprintf(stderr,"Calculating parameters for dummy atoms\n");
543 bFirst=FALSE;
546 nrbond=nrang=nridih=0;
547 bonds = NULL;
548 angles= NULL;
549 idihs = NULL;
550 nrset++;
551 /* now set the dummy parameters: */
552 get_bondeds(NRAL(ftype), plist[ftype].param[i].a, plist,
553 &nrbond, &bonds, &nrang, &angles, &nridih, &idihs);
554 if (debug) {
555 fprintf(debug, "Found %d bonds, %d angles and %d idihs "
556 "for dummy atom %u (%s)\n",nrbond,nrang,nridih,
557 plist[ftype].param[i].AI+1,
558 interaction_function[ftype].longname);
559 print_bad(debug, nrbond, bonds, nrang, angles, nridih, idihs);
560 } /* debug */
561 switch(ftype) {
562 case F_DUMMY3:
563 bERROR =
564 calc_dum3_param(&atype, &(plist[ftype].param[i]), atoms,
565 nrbond, bonds, nrang, angles);
566 break;
567 case F_DUMMY3FD:
568 bERROR =
569 calc_dum3fd_param(&(plist[ftype].param[i]),
570 nrbond, bonds, nrang, angles);
571 break;
572 case F_DUMMY3FAD:
573 bERROR =
574 calc_dum3fad_param(&(plist[ftype].param[i]),
575 nrbond, bonds, nrang, angles);
576 break;
577 case F_DUMMY3OUT:
578 bERROR =
579 calc_dum3out_param(&atype, &(plist[ftype].param[i]), atoms,
580 nrbond, bonds, nrang, angles);
581 break;
582 case F_DUMMY4FD:
583 bERROR =
584 calc_dum4fd_param(&(plist[ftype].param[i]),
585 nrbond, bonds, nrang, angles);
586 break;
587 default:
588 fatal_error(0,"Automatic parameter generation not supported "
589 "for %s atom %d",
590 interaction_function[ftype].longname,
591 plist[ftype].param[i].AI+1);
592 } /* switch */
593 if (bERROR)
594 fatal_error(0,"Automatic parameter generation not supported "
595 "for %s atom %d for this bonding configuration",
596 interaction_function[ftype].longname,
597 plist[ftype].param[i].AI+1);
598 sfree(bonds);
599 sfree(angles);
600 sfree(idihs);
601 } /* if bSet */
602 } /* for i */
603 if (debug && plist[ftype].nr)
604 fprintf(stderr,"Calculated parameters for %d out of %d %s atoms\n",
605 nrset,plist[ftype].nr,interaction_function[ftype].longname);
606 } /* if IF_DUMMY */
608 return ndum;
611 void set_dummies_ptype(bool bVerbose, t_idef *idef, t_atoms *atoms)
613 int i,ftype;
614 int nra,nrd,tp;
615 t_iatom *ia,adum;
617 if (bVerbose)
618 fprintf(stderr,"Setting particle type to Dummy for dummy atoms\n");
619 if (debug)
620 fprintf(stderr,"checking %d functypes\n",F_NRE);
621 for(ftype=0; (ftype<F_NRE); ftype++) {
622 if (interaction_function[ftype].flags & IF_DUMMY) {
623 nra = interaction_function[ftype].nratoms;
624 nrd = idef->il[ftype].nr;
625 ia = idef->il[ftype].iatoms;
627 if (debug && nrd)
628 fprintf(stderr,"doing %d %s dummies\n",
629 (nrd / (nra+1)),interaction_function[ftype].longname);
631 for(i=0; (i<nrd); ) {
632 tp = ia[0];
633 assert(ftype == idef->functype[tp]);
635 /* The dummy atom */
636 adum = ia[1];
637 atoms->atom[adum].ptype=eptDummy;
639 i += nra+1;
640 ia += nra+1;
647 typedef struct {
648 int ftype,parnr;
649 } t_pindex;
651 static void check_dum_constraints(t_params *plist,
652 int cftype, int dummy_type[])
654 int i,k,n;
655 atom_id atom;
656 t_params *ps;
658 n=0;
659 ps = &(plist[cftype]);
660 for(i=0; (i<ps->nr); i++)
661 for(k=0; k<2; k++) {
662 atom = ps->param[i].a[k];
663 if (dummy_type[atom]!=NOTSET) {
664 fprintf(stderr,
665 "ERROR: Cannot have constraint (%u-%u) with dummy atom (%u)\n",
666 ps->param[i].AI+1, ps->param[i].AJ+1, atom+1);
667 n++;
670 if (n)
671 fatal_error(0,"There were %d dummy atoms involved in constraints",n);
674 static void clean_dum_bonds(t_params *plist, t_pindex pindex[],
675 int cftype, int dummy_type[])
677 int ftype,i,j,parnr,k,l,m,n,ndum,nOut,kept_i,dumnral,dumtype;
678 atom_id atom,oatom,constr,at1,at2;
679 atom_id dumatoms[MAXATOMLIST];
680 bool bKeep,bRemove,bUsed,bPresent,bThisFD,bThisOUT,bAllFD,bFirstTwo;
681 t_params *ps;
683 ps = &(plist[cftype]);
684 dumnral=0;
685 kept_i=0;
686 nOut=0;
687 for(i=0; (i<ps->nr); i++) { /* for all bonds in the plist */
688 bKeep=FALSE;
689 bRemove=FALSE;
690 bAllFD=TRUE;
691 /* check if all dummies are constructed from the same atoms */
692 ndum=0;
693 if(debug)
694 fprintf(debug,"constr %u %u:",ps->param[i].AI+1,ps->param[i].AJ+1);
695 for(k=0; (k<2) && !bKeep && !bRemove; k++) {
696 /* for all atoms in the bond */
697 atom = ps->param[i].a[k];
698 if (dummy_type[atom]!=NOTSET) {
699 if(debug) {
700 fprintf(debug," d%d[%d: %d %d %d]",k,atom+1,
701 plist[pindex[atom].ftype].param[pindex[atom].parnr].AJ+1,
702 plist[pindex[atom].ftype].param[pindex[atom].parnr].AK+1,
703 plist[pindex[atom].ftype].param[pindex[atom].parnr].AL+1);
705 ndum++;
706 bThisFD = ( (pindex[atom].ftype == F_DUMMY3FD ) ||
707 (pindex[atom].ftype == F_DUMMY3FAD) ||
708 (pindex[atom].ftype == F_DUMMY4FD ) );
709 bThisOUT= ( (pindex[atom].ftype == F_DUMMY3OUT) &&
710 (interaction_function[cftype].flags & IF_CONSTRAINT) );
711 bAllFD = bAllFD && bThisFD;
712 if (bThisFD || bThisOUT) {
713 if(debug)fprintf(debug," %s",bThisOUT?"out":"fd");
714 oatom = ps->param[i].a[1-k]; /* the other atom */
715 if ( dummy_type[oatom]==NOTSET &&
716 oatom==plist[pindex[atom].ftype].param[pindex[atom].parnr].AJ ){
717 /* if the other atom isn't a dummy, and it is AI */
718 bRemove=TRUE;
719 if (bThisOUT)
720 nOut++;
721 if(debug)fprintf(debug," D-AI");
724 if (!bRemove) {
725 if (ndum==1) {
726 /* if this is the first dummy we encounter then
727 store construction atoms */
728 dumnral=NRAL(pindex[atom].ftype)-1;
729 for(m=0; (m<dumnral); m++)
730 dumatoms[m]=
731 plist[pindex[atom].ftype].param[pindex[atom].parnr].a[m+1];
732 } else {
733 /* if it is not the first then
734 check if this dummy is constructed from the same atoms */
735 if (dumnral == NRAL(pindex[atom].ftype)-1 )
736 for(m=0; (m<dumnral) && !bKeep; m++) {
737 bPresent=FALSE;
738 constr=
739 plist[pindex[atom].ftype].param[pindex[atom].parnr].a[m+1];
740 for(n=0; (n<dumnral) && !bPresent; n++)
741 if (constr == dumatoms[n])
742 bPresent=TRUE;
743 if (!bPresent) {
744 bKeep=TRUE;
745 if(debug)fprintf(debug," !present");
748 else {
749 bKeep=TRUE;
750 if(debug)fprintf(debug," !same#at");
757 if (bRemove)
758 bKeep=FALSE;
759 else {
760 /* if we have no dummies in this bond, keep it */
761 if (ndum==0) {
762 if (debug)fprintf(debug," no dum");
763 bKeep=TRUE;
766 /* check if all non-dummy atoms are used in construction: */
767 bFirstTwo=TRUE;
768 for(k=0; (k<2) && !bKeep; k++) { /* for all atoms in the bond */
769 atom = ps->param[i].a[k];
770 if (dummy_type[atom]==NOTSET) {
771 bUsed=FALSE;
772 for(m=0; (m<dumnral) && !bUsed; m++)
773 if (atom == dumatoms[m]) {
774 bUsed=TRUE;
775 bFirstTwo = bFirstTwo && m<2;
777 if (!bUsed) {
778 bKeep=TRUE;
779 if(debug)fprintf(debug," !used");
784 if ( ! ( bAllFD && bFirstTwo ) )
785 /* check if all constructing atoms are constrained together */
786 for (m=0; m<dumnral && !bKeep; m++) { /* all constr. atoms */
787 at1 = dumatoms[m];
788 at2 = dumatoms[(m+1) % dumnral];
789 bPresent=FALSE;
790 for (ftype=0; ftype<F_NRE; ftype++)
791 if ( interaction_function[ftype].flags & IF_CONSTRAINT )
792 for (j=0; (j<plist[ftype].nr) && !bPresent; j++)
793 /* all constraints until one matches */
794 bPresent = ( ( (plist[ftype].param[j].AI == at1) &&
795 (plist[ftype].param[j].AJ == at2) ) ||
796 ( (plist[ftype].param[j].AI == at2) &&
797 (plist[ftype].param[j].AJ == at1) ) );
798 if (!bPresent) {
799 bKeep=TRUE;
800 if(debug)fprintf(debug," !bonded");
805 if ( bKeep ) {
806 if(debug)fprintf(debug," keeping");
807 /* now copy the bond to the new array */
808 memcpy(&(ps->param[kept_i]),
809 &(ps->param[i]),(size_t)sizeof(ps->param[0]));
810 kept_i++;
812 if(debug)fprintf(debug,"\n");
815 if (ps->nr != kept_i)
816 fprintf(stderr,"Removed %4d %15ss with dummy atoms, %5d left\n",
817 ps->nr-kept_i, interaction_function[cftype].longname, kept_i);
818 if (nOut)
819 fprintf(stderr,"Warning: removed %d %ss with dummy with %s construction\n"
820 " This dummy construction does not guarantee constant "
821 "bond-length\n"
822 " If the constructions were generated by pdb2gmx ignore "
823 "this warning\n",
824 nOut, interaction_function[cftype].longname,
825 interaction_function[F_DUMMY3OUT].longname );
826 ps->nr=kept_i;
829 static void clean_dum_angles(t_params *plist, t_pindex pindex[],
830 int cftype, int dummy_type[])
832 int ftype,i,j,parnr,k,l,m,n,ndum,kept_i,dumnral,dumtype;
833 atom_id atom,constr,at1,at2;
834 atom_id dumatoms[MAXATOMLIST];
835 bool bKeep,bUsed,bPresent,bAll3FAD,bFirstTwo;
836 t_params *ps;
838 ps = &(plist[cftype]);
839 dumnral=0;
840 kept_i=0;
841 for(i=0; (i<ps->nr); i++) { /* for all angles in the plist */
842 bKeep=FALSE;
843 bAll3FAD=TRUE;
844 /* check if all dummies are constructed from the same atoms */
845 ndum=0;
846 for(k=0; (k<3) && !bKeep; k++) { /* for all atoms in the angle */
847 atom = ps->param[i].a[k];
848 if (dummy_type[atom]!=NOTSET) {
849 ndum++;
850 bAll3FAD = bAll3FAD && (pindex[atom].ftype == F_DUMMY3FAD);
851 if (ndum==1) {
852 /* store construction atoms of first dummy */
853 dumnral=NRAL(pindex[atom].ftype)-1;
854 for(m=0; (m<dumnral); m++)
855 dumatoms[m]=
856 plist[pindex[atom].ftype].param[pindex[atom].parnr].a[m+1];
857 } else
858 /* check if this dummy is constructed from the same atoms */
859 if (dumnral == NRAL(pindex[atom].ftype)-1 )
860 for(m=0; (m<dumnral) && !bKeep; m++) {
861 bPresent=FALSE;
862 constr=
863 plist[pindex[atom].ftype].param[pindex[atom].parnr].a[m+1];
864 for(n=0; (n<dumnral) && !bPresent; n++)
865 if (constr == dumatoms[n])
866 bPresent=TRUE;
867 if (!bPresent)
868 bKeep=TRUE;
870 else
871 bKeep=TRUE;
875 /* keep all angles with no dummies in them or
876 with dummies with more than 3 constr. atoms */
877 if ( ndum == 0 && dumnral > 3 )
878 bKeep=TRUE;
880 /* check if all non-dummy atoms are used in construction: */
881 bFirstTwo=TRUE;
882 for(k=0; (k<3) && !bKeep; k++) { /* for all atoms in the angle */
883 atom = ps->param[i].a[k];
884 if (dummy_type[atom]==NOTSET) {
885 bUsed=FALSE;
886 for(m=0; (m<dumnral) && !bUsed; m++)
887 if (atom == dumatoms[m]) {
888 bUsed=TRUE;
889 bFirstTwo = bFirstTwo && m<2;
891 if (!bUsed)
892 bKeep=TRUE;
896 if ( ! ( bAll3FAD && bFirstTwo ) )
897 /* check if all constructing atoms are constrained together */
898 for (m=0; m<dumnral && !bKeep; m++) { /* all constr. atoms */
899 at1 = dumatoms[m];
900 at2 = dumatoms[(m+1) % dumnral];
901 bPresent=FALSE;
902 for (ftype=0; ftype<F_NRE; ftype++)
903 if ( interaction_function[ftype].flags & IF_CONSTRAINT )
904 for (j=0; (j<plist[ftype].nr) && !bPresent; j++)
905 /* all constraints until one matches */
906 bPresent = ( ( (plist[ftype].param[j].AI == at1) &&
907 (plist[ftype].param[j].AJ == at2) ) ||
908 ( (plist[ftype].param[j].AI == at2) &&
909 (plist[ftype].param[j].AJ == at1) ) );
910 if (!bPresent)
911 bKeep=TRUE;
914 if ( bKeep ) {
915 /* now copy the angle to the new array */
916 memcpy(&(ps->param[kept_i]),
917 &(ps->param[i]),(size_t)sizeof(ps->param[0]));
918 kept_i++;
922 if (ps->nr != kept_i)
923 fprintf(stderr,"Removed %4d %15ss with dummy atoms, %5d left\n",
924 ps->nr-kept_i, interaction_function[cftype].longname, kept_i);
925 ps->nr=kept_i;
928 static void clean_dum_dihs(t_params *plist, t_pindex pindex[],
929 int cftype, int dummy_type[])
931 int ftype,i,parnr,k,l,m,n,ndum,kept_i,dumnral;
932 atom_id atom,constr;
933 atom_id dumatoms[3];
934 bool bKeep,bUsed,bPresent;
935 t_params *ps;
937 ps = &(plist[cftype]);
939 dumnral=0;
940 kept_i=0;
941 for(i=0; (i<ps->nr); i++) { /* for all dihedrals in the plist */
942 bKeep=FALSE;
943 /* check if all dummies are constructed from the same atoms */
944 ndum=0;
945 for(k=0; (k<4) && !bKeep; k++) { /* for all atoms in the dihedral */
946 atom = ps->param[i].a[k];
947 if (dummy_type[atom]!=NOTSET) {
948 ndum++;
949 if (ndum==1) {
950 /* store construction atoms of first dummy */
951 dumnral=NRAL(pindex[atom].ftype)-1;
952 for(m=0; (m<dumnral); m++)
953 dumatoms[m]=
954 plist[pindex[atom].ftype].param[pindex[atom].parnr].a[m+1];
955 if (debug) {
956 fprintf(debug,"dih w. dum: %u %u %u %u\n",
957 ps->param[i].AI+1,ps->param[i].AJ+1,
958 ps->param[i].AK+1,ps->param[i].AL+1);
959 fprintf(debug,"dum %u from: %u %u %u\n",
960 atom+1,dumatoms[0]+1,dumatoms[1]+1,dumatoms[2]+1);
962 } else
963 /* check if this dummy is constructed from the same atoms */
964 if (dumnral == NRAL(pindex[atom].ftype)-1 )
965 for(m=0; (m<dumnral) && !bKeep; m++) {
966 bPresent=FALSE;
967 constr=
968 plist[pindex[atom].ftype].param[pindex[atom].parnr].a[m+1];
969 for(n=0; (n<dumnral) && !bPresent; n++)
970 if (constr == dumatoms[n])
971 bPresent=TRUE;
972 if (!bPresent)
973 bKeep=TRUE;
978 /* keep all dihedrals with no dummies in them */
979 if (ndum==0)
980 bKeep=TRUE;
982 /* check if all atoms in dihedral are either dummies, or used in
983 construction of dummies. If so, keep it, if not throw away: */
984 for(k=0; (k<4) && !bKeep; k++) { /* for all atoms in the dihedral */
985 atom = ps->param[i].a[k];
986 if (dummy_type[atom]==NOTSET) {
987 bUsed=FALSE;
988 for(m=0; (m<dumnral) && !bUsed; m++)
989 if (atom == dumatoms[m])
990 bUsed=TRUE;
991 if (!bUsed) {
992 bKeep=TRUE;
993 if (debug) fprintf(debug,"unused atom in dih: %u\n",atom+1);
998 if ( bKeep ) {
999 memcpy(&(ps->param[kept_i]),
1000 &(ps->param[i]),(size_t)sizeof(ps->param[0]));
1001 kept_i++;
1005 if (ps->nr != kept_i)
1006 fprintf(stderr,"Removed %4d %15ss with dummy atoms, %5d left\n",
1007 ps->nr-kept_i, interaction_function[cftype].longname, kept_i);
1008 ps->nr=kept_i;
1011 void clean_dum_bondeds(t_params *plist, int natoms, bool bRmDumBds)
1013 int i,k,ndum,ftype,parnr;
1014 int *dummy_type;
1015 t_pindex *pindex;
1017 pindex=0; /* avoid warnings */
1018 /* make dummy_type array */
1019 snew(dummy_type,natoms);
1020 for(i=0; i<natoms; i++)
1021 dummy_type[i]=NOTSET;
1022 ndum=0;
1023 for(ftype=0; ftype<F_NRE; ftype++)
1024 if (interaction_function[ftype].flags & IF_DUMMY) {
1025 ndum+=plist[ftype].nr;
1026 for(i=0; i<plist[ftype].nr; i++)
1027 if ( dummy_type[plist[ftype].param[i].AI] == NOTSET)
1028 dummy_type[plist[ftype].param[i].AI]=ftype;
1029 else
1030 fatal_error(0,"multiple dummy constructions for atom %d",
1031 plist[ftype].param[i].AI+1);
1034 /* the rest only if we have dummies: */
1035 if (ndum) {
1036 fprintf(stderr,"Cleaning up constraints %swith dummy particles\n",
1037 bRmDumBds?"and constant bonded interactions ":"");
1038 snew(pindex,natoms);
1039 for(ftype=0; ftype<F_NRE; ftype++)
1040 if (interaction_function[ftype].flags & IF_DUMMY)
1041 for (parnr=0; (parnr<plist[ftype].nr); parnr++) {
1042 k=plist[ftype].param[parnr].AI;
1043 pindex[k].ftype=ftype;
1044 pindex[k].parnr=parnr;
1047 if (debug)
1048 for(i=0; i<natoms; i++)
1049 fprintf(debug,"atom %d dummy_type %s\n",i,
1050 dummy_type[i]==NOTSET ? "NOTSET" :
1051 interaction_function[dummy_type[i]].name);
1053 /* remove things with dummy atoms */
1054 for(ftype=0; ftype<F_NRE; ftype++)
1055 if ( ( ( interaction_function[ftype].flags & IF_BOND ) && bRmDumBds ) ||
1056 ( interaction_function[ftype].flags & IF_CONSTRAINT ) ) {
1057 if (interaction_function[ftype].flags & (IF_BTYPE | IF_CONSTRAINT) )
1058 clean_dum_bonds (plist, pindex, ftype, dummy_type);
1059 else if (interaction_function[ftype].flags & IF_ATYPE)
1060 clean_dum_angles(plist, pindex, ftype, dummy_type);
1061 else if ( (ftype==F_PDIHS) || (ftype==F_IDIHS) )
1062 clean_dum_dihs (plist, pindex, ftype, dummy_type);
1064 /* check if we have constraints left with dummy atoms in them */
1065 for(ftype=0; ftype<F_NRE; ftype++)
1066 if (interaction_function[ftype].flags & IF_CONSTRAINT)
1067 check_dum_constraints(plist, ftype, dummy_type);
1070 sfree(pindex);
1071 sfree(dummy_type);