Actual source code: tao_util.c

petsc-dev 2014-02-02
Report Typos and Errors
  1: #include <petsc-private/petscimpl.h>
  2: #include <petsctao.h>      /*I "petsctao.h" I*/


  5: PETSC_STATIC_INLINE PetscReal Fischer(PetscReal a, PetscReal b)
  6: {
  7:   /* Method suggested by Bob Vanderbei */
  8:    if (a + b <= 0) {
  9:      return PetscSqrtScalar(a*a + b*b) - (a + b);
 10:    }
 11:    return -2.0*a*b / (PetscSqrtScalar(a*a + b*b) + (a + b));
 12: }

 16: /*@
 17:    VecFischer - Evaluates the Fischer-Burmeister function for complementarity
 18:    problems.

 20:    Logically Collective on vectors

 22:    Input Parameters:
 23: +  X - current point
 24: .  F - function evaluated at x
 25: .  L - lower bounds
 26: -  U - upper bounds

 28:    Output Parameters:
 29: .  FB - The Fischer-Burmeister function vector

 31:    Notes:
 32:    The Fischer-Burmeister function is defined as
 33: $        phi(a,b) := sqrt(a*a + b*b) - a - b
 34:    and is used reformulate a complementarity problem as a semismooth
 35:    system of equations.

 37:    The result of this function is done by cases:
 38: +  l[i] == -infinity, u[i] == infinity  -- fb[i] = -f[i]
 39: .  l[i] == -infinity, u[i] finite       -- fb[i] = phi(u[i]-x[i], -f[i])
 40: .  l[i] finite,       u[i] == infinity  -- fb[i] = phi(x[i]-l[i],  f[i])
 41: .  l[i] finite < u[i] finite -- fb[i] = phi(x[i]-l[i], phi(u[i]-x[i], -f[u]))
 42: -  otherwise l[i] == u[i] -- fb[i] = l[i] - x[i]

 44:    Level: developer

 46: @*/
 47: PetscErrorCode VecFischer(Vec X, Vec F, Vec L, Vec U, Vec FB)
 48: {
 49:   PetscReal      *x, *f, *l, *u, *fb;
 50:   PetscReal      xval, fval, lval, uval;
 52:   PetscInt       low[5], high[5], n, i;


 61:   VecGetOwnershipRange(X, low, high);
 62:   VecGetOwnershipRange(F, low + 1, high + 1);
 63:   VecGetOwnershipRange(L, low + 2, high + 2);
 64:   VecGetOwnershipRange(U, low + 3, high + 3);
 65:   VecGetOwnershipRange(FB, low + 4, high + 4);

 67:   for (i = 1; i < 4; ++i) {
 68:     if (low[0] != low[i] || high[0] != high[i]) SETERRQ(PETSC_COMM_SELF,1,"Vectors must be identically loaded over processors");
 69:   }

 71:   VecGetArray(X, &x);
 72:   VecGetArray(F, &f);
 73:   VecGetArray(L, &l);
 74:   VecGetArray(U, &u);
 75:   VecGetArray(FB, &fb);

 77:   VecGetLocalSize(X, &n);

 79:   for (i = 0; i < n; ++i) {
 80:     xval = x[i]; fval = f[i];
 81:     lval = l[i]; uval = u[i];

 83:     if ((lval <= -PETSC_INFINITY) && (uval >= PETSC_INFINITY)) {
 84:       fb[i] = -fval;
 85:     } else if (lval <= -PETSC_INFINITY) {
 86:       fb[i] = -Fischer(uval - xval, -fval);
 87:     } else if (uval >=  PETSC_INFINITY) {
 88:       fb[i] =  Fischer(xval - lval,  fval);
 89:     } else if (lval == uval) {
 90:       fb[i] = lval - xval;
 91:     } else {
 92:       fval  =  Fischer(uval - xval, -fval);
 93:       fb[i] =  Fischer(xval - lval,  fval);
 94:     }
 95:   }

 97:   VecRestoreArray(X, &x);
 98:   VecRestoreArray(F, &f);
 99:   VecRestoreArray(L, &l);
100:   VecRestoreArray(U, &u);
101:   VecRestoreArray(FB, &fb);
102:   return(0);
103: }

105: PETSC_STATIC_INLINE PetscReal SFischer(PetscReal a, PetscReal b, PetscReal c)
106: {
107:   /* Method suggested by Bob Vanderbei */
108:    if (a + b <= 0) {
109:      return PetscSqrtScalar(a*a + b*b + 2.0*c*c) - (a + b);
110:    }
111:    return 2.0*(c*c - a*b) / (PetscSqrtScalar(a*a + b*b + 2.0*c*c) + (a + b));
112: }

