xref: /petsc/src/tao/pde_constrained/impls/lcl/lcl.c (revision 4e6ef68f07cf4e7ffee1b93dbc438d90283d533b)
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   }
244   ierr = VecCopy(lclP->lamda,lclP->lamda0);CHKERRQ(ierr);
245   ierr = LCLComputeAugmentedLagrangianAndGradient(tao->linesearch,tao->solution,&lclP->aug,lclP->GAugL,tao);CHKERRQ(ierr);
246 
247   ierr = LCLScatter(lclP,lclP->GL,lclP->GL_U,lclP->GL_V);CHKERRQ(ierr);
248   ierr = LCLScatter(lclP,lclP->GAugL,lclP->GAugL_U,lclP->GAugL_V);CHKERRQ(ierr);
249 
250   /* Evaluate constraint norm */
251   ierr = VecNorm(tao->constraints, NORM_2, &cnorm);CHKERRQ(ierr);
252   ierr = VecNorm(lclP->GAugL, NORM_2, &mnorm);CHKERRQ(ierr);
253 
254   /* Monitor convergence */
255   ierr = TaoMonitor(tao, iter,f,mnorm,cnorm,step,&reason);CHKERRQ(ierr);
256 
257   while (reason == TAO_CONTINUE_ITERATING) {
258     /* Compute a descent direction for the linearly constrained subproblem
259        minimize f(u+du, v+dv)
260        s.t. A(u0,v0)du + B(u0,v0)dv = -g(u0,v0) */
261 
262     /* Store the points around the linearization */
263     ierr = VecCopy(lclP->U, lclP->U0);CHKERRQ(ierr);
264     ierr = VecCopy(lclP->V, lclP->V0);CHKERRQ(ierr);
265     ierr = VecCopy(lclP->GU,lclP->GU0);CHKERRQ(ierr);
266     ierr = VecCopy(lclP->GV,lclP->GV0);CHKERRQ(ierr);
267     ierr = VecCopy(lclP->GAugL_U,lclP->GAugL_U0);CHKERRQ(ierr);
268     ierr = VecCopy(lclP->GAugL_V,lclP->GAugL_V0);CHKERRQ(ierr);
269     ierr = VecCopy(lclP->GL_U,lclP->GL_U0);CHKERRQ(ierr);
270     ierr = VecCopy(lclP->GL_V,lclP->GL_V0);CHKERRQ(ierr);
271 
272     lclP->aug0 = lclP->aug;
273     lclP->lgn0 = lclP->lgn;
274 
275     /* Given the design variables, we need to project the current iterate
276        onto the linearized constraint.  We choose to fix the design variables
277        and solve the linear system for the state variables.  The resulting
278        point is the Newton direction */
279 
280     /* Solve r = A\con */
281     lclP->solve_type = LCL_FORWARD1;
282     ierr = VecSet(lclP->r,0.0);CHKERRQ(ierr); /*  Initial guess in CG */
283 
284     if (tao->jacobian_state_inv) {
285       ierr = MatMult(tao->jacobian_state_inv, tao->constraints, lclP->r);CHKERRQ(ierr);
286     } else {
287       ierr = KSPSetOperators(tao->ksp, tao->jacobian_state, tao->jacobian_state_pre);CHKERRQ(ierr);
288       ierr = KSPSolve(tao->ksp, tao->constraints,  lclP->r);CHKERRQ(ierr);
289       ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr);
290       tao->ksp_its += its;
291     }
292 
293     /* Set design step direction dv to zero */
294     ierr = VecSet(lclP->s, 0.0);CHKERRQ(ierr);
295 
296     /*
297        Check sufficient descent for constraint merit function .5*||con||^2
298        con' Ak r >= eps1 ||r||^(2+eps2)
299     */
300 
301     /* Compute WU= Ak' * con */
302     if (symmetric)  {
303       ierr = MatMult(tao->jacobian_state,tao->constraints,lclP->WU);CHKERRQ(ierr);
304     } else {
305       ierr = MatMultTranspose(tao->jacobian_state,tao->constraints,lclP->WU);CHKERRQ(ierr);
306     }
307     /* Compute r * Ak' * con */
308     ierr = VecDot(lclP->r,lclP->WU,&rWU);CHKERRQ(ierr);
309 
310     /* compute ||r||^(2+eps2) */
311     ierr = VecNorm(lclP->r,NORM_2,&r2);CHKERRQ(ierr);
312     r2 = PetscPowScalar(r2,2.0+lclP->eps2);
313     adec = lclP->eps1 * r2;
314 
315     if (rWU < adec) {
316       ierr = PetscInfo(tao,"Newton direction not descent for constraint, feasibility phase required");CHKERRQ(ierr);
317       if (lclP->verbose) {
318         ierr = PetscPrintf(PETSC_COMM_WORLD,"Newton direction not descent for constraint: %g -- using steepest descent\n",(double)descent);CHKERRQ(ierr);
319       }
320 
321       ierr = PetscInfo(tao,"Using steepest descent direction instead.\n");CHKERRQ(ierr);
322       ierr = VecSet(lclP->r,0.0);CHKERRQ(ierr);
323       ierr = VecAXPY(lclP->r,-1.0,lclP->WU);CHKERRQ(ierr);
324       ierr = VecDot(lclP->r,lclP->r,&rWU);CHKERRQ(ierr);
325       ierr = VecNorm(lclP->r,NORM_2,&r2);CHKERRQ(ierr);
326       r2 = PetscPowScalar(r2,2.0+lclP->eps2);
327       ierr = VecDot(lclP->r,lclP->GAugL_U,&descent);CHKERRQ(ierr);
328       adec = lclP->eps1 * r2;
329     }
330 
331 
332     /*
333        Check descent for aug. lagrangian
334        r' (GUk - Ak'*yk - rho*Ak'*con) <= -eps1 ||r||^(2+eps2)
335           GL_U = GUk - Ak'*yk
336           WU   = Ak'*con
337                                          adec=eps1||r||^(2+eps2)
338 
339        ==>
340        Check r'GL_U - rho*r'WU <= adec
341     */
342 
343     ierr = VecDot(lclP->r,lclP->GL_U,&rGL_U);
344     aldescent =  rGL_U - lclP->rho*rWU;
345     if (aldescent > -adec) {
346       if (lclP->verbose) {
347         ierr = PetscPrintf(PETSC_COMM_WORLD," Newton direction not descent for augmented Lagrangian: %g",(double)aldescent);CHKERRQ(ierr);
348       }
349       ierr = PetscInfo1(tao,"Newton direction not descent for augmented Lagrangian: %g",(double)aldescent);CHKERRQ(ierr);
350       lclP->rho =  (rGL_U - adec)/rWU;
351       if (lclP->rho > lclP->rhomax) {
352         lclP->rho = lclP->rhomax;
353         SETERRQ1(PETSC_COMM_WORLD,0,"rho=%g > rhomax, case not implemented.  Increase rhomax (-tao_lcl_rhomax)",(double)lclP->rho);
354       }
355       if (lclP->verbose) {
356         ierr = PetscPrintf(PETSC_COMM_WORLD,"  Increasing penalty parameter to %g\n",(double)lclP->rho);CHKERRQ(ierr);
357       }
358       ierr = PetscInfo1(tao,"  Increasing penalty parameter to %g",(double)lclP->rho);
359     }
360 
361     ierr = LCLComputeAugmentedLagrangianAndGradient(tao->linesearch,tao->solution,&lclP->aug,lclP->GAugL,tao);CHKERRQ(ierr);
362     ierr = LCLScatter(lclP,lclP->GL,lclP->GL_U,lclP->GL_V);CHKERRQ(ierr);
363     ierr = LCLScatter(lclP,lclP->GAugL,lclP->GAugL_U,lclP->GAugL_V);CHKERRQ(ierr);
364 
365     /* We now minimize the augmented Lagrangian along the Newton direction */
366     ierr = VecScale(lclP->r,-1.0);CHKERRQ(ierr);
367     ierr = LCLGather(lclP, lclP->r,lclP->s,tao->stepdirection);CHKERRQ(ierr);
368     ierr = VecScale(lclP->r,-1.0);CHKERRQ(ierr);
369     ierr = LCLGather(lclP, lclP->GAugL_U0, lclP->GAugL_V0, lclP->GAugL);CHKERRQ(ierr);
370     ierr = LCLGather(lclP, lclP->U0,lclP->V0,lclP->X0);CHKERRQ(ierr);
371 
372     lclP->recompute_jacobian_flag = PETSC_TRUE;
373 
374     ierr = TaoLineSearchSetInitialStepLength(tao->linesearch,1.0);CHKERRQ(ierr);
375     ierr = TaoLineSearchSetType(tao->linesearch, TAOLINESEARCHMT);CHKERRQ(ierr);
376     ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr);
377     ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &lclP->aug, lclP->GAugL, tao->stepdirection, &step, &ls_reason);CHKERRQ(ierr);
378     if (lclP->verbose) {
379       ierr = PetscPrintf(PETSC_COMM_WORLD,"Steplength = %g\n",(double)step);CHKERRQ(ierr);
380     }
381 
382     ierr = LCLScatter(lclP,tao->solution,lclP->U,lclP->V);CHKERRQ(ierr);
383     ierr = TaoComputeObjectiveAndGradient(tao,tao->solution,&f,tao->gradient);CHKERRQ(ierr);
384     ierr = LCLScatter(lclP,tao->gradient,lclP->GU,lclP->GV);CHKERRQ(ierr);
385 
386     ierr = LCLScatter(lclP,lclP->GAugL,lclP->GAugL_U,lclP->GAugL_V);CHKERRQ(ierr);
387 
388     /* Check convergence */
389     ierr = VecNorm(lclP->GAugL, NORM_2, &mnorm);CHKERRQ(ierr);
390     ierr = VecNorm(tao->constraints, NORM_2, &cnorm);CHKERRQ(ierr);
391     ierr = TaoMonitor(tao, iter,f,mnorm,cnorm,step,&reason);CHKERRQ(ierr);
392     if (reason != TAO_CONTINUE_ITERATING){
393       break;
394     }
395 
396     /* TODO: use a heuristic to choose how many iterations should be performed within phase 2 */
397     for (phase2_iter=0; phase2_iter<lclP->phase2_niter; phase2_iter++){
398       /* We now minimize the objective function starting from the fraction of
399          the Newton point accepted by applying one step of a reduced-space
400          method.  The optimization problem is:
401 
402          minimize f(u+du, v+dv)
403          s. t.    A(u0,v0)du + B(u0,v0)du = -alpha g(u0,v0)
404 
405          In particular, we have that
406          du = -inv(A)*(Bdv + alpha g) */
407 
408       ierr = TaoComputeJacobianState(tao,lclP->X0,tao->jacobian_state,tao->jacobian_state_pre,tao->jacobian_state_inv);CHKERRQ(ierr);
409       ierr = TaoComputeJacobianDesign(tao,lclP->X0,tao->jacobian_design);CHKERRQ(ierr);
410 
411       /* Store V and constraints */
412       ierr = VecCopy(lclP->V, lclP->V1);CHKERRQ(ierr);
413       ierr = VecCopy(tao->constraints,lclP->con1);CHKERRQ(ierr);
414 
415       /* Compute multipliers */
416       /* p1 */
417       ierr = VecSet(lclP->lamda,0.0);CHKERRQ(ierr); /*  Initial guess in CG */
418       lclP->solve_type = LCL_ADJOINT1;
419       ierr = MatIsSymmetricKnown(tao->jacobian_state,&set,&flag);CHKERRQ(ierr);
420       if (tao->jacobian_state_pre) {
421         ierr = MatIsSymmetricKnown(tao->jacobian_state_pre,&pset,&pflag);CHKERRQ(ierr);
422       } else {
423         pset = pflag = PETSC_TRUE;
424       }
425       if (set && pset && flag && pflag) symmetric = PETSC_TRUE;
426       else symmetric = PETSC_FALSE;
427 
428       if (tao->jacobian_state_inv) {
429         if (symmetric) {
430           ierr = MatMult(tao->jacobian_state_inv, lclP->GAugL_U, lclP->lamda);CHKERRQ(ierr);
431         } else {
432           ierr = MatMultTranspose(tao->jacobian_state_inv, lclP->GAugL_U, lclP->lamda);CHKERRQ(ierr);
433         }
434       } else {
435         if (symmetric) {
436           ierr = KSPSolve(tao->ksp, lclP->GAugL_U,  lclP->lamda);CHKERRQ(ierr);
437         } else {
438           ierr = KSPSolveTranspose(tao->ksp, lclP->GAugL_U,  lclP->lamda);CHKERRQ(ierr);
439         }
440         ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr);
441         tao->ksp_its += its;
442       }
443       ierr = MatMultTranspose(tao->jacobian_design,lclP->lamda,lclP->g1);CHKERRQ(ierr);
444       ierr = VecAXPY(lclP->g1,-1.0,lclP->GAugL_V);CHKERRQ(ierr);
445 
446       /* Compute the limited-memory quasi-newton direction */
447       if (iter > 0) {
448         ierr = MatLMVMSolve(lclP->R,lclP->g1,lclP->s);CHKERRQ(ierr);
449         ierr = VecDot(lclP->s,lclP->g1,&descent);CHKERRQ(ierr);
450         if (descent < 0e-8) {
451           if (lclP->verbose) {
452             ierr = PetscPrintf(PETSC_COMM_WORLD,"Reduced-space direction not descent: %g\n",(double)descent);CHKERRQ(ierr);
453           }
454           ierr = VecCopy(lclP->g1,lclP->s);CHKERRQ(ierr);
455         }
456       } else {
457         ierr = VecCopy(lclP->g1,lclP->s);CHKERRQ(ierr);
458       }
459       ierr = VecScale(lclP->g1,-1.0);CHKERRQ(ierr);
460 
461       /* Recover the full space direction */
462       ierr = MatMult(tao->jacobian_design,lclP->s,lclP->WU);CHKERRQ(ierr);
463       /* ierr = VecSet(lclP->r,0.0);CHKERRQ(ierr); */ /*  Initial guess in CG */
464       lclP->solve_type = LCL_FORWARD2;
465       if (tao->jacobian_state_inv) {
466         ierr = MatMult(tao->jacobian_state_inv,lclP->WU,lclP->r);CHKERRQ(ierr);
467       } else {
468         ierr = KSPSolve(tao->ksp, lclP->WU, lclP->r);CHKERRQ(ierr);
469         ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr);
470         tao->ksp_its += its;
471       }
472 
473       /* We now minimize the augmented Lagrangian along the direction -r,s */
474       ierr = VecScale(lclP->r, -1.0);CHKERRQ(ierr);
475       ierr = LCLGather(lclP,lclP->r,lclP->s,tao->stepdirection);CHKERRQ(ierr);
476       ierr = VecScale(lclP->r, -1.0);CHKERRQ(ierr);
477       lclP->recompute_jacobian_flag = PETSC_TRUE;
478 
479       ierr = TaoLineSearchSetInitialStepLength(tao->linesearch,1.0);CHKERRQ(ierr);
480       ierr = TaoLineSearchSetType(tao->linesearch,TAOLINESEARCHMT);CHKERRQ(ierr);
481       ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr);
482       ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &lclP->aug, lclP->GAugL, tao->stepdirection,&step,&ls_reason);CHKERRQ(ierr);
483       if (lclP->verbose){
484         ierr = PetscPrintf(PETSC_COMM_WORLD,"Reduced-space steplength =  %g\n",(double)step);CHKERRQ(ierr);
485       }
486 
487       ierr = LCLScatter(lclP,tao->solution,lclP->U,lclP->V);CHKERRQ(ierr);
488       ierr = LCLScatter(lclP,lclP->GL,lclP->GL_U,lclP->GL_V);CHKERRQ(ierr);
489       ierr = LCLScatter(lclP,lclP->GAugL,lclP->GAugL_U,lclP->GAugL_V);CHKERRQ(ierr);
490       ierr = TaoComputeObjectiveAndGradient(tao,tao->solution,&f,tao->gradient);CHKERRQ(ierr);
491       ierr = LCLScatter(lclP,tao->gradient,lclP->GU,lclP->GV);CHKERRQ(ierr);
492 
493       /* Compute the reduced gradient at the new point */
494 
495       ierr = TaoComputeJacobianState(tao,lclP->X0,tao->jacobian_state,tao->jacobian_state_pre,tao->jacobian_state_inv);CHKERRQ(ierr);
496       ierr = TaoComputeJacobianDesign(tao,lclP->X0,tao->jacobian_design);CHKERRQ(ierr);
497 
498       /* p2 */
499       /* Compute multipliers, using lamda-rho*con as an initial guess in PCG */
500       if (phase2_iter==0){
501         ierr = VecWAXPY(lclP->lamda,-lclP->rho,lclP->con1,lclP->lamda0);CHKERRQ(ierr);
502       } else {
503         ierr = VecAXPY(lclP->lamda,-lclP->rho,tao->constraints);CHKERRQ(ierr);
504       }
505 
506       ierr = MatIsSymmetricKnown(tao->jacobian_state,&set,&flag);CHKERRQ(ierr);
507       if (tao->jacobian_state_pre) {
508         ierr = MatIsSymmetricKnown(tao->jacobian_state_pre,&pset,&pflag);CHKERRQ(ierr);
509       } else {
510         pset = pflag = PETSC_TRUE;
511       }
512       if (set && pset && flag && pflag) symmetric = PETSC_TRUE;
513       else symmetric = PETSC_FALSE;
514 
515       lclP->solve_type = LCL_ADJOINT2;
516       if (tao->jacobian_state_inv) {
517         if (symmetric) {
518           ierr = MatMult(tao->jacobian_state_inv, lclP->GU, lclP->lamda);CHKERRQ(ierr);
519         } else {
520           ierr = MatMultTranspose(tao->jacobian_state_inv, lclP->GU, lclP->lamda);CHKERRQ(ierr);
521         }
522       } else {
523         if (symmetric) {
524           ierr = KSPSolve(tao->ksp, lclP->GU,  lclP->lamda);CHKERRQ(ierr);
525         } else {
526           ierr = KSPSolveTranspose(tao->ksp, lclP->GU,  lclP->lamda);CHKERRQ(ierr);
527         }
528         ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr);
529         tao->ksp_its += its;
530       }
531 
532       ierr = MatMultTranspose(tao->jacobian_design,lclP->lamda,lclP->g2);CHKERRQ(ierr);
533       ierr = VecAXPY(lclP->g2,-1.0,lclP->GV);CHKERRQ(ierr);
534 
535       ierr = VecScale(lclP->g2,-1.0);CHKERRQ(ierr);
536 
537       /* Update the quasi-newton approximation */
538       if (phase2_iter >= 0){
539         ierr = MatLMVMSetPrev(lclP->R,lclP->V1,lclP->g1);
540       }
541       ierr = MatLMVMUpdate(lclP->R,lclP->V,lclP->g2);CHKERRQ(ierr);
542       /* 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 */
543 
544     }
545 
546     ierr = VecCopy(lclP->lamda,lclP->lamda0);CHKERRQ(ierr);
547 
548     /* Evaluate Function, Gradient, Constraints, and Jacobian */
549     ierr = TaoComputeObjectiveAndGradient(tao,tao->solution,&f,tao->gradient);CHKERRQ(ierr);
550     ierr = LCLScatter(lclP,tao->solution,lclP->U,lclP->V);CHKERRQ(ierr);
551     ierr = LCLScatter(lclP,tao->gradient,lclP->GU,lclP->GV);CHKERRQ(ierr);
552 
553     ierr = TaoComputeJacobianState(tao,tao->solution,tao->jacobian_state,tao->jacobian_state_pre,tao->jacobian_state_inv);CHKERRQ(ierr);
554     ierr = TaoComputeJacobianDesign(tao,tao->solution,tao->jacobian_design);CHKERRQ(ierr);
555     ierr = TaoComputeConstraints(tao,tao->solution, tao->constraints);CHKERRQ(ierr);
556 
557     ierr = LCLComputeAugmentedLagrangianAndGradient(tao->linesearch,tao->solution,&lclP->aug,lclP->GAugL,tao);CHKERRQ(ierr);
558 
559     ierr = VecNorm(lclP->GAugL, NORM_2, &mnorm);CHKERRQ(ierr);
560 
561     /* Evaluate constraint norm */
562     ierr = VecNorm(tao->constraints, NORM_2, &cnorm);CHKERRQ(ierr);
563 
564     /* Monitor convergence */
565     iter++;
566     ierr = TaoMonitor(tao, iter,f,mnorm,cnorm,step,&reason);CHKERRQ(ierr);
567   }
568   ierr = MatDestroy(&lclP->R);CHKERRQ(ierr);
569   PetscFunctionReturn(0);
570 }
571 
572 EXTERN_C_BEGIN
573 #undef __FUNCT__
574 #define __FUNCT__ "TaoCreate_LCL"
575 PetscErrorCode TaoCreate_LCL(Tao tao)
576 {
577   TAO_LCL        *lclP;
578   PetscErrorCode ierr;
579   const char     *morethuente_type = TAOLINESEARCHMT;
580 
581   PetscFunctionBegin;
582   tao->ops->setup = TaoSetup_LCL;
583   tao->ops->solve = TaoSolve_LCL;
584   tao->ops->view = TaoView_LCL;
585   tao->ops->setfromoptions = TaoSetFromOptions_LCL;
586   tao->ops->destroy = TaoDestroy_LCL;
587   ierr = PetscNewLog(tao,&lclP);CHKERRQ(ierr);
588   tao->data = (void*)lclP;
589 
590   tao->max_it=200;
591 #if defined(PETSC_USE_REAL_SINGLE)
592   tao->fatol=1e-5;
593   tao->frtol=1e-5;
594 #else
595   tao->fatol=1e-8;
596   tao->frtol=1e-8;
597 #endif
598   tao->catol=1e-4;
599   tao->crtol=1e-4;
600   tao->gttol=1e-4;
601   tao->gatol=1e-4;
602   tao->grtol=1e-4;
603   lclP->rho0 = 1.0e-4;
604   lclP->rhomax=1e5;
605   lclP->eps1 = 1.0e-8;
606   lclP->eps2 = 0.0;
607   lclP->solve_type=2;
608   lclP->tau[0] = lclP->tau[1] = lclP->tau[2] = lclP->tau[3] = 1.0e-4;
609   ierr = TaoLineSearchCreate(((PetscObject)tao)->comm, &tao->linesearch);CHKERRQ(ierr);
610   ierr = TaoLineSearchSetType(tao->linesearch, morethuente_type);CHKERRQ(ierr);
611 
612   ierr = TaoLineSearchSetObjectiveAndGradientRoutine(tao->linesearch,LCLComputeAugmentedLagrangianAndGradient, tao);CHKERRQ(ierr);
613   ierr = KSPCreate(((PetscObject)tao)->comm,&tao->ksp);CHKERRQ(ierr);
614   ierr = KSPSetFromOptions(tao->ksp);CHKERRQ(ierr);
615   PetscFunctionReturn(0);
616 }
617 EXTERN_C_END
618 
619 #undef __FUNCT__
620 #define __FUNCT__ "LCLComputeLagrangianAndGradient"
621 static PetscErrorCode LCLComputeLagrangianAndGradient(TaoLineSearch ls, Vec X, PetscReal *f, Vec G, void *ptr)
622 {
623   Tao            tao = (Tao)ptr;
624   TAO_LCL        *lclP = (TAO_LCL*)tao->data;
625   PetscBool      set,pset,flag,pflag,symmetric;
626   PetscReal      cdotl;
627   PetscErrorCode ierr;
628 
629   PetscFunctionBegin;
630   ierr = TaoComputeObjectiveAndGradient(tao,X,f,G);CHKERRQ(ierr);
631   ierr = LCLScatter(lclP,G,lclP->GU,lclP->GV);CHKERRQ(ierr);
632   if (lclP->recompute_jacobian_flag) {
633     ierr = TaoComputeJacobianState(tao,X,tao->jacobian_state,tao->jacobian_state_pre,tao->jacobian_state_inv);CHKERRQ(ierr);
634     ierr = TaoComputeJacobianDesign(tao,X,tao->jacobian_design);CHKERRQ(ierr);
635   }
636   ierr = TaoComputeConstraints(tao,X, tao->constraints);CHKERRQ(ierr);
637   ierr = MatIsSymmetricKnown(tao->jacobian_state,&set,&flag);CHKERRQ(ierr);
638   if (tao->jacobian_state_pre) {
639     ierr = MatIsSymmetricKnown(tao->jacobian_state_pre,&pset,&pflag);CHKERRQ(ierr);
640   } else {
641     pset = pflag = PETSC_TRUE;
642   }
643   if (set && pset && flag && pflag) symmetric = PETSC_TRUE;
644   else symmetric = PETSC_FALSE;
645 
646   ierr = VecDot(lclP->lamda0, tao->constraints, &cdotl);CHKERRQ(ierr);
647   lclP->lgn = *f - cdotl;
648 
649   /* Gradient of Lagrangian GL = G - J' * lamda */
650   /*      WU = A' * WL
651           WV = B' * WL */
652   if (symmetric) {
653     ierr = MatMult(tao->jacobian_state,lclP->lamda0,lclP->GL_U);CHKERRQ(ierr);
654   } else {
655     ierr = MatMultTranspose(tao->jacobian_state,lclP->lamda0,lclP->GL_U);CHKERRQ(ierr);
656   }
657   ierr = MatMultTranspose(tao->jacobian_design,lclP->lamda0,lclP->GL_V);CHKERRQ(ierr);
658   ierr = VecScale(lclP->GL_U,-1.0);CHKERRQ(ierr);
659   ierr = VecScale(lclP->GL_V,-1.0);CHKERRQ(ierr);
660   ierr = VecAXPY(lclP->GL_U,1.0,lclP->GU);CHKERRQ(ierr);
661   ierr = VecAXPY(lclP->GL_V,1.0,lclP->GV);CHKERRQ(ierr);
662   ierr = LCLGather(lclP,lclP->GL_U,lclP->GL_V,lclP->GL);CHKERRQ(ierr);
663 
664   f[0] = lclP->lgn;
665   ierr = VecCopy(lclP->GL,G);
666   PetscFunctionReturn(0);
667 }
668 
669 #undef __FUNCT__
670 #define __FUNCT__ "LCLComputeAugmentedLagrangianAndGradient"
671 static PetscErrorCode LCLComputeAugmentedLagrangianAndGradient(TaoLineSearch ls, Vec X, PetscReal *f, Vec G, void *ptr)
672 {
673   Tao            tao = (Tao)ptr;
674   TAO_LCL        *lclP = (TAO_LCL*)tao->data;
675   PetscReal      con2;
676   PetscBool      flag,pflag,set,pset,symmetric;
677   PetscErrorCode ierr;
678 
679   PetscFunctionBegin;
680   ierr = LCLComputeLagrangianAndGradient(tao->linesearch,X,f,G,tao);CHKERRQ(ierr);
681   ierr = LCLScatter(lclP,G,lclP->GL_U,lclP->GL_V);CHKERRQ(ierr);
682   ierr = VecDot(tao->constraints,tao->constraints,&con2);CHKERRQ(ierr);
683   lclP->aug = lclP->lgn + 0.5*lclP->rho*con2;
684 
685   /* Gradient of Aug. Lagrangian GAugL = GL + rho * J' c */
686   /*      WU = A' * c
687           WV = B' * c */
688   ierr = MatIsSymmetricKnown(tao->jacobian_state,&set,&flag);CHKERRQ(ierr);
689   if (tao->jacobian_state_pre) {
690     ierr = MatIsSymmetricKnown(tao->jacobian_state_pre,&pset,&pflag);CHKERRQ(ierr);
691   } else {
692     pset = pflag = PETSC_TRUE;
693   }
694   if (set && pset && flag && pflag) symmetric = PETSC_TRUE;
695   else symmetric = PETSC_FALSE;
696 
697   if (symmetric) {
698     ierr = MatMult(tao->jacobian_state,tao->constraints,lclP->GAugL_U);CHKERRQ(ierr);
699   } else {
700     ierr = MatMultTranspose(tao->jacobian_state,tao->constraints,lclP->GAugL_U);CHKERRQ(ierr);
701   }
702 
703   ierr = MatMultTranspose(tao->jacobian_design,tao->constraints,lclP->GAugL_V);CHKERRQ(ierr);
704   ierr = VecAYPX(lclP->GAugL_U,lclP->rho,lclP->GL_U);CHKERRQ(ierr);
705   ierr = VecAYPX(lclP->GAugL_V,lclP->rho,lclP->GL_V);CHKERRQ(ierr);
706   ierr = LCLGather(lclP,lclP->GAugL_U,lclP->GAugL_V,lclP->GAugL);CHKERRQ(ierr);
707 
708   f[0] = lclP->aug;
709   ierr = VecCopy(lclP->GAugL,G);CHKERRQ(ierr);
710   PetscFunctionReturn(0);
711 }
712 
713 #undef __FUNCT__
714 #define __FUNCT__ "LCLGather"
715 PetscErrorCode LCLGather(TAO_LCL *lclP, Vec u, Vec v, Vec x)
716 {
717   PetscErrorCode ierr;
718   PetscFunctionBegin;
719   ierr = VecScatterBegin(lclP->state_scatter, u, x, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr);
720   ierr = VecScatterEnd(lclP->state_scatter, u, x, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr);
721   ierr = VecScatterBegin(lclP->design_scatter, v, x, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr);
722   ierr = VecScatterEnd(lclP->design_scatter, v, x, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr);
723   PetscFunctionReturn(0);
724 
725 }
726 #undef __FUNCT__
727 #define __FUNCT__ "LCLScatter"
728 PetscErrorCode LCLScatter(TAO_LCL *lclP, Vec x, Vec u, Vec v)
729 {
730   PetscErrorCode ierr;
731   PetscFunctionBegin;
732   ierr = VecScatterBegin(lclP->state_scatter, x, u, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr);
733   ierr = VecScatterEnd(lclP->state_scatter, x, u, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr);
734   ierr = VecScatterBegin(lclP->design_scatter, x, v, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr);
735   ierr = VecScatterEnd(lclP->design_scatter, x, v, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr);
736   PetscFunctionReturn(0);
737 
738 }
739