PageRenderTime 50ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/src/ts/examples/tutorials/ex17.c

https://bitbucket.org/karpeev/petsc
C | 306 lines | 195 code | 41 blank | 70 comment | 45 complexity | 9b7b1ec59d69d1dfd69ca6664e0f7957 MD5 | raw file
  1. static const char help[] = "Time-dependent PDE in 1d. Simplified from ex15.c for illustrating how to solve DAEs. \n";
  2. /*
  3. u_t = uxx
  4. 0 < x < 1;
  5. At t=0: u(x) = exp(c*r*r*r), if r=PetscSqrtReal((x-.5)*(x-.5)) < .125
  6. u(x) = 0.0 if r >= .125
  7. Boundary conditions:
  8. Dirichlet BC:
  9. At x=0, x=1, u = 0.0
  10. Neumann BC:
  11. At x=0, x=1: du(x,t)/dx = 0
  12. mpiexec -n 2 ./ex17 -da_grid_x 40 -ts_max_steps 2 -snes_monitor -ksp_monitor
  13. ./ex17 -da_grid_x 40 -monitor_solution
  14. ./ex17 -da_grid_x 100 -ts_type theta -ts_theta_theta 0.5 # Midpoint is not L-stable
  15. ./ex17 -jac_type fd_coloring -da_grid_x 500 -boundary 1
  16. ./ex17 -da_grid_x 100 -ts_type gl -ts_adapt_type none -ts_max_steps 2
  17. */
  18. #include <petscdm.h>
  19. #include <petscdmda.h>
  20. #include <petscts.h>
  21. typedef enum {JACOBIAN_ANALYTIC,JACOBIAN_FD_COLORING,JACOBIAN_FD_FULL} JacobianType;
  22. static const char *const JacobianTypes[] = {"analytic","fd_coloring","fd_full","JacobianType","fd_",0};
  23. /*
  24. User-defined data structures and routines
  25. */
  26. typedef struct {
  27. PetscReal c;
  28. PetscInt boundary; /* Type of boundary condition */
  29. PetscBool viewJacobian;
  30. } AppCtx;
  31. static PetscErrorCode FormIFunction(TS,PetscReal,Vec,Vec,Vec,void*);
  32. static PetscErrorCode FormIJacobian(TS,PetscReal,Vec,Vec,PetscReal,Mat,Mat,void*);
  33. static PetscErrorCode FormInitialSolution(TS,Vec,void*);
  34. #undef __FUNCT__
  35. #define __FUNCT__ "main"
  36. int main(int argc,char **argv)
  37. {
  38. TS ts; /* nonlinear solver */
  39. Vec u; /* solution, residual vectors */
  40. Mat J; /* Jacobian matrix */
  41. PetscInt maxsteps = 1000; /* iterations for convergence */
  42. PetscInt nsteps;
  43. PetscReal vmin,vmax,norm;
  44. PetscErrorCode ierr;
  45. DM da;
  46. PetscReal ftime,dt;
  47. AppCtx user; /* user-defined work context */
  48. JacobianType jacType;
  49. PetscInitialize(&argc,&argv,(char*)0,help);
  50. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  51. Create distributed array (DMDA) to manage parallel grid and vectors
  52. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  53. ierr = DMDACreate1d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,-11,1,1,NULL,&da);CHKERRQ(ierr);
  54. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  55. Extract global vectors from DMDA;
  56. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  57. ierr = DMCreateGlobalVector(da,&u);CHKERRQ(ierr);
  58. /* Initialize user application context */
  59. user.c = -30.0;
  60. user.boundary = 0; /* 0: Dirichlet BC; 1: Neumann BC */
  61. user.viewJacobian = PETSC_FALSE;
  62. ierr = PetscOptionsGetInt(NULL,"-boundary",&user.boundary,NULL);CHKERRQ(ierr);
  63. ierr = PetscOptionsHasName(NULL,"-viewJacobian",&user.viewJacobian);CHKERRQ(ierr);
  64. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  65. Create timestepping solver context
  66. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  67. ierr = TSCreate(PETSC_COMM_WORLD,&ts);CHKERRQ(ierr);
  68. ierr = TSSetProblemType(ts,TS_NONLINEAR);CHKERRQ(ierr);
  69. ierr = TSSetType(ts,TSTHETA);CHKERRQ(ierr);
  70. ierr = TSThetaSetTheta(ts,1.0);CHKERRQ(ierr); /* Make the Theta method behave like backward Euler */
  71. ierr = TSSetIFunction(ts,NULL,FormIFunction,&user);CHKERRQ(ierr);
  72. ierr = DMSetMatType(da,MATAIJ);CHKERRQ(ierr);
  73. ierr = DMCreateMatrix(da,&J);CHKERRQ(ierr);
  74. jacType = JACOBIAN_ANALYTIC; /* use user-provide Jacobian */
  75. ierr = TSSetDM(ts,da);CHKERRQ(ierr); /* Use TSGetDM() to access. Setting here allows easy use of geometric multigrid. */
  76. ftime = 1.0;
  77. ierr = TSSetDuration(ts,maxsteps,ftime);CHKERRQ(ierr);
  78. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  79. Set initial conditions
  80. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  81. ierr = FormInitialSolution(ts,u,&user);CHKERRQ(ierr);
  82. ierr = TSSetSolution(ts,u);CHKERRQ(ierr);
  83. dt = .01;
  84. ierr = TSSetInitialTimeStep(ts,0.0,dt);CHKERRQ(ierr);
  85. /* Use slow fd Jacobian or fast fd Jacobian with colorings.
  86. Note: this requirs snes which is not created until TSSetUp()/TSSetFromOptions() is called */
  87. ierr = PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"Options for Jacobian evaluation",NULL);CHKERRQ(ierr);
  88. ierr = PetscOptionsEnum("-jac_type","Type of Jacobian","",JacobianTypes,(PetscEnum)jacType,(PetscEnum*)&jacType,0);CHKERRQ(ierr);
  89. ierr = PetscOptionsEnd();CHKERRQ(ierr);
  90. if (jacType == JACOBIAN_ANALYTIC) {
  91. ierr = TSSetIJacobian(ts,J,J,FormIJacobian,&user);CHKERRQ(ierr);
  92. } else if (jacType == JACOBIAN_FD_COLORING) {
  93. SNES snes;
  94. ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
  95. ierr = SNESSetJacobian(snes,J,J,SNESComputeJacobianDefaultColor,0);CHKERRQ(ierr);
  96. } else if (jacType == JACOBIAN_FD_FULL) {
  97. SNES snes;
  98. ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
  99. ierr = SNESSetJacobian(snes,J,J,SNESComputeJacobianDefault,&user);CHKERRQ(ierr);
  100. }
  101. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  102. Set runtime options
  103. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  104. ierr = TSSetFromOptions(ts);CHKERRQ(ierr);
  105. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  106. Integrate ODE system
  107. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  108. ierr = TSSolve(ts,u);CHKERRQ(ierr);
  109. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  110. Compute diagnostics of the solution
  111. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  112. ierr = VecNorm(u,NORM_1,&norm);CHKERRQ(ierr);
  113. ierr = VecMax(u,NULL,&vmax);CHKERRQ(ierr);
  114. ierr = VecMin(u,NULL,&vmin);CHKERRQ(ierr);
  115. ierr = TSGetTimeStepNumber(ts,&nsteps);CHKERRQ(ierr);
  116. ierr = TSGetTime(ts,&ftime);CHKERRQ(ierr);
  117. ierr = PetscPrintf(PETSC_COMM_WORLD,"timestep %D: time %g, solution norm %g, max %g, min %g\n",nsteps,(double)ftime,(double)norm,(double)vmax,(double)vmin);CHKERRQ(ierr);
  118. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  119. Free work space.
  120. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  121. ierr = MatDestroy(&J);CHKERRQ(ierr);
  122. ierr = VecDestroy(&u);CHKERRQ(ierr);
  123. ierr = TSDestroy(&ts);CHKERRQ(ierr);
  124. ierr = DMDestroy(&da);CHKERRQ(ierr);
  125. ierr = PetscFinalize();
  126. PetscFunctionReturn(0);
  127. }
  128. /* ------------------------------------------------------------------- */
  129. #undef __FUNCT__
  130. #define __FUNCT__ "FormIFunction"
  131. static PetscErrorCode FormIFunction(TS ts,PetscReal ftime,Vec U,Vec Udot,Vec F,void *ptr)
  132. {
  133. AppCtx *user=(AppCtx*)ptr;
  134. DM da;
  135. PetscErrorCode ierr;
  136. PetscInt i,Mx,xs,xm;
  137. PetscReal hx,sx;
  138. PetscScalar *u,*udot,*f;
  139. Vec localU;
  140. PetscFunctionBeginUser;
  141. ierr = TSGetDM(ts,&da);CHKERRQ(ierr);
  142. ierr = DMGetLocalVector(da,&localU);CHKERRQ(ierr);
  143. ierr = DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,
  144. PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);
  145. hx = 1.0/(PetscReal)(Mx-1); sx = 1.0/(hx*hx);
  146. /*
  147. Scatter ghost points to local vector,using the 2-step process
  148. DMGlobalToLocalBegin(),DMGlobalToLocalEnd().
  149. By placing code between these two statements, computations can be
  150. done while messages are in transition.
  151. */
  152. ierr = DMGlobalToLocalBegin(da,U,INSERT_VALUES,localU);CHKERRQ(ierr);
  153. ierr = DMGlobalToLocalEnd(da,U,INSERT_VALUES,localU);CHKERRQ(ierr);
  154. /* Get pointers to vector data */
  155. ierr = DMDAVecGetArrayRead(da,localU,&u);CHKERRQ(ierr);
  156. ierr = DMDAVecGetArrayRead(da,Udot,&udot);CHKERRQ(ierr);
  157. ierr = DMDAVecGetArray(da,F,&f);CHKERRQ(ierr);
  158. /* Get local grid boundaries */
  159. ierr = DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);CHKERRQ(ierr);
  160. /* Compute function over the locally owned part of the grid */
  161. for (i=xs; i<xs+xm; i++) {
  162. if (user->boundary == 0) { /* Dirichlet BC */
  163. if (i == 0 || i == Mx-1) f[i] = u[i]; /* F = U */
  164. else f[i] = udot[i] + (2.*u[i] - u[i-1] - u[i+1])*sx;
  165. } else { /* Neumann BC */
  166. if (i == 0) f[i] = u[0] - u[1];
  167. else if (i == Mx-1) f[i] = u[i] - u[i-1];
  168. else f[i] = udot[i] + (2.*u[i] - u[i-1] - u[i+1])*sx;
  169. }
  170. }
  171. /* Restore vectors */
  172. ierr = DMDAVecRestoreArrayRead(da,localU,&u);CHKERRQ(ierr);
  173. ierr = DMDAVecRestoreArrayRead(da,Udot,&udot);CHKERRQ(ierr);
  174. ierr = DMDAVecRestoreArray(da,F,&f);CHKERRQ(ierr);
  175. ierr = DMRestoreLocalVector(da,&localU);CHKERRQ(ierr);
  176. PetscFunctionReturn(0);
  177. }
  178. /* --------------------------------------------------------------------- */
  179. /*
  180. IJacobian - Compute IJacobian = dF/dU + a dF/dUdot
  181. */
  182. #undef __FUNCT__
  183. #define __FUNCT__ "FormIJacobian"
  184. PetscErrorCode FormIJacobian(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal a,Mat J,Mat Jpre,void *ctx)
  185. {
  186. PetscErrorCode ierr;
  187. PetscInt i,rstart,rend,Mx;
  188. PetscReal hx,sx;
  189. AppCtx *user = (AppCtx*)ctx;
  190. DM da;
  191. MatStencil col[3],row;
  192. PetscInt nc;
  193. PetscScalar vals[3];
  194. PetscFunctionBeginUser;
  195. ierr = TSGetDM(ts,&da);CHKERRQ(ierr);
  196. ierr = MatGetOwnershipRange(Jpre,&rstart,&rend);CHKERRQ(ierr);
  197. ierr = DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,
  198. PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);
  199. hx = 1.0/(PetscReal)(Mx-1); sx = 1.0/(hx*hx);
  200. for (i=rstart; i<rend; i++) {
  201. nc = 0;
  202. row.i = i;
  203. if (user->boundary == 0 && (i == 0 || i == Mx-1)) {
  204. col[nc].i = i; vals[nc++] = 1.0;
  205. } else if (user->boundary > 0 && i == 0) { /* Left Neumann */
  206. col[nc].i = i; vals[nc++] = 1.0;
  207. col[nc].i = i+1; vals[nc++] = -1.0;
  208. } else if (user->boundary > 0 && i == Mx-1) { /* Right Neumann */
  209. col[nc].i = i-1; vals[nc++] = -1.0;
  210. col[nc].i = i; vals[nc++] = 1.0;
  211. } else { /* Interior */
  212. col[nc].i = i-1; vals[nc++] = -1.0*sx;
  213. col[nc].i = i; vals[nc++] = 2.0*sx + a;
  214. col[nc].i = i+1; vals[nc++] = -1.0*sx;
  215. }
  216. ierr = MatSetValuesStencil(Jpre,1,&row,nc,col,vals,INSERT_VALUES);CHKERRQ(ierr);
  217. }
  218. ierr = MatAssemblyBegin(Jpre,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
  219. ierr = MatAssemblyEnd(Jpre,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
  220. if (J != Jpre) {
  221. ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
  222. ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
  223. }
  224. if (user->viewJacobian) {
  225. ierr = PetscPrintf(PETSC_COMM_WORLD,"Jpre:\n");CHKERRQ(ierr);
  226. ierr = MatView(Jpre,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
  227. }
  228. PetscFunctionReturn(0);
  229. }
  230. /* ------------------------------------------------------------------- */
  231. #undef __FUNCT__
  232. #define __FUNCT__ "FormInitialSolution"
  233. PetscErrorCode FormInitialSolution(TS ts,Vec U,void *ptr)
  234. {
  235. AppCtx *user=(AppCtx*)ptr;
  236. PetscReal c =user->c;
  237. DM da;
  238. PetscErrorCode ierr;
  239. PetscInt i,xs,xm,Mx;
  240. PetscScalar *u;
  241. PetscReal hx,x,r;
  242. PetscFunctionBeginUser;
  243. ierr = TSGetDM(ts,&da);CHKERRQ(ierr);
  244. ierr = DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,
  245. PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);
  246. hx = 1.0/(PetscReal)(Mx-1);
  247. /* Get pointers to vector data */
  248. ierr = DMDAVecGetArray(da,U,&u);CHKERRQ(ierr);
  249. /* Get local grid boundaries */
  250. ierr = DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);CHKERRQ(ierr);
  251. /* Compute function over the locally owned part of the grid */
  252. for (i=xs; i<xs+xm; i++) {
  253. x = i*hx;
  254. r = PetscSqrtReal((x-.5)*(x-.5));
  255. if (r < .125) u[i] = PetscExpReal(c*r*r*r);
  256. else u[i] = 0.0;
  257. }
  258. /* Restore vectors */
  259. ierr = DMDAVecRestoreArray(da,U,&u);CHKERRQ(ierr);
  260. PetscFunctionReturn(0);
  261. }