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; }
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; }
PETSC_EXTERN void PETSC_STDCALL matgetrowmaxabs_(Mat *mat,Vec *v,PetscInt idx[], int *ierr ) { CHKFORTRANNULLINTEGER(idx); *ierr = MatGetRowMaxAbs(*mat,*v,idx); }
static PetscErrorCode PCSetUp_Jacobi(PC pc) { PC_Jacobi *jac = (PC_Jacobi*)pc->data; Vec diag,diagsqrt; PetscErrorCode ierr; PetscInt n,i; PetscScalar *x; PetscBool zeroflag = PETSC_FALSE; PetscFunctionBegin; /* For most preconditioners the code would begin here something like if (pc->setupcalled == 0) { allocate space the first time this is ever called ierr = MatCreateVecs(pc->mat,&jac->diag);CHKERRQ(ierr); PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->diag); } But for this preconditioner we want to support use of both the matrix' diagonal elements (for left or right preconditioning) and square root of diagonal elements (for symmetric preconditioning). Hence we do not allocate space here, since we don't know at this point which will be needed (diag and/or diagsqrt) until the user applies the preconditioner, and we don't want to allocate BOTH unless we need them both. Thus, the diag and diagsqrt are allocated in PCSetUp_Jacobi_NonSymmetric() and PCSetUp_Jacobi_Symmetric(), respectively. */ /* Here we set up the preconditioner; that is, we copy the diagonal values from the matrix and put them into a format to make them quick to apply as a preconditioner. */ diag = jac->diag; diagsqrt = jac->diagsqrt; if (diag) { if (jac->userowmax) { ierr = MatGetRowMaxAbs(pc->pmat,diag,NULL);CHKERRQ(ierr); } else if (jac->userowsum) { ierr = MatGetRowSum(pc->pmat,diag);CHKERRQ(ierr); } else { ierr = MatGetDiagonal(pc->pmat,diag);CHKERRQ(ierr); } ierr = VecReciprocal(diag);CHKERRQ(ierr); ierr = VecGetLocalSize(diag,&n);CHKERRQ(ierr); ierr = VecGetArray(diag,&x);CHKERRQ(ierr); if (jac->useabs) { for (i=0; i<n; i++) x[i] = PetscAbsScalar(x[i]); } for (i=0; i<n; i++) { if (x[i] == 0.0) { x[i] = 1.0; zeroflag = PETSC_TRUE; } } ierr = VecRestoreArray(diag,&x);CHKERRQ(ierr); } if (diagsqrt) { if (jac->userowmax) { ierr = MatGetRowMaxAbs(pc->pmat,diagsqrt,NULL);CHKERRQ(ierr); } else if (jac->userowsum) { ierr = MatGetRowSum(pc->pmat,diagsqrt);CHKERRQ(ierr); } else { ierr = MatGetDiagonal(pc->pmat,diagsqrt);CHKERRQ(ierr); } ierr = VecGetLocalSize(diagsqrt,&n);CHKERRQ(ierr); ierr = VecGetArray(diagsqrt,&x);CHKERRQ(ierr); for (i=0; i<n; i++) { if (x[i] != 0.0) x[i] = 1.0/PetscSqrtReal(PetscAbsScalar(x[i])); else { x[i] = 1.0; zeroflag = PETSC_TRUE; } } ierr = VecRestoreArray(diagsqrt,&x);CHKERRQ(ierr); } if (zeroflag) { ierr = PetscInfo(pc,"Zero detected in diagonal of matrix, using 1 at those locations\n");CHKERRQ(ierr); } PetscFunctionReturn(0); }
EXTERN_C_END /* -------------------------------------------------------------------------- */ /* PCSetUp_Jacobi - Prepares for the use of the Jacobi preconditioner by setting data structures and options. Input Parameter: . pc - the preconditioner context Application Interface Routine: PCSetUp() Notes: The interface routine PCSetUp() is not usually called directly by the user, but instead is called by PCApply() if necessary. */ #undef __FUNCT__ #define __FUNCT__ "PCSetUp_Jacobi" static PetscErrorCode PCSetUp_Jacobi(PC pc) { PC_Jacobi *jac = (PC_Jacobi*)pc->data; Vec diag,diagsqrt; PetscErrorCode ierr; PetscInt n,i; PetscScalar *x; PetscBool zeroflag = PETSC_FALSE; PetscFunctionBegin; /* For most preconditioners the code would begin here something like if (pc->setupcalled == 0) { allocate space the first time this is ever called ierr = MatGetVecs(pc->mat,&jac->diag);CHKERRQ(ierr); PetscLogObjectParent(pc,jac->diag); } But for this preconditioner we want to support use of both the matrix' diagonal elements (for left or right preconditioning) and square root of diagonal elements (for symmetric preconditioning). Hence we do not allocate space here, since we don't know at this point which will be needed (diag and/or diagsqrt) until the user applies the preconditioner, and we don't want to allocate BOTH unless we need them both. Thus, the diag and diagsqrt are allocated in PCSetUp_Jacobi_NonSymmetric() and PCSetUp_Jacobi_Symmetric(), respectively. */ /* Here we set up the preconditioner; that is, we copy the diagonal values from the matrix and put them into a format to make them quick to apply as a preconditioner. */ diag = jac->diag; diagsqrt = jac->diagsqrt; if (diag) { if (jac->userowmax) { ierr = MatGetRowMaxAbs(pc->pmat,diag,PETSC_NULL);CHKERRQ(ierr); } else if (jac->userowsum) { ierr = MatGetRowSum(pc->pmat,diag);CHKERRQ(ierr); } else { ierr = MatGetDiagonal(pc->pmat,diag);CHKERRQ(ierr); } ierr = VecReciprocal(diag);CHKERRQ(ierr); ierr = VecGetLocalSize(diag,&n);CHKERRQ(ierr); ierr = VecGetArray(diag,&x);CHKERRQ(ierr); if (jac->useabs) { for (i=0; i<n; i++) { x[i] = PetscAbsScalar(x[i]); } } for (i=0; i<n; i++) { if (x[i] == 0.0) { x[i] = 1.0; zeroflag = PETSC_TRUE; } } ierr = VecRestoreArray(diag,&x);CHKERRQ(ierr); } if (diagsqrt) { if (jac->userowmax) { ierr = MatGetRowMaxAbs(pc->pmat,diagsqrt,PETSC_NULL);CHKERRQ(ierr); } else if (jac->userowsum) { ierr = MatGetRowSum(pc->pmat,diagsqrt);CHKERRQ(ierr); } else { ierr = MatGetDiagonal(pc->pmat,diagsqrt);CHKERRQ(ierr); } ierr = VecGetLocalSize(diagsqrt,&n);CHKERRQ(ierr); ierr = VecGetArray(diagsqrt,&x);CHKERRQ(ierr); for (i=0; i<n; i++) { if (x[i] != 0.0) x[i] = 1.0/PetscSqrtReal(PetscAbsScalar(x[i])); else { x[i] = 1.0; zeroflag = PETSC_TRUE; } } ierr = VecRestoreArray(diagsqrt,&x);CHKERRQ(ierr); } if (zeroflag) { ierr = PetscInfo(pc,"Zero detected in diagonal of matrix, using 1 at those locations\n");CHKERRQ(ierr); } PetscFunctionReturn(0); }
PETSC_EXTERN PetscErrorCode MatGetOrdering_AWBM(Mat A, MatOrderingType type, IS *permR, IS *permC) { Vec *scalR, *scalC, scalRVec, scalCVec; scalR = &scalRVec; scalC = &scalCVec; /* EVERYTHING IS WRITTEN AS IF THE MATRIX WERE COLUMN-MAJOR */ Mat_SeqAIJ *aij = (Mat_SeqAIJ *) A->data; PetscInt n = A->rmap->n; /* Number of local columns */ PetscInt m = A->cmap->n; /* Number of local rows */ PetscInt *match; /* The row matched to each column, and inverse column permutation */ PetscInt *matchR; /* The column matched to each row */ PetscInt *p; /* The column permutation */ const PetscInt *ia = aij->i; const PetscInt *ja = aij->j; const MatScalar *a = aij->a; Vec colMax; PetscScalar *a_j, *sr, *sc; PetscReal *weights /* c_ij */, *u /* u_i */, *v /* v_j */, eps = PETSC_SQRT_MACHINE_EPSILON; PetscInt debug = 0, r, c, r1, c1; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscOptionsGetInt(NULL, "-debug", &debug, NULL);CHKERRQ(ierr); ierr = MatGetVecs(A, NULL, &colMax);CHKERRQ(ierr); ierr = MatGetRowMaxAbs(A, colMax, NULL);CHKERRQ(ierr); ierr = PetscMalloc2(n, &match, m, &matchR);CHKERRQ(ierr); ierr = PetscMalloc1(n, &p);CHKERRQ(ierr); ierr = PetscCalloc3(m, &u, n, &v, ia[n], &weights);CHKERRQ(ierr); for (c = 0; c < n; ++c) match[c] = -1; /* Compute weights */ ierr = VecGetArray(colMax, &a_j);CHKERRQ(ierr); for (c = 0; c < n; ++c) { for (r = ia[c]; r < ia[c+1]; ++r) { PetscReal ar = PetscAbsScalar(a[r]); if (ar == 0.0) weights[r] = PETSC_MAX_REAL; else weights[r] = log(a_j[c]/ar); } } /* Compute local row weights */ for (r = 0; r < m; ++r) u[r] = PETSC_MAX_REAL; for (c = 0; c < n; ++c) { for (r = ia[c]; r < ia[c+1]; ++r) { u[ja[r]] = PetscMin(u[ja[r]], weights[r]); } } /* Compute local column weights */ for (c = 0; c < n; ++c) { v[c] = PETSC_MAX_REAL; for (r = ia[c]; r < ia[c+1]; ++r) { v[c] = PetscMin(v[c], weights[r] - u[ja[r]]); } } for (r = 0; r < m; ++r) matchR[r] = -1; /* Match columns */ ierr = CheckUnmatched(n, match, matchR);CHKERRQ(ierr); for (c = 0; c < n; ++c) { /* if (match[c] >= 0) continue; */ if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "Row %d\n Weights:", c);CHKERRQ(ierr);} for (r = ia[c]; r < ia[c+1]; ++r) { PetscReal weight = weights[r] - u[ja[r]] - v[c]; if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " %g", weight);CHKERRQ(ierr);} if ((weight <= eps) && (matchR[ja[r]] < 0)) { if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "Matched %d -- %d\n", c, ja[r]);CHKERRQ(ierr);} match[c] = ja[r]; matchR[ja[r]] = c; break; } } if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);} } /* Deal with unmatched columns */ ierr = CheckUnmatched(n, match, matchR);CHKERRQ(ierr); for (c = 0; c < n; ++c) { if (match[c] >= 0) continue; for (r = ia[c]; r < ia[c+1]; ++r) { PetscReal weight = weights[r] - u[ja[r]] - v[c]; if (weight > eps) continue; /* \bar c_ij = 0 and (r, j1) \in M */ c1 = matchR[ja[r]]; for (r1 = ia[c1]; r1 < ia[c1+1]; ++r1) { PetscReal weight1 = weights[r1] - u[ja[r1]] - v[c1]; if ((matchR[ja[r1]] < 0) && (weight1 <= eps)) { /* (r, c1) in M is replaced by (r, c) and (r1, c1) */ if (debug) { ierr = PetscPrintf(PETSC_COMM_SELF, "Replaced match %d -- %d\n", c1, ja[r]);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_SELF, " Added match %d -- %d\n", c, ja[r]);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_SELF, " Added match %d -- %d\n", c1, ja[r1]);CHKERRQ(ierr); } match[c] = ja[r]; matchR[ja[r]] = c; match[c1] = ja[r1]; matchR[ja[r1]] = c1; break; } } if (match[c] >= 0) break; } } /* Allow matching with non-optimal rows */ ierr = CheckUnmatched(n, match, matchR);CHKERRQ(ierr); for (c = 0; c < n; ++c) { if (match[c] >= 0) continue; for (r = ia[c]; r < ia[c+1]; ++r) { if (matchR[ja[r]] < 0) { if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "Matched non-opt %d -- %d\n", c, ja[r]);CHKERRQ(ierr);} match[c] = ja[r]; matchR[ja[r]] = c; break; } } } /* Deal with non-optimal unmatched columns */ ierr = CheckUnmatched(n, match, matchR);CHKERRQ(ierr); for (c = 0; c < n; ++c) { if (match[c] >= 0) continue; for (r = ia[c]; r < ia[c+1]; ++r) { /* \bar c_ij = 0 and (r, j1) \in M */ c1 = matchR[ja[r]]; for (r1 = ia[c1]; r1 < ia[c1+1]; ++r1) { if (matchR[ja[r1]] < 0) { /* (r, c1) in M is replaced by (r, c) and (r1, c1) */ if (debug) { ierr = PetscPrintf(PETSC_COMM_SELF, "Replaced match %d -- %d\n", c1, ja[r]);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_SELF, " Added match %d -- %d\n", c, ja[r]);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_SELF, " Added match %d -- %d\n", c1, ja[r1]);CHKERRQ(ierr); } match[c] = ja[r]; matchR[ja[r]] = c; match[c1] = ja[r1]; matchR[ja[r1]] = c1; break; } } if (match[c] >= 0) break; } } /* Complete matching */ ierr = CheckUnmatched(n, match, matchR);CHKERRQ(ierr); for (c = 0, r = 0; c < n; ++c) { if (match[c] >= n) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Column %d matched to invalid row %d", c, match[c]); if (match[c] < 0) { for (; r < n; ++r) { if (matchR[r] < 0) { if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "Matched default %d -- %d\n", c, r);CHKERRQ(ierr);} match[c] = r; matchR[r] = c; break; } } } } /* Check matching */ ierr = CheckUnmatched(n, match, matchR);CHKERRQ(ierr); for (c = 0; c < n; ++c) { if (match[c] < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Column %d unmatched", c); if (match[c] >= n) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Column %d matched to invalid row %d", c, match[c]); } /* Make permutation */ for (c = 0; c < n; ++c) {p[match[c]] = c;} ierr = ISCreateGeneral(PETSC_COMM_SELF, n, p, PETSC_OWN_POINTER, permR);CHKERRQ(ierr); ierr = ISSetPermutation(*permR);CHKERRQ(ierr); ierr = ISCreateStride(PETSC_COMM_SELF, n, 0, 1, permC);CHKERRQ(ierr); ierr = ISSetPermutation(*permC);CHKERRQ(ierr); ierr = PetscFree2(match, matchR);CHKERRQ(ierr); /* Make scaling */ ierr = VecCreateSeq(PETSC_COMM_SELF, n, scalR);CHKERRQ(ierr); ierr = VecCreateSeq(PETSC_COMM_SELF, n, scalC);CHKERRQ(ierr); ierr = VecGetArray(*scalR, &sr);CHKERRQ(ierr); ierr = VecGetArray(*scalC, &sc);CHKERRQ(ierr); for (c = 0; c < n; ++c) { sr[c] = PetscExpReal(v[c])/a_j[c]; sc[c] = PetscExpReal(u[c]); } ierr = VecRestoreArray(*scalR, &sr);CHKERRQ(ierr); ierr = VecRestoreArray(*scalC, &sc);CHKERRQ(ierr); ierr = VecRestoreArray(colMax, &a_j);CHKERRQ(ierr); ierr = VecDestroy(&colMax);CHKERRQ(ierr); ierr = PetscFree3(u,v,weights);CHKERRQ(ierr); ierr = VecDestroy(scalR);CHKERRQ(ierr); ierr = VecDestroy(scalC);CHKERRQ(ierr); PetscFunctionReturn(0); }
int main(int argc,char **args) { Mat A; Vec min,max,maxabs; PetscInt m,n; PetscInt imin[M],imax[M],imaxabs[M],indices[N],row; PetscScalar values[N]; PetscErrorCode ierr; MatType type; PetscMPIInt size; PetscBool doTest=PETSC_TRUE; ierr = PetscInitialize(&argc,&args,(char*)0,help);if (ierr) return ierr; ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); ierr = MatCreate(PETSC_COMM_WORLD,&A);CHKERRQ(ierr); ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr); ierr = MatSetFromOptions(A);CHKERRQ(ierr); ierr = MatSetUp(A);CHKERRQ(ierr); row = 0; indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 3; indices[4] = 4; indices[5] = 5; values[0] = -1.0; values[1] = 0.0; values[2] = 1.0; values[3] = 3.0; values[4] = 4.0; values[5] = -5.0; ierr = MatSetValues(A,1,&row,6,indices,values,INSERT_VALUES);CHKERRQ(ierr); row = 1; ierr = MatSetValues(A,1,&row,3,indices,values,INSERT_VALUES);CHKERRQ(ierr); row = 4; ierr = MatSetValues(A,1,&row,1,indices+4,values+4,INSERT_VALUES);CHKERRQ(ierr); row = 4; ierr = MatSetValues(A,1,&row,2,indices+4,values+4,INSERT_VALUES);CHKERRQ(ierr); ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatView(A,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = MatGetLocalSize(A, &m,&n);CHKERRQ(ierr); ierr = VecCreate(PETSC_COMM_WORLD,&min);CHKERRQ(ierr); ierr = VecSetSizes(min,m,PETSC_DECIDE);CHKERRQ(ierr); ierr = VecSetFromOptions(min);CHKERRQ(ierr); ierr = VecDuplicate(min,&max);CHKERRQ(ierr); ierr = VecDuplicate(min,&maxabs);CHKERRQ(ierr); /* Test MatGetRowMin, MatGetRowMax and MatGetRowMaxAbs */ if (size == 1) { ierr = MatGetRowMin(A,min,imin);CHKERRQ(ierr); ierr = MatGetRowMax(A,max,imax);CHKERRQ(ierr); ierr = MatGetRowMaxAbs(A,maxabs,imaxabs);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Row Minimums\n");CHKERRQ(ierr); ierr = VecView(min,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = PetscIntView(5,imin,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Row Maximums\n");CHKERRQ(ierr); ierr = VecView(max,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = PetscIntView(5,imax,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Row Maximum Absolute Values\n");CHKERRQ(ierr); ierr = VecView(maxabs,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = PetscIntView(5,imaxabs,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } else { ierr = MatGetType(A,&type);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"\nMatrix type: %s\n",type);CHKERRQ(ierr); /* AIJ */ ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&doTest);CHKERRQ(ierr); if (doTest) { ierr = MatGetRowMaxAbs(A,maxabs,NULL);CHKERRQ(ierr); ierr = MatGetRowMaxAbs(A,maxabs,imaxabs);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Row Maximum Absolute Values:\n");CHKERRQ(ierr); ierr = VecView(maxabs,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } /* BAIJ */ ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&doTest);CHKERRQ(ierr); if (doTest) { ierr = MatGetRowMaxAbs(A,maxabs,NULL);CHKERRQ(ierr); ierr = MatGetRowMaxAbs(A,maxabs,imaxabs);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Row Maximum Absolute Values:\n");CHKERRQ(ierr); ierr = VecView(maxabs,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } } if (size == 1) { ierr = MatConvert(A,MATDENSE,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr); ierr = MatGetRowMin(A,min,imin);CHKERRQ(ierr); ierr = MatGetRowMax(A,max,imax);CHKERRQ(ierr); ierr = MatGetRowMaxAbs(A,maxabs,imaxabs);CHKERRQ(ierr); ierr = MatView(A,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Row Minimums\n");CHKERRQ(ierr); ierr = VecView(min,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = PetscIntView(5,imin,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Row Maximums\n");CHKERRQ(ierr); ierr = VecView(max,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = PetscIntView(5,imax,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Row Maximum Absolute Values\n");CHKERRQ(ierr); ierr = VecView(maxabs,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = PetscIntView(5,imaxabs,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } ierr = VecDestroy(&min);CHKERRQ(ierr); ierr = VecDestroy(&max);CHKERRQ(ierr); ierr = VecDestroy(&maxabs);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = PetscFinalize(); return ierr; }