xref: /petsc/src/tao/pde_constrained/impls/lcl/lcl.c (revision a958fbfc1c07da5d8abfa22584ccb9c44e85e9ad)
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));
58*a958fbfcSStefano Zampini   PetscCall(KSPDestroy(&tao->ksp));
599566063dSJacob Faibussowitsch   PetscCall(PetscFree(tao->data));
60a7e14dcfSSatish Balay   PetscFunctionReturn(0);
61a7e14dcfSSatish Balay }
62a7e14dcfSSatish Balay 
634416b707SBarry Smith static PetscErrorCode TaoSetFromOptions_LCL(PetscOptionItems *PetscOptionsObject,Tao tao)
64a7e14dcfSSatish Balay {
65a7e14dcfSSatish Balay   TAO_LCL        *lclP = (TAO_LCL*)tao->data;
66a7e14dcfSSatish Balay 
67a7e14dcfSSatish Balay   PetscFunctionBegin;
68d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject,"Linearly-Constrained Augmented Lagrangian Method for PDE-constrained optimization");
699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_lcl_eps1","epsilon 1 tolerance","",lclP->eps1,&lclP->eps1,NULL));
709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_lcl_eps2","epsilon 2 tolerance","",lclP->eps2,&lclP->eps2,NULL));
719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_lcl_rho0","init value for rho","",lclP->rho0,&lclP->rho0,NULL));
729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_lcl_rhomax","max value for rho","",lclP->rhomax,&lclP->rhomax,NULL));
73a7e14dcfSSatish Balay   lclP->phase2_niter = 1;
749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-tao_lcl_phase2_niter","Number of phase 2 iterations in LCL algorithm","",lclP->phase2_niter,&lclP->phase2_niter,NULL));
75a7e14dcfSSatish Balay   lclP->verbose = PETSC_FALSE;
769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-tao_lcl_verbose","Print verbose output","",lclP->verbose,&lclP->verbose,NULL));
77a7e14dcfSSatish Balay   lclP->tau[0] = lclP->tau[1] = lclP->tau[2] = lclP->tau[3] = 1.0e-4;
789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_lcl_tola","Tolerance for first forward solve","",lclP->tau[0],&lclP->tau[0],NULL));
799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_lcl_tolb","Tolerance for first adjoint solve","",lclP->tau[1],&lclP->tau[1],NULL));
809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_lcl_tolc","Tolerance for second forward solve","",lclP->tau[2],&lclP->tau[2],NULL));
819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_lcl_told","Tolerance for second adjoint solve","",lclP->tau[3],&lclP->tau[3],NULL));
82d0609cedSBarry Smith   PetscOptionsHeadEnd();
839566063dSJacob Faibussowitsch   PetscCall(TaoLineSearchSetFromOptions(tao->linesearch));
849566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(lclP->R));
85a7e14dcfSSatish Balay   PetscFunctionReturn(0);
86a7e14dcfSSatish Balay }
87a7e14dcfSSatish Balay 
88441846f8SBarry Smith static PetscErrorCode TaoView_LCL(Tao tao, PetscViewer viewer)
89a7e14dcfSSatish Balay {
90a7e14dcfSSatish Balay   return 0;
91a7e14dcfSSatish Balay }
92a7e14dcfSSatish Balay 
93441846f8SBarry Smith static PetscErrorCode TaoSetup_LCL(Tao tao)
94a7e14dcfSSatish Balay {
95a7e14dcfSSatish Balay   TAO_LCL        *lclP = (TAO_LCL*)tao->data;
96a7e14dcfSSatish Balay   PetscInt       lo, hi, nlocalstate, nlocaldesign;
97a7e14dcfSSatish Balay   IS             is_state, is_design;
98f06e3bfaSBarry Smith 
99a7e14dcfSSatish Balay   PetscFunctionBegin;
1003c859ba3SBarry Smith   PetscCheck(tao->state_is,PetscObjectComm((PetscObject)tao),PETSC_ERR_ARG_WRONGSTATE,"LCL Solver requires an initial state index set -- use TaoSetStateIS()");
1019566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->solution, &tao->gradient));
1029566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->solution, &tao->stepdirection));
1039566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->solution, &lclP->W));
1049566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->solution, &lclP->X0));
1059566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->solution, &lclP->G0));
1069566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->solution, &lclP->GL));
1079566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->solution, &lclP->GAugL));
108a7e14dcfSSatish Balay 
1099566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->constraints, &lclP->lamda));
1109566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->constraints, &lclP->WL));
1119566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->constraints, &lclP->lamda0));
1129566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->constraints, &lclP->con1));
113a7e14dcfSSatish Balay 
1149566063dSJacob Faibussowitsch   PetscCall(VecSet(lclP->lamda,0.0));
115a7e14dcfSSatish Balay 
1169566063dSJacob Faibussowitsch   PetscCall(VecGetSize(tao->solution, &lclP->n));
1179566063dSJacob Faibussowitsch   PetscCall(VecGetSize(tao->constraints, &lclP->m));
118a7e14dcfSSatish Balay 
1199566063dSJacob Faibussowitsch   PetscCall(VecCreate(((PetscObject)tao)->comm,&lclP->U));
1209566063dSJacob Faibussowitsch   PetscCall(VecCreate(((PetscObject)tao)->comm,&lclP->V));
1219566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(tao->state_is,&nlocalstate));
1229566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(tao->design_is,&nlocaldesign));
1239566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(lclP->U,nlocalstate,lclP->m));
1249566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(lclP->V,nlocaldesign,lclP->n-lclP->m));
1259566063dSJacob Faibussowitsch   PetscCall(VecSetType(lclP->U,((PetscObject)(tao->solution))->type_name));
1269566063dSJacob Faibussowitsch   PetscCall(VecSetType(lclP->V,((PetscObject)(tao->solution))->type_name));
1279566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(lclP->U));
1289566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(lclP->V));
1299566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->DU));
1309566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->U0));
1319566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->GU));
1329566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->GU0));
1339566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->GAugL_U));
1349566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->GL_U));
1359566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->GAugL_U0));
1369566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->GL_U0));
1379566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->WU));
1389566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->U,&lclP->r));
1399566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->V0));
1409566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->V1));
1419566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->DV));
1429566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->s));
1439566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->GV));
1449566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->GV0));
1459566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->dbar));
1469566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->GAugL_V));
1479566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->GL_V));
1489566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->GAugL_V0));
1499566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->GL_V0));
1509566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->WV));
1519566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->g1));
1529566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(lclP->V,&lclP->g2));
153a7e14dcfSSatish Balay 
154a7e14dcfSSatish Balay   /* create scatters for state, design subvecs */
1559566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRange(lclP->U,&lo,&hi));
1569566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(((PetscObject)lclP->U)->comm,hi-lo,lo,1,&is_state));
1579566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRange(lclP->V,&lo,&hi));
158a7e14dcfSSatish Balay   if (0) {
159a7e14dcfSSatish Balay     PetscInt sizeU,sizeV;
1609566063dSJacob Faibussowitsch     PetscCall(VecGetSize(lclP->U,&sizeU));
1619566063dSJacob Faibussowitsch     PetscCall(VecGetSize(lclP->V,&sizeV));
16263a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD,"size(U)=%" PetscInt_FMT ", size(V)=%" PetscInt_FMT "\n",sizeU,sizeV));
163a7e14dcfSSatish Balay   }
1649566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(((PetscObject)lclP->V)->comm,hi-lo,lo,1,&is_design));
1659566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(tao->solution,tao->state_is,lclP->U,is_state,&lclP->state_scatter));
1669566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(tao->solution,tao->design_is,lclP->V,is_design,&lclP->design_scatter));
1679566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_state));
1689566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_design));
169a7e14dcfSSatish Balay   PetscFunctionReturn(0);
170a7e14dcfSSatish Balay }
171a7e14dcfSSatish Balay 
172441846f8SBarry Smith static PetscErrorCode TaoSolve_LCL(Tao tao)
173a7e14dcfSSatish Balay {
174a7e14dcfSSatish Balay   TAO_LCL                      *lclP = (TAO_LCL*)tao->data;
1758931d482SJason Sarich   PetscInt                     phase2_iter,nlocal,its;
176e4cb33bbSBarry Smith   TaoLineSearchConvergedReason ls_reason = TAOLINESEARCH_CONTINUE_ITERATING;
177a7e14dcfSSatish Balay   PetscReal                    step=1.0,f, descent, aldescent;
178a7e14dcfSSatish Balay   PetscReal                    cnorm, mnorm;
179a7e14dcfSSatish Balay   PetscReal                    adec,r2,rGL_U,rWU;
180a7e14dcfSSatish Balay   PetscBool                    set,pset,flag,pflag,symmetric;
181a7e14dcfSSatish Balay 
182f06e3bfaSBarry Smith   PetscFunctionBegin;
183a7e14dcfSSatish Balay   lclP->rho = lclP->rho0;
1849566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(lclP->U,&nlocal));
1859566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(lclP->V,&nlocal));
1869566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(lclP->R, nlocal, nlocal, lclP->n-lclP->m, lclP->n-lclP->m));
1879566063dSJacob Faibussowitsch   PetscCall(MatLMVMAllocate(lclP->R,lclP->V,lclP->V));
188a7e14dcfSSatish Balay   lclP->recompute_jacobian_flag = PETSC_TRUE;
189a7e14dcfSSatish Balay 
190a7e14dcfSSatish Balay   /* Scatter to U,V */
1919566063dSJacob Faibussowitsch   PetscCall(LCLScatter(lclP,tao->solution,lclP->U,lclP->V));
192a7e14dcfSSatish Balay 
193a7e14dcfSSatish Balay   /* Evaluate Function, Gradient, Constraints, and Jacobian */
1949566063dSJacob Faibussowitsch   PetscCall(TaoComputeObjectiveAndGradient(tao,tao->solution,&f,tao->gradient));
1959566063dSJacob Faibussowitsch   PetscCall(TaoComputeJacobianState(tao,tao->solution,tao->jacobian_state,tao->jacobian_state_pre,tao->jacobian_state_inv));
1969566063dSJacob Faibussowitsch   PetscCall(TaoComputeJacobianDesign(tao,tao->solution,tao->jacobian_design));
1979566063dSJacob Faibussowitsch   PetscCall(TaoComputeConstraints(tao,tao->solution, tao->constraints));
198a7e14dcfSSatish Balay 
199a7e14dcfSSatish Balay   /* Scatter gradient to GU,GV */
2009566063dSJacob Faibussowitsch   PetscCall(LCLScatter(lclP,tao->gradient,lclP->GU,lclP->GV));
201a7e14dcfSSatish Balay 
202a7e14dcfSSatish Balay   /* Evaluate Lagrangian function and gradient */
203a7e14dcfSSatish Balay   /* p0 */
2049566063dSJacob Faibussowitsch   PetscCall(VecSet(lclP->lamda,0.0)); /*  Initial guess in CG */
2059566063dSJacob Faibussowitsch   PetscCall(MatIsSymmetricKnown(tao->jacobian_state,&set,&flag));
206a7e14dcfSSatish Balay   if (tao->jacobian_state_pre) {
2079566063dSJacob Faibussowitsch     PetscCall(MatIsSymmetricKnown(tao->jacobian_state_pre,&pset,&pflag));
208a7e14dcfSSatish Balay   } else {
209a7e14dcfSSatish Balay     pset = pflag = PETSC_TRUE;
210a7e14dcfSSatish Balay   }
211f06e3bfaSBarry Smith   if (set && pset && flag && pflag) symmetric = PETSC_TRUE;
212f06e3bfaSBarry Smith   else symmetric = PETSC_FALSE;
213a7e14dcfSSatish Balay 
214a7e14dcfSSatish Balay   lclP->solve_type = LCL_ADJOINT2;
215a7e14dcfSSatish Balay   if (tao->jacobian_state_inv) {
216a7e14dcfSSatish Balay     if (symmetric) {
2179566063dSJacob Faibussowitsch       PetscCall(MatMult(tao->jacobian_state_inv, lclP->GU, lclP->lamda)); } else {
2189566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(tao->jacobian_state_inv, lclP->GU, lclP->lamda));
219a7e14dcfSSatish Balay     }
220a7e14dcfSSatish Balay   } else {
2219566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(tao->ksp, tao->jacobian_state, tao->jacobian_state_pre));
222a7e14dcfSSatish Balay     if (symmetric) {
2239566063dSJacob Faibussowitsch       PetscCall(KSPSolve(tao->ksp, lclP->GU,  lclP->lamda));
224a7e14dcfSSatish Balay     } else {
2259566063dSJacob Faibussowitsch       PetscCall(KSPSolveTranspose(tao->ksp, lclP->GU,  lclP->lamda));
226a7e14dcfSSatish Balay     }
2279566063dSJacob Faibussowitsch     PetscCall(KSPGetIterationNumber(tao->ksp,&its));
228a7e14dcfSSatish Balay     tao->ksp_its+=its;
229ae93cb3cSJason Sarich     tao->ksp_tot_its+=its;
230a7e14dcfSSatish Balay   }
2319566063dSJacob Faibussowitsch   PetscCall(VecCopy(lclP->lamda,lclP->lamda0));
2329566063dSJacob Faibussowitsch   PetscCall(LCLComputeAugmentedLagrangianAndGradient(tao->linesearch,tao->solution,&lclP->aug,lclP->GAugL,tao));
233a7e14dcfSSatish Balay 
2349566063dSJacob Faibussowitsch   PetscCall(LCLScatter(lclP,lclP->GL,lclP->GL_U,lclP->GL_V));
2359566063dSJacob Faibussowitsch   PetscCall(LCLScatter(lclP,lclP->GAugL,lclP->GAugL_U,lclP->GAugL_V));
236a7e14dcfSSatish Balay 
237a7e14dcfSSatish Balay   /* Evaluate constraint norm */
2389566063dSJacob Faibussowitsch   PetscCall(VecNorm(tao->constraints, NORM_2, &cnorm));
2399566063dSJacob Faibussowitsch   PetscCall(VecNorm(lclP->GAugL, NORM_2, &mnorm));
240a7e14dcfSSatish Balay 
241a7e14dcfSSatish Balay   /* Monitor convergence */
242763847b4SAlp Dener   tao->reason = TAO_CONTINUE_ITERATING;
2439566063dSJacob Faibussowitsch   PetscCall(TaoLogConvergenceHistory(tao,f,mnorm,cnorm,tao->ksp_its));
2449566063dSJacob Faibussowitsch   PetscCall(TaoMonitor(tao,tao->niter,f,mnorm,cnorm,step));
2459566063dSJacob Faibussowitsch   PetscCall((*tao->ops->convergencetest)(tao,tao->cnvP));
246a7e14dcfSSatish Balay 
247763847b4SAlp Dener   while (tao->reason == TAO_CONTINUE_ITERATING) {
248e1e80dc8SAlp Dener     /* Call general purpose update function */
249e1e80dc8SAlp Dener     if (tao->ops->update) {
2509566063dSJacob Faibussowitsch       PetscCall((*tao->ops->update)(tao, tao->niter, tao->user_update));
251e1e80dc8SAlp Dener     }
252ae93cb3cSJason Sarich     tao->ksp_its=0;
253a7e14dcfSSatish Balay     /* Compute a descent direction for the linearly constrained subproblem
254a7e14dcfSSatish Balay        minimize f(u+du, v+dv)
255a7e14dcfSSatish Balay        s.t. A(u0,v0)du + B(u0,v0)dv = -g(u0,v0) */
256a7e14dcfSSatish Balay 
257a7e14dcfSSatish Balay     /* Store the points around the linearization */
2589566063dSJacob Faibussowitsch     PetscCall(VecCopy(lclP->U, lclP->U0));
2599566063dSJacob Faibussowitsch     PetscCall(VecCopy(lclP->V, lclP->V0));
2609566063dSJacob Faibussowitsch     PetscCall(VecCopy(lclP->GU,lclP->GU0));
2619566063dSJacob Faibussowitsch     PetscCall(VecCopy(lclP->GV,lclP->GV0));
2629566063dSJacob Faibussowitsch     PetscCall(VecCopy(lclP->GAugL_U,lclP->GAugL_U0));
2639566063dSJacob Faibussowitsch     PetscCall(VecCopy(lclP->GAugL_V,lclP->GAugL_V0));
2649566063dSJacob Faibussowitsch     PetscCall(VecCopy(lclP->GL_U,lclP->GL_U0));
2659566063dSJacob Faibussowitsch     PetscCall(VecCopy(lclP->GL_V,lclP->GL_V0));
266a7e14dcfSSatish Balay 
267a7e14dcfSSatish Balay     lclP->aug0 = lclP->aug;
268a7e14dcfSSatish Balay     lclP->lgn0 = lclP->lgn;
269a7e14dcfSSatish Balay 
270a7e14dcfSSatish Balay     /* Given the design variables, we need to project the current iterate
271a7e14dcfSSatish Balay        onto the linearized constraint.  We choose to fix the design variables
272a7e14dcfSSatish Balay        and solve the linear system for the state variables.  The resulting
273a7e14dcfSSatish Balay        point is the Newton direction */
274a7e14dcfSSatish Balay 
275a7e14dcfSSatish Balay     /* Solve r = A\con */
276a7e14dcfSSatish Balay     lclP->solve_type = LCL_FORWARD1;
2779566063dSJacob Faibussowitsch     PetscCall(VecSet(lclP->r,0.0)); /*  Initial guess in CG */
278a7e14dcfSSatish Balay 
279a7e14dcfSSatish Balay     if (tao->jacobian_state_inv) {
2809566063dSJacob Faibussowitsch       PetscCall(MatMult(tao->jacobian_state_inv, tao->constraints, lclP->r));
281a7e14dcfSSatish Balay     } else {
2829566063dSJacob Faibussowitsch       PetscCall(KSPSetOperators(tao->ksp, tao->jacobian_state, tao->jacobian_state_pre));
2839566063dSJacob Faibussowitsch       PetscCall(KSPSolve(tao->ksp, tao->constraints,  lclP->r));
2849566063dSJacob Faibussowitsch       PetscCall(KSPGetIterationNumber(tao->ksp,&its));
285a7e14dcfSSatish Balay       tao->ksp_its+=its;
286ae93cb3cSJason Sarich       tao->ksp_tot_its+=tao->ksp_its;
287a7e14dcfSSatish Balay     }
288a7e14dcfSSatish Balay 
289a7e14dcfSSatish Balay     /* Set design step direction dv to zero */
2909566063dSJacob Faibussowitsch     PetscCall(VecSet(lclP->s, 0.0));
291a7e14dcfSSatish Balay 
292a7e14dcfSSatish Balay     /*
293a7e14dcfSSatish Balay        Check sufficient descent for constraint merit function .5*||con||^2
294a7e14dcfSSatish Balay        con' Ak r >= eps1 ||r||^(2+eps2)
295a7e14dcfSSatish Balay     */
296a7e14dcfSSatish Balay 
297a7e14dcfSSatish Balay     /* Compute WU= Ak' * con */
298a7e14dcfSSatish Balay     if (symmetric)  {
2999566063dSJacob Faibussowitsch       PetscCall(MatMult(tao->jacobian_state,tao->constraints,lclP->WU));
300a7e14dcfSSatish Balay     } else {
3019566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(tao->jacobian_state,tao->constraints,lclP->WU));
302a7e14dcfSSatish Balay     }
303a7e14dcfSSatish Balay     /* Compute r * Ak' * con */
3049566063dSJacob Faibussowitsch     PetscCall(VecDot(lclP->r,lclP->WU,&rWU));
305a7e14dcfSSatish Balay 
306a7e14dcfSSatish Balay     /* compute ||r||^(2+eps2) */
3079566063dSJacob Faibussowitsch     PetscCall(VecNorm(lclP->r,NORM_2,&r2));
308a7e14dcfSSatish Balay     r2 = PetscPowScalar(r2,2.0+lclP->eps2);
309a7e14dcfSSatish Balay     adec = lclP->eps1 * r2;
310a7e14dcfSSatish Balay 
311a7e14dcfSSatish Balay     if (rWU < adec) {
3129566063dSJacob Faibussowitsch       PetscCall(PetscInfo(tao,"Newton direction not descent for constraint, feasibility phase required\n"));
313a7e14dcfSSatish Balay       if (lclP->verbose) {
3149566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Newton direction not descent for constraint: %g -- using steepest descent\n",(double)descent));
315a7e14dcfSSatish Balay       }
316a7e14dcfSSatish Balay 
3179566063dSJacob Faibussowitsch       PetscCall(PetscInfo(tao,"Using steepest descent direction instead.\n"));
3189566063dSJacob Faibussowitsch       PetscCall(VecSet(lclP->r,0.0));
3199566063dSJacob Faibussowitsch       PetscCall(VecAXPY(lclP->r,-1.0,lclP->WU));
3209566063dSJacob Faibussowitsch       PetscCall(VecDot(lclP->r,lclP->r,&rWU));
3219566063dSJacob Faibussowitsch       PetscCall(VecNorm(lclP->r,NORM_2,&r2));
322a7e14dcfSSatish Balay       r2 = PetscPowScalar(r2,2.0+lclP->eps2);
3239566063dSJacob Faibussowitsch       PetscCall(VecDot(lclP->r,lclP->GAugL_U,&descent));
324a7e14dcfSSatish Balay       adec = lclP->eps1 * r2;
325a7e14dcfSSatish Balay     }
326a7e14dcfSSatish Balay 
327a7e14dcfSSatish Balay     /*
328a7e14dcfSSatish Balay        Check descent for aug. lagrangian
329a7e14dcfSSatish Balay        r' (GUk - Ak'*yk - rho*Ak'*con) <= -eps1 ||r||^(2+eps2)
330a7e14dcfSSatish Balay           GL_U = GUk - Ak'*yk
331a7e14dcfSSatish Balay           WU   = Ak'*con
332a7e14dcfSSatish Balay                                          adec=eps1||r||^(2+eps2)
333a7e14dcfSSatish Balay 
334a7e14dcfSSatish Balay        ==>
335a7e14dcfSSatish Balay        Check r'GL_U - rho*r'WU <= adec
336a7e14dcfSSatish Balay     */
337a7e14dcfSSatish Balay 
3389566063dSJacob Faibussowitsch     PetscCall(VecDot(lclP->r,lclP->GL_U,&rGL_U));
339a7e14dcfSSatish Balay     aldescent =  rGL_U - lclP->rho*rWU;
340a7e14dcfSSatish Balay     if (aldescent > -adec) {
341a7e14dcfSSatish Balay       if (lclP->verbose) {
3429566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_WORLD," Newton direction not descent for augmented Lagrangian: %g",(double)aldescent));
343a7e14dcfSSatish Balay       }
3449566063dSJacob Faibussowitsch       PetscCall(PetscInfo(tao,"Newton direction not descent for augmented Lagrangian: %g\n",(double)aldescent));
345a7e14dcfSSatish Balay       lclP->rho =  (rGL_U - adec)/rWU;
346a7e14dcfSSatish Balay       if (lclP->rho > lclP->rhomax) {
347a7e14dcfSSatish Balay         lclP->rho = lclP->rhomax;
34898921bdaSJacob Faibussowitsch         SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"rho=%g > rhomax, case not implemented.  Increase rhomax (-tao_lcl_rhomax)",(double)lclP->rho);
349a7e14dcfSSatish Balay       }
350a7e14dcfSSatish Balay       if (lclP->verbose) {
3519566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_WORLD,"  Increasing penalty parameter to %g\n",(double)lclP->rho));
352a7e14dcfSSatish Balay       }
3539566063dSJacob Faibussowitsch       PetscCall(PetscInfo(tao,"  Increasing penalty parameter to %g\n",(double)lclP->rho));
354a7e14dcfSSatish Balay     }
355a7e14dcfSSatish Balay 
3569566063dSJacob Faibussowitsch     PetscCall(LCLComputeAugmentedLagrangianAndGradient(tao->linesearch,tao->solution,&lclP->aug,lclP->GAugL,tao));
3579566063dSJacob Faibussowitsch     PetscCall(LCLScatter(lclP,lclP->GL,lclP->GL_U,lclP->GL_V));
3589566063dSJacob Faibussowitsch     PetscCall(LCLScatter(lclP,lclP->GAugL,lclP->GAugL_U,lclP->GAugL_V));
359a7e14dcfSSatish Balay 
360a7e14dcfSSatish Balay     /* We now minimize the augmented Lagrangian along the Newton direction */
3619566063dSJacob Faibussowitsch     PetscCall(VecScale(lclP->r,-1.0));
3629566063dSJacob Faibussowitsch     PetscCall(LCLGather(lclP, lclP->r,lclP->s,tao->stepdirection));
3639566063dSJacob Faibussowitsch     PetscCall(VecScale(lclP->r,-1.0));
3649566063dSJacob Faibussowitsch     PetscCall(LCLGather(lclP, lclP->GAugL_U0, lclP->GAugL_V0, lclP->GAugL));
3659566063dSJacob Faibussowitsch     PetscCall(LCLGather(lclP, lclP->U0,lclP->V0,lclP->X0));
366a7e14dcfSSatish Balay 
367a7e14dcfSSatish Balay     lclP->recompute_jacobian_flag = PETSC_TRUE;
368a7e14dcfSSatish Balay 
3699566063dSJacob Faibussowitsch     PetscCall(TaoLineSearchSetInitialStepLength(tao->linesearch,1.0));
3709566063dSJacob Faibussowitsch     PetscCall(TaoLineSearchSetType(tao->linesearch, TAOLINESEARCHMT));
3719566063dSJacob Faibussowitsch     PetscCall(TaoLineSearchSetFromOptions(tao->linesearch));
3729566063dSJacob Faibussowitsch     PetscCall(TaoLineSearchApply(tao->linesearch, tao->solution, &lclP->aug, lclP->GAugL, tao->stepdirection, &step, &ls_reason));
373a7e14dcfSSatish Balay     if (lclP->verbose) {
3749566063dSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Steplength = %g\n",(double)step));
375a7e14dcfSSatish Balay     }
376a7e14dcfSSatish Balay 
3779566063dSJacob Faibussowitsch     PetscCall(LCLScatter(lclP,tao->solution,lclP->U,lclP->V));
3789566063dSJacob Faibussowitsch     PetscCall(TaoComputeObjectiveAndGradient(tao,tao->solution,&f,tao->gradient));
3799566063dSJacob Faibussowitsch     PetscCall(LCLScatter(lclP,tao->gradient,lclP->GU,lclP->GV));
380a7e14dcfSSatish Balay 
3819566063dSJacob Faibussowitsch     PetscCall(LCLScatter(lclP,lclP->GAugL,lclP->GAugL_U,lclP->GAugL_V));
382a7e14dcfSSatish Balay 
383a7e14dcfSSatish Balay     /* Check convergence */
3849566063dSJacob Faibussowitsch     PetscCall(VecNorm(lclP->GAugL, NORM_2, &mnorm));
3859566063dSJacob Faibussowitsch     PetscCall(VecNorm(tao->constraints, NORM_2, &cnorm));
3869566063dSJacob Faibussowitsch     PetscCall(TaoLogConvergenceHistory(tao,f,mnorm,cnorm,tao->ksp_its));
3879566063dSJacob Faibussowitsch     PetscCall(TaoMonitor(tao,tao->niter,f,mnorm,cnorm,step));
3889566063dSJacob Faibussowitsch     PetscCall((*tao->ops->convergencetest)(tao,tao->cnvP));
389763847b4SAlp Dener     if (tao->reason != TAO_CONTINUE_ITERATING) {
390a7e14dcfSSatish Balay       break;
391a7e14dcfSSatish Balay     }
392a7e14dcfSSatish Balay 
393a7e14dcfSSatish Balay     /* TODO: use a heuristic to choose how many iterations should be performed within phase 2 */
394a7e14dcfSSatish Balay     for (phase2_iter=0; phase2_iter<lclP->phase2_niter; phase2_iter++) {
395a7e14dcfSSatish Balay       /* We now minimize the objective function starting from the fraction of
396a7e14dcfSSatish Balay          the Newton point accepted by applying one step of a reduced-space
397a7e14dcfSSatish Balay          method.  The optimization problem is:
398a7e14dcfSSatish Balay 
399a7e14dcfSSatish Balay          minimize f(u+du, v+dv)
400a7e14dcfSSatish Balay          s. t.    A(u0,v0)du + B(u0,v0)du = -alpha g(u0,v0)
401a7e14dcfSSatish Balay 
402a7e14dcfSSatish Balay          In particular, we have that
403a7e14dcfSSatish Balay          du = -inv(A)*(Bdv + alpha g) */
404a7e14dcfSSatish Balay 
4059566063dSJacob Faibussowitsch       PetscCall(TaoComputeJacobianState(tao,lclP->X0,tao->jacobian_state,tao->jacobian_state_pre,tao->jacobian_state_inv));
4069566063dSJacob Faibussowitsch       PetscCall(TaoComputeJacobianDesign(tao,lclP->X0,tao->jacobian_design));
407a7e14dcfSSatish Balay 
408a7e14dcfSSatish Balay       /* Store V and constraints */
4099566063dSJacob Faibussowitsch       PetscCall(VecCopy(lclP->V, lclP->V1));
4109566063dSJacob Faibussowitsch       PetscCall(VecCopy(tao->constraints,lclP->con1));
411a7e14dcfSSatish Balay 
412a7e14dcfSSatish Balay       /* Compute multipliers */
413a7e14dcfSSatish Balay       /* p1 */
4149566063dSJacob Faibussowitsch       PetscCall(VecSet(lclP->lamda,0.0)); /*  Initial guess in CG */
415a7e14dcfSSatish Balay       lclP->solve_type = LCL_ADJOINT1;
4169566063dSJacob Faibussowitsch       PetscCall(MatIsSymmetricKnown(tao->jacobian_state,&set,&flag));
417a7e14dcfSSatish Balay       if (tao->jacobian_state_pre) {
4189566063dSJacob Faibussowitsch         PetscCall(MatIsSymmetricKnown(tao->jacobian_state_pre,&pset,&pflag));
419a7e14dcfSSatish Balay       } else {
420a7e14dcfSSatish Balay         pset = pflag = PETSC_TRUE;
421a7e14dcfSSatish Balay       }
422f06e3bfaSBarry Smith       if (set && pset && flag && pflag) symmetric = PETSC_TRUE;
423f06e3bfaSBarry Smith       else symmetric = PETSC_FALSE;
424a7e14dcfSSatish Balay 
425a7e14dcfSSatish Balay       if (tao->jacobian_state_inv) {
426a7e14dcfSSatish Balay         if (symmetric) {
4279566063dSJacob Faibussowitsch           PetscCall(MatMult(tao->jacobian_state_inv, lclP->GAugL_U, lclP->lamda));
428a7e14dcfSSatish Balay         } else {
4299566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(tao->jacobian_state_inv, lclP->GAugL_U, lclP->lamda));
430a7e14dcfSSatish Balay         }
431a7e14dcfSSatish Balay       } else {
432a7e14dcfSSatish Balay         if (symmetric) {
4339566063dSJacob Faibussowitsch           PetscCall(KSPSolve(tao->ksp, lclP->GAugL_U,  lclP->lamda));
434a7e14dcfSSatish Balay         } else {
4359566063dSJacob Faibussowitsch           PetscCall(KSPSolveTranspose(tao->ksp, lclP->GAugL_U,  lclP->lamda));
436a7e14dcfSSatish Balay         }
4379566063dSJacob Faibussowitsch         PetscCall(KSPGetIterationNumber(tao->ksp,&its));
438a7e14dcfSSatish Balay         tao->ksp_its+=its;
439ae93cb3cSJason Sarich         tao->ksp_tot_its+=its;
440a7e14dcfSSatish Balay       }
4419566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(tao->jacobian_design,lclP->lamda,lclP->g1));
4429566063dSJacob Faibussowitsch       PetscCall(VecAXPY(lclP->g1,-1.0,lclP->GAugL_V));
443a7e14dcfSSatish Balay 
444a7e14dcfSSatish Balay       /* Compute the limited-memory quasi-newton direction */
4458931d482SJason Sarich       if (tao->niter > 0) {
4469566063dSJacob Faibussowitsch         PetscCall(MatSolve(lclP->R,lclP->g1,lclP->s));
4479566063dSJacob Faibussowitsch         PetscCall(VecDot(lclP->s,lclP->g1,&descent));
4480583ad50SJason Sarich         if (descent <= 0) {
449a7e14dcfSSatish Balay           if (lclP->verbose) {
4509566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Reduced-space direction not descent: %g\n",(double)descent));
451a7e14dcfSSatish Balay           }
4529566063dSJacob Faibussowitsch           PetscCall(VecCopy(lclP->g1,lclP->s));
453a7e14dcfSSatish Balay         }
454a7e14dcfSSatish Balay       } else {
4559566063dSJacob Faibussowitsch         PetscCall(VecCopy(lclP->g1,lclP->s));
456a7e14dcfSSatish Balay       }
4579566063dSJacob Faibussowitsch       PetscCall(VecScale(lclP->g1,-1.0));
458a7e14dcfSSatish Balay 
459a7e14dcfSSatish Balay       /* Recover the full space direction */
4609566063dSJacob Faibussowitsch       PetscCall(MatMult(tao->jacobian_design,lclP->s,lclP->WU));
4619566063dSJacob Faibussowitsch       /* PetscCall(VecSet(lclP->r,0.0)); */ /*  Initial guess in CG */
462a7e14dcfSSatish Balay       lclP->solve_type = LCL_FORWARD2;
463a7e14dcfSSatish Balay       if (tao->jacobian_state_inv) {
4649566063dSJacob Faibussowitsch         PetscCall(MatMult(tao->jacobian_state_inv,lclP->WU,lclP->r));
465a7e14dcfSSatish Balay       } else {
4669566063dSJacob Faibussowitsch         PetscCall(KSPSolve(tao->ksp, lclP->WU, lclP->r));
4679566063dSJacob Faibussowitsch         PetscCall(KSPGetIterationNumber(tao->ksp,&its));
468a7e14dcfSSatish Balay         tao->ksp_its += its;
469ae93cb3cSJason Sarich         tao->ksp_tot_its+=its;
470a7e14dcfSSatish Balay       }
471a7e14dcfSSatish Balay 
472a7e14dcfSSatish Balay       /* We now minimize the augmented Lagrangian along the direction -r,s */
4739566063dSJacob Faibussowitsch       PetscCall(VecScale(lclP->r, -1.0));
4749566063dSJacob Faibussowitsch       PetscCall(LCLGather(lclP,lclP->r,lclP->s,tao->stepdirection));
4759566063dSJacob Faibussowitsch       PetscCall(VecScale(lclP->r, -1.0));
476a7e14dcfSSatish Balay       lclP->recompute_jacobian_flag = PETSC_TRUE;
477a7e14dcfSSatish Balay 
4789566063dSJacob Faibussowitsch       PetscCall(TaoLineSearchSetInitialStepLength(tao->linesearch,1.0));
4799566063dSJacob Faibussowitsch       PetscCall(TaoLineSearchSetType(tao->linesearch,TAOLINESEARCHMT));
4809566063dSJacob Faibussowitsch       PetscCall(TaoLineSearchSetFromOptions(tao->linesearch));
4819566063dSJacob Faibussowitsch       PetscCall(TaoLineSearchApply(tao->linesearch, tao->solution, &lclP->aug, lclP->GAugL, tao->stepdirection,&step,&ls_reason));
482a7e14dcfSSatish Balay       if (lclP->verbose) {
4839566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Reduced-space steplength =  %g\n",(double)step));
484a7e14dcfSSatish Balay       }
485a7e14dcfSSatish Balay 
4869566063dSJacob Faibussowitsch       PetscCall(LCLScatter(lclP,tao->solution,lclP->U,lclP->V));
4879566063dSJacob Faibussowitsch       PetscCall(LCLScatter(lclP,lclP->GL,lclP->GL_U,lclP->GL_V));
4889566063dSJacob Faibussowitsch       PetscCall(LCLScatter(lclP,lclP->GAugL,lclP->GAugL_U,lclP->GAugL_V));
4899566063dSJacob Faibussowitsch       PetscCall(TaoComputeObjectiveAndGradient(tao,tao->solution,&f,tao->gradient));
4909566063dSJacob Faibussowitsch       PetscCall(LCLScatter(lclP,tao->gradient,lclP->GU,lclP->GV));
491a7e14dcfSSatish Balay 
492a7e14dcfSSatish Balay       /* Compute the reduced gradient at the new point */
493a7e14dcfSSatish Balay 
4949566063dSJacob Faibussowitsch       PetscCall(TaoComputeJacobianState(tao,lclP->X0,tao->jacobian_state,tao->jacobian_state_pre,tao->jacobian_state_inv));
4959566063dSJacob Faibussowitsch       PetscCall(TaoComputeJacobianDesign(tao,lclP->X0,tao->jacobian_design));
496a7e14dcfSSatish Balay 
497a7e14dcfSSatish Balay       /* p2 */
498a7e14dcfSSatish Balay       /* Compute multipliers, using lamda-rho*con as an initial guess in PCG */
499a7e14dcfSSatish Balay       if (phase2_iter==0) {
5009566063dSJacob Faibussowitsch         PetscCall(VecWAXPY(lclP->lamda,-lclP->rho,lclP->con1,lclP->lamda0));
501f06e3bfaSBarry Smith       } else {
5029566063dSJacob Faibussowitsch         PetscCall(VecAXPY(lclP->lamda,-lclP->rho,tao->constraints));
503a7e14dcfSSatish Balay       }
504a7e14dcfSSatish Balay 
5059566063dSJacob Faibussowitsch       PetscCall(MatIsSymmetricKnown(tao->jacobian_state,&set,&flag));
506a7e14dcfSSatish Balay       if (tao->jacobian_state_pre) {
5079566063dSJacob Faibussowitsch         PetscCall(MatIsSymmetricKnown(tao->jacobian_state_pre,&pset,&pflag));
508a7e14dcfSSatish Balay       } else {
509a7e14dcfSSatish Balay         pset = pflag = PETSC_TRUE;
510a7e14dcfSSatish Balay       }
511f06e3bfaSBarry Smith       if (set && pset && flag && pflag) symmetric = PETSC_TRUE;
512f06e3bfaSBarry Smith       else symmetric = PETSC_FALSE;
513a7e14dcfSSatish Balay 
514a7e14dcfSSatish Balay       lclP->solve_type = LCL_ADJOINT2;
515a7e14dcfSSatish Balay       if (tao->jacobian_state_inv) {
516a7e14dcfSSatish Balay         if (symmetric) {
5179566063dSJacob Faibussowitsch           PetscCall(MatMult(tao->jacobian_state_inv, lclP->GU, lclP->lamda));
518a7e14dcfSSatish Balay         } else {
5199566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(tao->jacobian_state_inv, lclP->GU, lclP->lamda));
520a7e14dcfSSatish Balay         }
521a7e14dcfSSatish Balay       } else {
522a7e14dcfSSatish Balay         if (symmetric) {
5239566063dSJacob Faibussowitsch           PetscCall(KSPSolve(tao->ksp, lclP->GU,  lclP->lamda));
524a7e14dcfSSatish Balay         } else {
5259566063dSJacob Faibussowitsch           PetscCall(KSPSolveTranspose(tao->ksp, lclP->GU,  lclP->lamda));
526a7e14dcfSSatish Balay         }
5279566063dSJacob Faibussowitsch         PetscCall(KSPGetIterationNumber(tao->ksp,&its));
528a7e14dcfSSatish Balay         tao->ksp_its += its;
5292d9aa51bSJason Sarich         tao->ksp_tot_its += its;
530a7e14dcfSSatish Balay       }
531a7e14dcfSSatish Balay 
5329566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(tao->jacobian_design,lclP->lamda,lclP->g2));
5339566063dSJacob Faibussowitsch       PetscCall(VecAXPY(lclP->g2,-1.0,lclP->GV));
534a7e14dcfSSatish Balay 
5359566063dSJacob Faibussowitsch       PetscCall(VecScale(lclP->g2,-1.0));
536a7e14dcfSSatish Balay 
537a7e14dcfSSatish Balay       /* Update the quasi-newton approximation */
5389566063dSJacob Faibussowitsch       PetscCall(MatLMVMUpdate(lclP->R,lclP->V,lclP->g2));
539a7e14dcfSSatish 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 */
540a7e14dcfSSatish Balay 
541a7e14dcfSSatish Balay     }
542a7e14dcfSSatish Balay 
5439566063dSJacob Faibussowitsch     PetscCall(VecCopy(lclP->lamda,lclP->lamda0));
544a7e14dcfSSatish Balay 
545a7e14dcfSSatish Balay     /* Evaluate Function, Gradient, Constraints, and Jacobian */
5469566063dSJacob Faibussowitsch     PetscCall(TaoComputeObjectiveAndGradient(tao,tao->solution,&f,tao->gradient));
5479566063dSJacob Faibussowitsch     PetscCall(LCLScatter(lclP,tao->solution,lclP->U,lclP->V));
5489566063dSJacob Faibussowitsch     PetscCall(LCLScatter(lclP,tao->gradient,lclP->GU,lclP->GV));
549a7e14dcfSSatish Balay 
5509566063dSJacob Faibussowitsch     PetscCall(TaoComputeJacobianState(tao,tao->solution,tao->jacobian_state,tao->jacobian_state_pre,tao->jacobian_state_inv));
5519566063dSJacob Faibussowitsch     PetscCall(TaoComputeJacobianDesign(tao,tao->solution,tao->jacobian_design));
5529566063dSJacob Faibussowitsch     PetscCall(TaoComputeConstraints(tao,tao->solution, tao->constraints));
553a7e14dcfSSatish Balay 
5549566063dSJacob Faibussowitsch     PetscCall(LCLComputeAugmentedLagrangianAndGradient(tao->linesearch,tao->solution,&lclP->aug,lclP->GAugL,tao));
555a7e14dcfSSatish Balay 
5569566063dSJacob Faibussowitsch     PetscCall(VecNorm(lclP->GAugL, NORM_2, &mnorm));
557a7e14dcfSSatish Balay 
558a7e14dcfSSatish Balay     /* Evaluate constraint norm */
5599566063dSJacob Faibussowitsch     PetscCall(VecNorm(tao->constraints, NORM_2, &cnorm));
560a7e14dcfSSatish Balay 
561a7e14dcfSSatish Balay     /* Monitor convergence */
5628931d482SJason Sarich     tao->niter++;
5639566063dSJacob Faibussowitsch     PetscCall(TaoLogConvergenceHistory(tao,f,mnorm,cnorm,tao->ksp_its));
5649566063dSJacob Faibussowitsch     PetscCall(TaoMonitor(tao,tao->niter,f,mnorm,cnorm,step));
5659566063dSJacob Faibussowitsch     PetscCall((*tao->ops->convergencetest)(tao,tao->cnvP));
566a7e14dcfSSatish Balay   }
567a7e14dcfSSatish Balay   PetscFunctionReturn(0);
568a7e14dcfSSatish Balay }
569a7e14dcfSSatish Balay 
5701522df2eSJason Sarich /*MC
5711522df2eSJason Sarich  TAOLCL - linearly constrained lagrangian method for pde-constrained optimization
5721522df2eSJason Sarich 
5731522df2eSJason Sarich + -tao_lcl_eps1 - epsilon 1 tolerance
574d0609cedSBarry Smith . -tao_lcl_eps2","epsilon 2 tolerance","",lclP->eps2,&lclP->eps2,NULL);
575d0609cedSBarry Smith . -tao_lcl_rho0","init value for rho","",lclP->rho0,&lclP->rho0,NULL);
576d0609cedSBarry Smith . -tao_lcl_rhomax","max value for rho","",lclP->rhomax,&lclP->rhomax,NULL);
5771522df2eSJason Sarich . -tao_lcl_phase2_niter - Number of phase 2 iterations in LCL algorithm
5781522df2eSJason Sarich . -tao_lcl_verbose - Print verbose output if True
5791522df2eSJason Sarich . -tao_lcl_tola - Tolerance for first forward solve
5801522df2eSJason Sarich . -tao_lcl_tolb - Tolerance for first adjoint solve
5811522df2eSJason Sarich . -tao_lcl_tolc - Tolerance for second forward solve
5821522df2eSJason Sarich - -tao_lcl_told - Tolerance for second adjoint solve
5831522df2eSJason Sarich 
5841eb8069cSJason Sarich   Level: beginner
5851522df2eSJason Sarich M*/
586728e0ed0SBarry Smith PETSC_EXTERN PetscErrorCode TaoCreate_LCL(Tao tao)
587a7e14dcfSSatish Balay {
588a7e14dcfSSatish Balay   TAO_LCL        *lclP;
5898caf6e8cSBarry Smith   const char     *morethuente_type = TAOLINESEARCHMT;
590a7e14dcfSSatish Balay 
591f06e3bfaSBarry Smith   PetscFunctionBegin;
592a7e14dcfSSatish Balay   tao->ops->setup = TaoSetup_LCL;
593a7e14dcfSSatish Balay   tao->ops->solve = TaoSolve_LCL;
594a7e14dcfSSatish Balay   tao->ops->view = TaoView_LCL;
595a7e14dcfSSatish Balay   tao->ops->setfromoptions = TaoSetFromOptions_LCL;
596a7e14dcfSSatish Balay   tao->ops->destroy = TaoDestroy_LCL;
5979566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(tao,&lclP));
598a7e14dcfSSatish Balay   tao->data = (void*)lclP;
599a7e14dcfSSatish Balay 
6006552cf8aSJason Sarich   /* Override default settings (unless already changed) */
6016552cf8aSJason Sarich   if (!tao->max_it_changed) tao->max_it = 200;
6026552cf8aSJason Sarich   if (!tao->catol_changed) tao->catol = 1.0e-4;
6036552cf8aSJason Sarich   if (!tao->gatol_changed) tao->gttol = 1.0e-4;
6046552cf8aSJason Sarich   if (!tao->grtol_changed) tao->gttol = 1.0e-4;
6056552cf8aSJason Sarich   if (!tao->gttol_changed) tao->gttol = 1.0e-4;
606a7e14dcfSSatish Balay   lclP->rho0 = 1.0e-4;
607a7e14dcfSSatish Balay   lclP->rhomax=1e5;
608a7e14dcfSSatish Balay   lclP->eps1 = 1.0e-8;
609a7e14dcfSSatish Balay   lclP->eps2 = 0.0;
610a7e14dcfSSatish Balay   lclP->solve_type=2;
611a7e14dcfSSatish Balay   lclP->tau[0] = lclP->tau[1] = lclP->tau[2] = lclP->tau[3] = 1.0e-4;
6129566063dSJacob Faibussowitsch   PetscCall(TaoLineSearchCreate(((PetscObject)tao)->comm, &tao->linesearch));
6139566063dSJacob Faibussowitsch   PetscCall(PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1));
6149566063dSJacob Faibussowitsch   PetscCall(TaoLineSearchSetType(tao->linesearch, morethuente_type));
6159566063dSJacob Faibussowitsch   PetscCall(TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix));
616a7e14dcfSSatish Balay 
6179566063dSJacob Faibussowitsch   PetscCall(TaoLineSearchSetObjectiveAndGradientRoutine(tao->linesearch,LCLComputeAugmentedLagrangianAndGradient, tao));
6189566063dSJacob Faibussowitsch   PetscCall(KSPCreate(((PetscObject)tao)->comm,&tao->ksp));
6199566063dSJacob Faibussowitsch   PetscCall(PetscObjectIncrementTabLevel((PetscObject)tao->ksp, (PetscObject)tao, 1));
6209566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(tao->ksp, tao->hdr.prefix));
6219566063dSJacob Faibussowitsch   PetscCall(KSPSetFromOptions(tao->ksp));
6220c51296cSAlp Dener 
6239566063dSJacob Faibussowitsch   PetscCall(MatCreate(((PetscObject)tao)->comm, &lclP->R));
6249566063dSJacob Faibussowitsch   PetscCall(MatSetType(lclP->R, MATLMVMBFGS));
625a7e14dcfSSatish Balay   PetscFunctionReturn(0);
626a7e14dcfSSatish Balay }
627a7e14dcfSSatish Balay 
628a7e14dcfSSatish Balay static PetscErrorCode LCLComputeLagrangianAndGradient(TaoLineSearch ls, Vec X, PetscReal *f, Vec G, void *ptr)
629a7e14dcfSSatish Balay {
630441846f8SBarry Smith   Tao            tao = (Tao)ptr;
631a7e14dcfSSatish Balay   TAO_LCL        *lclP = (TAO_LCL*)tao->data;
632a7e14dcfSSatish Balay   PetscBool      set,pset,flag,pflag,symmetric;
633a7e14dcfSSatish Balay   PetscReal      cdotl;
634a7e14dcfSSatish Balay 
635a7e14dcfSSatish Balay   PetscFunctionBegin;
6369566063dSJacob Faibussowitsch   PetscCall(TaoComputeObjectiveAndGradient(tao,X,f,G));
6379566063dSJacob Faibussowitsch   PetscCall(LCLScatter(lclP,G,lclP->GU,lclP->GV));
638a7e14dcfSSatish Balay   if (lclP->recompute_jacobian_flag) {
6399566063dSJacob Faibussowitsch     PetscCall(TaoComputeJacobianState(tao,X,tao->jacobian_state,tao->jacobian_state_pre,tao->jacobian_state_inv));
6409566063dSJacob Faibussowitsch     PetscCall(TaoComputeJacobianDesign(tao,X,tao->jacobian_design));
641a7e14dcfSSatish Balay   }
6429566063dSJacob Faibussowitsch   PetscCall(TaoComputeConstraints(tao,X, tao->constraints));
6439566063dSJacob Faibussowitsch   PetscCall(MatIsSymmetricKnown(tao->jacobian_state,&set,&flag));
644a7e14dcfSSatish Balay   if (tao->jacobian_state_pre) {
6459566063dSJacob Faibussowitsch     PetscCall(MatIsSymmetricKnown(tao->jacobian_state_pre,&pset,&pflag));
646a7e14dcfSSatish Balay   } else {
647a7e14dcfSSatish Balay     pset = pflag = PETSC_TRUE;
648a7e14dcfSSatish Balay   }
649f06e3bfaSBarry Smith   if (set && pset && flag && pflag) symmetric = PETSC_TRUE;
650f06e3bfaSBarry Smith   else symmetric = PETSC_FALSE;
651a7e14dcfSSatish Balay 
6529566063dSJacob Faibussowitsch   PetscCall(VecDot(lclP->lamda0, tao->constraints, &cdotl));
653a7e14dcfSSatish Balay   lclP->lgn = *f - cdotl;
654a7e14dcfSSatish Balay 
655a7e14dcfSSatish Balay   /* Gradient of Lagrangian GL = G - J' * lamda */
656a7e14dcfSSatish Balay   /*      WU = A' * WL
657a7e14dcfSSatish Balay           WV = B' * WL */
658a7e14dcfSSatish Balay   if (symmetric) {
6599566063dSJacob Faibussowitsch     PetscCall(MatMult(tao->jacobian_state,lclP->lamda0,lclP->GL_U));
660a7e14dcfSSatish Balay   } else {
6619566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(tao->jacobian_state,lclP->lamda0,lclP->GL_U));
662a7e14dcfSSatish Balay   }
6639566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(tao->jacobian_design,lclP->lamda0,lclP->GL_V));
6649566063dSJacob Faibussowitsch   PetscCall(VecScale(lclP->GL_U,-1.0));
6659566063dSJacob Faibussowitsch   PetscCall(VecScale(lclP->GL_V,-1.0));
6669566063dSJacob Faibussowitsch   PetscCall(VecAXPY(lclP->GL_U,1.0,lclP->GU));
6679566063dSJacob Faibussowitsch   PetscCall(VecAXPY(lclP->GL_V,1.0,lclP->GV));
6689566063dSJacob Faibussowitsch   PetscCall(LCLGather(lclP,lclP->GL_U,lclP->GL_V,lclP->GL));
669a7e14dcfSSatish Balay 
670a7e14dcfSSatish Balay   f[0] = lclP->lgn;
6719566063dSJacob Faibussowitsch   PetscCall(VecCopy(lclP->GL,G));
672a7e14dcfSSatish Balay   PetscFunctionReturn(0);
673a7e14dcfSSatish Balay }
674a7e14dcfSSatish Balay 
675a7e14dcfSSatish Balay static PetscErrorCode LCLComputeAugmentedLagrangianAndGradient(TaoLineSearch ls, Vec X, PetscReal *f, Vec G, void *ptr)
676a7e14dcfSSatish Balay {
677441846f8SBarry Smith   Tao            tao = (Tao)ptr;
678a7e14dcfSSatish Balay   TAO_LCL        *lclP = (TAO_LCL*)tao->data;
679a7e14dcfSSatish Balay   PetscReal      con2;
680a7e14dcfSSatish Balay   PetscBool      flag,pflag,set,pset,symmetric;
681a7e14dcfSSatish Balay 
682a7e14dcfSSatish Balay   PetscFunctionBegin;
6839566063dSJacob Faibussowitsch   PetscCall(LCLComputeLagrangianAndGradient(tao->linesearch,X,f,G,tao));
6849566063dSJacob Faibussowitsch   PetscCall(LCLScatter(lclP,G,lclP->GL_U,lclP->GL_V));
6859566063dSJacob Faibussowitsch   PetscCall(VecDot(tao->constraints,tao->constraints,&con2));
686a7e14dcfSSatish Balay   lclP->aug = lclP->lgn + 0.5*lclP->rho*con2;
687a7e14dcfSSatish Balay 
688a7e14dcfSSatish Balay   /* Gradient of Aug. Lagrangian GAugL = GL + rho * J' c */
689a7e14dcfSSatish Balay   /*      WU = A' * c
690a7e14dcfSSatish Balay           WV = B' * c */
6919566063dSJacob Faibussowitsch   PetscCall(MatIsSymmetricKnown(tao->jacobian_state,&set,&flag));
692a7e14dcfSSatish Balay   if (tao->jacobian_state_pre) {
6939566063dSJacob Faibussowitsch     PetscCall(MatIsSymmetricKnown(tao->jacobian_state_pre,&pset,&pflag));
694a7e14dcfSSatish Balay   } else {
695a7e14dcfSSatish Balay     pset = pflag = PETSC_TRUE;
696a7e14dcfSSatish Balay   }
697f06e3bfaSBarry Smith   if (set && pset && flag && pflag) symmetric = PETSC_TRUE;
698f06e3bfaSBarry Smith   else symmetric = PETSC_FALSE;
699a7e14dcfSSatish Balay 
700a7e14dcfSSatish Balay   if (symmetric) {
7019566063dSJacob Faibussowitsch     PetscCall(MatMult(tao->jacobian_state,tao->constraints,lclP->GAugL_U));
702a7e14dcfSSatish Balay   } else {
7039566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(tao->jacobian_state,tao->constraints,lclP->GAugL_U));
704a7e14dcfSSatish Balay   }
705a7e14dcfSSatish Balay 
7069566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(tao->jacobian_design,tao->constraints,lclP->GAugL_V));
7079566063dSJacob Faibussowitsch   PetscCall(VecAYPX(lclP->GAugL_U,lclP->rho,lclP->GL_U));
7089566063dSJacob Faibussowitsch   PetscCall(VecAYPX(lclP->GAugL_V,lclP->rho,lclP->GL_V));
7099566063dSJacob Faibussowitsch   PetscCall(LCLGather(lclP,lclP->GAugL_U,lclP->GAugL_V,lclP->GAugL));
710a7e14dcfSSatish Balay 
711a7e14dcfSSatish Balay   f[0] = lclP->aug;
7129566063dSJacob Faibussowitsch   PetscCall(VecCopy(lclP->GAugL,G));
713a7e14dcfSSatish Balay   PetscFunctionReturn(0);
714a7e14dcfSSatish Balay }
715a7e14dcfSSatish Balay 
716a7e14dcfSSatish Balay PetscErrorCode LCLGather(TAO_LCL *lclP, Vec u, Vec v, Vec x)
717a7e14dcfSSatish Balay {
718a7e14dcfSSatish Balay   PetscFunctionBegin;
7199566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(lclP->state_scatter, u, x, INSERT_VALUES, SCATTER_REVERSE));
7209566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(lclP->state_scatter, u, x, INSERT_VALUES, SCATTER_REVERSE));
7219566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(lclP->design_scatter, v, x, INSERT_VALUES, SCATTER_REVERSE));
7229566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(lclP->design_scatter, v, x, INSERT_VALUES, SCATTER_REVERSE));
723a7e14dcfSSatish Balay   PetscFunctionReturn(0);
724a7e14dcfSSatish Balay 
725a7e14dcfSSatish Balay }
726a7e14dcfSSatish Balay PetscErrorCode LCLScatter(TAO_LCL *lclP, Vec x, Vec u, Vec v)
727a7e14dcfSSatish Balay {
728a7e14dcfSSatish Balay   PetscFunctionBegin;
7299566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(lclP->state_scatter, x, u, INSERT_VALUES, SCATTER_FORWARD));
7309566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(lclP->state_scatter, x, u, INSERT_VALUES, SCATTER_FORWARD));
7319566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(lclP->design_scatter, x, v, INSERT_VALUES, SCATTER_FORWARD));
7329566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(lclP->design_scatter, x, v, INSERT_VALUES, SCATTER_FORWARD));
733a7e14dcfSSatish Balay   PetscFunctionReturn(0);
734a7e14dcfSSatish Balay 
735a7e14dcfSSatish Balay }
736