Actual source code: ex65.c
1: static char help[] = "2D coupled Allen-Cahn and Cahn-Hilliard equation for constant mobility. Only c_v and eta are considered.\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: ./ex63 -ksp_type fgmres -snes_vi_monitor -snes_atol 1.e-11 -snes_converged_reason -ksp_converged_reason -snes_ls_monitor -VG 10000000 -draw_fields 1,3,4 -pc_type mg -pc_mg_galerkin -log_summary -dt .000001 -mg_coarse_pc_type svd -ksp_monitor_true_residual -ksp_rtol 1.e-9 -snes_ls basic -T .0020 -P_casc .0005 -snes_monitor_solution -da_refine 10
13: */
15: #include petscsnes.h
16: #include petscdmda.h
18: typedef struct{
19: PetscReal dt,T; /* Time step and end time */
20: DM da1,da1_clone,da2;
21: Mat M; /* Jacobian matrix */
22: Mat M_0;
23: Vec q,wv,cv,eta,DPsiv,DPsieta,logcv,logcv2;
24: Vec work1,work2;
25: PetscScalar Mv,L,kaeta,kav,Evf,A,B,cv0,Sv;
26: PetscReal xmin,xmax,ymin,ymax;
27: PetscInt nx;
28: PetscBool graphics;
29: PetscBool periodic;
30: PetscBool lumpedmass;
31: }AppCtx;
33: PetscErrorCode GetParams(AppCtx*);
34: PetscErrorCode SetVariableBounds(DM,Vec,Vec);
35: PetscErrorCode SetUpMatrices(AppCtx*);
36: PetscErrorCode FormFunction(SNES,Vec,Vec,void*);
37: PetscErrorCode FormJacobian(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
38: PetscErrorCode SetInitialGuess(Vec,AppCtx*);
39: PetscErrorCode Update_q(AppCtx*);
40: PetscErrorCode Update_u(Vec,AppCtx*);
41: PetscErrorCode DPsi(AppCtx*);
42: PetscErrorCode Llog(Vec,Vec);
43: PetscErrorCode CheckRedundancy(SNES,IS,IS*,DM);
47: int main(int argc, char **argv)
48: {
50: Vec x,r; /* solution and residual vectors */
51: SNES snes; /* Nonlinear solver context */
52: AppCtx user; /* Application context */
53: Vec xl,xu; /* Upper and lower bounds on variables */
54: Mat J;
55: PetscScalar t=0.0;
56: PetscViewer view_out, view_p, view_q, view_psi, view_mat;
57: PetscReal bounds[] = {1000.0,-1000.,0.0,1.0,1000.0,-1000.0,0.0,1.0,1000.0,-1000.0};
60: PetscInitialize(&argc,&argv, (char*)0, help);
61:
62: /* Get physics and time parameters */
63: GetParams(&user);
65: if (user.periodic) {
66: DMDACreate2d(PETSC_COMM_WORLD,DMDA_BOUNDARY_PERIODIC,DMDA_BOUNDARY_PERIODIC,DMDA_STENCIL_BOX,-4,-4,PETSC_DECIDE,PETSC_DECIDE, 3, 1,PETSC_NULL,PETSC_NULL,&user.da1);
67: DMDACreate2d(PETSC_COMM_WORLD,DMDA_BOUNDARY_PERIODIC,DMDA_BOUNDARY_PERIODIC,DMDA_STENCIL_BOX,-4,-4,PETSC_DECIDE,PETSC_DECIDE, 3, 1,PETSC_NULL,PETSC_NULL,&user.da1_clone);
68: DMDACreate2d(PETSC_COMM_WORLD,DMDA_BOUNDARY_PERIODIC,DMDA_BOUNDARY_PERIODIC,DMDA_STENCIL_BOX,-4,-4,PETSC_DECIDE,PETSC_DECIDE, 1, 1,PETSC_NULL,PETSC_NULL,&user.da2);
69: } else {
70: DMDACreate2d(PETSC_COMM_WORLD,DMDA_BOUNDARY_NONE,DMDA_BOUNDARY_NONE,DMDA_STENCIL_BOX,-4,-4,PETSC_DECIDE,PETSC_DECIDE, 3, 1,PETSC_NULL,PETSC_NULL,&user.da1);
71: DMDACreate2d(PETSC_COMM_WORLD,DMDA_BOUNDARY_NONE,DMDA_BOUNDARY_NONE,DMDA_STENCIL_BOX,-4,-4,PETSC_DECIDE,PETSC_DECIDE, 3, 1,PETSC_NULL,PETSC_NULL,&user.da1_clone);
72: DMDACreate2d(PETSC_COMM_WORLD,DMDA_BOUNDARY_NONE,DMDA_BOUNDARY_NONE,DMDA_STENCIL_BOX,-4,-4,PETSC_DECIDE,PETSC_DECIDE, 1, 1,PETSC_NULL,PETSC_NULL,&user.da2);
73: }
74: /* Set Element type (triangular) */
75: DMDASetElementType(user.da1,DMDA_ELEMENT_P1);
76: DMDASetElementType(user.da2,DMDA_ELEMENT_P1);
77:
78: /* Set x and y coordinates */
79: DMDASetUniformCoordinates(user.da1,user.xmin,user.xmax,user.ymin,user.ymax,PETSC_NULL,PETSC_NULL);
80: DMDASetUniformCoordinates(user.da2,user.xmin,user.xmax,user.ymin,user.ymax,PETSC_NULL,PETSC_NULL);
81: /* Get global vector x from DM (da1) and duplicate vectors r,xl,xu */
82: DMCreateGlobalVector(user.da1,&x);
83: VecDuplicate(x,&r);
84: VecDuplicate(x,&xl);
85: VecDuplicate(x,&xu);
86: VecDuplicate(x,&user.q);
87:
88: /* Get global vector user->wv from da2 and duplicate other vectors */
89: DMCreateGlobalVector(user.da2,&user.wv);
90: VecDuplicate(user.wv,&user.cv);
91: VecDuplicate(user.wv,&user.eta);
92: VecDuplicate(user.wv,&user.DPsiv);
93: VecDuplicate(user.wv,&user.DPsieta);
94: VecDuplicate(user.wv,&user.logcv);
95: VecDuplicate(user.wv,&user.logcv2);
96: VecDuplicate(user.wv,&user.work1);
97: VecDuplicate(user.wv,&user.work2);
99: /* Get Jacobian matrix structure from the da for the entire thing, da1 */
100: DMGetMatrix(user.da1,MATAIJ,&user.M);
101: /* Get the (usual) mass matrix structure from da2 */
102: DMGetMatrix(user.da2,MATAIJ,&user.M_0);
103: /* Form the jacobian matrix and M_0 */
104: SetUpMatrices(&user);
105: SetInitialGuess(x,&user);
106: MatDuplicate(user.M,MAT_DO_NOT_COPY_VALUES,&J);
107:
108: SNESCreate(PETSC_COMM_WORLD,&snes);
109: SNESSetDM(snes,user.da1);
111: SNESSetFunction(snes,r,FormFunction,(void*)&user);
112: SNESSetJacobian(snes,J,J,FormJacobian,(void*)&user);
114: SNESSetType(snes,SNESVI);
115: SNESSetFromOptions(snes);
116: SetVariableBounds(user.da1,xl,xu);
117: //SNESVISetRedundancyCheck(snes,(PetscErrorCode (*)(SNES,IS,IS*,void*))CheckRedundancy,user.da1_clone);
118: SNESVISetVariableBounds(snes,xl,xu);
119: PetscViewerBinaryOpen(PETSC_COMM_WORLD,"file_out",FILE_MODE_WRITE,&view_out);
120: PetscViewerBinaryOpen(PETSC_COMM_WORLD,"file_p",FILE_MODE_WRITE,&view_p);
121: PetscViewerBinaryOpen(PETSC_COMM_WORLD,"file_q",FILE_MODE_WRITE,&view_q);
122: PetscViewerBinaryOpen(PETSC_COMM_WORLD,"file_psi",FILE_MODE_WRITE,&view_psi);
123: PetscViewerBinaryOpen(PETSC_COMM_WORLD,"file_mat",FILE_MODE_WRITE,&view_mat);
124: /* PetscViewerDrawSetBounds(PETSC_VIEWER_DRAW_(PETSC_COMM_WORLD),5,bounds); */
126: if (user.graphics) {
127: PetscViewerDrawSetBounds(PETSC_VIEWER_DRAW_(PETSC_COMM_WORLD),5,bounds);
129: VecView(x,PETSC_VIEWER_DRAW_(PETSC_COMM_WORLD));
130: }
131: while(t<user.T) {
133: char filename[PETSC_MAX_PATH_LEN];
134: PetscScalar a = 1.0;
135: PetscInt i;
136: PetscViewer view;
139: SNESSetFunction(snes,r,FormFunction,(void*)&user);
140: SNESSetJacobian(snes,J,J,FormJacobian,(void*)&user);
142: DPsi(&user);
143: VecView(user.DPsiv,view_psi);
144: VecView(user.DPsieta,view_psi);
146: Update_q(&user);
147: VecView(user.q,view_q);
148: MatView(user.M,view_mat);
150: SNESSolve(snes,PETSC_NULL,x);
151: VecView(x,view_out);
154: if (user.graphics) {
155: VecView(x,PETSC_VIEWER_DRAW_(PETSC_COMM_WORLD));
156: }
157:
158: PetscInt its;
159: SNESGetIterationNumber(snes,&its);
160: PetscPrintf(PETSC_COMM_WORLD,"SNESVI solver converged at t = %5.4g in %d iterations\n",t,its);
162: Update_u(x,&user);
164: for (i=0; i < (int)(user.T/a) ; i++) {
165: if (t/a > i - user.dt/a && t/a < i + user.dt/a) {
166: sprintf(filename,"output_%f",t);
167: PetscViewerBinaryOpen(PETSC_COMM_WORLD,filename,FILE_MODE_WRITE,&view);
168: VecView(user.cv,view);
169: VecView(user.eta,view);
170: PetscViewerDestroy(&view);
171: }
172:
173: }
175: t = t + user.dt;
176:
177: }
179:
180: PetscViewerDestroy(&view_out);
181: PetscViewerDestroy(&view_p);
182: PetscViewerDestroy(&view_q);
183: PetscViewerDestroy(&view_psi);
184: PetscViewerDestroy(&view_mat);
185: VecDestroy(&x);
186: VecDestroy(&r);
187: VecDestroy(&xl);
188: VecDestroy(&xu);
189: VecDestroy(&user.q);
190: VecDestroy(&user.wv);
191: VecDestroy(&user.cv);
192: VecDestroy(&user.eta);
193: VecDestroy(&user.DPsiv);
194: VecDestroy(&user.DPsieta);
195: VecDestroy(&user.logcv);
196: VecDestroy(&user.logcv2);
197: VecDestroy(&user.work1);
198: VecDestroy(&user.work2);
199: MatDestroy(&user.M);
200: MatDestroy(&user.M_0);
201: DMDestroy(&user.da1);
202: DMDestroy(&user.da1_clone);
203: DMDestroy(&user.da2);
204: SNESDestroy(&snes);
205: PetscFinalize();
206: return 0;
207: }
211: PetscErrorCode Update_u(Vec X,AppCtx *user)
212: {
214: PetscInt i,n;
215: PetscScalar *xx,*wv_p,*cv_p,*eta_p;
216:
218: VecGetLocalSize(user->wv,&n);
219:
220: VecGetArray(X,&xx);
221: VecGetArray(user->wv,&wv_p);
222: VecGetArray(user->cv,&cv_p);
223: VecGetArray(user->eta,&eta_p);
224:
225:
226: for(i=0;i<n;i++) {
227: wv_p[i] = xx[3*i];
228: cv_p[i] = xx[3*i+1];
229: eta_p[i] = xx[3*i+2];
230: }
231: VecRestoreArray(X,&xx);
232: VecRestoreArray(user->wv,&wv_p);
233: VecRestoreArray(user->cv,&cv_p);
234: VecRestoreArray(user->eta,&eta_p);
235:
236: return(0);
237: }
241: PetscErrorCode Update_q(AppCtx *user)
242: {
244: PetscScalar *q_p, *w1, *w2;
245: PetscInt n,i;
248:
249: VecGetArray(user->q,&q_p);
250: VecGetArray(user->work1,&w1);
251: VecGetArray(user->work2,&w2);
252: VecGetLocalSize(user->wv,&n);
254: MatMult(user->M_0,user->cv,user->work1);
255: VecScale(user->work1,-1.0);
256: for (i=0;i<n;i++) {
257: q_p[3*i]=w1[i];
258: }
260: MatMult(user->M_0,user->DPsiv,user->work1);
261: for (i=0;i<n;i++) {
262: q_p[3*i+1]=w1[i];
263: }
265: VecCopy(user->DPsieta,user->work1);
266: VecScale(user->work1,user->L*user->dt);
267: VecAXPY(user->work1,-1.0,user->eta);
268: MatMult(user->M_0,user->work1,user->work2);
269: for (i=0;i<n;i++) {
270: q_p[3*i+2]=w2[i];
271: }
273: VecRestoreArray(user->q,&q_p);
274: VecRestoreArray(user->work1,&w1);
275: VecRestoreArray(user->work2,&w2);
276:
277: return(0);
278: }
282: PetscErrorCode DPsi(AppCtx* user)
283: {
284: PetscErrorCode ierr;
285: PetscScalar Evf=user->Evf,A=user->A,B=user->B,cv0=user->cv0;
286: PetscScalar *cv_p,*eta_p,*logcv_p,*logcv2_p,*DPsiv_p,*DPsieta_p;
287: PetscInt n,i;
291: VecGetLocalSize(user->cv,&n);
292: VecGetArray(user->cv,&cv_p);
293: VecGetArray(user->eta,&eta_p);
294: VecGetArray(user->logcv,&logcv_p);
295: VecGetArray(user->logcv2,&logcv2_p);
296: VecGetArray(user->DPsiv,&DPsiv_p);
297: VecGetArray(user->DPsieta,&DPsieta_p);
299: Llog(user->cv,user->logcv);
301: VecCopy(user->cv,user->work1);
302: VecScale(user->work1,-1.0);
303: VecShift(user->work1,1.0);
304: Llog(user->work1,user->logcv2);
306: for (i=0;i<n;i++)
307: {
308: DPsiv_p[i] = (eta_p[i]-1.0)*(eta_p[i]-1.0)*(eta_p[i]+1.0)*(eta_p[i]+1.0)*( Evf + logcv_p[i] - logcv2_p[i]) - 2.0*A*(cv_p[i] - cv0)*eta_p[i]*(eta_p[i]+2.0)*(eta_p[i]-1.0)*(eta_p[i]-1.0) + 2.0*B*(cv_p[i] - 1.0)*eta_p[i]*eta_p[i];
309:
310: DPsieta_p[i] = 4.0*eta_p[i]*(eta_p[i]-1.0)*(eta_p[i]+1.0)*(Evf*cv_p[i] + cv_p[i]*logcv_p[i] + (1.0-cv_p[i])*logcv2_p[i] ) - A*(cv_p[i] - cv0)*(cv_p[i] - cv0)*(4.0*eta_p[i]*eta_p[i]*eta_p[i] - 6.0*eta_p[i] + 2.0) + 2.0*B*(cv_p[i]-1.0)*(cv_p[i]-1.0)*eta_p[i];
311:
312: }
314: VecRestoreArray(user->cv,&cv_p);
315: VecRestoreArray(user->eta,&eta_p);
316: VecGetArray(user->logcv,&logcv_p);
317: VecGetArray(user->logcv2,&logcv2_p);
318: VecRestoreArray(user->DPsiv,&DPsiv_p);
319: VecRestoreArray(user->DPsieta,&DPsieta_p);
322: return(0);
324: }
329: PetscErrorCode Llog(Vec X, Vec Y)
330: {
331: PetscErrorCode ierr;
332: PetscScalar *x,*y;
333: PetscInt n,i;
336:
337: VecGetArray(X,&x);
338: VecGetArray(Y,&y);
339: VecGetLocalSize(X,&n);
340: for (i=0;i<n;i++) {
341: if (x[i] < 1.0e-12) {
342: y[i] = log(1.0e-12);
343: }
344: else {
345: y[i] = log(x[i]);
346: }
347: }
348:
349: return(0);
350: }
354: PetscErrorCode SetInitialGuess(Vec X,AppCtx* user)
355: {
356: PetscErrorCode ierr;
359: PetscInt n,i,Mda,Nda;
360: PetscScalar *xx,*cv_p,*wv_p,*eta_p;
361: PetscViewer view_out;
362: /* needed for the void growth case */
363: PetscScalar xmid,ymid,cv_v=1.0,cv_m=user->Sv*user->cv0,eta_v=1.0,eta_m=0.0,h,lambda;
364: PetscInt nele,nen,idx[3];
365: const PetscInt *ele;
366: PetscScalar x[3],y[3];
367: Vec coords;
368: const PetscScalar *_coords;
369: PetscScalar xwidth = user->xmax - user->xmin, ywidth = user->ymax - user->ymin;
373: VecGetLocalSize(X,&n);
374:
375:
376: DMDAGetInfo(user->da2,PETSC_NULL,&Mda,&Nda,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL);
377: DMDAGetGhostedCoordinates(user->da2,&coords);
378: VecGetArrayRead(coords,&_coords);
380: if (user->periodic) {
381: h = (user->xmax-user->xmin)/Mda;
382: } else {
383: h = (user->xmax-user->xmin)/(Mda-1.0);
384: }
386: xmid = (user->xmax + user->xmin)/2.0;
387: ymid = (user->ymax + user->ymin)/2.0;
388: lambda = 4.0*h;
389:
390: DMDAGetElements(user->da2,&nele,&nen,&ele);
391: for (i=0;i < nele; i++) {
392: idx[0] = ele[3*i]; idx[1] = ele[3*i+1]; idx[2] = ele[3*i+2];
393:
394: x[0] = _coords[2*idx[0]]; y[0] = _coords[2*idx[0]+1];
395: x[1] = _coords[2*idx[1]]; y[1] = _coords[2*idx[1]+1];
396: x[2] = _coords[2*idx[2]]; y[2] = _coords[2*idx[2]+1];
397:
398: PetscInt k;
399: PetscScalar vals_DDcv[3],vals_cv[3],vals_eta[3],s,hhr,r;
400: for (k=0; k < 3 ; k++) {
401: //s = PetscAbs(x[k] - xmid);
402: s = sqrt((x[k] - xmid)*(x[k] - xmid) + (y[k] - ymid)*(y[k] - ymid));
403: if (s <= xwidth*(5.0/64.0)) {
404: vals_cv[k] = cv_v;
405: vals_eta[k] = eta_v;
406: vals_DDcv[k] = 0.0;
407: } else if (s> xwidth*(5.0/64.0) && s<= xwidth*(7.0/64.0) ) {
408: //r = (s - xwidth*(6.0/64.0) )/(0.5*lambda);
409: r = (s - xwidth*(6.0/64.0) )/(xwidth/64.0);
410: hhr = 0.25*(-r*r*r + 3*r + 2);
411: vals_cv[k] = cv_m + (1.0 - hhr)*(cv_v - cv_m);
412: vals_eta[k] = eta_m + (1.0 - hhr)*(eta_v - eta_m);
413: vals_DDcv[k] = (cv_v - cv_m)*r*6.0/(lambda*lambda);
414: } else {
415: vals_cv[k] = cv_m;
416: vals_eta[k] = eta_m;
417: vals_DDcv[k] = 0.0;
418: }
419: }
420:
421: VecSetValuesLocal(user->cv,3,idx,vals_cv,INSERT_VALUES);
422: VecSetValuesLocal(user->eta,3,idx,vals_eta,INSERT_VALUES);
423: VecSetValuesLocal(user->work2,3,idx,vals_DDcv,INSERT_VALUES);
424:
425: VecAssemblyBegin(user->cv);
426: VecAssemblyEnd(user->cv);
427: VecAssemblyBegin(user->eta);
428: VecAssemblyEnd(user->eta);
429: VecAssemblyBegin(user->work2);
430: VecAssemblyEnd(user->work2);
431:
432: DMDARestoreElements(user->da2,&nele,&nen,&ele);
433: VecRestoreArrayRead(coords,&_coords);
434: }
436: DPsi(user);
437: VecCopy(user->DPsiv,user->wv);
438: VecAXPY(user->wv,-2.0*user->kav,user->work2);
440: VecGetArray(X,&xx);
441: VecGetArray(user->wv,&wv_p);
442: VecGetArray(user->cv,&cv_p);
443: VecGetArray(user->eta,&eta_p);
445: for (i=0;i<n/3;i++)
446: {
447: xx[3*i]=wv_p[i];
448: xx[3*i+1]=cv_p[i];
449: xx[3*i+2]=eta_p[i];
450: }
452: PetscViewerBinaryOpen(PETSC_COMM_WORLD,"file_initial",FILE_MODE_WRITE,&view_out);
453: VecView(user->wv,view_out);
454: VecView(user->cv,view_out);
455: VecView(user->eta,view_out);
456: PetscViewerDestroy(&view_out);
458: VecRestoreArray(X,&xx);
459: VecRestoreArray(user->wv,&wv_p);
460: VecRestoreArray(user->cv,&cv_p);
461: VecRestoreArray(user->eta,&eta_p);
462: return(0);
463: }
467: PetscErrorCode FormFunction(SNES snes,Vec X,Vec F,void* ctx)
468: {
470: AppCtx *user=(AppCtx*)ctx;
471:
473: MatMultAdd(user->M,X,user->q,F);
474: return(0);
475: }
479: PetscErrorCode FormJacobian(SNES snes,Vec X,Mat *J,Mat *B,MatStructure *flg,void *ctx)
480: {
482: AppCtx *user=(AppCtx*)ctx;
483:
485: *flg = SAME_NONZERO_PATTERN;
486: MatCopy(user->M,*J,*flg);
487: MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
488: MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
489: return(0);
490: }
493: PetscErrorCode SetVariableBounds(DM da,Vec xl,Vec xu)
494: {
496: PetscScalar ***l,***u;
497: PetscInt xs,xm,ys,ym;
498: PetscInt i,j;
499:
501: DMDAVecGetArrayDOF(da,xl,&l);
502: DMDAVecGetArrayDOF(da,xu,&u);
503:
504: DMDAGetCorners(da,&xs,&ys,PETSC_NULL,&xm,&ym,PETSC_NULL);
505:
506: for (j=ys; j < ys+ym; j++) {
507: for(i=xs; i < xs+xm;i++) {
508: l[j][i][0] = -SNES_VI_INF;
509: l[j][i][1] = 0.0;
510: l[j][i][2] = 0.0;
511: u[j][i][0] = SNES_VI_INF;
512: u[j][i][1] = 1.0;
513: u[j][i][2] = 1.0;
514: }
515: }
516:
517: DMDAVecRestoreArrayDOF(da,xl,&l);
518: DMDAVecRestoreArrayDOF(da,xu,&u);
519: return(0);
520: }
524: PetscErrorCode GetParams(AppCtx* user)
525: {
527: PetscBool flg;
528:
530:
531: /* Set default parameters */
532: user->xmin = 0.0; user->xmax = 128.0;
533: user->ymin = 0.0; user->ymax = 128.0;
534: user->Mv = 1.0;
535: user->L = 1.0;
536: user->kaeta = 1.0;
537: user->kav = 0.5;
538: user->Evf = 9.09;
539: user->A = 9.09;
540: user->B = 9.09;
541: user->cv0 = 1.13e-4;
542: user->Sv = 500.0;
543: user->dt = 1.0e-5;
544: user->T = 1.0e-2;
545: user->graphics = PETSC_TRUE;
546: user->periodic = PETSC_FALSE;
547: user->lumpedmass = PETSC_FALSE;
548:
549: PetscOptionsGetReal(PETSC_NULL,"-xmin",&user->xmin,&flg);
550: PetscOptionsGetReal(PETSC_NULL,"-xmax",&user->xmax,&flg);
551: PetscOptionsGetReal(PETSC_NULL,"-T",&user->T,&flg);
552: PetscOptionsGetReal(PETSC_NULL,"-dt",&user->dt,&flg);
553: PetscOptionsBool("-graphics","Contour plot solutions at each timestep\n","None",user->graphics,&user->graphics,&flg);
554: PetscOptionsBool("-periodic","Use periodic boundary conditions\n","None",user->periodic,&user->periodic,&flg);
555: PetscOptionsBool("-lumpedmass","Use lumped mass matrix\n","None",user->lumpedmass,&user->lumpedmass,&flg);
556:
557: return(0);
558: }
563: PetscErrorCode SetUpMatrices(AppCtx* user)
564: {
565: PetscErrorCode ierr;
566: PetscInt nele,nen,i,n;
567: const PetscInt *ele;
568: PetscScalar dt=user->dt,h;
569:
570: PetscInt idx[3];
571: PetscScalar eM_0[3][3],eM_2[3][3];
572: Mat M=user->M;
573: Mat M_0=user->M_0;
574: PetscInt Mda,Nda;
576:
580: MatGetLocalSize(M,&n,PETSC_NULL);
581: DMDAGetInfo(user->da1,PETSC_NULL,&Mda,&Nda,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL);
583: if (Mda!=Nda) {
584: printf("Currently different Mda and Nda are not supported");
585: }
586: if (user->periodic) {
587: h = (user->xmax-user->xmin)/Mda;
588: } else {
589: h = (user->xmax-user->xmin)/(Mda-1.0);
590: }
591: if (user->lumpedmass) {
592: eM_0[0][0] = eM_0[1][1] = eM_0[2][2] = h*h/6.0;
593: eM_0[0][1] = eM_0[1][0] = eM_0[0][2] = eM_0[2][0] = eM_0[1][2] = eM_0[2][1] = 0.0;
594: } else {
595: eM_0[0][0] = eM_0[1][1] = eM_0[2][2] = h*h/12.0;
596: eM_0[0][1] = eM_0[0][2] = eM_0[1][0] = eM_0[1][2] = eM_0[2][0] = eM_0[2][1] = h*h/24.0;
597: }
598: eM_2[0][0] = 1.0;
599: eM_2[1][1] = eM_2[2][2] = 0.5;
600: eM_2[0][1] = eM_2[0][2] = eM_2[1][0]= eM_2[2][0] = -0.5;
601: eM_2[1][2] = eM_2[2][1] = 0.0;
604: /* Get local element info */
605: DMDAGetElements(user->da1,&nele,&nen,&ele);
606: for(i=0;i < nele;i++) {
607:
608: idx[0] = ele[3*i]; idx[1] = ele[3*i+1]; idx[2] = ele[3*i+2];
610: PetscInt row,cols[6],r,row_M_0,cols3[3];
611: PetscScalar vals[6],vals_M_0[3],vals3[3];
613: for(r=0;r<3;r++) {
614: row_M_0 = idx[r];
615: vals_M_0[0]=eM_0[r][0];
616: vals_M_0[1]=eM_0[r][1];
617: vals_M_0[2]=eM_0[r][2];
619: MatSetValuesLocal(M_0,1,&row_M_0,3,idx,vals_M_0,ADD_VALUES);
621: row = 3*idx[r];
622: cols[0] = 3*idx[0]; vals[0] = dt*eM_2[r][0]*user->Mv;
623: cols[1] = 3*idx[1]; vals[1] = dt*eM_2[r][1]*user->Mv;
624: cols[2] = 3*idx[2]; vals[2] = dt*eM_2[r][2]*user->Mv;
625: cols[3] = 3*idx[0]+1; vals[3] = eM_0[r][0];
626: cols[4] = 3*idx[1]+1; vals[4] = eM_0[r][1];
627: cols[5] = 3*idx[2]+1; vals[5] = eM_0[r][2];
628:
629: /* Insert values in matrix M for 1st dof */
630: MatSetValuesLocal(M,1,&row,6,cols,vals,ADD_VALUES);
631:
632: row = 3*idx[r]+1;
633: cols[0] = 3*idx[0]; vals[0] = -eM_0[r][0];
634: cols[1] = 3*idx[1]; vals[1] = -eM_0[r][1];
635: cols[2] = 3*idx[2]; vals[2] = -eM_0[r][2];
636: cols[3] = 3*idx[0]+1; vals[3] = 2.0*user->kav*eM_2[r][0];
637: cols[4] = 3*idx[1]+1; vals[4] = 2.0*user->kav*eM_2[r][1];
638: cols[5] = 3*idx[2]+1; vals[5] = 2.0*user->kav*eM_2[r][2];
640: /* Insert values in matrix M for 2nd dof */
641: MatSetValuesLocal(M,1,&row,6,cols,vals,ADD_VALUES);
642:
643: row = 3*idx[r]+2;
644: cols3[0] = 3*idx[0]+2; vals3[0] = eM_0[r][0] + user->dt*2.0*user->L*user->kaeta*eM_2[r][0];
645: cols3[1] = 3*idx[1]+2; vals3[1] = eM_0[r][1] + user->dt*2.0*user->L*user->kaeta*eM_2[r][1];
646: cols3[2] = 3*idx[2]+2; vals3[2] = eM_0[r][2] + user->dt*2.0*user->L*user->kaeta*eM_2[r][2];
647: MatSetValuesLocal(M,1,&row,3,cols3,vals3,ADD_VALUES);
648: }
649: }
651: MatAssemblyBegin(M_0,MAT_FINAL_ASSEMBLY);
652: MatAssemblyEnd(M_0,MAT_FINAL_ASSEMBLY);
653:
654: MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY);
655: MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY);
656:
657: DMDARestoreElements(user->da1,&nele,&nen,&ele);
658:
659:
660: return(0);
661: }
665: PetscErrorCode CheckRedundancy(SNES snes, IS act, IS *outact, DM da)
666: {
668: PetscScalar **uin,**uout;
669: Vec UIN, UOUT;
670: PetscInt xs,xm,*outindex;
671: const PetscInt *index;
672: PetscInt k,i,l,n,M,cnt=0;
673:
675: DMDAGetInfo(da,0,&M,0,0,0,0,0,0,0,0,0,0,0);
676: DMGetGlobalVector(da,&UIN);
677: VecSet(UIN,0.0);
678: DMGetLocalVector(da,&UOUT);
679: DMDAVecGetArrayDOF(da,UIN,&uin);
680: ISGetIndices(act,&index);
681: ISGetLocalSize(act,&n);
682: for (k=0;k<n;k++){
683: l = index[k]%5;
684: i = index[k]/5;
685: uin[i][l]=1.0;
686: }
687: printf("Number of active constraints before applying redundancy %d\n",n);
688: ISRestoreIndices(act,&index);
689: DMDAVecRestoreArrayDOF(da,UIN,&uin);
690: DMGlobalToLocalBegin(da,UIN,INSERT_VALUES,UOUT);
691: DMGlobalToLocalEnd(da,UIN,INSERT_VALUES,UOUT);
692: DMDAVecGetArrayDOF(da,UOUT,&uout);
693:
694: DMDAGetCorners(da,&xs,PETSC_NULL,PETSC_NULL,&xm,PETSC_NULL,PETSC_NULL);
696: for(i=xs; i < xs+xm;i++) {
697: if (uout[i-1][1] && uout[i][1] && uout[i+1][1])
698: uout[i][0] = 1.0;
699: if (uout[i-1][3] && uout[i][3] && uout[i+1][3])
700: uout[i][2] = 1.0;
701: }
703: for(i=xs; i < xs+xm;i++) {
704: for(l=0;l<5;l++) {
705: if (uout[i][l])
706: cnt++;
707: }
708: }
710: printf("Number of active constraints after applying redundancy %d\n",cnt);
711:
713: PetscMalloc(cnt*sizeof(PetscInt),&outindex);
714: cnt = 0;
715:
716: for(i=xs; i < xs+xm;i++) {
717: for(l=0;l<5;l++) {
718: if (uout[i][l])
719: outindex[cnt++] = 5*(i)+l;
720: }
721: }
722:
723:
724: ISCreateGeneral(PETSC_COMM_WORLD,cnt,outindex,PETSC_OWN_POINTER,outact);
725: DMDAVecRestoreArrayDOF(da,UOUT,&uout);
726: DMRestoreGlobalVector(da,&UIN);
727: DMRestoreLocalVector(da,&UOUT);
728: return(0);
729: }