/* The Problem: Solve the convection-diffusion equation: u_t+a*(u_x+u_y)=epsilon*(u_xx+u_yy) u=0 at x=0, y=0 u_x=0 at x=1 u_y=0 at y=1 u = exp(-20.0*(pow(x-0.5,2.0)+pow(y-0.5,2.0))) at t=0 This program tests the routine of computing the Jacobian by the finite difference method as well as PETSc. */ static char help[] = "Solve the convection-diffusion equation. \n\n"; #include typedef struct { PetscInt m; /* the number of mesh points in x-direction */ PetscInt n; /* the number of mesh points in y-direction */ PetscReal dx; /* the grid space in x-direction */ PetscReal dy; /* the grid space in y-direction */ PetscReal a; /* the convection coefficient */ PetscReal epsilon; /* the diffusion coefficient */ PetscReal tfinal; } Data; extern PetscErrorCode Monitor(TS,PetscInt,PetscReal,Vec,void*); extern PetscErrorCode Initial(Vec,void*); extern PetscErrorCode RHSFunction(TS,PetscReal,Vec,Vec,void*); extern PetscErrorCode RHSJacobian(TS,PetscReal,Vec,Mat,Mat,void*); extern PetscErrorCode PostStep(TS); int main(int argc,char **argv) { PetscErrorCode ierr; PetscInt time_steps=100,iout,NOUT=1; Vec global; PetscReal dt,ftime,ftime_original; TS ts; PetscViewer viewfile; Mat J = 0; Vec x; Data data; PetscInt mn; PetscBool flg; MatColoring mc; ISColoring iscoloring; MatFDColoring matfdcoloring = 0; PetscBool fd_jacobian_coloring = PETSC_FALSE; SNES snes; KSP ksp; PC pc; ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr; /* set data */ data.m = 9; data.n = 9; data.a = 1.0; data.epsilon = 0.1; data.dx = 1.0/(data.m+1.0); data.dy = 1.0/(data.n+1.0); mn = (data.m)*(data.n); ierr = PetscOptionsGetInt(NULL,NULL,"-time",&time_steps,NULL);CHKERRQ(ierr); /* set initial conditions */ ierr = VecCreate(PETSC_COMM_WORLD,&global);CHKERRQ(ierr); ierr = VecSetSizes(global,PETSC_DECIDE,mn);CHKERRQ(ierr); ierr = VecSetFromOptions(global);CHKERRQ(ierr); ierr = Initial(global,&data);CHKERRQ(ierr); ierr = VecDuplicate(global,&x);CHKERRQ(ierr); /* create timestep context */ ierr = TSCreate(PETSC_COMM_WORLD,&ts);CHKERRQ(ierr); ierr = TSMonitorSet(ts,Monitor,&data,NULL);CHKERRQ(ierr); ierr = TSSetType(ts,TSEULER);CHKERRQ(ierr); dt = 0.1; ftime_original = data.tfinal = 1.0; ierr = TSSetTimeStep(ts,dt);CHKERRQ(ierr); ierr = TSSetMaxSteps(ts,time_steps);CHKERRQ(ierr); ierr = TSSetMaxTime(ts,ftime_original);CHKERRQ(ierr); ierr = TSSetExactFinalTime(ts,TS_EXACTFINALTIME_STEPOVER);CHKERRQ(ierr); ierr = TSSetSolution(ts,global);CHKERRQ(ierr); /* set user provided RHSFunction and RHSJacobian */ ierr = TSSetRHSFunction(ts,NULL,RHSFunction,&data);CHKERRQ(ierr); ierr = MatCreate(PETSC_COMM_WORLD,&J);CHKERRQ(ierr); ierr = MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,mn,mn);CHKERRQ(ierr); ierr = MatSetFromOptions(J);CHKERRQ(ierr); ierr = MatSeqAIJSetPreallocation(J,5,NULL);CHKERRQ(ierr); ierr = MatMPIAIJSetPreallocation(J,5,NULL,5,NULL);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,NULL,"-ts_fd",&flg);CHKERRQ(ierr); if (!flg) { ierr = TSSetRHSJacobian(ts,J,J,RHSJacobian,&data);CHKERRQ(ierr); } else { ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,NULL,"-fd_color",&fd_jacobian_coloring);CHKERRQ(ierr); if (fd_jacobian_coloring) { /* Use finite differences with coloring */ /* Get data structure of J */ PetscBool pc_diagonal; ierr = PetscOptionsHasName(NULL,NULL,"-pc_diagonal",&pc_diagonal);CHKERRQ(ierr); if (pc_diagonal) { /* the preconditioner of J is a diagonal matrix */ PetscInt rstart,rend,i; PetscScalar zero=0.0; ierr = MatGetOwnershipRange(J,&rstart,&rend);CHKERRQ(ierr); for (i=rstart; im; dx = data->dx; dy = data->dy; /* determine starting point of each processor */ ierr = VecGetOwnershipRange(global,&mybase,&myend);CHKERRQ(ierr); ierr = VecGetLocalSize(global,&locsize);CHKERRQ(ierr); /* Initialize the array */ ierr = VecGetArrayWrite(global,&localptr);CHKERRQ(ierr); for (i=0; im; n = data->n; mn = m*n; dx = data->dx; dy = data->dy; a = data->a; epsilon = data->epsilon; xc = -2.0*epsilon*(1.0/(dx*dx)+1.0/(dy*dy)); xl = 0.5*a/dx+epsilon/(dx*dx); xr = -0.5*a/dx+epsilon/(dx*dx); yl = 0.5*a/dy+epsilon/(dy*dy); yr = -0.5*a/dy+epsilon/(dy*dy); row = 0; v[0] = xc; v[1] = xr; v[2] = yr; idx[0] = 0; idx[1] = 2; idx[2] = m; ierr = MatSetValues(A,1,&row,3,idx,v,INSERT_VALUES);CHKERRQ(ierr); row = m-1; v[0] = 2.0*xl; v[1] = xc; v[2] = yr; idx[0] = m-2; idx[1] = m-1; idx[2] = m-1+m; ierr = MatSetValues(A,1,&row,3,idx,v,INSERT_VALUES);CHKERRQ(ierr); for (i=1; im; n = data->n; mn = m*n; dx = data->dx; dy = data->dy; a = data->a; epsilon = data->epsilon; xc = -2.0*epsilon*(1.0/(dx*dx)+1.0/(dy*dy)); xl = 0.5*a/dx+epsilon/(dx*dx); xr = -0.5*a/dx+epsilon/(dx*dx); yl = 0.5*a/dy+epsilon/(dy*dy); yr = -0.5*a/dy+epsilon/(dy*dy); /* Get the length of parallel vector */ ierr = VecGetSize(globalin,&len);CHKERRQ(ierr); /* Set the index sets */ ierr = PetscMalloc1(len,&idx);CHKERRQ(ierr); for (i=0; i