Actual source code: almmutils.c

      1: #include <../src/tao/constrained/impls/almm/almm.h>
      2: #include <petsctao.h>
      3: #include <petsc/private/petscimpl.h>
      4: #include <petsc/private/vecimpl.h>

      6: /*@
      7:    TaoALMMGetType - Retreive the augmented Lagrangian formulation type for the subproblem.

      9:    Input Parameters:
     10: .  tao - the Tao context for the TAOALMM solver

     12:    Output Parameters:
     13: .  type - augmented Lagragrangian type

     15:    Level: advanced

     17: .seealso: TAOALMM, TaoALMMSetType(), TaoALMMType
     18: @*/
     19: PetscErrorCode TaoALMMGetType(Tao tao, TaoALMMType *type)
     20: {

     26:   PetscUseMethod(tao,"TaoALMMGetType_C",(Tao,TaoALMMType *),(tao,type));
     27:   return(0);
     28: }

     30: PetscErrorCode TaoALMMGetType_Private(Tao tao, TaoALMMType *type)
     31: {
     32:   TAO_ALMM        *auglag = (TAO_ALMM*)tao->data;

     35:   *type = auglag->type;
     36:   return(0);
     37: }

     39: /*@
     40:    TaoALMMSetType - Determine the augmented Lagrangian formulation type for the subproblem.

     42:    Input Parameters:
     43: +  tao - the Tao context for the TAOALMM solver
     44: -  type - augmented Lagragrangian type

     46:    Level: advanced

     48: .seealso: TAOALMM, TaoALMMGetType(), TaoALMMType
     49: @*/
     50: PetscErrorCode TaoALMMSetType(Tao tao, TaoALMMType type)
     51: {
     52:   PetscErrorCode  ierr;

     56:   PetscTryMethod(tao,"TaoALMMSetType_C",(Tao,TaoALMMType),(tao,type));
     57:   return(0);
     58: }

     60: PetscErrorCode TaoALMMSetType_Private(Tao tao, TaoALMMType type)
     61: {
     62:   TAO_ALMM        *auglag = (TAO_ALMM*)tao->data;

     65:   if (tao->setupcalled) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "TaoALMMSetType() must be called before TaoSetUp()");
     66:   auglag->type = type;
     67:   return(0);
     68: }

     70: /*@
     71:    TaoALMMGetSubsolver - Retrieve a pointer to the TAOALMM.

     73:    Input Parameters:
     74: .  tao - the Tao context for the TAOALMM solver

     76:    Output Parameter:
     77: .  subsolver - the Tao context for the subsolver

     79:    Level: advanced

     81: .seealso: TAOALMM, TaoALMMSetSubsolver()
     82: @*/
     83: PetscErrorCode TaoALMMGetSubsolver(Tao tao, Tao *subsolver)
     84: {
     85:   PetscErrorCode  ierr;

     90:   PetscUseMethod(tao,"TaoALMMGetSubsolver_C",(Tao,Tao *),(tao,subsolver));
     91:   return(0);
     92: }

     94: PetscErrorCode TaoALMMGetSubsolver_Private(Tao tao, Tao *subsolver)
     95: {
     96:   TAO_ALMM        *auglag = (TAO_ALMM*)tao->data;

     99:   *subsolver = auglag->subsolver;
    100:   return(0);
    101: }

    103: /*@
    104:    TaoALMMSetSubsolver - Changes the subsolver inside TAOALMM with the user provided one.

    106:    Input Parameters:
    107: +  tao - the Tao context for the TAOALMM solver
    108: -  subsolver - the Tao context for the subsolver

    110:    Level: advanced

    112: .seealso: TAOALMM, TaoALMMGetSubsolver()
    113: @*/
    114: PetscErrorCode TaoALMMSetSubsolver(Tao tao, Tao subsolver)
    115: {

    121:    PetscTryMethod(tao,"TaoALMMSetSubsolver_C",(Tao,Tao),(tao,subsolver));
    122:    return(0);
    123: }

    125: PetscErrorCode TaoALMMSetSubsolver_Private(Tao tao, Tao subsolver)
    126: {
    127:   TAO_ALMM        *auglag = (TAO_ALMM*)tao->data;
    128:   PetscBool       compatible;
    129:   PetscErrorCode  ierr;

    132:   if (subsolver == auglag->subsolver) return(0);
    133:   if (tao->bounded) {
    134:     PetscObjectTypeCompareAny((PetscObject)subsolver, &compatible, TAOSHELL, TAOBNCG, TAOBQNLS, TAOBQNKLS, TAOBQNKTR, TAOBQNKTL, "");
    135:     if (!compatible) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Subsolver must be a bound-constrained first-order method");
    136:   } else {
    137:     PetscObjectTypeCompareAny((PetscObject)subsolver, &compatible, TAOSHELL, TAOCG, TAOLMVM, TAOBNCG, TAOBQNLS, TAOBQNKLS, TAOBQNKTR, TAOBQNKTL, "");
    138:     if (!compatible) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Subsolver must be a first-order method");
    139:   }
    140:   if (!compatible) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Subsolver must be a first-order method");
    141:   PetscObjectReference((PetscObject)subsolver);
    142:   TaoDestroy(&auglag->subsolver);
    143:   auglag->subsolver = subsolver;
    144:   if (tao->setupcalled) {
    145:     TaoSetInitialVector(auglag->subsolver, auglag->P);
    146:     TaoSetObjectiveAndGradientRoutine(auglag->subsolver, TaoALMMSubsolverObjectiveAndGradient_Private, (void*)auglag);
    147:     TaoSetVariableBounds(auglag->subsolver, auglag->PL, auglag->PU);
    148:   }
    149:   return(0);
    150: }

    152: /*@
    153:    TaoALMMGetMultipliers - Retreive a pointer to the Lagrange multipliers.

    155:    Input Parameters:
    156: .  tao - the Tao context for the TAOALMM solver

    158:    Output Parameters:
    159: .  Y - vector of Lagrange multipliers

    161:    Level: advanced

    163:    Notes:
    164:    For problems with both equality and inequality constraints,
    165:    the multipliers are combined together as Y = (Ye, Yi). Users
    166:    can recover copies of the subcomponents using index sets
    167:    provided by TaoALMMGetDualIS() and use VecGetSubVector().

    169: .seealso: TAOALMM, TaoALMMSetMultipliers(), TaoALMMGetDualIS()
    170: @*/
    171: PetscErrorCode TaoALMMGetMultipliers(Tao tao, Vec *Y)
    172: {
    173:   PetscErrorCode  ierr;

    178:   PetscUseMethod(tao,"TaoALMMGetMultipliers_C",(Tao,Vec *),(tao,Y));
    179:   return(0);
    180: }

    182: PetscErrorCode TaoALMMGetMultipliers_Private(Tao tao, Vec *Y)
    183: {
    184:   TAO_ALMM        *auglag = (TAO_ALMM*)tao->data;

    187:   if (!tao->setupcalled) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "TaoSetUp() must be called first for scatters to be constructed");
    188:   *Y = auglag->Y;
    189:   return(0);
    190: }

    192: /*@
    193:    TaoALMMSetMultipliers - Set user-defined Lagrange multipliers. The vector type and
    194:                              parallel structure of the given vectormust match equality and
    195:                              inequality constraints. The vector must have a local size equal
    196:                              to the sum of the local sizes for the constraint vectors, and a
    197:                              global size equal to the sum of the global sizes of the constraint
    198:                              vectors.

    200:    Input Parameters:
    201: +  tao - the Tao context for the TAOALMM solver
    202: -  Y - vector of Lagrange multipliers

    204:    Level: advanced

    206:    Notes:
    207:    This routine is only useful if the user wants to change the
    208:    parallel distribution of the combined dual vector in problems that
    209:    feature both equality and inequality constraints. For other tasks,
    210:    it is strongly recommended that the user retreive the dual vector
    211:    created by the solver using TaoALMMGetMultipliers().

    213: .seealso: TAOALMM, TaoALMMGetMultipliers()
    214: @*/
    215: PetscErrorCode TaoALMMSetMultipliers(Tao tao, Vec Y)
    216: {
    217:   PetscErrorCode  ierr;

    222:   PetscTryMethod(tao,"TaoALMMSetMultipliers_C",(Tao,Vec),(tao,Y));
    223:   return(0);
    224: }

    226: PetscErrorCode TaoALMMSetMultipliers_Private(Tao tao, Vec Y)
    227: {
    228:   TAO_ALMM       *auglag = (TAO_ALMM*)tao->data;
    229:   VecType        Ytype;
    230:   PetscInt       Nuser, Neq, Nineq, N;
    231:   PetscBool      same = PETSC_FALSE;

    235:   /* no-op if user provides vector from TaoALMMGetMultipliers() */
    236:   if (Y == auglag->Y) return(0);
    237:   /* make sure vector type is same as equality and inequality constraints */
    238:   if (tao->eq_constrained) {
    239:     VecGetType(tao->constraints_equality, &Ytype);
    240:   } else {
    241:     VecGetType(tao->constraints_inequality, &Ytype);
    242:   }
    243:   PetscObjectTypeCompare((PetscObject)Y, Ytype, &same);
    244:   if (!same) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Given vector for multipliers is not the same type as constraint vectors");
    245:   /* make sure global size matches sum of equality and inequality */
    246:   if (tao->eq_constrained) {
    247:     VecGetSize(tao->constraints_equality, &Neq);
    248:   } else {
    249:     Neq = 0;
    250:   }
    251:   if (tao->ineq_constrained) {
    252:     VecGetSize(tao->constraints_inequality, &Nineq);
    253:   } else {
    254:     Nineq = 0;
    255:   }
    256:   N = Neq + Nineq;
    257:   VecGetSize(Y, &Nuser);
    258:   if (Nuser != N) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Given vector has wrong global size");
    259:   /* if there is only one type of constraint, then we need the local size to match too */
    260:   if (Neq == 0) {
    261:     VecGetLocalSize(tao->constraints_inequality, &Nineq);
    262:     VecGetLocalSize(Y, &Nuser);
    263:     if (Nuser != Nineq) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Given vector has wrong local size");
    264:   }
    265:   if (Nineq == 0) {
    266:     VecGetLocalSize(tao->constraints_equality, &Neq);
    267:     VecGetLocalSize(Y, &Nuser);
    268:     if (Nuser != Neq) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Given vector has wrong local size");
    269:   }
    270:   /* if we got here, the given vector is compatible so we can replace the current one */
    271:   PetscObjectReference((PetscObject)Y);
    272:   VecDestroy(&auglag->Y);
    273:   auglag->Y = Y;
    274:   /* if there are both types of constraints and the solver has already been set up,
    275:      then we need to regenerate VecScatter objects for the new combined dual vector */
    276:   if (tao->setupcalled && tao->eq_constrained && tao->ineq_constrained) {
    277:     VecDestroy(&auglag->C);
    278:     VecDuplicate(auglag->Y, &auglag->C);
    279:     VecScatterDestroy(&auglag->Yscatter[0]);
    280:     VecScatterCreate(auglag->Y, auglag->Yis[0], auglag->Ye, NULL, &auglag->Yscatter[0]);
    281:     VecScatterDestroy(&auglag->Yscatter[1]);
    282:     VecScatterCreate(auglag->Y, auglag->Yis[1], auglag->Yi, NULL, &auglag->Yscatter[1]);
    283:   }
    284:   return(0);
    285: }

    287: /*@
    288:    TaoALMMGetPrimalIS - Retreive a pointer to the index set that identifies optimization
    289:                         and slack variable components of the subsolver's solution vector.
    290:                         Not valid for problems with only equality constraints.

    292:    Input Parameters:
    293: .  tao - the Tao context for the TAOALMM solver

    295:    Output Parameters:
    296: +  opt_is - index set associated with the optimization variables (NULL if not needed)
    297: -  slack_is - index set associated with the slack variables (NULL if not needed)

    299:    Level: advanced

    301: .seealso: TAOALMM, TaoALMMGetPrimalVector()
    302: @*/
    303: PetscErrorCode TaoALMMGetPrimalIS(Tao tao, IS *opt_is, IS *slack_is)
    304: {

    309:   PetscUseMethod(tao,"TaoALMMGetPrimalIS_C",(Tao,IS *,IS *),(tao,opt_is,slack_is));
    310:   return(0);
    311: }

    313: PetscErrorCode TaoALMMGetPrimalIS_Private(Tao tao, IS *opt_is, IS *slack_is)
    314: {
    315:   TAO_ALMM   *auglag = (TAO_ALMM*)tao->data;

    318:   if (!tao->ineq_constrained) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "Primal space has index sets only for inequality constrained problems");
    319:   if (!tao->setupcalled) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "TaoSetUp() must be called first for index sets to be constructed");
    320:   if (!opt_is && !slack_is) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_NULL, "Both index set pointers cannot be NULL");
    321:   if (opt_is) {
    322:      *opt_is = auglag->Pis[0];
    323:   }
    324:   if (slack_is) {
    325:      *slack_is = auglag->Pis[1];
    326:   }
    327:   return(0);
    328: }

    330: /*@
    331:    TaoALMMGetDualIS - Retreive a pointer to the index set that identifies equality
    332:                       and inequality constraint components of the dual vector returned
    333:                       by TaoALMMGetMultipliers(). Not valid for problems with only one
    334:                       type of constraint.

    336:    Input Parameters:
    337: .  tao - the Tao context for the TAOALMM solver

    339:    Output Parameters:
    340: +  eq_is - index set associated with the equality constraints (NULL if not needed)
    341: -  ineq_is - index set associated with the inequality constraints (NULL if not needed)

    343:    Level: advanced

    345: .seealso: TAOALMM, TaoALMMGetMultipliers()
    346: @*/
    347: PetscErrorCode TaoALMMGetDualIS(Tao tao, IS *eq_is, IS *ineq_is)
    348: {

    353:    PetscUseMethod(tao,"TaoALMMGetDualIS_C",(Tao,IS *,IS *),(tao,eq_is,ineq_is));
    354:    return(0);
    355: }

    357: PetscErrorCode TaoALMMGetDualIS_Private(Tao tao, IS *eq_is, IS *ineq_is)
    358: {
    359:   TAO_ALMM   *auglag = (TAO_ALMM*)tao->data;

    363:   if (!tao->ineq_constrained || !tao->ineq_constrained) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "Dual space has index sets only when problem has both equality and inequality constraints");
    364:   if (!tao->setupcalled) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "TaoSetUp() must be called first for index sets to be constructed");
    365:   if (!eq_is && !ineq_is) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_NULL, "Both index set pointers cannot be NULL");
    366:   if (eq_is) {
    367:      *eq_is = auglag->Yis[0];
    368:   }
    369:   if (ineq_is) {
    370:      *ineq_is = auglag->Yis[1];
    371:   }
    372:   return(0);
    373: }