void coords_confine_cores(GSList *cores, struct model_pak *model) { gint dummy[3]; gdouble x[3]; GSList *list; struct core_pak *core; struct shel_pak *shell; g_assert(model != NULL); if (!model->periodic) return; /* translate cores to within the cell */ for (list=cores ; list ; list=g_slist_next(list)) { core = list->data; fractional_clamp(core->x, dummy, model->periodic); /* move shell */ if (core->shell) { shell = core->shell; /* want core-shell distance to be smallest possible */ ARR3SET(x, shell->x); ARR3SUB(x, core->x); fractional_min(x, model->periodic); ARR3SET(shell->x, core->x); ARR3ADD(shell->x, x); } } }
void camera_rescale(gdouble r, gpointer data) { gdouble x[3]; struct camera_pak *camera = data; ARR3SET(x, camera->x); normalize(x, 3); VEC3MUL(x, r); ARR3SET(camera->x, x); }
struct core_pak *copy_core(struct core_pak *core, struct model_pak *src, struct model_pak *dest) { gint items=0; gdouble vec[3]; struct core_pak *copyc; struct shel_pak *copys; /* checks */ g_assert(core != NULL); g_assert(src != NULL); g_assert(dest != NULL); /* duplicate data structure */ copyc = dup_core(core); items++; /* setup status */ copyc->status = copyc->status & (~SELECT & ~SELECT); copyc->orig = copyc->primary = TRUE; copyc->primary_core = NULL; VEC3SET(copyc->offset, 0.0, 0.0, 0.0); /* coords, account for transformation matrices */ ARR3SET(vec, core->rx); vecmat(dest->ilatmat, vec); ARR3ADD(vec, dest->centroid); ARR3SET(copyc->x, vec); dest->cores = g_slist_prepend(dest->cores, copyc); /* attached shell? */ if (copyc->shell) { copys = copyc->shell; items++; /* main info */ copys->status = copys->status & (~SELECT); copys->primary=copys->orig=TRUE; copys->primary_shell = NULL; VEC3SET(copys->offset, 0.0, 0.0, 0.0); /* coords, account for transformation matrices */ ARR3SET(vec, copys->rx); vecmat(dest->ilatmat, vec); ARR3ADD(vec, dest->centroid); ARR3SET(copys->x, vec); dest->shels = g_slist_prepend(dest->shels, copys); } return(copyc); }
void core_init(gchar *elem, struct core_pak *core, struct model_pak *model) { gint code; struct elem_pak elem_data; /* attempt to match atom type with database */ if (model->protein) code = pdb_elem_type(elem); else code = elem_test(elem); /* general initialization */ core->atom_code = code; core->atom_type = NULL; core->atom_label = NULL; core->res_name = NULL; core->res_no = 1; core->chain = NULL; core->atom_order = 0; /* default values for NMR values */ core->atom_nmr_shift=0.0; core->atom_nmr_aniso=0.0; core->atom_nmr_asym=0.0; core->atom_nmr_cq=0.0; core->atom_nmr_efgasym=0.0; /* element related initialization */ get_elem_data(code, &elem_data, model); core->bond_cutoff = elem_data.cova; ARR3SET(core->colour, elem_data.colour); core->colour[3] = 1.0; }
void gui_siesta_mode_show(GtkWidget *w, gpointer dialog) { gint i, atom, state; gdouble scale, x1[3], x2[3], colour[3]; gpointer button, spin; GSList *list; struct core_pak *core; struct spatial_pak *spatial; struct model_pak *model; g_assert(dialog != NULL); model = dialog_model(dialog); g_assert(model != NULL); button = dialog_child_get(dialog, "phonon_toggle"); g_assert(button != NULL); spatial_destroy_by_label("siesta_phonons", model); state = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)); if (!state) { redraw_canvas(SINGLE); return; } spin = dialog_child_get(dialog, "phonon_scaling"); scale = SPIN_FVAL(spin); /* create & init the spatial object */ spatial = spatial_new("siesta_phonons", SPATIAL_VECTOR, 2, TRUE, model); atom = 0; /* get eigenvectors from all atoms */ for (list=model->cores ; list; list=g_slist_next(list)) { core = list->data; ARR3SET(x1, core->x); /* get current eigenvector */ i = model->siesta.sorted_eig_values[model->siesta.current_animation]; x2[0] = mesch_me_get(model->siesta.eigen_xyz_atom_mat, 3*atom, i); x2[1] = mesch_me_get(model->siesta.eigen_xyz_atom_mat, 3*atom+1, i); x2[2] = mesch_me_get(model->siesta.eigen_xyz_atom_mat, 3*atom+2, i); atom++; /* compute coords */ VEC3MUL(x2, scale); vecmat(model->ilatmat, x2); ARR3ADD(x2, x1); /* add to spatial */ spatial_vertex_add(x2, colour, spatial); spatial_vertex_add(x1, colour, spatial); } /* drawing update */ coords_compute(model); redraw_canvas(SINGLE); }
/* NB - this is siesta specific */ void zmat_coord_print(FILE *fp, GSList *species_list, gpointer data) { gint i, j; gdouble x[3]; GSList *list, *clist, *slist; struct model_pak *model=data; struct species_pak *species_data; struct core_pak *core; struct zmat_pak *zmat; g_assert(data != NULL); clist = g_slist_copy(model->cores); zmat = model->zmatrix; g_assert(zmat != NULL); for (list=zmat->zcores ; list ; list=g_slist_next(list)) clist = g_slist_remove(clist, list->data); j = 1 + g_slist_length(zmat->zcores); if (clist) { if (model->fractional) fprintf(fp, "fractional\n"); else fprintf(fp, "cartesian\n"); for (list=clist ; list ; list=g_slist_next(list)) { core = list->data; ARR3SET(x, core->x); /* NB: want fractional if 3D periodic, otherwise cartesian */ if (!model->fractional) vecmat(model->latmat, x); /* find corresponding number of this element in the species block */ i=1; for (slist=species_list ; slist ; slist=g_slist_next(slist)) { species_data = slist->data; if (g_ascii_strcasecmp(core->atom_label, species_data->label) == 0) break; i++; } fprintf(fp," %d %14.9f %14.9f %14.9f 1 1 1 %d\n", i, x[0], x[1], x[2], j++); } } g_slist_free(clist); }
void camera_view(gdouble *v, gpointer data) { struct camera_pak *camera = data; g_assert(data != NULL); ARR3SET(v, camera->v); if (camera->mode == LOCKED) quat_rotate(v, camera->q); }
gint facet_equiv(struct model_pak *data, gint *f1, gint *f2) { gint i, index[3]; gdouble vec[3]; #if DEBUG_FACET_EQUIV printf("facet_equiv(): [%d %d %d] and (%d %d %d)\n", f1[0], f1[1], f1[2], f2[0], f2[1], f2[2]); #endif /* symmetry test */ if (data->sginfo.spacenum > 0) { for (i=0 ; i<data->sginfo.order ; i++) { ARR3SET(vec, f1); vecmat(*(data->sginfo.matrix+i), vec); ARR3SET(index, vec); #if DEBUG_FACET_EQUIV P3VEC("op -> ", vec); #endif if (index[0] == *f2 && index[1] == *(f2+1) && index[2] == *(f2+2)) { #if DEBUG_FACET_EQUIV printf(" *** equivalent (symop %d).\n", i); #endif return(TRUE); } } } else printf("No space group information.\n"); #if DEBUG_FACET_EQUIV printf("not equivalent.\n"); #endif return(FALSE); }
gint write_dmol(gchar *filename, struct model_pak *model) { gint i; gdouble x[3]; GSList *list; struct core_pak *core; FILE *fp; /* checks */ g_return_val_if_fail(model != NULL, 1); g_return_val_if_fail(filename != NULL, 2); /* open the file */ fp = fopen(filename,"wt"); if (!fp) return(3); if (model->periodic == 3) { fprintf(fp, "$cell vectors\n"); /* NB: DMOL matrices are transposed wrt gdis */ for (i=0 ; i<3 ; i++) { fprintf(fp, " %20.14f%20.14f%20.14f\n", model->latmat[i]/AU2ANG, model->latmat[i+3]/AU2ANG, model->latmat[i+6]/AU2ANG); } } fprintf(fp, "$coordinates\n"); for (list=model->cores ; list ; list=g_slist_next(list)) { core = list->data; if (core->status & DELETED) continue; /* everything is cartesian after latmat mult */ ARR3SET(x, core->x); vecmat(model->latmat, x); fprintf(fp,"%-10s%20.14f%20.14f%20.14f%5d\n", elements[core->atom_code].symbol, x[0]/AU2ANG, x[1]/AU2ANG, x[2]/AU2ANG, core->atom_code); } fprintf(fp, "$end\n"); fclose(fp); return(0); }
void camera_rotate_animate(gint axis, gdouble *angle, gint overwrite, struct model_pak *model) { gdouble a, radian[3]; GSList *journey; struct camera_pak *camera; g_assert(model != NULL); dialog_destroy_type(ANIM); /* TODO - angle checks */ ARR3SET(radian, angle); VEC3MUL(radian, D2R); journey = NULL; for (a=radian[0] ; a<radian[1]+0.5*radian[2] ; a+=radian[2]) { camera = camera_dup(model->camera); switch (axis) { case 1: quat_concat_euler(camera->q, ROLL, a); break; case 2: quat_concat_euler(camera->q, YAW, a); break; default: quat_concat_euler(camera->q, PITCH, a); } journey = g_slist_prepend(journey, camera); } journey = g_slist_reverse(journey); if (overwrite) { free_slist(model->transform_list); model->transform_list = journey; } else model->transform_list = g_slist_concat(model->transform_list, journey); model->num_frames = g_slist_length(model->transform_list); model->animation = TRUE; redraw_canvas(SINGLE); }
gpointer shell_new(gchar *elem, gchar *label, struct model_pak *model) { gint code; struct elem_pak elem_data; struct shel_pak *shell; g_assert(elem != NULL); g_assert(model != NULL); shell = g_malloc(sizeof(struct shel_pak)); /* attempt to match atom type with database */ code = elem_test(elem); if (!code) printf("Warning: element [%s] not found.\n", elem); /* init modifiable element data */ get_elem_data(code, &elem_data, model); ARR3SET(shell->colour, elem_data.colour); shell->atom_code = code; if (label) shell->shell_label = g_strdup(label); else shell->shell_label = g_strdup(elem); VEC4SET(shell->x, 0.0, 0.0, 0.0, 1.0); VEC4SET(shell->rx, 0.0, 0.0, 0.0, 1.0); VEC3SET(shell->v, 0.0, 0.0, 0.0); VEC3SET(shell->offset, 0.0, 0.0, 0.0); shell->status = NORMAL; shell->primary = TRUE; shell->orig = TRUE; shell->breathe = FALSE; shell->translate = FALSE; shell->region = REGION1A; shell->core = NULL; shell->primary_shell = NULL; shell->radius = 0.0; shell->charge = 0.0; shell->has_sof = FALSE; shell->sof = 1.0; shell->lookup_charge = TRUE; shell->flags = NULL; return(shell); }
void show_phonon_components(struct model_pak *model) { gdouble f, lc, lf, xc[3], xf[3]; gpointer ptr; GSList *list; struct core_pak *core; /* checks */ if (!model) return; /* get required mode to analyse */ ptr = g_slist_nth_data(model->phonons, model->current_phonon-1); if (!ptr) return; f = str_to_float(ptr); printf("--------------------------------------------------------------------------\n"); printf("Mode: %d, Frequency = %f\n", model->current_phonon, f); printf("--------------------------------------------------------------------------\n"); printf(" atom | len | x y z | a b c\n"); printf("--------------------------------------------------------------------------\n"); for (list=model->selection ; list; list=g_slist_next(list)) { core = (struct core_pak *) list->data; /* get eigen-vector components */ xc[0] = *((gdouble *) g_slist_nth_data(core->vibx_list, model->current_phonon-1)); xc[1] = *((gdouble *) g_slist_nth_data(core->viby_list, model->current_phonon-1)); xc[2] = *((gdouble *) g_slist_nth_data(core->vibz_list, model->current_phonon-1)); ARR3SET(xf, xc); vecmat(model->ilatmat, xf); lc = VEC3MAG(xc); lf = VEC3MAG(xf); VEC3MUL(xc, 1.0/lc); VEC3MUL(xf, 1.0/lf); printf("%6s | %7.4f | %7.2f %7.2f %7.2f | %7.2f %7.2f %7.2f\n", core->atom_label, lc, xc[0], xc[1], xc[2], xf[0], xf[1], xf[2]); } }
gint write_aims(gchar *filename, struct model_pak *model) { gint i; gdouble x[3]; GSList *list; struct core_pak *core; FILE *fp; /* checks */ g_return_val_if_fail(model != NULL, 1); g_return_val_if_fail(filename != NULL, 2); /* open the file */ fp = fopen(filename,"wt"); if (!fp) return(3); if (model->periodic == 3) { /* TODO: check whether lattice vectors in AIMS are transposed with respect GDIS */ for (i=0 ; i<3 ; i++) { fprintf(fp,"lattice_vector %14.8f %14.8f %14.8f \n", model->latmat[0+i], model->latmat[3+i], model->latmat[6+i]); } } for (list=model->cores ; list ; list=g_slist_next(list)) { core = list->data; if (core->status & DELETED) continue; /* everything is cartesian after latmat mult */ ARR3SET(x, core->x); vecmat(model->latmat, x); fprintf(fp," atom %14.8f %14.8f %14.8f %3s \n", x[0], x[1], x[2], elements[core->atom_code].symbol); } fclose(fp); return(0); }
void coords_confine_centroid(struct mol_pak *mol, struct model_pak *model) { gint xlat[3]; gdouble mov[3]; GSList *list; struct core_pak *core; /* calc moves required to bring centroid within pbc */ fractional_clamp(mol->centroid, xlat, model->periodic); ARR3SET(mov, xlat); /* apply to all atoms/shells in this molecule */ for (list=mol->cores ; list ; list=g_slist_next(list)) { core = list->data; ARR3ADD(core->x, mov); if (core->shell) { ARR3ADD((core->shell)->x, mov); } } }
gint facet_visible(struct model_pak *data, struct plane_pak *plane) { gdouble a, norm[3], vec[3]; /* NEW - an edge (2 vertices) is not to be treated as visible */ if (g_slist_length(plane->vertices) < 3) return(FALSE); /* get plane normal */ ARR3SET(norm, plane->norm); VEC3MUL(norm, -1.0); #if DEBUG_FACET printf("facet (%2d%2d%2d), norm: %5.2f,%5.2f,%5.2f " ,plane->index[0] ,plane->index[1] ,plane->index[2] ,norm[0],norm[1],norm[2]); #endif /* absolute viewing vector, determining if visible or not */ camera_view(vec, data->camera); /* got correct facet normal - is it visible? */ a = via(norm,vec,3); if (a < 0.5*G_PI) { #if DEBUG_FACET printf("view: %5.2f,%5.2f,%5.2f (%5.1f) YES\n",vec[0],vec[1],vec[2],180.0*a/PI); #endif return(TRUE); } /* else... */ #if DEBUG_FACET printf("view: %5.2f,%5.2f,%5.2f (%5.1f) NO\n",vec[0],vec[1],vec[2],180.0*a/PI); #endif return(FALSE); }
// not really an animate function as such... void gui_animate_phonon_vectors(struct model_pak *model) { gdouble *v, x1[3], x2[3], colour[3]; gpointer spatial, ptr; GSList *list, *xlist, *ylist, *zlist; struct core_pak *core, *prim; if (!model) return; /* create & init the spatial object */ spatial_destroy_by_label("phonons", model); spatial = spatial_new("phonons", SPATIAL_VECTOR, 2, TRUE, model); /* get eigenvectors from all atoms */ for (list=model->cores ; list; list=g_slist_next(list)) { core = list->data; ARR3SET(x1, core->x); /* get eigenvector list */ if (core->primary) { xlist = core->vibx_list; ylist = core->viby_list; zlist = core->vibz_list; } else { prim = core->primary_core; xlist = prim->vibx_list; ylist = prim->viby_list; zlist = prim->vibz_list; } if (!xlist || !ylist || !zlist) { printf("Missing phonon eigenvectors.\n"); return; } /* vibrational eigenvector */ /* NB: current_phonon starts from 1 */ ptr = g_slist_nth_data(xlist, model->current_phonon-1); if (ptr) x2[0] = *((gdouble *) ptr); ptr = g_slist_nth_data(ylist, model->current_phonon-1); if (ptr) x2[1] = *((gdouble *) ptr); v = g_slist_nth_data(zlist, model->current_phonon-1); if (ptr) x2[2] = *v; /* pulse offset scaling */ VEC3MUL(x2, sysenv.render.phonon_scaling); vecmat(model->ilatmat, x2); /* TODO - unify with siesta */ /* i = model->siesta.sorted_eig_values[model->siesta.current_animation]; x2[0] = mesch_me_get(model->siesta.eigen_xyz_atom_mat, 3*atom, i); x2[1] = mesch_me_get(model->siesta.eigen_xyz_atom_mat, 3*atom+1, i); x2[2] = mesch_me_get(model->siesta.eigen_xyz_atom_mat, 3*atom+2, i); atom++; */ /* compute coords */ ARR3ADD(x2, x1); /* add to spatial */ spatial_vertex_add(x2, colour, spatial); spatial_vertex_add(x1, colour, spatial); } coords_compute(model); gui_refresh(GUI_CANVAS); }
void delete_duplicate_cores(struct model_pak *model) { gdouble vec[3]; GSList *list1, *list2, *za_list; gpointer zone; struct core_pak *core1, *core2; struct shel_pak *s1, *s2; /* checks */ g_assert(model != NULL); g_assert(model->zone_array != NULL); #if DEBUG_REMOVE_DUPLICATES printf("Initial cores: %d\n", g_slist_length(model->cores)); printf("Initial shels: %d\n", g_slist_length(model->shels)); #endif /* enumerate all cores */ for (list1=model->cores ; list1 ; list1=g_slist_next(list1)) { core1 = list1->data; if (core1->status & DELETED) continue; /* enumerate cores in current locality */ zone = zone_get(core1->x, model->zone_array); #if DEBUG_REMOVE_DUPLICATES_MORE printf(" + %s [%p] : [%p] :", core1->atom_label, core1, zone); P3VEC(" ", core1->x); #endif /* should use zone_area_cores() as a very small coord difference */ /* can result in cores being put in different (neighbouring) zones */ /* for (list2=zone_cores(zone) ; list2 ; list2=g_slist_next(list2)) */ za_list = zone_area_cores(1, zone, model->zone_array); for (list2=za_list ; list2 ; list2=g_slist_next(list2)) { core2 = list2->data; if (core2->status & DELETED) continue; /* avoid double counting */ if (core1 >= core2) continue; if (core1->atom_code != core2->atom_code) continue; #if DEBUG_REMOVE_DUPLICATES_MORE printf(" - %s :", core2->atom_label); P3VEC(" ", core2->x); #endif /* compute and test the minimum separation */ ARR3SET(vec, core1->x); ARR3SUB(vec, core2->x); fractional_min(vec, model->periodic); if (VEC3MAGSQ(vec) < FRACTION_TOLERANCE) { /* delete core2, unless primary AND core1 is non primary */ if (core2->primary && !core1->primary) { core1->status |= DELETED; /* FIXME - this may be a problem since we start the core2 loop */ /* requiring that core1 be undeleted */ #if DEBUG_REMOVE_DUPLICATES_MORE printf(" * rm 1\n"); #endif } else { core2->status |= DELETED; #if DEBUG_REMOVE_DUPLICATES_MORE printf(" * rm 2\n"); #endif } } } g_slist_free(za_list); } /* commit before searching for duplicate shells, as a commit */ /* will delete some attached shells */ delete_commit(model); for (list1=model->shels ; list1 ; list1=g_slist_next(list1)) { s1 = list1->data; if (s1->status & DELETED) continue; /* NEW - enumerate shells in the current locality */ zone = zone_get(s1->x, model->zone_array); for (list2=zone_shells(zone) ; list2 ; list2=g_slist_next(list2)) { s2 = list2->data; if (s2->status & DELETED) continue; if (s1 == s2) continue; ARR3SET(vec, s1->x); ARR3SUB(vec, s2->x); /* adjust for periodicity */ fractional_min(vec, model->periodic); if (VEC3MAGSQ(vec) < FRACTION_TOLERANCE) { /* delete shell2, unless primary AND shell1 is non primary */ if (s2->primary && !s1->primary) s1->status |= DELETED; else s2->status |= DELETED; } } } delete_commit(model); #if DEBUG_REMOVE_DUPLICATES printf("Final cores: %d\n", g_slist_length(model->cores)); printf("Final shels: %d\n", g_slist_length(model->shels)); #endif }
gint write_gromacs_gro(gchar *filename, struct model_pak *model) { gint n, c, i, s; gdouble x[3], min[3], max[3]; GSList *list; struct core_pak *core; FILE *fp; fp = fopen(filename, "wt"); if (!fp) return(1); /* init min/max for box calculation */ for (i=3 ; i-- ; ) { max[i] = -G_MAXDOUBLE; min[i] = G_MAXDOUBLE; } fprintf(fp, "GROMACS coordinates (generated by GDIS v%f)\n", VERSION); c = g_slist_length(model->cores); s = g_slist_length(model->shels); fprintf(fp, "%5d\n", c+s); n = 1; for (list=model->cores ; list ; list=g_slist_next(list)) { core = list->data; /* cartesians */ ARR3SET(x, core->x); vecmat(model->latmat, x); /* angs -> nm */ VEC3MUL(x, 0.1); fprintf(fp, "%5i%5s%5s%5i%8.3f%8.3f%8.3f%8.4f%8.4f%8.4f\n", n, "UNK", core->atom_label, 1, x[0], x[1], x[2], 0.1*core->v[0], 0.1*core->v[1], 0.1*core->v[2]); /* record min/max for box calculation */ for (i=3 ; i-- ; ) { if (x[i] < min[i]) min[i] = x[i]; if (x[i] > max[i]) max[i] = x[i]; } if (core->shell) { /* TODO - has an 'x' post-fix to the atom_label */ } n++; } /* this is the distance between the min and max atom coords in x, y, and z */ /* box calculation */ if (model->periodic == 3) { fprintf(fp, "% f %f %f\n", 0.1*model->pbc[0], 0.1*model->pbc[1], 0.1*model->pbc[2]); } else { for (i=0 ; i<3 ; i++) fprintf(fp, " %f", fabs(max[i] - min[i])); fprintf(fp, "\n"); } fclose(fp); return(0); }
void zmat_process(gpointer data, struct model_pak *model) { gint i, n; gdouble r, a, d; gdouble v1[3], v2[3], v3[3], m1[9], m2[9]; gpointer tmp; GSList *list; struct zmat_pak *zmat = data; struct zval_pak *zval; struct core_pak *core[4] = {NULL, NULL, NULL, NULL}; /* checks */ if (!zmat) return; matrix_lattice_init(model); #if ZMAT_PROCESS_DEBUG printf("distance scale = %f\n", zmat->distance_scale); printf("angle scale = %f\n", zmat->angle_scale); #endif /* track the core # - 1st 3 items in zmatrix are exceptions */ n = 0; for (list=zmat->zlines ; list ; list=g_slist_next(list)) { zval = list->data; /* check for variable names */ for (i=3 ; i-- ; ) { if (zval->name[i]) { /* hash table lookup for variable value */ zval->value[i] = zmat_table_lookup(zval->name[i], zmat); } } /* create the core */ #if ZMAT_PROCESS_DEBUG printf("[%d = %s] [%d %d %d]", zval->type, zval->elem, zval->connect[0], zval->connect[1], zval->connect[2]); P3VEC(" x: ", zval->value); #endif /* TODO - need to mark zmatrix generated cores as special */ /* probably have another list in the zmat struct that contains */ /* all the cores created below */ switch (n) { case 0: /* TODO - convert to cartesian if fractional and enforce cart model */ core[0] = new_core(zval->elem, model); model->cores = g_slist_prepend(model->cores, core[0]); zmat->zcores = g_slist_prepend(zmat->zcores, core[0]); ARR3SET(core[0]->x, zval->value); if (zmat->fractional) vecmat(model->latmat, core[0]->x); else { VEC3MUL(core[0]->x, zmat->distance_scale); } break; case 1: core[1] = new_core(zval->elem, model); model->cores = g_slist_prepend(model->cores, core[1]); zmat->zcores = g_slist_prepend(zmat->zcores, core[1]); r = zmat->distance_scale * zval->value[0]; /* a = zmat->angle_scale * zval->value[1]; d = zmat->angle_scale * zval->value[2]; */ /* SIESTA hack : z-axis angle is 2nd, and theta is 3rd (last) */ a = zmat->angle_scale * zval->value[2]; d = zmat->angle_scale * zval->value[1]; v1[0] = v1[1] = r * sin(d); v1[0] *= cos(a); v1[1] *= sin(a); v1[2] = r * cos(d); ARR3SET(core[1]->x, core[0]->x); ARR3ADD(core[1]->x, v1); break; case 2: /* check the connection order */ if (zval->connect[0] == 2) { tmp = core[0]; core[0] = core[1]; core[1] = tmp; } r = zmat->distance_scale * zval->value[0]; a = zmat->angle_scale * zval->value[1]; d = zmat->angle_scale * zval->value[2]; ARR3SET(v2, core[1]->x); ARR3SUB(v2, core[0]->x); /* get rotation axis for bond angle */ VEC3SET(v3, 0.0, 0.0, 1.0); crossprod(v1, v3, v2); /* rotate bondlength scaled vector into position */ matrix_v_rotation(m2, v1, a); ARR3SET(v3, v2); normalize(v3, 3); VEC3MUL(v3, r); vecmat(m2, v3); /* rotate to give required dihedral */ matrix_v_rotation(m1, v2, d); vecmat(m1, v3); /* generate the atom position */ core[2] = new_core(zval->elem, model); model->cores = g_slist_prepend(model->cores, core[2]); zmat->zcores = g_slist_prepend(zmat->zcores, core[2]); ARR3SET(core[2]->x, core[0]->x); ARR3ADD(core[2]->x, v3); break; default: /* get core connectivity (NB: prepending cores - hence n - number) */ core[0] = g_slist_nth_data(zmat->zcores, n-zval->connect[0]); core[1] = g_slist_nth_data(zmat->zcores, n-zval->connect[1]); core[2] = g_slist_nth_data(zmat->zcores, n-zval->connect[2]); g_assert(core[0] != NULL); g_assert(core[1] != NULL); g_assert(core[2] != NULL); r = zmat->distance_scale * zval->value[0]; a = zmat->angle_scale * zval->value[1]; d = zmat->angle_scale * zval->value[2]; /* setup vectors */ ARR3SET(v2, core[1]->x); ARR3SUB(v2, core[0]->x); ARR3SET(v3, core[2]->x); ARR3SUB(v3, core[1]->x); /* rotate v3 about v2 to give dihedral */ matrix_v_rotation(m1, v2, d); vecmat(m1, v3); /* get rotation axis and matrix for bond angle */ crossprod(v1, v3, v2); matrix_v_rotation(m2, v1, a); normalize(v2, 3); VEC3MUL(v2, r); vecmat(m2, v2); /* generate the atom position */ core[3] = new_core(zval->elem, model); model->cores = g_slist_prepend(model->cores, core[3]); zmat->zcores = g_slist_prepend(zmat->zcores, core[3]); ARR3SET(core[3]->x, core[0]->x); ARR3ADD(core[3]->x, v2); /* TODO (maybe) - some zmatrix constructions implicitly assume */ /* some checking for duplicate atoms & reversing the torsional */ /* angle sense to accomodate this. */ break; } n++; } /* zmatrix cores are created in cartesians - revert to fractional if required */ if (model->fractional) { for (list=zmat->zcores ; list ; list=g_slist_next(list)) { core[0] = list->data; vecmat(model->ilatmat, core[0]->x); } } }
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); }
void povray_hdr(FILE *fp, struct model_pak *data) { gdouble xvec, yvec, amb, pos[3], colour[3]; gdouble x[3], o[3], v[3], e[3]; GSList *list; struct light_pak *light; struct camera_pak *camera; g_assert(data != NULL); g_assert(data->camera != NULL); fprintf(fp,"#include \"colors.inc\" \n"); fprintf(fp,"#include \"finish.inc\" \n"); fprintf(fp,"#include \"glass.inc\" \n"); fprintf(fp,"#include \"metals.inc\" \n"); fprintf(fp,"#include \"textures.inc\" \n"); /* background colour (except for glass morphologies) */ fprintf(fp,"background { color rgb<%f,%f,%f0> }\n", sysenv.render.bg_colour[0], sysenv.render.bg_colour[1], sysenv.render.bg_colour[2]); /* pixel to angstrom conversion, with yet another magic number... */ p2a = 0.565 * (gdouble) sysenv.render.width / data->rmax; /* preserve model aspect ratio for the given image size */ xvec = yvec = 2.0*sysenv.rsize; if (sysenv.render.width > sysenv.render.height) xvec *= sysenv.render.width/sysenv.render.height; if (sysenv.render.height > sysenv.render.width) yvec *= sysenv.render.height/sysenv.render.width; /* compute camera position and orientation */ camera = data->camera; ARR3SET(x, camera->x); ARR3SET(o, camera->o); ARR3SET(v, camera->v); switch (camera->mode) { case FREE: break; default: case LOCKED: quat_rotate(x, camera->q); quat_rotate(o, camera->q); quat_rotate(v, camera->q); break; } /* convert viewing vector to a location */ ARR3ADD(v, x); /* camera zoom */ xvec *= camera->zoom; yvec *= camera->zoom; /* NEW - enable movies of left/right eye to be produced */ if (sysenv.stereo) { /* get axis for eye translation (view x up vector) */ crossprod(e, v, o); normalize(e, 3); /* the old 2% rule ... */ VEC3MUL(e, 0.02 * sysenv.rsize); /* default is left eye only */ if (sysenv.render.stereo_right) { ARR3ADD(x, e); ARR3ADD(v, e); } else { ARR3SUB(x, e); ARR3SUB(v, e); } } /* sky is the orientation vector */ /* right and up give the perspective */ if (camera->perspective) { fprintf(fp,"camera { location <%f,%f,%f>\n", x[0], x[1], x[2]); fprintf(fp," sky <%f,%f,%f>\n", o[0], o[1], o[2]); fprintf(fp," right <%f,0,0> up <%f,0,0>\n", xvec, yvec); fprintf(fp," look_at <%f,%f,%f>\n", v[0], v[1], v[2]); fprintf(fp," angle %f }\n", camera->fov); } else { fprintf(fp,"camera { orthographic location <%f,%f,%f>\n", x[0], x[1], x[2]); fprintf(fp," sky <%f,%f,%f>\n", o[0], o[1], o[2]); fprintf(fp," right <%f,0,0> up <%f,0,0>\n", xvec, yvec); fprintf(fp," look_at <%f,%f,%f> }\n", v[0], v[1], v[2]); } /* create light sources */ for (list=sysenv.render.light_list ; list ; list=g_slist_next(list)) { light = list->data; ARR3SET(pos, light->x); /* OpenGL -> POVRay axes */ pos[0] *= -1.0; pos[1] *= -1.0; pos[2] *= -1.0; quat_rotate(pos, camera->q); switch (light->type) { case POSITIONAL: fprintf(fp,"light_source\n {\n <%f,%f,%f>\n", pos[0], pos[1], pos[2]); break; case DIRECTIONAL: /* move away far enough so the rays are ~ // */ VEC3MUL(pos, 100.0*data->rmax); fprintf(fp,"light_source\n {\n <%f,%f,%f>\n", pos[0], pos[1], pos[2]); break; default: continue; } /* simulate OpenGL style lights */ ARR3SET(colour, light->colour); VEC3MUL(colour, light->specular); if (sysenv.render.shadowless) fprintf(fp," color rgb<%f,%f,%f> shadowless }\n", colour[0], colour[1], colour[2]); else { /* old style lighting */ /* fprintf(fp," color rgb<%f,%f,%f> }\n", colour[0], colour[1], colour[2]); */ fprintf (fp,"color White\n"); fprintf (fp," area_light <5, 0, 0,>, <0, 0, 5>, 5, 5\n"); fprintf (fp," adaptive 1\n jitter\n}\n"); } } /* fill-light to bring out the shadows */ fprintf(fp,"light_source{<%f,%f,%f> color Gray80 shadowless}\n", pos[0], pos[1], pos[2]); /* morph is too dark with just the above, sky_sphere is *nice* */ /* TODO - choice of colour eg white/grey/light blue */ /* NB: white is a bit too bright (even with 0 ambience) */ if (data->id == MORPH) { if (!sysenv.render.wire_surface && !sysenv.render.shadowless) { fprintf(fp,"sky_sphere { pigment {gradient y color_map " "{[0, 1 color Gray20 color White]} rotate x*45}}\n"); } } /* POVRay is a bit darker than OpenGL */ amb = 20.0*sysenv.render.ambience; fprintf(fp,"global_settings { ambient_light rgb<%f, %f, %f> assumed_gamma 2.2}\n",amb,amb,amb); }
void camera_waypoint_animate(gint frames, gint overwrite, struct model_pak *model) { gint i; gdouble a, af, v[3], e[3], o[3], tmp[3]; gdouble jf, jv[3], x[3], mat[9]; GSList *list, *journey; struct camera_pak *cam, *cam1, *cam2; /* checks */ g_assert(model != NULL); g_assert(frames > 0); if (g_slist_length(model->waypoint_list) < 2) { gui_text_show(ERROR, "You need to make at least 2 waypoint.\n"); return; } /* close any active animation dialog */ dialog_destroy_type(ANIM); #if DEBUG_CAMERA_ANIMATE printf("frames for each traversal: %d\n", frames); #endif list = model->waypoint_list; cam1 = list->data; list = g_slist_next(list); /* create the camera journey */ journey = NULL; while (list) { cam2 = list->data; /* setup camera journey vector */ ARR3SET(jv, cam2->x); ARR3SUB(jv, cam1->x); /* add starting camera over journey leg */ for (i=0 ; i<frames ; i++) { /* journey fraction */ jf = i; jf /= frames; ARR3SET(x, jv); VEC3MUL(x, jf); cam = camera_dup(cam1); ARR3ADD(cam->x, x); journey = g_slist_prepend(journey, cam); } /* approx 5 degrees */ #define ROTATION_INCREMENT 0.08727 /* (v x e plane alignment) */ proj_vop(v, cam2->v, cam1->o); a = via(v, cam1->v, 3); /* compute rotation increment */ af = (gint) nearest_int(a / ROTATION_INCREMENT); if (!af) af = 1.0; /* test rotation sense */ matrix_v_rotation(mat, cam1->o, a); ARR3SET(tmp, cam1->v); vecmat(mat, tmp); if (via(tmp, v, 3) > 0.1) a *= -1.0; /* build rotaton */ matrix_v_rotation(mat, cam1->o, a/af); /* apply to camera */ ARR3SET(v, cam1->v); ARR3SET(e, cam1->e); for (i=af ; i-- ; ) { cam = camera_dup(cam1); ARR3SET(cam->x, cam2->x); vecmat(mat, v); vecmat(mat, e); ARR3SET(cam->v, v); ARR3SET(cam->e, e); journey = g_slist_prepend(journey, cam); } /* TODO - apply elevation to get v in complete coincidence */ /* rotate about e to achieve coincidence */ a = via(v, cam2->v, 3); /* compute rotation increment */ af = (gint) nearest_int(a / ROTATION_INCREMENT); if (!af) af = 1.0; /* test rotation sense */ matrix_v_rotation(mat, e, a); ARR3SET(tmp, v); vecmat(mat, tmp); if (via(tmp, cam2->v, 3) > 0.1) a *= -1.0; /* build rotaton */ matrix_v_rotation(mat, e, a/af); /* apply to camera */ ARR3SET(o, cam1->o); for (i=af ; i-- ; ) { cam = camera_dup(cam1); ARR3SET(cam->x, cam2->x); vecmat(mat, v); vecmat(mat, o); ARR3SET(cam->v, v); ARR3SET(cam->o, o); ARR3SET(cam->e, e); journey = g_slist_prepend(journey, cam); } /* endpoint camera */ journey = g_slist_prepend(journey, camera_dup(cam2)); /* get next journey leg */ cam1 = cam2; list = g_slist_next(list); } journey = g_slist_reverse(journey); if (overwrite) { free_slist(model->transform_list); model->transform_list = journey; } else model->transform_list = g_slist_concat(model->transform_list, journey); model->num_frames = g_slist_length(model->transform_list); model->animation = TRUE; redraw_canvas(SINGLE); }
gint write_diffax(gchar *filename, struct model_pak *data) { gint i, j, n, tot_layer; gdouble pr, x[3]; GSList *list1, *list2; struct layer_pak *layer; struct core_pak *core; struct elem_pak elem; FILE *fp; printf("write_diffax()\n"); /* checks */ g_return_val_if_fail(data != NULL, 1); g_return_val_if_fail(filename != NULL, 2); /* open the file */ fp = fopen(filename,"wt"); if (!fp) return(3); /* setup the layers */ #ifdef WITH_GUI diffract_layer_setup(data); #endif tot_layer = g_slist_length(data->layer_list); if (!tot_layer) { printf("No layers to write.\n"); return(0); } /* output */ fprintf(fp, "\n"); fprintf(fp, "INSTRUMENTAL\nX-RAY\n1.5418\n"); fprintf(fp, "GAUSSIAN 0.4\n\n"); fprintf(fp, "STRUCTURAL\n%11.6f %11.6f %11.6f %11.6f\nUNKNOWN\n%d\ninfinite\n\n", data->pbc[0], data->pbc[1], data->pbc[2]/tot_layer, R2D*data->pbc[5], tot_layer); /* write out the layers */ i=1; for (list1=data->layer_list ; list1 ; list1=g_slist_next(list1)) { fprintf(fp, "\nLAYER %d\nnone\n", i); /* write out the atoms within the layer */ n=1; layer = (struct layer_pak *) list1->data; for (list2=layer->cores ; list2 ; list2=g_slist_next(list2)) { core = (struct core_pak *) list2->data; if (core->status & DELETED) continue; ARR3SET(x, core->x); /* center layer on origin */ x[2] -= layer->centroid[2]; /* scale up to 0.0-1.0 range */ x[2] *= tot_layer; /* move centroid to middle of the layer */ x[2] += 0.5; get_elem_data(core->atom_code, &elem, NULL); fprintf(fp, "%4s %4d %11.6f %11.6f %11.6f 1.0 %8.6f\n", elem.symbol, n, x[0], x[1], x[2], core->sof); n++; } i++; } fprintf(fp, "\nSTACKING\nrecursive\ninfinite\n\n"); fprintf(fp, "TRANSITIONS\n"); /* omit region 0 - temporary impl for the later method where */ /* the desired layers will be in a linked list, rather than */ /* all 1..max regions included */ for (i=1 ; i<=tot_layer ; i++) { fprintf(fp, "\n"); /* uniform probability & no xlat */ pr = 1.0 / (gdouble) tot_layer; for (j=1 ; j<=tot_layer ; j++) fprintf(fp, "%8.6f 0.0 0.0 1.0 {layer %d-%d}\n",pr,i,j); } fclose(fp); return(0); }
void docking_project_create(GtkWidget *w, struct model_pak *model) { gint a, b, i, m, n, rx, ry, rz, size, rigid_save; gint a_max, b_max, rx_max, ry_max, rz_max; gchar *file, *dump, *dump_save, *rigid_move_save; gdouble dx, dy, dz, x[3], scale[3], mat[9], dock_centroid[3], q[4]; GString *name, *rigid; GSList *list, *core_list, *shell_list; struct dock_pak *dock; struct core_pak *core, *core2; struct shel_pak *shell, *shell2; FILE *fp; /* checks */ g_assert(model != NULL); size = g_slist_length(model->selection); if (!size) { gui_text_show(WARNING, "Please select the subset you wish to dock.\n"); return; } /* create new docking project */ dock = g_malloc(sizeof(struct dock_pak)); /* NEW - setup project path */ /* g_path_get_dirname(model->fullpath); g_get_current_dir(); */ /* seek a file name that doesn't exist (avoid background overwriting) */ name = g_string_new(NULL); i=0; do { g_string_sprintf(name, "project_%06d", i); i++; } while (g_file_test(name->str, G_FILE_TEST_EXISTS)); dock->path = g_build_path(sysenv.cwd, name->str, NULL); printf("creating new project: [%s]\n", dock->path); #if WIN32 if (mkdir(dock->path)) #else if (mkdir(dock->path, 0700)) #endif { gui_text_show(ERROR, "Failed to create project directory.\n"); g_free(dock->path); g_free(dock); return; } /* project control file */ g_string_sprintf(name, "%s%sproject.pcf", dock->path, DIR_SEP); fp = fopen(name->str, "wt"); /* save original variables */ dump_save = model->gulp.dump_file; model->gulp.dump_file = NULL; rigid_save = model->gulp.rigid; model->gulp.rigid = dock_rigid_on; rigid_move_save = model->gulp.rigid_move; model->gulp.rigid_move = NULL; if (model->gulp.rigid) { rigid = g_string_new(NULL); if (dock_rigid_x) g_string_sprintf(rigid, "x"); if (dock_rigid_y) g_string_sprintfa(rigid, "y"); if (dock_rigid_z) g_string_sprintfa(rigid, "z"); model->gulp.rigid_move = g_string_free(rigid, FALSE); } /* duplicate selection for docking */ core_list = NULL; shell_list = NULL; VEC3SET(dock_centroid, 0.0, 0.0, 0.0); for (list=model->selection ; list ; list=g_slist_next(list)) { core2 = dup_core(list->data); core_list = g_slist_prepend(core_list, core2); if (core2->shell) shell_list = g_slist_prepend(shell_list, core2->shell); /* compute centroid */ ARR3ADD(dock_centroid, core2->x); } /* NB: lists must have the same order as original selection */ core_list = g_slist_reverse(core_list); shell_list = g_slist_reverse(shell_list); VEC3MUL(dock_centroid, 1.0/(gdouble) size); /* fractional translation grid units */ scale[0] = dock_cell[0] / dock_grid[0]; scale[1] = dock_cell[1] / dock_grid[1]; /* rotational increments */ dx = PI/dock_rotate[0]; dy = PI/dock_rotate[1]; dz = PI/dock_rotate[2]; /* translational sampling */ if (dock_grid_on) { a_max = dock_grid[0]; b_max = dock_grid[1]; } else { a_max = 1; b_max = 1; } /* rotational sampling */ if (dock_rotate_on) { rx_max = dock_rotate[0]; ry_max = dock_rotate[1]; rz_max = dock_rotate[2]; } else { rx_max = 1; ry_max = 1; rz_max = 1; } /* project header */ fprintf(fp, "%%title solvent mapping project\n"); fprintf(fp, "%%set %d %d %f %f\n", a_max, b_max, dock_cell[0], dock_cell[1]); /* loop over all grid translations */ m = n = 0; for (a=0 ; a<a_max ; a++) { for (b=0 ; b<b_max ; b++) { VEC3SET(x, a, b, 0.0); x[0] *= scale[0]; x[1] *= scale[1]; /* loop over rotations */ VEC4SET(q, 1.0, 0.0, 0.0, 0.0); for (rx=0 ; rx<rx_max ; rx++) { if (rx) quat_concat_euler(q, PITCH, dx); for (ry=0 ; ry<ry_max ; ry++) { if (ry) quat_concat_euler(q, ROLL, dy); for (rz=0 ; rz<rz_max ; rz++) { if (rz) quat_concat_euler(q, YAW, dz); /* build total rotation matrix */ quat_matrix(mat, q); /* transform the cores and shells */ i = 0; for (list=model->selection ; list ; list=g_slist_next(list)) { core = list->data; /* FIXME - should we restore this after? how? */ core->region = 2; /* get original selection core coordinates */ core2 = g_slist_nth_data(core_list, i); ARR3SET(core->x, core2->x); /* perform the rotation (NB: must be done about origin in cartesian space) */ ARR3SUB(core->x, dock_centroid); vecmat(model->latmat, core->x); vecmat(mat, core->x); vecmat(model->ilatmat, core->x); ARR3ADD(core->x, dock_centroid); /* add the current translation offset */ ARR3ADD(core->x, x); /* as above, for the associated shell */ if (core->shell) { shell = core->shell; shell->region = 2; shell2 = core2->shell; g_assert(shell2 != NULL); ARR3SET(shell->x, shell2->x); ARR3SUB(shell->x, dock_centroid); vecmat(model->latmat, shell->x); vecmat(mat, shell->x); vecmat(model->ilatmat, shell->x); ARR3ADD(shell->x, dock_centroid); ARR3ADD(shell->x, x); } i++; } /* write docking configuration */ /* file = g_strdup_printf("%s_%06d.gin", model->basename, n); */ /* m identifies grid points (for later minimum check) */ fprintf(fp, "%s_%06d.gin %f %f %d\n", model->basename, n, x[0], x[1], m); file = g_strdup_printf("%s%s%s_%06d.gin", dock->path, DIR_SEP, model->basename, n); dump = g_strdup_printf("%s_%06d.res", model->basename, n); model->gulp.dump_file = dump; write_gulp(file, model); g_free(file); g_free(dump); n++; } } } m++; } } /* restore original variables */ model->gulp.dump_file = dump_save; model->gulp.rigid = rigid_save; g_free(model->gulp.rigid_move); model->gulp.rigid_move = rigid_move_save; /* restore original selection (delete, then concat saved list) */ i = 0; for (list=model->selection ; list ; list=g_slist_next(list)) { core = list->data; core2 = g_slist_nth_data(core_list, i); ARR3SET(core->x, core2->x); if (core->shell) { shell = core->shell; shell2 = core2->shell; g_assert(shell2 != NULL); ARR3SET(shell->x, shell2->x); } i++; } /* free docking core/shell lists */ free_slist(core_list); free_slist(shell_list); g_string_free(name, TRUE); fclose(fp); /* run docking in background unless told to stop after setup */ /* if (!dock_no_execute) submit_task("Docking", &docking_execute, dock, &docking_cleanup, dock, model); */ }
GSList *get_facet_equiv(struct model_pak *data, gint *f1) { gint i, flag, *f2, index[3]; gdouble d1, d2, vec[3]; GSList *flist=NULL, *list=NULL; g_return_val_if_fail(data != NULL, NULL); g_return_val_if_fail(f1 != NULL, NULL); /* NEW */ ARR3SET(vec, f1); vecmat(data->rlatmat, vec); d1 = 1.0/VEC3MAG(vec); #if DEBUG_GET_FACET_EQUIV printf("search for equiv faces to (%d %d %d) (Dhkl = %f)\n", f1[0], f1[1], f1[2], d1); #endif /* add the supplied face to the list (needed to eliminate repetitions) */ f2 = g_malloc(3*sizeof(gint)); ARR3SET(f2, f1); flist = g_slist_prepend(flist, (gpointer) f2); if (data->sginfo.spacenum) { /* skip 1st (trivial) op */ for (i=1 ; i<data->sginfo.order ; i++) { /* generate new symmetry related hkl */ ARR3SET(vec, f1); vecmat(*(data->sginfo.matrix+i), vec); ARR3SET(index, vec); /* NEW - weed out symop generated faces with different Dhkl values */ /* FIXME - why does this happen??? */ vecmat(data->rlatmat, vec); d2 = 1.0/VEC3MAG(vec); #if DEBUG_GET_FACET_EQUIV printf("candidate: (%3d %3d %3d) : (Dhkl=%7.4f)", index[0], index[1], index[2], d2); #endif if (fabs(d2-d1) > FRACTION_TOLERANCE) { #if DEBUG_GET_FACET_EQUIV printf("[NO : dhkl mis-match]\n"); #endif continue; } /* add new hkl if not found in the list */ flag = 0; list = flist; while (list != NULL) { f2 = (gint *) list->data; if (index[0] == f2[0] && index[1] == f2[1] && index[2] == f2[2]) { flag++; break; } list = g_slist_next(list); } if (!flag) { f2 = g_malloc(3*sizeof(gint)); ARR3SET(f2, index); flist = g_slist_prepend(flist, f2); #if DEBUG_GET_FACET_EQUIV printf("[YES : symop %d]\n", i); #endif } #if DEBUG_GET_FACET_EQUIV else { printf("[NO : already exists]\n"); } #endif } } else printf("No space group information.\n"); flist = g_slist_reverse(flist); return(flist); }
gint write_cif(gchar *filename, struct model_pak *data) { gint flag=0; gdouble tmat[9], x[3], depth=1.0; GSList *list; FILE *fp; time_t t1; struct core_pak *core; /* init & checks */ g_return_val_if_fail(data != NULL, 1); fp = fopen(filename, "wt"); g_return_val_if_fail(fp != NULL, 2); /* is it a surface with negative z? */ if (data->periodic == 2) { if (g_slist_length(data->cores)) { core = g_slist_nth_data(data->cores, 0); if (core->x[2] < 0.0) flag++; } } /* rot to make z positive */ matrix_rotation(&tmat[0], PI, PITCH); t1 = time(NULL); fprintf(fp, "data_block_1\n"); fprintf(fp, "_audit_creation_date '%s'\n", g_strstrip(ctime(&t1))); fprintf(fp, "_audit_creation_method 'generated by GDIS v%4.2f'\n", VERSION); fprintf(fp, "\n\n"); if (data->periodic) { fprintf(fp, "_cell_length_a %8.4f\n",data->pbc[0]); fprintf(fp, "_cell_length_b %8.4f\n",data->pbc[1]); if (data->periodic == 2) { /* get depth info */ depth = (data->surface.region[0]+data->surface.region[1])*data->surface.depth; /* no depth info - make it large enough to fit everything */ if (depth < POSITION_TOLERANCE) depth = 2.0*data->rmax; fprintf(fp, "_cell_length_c %8.4f\n", depth); } else fprintf(fp, "_cell_length_c %8.4f\n",data->pbc[2]); fprintf(fp, "_cell_angle_alpha %8.2f\n",180.0*data->pbc[3]/PI); fprintf(fp, "_cell_angle_beta %8.2f\n",180.0*data->pbc[4]/PI); fprintf(fp, "_cell_angle_gamma %8.2f\n",180.0*data->pbc[5]/PI); fprintf(fp, "\n\n"); fprintf(fp, "_symmetry_space_group_name_H-M '%s'\n",data->sginfo.spacename); fprintf(fp, "_symmetry_Int_Tables_number %d\n",data->sginfo.spacenum); fprintf(fp, "\n\n"); } /* coords - format section */ fprintf(fp, "loop_\n"); fprintf(fp, "_atom_site_label\n"); if (data->periodic) { fprintf(fp, "_atom_site_fract_x\n"); fprintf(fp, "_atom_site_fract_y\n"); fprintf(fp, "_atom_site_fract_z\n"); } else { fprintf(fp, "_atom_site_cartn_x\n"); fprintf(fp, "_atom_site_cartn_y\n"); fprintf(fp, "_atom_site_cartn_z\n"); } /* coords - data section */ for (list=data->cores ; list ; list=g_slist_next(list)) { core = list->data; /* only the asymmetric cell if periodic */ if (data->periodic && !core->primary) continue; /* NB: want fractional if 3D periodic, otherwise cartesian */ ARR3SET(x, core->x); /* transformation needed? */ if (flag) vecmat(tmat, x); /* make the z coordinate "fractional" for a surface */ if (data->periodic == 2) x[2] /= depth; fprintf(fp, "%2s %10.6f %10.6f %10.6f\n", elements[core->atom_code].symbol, x[0], x[1], x[2]); } fprintf(fp, "\n\n"); fclose(fp); return(0); }
gint surf_sysabs(struct model_pak *data, gint h, gint k, gint l) { gint i, flag; gint f1[3] /*, f2[3]*/; gdouble dp, dummy, vec[3], df[3]; #if DEBUG_FACET_ABSENT printf("testing %d %d %d\n", h, k, l); #endif /* apply the symmetry matrices (skip identity) */ VEC3SET(f1, h, k, l); for (i=1 ; i<data->sginfo.order ; i++) { /* NEW - identity + translation alone is insufficent */ if (matrix_is_identity(*(data->sginfo.matrix+i))) continue; VEC3SET(vec, h, k, l); vecmat(*(data->sginfo.matrix+i), vec); flag = 0; /* not needed - we've expanded all symmetry operations (incl. inversion) */ /* test f1 . m = -f1 */ /* ARR3SET(df, f1); ARR3ADD(df, vec); if (VEC3MAGSQ(df) < FRACTION_TOLERANCE) if (data->sginfo.inversion) flag++; */ /* test f1 . m = f1 */ ARR3SET(df, f1); ARR3SUB(df, vec); if (VEC3MAGSQ(df) < POSITION_TOLERANCE) flag++; if (flag) { #if DEBUG_FACET_ABSENT printf("symop [%d] satisfies 1st absence condition.\n", i); P3MAT("matrix:", *(data->sginfo.matrix+i)); P3VEC("offset:", *(data->sginfo.offset+i)); #endif /* test if <f1,t> = non-integer */ ARR3SET(vec, *(data->sginfo.offset+i)); ARR3MUL(vec, f1); dp = fabs(vec[0] + vec[1] + vec[2]); if (modf(dp, &dummy) > POSITION_TOLERANCE) { #if DEBUG_FACET_ABSENT printf("symop [%d] [%f %f %f] satisfies 2nd absence condition.\n", i, *(*(data->sginfo.offset+i)+0), *(*(data->sginfo.offset+i)+1), *(*(data->sginfo.offset+i)+2)); printf("facet is extinct.\n"); #endif return(TRUE); } } } #if DEBUG_FACET_ABSENT printf(">>> Not absent\n"); #endif return(FALSE); }
gint region_move_atom(struct core_pak *core, gint direction, struct model_pak *data) { gint flag, primary, secondary, mov[2]; gdouble vec[3], tmp[3], d[3]; GSList *list; struct core_pak *comp; #if DEBUG_REGION_SWITCH_ATOM printf(" model: %s\n", data->basename); printf(" periodicity: %d\n", data->periodic); printf(" hkl: %f %f %f\n", data->surface.miller[0], data->surface.miller[1], data->surface.miller[2]); printf(" dhkl: %f\n", data->surface.dspacing); printf("region sizes: %f %f\n", data->surface.region[0], data->surface.region[1]); printf(" moving: "); if (direction == UP) printf("UP\n"); else printf("DOWN\n"); #endif /* checks */ g_return_val_if_fail(data != NULL, 1); g_return_val_if_fail(data->periodic == 2, 1); if (data->surface.region[0] < 1) { gui_text_show(ERROR, "region 1 is empty.\n"); return(1); } /* setup region switching labels */ if (direction == UP) { primary = REGION1A; secondary = REGION2A; } else { primary = REGION2A; secondary = REGION1A; } /* get fractional depth translation vector */ ARR3SET(vec, data->surface.depth_vec); vecmat(data->ilatmat, vec); /* calculate offset to region boundary */ ARR3SET(tmp, vec); if (direction == DOWN) { VEC3MUL(tmp, data->surface.region[0]); VEC3MUL(tmp, -1.0); } else { if (data->surface.region[1] == 0) { VEC3MUL(tmp, data->surface.region[0]); } else { VEC3MUL(tmp, data->surface.region[1]); } } /* if region 2 is empty, just move core to the bottom */ if (data->surface.region[1] == 0.0) { ARR3ADD(core->x, tmp); if (core->shell) { ARR3ADD((core->shell)->x, tmp); } atom_colour_scheme(data->colour_scheme, core, data); return(0); } /* get coordinates of target atom */ ARR3ADD(tmp, core->x); #if DEBUG_REGION_SWITCH_ATOM P3VEC(" translation: ", vec); P3VEC(" target coords: ", tmp); #endif /* find the target */ flag=0; for (list=data->cores ; list ; list=g_slist_next(list)) { comp = list->data; /* only atoms of the same type need apply */ if (core->atom_code != comp->atom_code) continue; /* get difference vector */ ARR3SET(d, comp->x); ARR3SUB(d, tmp); /* pbc constraint */ while(d[0] < -FRACTION_TOLERANCE) d[0] += 1.0; while(d[0] > 0.5) d[0] -= 1.0; while(d[1] < -FRACTION_TOLERANCE) d[1] += 1.0; while(d[1] > 0.5) d[1] -= 1.0; /* test difference vector's magnitude */ if (VEC3MAGSQ(d) < FRACTION_TOLERANCE) { /* change its labelling */ #if DEBUG_REGION_SWITCH_ATOM printf("Matched core: %p\n", comp); #endif comp->region = secondary; if (comp->shell) { (comp->shell)->region = secondary; } atom_colour_scheme(data->colour_scheme, comp, data); flag++; break; } } if (!flag) { gui_text_show(ERROR, "Failed to find a boundary image.\n"); return(1); } /* now move selected atom to bottom of region 2 */ ARR3SET(tmp, vec); VEC3MUL(tmp, (data->surface.region[0] + data->surface.region[1])); if (direction == UP) VEC3MUL(tmp, -1.0); ARR3SUB(core->x, tmp); core->region = primary; /* pbc constrain */ fractional_clamp(core->x, mov, 2); if (core->shell) { ARR3SUB((core->shell)->x, tmp); ARR2ADD((core->shell)->x, mov); (core->shell)->region = primary; } atom_colour_scheme(data->colour_scheme, core, data); return(0); }
gint write_xml(gchar *filename, struct model_pak *model) { gdouble vec[3]; GSList *list, *list2; struct core_pak *core; struct vec_pak *v; struct spatial_pak *spatial; FILE *fp; fp = fopen(filename, "wt"); if (!fp) return(1); fprintf(fp, "<system>\n"); /* periodicity */ if (model->periodic) { switch (model->periodic) { case 1: fprintf(fp, " <crystal dictRef=\"gulp:polymer\">\n"); break; case 2: fprintf(fp, " <crystal dictRef=\"gulp:surface\">\n"); break; default: fprintf(fp, " <crystal dictRef=\"gulp:fullcell\">\n"); break; } fprintf(fp, " <cell dictRef=\"cml:a\"> %f </cell>\n", model->pbc[0]); fprintf(fp, " <cell dictRef=\"cml:b\"> %f </cell>\n", model->pbc[1]); fprintf(fp, " <cell dictRef=\"cml:c\"> %f </cell>\n", model->pbc[2]); fprintf(fp, " <cell dictRef=\"cml:alpha\"> %f </cell>\n", R2D*model->pbc[3]); fprintf(fp, " <cell dictRef=\"cml:beta\"> %f </cell>\n", R2D*model->pbc[4]); fprintf(fp, " <cell dictRef=\"cml:gamma\"> %f </cell>\n", R2D*model->pbc[5]); fprintf(fp, " </crystal>\n"); } /* cores */ for (list=model->cores ; list ; list=g_slist_next(list)) { core = list->data; ARR3SET(vec, core->x); vecmat(model->latmat, vec); /* fprintf(fp, " <atom elementType=\"%s\" x3=\"%f\" y3=\"%f\" z3=\"%f\">", core->atom_label, vec[0], vec[1], vec[2]); */ fprintf(fp, " <atom elementType=\"%s\" x3=\"%f\" y3=\"%f\" z3=\"%f\">", elements[core->atom_code].symbol, vec[0], vec[1], vec[2]); fprintf(fp, "</atom>\n"); /* TODO - shells as particles */ } /* spatial data */ for (list=model->spatial ; list ; list=g_slist_next(list)) { spatial = list->data; fprintf(fp, "<spatial Method=\"%d\" Periodic=\"%d\">\n", spatial->method, spatial->periodic); for (list2=spatial->list ; list2 ; list2=g_slist_next(list2)) { v = list2->data; fprintf(fp, " <vertex red=\"%f\" green=\"%f\" blue=\"%f\"", v->colour[0], v->colour[1], v->colour[2]); fprintf(fp, " x3=\"%f\" y3=\"%f\" z3=\"%f\"", v->x[0], v->x[1], v->x[2]); fprintf(fp, " nx=\"%f\" ny=\"%f\" nz=\"%f\"></vertex>\n", v->n[0], v->n[1], v->n[2]); } fprintf(fp, "</spatial>\n"); } /* camera waypoints */ for (list=model->waypoint_list ; list ; list=g_slist_next(list)) { struct camera_pak *camera = list->data; fprintf(fp, "<waypoint mode=\"%d\" perspective=\"%d\" fov=\"%f\" zoom=\"%f\"\n", camera->mode, camera->perspective, camera->fov, camera->zoom); fprintf(fp, "x0=\"%f\" x1=\"%f\" x2=\"%f\"\n",camera->x[0],camera->x[1],camera->x[2]); fprintf(fp, "o0=\"%f\" o1=\"%f\" o2=\"%f\"\n",camera->o[0],camera->o[1],camera->o[2]); fprintf(fp, "v0=\"%f\" v1=\"%f\" v2=\"%f\"\n",camera->v[0],camera->v[1],camera->v[2]); fprintf(fp, "e0=\"%f\" e1=\"%f\" e2=\"%f\"\n",camera->e[0],camera->e[1],camera->e[2]); fprintf(fp, "q0=\"%f\" q1=\"%f\" q2=\"%f\" q3=\"%f\">", camera->q[0], camera->q[1], camera->q[2], camera->q[3]); fprintf(fp, "</waypoint>\n"); } fprintf(fp, "</system>\n"); fclose(fp); return(0); }
gint write_gms(gchar *filename, struct model_pak *model) { gdouble x[3]; GSList *list; struct core_pak *core; FILE *fp; /* checks */ g_return_val_if_fail(model != NULL, 1); g_return_val_if_fail(filename != NULL, 2); /* open the file */ fp = fopen(filename,"wb"); if (!fp) return(3); /* TODO - enforce lines < 80 chars? */ /* print control keywords */ fprintf(fp, " $contrl coord=unique"); write_keyword(fp, GMS_EXETYPE_TXT, model->gamess.exe_type, exe_types); write_keyword(fp, GMS_SCFTYPE_TXT, model->gamess.scf_type, scf_types); write_keyword(fp, GMS_RUNTYPE_TXT, model->gamess.run_type, run_types); /* FIXME - put in to try & keep the lines below 80 chars */ fprintf(fp, "\n "); write_keyword(fp, GMS_UNITS_TXT, model->gamess.units, units); fprintf(fp, " %s%d", GMS_MAXIT_TXT, (gint) model->gamess.maxit); if (model->gamess.total_charge != 0.0) fprintf(fp, " %s%d", GMS_TOTAL_Q_TXT, (gint) model->gamess.total_charge); if (model->gamess.multiplicity > 1) fprintf(fp, " %s%d", GMS_MULT_TXT, (gint) model->gamess.multiplicity); if (model->gamess.wide_output) fprintf(fp, " %s6", GMS_WIDE_OUTPUT_TXT); fprintf(fp, " $end\n"); /* NEW - dft calc */ if (model->gamess.dft) { fprintf(fp, " $dft"); switch (model->gamess.dft_functional) { case SVWN: fprintf(fp, " dfttyp=SVWN"); break; case BLYP: fprintf(fp, " dfttyp=BLYP"); break; case B3LYP: fprintf(fp, " dfttyp=B3LYP"); break; } fprintf(fp, " $end\n"); } /* TODO: electron correlation stuff */ /* print size and memory */ fprintf(fp, " $system %s%d %s%d $end\x0a", GMS_TIMLIM_TXT, (gint) model->gamess.time_limit, GMS_MWORDS_TXT, (gint) model->gamess.mwords); /* print optimiser data */ if (model->gamess.run_type >= GMS_OPTIMIZE) { fprintf(fp, " $statpt %s%d ", GMS_NSTEP_TXT, (gint) model->gamess.nstep); write_keyword(fp, GMS_METHOD_TXT, model->gamess.opt_type, method_types); fprintf(fp, "$end\n"); } /* print basis set if one of the standard ones */ if (model->gamess.basis != GMS_USER) { fprintf(fp, " $basis "); write_keyword(fp, GMS_BASIS_TXT, model->gamess.basis, basis_types); if (model->gamess.ngauss) fprintf(fp, " %s%d", GMS_NGAUSS_TXT, model->gamess.ngauss); if (model->gamess.num_p) fprintf(fp, " %s%d", GMS_NUM_P_TXT, (gint) model->gamess.num_p); if (model->gamess.num_d) fprintf(fp, " %s%d", GMS_NUM_D_TXT, (gint) model->gamess.num_d); if (model->gamess.num_f) fprintf(fp, " %s%d", GMS_NUM_F_TXT, (gint) model->gamess.num_f); if (model->gamess.have_heavy_diffuse) fprintf(fp, " %s", GMS_DIFFSP_TXT); if (model->gamess.have_hydrogen_diffuse) fprintf(fp, " %s", GMS_DIFFS_TXT); fprintf(fp, " $end\n"); } /* print data */ fprintf(fp, " $DATA\n"); /* print data header */ fprintf(fp, "%s\n", model->gamess.title); /* print symmetry */ fprintf(fp, "c1\n"); for (list=model->cores ; list ; list=g_slist_next(list)) { core = list->data; if (core->status & DELETED) continue; /* everything is cartesian after latmat mult */ ARR3SET(x, core->x); vecmat(model->latmat, x); if (model->gamess.units == GMS_ANGS) fprintf(fp,"%-7s %d %14.9f %14.9f %14.9f\n", elements[core->atom_code].symbol, elements[core->atom_code].number, x[0], x[1], x[2]); else fprintf(fp,"%-7s %d %14.9f %14.9f %14.9f\n", elements[core->atom_code].symbol, elements[core->atom_code].number, x[0]/BOHR_TO_ANGS, x[1]/BOHR_TO_ANGS, x[2]/BOHR_TO_ANGS); } fprintf(fp, " $END\n"); fclose(fp); return(0); }