home *** CD-ROM | disk | FTP | other *** search
- /*
- * k-N(earest)N(eighbor) S(hells)
- *
- * construct kNN shells on the basis of Voronoi diagram output;
- *
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include "vora.h"
-
- #undef DEBUG
- #undef KNN_DEBUG
- #undef MN_DEBUG
- #undef KNN_ARRAY_VER
-
- /* globals */
- extern int KNN_MAX;
- int DISPL_KNNS = 0; /* when set, display full KNN shells */
-
-
- /*
- * for a given Site, evaluate the average, mn, of the nof NN of its nnn NN
- */
- float
- eval_mn (struct vSite *vS, struct vSite *vsa)
- {
- float mn;
- int inn;
-
- mn = (float) 0.0;
- for (inn = 0; inn < vS->nnn; inn++) {
- #ifdef MN_DEBUG
- printf ("\t %d (with %d NNs)\n",
- vS->nnsi[inn], (vsa + (vS->nnsi[inn]))->nnn);
- #endif
- mn += (float) (vsa + (vS->nnsi[inn]))->nnn;
- }
- mn /= (float) vS->nnn;
-
- return (mn);
- }
-
-
- /*
- * evaluate, for each site, the average, m, of the nof NN of its NN;
- * ignore sites which have been flagged (eFlag, aoiFlag) out-of-bounds
- *
- * --> Aboav-Weaire law for cellular structures
- * K.B.Lauritsen, C. Moukarzel & H.J.Herrmann, J. Physique I 3, 1941 (1993)
- */
- int
- m_of_n (int *ndn, float **m_n, int ns, struct vSite *vsa)
- {
- int is, nas;
- int cnn;
- float mn_av;
- struct vSite *vS;
-
- nas = 0;
- for (is = 0; is < ns; is++) {
- vS = (vsa + is);
- if ((vS->eFlag == UnSet) &&
- (vS->aoiFlag == UnSet)) {
- cnn = vS->nnn;
- mn_av = *(m_n[cnn] + ndn[cnn]) = eval_mn (vS, vsa);
- #ifdef MN_DEBUG
- printf ("\nM_OF_N: process site: %d\n", vS->sitenbr);
- printf ("\tmn_av: %f, ndn[%d]: %d, *(mn[]+ndn[]): %f\n", mn_av, cnn, ndn[cnn], *(m_n[cnn] + ndn[cnn]));
- #endif
- ndn[cnn]++;
- nas++;
- }
- }
- return (nas);
- }
-
-
- /*
- * evaluate the average area, Ak, of domains in the kNN shells of
- * the current Site
- */
- void
- eval_aka (struct vSite *vsa, int kNN, double *aka, struct linklist *sha)
- {
- int k;
-
- for (k = 0; k < kNN; k++) { /* loop over k-th NN shells */
- *(aka + k) = xak_kNN_list (vsa, sha + k, k);
- }
- }
-
-
-
-
- /*
- * evaluate, for the current Site, the product c(0)c(k)/nkNN, as a function
- * of k: c denotes topological charge, n-6, of a given site, nkNN denotes
- * the number of sites in the k-th NN shell; these products represent the
- * correlation function of topological charge as a function of topological
- * distance, k;
- */
- int
- eval_tctc (struct vSite *vsa, int kNN, double *tctc, struct linklist *sha)
- {
- int k;
- double c0, ck_bar;
-
-
- c0 = xc0 (vsa, sha + 0); /* topol charge of ref Site site */
- *(tctc + 0) = c0 * c0;
- for (k = 1; k < kNN; k++) { /* loop over k-th NN shells */
- ck_bar = xck_kNN_list (vsa, sha + k, k);
- *(tctc + k) = c0 * ck_bar;
- }
- return ((int) c0);
- }
-
-
- /*
- * evaluate the fractal measure, c, of a set of kNN shells, associated
- * with a given site, such that N_k = c*k**2, 0<=k<=kNN, N_k representing
- * the nof sites contained within the k-th NN shell, i.e.,
- * N_k = sum from {j=0 to j=k} N_j;
- */
- double
- eval_frms (int kNN, struct linklist *sha)
- {
- int k;
- int nk;
- double frms;
-
- nk = 1;
- for (k = 1; k < kNN; k++) { /* <= ??? */
- nk += ll_length (sha + k);
- }
- frms = (double) nk / (double) ((kNN - 1) * (kNN - 1));
- return (frms);
- }
-
-
-
- /*
- * compare list entries
- * key: Site index
- */
- int
- cmpSiteInd (struct nnSite *oldSite, struct nnSite *newSite)
- {
- return (SIGN (oldSite->sitenbr - newSite->sitenbr));
- }
-
- /*
- * init (empty) kNN shell lists
- */
- void
- init_sk (struct linklist *knnsll)
- {
- llzero (knnsll); /* init empty list */
- llsetsize (sizeof (struct nnSite), knnsll);
-
- llsetmatch (cmpSiteInd, knnsll);
- }
-
-
-
- /*
- * scan list, comparing index of newSite with that of Sites already
- * in current list; add Site in order of increasing indices;
- * employs matching function, here cmpSiteInd();
- * (see also: llsearch() in llist.c )
- */
- Boolean
- scanSiteInd (struct nnSite *newSite, struct linklist *list)
- {
- Boolean MatchStatus = False;
-
- llhead (list);
- do {
- if (((*list->match) (list->clp->item, newSite)) > 0)
- MatchStatus = True;
-
- } while ((MatchStatus != True) && (llnext (list) == True));
-
- return (MatchStatus);
- }
-
-
- /*
- * insert new site into current list, maintaining the list sorted
- * in order of increasing nnSite indices
- */
- void
- expand_kNN_list (struct nnSite *nnnS, struct linklist *list)
- {
- Boolean MatchStatus;
-
- llhead (list);
- if ((MatchStatus = scanSiteInd (nnnS, list)) == True)
- lladdprev ((char *) nnnS, list);
- else
- lladd ((char *) nnnS, list);
- }
-
-
- /*
- * remove duplicate entries from kNN list which is assumed to contain
- * kNN site indices in increasing order
- */
- void
- contract_kNN_list (struct linklist *list)
- {
- struct nnSite *nnS, *nnSpp;
-
-
- if (ll_length (list) < 2) {
- #ifdef KNN_DEBUG
- printf ("...list contains less than two entries\n");
- #endif
- }
- else {
- llhead (list);
- nnS = (struct nnSite *) list->clp->item;
- while (llnext (list) == True) {
- nnSpp = (struct nnSite *) list->clp->item;
- if (nnS->sitenbr == nnSpp->sitenbr) {
- lldelete (list);
- nnS = (struct nnSite *) list->clp->item;
- }
- else {
- nnS = nnSpp;
- }
- }
- }
- }
-
-
- /*
- * display list
- */
- void
- show_kNN_list (struct linklist *list, int k)
- {
- int is;
-
- printf ("SHOW_KNN_LIST: %2d-NN shell:", k);
- llhead (list);
- if (ll_length (list) != 0) { /* list not empty */
- is = 0;
- do {
- printf (" %3d ",
- ((struct nnSite *) list->clp->item)->sitenbr);
- is++;
-
- if ((is + 1) % 10 == 0)
- printf ("\n");
- } while (llnext (list) == True);
- printf ("\n");
- }
- else
- printf (" list empty\n");
- }
-
-
-
-
- /*
- * extract average area of k-th NN shells from corresponding lists
- */
- double
- xak_kNN_list (struct vSite *vsa, struct linklist *list, int k)
- {
- int is, lk;
- double ak = 0.0;
-
- llhead (list);
- if ((lk = ll_length (list)) != 0) { /* list not empty */
- do {
- is = ((struct nnSite *) list->clp->item)->sitenbr;
- ak += (double) ((vsa + is)->area);
-
- } while (llnext (list) == True);
- ak /= (double) lk;
- }
- else
- printf (" list for %d-th NN shell empty\n", k);
-
- return (ak);
- }
-
-
- /*
- * extract topol charge of ref Site (stored at top of list sha+0)
- */
- double
- xc0 (struct vSite *vsa, struct linklist *list)
- {
- int is, lk;
- double c0 = 100.0;
-
- llhead (list);
- if ((lk = ll_length (list)) != 0) { /* list not empty */
- is = ((struct nnSite *) list->clp->item)->sitenbr;
- c0 = (double) ((vsa + is)->nnn - 6);
- }
- else
- printf (" list empty, something wrong\n");
-
- return (c0);
- }
-
-
- /*
- * extract average topological charge of k-th NN shells
- * from corresponding lists
- */
- double
- xck_kNN_list (struct vSite *vsa, struct linklist *list, int k)
- {
- int is, lk;
- double tck = 0.0;
-
- llhead (list);
- if ((lk = ll_length (list)) != 0) { /* list not empty */
- do {
- is = ((struct nnSite *) list->clp->item)->sitenbr;
- tck += (double) ((vsa + is)->nnn - 6);
-
- } while (llnext (list) == True);
- tck /= (double) lk;
- }
- else
- printf (" list for %d-th NN shell empty\n", k);
-
- return (tck);
- }
-
-
- /*
- * copy vSite information to root of kNN shell lists
- */
- void
- init_sk0 (struct vSite *vsa, int sitenbr, struct linklist *list)
- {
- struct nnSite nnS, *pnnS = &nnS;
-
- (vsa + sitenbr)->status = InActive;
- pnnS->sitenbr = sitenbr;
-
- expand_kNN_list (pnnS, list);
- }
-
-
-
- /*
- * set Status of all Sites to Active
- */
- void
- SetActive (struct vSite *vsa, int ns)
- {
- int is;
-
- for (is = 0; is < ns; is++)
- (vsa + is)->status = Active;
- }
-
-
- /*
- * extract, from Voronoi diagram, kNN shells of a given site,
- * in order of increasing k: k=0 refers to the Site itself;
- * the NN shells are constructed on the basis of an array of Voronoi sites
- * which gives site coordinates, site index and NN site indices;
- *
- * the desired list of NN shells is implemented as a list of lists, for
- * each site in the set; for each k, there is a list of indices giving the
- * sites of the corresponding shell; for given ROOT site, each site is
- * uniquely assigned to one shell: that is, as k increases, only those
- * site indices area added to the current shell which have not been
- * assigned to any previous shell; once assigned, a site is given InActive
- * status; the recursion comes to an end when either a maximum k is reached
- * or else, if there are no more Active sites to be added to new shells
- */
- struct linklist *
- kNNs (struct vSite *vsa, struct linklist *plist, struct linklist *clist, int k)
- {
- struct nnSite *pnnS, nnS, *cnnS = &nnS;
- struct vSite *vS;
- int inn;
- Boolean Descend_Status;
-
-
- #ifdef DEBUG
- printf ("\nKNNS:\n");
- printf ("...pointers:\n");
- printf ("\tvsa: %p, plist: %p, clist: %p\n", vsa, plist, clist);
- printf ("\textract_kNN: %p\n", kNNs);
- printf ("...new parent list length: %3d\n", ll_length (plist));
- show_kNN_list (plist, k);
- #endif
-
- llhead (plist); /* parent list */
- llhead (clist); /* child list */
- Descend_Status = False;
- do { /* step through parent list */
- pnnS = (struct nnSite *) plist->clp->item;
- vS = vsa + (pnnS->sitenbr);
-
- for (inn = 0; inn < vS->nnn; inn++) { /* loop over NN ind of vS */
- if ((vsa + (vS->nnsi[inn]))->status == Active) {
-
- cnnS->sitenbr = (vS->nnsi[inn]);
- expand_kNN_list (cnnS, clist);
-
- if (Descend_Status == False)
- Descend_Status = True;
-
- (vsa + (vS->nnsi[inn]))->status = InActive;
- }
- }
- } while (llnext (plist) == True);
-
- if (Descend_Status == True) {
- contract_kNN_list (clist);
- return (clist);
- }
- else {
- #ifdef DEBUG
- printf ("\nKNNS: no more Active sites\n");
- #endif
- return (clist = (struct linklist *) NULL);
- }
- }
-
-
-
- /*
- * code to construct, on the basiis of the Voronoi diagram, the k-NN shells
- * for each site in a point set
- *
- * the function construct_kNNs() handles the kNN shells for a single
- * site at a time, and evaluates quantities of interest before going
- * on to the next site; that is, a single array of shells, sk, properly
- * dimensioned to KNN_MAX, is repeatedly used to store the kNN
- * shells of successively examined sites
- *
- * a note on the data structures:
- * sk is an array of pointers to struct kNNShell; one such array is
- * associated with each site, is <= ns, in the set; each entry in sk,
- * sk[is], contains the size, kNN, of the actual nof shells built for
- * a given ``root'' site, and quantities of interest evaluated from that
- * shell, such as the fractal measure;
- * for each root Site, an array, sha, of (maximally) KNN_MAX shells is
- * constructed (and then recycled for the following root Site): the k-th
- * element, sha[k], of that array represents the k-th NN shell of the root
- * Site in the form of a list of structs nnSite, containing, among other
- * entries, the indices (into the Site array vsa) identifying the k-th NN;
- *
- * if memory consumption still presents a concern, this version could
- * be modified to dispense with the array, sk, and just store information
- * for a single Site at a time: in that case, evaluation of quantities
- * such as the fractal measure would have to integrated in kNN construction
- *
- * a memory-consuming, but conceptually appealing version:
- * -------------------------------------------------------
- * for the akNNs version, sk[is] contains, in addition, an array of
- * kNN lists; the k-th element, (sk+is)->sha[k], in any such array is
- * a list containing the set of indices comprising the k-NN shell of
- * the ``root'' or reference site;
- * sites which have been flagged (eFlag, aoiFlag) out-of-bounds
- * are not processed: their kNN shells (k>0) contain 0 elements
- */
- double
- construct_kNNs (int ns, struct vSite *vsa, struct linklist *sha, struct kNNShell *sk)
- {
- int is, k;
- int nas;
- double frms;
- struct vSite *vS;
-
- struct linklist *plist, *clist; /* ptr to parent(k) list */
-
-
- /*
- * construct kNN shells, one site at a time
- */
- frms = 0.0;
- nas = 0;
- printf ("\tSite:");
- for (is = 0; is < ns; is++) { /* loop over sites */
- (sk + is)->sitenbr = (vsa + is)->sitenbr;
-
- if (is % 50 == 0)
- printf ("...%3d", is);
- if ((is + 1) == ns)
- printf ("...%3d\n", is);
-
- /* set status of all Sites to Active (must be repeated) */
- SetActive (vsa, ns);
-
- /* set up empty list structs */
- for (k = 0; k < KNN_MAX; k++)
- init_sk (sha + k);
-
- /* loop over successive k-NN shells of current ``root'' site */
- init_sk0 (vsa, (vsa + is)->sitenbr, sha + 0);
- if (DISPL_KNNS == 1)
- show_kNN_list (sha + 0, 0);
-
- if (((vS = (vsa + is))->eFlag == UnSet) &&
- (vS->aoiFlag == UnSet)) { /* Site out-of-bounds ? */
- k = 0;
- plist = (struct linklist *) (sha + 0);
- do {
- if (++k >= KNN_MAX) {
- #ifdef KNN_DEBUG
- printf ("...reached max NN shell: ");
- printf (" k: %d\n", k);
- #endif
- plist = (struct linklist *) NULL;
- }
- else {
- clist = (struct linklist *) (&sha[k]);
- plist = kNNs (vsa, plist, clist, k);
-
- #ifdef KNN_DEBUG
- printf ("...%d-th shell completed\n", k);
- for (j = 0; j <= k; j++)
- show_kNN_list (sha + j, j);
- #endif
- }
- } while (plist != (struct linklist *) NULL);
- (sk + is)->kNN = k;
-
- if (DISPL_KNNS == 1) {
- printf ("...%d-NN shells for Site %d\n",
- k, vS->sitenbr);
- for (k = 0; k < (sk + is)->kNN; k++)
- show_kNN_list (sha + k, k);
- }
-
- /*
- * employ kNN shells of current root Site to evaluate further
- * quantities of interest; soter these in sk[is]
- *
- * fractal measure:
- * c, in Nk = c*k**2, where Nk denotes the number
- * of domains in the k-th NN shell of a given site
- */
- (sk + is)->frms = eval_frms ((sk + is)->kNN, sha);
- #ifdef KNN_DEBUG
- printf ("\n...fractal measure (from %d shells): %lf\n",
- (sk + is)->kNN, (sk + is)->frms);
- #endif
- frms += (sk + is)->frms;
- nas++;
-
-
- /*
- * average area, <Ak>, of domains in k-th NN shell, as function of k
- */
- eval_aka (vsa, (sk + is)->kNN, (sk + is)->aka, sha);
-
- /*
- * correlation function, tccf(k) = c(0)c(k), of topological charge,
- * c=n-6, as function of topological distance, k, for given site;
- */
- (sk + is)->tc = eval_tctc (vsa, (sk + is)->kNN, (sk + is)->tctc, sha);
- }
- else { /* Site skipped */
- (sk + is)->kNN = 0;
- }
- }
- frms /= (double) nas;
- return (frms);
- }
-
-
-
- /*
- * code to construct k-NN shells for each site in a point set
- * on the basis of Voronoi diagram:
- * this version, construct_akNNs() handles an entire array of shells,
- * one for each site in the set (see loop over sites); this has the
- * disadvantage of requiring large amounts of memory, but has the
- * advantage of making available all requisite data for subsequent
- * computation of topological quantities
- *
- * 3/94: not completely debugged, not maintained
- *
- * a note on the data structures:
- * sk is an array of pointers to struct kNNShell; one such array is
- * associated with each site, is <= ns, in the set; each entry in sk,
- * sk[is], contains the size, kNN, of the actual nof shells built for
- * a given ``root'' site, and an array of kNN lists; the k-th element,
- * (sk+is)->sha[k], in any such array is a list containing the set
- * of indices comprising the k-NN shell of the ``root'' site
- */
- #ifdef KNN_ARRAY_VER
- struct kNNShell *
- construct_akNNs (int ns, struct vSite *vsa)
- {
- int is, j, k, kNN;
-
- struct kNNShell *sk; /* array of struct kNNShell */
- struct linklist *plist, *clist; /* ptr to parent(k) list */
- struct linklist *sksi;
-
- /*
- * mem alloc
- */
- if ((sk = (struct kNNShell *) calloc (ns, sizeof (struct kNNShell))) == NULL)
- fail_alloc ("sk", 1);
-
- for (is = 0; is < ns; is++) { /* loop over sites */
-
- /*
- * handle shell structure mem alloc
- */
- if (((sk + is)->sha = (struct linklist *) calloc (KNN_MAX, sizeof (struct linklist))) == NULL)
- fail_alloc ("(sk+is)->sha", 1);
-
- sksi = (sk + is)->sha; /* array of kNN lists */
-
- /*
- * printf("\n...size of struct linklist: %d\n",
- * sizeof(struct linklist));
- * printf("...size of sksi: %d\n", sizeof(sksi));
- */
-
- /*
- * set status of all Sites to Active (must be repeated)
- */
- SetActive (vsa, ns);
-
- /* set up empty list structs */
- printf ("\n...initialize empty k-NN shell lists\n");
- for (k = 0; k < KNN_MAX; k++)
- init_sk (&((sk + is)->sha[k]));
-
- /* loop over successive k-NN shells of current ``root'' site */
- init_sk0 (vsa, (vsa + is)->sitenbr, &((sk + is)->sha[0]));
- show_kNN_list (&((sk + is)->sha[0]), 0);
-
- k = 0;
- plist = &((sk + is)->sha[0]);
- do {
- /* clist = (struct linklist *)(sksi+k); */
- /*
- * printf("\n...pointers:\n");
- * printf("\tsksi: %p, sksi+k: %p, ++sksi: %p\n",
- * sksi, sksi+k, ++sksi);
- * printf("\tplist: %p, clist: %p\n", plist, clist);
- * --sksi;
- */
-
- if (++k >= KNN_MAX) {
- printf ("...reached max NN shell, k: %d\n", k);
- plist = (struct linklist *) NULL;
- }
- else {
- printf ("...new k: %d\n", k);
- clist = &((sk + is)->sha[k]);
-
-
- plist = kNNs (vsa, plist, clist, k);
-
- #ifdef KNN_DEBUG
- printf ("...%d-th shell completed\n", k);
- for (j = 0; j <= k; j++)
- show_kNN_list (&((sk + is)->sha[j]), j);
- #endif
- }
- } while (plist != (struct linklist *) NULL);
- (sk + is)->kNN = kNN = k;
-
- printf ("...%d-NN shells for Site %d\n", k, (vsa + is)->sitenbr);
- for (k = 0; k < (sk + is)->kNN; k++)
- show_kNN_list (&((sk + is)->sha[k]), k);
-
- if (((sk + is)->sha = (struct linklist *) realloc ((sk + is)->sha, kNN * sizeof (struct linklist))) == NULL)
- fail_alloc ("realloc (sk+is)->sha", 1);
- }
- for (is = 0; is < ns; is++)
- free ((sk + is));
- return (sk);
- }
- #endif
-