116: /*@
117:    VecSFischer - Evaluates the Smoothed Fischer-Burmeister function for
118:    complementarity problems.

120:    Logically Collective on vectors

122:    Input Parameters:
123: +  X - current point
124: .  F - function evaluated at x
125: .  L - lower bounds
126: .  U - upper bounds
127: -  mu - smoothing parameter

129:    Output Parameters:
130: .  FB - The Smoothed Fischer-Burmeister function vector

132:    Notes:
133:    The Smoothed Fischer-Burmeister function is defined as
134: $        phi(a,b) := sqrt(a*a + b*b + 2*mu*mu) - a - b
135:    and is used reformulate a complementarity problem as a semismooth
136:    system of equations.

138:    The result of this function is done by cases:
139: +  l[i] == -infinity, u[i] == infinity  -- fb[i] = -f[i] - 2*mu*x[i]
140: .  l[i] == -infinity, u[i] finite       -- fb[i] = phi(u[i]-x[i], -f[i], mu)
141: .  l[i] finite,       u[i] == infinity  -- fb[i] = phi(x[i]-l[i],  f[i], mu)
142: .  l[i] finite < u[i] finite -- fb[i] = phi(x[i]-l[i], phi(u[i]-x[i], -f[u], mu), mu)
143: -  otherwise l[i] == u[i] -- fb[i] = l[i] - x[i]

145:    Level: developer

147: .seealso  VecFischer()
148: @*/
149: PetscErrorCode VecSFischer(Vec X, Vec F, Vec L, Vec U, PetscReal mu, Vec FB)
150: {
151:   PetscReal      *x, *f, *l, *u, *fb;
152:   PetscReal      xval, fval, lval, uval;
154:   PetscInt       low[5], high[5], n, i;


163:   VecGetOwnershipRange(X, low, high);
164:   VecGetOwnershipRange(F, low + 1, high + 1);
165:   VecGetOwnershipRange(L, low + 2, high + 2);
166:   VecGetOwnershipRange(U, low + 3, high + 3);
167:   VecGetOwnershipRange(FB, low + 4, high + 4);

169:   for (i = 1; i < 4; ++i) {
170:     if (low[0] != low[i] || high[0] != high[i]) SETERRQ(PETSC_COMM_SELF,1,"Vectors must be identically loaded over processors");
171:   }

173:   VecGetArray(X, &x);
174:   VecGetArray(F, &f);
175:   VecGetArray(L, &l);
176:   VecGetArray(U, &u);
177:   VecGetArray(FB, &fb);

179:   VecGetLocalSize(X, &n);

181:   for (i = 0; i < n; ++i) {
182:     xval = (*x++); fval = (*f++);
183:     lval = (*l++); uval = (*u++);

185:     if ((lval <= -PETSC_INFINITY) && (uval >= PETSC_INFINITY)) {
186:       (*fb++) = -fval - mu*xval;
187:     } else if (lval <= -PETSC_INFINITY) {
188:       (*fb++) = -SFischer(uval - xval, -fval, mu);
189:     } else if (uval >=  PETSC_INFINITY) {
190:       (*fb++) =  SFischer(xval - lval,  fval, mu);
191:     } else if (lval == uval) {
192:       (*fb++) = lval - xval;
193:     } else {
194:       fval    =  SFischer(uval - xval, -fval, mu);
195:       (*fb++) =  SFischer(xval - lval,  fval, mu);
196:     }
197:   }
198:   x -= n; f -= n; l -=n; u -= n; fb -= n;

200:   VecRestoreArray(X, &x);
201:   VecRestoreArray(F, &f);
202:   VecRestoreArray(L, &l);
203:   VecRestoreArray(U, &u);
204:   VecRestoreArray(FB, &fb);
205:   return(0);
206: }

208: PETSC_STATIC_INLINE PetscReal fischnorm(PetscReal a, PetscReal b)
209: {
210:   return PetscSqrtScalar(a*a + b*b);
211: }

213: PETSC_STATIC_INLINE PetscReal fischsnorm(PetscReal a, PetscReal b, PetscReal c)
214: {
215:   return PetscSqrtScalar(a*a + b*b + 2.0*c*c);
216: }

