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
20da81f932SPierre Jolivet static char help[] = "Solves constrained optimization 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\
24c8b0c2b5SHansol Suh -no_bound : removes the bound constraints from the problem\n\
25f560b561SHong Zhang -init_view : view initial object setup\n\
26aad13602SShrirang Abhyankar -snes_fd : snes with finite difference Jacobian (needed for pdipm)\n\
27628da978Sresundermann -snes_compare_explicit : compare user Jacobian with finite difference Jacobian \n\
2810978b7dSBarry Smith -tao_monitor_constraint_norm : convergence monitor with constraint norm \n\
2910978b7dSBarry Smith -tao_monitor_solution : view exact solution at each iteration\n\
30f560b561SHong 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";
31aad13602SShrirang Abhyankar
32aad13602SShrirang Abhyankar /*
33628da978Sresundermann User-defined application context - contains data needed by the application
34aad13602SShrirang Abhyankar */
35aad13602SShrirang Abhyankar typedef struct {
36aad13602SShrirang Abhyankar PetscInt n; /* Global length of x */
37aad13602SShrirang Abhyankar PetscInt ne; /* Global number of equality constraints */
38aad13602SShrirang Abhyankar PetscInt ni; /* Global number of inequality constraints */
39c8b0c2b5SHansol Suh PetscBool noeqflag, noboundflag, initview;
40aad13602SShrirang Abhyankar Vec x, xl, xu;
41aad13602SShrirang Abhyankar Vec ce, ci, bl, bu, Xseq;
42aad13602SShrirang Abhyankar Mat Ae, Ai, H;
43aad13602SShrirang Abhyankar VecScatter scat;
44aad13602SShrirang Abhyankar } AppCtx;
45aad13602SShrirang Abhyankar
46aad13602SShrirang Abhyankar /* -------- User-defined Routines --------- */
47aad13602SShrirang Abhyankar PetscErrorCode InitializeProblem(AppCtx *);
48aad13602SShrirang Abhyankar PetscErrorCode DestroyProblem(AppCtx *);
49aad13602SShrirang Abhyankar PetscErrorCode FormFunctionGradient(Tao, Vec, PetscReal *, Vec, void *);
5083f04556SHong Zhang PetscErrorCode FormPDIPMHessian(Tao, Vec, Mat, Mat, void *);
51aad13602SShrirang Abhyankar PetscErrorCode FormInequalityConstraints(Tao, Vec, Vec, void *);
52aad13602SShrirang Abhyankar PetscErrorCode FormEqualityConstraints(Tao, Vec, Vec, void *);
53aad13602SShrirang Abhyankar PetscErrorCode FormInequalityJacobian(Tao, Vec, Mat, Mat, void *);
54aad13602SShrirang Abhyankar PetscErrorCode FormEqualityJacobian(Tao, Vec, Mat, Mat, void *);
55aad13602SShrirang Abhyankar
main(int argc,char ** argv)563ba16761SJacob Faibussowitsch int main(int argc, char **argv)
57d71ae5a4SJacob Faibussowitsch {
58aad13602SShrirang Abhyankar Tao tao;
59aad13602SShrirang Abhyankar KSP ksp;
60aad13602SShrirang Abhyankar PC pc;
61aad13602SShrirang Abhyankar AppCtx user; /* application context */
62f560b561SHong Zhang Vec x, G, CI, CE;
63f560b561SHong Zhang PetscMPIInt size;
64f560b561SHong Zhang PetscReal f;
65ab76df0cSBarry Smith PetscBool pdipm;
66aad13602SShrirang Abhyankar
67327415f7SBarry Smith PetscFunctionBeginUser;
68c8025a54SPierre Jolivet PetscCall(PetscInitialize(&argc, &argv, NULL, help));
699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
70ab76df0cSBarry Smith PetscCheck(size <= 2, PETSC_COMM_WORLD, PETSC_ERR_WRONG_MPI_SIZE, "More than 2 processes detected. Example written to use at most 2 processes.");
71aad13602SShrirang Abhyankar
729566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "---- Constrained Problem -----\n"));
739566063dSJacob Faibussowitsch PetscCall(InitializeProblem(&user)); /* sets up problem, function below */
749a09327dSAlp Dener
759566063dSJacob Faibussowitsch PetscCall(TaoCreate(PETSC_COMM_WORLD, &tao));
769a09327dSAlp Dener PetscCall(TaoSetType(tao, TAOALMM));
779a09327dSAlp Dener PetscCall(TaoSetSolution(tao, user.x));
78c8b0c2b5SHansol Suh if (!user.noboundflag) PetscCall(TaoSetVariableBounds(tao, user.xl, user.xu));
799566063dSJacob Faibussowitsch PetscCall(TaoSetObjectiveAndGradient(tao, NULL, FormFunctionGradient, (void *)&user));
809a09327dSAlp Dener PetscCall(TaoSetTolerances(tao, 1.e-4, 0.0, 0.0));
819a09327dSAlp Dener PetscCall(TaoSetConstraintTolerances(tao, 1.e-4, 0.0));
829a09327dSAlp Dener PetscCall(TaoSetMaximumFunctionEvaluations(tao, 1e6));
839566063dSJacob Faibussowitsch PetscCall(TaoSetFromOptions(tao));
849a09327dSAlp Dener
859a09327dSAlp Dener if (!user.noeqflag) {
869a09327dSAlp Dener PetscCall(TaoSetEqualityConstraintsRoutine(tao, user.ce, FormEqualityConstraints, (void *)&user));
879a09327dSAlp Dener PetscCall(TaoSetJacobianEqualityRoutine(tao, user.Ae, user.Ae, FormEqualityJacobian, (void *)&user));
889a09327dSAlp Dener }
899a09327dSAlp Dener PetscCall(TaoSetInequalityConstraintsRoutine(tao, user.ci, FormInequalityConstraints, (void *)&user));
909a09327dSAlp Dener PetscCall(TaoSetJacobianInequalityRoutine(tao, user.Ai, user.Ai, FormInequalityJacobian, (void *)&user));
919a09327dSAlp Dener
929566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)tao, TAOPDIPM, &pdipm));
93661095bbSAlp Dener if (pdipm) {
949a09327dSAlp Dener /*
959a09327dSAlp Dener PDIPM produces an indefinite KKT matrix with some zeros along the diagonal
969a09327dSAlp Dener Inverting this indefinite matrix requires PETSc to be configured with MUMPS
979a09327dSAlp Dener */
98ab76df0cSBarry Smith PetscCheck(PetscDefined(HAVE_MUMPS), PetscObjectComm((PetscObject)tao), PETSC_ERR_SUP, "TAOPDIPM requires PETSc to be configured with MUMPS (--download-mumps)");
999a09327dSAlp Dener PetscCall(TaoGetKSP(tao, &ksp));
1009a09327dSAlp Dener PetscCall(KSPGetPC(ksp, &pc));
1019a09327dSAlp Dener PetscCall(PCFactorSetMatSolverType(pc, MATSOLVERMUMPS));
1029a09327dSAlp Dener PetscCall(KSPSetType(ksp, KSPPREONLY));
10383f04556SHong Zhang PetscCall(PCSetType(pc, PCCHOLESKY));
1049a09327dSAlp Dener PetscCall(KSPSetFromOptions(ksp));
10583f04556SHong Zhang PetscCall(TaoSetHessian(tao, user.H, user.H, FormPDIPMHessian, (void *)&user));
1069a09327dSAlp Dener }
1079a09327dSAlp Dener
1089a09327dSAlp Dener /* Print out an initial view of the problem */
109f560b561SHong Zhang if (user.initview) {
1109566063dSJacob Faibussowitsch PetscCall(TaoSetUp(tao));
1119566063dSJacob Faibussowitsch PetscCall(VecDuplicate(user.x, &G));
1129566063dSJacob Faibussowitsch PetscCall(FormFunctionGradient(tao, user.x, &f, G, (void *)&user));
113c8b0c2b5SHansol Suh if (pdipm) PetscCall(FormPDIPMHessian(tao, user.x, user.H, user.H, (void *)&user));
1149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_WORLD));
11563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\nInitial point X:\n"));
1169566063dSJacob Faibussowitsch PetscCall(VecView(user.x, PETSC_VIEWER_STDOUT_WORLD));
11763a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\nInitial objective f(x) = %g\n", (double)f));
11863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\nInitial gradient and Hessian:\n"));
1199566063dSJacob Faibussowitsch PetscCall(VecView(G, PETSC_VIEWER_STDOUT_WORLD));
120c8b0c2b5SHansol Suh if (pdipm) PetscCall(MatView(user.H, PETSC_VIEWER_STDOUT_WORLD));
1219566063dSJacob Faibussowitsch PetscCall(VecDestroy(&G));
1229566063dSJacob Faibussowitsch PetscCall(FormInequalityJacobian(tao, user.x, user.Ai, user.Ai, (void *)&user));
1239566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(user.Ai, NULL, &CI));
1249566063dSJacob Faibussowitsch PetscCall(FormInequalityConstraints(tao, user.x, CI, (void *)&user));
12563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\nInitial inequality constraints and Jacobian:\n"));
1269566063dSJacob Faibussowitsch PetscCall(VecView(CI, PETSC_VIEWER_STDOUT_WORLD));
1279566063dSJacob Faibussowitsch PetscCall(MatView(user.Ai, PETSC_VIEWER_STDOUT_WORLD));
1289566063dSJacob Faibussowitsch PetscCall(VecDestroy(&CI));
129f560b561SHong Zhang if (!user.noeqflag) {
1309566063dSJacob Faibussowitsch PetscCall(FormEqualityJacobian(tao, user.x, user.Ae, user.Ae, (void *)&user));
1319566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(user.Ae, NULL, &CE));
1329566063dSJacob Faibussowitsch PetscCall(FormEqualityConstraints(tao, user.x, CE, (void *)&user));
13363a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\nInitial equality constraints and Jacobian:\n"));
1349566063dSJacob Faibussowitsch PetscCall(VecView(CE, PETSC_VIEWER_STDOUT_WORLD));
1359566063dSJacob Faibussowitsch PetscCall(MatView(user.Ae, PETSC_VIEWER_STDOUT_WORLD));
1369566063dSJacob Faibussowitsch PetscCall(VecDestroy(&CE));
137f560b561SHong Zhang }
1389566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\n"));
1399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_WORLD));
140f560b561SHong Zhang }
141aad13602SShrirang Abhyankar
1429566063dSJacob Faibussowitsch PetscCall(TaoSolve(tao));
1439566063dSJacob Faibussowitsch PetscCall(TaoGetSolution(tao, &x));
1449a09327dSAlp Dener PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Found solution:\n"));
1459566063dSJacob Faibussowitsch PetscCall(VecView(x, PETSC_VIEWER_STDOUT_WORLD));
146aad13602SShrirang Abhyankar
147aad13602SShrirang Abhyankar /* Free objects */
1489566063dSJacob Faibussowitsch PetscCall(DestroyProblem(&user));
1499566063dSJacob Faibussowitsch PetscCall(TaoDestroy(&tao));
1509566063dSJacob Faibussowitsch PetscCall(PetscFinalize());
1513ba16761SJacob Faibussowitsch return PETSC_SUCCESS;
152aad13602SShrirang Abhyankar }
153aad13602SShrirang Abhyankar
InitializeProblem(AppCtx * user)154d71ae5a4SJacob Faibussowitsch PetscErrorCode InitializeProblem(AppCtx *user)
155d71ae5a4SJacob Faibussowitsch {
156aad13602SShrirang Abhyankar PetscMPIInt size;
157aad13602SShrirang Abhyankar PetscMPIInt rank;
158aad13602SShrirang Abhyankar PetscInt nloc, neloc, niloc;
159aad13602SShrirang Abhyankar
160aad13602SShrirang Abhyankar PetscFunctionBegin;
1619566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
1629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1638e58fa1dSresundermann user->noeqflag = PETSC_FALSE;
164c8b0c2b5SHansol Suh user->noboundflag = PETSC_FALSE;
1659566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-no_eq", &user->noeqflag, NULL));
166c8b0c2b5SHansol Suh PetscCall(PetscOptionsGetBool(NULL, NULL, "-no_bound", &user->noboundflag, NULL));
167f560b561SHong Zhang user->initview = PETSC_FALSE;
1689566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-init_view", &user->initview, NULL));
169628da978Sresundermann
170f560b561SHong Zhang /* Tell user the correct solution, not an error checking */
1719a09327dSAlp Dener if (!user->noeqflag) {
172c8b0c2b5SHansol Suh /* With equality constraint, bound or no bound makes no different to the solution */
1739a09327dSAlp Dener PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Expected solution: f(1, 1) = -2\n"));
1749a09327dSAlp Dener } else {
175c8b0c2b5SHansol Suh if (user->noboundflag) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Expected solution (-no_eq, -no_bound): f(2.05655, 3.22938) = -9.05728\n"));
176c8b0c2b5SHansol Suh else PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Expected solution (-no_eq): f(1.73205, 2) = -7.3923\n"));
1778e58fa1dSresundermann }
178aad13602SShrirang Abhyankar
1792d4ee042Sprj- /* create vector x and set initial values */
180aad13602SShrirang Abhyankar user->n = 2; /* global length */
181f560b561SHong Zhang nloc = (size == 1) ? user->n : 1;
1829566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_WORLD, &user->x));
1839566063dSJacob Faibussowitsch PetscCall(VecSetSizes(user->x, nloc, user->n));
1849566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(user->x));
1859a09327dSAlp Dener PetscCall(VecSet(user->x, 0.0));
186aad13602SShrirang Abhyankar
187aad13602SShrirang Abhyankar /* create and set lower and upper bound vectors */
1889566063dSJacob Faibussowitsch PetscCall(VecDuplicate(user->x, &user->xl));
1899566063dSJacob Faibussowitsch PetscCall(VecDuplicate(user->x, &user->xu));
1909566063dSJacob Faibussowitsch PetscCall(VecSet(user->xl, -1.0));
1919566063dSJacob Faibussowitsch PetscCall(VecSet(user->xu, 2.0));
192aad13602SShrirang Abhyankar
193aad13602SShrirang Abhyankar /* create scater to zero */
1949566063dSJacob Faibussowitsch PetscCall(VecScatterCreateToZero(user->x, &user->scat, &user->Xseq));
195aad13602SShrirang Abhyankar
196aad13602SShrirang Abhyankar user->ne = 1;
197628da978Sresundermann user->ni = 2;
198aad13602SShrirang Abhyankar neloc = (rank == 0) ? user->ne : 0;
199f560b561SHong Zhang niloc = (size == 1) ? user->ni : 1;
200aad13602SShrirang Abhyankar
2018e58fa1dSresundermann if (!user->noeqflag) {
2029566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_WORLD, &user->ce)); /* a 1x1 vec for equality constraints */
2039566063dSJacob Faibussowitsch PetscCall(VecSetSizes(user->ce, neloc, user->ne));
2049566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(user->ce));
2059566063dSJacob Faibussowitsch PetscCall(VecSetUp(user->ce));
2068e58fa1dSresundermann }
207628da978Sresundermann
2089566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_WORLD, &user->ci)); /* a 2x1 vec for inequality constraints */
2099566063dSJacob Faibussowitsch PetscCall(VecSetSizes(user->ci, niloc, user->ni));
2109566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(user->ci));
2119566063dSJacob Faibussowitsch PetscCall(VecSetUp(user->ci));
212aad13602SShrirang Abhyankar
213baca6076SPierre Jolivet /* nexn & nixn matrices for equally and inequalty constraints */
2148e58fa1dSresundermann if (!user->noeqflag) {
2159566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &user->Ae));
2169566063dSJacob Faibussowitsch PetscCall(MatSetSizes(user->Ae, neloc, nloc, user->ne, user->n));
2179566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(user->Ae));
2189566063dSJacob Faibussowitsch PetscCall(MatSetUp(user->Ae));
2198e58fa1dSresundermann }
2208e58fa1dSresundermann
2219566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &user->Ai));
2229566063dSJacob Faibussowitsch PetscCall(MatSetSizes(user->Ai, niloc, nloc, user->ni, user->n));
2239566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(user->Ai));
2249566063dSJacob Faibussowitsch PetscCall(MatSetUp(user->Ai));
225628da978Sresundermann
2269566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &user->H));
2279566063dSJacob Faibussowitsch PetscCall(MatSetSizes(user->H, nloc, nloc, user->n, user->n));
2289566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(user->H));
2299566063dSJacob Faibussowitsch PetscCall(MatSetUp(user->H));
2303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
231aad13602SShrirang Abhyankar }
232aad13602SShrirang Abhyankar
DestroyProblem(AppCtx * user)233d71ae5a4SJacob Faibussowitsch PetscErrorCode DestroyProblem(AppCtx *user)
234d71ae5a4SJacob Faibussowitsch {
235aad13602SShrirang Abhyankar PetscFunctionBegin;
23648a46eb9SPierre Jolivet if (!user->noeqflag) PetscCall(MatDestroy(&user->Ae));
2379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user->Ai));
2389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user->H));
239aad13602SShrirang Abhyankar
2409566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->x));
24148a46eb9SPierre Jolivet if (!user->noeqflag) PetscCall(VecDestroy(&user->ce));
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));
2473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
248aad13602SShrirang Abhyankar }
249aad13602SShrirang Abhyankar
250628da978Sresundermann /* Evaluate
251628da978Sresundermann f(x) = (x0 - 2)^2 + (x1 - 2)^2 - 2*(x0 + x1)
25283f04556SHong Zhang G = grad f = [2*(x0 - 2) - 2, 2*(x1 - 2) - 2] = 2*X - 6
253aad13602SShrirang Abhyankar */
FormFunctionGradient(Tao tao,Vec X,PetscReal * f,Vec G,PetscCtx ctx)254*2a8381b2SBarry Smith PetscErrorCode FormFunctionGradient(Tao tao, Vec X, PetscReal *f, Vec G, PetscCtx ctx)
255d71ae5a4SJacob Faibussowitsch {
256aad13602SShrirang Abhyankar const PetscScalar *x;
257aad13602SShrirang Abhyankar MPI_Comm comm;
258aad13602SShrirang Abhyankar PetscMPIInt rank;
259aad13602SShrirang Abhyankar PetscReal fin;
260aad13602SShrirang Abhyankar AppCtx *user = (AppCtx *)ctx;
261aad13602SShrirang Abhyankar Vec Xseq = user->Xseq;
262aad13602SShrirang Abhyankar VecScatter scat = user->scat;
263aad13602SShrirang Abhyankar
264aad13602SShrirang Abhyankar PetscFunctionBegin;
26583f04556SHong Zhang /* f = (x0 - 2)^2 + (x1 - 2)^2 - 2*(x0 + x1) */
2669566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)tao, &comm));
2679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
268aad13602SShrirang Abhyankar
2699566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(scat, X, Xseq, INSERT_VALUES, SCATTER_FORWARD));
2709566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(scat, X, Xseq, INSERT_VALUES, SCATTER_FORWARD));
271aad13602SShrirang Abhyankar
272aad13602SShrirang Abhyankar fin = 0.0;
273dd400576SPatrick Sanan if (rank == 0) {
2749566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(Xseq, &x));
275aad13602SShrirang Abhyankar fin = (x[0] - 2.0) * (x[0] - 2.0) + (x[1] - 2.0) * (x[1] - 2.0) - 2.0 * (x[0] + x[1]);
2769566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(Xseq, &x));
277aad13602SShrirang Abhyankar }
278462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&fin, f, 1, MPIU_REAL, MPIU_SUM, comm));
27983f04556SHong Zhang
28083f04556SHong Zhang /* G = 2*X - 6 */
28183f04556SHong Zhang PetscCall(VecSet(G, -6.0));
28283f04556SHong Zhang PetscCall(VecAXPY(G, 2.0, X));
2833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
284aad13602SShrirang Abhyankar }
285aad13602SShrirang Abhyankar
28683f04556SHong Zhang /* Evaluate PDIPM Hessian, see Eqn(22) in http://doi.org/10.1049/gtd2.12708
28783f04556SHong Zhang H = Wxx = fxx + Jacobian(grad g^T*DE) - Jacobian(grad h^T*DI)]
28883f04556SHong Zhang = fxx + Jacobin([2*x0; 1]de[0]) - Jacobian([2*x0, -2*x0; -1, 1][di[0] di[1]]^T)
28983f04556SHong Zhang = [2 0; 0 2] + [2*de[0] 0; 0 0] - [2*di[0]-2*di[1], 0; 0, 0]
290628da978Sresundermann = [ 2*(1+de[0]-di[0]+di[1]), 0;
291628da978Sresundermann 0, 2]
292628da978Sresundermann */
FormPDIPMHessian(Tao tao,Vec x,Mat H,Mat Hpre,PetscCtx ctx)293*2a8381b2SBarry Smith PetscErrorCode FormPDIPMHessian(Tao tao, Vec x, Mat H, Mat Hpre, PetscCtx ctx)
294d71ae5a4SJacob Faibussowitsch {
295aad13602SShrirang Abhyankar AppCtx *user = (AppCtx *)ctx;
296aad13602SShrirang Abhyankar Vec DE, DI;
297aad13602SShrirang Abhyankar const PetscScalar *de, *di;
298aad13602SShrirang Abhyankar PetscInt zero = 0, one = 1;
299aad13602SShrirang Abhyankar PetscScalar two = 2.0;
300aad13602SShrirang Abhyankar PetscScalar val = 0.0;
301f560b561SHong Zhang Vec Deseq, Diseq;
302f560b561SHong Zhang VecScatter Descat, Discat;
303aad13602SShrirang Abhyankar PetscMPIInt rank;
304aad13602SShrirang Abhyankar MPI_Comm comm;
305aad13602SShrirang Abhyankar
306aad13602SShrirang Abhyankar PetscFunctionBegin;
3079566063dSJacob Faibussowitsch PetscCall(TaoGetDualVariables(tao, &DE, &DI));
308aad13602SShrirang Abhyankar
3099566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)tao, &comm));
3109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
311aad13602SShrirang Abhyankar
3128e58fa1dSresundermann if (!user->noeqflag) {
3139566063dSJacob Faibussowitsch PetscCall(VecScatterCreateToZero(DE, &Descat, &Deseq));
3149566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Descat, DE, Deseq, INSERT_VALUES, SCATTER_FORWARD));
3159566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Descat, DE, Deseq, INSERT_VALUES, SCATTER_FORWARD));
3168e58fa1dSresundermann }
3179566063dSJacob Faibussowitsch PetscCall(VecScatterCreateToZero(DI, &Discat, &Diseq));
3189566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Discat, DI, Diseq, INSERT_VALUES, SCATTER_FORWARD));
3199566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Discat, DI, Diseq, INSERT_VALUES, SCATTER_FORWARD));
320aad13602SShrirang Abhyankar
321dd400576SPatrick Sanan if (rank == 0) {
322ac530a7eSPierre Jolivet if (!user->noeqflag) PetscCall(VecGetArrayRead(Deseq, &de)); /* places equality constraint dual into array */
3239566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(Diseq, &di)); /* places inequality constraint dual into array */
324628da978Sresundermann
3258e58fa1dSresundermann if (!user->noeqflag) {
326628da978Sresundermann val = 2.0 * (1 + de[0] - di[0] + di[1]);
3279566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(Deseq, &de));
3289566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(Diseq, &di));
3298e58fa1dSresundermann } else {
330628da978Sresundermann val = 2.0 * (1 - di[0] + di[1]);
3318e58fa1dSresundermann }
3329566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(Diseq, &di));
3339566063dSJacob Faibussowitsch PetscCall(MatSetValues(H, 1, &zero, 1, &zero, &val, INSERT_VALUES));
3349566063dSJacob Faibussowitsch PetscCall(MatSetValues(H, 1, &one, 1, &one, &two, INSERT_VALUES));
335aad13602SShrirang Abhyankar }
3369566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(H, MAT_FINAL_ASSEMBLY));
3379566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(H, MAT_FINAL_ASSEMBLY));
3388e58fa1dSresundermann if (!user->noeqflag) {
3399566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&Descat));
3409566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Deseq));
3418e58fa1dSresundermann }
3429566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&Discat));
3439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Diseq));
3443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
345aad13602SShrirang Abhyankar }
346aad13602SShrirang Abhyankar
347628da978Sresundermann /* Evaluate
348628da978Sresundermann h = [ x0^2 - x1;
349628da978Sresundermann 1 -(x0^2 - x1)]
350628da978Sresundermann */
FormInequalityConstraints(Tao tao,Vec X,Vec CI,PetscCtx ctx)351*2a8381b2SBarry Smith PetscErrorCode FormInequalityConstraints(Tao tao, Vec X, Vec CI, PetscCtx ctx)
352d71ae5a4SJacob Faibussowitsch {
353aad13602SShrirang Abhyankar const PetscScalar *x;
354aad13602SShrirang Abhyankar PetscScalar ci;
355aad13602SShrirang Abhyankar MPI_Comm comm;
356aad13602SShrirang Abhyankar PetscMPIInt rank;
357aad13602SShrirang Abhyankar AppCtx *user = (AppCtx *)ctx;
358aad13602SShrirang Abhyankar Vec Xseq = user->Xseq;
359aad13602SShrirang Abhyankar VecScatter scat = user->scat;
360aad13602SShrirang Abhyankar
361aad13602SShrirang Abhyankar PetscFunctionBegin;
3629566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)tao, &comm));
3639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
364aad13602SShrirang Abhyankar
3659566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(scat, X, Xseq, INSERT_VALUES, SCATTER_FORWARD));
3669566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(scat, X, Xseq, INSERT_VALUES, SCATTER_FORWARD));
367aad13602SShrirang Abhyankar
368dd400576SPatrick Sanan if (rank == 0) {
3699566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(Xseq, &x));
370aad13602SShrirang Abhyankar ci = x[0] * x[0] - x[1];
3719566063dSJacob Faibussowitsch PetscCall(VecSetValue(CI, 0, ci, INSERT_VALUES));
372aad13602SShrirang Abhyankar ci = -x[0] * x[0] + x[1] + 1.0;
3739566063dSJacob Faibussowitsch PetscCall(VecSetValue(CI, 1, ci, INSERT_VALUES));
3749566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(Xseq, &x));
375aad13602SShrirang Abhyankar }
3769566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(CI));
3779566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(CI));
3783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
379aad13602SShrirang Abhyankar }
380aad13602SShrirang Abhyankar
381628da978Sresundermann /* Evaluate
382628da978Sresundermann g = [ x0^2 + x1 - 2]
383628da978Sresundermann */
FormEqualityConstraints(Tao tao,Vec X,Vec CE,PetscCtx ctx)384*2a8381b2SBarry Smith PetscErrorCode FormEqualityConstraints(Tao tao, Vec X, Vec CE, PetscCtx ctx)
385d71ae5a4SJacob Faibussowitsch {
386aad13602SShrirang Abhyankar const PetscScalar *x;
387aad13602SShrirang Abhyankar PetscScalar ce;
388aad13602SShrirang Abhyankar MPI_Comm comm;
389aad13602SShrirang Abhyankar PetscMPIInt rank;
390aad13602SShrirang Abhyankar AppCtx *user = (AppCtx *)ctx;
391aad13602SShrirang Abhyankar Vec Xseq = user->Xseq;
392aad13602SShrirang Abhyankar VecScatter scat = user->scat;
393aad13602SShrirang Abhyankar
394aad13602SShrirang Abhyankar PetscFunctionBegin;
3959566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)tao, &comm));
3969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
397aad13602SShrirang Abhyankar
3989566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(scat, X, Xseq, INSERT_VALUES, SCATTER_FORWARD));
3999566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(scat, X, Xseq, INSERT_VALUES, SCATTER_FORWARD));
400aad13602SShrirang Abhyankar
401dd400576SPatrick Sanan if (rank == 0) {
4029566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(Xseq, &x));
403aad13602SShrirang Abhyankar ce = x[0] * x[0] + x[1] - 2.0;
4049566063dSJacob Faibussowitsch PetscCall(VecSetValue(CE, 0, ce, INSERT_VALUES));
4059566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(Xseq, &x));
406aad13602SShrirang Abhyankar }
4079566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(CE));
4089566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(CE));
4093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
410aad13602SShrirang Abhyankar }
411aad13602SShrirang Abhyankar
412628da978Sresundermann /*
413628da978Sresundermann grad h = [ 2*x0, -1;
414628da978Sresundermann -2*x0, 1]
415628da978Sresundermann */
FormInequalityJacobian(Tao tao,Vec X,Mat JI,Mat JIpre,PetscCtx ctx)416*2a8381b2SBarry Smith PetscErrorCode FormInequalityJacobian(Tao tao, Vec X, Mat JI, Mat JIpre, PetscCtx ctx)
417d71ae5a4SJacob Faibussowitsch {
418aad13602SShrirang Abhyankar AppCtx *user = (AppCtx *)ctx;
419f560b561SHong Zhang PetscInt zero = 0, one = 1, cols[2];
420aad13602SShrirang Abhyankar PetscScalar vals[2];
421aad13602SShrirang Abhyankar const PetscScalar *x;
422aad13602SShrirang Abhyankar Vec Xseq = user->Xseq;
423aad13602SShrirang Abhyankar VecScatter scat = user->scat;
424aad13602SShrirang Abhyankar MPI_Comm comm;
425aad13602SShrirang Abhyankar PetscMPIInt rank;
426aad13602SShrirang Abhyankar
427aad13602SShrirang Abhyankar PetscFunctionBegin;
4289566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)tao, &comm));
4299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
4309566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(scat, X, Xseq, INSERT_VALUES, SCATTER_FORWARD));
4319566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(scat, X, Xseq, INSERT_VALUES, SCATTER_FORWARD));
432aad13602SShrirang Abhyankar
4339566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(Xseq, &x));
434c5853193SPierre Jolivet if (rank == 0) {
4359371c9d4SSatish Balay cols[0] = 0;
4369371c9d4SSatish Balay cols[1] = 1;
4379371c9d4SSatish Balay vals[0] = 2 * x[0];
4389371c9d4SSatish Balay vals[1] = -1.0;
4399566063dSJacob Faibussowitsch PetscCall(MatSetValues(JI, 1, &zero, 2, cols, vals, INSERT_VALUES));
4409371c9d4SSatish Balay vals[0] = -2 * x[0];
4419371c9d4SSatish Balay 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));
4473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
448aad13602SShrirang Abhyankar }
449aad13602SShrirang Abhyankar
450628da978Sresundermann /*
45183f04556SHong Zhang grad g = [2*x0, 1.0]
452628da978Sresundermann */
FormEqualityJacobian(Tao tao,Vec X,Mat JE,Mat JEpre,PetscCtx ctx)453*2a8381b2SBarry Smith PetscErrorCode FormEqualityJacobian(Tao tao, Vec X, Mat JE, Mat JEpre, PetscCtx ctx)
454d71ae5a4SJacob Faibussowitsch {
455f560b561SHong Zhang PetscInt zero = 0, cols[2];
456aad13602SShrirang Abhyankar PetscScalar vals[2];
457aad13602SShrirang Abhyankar const PetscScalar *x;
458aad13602SShrirang Abhyankar PetscMPIInt rank;
459aad13602SShrirang Abhyankar MPI_Comm comm;
460aad13602SShrirang Abhyankar
461aad13602SShrirang Abhyankar PetscFunctionBegin;
4629566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)tao, &comm));
4639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
464aad13602SShrirang Abhyankar
465dd400576SPatrick Sanan if (rank == 0) {
4669566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(X, &x));
4679371c9d4SSatish Balay cols[0] = 0;
4689371c9d4SSatish Balay cols[1] = 1;
4699371c9d4SSatish Balay vals[0] = 2 * x[0];
4709371c9d4SSatish Balay vals[1] = 1.0;
4719566063dSJacob Faibussowitsch PetscCall(MatSetValues(JE, 1, &zero, 2, cols, vals, INSERT_VALUES));
4729566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(X, &x));
473aad13602SShrirang Abhyankar }
4749566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(JE, MAT_FINAL_ASSEMBLY));
4759566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(JE, MAT_FINAL_ASSEMBLY));
4763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
477aad13602SShrirang Abhyankar }
478aad13602SShrirang Abhyankar
479aad13602SShrirang Abhyankar /*TEST
480aad13602SShrirang Abhyankar
481aad13602SShrirang Abhyankar build:
482f560b561SHong Zhang requires: !complex !defined(PETSC_USE_CXX)
483aad13602SShrirang Abhyankar
484aad13602SShrirang Abhyankar test:
4859a09327dSAlp Dener args: -tao_converged_reason -tao_gatol 1.e-6 -tao_type pdipm -tao_pdipm_kkt_shift_pd
486910b42cbSStefano Zampini requires: mumps !single
4879a09327dSAlp Dener filter: sed -e "s/CONVERGED_GATOL iterations *[0-9]\{1,\}/CONVERGED_GATOL/g"
488aad13602SShrirang Abhyankar
489aad13602SShrirang Abhyankar test:
49083f04556SHong Zhang suffix: pdipm_2
49183f04556SHong Zhang requires: mumps
49283f04556SHong Zhang nsize: 2
49383f04556SHong Zhang args: -tao_converged_reason -tao_gatol 1.e-6 -tao_type pdipm
49483f04556SHong Zhang filter: sed -e "s/CONVERGED_GATOL iterations *[0-9]\{1,\}/CONVERGED_GATOL/g"
49583f04556SHong Zhang
49683f04556SHong Zhang test:
497aad13602SShrirang Abhyankar suffix: 2
4989a09327dSAlp Dener args: -tao_converged_reason
4999a09327dSAlp Dener filter: sed -e "s/CONVERGED_GATOL iterations *[0-9]\{1,\}/CONVERGED_GATOL/g"
500aad13602SShrirang Abhyankar
5018e58fa1dSresundermann test:
5028e58fa1dSresundermann suffix: 3
5038e58fa1dSresundermann args: -tao_converged_reason -no_eq
5049a09327dSAlp Dener filter: sed -e "s/CONVERGED_GATOL iterations *[0-9]\{1,\}/CONVERGED_GATOL/g"
5058e58fa1dSresundermann
5068e58fa1dSresundermann test:
5078e58fa1dSresundermann suffix: 4
5089a09327dSAlp Dener args: -tao_converged_reason -tao_almm_type classic
5099a09327dSAlp Dener requires: !single
5109a09327dSAlp Dener filter: sed -e "s/CONVERGED_GATOL iterations *[0-9]\{1,\}/CONVERGED_GATOL/g"
5118e58fa1dSresundermann
512661095bbSAlp Dener test:
513661095bbSAlp Dener suffix: 5
514c8b0c2b5SHansol Suh args: -tao_converged_reason -tao_almm_type classic -no_eq
515c8b0c2b5SHansol Suh requires: !single
5169a09327dSAlp Dener filter: sed -e "s/CONVERGED_GATOL iterations *[0-9]\{1,\}/CONVERGED_GATOL/g"
517661095bbSAlp Dener
518661095bbSAlp Dener test:
519661095bbSAlp Dener suffix: 6
5209a09327dSAlp Dener args: -tao_converged_reason -tao_almm_subsolver_tao_type bqnktr
5219a09327dSAlp Dener filter: sed -e "s/CONVERGED_GATOL iterations *[0-9]\{1,\}/CONVERGED_GATOL/g"
522661095bbSAlp Dener
523661095bbSAlp Dener test:
524661095bbSAlp Dener suffix: 7
5259a09327dSAlp Dener args: -tao_converged_reason -tao_almm_subsolver_tao_type bncg
5269a09327dSAlp Dener filter: sed -e "s/CONVERGED_GATOL iterations *[0-9]\{1,\}/CONVERGED_GATOL/g"
527661095bbSAlp Dener
528661095bbSAlp Dener test:
529661095bbSAlp Dener suffix: 8
530661095bbSAlp Dener nsize: 2
5319a09327dSAlp Dener args: -tao_converged_reason
5329a09327dSAlp Dener filter: sed -e "s/CONVERGED_GATOL iterations *[0-9]\{1,\}/CONVERGED_GATOL/g"
533661095bbSAlp Dener
534661095bbSAlp Dener test:
535661095bbSAlp Dener suffix: 9
536661095bbSAlp Dener nsize: 2
5379a09327dSAlp Dener args: -tao_converged_reason -vec_type cuda -mat_type aijcusparse
5389a09327dSAlp Dener requires: cuda
5399a09327dSAlp Dener filter: sed -e "s/CONVERGED_GATOL iterations *[0-9]\{1,\}/CONVERGED_GATOL/g"
540661095bbSAlp Dener
541c8b0c2b5SHansol Suh test:
542c8b0c2b5SHansol Suh suffix: 10
543c8b0c2b5SHansol Suh args: -tao_converged_reason -tao_almm_type classic -no_eq -no_bound
544c8b0c2b5SHansol Suh requires: !single
545c8b0c2b5SHansol Suh filter: sed -e "s/CONVERGED_GATOL iterations *[0-9]\{1,\}/CONVERGED_GATOL/g"
546c8b0c2b5SHansol Suh
547c8b0c2b5SHansol Suh test:
548c8b0c2b5SHansol Suh suffix: 11
549c8b0c2b5SHansol Suh args: -tao_converged_reason -tao_almm_type classic -no_bound
550c8b0c2b5SHansol Suh requires: !single
551c8b0c2b5SHansol Suh filter: sed -e "s/CONVERGED_GATOL iterations *[0-9]\{1,\}/CONVERGED_GATOL/g"
552c8b0c2b5SHansol Suh
553c8b0c2b5SHansol Suh test:
554c8b0c2b5SHansol Suh suffix: 12
555c8b0c2b5SHansol Suh args: -tao_converged_reason -tao_almm_type phr -no_eq -no_bound
556c8b0c2b5SHansol Suh requires: !single
557c8b0c2b5SHansol Suh filter: sed -e "s/CONVERGED_GATOL iterations *[0-9]\{1,\}/CONVERGED_GATOL/g"
558c8b0c2b5SHansol Suh
559c8b0c2b5SHansol Suh test:
560c8b0c2b5SHansol Suh suffix: 13
561c8b0c2b5SHansol Suh args: -tao_converged_reason -tao_almm_type phr -no_bound
562c8b0c2b5SHansol Suh requires: !single
563c8b0c2b5SHansol Suh filter: sed -e "s/CONVERGED_GATOL iterations *[0-9]\{1,\}/CONVERGED_GATOL/g"
564c8b0c2b5SHansol Suh
565aad13602SShrirang Abhyankar TEST*/
566