xref: /petsc/src/tao/pde_constrained/tutorials/hyperbolic.c (revision a82e8c82ed9474375a7f877f23dfa96948657643)
1c4762a1bSJed Brown #include <petsctao.h>
2c4762a1bSJed Brown 
3c4762a1bSJed Brown /*T
4c4762a1bSJed Brown    Concepts: TAO^Solving a system of nonlinear equations, nonlinear least squares
5c4762a1bSJed Brown    Routines: TaoCreate();
6c4762a1bSJed Brown    Routines: TaoSetType();
7*a82e8c82SStefano Zampini    Routines: TaoSetSolution();
8*a82e8c82SStefano Zampini    Routines: TaoSetObjective();
9*a82e8c82SStefano Zampini    Routines: TaoSetGradient();
10c4762a1bSJed Brown    Routines: TaoSetConstraintsRoutine();
11c4762a1bSJed Brown    Routines: TaoSetJacobianStateRoutine();
12c4762a1bSJed Brown    Routines: TaoSetJacobianDesignRoutine();
13c4762a1bSJed Brown    Routines: TaoSetStateDesignIS();
14c4762a1bSJed Brown    Routines: TaoSetFromOptions();
15c4762a1bSJed Brown    Routines: TaoSolve();
16c4762a1bSJed Brown    Routines: TaoDestroy();
17c4762a1bSJed Brown    Processors: 1
18c4762a1bSJed Brown T*/
19c4762a1bSJed Brown 
20c4762a1bSJed Brown typedef struct {
21c4762a1bSJed Brown   PetscInt n; /*  Number of variables */
22c4762a1bSJed Brown   PetscInt m; /*  Number of constraints */
23c4762a1bSJed Brown   PetscInt mx; /*  grid points in each direction */
24c4762a1bSJed Brown   PetscInt nt; /*  Number of time steps */
25c4762a1bSJed Brown   PetscInt ndata; /*  Number of data points per sample */
26c4762a1bSJed Brown   IS       s_is;
27c4762a1bSJed Brown   IS       d_is;
28c4762a1bSJed Brown   VecScatter state_scatter;
29c4762a1bSJed Brown   VecScatter design_scatter;
30c4762a1bSJed Brown   VecScatter *uxi_scatter,*uyi_scatter,*ux_scatter,*uy_scatter,*ui_scatter;
31c4762a1bSJed Brown   VecScatter *yi_scatter;
32c4762a1bSJed Brown 
33c4762a1bSJed Brown   Mat       Js,Jd,JsBlockPrec,JsInv,JsBlock;
34c4762a1bSJed Brown   PetscBool jformed,c_formed;
35c4762a1bSJed Brown 
36c4762a1bSJed Brown   PetscReal alpha; /*  Regularization parameter */
37c4762a1bSJed Brown   PetscReal gamma;
38c4762a1bSJed Brown   PetscReal ht; /*  Time step */
39c4762a1bSJed Brown   PetscReal T; /*  Final time */
40c4762a1bSJed Brown   Mat Q,QT;
41c4762a1bSJed Brown   Mat L,LT;
42c4762a1bSJed Brown   Mat Div,Divwork,Divxy[2];
43c4762a1bSJed Brown   Mat Grad,Gradxy[2];
44c4762a1bSJed Brown   Mat M;
45c4762a1bSJed Brown   Mat *C,*Cwork;
46c4762a1bSJed Brown   /* Mat Hs,Hd,Hsd; */
47c4762a1bSJed Brown   Vec q;
48c4762a1bSJed Brown   Vec ur; /*  reference */
49c4762a1bSJed Brown 
50c4762a1bSJed Brown   Vec d;
51c4762a1bSJed Brown   Vec dwork;
52c4762a1bSJed Brown 
53c4762a1bSJed Brown   Vec y; /*  state variables */
54c4762a1bSJed Brown   Vec ywork;
55c4762a1bSJed Brown   Vec ytrue;
56c4762a1bSJed Brown   Vec *yi,*yiwork,*ziwork;
57c4762a1bSJed Brown   Vec *uxi,*uyi,*uxiwork,*uyiwork,*ui,*uiwork;
58c4762a1bSJed Brown 
59c4762a1bSJed Brown   Vec u; /*  design variables */
60c4762a1bSJed Brown   Vec uwork,vwork;
61c4762a1bSJed Brown   Vec utrue;
62c4762a1bSJed Brown 
63c4762a1bSJed Brown   Vec js_diag;
64c4762a1bSJed Brown 
65c4762a1bSJed Brown   Vec c; /*  constraint vector */
66c4762a1bSJed Brown   Vec cwork;
67c4762a1bSJed Brown 
68c4762a1bSJed Brown   Vec lwork;
69c4762a1bSJed Brown 
70c4762a1bSJed Brown   KSP      solver;
71c4762a1bSJed Brown   PC       prec;
72c4762a1bSJed Brown   PetscInt block_index;
73c4762a1bSJed Brown 
74c4762a1bSJed Brown   PetscInt ksp_its;
75c4762a1bSJed Brown   PetscInt ksp_its_initial;
76c4762a1bSJed Brown } AppCtx;
77c4762a1bSJed Brown 
78c4762a1bSJed Brown PetscErrorCode FormFunction(Tao, Vec, PetscReal*, void*);
79c4762a1bSJed Brown PetscErrorCode FormGradient(Tao, Vec, Vec, void*);
80c4762a1bSJed Brown PetscErrorCode FormFunctionGradient(Tao, Vec, PetscReal*, Vec, void*);
81c4762a1bSJed Brown PetscErrorCode FormJacobianState(Tao, Vec, Mat, Mat, Mat, void*);
82c4762a1bSJed Brown PetscErrorCode FormJacobianDesign(Tao, Vec, Mat,void*);
83c4762a1bSJed Brown PetscErrorCode FormConstraints(Tao, Vec, Vec, void*);
84c4762a1bSJed Brown PetscErrorCode FormHessian(Tao, Vec, Mat, Mat, void*);
85c4762a1bSJed Brown PetscErrorCode Gather(Vec x, Vec state, VecScatter s_scat, Vec design, VecScatter d_scat);
86c4762a1bSJed Brown PetscErrorCode Scatter(Vec x, Vec state, VecScatter s_scat, Vec design, VecScatter d_scat);
87c4762a1bSJed Brown PetscErrorCode HyperbolicInitialize(AppCtx *user);
88c4762a1bSJed Brown PetscErrorCode HyperbolicDestroy(AppCtx *user);
89c4762a1bSJed Brown PetscErrorCode HyperbolicMonitor(Tao, void*);
90c4762a1bSJed Brown 
91c4762a1bSJed Brown PetscErrorCode StateMatMult(Mat,Vec,Vec);
92c4762a1bSJed Brown PetscErrorCode StateMatBlockMult(Mat,Vec,Vec);
93c4762a1bSJed Brown PetscErrorCode StateMatBlockMultTranspose(Mat,Vec,Vec);
94c4762a1bSJed Brown PetscErrorCode StateMatMultTranspose(Mat,Vec,Vec);
95c4762a1bSJed Brown PetscErrorCode StateMatGetDiagonal(Mat,Vec);
96c4762a1bSJed Brown PetscErrorCode StateMatDuplicate(Mat,MatDuplicateOption,Mat*);
97c4762a1bSJed Brown PetscErrorCode StateMatInvMult(Mat,Vec,Vec);
98c4762a1bSJed Brown PetscErrorCode StateMatInvTransposeMult(Mat,Vec,Vec);
99c4762a1bSJed Brown PetscErrorCode StateMatBlockPrecMult(PC,Vec,Vec);
100c4762a1bSJed Brown 
101c4762a1bSJed Brown PetscErrorCode DesignMatMult(Mat,Vec,Vec);
102c4762a1bSJed Brown PetscErrorCode DesignMatMultTranspose(Mat,Vec,Vec);
103c4762a1bSJed Brown 
104c4762a1bSJed Brown PetscErrorCode Scatter_yi(Vec,Vec*,VecScatter*,PetscInt); /*  y to y1,y2,...,y_nt */
105c4762a1bSJed Brown PetscErrorCode Gather_yi(Vec,Vec*,VecScatter*,PetscInt);
106c4762a1bSJed Brown PetscErrorCode Scatter_uxi_uyi(Vec,Vec*,VecScatter*,Vec*,VecScatter*,PetscInt); /*  u to ux_1,uy_1,ux_2,uy_2,...,u */
107c4762a1bSJed Brown PetscErrorCode Gather_uxi_uyi(Vec,Vec*,VecScatter*,Vec*,VecScatter*,PetscInt);
108c4762a1bSJed Brown 
109c4762a1bSJed Brown static  char help[]="";
110c4762a1bSJed Brown 
111c4762a1bSJed Brown int main(int argc, char **argv)
112c4762a1bSJed Brown {
113c4762a1bSJed Brown   PetscErrorCode     ierr;
114c4762a1bSJed Brown   Vec                x,x0;
115c4762a1bSJed Brown   Tao                tao;
116c4762a1bSJed Brown   AppCtx             user;
117c4762a1bSJed Brown   IS                 is_allstate,is_alldesign;
118c4762a1bSJed Brown   PetscInt           lo,hi,hi2,lo2,ksp_old;
119c4762a1bSJed Brown   PetscInt           ntests = 1;
120c4762a1bSJed Brown   PetscInt           i;
121c4762a1bSJed Brown #if defined(PETSC_USE_LOG)
122c4762a1bSJed Brown   PetscLogStage      stages[1];
123c4762a1bSJed Brown #endif
124c4762a1bSJed Brown 
125c4762a1bSJed Brown   ierr = PetscInitialize(&argc, &argv, (char*)0,help);if (ierr) return ierr;
126c4762a1bSJed Brown   user.mx = 32;
12776280437SVaclav Hapla   ierr = PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"hyperbolic example",NULL);CHKERRQ(ierr);
128c4762a1bSJed Brown   ierr = PetscOptionsInt("-mx","Number of grid points in each direction","",user.mx,&user.mx,NULL);CHKERRQ(ierr);
129c4762a1bSJed Brown   user.nt = 16;
130c4762a1bSJed Brown   ierr = PetscOptionsInt("-nt","Number of time steps","",user.nt,&user.nt,NULL);CHKERRQ(ierr);
131c4762a1bSJed Brown   user.ndata = 64;
132c4762a1bSJed Brown   ierr = PetscOptionsInt("-ndata","Numbers of data points per sample","",user.ndata,&user.ndata,NULL);CHKERRQ(ierr);
133c4762a1bSJed Brown   user.alpha = 10.0;
134c4762a1bSJed Brown   ierr = PetscOptionsReal("-alpha","Regularization parameter","",user.alpha,&user.alpha,NULL);CHKERRQ(ierr);
135c4762a1bSJed Brown   user.T = 1.0/32.0;
136c4762a1bSJed Brown   ierr = PetscOptionsReal("-Tfinal","Final time","",user.T,&user.T,NULL);CHKERRQ(ierr);
13776280437SVaclav Hapla   ierr = PetscOptionsInt("-ntests","Number of times to repeat TaoSolve","",ntests,&ntests,NULL);CHKERRQ(ierr);
13876280437SVaclav Hapla   ierr = PetscOptionsEnd();CHKERRQ(ierr);
139c4762a1bSJed Brown 
140c4762a1bSJed Brown   user.m = user.mx*user.mx*user.nt; /*  number of constraints */
141c4762a1bSJed Brown   user.n = user.mx*user.mx*3*user.nt; /*  number of variables */
142c4762a1bSJed Brown   user.ht = user.T/user.nt; /*  Time step */
143c4762a1bSJed Brown   user.gamma = user.T*user.ht / (user.mx*user.mx);
144c4762a1bSJed Brown 
145c4762a1bSJed Brown   ierr = VecCreate(PETSC_COMM_WORLD,&user.u);CHKERRQ(ierr);
146c4762a1bSJed Brown   ierr = VecCreate(PETSC_COMM_WORLD,&user.y);CHKERRQ(ierr);
147c4762a1bSJed Brown   ierr = VecCreate(PETSC_COMM_WORLD,&user.c);CHKERRQ(ierr);
148c4762a1bSJed Brown   ierr = VecSetSizes(user.u,PETSC_DECIDE,user.n-user.m);CHKERRQ(ierr);
149c4762a1bSJed Brown   ierr = VecSetSizes(user.y,PETSC_DECIDE,user.m);CHKERRQ(ierr);
150c4762a1bSJed Brown   ierr = VecSetSizes(user.c,PETSC_DECIDE,user.m);CHKERRQ(ierr);
151c4762a1bSJed Brown   ierr = VecSetFromOptions(user.u);CHKERRQ(ierr);
152c4762a1bSJed Brown   ierr = VecSetFromOptions(user.y);CHKERRQ(ierr);
153c4762a1bSJed Brown   ierr = VecSetFromOptions(user.c);CHKERRQ(ierr);
154c4762a1bSJed Brown 
155c4762a1bSJed Brown   /* Create scatters for reduced spaces.
156c4762a1bSJed Brown      If the state vector y and design vector u are partitioned as
157c4762a1bSJed Brown      [y_1; y_2; ...; y_np] and [u_1; u_2; ...; u_np] (with np = # of processors),
158c4762a1bSJed Brown      then the solution vector x is organized as
159c4762a1bSJed Brown      [y_1; u_1; y_2; u_2; ...; y_np; u_np].
160c4762a1bSJed Brown      The index sets user.s_is and user.d_is correspond to the indices of the
161c4762a1bSJed Brown      state and design variables owned by the current processor.
162c4762a1bSJed Brown   */
163c4762a1bSJed Brown   ierr = VecCreate(PETSC_COMM_WORLD,&x);CHKERRQ(ierr);
164c4762a1bSJed Brown 
165c4762a1bSJed Brown   ierr = VecGetOwnershipRange(user.y,&lo,&hi);CHKERRQ(ierr);
166c4762a1bSJed Brown   ierr = VecGetOwnershipRange(user.u,&lo2,&hi2);CHKERRQ(ierr);
167c4762a1bSJed Brown 
168c4762a1bSJed Brown   ierr = ISCreateStride(PETSC_COMM_SELF,hi-lo,lo,1,&is_allstate);CHKERRQ(ierr);
169c4762a1bSJed Brown   ierr = ISCreateStride(PETSC_COMM_SELF,hi-lo,lo+lo2,1,&user.s_is);CHKERRQ(ierr);
170c4762a1bSJed Brown 
171c4762a1bSJed Brown   ierr = ISCreateStride(PETSC_COMM_SELF,hi2-lo2,lo2,1,&is_alldesign);CHKERRQ(ierr);
172c4762a1bSJed Brown   ierr = ISCreateStride(PETSC_COMM_SELF,hi2-lo2,hi+lo2,1,&user.d_is);CHKERRQ(ierr);
173c4762a1bSJed Brown 
174c4762a1bSJed Brown   ierr = VecSetSizes(x,hi-lo+hi2-lo2,user.n);CHKERRQ(ierr);
175c4762a1bSJed Brown   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
176c4762a1bSJed Brown 
177c4762a1bSJed Brown   ierr = VecScatterCreate(x,user.s_is,user.y,is_allstate,&user.state_scatter);CHKERRQ(ierr);
178c4762a1bSJed Brown   ierr = VecScatterCreate(x,user.d_is,user.u,is_alldesign,&user.design_scatter);CHKERRQ(ierr);
179c4762a1bSJed Brown   ierr = ISDestroy(&is_alldesign);CHKERRQ(ierr);
180c4762a1bSJed Brown   ierr = ISDestroy(&is_allstate);CHKERRQ(ierr);
181c4762a1bSJed Brown 
182c4762a1bSJed Brown   /* Create TAO solver and set desired solution method */
183c4762a1bSJed Brown   ierr = TaoCreate(PETSC_COMM_WORLD,&tao);CHKERRQ(ierr);
184c4762a1bSJed Brown   ierr = TaoSetType(tao,TAOLCL);CHKERRQ(ierr);
185c4762a1bSJed Brown 
186c4762a1bSJed Brown   /* Set up initial vectors and matrices */
187c4762a1bSJed Brown   ierr = HyperbolicInitialize(&user);CHKERRQ(ierr);
188c4762a1bSJed Brown 
189c4762a1bSJed Brown   ierr = Gather(x,user.y,user.state_scatter,user.u,user.design_scatter);CHKERRQ(ierr);
190c4762a1bSJed Brown   ierr = VecDuplicate(x,&x0);CHKERRQ(ierr);
191c4762a1bSJed Brown   ierr = VecCopy(x,x0);CHKERRQ(ierr);
192c4762a1bSJed Brown 
193c4762a1bSJed Brown   /* Set solution vector with an initial guess */
194*a82e8c82SStefano Zampini   ierr = TaoSetSolution(tao,x);CHKERRQ(ierr);
195*a82e8c82SStefano Zampini   ierr = TaoSetObjective(tao, FormFunction, &user);CHKERRQ(ierr);
196*a82e8c82SStefano Zampini   ierr = TaoSetGradient(tao, NULL, FormGradient, &user);CHKERRQ(ierr);
1973ec1f749SStefano Zampini   ierr = TaoSetConstraintsRoutine(tao, user.c, FormConstraints, &user);CHKERRQ(ierr);
1983ec1f749SStefano Zampini   ierr = TaoSetJacobianStateRoutine(tao, user.Js, user.Js, user.JsInv, FormJacobianState, &user);CHKERRQ(ierr);
1993ec1f749SStefano Zampini   ierr = TaoSetJacobianDesignRoutine(tao, user.Jd, FormJacobianDesign, &user);CHKERRQ(ierr);
200c4762a1bSJed Brown   ierr = TaoSetFromOptions(tao);CHKERRQ(ierr);
201c4762a1bSJed Brown   ierr = TaoSetStateDesignIS(tao,user.s_is,user.d_is);CHKERRQ(ierr);
202c4762a1bSJed Brown 
203c4762a1bSJed Brown   /* SOLVE THE APPLICATION */
204c4762a1bSJed Brown   ierr = PetscLogStageRegister("Trials",&stages[0]);CHKERRQ(ierr);
205c4762a1bSJed Brown   ierr = PetscLogStagePush(stages[0]);CHKERRQ(ierr);
206c4762a1bSJed Brown   user.ksp_its_initial = user.ksp_its;
207c4762a1bSJed Brown   ksp_old = user.ksp_its;
208c4762a1bSJed Brown   for (i=0; i<ntests; i++) {
209c4762a1bSJed Brown     ierr = TaoSolve(tao);CHKERRQ(ierr);
210c4762a1bSJed Brown     ierr = PetscPrintf(PETSC_COMM_WORLD,"KSP Iterations = %D\n",user.ksp_its-ksp_old);CHKERRQ(ierr);
211c4762a1bSJed Brown     ierr = VecCopy(x0,x);CHKERRQ(ierr);
212*a82e8c82SStefano Zampini     ierr = TaoSetSolution(tao,x);CHKERRQ(ierr);
213c4762a1bSJed Brown   }
214c4762a1bSJed Brown   ierr = PetscLogStagePop();CHKERRQ(ierr);
215c4762a1bSJed Brown   ierr = PetscBarrier((PetscObject)x);CHKERRQ(ierr);
216c4762a1bSJed Brown   ierr = PetscPrintf(PETSC_COMM_WORLD,"KSP iterations within initialization: ");CHKERRQ(ierr);
217c4762a1bSJed Brown   ierr = PetscPrintf(PETSC_COMM_WORLD,"%D\n",user.ksp_its_initial);CHKERRQ(ierr);
218c4762a1bSJed Brown   ierr = PetscPrintf(PETSC_COMM_WORLD,"Total KSP iterations over %D trial(s): ",ntests);CHKERRQ(ierr);
219c4762a1bSJed Brown   ierr = PetscPrintf(PETSC_COMM_WORLD,"%D\n",user.ksp_its);CHKERRQ(ierr);
220c4762a1bSJed Brown   ierr = PetscPrintf(PETSC_COMM_WORLD,"KSP iterations per trial: ");CHKERRQ(ierr);
221c4762a1bSJed Brown   ierr = PetscPrintf(PETSC_COMM_WORLD,"%D\n",(user.ksp_its-user.ksp_its_initial)/ntests);CHKERRQ(ierr);
222c4762a1bSJed Brown 
223c4762a1bSJed Brown   ierr = TaoDestroy(&tao);CHKERRQ(ierr);
224c4762a1bSJed Brown   ierr = VecDestroy(&x);CHKERRQ(ierr);
225c4762a1bSJed Brown   ierr = VecDestroy(&x0);CHKERRQ(ierr);
226c4762a1bSJed Brown   ierr = HyperbolicDestroy(&user);CHKERRQ(ierr);
227c4762a1bSJed Brown   ierr = PetscFinalize();
228c4762a1bSJed Brown   return ierr;
229c4762a1bSJed Brown }
230c4762a1bSJed Brown /* ------------------------------------------------------------------- */
231c4762a1bSJed Brown /*
232c4762a1bSJed Brown    dwork = Qy - d
233c4762a1bSJed Brown    lwork = L*(u-ur).^2
234c4762a1bSJed Brown    f = 1/2 * (dwork.dork + alpha*y.lwork)
235c4762a1bSJed Brown */
236c4762a1bSJed Brown PetscErrorCode FormFunction(Tao tao,Vec X,PetscReal *f,void *ptr)
237c4762a1bSJed Brown {
238c4762a1bSJed Brown   PetscErrorCode ierr;
239c4762a1bSJed Brown   PetscReal      d1=0,d2=0;
240c4762a1bSJed Brown   AppCtx         *user = (AppCtx*)ptr;
241c4762a1bSJed Brown 
242c4762a1bSJed Brown   PetscFunctionBegin;
243c4762a1bSJed Brown   ierr = Scatter(X,user->y,user->state_scatter,user->u,user->design_scatter);CHKERRQ(ierr);
244c4762a1bSJed Brown   ierr = MatMult(user->Q,user->y,user->dwork);CHKERRQ(ierr);
245c4762a1bSJed Brown   ierr = VecAXPY(user->dwork,-1.0,user->d);CHKERRQ(ierr);
246c4762a1bSJed Brown   ierr = VecDot(user->dwork,user->dwork,&d1);CHKERRQ(ierr);
247c4762a1bSJed Brown 
248c4762a1bSJed Brown   ierr = VecWAXPY(user->uwork,-1.0,user->ur,user->u);CHKERRQ(ierr);
249c4762a1bSJed Brown   ierr = VecPointwiseMult(user->uwork,user->uwork,user->uwork);CHKERRQ(ierr);
250c4762a1bSJed Brown   ierr = MatMult(user->L,user->uwork,user->lwork);CHKERRQ(ierr);
251c4762a1bSJed Brown   ierr = VecDot(user->y,user->lwork,&d2);CHKERRQ(ierr);
252c4762a1bSJed Brown   *f = 0.5 * (d1 + user->alpha*d2);
253c4762a1bSJed Brown   PetscFunctionReturn(0);
254c4762a1bSJed Brown }
255c4762a1bSJed Brown 
256c4762a1bSJed Brown /* ------------------------------------------------------------------- */
257c4762a1bSJed Brown /*
258c4762a1bSJed Brown     state: g_s = Q' *(Qy - d) + 0.5*alpha*L*(u-ur).^2
259c4762a1bSJed Brown     design: g_d = alpha*(L'y).*(u-ur)
260c4762a1bSJed Brown */
261c4762a1bSJed Brown PetscErrorCode FormGradient(Tao tao,Vec X,Vec G,void *ptr)
262c4762a1bSJed Brown {
263c4762a1bSJed Brown   PetscErrorCode ierr;
264c4762a1bSJed Brown   AppCtx         *user = (AppCtx*)ptr;
265c4762a1bSJed Brown 
266c4762a1bSJed Brown   PetscFunctionBegin;
267c4762a1bSJed Brown   ierr = Scatter(X,user->y,user->state_scatter,user->u,user->design_scatter);CHKERRQ(ierr);
268c4762a1bSJed Brown   ierr = MatMult(user->Q,user->y,user->dwork);CHKERRQ(ierr);
269c4762a1bSJed Brown   ierr = VecAXPY(user->dwork,-1.0,user->d);CHKERRQ(ierr);
270c4762a1bSJed Brown 
271c4762a1bSJed Brown   ierr = MatMult(user->QT,user->dwork,user->ywork);CHKERRQ(ierr);
272c4762a1bSJed Brown 
273c4762a1bSJed Brown   ierr = MatMult(user->LT,user->y,user->uwork);CHKERRQ(ierr);
274c4762a1bSJed Brown   ierr = VecWAXPY(user->vwork,-1.0,user->ur,user->u);CHKERRQ(ierr);
275c4762a1bSJed Brown   ierr = VecPointwiseMult(user->uwork,user->vwork,user->uwork);CHKERRQ(ierr);
276c4762a1bSJed Brown   ierr = VecScale(user->uwork,user->alpha);CHKERRQ(ierr);
277c4762a1bSJed Brown 
278c4762a1bSJed Brown   ierr = VecPointwiseMult(user->vwork,user->vwork,user->vwork);CHKERRQ(ierr);
279c4762a1bSJed Brown   ierr = MatMult(user->L,user->vwork,user->lwork);CHKERRQ(ierr);
280c4762a1bSJed Brown   ierr = VecAXPY(user->ywork,0.5*user->alpha,user->lwork);CHKERRQ(ierr);
281c4762a1bSJed Brown 
282c4762a1bSJed Brown   ierr = Gather(G,user->ywork,user->state_scatter,user->uwork,user->design_scatter);CHKERRQ(ierr);
283c4762a1bSJed Brown   PetscFunctionReturn(0);
284c4762a1bSJed Brown }
285c4762a1bSJed Brown 
286c4762a1bSJed Brown PetscErrorCode FormFunctionGradient(Tao tao, Vec X, PetscReal *f, Vec G, void *ptr)
287c4762a1bSJed Brown {
288c4762a1bSJed Brown   PetscErrorCode ierr;
289c4762a1bSJed Brown   PetscReal      d1,d2;
290c4762a1bSJed Brown   AppCtx         *user = (AppCtx*)ptr;
291c4762a1bSJed Brown 
292c4762a1bSJed Brown   PetscFunctionBegin;
293c4762a1bSJed Brown   ierr = Scatter(X,user->y,user->state_scatter,user->u,user->design_scatter);CHKERRQ(ierr);
294c4762a1bSJed Brown   ierr = MatMult(user->Q,user->y,user->dwork);CHKERRQ(ierr);
295c4762a1bSJed Brown   ierr = VecAXPY(user->dwork,-1.0,user->d);CHKERRQ(ierr);
296c4762a1bSJed Brown 
297c4762a1bSJed Brown   ierr = MatMult(user->QT,user->dwork,user->ywork);CHKERRQ(ierr);
298c4762a1bSJed Brown 
299c4762a1bSJed Brown   ierr = VecDot(user->dwork,user->dwork,&d1);CHKERRQ(ierr);
300c4762a1bSJed Brown 
301c4762a1bSJed Brown   ierr = MatMult(user->LT,user->y,user->uwork);CHKERRQ(ierr);
302c4762a1bSJed Brown   ierr = VecWAXPY(user->vwork,-1.0,user->ur,user->u);CHKERRQ(ierr);
303c4762a1bSJed Brown   ierr = VecPointwiseMult(user->uwork,user->vwork,user->uwork);CHKERRQ(ierr);
304c4762a1bSJed Brown   ierr = VecScale(user->uwork,user->alpha);CHKERRQ(ierr);
305c4762a1bSJed Brown 
306c4762a1bSJed Brown   ierr = VecPointwiseMult(user->vwork,user->vwork,user->vwork);CHKERRQ(ierr);
307c4762a1bSJed Brown   ierr = MatMult(user->L,user->vwork,user->lwork);CHKERRQ(ierr);
308c4762a1bSJed Brown   ierr = VecAXPY(user->ywork,0.5*user->alpha,user->lwork);CHKERRQ(ierr);
309c4762a1bSJed Brown 
310c4762a1bSJed Brown   ierr = VecDot(user->y,user->lwork,&d2);CHKERRQ(ierr);
311c4762a1bSJed Brown 
312c4762a1bSJed Brown   *f = 0.5 * (d1 + user->alpha*d2);
313c4762a1bSJed Brown   ierr = Gather(G,user->ywork,user->state_scatter,user->uwork,user->design_scatter);CHKERRQ(ierr);
314c4762a1bSJed Brown   PetscFunctionReturn(0);
315c4762a1bSJed Brown }
316c4762a1bSJed Brown 
317c4762a1bSJed Brown /* ------------------------------------------------------------------- */
318c4762a1bSJed Brown /* A
319c4762a1bSJed Brown MatShell object
320c4762a1bSJed Brown */
321c4762a1bSJed Brown PetscErrorCode FormJacobianState(Tao tao, Vec X, Mat J, Mat JPre, Mat JInv, void *ptr)
322c4762a1bSJed Brown {
323c4762a1bSJed Brown   PetscErrorCode ierr;
324c4762a1bSJed Brown   PetscInt       i;
325c4762a1bSJed Brown   AppCtx         *user = (AppCtx*)ptr;
326c4762a1bSJed Brown 
327c4762a1bSJed Brown   PetscFunctionBegin;
328c4762a1bSJed Brown   ierr = Scatter(X,user->y,user->state_scatter,user->u,user->design_scatter);CHKERRQ(ierr);
329c4762a1bSJed Brown   ierr = Scatter_yi(user->u,user->ui,user->ui_scatter,user->nt);CHKERRQ(ierr);
330c4762a1bSJed Brown   ierr = Scatter_uxi_uyi(user->u,user->uxi,user->uxi_scatter,user->uyi,user->uyi_scatter,user->nt);CHKERRQ(ierr);
331c4762a1bSJed Brown   for (i=0; i<user->nt; i++) {
332c4762a1bSJed Brown     ierr = MatCopy(user->Divxy[0],user->C[i],SUBSET_NONZERO_PATTERN);CHKERRQ(ierr);
333c4762a1bSJed Brown     ierr = MatCopy(user->Divxy[1],user->Cwork[i],SAME_NONZERO_PATTERN);CHKERRQ(ierr);
334c4762a1bSJed Brown 
335c4762a1bSJed Brown     ierr = MatDiagonalScale(user->C[i],NULL,user->uxi[i]);CHKERRQ(ierr);
336c4762a1bSJed Brown     ierr = MatDiagonalScale(user->Cwork[i],NULL,user->uyi[i]);CHKERRQ(ierr);
337c4762a1bSJed Brown     ierr = MatAXPY(user->C[i],1.0,user->Cwork[i],SUBSET_NONZERO_PATTERN);CHKERRQ(ierr);
338c4762a1bSJed Brown     ierr = MatScale(user->C[i],user->ht);CHKERRQ(ierr);
339c4762a1bSJed Brown     ierr = MatShift(user->C[i],1.0);CHKERRQ(ierr);
340c4762a1bSJed Brown   }
341c4762a1bSJed Brown   PetscFunctionReturn(0);
342c4762a1bSJed Brown }
343c4762a1bSJed Brown 
344c4762a1bSJed Brown /* ------------------------------------------------------------------- */
345c4762a1bSJed Brown /* B */
346c4762a1bSJed Brown PetscErrorCode FormJacobianDesign(Tao tao, Vec X, Mat J, void *ptr)
347c4762a1bSJed Brown {
348c4762a1bSJed Brown   PetscErrorCode ierr;
349c4762a1bSJed Brown   AppCtx         *user = (AppCtx*)ptr;
350c4762a1bSJed Brown 
351c4762a1bSJed Brown   PetscFunctionBegin;
352c4762a1bSJed Brown   ierr = Scatter(X,user->y,user->state_scatter,user->u,user->design_scatter);CHKERRQ(ierr);
353c4762a1bSJed Brown   PetscFunctionReturn(0);
354c4762a1bSJed Brown }
355c4762a1bSJed Brown 
356c4762a1bSJed Brown PetscErrorCode StateMatMult(Mat J_shell, Vec X, Vec Y)
357c4762a1bSJed Brown {
358c4762a1bSJed Brown   PetscErrorCode ierr;
359c4762a1bSJed Brown   PetscInt       i;
360c4762a1bSJed Brown   AppCtx         *user;
361c4762a1bSJed Brown 
362c4762a1bSJed Brown   PetscFunctionBegin;
3633ec1f749SStefano Zampini   ierr = MatShellGetContext(J_shell,&user);CHKERRQ(ierr);
364c4762a1bSJed Brown   ierr = Scatter_yi(X,user->yi,user->yi_scatter,user->nt);CHKERRQ(ierr);
365c4762a1bSJed Brown   user->block_index = 0;
366c4762a1bSJed Brown   ierr = MatMult(user->JsBlock,user->yi[0],user->yiwork[0]);CHKERRQ(ierr);
367c4762a1bSJed Brown 
368c4762a1bSJed Brown   for (i=1; i<user->nt; i++) {
369c4762a1bSJed Brown     user->block_index = i;
370c4762a1bSJed Brown     ierr = MatMult(user->JsBlock,user->yi[i],user->yiwork[i]);CHKERRQ(ierr);
371c4762a1bSJed Brown     ierr = MatMult(user->M,user->yi[i-1],user->ziwork[i-1]);CHKERRQ(ierr);
372c4762a1bSJed Brown     ierr = VecAXPY(user->yiwork[i],-1.0,user->ziwork[i-1]);CHKERRQ(ierr);
373c4762a1bSJed Brown   }
374c4762a1bSJed Brown   ierr = Gather_yi(Y,user->yiwork,user->yi_scatter,user->nt);CHKERRQ(ierr);
375c4762a1bSJed Brown   PetscFunctionReturn(0);
376c4762a1bSJed Brown }
377c4762a1bSJed Brown 
378c4762a1bSJed Brown PetscErrorCode StateMatMultTranspose(Mat J_shell, Vec X, Vec Y)
379c4762a1bSJed Brown {
380c4762a1bSJed Brown   PetscErrorCode ierr;
381c4762a1bSJed Brown   PetscInt       i;
382c4762a1bSJed Brown   AppCtx         *user;
383c4762a1bSJed Brown 
384c4762a1bSJed Brown   PetscFunctionBegin;
3853ec1f749SStefano Zampini   ierr = MatShellGetContext(J_shell,&user);CHKERRQ(ierr);
386c4762a1bSJed Brown   ierr = Scatter_yi(X,user->yi,user->yi_scatter,user->nt);CHKERRQ(ierr);
387c4762a1bSJed Brown 
388c4762a1bSJed Brown   for (i=0; i<user->nt-1; i++) {
389c4762a1bSJed Brown     user->block_index = i;
390c4762a1bSJed Brown     ierr = MatMultTranspose(user->JsBlock,user->yi[i],user->yiwork[i]);CHKERRQ(ierr);
391c4762a1bSJed Brown     ierr = MatMult(user->M,user->yi[i+1],user->ziwork[i+1]);CHKERRQ(ierr);
392c4762a1bSJed Brown     ierr = VecAXPY(user->yiwork[i],-1.0,user->ziwork[i+1]);CHKERRQ(ierr);
393c4762a1bSJed Brown   }
394c4762a1bSJed Brown 
395c4762a1bSJed Brown   i = user->nt-1;
396c4762a1bSJed Brown   user->block_index = i;
397c4762a1bSJed Brown   ierr = MatMultTranspose(user->JsBlock,user->yi[i],user->yiwork[i]);CHKERRQ(ierr);
398c4762a1bSJed Brown   ierr = Gather_yi(Y,user->yiwork,user->yi_scatter,user->nt);CHKERRQ(ierr);
399c4762a1bSJed Brown   PetscFunctionReturn(0);
400c4762a1bSJed Brown }
401c4762a1bSJed Brown 
402c4762a1bSJed Brown PetscErrorCode StateMatBlockMult(Mat J_shell, Vec X, Vec Y)
403c4762a1bSJed Brown {
404c4762a1bSJed Brown   PetscErrorCode ierr;
405c4762a1bSJed Brown   PetscInt       i;
406c4762a1bSJed Brown   AppCtx         *user;
407c4762a1bSJed Brown 
408c4762a1bSJed Brown   PetscFunctionBegin;
4093ec1f749SStefano Zampini   ierr = MatShellGetContext(J_shell,&user);CHKERRQ(ierr);
410c4762a1bSJed Brown   i = user->block_index;
411c4762a1bSJed Brown   ierr = VecPointwiseMult(user->uxiwork[i],X,user->uxi[i]);CHKERRQ(ierr);
412c4762a1bSJed Brown   ierr = VecPointwiseMult(user->uyiwork[i],X,user->uyi[i]);CHKERRQ(ierr);
413c4762a1bSJed Brown   ierr = Gather(user->uiwork[i],user->uxiwork[i],user->ux_scatter[i],user->uyiwork[i],user->uy_scatter[i]);CHKERRQ(ierr);
414c4762a1bSJed Brown   ierr = MatMult(user->Div,user->uiwork[i],Y);CHKERRQ(ierr);
415c4762a1bSJed Brown   ierr = VecAYPX(Y,user->ht,X);CHKERRQ(ierr);
416c4762a1bSJed Brown   PetscFunctionReturn(0);
417c4762a1bSJed Brown }
418c4762a1bSJed Brown 
419c4762a1bSJed Brown PetscErrorCode StateMatBlockMultTranspose(Mat J_shell, Vec X, Vec Y)
420c4762a1bSJed Brown {
421c4762a1bSJed Brown   PetscErrorCode ierr;
422c4762a1bSJed Brown   PetscInt       i;
423c4762a1bSJed Brown   AppCtx         *user;
424c4762a1bSJed Brown 
425c4762a1bSJed Brown   PetscFunctionBegin;
4263ec1f749SStefano Zampini   ierr = MatShellGetContext(J_shell,&user);CHKERRQ(ierr);
427c4762a1bSJed Brown   i = user->block_index;
428c4762a1bSJed Brown   ierr = MatMult(user->Grad,X,user->uiwork[i]);CHKERRQ(ierr);
429c4762a1bSJed Brown   ierr = Scatter(user->uiwork[i],user->uxiwork[i],user->ux_scatter[i],user->uyiwork[i],user->uy_scatter[i]);CHKERRQ(ierr);
430c4762a1bSJed Brown   ierr = VecPointwiseMult(user->uxiwork[i],user->uxi[i],user->uxiwork[i]);CHKERRQ(ierr);
431c4762a1bSJed Brown   ierr = VecPointwiseMult(user->uyiwork[i],user->uyi[i],user->uyiwork[i]);CHKERRQ(ierr);
432c4762a1bSJed Brown   ierr = VecWAXPY(Y,1.0,user->uxiwork[i],user->uyiwork[i]);CHKERRQ(ierr);
433c4762a1bSJed Brown   ierr = VecAYPX(Y,user->ht,X);CHKERRQ(ierr);
434c4762a1bSJed Brown   PetscFunctionReturn(0);
435c4762a1bSJed Brown }
436c4762a1bSJed Brown 
437c4762a1bSJed Brown PetscErrorCode DesignMatMult(Mat J_shell, Vec X, Vec Y)
438c4762a1bSJed Brown {
439c4762a1bSJed Brown   PetscErrorCode ierr;
440c4762a1bSJed Brown   PetscInt       i;
441c4762a1bSJed Brown   AppCtx         *user;
442c4762a1bSJed Brown 
443c4762a1bSJed Brown   PetscFunctionBegin;
4443ec1f749SStefano Zampini   ierr = MatShellGetContext(J_shell,&user);CHKERRQ(ierr);
445c4762a1bSJed Brown   ierr = Scatter_yi(user->y,user->yi,user->yi_scatter,user->nt);CHKERRQ(ierr);
446c4762a1bSJed Brown   ierr = Scatter_uxi_uyi(X,user->uxiwork,user->uxi_scatter,user->uyiwork,user->uyi_scatter,user->nt);CHKERRQ(ierr);
447c4762a1bSJed Brown   for (i=0; i<user->nt; i++) {
448c4762a1bSJed Brown     ierr = VecPointwiseMult(user->uxiwork[i],user->yi[i],user->uxiwork[i]);CHKERRQ(ierr);
449c4762a1bSJed Brown     ierr = VecPointwiseMult(user->uyiwork[i],user->yi[i],user->uyiwork[i]);CHKERRQ(ierr);
450c4762a1bSJed Brown     ierr = Gather(user->uiwork[i],user->uxiwork[i],user->ux_scatter[i],user->uyiwork[i],user->uy_scatter[i]);CHKERRQ(ierr);
451c4762a1bSJed Brown     ierr = MatMult(user->Div,user->uiwork[i],user->ziwork[i]);CHKERRQ(ierr);
452c4762a1bSJed Brown     ierr = VecScale(user->ziwork[i],user->ht);CHKERRQ(ierr);
453c4762a1bSJed Brown   }
454c4762a1bSJed Brown   ierr = Gather_yi(Y,user->ziwork,user->yi_scatter,user->nt);CHKERRQ(ierr);
455c4762a1bSJed Brown   PetscFunctionReturn(0);
456c4762a1bSJed Brown }
457c4762a1bSJed Brown 
458c4762a1bSJed Brown PetscErrorCode DesignMatMultTranspose(Mat J_shell, Vec X, Vec Y)
459c4762a1bSJed Brown {
460c4762a1bSJed Brown   PetscErrorCode ierr;
461c4762a1bSJed Brown   PetscInt       i;
462c4762a1bSJed Brown   AppCtx         *user;
463c4762a1bSJed Brown 
464c4762a1bSJed Brown   PetscFunctionBegin;
4653ec1f749SStefano Zampini   ierr = MatShellGetContext(J_shell,&user);CHKERRQ(ierr);
466c4762a1bSJed Brown   ierr = Scatter_yi(user->y,user->yi,user->yi_scatter,user->nt);CHKERRQ(ierr);
467c4762a1bSJed Brown   ierr = Scatter_yi(X,user->yiwork,user->yi_scatter,user->nt);CHKERRQ(ierr);
468c4762a1bSJed Brown   for (i=0; i<user->nt; i++) {
469c4762a1bSJed Brown     ierr = MatMult(user->Grad,user->yiwork[i],user->uiwork[i]);CHKERRQ(ierr);
470c4762a1bSJed Brown     ierr = Scatter(user->uiwork[i],user->uxiwork[i],user->ux_scatter[i],user->uyiwork[i],user->uy_scatter[i]);CHKERRQ(ierr);
471c4762a1bSJed Brown     ierr = VecPointwiseMult(user->uxiwork[i],user->yi[i],user->uxiwork[i]);CHKERRQ(ierr);
472c4762a1bSJed Brown     ierr = VecPointwiseMult(user->uyiwork[i],user->yi[i],user->uyiwork[i]);CHKERRQ(ierr);
473c4762a1bSJed Brown     ierr = Gather(user->uiwork[i],user->uxiwork[i],user->ux_scatter[i],user->uyiwork[i],user->uy_scatter[i]);CHKERRQ(ierr);
474c4762a1bSJed Brown     ierr = VecScale(user->uiwork[i],user->ht);CHKERRQ(ierr);
475c4762a1bSJed Brown   }
476c4762a1bSJed Brown   ierr = Gather_yi(Y,user->uiwork,user->ui_scatter,user->nt);CHKERRQ(ierr);
477c4762a1bSJed Brown   PetscFunctionReturn(0);
478c4762a1bSJed Brown }
479c4762a1bSJed Brown 
480c4762a1bSJed Brown PetscErrorCode StateMatBlockPrecMult(PC PC_shell, Vec X, Vec Y)
481c4762a1bSJed Brown {
482c4762a1bSJed Brown   PetscErrorCode ierr;
483c4762a1bSJed Brown   PetscInt       i;
484c4762a1bSJed Brown   AppCtx         *user;
485c4762a1bSJed Brown 
486c4762a1bSJed Brown   PetscFunctionBegin;
4873ec1f749SStefano Zampini   ierr = PCShellGetContext(PC_shell,&user);CHKERRQ(ierr);
488c4762a1bSJed Brown   i = user->block_index;
489c4762a1bSJed Brown   if (user->c_formed) {
490c4762a1bSJed Brown     ierr = MatSOR(user->C[i],X,1.0,(MatSORType)(SOR_ZERO_INITIAL_GUESS | SOR_LOCAL_SYMMETRIC_SWEEP),0.0,1,1,Y);CHKERRQ(ierr);
491c4762a1bSJed Brown   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not formed");
492c4762a1bSJed Brown   PetscFunctionReturn(0);
493c4762a1bSJed Brown }
494c4762a1bSJed Brown 
495c4762a1bSJed Brown PetscErrorCode StateMatBlockPrecMultTranspose(PC PC_shell, Vec X, Vec Y)
496c4762a1bSJed Brown {
497c4762a1bSJed Brown   PetscErrorCode ierr;
498c4762a1bSJed Brown   PetscInt       i;
499c4762a1bSJed Brown   AppCtx         *user;
500c4762a1bSJed Brown 
501c4762a1bSJed Brown   PetscFunctionBegin;
5023ec1f749SStefano Zampini   ierr = PCShellGetContext(PC_shell,&user);CHKERRQ(ierr);
503c4762a1bSJed Brown 
504c4762a1bSJed Brown   i = user->block_index;
505c4762a1bSJed Brown   if (user->c_formed) {
506c4762a1bSJed Brown     ierr = MatSOR(user->C[i],X,1.0,(MatSORType)(SOR_ZERO_INITIAL_GUESS | SOR_LOCAL_SYMMETRIC_SWEEP),0.0,1,1,Y);CHKERRQ(ierr);
507c4762a1bSJed Brown   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not formed");
508c4762a1bSJed Brown   PetscFunctionReturn(0);
509c4762a1bSJed Brown }
510c4762a1bSJed Brown 
511c4762a1bSJed Brown PetscErrorCode StateMatInvMult(Mat J_shell, Vec X, Vec Y)
512c4762a1bSJed Brown {
513c4762a1bSJed Brown   PetscErrorCode ierr;
514c4762a1bSJed Brown   AppCtx         *user;
515c4762a1bSJed Brown   PetscInt       its,i;
516c4762a1bSJed Brown 
517c4762a1bSJed Brown   PetscFunctionBegin;
5183ec1f749SStefano Zampini   ierr = MatShellGetContext(J_shell,&user);CHKERRQ(ierr);
519c4762a1bSJed Brown 
520c4762a1bSJed Brown   if (Y == user->ytrue) {
521c4762a1bSJed Brown     /* First solve is done using true solution to set up problem */
522c4762a1bSJed Brown     ierr = KSPSetTolerances(user->solver,1e-4,1e-20,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr);
523c4762a1bSJed Brown   } else {
524c4762a1bSJed Brown     ierr = KSPSetTolerances(user->solver,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr);
525c4762a1bSJed Brown   }
526c4762a1bSJed Brown   ierr = Scatter_yi(X,user->yi,user->yi_scatter,user->nt);CHKERRQ(ierr);
527c4762a1bSJed Brown   ierr = Scatter_yi(Y,user->yiwork,user->yi_scatter,user->nt);CHKERRQ(ierr);
528c4762a1bSJed Brown   ierr = Scatter_uxi_uyi(user->u,user->uxi,user->uxi_scatter,user->uyi,user->uyi_scatter,user->nt);CHKERRQ(ierr);
529c4762a1bSJed Brown 
530c4762a1bSJed Brown   user->block_index = 0;
531c4762a1bSJed Brown   ierr = KSPSolve(user->solver,user->yi[0],user->yiwork[0]);CHKERRQ(ierr);
532c4762a1bSJed Brown 
533c4762a1bSJed Brown   ierr = KSPGetIterationNumber(user->solver,&its);CHKERRQ(ierr);
534c4762a1bSJed Brown   user->ksp_its = user->ksp_its + its;
535c4762a1bSJed Brown   for (i=1; i<user->nt; i++) {
536c4762a1bSJed Brown     ierr = MatMult(user->M,user->yiwork[i-1],user->ziwork[i-1]);CHKERRQ(ierr);
537c4762a1bSJed Brown     ierr = VecAXPY(user->yi[i],1.0,user->ziwork[i-1]);CHKERRQ(ierr);
538c4762a1bSJed Brown     user->block_index = i;
539c4762a1bSJed Brown     ierr = KSPSolve(user->solver,user->yi[i],user->yiwork[i]);CHKERRQ(ierr);
540c4762a1bSJed Brown 
541c4762a1bSJed Brown     ierr = KSPGetIterationNumber(user->solver,&its);CHKERRQ(ierr);
542c4762a1bSJed Brown     user->ksp_its = user->ksp_its + its;
543c4762a1bSJed Brown   }
544c4762a1bSJed Brown   ierr = Gather_yi(Y,user->yiwork,user->yi_scatter,user->nt);CHKERRQ(ierr);
545c4762a1bSJed Brown   PetscFunctionReturn(0);
546c4762a1bSJed Brown }
547c4762a1bSJed Brown 
548c4762a1bSJed Brown PetscErrorCode StateMatInvTransposeMult(Mat J_shell, Vec X, Vec Y)
549c4762a1bSJed Brown {
550c4762a1bSJed Brown   PetscErrorCode ierr;
551c4762a1bSJed Brown   AppCtx         *user;
552c4762a1bSJed Brown   PetscInt       its,i;
553c4762a1bSJed Brown 
554c4762a1bSJed Brown   PetscFunctionBegin;
5553ec1f749SStefano Zampini   ierr = MatShellGetContext(J_shell,&user);CHKERRQ(ierr);
556c4762a1bSJed Brown 
557c4762a1bSJed Brown   ierr = Scatter_yi(X,user->yi,user->yi_scatter,user->nt);CHKERRQ(ierr);
558c4762a1bSJed Brown   ierr = Scatter_yi(Y,user->yiwork,user->yi_scatter,user->nt);CHKERRQ(ierr);
559c4762a1bSJed Brown   ierr = Scatter_uxi_uyi(user->u,user->uxi,user->uxi_scatter,user->uyi,user->uyi_scatter,user->nt);CHKERRQ(ierr);
560c4762a1bSJed Brown 
561c4762a1bSJed Brown   i = user->nt - 1;
562c4762a1bSJed Brown   user->block_index = i;
563c4762a1bSJed Brown   ierr = KSPSolveTranspose(user->solver,user->yi[i],user->yiwork[i]);CHKERRQ(ierr);
564c4762a1bSJed Brown 
565c4762a1bSJed Brown   ierr = KSPGetIterationNumber(user->solver,&its);CHKERRQ(ierr);
566c4762a1bSJed Brown   user->ksp_its = user->ksp_its + its;
567c4762a1bSJed Brown 
568c4762a1bSJed Brown   for (i=user->nt-2; i>=0; i--) {
569c4762a1bSJed Brown     ierr = MatMult(user->M,user->yiwork[i+1],user->ziwork[i+1]);CHKERRQ(ierr);
570c4762a1bSJed Brown     ierr = VecAXPY(user->yi[i],1.0,user->ziwork[i+1]);CHKERRQ(ierr);
571c4762a1bSJed Brown     user->block_index = i;
572c4762a1bSJed Brown     ierr = KSPSolveTranspose(user->solver,user->yi[i],user->yiwork[i]);CHKERRQ(ierr);
573c4762a1bSJed Brown 
574c4762a1bSJed Brown     ierr = KSPGetIterationNumber(user->solver,&its);CHKERRQ(ierr);
575c4762a1bSJed Brown     user->ksp_its = user->ksp_its + its;
576c4762a1bSJed Brown   }
577c4762a1bSJed Brown   ierr = Gather_yi(Y,user->yiwork,user->yi_scatter,user->nt);CHKERRQ(ierr);
578c4762a1bSJed Brown   PetscFunctionReturn(0);
579c4762a1bSJed Brown }
580c4762a1bSJed Brown 
581c4762a1bSJed Brown PetscErrorCode StateMatDuplicate(Mat J_shell, MatDuplicateOption opt, Mat *new_shell)
582c4762a1bSJed Brown {
583c4762a1bSJed Brown   PetscErrorCode ierr;
584c4762a1bSJed Brown   AppCtx         *user;
585c4762a1bSJed Brown 
586c4762a1bSJed Brown   PetscFunctionBegin;
5873ec1f749SStefano Zampini   ierr = MatShellGetContext(J_shell,&user);CHKERRQ(ierr);
588c4762a1bSJed Brown 
589c4762a1bSJed Brown   ierr = MatCreateShell(PETSC_COMM_WORLD,PETSC_DETERMINE,PETSC_DETERMINE,user->m,user->m,user,new_shell);CHKERRQ(ierr);
590c4762a1bSJed Brown   ierr = MatShellSetOperation(*new_shell,MATOP_MULT,(void(*)(void))StateMatMult);CHKERRQ(ierr);
591c4762a1bSJed Brown   ierr = MatShellSetOperation(*new_shell,MATOP_DUPLICATE,(void(*)(void))StateMatDuplicate);CHKERRQ(ierr);
592c4762a1bSJed Brown   ierr = MatShellSetOperation(*new_shell,MATOP_MULT_TRANSPOSE,(void(*)(void))StateMatMultTranspose);CHKERRQ(ierr);
593c4762a1bSJed Brown   ierr = MatShellSetOperation(*new_shell,MATOP_GET_DIAGONAL,(void(*)(void))StateMatGetDiagonal);CHKERRQ(ierr);
594c4762a1bSJed Brown   PetscFunctionReturn(0);
595c4762a1bSJed Brown }
596c4762a1bSJed Brown 
597c4762a1bSJed Brown PetscErrorCode StateMatGetDiagonal(Mat J_shell, Vec X)
598c4762a1bSJed Brown {
599c4762a1bSJed Brown   PetscErrorCode ierr;
600c4762a1bSJed Brown   AppCtx         *user;
601c4762a1bSJed Brown 
602c4762a1bSJed Brown   PetscFunctionBegin;
6033ec1f749SStefano Zampini   ierr = MatShellGetContext(J_shell,&user);CHKERRQ(ierr);
604c4762a1bSJed Brown   ierr =  VecCopy(user->js_diag,X);CHKERRQ(ierr);
605c4762a1bSJed Brown   PetscFunctionReturn(0);
606c4762a1bSJed Brown }
607c4762a1bSJed Brown 
608c4762a1bSJed Brown PetscErrorCode FormConstraints(Tao tao, Vec X, Vec C, void *ptr)
609c4762a1bSJed Brown {
610c4762a1bSJed Brown   /* con = Ay - q, A = [C(u1)  0     0     ...   0;
611c4762a1bSJed Brown                          -M  C(u2)   0     ...   0;
612c4762a1bSJed Brown                           0   -M   C(u3)   ...   0;
613c4762a1bSJed Brown                                       ...         ;
614c4762a1bSJed Brown                           0    ...      -M C(u_nt)]
615c4762a1bSJed Brown      C(u) = eye + ht*Div*[diag(u1); diag(u2)]       */
616c4762a1bSJed Brown   PetscErrorCode ierr;
617c4762a1bSJed Brown   PetscInt       i;
618c4762a1bSJed Brown   AppCtx         *user = (AppCtx*)ptr;
619c4762a1bSJed Brown 
620c4762a1bSJed Brown   PetscFunctionBegin;
621c4762a1bSJed Brown   ierr = Scatter(X,user->y,user->state_scatter,user->u,user->design_scatter);CHKERRQ(ierr);
622c4762a1bSJed Brown   ierr = Scatter_yi(user->y,user->yi,user->yi_scatter,user->nt);CHKERRQ(ierr);
623c4762a1bSJed Brown   ierr = Scatter_uxi_uyi(user->u,user->uxi,user->uxi_scatter,user->uyi,user->uyi_scatter,user->nt);CHKERRQ(ierr);
624c4762a1bSJed Brown 
625c4762a1bSJed Brown   user->block_index = 0;
626c4762a1bSJed Brown   ierr = MatMult(user->JsBlock,user->yi[0],user->yiwork[0]);CHKERRQ(ierr);
627c4762a1bSJed Brown 
628c4762a1bSJed Brown   for (i=1; i<user->nt; i++) {
629c4762a1bSJed Brown     user->block_index = i;
630c4762a1bSJed Brown     ierr = MatMult(user->JsBlock,user->yi[i],user->yiwork[i]);CHKERRQ(ierr);
631c4762a1bSJed Brown     ierr = MatMult(user->M,user->yi[i-1],user->ziwork[i-1]);CHKERRQ(ierr);
632c4762a1bSJed Brown     ierr = VecAXPY(user->yiwork[i],-1.0,user->ziwork[i-1]);CHKERRQ(ierr);
633c4762a1bSJed Brown   }
634c4762a1bSJed Brown 
635c4762a1bSJed Brown   ierr = Gather_yi(C,user->yiwork,user->yi_scatter,user->nt);CHKERRQ(ierr);
636c4762a1bSJed Brown   ierr = VecAXPY(C,-1.0,user->q);CHKERRQ(ierr);
637c4762a1bSJed Brown 
638c4762a1bSJed Brown   PetscFunctionReturn(0);
639c4762a1bSJed Brown }
640c4762a1bSJed Brown 
641c4762a1bSJed Brown PetscErrorCode Scatter(Vec x, Vec state, VecScatter s_scat, Vec design, VecScatter d_scat)
642c4762a1bSJed Brown {
643c4762a1bSJed Brown   PetscErrorCode ierr;
644c4762a1bSJed Brown 
645c4762a1bSJed Brown   PetscFunctionBegin;
646c4762a1bSJed Brown   ierr = VecScatterBegin(s_scat,x,state,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
647c4762a1bSJed Brown   ierr = VecScatterEnd(s_scat,x,state,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
648c4762a1bSJed Brown   ierr = VecScatterBegin(d_scat,x,design,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
649c4762a1bSJed Brown   ierr = VecScatterEnd(d_scat,x,design,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
650c4762a1bSJed Brown   PetscFunctionReturn(0);
651c4762a1bSJed Brown }
652c4762a1bSJed Brown 
653c4762a1bSJed Brown PetscErrorCode Scatter_uxi_uyi(Vec u, Vec *uxi, VecScatter *scatx, Vec *uyi, VecScatter *scaty, PetscInt nt)
654c4762a1bSJed Brown {
655c4762a1bSJed Brown   PetscErrorCode ierr;
656c4762a1bSJed Brown   PetscInt       i;
657c4762a1bSJed Brown 
658c4762a1bSJed Brown   PetscFunctionBegin;
659c4762a1bSJed Brown   for (i=0; i<nt; i++) {
660c4762a1bSJed Brown     ierr = VecScatterBegin(scatx[i],u,uxi[i],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
661c4762a1bSJed Brown     ierr = VecScatterEnd(scatx[i],u,uxi[i],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
662c4762a1bSJed Brown     ierr = VecScatterBegin(scaty[i],u,uyi[i],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
663c4762a1bSJed Brown     ierr = VecScatterEnd(scaty[i],u,uyi[i],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
664c4762a1bSJed Brown   }
665c4762a1bSJed Brown   PetscFunctionReturn(0);
666c4762a1bSJed Brown }
667c4762a1bSJed Brown 
668c4762a1bSJed Brown PetscErrorCode Gather(Vec x, Vec state, VecScatter s_scat, Vec design, VecScatter d_scat)
669c4762a1bSJed Brown {
670c4762a1bSJed Brown   PetscErrorCode ierr;
671c4762a1bSJed Brown 
672c4762a1bSJed Brown   PetscFunctionBegin;
673c4762a1bSJed Brown   ierr = VecScatterBegin(s_scat,state,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
674c4762a1bSJed Brown   ierr = VecScatterEnd(s_scat,state,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
675c4762a1bSJed Brown   ierr = VecScatterBegin(d_scat,design,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
676c4762a1bSJed Brown   ierr = VecScatterEnd(d_scat,design,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
677c4762a1bSJed Brown   PetscFunctionReturn(0);
678c4762a1bSJed Brown }
679c4762a1bSJed Brown 
680c4762a1bSJed Brown PetscErrorCode Gather_uxi_uyi(Vec u, Vec *uxi, VecScatter *scatx, Vec *uyi, VecScatter *scaty, PetscInt nt)
681c4762a1bSJed Brown {
682c4762a1bSJed Brown   PetscErrorCode ierr;
683c4762a1bSJed Brown   PetscInt       i;
684c4762a1bSJed Brown 
685c4762a1bSJed Brown   PetscFunctionBegin;
686c4762a1bSJed Brown   for (i=0; i<nt; i++) {
687c4762a1bSJed Brown     ierr = VecScatterBegin(scatx[i],uxi[i],u,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
688c4762a1bSJed Brown     ierr = VecScatterEnd(scatx[i],uxi[i],u,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
689c4762a1bSJed Brown     ierr = VecScatterBegin(scaty[i],uyi[i],u,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
690c4762a1bSJed Brown     ierr = VecScatterEnd(scaty[i],uyi[i],u,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
691c4762a1bSJed Brown   }
692c4762a1bSJed Brown   PetscFunctionReturn(0);
693c4762a1bSJed Brown }
694c4762a1bSJed Brown 
695c4762a1bSJed Brown PetscErrorCode Scatter_yi(Vec y, Vec *yi, VecScatter *scat, PetscInt nt)
696c4762a1bSJed Brown {
697c4762a1bSJed Brown   PetscErrorCode ierr;
698c4762a1bSJed Brown   PetscInt       i;
699c4762a1bSJed Brown 
700c4762a1bSJed Brown   PetscFunctionBegin;
701c4762a1bSJed Brown   for (i=0; i<nt; i++) {
702c4762a1bSJed Brown     ierr = VecScatterBegin(scat[i],y,yi[i],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
703c4762a1bSJed Brown     ierr = VecScatterEnd(scat[i],y,yi[i],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
704c4762a1bSJed Brown   }
705c4762a1bSJed Brown   PetscFunctionReturn(0);
706c4762a1bSJed Brown }
707c4762a1bSJed Brown 
708c4762a1bSJed Brown PetscErrorCode Gather_yi(Vec y, Vec *yi, VecScatter *scat, PetscInt nt)
709c4762a1bSJed Brown {
710c4762a1bSJed Brown   PetscErrorCode ierr;
711c4762a1bSJed Brown   PetscInt       i;
712c4762a1bSJed Brown 
713c4762a1bSJed Brown   PetscFunctionBegin;
714c4762a1bSJed Brown   for (i=0; i<nt; i++) {
715c4762a1bSJed Brown     ierr = VecScatterBegin(scat[i],yi[i],y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
716c4762a1bSJed Brown     ierr = VecScatterEnd(scat[i],yi[i],y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
717c4762a1bSJed Brown   }
718c4762a1bSJed Brown   PetscFunctionReturn(0);
719c4762a1bSJed Brown }
720c4762a1bSJed Brown 
721c4762a1bSJed Brown PetscErrorCode HyperbolicInitialize(AppCtx *user)
722c4762a1bSJed Brown {
723c4762a1bSJed Brown   PetscErrorCode ierr;
724c4762a1bSJed Brown   PetscInt       n,i,j,linear_index,istart,iend,iblock,lo,hi;
725c4762a1bSJed Brown   Vec            XX,YY,XXwork,YYwork,yi,uxi,ui,bc;
726c4762a1bSJed Brown   PetscReal      h,sum;
727c4762a1bSJed Brown   PetscScalar    hinv,neg_hinv,quarter=0.25,one=1.0,half_hinv,neg_half_hinv;
728c4762a1bSJed Brown   PetscScalar    vx,vy,zero=0.0;
729c4762a1bSJed Brown   IS             is_from_y,is_to_yi,is_from_u,is_to_uxi,is_to_uyi;
730c4762a1bSJed Brown 
731c4762a1bSJed Brown   PetscFunctionBegin;
732c4762a1bSJed Brown   user->jformed = PETSC_FALSE;
733c4762a1bSJed Brown   user->c_formed = PETSC_FALSE;
734c4762a1bSJed Brown 
735c4762a1bSJed Brown   user->ksp_its = 0;
736c4762a1bSJed Brown   user->ksp_its_initial = 0;
737c4762a1bSJed Brown 
738c4762a1bSJed Brown   n = user->mx * user->mx;
739c4762a1bSJed Brown 
740c4762a1bSJed Brown   h = 1.0/user->mx;
741c4762a1bSJed Brown   hinv = user->mx;
742c4762a1bSJed Brown   neg_hinv = -hinv;
743c4762a1bSJed Brown   half_hinv = hinv / 2.0;
744c4762a1bSJed Brown   neg_half_hinv = neg_hinv / 2.0;
745c4762a1bSJed Brown 
746c4762a1bSJed Brown   /* Generate Grad matrix */
747c4762a1bSJed Brown   ierr = MatCreate(PETSC_COMM_WORLD,&user->Grad);CHKERRQ(ierr);
748c4762a1bSJed Brown   ierr = MatSetSizes(user->Grad,PETSC_DECIDE,PETSC_DECIDE,2*n,n);CHKERRQ(ierr);
749c4762a1bSJed Brown   ierr = MatSetFromOptions(user->Grad);CHKERRQ(ierr);
750c4762a1bSJed Brown   ierr = MatMPIAIJSetPreallocation(user->Grad,3,NULL,3,NULL);CHKERRQ(ierr);
751c4762a1bSJed Brown   ierr = MatSeqAIJSetPreallocation(user->Grad,3,NULL);CHKERRQ(ierr);
752c4762a1bSJed Brown   ierr = MatGetOwnershipRange(user->Grad,&istart,&iend);CHKERRQ(ierr);
753c4762a1bSJed Brown 
754c4762a1bSJed Brown   for (i=istart; i<iend; i++) {
755c4762a1bSJed Brown     if (i<n) {
756c4762a1bSJed Brown       iblock = i / user->mx;
757c4762a1bSJed Brown       j = iblock*user->mx + ((i+user->mx-1) % user->mx);
758c4762a1bSJed Brown       ierr = MatSetValues(user->Grad,1,&i,1,&j,&half_hinv,INSERT_VALUES);CHKERRQ(ierr);
759c4762a1bSJed Brown       j = iblock*user->mx + ((i+1) % user->mx);
760c4762a1bSJed Brown       ierr = MatSetValues(user->Grad,1,&i,1,&j,&neg_half_hinv,INSERT_VALUES);CHKERRQ(ierr);
761c4762a1bSJed Brown     }
762c4762a1bSJed Brown     if (i>=n) {
763c4762a1bSJed Brown       j = (i - user->mx) % n;
764c4762a1bSJed Brown       ierr = MatSetValues(user->Grad,1,&i,1,&j,&half_hinv,INSERT_VALUES);CHKERRQ(ierr);
765c4762a1bSJed Brown       j = (j + 2*user->mx) % n;
766c4762a1bSJed Brown       ierr = MatSetValues(user->Grad,1,&i,1,&j,&neg_half_hinv,INSERT_VALUES);CHKERRQ(ierr);
767c4762a1bSJed Brown     }
768c4762a1bSJed Brown   }
769c4762a1bSJed Brown 
770c4762a1bSJed Brown   ierr = MatAssemblyBegin(user->Grad,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
771c4762a1bSJed Brown   ierr = MatAssemblyEnd(user->Grad,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
772c4762a1bSJed Brown 
773c4762a1bSJed Brown   ierr = MatCreate(PETSC_COMM_WORLD,&user->Gradxy[0]);CHKERRQ(ierr);
774c4762a1bSJed Brown   ierr = MatSetSizes(user->Gradxy[0],PETSC_DECIDE,PETSC_DECIDE,n,n);CHKERRQ(ierr);
775c4762a1bSJed Brown   ierr = MatSetFromOptions(user->Gradxy[0]);CHKERRQ(ierr);
776c4762a1bSJed Brown   ierr = MatMPIAIJSetPreallocation(user->Gradxy[0],3,NULL,3,NULL);CHKERRQ(ierr);
777c4762a1bSJed Brown   ierr = MatSeqAIJSetPreallocation(user->Gradxy[0],3,NULL);CHKERRQ(ierr);
778c4762a1bSJed Brown   ierr = MatGetOwnershipRange(user->Gradxy[0],&istart,&iend);CHKERRQ(ierr);
779c4762a1bSJed Brown 
780c4762a1bSJed Brown   for (i=istart; i<iend; i++) {
781c4762a1bSJed Brown     iblock = i / user->mx;
782c4762a1bSJed Brown     j = iblock*user->mx + ((i+user->mx-1) % user->mx);
783c4762a1bSJed Brown     ierr = MatSetValues(user->Gradxy[0],1,&i,1,&j,&half_hinv,INSERT_VALUES);CHKERRQ(ierr);
784c4762a1bSJed Brown     j = iblock*user->mx + ((i+1) % user->mx);
785c4762a1bSJed Brown     ierr = MatSetValues(user->Gradxy[0],1,&i,1,&j,&neg_half_hinv,INSERT_VALUES);CHKERRQ(ierr);
786c4762a1bSJed Brown     ierr = MatSetValues(user->Gradxy[0],1,&i,1,&i,&zero,INSERT_VALUES);CHKERRQ(ierr);
787c4762a1bSJed Brown   }
788c4762a1bSJed Brown   ierr = MatAssemblyBegin(user->Gradxy[0],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
789c4762a1bSJed Brown   ierr = MatAssemblyEnd(user->Gradxy[0],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
790c4762a1bSJed Brown 
791c4762a1bSJed Brown   ierr = MatCreate(PETSC_COMM_WORLD,&user->Gradxy[1]);CHKERRQ(ierr);
792c4762a1bSJed Brown   ierr = MatSetSizes(user->Gradxy[1],PETSC_DECIDE,PETSC_DECIDE,n,n);CHKERRQ(ierr);
793c4762a1bSJed Brown   ierr = MatSetFromOptions(user->Gradxy[1]);CHKERRQ(ierr);
794c4762a1bSJed Brown   ierr = MatMPIAIJSetPreallocation(user->Gradxy[1],3,NULL,3,NULL);CHKERRQ(ierr);
795c4762a1bSJed Brown   ierr = MatSeqAIJSetPreallocation(user->Gradxy[1],3,NULL);CHKERRQ(ierr);
796c4762a1bSJed Brown   ierr = MatGetOwnershipRange(user->Gradxy[1],&istart,&iend);CHKERRQ(ierr);
797c4762a1bSJed Brown 
798c4762a1bSJed Brown   for (i=istart; i<iend; i++) {
799c4762a1bSJed Brown     j = (i + n - user->mx) % n;
800c4762a1bSJed Brown     ierr = MatSetValues(user->Gradxy[1],1,&i,1,&j,&half_hinv,INSERT_VALUES);CHKERRQ(ierr);
801c4762a1bSJed Brown     j = (j + 2*user->mx) % n;
802c4762a1bSJed Brown     ierr = MatSetValues(user->Gradxy[1],1,&i,1,&j,&neg_half_hinv,INSERT_VALUES);CHKERRQ(ierr);
803c4762a1bSJed Brown     ierr = MatSetValues(user->Gradxy[1],1,&i,1,&i,&zero,INSERT_VALUES);CHKERRQ(ierr);
804c4762a1bSJed Brown   }
805c4762a1bSJed Brown   ierr = MatAssemblyBegin(user->Gradxy[1],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
806c4762a1bSJed Brown   ierr = MatAssemblyEnd(user->Gradxy[1],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
807c4762a1bSJed Brown 
808c4762a1bSJed Brown   /* Generate Div matrix */
809c4762a1bSJed Brown   ierr = MatTranspose(user->Grad,MAT_INITIAL_MATRIX,&user->Div);CHKERRQ(ierr);
810c4762a1bSJed Brown   ierr = MatTranspose(user->Gradxy[0],MAT_INITIAL_MATRIX,&user->Divxy[0]);CHKERRQ(ierr);
811c4762a1bSJed Brown   ierr = MatTranspose(user->Gradxy[1],MAT_INITIAL_MATRIX,&user->Divxy[1]);CHKERRQ(ierr);
812c4762a1bSJed Brown 
813c4762a1bSJed Brown   /* Off-diagonal averaging matrix */
814c4762a1bSJed Brown   ierr = MatCreate(PETSC_COMM_WORLD,&user->M);CHKERRQ(ierr);
815c4762a1bSJed Brown   ierr = MatSetSizes(user->M,PETSC_DECIDE,PETSC_DECIDE,n,n);CHKERRQ(ierr);
816c4762a1bSJed Brown   ierr = MatSetFromOptions(user->M);CHKERRQ(ierr);
817c4762a1bSJed Brown   ierr = MatMPIAIJSetPreallocation(user->M,4,NULL,4,NULL);CHKERRQ(ierr);
818c4762a1bSJed Brown   ierr = MatSeqAIJSetPreallocation(user->M,4,NULL);CHKERRQ(ierr);
819c4762a1bSJed Brown   ierr = MatGetOwnershipRange(user->M,&istart,&iend);CHKERRQ(ierr);
820c4762a1bSJed Brown 
821c4762a1bSJed Brown   for (i=istart; i<iend; i++) {
822c4762a1bSJed Brown     /* kron(Id,Av) */
823c4762a1bSJed Brown     iblock = i / user->mx;
824c4762a1bSJed Brown     j = iblock*user->mx + ((i+user->mx-1) % user->mx);
825c4762a1bSJed Brown     ierr = MatSetValues(user->M,1,&i,1,&j,&quarter,INSERT_VALUES);CHKERRQ(ierr);
826c4762a1bSJed Brown     j = iblock*user->mx + ((i+1) % user->mx);
827c4762a1bSJed Brown     ierr = MatSetValues(user->M,1,&i,1,&j,&quarter,INSERT_VALUES);CHKERRQ(ierr);
828c4762a1bSJed Brown 
829c4762a1bSJed Brown     /* kron(Av,Id) */
830c4762a1bSJed Brown     j = (i + user->mx) % n;
831c4762a1bSJed Brown     ierr = MatSetValues(user->M,1,&i,1,&j,&quarter,INSERT_VALUES);CHKERRQ(ierr);
832c4762a1bSJed Brown     j = (i + n - user->mx) % n;
833c4762a1bSJed Brown     ierr = MatSetValues(user->M,1,&i,1,&j,&quarter,INSERT_VALUES);CHKERRQ(ierr);
834c4762a1bSJed Brown   }
835c4762a1bSJed Brown   ierr = MatAssemblyBegin(user->M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
836c4762a1bSJed Brown   ierr = MatAssemblyEnd(user->M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
837c4762a1bSJed Brown 
838c4762a1bSJed Brown   /* Generate 2D grid */
839c4762a1bSJed Brown   ierr = VecCreate(PETSC_COMM_WORLD,&XX);CHKERRQ(ierr);
840c4762a1bSJed Brown   ierr = VecCreate(PETSC_COMM_WORLD,&user->q);CHKERRQ(ierr);
841c4762a1bSJed Brown   ierr = VecSetSizes(XX,PETSC_DECIDE,n);CHKERRQ(ierr);
842c4762a1bSJed Brown   ierr = VecSetSizes(user->q,PETSC_DECIDE,n*user->nt);CHKERRQ(ierr);
843c4762a1bSJed Brown   ierr = VecSetFromOptions(XX);CHKERRQ(ierr);
844c4762a1bSJed Brown   ierr = VecSetFromOptions(user->q);CHKERRQ(ierr);
845c4762a1bSJed Brown 
846c4762a1bSJed Brown   ierr = VecDuplicate(XX,&YY);CHKERRQ(ierr);
847c4762a1bSJed Brown   ierr = VecDuplicate(XX,&XXwork);CHKERRQ(ierr);
848c4762a1bSJed Brown   ierr = VecDuplicate(XX,&YYwork);CHKERRQ(ierr);
849c4762a1bSJed Brown   ierr = VecDuplicate(XX,&user->d);CHKERRQ(ierr);
850c4762a1bSJed Brown   ierr = VecDuplicate(XX,&user->dwork);CHKERRQ(ierr);
851c4762a1bSJed Brown 
852c4762a1bSJed Brown   ierr = VecGetOwnershipRange(XX,&istart,&iend);CHKERRQ(ierr);
853c4762a1bSJed Brown   for (linear_index=istart; linear_index<iend; linear_index++) {
854c4762a1bSJed Brown     i = linear_index % user->mx;
855c4762a1bSJed Brown     j = (linear_index-i)/user->mx;
856c4762a1bSJed Brown     vx = h*(i+0.5);
857c4762a1bSJed Brown     vy = h*(j+0.5);
858c4762a1bSJed Brown     ierr = VecSetValues(XX,1,&linear_index,&vx,INSERT_VALUES);CHKERRQ(ierr);
859c4762a1bSJed Brown     ierr = VecSetValues(YY,1,&linear_index,&vy,INSERT_VALUES);CHKERRQ(ierr);
860c4762a1bSJed Brown   }
861c4762a1bSJed Brown 
862c4762a1bSJed Brown   ierr = VecAssemblyBegin(XX);CHKERRQ(ierr);
863c4762a1bSJed Brown   ierr = VecAssemblyEnd(XX);CHKERRQ(ierr);
864c4762a1bSJed Brown   ierr = VecAssemblyBegin(YY);CHKERRQ(ierr);
865c4762a1bSJed Brown   ierr = VecAssemblyEnd(YY);CHKERRQ(ierr);
866c4762a1bSJed Brown 
867c4762a1bSJed Brown   /* Compute final density function yT
868c4762a1bSJed Brown      yT = 1.0 + exp(-30*((x-0.25)^2+(y-0.25)^2)) + exp(-30*((x-0.75)^2+(y-0.75)^2))
869c4762a1bSJed Brown      yT = yT / (h^2*sum(yT)) */
870c4762a1bSJed Brown   ierr = VecCopy(XX,XXwork);CHKERRQ(ierr);
871c4762a1bSJed Brown   ierr = VecCopy(YY,YYwork);CHKERRQ(ierr);
872c4762a1bSJed Brown 
873c4762a1bSJed Brown   ierr = VecShift(XXwork,-0.25);CHKERRQ(ierr);
874c4762a1bSJed Brown   ierr = VecShift(YYwork,-0.25);CHKERRQ(ierr);
875c4762a1bSJed Brown 
876c4762a1bSJed Brown   ierr = VecPointwiseMult(XXwork,XXwork,XXwork);CHKERRQ(ierr);
877c4762a1bSJed Brown   ierr = VecPointwiseMult(YYwork,YYwork,YYwork);CHKERRQ(ierr);
878c4762a1bSJed Brown 
879c4762a1bSJed Brown   ierr = VecCopy(XXwork,user->dwork);CHKERRQ(ierr);
880c4762a1bSJed Brown   ierr = VecAXPY(user->dwork,1.0,YYwork);CHKERRQ(ierr);
881c4762a1bSJed Brown   ierr = VecScale(user->dwork,-30.0);CHKERRQ(ierr);
882c4762a1bSJed Brown   ierr = VecExp(user->dwork);CHKERRQ(ierr);
883c4762a1bSJed Brown   ierr = VecCopy(user->dwork,user->d);CHKERRQ(ierr);
884c4762a1bSJed Brown 
885c4762a1bSJed Brown   ierr = VecCopy(XX,XXwork);CHKERRQ(ierr);
886c4762a1bSJed Brown   ierr = VecCopy(YY,YYwork);CHKERRQ(ierr);
887c4762a1bSJed Brown 
888c4762a1bSJed Brown   ierr = VecShift(XXwork,-0.75);CHKERRQ(ierr);
889c4762a1bSJed Brown   ierr = VecShift(YYwork,-0.75);CHKERRQ(ierr);
890c4762a1bSJed Brown 
891c4762a1bSJed Brown   ierr = VecPointwiseMult(XXwork,XXwork,XXwork);CHKERRQ(ierr);
892c4762a1bSJed Brown   ierr = VecPointwiseMult(YYwork,YYwork,YYwork);CHKERRQ(ierr);
893c4762a1bSJed Brown 
894c4762a1bSJed Brown   ierr = VecCopy(XXwork,user->dwork);CHKERRQ(ierr);
895c4762a1bSJed Brown   ierr = VecAXPY(user->dwork,1.0,YYwork);CHKERRQ(ierr);
896c4762a1bSJed Brown   ierr = VecScale(user->dwork,-30.0);CHKERRQ(ierr);
897c4762a1bSJed Brown   ierr = VecExp(user->dwork);CHKERRQ(ierr);
898c4762a1bSJed Brown 
899c4762a1bSJed Brown   ierr = VecAXPY(user->d,1.0,user->dwork);CHKERRQ(ierr);
900c4762a1bSJed Brown   ierr = VecShift(user->d,1.0);CHKERRQ(ierr);
901c4762a1bSJed Brown   ierr = VecSum(user->d,&sum);CHKERRQ(ierr);
902c4762a1bSJed Brown   ierr = VecScale(user->d,1.0/(h*h*sum));CHKERRQ(ierr);
903c4762a1bSJed Brown 
904c4762a1bSJed Brown   /* Initial conditions of forward problem */
905c4762a1bSJed Brown   ierr = VecDuplicate(XX,&bc);CHKERRQ(ierr);
906c4762a1bSJed Brown   ierr = VecCopy(XX,XXwork);CHKERRQ(ierr);
907c4762a1bSJed Brown   ierr = VecCopy(YY,YYwork);CHKERRQ(ierr);
908c4762a1bSJed Brown 
909c4762a1bSJed Brown   ierr = VecShift(XXwork,-0.5);CHKERRQ(ierr);
910c4762a1bSJed Brown   ierr = VecShift(YYwork,-0.5);CHKERRQ(ierr);
911c4762a1bSJed Brown 
912c4762a1bSJed Brown   ierr = VecPointwiseMult(XXwork,XXwork,XXwork);CHKERRQ(ierr);
913c4762a1bSJed Brown   ierr = VecPointwiseMult(YYwork,YYwork,YYwork);CHKERRQ(ierr);
914c4762a1bSJed Brown 
915c4762a1bSJed Brown   ierr = VecWAXPY(bc,1.0,XXwork,YYwork);CHKERRQ(ierr);
916c4762a1bSJed Brown   ierr = VecScale(bc,-50.0);CHKERRQ(ierr);
917c4762a1bSJed Brown   ierr = VecExp(bc);CHKERRQ(ierr);
918c4762a1bSJed Brown   ierr = VecShift(bc,1.0);CHKERRQ(ierr);
919c4762a1bSJed Brown   ierr = VecSum(bc,&sum);CHKERRQ(ierr);
920c4762a1bSJed Brown   ierr = VecScale(bc,1.0/(h*h*sum));CHKERRQ(ierr);
921c4762a1bSJed Brown 
922c4762a1bSJed Brown   /* Create scatter from y to y_1,y_2,...,y_nt */
923c4762a1bSJed Brown   /*  TODO: Reorder for better parallelism. (This will require reordering Q and L as well.) */
924c4762a1bSJed Brown   ierr = PetscMalloc1(user->nt*user->mx*user->mx,&user->yi_scatter);CHKERRQ(ierr);
925c4762a1bSJed Brown   ierr = VecCreate(PETSC_COMM_WORLD,&yi);CHKERRQ(ierr);
926c4762a1bSJed Brown   ierr = VecSetSizes(yi,PETSC_DECIDE,user->mx*user->mx);CHKERRQ(ierr);
927c4762a1bSJed Brown   ierr = VecSetFromOptions(yi);CHKERRQ(ierr);
928c4762a1bSJed Brown   ierr = VecDuplicateVecs(yi,user->nt,&user->yi);CHKERRQ(ierr);
929c4762a1bSJed Brown   ierr = VecDuplicateVecs(yi,user->nt,&user->yiwork);CHKERRQ(ierr);
930c4762a1bSJed Brown   ierr = VecDuplicateVecs(yi,user->nt,&user->ziwork);CHKERRQ(ierr);
931c4762a1bSJed Brown   for (i=0; i<user->nt; i++) {
932c4762a1bSJed Brown     ierr = VecGetOwnershipRange(user->yi[i],&lo,&hi);CHKERRQ(ierr);
933c4762a1bSJed Brown     ierr = ISCreateStride(PETSC_COMM_SELF,hi-lo,lo,1,&is_to_yi);CHKERRQ(ierr);
934c4762a1bSJed Brown     ierr = ISCreateStride(PETSC_COMM_SELF,hi-lo,lo+i*user->mx*user->mx,1,&is_from_y);CHKERRQ(ierr);
935c4762a1bSJed Brown     ierr = VecScatterCreate(user->y,is_from_y,user->yi[i],is_to_yi,&user->yi_scatter[i]);CHKERRQ(ierr);
936c4762a1bSJed Brown     ierr = ISDestroy(&is_to_yi);CHKERRQ(ierr);
937c4762a1bSJed Brown     ierr = ISDestroy(&is_from_y);CHKERRQ(ierr);
938c4762a1bSJed Brown   }
939c4762a1bSJed Brown 
940c4762a1bSJed Brown   /* Create scatter from u to ux_1,uy_1,ux_2,uy_2,...,ux_nt,uy_nt */
941c4762a1bSJed Brown   /*  TODO: reorder for better parallelism */
942c4762a1bSJed Brown   ierr = PetscMalloc1(user->nt*user->mx*user->mx,&user->uxi_scatter);CHKERRQ(ierr);
943c4762a1bSJed Brown   ierr = PetscMalloc1(user->nt*user->mx*user->mx,&user->uyi_scatter);CHKERRQ(ierr);
944c4762a1bSJed Brown   ierr = PetscMalloc1(user->nt*user->mx*user->mx,&user->ux_scatter);CHKERRQ(ierr);
945c4762a1bSJed Brown   ierr = PetscMalloc1(user->nt*user->mx*user->mx,&user->uy_scatter);CHKERRQ(ierr);
946c4762a1bSJed Brown   ierr = PetscMalloc1(2*user->nt*user->mx*user->mx,&user->ui_scatter);CHKERRQ(ierr);
947c4762a1bSJed Brown   ierr = VecCreate(PETSC_COMM_WORLD,&uxi);CHKERRQ(ierr);
948c4762a1bSJed Brown   ierr = VecCreate(PETSC_COMM_WORLD,&ui);CHKERRQ(ierr);
949c4762a1bSJed Brown   ierr = VecSetSizes(uxi,PETSC_DECIDE,user->mx*user->mx);CHKERRQ(ierr);
950c4762a1bSJed Brown   ierr = VecSetSizes(ui,PETSC_DECIDE,2*user->mx*user->mx);CHKERRQ(ierr);
951c4762a1bSJed Brown   ierr = VecSetFromOptions(uxi);CHKERRQ(ierr);
952c4762a1bSJed Brown   ierr = VecSetFromOptions(ui);CHKERRQ(ierr);
953c4762a1bSJed Brown   ierr = VecDuplicateVecs(uxi,user->nt,&user->uxi);CHKERRQ(ierr);
954c4762a1bSJed Brown   ierr = VecDuplicateVecs(uxi,user->nt,&user->uyi);CHKERRQ(ierr);
955c4762a1bSJed Brown   ierr = VecDuplicateVecs(uxi,user->nt,&user->uxiwork);CHKERRQ(ierr);
956c4762a1bSJed Brown   ierr = VecDuplicateVecs(uxi,user->nt,&user->uyiwork);CHKERRQ(ierr);
957c4762a1bSJed Brown   ierr = VecDuplicateVecs(ui,user->nt,&user->ui);CHKERRQ(ierr);
958c4762a1bSJed Brown   ierr = VecDuplicateVecs(ui,user->nt,&user->uiwork);CHKERRQ(ierr);
959c4762a1bSJed Brown   for (i=0; i<user->nt; i++) {
960c4762a1bSJed Brown     ierr = VecGetOwnershipRange(user->uxi[i],&lo,&hi);CHKERRQ(ierr);
961c4762a1bSJed Brown     ierr = ISCreateStride(PETSC_COMM_SELF,hi-lo,lo,1,&is_to_uxi);CHKERRQ(ierr);
962c4762a1bSJed Brown     ierr = ISCreateStride(PETSC_COMM_SELF,hi-lo,lo+2*i*user->mx*user->mx,1,&is_from_u);CHKERRQ(ierr);
963c4762a1bSJed Brown     ierr = VecScatterCreate(user->u,is_from_u,user->uxi[i],is_to_uxi,&user->uxi_scatter[i]);CHKERRQ(ierr);
964c4762a1bSJed Brown 
965c4762a1bSJed Brown     ierr = ISDestroy(&is_to_uxi);CHKERRQ(ierr);
966c4762a1bSJed Brown     ierr = ISDestroy(&is_from_u);CHKERRQ(ierr);
967c4762a1bSJed Brown 
968c4762a1bSJed Brown     ierr = VecGetOwnershipRange(user->uyi[i],&lo,&hi);CHKERRQ(ierr);
969c4762a1bSJed Brown     ierr = ISCreateStride(PETSC_COMM_SELF,hi-lo,lo,1,&is_to_uyi);CHKERRQ(ierr);
970c4762a1bSJed Brown     ierr = ISCreateStride(PETSC_COMM_SELF,hi-lo,lo+(2*i+1)*user->mx*user->mx,1,&is_from_u);CHKERRQ(ierr);
971c4762a1bSJed Brown     ierr = VecScatterCreate(user->u,is_from_u,user->uyi[i],is_to_uyi,&user->uyi_scatter[i]);CHKERRQ(ierr);
972c4762a1bSJed Brown 
973c4762a1bSJed Brown     ierr = ISDestroy(&is_to_uyi);CHKERRQ(ierr);
974c4762a1bSJed Brown     ierr = ISDestroy(&is_from_u);CHKERRQ(ierr);
975c4762a1bSJed Brown 
976c4762a1bSJed Brown     ierr = VecGetOwnershipRange(user->uxi[i],&lo,&hi);CHKERRQ(ierr);
977c4762a1bSJed Brown     ierr = ISCreateStride(PETSC_COMM_SELF,hi-lo,lo,1,&is_to_uxi);CHKERRQ(ierr);
978c4762a1bSJed Brown     ierr = ISCreateStride(PETSC_COMM_SELF,hi-lo,lo,1,&is_from_u);CHKERRQ(ierr);
979c4762a1bSJed Brown     ierr = VecScatterCreate(user->ui[i],is_from_u,user->uxi[i],is_to_uxi,&user->ux_scatter[i]);CHKERRQ(ierr);
980c4762a1bSJed Brown 
981c4762a1bSJed Brown     ierr = ISDestroy(&is_to_uxi);CHKERRQ(ierr);
982c4762a1bSJed Brown     ierr = ISDestroy(&is_from_u);CHKERRQ(ierr);
983c4762a1bSJed Brown 
984c4762a1bSJed Brown     ierr = VecGetOwnershipRange(user->uyi[i],&lo,&hi);CHKERRQ(ierr);
985c4762a1bSJed Brown     ierr = ISCreateStride(PETSC_COMM_SELF,hi-lo,lo,1,&is_to_uyi);CHKERRQ(ierr);
986c4762a1bSJed Brown     ierr = ISCreateStride(PETSC_COMM_SELF,hi-lo,lo+user->mx*user->mx,1,&is_from_u);CHKERRQ(ierr);
987c4762a1bSJed Brown     ierr = VecScatterCreate(user->ui[i],is_from_u,user->uyi[i],is_to_uyi,&user->uy_scatter[i]);CHKERRQ(ierr);
988c4762a1bSJed Brown 
989c4762a1bSJed Brown     ierr = ISDestroy(&is_to_uyi);CHKERRQ(ierr);
990c4762a1bSJed Brown     ierr = ISDestroy(&is_from_u);CHKERRQ(ierr);
991c4762a1bSJed Brown 
992c4762a1bSJed Brown     ierr = VecGetOwnershipRange(user->ui[i],&lo,&hi);CHKERRQ(ierr);
993c4762a1bSJed Brown     ierr = ISCreateStride(PETSC_COMM_SELF,hi-lo,lo,1,&is_to_uxi);CHKERRQ(ierr);
994c4762a1bSJed Brown     ierr = ISCreateStride(PETSC_COMM_SELF,hi-lo,lo+2*i*user->mx*user->mx,1,&is_from_u);CHKERRQ(ierr);
995c4762a1bSJed Brown     ierr = VecScatterCreate(user->u,is_from_u,user->ui[i],is_to_uxi,&user->ui_scatter[i]);CHKERRQ(ierr);
996c4762a1bSJed Brown 
997c4762a1bSJed Brown     ierr = ISDestroy(&is_to_uxi);CHKERRQ(ierr);
998c4762a1bSJed Brown     ierr = ISDestroy(&is_from_u);CHKERRQ(ierr);
999c4762a1bSJed Brown   }
1000c4762a1bSJed Brown 
1001c4762a1bSJed Brown   /* RHS of forward problem */
1002c4762a1bSJed Brown   ierr = MatMult(user->M,bc,user->yiwork[0]);CHKERRQ(ierr);
1003c4762a1bSJed Brown   for (i=1; i<user->nt; i++) {
1004c4762a1bSJed Brown     ierr = VecSet(user->yiwork[i],0.0);CHKERRQ(ierr);
1005c4762a1bSJed Brown   }
1006c4762a1bSJed Brown   ierr = Gather_yi(user->q,user->yiwork,user->yi_scatter,user->nt);CHKERRQ(ierr);
1007c4762a1bSJed Brown 
1008c4762a1bSJed Brown   /* Compute true velocity field utrue */
1009c4762a1bSJed Brown   ierr = VecDuplicate(user->u,&user->utrue);CHKERRQ(ierr);
1010c4762a1bSJed Brown   for (i=0; i<user->nt; i++) {
1011c4762a1bSJed Brown     ierr = VecCopy(YY,user->uxi[i]);CHKERRQ(ierr);
1012c4762a1bSJed Brown     ierr = VecScale(user->uxi[i],150.0*i*user->ht);CHKERRQ(ierr);
1013c4762a1bSJed Brown     ierr = VecCopy(XX,user->uyi[i]);CHKERRQ(ierr);
1014c4762a1bSJed Brown     ierr = VecShift(user->uyi[i],-10.0);CHKERRQ(ierr);
1015c4762a1bSJed Brown     ierr = VecScale(user->uyi[i],15.0*i*user->ht);CHKERRQ(ierr);
1016c4762a1bSJed Brown   }
1017c4762a1bSJed Brown   ierr = Gather_uxi_uyi(user->utrue,user->uxi,user->uxi_scatter,user->uyi,user->uyi_scatter,user->nt);CHKERRQ(ierr);
1018c4762a1bSJed Brown 
1019c4762a1bSJed Brown   /* Initial guess and reference model */
1020c4762a1bSJed Brown   ierr = VecDuplicate(user->utrue,&user->ur);CHKERRQ(ierr);
1021c4762a1bSJed Brown   for (i=0; i<user->nt; i++) {
1022c4762a1bSJed Brown     ierr = VecCopy(XX,user->uxi[i]);CHKERRQ(ierr);
1023c4762a1bSJed Brown     ierr = VecShift(user->uxi[i],i*user->ht);CHKERRQ(ierr);
1024c4762a1bSJed Brown     ierr = VecCopy(YY,user->uyi[i]);CHKERRQ(ierr);
1025c4762a1bSJed Brown     ierr = VecShift(user->uyi[i],-i*user->ht);CHKERRQ(ierr);
1026c4762a1bSJed Brown   }
1027c4762a1bSJed Brown   ierr = Gather_uxi_uyi(user->ur,user->uxi,user->uxi_scatter,user->uyi,user->uyi_scatter,user->nt);CHKERRQ(ierr);
1028c4762a1bSJed Brown 
1029c4762a1bSJed Brown   /* Generate regularization matrix L */
1030c4762a1bSJed Brown   ierr = MatCreate(PETSC_COMM_WORLD,&user->LT);CHKERRQ(ierr);
1031c4762a1bSJed Brown   ierr = MatSetSizes(user->LT,PETSC_DECIDE,PETSC_DECIDE,2*n*user->nt,n*user->nt);CHKERRQ(ierr);
1032c4762a1bSJed Brown   ierr = MatSetFromOptions(user->LT);CHKERRQ(ierr);
1033c4762a1bSJed Brown   ierr = MatMPIAIJSetPreallocation(user->LT,1,NULL,1,NULL);CHKERRQ(ierr);
1034c4762a1bSJed Brown   ierr = MatSeqAIJSetPreallocation(user->LT,1,NULL);CHKERRQ(ierr);
1035c4762a1bSJed Brown   ierr = MatGetOwnershipRange(user->LT,&istart,&iend);CHKERRQ(ierr);
1036c4762a1bSJed Brown 
1037c4762a1bSJed Brown   for (i=istart; i<iend; i++) {
1038c4762a1bSJed Brown     iblock = (i+n) / (2*n);
1039c4762a1bSJed Brown     j = i - iblock*n;
1040c4762a1bSJed Brown     ierr = MatSetValues(user->LT,1,&i,1,&j,&user->gamma,INSERT_VALUES);CHKERRQ(ierr);
1041c4762a1bSJed Brown   }
1042c4762a1bSJed Brown 
1043c4762a1bSJed Brown   ierr = MatAssemblyBegin(user->LT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1044c4762a1bSJed Brown   ierr = MatAssemblyEnd(user->LT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1045c4762a1bSJed Brown 
1046c4762a1bSJed Brown   ierr = MatTranspose(user->LT,MAT_INITIAL_MATRIX,&user->L);CHKERRQ(ierr);
1047c4762a1bSJed Brown 
1048c4762a1bSJed Brown   /* Build work vectors and matrices */
1049c4762a1bSJed Brown   ierr = VecCreate(PETSC_COMM_WORLD,&user->lwork);CHKERRQ(ierr);
1050c4762a1bSJed Brown   ierr = VecSetType(user->lwork,VECMPI);CHKERRQ(ierr);
1051c4762a1bSJed Brown   ierr = VecSetSizes(user->lwork,PETSC_DECIDE,user->m);CHKERRQ(ierr);
1052c4762a1bSJed Brown   ierr = VecSetFromOptions(user->lwork);CHKERRQ(ierr);
1053c4762a1bSJed Brown 
1054c4762a1bSJed Brown   ierr = MatDuplicate(user->Div,MAT_SHARE_NONZERO_PATTERN,&user->Divwork);CHKERRQ(ierr);
1055c4762a1bSJed Brown 
1056c4762a1bSJed Brown   ierr = VecDuplicate(user->y,&user->ywork);CHKERRQ(ierr);
1057c4762a1bSJed Brown   ierr = VecDuplicate(user->u,&user->uwork);CHKERRQ(ierr);
1058c4762a1bSJed Brown   ierr = VecDuplicate(user->u,&user->vwork);CHKERRQ(ierr);
1059c4762a1bSJed Brown   ierr = VecDuplicate(user->u,&user->js_diag);CHKERRQ(ierr);
1060c4762a1bSJed Brown   ierr = VecDuplicate(user->c,&user->cwork);CHKERRQ(ierr);
1061c4762a1bSJed Brown 
1062c4762a1bSJed Brown   /* Create matrix-free shell user->Js for computing A*x */
1063c4762a1bSJed Brown   ierr = MatCreateShell(PETSC_COMM_WORLD,PETSC_DETERMINE,PETSC_DETERMINE,user->m,user->m,user,&user->Js);CHKERRQ(ierr);
1064c4762a1bSJed Brown   ierr = MatShellSetOperation(user->Js,MATOP_MULT,(void(*)(void))StateMatMult);CHKERRQ(ierr);
1065c4762a1bSJed Brown   ierr = MatShellSetOperation(user->Js,MATOP_DUPLICATE,(void(*)(void))StateMatDuplicate);CHKERRQ(ierr);
1066c4762a1bSJed Brown   ierr = MatShellSetOperation(user->Js,MATOP_MULT_TRANSPOSE,(void(*)(void))StateMatMultTranspose);CHKERRQ(ierr);
1067c4762a1bSJed Brown   ierr = MatShellSetOperation(user->Js,MATOP_GET_DIAGONAL,(void(*)(void))StateMatGetDiagonal);CHKERRQ(ierr);
1068c4762a1bSJed Brown 
1069c4762a1bSJed Brown   /* Diagonal blocks of user->Js */
1070c4762a1bSJed Brown   ierr = MatCreateShell(PETSC_COMM_WORLD,PETSC_DETERMINE,PETSC_DETERMINE,n,n,user,&user->JsBlock);CHKERRQ(ierr);
1071c4762a1bSJed Brown   ierr = MatShellSetOperation(user->JsBlock,MATOP_MULT,(void(*)(void))StateMatBlockMult);CHKERRQ(ierr);
1072c4762a1bSJed Brown   ierr = MatShellSetOperation(user->JsBlock,MATOP_MULT_TRANSPOSE,(void(*)(void))StateMatBlockMultTranspose);CHKERRQ(ierr);
1073c4762a1bSJed Brown 
1074c4762a1bSJed Brown   /* Create a matrix-free shell user->JsBlockPrec for computing (U+D)\D*(L+D)\x, where JsBlock = L+D+U,
1075c4762a1bSJed Brown      D is diagonal, L is strictly lower triangular, and U is strictly upper triangular.
1076c4762a1bSJed Brown      This is an SOR preconditioner for user->JsBlock. */
1077c4762a1bSJed Brown   ierr = MatCreateShell(PETSC_COMM_WORLD,PETSC_DETERMINE,PETSC_DETERMINE,n,n,user,&user->JsBlockPrec);CHKERRQ(ierr);
1078c4762a1bSJed Brown   ierr = MatShellSetOperation(user->JsBlockPrec,MATOP_MULT,(void(*)(void))StateMatBlockPrecMult);CHKERRQ(ierr);
1079c4762a1bSJed Brown   ierr = MatShellSetOperation(user->JsBlockPrec,MATOP_MULT_TRANSPOSE,(void(*)(void))StateMatBlockPrecMultTranspose);CHKERRQ(ierr);
1080c4762a1bSJed Brown 
1081c4762a1bSJed Brown   /* Create a matrix-free shell user->Jd for computing B*x */
1082c4762a1bSJed Brown   ierr = MatCreateShell(PETSC_COMM_WORLD,PETSC_DETERMINE,PETSC_DETERMINE,user->m,user->n-user->m,user,&user->Jd);CHKERRQ(ierr);
1083c4762a1bSJed Brown   ierr = MatShellSetOperation(user->Jd,MATOP_MULT,(void(*)(void))DesignMatMult);CHKERRQ(ierr);
1084c4762a1bSJed Brown   ierr = MatShellSetOperation(user->Jd,MATOP_MULT_TRANSPOSE,(void(*)(void))DesignMatMultTranspose);CHKERRQ(ierr);
1085c4762a1bSJed Brown 
1086c4762a1bSJed Brown   /* User-defined routines for computing user->Js\x and user->Js^T\x*/
1087c4762a1bSJed Brown   ierr = MatCreateShell(PETSC_COMM_WORLD,PETSC_DETERMINE,PETSC_DETERMINE,user->m,user->m,user,&user->JsInv);CHKERRQ(ierr);
1088c4762a1bSJed Brown   ierr = MatShellSetOperation(user->JsInv,MATOP_MULT,(void(*)(void))StateMatInvMult);CHKERRQ(ierr);
1089c4762a1bSJed Brown   ierr = MatShellSetOperation(user->JsInv,MATOP_MULT_TRANSPOSE,(void(*)(void))StateMatInvTransposeMult);CHKERRQ(ierr);
1090c4762a1bSJed Brown 
1091c4762a1bSJed Brown   /* Build matrices for SOR preconditioner */
1092c4762a1bSJed Brown   ierr = Scatter_uxi_uyi(user->u,user->uxi,user->uxi_scatter,user->uyi,user->uyi_scatter,user->nt);CHKERRQ(ierr);
1093c4762a1bSJed Brown   ierr = PetscMalloc1(5*n,&user->C);CHKERRQ(ierr);
1094c4762a1bSJed Brown   ierr = PetscMalloc1(2*n,&user->Cwork);CHKERRQ(ierr);
1095c4762a1bSJed Brown   for (i=0; i<user->nt; i++) {
1096c4762a1bSJed Brown     ierr = MatDuplicate(user->Divxy[0],MAT_COPY_VALUES,&user->C[i]);CHKERRQ(ierr);
1097c4762a1bSJed Brown     ierr = MatDuplicate(user->Divxy[1],MAT_COPY_VALUES,&user->Cwork[i]);CHKERRQ(ierr);
1098c4762a1bSJed Brown 
1099c4762a1bSJed Brown     ierr = MatDiagonalScale(user->C[i],NULL,user->uxi[i]);CHKERRQ(ierr);
1100c4762a1bSJed Brown     ierr = MatDiagonalScale(user->Cwork[i],NULL,user->uyi[i]);CHKERRQ(ierr);
1101c4762a1bSJed Brown     ierr = MatAXPY(user->C[i],1.0,user->Cwork[i],DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
1102c4762a1bSJed Brown     ierr = MatScale(user->C[i],user->ht);CHKERRQ(ierr);
1103c4762a1bSJed Brown     ierr = MatShift(user->C[i],1.0);CHKERRQ(ierr);
1104c4762a1bSJed Brown   }
1105c4762a1bSJed Brown 
1106c4762a1bSJed Brown   /* Solver options and tolerances */
1107c4762a1bSJed Brown   ierr = KSPCreate(PETSC_COMM_WORLD,&user->solver);CHKERRQ(ierr);
1108c4762a1bSJed Brown   ierr = KSPSetType(user->solver,KSPGMRES);CHKERRQ(ierr);
1109c4762a1bSJed Brown   ierr = KSPSetOperators(user->solver,user->JsBlock,user->JsBlockPrec);CHKERRQ(ierr);
1110c4762a1bSJed Brown   ierr = KSPSetTolerances(user->solver,1e-4,1e-20,1e3,500);CHKERRQ(ierr);
1111c4762a1bSJed Brown   /* ierr = KSPSetTolerances(user->solver,1e-8,1e-16,1e3,500);CHKERRQ(ierr); */
1112c4762a1bSJed Brown   ierr = KSPGetPC(user->solver,&user->prec);CHKERRQ(ierr);
1113c4762a1bSJed Brown   ierr = PCSetType(user->prec,PCSHELL);CHKERRQ(ierr);
1114c4762a1bSJed Brown 
1115c4762a1bSJed Brown   ierr = PCShellSetApply(user->prec,StateMatBlockPrecMult);CHKERRQ(ierr);
1116c4762a1bSJed Brown   ierr = PCShellSetApplyTranspose(user->prec,StateMatBlockPrecMultTranspose);CHKERRQ(ierr);
1117c4762a1bSJed Brown   ierr = PCShellSetContext(user->prec,user);CHKERRQ(ierr);
1118c4762a1bSJed Brown 
1119c4762a1bSJed Brown   /* Compute true state function yt given ut */
1120c4762a1bSJed Brown   ierr = VecCreate(PETSC_COMM_WORLD,&user->ytrue);CHKERRQ(ierr);
1121c4762a1bSJed Brown   ierr = VecSetSizes(user->ytrue,PETSC_DECIDE,n*user->nt);CHKERRQ(ierr);
1122c4762a1bSJed Brown   ierr = VecSetFromOptions(user->ytrue);CHKERRQ(ierr);
1123c4762a1bSJed Brown   user->c_formed = PETSC_TRUE;
1124c4762a1bSJed Brown   ierr = VecCopy(user->utrue,user->u);CHKERRQ(ierr); /*  Set u=utrue temporarily for StateMatInv */
1125c4762a1bSJed Brown   ierr = VecSet(user->ytrue,0.0);CHKERRQ(ierr); /*  Initial guess */
1126c4762a1bSJed Brown   ierr = StateMatInvMult(user->Js,user->q,user->ytrue);CHKERRQ(ierr);
1127c4762a1bSJed Brown   ierr = VecCopy(user->ur,user->u);CHKERRQ(ierr); /*  Reset u=ur */
1128c4762a1bSJed Brown 
1129c4762a1bSJed Brown   /* Initial guess y0 for state given u0 */
1130c4762a1bSJed Brown   ierr = StateMatInvMult(user->Js,user->q,user->y);CHKERRQ(ierr);
1131c4762a1bSJed Brown 
1132c4762a1bSJed Brown   /* Data discretization */
1133c4762a1bSJed Brown   ierr = MatCreate(PETSC_COMM_WORLD,&user->Q);CHKERRQ(ierr);
1134c4762a1bSJed Brown   ierr = MatSetSizes(user->Q,PETSC_DECIDE,PETSC_DECIDE,user->mx*user->mx,user->m);CHKERRQ(ierr);
1135c4762a1bSJed Brown   ierr = MatSetFromOptions(user->Q);CHKERRQ(ierr);
1136c4762a1bSJed Brown   ierr = MatMPIAIJSetPreallocation(user->Q,0,NULL,1,NULL);CHKERRQ(ierr);
1137c4762a1bSJed Brown   ierr = MatSeqAIJSetPreallocation(user->Q,1,NULL);CHKERRQ(ierr);
1138c4762a1bSJed Brown 
1139c4762a1bSJed Brown   ierr = MatGetOwnershipRange(user->Q,&istart,&iend);CHKERRQ(ierr);
1140c4762a1bSJed Brown 
1141c4762a1bSJed Brown   for (i=istart; i<iend; i++) {
1142c4762a1bSJed Brown     j = i + user->m - user->mx*user->mx;
1143c4762a1bSJed Brown     ierr = MatSetValues(user->Q,1,&i,1,&j,&one,INSERT_VALUES);CHKERRQ(ierr);
1144c4762a1bSJed Brown   }
1145c4762a1bSJed Brown 
1146c4762a1bSJed Brown   ierr = MatAssemblyBegin(user->Q,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1147c4762a1bSJed Brown   ierr = MatAssemblyEnd(user->Q,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1148c4762a1bSJed Brown 
1149c4762a1bSJed Brown   ierr = MatTranspose(user->Q,MAT_INITIAL_MATRIX,&user->QT);CHKERRQ(ierr);
1150c4762a1bSJed Brown 
1151c4762a1bSJed Brown   ierr = VecDestroy(&XX);CHKERRQ(ierr);
1152c4762a1bSJed Brown   ierr = VecDestroy(&YY);CHKERRQ(ierr);
1153c4762a1bSJed Brown   ierr = VecDestroy(&XXwork);CHKERRQ(ierr);
1154c4762a1bSJed Brown   ierr = VecDestroy(&YYwork);CHKERRQ(ierr);
1155c4762a1bSJed Brown   ierr = VecDestroy(&yi);CHKERRQ(ierr);
1156c4762a1bSJed Brown   ierr = VecDestroy(&uxi);CHKERRQ(ierr);
1157c4762a1bSJed Brown   ierr = VecDestroy(&ui);CHKERRQ(ierr);
1158c4762a1bSJed Brown   ierr = VecDestroy(&bc);CHKERRQ(ierr);
1159c4762a1bSJed Brown 
1160c4762a1bSJed Brown   /* Now that initial conditions have been set, let the user pass tolerance options to the KSP solver */
1161c4762a1bSJed Brown   ierr = KSPSetFromOptions(user->solver);CHKERRQ(ierr);
1162c4762a1bSJed Brown   PetscFunctionReturn(0);
1163c4762a1bSJed Brown }
1164c4762a1bSJed Brown 
1165c4762a1bSJed Brown PetscErrorCode HyperbolicDestroy(AppCtx *user)
1166c4762a1bSJed Brown {
1167c4762a1bSJed Brown   PetscErrorCode ierr;
1168c4762a1bSJed Brown   PetscInt       i;
1169c4762a1bSJed Brown 
1170c4762a1bSJed Brown   PetscFunctionBegin;
1171c4762a1bSJed Brown   ierr = MatDestroy(&user->Q);CHKERRQ(ierr);
1172c4762a1bSJed Brown   ierr = MatDestroy(&user->QT);CHKERRQ(ierr);
1173c4762a1bSJed Brown   ierr = MatDestroy(&user->Div);CHKERRQ(ierr);
1174c4762a1bSJed Brown   ierr = MatDestroy(&user->Divwork);CHKERRQ(ierr);
1175c4762a1bSJed Brown   ierr = MatDestroy(&user->Grad);CHKERRQ(ierr);
1176c4762a1bSJed Brown   ierr = MatDestroy(&user->L);CHKERRQ(ierr);
1177c4762a1bSJed Brown   ierr = MatDestroy(&user->LT);CHKERRQ(ierr);
1178c4762a1bSJed Brown   ierr = KSPDestroy(&user->solver);CHKERRQ(ierr);
1179c4762a1bSJed Brown   ierr = MatDestroy(&user->Js);CHKERRQ(ierr);
1180c4762a1bSJed Brown   ierr = MatDestroy(&user->Jd);CHKERRQ(ierr);
1181c4762a1bSJed Brown   ierr = MatDestroy(&user->JsBlockPrec);CHKERRQ(ierr);
1182c4762a1bSJed Brown   ierr = MatDestroy(&user->JsInv);CHKERRQ(ierr);
1183c4762a1bSJed Brown   ierr = MatDestroy(&user->JsBlock);CHKERRQ(ierr);
1184c4762a1bSJed Brown   ierr = MatDestroy(&user->Divxy[0]);CHKERRQ(ierr);
1185c4762a1bSJed Brown   ierr = MatDestroy(&user->Divxy[1]);CHKERRQ(ierr);
1186c4762a1bSJed Brown   ierr = MatDestroy(&user->Gradxy[0]);CHKERRQ(ierr);
1187c4762a1bSJed Brown   ierr = MatDestroy(&user->Gradxy[1]);CHKERRQ(ierr);
1188c4762a1bSJed Brown   ierr = MatDestroy(&user->M);CHKERRQ(ierr);
1189c4762a1bSJed Brown   for (i=0; i<user->nt; i++) {
1190c4762a1bSJed Brown     ierr = MatDestroy(&user->C[i]);CHKERRQ(ierr);
1191c4762a1bSJed Brown     ierr = MatDestroy(&user->Cwork[i]);CHKERRQ(ierr);
1192c4762a1bSJed Brown   }
1193c4762a1bSJed Brown   ierr = PetscFree(user->C);CHKERRQ(ierr);
1194c4762a1bSJed Brown   ierr = PetscFree(user->Cwork);CHKERRQ(ierr);
1195c4762a1bSJed Brown   ierr = VecDestroy(&user->u);CHKERRQ(ierr);
1196c4762a1bSJed Brown   ierr = VecDestroy(&user->uwork);CHKERRQ(ierr);
1197c4762a1bSJed Brown   ierr = VecDestroy(&user->vwork);CHKERRQ(ierr);
1198c4762a1bSJed Brown   ierr = VecDestroy(&user->utrue);CHKERRQ(ierr);
1199c4762a1bSJed Brown   ierr = VecDestroy(&user->y);CHKERRQ(ierr);
1200c4762a1bSJed Brown   ierr = VecDestroy(&user->ywork);CHKERRQ(ierr);
1201c4762a1bSJed Brown   ierr = VecDestroy(&user->ytrue);CHKERRQ(ierr);
1202c4762a1bSJed Brown   ierr = VecDestroyVecs(user->nt,&user->yi);CHKERRQ(ierr);
1203c4762a1bSJed Brown   ierr = VecDestroyVecs(user->nt,&user->yiwork);CHKERRQ(ierr);
1204c4762a1bSJed Brown   ierr = VecDestroyVecs(user->nt,&user->ziwork);CHKERRQ(ierr);
1205c4762a1bSJed Brown   ierr = VecDestroyVecs(user->nt,&user->uxi);CHKERRQ(ierr);
1206c4762a1bSJed Brown   ierr = VecDestroyVecs(user->nt,&user->uyi);CHKERRQ(ierr);
1207c4762a1bSJed Brown   ierr = VecDestroyVecs(user->nt,&user->uxiwork);CHKERRQ(ierr);
1208c4762a1bSJed Brown   ierr = VecDestroyVecs(user->nt,&user->uyiwork);CHKERRQ(ierr);
1209c4762a1bSJed Brown   ierr = VecDestroyVecs(user->nt,&user->ui);CHKERRQ(ierr);
1210c4762a1bSJed Brown   ierr = VecDestroyVecs(user->nt,&user->uiwork);CHKERRQ(ierr);
1211c4762a1bSJed Brown   ierr = VecDestroy(&user->c);CHKERRQ(ierr);
1212c4762a1bSJed Brown   ierr = VecDestroy(&user->cwork);CHKERRQ(ierr);
1213c4762a1bSJed Brown   ierr = VecDestroy(&user->ur);CHKERRQ(ierr);
1214c4762a1bSJed Brown   ierr = VecDestroy(&user->q);CHKERRQ(ierr);
1215c4762a1bSJed Brown   ierr = VecDestroy(&user->d);CHKERRQ(ierr);
1216c4762a1bSJed Brown   ierr = VecDestroy(&user->dwork);CHKERRQ(ierr);
1217c4762a1bSJed Brown   ierr = VecDestroy(&user->lwork);CHKERRQ(ierr);
1218c4762a1bSJed Brown   ierr = VecDestroy(&user->js_diag);CHKERRQ(ierr);
1219c4762a1bSJed Brown   ierr = ISDestroy(&user->s_is);CHKERRQ(ierr);
1220c4762a1bSJed Brown   ierr = ISDestroy(&user->d_is);CHKERRQ(ierr);
1221c4762a1bSJed Brown   ierr = VecScatterDestroy(&user->state_scatter);CHKERRQ(ierr);
1222c4762a1bSJed Brown   ierr = VecScatterDestroy(&user->design_scatter);CHKERRQ(ierr);
1223c4762a1bSJed Brown   for (i=0; i<user->nt; i++) {
1224c4762a1bSJed Brown     ierr = VecScatterDestroy(&user->uxi_scatter[i]);CHKERRQ(ierr);
1225c4762a1bSJed Brown     ierr = VecScatterDestroy(&user->uyi_scatter[i]);CHKERRQ(ierr);
1226c4762a1bSJed Brown     ierr = VecScatterDestroy(&user->ux_scatter[i]);CHKERRQ(ierr);
1227c4762a1bSJed Brown     ierr = VecScatterDestroy(&user->uy_scatter[i]);CHKERRQ(ierr);
1228c4762a1bSJed Brown     ierr = VecScatterDestroy(&user->ui_scatter[i]);CHKERRQ(ierr);
1229c4762a1bSJed Brown     ierr = VecScatterDestroy(&user->yi_scatter[i]);CHKERRQ(ierr);
1230c4762a1bSJed Brown   }
1231c4762a1bSJed Brown   ierr = PetscFree(user->uxi_scatter);CHKERRQ(ierr);
1232c4762a1bSJed Brown   ierr = PetscFree(user->uyi_scatter);CHKERRQ(ierr);
1233c4762a1bSJed Brown   ierr = PetscFree(user->ux_scatter);CHKERRQ(ierr);
1234c4762a1bSJed Brown   ierr = PetscFree(user->uy_scatter);CHKERRQ(ierr);
1235c4762a1bSJed Brown   ierr = PetscFree(user->ui_scatter);CHKERRQ(ierr);
1236c4762a1bSJed Brown   ierr = PetscFree(user->yi_scatter);CHKERRQ(ierr);
1237c4762a1bSJed Brown   PetscFunctionReturn(0);
1238c4762a1bSJed Brown }
1239c4762a1bSJed Brown 
1240c4762a1bSJed Brown PetscErrorCode HyperbolicMonitor(Tao tao, void *ptr)
1241c4762a1bSJed Brown {
1242c4762a1bSJed Brown   PetscErrorCode ierr;
1243c4762a1bSJed Brown   Vec            X;
1244c4762a1bSJed Brown   PetscReal      unorm,ynorm;
1245c4762a1bSJed Brown   AppCtx         *user = (AppCtx*)ptr;
1246c4762a1bSJed Brown 
1247c4762a1bSJed Brown   PetscFunctionBegin;
1248*a82e8c82SStefano Zampini   ierr = TaoGetSolution(tao,&X);CHKERRQ(ierr);
1249c4762a1bSJed Brown   ierr = Scatter(X,user->ywork,user->state_scatter,user->uwork,user->design_scatter);CHKERRQ(ierr);
1250c4762a1bSJed Brown   ierr = VecAXPY(user->ywork,-1.0,user->ytrue);CHKERRQ(ierr);
1251c4762a1bSJed Brown   ierr = VecAXPY(user->uwork,-1.0,user->utrue);CHKERRQ(ierr);
1252c4762a1bSJed Brown   ierr = VecNorm(user->uwork,NORM_2,&unorm);CHKERRQ(ierr);
1253c4762a1bSJed Brown   ierr = VecNorm(user->ywork,NORM_2,&ynorm);CHKERRQ(ierr);
1254c4762a1bSJed Brown   ierr = PetscPrintf(MPI_COMM_WORLD, "||u-ut||=%g ||y-yt||=%g\n",(double)unorm,(double)ynorm);CHKERRQ(ierr);
1255c4762a1bSJed Brown   PetscFunctionReturn(0);
1256c4762a1bSJed Brown }
1257c4762a1bSJed Brown 
1258c4762a1bSJed Brown /*TEST
1259c4762a1bSJed Brown 
1260c4762a1bSJed Brown    build:
1261c4762a1bSJed Brown       requires: !complex
1262c4762a1bSJed Brown 
1263c4762a1bSJed Brown    test:
1264c4762a1bSJed Brown       requires: !single
1265c4762a1bSJed Brown       args: -tao_cmonitor -tao_max_funcs 10 -tao_type lcl -tao_gatol 1.e-5
1266c4762a1bSJed Brown 
1267c4762a1bSJed Brown    test:
1268c4762a1bSJed Brown       suffix: guess_pod
1269c4762a1bSJed Brown       requires: !single
1270c4762a1bSJed Brown       args: -tao_cmonitor -tao_max_funcs 10 -tao_type lcl -ksp_guess_type pod -tao_gatol 1.e-5
1271c4762a1bSJed Brown 
1272c4762a1bSJed Brown TEST*/
1273