Beispiel #1
0
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);
}