Actual source code: ex43.c
petsc-3.6.0 2015-06-09
1: static char help[] = "Solves the incompressible, variable viscosity Stokes equation in 2d on the unit domain \n\
2: using Q1Q1 elements, stabilized with Bochev's polynomial projection method. \n\
3: The models defined utilise free slip boundary conditions on all sides. \n\
4: Options: \n"
5: "\
6: -mx : Number of elements in the x-direction \n\
7: -my : Number of elements in the y-direction \n\
8: -o : Specify output filename for solution (will be petsc binary format or paraview format if the extension is .vts) \n\
9: -gnuplot : Output Gauss point coordinates, coefficients and u,p solution in gnuplot format \n\
10: -c_str : Indicates the structure of the coefficients to use \n"
11: "\
12: -c_str 0 => Coefficient definition for an analytic solution with a vertical jump in viscosity at x = xc \n\
13: This problem is driven by the forcing function f(x,y) = (0, sin(nz pi y)cos(pi x) \n\
14: Parameters: \n\
15: -solcx_eta0 : Viscosity to the left of the interface \n\
16: -solcx_eta1 : Viscosity to the right of the interface \n\
17: -solcx_xc : Location of the interface \n\
18: -solcx_nz : Wavenumber in the y direction \n"
19: "\
20: -c_str 1 => Coefficient definition for a dense rectangular blob located at the center of the domain \n\
21: Parameters: \n\
22: -sinker_eta0 : Viscosity of the background fluid \n\
23: -sinker_eta1 : Viscosity of the blob \n\
24: -sinker_dx : Width of the blob \n\
25: -sinker_dy : Height of the blob \n"
26: "\
27: -c_str 2 => Coefficient definition for a dense circular blob located at the center of the domain \n\
28: Parameters: \n\
29: -sinker_eta0 : Viscosity of the background fluid \n\
30: -sinker_eta1 : Viscosity of the blob \n\
31: -sinker_r : Radius of the blob \n"
32: "\
33: -c_str 3 => Coefficient definition for a dense circular and rectangular inclusion (located at the center of the domain) \n\
34: -sinker_eta0 : Viscosity of the background fluid \n\
35: -sinker_eta1 : Viscosity of the two inclusions \n\
36: -sinker_r : Radius of the circular inclusion \n\
37: -sinker_c0x : Origin (x-coord) of the circular inclusion \n\
38: -sinker_c0y : Origin (y-coord) of the circular inclusion \n\
39: -sinker_dx : Width of the rectangular inclusion \n\
40: -sinker_dy : Height of the rectangular inclusion \n\
41: -sinker_phi : Rotation angle of the rectangular inclusion \n\
42: -use_gp_coords : Evaluate the viscosity and force term at the global coordinates of each quadrature point \n\
43: By default, the viscosity and force term are evaulated at the element center and applied as a constant over the entire element \n" ;
45: /* Contributed by Dave May */
47: #include <petscksp.h>
48: #include <petscdm.h>
49: #include <petscdmda.h>
51: /* A Maple-generated exact solution created by Mirko Velic (mirko.velic@sci.monash.edu.au) */
52: #include "ex43-solcx.h"
54: static PetscErrorCode DMDABCApplyFreeSlip(DM ,Mat ,Vec ) ;
57: #define NSD 2 /* number of spatial dimensions */
58: #define NODES_PER_EL 4 /* nodes per element */
59: #define U_DOFS 2 /* degrees of freedom per velocity node */
60: #define P_DOFS 1 /* degrees of freedom per pressure node */
61: #define GAUSS_POINTS 4
63: /* Gauss point based evaluation 8+4+4+4 = 20 */
64: typedef struct {
65: PetscScalar gp_coords[2*GAUSS_POINTS];
66: PetscScalar eta[GAUSS_POINTS];
67: PetscScalar fx[GAUSS_POINTS];
68: PetscScalar fy[GAUSS_POINTS];
69: } GaussPointCoefficients;
71: typedef struct {
72: PetscScalar u_dof;
73: PetscScalar v_dof;
74: PetscScalar p_dof;
75: } StokesDOF;
78: /*
79: Element: Local basis function ordering
80: 1-----2
81: | |
82: | |
83: 0-----3
84: */
85: static void ConstructQ12D_Ni(PetscScalar _xi[],PetscScalar Ni[])
86: {
87: PetscScalar xi = _xi[0];
88: PetscScalar eta = _xi[1];
90: Ni[0] = 0.25*(1.0-xi)*(1.0-eta);
91: Ni[1] = 0.25*(1.0-xi)*(1.0+eta);
92: Ni[2] = 0.25*(1.0+xi)*(1.0+eta);
93: Ni[3] = 0.25*(1.0+xi)*(1.0-eta);
94: }
96: static void ConstructQ12D_GNi(PetscScalar _xi[],PetscScalar GNi[][NODES_PER_EL])
97: {
98: PetscScalar xi = _xi[0];
99: PetscScalar eta = _xi[1];
101: GNi[0][0] = -0.25*(1.0-eta);
102: GNi[0][1] = -0.25*(1.0+eta);
103: GNi[0][2] = 0.25*(1.0+eta);
104: GNi[0][3] = 0.25*(1.0-eta);
106: GNi[1][0] = -0.25*(1.0-xi);
107: GNi[1][1] = 0.25*(1.0-xi);
108: GNi[1][2] = 0.25*(1.0+xi);
109: GNi[1][3] = -0.25*(1.0+xi);
110: }
112: static void ConstructQ12D_GNx(PetscScalar GNi[][NODES_PER_EL],PetscScalar GNx[][NODES_PER_EL],PetscScalar coords[],PetscScalar *det_J)
113: {
114: PetscScalar J00,J01,J10,J11,J;
115: PetscScalar iJ00,iJ01,iJ10,iJ11;
116: PetscInt i;
118: J00 = J01 = J10 = J11 = 0.0;
119: for (i = 0; i < NODES_PER_EL; i++) {
120: PetscScalar cx = coords[2*i];
121: PetscScalar cy = coords[2*i+1];
123: J00 = J00+GNi[0][i]*cx; /* J_xx = dx/dxi */
124: J01 = J01+GNi[0][i]*cy; /* J_xy = dy/dxi */
125: J10 = J10+GNi[1][i]*cx; /* J_yx = dx/deta */
126: J11 = J11+GNi[1][i]*cy; /* J_yy = dy/deta */
127: }
128: J = (J00*J11)-(J01*J10);
130: iJ00 = J11/J;
131: iJ01 = -J01/J;
132: iJ10 = -J10/J;
133: iJ11 = J00/J;
135: for (i = 0; i < NODES_PER_EL; i++) {
136: GNx[0][i] = GNi[0][i]*iJ00+GNi[1][i]*iJ01;
137: GNx[1][i] = GNi[0][i]*iJ10+GNi[1][i]*iJ11;
138: }
140: if (det_J != NULL) *det_J = J;
141: }
143: static void ConstructGaussQuadrature(PetscInt *ngp,PetscScalar gp_xi[][2],PetscScalar gp_weight[])
144: {
145: *ngp = 4;
146: gp_xi[0][0] = -0.57735026919; gp_xi[0][1] = -0.57735026919;
147: gp_xi[1][0] = -0.57735026919; gp_xi[1][1] = 0.57735026919;
148: gp_xi[2][0] = 0.57735026919; gp_xi[2][1] = 0.57735026919;
149: gp_xi[3][0] = 0.57735026919; gp_xi[3][1] = -0.57735026919;
150: gp_weight[0] = 1.0;
151: gp_weight[1] = 1.0;
152: gp_weight[2] = 1.0;
153: gp_weight[3] = 1.0;
154: }
156: /* procs to the left claim the ghost node as their element */
159: static PetscErrorCode DMDAGetLocalElementSize(DM da,PetscInt *mxl,PetscInt *myl,PetscInt *mzl)
160: {
161: PetscInt m,n,p,M,N,P;
162: PetscInt sx,sy,sz;
165: DMDAGetInfo (da,0,&M,&N,&P,0,0,0,0,0,0,0,0,0);
166: DMDAGetCorners (da,&sx,&sy,&sz,&m,&n,&p);
168: if (mxl != NULL) {
169: *mxl = m;
170: if ((sx+m) == M) *mxl = m-1; /* last proc */
171: }
172: if (myl != NULL) {
173: *myl = n;
174: if ((sy+n) == N) *myl = n-1; /* last proc */
175: }
176: if (mzl != NULL) {
177: *mzl = p;
178: if ((sz+p) == P) *mzl = p-1; /* last proc */
179: }
180: return (0);
181: }
185: static PetscErrorCode DMDAGetElementCorners(DM da,PetscInt *sx,PetscInt *sy,PetscInt *sz,PetscInt *mx,PetscInt *my,PetscInt *mz)
186: {
187: PetscInt si,sj,sk;
190: DMDAGetGhostCorners (da,&si,&sj,&sk,0,0,0);
192: *sx = si;
193: if (si) *sx = si+1;
195: *sy = sj;
196: if (sj) *sy = sj+1;
198: if (sk) {
199: *sz = sk;
200: if (sk != 0) *sz = sk+1;
201: }
203: DMDAGetLocalElementSize(da,mx,my,mz);
204: return (0);
205: }
207: /*
208: i,j are the element indices
209: The unknown is a vector quantity.
210: The s[].c is used to indicate the degree of freedom.
211: */
214: static PetscErrorCode DMDAGetElementEqnums_up(MatStencil s_u[],MatStencil s_p[],PetscInt i,PetscInt j)
215: {
217: /* velocity */
218: /* node 0 */
219: s_u[0].i = i; s_u[0].j = j; s_u[0].c = 0; /* Vx0 */
220: s_u[1].i = i; s_u[1].j = j; s_u[1].c = 1; /* Vy0 */
222: /* node 1 */
223: s_u[2].i = i; s_u[2].j = j+1; s_u[2].c = 0; /* Vx1 */
224: s_u[3].i = i; s_u[3].j = j+1; s_u[3].c = 1; /* Vy1 */
226: /* node 2 */
227: s_u[4].i = i+1; s_u[4].j = j+1; s_u[4].c = 0; /* Vx2 */
228: s_u[5].i = i+1; s_u[5].j = j+1; s_u[5].c = 1; /* Vy2 */
230: /* node 3 */
231: s_u[6].i = i+1; s_u[6].j = j; s_u[6].c = 0; /* Vx3 */
232: s_u[7].i = i+1; s_u[7].j = j; s_u[7].c = 1; /* Vy3 */
234: /* pressure */
235: s_p[0].i = i; s_p[0].j = j; s_p[0].c = 2; /* P0 */
236: s_p[1].i = i; s_p[1].j = j+1; s_p[1].c = 2; /* P1 */
237: s_p[2].i = i+1; s_p[2].j = j+1; s_p[2].c = 2; /* P2 */
238: s_p[3].i = i+1; s_p[3].j = j; s_p[3].c = 2; /* P3 */
239: return (0);
240: }
244: static PetscErrorCode DMDAGetElementOwnershipRanges2d(DM da,PetscInt **_lx,PetscInt **_ly)
245: {
247: PetscMPIInt rank;
248: PetscInt proc_I,proc_J;
249: PetscInt cpu_x,cpu_y;
250: PetscInt local_mx,local_my;
251: Vec vlx,vly;
252: PetscInt *LX,*LY,i;
253: PetscScalar *_a;
254: Vec V_SEQ;
255: VecScatter ctx;
258: MPI_Comm_rank (PETSC_COMM_WORLD ,&rank);
260: DMDAGetInfo (da,0,0,0,0,&cpu_x,&cpu_y,0,0,0,0,0,0,0);
262: proc_J = rank/cpu_x;
263: proc_I = rank-cpu_x*proc_J;
265: PetscMalloc1 (cpu_x,&LX);
266: PetscMalloc1 (cpu_y,&LY);
268: DMDAGetLocalElementSize(da,&local_mx,&local_my,NULL);
269: VecCreate (PETSC_COMM_WORLD ,&vlx);
270: VecSetSizes (vlx,PETSC_DECIDE ,cpu_x);
271: VecSetFromOptions (vlx);
273: VecCreate (PETSC_COMM_WORLD ,&vly);
274: VecSetSizes (vly,PETSC_DECIDE ,cpu_y);
275: VecSetFromOptions (vly);
277: VecSetValue (vlx,proc_I,(PetscScalar )(local_mx+1.0e-9),INSERT_VALUES );
278: VecSetValue (vly,proc_J,(PetscScalar )(local_my+1.0e-9),INSERT_VALUES );
279: VecAssemblyBegin (vlx);VecAssemblyEnd (vlx);
280: VecAssemblyBegin (vly);VecAssemblyEnd (vly);
282: VecScatterCreateToAll (vlx,&ctx,&V_SEQ);
283: VecScatterBegin (ctx,vlx,V_SEQ,INSERT_VALUES ,SCATTER_FORWARD );
284: VecScatterEnd (ctx,vlx,V_SEQ,INSERT_VALUES ,SCATTER_FORWARD );
285: VecGetArray (V_SEQ,&_a);
286: for (i = 0; i < cpu_x; i++) LX[i] = (PetscInt )PetscRealPart(_a[i]);
287: VecRestoreArray (V_SEQ,&_a);
288: VecScatterDestroy (&ctx);
289: VecDestroy (&V_SEQ);
291: VecScatterCreateToAll (vly,&ctx,&V_SEQ);
292: VecScatterBegin (ctx,vly,V_SEQ,INSERT_VALUES ,SCATTER_FORWARD );
293: VecScatterEnd (ctx,vly,V_SEQ,INSERT_VALUES ,SCATTER_FORWARD );
294: VecGetArray (V_SEQ,&_a);
295: for (i = 0; i < cpu_y; i++) LY[i] = (PetscInt )PetscRealPart(_a[i]);
296: VecRestoreArray (V_SEQ,&_a);
297: VecScatterDestroy (&ctx);
298: VecDestroy (&V_SEQ);
300: *_lx = LX;
301: *_ly = LY;
303: VecDestroy (&vlx);
304: VecDestroy (&vly);
305: return (0);
306: }
310: static PetscErrorCode DMDACoordViewGnuplot2d(DM da,const char prefix[])
311: {
312: DM cda;
313: Vec coords;
314: DMDACoor2d **_coords;
315: PetscInt si,sj,nx,ny,i,j;
316: FILE *fp;
317: char fname[PETSC_MAX_PATH_LEN];
318: PetscMPIInt rank;
322: MPI_Comm_rank (PETSC_COMM_WORLD ,&rank);
323: PetscSNPrintf (fname,sizeof (fname),"%s-p%1.4d.dat" ,prefix,rank);
324: PetscFOpen (PETSC_COMM_SELF ,fname,"w" ,&fp);
325: if (!fp) SETERRQ (PETSC_COMM_SELF ,PETSC_ERR_USER,"Cannot open file" );
327: PetscFPrintf (PETSC_COMM_SELF ,fp,"### Element geometry for processor %1.4d ### \n" ,rank);
329: DMGetCoordinateDM (da,&cda);
330: DMGetCoordinatesLocal (da,&coords);
331: DMDAVecGetArrayRead (cda,coords,&_coords);
332: DMDAGetGhostCorners (cda,&si,&sj,0,&nx,&ny,0);
333: for (j = sj; j < sj+ny-1; j++) {
334: for (i = si; i < si+nx-1; i++) {
335: PetscFPrintf (PETSC_COMM_SELF ,fp,"%1.6e %1.6e \n" ,(double)PetscRealPart(_coords[j][i].x),(double)PetscRealPart(_coords[j][i].y));
336: PetscFPrintf (PETSC_COMM_SELF ,fp,"%1.6e %1.6e \n" ,(double)PetscRealPart(_coords[j+1][i].x),(double)PetscRealPart(_coords[j+1][i].y));
337: PetscFPrintf (PETSC_COMM_SELF ,fp,"%1.6e %1.6e \n" ,(double)PetscRealPart(_coords[j+1][i+1].x),(double)PetscRealPart(_coords[j+1][i+1].y));
338: PetscFPrintf (PETSC_COMM_SELF ,fp,"%1.6e %1.6e \n" ,(double)PetscRealPart(_coords[j][i+1].x),(double)PetscRealPart(_coords[j][i+1].y));
339: PetscFPrintf (PETSC_COMM_SELF ,fp,"%1.6e %1.6e \n\n" ,(double)PetscRealPart(_coords[j][i].x),(double)PetscRealPart(_coords[j][i].y));
340: }
341: }
342: DMDAVecRestoreArrayRead (cda,coords,&_coords);
344: PetscFClose (PETSC_COMM_SELF ,fp);
345: return (0);
346: }
350: static PetscErrorCode DMDAViewGnuplot2d(DM da,Vec fields,const char comment[],const char prefix[])
351: {
352: DM cda;
353: Vec coords,local_fields;
354: DMDACoor2d **_coords;
355: FILE *fp;
356: char fname[PETSC_MAX_PATH_LEN];
357: PetscMPIInt rank;
358: PetscInt si,sj,nx,ny,i,j;
359: PetscInt n_dofs,d;
360: PetscScalar *_fields;
364: MPI_Comm_rank (PETSC_COMM_WORLD ,&rank);
365: PetscSNPrintf (fname,sizeof (fname),"%s-p%1.4d.dat" ,prefix,rank);
366: PetscFOpen (PETSC_COMM_SELF ,fname,"w" ,&fp);
367: if (!fp) SETERRQ (PETSC_COMM_SELF ,PETSC_ERR_USER,"Cannot open file" );
369: PetscFPrintf (PETSC_COMM_SELF ,fp,"### %s (processor %1.4d) ### \n" ,comment,rank);
370: DMDAGetInfo (da,0,0,0,0,0,0,0,&n_dofs,0,0,0,0,0);
371: PetscFPrintf (PETSC_COMM_SELF ,fp,"### x y " );
372: for (d = 0; d < n_dofs; d++) {
373: const char *field_name;
374: DMDAGetFieldName (da,d,&field_name);
375: PetscFPrintf (PETSC_COMM_SELF ,fp,"%s " ,field_name);
376: }
377: PetscFPrintf (PETSC_COMM_SELF ,fp,"###\n" );
379: DMGetCoordinateDM (da,&cda);
380: DMGetCoordinatesLocal (da,&coords);
381: DMDAVecGetArray (cda,coords,&_coords);
382: DMDAGetGhostCorners (cda,&si,&sj,0,&nx,&ny,0);
384: DMCreateLocalVector (da,&local_fields);
385: DMGlobalToLocalBegin (da,fields,INSERT_VALUES ,local_fields);
386: DMGlobalToLocalEnd (da,fields,INSERT_VALUES ,local_fields);
387: VecGetArray (local_fields,&_fields);
389: for (j = sj; j < sj+ny; j++) {
390: for (i = si; i < si+nx; i++) {
391: PetscScalar coord_x,coord_y;
392: PetscScalar field_d;
394: coord_x = _coords[j][i].x;
395: coord_y = _coords[j][i].y;
397: PetscFPrintf (PETSC_COMM_SELF ,fp,"%1.6e %1.6e " ,(double)PetscRealPart(coord_x),(double)PetscRealPart(coord_y));
398: for (d = 0; d < n_dofs; d++) {
399: field_d = _fields[n_dofs*((i-si)+(j-sj)*(nx))+d];
400: PetscFPrintf (PETSC_COMM_SELF ,fp,"%1.6e " ,(double)PetscRealPart(field_d));
401: }
402: PetscFPrintf (PETSC_COMM_SELF ,fp,"\n" );
403: }
404: }
405: VecRestoreArray (local_fields,&_fields);
406: VecDestroy (&local_fields);
408: DMDAVecRestoreArray (cda,coords,&_coords);
410: PetscFClose (PETSC_COMM_SELF ,fp);
411: return (0);
412: }
416: static PetscErrorCode DMDAViewCoefficientsGnuplot2d(DM da,Vec fields,const char comment[],const char prefix[])
417: {
418: DM cda;
419: Vec local_fields;
420: FILE *fp;
421: char fname[PETSC_MAX_PATH_LEN];
422: PetscMPIInt rank;
423: PetscInt si,sj,nx,ny,i,j,p;
424: PetscInt n_dofs,d;
425: GaussPointCoefficients **_coefficients;
426: PetscErrorCode ierr;
429: MPI_Comm_rank (PETSC_COMM_WORLD ,&rank);
430: PetscSNPrintf (fname,sizeof (fname),"%s-p%1.4d.dat" ,prefix,rank);
431: PetscFOpen (PETSC_COMM_SELF ,fname,"w" ,&fp);
432: if (!fp) SETERRQ (PETSC_COMM_SELF ,PETSC_ERR_USER,"Cannot open file" );
434: PetscFPrintf (PETSC_COMM_SELF ,fp,"### %s (processor %1.4d) ### \n" ,comment,rank);
435: DMDAGetInfo (da,0,0,0,0,0,0,0,&n_dofs,0,0,0,0,0);
436: PetscFPrintf (PETSC_COMM_SELF ,fp,"### x y " );
437: for (d = 0; d < n_dofs; d++) {
438: const char *field_name;
439: DMDAGetFieldName (da,d,&field_name);
440: PetscFPrintf (PETSC_COMM_SELF ,fp,"%s " ,field_name);
441: }
442: PetscFPrintf (PETSC_COMM_SELF ,fp,"###\n" );
444: DMGetCoordinateDM (da,&cda);
445: DMDAGetGhostCorners (cda,&si,&sj,0,&nx,&ny,0);
447: DMCreateLocalVector (da,&local_fields);
448: DMGlobalToLocalBegin (da,fields,INSERT_VALUES ,local_fields);
449: DMGlobalToLocalEnd (da,fields,INSERT_VALUES ,local_fields);
450: DMDAVecGetArray (da,local_fields,&_coefficients);
452: for (j = sj; j < sj+ny; j++) {
453: for (i = si; i < si+nx; i++) {
454: PetscScalar coord_x,coord_y;
456: for (p = 0; p < GAUSS_POINTS; p++) {
457: coord_x = _coefficients[j][i].gp_coords[2*p];
458: coord_y = _coefficients[j][i].gp_coords[2*p+1];
460: PetscFPrintf (PETSC_COMM_SELF ,fp,"%1.6e %1.6e " ,(double)PetscRealPart(coord_x),(double)PetscRealPart(coord_y));
462: PetscFPrintf (PETSC_COMM_SELF ,fp,"%1.6e %1.6e %1.6e" ,(double)PetscRealPart(_coefficients[j][i].eta[p]),(double)PetscRealPart(_coefficients[j][i].fx[p]),(double)PetscRealPart(_coefficients[j][i].fy[p]));
463: PetscFPrintf (PETSC_COMM_SELF ,fp,"\n" );
464: }
465: }
466: }
467: DMDAVecRestoreArray (da,local_fields,&_coefficients);
468: VecDestroy (&local_fields);
470: PetscFClose (PETSC_COMM_SELF ,fp);
471: return (0);
472: }
474: static PetscInt ASS_MAP_wIwDI_uJuDJ(PetscInt wi,PetscInt wd,PetscInt w_NPE,PetscInt w_dof,PetscInt ui,PetscInt ud,PetscInt u_NPE,PetscInt u_dof)
475: {
476: PetscInt ij;
477: PetscInt r,c,nc;
479: nc = u_NPE*u_dof;
481: r = w_dof*wi+wd;
482: c = u_dof*ui+ud;
484: ij = r*nc+c;
486: return ij;
487: }
489: /*
490: D = [ 2.eta 0 0 ]
491: [ 0 2.eta 0 ]
492: [ 0 0 eta ]
493:
494: B = [ d_dx 0 ]
495: [ 0 d_dy ]
496: [ d_dy d_dx ]
497: */
498: static void FormStressOperatorQ1(PetscScalar Ke[],PetscScalar coords[],PetscScalar eta[])
499: {
500: PetscInt ngp;
501: PetscScalar gp_xi[GAUSS_POINTS][2];
502: PetscScalar gp_weight[GAUSS_POINTS];
503: PetscInt p,i,j,k;
504: PetscScalar GNi_p[NSD][NODES_PER_EL],GNx_p[NSD][NODES_PER_EL];
505: PetscScalar J_p,tildeD[3];
506: PetscScalar B[3][U_DOFS*NODES_PER_EL];
508: /* define quadrature rule */
509: ConstructGaussQuadrature(&ngp,gp_xi,gp_weight);
511: /* evaluate integral */
512: for (p = 0; p < ngp; p++) {
513: ConstructQ12D_GNi(gp_xi[p],GNi_p);
514: ConstructQ12D_GNx(GNi_p,GNx_p,coords,&J_p);
516: for (i = 0; i < NODES_PER_EL; i++) {
517: PetscScalar d_dx_i = GNx_p[0][i];
518: PetscScalar d_dy_i = GNx_p[1][i];
520: B[0][2*i] = d_dx_i;B[0][2*i+1] = 0.0;
521: B[1][2*i] = 0.0;B[1][2*i+1] = d_dy_i;
522: B[2][2*i] = d_dy_i;B[2][2*i+1] = d_dx_i;
523: }
525: tildeD[0] = 2.0*gp_weight[p]*J_p*eta[p];
526: tildeD[1] = 2.0*gp_weight[p]*J_p*eta[p];
527: tildeD[2] = gp_weight[p]*J_p*eta[p];
529: /* form Bt tildeD B */
530: /*
531: Ke_ij = Bt_ik . D_kl . B_lj
532: = B_ki . D_kl . B_lj
533: = B_ki . D_kk . B_kj
534: */
535: for (i = 0; i < 8; i++) {
536: for (j = 0; j < 8; j++) {
537: for (k = 0; k < 3; k++) { /* Note D is diagonal for stokes */
538: Ke[i+8*j] = Ke[i+8*j]+B[k][i]*tildeD[k]*B[k][j];
539: }
540: }
541: }
542: }
543: }
545: static void FormGradientOperatorQ1(PetscScalar Ke[],PetscScalar coords[])
546: {
547: PetscInt ngp;
548: PetscScalar gp_xi[GAUSS_POINTS][2];
549: PetscScalar gp_weight[GAUSS_POINTS];
550: PetscInt p,i,j,di;
551: PetscScalar Ni_p[NODES_PER_EL];
552: PetscScalar GNi_p[NSD][NODES_PER_EL],GNx_p[NSD][NODES_PER_EL];
553: PetscScalar J_p,fac;
555: /* define quadrature rule */
556: ConstructGaussQuadrature(&ngp,gp_xi,gp_weight);
558: /* evaluate integral */
559: for (p = 0; p < ngp; p++) {
560: ConstructQ12D_Ni(gp_xi[p],Ni_p);
561: ConstructQ12D_GNi(gp_xi[p],GNi_p);
562: ConstructQ12D_GNx(GNi_p,GNx_p,coords,&J_p);
563: fac = gp_weight[p]*J_p;
565: for (i = 0; i < NODES_PER_EL; i++) { /* u nodes */
566: for (di = 0; di < NSD; di++) { /* u dofs */
567: for (j = 0; j < 4; j++) { /* p nodes, p dofs = 1 (ie no loop) */
568: PetscInt IJ;
569: IJ = ASS_MAP_wIwDI_uJuDJ(i,di,NODES_PER_EL,2,j,0,NODES_PER_EL,1);
571: Ke[IJ] = Ke[IJ]-GNx_p[di][i]*Ni_p[j]*fac;
572: }
573: }
574: }
575: }
576: }
578: static void FormDivergenceOperatorQ1(PetscScalar De[],PetscScalar coords[])
579: {
580: PetscScalar Ge[U_DOFS*NODES_PER_EL*P_DOFS*NODES_PER_EL];
581: PetscInt i,j;
582: PetscInt nr_g,nc_g;
584: PetscMemzero (Ge,sizeof (PetscScalar )*U_DOFS*NODES_PER_EL*P_DOFS*NODES_PER_EL);
585: FormGradientOperatorQ1(Ge,coords);
587: nr_g = U_DOFS*NODES_PER_EL;
588: nc_g = P_DOFS*NODES_PER_EL;
590: for (i = 0; i < nr_g; i++) {
591: for (j = 0; j < nc_g; j++) {
592: De[nr_g*j+i] = Ge[nc_g*i+j];
593: }
594: }
595: }
597: static void FormStabilisationOperatorQ1(PetscScalar Ke[],PetscScalar coords[],PetscScalar eta[])
598: {
599: PetscInt ngp;
600: PetscScalar gp_xi[GAUSS_POINTS][2];
601: PetscScalar gp_weight[GAUSS_POINTS];
602: PetscInt p,i,j;
603: PetscScalar Ni_p[NODES_PER_EL];
604: PetscScalar GNi_p[NSD][NODES_PER_EL],GNx_p[NSD][NODES_PER_EL];
605: PetscScalar J_p,fac,eta_avg;
607: /* define quadrature rule */
608: ConstructGaussQuadrature(&ngp,gp_xi,gp_weight);
610: /* evaluate integral */
611: for (p = 0; p < ngp; p++) {
612: ConstructQ12D_Ni(gp_xi[p],Ni_p);
613: ConstructQ12D_GNi(gp_xi[p],GNi_p);
614: ConstructQ12D_GNx(GNi_p,GNx_p,coords,&J_p);
615: fac = gp_weight[p]*J_p;
617: for (i = 0; i < NODES_PER_EL; i++) {
618: for (j = 0; j < NODES_PER_EL; j++) {
619: Ke[NODES_PER_EL*i+j] = Ke[NODES_PER_EL*i+j]-fac*(Ni_p[i]*Ni_p[j]-0.0625);
620: }
621: }
622: }
624: /* scale */
625: eta_avg = 0.0;
626: for (p = 0; p < ngp; p++) eta_avg += eta[p];
627: eta_avg = (1.0/((PetscScalar )ngp))*eta_avg;
628: fac = 1.0/eta_avg;
629: for (i = 0; i < NODES_PER_EL; i++) {
630: for (j = 0; j < NODES_PER_EL; j++) {
631: Ke[NODES_PER_EL*i+j] = fac*Ke[NODES_PER_EL*i+j];
632: }
633: }
634: }
636: static void FormScaledMassMatrixOperatorQ1(PetscScalar Ke[],PetscScalar coords[],PetscScalar eta[])
637: {
638: PetscInt ngp;
639: PetscScalar gp_xi[GAUSS_POINTS][2];
640: PetscScalar gp_weight[GAUSS_POINTS];
641: PetscInt p,i,j;
642: PetscScalar Ni_p[NODES_PER_EL];
643: PetscScalar GNi_p[NSD][NODES_PER_EL],GNx_p[NSD][NODES_PER_EL];
644: PetscScalar J_p,fac,eta_avg;
646: /* define quadrature rule */
647: ConstructGaussQuadrature(&ngp,gp_xi,gp_weight);
649: /* evaluate integral */
650: for (p = 0; p < ngp; p++) {
651: ConstructQ12D_Ni(gp_xi[p],Ni_p);
652: ConstructQ12D_GNi(gp_xi[p],GNi_p);
653: ConstructQ12D_GNx(GNi_p,GNx_p,coords,&J_p);
654: fac = gp_weight[p]*J_p;
656: for (i = 0; i < NODES_PER_EL; i++) {
657: for (j = 0; j < NODES_PER_EL; j++) {
658: Ke[NODES_PER_EL*i+j] = Ke[NODES_PER_EL*i+j]-fac*Ni_p[i]*Ni_p[j];
659: }
660: }
661: }
663: /* scale */
664: eta_avg = 0.0;
665: for (p = 0; p < ngp; p++) eta_avg += eta[p];
666: eta_avg = (1.0/((PetscScalar )ngp))*eta_avg;
667: fac = 1.0/eta_avg;
668: for (i = 0; i < NODES_PER_EL; i++) {
669: for (j = 0; j < NODES_PER_EL; j++) {
670: Ke[NODES_PER_EL*i+j] = fac*Ke[NODES_PER_EL*i+j];
671: }
672: }
673: }
675: static void FormMomentumRhsQ1(PetscScalar Fe[],PetscScalar coords[],PetscScalar fx[],PetscScalar fy[])
676: {
677: PetscInt ngp;
678: PetscScalar gp_xi[GAUSS_POINTS][2];
679: PetscScalar gp_weight[GAUSS_POINTS];
680: PetscInt p,i;
681: PetscScalar Ni_p[NODES_PER_EL];
682: PetscScalar GNi_p[NSD][NODES_PER_EL],GNx_p[NSD][NODES_PER_EL];
683: PetscScalar J_p,fac;
685: /* define quadrature rule */
686: ConstructGaussQuadrature(&ngp,gp_xi,gp_weight);
688: /* evaluate integral */
689: for (p = 0; p < ngp; p++) {
690: ConstructQ12D_Ni(gp_xi[p],Ni_p);
691: ConstructQ12D_GNi(gp_xi[p],GNi_p);
692: ConstructQ12D_GNx(GNi_p,GNx_p,coords,&J_p);
693: fac = gp_weight[p]*J_p;
695: for (i = 0; i < NODES_PER_EL; i++) {
696: Fe[NSD*i] += fac*Ni_p[i]*fx[p];
697: Fe[NSD*i+1] += fac*Ni_p[i]*fy[p];
698: }
699: }
700: }
704: static PetscErrorCode GetElementCoords(DMDACoor2d **_coords,PetscInt ei,PetscInt ej,PetscScalar el_coords[])
705: {
707: /* get coords for the element */
708: el_coords[NSD*0] = _coords[ej][ei].x; el_coords[NSD*0+1] = _coords[ej][ei].y;
709: el_coords[NSD*1] = _coords[ej+1][ei].x; el_coords[NSD*1+1] = _coords[ej+1][ei].y;
710: el_coords[NSD*2] = _coords[ej+1][ei+1].x; el_coords[NSD*2+1] = _coords[ej+1][ei+1].y;
711: el_coords[NSD*3] = _coords[ej][ei+1].x; el_coords[NSD*3+1] = _coords[ej][ei+1].y;
712: return (0);
713: }
717: static PetscErrorCode AssembleA_Stokes(Mat A,DM stokes_da,DM properties_da,Vec properties)
718: {
719: DM cda;
720: Vec coords;
721: DMDACoor2d **_coords;
722: MatStencil u_eqn[NODES_PER_EL*U_DOFS]; /* 2 degrees of freedom */
723: MatStencil p_eqn[NODES_PER_EL*P_DOFS]; /* 1 degrees of freedom */
724: PetscInt sex,sey,mx,my;
725: PetscInt ei,ej;
726: PetscScalar Ae[NODES_PER_EL*U_DOFS*NODES_PER_EL*U_DOFS];
727: PetscScalar Ge[NODES_PER_EL*U_DOFS*NODES_PER_EL*P_DOFS];
728: PetscScalar De[NODES_PER_EL*P_DOFS*NODES_PER_EL*U_DOFS];
729: PetscScalar Ce[NODES_PER_EL*P_DOFS*NODES_PER_EL*P_DOFS];
730: PetscScalar el_coords[NODES_PER_EL*NSD];
731: Vec local_properties;
732: GaussPointCoefficients **props;
733: PetscScalar *prop_eta;
734: PetscErrorCode ierr;
737: /* setup for coords */
738: DMGetCoordinateDM (stokes_da,&cda);
739: DMGetCoordinatesLocal (stokes_da,&coords);
740: DMDAVecGetArray (cda,coords,&_coords);
742: /* setup for coefficients */
743: DMCreateLocalVector (properties_da,&local_properties);
744: DMGlobalToLocalBegin (properties_da,properties,INSERT_VALUES ,local_properties);
745: DMGlobalToLocalEnd (properties_da,properties,INSERT_VALUES ,local_properties);
746: DMDAVecGetArray (properties_da,local_properties,&props);
748: DMDAGetElementCorners(stokes_da,&sex,&sey,0,&mx,&my,0);
749: for (ej = sey; ej < sey+my; ej++) {
750: for (ei = sex; ei < sex+mx; ei++) {
751: /* get coords for the element */
752: GetElementCoords(_coords,ei,ej,el_coords);
754: /* get coefficients for the element */
755: prop_eta = props[ej][ei].eta;
757: /* initialise element stiffness matrix */
758: PetscMemzero (Ae,sizeof (PetscScalar )*NODES_PER_EL*U_DOFS*NODES_PER_EL*U_DOFS);
759: PetscMemzero (Ge,sizeof (PetscScalar )*NODES_PER_EL*U_DOFS*NODES_PER_EL*P_DOFS);
760: PetscMemzero (De,sizeof (PetscScalar )*NODES_PER_EL*P_DOFS*NODES_PER_EL*U_DOFS);
761: PetscMemzero (Ce,sizeof (PetscScalar )*NODES_PER_EL*P_DOFS*NODES_PER_EL*P_DOFS);
763: /* form element stiffness matrix */
764: FormStressOperatorQ1(Ae,el_coords,prop_eta);
765: FormGradientOperatorQ1(Ge,el_coords);
766: FormDivergenceOperatorQ1(De,el_coords);
767: FormStabilisationOperatorQ1(Ce,el_coords,prop_eta);
769: /* insert element matrix into global matrix */
770: DMDAGetElementEqnums_up(u_eqn,p_eqn,ei,ej);
771: MatSetValuesStencil (A,NODES_PER_EL*U_DOFS,u_eqn,NODES_PER_EL*U_DOFS,u_eqn,Ae,ADD_VALUES );
772: MatSetValuesStencil (A,NODES_PER_EL*U_DOFS,u_eqn,NODES_PER_EL*P_DOFS,p_eqn,Ge,ADD_VALUES );
773: MatSetValuesStencil (A,NODES_PER_EL*P_DOFS,p_eqn,NODES_PER_EL*U_DOFS,u_eqn,De,ADD_VALUES );
774: MatSetValuesStencil (A,NODES_PER_EL*P_DOFS,p_eqn,NODES_PER_EL*P_DOFS,p_eqn,Ce,ADD_VALUES );
775: }
776: }
777: MatAssemblyBegin (A,MAT_FINAL_ASSEMBLY);
778: MatAssemblyEnd (A,MAT_FINAL_ASSEMBLY);
780: DMDAVecRestoreArray (cda,coords,&_coords);
782: DMDAVecRestoreArray (properties_da,local_properties,&props);
783: VecDestroy (&local_properties);
784: return (0);
785: }
789: static PetscErrorCode AssembleA_PCStokes(Mat A,DM stokes_da,DM properties_da,Vec properties)
790: {
791: DM cda;
792: Vec coords;
793: DMDACoor2d **_coords;
794: MatStencil u_eqn[NODES_PER_EL*U_DOFS]; /* 2 degrees of freedom */
795: MatStencil p_eqn[NODES_PER_EL*P_DOFS]; /* 1 degrees of freedom */
796: PetscInt sex,sey,mx,my;
797: PetscInt ei,ej;
798: PetscScalar Ae[NODES_PER_EL*U_DOFS*NODES_PER_EL*U_DOFS];
799: PetscScalar Ge[NODES_PER_EL*U_DOFS*NODES_PER_EL*P_DOFS];
800: PetscScalar De[NODES_PER_EL*P_DOFS*NODES_PER_EL*U_DOFS];
801: PetscScalar Ce[NODES_PER_EL*P_DOFS*NODES_PER_EL*P_DOFS];
802: PetscScalar el_coords[NODES_PER_EL*NSD];
803: Vec local_properties;
804: GaussPointCoefficients **props;
805: PetscScalar *prop_eta;
806: PetscErrorCode ierr;
809: /* setup for coords */
810: DMGetCoordinateDM (stokes_da,&cda);
811: DMGetCoordinatesLocal (stokes_da,&coords);
812: DMDAVecGetArray (cda,coords,&_coords);
814: /* setup for coefficients */
815: DMCreateLocalVector (properties_da,&local_properties);
816: DMGlobalToLocalBegin (properties_da,properties,INSERT_VALUES ,local_properties);
817: DMGlobalToLocalEnd (properties_da,properties,INSERT_VALUES ,local_properties);
818: DMDAVecGetArray (properties_da,local_properties,&props);
820: DMDAGetElementCorners(stokes_da,&sex,&sey,0,&mx,&my,0);
821: for (ej = sey; ej < sey+my; ej++) {
822: for (ei = sex; ei < sex+mx; ei++) {
823: /* get coords for the element */
824: GetElementCoords(_coords,ei,ej,el_coords);
826: /* get coefficients for the element */
827: prop_eta = props[ej][ei].eta;
829: /* initialise element stiffness matrix */
830: PetscMemzero (Ae,sizeof (PetscScalar )*NODES_PER_EL*U_DOFS*NODES_PER_EL*U_DOFS);
831: PetscMemzero (Ge,sizeof (PetscScalar )*NODES_PER_EL*U_DOFS*NODES_PER_EL*P_DOFS);
832: PetscMemzero (De,sizeof (PetscScalar )*NODES_PER_EL*P_DOFS*NODES_PER_EL*U_DOFS);
833: PetscMemzero (Ce,sizeof (PetscScalar )*NODES_PER_EL*P_DOFS*NODES_PER_EL*P_DOFS);
835: /* form element stiffness matrix */
836: FormStressOperatorQ1(Ae,el_coords,prop_eta);
837: FormGradientOperatorQ1(Ge,el_coords);
line839">839: FormScaledMassMatrixOperatorQ1(Ce,el_coords,pro
/* insert element matrix into global matrix */
line842">842: DMDAGetElementEqnums_up(u_eqn,p_eqn,
line843">843: MatSetValuesStencil (A,NODES_PER_EL*U_DOFS,u_eqn,NODES_PER_EL*U_DOFS,u_eqn,Ae,ADD_VALUE
line844">844: MatSetValuesStencil (A,NODES_PER_EL*U_DOFS,u_eqn,NODES_PER_EL*P_DOFS,p_eqn,Ge,ADD_VALUE
/* MatSetValuesStencil (A, NODES_PER_EL*P_DOFS,p_eqn,NODES_PER_EL*U_DOFS,u_eqn,De,ADD_VALUES );*/
line846">846: MatSetValuesStencil (A,NODES_PER_EL*P_DOFS,p_eqn,NODES_PER_EL*P_DOFS,p_eqn,Ce,ADD_VALUE
line847">847:
line848">848:
line849">849: MatAssemblyBegin (A,MAT_FINAL_ASS
line850">850: MatAssemblyEnd (A,MAT_FINAL_ASS
line852">852: DMDAVecRestoreArray (cda,coords,&_c
line854">854: DMDAVecRestoreArray (properties_da,local_properties,&
line855">855: VecDestroy (&local_prope
line856">856: return
line857">857
line861">861: static PetscErrorCode DMDASetValuesLocalStencil_ADD_VALUES(StokesDOF **fields_F,MatStencil u_eqn[],MatStencil p_eqn[],PetscScalar Fe_u[],PetscScalar Fe_p[])
line862">862
line863">863: PetscInt
line866">866: for (n = 0; n < 4;
line867">867: fields_F[u_eqn[2*n].j][u_eqn[2*n].i].u_dof = fields_F[u_eqn[2*n].j][u_eqn[2*n].i].u_dof+Fe_
line868">868: fields_F[u_eqn[2*n+1].j][u_eqn[2*n+1].i].v_dof = fields_F[u_eqn[2*n+1].j][u_eqn[2*n+1].i].v_dof+Fe_u[
line869">869: fields_F[p_eqn[n].j][p_eqn[n].i].p_dof = fields_F[p_eqn[n].j][p_eqn[n].i].p_dof+F
line870">870:
line871">871: return
line872">872
line876">876: static PetscErrorCode AssembleF_Stokes(Vec F,DM stokes_da,DM properties_da,Vec properties)
line877">877
line878">878: DM
line879">879: Vec
line880">880: DMDACoor2d **_
/* 2 degrees of freedom */
/* 1 degrees of freedom */
line883">883: PetscInt sex,sey
line884">884: PetscInt
line885">885: PetscScalar Fe[NODES_PER_EL*U
line886">886: PetscScalar He[NODES_PER_EL*P
line887">887: PetscScalar el_coords[NODES_PER_E
line888">888: Vec local_prop
line889">889: GaussPointCoefficients *
line890">890: PetscScalar *prop_fx,*p
line891">891: Vec l
line892">892: StokesDOF
line893">893: PetscErrorCode
/* setup for coords */
line897">897: DMGetCoordinateDM (stokes_da,&am
line898">898: DMGetCoordinatesLocal (stokes_da,&c
line899">899: DMDAVecGetArray (cda,coords,&_c
/* setup for coefficients */
line902">902: DMGetLocalVector (properties_da,&local_prope
line903">903: DMGlobalToLocalBegin (properties_da,properties,INSERT_VALUES ,local_prope
line904">904: DMGlobalToLocalEnd (properties_da,properties,INSERT_VALUES ,local_prope
line905">905: DMDAVecGetArray (properties_da,local_properties,&
/* get acces to the vector */
line908">908: DMGetLocalVector (stokes_da,&lo
line909">909: VecZeroEntries (lo
line910">910: DMDAVecGetArray (stokes_da,local_F,&a
line912">912: DMDAGetElementCorners(stokes_da,&sex,&sey,0,&mx,&
line913">913: for (ej = sey; ej < sey+my;
line914">914: for (ei = sex; ei < sex+mx;
/* get coords for the element */
line916">916: GetElementCoords(_coords,ei,ej,el_c
/* get coefficients for the element */
line919">919: prop_fx = props[ej][
line920">920: prop_fy = props[ej][
/* initialise element stiffness matrix */
line923">923: PetscMemzero (Fe,sizeof (PetscScalar )*NODES_PER_EL*U
line924">924: PetscMemzero (He,sizeof (PetscScalar )*NODES_PER_EL*P
/* form element stiffness matrix */
line927">927: FormMomentumRhsQ1(Fe,el_coords,prop_fx,pr
/* insert element matrix into global matrix */
line930">930: DMDAGetElementEqnums_up(u_eqn,p_eqn,
line932">932: DMDASetValuesLocalStencil_ADD_VALUES(ff,u_eqn,p_eqn,
line933">933:
line934">934:
line936">936: DMDAVecRestoreArray (stokes_da,local_F,&a
line937">937: DMLocalToGlobalBegin (stokes_da,local_F,ADD_VALUES<
line938">938: DMLocalToGlobalEnd (stokes_da,local_F,ADD_VALUES<
line939">939: DMRestoreLocalVector (stokes_da,&lo
line941">941: DMDAVecRestoreArray (cda,coords,&_c
line943">943: DMDAVecRestoreArray (properties_da,local_properties,&
line944">944: DMRestoreLocalVector (properties_da,&local_prope
line945">945: return
line946">946
line950">950: static PetscErrorCode DMDACreateSolCx(PetscReal eta0,PetscReal eta1,PetscReal xc,PetscInt nz,PetscInt mx,PetscInt my,DM *_da,Vec *_X)
line951">951
line952">952: DM
line953">953: Vec
line954">954: StokesDOF **_
line955">955: Vec
line956">956: DMDACoor2d **_
line957">957: PetscInt si,sj,ei,
line961">961: DMDACreate2d (PETSC_COMM_WORLD , DM_BOUNDARY_NONE, DM_BOUNDARY_NONE,DMDA_STENCIL_B
line962">962: mx+1,my+1,PETSC_DECIDE ,PETSC_DECIDE ,3,1,NULL,NULL,&a
line963">963: DMDASetFieldName (da,0,"anlytic_Vx"
line964">964: DMDASetFieldName (da,1,"anlytic_Vy"
line965">965: DMDASetFieldName (da,2,"analytic_P"
line967">967: DMDASetUniformCoordinates (da,0.0,1.0,0.0,1.0,
line969">969: DMGetCoordinatesLocal (da,&c
line970">970: DMGetCoordinateDM (da,&am
line971">971: DMDAVecGetArray (cda,coords,&_c
line973">973: DMCreateGlobalVector (da,&
line974">974: DMDAVecGetArray (da,X,&_s
line976">976: DMDAGetCorners (da,&si,&sj,0,&ei,&
line977">977: for (j = sj; j < sj+ej;
line978">978: for (i = si; i < si+ei;
line979">979: PetscReal pos[2],pressure,vel[2],total_stress[3],strain_r
line981">981: pos[0] = PetscRealPart(_coords[j]
line982">982: pos[1] = PetscRealPart(_coords[j]
line984">984: evaluate_solCx(pos,eta0,eta1,xc,nz,vel,&pressure,total_stress,strain
line986">986: _stokes[j][i].u_dof =
line987">987: _stokes[j][i].v_dof =
line988">988: _stokes[j][i].p_dof = pr
line989">989:
line990">990:
line991">991: DMDAVecRestoreArray (da,X,&_s
line992">992: DMDAVecRestoreArray (cda,coords,&_c
line994">994: *_d
line995">995: *_
line996">996: return
line997">997
line1001">1001: static PetscErrorCode StokesDAGetNodalFields(StokesDOF **fields,PetscInt ei,PetscInt ej,StokesDOF nodal_fields[])
line1002">1002
/* get the nodal fields */
line1005">1005: nodal_fields[0].u_dof = fields[ej][ei].u_dof; nodal_fields[0].v_dof = fields[ej][ei].v_dof; nodal_fields[0].p_dof = fields[ej][ei]
line1006">1006: nodal_fields[1].u_dof = fields[ej+1][ei].u_dof; nodal_fields[1].v_dof = fields[ej+1][ei].v_dof; nodal_fields[1].p_dof = fields[ej+1][ei]
line1007">1007: nodal_fields[2].u_dof = fields[ej+1][ei+1].u_dof; nodal_fields[2].v_dof = fields[ej+1][ei+1].v_dof; nodal_fields[2].p_dof = fields[ej+1][ei+1]
line1008">1008: nodal_fields[3].u_dof = fields[ej][ei+1].u_dof; nodal_fields[3].v_dof = fields[ej][ei+1].v_dof; nodal_fields[3].p_dof = fields[ej][ei+1]
line1009">1009: return
line1010">1010
line1014">1014: static PetscErrorCode DMDAIntegrateErrors(DM stokes_da,Vec X,Vec X_analytic)
line1015">1015
line1016">1016: DM
line1017">1017: Vec coords,X_analytic_local,X
line1018">1018: DMDACoor2d **_
line1019">1019: PetscInt sex,sey
line1020">1020: PetscInt
line1021">1021: PetscScalar el_coords[NODES_PER_E
line1022">1022: StokesDOF **stokes_analytic,**
line1023">1023: StokesDOF stokes_analytic_e[4],stoke
line1025">1025: PetscScalar GNi_p[NSD][NODES_PER_EL],GNx_p[NSD][NODES_P
line1026">1026: PetscScalar Ni_p[NODES_P
line1027">1027: PetscInt
line1028">1028: PetscScalar gp_xi[GAUSS_POIN
line1029">1029: PetscScalar gp_weight[GAUSS_P
line1030">1030: PetscInt
line1031">1031: PetscScalar J
line1032">1032: PetscScalar h,p_e_L2,u_e_L2,u_e_H1,p_L2,u_L2,u_H1,tp_L2,tu_L2
line1033">1033: PetscInt
line1034">1034: PetscReal xymin[2],xy
/* define quadrature rule */
line1039">1039: ConstructGaussQuadrature(&ngp,gp_xi,gp_w
/* setup for coords */
line1042">1042: DMGetCoordinateDM (stokes_da,&am
line1043">1043: DMGetCoordinatesLocal (stokes_da,&c
line1044">1044: DMDAVecGetArray (cda,coords,&_c
/* setup for analytic */
line1047">1047: DMCreateLocalVector (stokes_da,&X_analytic_
line1048">1048: DMGlobalToLocalBegin (stokes_da,X_analytic,INSERT_VALUES ,X_analytic_
line1049">1049: DMGlobalToLocalEnd (stokes_da,X_analytic,INSERT_VALUES ,X_analytic_
line1050">1050: DMDAVecGetArray (stokes_da,X_analytic_local,&stokes_ana
/* setup for solution */
line1053">1053: DMCreateLocalVector (stokes_da,&X_
line1054">1054: DMGlobalToLocalBegin (stokes_da,X,INSERT_VALUES ,X_
line1055">1055: DMGlobalToLocalEnd (stokes_da,X,INSERT_VALUES ,X_
line1056">1056: DMDAVecGetArray (stokes_da,X_local,&s
line1058">1058: DMDAGetInfo (stokes_da,0,&M,0,0,0,0,0,0,0,0,
line1059">1059: DMDAGetBoundingBox (stokes_da,xymin,
line1061">1061: h = (xymax[0]-xymin[0])/((PetscReal<
line1063">1063: tp_L2 = tu_L2 = tu_H1
line1065">1065: DMDAGetElementCorners(stokes_da,&sex,&sey,0,&mx,&
line1066">1066: for (ej = sey; ej < sey+my;
line1067">1067: for (ei = sex; ei < sex+mx;
/* get coords for the element */
line1069">1069: GetElementCoords(_coords,ei,ej,el_c
line1070">1070: StokesDAGetNodalFields(stokes,ei,ej,sto
line1071">1071: StokesDAGetNodalFields(stokes_analytic,ei,ej,stokes_analy
/* evaluate integral */
line1074">1074: p_e_L2
line1075">1075: u_e_L2
line1076">1076: u_e_H1
line1077">1077: for (p = 0; p < ngp;
line1078">1078: ConstructQ12D_Ni(gp_xi[p]
line1079">1079: ConstructQ12D_GNi(gp_xi[p],
line1080">1080: ConstructQ12D_GNx(GNi_p,GNx_p,el_coords,&am
line1081">1081: fac = gp_weight[
line1083">1083: for (i = 0; i < NODES_PER_EL;
line1084">1084: PetscScalar u_error,v
line1086">1086: p_e_L2 = p_e_L2+fac*Ni_p[i]*(stokes_e[i].p_dof-stokes_analytic_e[i].p_dof)*(stokes_e[i].p_dof-stokes_analytic_e[i].
line1088">1088: u_error = stokes_e[i].u_dof-stokes_analytic_e[i]
line1089">1089: v_error = stokes_e[i].v_dof-stokes_analytic_e[i]
line1090">1090: u_e_L2 += fac*Ni_p[i]*(u_error*u_error+v_error*v_
/* du/dx */
/* du/dy */
/* dv/dx */
/* dv/dy */
line1096">1096:
line1097">1097:
line1099">1099: tp_L2 +=
line1100">1100: tu_L2 +=
line1101">1101: tu_H1 +=
line1102">1102:
line1103">1103:
line1104">1104: MPI_Allreduce (&tp_L2,&p_L2,1,MPIU_SCALAR ,MPIU_SUM,PETSC_COMM_WORL
line1105">1105: MPI_Allreduce (&tu_L2,&u_L2,1,MPIU_SCALAR ,MPIU_SUM,PETSC_COMM_WORL
line1106">1106: MPI_Allreduce (&tu_H1,&u_H1,1,MPIU_SCALAR ,MPIU_SUM,PETSC_COMM_WORL
line1107">1107: p_L2 = PetscSqrtScalar
line1108">1108: u_L2 = PetscSqrtScalar
line1109">1109: u_H1 = PetscSqrtScalar
line1111">1111: PetscPrintf (PETSC_COMM_WORLD ,"%1.4e %1.4e %1.4e %1.4e \n" ,(double)PetscRealPart(h),(double)PetscRealPart(p_L2),(double)PetscRealPart(u_L2),(double)PetscRealPart(
line1113">1113: DMDAVecRestoreArray (cda,coords,&_c
line1115">1115: DMDAVecRestoreArray (stokes_da,X_analytic_local,&stokes_ana
line1116">1116: VecDestroy (&X_analytic_
line1117">1117: DMDAVecRestoreArray (stokes_da,X_local,&s
line1118">1118: VecDestroy (&X_
line1119">1119: return
line1120">1120
line1124">1124: static PetscErrorCode solve_stokes_2d_coupled(PetscInt mx,PetscInt my)
line1125">1125
line1126">1126: DM da_Stokes,d
line1127">1127: PetscInt u_dof,p_dof,dof,stencil
line1128">1128: Mat
line1129">1129: PetscInt m
line1130">1130: DM prop_cda,v
line1131">1131: Vec prop_coords,vel_
line1132">1132: PetscInt si,sj,nx,ny
line1133">1133: Vec
line1134">1134: PetscInt prop_dof,prop_stencil
line1135">1135: Vec properties,l_prop
line1136">1136: PetscReal
line1137">1137: PetscInt
line1138">1138: DMDACoor2d **_prop_coords,**_vel_
line1139">1139: GaussPointCoefficients **element
line1140">1140: PetscInt
line1141">1141: KSP
line1142">1142: PetscInt coefficient_structu
line1143">1143: PetscInt cpu_x,cpu_y,*lx = NULL,*ly
line1144">1144: PetscBool use_gp_coords = PETSC_FALSE ,set,output_gnuplot = PETSC_FAL
line1145">1145: char filename[PETSC_MAX_PAT
line1146">1146: PetscErrorCode
line1150">1150: PetscOptionsGetBool (NULL,"-gnuplot" ,&output_gnuplot
line1151">115
/* Generate the da for velocity and pressure */
/*
We use Q1 elements for the temperature.
FEM has a 9-point stencil (BOX) or connectivity pattern
Num nodes in each direction is mx+1, my+1
*/
/* Vx, Vy - velocities */
/* p - pressure */
line1160">1160: dof = u_dof
line1161">1161: stencil_wid
line1162">1162: DMDACreate2d (PETSC_COMM_WORLD , DM_BOUNDARY_NONE, DM_BOUNDARY_NONE,DMDA_STENCIL_B
line1163">1163: mx+1,my+1,PETSC_DECIDE ,PETSC_DECIDE ,dof,stencil_width,NULL,NULL,&da_S
line1164">1164: DMDASetFieldName (da_Stokes,0,"Vx"
line1165">1165: DMDASetFieldName (da_Stokes,1,"Vy"
line1166">1166: DMDASetFieldName (da_Stokes,2,"P"
/* unit box [0,1] x [0,1] */
line1169">1169: DMDASetUniformCoordinates (da_Stokes,0.0,1.0,0.0,1.0,
/* Generate element properties, we will assume all material properties are constant over the element */
/* local number of elements */
line1173">1173: DMDAGetLocalElementSize(da_Stokes,&mxl,&myl
/* !!! IN PARALLEL WE MUST MAKE SURE THE TWO DMDA 's ALIGN !!! */
line1176">1176: DMDAGetInfo (da_Stokes,0,0,0,0,&cpu_x,&cpu_y,0,0,0,0,
line1177">1177: DMDAGetElementOwnershipRanges2d(da_Stokes,&lx,&a
/* gauss point setup */
line1180">1180: prop_stencil_wid
line1181">1181: DMDACreate2d (PETSC_COMM_WORLD , DM_BOUNDARY_NONE, DM_BOUNDARY_NONE,DMDA_STENCIL_B
line1182">1182: mx,my,cpu_x,cpu_y,prop_dof,prop_stencil_width,lx,ly,&da
line1183">1183: PetscFree
line1184">1184: PetscFree
/* define centroid positions */
line1187">1187: DMDAGetInfo (da_prop,0,&M,&N,0,0,0,0,0,0,0,
line1188">1188: dx = 1.0/((PetscReal
line1189">1189: dy = 1.0/((PetscReal
line1191">1191: DMDASetUniformCoordinates (da_prop,0.0+0.5*dx,1.0-0.5*dx,0.0+0.5*dy,1.0-0.5*dy
/* define coefficients */
line1194">1194: PetscOptionsGetInt (NULL,"-c_str" ,&coefficient_structure
line1196">1196: DMCreateGlobalVector (da_prop,&prope
line1197">1197: DMCreateLocalVector (da_prop,&l_prope
line1198">1198: DMDAVecGetArray (da_prop,l_properties,&element_
line1200">1200: DMGetCoordinateDM (da_prop,&pro
line1201">1201: DMGetCoordinatesLocal (da_prop,&prop_c
line1202">1202: DMDAVecGetArray (prop_cda,prop_coords,&_prop_c
line1204">1204: DMDAGetGhostCorners (prop_cda,&si,&sj,0,&nx,&
line1206">1206: DMGetCoordinateDM (da_Stokes,&ve
line1207">1207: DMGetCoordinatesLocal (da_Stokes,&vel_c
line1208">1208: DMDAVecGetArray (vel_cda,vel_coords,&_vel_c
/* interpolate the coordinates */
line1211">1211: for (j = sj; j < sj+ny;
line1212">1212: for (i = si; i < si+nx;
line1213">1213: PetscInt
line1214">1214: PetscScalar gp_xi[GAUSS_POINTS][2],gp_weight[GAUSS_P
line1215">1215: PetscScalar el_coo
line1217">1217: GetElementCoords(_vel_coords,i,j,el_c
line1218">1218: ConstructGaussQuadrature(&ngp,gp_xi,gp_w
line1220">1220: for (p = 0; p < GAUSS_POINTS;
line1221">1221: PetscScalar gp_
line1222">1222: PetscInt
line1223">1223: PetscScalar xi_p[2],N
line1225">1225: xi_p[0] = gp_xi
line1226">1226: xi_p[1] = gp_xi
line1227">1227: ConstructQ12D_Ni(xi_p
line1229">1229: gp_x
line1230">1230: gp_y
line1231">1231: for (n = 0; n < NODES_PER_EL;
line1232">1232: gp_x = gp_x+Ni_p[n]*el_coord
line1233">1233: gp_y = gp_y+Ni_p[n]*el_coords[
line1234">1234:
line1235">1235: element_props[j][i].gp_coords[2*p]
line1236">1236: element_props[j][i].gp_coords[2*p+1]
line1237">1237:
line1238">1238:
line1239">1239:
/* define the coefficients */
line1242">1242: PetscOptionsGetBool (NULL,"-use_gp_coords" ,&use_gp_coords
line1244">1244: for (j = sj; j < sj+ny;
line1245">1245: for (i = si; i < si+nx;
/* centroids of cell */
line1247">1247: PetscReal centroid_y = PetscRealPart(_prop_coords[j]
line1248">1248: PetscReal coord_x,c
line1250">1250: if (coefficient_structure
line1251">1251: PetscReal opts_eta0,opts_eta1,o
line1252">1252: PetscInt o
line1254">1254: opts_eta0
line1255">1255: opts_eta1
line1256">1256: opts_xc
line1257">1257: opts_nz
line1259">1259: PetscOptionsGetReal (NULL,"-solcx_eta0" ,&opts_eta0
line1260">1260: PetscOptionsGetReal (NULL,"-solcx_eta1" ,&opts_eta1
line1261">1261: PetscOptionsGetReal (NULL,"-solcx_xc" ,&opts_xc
line1262">1262: PetscOptionsGetInt (NULL,"-solcx_nz" ,&opts_nz
line1264">1264: for (p = 0; p < GAUSS_POINTS;
line1265">1265: coord_x = cent
line1266">1266: coord_y = cent
line1267">1267: if (use_gp_co
line1268">1268: coord_x = PetscRealPart(element_props[j][i].gp_coords
line1269">1269: coord_y = PetscRealPart(element_props[j][i].gp_coords[2
line1270">1270:
line1272">1272: element_props[j][i].eta[p] = opt
line1273">1273: if (coord_x > opts_xc) element_props[j][i].eta[p] = opt
line1275">1275: element_props[j][i].fx[p]
line1276">1276: element_props[j][i].fy[p] = PetscSinReal(opts_nz*PETSC_PI*coord_y)*PetscCosReal(1.0*PETSC_PI*co
line1277">1277:
/* square sinker */
line1279">1279: PetscReal opts_eta0,opts_eta1,opts_dx,o
line1281">1281: opts_eta0
line1282">1282: opts_eta1
line1283">1283: opts_dx
line1284">1284: opts_dy
line1286">1286: PetscOptionsGetReal (NULL,"-sinker_eta0" ,&opts_eta0
line1287">1287: PetscOptionsGetReal (NULL,"-sinker_eta1" ,&opts_eta1
line1288">1288: PetscOptionsGetReal (NULL,"-sinker_dx" ,&opts_dx
line1289">1289: PetscOptionsGetReal (NULL,"-sinker_dy" ,&opts_dy
line1291">1291: for (p = 0; p < GAUSS_POINTS;
line1292">1292: coord_x = cent
line1293">1293: coord_y = cent
line1294">1294: if (use_gp_co
line1295">1295: coord_x = PetscRealPart(element_props[j][i].gp_coords
line1296">1296: coord_y = PetscRealPart(element_props[j][i].gp_coords[2
line1297">1297:
line1299">1299: element_props[j][i].eta[p] = opt
line1300">1300: element_props[j][i].fx[p]
line1301">1301: element_props[j][i].fy[p]
line1303">1303: if ((coord_x > -0.5*opts_dx+0.5) && (coord_x < 0.5*opts_dx+
line1304">1304: if ((coord_y > -0.5*opts_dy+0.5) && (coord_y < 0.5*opts_dy+
line1305">1305: element_props[j][i].eta[p] = opt
line1306">1306: element_props[j][i].fx[p]
line1307">1307: element_props[j][i].fy[p]
line1308">1308:
line1309">1309:
line1310">1310:
/* circular sinker */
line1312">1312: PetscReal opts_eta0,opts_eta1,opts_r,r
line1314">1314: opts_eta0
line1315">1315: opts_eta1
line1316">1316: opts_r
line1318">1318: PetscOptionsGetReal (NULL,"-sinker_eta0" ,&opts_eta0
line1319">1319: PetscOptionsGetReal (NULL,"-sinker_eta1" ,&opts_eta1
line1320">1320: PetscOptionsGetReal (NULL,"-sinker_r" ,&opts_r
line1322">1322: for (p = 0; p < GAUSS_POINTS;
line1323">1323: coord_x = cent
line1324">1324: coord_y = cent
line1325">1325: if (use_gp_co
line1326">1326: coord_x = PetscRealPart(element_props[j][i].gp_coords
line1327">1327: coord_y = PetscRealPart(element_props[j][i].gp_coords[2
line1328">1328:
line1330">1330: element_props[j][i].eta[p] = opt
line1331">1331: element_props[j][i].fx[p]
line1332">1332: element_props[j][i].fy[p]
line1334">1334: radius2 = (coord_x-0.5)*(coord_x-0.5)+(coord_y-0.5)*(coord_
line1335">1335: if (radius2 < opts_r*op
line1336">1336: element_props[j][i].eta[p] = opt
line1337">1337: element_props[j][i].fx[p]
line1338">1338: element_props[j][i].fy[p]
line1339">1339:
line1340">1340:
/* circular and rectangular inclusion */
line1342">1342: PetscReal opts_eta0,opts_eta1,opts_r,opts_dx,opts_dy,opts_c0x,opts_c0y,opts_s0x,opts_s0y,opts_phi,r
line1344">1344: opts_eta0
line1345">1345: opts_eta1
line1346">1346: opts_r
/* circle center */
line1348">1348: opts_c0y
/* square center */
line1350">1350: opts_s0y
line1351">1351: opts_dx
line1352">1352: opts_dy
line1353">1353: opts_phi
line1355">1355: PetscOptionsGetReal (NULL,"-sinker_eta0" ,&opts_eta0
line1356">1356: PetscOptionsGetReal (NULL,"-sinker_eta1" ,&opts_eta1
line1357">1357: PetscOptionsGetReal (NULL,"-sinker_r" ,&opts_r
line1358">1358: PetscOptionsGetReal (NULL,"-sinker_c0x" ,&opts_c0x
line1359">1359: PetscOptionsGetReal (NULL,"-sinker_c0y" ,&opts_c0y
line1360">1360: PetscOptionsGetReal (NULL,"-sinker_s0x" ,&opts_s0x
line1361">1361: PetscOptionsGetReal (NULL,"-sinker_s0y" ,&opts_s0y
line1362">1362: PetscOptionsGetReal (NULL,"-sinker_dx" ,&opts_dx
line1363">1363: PetscOptionsGetReal (NULL,"-sinker_dy" ,&opts_dy
line1364">1364: PetscOptionsGetReal (NULL,"-sinker_phi" ,&opts_phi
line1365">1365: opts_phi *= PETSC_PI
line1367">1367: for (p = 0; p < GAUSS_POINTS;
line1368">1368: coord_x = cent
line1369">1369: coord_y = cent
line1370">1370: if (use_gp_co
line1371">1371: coord_x = PetscRealPart(element_props[j][i].gp_coords
line1372">1372: coord_y = PetscRealPart(element_props[j][i].gp_coords[2
line1373">1373:
line1375">1375: element_props[j][i].eta[p] = opt
line1376">1376: element_props[j][i].fx[p]
line1377">1377: element_props[j][i].fy[p]
line1379">1379: radius2 = PetscSqr(coord_x - opts_c0x) + PetscSqr(coord_y - opt
line1380">1380: if (radius2 < opts_r
line1381">1381: || (PetscAbs(+(coord_x - opts_s0x)*PetscCosReal(opts_phi) + (coord_y - opts_s0y)*PetscSinReal(opts_phi)) < op
line1382">1382: && PetscAbs(-(coord_x - opts_s0x)*PetscSinReal(opts_phi) + (coord_y - opts_s0y)*PetscCosReal(opts_phi)) < opts_d
line1383">1383: element_props[j][i].eta[p] = opt
line1384">1384: element_props[j][i].fx[p]
line1385">1385: element_props[j][i].fy[p]
line1386">1386:
line1387">1387:
line1388">1388: } else SETERRQ (PETSC_COMM_SELF ,PETSC_ERR_USER,"Unknown coefficient_structure"
line1389">1389:
line1390">1390:
line1391">1391: DMDAVecRestoreArray (prop_cda,prop_coords,&_prop_c
line1393">1393: DMDAVecRestoreArray (vel_cda,vel_coords,&_vel_c
line1395">1395: DMDAVecRestoreArray (da_prop,l_properties,&element_
line1396">1396: DMLocalToGlobalBegin (da_prop,l_properties,ADD_VALUES ,prope
line1397">1397: DMLocalToGlobalEnd (da_prop,l_properties,ADD_VALUES ,prope
line1399">1399: if (output_gnu
line1400">1400: DMDACoordViewGnuplot2d(da_Stokes,"mesh"
line1401">1401: DMDAViewCoefficientsGnuplot2d(da_prop,properties,"Coeffcients for Stokes eqn." ,"properties"
line1402">1402:
/* Generate a matrix with the correct non-zero pattern of type AIJ. This will work in parallel and serial */
line1405">1405: DMSetMatType (da_Stokes,MATAI
line1406">1406: DMCreateMatrix (da_Stokes,&
line1407">1407: DMCreateMatrix (da_Stokes,&
line1408">1408: DMCreateGlobalVector (da_Stokes,&
line1409">1409: DMCreateGlobalVector (da_Stokes,&
/* assemble A11 */
line1412">1412: MatZeroEntries<
line1413">1413: MatZeroEntries<
line1414">1414: VecZeroEntries<
line1416">1416: AssembleA_Stokes(A,da_Stokes,da_prop,prope
line1417">1417: AssembleA_PCStokes(B,da_Stokes,da_prop,prope
/* build force vector */
line1419">1419: AssembleF_Stokes(f,da_Stokes,da_prop,prope
line1421">1421: DMDABCApplyFreeSlip(da_Stoke
line1422">1422: DMDABCApplyFreeSlip(da_Stokes,B
/* SOLVE */
line1425">1425: KSPCreate (PETSC_COMM_WORLD ,&
line1426">1426: KSPSetOptionsPrefix (ksp_S,"stokes_"
line1427">1427: KSPSetDM (ksp_S,da_S
line1428">1428: KSPSetDMActive (ksp_S,PETSC_FALS
line1429">1429: KSPSetOperators (ksp_
line1430">1430: KSPSetFromOptions (
line1431">1431:
line1432">1432: PC
line1433">1433: const PetscInt ufields[] = {0,1},pfields[1]
line1434">1434: KSPGetPC (ksp_S,&a
line1435">1435: PCFieldSplitSetBlockSize
line1436">1436: PCFieldSplitSetFields (pc,"u" ,2,ufields,uf
line1437">1437: PCFieldSplitSetFields (pc,"p" ,1,pfields,pf
line1438">1438:
line1440">1440:
line1441">1441: PC
line1442">1442: KSP *sub_ksp
line1443">1443: PetscInt n
line1444">1444: DM
line1445">1445: PetscBool i
line1447">1447: KSPSetUp (
line1448">1448: KSPGetPC (ksp_S,&
line1450">1450: is_pcfs = PETSC_FAL
line1451">1451: PetscObjectTypeCompare ((PetscObject )pc_S,PCFIELDSPLIT ,&is
line1453">1453: if (is_
line1454">1454: PCFieldSplitGetSubKSP (pc_S,&nsplits,&su
line1455">1455: ksp_U = sub_
line1456">1456: PetscFree (su
line1458">1458: if (nsplits
line1459">1459: DMDAGetReducedDMDA (da_Stokes,2,&
line1461">1461: KSPSetDM (ksp_U
line1462">1462: KSPSetDMActive (ksp_U,PETSC_FALS
line1463">1463: DMDestroy (&
line1464">1464:
line1465">1465:
line1466">1466:
line1468">1468: KSPSolve (ksp_
line1470">1470: PetscOptionsGetString (NULL,"-o" ,filename,sizeof (filename),&am
line1471">1471: if
line1472">1472: char
line1473">1473: PetscViewer
line1474">1474: PetscBool
line1475">1475: PetscViewerCreate (PETSC_COMM_WORLD ,&v
line1476">1476: PetscStrrchr (filename,'.',&am
line1477">1477: PetscStrcmp ("vts" ,ext,&am
line1478">1478: if
line1479">1479: PetscViewerSetType (viewer,PETSCVIEW
line1480">1480: } else
line1481">1481: PetscViewerSetType (viewer,PETSCVIEWERB
line1482">1482:
line1483">1483: PetscViewerFileSetMode (viewer,FILE_MODE_
line1484">1484: PetscViewerFileSetName (viewer,fil
line1485">1485: VecView (X,v
line1486">1486: PetscViewerDestroy (&v
line1487">1487:
line1488">1488: if (output_gnu
line1489">1489: DMDAViewGnuplot2d(da_Stokes,X,"Velocity solution for Stokes eqn." ,"X"
line1490">1490:
line1492">1492: KSPGetIterationNumber (ksp_S,&am
line1494">1494: if (coefficient_structure
line1495">1495: PetscReal opts_eta0,opts_eta1,o
line1496">1496: PetscInt opt
line1497">1497: DM da_Stokes_an
line1498">1498: Vec X_an
line1499">1499: PetscReal nrm1[3],nrm2[3],n
line1501">1501: opts_eta0
line1502">1502: opts_eta1
line1503">1503: opts_xc
line1504">1504: opts_nz
line1506">1506: PetscOptionsGetReal (NULL,"-solcx_eta0" ,&opts_eta0
line1507">1507: PetscOptionsGetReal (NULL,"-solcx_eta1" ,&opts_eta1
line1508">1508: PetscOptionsGetReal (NULL,"-solcx_xc" ,&opts_xc
line1509">1509: PetscOptionsGetInt (NULL,"-solcx_nz" ,&opts_nz
line1511">1511: DMDACreateSolCx(opts_eta0,opts_eta1,opts_xc,opts_nz,mx,my,&da_Stokes_analytic,&X_ana
line1512">1512: if (output_gnu
line1513">1513: DMDAViewGnuplot2d(da_Stokes_analytic,X_analytic,"Analytic solution for Stokes eqn." ,"X_analytic"
line1514">1514:
line1515">1515: DMDAIntegrateErrors(da_Stokes_analytic,X,X_ana
line1517">1517: VecAXPY (X_analytic,-
line1518">1518: VecGetSize (X_analytic,&
line1519">1519: N
line1521">1521: VecStrideNorm (X_analytic,0,NORM_1 ,&nr
line1522">1522: VecStrideNorm (X_analytic,0,NORM_2 ,&nr
line1523">1523: VecStrideNorm (X_analytic,0,NORM_INFINITY ,&nr
line1525">1525: VecStrideNorm (X_analytic,1,NORM_1 ,&nr
line1526">1526: VecStrideNorm (X_analytic,1,NORM_2 ,&nr
line1527">1527: VecStrideNorm (X_analytic,1,NORM_INFINITY ,&nr
line1529">1529: VecStrideNorm (X_analytic,2,NORM_1 ,&nr
line1530">1530: VecStrideNorm (X_analytic,2,NORM_2 ,&nr
line1531">1531: VecStrideNorm (X_analytic,2,NORM_INFINITY ,&nr
line1533">1533: DMDestroy (&da_Stokes_ana
line1534">1534: VecDestroy (&X_ana
line1535">1535:
line1537">1537: KSPDestroy (&
line1538">1538: VecDestroy (&
line1539">1539: VecDestroy (&
line1540">1540: MatDestroy (&
line1541">1541: MatDestroy (&
line1543">1543: DMDestroy (&da_S
line1544">1544: DMDestroy (&da
line1546">1546: VecDestroy (&prope
line1547">1547: VecDestroy (&l_prope
line1548">1548: return
line1549">1549
line1553">1553: int main(int argc,char **args)
line1554">1554
line1556">1556: PetscInt
line1558">1558: PetscInitialize (&argc,&args,(char*)0
line1560">1560: mx = m
line1561">1561: PetscOptionsGetInt (NULL,"-mx" ,&mx
line1562">1562: PetscOptionsGetInt (NULL,"-my" ,&my
line1564">1564: solve_stokes_2d_coupled(
line1566">1566: PetscFinalize
line1567">1567: return
line1568">1568
/* -------------------------- helpers for boundary conditions -------------------------------- */
line1573">1573: static PetscErrorCode BCApplyZero_EAST(DM da,PetscInt d_idx,Mat A,Vec b)
line1574">1574
line1575">1575: DM
line1576">1576: Vec
line1577">1577: PetscInt si,sj,nx,
line1578">1578: PetscInt
line1579">1579: DMDACoor2d **_
line1580">1580: const PetscInt
line1581">1581: PetscInt *bc_glob
line1582">1582: PetscScalar *b
line1583">1583: PetscInt
line1584">1584: PetscInt
line1585">1585: PetscErrorCode
line1586">1586: ISLocalToGlobalMapping
line1589">1589: DMGetLocalToGlobalMapping (da,&
line1590">1590: ISLocalToGlobalMappingGetIndices (ltogm,&
line1592">1592: DMGetCoordinateDM (da,&am
line1593">1593: DMGetCoordinatesLocal (da,&c
line1594">1594: DMDAVecGetArray (cda,coords,&_c
line1595">1595: DMDAGetGhostCorners (cda,&si,&sj,0,&nx,&
line1596">1596: DMDAGetInfo (da,0,&M,&N,0,0,0,0,&n_dofs,0,0,
line1598">1598: PetscMalloc1 (ny*n_dofs,&bc_globa
line1599">1599: PetscMalloc1 (ny*n_dofs,&bc
/* init the entries to -1 so VecSetValues will ignore them */
line1602">1602: for (i = 0; i < ny*n_dofs; i++) bc_global_ids[i
line1604">1604: i
line1605">1605: for (j = 0; j < ny;
line1606">1606: PetscInt lo
line1608">1608: local_id =
line1610">1610: bc_global_ids[j] = g_idx[n_dofs*local_id+
line1612">1612: bc_vals[j]
line1613">1613:
line1614">1614: ISLocalToGlobalMappingRestoreIndices (ltogm,&
line1615">1615: nb
line1616">1616: if ((si+nx) == (M)) nbc
line1618">1618: if (b !=
line1619">1619: VecSetValues (b,nbcs,bc_global_ids,bc_vals,INSERT_VALUE
line1620">1620: VecAssemblyBegin<
line1621">1621: VecAssemblyEnd<
line1622">1622:
line1623">1623: if (A !=
line1624">1624: MatZeroRowsColumns (A,nbcs,bc_global_ids,1.
line1625">1625:
line1627">1627: PetscFree (bc
line1628">1628: PetscFree (bc_globa
line1630">1630: DMDAVecRestoreArray (cda,coords,&_c
line1631">1631: return
line1632">1632
line1636">1636: static PetscErrorCode BCApplyZero_WEST(DM da,PetscInt d_idx,Mat A,Vec b)
line1637">1637
line1638">1638: DM
line1639">1639: Vec
line1640">1640: PetscInt si,sj,nx,
line1641">1641: PetscInt
line1642">1642: DMDACoor2d **_
line1643">1643: const PetscInt
line1644">1644: PetscInt *bc_glob
line1645">1645: PetscScalar *b
line1646">1646: PetscInt
line1647">1647: PetscInt
line1648">1648: PetscErrorCode
line1649">1649: ISLocalToGlobalMapping
line1652">1652: DMGetLocalToGlobalMapping (da,&
line1653">1653: ISLocalToGlobalMappingGetIndices (ltogm,&
line1655">1655: DMGetCoordinateDM (da,&am
line1656">1656: DMGetCoordinatesLocal (da,&c
line1657">1657: DMDAVecGetArray (cda,coords,&_c
line1658">1658: DMDAGetGhostCorners (cda,&si,&sj,0,&nx,&
line1659">1659: DMDAGetInfo (da,0,&M,&N,0,0,0,0,&n_dofs,0,0,
line1661">1661: PetscMalloc1 (ny*n_dofs,&bc_globa
line1662">1662: PetscMalloc1 (ny*n_dofs,&bc
/* init the entries to -1 so VecSetValues will ignore them */
line1665">1665: for (i = 0; i < ny*n_dofs; i++) bc_global_ids[i
line1667">1667:
line1668">1668: for (j = 0; j < ny;
line1669">1669: PetscInt lo
line1671">1671: local_id =
line1673">1673: bc_global_ids[j] = g_idx[n_dofs*local_id+
line1675">1675: bc_vals[j]
line1676">1676:
line1677">1677: ISLocalToGlobalMappingRestoreIndices (ltogm,&
line1678">1678: nb
line1679">1679: if (si == 0) nbc
line1681">1681: if (b !=
line1682">1682: VecSetValues (b,nbcs,bc_global_ids,bc_vals,INSERT_VALUE
line1683">1683: VecAssemblyBegin<
line1684">1684: VecAssemblyEnd<
line1685">1685:
line1687">1687: if (A !=
line1688">1688: MatZeroRowsColumns (A,nbcs,bc_global_ids,1.
line1689">1689:
line1691">1691: PetscFree (bc
line1692">1692: PetscFree (bc_globa
line1694">1694: DMDAVecRestoreArray (cda,coords,&_c
line1695">1695: return
line1696">1696
line1700">1700: static PetscErrorCode BCApplyZero_NORTH(DM da,PetscInt d_idx,Mat A,Vec b)
line1701">1701
line1702">1702: DM
line1703">1703: Vec
line1704">1704: PetscInt si,sj,nx,
line1705">1705: PetscInt
line1706">1706: DMDACoor2d **_
line1707">1707: const PetscInt
line1708">1708: PetscInt *bc_glob
line1709">1709: PetscScalar *b
line1710">1710: PetscInt
line1711">1711: PetscInt
line1712">1712: PetscErrorCode
line1713">1713: ISLocalToGlobalMapping
line1716">1716: DMGetLocalToGlobalMapping (da,&
line1717">1717: ISLocalToGlobalMappingGetIndices (ltogm,&
line1719">1719: DMGetCoordinateDM (da,&am
line1720">1720: DMGetCoordinatesLocal (da,&c
line1721">1721: DMDAVecGetArray (cda,coords,&_c
line1722">1722: DMDAGetGhostCorners (cda,&si,&sj,0,&nx,&
line1723">1723: DMDAGetInfo (da,0,&M,&N,0,0,0,0,&n_dofs,0,0,
line1725">1725: PetscMalloc1 (nx,&bc_globa
line1726">1726: PetscMalloc1 (nx,&bc
/* init the entries to -1 so VecSetValues will ignore them */
line1729">1729: for (i = 0; i < nx; i++) bc_global_ids[i
line1731">1731: j
line1732">1732: for (i = 0; i < nx;
line1733">1733: PetscInt lo
line1735">1735: local_id =
line1737">1737: bc_global_ids[i] = g_idx[n_dofs*local_id+
line1739">1739: bc_vals[i]
line1740">1740:
line1741">1741: ISLocalToGlobalMappingRestoreIndices (ltogm,&
line1742">1742: nb
line1743">1743: if ((sj+ny) == (N)) nbc
line1745">1745: if (b !=
line1746">1746: VecSetValues (b,nbcs,bc_global_ids,bc_vals,INSERT_VALUE
line1747">1747: VecAssemblyBegin<
line1748">1748: VecAssemblyEnd<
line1749">1749:
line1750">1750: if (A !=
line1751">1751: MatZeroRowsColumns (A,nbcs,bc_global_ids,1.
line1752">1752:
line1754">1754: PetscFree (bc
line1755">1755: PetscFree (bc_globa
line1757">1757: DMDAVecRestoreArray (cda,coords,&_c
line1758">1758: return
line1759">1759
line1763">1763: static PetscErrorCode BCApplyZero_SOUTH(DM da,PetscInt d_idx,Mat A,Vec b)
line1764">1764
line1765">1765: DM
line1766">1766: Vec
line1767">1767: PetscInt si,sj,nx,
line1768">1768: PetscInt
line1769">1769: DMDACoor2d **_
line1770">1770: const PetscInt
line1771">1771: PetscInt *bc_glob
line1772">1772: PetscScalar *b
line1773">1773: PetscInt
line1774">1774: PetscInt
line1775">1775: PetscErrorCode
line1776">1776: ISLocalToGlobalMapping
line1779">1779: DMGetLocalToGlobalMapping (da,&
line1780">1780: ISLocalToGlobalMappingGetIndices (ltogm,&
line1782">1782: DMGetCoordinateDM (da,&am
line1783">1783: DMGetCoordinatesLocal (da,&c
line1784">1784: DMDAVecGetArray (cda,coords,&_c
line1785">1785: DMDAGetGhostCorners (cda,&si,&sj,0,&nx,&
line1786">1786: DMDAGetInfo (da,0,&M,&N,0,0,0,0,&n_dofs,0,0,
line1788">1788: PetscMalloc1 (nx,&bc_globa
line1789">1789: PetscMalloc1 (nx,&bc
/* init the entries to -1 so VecSetValues will ignore them */
line1792">1792: for (i = 0; i < nx; i++) bc_global_ids[i
line1794">1794:
line1795">1795: for (i = 0; i < nx;
line1796">1796: PetscInt lo
line1798">1798: local_id =
line1800">1800: bc_global_ids[i] = g_idx[n_dofs*local_id+
line1802">1802: bc_vals[i]
line1803">1803:
line1804">1804: ISLocalToGlobalMappingRestoreIndices (ltogm,&
line1805">1805: nb
line1806">1806: if (sj == 0) nbc
line1808">1808: if (b !=
line1809">1809: VecSetValues (b,nbcs,bc_global_ids,bc_vals,INSERT_VALUE
line1810">1810: VecAssemblyBegin<
line1811">1811: VecAssemblyEnd<
line1812">1812:
line1813">1813: if (A !=
line1814">1814: MatZeroRowsColumns (A,nbcs,bc_global_ids,1.
line1815">1815:
line1817">1817: PetscFree (bc
line1818">1818: PetscFree (bc_globa
line1820">1820: DMDAVecRestoreArray (cda,coords,&_c
line1821">1821: return
line1822">1822
/* Impose free slip boundary conditions; u_{i} n_{i} = 0, tau_{ij} t_j = 0 */
line1827">1827: static PetscErrorCode DMDABCApplyFreeSlip(DM da_Stokes,Mat A,Vec f)
line1828">1828
line1832">1832: BCApplyZero_NORTH(da_Stokes,
line1833">1833: BCApplyZero_EAST(da_Stokes,
line1834">1834: BCApplyZero_SOUTH(da_Stokes,
line1835">1835: BCApplyZero_WEST(da_Stokes,
line1836">1836: return
line1837">1837