int Zoltan_Matrix_Build (ZZ* zz, Zoltan_matrix_options *opt, Zoltan_matrix* matrix) { static char *yo = "Zoltan_Matrix_Build"; int ierr = ZOLTAN_OK; int nX; int *xGNO = NULL; ZOLTAN_ID_PTR xLID=NULL; ZOLTAN_ID_PTR xGID=NULL; ZOLTAN_ID_PTR yGID=NULL; ZOLTAN_ID_PTR pinID=NULL; float *xwgt = NULL; int * Input_Parts=NULL; struct Zoltan_DD_Struct *dd = NULL; int *proclist = NULL; int *xpid = NULL; int i; ZOLTAN_TRACE_ENTER(zz, yo); memset (matrix, 0, sizeof(Zoltan_matrix)); /* Set all fields to 0 */ memcpy (&matrix->opts, opt, sizeof(Zoltan_matrix_options)); /**************************************************/ /* Obtain vertex information from the application */ /**************************************************/ ierr = Zoltan_Get_Obj_List(zz, &nX, &xGID, &xLID, zz->Obj_Weight_Dim, &xwgt, &Input_Parts); if (ierr != ZOLTAN_OK && ierr != ZOLTAN_WARN) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error getting object data"); goto End; } ZOLTAN_FREE(&Input_Parts); ZOLTAN_FREE(&xwgt); /*******************************************************************/ /* Assign vertex consecutive numbers (gnos) */ /*******************************************************************/ if (matrix->opts.speed == MATRIX_FULL_DD) { /* Zoltan computes a translation */ if (nX) { xGNO = (int*) ZOLTAN_MALLOC(nX*sizeof(int)); if (xGNO == NULL) MEMORY_ERROR; } ierr = Zoltan_PHG_GIDs_to_global_numbers(zz, xGNO, nX, matrix->opts.randomize, &matrix->globalX); if (ierr != ZOLTAN_OK && ierr != ZOLTAN_WARN) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error assigning global numbers to vertices"); goto End; } ierr = Zoltan_DD_Create (&dd, zz->Communicator, zz->Num_GID, 1, 0, nX, 0); CHECK_IERR; /* Make our new numbering public */ Zoltan_DD_Update (dd, xGID, (ZOLTAN_ID_PTR) xGNO, NULL, NULL, nX); } else { /* We don't want to use the DD */ xGNO = (int *) xGID; MPI_Allreduce(&nX, &matrix->globalX, 1, MPI_INT, MPI_SUM, zz->Communicator); } /* I store : xGNO, xGID, xpid, */ ierr = Zoltan_DD_Create (&matrix->ddX, zz->Communicator, 1, zz->Num_GID, 1, matrix->globalX/zz->Num_Proc, 0); CHECK_IERR; /* Hope a linear assignment will help a little */ Zoltan_DD_Set_Neighbor_Hash_Fn1(matrix->ddX, matrix->globalX/zz->Num_Proc); /* Associate all the data with our xGNO */ xpid = (int*)ZOLTAN_MALLOC(nX*sizeof(int)); if (nX >0 && xpid == NULL) MEMORY_ERROR; for (i = 0 ; i < nX ; ++i) xpid[i] = zz->Proc; Zoltan_DD_Update (matrix->ddX, (ZOLTAN_ID_PTR)xGNO, xGID, (ZOLTAN_ID_PTR) xpid, NULL, nX); ZOLTAN_FREE(&xpid); if (matrix->opts.pinwgt) matrix->pinwgtdim = zz->Edge_Weight_Dim; else matrix->pinwgtdim = 0; ierr = matrix_get_edges(zz, matrix, &yGID, &pinID, nX, &xGID, &xLID, &xGNO, &xwgt); CHECK_IERR; matrix->nY_ori = matrix->nY; if ((ierr != ZOLTAN_OK) && (ierr != ZOLTAN_WARN)){ goto End; } if (matrix->opts.enforceSquare && matrix->redist) { /* Convert yGID to yGNO using the same translation as x */ /* Needed for graph : rowID = colID */ /* y and x may have different distributions */ matrix->yGNO = (int*)ZOLTAN_MALLOC(matrix->nY * sizeof(int)); if (matrix->nY && matrix->yGNO == NULL) MEMORY_ERROR; ierr = Zoltan_DD_Find (dd, yGID, (ZOLTAN_ID_PTR)(matrix->yGNO), NULL, NULL, matrix->nY, NULL); if (ierr != ZOLTAN_OK) { ZOLTAN_PRINT_ERROR(zz->Proc,yo,"Hyperedge GIDs don't match.\n"); ierr = ZOLTAN_FATAL; goto End; } } if (matrix->opts.local) { /* keep only local edges */ proclist = (int*) ZOLTAN_MALLOC(matrix->nPins*sizeof(int)); if (matrix->nPins && proclist == NULL) MEMORY_ERROR; } else proclist = NULL; /* Convert pinID to pinGNO using the same translation as x */ if (matrix->opts.speed == MATRIX_FULL_DD) { matrix->pinGNO = (int*)ZOLTAN_MALLOC(matrix->nPins* sizeof(int)); if ((matrix->nPins > 0) && (matrix->pinGNO == NULL)) MEMORY_ERROR; ierr = Zoltan_DD_Find (dd, pinID, (ZOLTAN_ID_PTR)(matrix->pinGNO), NULL, NULL, matrix->nPins, proclist); if (ierr != ZOLTAN_OK) { ZOLTAN_PRINT_ERROR(zz->Proc,yo,"Undefined GID found.\n"); ierr = ZOLTAN_FATAL; goto End; } ZOLTAN_FREE(&pinID); Zoltan_DD_Destroy(&dd); dd = NULL; } else { matrix->pinGNO = (int *) pinID; pinID = NULL; } /* if (matrix->opts.local) { /\* keep only local edges *\/ */ /* int *nnz_list; /\* nnz offset to delete *\/ */ /* int nnz; /\* number of nnz to delete *\/ */ /* int i; */ /* nnz_list = (int*) ZOLTAN_MALLOC(matrix->nPins*sizeof(int)); */ /* if (matrix->nPins && nnz_list == NULL) MEMORY_ERROR; */ /* for (i = 0, nnz=0 ; i < matrix->nPins ; ++i) { */ /* if (proclist[i] == zz->Proc) continue; */ /* nnz_list[nnz++] = i; */ /* } */ /* ZOLTAN_FREE(&proclist); */ /* Zoltan_Matrix_Delete_nnz(zz, matrix, nnz, nnz_list); */ /* } */ if (!matrix->opts.enforceSquare) { /* Hyperedges name translation is different from the one of vertices */ matrix->yGNO = (int*)ZOLTAN_CALLOC(matrix->nY, sizeof(int)); if (matrix->nY && matrix->yGNO == NULL) MEMORY_ERROR; /* int nGlobalEdges = 0; */ ierr = Zoltan_PHG_GIDs_to_global_numbers(zz, matrix->yGNO, matrix->nY, matrix->opts.randomize, &matrix->globalY); CHECK_IERR; /* /\**************************************************************************************** */ /* * If it is desired to remove dense edges, divide the list of edges into */ /* * two lists. The ZHG structure will contain the removed edges (if final_output is true), */ /* * and the kept edges will be returned. */ /* ****************************************************************************************\/ */ /* totalNumEdges = zhg->globalHedges; */ /* ierr = remove_dense_edges_matrix(zz, zhg, edgeSizeThreshold, final_output, */ /* &nLocalEdges, &nGlobalEdges, &nPins, */ /* &edgeGNO, &edgeSize, &edgeWeight, &pinGNO, &pinProcs); */ /* if (nGlobalEdges < totalNumEdges){ */ /* /\* re-assign edge global numbers if any edges were removed *\/ */ /* ierr = Zoltan_PHG_GIDs_to_global_numbers(zz, edgeGNO, nLocalEdges, */ /* randomizeInitDist, &totalNumEdges); */ /* if (ierr != ZOLTAN_OK && ierr != ZOLTAN_WARN) { */ /* ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error reassigning global numbers to edges"); */ /* goto End; */ /* } */ /* } */ /* We have to define ddY : yGNO, yGID, ywgt */ ierr = Zoltan_DD_Create (&matrix->ddY, zz->Communicator, 1, zz->Num_GID, 0, matrix->globalY/zz->Num_Proc, 0); /* Hope a linear assignment will help a little */ Zoltan_DD_Set_Neighbor_Hash_Fn1(matrix->ddY, matrix->globalY/zz->Num_Proc); /* Associate all the data with our yGNO */ Zoltan_DD_Update (matrix->ddY, (ZOLTAN_ID_PTR)matrix->yGNO, yGID, NULL, NULL, matrix->nY); } End: ZOLTAN_FREE(&xpid); ZOLTAN_FREE(&xLID); ZOLTAN_FREE(&xGNO); ZOLTAN_FREE(&xGID); ZOLTAN_FREE(&xwgt); ZOLTAN_FREE(&Input_Parts); ZOLTAN_FREE(&proclist); if (dd != NULL) Zoltan_DD_Destroy(&dd); /* Already stored in the DD */ ZOLTAN_FREE(&yGID); ZOLTAN_TRACE_EXIT(zz, yo); return (ierr); }
int Zoltan_Matrix_Build (ZZ* zz, Zoltan_matrix_options *opt, Zoltan_matrix* matrix, int request_GNOs, /* Input: Flag indicating calling code needs translation of extra GIDs to GNOs; partial 2D coloring needs this feature. */ int num_requested, /* Input: Local # of GIDs needing translation to GNOs. */ ZOLTAN_ID_PTR requested_GIDs, /* Input: Calling code requests the GNOs for these GIDs */ ZOLTAN_GNO_TYPE *requested_GNOs /* Output: Return GNOs of the requested GIDs. */ ) { static char *yo = "Zoltan_Matrix_Build"; int ierr = ZOLTAN_OK; int nX; ZOLTAN_GNO_TYPE tmp; ZOLTAN_GNO_TYPE *xGNO = NULL; ZOLTAN_ID_PTR xLID=NULL; ZOLTAN_ID_PTR xGID=NULL; ZOLTAN_ID_PTR yGID=NULL; ZOLTAN_ID_PTR pinID=NULL; float *xwgt = NULL; int * Input_Parts=NULL; struct Zoltan_DD_Struct *dd = NULL; int *proclist = NULL; int *xpid = NULL; int i; int gno_size_for_dd; MPI_Datatype zoltan_gno_mpi_type; int use_full_dd = (opt->speed == MATRIX_FULL_DD); int fast_build_base = opt->fast_build_base; matrix->opts.speed = opt->speed; matrix->opts.fast_build_base = opt->fast_build_base; ZOLTAN_TRACE_ENTER(zz, yo); if (num_requested && (!requested_GIDs || !requested_GNOs)) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error in requested input; needed arrays are NULL.\n"); } /* ZOLTAN_GNO_TYPE is >= ZOLTAN_ID_TYPE */ gno_size_for_dd = sizeof(ZOLTAN_GNO_TYPE) / sizeof(ZOLTAN_ID_TYPE); zoltan_gno_mpi_type = Zoltan_mpi_gno_type(); memset (matrix, 0, sizeof(Zoltan_matrix)); /* Set all fields to 0 */ memcpy (&matrix->opts, opt, sizeof(Zoltan_matrix_options)); /**************************************************/ /* Obtain vertex information from the application */ /**************************************************/ ierr = Zoltan_Get_Obj_List(zz, &nX, &xGID, &xLID, zz->Obj_Weight_Dim, &xwgt, &Input_Parts); if (ierr != ZOLTAN_OK && ierr != ZOLTAN_WARN) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error getting object data"); goto End; } ZOLTAN_FREE(&Input_Parts); ZOLTAN_FREE(&xwgt); /*******************************************************************/ /* Assign vertex consecutive numbers (gnos) */ /*******************************************************************/ if (use_full_dd) { /* Zoltan computes a translation */ /* Have to use Data Directory if request_GNOs is true. */ if (nX) { xGNO = (ZOLTAN_GNO_TYPE*) ZOLTAN_MALLOC(nX*sizeof(ZOLTAN_GNO_TYPE)); if (xGNO == NULL) MEMORY_ERROR; } ierr = Zoltan_PHG_GIDs_to_global_numbers(zz, xGNO, nX, matrix->opts.randomize, &matrix->globalX); if (ierr != ZOLTAN_OK && ierr != ZOLTAN_WARN) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error assigning global numbers to vertices"); goto End; } ierr = Zoltan_DD_Create (&dd, zz->Communicator, zz->Num_GID, gno_size_for_dd, 0, nX, 0); CHECK_IERR; /* Make our new numbering public */ Zoltan_DD_Update (dd, xGID, (ZOLTAN_ID_PTR) xGNO, NULL, NULL, nX); if (request_GNOs) { Zoltan_DD_Find(dd, requested_GIDs, (ZOLTAN_ID_PTR) requested_GNOs, NULL, NULL, num_requested, NULL); } } else { /* We don't want to use the DD */ /* * KDDKDD 2/10/11 This code cannot work when NUM_GID_ENTRIES>1. * KDDKDD 2/10/11 The assumption is that, if a user sets the * KDDKDD 2/10/11 appropriate parameter to enable this code, the user * KDDKDD 2/10/11 knows that his GIDs are compatible with integers. */ if (sizeof(ZOLTAN_GNO_TYPE) != sizeof(ZOLTAN_ID_TYPE)){ xGNO = (ZOLTAN_GNO_TYPE*) ZOLTAN_MALLOC(nX*sizeof(ZOLTAN_GNO_TYPE)); if (nX && xGNO == NULL) MEMORY_ERROR; for (i=0; i < nX; i++) xGNO[i] = (ZOLTAN_GNO_TYPE)xGID[i] - fast_build_base; } else { xGNO = (ZOLTAN_GNO_TYPE *)xGID; if (fast_build_base) for (i = 0; i < nX; i++) xGNO[i] -= fast_build_base; } for (i = 0; i < num_requested; i++) requested_GNOs[i] = (ZOLTAN_GNO_TYPE)requested_GIDs[i] - fast_build_base; tmp = (ZOLTAN_GNO_TYPE)nX; MPI_Allreduce(&tmp, &matrix->globalX, 1, zoltan_gno_mpi_type, MPI_SUM, zz->Communicator); } /* I store : xGNO, xGID, xpid, */ ierr = Zoltan_DD_Create (&matrix->ddX, zz->Communicator, gno_size_for_dd, zz->Num_GID, sizeof(int), matrix->globalX/zz->Num_Proc, 0); CHECK_IERR; /* Hope a linear assignment will help a little */ if (matrix->globalX/zz->Num_Proc) Zoltan_DD_Set_Neighbor_Hash_Fn1(matrix->ddX, matrix->globalX/zz->Num_Proc); /* Associate all the data with our xGNO */ xpid = (int*)ZOLTAN_MALLOC(nX*sizeof(int)); if (nX >0 && xpid == NULL) MEMORY_ERROR; for (i = 0 ; i < nX ; ++i) xpid[i] = zz->Proc; Zoltan_DD_Update (matrix->ddX, (ZOLTAN_ID_PTR)xGNO, xGID, (char *)xpid, NULL, nX); ZOLTAN_FREE(&xpid); if (matrix->opts.pinwgt) matrix->pinwgtdim = zz->Edge_Weight_Dim; else matrix->pinwgtdim = 0; ierr = matrix_get_edges(zz, matrix, &yGID, &pinID, nX, &xGID, &xLID, &xGNO, &xwgt, use_full_dd); CHECK_IERR; matrix->nY_ori = matrix->nY; if ((ierr != ZOLTAN_OK) && (ierr != ZOLTAN_WARN)){ goto End; } if (matrix->opts.enforceSquare && matrix->redist) { /* Convert yGID to yGNO using the same translation as x */ /* Needed for graph : rowID = colID */ /* y and x may have different distributions */ matrix->yGNO = (ZOLTAN_GNO_TYPE*)ZOLTAN_MALLOC(matrix->nY * sizeof(ZOLTAN_GNO_TYPE)); if (matrix->nY && matrix->yGNO == NULL) { ZOLTAN_FREE(&pinID); MEMORY_ERROR; } ierr = Zoltan_DD_Find (dd, yGID, (ZOLTAN_ID_PTR)(matrix->yGNO), NULL, NULL, matrix->nY, NULL); if (ierr != ZOLTAN_OK) { ZOLTAN_PRINT_ERROR(zz->Proc,yo,"Hyperedge GIDs don't match.\n"); ierr = ZOLTAN_FATAL; ZOLTAN_FREE(&pinID); goto End; } } if (matrix->opts.local) { /* keep only local edges */ proclist = (int*) ZOLTAN_MALLOC(matrix->nPins*sizeof(int)); if (matrix->nPins && proclist == NULL) { ZOLTAN_FREE(&pinID); MEMORY_ERROR; } } else proclist = NULL; /* Convert pinID to pinGNO using the same translation as x */ if (use_full_dd) { matrix->pinGNO = (ZOLTAN_GNO_TYPE*)ZOLTAN_MALLOC(matrix->nPins* sizeof(ZOLTAN_GNO_TYPE)); if ((matrix->nPins > 0) && (matrix->pinGNO == NULL)) { ZOLTAN_FREE(&pinID); MEMORY_ERROR; } ierr = Zoltan_DD_Find (dd, pinID, (ZOLTAN_ID_PTR)(matrix->pinGNO), NULL, NULL, matrix->nPins, proclist); if (ierr != ZOLTAN_OK) { ZOLTAN_PRINT_ERROR(zz->Proc,yo,"Undefined GID found.\n"); ierr = ZOLTAN_FATAL; goto End; } ZOLTAN_FREE(&pinID); Zoltan_DD_Destroy(&dd); dd = NULL; } else { if (sizeof(ZOLTAN_GNO_TYPE) != sizeof(ZOLTAN_ID_TYPE)){ matrix->pinGNO = (ZOLTAN_GNO_TYPE *)ZOLTAN_MALLOC(matrix->nPins * sizeof(ZOLTAN_GNO_TYPE)); if (matrix->nPins && !matrix->pinGNO){ ZOLTAN_FREE(&pinID); MEMORY_ERROR; } for (i=0; i < matrix->nPins; i++) matrix->pinGNO[i] = (ZOLTAN_GNO_TYPE)pinID[i] - fast_build_base; ZOLTAN_FREE(&pinID); } else{ matrix->pinGNO = (ZOLTAN_GNO_TYPE *) pinID; if (fast_build_base) for (i=0; i < matrix->nPins; i++) matrix->pinGNO[i] -= fast_build_base; pinID = NULL; } } /* if (matrix->opts.local) { /\* keep only local edges *\/ */ /* int *nnz_list; /\* nnz offset to delete *\/ */ /* int nnz; /\* number of nnz to delete *\/ */ /* int i; */ /* nnz_list = (int*) ZOLTAN_MALLOC(matrix->nPins*sizeof(int)); */ /* if (matrix->nPins && nnz_list == NULL) MEMORY_ERROR; */ /* for (i = 0, nnz=0 ; i < matrix->nPins ; ++i) { */ /* if (proclist[i] == zz->Proc) continue; */ /* nnz_list[nnz++] = i; */ /* } */ /* ZOLTAN_FREE(&proclist); */ /* Zoltan_Matrix_Delete_nnz(zz, matrix, nnz, nnz_list); */ /* } */ if (!matrix->opts.enforceSquare) { /* Hyperedges name translation is different from the one of vertices */ matrix->yGNO = (ZOLTAN_GNO_TYPE*)ZOLTAN_CALLOC(matrix->nY, sizeof(ZOLTAN_GNO_TYPE)); if (matrix->nY && matrix->yGNO == NULL) MEMORY_ERROR; /* int nGlobalEdges = 0; */ ierr = Zoltan_PHG_GIDs_to_global_numbers(zz, matrix->yGNO, matrix->nY, matrix->opts.randomize, &matrix->globalY); CHECK_IERR; /* /\**************************************************************************************** */ /* * If it is desired to remove dense edges, divide the list of edges into */ /* * two lists. The ZHG structure will contain the removed edges (if final_output is true), */ /* * and the kept edges will be returned. */ /* ****************************************************************************************\/ */ /* totalNumEdges = zhg->globalHedges; */ /* ierr = remove_dense_edges_matrix(zz, zhg, edgeSizeThreshold, final_output, */ /* &nLocalEdges, &nGlobalEdges, &nPins, */ /* &edgeGNO, &edgeSize, &edgeWeight, &pinGNO, &pinProcs); */ /* if (nGlobalEdges < totalNumEdges){ */ /* /\* re-assign edge global numbers if any edges were removed *\/ */ /* ierr = Zoltan_PHG_GIDs_to_global_numbers(zz, edgeGNO, nLocalEdges, */ /* randomizeInitDist, &totalNumEdges); */ /* if (ierr != ZOLTAN_OK && ierr != ZOLTAN_WARN) { */ /* ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error reassigning global numbers to edges"); */ /* goto End; */ /* } */ /* } */ /* We have to define ddY : yGNO, yGID, ywgt */ ierr = Zoltan_DD_Create (&matrix->ddY, zz->Communicator, gno_size_for_dd, zz->Num_GID, 0, matrix->globalY/zz->Num_Proc, 0); /* Hope a linear assignment will help a little */ if (matrix->globalY/zz->Num_Proc) Zoltan_DD_Set_Neighbor_Hash_Fn1(matrix->ddY, matrix->globalY/zz->Num_Proc); /* Associate all the data with our yGNO */ Zoltan_DD_Update (matrix->ddY, (ZOLTAN_ID_PTR)matrix->yGNO, yGID, NULL, NULL, matrix->nY); } End: ZOLTAN_FREE(&xpid); ZOLTAN_FREE(&xLID); ZOLTAN_FREE(&xGNO); ZOLTAN_FREE(&xGID); ZOLTAN_FREE(&xwgt); ZOLTAN_FREE(&Input_Parts); ZOLTAN_FREE(&proclist); if (dd != NULL) Zoltan_DD_Destroy(&dd); /* Already stored in the DD */ ZOLTAN_FREE(&yGID); ZOLTAN_TRACE_EXIT(zz, yo); return (ierr); }