1 2 /* 3 Creates hypre ijmatrix from PETSc matrix 4 */ 5 6 #include <petscmathypre.h> 7 #include <petsc/private/matimpl.h> 8 #include <../src/mat/impls/hypre/mhypre.h> 9 #include <../src/mat/impls/aij/mpi/mpiaij.h> 10 #include <../src/vec/vec/impls/hypre/vhyp.h> 11 #include <HYPRE.h> 12 #include <HYPRE_utilities.h> 13 #include <_hypre_parcsr_ls.h> 14 #include <_hypre_sstruct_ls.h> 15 16 static PetscErrorCode MatHYPRE_CreateFromMat(Mat,Mat_HYPRE*); 17 static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat,Mat,HYPRE_IJMatrix); 18 static PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat,HYPRE_IJMatrix); 19 static PetscErrorCode MatHYPRE_IJMatrixFastCopy_SeqAIJ(Mat,HYPRE_IJMatrix); 20 static PetscErrorCode MatHYPRE_MultKernel_Private(Mat,Vec,Vec,PetscBool); 21 static PetscErrorCode hypre_array_destroy(void*); 22 PetscErrorCode MatSetValues_HYPRE(Mat, PetscInt,const PetscInt[],PetscInt,const PetscInt[],const PetscScalar[],InsertMode ins); 23 24 static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat A_d, Mat A_o, HYPRE_IJMatrix ij) 25 { 26 PetscErrorCode ierr; 27 PetscInt i,n_d,n_o; 28 const PetscInt *ia_d,*ia_o; 29 PetscBool done_d=PETSC_FALSE,done_o=PETSC_FALSE; 30 PetscInt *nnz_d=NULL,*nnz_o=NULL; 31 32 PetscFunctionBegin; 33 if (A_d) { /* determine number of nonzero entries in local diagonal part */ 34 ierr = MatGetRowIJ(A_d,0,PETSC_FALSE,PETSC_FALSE,&n_d,&ia_d,NULL,&done_d);CHKERRQ(ierr); 35 if (done_d) { 36 ierr = PetscMalloc1(n_d,&nnz_d);CHKERRQ(ierr); 37 for (i=0; i<n_d; i++) { 38 nnz_d[i] = ia_d[i+1] - ia_d[i]; 39 } 40 } 41 ierr = MatRestoreRowIJ(A_d,0,PETSC_FALSE,PETSC_FALSE,NULL,&ia_d,NULL,&done_d);CHKERRQ(ierr); 42 } 43 if (A_o) { /* determine number of nonzero entries in local off-diagonal part */ 44 ierr = MatGetRowIJ(A_o,0,PETSC_FALSE,PETSC_FALSE,&n_o,&ia_o,NULL,&done_o);CHKERRQ(ierr); 45 if (done_o) { 46 ierr = PetscMalloc1(n_o,&nnz_o);CHKERRQ(ierr); 47 for (i=0; i<n_o; i++) { 48 nnz_o[i] = ia_o[i+1] - ia_o[i]; 49 } 50 } 51 ierr = MatRestoreRowIJ(A_o,0,PETSC_FALSE,PETSC_FALSE,&n_o,&ia_o,NULL,&done_o);CHKERRQ(ierr); 52 } 53 if (done_d) { /* set number of nonzeros in HYPRE IJ matrix */ 54 if (!done_o) { /* only diagonal part */ 55 ierr = PetscMalloc1(n_d,&nnz_o);CHKERRQ(ierr); 56 for (i=0; i<n_d; i++) { 57 nnz_o[i] = 0; 58 } 59 } 60 PetscStackCallStandard(HYPRE_IJMatrixSetDiagOffdSizes,(ij,(HYPRE_Int *)nnz_d,(HYPRE_Int *)nnz_o)); 61 ierr = PetscFree(nnz_d);CHKERRQ(ierr); 62 ierr = PetscFree(nnz_o);CHKERRQ(ierr); 63 } 64 PetscFunctionReturn(0); 65 } 66 67 static PetscErrorCode MatHYPRE_CreateFromMat(Mat A, Mat_HYPRE *hA) 68 { 69 PetscErrorCode ierr; 70 PetscInt rstart,rend,cstart,cend; 71 72 PetscFunctionBegin; 73 ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 74 ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 75 rstart = A->rmap->rstart; 76 rend = A->rmap->rend; 77 cstart = A->cmap->rstart; 78 cend = A->cmap->rend; 79 PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rstart,rend-1,cstart,cend-1,&hA->ij)); 80 PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR)); 81 { 82 PetscBool same; 83 Mat A_d,A_o; 84 const PetscInt *colmap; 85 ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&same);CHKERRQ(ierr); 86 if (same) { 87 ierr = MatMPIAIJGetSeqAIJ(A,&A_d,&A_o,&colmap);CHKERRQ(ierr); 88 ierr = MatHYPRE_IJMatrixPreallocate(A_d,A_o,hA->ij);CHKERRQ(ierr); 89 PetscFunctionReturn(0); 90 } 91 ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&same);CHKERRQ(ierr); 92 if (same) { 93 ierr = MatMPIBAIJGetSeqBAIJ(A,&A_d,&A_o,&colmap);CHKERRQ(ierr); 94 ierr = MatHYPRE_IJMatrixPreallocate(A_d,A_o,hA->ij);CHKERRQ(ierr); 95 PetscFunctionReturn(0); 96 } 97 ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&same);CHKERRQ(ierr); 98 if (same) { 99 ierr = MatHYPRE_IJMatrixPreallocate(A,NULL,hA->ij);CHKERRQ(ierr); 100 PetscFunctionReturn(0); 101 } 102 ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQBAIJ,&same);CHKERRQ(ierr); 103 if (same) { 104 ierr = MatHYPRE_IJMatrixPreallocate(A,NULL,hA->ij);CHKERRQ(ierr); 105 PetscFunctionReturn(0); 106 } 107 } 108 PetscFunctionReturn(0); 109 } 110 111 static PetscErrorCode MatHYPRE_IJMatrixCopy(Mat A, HYPRE_IJMatrix ij) 112 { 113 PetscErrorCode ierr; 114 PetscInt i,rstart,rend,ncols,nr,nc; 115 const PetscScalar *values; 116 const PetscInt *cols; 117 PetscBool flg; 118 119 PetscFunctionBegin; 120 ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&flg);CHKERRQ(ierr); 121 ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr); 122 if (flg && nr == nc) { 123 ierr = MatHYPRE_IJMatrixFastCopy_MPIAIJ(A,ij);CHKERRQ(ierr); 124 PetscFunctionReturn(0); 125 } 126 ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&flg);CHKERRQ(ierr); 127 if (flg) { 128 ierr = MatHYPRE_IJMatrixFastCopy_SeqAIJ(A,ij);CHKERRQ(ierr); 129 PetscFunctionReturn(0); 130 } 131 132 PetscStackCallStandard(HYPRE_IJMatrixInitialize,(ij)); 133 ierr = MatGetOwnershipRange(A,&rstart,&rend);CHKERRQ(ierr); 134 for (i=rstart; i<rend; i++) { 135 ierr = MatGetRow(A,i,&ncols,&cols,&values);CHKERRQ(ierr); 136 if (ncols) { 137 PetscStackCallStandard(HYPRE_IJMatrixSetValues,(ij,1,(HYPRE_Int *)&ncols,(HYPRE_Int *)&i,(HYPRE_Int *)cols,values)); 138 } 139 ierr = MatRestoreRow(A,i,&ncols,&cols,&values);CHKERRQ(ierr); 140 } 141 PetscFunctionReturn(0); 142 } 143 144 static PetscErrorCode MatHYPRE_IJMatrixFastCopy_SeqAIJ(Mat A, HYPRE_IJMatrix ij) 145 { 146 PetscErrorCode ierr; 147 Mat_SeqAIJ *pdiag = (Mat_SeqAIJ*)A->data; 148 HYPRE_Int type; 149 hypre_ParCSRMatrix *par_matrix; 150 hypre_AuxParCSRMatrix *aux_matrix; 151 hypre_CSRMatrix *hdiag; 152 153 PetscFunctionBegin; 154 PetscStackCallStandard(HYPRE_IJMatrixInitialize,(ij)); 155 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(ij,&type)); 156 if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 157 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(ij,(void**)&par_matrix)); 158 hdiag = hypre_ParCSRMatrixDiag(par_matrix); 159 /* 160 this is the Hack part where we monkey directly with the hypre datastructures 161 */ 162 ierr = PetscMemcpy(hdiag->i,pdiag->i,(A->rmap->n + 1)*sizeof(PetscInt)); 163 ierr = PetscMemcpy(hdiag->j,pdiag->j,pdiag->nz*sizeof(PetscInt)); 164 ierr = PetscMemcpy(hdiag->data,pdiag->a,pdiag->nz*sizeof(PetscScalar)); 165 166 aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij); 167 hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0; 168 PetscFunctionReturn(0); 169 } 170 171 static PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat A, HYPRE_IJMatrix ij) 172 { 173 PetscErrorCode ierr; 174 Mat_MPIAIJ *pA = (Mat_MPIAIJ*)A->data; 175 Mat_SeqAIJ *pdiag,*poffd; 176 PetscInt i,*garray = pA->garray,*jj,cstart,*pjj; 177 HYPRE_Int type; 178 hypre_ParCSRMatrix *par_matrix; 179 hypre_AuxParCSRMatrix *aux_matrix; 180 hypre_CSRMatrix *hdiag,*hoffd; 181 182 PetscFunctionBegin; 183 pdiag = (Mat_SeqAIJ*) pA->A->data; 184 poffd = (Mat_SeqAIJ*) pA->B->data; 185 /* cstart is only valid for square MPIAIJ layed out in the usual way */ 186 ierr = MatGetOwnershipRange(A,&cstart,NULL);CHKERRQ(ierr); 187 188 PetscStackCallStandard(HYPRE_IJMatrixInitialize,(ij)); 189 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(ij,&type)); 190 if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 191 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(ij,(void**)&par_matrix)); 192 hdiag = hypre_ParCSRMatrixDiag(par_matrix); 193 hoffd = hypre_ParCSRMatrixOffd(par_matrix); 194 195 /* 196 this is the Hack part where we monkey directly with the hypre datastructures 197 */ 198 ierr = PetscMemcpy(hdiag->i,pdiag->i,(pA->A->rmap->n + 1)*sizeof(PetscInt)); 199 /* need to shift the diag column indices (hdiag->j) back to global numbering since hypre is expecting this */ 200 jj = (PetscInt*)hdiag->j; 201 pjj = (PetscInt*)pdiag->j; 202 for (i=0; i<pdiag->nz; i++) jj[i] = cstart + pjj[i]; 203 ierr = PetscMemcpy(hdiag->data,pdiag->a,pdiag->nz*sizeof(PetscScalar)); 204 ierr = PetscMemcpy(hoffd->i,poffd->i,(pA->A->rmap->n + 1)*sizeof(PetscInt)); 205 /* need to move the offd column indices (hoffd->j) back to global numbering since hypre is expecting this 206 If we hacked a hypre a bit more we might be able to avoid this step */ 207 jj = (PetscInt*) hoffd->j; 208 pjj = (PetscInt*) poffd->j; 209 for (i=0; i<poffd->nz; i++) jj[i] = garray[pjj[i]]; 210 ierr = PetscMemcpy(hoffd->data,poffd->a,poffd->nz*sizeof(PetscScalar)); 211 212 aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij); 213 hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0; 214 PetscFunctionReturn(0); 215 } 216 217 static PetscErrorCode MatConvert_HYPRE_IS(Mat A, MatType mtype, MatReuse reuse, Mat* B) 218 { 219 Mat_HYPRE* mhA = (Mat_HYPRE*)(A->data); 220 Mat lA; 221 ISLocalToGlobalMapping rl2g,cl2g; 222 IS is; 223 hypre_ParCSRMatrix *hA; 224 hypre_CSRMatrix *hdiag,*hoffd; 225 MPI_Comm comm; 226 PetscScalar *hdd,*hod,*aa,*data; 227 HYPRE_Int *col_map_offd,*hdi,*hdj,*hoi,*hoj; 228 PetscInt *ii,*jj,*iptr,*jptr; 229 PetscInt cum,dr,dc,oc,str,stc,nnz,i,jd,jo,M,N; 230 HYPRE_Int type; 231 PetscErrorCode ierr; 232 233 PetscFunctionBegin; 234 comm = PetscObjectComm((PetscObject)A); 235 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(mhA->ij,&type)); 236 if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 237 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(mhA->ij,(void**)&hA)); 238 M = hypre_ParCSRMatrixGlobalNumRows(hA); 239 N = hypre_ParCSRMatrixGlobalNumCols(hA); 240 str = hypre_ParCSRMatrixFirstRowIndex(hA); 241 stc = hypre_ParCSRMatrixFirstColDiag(hA); 242 hdiag = hypre_ParCSRMatrixDiag(hA); 243 hoffd = hypre_ParCSRMatrixOffd(hA); 244 dr = hypre_CSRMatrixNumRows(hdiag); 245 dc = hypre_CSRMatrixNumCols(hdiag); 246 nnz = hypre_CSRMatrixNumNonzeros(hdiag); 247 hdi = hypre_CSRMatrixI(hdiag); 248 hdj = hypre_CSRMatrixJ(hdiag); 249 hdd = hypre_CSRMatrixData(hdiag); 250 oc = hypre_CSRMatrixNumCols(hoffd); 251 nnz += hypre_CSRMatrixNumNonzeros(hoffd); 252 hoi = hypre_CSRMatrixI(hoffd); 253 hoj = hypre_CSRMatrixJ(hoffd); 254 hod = hypre_CSRMatrixData(hoffd); 255 if (reuse != MAT_REUSE_MATRIX) { 256 PetscInt *aux; 257 258 /* generate l2g maps for rows and cols */ 259 ierr = ISCreateStride(comm,dr,str,1,&is);CHKERRQ(ierr); 260 ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr); 261 ierr = ISDestroy(&is);CHKERRQ(ierr); 262 col_map_offd = hypre_ParCSRMatrixColMapOffd(hA); 263 ierr = PetscMalloc1(dc+oc,&aux);CHKERRQ(ierr); 264 for (i=0; i<dc; i++) aux[i] = i+stc; 265 for (i=0; i<oc; i++) aux[i+dc] = col_map_offd[i]; 266 ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 267 ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr); 268 ierr = ISDestroy(&is);CHKERRQ(ierr); 269 /* create MATIS object */ 270 ierr = MatCreate(comm,B);CHKERRQ(ierr); 271 ierr = MatSetSizes(*B,dr,dc,M,N);CHKERRQ(ierr); 272 ierr = MatSetType(*B,MATIS);CHKERRQ(ierr); 273 ierr = MatSetLocalToGlobalMapping(*B,rl2g,cl2g);CHKERRQ(ierr); 274 ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 275 ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 276 277 /* allocate CSR for local matrix */ 278 ierr = PetscMalloc1(dr+1,&iptr);CHKERRQ(ierr); 279 ierr = PetscMalloc1(nnz,&jptr);CHKERRQ(ierr); 280 ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr); 281 } else { 282 PetscInt nr; 283 PetscBool done; 284 ierr = MatISGetLocalMat(*B,&lA);CHKERRQ(ierr); 285 ierr = MatGetRowIJ(lA,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&iptr,(const PetscInt**)&jptr,&done);CHKERRQ(ierr); 286 if (nr != dr) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of rows in local mat! %D != %D",nr,dr); 287 if (iptr[nr] < nnz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of nonzeros in local mat! reuse %D requested %D",iptr[nr],nnz); 288 ierr = MatSeqAIJGetArray(lA,&data);CHKERRQ(ierr); 289 } 290 /* merge local matrices */ 291 ii = iptr; 292 jj = jptr; 293 aa = data; 294 *ii = *(hdi++) + *(hoi++); 295 for (jd=0,jo=0,cum=0; *ii<nnz; cum++) { 296 PetscScalar *aold = aa; 297 PetscInt *jold = jj,nc = jd+jo; 298 for (; jd<*hdi; jd++) { *jj++ = *hdj++; *aa++ = *hdd++; } 299 for (; jo<*hoi; jo++) { *jj++ = *hoj++ + dc; *aa++ = *hod++; } 300 *(++ii) = *(hdi++) + *(hoi++); 301 ierr = PetscSortIntWithScalarArray(jd+jo-nc,jold,aold);CHKERRQ(ierr); 302 } 303 for (; cum<dr; cum++) *(++ii) = nnz; 304 if (reuse != MAT_REUSE_MATRIX) { 305 Mat_SeqAIJ* a; 306 307 ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,dc+oc,iptr,jptr,data,&lA);CHKERRQ(ierr); 308 ierr = MatISSetLocalMat(*B,lA);CHKERRQ(ierr); 309 /* hack SeqAIJ */ 310 a = (Mat_SeqAIJ*)(lA->data); 311 a->free_a = PETSC_TRUE; 312 a->free_ij = PETSC_TRUE; 313 ierr = MatDestroy(&lA);CHKERRQ(ierr); 314 } 315 ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 316 ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 317 if (reuse == MAT_INPLACE_MATRIX) { 318 ierr = MatHeaderReplace(A,B);CHKERRQ(ierr); 319 } 320 PetscFunctionReturn(0); 321 } 322 323 PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B) 324 { 325 Mat_HYPRE *hB; 326 MPI_Comm comm = PetscObjectComm((PetscObject)A); 327 PetscErrorCode ierr; 328 329 PetscFunctionBegin; 330 if (reuse == MAT_INPLACE_MATRIX) SETERRQ(comm,PETSC_ERR_SUP,"Unsupported MAT_INPLACE_MATRIX"); 331 if (reuse == MAT_REUSE_MATRIX) { 332 /* always destroy the old matrix and create a new memory; 333 hope this does not churn the memory too much. The problem 334 is I do not know if it is possible to put the matrix back to 335 its initial state so that we can directly copy the values 336 the second time through. */ 337 hB = (Mat_HYPRE*)((*B)->data); 338 PetscStackCallStandard(HYPRE_IJMatrixDestroy,(hB->ij)); 339 } else { 340 ierr = MatCreate(comm,B);CHKERRQ(ierr); 341 ierr = MatSetType(*B,MATHYPRE);CHKERRQ(ierr); 342 ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 343 hB = (Mat_HYPRE*)((*B)->data); 344 } 345 ierr = MatHYPRE_CreateFromMat(A,hB);CHKERRQ(ierr); 346 ierr = MatHYPRE_IJMatrixCopy(A,hB->ij);CHKERRQ(ierr); 347 (*B)->preallocated = PETSC_TRUE; 348 ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 349 ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 350 PetscFunctionReturn(0); 351 } 352 353 static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B) 354 { 355 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 356 hypre_ParCSRMatrix *parcsr; 357 hypre_CSRMatrix *hdiag,*hoffd; 358 MPI_Comm comm; 359 PetscScalar *da,*oa,*aptr; 360 PetscInt *dii,*djj,*oii,*ojj,*iptr; 361 PetscInt i,dnnz,onnz,m,n; 362 HYPRE_Int type; 363 PetscMPIInt size; 364 PetscErrorCode ierr; 365 366 PetscFunctionBegin; 367 comm = PetscObjectComm((PetscObject)A); 368 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type)); 369 if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 370 if (reuse == MAT_REUSE_MATRIX) { 371 PetscBool ismpiaij,isseqaij; 372 ierr = PetscObjectTypeCompare((PetscObject)*B,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr); 373 ierr = PetscObjectBaseTypeCompare((PetscObject)*B,MATSEQAIJ,&isseqaij);CHKERRQ(ierr); 374 if (!ismpiaij && !isseqaij) SETERRQ(comm,PETSC_ERR_SUP,"Only MATMPIAIJ or MATSEQAIJ are supported"); 375 } 376 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 377 378 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr)); 379 hdiag = hypre_ParCSRMatrixDiag(parcsr); 380 hoffd = hypre_ParCSRMatrixOffd(parcsr); 381 m = hypre_CSRMatrixNumRows(hdiag); 382 n = hypre_CSRMatrixNumCols(hdiag); 383 dnnz = hypre_CSRMatrixNumNonzeros(hdiag); 384 onnz = hypre_CSRMatrixNumNonzeros(hoffd); 385 if (reuse == MAT_INITIAL_MATRIX) { 386 ierr = PetscMalloc1(m+1,&dii);CHKERRQ(ierr); 387 ierr = PetscMalloc1(dnnz,&djj);CHKERRQ(ierr); 388 ierr = PetscMalloc1(dnnz,&da);CHKERRQ(ierr); 389 } else if (reuse == MAT_REUSE_MATRIX) { 390 PetscInt nr; 391 PetscBool done; 392 if (size > 1) { 393 Mat_MPIAIJ *b = (Mat_MPIAIJ*)((*B)->data); 394 395 ierr = MatGetRowIJ(b->A,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&dii,(const PetscInt**)&djj,&done);CHKERRQ(ierr); 396 if (nr != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of local rows in diag part! %D != %D",nr,m); 397 if (dii[nr] < dnnz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of nonzeros in diag part! reuse %D hypre %D",dii[nr],dnnz); 398 ierr = MatSeqAIJGetArray(b->A,&da);CHKERRQ(ierr); 399 } else { 400 ierr = MatGetRowIJ(*B,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&dii,(const PetscInt**)&djj,&done);CHKERRQ(ierr); 401 if (nr != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of local rows! %D != %D",nr,m); 402 if (dii[nr] < dnnz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of nonzeros! reuse %D hypre %D",dii[nr],dnnz); 403 ierr = MatSeqAIJGetArray(*B,&da);CHKERRQ(ierr); 404 } 405 } else { /* MAT_INPLACE_MATRIX */ 406 dii = (PetscInt*)hypre_CSRMatrixI(hdiag); 407 djj = (PetscInt*)hypre_CSRMatrixJ(hdiag); 408 da = hypre_CSRMatrixData(hdiag); 409 } 410 ierr = PetscMemcpy(dii,hypre_CSRMatrixI(hdiag),(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 411 ierr = PetscMemcpy(djj,hypre_CSRMatrixJ(hdiag),dnnz*sizeof(PetscInt));CHKERRQ(ierr); 412 ierr = PetscMemcpy(da,hypre_CSRMatrixData(hdiag),dnnz*sizeof(PetscScalar));CHKERRQ(ierr); 413 iptr = djj; 414 aptr = da; 415 for (i=0; i<m; i++) { 416 PetscInt nc = dii[i+1]-dii[i]; 417 ierr = PetscSortIntWithScalarArray(nc,iptr,aptr);CHKERRQ(ierr); 418 iptr += nc; 419 aptr += nc; 420 } 421 if (size > 1) { 422 HYPRE_Int *offdj,*coffd; 423 424 if (reuse == MAT_INITIAL_MATRIX) { 425 ierr = PetscMalloc1(m+1,&oii);CHKERRQ(ierr); 426 ierr = PetscMalloc1(onnz,&ojj);CHKERRQ(ierr); 427 ierr = PetscMalloc1(onnz,&oa);CHKERRQ(ierr); 428 } else if (reuse == MAT_REUSE_MATRIX) { 429 Mat_MPIAIJ *b = (Mat_MPIAIJ*)((*B)->data); 430 PetscInt nr,hr = hypre_CSRMatrixNumRows(hoffd); 431 PetscBool done; 432 433 ierr = MatGetRowIJ(b->B,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&oii,(const PetscInt**)&ojj,&done);CHKERRQ(ierr); 434 if (nr != hr) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of local rows in offdiag part! %D != %D",nr,hr); 435 if (oii[nr] < onnz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of nonzeros in offdiag part! reuse %D hypre %D",oii[nr],onnz); 436 ierr = MatSeqAIJGetArray(b->B,&oa);CHKERRQ(ierr); 437 } else { /* MAT_INPLACE_MATRIX */ 438 oii = (PetscInt*)hypre_CSRMatrixI(hoffd); 439 ojj = (PetscInt*)hypre_CSRMatrixJ(hoffd); 440 oa = hypre_CSRMatrixData(hoffd); 441 } 442 ierr = PetscMemcpy(oii,hypre_CSRMatrixI(hoffd),(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 443 offdj = hypre_CSRMatrixJ(hoffd); 444 coffd = hypre_ParCSRMatrixColMapOffd(parcsr); 445 for (i=0; i<onnz; i++) ojj[i] = coffd[offdj[i]]; 446 ierr = PetscMemcpy(oa,hypre_CSRMatrixData(hoffd),onnz*sizeof(PetscScalar));CHKERRQ(ierr); 447 iptr = ojj; 448 aptr = oa; 449 for (i=0; i<m; i++) { 450 PetscInt nc = oii[i+1]-oii[i]; 451 ierr = PetscSortIntWithScalarArray(nc,iptr,aptr);CHKERRQ(ierr); 452 iptr += nc; 453 aptr += nc; 454 } 455 if (reuse == MAT_INITIAL_MATRIX) { 456 Mat_MPIAIJ *b; 457 Mat_SeqAIJ *d,*o; 458 459 ierr = MatCreateMPIAIJWithSplitArrays(comm,m,n,PETSC_DECIDE,PETSC_DECIDE,dii,djj,da,oii,ojj,oa,B);CHKERRQ(ierr); 460 /* hack MPIAIJ */ 461 b = (Mat_MPIAIJ*)((*B)->data); 462 d = (Mat_SeqAIJ*)b->A->data; 463 o = (Mat_SeqAIJ*)b->B->data; 464 d->free_a = PETSC_TRUE; 465 d->free_ij = PETSC_TRUE; 466 o->free_a = PETSC_TRUE; 467 o->free_ij = PETSC_TRUE; 468 } else if (reuse == MAT_INPLACE_MATRIX) { 469 Mat T; 470 ierr = MatCreateMPIAIJWithSplitArrays(comm,m,n,PETSC_DECIDE,PETSC_DECIDE,dii,djj,da,oii,ojj,oa,&T);CHKERRQ(ierr); 471 hypre_CSRMatrixI(hdiag) = NULL; 472 hypre_CSRMatrixJ(hdiag) = NULL; 473 hypre_CSRMatrixData(hdiag) = NULL; 474 hypre_CSRMatrixI(hoffd) = NULL; 475 hypre_CSRMatrixJ(hoffd) = NULL; 476 hypre_CSRMatrixData(hoffd) = NULL; 477 ierr = MatHeaderReplace(A,&T);CHKERRQ(ierr); 478 } 479 } else { 480 oii = NULL; 481 ojj = NULL; 482 oa = NULL; 483 if (reuse == MAT_INITIAL_MATRIX) { 484 Mat_SeqAIJ* b; 485 ierr = MatCreateSeqAIJWithArrays(comm,m,n,dii,djj,da,B);CHKERRQ(ierr); 486 /* hack SeqAIJ */ 487 b = (Mat_SeqAIJ*)((*B)->data); 488 b->free_a = PETSC_TRUE; 489 b->free_ij = PETSC_TRUE; 490 } else if (reuse == MAT_INPLACE_MATRIX) { 491 Mat T; 492 ierr = MatCreateSeqAIJWithArrays(comm,m,n,dii,djj,da,&T);CHKERRQ(ierr); 493 hypre_CSRMatrixI(hdiag) = NULL; 494 hypre_CSRMatrixJ(hdiag) = NULL; 495 hypre_CSRMatrixData(hdiag) = NULL; 496 ierr = MatHeaderReplace(A,&T);CHKERRQ(ierr); 497 } 498 } 499 500 /* we have to use hypre_Tfree to free the arrays */ 501 if (reuse == MAT_INPLACE_MATRIX) { 502 void *ptrs[6] = {dii,djj,da,oii,ojj,oa}; 503 const char *names[6] = {"_hypre_csr_dii", 504 "_hypre_csr_djj", 505 "_hypre_csr_da", 506 "_hypre_csr_oii", 507 "_hypre_csr_ojj", 508 "_hypre_csr_oa"}; 509 for (i=0; i<6; i++) { 510 PetscContainer c; 511 512 ierr = PetscContainerCreate(comm,&c);CHKERRQ(ierr); 513 ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr); 514 ierr = PetscContainerSetUserDestroy(c,hypre_array_destroy);CHKERRQ(ierr); 515 ierr = PetscObjectCompose((PetscObject)(*B),names[i],(PetscObject)c);CHKERRQ(ierr); 516 ierr = PetscContainerDestroy(&c);CHKERRQ(ierr); 517 } 518 } 519 PetscFunctionReturn(0); 520 } 521 522 static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA) 523 { 524 hypre_ParCSRMatrix *tA; 525 hypre_CSRMatrix *hdiag,*hoffd; 526 Mat_SeqAIJ *diag,*offd; 527 PetscInt *garray,noffd,dnnz,onnz,*row_starts,*col_starts; 528 MPI_Comm comm = PetscObjectComm((PetscObject)A); 529 PetscBool ismpiaij,isseqaij; 530 PetscErrorCode ierr; 531 532 PetscFunctionBegin; 533 ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr); 534 ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr); 535 if (!ismpiaij && !isseqaij) SETERRQ1(comm,PETSC_ERR_SUP,"Unsupported type %s",((PetscObject)A)->type); 536 if (ismpiaij) { 537 Mat_MPIAIJ *a = (Mat_MPIAIJ*)(A->data); 538 539 diag = (Mat_SeqAIJ*)a->A->data; 540 offd = (Mat_SeqAIJ*)a->B->data; 541 garray = a->garray; 542 noffd = a->B->cmap->N; 543 dnnz = diag->nz; 544 onnz = offd->nz; 545 } else { 546 diag = (Mat_SeqAIJ*)A->data; 547 offd = NULL; 548 garray = NULL; 549 noffd = 0; 550 dnnz = diag->nz; 551 onnz = 0; 552 } 553 554 /* create a temporary ParCSR */ 555 if (HYPRE_AssumedPartitionCheck()) { 556 PetscMPIInt myid; 557 558 ierr = MPI_Comm_rank(comm,&myid);CHKERRQ(ierr); 559 row_starts = A->rmap->range + myid; 560 col_starts = A->cmap->range + myid; 561 } else { 562 row_starts = A->rmap->range; 563 col_starts = A->cmap->range; 564 } 565 tA = hypre_ParCSRMatrixCreate(comm,A->rmap->N,A->cmap->N,(HYPRE_Int*)row_starts,(HYPRE_Int*)col_starts,noffd,dnnz,onnz); 566 hypre_ParCSRMatrixSetRowStartsOwner(tA,0); 567 hypre_ParCSRMatrixSetColStartsOwner(tA,0); 568 569 /* set diagonal part */ 570 hdiag = hypre_ParCSRMatrixDiag(tA); 571 hypre_CSRMatrixI(hdiag) = (HYPRE_Int*)diag->i; 572 hypre_CSRMatrixJ(hdiag) = (HYPRE_Int*)diag->j; 573 hypre_CSRMatrixData(hdiag) = diag->a; 574 hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz; 575 hypre_CSRMatrixSetRownnz(hdiag); 576 hypre_CSRMatrixSetDataOwner(hdiag,0); 577 578 /* set offdiagonal part */ 579 hoffd = hypre_ParCSRMatrixOffd(tA); 580 if (offd) { 581 hypre_CSRMatrixI(hoffd) = (HYPRE_Int*)offd->i; 582 hypre_CSRMatrixJ(hoffd) = (HYPRE_Int*)offd->j; 583 hypre_CSRMatrixData(hoffd) = offd->a; 584 hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz; 585 hypre_CSRMatrixSetRownnz(hoffd); 586 hypre_CSRMatrixSetDataOwner(hoffd,0); 587 hypre_ParCSRMatrixSetNumNonzeros(tA); 588 hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_Int*)garray; 589 } 590 *hA = tA; 591 PetscFunctionReturn(0); 592 } 593 594 static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA) 595 { 596 hypre_CSRMatrix *hdiag,*hoffd; 597 598 PetscFunctionBegin; 599 hdiag = hypre_ParCSRMatrixDiag(*hA); 600 hoffd = hypre_ParCSRMatrixOffd(*hA); 601 /* set pointers to NULL before destroying tA */ 602 hypre_CSRMatrixI(hdiag) = NULL; 603 hypre_CSRMatrixJ(hdiag) = NULL; 604 hypre_CSRMatrixData(hdiag) = NULL; 605 hypre_CSRMatrixI(hoffd) = NULL; 606 hypre_CSRMatrixJ(hoffd) = NULL; 607 hypre_CSRMatrixData(hoffd) = NULL; 608 hypre_ParCSRMatrixColMapOffd(*hA) = NULL; 609 hypre_ParCSRMatrixDestroy(*hA); 610 *hA = NULL; 611 PetscFunctionReturn(0); 612 } 613 614 /* calls RAP from BoomerAMG: 615 the resulting ParCSR will not own the column and row starts 616 It looks like we don't need to have the diagonal entries 617 ordered first in the rows of the diagonal part 618 for boomerAMGBuildCoarseOperator to work */ 619 static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA,hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP) 620 { 621 PetscErrorCode ierr; 622 HYPRE_Int P_owns_col_starts,R_owns_row_starts; 623 624 PetscFunctionBegin; 625 P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP); 626 R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR); 627 PetscStackCallStandard(hypre_BoomerAMGBuildCoarseOperator,(hR,hA,hP,hRAP)); 628 PetscStackCallStandard(hypre_ParCSRMatrixSetNumNonzeros,(*hRAP)); 629 /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */ 630 hypre_ParCSRMatrixSetRowStartsOwner(*hRAP,0); 631 hypre_ParCSRMatrixSetColStartsOwner(*hRAP,0); 632 if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP,1); 633 if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR,1); 634 PetscFunctionReturn(0); 635 } 636 637 static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A,Mat P,Mat C) 638 { 639 Mat B; 640 hypre_ParCSRMatrix *hA,*hP,*hPtAP; 641 PetscErrorCode ierr; 642 643 PetscFunctionBegin; 644 ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr); 645 ierr = MatAIJGetParCSR_Private(P,&hP);CHKERRQ(ierr); 646 ierr = MatHYPRE_ParCSR_RAP(hP,hA,hP,&hPtAP);CHKERRQ(ierr); 647 ierr = MatCreateFromParCSR(hPtAP,MATAIJ,PETSC_OWN_POINTER,&B);CHKERRQ(ierr); 648 ierr = MatHeaderMerge(C,&B);CHKERRQ(ierr); 649 ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr); 650 ierr = MatAIJRestoreParCSR_Private(P,&hP);CHKERRQ(ierr); 651 PetscFunctionReturn(0); 652 } 653 654 PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A,Mat P,PetscReal fill,Mat *C) 655 { 656 PetscErrorCode ierr; 657 658 PetscFunctionBegin; 659 ierr = MatCreate(PetscObjectComm((PetscObject)A),C);CHKERRQ(ierr); 660 ierr = MatSetType(*C,MATAIJ);CHKERRQ(ierr); 661 (*C)->ops->ptapnumeric = MatPtAPNumeric_AIJ_AIJ_wHYPRE; 662 PetscFunctionReturn(0); 663 } 664 665 static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A,Mat P,Mat C) 666 { 667 Mat B; 668 Mat_HYPRE *hP; 669 hypre_ParCSRMatrix *hA = NULL,*Pparcsr,*ptapparcsr; 670 HYPRE_Int type; 671 MPI_Comm comm = PetscObjectComm((PetscObject)A); 672 PetscBool ishypre; 673 PetscErrorCode ierr; 674 675 PetscFunctionBegin; 676 ierr = PetscObjectTypeCompare((PetscObject)P,MATHYPRE,&ishypre);CHKERRQ(ierr); 677 if (!ishypre) SETERRQ1(comm,PETSC_ERR_USER,"P should be of type %s",MATHYPRE); 678 hP = (Mat_HYPRE*)P->data; 679 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hP->ij,&type)); 680 if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 681 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hP->ij,(void**)&Pparcsr)); 682 683 ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr); 684 ierr = MatHYPRE_ParCSR_RAP(Pparcsr,hA,Pparcsr,&ptapparcsr);CHKERRQ(ierr); 685 ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr); 686 687 /* create temporary matrix and merge to C */ 688 ierr = MatCreateFromParCSR(ptapparcsr,((PetscObject)C)->type_name,PETSC_OWN_POINTER,&B);CHKERRQ(ierr); 689 ierr = MatHeaderMerge(C,&B);CHKERRQ(ierr); 690 PetscFunctionReturn(0); 691 } 692 693 static PetscErrorCode MatPtAP_AIJ_HYPRE(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C) 694 { 695 PetscErrorCode ierr; 696 697 PetscFunctionBegin; 698 if (scall == MAT_INITIAL_MATRIX) { 699 const char *deft = MATAIJ; 700 char type[256]; 701 PetscBool flg; 702 703 ierr = PetscObjectOptionsBegin((PetscObject)A);CHKERRQ(ierr); 704 ierr = PetscOptionsFList("-matptap_hypre_outtype","Matrix type",NULL,MatList,deft,type,256,&flg);CHKERRQ(ierr); 705 ierr = PetscOptionsEnd();CHKERRQ(ierr); 706 ierr = PetscLogEventBegin(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr); 707 ierr = MatCreate(PetscObjectComm((PetscObject)A),C);CHKERRQ(ierr); 708 if (flg) { 709 ierr = MatSetType(*C,type);CHKERRQ(ierr); 710 } else { 711 ierr = MatSetType(*C,deft);CHKERRQ(ierr); 712 } 713 (*C)->ops->ptapnumeric = MatPtAPNumeric_AIJ_HYPRE; 714 ierr = PetscLogEventEnd(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr); 715 } 716 ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 717 ierr = (*(*C)->ops->ptapnumeric)(A,P,*C);CHKERRQ(ierr); 718 ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 719 PetscFunctionReturn(0); 720 } 721 722 static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A,Mat P,Mat C) 723 { 724 Mat B; 725 hypre_ParCSRMatrix *Aparcsr,*Pparcsr,*ptapparcsr; 726 Mat_HYPRE *hA,*hP; 727 PetscBool ishypre; 728 HYPRE_Int type; 729 PetscErrorCode ierr; 730 731 PetscFunctionBegin; 732 ierr = PetscObjectTypeCompare((PetscObject)P,MATHYPRE,&ishypre);CHKERRQ(ierr); 733 if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)P),PETSC_ERR_USER,"P should be of type %s",MATHYPRE); 734 ierr = PetscObjectTypeCompare((PetscObject)A,MATHYPRE,&ishypre);CHKERRQ(ierr); 735 if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"A should be of type %s",MATHYPRE); 736 hA = (Mat_HYPRE*)A->data; 737 hP = (Mat_HYPRE*)P->data; 738 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type)); 739 if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 740 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hP->ij,&type)); 741 if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)P),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 742 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&Aparcsr)); 743 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hP->ij,(void**)&Pparcsr)); 744 ierr = MatHYPRE_ParCSR_RAP(Pparcsr,Aparcsr,Pparcsr,&ptapparcsr);CHKERRQ(ierr); 745 ierr = MatCreateFromParCSR(ptapparcsr,MATHYPRE,PETSC_OWN_POINTER,&B);CHKERRQ(ierr); 746 ierr = MatHeaderMerge(C,&B);CHKERRQ(ierr); 747 PetscFunctionReturn(0); 748 } 749 750 static PetscErrorCode MatPtAP_HYPRE_HYPRE(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C) 751 { 752 PetscErrorCode ierr; 753 754 PetscFunctionBegin; 755 if (scall == MAT_INITIAL_MATRIX) { 756 ierr = PetscLogEventBegin(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr); 757 ierr = MatCreate(PetscObjectComm((PetscObject)A),C);CHKERRQ(ierr); 758 ierr = MatSetType(*C,MATHYPRE);CHKERRQ(ierr); 759 (*C)->ops->ptapnumeric = MatPtAPNumeric_HYPRE_HYPRE; 760 ierr = PetscLogEventEnd(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr); 761 } 762 ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 763 ierr = (*(*C)->ops->ptapnumeric)(A,P,*C);CHKERRQ(ierr); 764 ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 765 PetscFunctionReturn(0); 766 } 767 768 /* calls hypre_ParMatmul 769 hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA 770 hypre_ParMatrixCreate does not duplicate the communicator 771 It looks like we don't need to have the diagonal entries 772 ordered first in the rows of the diagonal part 773 for boomerAMGBuildCoarseOperator to work */ 774 static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB) 775 { 776 PetscFunctionBegin; 777 PetscStackPush("hypre_ParMatmul"); 778 *hAB = hypre_ParMatmul(hA,hB); 779 PetscStackPop; 780 PetscFunctionReturn(0); 781 } 782 783 static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A,Mat B,Mat C) 784 { 785 Mat D; 786 hypre_ParCSRMatrix *hA,*hB,*hAB = NULL; 787 PetscErrorCode ierr; 788 789 PetscFunctionBegin; 790 ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr); 791 ierr = MatAIJGetParCSR_Private(B,&hB);CHKERRQ(ierr); 792 ierr = MatHYPRE_ParCSR_MatMatMult(hA,hB,&hAB);CHKERRQ(ierr); 793 ierr = MatCreateFromParCSR(hAB,MATAIJ,PETSC_OWN_POINTER,&D);CHKERRQ(ierr); 794 ierr = MatHeaderMerge(C,&D);CHKERRQ(ierr); 795 ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr); 796 ierr = MatAIJRestoreParCSR_Private(B,&hB);CHKERRQ(ierr); 797 PetscFunctionReturn(0); 798 } 799 800 PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A,Mat B,PetscReal fill,Mat *C) 801 { 802 PetscErrorCode ierr; 803 804 PetscFunctionBegin; 805 ierr = MatCreate(PetscObjectComm((PetscObject)A),C);CHKERRQ(ierr); 806 ierr = MatSetType(*C,MATAIJ);CHKERRQ(ierr); 807 (*C)->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE; 808 PetscFunctionReturn(0); 809 } 810 811 static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A,Mat B,Mat C) 812 { 813 Mat D; 814 hypre_ParCSRMatrix *Aparcsr,*Bparcsr,*ABparcsr = NULL; 815 Mat_HYPRE *hA,*hB; 816 PetscBool ishypre; 817 HYPRE_Int type; 818 PetscErrorCode ierr; 819 820 PetscFunctionBegin; 821 ierr = PetscObjectTypeCompare((PetscObject)B,MATHYPRE,&ishypre);CHKERRQ(ierr); 822 if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)B),PETSC_ERR_USER,"B should be of type %s",MATHYPRE); 823 ierr = PetscObjectTypeCompare((PetscObject)A,MATHYPRE,&ishypre);CHKERRQ(ierr); 824 if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"A should be of type %s",MATHYPRE); 825 hA = (Mat_HYPRE*)A->data; 826 hB = (Mat_HYPRE*)B->data; 827 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type)); 828 if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 829 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hB->ij,&type)); 830 if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 831 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&Aparcsr)); 832 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hB->ij,(void**)&Bparcsr)); 833 ierr = MatHYPRE_ParCSR_MatMatMult(Aparcsr,Bparcsr,&ABparcsr);CHKERRQ(ierr); 834 ierr = MatCreateFromParCSR(ABparcsr,MATHYPRE,PETSC_OWN_POINTER,&D);CHKERRQ(ierr); 835 /* need to use HeaderReplace because HeaderMerge messes up with the communicator */ 836 ierr = MatHeaderReplace(C,&D);CHKERRQ(ierr); 837 C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE; 838 PetscFunctionReturn(0); 839 } 840 841 static PetscErrorCode MatMatMult_HYPRE_HYPRE(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C) 842 { 843 PetscErrorCode ierr; 844 845 PetscFunctionBegin; 846 if (scall == MAT_INITIAL_MATRIX) { 847 ierr = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 848 ierr = MatCreate(PetscObjectComm((PetscObject)A),C);CHKERRQ(ierr); 849 ierr = MatSetType(*C,MATHYPRE);CHKERRQ(ierr); 850 (*C)->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE; 851 ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 852 } 853 ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 854 ierr = (*(*C)->ops->matmultnumeric)(A,B,*C);CHKERRQ(ierr); 855 ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 856 PetscFunctionReturn(0); 857 } 858 859 PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A,Mat B,Mat C,Mat D) 860 { 861 Mat E; 862 hypre_ParCSRMatrix *hA,*hB,*hC,*hABC; 863 PetscErrorCode ierr; 864 865 PetscFunctionBegin; 866 ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr); 867 ierr = MatAIJGetParCSR_Private(B,&hB);CHKERRQ(ierr); 868 ierr = MatAIJGetParCSR_Private(C,&hC);CHKERRQ(ierr); 869 ierr = MatHYPRE_ParCSR_RAP(hA,hB,hC,&hABC);CHKERRQ(ierr); 870 ierr = MatCreateFromParCSR(hABC,MATAIJ,PETSC_OWN_POINTER,&E);CHKERRQ(ierr); 871 ierr = MatHeaderMerge(D,&E);CHKERRQ(ierr); 872 ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr); 873 ierr = MatAIJRestoreParCSR_Private(B,&hB);CHKERRQ(ierr); 874 ierr = MatAIJRestoreParCSR_Private(C,&hC);CHKERRQ(ierr); 875 PetscFunctionReturn(0); 876 } 877 878 PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A,Mat B,Mat C,PetscReal fill,Mat *D) 879 { 880 PetscErrorCode ierr; 881 882 PetscFunctionBegin; 883 ierr = MatCreate(PetscObjectComm((PetscObject)A),D);CHKERRQ(ierr); 884 ierr = MatSetType(*D,MATAIJ);CHKERRQ(ierr); 885 PetscFunctionReturn(0); 886 } 887 888 static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y) 889 { 890 PetscErrorCode ierr; 891 892 PetscFunctionBegin; 893 ierr = MatHYPRE_MultKernel_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr); 894 PetscFunctionReturn(0); 895 } 896 897 static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y) 898 { 899 PetscErrorCode ierr; 900 901 PetscFunctionBegin; 902 ierr = MatHYPRE_MultKernel_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr); 903 PetscFunctionReturn(0); 904 } 905 906 static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, Vec x, Vec y, PetscBool trans) 907 { 908 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 909 hypre_ParCSRMatrix *parcsr; 910 hypre_ParVector *hx,*hy; 911 PetscScalar *ax,*ay,*sax,*say; 912 PetscErrorCode ierr; 913 914 PetscFunctionBegin; 915 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr)); 916 PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->x,(void**)&hx)); 917 PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->b,(void**)&hy)); 918 ierr = VecGetArrayRead(x,(const PetscScalar**)&ax);CHKERRQ(ierr); 919 ierr = VecGetArray(y,&ay);CHKERRQ(ierr); 920 if (trans) { 921 VecHYPRE_ParVectorReplacePointer(hA->x,ay,say); 922 VecHYPRE_ParVectorReplacePointer(hA->b,ax,sax); 923 hypre_ParCSRMatrixMatvecT(1.,parcsr,hy,0.,hx); 924 VecHYPRE_ParVectorReplacePointer(hA->x,say,ay); 925 VecHYPRE_ParVectorReplacePointer(hA->b,sax,ax); 926 } else { 927 VecHYPRE_ParVectorReplacePointer(hA->x,ax,sax); 928 VecHYPRE_ParVectorReplacePointer(hA->b,ay,say); 929 hypre_ParCSRMatrixMatvec(1.,parcsr,hx,0.,hy); 930 VecHYPRE_ParVectorReplacePointer(hA->x,sax,ax); 931 VecHYPRE_ParVectorReplacePointer(hA->b,say,ay); 932 } 933 ierr = VecRestoreArrayRead(x,(const PetscScalar**)&ax);CHKERRQ(ierr); 934 ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr); 935 PetscFunctionReturn(0); 936 } 937 938 static PetscErrorCode MatDestroy_HYPRE(Mat A) 939 { 940 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 941 PetscErrorCode ierr; 942 943 PetscFunctionBegin; 944 if (hA->x) PetscStackCallStandard(HYPRE_IJVectorDestroy,(hA->x)); 945 if (hA->b) PetscStackCallStandard(HYPRE_IJVectorDestroy,(hA->b)); 946 if (hA->ij) { 947 if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL; 948 PetscStackCallStandard(HYPRE_IJMatrixDestroy,(hA->ij)); 949 } 950 if (hA->comm) { ierr = MPI_Comm_free(&hA->comm);CHKERRQ(ierr); } 951 952 ierr = MatStashDestroy_Private(&A->stash);CHKERRQ(ierr); 953 954 ierr = PetscFree(hA->array);CHKERRQ(ierr); 955 956 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_hypre_aij_C",NULL);CHKERRQ(ierr); 957 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_hypre_is_C",NULL);CHKERRQ(ierr); 958 ierr = PetscObjectComposeFunction((PetscObject)A,"MatPtAP_seqaij_hypre_C",NULL);CHKERRQ(ierr); 959 ierr = PetscObjectComposeFunction((PetscObject)A,"MatPtAP_mpiaij_hypre_C",NULL);CHKERRQ(ierr); 960 ierr = PetscObjectComposeFunction((PetscObject)A,"MatHYPRESetPreallocation_C",NULL);CHKERRQ(ierr); 961 ierr = PetscObjectComposeFunction((PetscObject)A,"MatHYPREGetParCSR_C",NULL);CHKERRQ(ierr); 962 ierr = PetscFree(A->data);CHKERRQ(ierr); 963 PetscFunctionReturn(0); 964 } 965 966 static PetscErrorCode MatSetUp_HYPRE(Mat A) 967 { 968 PetscErrorCode ierr; 969 970 PetscFunctionBegin; 971 ierr = MatHYPRESetPreallocation(A,PETSC_DEFAULT,NULL,PETSC_DEFAULT,NULL);CHKERRQ(ierr); 972 PetscFunctionReturn(0); 973 } 974 975 976 static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode) 977 { 978 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 979 Vec x,b; 980 PetscMPIInt n; 981 PetscInt i,j,rstart,ncols,flg; 982 PetscInt *row,*col; 983 PetscScalar *val; 984 PetscErrorCode ierr; 985 986 PetscFunctionBegin; 987 if (mode == MAT_FLUSH_ASSEMBLY) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE"); 988 989 if (!A->nooffprocentries) { 990 while (1) { 991 ierr = MatStashScatterGetMesg_Private(&A->stash,&n,&row,&col,&val,&flg);CHKERRQ(ierr); 992 if (!flg) break; 993 994 for (i=0; i<n; ) { 995 /* Now identify the consecutive vals belonging to the same row */ 996 for (j=i,rstart=row[j]; j<n; j++) { 997 if (row[j] != rstart) break; 998 } 999 if (j < n) ncols = j-i; 1000 else ncols = n-i; 1001 /* Now assemble all these values with a single function call */ 1002 ierr = MatSetValues_HYPRE(A,1,row+i,ncols,col+i,val+i,A->insertmode);CHKERRQ(ierr); 1003 1004 i = j; 1005 } 1006 } 1007 ierr = MatStashScatterEnd_Private(&A->stash);CHKERRQ(ierr); 1008 } 1009 1010 PetscStackCallStandard(HYPRE_IJMatrixAssemble,(hA->ij)); 1011 if (hA->x) PetscFunctionReturn(0); 1012 ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 1013 ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 1014 ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)A),1,A->cmap->n,A->cmap->N,NULL,&x);CHKERRQ(ierr); 1015 ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)A),1,A->rmap->n,A->rmap->N,NULL,&b);CHKERRQ(ierr); 1016 ierr = VecHYPRE_IJVectorCreate(x,&hA->x);CHKERRQ(ierr); 1017 ierr = VecHYPRE_IJVectorCreate(b,&hA->b);CHKERRQ(ierr); 1018 ierr = VecDestroy(&x);CHKERRQ(ierr); 1019 ierr = VecDestroy(&b);CHKERRQ(ierr); 1020 PetscFunctionReturn(0); 1021 } 1022 1023 static PetscErrorCode MatGetArray_HYPRE(Mat A, PetscInt size, void **array) 1024 { 1025 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 1026 PetscErrorCode ierr; 1027 1028 PetscFunctionBegin; 1029 if (!hA->available) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Temporary space is in use"); 1030 1031 if (hA->size >= size) *array = hA->array; 1032 else { 1033 ierr = PetscFree(hA->array);CHKERRQ(ierr); 1034 hA->size = size; 1035 ierr = PetscMalloc(hA->size,&hA->array);CHKERRQ(ierr); 1036 *array = hA->array; 1037 } 1038 1039 hA->available = PETSC_FALSE; 1040 PetscFunctionReturn(0); 1041 } 1042 1043 static PetscErrorCode MatRestoreArray_HYPRE(Mat A, void **array) 1044 { 1045 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 1046 1047 PetscFunctionBegin; 1048 *array = NULL; 1049 hA->available = PETSC_TRUE; 1050 PetscFunctionReturn(0); 1051 } 1052 1053 1054 PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins) 1055 { 1056 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 1057 PetscScalar *vals = (PetscScalar *)v; 1058 PetscScalar *sscr; 1059 PetscInt *cscr[2]; 1060 PetscInt i,nzc; 1061 void *array = NULL; 1062 PetscErrorCode ierr; 1063 1064 PetscFunctionBegin; 1065 ierr = MatGetArray_HYPRE(A,sizeof(PetscInt)*(2*nc)+sizeof(PetscScalar)*nc*nr,&array);CHKERRQ(ierr); 1066 cscr[0] = (PetscInt*)array; 1067 cscr[1] = ((PetscInt*)array)+nc; 1068 sscr = (PetscScalar*)(((PetscInt*)array)+nc*2); 1069 for (i=0,nzc=0;i<nc;i++) { 1070 if (cols[i] >= 0) { 1071 cscr[0][nzc ] = cols[i]; 1072 cscr[1][nzc++] = i; 1073 } 1074 } 1075 if (!nzc) { 1076 ierr = MatRestoreArray_HYPRE(A,&array);CHKERRQ(ierr); 1077 PetscFunctionReturn(0); 1078 } 1079 1080 if (ins == ADD_VALUES) { 1081 for (i=0;i<nr;i++) { 1082 if (rows[i] >= 0 && nzc) { 1083 PetscInt j; 1084 for (j=0;j<nzc;j++) sscr[j] = vals[cscr[1][j]]; 1085 PetscStackCallStandard(HYPRE_IJMatrixAddToValues,(hA->ij,1,(HYPRE_Int*)&nzc,(HYPRE_Int*)(rows+i),(HYPRE_Int*)cscr[0],sscr)); 1086 } 1087 vals += nc; 1088 } 1089 } else { /* INSERT_VALUES */ 1090 1091 PetscInt rst,ren; 1092 ierr = MatGetOwnershipRange(A,&rst,&ren);CHKERRQ(ierr); 1093 1094 for (i=0;i<nr;i++) { 1095 if (rows[i] >= 0 && nzc) { 1096 PetscInt j; 1097 for (j=0;j<nzc;j++) sscr[j] = vals[cscr[1][j]]; 1098 /* nonlocal values */ 1099 if (rows[i] < rst || rows[i] >= ren) { ierr = MatStashValuesRow_Private(&A->stash,rows[i],nzc,cscr[0],sscr, PETSC_FALSE);CHKERRQ(ierr); } 1100 /* local values */ 1101 else PetscStackCallStandard(HYPRE_IJMatrixSetValues,(hA->ij,1,(HYPRE_Int*)&nzc,(HYPRE_Int*)(rows+i),(HYPRE_Int*)cscr[0],sscr)); 1102 } 1103 vals += nc; 1104 } 1105 } 1106 1107 ierr = MatRestoreArray_HYPRE(A,&array);CHKERRQ(ierr); 1108 PetscFunctionReturn(0); 1109 } 1110 1111 static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[]) 1112 { 1113 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 1114 HYPRE_Int *hdnnz,*honnz; 1115 PetscInt i,rs,re,cs,ce,bs; 1116 PetscMPIInt size; 1117 PetscErrorCode ierr; 1118 1119 PetscFunctionBegin; 1120 ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 1121 ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 1122 ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 1123 rs = A->rmap->rstart; 1124 re = A->rmap->rend; 1125 cs = A->cmap->rstart; 1126 ce = A->cmap->rend; 1127 if (!hA->ij) { 1128 PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rs,re-1,cs,ce-1,&hA->ij)); 1129 PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR)); 1130 } else { 1131 HYPRE_Int hrs,hre,hcs,hce; 1132 PetscStackCallStandard(HYPRE_IJMatrixGetLocalRange,(hA->ij,&hrs,&hre,&hcs,&hce)); 1133 if (hre-hrs+1 != re -rs) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent local rows: IJMatrix [%D,%D), PETSc [%D,%d)",hrs,hre+1,rs,re); 1134 if (hce-hcs+1 != ce -cs) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent local cols: IJMatrix [%D,%D), PETSc [%D,%d)",hcs,hce+1,cs,ce); 1135 } 1136 PetscStackCallStandard(HYPRE_IJMatrixInitialize,(hA->ij)); 1137 1138 if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10*bs; 1139 if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10*bs; 1140 1141 if (!dnnz) { 1142 ierr = PetscMalloc1(A->rmap->n,&hdnnz);CHKERRQ(ierr); 1143 for (i=0;i<A->rmap->n;i++) hdnnz[i] = dnz; 1144 } else { 1145 hdnnz = (HYPRE_Int*)dnnz; 1146 } 1147 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr); 1148 if (size > 1) { 1149 if (!onnz) { 1150 ierr = PetscMalloc1(A->rmap->n,&honnz);CHKERRQ(ierr); 1151 for (i=0;i<A->rmap->n;i++) honnz[i] = onz; 1152 } else { 1153 honnz = (HYPRE_Int*)onnz; 1154 } 1155 PetscStackCallStandard(HYPRE_IJMatrixSetDiagOffdSizes,(hA->ij,hdnnz,honnz)); 1156 } else { 1157 honnz = NULL; 1158 PetscStackCallStandard(HYPRE_IJMatrixSetRowSizes,(hA->ij,hdnnz)); 1159 } 1160 if (!dnnz) { 1161 ierr = PetscFree(hdnnz);CHKERRQ(ierr); 1162 } 1163 if (!onnz && honnz) { 1164 ierr = PetscFree(honnz);CHKERRQ(ierr); 1165 } 1166 A->preallocated = PETSC_TRUE; 1167 1168 /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0 */ 1169 { 1170 hypre_AuxParCSRMatrix *aux_matrix; 1171 aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(hA->ij); 1172 hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; 1173 } 1174 PetscFunctionReturn(0); 1175 } 1176 1177 /*@C 1178 MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format 1179 1180 Collective on Mat 1181 1182 Input Parameters: 1183 + A - the matrix 1184 . dnz - number of nonzeros per row in DIAGONAL portion of local submatrix 1185 (same value is used for all local rows) 1186 . dnnz - array containing the number of nonzeros in the various rows of the 1187 DIAGONAL portion of the local submatrix (possibly different for each row) 1188 or NULL (PETSC_NULL_INTEGER in Fortran), if d_nz is used to specify the nonzero structure. 1189 The size of this array is equal to the number of local rows, i.e 'm'. 1190 For matrices that will be factored, you must leave room for (and set) 1191 the diagonal entry even if it is zero. 1192 . onz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1193 submatrix (same value is used for all local rows). 1194 - onnz - array containing the number of nonzeros in the various rows of the 1195 OFF-DIAGONAL portion of the local submatrix (possibly different for 1196 each row) or NULL (PETSC_NULL_INTEGER in Fortran), if o_nz is used to specify the nonzero 1197 structure. The size of this array is equal to the number 1198 of local rows, i.e 'm'. 1199 1200 Notes: If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, onz and onnz are ignored. 1201 1202 Level: intermediate 1203 1204 .keywords: matrix, aij, compressed row, sparse, parallel 1205 1206 .seealso: MatCreate(), MatMPIAIJSetPreallocation, MATHYPRE 1207 @*/ 1208 PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[]) 1209 { 1210 PetscErrorCode ierr; 1211 1212 PetscFunctionBegin; 1213 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1214 PetscValidType(A,1); 1215 ierr = PetscTryMethod(A,"MatHYPRESetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(A,dnz,dnnz,onz,onnz));CHKERRQ(ierr); 1216 PetscFunctionReturn(0); 1217 } 1218 1219 /* 1220 MatCreateFromParCSR - Creates a matrix from a hypre_ParCSRMatrix 1221 1222 Collective 1223 1224 Input Parameters: 1225 + vparcsr - the pointer to the hypre_ParCSRMatrix 1226 . mtype - matrix type to be created. Currently MATAIJ, MATIS and MATHYPRE are supported. 1227 - copymode - PETSc copying options 1228 1229 Output Parameter: 1230 . A - the matrix 1231 1232 Level: intermediate 1233 1234 .seealso: MatHYPRE, PetscCopyMode 1235 */ 1236 PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *vparcsr, MatType mtype, PetscCopyMode copymode, Mat* A) 1237 { 1238 Mat T; 1239 Mat_HYPRE *hA; 1240 hypre_ParCSRMatrix *parcsr; 1241 MPI_Comm comm; 1242 PetscInt rstart,rend,cstart,cend,M,N; 1243 PetscBool isseqaij,ismpiaij,isaij,ishyp,isis; 1244 PetscErrorCode ierr; 1245 1246 PetscFunctionBegin; 1247 parcsr = (hypre_ParCSRMatrix *)vparcsr; 1248 comm = hypre_ParCSRMatrixComm(parcsr); 1249 ierr = PetscStrcmp(mtype,MATSEQAIJ,&isseqaij);CHKERRQ(ierr); 1250 ierr = PetscStrcmp(mtype,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr); 1251 ierr = PetscStrcmp(mtype,MATAIJ,&isaij);CHKERRQ(ierr); 1252 ierr = PetscStrcmp(mtype,MATHYPRE,&ishyp);CHKERRQ(ierr); 1253 ierr = PetscStrcmp(mtype,MATIS,&isis);CHKERRQ(ierr); 1254 isaij = (PetscBool)(isseqaij || ismpiaij || isaij); 1255 if (!isaij && !ishyp && !isis) SETERRQ6(comm,PETSC_ERR_SUP,"Unsupported MatType %s! Supported types are %s, %s, %s, %s, and %s",mtype,MATAIJ,MATSEQAIJ,MATMPIAIJ,MATIS,MATHYPRE); 1256 if (ishyp && copymode == PETSC_COPY_VALUES) SETERRQ(comm,PETSC_ERR_SUP,"Unsupported copymode PETSC_COPY_VALUES"); 1257 1258 /* access ParCSRMatrix */ 1259 rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr); 1260 rend = hypre_ParCSRMatrixLastRowIndex(parcsr); 1261 cstart = hypre_ParCSRMatrixFirstColDiag(parcsr); 1262 cend = hypre_ParCSRMatrixLastColDiag(parcsr); 1263 M = hypre_ParCSRMatrixGlobalNumRows(parcsr); 1264 N = hypre_ParCSRMatrixGlobalNumCols(parcsr); 1265 1266 /* fix for empty local rows/columns */ 1267 if (rend < rstart) rend = rstart; 1268 if (cend < cstart) cend = cstart; 1269 1270 /* create PETSc matrix with MatHYPRE */ 1271 ierr = MatCreate(comm,&T);CHKERRQ(ierr); 1272 ierr = MatSetSizes(T,rend-rstart+1,cend-cstart+1,M,N);CHKERRQ(ierr); 1273 ierr = MatSetType(T,MATHYPRE);CHKERRQ(ierr); 1274 hA = (Mat_HYPRE*)(T->data); 1275 1276 /* create HYPRE_IJMatrix */ 1277 PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rstart,rend-1,cstart,cend-1,&hA->ij)); 1278 1279 /* set ParCSR object */ 1280 PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR)); 1281 hypre_IJMatrixObject(hA->ij) = parcsr; 1282 T->preallocated = PETSC_TRUE; 1283 1284 /* set assembled flag */ 1285 hypre_IJMatrixAssembleFlag(hA->ij) = 1; 1286 PetscStackCallStandard(HYPRE_IJMatrixInitialize,(hA->ij)); 1287 if (ishyp) { 1288 PetscMPIInt myid = 0; 1289 1290 /* make sure we always have row_starts and col_starts available */ 1291 if (HYPRE_AssumedPartitionCheck()) { 1292 ierr = MPI_Comm_rank(comm,&myid);CHKERRQ(ierr); 1293 } 1294 if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) { 1295 PetscLayout map; 1296 1297 ierr = MatGetLayouts(T,NULL,&map);CHKERRQ(ierr); 1298 ierr = PetscLayoutSetUp(map);CHKERRQ(ierr); 1299 hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_Int*)(map->range + myid); 1300 } 1301 if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) { 1302 PetscLayout map; 1303 1304 ierr = MatGetLayouts(T,&map,NULL);CHKERRQ(ierr); 1305 ierr = PetscLayoutSetUp(map);CHKERRQ(ierr); 1306 hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_Int*)(map->range + myid); 1307 } 1308 /* prevent from freeing the pointer */ 1309 if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE; 1310 *A = T; 1311 ierr = MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1312 ierr = MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1313 } else if (isaij) { 1314 if (copymode != PETSC_OWN_POINTER) { 1315 /* prevent from freeing the pointer */ 1316 hA->inner_free = PETSC_FALSE; 1317 ierr = MatConvert_HYPRE_AIJ(T,MATAIJ,MAT_INITIAL_MATRIX,A);CHKERRQ(ierr); 1318 ierr = MatDestroy(&T);CHKERRQ(ierr); 1319 } else { /* AIJ return type with PETSC_OWN_POINTER */ 1320 ierr = MatConvert_HYPRE_AIJ(T,MATAIJ,MAT_INPLACE_MATRIX,&T);CHKERRQ(ierr); 1321 *A = T; 1322 } 1323 } else if (isis) { 1324 ierr = MatConvert_HYPRE_IS(T,MATIS,MAT_INITIAL_MATRIX,A);CHKERRQ(ierr); 1325 if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE; 1326 ierr = MatDestroy(&T);CHKERRQ(ierr); 1327 } 1328 PetscFunctionReturn(0); 1329 } 1330 1331 static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr) 1332 { 1333 Mat_HYPRE* hA = (Mat_HYPRE*)A->data; 1334 HYPRE_Int type; 1335 PetscErrorCode ierr; 1336 1337 PetscFunctionBegin; 1338 if (!hA->ij) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"HYPRE_IJMatrix not present"); 1339 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type)); 1340 if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"HYPRE_IJMatrix is not of type HYPRE_PARCSR"); 1341 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)parcsr)); 1342 PetscFunctionReturn(0); 1343 } 1344 1345 /* 1346 MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix 1347 1348 Not collective 1349 1350 Input Parameters: 1351 + A - the MATHYPRE object 1352 1353 Output Parameter: 1354 . parcsr - the pointer to the hypre_ParCSRMatrix 1355 1356 Level: intermediate 1357 1358 .seealso: MatHYPRE, PetscCopyMode 1359 */ 1360 PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr) 1361 { 1362 PetscErrorCode ierr; 1363 1364 PetscFunctionBegin; 1365 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1366 PetscValidType(A,1); 1367 ierr = PetscUseMethod(A,"MatHYPREGetParCSR_C",(Mat,hypre_ParCSRMatrix**),(A,parcsr));CHKERRQ(ierr); 1368 PetscFunctionReturn(0); 1369 } 1370 1371 static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd) 1372 { 1373 hypre_ParCSRMatrix *parcsr; 1374 hypre_CSRMatrix *ha; 1375 PetscInt rst; 1376 PetscErrorCode ierr; 1377 1378 PetscFunctionBegin; 1379 if (A->rmap->n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented with non-square diagonal blocks"); 1380 ierr = MatGetOwnershipRange(A,&rst,NULL);CHKERRQ(ierr); 1381 ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr); 1382 if (missing) *missing = PETSC_FALSE; 1383 if (dd) *dd = -1; 1384 ha = hypre_ParCSRMatrixDiag(parcsr); 1385 if (ha) { 1386 PetscInt size,i; 1387 HYPRE_Int *ii,*jj; 1388 1389 size = hypre_CSRMatrixNumRows(ha); 1390 ii = hypre_CSRMatrixI(ha); 1391 jj = hypre_CSRMatrixJ(ha); 1392 for (i = 0; i < size; i++) { 1393 PetscInt j; 1394 PetscBool found = PETSC_FALSE; 1395 1396 for (j = ii[i]; j < ii[i+1] && !found; j++) 1397 found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE; 1398 1399 if (!found) { 1400 PetscInfo1(A,"Matrix is missing local diagonal entry %D\n",i); 1401 if (missing) *missing = PETSC_TRUE; 1402 if (dd) *dd = i+rst; 1403 PetscFunctionReturn(0); 1404 } 1405 } 1406 if (!size) { 1407 PetscInfo(A,"Matrix has no diagonal entries therefore is missing diagonal\n"); 1408 if (missing) *missing = PETSC_TRUE; 1409 if (dd) *dd = rst; 1410 } 1411 } else { 1412 PetscInfo(A,"Matrix has no diagonal entries therefore is missing diagonal\n"); 1413 if (missing) *missing = PETSC_TRUE; 1414 if (dd) *dd = rst; 1415 } 1416 PetscFunctionReturn(0); 1417 } 1418 1419 static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s) 1420 { 1421 hypre_ParCSRMatrix *parcsr; 1422 hypre_CSRMatrix *ha; 1423 PetscErrorCode ierr; 1424 1425 PetscFunctionBegin; 1426 ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr); 1427 /* diagonal part */ 1428 ha = hypre_ParCSRMatrixDiag(parcsr); 1429 if (ha) { 1430 PetscInt size,i; 1431 HYPRE_Int *ii; 1432 PetscScalar *a; 1433 1434 size = hypre_CSRMatrixNumRows(ha); 1435 a = hypre_CSRMatrixData(ha); 1436 ii = hypre_CSRMatrixI(ha); 1437 for (i = 0; i < ii[size]; i++) a[i] *= s; 1438 } 1439 /* offdiagonal part */ 1440 ha = hypre_ParCSRMatrixOffd(parcsr); 1441 if (ha) { 1442 PetscInt size,i; 1443 HYPRE_Int *ii; 1444 PetscScalar *a; 1445 1446 size = hypre_CSRMatrixNumRows(ha); 1447 a = hypre_CSRMatrixData(ha); 1448 ii = hypre_CSRMatrixI(ha); 1449 for (i = 0; i < ii[size]; i++) a[i] *= s; 1450 } 1451 PetscFunctionReturn(0); 1452 } 1453 1454 static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 1455 { 1456 hypre_ParCSRMatrix *parcsr; 1457 HYPRE_Int *lrows; 1458 PetscInt rst,ren,i; 1459 PetscErrorCode ierr; 1460 1461 PetscFunctionBegin; 1462 if (x || b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"To be implemented"); 1463 ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr); 1464 ierr = PetscMalloc1(numRows,&lrows);CHKERRQ(ierr); 1465 ierr = MatGetOwnershipRange(A,&rst,&ren);CHKERRQ(ierr); 1466 for (i=0;i<numRows;i++) { 1467 if (rows[i] < rst || rows[i] >= ren) 1468 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-local rows not yet supported"); 1469 lrows[i] = rows[i] - rst; 1470 } 1471 PetscStackCallStandard(hypre_ParCSRMatrixEliminateRowsCols,(parcsr,numRows,lrows)); 1472 ierr = PetscFree(lrows);CHKERRQ(ierr); 1473 PetscFunctionReturn(0); 1474 } 1475 1476 static PetscErrorCode MatZeroEntries_HYPRE_CSRMatrix(hypre_CSRMatrix *ha) 1477 { 1478 PetscErrorCode ierr; 1479 1480 PetscFunctionBegin; 1481 if (ha) { 1482 HYPRE_Int *ii, size; 1483 HYPRE_Complex *a; 1484 1485 size = hypre_CSRMatrixNumRows(ha); 1486 a = hypre_CSRMatrixData(ha); 1487 ii = hypre_CSRMatrixI(ha); 1488 1489 if (a) { ierr = PetscMemzero(a,(ii[size])*sizeof(HYPRE_Complex));CHKERRQ(ierr); } 1490 } 1491 PetscFunctionReturn(0); 1492 } 1493 1494 PetscErrorCode MatZeroEntries_HYPRE(Mat A) 1495 { 1496 hypre_ParCSRMatrix *parcsr; 1497 PetscErrorCode ierr; 1498 1499 PetscFunctionBegin; 1500 ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr); 1501 /* diagonal part */ 1502 ierr = MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr));CHKERRQ(ierr); 1503 /* off-diagonal part */ 1504 ierr = MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr));CHKERRQ(ierr); 1505 PetscFunctionReturn(0); 1506 } 1507 1508 1509 static PetscErrorCode MatZeroRows_HYPRE_CSRMatrix(hypre_CSRMatrix *hA,PetscInt N,const PetscInt rows[],PetscScalar diag) 1510 { 1511 PetscInt ii, jj, ibeg, iend, irow; 1512 PetscInt *i, *j; 1513 PetscScalar *a; 1514 1515 PetscFunctionBegin; 1516 1517 if (!hA) PetscFunctionReturn(0); 1518 1519 i = (PetscInt*) hypre_CSRMatrixI(hA); 1520 j = (PetscInt*) hypre_CSRMatrixJ(hA); 1521 a = hypre_CSRMatrixData(hA); 1522 1523 for (ii = 0; ii < N; ii++) { 1524 irow = rows[ii]; 1525 ibeg = i[irow]; 1526 iend = i[irow+1]; 1527 for (jj = ibeg; jj < iend; jj++) 1528 if (j[jj] == irow) a[jj] = diag; 1529 else a[jj] = 0.0; 1530 } 1531 1532 PetscFunctionReturn(0); 1533 } 1534 1535 PetscErrorCode MatZeroRows_HYPRE(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 1536 { 1537 hypre_ParCSRMatrix *parcsr; 1538 PetscInt *lrows,len; 1539 PetscErrorCode ierr; 1540 1541 PetscFunctionBegin; 1542 if (x || b) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size \n"); 1543 /* retrieve the internal matrix */ 1544 ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr); 1545 /* get locally owned rows */ 1546 ierr = MatZeroRowsMapLocal_Private(A,N,rows,&len,&lrows);CHKERRQ(ierr); 1547 /* zero diagonal part */ 1548 ierr = MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr),len,lrows,diag);CHKERRQ(ierr); 1549 /* zero off-diagonal part */ 1550 ierr = MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr),len,lrows,0.0);CHKERRQ(ierr); 1551 1552 ierr = PetscFree(lrows);CHKERRQ(ierr); 1553 PetscFunctionReturn(0); 1554 } 1555 1556 1557 PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat,MatAssemblyType mode) 1558 { 1559 PetscErrorCode ierr; 1560 1561 PetscFunctionBegin; 1562 if (mat->nooffprocentries) PetscFunctionReturn(0); 1563 1564 ierr = MatStashScatterBegin_Private(mat,&mat->stash,mat->rmap->range);CHKERRQ(ierr); 1565 PetscFunctionReturn(0); 1566 } 1567 1568 PetscErrorCode MatGetRow_HYPRE(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 1569 { 1570 hypre_ParCSRMatrix *parcsr; 1571 PetscErrorCode ierr; 1572 1573 PetscFunctionBegin; 1574 /* retrieve the internal matrix */ 1575 ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr); 1576 /* call HYPRE API */ 1577 PetscStackCallStandard(HYPRE_ParCSRMatrixGetRow,(parcsr,row,(HYPRE_Int*)nz,(HYPRE_Int**)idx,v)); 1578 PetscFunctionReturn(0); 1579 } 1580 1581 PetscErrorCode MatRestoreRow_HYPRE(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 1582 { 1583 hypre_ParCSRMatrix *parcsr; 1584 PetscErrorCode ierr; 1585 1586 PetscFunctionBegin; 1587 /* retrieve the internal matrix */ 1588 ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr); 1589 /* call HYPRE API */ 1590 PetscStackCallStandard(HYPRE_ParCSRMatrixRestoreRow,(parcsr,row,(HYPRE_Int*)nz,(HYPRE_Int**)idx,v)); 1591 PetscFunctionReturn(0); 1592 } 1593 1594 1595 1596 PetscErrorCode MatGetValues_HYPRE(Mat A,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[]) 1597 { 1598 HYPRE_IJMatrix *hIJ = (HYPRE_IJMatrix*)A->data; 1599 PetscErrorCode ierr; 1600 PetscInt i; 1601 PetscFunctionBegin; 1602 if (!m || !n) PetscFunctionReturn(0); 1603 1604 /* Ignore negative row indices 1605 * And negative column indices should be automatically ignored in hypre 1606 * */ 1607 for (i=0; i<m; i++) 1608 if (idxm[i] >= 0) PetscStackCallStandard(HYPRE_IJMatrixGetValues,(*hIJ,1,(HYPRE_Int*)&n,(HYPRE_Int*)&idxm[i],(HYPRE_Int*)idxn,&v[i*n])); 1609 1610 PetscFunctionReturn(0); 1611 } 1612 1613 1614 /*MC 1615 MATHYPRE - MATHYPRE = "hypre" - A matrix type to be used for sequential and parallel sparse matrices 1616 based on the hypre IJ interface. 1617 1618 Level: intermediate 1619 1620 .seealso: MatCreate() 1621 M*/ 1622 1623 PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B) 1624 { 1625 Mat_HYPRE *hB; 1626 PetscErrorCode ierr; 1627 1628 PetscFunctionBegin; 1629 ierr = PetscNewLog(B,&hB);CHKERRQ(ierr); 1630 hB->inner_free = PETSC_TRUE; 1631 hB->available = PETSC_TRUE; 1632 hB->size = 0; 1633 hB->array = NULL; 1634 1635 B->data = (void*)hB; 1636 B->rmap->bs = 1; 1637 B->assembled = PETSC_FALSE; 1638 1639 ierr = PetscMemzero(B->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 1640 B->ops->mult = MatMult_HYPRE; 1641 B->ops->multtranspose = MatMultTranspose_HYPRE; 1642 B->ops->setup = MatSetUp_HYPRE; 1643 B->ops->destroy = MatDestroy_HYPRE; 1644 1645 /* build cache for off array entries formed */ 1646 ierr = MatStashCreate_Private(PetscObjectComm((PetscObject)B),1,&B->stash);CHKERRQ(ierr); 1647 B->ops->assemblyend = MatAssemblyEnd_HYPRE; 1648 B->ops->assemblybegin = MatAssemblyBegin_HYPRE; 1649 1650 B->ops->ptap = MatPtAP_HYPRE_HYPRE; 1651 B->ops->matmult = MatMatMult_HYPRE_HYPRE; 1652 B->ops->setvalues = MatSetValues_HYPRE; 1653 B->ops->missingdiagonal = MatMissingDiagonal_HYPRE; 1654 B->ops->scale = MatScale_HYPRE; 1655 B->ops->zerorowscolumns = MatZeroRowsColumns_HYPRE; 1656 B->ops->zeroentries = MatZeroEntries_HYPRE; 1657 B->ops->zerorows = MatZeroRows_HYPRE; 1658 B->ops->getrow = MatGetRow_HYPRE; 1659 B->ops->restorerow = MatRestoreRow_HYPRE; 1660 B->ops->getvalues = MatGetValues_HYPRE; 1661 1662 ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)B),&hB->comm);CHKERRQ(ierr); 1663 ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRE);CHKERRQ(ierr); 1664 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_hypre_aij_C",MatConvert_HYPRE_AIJ);CHKERRQ(ierr); 1665 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_hypre_is_C",MatConvert_HYPRE_IS);CHKERRQ(ierr); 1666 ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_seqaij_hypre_C",MatPtAP_AIJ_HYPRE);CHKERRQ(ierr); 1667 ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_mpiaij_hypre_C",MatPtAP_AIJ_HYPRE);CHKERRQ(ierr); 1668 ierr = PetscObjectComposeFunction((PetscObject)B,"MatHYPRESetPreallocation_C",MatHYPRESetPreallocation_HYPRE);CHKERRQ(ierr); 1669 ierr = PetscObjectComposeFunction((PetscObject)B,"MatHYPREGetParCSR_C",MatHYPREGetParCSR_HYPRE);CHKERRQ(ierr); 1670 PetscFunctionReturn(0); 1671 } 1672 1673 static PetscErrorCode hypre_array_destroy(void *ptr) 1674 { 1675 PetscFunctionBegin; 1676 hypre_TFree(ptr,HYPRE_MEMORY_HOST); 1677 PetscFunctionReturn(0); 1678 } 1679