xref: /petsc/src/tao/constrained/tutorials/ex1.c (revision 327415f76d85372a4417cf1aaa14db707d4d6c04)
1aad13602SShrirang Abhyankar /* Program usage: mpiexec -n 2 ./ex1 [-help] [all TAO options] */
2aad13602SShrirang Abhyankar 
3aad13602SShrirang Abhyankar /* ----------------------------------------------------------------------
4628da978Sresundermann min f(x) = (x0 - 2)^2 + (x1 - 2)^2 - 2*(x0 + x1)
5aad13602SShrirang Abhyankar s.t.  x0^2 + x1 - 2 = 0
6aad13602SShrirang Abhyankar       0  <= x0^2 - x1 <= 1
7aad13602SShrirang Abhyankar       -1 <= x0, x1 <= 2
8628da978Sresundermann -->
9628da978Sresundermann       g(x)  = 0
10628da978Sresundermann       h(x) >= 0
11628da978Sresundermann       -1 <= x0, x1 <= 2
12628da978Sresundermann where
13628da978Sresundermann       g(x) = x0^2 + x1 - 2
14628da978Sresundermann       h(x) = [x0^2 - x1
15628da978Sresundermann               1 -(x0^2 - x1)]
16aad13602SShrirang Abhyankar ---------------------------------------------------------------------- */
17aad13602SShrirang Abhyankar 
18aad13602SShrirang Abhyankar #include <petsctao.h>
19aad13602SShrirang Abhyankar 
20aad13602SShrirang Abhyankar static  char help[]= "Solves constrained optimiztion problem using pdipm.\n\
21aad13602SShrirang Abhyankar Input parameters include:\n\
22aad13602SShrirang Abhyankar   -tao_type pdipm    : sets Tao solver\n\
238e58fa1dSresundermann   -no_eq             : removes the equaility constraints from the problem\n\
24f560b561SHong Zhang   -init_view         : view initial object setup\n\
25aad13602SShrirang Abhyankar   -snes_fd           : snes with finite difference Jacobian (needed for pdipm)\n\
26628da978Sresundermann   -snes_compare_explicit : compare user Jacobian with finite difference Jacobian \n\
27aad13602SShrirang Abhyankar   -tao_cmonitor      : convergence monitor with constraint norm \n\
28a5b23f4aSJose E. Roman   -tao_view_solution : view exact solution at each iteration\n\
29f560b561SHong Zhang   Note: external package MUMPS is required to run pdipm in parallel. This is designed for a maximum of 2 processors, the code will error if size > 2.\n";
30aad13602SShrirang Abhyankar 
31aad13602SShrirang Abhyankar /*
32628da978Sresundermann    User-defined application context - contains data needed by the application
33aad13602SShrirang Abhyankar */
34aad13602SShrirang Abhyankar typedef struct {
35aad13602SShrirang Abhyankar   PetscInt   n;  /* Global length of x */
36aad13602SShrirang Abhyankar   PetscInt   ne; /* Global number of equality constraints */
37aad13602SShrirang Abhyankar   PetscInt   ni; /* Global number of inequality constraints */
38f560b561SHong Zhang   PetscBool  noeqflag, initview;
39aad13602SShrirang Abhyankar   Vec        x,xl,xu;
40aad13602SShrirang Abhyankar   Vec        ce,ci,bl,bu,Xseq;
41aad13602SShrirang Abhyankar   Mat        Ae,Ai,H;
42aad13602SShrirang Abhyankar   VecScatter scat;
43aad13602SShrirang Abhyankar } AppCtx;
44aad13602SShrirang Abhyankar 
45aad13602SShrirang Abhyankar /* -------- User-defined Routines --------- */
46aad13602SShrirang Abhyankar PetscErrorCode InitializeProblem(AppCtx *);
47aad13602SShrirang Abhyankar PetscErrorCode DestroyProblem(AppCtx *);
48aad13602SShrirang Abhyankar PetscErrorCode FormFunctionGradient(Tao,Vec,PetscReal *,Vec,void *);
49aad13602SShrirang Abhyankar PetscErrorCode FormHessian(Tao,Vec,Mat,Mat, void*);
50aad13602SShrirang Abhyankar PetscErrorCode FormInequalityConstraints(Tao,Vec,Vec,void*);
51aad13602SShrirang Abhyankar PetscErrorCode FormEqualityConstraints(Tao,Vec,Vec,void*);
52aad13602SShrirang Abhyankar PetscErrorCode FormInequalityJacobian(Tao,Vec,Mat,Mat, void*);
53aad13602SShrirang Abhyankar PetscErrorCode FormEqualityJacobian(Tao,Vec,Mat,Mat, void*);
54aad13602SShrirang Abhyankar 
55aad13602SShrirang Abhyankar PetscErrorCode main(int argc,char **argv)
56aad13602SShrirang Abhyankar {
57aad13602SShrirang Abhyankar   Tao            tao;
58aad13602SShrirang Abhyankar   KSP            ksp;
59aad13602SShrirang Abhyankar   PC             pc;
60aad13602SShrirang Abhyankar   AppCtx         user;  /* application context */
61f560b561SHong Zhang   Vec            x,G,CI,CE;
62f560b561SHong Zhang   PetscMPIInt    size;
63661095bbSAlp Dener   TaoType        type;
64f560b561SHong Zhang   PetscReal      f;
65661095bbSAlp Dener   PetscBool      pdipm;
66aad13602SShrirang Abhyankar 
67*327415f7SBarry Smith   PetscFunctionBeginUser;
689566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc,&argv,(char*)0,help));
699566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size));
703c859ba3SBarry Smith   PetscCheck(size <= 2,PETSC_COMM_SELF,PETSC_ERR_WRONG_MPI_SIZE,"More than 2 processors detected. Example written to use max of 2 processors.");
71aad13602SShrirang Abhyankar 
729566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD,"---- Constrained Problem -----\n"));
739566063dSJacob Faibussowitsch   PetscCall(InitializeProblem(&user)); /* sets up problem, function below */
749566063dSJacob Faibussowitsch   PetscCall(TaoCreate(PETSC_COMM_WORLD,&tao));
759566063dSJacob Faibussowitsch   PetscCall(TaoSetType(tao,TAOPDIPM));
769566063dSJacob Faibussowitsch   PetscCall(TaoSetSolution(tao,user.x)); /* gets solution vector from problem */
779566063dSJacob Faibussowitsch   PetscCall(TaoSetVariableBounds(tao,user.xl,user.xu)); /* sets lower upper bounds from given solution */
789566063dSJacob Faibussowitsch   PetscCall(TaoSetObjectiveAndGradient(tao,NULL,FormFunctionGradient,(void*)&user));
79aad13602SShrirang Abhyankar 
808e58fa1dSresundermann   if (!user.noeqflag) {
819566063dSJacob Faibussowitsch     PetscCall(TaoSetEqualityConstraintsRoutine(tao,user.ce,FormEqualityConstraints,(void*)&user));
828e58fa1dSresundermann   }
839566063dSJacob Faibussowitsch   PetscCall(TaoSetInequalityConstraintsRoutine(tao,user.ci,FormInequalityConstraints,(void*)&user));
848e58fa1dSresundermann   if (!user.noeqflag) {
859566063dSJacob Faibussowitsch     PetscCall(TaoSetJacobianEqualityRoutine(tao,user.Ae,user.Ae,FormEqualityJacobian,(void*)&user)); /* equality jacobian */
868e58fa1dSresundermann   }
879566063dSJacob Faibussowitsch   PetscCall(TaoSetJacobianInequalityRoutine(tao,user.Ai,user.Ai,FormInequalityJacobian,(void*)&user)); /* inequality jacobian */
889566063dSJacob Faibussowitsch   PetscCall(TaoSetTolerances(tao,1.e-6,1.e-6,1.e-6));
899566063dSJacob Faibussowitsch   PetscCall(TaoSetConstraintTolerances(tao,1.e-6,1.e-6));
90aad13602SShrirang Abhyankar 
919566063dSJacob Faibussowitsch   PetscCall(TaoGetKSP(tao,&ksp));
929566063dSJacob Faibussowitsch   PetscCall(KSPGetPC(ksp,&pc));
939566063dSJacob Faibussowitsch   PetscCall(PCSetType(pc,PCCHOLESKY));
94aad13602SShrirang Abhyankar   /*
95aad13602SShrirang Abhyankar       This algorithm produces matrices with zeros along the diagonal therefore we use
9612d688e0SRylee Sundermann     MUMPS which provides solver for indefinite matrices
97aad13602SShrirang Abhyankar   */
98f560b561SHong Zhang #if defined(PETSC_HAVE_MUMPS)
999566063dSJacob Faibussowitsch   PetscCall(PCFactorSetMatSolverType(pc,MATSOLVERMUMPS));  /* requires mumps to solve pdipm */
100f560b561SHong Zhang #else
1013c859ba3SBarry Smith   PetscCheck(size == 1,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Requires an external package that supports parallel PCCHOLESKY, e.g., MUMPS.");
102f560b561SHong Zhang #endif
1039566063dSJacob Faibussowitsch   PetscCall(KSPSetType(ksp,KSPPREONLY));
1049566063dSJacob Faibussowitsch   PetscCall(KSPSetFromOptions(ksp));
105aad13602SShrirang Abhyankar 
1069566063dSJacob Faibussowitsch   PetscCall(TaoSetFromOptions(tao));
1079566063dSJacob Faibussowitsch   PetscCall(TaoGetType(tao,&type));
1089566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)tao,TAOPDIPM,&pdipm));
109661095bbSAlp Dener   if (pdipm) {
1109566063dSJacob Faibussowitsch     PetscCall(TaoSetHessian(tao,user.H,user.H,FormHessian,(void*)&user));
111f560b561SHong Zhang     if (user.initview) {
1129566063dSJacob Faibussowitsch       PetscCall(TaoSetUp(tao));
1139566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(user.x, &G));
1149566063dSJacob Faibussowitsch       PetscCall(FormFunctionGradient(tao, user.x, &f, G, (void*)&user));
1159566063dSJacob Faibussowitsch       PetscCall(FormHessian(tao, user.x, user.H, user.H, (void*)&user));
1169566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_WORLD));
11763a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nInitial point X:\n"));
1189566063dSJacob Faibussowitsch       PetscCall(VecView(user.x, PETSC_VIEWER_STDOUT_WORLD));
11963a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nInitial objective f(x) = %g\n",(double)f));
12063a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nInitial gradient and Hessian:\n"));
1219566063dSJacob Faibussowitsch       PetscCall(VecView(G, PETSC_VIEWER_STDOUT_WORLD));
1229566063dSJacob Faibussowitsch       PetscCall(MatView(user.H, PETSC_VIEWER_STDOUT_WORLD));
1239566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&G));
1249566063dSJacob Faibussowitsch       PetscCall(FormInequalityJacobian(tao, user.x, user.Ai, user.Ai, (void*)&user));
1259566063dSJacob Faibussowitsch       PetscCall(MatCreateVecs(user.Ai, NULL, &CI));
1269566063dSJacob Faibussowitsch       PetscCall(FormInequalityConstraints(tao, user.x, CI, (void*)&user));
12763a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nInitial inequality constraints and Jacobian:\n"));
1289566063dSJacob Faibussowitsch       PetscCall(VecView(CI, PETSC_VIEWER_STDOUT_WORLD));
1299566063dSJacob Faibussowitsch       PetscCall(MatView(user.Ai, PETSC_VIEWER_STDOUT_WORLD));
1309566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&CI));
131f560b561SHong Zhang       if (!user.noeqflag) {
1329566063dSJacob Faibussowitsch         PetscCall(FormEqualityJacobian(tao, user.x, user.Ae, user.Ae, (void*)&user));
1339566063dSJacob Faibussowitsch         PetscCall(MatCreateVecs(user.Ae, NULL, &CE));
1349566063dSJacob Faibussowitsch         PetscCall(FormEqualityConstraints(tao, user.x, CE, (void*)&user));
13563a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nInitial equality constraints and Jacobian:\n"));
1369566063dSJacob Faibussowitsch         PetscCall(VecView(CE, PETSC_VIEWER_STDOUT_WORLD));
1379566063dSJacob Faibussowitsch         PetscCall(MatView(user.Ae, PETSC_VIEWER_STDOUT_WORLD));
1389566063dSJacob Faibussowitsch         PetscCall(VecDestroy(&CE));
139f560b561SHong Zhang       }
1409566063dSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\n"));
1419566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_WORLD));
142f560b561SHong Zhang     }
143661095bbSAlp Dener   }
144aad13602SShrirang Abhyankar 
1459566063dSJacob Faibussowitsch   PetscCall(TaoSolve(tao));
1469566063dSJacob Faibussowitsch   PetscCall(TaoGetSolution(tao,&x));
1479566063dSJacob Faibussowitsch   PetscCall(VecView(x,PETSC_VIEWER_STDOUT_WORLD));
148aad13602SShrirang Abhyankar 
149aad13602SShrirang Abhyankar   /* Free objects */
1509566063dSJacob Faibussowitsch   PetscCall(DestroyProblem(&user));
1519566063dSJacob Faibussowitsch   PetscCall(TaoDestroy(&tao));
1529566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
153b122ec5aSJacob Faibussowitsch   return 0;
154aad13602SShrirang Abhyankar }
155aad13602SShrirang Abhyankar 
156aad13602SShrirang Abhyankar PetscErrorCode InitializeProblem(AppCtx *user)
157aad13602SShrirang Abhyankar {
158aad13602SShrirang Abhyankar   PetscMPIInt    size;
159aad13602SShrirang Abhyankar   PetscMPIInt    rank;
160aad13602SShrirang Abhyankar   PetscInt       nloc,neloc,niloc;
161aad13602SShrirang Abhyankar 
162aad13602SShrirang Abhyankar   PetscFunctionBegin;
1639566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size));
1649566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
1658e58fa1dSresundermann   user->noeqflag = PETSC_FALSE;
1669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL,NULL,"-no_eq",&user->noeqflag,NULL));
167f560b561SHong Zhang   user->initview = PETSC_FALSE;
1689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL,NULL,"-init_view",&user->initview,NULL));
169628da978Sresundermann 
1708e58fa1dSresundermann   if (!user->noeqflag) {
171f560b561SHong Zhang     /* Tell user the correct solution, not an error checking */
1729566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Solution should be f(1,1)=-2\n"));
1738e58fa1dSresundermann   }
174aad13602SShrirang Abhyankar 
1752d4ee042Sprj-   /* create vector x and set initial values */
176aad13602SShrirang Abhyankar   user->n = 2; /* global length */
177f560b561SHong Zhang   nloc = (size==1)?user->n:1;
1789566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_WORLD,&user->x));
1799566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(user->x,nloc,user->n));
1809566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(user->x));
1819566063dSJacob Faibussowitsch   PetscCall(VecSet(user->x,0));
182aad13602SShrirang Abhyankar 
183aad13602SShrirang Abhyankar   /* create and set lower and upper bound vectors */
1849566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(user->x,&user->xl));
1859566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(user->x,&user->xu));
1869566063dSJacob Faibussowitsch   PetscCall(VecSet(user->xl,-1.0));
1879566063dSJacob Faibussowitsch   PetscCall(VecSet(user->xu,2.0));
188aad13602SShrirang Abhyankar 
189aad13602SShrirang Abhyankar   /* create scater to zero */
1909566063dSJacob Faibussowitsch   PetscCall(VecScatterCreateToZero(user->x,&user->scat,&user->Xseq));
191aad13602SShrirang Abhyankar 
192aad13602SShrirang Abhyankar   user->ne = 1;
193628da978Sresundermann   user->ni = 2;
194aad13602SShrirang Abhyankar   neloc = (rank==0)?user->ne:0;
195f560b561SHong Zhang   niloc = (size==1)?user->ni:1;
196aad13602SShrirang Abhyankar 
1978e58fa1dSresundermann   if (!user->noeqflag) {
1989566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_WORLD,&user->ce)); /* a 1x1 vec for equality constraints */
1999566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(user->ce,neloc,user->ne));
2009566063dSJacob Faibussowitsch     PetscCall(VecSetFromOptions(user->ce));
2019566063dSJacob Faibussowitsch     PetscCall(VecSetUp(user->ce));
2028e58fa1dSresundermann   }
203628da978Sresundermann 
2049566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_WORLD,&user->ci)); /* a 2x1 vec for inequality constraints */
2059566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(user->ci,niloc,user->ni));
2069566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(user->ci));
2079566063dSJacob Faibussowitsch   PetscCall(VecSetUp(user->ci));
208aad13602SShrirang Abhyankar 
209a5b23f4aSJose E. Roman   /* nexn & nixn matricies for equally and inequalty constraints */
2108e58fa1dSresundermann   if (!user->noeqflag) {
2119566063dSJacob Faibussowitsch     PetscCall(MatCreate(PETSC_COMM_WORLD,&user->Ae));
2129566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(user->Ae,neloc,nloc,user->ne,user->n));
2139566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(user->Ae));
2149566063dSJacob Faibussowitsch     PetscCall(MatSetUp(user->Ae));
2158e58fa1dSresundermann   }
2168e58fa1dSresundermann 
2179566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_WORLD,&user->Ai));
2189566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(user->Ai,niloc,nloc,user->ni,user->n));
2199566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(user->Ai));
2209566063dSJacob Faibussowitsch   PetscCall(MatSetUp(user->Ai));
221628da978Sresundermann 
2229566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_WORLD,&user->H));
2239566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(user->H,nloc,nloc,user->n,user->n));
2249566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(user->H));
2259566063dSJacob Faibussowitsch   PetscCall(MatSetUp(user->H));
226aad13602SShrirang Abhyankar   PetscFunctionReturn(0);
227aad13602SShrirang Abhyankar }
228aad13602SShrirang Abhyankar 
229aad13602SShrirang Abhyankar PetscErrorCode DestroyProblem(AppCtx *user)
230aad13602SShrirang Abhyankar {
231aad13602SShrirang Abhyankar   PetscFunctionBegin;
2328e58fa1dSresundermann   if (!user->noeqflag) {
2339566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&user->Ae));
2348e58fa1dSresundermann   }
2359566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&user->Ai));
2369566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&user->H));
237aad13602SShrirang Abhyankar 
2389566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&user->x));
2398e58fa1dSresundermann   if (!user->noeqflag) {
2409566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&user->ce));
2418e58fa1dSresundermann   }
2429566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&user->ci));
2439566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&user->xl));
2449566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&user->xu));
2459566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&user->Xseq));
2469566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&user->scat));
247aad13602SShrirang Abhyankar   PetscFunctionReturn(0);
248aad13602SShrirang Abhyankar }
249aad13602SShrirang Abhyankar 
250628da978Sresundermann /* Evaluate
251628da978Sresundermann    f(x) = (x0 - 2)^2 + (x1 - 2)^2 - 2*(x0 + x1)
252628da978Sresundermann    G = grad f = [2*(x0 - 2) - 2;
253628da978Sresundermann                  2*(x1 - 2) - 2]
254aad13602SShrirang Abhyankar */
255aad13602SShrirang Abhyankar PetscErrorCode FormFunctionGradient(Tao tao, Vec X, PetscReal *f, Vec G, void *ctx)
256aad13602SShrirang Abhyankar {
257aad13602SShrirang Abhyankar   PetscScalar       g;
258aad13602SShrirang Abhyankar   const PetscScalar *x;
259aad13602SShrirang Abhyankar   MPI_Comm          comm;
260aad13602SShrirang Abhyankar   PetscMPIInt       rank;
261aad13602SShrirang Abhyankar   PetscReal         fin;
262aad13602SShrirang Abhyankar   AppCtx            *user=(AppCtx*)ctx;
263aad13602SShrirang Abhyankar   Vec               Xseq=user->Xseq;
264aad13602SShrirang Abhyankar   VecScatter        scat=user->scat;
265aad13602SShrirang Abhyankar 
266aad13602SShrirang Abhyankar   PetscFunctionBegin;
2679566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)tao,&comm));
2689566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm,&rank));
269aad13602SShrirang Abhyankar 
2709566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(scat,X,Xseq,INSERT_VALUES,SCATTER_FORWARD));
2719566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(scat,X,Xseq,INSERT_VALUES,SCATTER_FORWARD));
272aad13602SShrirang Abhyankar 
273aad13602SShrirang Abhyankar   fin = 0.0;
274dd400576SPatrick Sanan   if (rank == 0) {
2759566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(Xseq,&x));
276aad13602SShrirang Abhyankar     fin = (x[0]-2.0)*(x[0]-2.0) + (x[1]-2.0)*(x[1]-2.0) - 2.0*(x[0]+x[1]);
277aad13602SShrirang Abhyankar     g = 2.0*(x[0]-2.0) - 2.0;
2789566063dSJacob Faibussowitsch     PetscCall(VecSetValue(G,0,g,INSERT_VALUES));
279aad13602SShrirang Abhyankar     g = 2.0*(x[1]-2.0) - 2.0;
2809566063dSJacob Faibussowitsch     PetscCall(VecSetValue(G,1,g,INSERT_VALUES));
2819566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(Xseq,&x));
282aad13602SShrirang Abhyankar   }
2839566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(&fin,f,1,MPIU_REAL,MPIU_SUM,comm));
2849566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(G));
2859566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(G));
286aad13602SShrirang Abhyankar   PetscFunctionReturn(0);
287aad13602SShrirang Abhyankar }
288aad13602SShrirang Abhyankar 
289628da978Sresundermann /* Evaluate
290628da978Sresundermann    H = fxx + grad (grad g^T*DI) - grad (grad h^T*DE)]
291628da978Sresundermann      = [ 2*(1+de[0]-di[0]+di[1]), 0;
292628da978Sresundermann                    0,             2]
293628da978Sresundermann */
294aad13602SShrirang Abhyankar PetscErrorCode FormHessian(Tao tao, Vec x,Mat H, Mat Hpre, void *ctx)
295aad13602SShrirang Abhyankar {
296aad13602SShrirang Abhyankar   AppCtx            *user=(AppCtx*)ctx;
297aad13602SShrirang Abhyankar   Vec               DE,DI;
298aad13602SShrirang Abhyankar   const PetscScalar *de,*di;
299aad13602SShrirang Abhyankar   PetscInt          zero=0,one=1;
300aad13602SShrirang Abhyankar   PetscScalar       two=2.0;
301aad13602SShrirang Abhyankar   PetscScalar       val=0.0;
302f560b561SHong Zhang   Vec               Deseq,Diseq;
303f560b561SHong Zhang   VecScatter        Descat,Discat;
304aad13602SShrirang Abhyankar   PetscMPIInt       rank;
305aad13602SShrirang Abhyankar   MPI_Comm          comm;
306aad13602SShrirang Abhyankar 
307aad13602SShrirang Abhyankar   PetscFunctionBegin;
3089566063dSJacob Faibussowitsch   PetscCall(TaoGetDualVariables(tao,&DE,&DI));
309aad13602SShrirang Abhyankar 
3109566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)tao,&comm));
3119566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm,&rank));
312aad13602SShrirang Abhyankar 
3138e58fa1dSresundermann   if (!user->noeqflag) {
3149566063dSJacob Faibussowitsch    PetscCall(VecScatterCreateToZero(DE,&Descat,&Deseq));
3159566063dSJacob Faibussowitsch    PetscCall(VecScatterBegin(Descat,DE,Deseq,INSERT_VALUES,SCATTER_FORWARD));
3169566063dSJacob Faibussowitsch    PetscCall(VecScatterEnd(Descat,DE,Deseq,INSERT_VALUES,SCATTER_FORWARD));
3178e58fa1dSresundermann   }
3189566063dSJacob Faibussowitsch   PetscCall(VecScatterCreateToZero(DI,&Discat,&Diseq));
3199566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(Discat,DI,Diseq,INSERT_VALUES,SCATTER_FORWARD));
3209566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(Discat,DI,Diseq,INSERT_VALUES,SCATTER_FORWARD));
321aad13602SShrirang Abhyankar 
322dd400576SPatrick Sanan   if (rank == 0) {
3238e58fa1dSresundermann     if (!user->noeqflag) {
3249566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(Deseq,&de));  /* places equality constraint dual into array */
3258e58fa1dSresundermann     }
3269566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(Diseq,&di));  /* places inequality constraint dual into array */
327628da978Sresundermann 
3288e58fa1dSresundermann     if (!user->noeqflag) {
329628da978Sresundermann       val = 2.0 * (1 + de[0] - di[0] + di[1]);
3309566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(Deseq,&de));
3319566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(Diseq,&di));
3328e58fa1dSresundermann     } else {
333628da978Sresundermann       val = 2.0 * (1 - di[0] + di[1]);
3348e58fa1dSresundermann     }
3359566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(Diseq,&di));
3369566063dSJacob Faibussowitsch     PetscCall(MatSetValues(H,1,&zero,1,&zero,&val,INSERT_VALUES));
3379566063dSJacob Faibussowitsch     PetscCall(MatSetValues(H,1,&one,1,&one,&two,INSERT_VALUES));
338aad13602SShrirang Abhyankar   }
3399566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(H,MAT_FINAL_ASSEMBLY));
3409566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(H,MAT_FINAL_ASSEMBLY));
3418e58fa1dSresundermann   if (!user->noeqflag) {
3429566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&Descat));
3439566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&Deseq));
3448e58fa1dSresundermann   }
3459566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&Discat));
3469566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&Diseq));
347aad13602SShrirang Abhyankar   PetscFunctionReturn(0);
348aad13602SShrirang Abhyankar }
349aad13602SShrirang Abhyankar 
350628da978Sresundermann /* Evaluate
351628da978Sresundermann    h = [ x0^2 - x1;
352628da978Sresundermann          1 -(x0^2 - x1)]
353628da978Sresundermann */
354aad13602SShrirang Abhyankar PetscErrorCode FormInequalityConstraints(Tao tao,Vec X,Vec CI,void *ctx)
355aad13602SShrirang Abhyankar {
356aad13602SShrirang Abhyankar   const PetscScalar *x;
357aad13602SShrirang Abhyankar   PetscScalar       ci;
358aad13602SShrirang Abhyankar   MPI_Comm          comm;
359aad13602SShrirang Abhyankar   PetscMPIInt       rank;
360aad13602SShrirang Abhyankar   AppCtx            *user=(AppCtx*)ctx;
361aad13602SShrirang Abhyankar   Vec               Xseq=user->Xseq;
362aad13602SShrirang Abhyankar   VecScatter        scat=user->scat;
363aad13602SShrirang Abhyankar 
364aad13602SShrirang Abhyankar   PetscFunctionBegin;
3659566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)tao,&comm));
3669566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm,&rank));
367aad13602SShrirang Abhyankar 
3689566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(scat,X,Xseq,INSERT_VALUES,SCATTER_FORWARD));
3699566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(scat,X,Xseq,INSERT_VALUES,SCATTER_FORWARD));
370aad13602SShrirang Abhyankar 
371dd400576SPatrick Sanan   if (rank == 0) {
3729566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(Xseq,&x));
373aad13602SShrirang Abhyankar     ci = x[0]*x[0] - x[1];
3749566063dSJacob Faibussowitsch     PetscCall(VecSetValue(CI,0,ci,INSERT_VALUES));
375aad13602SShrirang Abhyankar     ci = -x[0]*x[0] + x[1] + 1.0;
3769566063dSJacob Faibussowitsch     PetscCall(VecSetValue(CI,1,ci,INSERT_VALUES));
3779566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(Xseq,&x));
378aad13602SShrirang Abhyankar   }
3799566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(CI));
3809566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(CI));
381aad13602SShrirang Abhyankar   PetscFunctionReturn(0);
382aad13602SShrirang Abhyankar }
383aad13602SShrirang Abhyankar 
384628da978Sresundermann /* Evaluate
385628da978Sresundermann    g = [ x0^2 + x1 - 2]
386628da978Sresundermann */
387aad13602SShrirang Abhyankar PetscErrorCode FormEqualityConstraints(Tao tao,Vec X,Vec CE,void *ctx)
388aad13602SShrirang Abhyankar {
389aad13602SShrirang Abhyankar   const PetscScalar *x;
390aad13602SShrirang Abhyankar   PetscScalar       ce;
391aad13602SShrirang Abhyankar   MPI_Comm          comm;
392aad13602SShrirang Abhyankar   PetscMPIInt       rank;
393aad13602SShrirang Abhyankar   AppCtx            *user=(AppCtx*)ctx;
394aad13602SShrirang Abhyankar   Vec               Xseq=user->Xseq;
395aad13602SShrirang Abhyankar   VecScatter        scat=user->scat;
396aad13602SShrirang Abhyankar 
397aad13602SShrirang Abhyankar   PetscFunctionBegin;
3989566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)tao,&comm));
3999566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm,&rank));
400aad13602SShrirang Abhyankar 
4019566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(scat,X,Xseq,INSERT_VALUES,SCATTER_FORWARD));
4029566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(scat,X,Xseq,INSERT_VALUES,SCATTER_FORWARD));
403aad13602SShrirang Abhyankar 
404dd400576SPatrick Sanan   if (rank == 0) {
4059566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(Xseq,&x));
406aad13602SShrirang Abhyankar     ce = x[0]*x[0] + x[1] - 2.0;
4079566063dSJacob Faibussowitsch     PetscCall(VecSetValue(CE,0,ce,INSERT_VALUES));
4089566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(Xseq,&x));
409aad13602SShrirang Abhyankar   }
4109566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(CE));
4119566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(CE));
412aad13602SShrirang Abhyankar   PetscFunctionReturn(0);
413aad13602SShrirang Abhyankar }
414aad13602SShrirang Abhyankar 
415628da978Sresundermann /*
416628da978Sresundermann   grad h = [  2*x0, -1;
417628da978Sresundermann              -2*x0,  1]
418628da978Sresundermann */
419aad13602SShrirang Abhyankar PetscErrorCode FormInequalityJacobian(Tao tao, Vec X, Mat JI, Mat JIpre,  void *ctx)
420aad13602SShrirang Abhyankar {
421aad13602SShrirang Abhyankar   AppCtx            *user=(AppCtx*)ctx;
422f560b561SHong Zhang   PetscInt          zero=0,one=1,cols[2];
423aad13602SShrirang Abhyankar   PetscScalar       vals[2];
424aad13602SShrirang Abhyankar   const PetscScalar *x;
425aad13602SShrirang Abhyankar   Vec               Xseq=user->Xseq;
426aad13602SShrirang Abhyankar   VecScatter        scat=user->scat;
427aad13602SShrirang Abhyankar   MPI_Comm          comm;
428aad13602SShrirang Abhyankar   PetscMPIInt       rank;
429aad13602SShrirang Abhyankar 
430aad13602SShrirang Abhyankar   PetscFunctionBegin;
4319566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)tao,&comm));
4329566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm,&rank));
4339566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(scat,X,Xseq,INSERT_VALUES,SCATTER_FORWARD));
4349566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(scat,X,Xseq,INSERT_VALUES,SCATTER_FORWARD));
435aad13602SShrirang Abhyankar 
4369566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(Xseq,&x));
437c5853193SPierre Jolivet   if (rank == 0) {
438aad13602SShrirang Abhyankar     cols[0] = 0; cols[1] = 1;
439628da978Sresundermann     vals[0] = 2*x[0]; vals[1] = -1.0;
4409566063dSJacob Faibussowitsch     PetscCall(MatSetValues(JI,1,&zero,2,cols,vals,INSERT_VALUES));
441628da978Sresundermann     vals[0] = -2*x[0]; vals[1] = 1.0;
4429566063dSJacob Faibussowitsch     PetscCall(MatSetValues(JI,1,&one,2,cols,vals,INSERT_VALUES));
443aad13602SShrirang Abhyankar   }
4449566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(Xseq,&x));
4459566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(JI,MAT_FINAL_ASSEMBLY));
4469566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(JI,MAT_FINAL_ASSEMBLY));
447aad13602SShrirang Abhyankar   PetscFunctionReturn(0);
448aad13602SShrirang Abhyankar }
449aad13602SShrirang Abhyankar 
450628da978Sresundermann /*
451628da978Sresundermann   grad g = [2*x0
452628da978Sresundermann              1.0 ]
453628da978Sresundermann */
454aad13602SShrirang Abhyankar PetscErrorCode FormEqualityJacobian(Tao tao,Vec X,Mat JE,Mat JEpre,void *ctx)
455aad13602SShrirang Abhyankar {
456f560b561SHong Zhang   PetscInt          zero=0,cols[2];
457aad13602SShrirang Abhyankar   PetscScalar       vals[2];
458aad13602SShrirang Abhyankar   const PetscScalar *x;
459aad13602SShrirang Abhyankar   PetscMPIInt       rank;
460aad13602SShrirang Abhyankar   MPI_Comm          comm;
461aad13602SShrirang Abhyankar 
462aad13602SShrirang Abhyankar   PetscFunctionBegin;
4639566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)tao,&comm));
4649566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm,&rank));
465aad13602SShrirang Abhyankar 
466dd400576SPatrick Sanan   if (rank == 0) {
4679566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(X,&x));
468f560b561SHong Zhang     cols[0] = 0;       cols[1] = 1;
469aad13602SShrirang Abhyankar     vals[0] = 2*x[0];  vals[1] = 1.0;
4709566063dSJacob Faibussowitsch     PetscCall(MatSetValues(JE,1,&zero,2,cols,vals,INSERT_VALUES));
4719566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(X,&x));
472aad13602SShrirang Abhyankar   }
4739566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(JE,MAT_FINAL_ASSEMBLY));
4749566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(JE,MAT_FINAL_ASSEMBLY));
475aad13602SShrirang Abhyankar   PetscFunctionReturn(0);
476aad13602SShrirang Abhyankar }
477aad13602SShrirang Abhyankar 
478aad13602SShrirang Abhyankar /*TEST
479aad13602SShrirang Abhyankar 
480aad13602SShrirang Abhyankar    build:
481f560b561SHong Zhang       requires: !complex !defined(PETSC_USE_CXX)
482aad13602SShrirang Abhyankar 
483aad13602SShrirang Abhyankar    test:
48409ee8bb0SRylee Sundermann       args: -tao_converged_reason -tao_pdipm_kkt_shift_pd
485f560b561SHong Zhang       requires: mumps
486aad13602SShrirang Abhyankar 
487aad13602SShrirang Abhyankar    test:
488aad13602SShrirang Abhyankar       suffix: 2
489aad13602SShrirang Abhyankar       nsize: 2
49009ee8bb0SRylee Sundermann       args: -tao_converged_reason -tao_pdipm_kkt_shift_pd
491f560b561SHong Zhang       requires: mumps
492aad13602SShrirang Abhyankar 
4938e58fa1dSresundermann    test:
4948e58fa1dSresundermann       suffix: 3
4958e58fa1dSresundermann       args: -tao_converged_reason -no_eq
496f560b561SHong Zhang       requires: mumps
4978e58fa1dSresundermann 
4988e58fa1dSresundermann    test:
4998e58fa1dSresundermann       suffix: 4
5008e58fa1dSresundermann       nsize: 2
5018e58fa1dSresundermann       args: -tao_converged_reason -no_eq
502f560b561SHong Zhang       requires: mumps
5038e58fa1dSresundermann 
504661095bbSAlp Dener    test:
505661095bbSAlp Dener       suffix: 5
506661095bbSAlp Dener       args: -tao_cmonitor -tao_type almm
507f560b561SHong Zhang       requires: mumps
508661095bbSAlp Dener 
509661095bbSAlp Dener    test:
510661095bbSAlp Dener       suffix: 6
511661095bbSAlp Dener       args: -tao_cmonitor -tao_type almm -tao_almm_type phr
512f560b561SHong Zhang       requires: mumps
513661095bbSAlp Dener 
514661095bbSAlp Dener    test:
515661095bbSAlp Dener       suffix: 7
516661095bbSAlp Dener       nsize: 2
517f560b561SHong Zhang       requires: mumps
518661095bbSAlp Dener       args: -tao_cmonitor -tao_type almm
519661095bbSAlp Dener 
520661095bbSAlp Dener    test:
521661095bbSAlp Dener       suffix: 8
522661095bbSAlp Dener       nsize: 2
523f560b561SHong Zhang       requires: cuda mumps
524661095bbSAlp Dener       args: -tao_cmonitor -tao_type almm -vec_type cuda -mat_type aijcusparse
525661095bbSAlp Dener 
526661095bbSAlp Dener    test:
527661095bbSAlp Dener       suffix: 9
528661095bbSAlp Dener       nsize: 2
529661095bbSAlp Dener       args: -tao_cmonitor -tao_type almm -no_eq
530f560b561SHong Zhang       requires: mumps
531661095bbSAlp Dener 
532661095bbSAlp Dener    test:
533661095bbSAlp Dener       suffix: 10
534661095bbSAlp Dener       nsize: 2
535661095bbSAlp Dener       args: -tao_cmonitor -tao_type almm -tao_almm_type phr -no_eq
536f560b561SHong Zhang       requires: mumps
537661095bbSAlp Dener 
538aad13602SShrirang Abhyankar TEST*/
539