int HYPRE_SStructGraphCreate( MPI_Comm comm, HYPRE_SStructGrid grid, HYPRE_SStructGraph *graph_ptr ) { int ierr = 0; hypre_SStructGraph *graph; int nparts; hypre_SStructStencil ***stencils; hypre_SStructPGrid **pgrids; int nvars; int part, var; graph = hypre_TAlloc(hypre_SStructGraph, 1); hypre_SStructGraphComm(graph) = comm; hypre_SStructGraphNDim(graph) = hypre_SStructGridNDim(grid); hypre_SStructGridRef(grid, &hypre_SStructGraphGrid(graph)); nparts = hypre_SStructGridNParts(grid); hypre_SStructGraphNParts(graph) = nparts; pgrids = hypre_SStructGridPGrids(grid); hypre_SStructGraphPGrids(graph) = pgrids; stencils = hypre_TAlloc(hypre_SStructStencil **, nparts); for (part = 0; part < nparts; part++) { nvars = hypre_SStructPGridNVars(pgrids[part]); stencils[part] = hypre_TAlloc(hypre_SStructStencil *, nvars); for (var = 0; var < nvars; var++) { stencils[part][var] = NULL; } } hypre_SStructGraphStencils(graph) = stencils; hypre_SStructGraphNUVEntries(graph) = 0; hypre_SStructGraphAUVEntries(graph) = 0; hypre_SStructGraphIUVEntries(graph) = NULL; hypre_SStructGraphUVEntries(graph) = NULL; hypre_SStructGraphTotUEntries(graph) = 0; hypre_SStructGraphRefCount(graph) = 1; hypre_SStructGraphObjectType(graph) = HYPRE_SSTRUCT; *graph_ptr = graph; return ierr; }
HYPRE_Int HYPRE_SStructGridDestroy( HYPRE_SStructGrid grid ) { HYPRE_Int nparts; hypre_SStructPGrid **pgrids; HYPRE_Int *nneighbors; hypre_SStructNeighbor **neighbors; hypre_Index **nbor_offsets; HYPRE_Int **nvneighbors; hypre_SStructNeighbor ***vneighbors; hypre_SStructCommInfo **vnbor_comm_info; HYPRE_Int vnbor_ncomms; HYPRE_Int *fem_nvars; HYPRE_Int **fem_vars; hypre_Index **fem_offsets; hypre_BoxManager ***managers; hypre_BoxManager ***nbor_managers; HYPRE_Int nvars; HYPRE_Int part, var, i; if (grid) { hypre_SStructGridRefCount(grid) --; if (hypre_SStructGridRefCount(grid) == 0) { nparts = hypre_SStructGridNParts(grid); pgrids = hypre_SStructGridPGrids(grid); nneighbors = hypre_SStructGridNNeighbors(grid); neighbors = hypre_SStructGridNeighbors(grid); nbor_offsets = hypre_SStructGridNborOffsets(grid); nvneighbors = hypre_SStructGridNVNeighbors(grid); vneighbors = hypre_SStructGridVNeighbors(grid); vnbor_comm_info = hypre_SStructGridVNborCommInfo(grid); vnbor_ncomms = hypre_SStructGridVNborNComms(grid); fem_nvars = hypre_SStructGridFEMNVars(grid); fem_vars = hypre_SStructGridFEMVars(grid); fem_offsets = hypre_SStructGridFEMOffsets(grid); managers = hypre_SStructGridBoxManagers(grid); nbor_managers = hypre_SStructGridNborBoxManagers(grid); for (part = 0; part < nparts; part++) { nvars = hypre_SStructPGridNVars(pgrids[part]); for (var = 0; var < nvars; var++) { hypre_TFree(vneighbors[part][var]); hypre_BoxManDestroy(managers[part][var]); hypre_BoxManDestroy(nbor_managers[part][var]); } hypre_TFree(neighbors[part]); hypre_TFree(nbor_offsets[part]); hypre_TFree(nvneighbors[part]); hypre_TFree(vneighbors[part]); hypre_SStructPGridDestroy(pgrids[part]); hypre_TFree(fem_vars[part]); hypre_TFree(fem_offsets[part]); hypre_TFree(managers[part]); hypre_TFree(nbor_managers[part]); } for (i = 0; i < vnbor_ncomms; i++) { hypre_CommInfoDestroy( hypre_SStructCommInfoCommInfo(vnbor_comm_info[i])); hypre_TFree(vnbor_comm_info[i]); } hypre_TFree(vnbor_comm_info); hypre_TFree(pgrids); hypre_TFree(nneighbors); hypre_TFree(neighbors); hypre_TFree(nbor_offsets); hypre_TFree(fem_nvars); hypre_TFree(fem_vars); hypre_TFree(fem_offsets); hypre_TFree(nvneighbors); hypre_TFree(vneighbors); hypre_TFree(vnbor_comm_info); hypre_TFree(managers); hypre_TFree(nbor_managers); hypre_TFree(grid); } } return hypre_error_flag; }
HYPRE_Int HYPRE_SStructGridCreate( MPI_Comm comm, HYPRE_Int ndim, HYPRE_Int nparts, HYPRE_SStructGrid *grid_ptr ) { hypre_SStructGrid *grid; hypre_SStructPGrid **pgrids; hypre_SStructPGrid *pgrid; HYPRE_Int *nneighbors; hypre_SStructNeighbor **neighbors; hypre_Index **nbor_offsets; HYPRE_Int *fem_nvars; HYPRE_Int **fem_vars; hypre_Index **fem_offsets; HYPRE_Int i; grid = hypre_TAlloc(hypre_SStructGrid, 1); hypre_SStructGridComm(grid) = comm; hypre_SStructGridNDim(grid) = ndim; hypre_SStructGridNParts(grid) = nparts; pgrids = hypre_TAlloc(hypre_SStructPGrid *, nparts); nneighbors = hypre_TAlloc(HYPRE_Int, nparts); neighbors = hypre_TAlloc(hypre_SStructNeighbor *, nparts); nbor_offsets = hypre_TAlloc(hypre_Index *, nparts); fem_nvars = hypre_TAlloc(HYPRE_Int, nparts); fem_vars = hypre_TAlloc(HYPRE_Int *, nparts); fem_offsets = hypre_TAlloc(hypre_Index *, nparts); for (i = 0; i < nparts; i++) { hypre_SStructPGridCreate(comm, ndim, &pgrid); pgrids[i] = pgrid; nneighbors[i] = 0; neighbors[i] = NULL; nbor_offsets[i] = NULL; fem_nvars[i] = 0; fem_vars[i] = NULL; fem_offsets[i] = NULL; } hypre_SStructGridPGrids(grid) = pgrids; hypre_SStructGridNNeighbors(grid) = nneighbors; hypre_SStructGridNeighbors(grid) = neighbors; hypre_SStructGridNborOffsets(grid) = nbor_offsets; hypre_SStructGridNUCVars(grid) = 0; hypre_SStructGridUCVars(grid) = NULL; hypre_SStructGridFEMNVars(grid) = fem_nvars; hypre_SStructGridFEMVars(grid) = fem_vars; hypre_SStructGridFEMOffsets(grid) = fem_offsets; hypre_SStructGridBoxManagers(grid) = NULL; hypre_SStructGridNborBoxManagers(grid) = NULL; /* miscellaneous */ hypre_SStructGridLocalSize(grid) = 0; hypre_SStructGridGlobalSize(grid) = 0; hypre_SStructGridRefCount(grid) = 1; /* GEC0902 ghost addition to the grid */ hypre_SStructGridGhlocalSize(grid) = 0; *grid_ptr = grid; return hypre_error_flag; }
/*-------------------------------------------------------------------------- * hypre_SStructSharedDOF_ParcsrMatRowsComm * Given a sstruct_grid & parcsr matrix with rows corresponding to the * sstruct_grid, determine and extract the rows that must be communicated. * These rows are for shared dof that geometrically lie on processor * boundaries but internally are stored on one processor. * Algo: * for each cellbox * RECVs: * i) stretch the cellbox to the variable box * ii) in the appropriate (dof-dependent) direction, take the * boundary and boxman_intersect to extract boxmanentries * that contain these boundary edges. * iii)loop over the boxmanentries and see if they belong * on this proc or another proc * a) if belong on another proc, these are the recvs: * count and prepare the communication buffers and * values. * * SENDs: * i) form layer of cells that is one layer off cellbox * (stretches in the appropriate direction) * ii) boxman_intersect with the cellgrid boxman * iii)loop over the boxmanentries and see if they belong * on this proc or another proc * a) if belong on another proc, these are the sends: * count and prepare the communication buffers and * values. * * Note: For the recv data, the dof can come from only one processor. * For the send data, the dof can go to more than one processor * (the same dof is on the boundary of several cells). *--------------------------------------------------------------------------*/ HYPRE_Int hypre_SStructSharedDOF_ParcsrMatRowsComm( hypre_SStructGrid *grid, hypre_ParCSRMatrix *A, HYPRE_Int *num_offprocrows_ptr, hypre_MaxwellOffProcRow ***OffProcRows_ptr) { MPI_Comm A_comm= hypre_ParCSRMatrixComm(A); MPI_Comm grid_comm= hypre_SStructGridComm(grid); HYPRE_Int matrix_type= HYPRE_PARCSR; HYPRE_Int nparts= hypre_SStructGridNParts(grid); HYPRE_Int ndim = hypre_SStructGridNDim(grid); hypre_SStructGrid *cell_ssgrid; hypre_SStructPGrid *pgrid; hypre_StructGrid *cellgrid; hypre_BoxArray *cellboxes; hypre_Box *box, *cellbox, vbox, boxman_entry_box; hypre_Index loop_size, start; HYPRE_Int loopi, loopj, loopk; HYPRE_Int start_rank, end_rank, rank; HYPRE_Int i, j, k, m, n, t, part, var, nvars; HYPRE_SStructVariable *vartypes; HYPRE_Int nbdry_slabs; hypre_BoxArray *recv_slabs, *send_slabs; hypre_Index varoffset; hypre_BoxManager **boxmans, *cell_boxman; hypre_BoxManEntry **boxman_entries, *entry; HYPRE_Int nboxman_entries; hypre_Index ishift, jshift, kshift, zero_index; hypre_Index ilower, iupper, index; HYPRE_Int proc, nprocs, myproc; HYPRE_Int *SendToProcs, *RecvFromProcs; HYPRE_Int **send_RowsNcols; /* buffer for rows & ncols */ HYPRE_Int *send_RowsNcols_alloc; HYPRE_Int *send_ColsData_alloc; HYPRE_Int *tot_nsendRowsNcols, *tot_sendColsData; double **vals; /* buffer for cols & data */ HYPRE_Int *col_inds; double *values; hypre_MPI_Request *requests; hypre_MPI_Status *status; HYPRE_Int **rbuffer_RowsNcols; double **rbuffer_ColsData; HYPRE_Int num_sends, num_recvs; hypre_MaxwellOffProcRow **OffProcRows; HYPRE_Int *starts; HYPRE_Int ierr= 0; hypre_MPI_Comm_rank(A_comm, &myproc); hypre_MPI_Comm_size(grid_comm, &nprocs); start_rank= hypre_ParCSRMatrixFirstRowIndex(A); end_rank = hypre_ParCSRMatrixLastRowIndex(A); hypre_SetIndex(ishift, 1, 0, 0); hypre_SetIndex(jshift, 0, 1, 0); hypre_SetIndex(kshift, 0, 0, 1); hypre_SetIndex(zero_index, 0, 0, 0); /* need a cellgrid boxman to determine the send boxes -> only the cell dofs are unique so a boxman intersect can be used to get the edges that must be sent. */ HYPRE_SStructGridCreate(grid_comm, ndim, nparts, &cell_ssgrid); vartypes= hypre_CTAlloc(HYPRE_SStructVariable, 1); vartypes[0]= HYPRE_SSTRUCT_VARIABLE_CELL; for (i= 0; i< nparts; i++) { pgrid= hypre_SStructGridPGrid(grid, i); cellgrid= hypre_SStructPGridCellSGrid(pgrid); cellboxes= hypre_StructGridBoxes(cellgrid); hypre_ForBoxI(j, cellboxes) { box= hypre_BoxArrayBox(cellboxes, j); HYPRE_SStructGridSetExtents(cell_ssgrid, i, hypre_BoxIMin(box), hypre_BoxIMax(box)); } HYPRE_SStructGridSetVariables(cell_ssgrid, i, 1, vartypes); }
/*-------------------------------------------------------------------------- * hypre_Maxwell_Grad.c * Forms a node-to-edge gradient operator. Looping over the * edge grid so that each processor fills up only its own rows. Each * processor will have its processor interface nodal ranks. * Loops over two types of boxes, interior of grid boxes and boundary * of boxes. Algo: * find all nodal and edge physical boundary points and set * the appropriate flag to be 0 at a boundary dof. * set -1's in value array * for each edge box, * for interior * { * connect edge ijk (row) to nodes (col) connected to this edge * and change -1 to 1 if needed; * } * for boundary layers * { * if edge not on the physical boundary connect only the nodes * that are not on the physical boundary * } * set parcsr matrix with values; * * Note that the nodes that are on the processor interface can be * on the physical boundary. But the off-proc edges connected to this * type of node will be a physical boundary edge. * *--------------------------------------------------------------------------*/ hypre_ParCSRMatrix * hypre_Maxwell_Grad(hypre_SStructGrid *grid) { MPI_Comm comm = (grid -> comm); HYPRE_IJMatrix T_grad; hypre_ParCSRMatrix *parcsr_grad; HYPRE_Int matrix_type= HYPRE_PARCSR; hypre_SStructGrid *node_grid, *edge_grid; hypre_SStructPGrid *pgrid; hypre_StructGrid *var_grid; hypre_BoxArray *boxes, *tmp_box_array1, *tmp_box_array2; hypre_BoxArray *node_boxes, *edge_boxes, *cell_boxes; hypre_Box *box, *cell_box; hypre_Box layer, interior_box; hypre_Box *box_piece; hypre_BoxManager *boxman; hypre_BoxManEntry *entry; HYPRE_Int *inode, *jedge; HYPRE_Int nrows, nnodes, *nflag, *eflag, *ncols; HYPRE_Real *vals; hypre_Index index; hypre_Index loop_size, start, lindex; hypre_Index shift, shift2; hypre_Index *offsets, *varoffsets; HYPRE_Int nparts= hypre_SStructGridNParts(grid); HYPRE_Int ndim = hypre_SStructGridNDim(grid); HYPRE_SStructVariable vartype_node, *vartype_edges; HYPRE_SStructVariable *vartypes; HYPRE_Int nvars, part; HYPRE_Int i, j, k, m, n, d; HYPRE_Int *direction, ndirection; HYPRE_Int ilower, iupper; HYPRE_Int jlower, jupper; HYPRE_Int start_rank1, start_rank2, rank; HYPRE_Int myproc; HYPRE_Int ierr=0; hypre_BoxInit(&layer, ndim); hypre_BoxInit(&interior_box, ndim); hypre_MPI_Comm_rank(comm, &myproc); hypre_ClearIndex(shift); for (i= 0; i< ndim; i++) { hypre_IndexD(shift, i)= -1; } /* To get the correct ranks, separate node & edge grids must be formed. Note that the edge vars must be ordered the same way as is in grid.*/ HYPRE_SStructGridCreate(comm, ndim, nparts, &node_grid); HYPRE_SStructGridCreate(comm, ndim, nparts, &edge_grid); vartype_node = HYPRE_SSTRUCT_VARIABLE_NODE; vartype_edges= hypre_TAlloc(HYPRE_SStructVariable, ndim); /* Assuming the same edge variable types on all parts */ pgrid = hypre_SStructGridPGrid(grid, 0); vartypes= hypre_SStructPGridVarTypes(pgrid); nvars = hypre_SStructPGridNVars(pgrid); k= 0; for (i= 0; i< nvars; i++) { j= vartypes[i]; switch(j) { case 2: { vartype_edges[k]= HYPRE_SSTRUCT_VARIABLE_XFACE; k++; break; } case 3: { vartype_edges[k]= HYPRE_SSTRUCT_VARIABLE_YFACE; k++; break; } case 5: { vartype_edges[k]= HYPRE_SSTRUCT_VARIABLE_XEDGE; k++; break; } case 6: { vartype_edges[k]= HYPRE_SSTRUCT_VARIABLE_YEDGE; k++; break; } case 7: { vartype_edges[k]= HYPRE_SSTRUCT_VARIABLE_ZEDGE; k++; break; } } /* switch(j) */ } /* for (i= 0; i< nvars; i++) */ for (part= 0; part< nparts; part++) { pgrid= hypre_SStructGridPGrid(grid, part); var_grid= hypre_SStructPGridCellSGrid(pgrid) ; boxes= hypre_StructGridBoxes(var_grid); hypre_ForBoxI(j, boxes) { box= hypre_BoxArrayBox(boxes, j); HYPRE_SStructGridSetExtents(node_grid, part, hypre_BoxIMin(box), hypre_BoxIMax(box)); HYPRE_SStructGridSetExtents(edge_grid, part, hypre_BoxIMin(box), hypre_BoxIMax(box)); } HYPRE_SStructGridSetVariables(node_grid, part, 1, &vartype_node); HYPRE_SStructGridSetVariables(edge_grid, part, ndim, vartype_edges); }
HYPRE_Int HYPRE_SStructGraphCreate( MPI_Comm comm, HYPRE_SStructGrid grid, HYPRE_SStructGraph *graph_ptr ) { hypre_SStructGraph *graph; HYPRE_Int nparts; hypre_SStructStencil ***stencils; hypre_SStructPGrid **pgrids; HYPRE_Int *fem_nsparse; HYPRE_Int **fem_sparse_i; HYPRE_Int **fem_sparse_j; HYPRE_Int **fem_entries; HYPRE_Int nvars; HYPRE_Int part, var; graph = hypre_TAlloc(hypre_SStructGraph, 1); hypre_SStructGraphComm(graph) = comm; hypre_SStructGraphNDim(graph) = hypre_SStructGridNDim(grid); hypre_SStructGridRef(grid, &hypre_SStructGraphGrid(graph)); hypre_SStructGridRef(grid, &hypre_SStructGraphDomainGrid(graph)); nparts = hypre_SStructGridNParts(grid); hypre_SStructGraphNParts(graph) = nparts; pgrids = hypre_SStructGridPGrids(grid); stencils = hypre_TAlloc(hypre_SStructStencil **, nparts); fem_nsparse = hypre_TAlloc(HYPRE_Int, nparts); fem_sparse_i = hypre_TAlloc(HYPRE_Int *, nparts); fem_sparse_j = hypre_TAlloc(HYPRE_Int *, nparts); fem_entries = hypre_TAlloc(HYPRE_Int *, nparts); for (part = 0; part < nparts; part++) { nvars = hypre_SStructPGridNVars(pgrids[part]); stencils[part] = hypre_TAlloc(hypre_SStructStencil *, nvars); fem_nsparse[part] = 0; fem_sparse_i[part] = NULL; fem_sparse_j[part] = NULL; fem_entries[part] = NULL; for (var = 0; var < nvars; var++) { stencils[part][var] = NULL; } } hypre_SStructGraphStencils(graph) = stencils; hypre_SStructGraphFEMNSparse(graph) = fem_nsparse; hypre_SStructGraphFEMSparseJ(graph) = fem_sparse_i; hypre_SStructGraphFEMSparseI(graph) = fem_sparse_j; hypre_SStructGraphFEMEntries(graph) = fem_entries; hypre_SStructGraphNUVEntries(graph) = 0; hypre_SStructGraphAUVEntries(graph) = 0; hypre_SStructGraphIUVEntries(graph) = NULL; hypre_SStructGraphUVEntries(graph) = NULL; hypre_SStructGraphTotUEntries(graph) = 0; hypre_SStructGraphRefCount(graph) = 1; hypre_SStructGraphObjectType(graph) = HYPRE_SSTRUCT; hypre_SStructGraphEntries(graph) = NULL; hypre_SStructNGraphEntries(graph) = 0; hypre_SStructAGraphEntries(graph) = 0; *graph_ptr = graph; return hypre_error_flag; }