Actual source code: ex65.c

petsc-3.7.7 2017-09-25
Report Typos and Errors
  2: /*
  3:  Partial differential equation

  5:    d   d u = 1, 0 < x < 1,
  6:    --   --
  7:    dx   dx
  8: with boundary conditions

 10:    u = 0 for x = 0, x = 1

 12:    This uses multigrid to solve the linear system

 14:    Demonstrates how to build a DMSHELL for managing multigrid. The DMSHELL simply creates a 
 15:    DMDA1d to construct all the needed PETSc objects.

 17: */

 19: static char help[] = "Solves 1D constant coefficient Laplacian using DMSHELL and multigrid.\n\n";

 21: #include <petscdm.h>
 22: #include <petscdmda.h>
 23: #include <petscdmshell.h>
 24: #include <petscksp.h>

 26: static PetscErrorCode ComputeMatrix(KSP,Mat,Mat,void*);
 27: static PetscErrorCode ComputeRHS(KSP,Vec,void*);
 28: static PetscErrorCode CreateMatrix(DM,Mat*);
 29: static PetscErrorCode CreateGlobalVector(DM,Vec*);
 30: static PetscErrorCode CreateLocalVector(DM,Vec*);
 31: static PetscErrorCode Refine(DM,MPI_Comm,DM*);
 32: static PetscErrorCode Coarsen(DM,MPI_Comm,DM*);
 33: static PetscErrorCode CreateInterpolation(DM,DM,Mat*,Vec*);
 34: static PetscErrorCode CreateRestriction(DM,DM,Mat*);

 36: static PetscErrorCode MyDMShellCreate(MPI_Comm comm,DM da,DM *shell)
 37: {

 40:   DMShellCreate(comm,shell);
 41:   DMShellSetContext(*shell,da);
 42:   DMShellSetCreateMatrix(*shell,CreateMatrix);
 43:   DMShellSetCreateGlobalVector(*shell,CreateGlobalVector);
 44:   DMShellSetCreateLocalVector(*shell,CreateLocalVector);
 45:   DMShellSetRefine(*shell,Refine);
 46:   DMShellSetCoarsen(*shell,Coarsen);
 47:   DMShellSetCreateInterpolation(*shell,CreateInterpolation);
 48:   DMShellSetCreateRestriction(*shell,CreateRestriction);
 49:   return 0;
 50: }

 54: int main(int argc,char **argv)
 55: {
 57:   KSP            ksp;
 58:   DM             da,shell;
 59:   PetscInt       levels;

 61:   PetscInitialize(&argc,&argv,(char*)0,help);

 63:   KSPCreate(PETSC_COMM_WORLD,&ksp);
 64:   DMDACreate1d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,-129,1,1,0,&da);
 65:   MyDMShellCreate(PETSC_COMM_WORLD,da,&shell);
 66:   /* these two lines are not needed but allow PCMG to automatically know how many multigrid levels the user wants */
 67:   DMGetRefineLevel(da,&levels);
 68:   DMSetRefineLevel(shell,levels);

 70:   KSPSetDM(ksp,shell);
 71:   KSPSetComputeRHS(ksp,ComputeRHS,NULL);
 72:   KSPSetComputeOperators(ksp,ComputeMatrix,NULL);
 73:   KSPSetFromOptions(ksp);
 74:   KSPSolve(ksp,NULL,NULL);

 76:   KSPDestroy(&ksp);
 77:   DMDestroy(&shell);
 78:   DMDestroy(&da);
 79:   PetscFinalize();

 81:   return 0;
 82: }

 86: static PetscErrorCode CreateMatrix(DM shell,Mat *A)
 87: {
 89:   DM             da;

 91:   DMShellGetContext(shell,(void**)&da);
 92:   DMCreateMatrix(da,A);
 93:   return 0;
 94: }

 98: static PetscErrorCode CreateInterpolation(DM dm1,DM dm2,Mat *mat,Vec *vec)
 99: {
100:   DM             da1,da2;

103:   DMShellGetContext(dm1,(void**)&da1);
104:   DMShellGetContext(dm2,(void**)&da2);
105:   DMCreateInterpolation(da1,da2,mat,vec);
106:   return 0;
107: }

