void zmat_build(void) { gint i, j, k, n, type; gdouble r, a, d, x[4][3], v[3]; gdouble zaxis[3] = {0.0, 0.0, 1.0}; gchar *line; GSList *list, *species; struct zmat_pak *zmat; struct core_pak *core[4] = {NULL, NULL, NULL, NULL}; struct model_pak *model; model = sysenv.active_model; if (!model) return; /* CURRENT - using selection as our list of cores to generate a zmatrix from */ if (!model->selection) { gui_text_show(WARNING, "ZMATRIX: please select a molecule.\n"); return; } /* destroy old zmatrix */ /* TODO - prompt if non null */ zmat_free(model->zmatrix); zmat = model->zmatrix = zmat_new(); zmat_angle_units_set(model->zmatrix, DEGREES); /* setup SIESTA species type */ species = fdf_species_build(model); /* sort the list so it follows molecular connectivity */ model->selection = zmat_connect_sort(model->selection); n=0; for (list=model->selection ; list ; list=g_slist_next(list)) { /* current atom/zmatrix line init */ core[0] = list->data; type = fdf_species_index(core[0]->atom_label, species); line = NULL; zmat->zcores = g_slist_append(zmat->zcores, core[0]); /* build a ZMATRIX line for processing */ switch (n) { case 0: if (core[0]) { ARR3SET(x[0], core[0]->x); vecmat(model->latmat, x[0]); } line = g_strdup_printf("%d 0 0 0 %f %f %f 0 0 0\n", type, x[0][0], x[0][1], x[0][2]); break; case 1: if (core[0]) { ARR3SET(x[0], core[0]->x); vecmat(model->latmat, x[0]); } if (core[1]) { ARR3SET(x[1], core[1]->x); vecmat(model->latmat, x[1]); } r = measure_distance(x[0], x[1]); /* angle with z axis */ ARR3SET(v, x[0]); ARR3SUB(v, x[1]); a = R2D * via(v, zaxis, 3); /* angle between xy projection and x axis */ d = R2D * angle_x_compute(v[0], v[1]); line = g_strdup_printf("%d 1 0 0 %f %f %f 0 0 0\n", type, r, a, d); break; case 2: /* coords init */ for (i=3 ; i-- ; ) { if (core[i]) { ARR3SET(x[i], core[i]->x); vecmat(model->latmat, x[i]); } else g_assert_not_reached(); } r = measure_distance(x[0], x[1]); a = measure_angle(x[0], x[1], x[2]); /* create a fake core -> 1 unit displaced in the z direction */ g_assert(core[3] == NULL); core[3] = core_new("x", NULL, model); ARR3SET(core[3]->rx, core[2]->rx); ARR3ADD(core[3]->rx, zaxis); d = measure_torsion(core); core_free(core[3]); line = g_strdup_printf("%d 2 1 0 %f %f %f 0 0 0\n", type,r,a,d); break; default: /* connectivity test */ if (!zmat_bond_check(core[0], core[1])) { #if DEBUG_ZMAT_BUILD printf("[%d] non-connected atoms [%f]\n", n, measure_distance(x[0], x[1])); #endif /* need to build a new connectivity chain starting from core[0] */ core[1] = core[2] = core[3] = NULL; if (!zmat_connect_find(n, core, zmat)) { gui_text_show(WARNING, "ZMATRIX: bad connectivity (molecule will be incomplete)\n"); goto zmat_build_done; } } /* coords init */ for (i=3 ; i-- ; ) { if (core[i]) { ARR3SET(x[i], core[i]->x); vecmat(model->latmat, x[i]); } else g_assert_not_reached(); } r = measure_distance(x[0], x[1]); a = measure_angle(x[0], x[1], x[2]); d = measure_torsion(core); /* NB: indexing starts from 0, siesta starts from 1 (naturally) */ i = 1+g_slist_index(zmat->zcores, core[1]); j = 1+g_slist_index(zmat->zcores, core[2]); k = 1+g_slist_index(zmat->zcores, core[3]); line = g_strdup_printf("%d %d %d %d %f %f %f 0 0 0\n", type,i,j,k,r,a,d); } /* process a successfully constructed ZMATRIX line */ if (line) { zmat_core_add(line, model->zmatrix); g_free(line); } /* shuffle */ core[3] = core[2]; core[2] = core[1]; core[1] = core[0]; n++; } zmat_build_done: /* do the species typing */ zmat_type(model->zmatrix, species); free_slist(species); }
gint write_gromacs_dihedrals(FILE *fp, struct model_pak *model) { gint i, j, k, l, n; gdouble angle, da; GSList *list, *list1, *list2, *end1, *end2; GSList *d_list, *r_list, *i_list; struct core_pak *c[4]; struct bond_pak *bond; struct forcefield_pak *ff, *ff_gromacs; g_assert(model != NULL); d_list = ff_filter_list(FF_DIHEDRAL, model->ff_list); r_list = ff_filter_list(FF_DIHEDRAL_RB, model->ff_list); i_list = ff_filter_list(FF_IMPROPER, model->ff_list); /* header */ fprintf(fp, "\n[ dihedrals ]\n"); /* generate torsions for all combinations about a bond */ for (list=model->bonds ; list ; list=g_slist_next(list)) { bond = list->data; if (bond->type == BOND_HBOND) continue; c[1] = bond->atom1; c[2] = bond->atom2; /* get lists of connected atoms at each end */ end1 = connect_neighbours(c[1]); end1 = g_slist_remove(end1, c[2]); end2 = connect_neighbours(c[2]); end2 = g_slist_remove(end2, c[1]); /* skip bonds with no neighbour atoms */ /* if (!end1 || !end2) goto gromacs_dihedral_loop_done; */ /* enumerate four body terms */ for (list1=end1 ; list1 ; list1=g_slist_next(list1)) { c[0] = list1->data; for (list2=end2 ; list2 ; list2=g_slist_next(list2)) { c[3] = list2->data; /* search for standard dihedral potential */ ff = ff_search(c, 4, d_list); /* search for RB dihedral */ if (!ff) ff = ff_search(c, 4, r_list); /* CURRENT */ /* printf("[%s][%s][%s][%s]", c[0]->atom_label, c[1]->atom_label, c[2]->atom_label, c[3]->atom_label); printf(" : dihedral = %f\n", measure_torsion(c)); */ if (ff) { ff_gromacs = gromacs_type(ff); i = g_slist_index(model->cores, c[0])+1; j = g_slist_index(model->cores, c[1])+1; k = g_slist_index(model->cores, c[2])+1; l = g_slist_index(model->cores, c[3])+1; /* lambda 0 */ /* print atoms and type */ fprintf(fp, "%2d %2d %2d %2d %d ", i, j, k, l, ff_gromacs->type); /* NB: gromacs has the bond length 1st, followed by the potential parameters */ /* which is the reverse from internal/GULP format */ if (ff_gromacs->bond_expected) fprintf(fp, "%f", ff_gromacs->bond_value); for (n=0 ; n<ff_gromacs->data_expected ; n++) fprintf(fp, " %f", ff_gromacs->data[n]); /* lambda 1 */ fprintf(fp, " "); if (ff_gromacs->bond_expected) fprintf(fp, "%f", ff_gromacs->bond_value); for (n=0 ; n<ff_gromacs->data_expected ; n++) fprintf(fp, " %f", ff_gromacs->data[n]); fprintf(fp, "\n"); g_free(ff_gromacs); } } } g_slist_free(end1); g_slist_free(end2); } /* CURRENT - improper torsions (implemented as proper) */ /* FIXME - only valid for OPLS-AA */ /* fprintf(fp, "\n[ impropers ]\n"); */ fprintf(fp, "; Improper terms, implemented as proper torsions.\n"); /* for each atom with 3 bonds (planar) */ for (list=model->cores ; list ; list=g_slist_next(list)) { c[0] = list->data; list1 = connect_neighbours(c[0]); /* CHECK - only an atom with 3 bonds can be a candidate */ if (g_slist_length(list1) == 3) { c[1] = list1->data; list2 = g_slist_next(list1); c[2] = list2->data; list2 = g_slist_next(list2); c[3] = list2->data; /* TODO - want c[3] to be defined so that the c[1] - c[2] axis is */ /* orthogonal to the c[0] - c[3] direction */ /* TODO - choose c[1] & c[2] to be same type (if possible) */ /* improper torsion - only allow if angle is ~180 */ angle = measure_torsion(c); /* da = fabs(180.0 - fabs(angle)); */ da = fabs(angle); /* 10 degree tolerance */ ff = NULL; if (da < 10.0) ff = ff_search(c, 4, i_list); if (ff) { ff_gromacs = gromacs_type(ff); i = g_slist_index(model->cores, c[0])+1; j = g_slist_index(model->cores, c[1])+1; k = g_slist_index(model->cores, c[2])+1; l = g_slist_index(model->cores, c[3])+1; /* lambda 0 */ fprintf(fp, "%2d %2d %2d %2d 1 ", i, j, k, l); fprintf(fp, " %f", ff_gromacs->bond_value); for (n=0 ; n<ff_gromacs->data_current ; n++) fprintf(fp, " %f", ff_gromacs->data[n]); /* lambda 1 */ fprintf(fp, " %f", ff_gromacs->bond_value); for (n=0 ; n<ff_gromacs->data_current ; n++) fprintf(fp, " %f", ff_gromacs->data[n]); fprintf(fp, "\n"); g_free(ff_gromacs); } } g_slist_free(list1); } /* cleanup */ g_slist_free(d_list); g_slist_free(r_list); g_slist_free(i_list); return(0); }