PetscErrorCode PCGAMGOptProl_Classical_Jacobi(PC pc,const Mat A,Mat *P) { PetscErrorCode ierr; PetscInt f,s,n,cf,cs,i,idx; PetscInt *coarserows; PetscInt ncols; const PetscInt *pcols; const PetscScalar *pvals; Mat Pnew; Vec diag; PC_MG *mg = (PC_MG*)pc->data; PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; PC_GAMG_Classical *cls = (PC_GAMG_Classical*)pc_gamg->subctx; PetscFunctionBegin; if (cls->nsmooths == 0) { ierr = PCGAMGTruncateProlongator_Private(pc,P);CHKERRQ(ierr); PetscFunctionReturn(0); } ierr = MatGetOwnershipRange(*P,&s,&f);CHKERRQ(ierr); n = f-s; ierr = MatGetOwnershipRangeColumn(*P,&cs,&cf);CHKERRQ(ierr); ierr = PetscMalloc(sizeof(PetscInt)*n,&coarserows);CHKERRQ(ierr); /* identify the rows corresponding to coarse unknowns */ idx = 0; for (i=s;i<f;i++) { ierr = MatGetRow(*P,i,&ncols,&pcols,&pvals);CHKERRQ(ierr); /* assume, for now, that it's a coarse unknown if it has a single unit entry */ if (ncols == 1) { if (pvals[0] == 1.) { coarserows[idx] = i; idx++; } } ierr = MatRestoreRow(*P,i,&ncols,&pcols,&pvals);CHKERRQ(ierr); } ierr = MatGetVecs(A,&diag,0);CHKERRQ(ierr); ierr = MatGetDiagonal(A,diag);CHKERRQ(ierr); ierr = VecReciprocal(diag);CHKERRQ(ierr); for (i=0;i<cls->nsmooths;i++) { ierr = MatMatMult(A,*P,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&Pnew);CHKERRQ(ierr); ierr = MatZeroRows(Pnew,idx,coarserows,0.,NULL,NULL);CHKERRQ(ierr); ierr = MatDiagonalScale(Pnew,diag,0);CHKERRQ(ierr); ierr = MatAYPX(Pnew,-1.0,*P,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = MatDestroy(P);CHKERRQ(ierr); *P = Pnew; Pnew = NULL; } ierr = VecDestroy(&diag);CHKERRQ(ierr); ierr = PetscFree(coarserows);CHKERRQ(ierr); ierr = PCGAMGTruncateProlongator_Private(pc,P);CHKERRQ(ierr); PetscFunctionReturn(0); }
bool PetscMatTools::CheckEquality(const Mat mat1, const Mat mat2, double tol) { Mat y; MatDuplicate(mat2, MAT_COPY_VALUES, &y); double minus_one = -1.0; #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2 // MatAYPX(*a, X, Y) does Y = X + a*Y. MatAYPX(&minus_one, mat1, y); #elif (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 3 && PETSC_VERSION_SUBMINOR == 1) //PETSc 2.3.1 // MatAYPX( Y, a, X) does Y = a*Y + X. MatAYPX(y, minus_one, mat1); #else // MatAYPX( Y, a, X, structure) does Y = a*Y + X. MatAYPX(y, minus_one, mat1, DIFFERENT_NONZERO_PATTERN); #endif PetscReal norm; MatNorm(y, NORM_INFINITY, &norm); PetscTools::Destroy(y); return (norm < tol); }
/*@ MatCreateSchurComplementPmat - create a preconditioning matrix for the Schur complement by assembling Sp = A11 - A10 inv(diag(A00)) A01 Collective on Mat Input Parameters: + A00,A01,A10,A11 - the four parts of the original matrix A = [A00 A01; A10 A11] (A01,A10, and A11 are optional, implying zero matrices) . ainvtype - type of approximation for inv(A00) used when forming Sp = A11 - A10 inv(A00) A01 - preuse - MAT_INITIAL_MATRIX for a new Sp, or MAT_REUSE_MATRIX to reuse an existing Sp, or MAT_IGNORE_MATRIX to put nothing in Sp Output Parameter: - Spmat - approximate Schur complement suitable for preconditioning S = A11 - A10 inv(diag(A00)) A01 Note: Since the real Schur complement is usually dense, providing a good approximation to newpmat usually requires application-specific information. The default for assembled matrices is to use the inverse of the diagonal of the (0,0) block A00 in place of A00^{-1}. This rarely produce a scalable algorithm. Optionally, A00 can be lumped before forming inv(diag(A00)). Level: advanced Concepts: matrices^submatrices .seealso: MatCreateSchurComplement(), MatGetSchurComplement(), MatSchurComplementGetPmat(), MatSchurComplementAinvType @*/ PetscErrorCode MatCreateSchurComplementPmat(Mat A00,Mat A01,Mat A10,Mat A11,MatSchurComplementAinvType ainvtype,MatReuse preuse,Mat *Spmat) { PetscErrorCode ierr; PetscInt N00; PetscFunctionBegin; /* Use an appropriate approximate inverse of A00 to form A11 - A10 inv(diag(A00)) A01; a NULL A01, A10 or A11 indicates a zero matrix. */ /* TODO: Perhaps should create an appropriately-sized zero matrix of the same type as A00? */ if ((!A01 || !A10) & !A11) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot assemble Spmat: A01, A10 and A11 are all NULL."); if (preuse == MAT_IGNORE_MATRIX) PetscFunctionReturn(0); /* A zero size A00 or empty A01 or A10 imply S = A11. */ ierr = MatGetSize(A00,&N00,NULL);CHKERRQ(ierr); if (!A01 || !A10 || !N00) { if (preuse == MAT_INITIAL_MATRIX) { ierr = MatDuplicate(A11,MAT_COPY_VALUES,Spmat);CHKERRQ(ierr); } else { /* MAT_REUSE_MATRIX */ /* TODO: when can we pass SAME_NONZERO_PATTERN? */ ierr = MatCopy(A11,*Spmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); } } else { Mat AdB; Vec diag; ierr = MatCreateVecs(A00,&diag,NULL);CHKERRQ(ierr); if (ainvtype == MAT_SCHUR_COMPLEMENT_AINV_LUMP) { ierr = MatGetRowSum(A00,diag);CHKERRQ(ierr); } else if (ainvtype == MAT_SCHUR_COMPLEMENT_AINV_DIAG) { ierr = MatGetDiagonal(A00,diag);CHKERRQ(ierr); } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown MatSchurComplementAinvType: %D", ainvtype); ierr = VecReciprocal(diag);CHKERRQ(ierr); ierr = MatDuplicate(A01,MAT_COPY_VALUES,&AdB);CHKERRQ(ierr); ierr = MatDiagonalScale(AdB,diag,NULL);CHKERRQ(ierr); ierr = VecDestroy(&diag);CHKERRQ(ierr); /* Cannot really reuse Spmat in MatMatMult() because of MatAYPX() --> MatAXPY() --> MatHeaderReplace() --> MatDestroy_XXX_MatMatMult() */ ierr = MatDestroy(Spmat);CHKERRQ(ierr); ierr = MatMatMult(A10,AdB,MAT_INITIAL_MATRIX,PETSC_DEFAULT,Spmat);CHKERRQ(ierr); if (!A11) { ierr = MatScale(*Spmat,-1.0);CHKERRQ(ierr); } else { /* TODO: when can we pass SAME_NONZERO_PATTERN? */ ierr = MatAYPX(*Spmat,-1,A11,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); } ierr = MatDestroy(&AdB);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/* Developer Notes: This should be implemented with a MatCreate_SchurComplement() as that is the standard design for new Mat classes. */ PetscErrorCode MatGetSchurComplement_Basic(Mat mat,IS isrow0,IS iscol0,IS isrow1,IS iscol1,MatReuse mreuse,Mat *newmat,MatReuse preuse,Mat *newpmat) { PetscErrorCode ierr; Mat A=0,Ap=0,B=0,C=0,D=0; PetscFunctionBegin; PetscValidHeaderSpecific(mat,MAT_CLASSID,1); PetscValidHeaderSpecific(isrow0,IS_CLASSID,2); PetscValidHeaderSpecific(iscol0,IS_CLASSID,3); PetscValidHeaderSpecific(isrow1,IS_CLASSID,4); PetscValidHeaderSpecific(iscol1,IS_CLASSID,5); if (mreuse == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat,MAT_CLASSID,7); if (preuse == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newpmat,MAT_CLASSID,9); PetscValidType(mat,1); if (mat->factortype) SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); if (mreuse != MAT_IGNORE_MATRIX) { /* Use MatSchurComplement */ if (mreuse == MAT_REUSE_MATRIX) { ierr = MatSchurComplementGetSubmatrices(*newmat,&A,&Ap,&B,&C,&D);CHKERRQ(ierr); if (!A || !Ap || !B || !C) SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_ARG_WRONGSTATE,"Attempting to reuse matrix but Schur complement matrices unset"); if (A != Ap) SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_ARG_WRONGSTATE,"Preconditioning matrix does not match operator"); ierr = MatDestroy(&Ap);CHKERRQ(ierr); /* get rid of extra reference */ } ierr = MatGetSubMatrix(mat,isrow0,iscol0,mreuse,&A);CHKERRQ(ierr); ierr = MatGetSubMatrix(mat,isrow0,iscol1,mreuse,&B);CHKERRQ(ierr); ierr = MatGetSubMatrix(mat,isrow1,iscol0,mreuse,&C);CHKERRQ(ierr); ierr = MatGetSubMatrix(mat,isrow1,iscol1,mreuse,&D);CHKERRQ(ierr); switch (mreuse) { case MAT_INITIAL_MATRIX: ierr = MatCreateSchurComplement(A,A,B,C,D,newmat);CHKERRQ(ierr); break; case MAT_REUSE_MATRIX: ierr = MatSchurComplementUpdate(*newmat,A,A,B,C,D,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); break; default: SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_SUP,"Unrecognized value of mreuse"); } } if (preuse != MAT_IGNORE_MATRIX) { /* Use the diagonal part of A to form D - C inv(diag(A)) B */ Mat Ad,AdB,S; Vec diag; PetscInt i,m,n,mstart,mend; PetscScalar *x; /* We could compose these with newpmat so that the matrices can be reused. */ if (!A) {ierr = MatGetSubMatrix(mat,isrow0,iscol0,MAT_INITIAL_MATRIX,&A);CHKERRQ(ierr);} if (!B) {ierr = MatGetSubMatrix(mat,isrow0,iscol1,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);} if (!C) {ierr = MatGetSubMatrix(mat,isrow1,iscol0,MAT_INITIAL_MATRIX,&C);CHKERRQ(ierr);} if (!D) {ierr = MatGetSubMatrix(mat,isrow1,iscol1,MAT_INITIAL_MATRIX,&D);CHKERRQ(ierr);} ierr = MatGetVecs(A,&diag,PETSC_NULL);CHKERRQ(ierr); ierr = MatGetDiagonal(A,diag);CHKERRQ(ierr); ierr = VecReciprocal(diag);CHKERRQ(ierr); ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr); /* We need to compute S = D - C inv(diag(A)) B. For row-oriented formats, it is easy to scale the rows of B and * for column-oriented formats the columns of C can be scaled. Would skip creating a silly diagonal matrix. */ ierr = MatCreate(((PetscObject)A)->comm,&Ad);CHKERRQ(ierr); ierr = MatSetSizes(Ad,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); ierr = MatSetOptionsPrefix(Ad,((PetscObject)mat)->prefix);CHKERRQ(ierr); ierr = MatAppendOptionsPrefix(Ad,"diag_");CHKERRQ(ierr); ierr = MatSetFromOptions(Ad);CHKERRQ(ierr); ierr = MatSeqAIJSetPreallocation(Ad,1,PETSC_NULL);CHKERRQ(ierr); ierr = MatMPIAIJSetPreallocation(Ad,1,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr); ierr = MatGetOwnershipRange(Ad,&mstart,&mend);CHKERRQ(ierr); ierr = VecGetArray(diag,&x);CHKERRQ(ierr); for (i=mstart; i<mend; i++) { ierr = MatSetValue(Ad,i,i,x[i-mstart],INSERT_VALUES);CHKERRQ(ierr); } ierr = VecRestoreArray(diag,&x);CHKERRQ(ierr); ierr = MatAssemblyBegin(Ad,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(Ad,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = VecDestroy(&diag);CHKERRQ(ierr); ierr = MatMatMult(Ad,B,MAT_INITIAL_MATRIX,1,&AdB);CHKERRQ(ierr); S = (preuse == MAT_REUSE_MATRIX) ? *newpmat : (Mat)0; ierr = MatMatMult(C,AdB,preuse,PETSC_DEFAULT,&S);CHKERRQ(ierr); ierr = MatAYPX(S,-1,D,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); *newpmat = S; ierr = MatDestroy(&Ad);CHKERRQ(ierr); ierr = MatDestroy(&AdB);CHKERRQ(ierr); } ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = MatDestroy(&B);CHKERRQ(ierr); ierr = MatDestroy(&C);CHKERRQ(ierr); ierr = MatDestroy(&D);CHKERRQ(ierr); PetscFunctionReturn(0); }
int main(int argc,char **argv) { Mat mat,tmat = 0; PetscInt m = 7,n,i,j,rstart,rend,rect = 0; PetscErrorCode ierr; PetscMPIInt size,rank; PetscBool flg; PetscScalar v, alpha; PetscReal normf,normi,norm1; ierr = PetscInitialize(&argc,&argv,(char*)0,help);CHKERRQ(ierr); ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_COMMON);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-m",&m,NULL);CHKERRQ(ierr); ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); n = m; ierr = PetscOptionsHasName(NULL,"-rectA",&flg);CHKERRQ(ierr); if (flg) {n += 2; rect = 1;} ierr = PetscOptionsHasName(NULL,"-rectB",&flg);CHKERRQ(ierr); if (flg) {n -= 2; rect = 1;} /* ------- Assemble matrix, test MatValid() --------- */ ierr = MatCreate(PETSC_COMM_WORLD,&mat);CHKERRQ(ierr); ierr = MatSetSizes(mat,PETSC_DECIDE,PETSC_DECIDE,m,n);CHKERRQ(ierr); ierr = MatSetFromOptions(mat);CHKERRQ(ierr); ierr = MatSetUp(mat);CHKERRQ(ierr); ierr = MatGetOwnershipRange(mat,&rstart,&rend);CHKERRQ(ierr); for (i=rstart; i<rend; i++) { for (j=0; j<n; j++) { v = 10.0*i+j; ierr = MatSetValues(mat,1,&i,1,&j,&v,INSERT_VALUES);CHKERRQ(ierr); } } ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* ----------------- Test MatNorm() ----------------- */ ierr = MatNorm(mat,NORM_FROBENIUS,&normf);CHKERRQ(ierr); ierr = MatNorm(mat,NORM_1,&norm1);CHKERRQ(ierr); ierr = MatNorm(mat,NORM_INFINITY,&normi);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"original A: Frobenious norm = %G, one norm = %G, infinity norm = %G\n", normf,norm1,normi);CHKERRQ(ierr); ierr = MatView(mat,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); /* --------------- Test MatTranspose() -------------- */ ierr = PetscOptionsHasName(NULL,"-in_place",&flg);CHKERRQ(ierr); if (!rect && flg) { ierr = MatTranspose(mat,MAT_REUSE_MATRIX,&mat);CHKERRQ(ierr); /* in-place transpose */ tmat = mat; mat = 0; } else { /* out-of-place transpose */ ierr = MatTranspose(mat,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr); } /* ----------------- Test MatNorm() ----------------- */ /* Print info about transpose matrix */ ierr = MatNorm(tmat,NORM_FROBENIUS,&normf);CHKERRQ(ierr); ierr = MatNorm(tmat,NORM_1,&norm1);CHKERRQ(ierr); ierr = MatNorm(tmat,NORM_INFINITY,&normi);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"B = A^T: Frobenious norm = %G, one norm = %G, infinity norm = %G\n", normf,norm1,normi);CHKERRQ(ierr); ierr = MatView(tmat,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); /* ----------------- Test MatAXPY(), MatAYPX() ----------------- */ if (mat && !rect) { alpha = 1.0; ierr = PetscOptionsGetScalar(NULL,"-alpha",&alpha,NULL);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"MatAXPY: B = B + alpha * A\n");CHKERRQ(ierr); ierr = MatAXPY(tmat,alpha,mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = MatView(tmat,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"MatAYPX: B = alpha*B + A\n");CHKERRQ(ierr); ierr = MatAYPX(tmat,alpha,mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = MatView(tmat,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } { Mat C; alpha = 1.0; ierr = PetscPrintf(PETSC_COMM_WORLD,"MatAXPY: C = C + alpha * A, C=A, SAME_NONZERO_PATTERN\n");CHKERRQ(ierr); ierr = MatDuplicate(mat,MAT_COPY_VALUES,&C);CHKERRQ(ierr); ierr = MatAXPY(C,alpha,mat,SAME_NONZERO_PATTERN);CHKERRQ(ierr); ierr = MatView(C,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = MatDestroy(&C);CHKERRQ(ierr); } { Mat matB; /* get matB that has nonzeros of mat in all even numbers of row and col */ ierr = MatCreate(PETSC_COMM_WORLD,&matB);CHKERRQ(ierr); ierr = MatSetSizes(matB,PETSC_DECIDE,PETSC_DECIDE,m,n);CHKERRQ(ierr); ierr = MatSetFromOptions(matB);CHKERRQ(ierr); ierr = MatSetUp(matB);CHKERRQ(ierr); ierr = MatGetOwnershipRange(matB,&rstart,&rend);CHKERRQ(ierr); if (rstart % 2 != 0) rstart++; for (i=rstart; i<rend; i += 2) { for (j=0; j<n; j += 2) { v = 10.0*i+j; ierr = MatSetValues(matB,1,&i,1,&j,&v,INSERT_VALUES);CHKERRQ(ierr); } } ierr = MatAssemblyBegin(matB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(matB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); PetscPrintf(PETSC_COMM_WORLD," A: original matrix:\n"); ierr = MatView(mat,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); PetscPrintf(PETSC_COMM_WORLD," B(a subset of A):\n"); ierr = MatView(matB,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"MatAXPY: B = B + alpha * A, SUBSET_NONZERO_PATTERN\n");CHKERRQ(ierr); ierr = MatAXPY(mat,alpha,matB,SUBSET_NONZERO_PATTERN);CHKERRQ(ierr); ierr = MatView(mat,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = MatDestroy(&matB);CHKERRQ(ierr); } /* Free data structures */ if (mat) {ierr = MatDestroy(&mat);CHKERRQ(ierr);} if (tmat) {ierr = MatDestroy(&tmat);CHKERRQ(ierr);} ierr = PetscFinalize(); return 0; }
void PETSC_STDCALL mataypx_(Mat Y,PetscScalar *a,Mat X,MatStructure *str, int *__ierr ){ *__ierr = MatAYPX( (Mat)PetscToPointer((Y) ),*a, (Mat)PetscToPointer((X) ),*str); }
PetscErrorCode TaoSolve_Test(Tao tao) { Mat A = tao->hessian,B; Vec x = tao->solution,g1,g2; PetscErrorCode ierr; PetscInt i; PetscReal nrm,gnorm,hcnorm,fdnorm; MPI_Comm comm; Tao_Test *fd = (Tao_Test*)tao->data; PetscFunctionBegin; comm = ((PetscObject)tao)->comm; if (fd->check_gradient) { ierr = VecDuplicate(x,&g1);CHKERRQ(ierr); ierr = VecDuplicate(x,&g2);CHKERRQ(ierr); ierr = PetscPrintf(comm,"Testing hand-coded gradient (hc) against finite difference gradient (fd), if the ratio ||fd - hc|| / ||hc|| is\n");CHKERRQ(ierr); ierr = PetscPrintf(comm,"0 (1.e-8), the hand-coded gradient is probably correct.\n");CHKERRQ(ierr); if (!fd->complete_print) { ierr = PetscPrintf(comm,"Run with -tao_test_display to show difference\n");CHKERRQ(ierr); ierr = PetscPrintf(comm,"between hand-coded and finite difference gradient.\n");CHKERRQ(ierr); } for (i=0; i<3; i++) { if (i == 1) {ierr = VecSet(x,-1.0);CHKERRQ(ierr);} else if (i == 2) {ierr = VecSet(x,1.0);CHKERRQ(ierr);} /* Compute both version of gradient */ ierr = TaoComputeGradient(tao,x,g1);CHKERRQ(ierr); ierr = TaoDefaultComputeGradient(tao,x,g2,NULL);CHKERRQ(ierr); if (fd->complete_print) { MPI_Comm gcomm; PetscViewer viewer; ierr = PetscPrintf(comm,"Finite difference gradient\n");CHKERRQ(ierr); ierr = PetscObjectGetComm((PetscObject)g2,&gcomm);CHKERRQ(ierr); ierr = PetscViewerASCIIGetStdout(gcomm,&viewer);CHKERRQ(ierr); ierr = VecView(g2,viewer);CHKERRQ(ierr); ierr = PetscPrintf(comm,"Hand-coded gradient\n");CHKERRQ(ierr); ierr = PetscObjectGetComm((PetscObject)g1,&gcomm);CHKERRQ(ierr); ierr = PetscViewerASCIIGetStdout(gcomm,&viewer);CHKERRQ(ierr); ierr = VecView(g1,viewer);CHKERRQ(ierr); ierr = PetscPrintf(comm,"\n");CHKERRQ(ierr); } ierr = VecAXPY(g2,-1.0,g1);CHKERRQ(ierr); ierr = VecNorm(g1,NORM_2,&hcnorm);CHKERRQ(ierr); ierr = VecNorm(g2,NORM_2,&fdnorm);CHKERRQ(ierr); if (!hcnorm) hcnorm=1.0e-20; ierr = PetscPrintf(comm,"ratio ||fd-hc||/||hc|| = %g, difference ||fd-hc|| = %g\n", (double)(fdnorm/hcnorm), (double)fdnorm);CHKERRQ(ierr); } ierr = VecDestroy(&g1);CHKERRQ(ierr); ierr = VecDestroy(&g2);CHKERRQ(ierr); } if (fd->check_hessian) { if (A != tao->hessian_pre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Cannot test with alternative preconditioner"); ierr = PetscPrintf(comm,"Testing hand-coded Hessian (hc) against finite difference Hessian (fd). If the ratio is\n");CHKERRQ(ierr); ierr = PetscPrintf(comm,"O (1.e-8), the hand-coded Hessian is probably correct.\n");CHKERRQ(ierr); if (!fd->complete_print) { ierr = PetscPrintf(comm,"Run with -tao_test_display to show difference\n");CHKERRQ(ierr); ierr = PetscPrintf(comm,"of hand-coded and finite difference Hessian.\n");CHKERRQ(ierr); } for (i=0;i<3;i++) { /* compute both versions of Hessian */ ierr = TaoComputeHessian(tao,x,A,A);CHKERRQ(ierr); if (!i) {ierr = MatConvert(A,MATSAME,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);} ierr = TaoDefaultComputeHessian(tao,x,B,B,tao->user_hessP);CHKERRQ(ierr); if (fd->complete_print) { MPI_Comm bcomm; PetscViewer viewer; ierr = PetscPrintf(comm,"Finite difference Hessian\n");CHKERRQ(ierr); ierr = PetscObjectGetComm((PetscObject)B,&bcomm);CHKERRQ(ierr); ierr = PetscViewerASCIIGetStdout(bcomm,&viewer);CHKERRQ(ierr); ierr = MatView(B,viewer);CHKERRQ(ierr); } /* compare */ ierr = MatAYPX(B,-1.0,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = MatNorm(B,NORM_FROBENIUS,&nrm);CHKERRQ(ierr); ierr = MatNorm(A,NORM_FROBENIUS,&gnorm);CHKERRQ(ierr); if (fd->complete_print) { MPI_Comm hcomm; PetscViewer viewer; ierr = PetscPrintf(comm,"Hand-coded Hessian\n");CHKERRQ(ierr); ierr = PetscObjectGetComm((PetscObject)B,&hcomm);CHKERRQ(ierr); ierr = PetscViewerASCIIGetStdout(hcomm,&viewer);CHKERRQ(ierr); ierr = MatView(A,viewer);CHKERRQ(ierr); ierr = PetscPrintf(comm,"Hand-coded minus finite difference Hessian\n");CHKERRQ(ierr); ierr = MatView(B,viewer);CHKERRQ(ierr); } if (!gnorm) gnorm = 1.0e-20; ierr = PetscPrintf(comm,"ratio ||fd-hc||/||hc|| = %g, difference ||fd-hc|| = %g\n",(double)(nrm/gnorm),(double)nrm);CHKERRQ(ierr); } ierr = MatDestroy(&B);CHKERRQ(ierr); } tao->reason = TAO_CONVERGED_USER; PetscFunctionReturn(0); }
/*@C SNESUpdateCheckJacobian - Checks each Jacobian computed by the nonlinear solver comparing the users function with a finite difference computation. Options Database: + -snes_check_jacobian - use this every time SNESSolve() is called - -snes_check_jacobian_view - Display difference between approximate and hand-coded Jacobian Level: intermediate .seealso: SNESCreate(), SNES, SNESSetType(), SNESNEWTONLS, SNESNEWTONTR, SNESSolve() @*/ PetscErrorCode SNESUpdateCheckJacobian(SNES snes,PetscInt it) { Mat A = snes->jacobian,B; Vec x = snes->vec_sol,f = snes->vec_func,f1 = snes->vec_sol_update; PetscErrorCode ierr; PetscReal nrm,gnorm; PetscErrorCode (*objective)(SNES,Vec,PetscReal*,void*); void *ctx; PetscReal fnorm,f1norm,dnorm; PetscInt m,n,M,N; PetscBool complete_print = PETSC_FALSE; void *functx; PetscViewer viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); PetscFunctionBegin; ierr = PetscOptionsHasName(((PetscObject)snes)->prefix,"-snes_check_jacobian_view",&complete_print);CHKERRQ(ierr); if (A != snes->jacobian_pre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Cannot check Jacobian with alternative preconditioner"); ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer," Testing hand-coded Jacobian, if the ratio is O(1.e-8), the hand-coded Jacobian is probably correct.\n");CHKERRQ(ierr); if (!complete_print) { ierr = PetscViewerASCIIPrintf(viewer," Run with -snes_check_jacobian_view [viewer][:filename][:format] to show difference of hand-coded and finite difference Jacobian.\n");CHKERRQ(ierr); } /* compute both versions of Jacobian */ ierr = SNESComputeJacobian(snes,x,A,A);CHKERRQ(ierr); ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr); ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr); ierr = MatSetSizes(B,m,n,M,N);CHKERRQ(ierr); ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr); ierr = MatSetUp(B);CHKERRQ(ierr); ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); ierr = SNESGetFunction(snes,NULL,NULL,&functx);CHKERRQ(ierr); ierr = SNESComputeJacobianDefault(snes,x,B,B,functx);CHKERRQ(ierr); if (complete_print) { ierr = PetscViewerASCIIPrintf(viewer," Finite difference Jacobian\n");CHKERRQ(ierr); ierr = MatViewFromOptions(B,((PetscObject)snes)->prefix,"-snes_check_jacobian_view");CHKERRQ(ierr); } /* compare */ ierr = MatAYPX(B,-1.0,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = MatNorm(B,NORM_FROBENIUS,&nrm);CHKERRQ(ierr); ierr = MatNorm(A,NORM_FROBENIUS,&gnorm);CHKERRQ(ierr); if (complete_print) { ierr = PetscViewerASCIIPrintf(viewer," Hand-coded Jacobian\n");CHKERRQ(ierr); ierr = MatViewFromOptions(A,((PetscObject)snes)->prefix,"-snes_check_jacobian_view");CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer," Hand-coded minus finite difference Jacobian\n");CHKERRQ(ierr); ierr = MatViewFromOptions(B,((PetscObject)snes)->prefix,"-snes_check_jacobian_view");CHKERRQ(ierr); } if (!gnorm) gnorm = 1; /* just in case */ ierr = PetscViewerASCIIPrintf(viewer," %g = ||J - Jfd||//J|| %g = ||J - Jfd||\n",(double)(nrm/gnorm),(double)nrm);CHKERRQ(ierr); ierr = SNESGetObjective(snes,&objective,&ctx);CHKERRQ(ierr); if (objective) { ierr = SNESComputeFunction(snes,x,f);CHKERRQ(ierr); ierr = VecNorm(f,NORM_2,&fnorm);CHKERRQ(ierr); if (complete_print) { ierr = PetscViewerASCIIPrintf(viewer," Hand-coded Objective Function \n");CHKERRQ(ierr); ierr = VecView(f,viewer);CHKERRQ(ierr); } ierr = SNESObjectiveComputeFunctionDefaultFD(snes,x,f1,NULL);CHKERRQ(ierr); ierr = VecNorm(f1,NORM_2,&f1norm);CHKERRQ(ierr); if (complete_print) { ierr = PetscViewerASCIIPrintf(viewer," Finite-Difference Objective Function\n");CHKERRQ(ierr); ierr = VecView(f1,viewer);CHKERRQ(ierr); } /* compare the two */ ierr = VecAXPY(f,-1.0,f1);CHKERRQ(ierr); ierr = VecNorm(f,NORM_2,&dnorm);CHKERRQ(ierr); if (!fnorm) fnorm = 1.; ierr = PetscViewerASCIIPrintf(viewer," %g = Norm of objective function ratio %g = difference\n",dnorm/fnorm,dnorm);CHKERRQ(ierr); if (complete_print) { ierr = PetscViewerASCIIPrintf(viewer," Difference\n");CHKERRQ(ierr); ierr = VecView(f,viewer);CHKERRQ(ierr); } } ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); ierr = MatDestroy(&B);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode SNESSolve_Test(SNES snes) { Mat A = snes->jacobian,B; Vec x = snes->vec_sol,f = snes->vec_func,f1 = snes->vec_sol_update; PetscErrorCode ierr; PetscInt i; PetscReal nrm,gnorm; SNES_Test *neP = (SNES_Test*)snes->data; PetscErrorCode (*objective)(SNES,Vec,PetscReal*,void*); void *ctx; PetscReal fnorm,f1norm,dnorm; PetscFunctionBegin; if (A != snes->jacobian_pre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Cannot test with alternative preconditioner"); ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Testing hand-coded Jacobian, if the ratio is\n");CHKERRQ(ierr); ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"O(1.e-8), the hand-coded Jacobian is probably correct.\n");CHKERRQ(ierr); if (!neP->complete_print) { ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Run with -snes_test_display to show difference\n");CHKERRQ(ierr); ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"of hand-coded and finite difference Jacobian.\n");CHKERRQ(ierr); } for (i=0; i<3; i++) { void *functx; static const char *const loc[] = {"user-defined state","constant state -1.0","constant state 1.0"}; PetscInt m,n,M,N; if (i == 1) { ierr = VecSet(x,-1.0);CHKERRQ(ierr); } else if (i == 2) { ierr = VecSet(x,1.0);CHKERRQ(ierr); } /* evaluate the function at this point because SNESComputeJacobianDefaultColor() assumes that the function has been evaluated and put into snes->vec_func */ ierr = SNESComputeFunction(snes,x,f);CHKERRQ(ierr); if (snes->domainerror) { ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Domain error at %s\n",loc[i]);CHKERRQ(ierr); snes->domainerror = PETSC_FALSE; continue; } /* compute both versions of Jacobian */ ierr = SNESComputeJacobian(snes,x,A,A);CHKERRQ(ierr); ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr); ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr); ierr = MatSetSizes(B,m,n,M,N);CHKERRQ(ierr); ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr); ierr = MatSetUp(B);CHKERRQ(ierr); ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); ierr = SNESGetFunction(snes,NULL,NULL,&functx);CHKERRQ(ierr); ierr = SNESComputeJacobianDefault(snes,x,B,B,functx);CHKERRQ(ierr); if (neP->complete_print) { MPI_Comm comm; PetscViewer viewer; ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Finite difference Jacobian (%s)\n",loc[i]);CHKERRQ(ierr); ierr = PetscObjectGetComm((PetscObject)B,&comm);CHKERRQ(ierr); ierr = PetscViewerASCIIGetStdout(comm,&viewer);CHKERRQ(ierr); ierr = MatView(B,viewer);CHKERRQ(ierr); } /* compare */ ierr = MatAYPX(B,-1.0,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = MatNorm(B,NORM_FROBENIUS,&nrm);CHKERRQ(ierr); ierr = MatNorm(A,NORM_FROBENIUS,&gnorm);CHKERRQ(ierr); if (neP->complete_print) { MPI_Comm comm; PetscViewer viewer; ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Hand-coded Jacobian (%s)\n",loc[i]);CHKERRQ(ierr); ierr = PetscObjectGetComm((PetscObject)B,&comm);CHKERRQ(ierr); ierr = PetscViewerASCIIGetStdout(comm,&viewer);CHKERRQ(ierr); ierr = MatView(A,viewer);CHKERRQ(ierr); ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Hand-coded minus finite difference Jacobian (%s)\n",loc[i]);CHKERRQ(ierr); ierr = MatView(B,viewer);CHKERRQ(ierr); } if (!gnorm) gnorm = 1; /* just in case */ ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Norm of matrix ratio %g difference %g (%s)\n",(double)(nrm/gnorm),(double)nrm,loc[i]);CHKERRQ(ierr); ierr = SNESGetObjective(snes,&objective,&ctx);CHKERRQ(ierr); if (objective) { ierr = SNESComputeFunction(snes,x,f);CHKERRQ(ierr); ierr = VecNorm(f,NORM_2,&fnorm);CHKERRQ(ierr); if (neP->complete_print) { PetscViewer viewer; ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Hand-coded Function (%s)\n",loc[i]);CHKERRQ(ierr); ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes),&viewer);CHKERRQ(ierr); ierr = VecView(f,viewer);CHKERRQ(ierr); } ierr = SNESObjectiveComputeFunctionDefaultFD(snes,x,f1,NULL);CHKERRQ(ierr); ierr = VecNorm(f1,NORM_2,&f1norm);CHKERRQ(ierr); if (neP->complete_print) { PetscViewer viewer; ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Finite-Difference Function (%s)\n",loc[i]);CHKERRQ(ierr); ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes),&viewer);CHKERRQ(ierr); ierr = VecView(f1,viewer);CHKERRQ(ierr); } /* compare the two */ ierr = VecAXPY(f,-1.0,f1);CHKERRQ(ierr); ierr = VecNorm(f,NORM_2,&dnorm);CHKERRQ(ierr); if (!fnorm) fnorm = 1.; ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Norm of function ratio %g difference %g (%s)\n",dnorm/fnorm,dnorm,loc[i]);CHKERRQ(ierr); if (neP->complete_print) { PetscViewer viewer; ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Difference (%s)\n",loc[i]);CHKERRQ(ierr); ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes),&viewer);CHKERRQ(ierr); ierr = VecView(f,viewer);CHKERRQ(ierr); } } ierr = MatDestroy(&B);CHKERRQ(ierr); } /* Abort after the first iteration due to the jacobian not being valid. */ SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"SNESTest aborts after Jacobian test"); PetscFunctionReturn(0); }
int main(int argc,char **args) { Mat Cdense,B,C,Ct; Vec d; PetscInt i,j,m = 5,n,nrows,ncols; const PetscInt *rows,*cols; IS isrows,iscols; PetscErrorCode ierr; PetscScalar *v; PetscMPIInt rank,size; PetscReal Cnorm; PetscBool flg,mats_view=PETSC_FALSE; ierr = PetscInitialize(&argc,&args,(char*)0,help); if (ierr) return ierr; ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); CHKERRQ(ierr); ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size); CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,NULL,"-m",&m,NULL); CHKERRQ(ierr); n = m; ierr = PetscOptionsGetInt(NULL,NULL,"-n",&n,NULL); CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,NULL,"-mats_view",&mats_view); CHKERRQ(ierr); ierr = MatCreate(PETSC_COMM_WORLD,&C); CHKERRQ(ierr); ierr = MatSetSizes(C,m,n,PETSC_DECIDE,PETSC_DECIDE); CHKERRQ(ierr); ierr = MatSetType(C,MATELEMENTAL); CHKERRQ(ierr); ierr = MatSetFromOptions(C); CHKERRQ(ierr); ierr = MatSetUp(C); CHKERRQ(ierr); ierr = MatGetOwnershipIS(C,&isrows,&iscols); CHKERRQ(ierr); ierr = ISGetLocalSize(isrows,&nrows); CHKERRQ(ierr); ierr = ISGetIndices(isrows,&rows); CHKERRQ(ierr); ierr = ISGetLocalSize(iscols,&ncols); CHKERRQ(ierr); ierr = ISGetIndices(iscols,&cols); CHKERRQ(ierr); ierr = PetscMalloc1(nrows*ncols,&v); CHKERRQ(ierr); #if defined(PETSC_USE_COMPLEX) PetscRandom rand; PetscScalar rval; ierr = PetscRandomCreate(PETSC_COMM_WORLD,&rand); CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(rand); CHKERRQ(ierr); for (i=0; i<nrows; i++) { for (j=0; j<ncols; j++) { ierr = PetscRandomGetValue(rand,&rval); CHKERRQ(ierr); v[i*ncols+j] = rval; } } ierr = PetscRandomDestroy(&rand); CHKERRQ(ierr); #else for (i=0; i<nrows; i++) { for (j=0; j<ncols; j++) { v[i*ncols+j] = (PetscReal)(10000*rank+100*rows[i]+cols[j]); } } #endif ierr = MatSetValues(C,nrows,rows,ncols,cols,v,INSERT_VALUES); CHKERRQ(ierr); ierr = ISRestoreIndices(isrows,&rows); CHKERRQ(ierr); ierr = ISRestoreIndices(iscols,&cols); CHKERRQ(ierr); ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = ISDestroy(&isrows); CHKERRQ(ierr); ierr = ISDestroy(&iscols); CHKERRQ(ierr); /* Test MatView(), MatDuplicate() and out-of-place MatConvert() */ ierr = MatDuplicate(C,MAT_COPY_VALUES,&B); CHKERRQ(ierr); if (mats_view) { ierr = PetscPrintf(PETSC_COMM_WORLD,"Duplicated C:\n"); CHKERRQ(ierr); ierr = MatView(B,PETSC_VIEWER_STDOUT_WORLD); CHKERRQ(ierr); } ierr = MatDestroy(&B); CHKERRQ(ierr); ierr = MatConvert(C,MATMPIDENSE,MAT_INITIAL_MATRIX,&Cdense); CHKERRQ(ierr); ierr = MatMultEqual(C,Cdense,5,&flg); CHKERRQ(ierr); if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMETYPE,"Cdense != C. MatConvert() fails"); /* Test MatNorm() */ ierr = MatNorm(C,NORM_1,&Cnorm); CHKERRQ(ierr); /* Test MatTranspose(), MatZeroEntries() and MatGetDiagonal() */ ierr = MatTranspose(C,MAT_INITIAL_MATRIX,&Ct); CHKERRQ(ierr); ierr = MatConjugate(Ct); CHKERRQ(ierr); if (mats_view) { ierr = PetscPrintf(PETSC_COMM_WORLD,"C's Transpose Conjugate:\n"); CHKERRQ(ierr); ierr = MatView(Ct,PETSC_VIEWER_STDOUT_WORLD); CHKERRQ(ierr); } ierr = MatZeroEntries(Ct); CHKERRQ(ierr); ierr = VecCreate(PETSC_COMM_WORLD,&d); CHKERRQ(ierr); ierr = VecSetSizes(d,m>n ? n : m,PETSC_DECIDE); CHKERRQ(ierr); ierr = VecSetFromOptions(d); CHKERRQ(ierr); ierr = MatGetDiagonal(C,d); CHKERRQ(ierr); if (mats_view) { ierr = PetscPrintf(PETSC_COMM_WORLD,"Diagonal of C:\n"); CHKERRQ(ierr); ierr = VecView(d,PETSC_VIEWER_STDOUT_WORLD); CHKERRQ(ierr); } if (m>n) { ierr = MatDiagonalScale(C,NULL,d); CHKERRQ(ierr); } else { ierr = MatDiagonalScale(C,d,NULL); CHKERRQ(ierr); } if (mats_view) { ierr = PetscPrintf(PETSC_COMM_WORLD,"Diagonal Scaled C:\n"); CHKERRQ(ierr); ierr = MatView(C,PETSC_VIEWER_STDOUT_WORLD); CHKERRQ(ierr); } /* Test MatAXPY(), MatAYPX() and in-place MatConvert() */ ierr = MatCreate(PETSC_COMM_WORLD,&B); CHKERRQ(ierr); ierr = MatSetSizes(B,m,n,PETSC_DECIDE,PETSC_DECIDE); CHKERRQ(ierr); ierr = MatSetType(B,MATELEMENTAL); CHKERRQ(ierr); ierr = MatSetFromOptions(B); CHKERRQ(ierr); ierr = MatSetUp(B); CHKERRQ(ierr); ierr = MatGetOwnershipIS(B,&isrows,&iscols); CHKERRQ(ierr); ierr = ISGetLocalSize(isrows,&nrows); CHKERRQ(ierr); ierr = ISGetIndices(isrows,&rows); CHKERRQ(ierr); ierr = ISGetLocalSize(iscols,&ncols); CHKERRQ(ierr); ierr = ISGetIndices(iscols,&cols); CHKERRQ(ierr); for (i=0; i<nrows; i++) { for (j=0; j<ncols; j++) { v[i*ncols+j] = (PetscReal)(1000*rows[i]+cols[j]); } } ierr = MatSetValues(B,nrows,rows,ncols,cols,v,INSERT_VALUES); CHKERRQ(ierr); ierr = PetscFree(v); CHKERRQ(ierr); ierr = ISRestoreIndices(isrows,&rows); CHKERRQ(ierr); ierr = ISRestoreIndices(iscols,&cols); CHKERRQ(ierr); ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = MatAXPY(B,2.5,C,SAME_NONZERO_PATTERN); CHKERRQ(ierr); ierr = MatAYPX(B,3.75,C,SAME_NONZERO_PATTERN); CHKERRQ(ierr); ierr = MatConvert(B,MATDENSE,MAT_INPLACE_MATRIX,&B); CHKERRQ(ierr); if (mats_view) { ierr = PetscPrintf(PETSC_COMM_WORLD,"B after MatAXPY and MatAYPX:\n"); CHKERRQ(ierr); ierr = MatView(B,PETSC_VIEWER_STDOUT_WORLD); CHKERRQ(ierr); } ierr = ISDestroy(&isrows); CHKERRQ(ierr); ierr = ISDestroy(&iscols); CHKERRQ(ierr); ierr = MatDestroy(&B); CHKERRQ(ierr); /* Test MatMatTransposeMult(): B = C*C^T */ ierr = MatMatTransposeMult(C,C,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B); CHKERRQ(ierr); if (mats_view) { ierr = PetscPrintf(PETSC_COMM_WORLD,"C MatMatTransposeMult C:\n"); CHKERRQ(ierr); ierr = MatView(B,PETSC_VIEWER_STDOUT_WORLD); CHKERRQ(ierr); } ierr = MatDestroy(&Cdense); CHKERRQ(ierr); ierr = PetscFree(v); CHKERRQ(ierr); ierr = MatDestroy(&B); CHKERRQ(ierr); ierr = MatDestroy(&C); CHKERRQ(ierr); ierr = MatDestroy(&Ct); CHKERRQ(ierr); ierr = VecDestroy(&d); CHKERRQ(ierr); ierr = PetscFinalize(); return ierr; }