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 = PetscObjectTypeCompare((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 = PetscObjectTypeCompare((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 PetscFunctionBegin; 657 ierr = MatCreate(PetscObjectComm((PetscObject)A),C);CHKERRQ(ierr); 658 ierr = MatSetType(*C,MATAIJ);CHKERRQ(ierr); 659 (*C)->ops->ptapnumeric = MatPtAPNumeric_AIJ_AIJ_wHYPRE; 660 PetscFunctionReturn(0); 661 } 662 663 static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A,Mat P,Mat C) 664 { 665 Mat B; 666 Mat_HYPRE *hP; 667 hypre_ParCSRMatrix *hA = NULL,*Pparcsr,*ptapparcsr; 668 HYPRE_Int type; 669 MPI_Comm comm = PetscObjectComm((PetscObject)A); 670 PetscBool ishypre; 671 PetscErrorCode ierr; 672 673 PetscFunctionBegin; 674 ierr = PetscObjectTypeCompare((PetscObject)P,MATHYPRE,&ishypre);CHKERRQ(ierr); 675 if (!ishypre) SETERRQ1(comm,PETSC_ERR_USER,"P should be of type %s",MATHYPRE); 676 hP = (Mat_HYPRE*)P->data; 677 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hP->ij,&type)); 678 if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 679 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hP->ij,(void**)&Pparcsr)); 680 681 ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr); 682 ierr = MatHYPRE_ParCSR_RAP(Pparcsr,hA,Pparcsr,&ptapparcsr);CHKERRQ(ierr); 683 ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr); 684 685 /* create temporary matrix and merge to C */ 686 ierr = MatCreateFromParCSR(ptapparcsr,((PetscObject)C)->type_name,PETSC_OWN_POINTER,&B);CHKERRQ(ierr); 687 ierr = MatHeaderMerge(C,&B);CHKERRQ(ierr); 688 PetscFunctionReturn(0); 689 } 690 691 static PetscErrorCode MatPtAP_AIJ_HYPRE(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C) 692 { 693 PetscErrorCode ierr; 694 695 PetscFunctionBegin; 696 if (scall == MAT_INITIAL_MATRIX) { 697 const char *deft = MATAIJ; 698 char type[256]; 699 PetscBool flg; 700 701 ierr = PetscObjectOptionsBegin((PetscObject)A);CHKERRQ(ierr); 702 ierr = PetscOptionsFList("-matptap_hypre_outtype","Matrix type",NULL,MatList,deft,type,256,&flg);CHKERRQ(ierr); 703 ierr = PetscOptionsEnd();CHKERRQ(ierr); 704 ierr = PetscLogEventBegin(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr); 705 ierr = MatCreate(PetscObjectComm((PetscObject)A),C);CHKERRQ(ierr); 706 if (flg) { 707 ierr = MatSetType(*C,type);CHKERRQ(ierr); 708 } else { 709 ierr = MatSetType(*C,deft);CHKERRQ(ierr); 710 } 711 (*C)->ops->ptapnumeric = MatPtAPNumeric_AIJ_HYPRE; 712 ierr = PetscLogEventEnd(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr); 713 } 714 ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 715 ierr = (*(*C)->ops->ptapnumeric)(A,P,*C);CHKERRQ(ierr); 716 ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 717 PetscFunctionReturn(0); 718 } 719 720 static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A,Mat P,Mat C) 721 { 722 Mat B; 723 hypre_ParCSRMatrix *Aparcsr,*Pparcsr,*ptapparcsr; 724 Mat_HYPRE *hA,*hP; 725 PetscBool ishypre; 726 HYPRE_Int type; 727 PetscErrorCode ierr; 728 729 PetscFunctionBegin; 730 ierr = PetscObjectTypeCompare((PetscObject)P,MATHYPRE,&ishypre);CHKERRQ(ierr); 731 if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)P),PETSC_ERR_USER,"P should be of type %s",MATHYPRE); 732 ierr = PetscObjectTypeCompare((PetscObject)A,MATHYPRE,&ishypre);CHKERRQ(ierr); 733 if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"A should be of type %s",MATHYPRE); 734 hA = (Mat_HYPRE*)A->data; 735 hP = (Mat_HYPRE*)P->data; 736 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type)); 737 if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 738 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hP->ij,&type)); 739 if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)P),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 740 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&Aparcsr)); 741 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hP->ij,(void**)&Pparcsr)); 742 ierr = MatHYPRE_ParCSR_RAP(Pparcsr,Aparcsr,Pparcsr,&ptapparcsr);CHKERRQ(ierr); 743 ierr = MatCreateFromParCSR(ptapparcsr,MATHYPRE,PETSC_OWN_POINTER,&B);CHKERRQ(ierr); 744 ierr = MatHeaderMerge(C,&B);CHKERRQ(ierr); 745 PetscFunctionReturn(0); 746 } 747 748 static PetscErrorCode MatPtAP_HYPRE_HYPRE(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C) 749 { 750 PetscErrorCode ierr; 751 752 PetscFunctionBegin; 753 if (scall == MAT_INITIAL_MATRIX) { 754 ierr = PetscLogEventBegin(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr); 755 ierr = MatCreate(PetscObjectComm((PetscObject)A),C);CHKERRQ(ierr); 756 ierr = MatSetType(*C,MATHYPRE);CHKERRQ(ierr); 757 (*C)->ops->ptapnumeric = MatPtAPNumeric_HYPRE_HYPRE; 758 ierr = PetscLogEventEnd(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr); 759 } 760 ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 761 ierr = (*(*C)->ops->ptapnumeric)(A,P,*C);CHKERRQ(ierr); 762 ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 763 PetscFunctionReturn(0); 764 } 765 766 /* calls hypre_ParMatmul 767 hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA 768 hypre_ParMatrixCreate does not duplicate the communicator 769 It looks like we don't need to have the diagonal entries 770 ordered first in the rows of the diagonal part 771 for boomerAMGBuildCoarseOperator to work */ 772 static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB) 773 { 774 PetscFunctionBegin; 775 PetscStackPush("hypre_ParMatmul"); 776 *hAB = hypre_ParMatmul(hA,hB); 777 PetscStackPop; 778 PetscFunctionReturn(0); 779 } 780 781 static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A,Mat B,Mat C) 782 { 783 Mat D; 784 hypre_ParCSRMatrix *hA,*hB,*hAB = NULL; 785 PetscErrorCode ierr; 786 787 PetscFunctionBegin; 788 ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr); 789 ierr = MatAIJGetParCSR_Private(B,&hB);CHKERRQ(ierr); 790 ierr = MatHYPRE_ParCSR_MatMatMult(hA,hB,&hAB);CHKERRQ(ierr); 791 ierr = MatCreateFromParCSR(hAB,MATAIJ,PETSC_OWN_POINTER,&D);CHKERRQ(ierr); 792 ierr = MatHeaderMerge(C,&D);CHKERRQ(ierr); 793 ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr); 794 ierr = MatAIJRestoreParCSR_Private(B,&hB);CHKERRQ(ierr); 795 PetscFunctionReturn(0); 796 } 797 798 PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A,Mat B,PetscReal fill,Mat *C) 799 { 800 PetscErrorCode ierr; 801 802 PetscFunctionBegin; 803 ierr = MatCreate(PetscObjectComm((PetscObject)A),C);CHKERRQ(ierr); 804 ierr = MatSetType(*C,MATAIJ);CHKERRQ(ierr); 805 (*C)->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE; 806 PetscFunctionReturn(0); 807 } 808 809 static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A,Mat B,Mat C) 810 { 811 Mat D; 812 hypre_ParCSRMatrix *Aparcsr,*Bparcsr,*ABparcsr = NULL; 813 Mat_HYPRE *hA,*hB; 814 PetscBool ishypre; 815 HYPRE_Int type; 816 PetscErrorCode ierr; 817 818 PetscFunctionBegin; 819 ierr = PetscObjectTypeCompare((PetscObject)B,MATHYPRE,&ishypre);CHKERRQ(ierr); 820 if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)B),PETSC_ERR_USER,"B should be of type %s",MATHYPRE); 821 ierr = PetscObjectTypeCompare((PetscObject)A,MATHYPRE,&ishypre);CHKERRQ(ierr); 822 if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"A should be of type %s",MATHYPRE); 823 hA = (Mat_HYPRE*)A->data; 824 hB = (Mat_HYPRE*)B->data; 825 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type)); 826 if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 827 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hB->ij,&type)); 828 if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 829 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&Aparcsr)); 830 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hB->ij,(void**)&Bparcsr)); 831 ierr = MatHYPRE_ParCSR_MatMatMult(Aparcsr,Bparcsr,&ABparcsr);CHKERRQ(ierr); 832 ierr = MatCreateFromParCSR(ABparcsr,MATHYPRE,PETSC_OWN_POINTER,&D);CHKERRQ(ierr); 833 /* need to use HeaderReplace because HeaderMerge messes up with the communicator */ 834 ierr = MatHeaderReplace(C,&D);CHKERRQ(ierr); 835 C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE; 836 PetscFunctionReturn(0); 837 } 838 839 static PetscErrorCode MatMatMult_HYPRE_HYPRE(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C) 840 { 841 PetscErrorCode ierr; 842 843 PetscFunctionBegin; 844 if (scall == MAT_INITIAL_MATRIX) { 845 ierr = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 846 ierr = MatCreate(PetscObjectComm((PetscObject)A),C);CHKERRQ(ierr); 847 ierr = MatSetType(*C,MATHYPRE);CHKERRQ(ierr); 848 (*C)->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE; 849 ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 850 } 851 ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 852 ierr = (*(*C)->ops->matmultnumeric)(A,B,*C);CHKERRQ(ierr); 853 ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 854 PetscFunctionReturn(0); 855 } 856 857 PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A,Mat B,Mat C,Mat D) 858 { 859 Mat E; 860 hypre_ParCSRMatrix *hA,*hB,*hC,*hABC; 861 PetscErrorCode ierr; 862 863 PetscFunctionBegin; 864 ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr); 865 ierr = MatAIJGetParCSR_Private(B,&hB);CHKERRQ(ierr); 866 ierr = MatAIJGetParCSR_Private(C,&hC);CHKERRQ(ierr); 867 ierr = MatHYPRE_ParCSR_RAP(hA,hB,hC,&hABC);CHKERRQ(ierr); 868 ierr = MatCreateFromParCSR(hABC,MATAIJ,PETSC_OWN_POINTER,&E);CHKERRQ(ierr); 869 ierr = MatHeaderMerge(D,&E);CHKERRQ(ierr); 870 ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr); 871 ierr = MatAIJRestoreParCSR_Private(B,&hB);CHKERRQ(ierr); 872 ierr = MatAIJRestoreParCSR_Private(C,&hC);CHKERRQ(ierr); 873 PetscFunctionReturn(0); 874 } 875 876 PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A,Mat B,Mat C,PetscReal fill,Mat *D) 877 { 878 PetscErrorCode ierr; 879 880 PetscFunctionBegin; 881 ierr = MatCreate(PetscObjectComm((PetscObject)A),D);CHKERRQ(ierr); 882 ierr = MatSetType(*D,MATAIJ);CHKERRQ(ierr); 883 PetscFunctionReturn(0); 884 } 885 886 static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y) 887 { 888 PetscErrorCode ierr; 889 890 PetscFunctionBegin; 891 ierr = MatHYPRE_MultKernel_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr); 892 PetscFunctionReturn(0); 893 } 894 895 static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y) 896 { 897 PetscErrorCode ierr; 898 899 PetscFunctionBegin; 900 ierr = MatHYPRE_MultKernel_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr); 901 PetscFunctionReturn(0); 902 } 903 904 static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, Vec x, Vec y, PetscBool trans) 905 { 906 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 907 hypre_ParCSRMatrix *parcsr; 908 hypre_ParVector *hx,*hy; 909 PetscScalar *ax,*ay,*sax,*say; 910 PetscErrorCode ierr; 911 912 PetscFunctionBegin; 913 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr)); 914 PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->x,(void**)&hx)); 915 PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->b,(void**)&hy)); 916 ierr = VecGetArrayRead(x,(const PetscScalar**)&ax);CHKERRQ(ierr); 917 ierr = VecGetArray(y,&ay);CHKERRQ(ierr); 918 if (trans) { 919 VecHYPRE_ParVectorReplacePointer(hA->x,ay,say); 920 VecHYPRE_ParVectorReplacePointer(hA->b,ax,sax); 921 hypre_ParCSRMatrixMatvecT(1.,parcsr,hy,0.,hx); 922 VecHYPRE_ParVectorReplacePointer(hA->x,say,ay); 923 VecHYPRE_ParVectorReplacePointer(hA->b,sax,ax); 924 } else { 925 VecHYPRE_ParVectorReplacePointer(hA->x,ax,sax); 926 VecHYPRE_ParVectorReplacePointer(hA->b,ay,say); 927 hypre_ParCSRMatrixMatvec(1.,parcsr,hx,0.,hy); 928 VecHYPRE_ParVectorReplacePointer(hA->x,sax,ax); 929 VecHYPRE_ParVectorReplacePointer(hA->b,say,ay); 930 } 931 ierr = VecRestoreArrayRead(x,(const PetscScalar**)&ax);CHKERRQ(ierr); 932 ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr); 933 PetscFunctionReturn(0); 934 } 935 936 static PetscErrorCode MatDestroy_HYPRE(Mat A) 937 { 938 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 939 PetscErrorCode ierr; 940 941 PetscFunctionBegin; 942 if (hA->x) PetscStackCallStandard(HYPRE_IJVectorDestroy,(hA->x)); 943 if (hA->b) PetscStackCallStandard(HYPRE_IJVectorDestroy,(hA->b)); 944 if (hA->ij) { 945 if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL; 946 PetscStackCallStandard(HYPRE_IJMatrixDestroy,(hA->ij)); 947 } 948 if (hA->comm) { ierr = MPI_Comm_free(&hA->comm);CHKERRQ(ierr); } 949 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_hypre_aij_C",NULL);CHKERRQ(ierr); 950 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_hypre_is_C",NULL);CHKERRQ(ierr); 951 ierr = PetscObjectComposeFunction((PetscObject)A,"MatPtAP_seqaij_hypre_C",NULL);CHKERRQ(ierr); 952 ierr = PetscObjectComposeFunction((PetscObject)A,"MatPtAP_mpiaij_hypre_C",NULL);CHKERRQ(ierr); 953 ierr = PetscObjectComposeFunction((PetscObject)A,"MatHYPRESetPreallocation_C",NULL);CHKERRQ(ierr); 954 ierr = PetscObjectComposeFunction((PetscObject)A,"MatHYPREGetParCSR_C",NULL);CHKERRQ(ierr); 955 ierr = PetscFree(A->data);CHKERRQ(ierr); 956 PetscFunctionReturn(0); 957 } 958 959 static PetscErrorCode MatSetUp_HYPRE(Mat A) 960 { 961 PetscErrorCode ierr; 962 963 PetscFunctionBegin; 964 ierr = MatHYPRESetPreallocation(A,PETSC_DEFAULT,NULL,PETSC_DEFAULT,NULL);CHKERRQ(ierr); 965 PetscFunctionReturn(0); 966 } 967 968 static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode) 969 { 970 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 971 Vec x,b; 972 PetscErrorCode ierr; 973 974 PetscFunctionBegin; 975 if (mode == MAT_FLUSH_ASSEMBLY) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE"); 976 PetscStackCallStandard(HYPRE_IJMatrixAssemble,(hA->ij)); 977 if (hA->x) PetscFunctionReturn(0); 978 ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 979 ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 980 ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)A),1,A->cmap->n,A->cmap->N,NULL,&x);CHKERRQ(ierr); 981 ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)A),1,A->rmap->n,A->rmap->N,NULL,&b);CHKERRQ(ierr); 982 ierr = VecHYPRE_IJVectorCreate(x,&hA->x);CHKERRQ(ierr); 983 ierr = VecHYPRE_IJVectorCreate(b,&hA->b);CHKERRQ(ierr); 984 ierr = VecDestroy(&x);CHKERRQ(ierr); 985 ierr = VecDestroy(&b);CHKERRQ(ierr); 986 PetscFunctionReturn(0); 987 } 988 989 #define MATHYPRE_SCRATCH 2048 990 991 PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins) 992 { 993 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 994 PetscScalar *vals = (PetscScalar *)v; 995 PetscScalar sscr[MATHYPRE_SCRATCH]; 996 HYPRE_Int cscr[2][MATHYPRE_SCRATCH]; 997 HYPRE_Int i,nzc; 998 PetscErrorCode ierr; 999 1000 PetscFunctionBegin; 1001 for (i=0,nzc=0;i<nc;i++) { 1002 if (cols[i] >= 0) { 1003 cscr[0][nzc ] = cols[i]; 1004 cscr[1][nzc++] = i; 1005 } 1006 } 1007 if (!nzc) PetscFunctionReturn(0); 1008 1009 if (ins == ADD_VALUES) { 1010 for (i=0;i<nr;i++) { 1011 if (rows[i] >= 0 && nzc) { 1012 PetscInt j; 1013 for (j=0;j<nzc;j++) sscr[j] = vals[cscr[1][j]]; 1014 PetscStackCallStandard(HYPRE_IJMatrixAddToValues,(hA->ij,1,&nzc,(HYPRE_Int*)(rows+i),cscr[0],sscr)); 1015 } 1016 vals += nc; 1017 } 1018 } else { /* INSERT_VALUES */ 1019 #if defined(PETSC_USE_DEBUG) 1020 /* Insert values cannot be used to insert offproc entries */ 1021 PetscInt rst,ren; 1022 ierr = MatGetOwnershipRange(A,&rst,&ren);CHKERRQ(ierr); 1023 for (i=0;i<nr;i++) 1024 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"); 1025 #endif 1026 for (i=0;i<nr;i++) { 1027 if (rows[i] >= 0 && nzc) { 1028 PetscInt j; 1029 for (j=0;j<nzc;j++) sscr[j] = vals[cscr[1][j]]; 1030 PetscStackCallStandard(HYPRE_IJMatrixSetValues,(hA->ij,1,&nzc,(HYPRE_Int*)(rows+i),cscr[0],sscr)); 1031 } 1032 vals += nc; 1033 } 1034 } 1035 PetscFunctionReturn(0); 1036 } 1037 1038 static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[]) 1039 { 1040 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 1041 HYPRE_Int *hdnnz,*honnz; 1042 PetscInt i,rs,re,cs,ce,bs; 1043 PetscMPIInt size; 1044 PetscErrorCode ierr; 1045 1046 PetscFunctionBegin; 1047 ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 1048 ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 1049 ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 1050 rs = A->rmap->rstart; 1051 re = A->rmap->rend; 1052 cs = A->cmap->rstart; 1053 ce = A->cmap->rend; 1054 if (!hA->ij) { 1055 PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rs,re-1,cs,ce-1,&hA->ij)); 1056 PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR)); 1057 } else { 1058 HYPRE_Int hrs,hre,hcs,hce; 1059 PetscStackCallStandard(HYPRE_IJMatrixGetLocalRange,(hA->ij,&hrs,&hre,&hcs,&hce)); 1060 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); 1061 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); 1062 } 1063 PetscStackCallStandard(HYPRE_IJMatrixInitialize,(hA->ij)); 1064 1065 if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10*bs; 1066 if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10*bs; 1067 1068 if (!dnnz) { 1069 ierr = PetscMalloc1(A->rmap->n,&hdnnz);CHKERRQ(ierr); 1070 for (i=0;i<A->rmap->n;i++) hdnnz[i] = dnz; 1071 } else { 1072 hdnnz = (HYPRE_Int*)dnnz; 1073 } 1074 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr); 1075 if (size > 1) { 1076 if (!onnz) { 1077 ierr = PetscMalloc1(A->rmap->n,&honnz);CHKERRQ(ierr); 1078 for (i=0;i<A->rmap->n;i++) honnz[i] = onz; 1079 } else { 1080 honnz = (HYPRE_Int*)onnz; 1081 } 1082 PetscStackCallStandard(HYPRE_IJMatrixSetDiagOffdSizes,(hA->ij,hdnnz,honnz)); 1083 } else { 1084 honnz = NULL; 1085 PetscStackCallStandard(HYPRE_IJMatrixSetRowSizes,(hA->ij,hdnnz)); 1086 } 1087 if (!dnnz) { 1088 ierr = PetscFree(hdnnz);CHKERRQ(ierr); 1089 } 1090 if (!onnz && honnz) { 1091 ierr = PetscFree(honnz);CHKERRQ(ierr); 1092 } 1093 A->preallocated = PETSC_TRUE; 1094 1095 /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0 */ 1096 { 1097 hypre_AuxParCSRMatrix *aux_matrix; 1098 aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(hA->ij); 1099 hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; 1100 } 1101 PetscFunctionReturn(0); 1102 } 1103 1104 /*@C 1105 MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format 1106 1107 Collective on Mat 1108 1109 Input Parameters: 1110 + A - the matrix 1111 . dnz - number of nonzeros per row in DIAGONAL portion of local submatrix 1112 (same value is used for all local rows) 1113 . dnnz - array containing the number of nonzeros in the various rows of the 1114 DIAGONAL portion of the local submatrix (possibly different for each row) 1115 or NULL (PETSC_NULL_INTEGER in Fortran), if d_nz is used to specify the nonzero structure. 1116 The size of this array is equal to the number of local rows, i.e 'm'. 1117 For matrices that will be factored, you must leave room for (and set) 1118 the diagonal entry even if it is zero. 1119 . onz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1120 submatrix (same value is used for all local rows). 1121 - onnz - array containing the number of nonzeros in the various rows of the 1122 OFF-DIAGONAL portion of the local submatrix (possibly different for 1123 each row) or NULL (PETSC_NULL_INTEGER in Fortran), if o_nz is used to specify the nonzero 1124 structure. The size of this array is equal to the number 1125 of local rows, i.e 'm'. 1126 1127 Notes: If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, onz and onnz are ignored. 1128 1129 Level: intermediate 1130 1131 .keywords: matrix, aij, compressed row, sparse, parallel 1132 1133 .seealso: MatCreate(), MatMPIAIJSetPreallocation, MATHYPRE 1134 @*/ 1135 PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[]) 1136 { 1137 PetscErrorCode ierr; 1138 1139 PetscFunctionBegin; 1140 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1141 PetscValidType(A,1); 1142 ierr = PetscTryMethod(A,"MatHYPRESetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(A,dnz,dnnz,onz,onnz));CHKERRQ(ierr); 1143 PetscFunctionReturn(0); 1144 } 1145 1146 /* 1147 MatCreateFromParCSR - Creates a matrix from a hypre_ParCSRMatrix 1148 1149 Collective 1150 1151 Input Parameters: 1152 + vparcsr - the pointer to the hypre_ParCSRMatrix 1153 . mtype - matrix type to be created. Currently MATAIJ, MATIS and MATHYPRE are supported. 1154 - copymode - PETSc copying options 1155 1156 Output Parameter: 1157 . A - the matrix 1158 1159 Level: intermediate 1160 1161 .seealso: MatHYPRE, PetscCopyMode 1162 */ 1163 PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *vparcsr, MatType mtype, PetscCopyMode copymode, Mat* A) 1164 { 1165 Mat T; 1166 Mat_HYPRE *hA; 1167 hypre_ParCSRMatrix *parcsr; 1168 MPI_Comm comm; 1169 PetscInt rstart,rend,cstart,cend,M,N; 1170 PetscBool isseqaij,ismpiaij,isaij,ishyp,isis; 1171 PetscErrorCode ierr; 1172 1173 PetscFunctionBegin; 1174 parcsr = (hypre_ParCSRMatrix *)vparcsr; 1175 comm = hypre_ParCSRMatrixComm(parcsr); 1176 ierr = PetscStrcmp(mtype,MATSEQAIJ,&isseqaij);CHKERRQ(ierr); 1177 ierr = PetscStrcmp(mtype,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr); 1178 ierr = PetscStrcmp(mtype,MATAIJ,&isaij);CHKERRQ(ierr); 1179 ierr = PetscStrcmp(mtype,MATHYPRE,&ishyp);CHKERRQ(ierr); 1180 ierr = PetscStrcmp(mtype,MATIS,&isis);CHKERRQ(ierr); 1181 isaij = (PetscBool)(isseqaij || ismpiaij || isaij); 1182 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); 1183 if (ishyp && copymode == PETSC_COPY_VALUES) SETERRQ(comm,PETSC_ERR_SUP,"Unsupported copymode PETSC_COPY_VALUES"); 1184 1185 /* access ParCSRMatrix */ 1186 rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr); 1187 rend = hypre_ParCSRMatrixLastRowIndex(parcsr); 1188 cstart = hypre_ParCSRMatrixFirstColDiag(parcsr); 1189 cend = hypre_ParCSRMatrixLastColDiag(parcsr); 1190 M = hypre_ParCSRMatrixGlobalNumRows(parcsr); 1191 N = hypre_ParCSRMatrixGlobalNumCols(parcsr); 1192 1193 /* fix for empty local rows/columns */ 1194 if (rend < rstart) rend = rstart; 1195 if (cend < cstart) cend = cstart; 1196 1197 /* create PETSc matrix with MatHYPRE */ 1198 ierr = MatCreate(comm,&T);CHKERRQ(ierr); 1199 ierr = MatSetSizes(T,rend-rstart+1,cend-cstart+1,M,N);CHKERRQ(ierr); 1200 ierr = MatSetType(T,MATHYPRE);CHKERRQ(ierr); 1201 hA = (Mat_HYPRE*)(T->data); 1202 1203 /* create HYPRE_IJMatrix */ 1204 PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rstart,rend-1,cstart,cend-1,&hA->ij)); 1205 1206 /* set ParCSR object */ 1207 PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR)); 1208 hypre_IJMatrixObject(hA->ij) = parcsr; 1209 T->preallocated = PETSC_TRUE; 1210 1211 /* set assembled flag */ 1212 hypre_IJMatrixAssembleFlag(hA->ij) = 1; 1213 PetscStackCallStandard(HYPRE_IJMatrixInitialize,(hA->ij)); 1214 if (ishyp) { 1215 PetscMPIInt myid = 0; 1216 1217 /* make sure we always have row_starts and col_starts available */ 1218 if (HYPRE_AssumedPartitionCheck()) { 1219 ierr = MPI_Comm_rank(comm,&myid);CHKERRQ(ierr); 1220 } 1221 if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) { 1222 PetscLayout map; 1223 1224 ierr = MatGetLayouts(T,NULL,&map);CHKERRQ(ierr); 1225 ierr = PetscLayoutSetUp(map);CHKERRQ(ierr); 1226 hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_Int*)(map->range + myid); 1227 } 1228 if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) { 1229 PetscLayout map; 1230 1231 ierr = MatGetLayouts(T,&map,NULL);CHKERRQ(ierr); 1232 ierr = PetscLayoutSetUp(map);CHKERRQ(ierr); 1233 hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_Int*)(map->range + myid); 1234 } 1235 /* prevent from freeing the pointer */ 1236 if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE; 1237 *A = T; 1238 ierr = MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1239 ierr = MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1240 } else if (isaij) { 1241 if (copymode != PETSC_OWN_POINTER) { 1242 /* prevent from freeing the pointer */ 1243 hA->inner_free = PETSC_FALSE; 1244 ierr = MatConvert_HYPRE_AIJ(T,MATAIJ,MAT_INITIAL_MATRIX,A);CHKERRQ(ierr); 1245 ierr = MatDestroy(&T);CHKERRQ(ierr); 1246 } else { /* AIJ return type with PETSC_OWN_POINTER */ 1247 ierr = MatConvert_HYPRE_AIJ(T,MATAIJ,MAT_INPLACE_MATRIX,&T);CHKERRQ(ierr); 1248 *A = T; 1249 } 1250 } else if (isis) { 1251 ierr = MatConvert_HYPRE_IS(T,MATIS,MAT_INITIAL_MATRIX,A);CHKERRQ(ierr); 1252 if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE; 1253 ierr = MatDestroy(&T);CHKERRQ(ierr); 1254 } 1255 PetscFunctionReturn(0); 1256 } 1257 1258 static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr) 1259 { 1260 Mat_HYPRE* hA = (Mat_HYPRE*)A->data; 1261 HYPRE_Int type; 1262 PetscErrorCode ierr; 1263 1264 PetscFunctionBegin; 1265 if (!hA->ij) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"HYPRE_IJMatrix not present"); 1266 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type)); 1267 if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"HYPRE_IJMatrix is not of type HYPRE_PARCSR"); 1268 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)parcsr)); 1269 PetscFunctionReturn(0); 1270 } 1271 1272 /* 1273 MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix 1274 1275 Not collective 1276 1277 Input Parameters: 1278 + A - the MATHYPRE object 1279 1280 Output Parameter: 1281 . parcsr - the pointer to the hypre_ParCSRMatrix 1282 1283 Level: intermediate 1284 1285 .seealso: MatHYPRE, PetscCopyMode 1286 */ 1287 PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr) 1288 { 1289 PetscErrorCode ierr; 1290 1291 PetscFunctionBegin; 1292 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1293 PetscValidType(A,1); 1294 ierr = PetscUseMethod(A,"MatHYPREGetParCSR_C",(Mat,hypre_ParCSRMatrix**),(A,parcsr));CHKERRQ(ierr); 1295 PetscFunctionReturn(0); 1296 } 1297 1298 static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd) 1299 { 1300 hypre_ParCSRMatrix *parcsr; 1301 hypre_CSRMatrix *ha; 1302 PetscInt rst; 1303 PetscErrorCode ierr; 1304 1305 PetscFunctionBegin; 1306 if (A->rmap->n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented with non-square diagonal blocks"); 1307 ierr = MatGetOwnershipRange(A,&rst,NULL);CHKERRQ(ierr); 1308 ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr); 1309 if (missing) *missing = PETSC_FALSE; 1310 if (dd) *dd = -1; 1311 ha = hypre_ParCSRMatrixDiag(parcsr); 1312 if (ha) { 1313 PetscInt size,i; 1314 HYPRE_Int *ii,*jj; 1315 1316 size = hypre_CSRMatrixNumRows(ha); 1317 ii = hypre_CSRMatrixI(ha); 1318 jj = hypre_CSRMatrixJ(ha); 1319 for (i = 0; i < size; i++) { 1320 PetscInt j; 1321 PetscBool found = PETSC_FALSE; 1322 1323 for (j = ii[i]; j < ii[i+1] && !found; j++) 1324 found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE; 1325 1326 if (!found) { 1327 PetscInfo1(A,"Matrix is missing local diagonal entry %D\n",i); 1328 if (missing) *missing = PETSC_TRUE; 1329 if (dd) *dd = i+rst; 1330 PetscFunctionReturn(0); 1331 } 1332 } 1333 if (!size) { 1334 PetscInfo(A,"Matrix has no diagonal entries therefore is missing diagonal\n"); 1335 if (missing) *missing = PETSC_TRUE; 1336 if (dd) *dd = rst; 1337 } 1338 } else { 1339 PetscInfo(A,"Matrix has no diagonal entries therefore is missing diagonal\n"); 1340 if (missing) *missing = PETSC_TRUE; 1341 if (dd) *dd = rst; 1342 } 1343 PetscFunctionReturn(0); 1344 } 1345 1346 static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s) 1347 { 1348 hypre_ParCSRMatrix *parcsr; 1349 hypre_CSRMatrix *ha; 1350 PetscErrorCode ierr; 1351 1352 PetscFunctionBegin; 1353 ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr); 1354 /* diagonal part */ 1355 ha = hypre_ParCSRMatrixDiag(parcsr); 1356 if (ha) { 1357 PetscInt size,i; 1358 HYPRE_Int *ii; 1359 PetscScalar *a; 1360 1361 size = hypre_CSRMatrixNumRows(ha); 1362 a = hypre_CSRMatrixData(ha); 1363 ii = hypre_CSRMatrixI(ha); 1364 for (i = 0; i < ii[size]; i++) a[i] *= s; 1365 } 1366 /* offdiagonal part */ 1367 ha = hypre_ParCSRMatrixOffd(parcsr); 1368 if (ha) { 1369 PetscInt size,i; 1370 HYPRE_Int *ii; 1371 PetscScalar *a; 1372 1373 size = hypre_CSRMatrixNumRows(ha); 1374 a = hypre_CSRMatrixData(ha); 1375 ii = hypre_CSRMatrixI(ha); 1376 for (i = 0; i < ii[size]; i++) a[i] *= s; 1377 } 1378 PetscFunctionReturn(0); 1379 } 1380 1381 static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 1382 { 1383 hypre_ParCSRMatrix *parcsr; 1384 HYPRE_Int *lrows; 1385 PetscInt rst,ren,i; 1386 PetscErrorCode ierr; 1387 1388 PetscFunctionBegin; 1389 if (x || b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"To be implemented"); 1390 ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr); 1391 ierr = PetscMalloc1(numRows,&lrows);CHKERRQ(ierr); 1392 ierr = MatGetOwnershipRange(A,&rst,&ren);CHKERRQ(ierr); 1393 for (i=0;i<numRows;i++) { 1394 if (rows[i] < rst || rows[i] >= ren) 1395 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-local rows not yet supported"); 1396 lrows[i] = rows[i] - rst; 1397 } 1398 PetscStackCallStandard(hypre_ParCSRMatrixEliminateRowsCols,(parcsr,numRows,lrows)); 1399 ierr = PetscFree(lrows);CHKERRQ(ierr); 1400 PetscFunctionReturn(0); 1401 } 1402 1403 /*MC 1404 MATHYPRE - MATHYPRE = "hypre" - A matrix type to be used for sequential and parallel sparse matrices 1405 based on the hypre IJ interface. 1406 1407 Level: intermediate 1408 1409 .seealso: MatCreate() 1410 M*/ 1411 1412 PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B) 1413 { 1414 Mat_HYPRE *hB; 1415 PetscErrorCode ierr; 1416 1417 PetscFunctionBegin; 1418 ierr = PetscNewLog(B,&hB);CHKERRQ(ierr); 1419 hB->inner_free = PETSC_TRUE; 1420 1421 B->data = (void*)hB; 1422 B->rmap->bs = 1; 1423 B->assembled = PETSC_FALSE; 1424 1425 B->ops->mult = MatMult_HYPRE; 1426 B->ops->multtranspose = MatMultTranspose_HYPRE; 1427 B->ops->setup = MatSetUp_HYPRE; 1428 B->ops->destroy = MatDestroy_HYPRE; 1429 B->ops->assemblyend = MatAssemblyEnd_HYPRE; 1430 B->ops->ptap = MatPtAP_HYPRE_HYPRE; 1431 B->ops->matmult = MatMatMult_HYPRE_HYPRE; 1432 B->ops->setvalues = MatSetValues_HYPRE; 1433 B->ops->missingdiagonal = MatMissingDiagonal_HYPRE; 1434 B->ops->scale = MatScale_HYPRE; 1435 B->ops->zerorowscolumns = MatZeroRowsColumns_HYPRE; 1436 1437 ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)B),&hB->comm);CHKERRQ(ierr); 1438 ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRE);CHKERRQ(ierr); 1439 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_hypre_aij_C",MatConvert_HYPRE_AIJ);CHKERRQ(ierr); 1440 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_hypre_is_C",MatConvert_HYPRE_IS);CHKERRQ(ierr); 1441 ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_seqaij_hypre_C",MatPtAP_AIJ_HYPRE);CHKERRQ(ierr); 1442 ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_mpiaij_hypre_C",MatPtAP_AIJ_HYPRE);CHKERRQ(ierr); 1443 ierr = PetscObjectComposeFunction((PetscObject)B,"MatHYPRESetPreallocation_C",MatHYPRESetPreallocation_HYPRE);CHKERRQ(ierr); 1444 ierr = PetscObjectComposeFunction((PetscObject)B,"MatHYPREGetParCSR_C",MatHYPREGetParCSR_HYPRE);CHKERRQ(ierr); 1445 PetscFunctionReturn(0); 1446 } 1447 1448 static PetscErrorCode hypre_array_destroy(void *ptr) 1449 { 1450 PetscFunctionBegin; 1451 hypre_TFree(ptr); 1452 PetscFunctionReturn(0); 1453 } 1454