static PetscErrorCode PCView_Redistribute(PC pc,PetscViewer viewer) { PC_Redistribute *red = (PC_Redistribute*)pc->data; PetscErrorCode ierr; PetscBool iascii,isstring; PetscInt ncnt,N; PetscFunctionBegin; ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr); if (iascii) { ierr = MPI_Allreduce(&red->dcnt,&ncnt,1,MPIU_INT,MPI_SUM,((PetscObject)pc)->comm);CHKERRQ(ierr); ierr = MatGetSize(pc->pmat,&N,PETSC_NULL);CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer," Number rows eliminated %D Percentage rows eliminated %g\n",ncnt,100.0*((PetscReal)ncnt)/((PetscReal)N));CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer," Redistribute preconditioner: \n");CHKERRQ(ierr); ierr = KSPView(red->ksp,viewer);CHKERRQ(ierr); } else if (isstring) { ierr = PetscViewerStringSPrintf(viewer," Redistribute preconditioner");CHKERRQ(ierr); ierr = KSPView(red->ksp,viewer);CHKERRQ(ierr); } else SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for PC redistribute",((PetscObject)viewer)->type_name); PetscFunctionReturn(0); }
/*@ MatFDColoringCreate - Creates a matrix coloring context for finite difference computation of Jacobians. Collective on Mat Input Parameters: + mat - the matrix containing the nonzero structure of the Jacobian - iscoloring - the coloring of the matrix; usually obtained with MatColoringCreate() or DMCreateColoring() Output Parameter: . color - the new coloring context Level: intermediate .seealso: MatFDColoringDestroy(),SNESComputeJacobianDefaultColor(), ISColoringCreate(), MatFDColoringSetFunction(), MatFDColoringSetFromOptions(), MatFDColoringApply(), MatFDColoringView(), MatFDColoringSetParameters(), MatColoringCreate(), DMCreateColoring() @*/ PetscErrorCode MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color) { MatFDColoring c; MPI_Comm comm; PetscErrorCode ierr; PetscInt M,N; PetscFunctionBegin; PetscValidHeaderSpecific(mat,MAT_CLASSID,1); if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Matrix must be assembled by calls to MatAssemblyBegin/End();"); ierr = PetscLogEventBegin(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr); ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr); if (M != N) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Only for square matrices"); ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr); ierr = PetscHeaderCreate(c,MAT_FDCOLORING_CLASSID,"MatFDColoring","Jacobian computation via finite differences with coloring","Mat",comm,MatFDColoringDestroy,MatFDColoringView);CHKERRQ(ierr); c->ctype = iscoloring->ctype; if (mat->ops->fdcoloringcreate) { ierr = (*mat->ops->fdcoloringcreate)(mat,iscoloring,c);CHKERRQ(ierr); } else SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Code not yet written for matrix type %s",((PetscObject)mat)->type_name); ierr = MatCreateVecs(mat,NULL,&c->w1);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)c,(PetscObject)c->w1);CHKERRQ(ierr); ierr = VecDuplicate(c->w1,&c->w2);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)c,(PetscObject)c->w2);CHKERRQ(ierr); c->error_rel = PETSC_SQRT_MACHINE_EPSILON; c->umin = 100.0*PETSC_SQRT_MACHINE_EPSILON; c->currentcolor = -1; c->htype = "wp"; c->fset = PETSC_FALSE; c->setupcalled = PETSC_FALSE; *color = c; ierr = PetscObjectCompose((PetscObject)mat,"SNESMatFDColoring",(PetscObject)c);CHKERRQ(ierr); ierr = PetscLogEventEnd(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode MatColoringApply_Greedy(MatColoring mc,ISColoring *iscoloring) { PetscErrorCode ierr; PetscInt finalcolor,finalcolor_global; ISColoringValue *colors; PetscInt ncolstotal,ncols; PetscReal *wts; PetscInt i,*lperm; PetscFunctionBegin; ierr = MatGetSize(mc->mat,NULL,&ncolstotal);CHKERRQ(ierr); ierr = MatGetLocalSize(mc->mat,NULL,&ncols);CHKERRQ(ierr); if (!mc->user_weights) { ierr = MatColoringCreateWeights(mc,&wts,&lperm);CHKERRQ(ierr); } else { wts = mc->user_weights; lperm = mc->user_lperm; } ierr = PetscMalloc1(ncols,&colors);CHKERRQ(ierr); if (mc->dist == 1) { ierr = GreedyColoringLocalDistanceOne_Private(mc,wts,lperm,colors);CHKERRQ(ierr); } else if (mc->dist == 2) { ierr = GreedyColoringLocalDistanceTwo_Private(mc,wts,lperm,colors);CHKERRQ(ierr); } else SETERRQ(PetscObjectComm((PetscObject)mc),PETSC_ERR_ARG_OUTOFRANGE,"Only distance 1 and distance 2 supported by MatColoringGreedy"); finalcolor=0; for (i=0;i<ncols;i++) { if (colors[i] > finalcolor) finalcolor=colors[i]; } finalcolor_global=0; ierr = MPIU_Allreduce(&finalcolor,&finalcolor_global,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)mc));CHKERRQ(ierr); ierr = PetscLogEventBegin(MATCOLORING_ISCreate,mc,0,0,0);CHKERRQ(ierr); ierr = ISColoringCreate(PetscObjectComm((PetscObject)mc),finalcolor_global+1,ncols,colors,PETSC_OWN_POINTER,iscoloring);CHKERRQ(ierr); ierr = PetscLogEventEnd(MATCOLORING_ISCreate,mc,0,0,0);CHKERRQ(ierr); if (!mc->user_weights) { ierr = PetscFree(wts);CHKERRQ(ierr); ierr = PetscFree(lperm);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) { Mat_IS *matis = (Mat_IS*)(B->data); PetscInt bs,i,nlocalcols; PetscErrorCode ierr; PetscFunctionBegin; if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping"); if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */ ierr = MatISComputeSF_Private(B);CHKERRQ(ierr); } if (!d_nnz) { for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nz; } else { for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nnz[i]; } if (!o_nnz) { for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nz; } else { for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nnz[i]; } ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr); ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr); ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); for (i=0;i<matis->sf_nleaves;i++) { matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols); } ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr); for (i=0;i<matis->sf_nleaves/bs;i++) { matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs; } ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr); for (i=0;i<matis->sf_nleaves/bs;i++) { matis->sf_leafdata[i] = matis->sf_leafdata[i]-i; } ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr); PetscFunctionReturn(0); }
static void PETScMatvecGenRowMajor(void *x, PRIMME_INT ldx, void *y, PRIMME_INT ldy, int blockSize, int trans, Mat matrix, MPI_Comm comm) { PetscInt m, n, mLocal, nLocal; PetscErrorCode ierr; Mat X, Y; if (blockSize == 1) { PETScMatvecGenNoBlock(x, ldx, y, ldy, blockSize, trans, matrix, comm); return; } assert(sizeof(PetscScalar) == sizeof(SCALAR)); ierr = MatGetSize(matrix, &m, &n); CHKERRABORT(comm, ierr); ierr = MatGetLocalSize(matrix, &mLocal, &nLocal); CHKERRABORT(comm, ierr); if (trans == 0) { ierr = MatMatMult_MPIAIJ_MPIDense0(matrix,(PetscScalar*)x,blockSize,ldx,(PetscScalar*)y,ldy);CHKERRABORT(comm, ierr); } else { ierr = MatHermitianTransposeMatMult_MPIAIJ_MPIDense0(matrix,(PetscScalar*)x,blockSize,ldx,(PetscScalar*)y,ldy);CHKERRABORT(comm, ierr); } }
static PetscErrorCode PCBDDCMatTransposeMatSolve_SeqDense(Mat A,Mat B,Mat X) { Mat_SeqDense *mat = (Mat_SeqDense*)A->data; PetscErrorCode ierr; const PetscScalar *b; PetscScalar *x; PetscInt n; PetscBLASInt nrhs,info,m; PetscBool flg; PetscFunctionBegin; ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr); ierr = PetscObjectTypeCompareAny((PetscObject)B,&flg,MATSEQDENSE,MATMPIDENSE,NULL);CHKERRQ(ierr); if (!flg) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Matrix B must be MATDENSE matrix"); ierr = PetscObjectTypeCompareAny((PetscObject)X,&flg,MATSEQDENSE,MATMPIDENSE,NULL);CHKERRQ(ierr); if (!flg) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Matrix X must be MATDENSE matrix"); ierr = MatGetSize(B,NULL,&n);CHKERRQ(ierr); ierr = PetscBLASIntCast(n,&nrhs);CHKERRQ(ierr); ierr = MatDenseGetArrayRead(B,&b);CHKERRQ(ierr); ierr = MatDenseGetArray(X,&x);CHKERRQ(ierr); ierr = PetscMemcpy(x,b,m*nrhs*sizeof(PetscScalar));CHKERRQ(ierr); ierr = MatDenseRestoreArrayRead(B,&b);CHKERRQ(ierr); if (A->factortype == MAT_FACTOR_LU) { #if defined(PETSC_MISSING_LAPACK_GETRS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable."); #else PetscStackCallBLAS("LAPACKgetrs",LAPACKgetrs_("T",&m,&nrhs,mat->v,&mat->lda,mat->pivots,x,&m,&info)); if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"GETRS - Bad solve"); #endif } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only LU factor supported"); ierr = MatDenseRestoreArray(X,&x);CHKERRQ(ierr); ierr = PetscLogFlops(nrhs*(2.0*m*m - m));CHKERRQ(ierr); PetscFunctionReturn(0); }
/* MatConvert_Basic - Converts from any input format to another format. For parallel formats, the new matrix distribution is determined by PETSc. Does not do preallocation so in general will be slow */ PetscErrorCode MatConvert_Basic(Mat mat, const MatType newtype,MatReuse reuse,Mat *newmat) { Mat M; const PetscScalar *vwork; PetscErrorCode ierr; PetscInt i,nz,m,n,rstart,rend,lm,ln; const PetscInt *cwork; PetscFunctionBegin; ierr = MatGetSize(mat,&m,&n);CHKERRQ(ierr); ierr = MatGetLocalSize(mat,&lm,&ln);CHKERRQ(ierr); if (ln == n) ln = PETSC_DECIDE; /* try to preserve column ownership */ ierr = MatCreate(((PetscObject)mat)->comm,&M);CHKERRQ(ierr); ierr = MatSetSizes(M,lm,ln,m,n);CHKERRQ(ierr); ierr = MatSetType(M,newtype);CHKERRQ(ierr); ierr = MatGetOwnershipRange(mat,&rstart,&rend);CHKERRQ(ierr); for (i=rstart; i<rend; i++) { ierr = MatGetRow(mat,i,&nz,&cwork,&vwork);CHKERRQ(ierr); ierr = MatSetValues(M,1,&i,nz,cwork,vwork,INSERT_VALUES);CHKERRQ(ierr); ierr = MatRestoreRow(mat,i,&nz,&cwork,&vwork);CHKERRQ(ierr); } ierr = MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); if (mat->hermitian){ ierr = MatSetOption(M,MAT_HERMITIAN,PETSC_TRUE);CHKERRQ(ierr); } if (reuse == MAT_REUSE_MATRIX) { ierr = MatHeaderReplace(mat,M);CHKERRQ(ierr); } else { *newmat = M; } PetscFunctionReturn(0); }
// updated PetscErrorCode BSSCR_MatMVBlock_ConstructScaling( MatStokesBlockScaling BA, Mat A, Vec b, Vec x, PetscTruth sym ) { if( BA->scaling_exists == PETSC_FALSE ) { PetscInt M,N; PetscTruth is_block; /* check A is 2x2 block matrix */ Stg_PetscObjectTypeCompare( (PetscObject)A, "block", &is_block ); if (is_block==PETSC_FALSE) { Stg_SETERRQ( PETSC_ERR_SUP, "Only valid for MatType = block" ); } MatGetSize( A, &M, &N ); if ( (M!=2) || (N!=2) ) { Stg_SETERRQ2( PETSC_ERR_SUP, "Only valid for 2x2 block. Yours has dimension %Dx%D", M,N ); } VecDuplicate( x, &BA->Lz ); VecDuplicate( x, &BA->Rz ); BA->scaling_exists = PETSC_TRUE; } // if( BA->user_build_scaling != PETSC_NULL ) { // BA->user_build_scaling( A,b,x,BA->scaling_ctx); // } // else { BSSCR_MatStokesMVBlockDefaultBuildScaling(BA,A,b,x, sym); // } BA->scalings_have_been_inverted = PETSC_FALSE; PetscFunctionReturn(0); }
static PetscErrorCode getSumSquares(Mat matrix, double *diag) { PetscErrorCode ierr; int i, j; double *sumr, *sumc; PetscInt n, mLocal, nLocal, low, high; PetscReal *aux; PetscFunctionBegin; ierr = MatGetSize(matrix, NULL, &n); CHKERRQ(ierr); ierr = MatGetLocalSize(matrix, &mLocal, &nLocal); CHKERRQ(ierr); sumr = diag; sumc = &diag[mLocal]; ierr = PetscMalloc1(n, &aux); CHKERRQ(ierr); ierr = MatGetColumnNorms(matrix, NORM_2, aux); CHKERRQ(ierr); ierr = MatGetOwnershipRangeColumn(matrix, &low, &high);CHKERRQ(ierr); for (i=low; i<high; i++) { sumc[i-low] = aux[i]*aux[i]; } ierr = PetscFree(aux); CHKERRQ(ierr); ierr = MatGetOwnershipRange(matrix, &low, &high); CHKERRQ(ierr); for (i=low; i<high; i++) { PetscInt ncols; const PetscInt *cols; const PetscScalar *vals; sumr[i-low] = 0.0; ierr = MatGetRow(matrix, i, &ncols, &cols, &vals); CHKERRQ(ierr); for (j = 0; j < ncols; j++) { sumr[i-low] += PetscRealPart(vals[j]*PetscConj(vals[j])); } ierr = MatRestoreRow(matrix, i, &ncols, &cols, &vals); CHKERRQ(ierr); } PetscFunctionReturn(0); }
/* name[] is operator name */ PetscErrorCode BSSCR_MatInfoLog(PetscViewer v,Mat A,const char name[]) { MatInfo i; PetscReal nrm_1,nrm_f,nrm_inf; MatType mtype; PetscInt M,N; PetscViewerType vtype; PetscTruth isascii; PetscViewerGetType( v, &vtype ); Stg_PetscObjectTypeCompare( (PetscObject)v,PETSC_VIEWER_ASCII,&isascii ); if (!isascii) { PetscFunctionReturn(0); } MatGetSize( A, &M,&N ); MatGetInfo(A,MAT_GLOBAL_SUM,&i); MatGetType( A, &mtype ); MatNorm( A, NORM_1, &nrm_1 ); MatNorm( A, NORM_FROBENIUS, &nrm_f ); MatNorm( A, NORM_INFINITY, &nrm_inf ); PetscViewerASCIIPrintf( v, "MatInfo: %s \n", name ); PetscViewerASCIIPushTab(v); PetscViewerASCIIPrintf( v, "type=%s \n", mtype ); PetscViewerASCIIPrintf( v, "dimension=%Dx%D \n", M,N ); PetscViewerASCIIPrintf( v, "nnz=%D (total)\n", (PetscInt)i.nz_used ); PetscViewerASCIIPrintf( v, "nnz=%D (allocated)\n", (PetscInt)i.nz_allocated ); PetscViewerASCIIPrintf( v, "|A|_1 = %1.12e\n", nrm_1 ); PetscViewerASCIIPrintf( v, "|A|_frobenius = %1.12e\n", nrm_f ); PetscViewerASCIIPrintf( v, "|A|_inf = %1.12e\n", nrm_inf ); PetscViewerASCIIPopTab(v); PetscFunctionReturn(0); }
/* MatDumpSPAI - Dumps a PETSc matrix to a file in an ASCII format suitable for the SPAI code of Stephen Barnard to solve. This routine is simply here to allow testing of matrices directly with the SPAI code, rather then through the PETSc interface. */ PetscErrorCode MatDumpSPAI(Mat A,FILE *file) { const PetscScalar *vals; PetscErrorCode ierr; int i,j,n,size,nz; const int *cols; MPI_Comm comm; PetscObjectGetComm((PetscObject)A,&comm); MPI_Comm_size(comm,&size); if (size > 1) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only single processor dumps"); ierr = MatGetSize(A,&n,&n);CHKERRQ(ierr); /* print the matrix */ fprintf(file,"%d\n",n); for (i=0; i<n; i++) { ierr = MatGetRow(A,i,&nz,&cols,&vals);CHKERRQ(ierr); for (j=0; j<nz; j++) fprintf(file,"%d %d %16.14e\n",i+1,cols[j]+1,vals[j]); ierr = MatRestoreRow(A,i,&nz,&cols,&vals);CHKERRQ(ierr); } PetscFunctionReturn(0); }
static int PetscML_getrow(ML_Operator *ML_data, int N_requested_rows, int requested_rows[],int allocated_space, int columns[], double values[], int row_lengths[]) { PetscErrorCode ierr; PetscInt m,i,j,k=0,row,*aj; PetscScalar *aa; FineGridCtx *ml=(FineGridCtx*)ML_Get_MyGetrowData(ML_data); Mat_SeqAIJ *a = (Mat_SeqAIJ*)ml->Aloc->data; ierr = MatGetSize(ml->Aloc,&m,PETSC_NULL); if (ierr) return(0); for (i = 0; i<N_requested_rows; i++) { row = requested_rows[i]; row_lengths[i] = a->ilen[row]; if (allocated_space < k+row_lengths[i]) return(0); if ( (row >= 0) || (row <= (m-1)) ) { aj = a->j + a->i[row]; aa = a->a + a->i[row]; for (j=0; j<row_lengths[i]; j++){ columns[k] = aj[j]; values[k++] = aa[j]; } } } return(1); }
// ------------------------------------------------------------- // MatDuplicate_DenseGA // ------------------------------------------------------------- static PetscErrorCode MatDuplicate_DenseGA(Mat mat, MatDuplicateOption op, Mat *M) { PetscErrorCode ierr = 0; struct MatGACtx *ctx, *newctx; ierr = MatShellGetContext(mat, &ctx); CHKERRQ(ierr); MPI_Comm comm; ierr = PetscObjectGetComm((PetscObject)mat, &comm); CHKERRQ(ierr); PetscInt lrows, grows, lcols, gcols; ierr = MatGetSize(mat, &grows, &gcols); CHKERRQ(ierr); ierr = MatGetLocalSize(mat, &lrows, &lcols); CHKERRQ(ierr); ierr = PetscMalloc(sizeof(struct MatGACtx), &newctx); CHKERRQ(ierr); newctx->gaGroup = ctx->gaGroup; newctx->ga = GA_Duplicate(ctx->ga, "PETSc Dense Matrix"); ierr = MatCreateShell(comm, lrows, lcols, grows, gcols, newctx, M); CHKERRQ(ierr); ierr = MatSetOperations_DenseGA(*M); PetscScalar z(0.0); switch (op) { case (MAT_COPY_VALUES): GA_Copy(ctx->ga, newctx->ga); break; default: GA_Fill(newctx->ga, &z); break; } GA_Pgroup_sync(newctx->gaGroup); return ierr; }
/* PCGAMGCreateGraph - create simple scaled scalar graph from matrix Input Parameter: . Amat - matrix Output Parameter: . a_Gmaat - eoutput scalar graph (symmetric?) */ PetscErrorCode PCGAMGCreateGraph(Mat Amat, Mat *a_Gmat) { PetscErrorCode ierr; PetscInt Istart,Iend,Ii,jj,kk,ncols,nloc,NN,MM,bs; MPI_Comm comm; Mat Gmat; MatType mtype; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)Amat,&comm);CHKERRQ(ierr); ierr = MatGetOwnershipRange(Amat, &Istart, &Iend);CHKERRQ(ierr); ierr = MatGetSize(Amat, &MM, &NN);CHKERRQ(ierr); ierr = MatGetBlockSize(Amat, &bs);CHKERRQ(ierr); nloc = (Iend-Istart)/bs; #if defined PETSC_GAMG_USE_LOG ierr = PetscLogEventBegin(petsc_gamg_setup_events[GRAPH],0,0,0,0);CHKERRQ(ierr); #endif if (bs > 1) { const PetscScalar *vals; const PetscInt *idx; PetscInt *d_nnz, *o_nnz,*w0,*w1,*w2; PetscBool ismpiaij,isseqaij; /* Determine the preallocation needed for the scalar matrix derived from the vector matrix. */ ierr = PetscObjectBaseTypeCompare((PetscObject)Amat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr); ierr = PetscObjectBaseTypeCompare((PetscObject)Amat,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr); ierr = PetscMalloc2(nloc, &d_nnz,isseqaij ? 0 : nloc, &o_nnz);CHKERRQ(ierr); if (isseqaij) { PetscInt max_d_nnz; /* Determine exact preallocation count for (sequential) scalar matrix */ ierr = MatSeqAIJGetMaxRowNonzeros(Amat,&max_d_nnz);CHKERRQ(ierr); max_d_nnz = PetscMin(nloc,bs*max_d_nnz);CHKERRQ(ierr); ierr = PetscMalloc3(max_d_nnz, &w0,max_d_nnz, &w1,max_d_nnz, &w2);CHKERRQ(ierr); for (Ii = 0, jj = 0; Ii < Iend; Ii += bs, jj++) { ierr = MatCollapseRows(Amat,Ii,bs,w0,w1,w2,&d_nnz[jj],NULL);CHKERRQ(ierr); } ierr = PetscFree3(w0,w1,w2);CHKERRQ(ierr); } else if (ismpiaij) { Mat Daij,Oaij; const PetscInt *garray; PetscInt max_d_nnz; ierr = MatMPIAIJGetSeqAIJ(Amat,&Daij,&Oaij,&garray);CHKERRQ(ierr); /* Determine exact preallocation count for diagonal block portion of scalar matrix */ ierr = MatSeqAIJGetMaxRowNonzeros(Daij,&max_d_nnz);CHKERRQ(ierr); max_d_nnz = PetscMin(nloc,bs*max_d_nnz);CHKERRQ(ierr); ierr = PetscMalloc3(max_d_nnz, &w0,max_d_nnz, &w1,max_d_nnz, &w2);CHKERRQ(ierr); for (Ii = 0, jj = 0; Ii < Iend - Istart; Ii += bs, jj++) { ierr = MatCollapseRows(Daij,Ii,bs,w0,w1,w2,&d_nnz[jj],NULL);CHKERRQ(ierr); } ierr = PetscFree3(w0,w1,w2);CHKERRQ(ierr); /* Over estimate (usually grossly over), preallocation count for off-diagonal portion of scalar matrix */ for (Ii = 0, jj = 0; Ii < Iend - Istart; Ii += bs, jj++) { o_nnz[jj] = 0; for (kk=0; kk<bs; kk++) { /* rows that get collapsed to a single row */ ierr = MatGetRow(Oaij,Ii+kk,&ncols,0,0);CHKERRQ(ierr); o_nnz[jj] += ncols; ierr = MatRestoreRow(Oaij,Ii+kk,&ncols,0,0);CHKERRQ(ierr); } if (o_nnz[jj] > (NN/bs-nloc)) o_nnz[jj] = NN/bs-nloc; } } else SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_USER,"Require AIJ matrix type"); /* get scalar copy (norms) of matrix */ ierr = MatGetType(Amat,&mtype);CHKERRQ(ierr); ierr = MatCreate(comm, &Gmat);CHKERRQ(ierr); ierr = MatSetSizes(Gmat,nloc,nloc,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); ierr = MatSetBlockSizes(Gmat, 1, 1);CHKERRQ(ierr); ierr = MatSetType(Gmat, mtype);CHKERRQ(ierr); ierr = MatSeqAIJSetPreallocation(Gmat,0,d_nnz);CHKERRQ(ierr); ierr = MatMPIAIJSetPreallocation(Gmat,0,d_nnz,0,o_nnz);CHKERRQ(ierr); ierr = PetscFree2(d_nnz,o_nnz);CHKERRQ(ierr); for (Ii = Istart; Ii < Iend; Ii++) { PetscInt dest_row = Ii/bs; ierr = MatGetRow(Amat,Ii,&ncols,&idx,&vals);CHKERRQ(ierr); for (jj=0; jj<ncols; jj++) { PetscInt dest_col = idx[jj]/bs; PetscScalar sv = PetscAbs(PetscRealPart(vals[jj])); ierr = MatSetValues(Gmat,1,&dest_row,1,&dest_col,&sv,ADD_VALUES);CHKERRQ(ierr); } ierr = MatRestoreRow(Amat,Ii,&ncols,&idx,&vals);CHKERRQ(ierr); } ierr = MatAssemblyBegin(Gmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(Gmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); } else { /* just copy scalar matrix - abs() not taken here but scaled later */ ierr = MatDuplicate(Amat, MAT_COPY_VALUES, &Gmat);CHKERRQ(ierr); } #if defined PETSC_GAMG_USE_LOG ierr = PetscLogEventEnd(petsc_gamg_setup_events[GRAPH],0,0,0,0);CHKERRQ(ierr); #endif *a_Gmat = Gmat; PetscFunctionReturn(0); }
PetscErrorCode Create(MPI_Comm comm,Mat *inA,IS *is0,IS *is1) { PetscErrorCode ierr; Mat A; PetscInt r,rend,M; PetscMPIInt rank; PetscFunctionBeginUser; *inA = 0; ierr = MatCreate(comm,&A); CHKERRQ(ierr); ierr = MatSetSizes(A,4,4,PETSC_DETERMINE,PETSC_DETERMINE); CHKERRQ(ierr); ierr = MatSetFromOptions(A); CHKERRQ(ierr); ierr = MatSetUp(A); CHKERRQ(ierr); ierr = MatGetOwnershipRange(A,&r,&rend); CHKERRQ(ierr); ierr = MatGetSize(A,&M,NULL); CHKERRQ(ierr); ierr = ISCreateStride(comm,2,r,1,is0); CHKERRQ(ierr); ierr = ISCreateStride(comm,2,r+2,1,is1); CHKERRQ(ierr); ierr = MPI_Comm_rank(comm,&rank); CHKERRQ(ierr); { PetscInt rows[4],cols0[5],cols1[5],cols2[3],cols3[3]; PetscScalar RR = 1000.*rank,vals0[5],vals1[4],vals2[3],vals3[3]; rows[0] = r; rows[1] = r+1; rows[2] = r+2; rows[3] = r+3; cols0[0] = r+0; cols0[1] = r+1; cols0[2] = r+3; cols0[3] = (r+4)%M; cols0[4] = (r+M-4)%M; cols1[0] = r+1; cols1[1] = r+2; cols1[2] = (r+4+1)%M; cols1[3] = (r+M-4+1)%M; cols2[0] = r; cols2[1] = r+2; cols2[2] = (r+4+2)%M; cols3[0] = r+1; cols3[1] = r+3; cols3[2] = (r+4+3)%M; vals0[0] = RR+1.; vals0[1] = RR+2.; vals0[2] = RR+3.; vals0[3] = RR+4.; vals0[4] = RR+5.; vals1[0] = RR+6.; vals1[1] = RR+7.; vals1[2] = RR+8.; vals1[3] = RR+9.; vals2[0] = RR+10.; vals2[1] = RR+11.; vals2[2] = RR+12.; vals3[0] = RR+13.; vals3[1] = RR+14.; vals3[2] = RR+15.; ierr = MatSetValues(A,1,&rows[0],5,cols0,vals0,INSERT_VALUES); CHKERRQ(ierr); ierr = MatSetValues(A,1,&rows[1],4,cols1,vals1,INSERT_VALUES); CHKERRQ(ierr); ierr = MatSetValues(A,1,&rows[2],3,cols2,vals2,INSERT_VALUES); CHKERRQ(ierr); ierr = MatSetValues(A,1,&rows[3],3,cols3,vals3,INSERT_VALUES); CHKERRQ(ierr); } ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = MatAssemblyEnd (A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); *inA = A; PetscFunctionReturn(0); }
static PetscErrorCode PCSetUp_PARMS(PC pc) { Mat pmat; PC_PARMS *parms = (PC_PARMS*)pc->data; const PetscInt *mapptr0; PetscInt n, lsize, low, high, i, pos, ncols, length; int *maptmp, *mapptr, *ia, *ja, *ja1, *im; PetscScalar *aa, *aa1; const PetscInt *cols; PetscInt meth[8]; const PetscScalar *values; PetscErrorCode ierr; MatInfo matinfo; PetscMPIInt rank, npro; PetscFunctionBegin; /* Get preconditioner matrix from PETSc and setup pARMS structs */ ierr = PCGetOperators(pc,PETSC_NULL,&pmat,PETSC_NULL);CHKERRQ(ierr); MPI_Comm_size(((PetscObject)pmat)->comm,&npro); MPI_Comm_rank(((PetscObject)pmat)->comm,&rank); ierr = MatGetSize(pmat,&n,PETSC_NULL);CHKERRQ(ierr); ierr = PetscMalloc((npro+1)*sizeof(int),&mapptr);CHKERRQ(ierr); ierr = PetscMalloc(n*sizeof(int),&maptmp);CHKERRQ(ierr); ierr = MatGetOwnershipRanges(pmat,&mapptr0);CHKERRQ(ierr); low = mapptr0[rank]; high = mapptr0[rank+1]; lsize = high - low; for (i=0; i<npro+1; i++) mapptr[i] = mapptr0[i]+1; for (i = 0; i<n; i++) maptmp[i] = i+1; /* if created, destroy the previous map */ if (parms->map) { parms_MapFree(&parms->map); parms->map = PETSC_NULL; } /* create pARMS map object */ parms_MapCreateFromPtr(&parms->map,(int)n,maptmp,mapptr,((PetscObject)pmat)->comm,1,NONINTERLACED); /* if created, destroy the previous pARMS matrix */ if (parms->A) { parms_MatFree(&parms->A); parms->A = PETSC_NULL; } /* create pARMS mat object */ parms_MatCreate(&parms->A,parms->map); /* setup and copy csr data structure for pARMS */ ierr = PetscMalloc((lsize+1)*sizeof(int),&ia);CHKERRQ(ierr); ia[0] = 1; ierr = MatGetInfo(pmat,MAT_LOCAL,&matinfo);CHKERRQ(ierr); length = matinfo.nz_used; ierr = PetscMalloc(length*sizeof(int),&ja);CHKERRQ(ierr); ierr = PetscMalloc(length*sizeof(PetscScalar),&aa);CHKERRQ(ierr); for (i = low; i<high; i++) { pos = ia[i-low]-1; ierr = MatGetRow(pmat,i,&ncols,&cols,&values);CHKERRQ(ierr); ia[i-low+1] = ia[i-low] + ncols; if (ia[i-low+1] >= length) { length += ncols; ierr = PetscMalloc(length*sizeof(int),&ja1);CHKERRQ(ierr); ierr = PetscMemcpy(ja1,ja,(ia[i-low]-1)*sizeof(int));CHKERRQ(ierr); ierr = PetscFree(ja);CHKERRQ(ierr); ja = ja1; ierr = PetscMalloc(length*sizeof(PetscScalar),&aa1);CHKERRQ(ierr); ierr = PetscMemcpy(aa1,aa,(ia[i-low]-1)*sizeof(PetscScalar));CHKERRQ(ierr); ierr = PetscFree(aa);CHKERRQ(ierr); aa = aa1; } ierr = PetscMemcpy(&ja[pos],cols,ncols*sizeof(int));CHKERRQ(ierr); ierr = PetscMemcpy(&aa[pos],values,ncols*sizeof(PetscScalar));CHKERRQ(ierr); ierr = MatRestoreRow(pmat,i,&ncols,&cols,&values);CHKERRQ(ierr); } /* csr info is for local matrix so initialize im[] locally */ ierr = PetscMalloc(lsize*sizeof(int),&im);CHKERRQ(ierr); ierr = PetscMemcpy(im,&maptmp[mapptr[rank]-1],lsize*sizeof(int));CHKERRQ(ierr); /* 1-based indexing */ for (i=0; i<ia[lsize]-1; i++) ja[i] = ja[i]+1; /* Now copy csr matrix to parms_mat object */ parms_MatSetValues(parms->A,(int)lsize,im,ia,ja,aa,INSERT); /* free memory */ ierr = PetscFree(maptmp);CHKERRQ(ierr); ierr = PetscFree(mapptr);CHKERRQ(ierr); ierr = PetscFree(aa);CHKERRQ(ierr); ierr = PetscFree(ja);CHKERRQ(ierr); ierr = PetscFree(ia);CHKERRQ(ierr); ierr = PetscFree(im);CHKERRQ(ierr); /* setup parms matrix */ parms_MatSetup(parms->A); /* if created, destroy the previous pARMS pc */ if (parms->pc) { parms_PCFree(&parms->pc); parms->pc = PETSC_NULL; } /* Now create pARMS preconditioner object based on A */ parms_PCCreate(&parms->pc,parms->A); /* Transfer options from PC to pARMS */ switch(parms->global) { case 0: parms_PCSetType(parms->pc, PCRAS); break; case 1: parms_PCSetType(parms->pc, PCSCHUR); break; case 2: parms_PCSetType(parms->pc, PCBJ); break; } switch(parms->local) { case 0: parms_PCSetILUType(parms->pc, PCILU0); break; case 1: parms_PCSetILUType(parms->pc, PCILUK); break; case 2: parms_PCSetILUType(parms->pc, PCILUT); break; case 3: parms_PCSetILUType(parms->pc, PCARMS); break; } parms_PCSetInnerEps(parms->pc, parms->solvetol); parms_PCSetNlevels(parms->pc, parms->levels); parms_PCSetPermType(parms->pc, parms->nonsymperm?1:0); parms_PCSetBsize(parms->pc, parms->blocksize); parms_PCSetTolInd(parms->pc, parms->indtol); parms_PCSetInnerKSize(parms->pc, parms->maxdim); parms_PCSetInnerMaxits(parms->pc, parms->maxits); for (i=0; i<8; i++) meth[i] = parms->meth[i]?1:0; parms_PCSetPermScalOptions(parms->pc, &meth[0], 1); parms_PCSetPermScalOptions(parms->pc, &meth[4], 0); parms_PCSetFill(parms->pc, parms->lfil); parms_PCSetTol(parms->pc, parms->droptol); parms_PCSetup(parms->pc); /* Allocate two auxiliary vector of length lsize */ if (parms->lvec0) { ierr = PetscFree(parms->lvec0);CHKERRQ(ierr); } ierr = PetscMalloc(lsize*sizeof(PetscScalar), &parms->lvec0);CHKERRQ(ierr); if (parms->lvec1) { ierr = PetscFree(parms->lvec1);CHKERRQ(ierr); } ierr = PetscMalloc(lsize*sizeof(PetscScalar), &parms->lvec1);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C PCGAMGFilterGraph - filter (remove zero and possibly small values from the) graph and make it symmetric if requested Collective on Mat Input Parameter: + a_Gmat - the graph . vfilter - threshold paramter [0,1) - symm - make the result symmetric Level: developer Notes: This is called before graph coarsers are called. .seealso: PCGAMGSetThreshold() @*/ PetscErrorCode PCGAMGFilterGraph(Mat *a_Gmat,PetscReal vfilter,PetscBool symm) { PetscErrorCode ierr; PetscInt Istart,Iend,Ii,jj,ncols,nnz0,nnz1, NN, MM, nloc; PetscMPIInt rank; Mat Gmat = *a_Gmat, tGmat, matTrans; MPI_Comm comm; const PetscScalar *vals; const PetscInt *idx; PetscInt *d_nnz, *o_nnz; Vec diag; MatType mtype; PetscFunctionBegin; #if defined PETSC_GAMG_USE_LOG ierr = PetscLogEventBegin(petsc_gamg_setup_events[GRAPH],0,0,0,0);CHKERRQ(ierr); #endif /* scale Gmat for all values between -1 and 1 */ ierr = MatCreateVecs(Gmat, &diag, 0);CHKERRQ(ierr); ierr = MatGetDiagonal(Gmat, diag);CHKERRQ(ierr); ierr = VecReciprocal(diag);CHKERRQ(ierr); ierr = VecSqrtAbs(diag);CHKERRQ(ierr); ierr = MatDiagonalScale(Gmat, diag, diag);CHKERRQ(ierr); ierr = VecDestroy(&diag);CHKERRQ(ierr); if (vfilter < 0.0 && !symm) { /* Just use the provided matrix as the graph but make all values positive */ MatInfo info; PetscScalar *avals; PetscBool isaij,ismpiaij; ierr = PetscObjectBaseTypeCompare((PetscObject)Gmat,MATSEQAIJ,&isaij);CHKERRQ(ierr); ierr = PetscObjectBaseTypeCompare((PetscObject)Gmat,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr); if (!isaij && !ismpiaij) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_USER,"Require (MPI)AIJ matrix type"); if (isaij) { ierr = MatGetInfo(Gmat,MAT_LOCAL,&info);CHKERRQ(ierr); ierr = MatSeqAIJGetArray(Gmat,&avals);CHKERRQ(ierr); for (jj = 0; jj<info.nz_used; jj++) avals[jj] = PetscAbsScalar(avals[jj]); ierr = MatSeqAIJRestoreArray(Gmat,&avals);CHKERRQ(ierr); } else { Mat_MPIAIJ *aij = (Mat_MPIAIJ*)Gmat->data; ierr = MatGetInfo(aij->A,MAT_LOCAL,&info);CHKERRQ(ierr); ierr = MatSeqAIJGetArray(aij->A,&avals);CHKERRQ(ierr); for (jj = 0; jj<info.nz_used; jj++) avals[jj] = PetscAbsScalar(avals[jj]); ierr = MatSeqAIJRestoreArray(aij->A,&avals);CHKERRQ(ierr); ierr = MatGetInfo(aij->B,MAT_LOCAL,&info);CHKERRQ(ierr); ierr = MatSeqAIJGetArray(aij->B,&avals);CHKERRQ(ierr); for (jj = 0; jj<info.nz_used; jj++) avals[jj] = PetscAbsScalar(avals[jj]); ierr = MatSeqAIJRestoreArray(aij->B,&avals);CHKERRQ(ierr); } #if defined PETSC_GAMG_USE_LOG ierr = PetscLogEventEnd(petsc_gamg_setup_events[GRAPH],0,0,0,0);CHKERRQ(ierr); #endif PetscFunctionReturn(0); } ierr = PetscObjectGetComm((PetscObject)Gmat,&comm);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); ierr = MatGetOwnershipRange(Gmat, &Istart, &Iend);CHKERRQ(ierr); nloc = Iend - Istart; ierr = MatGetSize(Gmat, &MM, &NN);CHKERRQ(ierr); if (symm) { ierr = MatTranspose(Gmat, MAT_INITIAL_MATRIX, &matTrans);CHKERRQ(ierr); } /* Determine upper bound on nonzeros needed in new filtered matrix */ ierr = PetscMalloc2(nloc, &d_nnz,nloc, &o_nnz);CHKERRQ(ierr); for (Ii = Istart, jj = 0; Ii < Iend; Ii++, jj++) { ierr = MatGetRow(Gmat,Ii,&ncols,NULL,NULL);CHKERRQ(ierr); d_nnz[jj] = ncols; o_nnz[jj] = ncols; ierr = MatRestoreRow(Gmat,Ii,&ncols,NULL,NULL);CHKERRQ(ierr); if (symm) { ierr = MatGetRow(matTrans,Ii,&ncols,NULL,NULL);CHKERRQ(ierr); d_nnz[jj] += ncols; o_nnz[jj] += ncols; ierr = MatRestoreRow(matTrans,Ii,&ncols,NULL,NULL);CHKERRQ(ierr); } if (d_nnz[jj] > nloc) d_nnz[jj] = nloc; if (o_nnz[jj] > (MM-nloc)) o_nnz[jj] = MM - nloc; } ierr = MatGetType(Gmat,&mtype);CHKERRQ(ierr); ierr = MatCreate(comm, &tGmat);CHKERRQ(ierr); ierr = MatSetSizes(tGmat,nloc,nloc,MM,MM);CHKERRQ(ierr); ierr = MatSetBlockSizes(tGmat, 1, 1);CHKERRQ(ierr); ierr = MatSetType(tGmat, mtype);CHKERRQ(ierr); ierr = MatSeqAIJSetPreallocation(tGmat,0,d_nnz);CHKERRQ(ierr); ierr = MatMPIAIJSetPreallocation(tGmat,0,d_nnz,0,o_nnz);CHKERRQ(ierr); ierr = PetscFree2(d_nnz,o_nnz);CHKERRQ(ierr); if (symm) { ierr = MatDestroy(&matTrans);CHKERRQ(ierr); } else { /* all entries are generated locally so MatAssembly will be slightly faster for large process counts */ ierr = MatSetOption(tGmat,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr); } for (Ii = Istart, nnz0 = nnz1 = 0; Ii < Iend; Ii++) { ierr = MatGetRow(Gmat,Ii,&ncols,&idx,&vals);CHKERRQ(ierr); for (jj=0; jj<ncols; jj++,nnz0++) { PetscScalar sv = PetscAbs(PetscRealPart(vals[jj])); if (PetscRealPart(sv) > vfilter) { nnz1++; if (symm) { sv *= 0.5; ierr = MatSetValues(tGmat,1,&Ii,1,&idx[jj],&sv,ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValues(tGmat,1,&idx[jj],1,&Ii,&sv,ADD_VALUES);CHKERRQ(ierr); } else { ierr = MatSetValues(tGmat,1,&Ii,1,&idx[jj],&sv,ADD_VALUES);CHKERRQ(ierr); } } } ierr = MatRestoreRow(Gmat,Ii,&ncols,&idx,&vals);CHKERRQ(ierr); } ierr = MatAssemblyBegin(tGmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(tGmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); #if defined PETSC_GAMG_USE_LOG ierr = PetscLogEventEnd(petsc_gamg_setup_events[GRAPH],0,0,0,0);CHKERRQ(ierr); #endif #if defined(PETSC_USE_INFO) { double t1 = (!nnz0) ? 1. : 100.*(double)nnz1/(double)nnz0, t2 = (!nloc) ? 1. : (double)nnz0/(double)nloc; ierr = PetscInfo4(*a_Gmat,"\t %g%% nnz after filtering, with threshold %g, %g nnz ave. (N=%D)\n",t1,vfilter,t2,MM);CHKERRQ(ierr); } #endif ierr = MatDestroy(&Gmat);CHKERRQ(ierr); *a_Gmat = tGmat; PetscFunctionReturn(0); }
/* MatConvert_Basic - Converts from any input format to another format. For parallel formats, the new matrix distribution is determined by PETSc. Does not do preallocation so in general will be slow */ PetscErrorCode MatConvert_Basic(Mat mat, MatType newtype,MatReuse reuse,Mat *newmat) { Mat M; const PetscScalar *vwork; PetscErrorCode ierr; PetscInt i,j,nz,m,n,rstart,rend,lm,ln,prbs,pcbs,cstart,cend,*dnz,*onz; const PetscInt *cwork; PetscBool isseqsbaij,ismpisbaij,isseqbaij,ismpibaij,isseqdense,ismpidense; PetscFunctionBegin; ierr = MatGetSize(mat,&m,&n);CHKERRQ(ierr); ierr = MatGetLocalSize(mat,&lm,&ln);CHKERRQ(ierr); if (ln == n) ln = PETSC_DECIDE; /* try to preserve column ownership */ ierr = MatCreate(PetscObjectComm((PetscObject)mat),&M);CHKERRQ(ierr); ierr = MatSetSizes(M,lm,ln,m,n);CHKERRQ(ierr); ierr = MatSetBlockSizes(M,mat->rmap->bs,mat->cmap->bs);CHKERRQ(ierr); ierr = MatSetType(M,newtype);CHKERRQ(ierr); ierr = MatGetOwnershipRange(mat,&rstart,&rend);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)M,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)M,MATMPISBAIJ,&ismpisbaij);CHKERRQ(ierr); if (isseqsbaij || ismpisbaij) {ierr = MatSetOption(M,MAT_IGNORE_LOWER_TRIANGULAR,PETSC_TRUE);CHKERRQ(ierr);} ierr = PetscObjectTypeCompare((PetscObject)M,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)M,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)M,MATSEQDENSE,&isseqdense);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)M,MATMPIDENSE,&ismpidense);CHKERRQ(ierr); if (isseqdense) { ierr = MatSeqDenseSetPreallocation(M,NULL);CHKERRQ(ierr); } else if (ismpidense) { ierr = MatMPIDenseSetPreallocation(M,NULL);CHKERRQ(ierr); } else { /* Preallocation block sizes. (S)BAIJ matrices will have one index per block. */ prbs = (isseqbaij || ismpibaij || isseqsbaij || ismpisbaij) ? M->rmap->bs : 1; pcbs = (isseqbaij || ismpibaij || isseqsbaij || ismpisbaij) ? M->cmap->bs : 1; ierr = PetscMalloc2(lm/prbs,&dnz,lm/prbs,&onz);CHKERRQ(ierr); ierr = MatGetOwnershipRangeColumn(mat,&cstart,&cend);CHKERRQ(ierr); for (i=0; i<lm; i+=prbs) { ierr = MatGetRow(mat,rstart+i,&nz,&cwork,NULL);CHKERRQ(ierr); dnz[i] = 0; onz[i] = 0; for (j=0; j<nz; j+=pcbs) { if ((isseqsbaij || ismpisbaij) && cwork[j] < rstart+i) continue; if (cstart <= cwork[j] && cwork[j] < cend) dnz[i]++; else onz[i]++; } ierr = MatRestoreRow(mat,rstart+i,&nz,&cwork,NULL);CHKERRQ(ierr); } ierr = MatXAIJSetPreallocation(M,M->rmap->bs,dnz,onz,dnz,onz);CHKERRQ(ierr); ierr = PetscFree2(dnz,onz);CHKERRQ(ierr); } for (i=rstart; i<rend; i++) { ierr = MatGetRow(mat,i,&nz,&cwork,&vwork);CHKERRQ(ierr); ierr = MatSetValues(M,1,&i,nz,cwork,vwork,INSERT_VALUES);CHKERRQ(ierr); ierr = MatRestoreRow(mat,i,&nz,&cwork,&vwork);CHKERRQ(ierr); } ierr = MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); if (reuse == MAT_REUSE_MATRIX) { ierr = MatHeaderReplace(mat,M);CHKERRQ(ierr); } else { *newmat = M; } PetscFunctionReturn(0); }
static PetscErrorCode KSPSolve_LSQR(KSP ksp) { PetscErrorCode ierr; PetscInt i,size1,size2; PetscScalar rho,rhobar,phi,phibar,theta,c,s,tmp,tau; PetscReal beta,alpha,rnorm; Vec X,B,V,V1,U,U1,TMP,W,W2,SE,Z = NULL; Mat Amat,Pmat; MatStructure pflag; KSP_LSQR *lsqr = (KSP_LSQR*)ksp->data; PetscBool diagonalscale,nopreconditioner; PetscFunctionBegin; ierr = PCGetDiagonalScale(ksp->pc,&diagonalscale);CHKERRQ(ierr); if (diagonalscale) SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name); ierr = PCGetOperators(ksp->pc,&Amat,&Pmat,&pflag);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)ksp->pc,PCNONE,&nopreconditioner);CHKERRQ(ierr); /* nopreconditioner =PETSC_FALSE; */ /* Calculate norm of right hand side */ ierr = VecNorm(ksp->vec_rhs,NORM_2,&lsqr->rhs_norm);CHKERRQ(ierr); /* mark norm of matrix with negative number to indicate it has not yet been computed */ lsqr->anorm = -1.0; /* vectors of length m, where system size is mxn */ B = ksp->vec_rhs; U = lsqr->vwork_m[0]; U1 = lsqr->vwork_m[1]; /* vectors of length n */ X = ksp->vec_sol; W = lsqr->vwork_n[0]; V = lsqr->vwork_n[1]; V1 = lsqr->vwork_n[2]; W2 = lsqr->vwork_n[3]; if (!nopreconditioner) Z = lsqr->vwork_n[4]; /* standard error vector */ SE = lsqr->se; if (SE) { ierr = VecGetSize(SE,&size1);CHKERRQ(ierr); ierr = VecGetSize(X,&size2);CHKERRQ(ierr); if (size1 != size2) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Standard error vector (size %d) does not match solution vector (size %d)",size1,size2); ierr = VecSet(SE,0.0);CHKERRQ(ierr); } /* Compute initial residual, temporarily use work vector u */ if (!ksp->guess_zero) { ierr = KSP_MatMult(ksp,Amat,X,U);CHKERRQ(ierr); /* u <- b - Ax */ ierr = VecAYPX(U,-1.0,B);CHKERRQ(ierr); } else { ierr = VecCopy(B,U);CHKERRQ(ierr); /* u <- b (x is 0) */ } /* Test for nothing to do */ ierr = VecNorm(U,NORM_2,&rnorm);CHKERRQ(ierr); ierr = PetscObjectAMSTakeAccess((PetscObject)ksp);CHKERRQ(ierr); ksp->its = 0; ksp->rnorm = rnorm; ierr = PetscObjectAMSGrantAccess((PetscObject)ksp);CHKERRQ(ierr); ierr = KSPLogResidualHistory(ksp,rnorm);CHKERRQ(ierr); ierr = KSPMonitor(ksp,0,rnorm);CHKERRQ(ierr); ierr = (*ksp->converged)(ksp,0,rnorm,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) PetscFunctionReturn(0); beta = rnorm; ierr = VecScale(U,1.0/beta);CHKERRQ(ierr); ierr = KSP_MatMultTranspose(ksp,Amat,U,V);CHKERRQ(ierr); if (nopreconditioner) { ierr = VecNorm(V,NORM_2,&alpha);CHKERRQ(ierr); } else { ierr = PCApply(ksp->pc,V,Z);CHKERRQ(ierr); ierr = VecDotRealPart(V,Z,&alpha);CHKERRQ(ierr); if (alpha <= 0.0) { ksp->reason = KSP_DIVERGED_BREAKDOWN; PetscFunctionReturn(0); } alpha = PetscSqrtReal(alpha); ierr = VecScale(Z,1.0/alpha);CHKERRQ(ierr); } ierr = VecScale(V,1.0/alpha);CHKERRQ(ierr); if (nopreconditioner) { ierr = VecCopy(V,W);CHKERRQ(ierr); } else { ierr = VecCopy(Z,W);CHKERRQ(ierr); } lsqr->arnorm = alpha * beta; phibar = beta; rhobar = alpha; i = 0; do { if (nopreconditioner) { ierr = KSP_MatMult(ksp,Amat,V,U1);CHKERRQ(ierr); } else { ierr = KSP_MatMult(ksp,Amat,Z,U1);CHKERRQ(ierr); } ierr = VecAXPY(U1,-alpha,U);CHKERRQ(ierr); ierr = VecNorm(U1,NORM_2,&beta);CHKERRQ(ierr); if (beta == 0.0) { ksp->reason = KSP_DIVERGED_BREAKDOWN; break; } ierr = VecScale(U1,1.0/beta);CHKERRQ(ierr); ierr = KSP_MatMultTranspose(ksp,Amat,U1,V1);CHKERRQ(ierr); ierr = VecAXPY(V1,-beta,V);CHKERRQ(ierr); if (nopreconditioner) { ierr = VecNorm(V1,NORM_2,&alpha);CHKERRQ(ierr); } else { ierr = PCApply(ksp->pc,V1,Z);CHKERRQ(ierr); ierr = VecDotRealPart(V1,Z,&alpha);CHKERRQ(ierr); if (alpha <= 0.0) { ksp->reason = KSP_DIVERGED_BREAKDOWN; break; } alpha = PetscSqrtReal(alpha); ierr = VecScale(Z,1.0/alpha);CHKERRQ(ierr); } ierr = VecScale(V1,1.0/alpha);CHKERRQ(ierr); rho = PetscSqrtScalar(rhobar*rhobar + beta*beta); c = rhobar / rho; s = beta / rho; theta = s * alpha; rhobar = -c * alpha; phi = c * phibar; phibar = s * phibar; tau = s * phi; ierr = VecAXPY(X,phi/rho,W);CHKERRQ(ierr); /* x <- x + (phi/rho) w */ if (SE) { ierr = VecCopy(W,W2);CHKERRQ(ierr); ierr = VecSquare(W2);CHKERRQ(ierr); ierr = VecScale(W2,1.0/(rho*rho));CHKERRQ(ierr); ierr = VecAXPY(SE, 1.0, W2);CHKERRQ(ierr); /* SE <- SE + (w^2/rho^2) */ } if (nopreconditioner) { ierr = VecAYPX(W,-theta/rho,V1);CHKERRQ(ierr); /* w <- v - (theta/rho) w */ } else { ierr = VecAYPX(W,-theta/rho,Z);CHKERRQ(ierr); /* w <- z - (theta/rho) w */ } lsqr->arnorm = alpha*PetscAbsScalar(tau); rnorm = PetscRealPart(phibar); ierr = PetscObjectAMSTakeAccess((PetscObject)ksp);CHKERRQ(ierr); ksp->its++; ksp->rnorm = rnorm; ierr = PetscObjectAMSGrantAccess((PetscObject)ksp);CHKERRQ(ierr); ierr = KSPLogResidualHistory(ksp,rnorm);CHKERRQ(ierr); ierr = KSPMonitor(ksp,i+1,rnorm);CHKERRQ(ierr); ierr = (*ksp->converged)(ksp,i+1,rnorm,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) break; SWAP(U1,U,TMP); SWAP(V1,V,TMP); i++; } while (i<ksp->max_it); if (i >= ksp->max_it && !ksp->reason) ksp->reason = KSP_DIVERGED_ITS; /* Finish off the standard error estimates */ if (SE) { tmp = 1.0; ierr = MatGetSize(Amat,&size1,&size2);CHKERRQ(ierr); if (size1 > size2) tmp = size1 - size2; tmp = rnorm / PetscSqrtScalar(tmp); ierr = VecSqrtAbs(SE);CHKERRQ(ierr); ierr = VecScale(SE,tmp);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode BearQuery(PetscInt s, PetscScalar c, Mat invL1, Mat invU1, Mat invL2, Mat invU2, Mat H12, Mat H21, Vec order, Vec or){ PetscErrorCode err; PetscInt n1, n2, n; PetscInt oseed; PetscScalar val, one = 1.0; Vec r = NULL; Vec r1 = NULL, q1 = NULL, t1_1 = NULL, t1_2 = NULL, t1_3 = NULL, t1_4 = NULL, t1_5 = NULL; // dimension: n1 Vec r2 = NULL, q2 = NULL, q_tilda = NULL, t2_1 = NULL, t2_2 = NULL, t2_3 = NULL; // dimension: n2 err = MatGetSize(H12, &n1, &n2); CHKERRQ(err); n = n1 + n2; // err = PetscPrintf(PETSC_COMM_WORLD, "n1: %d, n2: %d\n", n1, n2); CHKERRQ(err); err = VecCreateMPI(PETSC_COMM_WORLD, PETSC_DECIDE, n, &r); CHKERRQ(err); err = VecCreateMPI(PETSC_COMM_WORLD, PETSC_DECIDE, n1, &q1); CHKERRQ(err); err = VecCreateMPI(PETSC_COMM_WORLD, PETSC_DECIDE, n2, &q2); CHKERRQ(err); err = VecSet(q1, 0); CHKERRQ(err); err = VecSet(q2, 0); CHKERRQ(err); s = s - 1; // shift -1 for zero-based index err = VecGetValues(order, 1, &s, &val); CHKERRQ(err); oseed = (PetscInt) val; // err = PetscPrintf(PETSC_COMM_WORLD, "Given seed: %d, Reorered seed: %d (0 ~ n-1)\n", s, oseed); CHKERRQ(err); if(oseed < n1){ err = VecSetValues(q1, 1, &oseed, &one, INSERT_VALUES); CHKERRQ(err); }else{ oseed = oseed - n1; err = VecSetValues(q2, 1, &oseed, &one, INSERT_VALUES); CHKERRQ(err); //err = printVecSum(q2); } err = VecAssemblyBegin(q1); CHKERRQ(err); err = VecAssemblyBegin(q2); CHKERRQ(err); err = VecAssemblyEnd(q1); CHKERRQ(err); err = VecAssemblyEnd(q2); CHKERRQ(err); err = VecDuplicate(q1, &r1); CHKERRQ(err); err = VecDuplicate(q1, &t1_1); CHKERRQ(err); err = VecDuplicate(q1, &t1_2); CHKERRQ(err); err = VecDuplicate(q1, &t1_3); CHKERRQ(err); err = VecDuplicate(q1, &t1_4); CHKERRQ(err); err = VecDuplicate(q1, &t1_5); CHKERRQ(err); err = VecDuplicate(q2, &r2); CHKERRQ(err); err = VecDuplicate(q2, &q_tilda); CHKERRQ(err); err = VecDuplicate(q2, &t2_1); CHKERRQ(err); err = VecDuplicate(q2, &t2_2); CHKERRQ(err); err = VecDuplicate(q2, &t2_3); CHKERRQ(err); // Start matrix-vec multiplications err = MatMult(invL1, q1, t1_1); CHKERRQ(err); err = MatMult(invU1, t1_1, t1_2); CHKERRQ(err); err = MatMult(H21, t1_2, t2_1); CHKERRQ(err); err = VecAXPBYPCZ(q_tilda, 1.0, -1.0, 0.0, q2, t2_1); CHKERRQ(err); err = MatMult(invL2, q_tilda, t2_2); CHKERRQ(err); err = MatMult(invU2, t2_2, r2); CHKERRQ(err); err = MatMult(H12, r2, t1_3); CHKERRQ(err); err = VecAXPBYPCZ(t1_4, 1.0, -1.0, 0.0, q1, t1_3); CHKERRQ(err); err = MatMult(invL1, t1_4, t1_5); CHKERRQ(err); err = MatMult(invU1, t1_5, r1); CHKERRQ(err); //err = printVecSum(r1); //err = VecView(r2, PETSC_VIEWER_STDOUT_WORLD); // Concatenate r1 and r2 err = VecMerge(r1, r2, r); CHKERRQ(err); err = VecScale(r, c); CHKERRQ(err); //err = VecView(r, PETSC_VIEWER_STDOUT_WORLD); //err = VecDuplicate(r, &or); CHKERRQ(err); err = VecReorder(r, order, or); CHKERRQ(err); //err = VecView(or, PETSC_VIEWER_STDOUT_WORLD); err = VecDestroy(&r); CHKERRQ(err); err = VecDestroy(&r1); CHKERRQ(err); err = VecDestroy(&q1); CHKERRQ(err); err = VecDestroy(&t1_1); CHKERRQ(err); err = VecDestroy(&t1_2); CHKERRQ(err); err = VecDestroy(&t1_3); CHKERRQ(err); err = VecDestroy(&t1_4); CHKERRQ(err); err = VecDestroy(&t1_5); CHKERRQ(err); err = VecDestroy(&r2); CHKERRQ(err); err = VecDestroy(&q2); CHKERRQ(err); err = VecDestroy(&q_tilda); CHKERRQ(err); err = VecDestroy(&t2_1); CHKERRQ(err); err = VecDestroy(&t2_2); CHKERRQ(err); err = VecDestroy(&t2_3); CHKERRQ(err); return err; }
PetscErrorCode InitializeProblem(AppCtx *user) { PetscErrorCode ierr; PetscViewer loader; MPI_Comm comm; PetscInt nrows,ncols,i; PetscScalar one=1.0; char filebase[128]; char filename[128]; PetscFunctionBegin; comm = PETSC_COMM_WORLD; ierr = PetscStrncpy(filebase,user->name,128);CHKERRQ(ierr); ierr = PetscStrncat(filebase,"/",1);CHKERRQ(ierr); ierr = PetscStrncpy(filename,filebase,128);CHKERRQ(ierr); ierr = PetscStrncat(filename,"f",3);CHKERRQ(ierr); ierr = PetscViewerBinaryOpen(comm,filename,FILE_MODE_READ,&loader);CHKERRQ(ierr); ierr = VecCreate(comm,&user->d);CHKERRQ(ierr); ierr = VecLoad(user->d,loader);CHKERRQ(ierr); ierr = PetscViewerDestroy(&loader);CHKERRQ(ierr); ierr = VecGetSize(user->d,&nrows);CHKERRQ(ierr); ierr = VecSetFromOptions(user->d);CHKERRQ(ierr); user->n = nrows; ierr = PetscStrncpy(filename,filebase,128);CHKERRQ(ierr); ierr = PetscStrncat(filename,"H",3);CHKERRQ(ierr); ierr = PetscViewerBinaryOpen(comm,filename,FILE_MODE_READ,&loader);CHKERRQ(ierr); ierr = MatCreate(comm,&user->H);CHKERRQ(ierr); ierr = MatSetSizes(user->H,PETSC_DECIDE,PETSC_DECIDE,nrows,nrows);CHKERRQ(ierr); ierr = MatLoad(user->H,loader);CHKERRQ(ierr); ierr = PetscViewerDestroy(&loader);CHKERRQ(ierr); ierr = MatGetSize(user->H,&nrows,&ncols);CHKERRQ(ierr); if (nrows != user->n) SETERRQ(comm,0,"H: nrows != n\n"); if (ncols != user->n) SETERRQ(comm,0,"H: ncols != n\n"); ierr = MatSetFromOptions(user->H);CHKERRQ(ierr); ierr = PetscStrncpy(filename,filebase,128);CHKERRQ(ierr); ierr = PetscStrncat(filename,"Aeq",3);CHKERRQ(ierr); ierr = PetscViewerBinaryOpen(comm,filename,FILE_MODE_READ,&loader); if (ierr) { user->Aeq = NULL; user->me = 0; } else { ierr = MatCreate(comm,&user->Aeq);CHKERRQ(ierr); ierr = MatLoad(user->Aeq,loader);CHKERRQ(ierr); ierr = PetscViewerDestroy(&loader);CHKERRQ(ierr); ierr = MatGetSize(user->Aeq,&nrows,&ncols);CHKERRQ(ierr); if (ncols != user->n) SETERRQ(comm,0,"Aeq ncols != H nrows\n"); ierr = MatSetFromOptions(user->Aeq);CHKERRQ(ierr); user->me = nrows; } ierr = PetscStrncpy(filename,filebase,128);CHKERRQ(ierr); ierr = PetscStrncat(filename,"Beq",3);CHKERRQ(ierr); ierr = PetscViewerBinaryOpen(comm,filename,FILE_MODE_READ,&loader);CHKERRQ(ierr); if (ierr) { user->beq = 0; } else { ierr = VecCreate(comm,&user->beq);CHKERRQ(ierr); ierr = VecLoad(user->beq,loader);CHKERRQ(ierr); ierr = PetscViewerDestroy(&loader);CHKERRQ(ierr); ierr = VecGetSize(user->beq,&nrows);CHKERRQ(ierr); if (nrows != user->me) SETERRQ(comm,0,"Aeq nrows != Beq n\n"); ierr = VecSetFromOptions(user->beq);CHKERRQ(ierr); } user->mi = user->n; /* Ain = eye(n,n) */ ierr = MatCreate(comm,&user->Ain);CHKERRQ(ierr); ierr = MatSetType(user->Ain,MATAIJ);CHKERRQ(ierr); ierr = MatSetSizes(user->Ain,PETSC_DECIDE,PETSC_DECIDE,user->mi,user->mi);CHKERRQ(ierr); ierr = MatMPIAIJSetPreallocation(user->Ain,1,NULL,0,NULL);CHKERRQ(ierr); ierr = MatSeqAIJSetPreallocation(user->Ain,1,NULL);CHKERRQ(ierr); for (i=0;i<user->mi;i++) { ierr = MatSetValues(user->Ain,1,&i,1,&i,&one,INSERT_VALUES);CHKERRQ(ierr); } ierr = MatAssemblyBegin(user->Ain,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(user->Ain,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatSetFromOptions(user->Ain);CHKERRQ(ierr); /* bin = [0,0 ... 0]' */ ierr = VecCreate(comm,&user->bin);CHKERRQ(ierr); ierr = VecSetType(user->bin,VECMPI);CHKERRQ(ierr); ierr = VecSetSizes(user->bin,PETSC_DECIDE,user->mi);CHKERRQ(ierr); ierr = VecSet(user->bin,0.0);CHKERRQ(ierr); ierr = VecSetFromOptions(user->bin);CHKERRQ(ierr); user->m = user->me + user->mi; PetscFunctionReturn(0); }
int main(int argc,char **args) { Mat A,Asp; PetscViewer fd; /* viewer */ char file[PETSC_MAX_PATH_LEN]; /* input file name */ PetscErrorCode ierr; PetscInt m,n,rstart,rend; PetscBool flg; PetscInt row,ncols,j,nrows,nnzA=0,nnzAsp=0; const PetscInt *cols; const PetscScalar *vals; PetscReal norm,percent,val,dtol=1.e-16; PetscMPIInt rank; MatInfo matinfo; PetscInt Dnnz,Onnz; PetscInitialize(&argc,&args,(char *)0,help); ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); /* Determine files from which we read the linear systems. */ ierr = PetscOptionsGetString(PETSC_NULL,"-f",file,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr); if (!flg) SETERRQ(PETSC_COMM_WORLD,1,"Must indicate binary file with the -f option"); /* Open binary file. Note that we use FILE_MODE_READ to indicate reading from this file. */ ierr = PetscViewerBinaryOpen(PETSC_COMM_WORLD,file,FILE_MODE_READ,&fd);CHKERRQ(ierr); /* Load the matrix; then destroy the viewer. */ ierr = MatCreate(PETSC_COMM_WORLD,&A);CHKERRQ(ierr); ierr = MatSetOptionsPrefix(A,"a_");CHKERRQ(ierr); ierr = MatSetFromOptions(A);CHKERRQ(ierr); ierr = MatLoad(A,fd);CHKERRQ(ierr); ierr = PetscViewerDestroy(&fd);CHKERRQ(ierr); ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr); ierr = MatGetInfo(A,MAT_LOCAL,&matinfo);CHKERRQ(ierr); //printf("matinfo.nz_used %g\n",matinfo.nz_used); /* Get a sparse matrix Asp by dumping zero entries of A */ ierr = MatCreate(PETSC_COMM_WORLD,&Asp);CHKERRQ(ierr); ierr = MatSetSizes(Asp,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); ierr = MatSetOptionsPrefix(Asp,"asp_");CHKERRQ(ierr); ierr = MatSetFromOptions(Asp);CHKERRQ(ierr); Dnnz = (PetscInt)matinfo.nz_used/m + 1; Onnz = Dnnz/2; printf("Dnnz %d %d\n",Dnnz,Onnz); ierr = MatSeqAIJSetPreallocation(Asp,Dnnz,PETSC_NULL);CHKERRQ(ierr); ierr = MatMPIAIJSetPreallocation(Asp,Dnnz,PETSC_NULL,Onnz,PETSC_NULL);CHKERRQ(ierr); /* Check zero rows */ ierr = MatGetOwnershipRange(A,&rstart,&rend);CHKERRQ(ierr); nrows = 0; for (row=rstart; row<rend; row++){ ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr); nnzA += ncols; norm = 0.0; for (j=0; j<ncols; j++){ val = PetscAbsScalar(vals[j]); if (norm < val) norm = norm; if (val > dtol){ ierr = MatSetValues(Asp,1,&row,1,&cols[j],&vals[j],INSERT_VALUES);CHKERRQ(ierr); nnzAsp++; } } if (!norm) nrows++; ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr); } ierr = MatAssemblyBegin(Asp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(Asp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); percent=(PetscReal)nnzA*100/(m*n); ierr = PetscPrintf(PETSC_COMM_SELF," [%d] Matrix A local size %d,%d; nnzA %d, %g percent; No. of zero rows: %d\n",rank,m,n,nnzA,percent,nrows); percent=(PetscReal)nnzAsp*100/(m*n); ierr = PetscPrintf(PETSC_COMM_SELF," [%d] Matrix Asp nnzAsp %d, %g percent\n",rank,nnzAsp,percent); /* investigate matcoloring for Asp */ PetscBool Asp_coloring = PETSC_FALSE; ierr = PetscOptionsHasName(PETSC_NULL,"-Asp_color",&Asp_coloring);CHKERRQ(ierr); if (Asp_coloring){ ISColoring iscoloring; MatFDColoring matfdcoloring; ierr = PetscPrintf(PETSC_COMM_WORLD," Create coloring of Asp...\n"); ierr = MatGetColoring(Asp,MATCOLORINGSL,&iscoloring);CHKERRQ(ierr); ierr = MatFDColoringCreate(Asp,iscoloring,&matfdcoloring);CHKERRQ(ierr); ierr = MatFDColoringSetFromOptions(matfdcoloring);CHKERRQ(ierr); //ierr = MatFDColoringView(matfdcoloring,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr); ierr = MatFDColoringDestroy(&matfdcoloring);CHKERRQ(ierr); } /* Write Asp in binary for study - see ~petsc/src/mat/examples/tests/ex124.c */ PetscBool Asp_write = PETSC_FALSE; ierr = PetscOptionsHasName(PETSC_NULL,"-Asp_write",&Asp_write);CHKERRQ(ierr); if (Asp_write){ PetscViewer viewer; ierr = PetscPrintf(PETSC_COMM_SELF,"Write Asp into file Asp.dat ...\n"); ierr = PetscViewerBinaryOpen(PETSC_COMM_WORLD,"Asp.dat",FILE_MODE_WRITE,&viewer);CHKERRQ(ierr); ierr = MatView(Asp,viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); } ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = MatDestroy(&Asp);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
int main(int argc,char **args) { Vec x,y,u,s1,s2; Mat A,sA,sB; PetscRandom rctx; PetscReal r1,r2,rnorm,tol = PETSC_SQRT_MACHINE_EPSILON; PetscScalar one=1.0, neg_one=-1.0, value[3], four=4.0,alpha=0.1; PetscInt n,col[3],n1,block,row,i,j,i2,j2,Ii,J,rstart,rend,bs=1,mbs=16,d_nz=3,o_nz=3,prob=2; PetscErrorCode ierr; PetscMPIInt size,rank; PetscBool flg; MatType type; ierr = PetscInitialize(&argc,&args,(char*)0,help); if (ierr) return ierr; ierr = PetscOptionsGetInt(NULL,NULL,"-mbs",&mbs,NULL); CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,NULL,"-bs",&bs,NULL); CHKERRQ(ierr); ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); CHKERRQ(ierr); ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size); CHKERRQ(ierr); n = mbs*bs; /* Assemble MPISBAIJ matrix sA */ ierr = MatCreate(PETSC_COMM_WORLD,&sA); CHKERRQ(ierr); ierr = MatSetSizes(sA,PETSC_DECIDE,PETSC_DECIDE,n,n); CHKERRQ(ierr); ierr = MatSetType(sA,MATSBAIJ); CHKERRQ(ierr); ierr = MatSetFromOptions(sA); CHKERRQ(ierr); ierr = MatGetType(sA,&type); CHKERRQ(ierr); ierr = MatMPISBAIJSetPreallocation(sA,bs,d_nz,NULL,o_nz,NULL); CHKERRQ(ierr); ierr = MatSeqSBAIJSetPreallocation(sA,bs,d_nz,NULL); CHKERRQ(ierr); ierr = MatSetOption(sA,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE); CHKERRQ(ierr); if (bs == 1) { if (prob == 1) { /* tridiagonal matrix */ value[0] = -1.0; value[1] = 2.0; value[2] = -1.0; for (i=1; i<n-1; i++) { col[0] = i-1; col[1] = i; col[2] = i+1; ierr = MatSetValues(sA,1,&i,3,col,value,INSERT_VALUES); CHKERRQ(ierr); } i = n - 1; col[0]=0; col[1] = n - 2; col[2] = n - 1; value[0]= 0.1; value[1]=-1; value[2]=2; ierr = MatSetValues(sA,1,&i,3,col,value,INSERT_VALUES); CHKERRQ(ierr); i = 0; col[0] = 0; col[1] = 1; col[2]=n-1; value[0] = 2.0; value[1] = -1.0; value[2]=0.1; ierr = MatSetValues(sA,1,&i,3,col,value,INSERT_VALUES); CHKERRQ(ierr); } else if (prob ==2) { /* matrix for the five point stencil */ n1 = (int) PetscSqrtReal((PetscReal)n); if (n1*n1 != n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"n must be a perfect square of n1"); for (i=0; i<n1; i++) { for (j=0; j<n1; j++) { Ii = j + n1*i; if (i>0) { J = Ii - n1; ierr = MatSetValues(sA,1,&Ii,1,&J,&neg_one,INSERT_VALUES); CHKERRQ(ierr); } if (i<n1-1) { J = Ii + n1; ierr = MatSetValues(sA,1,&Ii,1,&J,&neg_one,INSERT_VALUES); CHKERRQ(ierr); } if (j>0) { J = Ii - 1; ierr = MatSetValues(sA,1,&Ii,1,&J,&neg_one,INSERT_VALUES); CHKERRQ(ierr); } if (j<n1-1) { J = Ii + 1; ierr = MatSetValues(sA,1,&Ii,1,&J,&neg_one,INSERT_VALUES); CHKERRQ(ierr); } ierr = MatSetValues(sA,1,&Ii,1,&Ii,&four,INSERT_VALUES); CHKERRQ(ierr); } } } /* end of if (bs == 1) */ } else { /* bs > 1 */ for (block=0; block<n/bs; block++) { /* diagonal blocks */ value[0] = -1.0; value[1] = 4.0; value[2] = -1.0; for (i=1+block*bs; i<bs-1+block*bs; i++) { col[0] = i-1; col[1] = i; col[2] = i+1; ierr = MatSetValues(sA,1,&i,3,col,value,INSERT_VALUES); CHKERRQ(ierr); } i = bs - 1+block*bs; col[0] = bs - 2+block*bs; col[1] = bs - 1+block*bs; value[0]=-1.0; value[1]=4.0; ierr = MatSetValues(sA,1,&i,2,col,value,INSERT_VALUES); CHKERRQ(ierr); i = 0+block*bs; col[0] = 0+block*bs; col[1] = 1+block*bs; value[0]=4.0; value[1] = -1.0; ierr = MatSetValues(sA,1,&i,2,col,value,INSERT_VALUES); CHKERRQ(ierr); } /* off-diagonal blocks */ value[0]=-1.0; for (i=0; i<(n/bs-1)*bs; i++) { col[0]=i+bs; ierr = MatSetValues(sA,1,&i,1,col,value,INSERT_VALUES); CHKERRQ(ierr); col[0]=i; row=i+bs; ierr = MatSetValues(sA,1,&row,1,col,value,INSERT_VALUES); CHKERRQ(ierr); } } ierr = MatAssemblyBegin(sA,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = MatAssemblyEnd(sA,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); /* Test MatView() */ ierr = MatCreateBAIJ(PETSC_COMM_WORLD,bs,PETSC_DECIDE,PETSC_DECIDE,n,n,d_nz,NULL,o_nz,NULL,&A); CHKERRQ(ierr); ierr = MatSetOption(A,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE); CHKERRQ(ierr); if (bs == 1) { if (prob == 1) { /* tridiagonal matrix */ value[0] = -1.0; value[1] = 2.0; value[2] = -1.0; for (i=1; i<n-1; i++) { col[0] = i-1; col[1] = i; col[2] = i+1; ierr = MatSetValues(A,1,&i,3,col,value,INSERT_VALUES); CHKERRQ(ierr); } i = n - 1; col[0]=0; col[1] = n - 2; col[2] = n - 1; value[0]= 0.1; value[1]=-1; value[2]=2; ierr = MatSetValues(A,1,&i,3,col,value,INSERT_VALUES); CHKERRQ(ierr); i = 0; col[0] = 0; col[1] = 1; col[2]=n-1; value[0] = 2.0; value[1] = -1.0; value[2]=0.1; ierr = MatSetValues(A,1,&i,3,col,value,INSERT_VALUES); CHKERRQ(ierr); } else if (prob ==2) { /* matrix for the five point stencil */ n1 = (int) PetscSqrtReal((PetscReal)n); for (i=0; i<n1; i++) { for (j=0; j<n1; j++) { Ii = j + n1*i; if (i>0) { J = Ii - n1; ierr = MatSetValues(A,1,&Ii,1,&J,&neg_one,INSERT_VALUES); CHKERRQ(ierr); } if (i<n1-1) { J = Ii + n1; ierr = MatSetValues(A,1,&Ii,1,&J,&neg_one,INSERT_VALUES); CHKERRQ(ierr); } if (j>0) { J = Ii - 1; ierr = MatSetValues(A,1,&Ii,1,&J,&neg_one,INSERT_VALUES); CHKERRQ(ierr); } if (j<n1-1) { J = Ii + 1; ierr = MatSetValues(A,1,&Ii,1,&J,&neg_one,INSERT_VALUES); CHKERRQ(ierr); } ierr = MatSetValues(A,1,&Ii,1,&Ii,&four,INSERT_VALUES); CHKERRQ(ierr); } } } /* end of if (bs == 1) */ } else { /* bs > 1 */ for (block=0; block<n/bs; block++) { /* diagonal blocks */ value[0] = -1.0; value[1] = 4.0; value[2] = -1.0; for (i=1+block*bs; i<bs-1+block*bs; i++) { col[0] = i-1; col[1] = i; col[2] = i+1; ierr = MatSetValues(A,1,&i,3,col,value,INSERT_VALUES); CHKERRQ(ierr); } i = bs - 1+block*bs; col[0] = bs - 2+block*bs; col[1] = bs - 1+block*bs; value[0]=-1.0; value[1]=4.0; ierr = MatSetValues(A,1,&i,2,col,value,INSERT_VALUES); CHKERRQ(ierr); i = 0+block*bs; col[0] = 0+block*bs; col[1] = 1+block*bs; value[0]=4.0; value[1] = -1.0; ierr = MatSetValues(A,1,&i,2,col,value,INSERT_VALUES); CHKERRQ(ierr); } /* off-diagonal blocks */ value[0]=-1.0; for (i=0; i<(n/bs-1)*bs; i++) { col[0]=i+bs; ierr = MatSetValues(A,1,&i,1,col,value,INSERT_VALUES); CHKERRQ(ierr); col[0]=i; row=i+bs; ierr = MatSetValues(A,1,&row,1,col,value,INSERT_VALUES); CHKERRQ(ierr); } } ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); /* Test MatGetSize(), MatGetLocalSize() */ ierr = MatGetSize(sA, &i,&j); CHKERRQ(ierr); ierr = MatGetSize(A, &i2,&j2); CHKERRQ(ierr); i -= i2; j -= j2; if (i || j) { ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD,"[%d], Error: MatGetSize()\n",rank); CHKERRQ(ierr); ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); CHKERRQ(ierr); } ierr = MatGetLocalSize(sA, &i,&j); CHKERRQ(ierr); ierr = MatGetLocalSize(A, &i2,&j2); CHKERRQ(ierr); i2 -= i; j2 -= j; if (i2 || j2) { ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD,"[%d], Error: MatGetLocalSize()\n",rank); CHKERRQ(ierr); ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); CHKERRQ(ierr); } /* vectors */ /*--------------------*/ /* i is obtained from MatGetLocalSize() */ ierr = VecCreate(PETSC_COMM_WORLD,&x); CHKERRQ(ierr); ierr = VecSetSizes(x,i,PETSC_DECIDE); CHKERRQ(ierr); ierr = VecSetFromOptions(x); CHKERRQ(ierr); ierr = VecDuplicate(x,&y); CHKERRQ(ierr); ierr = VecDuplicate(x,&u); CHKERRQ(ierr); ierr = VecDuplicate(x,&s1); CHKERRQ(ierr); ierr = VecDuplicate(x,&s2); CHKERRQ(ierr); ierr = PetscRandomCreate(PETSC_COMM_WORLD,&rctx); CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(rctx); CHKERRQ(ierr); ierr = VecSetRandom(x,rctx); CHKERRQ(ierr); ierr = VecSet(u,one); CHKERRQ(ierr); /* Test MatNorm() */ ierr = MatNorm(A,NORM_FROBENIUS,&r1); CHKERRQ(ierr); ierr = MatNorm(sA,NORM_FROBENIUS,&r2); CHKERRQ(ierr); rnorm = PetscAbsReal(r1-r2)/r2; if (rnorm > tol && !rank) { ierr = PetscPrintf(PETSC_COMM_SELF,"Error: MatNorm_FROBENIUS(), Anorm=%16.14e, sAnorm=%16.14e bs=%D\n",r1,r2,bs); CHKERRQ(ierr); } ierr = MatNorm(A,NORM_INFINITY,&r1); CHKERRQ(ierr); ierr = MatNorm(sA,NORM_INFINITY,&r2); CHKERRQ(ierr); rnorm = PetscAbsReal(r1-r2)/r2; if (rnorm > tol && !rank) { ierr = PetscPrintf(PETSC_COMM_WORLD,"Error: MatNorm_INFINITY(), Anorm=%16.14e, sAnorm=%16.14e bs=%D\n",r1,r2,bs); CHKERRQ(ierr); } ierr = MatNorm(A,NORM_1,&r1); CHKERRQ(ierr); ierr = MatNorm(sA,NORM_1,&r2); CHKERRQ(ierr); rnorm = PetscAbsReal(r1-r2)/r2; if (rnorm > tol && !rank) { ierr = PetscPrintf(PETSC_COMM_WORLD,"Error: MatNorm_1(), Anorm=%16.14e, sAnorm=%16.14e bs=%D\n",r1,r2,bs); CHKERRQ(ierr); } /* Test MatGetOwnershipRange() */ ierr = MatGetOwnershipRange(sA,&rstart,&rend); CHKERRQ(ierr); ierr = MatGetOwnershipRange(A,&i2,&j2); CHKERRQ(ierr); i2 -= rstart; j2 -= rend; if (i2 || j2) { ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD,"[%d], Error: MaGetOwnershipRange()\n",rank); CHKERRQ(ierr); ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); CHKERRQ(ierr); } /* Test MatDiagonalScale() */ ierr = MatDiagonalScale(A,x,x); CHKERRQ(ierr); ierr = MatDiagonalScale(sA,x,x); CHKERRQ(ierr); ierr = MatMultEqual(A,sA,10,&flg); CHKERRQ(ierr); if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMETYPE,"Error in MatDiagonalScale"); /* Test MatGetDiagonal(), MatScale() */ ierr = MatGetDiagonal(A,s1); CHKERRQ(ierr); ierr = MatGetDiagonal(sA,s2); CHKERRQ(ierr); ierr = VecNorm(s1,NORM_1,&r1); CHKERRQ(ierr); ierr = VecNorm(s2,NORM_1,&r2); CHKERRQ(ierr); r1 -= r2; if (r1<-tol || r1>tol) { ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD,"[%d], Error: MatDiagonalScale() or MatGetDiagonal(), r1=%g \n",rank,(double)r1); CHKERRQ(ierr); ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); CHKERRQ(ierr); } ierr = MatScale(A,alpha); CHKERRQ(ierr); ierr = MatScale(sA,alpha); CHKERRQ(ierr); /* Test MatGetRowMaxAbs() */ ierr = MatGetRowMaxAbs(A,s1,NULL); CHKERRQ(ierr); ierr = MatGetRowMaxAbs(sA,s2,NULL); CHKERRQ(ierr); ierr = VecNorm(s1,NORM_1,&r1); CHKERRQ(ierr); ierr = VecNorm(s2,NORM_1,&r2); CHKERRQ(ierr); r1 -= r2; if (r1<-tol || r1>tol) { ierr = PetscPrintf(PETSC_COMM_SELF,"Error: MatGetRowMaxAbs() \n"); CHKERRQ(ierr); } /* Test MatMult(), MatMultAdd() */ ierr = MatMultEqual(A,sA,10,&flg); CHKERRQ(ierr); if (!flg) { ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD,"[%d], Error: MatMult() or MatScale()\n",rank); CHKERRQ(ierr); ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); CHKERRQ(ierr); } ierr = MatMultAddEqual(A,sA,10,&flg); CHKERRQ(ierr); if (!flg) { ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD,"[%d], Error: MatMultAdd()\n",rank); CHKERRQ(ierr); ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); CHKERRQ(ierr); } /* Test MatMultTranspose(), MatMultTransposeAdd() */ for (i=0; i<10; i++) { ierr = VecSetRandom(x,rctx); CHKERRQ(ierr); ierr = MatMultTranspose(A,x,s1); CHKERRQ(ierr); ierr = MatMultTranspose(sA,x,s2); CHKERRQ(ierr); ierr = VecNorm(s1,NORM_1,&r1); CHKERRQ(ierr); ierr = VecNorm(s2,NORM_1,&r2); CHKERRQ(ierr); r1 -= r2; if (r1<-tol || r1>tol) { ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD,"[%d], Error: MatMult() or MatScale(), err=%g\n",rank,(double)r1); CHKERRQ(ierr); ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); CHKERRQ(ierr); } } for (i=0; i<10; i++) { ierr = VecSetRandom(x,rctx); CHKERRQ(ierr); ierr = VecSetRandom(y,rctx); CHKERRQ(ierr); ierr = MatMultTransposeAdd(A,x,y,s1); CHKERRQ(ierr); ierr = MatMultTransposeAdd(sA,x,y,s2); CHKERRQ(ierr); ierr = VecNorm(s1,NORM_1,&r1); CHKERRQ(ierr); ierr = VecNorm(s2,NORM_1,&r2); CHKERRQ(ierr); r1 -= r2; if (r1<-tol || r1>tol) { ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD,"[%d], Error: MatMultAdd(), err=%g \n",rank,(double)r1); CHKERRQ(ierr); ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); CHKERRQ(ierr); } } /* Test MatDuplicate() */ ierr = MatDuplicate(sA,MAT_COPY_VALUES,&sB); CHKERRQ(ierr); ierr = MatEqual(sA,sB,&flg); CHKERRQ(ierr); if (!flg) { ierr = PetscPrintf(PETSC_COMM_WORLD," Error in MatDuplicate(), sA != sB \n"); CHKERRQ(ierr); CHKERRQ(ierr); } ierr = MatMultEqual(sA,sB,5,&flg); CHKERRQ(ierr); if (!flg) { ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD,"[%d], Error: MatDuplicate() or MatMult()\n",rank); CHKERRQ(ierr); ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); CHKERRQ(ierr); } ierr = MatMultAddEqual(sA,sB,5,&flg); CHKERRQ(ierr); if (!flg) { ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD,"[%d], Error: MatDuplicate() or MatMultAdd(()\n",rank); CHKERRQ(ierr); ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); CHKERRQ(ierr); } ierr = MatDestroy(&sB); CHKERRQ(ierr); ierr = VecDestroy(&u); CHKERRQ(ierr); ierr = VecDestroy(&x); CHKERRQ(ierr); ierr = VecDestroy(&y); CHKERRQ(ierr); ierr = VecDestroy(&s1); CHKERRQ(ierr); ierr = VecDestroy(&s2); CHKERRQ(ierr); ierr = MatDestroy(&sA); CHKERRQ(ierr); ierr = MatDestroy(&A); CHKERRQ(ierr); ierr = PetscRandomDestroy(&rctx); CHKERRQ(ierr); ierr = PetscFinalize(); return ierr; }
/* Converts from a PETSc matrix to an SPAI matrix */ PetscErrorCode ConvertMatToMatrix(MPI_Comm comm, Mat A,Mat AT,matrix **B) { matrix *M; int i,j,col; int row_indx; int len,pe,local_indx,start_indx; int *mapping; PetscErrorCode ierr; const int *cols; const double *vals; int n,mnl,nnl,nz,rstart,rend; PetscMPIInt size,rank; struct compressed_lines *rows; PetscFunctionBegin; ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); ierr = MatGetSize(A,&n,&n);CHKERRQ(ierr); ierr = MatGetLocalSize(A,&mnl,&nnl);CHKERRQ(ierr); /* not sure why a barrier is required. commenting out ierr = MPI_Barrier(comm);CHKERRQ(ierr); */ M = new_matrix((SPAI_Comm)comm); M->n = n; M->bs = 1; M->max_block_size = 1; M->mnls = (int*)malloc(sizeof(int)*size); M->start_indices = (int*)malloc(sizeof(int)*size); M->pe = (int*)malloc(sizeof(int)*n); M->block_sizes = (int*)malloc(sizeof(int)*n); for (i=0; i<n; i++) M->block_sizes[i] = 1; ierr = MPI_Allgather(&mnl,1,MPI_INT,M->mnls,1,MPI_INT,comm);CHKERRQ(ierr); M->start_indices[0] = 0; for (i=1; i<size; i++) M->start_indices[i] = M->start_indices[i-1] + M->mnls[i-1]; M->mnl = M->mnls[M->myid]; M->my_start_index = M->start_indices[M->myid]; for (i=0; i<size; i++) { start_indx = M->start_indices[i]; for (j=0; j<M->mnls[i]; j++) M->pe[start_indx+j] = i; } if (AT) { M->lines = new_compressed_lines(M->mnls[rank],1);CHKERRQ(ierr); } else { M->lines = new_compressed_lines(M->mnls[rank],0);CHKERRQ(ierr); } rows = M->lines; /* Determine the mapping from global indices to pointers */ ierr = PetscMalloc1(M->n,&mapping);CHKERRQ(ierr); pe = 0; local_indx = 0; for (i=0; i<M->n; i++) { if (local_indx >= M->mnls[pe]) { pe++; local_indx = 0; } mapping[i] = local_indx + M->start_indices[pe]; local_indx++; } /*********************************************************/ /************** Set up the row structure *****************/ /*********************************************************/ ierr = MatGetOwnershipRange(A,&rstart,&rend);CHKERRQ(ierr); for (i=rstart; i<rend; i++) { row_indx = i - rstart; ierr = MatGetRow(A,i,&nz,&cols,&vals);CHKERRQ(ierr); /* allocate buffers */ rows->ptrs[row_indx] = (int*)malloc(nz*sizeof(int)); rows->A[row_indx] = (double*)malloc(nz*sizeof(double)); /* copy the matrix */ for (j=0; j<nz; j++) { col = cols[j]; len = rows->len[row_indx]++; rows->ptrs[row_indx][len] = mapping[col]; rows->A[row_indx][len] = vals[j]; } rows->slen[row_indx] = rows->len[row_indx]; ierr = MatRestoreRow(A,i,&nz,&cols,&vals);CHKERRQ(ierr); } /************************************************************/ /************** Set up the column structure *****************/ /*********************************************************/ if (AT) { for (i=rstart; i<rend; i++) { row_indx = i - rstart; ierr = MatGetRow(AT,i,&nz,&cols,&vals);CHKERRQ(ierr); /* allocate buffers */ rows->rptrs[row_indx] = (int*)malloc(nz*sizeof(int)); /* copy the matrix (i.e., the structure) */ for (j=0; j<nz; j++) { col = cols[j]; len = rows->rlen[row_indx]++; rows->rptrs[row_indx][len] = mapping[col]; } ierr = MatRestoreRow(AT,i,&nz,&cols,&vals);CHKERRQ(ierr); } } ierr = PetscFree(mapping);CHKERRQ(ierr); order_pointers(M); M->maxnz = calc_maxnz(M); *B = M; PetscFunctionReturn(0); }
PETSC_EXTERN void PETSC_STDCALL matgetsize_(Mat *mat,PetscInt *m,PetscInt *n, int *ierr ) { CHKFORTRANNULLINTEGER(m); CHKFORTRANNULLINTEGER(n); *ierr = MatGetSize(*mat,m,n); }
PETSC_INTERN PetscErrorCode MatReorderForNonzeroDiagonal_SeqAIJ(Mat mat,PetscReal abstol,IS ris,IS cis) { PetscErrorCode ierr; PetscInt prow,k,nz,n,repl,*j,*col,*row,m,*icol,nnz,*jj,kk; PetscScalar *v,*vv; PetscReal repla; IS icis; PetscFunctionBegin; /* access the indices of the IS directly, because it changes them */ row = ((IS_General*)ris->data)->idx; col = ((IS_General*)cis->data)->idx; ierr = ISInvertPermutation(cis,PETSC_DECIDE,&icis);CHKERRQ(ierr); icol = ((IS_General*)icis->data)->idx; ierr = MatGetSize(mat,&m,&n);CHKERRQ(ierr); for (prow=0; prow<n; prow++) { ierr = MatGetRow_SeqAIJ(mat,row[prow],&nz,&j,&v);CHKERRQ(ierr); for (k=0; k<nz; k++) { if (icol[j[k]] == prow) break; } if (k >= nz || PetscAbsScalar(v[k]) <= abstol) { /* Element too small or zero; find the best candidate */ repla = (k >= nz) ? 0.0 : PetscAbsScalar(v[k]); /* Look for a later column we can swap with this one */ for (k=0; k<nz; k++) { if (icol[j[k]] > prow && PetscAbsScalar(v[k]) > repla) { /* found a suitable later column */ repl = icol[j[k]]; SWAP(icol[col[prow]],icol[col[repl]]); SWAP(col[prow],col[repl]); goto found; } } /* Did not find a suitable later column so look for an earlier column We need to be sure that we don't introduce a zero in a previous diagonal */ for (k=0; k<nz; k++) { if (icol[j[k]] < prow && PetscAbsScalar(v[k]) > repla) { /* See if this one will work */ repl = icol[j[k]]; ierr = MatGetRow_SeqAIJ(mat,row[repl],&nnz,&jj,&vv);CHKERRQ(ierr); for (kk=0; kk<nnz; kk++) { if (icol[jj[kk]] == prow && PetscAbsScalar(vv[kk]) > abstol) { ierr = MatRestoreRow_SeqAIJ(mat,row[repl],&nnz,&jj,&vv);CHKERRQ(ierr); SWAP(icol[col[prow]],icol[col[repl]]); SWAP(col[prow],col[repl]); goto found; } } ierr = MatRestoreRow_SeqAIJ(mat,row[repl],&nnz,&jj,&vv);CHKERRQ(ierr); } } /* No column suitable; instead check all future rows Note: this will be very slow */ for (k=prow+1; k<n; k++) { ierr = MatGetRow_SeqAIJ(mat,row[k],&nnz,&jj,&vv);CHKERRQ(ierr); for (kk=0; kk<nnz; kk++) { if (icol[jj[kk]] == prow && PetscAbsScalar(vv[kk]) > abstol) { /* found a row */ SWAP(row[prow],row[k]); goto found; } } ierr = MatRestoreRow_SeqAIJ(mat,row[k],&nnz,&jj,&vv);CHKERRQ(ierr); } found:; } ierr = MatRestoreRow_SeqAIJ(mat,row[prow],&nz,&j,&v);CHKERRQ(ierr); } ierr = ISDestroy(&icis);CHKERRQ(ierr); PetscFunctionReturn(0); }
int main(int argc,char **args) { PetscMPIInt size; PetscErrorCode ierr; Vec x,y,b,s1,s2; Mat A; /* linear system matrix */ Mat sA,sB,sC; /* symmetric part of the matrices */ PetscInt n,mbs=16,bs=1,nz=3,prob=1,i,j,k1,k2,col[3],lf,block, row,Ii,J,n1,inc; PetscReal norm1,norm2,rnorm,tol=PETSC_SMALL; PetscScalar neg_one = -1.0,four=4.0,value[3]; IS perm, iscol; PetscRandom rdm; PetscBool doIcc=PETSC_TRUE,equal; MatInfo minfo1,minfo2; MatFactorInfo factinfo; MatType type; PetscInitialize(&argc,&args,(char*)0,help); ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); if (size != 1) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"This is a uniprocessor example only!"); ierr = PetscOptionsGetInt(NULL,"-bs",&bs,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-mbs",&mbs,NULL);CHKERRQ(ierr); n = mbs*bs; ierr = MatCreate(PETSC_COMM_SELF,&A);CHKERRQ(ierr); ierr = MatSetSizes(A,n,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); ierr = MatSetType(A,MATSEQBAIJ);CHKERRQ(ierr); ierr = MatSetFromOptions(A);CHKERRQ(ierr); ierr = MatSeqBAIJSetPreallocation(A,bs,nz,NULL);CHKERRQ(ierr); ierr = MatCreate(PETSC_COMM_SELF,&sA);CHKERRQ(ierr); ierr = MatSetSizes(sA,n,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); ierr = MatSetType(sA,MATSEQSBAIJ);CHKERRQ(ierr); ierr = MatSetFromOptions(sA);CHKERRQ(ierr); ierr = MatGetType(sA,&type);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)sA,MATSEQSBAIJ,&doIcc);CHKERRQ(ierr); ierr = MatSeqSBAIJSetPreallocation(sA,bs,nz,NULL);CHKERRQ(ierr); ierr = MatSetOption(sA,MAT_IGNORE_LOWER_TRIANGULAR,PETSC_TRUE);CHKERRQ(ierr); /* Test MatGetOwnershipRange() */ ierr = MatGetOwnershipRange(A,&Ii,&J);CHKERRQ(ierr); ierr = MatGetOwnershipRange(sA,&i,&j);CHKERRQ(ierr); if (i-Ii || j-J) { ierr = PetscPrintf(PETSC_COMM_SELF,"Error: MatGetOwnershipRange() in MatSBAIJ format\n");CHKERRQ(ierr); } /* Assemble matrix */ if (bs == 1) { ierr = PetscOptionsGetInt(NULL,"-test_problem",&prob,NULL);CHKERRQ(ierr); if (prob == 1) { /* tridiagonal matrix */ value[0] = -1.0; value[1] = 2.0; value[2] = -1.0; for (i=1; i<n-1; i++) { col[0] = i-1; col[1] = i; col[2] = i+1; ierr = MatSetValues(A,1,&i,3,col,value,INSERT_VALUES);CHKERRQ(ierr); ierr = MatSetValues(sA,1,&i,3,col,value,INSERT_VALUES);CHKERRQ(ierr); } i = n - 1; col[0]=0; col[1] = n - 2; col[2] = n - 1; value[0]= 0.1; value[1]=-1; value[2]=2; ierr = MatSetValues(A,1,&i,3,col,value,INSERT_VALUES);CHKERRQ(ierr); ierr = MatSetValues(sA,1,&i,3,col,value,INSERT_VALUES);CHKERRQ(ierr); i = 0; col[0] = n-1; col[1] = 1; col[2] = 0; value[0] = 0.1; value[1] = -1.0; value[2] = 2; ierr = MatSetValues(A,1,&i,3,col,value,INSERT_VALUES);CHKERRQ(ierr); ierr = MatSetValues(sA,1,&i,3,col,value,INSERT_VALUES);CHKERRQ(ierr); } else if (prob ==2) { /* matrix for the five point stencil */ n1 = (PetscInt) (PetscSqrtReal((PetscReal)n) + 0.001); if (n1*n1 - n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"sqrt(n) must be a positive interger!"); for (i=0; i<n1; i++) { for (j=0; j<n1; j++) { Ii = j + n1*i; if (i>0) { J = Ii - n1; ierr = MatSetValues(A,1,&Ii,1,&J,&neg_one,INSERT_VALUES);CHKERRQ(ierr); ierr = MatSetValues(sA,1,&Ii,1,&J,&neg_one,INSERT_VALUES);CHKERRQ(ierr); } if (i<n1-1) { J = Ii + n1; ierr = MatSetValues(A,1,&Ii,1,&J,&neg_one,INSERT_VALUES);CHKERRQ(ierr); ierr = MatSetValues(sA,1,&Ii,1,&J,&neg_one,INSERT_VALUES);CHKERRQ(ierr); } if (j>0) { J = Ii - 1; ierr = MatSetValues(A,1,&Ii,1,&J,&neg_one,INSERT_VALUES);CHKERRQ(ierr); ierr = MatSetValues(sA,1,&Ii,1,&J,&neg_one,INSERT_VALUES);CHKERRQ(ierr); } if (j<n1-1) { J = Ii + 1; ierr = MatSetValues(A,1,&Ii,1,&J,&neg_one,INSERT_VALUES);CHKERRQ(ierr); ierr = MatSetValues(sA,1,&Ii,1,&J,&neg_one,INSERT_VALUES);CHKERRQ(ierr); } ierr = MatSetValues(A,1,&Ii,1,&Ii,&four,INSERT_VALUES);CHKERRQ(ierr); ierr = MatSetValues(sA,1,&Ii,1,&Ii,&four,INSERT_VALUES);CHKERRQ(ierr); } } } } else { /* bs > 1 */ for (block=0; block<n/bs; block++) { /* diagonal blocks */ value[0] = -1.0; value[1] = 4.0; value[2] = -1.0; for (i=1+block*bs; i<bs-1+block*bs; i++) { col[0] = i-1; col[1] = i; col[2] = i+1; ierr = MatSetValues(A,1,&i,3,col,value,INSERT_VALUES);CHKERRQ(ierr); ierr = MatSetValues(sA,1,&i,3,col,value,INSERT_VALUES);CHKERRQ(ierr); } i = bs - 1+block*bs; col[0] = bs - 2+block*bs; col[1] = bs - 1+block*bs; value[0]=-1.0; value[1]=4.0; ierr = MatSetValues(A,1,&i,2,col,value,INSERT_VALUES);CHKERRQ(ierr); ierr = MatSetValues(sA,1,&i,2,col,value,INSERT_VALUES);CHKERRQ(ierr); i = 0+block*bs; col[0] = 0+block*bs; col[1] = 1+block*bs; value[0]=4.0; value[1] = -1.0; ierr = MatSetValues(A,1,&i,2,col,value,INSERT_VALUES);CHKERRQ(ierr); ierr = MatSetValues(sA,1,&i,2,col,value,INSERT_VALUES);CHKERRQ(ierr); } /* off-diagonal blocks */ value[0]=-1.0; for (i=0; i<(n/bs-1)*bs; i++) { col[0]=i+bs; ierr = MatSetValues(A,1,&i,1,col,value,INSERT_VALUES);CHKERRQ(ierr); ierr = MatSetValues(sA,1,&i,1,col,value,INSERT_VALUES);CHKERRQ(ierr); col[0]=i; row=i+bs; ierr = MatSetValues(A,1,&row,1,col,value,INSERT_VALUES);CHKERRQ(ierr); ierr = MatSetValues(sA,1,&row,1,col,value,INSERT_VALUES);CHKERRQ(ierr); } } ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyBegin(sA,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(sA,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* Test MatGetInfo() of A and sA */ ierr = MatGetInfo(A,MAT_LOCAL,&minfo1);CHKERRQ(ierr); ierr = MatGetInfo(sA,MAT_LOCAL,&minfo2);CHKERRQ(ierr); /* printf("A matrix nonzeros (BAIJ format) = %d, allocated nonzeros= %d\n", (int)minfo1.nz_used,(int)minfo1.nz_allocated); printf("sA matrix nonzeros(SBAIJ format) = %d, allocated nonzeros= %d\n", (int)minfo2.nz_used,(int)minfo2.nz_allocated); */ i = (int) (minfo1.nz_used - minfo2.nz_used); j = (int) (minfo1.nz_allocated - minfo2.nz_allocated); k1 = (int) (minfo1.nz_allocated - minfo1.nz_used); k2 = (int) (minfo2.nz_allocated - minfo2.nz_used); if (i < 0 || j < 0 || k1 < 0 || k2 < 0) { ierr = PetscPrintf(PETSC_COMM_SELF,"Error (compare A and sA): MatGetInfo()\n");CHKERRQ(ierr); } /* Test MatDuplicate() */ ierr = MatNorm(A,NORM_FROBENIUS,&norm1);CHKERRQ(ierr); ierr = MatDuplicate(sA,MAT_COPY_VALUES,&sB);CHKERRQ(ierr); ierr = MatEqual(sA,sB,&equal);CHKERRQ(ierr); if (!equal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMETYPE,"Error in MatDuplicate()"); /* Test MatNorm() */ ierr = MatNorm(A,NORM_FROBENIUS,&norm1);CHKERRQ(ierr); ierr = MatNorm(sB,NORM_FROBENIUS,&norm2);CHKERRQ(ierr); rnorm = PetscAbsReal(norm1-norm2)/norm2; if (rnorm > tol) { ierr = PetscPrintf(PETSC_COMM_SELF,"Error: MatNorm_FROBENIUS, NormA=%16.14e NormsB=%16.14e\n",norm1,norm2);CHKERRQ(ierr); } ierr = MatNorm(A,NORM_INFINITY,&norm1);CHKERRQ(ierr); ierr = MatNorm(sB,NORM_INFINITY,&norm2);CHKERRQ(ierr); rnorm = PetscAbsReal(norm1-norm2)/norm2; if (rnorm > tol) { ierr = PetscPrintf(PETSC_COMM_SELF,"Error: MatNorm_INFINITY(), NormA=%16.14e NormsB=%16.14e\n",norm1,norm2);CHKERRQ(ierr); } ierr = MatNorm(A,NORM_1,&norm1);CHKERRQ(ierr); ierr = MatNorm(sB,NORM_1,&norm2);CHKERRQ(ierr); rnorm = PetscAbsReal(norm1-norm2)/norm2; if (rnorm > tol) { ierr = PetscPrintf(PETSC_COMM_SELF,"Error: MatNorm_INFINITY(), NormA=%16.14e NormsB=%16.14e\n",norm1,norm2);CHKERRQ(ierr); } /* Test MatGetInfo(), MatGetSize(), MatGetBlockSize() */ ierr = MatGetInfo(A,MAT_LOCAL,&minfo1);CHKERRQ(ierr); ierr = MatGetInfo(sB,MAT_LOCAL,&minfo2);CHKERRQ(ierr); /* printf("matrix nonzeros (BAIJ format) = %d, allocated nonzeros= %d\n", (int)minfo1.nz_used,(int)minfo1.nz_allocated); printf("matrix nonzeros(SBAIJ format) = %d, allocated nonzeros= %d\n", (int)minfo2.nz_used,(int)minfo2.nz_allocated); */ i = (int) (minfo1.nz_used - minfo2.nz_used); j = (int) (minfo1.nz_allocated - minfo2.nz_allocated); k1 = (int) (minfo1.nz_allocated - minfo1.nz_used); k2 = (int) (minfo2.nz_allocated - minfo2.nz_used); if (i < 0 || j < 0 || k1 < 0 || k2 < 0) { ierr = PetscPrintf(PETSC_COMM_SELF,"Error(compare A and sB): MatGetInfo()\n");CHKERRQ(ierr); } ierr = MatGetSize(A,&Ii,&J);CHKERRQ(ierr); ierr = MatGetSize(sB,&i,&j);CHKERRQ(ierr); if (i-Ii || j-J) { PetscPrintf(PETSC_COMM_SELF,"Error: MatGetSize()\n");CHKERRQ(ierr); } ierr = MatGetBlockSize(A, &Ii);CHKERRQ(ierr); ierr = MatGetBlockSize(sB, &i);CHKERRQ(ierr); if (i-Ii) { ierr = PetscPrintf(PETSC_COMM_SELF,"Error: MatGetBlockSize()\n");CHKERRQ(ierr); } ierr = PetscRandomCreate(PETSC_COMM_SELF,&rdm);CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(rdm);CHKERRQ(ierr); ierr = VecCreateSeq(PETSC_COMM_SELF,n,&x);CHKERRQ(ierr); ierr = VecDuplicate(x,&s1);CHKERRQ(ierr); ierr = VecDuplicate(x,&s2);CHKERRQ(ierr); ierr = VecDuplicate(x,&y);CHKERRQ(ierr); ierr = VecDuplicate(x,&b);CHKERRQ(ierr); ierr = VecSetRandom(x,rdm);CHKERRQ(ierr); /* Test MatDiagonalScale(), MatGetDiagonal(), MatScale() */ #if !defined(PETSC_USE_COMPLEX) /* Scaling matrix with complex numbers results non-spd matrix, causing crash of MatForwardSolve() and MatBackwardSolve() */ ierr = MatDiagonalScale(A,x,x);CHKERRQ(ierr); ierr = MatDiagonalScale(sB,x,x);CHKERRQ(ierr); ierr = MatMultEqual(A,sB,10,&equal);CHKERRQ(ierr); if (!equal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMETYPE,"Error in MatDiagonalScale"); ierr = MatGetDiagonal(A,s1);CHKERRQ(ierr); ierr = MatGetDiagonal(sB,s2);CHKERRQ(ierr); ierr = VecAXPY(s2,neg_one,s1);CHKERRQ(ierr); ierr = VecNorm(s2,NORM_1,&norm1);CHKERRQ(ierr); if (norm1>tol) { ierr = PetscPrintf(PETSC_COMM_SELF,"Error:MatGetDiagonal(), ||s1-s2||=%G\n",norm1);CHKERRQ(ierr); } { PetscScalar alpha=0.1; ierr = MatScale(A,alpha);CHKERRQ(ierr); ierr = MatScale(sB,alpha);CHKERRQ(ierr); } #endif /* Test MatGetRowMaxAbs() */ ierr = MatGetRowMaxAbs(A,s1,NULL);CHKERRQ(ierr); ierr = MatGetRowMaxAbs(sB,s2,NULL);CHKERRQ(ierr); ierr = VecNorm(s1,NORM_1,&norm1);CHKERRQ(ierr); ierr = VecNorm(s2,NORM_1,&norm2);CHKERRQ(ierr); norm1 -= norm2; if (norm1<-tol || norm1>tol) { ierr = PetscPrintf(PETSC_COMM_SELF,"Error:MatGetRowMaxAbs() \n");CHKERRQ(ierr); } /* Test MatMult() */ for (i=0; i<40; i++) { ierr = VecSetRandom(x,rdm);CHKERRQ(ierr); ierr = MatMult(A,x,s1);CHKERRQ(ierr); ierr = MatMult(sB,x,s2);CHKERRQ(ierr); ierr = VecNorm(s1,NORM_1,&norm1);CHKERRQ(ierr); ierr = VecNorm(s2,NORM_1,&norm2);CHKERRQ(ierr); norm1 -= norm2; if (norm1<-tol || norm1>tol) { ierr = PetscPrintf(PETSC_COMM_SELF,"Error: MatMult(), norm1-norm2: %G\n",norm1);CHKERRQ(ierr); } } /* MatMultAdd() */ for (i=0; i<40; i++) { ierr = VecSetRandom(x,rdm);CHKERRQ(ierr); ierr = VecSetRandom(y,rdm);CHKERRQ(ierr); ierr = MatMultAdd(A,x,y,s1);CHKERRQ(ierr); ierr = MatMultAdd(sB,x,y,s2);CHKERRQ(ierr); ierr = VecNorm(s1,NORM_1,&norm1);CHKERRQ(ierr); ierr = VecNorm(s2,NORM_1,&norm2);CHKERRQ(ierr); norm1 -= norm2; if (norm1<-tol || norm1>tol) { ierr = PetscPrintf(PETSC_COMM_SELF,"Error:MatMultAdd(), norm1-norm2: %G\n",norm1);CHKERRQ(ierr); } } /* Test MatCholeskyFactor(), MatICCFactor() with natural ordering */ ierr = MatGetOrdering(A,MATORDERINGNATURAL,&perm,&iscol);CHKERRQ(ierr); ierr = ISDestroy(&iscol);CHKERRQ(ierr); norm1 = tol; inc = bs; /* initialize factinfo */ ierr = PetscMemzero(&factinfo,sizeof(MatFactorInfo));CHKERRQ(ierr); for (lf=-1; lf<10; lf += inc) { if (lf==-1) { /* Cholesky factor of sB (duplicate sA) */ factinfo.fill = 5.0; ierr = MatGetFactor(sB,MATSOLVERPETSC,MAT_FACTOR_CHOLESKY,&sC);CHKERRQ(ierr); ierr = MatCholeskyFactorSymbolic(sC,sB,perm,&factinfo);CHKERRQ(ierr); } else if (!doIcc) break; else { /* incomplete Cholesky factor */ factinfo.fill = 5.0; factinfo.levels = lf; ierr = MatGetFactor(sB,MATSOLVERPETSC,MAT_FACTOR_ICC,&sC);CHKERRQ(ierr); ierr = MatICCFactorSymbolic(sC,sB,perm,&factinfo);CHKERRQ(ierr); } ierr = MatCholeskyFactorNumeric(sC,sB,&factinfo);CHKERRQ(ierr); /* MatView(sC, PETSC_VIEWER_DRAW_WORLD); */ /* test MatGetDiagonal on numeric factor */ /* if (lf == -1) { ierr = MatGetDiagonal(sC,s1);CHKERRQ(ierr); printf(" in ex74.c, diag: \n"); ierr = VecView(s1,PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); } */ ierr = MatMult(sB,x,b);CHKERRQ(ierr); /* test MatForwardSolve() and MatBackwardSolve() */ if (lf == -1) { ierr = MatForwardSolve(sC,b,s1);CHKERRQ(ierr); ierr = MatBackwardSolve(sC,s1,s2);CHKERRQ(ierr); ierr = VecAXPY(s2,neg_one,x);CHKERRQ(ierr); ierr = VecNorm(s2,NORM_2,&norm2);CHKERRQ(ierr); if (10*norm1 < norm2) { ierr = PetscPrintf(PETSC_COMM_SELF,"MatForwardSolve and BackwardSolve: Norm of error=%G, bs=%d\n",norm2,bs);CHKERRQ(ierr); } } /* test MatSolve() */ ierr = MatSolve(sC,b,y);CHKERRQ(ierr); ierr = MatDestroy(&sC);CHKERRQ(ierr); /* Check the error */ ierr = VecAXPY(y,neg_one,x);CHKERRQ(ierr); ierr = VecNorm(y,NORM_2,&norm2);CHKERRQ(ierr); /* printf("lf: %d, error: %G\n", lf,norm2); */ if (10*norm1 < norm2 && lf-inc != -1) { ierr = PetscPrintf(PETSC_COMM_SELF,"lf=%D, %D, Norm of error=%G, %G\n",lf-inc,lf,norm1,norm2);CHKERRQ(ierr); } norm1 = norm2; if (norm2 < tol && lf != -1) break; } ierr = ISDestroy(&perm);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = MatDestroy(&sB);CHKERRQ(ierr); ierr = MatDestroy(&sA);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&y);CHKERRQ(ierr); ierr = VecDestroy(&s1);CHKERRQ(ierr); ierr = VecDestroy(&s2);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = PetscRandomDestroy(&rdm);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
PetscErrorCode PCGAMGFilterGraph(Mat *a_Gmat,const PetscReal vfilter,const PetscBool symm,const PetscInt verbose) { PetscErrorCode ierr; PetscInt Istart,Iend,Ii,jj,ncols,nnz0,nnz1, NN, MM, nloc; PetscMPIInt rank, size; Mat Gmat = *a_Gmat, tGmat, matTrans; MPI_Comm comm; const PetscScalar *vals; const PetscInt *idx; PetscInt *d_nnz, *o_nnz; Vec diag; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)Gmat,&comm);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); ierr = MatGetOwnershipRange(Gmat, &Istart, &Iend);CHKERRQ(ierr); nloc = Iend - Istart; ierr = MatGetSize(Gmat, &MM, &NN);CHKERRQ(ierr); #if defined PETSC_GAMG_USE_LOG ierr = PetscLogEventBegin(petsc_gamg_setup_events[GRAPH],0,0,0,0);CHKERRQ(ierr); #endif /* scale Gmat so filter works */ ierr = MatGetVecs(Gmat, &diag, 0);CHKERRQ(ierr); ierr = MatGetDiagonal(Gmat, diag);CHKERRQ(ierr); ierr = VecReciprocal(diag);CHKERRQ(ierr); ierr = VecSqrtAbs(diag);CHKERRQ(ierr); ierr = MatDiagonalScale(Gmat, diag, diag);CHKERRQ(ierr); ierr = VecDestroy(&diag);CHKERRQ(ierr); if (symm) { ierr = MatTranspose(Gmat, MAT_INITIAL_MATRIX, &matTrans);CHKERRQ(ierr); } /* filter - dup zeros out matrix */ ierr = PetscMalloc1(nloc, &d_nnz);CHKERRQ(ierr); ierr = PetscMalloc1(nloc, &o_nnz);CHKERRQ(ierr); for (Ii = Istart, jj = 0; Ii < Iend; Ii++, jj++) { ierr = MatGetRow(Gmat,Ii,&ncols,NULL,NULL);CHKERRQ(ierr); d_nnz[jj] = ncols; o_nnz[jj] = ncols; ierr = MatRestoreRow(Gmat,Ii,&ncols,NULL,NULL);CHKERRQ(ierr); if (symm) { ierr = MatGetRow(matTrans,Ii,&ncols,NULL,NULL);CHKERRQ(ierr); d_nnz[jj] += ncols; o_nnz[jj] += ncols; ierr = MatRestoreRow(matTrans,Ii,&ncols,NULL,NULL);CHKERRQ(ierr); } if (d_nnz[jj] > nloc) d_nnz[jj] = nloc; if (o_nnz[jj] > (MM-nloc)) o_nnz[jj] = MM - nloc; } ierr = MatCreateAIJ(comm, nloc, nloc, MM, MM, 0, d_nnz, 0, o_nnz, &tGmat);CHKERRQ(ierr); ierr = PetscFree(d_nnz);CHKERRQ(ierr); ierr = PetscFree(o_nnz);CHKERRQ(ierr); if (symm) { ierr = MatDestroy(&matTrans);CHKERRQ(ierr); } for (Ii = Istart, nnz0 = nnz1 = 0; Ii < Iend; Ii++) { ierr = MatGetRow(Gmat,Ii,&ncols,&idx,&vals);CHKERRQ(ierr); for (jj=0; jj<ncols; jj++,nnz0++) { PetscScalar sv = PetscAbs(PetscRealPart(vals[jj])); if (PetscRealPart(sv) > vfilter) { nnz1++; if (symm) { sv *= 0.5; ierr = MatSetValues(tGmat,1,&Ii,1,&idx[jj],&sv,ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValues(tGmat,1,&idx[jj],1,&Ii,&sv,ADD_VALUES);CHKERRQ(ierr); } else { ierr = MatSetValues(tGmat,1,&Ii,1,&idx[jj],&sv,ADD_VALUES);CHKERRQ(ierr); } } } ierr = MatRestoreRow(Gmat,Ii,&ncols,&idx,&vals);CHKERRQ(ierr); } ierr = MatAssemblyBegin(tGmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(tGmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); #if defined PETSC_GAMG_USE_LOG ierr = PetscLogEventEnd(petsc_gamg_setup_events[GRAPH],0,0,0,0);CHKERRQ(ierr); #endif if (verbose) { if (verbose == 1) { ierr = PetscPrintf(comm,"\t[%d]%s %g%% nnz after filtering, with threshold %g, %g nnz ave. (N=%d)\n",rank,__FUNCT__, 100.*(double)nnz1/(double)nnz0,vfilter,(double)nnz0/(double)nloc,MM);CHKERRQ(ierr); } else { PetscInt nnz[2],out[2]; nnz[0] = nnz0; nnz[1] = nnz1; ierr = MPI_Allreduce(nnz, out, 2, MPIU_INT, MPI_SUM, comm);CHKERRQ(ierr); ierr = PetscPrintf(comm,"\t[%d]%s %g%% nnz after filtering, with threshold %g, %g nnz ave. (N=%d)\n",rank,__FUNCT__, 100.*(double)out[1]/(double)out[0],vfilter,(double)out[0]/(double)MM,MM);CHKERRQ(ierr); } } ierr = MatDestroy(&Gmat);CHKERRQ(ierr); *a_Gmat = tGmat; PetscFunctionReturn(0); }
static PetscErrorCode MatPartitioningApply_Party(MatPartitioning part, IS * partitioning) { PetscErrorCode ierr; int *locals, *parttab = NULL, rank, size; Mat mat = part->adj, matMPI, matSeq; int nb_locals; Mat_MPIAdj *adj = (Mat_MPIAdj *) mat->data; MatPartitioning_Party *party = (MatPartitioning_Party *) part->data; PetscTruth flg; #ifdef PETSC_HAVE_UNISTD_H int fd_stdout, fd_pipe[2], count,err; #endif PetscFunctionBegin; /* check if the matrix is sequential, use MatGetSubMatrices if necessary */ ierr = PetscTypeCompare((PetscObject) mat, MATMPIADJ, &flg);CHKERRQ(ierr); ierr = MPI_Comm_size(((PetscObject)mat)->comm, &size);CHKERRQ(ierr); ierr = MPI_Comm_rank(((PetscObject)part)->comm, &rank);CHKERRQ(ierr); if (size > 1) { int M, N; IS isrow, iscol; Mat *A; if (flg) SETERRQ(PETSC_ERR_SUP,"Distributed matrix format MPIAdj is not supported for sequential partitioners"); ierr = PetscPrintf(((PetscObject)part)->comm,"Converting distributed matrix to sequential: this could be a performance loss\n");CHKERRQ(ierr); ierr = MatGetSize(mat, &M, &N);CHKERRQ(ierr); ierr = ISCreateStride(PETSC_COMM_SELF, M, 0, 1, &isrow);CHKERRQ(ierr); ierr = ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol);CHKERRQ(ierr); ierr = MatGetSubMatrices(mat, 1, &isrow, &iscol, MAT_INITIAL_MATRIX, &A);CHKERRQ(ierr); ierr = ISDestroy(isrow);CHKERRQ(ierr); ierr = ISDestroy(iscol);CHKERRQ(ierr); matSeq = *A; ierr = PetscFree(A);CHKERRQ(ierr); } else { matSeq = mat; } /* check for the input format that is supported only for a MPIADJ type and set it to matMPI */ if (!flg) { ierr = MatConvert(matSeq, MATMPIADJ, MAT_INITIAL_MATRIX, &matMPI);CHKERRQ(ierr); } else { matMPI = matSeq; } adj = (Mat_MPIAdj *) matMPI->data; /* finaly adj contains adjacency graph */ { /* Party library arguments definition */ int n = mat->rmap->N; /* number of vertices in full graph */ int *edge_p = adj->i; /* start of edge list for each vertex */ int *edge = adj->j; /* edge list data */ int *vertex_w = NULL; /* weights for all vertices */ int *edge_w = NULL; /* weights for all edges */ float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ int p = part->n; /* number of parts to create */ int *part_party; /* set number of each vtx (length n) */ int cutsize; /* number of edge cut */ char *global = party->global_method; /* global partitioning algorithm */ char *local = party->local_method; /* local partitioning algorithm */ int redl = party->nbvtxcoarsed; /* how many vertices to coarsen down to? */ char *redm = party->redm; char *redo = party->redo; int rec = party->rec; int output = party->output; ierr = PetscMalloc((mat->rmap->N) * sizeof(int), &part_party);CHKERRQ(ierr); /* redirect output to buffer party->mesg_log */ #ifdef PETSC_HAVE_UNISTD_H fd_stdout = dup(1); pipe(fd_pipe); close(1); dup2(fd_pipe[1], 1); ierr = PetscMalloc(SIZE_LOG * sizeof(char), &(party->mesg_log));CHKERRQ(ierr); #endif /* library call */ party_lib_times_start(); ierr = party_lib(n, vertex_w, x, y, z, edge_p, edge, edge_w, p, part_party, &cutsize, redl, redm, redo, global, local, rec, output); party_lib_times_output(output); part_info(n, vertex_w, edge_p, edge, edge_w, p, part_party, output); #ifdef PETSC_HAVE_UNISTD_H err = fflush(stdout); if (err) SETERRQ(PETSC_ERR_SYS,"fflush() failed on stdout"); count = read(fd_pipe[0], party->mesg_log, (SIZE_LOG - 1) * sizeof(char)); if (count < 0) count = 0; party->mesg_log[count] = 0; close(1); dup2(fd_stdout, 1); close(fd_stdout); close(fd_pipe[0]); close(fd_pipe[1]); #endif /* if in the call we got an error, we say it */ if (ierr) SETERRQ(PETSC_ERR_LIB, party->mesg_log); parttab = part_party; } /* Creation of the index set */ ierr = MPI_Comm_rank(((PetscObject)part)->comm, &rank);CHKERRQ(ierr); ierr = MPI_Comm_size(((PetscObject)part)->comm, &size);CHKERRQ(ierr); nb_locals = mat->rmap->N / size; locals = parttab + rank * nb_locals; if (rank < mat->rmap->N % size) { nb_locals++; locals += rank; } else { locals += mat->rmap->N % size; } ierr = ISCreateGeneral(((PetscObject)part)->comm, nb_locals, locals, partitioning);CHKERRQ(ierr); /* destroying old objects */ ierr = PetscFree(parttab);CHKERRQ(ierr); if (matSeq != mat) { ierr = MatDestroy(matSeq);CHKERRQ(ierr); } if (matMPI != mat) { ierr = MatDestroy(matMPI);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode PCGAMGCreateGraph(const Mat Amat, Mat *a_Gmat) { PetscErrorCode ierr; PetscInt Istart,Iend,Ii,jj,kk,ncols,nloc,NN,MM,bs; PetscMPIInt rank, size; MPI_Comm comm; Mat Gmat; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)Amat,&comm);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); ierr = MatGetOwnershipRange(Amat, &Istart, &Iend);CHKERRQ(ierr); ierr = MatGetSize(Amat, &MM, &NN);CHKERRQ(ierr); ierr = MatGetBlockSize(Amat, &bs);CHKERRQ(ierr); nloc = (Iend-Istart)/bs; #if defined PETSC_GAMG_USE_LOG ierr = PetscLogEventBegin(petsc_gamg_setup_events[GRAPH],0,0,0,0);CHKERRQ(ierr); #endif if (bs > 1) { const PetscScalar *vals; const PetscInt *idx; PetscInt *d_nnz, *o_nnz; /* count nnz, there is sparcity in here so this might not be enough */ ierr = PetscMalloc1(nloc, &d_nnz);CHKERRQ(ierr); ierr = PetscMalloc1(nloc, &o_nnz);CHKERRQ(ierr); for (Ii = Istart, jj = 0; Ii < Iend; Ii += bs, jj++) { d_nnz[jj] = 0; for (kk=0; kk<bs; kk++) { ierr = MatGetRow(Amat,Ii+kk,&ncols,0,0);CHKERRQ(ierr); if (ncols > d_nnz[jj]) { d_nnz[jj] = ncols; /* very pessimistic but could be too low in theory */ o_nnz[jj] = ncols; if (d_nnz[jj] > nloc) d_nnz[jj] = nloc; if (o_nnz[jj] > (NN/bs-nloc)) o_nnz[jj] = NN/bs-nloc; } ierr = MatRestoreRow(Amat,Ii+kk,&ncols,0,0);CHKERRQ(ierr); } } /* get scalar copy (norms) of matrix -- AIJ specific!!! */ ierr = MatCreateAIJ(comm, nloc, nloc, PETSC_DETERMINE, PETSC_DETERMINE,0, d_nnz, 0, o_nnz, &Gmat);CHKERRQ(ierr); ierr = PetscFree(d_nnz);CHKERRQ(ierr); ierr = PetscFree(o_nnz);CHKERRQ(ierr); for (Ii = Istart; Ii < Iend; Ii++) { PetscInt dest_row = Ii/bs; ierr = MatGetRow(Amat,Ii,&ncols,&idx,&vals);CHKERRQ(ierr); for (jj=0; jj<ncols; jj++) { PetscInt dest_col = idx[jj]/bs; PetscScalar sv = PetscAbs(PetscRealPart(vals[jj])); ierr = MatSetValues(Gmat,1,&dest_row,1,&dest_col,&sv,ADD_VALUES);CHKERRQ(ierr); } ierr = MatRestoreRow(Amat,Ii,&ncols,&idx,&vals);CHKERRQ(ierr); } ierr = MatAssemblyBegin(Gmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(Gmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); } else { /* just copy scalar matrix - abs() not taken here but scaled later */ ierr = MatDuplicate(Amat, MAT_COPY_VALUES, &Gmat);CHKERRQ(ierr); } #if defined PETSC_GAMG_USE_LOG ierr = PetscLogEventEnd(petsc_gamg_setup_events[GRAPH],0,0,0,0);CHKERRQ(ierr); #endif *a_Gmat = Gmat; PetscFunctionReturn(0); }