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 read_nwchem_geometry(gpointer scan, struct model_pak *model) { gint n, zmode=0, end_count=0; gchar **buff; struct core_pak *core; #if DEBUG_READ_NWCHEM_GEOMETRY printf("read_nwchem_geometry(): start\n"); #endif // TODO - rewrite this using symbol scanning functionality while (!scan_complete(scan)) { buff = scan_get_tokens(scan, &n); // zmatrix? if (g_ascii_strncasecmp(*buff, "zmatrix", 7) == 0) { zmode = 1; g_strfreev(buff); continue; } if (g_ascii_strncasecmp(*buff, "variables", 9) == 0) { zmode = 2; g_strfreev(buff); continue; } if (g_ascii_strncasecmp(*buff, "constants", 9) == 0) { zmode = 3; g_strfreev(buff); continue; } // end? if (n) { if (g_ascii_strncasecmp(*buff, "end", 3) == 0) { g_strfreev(buff); /* if we processed zmatrix entries - expect 2 x end */ if (zmode && !end_count) { /* keep going until we hit a second end ... */ end_count++; continue; } /* exit */ break; } } /* main parse */ switch (zmode) { // cartesian coords case 0: // can cart coord line have >4 tokens? if (n == 4) { if (elem_test(*buff)) { core = core_new(*buff, NULL, model); model->cores = g_slist_prepend(model->cores, core); core->x[0] = str_to_float(*(buff+1)); core->x[1] = str_to_float(*(buff+2)); core->x[2] = str_to_float(*(buff+3)); #if DEBUG_READ_NWCHEM_GEOMETRY printf("Added [%s] ", *buff); P3VEC(": ", core->x); #endif } } break; // zmatrix coords case 1: #if DEBUG_READ_NWCHEM_GEOMETRY printf("zcoord: %s", scan_cur_line(scan)); #endif zmat_nwchem_core_add(scan_cur_line(scan), model->zmatrix); break; // zmatrix vars case 2: #if DEBUG_READ_NWCHEM_GEOMETRY printf("zvar: %s", scan_cur_line(scan)); #endif zmat_var_add(scan_cur_line(scan), model->zmatrix); break; // zmatrix consts case 3: #if DEBUG_READ_NWCHEM_GEOMETRY printf("zconst: %s", scan_cur_line(scan)); #endif zmat_const_add(scan_cur_line(scan), model->zmatrix); break; } g_strfreev(buff); } if (zmode) { #if DEBUG_READ_NWCHEM_GEOMETRY printf("Creating zmatrix cores...\n"); #endif zmat_angle_units_set(model->zmatrix, DEGREES); zmat_process(model->zmatrix, model); } #if DEBUG_READ_NWCHEM_GEOMETRY printf("read_nwchem_geometry(): stop\n"); #endif return(0); }