1c4762a1bSJed Brown 2c4762a1bSJed Brown static char help[] ="Solves the time independent Bratu problem using pseudo-timestepping."; 3c4762a1bSJed Brown 4c4762a1bSJed Brown /* 5c4762a1bSJed Brown Concepts: TS^pseudo-timestepping 6ee300463SSatish Balay Concepts: TS^pseudo-timestepping 7c4762a1bSJed Brown Concepts: TS^nonlinear problems 8c4762a1bSJed Brown Processors: 1 9c4762a1bSJed Brown 10c4762a1bSJed Brown */ 11c4762a1bSJed Brown 12c4762a1bSJed Brown /* ------------------------------------------------------------------------ 13c4762a1bSJed Brown 14c4762a1bSJed Brown This code demonstrates how one may solve a nonlinear problem 15c4762a1bSJed Brown with pseudo-timestepping. In this simple example, the pseudo-timestep 16c4762a1bSJed Brown is the same for all grid points, i.e., this is equivalent to using 17c4762a1bSJed Brown the backward Euler method with a variable timestep. 18c4762a1bSJed Brown 19c4762a1bSJed Brown Note: This example does not require pseudo-timestepping since it 20c4762a1bSJed Brown is an easy nonlinear problem, but it is included to demonstrate how 21c4762a1bSJed Brown the pseudo-timestepping may be done. 22c4762a1bSJed Brown 23c4762a1bSJed Brown See snes/tutorials/ex4.c[ex4f.F] and 24c4762a1bSJed Brown snes/tutorials/ex5.c[ex5f.F] where the problem is described 25c4762a1bSJed Brown and solved using Newton's method alone. 26c4762a1bSJed Brown 27c4762a1bSJed Brown ----------------------------------------------------------------------------- */ 28c4762a1bSJed Brown /* 29c4762a1bSJed Brown Include "petscts.h" to use the PETSc timestepping routines. Note that 30c4762a1bSJed Brown this file automatically includes "petscsys.h" and other lower-level 31c4762a1bSJed Brown PETSc include files. 32c4762a1bSJed Brown */ 33c4762a1bSJed Brown #include <petscts.h> 34c4762a1bSJed Brown 35c4762a1bSJed Brown /* 36c4762a1bSJed Brown Create an application context to contain data needed by the 37c4762a1bSJed Brown application-provided call-back routines, FormJacobian() and 38c4762a1bSJed Brown FormFunction(). 39c4762a1bSJed Brown */ 40c4762a1bSJed Brown typedef struct { 41c4762a1bSJed Brown PetscReal param; /* test problem parameter */ 42c4762a1bSJed Brown PetscInt mx; /* Discretization in x-direction */ 43c4762a1bSJed Brown PetscInt my; /* Discretization in y-direction */ 44c4762a1bSJed Brown } AppCtx; 45c4762a1bSJed Brown 46c4762a1bSJed Brown /* 47c4762a1bSJed Brown User-defined routines 48c4762a1bSJed Brown */ 49c4762a1bSJed Brown extern PetscErrorCode FormJacobian(TS,PetscReal,Vec,Mat,Mat,void*), FormFunction(TS,PetscReal,Vec,Vec,void*), FormInitialGuess(Vec,AppCtx*); 50c4762a1bSJed Brown 51c4762a1bSJed Brown int main(int argc,char **argv) 52c4762a1bSJed Brown { 53c4762a1bSJed Brown TS ts; /* timestepping context */ 54c4762a1bSJed Brown Vec x,r; /* solution, residual vectors */ 55c4762a1bSJed Brown Mat J; /* Jacobian matrix */ 56c4762a1bSJed Brown AppCtx user; /* user-defined work context */ 57c4762a1bSJed Brown PetscInt its,N; /* iterations for convergence */ 58c4762a1bSJed Brown PetscReal param_max = 6.81,param_min = 0.,dt; 59c4762a1bSJed Brown PetscReal ftime; 60c4762a1bSJed Brown PetscMPIInt size; 61c4762a1bSJed Brown 62*b122ec5aSJacob Faibussowitsch CHKERRQ(PetscInitialize(&argc,&argv,NULL,help)); 635f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size)); 643c633725SBarry Smith PetscCheck(size == 1,PETSC_COMM_WORLD,PETSC_ERR_WRONG_MPI_SIZE,"This is a uniprocessor example only"); 65c4762a1bSJed Brown 66c4762a1bSJed Brown user.mx = 4; 67c4762a1bSJed Brown user.my = 4; 68c4762a1bSJed Brown user.param = 6.0; 69c4762a1bSJed Brown 70c4762a1bSJed Brown /* 71c4762a1bSJed Brown Allow user to set the grid dimensions and nonlinearity parameter at run-time 72c4762a1bSJed Brown */ 73c4762a1bSJed Brown PetscOptionsGetInt(NULL,NULL,"-mx",&user.mx,NULL); 74c4762a1bSJed Brown PetscOptionsGetInt(NULL,NULL,"-my",&user.my,NULL); 75c4762a1bSJed Brown N = user.mx*user.my; 76c4762a1bSJed Brown dt = .5/PetscMax(user.mx,user.my); 77c4762a1bSJed Brown PetscOptionsGetReal(NULL,NULL,"-param",&user.param,NULL); 783c633725SBarry Smith PetscCheck(user.param < param_max && user.param >= param_min,PETSC_COMM_WORLD,PETSC_ERR_ARG_OUTOFRANGE,"Parameter is out of range"); 79c4762a1bSJed Brown 80c4762a1bSJed Brown /* 81c4762a1bSJed Brown Create vectors to hold the solution and function value 82c4762a1bSJed Brown */ 835f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateSeq(PETSC_COMM_SELF,N,&x)); 845f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(x,&r)); 85c4762a1bSJed Brown 86c4762a1bSJed Brown /* 87c4762a1bSJed Brown Create matrix to hold Jacobian. Preallocate 5 nonzeros per row 88c4762a1bSJed Brown in the sparse matrix. Note that this is not the optimal strategy; see 89c4762a1bSJed Brown the Performance chapter of the users manual for information on 90c4762a1bSJed Brown preallocating memory in sparse matrices. 91c4762a1bSJed Brown */ 925f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqAIJ(PETSC_COMM_SELF,N,N,5,0,&J)); 93c4762a1bSJed Brown 94c4762a1bSJed Brown /* 95c4762a1bSJed Brown Create timestepper context 96c4762a1bSJed Brown */ 975f80ce2aSJacob Faibussowitsch CHKERRQ(TSCreate(PETSC_COMM_WORLD,&ts)); 985f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetProblemType(ts,TS_NONLINEAR)); 99c4762a1bSJed Brown 100c4762a1bSJed Brown /* 101c4762a1bSJed Brown Tell the timestepper context where to compute solutions 102c4762a1bSJed Brown */ 1035f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetSolution(ts,x)); 104c4762a1bSJed Brown 105c4762a1bSJed Brown /* 106c4762a1bSJed Brown Provide the call-back for the nonlinear function we are 107c4762a1bSJed Brown evaluating. Thus whenever the timestepping routines need the 108c4762a1bSJed Brown function they will call this routine. Note the final argument 109c4762a1bSJed Brown is the application context used by the call-back functions. 110c4762a1bSJed Brown */ 1115f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetRHSFunction(ts,NULL,FormFunction,&user)); 112c4762a1bSJed Brown 113c4762a1bSJed Brown /* 114c4762a1bSJed Brown Set the Jacobian matrix and the function used to compute 115c4762a1bSJed Brown Jacobians. 116c4762a1bSJed Brown */ 1175f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetRHSJacobian(ts,J,J,FormJacobian,&user)); 118c4762a1bSJed Brown 119c4762a1bSJed Brown /* 120c4762a1bSJed Brown Form the initial guess for the problem 121c4762a1bSJed Brown */ 1225f80ce2aSJacob Faibussowitsch CHKERRQ(FormInitialGuess(x,&user)); 123c4762a1bSJed Brown 124c4762a1bSJed Brown /* 125c4762a1bSJed Brown This indicates that we are using pseudo timestepping to 126c4762a1bSJed Brown find a steady state solution to the nonlinear problem. 127c4762a1bSJed Brown */ 1285f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetType(ts,TSPSEUDO)); 129c4762a1bSJed Brown 130c4762a1bSJed Brown /* 131c4762a1bSJed Brown Set the initial time to start at (this is arbitrary for 132c4762a1bSJed Brown steady state problems); and the initial timestep given above 133c4762a1bSJed Brown */ 1345f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetTimeStep(ts,dt)); 135c4762a1bSJed Brown 136c4762a1bSJed Brown /* 137c4762a1bSJed Brown Set a large number of timesteps and final duration time 138c4762a1bSJed Brown to insure convergence to steady state. 139c4762a1bSJed Brown */ 1405f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetMaxSteps(ts,10000)); 1415f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetMaxTime(ts,1e12)); 1425f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetExactFinalTime(ts,TS_EXACTFINALTIME_STEPOVER)); 143c4762a1bSJed Brown 144c4762a1bSJed Brown /* 145c4762a1bSJed Brown Use the default strategy for increasing the timestep 146c4762a1bSJed Brown */ 1475f80ce2aSJacob Faibussowitsch CHKERRQ(TSPseudoSetTimeStep(ts,TSPseudoTimeStepDefault,0)); 148c4762a1bSJed Brown 149c4762a1bSJed Brown /* 150c4762a1bSJed Brown Set any additional options from the options database. This 151c4762a1bSJed Brown includes all options for the nonlinear and linear solvers used 152c4762a1bSJed Brown internally the timestepping routines. 153c4762a1bSJed Brown */ 1545f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetFromOptions(ts)); 155c4762a1bSJed Brown 1565f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetUp(ts)); 157c4762a1bSJed Brown 158c4762a1bSJed Brown /* 159c4762a1bSJed Brown Perform the solve. This is where the timestepping takes place. 160c4762a1bSJed Brown */ 1615f80ce2aSJacob Faibussowitsch CHKERRQ(TSSolve(ts,x)); 1625f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetSolveTime(ts,&ftime)); 163c4762a1bSJed Brown 164c4762a1bSJed Brown /* 165c4762a1bSJed Brown Get the number of steps 166c4762a1bSJed Brown */ 1675f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetStepNumber(ts,&its)); 168c4762a1bSJed Brown 1695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"Number of pseudo timesteps = %D final time %4.2e\n",its,(double)ftime)); 170c4762a1bSJed Brown 171c4762a1bSJed Brown /* 172c4762a1bSJed Brown Free the data structures constructed above 173c4762a1bSJed Brown */ 1745f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&x)); 1755f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&r)); 1765f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&J)); 1775f80ce2aSJacob Faibussowitsch CHKERRQ(TSDestroy(&ts)); 178*b122ec5aSJacob Faibussowitsch CHKERRQ(PetscFinalize()); 179*b122ec5aSJacob Faibussowitsch return 0; 180c4762a1bSJed Brown } 181c4762a1bSJed Brown /* ------------------------------------------------------------------ */ 182c4762a1bSJed Brown /* Bratu (Solid Fuel Ignition) Test Problem */ 183c4762a1bSJed Brown /* ------------------------------------------------------------------ */ 184c4762a1bSJed Brown 185c4762a1bSJed Brown /* -------------------- Form initial approximation ----------------- */ 186c4762a1bSJed Brown 187c4762a1bSJed Brown PetscErrorCode FormInitialGuess(Vec X,AppCtx *user) 188c4762a1bSJed Brown { 189c4762a1bSJed Brown PetscInt i,j,row,mx,my; 190c4762a1bSJed Brown PetscReal one = 1.0,lambda; 191c4762a1bSJed Brown PetscReal temp1,temp,hx,hy; 192c4762a1bSJed Brown PetscScalar *x; 193c4762a1bSJed Brown 194c4762a1bSJed Brown mx = user->mx; 195c4762a1bSJed Brown my = user->my; 196c4762a1bSJed Brown lambda = user->param; 197c4762a1bSJed Brown 198c4762a1bSJed Brown hx = one / (PetscReal)(mx-1); 199c4762a1bSJed Brown hy = one / (PetscReal)(my-1); 200c4762a1bSJed Brown 2015f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(X,&x)); 202c4762a1bSJed Brown temp1 = lambda/(lambda + one); 203c4762a1bSJed Brown for (j=0; j<my; j++) { 204c4762a1bSJed Brown temp = (PetscReal)(PetscMin(j,my-j-1))*hy; 205c4762a1bSJed Brown for (i=0; i<mx; i++) { 206c4762a1bSJed Brown row = i + j*mx; 207c4762a1bSJed Brown if (i == 0 || j == 0 || i == mx-1 || j == my-1) { 208c4762a1bSJed Brown x[row] = 0.0; 209c4762a1bSJed Brown continue; 210c4762a1bSJed Brown } 211c4762a1bSJed Brown x[row] = temp1*PetscSqrtReal(PetscMin((PetscReal)(PetscMin(i,mx-i-1))*hx,temp)); 212c4762a1bSJed Brown } 213c4762a1bSJed Brown } 2145f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(X,&x)); 215c4762a1bSJed Brown return 0; 216c4762a1bSJed Brown } 217c4762a1bSJed Brown /* -------------------- Evaluate Function F(x) --------------------- */ 218c4762a1bSJed Brown 219c4762a1bSJed Brown PetscErrorCode FormFunction(TS ts,PetscReal t,Vec X,Vec F,void *ptr) 220c4762a1bSJed Brown { 221c4762a1bSJed Brown AppCtx *user = (AppCtx*)ptr; 222c4762a1bSJed Brown PetscInt i,j,row,mx,my; 223c4762a1bSJed Brown PetscReal two = 2.0,one = 1.0,lambda; 224c4762a1bSJed Brown PetscReal hx,hy,hxdhy,hydhx; 225c4762a1bSJed Brown PetscScalar ut,ub,ul,ur,u,uxx,uyy,sc,*f; 226c4762a1bSJed Brown const PetscScalar *x; 227c4762a1bSJed Brown 228c4762a1bSJed Brown mx = user->mx; 229c4762a1bSJed Brown my = user->my; 230c4762a1bSJed Brown lambda = user->param; 231c4762a1bSJed Brown 232c4762a1bSJed Brown hx = one / (PetscReal)(mx-1); 233c4762a1bSJed Brown hy = one / (PetscReal)(my-1); 234c4762a1bSJed Brown sc = hx*hy; 235c4762a1bSJed Brown hxdhy = hx/hy; 236c4762a1bSJed Brown hydhx = hy/hx; 237c4762a1bSJed Brown 2385f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(X,&x)); 2395f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(F,&f)); 240c4762a1bSJed Brown for (j=0; j<my; j++) { 241c4762a1bSJed Brown for (i=0; i<mx; i++) { 242c4762a1bSJed Brown row = i + j*mx; 243c4762a1bSJed Brown if (i == 0 || j == 0 || i == mx-1 || j == my-1) { 244c4762a1bSJed Brown f[row] = x[row]; 245c4762a1bSJed Brown continue; 246c4762a1bSJed Brown } 247c4762a1bSJed Brown u = x[row]; 248c4762a1bSJed Brown ub = x[row - mx]; 249c4762a1bSJed Brown ul = x[row - 1]; 250c4762a1bSJed Brown ut = x[row + mx]; 251c4762a1bSJed Brown ur = x[row + 1]; 252c4762a1bSJed Brown uxx = (-ur + two*u - ul)*hydhx; 253c4762a1bSJed Brown uyy = (-ut + two*u - ub)*hxdhy; 254c4762a1bSJed Brown f[row] = -uxx + -uyy + sc*lambda*PetscExpScalar(u); 255c4762a1bSJed Brown } 256c4762a1bSJed Brown } 2575f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(X,&x)); 2585f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(F,&f)); 259c4762a1bSJed Brown return 0; 260c4762a1bSJed Brown } 261c4762a1bSJed Brown /* -------------------- Evaluate Jacobian F'(x) -------------------- */ 262c4762a1bSJed Brown 263c4762a1bSJed Brown /* 264c4762a1bSJed Brown Calculate the Jacobian matrix J(X,t). 265c4762a1bSJed Brown 266c4762a1bSJed Brown Note: We put the Jacobian in the preconditioner storage B instead of J. This 267c4762a1bSJed Brown way we can give the -snes_mf_operator flag to check our work. This replaces 268c4762a1bSJed Brown J with a finite difference approximation, using our analytic Jacobian B for 269c4762a1bSJed Brown the preconditioner. 270c4762a1bSJed Brown */ 271c4762a1bSJed Brown PetscErrorCode FormJacobian(TS ts,PetscReal t,Vec X,Mat J,Mat B,void *ptr) 272c4762a1bSJed Brown { 273c4762a1bSJed Brown AppCtx *user = (AppCtx*)ptr; 274c4762a1bSJed Brown PetscInt i,j,row,mx,my,col[5]; 275c4762a1bSJed Brown PetscScalar two = 2.0,one = 1.0,lambda,v[5],sc; 276c4762a1bSJed Brown const PetscScalar *x; 277c4762a1bSJed Brown PetscReal hx,hy,hxdhy,hydhx; 278c4762a1bSJed Brown 279c4762a1bSJed Brown mx = user->mx; 280c4762a1bSJed Brown my = user->my; 281c4762a1bSJed Brown lambda = user->param; 282c4762a1bSJed Brown 283c4762a1bSJed Brown hx = 1.0 / (PetscReal)(mx-1); 284c4762a1bSJed Brown hy = 1.0 / (PetscReal)(my-1); 285c4762a1bSJed Brown sc = hx*hy; 286c4762a1bSJed Brown hxdhy = hx/hy; 287c4762a1bSJed Brown hydhx = hy/hx; 288c4762a1bSJed Brown 2895f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(X,&x)); 290c4762a1bSJed Brown for (j=0; j<my; j++) { 291c4762a1bSJed Brown for (i=0; i<mx; i++) { 292c4762a1bSJed Brown row = i + j*mx; 293c4762a1bSJed Brown if (i == 0 || j == 0 || i == mx-1 || j == my-1) { 2945f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(B,1,&row,1,&row,&one,INSERT_VALUES)); 295c4762a1bSJed Brown continue; 296c4762a1bSJed Brown } 297c4762a1bSJed Brown v[0] = hxdhy; col[0] = row - mx; 298c4762a1bSJed Brown v[1] = hydhx; col[1] = row - 1; 299c4762a1bSJed Brown v[2] = -two*(hydhx + hxdhy) + sc*lambda*PetscExpScalar(x[row]); col[2] = row; 300c4762a1bSJed Brown v[3] = hydhx; col[3] = row + 1; 301c4762a1bSJed Brown v[4] = hxdhy; col[4] = row + mx; 3025f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(B,1,&row,5,col,v,INSERT_VALUES)); 303c4762a1bSJed Brown } 304c4762a1bSJed Brown } 3055f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(X,&x)); 3065f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY)); 3075f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY)); 308c4762a1bSJed Brown if (J != B) { 3095f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY)); 3105f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY)); 311c4762a1bSJed Brown } 312c4762a1bSJed Brown return 0; 313c4762a1bSJed Brown } 314c4762a1bSJed Brown 315c4762a1bSJed Brown /*TEST 316c4762a1bSJed Brown 317c4762a1bSJed Brown test: 318c4762a1bSJed Brown args: -ksp_gmres_cgs_refinement_type refine_always -snes_type newtonls -ts_monitor_pseudo -snes_atol 1.e-7 -ts_pseudo_frtol 1.e-5 -ts_view draw:tikz:fig.tex 319c4762a1bSJed Brown 320c4762a1bSJed Brown test: 321c4762a1bSJed Brown suffix: 2 322c4762a1bSJed Brown args: -ts_monitor_pseudo -ts_pseudo_frtol 1.e-5 323c4762a1bSJed Brown 324c4762a1bSJed Brown TEST*/ 325