111: static PetscErrorCode CreateRestriction(DM dm1,DM dm2,Mat *mat)
112: {
113:   DM             da1,da2;

116:   DMShellGetContext(dm1,(void**)&da1);
117:   DMShellGetContext(dm2,(void**)&da2);
118:   DMCreateInterpolation(da1,da2,mat,NULL);
119:   return 0;
120: }

124: static PetscErrorCode CreateGlobalVector(DM shell,Vec *x)
125: {
127:   DM             da;

129:   DMShellGetContext(shell,(void**)&da);
130:   DMCreateGlobalVector(da,x);
131:   VecSetDM(*x,shell);
132:   return 0;
133: }

137: static PetscErrorCode CreateLocalVector(DM shell,Vec *x)
138: {
140:   DM             da;

142:   DMShellGetContext(shell,(void**)&da);
143:   DMCreateLocalVector(da,x);
144:   VecSetDM(*x,shell);
145:   return 0;
146: }

150: static PetscErrorCode Refine(DM shell,MPI_Comm comm,DM *dmnew)
151: {
153:   DM             da,dafine;

155:   DMShellGetContext(shell,(void**)&da);
156:   DMRefine(da,comm,&dafine);
157:   MyDMShellCreate(PetscObjectComm((PetscObject)shell),dafine,dmnew);
158:   return 0;
159: }

163: static PetscErrorCode Coarsen(DM shell,MPI_Comm comm,DM *dmnew)
164: {
166:   DM             da,dacoarse;

168:   DMShellGetContext(shell,(void**)&da);
169:   DMCoarsen(da,comm,&dacoarse);
170:   MyDMShellCreate(PetscObjectComm((PetscObject)shell),dacoarse,dmnew);
171:   /* discard an "extra" reference count to dacoarse */
172:   DMDestroy(&dacoarse);
173:   return 0;
174: }

178: static PetscErrorCode ComputeRHS(KSP ksp,Vec b,void *ctx)
179: {
181:   PetscInt       mx,idx[2];
182:   PetscScalar    h,v[2];
183:   DM             da,shell;

186:   KSPGetDM(ksp,&shell);
187:   DMShellGetContext(shell,(void**)&da);
188:   DMDAGetInfo(da,0,&mx,0,0,0,0,0,0,0,0,0,0,0);
189:   h      = 1.0/((mx-1));
190:   VecSet(b,h);
191:   idx[0] = 0; idx[1] = mx -1;
192:   v[0]   = v[1] = 0.0;
193:   VecSetValues(b,2,idx,v,INSERT_VALUES);
194:   VecAssemblyBegin(b);
195:   VecAssemblyEnd(b);
196:   return(0);
197: }

201: static PetscErrorCode ComputeMatrix(KSP ksp,Mat J,Mat jac,void *ctx)
202: {
204:   PetscInt       i,mx,xm,xs;
205:   PetscScalar    v[3],h;
206:   MatStencil     row,col[3];
207:   DM             da,shell;

210:   KSPGetDM(ksp,&shell);
211:   DMShellGetContext(shell,(void**)&da);
212:   DMDAGetInfo(da,0,&mx,0,0,0,0,0,0,0,0,0,0,0);
213:   DMDAGetCorners(da,&xs,0,0,&xm,0,0);
214:   h    = 1.0/(mx-1);

216:   for (i=xs; i<xs+xm; i++) {
217:     row.i = i;
218:     if (i==0 || i==mx-1) {
219:       v[0] = 2.0/h;
220:       MatSetValuesStencil(jac,1,&row,1,&row,v,INSERT_VALUES);
221:     } else {
222:       v[0]  = (-1.0)/h;col[0].i = i-1;
223:       v[1]  = (2.0)/h;col[1].i = row.i;
224:       v[2]  = (-1.0)/h;col[2].i = i+1;
225:       MatSetValuesStencil(jac,1,&row,3,col,v,INSERT_VALUES);
226:     }
227:   }
228:   MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);
229:   MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);
230:   return(0);
231: }