Actual source code: maros.c

  1: /* Program usage: mpiexec -n 1 maros1 [-help] [all TAO options] */

  3: /* ----------------------------------------------------------------------
  4: TODO Explain maros example
  5: ---------------------------------------------------------------------- */

  7: #include <petsctao.h>

  9: static char help[] = "";

 11: /*
 12:    User-defined application context - contains data needed by the
 13:    application-provided call-back routines, FormFunction(),
 14:    FormGradient(), and FormHessian().
 15: */

 17: /*
 18:    x,d in R^n
 19:    f in R
 20:    bin in R^mi
 21:    beq in R^me
 22:    Aeq in R^(me x n)
 23:    Ain in R^(mi x n)
 24:    H in R^(n x n)
 25:    min f=(1/2)*x'*H*x + d'*x
 26:    s.t.  Aeq*x == beq
 27:          Ain*x >= bin
 28: */
 29: typedef struct {
 30:   char     name[32];
 31:   PetscInt n;  /* Length x */
 32:   PetscInt me; /* number of equality constraints */
 33:   PetscInt mi; /* number of inequality constraints */
 34:   PetscInt m;  /* me+mi */
 35:   Mat      Aeq, Ain, H;
 36:   Vec      beq, bin, d;
 37: } AppCtx;

 39: /* -------- User-defined Routines --------- */

 41: PetscErrorCode InitializeProblem(AppCtx *);
 42: PetscErrorCode DestroyProblem(AppCtx *);
 43: PetscErrorCode FormFunctionGradient(Tao, Vec, PetscReal *, Vec, void *);
 44: PetscErrorCode FormHessian(Tao, Vec, Mat, Mat, void *);
 45: PetscErrorCode FormInequalityConstraints(Tao, Vec, Vec, void *);
 46: PetscErrorCode FormEqualityConstraints(Tao, Vec, Vec, void *);
 47: PetscErrorCode FormInequalityJacobian(Tao, Vec, Mat, Mat, void *);
 48: PetscErrorCode FormEqualityJacobian(Tao, Vec, Mat, Mat, void *);

 50: int main(int argc, char **argv)
 51: {
 52:   PetscMPIInt        size;
 53:   Vec                x; /* solution */
 54:   KSP                ksp;
 55:   PC                 pc;
 56:   Vec                ceq, cin;
 57:   PetscBool          flg; /* A return value when checking for use options */
 58:   Tao                tao; /* Tao solver context */
 59:   TaoConvergedReason reason;
 60:   AppCtx             user; /* application context */

 62:   /* Initialize TAO,PETSc */
 63:   PetscFunctionBeginUser;
 64:   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
 65:   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
 66:   /* Specify default parameters for the problem, check for command-line overrides */
 67:   PetscCall(PetscStrncpy(user.name, "HS21", sizeof(user.name)));
 68:   PetscCall(PetscOptionsGetString(NULL, NULL, "-cutername", user.name, sizeof(user.name), &flg));

 70:   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\n---- MAROS Problem %s -----\n", user.name));
 71:   PetscCall(InitializeProblem(&user));
 72:   PetscCall(VecDuplicate(user.d, &x));
 73:   PetscCall(VecDuplicate(user.beq, &ceq));
 74:   PetscCall(VecDuplicate(user.bin, &cin));
 75:   PetscCall(VecSet(x, 1.0));

 77:   PetscCall(TaoCreate(PETSC_COMM_WORLD, &tao));
 78:   PetscCall(TaoSetType(tao, TAOIPM));
 79:   PetscCall(TaoSetSolution(tao, x));
 80:   PetscCall(TaoSetObjectiveAndGradient(tao, NULL, FormFunctionGradient, (void *)&user));
 81:   PetscCall(TaoSetEqualityConstraintsRoutine(tao, ceq, FormEqualityConstraints, (void *)&user));
 82:   PetscCall(TaoSetInequalityConstraintsRoutine(tao, cin, FormInequalityConstraints, (void *)&user));
 83:   PetscCall(TaoSetInequalityBounds(tao, user.bin, NULL));
 84:   PetscCall(TaoSetJacobianEqualityRoutine(tao, user.Aeq, user.Aeq, FormEqualityJacobian, (void *)&user));
 85:   PetscCall(TaoSetJacobianInequalityRoutine(tao, user.Ain, user.Ain, FormInequalityJacobian, (void *)&user));
 86:   PetscCall(TaoSetHessian(tao, user.H, user.H, FormHessian, (void *)&user));
 87:   PetscCall(TaoGetKSP(tao, &ksp));
 88:   PetscCall(KSPGetPC(ksp, &pc));
 89:   PetscCall(PCSetType(pc, PCLU));
 90:   /*
 91:       This algorithm produces matrices with zeros along the diagonal therefore we need to use
 92:     SuperLU which does partial pivoting
 93:   */
 94:   PetscCall(PCFactorSetMatSolverType(pc, MATSOLVERSUPERLU));
 95:   PetscCall(KSPSetType(ksp, KSPPREONLY));
 96:   PetscCall(TaoSetTolerances(tao, 0, 0, 0));

 98:   PetscCall(TaoSetFromOptions(tao));
 99:   PetscCall(TaoSolve(tao));
100:   PetscCall(TaoGetConvergedReason(tao, &reason));
101:   if (reason < 0) {
102:     PetscCall(PetscPrintf(MPI_COMM_WORLD, "TAO failed to converge due to %s.\n", TaoConvergedReasons[reason]));
103:   } else {
104:     PetscCall(PetscPrintf(MPI_COMM_WORLD, "Optimization completed with status %s.\n", TaoConvergedReasons[reason]));
105:   }

107:   PetscCall(DestroyProblem(&user));
108:   PetscCall(VecDestroy(&x));
109:   PetscCall(VecDestroy(&ceq));
110:   PetscCall(VecDestroy(&cin));
111:   PetscCall(TaoDestroy(&tao));

113:   PetscCall(PetscFinalize());
114:   return 0;
115: }

