Actual source code: ex55.c

petsc-3.4.5 2014-06-29
  1: static char help[] = "Allen-Cahn-2d problem for constant mobility and triangular elements.\n\
  2: Runtime options include:\n\
  3: -xmin <xmin>\n\
  4: -xmax <xmax>\n\
  5: -ymin <ymin>\n\
  6: -T <T>, where <T> is the end time for the time domain simulation\n\
  7: -dt <dt>,where <dt> is the step size for the numerical integration\n\
  8: -gamma <gamma>\n\
  9: -theta_c <theta_c>\n\n";

 11: /*
 12:   Solves the linear system using a Schur complement solver based on PCLSC, solve the A00 block with hypre BoomerAMG

 14:   ./ex55 -ksp_type fgmres -pc_type fieldsplit -pc_fieldsplit_detect_saddle_point -pc_fieldsplit_type schur -pc_fieldsplit_schur_precondition self -fieldsplit_1_ksp_type fgmres -fieldsplit_1_pc_type lsc -snes_vi_monitor -ksp_monitor_true_residual -fieldsplit_ksp_monitor -fieldsplit_0_pc_type hypre -da_grid_x 65 -da_grid_y 65 -snes_atol 1.e-11  -ksp_rtol 1.e-8

 16:   Solves the linear systems with multigrid on the entire system using  a Schur complement based smoother (which is handled by PCFIELDSPLIT)

 18: ./ex55 -ksp_type fgmres -pc_type mg -mg_levels_ksp_type fgmres -mg_levels_pc_type fieldsplit -mg_levels_pc_fieldsplit_detect_saddle_point -mg_levels_pc_fieldsplit_type schur -mg_levels_pc_fieldsplit_factorization_type full -mg_levels_pc_fieldsplit_schur_precondition user -mg_levels_fieldsplit_1_ksp_type gmres -mg_levels_fieldsplit_1_pc_type none -mg_levels_fieldsplit_0_ksp_type preonly -mg_levels_fieldsplit_0_pc_type sor -mg_levels_fieldsplit_0_pc_sor_forward -snes_vi_monitor -ksp_monitor_true_residual -pc_mg_levels 5 -pc_mg_galerkin -mg_levels_ksp_monitor -mg_levels_fieldsplit_ksp_monitor -mg_levels_ksp_max_it 2 -mg_levels_fieldsplit_ksp_max_it 5 -snes_atol 1.e-11 -mg_coarse_ksp_type preonly -mg_coarse_pc_type svd -da_grid_x 65 -da_grid_y 65 -ksp_rtol 1.e-8

 20:  */

 22:  #include petscsnes.h
 23:  #include petscdmda.h

 25: typedef struct {
 26:   PetscReal   dt,T; /* Time step and end time */
 27:   DM          da;
 28:   Mat         M;    /* Jacobian matrix */
 29:   Mat         M_0;
 30:   Vec         q,u1,u2,u3,work1,work2,work3,work4;
 31:   PetscScalar epsilon; /* physics parameters */
 32:   PetscReal   xmin,xmax,ymin,ymax;
 33: } AppCtx;

 35: PetscErrorCode GetParams(AppCtx*);
 36: PetscErrorCode SetVariableBounds(DM,Vec,Vec);
 37: PetscErrorCode SetUpMatrices(AppCtx*);
 38: PetscErrorCode FormFunction(SNES,Vec,Vec,void*);
 39: PetscErrorCode FormJacobian(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
 40: PetscErrorCode SetInitialGuess(Vec,AppCtx*);
 41: PetscErrorCode Update_q(Vec,Vec,Vec,Vec,Mat,AppCtx*);
 42: PetscErrorCode Update_u(Vec,Vec,Vec,Vec);

 46: int main(int argc, char **argv)
 47: {
 49:   Vec            x,r;  /* Solution and residual vectors */
 50:   SNES           snes; /* Nonlinear solver context */
 51:   AppCtx         user; /* Application context */
 52:   Vec            xl,xu; /* Upper and lower bounds on variables */
 53:   Mat            J;
 54:   PetscScalar    t=0.0;
 55:   PetscViewer    view_out, view_q, view1;

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

 59:   /* Get physics and time parameters */
 60:   GetParams(&user);
 61:   /* Create a 2D DA with dof = 2 */
 62:   DMDACreate2d(PETSC_COMM_WORLD,DMDA_BOUNDARY_NONE,DMDA_BOUNDARY_NONE,DMDA_STENCIL_BOX,-4,-4,PETSC_DECIDE,PETSC_DECIDE,4,1,NULL,NULL,&user.da);
 63:   /* Set Element type (triangular) */
 64:   DMDASetElementType(user.da,DMDA_ELEMENT_P1);

 66:   /* Set x and y coordinates */
 67:   DMDASetUniformCoordinates(user.da,user.xmin,user.xmax,user.ymin,user.ymax,0.0,1.0);

 69:   /* Get global vector x from DM and duplicate vectors r,xl,xu */
 70:   DMCreateGlobalVector(user.da,&x);
 71:   VecDuplicate(x,&r);
 72:   VecDuplicate(x,&xl);
 73:   VecDuplicate(x,&xu);
 74:   VecDuplicate(x,&user.q);

 76:   /* Get Jacobian matrix structure from the da */
 77:   DMCreateMatrix(user.da,MATAIJ,&user.M);
 78:   /* Form the jacobian matrix and M_0 */
 79:   SetUpMatrices(&user);
 80:   MatDuplicate(user.M,MAT_DO_NOT_COPY_VALUES,&J);

 82:   /* Create nonlinear solver context */
 83:   SNESCreate(PETSC_COMM_WORLD,&snes);
 84:   SNESSetDM(snes,user.da);

 86:   /* Set Function evaluation and jacobian evaluation routines */
 87:   SNESSetFunction(snes,r,FormFunction,(void*)&user);
 88:   SNESSetJacobian(snes,J,J,FormJacobian,(void*)&user);

 90:   /* Set the boundary conditions */
 91:   SetVariableBounds(user.da,xl,xu);
 92:   SNESVISetVariableBounds(snes,xl,xu);
 93:   SNESSetFromOptions(snes);

 95:   SetInitialGuess(x,&user);
 96:   PetscViewerBinaryOpen(PETSC_COMM_WORLD,"file_out",FILE_MODE_WRITE,&view_out);
 97:   PetscViewerBinaryOpen(PETSC_COMM_WORLD,"file_q",FILE_MODE_WRITE,&view_q);
 98:   PetscViewerBinaryOpen(PETSC_COMM_WORLD,"file1",FILE_MODE_WRITE,&view1);
 99:   /* Begin time loop */
100:   while (t < user.T) {
101:     VecView(user.u1,view1);
102:     VecView(user.u2,view1);
103:     VecView(user.u3,view1);

105:     Update_q(user.q,user.u1,user.u2,user.u3,user.M_0,&user);
106:     VecView(user.q,view_q);
107:     SNESSolve(snes,NULL,x);
108:     PetscInt its;
109:     SNESGetIterationNumber(snes,&its);
110:     PetscPrintf(PETSC_COMM_WORLD,"SNESVI solver converged at t = %5.4f in %d iterations\n",t,its);
111:     Update_u(user.u1,user.u2,user.u3,x);
112:     t    = t + user.dt;
113:     VecView(user.u1,view_out);
114:     VecView(user.u2,view_out);
115:     VecView(user.u3,view_out);
116:   }



120:   PetscViewerDestroy(&view_out);
121:   PetscViewerDestroy(&view_q);
122:   PetscViewerDestroy(&view1);

124:   VecDestroy(&x);
125:   VecDestroy(&r);
126:   VecDestroy(&xl);
127:   VecDestroy(&xu);
128:   VecDestroy(&user.q);
129:   VecDestroy(&user.u1);
130:   VecDestroy(&user.u2);
131:   VecDestroy(&user.u3);
132:   VecDestroy(&user.work1);
133:   VecDestroy(&user.work2);
134:   VecDestroy(&user.work3);
135:   VecDestroy(&user.work4);
136:   MatDestroy(&user.M);
137:   MatDestroy(&user.M_0);
138:   MatDestroy(&J);
139:   DMDestroy(&user.da);
140:   SNESDestroy(&snes);
141:   PetscFinalize();
142:   return 0;
143: }

147: PetscErrorCode Update_u(Vec u1,Vec u2,Vec u3,Vec X)
148: {
150:   PetscInt       i,n;
151:   PetscScalar    *u1_arr,*u2_arr,*u3_arr,*x_arr;

154:   VecGetLocalSize(u1,&n);
155:   VecGetArray(u1,&u1_arr);
156:   VecGetArray(u2,&u2_arr);
157:   VecGetArray(u3,&u3_arr);
158:   VecGetArray(X,&x_arr);
159:   for (i=0; i<n; i++) {
160:     u1_arr[i] = x_arr[4*i];
161:     u2_arr[i] = x_arr[4*i+1];
162:     u3_arr[i] = x_arr[4*i+2];
163:   }
164:   VecRestoreArray(u1,&u1_arr);
165:   VecRestoreArray(u2,&u2_arr);
166:   VecRestoreArray(u3,&u3_arr);
167:   VecRestoreArray(X,&x_arr);
168:   return(0);
169: }

173: PetscErrorCode Update_q(Vec q,Vec u1,Vec u2,Vec u3,Mat M_0,AppCtx *user)
174: {
176:   PetscScalar    *q_arr,*w_arr;
177:   PetscInt       i,n;
178:   /*PetscViewer    view_q;*/

181:   VecSet(user->work1,user->dt/3);
182:   /*    VecView(user->work1,PETSC_VIEWER_STDOUT_WORLD);*/
183:   MatMult(M_0,user->work1,user->work2);
184:   /*    VecView(user->work2,PETSC_VIEWER_STDOUT_WORLD);*/

186:   MatMult(M_0,u1,user->work1);
187:   MatMult(M_0,u1,user->work4);
188:   /*    VecView(u1,PETSC_VIEWER_STDOUT_WORLD);*/
189:   /*    VecView(user->work4,PETSC_VIEWER_STDOUT_WORLD);*/
190:   VecScale(user->work1,-1.0-(user->dt));
191:   VecAXPY(user->work1,1.0,user->work2);

193:   VecGetLocalSize(u1,&n);
194:   VecGetArray(q,&q_arr);
195:   VecGetArray(user->work1,&w_arr);
196:   for (i=0; i<n; i++) q_arr[4*i] = w_arr[i];
197:   VecRestoreArray(q,&q_arr);
198:   VecRestoreArray(user->work1,&w_arr);

200:   MatMult(M_0,u2,user->work1);
201:   VecScale(user->work1,-1.0-(user->dt));
202:   VecAXPY(user->work1,1.0,user->work2);

204:   VecGetArray(q,&q_arr);
205:   VecGetArray(user->work1,&w_arr);
206:   for (i=0; i<n; i++) q_arr[4*i+1] = w_arr[i];
207:   VecRestoreArray(q,&q_arr);
208:   VecRestoreArray(user->work1,&w_arr);

210:   MatMult(M_0,u3,user->work1);
211:   VecScale(user->work1,-1.0-(user->dt));
212:   VecAXPY(user->work1,1.0,user->work2);

214:   VecGetArray(q,&q_arr);
215:   VecGetArray(user->work1,&w_arr);
216:   for (i=0; i<n; i++) {
217:     q_arr[4*i+2] = w_arr[i];
218:     q_arr[4*i+3] = 1.0;
219:   }
220:   VecRestoreArray(q,&q_arr);
221:   VecRestoreArray(user->work1,&w_arr);
222:   return(0);
223: }

227: PetscErrorCode SetInitialGuess(Vec X,AppCtx *user)
228: {
229:   PetscErrorCode    ierr;
230:   PetscInt          nele,nen,n,i;
231:   const PetscInt    *ele;
232:   Vec               coords, rand1, rand2;
233:   const PetscScalar *_coords;
234:   PetscScalar       x[3],y[3];
235:   PetscInt          idx[3];
236:   PetscScalar       *xx,*w1,*w2,*u1,*u2,*u3;
237:   PetscViewer       view_out;

240:   /* Get ghosted coordinates */
241:   DMGetCoordinatesLocal(user->da,&coords);
242:   VecDuplicate(user->u1,&rand1);
243:   VecDuplicate(user->u1,&rand2);
244:   VecSetRandom(rand1,NULL);
245:   VecSetRandom(rand2,NULL);

247:   VecGetLocalSize(X,&n);
248:   VecGetArrayRead(coords,&_coords);
249:   VecGetArray(X,&xx);
250:   VecGetArray(user->work1,&w1);
251:   VecGetArray(user->work2,&w2);
252:   VecGetArray(user->u1,&u1);
253:   VecGetArray(user->u2,&u2);
254:   VecGetArray(user->u3,&u3);

256:   /* Get local element info */
257:   DMDAGetElements(user->da,&nele,&nen,&ele);
258:   for (i=0; i < nele; i++) {
259:     idx[0] = ele[3*i]; idx[1] = ele[3*i+1]; idx[2] = ele[3*i+2];
260:     x[0]   = _coords[2*idx[0]]; y[0] = _coords[2*idx[0]+1];
261:     x[1]   = _coords[2*idx[1]]; y[1] = _coords[2*idx[1]+1];
262:     x[2]   = _coords[2*idx[2]]; y[2] = _coords[2*idx[2]+1];

264:     PetscScalar vals1[3],vals2[3],valsrand[3];
265:     PetscInt    r;
266:     for (r=0; r<3; r++) {
267:       valsrand[r]=5*x[r]*(1-x[r])*y[r]*(1-y[r]);
268:       if (x[r]>=0.5 && y[r]>=0.5) {
269:         vals1[r]=0.75;
270:         vals2[r]=0.0;
271:       }
272:       if (x[r]>=0.5 && y[r]<0.5) {
273:         vals1[r]=0.0;
274:         vals2[r]=0.0;
275:       }
276:       if (x[r]<0.5 && y[r]>=0.5) {
277:         vals1[r]=0.0;
278:         vals2[r]=0.75;
279:       }
280:       if (x[r]<0.5 && y[r]<0.5) {
281:         vals1[r]=0.75;
282:         vals2[r]=0.0;
283:       }
284:     }

286:     VecSetValues(user->work1,3,idx,vals1,INSERT_VALUES);
287:     VecSetValues(user->work2,3,idx,vals2,INSERT_VALUES);
288:     VecSetValues(user->work3,3,idx,valsrand,INSERT_VALUES);
289:   }

291:   VecAssemblyBegin(user->work1);
292:   VecAssemblyEnd(user->work1);
293:   VecAssemblyBegin(user->work2);
294:   VecAssemblyEnd(user->work2);
295:   VecAssemblyBegin(user->work3);
296:   VecAssemblyEnd(user->work3);

298:   VecAXPY(user->work1,1.0,user->work3);
299:   VecAXPY(user->work2,1.0,user->work3);

301:   for (i=0; i<n/4; i++) {
302:     xx[4*i] = w1[i];
303:     if (xx[4*i]>1) xx[4*i]=1;

305:     xx[4*i+1] = w2[i];
306:     if (xx[4*i+1]>1) xx[4*i+1]=1;

308:     if (xx[4*i]+xx[4*i+1]>1) xx[4*i+1] = 1.0 - xx[4*i];

310:     xx[4*i+2] = 1.0 - xx[4*i] - xx[4*i+1];
311:     xx[4*i+3] = 0.0;

313:     u1[i] = xx[4*i];
314:     u2[i] = xx[4*i+1];
315:     u3[i] = xx[4*i+2];
316:   }

318:   PetscViewerBinaryOpen(PETSC_COMM_WORLD,"file_initial",FILE_MODE_WRITE,&view_out);
319:   VecView(user->u1,view_out);
320:   VecView(user->u2,view_out);
321:   VecView(user->u3,view_out);
322:   PetscViewerDestroy(&view_out);

324:   DMDARestoreElements(user->da,&nele,&nen,&ele);
325:   VecRestoreArrayRead(coords,&_coords);
326:   VecRestoreArray(X,&xx);
327:   VecRestoreArray(user->work2,&w1);
328:   VecRestoreArray(user->work4,&w2);
329:   VecRestoreArray(user->u1,&u1);
330:   VecRestoreArray(user->u2,&u2);
331:   VecRestoreArray(user->u3,&u3);
332:   VecDestroy(&rand1);
333:   VecDestroy(&rand2);
334:   return(0);
335: }



341: PetscErrorCode FormFunction(SNES snes,Vec X,Vec F,void *ctx)
342: {
344:   AppCtx         *user=(AppCtx*)ctx;

347:   MatMultAdd(user->M,X,user->q,F);
348:   return(0);
349: }

353: PetscErrorCode FormJacobian(SNES snes,Vec X,Mat *J,Mat *B,MatStructure *flg,void *ctx)
354: {
356:   AppCtx         *user=(AppCtx*)ctx;

359:   *flg = SAME_NONZERO_PATTERN;
360:   MatCopy(user->M,*J,*flg);
361:   MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
362:   MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
363:   return(0);
364: }

368: PetscErrorCode SetVariableBounds(DM da,Vec xl,Vec xu)
369: {
371:   PetscScalar    ***l,***u;
372:   PetscInt       xs,xm,ys,ym;
373:   PetscInt       j,i;

376:   DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL);
377:   DMDAVecGetArrayDOF(da,xl,&l);
378:   DMDAVecGetArrayDOF(da,xu,&u);
379:   for (j=ys; j < ys+ym; j++) {
380:     for (i=xs; i < xs+xm; i++) {
381:       l[j][i][0] = 0.0;
382:       l[j][i][1] = 0.0;
383:       l[j][i][2] = 0.0;
384:       l[j][i][3] = -SNES_VI_INF;
385:       u[j][i][0] = 1.0;
386:       u[j][i][1] = 1.0;
387:       u[j][i][2] = 1.0;
388:       u[j][i][3] = SNES_VI_INF;
389:     }
390:   }
391:   DMDAVecRestoreArrayDOF(da,xl,&l);
392:   DMDAVecRestoreArrayDOF(da,xu,&u);
393:   return(0);
394: }

