1 2 /* 3 Creates hypre ijmatrix from PETSc matrix 4 */ 5 6 /*MC 7 MATHYPRE - MATHYPRE = "hypre" - A matrix type to be used for sequential and parallel sparse matrices 8 based on the hypre IJ interface. 9 10 Level: intermediate 11 12 .seealso: MatCreate() 13 M*/ 14 15 #include <petscsys.h> 16 #include <petsc/private/matimpl.h> 17 #include <../src/mat/impls/hypre/mhypre.h> 18 #include <../src/mat/impls/aij/mpi/mpiaij.h> 19 #include <../src/vec/vec/impls/hypre/vhyp.h> 20 #include <HYPRE.h> 21 #include <HYPRE_utilities.h> 22 #include <_hypre_parcsr_ls.h> 23 24 static PetscErrorCode MatHYPRE_CreateFromMat(Mat,Mat_HYPRE*); 25 static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat,Mat,HYPRE_IJMatrix); 26 static PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat,HYPRE_IJMatrix); 27 static PetscErrorCode MatHYPRE_IJMatrixFastCopy_SeqAIJ(Mat,HYPRE_IJMatrix); 28 static PetscErrorCode MatHYPRE_MultKernel_Private(Mat,Vec,Vec,PetscBool); 29 static PetscErrorCode hypre_array_destroy(void*); 30 31 #undef __FUNCT__ 32 #define __FUNCT__ "MatHYPRE_IJMatrixPreallocate" 33 static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat A_d, Mat A_o, HYPRE_IJMatrix ij) 34 { 35 PetscErrorCode ierr; 36 PetscInt i,n_d,n_o; 37 const PetscInt *ia_d,*ia_o; 38 PetscBool done_d=PETSC_FALSE,done_o=PETSC_FALSE; 39 PetscInt *nnz_d=NULL,*nnz_o=NULL; 40 41 PetscFunctionBegin; 42 if (A_d) { /* determine number of nonzero entries in local diagonal part */ 43 ierr = MatGetRowIJ(A_d,0,PETSC_FALSE,PETSC_FALSE,&n_d,&ia_d,NULL,&done_d);CHKERRQ(ierr); 44 if (done_d) { 45 ierr = PetscMalloc1(n_d,&nnz_d);CHKERRQ(ierr); 46 for (i=0; i<n_d; i++) { 47 nnz_d[i] = ia_d[i+1] - ia_d[i]; 48 } 49 } 50 ierr = MatRestoreRowIJ(A_d,0,PETSC_FALSE,PETSC_FALSE,NULL,&ia_d,NULL,&done_d);CHKERRQ(ierr); 51 } 52 if (A_o) { /* determine number of nonzero entries in local off-diagonal part */ 53 ierr = MatGetRowIJ(A_o,0,PETSC_FALSE,PETSC_FALSE,&n_o,&ia_o,NULL,&done_o);CHKERRQ(ierr); 54 if (done_o) { 55 ierr = PetscMalloc1(n_o,&nnz_o);CHKERRQ(ierr); 56 for (i=0; i<n_o; i++) { 57 nnz_o[i] = ia_o[i+1] - ia_o[i]; 58 } 59 } 60 ierr = MatRestoreRowIJ(A_o,0,PETSC_FALSE,PETSC_FALSE,&n_o,&ia_o,NULL,&done_o);CHKERRQ(ierr); 61 } 62 if (done_d) { /* set number of nonzeros in HYPRE IJ matrix */ 63 if (!done_o) { /* only diagonal part */ 64 ierr = PetscMalloc1(n_d,&nnz_o);CHKERRQ(ierr); 65 for (i=0; i<n_d; i++) { 66 nnz_o[i] = 0; 67 } 68 } 69 PetscStackCallStandard(HYPRE_IJMatrixSetDiagOffdSizes,(ij,(HYPRE_Int *)nnz_d,(HYPRE_Int *)nnz_o)); 70 ierr = PetscFree(nnz_d);CHKERRQ(ierr); 71 ierr = PetscFree(nnz_o);CHKERRQ(ierr); 72 } 73 PetscFunctionReturn(0); 74 } 75 76 #undef __FUNCT__ 77 #define __FUNCT__ "MatHYPRE_CreateFromMat" 78 static PetscErrorCode MatHYPRE_CreateFromMat(Mat A, Mat_HYPRE *hA) 79 { 80 PetscErrorCode ierr; 81 PetscInt rstart,rend,cstart,cend; 82 83 PetscFunctionBegin; 84 ierr = MatSetUp(A);CHKERRQ(ierr); 85 rstart = A->rmap->rstart; 86 rend = A->rmap->rend; 87 cstart = A->cmap->rstart; 88 cend = A->cmap->rend; 89 PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rstart,rend-1,cstart,cend-1,&hA->ij)); 90 PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR)); 91 { 92 PetscBool same; 93 Mat A_d,A_o; 94 const PetscInt *colmap; 95 ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&same);CHKERRQ(ierr); 96 if (same) { 97 ierr = MatMPIAIJGetSeqAIJ(A,&A_d,&A_o,&colmap);CHKERRQ(ierr); 98 ierr = MatHYPRE_IJMatrixPreallocate(A_d,A_o,hA->ij);CHKERRQ(ierr); 99 PetscFunctionReturn(0); 100 } 101 ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&same);CHKERRQ(ierr); 102 if (same) { 103 ierr = MatMPIBAIJGetSeqBAIJ(A,&A_d,&A_o,&colmap);CHKERRQ(ierr); 104 ierr = MatHYPRE_IJMatrixPreallocate(A_d,A_o,hA->ij);CHKERRQ(ierr); 105 PetscFunctionReturn(0); 106 } 107 ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&same);CHKERRQ(ierr); 108 if (same) { 109 ierr = MatHYPRE_IJMatrixPreallocate(A,NULL,hA->ij);CHKERRQ(ierr); 110 PetscFunctionReturn(0); 111 } 112 ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQBAIJ,&same);CHKERRQ(ierr); 113 if (same) { 114 ierr = MatHYPRE_IJMatrixPreallocate(A,NULL,hA->ij);CHKERRQ(ierr); 115 PetscFunctionReturn(0); 116 } 117 } 118 PetscFunctionReturn(0); 119 } 120 121 #undef __FUNCT__ 122 #define __FUNCT__ "MatHYPRE_IJMatrixCopy" 123 static PetscErrorCode MatHYPRE_IJMatrixCopy(Mat A, HYPRE_IJMatrix ij) 124 { 125 PetscErrorCode ierr; 126 PetscInt i,rstart,rend,ncols,nr,nc; 127 const PetscScalar *values; 128 const PetscInt *cols; 129 PetscBool flg; 130 131 PetscFunctionBegin; 132 ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&flg);CHKERRQ(ierr); 133 ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr); 134 if (flg && nr == nc) { 135 ierr = MatHYPRE_IJMatrixFastCopy_MPIAIJ(A,ij);CHKERRQ(ierr); 136 PetscFunctionReturn(0); 137 } 138 ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&flg);CHKERRQ(ierr); 139 if (flg) { 140 ierr = MatHYPRE_IJMatrixFastCopy_SeqAIJ(A,ij);CHKERRQ(ierr); 141 PetscFunctionReturn(0); 142 } 143 144 PetscStackCallStandard(HYPRE_IJMatrixInitialize,(ij)); 145 ierr = MatGetOwnershipRange(A,&rstart,&rend);CHKERRQ(ierr); 146 for (i=rstart; i<rend; i++) { 147 ierr = MatGetRow(A,i,&ncols,&cols,&values);CHKERRQ(ierr); 148 PetscStackCallStandard(HYPRE_IJMatrixSetValues,(ij,1,(HYPRE_Int *)&ncols,(HYPRE_Int *)&i,(HYPRE_Int *)cols,values)); 149 ierr = MatRestoreRow(A,i,&ncols,&cols,&values);CHKERRQ(ierr); 150 } 151 PetscFunctionReturn(0); 152 } 153 154 #undef __FUNCT__ 155 #define __FUNCT__ "MatHYPRE_IJMatrixFastCopy_SeqAIJ" 156 static PetscErrorCode MatHYPRE_IJMatrixFastCopy_SeqAIJ(Mat A, HYPRE_IJMatrix ij) 157 { 158 PetscErrorCode ierr; 159 Mat_SeqAIJ *pdiag = (Mat_SeqAIJ*)A->data; 160 HYPRE_Int type; 161 hypre_ParCSRMatrix *par_matrix; 162 hypre_AuxParCSRMatrix *aux_matrix; 163 hypre_CSRMatrix *hdiag; 164 165 PetscFunctionBegin; 166 PetscStackCallStandard(HYPRE_IJMatrixInitialize,(ij)); 167 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(ij,&type)); 168 if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 169 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(ij,(void**)&par_matrix)); 170 hdiag = hypre_ParCSRMatrixDiag(par_matrix); 171 /* 172 this is the Hack part where we monkey directly with the hypre datastructures 173 */ 174 ierr = PetscMemcpy(hdiag->i,pdiag->i,(A->rmap->n + 1)*sizeof(PetscInt)); 175 ierr = PetscMemcpy(hdiag->j,pdiag->j,pdiag->nz*sizeof(PetscInt)); 176 ierr = PetscMemcpy(hdiag->data,pdiag->a,pdiag->nz*sizeof(PetscScalar)); 177 178 aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij); 179 hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0; 180 PetscFunctionReturn(0); 181 } 182 183 #undef __FUNCT__ 184 #define __FUNCT__ "MatHYPRE_IJMatrixFastCopy_MPIAIJ" 185 static PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat A, HYPRE_IJMatrix ij) 186 { 187 PetscErrorCode ierr; 188 Mat_MPIAIJ *pA = (Mat_MPIAIJ*)A->data; 189 Mat_SeqAIJ *pdiag,*poffd; 190 PetscInt i,*garray = pA->garray,*jj,cstart,*pjj; 191 HYPRE_Int type; 192 hypre_ParCSRMatrix *par_matrix; 193 hypre_AuxParCSRMatrix *aux_matrix; 194 hypre_CSRMatrix *hdiag,*hoffd; 195 196 PetscFunctionBegin; 197 pdiag = (Mat_SeqAIJ*) pA->A->data; 198 poffd = (Mat_SeqAIJ*) pA->B->data; 199 /* cstart is only valid for square MPIAIJ layed out in the usual way */ 200 ierr = MatGetOwnershipRange(A,&cstart,NULL);CHKERRQ(ierr); 201 202 PetscStackCallStandard(HYPRE_IJMatrixInitialize,(ij)); 203 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(ij,&type)); 204 if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 205 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(ij,(void**)&par_matrix)); 206 hdiag = hypre_ParCSRMatrixDiag(par_matrix); 207 hoffd = hypre_ParCSRMatrixOffd(par_matrix); 208 209 /* 210 this is the Hack part where we monkey directly with the hypre datastructures 211 */ 212 ierr = PetscMemcpy(hdiag->i,pdiag->i,(pA->A->rmap->n + 1)*sizeof(PetscInt)); 213 /* need to shift the diag column indices (hdiag->j) back to global numbering since hypre is expecting this */ 214 jj = (PetscInt*)hdiag->j; 215 pjj = (PetscInt*)pdiag->j; 216 for (i=0; i<pdiag->nz; i++) jj[i] = cstart + pjj[i]; 217 ierr = PetscMemcpy(hdiag->data,pdiag->a,pdiag->nz*sizeof(PetscScalar)); 218 ierr = PetscMemcpy(hoffd->i,poffd->i,(pA->A->rmap->n + 1)*sizeof(PetscInt)); 219 /* need to move the offd column indices (hoffd->j) back to global numbering since hypre is expecting this 220 If we hacked a hypre a bit more we might be able to avoid this step */ 221 jj = (PetscInt*) hoffd->j; 222 pjj = (PetscInt*) poffd->j; 223 for (i=0; i<poffd->nz; i++) jj[i] = garray[pjj[i]]; 224 ierr = PetscMemcpy(hoffd->data,poffd->a,poffd->nz*sizeof(PetscScalar)); 225 226 aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij); 227 hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0; 228 PetscFunctionReturn(0); 229 } 230 231 #undef __FUNCT__ 232 #define __FUNCT__ "MatConvert_HYPRE_IS" 233 static PetscErrorCode MatConvert_HYPRE_IS(Mat A, MatType mtype, MatReuse reuse, Mat* B) 234 { 235 Mat_HYPRE* mhA = (Mat_HYPRE*)(A->data); 236 Mat lA; 237 ISLocalToGlobalMapping rl2g,cl2g; 238 IS is; 239 hypre_ParCSRMatrix *hA; 240 hypre_CSRMatrix *hdiag,*hoffd; 241 MPI_Comm comm; 242 PetscScalar *hdd,*hod,*aa,*data; 243 PetscInt *col_map_offd,*hdi,*hdj,*hoi,*hoj; 244 PetscInt *ii,*jj,*iptr,*jptr; 245 PetscInt cum,dr,dc,oc,str,stc,nnz,i,jd,jo,M,N; 246 HYPRE_Int type; 247 PetscErrorCode ierr; 248 249 PetscFunctionBegin; 250 comm = PetscObjectComm((PetscObject)A); 251 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(mhA->ij,&type)); 252 if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 253 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(mhA->ij,(void**)&hA)); 254 M = hypre_ParCSRMatrixGlobalNumRows(hA); 255 N = hypre_ParCSRMatrixGlobalNumCols(hA); 256 str = hypre_ParCSRMatrixFirstRowIndex(hA); 257 stc = hypre_ParCSRMatrixFirstColDiag(hA); 258 hdiag = hypre_ParCSRMatrixDiag(hA); 259 hoffd = hypre_ParCSRMatrixOffd(hA); 260 dr = hypre_CSRMatrixNumRows(hdiag); 261 dc = hypre_CSRMatrixNumCols(hdiag); 262 nnz = hypre_CSRMatrixNumNonzeros(hdiag); 263 hdi = hypre_CSRMatrixI(hdiag); 264 hdj = hypre_CSRMatrixJ(hdiag); 265 hdd = hypre_CSRMatrixData(hdiag); 266 oc = hypre_CSRMatrixNumCols(hoffd); 267 nnz += hypre_CSRMatrixNumNonzeros(hoffd); 268 hoi = hypre_CSRMatrixI(hoffd); 269 hoj = hypre_CSRMatrixJ(hoffd); 270 hod = hypre_CSRMatrixData(hoffd); 271 if (reuse != MAT_REUSE_MATRIX) { 272 PetscInt *aux; 273 274 /* generate l2g maps for rows and cols */ 275 ierr = ISCreateStride(comm,dr,str,1,&is);CHKERRQ(ierr); 276 ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr); 277 ierr = ISDestroy(&is);CHKERRQ(ierr); 278 col_map_offd = hypre_ParCSRMatrixColMapOffd(hA); 279 ierr = PetscMalloc1(dc+oc,&aux);CHKERRQ(ierr); 280 for (i=0; i<dc; i++) aux[i] = i+stc; 281 for (i=0; i<oc; i++) aux[i+dc] = col_map_offd[i]; 282 ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 283 ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr); 284 ierr = ISDestroy(&is);CHKERRQ(ierr); 285 /* create MATIS object */ 286 ierr = MatCreate(comm,B);CHKERRQ(ierr); 287 ierr = MatSetSizes(*B,dr,dc,M,N);CHKERRQ(ierr); 288 ierr = MatSetType(*B,MATIS);CHKERRQ(ierr); 289 ierr = MatSetLocalToGlobalMapping(*B,rl2g,cl2g);CHKERRQ(ierr); 290 ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 291 ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 292 293 /* allocate CSR for local matrix */ 294 ierr = PetscMalloc1(dr+1,&iptr);CHKERRQ(ierr); 295 ierr = PetscMalloc1(nnz,&jptr);CHKERRQ(ierr); 296 ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr); 297 } else { 298 PetscInt nr; 299 PetscBool done; 300 ierr = MatISGetLocalMat(*B,&lA);CHKERRQ(ierr); 301 ierr = MatGetRowIJ(lA,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&iptr,(const PetscInt**)&jptr,&done);CHKERRQ(ierr); 302 if (nr != dr) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of rows in local mat! %D != %D",nr,dr); 303 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); 304 ierr = MatSeqAIJGetArray(lA,&data);CHKERRQ(ierr); 305 } 306 /* merge local matrices */ 307 ii = iptr; 308 jj = jptr; 309 aa = data; 310 *ii = *(hdi++) + *(hoi++); 311 for (jd=0,jo=0,cum=0; *ii<nnz; cum++) { 312 PetscScalar *aold = aa; 313 PetscInt *jold = jj,nc = jd+jo; 314 for (; jd<*hdi; jd++) { *jj++ = *hdj++; *aa++ = *hdd++; } 315 for (; jo<*hoi; jo++) { *jj++ = *hoj++ + dc; *aa++ = *hod++; } 316 *(++ii) = *(hdi++) + *(hoi++); 317 ierr = PetscSortIntWithScalarArray(jd+jo-nc,jold,aold);CHKERRQ(ierr); 318 } 319 for (; cum<dr; cum++) *(++ii) = nnz; 320 if (reuse != MAT_REUSE_MATRIX) { 321 Mat_SeqAIJ* a; 322 323 ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,dc+oc,iptr,jptr,data,&lA);CHKERRQ(ierr); 324 ierr = MatISSetLocalMat(*B,lA);CHKERRQ(ierr); 325 /* hack SeqAIJ */ 326 a = (Mat_SeqAIJ*)(lA->data); 327 a->free_a = PETSC_TRUE; 328 a->free_ij = PETSC_TRUE; 329 ierr = MatDestroy(&lA);CHKERRQ(ierr); 330 } 331 ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 332 ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 333 if (reuse == MAT_INPLACE_MATRIX) { 334 ierr = MatHeaderReplace(A,B);CHKERRQ(ierr); 335 } 336 PetscFunctionReturn(0); 337 } 338 339 #undef __FUNCT__ 340 #define __FUNCT__ "MatConvert_AIJ_HYPRE" 341 PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B) 342 { 343 Mat_HYPRE *hB; 344 MPI_Comm comm = PetscObjectComm((PetscObject)A); 345 PetscErrorCode ierr; 346 347 PetscFunctionBegin; 348 if (reuse == MAT_INPLACE_MATRIX) SETERRQ(comm,PETSC_ERR_SUP,"Unsupported MAT_INPLACE_MATRIX"); 349 if (reuse == MAT_REUSE_MATRIX) { 350 /* always destroy the old matrix and create a new memory; 351 hope this does not churn the memory too much. The problem 352 is I do not know if it is possible to put the matrix back to 353 its initial state so that we can directly copy the values 354 the second time through. */ 355 hB = (Mat_HYPRE*)((*B)->data); 356 PetscStackCallStandard(HYPRE_IJMatrixDestroy,(hB->ij)); 357 } else { 358 ierr = MatCreate(comm,B);CHKERRQ(ierr); 359 ierr = MatSetType(*B,MATHYPRE);CHKERRQ(ierr); 360 ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 361 ierr = MatSetUp(*B);CHKERRQ(ierr); 362 hB = (Mat_HYPRE*)((*B)->data); 363 } 364 ierr = MatHYPRE_CreateFromMat(A,hB);CHKERRQ(ierr); 365 ierr = MatHYPRE_IJMatrixCopy(A,hB->ij);CHKERRQ(ierr); 366 ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 367 ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 368 PetscFunctionReturn(0); 369 } 370 371 #undef __FUNCT__ 372 #define __FUNCT__ "MatConvert_HYPRE_AIJ" 373 static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B) 374 { 375 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 376 hypre_ParCSRMatrix *parcsr; 377 hypre_CSRMatrix *hdiag,*hoffd; 378 MPI_Comm comm; 379 PetscScalar *da,*oa,*aptr; 380 PetscInt *dii,*djj,*oii,*ojj,*iptr; 381 PetscInt i,dnnz,onnz,m,n; 382 HYPRE_Int type; 383 PetscMPIInt size; 384 PetscErrorCode ierr; 385 386 PetscFunctionBegin; 387 comm = PetscObjectComm((PetscObject)A); 388 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type)); 389 if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 390 if (reuse == MAT_REUSE_MATRIX) { 391 PetscBool ismpiaij,isseqaij; 392 ierr = PetscObjectTypeCompare((PetscObject)*B,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr); 393 ierr = PetscObjectTypeCompare((PetscObject)*B,MATSEQAIJ,&isseqaij);CHKERRQ(ierr); 394 if (!ismpiaij && !isseqaij) SETERRQ(comm,PETSC_ERR_SUP,"Only MATMPIAIJ or MATSEQAIJ are supported"); 395 } 396 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 397 398 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr)); 399 hdiag = hypre_ParCSRMatrixDiag(parcsr); 400 hoffd = hypre_ParCSRMatrixOffd(parcsr); 401 m = hypre_CSRMatrixNumRows(hdiag); 402 n = hypre_CSRMatrixNumCols(hdiag); 403 dnnz = hypre_CSRMatrixNumNonzeros(hdiag); 404 onnz = hypre_CSRMatrixNumNonzeros(hoffd); 405 if (reuse == MAT_INITIAL_MATRIX) { 406 ierr = PetscMalloc1(m+1,&dii);CHKERRQ(ierr); 407 ierr = PetscMalloc1(dnnz,&djj);CHKERRQ(ierr); 408 ierr = PetscMalloc1(dnnz,&da);CHKERRQ(ierr); 409 } else if (reuse == MAT_REUSE_MATRIX) { 410 PetscInt nr; 411 PetscBool done; 412 if (size > 1) { 413 Mat_MPIAIJ *b = (Mat_MPIAIJ*)((*B)->data); 414 415 ierr = MatGetRowIJ(b->A,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&dii,(const PetscInt**)&djj,&done);CHKERRQ(ierr); 416 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); 417 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); 418 ierr = MatSeqAIJGetArray(b->A,&da);CHKERRQ(ierr); 419 } else { 420 ierr = MatGetRowIJ(*B,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&dii,(const PetscInt**)&djj,&done);CHKERRQ(ierr); 421 if (nr != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of local rows! %D != %D",nr,m); 422 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); 423 ierr = MatSeqAIJGetArray(*B,&da);CHKERRQ(ierr); 424 } 425 } else { /* MAT_INPLACE_MATRIX */ 426 dii = hypre_CSRMatrixI(hdiag); 427 djj = hypre_CSRMatrixJ(hdiag); 428 da = hypre_CSRMatrixData(hdiag); 429 } 430 ierr = PetscMemcpy(dii,hypre_CSRMatrixI(hdiag),(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 431 ierr = PetscMemcpy(djj,hypre_CSRMatrixJ(hdiag),dnnz*sizeof(PetscInt));CHKERRQ(ierr); 432 ierr = PetscMemcpy(da,hypre_CSRMatrixData(hdiag),dnnz*sizeof(PetscScalar));CHKERRQ(ierr); 433 iptr = djj; 434 aptr = da; 435 for (i=0; i<m; i++) { 436 PetscInt nc = dii[i+1]-dii[i]; 437 ierr = PetscSortIntWithScalarArray(nc,iptr,aptr);CHKERRQ(ierr); 438 iptr += nc; 439 aptr += nc; 440 } 441 if (size > 1) { 442 PetscInt *offdj,*coffd; 443 444 if (reuse == MAT_INITIAL_MATRIX) { 445 ierr = PetscMalloc1(m+1,&oii);CHKERRQ(ierr); 446 ierr = PetscMalloc1(onnz,&ojj);CHKERRQ(ierr); 447 ierr = PetscMalloc1(onnz,&oa);CHKERRQ(ierr); 448 } else if (reuse == MAT_REUSE_MATRIX) { 449 Mat_MPIAIJ *b = (Mat_MPIAIJ*)((*B)->data); 450 PetscInt nr,hr = hypre_CSRMatrixNumRows(hoffd); 451 PetscBool done; 452 453 ierr = MatGetRowIJ(b->B,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&oii,(const PetscInt**)&ojj,&done);CHKERRQ(ierr); 454 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); 455 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); 456 ierr = MatSeqAIJGetArray(b->B,&oa);CHKERRQ(ierr); 457 } else { /* MAT_INPLACE_MATRIX */ 458 oii = hypre_CSRMatrixI(hoffd); 459 ojj = hypre_CSRMatrixJ(hoffd); 460 oa = hypre_CSRMatrixData(hoffd); 461 } 462 ierr = PetscMemcpy(oii,hypre_CSRMatrixI(hoffd),(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 463 offdj = hypre_CSRMatrixJ(hoffd); 464 coffd = hypre_ParCSRMatrixColMapOffd(parcsr); 465 for (i=0; i<onnz; i++) ojj[i] = coffd[offdj[i]]; 466 ierr = PetscMemcpy(oa,hypre_CSRMatrixData(hoffd),onnz*sizeof(PetscScalar));CHKERRQ(ierr); 467 iptr = ojj; 468 aptr = oa; 469 for (i=0; i<m; i++) { 470 PetscInt nc = oii[i+1]-oii[i]; 471 ierr = PetscSortIntWithScalarArray(nc,iptr,aptr);CHKERRQ(ierr); 472 iptr += nc; 473 aptr += nc; 474 } 475 if (reuse == MAT_INITIAL_MATRIX) { 476 Mat_MPIAIJ *b; 477 Mat_SeqAIJ *d,*o; 478 479 ierr = MatCreateMPIAIJWithSplitArrays(comm,m,n,PETSC_DECIDE,PETSC_DECIDE,dii,djj,da,oii,ojj,oa,B);CHKERRQ(ierr); 480 /* hack MPIAIJ */ 481 b = (Mat_MPIAIJ*)((*B)->data); 482 d = (Mat_SeqAIJ*)b->A->data; 483 o = (Mat_SeqAIJ*)b->B->data; 484 d->free_a = PETSC_TRUE; 485 d->free_ij = PETSC_TRUE; 486 o->free_a = PETSC_TRUE; 487 o->free_ij = PETSC_TRUE; 488 } else if (reuse == MAT_INPLACE_MATRIX) { 489 Mat T; 490 ierr = MatCreateMPIAIJWithSplitArrays(comm,m,n,PETSC_DECIDE,PETSC_DECIDE,dii,djj,da,oii,ojj,oa,&T);CHKERRQ(ierr); 491 hypre_CSRMatrixI(hdiag) = NULL; 492 hypre_CSRMatrixJ(hdiag) = NULL; 493 hypre_CSRMatrixData(hdiag) = NULL; 494 hypre_CSRMatrixI(hoffd) = NULL; 495 hypre_CSRMatrixJ(hoffd) = NULL; 496 hypre_CSRMatrixData(hoffd) = NULL; 497 ierr = MatHeaderReplace(A,&T);CHKERRQ(ierr); 498 } 499 } else { 500 oii = NULL; 501 ojj = NULL; 502 oa = NULL; 503 if (reuse == MAT_INITIAL_MATRIX) { 504 Mat_SeqAIJ* b; 505 ierr = MatCreateSeqAIJWithArrays(comm,m,n,dii,djj,da,B);CHKERRQ(ierr); 506 /* hack SeqAIJ */ 507 b = (Mat_SeqAIJ*)((*B)->data); 508 b->free_a = PETSC_TRUE; 509 b->free_ij = PETSC_TRUE; 510 } else if (reuse == MAT_INPLACE_MATRIX) { 511 Mat T; 512 ierr = MatCreateSeqAIJWithArrays(comm,m,n,dii,djj,da,&T);CHKERRQ(ierr); 513 hypre_CSRMatrixI(hdiag) = NULL; 514 hypre_CSRMatrixJ(hdiag) = NULL; 515 hypre_CSRMatrixData(hdiag) = NULL; 516 ierr = MatHeaderReplace(A,&T);CHKERRQ(ierr); 517 } 518 } 519 520 /* we have to use hypre_Tfree to free the arrays */ 521 if (reuse == MAT_INPLACE_MATRIX) { 522 void *ptrs[6] = {dii,djj,da,oii,ojj,oa}; 523 const char *names[6] = {"_hypre_csr_dii", 524 "_hypre_csr_djj", 525 "_hypre_csr_da", 526 "_hypre_csr_oii", 527 "_hypre_csr_ojj", 528 "_hypre_csr_oa"}; 529 for (i=0; i<6; i++) { 530 PetscContainer c; 531 532 ierr = PetscContainerCreate(comm,&c);CHKERRQ(ierr); 533 ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr); 534 ierr = PetscContainerSetUserDestroy(c,hypre_array_destroy);CHKERRQ(ierr); 535 ierr = PetscObjectCompose((PetscObject)(*B),names[i],(PetscObject)c);CHKERRQ(ierr); 536 ierr = PetscContainerDestroy(&c);CHKERRQ(ierr); 537 } 538 } 539 PetscFunctionReturn(0); 540 } 541 542 #undef __FUNCT__ 543 #define __FUNCT__ "MatPtAP_AIJ_HYPRE" 544 static PetscErrorCode MatPtAP_AIJ_HYPRE(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C) 545 { 546 Mat_HYPRE *hP = (Mat_HYPRE*)P->data; 547 hypre_ParCSRMatrix *tA,*Pparcsr,*ptapparcsr; 548 hypre_CSRMatrix *hdiag,*hoffd; 549 Mat_SeqAIJ *diag,*offd; 550 PetscInt *garray,noffd,dnnz,onnz,*row_starts,*col_starts; 551 HYPRE_Int type,P_owns_col_starts; 552 PetscBool ismpiaij,isseqaij; 553 MPI_Comm comm = PetscObjectComm((PetscObject)A); 554 char mtype[256]; 555 PetscErrorCode ierr; 556 557 PetscFunctionBegin; 558 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hP->ij,&type)); 559 if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 560 if (scall == MAT_REUSE_MATRIX) SETERRQ(comm,PETSC_ERR_SUP,"Unsupported MAT_REUSE_MATRIX"); 561 ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr); 562 ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr); 563 if (!ismpiaij && !isseqaij) SETERRQ1(comm,PETSC_ERR_SUP,"Unsupported type %s",((PetscObject)A)->type); 564 565 /* It looks like we don't need to have the diagonal entries 566 ordered first in the rows of the diagonal part 567 for boomerAMGBuildCoarseOperator to work */ 568 if (ismpiaij) { 569 Mat_MPIAIJ *a = (Mat_MPIAIJ*)(A->data); 570 571 diag = (Mat_SeqAIJ*)a->A->data; 572 offd = (Mat_SeqAIJ*)a->B->data; 573 garray = a->garray; 574 noffd = a->B->cmap->N; 575 dnnz = diag->nz; 576 onnz = offd->nz; 577 } else { 578 diag = (Mat_SeqAIJ*)A->data; 579 offd = NULL; 580 garray = NULL; 581 noffd = 0; 582 dnnz = diag->nz; 583 onnz = 0; 584 } 585 586 /* create a temporary ParCSR */ 587 if (HYPRE_AssumedPartitionCheck()) { 588 PetscMPIInt myid; 589 590 ierr = MPI_Comm_rank(comm,&myid);CHKERRQ(ierr); 591 row_starts = A->rmap->range + myid; 592 col_starts = A->cmap->range + myid; 593 } else { 594 row_starts = A->rmap->range; 595 col_starts = A->cmap->range; 596 } 597 tA = hypre_ParCSRMatrixCreate(comm,A->rmap->N,A->cmap->N,row_starts,col_starts,noffd,dnnz,onnz); 598 hypre_ParCSRMatrixSetRowStartsOwner(tA,0); 599 hypre_ParCSRMatrixSetColStartsOwner(tA,0); 600 601 /* set diagonal part */ 602 hdiag = hypre_ParCSRMatrixDiag(tA); 603 hypre_CSRMatrixI(hdiag) = diag->i; 604 hypre_CSRMatrixJ(hdiag) = diag->j; 605 hypre_CSRMatrixData(hdiag) = diag->a; 606 hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz; 607 hypre_CSRMatrixSetRownnz(hdiag); 608 hypre_CSRMatrixSetDataOwner(hdiag,0); 609 610 /* set offdiagonal part */ 611 hoffd = hypre_ParCSRMatrixOffd(tA); 612 if (offd) { 613 hypre_CSRMatrixI(hoffd) = offd->i; 614 hypre_CSRMatrixJ(hoffd) = offd->j; 615 hypre_CSRMatrixData(hoffd) = offd->a; 616 hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz; 617 hypre_CSRMatrixSetRownnz(hoffd); 618 hypre_CSRMatrixSetDataOwner(hoffd,0); 619 hypre_ParCSRMatrixSetNumNonzeros(tA); 620 hypre_ParCSRMatrixColMapOffd(tA) = garray; 621 } 622 623 /* call RAP from BoomerAMG */ 624 /* Warning: hypre_BoomerAMGBuildCoarseOperator steals the col_starts 625 from Pparcsr (even if it does not own them)! */ 626 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hP->ij,(void**)&Pparcsr)); 627 P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(Pparcsr); 628 ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 629 PetscStackCallStandard(hypre_BoomerAMGBuildCoarseOperator,(Pparcsr,tA,Pparcsr,&ptapparcsr)); 630 ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 631 hypre_ParCSRMatrixSetRowStartsOwner(ptapparcsr,0); 632 hypre_ParCSRMatrixSetColStartsOwner(ptapparcsr,0); 633 if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(Pparcsr, 1); 634 635 /* set pointers to NULL before destroying tA */ 636 hypre_CSRMatrixI(hdiag) = NULL; 637 hypre_CSRMatrixJ(hdiag) = NULL; 638 hypre_CSRMatrixData(hdiag) = NULL; 639 hypre_CSRMatrixI(hoffd) = NULL; 640 hypre_CSRMatrixJ(hoffd) = NULL; 641 hypre_CSRMatrixData(hoffd) = NULL; 642 hypre_ParCSRMatrixColMapOffd(tA) = NULL; 643 hypre_ParCSRMatrixDestroy(tA); 644 645 /* create C depending on mtype */ 646 sprintf(mtype,MATAIJ); 647 ierr = PetscOptionsGetString(((PetscObject)A)->options,((PetscObject)A)->prefix,"-matptap_hypre_outtype",mtype,256,NULL);CHKERRQ(ierr); 648 ierr = MatCreateFromParCSR(ptapparcsr,mtype,PETSC_OWN_POINTER,C);CHKERRQ(ierr); 649 PetscFunctionReturn(0); 650 } 651 652 #undef __FUNCT__ 653 #define __FUNCT__ "MatPtAP_HYPRE_HYPRE" 654 static PetscErrorCode MatPtAP_HYPRE_HYPRE(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C) 655 { 656 hypre_ParCSRMatrix *Aparcsr,*Pparcsr,*ptapparcsr; 657 Mat_HYPRE *hA = (Mat_HYPRE*)A->data, *hP = (Mat_HYPRE*)P->data; 658 HYPRE_Int type,P_owns_col_starts; 659 PetscErrorCode ierr; 660 661 PetscFunctionBegin; 662 if (scall == MAT_REUSE_MATRIX) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Unsupported MAT_REUSE_MATRIX"); 663 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type)); 664 if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 665 PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hP->ij,&type)); 666 if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)P),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported"); 667 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&Aparcsr)); 668 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hP->ij,(void**)&Pparcsr)); 669 670 /* call RAP from BoomerAMG */ 671 /* Warning: hypre_BoomerAMGBuildCoarseOperator steals the col_starts 672 from Pparcsr (even if it does not own them)! */ 673 P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(Pparcsr); 674 ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 675 PetscStackCallStandard(hypre_BoomerAMGBuildCoarseOperator,(Pparcsr,Aparcsr,Pparcsr,&ptapparcsr)); 676 ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 677 hypre_ParCSRMatrixSetRowStartsOwner(ptapparcsr,0); 678 hypre_ParCSRMatrixSetColStartsOwner(ptapparcsr,0); 679 if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(Pparcsr, 1); 680 681 /* create MatHYPRE */ 682 ierr = MatCreateFromParCSR(ptapparcsr,MATHYPRE,PETSC_OWN_POINTER,C);CHKERRQ(ierr); 683 PetscFunctionReturn(0); 684 } 685 686 #undef __FUNCT__ 687 #define __FUNCT__ "MatMultTranspose_HYPRE" 688 static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y) 689 { 690 PetscErrorCode ierr; 691 692 PetscFunctionBegin; 693 ierr = MatHYPRE_MultKernel_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr); 694 PetscFunctionReturn(0); 695 } 696 697 #undef __FUNCT__ 698 #define __FUNCT__ "MatMult_HYPRE" 699 static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y) 700 { 701 PetscErrorCode ierr; 702 703 PetscFunctionBegin; 704 ierr = MatHYPRE_MultKernel_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr); 705 PetscFunctionReturn(0); 706 } 707 708 #undef __FUNCT__ 709 #define __FUNCT__ "MatHYPRE_MultKernel_Private" 710 static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, Vec x, Vec y, PetscBool trans) 711 { 712 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 713 hypre_ParCSRMatrix *parcsr; 714 hypre_ParVector *hx,*hy; 715 PetscScalar *ax,*ay,*sax,*say; 716 PetscErrorCode ierr; 717 718 PetscFunctionBegin; 719 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr)); 720 PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->x,(void**)&hx)); 721 PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->b,(void**)&hy)); 722 ierr = VecGetArrayRead(x,(const PetscScalar**)&ax);CHKERRQ(ierr); 723 ierr = VecGetArray(y,&ay);CHKERRQ(ierr); 724 if (trans) { 725 VecHYPRE_ParVectorReplacePointer(hA->x,ay,say); 726 VecHYPRE_ParVectorReplacePointer(hA->b,ax,sax); 727 hypre_ParCSRMatrixMatvecT(1.,parcsr,hy,0.,hx); 728 VecHYPRE_ParVectorReplacePointer(hA->x,say,ay); 729 VecHYPRE_ParVectorReplacePointer(hA->b,sax,ax); 730 } else { 731 VecHYPRE_ParVectorReplacePointer(hA->x,ax,sax); 732 VecHYPRE_ParVectorReplacePointer(hA->b,ay,say); 733 hypre_ParCSRMatrixMatvec(1.,parcsr,hx,0.,hy); 734 VecHYPRE_ParVectorReplacePointer(hA->x,sax,ax); 735 VecHYPRE_ParVectorReplacePointer(hA->b,say,ay); 736 } 737 ierr = VecRestoreArrayRead(x,(const PetscScalar**)&ax);CHKERRQ(ierr); 738 ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr); 739 PetscFunctionReturn(0); 740 } 741 742 #undef __FUNCT__ 743 #define __FUNCT__ "MatDestroy_HYPRE" 744 static PetscErrorCode MatDestroy_HYPRE(Mat A) 745 { 746 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 747 PetscErrorCode ierr; 748 749 PetscFunctionBegin; 750 if (hA->x) PetscStackCallStandard(HYPRE_IJVectorDestroy,(hA->x)); 751 if (hA->b) PetscStackCallStandard(HYPRE_IJVectorDestroy,(hA->b)); 752 if (hA->ij) { 753 if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL; 754 PetscStackCallStandard(HYPRE_IJMatrixDestroy,(hA->ij)); 755 } 756 if (hA->comm) { ierr = MPI_Comm_free(&hA->comm);CHKERRQ(ierr); } 757 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_hypre_aij_C",NULL);CHKERRQ(ierr); 758 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_hypre_is_C",NULL);CHKERRQ(ierr); 759 ierr = PetscObjectComposeFunction((PetscObject)A,"MatPtAP_seqaij_hypre_C",NULL);CHKERRQ(ierr); 760 ierr = PetscObjectComposeFunction((PetscObject)A,"MatPtAP_mpiaij_hypre_C",NULL);CHKERRQ(ierr); 761 ierr = PetscFree(A->data);CHKERRQ(ierr); 762 PetscFunctionReturn(0); 763 } 764 765 #undef __FUNCT__ 766 #define __FUNCT__ "MatSetUp_HYPRE" 767 static PetscErrorCode MatSetUp_HYPRE(Mat A) 768 { 769 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 770 Vec x,b; 771 PetscErrorCode ierr; 772 773 PetscFunctionBegin; 774 if (hA->x) PetscFunctionReturn(0); 775 ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 776 ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 777 ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)A),1,A->cmap->n,A->cmap->N,NULL,&x);CHKERRQ(ierr); 778 ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)A),1,A->rmap->n,A->rmap->N,NULL,&b);CHKERRQ(ierr); 779 ierr = VecHYPRE_IJVectorCreate(x,&hA->x);CHKERRQ(ierr); 780 ierr = VecHYPRE_IJVectorCreate(b,&hA->b);CHKERRQ(ierr); 781 ierr = VecDestroy(&x);CHKERRQ(ierr); 782 ierr = VecDestroy(&b);CHKERRQ(ierr); 783 PetscFunctionReturn(0); 784 } 785 786 #undef __FUNCT__ 787 #define __FUNCT__ "MatAssemblyEnd_HYPRE" 788 static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode) 789 { 790 Mat_HYPRE *hA = (Mat_HYPRE*)A->data; 791 PetscErrorCode ierr; 792 793 PetscFunctionBegin; 794 PetscStackCallStandard(HYPRE_IJMatrixAssemble,(hA->ij)); 795 PetscFunctionReturn(0); 796 } 797 798 /* 799 MatCreateFromParCSR - Creates a matrix from a hypre_ParCSRMatrix 800 801 Collective 802 803 Input Parameters: 804 + vparcsr - the pointer to the hypre_ParCSRMatrix 805 . mtype - matrix type to be created. Currently MATAIJ, MATIS and MATHYPRE are supported. 806 - copymode - PETSc copying options 807 808 Output Parameter: 809 . A - the matrix 810 811 Level: intermediate 812 813 .seealso: MatHYPRE, PetscCopyMode 814 */ 815 #undef __FUNCT__ 816 #define __FUNCT__ "MatCreateFromParCSR" 817 PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(void *vparcsr, MatType mtype, PetscCopyMode copymode, Mat* A) 818 { 819 Mat T; 820 Mat_HYPRE *hA; 821 hypre_ParCSRMatrix *parcsr; 822 MPI_Comm comm; 823 PetscInt rstart,rend,cstart,cend,M,N; 824 PetscBool isseqaij,ismpiaij,isaij,ishyp,isis; 825 PetscErrorCode ierr; 826 827 PetscFunctionBegin; 828 parcsr = (hypre_ParCSRMatrix *)vparcsr; 829 comm = hypre_ParCSRMatrixComm(parcsr); 830 ierr = PetscStrcmp(mtype,MATSEQAIJ,&isseqaij);CHKERRQ(ierr); 831 ierr = PetscStrcmp(mtype,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr); 832 ierr = PetscStrcmp(mtype,MATAIJ,&isaij);CHKERRQ(ierr); 833 ierr = PetscStrcmp(mtype,MATHYPRE,&ishyp);CHKERRQ(ierr); 834 ierr = PetscStrcmp(mtype,MATIS,&isis);CHKERRQ(ierr); 835 isaij = (PetscBool)(isseqaij || ismpiaij || isaij); 836 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); 837 if (ishyp && copymode == PETSC_COPY_VALUES) SETERRQ(comm,PETSC_ERR_SUP,"Unsupported copymode PETSC_COPY_VALUES"); 838 839 /* access ParCSRMatrix */ 840 rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr); 841 rend = hypre_ParCSRMatrixLastRowIndex(parcsr); 842 cstart = hypre_ParCSRMatrixFirstColDiag(parcsr); 843 cend = hypre_ParCSRMatrixLastColDiag(parcsr); 844 M = hypre_ParCSRMatrixGlobalNumRows(parcsr); 845 N = hypre_ParCSRMatrixGlobalNumCols(parcsr); 846 847 /* create PETSc matrix with MatHYPRE */ 848 ierr = MatCreate(comm,&T);CHKERRQ(ierr); 849 ierr = MatSetSizes(T,rend-rstart+1,cend-cstart+1,M,N);CHKERRQ(ierr); 850 ierr = MatSetType(T,MATHYPRE);CHKERRQ(ierr); 851 ierr = MatSetUp(T);CHKERRQ(ierr); 852 hA = (Mat_HYPRE*)(T->data); 853 854 /* create HYPRE_IJMatrix */ 855 PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rstart,rend-1,cstart,cend-1,&hA->ij)); 856 857 /* set ParCSR object */ 858 PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR)); 859 hypre_IJMatrixObject(hA->ij) = parcsr; 860 861 /* set assembled flag */ 862 hypre_IJMatrixAssembleFlag(hA->ij) = 1; 863 PetscStackCallStandard(HYPRE_IJMatrixInitialize,(hA->ij)); 864 if (ishyp) { 865 /* prevent from freeing the pointer */ 866 if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE; 867 *A = T; 868 ierr = MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 869 ierr = MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 870 } else if (isaij) { 871 if (copymode != PETSC_OWN_POINTER) { 872 /* prevent from freeing the pointer */ 873 hA->inner_free = PETSC_FALSE; 874 ierr = MatConvert_HYPRE_AIJ(T,MATAIJ,MAT_INITIAL_MATRIX,A);CHKERRQ(ierr); 875 ierr = MatDestroy(&T);CHKERRQ(ierr); 876 } else { /* AIJ return type with PETSC_OWN_POINTER */ 877 ierr = MatConvert_HYPRE_AIJ(T,MATAIJ,MAT_INPLACE_MATRIX,&T);CHKERRQ(ierr); 878 *A = T; 879 } 880 } else if (isis) { 881 ierr = MatConvert_HYPRE_IS(T,MATIS,MAT_INITIAL_MATRIX,A);CHKERRQ(ierr); 882 if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE; 883 ierr = MatDestroy(&T);CHKERRQ(ierr); 884 } 885 PetscFunctionReturn(0); 886 } 887 888 #undef __FUNCT__ 889 #define __FUNCT__ "MatCreate_HYPRE" 890 PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B) 891 { 892 Mat_HYPRE *hB; 893 PetscErrorCode ierr; 894 895 PetscFunctionBegin; 896 ierr = PetscNewLog(B,&hB);CHKERRQ(ierr); 897 hB->inner_free = PETSC_TRUE; 898 899 B->data = (void*)hB; 900 B->rmap->bs = 1; 901 B->assembled = PETSC_FALSE; 902 903 B->ops->mult = MatMult_HYPRE; 904 B->ops->multtranspose = MatMultTranspose_HYPRE; 905 B->ops->setup = MatSetUp_HYPRE; 906 B->ops->destroy = MatDestroy_HYPRE; 907 B->ops->assemblyend = MatAssemblyEnd_HYPRE; 908 B->ops->ptap = MatPtAP_HYPRE_HYPRE; 909 910 ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)B),&hB->comm);CHKERRQ(ierr); 911 ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRE);CHKERRQ(ierr); 912 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_hypre_aij_C",MatConvert_HYPRE_AIJ);CHKERRQ(ierr); 913 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_hypre_is_C",MatConvert_HYPRE_IS);CHKERRQ(ierr); 914 ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_seqaij_hypre_C",MatPtAP_AIJ_HYPRE);CHKERRQ(ierr); 915 ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_mpiaij_hypre_C",MatPtAP_AIJ_HYPRE);CHKERRQ(ierr); 916 PetscFunctionReturn(0); 917 } 918 919 #undef __FUNCT__ 920 #define __FUNCT__ "hypre_array_destroy" 921 static PetscErrorCode hypre_array_destroy(void *ptr) 922 { 923 PetscFunctionBegin; 924 hypre_TFree(ptr); 925 PetscFunctionReturn(0); 926 } 927 928 #if 0 929 /* 930 Does NOT copy the data over, instead uses DIRECTLY the pointers from the PETSc MPIAIJ format 931 932 This is UNFINISHED and does NOT work! The problem is that hypre puts the diagonal entry first 933 which will corrupt the PETSc data structure if we did this. Need a work around to this problem. 934 */ 935 #include <_hypre_IJ_mv.h> 936 #include <HYPRE_IJ_mv.h> 937 938 #undef __FUNCT__ 939 #define __FUNCT__ "MatHYPRE_IJMatrixLink" 940 PetscErrorCode MatHYPRE_IJMatrixLink(Mat A, HYPRE_IJMatrix *ij) 941 { 942 PetscErrorCode ierr; 943 PetscInt rstart,rend,cstart,cend; 944 PetscBool flg; 945 hypre_AuxParCSRMatrix *aux_matrix; 946 947 PetscFunctionBegin; 948 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 949 PetscValidType(A,1); 950 PetscValidPointer(ij,2); 951 ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&flg);CHKERRQ(ierr); 952 if (!flg) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Can only use with PETSc MPIAIJ matrices"); 953 ierr = MatSetUp(A);CHKERRQ(ierr); 954 955 ierr = PetscLogEventBegin(MAT_Convert,A,0,0,0);CHKERRQ(ierr); 956 rstart = A->rmap->rstart; 957 rend = A->rmap->rend; 958 cstart = A->cmap->rstart; 959 cend = A->cmap->rend; 960 PetscStackCallStandard(HYPRE_IJMatrixCreate,(PetscObjectComm((PetscObject)A),rstart,rend-1,cstart,cend-1,ij)); 961 PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(*ij,HYPRE_PARCSR)); 962 963 PetscStackCallStandard(HYPRE_IJMatrixInitialize,(*ij)); 964 PetscStackCall("hypre_IJMatrixTranslator",aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(*ij)); 965 966 hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0; 967 968 /* this is the Hack part where we monkey directly with the hypre datastructures */ 969 970 PetscStackCallStandard(HYPRE_IJMatrixAssemble,(*ij)); 971 ierr = PetscLogEventEnd(MAT_Convert,A,0,0,0);CHKERRQ(ierr); 972 PetscFunctionReturn(0); 973 } 974 #endif 975