gint anim_read_all_frames(struct model_pak *model) { gint i; struct frame_pak *frame; FILE *fp; /* checks */ g_assert(model != NULL); g_assert(model->animation == TRUE); /* TODO - test is we have enough memory by using g_try_malloc() */ /* read in all frames and store relevant data */ fp = fopen(model->filename, "r"); if (!fp) { printf("Could not open source file."); return(1); } for (i=0 ; i<model->num_frames ; i++) { /* NB: frames start at 1 */ read_raw_frame(fp, i+1, model); matrix_lattice_init(model); frame = g_malloc(sizeof(struct frame_pak *)); memcpy(frame->latmat, model->latmat, 9*sizeof(gdouble)); frame->core_list = dup_core_list(model->cores); frame->shell_list = dup_shell_list(model->shels); model->frame_data_list = g_slist_prepend(model->frame_data_list, frame); } model->frame_data_list = g_slist_reverse(model->frame_data_list); return(1); }
gint load_planes(gchar *filename, struct model_pak *data) { gint h, k, l, num_tokens; gint cflag=FALSE, sflag=FALSE, gflag=FALSE; gdouble m[3]; gchar **buff; GSList *list, *new_planes; struct plane_pak *plane=NULL; struct shift_pak *shift=NULL; FILE *fp; fp = fopen(filename, "rt"); if (!fp) return(1); /* get next line */ new_planes = NULL; for (;;) { buff = get_tokenized_line(fp, &num_tokens); if (!buff) break; /* NB: only update space/cell etc. data if this call did */ /* not originate from an import planes call */ if (data->id == MORPH) { /* cell parameters */ if (g_ascii_strncasecmp(*buff,"cell",4) == 0) { if (num_tokens >= 7) { cflag=TRUE; data->pbc[0] = str_to_float(*(buff+1)); data->pbc[1] = str_to_float(*(buff+2)); data->pbc[2] = str_to_float(*(buff+3)); data->pbc[3] = PI*str_to_float(*(buff+4))/180.0; data->pbc[4] = PI*str_to_float(*(buff+5))/180.0; data->pbc[5] = PI*str_to_float(*(buff+6))/180.0; /* compute direct & reciprocal lattices */ /* NB: enables fn_make_plane() to correctly compute Dhkl */ matrix_lattice_init(data); } else printf("load_planes() error: bad cell line.\n"); } /* space group */ if (g_ascii_strncasecmp(*buff,"space",5) == 0) { if (num_tokens > 1) { sflag=TRUE; data->sginfo.spacename = g_strjoinv(" ", buff+1); data->sginfo.spacenum = 0; } } /* default morphology type */ if (g_ascii_strncasecmp(*buff, "morph", 5) == 0) { if (num_tokens >= 3) { if (g_ascii_strncasecmp(*(buff+1), "unrelaxed", 9) == 0) { if (g_ascii_strncasecmp(*(buff+2), "equil", 5) == 0) data->morph_type = EQUIL_UN; if (g_ascii_strncasecmp(*(buff+2), "growth", 6) == 0) data->morph_type = GROWTH_UN; } if (g_ascii_strncasecmp(*(buff+1), "relaxed", 7) == 0) { if (g_ascii_strncasecmp(*(buff+2), "equil", 5) == 0) data->morph_type = EQUIL_RE; if (g_ascii_strncasecmp(*(buff+2), "growth", 6) == 0) data->morph_type = GROWTH_RE; } } else printf("load_planes() error: bad type line.\n"); } } /* process miller line */ if (g_ascii_strncasecmp(*buff,"miller",6) == 0) { /* init space group (latmat? - if so, remove the make_latmat() in cell parse) */ if (cflag && sflag) { if (!gflag) { if (space_lookup(data)) printf("Error in space group lookup.\n"); gflag = TRUE; } } else { if (data->id == MORPH) { printf("load_planes() error: miller encountered before space or cell.\n"); return(2); } } if (num_tokens >= 4) { h = (gint) str_to_float(*(buff+1)); k = (gint) str_to_float(*(buff+2)); l = (gint) str_to_float(*(buff+3)); #if DEBUG_LOAD_PLANES printf("read plane: %d %d %d\n", h, k, l); #endif VEC3SET(m, h, k, l); /* FIXME - signature change */ /* plane = plane_find(m, data); */ if (!plane) { plane = plane_new(m, data); if (plane) new_planes = g_slist_prepend(new_planes, plane); } } } /* potential data */ if (num_tokens >= 8 && plane) { /* NB: use create_shift(), as it sets some important defaults */ shift = shift_new(0.0); if (shift) { shift->shift = str_to_float(*(buff+0)); shift->region[0] = str_to_float(*(buff+1)); shift->region[1] = str_to_float(*(buff+2)); shift->esurf[0] = str_to_float(*(buff+3)); shift->eatt[0] = str_to_float(*(buff+4)); shift->esurf[1] = str_to_float(*(buff+5)); shift->eatt[1] = str_to_float(*(buff+6)); shift->gnorm = str_to_float(*(buff+7)); #if DEBUG_LOAD_PLANES printf("adding shift: %f\n", shift->shift); #endif /* append to preserve order (eg import on existing plane set) */ plane->shifts = g_slist_append(plane->shifts, shift); } } g_strfreev(buff); } data->planes = g_slist_concat(data->planes, g_slist_reverse(new_planes)); /* compute dhkl's for the plane's list */ for (list=data->planes ; list ; list=g_slist_next(list)) { plane = list->data; /* create default shift if none found */ if (!plane->shifts) { shift = shift_new(0.0); if (shift) plane->shifts = g_slist_append(plane->shifts, shift); } /* get best energy for the plane */ /* FIXME - signature changed */ /* update_plane_energy(plane, data); */ } /* compute symmetry related faces */ /* FIXME - new surface rewrite */ /* surf_symmetry_generate(data); */ 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); } } }