398: PetscErrorCode GetParams(AppCtx *user)
399: {
401:   PetscBool      flg;

404:   /* Set default parameters */
405:   user->xmin    = 0.0; user->xmax = 1.0;
406:   user->ymin    = 0.0; user->ymax = 1.0;
407:   user->T       = 0.2; user->dt   = 0.001;
408:   user->epsilon = 0.05;

410:   PetscOptionsGetReal(NULL,"-xmin",&user->xmin,&flg);
411:   PetscOptionsGetReal(NULL,"-xmax",&user->xmax,&flg);
412:   PetscOptionsGetReal(NULL,"-ymin",&user->ymin,&flg);
413:   PetscOptionsGetReal(NULL,"-ymax",&user->ymax,&flg);
414:   PetscOptionsGetReal(NULL,"-T",&user->T,&flg);
415:   PetscOptionsGetReal(NULL,"-dt",&user->dt,&flg);
416:   PetscOptionsGetScalar(NULL,"-epsilon",&user->epsilon,&flg);
417:   return(0);
418: }

422: PetscErrorCode SetUpMatrices(AppCtx *user)
423: {
424:   PetscErrorCode    ierr;
425:   PetscInt          nele,nen,i,j;
426:   const PetscInt    *ele;
427:   PetscScalar       dt=user->dt;
428:   Vec               coords;
429:   const PetscScalar *_coords;
430:   PetscScalar       x[3],y[3];
431:   PetscInt          idx[3];
432:   PetscScalar       eM_0[3][3],eM_2_odd[3][3],eM_2_even[3][3];
433:   Mat               M      =user->M;
434:   PetscScalar       epsilon=user->epsilon;
435:   PetscScalar       hx;
436:   PetscInt          n,Mda,Nda;
437:   DM                da;

440:   /* Get ghosted coordinates */
441:   DMGetCoordinatesLocal(user->da,&coords);
442:   VecGetArrayRead(coords,&_coords);

444:   /* Create the mass matrix M_0 */
445:   MatGetLocalSize(M,&n,NULL);


448:   /* MatCreate(PETSC_COMM_WORLD,&user->M_0);*/
449:   DMDAGetInfo(user->da,NULL,&Mda,&Nda,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
450:   hx   = 1.0/(Mda-1);
451:   DMDACreate2d(PETSC_COMM_WORLD,DMDA_BOUNDARY_NONE,DMDA_BOUNDARY_NONE,DMDA_STENCIL_BOX,Mda,Nda,PETSC_DECIDE,PETSC_DECIDE,1,1,NULL,NULL,&da);
452:   DMCreateMatrix(da,MATAIJ,&user->M_0);
453:   DMDestroy(&da);

455:   eM_0[0][0]=eM_0[1][1]=eM_0[2][2]=hx*hx/12.0;
456:   eM_0[0][1]=eM_0[0][2]=eM_0[1][0]=eM_0[1][2]=eM_0[2][0]=eM_0[2][1]=hx*hx/24.0;

458:   eM_2_odd[0][0] = eM_2_odd[0][1] = eM_2_odd[0][2] = 0.0;
459:   eM_2_odd[1][0] = eM_2_odd[1][1] = eM_2_odd[1][2] = 0.0;
460:   eM_2_odd[2][0] = eM_2_odd[2][1] = eM_2_odd[2][2] = 0.0;

462:   eM_2_odd[0][0]=1.0;
463:   eM_2_odd[1][1]=eM_2_odd[2][2]=0.5;
464:   eM_2_odd[0][1]=eM_2_odd[0][2]=eM_2_odd[1][0]=eM_2_odd[2][0]=-0.5;

466:   eM_2_even[0][0] = eM_2_even[0][1] = eM_2_even[0][2] = 0.0;
467:   eM_2_even[0][0] = eM_2_even[0][1] = eM_2_even[0][2] = 0.0;
468:   eM_2_even[0][0] = eM_2_even[0][1] = eM_2_even[0][2] = 0.0;

470:   eM_2_even[1][1]=1;
471:   eM_2_even[0][0]=eM_2_even[2][2]=0.5;
472:   eM_2_even[0][1]=eM_2_even[1][0]=eM_2_even[1][2]=eM_2_even[2][1]=-0.5;

474:   /* Get local element info */
475:   DMDAGetElements(user->da,&nele,&nen,&ele);
476:   for (i=0; i < nele; i++) {
477:     idx[0] = ele[3*i]; idx[1] = ele[3*i+1]; idx[2] = ele[3*i+2];
478:     x[0]   = _coords[2*idx[0]]; y[0] = _coords[2*idx[0]+1];
479:     x[1]   = _coords[2*idx[1]]; y[1] = _coords[2*idx[1]+1];
480:     x[2]   = _coords[2*idx[2]]; y[2] = _coords[2*idx[2]+1];

482:     PetscInt    row,cols[3],r,row_M_0;
483:     PetscScalar vals[3],vals_M_0[3];

485:     for (r=0; r<3; r++) {
486:       row_M_0 = idx[r];

488:       vals_M_0[0]=eM_0[r][0];
489:       vals_M_0[1]=eM_0[r][1];
490:       vals_M_0[2]=eM_0[r][2];

492:       MatSetValues(user->M_0,1,&row_M_0,3,idx,vals_M_0,ADD_VALUES);

494:       if (y[1]==y[0]) {
495:         row     = 4*idx[r];
496:         cols[0] = 4*idx[0];     vals[0] = eM_0[r][0]+dt*epsilon*epsilon*eM_2_odd[r][0];
497:         cols[1] = 4*idx[1];     vals[1] = eM_0[r][1]+dt*epsilon*epsilon*eM_2_odd[r][1];
498:         cols[2] = 4*idx[2];     vals[2] = eM_0[r][2]+dt*epsilon*epsilon*eM_2_odd[r][2];
499:         /* Insert values in matrix M for 1st dof */
500:         MatSetValuesLocal(M,1,&row,3,cols,vals,ADD_VALUES);

502:         row     = 4*idx[r]+1;
503:         cols[0] = 4*idx[0]+1;   vals[0] = eM_0[r][0]+dt*epsilon*epsilon*eM_2_odd[r][0];
504:         cols[1] = 4*idx[1]+1;   vals[1] = eM_0[r][1]+dt*epsilon*epsilon*eM_2_odd[r][1];
505:         cols[2] = 4*idx[2]+1;   vals[2] = eM_0[r][2]+dt*epsilon*epsilon*eM_2_odd[r][2];
506:         /* Insert values in matrix M for 2nd dof */
507:         MatSetValuesLocal(M,1,&row,3,cols,vals,ADD_VALUES);

509:         row     = 4*idx[r]+2;
510:         cols[0] = 4*idx[0]+2;   vals[0] = eM_0[r][0]+dt*epsilon*epsilon*eM_2_odd[r][0];
511:         cols[1] = 4*idx[1]+2;   vals[1] = eM_0[r][1]+dt*epsilon*epsilon*eM_2_odd[r][1];
512:         cols[2] = 4*idx[2]+2;   vals[2] = eM_0[r][2]+dt*epsilon*epsilon*eM_2_odd[r][2];
513:         /* Insert values in matrix M for 3nd dof */
514:         MatSetValuesLocal(M,1,&row,3,cols,vals,ADD_VALUES);
515:       } else {
516:         row     = 4*idx[r];
517:         cols[0] = 4*idx[0];     vals[0] = eM_0[r][0]+dt*epsilon*epsilon*eM_2_even[r][0];
518:         cols[1] = 4*idx[1];     vals[1] = eM_0[r][1]+dt*epsilon*epsilon*eM_2_even[r][1];
519:         cols[2] = 4*idx[2];     vals[2] = eM_0[r][2]+dt*epsilon*epsilon*eM_2_even[r][2];
520:         /* Insert values in matrix M for 1st dof */
521:         MatSetValuesLocal(M,1,&row,3,cols,vals,ADD_VALUES);

523:         row     = 4*idx[r]+1;
524:         cols[0] = 4*idx[0]+1;   vals[0] = eM_0[r][0]+dt*epsilon*epsilon*eM_2_even[r][0];
525:         cols[1] = 4*idx[1]+1;   vals[1] = eM_0[r][1]+dt*epsilon*epsilon*eM_2_even[r][1];
526:         cols[2] = 4*idx[2]+1;   vals[2] = eM_0[r][2]+dt*epsilon*epsilon*eM_2_even[r][2];
527:         /* Insert values in matrix M for 2nd dof */
528:         MatSetValuesLocal(M,1,&row,3,cols,vals,ADD_VALUES);

530:         row     = 4*idx[r]+2;
531:         cols[0] = 4*idx[0]+2;   vals[0] = eM_0[r][0]+dt*epsilon*epsilon*eM_2_even[r][0];
532:         cols[1] = 4*idx[1]+2;   vals[1] = eM_0[r][1]+dt*epsilon*epsilon*eM_2_even[r][1];
533:         cols[2] = 4*idx[2]+2;   vals[2] = eM_0[r][2]+dt*epsilon*epsilon*eM_2_even[r][2];
534:         /* Insert values in matrix M for 3nd dof */
535:         MatSetValuesLocal(M,1,&row,3,cols,vals,ADD_VALUES);
536:       }
537:     }
538:   }

540:   MatAssemblyBegin(user->M_0,MAT_FINAL_ASSEMBLY);
541:   MatAssemblyEnd(user->M_0,MAT_FINAL_ASSEMBLY);

543:   MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY);
544:   MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY);

