int hypre_SStructUMatrixInitialize( hypre_SStructMatrix *matrix ) { HYPRE_IJMatrix ijmatrix = hypre_SStructMatrixIJMatrix(matrix); hypre_SStructGraph *graph = hypre_SStructMatrixGraph(matrix); hypre_SStructGrid *grid = hypre_SStructGraphGrid(graph); int nparts = hypre_SStructGraphNParts(graph); hypre_SStructPGrid **pgrids = hypre_SStructGraphPGrids(graph); hypre_SStructStencil ***stencils = hypre_SStructGraphStencils(graph); int nUventries = hypre_SStructGraphNUVEntries(graph); int *iUventries = hypre_SStructGraphIUVEntries(graph); hypre_SStructUVEntry **Uventries = hypre_SStructGraphUVEntries(graph); int **nvneighbors = hypre_SStructGridNVNeighbors(grid); hypre_StructGrid *sgrid; hypre_SStructStencil *stencil; int *split; int nvars; int nrows, nnzs ; int part, var, entry, i, j, k,m,b; int *row_sizes; int max_row_size; int matrix_type = hypre_SStructMatrixObjectType(matrix); hypre_Box *gridbox; hypre_Box *loopbox; hypre_Box *ghostbox; hypre_BoxArray *boxes; int *num_ghost; HYPRE_IJMatrixSetObjectType(ijmatrix, HYPRE_PARCSR); /* GEC1002 the ghlocalsize is used to set the number of rows */ if (matrix_type == HYPRE_PARCSR) { nrows = hypre_SStructGridLocalSize(grid); } if (matrix_type == HYPRE_SSTRUCT || matrix_type == HYPRE_STRUCT) { nrows = hypre_SStructGridGhlocalSize(grid) ; } /* set row sizes */ m = 0; row_sizes = hypre_CTAlloc(int, nrows); max_row_size = 0; for (part = 0; part < nparts; part++) { nvars = hypre_SStructPGridNVars(pgrids[part]); for (var = 0; var < nvars; var++) { sgrid = hypre_SStructPGridSGrid(pgrids[part], var); stencil = stencils[part][var]; split = hypre_SStructMatrixSplit(matrix, part, var); nnzs = 0; for (entry = 0; entry < hypre_SStructStencilSize(stencil); entry++) { if (split[entry] == -1) { nnzs++; } } #if 0 /* TODO: For now, assume stencil is full/complete */ if (hypre_SStructMatrixSymmetric(matrix)) { nnzs = 2*nnzs - 1; } #endif /**************/ boxes = hypre_StructGridBoxes(sgrid) ; num_ghost = hypre_StructGridNumGhost(sgrid); for (b = 0; b < hypre_BoxArraySize(boxes); b++) { gridbox = hypre_BoxArrayBox(boxes, b); ghostbox = hypre_BoxCreate(); loopbox = hypre_BoxCreate(); hypre_CopyBox(gridbox,ghostbox); hypre_BoxExpand(ghostbox,num_ghost); if (matrix_type == HYPRE_SSTRUCT || matrix_type == HYPRE_STRUCT) { hypre_CopyBox(ghostbox,loopbox); } if (matrix_type == HYPRE_PARCSR) { hypre_CopyBox(gridbox,loopbox); } for (k = hypre_BoxIMinZ(loopbox); k <= hypre_BoxIMaxZ(loopbox); k++) { for (j = hypre_BoxIMinY(loopbox); j <= hypre_BoxIMaxY(loopbox); j++) { for (i = hypre_BoxIMinX(loopbox); i <= hypre_BoxIMaxX(loopbox); i++) { if ( ( ( i>=hypre_BoxIMinX(gridbox) ) && ( j>=hypre_BoxIMinY(gridbox) ) ) && ( k>=hypre_BoxIMinZ(gridbox) ) ) { if ( ( ( i<=hypre_BoxIMaxX(gridbox) ) && ( j<=hypre_BoxIMaxY(gridbox) ) ) && ( k<=hypre_BoxIMaxZ(gridbox) ) ) { row_sizes[m] = nnzs; max_row_size = hypre_max(max_row_size, row_sizes[m]); } } m++; } } } hypre_BoxDestroy(ghostbox); hypre_BoxDestroy(loopbox); } if (nvneighbors[part][var]) { max_row_size = hypre_max(max_row_size, hypre_SStructStencilSize(stencil)); } /*********************/ } } /* GEC0902 essentially for each UVentry we figure out how many extra columns * we need to add to the rowsizes */ for (entry = 0; entry < nUventries; entry++) { i = iUventries[entry]; row_sizes[i] += hypre_SStructUVEntryNUEntries(Uventries[i]); max_row_size = hypre_max(max_row_size, row_sizes[i]); } /* ZTODO: Update row_sizes based on neighbor off-part couplings */ HYPRE_IJMatrixSetRowSizes (ijmatrix, (const int *) row_sizes); hypre_TFree(row_sizes); hypre_SStructMatrixTmpColCoords(matrix) = hypre_CTAlloc(HYPRE_BigInt, max_row_size); hypre_SStructMatrixTmpCoeffs(matrix) = hypre_CTAlloc(double, max_row_size); /* GEC1002 at this point the processor has the partitioning (creation of ij) */ HYPRE_IJMatrixInitialize(ijmatrix); return hypre_error_flag; }
int hypre_SStructUMatrixSetBoxValues( hypre_SStructMatrix *matrix, int part, hypre_Index ilower, hypre_Index iupper, int var, int nentries, int *entries, double *values, int add_to ) { HYPRE_IJMatrix ijmatrix = hypre_SStructMatrixIJMatrix(matrix); hypre_SStructGraph *graph = hypre_SStructMatrixGraph(matrix); hypre_SStructGrid *grid = hypre_SStructGraphGrid(graph); hypre_SStructStencil *stencil = hypre_SStructGraphStencil(graph, part, var); int *vars = hypre_SStructStencilVars(stencil); hypre_Index *shape = hypre_SStructStencilShape(stencil); int size = hypre_SStructStencilSize(stencil); hypre_IndexRef offset; hypre_BoxMap *map; hypre_BoxMapEntry **map_entries; int nmap_entries; hypre_BoxMapEntry **map_to_entries; int nmap_to_entries; int nrows; int *ncols; HYPRE_BigInt *rows; HYPRE_BigInt *cols; double *ijvalues; hypre_Box *box; hypre_Box *to_box; hypre_Box *map_box; hypre_Box *int_box; hypre_Index index; hypre_Index rs, cs; int sy, sz; HYPRE_BigInt row_base, col_base; int val_base; int e, entry, ii, jj, i, j, k; int proc, myproc; /* GEC1002 the matrix type */ int matrix_type = hypre_SStructMatrixObjectType(matrix); box = hypre_BoxCreate(); /*------------------------------------------ * all stencil entries *------------------------------------------*/ if (entries[0] < size) { to_box = hypre_BoxCreate(); map_box = hypre_BoxCreate(); int_box = hypre_BoxCreate(); hypre_CopyIndex(ilower, hypre_BoxIMin(box)); hypre_CopyIndex(iupper, hypre_BoxIMax(box)); /* ZTODO: check that this change fixes multiple-entry problem */ nrows = hypre_BoxVolume(box)*nentries; ncols = hypre_CTAlloc(int, nrows); for (i = 0; i < nrows; i++) { ncols[i] = 1; } rows = hypre_CTAlloc(HYPRE_BigInt, nrows); cols = hypre_CTAlloc(HYPRE_BigInt, nrows); ijvalues = hypre_CTAlloc(double, nrows); sy = (hypre_IndexX(iupper) - hypre_IndexX(ilower) + 1); sz = (hypre_IndexY(iupper) - hypre_IndexY(ilower) + 1) * sy; map = hypre_SStructGridMap(grid, part, var); hypre_BoxMapIntersect(map, ilower, iupper, &map_entries, &nmap_entries); for (ii = 0; ii < nmap_entries; ii++) { /* Only Set values if I am the owner process; off-process AddTo and Get * values are done by IJ */ if (!add_to) { hypre_SStructMapEntryGetProcess(map_entries[ii], &proc); MPI_Comm_rank(hypre_SStructGridComm(grid), &myproc); if (proc != myproc) { continue; } } /* GEC1002 introducing the strides based on the type of the matrix */ hypre_SStructMapEntryGetStrides(map_entries[ii], rs, matrix_type); hypre_CopyIndex(ilower, hypre_BoxIMin(box)); hypre_CopyIndex(iupper, hypre_BoxIMax(box)); hypre_BoxMapEntryGetExtents(map_entries[ii], hypre_BoxIMin(map_box), hypre_BoxIMax(map_box)); hypre_IntersectBoxes(box, map_box, int_box); hypre_CopyBox(int_box, box); nrows = 0; for (e = 0; e < nentries; e++) { entry = entries[e]; hypre_CopyBox(box, to_box); offset = shape[entry]; hypre_BoxIMinX(to_box) += hypre_IndexX(offset); hypre_BoxIMinY(to_box) += hypre_IndexY(offset); hypre_BoxIMinZ(to_box) += hypre_IndexZ(offset); hypre_BoxIMaxX(to_box) += hypre_IndexX(offset); hypre_BoxIMaxY(to_box) += hypre_IndexY(offset); hypre_BoxIMaxZ(to_box) += hypre_IndexZ(offset); map = hypre_SStructGridMap(grid, part, vars[entry]); hypre_BoxMapIntersect(map, hypre_BoxIMin(to_box), hypre_BoxIMax(to_box), &map_to_entries, &nmap_to_entries ); for (jj = 0; jj < nmap_to_entries; jj++) { /* GEC1002 introducing the strides based on the type of the matrix */ hypre_SStructMapEntryGetStrides(map_to_entries[jj], cs, matrix_type); hypre_BoxMapEntryGetExtents(map_to_entries[jj], hypre_BoxIMin(map_box), hypre_BoxIMax(map_box)); hypre_IntersectBoxes(to_box, map_box, int_box); hypre_CopyIndex(hypre_BoxIMin(int_box), index); /* GEC1002 introducing the rank based on the type of the matrix */ hypre_SStructMapEntryGetGlobalRank(map_to_entries[jj], index, &col_base,matrix_type); hypre_IndexX(index) -= hypre_IndexX(offset); hypre_IndexY(index) -= hypre_IndexY(offset); hypre_IndexZ(index) -= hypre_IndexZ(offset); /* GEC1002 introducing the rank based on the type of the matrix */ hypre_SStructMapEntryGetGlobalRank(map_entries[ii], index, &row_base,matrix_type); hypre_IndexX(index) -= hypre_IndexX(ilower); hypre_IndexY(index) -= hypre_IndexY(ilower); hypre_IndexZ(index) -= hypre_IndexZ(ilower); val_base = e + (hypre_IndexX(index) + hypre_IndexY(index)*sy + hypre_IndexZ(index)*sz) * nentries; for (k = 0; k < hypre_BoxSizeZ(int_box); k++) { for (j = 0; j < hypre_BoxSizeY(int_box); j++) { for (i = 0; i < hypre_BoxSizeX(int_box); i++) { rows[nrows] = row_base + (HYPRE_BigInt)(i*rs[0] + j*rs[1] + k*rs[2]); cols[nrows] = col_base + (HYPRE_BigInt)(i*cs[0] + j*cs[1] + k*cs[2]); ijvalues[nrows] = values[val_base + (i + j*sy + k*sz)*nentries]; nrows++; } } } } hypre_TFree(map_to_entries); } /*------------------------------------------ * set IJ values one stencil entry at a time *------------------------------------------*/ if (add_to > 0) { HYPRE_IJMatrixAddToValues(ijmatrix, nrows, ncols, (const HYPRE_BigInt *) rows, (const HYPRE_BigInt *) cols, (const double *) ijvalues); } else if (add_to > -1) { HYPRE_IJMatrixSetValues(ijmatrix, nrows, ncols, (const HYPRE_BigInt *) rows, (const HYPRE_BigInt *) cols, (const double *) ijvalues); } else { HYPRE_IJMatrixGetValues(ijmatrix, nrows, ncols, rows, cols, values); } } hypre_TFree(map_entries); hypre_TFree(ncols); hypre_TFree(rows); hypre_TFree(cols); hypre_TFree(ijvalues); hypre_BoxDestroy(to_box); hypre_BoxDestroy(map_box); hypre_BoxDestroy(int_box); }
int hypre_StructCoarsen( hypre_StructGrid *fgrid, hypre_Index index, hypre_Index stride, int prune, hypre_StructGrid **cgrid_ptr ) { int ierr = 0; hypre_StructGrid *cgrid; MPI_Comm comm; int dim; hypre_BoxNeighbors *neighbors; hypre_BoxArray *hood_boxes; int num_hood; int *hood_procs; int *hood_ids; int first_local; int num_local; int num_periodic; int max_distance; hypre_Box *bounding_box; hypre_Index periodic; MPI_Request *send_requests; MPI_Status *send_status; int *send_buffer; int send_size; MPI_Request *recv_requests; MPI_Status *recv_status; int **recv_buffers; int *recv_sizes; int my_rank; int *send_procs; int *recv_procs; int num_sends; int num_recvs; hypre_BoxArray *new_hood_boxes; int new_num_hood; int *new_hood_procs; int *new_hood_ids; int new_first_local; int new_num_local; int new_num_periodic; hypre_Box *box; hypre_Box *local_box; hypre_Box *neighbor_box; hypre_Box *local_cbox; hypre_Box *neighbor_cbox; hypre_Index imin; hypre_Index imax; int alloc_size; double perimeter_count, cperimeter_count; /*double diff, distance, perimeter_count, cperimeter_count;*/ int *iarray; int *jrecv; int i, j, d, ilocal; int data_id, min_id, jj; /*----------------------------------------- * Copy needed info from fgrid *-----------------------------------------*/ comm = hypre_StructGridComm(fgrid); dim = hypre_StructGridDim(fgrid); neighbors = hypre_StructGridNeighbors(fgrid); hood_boxes = hypre_BoxArrayDuplicate(hypre_BoxNeighborsBoxes(neighbors)); num_hood = hypre_BoxArraySize(hood_boxes); iarray = hypre_BoxNeighborsProcs(neighbors); hood_procs = hypre_TAlloc(int, num_hood); for (i = 0; i < num_hood; i++) { hood_procs[i] = iarray[i]; } iarray = hypre_BoxNeighborsIDs(neighbors); hood_ids = hypre_TAlloc(int, num_hood); for (i = 0; i < num_hood; i++) { hood_ids[i] = iarray[i]; } first_local = hypre_BoxNeighborsFirstLocal(neighbors); num_local = hypre_BoxNeighborsNumLocal(neighbors); num_periodic = hypre_BoxNeighborsNumPeriodic(neighbors); max_distance = hypre_StructGridMaxDistance(fgrid); bounding_box = hypre_BoxDuplicate(hypre_StructGridBoundingBox(fgrid)); hypre_CopyIndex(hypre_StructGridPeriodic(fgrid), periodic); MPI_Comm_rank(comm, &my_rank); #if DEBUG sprintf(filename, "zcoarsen.%05d", my_rank); if ((file = fopen(filename, "a")) == NULL) { printf("Error: can't open output file %s\n", filename); exit(1); } fprintf(file, "\n\n============================\n\n"); fprintf(file, "\n\n%d\n\n", debug_count++); fprintf(file, "num_hood = %d\n", num_hood); for (i = 0; i < num_hood; i++) { box = hypre_BoxArrayBox(hood_boxes, i); fprintf(file, "(%d,%d,%d) X (%d,%d,%d) ; (%d,%d); %d\n", hypre_BoxIMinX(box),hypre_BoxIMinY(box),hypre_BoxIMinZ(box), hypre_BoxIMaxX(box),hypre_BoxIMaxY(box),hypre_BoxIMaxZ(box), hood_procs[i], hood_ids[i], hypre_BoxVolume(box)); } fprintf(file, "first_local = %d\n", first_local); fprintf(file, "num_local = %d\n", num_local); fprintf(file, "num_periodic = %d\n", num_periodic); #endif /*----------------------------------------- * Coarsen bounding box *-----------------------------------------*/ hypre_StructCoarsenBox(bounding_box, index, stride); /*----------------------------------------- * Coarsen neighborhood boxes & determine * send / recv procs * * NOTE: Currently, this always communicates * with all neighboring processes. *-----------------------------------------*/ local_cbox = hypre_BoxCreate(); neighbor_cbox = hypre_BoxCreate(); num_recvs = 0; num_sends = 0; recv_procs = NULL; send_procs = NULL; for (i = 0; i < num_hood; i++) { if (hood_procs[i] != my_rank) { for (j = 0; j < num_local; j++) { ilocal = first_local + j; local_box = hypre_BoxArrayBox(hood_boxes, ilocal); neighbor_box = hypre_BoxArrayBox(hood_boxes, i); /* coarsen boxes being considered */ hypre_CopyBox(local_box, local_cbox); hypre_StructCoarsenBox(local_cbox, index, stride); hypre_CopyBox(neighbor_box, neighbor_cbox); hypre_StructCoarsenBox(neighbor_cbox, index, stride); /*----------------------- * Receive info? *-----------------------*/ /* always communicate */ #if 0 perimeter_count = 0; cperimeter_count = 0; for (d = 0; d < 3; d++) { distance = max_distance; diff = hypre_BoxIMaxD(neighbor_box, d) - hypre_BoxIMaxD(local_box, d); if (diff > 0) { distance = hypre_min(distance, diff); } diff = hypre_BoxIMinD(local_box, d) - hypre_BoxIMinD(neighbor_box, d); if (diff > 0) { distance = hypre_min(distance, diff); } if (distance < max_distance) { perimeter_count++; } distance = max_distance; diff = hypre_BoxIMaxD(neighbor_cbox, d) - hypre_BoxIMaxD(local_cbox, d); if (diff > 0) { distance = hypre_min(distance, diff); } diff = hypre_BoxIMinD(local_cbox, d) - hypre_BoxIMinD(neighbor_cbox, d); if (diff > 0) { distance = hypre_min(distance, diff); } if (distance < max_distance) { cperimeter_count++; } } #else perimeter_count = 0; cperimeter_count = 1; #endif if (cperimeter_count > perimeter_count) { if (num_recvs == 0) { recv_procs = hypre_TAlloc(int, num_hood); recv_procs[num_recvs] = hood_procs[i]; num_recvs++; } else if (hood_procs[i] != recv_procs[num_recvs-1]) { recv_procs[num_recvs] = hood_procs[i]; num_recvs++; } } /*----------------------- * Send info? *-----------------------*/ /* always communicate */ #if 0 perimeter_count = 0; cperimeter_count = 0; for (d = 0; d < 3; d++) { distance = max_distance; diff = hypre_BoxIMaxD(local_box, d) - hypre_BoxIMaxD(neighbor_box, d); if (diff > 0) { distance = hypre_min(distance, diff); } diff = hypre_BoxIMinD(neighbor_box, d) - hypre_BoxIMinD(local_box, d); if (diff > 0) { distance = hypre_min(distance, diff); } if (distance < max_distance) { perimeter_count++; } distance = max_distance; diff = hypre_BoxIMaxD(local_cbox, d) - hypre_BoxIMaxD(neighbor_cbox, d); if (diff > 0) { distance = hypre_min(distance, diff); } diff = hypre_BoxIMinD(neighbor_cbox, d) - hypre_BoxIMinD(local_cbox, d); if (diff > 0) { distance = hypre_min(distance, diff); } if (distance < max_distance) { cperimeter_count++; } } #else perimeter_count = 0; cperimeter_count = 1; #endif if (cperimeter_count > perimeter_count) { if (num_sends == 0) { send_procs = hypre_TAlloc(int, num_hood); send_procs[num_sends] = hood_procs[i]; num_sends++; } else if (hood_procs[i] != send_procs[num_sends-1]) { send_procs[num_sends] = hood_procs[i]; num_sends++; } }