2
Copyright (C) 2003 by Sean David Fleming
6
This program is free software; you can redistribute it and/or
7
modify it under the terms of the GNU General Public License
8
as published by the Free Software Foundation; either version 2
9
of the License, or (at your option) any later version.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
The GNU GPL can also be found at http://www.gnu.org
39
#include "interface.h"
42
extern struct sysenv_pak sysenv;
43
extern struct elem_pak elements[];
45
/************************************************/
46
/* convert internal forcefield type to GROMACS */
47
/************************************************/
48
gpointer gromacs_type(struct forcefield_pak *ff)
50
struct forcefield_pak *gff;
58
switch (ff->data_expected)
63
gff->data_expected = 1;
69
gff->data_expected = 2;
73
g_assert_not_reached();
80
gff->data_expected = 2;
85
switch (ff->data_expected)
89
gff->data_expected = 5;
96
gff->data_expected = 1;
103
gff->data_expected = 1;
107
gff->data_expected = 1;
111
gff->data_expected = 6;
117
gff->data_expected = 2;
121
gff->data_expected = 2;
125
/* GROMACS length units are nm */
126
switch (ff->bond_units)
129
gff->bond_value *= 0.1;
136
/******************************/
137
/* raw coordinate data (.gro) */
138
/******************************/
139
gint read_gromacs_gro(gchar *filename, struct model_pak *model)
145
g_assert(model != NULL);
147
fp = fopen(filename,"rt");
152
line = file_read_line(fp);
154
line = file_read_line(fp);
159
/* FIXME - properly should do formatted read, since things can be */
160
/* adjacent with no spaces in between -> tokenize() will fail */
162
fprintf(fp, "%5i%5s%5s%5i%8.3f%8.3f%8.3f%8.4f%8.4f%8.4f\n",
163
n, "UNK", core->atom_label, 1,
164
x[0], x[1], x[2], 0.1*core->v[0], 0.1*core->v[1], 0.1*core->v[2]);
167
if (strlen(line) > 10)
169
/* tokenize from atom label (avoids some problems with no space separation) */
170
buff = tokenize(&line[10], &num_tokens);
174
/* TODO - deal with water properly (ie set atom_types) */
175
if (g_ascii_strncasecmp(*(buff+0), "HW", 2) == 0)
178
*(buff+0) = g_strdup("H");
180
if (g_ascii_strncasecmp(*(buff+0), "OW", 2) == 0)
183
*(buff+0) = g_strdup("O");
186
if (elem_test(*(buff+0)))
188
struct core_pak *core = new_core(*(buff+0), model);
190
core->x[0] = 10.0*str_to_float(*(buff+2));
191
core->x[1] = 10.0*str_to_float(*(buff+3));
192
core->x[2] = 10.0*str_to_float(*(buff+4));
194
model->cores = g_slist_prepend(model->cores, core);
200
line = file_read_line(fp);
203
model->cores = g_slist_reverse(model->cores);
210
/******************************/
211
/* raw coordinate data (.gro) */
212
/******************************/
213
gint write_gromacs_gro(gchar *filename, struct model_pak *model)
216
gdouble x[3], min[3], max[3];
218
struct core_pak *core;
219
struct shel_pak *shell;
222
fp = fopen(filename, "wt");
226
/* init min/max for box calculation */
229
max[i] = -G_MAXDOUBLE;
230
min[i] = G_MAXDOUBLE;
233
fprintf(fp, "GROMACS coordinates (generated by GDIS v%f)\n", VERSION);
235
c = g_slist_length(model->cores);
236
s = g_slist_length(model->shels);
238
fprintf(fp, "%5d\n", c+s);
241
for (list=model->cores ; list ; list=g_slist_next(list))
247
vecmat(model->latmat, x);
250
fprintf(fp, "%5i%5s%5s%5i%8.3f%8.3f%8.3f%8.4f%8.4f%8.4f\n",
251
n, "UNK", core->atom_label, 1,
252
x[0], x[1], x[2], 0.1*core->v[0], 0.1*core->v[1], 0.1*core->v[2]);
254
/* record min/max for box calculation */
265
/* TODO - has an 'x' post-fix to the atom_label */
271
/* this is the distance between the min and max atom coords in x, y, and z */
272
/* box calculation */
273
if (model->periodic == 3)
275
fprintf(fp, "% f %f %f\n", 0.1*model->pbc[0], 0.1*model->pbc[1], 0.1*model->pbc[2]);
279
for (i=0 ; i<3 ; i++)
280
fprintf(fp, " %f", fabs(max[i] - min[i]));
289
/********************/
290
/* write the header */
291
/********************/
292
gint write_gromacs_header(FILE *fp, struct model_pak *model)
295
fprintf(fp, "\n;\n; Generated by GDIS v%f\n;\n", VERSION);
298
fprintf(fp, "\n[ system ]\n");
299
fprintf(fp, "%s\n", model->basename);
301
fprintf(fp, "\n[ moleculetype ]\n");
302
/* label, exclusion type */
303
fprintf(fp, "%s %d\n", model->basename, 3);
308
/********************/
309
/* write the footer */
310
/********************/
311
gint write_gromacs_footer(FILE *fp, struct model_pak *model)
314
fprintf(fp, "\n[ molecules ]\n");
315
/* label, number of occurences */
316
fprintf(fp, "%s 1\n", model->basename);
321
/*******************/
322
/* write the atoms */
323
/*******************/
324
gint write_gromacs_atoms(FILE *fp, struct model_pak *model)
329
struct core_pak *core;
331
fprintf(fp, "\n[ atoms ]\n");
334
for (list=model->cores ; list ; list=g_slist_next(list))
338
w = elements[core->atom_code].weight;
340
/* if 2nd column is atom type - use if available */
343
fprintf(fp, "%9d %5s %5d %5s %5s %5d %8.4f %8.4f",
344
n, core->atom_type, 1, "UNK", core->atom_label, n,
349
fprintf(fp, "%9d %5s %5d %5s %5s %5d %8.4f %8.4f",
350
n, core->atom_label, 1, "UNK", core->atom_label, n,
354
/* the lambda = 1.0 values - default to dummy for the time being */
355
fprintf(fp, " DUM 0.0 %8.4f\n", w);
363
/********************************/
364
/* write forcefield information */
365
/********************************/
366
gint write_gromacs_bonds(FILE *fp, struct model_pak *model)
370
struct core_pak *core[2];
371
struct forcefield_pak *ff, *ff_gromacs;
373
g_assert(model != NULL);
374
g_assert(fp != NULL);
377
fprintf(fp, "\n[ bonds ]\n");
379
/* for each bond FF type in the list -> ff_bond_search -> output */
380
for (list=model->bonds ; list ; list=g_slist_next(list))
382
struct bond_pak *bond = list->data;
384
core[0] = bond->atom1;
385
core[1] = bond->atom2;
387
ff = ff_search(core, 2, model->ff_list);
391
/* get core numbering order */
392
i = g_slist_index(model->cores, core[0]) + 1;
393
j = g_slist_index(model->cores, core[1]) + 1;
395
ff_gromacs = gromacs_type(ff);
398
/* print atoms and type */
399
fprintf(fp, "%2d %2d %d ", i, j, ff_gromacs->type);
401
/* NB: gromacs has the bond length 1st, followed by the potential parameters */
402
/* which is the reverse from internal/GULP format */
403
if (ff_gromacs->bond_expected)
404
fprintf(fp, "%f", ff_gromacs->bond_value);
405
for (n=0 ; n<ff_gromacs->data_expected ; n++)
406
fprintf(fp, " %f", ff_gromacs->data[n]);
410
if (ff_gromacs->bond_expected)
411
fprintf(fp, "%f", ff_gromacs->bond_value);
412
for (n=0 ; n<ff_gromacs->data_expected ; n++)
413
fprintf(fp, " %f", ff_gromacs->data[n]);
424
/********************************/
425
/* write forcefield information */
426
/********************************/
428
gint write_gromacs_angles(FILE *fp, struct model_pak *model)
430
gint i, j, k, m, n, ni, nj;
431
GSList *list1, *list2, *nlist;
432
struct core_pak *core[3], *nc[MAX_CORES];
433
struct forcefield_pak *ff, *ff_gromacs;
435
g_assert(model != NULL);
436
g_assert(fp != NULL);
439
fprintf(fp, "\n[ angles ]\n");
441
/* TODO - for all atoms with 2 + bonds -> check if 3 body term that matches */
442
for (list1=model->cores,k=1 ; list1 ; list1=g_slist_next(list1),k++)
444
core[1] = list1->data;
446
nlist = connect_neighbours(core[1]);
448
n = g_slist_length(nlist);
450
/* skip if too few, or suspiciously many */
451
if (n < 2 || n >= MAX_CORES)
455
for (list2 = nlist ; list2 ; list2=g_slist_next(list2))
456
nc[i++] = list2->data;
458
/* iterate over unique neighbour pairs */
459
for (i=0 ; i<n-1 ; i++)
463
for (j=i+1 ; j<n ; j++)
467
ff = ff_search(core, 3, model->ff_list);
471
/* TODO - write the entry */
473
printf("FF found\n");
476
/* get core numbering order */
477
ni = g_slist_index(model->cores, core[0]) + 1;
478
nj = g_slist_index(model->cores, core[2]) + 1;
480
ff_gromacs = gromacs_type(ff);
483
/* print atoms and type */
484
fprintf(fp, "%2d %2d %2d %d ", ni, k, nj, ff_gromacs->type);
486
/* NB: gromacs has the bond length 1st, followed by the potential parameters */
487
/* which is the reverse from internal/GULP format */
488
if (ff_gromacs->bond_expected)
489
fprintf(fp, "%f", ff_gromacs->bond_value);
490
for (m=0 ; m<ff_gromacs->data_expected ; m++)
491
fprintf(fp, " %f", ff_gromacs->data[m]);
495
if (ff_gromacs->bond_expected)
496
fprintf(fp, "%f", ff_gromacs->bond_value);
497
for (m=0 ; m<ff_gromacs->data_expected ; m++)
498
fprintf(fp, " %f", ff_gromacs->data[m]);
509
/********************************/
510
/* write forcefield information */
511
/********************************/
512
gint write_gromacs_dihedrals(FILE *fp, struct model_pak *model)
516
GSList *list, *list1, *list2, *end1, *end2;
517
GSList *d_list, *r_list, *i_list;
518
struct core_pak *c[4];
519
struct bond_pak *bond;
520
struct forcefield_pak *ff, *ff_gromacs;
522
g_assert(model != NULL);
524
d_list = ff_filter_list(FF_DIHEDRAL, model->ff_list);
525
r_list = ff_filter_list(FF_DIHEDRAL_RB, model->ff_list);
526
i_list = ff_filter_list(FF_IMPROPER, model->ff_list);
529
fprintf(fp, "\n[ dihedrals ]\n");
531
/* generate torsions for all combinations about a bond */
532
for (list=model->bonds ; list ; list=g_slist_next(list))
536
if (bond->type == BOND_HBOND)
542
/* get lists of connected atoms at each end */
543
end1 = connect_neighbours(c[1]);
544
end1 = g_slist_remove(end1, c[2]);
545
end2 = connect_neighbours(c[2]);
546
end2 = g_slist_remove(end2, c[1]);
548
/* skip bonds with no neighbour atoms */
551
goto gromacs_dihedral_loop_done;
554
/* enumerate four body terms */
555
for (list1=end1 ; list1 ; list1=g_slist_next(list1))
559
for (list2=end2 ; list2 ; list2=g_slist_next(list2))
563
/* search for standard dihedral potential */
564
ff = ff_search(c, 4, d_list);
566
/* search for RB dihedral */
568
ff = ff_search(c, 4, r_list);
572
printf("[%s][%s][%s][%s]", c[0]->atom_label, c[1]->atom_label, c[2]->atom_label, c[3]->atom_label);
573
printf(" : dihedral = %f\n", measure_torsion(c));
578
ff_gromacs = gromacs_type(ff);
580
i = g_slist_index(model->cores, c[0])+1;
581
j = g_slist_index(model->cores, c[1])+1;
582
k = g_slist_index(model->cores, c[2])+1;
583
l = g_slist_index(model->cores, c[3])+1;
586
/* print atoms and type */
587
fprintf(fp, "%2d %2d %2d %2d %d ", i, j, k, l, ff_gromacs->type);
588
/* NB: gromacs has the bond length 1st, followed by the potential parameters */
589
/* which is the reverse from internal/GULP format */
590
if (ff_gromacs->bond_expected)
591
fprintf(fp, "%f", ff_gromacs->bond_value);
592
for (n=0 ; n<ff_gromacs->data_expected ; n++)
593
fprintf(fp, " %f", ff_gromacs->data[n]);
597
if (ff_gromacs->bond_expected)
598
fprintf(fp, "%f", ff_gromacs->bond_value);
599
for (n=0 ; n<ff_gromacs->data_expected ; n++)
600
fprintf(fp, " %f", ff_gromacs->data[n]);
613
/* CURRENT - improper torsions (implemented as proper) */
614
/* FIXME - only valid for OPLS-AA */
616
fprintf(fp, "\n[ impropers ]\n");
618
fprintf(fp, "; Improper terms, implemented as proper torsions.\n");
620
/* for each atom with 3 bonds (planar) */
621
for (list=model->cores ; list ; list=g_slist_next(list))
625
list1 = connect_neighbours(c[0]);
627
/* CHECK - only an atom with 3 bonds can be a candidate */
628
if (g_slist_length(list1) == 3)
631
list2 = g_slist_next(list1);
633
list2 = g_slist_next(list2);
637
/* TODO - want c[3] to be defined so that the c[1] - c[2] axis is */
638
/* orthogonal to the c[0] - c[3] direction */
640
/* TODO - choose c[1] & c[2] to be same type (if possible) */
642
/* improper torsion - only allow if angle is ~180 */
643
angle = measure_torsion(c);
645
da = fabs(180.0 - fabs(angle));
649
/* 10 degree tolerance */
652
ff = ff_search(c, 4, i_list);
656
ff_gromacs = gromacs_type(ff);
658
i = g_slist_index(model->cores, c[0])+1;
659
j = g_slist_index(model->cores, c[1])+1;
660
k = g_slist_index(model->cores, c[2])+1;
661
l = g_slist_index(model->cores, c[3])+1;
664
fprintf(fp, "%2d %2d %2d %2d 1 ", i, j, k, l);
665
fprintf(fp, " %f", ff_gromacs->bond_value);
666
for (n=0 ; n<ff_gromacs->data_current ; n++)
667
fprintf(fp, " %f", ff_gromacs->data[n]);
670
fprintf(fp, " %f", ff_gromacs->bond_value);
671
for (n=0 ; n<ff_gromacs->data_current ; n++)
672
fprintf(fp, " %f", ff_gromacs->data[n]);
683
g_slist_free(d_list);
684
g_slist_free(r_list);
685
g_slist_free(i_list);
690
/********************************/
691
/* write forcefield information */
692
/********************************/
693
gint write_gromacs_nonbond(FILE *fp, struct model_pak *model)
697
struct forcefield_pak *ff, *ff_gromacs;
699
g_assert(model != NULL);
702
fprintf(fp, "\n[ nonbond_params ]\n");
704
for (list=model->ff_list ; list ; list=g_slist_next(list))
708
/* skip anything that doesnt have only 2 atom identifiers */
709
if (ff->atoms_expected != 2)
711
if (ff->atoms_current != 2)
714
/* GROMACS only supports LJ/BUCK */
715
if (ff->type == FF_LENNARD || ff->type == FF_BUCKINGHAM)
717
/* get appropriate type */
718
ff_gromacs = gromacs_type(ff);
721
fprintf(fp, "%s %s %d", ff->atom[0], ff->atom[1], ff_gromacs->type);
722
for (i=0 ; i<ff_gromacs->data_expected ; i++)
723
fprintf(fp, " %f", ff_gromacs->data[i]);
732
/***********************************************************/
733
/* topology ie molecule, connectivity, force fields (.top) */
734
/***********************************************************/
735
gint write_gromacs_top(gchar *filename, struct model_pak *model)
739
fp = fopen(filename, "wt");
741
/* for each molecule write topology entry */
742
/* TODO - sort into unique molecules (atoms must also be ordered the same) */
744
write_gromacs_header(fp, model);
746
write_gromacs_atoms(fp, model);
748
write_gromacs_bonds(fp, model);
750
write_gromacs_angles(fp, model);
752
write_gromacs_dihedrals(fp, model);
754
write_gromacs_nonbond(fp, model);
756
write_gromacs_footer(fp, model);
766
gint write_gromacs(gchar *filename, struct model_pak *model)
770
temp = parse_extension_set(filename, "top");
772
write_gromacs_gro(filename, model);
773
write_gromacs_top(temp, model);
780
/********************************/
781
/* read in a GROMACS FF library */
782
/********************************/
783
#define DEBUG_GROMACS_READ_FF 0
784
GSList *gromacs_read_ff(const gchar *filename)
786
gint state, type, num_tokens, ub, ua, ud, i;
787
gchar *line, **buff, **abuff, **dbuff;
789
struct forcefield_pak *ff;
792
fp = fopen(filename, "rt");
796
/* unknown bond, angle, dihedral types */
799
/* stop auto skip of lines starting with # ... ie #define */
800
file_skip_comment(FALSE);
802
line = file_read_line(fp);
806
/* TODO - get rid of leading whitespace, so funny comment lines are properly ignored */
810
/* directive processing */
815
if (g_strrstr(line, "bond"))
817
if (g_strrstr(line, "angle"))
819
if (g_strrstr(line, "dihedral"))
823
/* process #defines */
825
if (g_ascii_strncasecmp("#define", line, 7) == 0)
827
buff = get_tokens(line, 3);
828
abuff = g_strsplit(*(buff+1), "_", -1);
830
#if GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 6
831
num_tokens = g_strv_length(abuff);
838
if (g_ascii_strncasecmp(*(abuff), "improper", 8) == 0)
842
ff = ff_type_new(FF_IMPROPER);
843
g_snprintf(ff->atom[0], FF_MAX_SYMBOL, "%s", *(abuff+num_tokens-4));
844
g_snprintf(ff->atom[1], FF_MAX_SYMBOL, "%s", *(abuff+num_tokens-3));
845
g_snprintf(ff->atom[2], FF_MAX_SYMBOL, "%s", *(abuff+num_tokens-2));
846
g_snprintf(ff->atom[3], FF_MAX_SYMBOL, "%s", *(abuff+num_tokens-1));
847
/* TODO - Y, Z -> X ... since X is wildcard type */
849
if (ff->atom[i][0] == 'Y' || ff->atom[i][0] == 'Z')
850
ff->atom[i][0] = 'X';
852
dbuff = get_tokens(line, 6);
853
ff->bond_value = str_to_float(*(dbuff+2));
854
ff->bond_units = FF_DEG;
855
ff->data[0] = str_to_float(*(dbuff+3));
856
ff->data[1] = str_to_float(*(dbuff+4));
859
ff->atoms_current = ff->atoms_expected;
860
ff->data_current = ff->data_expected = 2;
862
list = g_slist_prepend(list, ff);
878
/* normal processing */
879
buff = tokenize(line, &num_tokens);
885
type = g_ascii_strtod(*(buff+2), NULL);
889
ff = ff_type_new(FF_HARMONIC);
890
g_snprintf(ff->atom[0], FF_MAX_SYMBOL, "%s", *(buff+0));
891
g_snprintf(ff->atom[1], FF_MAX_SYMBOL, "%s", *(buff+1));
892
/* NB: GROMACS uses nm rather than angs */
893
ff->bond_value = 10.0 * str_to_float(*(buff+3));
894
ff->bond_units = FF_ANG;
895
/* nm -> ang correction */
896
ff->data[0] = 0.01 * str_to_float(*(buff+4));
897
ff->data_units = FF_KJ;
899
ff->atoms_current = ff->atoms_expected;
900
ff->data_current = ff->data_expected;
904
g_assert(num_tokens > 5);
905
ff = ff_type_new(FF_MORSE);
906
g_snprintf(ff->atom[0], FF_MAX_SYMBOL, "%s", *(buff+0));
907
g_snprintf(ff->atom[1], FF_MAX_SYMBOL, "%s", *(buff+1));
908
/* nm -> ang correction */
909
ff->bond_value = 10.0*str_to_float(*(buff+3));
910
ff->bond_units = FF_ANG;
911
ff->data[0] = str_to_float(*(buff+4));
912
ff->data[1] = 0.1 * str_to_float(*(buff+5));
913
ff->data_units = FF_KJ;
915
ff->atoms_current = ff->atoms_expected;
916
ff->data_current = ff->data_expected;
928
type = g_ascii_strtod(*(buff+3), NULL);
932
ff = ff_type_new(FF_3B_HARMONIC);
933
g_snprintf(ff->atom[0], FF_MAX_SYMBOL, "%s", *(buff+0));
934
g_snprintf(ff->atom[1], FF_MAX_SYMBOL, "%s", *(buff+1));
935
g_snprintf(ff->atom[2], FF_MAX_SYMBOL, "%s", *(buff+2));
936
ff->bond_value = str_to_float(*(buff+4));
937
ff->bond_units = FF_DEG;
938
ff->data[0] = str_to_float(*(buff+5));
939
/* strictly - kJ/mol rad-2 */
940
ff->data_units = FF_KJ;
941
ff->atoms_current = ff->atoms_expected;
942
ff->data_current = ff->data_expected;
954
type = g_ascii_strtod(*(buff+4), NULL);
963
ff = ff_type_new(FF_DIHEDRAL);
964
g_snprintf(ff->atom[0], FF_MAX_SYMBOL, "%s", *(buff+0));
965
g_snprintf(ff->atom[1], FF_MAX_SYMBOL, "%s", *(buff+1));
966
g_snprintf(ff->atom[2], FF_MAX_SYMBOL, "%s", *(buff+2));
967
g_snprintf(ff->atom[3], FF_MAX_SYMBOL, "%s", *(buff+3));
968
ff->bond_value = str_to_float(*(buff+5));
969
ff->bond_units = FF_DEG;
970
ff->data[0] = str_to_float(*(buff+6));
971
ff->data_units = FF_KJ;
972
ff->atoms_current = ff->atoms_expected;
973
ff->data_current = ff->data_expected;
982
ff = ff_type_new(FF_DIHEDRAL_RB);
983
g_snprintf(ff->atom[0], FF_MAX_SYMBOL, "%s", *(buff+0));
984
g_snprintf(ff->atom[1], FF_MAX_SYMBOL, "%s", *(buff+1));
985
g_snprintf(ff->atom[2], FF_MAX_SYMBOL, "%s", *(buff+2));
986
g_snprintf(ff->atom[3], FF_MAX_SYMBOL, "%s", *(buff+3));
987
ff->data[0] = str_to_float(*(buff+5));
988
ff->data[1] = str_to_float(*(buff+6));
989
ff->data[2] = str_to_float(*(buff+7));
990
ff->data[3] = str_to_float(*(buff+8));
991
ff->data[4] = str_to_float(*(buff+9));
992
ff->data[5] = str_to_float(*(buff+10));
993
ff->data_units = FF_KJ;
995
ff->atoms_current = ff->atoms_expected;
996
ff->data_current = ff->data_expected;
1006
/* add the object to the return list */
1008
list = g_slist_prepend(list, ff);
1015
line = file_read_line(fp);
1020
#if DEBUG_GROMACS_READ_FF
1021
printf("processed: %d items.\n", g_slist_length(list));
1022
printf("ignored: [bonds = %d] [angles = %d] [dihedrals = %d]\n", ub, ua, ud);
1024
ff_dump_type(FF_IMPROPER, list);
1028
file_skip_comment(TRUE);