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