117: PetscErrorCode InitializeProblem(AppCtx *user)
118: {
119:   PetscViewer loader;
120:   MPI_Comm    comm;
121:   PetscInt    nrows, ncols, i;
122:   PetscScalar one = 1.0;
123:   char        filebase[128];
124:   char        filename[128];

126:   PetscFunctionBegin;
127:   comm = PETSC_COMM_WORLD;
128:   PetscCall(PetscStrncpy(filebase, user->name, sizeof(filebase)));
129:   PetscCall(PetscStrlcat(filebase, "/", sizeof(filebase)));
130:   PetscCall(PetscStrncpy(filename, filebase, sizeof(filename)));
131:   PetscCall(PetscStrlcat(filename, "f", sizeof(filename)));
132:   PetscCall(PetscViewerBinaryOpen(comm, filename, FILE_MODE_READ, &loader));

134:   PetscCall(VecCreate(comm, &user->d));
135:   PetscCall(VecLoad(user->d, loader));
136:   PetscCall(PetscViewerDestroy(&loader));
137:   PetscCall(VecGetSize(user->d, &nrows));
138:   PetscCall(VecSetFromOptions(user->d));
139:   user->n = nrows;

141:   PetscCall(PetscStrncpy(filename, filebase, sizeof(filename)));
142:   PetscCall(PetscStrlcat(filename, "H", sizeof(filename)));
143:   PetscCall(PetscViewerBinaryOpen(comm, filename, FILE_MODE_READ, &loader));

145:   PetscCall(MatCreate(comm, &user->H));
146:   PetscCall(MatSetSizes(user->H, PETSC_DECIDE, PETSC_DECIDE, nrows, nrows));
147:   PetscCall(MatLoad(user->H, loader));
148:   PetscCall(PetscViewerDestroy(&loader));
149:   PetscCall(MatGetSize(user->H, &nrows, &ncols));
150:   PetscCheck(nrows == user->n, comm, PETSC_ERR_ARG_SIZ, "H: nrows != n");
151:   PetscCheck(ncols == user->n, comm, PETSC_ERR_ARG_SIZ, "H: ncols != n");
152:   PetscCall(MatSetFromOptions(user->H));

154:   PetscCall(PetscStrncpy(filename, filebase, sizeof(filename)));
155:   PetscCall(PetscStrlcat(filename, "Aeq", sizeof(filename)));
156:   PetscCall(PetscViewerBinaryOpen(comm, filename, FILE_MODE_READ, &loader));
157:   PetscCall(MatCreate(comm, &user->Aeq));
158:   PetscCall(MatLoad(user->Aeq, loader));
159:   PetscCall(PetscViewerDestroy(&loader));
160:   PetscCall(MatGetSize(user->Aeq, &nrows, &ncols));
161:   PetscCheck(ncols == user->n, comm, PETSC_ERR_ARG_SIZ, "Aeq ncols != H nrows");
162:   PetscCall(MatSetFromOptions(user->Aeq));
163:   user->me = nrows;

165:   PetscCall(PetscStrncpy(filename, filebase, sizeof(filename)));
166:   PetscCall(PetscStrlcat(filename, "Beq", sizeof(filename)));
167:   PetscCall(PetscViewerBinaryOpen(comm, filename, FILE_MODE_READ, &loader));
168:   PetscCall(VecCreate(comm, &user->beq));
169:   PetscCall(VecLoad(user->beq, loader));
170:   PetscCall(PetscViewerDestroy(&loader));
171:   PetscCall(VecGetSize(user->beq, &nrows));
172:   PetscCheck(nrows == user->me, comm, PETSC_ERR_ARG_SIZ, "Aeq nrows != Beq n");
173:   PetscCall(VecSetFromOptions(user->beq));

175:   user->mi = user->n;
176:   /* Ain = eye(n,n) */
177:   PetscCall(MatCreate(comm, &user->Ain));
178:   PetscCall(MatSetType(user->Ain, MATAIJ));
179:   PetscCall(MatSetSizes(user->Ain, PETSC_DECIDE, PETSC_DECIDE, user->mi, user->mi));

181:   PetscCall(MatMPIAIJSetPreallocation(user->Ain, 1, NULL, 0, NULL));
182:   PetscCall(MatSeqAIJSetPreallocation(user->Ain, 1, NULL));

184:   for (i = 0; i < user->mi; i++) PetscCall(MatSetValues(user->Ain, 1, &i, 1, &i, &one, INSERT_VALUES));
185:   PetscCall(MatAssemblyBegin(user->Ain, MAT_FINAL_ASSEMBLY));
186:   PetscCall(MatAssemblyEnd(user->Ain, MAT_FINAL_ASSEMBLY));
187:   PetscCall(MatSetFromOptions(user->Ain));

189:   /* bin = [0,0 ... 0]' */
190:   PetscCall(VecCreate(comm, &user->bin));
191:   PetscCall(VecSetType(user->bin, VECMPI));
192:   PetscCall(VecSetSizes(user->bin, PETSC_DECIDE, user->mi));
193:   PetscCall(VecSet(user->bin, 0.0));
194:   PetscCall(VecSetFromOptions(user->bin));
195:   user->m = user->me + user->mi;
196:   PetscFunctionReturn(PETSC_SUCCESS);
197: }

