Actual source code: elliptic.c
petsc-dev 2014-02-02
1: #include <petsc-private/taoimpl.h>
2: #include "../src/tao/pde_constrained/impls/lcl/lcl.h"
4: /*T
5: Concepts: TAO^Solving a system of nonlinear equations, nonlinear least squares
6: Routines: TaoCreate();
7: Routines: TaoSetType();
8: Routines: TaoSetInitialVector();
9: Routines: TaoSetObjectiveRoutine();
10: Routines: TaoSetGradientRoutine();
11: Routines: TaoSetConstraintsRoutine();
12: Routines: TaoSetJacobianStateRoutine();
13: Routines: TaoSetJacobianDesignRoutine();
14: Routines: TaoSetStateDesignIS();
15: Routines: TaoSetFromOptions();
16: Routines: TaoSetHistory(); TaoGetHistory();
17: Routines: TaoSolve();
18: Routines: TaoGetTerminationReason(); TaoDestroy();
19: Processors: n
20: T*/
22: typedef struct {
23: PetscInt n; /* Number of total variables */
24: PetscInt m; /* Number of constraints */
25: PetscInt nstate;
26: PetscInt ndesign;
27: PetscInt mx; /* grid points in each direction */
28: PetscInt ns; /* Number of data samples (1<=ns<=8)
29: Currently only ns=1 is supported */
30: PetscInt ndata; /* Number of data points per sample */
31: IS s_is;
32: IS d_is;
34: VecScatter state_scatter;
35: VecScatter design_scatter;
36: VecScatter *yi_scatter, *di_scatter;
37: Vec suby,subq,subd;
38: Mat Js,Jd,JsPrec,JsInv,JsBlock;
40: PetscReal alpha; /* Regularization parameter */
41: PetscReal beta; /* Weight attributed to ||u||^2 in regularization functional */
42: PetscReal noise; /* Amount of noise to add to data */
43: PetscReal *ones;
44: Mat Q;
45: Mat MQ;
46: Mat L;
48: Mat Grad;
49: Mat Av,Avwork;
50: Mat Div, Divwork;
51: Mat DSG;
52: Mat Diag,Ones;
55: Vec q;
56: Vec ur; /* reference */
58: Vec d;
59: Vec dwork;
61: Vec x; /* super vec of y,u */
63: Vec y; /* state variables */
64: Vec ywork;
66: Vec ytrue;
68: Vec u; /* design variables */
69: Vec uwork;
71: Vec utrue;
73: Vec js_diag;
75: Vec c; /* constraint vector */
76: Vec cwork;
78: Vec lwork;
79: Vec S;
80: Vec Swork,Twork,Sdiag,Ywork;
81: Vec Av_u;
83: KSP solver;
84: PC prec;
86: PetscReal tola,tolb,tolc,told;
87: PetscInt ksp_its;
88: PetscInt ksp_its_initial;
89: int stages[10];
90: PetscBool use_ptap;
91: PetscBool use_lrc;
92: TAO_LCL* lcl;
93: } AppCtx;
95: PetscErrorCode FormFunction(Tao, Vec, PetscReal*, void*);
96: PetscErrorCode FormGradient(Tao, Vec, Vec, void*);
97: PetscErrorCode FormFunctionGradient(Tao, Vec, PetscReal*, Vec, void*);
98: PetscErrorCode FormJacobianState(Tao, Vec, Mat*, Mat*, Mat*, MatStructure*,void*);
99: PetscErrorCode FormJacobianDesign(Tao, Vec, Mat*,void*);
100: PetscErrorCode FormConstraints(Tao, Vec, Vec, void*);
101: PetscErrorCode FormHessian(Tao, Vec, Mat*, Mat*, MatStructure*, void*);
102: PetscErrorCode Gather(Vec, Vec, VecScatter, Vec, VecScatter);
103: PetscErrorCode Scatter(Vec, Vec, VecScatter, Vec, VecScatter);
104: PetscErrorCode EllipticInitialize(AppCtx*);
105: PetscErrorCode EllipticDestroy(AppCtx*);
106: PetscErrorCode EllipticMonitor(Tao, void*);
108: PetscErrorCode StateBlockMatMult(Mat,Vec,Vec);
109: PetscErrorCode StateMatMult(Mat,Vec,Vec);
111: PetscErrorCode StateInvMatMult(Mat,Vec,Vec);
112: PetscErrorCode DesignMatMult(Mat,Vec,Vec);
113: PetscErrorCode DesignMatMultTranspose(Mat,Vec,Vec);
115: PetscErrorCode QMatMult(Mat,Vec,Vec);
116: PetscErrorCode QMatMultTranspose(Mat,Vec,Vec);
118: static char help[]="";
122: int main(int argc, char **argv)
123: {
124: PetscErrorCode ierr;
125: Vec x0;
126: Tao tao;
127: TaoTerminationReason reason;
128: AppCtx user;
129: PetscBool flag;
130: PetscInt ntests = 1;
131: PetscInt i;
133: PetscInitialize(&argc, &argv, (char*)0,help);
134: user.mx = 8;
135: PetscOptionsInt("-mx","Number of grid points in each direction","",user.mx,&user.mx,&flag);
136: user.ns = 6;
137: PetscOptionsInt("-ns","Number of data samples (1<=ns<=8)","",user.ns,&user.ns,&flag);
138: user.ndata = 64;
139: PetscOptionsInt("-ndata","Numbers of data points per sample","",user.ndata,&user.ndata,&flag);
140: user.alpha = 0.1;
141: PetscOptionsReal("-alpha","Regularization parameter","",user.alpha,&user.alpha,&flag);
142: user.beta = 0.00001;
143: PetscOptionsReal("-beta","Weight attributed to ||u||^2 in regularization functional","",user.beta,&user.beta,&flag);
144: user.noise = 0.01;
145: PetscOptionsReal("-noise","Amount of noise to add to data","",user.noise,&user.noise,&flag);
147: PetscOptionsBool("-use_ptap","Use ptap matrix for DSG","",PETSC_FALSE,&user.use_ptap,&flag);
148: PetscOptionsBool("-use_lrc","Use lrc matrix for Js","",PETSC_FALSE,&user.use_lrc,&flag);
150: user.m = user.ns*user.mx*user.mx*user.mx; /* number of constraints */
151: user.nstate = user.m;
152: user.ndesign = user.mx*user.mx*user.mx;
153: user.n = user.nstate + user.ndesign; /* number of variables */
155: /* Create TAO solver and set desired solution method */
156: TaoCreate(PETSC_COMM_WORLD,&tao);
157: TaoSetType(tao,"tao_lcl");
158: user.lcl = (TAO_LCL*)(tao->data);
160: /* Set up initial vectors and matrices */
161: EllipticInitialize(&user);
163: Gather(user.x,user.y,user.state_scatter,user.u,user.design_scatter);
164: VecDuplicate(user.x,&x0);
165: VecCopy(user.x,x0);
167: /* Set solution vector with an initial guess */
168: TaoSetInitialVector(tao,user.x);
169: TaoSetObjectiveRoutine(tao, FormFunction, (void *)&user);
170: TaoSetGradientRoutine(tao, FormGradient, (void *)&user);
171: TaoSetConstraintsRoutine(tao, user.c, FormConstraints, (void *)&user);
173: TaoSetJacobianStateRoutine(tao, user.Js, NULL, user.JsInv, FormJacobianState, (void *)&user);
174: TaoSetJacobianDesignRoutine(tao, user.Jd, FormJacobianDesign, (void *)&user);
176: TaoSetStateDesignIS(tao,user.s_is,user.d_is);
177: TaoSetFromOptions(tao);
179: /* SOLVE THE APPLICATION */
180: PetscOptionsInt("-ntests","Number of times to repeat TaoSolve","",ntests,&ntests,&flag);
181: PetscLogStageRegister("Trials",&user.stages[1]);
182: PetscLogStagePush(user.stages[1]);
183: for (i=0; i<ntests; i++){
184: TaoSolve(tao);
185: PetscPrintf(PETSC_COMM_WORLD,"KSP Iterations = %D\n",user.ksp_its);
186: VecCopy(x0,user.x);
187: }
188: PetscLogStagePop();
189: PetscBarrier((PetscObject)user.x);
190: PetscPrintf(PETSC_COMM_WORLD,"KSP iterations within initialization: ");
191: PetscPrintf(PETSC_COMM_WORLD,"%D\n",user.ksp_its_initial);
193: TaoGetTerminationReason(tao,&reason);
194: if (reason < 0) {
195: PetscPrintf(MPI_COMM_WORLD, "TAO failed to converge.\n");
196: } else {
197: PetscPrintf(MPI_COMM_WORLD, "Optimization terminated with status %D.\n", reason);
198: }
200: TaoDestroy(&tao);
201: VecDestroy(&x0);
202: EllipticDestroy(&user);
203: PetscFinalize();
204: return 0;
205: }
206: /* ------------------------------------------------------------------- */
209: /*
210: dwork = Qy - d
211: lwork = L*(u-ur)
212: f = 1/2 * (dwork.dwork + alpha*lwork.lwork)
213: */
214: PetscErrorCode FormFunction(Tao tao,Vec X,PetscReal *f,void *ptr)
215: {
217: PetscReal d1=0,d2=0;
218: AppCtx *user = (AppCtx*)ptr;
221: Scatter(X,user->y,user->state_scatter,user->u,user->design_scatter);
222: MatMult(user->MQ,user->y,user->dwork);
223: VecAXPY(user->dwork,-1.0,user->d);
224: VecDot(user->dwork,user->dwork,&d1);
225: VecWAXPY(user->uwork,-1.0,user->ur,user->u);
226: MatMult(user->L,user->uwork,user->lwork);
227: VecDot(user->lwork,user->lwork,&d2);
228: *f = 0.5 * (d1 + user->alpha*d2);
229: return(0);
230: }
232: /* ------------------------------------------------------------------- */
235: /*
236: state: g_s = Q' *(Qy - d)
237: design: g_d = alpha*L'*L*(u-ur)
238: */
239: PetscErrorCode FormGradient(Tao tao,Vec X,Vec G,void *ptr)
240: {
242: AppCtx *user = (AppCtx*)ptr;
245: Scatter(X,user->y,user->state_scatter,user->u,user->design_scatter);
246: MatMult(user->MQ,user->y,user->dwork);
247: VecAXPY(user->dwork,-1.0,user->d);
248: MatMultTranspose(user->MQ,user->dwork,user->ywork);
249: VecWAXPY(user->uwork,-1.0,user->ur,user->u);
250: MatMult(user->L,user->uwork,user->lwork);
251: MatMultTranspose(user->L,user->lwork,user->uwork);
252: VecScale(user->uwork, user->alpha);
253: Gather(G,user->ywork,user->state_scatter,user->uwork,user->design_scatter);
254: return(0);
255: }
259: PetscErrorCode FormFunctionGradient(Tao tao, Vec X, PetscReal *f, Vec G, void *ptr)
260: {
262: PetscReal d1,d2;
263: AppCtx *user = (AppCtx*)ptr;
266: Scatter(X,user->y,user->state_scatter,user->u,user->design_scatter);
267: MatMult(user->MQ,user->y,user->dwork);
268: VecAXPY(user->dwork,-1.0,user->d);
269: VecDot(user->dwork,user->dwork,&d1);
270: MatMultTranspose(user->MQ,user->dwork,user->ywork);
272: VecWAXPY(user->uwork,-1.0,user->ur,user->u);
273: MatMult(user->L,user->uwork,user->lwork);
274: VecDot(user->lwork,user->lwork,&d2);
275: MatMultTranspose(user->L,user->lwork,user->uwork);
276: VecScale(user->uwork, user->alpha);
277: *f = 0.5 * (d1 + user->alpha*d2);
278: Gather(G,user->ywork,user->state_scatter,user->uwork,user->design_scatter);
279: return(0);
280: }
282: /* ------------------------------------------------------------------- */
285: /* A
286: MatShell object
287: */
288: PetscErrorCode FormJacobianState(Tao tao, Vec X, Mat *J, Mat* JPre, Mat* JInv, MatStructure* flag, void *ptr)
289: {
291: AppCtx *user = (AppCtx*)ptr;
294: Scatter(X,user->y,user->state_scatter,user->u,user->design_scatter);
295: /* DSG = Div * (1/Av_u) * Grad */
296: VecSet(user->uwork,0);
297: VecAXPY(user->uwork,-1.0,user->u);
298: VecExp(user->uwork);
299: MatMult(user->Av,user->uwork,user->Av_u);
300: VecCopy(user->Av_u,user->Swork);
301: VecReciprocal(user->Swork);
302: if (user->use_ptap) {
303: MatDiagonalSet(user->Diag,user->Swork,INSERT_VALUES);
304: MatPtAP(user->Diag,user->Grad,MAT_REUSE_MATRIX,1.0,&user->DSG);
305: } else {
306: MatCopy(user->Div,user->Divwork,SAME_NONZERO_PATTERN);
307: MatDiagonalScale(user->Divwork,NULL,user->Swork);
308: MatMatMultNumeric(user->Divwork,user->Grad,user->DSG);
309: }
310: *flag = SAME_NONZERO_PATTERN;
311: return(0);
312: }
313: /* ------------------------------------------------------------------- */
316: /* B */
317: PetscErrorCode FormJacobianDesign(Tao tao, Vec X, Mat *J, void *ptr)
318: {
320: AppCtx *user = (AppCtx*)ptr;
323: Scatter(X,user->y,user->state_scatter,user->u,user->design_scatter);
324: *J = user->Jd;
325: return(0);
326: }
330: PetscErrorCode StateBlockMatMult(Mat J_shell, Vec X, Vec Y)
331: {
333: PetscReal sum;
334: AppCtx *user;
337: MatShellGetContext(J_shell,(void**)&user);
338: MatMult(user->DSG,X,Y);
339: VecSum(X,&sum);
340: sum /= user->ndesign;
341: VecShift(Y,sum);
342: return(0);
343: }
347: PetscErrorCode StateMatMult(Mat J_shell, Vec X, Vec Y)
348: {
350: PetscInt i;
351: AppCtx *user;
354: MatShellGetContext(J_shell,(void**)&user);
355: if (user->ns == 1) {
356: MatMult(user->JsBlock,X,Y);
357: } else {
358: for (i=0;i<user->ns;i++) {
359: Scatter(X,user->subq,user->yi_scatter[i],0,0);
360: Scatter(Y,user->suby,user->yi_scatter[i],0,0);
361: MatMult(user->JsBlock,user->subq,user->suby);
362: Gather(X,user->subq,user->yi_scatter[i],0,0);
363: Gather(Y,user->suby,user->yi_scatter[i],0,0);
364: }
365: }
366: return(0);
367: }
371: PetscErrorCode StateInvMatMult(Mat J_shell, Vec X, Vec Y)
372: {
374: PetscInt its,i;
375: PetscReal tau;
376: AppCtx *user;
379: MatShellGetContext(J_shell,(void**)&user);
380: KSPSetOperators(user->solver,user->JsBlock,user->DSG,SAME_NONZERO_PATTERN);
381: if (Y == user->ytrue) {
382: KSPSetTolerances(user->solver,1e-8,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
383: } else if (user->lcl) {
384: tau = user->lcl->tau[user->lcl->solve_type];
385: KSPSetTolerances(user->solver,tau,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
386: }
387: if (user->ns == 1) {
388: KSPSolve(user->solver,X,Y);
389: KSPGetIterationNumber(user->solver,&its);
390: user->ksp_its+=its;
391: } else {
392: for (i=0;i<user->ns;i++) {
393: Scatter(X,user->subq,user->yi_scatter[i],0,0);
394: Scatter(Y,user->suby,user->yi_scatter[i],0,0);
395: KSPSolve(user->solver,user->subq,user->suby);
396: KSPGetIterationNumber(user->solver,&its);
397: user->ksp_its+=its;
398: Gather(X,user->subq,user->yi_scatter[i],0,0);
399: Gather(Y,user->suby,user->yi_scatter[i],0,0);
400: }
401: }
402: return(0);
403: }
406: PetscErrorCode QMatMult(Mat J_shell, Vec X, Vec Y)
407: {
409: AppCtx *user;
410: PetscInt i;
413: MatShellGetContext(J_shell,(void**)&user);
414: if (user->ns == 1) {
415: MatMult(user->Q,X,Y);
416: } else {
417: for (i=0;i<user->ns;i++) {
418: Scatter(X,user->subq,user->yi_scatter[i],0,0);
419: Scatter(Y,user->subd,user->di_scatter[i],0,0);
420: MatMult(user->Q,user->subq,user->subd);
421: Gather(X,user->subq,user->yi_scatter[i],0,0);
422: Gather(Y,user->subd,user->di_scatter[i],0,0);
423: }
424: }
425: return(0);
426: }
430: PetscErrorCode QMatMultTranspose(Mat J_shell, Vec X, Vec Y)
431: {
433: AppCtx *user;
434: PetscInt i;
437: MatShellGetContext(J_shell,(void**)&user);
438: if (user->ns == 1) {
439: MatMultTranspose(user->Q,X,Y);
440: } else {
441: for (i=0;i<user->ns;i++) {
442: Scatter(X,user->subd,user->di_scatter[i],0,0);
443: Scatter(Y,user->suby,user->yi_scatter[i],0,0);
444: MatMultTranspose(user->Q,user->subd,user->suby);
445: Gather(X,user->subd,user->di_scatter[i],0,0);
446: Gather(Y,user->suby,user->yi_scatter[i],0,0);
447: }
448: }
449: return(0);
450: }
454: PetscErrorCode DesignMatMult(Mat J_shell, Vec X, Vec Y)
455: {
457: PetscInt i;
458: AppCtx *user;
461: MatShellGetContext(J_shell,(void**)&user);
463: /* sdiag(1./v) */
464: VecSet(user->uwork,0);
465: VecAXPY(user->uwork,-1.0,user->u);
466: VecExp(user->uwork);
468: /* sdiag(1./((Av*(1./v)).^2)) */
469: MatMult(user->Av,user->uwork,user->Swork);
470: VecPointwiseMult(user->Swork,user->Swork,user->Swork);
471: VecReciprocal(user->Swork);
473: /* (Av * (sdiag(1./v) * b)) */
474: VecPointwiseMult(user->uwork,user->uwork,X);
475: MatMult(user->Av,user->uwork,user->Twork);
477: /* (sdiag(1./((Av*(1./v)).^2)) * (Av * (sdiag(1./v) * b))) */
478: VecPointwiseMult(user->Swork,user->Twork,user->Swork);
480: if (user->ns == 1) {
481: /* (sdiag(Grad*y(:,i)) */
482: MatMult(user->Grad,user->y,user->Twork);
484: /* Div * (sdiag(Grad*y(:,i)) * (sdiag(1./((Av*(1./v)).^2)) * (Av * (sdiag(1./v) * b)))) */
485: VecPointwiseMult(user->Swork,user->Twork,user->Swork);
486: MatMultTranspose(user->Grad,user->Swork,Y);
487: } else {
488: for (i=0;i<user->ns;i++) {
489: Scatter(user->y,user->suby,user->yi_scatter[i],0,0);
490: Scatter(Y,user->subq,user->yi_scatter[i],0,0);
492: MatMult(user->Grad,user->suby,user->Twork);
493: VecPointwiseMult(user->Twork,user->Twork,user->Swork);
494: MatMultTranspose(user->Grad,user->Twork,user->subq);
495: Gather(user->y,user->suby,user->yi_scatter[i],0,0);
496: Gather(Y,user->subq,user->yi_scatter[i],0,0);
497: }
498: }
499: return(0);
500: }
504: PetscErrorCode DesignMatMultTranspose(Mat J_shell, Vec X, Vec Y)
505: {
507: PetscInt i;
508: AppCtx *user;
511: MatShellGetContext(J_shell,(void**)&user);
512: VecZeroEntries(Y);
514: /* Sdiag = 1./((Av*(1./v)).^2) */
515: VecSet(user->uwork,0);
516: VecAXPY(user->uwork,-1.0,user->u);
517: VecExp(user->uwork);
518: MatMult(user->Av,user->uwork,user->Swork);
519: VecPointwiseMult(user->Sdiag,user->Swork,user->Swork);
520: VecReciprocal(user->Sdiag);
522: for (i=0;i<user->ns;i++) {
523: Scatter(X,user->subq,user->yi_scatter[i],0,0);
524: Scatter(user->y,user->suby,user->yi_scatter[i],0,0);
526: /* Swork = (Div' * b(:,i)) */
527: MatMult(user->Grad,user->subq,user->Swork);
529: /* Twork = Grad*y(:,i) */
530: MatMult(user->Grad,user->suby,user->Twork);
532: /* Twork = sdiag(Twork) * Swork */
533: VecPointwiseMult(user->Twork,user->Swork,user->Twork);
536: /* Swork = pointwisemult(Sdiag,Twork) */
537: VecPointwiseMult(user->Swork,user->Twork,user->Sdiag);
539: /* Ywork = Av' * Swork */
540: MatMultTranspose(user->Av,user->Swork,user->Ywork);
542: /* Ywork = pointwisemult(uwork,Ywork) */
543: VecPointwiseMult(user->Ywork,user->uwork,user->Ywork);
544: VecAXPY(Y,1.0,user->Ywork);
545: Gather(X,user->subq,user->yi_scatter[i],0,0);
546: Gather(user->y,user->suby,user->yi_scatter[i],0,0);
547: }
548: return(0);
549: }
553: PetscErrorCode FormConstraints(Tao tao, Vec X, Vec C, void *ptr)
554: {
555: /* C=Ay - q A = Div * Sigma * Grad + hx*hx*hx*ones(n,n) */
557: PetscReal sum;
558: PetscInt i;
559: AppCtx *user = (AppCtx*)ptr;
562: Scatter(X,user->y,user->state_scatter,user->u,user->design_scatter);
563: if (user->ns == 1) {
564: MatMult(user->Grad,user->y,user->Swork);
565: VecPointwiseDivide(user->Swork,user->Swork,user->Av_u);
566: MatMultTranspose(user->Grad,user->Swork,C);
567: VecSum(user->y,&sum);
568: sum /= user->ndesign;
569: VecShift(C,sum);
570: } else {
571: for (i=0;i<user->ns;i++) {
572: Scatter(user->y,user->suby,user->yi_scatter[i],0,0);
573: Scatter(C,user->subq,user->yi_scatter[i],0,0);
574: MatMult(user->Grad,user->suby,user->Swork);
575: VecPointwiseDivide(user->Swork,user->Swork,user->Av_u);
576: MatMultTranspose(user->Grad,user->Swork,user->subq);
578: VecSum(user->suby,&sum);
579: sum /= user->ndesign;
580: VecShift(user->subq,sum);
582: Gather(user->y,user->suby,user->yi_scatter[i],0,0);
583: Gather(C,user->subq,user->yi_scatter[i],0,0);
584: }
585: }
586: VecAXPY(C,-1.0,user->q);
587: return(0);
588: }
592: PetscErrorCode Scatter(Vec x, Vec sub1, VecScatter scat1, Vec sub2, VecScatter scat2)
593: {
597: VecScatterBegin(scat1,x,sub1,INSERT_VALUES,SCATTER_FORWARD);
598: VecScatterEnd(scat1,x,sub1,INSERT_VALUES,SCATTER_FORWARD);
599: if (sub2) {
600: VecScatterBegin(scat2,x,sub2,INSERT_VALUES,SCATTER_FORWARD);
601: VecScatterEnd(scat2,x,sub2,INSERT_VALUES,SCATTER_FORWARD);
602: }
603: return(0);
604: }
608: PetscErrorCode Gather(Vec x, Vec sub1, VecScatter scat1, Vec sub2, VecScatter scat2)
609: {
613: VecScatterBegin(scat1,sub1,x,INSERT_VALUES,SCATTER_REVERSE);
614: VecScatterEnd(scat1,sub1,x,INSERT_VALUES,SCATTER_REVERSE);
615: if (sub2) {
616: VecScatterBegin(scat2,sub2,x,INSERT_VALUES,SCATTER_REVERSE);
617: VecScatterEnd(scat2,sub2,x,INSERT_VALUES,SCATTER_REVERSE);
618: }
619: return(0);
620: }
624: PetscErrorCode EllipticInitialize(AppCtx *user)
625: {
627: PetscInt m,n,i,j,k,l,linear_index,is,js,ks,ls,istart,iend,iblock;
628: Vec XX,YY,ZZ,XXwork,YYwork,ZZwork,UTwork;
629: PetscReal *x,*y,*z;
630: PetscReal h,meanut;
631: PetscScalar hinv,neg_hinv,half = 0.5,sqrt_beta;
632: PetscInt im,indx1,indx2,indy1,indy2,indz1,indz2,nx,ny,nz;
633: IS is_alldesign,is_allstate;
634: IS is_from_d;
635: IS is_from_y;
636: PetscInt lo,hi,hi2,lo2,ysubnlocal,dsubnlocal;
637: const PetscInt *ranges, *subranges;
638: PetscMPIInt size;
639: PetscReal xri,yri,zri,xim,yim,zim,dx1,dx2,dy1,dy2,dz1,dz2,Dx,Dy,Dz;
640: PetscScalar v,vx,vy,vz;
641: PetscInt offset,subindex,subvec,nrank,kk;
643: PetscScalar xr[64] = {0.4970, 0.8498, 0.7814, 0.6268, 0.7782, 0.6402, 0.3617, 0.3160,
644: 0.3610, 0.5298, 0.6987, 0.3331, 0.7962, 0.5596, 0.3866, 0.6774,
645: 0.5407, 0.4518, 0.6702, 0.6061, 0.7580, 0.8997, 0.5198, 0.8326,
646: 0.2138, 0.9198, 0.3000, 0.2833, 0.8288, 0.7076, 0.1820, 0.0728,
647: 0.8447, 0.2367, 0.3239, 0.6413, 0.3114, 0.4731, 0.1192, 0.9273,
648: 0.5724, 0.4331, 0.5136, 0.3547, 0.4413, 0.2602, 0.5698, 0.7278,
649: 0.5261, 0.6230, 0.2454, 0.3948, 0.7479, 0.6582, 0.4660, 0.5594,
650: 0.7574, 0.1143, 0.5900, 0.1065, 0.4260, 0.3294, 0.8276, 0.0756};
652: PetscScalar yr[64] = {0.7345, 0.9120, 0.9288, 0.7528, 0.4463, 0.4985, 0.2497, 0.6256,
653: 0.3425, 0.9026, 0.6983, 0.4230, 0.7140, 0.2970, 0.4474, 0.8792,
654: 0.6604, 0.2485, 0.7968, 0.6127, 0.1796, 0.2437, 0.5938, 0.6137,
655: 0.3867, 0.5658, 0.4575, 0.1009, 0.0863, 0.3361, 0.0738, 0.3985,
656: 0.6602, 0.1437, 0.0934, 0.5983, 0.5950, 0.0763, 0.0768, 0.2288,
657: 0.5761, 0.1129, 0.3841, 0.6150, 0.6904, 0.6686, 0.1361, 0.4601,
658: 0.4491, 0.3716, 0.1969, 0.6537, 0.6743, 0.6991, 0.4811, 0.5480,
659: 0.1684, 0.4569, 0.6889, 0.8437, 0.3015, 0.2854, 0.8199, 0.2658};
661: PetscScalar zr[64] = {0.7668, 0.8573, 0.2654, 0.2719, 0.1060, 0.1311, 0.6232, 0.2295,
662: 0.8009, 0.2147, 0.2119, 0.9325, 0.4473, 0.3600, 0.3374, 0.3819,
663: 0.4066, 0.5801, 0.1673, 0.0959, 0.4638, 0.8236, 0.8800, 0.2939,
664: 0.2028, 0.8262, 0.2706, 0.6276, 0.9085, 0.6443, 0.8241, 0.0712,
665: 0.1824, 0.7789, 0.4389, 0.8415, 0.7055, 0.6639, 0.3653, 0.2078,
666: 0.1987, 0.2297, 0.4321, 0.8115, 0.4915, 0.7764, 0.4657, 0.4627,
667: 0.4569, 0.4232, 0.8514, 0.0674, 0.3227, 0.1055, 0.6690, 0.6313,
668: 0.9226, 0.5461, 0.4126, 0.2364, 0.6096, 0.7042, 0.3914, 0.0711};
671: MPI_Comm_size(PETSC_COMM_WORLD,&size);
672: PetscLogStageRegister("Elliptic Setup",&user->stages[0]);
673: PetscLogStagePush(user->stages[0]);
675: /* Create u,y,c,x */
676: VecCreate(PETSC_COMM_WORLD,&user->u);
677: VecCreate(PETSC_COMM_WORLD,&user->y);
678: VecCreate(PETSC_COMM_WORLD,&user->c);
679: VecSetSizes(user->u,PETSC_DECIDE,user->ndesign);
680: VecSetFromOptions(user->u);
681: VecGetLocalSize(user->u,&ysubnlocal);
682: VecSetSizes(user->y,ysubnlocal*user->ns,user->nstate);
683: VecSetSizes(user->c,ysubnlocal*user->ns,user->m);
684: VecSetFromOptions(user->y);
685: VecSetFromOptions(user->c);
687: /*
688: *******************************
689: Create scatters for x <-> y,u
690: *******************************
692: If the state vector y and design vector u are partitioned as
693: [y_1; y_2; ...; y_np] and [u_1; u_2; ...; u_np] (with np = # of processors),
694: then the solution vector x is organized as
695: [y_1; u_1; y_2; u_2; ...; y_np; u_np].
696: The index sets user->s_is and user->d_is correspond to the indices of the
697: state and design variables owned by the current processor.
698: */
699: VecCreate(PETSC_COMM_WORLD,&user->x);
701: VecGetOwnershipRange(user->y,&lo,&hi);
702: VecGetOwnershipRange(user->u,&lo2,&hi2);
704: ISCreateStride(PETSC_COMM_SELF,hi-lo,lo,1,&is_allstate);
705: ISCreateStride(PETSC_COMM_SELF,hi-lo,lo+lo2,1,&user->s_is);
706: ISCreateStride(PETSC_COMM_SELF,hi2-lo2,lo2,1,&is_alldesign);
707: ISCreateStride(PETSC_COMM_SELF,hi2-lo2,hi+lo2,1,&user->d_is);
709: VecSetSizes(user->x,hi-lo+hi2-lo2,user->n);
710: VecSetFromOptions(user->x);
712: VecScatterCreate(user->x,user->s_is,user->y,is_allstate,&user->state_scatter);
713: VecScatterCreate(user->x,user->d_is,user->u,is_alldesign,&user->design_scatter);
714: ISDestroy(&is_alldesign);
715: ISDestroy(&is_allstate);
716: /*
717: *******************************
718: Create scatter from y to y_1,y_2,...,y_ns
719: *******************************
720: */
721: PetscMalloc1(user->ns,&user->yi_scatter);
722: VecDuplicate(user->u,&user->suby);
723: VecDuplicate(user->u,&user->subq);
725: VecGetOwnershipRange(user->y,&lo2,&hi2);
726: istart = 0;
727: for (i=0; i<user->ns; i++){
728: VecGetOwnershipRange(user->suby,&lo,&hi);
729: ISCreateStride(PETSC_COMM_SELF,hi-lo,lo2+istart,1,&is_from_y);
730: VecScatterCreate(user->y,is_from_y,user->suby,NULL,&user->yi_scatter[i]);
731: istart = istart + hi-lo;
732: ISDestroy(&is_from_y);
733: }
734: /*
735: *******************************
736: Create scatter from d to d_1,d_2,...,d_ns
737: *******************************
738: */
739: VecCreate(PETSC_COMM_WORLD,&user->subd);
740: VecSetSizes(user->subd,PETSC_DECIDE,user->ndata);
741: VecSetFromOptions(user->subd);
742: VecCreate(PETSC_COMM_WORLD,&user->d);
743: VecGetLocalSize(user->subd,&dsubnlocal);
744: VecSetSizes(user->d,dsubnlocal*user->ns,user->ndata*user->ns);
745: VecSetFromOptions(user->d);
746: PetscMalloc1(user->ns,&user->di_scatter);
748: VecGetOwnershipRange(user->d,&lo2,&hi2);
749: istart = 0;
750: for (i=0; i<user->ns; i++){
751: VecGetOwnershipRange(user->subd,&lo,&hi);
752: ISCreateStride(PETSC_COMM_SELF,hi-lo,lo2+istart,1,&is_from_d);
753: VecScatterCreate(user->d,is_from_d,user->subd,NULL,&user->di_scatter[i]);
754: istart = istart + hi-lo;
755: ISDestroy(&is_from_d);
756: }
758: PetscMalloc1(user->mx,&x);
759: PetscMalloc1(user->mx,&y);
760: PetscMalloc1(user->mx,&z);
762: user->ksp_its = 0;
763: user->ksp_its_initial = 0;
765: n = user->mx * user->mx * user->mx;
766: m = 3 * user->mx * user->mx * (user->mx-1);
767: sqrt_beta = PetscSqrtScalar(user->beta);
769: VecCreate(PETSC_COMM_WORLD,&XX);
770: VecCreate(PETSC_COMM_WORLD,&user->q);
771: VecSetSizes(XX,ysubnlocal,n);
772: VecSetSizes(user->q,ysubnlocal*user->ns,user->m);
773: VecSetFromOptions(XX);
774: VecSetFromOptions(user->q);
776: VecDuplicate(XX,&YY);
777: VecDuplicate(XX,&ZZ);
778: VecDuplicate(XX,&XXwork);
779: VecDuplicate(XX,&YYwork);
780: VecDuplicate(XX,&ZZwork);
781: VecDuplicate(XX,&UTwork);
782: VecDuplicate(XX,&user->utrue);
784: /* map for striding q */
785: /*
786: PetscMalloc1((size+1),&ranges);
787: PetscMalloc1((size+1),&subranges); */
788: VecGetOwnershipRanges(user->q,&ranges);
789: VecGetOwnershipRanges(user->u,&subranges);
791: VecGetOwnershipRange(user->q,&lo2,&hi2);
792: VecGetOwnershipRange(user->u,&lo,&hi);
793: /* Generate 3D grid, and collect ns (1<=ns<=8) right-hand-side vectors into user->q */
794: h = 1.0/user->mx;
795: hinv = user->mx;
796: neg_hinv = -hinv;
798: VecGetOwnershipRange(XX,&istart,&iend);
799: for (linear_index=istart; linear_index<iend; linear_index++){
800: i = linear_index % user->mx;
801: j = ((linear_index-i)/user->mx) % user->mx;
802: k = ((linear_index-i)/user->mx-j) / user->mx;
803: vx = h*(i+0.5);
804: vy = h*(j+0.5);
805: vz = h*(k+0.5);
806: VecSetValues(XX,1,&linear_index,&vx,INSERT_VALUES);
807: VecSetValues(YY,1,&linear_index,&vy,INSERT_VALUES);
808: VecSetValues(ZZ,1,&linear_index,&vz,INSERT_VALUES);
809: for (is=0; is<2; is++){
810: for (js=0; js<2; js++){
811: for (ks=0; ks<2; ks++){
812: ls = is*4 + js*2 + ks;
813: if (ls<user->ns){
814: l =ls*n + linear_index;
815: /* remap */
816: subindex = l%n;
817: subvec = l/n;
818: nrank=0;
819: while (subindex >= subranges[nrank+1]) nrank++;
820: offset = subindex - subranges[nrank];
821: istart=0;
822: for (kk=0;kk<nrank;kk++) istart+=user->ns*(subranges[kk+1]-subranges[kk]);
823: istart += (subranges[nrank+1]-subranges[nrank])*subvec;
824: l = istart+offset;
825: v = 100*PetscSinScalar(2*PETSC_PI*(vx+0.25*is))*sin(2*PETSC_PI*(vy+0.25*js))*sin(2*PETSC_PI*(vz+0.25*ks));
826: VecSetValues(user->q,1,&l,&v,INSERT_VALUES);
827: }
828: }
829: }
830: }
831: }
833: VecAssemblyBegin(XX);
834: VecAssemblyEnd(XX);
835: VecAssemblyBegin(YY);
836: VecAssemblyEnd(YY);
837: VecAssemblyBegin(ZZ);
838: VecAssemblyEnd(ZZ);
839: VecAssemblyBegin(user->q);
840: VecAssemblyEnd(user->q);
842: /* Compute true parameter function
843: ut = exp(-((x-0.25)^2+(y-0.25)^2+(z-0.25)^2)/0.05) - exp((x-0.75)^2-(y-0.75)^2-(z-0.75))^2/0.05) */
844: VecCopy(XX,XXwork);
845: VecCopy(YY,YYwork);
846: VecCopy(ZZ,ZZwork);
848: VecShift(XXwork,-0.25);
849: VecShift(YYwork,-0.25);
850: VecShift(ZZwork,-0.25);
852: VecPointwiseMult(XXwork,XXwork,XXwork);
853: VecPointwiseMult(YYwork,YYwork,YYwork);
854: VecPointwiseMult(ZZwork,ZZwork,ZZwork);
856: VecCopy(XXwork,UTwork);
857: VecAXPY(UTwork,1.0,YYwork);
858: VecAXPY(UTwork,1.0,ZZwork);
859: VecScale(UTwork,-20.0);
860: VecExp(UTwork);
861: VecCopy(UTwork,user->utrue);
863: VecCopy(XX,XXwork);
864: VecCopy(YY,YYwork);
865: VecCopy(ZZ,ZZwork);
867: VecShift(XXwork,-0.75);
868: VecShift(YYwork,-0.75);
869: VecShift(ZZwork,-0.75);
871: VecPointwiseMult(XXwork,XXwork,XXwork);
872: VecPointwiseMult(YYwork,YYwork,YYwork);
873: VecPointwiseMult(ZZwork,ZZwork,ZZwork);
875: VecCopy(XXwork,UTwork);
876: VecAXPY(UTwork,1.0,YYwork);
877: VecAXPY(UTwork,1.0,ZZwork);
878: VecScale(UTwork,-20.0);
879: VecExp(UTwork);
881: VecAXPY(user->utrue,-1.0,UTwork);
883: VecDestroy(&XX);
884: VecDestroy(&YY);
885: VecDestroy(&ZZ);
886: VecDestroy(&XXwork);
887: VecDestroy(&YYwork);
888: VecDestroy(&ZZwork);
889: VecDestroy(&UTwork);
891: /* Initial guess and reference model */
892: VecDuplicate(user->utrue,&user->ur);
893: VecSum(user->utrue,&meanut);
894: meanut = meanut / n;
895: VecSet(user->ur,meanut);
896: VecCopy(user->ur,user->u);
898: /* Generate Grad matrix */
899: MatCreate(PETSC_COMM_WORLD,&user->Grad);
900: MatSetSizes(user->Grad,PETSC_DECIDE,ysubnlocal,m,n);
901: MatSetFromOptions(user->Grad);
902: MatMPIAIJSetPreallocation(user->Grad,2,NULL,2,NULL);
903: MatSeqAIJSetPreallocation(user->Grad,2,NULL);
904: MatGetOwnershipRange(user->Grad,&istart,&iend);
906: for (i=istart; i<iend; i++){
907: if (i<m/3){
908: iblock = i / (user->mx-1);
909: j = iblock*user->mx + (i % (user->mx-1));
910: MatSetValues(user->Grad,1,&i,1,&j,&neg_hinv,INSERT_VALUES);
911: j = j+1;
912: MatSetValues(user->Grad,1,&i,1,&j,&hinv,INSERT_VALUES);
913: }
914: if (i>=m/3 && i<2*m/3){
915: iblock = (i-m/3) / (user->mx*(user->mx-1));
916: j = iblock*user->mx*user->mx + ((i-m/3) % (user->mx*(user->mx-1)));
917: MatSetValues(user->Grad,1,&i,1,&j,&neg_hinv,INSERT_VALUES);
918: j = j + user->mx;
919: MatSetValues(user->Grad,1,&i,1,&j,&hinv,INSERT_VALUES);
920: }
921: if (i>=2*m/3){
922: j = i-2*m/3;
923: MatSetValues(user->Grad,1,&i,1,&j,&neg_hinv,INSERT_VALUES);
924: j = j + user->mx*user->mx;
925: MatSetValues(user->Grad,1,&i,1,&j,&hinv,INSERT_VALUES);
926: }
927: }
929: MatAssemblyBegin(user->Grad,MAT_FINAL_ASSEMBLY);
930: MatAssemblyEnd(user->Grad,MAT_FINAL_ASSEMBLY);
932: /* Generate arithmetic averaging matrix Av */
933: MatCreate(PETSC_COMM_WORLD,&user->Av);
934: MatSetSizes(user->Av,PETSC_DECIDE,ysubnlocal,m,n);
935: MatSetFromOptions(user->Av);
936: MatMPIAIJSetPreallocation(user->Av,2,NULL,2,NULL);
937: MatSeqAIJSetPreallocation(user->Av,2,NULL);
938: MatGetOwnershipRange(user->Av,&istart,&iend);
940: for (i=istart; i<iend; i++){
941: if (i<m/3){
942: iblock = i / (user->mx-1);
943: j = iblock*user->mx + (i % (user->mx-1));
944: MatSetValues(user->Av,1,&i,1,&j,&half,INSERT_VALUES);
945: j = j+1;
946: MatSetValues(user->Av,1,&i,1,&j,&half,INSERT_VALUES);
947: }
948: if (i>=m/3 && i<2*m/3){
949: iblock = (i-m/3) / (user->mx*(user->mx-1));
950: j = iblock*user->mx*user->mx + ((i-m/3) % (user->mx*(user->mx-1)));
951: MatSetValues(user->Av,1,&i,1,&j,&half,INSERT_VALUES);
952: j = j + user->mx;
953: MatSetValues(user->Av,1,&i,1,&j,&half,INSERT_VALUES);
954: }
955: if (i>=2*m/3){
956: j = i-2*m/3;
957: MatSetValues(user->Av,1,&i,1,&j,&half,INSERT_VALUES);
958: j = j + user->mx*user->mx;
959: MatSetValues(user->Av,1,&i,1,&j,&half,INSERT_VALUES);
960: }
961: }
963: MatAssemblyBegin(user->Av,MAT_FINAL_ASSEMBLY);
964: MatAssemblyEnd(user->Av,MAT_FINAL_ASSEMBLY);
966: MatCreate(PETSC_COMM_WORLD,&user->L);
967: MatSetSizes(user->L,PETSC_DECIDE,ysubnlocal,m+n,n);
968: MatSetFromOptions(user->L);
969: MatMPIAIJSetPreallocation(user->L,2,NULL,2,NULL);
970: MatSeqAIJSetPreallocation(user->L,2,NULL);
971: MatGetOwnershipRange(user->L,&istart,&iend);
973: for (i=istart; i<iend; i++){
974: if (i<m/3){
975: iblock = i / (user->mx-1);
976: j = iblock*user->mx + (i % (user->mx-1));
977: MatSetValues(user->L,1,&i,1,&j,&neg_hinv,INSERT_VALUES);
978: j = j+1;
979: MatSetValues(user->L,1,&i,1,&j,&hinv,INSERT_VALUES);
980: }
981: if (i>=m/3 && i<2*m/3){
982: iblock = (i-m/3) / (user->mx*(user->mx-1));
983: j = iblock*user->mx*user->mx + ((i-m/3) % (user->mx*(user->mx-1)));
984: MatSetValues(user->L,1,&i,1,&j,&neg_hinv,INSERT_VALUES);
985: j = j + user->mx;
986: MatSetValues(user->L,1,&i,1,&j,&hinv,INSERT_VALUES);
987: }
988: if (i>=2*m/3 && i<m){
989: j = i-2*m/3;
990: MatSetValues(user->L,1,&i,1,&j,&neg_hinv,INSERT_VALUES);
991: j = j + user->mx*user->mx;
992: MatSetValues(user->L,1,&i,1,&j,&hinv,INSERT_VALUES);
993: }
994: if (i>=m){
995: j = i - m;
996: MatSetValues(user->L,1,&i,1,&j,&sqrt_beta,INSERT_VALUES);
997: }
998: }
999: MatAssemblyBegin(user->L,MAT_FINAL_ASSEMBLY);
1000: MatAssemblyEnd(user->L,MAT_FINAL_ASSEMBLY);
1001: MatScale(user->L,PetscPowScalar(h,1.5));
1003: /* Generate Div matrix */
1004: if (!user->use_ptap) {
1005: /* Generate Div matrix */
1006: MatCreate(PETSC_COMM_WORLD,&user->Div);
1007: MatSetSizes(user->Div,ysubnlocal,PETSC_DECIDE,n,m);
1008: MatSetFromOptions(user->Div);
1009: MatMPIAIJSetPreallocation(user->Div,4,NULL,4,NULL);
1010: MatSeqAIJSetPreallocation(user->Div,6,NULL);
1011: MatGetOwnershipRange(user->Grad,&istart,&iend);
1013: for (i=istart; i<iend; i++){
1014: if (i<m/3){
1015: iblock = i / (user->mx-1);
1016: j = iblock*user->mx + (i % (user->mx-1));
1017: MatSetValues(user->Div,1,&j,1,&i,&neg_hinv,INSERT_VALUES);
1018: j = j+1;
1019: MatSetValues(user->Div,1,&j,1,&i,&hinv,INSERT_VALUES);
1020: }
1021: if (i>=m/3 && i<2*m/3){
1022: iblock = (i-m/3) / (user->mx*(user->mx-1));
1023: j = iblock*user->mx*user->mx + ((i-m/3) % (user->mx*(user->mx-1)));
1024: MatSetValues(user->Div,1,&j,1,&i,&neg_hinv,INSERT_VALUES);
1025: j = j + user->mx;
1026: MatSetValues(user->Div,1,&j,1,&i,&hinv,INSERT_VALUES);
1027: }
1028: if (i>=2*m/3){
1029: j = i-2*m/3;
1030: MatSetValues(user->Div,1,&j,1,&i,&neg_hinv,INSERT_VALUES);
1031: j = j + user->mx*user->mx;
1032: MatSetValues(user->Div,1,&j,1,&i,&hinv,INSERT_VALUES);
1033: }
1034: }
1036: MatAssemblyBegin(user->Div,MAT_FINAL_ASSEMBLY);
1037: MatAssemblyEnd(user->Div,MAT_FINAL_ASSEMBLY);
1038: MatDuplicate(user->Div,MAT_SHARE_NONZERO_PATTERN,&user->Divwork);
1039: } else {
1040: MatCreate(PETSC_COMM_WORLD,&user->Diag);
1041: MatSetSizes(user->Diag,PETSC_DECIDE,PETSC_DECIDE,m,m);
1042: MatSetFromOptions(user->Diag);
1043: MatMPIAIJSetPreallocation(user->Diag,1,NULL,0,NULL);
1044: MatSeqAIJSetPreallocation(user->Diag,1,NULL);
1045: }
1047: /* Build work vectors and matrices */
1048: VecCreate(PETSC_COMM_WORLD,&user->S);
1049: VecSetSizes(user->S, PETSC_DECIDE, m);
1050: VecSetFromOptions(user->S);
1052: VecCreate(PETSC_COMM_WORLD,&user->lwork);
1053: VecSetSizes(user->lwork,PETSC_DECIDE,m+user->mx*user->mx*user->mx);
1054: VecSetFromOptions(user->lwork);
1056: MatDuplicate(user->Av,MAT_SHARE_NONZERO_PATTERN,&user->Avwork);
1058: VecDuplicate(user->S,&user->Swork);
1059: VecDuplicate(user->S,&user->Sdiag);
1060: VecDuplicate(user->S,&user->Av_u);
1061: VecDuplicate(user->S,&user->Twork);
1062: VecDuplicate(user->y,&user->ywork);
1063: VecDuplicate(user->u,&user->Ywork);
1064: VecDuplicate(user->u,&user->uwork);
1065: VecDuplicate(user->u,&user->js_diag);
1066: VecDuplicate(user->c,&user->cwork);
1067: VecDuplicate(user->d,&user->dwork);
1069: /* Create a matrix-free shell user->Jd for computing B*x */
1070: MatCreateShell(PETSC_COMM_WORLD,ysubnlocal*user->ns,ysubnlocal,user->nstate,user->ndesign,user,&user->Jd);
1071: MatShellSetOperation(user->Jd,MATOP_MULT,(void(*)(void))DesignMatMult);
1072: MatShellSetOperation(user->Jd,MATOP_MULT_TRANSPOSE,(void(*)(void))DesignMatMultTranspose);
1074: /* Compute true state function ytrue given utrue */
1075: VecDuplicate(user->y,&user->ytrue);
1077: /* First compute Av_u = Av*exp(-u) */
1078: VecSet(user->uwork, 0);
1079: VecAXPY(user->uwork,-1.0,user->utrue); /* Note: user->utrue */
1080: VecExp(user->uwork);
1081: MatMult(user->Av,user->uwork,user->Av_u);
1083: /* Next form DSG = Div*S*Grad */
1084: VecCopy(user->Av_u,user->Swork);
1085: VecReciprocal(user->Swork);
1086: if (user->use_ptap) {
1087: MatDiagonalSet(user->Diag,user->Swork,INSERT_VALUES);
1088: MatPtAP(user->Diag,user->Grad,MAT_INITIAL_MATRIX,1.0,&user->DSG);
1089: } else {
1090: MatCopy(user->Div,user->Divwork,SAME_NONZERO_PATTERN);
1091: MatDiagonalScale(user->Divwork,NULL,user->Swork);
1092: MatMatMultSymbolic(user->Divwork,user->Grad,1.0,&user->DSG);
1093: MatMatMultNumeric(user->Divwork,user->Grad,user->DSG);
1094: }
1096: MatSetOption(user->DSG,MAT_SYMMETRIC,PETSC_TRUE);
1097: MatSetOption(user->DSG,MAT_SYMMETRY_ETERNAL,PETSC_TRUE);
1099: if (user->use_lrc == PETSC_TRUE) {
1100: v=PetscSqrtReal(1.0 /user->ndesign);
1101: PetscMalloc1(user->ndesign,&user->ones);
1103: for (i=0;i<user->ndesign;i++) {
1104: user->ones[i]=v;
1105: }
1106: MatCreateDense(PETSC_COMM_WORLD,ysubnlocal,PETSC_DECIDE,user->ndesign,1,user->ones,&user->Ones);
1107: MatAssemblyBegin(user->Ones, MAT_FINAL_ASSEMBLY);
1108: MatAssemblyEnd(user->Ones, MAT_FINAL_ASSEMBLY);
1109: MatCreateLRC(user->DSG,user->Ones,user->Ones,&user->JsBlock);
1110: MatSetUp(user->JsBlock);
1111: } else {
1112: /* Create matrix-free shell user->Js for computing (A + h^3*e*e^T)*x */
1113: MatCreateShell(PETSC_COMM_WORLD,ysubnlocal,ysubnlocal,user->ndesign,user->ndesign,user,&user->JsBlock);
1114: MatShellSetOperation(user->JsBlock,MATOP_MULT,(void(*)(void))StateBlockMatMult);
1115: MatShellSetOperation(user->JsBlock,MATOP_MULT_TRANSPOSE,(void(*)(void))StateBlockMatMult);
1116: }
1117: MatSetOption(user->JsBlock,MAT_SYMMETRIC,PETSC_TRUE);
1118: MatSetOption(user->JsBlock,MAT_SYMMETRY_ETERNAL,PETSC_TRUE);
1119: MatCreateShell(PETSC_COMM_WORLD,ysubnlocal*user->ns,ysubnlocal*user->ns,user->nstate,user->nstate,user,&user->Js);
1120: MatShellSetOperation(user->Js,MATOP_MULT,(void(*)(void))StateMatMult);
1121: MatShellSetOperation(user->Js,MATOP_MULT_TRANSPOSE,(void(*)(void))StateMatMult);
1122: MatSetOption(user->Js,MAT_SYMMETRIC,PETSC_TRUE);
1123: MatSetOption(user->Js,MAT_SYMMETRY_ETERNAL,PETSC_TRUE);
1125: MatCreateShell(PETSC_COMM_WORLD,ysubnlocal*user->ns,ysubnlocal*user->ns,user->nstate,user->nstate,user,&user->JsInv);
1126: MatShellSetOperation(user->JsInv,MATOP_MULT,(void(*)(void))StateInvMatMult);
1127: MatShellSetOperation(user->JsInv,MATOP_MULT_TRANSPOSE,(void(*)(void))StateInvMatMult);
1128: MatSetOption(user->JsInv,MAT_SYMMETRIC,PETSC_TRUE);
1129: MatSetOption(user->JsInv,MAT_SYMMETRY_ETERNAL,PETSC_TRUE);
1131: MatSetOption(user->DSG,MAT_SYMMETRIC,PETSC_TRUE);
1132: MatSetOption(user->DSG,MAT_SYMMETRY_ETERNAL,PETSC_TRUE);
1133: /* Now solve for ytrue */
1134: KSPCreate(PETSC_COMM_WORLD,&user->solver);
1135: KSPSetFromOptions(user->solver);
1137: KSPSetOperators(user->solver,user->JsBlock,user->DSG,SAME_NONZERO_PATTERN);
1138: user->lcl->solve_type = LCL_FORWARD1;
1139: MatMult(user->JsInv,user->q,user->ytrue);
1140: /* First compute Av_u = Av*exp(-u) */
1141: VecSet(user->uwork,0);
1142: VecAXPY(user->uwork,-1.0,user->u); /* Note: user->u */
1143: VecExp(user->uwork);
1144: MatMult(user->Av,user->uwork,user->Av_u);
1146: /* Next update DSG = Div*S*Grad with user->u */
1147: VecCopy(user->Av_u,user->Swork);
1148: VecReciprocal(user->Swork);
1149: if (user->use_ptap) {
1150: MatDiagonalSet(user->Diag,user->Swork,INSERT_VALUES);
1151: MatPtAP(user->Diag,user->Grad,MAT_REUSE_MATRIX,1.0,&user->DSG);
1152: } else {
1153: MatCopy(user->Div,user->Divwork,SAME_NONZERO_PATTERN);
1154: MatDiagonalScale(user->Divwork,NULL,user->Av_u);
1155: MatMatMultNumeric(user->Divwork,user->Grad,user->DSG);
1156: }
1158: /* Now solve for y */
1159: user->lcl->solve_type = LCL_FORWARD1;
1160: MatMult(user->JsInv,user->q,user->y);
1162: user->ksp_its_initial = user->ksp_its;
1163: user->ksp_its = 0;
1164: /* Construct projection matrix Q (blocks) */
1165: MatCreate(PETSC_COMM_WORLD,&user->Q);
1166: MatSetSizes(user->Q,dsubnlocal,ysubnlocal,user->ndata,user->ndesign);
1167: MatSetFromOptions(user->Q);
1168: MatMPIAIJSetPreallocation(user->Q,8,NULL,8,NULL);
1169: MatSeqAIJSetPreallocation(user->Q,8,NULL);
1171: for (i=0; i<user->mx; i++){
1172: x[i] = h*(i+0.5);
1173: y[i] = h*(i+0.5);
1174: z[i] = h*(i+0.5);
1175: }
1176: MatGetOwnershipRange(user->Q,&istart,&iend);
1178: nx = user->mx; ny = user->mx; nz = user->mx;
1179: for (i=istart; i<iend; i++){
1181: xri = xr[i];
1182: im = 0;
1183: xim = x[im];
1184: while (xri>xim && im<nx){
1185: im = im+1;
1186: xim = x[im];
1187: }
1188: indx1 = im-1;
1189: indx2 = im;
1190: dx1 = xri - x[indx1];
1191: dx2 = x[indx2] - xri;
1193: yri = yr[i];
1194: im = 0;
1195: yim = y[im];
1196: while (yri>yim && im<ny){
1197: im = im+1;
1198: yim = y[im];
1199: }
1200: indy1 = im-1;
1201: indy2 = im;
1202: dy1 = yri - y[indy1];
1203: dy2 = y[indy2] - yri;
1205: zri = zr[i];
1206: im = 0;
1207: zim = z[im];
1208: while (zri>zim && im<nz){
1209: im = im+1;
1210: zim = z[im];
1211: }
1212: indz1 = im-1;
1213: indz2 = im;
1214: dz1 = zri - z[indz1];
1215: dz2 = z[indz2] - zri;
1217: Dx = x[indx2] - x[indx1];
1218: Dy = y[indy2] - y[indy1];
1219: Dz = z[indz2] - z[indz1];
1221: j = indx1 + indy1*nx + indz1*nx*ny;
1222: v = (1-dx1/Dx)*(1-dy1/Dy)*(1-dz1/Dz);
1223: MatSetValues(user->Q,1,&i,1,&j,&v,INSERT_VALUES);
1225: j = indx1 + indy1*nx + indz2*nx*ny;
1226: v = (1-dx1/Dx)*(1-dy1/Dy)*(1-dz2/Dz);
1227: MatSetValues(user->Q,1,&i,1,&j,&v,INSERT_VALUES);
1229: j = indx1 + indy2*nx + indz1*nx*ny;
1230: v = (1-dx1/Dx)*(1-dy2/Dy)*(1-dz1/Dz);
1231: MatSetValues(user->Q,1,&i,1,&j,&v,INSERT_VALUES);
1233: j = indx1 + indy2*nx + indz2*nx*ny;
1234: v = (1-dx1/Dx)*(1-dy2/Dy)*(1-dz2/Dz);
1235: MatSetValues(user->Q,1,&i,1,&j,&v,INSERT_VALUES);
1237: j = indx2 + indy1*nx + indz1*nx*ny;
1238: v = (1-dx2/Dx)*(1-dy1/Dy)*(1-dz1/Dz);
1239: MatSetValues(user->Q,1,&i,1,&j,&v,INSERT_VALUES);
1241: j = indx2 + indy1*nx + indz2*nx*ny;
1242: v = (1-dx2/Dx)*(1-dy1/Dy)*(1-dz2/Dz);
1243: MatSetValues(user->Q,1,&i,1,&j,&v,INSERT_VALUES);
1245: j = indx2 + indy2*nx + indz1*nx*ny;
1246: v = (1-dx2/Dx)*(1-dy2/Dy)*(1-dz1/Dz);
1247: MatSetValues(user->Q,1,&i,1,&j,&v,INSERT_VALUES);
1249: j = indx2 + indy2*nx + indz2*nx*ny;
1250: v = (1-dx2/Dx)*(1-dy2/Dy)*(1-dz2/Dz);
1251: MatSetValues(user->Q,1,&i,1,&j,&v,INSERT_VALUES);
1252: }
1254: MatAssemblyBegin(user->Q,MAT_FINAL_ASSEMBLY);
1255: MatAssemblyEnd(user->Q,MAT_FINAL_ASSEMBLY);
1256: /* Create MQ (composed of blocks of Q */
1257: MatCreateShell(PETSC_COMM_WORLD,dsubnlocal*user->ns,PETSC_DECIDE,user->ndata*user->ns,user->nstate,user,&user->MQ);
1258: MatShellSetOperation(user->MQ,MATOP_MULT,(void(*)(void))QMatMult);
1259: MatShellSetOperation(user->MQ,MATOP_MULT_TRANSPOSE,(void(*)(void))QMatMultTranspose);
1261: /* Add noise to the measurement data */
1262: VecSet(user->ywork,1.0);
1263: VecAYPX(user->ywork,user->noise,user->ytrue);
1264: MatMult(user->MQ,user->ywork,user->d);
1266: /* Now that initial conditions have been set, let the user pass tolerance options to the KSP solver */
1267: PetscFree(x);
1268: PetscFree(y);
1269: PetscFree(z);
1270: PetscLogStagePop();
1271: return(0);
1272: }
1276: PetscErrorCode EllipticDestroy(AppCtx *user)
1277: {
1279: PetscInt i;
1282: MatDestroy(&user->DSG);
1283: KSPDestroy(&user->solver);
1284: MatDestroy(&user->Q);
1285: MatDestroy(&user->MQ);
1286: if (!user->use_ptap) {
1287: MatDestroy(&user->Div);
1288: MatDestroy(&user->Divwork);
1289: } else {
1290: MatDestroy(&user->Diag);
1291: }
1292: if (user->use_lrc) {
1293: MatDestroy(&user->Ones);
1294: }
1296: MatDestroy(&user->Grad);
1297: MatDestroy(&user->Av);
1298: MatDestroy(&user->Avwork);
1299: MatDestroy(&user->L);
1300: MatDestroy(&user->Js);
1301: MatDestroy(&user->Jd);
1302: MatDestroy(&user->JsBlock);
1303: MatDestroy(&user->JsInv);
1305: VecDestroy(&user->x);
1306: VecDestroy(&user->u);
1307: VecDestroy(&user->uwork);
1308: VecDestroy(&user->utrue);
1309: VecDestroy(&user->y);
1310: VecDestroy(&user->ywork);
1311: VecDestroy(&user->ytrue);
1312: VecDestroy(&user->c);
1313: VecDestroy(&user->cwork);
1314: VecDestroy(&user->ur);
1315: VecDestroy(&user->q);
1316: VecDestroy(&user->d);
1317: VecDestroy(&user->dwork);
1318: VecDestroy(&user->lwork);
1319: VecDestroy(&user->S);
1320: VecDestroy(&user->Swork);
1321: VecDestroy(&user->Sdiag);
1322: VecDestroy(&user->Ywork);
1323: VecDestroy(&user->Twork);
1324: VecDestroy(&user->Av_u);
1325: VecDestroy(&user->js_diag);
1326: ISDestroy(&user->s_is);
1327: ISDestroy(&user->d_is);
1328: VecDestroy(&user->suby);
1329: VecDestroy(&user->subd);
1330: VecDestroy(&user->subq);
1331: VecScatterDestroy(&user->state_scatter);
1332: VecScatterDestroy(&user->design_scatter);
1333: for (i=0;i<user->ns;i++) {
1334: VecScatterDestroy(&user->yi_scatter[i]);
1335: VecScatterDestroy(&user->di_scatter[i]);
1336: }
1337: PetscFree(user->yi_scatter);
1338: PetscFree(user->di_scatter);
1339: if (user->use_lrc) {
1340: PetscFree(user->ones);
1341: MatDestroy(&user->Ones);
1342: }
1343: return(0);
1344: }
1348: PetscErrorCode EllipticMonitor(Tao tao, void *ptr)
1349: {
1351: Vec X;
1352: PetscReal unorm,ynorm;
1353: AppCtx *user = (AppCtx*)ptr;
1356: TaoGetSolutionVector(tao,&X);
1357: Scatter(X,user->ywork,user->state_scatter,user->uwork,user->design_scatter);
1358: VecAXPY(user->ywork,-1.0,user->ytrue);
1359: VecAXPY(user->uwork,-1.0,user->utrue);
1360: VecNorm(user->uwork,NORM_2,&unorm);
1361: VecNorm(user->ywork,NORM_2,&ynorm);
1362: PetscPrintf(MPI_COMM_WORLD, "||u-ut||=%g ||y-yt||=%g\n",(double)unorm,(double)ynorm);
1363: return(0);
1364: }