/* Program usage: mpiexec -n 1 maros1 [-help] [all TAO options] */ /* ---------------------------------------------------------------------- TODO Explain maros example ---------------------------------------------------------------------- */ #include static char help[] = ""; /* User-defined application context - contains data needed by the application-provided call-back routines, FormFunction(), FormGradient(), and FormHessian(). */ /* x,d in R^n f in R bin in R^mi beq in R^me Aeq in R^(me x n) Ain in R^(mi x n) H in R^(n x n) min f=(1/2)*x'*H*x + d'*x s.t. Aeq*x == beq Ain*x >= bin */ typedef struct { char name[32]; PetscInt n; /* Length x */ PetscInt me; /* number of equality constraints */ PetscInt mi; /* number of inequality constraints */ PetscInt m; /* me+mi */ Mat Aeq, Ain, H; Vec beq, bin, d; } AppCtx; /* -------- User-defined Routines --------- */ PetscErrorCode InitializeProblem(AppCtx *); PetscErrorCode DestroyProblem(AppCtx *); PetscErrorCode FormFunctionGradient(Tao, Vec, PetscReal *, Vec, void *); PetscErrorCode FormHessian(Tao, Vec, Mat, Mat, void *); PetscErrorCode FormInequalityConstraints(Tao, Vec, Vec, void *); PetscErrorCode FormEqualityConstraints(Tao, Vec, Vec, void *); PetscErrorCode FormInequalityJacobian(Tao, Vec, Mat, Mat, void *); PetscErrorCode FormEqualityJacobian(Tao, Vec, Mat, Mat, void *); int main(int argc, char **argv) { PetscMPIInt size; Vec x; /* solution */ KSP ksp; PC pc; Vec ceq, cin; PetscBool flg; /* A return value when checking for use options */ Tao tao; /* Tao solver context */ TaoConvergedReason reason; AppCtx user; /* application context */ /* Initialize TAO,PETSc */ PetscFunctionBeginUser; PetscCall(PetscInitialize(&argc, &argv, (char *)0, help)); PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size)); /* Specify default parameters for the problem, check for command-line overrides */ PetscCall(PetscStrncpy(user.name, "HS21", sizeof(user.name))); PetscCall(PetscOptionsGetString(NULL, NULL, "-cutername", user.name, sizeof(user.name), &flg)); PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\n---- MAROS Problem %s -----\n", user.name)); PetscCall(InitializeProblem(&user)); PetscCall(VecDuplicate(user.d, &x)); PetscCall(VecDuplicate(user.beq, &ceq)); PetscCall(VecDuplicate(user.bin, &cin)); PetscCall(VecSet(x, 1.0)); PetscCall(TaoCreate(PETSC_COMM_WORLD, &tao)); PetscCall(TaoSetType(tao, TAOIPM)); PetscCall(TaoSetSolution(tao, x)); PetscCall(TaoSetObjectiveAndGradient(tao, NULL, FormFunctionGradient, (void *)&user)); PetscCall(TaoSetEqualityConstraintsRoutine(tao, ceq, FormEqualityConstraints, (void *)&user)); PetscCall(TaoSetInequalityConstraintsRoutine(tao, cin, FormInequalityConstraints, (void *)&user)); PetscCall(TaoSetInequalityBounds(tao, user.bin, NULL)); PetscCall(TaoSetJacobianEqualityRoutine(tao, user.Aeq, user.Aeq, FormEqualityJacobian, (void *)&user)); PetscCall(TaoSetJacobianInequalityRoutine(tao, user.Ain, user.Ain, FormInequalityJacobian, (void *)&user)); PetscCall(TaoSetHessian(tao, user.H, user.H, FormHessian, (void *)&user)); PetscCall(TaoGetKSP(tao, &ksp)); PetscCall(KSPGetPC(ksp, &pc)); PetscCall(PCSetType(pc, PCLU)); /* This algorithm produces matrices with zeros along the diagonal therefore we need to use SuperLU which does partial pivoting */ PetscCall(PCFactorSetMatSolverType(pc, MATSOLVERSUPERLU)); PetscCall(KSPSetType(ksp, KSPPREONLY)); PetscCall(TaoSetTolerances(tao, 0, 0, 0)); PetscCall(TaoSetFromOptions(tao)); PetscCall(TaoSolve(tao)); PetscCall(TaoGetConvergedReason(tao, &reason)); if (reason < 0) { PetscCall(PetscPrintf(MPI_COMM_WORLD, "TAO failed to converge due to %s.\n", TaoConvergedReasons[reason])); } else { PetscCall(PetscPrintf(MPI_COMM_WORLD, "Optimization completed with status %s.\n", TaoConvergedReasons[reason])); } PetscCall(DestroyProblem(&user)); PetscCall(VecDestroy(&x)); PetscCall(VecDestroy(&ceq)); PetscCall(VecDestroy(&cin)); PetscCall(TaoDestroy(&tao)); PetscCall(PetscFinalize()); return 0; } PetscErrorCode InitializeProblem(AppCtx *user) { PetscViewer loader; MPI_Comm comm; PetscInt nrows, ncols, i; PetscScalar one = 1.0; char filebase[128]; char filename[128]; PetscFunctionBegin; comm = PETSC_COMM_WORLD; PetscCall(PetscStrncpy(filebase, user->name, sizeof(filebase))); PetscCall(PetscStrlcat(filebase, "/", sizeof(filebase))); PetscCall(PetscStrncpy(filename, filebase, sizeof(filename))); PetscCall(PetscStrlcat(filename, "f", sizeof(filename))); PetscCall(PetscViewerBinaryOpen(comm, filename, FILE_MODE_READ, &loader)); PetscCall(VecCreate(comm, &user->d)); PetscCall(VecLoad(user->d, loader)); PetscCall(PetscViewerDestroy(&loader)); PetscCall(VecGetSize(user->d, &nrows)); PetscCall(VecSetFromOptions(user->d)); user->n = nrows; PetscCall(PetscStrncpy(filename, filebase, sizeof(filename))); PetscCall(PetscStrlcat(filename, "H", sizeof(filename))); PetscCall(PetscViewerBinaryOpen(comm, filename, FILE_MODE_READ, &loader)); PetscCall(MatCreate(comm, &user->H)); PetscCall(MatSetSizes(user->H, PETSC_DECIDE, PETSC_DECIDE, nrows, nrows)); PetscCall(MatLoad(user->H, loader)); PetscCall(PetscViewerDestroy(&loader)); PetscCall(MatGetSize(user->H, &nrows, &ncols)); PetscCheck(nrows == user->n, comm, PETSC_ERR_ARG_SIZ, "H: nrows != n"); PetscCheck(ncols == user->n, comm, PETSC_ERR_ARG_SIZ, "H: ncols != n"); PetscCall(MatSetFromOptions(user->H)); PetscCall(PetscStrncpy(filename, filebase, sizeof(filename))); PetscCall(PetscStrlcat(filename, "Aeq", sizeof(filename))); PetscCall(PetscViewerBinaryOpen(comm, filename, FILE_MODE_READ, &loader)); PetscCall(MatCreate(comm, &user->Aeq)); PetscCall(MatLoad(user->Aeq, loader)); PetscCall(PetscViewerDestroy(&loader)); PetscCall(MatGetSize(user->Aeq, &nrows, &ncols)); PetscCheck(ncols == user->n, comm, PETSC_ERR_ARG_SIZ, "Aeq ncols != H nrows"); PetscCall(MatSetFromOptions(user->Aeq)); user->me = nrows; PetscCall(PetscStrncpy(filename, filebase, sizeof(filename))); PetscCall(PetscStrlcat(filename, "Beq", sizeof(filename))); PetscCall(PetscViewerBinaryOpen(comm, filename, FILE_MODE_READ, &loader)); PetscCall(VecCreate(comm, &user->beq)); PetscCall(VecLoad(user->beq, loader)); PetscCall(PetscViewerDestroy(&loader)); PetscCall(VecGetSize(user->beq, &nrows)); PetscCheck(nrows == user->me, comm, PETSC_ERR_ARG_SIZ, "Aeq nrows != Beq n"); PetscCall(VecSetFromOptions(user->beq)); user->mi = user->n; /* Ain = eye(n,n) */ PetscCall(MatCreate(comm, &user->Ain)); PetscCall(MatSetType(user->Ain, MATAIJ)); PetscCall(MatSetSizes(user->Ain, PETSC_DECIDE, PETSC_DECIDE, user->mi, user->mi)); PetscCall(MatMPIAIJSetPreallocation(user->Ain, 1, NULL, 0, NULL)); PetscCall(MatSeqAIJSetPreallocation(user->Ain, 1, NULL)); for (i = 0; i < user->mi; i++) PetscCall(MatSetValues(user->Ain, 1, &i, 1, &i, &one, INSERT_VALUES)); PetscCall(MatAssemblyBegin(user->Ain, MAT_FINAL_ASSEMBLY)); PetscCall(MatAssemblyEnd(user->Ain, MAT_FINAL_ASSEMBLY)); PetscCall(MatSetFromOptions(user->Ain)); /* bin = [0,0 ... 0]' */ PetscCall(VecCreate(comm, &user->bin)); PetscCall(VecSetType(user->bin, VECMPI)); PetscCall(VecSetSizes(user->bin, PETSC_DECIDE, user->mi)); PetscCall(VecSet(user->bin, 0.0)); PetscCall(VecSetFromOptions(user->bin)); user->m = user->me + user->mi; PetscFunctionReturn(PETSC_SUCCESS); } PetscErrorCode DestroyProblem(AppCtx *user) { PetscFunctionBegin; PetscCall(MatDestroy(&user->H)); PetscCall(MatDestroy(&user->Aeq)); PetscCall(MatDestroy(&user->Ain)); PetscCall(VecDestroy(&user->beq)); PetscCall(VecDestroy(&user->bin)); PetscCall(VecDestroy(&user->d)); PetscFunctionReturn(PETSC_SUCCESS); } PetscErrorCode FormFunctionGradient(Tao tao, Vec x, PetscReal *f, Vec g, void *ctx) { AppCtx *user = (AppCtx *)ctx; PetscScalar xtHx; PetscFunctionBegin; PetscCall(MatMult(user->H, x, g)); PetscCall(VecDot(x, g, &xtHx)); PetscCall(VecDot(x, user->d, f)); *f += 0.5 * xtHx; PetscCall(VecAXPY(g, 1.0, user->d)); PetscFunctionReturn(PETSC_SUCCESS); } PetscErrorCode FormHessian(Tao tao, Vec x, Mat H, Mat Hpre, void *ctx) { PetscFunctionBegin; PetscFunctionReturn(PETSC_SUCCESS); } PetscErrorCode FormInequalityConstraints(Tao tao, Vec x, Vec ci, void *ctx) { AppCtx *user = (AppCtx *)ctx; PetscFunctionBegin; PetscCall(MatMult(user->Ain, x, ci)); PetscFunctionReturn(PETSC_SUCCESS); } PetscErrorCode FormEqualityConstraints(Tao tao, Vec x, Vec ce, void *ctx) { AppCtx *user = (AppCtx *)ctx; PetscFunctionBegin; PetscCall(MatMult(user->Aeq, x, ce)); PetscCall(VecAXPY(ce, -1.0, user->beq)); PetscFunctionReturn(PETSC_SUCCESS); } PetscErrorCode FormInequalityJacobian(Tao tao, Vec x, Mat JI, Mat JIpre, void *ctx) { PetscFunctionBegin; PetscFunctionReturn(PETSC_SUCCESS); } PetscErrorCode FormEqualityJacobian(Tao tao, Vec x, Mat JE, Mat JEpre, void *ctx) { PetscFunctionBegin; PetscFunctionReturn(PETSC_SUCCESS); } /*TEST build: requires: !complex test: requires: superlu localrunfiles: HS21 TEST*/