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