220: /*@
221:    D_Fischer - Calculates an element of the B-subdifferential of the
222:    Fischer-Burmeister function for complementarity problems.

224:    Collective on jac

226:    Input Parameters:
227: +  jac - the jacobian of f at X
228: .  X - current point
229: .  Con - constraints function evaluated at X
230: .  XL - lower bounds
231: .  XU - upper bounds
232: .  t1 - work vector
233: -  t2 - work vector

235:    Output Parameters:
236: +  Da - diagonal perturbation component of the result
237: -  Db - row scaling component of the result

239:    Level: developer

241: .seealso: VecFischer()
242: @*/
243: PetscErrorCode D_Fischer(Mat jac, Vec X, Vec Con, Vec XL, Vec XU, Vec T1, Vec T2, Vec Da, Vec Db)
244: {
246:   PetscInt       i,nn;
247:   PetscReal      *x,*f,*l,*u,*da,*db,*t1,*t2;
248:   PetscReal      ai,bi,ci,di,ei;

251:   VecGetLocalSize(X,&nn);
252:   VecGetArray(X,&x);
253:   VecGetArray(Con,&f);
254:   VecGetArray(XL,&l);
255:   VecGetArray(XU,&u);
256:   VecGetArray(Da,&da);
257:   VecGetArray(Db,&db);
258:   VecGetArray(T1,&t1);
259:   VecGetArray(T2,&t2);

261:   for (i = 0; i < nn; i++) {
262:     da[i] = 0;
263:     db[i] = 0;
264:     t1[i] = 0;

266:     if (PetscAbsReal(f[i]) <= PETSC_MACHINE_EPSILON) {
267:       if (l[i] > PETSC_NINFINITY && PetscAbsReal(x[i] - l[i]) <= PETSC_MACHINE_EPSILON) {
268:         t1[i] = 1;
269:         da[i] = 1;
270:       }

272:       if (u[i] <  PETSC_INFINITY && PetscAbsReal(u[i] - x[i]) <= PETSC_MACHINE_EPSILON) {
273:         t1[i] = 1;
274:         db[i] = 1;
275:       }
276:     }
277:   }

279:   VecRestoreArray(T1,&t1);
280:   VecRestoreArray(T2,&t2);
281:   MatMult(jac,T1,T2);
282:   VecGetArray(T2,&t2);

284:   for (i = 0; i < nn; i++) {
285:     if ((l[i] <= PETSC_NINFINITY) && (u[i] >= PETSC_INFINITY)) {
286:       da[i] = 0;
287:       db[i] = -1;
288:     } else if (l[i] <= PETSC_NINFINITY) {
289:       if (db[i] >= 1) {
290:         ai = fischnorm(1, t2[i]);

292:         da[i] = -1/ai - 1;
293:         db[i] = -t2[i]/ai - 1;
294:       } else {
295:         bi = u[i] - x[i];
296:         ai = fischnorm(bi, f[i]);
297:         ai = PetscMax(PETSC_MACHINE_EPSILON, ai);

299:         da[i] = bi / ai - 1;
300:         db[i] = -f[i] / ai - 1;
301:       }
302:     } else if (u[i] >=  PETSC_INFINITY) {
303:       if (da[i] >= 1) {
304:         ai = fischnorm(1, t2[i]);

306:         da[i] = 1 / ai - 1;
307:         db[i] = t2[i] / ai - 1;
308:       } else {
309:         bi = x[i] - l[i];
310:         ai = fischnorm(bi, f[i]);
311:         ai = PetscMax(PETSC_MACHINE_EPSILON, ai);

313:         da[i] = bi / ai - 1;
314:         db[i] = f[i] / ai - 1;
315:       }
316:     } else if (l[i] == u[i]) {
317:       da[i] = -1;
318:       db[i] = 0;
319:     } else {
320:       if (db[i] >= 1) {
321:         ai = fischnorm(1, t2[i]);

323:         ci = 1 / ai + 1;
324:         di = t2[i] / ai + 1;
325:       } else {
326:         bi = x[i] - u[i];
327:         ai = fischnorm(bi, f[i]);
328:         ai = PetscMax(PETSC_MACHINE_EPSILON, ai);

330:         ci = bi / ai + 1;
331:         di = f[i] / ai + 1;
332:       }

334:       if (da[i] >= 1) {
335:         bi = ci + di*t2[i];
336:         ai = fischnorm(1, bi);

338:         bi = bi / ai - 1;
339:         ai = 1 / ai - 1;
340:       } else {
341:         ei = Fischer(u[i] - x[i], -f[i]);
342:         ai = fischnorm(x[i] - l[i], ei);
343:         ai = PetscMax(PETSC_MACHINE_EPSILON, ai);

345:         bi = ei / ai - 1;
346:         ai = (x[i] - l[i]) / ai - 1;
347:       }

349:       da[i] = ai + bi*ci;
350:       db[i] = bi*di;
351:     }
352:   }

354:   VecRestoreArray(Da,&da);
355:   VecRestoreArray(Db,&db);
356:   VecRestoreArray(X,&x);
357:   VecRestoreArray(Con,&f);
358:   VecRestoreArray(XL,&l);
359:   VecRestoreArray(XU,&u);
360:   VecRestoreArray(T2,&t2);
361:   return(0);
362: }

