Actual source code: ex27.c
petsc-3.7.5 2017-01-01
2: static char help[] = "Reads a PETSc matrix and vector from a file and solves a linear system.\n\
3: Test MatMatSolve(). Input parameters include\n\
4: -f <input_file> : file to load \n\n";
6: /*
7: Usage:
8: ex27 -f0 <mat_binaryfile>
9: */
11: #include <petscksp.h>
12: extern PetscErrorCode PCShellApply_Matinv(PC,Vec,Vec);
16: int main(int argc,char **args)
17: {
18: KSP ksp;
19: Mat A,B,F,X;
20: Vec x,b,u; /* approx solution, RHS, exact solution */
21: PetscViewer fd; /* viewer */
22: char file[1][PETSC_MAX_PATH_LEN]; /* input file name */
23: PetscBool flg;
25: PetscInt M,N,i,its;
26: PetscReal norm;
27: PetscScalar val=1.0;
28: PetscMPIInt size;
29: PC pc;
31: PetscInitialize(&argc,&args,(char*)0,help);
32: MPI_Comm_size(PETSC_COMM_WORLD,&size);
33: if (size != 1) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"This is a uniprocessor example only!");
35: /* Read matrix and right-hand-side vector */
36: PetscOptionsGetString(NULL,NULL,"-f",file[0],PETSC_MAX_PATH_LEN,&flg);
37: if (!flg) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_USER,"Must indicate binary file with the -f option");
39: PetscViewerBinaryOpen(PETSC_COMM_WORLD,file[0],FILE_MODE_READ,&fd);
40: MatCreate(PETSC_COMM_WORLD,&A);
41: MatSetType(A,MATAIJ);
42: MatLoad(A,fd);
43: VecCreate(PETSC_COMM_WORLD,&b);
44: VecLoad(b,fd);
45: PetscViewerDestroy(&fd);
47: /*
48: If the loaded matrix is larger than the vector (due to being padded
49: to match the block size of the system), then create a new padded vector.
50: */
51: {
52: PetscInt m,n,j,mvec,start,end,indx;
53: Vec tmp;
54: PetscScalar *bold;
56: /* Create a new vector b by padding the old one */
57: MatGetLocalSize(A,&m,&n);
58: if (m != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ, "This example is not intended for rectangular matrices (%d, %d)", m, n);
59: VecCreate(PETSC_COMM_WORLD,&tmp);
60: VecSetSizes(tmp,m,PETSC_DECIDE);
61: VecSetFromOptions(tmp);
62: VecGetOwnershipRange(b,&start,&end);
63: VecGetLocalSize(b,&mvec);
64: VecGetArray(b,&bold);
65: for (j=0; j<mvec; j++) {
66: indx = start+j;
67: VecSetValues(tmp,1,&indx,bold+j,INSERT_VALUES);
68: }
69: VecRestoreArray(b,&bold);
70: VecDestroy(&b);
71: VecAssemblyBegin(tmp);
72: VecAssemblyEnd(tmp);
73: b = tmp;
74: }
75: VecDuplicate(b,&x);
76: VecDuplicate(b,&u);
77: VecSet(x,0.0);
79: /* Create dense matric B and X. Set B as an identity matrix */
80: MatGetSize(A,&M,&N);
81: MatCreate(MPI_COMM_SELF,&B);
82: MatSetSizes(B,M,N,M,N);
83: MatSetType(B,MATSEQDENSE);
84: MatSeqDenseSetPreallocation(B,NULL);
85: for (i=0; i<M; i++) {
86: MatSetValues(B,1,&i,1,&i,&val,INSERT_VALUES);
87: }
88: MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
89: MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
91: MatDuplicate(B,MAT_DO_NOT_COPY_VALUES,&X);
93: /* Compute X=inv(A) by MatMatSolve() */
94: KSPCreate(PETSC_COMM_WORLD,&ksp);
95: KSPSetOperators(ksp,A,A);
96: KSPGetPC(ksp,&pc);
97: PCSetType(pc,PCLU);
98: KSPSetFromOptions(ksp);
99: KSPSetUp(ksp);
100: PCFactorGetMatrix(pc,&F);
101: MatMatSolve(F,B,X);
102: MatDestroy(&B);
104: /* Now, set X=inv(A) as a preconditioner */
105: PCSetType(pc,PCSHELL);
106: PCShellSetContext(pc,(void*)X);
107: PCShellSetApply(pc,PCShellApply_Matinv);
108: KSPSetFromOptions(ksp);
110: /* Sove preconditioned system A*x = b */
111: KSPSolve(ksp,b,x);
112: KSPGetIterationNumber(ksp,&its);
114: /* Check error */
115: MatMult(A,x,u);
116: VecAXPY(u,-1.0,b);
117: VecNorm(u,NORM_2,&norm);
118: PetscPrintf(PETSC_COMM_WORLD,"Number of iterations = %3D\n",its);
119: PetscPrintf(PETSC_COMM_WORLD,"Residual norm %g\n",(double)norm);
121: /* Free work space. */
122: MatDestroy(&X);
123: MatDestroy(&A); VecDestroy(&b);
124: VecDestroy(&u); VecDestroy(&x);
125: KSPDestroy(&ksp);
126: PetscFinalize();
127: return 0;
128: }
132: PetscErrorCode PCShellApply_Matinv(PC pc,Vec xin,Vec xout)
133: {
135: Mat X;
138: PCShellGetContext(pc,(void**)&X);
139: MatMult(X,xin,xout);
140: return(0);
141: }