PageRenderTime 24ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/ksp/ksp/examples/tutorials/ex8.c

https://bitbucket.org/BarryFSmith/petsc
C | 293 lines | 129 code | 31 blank | 133 comment | 19 complexity | b28b9eb264c1737436f4031b95c94bb4 MD5 | raw file
  1. static char help[] = "Illustrates use of the preconditioner ASM.\n\
  2. The Additive Schwarz Method for solving a linear system in parallel with KSP. The\n\
  3. code indicates the procedure for setting user-defined subdomains. Input\n\
  4. parameters include:\n\
  5. -user_set_subdomain_solvers: User explicitly sets subdomain solvers\n\
  6. -user_set_subdomains: Activate user-defined subdomains\n\n";
  7. /*
  8. Note: This example focuses on setting the subdomains for the ASM
  9. preconditioner for a problem on a 2D rectangular grid. See ex1.c
  10. and ex2.c for more detailed comments on the basic usage of KSP
  11. (including working with matrices and vectors).
  12. The ASM preconditioner is fully parallel, but currently the routine
  13. PCASMCreateSubdomains2D(), which is used in this example to demonstrate
  14. user-defined subdomains (activated via -user_set_subdomains), is
  15. uniprocessor only.
  16. This matrix in this linear system arises from the discretized Laplacian,
  17. and thus is not very interesting in terms of experimenting with variants
  18. of the ASM preconditioner.
  19. */
  20. /*T
  21. Concepts: KSP^Additive Schwarz Method (ASM) with user-defined subdomains
  22. Processors: n
  23. T*/
  24. /*
  25. Include "petscksp.h" so that we can use KSP solvers. Note that this file
  26. automatically includes:
  27. petscsys.h - base PETSc routines petscvec.h - vectors
  28. petscmat.h - matrices
  29. petscis.h - index sets petscksp.h - Krylov subspace methods
  30. petscviewer.h - viewers petscpc.h - preconditioners
  31. */
  32. #include <petscksp.h>
  33. #undef __FUNCT__
  34. #define __FUNCT__ "main"
  35. int main(int argc,char **args)
  36. {
  37. Vec x,b,u; /* approx solution, RHS, exact solution */
  38. Mat A; /* linear system matrix */
  39. KSP ksp; /* linear solver context */
  40. PC pc; /* PC context */
  41. IS *is,*is_local; /* array of index sets that define the subdomains */
  42. PetscInt overlap = 1; /* width of subdomain overlap */
  43. PetscInt Nsub; /* number of subdomains */
  44. PetscInt m = 15,n = 17; /* mesh dimensions in x- and y- directions */
  45. PetscInt M = 2,N = 1; /* number of subdomains in x- and y- directions */
  46. PetscInt i,j,Ii,J,Istart,Iend;
  47. PetscErrorCode ierr;
  48. PetscMPIInt size;
  49. PetscBool flg;
  50. PetscBool user_subdomains = PETSC_FALSE;
  51. PetscScalar v, one = 1.0;
  52. PetscReal e;
  53. PetscInitialize(&argc,&args,(char*)0,help);
  54. ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
  55. ierr = PetscOptionsGetInt(NULL,"-m",&m,NULL);CHKERRQ(ierr);
  56. ierr = PetscOptionsGetInt(NULL,"-n",&n,NULL);CHKERRQ(ierr);
  57. ierr = PetscOptionsGetInt(NULL,"-Mdomains",&M,NULL);CHKERRQ(ierr);
  58. ierr = PetscOptionsGetInt(NULL,"-Ndomains",&N,NULL);CHKERRQ(ierr);
  59. ierr = PetscOptionsGetInt(NULL,"-overlap",&overlap,NULL);CHKERRQ(ierr);
  60. ierr = PetscOptionsGetBool(NULL,"-user_set_subdomains",&user_subdomains,NULL);CHKERRQ(ierr);
  61. /* -------------------------------------------------------------------
  62. Compute the matrix and right-hand-side vector that define
  63. the linear system, Ax = b.
  64. ------------------------------------------------------------------- */
  65. /*
  66. Assemble the matrix for the five point stencil, YET AGAIN
  67. */
  68. ierr = MatCreate(PETSC_COMM_WORLD,&A);CHKERRQ(ierr);
  69. ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,m*n,m*n);CHKERRQ(ierr);
  70. ierr = MatSetFromOptions(A);CHKERRQ(ierr);
  71. ierr = MatSetUp(A);CHKERRQ(ierr);
  72. ierr = MatGetOwnershipRange(A,&Istart,&Iend);CHKERRQ(ierr);
  73. for (Ii=Istart; Ii<Iend; Ii++) {
  74. v = -1.0; i = Ii/n; j = Ii - i*n;
  75. if (i>0) {J = Ii - n; ierr = MatSetValues(A,1,&Ii,1,&J,&v,INSERT_VALUES);CHKERRQ(ierr);}
  76. if (i<m-1) {J = Ii + n; ierr = MatSetValues(A,1,&Ii,1,&J,&v,INSERT_VALUES);CHKERRQ(ierr);}
  77. if (j>0) {J = Ii - 1; ierr = MatSetValues(A,1,&Ii,1,&J,&v,INSERT_VALUES);CHKERRQ(ierr);}
  78. if (j<n-1) {J = Ii + 1; ierr = MatSetValues(A,1,&Ii,1,&J,&v,INSERT_VALUES);CHKERRQ(ierr);}
  79. v = 4.0; ierr = MatSetValues(A,1,&Ii,1,&Ii,&v,INSERT_VALUES);CHKERRQ(ierr);
  80. }
  81. ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
  82. ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
  83. /*
  84. Create and set vectors
  85. */
  86. ierr = VecCreate(PETSC_COMM_WORLD,&b);CHKERRQ(ierr);
  87. ierr = VecSetSizes(b,PETSC_DECIDE,m*n);CHKERRQ(ierr);
  88. ierr = VecSetFromOptions(b);CHKERRQ(ierr);
  89. ierr = VecDuplicate(b,&u);CHKERRQ(ierr);
  90. ierr = VecDuplicate(b,&x);CHKERRQ(ierr);
  91. ierr = VecSet(u,one);CHKERRQ(ierr);
  92. ierr = MatMult(A,u,b);CHKERRQ(ierr);
  93. /*
  94. Create linear solver context
  95. */
  96. ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr);
  97. /*
  98. Set operators. Here the matrix that defines the linear system
  99. also serves as the preconditioning matrix.
  100. */
  101. ierr = KSPSetOperators(ksp,A,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
  102. /*
  103. Set the default preconditioner for this program to be ASM
  104. */
  105. ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
  106. ierr = PCSetType(pc,PCASM);CHKERRQ(ierr);
  107. /* -------------------------------------------------------------------
  108. Define the problem decomposition
  109. ------------------------------------------------------------------- */
  110. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  111. Basic method, should be sufficient for the needs of many users.
  112. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  113. Set the overlap, using the default PETSc decomposition via
  114. PCASMSetOverlap(pc,overlap);
  115. Could instead use the option -pc_asm_overlap <ovl>
  116. Set the total number of blocks via -pc_asm_blocks <blks>
  117. Note: The ASM default is to use 1 block per processor. To
  118. experiment on a single processor with various overlaps, you
  119. must specify use of multiple blocks!
  120. */
  121. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  122. More advanced method, setting user-defined subdomains
  123. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  124. Firstly, create index sets that define the subdomains. The utility
  125. routine PCASMCreateSubdomains2D() is a simple example (that currently
  126. supports 1 processor only!). More generally, the user should write
  127. a custom routine for a particular problem geometry.
  128. Then call either PCASMSetLocalSubdomains() or PCASMSetTotalSubdomains()
  129. to set the subdomains for the ASM preconditioner.
  130. */
  131. if (!user_subdomains) { /* basic version */
  132. ierr = PCASMSetOverlap(pc,overlap);CHKERRQ(ierr);
  133. } else { /* advanced version */
  134. if (size != 1) SETERRQ(PETSC_COMM_WORLD,1,"PCASMCreateSubdomains2D() is currently a uniprocessor routine only!");
  135. ierr = PCASMCreateSubdomains2D(m,n,M,N,1,overlap,&Nsub,&is,&is_local);CHKERRQ(ierr);
  136. ierr = PCASMSetLocalSubdomains(pc,Nsub,is,is_local);CHKERRQ(ierr);
  137. flg = PETSC_FALSE;
  138. ierr = PetscOptionsGetBool(NULL,"-subdomain_view",&flg,NULL);CHKERRQ(ierr);
  139. if (flg) {
  140. printf("Nmesh points: %d x %d; subdomain partition: %d x %d; overlap: %d; Nsub: %d\n",m,n,M,N,overlap,Nsub);
  141. printf("IS:\n");
  142. for (i=0; i<Nsub; i++) {
  143. printf(" IS[%d]\n",i);
  144. ierr = ISView(is[i],PETSC_VIEWER_STDOUT_SELF);
  145. }
  146. printf("IS_local:\n");
  147. for (i=0; i<Nsub; i++) {
  148. printf(" IS_local[%d]\n",i);
  149. ierr = ISView(is_local[i],PETSC_VIEWER_STDOUT_SELF);
  150. }
  151. }
  152. }
  153. /* -------------------------------------------------------------------
  154. Set the linear solvers for the subblocks
  155. ------------------------------------------------------------------- */
  156. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  157. Basic method, should be sufficient for the needs of most users.
  158. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  159. By default, the ASM preconditioner uses the same solver on each
  160. block of the problem. To set the same solver options on all blocks,
  161. use the prefix -sub before the usual PC and KSP options, e.g.,
  162. -sub_pc_type <pc> -sub_ksp_type <ksp> -sub_ksp_rtol 1.e-4
  163. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  164. Advanced method, setting different solvers for various blocks.
  165. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  166. Note that each block's KSP context is completely independent of
  167. the others, and the full range of uniprocessor KSP options is
  168. available for each block.
  169. - Use PCASMGetSubKSP() to extract the array of KSP contexts for
  170. the local blocks.
  171. - See ex7.c for a simple example of setting different linear solvers
  172. for the individual blocks for the block Jacobi method (which is
  173. equivalent to the ASM method with zero overlap).
  174. */
  175. flg = PETSC_FALSE;
  176. ierr = PetscOptionsGetBool(NULL,"-user_set_subdomain_solvers",&flg,NULL);CHKERRQ(ierr);
  177. if (flg) {
  178. KSP *subksp; /* array of KSP contexts for local subblocks */
  179. PetscInt nlocal,first; /* number of local subblocks, first local subblock */
  180. PC subpc; /* PC context for subblock */
  181. PetscBool isasm;
  182. ierr = PetscPrintf(PETSC_COMM_WORLD,"User explicitly sets subdomain solvers.\n");CHKERRQ(ierr);
  183. /*
  184. Set runtime options
  185. */
  186. ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr);
  187. /*
  188. Flag an error if PCTYPE is changed from the runtime options
  189. */
  190. ierr = PetscObjectTypeCompare((PetscObject)pc,PCASM,&isasm);CHKERRQ(ierr);
  191. if (!isasm) SETERRQ(PETSC_COMM_WORLD,1,"Cannot Change the PCTYPE when manually changing the subdomain solver settings");
  192. /*
  193. Call KSPSetUp() to set the block Jacobi data structures (including
  194. creation of an internal KSP context for each block).
  195. Note: KSPSetUp() MUST be called before PCASMGetSubKSP().
  196. */
  197. ierr = KSPSetUp(ksp);CHKERRQ(ierr);
  198. /*
  199. Extract the array of KSP contexts for the local blocks
  200. */
  201. ierr = PCASMGetSubKSP(pc,&nlocal,&first,&subksp);CHKERRQ(ierr);
  202. /*
  203. Loop over the local blocks, setting various KSP options
  204. for each block.
  205. */
  206. for (i=0; i<nlocal; i++) {
  207. ierr = KSPGetPC(subksp[i],&subpc);CHKERRQ(ierr);
  208. ierr = PCSetType(subpc,PCILU);CHKERRQ(ierr);
  209. ierr = KSPSetType(subksp[i],KSPGMRES);CHKERRQ(ierr);
  210. ierr = KSPSetTolerances(subksp[i],1.e-7,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr);
  211. }
  212. } else {
  213. /*
  214. Set runtime options
  215. */
  216. ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr);
  217. }
  218. /* -------------------------------------------------------------------
  219. Solve the linear system
  220. ------------------------------------------------------------------- */
  221. ierr = KSPSolve(ksp,b,x);CHKERRQ(ierr);
  222. /* -------------------------------------------------------------------
  223. Compare result to the exact solution
  224. ------------------------------------------------------------------- */
  225. ierr = VecAXPY(x,-1.0,u);CHKERRQ(ierr);
  226. ierr = VecNorm(x,NORM_INFINITY, &e);CHKERRQ(ierr);
  227. flg = PETSC_FALSE;
  228. ierr = PetscOptionsGetBool(NULL,"-print_error",&flg,NULL);CHKERRQ(ierr);
  229. if (flg) {
  230. ierr = PetscPrintf(PETSC_COMM_WORLD, "Infinity norm of the error: %G\n", e);CHKERRQ(ierr);
  231. }
  232. /*
  233. Free work space. All PETSc objects should be destroyed when they
  234. are no longer needed.
  235. */
  236. if (user_subdomains) {
  237. for (i=0; i<Nsub; i++) {
  238. ierr = ISDestroy(&is[i]);CHKERRQ(ierr);
  239. ierr = ISDestroy(&is_local[i]);CHKERRQ(ierr);
  240. }
  241. ierr = PetscFree(is);CHKERRQ(ierr);
  242. ierr = PetscFree(is_local);CHKERRQ(ierr);
  243. }
  244. ierr = KSPDestroy(&ksp);CHKERRQ(ierr);
  245. ierr = VecDestroy(&u);CHKERRQ(ierr);
  246. ierr = VecDestroy(&x);CHKERRQ(ierr);
  247. ierr = VecDestroy(&b);CHKERRQ(ierr);
  248. ierr = MatDestroy(&A);CHKERRQ(ierr);
  249. ierr = PetscFinalize();
  250. return 0;
  251. }