1 // /home/couturie/work/petsc-3.5.1/arch-linux2-c-debug/bin/mpirun -np 4 ./ex49 -mx 900 -my 900 -ksp_type fgmres
4 static char help[] = " Solves the compressible plane strain elasticity equations in 2d on the unit domain using Q1 finite elements. \n\
5 Material properties E (Youngs moduls) and nu (Poisson ratio) may vary as a function of space. \n\
6 The model utilisse boundary conditions which produce compression in the x direction. \n\
8 -mx : number elements in x-direciton \n\
9 -my : number elements in y-direciton \n\
10 -c_str : indicates the structure of the coefficients to use. \n\
11 -c_str 0 => Setup for an isotropic material with constant coefficients. \n\
13 -iso_E : Youngs modulus \n\
14 -iso_nu : Poisson ratio \n\
15 -c_str 1 => Setup for a step function in the material properties in x. \n\
17 -step_E0 : Youngs modulus to the left of the step \n\
18 -step_nu0 : Poisson ratio to the left of the step \n\
19 -step_E1 : Youngs modulus to the right of the step \n\
20 -step_n1 : Poisson ratio to the right of the step \n\
21 -step_xc : x coordinate of the step \n\
22 -c_str 2 => Setup for a checkerboard material with alternating properties. \n\
23 Repeats the following pattern throughout the domain. For example with 4 materials specified, we would heve \n\
24 -------------------------\n\
26 ------|-----|-----|------\n\
28 ------|-----|-----|------\n\
30 ------|-----|-----|------\n\
32 -------------------------\n\
35 -brick_E : a comma seperated list of Young's modulii \n\
36 -brick_nu : a comma seperated list of Poisson ratio's \n\
37 -brick_span : the number of elements in x and y each brick will span \n\
38 -c_str 3 => Setup for a sponge-like material with alternating properties. \n\
39 Repeats the following pattern throughout the domain \n\
40 -----------------------------\n\
43 | ----------------- |\n\
44 | | [inclusion] | |\n\
47 | | <---- w ----> | |\n\
50 | ----------------- |\n\
53 -----------------------------\n\
54 <-------- t + w + t ------->\n\
57 -sponge_E0 : Youngs moduls of the surrounding material \n\
58 -sponge_E1 : Youngs moduls of the inclusio \n\
59 -sponge_nu0 : Poisson ratio of the surrounding material \n\
60 -sponge_nu1 : Poisson ratio of the inclusio \n\
61 -sponge_t : the number of elements defining the border around each inclusion \n\
62 -sponge_w : the number of elements in x and y each inclusion will span\n\
63 -use_gp_coords : Evaluate the Youngs modulus, Poisson ratio and the body force at the global coordinates of the quadrature points.\n\
64 By default, E, nu and the body force are evaulated at the element center and applied as a constant over the entire element.\n\
65 -use_nonsymbc : Option to use non-symmetric boundary condition imposition. This choice will use less memory.";
67 /* Contributed by Dave May */
71 #include <petscdmda.h>
73 static PetscErrorCode DMDABCApplyCompression(DM,Mat,Vec);
74 static PetscErrorCode DMDABCApplySymmetricCompression(DM elas_da,Mat A,Vec f,IS *dofs,Mat *AA,Vec *ff);
77 #define NSD 2 /* number of spatial dimensions */
78 #define NODES_PER_EL 4 /* nodes per element */
79 #define U_DOFS 2 /* degrees of freedom per displacement node */
80 #define GAUSS_POINTS 4
85 int KrylovMinimize(Mat A, Vec b, Vec x) {
90 PetscScalar gamma, alpha, oldgamma, beta;
91 PetscReal norm=20, Eprecision=1e-8, cgprec=1e-40;
92 PetscInt giter=0, ColS=8, col=0, Emaxiter=50000000, iter=0, iterations=15, Iiter=0;
104 Vec Alpha, p, ss, vect, r, q, Ax;
109 ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr);
110 ierr = KSPSetOperators(ksp,A,A);CHKERRQ(ierr);
111 ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr);
118 ierr = PetscPrintf(PETSC_COMM_WORLD, "Size of vector %D\n", size); CHKERRQ(ierr);
121 MatGetOwnershipRange(A,&aa,&bb);
123 // ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD, "%D %D\n", aa,bb); CHKERRQ(ierr);
124 //PetscSynchronizedFlush(PETSC_COMM_WORLD);
127 ierr = MatCreate(PETSC_COMM_WORLD, &S);CHKERRQ(ierr);
128 ierr = MatSetSizes(S, bb-aa, PETSC_DECIDE, size, ColS); CHKERRQ(ierr);
129 ierr = MatSetType(S, MATMPIDENSE); CHKERRQ(ierr);
130 ierr = MatSetUp(S); CHKERRQ(ierr);
132 ierr = MatGetOwnershipRange(S, &Istart, &Iend); CHKERRQ(ierr);
134 ierr = VecCreate(PETSC_COMM_WORLD, &Alpha); CHKERRQ(ierr);
135 ierr = VecSetSizes(Alpha, PETSC_DECIDE, ColS); CHKERRQ(ierr);
136 ierr = VecSetFromOptions(Alpha); CHKERRQ(ierr);
137 ierr = VecDuplicate(Alpha, &vect); CHKERRQ(ierr);
138 ierr = VecDuplicate(Alpha, &p); CHKERRQ(ierr);
139 ierr = VecDuplicate(Alpha, &ss); CHKERRQ(ierr);
140 ierr = VecDuplicate(b, &r); CHKERRQ(ierr);
141 ierr = VecDuplicate(b, &q); CHKERRQ(ierr);
142 ierr = VecDuplicate(b, &Ax); CHKERRQ(ierr);
144 ierr = VecDuplicate(b,&x_old);CHKERRQ(ierr);
145 ierr = VecDuplicate(b,&residu);CHKERRQ(ierr);
149 //indexes of row (these indexes are global)
150 ind_row = (PetscInt*)malloc(sizeof(PetscInt)*(Iend-Istart));
151 for(i=0; i<Iend-Istart; i++) ind_row[i] = i + Istart;
154 // ierr = KSPGMRESSetRestart(ksp, 16); CHKERRQ(ierr);
155 ierr = KSPSetTolerances(ksp, 1e-13, 1e-13, PETSC_DEFAULT, 16); CHKERRQ(ierr);
156 ierr = KSPSetInitialGuessNonzero(ksp, PETSC_TRUE); CHKERRQ(ierr);
160 //GMRES WITH MINIMIZATION
162 while(giter<Emaxiter && norm>Eprecision ){
163 for(col=0; col<ColS && norm>Eprecision; col++){
167 ierr = KSPSolve(ksp, b, x); CHKERRQ(ierr);
169 ierr = KSPGetIterationNumber(ksp, &its); CHKERRQ(ierr);
170 total += its; Iiter ++;
175 ierr = VecGetArray(x, &array);
176 ierr = MatSetValues(S, Iend-Istart, ind_row, 1, &col, array, INSERT_VALUES);
177 VecRestoreArray(x, &array);
181 KSPGetResidualNorm(ksp,&norm);
184 ierr = VecCopy(x, residu); CHKERRQ(ierr);
185 ierr = VecAXPY(residu, -1, x_old); CHKERRQ(ierr);
186 ierr = VecNorm(residu, NORM_INFINITY, &norm); CHKERRQ(ierr);
190 ierr = PetscPrintf(PETSC_COMM_WORLD, "Norm of error %g, outer iteration %D\n", norm, giter); CHKERRQ(ierr);
191 ierr = VecCopy(x, x_old); CHKERRQ(ierr);
198 if( norm>Eprecision) {
200 MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY);
201 MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY);
206 MatMatMult(A,S, MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AS);
210 MatMatMult(A,S, MAT_REUSE_MATRIX,PETSC_DEFAULT,&AS);
215 //Minimization with CGLS
216 MatMult(AS, Alpha, r); VecAYPX(r, -1, b); //r_0 = b-AS*x_0
219 MatMultTranspose(AS, r, p); //p_0 = AS'*r_0
224 ierr = VecCopy(p, ss); CHKERRQ(ierr); //p_0 = s_0
225 VecNorm(ss, NORM_2, &gamma); gamma = gamma * gamma; //gamma = norm2(s)^2
226 while(gamma>cgprec && iter<iterations){
227 MatMult(AS, p, q); //q = AS*p
228 VecNorm(q, NORM_2, &alpha); alpha = alpha * alpha; //alpha = norm2(q)^2
229 alpha = gamma / alpha;
230 VecAXPY(Alpha, alpha, p); //Alpha += alpha*p
231 VecAXPY(r, -alpha, q); //r -= alpha*q
232 MatMultTranspose(AS, r, ss); // ss = AS'*r
234 VecNorm(ss, NORM_2, &gamma); gamma = gamma * gamma; //gamma = norm2(s)^2
235 beta = gamma / oldgamma;
236 VecAYPX(p, beta, ss); //p = s+beta*p;
242 MatMult(S, Alpha, x); //x = S*Alpha;
247 ierr = PetscPrintf(PETSC_COMM_WORLD, "\t\t\t -- Execution time : %g (s)\n", T2-T1); CHKERRQ(ierr);
248 ierr = PetscPrintf(PETSC_COMM_WORLD, "\t\t\t -- Total number of iterations : %D\n", total); CHKERRQ(ierr);
262 int KrylovMinimizeLSQR(Mat A, Vec b, Vec x) {
267 PetscScalar alpha, beta;
268 PetscReal norm=20, Eprecision=1e-8, tol=1e-40;
269 PetscInt giter=0, ColS=8, col=0, Emaxiter=50000000, iter=0, iterations=15, Iiter=0;
275 PetscInt Istart,Iend;
282 PetscScalar norm_ksp;
283 Vec u,v,d,uu,vt,zero_long,zero_short,x_lsqr;
287 ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr);
288 ierr = KSPSetOperators(ksp,A,A);CHKERRQ(ierr);
289 ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr);
296 ierr = PetscPrintf(PETSC_COMM_WORLD, "Size of vector %D\n", size); CHKERRQ(ierr);
299 MatGetOwnershipRange(A,&aa,&bb);
301 // ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD, "%D %D\n", aa,bb); CHKERRQ(ierr);
302 //PetscSynchronizedFlush(PETSC_COMM_WORLD);
305 ierr = MatCreate(PETSC_COMM_WORLD, &S);CHKERRQ(ierr);
306 ierr = MatSetSizes(S, bb-aa, PETSC_DECIDE, size, ColS); CHKERRQ(ierr);
307 ierr = MatSetType(S, MATMPIDENSE); CHKERRQ(ierr);
308 ierr = MatSetUp(S); CHKERRQ(ierr);
310 ierr = MatGetOwnershipRange(S, &Istart, &Iend); CHKERRQ(ierr);
314 ierr = VecDuplicate(b, &Ax); CHKERRQ(ierr);
316 ierr = VecDuplicate(b,&x_old);CHKERRQ(ierr);
317 ierr = VecDuplicate(b,&residu);CHKERRQ(ierr);
321 ierr = VecDuplicate(b,&u);CHKERRQ(ierr);
324 ierr = VecDuplicate(b,&uu);CHKERRQ(ierr);
325 ierr = VecDuplicate(b,&zero_long);CHKERRQ(ierr);
326 ierr = VecSet(zero_long,0);CHKERRQ(ierr);
329 ierr = VecCreate(PETSC_COMM_WORLD, &v); CHKERRQ(ierr);
330 ierr = VecSetSizes(v, PETSC_DECIDE, ColS); CHKERRQ(ierr);
331 ierr = VecSetFromOptions(v); CHKERRQ(ierr);
332 ierr = VecDuplicate(v,&zero_short);CHKERRQ(ierr);
333 ierr = VecSet(zero_short,0);CHKERRQ(ierr);
334 ierr = VecDuplicate(v,&d);CHKERRQ(ierr);
335 ierr = VecDuplicate(v,&vt);CHKERRQ(ierr);
336 ierr = VecDuplicate(v,&x_lsqr);CHKERRQ(ierr);
339 //indexes of row (these indexes are global)
340 ind_row = (PetscInt*)malloc(sizeof(PetscInt)*(Iend-Istart));
341 for(i=0; i<Iend-Istart; i++) ind_row[i] = i + Istart;
344 // ierr = KSPGMRESSetRestart(ksp, 16); CHKERRQ(ierr);
345 ierr = KSPSetTolerances(ksp, 1e-13, 1e-13, PETSC_DEFAULT, 16); CHKERRQ(ierr);
346 ierr = KSPSetInitialGuessNonzero(ksp, PETSC_TRUE); CHKERRQ(ierr);
351 //GMRES WITH MINIMIZATION
353 while(giter<Emaxiter && norm>Eprecision ){
354 for(col=0; col<ColS && norm>Eprecision; col++){
358 ierr = KSPSolve(ksp, b, x); CHKERRQ(ierr);
360 ierr = KSPGetIterationNumber(ksp, &its); CHKERRQ(ierr);
361 total += its; Iiter ++;
366 ierr = VecGetArray(x, &array);
367 ierr = MatSetValues(S, Iend-Istart, ind_row, 1, &col, array, INSERT_VALUES);
368 VecRestoreArray(x, &array);
372 KSPGetResidualNorm(ksp,&norm);
375 ierr = VecCopy(x, residu); CHKERRQ(ierr);
376 ierr = VecAXPY(residu, -1, x_old); CHKERRQ(ierr);
377 ierr = VecNorm(residu, NORM_INFINITY, &norm); CHKERRQ(ierr);
381 ierr = PetscPrintf(PETSC_COMM_WORLD, "Norm of error %g, outer iteration %D\n", norm, giter); CHKERRQ(ierr);
382 ierr = VecCopy(x, x_old); CHKERRQ(ierr);
389 if( norm>Eprecision) {
391 MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY);
392 MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY);
399 MatMatMult(A,S, MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AS);
404 MatMatMult(A,S, MAT_REUSE_MATRIX,PETSC_DEFAULT,&AS);
416 PetscScalar n2b,tolb,normr,c,s,phibar,normar,norma,thet,rhot,rho,phi;
419 VecNorm(b, NORM_2, &n2b); //n2b = norm(b);
420 ierr = VecCopy(b, u); CHKERRQ(ierr); //u=b
421 VecNorm(u, NORM_2, &beta); // beta=norm(u)
424 VecAYPX(u,1/beta,zero_long); // u = u / beta;
429 MatMultTranspose(AS, u, v); //v=A'*u
430 ierr = VecSet(x_lsqr,0);CHKERRQ(ierr);
431 VecNorm(v, NORM_2, &alpha); // alpha=norm(v)
433 VecAYPX(v,1/alpha,zero_short); // v = v / alpha;
435 ierr = VecSet(d,0);CHKERRQ(ierr);
436 normar = alpha * beta;
439 for(i=0;i<iterations;i++) {
440 MatMult(AS, v, uu); //uu=A*v
441 VecAYPX(u, -alpha, uu); //u = uu-alpha*u;
442 VecNorm(u, NORM_2, &beta); // beta=norm(u)
443 VecAYPX(u,1/beta,zero_long); // u = u / beta;
444 norma=sqrt(norma*norma+alpha*alpha+beta*beta); // norma = norm([norma alpha beta]);
447 rho = sqrt(rhot*rhot + beta*beta);
451 if (phi == 0) { // stagnation of the method
455 VecAYPX(d,-thet,v); //d = (v - thet * d);
456 VecAYPX(d,1/rho,zero_short); //d=d/ rho;
460 VecAXPY(x_lsqr,phi,d); // x_lsqr=x_lsqr+phi*d
461 normr = abs(s) * normr;
462 MatMultTranspose(AS, u, vt); //vt=A'*u;
463 VecAYPX(v,-beta,vt); // v = vt - beta * v;
464 VecNorm(v, NORM_2, &alpha); // alpha=norm(v)
465 VecAYPX(v,1/alpha,zero_short); // v = v / alpha;
466 normar = alpha * abs( s * phi);
473 MatMult(S, x_lsqr, x); //x = S*x_small;
478 ierr = PetscPrintf(PETSC_COMM_WORLD, "\t\t\t -- Execution time LSQR : %g (s)\n", T2-T1); CHKERRQ(ierr);
479 ierr = PetscPrintf(PETSC_COMM_WORLD, "\t\t\t -- Total number of iterations LSQR : %D\n", total); CHKERRQ(ierr);
490 /* cell based evaluation */
492 PetscScalar E,nu,fx,fy;
495 /* Gauss point based evaluation 8+4+4+4 = 20 */
497 PetscScalar gp_coords[2*GAUSS_POINTS];
498 PetscScalar E[GAUSS_POINTS];
499 PetscScalar nu[GAUSS_POINTS];
500 PetscScalar fx[GAUSS_POINTS];
501 PetscScalar fy[GAUSS_POINTS];
502 } GaussPointCoefficients;
512 D = E/((1+nu)(1-2nu)) * [ 1-nu nu 0 ]
524 Element: Local basis function ordering
530 static void ConstructQ12D_Ni(PetscScalar _xi[],PetscScalar Ni[])
532 PetscScalar xi = _xi[0];
533 PetscScalar eta = _xi[1];
535 Ni[0] = 0.25*(1.0-xi)*(1.0-eta);
536 Ni[1] = 0.25*(1.0-xi)*(1.0+eta);
537 Ni[2] = 0.25*(1.0+xi)*(1.0+eta);
538 Ni[3] = 0.25*(1.0+xi)*(1.0-eta);
541 static void ConstructQ12D_GNi(PetscScalar _xi[],PetscScalar GNi[][NODES_PER_EL])
543 PetscScalar xi = _xi[0];
544 PetscScalar eta = _xi[1];
546 GNi[0][0] = -0.25*(1.0-eta);
547 GNi[0][1] = -0.25*(1.0+eta);
548 GNi[0][2] = 0.25*(1.0+eta);
549 GNi[0][3] = 0.25*(1.0-eta);
551 GNi[1][0] = -0.25*(1.0-xi);
552 GNi[1][1] = 0.25*(1.0-xi);
553 GNi[1][2] = 0.25*(1.0+xi);
554 GNi[1][3] = -0.25*(1.0+xi);
557 static void ConstructQ12D_GNx(PetscScalar GNi[][NODES_PER_EL],PetscScalar GNx[][NODES_PER_EL],PetscScalar coords[],PetscScalar *det_J)
559 PetscScalar J00,J01,J10,J11,J;
560 PetscScalar iJ00,iJ01,iJ10,iJ11;
563 J00 = J01 = J10 = J11 = 0.0;
564 for (i = 0; i < NODES_PER_EL; i++) {
565 PetscScalar cx = coords[2*i+0];
566 PetscScalar cy = coords[2*i+1];
568 J00 = J00+GNi[0][i]*cx; /* J_xx = dx/dxi */
569 J01 = J01+GNi[0][i]*cy; /* J_xy = dy/dxi */
570 J10 = J10+GNi[1][i]*cx; /* J_yx = dx/deta */
571 J11 = J11+GNi[1][i]*cy; /* J_yy = dy/deta */
573 J = (J00*J11)-(J01*J10);
581 for (i = 0; i < NODES_PER_EL; i++) {
582 GNx[0][i] = GNi[0][i]*iJ00+GNi[1][i]*iJ01;
583 GNx[1][i] = GNi[0][i]*iJ10+GNi[1][i]*iJ11;
586 if (det_J != NULL) *det_J = J;
589 static void ConstructGaussQuadrature(PetscInt *ngp,PetscScalar gp_xi[][2],PetscScalar gp_weight[])
592 gp_xi[0][0] = -0.57735026919;gp_xi[0][1] = -0.57735026919;
593 gp_xi[1][0] = -0.57735026919;gp_xi[1][1] = 0.57735026919;
594 gp_xi[2][0] = 0.57735026919;gp_xi[2][1] = 0.57735026919;
595 gp_xi[3][0] = 0.57735026919;gp_xi[3][1] = -0.57735026919;
603 /* procs to the left claim the ghost node as their element */
605 #define __FUNCT__ "DMDAGetLocalElementSize"
606 static PetscErrorCode DMDAGetLocalElementSize(DM da,PetscInt *mxl,PetscInt *myl,PetscInt *mzl)
609 PetscInt m,n,p,M,N,P;
612 PetscFunctionBeginUser;
613 ierr = DMDAGetInfo(da,0,&M,&N,&P,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr);
614 ierr = DMDAGetCorners(da,&sx,&sy,&sz,&m,&n,&p);CHKERRQ(ierr);
618 if ((sx+m) == M) *mxl = m-1; /* last proc */
622 if ((sy+n) == N) *myl = n-1; /* last proc */
626 if ((sz+p) == P) *mzl = p-1; /* last proc */
628 PetscFunctionReturn(0);
632 #define __FUNCT__ "DMDAGetElementCorners"
633 static PetscErrorCode DMDAGetElementCorners(DM da,PetscInt *sx,PetscInt *sy,PetscInt *sz,PetscInt *mx,PetscInt *my,PetscInt *mz)
638 PetscFunctionBeginUser;
639 ierr = DMDAGetGhostCorners(da,&si,&sj,&sk,0,0,0);CHKERRQ(ierr);
643 if (si != 0) *sx = si+1;
647 if (sj != 0) *sy = sj+1;
652 if (sk != 0) *sz = sk+1;
655 ierr = DMDAGetLocalElementSize(da,mx,my,mz);CHKERRQ(ierr);
656 PetscFunctionReturn(0);
660 #define __FUNCT__ "DMDAGetElementOwnershipRanges2d"
661 static PetscErrorCode DMDAGetElementOwnershipRanges2d(DM da,PetscInt **_lx,PetscInt **_ly)
665 PetscInt proc_I,proc_J;
666 PetscInt cpu_x,cpu_y;
667 PetscInt local_mx,local_my;
674 PetscFunctionBeginUser;
675 MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
677 DMDAGetInfo(da,0,0,0,0,&cpu_x,&cpu_y,0,0,0,0,0,0,0);
680 proc_I = rank-cpu_x*proc_J;
682 ierr = PetscMalloc(sizeof(PetscInt)*cpu_x,&LX);CHKERRQ(ierr);
683 ierr = PetscMalloc(sizeof(PetscInt)*cpu_y,&LY);CHKERRQ(ierr);
685 ierr = DMDAGetLocalElementSize(da,&local_mx,&local_my,NULL);CHKERRQ(ierr);
686 ierr = VecCreate(PETSC_COMM_WORLD,&vlx);CHKERRQ(ierr);
687 ierr = VecSetSizes(vlx,PETSC_DECIDE,cpu_x);CHKERRQ(ierr);
688 ierr = VecSetFromOptions(vlx);CHKERRQ(ierr);
690 ierr = VecCreate(PETSC_COMM_WORLD,&vly);CHKERRQ(ierr);
691 ierr = VecSetSizes(vly,PETSC_DECIDE,cpu_y);CHKERRQ(ierr);
692 ierr = VecSetFromOptions(vly);CHKERRQ(ierr);
694 ierr = VecSetValue(vlx,proc_I,(PetscScalar)(local_mx+1.0e-9),INSERT_VALUES);CHKERRQ(ierr);
695 ierr = VecSetValue(vly,proc_J,(PetscScalar)(local_my+1.0e-9),INSERT_VALUES);CHKERRQ(ierr);
696 ierr = VecAssemblyBegin(vlx);VecAssemblyEnd(vlx);CHKERRQ(ierr);
697 ierr = VecAssemblyBegin(vly);VecAssemblyEnd(vly);CHKERRQ(ierr);
701 ierr = VecScatterCreateToAll(vlx,&ctx,&V_SEQ);CHKERRQ(ierr);
702 ierr = VecScatterBegin(ctx,vlx,V_SEQ,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
703 ierr = VecScatterEnd(ctx,vlx,V_SEQ,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
704 ierr = VecGetArray(V_SEQ,&_a);CHKERRQ(ierr);
705 for (i = 0; i < cpu_x; i++) LX[i] = (PetscInt)PetscRealPart(_a[i]);
706 ierr = VecRestoreArray(V_SEQ,&_a);CHKERRQ(ierr);
707 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr);
708 ierr = VecDestroy(&V_SEQ);CHKERRQ(ierr);
710 ierr = VecScatterCreateToAll(vly,&ctx,&V_SEQ);CHKERRQ(ierr);
711 ierr = VecScatterBegin(ctx,vly,V_SEQ,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
712 ierr = VecScatterEnd(ctx,vly,V_SEQ,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
713 ierr = VecGetArray(V_SEQ,&_a);CHKERRQ(ierr);
714 for (i = 0; i < cpu_y; i++) LY[i] = (PetscInt)PetscRealPart(_a[i]);
715 ierr = VecRestoreArray(V_SEQ,&_a);CHKERRQ(ierr);
716 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr);
717 ierr = VecDestroy(&V_SEQ);CHKERRQ(ierr);
722 ierr = VecDestroy(&vlx);CHKERRQ(ierr);
723 ierr = VecDestroy(&vly);CHKERRQ(ierr);
724 PetscFunctionReturn(0);
728 #define __FUNCT__ "DMDACoordViewGnuplot2d"
729 static PetscErrorCode DMDACoordViewGnuplot2d(DM da,const char prefix[])
733 DMDACoor2d **_coords;
734 PetscInt si,sj,nx,ny,i,j;
736 char fname[PETSC_MAX_PATH_LEN];
740 PetscFunctionBeginUser;
741 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
742 ierr = PetscSNPrintf(fname,sizeof(fname),"%s-p%1.4d.dat",prefix,rank);CHKERRQ(ierr);
743 ierr = PetscFOpen(PETSC_COMM_SELF,fname,"w",&fp);CHKERRQ(ierr);
744 if (!fp) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot open file");
745 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"### Element geometry for processor %1.4d ### \n",rank);CHKERRQ(ierr);
747 ierr = DMGetCoordinateDM(da,&cda);CHKERRQ(ierr);
748 ierr = DMGetCoordinatesLocal(da,&coords);CHKERRQ(ierr);
749 ierr = DMDAVecGetArray(cda,coords,&_coords);CHKERRQ(ierr);
750 ierr = DMDAGetGhostCorners(cda,&si,&sj,0,&nx,&ny,0);CHKERRQ(ierr);
751 for (j = sj; j < sj+ny-1; j++) {
752 for (i = si; i < si+nx-1; i++) {
753 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"%1.6e %1.6e \n",PetscRealPart(_coords[j][i].x),PetscRealPart(_coords[j][i].y));CHKERRQ(ierr);
754 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"%1.6e %1.6e \n",PetscRealPart(_coords[j+1][i].x),PetscRealPart(_coords[j+1][i].y));CHKERRQ(ierr);
755 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"%1.6e %1.6e \n",PetscRealPart(_coords[j+1][i+1].x),PetscRealPart(_coords[j+1][i+1].y));CHKERRQ(ierr);
756 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"%1.6e %1.6e \n",PetscRealPart(_coords[j][i+1].x),PetscRealPart(_coords[j][i+1].y));CHKERRQ(ierr);
757 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"%1.6e %1.6e \n\n",PetscRealPart(_coords[j][i].x),PetscRealPart(_coords[j][i].y));CHKERRQ(ierr);
760 ierr = DMDAVecRestoreArray(cda,coords,&_coords);CHKERRQ(ierr);
762 ierr = PetscFClose(PETSC_COMM_SELF,fp);CHKERRQ(ierr);
763 PetscFunctionReturn(0);
767 #define __FUNCT__ "DMDAViewGnuplot2d"
768 static PetscErrorCode DMDAViewGnuplot2d(DM da,Vec fields,const char comment[],const char prefix[])
771 Vec coords,local_fields;
772 DMDACoor2d **_coords;
774 char fname[PETSC_MAX_PATH_LEN];
775 const char *field_name;
777 PetscInt si,sj,nx,ny,i,j;
779 PetscScalar *_fields;
782 PetscFunctionBeginUser;
783 MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
784 ierr = PetscSNPrintf(fname,sizeof(fname),"%s-p%1.4d.dat",prefix,rank);CHKERRQ(ierr);
785 ierr = PetscFOpen(PETSC_COMM_SELF,fname,"w",&fp);CHKERRQ(ierr);
786 if (!fp) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot open file");
788 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"### %s (processor %1.4d) ### \n",comment,rank);CHKERRQ(ierr);
789 ierr = DMDAGetInfo(da,0,0,0,0,0,0,0,&n_dofs,0,0,0,0,0);CHKERRQ(ierr);
790 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"### x y ");CHKERRQ(ierr);
791 for (d = 0; d < n_dofs; d++) {
792 ierr = DMDAGetFieldName(da,d,&field_name);CHKERRQ(ierr);
793 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"%s ",field_name);CHKERRQ(ierr);
795 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"###\n");CHKERRQ(ierr);
798 ierr = DMGetCoordinateDM(da,&cda);CHKERRQ(ierr);
799 ierr = DMGetCoordinatesLocal(da,&coords);CHKERRQ(ierr);
800 ierr = DMDAVecGetArray(cda,coords,&_coords);CHKERRQ(ierr);
801 ierr = DMDAGetGhostCorners(cda,&si,&sj,0,&nx,&ny,0);CHKERRQ(ierr);
803 ierr = DMCreateLocalVector(da,&local_fields);CHKERRQ(ierr);
804 ierr = DMGlobalToLocalBegin(da,fields,INSERT_VALUES,local_fields);CHKERRQ(ierr);
805 ierr = DMGlobalToLocalEnd(da,fields,INSERT_VALUES,local_fields);CHKERRQ(ierr);
806 ierr = VecGetArray(local_fields,&_fields);CHKERRQ(ierr);
808 for (j = sj; j < sj+ny; j++) {
809 for (i = si; i < si+nx; i++) {
810 PetscScalar coord_x,coord_y;
813 coord_x = _coords[j][i].x;
814 coord_y = _coords[j][i].y;
816 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"%1.6e %1.6e ",PetscRealPart(coord_x),PetscRealPart(coord_y));CHKERRQ(ierr);
817 for (d = 0; d < n_dofs; d++) {
818 field_d = _fields[n_dofs*((i-si)+(j-sj)*(nx))+d];
819 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"%1.6e ",PetscRealPart(field_d));CHKERRQ(ierr);
821 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"\n");CHKERRQ(ierr);
824 ierr = VecRestoreArray(local_fields,&_fields);CHKERRQ(ierr);
825 ierr = VecDestroy(&local_fields);CHKERRQ(ierr);
827 ierr = DMDAVecRestoreArray(cda,coords,&_coords);CHKERRQ(ierr);
829 ierr = PetscFClose(PETSC_COMM_SELF,fp);CHKERRQ(ierr);
830 PetscFunctionReturn(0);
834 #define __FUNCT__ "DMDAViewCoefficientsGnuplot2d"
835 static PetscErrorCode DMDAViewCoefficientsGnuplot2d(DM da,Vec fields,const char comment[],const char prefix[])
840 char fname[PETSC_MAX_PATH_LEN];
841 const char *field_name;
843 PetscInt si,sj,nx,ny,i,j,p;
845 GaussPointCoefficients **_coefficients;
848 PetscFunctionBeginUser;
849 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
850 ierr = PetscSNPrintf(fname,sizeof(fname),"%s-p%1.4d.dat",prefix,rank);CHKERRQ(ierr);
851 ierr = PetscFOpen(PETSC_COMM_SELF,fname,"w",&fp);CHKERRQ(ierr);
852 if (!fp) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot open file");
854 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"### %s (processor %1.4d) ### \n",comment,rank);CHKERRQ(ierr);
855 ierr = DMDAGetInfo(da,0,0,0,0,0,0,0,&n_dofs,0,0,0,0,0);CHKERRQ(ierr);
856 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"### x y ");CHKERRQ(ierr);
857 for (d = 0; d < n_dofs; d++) {
858 ierr = DMDAGetFieldName(da,d,&field_name);CHKERRQ(ierr);
859 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"%s ",field_name);CHKERRQ(ierr);
861 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"###\n");CHKERRQ(ierr);
864 ierr = DMGetCoordinateDM(da,&cda);CHKERRQ(ierr);
865 ierr = DMDAGetGhostCorners(cda,&si,&sj,0,&nx,&ny,0);CHKERRQ(ierr);
867 ierr = DMCreateLocalVector(da,&local_fields);CHKERRQ(ierr);
868 ierr = DMGlobalToLocalBegin(da,fields,INSERT_VALUES,local_fields);CHKERRQ(ierr);
869 ierr = DMGlobalToLocalEnd(da,fields,INSERT_VALUES,local_fields);CHKERRQ(ierr);
870 ierr = DMDAVecGetArray(da,local_fields,&_coefficients);CHKERRQ(ierr);
872 for (j = sj; j < sj+ny; j++) {
873 for (i = si; i < si+nx; i++) {
874 PetscScalar coord_x,coord_y;
876 for (p = 0; p < GAUSS_POINTS; p++) {
877 coord_x = _coefficients[j][i].gp_coords[2*p];
878 coord_y = _coefficients[j][i].gp_coords[2*p+1];
880 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"%1.6e %1.6e ",PetscRealPart(coord_x),PetscRealPart(coord_y));CHKERRQ(ierr);
882 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"%1.6e %1.6e %1.6e %1.6e",
883 PetscRealPart(_coefficients[j][i].E[p]),PetscRealPart(_coefficients[j][i].nu[p]),
884 PetscRealPart(_coefficients[j][i].fx[p]),PetscRealPart(_coefficients[j][i].fy[p]));CHKERRQ(ierr);
885 ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"\n");CHKERRQ(ierr);
889 ierr = DMDAVecRestoreArray(da,local_fields,&_coefficients);CHKERRQ(ierr);
890 ierr = VecDestroy(&local_fields);CHKERRQ(ierr);
892 ierr = PetscFClose(PETSC_COMM_SELF,fp);CHKERRQ(ierr);
893 PetscFunctionReturn(0);
896 static void FormStressOperatorQ1(PetscScalar Ke[],PetscScalar coords[],PetscScalar E[],PetscScalar nu[])
899 PetscScalar gp_xi[GAUSS_POINTS][2];
900 PetscScalar gp_weight[GAUSS_POINTS];
902 PetscScalar GNi_p[NSD][NODES_PER_EL],GNx_p[NSD][NODES_PER_EL];
904 PetscScalar B[3][U_DOFS*NODES_PER_EL];
905 PetscScalar prop_E,prop_nu,factor,constit_D[3][3];
907 /* define quadrature rule */
908 ConstructGaussQuadrature(&ngp,gp_xi,gp_weight);
910 /* evaluate integral */
911 for (p = 0; p < ngp; p++) {
912 ConstructQ12D_GNi(gp_xi[p],GNi_p);
913 ConstructQ12D_GNx(GNi_p,GNx_p,coords,&J_p);
915 for (i = 0; i < NODES_PER_EL; i++) {
916 PetscScalar d_dx_i = GNx_p[0][i];
917 PetscScalar d_dy_i = GNx_p[1][i];
919 B[0][2*i] = d_dx_i; B[0][2*i+1] = 0.0;
920 B[1][2*i] = 0.0; B[1][2*i+1] = d_dy_i;
921 B[2][2*i] = d_dy_i; B[2][2*i+1] = d_dx_i;
924 /* form D for the quadrature point */
927 factor = prop_E / ((1.0+prop_nu)*(1.0-2.0*prop_nu));
928 constit_D[0][0] = 1.0-prop_nu; constit_D[0][1] = prop_nu; constit_D[0][2] = 0.0;
929 constit_D[1][0] = prop_nu; constit_D[1][1] = 1.0-prop_nu; constit_D[1][2] = 0.0;
930 constit_D[2][0] = 0.0; constit_D[2][1] = 0.0; constit_D[2][2] = 0.5*(1.0-2.0*prop_nu);
931 for (i = 0; i < 3; i++) {
932 for (j = 0; j < 3; j++) {
933 constit_D[i][j] = factor * constit_D[i][j] * gp_weight[p] * J_p;
937 /* form Bt tildeD B */
939 Ke_ij = Bt_ik . D_kl . B_lj
942 for (i = 0; i < 8; i++) {
943 for (j = 0; j < 8; j++) {
944 for (k = 0; k < 3; k++) {
945 for (l = 0; l < 3; l++) {
946 Ke[8*i+j] = Ke[8*i+j] + B[k][i] * constit_D[k][l] * B[l][j];
952 } /* end quadrature */
955 static void FormMomentumRhsQ1(PetscScalar Fe[],PetscScalar coords[],PetscScalar fx[],PetscScalar fy[])
958 PetscScalar gp_xi[GAUSS_POINTS][2];
959 PetscScalar gp_weight[GAUSS_POINTS];
961 PetscScalar Ni_p[NODES_PER_EL];
962 PetscScalar GNi_p[NSD][NODES_PER_EL],GNx_p[NSD][NODES_PER_EL];
965 /* define quadrature rule */
966 ConstructGaussQuadrature(&ngp,gp_xi,gp_weight);
968 /* evaluate integral */
969 for (p = 0; p < ngp; p++) {
970 ConstructQ12D_Ni(gp_xi[p],Ni_p);
971 ConstructQ12D_GNi(gp_xi[p],GNi_p);
972 ConstructQ12D_GNx(GNi_p,GNx_p,coords,&J_p);
973 fac = gp_weight[p]*J_p;
975 for (i = 0; i < NODES_PER_EL; i++) {
976 Fe[NSD*i] += fac*Ni_p[i]*fx[p];
977 Fe[NSD*i+1] += fac*Ni_p[i]*fy[p];
983 i,j are the element indices
984 The unknown is a vector quantity.
985 The s[].c is used to indicate the degree of freedom.
988 #define __FUNCT__ "DMDAGetElementEqnums_u"
989 static PetscErrorCode DMDAGetElementEqnums_u(MatStencil s_u[],PetscInt i,PetscInt j)
991 PetscFunctionBeginUser;
994 s_u[0].i = i;s_u[0].j = j;s_u[0].c = 0; /* Ux0 */
995 s_u[1].i = i;s_u[1].j = j;s_u[1].c = 1; /* Uy0 */
998 s_u[2].i = i;s_u[2].j = j+1;s_u[2].c = 0; /* Ux1 */
999 s_u[3].i = i;s_u[3].j = j+1;s_u[3].c = 1; /* Uy1 */
1002 s_u[4].i = i+1;s_u[4].j = j+1;s_u[4].c = 0; /* Ux2 */
1003 s_u[5].i = i+1;s_u[5].j = j+1;s_u[5].c = 1; /* Uy2 */
1006 s_u[6].i = i+1;s_u[6].j = j;s_u[6].c = 0; /* Ux3 */
1007 s_u[7].i = i+1;s_u[7].j = j;s_u[7].c = 1; /* Uy3 */
1008 PetscFunctionReturn(0);
1012 #define __FUNCT__ "GetElementCoords"
1013 static PetscErrorCode GetElementCoords(DMDACoor2d **_coords,PetscInt ei,PetscInt ej,PetscScalar el_coords[])
1015 PetscFunctionBeginUser;
1016 /* get coords for the element */
1017 el_coords[NSD*0+0] = _coords[ej][ei].x; el_coords[NSD*0+1] = _coords[ej][ei].y;
1018 el_coords[NSD*1+0] = _coords[ej+1][ei].x; el_coords[NSD*1+1] = _coords[ej+1][ei].y;
1019 el_coords[NSD*2+0] = _coords[ej+1][ei+1].x; el_coords[NSD*2+1] = _coords[ej+1][ei+1].y;
1020 el_coords[NSD*3+0] = _coords[ej][ei+1].x; el_coords[NSD*3+1] = _coords[ej][ei+1].y;
1021 PetscFunctionReturn(0);
1025 #define __FUNCT__ "AssembleA_Elasticity"
1026 static PetscErrorCode AssembleA_Elasticity(Mat A,DM elas_da,DM properties_da,Vec properties)
1030 DMDACoor2d **_coords;
1031 MatStencil u_eqn[NODES_PER_EL*U_DOFS]; /* 2 degrees of freedom */
1032 PetscInt sex,sey,mx,my;
1034 PetscScalar Ae[NODES_PER_EL*U_DOFS*NODES_PER_EL*U_DOFS];
1035 PetscScalar el_coords[NODES_PER_EL*NSD];
1036 Vec local_properties;
1037 GaussPointCoefficients **props;
1038 PetscScalar *prop_E,*prop_nu;
1039 PetscErrorCode ierr;
1041 PetscFunctionBeginUser;
1042 /* setup for coords */
1043 ierr = DMGetCoordinateDM(elas_da,&cda);CHKERRQ(ierr);
1044 ierr = DMGetCoordinatesLocal(elas_da,&coords);CHKERRQ(ierr);
1045 ierr = DMDAVecGetArray(cda,coords,&_coords);CHKERRQ(ierr);
1047 /* setup for coefficients */
1048 ierr = DMCreateLocalVector(properties_da,&local_properties);CHKERRQ(ierr);
1049 ierr = DMGlobalToLocalBegin(properties_da,properties,INSERT_VALUES,local_properties);CHKERRQ(ierr);
1050 ierr = DMGlobalToLocalEnd(properties_da,properties,INSERT_VALUES,local_properties);CHKERRQ(ierr);
1051 ierr = DMDAVecGetArray(properties_da,local_properties,&props);CHKERRQ(ierr);
1053 ierr = DMDAGetElementCorners(elas_da,&sex,&sey,0,&mx,&my,0);CHKERRQ(ierr);
1054 for (ej = sey; ej < sey+my; ej++) {
1055 for (ei = sex; ei < sex+mx; ei++) {
1056 /* get coords for the element */
1057 GetElementCoords(_coords,ei,ej,el_coords);
1059 /* get coefficients for the element */
1060 prop_E = props[ej][ei].E;
1061 prop_nu = props[ej][ei].nu;
1063 /* initialise element stiffness matrix */
1064 ierr = PetscMemzero(Ae,sizeof(PetscScalar)*NODES_PER_EL*U_DOFS*NODES_PER_EL*U_DOFS);CHKERRQ(ierr);
1066 /* form element stiffness matrix */
1067 FormStressOperatorQ1(Ae,el_coords,prop_E,prop_nu);
1069 /* insert element matrix into global matrix */
1070 ierr = DMDAGetElementEqnums_u(u_eqn,ei,ej);CHKERRQ(ierr);
1071 ierr = MatSetValuesStencil(A,NODES_PER_EL*U_DOFS,u_eqn,NODES_PER_EL*U_DOFS,u_eqn,Ae,ADD_VALUES);CHKERRQ(ierr);
1074 ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1075 ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1077 ierr = DMDAVecRestoreArray(cda,coords,&_coords);CHKERRQ(ierr);
1079 ierr = DMDAVecRestoreArray(properties_da,local_properties,&props);CHKERRQ(ierr);
1080 ierr = VecDestroy(&local_properties);CHKERRQ(ierr);
1081 PetscFunctionReturn(0);
1086 #define __FUNCT__ "DMDASetValuesLocalStencil_ADD_VALUES"
1087 static PetscErrorCode DMDASetValuesLocalStencil_ADD_VALUES(ElasticityDOF **fields_F,MatStencil u_eqn[],PetscScalar Fe_u[])
1091 PetscFunctionBeginUser;
1092 for (n = 0; n < 4; n++) {
1093 fields_F[u_eqn[2*n].j][u_eqn[2*n].i].ux_dof = fields_F[u_eqn[2*n].j][u_eqn[2*n].i].ux_dof+Fe_u[2*n];
1094 fields_F[u_eqn[2*n+1].j][u_eqn[2*n+1].i].uy_dof = fields_F[u_eqn[2*n+1].j][u_eqn[2*n+1].i].uy_dof+Fe_u[2*n+1];
1096 PetscFunctionReturn(0);
1100 #define __FUNCT__ "AssembleF_Elasticity"
1101 static PetscErrorCode AssembleF_Elasticity(Vec F,DM elas_da,DM properties_da,Vec properties)
1105 DMDACoor2d **_coords;
1106 MatStencil u_eqn[NODES_PER_EL*U_DOFS]; /* 2 degrees of freedom */
1107 PetscInt sex,sey,mx,my;
1109 PetscScalar Fe[NODES_PER_EL*U_DOFS];
1110 PetscScalar el_coords[NODES_PER_EL*NSD];
1111 Vec local_properties;
1112 GaussPointCoefficients **props;
1113 PetscScalar *prop_fx,*prop_fy;
1116 PetscErrorCode ierr;
1118 PetscFunctionBeginUser;
1119 /* setup for coords */
1120 ierr = DMGetCoordinateDM(elas_da,&cda);CHKERRQ(ierr);
1121 ierr = DMGetCoordinatesLocal(elas_da,&coords);CHKERRQ(ierr);
1122 ierr = DMDAVecGetArray(cda,coords,&_coords);CHKERRQ(ierr);
1124 /* setup for coefficients */
1125 ierr = DMGetLocalVector(properties_da,&local_properties);CHKERRQ(ierr);
1126 ierr = DMGlobalToLocalBegin(properties_da,properties,INSERT_VALUES,local_properties);CHKERRQ(ierr);
1127 ierr = DMGlobalToLocalEnd(properties_da,properties,INSERT_VALUES,local_properties);CHKERRQ(ierr);
1128 ierr = DMDAVecGetArray(properties_da,local_properties,&props);CHKERRQ(ierr);
1130 /* get acces to the vector */
1131 ierr = DMGetLocalVector(elas_da,&local_F);CHKERRQ(ierr);
1132 ierr = VecZeroEntries(local_F);CHKERRQ(ierr);
1133 ierr = DMDAVecGetArray(elas_da,local_F,&ff);CHKERRQ(ierr);
1136 ierr = DMDAGetElementCorners(elas_da,&sex,&sey,0,&mx,&my,0);CHKERRQ(ierr);
1137 for (ej = sey; ej < sey+my; ej++) {
1138 for (ei = sex; ei < sex+mx; ei++) {
1139 /* get coords for the element */
1140 GetElementCoords(_coords,ei,ej,el_coords);
1142 /* get coefficients for the element */
1143 prop_fx = props[ej][ei].fx;
1144 prop_fy = props[ej][ei].fy;
1146 /* initialise element stiffness matrix */
1147 ierr = PetscMemzero(Fe,sizeof(PetscScalar)*NODES_PER_EL*U_DOFS);CHKERRQ(ierr);
1149 /* form element stiffness matrix */
1150 FormMomentumRhsQ1(Fe,el_coords,prop_fx,prop_fy);
1152 /* insert element matrix into global matrix */
1153 ierr = DMDAGetElementEqnums_u(u_eqn,ei,ej);CHKERRQ(ierr);
1155 ierr = DMDASetValuesLocalStencil_ADD_VALUES(ff,u_eqn,Fe);CHKERRQ(ierr);
1159 ierr = DMDAVecRestoreArray(elas_da,local_F,&ff);CHKERRQ(ierr);
1160 ierr = DMLocalToGlobalBegin(elas_da,local_F,ADD_VALUES,F);CHKERRQ(ierr);
1161 ierr = DMLocalToGlobalEnd(elas_da,local_F,ADD_VALUES,F);CHKERRQ(ierr);
1162 ierr = DMRestoreLocalVector(elas_da,&local_F);CHKERRQ(ierr);
1164 ierr = DMDAVecRestoreArray(cda,coords,&_coords);CHKERRQ(ierr);
1166 ierr = DMDAVecRestoreArray(properties_da,local_properties,&props);CHKERRQ(ierr);
1167 ierr = DMRestoreLocalVector(properties_da,&local_properties);CHKERRQ(ierr);
1168 PetscFunctionReturn(0);
1172 #define __FUNCT__ "solve_elasticity_2d"
1173 static PetscErrorCode solve_elasticity_2d(PetscInt mx,PetscInt my)
1176 PetscInt u_dof,dof,stencil_width;
1179 DM prop_cda,vel_cda;
1180 Vec prop_coords,vel_coords;
1181 PetscInt si,sj,nx,ny,i,j,p;
1183 PetscInt prop_dof,prop_stencil_width;
1184 Vec properties,l_properties;
1185 MatNullSpace matnull;
1188 DMDACoor2d **_prop_coords,**_vel_coords;
1189 GaussPointCoefficients **element_props;
1191 PetscInt coefficient_structure = 0;
1192 PetscInt cpu_x,cpu_y,*lx = NULL,*ly = NULL;
1193 PetscBool use_gp_coords = PETSC_FALSE;
1194 PetscBool use_nonsymbc = PETSC_FALSE;
1195 PetscBool no_view = PETSC_FALSE;
1197 PetscErrorCode ierr;
1199 PetscFunctionBeginUser;
1200 /* Generate the da for velocity and pressure */
1202 We use Q1 elements for the temperature.
1203 FEM has a 9-point stencil (BOX) or connectivity pattern
1204 Num nodes in each direction is mx+1, my+1
1206 u_dof = U_DOFS; /* Vx, Vy - velocities */
1209 ierr = DMDACreate2d(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE,DMDA_STENCIL_BOX,
1210 mx+1,my+1,PETSC_DECIDE,PETSC_DECIDE,dof,stencil_width,NULL,NULL,&elas_da);CHKERRQ(ierr);
1211 ierr = DMDASetFieldName(elas_da,0,"Ux");CHKERRQ(ierr);
1212 ierr = DMDASetFieldName(elas_da,1,"Uy");CHKERRQ(ierr);
1214 /* unit box [0,1] x [0,1] */
1215 ierr = DMDASetUniformCoordinates(elas_da,0.0,1.0,0.0,1.0,0.0,1.0);CHKERRQ(ierr);
1218 /* Generate element properties, we will assume all material properties are constant over the element */
1219 /* local number of elements */
1220 ierr = DMDAGetLocalElementSize(elas_da,&mxl,&myl,NULL);CHKERRQ(ierr);
1222 /* !!! IN PARALLEL WE MUST MAKE SURE THE TWO DMDA's ALIGN !!! */
1223 ierr = DMDAGetInfo(elas_da,0,0,0,0,&cpu_x,&cpu_y,0,0,0,0,0,0,0);CHKERRQ(ierr);
1224 ierr = DMDAGetElementOwnershipRanges2d(elas_da,&lx,&ly);CHKERRQ(ierr);
1226 prop_dof = (PetscInt)(sizeof(GaussPointCoefficients)/sizeof(PetscScalar)); /* gauss point setup */
1227 prop_stencil_width = 0;
1228 ierr = DMDACreate2d(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE,DMDA_STENCIL_BOX,
1229 mx,my,cpu_x,cpu_y,prop_dof,prop_stencil_width,lx,ly,&da_prop);CHKERRQ(ierr);
1230 ierr = PetscFree(lx);CHKERRQ(ierr);
1231 ierr = PetscFree(ly);CHKERRQ(ierr);
1233 /* define centroid positions */
1234 ierr = DMDAGetInfo(da_prop,0,&M,&N,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr);
1235 dx = 1.0/((PetscReal)(M));
1236 dy = 1.0/((PetscReal)(N));
1238 ierr = DMDASetUniformCoordinates(da_prop,0.0+0.5*dx,1.0-0.5*dx,0.0+0.5*dy,1.0-0.5*dy,0.0,1.0);CHKERRQ(ierr);
1240 /* define coefficients */
1241 ierr = PetscOptionsGetInt(NULL,"-c_str",&coefficient_structure,NULL);CHKERRQ(ierr);
1243 ierr = DMCreateGlobalVector(da_prop,&properties);CHKERRQ(ierr);
1244 ierr = DMCreateLocalVector(da_prop,&l_properties);CHKERRQ(ierr);
1245 ierr = DMDAVecGetArray(da_prop,l_properties,&element_props);CHKERRQ(ierr);
1247 ierr = DMGetCoordinateDM(da_prop,&prop_cda);CHKERRQ(ierr);
1248 ierr = DMGetCoordinatesLocal(da_prop,&prop_coords);CHKERRQ(ierr);
1249 ierr = DMDAVecGetArray(prop_cda,prop_coords,&_prop_coords);CHKERRQ(ierr);
1251 ierr = DMDAGetGhostCorners(prop_cda,&si,&sj,0,&nx,&ny,0);CHKERRQ(ierr);
1253 ierr = DMGetCoordinateDM(elas_da,&vel_cda);CHKERRQ(ierr);
1254 ierr = DMGetCoordinatesLocal(elas_da,&vel_coords);CHKERRQ(ierr);
1255 ierr = DMDAVecGetArray(vel_cda,vel_coords,&_vel_coords);CHKERRQ(ierr);
1258 /* interpolate the coordinates */
1259 for (j = sj; j < sj+ny; j++) {
1260 for (i = si; i < si+nx; i++) {
1262 PetscScalar gp_xi[GAUSS_POINTS][2],gp_weight[GAUSS_POINTS];
1263 PetscScalar el_coords[8];
1265 ierr = GetElementCoords(_vel_coords,i,j,el_coords);CHKERRQ(ierr);
1266 ConstructGaussQuadrature(&ngp,gp_xi,gp_weight);
1268 for (p = 0; p < GAUSS_POINTS; p++) {
1269 PetscScalar gp_x,gp_y;
1271 PetscScalar xi_p[2],Ni_p[4];
1273 xi_p[0] = gp_xi[p][0];
1274 xi_p[1] = gp_xi[p][1];
1275 ConstructQ12D_Ni(xi_p,Ni_p);
1279 for (n = 0; n < NODES_PER_EL; n++) {
1280 gp_x = gp_x+Ni_p[n]*el_coords[2*n];
1281 gp_y = gp_y+Ni_p[n]*el_coords[2*n+1];
1283 element_props[j][i].gp_coords[2*p] = gp_x;
1284 element_props[j][i].gp_coords[2*p+1] = gp_y;
1289 /* define the coefficients */
1290 ierr = PetscOptionsGetBool(NULL,"-use_gp_coords",&use_gp_coords,&flg);CHKERRQ(ierr);
1292 for (j = sj; j < sj+ny; j++) {
1293 for (i = si; i < si+nx; i++) {
1294 PetscScalar centroid_x = _prop_coords[j][i].x; /* centroids of cell */
1295 PetscScalar centroid_y = _prop_coords[j][i].y;
1296 PETSC_UNUSED PetscScalar coord_x,coord_y;
1299 if (coefficient_structure == 0) { /* isotropic */
1300 PetscScalar opts_E,opts_nu;
1304 ierr = PetscOptionsGetScalar(NULL,"-iso_E",&opts_E,&flg);CHKERRQ(ierr);
1305 ierr = PetscOptionsGetScalar(NULL,"-iso_nu",&opts_nu,&flg);CHKERRQ(ierr);
1307 for (p = 0; p < GAUSS_POINTS; p++) {
1308 element_props[j][i].E[p] = opts_E;
1309 element_props[j][i].nu[p] = opts_nu;
1311 element_props[j][i].fx[p] = 0.0;
1312 element_props[j][i].fy[p] = 0.0;
1314 } else if (coefficient_structure == 1) { /* step */
1315 PetscScalar opts_E0,opts_nu0,opts_xc;
1316 PetscScalar opts_E1,opts_nu1;
1318 opts_E0 = opts_E1 = 1.0;
1319 opts_nu0 = opts_nu1 = 0.333;
1321 ierr = PetscOptionsGetScalar(NULL,"-step_E0",&opts_E0,&flg);CHKERRQ(ierr);
1322 ierr = PetscOptionsGetScalar(NULL,"-step_nu0",&opts_nu0,&flg);CHKERRQ(ierr);
1323 ierr = PetscOptionsGetScalar(NULL,"-step_E1",&opts_E1,&flg);CHKERRQ(ierr);
1324 ierr = PetscOptionsGetScalar(NULL,"-step_nu1",&opts_nu1,&flg);CHKERRQ(ierr);
1325 ierr = PetscOptionsGetScalar(NULL,"-step_xc",&opts_xc,&flg);CHKERRQ(ierr);
1327 for (p = 0; p < GAUSS_POINTS; p++) {
1328 coord_x = centroid_x;
1329 coord_y = centroid_y;
1330 if (use_gp_coords) {
1331 coord_x = element_props[j][i].gp_coords[2*p];
1332 coord_y = element_props[j][i].gp_coords[2*p+1];
1335 element_props[j][i].E[p] = opts_E0;
1336 element_props[j][i].nu[p] = opts_nu0;
1337 if (PetscRealPart(coord_x) > PetscRealPart(opts_xc)) {
1338 element_props[j][i].E[p] = opts_E1;
1339 element_props[j][i].nu[p] = opts_nu1;
1342 element_props[j][i].fx[p] = 0.0;
1343 element_props[j][i].fy[p] = 0.0;
1345 } else if (coefficient_structure == 2) { /* brick */
1346 PetscReal values_E[10];
1347 PetscReal values_nu[10];
1348 PetscInt nbricks,maxnbricks;
1349 PetscInt index,span;
1354 ierr = PetscOptionsGetRealArray(NULL, "-brick_E",values_E,&maxnbricks,&flg);CHKERRQ(ierr);
1355 nbricks = maxnbricks;
1356 if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"User must supply a list of E values for each brick");CHKERRQ(ierr);
1360 ierr = PetscOptionsGetRealArray(NULL, "-brick_nu",values_nu,&maxnbricks,&flg);CHKERRQ(ierr);
1361 if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"User must supply a list of nu values for each brick");CHKERRQ(ierr);
1362 if (maxnbricks != nbricks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"User must supply equal numbers of values for E and nu");CHKERRQ(ierr);
1365 ierr = PetscOptionsGetInt(NULL,"-brick_span",&span,&flg);CHKERRQ(ierr);
1367 /* cycle through the indices so that no two material properties are repeated in lines of x or y */
1368 jj = (j/span)%nbricks;
1369 index = (jj+i/span)%nbricks;
1370 /*printf("j=%d: index = %d \n", j,index); */
1372 for (p = 0; p < GAUSS_POINTS; p++) {
1373 element_props[j][i].E[p] = values_E[index];
1374 element_props[j][i].nu[p] = values_nu[index];
1376 } else if (coefficient_structure == 3) { /* sponge */
1377 PetscScalar opts_E0,opts_nu0;
1378 PetscScalar opts_E1,opts_nu1;
1379 PetscInt opts_t,opts_w;
1380 PetscInt ii,jj,ci,cj;
1382 opts_E0 = opts_E1 = 1.0;
1383 opts_nu0 = opts_nu1 = 0.333;
1384 ierr = PetscOptionsGetScalar(NULL,"-sponge_E0",&opts_E0,&flg);CHKERRQ(ierr);
1385 ierr = PetscOptionsGetScalar(NULL,"-sponge_nu0",&opts_nu0,&flg);CHKERRQ(ierr);
1386 ierr = PetscOptionsGetScalar(NULL,"-sponge_E1",&opts_E1,&flg);CHKERRQ(ierr);
1387 ierr = PetscOptionsGetScalar(NULL,"-sponge_nu1",&opts_nu1,&flg);CHKERRQ(ierr);
1389 opts_t = opts_w = 1;
1390 ierr = PetscOptionsGetInt(NULL,"-sponge_t",&opts_t,&flg);CHKERRQ(ierr);
1391 ierr = PetscOptionsGetInt(NULL,"-sponge_w",&opts_w,&flg);CHKERRQ(ierr);
1393 ii = (i)/(opts_t+opts_w+opts_t);
1394 jj = (j)/(opts_t+opts_w+opts_t);
1396 ci = i - ii*(opts_t+opts_w+opts_t);
1397 cj = j - jj*(opts_t+opts_w+opts_t);
1399 for (p = 0; p < GAUSS_POINTS; p++) {
1400 element_props[j][i].E[p] = opts_E0;
1401 element_props[j][i].nu[p] = opts_nu0;
1403 if ((ci >= opts_t) && (ci < opts_t+opts_w)) {
1404 if ((cj >= opts_t) && (cj < opts_t+opts_w)) {
1405 for (p = 0; p < GAUSS_POINTS; p++) {
1406 element_props[j][i].E[p] = opts_E1;
1407 element_props[j][i].nu[p] = opts_nu1;
1412 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Unknown coefficient_structure");
1415 ierr = DMDAVecRestoreArray(prop_cda,prop_coords,&_prop_coords);CHKERRQ(ierr);
1417 ierr = DMDAVecRestoreArray(vel_cda,vel_coords,&_vel_coords);CHKERRQ(ierr);
1419 ierr = DMDAVecRestoreArray(da_prop,l_properties,&element_props);CHKERRQ(ierr);
1420 ierr = DMLocalToGlobalBegin(da_prop,l_properties,ADD_VALUES,properties);CHKERRQ(ierr);
1421 ierr = DMLocalToGlobalEnd(da_prop,l_properties,ADD_VALUES,properties);CHKERRQ(ierr);
1423 /* ierr = PetscOptionsGetBool(NULL,"-no_view",&no_view,NULL);CHKERRQ(ierr);
1425 ierr = DMDAViewCoefficientsGnuplot2d(da_prop,properties,"Coeffcients for elasticity eqn.","properties");CHKERRQ(ierr);
1426 ierr = DMDACoordViewGnuplot2d(elas_da,"mesh");CHKERRQ(ierr);
1429 /* Generate a matrix with the correct non-zero pattern of type AIJ. This will work in parallel and serial */
1430 ierr = DMSetMatType(elas_da,MATAIJ);CHKERRQ(ierr);
1431 ierr = DMCreateMatrix(elas_da,&A);CHKERRQ(ierr);
1432 ierr = DMGetCoordinates(elas_da,&vel_coords);CHKERRQ(ierr);
1433 ierr = MatNullSpaceCreateRigidBody(vel_coords,&matnull);CHKERRQ(ierr);
1434 ierr = MatSetNearNullSpace(A,matnull);CHKERRQ(ierr);
1435 ierr = MatNullSpaceDestroy(&matnull);CHKERRQ(ierr);
1436 ierr = MatGetVecs(A,&f,&X);CHKERRQ(ierr);
1439 ierr = MatZeroEntries(A);CHKERRQ(ierr);
1440 ierr = VecZeroEntries(f);CHKERRQ(ierr);
1442 ierr = AssembleA_Elasticity(A,elas_da,da_prop,properties);CHKERRQ(ierr);
1443 /* build force vector */
1444 ierr = AssembleF_Elasticity(f,elas_da,da_prop,properties);CHKERRQ(ierr);
1447 ierr = KSPCreate(PETSC_COMM_WORLD,&ksp_E);CHKERRQ(ierr);
1448 ierr = KSPSetOptionsPrefix(ksp_E,"elas_");CHKERRQ(ierr); /* elasticity */
1450 ierr = PetscOptionsGetBool(NULL,"-use_nonsymbc",&use_nonsymbc,&flg);CHKERRQ(ierr);
1452 if (!use_nonsymbc) {
1458 ierr = DMDABCApplySymmetricCompression(elas_da,A,f,&is,&AA,&ff);CHKERRQ(ierr);
1459 ierr = VecDuplicate(ff,&XX);CHKERRQ(ierr);
1461 ierr = KSPSetOperators(ksp_E,AA,AA);CHKERRQ(ierr);
1462 ierr = KSPSetFromOptions(ksp_E);CHKERRQ(ierr);
1464 ierr = KSPSetFromOptions(ksp_E);CHKERRQ(ierr);
1467 ierr = KSPSetTolerances(ksp_E, 1e-9, 1e-9, PETSC_DEFAULT, 50000000); CHKERRQ(ierr);
1468 /* T1 = MPI_Wtime();
1470 ierr = KSPSolve(ksp_E,ff,XX);CHKERRQ(ierr);
1478 VecDuplicate(ff,&sol);
1479 VecDuplicate(ff,&X2);
1483 KSPGetOperators(ksp_E,&A,NULL);
1486 VecNorm(sol, NORM_2, &norm);
1489 ierr = PetscPrintf(PETSC_COMM_WORLD, "\t\t\t -- Norm of error : %g\n", (double)norm); CHKERRQ(ierr);
1490 ierr = PetscPrintf(PETSC_COMM_WORLD, "\t\t\t -- Execution time : %g (s)\n", T2-T1); CHKERRQ(ierr);
1492 ierr = KSPGetIterationNumber(ksp_E, &total); CHKERRQ(ierr);
1493 ierr = PetscPrintf(PETSC_COMM_WORLD, "\t\t\t -- Total number of iterations : %D\n", total); CHKERRQ(ierr);
1498 KrylovMinimize(A, ff, X2);
1503 VecNorm(sol, NORM_2, &norm);
1504 ierr = PetscPrintf(PETSC_COMM_WORLD, "Error2 %g\n",norm);
1510 KrylovMinimizeLSQR(A, ff, X2);
1515 VecNorm(sol, NORM_2, &norm);
1516 ierr = PetscPrintf(PETSC_COMM_WORLD, "ErrorLSQR %g\n",norm);
1520 /* push XX back into X */
1521 ierr = DMDABCApplyCompression(elas_da,NULL,X);CHKERRQ(ierr);
1523 ierr = VecScatterCreate(XX,NULL,X,is,&scat);CHKERRQ(ierr);
1524 ierr = VecScatterBegin(scat,XX,X,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1525 ierr = VecScatterEnd(scat,XX,X,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1526 ierr = VecScatterDestroy(&scat);CHKERRQ(ierr);
1528 ierr = MatDestroy(&AA);CHKERRQ(ierr);
1529 ierr = VecDestroy(&ff);CHKERRQ(ierr);
1530 ierr = VecDestroy(&XX);CHKERRQ(ierr);
1531 ierr = ISDestroy(&is);CHKERRQ(ierr);
1533 ierr = DMDABCApplyCompression(elas_da,A,f);CHKERRQ(ierr);
1535 ierr = KSPSetOperators(ksp_E,A,A);CHKERRQ(ierr);
1536 ierr = KSPSetFromOptions(ksp_E);CHKERRQ(ierr);
1538 ierr = KSPSolve(ksp_E,f,X);CHKERRQ(ierr);
1541 // if (!no_view) {ierr = DMDAViewGnuplot2d(elas_da,X,"Displacement solution for elasticity eqn.","X");CHKERRQ(ierr);}
1542 ierr = KSPDestroy(&ksp_E);CHKERRQ(ierr);
1544 ierr = VecDestroy(&X);CHKERRQ(ierr);
1545 ierr = VecDestroy(&f);CHKERRQ(ierr);
1546 ierr = MatDestroy(&A);CHKERRQ(ierr);
1548 ierr = DMDestroy(&elas_da);CHKERRQ(ierr);
1549 ierr = DMDestroy(&da_prop);CHKERRQ(ierr);
1551 ierr = VecDestroy(&properties);CHKERRQ(ierr);
1552 ierr = VecDestroy(&l_properties);CHKERRQ(ierr);
1553 PetscFunctionReturn(0);
1557 #define __FUNCT__ "main"
1558 int main(int argc,char **args)
1560 PetscErrorCode ierr;
1563 ierr = PetscInitialize(&argc,&args,(char*)0,help);CHKERRQ(ierr);
1566 ierr = PetscOptionsGetInt(NULL,"-mx",&mx,NULL);CHKERRQ(ierr);
1567 ierr = PetscOptionsGetInt(NULL,"-my",&my,NULL);CHKERRQ(ierr);
1571 MPI_Comm_size(PETSC_COMM_WORLD,&size);
1572 PetscPrintf(PETSC_COMM_WORLD,"Number of processors = %d\n",size);
1575 ierr = solve_elasticity_2d(mx,my);CHKERRQ(ierr);
1577 ierr = PetscFinalize();CHKERRQ(ierr);
1581 /* -------------------------- helpers for boundary conditions -------------------------------- */
1584 #define __FUNCT__ "BCApply_EAST"
1585 static PetscErrorCode BCApply_EAST(DM da,PetscInt d_idx,PetscScalar bc_val,Mat A,Vec b)
1589 PetscInt si,sj,nx,ny,i,j;
1591 DMDACoor2d **_coords;
1592 const PetscInt *g_idx;
1593 PetscInt *bc_global_ids;
1594 PetscScalar *bc_vals;
1597 PetscErrorCode ierr;
1598 ISLocalToGlobalMapping ltogm;
1600 PetscFunctionBeginUser;
1602 ierr = DMGetLocalToGlobalMapping(da,<ogm);CHKERRQ(ierr);
1603 ierr = ISLocalToGlobalMappingGetIndices(ltogm,&g_idx);CHKERRQ(ierr);
1605 ierr = DMGetCoordinateDM(da,&cda);CHKERRQ(ierr);
1606 ierr = DMGetCoordinatesLocal(da,&coords);CHKERRQ(ierr);
1607 ierr = DMDAVecGetArray(cda,coords,&_coords);CHKERRQ(ierr);
1608 ierr = DMDAGetGhostCorners(cda,&si,&sj,0,&nx,&ny,0);CHKERRQ(ierr);
1609 ierr = DMDAGetInfo(da,0,&M,&N,0,0,0,0,&n_dofs,0,0,0,0,0);CHKERRQ(ierr);
1613 ierr = PetscMalloc(sizeof(PetscInt)*ny*n_dofs,&bc_global_ids);CHKERRQ(ierr);
1614 ierr = PetscMalloc(sizeof(PetscScalar)*ny*n_dofs,&bc_vals);CHKERRQ(ierr);
1616 /* init the entries to -1 so VecSetValues will ignore them */
1617 for (i = 0; i < ny*n_dofs; i++) bc_global_ids[i] = -1;
1620 for (j = 0; j < ny; j++) {
1622 PETSC_UNUSED PetscScalar coordx,coordy;
1626 bc_global_ids[j] = g_idx[n_dofs*local_id+d_idx];
1628 coordx = _coords[j+sj][i+si].x;
1629 coordy = _coords[j+sj][i+si].y;
1631 bc_vals[j] = bc_val;
1633 ierr = ISLocalToGlobalMappingRestoreIndices(ltogm,&g_idx);CHKERRQ(ierr);
1635 if ((si+nx) == (M)) nbcs = ny;
1638 ierr = VecSetValues(b,nbcs,bc_global_ids,bc_vals,INSERT_VALUES);CHKERRQ(ierr);
1639 ierr = VecAssemblyBegin(b);CHKERRQ(ierr);
1640 ierr = VecAssemblyEnd(b);CHKERRQ(ierr);
1643 ierr = MatZeroRows(A,nbcs,bc_global_ids,1.0,0,0);CHKERRQ(ierr);
1646 ierr = PetscFree(bc_vals);CHKERRQ(ierr);
1647 ierr = PetscFree(bc_global_ids);CHKERRQ(ierr);
1649 ierr = DMDAVecRestoreArray(cda,coords,&_coords);CHKERRQ(ierr);
1650 PetscFunctionReturn(0);
1654 #define __FUNCT__ "BCApply_WEST"
1655 static PetscErrorCode BCApply_WEST(DM da,PetscInt d_idx,PetscScalar bc_val,Mat A,Vec b)
1659 PetscInt si,sj,nx,ny,i,j;
1661 DMDACoor2d **_coords;
1662 const PetscInt *g_idx;
1663 PetscInt *bc_global_ids;
1664 PetscScalar *bc_vals;
1667 PetscErrorCode ierr;
1668 ISLocalToGlobalMapping ltogm;
1670 PetscFunctionBeginUser;
1672 ierr = DMGetLocalToGlobalMapping(da,<ogm);CHKERRQ(ierr);
1673 ierr = ISLocalToGlobalMappingGetIndices(ltogm,&g_idx);CHKERRQ(ierr);
1675 ierr = DMGetCoordinateDM(da,&cda);CHKERRQ(ierr);
1676 ierr = DMGetCoordinatesLocal(da,&coords);CHKERRQ(ierr);
1677 ierr = DMDAVecGetArray(cda,coords,&_coords);CHKERRQ(ierr);
1678 ierr = DMDAGetGhostCorners(cda,&si,&sj,0,&nx,&ny,0);CHKERRQ(ierr);
1679 ierr = DMDAGetInfo(da,0,&M,&N,0,0,0,0,&n_dofs,0,0,0,0,0);CHKERRQ(ierr);
1683 ierr = PetscMalloc(sizeof(PetscInt)*ny*n_dofs,&bc_global_ids);CHKERRQ(ierr);
1684 ierr = PetscMalloc(sizeof(PetscScalar)*ny*n_dofs,&bc_vals);CHKERRQ(ierr);
1686 /* init the entries to -1 so VecSetValues will ignore them */
1687 for (i = 0; i < ny*n_dofs; i++) bc_global_ids[i] = -1;
1690 for (j = 0; j < ny; j++) {
1692 PETSC_UNUSED PetscScalar coordx,coordy;
1696 bc_global_ids[j] = g_idx[n_dofs*local_id+d_idx];
1698 coordx = _coords[j+sj][i+si].x;
1699 coordy = _coords[j+sj][i+si].y;
1701 bc_vals[j] = bc_val;
1703 ierr = ISLocalToGlobalMappingRestoreIndices(ltogm,&g_idx);CHKERRQ(ierr);
1705 if (si == 0) nbcs = ny;
1708 ierr = VecSetValues(b,nbcs,bc_global_ids,bc_vals,INSERT_VALUES);CHKERRQ(ierr);
1709 ierr = VecAssemblyBegin(b);CHKERRQ(ierr);
1710 ierr = VecAssemblyEnd(b);CHKERRQ(ierr);
1713 ierr = MatZeroRows(A,nbcs,bc_global_ids,1.0,0,0);CHKERRQ(ierr);
1716 ierr = PetscFree(bc_vals);CHKERRQ(ierr);
1717 ierr = PetscFree(bc_global_ids);CHKERRQ(ierr);
1719 ierr = DMDAVecRestoreArray(cda,coords,&_coords);CHKERRQ(ierr);
1720 PetscFunctionReturn(0);
1724 #define __FUNCT__ "DMDABCApplyCompression"
1725 static PetscErrorCode DMDABCApplyCompression(DM elas_da,Mat A,Vec f)
1727 PetscErrorCode ierr;
1729 PetscFunctionBeginUser;
1730 ierr = BCApply_EAST(elas_da,0,-1.0,A,f);CHKERRQ(ierr);
1731 ierr = BCApply_EAST(elas_da,1, 0.0,A,f);CHKERRQ(ierr);
1732 ierr = BCApply_WEST(elas_da,0,1.0,A,f);CHKERRQ(ierr);
1733 ierr = BCApply_WEST(elas_da,1,0.0,A,f);CHKERRQ(ierr);
1734 PetscFunctionReturn(0);
1738 #define __FUNCT__ "DMDABCApplySymmetricCompression"
1739 static PetscErrorCode DMDABCApplySymmetricCompression(DM elas_da,Mat A,Vec f,IS *dofs,Mat *AA,Vec *ff)
1741 PetscErrorCode ierr;
1742 PetscInt start,end,m;
1743 PetscInt *unconstrained;
1750 PetscFunctionBeginUser;
1751 /* push bc's into f and A */
1752 ierr = VecDuplicate(f,&x);CHKERRQ(ierr);
1753 ierr = BCApply_EAST(elas_da,0,-1.0,A,x);CHKERRQ(ierr);
1754 ierr = BCApply_EAST(elas_da,1, 0.0,A,x);CHKERRQ(ierr);
1755 ierr = BCApply_WEST(elas_da,0,1.0,A,x);CHKERRQ(ierr);
1756 ierr = BCApply_WEST(elas_da,1,0.0,A,x);CHKERRQ(ierr);
1758 /* define which dofs are not constrained */
1759 ierr = VecGetLocalSize(x,&m);CHKERRQ(ierr);
1760 ierr = PetscMalloc(sizeof(PetscInt)*m,&unconstrained);CHKERRQ(ierr);
1761 ierr = VecGetOwnershipRange(x,&start,&end);CHKERRQ(ierr);
1762 ierr = VecGetArray(x,&_x);CHKERRQ(ierr);
1764 for (i = 0; i < m; i++) {
1767 val = PetscRealPart(_x[i]);
1768 if (fabs(val) < 0.1) {
1769 unconstrained[cnt] = start + i;
1773 ierr = VecRestoreArray(x,&_x);CHKERRQ(ierr);
1775 ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,unconstrained,PETSC_COPY_VALUES,&is);CHKERRQ(ierr);
1776 ierr = PetscFree(unconstrained);CHKERRQ(ierr);
1778 /* define correction for dirichlet in the rhs */
1779 ierr = MatMult(A,x,f);CHKERRQ(ierr);
1780 ierr = VecScale(f,-1.0);CHKERRQ(ierr);
1782 /* get new matrix */
1783 ierr = MatGetSubMatrix(A,is,is,MAT_INITIAL_MATRIX,AA);CHKERRQ(ierr);
1784 /* get new vector */
1785 ierr = MatGetVecs(*AA,NULL,ff);CHKERRQ(ierr);
1787 ierr = VecScatterCreate(f,is,*ff,NULL,&scat);CHKERRQ(ierr);
1788 ierr = VecScatterBegin(scat,f,*ff,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1789 ierr = VecScatterEnd(scat,f,*ff,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1791 { /* Constrain near-null space */
1795 PetscBool has_const;
1796 MatNullSpace mnull,unull;
1797 ierr = MatGetNearNullSpace(A,&mnull);CHKERRQ(ierr);
1798 ierr = MatNullSpaceGetVecs(mnull,&has_const,&nvecs,&vecs);CHKERRQ(ierr);
1799 ierr = VecDuplicateVecs(*ff,nvecs,&uvecs);CHKERRQ(ierr);
1800 for (i=0; i<nvecs; i++) {
1801 ierr = VecScatterBegin(scat,vecs[i],uvecs[i],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1802 ierr = VecScatterEnd(scat,vecs[i],uvecs[i],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1804 ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)A),has_const,nvecs,uvecs,&unull);CHKERRQ(ierr);
1805 ierr = MatSetNearNullSpace(*AA,unull);CHKERRQ(ierr);
1806 ierr = MatNullSpaceDestroy(&unull);CHKERRQ(ierr);
1807 for (i=0; i<nvecs; i++) {
1808 ierr = VecDestroy(&uvecs[i]);CHKERRQ(ierr);
1810 ierr = PetscFree(uvecs);CHKERRQ(ierr);
1813 ierr = VecScatterDestroy(&scat);CHKERRQ(ierr);
1816 ierr = VecDestroy(&x);CHKERRQ(ierr);
1817 PetscFunctionReturn(0);