1 2 /* 3 Creates hypre ijmatrix from PETSc matrix 4 */ 5 #include <petscsys.h> 6 #include <petsc/private/matimpl.h> 7 #include <../src/mat/impls/hypre/mhypre.h> 8 #include <../src/mat/impls/aij/mpi/mpiaij.h> 9 #include <../src/vec/vec/impls/hypre/vhyp.h> 10 #include <HYPRE.h> 11 12 static PetscErrorCode MatHYPRE_CreateFromMat(Mat,Mat_HYPRE*); 13 static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat,Mat,HYPRE_IJMatrix); 14 static PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat,HYPRE_IJMatrix); 15 static PetscErrorCode MatHYPRE_IJMatrixFastCopy_SeqAIJ(Mat,HYPRE_IJMatrix); 16 static PetscErrorCode MatHYPRE_MultKernel_Private(Mat,Vec,Vec,PetscBool); 17 18 #undef __FUNCT__ 19 #define __FUNCT__ "MatHYPRE_IJMatrixPreallocate" 20 static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat A_d, Mat A_o, HYPRE_IJMatrix ij) 21 { 22 PetscErrorCode ierr; 23 PetscInt i,n_d,n_o; 24 const PetscInt *ia_d,*ia_o; 25 PetscBool done_d=PETSC_FALSE,done_o=PETSC_FALSE; 26 PetscInt *nnz_d=NULL,*nnz_o=NULL; 27 28 PetscFunctionBegin; 29 if (A_d) { /* determine number of nonzero entries in local diagonal part */ 30 ierr = MatGetRowIJ(A_d,0,PETSC_FALSE,PETSC_FALSE,&n_d,&ia_d,NULL,&done_d);CHKERRQ(ierr); 31 if (done_d) { 32 ierr = PetscMalloc1(n_d,&nnz_d);CHKERRQ(ierr); 33 for (i=0; i<n_d; i++) { 34 nnz_d[i] = ia_d[i+1] - ia_d[i]; 35 } 36 } 37 ierr = MatRestoreRowIJ(A_d,0,PETSC_FALSE,PETSC_FALSE,NULL,&ia_d,NULL,&done_d);CHKERRQ(ierr); 38 } 39 if (A_o) { /* determine number of nonzero entries in local off-diagonal part */ 40 ierr = MatGetRowIJ(A_o,0,PETSC_FALSE,PETSC_FALSE,&n_o,&ia_o,NULL,&done_o);CHKERRQ(ierr); 41 if (done_o) { 42 ierr = PetscMalloc1(n_o,&nnz_o);CHKERRQ(ierr); 43 for (i=0; i<n_o; i++) { 44 nnz_o[i] = ia_o[i+1] - ia_o[i]; 45 } 46 } 47 ierr = MatRestoreRowIJ(A_o,0,PETSC_FALSE,PETSC_FALSE,&n_o,&ia_o,NULL,&done_o);CHKERRQ(ierr); 48 } 49 if (done_d) { /* set number of nonzeros in HYPRE IJ matrix */ 50 if (!done_o) { /* only diagonal part */ 51 ierr = PetscMalloc1(n_d,&nnz_o);CHKERRQ(ierr); 52 for (i=0; i<n_d; i++) { 53 nnz_o[i] = 0; 54 } 55 } 56 PetscStackCallStandard(HYPRE_IJMatrixSetDiagOffdSizes,(ij,(HYPRE_Int *)nnz_d,(HYPRE_Int *)nnz_o)); 57 ierr = PetscFree(nnz_d);CHKERRQ(ierr); 58 ierr = PetscFree(nnz_o);CHKERRQ(ierr); 59 } 60 PetscFunctionReturn(0); 61 } 62 63 #undef __FUNCT__ 64 #define __FUNCT__ "MatHYPRE_CreateFromMat" 65 static PetscErrorCode MatHYPRE_CreateFromMat(Mat A, Mat_HYPRE *hA) 66 { 67 PetscErrorCode ierr; 68 PetscInt rstart,rend,cstart,cend; 69 70 PetscFunctionBegin; 71 ierr = MatSetUp(A);CHKERRQ(ierr); 72 rstart = A->rmap->rstart; 73 rend = A->rmap->rend; 74 cstart = A->cmap->rstart; 75 cend = A->cmap->rend; 76 PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rstart,rend-1,cstart,cend-1,&hA->ij)); 77 PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR)); 78 { 79 PetscBool same; 80 Mat A_d,A_o; 81 const PetscInt *colmap; 82 ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&same);CHKERRQ(ierr); 83 if (same) { 84 ierr = MatMPIAIJGetSeqAIJ(A,&A_d,&A_o,&colmap);CHKERRQ(ierr); 85 ierr = MatHYPRE_IJMatrixPreallocate(A_d,A_o,hA->ij);CHKERRQ(ierr); 86 PetscFunctionReturn(0); 87 } 88 ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&same);CHKERRQ(ierr); 89 if (same) { 90 ierr = MatMPIBAIJGetSeqBAIJ(A,&A_d,&A_o,&colmap);CHKERRQ(ierr); 91 ierr = MatHYPRE_IJMatrixPreallocate(A_d,A_o,hA->ij);CHKERRQ(ierr); 92 PetscFunctionReturn(0); 93 } 94 ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&same);CHKERRQ(ierr); 95 if (same) { 96 ierr = MatHYPRE_IJMatrixPreallocate(A,NULL,hA->ij);CHKERRQ(ierr); 97 PetscFunctionReturn(0); 98 } 99 ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQBAIJ,&same);CHKERRQ(ierr); 100 if (same) { 101 ierr = MatHYPRE_IJMatrixPreallocate(A,NULL,hA->ij);CHKERRQ(ierr); 102 PetscFunctionReturn(0); 103 } 104 } 105 PetscFunctionReturn(0); 106 } 107 108 #undef __FUNCT__ 109 #define __FUNCT__ "MatHYPRE_IJMatrixCopy" 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 PetscStackCallStandard(HYPRE_IJMatrixSetValues,(ij,1,(HYPRE_Int *)&ncols,(HYPRE_Int *)&i,(HYPRE_Int *)cols,values)); 136 ierr = MatRestoreRow(A,i,&ncols,&cols,&values);CHKERRQ(ierr); 137 } 138 PetscFunctionReturn(0); 139 } 140 141 #undef __FUNCT__ 142 #define __FUNCT__ "MatHYPRE_IJMatrixFastCopy_SeqAIJ" 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 #undef __FUNCT__ 171 #define __FUNCT__ "MatHYPRE_IJMatrixFastCopy_MPIAIJ" 172 static PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat A, HYPRE_IJMatrix ij) 173 { 174 PetscErrorCode ierr; 175 Mat_MPIAIJ *pA = (Mat_MPIAIJ*)A->data; 176 Mat_SeqAIJ *pdiag,*poffd; 177 PetscInt i,*garray = pA->garray,*jj,cstart,*pjj; 178 HYPRE_Int type; 179 hypre_ParCSRMatrix *par_matrix; 180 hypre_AuxParCSRMatrix *aux_matrix; 181 hypre_CSRMatrix *hdiag,*hoffd; 182 183 PetscFunctionBegin; 184 pdiag = (Mat_SeqAIJ*) pA->A->data; 185 poffd = (Mat_SeqAIJ*) pA->B->data; 186 /* cstart is only valid for square MPIAIJ layed out in the usual way */ 187 ierr = MatGetOwnershipRange(A,&cstart,NULL);CHKERRQ(ierr); 188 189 PetscStackCallStandard(HYPRE_IJMatrixInitialize,(ij)); 190 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(ij,&type)); 191 if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 192 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(ij,(void**)&par_matrix)); 193 hdiag = hypre_ParCSRMatrixDiag(par_matrix); 194 hoffd = hypre_ParCSRMatrixOffd(par_matrix); 195 196 /* 197 this is the Hack part where we monkey directly with the hypre datastructures 198 */ 199 ierr = PetscMemcpy(hdiag->i,pdiag->i,(pA->A->rmap->n + 1)*sizeof(PetscInt)); 200 /* need to shift the diag column indices (hdiag->j) back to global numbering since hypre is expecting this */ 201 jj = (PetscInt*)hdiag->j; 202 pjj = (PetscInt*)pdiag->j; 203 for (i=0; i<pdiag->nz; i++) jj[i] = cstart + pjj[i]; 204 ierr = PetscMemcpy(hdiag->data,pdiag->a,pdiag->nz*sizeof(PetscScalar)); 205 ierr = PetscMemcpy(hoffd->i,poffd->i,(pA->A->rmap->n + 1)*sizeof(PetscInt)); 206 /* need to move the offd column indices (hoffd->j) back to global numbering since hypre is expecting this 207 If we hacked a hypre a bit more we might be able to avoid this step */ 208 jj = (PetscInt*) hoffd->j; 209 pjj = (PetscInt*) poffd->j; 210 for (i=0; i<poffd->nz; i++) jj[i] = garray[pjj[i]]; 211 ierr = PetscMemcpy(hoffd->data,poffd->a,poffd->nz*sizeof(PetscScalar)); 212 213 aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij); 214 hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0; 215 PetscFunctionReturn(0); 216 } 217 218 #undef __FUNCT__ 219 #define __FUNCT__ "MatConvert_HYPRE_IS" 220 static PetscErrorCode MatConvert_HYPRE_IS(Mat A, MatType mtype, MatReuse reuse, Mat* B) 221 { 222 Mat_HYPRE* mhA = (Mat_HYPRE*)(A->data); 223 Mat lA; 224 ISLocalToGlobalMapping rl2g,cl2g; 225 IS is; 226 hypre_ParCSRMatrix *hA; 227 hypre_CSRMatrix *hdiag,*hoffd; 228 MPI_Comm comm; 229 PetscScalar *hdd,*hod,*aa,*data; 230 PetscInt *col_map_offd,*hdi,*hdj,*hoi,*hoj; 231 PetscInt *ii,*jj,*iptr,*jptr; 232 PetscInt cum,dr,dc,oc,str,stc,nnz,i,jd,jo,M,N; 233 HYPRE_Int type; 234 PetscErrorCode ierr; 235 236 PetscFunctionBegin; 237 comm = PetscObjectComm((PetscObject)A); 238 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(mhA->ij,&type)); 239 if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 240 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(mhA->ij,(void**)&hA)); 241 M = hypre_ParCSRMatrixGlobalNumRows(hA); 242 N = hypre_ParCSRMatrixGlobalNumCols(hA); 243 str = hypre_ParCSRMatrixFirstRowIndex(hA); 244 stc = hypre_ParCSRMatrixFirstColDiag(hA); 245 hdiag = hypre_ParCSRMatrixDiag(hA); 246 hoffd = hypre_ParCSRMatrixOffd(hA); 247 dr = hypre_CSRMatrixNumRows(hdiag); 248 dc = hypre_CSRMatrixNumCols(hdiag); 249 nnz = hypre_CSRMatrixNumNonzeros(hdiag); 250 hdi = hypre_CSRMatrixI(hdiag); 251 hdj = hypre_CSRMatrixJ(hdiag); 252 hdd = hypre_CSRMatrixData(hdiag); 253 oc = hypre_CSRMatrixNumCols(hoffd); 254 nnz += hypre_CSRMatrixNumNonzeros(hoffd); 255 hoi = hypre_CSRMatrixI(hoffd); 256 hoj = hypre_CSRMatrixJ(hoffd); 257 hod = hypre_CSRMatrixData(hoffd); 258 if (reuse != MAT_REUSE_MATRIX) { 259 PetscInt *aux; 260 261 /* generate l2g maps for rows and cols */ 262 ierr = ISCreateStride(comm,dr,str,1,&is);CHKERRQ(ierr); 263 ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr); 264 ierr = ISDestroy(&is);CHKERRQ(ierr); 265 col_map_offd = hypre_ParCSRMatrixColMapOffd(hA); 266 ierr = PetscMalloc1(dc+oc,&aux);CHKERRQ(ierr); 267 for (i=0; i<dc; i++) aux[i] = i+stc; 268 for (i=0; i<oc; i++) aux[i+dc] = col_map_offd[i]; 269 ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 270 ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr); 271 ierr = ISDestroy(&is);CHKERRQ(ierr); 272 /* create MATIS object */ 273 ierr = MatCreate(comm,B);CHKERRQ(ierr); 274 ierr = MatSetSizes(*B,dr,dc,M,N);CHKERRQ(ierr); 275 ierr = MatSetType(*B,MATIS);CHKERRQ(ierr); 276 ierr = MatSetLocalToGlobalMapping(*B,rl2g,cl2g);CHKERRQ(ierr); 277 ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 278 ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 279 280 /* allocate CSR for local matrix */ 281 ierr = PetscMalloc1(dr+1,&iptr);CHKERRQ(ierr); 282 ierr = PetscMalloc1(nnz,&jptr);CHKERRQ(ierr); 283 ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr); 284 } else { 285 PetscInt nr; 286 PetscBool done; 287 ierr = MatISGetLocalMat(*B,&lA);CHKERRQ(ierr); 288 ierr = MatGetRowIJ(lA,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&iptr,(const PetscInt**)&jptr,&done);CHKERRQ(ierr); 289 if (nr != dr) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of rows in local mat! %D != %D",nr,dr); 290 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); 291 ierr = MatSeqAIJGetArray(lA,&data);CHKERRQ(ierr); 292 } 293 /* merge local matrices */ 294 ii = iptr; 295 jj = jptr; 296 aa = data; 297 *ii = *(hdi++) + *(hoi++); 298 for (jd=0,jo=0,cum=0; *ii<nnz; cum++) { 299 PetscScalar *aold = aa; 300 PetscInt *jold = jj,nc = jd+jo; 301 for (; jd<*hdi; jd++) { *jj++ = *hdj++; *aa++ = *hdd++; } 302 for (; jo<*hoi; jo++) { *jj++ = *hoj++ + dc; *aa++ = *hod++; } 303 *(++ii) = *(hdi++) + *(hoi++); 304 ierr = PetscSortIntWithScalarArray(jd+jo-nc,jold,aold);CHKERRQ(ierr); 305 } 306 for (; cum<dr; cum++) *(++ii) = nnz; 307 if (reuse != MAT_REUSE_MATRIX) { 308 Mat_SeqAIJ* a; 309 310 ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,dc+oc,iptr,jptr,data,&lA);CHKERRQ(ierr); 311 ierr = MatISSetLocalMat(*B,lA);CHKERRQ(ierr); 312 /* hack SeqAIJ */ 313 a = (Mat_SeqAIJ*)(lA->data); 314 a->free_a = PETSC_TRUE; 315 a->free_ij = PETSC_TRUE; 316 ierr = MatDestroy(&lA);CHKERRQ(ierr); 317 } 318 ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 319 ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 320 if (reuse == MAT_INPLACE_MATRIX) { 321 ierr = MatHeaderReplace(A,B);CHKERRQ(ierr); 322 } 323 PetscFunctionReturn(0); 324 } 325 326 #undef __FUNCT__ 327 #define __FUNCT__ "MatConvert_AIJ_HYPRE" 328 PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B) 329 { 330 Mat_HYPRE *hB; 331 MPI_Comm comm = PetscObjectComm((PetscObject)A); 332 PetscErrorCode ierr; 333 334 PetscFunctionBegin; 335 if (reuse == MAT_INPLACE_MATRIX) SETERRQ(comm,PETSC_ERR_SUP,"Unsupported MAT_INPLACE_MATRIX"); 336 if (reuse == MAT_REUSE_MATRIX) { 337 /* always destroy the old matrix and create a new memory; 338 hope this does not churn the memory too much. The problem 339 is I do not know if it is possible to put the matrix back to 340 its initial state so that we can directly copy the values 341 the second time through. */ 342 hB = (Mat_HYPRE*)((*B)->data); 343 PetscStackCallStandard(HYPRE_IJMatrixDestroy,(hB->ij)); 344 } else { 345 ierr = MatCreate(comm,B);CHKERRQ(ierr); 346 ierr = MatSetType(*B,MATHYPRE);CHKERRQ(ierr); 347 ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 348 ierr = MatSetUp(*B);CHKERRQ(ierr); 349 hB = (Mat_HYPRE*)((*B)->data); 350 } 351 ierr = MatHYPRE_CreateFromMat(A,hB);CHKERRQ(ierr); 352 ierr = MatHYPRE_IJMatrixCopy(A,hB->ij);CHKERRQ(ierr); 353 ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 354 ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 355 PetscFunctionReturn(0); 356 } 357 358 #undef __FUNCT__ 359 #define __FUNCT__ "MatConvert_HYPRE_AIJ" 360 static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B) 361 { 362 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 363 hypre_ParCSRMatrix *parcsr; 364 hypre_CSRMatrix *hdiag,*hoffd; 365 MPI_Comm comm; 366 PetscScalar *da,*oa,*aptr; 367 PetscInt *dii,*djj,*oii,*ojj,*iptr; 368 PetscInt i,dnnz,onnz,m,n; 369 HYPRE_Int type; 370 PetscMPIInt size; 371 PetscErrorCode ierr; 372 373 PetscFunctionBegin; 374 comm = PetscObjectComm((PetscObject)A); 375 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type)); 376 if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 377 if (reuse == MAT_REUSE_MATRIX) { 378 PetscBool ismpiaij,isseqaij; 379 ierr = PetscObjectTypeCompare((PetscObject)*B,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr); 380 ierr = PetscObjectTypeCompare((PetscObject)*B,MATSEQAIJ,&isseqaij);CHKERRQ(ierr); 381 if (!ismpiaij && !isseqaij) SETERRQ(comm,PETSC_ERR_SUP,"Only MATMPIAIJ or MATSEQAIJ are supported"); 382 } 383 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 384 385 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr)); 386 hdiag = hypre_ParCSRMatrixDiag(parcsr); 387 hoffd = hypre_ParCSRMatrixOffd(parcsr); 388 m = hypre_CSRMatrixNumRows(hdiag); 389 n = hypre_CSRMatrixNumCols(hdiag); 390 dnnz = hypre_CSRMatrixNumNonzeros(hdiag); 391 onnz = hypre_CSRMatrixNumNonzeros(hoffd); 392 if (reuse != MAT_REUSE_MATRIX) { 393 ierr = PetscMalloc1(m+1,&dii);CHKERRQ(ierr); 394 ierr = PetscMalloc1(dnnz,&djj);CHKERRQ(ierr); 395 ierr = PetscMalloc1(dnnz,&da);CHKERRQ(ierr); 396 } else { 397 PetscInt nr; 398 PetscBool done; 399 if (size > 1) { 400 Mat_MPIAIJ *b = (Mat_MPIAIJ*)((*B)->data); 401 402 ierr = MatGetRowIJ(b->A,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&dii,(const PetscInt**)&djj,&done);CHKERRQ(ierr); 403 if (nr != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of local rows in diag part! %D != %D",nr,m); 404 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); 405 ierr = MatSeqAIJGetArray(b->A,&da);CHKERRQ(ierr); 406 } else { 407 ierr = MatGetRowIJ(*B,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&dii,(const PetscInt**)&djj,&done);CHKERRQ(ierr); 408 if (nr != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of local rows! %D != %D",nr,m); 409 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); 410 ierr = MatSeqAIJGetArray(*B,&da);CHKERRQ(ierr); 411 } 412 } 413 ierr = PetscMemcpy(dii,hypre_CSRMatrixI(hdiag),(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 414 ierr = PetscMemcpy(djj,hypre_CSRMatrixJ(hdiag),dnnz*sizeof(PetscInt));CHKERRQ(ierr); 415 ierr = PetscMemcpy(da,hypre_CSRMatrixData(hdiag),dnnz*sizeof(PetscScalar));CHKERRQ(ierr); 416 iptr = djj; 417 aptr = da; 418 for (i=0; i<m; i++) { 419 PetscInt nc = dii[i+1]-dii[i]; 420 ierr = PetscSortIntWithScalarArray(nc,iptr,aptr);CHKERRQ(ierr); 421 iptr += nc; 422 aptr += nc; 423 } 424 if (size > 1) { 425 PetscInt *offdj,*coffd; 426 427 if (reuse != MAT_REUSE_MATRIX) { 428 ierr = PetscMalloc1(m+1,&oii);CHKERRQ(ierr); 429 ierr = PetscMalloc1(onnz,&ojj);CHKERRQ(ierr); 430 ierr = PetscMalloc1(onnz,&oa);CHKERRQ(ierr); 431 } else { 432 Mat_MPIAIJ *b = (Mat_MPIAIJ*)((*B)->data); 433 PetscInt nr,hr = hypre_CSRMatrixNumRows(hoffd); 434 PetscBool done; 435 436 ierr = MatGetRowIJ(b->B,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&oii,(const PetscInt**)&ojj,&done);CHKERRQ(ierr); 437 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); 438 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); 439 ierr = MatSeqAIJGetArray(b->B,&oa);CHKERRQ(ierr); 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_REUSE_MATRIX) { 455 Mat_MPIAIJ *b; 456 Mat_SeqAIJ *d,*o; 457 ierr = MatCreateMPIAIJWithSplitArrays(comm,m,n,PETSC_DECIDE,PETSC_DECIDE,dii, 458 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 } 468 } else if (reuse != MAT_REUSE_MATRIX) { 469 Mat_SeqAIJ* b; 470 ierr = MatCreateSeqAIJWithArrays(comm,m,n,dii,djj,da,B);CHKERRQ(ierr); 471 /* hack SeqAIJ */ 472 b = (Mat_SeqAIJ*)((*B)->data); 473 b->free_a = PETSC_TRUE; 474 b->free_ij = PETSC_TRUE; 475 } 476 if (reuse == MAT_INPLACE_MATRIX) { 477 ierr = MatHeaderReplace(A,B);CHKERRQ(ierr); 478 } 479 PetscFunctionReturn(0); 480 } 481 482 #undef __FUNCT__ 483 #define __FUNCT__ "MatMultTranspose_HYPRE" 484 static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y) 485 { 486 PetscErrorCode ierr; 487 488 PetscFunctionBegin; 489 ierr = MatHYPRE_MultKernel_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr); 490 PetscFunctionReturn(0); 491 } 492 493 #undef __FUNCT__ 494 #define __FUNCT__ "MatMult_HYPRE" 495 static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y) 496 { 497 PetscErrorCode ierr; 498 499 PetscFunctionBegin; 500 ierr = MatHYPRE_MultKernel_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr); 501 PetscFunctionReturn(0); 502 } 503 504 #undef __FUNCT__ 505 #define __FUNCT__ "MatHYPRE_MultKernel_Private" 506 static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, Vec x, Vec y, PetscBool trans) 507 { 508 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 509 hypre_ParCSRMatrix *parcsr; 510 hypre_ParVector *hx,*hy; 511 PetscScalar *ax,*ay,*sax,*say; 512 PetscErrorCode ierr; 513 514 PetscFunctionBegin; 515 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr)); 516 PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->x,(void**)&hx)); 517 PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->b,(void**)&hy)); 518 ierr = VecGetArrayRead(x,(const PetscScalar**)&ax);CHKERRQ(ierr); 519 ierr = VecGetArray(y,&ay);CHKERRQ(ierr); 520 if (trans) { 521 VecHYPRE_ParVectorReplacePointer(hA->x,ay,say); 522 VecHYPRE_ParVectorReplacePointer(hA->b,ax,sax); 523 hypre_ParCSRMatrixMatvecT(1.,parcsr,hy,0.,hx); 524 VecHYPRE_ParVectorReplacePointer(hA->x,say,ay); 525 VecHYPRE_ParVectorReplacePointer(hA->b,sax,ax); 526 } else { 527 VecHYPRE_ParVectorReplacePointer(hA->x,ax,sax); 528 VecHYPRE_ParVectorReplacePointer(hA->b,ay,say); 529 hypre_ParCSRMatrixMatvec(1.,parcsr,hx,0.,hy); 530 VecHYPRE_ParVectorReplacePointer(hA->x,sax,ax); 531 VecHYPRE_ParVectorReplacePointer(hA->b,say,ay); 532 } 533 ierr = VecRestoreArrayRead(x,(const PetscScalar**)&ax);CHKERRQ(ierr); 534 ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr); 535 PetscFunctionReturn(0); 536 } 537 538 #undef __FUNCT__ 539 #define __FUNCT__ "MatDestroy_HYPRE" 540 static PetscErrorCode MatDestroy_HYPRE(Mat A) 541 { 542 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 543 PetscErrorCode ierr; 544 545 PetscFunctionBegin; 546 if (hA->x) PetscStackCallStandard(HYPRE_IJVectorDestroy,(hA->x)); 547 if (hA->b) PetscStackCallStandard(HYPRE_IJVectorDestroy,(hA->b)); 548 if (hA->ij) { 549 if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL; 550 PetscStackCallStandard(HYPRE_IJMatrixDestroy,(hA->ij)); 551 } 552 if (hA->comm) { ierr = MPI_Comm_free(&hA->comm);CHKERRQ(ierr); } 553 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_hypre_aij_C",NULL);CHKERRQ(ierr); 554 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_hypre_is_C",NULL);CHKERRQ(ierr); 555 ierr = PetscFree(A->data);CHKERRQ(ierr); 556 PetscFunctionReturn(0); 557 } 558 559 #undef __FUNCT__ 560 #define __FUNCT__ "MatSetUp_HYPRE" 561 static PetscErrorCode MatSetUp_HYPRE(Mat A) 562 { 563 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 564 Vec x,b; 565 PetscErrorCode ierr; 566 567 PetscFunctionBegin; 568 if (hA->x) PetscFunctionReturn(0); 569 ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 570 ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 571 ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)A),1,A->cmap->n,A->cmap->N,NULL,&x);CHKERRQ(ierr); 572 ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)A),1,A->rmap->n,A->rmap->N,NULL,&b);CHKERRQ(ierr); 573 ierr = VecHYPRE_IJVectorCreate(x,&hA->x);CHKERRQ(ierr); 574 ierr = VecHYPRE_IJVectorCreate(b,&hA->b);CHKERRQ(ierr); 575 ierr = VecDestroy(&x);CHKERRQ(ierr); 576 ierr = VecDestroy(&b);CHKERRQ(ierr); 577 PetscFunctionReturn(0); 578 } 579 580 #undef __FUNCT__ 581 #define __FUNCT__ "MatAssemblyEnd_HYPRE" 582 static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode) 583 { 584 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 585 PetscErrorCode ierr; 586 587 PetscFunctionBegin; 588 PetscStackCallStandard(HYPRE_IJMatrixAssemble,(hA->ij)); 589 PetscFunctionReturn(0); 590 } 591 592 #undef __FUNCT__ 593 #define __FUNCT__ "MatHYPRECreateFromParCSR" 594 PETSC_EXTERN PetscErrorCode MatHYPRECreateFromParCSR(void *vparcsr, PetscCopyMode copymode, Mat* A) 595 { 596 Mat_HYPRE *hA; 597 hypre_ParCSRMatrix *parcsr; 598 MPI_Comm comm; 599 PetscInt rstart,rend,cstart,cend,M,N; 600 PetscErrorCode ierr; 601 602 PetscFunctionBegin; 603 parcsr = (hypre_ParCSRMatrix *)vparcsr; 604 comm = hypre_ParCSRMatrixComm(parcsr); 605 if (copymode == PETSC_COPY_VALUES) SETERRQ(comm,PETSC_ERR_SUP,"Unsupported copymode PETSC_COPY_VALUES"); 606 607 /* access ParCSRMatrix */ 608 rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr); 609 rend = hypre_ParCSRMatrixLastRowIndex(parcsr); 610 cstart = hypre_ParCSRMatrixFirstColDiag(parcsr); 611 cend = hypre_ParCSRMatrixLastColDiag(parcsr); 612 M = hypre_ParCSRMatrixGlobalNumRows(parcsr); 613 N = hypre_ParCSRMatrixGlobalNumCols(parcsr); 614 615 /* create PETSc matrix with MatHYPRE */ 616 ierr = MatCreate(comm,A);CHKERRQ(ierr); 617 ierr = MatSetSizes(*A,rend-rstart+1,cend-cstart+1,M,N);CHKERRQ(ierr); 618 ierr = MatSetType(*A,MATHYPRE);CHKERRQ(ierr); 619 ierr = MatSetUp(*A);CHKERRQ(ierr); 620 hA = (Mat_HYPRE*)((*A)->data); 621 622 /* create HYPRE_IJMatrix */ 623 PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rstart,rend-1,cstart,cend-1,&hA->ij)); 624 625 /* set ParCSR object */ 626 PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR)); 627 hypre_IJMatrixObject(hA->ij) = parcsr; 628 629 /* set assembled flag */ 630 hypre_IJMatrixAssembleFlag(hA->ij) = 1; 631 PetscStackCallStandard(HYPRE_IJMatrixInitialize,(hA->ij)); 632 633 /* prevent from freeing the pointer */ 634 if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE; 635 636 ierr = MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 637 ierr = MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 638 PetscFunctionReturn(0); 639 } 640 641 #undef __FUNCT__ 642 #define __FUNCT__ "MatCreate_HYPRE" 643 PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B) 644 { 645 Mat_HYPRE *hB; 646 PetscErrorCode ierr; 647 648 PetscFunctionBegin; 649 ierr = PetscNewLog(B,&hB);CHKERRQ(ierr); 650 hB->inner_free = PETSC_TRUE; 651 652 B->data = (void*)hB; 653 B->rmap->bs = 1; 654 B->assembled = PETSC_FALSE; 655 656 B->ops->mult = MatMult_HYPRE; 657 B->ops->multtranspose = MatMultTranspose_HYPRE; 658 B->ops->setup = MatSetUp_HYPRE; 659 B->ops->destroy = MatDestroy_HYPRE; 660 B->ops->assemblyend = MatAssemblyEnd_HYPRE; 661 662 ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)B),&hB->comm);CHKERRQ(ierr); 663 ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRE);CHKERRQ(ierr); 664 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_hypre_aij_C",MatConvert_HYPRE_AIJ);CHKERRQ(ierr); 665 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_hypre_is_C",MatConvert_HYPRE_IS);CHKERRQ(ierr); 666 PetscFunctionReturn(0); 667 } 668 669 #if 0 670 /* 671 Does NOT copy the data over, instead uses DIRECTLY the pointers from the PETSc MPIAIJ format 672 673 This is UNFINISHED and does NOT work! The problem is that hypre puts the diagonal entry first 674 which will corrupt the PETSc data structure if we did this. Need a work around to this problem. 675 */ 676 #include <_hypre_IJ_mv.h> 677 #include <HYPRE_IJ_mv.h> 678 679 #undef __FUNCT__ 680 #define __FUNCT__ "MatHYPRE_IJMatrixLink" 681 PetscErrorCode MatHYPRE_IJMatrixLink(Mat A, HYPRE_IJMatrix *ij) 682 { 683 PetscErrorCode ierr; 684 PetscInt rstart,rend,cstart,cend; 685 PetscBool flg; 686 hypre_AuxParCSRMatrix *aux_matrix; 687 688 PetscFunctionBegin; 689 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 690 PetscValidType(A,1); 691 PetscValidPointer(ij,2); 692 ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&flg);CHKERRQ(ierr); 693 if (!flg) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Can only use with PETSc MPIAIJ matrices"); 694 ierr = MatSetUp(A);CHKERRQ(ierr); 695 696 ierr = PetscLogEventBegin(MAT_Convert,A,0,0,0);CHKERRQ(ierr); 697 rstart = A->rmap->rstart; 698 rend = A->rmap->rend; 699 cstart = A->cmap->rstart; 700 cend = A->cmap->rend; 701 PetscStackCallStandard(HYPRE_IJMatrixCreate,(PetscObjectComm((PetscObject)A),rstart,rend-1,cstart,cend-1,ij)); 702 PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(*ij,HYPRE_PARCSR)); 703 704 PetscStackCallStandard(HYPRE_IJMatrixInitialize,(*ij)); 705 PetscStackCall("hypre_IJMatrixTranslator",aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(*ij)); 706 707 hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0; 708 709 /* this is the Hack part where we monkey directly with the hypre datastructures */ 710 711 PetscStackCallStandard(HYPRE_IJMatrixAssemble,(*ij)); 712 ierr = PetscLogEventEnd(MAT_Convert,A,0,0,0);CHKERRQ(ierr); 713 PetscFunctionReturn(0); 714 } 715 #endif 716