366: /*@
367:    D_SFischer - Calculates an element of the B-subdifferential of the
368:    smoothed Fischer-Burmeister function for complementarity problems.

370:    Collective on jac

372:    Input Parameters:
373: +  jac - the jacobian of f at X
374: .  X - current point
375: .  F - constraint function evaluated at X
376: .  XL - lower bounds
377: .  XU - upper bounds
378: .  mu - smoothing parameter
379: .  T1 - work vector
380: -  T2 - work vector

382:    Output Parameter:
383: +  Da - diagonal perturbation component of the result
384: .  Db - row scaling component of the result
385: -  Dm - derivative with respect to scaling parameter

387:    Level: developer

389: .seealso D_Fischer()
390: @*/
391: PetscErrorCode D_SFischer(Mat jac, Vec X, Vec Con,Vec XL, Vec XU, PetscReal mu,Vec T1, Vec T2,Vec Da, Vec Db, Vec Dm)
392: {
394:   PetscInt       i,nn;
395:   PetscReal      *x, *f, *l, *u, *da, *db, *dm;
396:   PetscReal      ai, bi, ci, di, ei, fi;

399:   if (PetscAbsReal(mu) <= PETSC_MACHINE_EPSILON) {
400:     VecZeroEntries(Dm);
401:     D_Fischer(jac, X, Con, XL, XU, T1, T2, Da, Db);
402:   } else {
403:     VecGetLocalSize(X,&nn);
404:     VecGetArray(X,&x);
405:     VecGetArray(Con,&f);
406:     VecGetArray(XL,&l);
407:     VecGetArray(XU,&u);
408:     VecGetArray(Da,&da);
409:     VecGetArray(Db,&db);
410:     VecGetArray(Dm,&dm);

412:     for (i = 0; i < nn; ++i) {
413:       if ((l[i] <= PETSC_NINFINITY) && (u[i] >= PETSC_INFINITY)) {
414:         da[i] = -mu;
415:         db[i] = -1;
416:         dm[i] = -x[i];
417:       } else if (l[i] <= PETSC_NINFINITY) {
418:         bi = u[i] - x[i];
419:         ai = fischsnorm(bi, f[i], mu);
420:         ai = PetscMax(PETSC_MACHINE_EPSILON, ai);

422:         da[i] = bi / ai - 1;
423:         db[i] = -f[i] / ai - 1;
424:         dm[i] = 2.0 * mu / ai;
425:       } else if (u[i] >=  PETSC_INFINITY) {
426:         bi = x[i] - l[i];
427:         ai = fischsnorm(bi, f[i], mu);
428:         ai = PetscMax(PETSC_MACHINE_EPSILON, ai);

430:         da[i] = bi / ai - 1;
431:         db[i] = f[i] / ai - 1;
432:         dm[i] = 2.0 * mu / ai;
433:       } else if (l[i] == u[i]) {
434:         da[i] = -1;
435:         db[i] = 0;
436:         dm[i] = 0;
437:       } else {
438:         bi = x[i] - u[i];
439:         ai = fischsnorm(bi, f[i], mu);
440:         ai = PetscMax(PETSC_MACHINE_EPSILON, ai);

442:         ci = bi / ai + 1;
443:         di = f[i] / ai + 1;
444:         fi = 2.0 * mu / ai;

446:         ei = SFischer(u[i] - x[i], -f[i], mu);
447:         ai = fischsnorm(x[i] - l[i], ei, mu);
448:         ai = PetscMax(PETSC_MACHINE_EPSILON, ai);

450:         bi = ei / ai - 1;
451:         ei = 2.0 * mu / ei;
452:         ai = (x[i] - l[i]) / ai - 1;

454:         da[i] = ai + bi*ci;
455:         db[i] = bi*di;
456:         dm[i] = ei + bi*fi;
457:       }
458:     }

460:     VecRestoreArray(X,&x);
461:     VecRestoreArray(Con,&f);
462:     VecRestoreArray(XL,&l);
463:     VecRestoreArray(XU,&u);
464:     VecRestoreArray(Da,&da);
465:     VecRestoreArray(Db,&db);
466:     VecRestoreArray(Dm,&dm);
467:   }
468:   return(0);
469: }