void fractional_min(gdouble *x, gint dim) { gint i, j; gdouble whole; g_assert(dim < 4); #if DEBUG_FRAC_MINSQ P3VEC("b4: ", x); #endif for (i=0 ; i<dim ; i++) { /* clamp value -1 < x < 1 */ x[i] = modf(x[i], &whole); /* clamp to range (-0.5, 0.5) */ j = (gint) (-2.0 * x[i]); x[i] += (gdouble) j; } #if DEBUG_FRAC_MINSQ P3VEC("af: ", x); #endif }
void fractional_clamp(gdouble *vec, gint *mov, gint dim) { gint i; gdouble ip; #if DEBUG_CLAMP P3VEC("inp: ", vec); #endif /* NB: init ALL 3 coords as isolated molecules call this */ /* routine & it is expected that mov to be set to 0,0,0 */ mov[0] = mov[1] = mov[2] = 0; /* for (i=0 ; i<dim ; i++) */ for (i=dim ; i-- ; ) { mov[i] = -vec[i]; if (vec[i] < 0.0) { /* increment the move for -ve's with exception -1.0, -2.0, -3.0,... */ if (modf(vec[i], &ip) != 0.0) mov[i]++; } else mov[i] = -vec[i]; vec[i] += (gdouble) mov[i]; } #if DEBUG_CLAMP P3VEC("out: ", vec); #endif }
void camera_dump(gpointer data) { struct camera_pak *camera = data; printf("camera [%p]\n", camera); P4VEC("q: ", camera->q); P3VEC("x: ", camera->x); P3VEC("o: ", camera->o); P3VEC("v: ", camera->v); }
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 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 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 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); }
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); } } }
gint read_nwout_block(FILE *fp, struct model_pak *model) { gint num_tokens; gchar **buff, line[LINELEN], *text; GString *gstring; GSList *clist; struct core_pak *core; clist = model->cores; /* skip until get a 1 in first column for first coordinate */ if (fgetline(fp, line)) return(1); while (g_ascii_strncasecmp(line, " 1", 5) != 0) { if (fgetline(fp, line)) return(1); } buff = tokenize(line, &num_tokens); while (num_tokens > 0) { if (clist) { core = clist->data; clist = g_slist_next(clist); } else { core = new_core(*(buff+1), model); model->cores = g_slist_append(model->cores, core); } core->x[0] = str_to_float(*(buff+3)); core->x[1] = str_to_float(*(buff+4)); core->x[2] = str_to_float(*(buff+5)); #if DEBUG_READ_NWOUT P3VEC("coords: ", core->x); #endif /* get next line */ g_strfreev(buff); if (fgetline(fp, line)) return(2); buff = tokenize(line, &num_tokens); } g_strfreev(buff); /* read until get the details of the current optimisation step */ while (g_ascii_strncasecmp(line, "@", 1) != 0) { if (fgetline(fp, line)) return(0); } buff = tokenize(line, &num_tokens); while (g_ascii_strncasecmp(line, "@", 1) == 0) { if (g_ascii_isdigit(buff[1][0])) { text = format_value_and_units(*(buff+2), 5); gstring = g_string_new(text); g_free(text); g_string_append(gstring, " a.u."); property_add_ranked(3, "Energy", gstring->str, model); g_string_free(gstring, TRUE); text = format_value_and_units(*(buff+5), 5); gstring = g_string_new(text); g_free(text); g_string_append(gstring, " a.u./A"); property_add_ranked(4, "RMS Gradient", gstring->str, model); g_string_free(gstring, TRUE); } /* get next line */ g_strfreev(buff); if (fgetline(fp, line)) return(2); buff = tokenize(line, &num_tokens); } return(0); }
gint read_nwchem_geometry(gpointer scan, struct model_pak *model) { gint n, zmode=0, end_count=0; gchar **buff; struct core_pak *core; #if DEBUG_READ_NWCHEM_GEOMETRY printf("read_nwchem_geometry(): start\n"); #endif // TODO - rewrite this using symbol scanning functionality while (!scan_complete(scan)) { buff = scan_get_tokens(scan, &n); // zmatrix? if (g_ascii_strncasecmp(*buff, "zmatrix", 7) == 0) { zmode = 1; g_strfreev(buff); continue; } if (g_ascii_strncasecmp(*buff, "variables", 9) == 0) { zmode = 2; g_strfreev(buff); continue; } if (g_ascii_strncasecmp(*buff, "constants", 9) == 0) { zmode = 3; g_strfreev(buff); continue; } // end? if (n) { if (g_ascii_strncasecmp(*buff, "end", 3) == 0) { g_strfreev(buff); /* if we processed zmatrix entries - expect 2 x end */ if (zmode && !end_count) { /* keep going until we hit a second end ... */ end_count++; continue; } /* exit */ break; } } /* main parse */ switch (zmode) { // cartesian coords case 0: // can cart coord line have >4 tokens? if (n == 4) { if (elem_test(*buff)) { core = core_new(*buff, NULL, model); model->cores = g_slist_prepend(model->cores, core); core->x[0] = str_to_float(*(buff+1)); core->x[1] = str_to_float(*(buff+2)); core->x[2] = str_to_float(*(buff+3)); #if DEBUG_READ_NWCHEM_GEOMETRY printf("Added [%s] ", *buff); P3VEC(": ", core->x); #endif } } break; // zmatrix coords case 1: #if DEBUG_READ_NWCHEM_GEOMETRY printf("zcoord: %s", scan_cur_line(scan)); #endif zmat_nwchem_core_add(scan_cur_line(scan), model->zmatrix); break; // zmatrix vars case 2: #if DEBUG_READ_NWCHEM_GEOMETRY printf("zvar: %s", scan_cur_line(scan)); #endif zmat_var_add(scan_cur_line(scan), model->zmatrix); break; // zmatrix consts case 3: #if DEBUG_READ_NWCHEM_GEOMETRY printf("zconst: %s", scan_cur_line(scan)); #endif zmat_const_add(scan_cur_line(scan), model->zmatrix); break; } g_strfreev(buff); } if (zmode) { #if DEBUG_READ_NWCHEM_GEOMETRY printf("Creating zmatrix cores...\n"); #endif zmat_angle_units_set(model->zmatrix, DEGREES); zmat_process(model->zmatrix, model); } #if DEBUG_READ_NWCHEM_GEOMETRY printf("read_nwchem_geometry(): stop\n"); #endif return(0); }