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