/* * Copyright 1997, Regents of the University of Minnesota * * mesh.c * * This file contains routines for converting 3D and 4D finite element * meshes into dual or nodal graphs * * Started 8/18/97 * George * * $Id: mesh.c 13804 2013-03-04 23:49:08Z karypis $ * */ #include "metislib.h" /*****************************************************************************/ /*! This function creates a graph corresponding to the dual of a finite element mesh. \param ne is the number of elements in the mesh. \param nn is the number of nodes in the mesh. \param eptr is an array of size ne+1 used to mark the start and end locations in the nind array. \param eind is an array that stores for each element the set of node IDs (indices) that it is made off. The length of this array is equal to the total number of nodes over all the mesh elements. \param ncommon is the minimum number of nodes that two elements must share in order to be connected via an edge in the dual graph. \param numflag is either 0 or 1 indicating if the numbering of the nodes starts from 0 or 1, respectively. The same numbering is used for the returned graph as well. \param r_xadj indicates where the adjacency list of each vertex is stored in r_adjncy. The memory for this array is allocated by this routine. It can be freed by calling METIS_free(). \param r_adjncy stores the adjacency list of each vertex in the generated dual graph. The memory for this array is allocated by this routine. It can be freed by calling METIS_free(). */ /*****************************************************************************/ int METIS_MeshToDual(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *ncommon, idx_t *numflag, idx_t **r_xadj, idx_t **r_adjncy) { int sigrval=0, renumber=0; /* set up malloc cleaning code and signal catchers */ if (!gk_malloc_init()) return METIS_ERROR_MEMORY; gk_sigtrap(); if ((sigrval = gk_sigcatch()) != 0) goto SIGTHROW; /* renumber the mesh */ if (*numflag == 1) { ChangeMesh2CNumbering(*ne, eptr, eind); renumber = 1; } /* create dual graph */ *r_xadj = *r_adjncy = NULL; CreateGraphDual(*ne, *nn, eptr, eind, *ncommon, r_xadj, r_adjncy); SIGTHROW: if (renumber) ChangeMesh2FNumbering(*ne, eptr, eind, *ne, *r_xadj, *r_adjncy); gk_siguntrap(); gk_malloc_cleanup(0); if (sigrval != 0) { if (*r_xadj != NULL) free(*r_xadj); if (*r_adjncy != NULL) free(*r_adjncy); *r_xadj = *r_adjncy = NULL; } return metis_rcode(sigrval); } /*****************************************************************************/ /*! This function creates a graph corresponding to (almost) the nodal of a finite element mesh. In the nodal graph, each node is connected to the nodes corresponding to the union of nodes present in all the elements in which that node belongs. \param ne is the number of elements in the mesh. \param nn is the number of nodes in the mesh. \param eptr is an array of size ne+1 used to mark the start and end locations in the nind array. \param eind is an array that stores for each element the set of node IDs (indices) that it is made off. The length of this array is equal to the total number of nodes over all the mesh elements. \param numflag is either 0 or 1 indicating if the numbering of the nodes starts from 0 or 1, respectively. The same numbering is used for the returned graph as well. \param r_xadj indicates where the adjacency list of each vertex is stored in r_adjncy. The memory for this array is allocated by this routine. It can be freed by calling METIS_free(). \param r_adjncy stores the adjacency list of each vertex in the generated dual graph. The memory for this array is allocated by this routine. It can be freed by calling METIS_free(). */ /*****************************************************************************/ int METIS_MeshToNodal(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *numflag, idx_t **r_xadj, idx_t **r_adjncy) { int sigrval=0, renumber=0; /* set up malloc cleaning code and signal catchers */ if (!gk_malloc_init()) return METIS_ERROR_MEMORY; gk_sigtrap(); if ((sigrval = gk_sigcatch()) != 0) goto SIGTHROW; /* renumber the mesh */ if (*numflag == 1) { ChangeMesh2CNumbering(*ne, eptr, eind); renumber = 1; } /* create nodal graph */ *r_xadj = *r_adjncy = NULL; CreateGraphNodal(*ne, *nn, eptr, eind, r_xadj, r_adjncy); SIGTHROW: if (renumber) ChangeMesh2FNumbering(*ne, eptr, eind, *nn, *r_xadj, *r_adjncy); gk_siguntrap(); gk_malloc_cleanup(0); if (sigrval != 0) { if (*r_xadj != NULL) free(*r_xadj); if (*r_adjncy != NULL) free(*r_adjncy); *r_xadj = *r_adjncy = NULL; } return metis_rcode(sigrval); } /*****************************************************************************/ /*! This function creates the dual of a finite element mesh */ /*****************************************************************************/ void CreateGraphDual(idx_t ne, idx_t nn, idx_t *eptr, idx_t *eind, idx_t ncommon, idx_t **r_xadj, idx_t **r_adjncy) { idx_t i, j, nnbrs; idx_t *nptr, *nind; idx_t *xadj, *adjncy; idx_t *marker, *nbrs; if (ncommon < 1) { printf(" Increased ncommon to 1, as it was initially %"PRIDX"\n", ncommon); ncommon = 1; } /* construct the node-element list first */ nptr = ismalloc(nn+1, 0, "CreateGraphDual: nptr"); nind = imalloc(eptr[ne], "CreateGraphDual: nind"); for (i=0; i= ncommon || overlap >= elen-1 || overlap >= eptr[l+1]-eptr[l]-1) nbrs[j++] = l; marker[l] = 0; } return j; } /*****************************************************************************/ /*! This function creates the (almost) nodal of a finite element mesh */ /*****************************************************************************/ void CreateGraphNodal(idx_t ne, idx_t nn, idx_t *eptr, idx_t *eind, idx_t **r_xadj, idx_t **r_adjncy) { idx_t i, j, nnbrs; idx_t *nptr, *nind; idx_t *xadj, *adjncy; idx_t *marker, *nbrs; /* construct the node-element list first */ nptr = ismalloc(nn+1, 0, "CreateGraphNodal: nptr"); nind = imalloc(eptr[ne], "CreateGraphNodal: nind"); for (i=0; ieptr, &mesh->eind, &mesh->ewgt, &mesh, LTERM); *r_mesh = NULL; }