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