546:   PetscScalar vals[9];

548:   vals[0] = -1.0; vals[1] =  0.0; vals[2] =  0.0;
549:   vals[3] =  0.0; vals[4] = -1.0; vals[5] =  0.0;
550:   vals[6] =  0.0; vals[7] =  0.0; vals[8] = -1.0;


553:   for (j=0; j < nele; j++) {
554:     idx[0] = ele[3*j]; idx[1] = ele[3*j+1]; idx[2] = ele[3*j+2];

556:     PetscInt r,rows[3],cols[3];
557:     for (r=0; r<3; r++) {

559:       rows[0] = 4*idx[0]+r;     cols[0] = 4*idx[0]+3;
560:       rows[1] = 4*idx[1]+r;   cols[1] = 4*idx[1]+3;
561:       rows[2] = 4*idx[2]+r;   cols[2] = 4*idx[2]+3;

563:       MatSetValuesLocal(M,3,rows,3,cols,vals,INSERT_VALUES);
564:       MatSetValuesLocal(M,3,cols,3,rows,vals,INSERT_VALUES);

566:     }

568:   }

570:   DMDARestoreElements(user->da,&nele,&nen,&ele);
571:   VecRestoreArrayRead(coords,&_coords);

573:   MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY);
574:   MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY);



578:   VecCreate(PETSC_COMM_WORLD,&user->u1);
579:   VecSetSizes(user->u1,n/4,PETSC_DECIDE);
580:   VecSetFromOptions(user->u1);
581:   VecDuplicate(user->u1,&user->u2);
582:   VecDuplicate(user->u1,&user->u3);
583:   VecDuplicate(user->u1,&user->work1);
584:   VecDuplicate(user->u1,&user->work2);
585:   VecDuplicate(user->u1,&user->work3);
586:   VecDuplicate(user->u1,&user->work4);
587:   return(0);
588: }