Actual source code: ex64.c
petsc-dev 2014-02-02
1: static char help[] = "1D 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_linesearch_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_linesearch_type 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;
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);
62: /* Get physics and time parameters */
63: GetParams(&user);
65: if (user.periodic) {
66: DMDACreate1d(PETSC_COMM_WORLD,DMDA_BOUNDARY_PERIODIC, -4, 3, 1,NULL,&user.da1);
67: DMDACreate1d(PETSC_COMM_WORLD,DMDA_BOUNDARY_PERIODIC, -4, 3, 1,NULL,&user.da1_clone);
68: DMDACreate1d(PETSC_COMM_WORLD,DMDA_BOUNDARY_PERIODIC, -4, 1, 1,NULL,&user.da2);
69: } else {
70: DMDACreate1d(PETSC_COMM_WORLD,DMDA_BOUNDARY_NONE, -4, 3, 1,NULL,&user.da1);
71: DMDACreate1d(PETSC_COMM_WORLD,DMDA_BOUNDARY_NONE, -4, 3, 1,NULL,&user.da1_clone);
72: DMDACreate1d(PETSC_COMM_WORLD,DMDA_BOUNDARY_NONE, -4, 1, 1,NULL,&user.da2);
74: }
75: /* Set Element type (triangular) */
76: DMDASetElementType(user.da1,DMDA_ELEMENT_P1);
77: DMDASetElementType(user.da2,DMDA_ELEMENT_P1);
79: /* Set x and y coordinates */
80: DMDASetUniformCoordinates(user.da1,user.xmin,user.xmax,NULL,NULL,NULL,NULL);
81: DMDASetUniformCoordinates(user.da2,user.xmin,user.xmax,NULL,NULL,NULL,NULL);
82: /* Get global vector x from DM (da1) and duplicate vectors r,xl,xu */
83: DMCreateGlobalVector(user.da1,&x);
84: VecDuplicate(x,&r);
85: VecDuplicate(x,&xl);
86: VecDuplicate(x,&xu);
87: VecDuplicate(x,&user.q);
89: /* Get global vector user->wv from da2 and duplicate other vectors */
90: DMCreateGlobalVector(user.da2,&user.wv);
91: VecDuplicate(user.wv,&user.cv);
92: VecDuplicate(user.wv,&user.eta);
93: VecDuplicate(user.wv,&user.DPsiv);
94: VecDuplicate(user.wv,&user.DPsieta);
95: VecDuplicate(user.wv,&user.logcv);
96: VecDuplicate(user.wv,&user.logcv2);
97: VecDuplicate(user.wv,&user.work1);
98: VecDuplicate(user.wv,&user.work2);
100: /* Get Jacobian matrix structure from the da for the entire thing, da1 */
101: DMSetMatType(user.da1,MATAIJ);
102: DMCreateMatrix(user.da1,&user.M);
103: /* Get the (usual) mass matrix structure from da2 */
104: DMSetMatType(user.da2,MATAIJ);
105: DMCreateMatrix(user.da2,&user.M_0);
106: /* Form the jacobian matrix and M_0 */
107: SetUpMatrices(&user);
108: SetInitialGuess(x,&user);
109: MatDuplicate(user.M,MAT_DO_NOT_COPY_VALUES,&J);
111: SNESCreate(PETSC_COMM_WORLD,&snes);
112: SNESSetDM(snes,user.da1);
114: SNESSetFunction(snes,r,FormFunction,(void*)&user);
115: SNESSetJacobian(snes,J,J,FormJacobian,(void*)&user);
117: SetVariableBounds(user.da1,xl,xu);
118: SNESVISetVariableBounds(snes,xl,xu);
119: SNESSetFromOptions(snes);
120: /*SNESVISetRedundancyCheck(snes,(PetscErrorCode (*)(SNES,IS,IS*,void*))CheckRedundancy,user.da1_clone);*/
121: PetscViewerBinaryOpen(PETSC_COMM_WORLD,"file_out",FILE_MODE_WRITE,&view_out);
122: PetscViewerBinaryOpen(PETSC_COMM_WORLD,"file_p",FILE_MODE_WRITE,&view_p);
123: PetscViewerBinaryOpen(PETSC_COMM_WORLD,"file_q",FILE_MODE_WRITE,&view_q);
124: PetscViewerBinaryOpen(PETSC_COMM_WORLD,"file_psi",FILE_MODE_WRITE,&view_psi);
125: PetscViewerBinaryOpen(PETSC_COMM_WORLD,"file_mat",FILE_MODE_WRITE,&view_mat);
126: /* PetscViewerDrawSetBounds(PETSC_VIEWER_DRAW_(PETSC_COMM_WORLD),5,bounds); */
128: if (user.graphics) {
129: PetscViewerDrawSetBounds(PETSC_VIEWER_DRAW_(PETSC_COMM_WORLD),5,bounds);
131: VecView(x,PETSC_VIEWER_DRAW_(PETSC_COMM_WORLD));
132: }
133: while (t<user.T) {
135: char filename[PETSC_MAX_PATH_LEN];
136: PetscScalar a = 1.0;
137: PetscInt i;
138: PetscViewer view;
141: SNESSetFunction(snes,r,FormFunction,(void*)&user);
142: SNESSetJacobian(snes,J,J,FormJacobian,(void*)&user);
144: DPsi(&user);
145: VecView(user.DPsiv,view_psi);
146: VecView(user.DPsieta,view_psi);
148: Update_q(&user);
149: VecView(user.q,view_q);
150: MatView(user.M,view_mat);
152: SNESSolve(snes,NULL,x);
153: VecView(x,view_out);
156: if (user.graphics) {
157: VecView(x,PETSC_VIEWER_DRAW_(PETSC_COMM_WORLD));
158: }
160: PetscInt its;
161: SNESGetIterationNumber(snes,&its);
162: PetscPrintf(PETSC_COMM_WORLD,"SNESVI solver converged at t = %5.4g in %d iterations\n",t,its);
164: Update_u(x,&user);
166: for (i=0; i < (int)(user.T/a) ; i++) {
167: if (t/a > i - user.dt/a && t/a < i + user.dt/a) {
168: sprintf(filename,"output_%f",t);
169: PetscViewerBinaryOpen(PETSC_COMM_WORLD,filename,FILE_MODE_WRITE,&view);
170: VecView(user.cv,view);
171: VecView(user.eta,view);
172: PetscViewerDestroy(&view);
173: }
174: }
176: t = t + user.dt;
178: }
181: PetscViewerDestroy(&view_out);
182: PetscViewerDestroy(&view_p);
183: PetscViewerDestroy(&view_q);
184: PetscViewerDestroy(&view_psi);
185: PetscViewerDestroy(&view_mat);
186: VecDestroy(&x);
187: VecDestroy(&r);
188: VecDestroy(&xl);
189: VecDestroy(&xu);
190: VecDestroy(&user.q);
191: VecDestroy(&user.wv);
192: VecDestroy(&user.cv);
193: VecDestroy(&user.eta);
194: VecDestroy(&user.DPsiv);
195: VecDestroy(&user.DPsieta);
196: VecDestroy(&user.logcv);
197: VecDestroy(&user.logcv2);
198: VecDestroy(&user.work1);
199: VecDestroy(&user.work2);
200: MatDestroy(&user.M);
201: MatDestroy(&user.M_0);
202: DMDestroy(&user.da1);
203: DMDestroy(&user.da1_clone);
204: DMDestroy(&user.da2);
205: SNESDestroy(&snes);
206: PetscFinalize();
207: return 0;
208: }
212: PetscErrorCode Update_u(Vec X,AppCtx *user)
213: {
215: PetscInt i,n;
216: PetscScalar *xx,*wv_p,*cv_p,*eta_p;
219: VecGetLocalSize(user->wv,&n);
221: VecGetArray(X,&xx);
222: VecGetArray(user->wv,&wv_p);
223: VecGetArray(user->cv,&cv_p);
224: VecGetArray(user->eta,&eta_p);
227: for (i=0; i<n; i++) {
228: wv_p[i] = xx[3*i];
229: cv_p[i] = xx[3*i+1];
230: eta_p[i] = xx[3*i+2];
231: }
232: VecRestoreArray(X,&xx);
233: VecRestoreArray(user->wv,&wv_p);
234: VecRestoreArray(user->cv,&cv_p);
235: VecRestoreArray(user->eta,&eta_p);
236: return(0);
237: }
241: PetscErrorCode Update_q(AppCtx *user)
242: {
244: PetscScalar *q_p, *w1, *w2;
245: PetscInt n,i;
248: VecGetArray(user->q,&q_p);
249: VecGetArray(user->work1,&w1);
250: VecGetArray(user->work2,&w2);
251: VecGetLocalSize(user->wv,&n);
253: MatMult(user->M_0,user->cv,user->work1);
254: VecScale(user->work1,-1.0);
255: for (i=0; i<n; i++) q_p[3*i]=w1[i];
257: MatMult(user->M_0,user->DPsiv,user->work1);
258: for (i=0; i<n; i++) q_p[3*i+1]=w1[i];
260: VecCopy(user->DPsieta,user->work1);
261: VecScale(user->work1,user->L*user->dt);
262: VecAXPY(user->work1,-1.0,user->eta);
263: MatMult(user->M_0,user->work1,user->work2);
264: for (i=0; i<n; i++) q_p[3*i+2]=w2[i];
266: VecRestoreArray(user->q,&q_p);
267: VecRestoreArray(user->work1,&w1);
268: VecRestoreArray(user->work2,&w2);
269: return(0);
270: }
274: PetscErrorCode DPsi(AppCtx *user)
275: {
277: PetscScalar Evf=user->Evf,A=user->A,B=user->B,cv0=user->cv0;
278: PetscScalar *cv_p,*eta_p,*logcv_p,*logcv2_p,*DPsiv_p,*DPsieta_p;
279: PetscInt n,i;
282: VecGetLocalSize(user->cv,&n);
283: VecGetArray(user->cv,&cv_p);
284: VecGetArray(user->eta,&eta_p);
285: VecGetArray(user->logcv,&logcv_p);
286: VecGetArray(user->logcv2,&logcv2_p);
287: VecGetArray(user->DPsiv,&DPsiv_p);
288: VecGetArray(user->DPsieta,&DPsieta_p);
290: Llog(user->cv,user->logcv);
292: VecCopy(user->cv,user->work1);
293: VecScale(user->work1,-1.0);
294: VecShift(user->work1,1.0);
295: Llog(user->work1,user->logcv2);
297: for (i=0; i<n; i++)
298: {
299: 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];
301: 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];
303: }
305: VecRestoreArray(user->cv,&cv_p);
306: VecRestoreArray(user->eta,&eta_p);
307: VecGetArray(user->logcv,&logcv_p);
308: VecGetArray(user->logcv2,&logcv2_p);
309: VecRestoreArray(user->DPsiv,&DPsiv_p);
310: VecRestoreArray(user->DPsieta,&DPsieta_p);
311: return(0);
313: }
318: PetscErrorCode Llog(Vec X, Vec Y)
319: {
321: PetscScalar *x,*y;
322: PetscInt n,i;
325: VecGetArray(X,&x);
326: VecGetArray(Y,&y);
327: VecGetLocalSize(X,&n);
328: for (i=0; i<n; i++) {
329: if (x[i] < 1.0e-12) y[i] = log(1.0e-12);
330: else y[i] = log(x[i]);
331: }
332: return(0);
333: }
337: PetscErrorCode SetInitialGuess(Vec X,AppCtx *user)
338: {
341: PetscInt n,i,Mda;
342: PetscScalar *xx,*cv_p,*wv_p,*eta_p;
343: PetscViewer view_out;
345: /* needed for the void growth case */
346: PetscScalar xmid,cv_v=1.0,cv_m=user->Sv*user->cv0,eta_v=1.0,eta_m=0.0,h,lambda;
347: PetscInt nele,nen,idx[2];
348: const PetscInt *ele;
349: PetscScalar x[2];
350: Vec coords;
351: const PetscScalar *_coords;
352: PetscScalar xwidth = user->xmax - user->xmin;
355: VecGetLocalSize(X,&n);
357: DMDAGetInfo(user->da2,NULL,&Mda,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
358: DMGetCoordinatesLocal(user->da2,&coords);
359: VecGetArrayRead(coords,&_coords);
361: if (user->periodic) h = (user->xmax-user->xmin)/Mda;
362: else h = (user->xmax-user->xmin)/(Mda-1.0);
364: xmid = (user->xmax + user->xmin)/2.0;
365: lambda = 4.0*h;
367: DMDAGetElements(user->da2,&nele,&nen,&ele);
368: for (i=0; i < nele; i++) {
369: idx[0] = ele[2*i]; idx[1] = ele[2*i+1];
371: x[0] = _coords[idx[0]];
372: x[1] = _coords[idx[1]];
375: PetscInt k;
376: PetscScalar vals_DDcv[2],vals_cv[2],vals_eta[2],s,hhr,r;
377: for (k=0; k < 2; k++) {
378: s = PetscAbs(x[k] - xmid);
379: if (s <= xwidth*(5.0/64.0)) {
380: vals_cv[k] = cv_v;
381: vals_eta[k] = eta_v;
382: vals_DDcv[k] = 0.0;
383: } else if (s> xwidth*(5.0/64.0) && s<= xwidth*(7.0/64.0)) {
384: /*r = (s - xwidth*(6.0/64.0))/(0.5*lambda);*/
385: r = (s - xwidth*(6.0/64.0))/(xwidth/64.0);
386: hhr = 0.25*(-r*r*r + 3*r + 2);
387: vals_cv[k] = cv_m + (1.0 - hhr)*(cv_v - cv_m);
388: vals_eta[k] = eta_m + (1.0 - hhr)*(eta_v - eta_m);
389: vals_DDcv[k] = (cv_v - cv_m)*r*6.0/(lambda*lambda);
390: } else {
391: vals_cv[k] = cv_m;
392: vals_eta[k] = eta_m;
393: vals_DDcv[k] = 0.0;
394: }
395: }
397: VecSetValuesLocal(user->cv,2,idx,vals_cv,INSERT_VALUES);
398: VecSetValuesLocal(user->eta,2,idx,vals_eta,INSERT_VALUES);
399: VecSetValuesLocal(user->work2,2,idx,vals_DDcv,INSERT_VALUES);
401: }
402: DMDARestoreElements(user->da2,&nele,&nen,&ele);
403: VecRestoreArrayRead(coords,&_coords);
405: VecAssemblyBegin(user->cv);
406: VecAssemblyEnd(user->cv);
407: VecAssemblyBegin(user->eta);
408: VecAssemblyEnd(user->eta);
409: VecAssemblyBegin(user->work2);
410: VecAssemblyEnd(user->work2);
412: DPsi(user);
413: VecCopy(user->DPsiv,user->wv);
414: VecAXPY(user->wv,-2.0*user->kav,user->work2);
416: VecGetArray(X,&xx);
417: VecGetArray(user->wv,&wv_p);
418: VecGetArray(user->cv,&cv_p);
419: VecGetArray(user->eta,&eta_p);
421: for (i=0; i<n/3; i++) {
422: xx[3*i] =wv_p[i];
423: xx[3*i+1]=cv_p[i];
424: xx[3*i+2]=eta_p[i];
425: }
427: PetscViewerBinaryOpen(PETSC_COMM_WORLD,"file_initial",FILE_MODE_WRITE,&view_out);
428: VecView(user->wv,view_out);
429: VecView(user->cv,view_out);
430: VecView(user->eta,view_out);
431: PetscViewerDestroy(&view_out);
433: VecRestoreArray(X,&xx);
434: VecRestoreArray(user->wv,&wv_p);
435: VecRestoreArray(user->cv,&cv_p);
436: VecRestoreArray(user->eta,&eta_p);
437: return(0);
438: }
442: PetscErrorCode FormFunction(SNES snes,Vec X,Vec F,void *ctx)
443: {
445: AppCtx *user=(AppCtx*)ctx;
448: MatMultAdd(user->M,X,user->q,F);
449: return(0);
450: }
454: PetscErrorCode FormJacobian(SNES snes,Vec X,Mat *J,Mat *B,MatStructure *flg,void *ctx)
455: {
457: AppCtx *user=(AppCtx*)ctx;
460: *flg = SAME_NONZERO_PATTERN;
461: MatCopy(user->M,*J,*flg);
462: MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
463: MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
464: return(0);
465: }
468: PetscErrorCode SetVariableBounds(DM da,Vec xl,Vec xu)
469: {
471: PetscScalar **l,**u;
472: PetscInt xs,xm;
473: PetscInt i;
476: DMDAVecGetArrayDOF(da,xl,&l);
477: DMDAVecGetArrayDOF(da,xu,&u);
479: DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);
482: for (i=xs; i < xs+xm; i++) {
483: l[i][0] = -PETSC_INFINITY;
484: l[i][1] = 0.0;
485: l[i][2] = 0.0;
486: u[i][0] = PETSC_INFINITY;
487: u[i][1] = 1.0;
488: u[i][2] = 1.0;
489: }
491: DMDAVecRestoreArrayDOF(da,xl,&l);
492: DMDAVecRestoreArrayDOF(da,xu,&u);
493: return(0);
494: }
498: PetscErrorCode GetParams(AppCtx *user)
499: {
501: PetscBool flg;
504: /* Set default parameters */
505: user->xmin = 0.0; user->xmax = 128.0;
506: user->Mv = 1.0;
507: user->L = 1.0;
508: user->kaeta = 1.0;
509: user->kav = 0.5;
510: user->Evf = 9.09;
511: user->A = 9.09;
512: user->B = 9.09;
513: user->cv0 = 1.13e-4;
514: user->Sv = 500.0;
515: user->dt = 1.0e-5;
516: user->T = 1.0e-2;
517: user->graphics = PETSC_TRUE;
518: user->periodic = PETSC_FALSE;
519: user->lumpedmass = PETSC_FALSE;
521: PetscOptionsGetReal(NULL,"-xmin",&user->xmin,&flg);
522: PetscOptionsGetReal(NULL,"-xmax",&user->xmax,&flg);
523: PetscOptionsGetReal(NULL,"-T",&user->T,&flg);
524: PetscOptionsGetReal(NULL,"-dt",&user->dt,&flg);
525: PetscOptionsBool("-graphics","Contour plot solutions at each timestep\n","None",user->graphics,&user->graphics,&flg);
526: PetscOptionsBool("-periodic","Use periodic boundary conditions\n","None",user->periodic,&user->periodic,&flg);
527: PetscOptionsBool("-lumpedmass","Use lumped mass matrix\n","None",user->lumpedmass,&user->lumpedmass,&flg);
528: return(0);
529: }
534: PetscErrorCode SetUpMatrices(AppCtx *user)
535: {
537: PetscInt nele,nen,i,n;
538: const PetscInt *ele;
539: PetscScalar dt=user->dt,h;
541: PetscInt idx[2];
542: PetscScalar eM_0[2][2],eM_2[2][2];
543: Mat M =user->M;
544: Mat M_0=user->M_0;
545: PetscInt Mda;
549: MatGetLocalSize(M,&n,NULL);
550: DMDAGetInfo(user->da1,NULL,&Mda,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
552: if (user->periodic) h = (user->xmax-user->xmin)/Mda;
553: else h = (user->xmax-user->xmin)/(Mda-1.0);
555: if (user->lumpedmass) {
556: eM_0[0][0] = h/2.0;
557: eM_0[1][1] = h/2.0;
558: eM_0[0][1] = eM_0[1][0] = 0.0;
559: } else {
560: eM_0[0][0]=eM_0[1][1]=h/3.0;
561: eM_0[0][1]=eM_0[1][0]=h/6.0;
562: }
563: eM_2[0][0]=eM_2[1][1]=1.0/h;
564: eM_2[0][1]=eM_2[1][0]=-1.0/h;
566: /* Get local element info */
567: DMDAGetElements(user->da1,&nele,&nen,&ele);
568: for (i=0; i < nele; i++) {
570: idx[0] = ele[2*i]; idx[1] = ele[2*i+1];
572: PetscInt row,cols[4],r,row_M_0,cols2[2];
573: PetscScalar vals[4],vals_M_0[2],vals2[2];
575: for (r=0; r<2; r++) {
576: row_M_0 = idx[r];
577: vals_M_0[0]=eM_0[r][0];
578: vals_M_0[1]=eM_0[r][1];
580: MatSetValuesLocal(M_0,1,&row_M_0,2,idx,vals_M_0,ADD_VALUES);
582: row = 3*idx[r];
583: cols[0] = 3*idx[0]; vals[0] = dt*eM_2[r][0]*user->Mv;
584: cols[1] = 3*idx[1]; vals[1] = dt*eM_2[r][1]*user->Mv;
585: cols[2] = 3*idx[0]+1; vals[2] = eM_0[r][0];
586: cols[3] = 3*idx[1]+1; vals[3] = eM_0[r][1];
588: /* Insert values in matrix M for 1st dof */
589: MatSetValuesLocal(M,1,&row,4,cols,vals,ADD_VALUES);
591: row = 3*idx[r]+1;
592: cols[0] = 3*idx[0]; vals[0] = -eM_0[r][0];
593: cols[1] = 3*idx[1]; vals[1] = -eM_0[r][1];
594: cols[2] = 3*idx[0]+1; vals[2] = 2.0*user->kav*eM_2[r][0];
595: cols[3] = 3*idx[1]+1; vals[3] = 2.0*user->kav*eM_2[r][1];
597: /* Insert values in matrix M for 2nd dof */
598: MatSetValuesLocal(M,1,&row,4,cols,vals,ADD_VALUES);
601: row = 3*idx[r]+2;
602: cols2[0] = 3*idx[0]+2; vals2[0] = eM_0[r][0] + user->dt*2.0*user->L*user->kaeta*eM_2[r][0];
603: cols2[1] = 3*idx[1]+2; vals2[1] = eM_0[r][1] + user->dt*2.0*user->L*user->kaeta*eM_2[r][1];
605: MatSetValuesLocal(M,1,&row,2,cols2,vals2,ADD_VALUES);
606: }
607: }
609: MatAssemblyBegin(M_0,MAT_FINAL_ASSEMBLY);
610: MatAssemblyEnd(M_0,MAT_FINAL_ASSEMBLY);
612: MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY);
613: MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY);
615: DMDARestoreElements(user->da1,&nele,&nen,&ele);
616: return(0);
617: }
621: PetscErrorCode CheckRedundancy(SNES snes, IS act, IS *outact, DM da)
622: {
624: PetscScalar **uin,**uout;
625: Vec UIN, UOUT;
626: PetscInt xs,xm,*outindex;
627: const PetscInt *index;
628: PetscInt k,i,l,n,M,cnt=0;
631: DMDAGetInfo(da,0,&M,0,0,0,0,0,0,0,0,0,0,0);
632: DMGetGlobalVector(da,&UIN);
633: VecSet(UIN,0.0);
634: DMGetLocalVector(da,&UOUT);
635: DMDAVecGetArrayDOF(da,UIN,&uin);
636: ISGetIndices(act,&index);
637: ISGetLocalSize(act,&n);
638: for (k=0; k<n; k++) {
639: l = index[k]%5;
640: i = index[k]/5;
642: uin[i][l]=1.0;
643: }
644: printf("Number of active constraints before applying redundancy %d\n",n);
645: ISRestoreIndices(act,&index);
646: DMDAVecRestoreArrayDOF(da,UIN,&uin);
647: DMGlobalToLocalBegin(da,UIN,INSERT_VALUES,UOUT);
648: DMGlobalToLocalEnd(da,UIN,INSERT_VALUES,UOUT);
649: DMDAVecGetArrayDOF(da,UOUT,&uout);
651: DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);
653: for (i=xs; i < xs+xm;i++) {
654: if (uout[i-1][1] && uout[i][1] && uout[i+1][1]) uout[i][0] = 1.0;
655: if (uout[i-1][3] && uout[i][3] && uout[i+1][3]) uout[i][2] = 1.0;
656: }
658: for (i=xs; i < xs+xm; i++) {
659: for (l=0; l < 5; l++) {
660: if (uout[i][l]) cnt++;
661: }
662: }
664: printf("Number of active constraints after applying redundancy %d\n",cnt);
666: PetscMalloc1(cnt,&outindex);
667: cnt = 0;
669: for (i=xs; i < xs+xm;i++) {
670: for (l=0;l<5;l++) {
671: if (uout[i][l]) outindex[cnt++] = 5*(i)+l;
672: }
673: }
676: ISCreateGeneral(PETSC_COMM_WORLD,cnt,outindex,PETSC_OWN_POINTER,outact);
677: DMDAVecRestoreArrayDOF(da,UOUT,&uout);
678: DMRestoreGlobalVector(da,&UIN);
679: DMRestoreLocalVector(da,&UOUT);
680: return(0);
681: }