HYPRE_Int hypre_ParCSRBlockMatrixDestroy( hypre_ParCSRBlockMatrix *matrix ) { if (matrix) { if ( hypre_ParCSRBlockMatrixOwnsData(matrix) ) { hypre_CSRBlockMatrixDestroy(hypre_ParCSRBlockMatrixDiag(matrix)); hypre_CSRBlockMatrixDestroy(hypre_ParCSRBlockMatrixOffd(matrix)); if (hypre_ParCSRBlockMatrixColMapOffd(matrix)) hypre_TFree(hypre_ParCSRBlockMatrixColMapOffd(matrix)); if (hypre_ParCSRBlockMatrixCommPkg(matrix)) hypre_MatvecCommPkgDestroy(hypre_ParCSRBlockMatrixCommPkg(matrix)); if (hypre_ParCSRBlockMatrixCommPkgT(matrix)) hypre_MatvecCommPkgDestroy(hypre_ParCSRBlockMatrixCommPkgT(matrix)); } if ( hypre_ParCSRBlockMatrixOwnsRowStarts(matrix) ) hypre_TFree(hypre_ParCSRBlockMatrixRowStarts(matrix)); if ( hypre_ParCSRBlockMatrixOwnsColStarts(matrix) ) hypre_TFree(hypre_ParCSRBlockMatrixColStarts(matrix)); if (hypre_ParCSRBlockMatrixAssumedPartition(matrix)) hypre_ParCSRBlockMatrixDestroyAssumedPartition(matrix); hypre_TFree(matrix); } return hypre_error_flag; }
HYPRE_Int hypre_ParCSRBlockMatrixMatvec(HYPRE_Complex alpha, hypre_ParCSRBlockMatrix *A, hypre_ParVector *x, HYPRE_Complex beta, hypre_ParVector *y) { hypre_ParCSRCommHandle *comm_handle; hypre_ParCSRCommPkg *comm_pkg; hypre_CSRBlockMatrix *diag, *offd; hypre_Vector *x_local, *y_local, *x_tmp; HYPRE_Int i, j, k, index, num_rows, num_cols; HYPRE_Int blk_size, x_size, y_size, size; HYPRE_Int num_cols_offd, start, finish, elem; HYPRE_Int ierr = 0, nprocs, num_sends, mypid; HYPRE_Complex *x_tmp_data, *x_buf_data, *x_local_data; hypre_MPI_Comm_size(hypre_ParCSRBlockMatrixComm(A), &nprocs); hypre_MPI_Comm_rank(hypre_ParCSRBlockMatrixComm(A), &mypid); comm_pkg = hypre_ParCSRBlockMatrixCommPkg(A); num_rows = hypre_ParCSRBlockMatrixGlobalNumRows(A); num_cols = hypre_ParCSRBlockMatrixGlobalNumCols(A); blk_size = hypre_ParCSRBlockMatrixBlockSize(A); diag = hypre_ParCSRBlockMatrixDiag(A); offd = hypre_ParCSRBlockMatrixOffd(A); num_cols_offd = hypre_CSRBlockMatrixNumCols(offd); x_local = hypre_ParVectorLocalVector(x); y_local = hypre_ParVectorLocalVector(y); x_size = hypre_ParVectorGlobalSize(x); y_size = hypre_ParVectorGlobalSize(y); x_local_data = hypre_VectorData(x_local); /*--------------------------------------------------------------------- * Check for size compatibility. *--------------------------------------------------------------------*/ if (num_cols*blk_size != x_size) ierr = 11; if (num_rows*blk_size != y_size) ierr = 12; if (num_cols*blk_size != x_size && num_rows*blk_size != y_size) ierr = 13; if (nprocs > 1) { x_tmp = hypre_SeqVectorCreate(num_cols_offd*blk_size); hypre_SeqVectorInitialize(x_tmp); x_tmp_data = hypre_VectorData(x_tmp); if (!comm_pkg) { hypre_BlockMatvecCommPkgCreate(A); comm_pkg = hypre_ParCSRBlockMatrixCommPkg(A); } num_sends = hypre_ParCSRCommPkgNumSends(comm_pkg); size = hypre_ParCSRCommPkgSendMapStart(comm_pkg,num_sends)*blk_size; x_buf_data = hypre_CTAlloc(HYPRE_Complex, size); index = 0; for (i = 0; i < num_sends; i++) { start = hypre_ParCSRCommPkgSendMapStart(comm_pkg, i); finish = hypre_ParCSRCommPkgSendMapStart(comm_pkg, i+1); for (j = start; j < finish; j++) { elem = hypre_ParCSRCommPkgSendMapElmt(comm_pkg,j)*blk_size; for (k = 0; k < blk_size; k++) x_buf_data[index++] = x_local_data[elem++]; } } comm_handle = hypre_ParCSRBlockCommHandleCreate(1, blk_size,comm_pkg, x_buf_data, x_tmp_data); } hypre_CSRBlockMatrixMatvec(alpha, diag, x_local, beta, y_local); if (nprocs > 1) { hypre_ParCSRBlockCommHandleDestroy(comm_handle); comm_handle = NULL; if (num_cols_offd) hypre_CSRBlockMatrixMatvec(alpha,offd,x_tmp,1.0,y_local); hypre_SeqVectorDestroy(x_tmp); x_tmp = NULL; hypre_TFree(x_buf_data); } return ierr; }
HYPRE_Int hypre_ParCSRBlockMatrixMatvecT( HYPRE_Complex alpha, hypre_ParCSRBlockMatrix *A, hypre_ParVector *x, HYPRE_Complex beta, hypre_ParVector *y ) { hypre_ParCSRCommHandle *comm_handle; hypre_ParCSRCommPkg *comm_pkg = hypre_ParCSRBlockMatrixCommPkg(A); hypre_CSRBlockMatrix *diag = hypre_ParCSRBlockMatrixDiag(A); hypre_CSRBlockMatrix *offd = hypre_ParCSRBlockMatrixOffd(A); hypre_Vector *x_local = hypre_ParVectorLocalVector(x); hypre_Vector *y_local = hypre_ParVectorLocalVector(y); hypre_Vector *y_tmp; HYPRE_Complex *y_local_data; HYPRE_Int blk_size = hypre_ParCSRBlockMatrixBlockSize(A); HYPRE_Int x_size = hypre_ParVectorGlobalSize(x); HYPRE_Int y_size = hypre_ParVectorGlobalSize(y); HYPRE_Complex *y_tmp_data, *y_buf_data; HYPRE_Int num_rows = hypre_ParCSRBlockMatrixGlobalNumRows(A); HYPRE_Int num_cols = hypre_ParCSRBlockMatrixGlobalNumCols(A); HYPRE_Int num_cols_offd = hypre_CSRBlockMatrixNumCols(offd); HYPRE_Int i, j, index, start, finish, elem, num_sends; HYPRE_Int size, k; HYPRE_Int ierr = 0; /*--------------------------------------------------------------------- * Check for size compatibility. MatvecT returns ierr = 1 if * length of X doesn't equal the number of rows of A, * ierr = 2 if the length of Y doesn't equal the number of * columns of A, and ierr = 3 if both are true. * * Because temporary vectors are often used in MatvecT, none of * these conditions terminates processing, and the ierr flag * is informational only. *--------------------------------------------------------------------*/ if (num_rows*blk_size != x_size) ierr = 1; if (num_cols*blk_size != y_size) ierr = 2; if (num_rows*blk_size != x_size && num_cols*blk_size != y_size) ierr = 3; /*----------------------------------------------------------------------- *-----------------------------------------------------------------------*/ y_tmp = hypre_SeqVectorCreate(num_cols_offd*blk_size); hypre_SeqVectorInitialize(y_tmp); /*--------------------------------------------------------------------- * If there exists no CommPkg for A, a CommPkg is generated using * equally load balanced partitionings *--------------------------------------------------------------------*/ if (!comm_pkg) { hypre_BlockMatvecCommPkgCreate(A); comm_pkg = hypre_ParCSRBlockMatrixCommPkg(A); } num_sends = hypre_ParCSRCommPkgNumSends(comm_pkg); size = hypre_ParCSRCommPkgSendMapStart(comm_pkg, num_sends)*blk_size; y_buf_data = hypre_CTAlloc(HYPRE_Complex, size); y_tmp_data = hypre_VectorData(y_tmp); y_local_data = hypre_VectorData(y_local); if (num_cols_offd) hypre_CSRBlockMatrixMatvecT(alpha, offd, x_local, 0.0, y_tmp); comm_handle = hypre_ParCSRBlockCommHandleCreate ( 2, blk_size, comm_pkg, y_tmp_data, y_buf_data); hypre_CSRBlockMatrixMatvecT(alpha, diag, x_local, beta, y_local); hypre_ParCSRCommHandleDestroy(comm_handle); comm_handle = NULL; index = 0; for (i = 0; i < num_sends; i++) { start = hypre_ParCSRCommPkgSendMapStart(comm_pkg, i); finish = hypre_ParCSRCommPkgSendMapStart(comm_pkg, i+1); for (j = start; j < finish; j++) { elem = hypre_ParCSRCommPkgSendMapElmt(comm_pkg, j)*blk_size; for (k = 0; k < blk_size; k++) { y_local_data[elem++] += y_buf_data[index++]; } } } hypre_TFree(y_buf_data); hypre_SeqVectorDestroy(y_tmp); y_tmp = NULL; return ierr; }
hypre_CSRBlockMatrix * hypre_ParCSRBlockMatrixExtractBExt(hypre_ParCSRBlockMatrix *B, hypre_ParCSRBlockMatrix *A, HYPRE_Int data) { MPI_Comm comm = hypre_ParCSRBlockMatrixComm(B); HYPRE_Int first_col_diag = hypre_ParCSRBlockMatrixFirstColDiag(B); HYPRE_Int *col_map_offd = hypre_ParCSRBlockMatrixColMapOffd(B); HYPRE_Int block_size = hypre_ParCSRBlockMatrixBlockSize(B); hypre_ParCSRCommPkg *comm_pkg = hypre_ParCSRBlockMatrixCommPkg(A); HYPRE_Int num_recvs = hypre_ParCSRCommPkgNumRecvs(comm_pkg); HYPRE_Int *recv_vec_starts = hypre_ParCSRCommPkgRecvVecStarts(comm_pkg); HYPRE_Int num_sends = hypre_ParCSRCommPkgNumSends(comm_pkg); HYPRE_Int *send_map_starts = hypre_ParCSRCommPkgSendMapStarts(comm_pkg); HYPRE_Int *send_map_elmts = hypre_ParCSRCommPkgSendMapElmts(comm_pkg); hypre_ParCSRCommHandle *comm_handle; hypre_ParCSRCommPkg *tmp_comm_pkg; hypre_CSRBlockMatrix *diag = hypre_ParCSRBlockMatrixDiag(B); HYPRE_Int *diag_i = hypre_CSRBlockMatrixI(diag); HYPRE_Int *diag_j = hypre_CSRBlockMatrixJ(diag); HYPRE_Complex *diag_data = hypre_CSRBlockMatrixData(diag); hypre_CSRBlockMatrix *offd = hypre_ParCSRBlockMatrixOffd(B); HYPRE_Int *offd_i = hypre_CSRBlockMatrixI(offd); HYPRE_Int *offd_j = hypre_CSRBlockMatrixJ(offd); HYPRE_Complex *offd_data = hypre_CSRBlockMatrixData(offd); HYPRE_Int *B_int_i; HYPRE_Int *B_int_j; HYPRE_Complex *B_int_data; HYPRE_Int num_cols_B, num_nonzeros; HYPRE_Int num_rows_B_ext; HYPRE_Int num_procs, my_id; hypre_CSRBlockMatrix *B_ext; HYPRE_Int *B_ext_i; HYPRE_Int *B_ext_j; HYPRE_Complex *B_ext_data; HYPRE_Int *jdata_recv_vec_starts; HYPRE_Int *jdata_send_map_starts; HYPRE_Int i, j, k, l, counter, bnnz; HYPRE_Int start_index; HYPRE_Int j_cnt, jrow; hypre_MPI_Comm_size(comm,&num_procs); hypre_MPI_Comm_rank(comm,&my_id); bnnz = block_size * block_size; num_cols_B = hypre_ParCSRMatrixGlobalNumCols(B); num_rows_B_ext = recv_vec_starts[num_recvs]; B_int_i = hypre_CTAlloc(HYPRE_Int, send_map_starts[num_sends]+1); B_ext_i = hypre_CTAlloc(HYPRE_Int, num_rows_B_ext+1); /*-------------------------------------------------------------------------- * generate B_int_i through adding number of row-elements of offd and diag * for corresponding rows. B_int_i[j+1] contains the number of elements of * a row j (which is determined through send_map_elmts) *--------------------------------------------------------------------------*/ B_int_i[0] = 0; j_cnt = 0; num_nonzeros = 0; for (i=0; i < num_sends; i++) { for (j = send_map_starts[i]; j < send_map_starts[i+1]; j++) { jrow = send_map_elmts[j]; B_int_i[++j_cnt] = offd_i[jrow+1] - offd_i[jrow] + diag_i[jrow+1] - diag_i[jrow]; num_nonzeros += B_int_i[j_cnt]; } } /*-------------------------------------------------------------------------- * initialize communication *--------------------------------------------------------------------------*/ comm_handle = hypre_ParCSRCommHandleCreate(11,comm_pkg, &B_int_i[1],&B_ext_i[1]); B_int_j = hypre_CTAlloc(HYPRE_Int, num_nonzeros); if (data) B_int_data = hypre_CTAlloc(HYPRE_Complex, num_nonzeros*bnnz); jdata_send_map_starts = hypre_CTAlloc(HYPRE_Int, num_sends+1); jdata_recv_vec_starts = hypre_CTAlloc(HYPRE_Int, num_recvs+1); start_index = B_int_i[0]; jdata_send_map_starts[0] = start_index; counter = 0; for (i=0; i < num_sends; i++) { num_nonzeros = counter; for (j = send_map_starts[i]; j < send_map_starts[i+1]; j++) { jrow = send_map_elmts[j]; for (k=diag_i[jrow]; k < diag_i[jrow+1]; k++) { B_int_j[counter] = diag_j[k]+first_col_diag; if (data) { for(l = 0; l < bnnz; l++) B_int_data[counter*bnnz+ l] = diag_data[k*bnnz+ l]; } counter++; } for (k=offd_i[jrow]; k < offd_i[jrow+1]; k++) { B_int_j[counter] = col_map_offd[offd_j[k]]; if (data) { for(l = 0; l < bnnz; l++) B_int_data[counter*bnnz+ l] = offd_data[k*bnnz+ l]; } counter++; } } num_nonzeros = counter - num_nonzeros; start_index += num_nonzeros; jdata_send_map_starts[i+1] = start_index; } tmp_comm_pkg = hypre_CTAlloc(hypre_ParCSRCommPkg,1); hypre_ParCSRCommPkgComm(tmp_comm_pkg) = comm; hypre_ParCSRCommPkgNumSends(tmp_comm_pkg) = num_sends; hypre_ParCSRCommPkgNumRecvs(tmp_comm_pkg) = num_recvs; hypre_ParCSRCommPkgSendProcs(tmp_comm_pkg) = hypre_ParCSRCommPkgSendProcs(comm_pkg); hypre_ParCSRCommPkgRecvProcs(tmp_comm_pkg) = hypre_ParCSRCommPkgRecvProcs(comm_pkg); hypre_ParCSRCommPkgSendMapStarts(tmp_comm_pkg) = jdata_send_map_starts; hypre_ParCSRCommHandleDestroy(comm_handle); comm_handle = NULL; /*-------------------------------------------------------------------------- * after communication exchange B_ext_i[j+1] contains the number of elements * of a row j ! * evaluate B_ext_i and compute num_nonzeros for B_ext *--------------------------------------------------------------------------*/ for (i=0; i < num_recvs; i++) for (j = recv_vec_starts[i]; j < recv_vec_starts[i+1]; j++) B_ext_i[j+1] += B_ext_i[j]; num_nonzeros = B_ext_i[num_rows_B_ext]; B_ext = hypre_CSRBlockMatrixCreate(block_size, num_rows_B_ext, num_cols_B, num_nonzeros); B_ext_j = hypre_CTAlloc(HYPRE_Int, num_nonzeros); if (data) B_ext_data = hypre_CTAlloc(HYPRE_Complex, num_nonzeros*bnnz); for (i=0; i < num_recvs; i++) { start_index = B_ext_i[recv_vec_starts[i]]; num_nonzeros = B_ext_i[recv_vec_starts[i+1]]-start_index; jdata_recv_vec_starts[i+1] = B_ext_i[recv_vec_starts[i+1]]; } hypre_ParCSRCommPkgRecvVecStarts(tmp_comm_pkg) = jdata_recv_vec_starts; comm_handle = hypre_ParCSRCommHandleCreate(11,tmp_comm_pkg,B_int_j,B_ext_j); hypre_ParCSRCommHandleDestroy(comm_handle); comm_handle = NULL; if (data) { comm_handle = hypre_ParCSRBlockCommHandleCreate(1, bnnz,tmp_comm_pkg, B_int_data, B_ext_data); hypre_ParCSRBlockCommHandleDestroy(comm_handle); comm_handle = NULL; } hypre_CSRBlockMatrixI(B_ext) = B_ext_i; hypre_CSRBlockMatrixJ(B_ext) = B_ext_j; if (data) hypre_CSRBlockMatrixData(B_ext) = B_ext_data; hypre_TFree(B_int_i); hypre_TFree(B_int_j); if (data) hypre_TFree(B_int_data); hypre_TFree(jdata_send_map_starts); hypre_TFree(jdata_recv_vec_starts); hypre_TFree(tmp_comm_pkg); return B_ext; }
HYPRE_Int hypre_BlockMatvecCommPkgCreate(hypre_ParCSRBlockMatrix *A) { #ifdef HYPRE_NO_GLOBAL_PARTITION HYPRE_Int col_start = 0, col_end = 0; HYPRE_Int num_recvs, *recv_procs, *recv_vec_starts; HYPRE_Int num_sends, *send_procs, *send_map_starts; HYPRE_Int *send_map_elmts; HYPRE_Int num_cols_off_d; HYPRE_Int *col_map_off_d; HYPRE_Int first_col_diag; HYPRE_Int global_num_cols; MPI_Comm comm; hypre_ParCSRCommPkg *comm_pkg; hypre_IJAssumedPart *apart; /*----------------------------------------------------------- * get parcsr_A information *----------------------------------------------------------*/ col_start = hypre_ParCSRBlockMatrixFirstColDiag(A); col_end = hypre_ParCSRBlockMatrixLastColDiag(A); col_map_off_d = hypre_ParCSRBlockMatrixColMapOffd(A); num_cols_off_d = hypre_CSRBlockMatrixNumCols(hypre_ParCSRBlockMatrixOffd(A)); global_num_cols = hypre_ParCSRBlockMatrixGlobalNumCols(A); comm = hypre_ParCSRBlockMatrixComm(A); first_col_diag = hypre_ParCSRBlockMatrixFirstColDiag(A); /* Create the assumed partition */ if (hypre_ParCSRBlockMatrixAssumedPartition(A) == NULL) { hypre_ParCSRBlockMatrixCreateAssumedPartition(A); } apart = hypre_ParCSRBlockMatrixAssumedPartition(A); /*----------------------------------------------------------- * get commpkg info information *----------------------------------------------------------*/ hypre_NewCommPkgCreate_core( comm, col_map_off_d, first_col_diag, col_start, col_end, num_cols_off_d, global_num_cols, &num_recvs, &recv_procs, &recv_vec_starts, &num_sends, &send_procs, &send_map_starts, &send_map_elmts, apart); if (!num_recvs) { hypre_TFree(recv_procs); recv_procs = NULL; } if (!num_sends) { hypre_TFree(send_procs); hypre_TFree(send_map_elmts); send_procs = NULL; send_map_elmts = NULL; } #else hypre_ParCSRCommPkg *comm_pkg; MPI_Comm comm = hypre_ParCSRBlockMatrixComm(A); HYPRE_Int num_sends; HYPRE_Int *send_procs; HYPRE_Int *send_map_starts; HYPRE_Int *send_map_elmts; HYPRE_Int num_recvs; HYPRE_Int *recv_procs; HYPRE_Int *recv_vec_starts; HYPRE_Int *col_map_offd = hypre_ParCSRBlockMatrixColMapOffd(A); HYPRE_Int first_col_diag = hypre_ParCSRBlockMatrixFirstColDiag(A); HYPRE_Int *col_starts = hypre_ParCSRBlockMatrixColStarts(A); HYPRE_Int num_cols_diag = hypre_CSRBlockMatrixNumCols(hypre_ParCSRBlockMatrixDiag(A)); HYPRE_Int num_cols_offd = hypre_CSRBlockMatrixNumCols(hypre_ParCSRBlockMatrixOffd(A)); hypre_MatvecCommPkgCreate_core(comm, col_map_offd, first_col_diag, col_starts, num_cols_diag, num_cols_offd, first_col_diag, col_map_offd, 1, &num_recvs, &recv_procs, &recv_vec_starts, &num_sends, &send_procs, &send_map_starts, &send_map_elmts); #endif /*----------------------------------------------------------- * setup commpkg *----------------------------------------------------------*/ comm_pkg = hypre_CTAlloc(hypre_ParCSRCommPkg, 1); hypre_ParCSRCommPkgComm(comm_pkg) = comm; hypre_ParCSRCommPkgNumRecvs(comm_pkg) = num_recvs; hypre_ParCSRCommPkgRecvProcs(comm_pkg) = recv_procs; hypre_ParCSRCommPkgRecvVecStarts(comm_pkg) = recv_vec_starts; hypre_ParCSRCommPkgNumSends(comm_pkg) = num_sends; hypre_ParCSRCommPkgSendProcs(comm_pkg) = send_procs; hypre_ParCSRCommPkgSendMapStarts(comm_pkg) = send_map_starts; hypre_ParCSRCommPkgSendMapElmts(comm_pkg) = send_map_elmts; hypre_ParCSRBlockMatrixCommPkg(A) = comm_pkg; return hypre_error_flag; }
hypre_ParCSRBlockMatrix * hypre_ParCSRBlockMatrixConvertFromParCSRMatrix(hypre_ParCSRMatrix *matrix, HYPRE_Int matrix_C_block_size ) { MPI_Comm comm = hypre_ParCSRMatrixComm(matrix); hypre_CSRMatrix *diag = hypre_ParCSRMatrixDiag(matrix); hypre_CSRMatrix *offd = hypre_ParCSRMatrixOffd(matrix); HYPRE_Int global_num_rows = hypre_ParCSRMatrixGlobalNumRows(matrix); HYPRE_Int global_num_cols = hypre_ParCSRMatrixGlobalNumCols(matrix); HYPRE_Int *row_starts = hypre_ParCSRMatrixRowStarts(matrix); HYPRE_Int *col_starts = hypre_ParCSRMatrixColStarts(matrix); HYPRE_Int num_cols_offd = hypre_CSRMatrixNumCols(offd); HYPRE_Int *col_map_offd = hypre_ParCSRBlockMatrixColMapOffd(matrix); HYPRE_Int *map_to_node=NULL, *counter=NULL, *col_in_j_map=NULL; HYPRE_Int *matrix_C_col_map_offd = NULL; HYPRE_Int matrix_C_num_cols_offd; HYPRE_Int matrix_C_num_nonzeros_offd; HYPRE_Int num_rows, num_nodes; HYPRE_Int *offd_i = hypre_CSRMatrixI(offd); HYPRE_Int *offd_j = hypre_CSRMatrixJ(offd); HYPRE_Complex * offd_data = hypre_CSRMatrixData(offd); hypre_ParCSRBlockMatrix *matrix_C; HYPRE_Int *matrix_C_row_starts; HYPRE_Int *matrix_C_col_starts; hypre_CSRBlockMatrix *matrix_C_diag; hypre_CSRBlockMatrix *matrix_C_offd; HYPRE_Int *matrix_C_offd_i=NULL, *matrix_C_offd_j = NULL; HYPRE_Complex *matrix_C_offd_data = NULL; HYPRE_Int num_procs, i, j, k, k_map, count, index, start_index, pos, row; hypre_MPI_Comm_size(comm,&num_procs); #ifdef HYPRE_NO_GLOBAL_PARTITION matrix_C_row_starts = hypre_CTAlloc(HYPRE_Int, 2); matrix_C_col_starts = hypre_CTAlloc(HYPRE_Int, 2); for(i = 0; i < 2; i++) { matrix_C_row_starts[i] = row_starts[i]/matrix_C_block_size; matrix_C_col_starts[i] = col_starts[i]/matrix_C_block_size; } #else matrix_C_row_starts = hypre_CTAlloc(HYPRE_Int, num_procs + 1); matrix_C_col_starts = hypre_CTAlloc(HYPRE_Int, num_procs + 1); for(i = 0; i < num_procs + 1; i++) { matrix_C_row_starts[i] = row_starts[i]/matrix_C_block_size; matrix_C_col_starts[i] = col_starts[i]/matrix_C_block_size; } #endif /************* create the diagonal part ************/ matrix_C_diag = hypre_CSRBlockMatrixConvertFromCSRMatrix(diag, matrix_C_block_size); /******* the offd part *******************/ /* can't use the same function for the offd part - because this isn't square and the offd j entries aren't global numbering (have to consider the offd map) - need to look at col_map_offd first */ /* figure out the new number of offd columns (num rows is same as diag) */ num_cols_offd = hypre_CSRMatrixNumCols(offd); num_rows = hypre_CSRMatrixNumRows(diag); num_nodes = num_rows/matrix_C_block_size; matrix_C_offd_i = hypre_CTAlloc(HYPRE_Int, num_nodes + 1); matrix_C_num_cols_offd = 0; matrix_C_offd_i[0] = 0; matrix_C_num_nonzeros_offd = 0; if (num_cols_offd) { map_to_node = hypre_CTAlloc(HYPRE_Int, num_cols_offd); matrix_C_num_cols_offd = 1; map_to_node[0] = col_map_offd[0]/matrix_C_block_size; for (i=1; i < num_cols_offd; i++) { map_to_node[i] = col_map_offd[i]/matrix_C_block_size; if (map_to_node[i] > map_to_node[i-1]) matrix_C_num_cols_offd++; } matrix_C_col_map_offd = hypre_CTAlloc(HYPRE_Int, matrix_C_num_cols_offd); col_in_j_map = hypre_CTAlloc(HYPRE_Int, num_cols_offd); matrix_C_col_map_offd[0] = map_to_node[0]; col_in_j_map[0] = 0; count = 1; j = 1; /* fill in the col_map_off_d - these are global numbers. Then we need to map these to j entries (these have local numbers) */ for (i=1; i < num_cols_offd; i++) { if (map_to_node[i] > map_to_node[i-1]) { matrix_C_col_map_offd[count++] = map_to_node[i]; } col_in_j_map[j++] = count - 1; } /* now figure the nonzeros */ matrix_C_num_nonzeros_offd = 0; counter = hypre_CTAlloc(HYPRE_Int, matrix_C_num_cols_offd); for (i=0; i < matrix_C_num_cols_offd; i++) counter[i] = -1; for (i=0; i < num_nodes; i++) /* for each block row */ { matrix_C_offd_i[i] = matrix_C_num_nonzeros_offd; for (j=0; j < matrix_C_block_size; j++) { row = i*matrix_C_block_size+j; for (k=offd_i[row]; k < offd_i[row+1]; k++) /* go through single row */ { k_map = col_in_j_map[offd_j[k]]; /*nodal col - see if this has been in this block row (i) already*/ if (counter[k_map] < i) /* not yet counted for this nodal row */ { counter[k_map] = i; matrix_C_num_nonzeros_offd++; } } } } /* fill in final i entry */ matrix_C_offd_i[num_nodes] = matrix_C_num_nonzeros_offd; } /* create offd matrix */ matrix_C_offd = hypre_CSRBlockMatrixCreate(matrix_C_block_size, num_nodes, matrix_C_num_cols_offd, matrix_C_num_nonzeros_offd); /* assign i */ hypre_CSRBlockMatrixI(matrix_C_offd) = matrix_C_offd_i; /* create (and allocate j and data) */ if (matrix_C_num_nonzeros_offd) { matrix_C_offd_j = hypre_CTAlloc(HYPRE_Int, matrix_C_num_nonzeros_offd); matrix_C_offd_data = hypre_CTAlloc(HYPRE_Complex, matrix_C_num_nonzeros_offd*matrix_C_block_size* matrix_C_block_size); hypre_CSRBlockMatrixJ(matrix_C_offd) = matrix_C_offd_j; hypre_CSRMatrixData(matrix_C_offd) = matrix_C_offd_data; for (i=0; i < matrix_C_num_cols_offd; i++) counter[i] = -1; index = 0; /*keep track of entry in matrix_C_offd_j*/ start_index = 0; for (i=0; i < num_nodes; i++) /* for each block row */ { for (j=0; j < matrix_C_block_size; j++) /* for each row in block */ { row = i*matrix_C_block_size+j; for (k=offd_i[row]; k < offd_i[row+1]; k++) /* go through single row's cols */ { k_map = col_in_j_map[offd_j[k]]; /*nodal col for off_d */ if (counter[k_map] < start_index) /* not yet counted for this nodal row */ { counter[k_map] = index; matrix_C_offd_j[index] = k_map; /*copy the data: which position (corresponds to j array) + which row + which col */ pos = (index * matrix_C_block_size * matrix_C_block_size) + (j * matrix_C_block_size) + col_map_offd[offd_j[k]]%matrix_C_block_size; matrix_C_offd_data[pos] = offd_data[k]; index ++; } else /* this col has already been listed for this row */ { /*copy the data: which position (corresponds to j array) + which row + which col */ pos = (counter[k_map]* matrix_C_block_size * matrix_C_block_size) + (j * matrix_C_block_size) + col_map_offd[offd_j[k]]%matrix_C_block_size; matrix_C_offd_data[pos] = offd_data[k]; } } } start_index = index; /* first index for current nodal row */ } } /* *********create the new matrix *************/ matrix_C = hypre_ParCSRBlockMatrixCreate(comm, matrix_C_block_size, global_num_rows/matrix_C_block_size, global_num_cols/matrix_C_block_size, matrix_C_row_starts, matrix_C_col_starts, matrix_C_num_cols_offd, hypre_CSRBlockMatrixNumNonzeros(matrix_C_diag), matrix_C_num_nonzeros_offd); /* use the diag and off diag matrices we have already created */ hypre_CSRBlockMatrixDestroy(hypre_ParCSRMatrixDiag(matrix_C)); hypre_ParCSRBlockMatrixDiag(matrix_C) = matrix_C_diag; hypre_CSRBlockMatrixDestroy(hypre_ParCSRMatrixOffd(matrix_C)); hypre_ParCSRBlockMatrixOffd(matrix_C) = matrix_C_offd; hypre_ParCSRMatrixColMapOffd(matrix_C) = matrix_C_col_map_offd; /* *********don't bother to copy the comm_pkg *************/ hypre_ParCSRBlockMatrixCommPkg(matrix_C) = NULL; /* CLEAN UP !!!! */ hypre_TFree(map_to_node); hypre_TFree(col_in_j_map); hypre_TFree(counter); return matrix_C; }
hypre_ParCSRBlockMatrix * hypre_ParCSRBlockMatrixCreate( MPI_Comm comm, HYPRE_Int block_size, HYPRE_Int global_num_rows, HYPRE_Int global_num_cols, HYPRE_Int *row_starts, HYPRE_Int *col_starts, HYPRE_Int num_cols_offd, HYPRE_Int num_nonzeros_diag, HYPRE_Int num_nonzeros_offd ) { hypre_ParCSRBlockMatrix *matrix; HYPRE_Int num_procs, my_id; HYPRE_Int local_num_rows, local_num_cols; HYPRE_Int first_row_index, first_col_diag; matrix = hypre_CTAlloc(hypre_ParCSRBlockMatrix, 1); hypre_MPI_Comm_rank(comm,&my_id); hypre_MPI_Comm_size(comm,&num_procs); if (!row_starts) { #ifdef HYPRE_NO_GLOBAL_PARTITION hypre_GenerateLocalPartitioning(global_num_rows, num_procs, my_id, &row_starts); #else hypre_GeneratePartitioning(global_num_rows,num_procs,&row_starts); #endif } if (!col_starts) { if (global_num_rows == global_num_cols) { col_starts = row_starts; } else { #ifdef HYPRE_NO_GLOBAL_PARTITION hypre_GenerateLocalPartitioning(global_num_cols, num_procs, my_id, &col_starts); #else hypre_GeneratePartitioning(global_num_cols,num_procs,&col_starts); #endif } } #ifdef HYPRE_NO_GLOBAL_PARTITION /* row_starts[0] is start of local rows. row_starts[1] is start of next processor's rows */ first_row_index = row_starts[0]; local_num_rows = row_starts[1]-first_row_index ; first_col_diag = col_starts[0]; local_num_cols = col_starts[1]-first_col_diag; #else first_row_index = row_starts[my_id]; local_num_rows = row_starts[my_id+1]-first_row_index; first_col_diag = col_starts[my_id]; local_num_cols = col_starts[my_id+1]-first_col_diag; #endif hypre_ParCSRBlockMatrixComm(matrix) = comm; hypre_ParCSRBlockMatrixDiag(matrix) = hypre_CSRBlockMatrixCreate(block_size, local_num_rows,local_num_cols,num_nonzeros_diag); hypre_ParCSRBlockMatrixOffd(matrix) = hypre_CSRBlockMatrixCreate(block_size, local_num_rows, num_cols_offd, num_nonzeros_offd); hypre_ParCSRBlockMatrixBlockSize(matrix) = block_size; hypre_ParCSRBlockMatrixGlobalNumRows(matrix) = global_num_rows; hypre_ParCSRBlockMatrixGlobalNumCols(matrix) = global_num_cols; hypre_ParCSRBlockMatrixFirstRowIndex(matrix) = first_row_index; hypre_ParCSRBlockMatrixFirstColDiag(matrix) = first_col_diag; hypre_ParCSRBlockMatrixLastRowIndex(matrix) = first_row_index + local_num_rows - 1; hypre_ParCSRBlockMatrixLastColDiag(matrix) = first_col_diag + local_num_cols - 1; hypre_ParCSRBlockMatrixColMapOffd(matrix) = NULL; hypre_ParCSRBlockMatrixAssumedPartition(matrix) = NULL; /* When NO_GLOBAL_PARTITION is set we could make these null, instead of leaving the range. If that change is made, then when this create is called from functions like the matrix-matrix multiply, be careful not to generate a new partition */ hypre_ParCSRBlockMatrixRowStarts(matrix) = row_starts; hypre_ParCSRBlockMatrixColStarts(matrix) = col_starts; hypre_ParCSRBlockMatrixCommPkg(matrix) = NULL; hypre_ParCSRBlockMatrixCommPkgT(matrix) = NULL; /* set defaults */ hypre_ParCSRBlockMatrixOwnsData(matrix) = 1; hypre_ParCSRBlockMatrixOwnsRowStarts(matrix) = 1; hypre_ParCSRBlockMatrixOwnsColStarts(matrix) = 1; if (row_starts == col_starts) hypre_ParCSRBlockMatrixOwnsColStarts(matrix) = 0; return matrix; }
HYPRE_Int hypre_BoomerAMGBlockCreateNodalA(hypre_ParCSRBlockMatrix *A, HYPRE_Int option, HYPRE_Int diag_option, hypre_ParCSRMatrix **AN_ptr) { MPI_Comm comm = hypre_ParCSRBlockMatrixComm(A); hypre_CSRBlockMatrix *A_diag = hypre_ParCSRBlockMatrixDiag(A); HYPRE_Int *A_diag_i = hypre_CSRBlockMatrixI(A_diag); HYPRE_Real *A_diag_data = hypre_CSRBlockMatrixData(A_diag); HYPRE_Int block_size = hypre_CSRBlockMatrixBlockSize(A_diag); HYPRE_Int bnnz = block_size*block_size; hypre_CSRBlockMatrix *A_offd = hypre_ParCSRMatrixOffd(A); HYPRE_Int *A_offd_i = hypre_CSRBlockMatrixI(A_offd); HYPRE_Real *A_offd_data = hypre_CSRBlockMatrixData(A_offd); HYPRE_Int *A_diag_j = hypre_CSRBlockMatrixJ(A_diag); HYPRE_Int *A_offd_j = hypre_CSRBlockMatrixJ(A_offd); HYPRE_Int *row_starts = hypre_ParCSRBlockMatrixRowStarts(A); HYPRE_Int *col_map_offd = hypre_ParCSRBlockMatrixColMapOffd(A); HYPRE_Int num_nonzeros_diag; HYPRE_Int num_nonzeros_offd = 0; HYPRE_Int num_cols_offd = 0; hypre_ParCSRMatrix *AN; hypre_CSRMatrix *AN_diag; HYPRE_Int *AN_diag_i; HYPRE_Int *AN_diag_j=NULL; HYPRE_Real *AN_diag_data = NULL; hypre_CSRMatrix *AN_offd; HYPRE_Int *AN_offd_i; HYPRE_Int *AN_offd_j = NULL; HYPRE_Real *AN_offd_data = NULL; HYPRE_Int *col_map_offd_AN = NULL; HYPRE_Int *row_starts_AN; hypre_ParCSRCommPkg *comm_pkg = hypre_ParCSRBlockMatrixCommPkg(A); HYPRE_Int num_sends; HYPRE_Int num_recvs; HYPRE_Int *send_procs; HYPRE_Int *send_map_starts; HYPRE_Int *send_map_elmts; HYPRE_Int *recv_procs; HYPRE_Int *recv_vec_starts; hypre_ParCSRCommPkg *comm_pkg_AN = NULL; HYPRE_Int *send_procs_AN = NULL; HYPRE_Int *send_map_starts_AN = NULL; HYPRE_Int *send_map_elmts_AN = NULL; HYPRE_Int *recv_procs_AN = NULL; HYPRE_Int *recv_vec_starts_AN = NULL; HYPRE_Int i; HYPRE_Int ierr = 0; HYPRE_Int num_procs; HYPRE_Int cnt; HYPRE_Int norm_type; HYPRE_Int global_num_nodes; HYPRE_Int num_nodes; HYPRE_Int index, k; HYPRE_Real tmp; HYPRE_Real sum; hypre_MPI_Comm_size(comm,&num_procs); if (!comm_pkg) { hypre_BlockMatvecCommPkgCreate(A); comm_pkg = hypre_ParCSRBlockMatrixCommPkg(A); } norm_type = fabs(option); /* Set up the new matrix AN */ #ifdef HYPRE_NO_GLOBAL_PARTITION row_starts_AN = hypre_CTAlloc(HYPRE_Int, 2); for (i=0; i < 2; i++) { row_starts_AN[i] = row_starts[i]; } #else row_starts_AN = hypre_CTAlloc(HYPRE_Int, num_procs+1); for (i=0; i < num_procs+1; i++) { row_starts_AN[i] = row_starts[i]; } #endif global_num_nodes = hypre_ParCSRBlockMatrixGlobalNumRows(A); num_nodes = hypre_CSRBlockMatrixNumRows(A_diag); /* the diag part */ num_nonzeros_diag = A_diag_i[num_nodes]; AN_diag_i = hypre_CTAlloc(HYPRE_Int, num_nodes+1); for (i=0; i <= num_nodes; i++) { AN_diag_i[i] = A_diag_i[i]; } AN_diag_j = hypre_CTAlloc(HYPRE_Int, num_nonzeros_diag); AN_diag_data = hypre_CTAlloc(HYPRE_Real, num_nonzeros_diag); AN_diag = hypre_CSRMatrixCreate(num_nodes, num_nodes, num_nonzeros_diag); hypre_CSRMatrixI(AN_diag) = AN_diag_i; hypre_CSRMatrixJ(AN_diag) = AN_diag_j; hypre_CSRMatrixData(AN_diag) = AN_diag_data; for (i=0; i< num_nonzeros_diag; i++) { AN_diag_j[i] = A_diag_j[i]; hypre_CSRBlockMatrixBlockNorm(norm_type, &A_diag_data[i*bnnz], &tmp, block_size); AN_diag_data[i] = tmp; } if (diag_option ==1 ) { /* make the diag entry the negative of the sum of off-diag entries (NEED * to get more below!)*/ /* the diagonal is the first element listed in each row - */ for (i=0; i < num_nodes; i++) { index = AN_diag_i[i]; sum = 0.0; for (k = AN_diag_i[i]+1; k < AN_diag_i[i+1]; k++) { sum += AN_diag_data[k]; } AN_diag_data[index] = -sum; } } else if (diag_option == 2) { /* make all diagonal entries negative */ /* the diagonal is the first element listed in each row - */ for (i=0; i < num_nodes; i++) { index = AN_diag_i[i]; AN_diag_data[index] = -AN_diag_data[index]; } } /* copy the commpkg */ if (comm_pkg) { comm_pkg_AN = hypre_CTAlloc(hypre_ParCSRCommPkg,1); hypre_ParCSRCommPkgComm(comm_pkg_AN) = comm; num_sends = hypre_ParCSRCommPkgNumSends(comm_pkg); hypre_ParCSRCommPkgNumSends(comm_pkg_AN) = num_sends; num_recvs = hypre_ParCSRCommPkgNumRecvs(comm_pkg); hypre_ParCSRCommPkgNumRecvs(comm_pkg_AN) = num_recvs; send_procs = hypre_ParCSRCommPkgSendProcs(comm_pkg); send_map_starts = hypre_ParCSRCommPkgSendMapStarts(comm_pkg); send_map_elmts = hypre_ParCSRCommPkgSendMapElmts(comm_pkg); if (num_sends) { send_procs_AN = hypre_CTAlloc(HYPRE_Int, num_sends); send_map_elmts_AN = hypre_CTAlloc(HYPRE_Int, send_map_starts[num_sends]); } send_map_starts_AN = hypre_CTAlloc(HYPRE_Int, num_sends+1); send_map_starts_AN[0] = 0; for (i=0; i < num_sends; i++) { send_procs_AN[i] = send_procs[i]; send_map_starts_AN[i+1] = send_map_starts[i+1]; } cnt = send_map_starts_AN[num_sends]; for (i=0; i< cnt; i++) { send_map_elmts_AN[i] = send_map_elmts[i]; } hypre_ParCSRCommPkgSendProcs(comm_pkg_AN) = send_procs_AN; hypre_ParCSRCommPkgSendMapStarts(comm_pkg_AN) = send_map_starts_AN; hypre_ParCSRCommPkgSendMapElmts(comm_pkg_AN) = send_map_elmts_AN; recv_procs = hypre_ParCSRCommPkgRecvProcs(comm_pkg); recv_vec_starts = hypre_ParCSRCommPkgRecvVecStarts(comm_pkg); recv_vec_starts_AN = hypre_CTAlloc(HYPRE_Int, num_recvs+1); if (num_recvs) recv_procs_AN = hypre_CTAlloc(HYPRE_Int, num_recvs); recv_vec_starts_AN[0] = recv_vec_starts[0]; for (i=0; i < num_recvs; i++) { recv_procs_AN[i] = recv_procs[i]; recv_vec_starts_AN[i+1] = recv_vec_starts[i+1]; } hypre_ParCSRCommPkgRecvProcs(comm_pkg_AN) = recv_procs_AN; hypre_ParCSRCommPkgRecvVecStarts(comm_pkg_AN) = recv_vec_starts_AN; } /* the off-diag part */ num_cols_offd = hypre_CSRBlockMatrixNumCols(A_offd); col_map_offd_AN = hypre_CTAlloc(HYPRE_Int, num_cols_offd); for (i=0; i < num_cols_offd; i++) { col_map_offd_AN[i] = col_map_offd[i]; } num_nonzeros_offd = A_offd_i[num_nodes]; AN_offd_i = hypre_CTAlloc(HYPRE_Int, num_nodes+1); for (i=0; i <= num_nodes; i++) { AN_offd_i[i] = A_offd_i[i]; } AN_offd_j = hypre_CTAlloc(HYPRE_Int, num_nonzeros_offd); AN_offd_data = hypre_CTAlloc(HYPRE_Real, num_nonzeros_offd); for (i=0; i< num_nonzeros_offd; i++) { AN_offd_j[i] = A_offd_j[i]; hypre_CSRBlockMatrixBlockNorm(norm_type, &A_offd_data[i*bnnz], &tmp, block_size); AN_offd_data[i] = tmp; } AN_offd = hypre_CSRMatrixCreate(num_nodes, num_cols_offd, num_nonzeros_offd); hypre_CSRMatrixI(AN_offd) = AN_offd_i; hypre_CSRMatrixJ(AN_offd) = AN_offd_j; hypre_CSRMatrixData(AN_offd) = AN_offd_data; if (diag_option ==1 ) { /* make the diag entry the negative of the sum of off-diag entries (here we are adding the off_diag contribution)*/ /* the diagonal is the first element listed in each row of AN_diag_data - */ for (i=0; i < num_nodes; i++) { sum = 0.0; for (k = AN_offd_i[i]; k < AN_offd_i[i+1]; k++) { sum += AN_offd_data[k]; } index = AN_diag_i[i];/* location of diag entry in data */ AN_diag_data[index] -= sum; /* subtract from current value */ } } /* now create AN */ AN = hypre_ParCSRMatrixCreate(comm, global_num_nodes, global_num_nodes, row_starts_AN, row_starts_AN, num_cols_offd, num_nonzeros_diag, num_nonzeros_offd); /* we already created the diag and offd matrices - so we don't need the ones created above */ hypre_CSRMatrixDestroy(hypre_ParCSRMatrixDiag(AN)); hypre_CSRMatrixDestroy(hypre_ParCSRMatrixOffd(AN)); hypre_ParCSRMatrixDiag(AN) = AN_diag; hypre_ParCSRMatrixOffd(AN) = AN_offd; hypre_ParCSRMatrixColMapOffd(AN) = col_map_offd_AN; hypre_ParCSRMatrixCommPkg(AN) = comm_pkg_AN; *AN_ptr = AN; return (ierr); }