199: PetscErrorCode DestroyProblem(AppCtx *user)
200: {
201:   PetscFunctionBegin;
202:   PetscCall(MatDestroy(&user->H));
203:   PetscCall(MatDestroy(&user->Aeq));
204:   PetscCall(MatDestroy(&user->Ain));
205:   PetscCall(VecDestroy(&user->beq));
206:   PetscCall(VecDestroy(&user->bin));
207:   PetscCall(VecDestroy(&user->d));
208:   PetscFunctionReturn(PETSC_SUCCESS);
209: }

211: PetscErrorCode FormFunctionGradient(Tao tao, Vec x, PetscReal *f, Vec g, void *ctx)
212: {
213:   AppCtx     *user = (AppCtx *)ctx;
214:   PetscScalar xtHx;

216:   PetscFunctionBegin;
217:   PetscCall(MatMult(user->H, x, g));
218:   PetscCall(VecDot(x, g, &xtHx));
219:   PetscCall(VecDot(x, user->d, f));
220:   *f += 0.5 * xtHx;
221:   PetscCall(VecAXPY(g, 1.0, user->d));
222:   PetscFunctionReturn(PETSC_SUCCESS);
223: }

225: PetscErrorCode FormHessian(Tao tao, Vec x, Mat H, Mat Hpre, void *ctx)
226: {
227:   PetscFunctionBegin;
228:   PetscFunctionReturn(PETSC_SUCCESS);
229: }

231: PetscErrorCode FormInequalityConstraints(Tao tao, Vec x, Vec ci, void *ctx)
232: {
233:   AppCtx *user = (AppCtx *)ctx;

235:   PetscFunctionBegin;
236:   PetscCall(MatMult(user->Ain, x, ci));
237:   PetscFunctionReturn(PETSC_SUCCESS);
238: }

240: PetscErrorCode FormEqualityConstraints(Tao tao, Vec x, Vec ce, void *ctx)
241: {
242:   AppCtx *user = (AppCtx *)ctx;

244:   PetscFunctionBegin;
245:   PetscCall(MatMult(user->Aeq, x, ce));
246:   PetscCall(VecAXPY(ce, -1.0, user->beq));
247:   PetscFunctionReturn(PETSC_SUCCESS);
248: }

250: PetscErrorCode FormInequalityJacobian(Tao tao, Vec x, Mat JI, Mat JIpre, void *ctx)
251: {
252:   PetscFunctionBegin;
253:   PetscFunctionReturn(PETSC_SUCCESS);
254: }

256: PetscErrorCode FormEqualityJacobian(Tao tao, Vec x, Mat JE, Mat JEpre, void *ctx)
257: {
258:   PetscFunctionBegin;
259:   PetscFunctionReturn(PETSC_SUCCESS);
260: }

262: /*TEST

264:    build:
265:       requires: !complex

267:    test:
268:       requires: !single superlu
269:       localrunfiles: HS21

271: TEST*/