xref: /petsc/src/tao/constrained/tutorials/maros.c (revision 4e8208cbcbc709572b8abe32f33c78b69c819375) !
1c4762a1bSJed Brown /* Program usage: mpiexec -n 1 maros1 [-help] [all TAO options] */
2c4762a1bSJed Brown 
3c4762a1bSJed Brown /* ----------------------------------------------------------------------
4c4762a1bSJed Brown TODO Explain maros example
5c4762a1bSJed Brown ---------------------------------------------------------------------- */
6c4762a1bSJed Brown 
7c4762a1bSJed Brown #include <petsctao.h>
8c4762a1bSJed Brown 
9c4762a1bSJed Brown static char help[] = "";
10c4762a1bSJed Brown 
11c4762a1bSJed Brown /*
12c4762a1bSJed Brown    User-defined application context - contains data needed by the
13c4762a1bSJed Brown    application-provided call-back routines, FormFunction(),
14c4762a1bSJed Brown    FormGradient(), and FormHessian().
15c4762a1bSJed Brown */
16c4762a1bSJed Brown 
17c4762a1bSJed Brown /*
18c4762a1bSJed Brown    x,d in R^n
19c4762a1bSJed Brown    f in R
20c4762a1bSJed Brown    bin in R^mi
21c4762a1bSJed Brown    beq in R^me
22c4762a1bSJed Brown    Aeq in R^(me x n)
23c4762a1bSJed Brown    Ain in R^(mi x n)
24c4762a1bSJed Brown    H in R^(n x n)
25c4762a1bSJed Brown    min f=(1/2)*x'*H*x + d'*x
26c4762a1bSJed Brown    s.t.  Aeq*x == beq
27c4762a1bSJed Brown          Ain*x >= bin
28c4762a1bSJed Brown */
29c4762a1bSJed Brown typedef struct {
30c4762a1bSJed Brown   char     name[32];
31c4762a1bSJed Brown   PetscInt n;  /* Length x */
32c4762a1bSJed Brown   PetscInt me; /* number of equality constraints */
33c4762a1bSJed Brown   PetscInt mi; /* number of inequality constraints */
34c4762a1bSJed Brown   PetscInt m;  /* me+mi */
35c4762a1bSJed Brown   Mat      Aeq, Ain, H;
36c4762a1bSJed Brown   Vec      beq, bin, d;
37c4762a1bSJed Brown } AppCtx;
38c4762a1bSJed Brown 
39c4762a1bSJed Brown /* -------- User-defined Routines --------- */
40c4762a1bSJed Brown 
41c4762a1bSJed Brown PetscErrorCode InitializeProblem(AppCtx *);
42c4762a1bSJed Brown PetscErrorCode DestroyProblem(AppCtx *);
43c4762a1bSJed Brown PetscErrorCode FormFunctionGradient(Tao, Vec, PetscReal *, Vec, void *);
44c4762a1bSJed Brown PetscErrorCode FormHessian(Tao, Vec, Mat, Mat, void *);
45c4762a1bSJed Brown PetscErrorCode FormInequalityConstraints(Tao, Vec, Vec, void *);
46c4762a1bSJed Brown PetscErrorCode FormEqualityConstraints(Tao, Vec, Vec, void *);
47c4762a1bSJed Brown PetscErrorCode FormInequalityJacobian(Tao, Vec, Mat, Mat, void *);
48c4762a1bSJed Brown PetscErrorCode FormEqualityJacobian(Tao, Vec, Mat, Mat, void *);
49c4762a1bSJed Brown 
main(int argc,char ** argv)503ba16761SJacob Faibussowitsch int main(int argc, char **argv)
51d71ae5a4SJacob Faibussowitsch {
52c4762a1bSJed Brown   PetscMPIInt        size;
53c4762a1bSJed Brown   Vec                x; /* solution */
54c4762a1bSJed Brown   KSP                ksp;
55c4762a1bSJed Brown   PC                 pc;
56c4762a1bSJed Brown   Vec                ceq, cin;
57c4762a1bSJed Brown   PetscBool          flg; /* A return value when checking for use options */
58c4762a1bSJed Brown   Tao                tao; /* Tao solver context */
59c4762a1bSJed Brown   TaoConvergedReason reason;
60c4762a1bSJed Brown   AppCtx             user; /* application context */
61c4762a1bSJed Brown 
62c4762a1bSJed Brown   /* Initialize TAO,PETSc */
63327415f7SBarry Smith   PetscFunctionBeginUser;
64c8025a54SPierre Jolivet   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
659566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
66c4762a1bSJed Brown   /* Specify default parameters for the problem, check for command-line overrides */
679566063dSJacob Faibussowitsch   PetscCall(PetscStrncpy(user.name, "HS21", sizeof(user.name)));
689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetString(NULL, NULL, "-cutername", user.name, sizeof(user.name), &flg));
69c4762a1bSJed Brown 
709566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\n---- MAROS Problem %s -----\n", user.name));
719566063dSJacob Faibussowitsch   PetscCall(InitializeProblem(&user));
729566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(user.d, &x));
739566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(user.beq, &ceq));
749566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(user.bin, &cin));
759566063dSJacob Faibussowitsch   PetscCall(VecSet(x, 1.0));
76c4762a1bSJed Brown 
779566063dSJacob Faibussowitsch   PetscCall(TaoCreate(PETSC_COMM_WORLD, &tao));
789566063dSJacob Faibussowitsch   PetscCall(TaoSetType(tao, TAOIPM));
799566063dSJacob Faibussowitsch   PetscCall(TaoSetSolution(tao, x));
809566063dSJacob Faibussowitsch   PetscCall(TaoSetObjectiveAndGradient(tao, NULL, FormFunctionGradient, (void *)&user));
819566063dSJacob Faibussowitsch   PetscCall(TaoSetEqualityConstraintsRoutine(tao, ceq, FormEqualityConstraints, (void *)&user));
829566063dSJacob Faibussowitsch   PetscCall(TaoSetInequalityConstraintsRoutine(tao, cin, FormInequalityConstraints, (void *)&user));
839566063dSJacob Faibussowitsch   PetscCall(TaoSetInequalityBounds(tao, user.bin, NULL));
849566063dSJacob Faibussowitsch   PetscCall(TaoSetJacobianEqualityRoutine(tao, user.Aeq, user.Aeq, FormEqualityJacobian, (void *)&user));
859566063dSJacob Faibussowitsch   PetscCall(TaoSetJacobianInequalityRoutine(tao, user.Ain, user.Ain, FormInequalityJacobian, (void *)&user));
869566063dSJacob Faibussowitsch   PetscCall(TaoSetHessian(tao, user.H, user.H, FormHessian, (void *)&user));
879566063dSJacob Faibussowitsch   PetscCall(TaoGetKSP(tao, &ksp));
889566063dSJacob Faibussowitsch   PetscCall(KSPGetPC(ksp, &pc));
899566063dSJacob Faibussowitsch   PetscCall(PCSetType(pc, PCLU));
90c4762a1bSJed Brown   /*
91c4762a1bSJed Brown       This algorithm produces matrices with zeros along the diagonal therefore we need to use
92c4762a1bSJed Brown     SuperLU which does partial pivoting
93c4762a1bSJed Brown   */
949566063dSJacob Faibussowitsch   PetscCall(PCFactorSetMatSolverType(pc, MATSOLVERSUPERLU));
959566063dSJacob Faibussowitsch   PetscCall(KSPSetType(ksp, KSPPREONLY));
969566063dSJacob Faibussowitsch   PetscCall(TaoSetTolerances(tao, 0, 0, 0));
97c4762a1bSJed Brown 
989566063dSJacob Faibussowitsch   PetscCall(TaoSetFromOptions(tao));
999566063dSJacob Faibussowitsch   PetscCall(TaoSolve(tao));
1009566063dSJacob Faibussowitsch   PetscCall(TaoGetConvergedReason(tao, &reason));
101c4762a1bSJed Brown   if (reason < 0) {
1029566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(MPI_COMM_WORLD, "TAO failed to converge due to %s.\n", TaoConvergedReasons[reason]));
103c4762a1bSJed Brown   } else {
1049566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(MPI_COMM_WORLD, "Optimization completed with status %s.\n", TaoConvergedReasons[reason]));
105c4762a1bSJed Brown   }
106c4762a1bSJed Brown 
1079566063dSJacob Faibussowitsch   PetscCall(DestroyProblem(&user));
1089566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
1099566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ceq));
1109566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cin));
1119566063dSJacob Faibussowitsch   PetscCall(TaoDestroy(&tao));
112c4762a1bSJed Brown 
1139566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
114b122ec5aSJacob Faibussowitsch   return 0;
115c4762a1bSJed Brown }
116c4762a1bSJed Brown 
InitializeProblem(AppCtx * user)117d71ae5a4SJacob Faibussowitsch PetscErrorCode InitializeProblem(AppCtx *user)
118d71ae5a4SJacob Faibussowitsch {
119c4762a1bSJed Brown   PetscViewer loader;
120c4762a1bSJed Brown   MPI_Comm    comm;
121c4762a1bSJed Brown   PetscInt    nrows, ncols, i;
122c4762a1bSJed Brown   PetscScalar one = 1.0;
123c4762a1bSJed Brown   char        filebase[128];
124c4762a1bSJed Brown   char        filename[128];
125c4762a1bSJed Brown 
126c4762a1bSJed Brown   PetscFunctionBegin;
127c4762a1bSJed Brown   comm = PETSC_COMM_WORLD;
1289566063dSJacob Faibussowitsch   PetscCall(PetscStrncpy(filebase, user->name, sizeof(filebase)));
1299566063dSJacob Faibussowitsch   PetscCall(PetscStrlcat(filebase, "/", sizeof(filebase)));
1309566063dSJacob Faibussowitsch   PetscCall(PetscStrncpy(filename, filebase, sizeof(filename)));
1319566063dSJacob Faibussowitsch   PetscCall(PetscStrlcat(filename, "f", sizeof(filename)));
1329566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryOpen(comm, filename, FILE_MODE_READ, &loader));
133c4762a1bSJed Brown 
1349566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm, &user->d));
1359566063dSJacob Faibussowitsch   PetscCall(VecLoad(user->d, loader));
1369566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&loader));
1379566063dSJacob Faibussowitsch   PetscCall(VecGetSize(user->d, &nrows));
1389566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(user->d));
139c4762a1bSJed Brown   user->n = nrows;
140c4762a1bSJed Brown 
1419566063dSJacob Faibussowitsch   PetscCall(PetscStrncpy(filename, filebase, sizeof(filename)));
1429566063dSJacob Faibussowitsch   PetscCall(PetscStrlcat(filename, "H", sizeof(filename)));
1439566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryOpen(comm, filename, FILE_MODE_READ, &loader));
144c4762a1bSJed Brown 
1459566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &user->H));
1469566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(user->H, PETSC_DECIDE, PETSC_DECIDE, nrows, nrows));
1479566063dSJacob Faibussowitsch   PetscCall(MatLoad(user->H, loader));
1489566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&loader));
1499566063dSJacob Faibussowitsch   PetscCall(MatGetSize(user->H, &nrows, &ncols));
1503c859ba3SBarry Smith   PetscCheck(nrows == user->n, comm, PETSC_ERR_ARG_SIZ, "H: nrows != n");
1513c859ba3SBarry Smith   PetscCheck(ncols == user->n, comm, PETSC_ERR_ARG_SIZ, "H: ncols != n");
1529566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(user->H));
153c4762a1bSJed Brown 
1549566063dSJacob Faibussowitsch   PetscCall(PetscStrncpy(filename, filebase, sizeof(filename)));
1559566063dSJacob Faibussowitsch   PetscCall(PetscStrlcat(filename, "Aeq", sizeof(filename)));
1569566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryOpen(comm, filename, FILE_MODE_READ, &loader));
1579566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &user->Aeq));
1589566063dSJacob Faibussowitsch   PetscCall(MatLoad(user->Aeq, loader));
1599566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&loader));
1609566063dSJacob Faibussowitsch   PetscCall(MatGetSize(user->Aeq, &nrows, &ncols));
1613c859ba3SBarry Smith   PetscCheck(ncols == user->n, comm, PETSC_ERR_ARG_SIZ, "Aeq ncols != H nrows");
1629566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(user->Aeq));
163c4762a1bSJed Brown   user->me = nrows;
164c4762a1bSJed Brown 
1659566063dSJacob Faibussowitsch   PetscCall(PetscStrncpy(filename, filebase, sizeof(filename)));
1669566063dSJacob Faibussowitsch   PetscCall(PetscStrlcat(filename, "Beq", sizeof(filename)));
1679566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryOpen(comm, filename, FILE_MODE_READ, &loader));
1689566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm, &user->beq));
1699566063dSJacob Faibussowitsch   PetscCall(VecLoad(user->beq, loader));
1709566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&loader));
1719566063dSJacob Faibussowitsch   PetscCall(VecGetSize(user->beq, &nrows));
1723c859ba3SBarry Smith   PetscCheck(nrows == user->me, comm, PETSC_ERR_ARG_SIZ, "Aeq nrows != Beq n");
1739566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(user->beq));
174c4762a1bSJed Brown 
175c4762a1bSJed Brown   user->mi = user->n;
176c4762a1bSJed Brown   /* Ain = eye(n,n) */
1779566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &user->Ain));
1789566063dSJacob Faibussowitsch   PetscCall(MatSetType(user->Ain, MATAIJ));
1799566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(user->Ain, PETSC_DECIDE, PETSC_DECIDE, user->mi, user->mi));
180c4762a1bSJed Brown 
1819566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(user->Ain, 1, NULL, 0, NULL));
1829566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(user->Ain, 1, NULL));
183c4762a1bSJed Brown 
1849566063dSJacob Faibussowitsch   for (i = 0; i < user->mi; i++) PetscCall(MatSetValues(user->Ain, 1, &i, 1, &i, &one, INSERT_VALUES));
1859566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(user->Ain, MAT_FINAL_ASSEMBLY));
1869566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(user->Ain, MAT_FINAL_ASSEMBLY));
1879566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(user->Ain));
188c4762a1bSJed Brown 
189c4762a1bSJed Brown   /* bin = [0,0 ... 0]' */
1909566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm, &user->bin));
1919566063dSJacob Faibussowitsch   PetscCall(VecSetType(user->bin, VECMPI));
1929566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(user->bin, PETSC_DECIDE, user->mi));
1939566063dSJacob Faibussowitsch   PetscCall(VecSet(user->bin, 0.0));
1949566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(user->bin));
195c4762a1bSJed Brown   user->m = user->me + user->mi;
1963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
197c4762a1bSJed Brown }
198c4762a1bSJed Brown 
DestroyProblem(AppCtx * user)199d71ae5a4SJacob Faibussowitsch PetscErrorCode DestroyProblem(AppCtx *user)
200d71ae5a4SJacob Faibussowitsch {
201c4762a1bSJed Brown   PetscFunctionBegin;
2029566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&user->H));
2039566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&user->Aeq));
2049566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&user->Ain));
2059566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&user->beq));
2069566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&user->bin));
2079566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&user->d));
2083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
209c4762a1bSJed Brown }
2105f80ce2aSJacob Faibussowitsch 
FormFunctionGradient(Tao tao,Vec x,PetscReal * f,Vec g,PetscCtx ctx)211*2a8381b2SBarry Smith PetscErrorCode FormFunctionGradient(Tao tao, Vec x, PetscReal *f, Vec g, PetscCtx ctx)
212d71ae5a4SJacob Faibussowitsch {
213c4762a1bSJed Brown   AppCtx     *user = (AppCtx *)ctx;
214c4762a1bSJed Brown   PetscScalar xtHx;
215c4762a1bSJed Brown 
216c4762a1bSJed Brown   PetscFunctionBegin;
2179566063dSJacob Faibussowitsch   PetscCall(MatMult(user->H, x, g));
2189566063dSJacob Faibussowitsch   PetscCall(VecDot(x, g, &xtHx));
2199566063dSJacob Faibussowitsch   PetscCall(VecDot(x, user->d, f));
220c4762a1bSJed Brown   *f += 0.5 * xtHx;
2219566063dSJacob Faibussowitsch   PetscCall(VecAXPY(g, 1.0, user->d));
2223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
223c4762a1bSJed Brown }
224c4762a1bSJed Brown 
FormHessian(Tao tao,Vec x,Mat H,Mat Hpre,PetscCtx ctx)225*2a8381b2SBarry Smith PetscErrorCode FormHessian(Tao tao, Vec x, Mat H, Mat Hpre, PetscCtx ctx)
226d71ae5a4SJacob Faibussowitsch {
227c4762a1bSJed Brown   PetscFunctionBegin;
2283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
229c4762a1bSJed Brown }
230c4762a1bSJed Brown 
FormInequalityConstraints(Tao tao,Vec x,Vec ci,PetscCtx ctx)231*2a8381b2SBarry Smith PetscErrorCode FormInequalityConstraints(Tao tao, Vec x, Vec ci, PetscCtx ctx)
232d71ae5a4SJacob Faibussowitsch {
233c4762a1bSJed Brown   AppCtx *user = (AppCtx *)ctx;
234c4762a1bSJed Brown 
235c4762a1bSJed Brown   PetscFunctionBegin;
2369566063dSJacob Faibussowitsch   PetscCall(MatMult(user->Ain, x, ci));
2373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
238c4762a1bSJed Brown }
239c4762a1bSJed Brown 
FormEqualityConstraints(Tao tao,Vec x,Vec ce,PetscCtx ctx)240*2a8381b2SBarry Smith PetscErrorCode FormEqualityConstraints(Tao tao, Vec x, Vec ce, PetscCtx ctx)
241d71ae5a4SJacob Faibussowitsch {
242c4762a1bSJed Brown   AppCtx *user = (AppCtx *)ctx;
243c4762a1bSJed Brown 
244c4762a1bSJed Brown   PetscFunctionBegin;
2459566063dSJacob Faibussowitsch   PetscCall(MatMult(user->Aeq, x, ce));
2469566063dSJacob Faibussowitsch   PetscCall(VecAXPY(ce, -1.0, user->beq));
2473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
248c4762a1bSJed Brown }
249c4762a1bSJed Brown 
FormInequalityJacobian(Tao tao,Vec x,Mat JI,Mat JIpre,PetscCtx ctx)250*2a8381b2SBarry Smith PetscErrorCode FormInequalityJacobian(Tao tao, Vec x, Mat JI, Mat JIpre, PetscCtx ctx)
251d71ae5a4SJacob Faibussowitsch {
252c4762a1bSJed Brown   PetscFunctionBegin;
2533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
254c4762a1bSJed Brown }
255c4762a1bSJed Brown 
FormEqualityJacobian(Tao tao,Vec x,Mat JE,Mat JEpre,PetscCtx ctx)256*2a8381b2SBarry Smith PetscErrorCode FormEqualityJacobian(Tao tao, Vec x, Mat JE, Mat JEpre, PetscCtx ctx)
257d71ae5a4SJacob Faibussowitsch {
258c4762a1bSJed Brown   PetscFunctionBegin;
2593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
260c4762a1bSJed Brown }
261c4762a1bSJed Brown 
262c4762a1bSJed Brown /*TEST
263c4762a1bSJed Brown 
264c4762a1bSJed Brown    build:
265c4762a1bSJed Brown       requires: !complex
266c4762a1bSJed Brown 
267c4762a1bSJed Brown    test:
268910b42cbSStefano Zampini       requires: !single superlu
269c4762a1bSJed Brown       localrunfiles: HS21
270c4762a1bSJed Brown 
271c4762a1bSJed Brown TEST*/
272