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 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 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); }
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 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); }
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); }
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 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); */ }
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 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); } } }
// 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); }