1aad13602SShrirang Abhyankar #include <../src/tao/constrained/impls/ipm/pdipm.h> 2aad13602SShrirang Abhyankar 3aad13602SShrirang Abhyankar /* 4aad13602SShrirang Abhyankar TaoPDIPMEvaluateFunctionsAndJacobians - Evaluate the objective function f, gradient fx, constraints, and all the Jacobians at current vector 5aad13602SShrirang Abhyankar 6c3339decSBarry Smith Collective 7aad13602SShrirang Abhyankar 8aad13602SShrirang Abhyankar Input Parameter: 9aad13602SShrirang Abhyankar + tao - solver context 10aad13602SShrirang Abhyankar - x - vector at which all objects to be evaluated 11aad13602SShrirang Abhyankar 12aad13602SShrirang Abhyankar Level: beginner 13aad13602SShrirang Abhyankar 142fe279fdSBarry Smith .seealso: `TAOPDIPM`, `TaoPDIPMUpdateConstraints()`, `TaoPDIPMSetUpBounds()` 15aad13602SShrirang Abhyankar */ 16d71ae5a4SJacob Faibussowitsch static PetscErrorCode TaoPDIPMEvaluateFunctionsAndJacobians(Tao tao, Vec x) 17d71ae5a4SJacob Faibussowitsch { 18aad13602SShrirang Abhyankar TAO_PDIPM *pdipm = (TAO_PDIPM *)tao->data; 19aad13602SShrirang Abhyankar 20aad13602SShrirang Abhyankar PetscFunctionBegin; 21aad13602SShrirang Abhyankar /* Compute user objective function and gradient */ 229566063dSJacob Faibussowitsch PetscCall(TaoComputeObjectiveAndGradient(tao, x, &pdipm->obj, tao->gradient)); 23aad13602SShrirang Abhyankar 24aad13602SShrirang Abhyankar /* Equality constraints and Jacobian */ 25aad13602SShrirang Abhyankar if (pdipm->Ng) { 269566063dSJacob Faibussowitsch PetscCall(TaoComputeEqualityConstraints(tao, x, tao->constraints_equality)); 279566063dSJacob Faibussowitsch PetscCall(TaoComputeJacobianEquality(tao, x, tao->jacobian_equality, tao->jacobian_equality_pre)); 28aad13602SShrirang Abhyankar } 29aad13602SShrirang Abhyankar 30aad13602SShrirang Abhyankar /* Inequality constraints and Jacobian */ 31aad13602SShrirang Abhyankar if (pdipm->Nh) { 329566063dSJacob Faibussowitsch PetscCall(TaoComputeInequalityConstraints(tao, x, tao->constraints_inequality)); 339566063dSJacob Faibussowitsch PetscCall(TaoComputeJacobianInequality(tao, x, tao->jacobian_inequality, tao->jacobian_inequality_pre)); 34aad13602SShrirang Abhyankar } 353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 36aad13602SShrirang Abhyankar } 37aad13602SShrirang Abhyankar 38aad13602SShrirang Abhyankar /* 39aad13602SShrirang Abhyankar TaoPDIPMUpdateConstraints - Update the vectors ce and ci at x 40aad13602SShrirang Abhyankar 41aad13602SShrirang Abhyankar Collective 42aad13602SShrirang Abhyankar 43aad13602SShrirang Abhyankar Input Parameter: 44aad13602SShrirang Abhyankar + tao - Tao context 45a5b23f4aSJose E. Roman - x - vector at which constraints to be evaluated 46aad13602SShrirang Abhyankar 47aad13602SShrirang Abhyankar Level: beginner 48aad13602SShrirang Abhyankar 492fe279fdSBarry Smith .seealso: `TAOPDIPM`, `TaoPDIPMEvaluateFunctionsAndJacobians()` 50aad13602SShrirang Abhyankar */ 51d71ae5a4SJacob Faibussowitsch static PetscErrorCode TaoPDIPMUpdateConstraints(Tao tao, Vec x) 52d71ae5a4SJacob Faibussowitsch { 53aad13602SShrirang Abhyankar TAO_PDIPM *pdipm = (TAO_PDIPM *)tao->data; 54aad13602SShrirang Abhyankar PetscInt i, offset, offset1, k, xstart; 55aad13602SShrirang Abhyankar PetscScalar *carr; 56aad13602SShrirang Abhyankar const PetscInt *ubptr, *lbptr, *bxptr, *fxptr; 57aad13602SShrirang Abhyankar const PetscScalar *xarr, *xuarr, *xlarr, *garr, *harr; 58aad13602SShrirang Abhyankar 59aad13602SShrirang Abhyankar PetscFunctionBegin; 609566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(x, &xstart, NULL)); 619566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xarr)); 629566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(tao->XU, &xuarr)); 639566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(tao->XL, &xlarr)); 64aad13602SShrirang Abhyankar 65aad13602SShrirang Abhyankar /* (1) Update ce vector */ 669566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(pdipm->ce, &carr)); 67aad13602SShrirang Abhyankar 688e58fa1dSresundermann if (pdipm->Ng) { 692da392ccSBarry Smith /* (1.a) Inserting updated g(x) */ 709566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(tao->constraints_equality, &garr)); 719566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(carr, garr, pdipm->ng * sizeof(PetscScalar))); 729566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(tao->constraints_equality, &garr)); 73aad13602SShrirang Abhyankar } 74aad13602SShrirang Abhyankar 75aad13602SShrirang Abhyankar /* (1.b) Update xfixed */ 76aad13602SShrirang Abhyankar if (pdipm->Nxfixed) { 77aad13602SShrirang Abhyankar offset = pdipm->ng; 789566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pdipm->isxfixed, &fxptr)); /* global indices in x */ 79aad13602SShrirang Abhyankar for (k = 0; k < pdipm->nxfixed; k++) { 80aad13602SShrirang Abhyankar i = fxptr[k] - xstart; 81aad13602SShrirang Abhyankar carr[offset + k] = xarr[i] - xuarr[i]; 82aad13602SShrirang Abhyankar } 83aad13602SShrirang Abhyankar } 849566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(pdipm->ce, &carr)); 85aad13602SShrirang Abhyankar 86aad13602SShrirang Abhyankar /* (2) Update ci vector */ 879566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(pdipm->ci, &carr)); 88aad13602SShrirang Abhyankar 89aad13602SShrirang Abhyankar if (pdipm->Nh) { 90aad13602SShrirang Abhyankar /* (2.a) Inserting updated h(x) */ 919566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(tao->constraints_inequality, &harr)); 929566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(carr, harr, pdipm->nh * sizeof(PetscScalar))); 939566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(tao->constraints_inequality, &harr)); 94aad13602SShrirang Abhyankar } 95aad13602SShrirang Abhyankar 96aad13602SShrirang Abhyankar /* (2.b) Update xub */ 97aad13602SShrirang Abhyankar offset = pdipm->nh; 98aad13602SShrirang Abhyankar if (pdipm->Nxub) { 999566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pdipm->isxub, &ubptr)); 100aad13602SShrirang Abhyankar for (k = 0; k < pdipm->nxub; k++) { 101aad13602SShrirang Abhyankar i = ubptr[k] - xstart; 102aad13602SShrirang Abhyankar carr[offset + k] = xuarr[i] - xarr[i]; 103aad13602SShrirang Abhyankar } 104aad13602SShrirang Abhyankar } 105aad13602SShrirang Abhyankar 106aad13602SShrirang Abhyankar if (pdipm->Nxlb) { 107aad13602SShrirang Abhyankar /* (2.c) Update xlb */ 108aad13602SShrirang Abhyankar offset += pdipm->nxub; 1099566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pdipm->isxlb, &lbptr)); /* global indices in x */ 110aad13602SShrirang Abhyankar for (k = 0; k < pdipm->nxlb; k++) { 111aad13602SShrirang Abhyankar i = lbptr[k] - xstart; 112aad13602SShrirang Abhyankar carr[offset + k] = xarr[i] - xlarr[i]; 113aad13602SShrirang Abhyankar } 114aad13602SShrirang Abhyankar } 115aad13602SShrirang Abhyankar 116aad13602SShrirang Abhyankar if (pdipm->Nxbox) { 117aad13602SShrirang Abhyankar /* (2.d) Update xbox */ 118aad13602SShrirang Abhyankar offset += pdipm->nxlb; 119aad13602SShrirang Abhyankar offset1 = offset + pdipm->nxbox; 1209566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pdipm->isxbox, &bxptr)); /* global indices in x */ 121aad13602SShrirang Abhyankar for (k = 0; k < pdipm->nxbox; k++) { 122aad13602SShrirang Abhyankar i = bxptr[k] - xstart; /* local indices in x */ 123aad13602SShrirang Abhyankar carr[offset + k] = xuarr[i] - xarr[i]; 124aad13602SShrirang Abhyankar carr[offset1 + k] = xarr[i] - xlarr[i]; 125aad13602SShrirang Abhyankar } 126aad13602SShrirang Abhyankar } 1279566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(pdipm->ci, &carr)); 128aad13602SShrirang Abhyankar 129aad13602SShrirang Abhyankar /* Restoring Vectors */ 1309566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xarr)); 1319566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(tao->XU, &xuarr)); 1329566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(tao->XL, &xlarr)); 1333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 134aad13602SShrirang Abhyankar } 135aad13602SShrirang Abhyankar 136aad13602SShrirang Abhyankar /* 137aad13602SShrirang Abhyankar TaoPDIPMSetUpBounds - Create upper and lower bound vectors of x 138aad13602SShrirang Abhyankar 139aad13602SShrirang Abhyankar Collective 140aad13602SShrirang Abhyankar 141aad13602SShrirang Abhyankar Input Parameter: 142aad13602SShrirang Abhyankar . tao - holds pdipm and XL & XU 143aad13602SShrirang Abhyankar 144aad13602SShrirang Abhyankar Level: beginner 145aad13602SShrirang Abhyankar 1462fe279fdSBarry Smith .seealso: `TAOPDIPM`, `TaoPDIPMUpdateConstraints` 147aad13602SShrirang Abhyankar */ 148d71ae5a4SJacob Faibussowitsch static PetscErrorCode TaoPDIPMSetUpBounds(Tao tao) 149d71ae5a4SJacob Faibussowitsch { 150aad13602SShrirang Abhyankar TAO_PDIPM *pdipm = (TAO_PDIPM *)tao->data; 151aad13602SShrirang Abhyankar const PetscScalar *xl, *xu; 152aad13602SShrirang Abhyankar PetscInt n, *ixlb, *ixub, *ixfixed, *ixfree, *ixbox, i, low, high, idx; 153aad13602SShrirang Abhyankar MPI_Comm comm; 154aad13602SShrirang Abhyankar PetscInt sendbuf[5], recvbuf[5]; 155aad13602SShrirang Abhyankar 156aad13602SShrirang Abhyankar PetscFunctionBegin; 157aad13602SShrirang Abhyankar /* Creates upper and lower bounds vectors on x, if not created already */ 1589566063dSJacob Faibussowitsch PetscCall(TaoComputeVariableBounds(tao)); 159aad13602SShrirang Abhyankar 1609566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(tao->XL, &n)); 1619566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(n, &ixlb, n, &ixub, n, &ixfree, n, &ixfixed, n, &ixbox)); 162aad13602SShrirang Abhyankar 1639566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(tao->XL, &low, &high)); 1649566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(tao->XL, &xl)); 1659566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(tao->XU, &xu)); 166aad13602SShrirang Abhyankar for (i = 0; i < n; i++) { 167aad13602SShrirang Abhyankar idx = low + i; 168aad13602SShrirang Abhyankar if ((PetscRealPart(xl[i]) > PETSC_NINFINITY) && (PetscRealPart(xu[i]) < PETSC_INFINITY)) { 169aad13602SShrirang Abhyankar if (PetscRealPart(xl[i]) == PetscRealPart(xu[i])) { 170aad13602SShrirang Abhyankar ixfixed[pdipm->nxfixed++] = idx; 171aad13602SShrirang Abhyankar } else ixbox[pdipm->nxbox++] = idx; 172aad13602SShrirang Abhyankar } else { 173aad13602SShrirang Abhyankar if ((PetscRealPart(xl[i]) > PETSC_NINFINITY) && (PetscRealPart(xu[i]) >= PETSC_INFINITY)) { 174aad13602SShrirang Abhyankar ixlb[pdipm->nxlb++] = idx; 175aad13602SShrirang Abhyankar } else if ((PetscRealPart(xl[i]) <= PETSC_NINFINITY) && (PetscRealPart(xu[i]) < PETSC_INFINITY)) { 176aad13602SShrirang Abhyankar ixub[pdipm->nxlb++] = idx; 177aad13602SShrirang Abhyankar } else ixfree[pdipm->nxfree++] = idx; 178aad13602SShrirang Abhyankar } 179aad13602SShrirang Abhyankar } 1809566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(tao->XL, &xl)); 1819566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(tao->XU, &xu)); 182aad13602SShrirang Abhyankar 1839566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)tao, &comm)); 184aad13602SShrirang Abhyankar sendbuf[0] = pdipm->nxlb; 185aad13602SShrirang Abhyankar sendbuf[1] = pdipm->nxub; 186aad13602SShrirang Abhyankar sendbuf[2] = pdipm->nxfixed; 187aad13602SShrirang Abhyankar sendbuf[3] = pdipm->nxbox; 188aad13602SShrirang Abhyankar sendbuf[4] = pdipm->nxfree; 189aad13602SShrirang Abhyankar 190462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(sendbuf, recvbuf, 5, MPIU_INT, MPI_SUM, comm)); 191aad13602SShrirang Abhyankar pdipm->Nxlb = recvbuf[0]; 192aad13602SShrirang Abhyankar pdipm->Nxub = recvbuf[1]; 193aad13602SShrirang Abhyankar pdipm->Nxfixed = recvbuf[2]; 194aad13602SShrirang Abhyankar pdipm->Nxbox = recvbuf[3]; 195aad13602SShrirang Abhyankar pdipm->Nxfree = recvbuf[4]; 196aad13602SShrirang Abhyankar 19748a46eb9SPierre Jolivet if (pdipm->Nxlb) PetscCall(ISCreateGeneral(comm, pdipm->nxlb, ixlb, PETSC_COPY_VALUES, &pdipm->isxlb)); 19848a46eb9SPierre Jolivet if (pdipm->Nxub) PetscCall(ISCreateGeneral(comm, pdipm->nxub, ixub, PETSC_COPY_VALUES, &pdipm->isxub)); 19948a46eb9SPierre Jolivet if (pdipm->Nxfixed) PetscCall(ISCreateGeneral(comm, pdipm->nxfixed, ixfixed, PETSC_COPY_VALUES, &pdipm->isxfixed)); 20048a46eb9SPierre Jolivet if (pdipm->Nxbox) PetscCall(ISCreateGeneral(comm, pdipm->nxbox, ixbox, PETSC_COPY_VALUES, &pdipm->isxbox)); 20148a46eb9SPierre Jolivet if (pdipm->Nxfree) PetscCall(ISCreateGeneral(comm, pdipm->nxfree, ixfree, PETSC_COPY_VALUES, &pdipm->isxfree)); 2029566063dSJacob Faibussowitsch PetscCall(PetscFree5(ixlb, ixub, ixfixed, ixbox, ixfree)); 2033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 204aad13602SShrirang Abhyankar } 205aad13602SShrirang Abhyankar 206aad13602SShrirang Abhyankar /* 2072fe279fdSBarry Smith TaoPDIPMInitializeSolution - Initialize `TAOPDIPM` solution X = [x; lambdae; lambdai; z]. 208aad13602SShrirang Abhyankar X consists of four subvectors in the order [x; lambdae; lambdai; z]. These 209aad13602SShrirang Abhyankar four subvectors need to be initialized and its values copied over to X. Instead 2102fe279fdSBarry Smith of copying, we use `VecPlaceArray()`/`VecResetArray()` functions to share the memory locations for 211aad13602SShrirang Abhyankar X and the subvectors 212aad13602SShrirang Abhyankar 213aad13602SShrirang Abhyankar Collective 214aad13602SShrirang Abhyankar 215aad13602SShrirang Abhyankar Input Parameter: 216aad13602SShrirang Abhyankar . tao - Tao context 217aad13602SShrirang Abhyankar 218aad13602SShrirang Abhyankar Level: beginner 219aad13602SShrirang Abhyankar */ 220d71ae5a4SJacob Faibussowitsch static PetscErrorCode TaoPDIPMInitializeSolution(Tao tao) 221d71ae5a4SJacob Faibussowitsch { 222aad13602SShrirang Abhyankar TAO_PDIPM *pdipm = (TAO_PDIPM *)tao->data; 223aad13602SShrirang Abhyankar PetscScalar *Xarr, *z, *lambdai; 224aad13602SShrirang Abhyankar PetscInt i; 225aad13602SShrirang Abhyankar const PetscScalar *xarr, *h; 226aad13602SShrirang Abhyankar 227aad13602SShrirang Abhyankar PetscFunctionBegin; 2289566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(pdipm->X, &Xarr)); 229aad13602SShrirang Abhyankar 230aad13602SShrirang Abhyankar /* Set Initialize X.x = tao->solution */ 2319566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(tao->solution, &xarr)); 2329566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(Xarr, xarr, pdipm->nx * sizeof(PetscScalar))); 2339566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(tao->solution, &xarr)); 234aad13602SShrirang Abhyankar 235aad13602SShrirang Abhyankar /* Initialize X.lambdae = 0.0 */ 2361baa6e33SBarry Smith if (pdipm->lambdae) PetscCall(VecSet(pdipm->lambdae, 0.0)); 2377f6ac294SRylee Sundermann 238aad13602SShrirang Abhyankar /* Initialize X.lambdai = push_init_lambdai, X.z = push_init_slack */ 2397f6ac294SRylee Sundermann if (pdipm->Nci) { 2409566063dSJacob Faibussowitsch PetscCall(VecSet(pdipm->lambdai, pdipm->push_init_lambdai)); 2419566063dSJacob Faibussowitsch PetscCall(VecSet(pdipm->z, pdipm->push_init_slack)); 242aad13602SShrirang Abhyankar 243aad13602SShrirang Abhyankar /* Additional modification for X.lambdai and X.z */ 2449566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(pdipm->lambdai, &lambdai)); 2459566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(pdipm->z, &z)); 246aad13602SShrirang Abhyankar if (pdipm->Nh) { 2479566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(tao->constraints_inequality, &h)); 248aad13602SShrirang Abhyankar for (i = 0; i < pdipm->nh; i++) { 249aad13602SShrirang Abhyankar if (h[i] < -pdipm->push_init_slack) z[i] = -h[i]; 250aad13602SShrirang Abhyankar if (pdipm->mu / z[i] > pdipm->push_init_lambdai) lambdai[i] = pdipm->mu / z[i]; 251aad13602SShrirang Abhyankar } 2529566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(tao->constraints_inequality, &h)); 253aad13602SShrirang Abhyankar } 2549566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(pdipm->lambdai, &lambdai)); 2559566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(pdipm->z, &z)); 25652030a5eSPierre Jolivet } 257aad13602SShrirang Abhyankar 2589566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(pdipm->X, &Xarr)); 2593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 260aad13602SShrirang Abhyankar } 261aad13602SShrirang Abhyankar 262aad13602SShrirang Abhyankar /* 263aad13602SShrirang Abhyankar TaoSNESJacobian_PDIPM - Evaluate the Hessian matrix at X 264aad13602SShrirang Abhyankar 265aad13602SShrirang Abhyankar Input Parameter: 266aad13602SShrirang Abhyankar snes - SNES context 267aad13602SShrirang Abhyankar X - KKT Vector 268aad13602SShrirang Abhyankar *ctx - pdipm context 269aad13602SShrirang Abhyankar 270aad13602SShrirang Abhyankar Output Parameter: 271aad13602SShrirang Abhyankar J - Hessian matrix 2722fe279fdSBarry Smith Jpre - matrix to build the preconditioner from 273aad13602SShrirang Abhyankar */ 274d71ae5a4SJacob Faibussowitsch static PetscErrorCode TaoSNESJacobian_PDIPM(SNES snes, Vec X, Mat J, Mat Jpre, void *ctx) 275d71ae5a4SJacob Faibussowitsch { 276aad13602SShrirang Abhyankar Tao tao = (Tao)ctx; 277aad13602SShrirang Abhyankar TAO_PDIPM *pdipm = (TAO_PDIPM *)tao->data; 278aad13602SShrirang Abhyankar PetscInt i, row, cols[2], Jrstart, rjstart, nc, j; 279aad13602SShrirang Abhyankar const PetscInt *aj, *ranges, *Jranges, *rranges, *cranges; 280aad13602SShrirang Abhyankar const PetscScalar *Xarr, *aa; 281aad13602SShrirang Abhyankar PetscScalar vals[2]; 282aad13602SShrirang Abhyankar PetscInt proc, nx_all, *nce_all = pdipm->nce_all; 283aad13602SShrirang Abhyankar MPI_Comm comm; 284aad13602SShrirang Abhyankar PetscMPIInt rank, size; 285aad13602SShrirang Abhyankar 286aad13602SShrirang Abhyankar PetscFunctionBegin; 2879566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 2889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 2899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &size)); 290aad13602SShrirang Abhyankar 2919566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRanges(Jpre, &Jranges)); 2929566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(Jpre, &Jrstart, NULL)); 2939566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangesColumn(tao->hessian, &rranges)); 2949566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangesColumn(tao->hessian, &cranges)); 295aad13602SShrirang Abhyankar 2969566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(X, &Xarr)); 297aad13602SShrirang Abhyankar 2987f6ac294SRylee Sundermann /* (1) insert Z and Ci to the 4th block of Jpre -- overwrite existing values */ 29912d688e0SRylee Sundermann if (pdipm->solve_symmetric_kkt) { /* 1 for eq 17 revised pdipm doc 0 for eq 18 (symmetric KKT) */ 30012d688e0SRylee Sundermann vals[0] = 1.0; 30112d688e0SRylee Sundermann for (i = 0; i < pdipm->nci; i++) { 30212d688e0SRylee Sundermann row = Jrstart + pdipm->off_z + i; 30312d688e0SRylee Sundermann cols[0] = Jrstart + pdipm->off_lambdai + i; 30412d688e0SRylee Sundermann cols[1] = row; 30512d688e0SRylee Sundermann vals[1] = Xarr[pdipm->off_lambdai + i] / Xarr[pdipm->off_z + i]; 3069566063dSJacob Faibussowitsch PetscCall(MatSetValues(Jpre, 1, &row, 2, cols, vals, INSERT_VALUES)); 30712d688e0SRylee Sundermann } 30812d688e0SRylee Sundermann } else { 309aad13602SShrirang Abhyankar for (i = 0; i < pdipm->nci; i++) { 310aad13602SShrirang Abhyankar row = Jrstart + pdipm->off_z + i; 311aad13602SShrirang Abhyankar cols[0] = Jrstart + pdipm->off_lambdai + i; 312aad13602SShrirang Abhyankar cols[1] = row; 313aad13602SShrirang Abhyankar vals[0] = Xarr[pdipm->off_z + i]; 314aad13602SShrirang Abhyankar vals[1] = Xarr[pdipm->off_lambdai + i]; 3159566063dSJacob Faibussowitsch PetscCall(MatSetValues(Jpre, 1, &row, 2, cols, vals, INSERT_VALUES)); 316aad13602SShrirang Abhyankar } 31712d688e0SRylee Sundermann } 318aad13602SShrirang Abhyankar 3197f6ac294SRylee Sundermann /* (2) insert 2nd row block of Jpre: [ grad g, 0, 0, 0] */ 320aad13602SShrirang Abhyankar if (pdipm->Ng) { 3219566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(tao->jacobian_equality, &rjstart, NULL)); 322aad13602SShrirang Abhyankar for (i = 0; i < pdipm->ng; i++) { 323aad13602SShrirang Abhyankar row = Jrstart + pdipm->off_lambdae + i; 324aad13602SShrirang Abhyankar 3259566063dSJacob Faibussowitsch PetscCall(MatGetRow(tao->jacobian_equality, i + rjstart, &nc, &aj, &aa)); 326aad13602SShrirang Abhyankar proc = 0; 327aad13602SShrirang Abhyankar for (j = 0; j < nc; j++) { 328aad13602SShrirang Abhyankar while (aj[j] >= cranges[proc + 1]) proc++; 329aad13602SShrirang Abhyankar cols[0] = aj[j] - cranges[proc] + Jranges[proc]; 3309566063dSJacob Faibussowitsch PetscCall(MatSetValue(Jpre, row, cols[0], aa[j], INSERT_VALUES)); 331aad13602SShrirang Abhyankar } 3329566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(tao->jacobian_equality, i + rjstart, &nc, &aj, &aa)); 33309ee8bb0SRylee Sundermann if (pdipm->kkt_pd) { 3347f6ac294SRylee Sundermann /* add shift \delta_c */ 3359566063dSJacob Faibussowitsch PetscCall(MatSetValue(Jpre, row, row, -pdipm->deltac, INSERT_VALUES)); 33609ee8bb0SRylee Sundermann } 337aad13602SShrirang Abhyankar } 338aad13602SShrirang Abhyankar } 339aad13602SShrirang Abhyankar 340a5b23f4aSJose E. Roman /* (3) insert 3rd row block of Jpre: [ -grad h, 0, deltac, I] */ 341aad13602SShrirang Abhyankar if (pdipm->Nh) { 3429566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(tao->jacobian_inequality, &rjstart, NULL)); 343aad13602SShrirang Abhyankar for (i = 0; i < pdipm->nh; i++) { 344aad13602SShrirang Abhyankar row = Jrstart + pdipm->off_lambdai + i; 3459566063dSJacob Faibussowitsch PetscCall(MatGetRow(tao->jacobian_inequality, i + rjstart, &nc, &aj, &aa)); 346aad13602SShrirang Abhyankar proc = 0; 347aad13602SShrirang Abhyankar for (j = 0; j < nc; j++) { 348aad13602SShrirang Abhyankar while (aj[j] >= cranges[proc + 1]) proc++; 349aad13602SShrirang Abhyankar cols[0] = aj[j] - cranges[proc] + Jranges[proc]; 3509566063dSJacob Faibussowitsch PetscCall(MatSetValue(Jpre, row, cols[0], -aa[j], INSERT_VALUES)); 351aad13602SShrirang Abhyankar } 3529566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(tao->jacobian_inequality, i + rjstart, &nc, &aj, &aa)); 35309ee8bb0SRylee Sundermann if (pdipm->kkt_pd) { 3547f6ac294SRylee Sundermann /* add shift \delta_c */ 3559566063dSJacob Faibussowitsch PetscCall(MatSetValue(Jpre, row, row, -pdipm->deltac, INSERT_VALUES)); 35609ee8bb0SRylee Sundermann } 357aad13602SShrirang Abhyankar } 358aad13602SShrirang Abhyankar } 359aad13602SShrirang Abhyankar 3607f6ac294SRylee Sundermann /* (4) insert 1st row block of Jpre: [Wxx, grad g', -grad h', 0] */ 3617f6ac294SRylee Sundermann if (pdipm->Ng) { /* grad g' */ 3629a8cc538SBarry Smith PetscCall(MatTranspose(tao->jacobian_equality, MAT_REUSE_MATRIX, &pdipm->jac_equality_trans)); 363aad13602SShrirang Abhyankar } 3647f6ac294SRylee Sundermann if (pdipm->Nh) { /* grad h' */ 3659a8cc538SBarry Smith PetscCall(MatTranspose(tao->jacobian_inequality, MAT_REUSE_MATRIX, &pdipm->jac_inequality_trans)); 366aad13602SShrirang Abhyankar } 367aad13602SShrirang Abhyankar 3689566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pdipm->x, Xarr)); 3699566063dSJacob Faibussowitsch PetscCall(TaoComputeHessian(tao, pdipm->x, tao->hessian, tao->hessian_pre)); 3709566063dSJacob Faibussowitsch PetscCall(VecResetArray(pdipm->x)); 371aad13602SShrirang Abhyankar 3729566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(tao->hessian, &rjstart, NULL)); 373aad13602SShrirang Abhyankar for (i = 0; i < pdipm->nx; i++) { 374aad13602SShrirang Abhyankar row = Jrstart + i; 375aad13602SShrirang Abhyankar 3767f6ac294SRylee Sundermann /* insert Wxx = fxx + ... -- provided by user */ 3779566063dSJacob Faibussowitsch PetscCall(MatGetRow(tao->hessian, i + rjstart, &nc, &aj, &aa)); 378aad13602SShrirang Abhyankar proc = 0; 379aad13602SShrirang Abhyankar for (j = 0; j < nc; j++) { 380aad13602SShrirang Abhyankar while (aj[j] >= cranges[proc + 1]) proc++; 381aad13602SShrirang Abhyankar cols[0] = aj[j] - cranges[proc] + Jranges[proc]; 38209ee8bb0SRylee Sundermann if (row == cols[0] && pdipm->kkt_pd) { 3837f6ac294SRylee Sundermann /* add shift deltaw to Wxx component */ 3849566063dSJacob Faibussowitsch PetscCall(MatSetValue(Jpre, row, cols[0], aa[j] + pdipm->deltaw, INSERT_VALUES)); 38509ee8bb0SRylee Sundermann } else { 3869566063dSJacob Faibussowitsch PetscCall(MatSetValue(Jpre, row, cols[0], aa[j], INSERT_VALUES)); 387aad13602SShrirang Abhyankar } 38809ee8bb0SRylee Sundermann } 3899566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(tao->hessian, i + rjstart, &nc, &aj, &aa)); 390aad13602SShrirang Abhyankar 391aad13602SShrirang Abhyankar /* insert grad g' */ 3927f6ac294SRylee Sundermann if (pdipm->ng) { 3939a8cc538SBarry Smith PetscCall(MatGetRow(pdipm->jac_equality_trans, i + rjstart, &nc, &aj, &aa)); 3949566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRanges(tao->jacobian_equality, &ranges)); 395aad13602SShrirang Abhyankar proc = 0; 396aad13602SShrirang Abhyankar for (j = 0; j < nc; j++) { 397aad13602SShrirang Abhyankar /* find row ownership of */ 398aad13602SShrirang Abhyankar while (aj[j] >= ranges[proc + 1]) proc++; 399aad13602SShrirang Abhyankar nx_all = rranges[proc + 1] - rranges[proc]; 400aad13602SShrirang Abhyankar cols[0] = aj[j] - ranges[proc] + Jranges[proc] + nx_all; 4019566063dSJacob Faibussowitsch PetscCall(MatSetValue(Jpre, row, cols[0], aa[j], INSERT_VALUES)); 402aad13602SShrirang Abhyankar } 4039a8cc538SBarry Smith PetscCall(MatRestoreRow(pdipm->jac_equality_trans, i + rjstart, &nc, &aj, &aa)); 404aad13602SShrirang Abhyankar } 405aad13602SShrirang Abhyankar 406aad13602SShrirang Abhyankar /* insert -grad h' */ 4077f6ac294SRylee Sundermann if (pdipm->nh) { 4089a8cc538SBarry Smith PetscCall(MatGetRow(pdipm->jac_inequality_trans, i + rjstart, &nc, &aj, &aa)); 4099566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRanges(tao->jacobian_inequality, &ranges)); 410aad13602SShrirang Abhyankar proc = 0; 411aad13602SShrirang Abhyankar for (j = 0; j < nc; j++) { 412aad13602SShrirang Abhyankar /* find row ownership of */ 413aad13602SShrirang Abhyankar while (aj[j] >= ranges[proc + 1]) proc++; 414aad13602SShrirang Abhyankar nx_all = rranges[proc + 1] - rranges[proc]; 415aad13602SShrirang Abhyankar cols[0] = aj[j] - ranges[proc] + Jranges[proc] + nx_all + nce_all[proc]; 4169566063dSJacob Faibussowitsch PetscCall(MatSetValue(Jpre, row, cols[0], -aa[j], INSERT_VALUES)); 417aad13602SShrirang Abhyankar } 4189a8cc538SBarry Smith PetscCall(MatRestoreRow(pdipm->jac_inequality_trans, i + rjstart, &nc, &aj, &aa)); 419aad13602SShrirang Abhyankar } 420aad13602SShrirang Abhyankar } 4219566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(X, &Xarr)); 422aad13602SShrirang Abhyankar 423aad13602SShrirang Abhyankar /* (6) assemble Jpre and J */ 4249566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(Jpre, MAT_FINAL_ASSEMBLY)); 4259566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(Jpre, MAT_FINAL_ASSEMBLY)); 426aad13602SShrirang Abhyankar 427aad13602SShrirang Abhyankar if (J != Jpre) { 4289566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 4299566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 430aad13602SShrirang Abhyankar } 4313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 432aad13602SShrirang Abhyankar } 433aad13602SShrirang Abhyankar 434aad13602SShrirang Abhyankar /* 435aad13602SShrirang Abhyankar TaoSnesFunction_PDIPM - Evaluate KKT function at X 436aad13602SShrirang Abhyankar 437aad13602SShrirang Abhyankar Input Parameter: 438aad13602SShrirang Abhyankar snes - SNES context 439aad13602SShrirang Abhyankar X - KKT Vector 440aad13602SShrirang Abhyankar *ctx - pdipm 441aad13602SShrirang Abhyankar 442aad13602SShrirang Abhyankar Output Parameter: 443aad13602SShrirang Abhyankar F - Updated Lagrangian vector 444aad13602SShrirang Abhyankar */ 445d71ae5a4SJacob Faibussowitsch static PetscErrorCode TaoSNESFunction_PDIPM(SNES snes, Vec X, Vec F, void *ctx) 446d71ae5a4SJacob Faibussowitsch { 447aad13602SShrirang Abhyankar Tao tao = (Tao)ctx; 448aad13602SShrirang Abhyankar TAO_PDIPM *pdipm = (TAO_PDIPM *)tao->data; 4497f6ac294SRylee Sundermann PetscScalar *Farr; 450aad13602SShrirang Abhyankar Vec x, L1; 451aad13602SShrirang Abhyankar PetscInt i; 452aad13602SShrirang Abhyankar const PetscScalar *Xarr, *carr, *zarr, *larr; 453aad13602SShrirang Abhyankar 454aad13602SShrirang Abhyankar PetscFunctionBegin; 4559566063dSJacob Faibussowitsch PetscCall(VecSet(F, 0.0)); 456aad13602SShrirang Abhyankar 4579566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(X, &Xarr)); 4589566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(F, &Farr)); 459aad13602SShrirang Abhyankar 4607f6ac294SRylee Sundermann /* (0) Evaluate f, fx, gradG, gradH at X.x Note: pdipm->x is not changed below */ 461aad13602SShrirang Abhyankar x = pdipm->x; 4629566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(x, Xarr)); 4639566063dSJacob Faibussowitsch PetscCall(TaoPDIPMEvaluateFunctionsAndJacobians(tao, x)); 464aad13602SShrirang Abhyankar 465aad13602SShrirang Abhyankar /* Update ce, ci, and Jci at X.x */ 4669566063dSJacob Faibussowitsch PetscCall(TaoPDIPMUpdateConstraints(tao, x)); 4679566063dSJacob Faibussowitsch PetscCall(VecResetArray(x)); 468aad13602SShrirang Abhyankar 469aad13602SShrirang Abhyankar /* (1) L1 = fx + (gradG'*DE + Jce_xfixed'*lambdae_xfixed) - (gradH'*DI + Jci_xb'*lambdai_xb) */ 470aad13602SShrirang Abhyankar L1 = pdipm->x; 4719566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(L1, Farr)); /* L1 = 0.0 */ 472aad13602SShrirang Abhyankar if (pdipm->Nci) { 473aad13602SShrirang Abhyankar if (pdipm->Nh) { 474aad13602SShrirang Abhyankar /* L1 += gradH'*DI. Note: tao->DI is not changed below */ 4759566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(tao->DI, Xarr + pdipm->off_lambdai)); 4769566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(tao->jacobian_inequality, tao->DI, L1, L1)); 4779566063dSJacob Faibussowitsch PetscCall(VecResetArray(tao->DI)); 478aad13602SShrirang Abhyankar } 479aad13602SShrirang Abhyankar 480aad13602SShrirang Abhyankar /* L1 += Jci_xb'*lambdai_xb */ 4819566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pdipm->lambdai_xb, Xarr + pdipm->off_lambdai + pdipm->nh)); 4829566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(pdipm->Jci_xb, pdipm->lambdai_xb, L1, L1)); 4839566063dSJacob Faibussowitsch PetscCall(VecResetArray(pdipm->lambdai_xb)); 484aad13602SShrirang Abhyankar 4857f6ac294SRylee Sundermann /* L1 = - (gradH'*DI + Jci_xb'*lambdai_xb) */ 4869566063dSJacob Faibussowitsch PetscCall(VecScale(L1, -1.0)); 487aad13602SShrirang Abhyankar } 488aad13602SShrirang Abhyankar 489aad13602SShrirang Abhyankar /* L1 += fx */ 4909566063dSJacob Faibussowitsch PetscCall(VecAXPY(L1, 1.0, tao->gradient)); 491aad13602SShrirang Abhyankar 492aad13602SShrirang Abhyankar if (pdipm->Nce) { 493aad13602SShrirang Abhyankar if (pdipm->Ng) { 494aad13602SShrirang Abhyankar /* L1 += gradG'*DE. Note: tao->DE is not changed below */ 4959566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(tao->DE, Xarr + pdipm->off_lambdae)); 4969566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(tao->jacobian_equality, tao->DE, L1, L1)); 4979566063dSJacob Faibussowitsch PetscCall(VecResetArray(tao->DE)); 498aad13602SShrirang Abhyankar } 499aad13602SShrirang Abhyankar if (pdipm->Nxfixed) { 500aad13602SShrirang Abhyankar /* L1 += Jce_xfixed'*lambdae_xfixed */ 5019566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pdipm->lambdae_xfixed, Xarr + pdipm->off_lambdae + pdipm->ng)); 5029566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(pdipm->Jce_xfixed, pdipm->lambdae_xfixed, L1, L1)); 5039566063dSJacob Faibussowitsch PetscCall(VecResetArray(pdipm->lambdae_xfixed)); 504aad13602SShrirang Abhyankar } 505aad13602SShrirang Abhyankar } 5069566063dSJacob Faibussowitsch PetscCall(VecResetArray(L1)); 507aad13602SShrirang Abhyankar 508aad13602SShrirang Abhyankar /* (2) L2 = ce(x) */ 509aad13602SShrirang Abhyankar if (pdipm->Nce) { 5109566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pdipm->ce, &carr)); 511aad13602SShrirang Abhyankar for (i = 0; i < pdipm->nce; i++) Farr[pdipm->off_lambdae + i] = carr[i]; 5129566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pdipm->ce, &carr)); 513aad13602SShrirang Abhyankar } 514aad13602SShrirang Abhyankar 515aad13602SShrirang Abhyankar if (pdipm->Nci) { 51612d688e0SRylee Sundermann if (pdipm->solve_symmetric_kkt) { 5177f6ac294SRylee Sundermann /* (3) L3 = z - ci(x); 5187f6ac294SRylee Sundermann (4) L4 = Lambdai * e - mu/z *e */ 5199566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pdipm->ci, &carr)); 52012d688e0SRylee Sundermann larr = Xarr + pdipm->off_lambdai; 52112d688e0SRylee Sundermann zarr = Xarr + pdipm->off_z; 52212d688e0SRylee Sundermann for (i = 0; i < pdipm->nci; i++) { 52312d688e0SRylee Sundermann Farr[pdipm->off_lambdai + i] = zarr[i] - carr[i]; 52412d688e0SRylee Sundermann Farr[pdipm->off_z + i] = larr[i] - pdipm->mu / zarr[i]; 52512d688e0SRylee Sundermann } 5269566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pdipm->ci, &carr)); 52712d688e0SRylee Sundermann } else { 5287f6ac294SRylee Sundermann /* (3) L3 = z - ci(x); 5297f6ac294SRylee Sundermann (4) L4 = Z * Lambdai * e - mu * e */ 5309566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pdipm->ci, &carr)); 531aad13602SShrirang Abhyankar larr = Xarr + pdipm->off_lambdai; 532aad13602SShrirang Abhyankar zarr = Xarr + pdipm->off_z; 533aad13602SShrirang Abhyankar for (i = 0; i < pdipm->nci; i++) { 53412d688e0SRylee Sundermann Farr[pdipm->off_lambdai + i] = zarr[i] - carr[i]; 535aad13602SShrirang Abhyankar Farr[pdipm->off_z + i] = zarr[i] * larr[i] - pdipm->mu; 536aad13602SShrirang Abhyankar } 5379566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pdipm->ci, &carr)); 538aad13602SShrirang Abhyankar } 53912d688e0SRylee Sundermann } 540aad13602SShrirang Abhyankar 5419566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(X, &Xarr)); 5429566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(F, &Farr)); 5433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5447f6ac294SRylee Sundermann } 545aad13602SShrirang Abhyankar 5467f6ac294SRylee Sundermann /* 54715229ffcSPierre Jolivet Evaluate F(X); then update tao->gnorm0, tao->step = mu, 548f560b561SHong Zhang tao->residual = norm2(F_x,F_z) and tao->cnorm = norm2(F_ce,F_ci). 5497f6ac294SRylee Sundermann */ 550d71ae5a4SJacob Faibussowitsch static PetscErrorCode TaoSNESFunction_PDIPM_residual(SNES snes, Vec X, Vec F, void *ctx) 551d71ae5a4SJacob Faibussowitsch { 5527f6ac294SRylee Sundermann Tao tao = (Tao)ctx; 5537f6ac294SRylee Sundermann TAO_PDIPM *pdipm = (TAO_PDIPM *)tao->data; 5547f6ac294SRylee Sundermann PetscScalar *Farr, *tmparr; 5557f6ac294SRylee Sundermann Vec L1; 5567f6ac294SRylee Sundermann PetscInt i; 5577f6ac294SRylee Sundermann PetscReal res[2], cnorm[2]; 5587f6ac294SRylee Sundermann const PetscScalar *Xarr = NULL; 5597f6ac294SRylee Sundermann 5607f6ac294SRylee Sundermann PetscFunctionBegin; 5619566063dSJacob Faibussowitsch PetscCall(TaoSNESFunction_PDIPM(snes, X, F, (void *)tao)); 5629566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(F, &Farr)); 5639566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(X, &Xarr)); 5647f6ac294SRylee Sundermann 565f560b561SHong Zhang /* compute res[0] = norm2(F_x) */ 5667f6ac294SRylee Sundermann L1 = pdipm->x; 5679566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(L1, Farr)); 5689566063dSJacob Faibussowitsch PetscCall(VecNorm(L1, NORM_2, &res[0])); 5699566063dSJacob Faibussowitsch PetscCall(VecResetArray(L1)); 5707f6ac294SRylee Sundermann 571f560b561SHong Zhang /* compute res[1] = norm2(F_z), cnorm[1] = norm2(F_ci) */ 57252030a5eSPierre Jolivet if (pdipm->z) { 57312d688e0SRylee Sundermann if (pdipm->solve_symmetric_kkt) { 5749566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pdipm->z, Farr + pdipm->off_z)); 57512d688e0SRylee Sundermann if (pdipm->Nci) { 5769566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(pdipm->z, &tmparr)); 57712d688e0SRylee Sundermann for (i = 0; i < pdipm->nci; i++) tmparr[i] *= Xarr[pdipm->off_z + i]; 5789566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(pdipm->z, &tmparr)); 57912d688e0SRylee Sundermann } 58012d688e0SRylee Sundermann 5819566063dSJacob Faibussowitsch PetscCall(VecNorm(pdipm->z, NORM_2, &res[1])); 5827f6ac294SRylee Sundermann 58312d688e0SRylee Sundermann if (pdipm->Nci) { 5849566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(pdipm->z, &tmparr)); 585ad540459SPierre Jolivet for (i = 0; i < pdipm->nci; i++) tmparr[i] /= Xarr[pdipm->off_z + i]; 5869566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(pdipm->z, &tmparr)); 58712d688e0SRylee Sundermann } 5889566063dSJacob Faibussowitsch PetscCall(VecResetArray(pdipm->z)); 5897f6ac294SRylee Sundermann } else { /* !solve_symmetric_kkt */ 5909566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pdipm->z, Farr + pdipm->off_z)); 5919566063dSJacob Faibussowitsch PetscCall(VecNorm(pdipm->z, NORM_2, &res[1])); 5929566063dSJacob Faibussowitsch PetscCall(VecResetArray(pdipm->z)); 59312d688e0SRylee Sundermann } 594aad13602SShrirang Abhyankar 5959566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pdipm->ci, Farr + pdipm->off_lambdai)); 5969566063dSJacob Faibussowitsch PetscCall(VecNorm(pdipm->ci, NORM_2, &cnorm[1])); 5979566063dSJacob Faibussowitsch PetscCall(VecResetArray(pdipm->ci)); 598f560b561SHong Zhang } else { 5999371c9d4SSatish Balay res[1] = 0.0; 6009371c9d4SSatish Balay cnorm[1] = 0.0; 601f560b561SHong Zhang } 6027f6ac294SRylee Sundermann 603f560b561SHong Zhang /* compute cnorm[0] = norm2(F_ce) */ 6047f6ac294SRylee Sundermann if (pdipm->Nce) { 6059566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pdipm->ce, Farr + pdipm->off_lambdae)); 6069566063dSJacob Faibussowitsch PetscCall(VecNorm(pdipm->ce, NORM_2, &cnorm[0])); 6079566063dSJacob Faibussowitsch PetscCall(VecResetArray(pdipm->ce)); 6087f6ac294SRylee Sundermann } else cnorm[0] = 0.0; 6097f6ac294SRylee Sundermann 6109566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(F, &Farr)); 6119566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(X, &Xarr)); 612f560b561SHong Zhang 613f560b561SHong Zhang tao->gnorm0 = tao->residual; 614f560b561SHong Zhang tao->residual = PetscSqrtReal(res[0] * res[0] + res[1] * res[1]); 615f560b561SHong Zhang tao->cnorm = PetscSqrtReal(cnorm[0] * cnorm[0] + cnorm[1] * cnorm[1]); 616f560b561SHong Zhang tao->step = pdipm->mu; 6173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 618aad13602SShrirang Abhyankar } 619aad13602SShrirang Abhyankar 620aad13602SShrirang Abhyankar /* 621*ab76df0cSBarry Smith PCPostSetup_PDIPM -- called when the KKT matrix is Cholesky factored for the preconditioner. Checks the inertia of Cholesky factor of the KKT matrix. 6227f6ac294SRylee Sundermann If it does not match the numbers of prime and dual variables, add shifts to the KKT matrix. 623aad13602SShrirang Abhyankar */ 624*ab76df0cSBarry Smith static PetscErrorCode PCPostSetUp_PDIPM(PC pc) 625d71ae5a4SJacob Faibussowitsch { 626*ab76df0cSBarry Smith Tao tao; 627*ab76df0cSBarry Smith TAO_PDIPM *pdipm; 628*ab76df0cSBarry Smith Vec X; 629*ab76df0cSBarry Smith SNES snes; 63009ee8bb0SRylee Sundermann KSP ksp; 63109ee8bb0SRylee Sundermann Mat Factor; 63209ee8bb0SRylee Sundermann PetscBool isCHOL; 6337f6ac294SRylee Sundermann PetscInt nneg, nzero, npos; 634aad13602SShrirang Abhyankar 635aad13602SShrirang Abhyankar PetscFunctionBegin; 636*ab76df0cSBarry Smith PetscCall(PCGetApplicationContext(pc, &tao)); 637*ab76df0cSBarry Smith pdipm = (TAO_PDIPM *)tao->data; 638*ab76df0cSBarry Smith X = pdipm->X; 639*ab76df0cSBarry Smith snes = pdipm->snes; 640*ab76df0cSBarry Smith 6417f6ac294SRylee Sundermann /* Get the inertia of Cholesky factor */ 6429566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 6439566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 6449566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCCHOLESKY, &isCHOL)); 6453ba16761SJacob Faibussowitsch if (!isCHOL) PetscFunctionReturn(PETSC_SUCCESS); 64609ee8bb0SRylee Sundermann 6479566063dSJacob Faibussowitsch PetscCall(PCFactorGetMatrix(pc, &Factor)); 6489566063dSJacob Faibussowitsch PetscCall(MatGetInertia(Factor, &nneg, &nzero, &npos)); 64909ee8bb0SRylee Sundermann 65009ee8bb0SRylee Sundermann if (npos < pdipm->Nx + pdipm->Nci) { 65109ee8bb0SRylee Sundermann pdipm->deltaw = PetscMax(pdipm->lastdeltaw / 3, 1.e-4 * PETSC_MACHINE_EPSILON); 65263a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(tao, "Test reduced deltaw=%g; previous MatInertia: nneg %" PetscInt_FMT ", nzero %" PetscInt_FMT ", npos %" PetscInt_FMT "(<%" PetscInt_FMT ")\n", (double)pdipm->deltaw, nneg, nzero, npos, pdipm->Nx + pdipm->Nci)); 6539566063dSJacob Faibussowitsch PetscCall(TaoSNESJacobian_PDIPM(snes, X, pdipm->K, pdipm->K, tao)); 654*ab76df0cSBarry Smith PetscCall(PCSetPostSetUp(pc, NULL)); 6559566063dSJacob Faibussowitsch PetscCall(PCSetUp(pc)); 6569566063dSJacob Faibussowitsch PetscCall(MatGetInertia(Factor, &nneg, &nzero, &npos)); 65709ee8bb0SRylee Sundermann 65809ee8bb0SRylee Sundermann if (npos < pdipm->Nx + pdipm->Nci) { 65909ee8bb0SRylee Sundermann pdipm->deltaw = pdipm->lastdeltaw; /* in case reduction update does not help, this prevents that step from impacting increasing update */ 660f560b561SHong Zhang while (npos < pdipm->Nx + pdipm->Nci && pdipm->deltaw <= 1. / PETSC_SMALL) { /* increase deltaw */ 66163a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(tao, " deltaw=%g fails, MatInertia: nneg %" PetscInt_FMT ", nzero %" PetscInt_FMT ", npos %" PetscInt_FMT "(<%" PetscInt_FMT ")\n", (double)pdipm->deltaw, nneg, nzero, npos, pdipm->Nx + pdipm->Nci)); 66209ee8bb0SRylee Sundermann pdipm->deltaw = PetscMin(8 * pdipm->deltaw, PetscPowReal(10, 20)); 6639566063dSJacob Faibussowitsch PetscCall(TaoSNESJacobian_PDIPM(snes, X, pdipm->K, pdipm->K, tao)); 6649566063dSJacob Faibussowitsch PetscCall(PCSetUp(pc)); 6659566063dSJacob Faibussowitsch PetscCall(MatGetInertia(Factor, &nneg, &nzero, &npos)); 66609ee8bb0SRylee Sundermann } 66709ee8bb0SRylee Sundermann 6683c859ba3SBarry Smith PetscCheck(pdipm->deltaw < 1. / PETSC_SMALL, PetscObjectComm((PetscObject)tao), PETSC_ERR_CONV_FAILED, "Reached maximum delta w will not converge, try different initial x0"); 669f560b561SHong Zhang 6709566063dSJacob Faibussowitsch PetscCall(PetscInfo(tao, "Updated deltaw %g\n", (double)pdipm->deltaw)); 67109ee8bb0SRylee Sundermann pdipm->lastdeltaw = pdipm->deltaw; 67209ee8bb0SRylee Sundermann pdipm->deltaw = 0.0; 67309ee8bb0SRylee Sundermann } 67409ee8bb0SRylee Sundermann } 67509ee8bb0SRylee Sundermann 67609ee8bb0SRylee Sundermann if (nzero) { /* Jacobian is singular */ 67709ee8bb0SRylee Sundermann if (pdipm->deltac == 0.0) { 6787f6ac294SRylee Sundermann pdipm->deltac = PETSC_SQRT_MACHINE_EPSILON; 67909ee8bb0SRylee Sundermann } else { 68009ee8bb0SRylee Sundermann pdipm->deltac = pdipm->deltac * PetscPowReal(pdipm->mu, .25); 68109ee8bb0SRylee Sundermann } 68263a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(tao, "Updated deltac=%g, MatInertia: nneg %" PetscInt_FMT ", nzero %" PetscInt_FMT "(!=0), npos %" PetscInt_FMT "\n", (double)pdipm->deltac, nneg, nzero, npos)); 6839566063dSJacob Faibussowitsch PetscCall(TaoSNESJacobian_PDIPM(snes, X, pdipm->K, pdipm->K, tao)); 684*ab76df0cSBarry Smith PetscCall(PCSetPostSetUp(pc, NULL)); 6859566063dSJacob Faibussowitsch PetscCall(PCSetUp(pc)); 6869566063dSJacob Faibussowitsch PetscCall(MatGetInertia(Factor, &nneg, &nzero, &npos)); 68709ee8bb0SRylee Sundermann } 688*ab76df0cSBarry Smith PetscCall(PCSetPostSetUp(pc, PCPostSetUp_PDIPM)); 6893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6907f6ac294SRylee Sundermann } 6917f6ac294SRylee Sundermann 6927f6ac294SRylee Sundermann /* 6937f6ac294SRylee Sundermann SNESLineSearch_PDIPM - Custom line search used with PDIPM. 6947f6ac294SRylee Sundermann 695c3339decSBarry Smith Collective 6967f6ac294SRylee Sundermann 6977f6ac294SRylee Sundermann Notes: 6987f6ac294SRylee Sundermann This routine employs a simple backtracking line-search to keep 6997f6ac294SRylee Sundermann the slack variables (z) and inequality constraints Lagrange multipliers 7007f6ac294SRylee Sundermann (lambdai) positive, i.e., z,lambdai >=0. It does this by calculating scalars 7017f6ac294SRylee Sundermann alpha_p and alpha_d to keep z,lambdai non-negative. The decision (x), and the 702f560b561SHong Zhang slack variables are updated as X = X - alpha_d*dx. The constraint multipliers 7037f6ac294SRylee Sundermann are updated as Lambdai = Lambdai + alpha_p*dLambdai. The barrier parameter mu 7047f6ac294SRylee Sundermann is also updated as mu = mu + z'lambdai/Nci 7057f6ac294SRylee Sundermann */ 706d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESLineSearch_PDIPM(SNESLineSearch linesearch, void *ctx) 707d71ae5a4SJacob Faibussowitsch { 7087f6ac294SRylee Sundermann Tao tao = (Tao)ctx; 7097f6ac294SRylee Sundermann TAO_PDIPM *pdipm = (TAO_PDIPM *)tao->data; 7107f6ac294SRylee Sundermann SNES snes; 711f560b561SHong Zhang Vec X, F, Y; 7127f6ac294SRylee Sundermann PetscInt i, iter; 7137f6ac294SRylee Sundermann PetscReal alpha_p = 1.0, alpha_d = 1.0, alpha[4]; 7147f6ac294SRylee Sundermann PetscScalar *Xarr, *z, *lambdai, dot, *taosolarr; 7157f6ac294SRylee Sundermann const PetscScalar *dXarr, *dz, *dlambdai; 7167f6ac294SRylee Sundermann 7177f6ac294SRylee Sundermann PetscFunctionBegin; 7189566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetSNES(linesearch, &snes)); 7199566063dSJacob Faibussowitsch PetscCall(SNESGetIterationNumber(snes, &iter)); 7207f6ac294SRylee Sundermann 7219566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetReason(linesearch, SNES_LINESEARCH_SUCCEEDED)); 7229566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetVecs(linesearch, &X, &F, &Y, NULL, NULL)); 7237f6ac294SRylee Sundermann 7249566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(X, &Xarr)); 7259566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(Y, &dXarr)); 7267f6ac294SRylee Sundermann z = Xarr + pdipm->off_z; 7277f6ac294SRylee Sundermann dz = dXarr + pdipm->off_z; 7287f6ac294SRylee Sundermann for (i = 0; i < pdipm->nci; i++) { 729f560b561SHong Zhang if (z[i] - dz[i] < 0.0) alpha_p = PetscMin(alpha_p, 0.9999 * z[i] / dz[i]); 7307f6ac294SRylee Sundermann } 7317f6ac294SRylee Sundermann 7327f6ac294SRylee Sundermann lambdai = Xarr + pdipm->off_lambdai; 7337f6ac294SRylee Sundermann dlambdai = dXarr + pdipm->off_lambdai; 7347f6ac294SRylee Sundermann 7357f6ac294SRylee Sundermann for (i = 0; i < pdipm->nci; i++) { 736f560b561SHong Zhang if (lambdai[i] - dlambdai[i] < 0.0) alpha_d = PetscMin(0.9999 * lambdai[i] / dlambdai[i], alpha_d); 7377f6ac294SRylee Sundermann } 7387f6ac294SRylee Sundermann 7397f6ac294SRylee Sundermann alpha[0] = alpha_p; 7407f6ac294SRylee Sundermann alpha[1] = alpha_d; 7419566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(Y, &dXarr)); 7429566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(X, &Xarr)); 7437f6ac294SRylee Sundermann 7447f6ac294SRylee Sundermann /* alpha = min(alpha) over all processes */ 745462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(alpha, alpha + 2, 2, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)tao))); 7467f6ac294SRylee Sundermann 7477f6ac294SRylee Sundermann alpha_p = alpha[2]; 7487f6ac294SRylee Sundermann alpha_d = alpha[3]; 7497f6ac294SRylee Sundermann 750f560b561SHong Zhang /* X = X - alpha * Y */ 7519566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(X, &Xarr)); 7529566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(Y, &dXarr)); 7537f6ac294SRylee Sundermann for (i = 0; i < pdipm->nx; i++) Xarr[i] -= alpha_p * dXarr[i]; 754f560b561SHong Zhang for (i = 0; i < pdipm->nce; i++) Xarr[i + pdipm->off_lambdae] -= alpha_d * dXarr[i + pdipm->off_lambdae]; 7557f6ac294SRylee Sundermann 7567f6ac294SRylee Sundermann for (i = 0; i < pdipm->nci; i++) { 7577f6ac294SRylee Sundermann Xarr[i + pdipm->off_lambdai] -= alpha_d * dXarr[i + pdipm->off_lambdai]; 7587f6ac294SRylee Sundermann Xarr[i + pdipm->off_z] -= alpha_p * dXarr[i + pdipm->off_z]; 7597f6ac294SRylee Sundermann } 7609566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(tao->solution, &taosolarr)); 7619566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(taosolarr, Xarr, pdipm->nx * sizeof(PetscScalar))); 7629566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(tao->solution, &taosolarr)); 7637f6ac294SRylee Sundermann 7649566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(X, &Xarr)); 7659566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(Y, &dXarr)); 7667f6ac294SRylee Sundermann 767f560b561SHong Zhang /* Update mu = mu_update_factor * dot(z,lambdai)/pdipm->nci at updated X */ 7687f6ac294SRylee Sundermann if (pdipm->z) { 7699566063dSJacob Faibussowitsch PetscCall(VecDot(pdipm->z, pdipm->lambdai, &dot)); 7707f6ac294SRylee Sundermann } else dot = 0.0; 7717f6ac294SRylee Sundermann 7727f6ac294SRylee Sundermann /* if (PetscAbsReal(pdipm->gradL) < 0.9*pdipm->mu) */ 7737f6ac294SRylee Sundermann pdipm->mu = pdipm->mu_update_factor * dot / pdipm->Nci; 7747f6ac294SRylee Sundermann 7757f6ac294SRylee Sundermann /* Update F; get tao->residual and tao->cnorm */ 7769566063dSJacob Faibussowitsch PetscCall(TaoSNESFunction_PDIPM_residual(snes, X, F, (void *)tao)); 7777f6ac294SRylee Sundermann 7787f6ac294SRylee Sundermann tao->niter++; 7799566063dSJacob Faibussowitsch PetscCall(TaoLogConvergenceHistory(tao, pdipm->obj, tao->residual, tao->cnorm, tao->niter)); 7809566063dSJacob Faibussowitsch PetscCall(TaoMonitor(tao, tao->niter, pdipm->obj, tao->residual, tao->cnorm, pdipm->mu)); 7817f6ac294SRylee Sundermann 782dbbe0bcdSBarry Smith PetscUseTypeMethod(tao, convergencetest, tao->cnvP); 7831baa6e33SBarry Smith if (tao->reason) PetscCall(SNESSetConvergedReason(snes, SNES_CONVERGED_FNORM_ABS)); 7843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 785aad13602SShrirang Abhyankar } 786aad13602SShrirang Abhyankar 78766976f2fSJacob Faibussowitsch static PetscErrorCode TaoSolve_PDIPM(Tao tao) 788d71ae5a4SJacob Faibussowitsch { 789aad13602SShrirang Abhyankar TAO_PDIPM *pdipm = (TAO_PDIPM *)tao->data; 790aad13602SShrirang Abhyankar SNESLineSearch linesearch; /* SNESLineSearch context */ 791aad13602SShrirang Abhyankar Vec dummy; 792aad13602SShrirang Abhyankar 793aad13602SShrirang Abhyankar PetscFunctionBegin; 7943c859ba3SBarry Smith PetscCheck(tao->constraints_equality || tao->constraints_inequality, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_NULL, "Equality and inequality constraints are not set. Either set them or switch to a different algorithm"); 7958e58fa1dSresundermann 796aad13602SShrirang Abhyankar /* Initialize all variables */ 7979566063dSJacob Faibussowitsch PetscCall(TaoPDIPMInitializeSolution(tao)); 798aad13602SShrirang Abhyankar 799aad13602SShrirang Abhyankar /* Set linesearch */ 8009566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(pdipm->snes, &linesearch)); 8019566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetType(linesearch, SNESLINESEARCHSHELL)); 8029bcc50f1SBarry Smith PetscCall(SNESLineSearchShellSetApply(linesearch, SNESLineSearch_PDIPM, tao)); 8039566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFromOptions(linesearch)); 804aad13602SShrirang Abhyankar 805aad13602SShrirang Abhyankar tao->reason = TAO_CONTINUE_ITERATING; 806aad13602SShrirang Abhyankar 807aad13602SShrirang Abhyankar /* -tao_monitor for iteration 0 and check convergence */ 8089566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pdipm->X, &dummy)); 8099566063dSJacob Faibussowitsch PetscCall(TaoSNESFunction_PDIPM_residual(pdipm->snes, pdipm->X, dummy, (void *)tao)); 810aad13602SShrirang Abhyankar 8119566063dSJacob Faibussowitsch PetscCall(TaoLogConvergenceHistory(tao, pdipm->obj, tao->residual, tao->cnorm, tao->niter)); 8129566063dSJacob Faibussowitsch PetscCall(TaoMonitor(tao, tao->niter, pdipm->obj, tao->residual, tao->cnorm, pdipm->mu)); 8139566063dSJacob Faibussowitsch PetscCall(VecDestroy(&dummy)); 814dbbe0bcdSBarry Smith PetscUseTypeMethod(tao, convergencetest, tao->cnvP); 81563a3b9bcSJacob Faibussowitsch if (tao->reason) PetscCall(SNESSetConvergedReason(pdipm->snes, SNES_CONVERGED_FNORM_ABS)); 816aad13602SShrirang Abhyankar 817aad13602SShrirang Abhyankar while (tao->reason == TAO_CONTINUE_ITERATING) { 818aad13602SShrirang Abhyankar SNESConvergedReason reason; 8199566063dSJacob Faibussowitsch PetscCall(SNESSolve(pdipm->snes, NULL, pdipm->X)); 820aad13602SShrirang Abhyankar 821aad13602SShrirang Abhyankar /* Check SNES convergence */ 8229566063dSJacob Faibussowitsch PetscCall(SNESGetConvergedReason(pdipm->snes, &reason)); 82348a46eb9SPierre Jolivet if (reason < 0) PetscCall(PetscPrintf(PetscObjectComm((PetscObject)pdipm->snes), "SNES solve did not converged due to reason %s\n", SNESConvergedReasons[reason])); 824aad13602SShrirang Abhyankar 825aad13602SShrirang Abhyankar /* Check TAO convergence */ 8263c859ba3SBarry Smith PetscCheck(!PetscIsInfOrNanReal(pdipm->obj), PETSC_COMM_SELF, PETSC_ERR_SUP, "User-provided compute function generated Inf or NaN"); 827aad13602SShrirang Abhyankar } 8283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 829aad13602SShrirang Abhyankar } 830aad13602SShrirang Abhyankar 83166976f2fSJacob Faibussowitsch static PetscErrorCode TaoView_PDIPM(Tao tao, PetscViewer viewer) 832d71ae5a4SJacob Faibussowitsch { 83370c9796eSresundermann TAO_PDIPM *pdipm = (TAO_PDIPM *)tao->data; 83470c9796eSresundermann 83570c9796eSresundermann PetscFunctionBegin; 83670c9796eSresundermann tao->constrained = PETSC_TRUE; 8379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 83863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Number of prime=%" PetscInt_FMT ", Number of dual=%" PetscInt_FMT "\n", pdipm->Nx + pdipm->Nci, pdipm->Nce + pdipm->Nci)); 83948a46eb9SPierre Jolivet if (pdipm->kkt_pd) PetscCall(PetscViewerASCIIPrintf(viewer, "KKT shifts deltaw=%g, deltac=%g\n", (double)pdipm->deltaw, (double)pdipm->deltac)); 8409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 8413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 84270c9796eSresundermann } 84370c9796eSresundermann 84466976f2fSJacob Faibussowitsch static PetscErrorCode TaoSetup_PDIPM(Tao tao) 845d71ae5a4SJacob Faibussowitsch { 846aad13602SShrirang Abhyankar TAO_PDIPM *pdipm = (TAO_PDIPM *)tao->data; 847aad13602SShrirang Abhyankar MPI_Comm comm; 848f560b561SHong Zhang PetscMPIInt size; 849aad13602SShrirang Abhyankar PetscInt row, col, Jcrstart, Jcrend, k, tmp, nc, proc, *nh_all, *ng_all; 850aad13602SShrirang Abhyankar PetscInt offset, *xa, *xb, i, j, rstart, rend; 8517f6ac294SRylee Sundermann PetscScalar one = 1.0, neg_one = -1.0; 852aad13602SShrirang Abhyankar const PetscInt *cols, *rranges, *cranges, *aj, *ranges; 8537f6ac294SRylee Sundermann const PetscScalar *aa, *Xarr; 8549a8cc538SBarry Smith Mat J; 855aad13602SShrirang Abhyankar Mat Jce_xfixed_trans, Jci_xb_trans; 856aad13602SShrirang Abhyankar PetscInt *dnz, *onz, rjstart, nx_all, *nce_all, *Jranges, cols1[2]; 857aad13602SShrirang Abhyankar 858aad13602SShrirang Abhyankar PetscFunctionBegin; 8599566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)tao, &comm)); 8609566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 861aad13602SShrirang Abhyankar 862aad13602SShrirang Abhyankar /* (1) Setup Bounds and create Tao vectors */ 8639566063dSJacob Faibussowitsch PetscCall(TaoPDIPMSetUpBounds(tao)); 864aad13602SShrirang Abhyankar 865aad13602SShrirang Abhyankar if (!tao->gradient) { 8669566063dSJacob Faibussowitsch PetscCall(VecDuplicate(tao->solution, &tao->gradient)); 8679566063dSJacob Faibussowitsch PetscCall(VecDuplicate(tao->solution, &tao->stepdirection)); 868aad13602SShrirang Abhyankar } 869aad13602SShrirang Abhyankar 870aad13602SShrirang Abhyankar /* (2) Get sizes */ 871a82e8c82SStefano Zampini /* Size of vector x - This is set by TaoSetSolution */ 8729566063dSJacob Faibussowitsch PetscCall(VecGetSize(tao->solution, &pdipm->Nx)); 8739566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(tao->solution, &pdipm->nx)); 874aad13602SShrirang Abhyankar 875aad13602SShrirang Abhyankar /* Size of equality constraints and vectors */ 876aad13602SShrirang Abhyankar if (tao->constraints_equality) { 8779566063dSJacob Faibussowitsch PetscCall(VecGetSize(tao->constraints_equality, &pdipm->Ng)); 8789566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(tao->constraints_equality, &pdipm->ng)); 879aad13602SShrirang Abhyankar } else { 880aad13602SShrirang Abhyankar pdipm->ng = pdipm->Ng = 0; 881aad13602SShrirang Abhyankar } 882aad13602SShrirang Abhyankar 883aad13602SShrirang Abhyankar pdipm->nce = pdipm->ng + pdipm->nxfixed; 884aad13602SShrirang Abhyankar pdipm->Nce = pdipm->Ng + pdipm->Nxfixed; 885aad13602SShrirang Abhyankar 886aad13602SShrirang Abhyankar /* Size of inequality constraints and vectors */ 887aad13602SShrirang Abhyankar if (tao->constraints_inequality) { 8889566063dSJacob Faibussowitsch PetscCall(VecGetSize(tao->constraints_inequality, &pdipm->Nh)); 8899566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(tao->constraints_inequality, &pdipm->nh)); 890aad13602SShrirang Abhyankar } else { 891aad13602SShrirang Abhyankar pdipm->nh = pdipm->Nh = 0; 892aad13602SShrirang Abhyankar } 893aad13602SShrirang Abhyankar 894aad13602SShrirang Abhyankar pdipm->nci = pdipm->nh + pdipm->nxlb + pdipm->nxub + 2 * pdipm->nxbox; 895aad13602SShrirang Abhyankar pdipm->Nci = pdipm->Nh + pdipm->Nxlb + pdipm->Nxub + 2 * pdipm->Nxbox; 896aad13602SShrirang Abhyankar 897aad13602SShrirang Abhyankar /* Full size of the KKT system to be solved */ 898aad13602SShrirang Abhyankar pdipm->n = pdipm->nx + pdipm->nce + 2 * pdipm->nci; 899aad13602SShrirang Abhyankar pdipm->N = pdipm->Nx + pdipm->Nce + 2 * pdipm->Nci; 900aad13602SShrirang Abhyankar 901aad13602SShrirang Abhyankar /* (3) Offsets for subvectors */ 902aad13602SShrirang Abhyankar pdipm->off_lambdae = pdipm->nx; 903aad13602SShrirang Abhyankar pdipm->off_lambdai = pdipm->off_lambdae + pdipm->nce; 904aad13602SShrirang Abhyankar pdipm->off_z = pdipm->off_lambdai + pdipm->nci; 905aad13602SShrirang Abhyankar 906aad13602SShrirang Abhyankar /* (4) Create vectors and subvectors */ 907aad13602SShrirang Abhyankar /* Ce and Ci vectors */ 9089566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, &pdipm->ce)); 9099566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pdipm->ce, pdipm->nce, pdipm->Nce)); 9109566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(pdipm->ce)); 911aad13602SShrirang Abhyankar 9129566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, &pdipm->ci)); 9139566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pdipm->ci, pdipm->nci, pdipm->Nci)); 9149566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(pdipm->ci)); 915aad13602SShrirang Abhyankar 916aad13602SShrirang Abhyankar /* X=[x; lambdae; lambdai; z] for the big KKT system */ 9179566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, &pdipm->X)); 9189566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pdipm->X, pdipm->n, pdipm->N)); 9199566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(pdipm->X)); 920aad13602SShrirang Abhyankar 921aad13602SShrirang Abhyankar /* Subvectors; they share local arrays with X */ 9229566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pdipm->X, &Xarr)); 923aad13602SShrirang Abhyankar /* x shares local array with X.x */ 92448a46eb9SPierre Jolivet if (pdipm->Nx) PetscCall(VecCreateMPIWithArray(comm, 1, pdipm->nx, pdipm->Nx, Xarr, &pdipm->x)); 925aad13602SShrirang Abhyankar 926aad13602SShrirang Abhyankar /* lambdae shares local array with X.lambdae */ 92748a46eb9SPierre Jolivet if (pdipm->Nce) PetscCall(VecCreateMPIWithArray(comm, 1, pdipm->nce, pdipm->Nce, Xarr + pdipm->off_lambdae, &pdipm->lambdae)); 928aad13602SShrirang Abhyankar 929aad13602SShrirang Abhyankar /* tao->DE shares local array with X.lambdae_g */ 930aad13602SShrirang Abhyankar if (pdipm->Ng) { 9319566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(comm, 1, pdipm->ng, pdipm->Ng, Xarr + pdipm->off_lambdae, &tao->DE)); 932aad13602SShrirang Abhyankar 9339566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, &pdipm->lambdae_xfixed)); 9349566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pdipm->lambdae_xfixed, pdipm->nxfixed, PETSC_DECIDE)); 9359566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(pdipm->lambdae_xfixed)); 936aad13602SShrirang Abhyankar } 937aad13602SShrirang Abhyankar 938aad13602SShrirang Abhyankar if (pdipm->Nci) { 939aad13602SShrirang Abhyankar /* lambdai shares local array with X.lambdai */ 9409566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(comm, 1, pdipm->nci, pdipm->Nci, Xarr + pdipm->off_lambdai, &pdipm->lambdai)); 941aad13602SShrirang Abhyankar 942aad13602SShrirang Abhyankar /* z for slack variables; it shares local array with X.z */ 9439566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(comm, 1, pdipm->nci, pdipm->Nci, Xarr + pdipm->off_z, &pdipm->z)); 944aad13602SShrirang Abhyankar } 945aad13602SShrirang Abhyankar 946aad13602SShrirang Abhyankar /* tao->DI which shares local array with X.lambdai_h */ 94748a46eb9SPierre Jolivet if (pdipm->Nh) PetscCall(VecCreateMPIWithArray(comm, 1, pdipm->nh, pdipm->Nh, Xarr + pdipm->off_lambdai, &tao->DI)); 9489566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, &pdipm->lambdai_xb)); 94957508eceSPierre Jolivet PetscCall(VecSetSizes(pdipm->lambdai_xb, pdipm->nci - pdipm->nh, PETSC_DECIDE)); 9509566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(pdipm->lambdai_xb)); 951aad13602SShrirang Abhyankar 9529566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pdipm->X, &Xarr)); 953aad13602SShrirang Abhyankar 954aad13602SShrirang Abhyankar /* (5) Create Jacobians Jce_xfixed and Jci */ 955aad13602SShrirang Abhyankar /* (5.1) PDIPM Jacobian of equality bounds cebound(x) = J_nxfixed */ 956aad13602SShrirang Abhyankar if (pdipm->Nxfixed) { 957aad13602SShrirang Abhyankar /* Create Jce_xfixed */ 9589566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &pdipm->Jce_xfixed)); 9599566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pdipm->Jce_xfixed, pdipm->nxfixed, pdipm->nx, PETSC_DECIDE, pdipm->Nx)); 9609566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(pdipm->Jce_xfixed)); 9619566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pdipm->Jce_xfixed, 1, NULL)); 9629566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(pdipm->Jce_xfixed, 1, NULL, 1, NULL)); 963aad13602SShrirang Abhyankar 9649566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(pdipm->Jce_xfixed, &Jcrstart, &Jcrend)); 9659566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pdipm->isxfixed, &cols)); 966aad13602SShrirang Abhyankar k = 0; 967aad13602SShrirang Abhyankar for (row = Jcrstart; row < Jcrend; row++) { 9689566063dSJacob Faibussowitsch PetscCall(MatSetValues(pdipm->Jce_xfixed, 1, &row, 1, cols + k, &one, INSERT_VALUES)); 969aad13602SShrirang Abhyankar k++; 970aad13602SShrirang Abhyankar } 9719566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pdipm->isxfixed, &cols)); 9729566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pdipm->Jce_xfixed, MAT_FINAL_ASSEMBLY)); 9739566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pdipm->Jce_xfixed, MAT_FINAL_ASSEMBLY)); 974aad13602SShrirang Abhyankar } 975aad13602SShrirang Abhyankar 976aad13602SShrirang Abhyankar /* (5.2) PDIPM inequality Jacobian Jci = [tao->jacobian_inequality; ...] */ 9779566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &pdipm->Jci_xb)); 9789566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pdipm->Jci_xb, pdipm->nci - pdipm->nh, pdipm->nx, PETSC_DECIDE, pdipm->Nx)); 9799566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(pdipm->Jci_xb)); 9809566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pdipm->Jci_xb, 1, NULL)); 9819566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(pdipm->Jci_xb, 1, NULL, 1, NULL)); 982aad13602SShrirang Abhyankar 9839566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(pdipm->Jci_xb, &Jcrstart, &Jcrend)); 984aad13602SShrirang Abhyankar offset = Jcrstart; 985aad13602SShrirang Abhyankar if (pdipm->Nxub) { 986aad13602SShrirang Abhyankar /* Add xub to Jci_xb */ 9879566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pdipm->isxub, &cols)); 988aad13602SShrirang Abhyankar k = 0; 989aad13602SShrirang Abhyankar for (row = offset; row < offset + pdipm->nxub; row++) { 9909566063dSJacob Faibussowitsch PetscCall(MatSetValues(pdipm->Jci_xb, 1, &row, 1, cols + k, &neg_one, INSERT_VALUES)); 991aad13602SShrirang Abhyankar k++; 992aad13602SShrirang Abhyankar } 9939566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pdipm->isxub, &cols)); 994aad13602SShrirang Abhyankar } 995aad13602SShrirang Abhyankar 996aad13602SShrirang Abhyankar if (pdipm->Nxlb) { 997aad13602SShrirang Abhyankar /* Add xlb to Jci_xb */ 9989566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pdipm->isxlb, &cols)); 999aad13602SShrirang Abhyankar k = 0; 1000aad13602SShrirang Abhyankar offset += pdipm->nxub; 1001aad13602SShrirang Abhyankar for (row = offset; row < offset + pdipm->nxlb; row++) { 10029566063dSJacob Faibussowitsch PetscCall(MatSetValues(pdipm->Jci_xb, 1, &row, 1, cols + k, &one, INSERT_VALUES)); 1003aad13602SShrirang Abhyankar k++; 1004aad13602SShrirang Abhyankar } 10059566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pdipm->isxlb, &cols)); 1006aad13602SShrirang Abhyankar } 1007aad13602SShrirang Abhyankar 1008aad13602SShrirang Abhyankar /* Add xbox to Jci_xb */ 1009aad13602SShrirang Abhyankar if (pdipm->Nxbox) { 10109566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pdipm->isxbox, &cols)); 1011aad13602SShrirang Abhyankar k = 0; 1012aad13602SShrirang Abhyankar offset += pdipm->nxlb; 1013aad13602SShrirang Abhyankar for (row = offset; row < offset + pdipm->nxbox; row++) { 10149566063dSJacob Faibussowitsch PetscCall(MatSetValues(pdipm->Jci_xb, 1, &row, 1, cols + k, &neg_one, INSERT_VALUES)); 1015aad13602SShrirang Abhyankar tmp = row + pdipm->nxbox; 10169566063dSJacob Faibussowitsch PetscCall(MatSetValues(pdipm->Jci_xb, 1, &tmp, 1, cols + k, &one, INSERT_VALUES)); 1017aad13602SShrirang Abhyankar k++; 1018aad13602SShrirang Abhyankar } 10199566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pdipm->isxbox, &cols)); 1020aad13602SShrirang Abhyankar } 1021aad13602SShrirang Abhyankar 10229566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pdipm->Jci_xb, MAT_FINAL_ASSEMBLY)); 10239566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pdipm->Jci_xb, MAT_FINAL_ASSEMBLY)); 10249566063dSJacob Faibussowitsch /* PetscCall(MatView(pdipm->Jci_xb,PETSC_VIEWER_STDOUT_WORLD)); */ 1025aad13602SShrirang Abhyankar 1026aad13602SShrirang Abhyankar /* (6) Set up ISs for PC Fieldsplit */ 1027aad13602SShrirang Abhyankar if (pdipm->solve_reduced_kkt) { 10289566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pdipm->nx + pdipm->nce, &xa, 2 * pdipm->nci, &xb)); 1029aad13602SShrirang Abhyankar for (i = 0; i < pdipm->nx + pdipm->nce; i++) xa[i] = i; 1030aad13602SShrirang Abhyankar for (i = 0; i < 2 * pdipm->nci; i++) xb[i] = pdipm->off_lambdai + i; 1031aad13602SShrirang Abhyankar 10329566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, pdipm->nx + pdipm->nce, xa, PETSC_OWN_POINTER, &pdipm->is1)); 10339566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, 2 * pdipm->nci, xb, PETSC_OWN_POINTER, &pdipm->is2)); 1034aad13602SShrirang Abhyankar } 1035aad13602SShrirang Abhyankar 1036aad13602SShrirang Abhyankar /* (7) Gather offsets from all processes */ 10379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &pdipm->nce_all)); 1038aad13602SShrirang Abhyankar 1039aad13602SShrirang Abhyankar /* Get rstart of KKT matrix */ 10409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scan(&pdipm->n, &rstart, 1, MPIU_INT, MPI_SUM, comm)); 1041aad13602SShrirang Abhyankar rstart -= pdipm->n; 1042aad13602SShrirang Abhyankar 10439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(&pdipm->nce, 1, MPIU_INT, pdipm->nce_all, 1, MPIU_INT, comm)); 1044aad13602SShrirang Abhyankar 10459566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(size, &ng_all, size, &nh_all, size, &Jranges)); 10469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(&rstart, 1, MPIU_INT, Jranges, 1, MPIU_INT, comm)); 10479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(&pdipm->nh, 1, MPIU_INT, nh_all, 1, MPIU_INT, comm)); 10489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(&pdipm->ng, 1, MPIU_INT, ng_all, 1, MPIU_INT, comm)); 1049aad13602SShrirang Abhyankar 10509566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRanges(tao->hessian, &rranges)); 10519566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangesColumn(tao->hessian, &cranges)); 1052aad13602SShrirang Abhyankar 1053aad13602SShrirang Abhyankar if (pdipm->Ng) { 10549566063dSJacob Faibussowitsch PetscCall(TaoComputeJacobianEquality(tao, tao->solution, tao->jacobian_equality, tao->jacobian_equality_pre)); 10559566063dSJacob Faibussowitsch PetscCall(MatTranspose(tao->jacobian_equality, MAT_INITIAL_MATRIX, &pdipm->jac_equality_trans)); 1056aad13602SShrirang Abhyankar } 1057aad13602SShrirang Abhyankar if (pdipm->Nh) { 10589566063dSJacob Faibussowitsch PetscCall(TaoComputeJacobianInequality(tao, tao->solution, tao->jacobian_inequality, tao->jacobian_inequality_pre)); 10599566063dSJacob Faibussowitsch PetscCall(MatTranspose(tao->jacobian_inequality, MAT_INITIAL_MATRIX, &pdipm->jac_inequality_trans)); 1060aad13602SShrirang Abhyankar } 1061aad13602SShrirang Abhyankar 1062aad13602SShrirang Abhyankar /* Count dnz,onz for preallocation of KKT matrix */ 1063aad13602SShrirang Abhyankar nce_all = pdipm->nce_all; 1064aad13602SShrirang Abhyankar 106548a46eb9SPierre Jolivet if (pdipm->Nxfixed) PetscCall(MatTranspose(pdipm->Jce_xfixed, MAT_INITIAL_MATRIX, &Jce_xfixed_trans)); 10669566063dSJacob Faibussowitsch PetscCall(MatTranspose(pdipm->Jci_xb, MAT_INITIAL_MATRIX, &Jci_xb_trans)); 1067aad13602SShrirang Abhyankar 1068d0609cedSBarry Smith MatPreallocateBegin(comm, pdipm->n, pdipm->n, dnz, onz); 1069aad13602SShrirang Abhyankar 1070aad13602SShrirang Abhyankar /* 1st row block of KKT matrix: [Wxx; gradCe'; -gradCi'; 0] */ 10719566063dSJacob Faibussowitsch PetscCall(TaoPDIPMEvaluateFunctionsAndJacobians(tao, pdipm->x)); 10729566063dSJacob Faibussowitsch PetscCall(TaoComputeHessian(tao, tao->solution, tao->hessian, tao->hessian_pre)); 1073aad13602SShrirang Abhyankar 1074aad13602SShrirang Abhyankar /* Insert tao->hessian */ 10759566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(tao->hessian, &rjstart, NULL)); 1076aad13602SShrirang Abhyankar for (i = 0; i < pdipm->nx; i++) { 1077aad13602SShrirang Abhyankar row = rstart + i; 1078aad13602SShrirang Abhyankar 10799566063dSJacob Faibussowitsch PetscCall(MatGetRow(tao->hessian, i + rjstart, &nc, &aj, NULL)); 1080aad13602SShrirang Abhyankar proc = 0; 1081aad13602SShrirang Abhyankar for (j = 0; j < nc; j++) { 1082aad13602SShrirang Abhyankar while (aj[j] >= cranges[proc + 1]) proc++; 1083aad13602SShrirang Abhyankar col = aj[j] - cranges[proc] + Jranges[proc]; 10849566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row, 1, &col, dnz, onz)); 1085aad13602SShrirang Abhyankar } 10869566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(tao->hessian, i + rjstart, &nc, &aj, NULL)); 1087aad13602SShrirang Abhyankar 1088aad13602SShrirang Abhyankar if (pdipm->ng) { 1089aad13602SShrirang Abhyankar /* Insert grad g' */ 10909a8cc538SBarry Smith PetscCall(MatGetRow(pdipm->jac_equality_trans, i + rjstart, &nc, &aj, NULL)); 10919566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRanges(tao->jacobian_equality, &ranges)); 1092aad13602SShrirang Abhyankar proc = 0; 1093aad13602SShrirang Abhyankar for (j = 0; j < nc; j++) { 1094aad13602SShrirang Abhyankar /* find row ownership of */ 1095aad13602SShrirang Abhyankar while (aj[j] >= ranges[proc + 1]) proc++; 1096aad13602SShrirang Abhyankar nx_all = rranges[proc + 1] - rranges[proc]; 1097aad13602SShrirang Abhyankar col = aj[j] - ranges[proc] + Jranges[proc] + nx_all; 10989566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row, 1, &col, dnz, onz)); 1099aad13602SShrirang Abhyankar } 11009a8cc538SBarry Smith PetscCall(MatRestoreRow(pdipm->jac_equality_trans, i + rjstart, &nc, &aj, NULL)); 1101aad13602SShrirang Abhyankar } 1102aad13602SShrirang Abhyankar 1103aad13602SShrirang Abhyankar /* Insert Jce_xfixed^T' */ 1104aad13602SShrirang Abhyankar if (pdipm->nxfixed) { 11059566063dSJacob Faibussowitsch PetscCall(MatGetRow(Jce_xfixed_trans, i + rjstart, &nc, &aj, NULL)); 11069566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRanges(pdipm->Jce_xfixed, &ranges)); 1107aad13602SShrirang Abhyankar proc = 0; 1108aad13602SShrirang Abhyankar for (j = 0; j < nc; j++) { 1109aad13602SShrirang Abhyankar /* find row ownership of */ 1110aad13602SShrirang Abhyankar while (aj[j] >= ranges[proc + 1]) proc++; 1111aad13602SShrirang Abhyankar nx_all = rranges[proc + 1] - rranges[proc]; 1112aad13602SShrirang Abhyankar col = aj[j] - ranges[proc] + Jranges[proc] + nx_all + ng_all[proc]; 11139566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row, 1, &col, dnz, onz)); 1114aad13602SShrirang Abhyankar } 11159566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(Jce_xfixed_trans, i + rjstart, &nc, &aj, NULL)); 1116aad13602SShrirang Abhyankar } 1117aad13602SShrirang Abhyankar 1118aad13602SShrirang Abhyankar if (pdipm->nh) { 1119aad13602SShrirang Abhyankar /* Insert -grad h' */ 11209a8cc538SBarry Smith PetscCall(MatGetRow(pdipm->jac_inequality_trans, i + rjstart, &nc, &aj, NULL)); 11219566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRanges(tao->jacobian_inequality, &ranges)); 1122aad13602SShrirang Abhyankar proc = 0; 1123aad13602SShrirang Abhyankar for (j = 0; j < nc; j++) { 1124aad13602SShrirang Abhyankar /* find row ownership of */ 1125aad13602SShrirang Abhyankar while (aj[j] >= ranges[proc + 1]) proc++; 1126aad13602SShrirang Abhyankar nx_all = rranges[proc + 1] - rranges[proc]; 1127aad13602SShrirang Abhyankar col = aj[j] - ranges[proc] + Jranges[proc] + nx_all + nce_all[proc]; 11289566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row, 1, &col, dnz, onz)); 1129aad13602SShrirang Abhyankar } 11309a8cc538SBarry Smith PetscCall(MatRestoreRow(pdipm->jac_inequality_trans, i + rjstart, &nc, &aj, NULL)); 1131aad13602SShrirang Abhyankar } 1132aad13602SShrirang Abhyankar 1133aad13602SShrirang Abhyankar /* Insert Jci_xb^T' */ 11349566063dSJacob Faibussowitsch PetscCall(MatGetRow(Jci_xb_trans, i + rjstart, &nc, &aj, NULL)); 11359566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRanges(pdipm->Jci_xb, &ranges)); 1136aad13602SShrirang Abhyankar proc = 0; 1137aad13602SShrirang Abhyankar for (j = 0; j < nc; j++) { 1138aad13602SShrirang Abhyankar /* find row ownership of */ 1139aad13602SShrirang Abhyankar while (aj[j] >= ranges[proc + 1]) proc++; 1140aad13602SShrirang Abhyankar nx_all = rranges[proc + 1] - rranges[proc]; 1141aad13602SShrirang Abhyankar col = aj[j] - ranges[proc] + Jranges[proc] + nx_all + nce_all[proc] + nh_all[proc]; 11429566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row, 1, &col, dnz, onz)); 1143aad13602SShrirang Abhyankar } 11449566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(Jci_xb_trans, i + rjstart, &nc, &aj, NULL)); 1145aad13602SShrirang Abhyankar } 1146aad13602SShrirang Abhyankar 114709ee8bb0SRylee Sundermann /* 2nd Row block of KKT matrix: [grad Ce, deltac*I, 0, 0] */ 1148aad13602SShrirang Abhyankar if (pdipm->Ng) { 11499566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(tao->jacobian_equality, &rjstart, NULL)); 1150aad13602SShrirang Abhyankar for (i = 0; i < pdipm->ng; i++) { 1151aad13602SShrirang Abhyankar row = rstart + pdipm->off_lambdae + i; 1152aad13602SShrirang Abhyankar 11539566063dSJacob Faibussowitsch PetscCall(MatGetRow(tao->jacobian_equality, i + rjstart, &nc, &aj, NULL)); 1154aad13602SShrirang Abhyankar proc = 0; 1155aad13602SShrirang Abhyankar for (j = 0; j < nc; j++) { 1156aad13602SShrirang Abhyankar while (aj[j] >= cranges[proc + 1]) proc++; 1157aad13602SShrirang Abhyankar col = aj[j] - cranges[proc] + Jranges[proc]; 11589566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row, 1, &col, dnz, onz)); /* grad g */ 1159aad13602SShrirang Abhyankar } 11609566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(tao->jacobian_equality, i + rjstart, &nc, &aj, NULL)); 1161aad13602SShrirang Abhyankar } 1162aad13602SShrirang Abhyankar } 1163aad13602SShrirang Abhyankar /* Jce_xfixed */ 1164aad13602SShrirang Abhyankar if (pdipm->Nxfixed) { 11659566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(pdipm->Jce_xfixed, &Jcrstart, NULL)); 1166aad13602SShrirang Abhyankar for (i = 0; i < (pdipm->nce - pdipm->ng); i++) { 1167aad13602SShrirang Abhyankar row = rstart + pdipm->off_lambdae + pdipm->ng + i; 1168aad13602SShrirang Abhyankar 11699566063dSJacob Faibussowitsch PetscCall(MatGetRow(pdipm->Jce_xfixed, i + Jcrstart, &nc, &cols, NULL)); 11703c859ba3SBarry Smith PetscCheck(nc == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "nc != 1"); 1171aad13602SShrirang Abhyankar 1172aad13602SShrirang Abhyankar proc = 0; 1173aad13602SShrirang Abhyankar j = 0; 1174aad13602SShrirang Abhyankar while (cols[j] >= cranges[proc + 1]) proc++; 1175aad13602SShrirang Abhyankar col = cols[j] - cranges[proc] + Jranges[proc]; 11769566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row, 1, &col, dnz, onz)); 11779566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(pdipm->Jce_xfixed, i + Jcrstart, &nc, &cols, NULL)); 1178aad13602SShrirang Abhyankar } 1179aad13602SShrirang Abhyankar } 1180aad13602SShrirang Abhyankar 118109ee8bb0SRylee Sundermann /* 3rd Row block of KKT matrix: [ gradCi, 0, deltac*I, -I] */ 1182aad13602SShrirang Abhyankar if (pdipm->Nh) { 11839566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(tao->jacobian_inequality, &rjstart, NULL)); 1184aad13602SShrirang Abhyankar for (i = 0; i < pdipm->nh; i++) { 1185aad13602SShrirang Abhyankar row = rstart + pdipm->off_lambdai + i; 1186aad13602SShrirang Abhyankar 11879566063dSJacob Faibussowitsch PetscCall(MatGetRow(tao->jacobian_inequality, i + rjstart, &nc, &aj, NULL)); 1188aad13602SShrirang Abhyankar proc = 0; 1189aad13602SShrirang Abhyankar for (j = 0; j < nc; j++) { 1190aad13602SShrirang Abhyankar while (aj[j] >= cranges[proc + 1]) proc++; 1191aad13602SShrirang Abhyankar col = aj[j] - cranges[proc] + Jranges[proc]; 11929566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row, 1, &col, dnz, onz)); /* grad h */ 1193aad13602SShrirang Abhyankar } 11949566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(tao->jacobian_inequality, i + rjstart, &nc, &aj, NULL)); 1195aad13602SShrirang Abhyankar } 119612d688e0SRylee Sundermann /* I */ 1197aad13602SShrirang Abhyankar for (i = 0; i < pdipm->nh; i++) { 1198aad13602SShrirang Abhyankar row = rstart + pdipm->off_lambdai + i; 1199aad13602SShrirang Abhyankar col = rstart + pdipm->off_z + i; 12009566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row, 1, &col, dnz, onz)); 1201aad13602SShrirang Abhyankar } 1202aad13602SShrirang Abhyankar } 1203aad13602SShrirang Abhyankar 1204aad13602SShrirang Abhyankar /* Jci_xb */ 12059566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(pdipm->Jci_xb, &Jcrstart, NULL)); 1206aad13602SShrirang Abhyankar for (i = 0; i < (pdipm->nci - pdipm->nh); i++) { 1207aad13602SShrirang Abhyankar row = rstart + pdipm->off_lambdai + pdipm->nh + i; 1208aad13602SShrirang Abhyankar 12099566063dSJacob Faibussowitsch PetscCall(MatGetRow(pdipm->Jci_xb, i + Jcrstart, &nc, &cols, NULL)); 12103c859ba3SBarry Smith PetscCheck(nc == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "nc != 1"); 1211aad13602SShrirang Abhyankar proc = 0; 1212aad13602SShrirang Abhyankar for (j = 0; j < nc; j++) { 1213aad13602SShrirang Abhyankar while (cols[j] >= cranges[proc + 1]) proc++; 1214aad13602SShrirang Abhyankar col = cols[j] - cranges[proc] + Jranges[proc]; 12159566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row, 1, &col, dnz, onz)); 1216aad13602SShrirang Abhyankar } 12179566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(pdipm->Jci_xb, i + Jcrstart, &nc, &cols, NULL)); 121812d688e0SRylee Sundermann /* I */ 1219aad13602SShrirang Abhyankar col = rstart + pdipm->off_z + pdipm->nh + i; 12209566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row, 1, &col, dnz, onz)); 1221aad13602SShrirang Abhyankar } 1222aad13602SShrirang Abhyankar 1223aad13602SShrirang Abhyankar /* 4-th Row block of KKT matrix: Z and Ci */ 1224aad13602SShrirang Abhyankar for (i = 0; i < pdipm->nci; i++) { 1225aad13602SShrirang Abhyankar row = rstart + pdipm->off_z + i; 1226aad13602SShrirang Abhyankar cols1[0] = rstart + pdipm->off_lambdai + i; 1227aad13602SShrirang Abhyankar cols1[1] = row; 12289566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row, 2, cols1, dnz, onz)); 1229aad13602SShrirang Abhyankar } 1230aad13602SShrirang Abhyankar 1231aad13602SShrirang Abhyankar /* diagonal entry */ 1232aad13602SShrirang Abhyankar for (i = 0; i < pdipm->n; i++) dnz[i]++; /* diagonal entry */ 1233aad13602SShrirang Abhyankar 1234aad13602SShrirang Abhyankar /* Create KKT matrix */ 12359566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &J)); 12369566063dSJacob Faibussowitsch PetscCall(MatSetSizes(J, pdipm->n, pdipm->n, PETSC_DECIDE, PETSC_DECIDE)); 12379566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 12389566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(J, 0, dnz)); 12399566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(J, 0, dnz, 0, onz)); 1240d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 1241aad13602SShrirang Abhyankar pdipm->K = J; 1242aad13602SShrirang Abhyankar 1243f560b561SHong Zhang /* (8) Insert constant entries to K */ 1244aad13602SShrirang Abhyankar /* Set 0.0 to diagonal of K, so that the solver does not complain *about missing diagonal value */ 12459566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(J, &rstart, &rend)); 124648a46eb9SPierre Jolivet for (i = rstart; i < rend; i++) PetscCall(MatSetValue(J, i, i, 0.0, INSERT_VALUES)); 124709ee8bb0SRylee Sundermann /* In case Wxx has no diagonal entries preset set diagonal to deltaw given */ 124809ee8bb0SRylee Sundermann if (pdipm->kkt_pd) { 124909ee8bb0SRylee Sundermann for (i = 0; i < pdipm->nh; i++) { 125009ee8bb0SRylee Sundermann row = rstart + i; 12519566063dSJacob Faibussowitsch PetscCall(MatSetValue(J, row, row, pdipm->deltaw, INSERT_VALUES)); 125209ee8bb0SRylee Sundermann } 125309ee8bb0SRylee Sundermann } 1254aad13602SShrirang Abhyankar 1255aad13602SShrirang Abhyankar /* Row block of K: [ grad Ce, 0, 0, 0] */ 1256aad13602SShrirang Abhyankar if (pdipm->Nxfixed) { 12579566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(pdipm->Jce_xfixed, &Jcrstart, NULL)); 1258aad13602SShrirang Abhyankar for (i = 0; i < (pdipm->nce - pdipm->ng); i++) { 1259aad13602SShrirang Abhyankar row = rstart + pdipm->off_lambdae + pdipm->ng + i; 1260aad13602SShrirang Abhyankar 12619566063dSJacob Faibussowitsch PetscCall(MatGetRow(pdipm->Jce_xfixed, i + Jcrstart, &nc, &cols, &aa)); 1262aad13602SShrirang Abhyankar proc = 0; 1263aad13602SShrirang Abhyankar for (j = 0; j < nc; j++) { 1264aad13602SShrirang Abhyankar while (cols[j] >= cranges[proc + 1]) proc++; 1265aad13602SShrirang Abhyankar col = cols[j] - cranges[proc] + Jranges[proc]; 12669566063dSJacob Faibussowitsch PetscCall(MatSetValue(J, row, col, aa[j], INSERT_VALUES)); /* grad Ce */ 12679566063dSJacob Faibussowitsch PetscCall(MatSetValue(J, col, row, aa[j], INSERT_VALUES)); /* grad Ce' */ 1268aad13602SShrirang Abhyankar } 12699566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(pdipm->Jce_xfixed, i + Jcrstart, &nc, &cols, &aa)); 1270aad13602SShrirang Abhyankar } 1271aad13602SShrirang Abhyankar } 1272aad13602SShrirang Abhyankar 127312d688e0SRylee Sundermann /* Row block of K: [ -grad Ci, 0, 0, I] */ 12749566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(pdipm->Jci_xb, &Jcrstart, NULL)); 12752da392ccSBarry Smith for (i = 0; i < pdipm->nci - pdipm->nh; i++) { 1276aad13602SShrirang Abhyankar row = rstart + pdipm->off_lambdai + pdipm->nh + i; 1277aad13602SShrirang Abhyankar 12789566063dSJacob Faibussowitsch PetscCall(MatGetRow(pdipm->Jci_xb, i + Jcrstart, &nc, &cols, &aa)); 1279aad13602SShrirang Abhyankar proc = 0; 1280aad13602SShrirang Abhyankar for (j = 0; j < nc; j++) { 1281aad13602SShrirang Abhyankar while (cols[j] >= cranges[proc + 1]) proc++; 1282aad13602SShrirang Abhyankar col = cols[j] - cranges[proc] + Jranges[proc]; 12839566063dSJacob Faibussowitsch PetscCall(MatSetValue(J, col, row, -aa[j], INSERT_VALUES)); 12849566063dSJacob Faibussowitsch PetscCall(MatSetValue(J, row, col, -aa[j], INSERT_VALUES)); 1285aad13602SShrirang Abhyankar } 12869566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(pdipm->Jci_xb, i + Jcrstart, &nc, &cols, &aa)); 1287aad13602SShrirang Abhyankar 1288aad13602SShrirang Abhyankar col = rstart + pdipm->off_z + pdipm->nh + i; 12899566063dSJacob Faibussowitsch PetscCall(MatSetValue(J, row, col, 1, INSERT_VALUES)); 1290aad13602SShrirang Abhyankar } 1291aad13602SShrirang Abhyankar 1292aad13602SShrirang Abhyankar for (i = 0; i < pdipm->nh; i++) { 1293aad13602SShrirang Abhyankar row = rstart + pdipm->off_lambdai + i; 1294aad13602SShrirang Abhyankar col = rstart + pdipm->off_z + i; 12959566063dSJacob Faibussowitsch PetscCall(MatSetValue(J, row, col, 1, INSERT_VALUES)); 129612d688e0SRylee Sundermann } 129712d688e0SRylee Sundermann 129812d688e0SRylee Sundermann /* Row block of K: [ 0, 0, I, ...] */ 129912d688e0SRylee Sundermann for (i = 0; i < pdipm->nci; i++) { 130012d688e0SRylee Sundermann row = rstart + pdipm->off_z + i; 130112d688e0SRylee Sundermann col = rstart + pdipm->off_lambdai + i; 13029566063dSJacob Faibussowitsch PetscCall(MatSetValue(J, row, col, 1, INSERT_VALUES)); 1303aad13602SShrirang Abhyankar } 1304aad13602SShrirang Abhyankar 130548a46eb9SPierre Jolivet if (pdipm->Nxfixed) PetscCall(MatDestroy(&Jce_xfixed_trans)); 13069566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Jci_xb_trans)); 13079566063dSJacob Faibussowitsch PetscCall(PetscFree3(ng_all, nh_all, Jranges)); 13087f6ac294SRylee Sundermann 1309f560b561SHong Zhang /* (9) Set up nonlinear solver SNES */ 13109566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(pdipm->snes, NULL, TaoSNESFunction_PDIPM, (void *)tao)); 13119566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(pdipm->snes, J, J, TaoSNESJacobian_PDIPM, (void *)tao)); 1312f560b561SHong Zhang 1313f560b561SHong Zhang if (pdipm->solve_reduced_kkt) { 1314f560b561SHong Zhang PC pc; 13159566063dSJacob Faibussowitsch PetscCall(KSPGetPC(tao->ksp, &pc)); 13169566063dSJacob Faibussowitsch PetscCall(PCSetType(pc, PCFIELDSPLIT)); 13179566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetType(pc, PC_COMPOSITE_SCHUR)); 13189566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetIS(pc, "2", pdipm->is2)); 13199566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetIS(pc, "1", pdipm->is1)); 1320f560b561SHong Zhang } 13219566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(pdipm->snes)); 1322f560b561SHong Zhang 1323*ab76df0cSBarry Smith /* (10) Setup PCPostSetUp() for pdipm->solve_symmetric_kkt */ 13247f6ac294SRylee Sundermann if (pdipm->solve_symmetric_kkt) { 13257f6ac294SRylee Sundermann KSP ksp; 13267f6ac294SRylee Sundermann PC pc; 1327f560b561SHong Zhang PetscBool isCHOL; 1328*ab76df0cSBarry Smith 13299566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(pdipm->snes, &ksp)); 13309566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 1331*ab76df0cSBarry Smith PetscCall(PCSetPostSetUp(pc, PCPostSetUp_PDIPM)); 1332f560b561SHong Zhang 13339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCCHOLESKY, &isCHOL)); 1334f560b561SHong Zhang if (isCHOL) { 1335f560b561SHong Zhang Mat Factor; 1336f560b561SHong Zhang PetscBool isMUMPS; 13379566063dSJacob Faibussowitsch PetscCall(PCFactorGetMatrix(pc, &Factor)); 13389566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)Factor, "mumps", &isMUMPS)); 1339f560b561SHong Zhang if (isMUMPS) { /* must set mumps ICNTL(13)=1 and ICNTL(24)=1 to call MatGetInertia() */ 1340f560b561SHong Zhang #if defined(PETSC_HAVE_MUMPS) 13419566063dSJacob Faibussowitsch PetscCall(MatMumpsSetIcntl(Factor, 24, 1)); /* detection of null pivot rows */ 13429371c9d4SSatish Balay if (size > 1) { PetscCall(MatMumpsSetIcntl(Factor, 13, 1)); /* parallelism of the root node (enable ScaLAPACK) and its splitting */ } 1343f560b561SHong Zhang #else 1344f560b561SHong Zhang SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_SUP, "Requires external package MUMPS"); 1345f560b561SHong Zhang #endif 1346f560b561SHong Zhang } 1347f560b561SHong Zhang } 13487f6ac294SRylee Sundermann } 13493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1350aad13602SShrirang Abhyankar } 1351aad13602SShrirang Abhyankar 135266976f2fSJacob Faibussowitsch static PetscErrorCode TaoDestroy_PDIPM(Tao tao) 1353d71ae5a4SJacob Faibussowitsch { 1354aad13602SShrirang Abhyankar TAO_PDIPM *pdipm = (TAO_PDIPM *)tao->data; 1355aad13602SShrirang Abhyankar 1356aad13602SShrirang Abhyankar PetscFunctionBegin; 1357aad13602SShrirang Abhyankar /* Freeing Vectors assocaiated with KKT (X) */ 13589566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pdipm->x)); /* Solution x */ 13599566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pdipm->lambdae)); /* Equality constraints lagrangian multiplier*/ 13609566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pdipm->lambdai)); /* Inequality constraints lagrangian multiplier*/ 13619566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pdipm->z)); /* Slack variables */ 13629566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pdipm->X)); /* Big KKT system vector [x; lambdae; lambdai; z] */ 1363aad13602SShrirang Abhyankar 1364aad13602SShrirang Abhyankar /* work vectors */ 13659566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pdipm->lambdae_xfixed)); 13669566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pdipm->lambdai_xb)); 1367aad13602SShrirang Abhyankar 1368aad13602SShrirang Abhyankar /* Legrangian equality and inequality Vec */ 13699566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pdipm->ce)); /* Vec of equality constraints */ 13709566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pdipm->ci)); /* Vec of inequality constraints */ 1371aad13602SShrirang Abhyankar 1372aad13602SShrirang Abhyankar /* Matrices */ 13739566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pdipm->Jce_xfixed)); 13749566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pdipm->Jci_xb)); /* Jacobian of inequality constraints Jci = [tao->jacobian_inequality ; J(nxub); J(nxlb); J(nxbx)] */ 13759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pdipm->K)); 1376aad13602SShrirang Abhyankar 1377aad13602SShrirang Abhyankar /* Index Sets */ 13789371c9d4SSatish Balay if (pdipm->Nxub) { PetscCall(ISDestroy(&pdipm->isxub)); /* Finite upper bound only -inf < x < ub */ } 1379aad13602SShrirang Abhyankar 13809371c9d4SSatish Balay if (pdipm->Nxlb) { PetscCall(ISDestroy(&pdipm->isxlb)); /* Finite lower bound only lb <= x < inf */ } 1381aad13602SShrirang Abhyankar 13829371c9d4SSatish Balay if (pdipm->Nxfixed) { PetscCall(ISDestroy(&pdipm->isxfixed)); /* Fixed variables lb = x = ub */ } 1383aad13602SShrirang Abhyankar 13849371c9d4SSatish Balay if (pdipm->Nxbox) { PetscCall(ISDestroy(&pdipm->isxbox)); /* Boxed variables lb <= x <= ub */ } 1385aad13602SShrirang Abhyankar 13869371c9d4SSatish Balay if (pdipm->Nxfree) { PetscCall(ISDestroy(&pdipm->isxfree)); /* Free variables -inf <= x <= inf */ } 1387aad13602SShrirang Abhyankar 1388aad13602SShrirang Abhyankar if (pdipm->solve_reduced_kkt) { 13899566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pdipm->is1)); 13909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pdipm->is2)); 1391aad13602SShrirang Abhyankar } 1392aad13602SShrirang Abhyankar 1393aad13602SShrirang Abhyankar /* SNES */ 13949566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&pdipm->snes)); /* Nonlinear solver */ 13959566063dSJacob Faibussowitsch PetscCall(PetscFree(pdipm->nce_all)); 13969566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pdipm->jac_equality_trans)); 13979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pdipm->jac_inequality_trans)); 1398aad13602SShrirang Abhyankar 1399aad13602SShrirang Abhyankar /* Destroy pdipm */ 14009566063dSJacob Faibussowitsch PetscCall(PetscFree(tao->data)); /* Holding locations of pdipm */ 1401aad13602SShrirang Abhyankar 1402aad13602SShrirang Abhyankar /* Destroy Dual */ 14039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&tao->DE)); /* equality dual */ 14049566063dSJacob Faibussowitsch PetscCall(VecDestroy(&tao->DI)); /* dinequality dual */ 14053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1406aad13602SShrirang Abhyankar } 1407aad13602SShrirang Abhyankar 1408ce78bad3SBarry Smith static PetscErrorCode TaoSetFromOptions_PDIPM(Tao tao, PetscOptionItems PetscOptionsObject) 1409d71ae5a4SJacob Faibussowitsch { 1410aad13602SShrirang Abhyankar TAO_PDIPM *pdipm = (TAO_PDIPM *)tao->data; 1411aad13602SShrirang Abhyankar 1412aad13602SShrirang Abhyankar PetscFunctionBegin; 1413d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "PDIPM method for constrained optimization"); 14149566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-tao_pdipm_push_init_slack", "parameter to push initial slack variables away from bounds", NULL, pdipm->push_init_slack, &pdipm->push_init_slack, NULL)); 14159566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-tao_pdipm_push_init_lambdai", "parameter to push initial (inequality) dual variables away from bounds", NULL, pdipm->push_init_lambdai, &pdipm->push_init_lambdai, NULL)); 14169566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-tao_pdipm_solve_reduced_kkt", "Solve reduced KKT system using Schur-complement", NULL, pdipm->solve_reduced_kkt, &pdipm->solve_reduced_kkt, NULL)); 14179566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-tao_pdipm_mu_update_factor", "Update scalar for barrier parameter (mu) update", NULL, pdipm->mu_update_factor, &pdipm->mu_update_factor, NULL)); 14189566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-tao_pdipm_symmetric_kkt", "Solve non reduced symmetric KKT system", NULL, pdipm->solve_symmetric_kkt, &pdipm->solve_symmetric_kkt, NULL)); 14199566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-tao_pdipm_kkt_shift_pd", "Add shifts to make KKT matrix positive definite", NULL, pdipm->kkt_pd, &pdipm->kkt_pd, NULL)); 1420d0609cedSBarry Smith PetscOptionsHeadEnd(); 14213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1422aad13602SShrirang Abhyankar } 1423aad13602SShrirang Abhyankar 1424aad13602SShrirang Abhyankar /*MC 1425aad13602SShrirang Abhyankar TAOPDIPM - Barrier-based primal-dual interior point algorithm for generally constrained optimization. 1426aad13602SShrirang Abhyankar 14272fe279fdSBarry Smith Options Database Keys: 1428aad13602SShrirang Abhyankar + -tao_pdipm_push_init_lambdai - parameter to push initial dual variables away from bounds (> 0) 1429aad13602SShrirang Abhyankar . -tao_pdipm_push_init_slack - parameter to push initial slack variables away from bounds (> 0) 143012d688e0SRylee Sundermann . -tao_pdipm_mu_update_factor - update scalar for barrier parameter (mu) update (> 0) 143109ee8bb0SRylee Sundermann . -tao_pdipm_symmetric_kkt - Solve non-reduced symmetric KKT system 143209ee8bb0SRylee Sundermann - -tao_pdipm_kkt_shift_pd - Add shifts to make KKT matrix positive definite 1433aad13602SShrirang Abhyankar 1434aad13602SShrirang Abhyankar Level: beginner 143520f4b53cSBarry Smith 14362fe279fdSBarry Smith .seealso: `TAOPDIPM`, `Tao`, `TaoType` 1437aad13602SShrirang Abhyankar M*/ 143820f4b53cSBarry Smith 1439d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode TaoCreate_PDIPM(Tao tao) 1440d71ae5a4SJacob Faibussowitsch { 1441aad13602SShrirang Abhyankar TAO_PDIPM *pdipm; 1442*ab76df0cSBarry Smith PC pc; 1443aad13602SShrirang Abhyankar 1444aad13602SShrirang Abhyankar PetscFunctionBegin; 1445aad13602SShrirang Abhyankar tao->ops->setup = TaoSetup_PDIPM; 1446aad13602SShrirang Abhyankar tao->ops->solve = TaoSolve_PDIPM; 1447aad13602SShrirang Abhyankar tao->ops->setfromoptions = TaoSetFromOptions_PDIPM; 144870c9796eSresundermann tao->ops->view = TaoView_PDIPM; 1449aad13602SShrirang Abhyankar tao->ops->destroy = TaoDestroy_PDIPM; 1450aad13602SShrirang Abhyankar 14514dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&pdipm)); 1452aad13602SShrirang Abhyankar tao->data = (void *)pdipm; 1453aad13602SShrirang Abhyankar 1454aad13602SShrirang Abhyankar pdipm->nx = pdipm->Nx = 0; 1455aad13602SShrirang Abhyankar pdipm->nxfixed = pdipm->Nxfixed = 0; 1456aad13602SShrirang Abhyankar pdipm->nxlb = pdipm->Nxlb = 0; 1457aad13602SShrirang Abhyankar pdipm->nxub = pdipm->Nxub = 0; 1458aad13602SShrirang Abhyankar pdipm->nxbox = pdipm->Nxbox = 0; 1459aad13602SShrirang Abhyankar pdipm->nxfree = pdipm->Nxfree = 0; 1460aad13602SShrirang Abhyankar 1461aad13602SShrirang Abhyankar pdipm->ng = pdipm->Ng = pdipm->nce = pdipm->Nce = 0; 1462aad13602SShrirang Abhyankar pdipm->nh = pdipm->Nh = pdipm->nci = pdipm->Nci = 0; 1463aad13602SShrirang Abhyankar pdipm->n = pdipm->N = 0; 1464aad13602SShrirang Abhyankar pdipm->mu = 1.0; 1465aad13602SShrirang Abhyankar pdipm->mu_update_factor = 0.1; 1466aad13602SShrirang Abhyankar 146709ee8bb0SRylee Sundermann pdipm->deltaw = 0.0; 146809ee8bb0SRylee Sundermann pdipm->lastdeltaw = 3 * 1.e-4; 146909ee8bb0SRylee Sundermann pdipm->deltac = 0.0; 147009ee8bb0SRylee Sundermann pdipm->kkt_pd = PETSC_FALSE; 147109ee8bb0SRylee Sundermann 1472aad13602SShrirang Abhyankar pdipm->push_init_slack = 1.0; 1473aad13602SShrirang Abhyankar pdipm->push_init_lambdai = 1.0; 1474aad13602SShrirang Abhyankar pdipm->solve_reduced_kkt = PETSC_FALSE; 147512d688e0SRylee Sundermann pdipm->solve_symmetric_kkt = PETSC_TRUE; 1476aad13602SShrirang Abhyankar 1477aad13602SShrirang Abhyankar /* Override default settings (unless already changed) */ 1478606f75f6SBarry Smith PetscCall(TaoParametersInitialize(tao)); 1479606f75f6SBarry Smith PetscObjectParameterSetDefault(tao, max_it, 200); 1480606f75f6SBarry Smith PetscObjectParameterSetDefault(tao, max_funcs, 500); 1481aad13602SShrirang Abhyankar 14829566063dSJacob Faibussowitsch PetscCall(SNESCreate(((PetscObject)tao)->comm, &pdipm->snes)); 14839566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(pdipm->snes, tao->hdr.prefix)); 14849566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(pdipm->snes, &tao->ksp)); 14859566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)tao->ksp)); 1486*ab76df0cSBarry Smith PetscCall(KSPGetPC(tao->ksp, &pc)); 1487*ab76df0cSBarry Smith PetscCall(PCSetApplicationContext(pc, (void *)tao)); 14883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1489aad13602SShrirang Abhyankar } 1490