xref: /petsc/src/tao/pde_constrained/impls/lcl/lcl.c (revision a70f9b69f9bda94bd5bd726737b665ff663d1209)
1 #include <../src/tao/pde_constrained/impls/lcl/lcl.h>
2 #include <../src/tao/matrix/lmvmmat.h>
3 static PetscErrorCode LCLComputeLagrangianAndGradient(TaoLineSearch,Vec,PetscReal*,Vec,void*);
4 static PetscErrorCode LCLComputeAugmentedLagrangianAndGradient(TaoLineSearch,Vec,PetscReal*,Vec,void*);
5 static PetscErrorCode LCLScatter(TAO_LCL*,Vec,Vec,Vec);
6 static PetscErrorCode LCLGather(TAO_LCL*,Vec,Vec,Vec);
7 
8 #undef __FUNCT__
9 #define __FUNCT__ "TaoDestroy_LCL"
10 static PetscErrorCode TaoDestroy_LCL(Tao tao)
11 {
12   TAO_LCL        *lclP = (TAO_LCL*)tao->data;
13   PetscErrorCode ierr;
14 
15   PetscFunctionBegin;
16   if (tao->setupcalled) {
17     ierr = MatDestroy(&lclP->R);CHKERRQ(ierr);
18     ierr = VecDestroy(&lclP->lamda);CHKERRQ(ierr);
19     ierr = VecDestroy(&lclP->lamda0);CHKERRQ(ierr);
20     ierr = VecDestroy(&lclP->WL);CHKERRQ(ierr);
21     ierr = VecDestroy(&lclP->W);CHKERRQ(ierr);
22     ierr = VecDestroy(&lclP->X0);CHKERRQ(ierr);
23     ierr = VecDestroy(&lclP->G0);CHKERRQ(ierr);
24     ierr = VecDestroy(&lclP->GL);CHKERRQ(ierr);
25     ierr = VecDestroy(&lclP->GAugL);CHKERRQ(ierr);
26     ierr = VecDestroy(&lclP->dbar);CHKERRQ(ierr);
27     ierr = VecDestroy(&lclP->U);CHKERRQ(ierr);
28     ierr = VecDestroy(&lclP->U0);CHKERRQ(ierr);
29     ierr = VecDestroy(&lclP->V);CHKERRQ(ierr);
30     ierr = VecDestroy(&lclP->V0);CHKERRQ(ierr);
31     ierr = VecDestroy(&lclP->V1);CHKERRQ(ierr);
32     ierr = VecDestroy(&lclP->GU);CHKERRQ(ierr);
33     ierr = VecDestroy(&lclP->GV);CHKERRQ(ierr);
34     ierr = VecDestroy(&lclP->GU0);CHKERRQ(ierr);
35     ierr = VecDestroy(&lclP->GV0);CHKERRQ(ierr);
36     ierr = VecDestroy(&lclP->GL_U);CHKERRQ(ierr);
37     ierr = VecDestroy(&lclP->GL_V);CHKERRQ(ierr);
38     ierr = VecDestroy(&lclP->GAugL_U);CHKERRQ(ierr);
39     ierr = VecDestroy(&lclP->GAugL_V);CHKERRQ(ierr);
40     ierr = VecDestroy(&lclP->GL_U0);CHKERRQ(ierr);
41     ierr = VecDestroy(&lclP->GL_V0);CHKERRQ(ierr);
42     ierr = VecDestroy(&lclP->GAugL_U0);CHKERRQ(ierr);
43     ierr = VecDestroy(&lclP->GAugL_V0);CHKERRQ(ierr);
44     ierr = VecDestroy(&lclP->DU);CHKERRQ(ierr);
45     ierr = VecDestroy(&lclP->DV);CHKERRQ(ierr);
46     ierr = VecDestroy(&lclP->WU);CHKERRQ(ierr);
47     ierr = VecDestroy(&lclP->WV);CHKERRQ(ierr);
48     ierr = VecDestroy(&lclP->g1);CHKERRQ(ierr);
49     ierr = VecDestroy(&lclP->g2);CHKERRQ(ierr);
50     ierr = VecDestroy(&lclP->con1);CHKERRQ(ierr);
51 
52     ierr = VecDestroy(&lclP->r);CHKERRQ(ierr);
53     ierr = VecDestroy(&lclP->s);CHKERRQ(ierr);
54 
55     ierr = ISDestroy(&tao->state_is);CHKERRQ(ierr);
56     ierr = ISDestroy(&tao->design_is);CHKERRQ(ierr);
57 
58     ierr = VecScatterDestroy(&lclP->state_scatter);CHKERRQ(ierr);
59     ierr = VecScatterDestroy(&lclP->design_scatter);CHKERRQ(ierr);
60   }
61   ierr = PetscFree(tao->data);
62   PetscFunctionReturn(0);
63 }
64 
65 #undef __FUNCT__
66 #define __FUNCT__ "TaoSetFromOptions_LCL"
67 static PetscErrorCode TaoSetFromOptions_LCL(Tao tao)
68 {
69   TAO_LCL        *lclP = (TAO_LCL*)tao->data;
70   PetscBool      flg;
71   PetscErrorCode ierr;
72 
73   PetscFunctionBegin;
74   ierr = PetscOptionsHead("Linearly-Constrained Augmented Lagrangian Method for PDE-constrained optimization");CHKERRQ(ierr);
75   ierr = PetscOptionsReal("-tao_lcl_eps1","epsilon 1 tolerance","",lclP->eps1,&lclP->eps1,&flg);CHKERRQ(ierr);
76   ierr = PetscOptionsReal("-tao_lcl_eps2","epsilon 2 tolerance","",lclP->eps2,&lclP->eps2,&flg);CHKERRQ(ierr);
77   ierr = PetscOptionsReal("-tao_lcl_rho0","init value for rho","",lclP->rho0,&lclP->rho0,&flg);CHKERRQ(ierr);
78   ierr = PetscOptionsReal("-tao_lcl_rhomax","max value for rho","",lclP->rhomax,&lclP->rhomax,&flg);CHKERRQ(ierr);
79   lclP->phase2_niter = 1;
80   ierr = PetscOptionsInt("-tao_lcl_phase2_niter","Number of phase 2 iterations in LCL algorithm","",lclP->phase2_niter,&lclP->phase2_niter,&flg);CHKERRQ(ierr);
81   lclP->verbose = PETSC_FALSE;
82   ierr = PetscOptionsBool("-tao_lcl_verbose","Print verbose output","",lclP->verbose,&lclP->verbose,&flg);CHKERRQ(ierr);
83   lclP->tau[0] = lclP->tau[1] = lclP->tau[2] = lclP->tau[3] = 1.0e-4;
84   ierr = PetscOptionsReal("-tao_lcl_tola","Tolerance for first forward solve","",lclP->tau[0],&lclP->tau[0],&flg);CHKERRQ(ierr);
85   ierr = PetscOptionsReal("-tao_lcl_tolb","Tolerance for first adjoint solve","",lclP->tau[1],&lclP->tau[1],&flg);CHKERRQ(ierr);
86   ierr = PetscOptionsReal("-tao_lcl_tolc","Tolerance for second forward solve","",lclP->tau[2],&lclP->tau[2],&flg);CHKERRQ(ierr);
87   ierr = PetscOptionsReal("-tao_lcl_told","Tolerance for second adjoint solve","",lclP->tau[3],&lclP->tau[3],&flg);CHKERRQ(ierr);
88   ierr = PetscOptionsTail();CHKERRQ(ierr);
89   ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr);
90   PetscFunctionReturn(0);
91 }
92 
93 #undef __FUNCT__
94 #define __FUNCT__ "TaoView_LCL"
95 static PetscErrorCode TaoView_LCL(Tao tao, PetscViewer viewer)
96 {
97   return 0;
98 }
99 
100 #undef __FUNCT__
101 #define __FUNCT__ "TaoSetup_LCL"
102 static PetscErrorCode TaoSetup_LCL(Tao tao)
103 {
104   TAO_LCL        *lclP = (TAO_LCL*)tao->data;
105   PetscInt       lo, hi, nlocalstate, nlocaldesign;
106   PetscErrorCode ierr;
107   IS             is_state, is_design;
108 
109   PetscFunctionBegin;
110   if (!tao->state_is) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONGSTATE,"LCL Solver requires an initial state index set -- use TaoSetStateIS()");
111   ierr = VecDuplicate(tao->solution, &tao->gradient);CHKERRQ(ierr);
112   ierr = VecDuplicate(tao->solution, &tao->stepdirection);CHKERRQ(ierr);
113   ierr = VecDuplicate(tao->solution, &lclP->W);CHKERRQ(ierr);
114   ierr = VecDuplicate(tao->solution, &lclP->X0);CHKERRQ(ierr);
115   ierr = VecDuplicate(tao->solution, &lclP->G0);CHKERRQ(ierr);
116   ierr = VecDuplicate(tao->solution, &lclP->GL);CHKERRQ(ierr);
117   ierr = VecDuplicate(tao->solution, &lclP->GAugL);CHKERRQ(ierr);
118 
119   ierr = VecDuplicate(tao->constraints, &lclP->lamda);CHKERRQ(ierr);
120   ierr = VecDuplicate(tao->constraints, &lclP->WL);CHKERRQ(ierr);
121   ierr = VecDuplicate(tao->constraints, &lclP->lamda0);CHKERRQ(ierr);
122   ierr = VecDuplicate(tao->constraints, &lclP->con1);CHKERRQ(ierr);
123 
124   ierr = VecSet(lclP->lamda,0.0);CHKERRQ(ierr);
125 
126   ierr = VecGetSize(tao->solution, &lclP->n);CHKERRQ(ierr);
127   ierr = VecGetSize(tao->constraints, &lclP->m);CHKERRQ(ierr);
128 
129   ierr = VecCreate(((PetscObject)tao)->comm,&lclP->U);CHKERRQ(ierr);
130   ierr = VecCreate(((PetscObject)tao)->comm,&lclP->V);CHKERRQ(ierr);
131   ierr = ISGetLocalSize(tao->state_is,&nlocalstate);CHKERRQ(ierr);
132   ierr = ISGetLocalSize(tao->design_is,&nlocaldesign);CHKERRQ(ierr);
133   ierr = VecSetSizes(lclP->U,nlocalstate,lclP->m);CHKERRQ(ierr);
134   ierr = VecSetSizes(lclP->V,nlocaldesign,lclP->n-lclP->m);CHKERRQ(ierr);
135   ierr = VecSetType(lclP->U,((PetscObject)(tao->solution))->type_name);CHKERRQ(ierr);
136   ierr = VecSetType(lclP->V,((PetscObject)(tao->solution))->type_name);CHKERRQ(ierr);
137   ierr = VecSetFromOptions(lclP->U);CHKERRQ(ierr);
138   ierr = VecSetFromOptions(lclP->V);CHKERRQ(ierr);
139   ierr = VecDuplicate(lclP->U,&lclP->DU);CHKERRQ(ierr);
140   ierr = VecDuplicate(lclP->U,&lclP->U0);CHKERRQ(ierr);
141   ierr = VecDuplicate(lclP->U,&lclP->GU);CHKERRQ(ierr);
142   ierr = VecDuplicate(lclP->U,&lclP->GU0);CHKERRQ(ierr);
143   ierr = VecDuplicate(lclP->U,&lclP->GAugL_U);CHKERRQ(ierr);
144   ierr = VecDuplicate(lclP->U,&lclP->GL_U);CHKERRQ(ierr);
145   ierr = VecDuplicate(lclP->U,&lclP->GAugL_U0);CHKERRQ(ierr);
146   ierr = VecDuplicate(lclP->U,&lclP->GL_U0);CHKERRQ(ierr);
147   ierr = VecDuplicate(lclP->U,&lclP->WU);CHKERRQ(ierr);
148   ierr = VecDuplicate(lclP->U,&lclP->r);CHKERRQ(ierr);
149   ierr = VecDuplicate(lclP->V,&lclP->V0);CHKERRQ(ierr);
150   ierr = VecDuplicate(lclP->V,&lclP->V1);CHKERRQ(ierr);
151   ierr = VecDuplicate(lclP->V,&lclP->DV);CHKERRQ(ierr);
152   ierr = VecDuplicate(lclP->V,&lclP->s);CHKERRQ(ierr);
153   ierr = VecDuplicate(lclP->V,&lclP->GV);CHKERRQ(ierr);
154   ierr = VecDuplicate(lclP->V,&lclP->GV0);CHKERRQ(ierr);
155   ierr = VecDuplicate(lclP->V,&lclP->dbar);CHKERRQ(ierr);
156   ierr = VecDuplicate(lclP->V,&lclP->GAugL_V);CHKERRQ(ierr);
157   ierr = VecDuplicate(lclP->V,&lclP->GL_V);CHKERRQ(ierr);
158   ierr = VecDuplicate(lclP->V,&lclP->GAugL_V0);CHKERRQ(ierr);
159   ierr = VecDuplicate(lclP->V,&lclP->GL_V0);CHKERRQ(ierr);
160   ierr = VecDuplicate(lclP->V,&lclP->WV);CHKERRQ(ierr);
161   ierr = VecDuplicate(lclP->V,&lclP->g1);CHKERRQ(ierr);
162   ierr = VecDuplicate(lclP->V,&lclP->g2);CHKERRQ(ierr);
163 
164   /* create scatters for state, design subvecs */
165   ierr = VecGetOwnershipRange(lclP->U,&lo,&hi);CHKERRQ(ierr);
166   ierr = ISCreateStride(((PetscObject)lclP->U)->comm,hi-lo,lo,1,&is_state);CHKERRQ(ierr);
167   ierr = VecGetOwnershipRange(lclP->V,&lo,&hi);CHKERRQ(ierr);
168   if (0) {
169     PetscInt sizeU,sizeV;
170     ierr = VecGetSize(lclP->U,&sizeU);
171     ierr = VecGetSize(lclP->V,&sizeV);
172     ierr = PetscPrintf(PETSC_COMM_WORLD,"size(U)=%D, size(V)=%D\n",sizeU,sizeV);
173   }
174   ierr = ISCreateStride(((PetscObject)lclP->V)->comm,hi-lo,lo,1,&is_design);CHKERRQ(ierr);
175   ierr = VecScatterCreate(tao->solution,tao->state_is,lclP->U,is_state,&lclP->state_scatter);CHKERRQ(ierr);
176   ierr = VecScatterCreate(tao->solution,tao->design_is,lclP->V,is_design,&lclP->design_scatter);CHKERRQ(ierr);
177   ierr = ISDestroy(&is_state);CHKERRQ(ierr);
178   ierr = ISDestroy(&is_design);CHKERRQ(ierr);
179   PetscFunctionReturn(0);
180 }
181 
182 #undef __FUNCT__
183 #define __FUNCT__ "TaoSolve_LCL"
184 static PetscErrorCode TaoSolve_LCL(Tao tao)
185 {
186   TAO_LCL                      *lclP = (TAO_LCL*)tao->data;
187   PetscInt                     iter=0,phase2_iter,nlocal,its;
188   TaoConvergedReason           reason = TAO_CONTINUE_ITERATING;
189   TaoLineSearchConvergedReason ls_reason = TAOLINESEARCH_CONTINUE_ITERATING;
190   PetscReal                    step=1.0,f, descent, aldescent;
191   PetscReal                    cnorm, mnorm;
192   PetscReal                    adec,r2,rGL_U,rWU;
193   PetscBool                    set,pset,flag,pflag,symmetric;
194   PetscErrorCode               ierr;
195 
196   PetscFunctionBegin;
197   lclP->rho = lclP->rho0;
198   ierr = VecGetLocalSize(lclP->U,&nlocal);CHKERRQ(ierr);
199   ierr = VecGetLocalSize(lclP->V,&nlocal);CHKERRQ(ierr);
200   ierr = MatCreateLMVM(((PetscObject)tao)->comm,nlocal,lclP->n-lclP->m,&lclP->R);CHKERRQ(ierr);
201   ierr = MatLMVMAllocateVectors(lclP->R,lclP->V);CHKERRQ(ierr);
202   lclP->recompute_jacobian_flag = PETSC_TRUE;
203 
204   /* Scatter to U,V */
205   ierr = LCLScatter(lclP,tao->solution,lclP->U,lclP->V);CHKERRQ(ierr);
206 
207   /* Evaluate Function, Gradient, Constraints, and Jacobian */
208   ierr = TaoComputeObjectiveAndGradient(tao,tao->solution,&f,tao->gradient);CHKERRQ(ierr);
209   ierr = TaoComputeJacobianState(tao,tao->solution,tao->jacobian_state,tao->jacobian_state_pre,tao->jacobian_state_inv);CHKERRQ(ierr);
210   ierr = TaoComputeJacobianDesign(tao,tao->solution,tao->jacobian_design);CHKERRQ(ierr);
211   ierr = TaoComputeConstraints(tao,tao->solution, tao->constraints);CHKERRQ(ierr);
212 
213   /* Scatter gradient to GU,GV */
214   ierr = LCLScatter(lclP,tao->gradient,lclP->GU,lclP->GV);CHKERRQ(ierr);
215 
216   /* Evaluate Lagrangian function and gradient */
217   /* p0 */
218   ierr = VecSet(lclP->lamda,0.0);CHKERRQ(ierr); /*  Initial guess in CG */
219   ierr = MatIsSymmetricKnown(tao->jacobian_state,&set,&flag);CHKERRQ(ierr);
220   if (tao->jacobian_state_pre) {
221     ierr = MatIsSymmetricKnown(tao->jacobian_state_pre,&pset,&pflag);CHKERRQ(ierr);
222   } else {
223     pset = pflag = PETSC_TRUE;
224   }
225   if (set && pset && flag && pflag) symmetric = PETSC_TRUE;
226   else symmetric = PETSC_FALSE;
227 
228   lclP->solve_type = LCL_ADJOINT2;
229   if (tao->jacobian_state_inv) {
230     if (symmetric) {
231       ierr = MatMult(tao->jacobian_state_inv, lclP->GU, lclP->lamda);CHKERRQ(ierr); } else {
232       ierr = MatMultTranspose(tao->jacobian_state_inv, lclP->GU, lclP->lamda);CHKERRQ(ierr);
233     }
234   } else {
235     ierr = KSPSetOperators(tao->ksp, tao->jacobian_state, tao->jacobian_state_pre);CHKERRQ(ierr);
236     if (symmetric) {
237       ierr = KSPSolve(tao->ksp, lclP->GU,  lclP->lamda);CHKERRQ(ierr);
238     } else {
239       ierr = KSPSolveTranspose(tao->ksp, lclP->GU,  lclP->lamda);CHKERRQ(ierr);
240     }
241     ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr);
242     tao->ksp_its+=its;
243     tao->ksp_tot_its+=its;
244   }
245   ierr = VecCopy(lclP->lamda,lclP->lamda0);CHKERRQ(ierr);
246   ierr = LCLComputeAugmentedLagrangianAndGradient(tao->linesearch,tao->solution,&lclP->aug,lclP->GAugL,tao);CHKERRQ(ierr);
247 
248   ierr = LCLScatter(lclP,lclP->GL,lclP->GL_U,lclP->GL_V);CHKERRQ(ierr);
249   ierr = LCLScatter(lclP,lclP->GAugL,lclP->GAugL_U,lclP->GAugL_V);CHKERRQ(ierr);
250 
251   /* Evaluate constraint norm */
252   ierr = VecNorm(tao->constraints, NORM_2, &cnorm);CHKERRQ(ierr);
253   ierr = VecNorm(lclP->GAugL, NORM_2, &mnorm);CHKERRQ(ierr);
254 
255   /* Monitor convergence */
256   ierr = TaoMonitor(tao, iter,f,mnorm,cnorm,step,&reason);CHKERRQ(ierr);
257 
258   while (reason == TAO_CONTINUE_ITERATING) {
259     tao->ksp_its=0;
260     /* Compute a descent direction for the linearly constrained subproblem
261        minimize f(u+du, v+dv)
262        s.t. A(u0,v0)du + B(u0,v0)dv = -g(u0,v0) */
263 
264     /* Store the points around the linearization */
265     ierr = VecCopy(lclP->U, lclP->U0);CHKERRQ(ierr);
266     ierr = VecCopy(lclP->V, lclP->V0);CHKERRQ(ierr);
267     ierr = VecCopy(lclP->GU,lclP->GU0);CHKERRQ(ierr);
268     ierr = VecCopy(lclP->GV,lclP->GV0);CHKERRQ(ierr);
269     ierr = VecCopy(lclP->GAugL_U,lclP->GAugL_U0);CHKERRQ(ierr);
270     ierr = VecCopy(lclP->GAugL_V,lclP->GAugL_V0);CHKERRQ(ierr);
271     ierr = VecCopy(lclP->GL_U,lclP->GL_U0);CHKERRQ(ierr);
272     ierr = VecCopy(lclP->GL_V,lclP->GL_V0);CHKERRQ(ierr);
273 
274     lclP->aug0 = lclP->aug;
275     lclP->lgn0 = lclP->lgn;
276 
277     /* Given the design variables, we need to project the current iterate
278        onto the linearized constraint.  We choose to fix the design variables
279        and solve the linear system for the state variables.  The resulting
280        point is the Newton direction */
281 
282     /* Solve r = A\con */
283     lclP->solve_type = LCL_FORWARD1;
284     ierr = VecSet(lclP->r,0.0);CHKERRQ(ierr); /*  Initial guess in CG */
285 
286     if (tao->jacobian_state_inv) {
287       ierr = MatMult(tao->jacobian_state_inv, tao->constraints, lclP->r);CHKERRQ(ierr);
288     } else {
289       ierr = KSPSetOperators(tao->ksp, tao->jacobian_state, tao->jacobian_state_pre);CHKERRQ(ierr);
290       ierr = KSPSolve(tao->ksp, tao->constraints,  lclP->r);CHKERRQ(ierr);
291       ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr);
292       tao->ksp_its+=its;
293       tao->ksp_tot_its+=tao->ksp_its;
294     }
295 
296     /* Set design step direction dv to zero */
297     ierr = VecSet(lclP->s, 0.0);CHKERRQ(ierr);
298 
299     /*
300        Check sufficient descent for constraint merit function .5*||con||^2
301        con' Ak r >= eps1 ||r||^(2+eps2)
302     */
303 
304     /* Compute WU= Ak' * con */
305     if (symmetric)  {
306       ierr = MatMult(tao->jacobian_state,tao->constraints,lclP->WU);CHKERRQ(ierr);
307     } else {
308       ierr = MatMultTranspose(tao->jacobian_state,tao->constraints,lclP->WU);CHKERRQ(ierr);
309     }
310     /* Compute r * Ak' * con */
311     ierr = VecDot(lclP->r,lclP->WU,&rWU);CHKERRQ(ierr);
312 
313     /* compute ||r||^(2+eps2) */
314     ierr = VecNorm(lclP->r,NORM_2,&r2);CHKERRQ(ierr);
315     r2 = PetscPowScalar(r2,2.0+lclP->eps2);
316     adec = lclP->eps1 * r2;
317 
318     if (rWU < adec) {
319       ierr = PetscInfo(tao,"Newton direction not descent for constraint, feasibility phase required");CHKERRQ(ierr);
320       if (lclP->verbose) {
321         ierr = PetscPrintf(PETSC_COMM_WORLD,"Newton direction not descent for constraint: %g -- using steepest descent\n",(double)descent);CHKERRQ(ierr);
322       }
323 
324       ierr = PetscInfo(tao,"Using steepest descent direction instead.\n");CHKERRQ(ierr);
325       ierr = VecSet(lclP->r,0.0);CHKERRQ(ierr);
326       ierr = VecAXPY(lclP->r,-1.0,lclP->WU);CHKERRQ(ierr);
327       ierr = VecDot(lclP->r,lclP->r,&rWU);CHKERRQ(ierr);
328       ierr = VecNorm(lclP->r,NORM_2,&r2);CHKERRQ(ierr);
329       r2 = PetscPowScalar(r2,2.0+lclP->eps2);
330       ierr = VecDot(lclP->r,lclP->GAugL_U,&descent);CHKERRQ(ierr);
331       adec = lclP->eps1 * r2;
332     }
333 
334 
335     /*
336        Check descent for aug. lagrangian
337        r' (GUk - Ak'*yk - rho*Ak'*con) <= -eps1 ||r||^(2+eps2)
338           GL_U = GUk - Ak'*yk
339           WU   = Ak'*con
340                                          adec=eps1||r||^(2+eps2)
341 
342        ==>
343        Check r'GL_U - rho*r'WU <= adec
344     */
345 
346     ierr = VecDot(lclP->r,lclP->GL_U,&rGL_U);
347     aldescent =  rGL_U - lclP->rho*rWU;
348     if (aldescent > -adec) {
349       if (lclP->verbose) {
350         ierr = PetscPrintf(PETSC_COMM_WORLD," Newton direction not descent for augmented Lagrangian: %g",(double)aldescent);CHKERRQ(ierr);
351       }
352       ierr = PetscInfo1(tao,"Newton direction not descent for augmented Lagrangian: %g",(double)aldescent);CHKERRQ(ierr);
353       lclP->rho =  (rGL_U - adec)/rWU;
354       if (lclP->rho > lclP->rhomax) {
355         lclP->rho = lclP->rhomax;
356         SETERRQ1(PETSC_COMM_WORLD,0,"rho=%g > rhomax, case not implemented.  Increase rhomax (-tao_lcl_rhomax)",(double)lclP->rho);
357       }
358       if (lclP->verbose) {
359         ierr = PetscPrintf(PETSC_COMM_WORLD,"  Increasing penalty parameter to %g\n",(double)lclP->rho);CHKERRQ(ierr);
360       }
361       ierr = PetscInfo1(tao,"  Increasing penalty parameter to %g",(double)lclP->rho);
362     }
363 
364     ierr = LCLComputeAugmentedLagrangianAndGradient(tao->linesearch,tao->solution,&lclP->aug,lclP->GAugL,tao);CHKERRQ(ierr);
365     ierr = LCLScatter(lclP,lclP->GL,lclP->GL_U,lclP->GL_V);CHKERRQ(ierr);
366     ierr = LCLScatter(lclP,lclP->GAugL,lclP->GAugL_U,lclP->GAugL_V);CHKERRQ(ierr);
367 
368     /* We now minimize the augmented Lagrangian along the Newton direction */
369     ierr = VecScale(lclP->r,-1.0);CHKERRQ(ierr);
370     ierr = LCLGather(lclP, lclP->r,lclP->s,tao->stepdirection);CHKERRQ(ierr);
371     ierr = VecScale(lclP->r,-1.0);CHKERRQ(ierr);
372     ierr = LCLGather(lclP, lclP->GAugL_U0, lclP->GAugL_V0, lclP->GAugL);CHKERRQ(ierr);
373     ierr = LCLGather(lclP, lclP->U0,lclP->V0,lclP->X0);CHKERRQ(ierr);
374 
375     lclP->recompute_jacobian_flag = PETSC_TRUE;
376 
377     ierr = TaoLineSearchSetInitialStepLength(tao->linesearch,1.0);CHKERRQ(ierr);
378     ierr = TaoLineSearchSetType(tao->linesearch, TAOLINESEARCHMT);CHKERRQ(ierr);
379     ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr);
380     ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &lclP->aug, lclP->GAugL, tao->stepdirection, &step, &ls_reason);CHKERRQ(ierr);
381     if (lclP->verbose) {
382       ierr = PetscPrintf(PETSC_COMM_WORLD,"Steplength = %g\n",(double)step);CHKERRQ(ierr);
383     }
384 
385     ierr = LCLScatter(lclP,tao->solution,lclP->U,lclP->V);CHKERRQ(ierr);
386     ierr = TaoComputeObjectiveAndGradient(tao,tao->solution,&f,tao->gradient);CHKERRQ(ierr);
387     ierr = LCLScatter(lclP,tao->gradient,lclP->GU,lclP->GV);CHKERRQ(ierr);
388 
389     ierr = LCLScatter(lclP,lclP->GAugL,lclP->GAugL_U,lclP->GAugL_V);CHKERRQ(ierr);
390 
391     /* Check convergence */
392     ierr = VecNorm(lclP->GAugL, NORM_2, &mnorm);CHKERRQ(ierr);
393     ierr = VecNorm(tao->constraints, NORM_2, &cnorm);CHKERRQ(ierr);
394     ierr = TaoMonitor(tao, iter,f,mnorm,cnorm,step,&reason);CHKERRQ(ierr);
395     if (reason != TAO_CONTINUE_ITERATING){
396       break;
397     }
398 
399     /* TODO: use a heuristic to choose how many iterations should be performed within phase 2 */
400     for (phase2_iter=0; phase2_iter<lclP->phase2_niter; phase2_iter++){
401       /* We now minimize the objective function starting from the fraction of
402          the Newton point accepted by applying one step of a reduced-space
403          method.  The optimization problem is:
404 
405          minimize f(u+du, v+dv)
406          s. t.    A(u0,v0)du + B(u0,v0)du = -alpha g(u0,v0)
407 
408          In particular, we have that
409          du = -inv(A)*(Bdv + alpha g) */
410 
411       ierr = TaoComputeJacobianState(tao,lclP->X0,tao->jacobian_state,tao->jacobian_state_pre,tao->jacobian_state_inv);CHKERRQ(ierr);
412       ierr = TaoComputeJacobianDesign(tao,lclP->X0,tao->jacobian_design);CHKERRQ(ierr);
413 
414       /* Store V and constraints */
415       ierr = VecCopy(lclP->V, lclP->V1);CHKERRQ(ierr);
416       ierr = VecCopy(tao->constraints,lclP->con1);CHKERRQ(ierr);
417 
418       /* Compute multipliers */
419       /* p1 */
420       ierr = VecSet(lclP->lamda,0.0);CHKERRQ(ierr); /*  Initial guess in CG */
421       lclP->solve_type = LCL_ADJOINT1;
422       ierr = MatIsSymmetricKnown(tao->jacobian_state,&set,&flag);CHKERRQ(ierr);
423       if (tao->jacobian_state_pre) {
424         ierr = MatIsSymmetricKnown(tao->jacobian_state_pre,&pset,&pflag);CHKERRQ(ierr);
425       } else {
426         pset = pflag = PETSC_TRUE;
427       }
428       if (set && pset && flag && pflag) symmetric = PETSC_TRUE;
429       else symmetric = PETSC_FALSE;
430 
431       if (tao->jacobian_state_inv) {
432         if (symmetric) {
433           ierr = MatMult(tao->jacobian_state_inv, lclP->GAugL_U, lclP->lamda);CHKERRQ(ierr);
434         } else {
435           ierr = MatMultTranspose(tao->jacobian_state_inv, lclP->GAugL_U, lclP->lamda);CHKERRQ(ierr);
436         }
437       } else {
438         if (symmetric) {
439           ierr = KSPSolve(tao->ksp, lclP->GAugL_U,  lclP->lamda);CHKERRQ(ierr);
440         } else {
441           ierr = KSPSolveTranspose(tao->ksp, lclP->GAugL_U,  lclP->lamda);CHKERRQ(ierr);
442         }
443         ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr);
444         tao->ksp_its+=its;
445         tao->ksp_tot_its+=its;
446       }
447       ierr = MatMultTranspose(tao->jacobian_design,lclP->lamda,lclP->g1);CHKERRQ(ierr);
448       ierr = VecAXPY(lclP->g1,-1.0,lclP->GAugL_V);CHKERRQ(ierr);
449 
450       /* Compute the limited-memory quasi-newton direction */
451       if (iter > 0) {
452         ierr = MatLMVMSolve(lclP->R,lclP->g1,lclP->s);CHKERRQ(ierr);
453         ierr = VecDot(lclP->s,lclP->g1,&descent);CHKERRQ(ierr);
454         if (descent <= 0) {
455           if (lclP->verbose) {
456             ierr = PetscPrintf(PETSC_COMM_WORLD,"Reduced-space direction not descent: %g\n",(double)descent);CHKERRQ(ierr);
457           }
458           ierr = VecCopy(lclP->g1,lclP->s);CHKERRQ(ierr);
459         }
460       } else {
461         ierr = VecCopy(lclP->g1,lclP->s);CHKERRQ(ierr);
462       }
463       ierr = VecScale(lclP->g1,-1.0);CHKERRQ(ierr);
464 
465       /* Recover the full space direction */
466       ierr = MatMult(tao->jacobian_design,lclP->s,lclP->WU);CHKERRQ(ierr);
467       /* ierr = VecSet(lclP->r,0.0);CHKERRQ(ierr); */ /*  Initial guess in CG */
468       lclP->solve_type = LCL_FORWARD2;
469       if (tao->jacobian_state_inv) {
470         ierr = MatMult(tao->jacobian_state_inv,lclP->WU,lclP->r);CHKERRQ(ierr);
471       } else {
472         ierr = KSPSolve(tao->ksp, lclP->WU, lclP->r);CHKERRQ(ierr);
473         ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr);
474         tao->ksp_its += its;
475         tao->ksp_tot_its+=its;
476       }
477 
478       /* We now minimize the augmented Lagrangian along the direction -r,s */
479       ierr = VecScale(lclP->r, -1.0);CHKERRQ(ierr);
480       ierr = LCLGather(lclP,lclP->r,lclP->s,tao->stepdirection);CHKERRQ(ierr);
481       ierr = VecScale(lclP->r, -1.0);CHKERRQ(ierr);
482       lclP->recompute_jacobian_flag = PETSC_TRUE;
483 
484       ierr = TaoLineSearchSetInitialStepLength(tao->linesearch,1.0);CHKERRQ(ierr);
485       ierr = TaoLineSearchSetType(tao->linesearch,TAOLINESEARCHMT);CHKERRQ(ierr);
486       ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr);
487       ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &lclP->aug, lclP->GAugL, tao->stepdirection,&step,&ls_reason);CHKERRQ(ierr);
488       if (lclP->verbose){
489         ierr = PetscPrintf(PETSC_COMM_WORLD,"Reduced-space steplength =  %g\n",(double)step);CHKERRQ(ierr);
490       }
491 
492       ierr = LCLScatter(lclP,tao->solution,lclP->U,lclP->V);CHKERRQ(ierr);
493       ierr = LCLScatter(lclP,lclP->GL,lclP->GL_U,lclP->GL_V);CHKERRQ(ierr);
494       ierr = LCLScatter(lclP,lclP->GAugL,lclP->GAugL_U,lclP->GAugL_V);CHKERRQ(ierr);
495       ierr = TaoComputeObjectiveAndGradient(tao,tao->solution,&f,tao->gradient);CHKERRQ(ierr);
496       ierr = LCLScatter(lclP,tao->gradient,lclP->GU,lclP->GV);CHKERRQ(ierr);
497 
498       /* Compute the reduced gradient at the new point */
499 
500       ierr = TaoComputeJacobianState(tao,lclP->X0,tao->jacobian_state,tao->jacobian_state_pre,tao->jacobian_state_inv);CHKERRQ(ierr);
501       ierr = TaoComputeJacobianDesign(tao,lclP->X0,tao->jacobian_design);CHKERRQ(ierr);
502 
503       /* p2 */
504       /* Compute multipliers, using lamda-rho*con as an initial guess in PCG */
505       if (phase2_iter==0){
506         ierr = VecWAXPY(lclP->lamda,-lclP->rho,lclP->con1,lclP->lamda0);CHKERRQ(ierr);
507       } else {
508         ierr = VecAXPY(lclP->lamda,-lclP->rho,tao->constraints);CHKERRQ(ierr);
509       }
510 
511       ierr = MatIsSymmetricKnown(tao->jacobian_state,&set,&flag);CHKERRQ(ierr);
512       if (tao->jacobian_state_pre) {
513         ierr = MatIsSymmetricKnown(tao->jacobian_state_pre,&pset,&pflag);CHKERRQ(ierr);
514       } else {
515         pset = pflag = PETSC_TRUE;
516       }
517       if (set && pset && flag && pflag) symmetric = PETSC_TRUE;
518       else symmetric = PETSC_FALSE;
519 
520       lclP->solve_type = LCL_ADJOINT2;
521       if (tao->jacobian_state_inv) {
522         if (symmetric) {
523           ierr = MatMult(tao->jacobian_state_inv, lclP->GU, lclP->lamda);CHKERRQ(ierr);
524         } else {
525           ierr = MatMultTranspose(tao->jacobian_state_inv, lclP->GU, lclP->lamda);CHKERRQ(ierr);
526         }
527       } else {
528         if (symmetric) {
529           ierr = KSPSolve(tao->ksp, lclP->GU,  lclP->lamda);CHKERRQ(ierr);
530         } else {
531           ierr = KSPSolveTranspose(tao->ksp, lclP->GU,  lclP->lamda);CHKERRQ(ierr);
532         }
533         ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr);
534         tao->ksp_its += its;
535       }
536 
537       ierr = MatMultTranspose(tao->jacobian_design,lclP->lamda,lclP->g2);CHKERRQ(ierr);
538       ierr = VecAXPY(lclP->g2,-1.0,lclP->GV);CHKERRQ(ierr);
539 
540       ierr = VecScale(lclP->g2,-1.0);CHKERRQ(ierr);
541 
542       /* Update the quasi-newton approximation */
543       if (phase2_iter >= 0){
544         ierr = MatLMVMSetPrev(lclP->R,lclP->V1,lclP->g1);
545       }
546       ierr = MatLMVMUpdate(lclP->R,lclP->V,lclP->g2);CHKERRQ(ierr);
547       /* Use "-tao_ls_type gpcg -tao_ls_ftol 0 -tao_lmm_broyden_phi 0.0 -tao_lmm_scale_type scalar" to obtain agreement with Matlab code */
548 
549     }
550 
551     ierr = VecCopy(lclP->lamda,lclP->lamda0);CHKERRQ(ierr);
552 
553     /* Evaluate Function, Gradient, Constraints, and Jacobian */
554     ierr = TaoComputeObjectiveAndGradient(tao,tao->solution,&f,tao->gradient);CHKERRQ(ierr);
555     ierr = LCLScatter(lclP,tao->solution,lclP->U,lclP->V);CHKERRQ(ierr);
556     ierr = LCLScatter(lclP,tao->gradient,lclP->GU,lclP->GV);CHKERRQ(ierr);
557 
558     ierr = TaoComputeJacobianState(tao,tao->solution,tao->jacobian_state,tao->jacobian_state_pre,tao->jacobian_state_inv);CHKERRQ(ierr);
559     ierr = TaoComputeJacobianDesign(tao,tao->solution,tao->jacobian_design);CHKERRQ(ierr);
560     ierr = TaoComputeConstraints(tao,tao->solution, tao->constraints);CHKERRQ(ierr);
561 
562     ierr = LCLComputeAugmentedLagrangianAndGradient(tao->linesearch,tao->solution,&lclP->aug,lclP->GAugL,tao);CHKERRQ(ierr);
563 
564     ierr = VecNorm(lclP->GAugL, NORM_2, &mnorm);CHKERRQ(ierr);
565 
566     /* Evaluate constraint norm */
567     ierr = VecNorm(tao->constraints, NORM_2, &cnorm);CHKERRQ(ierr);
568 
569     /* Monitor convergence */
570     iter++;
571     ierr = TaoMonitor(tao, iter,f,mnorm,cnorm,step,&reason);CHKERRQ(ierr);
572   }
573   ierr = MatDestroy(&lclP->R);CHKERRQ(ierr);
574   PetscFunctionReturn(0);
575 }
576 
577 /*MC
578  TAOLCL - linearly constrained lagrangian method for pde-constrained optimization
579 
580 + -tao_lcl_eps1 - epsilon 1 tolerance
581 . -tao_lcl_eps2","epsilon 2 tolerance","",lclP->eps2,&lclP->eps2,&flg);CHKERRQ(ierr);
582 . -tao_lcl_rho0","init value for rho","",lclP->rho0,&lclP->rho0,&flg);CHKERRQ(ierr);
583 . -tao_lcl_rhomax","max value for rho","",lclP->rhomax,&lclP->rhomax,&flg);CHKERRQ(ierr);
584 . -tao_lcl_phase2_niter - Number of phase 2 iterations in LCL algorithm
585 . -tao_lcl_verbose - Print verbose output if True
586 . -tao_lcl_tola - Tolerance for first forward solve
587 . -tao_lcl_tolb - Tolerance for first adjoint solve
588 . -tao_lcl_tolc - Tolerance for second forward solve
589 - -tao_lcl_told - Tolerance for second adjoint solve
590 
591   Level: beginner
592 M*/
593 #undef __FUNCT__
594 #define __FUNCT__ "TaoCreate_LCL"
595 PETSC_EXTERN PetscErrorCode TaoCreate_LCL(Tao tao)
596 {
597   TAO_LCL        *lclP;
598   PetscErrorCode ierr;
599   const char     *morethuente_type = TAOLINESEARCHMT;
600 
601   PetscFunctionBegin;
602   tao->ops->setup = TaoSetup_LCL;
603   tao->ops->solve = TaoSolve_LCL;
604   tao->ops->view = TaoView_LCL;
605   tao->ops->setfromoptions = TaoSetFromOptions_LCL;
606   tao->ops->destroy = TaoDestroy_LCL;
607   ierr = PetscNewLog(tao,&lclP);CHKERRQ(ierr);
608   tao->data = (void*)lclP;
609 
610   tao->max_it=200;
611 #if defined(PETSC_USE_REAL_SINGLE)
612   tao->fatol=1e-5;
613   tao->frtol=1e-5;
614 #else
615   tao->fatol=1e-8;
616   tao->frtol=1e-8;
617 #endif
618   tao->catol=1e-4;
619   tao->crtol=1e-4;
620   tao->gttol=1e-4;
621   tao->gatol=1e-4;
622   tao->grtol=1e-4;
623   lclP->rho0 = 1.0e-4;
624   lclP->rhomax=1e5;
625   lclP->eps1 = 1.0e-8;
626   lclP->eps2 = 0.0;
627   lclP->solve_type=2;
628   lclP->tau[0] = lclP->tau[1] = lclP->tau[2] = lclP->tau[3] = 1.0e-4;
629   ierr = TaoLineSearchCreate(((PetscObject)tao)->comm, &tao->linesearch);CHKERRQ(ierr);
630   ierr = TaoLineSearchSetType(tao->linesearch, morethuente_type);CHKERRQ(ierr);
631 
632   ierr = TaoLineSearchSetObjectiveAndGradientRoutine(tao->linesearch,LCLComputeAugmentedLagrangianAndGradient, tao);CHKERRQ(ierr);
633   ierr = KSPCreate(((PetscObject)tao)->comm,&tao->ksp);CHKERRQ(ierr);
634   ierr = KSPSetFromOptions(tao->ksp);CHKERRQ(ierr);
635   PetscFunctionReturn(0);
636 }
637 
638 #undef __FUNCT__
639 #define __FUNCT__ "LCLComputeLagrangianAndGradient"
640 static PetscErrorCode LCLComputeLagrangianAndGradient(TaoLineSearch ls, Vec X, PetscReal *f, Vec G, void *ptr)
641 {
642   Tao            tao = (Tao)ptr;
643   TAO_LCL        *lclP = (TAO_LCL*)tao->data;
644   PetscBool      set,pset,flag,pflag,symmetric;
645   PetscReal      cdotl;
646   PetscErrorCode ierr;
647 
648   PetscFunctionBegin;
649   ierr = TaoComputeObjectiveAndGradient(tao,X,f,G);CHKERRQ(ierr);
650   ierr = LCLScatter(lclP,G,lclP->GU,lclP->GV);CHKERRQ(ierr);
651   if (lclP->recompute_jacobian_flag) {
652     ierr = TaoComputeJacobianState(tao,X,tao->jacobian_state,tao->jacobian_state_pre,tao->jacobian_state_inv);CHKERRQ(ierr);
653     ierr = TaoComputeJacobianDesign(tao,X,tao->jacobian_design);CHKERRQ(ierr);
654   }
655   ierr = TaoComputeConstraints(tao,X, tao->constraints);CHKERRQ(ierr);
656   ierr = MatIsSymmetricKnown(tao->jacobian_state,&set,&flag);CHKERRQ(ierr);
657   if (tao->jacobian_state_pre) {
658     ierr = MatIsSymmetricKnown(tao->jacobian_state_pre,&pset,&pflag);CHKERRQ(ierr);
659   } else {
660     pset = pflag = PETSC_TRUE;
661   }
662   if (set && pset && flag && pflag) symmetric = PETSC_TRUE;
663   else symmetric = PETSC_FALSE;
664 
665   ierr = VecDot(lclP->lamda0, tao->constraints, &cdotl);CHKERRQ(ierr);
666   lclP->lgn = *f - cdotl;
667 
668   /* Gradient of Lagrangian GL = G - J' * lamda */
669   /*      WU = A' * WL
670           WV = B' * WL */
671   if (symmetric) {
672     ierr = MatMult(tao->jacobian_state,lclP->lamda0,lclP->GL_U);CHKERRQ(ierr);
673   } else {
674     ierr = MatMultTranspose(tao->jacobian_state,lclP->lamda0,lclP->GL_U);CHKERRQ(ierr);
675   }
676   ierr = MatMultTranspose(tao->jacobian_design,lclP->lamda0,lclP->GL_V);CHKERRQ(ierr);
677   ierr = VecScale(lclP->GL_U,-1.0);CHKERRQ(ierr);
678   ierr = VecScale(lclP->GL_V,-1.0);CHKERRQ(ierr);
679   ierr = VecAXPY(lclP->GL_U,1.0,lclP->GU);CHKERRQ(ierr);
680   ierr = VecAXPY(lclP->GL_V,1.0,lclP->GV);CHKERRQ(ierr);
681   ierr = LCLGather(lclP,lclP->GL_U,lclP->GL_V,lclP->GL);CHKERRQ(ierr);
682 
683   f[0] = lclP->lgn;
684   ierr = VecCopy(lclP->GL,G);
685   PetscFunctionReturn(0);
686 }
687 
688 #undef __FUNCT__
689 #define __FUNCT__ "LCLComputeAugmentedLagrangianAndGradient"
690 static PetscErrorCode LCLComputeAugmentedLagrangianAndGradient(TaoLineSearch ls, Vec X, PetscReal *f, Vec G, void *ptr)
691 {
692   Tao            tao = (Tao)ptr;
693   TAO_LCL        *lclP = (TAO_LCL*)tao->data;
694   PetscReal      con2;
695   PetscBool      flag,pflag,set,pset,symmetric;
696   PetscErrorCode ierr;
697 
698   PetscFunctionBegin;
699   ierr = LCLComputeLagrangianAndGradient(tao->linesearch,X,f,G,tao);CHKERRQ(ierr);
700   ierr = LCLScatter(lclP,G,lclP->GL_U,lclP->GL_V);CHKERRQ(ierr);
701   ierr = VecDot(tao->constraints,tao->constraints,&con2);CHKERRQ(ierr);
702   lclP->aug = lclP->lgn + 0.5*lclP->rho*con2;
703 
704   /* Gradient of Aug. Lagrangian GAugL = GL + rho * J' c */
705   /*      WU = A' * c
706           WV = B' * c */
707   ierr = MatIsSymmetricKnown(tao->jacobian_state,&set,&flag);CHKERRQ(ierr);
708   if (tao->jacobian_state_pre) {
709     ierr = MatIsSymmetricKnown(tao->jacobian_state_pre,&pset,&pflag);CHKERRQ(ierr);
710   } else {
711     pset = pflag = PETSC_TRUE;
712   }
713   if (set && pset && flag && pflag) symmetric = PETSC_TRUE;
714   else symmetric = PETSC_FALSE;
715 
716   if (symmetric) {
717     ierr = MatMult(tao->jacobian_state,tao->constraints,lclP->GAugL_U);CHKERRQ(ierr);
718   } else {
719     ierr = MatMultTranspose(tao->jacobian_state,tao->constraints,lclP->GAugL_U);CHKERRQ(ierr);
720   }
721 
722   ierr = MatMultTranspose(tao->jacobian_design,tao->constraints,lclP->GAugL_V);CHKERRQ(ierr);
723   ierr = VecAYPX(lclP->GAugL_U,lclP->rho,lclP->GL_U);CHKERRQ(ierr);
724   ierr = VecAYPX(lclP->GAugL_V,lclP->rho,lclP->GL_V);CHKERRQ(ierr);
725   ierr = LCLGather(lclP,lclP->GAugL_U,lclP->GAugL_V,lclP->GAugL);CHKERRQ(ierr);
726 
727   f[0] = lclP->aug;
728   ierr = VecCopy(lclP->GAugL,G);CHKERRQ(ierr);
729   PetscFunctionReturn(0);
730 }
731 
732 #undef __FUNCT__
733 #define __FUNCT__ "LCLGather"
734 PetscErrorCode LCLGather(TAO_LCL *lclP, Vec u, Vec v, Vec x)
735 {
736   PetscErrorCode ierr;
737   PetscFunctionBegin;
738   ierr = VecScatterBegin(lclP->state_scatter, u, x, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr);
739   ierr = VecScatterEnd(lclP->state_scatter, u, x, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr);
740   ierr = VecScatterBegin(lclP->design_scatter, v, x, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr);
741   ierr = VecScatterEnd(lclP->design_scatter, v, x, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr);
742   PetscFunctionReturn(0);
743 
744 }
745 #undef __FUNCT__
746 #define __FUNCT__ "LCLScatter"
747 PetscErrorCode LCLScatter(TAO_LCL *lclP, Vec x, Vec u, Vec v)
748 {
749   PetscErrorCode ierr;
750   PetscFunctionBegin;
751   ierr = VecScatterBegin(lclP->state_scatter, x, u, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr);
752   ierr = VecScatterEnd(lclP->state_scatter, x, u, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr);
753   ierr = VecScatterBegin(lclP->design_scatter, x, v, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr);
754   ierr = VecScatterEnd(lclP->design_scatter, x, v, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr);
755   PetscFunctionReturn(0);
756 
757 }
758