/* * Copyright(C) 1999-2020 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * * See packages/seacas/LICENSE for details */ #include "structs.h" // for vtx_data /* Interpolate the eigenvector from the coarsened to the original graph. This may require regenerating mflag and v2cv arrays from merged array. I also need to undo the merged edges in the reverse order from that in which they were collapsed. */ void ch_interpolate(double ** vecs, /* approximate eigenvectors for graph */ double ** cvecs, /* exact eigenvectors for coarse graph */ int ndims, /* number of vectors to interpolate */ struct vtx_data **graph, /* array of vtx data for graph */ int nvtxs, /* number of vertices in graph */ int * v2cv, /* mapping from vtxs to cvtxs */ int using_ewgts /* are edge weights being used in fine graph? */ ) { double *vec, *cvec; /* pointers into vecs and vecs */ int * eptr; /* loops through edge lists */ float * ewptr; /* loops through edge weights */ float ewgt; /* value for edge weight */ double ewsum; /* sum of incident edge weights */ double sum; /* sum of values of neighbors */ int neighbor; /* neighboring vertex */ int degree; /* number of neighbors */ int npasses = 1; /* number of Gauss-Seidel iterations */ int pass; /* loops through Gauss-Seidel iterations */ int i, j, k; /* loop counters */ /* Uncompress the coarse eigenvector by replicating matched values. */ for (j = 1; j <= ndims; j++) { vec = vecs[j]; cvec = cvecs[j]; for (i = 1; i <= nvtxs; i++) { vec[i] = cvec[v2cv[i]]; } } /* Now do a single pass of Gauss-Seidel to smooth eigenvectors. */ for (pass = 1; pass <= npasses; pass++) { if (using_ewgts) { for (j = 1; j <= ndims; j++) { vec = vecs[j]; for (i = 1; i <= nvtxs; i++) { eptr = graph[i]->edges; ewptr = graph[i]->ewgts; sum = 0; ewsum = 0; degree = graph[i]->nedges - 1; for (k = degree; k; k--) { neighbor = *(++eptr); ewgt = *(++ewptr); sum += ewgt * vec[neighbor]; ewsum += ewgt; } vec[i] = sum / ewsum; } } } else { for (j = 1; j <= ndims; j++) { vec = vecs[j]; for (i = 1; i <= nvtxs; i++) { eptr = graph[i]->edges; sum = 0; degree = graph[i]->nedges - 1; for (k = degree; k; k--) { neighbor = *(++eptr); sum += vec[neighbor]; } vec[i] = sum / degree; } } } } }