xref: /petsc/src/tao/pde_constrained/impls/lcl/lcl.c (revision 63a3b9bc7a1f24f247904ccba9383635fe6abade)
1aaa7dc30SBarry Smith #include <../src/tao/pde_constrained/impls/lcl/lcl.h>
2a7e14dcfSSatish Balay static PetscErrorCode LCLComputeLagrangianAndGradient(TaoLineSearch,Vec,PetscReal*,Vec,void*);
3a7e14dcfSSatish Balay static PetscErrorCode LCLComputeAugmentedLagrangianAndGradient(TaoLineSearch,Vec,PetscReal*,Vec,void*);
4a7e14dcfSSatish Balay static PetscErrorCode LCLScatter(TAO_LCL*,Vec,Vec,Vec);
5a7e14dcfSSatish Balay static PetscErrorCode LCLGather(TAO_LCL*,Vec,Vec,Vec);
6a7e14dcfSSatish Balay 
7441846f8SBarry Smith static PetscErrorCode TaoDestroy_LCL(Tao tao)
8a7e14dcfSSatish Balay {
9a7e14dcfSSatish Balay   TAO_LCL        *lclP = (TAO_LCL*)tao->data;
10f06e3bfaSBarry Smith 
11a7e14dcfSSatish Balay   PetscFunctionBegin;
12a7e14dcfSSatish Balay   if (tao->setupcalled) {
139566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&lclP->R));
149566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->lamda));
159566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->lamda0));
169566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->WL));
179566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->W));
189566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->X0));
199566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->G0));
209566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->GL));
219566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->GAugL));
229566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->dbar));
239566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->U));
249566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->U0));
259566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->V));
269566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->V0));
279566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->V1));
289566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->GU));
299566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->GV));
309566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->GU0));
319566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->GV0));
329566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->GL_U));
339566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->GL_V));
349566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->GAugL_U));
359566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->GAugL_V));
369566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->GL_U0));
379566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->GL_V0));
389566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->GAugL_U0));
399566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->GAugL_V0));
409566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->DU));
419566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->DV));
429566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->WU));
439566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->WV));
449566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->g1));
459566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->g2));
469566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->con1));
47a7e14dcfSSatish Balay 
489566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->r));
499566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lclP->s));
50a7e14dcfSSatish Balay 
519566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&tao->state_is));
529566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&tao->design_is));
53a7e14dcfSSatish Balay 
549566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&lclP->state_scatter));
559566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&lclP->design_scatter));
56a7e14dcfSSatish Balay   }
579566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lclP->R));
589566063dSJacob Faibussowitsch   PetscCall(PetscFree(tao->data));
59a7e14dcfSSatish Balay   PetscFunctionReturn(0);
60a7e14dcfSSatish Balay }
61a7e14dcfSSatish Balay 
624416b707SBarry Smith static PetscErrorCode TaoSetFromOptions_LCL(PetscOptionItems *PetscOptionsObject,Tao tao)
63a7e14dcfSSatish Balay {
64a7e14dcfSSatish Balay   TAO_LCL        *lclP = (TAO_LCL*)tao->data;
65a7e14dcfSSatish Balay 
66a7e14dcfSSatish Balay   PetscFunctionBegin;
67d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject,"Linearly-Constrained Augmented Lagrangian Method for PDE-constrained optimization");
689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_lcl_eps1","epsilon 1 tolerance","",lclP->eps1,&lclP->eps1,NULL));
699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_lcl_eps2","epsilon 2 tolerance","",lclP->eps2,&lclP->eps2,NULL));
709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_lcl_rho0","init value for rho","",lclP->rho0,&lclP->rho0,NULL));
719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_lcl_rhomax","max value for rho","",lclP->rhomax,&lclP->rhomax,NULL));
72a7e14dcfSSatish Balay   lclP->phase2_niter = 1;
739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-tao_lcl_phase2_niter","Number of phase 2 iterations in LCL algorithm","",lclP->phase2_niter,&lclP->phase2_niter,NULL));
74a7e14dcfSSatish Balay   lclP->verbose = PETSC_FALSE;
759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-tao_lcl_verbose","Print verbose output","",lclP->verbose,&lclP->verbose,NULL));
76a7e14dcfSSatish Balay   lclP->tau[0] = lclP->tau[1] = lclP->tau[2] = lclP->tau[3] = 1.0e-4;
779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_lcl_tola","Tolerance for first forward solve","",lclP->tau[0],&lclP->tau[0],NULL));
789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_lcl_tolb","Tolerance for first adjoint solve","",lclP->tau[1],&lclP->tau[1],NULL));
799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_lcl_tolc","Tolerance for second forward solve","",lclP->tau[2],&lclP->tau[2],NULL));
809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_lcl_told","Tolerance for second adjoint solve","",lclP->tau[3],&lclP->tau[3],NULL));
81d0609cedSBarry Smith   PetscOptionsHeadEnd();
829566063dSJacob Faibussowitsch   PetscCall(TaoLineSearchSetFromOptions(tao->linesearch));
839566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(lclP->R));
84a7e14dcfSSatish Balay   PetscFunctionReturn(0);
85a7e14dcfSSatish Balay }
86a7e14dcfSSatish Balay 
87441846f8SBarry Smith static PetscErrorCode TaoView_LCL(Tao tao, PetscViewer viewer)
88a7e14dcfSSatish Balay {
89a7e14dcfSSatish Balay   return 0;
90a7e14dcfSSatish Balay }
91a7e14dcfSSatish Balay 
92441846f8SBarry Smith static PetscErrorCode TaoSetup_LCL(Tao tao)
93a7e14dcfSSatish Balay {
94a7e14dcfSSatish Balay   TAO_LCL        *lclP = (TAO_LCL*)tao->data;
95a7e14dcfSSatish Balay   PetscInt       lo, hi, nlocalstate, nlocaldesign;
96a7e14dcfSSatish Balay   IS             is_state, is_design;
97f06e3bfaSBarry Smith 
98a7e14dcfSSatish Balay   PetscFunctionBegin;
993c859ba3SBarry Smith   PetscCheck(tao->state_is,PetscObjectComm((PetscObject)tao),PETSC_ERR_ARG_WRONGSTATE,"LCL Solver requires an initial state index set -- use TaoSetStateIS()");
1009566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->solution, &tao->gradient));
1019566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->solution, &tao->stepdirection));
1029566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->solution, &lclP->W));
1039566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->solution, &lclP->X0));
1049566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->solution, &lclP->G0));
1059566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->solution, &lclP->GL));
1069566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->solution, &lclP->GAugL));
107a7e14dcfSSatish Balay 
1089566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->constraints, &lclP->lamda));
1099566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->constraints, &lclP->WL));
1109566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->constraints, &lclP->lamda0));
1119566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->constraints, &lclP->con1));
112a7e14dcfSSatish Balay 
1139566063dSJacob Faibussowitsch   PetscCall(VecSet(lclP->lamda,0.0));
114a7e14dcfSSatish Balay 
1159566063dSJacob Faibussowitsch   PetscCall(VecGetSize(tao->solution, &lclP->n));
1169566063dSJacob Faibussowitsch   PetscCall(VecGetSize(tao->constraints, &lclP->m));
117a7e14dcfSSatish Balay 
1189566063dSJacob Faibussowitsch   PetscCall(VecCreate(((PetscObject)tao)->comm,&lclP->U));
1199566063dSJacob Faibussowitsch   PetscCall(VecCreate(((PetscObject)tao)->comm,&lclP->V));
1209566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(tao->state_is,&nlocalstate));
1219566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(tao->design_is,&nlocaldesign));
1229566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(lclP->U,nlocalstate,lclP->m));
1239566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(lclP->V,nlocaldesign,lclP->n-lclP->m));
1249566063dSJacob Faibussowitsch   PetscCall(VecSetType(lclP->U,((PetscObject)(tao->solution))->type_name));
1259566063dSJacob Faibussowitsch   PetscCall(VecSetType(lclP->V,((PetscObject)(tao->solution))->type_name));
1269566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(lclP->U));
1279566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(lclP->V));
1289566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->DU));
1299566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->U0));
1309566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->GU));
1319566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->GU0));
1329566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->GAugL_U));
1339566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->GL_U));
1349566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->GAugL_U0));
1359566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->GL_U0));
1369566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->WU));
1379566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->r));
1389566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->V0));
1399566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->V1));
1409566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->DV));
1419566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->s));
1429566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->GV));
1439566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->GV0));
1449566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->dbar));
1459566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->GAugL_V));
1469566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->GL_V));
1479566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->GAugL_V0));
1489566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->GL_V0));
1499566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->WV));
1509566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->g1));
1519566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->g2));
152a7e14dcfSSatish Balay 
153a7e14dcfSSatish Balay   /* create scatters for state, design subvecs */
1549566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRange(lclP->U,&lo,&hi));
1559566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(((PetscObject)lclP->U)->comm,hi-lo,lo,1,&is_state));
1569566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRange(lclP->V,&lo,&hi));
157a7e14dcfSSatish Balay   if (0) {
158a7e14dcfSSatish Balay     PetscInt sizeU,sizeV;
1599566063dSJacob Faibussowitsch     PetscCall(VecGetSize(lclP->U,&sizeU));
1609566063dSJacob Faibussowitsch     PetscCall(VecGetSize(lclP->V,&sizeV));
161*63a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD,"size(U)=%" PetscInt_FMT ", size(V)=%" PetscInt_FMT "\n",sizeU,sizeV));
162a7e14dcfSSatish Balay   }
1639566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(((PetscObject)lclP->V)->comm,hi-lo,lo,1,&is_design));
1649566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(tao->solution,tao->state_is,lclP->U,is_state,&lclP->state_scatter));
1659566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(tao->solution,tao->design_is,lclP->V,is_design,&lclP->design_scatter));
1669566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_state));
1679566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_design));
168a7e14dcfSSatish Balay   PetscFunctionReturn(0);
169a7e14dcfSSatish Balay }
170a7e14dcfSSatish Balay 
171441846f8SBarry Smith static PetscErrorCode TaoSolve_LCL(Tao tao)
172a7e14dcfSSatish Balay {
173a7e14dcfSSatish Balay   TAO_LCL                      *lclP = (TAO_LCL*)tao->data;
1748931d482SJason Sarich   PetscInt                     phase2_iter,nlocal,its;
175e4cb33bbSBarry Smith   TaoLineSearchConvergedReason ls_reason = TAOLINESEARCH_CONTINUE_ITERATING;
176a7e14dcfSSatish Balay   PetscReal                    step=1.0,f, descent, aldescent;
177a7e14dcfSSatish Balay   PetscReal                    cnorm, mnorm;
178a7e14dcfSSatish Balay   PetscReal                    adec,r2,rGL_U,rWU;
179a7e14dcfSSatish Balay   PetscBool                    set,pset,flag,pflag,symmetric;
180a7e14dcfSSatish Balay 
181f06e3bfaSBarry Smith   PetscFunctionBegin;
182a7e14dcfSSatish Balay   lclP->rho = lclP->rho0;
1839566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(lclP->U,&nlocal));
1849566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(lclP->V,&nlocal));
1859566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(lclP->R, nlocal, nlocal, lclP->n-lclP->m, lclP->n-lclP->m));
1869566063dSJacob Faibussowitsch   PetscCall(MatLMVMAllocate(lclP->R,lclP->V,lclP->V));
187a7e14dcfSSatish Balay   lclP->recompute_jacobian_flag = PETSC_TRUE;
188a7e14dcfSSatish Balay 
189a7e14dcfSSatish Balay   /* Scatter to U,V */
1909566063dSJacob Faibussowitsch   PetscCall(LCLScatter(lclP,tao->solution,lclP->U,lclP->V));
191a7e14dcfSSatish Balay 
192a7e14dcfSSatish Balay   /* Evaluate Function, Gradient, Constraints, and Jacobian */
1939566063dSJacob Faibussowitsch   PetscCall(TaoComputeObjectiveAndGradient(tao,tao->solution,&f,tao->gradient));
1949566063dSJacob Faibussowitsch   PetscCall(TaoComputeJacobianState(tao,tao->solution,tao->jacobian_state,tao->jacobian_state_pre,tao->jacobian_state_inv));
1959566063dSJacob Faibussowitsch   PetscCall(TaoComputeJacobianDesign(tao,tao->solution,tao->jacobian_design));
1969566063dSJacob Faibussowitsch   PetscCall(TaoComputeConstraints(tao,tao->solution, tao->constraints));
197a7e14dcfSSatish Balay 
198a7e14dcfSSatish Balay   /* Scatter gradient to GU,GV */
1999566063dSJacob Faibussowitsch   PetscCall(LCLScatter(lclP,tao->gradient,lclP->GU,lclP->GV));
200a7e14dcfSSatish Balay 
201a7e14dcfSSatish Balay   /* Evaluate Lagrangian function and gradient */
202a7e14dcfSSatish Balay   /* p0 */
2039566063dSJacob Faibussowitsch   PetscCall(VecSet(lclP->lamda,0.0)); /*  Initial guess in CG */
2049566063dSJacob Faibussowitsch   PetscCall(MatIsSymmetricKnown(tao->jacobian_state,&set,&flag));
205a7e14dcfSSatish Balay   if (tao->jacobian_state_pre) {
2069566063dSJacob Faibussowitsch     PetscCall(MatIsSymmetricKnown(tao->jacobian_state_pre,&pset,&pflag));
207a7e14dcfSSatish Balay   } else {
208a7e14dcfSSatish Balay     pset = pflag = PETSC_TRUE;
209a7e14dcfSSatish Balay   }
210f06e3bfaSBarry Smith   if (set && pset && flag && pflag) symmetric = PETSC_TRUE;
211f06e3bfaSBarry Smith   else symmetric = PETSC_FALSE;
212a7e14dcfSSatish Balay 
213a7e14dcfSSatish Balay   lclP->solve_type = LCL_ADJOINT2;
214a7e14dcfSSatish Balay   if (tao->jacobian_state_inv) {
215a7e14dcfSSatish Balay     if (symmetric) {
2169566063dSJacob Faibussowitsch       PetscCall(MatMult(tao->jacobian_state_inv, lclP->GU, lclP->lamda)); } else {
2179566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(tao->jacobian_state_inv, lclP->GU, lclP->lamda));
218a7e14dcfSSatish Balay     }
219a7e14dcfSSatish Balay   } else {
2209566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(tao->ksp, tao->jacobian_state, tao->jacobian_state_pre));
221a7e14dcfSSatish Balay     if (symmetric) {
2229566063dSJacob Faibussowitsch       PetscCall(KSPSolve(tao->ksp, lclP->GU,  lclP->lamda));
223a7e14dcfSSatish Balay     } else {
2249566063dSJacob Faibussowitsch       PetscCall(KSPSolveTranspose(tao->ksp, lclP->GU,  lclP->lamda));
225a7e14dcfSSatish Balay     }
2269566063dSJacob Faibussowitsch     PetscCall(KSPGetIterationNumber(tao->ksp,&its));
227a7e14dcfSSatish Balay     tao->ksp_its+=its;
228ae93cb3cSJason Sarich     tao->ksp_tot_its+=its;
229a7e14dcfSSatish Balay   }
2309566063dSJacob Faibussowitsch   PetscCall(VecCopy(lclP->lamda,lclP->lamda0));
2319566063dSJacob Faibussowitsch   PetscCall(LCLComputeAugmentedLagrangianAndGradient(tao->linesearch,tao->solution,&lclP->aug,lclP->GAugL,tao));
232a7e14dcfSSatish Balay 
2339566063dSJacob Faibussowitsch   PetscCall(LCLScatter(lclP,lclP->GL,lclP->GL_U,lclP->GL_V));
2349566063dSJacob Faibussowitsch   PetscCall(LCLScatter(lclP,lclP->GAugL,lclP->GAugL_U,lclP->GAugL_V));
235a7e14dcfSSatish Balay 
236a7e14dcfSSatish Balay   /* Evaluate constraint norm */
2379566063dSJacob Faibussowitsch   PetscCall(VecNorm(tao->constraints, NORM_2, &cnorm));
2389566063dSJacob Faibussowitsch   PetscCall(VecNorm(lclP->GAugL, NORM_2, &mnorm));
239a7e14dcfSSatish Balay 
240a7e14dcfSSatish Balay   /* Monitor convergence */
241763847b4SAlp Dener   tao->reason = TAO_CONTINUE_ITERATING;
2429566063dSJacob Faibussowitsch   PetscCall(TaoLogConvergenceHistory(tao,f,mnorm,cnorm,tao->ksp_its));
2439566063dSJacob Faibussowitsch   PetscCall(TaoMonitor(tao,tao->niter,f,mnorm,cnorm,step));
2449566063dSJacob Faibussowitsch   PetscCall((*tao->ops->convergencetest)(tao,tao->cnvP));
245a7e14dcfSSatish Balay 
246763847b4SAlp Dener   while (tao->reason == TAO_CONTINUE_ITERATING) {
247e1e80dc8SAlp Dener     /* Call general purpose update function */
248e1e80dc8SAlp Dener     if (tao->ops->update) {
2499566063dSJacob Faibussowitsch       PetscCall((*tao->ops->update)(tao, tao->niter, tao->user_update));
250e1e80dc8SAlp Dener     }
251ae93cb3cSJason Sarich     tao->ksp_its=0;
252a7e14dcfSSatish Balay     /* Compute a descent direction for the linearly constrained subproblem
253a7e14dcfSSatish Balay        minimize f(u+du, v+dv)
254a7e14dcfSSatish Balay        s.t. A(u0,v0)du + B(u0,v0)dv = -g(u0,v0) */
255a7e14dcfSSatish Balay 
256a7e14dcfSSatish Balay     /* Store the points around the linearization */
2579566063dSJacob Faibussowitsch     PetscCall(VecCopy(lclP->U, lclP->U0));
2589566063dSJacob Faibussowitsch     PetscCall(VecCopy(lclP->V, lclP->V0));
2599566063dSJacob Faibussowitsch     PetscCall(VecCopy(lclP->GU,lclP->GU0));
2609566063dSJacob Faibussowitsch     PetscCall(VecCopy(lclP->GV,lclP->GV0));
2619566063dSJacob Faibussowitsch     PetscCall(VecCopy(lclP->GAugL_U,lclP->GAugL_U0));
2629566063dSJacob Faibussowitsch     PetscCall(VecCopy(lclP->GAugL_V,lclP->GAugL_V0));
2639566063dSJacob Faibussowitsch     PetscCall(VecCopy(lclP->GL_U,lclP->GL_U0));
2649566063dSJacob Faibussowitsch     PetscCall(VecCopy(lclP->GL_V,lclP->GL_V0));
265a7e14dcfSSatish Balay 
266a7e14dcfSSatish Balay     lclP->aug0 = lclP->aug;
267a7e14dcfSSatish Balay     lclP->lgn0 = lclP->lgn;
268a7e14dcfSSatish Balay 
269a7e14dcfSSatish Balay     /* Given the design variables, we need to project the current iterate
270a7e14dcfSSatish Balay        onto the linearized constraint.  We choose to fix the design variables
271a7e14dcfSSatish Balay        and solve the linear system for the state variables.  The resulting
272a7e14dcfSSatish Balay        point is the Newton direction */
273a7e14dcfSSatish Balay 
274a7e14dcfSSatish Balay     /* Solve r = A\con */
275a7e14dcfSSatish Balay     lclP->solve_type = LCL_FORWARD1;
2769566063dSJacob Faibussowitsch     PetscCall(VecSet(lclP->r,0.0)); /*  Initial guess in CG */
277a7e14dcfSSatish Balay 
278a7e14dcfSSatish Balay     if (tao->jacobian_state_inv) {
2799566063dSJacob Faibussowitsch       PetscCall(MatMult(tao->jacobian_state_inv, tao->constraints, lclP->r));
280a7e14dcfSSatish Balay     } else {
2819566063dSJacob Faibussowitsch       PetscCall(KSPSetOperators(tao->ksp, tao->jacobian_state, tao->jacobian_state_pre));
2829566063dSJacob Faibussowitsch       PetscCall(KSPSolve(tao->ksp, tao->constraints,  lclP->r));
2839566063dSJacob Faibussowitsch       PetscCall(KSPGetIterationNumber(tao->ksp,&its));
284a7e14dcfSSatish Balay       tao->ksp_its+=its;
285ae93cb3cSJason Sarich       tao->ksp_tot_its+=tao->ksp_its;
286a7e14dcfSSatish Balay     }
287a7e14dcfSSatish Balay 
288a7e14dcfSSatish Balay     /* Set design step direction dv to zero */
2899566063dSJacob Faibussowitsch     PetscCall(VecSet(lclP->s, 0.0));
290a7e14dcfSSatish Balay 
291a7e14dcfSSatish Balay     /*
292a7e14dcfSSatish Balay        Check sufficient descent for constraint merit function .5*||con||^2
293a7e14dcfSSatish Balay        con' Ak r >= eps1 ||r||^(2+eps2)
294a7e14dcfSSatish Balay     */
295a7e14dcfSSatish Balay 
296a7e14dcfSSatish Balay     /* Compute WU= Ak' * con */
297a7e14dcfSSatish Balay     if (symmetric)  {
2989566063dSJacob Faibussowitsch       PetscCall(MatMult(tao->jacobian_state,tao->constraints,lclP->WU));
299a7e14dcfSSatish Balay     } else {
3009566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(tao->jacobian_state,tao->constraints,lclP->WU));
301a7e14dcfSSatish Balay     }
302a7e14dcfSSatish Balay     /* Compute r * Ak' * con */
3039566063dSJacob Faibussowitsch     PetscCall(VecDot(lclP->r,lclP->WU,&rWU));
304a7e14dcfSSatish Balay 
305a7e14dcfSSatish Balay     /* compute ||r||^(2+eps2) */
3069566063dSJacob Faibussowitsch     PetscCall(VecNorm(lclP->r,NORM_2,&r2));
307a7e14dcfSSatish Balay     r2 = PetscPowScalar(r2,2.0+lclP->eps2);
308a7e14dcfSSatish Balay     adec = lclP->eps1 * r2;
309a7e14dcfSSatish Balay 
310a7e14dcfSSatish Balay     if (rWU < adec) {
3119566063dSJacob Faibussowitsch       PetscCall(PetscInfo(tao,"Newton direction not descent for constraint, feasibility phase required\n"));
312a7e14dcfSSatish Balay       if (lclP->verbose) {
3139566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Newton direction not descent for constraint: %g -- using steepest descent\n",(double)descent));
314a7e14dcfSSatish Balay       }
315a7e14dcfSSatish Balay 
3169566063dSJacob Faibussowitsch       PetscCall(PetscInfo(tao,"Using steepest descent direction instead.\n"));
3179566063dSJacob Faibussowitsch       PetscCall(VecSet(lclP->r,0.0));
3189566063dSJacob Faibussowitsch       PetscCall(VecAXPY(lclP->r,-1.0,lclP->WU));
3199566063dSJacob Faibussowitsch       PetscCall(VecDot(lclP->r,lclP->r,&rWU));
3209566063dSJacob Faibussowitsch       PetscCall(VecNorm(lclP->r,NORM_2,&r2));
321a7e14dcfSSatish Balay       r2 = PetscPowScalar(r2,2.0+lclP->eps2);
3229566063dSJacob Faibussowitsch       PetscCall(VecDot(lclP->r,lclP->GAugL_U,&descent));
323a7e14dcfSSatish Balay       adec = lclP->eps1 * r2;
324a7e14dcfSSatish Balay     }
325a7e14dcfSSatish Balay 
326a7e14dcfSSatish Balay     /*
327a7e14dcfSSatish Balay        Check descent for aug. lagrangian
328a7e14dcfSSatish Balay        r' (GUk - Ak'*yk - rho*Ak'*con) <= -eps1 ||r||^(2+eps2)
329a7e14dcfSSatish Balay           GL_U = GUk - Ak'*yk
330a7e14dcfSSatish Balay           WU   = Ak'*con
331a7e14dcfSSatish Balay                                          adec=eps1||r||^(2+eps2)
332a7e14dcfSSatish Balay 
333a7e14dcfSSatish Balay        ==>
334a7e14dcfSSatish Balay        Check r'GL_U - rho*r'WU <= adec
335a7e14dcfSSatish Balay     */
336a7e14dcfSSatish Balay 
3379566063dSJacob Faibussowitsch     PetscCall(VecDot(lclP->r,lclP->GL_U,&rGL_U));
338a7e14dcfSSatish Balay     aldescent =  rGL_U - lclP->rho*rWU;
339a7e14dcfSSatish Balay     if (aldescent > -adec) {
340a7e14dcfSSatish Balay       if (lclP->verbose) {
3419566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_WORLD," Newton direction not descent for augmented Lagrangian: %g",(double)aldescent));
342a7e14dcfSSatish Balay       }
3439566063dSJacob Faibussowitsch       PetscCall(PetscInfo(tao,"Newton direction not descent for augmented Lagrangian: %g\n",(double)aldescent));
344a7e14dcfSSatish Balay       lclP->rho =  (rGL_U - adec)/rWU;
345a7e14dcfSSatish Balay       if (lclP->rho > lclP->rhomax) {
346a7e14dcfSSatish Balay         lclP->rho = lclP->rhomax;
34798921bdaSJacob Faibussowitsch         SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"rho=%g > rhomax, case not implemented.  Increase rhomax (-tao_lcl_rhomax)",(double)lclP->rho);
348a7e14dcfSSatish Balay       }
349a7e14dcfSSatish Balay       if (lclP->verbose) {
3509566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_WORLD,"  Increasing penalty parameter to %g\n",(double)lclP->rho));
351a7e14dcfSSatish Balay       }
3529566063dSJacob Faibussowitsch       PetscCall(PetscInfo(tao,"  Increasing penalty parameter to %g\n",(double)lclP->rho));
353a7e14dcfSSatish Balay     }
354a7e14dcfSSatish Balay 
3559566063dSJacob Faibussowitsch     PetscCall(LCLComputeAugmentedLagrangianAndGradient(tao->linesearch,tao->solution,&lclP->aug,lclP->GAugL,tao));
3569566063dSJacob Faibussowitsch     PetscCall(LCLScatter(lclP,lclP->GL,lclP->GL_U,lclP->GL_V));
3579566063dSJacob Faibussowitsch     PetscCall(LCLScatter(lclP,lclP->GAugL,lclP->GAugL_U,lclP->GAugL_V));
358a7e14dcfSSatish Balay 
359a7e14dcfSSatish Balay     /* We now minimize the augmented Lagrangian along the Newton direction */
3609566063dSJacob Faibussowitsch     PetscCall(VecScale(lclP->r,-1.0));
3619566063dSJacob Faibussowitsch     PetscCall(LCLGather(lclP, lclP->r,lclP->s,tao->stepdirection));
3629566063dSJacob Faibussowitsch     PetscCall(VecScale(lclP->r,-1.0));
3639566063dSJacob Faibussowitsch     PetscCall(LCLGather(lclP, lclP->GAugL_U0, lclP->GAugL_V0, lclP->GAugL));
3649566063dSJacob Faibussowitsch     PetscCall(LCLGather(lclP, lclP->U0,lclP->V0,lclP->X0));
365a7e14dcfSSatish Balay 
366a7e14dcfSSatish Balay     lclP->recompute_jacobian_flag = PETSC_TRUE;
367a7e14dcfSSatish Balay 
3689566063dSJacob Faibussowitsch     PetscCall(TaoLineSearchSetInitialStepLength(tao->linesearch,1.0));
3699566063dSJacob Faibussowitsch     PetscCall(TaoLineSearchSetType(tao->linesearch, TAOLINESEARCHMT));
3709566063dSJacob Faibussowitsch     PetscCall(TaoLineSearchSetFromOptions(tao->linesearch));
3719566063dSJacob Faibussowitsch     PetscCall(TaoLineSearchApply(tao->linesearch, tao->solution, &lclP->aug, lclP->GAugL, tao->stepdirection, &step, &ls_reason));
372a7e14dcfSSatish Balay     if (lclP->verbose) {
3739566063dSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Steplength = %g\n",(double)step));
374a7e14dcfSSatish Balay     }
375a7e14dcfSSatish Balay 
3769566063dSJacob Faibussowitsch     PetscCall(LCLScatter(lclP,tao->solution,lclP->U,lclP->V));
3779566063dSJacob Faibussowitsch     PetscCall(TaoComputeObjectiveAndGradient(tao,tao->solution,&f,tao->gradient));
3789566063dSJacob Faibussowitsch     PetscCall(LCLScatter(lclP,tao->gradient,lclP->GU,lclP->GV));
379a7e14dcfSSatish Balay 
3809566063dSJacob Faibussowitsch     PetscCall(LCLScatter(lclP,lclP->GAugL,lclP->GAugL_U,lclP->GAugL_V));
381a7e14dcfSSatish Balay 
382a7e14dcfSSatish Balay     /* Check convergence */
3839566063dSJacob Faibussowitsch     PetscCall(VecNorm(lclP->GAugL, NORM_2, &mnorm));
3849566063dSJacob Faibussowitsch     PetscCall(VecNorm(tao->constraints, NORM_2, &cnorm));
3859566063dSJacob Faibussowitsch     PetscCall(TaoLogConvergenceHistory(tao,f,mnorm,cnorm,tao->ksp_its));
3869566063dSJacob Faibussowitsch     PetscCall(TaoMonitor(tao,tao->niter,f,mnorm,cnorm,step));
3879566063dSJacob Faibussowitsch     PetscCall((*tao->ops->convergencetest)(tao,tao->cnvP));
388763847b4SAlp Dener     if (tao->reason != TAO_CONTINUE_ITERATING) {
389a7e14dcfSSatish Balay       break;
390a7e14dcfSSatish Balay     }
391a7e14dcfSSatish Balay 
392a7e14dcfSSatish Balay     /* TODO: use a heuristic to choose how many iterations should be performed within phase 2 */
393a7e14dcfSSatish Balay     for (phase2_iter=0; phase2_iter<lclP->phase2_niter; phase2_iter++) {
394a7e14dcfSSatish Balay       /* We now minimize the objective function starting from the fraction of
395a7e14dcfSSatish Balay          the Newton point accepted by applying one step of a reduced-space
396a7e14dcfSSatish Balay          method.  The optimization problem is:
397a7e14dcfSSatish Balay 
398a7e14dcfSSatish Balay          minimize f(u+du, v+dv)
399a7e14dcfSSatish Balay          s. t.    A(u0,v0)du + B(u0,v0)du = -alpha g(u0,v0)
400a7e14dcfSSatish Balay 
401a7e14dcfSSatish Balay          In particular, we have that
402a7e14dcfSSatish Balay          du = -inv(A)*(Bdv + alpha g) */
403a7e14dcfSSatish Balay 
4049566063dSJacob Faibussowitsch       PetscCall(TaoComputeJacobianState(tao,lclP->X0,tao->jacobian_state,tao->jacobian_state_pre,tao->jacobian_state_inv));
4059566063dSJacob Faibussowitsch       PetscCall(TaoComputeJacobianDesign(tao,lclP->X0,tao->jacobian_design));
406a7e14dcfSSatish Balay 
407a7e14dcfSSatish Balay       /* Store V and constraints */
4089566063dSJacob Faibussowitsch       PetscCall(VecCopy(lclP->V, lclP->V1));
4099566063dSJacob Faibussowitsch       PetscCall(VecCopy(tao->constraints,lclP->con1));
410a7e14dcfSSatish Balay 
411a7e14dcfSSatish Balay       /* Compute multipliers */
412a7e14dcfSSatish Balay       /* p1 */
4139566063dSJacob Faibussowitsch       PetscCall(VecSet(lclP->lamda,0.0)); /*  Initial guess in CG */
414a7e14dcfSSatish Balay       lclP->solve_type = LCL_ADJOINT1;
4159566063dSJacob Faibussowitsch       PetscCall(MatIsSymmetricKnown(tao->jacobian_state,&set,&flag));
416a7e14dcfSSatish Balay       if (tao->jacobian_state_pre) {
4179566063dSJacob Faibussowitsch         PetscCall(MatIsSymmetricKnown(tao->jacobian_state_pre,&pset,&pflag));
418a7e14dcfSSatish Balay       } else {
419a7e14dcfSSatish Balay         pset = pflag = PETSC_TRUE;
420a7e14dcfSSatish Balay       }
421f06e3bfaSBarry Smith       if (set && pset && flag && pflag) symmetric = PETSC_TRUE;
422f06e3bfaSBarry Smith       else symmetric = PETSC_FALSE;
423a7e14dcfSSatish Balay 
424a7e14dcfSSatish Balay       if (tao->jacobian_state_inv) {
425a7e14dcfSSatish Balay         if (symmetric) {
4269566063dSJacob Faibussowitsch           PetscCall(MatMult(tao->jacobian_state_inv, lclP->GAugL_U, lclP->lamda));
427a7e14dcfSSatish Balay         } else {
4289566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(tao->jacobian_state_inv, lclP->GAugL_U, lclP->lamda));
429a7e14dcfSSatish Balay         }
430a7e14dcfSSatish Balay       } else {
431a7e14dcfSSatish Balay         if (symmetric) {
4329566063dSJacob Faibussowitsch           PetscCall(KSPSolve(tao->ksp, lclP->GAugL_U,  lclP->lamda));
433a7e14dcfSSatish Balay         } else {
4349566063dSJacob Faibussowitsch           PetscCall(KSPSolveTranspose(tao->ksp, lclP->GAugL_U,  lclP->lamda));
435a7e14dcfSSatish Balay         }
4369566063dSJacob Faibussowitsch         PetscCall(KSPGetIterationNumber(tao->ksp,&its));
437a7e14dcfSSatish Balay         tao->ksp_its+=its;
438ae93cb3cSJason Sarich         tao->ksp_tot_its+=its;
439a7e14dcfSSatish Balay       }
4409566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(tao->jacobian_design,lclP->lamda,lclP->g1));
4419566063dSJacob Faibussowitsch       PetscCall(VecAXPY(lclP->g1,-1.0,lclP->GAugL_V));
442a7e14dcfSSatish Balay 
443a7e14dcfSSatish Balay       /* Compute the limited-memory quasi-newton direction */
4448931d482SJason Sarich       if (tao->niter > 0) {
4459566063dSJacob Faibussowitsch         PetscCall(MatSolve(lclP->R,lclP->g1,lclP->s));
4469566063dSJacob Faibussowitsch         PetscCall(VecDot(lclP->s,lclP->g1,&descent));
4470583ad50SJason Sarich         if (descent <= 0) {
448a7e14dcfSSatish Balay           if (lclP->verbose) {
4499566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Reduced-space direction not descent: %g\n",(double)descent));
450a7e14dcfSSatish Balay           }
4519566063dSJacob Faibussowitsch           PetscCall(VecCopy(lclP->g1,lclP->s));
452a7e14dcfSSatish Balay         }
453a7e14dcfSSatish Balay       } else {
4549566063dSJacob Faibussowitsch         PetscCall(VecCopy(lclP->g1,lclP->s));
455a7e14dcfSSatish Balay       }
4569566063dSJacob Faibussowitsch       PetscCall(VecScale(lclP->g1,-1.0));
457a7e14dcfSSatish Balay 
458a7e14dcfSSatish Balay       /* Recover the full space direction */
4599566063dSJacob Faibussowitsch       PetscCall(MatMult(tao->jacobian_design,lclP->s,lclP->WU));
4609566063dSJacob Faibussowitsch       /* PetscCall(VecSet(lclP->r,0.0)); */ /*  Initial guess in CG */
461a7e14dcfSSatish Balay       lclP->solve_type = LCL_FORWARD2;
462a7e14dcfSSatish Balay       if (tao->jacobian_state_inv) {
4639566063dSJacob Faibussowitsch         PetscCall(MatMult(tao->jacobian_state_inv,lclP->WU,lclP->r));
464a7e14dcfSSatish Balay       } else {
4659566063dSJacob Faibussowitsch         PetscCall(KSPSolve(tao->ksp, lclP->WU, lclP->r));
4669566063dSJacob Faibussowitsch         PetscCall(KSPGetIterationNumber(tao->ksp,&its));
467a7e14dcfSSatish Balay         tao->ksp_its += its;
468ae93cb3cSJason Sarich         tao->ksp_tot_its+=its;
469a7e14dcfSSatish Balay       }
470a7e14dcfSSatish Balay 
471a7e14dcfSSatish Balay       /* We now minimize the augmented Lagrangian along the direction -r,s */
4729566063dSJacob Faibussowitsch       PetscCall(VecScale(lclP->r, -1.0));
4739566063dSJacob Faibussowitsch       PetscCall(LCLGather(lclP,lclP->r,lclP->s,tao->stepdirection));
4749566063dSJacob Faibussowitsch       PetscCall(VecScale(lclP->r, -1.0));
475a7e14dcfSSatish Balay       lclP->recompute_jacobian_flag = PETSC_TRUE;
476a7e14dcfSSatish Balay 
4779566063dSJacob Faibussowitsch       PetscCall(TaoLineSearchSetInitialStepLength(tao->linesearch,1.0));
4789566063dSJacob Faibussowitsch       PetscCall(TaoLineSearchSetType(tao->linesearch,TAOLINESEARCHMT));
4799566063dSJacob Faibussowitsch       PetscCall(TaoLineSearchSetFromOptions(tao->linesearch));
4809566063dSJacob Faibussowitsch       PetscCall(TaoLineSearchApply(tao->linesearch, tao->solution, &lclP->aug, lclP->GAugL, tao->stepdirection,&step,&ls_reason));
481a7e14dcfSSatish Balay       if (lclP->verbose) {
4829566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Reduced-space steplength =  %g\n",(double)step));
483a7e14dcfSSatish Balay       }
484a7e14dcfSSatish Balay 
4859566063dSJacob Faibussowitsch       PetscCall(LCLScatter(lclP,tao->solution,lclP->U,lclP->V));
4869566063dSJacob Faibussowitsch       PetscCall(LCLScatter(lclP,lclP->GL,lclP->GL_U,lclP->GL_V));
4879566063dSJacob Faibussowitsch       PetscCall(LCLScatter(lclP,lclP->GAugL,lclP->GAugL_U,lclP->GAugL_V));
4889566063dSJacob Faibussowitsch       PetscCall(TaoComputeObjectiveAndGradient(tao,tao->solution,&f,tao->gradient));
4899566063dSJacob Faibussowitsch       PetscCall(LCLScatter(lclP,tao->gradient,lclP->GU,lclP->GV));
490a7e14dcfSSatish Balay 
491a7e14dcfSSatish Balay       /* Compute the reduced gradient at the new point */
492a7e14dcfSSatish Balay 
4939566063dSJacob Faibussowitsch       PetscCall(TaoComputeJacobianState(tao,lclP->X0,tao->jacobian_state,tao->jacobian_state_pre,tao->jacobian_state_inv));
4949566063dSJacob Faibussowitsch       PetscCall(TaoComputeJacobianDesign(tao,lclP->X0,tao->jacobian_design));
495a7e14dcfSSatish Balay 
496a7e14dcfSSatish Balay       /* p2 */
497a7e14dcfSSatish Balay       /* Compute multipliers, using lamda-rho*con as an initial guess in PCG */
498a7e14dcfSSatish Balay       if (phase2_iter==0) {
4999566063dSJacob Faibussowitsch         PetscCall(VecWAXPY(lclP->lamda,-lclP->rho,lclP->con1,lclP->lamda0));
500f06e3bfaSBarry Smith       } else {
5019566063dSJacob Faibussowitsch         PetscCall(VecAXPY(lclP->lamda,-lclP->rho,tao->constraints));
502a7e14dcfSSatish Balay       }
503a7e14dcfSSatish Balay 
5049566063dSJacob Faibussowitsch       PetscCall(MatIsSymmetricKnown(tao->jacobian_state,&set,&flag));
505a7e14dcfSSatish Balay       if (tao->jacobian_state_pre) {
5069566063dSJacob Faibussowitsch         PetscCall(MatIsSymmetricKnown(tao->jacobian_state_pre,&pset,&pflag));
507a7e14dcfSSatish Balay       } else {
508a7e14dcfSSatish Balay         pset = pflag = PETSC_TRUE;
509a7e14dcfSSatish Balay       }
510f06e3bfaSBarry Smith       if (set && pset && flag && pflag) symmetric = PETSC_TRUE;
511f06e3bfaSBarry Smith       else symmetric = PETSC_FALSE;
512a7e14dcfSSatish Balay 
513a7e14dcfSSatish Balay       lclP->solve_type = LCL_ADJOINT2;
514a7e14dcfSSatish Balay       if (tao->jacobian_state_inv) {
515a7e14dcfSSatish Balay         if (symmetric) {
5169566063dSJacob Faibussowitsch           PetscCall(MatMult(tao->jacobian_state_inv, lclP->GU, lclP->lamda));
517a7e14dcfSSatish Balay         } else {
5189566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(tao->jacobian_state_inv, lclP->GU, lclP->lamda));
519a7e14dcfSSatish Balay         }
520a7e14dcfSSatish Balay       } else {
521a7e14dcfSSatish Balay         if (symmetric) {
5229566063dSJacob Faibussowitsch           PetscCall(KSPSolve(tao->ksp, lclP->GU,  lclP->lamda));
523a7e14dcfSSatish Balay         } else {
5249566063dSJacob Faibussowitsch           PetscCall(KSPSolveTranspose(tao->ksp, lclP->GU,  lclP->lamda));
525a7e14dcfSSatish Balay         }
5269566063dSJacob Faibussowitsch         PetscCall(KSPGetIterationNumber(tao->ksp,&its));
527a7e14dcfSSatish Balay         tao->ksp_its += its;
5282d9aa51bSJason Sarich         tao->ksp_tot_its += its;
529a7e14dcfSSatish Balay       }
530a7e14dcfSSatish Balay 
5319566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(tao->jacobian_design,lclP->lamda,lclP->g2));
5329566063dSJacob Faibussowitsch       PetscCall(VecAXPY(lclP->g2,-1.0,lclP->GV));
533a7e14dcfSSatish Balay 
5349566063dSJacob Faibussowitsch       PetscCall(VecScale(lclP->g2,-1.0));
535a7e14dcfSSatish Balay 
536a7e14dcfSSatish Balay       /* Update the quasi-newton approximation */
5379566063dSJacob Faibussowitsch       PetscCall(MatLMVMUpdate(lclP->R,lclP->V,lclP->g2));
538a7e14dcfSSatish 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 */
539a7e14dcfSSatish Balay 
540a7e14dcfSSatish Balay     }
541a7e14dcfSSatish Balay 
5429566063dSJacob Faibussowitsch     PetscCall(VecCopy(lclP->lamda,lclP->lamda0));
543a7e14dcfSSatish Balay 
544a7e14dcfSSatish Balay     /* Evaluate Function, Gradient, Constraints, and Jacobian */
5459566063dSJacob Faibussowitsch     PetscCall(TaoComputeObjectiveAndGradient(tao,tao->solution,&f,tao->gradient));
5469566063dSJacob Faibussowitsch     PetscCall(LCLScatter(lclP,tao->solution,lclP->U,lclP->V));
5479566063dSJacob Faibussowitsch     PetscCall(LCLScatter(lclP,tao->gradient,lclP->GU,lclP->GV));
548a7e14dcfSSatish Balay 
5499566063dSJacob Faibussowitsch     PetscCall(TaoComputeJacobianState(tao,tao->solution,tao->jacobian_state,tao->jacobian_state_pre,tao->jacobian_state_inv));
5509566063dSJacob Faibussowitsch     PetscCall(TaoComputeJacobianDesign(tao,tao->solution,tao->jacobian_design));
5519566063dSJacob Faibussowitsch     PetscCall(TaoComputeConstraints(tao,tao->solution, tao->constraints));
552a7e14dcfSSatish Balay 
5539566063dSJacob Faibussowitsch     PetscCall(LCLComputeAugmentedLagrangianAndGradient(tao->linesearch,tao->solution,&lclP->aug,lclP->GAugL,tao));
554a7e14dcfSSatish Balay 
5559566063dSJacob Faibussowitsch     PetscCall(VecNorm(lclP->GAugL, NORM_2, &mnorm));
556a7e14dcfSSatish Balay 
557a7e14dcfSSatish Balay     /* Evaluate constraint norm */
5589566063dSJacob Faibussowitsch     PetscCall(VecNorm(tao->constraints, NORM_2, &cnorm));
559a7e14dcfSSatish Balay 
560a7e14dcfSSatish Balay     /* Monitor convergence */
5618931d482SJason Sarich     tao->niter++;
5629566063dSJacob Faibussowitsch     PetscCall(TaoLogConvergenceHistory(tao,f,mnorm,cnorm,tao->ksp_its));
5639566063dSJacob Faibussowitsch     PetscCall(TaoMonitor(tao,tao->niter,f,mnorm,cnorm,step));
5649566063dSJacob Faibussowitsch     PetscCall((*tao->ops->convergencetest)(tao,tao->cnvP));
565a7e14dcfSSatish Balay   }
566a7e14dcfSSatish Balay   PetscFunctionReturn(0);
567a7e14dcfSSatish Balay }
568a7e14dcfSSatish Balay 
5691522df2eSJason Sarich /*MC
5701522df2eSJason Sarich  TAOLCL - linearly constrained lagrangian method for pde-constrained optimization
5711522df2eSJason Sarich 
5721522df2eSJason Sarich + -tao_lcl_eps1 - epsilon 1 tolerance
573d0609cedSBarry Smith . -tao_lcl_eps2","epsilon 2 tolerance","",lclP->eps2,&lclP->eps2,NULL);
574d0609cedSBarry Smith . -tao_lcl_rho0","init value for rho","",lclP->rho0,&lclP->rho0,NULL);
575d0609cedSBarry Smith . -tao_lcl_rhomax","max value for rho","",lclP->rhomax,&lclP->rhomax,NULL);
5761522df2eSJason Sarich . -tao_lcl_phase2_niter - Number of phase 2 iterations in LCL algorithm
5771522df2eSJason Sarich . -tao_lcl_verbose - Print verbose output if True
5781522df2eSJason Sarich . -tao_lcl_tola - Tolerance for first forward solve
5791522df2eSJason Sarich . -tao_lcl_tolb - Tolerance for first adjoint solve
5801522df2eSJason Sarich . -tao_lcl_tolc - Tolerance for second forward solve
5811522df2eSJason Sarich - -tao_lcl_told - Tolerance for second adjoint solve
5821522df2eSJason Sarich 
5831eb8069cSJason Sarich   Level: beginner
5841522df2eSJason Sarich M*/
585728e0ed0SBarry Smith PETSC_EXTERN PetscErrorCode TaoCreate_LCL(Tao tao)
586a7e14dcfSSatish Balay {
587a7e14dcfSSatish Balay   TAO_LCL        *lclP;
5888caf6e8cSBarry Smith   const char     *morethuente_type = TAOLINESEARCHMT;
589a7e14dcfSSatish Balay 
590f06e3bfaSBarry Smith   PetscFunctionBegin;
591a7e14dcfSSatish Balay   tao->ops->setup = TaoSetup_LCL;
592a7e14dcfSSatish Balay   tao->ops->solve = TaoSolve_LCL;
593a7e14dcfSSatish Balay   tao->ops->view = TaoView_LCL;
594a7e14dcfSSatish Balay   tao->ops->setfromoptions = TaoSetFromOptions_LCL;
595a7e14dcfSSatish Balay   tao->ops->destroy = TaoDestroy_LCL;
5969566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(tao,&lclP));
597a7e14dcfSSatish Balay   tao->data = (void*)lclP;
598a7e14dcfSSatish Balay 
5996552cf8aSJason Sarich   /* Override default settings (unless already changed) */
6006552cf8aSJason Sarich   if (!tao->max_it_changed) tao->max_it = 200;
6016552cf8aSJason Sarich   if (!tao->catol_changed) tao->catol = 1.0e-4;
6026552cf8aSJason Sarich   if (!tao->gatol_changed) tao->gttol = 1.0e-4;
6036552cf8aSJason Sarich   if (!tao->grtol_changed) tao->gttol = 1.0e-4;
6046552cf8aSJason Sarich   if (!tao->gttol_changed) tao->gttol = 1.0e-4;
605a7e14dcfSSatish Balay   lclP->rho0 = 1.0e-4;
606a7e14dcfSSatish Balay   lclP->rhomax=1e5;
607a7e14dcfSSatish Balay   lclP->eps1 = 1.0e-8;
608a7e14dcfSSatish Balay   lclP->eps2 = 0.0;
609a7e14dcfSSatish Balay   lclP->solve_type=2;
610a7e14dcfSSatish Balay   lclP->tau[0] = lclP->tau[1] = lclP->tau[2] = lclP->tau[3] = 1.0e-4;
6119566063dSJacob Faibussowitsch   PetscCall(TaoLineSearchCreate(((PetscObject)tao)->comm, &tao->linesearch));
6129566063dSJacob Faibussowitsch   PetscCall(PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1));
6139566063dSJacob Faibussowitsch   PetscCall(TaoLineSearchSetType(tao->linesearch, morethuente_type));
6149566063dSJacob Faibussowitsch   PetscCall(TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix));
615a7e14dcfSSatish Balay 
6169566063dSJacob Faibussowitsch   PetscCall(TaoLineSearchSetObjectiveAndGradientRoutine(tao->linesearch,LCLComputeAugmentedLagrangianAndGradient, tao));
6179566063dSJacob Faibussowitsch   PetscCall(KSPCreate(((PetscObject)tao)->comm,&tao->ksp));
6189566063dSJacob Faibussowitsch   PetscCall(PetscObjectIncrementTabLevel((PetscObject)tao->ksp, (PetscObject)tao, 1));
6199566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(tao->ksp, tao->hdr.prefix));
6209566063dSJacob Faibussowitsch   PetscCall(KSPSetFromOptions(tao->ksp));
6210c51296cSAlp Dener 
6229566063dSJacob Faibussowitsch   PetscCall(MatCreate(((PetscObject)tao)->comm, &lclP->R));
6239566063dSJacob Faibussowitsch   PetscCall(MatSetType(lclP->R, MATLMVMBFGS));
624a7e14dcfSSatish Balay   PetscFunctionReturn(0);
625a7e14dcfSSatish Balay }
626a7e14dcfSSatish Balay 
627a7e14dcfSSatish Balay static PetscErrorCode LCLComputeLagrangianAndGradient(TaoLineSearch ls, Vec X, PetscReal *f, Vec G, void *ptr)
628a7e14dcfSSatish Balay {
629441846f8SBarry Smith   Tao            tao = (Tao)ptr;
630a7e14dcfSSatish Balay   TAO_LCL        *lclP = (TAO_LCL*)tao->data;
631a7e14dcfSSatish Balay   PetscBool      set,pset,flag,pflag,symmetric;
632a7e14dcfSSatish Balay   PetscReal      cdotl;
633a7e14dcfSSatish Balay 
634a7e14dcfSSatish Balay   PetscFunctionBegin;
6359566063dSJacob Faibussowitsch   PetscCall(TaoComputeObjectiveAndGradient(tao,X,f,G));
6369566063dSJacob Faibussowitsch   PetscCall(LCLScatter(lclP,G,lclP->GU,lclP->GV));
637a7e14dcfSSatish Balay   if (lclP->recompute_jacobian_flag) {
6389566063dSJacob Faibussowitsch     PetscCall(TaoComputeJacobianState(tao,X,tao->jacobian_state,tao->jacobian_state_pre,tao->jacobian_state_inv));
6399566063dSJacob Faibussowitsch     PetscCall(TaoComputeJacobianDesign(tao,X,tao->jacobian_design));
640a7e14dcfSSatish Balay   }
6419566063dSJacob Faibussowitsch   PetscCall(TaoComputeConstraints(tao,X, tao->constraints));
6429566063dSJacob Faibussowitsch   PetscCall(MatIsSymmetricKnown(tao->jacobian_state,&set,&flag));
643a7e14dcfSSatish Balay   if (tao->jacobian_state_pre) {
6449566063dSJacob Faibussowitsch     PetscCall(MatIsSymmetricKnown(tao->jacobian_state_pre,&pset,&pflag));
645a7e14dcfSSatish Balay   } else {
646a7e14dcfSSatish Balay     pset = pflag = PETSC_TRUE;
647a7e14dcfSSatish Balay   }
648f06e3bfaSBarry Smith   if (set && pset && flag && pflag) symmetric = PETSC_TRUE;
649f06e3bfaSBarry Smith   else symmetric = PETSC_FALSE;
650a7e14dcfSSatish Balay 
6519566063dSJacob Faibussowitsch   PetscCall(VecDot(lclP->lamda0, tao->constraints, &cdotl));
652a7e14dcfSSatish Balay   lclP->lgn = *f - cdotl;
653a7e14dcfSSatish Balay 
654a7e14dcfSSatish Balay   /* Gradient of Lagrangian GL = G - J' * lamda */
655a7e14dcfSSatish Balay   /*      WU = A' * WL
656a7e14dcfSSatish Balay           WV = B' * WL */
657a7e14dcfSSatish Balay   if (symmetric) {
6589566063dSJacob Faibussowitsch     PetscCall(MatMult(tao->jacobian_state,lclP->lamda0,lclP->GL_U));
659a7e14dcfSSatish Balay   } else {
6609566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(tao->jacobian_state,lclP->lamda0,lclP->GL_U));
661a7e14dcfSSatish Balay   }
6629566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(tao->jacobian_design,lclP->lamda0,lclP->GL_V));
6639566063dSJacob Faibussowitsch   PetscCall(VecScale(lclP->GL_U,-1.0));
6649566063dSJacob Faibussowitsch   PetscCall(VecScale(lclP->GL_V,-1.0));
6659566063dSJacob Faibussowitsch   PetscCall(VecAXPY(lclP->GL_U,1.0,lclP->GU));
6669566063dSJacob Faibussowitsch   PetscCall(VecAXPY(lclP->GL_V,1.0,lclP->GV));
6679566063dSJacob Faibussowitsch   PetscCall(LCLGather(lclP,lclP->GL_U,lclP->GL_V,lclP->GL));
668a7e14dcfSSatish Balay 
669a7e14dcfSSatish Balay   f[0] = lclP->lgn;
6709566063dSJacob Faibussowitsch   PetscCall(VecCopy(lclP->GL,G));
671a7e14dcfSSatish Balay   PetscFunctionReturn(0);
672a7e14dcfSSatish Balay }
673a7e14dcfSSatish Balay 
674a7e14dcfSSatish Balay static PetscErrorCode LCLComputeAugmentedLagrangianAndGradient(TaoLineSearch ls, Vec X, PetscReal *f, Vec G, void *ptr)
675a7e14dcfSSatish Balay {
676441846f8SBarry Smith   Tao            tao = (Tao)ptr;
677a7e14dcfSSatish Balay   TAO_LCL        *lclP = (TAO_LCL*)tao->data;
678a7e14dcfSSatish Balay   PetscReal      con2;
679a7e14dcfSSatish Balay   PetscBool      flag,pflag,set,pset,symmetric;
680a7e14dcfSSatish Balay 
681a7e14dcfSSatish Balay   PetscFunctionBegin;
6829566063dSJacob Faibussowitsch   PetscCall(LCLComputeLagrangianAndGradient(tao->linesearch,X,f,G,tao));
6839566063dSJacob Faibussowitsch   PetscCall(LCLScatter(lclP,G,lclP->GL_U,lclP->GL_V));
6849566063dSJacob Faibussowitsch   PetscCall(VecDot(tao->constraints,tao->constraints,&con2));
685a7e14dcfSSatish Balay   lclP->aug = lclP->lgn + 0.5*lclP->rho*con2;
686a7e14dcfSSatish Balay 
687a7e14dcfSSatish Balay   /* Gradient of Aug. Lagrangian GAugL = GL + rho * J' c */
688a7e14dcfSSatish Balay   /*      WU = A' * c
689a7e14dcfSSatish Balay           WV = B' * c */
6909566063dSJacob Faibussowitsch   PetscCall(MatIsSymmetricKnown(tao->jacobian_state,&set,&flag));
691a7e14dcfSSatish Balay   if (tao->jacobian_state_pre) {
6929566063dSJacob Faibussowitsch     PetscCall(MatIsSymmetricKnown(tao->jacobian_state_pre,&pset,&pflag));
693a7e14dcfSSatish Balay   } else {
694a7e14dcfSSatish Balay     pset = pflag = PETSC_TRUE;
695a7e14dcfSSatish Balay   }
696f06e3bfaSBarry Smith   if (set && pset && flag && pflag) symmetric = PETSC_TRUE;
697f06e3bfaSBarry Smith   else symmetric = PETSC_FALSE;
698a7e14dcfSSatish Balay 
699a7e14dcfSSatish Balay   if (symmetric) {
7009566063dSJacob Faibussowitsch     PetscCall(MatMult(tao->jacobian_state,tao->constraints,lclP->GAugL_U));
701a7e14dcfSSatish Balay   } else {
7029566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(tao->jacobian_state,tao->constraints,lclP->GAugL_U));
703a7e14dcfSSatish Balay   }
704a7e14dcfSSatish Balay 
7059566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(tao->jacobian_design,tao->constraints,lclP->GAugL_V));
7069566063dSJacob Faibussowitsch   PetscCall(VecAYPX(lclP->GAugL_U,lclP->rho,lclP->GL_U));
7079566063dSJacob Faibussowitsch   PetscCall(VecAYPX(lclP->GAugL_V,lclP->rho,lclP->GL_V));
7089566063dSJacob Faibussowitsch   PetscCall(LCLGather(lclP,lclP->GAugL_U,lclP->GAugL_V,lclP->GAugL));
709a7e14dcfSSatish Balay 
710a7e14dcfSSatish Balay   f[0] = lclP->aug;
7119566063dSJacob Faibussowitsch   PetscCall(VecCopy(lclP->GAugL,G));
712a7e14dcfSSatish Balay   PetscFunctionReturn(0);
713a7e14dcfSSatish Balay }
714a7e14dcfSSatish Balay 
715a7e14dcfSSatish Balay PetscErrorCode LCLGather(TAO_LCL *lclP, Vec u, Vec v, Vec x)
716a7e14dcfSSatish Balay {
717a7e14dcfSSatish Balay   PetscFunctionBegin;
7189566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(lclP->state_scatter, u, x, INSERT_VALUES, SCATTER_REVERSE));
7199566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(lclP->state_scatter, u, x, INSERT_VALUES, SCATTER_REVERSE));
7209566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(lclP->design_scatter, v, x, INSERT_VALUES, SCATTER_REVERSE));
7219566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(lclP->design_scatter, v, x, INSERT_VALUES, SCATTER_REVERSE));
722a7e14dcfSSatish Balay   PetscFunctionReturn(0);
723a7e14dcfSSatish Balay 
724a7e14dcfSSatish Balay }
725a7e14dcfSSatish Balay PetscErrorCode LCLScatter(TAO_LCL *lclP, Vec x, Vec u, Vec v)
726a7e14dcfSSatish Balay {
727a7e14dcfSSatish Balay   PetscFunctionBegin;
7289566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(lclP->state_scatter, x, u, INSERT_VALUES, SCATTER_FORWARD));
7299566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(lclP->state_scatter, x, u, INSERT_VALUES, SCATTER_FORWARD));
7309566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(lclP->design_scatter, x, v, INSERT_VALUES, SCATTER_FORWARD));
7319566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(lclP->design_scatter, x, v, INSERT_VALUES, SCATTER_FORWARD));
732a7e14dcfSSatish Balay   PetscFunctionReturn(0);
733a7e14dcfSSatish Balay 
734a7e14dcfSSatish Balay }
735