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