Actual source code: tao_util.c

petsc-3.7.3 2016-08-01
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 PetscSqrtReal(a*a + b*b) - (a + b);
 10:    }
 11:    return -2.0*a*b / (PetscSqrtReal(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:   const PetscScalar *x, *f, *l, *u;
 50:   PetscScalar       *fb;
 51:   PetscReal         xval, fval, lval, uval;
 52:   PetscErrorCode    ierr;
 53:   PetscInt          low[5], high[5], n, i;


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

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

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

 78:   VecGetLocalSize(X, &n);

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

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

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

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

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

121:    Logically Collective on vectors

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

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

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

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

146:    Level: developer

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


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

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

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

181:   VecGetLocalSize(X, &n);

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

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

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

210: PETSC_STATIC_INLINE PetscReal fischnorm(PetscReal a, PetscReal b)
211: {
212:   return PetscSqrtReal(a*a + b*b);
213: }

215: PETSC_STATIC_INLINE PetscReal fischsnorm(PetscReal a, PetscReal b, PetscReal c)
216: {
217:   return PetscSqrtReal(a*a + b*b + 2.0*c*c);
218: }

222: /*@
223:    MatDFischer - Calculates an element of the B-subdifferential of the
224:    Fischer-Burmeister function for complementarity problems.

226:    Collective on jac

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

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

241:    Level: developer

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

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

264:   for (i = 0; i < nn; i++) {
265:     da[i] = 0.0;
266:     db[i] = 0.0;
267:     t1[i] = 0.0;

269:     if (PetscAbsScalar(f[i]) <= PETSC_MACHINE_EPSILON) {
270:       if (PetscRealPart(l[i]) > PETSC_NINFINITY && PetscAbsScalar(x[i] - l[i]) <= PETSC_MACHINE_EPSILON) {
271:         t1[i] = 1.0;
272:         da[i] = 1.0;
273:       }

275:       if (PetscRealPart(u[i]) <  PETSC_INFINITY && PetscAbsScalar(u[i] - x[i]) <= PETSC_MACHINE_EPSILON) {
276:         t1[i] = 1.0;
277:         db[i] = 1.0;
278:       }
279:     }
280:   }

282:   VecRestoreArray(T1,&t1);
283:   VecRestoreArrayRead(T2,&t2);
284:   MatMult(jac,T1,T2);
285:   VecGetArrayRead(T2,&t2);

287:   for (i = 0; i < nn; i++) {
288:     if ((PetscRealPart(l[i]) <= PETSC_NINFINITY) && (PetscRealPart(u[i]) >= PETSC_INFINITY)) {
289:       da[i] = 0.0;
290:       db[i] = -1.0;
291:     } else if (PetscRealPart(l[i]) <= PETSC_NINFINITY) {
292:       if (PetscRealPart(db[i]) >= 1) {
293:         ai = fischnorm(1.0, PetscRealPart(t2[i]));

295:         da[i] = -1.0 / ai - 1.0;
296:         db[i] = -t2[i] / ai - 1.0;
297:       } else {
298:         bi = PetscRealPart(u[i]) - PetscRealPart(x[i]);
299:         ai = fischnorm(bi, PetscRealPart(f[i]));
300:         ai = PetscMax(PETSC_MACHINE_EPSILON, ai);

302:         da[i] = bi / ai - 1.0;
303:         db[i] = -f[i] / ai - 1.0;
304:       }
305:     } else if (PetscRealPart(u[i]) >=  PETSC_INFINITY) {
306:       if (PetscRealPart(da[i]) >= 1) {
307:         ai = fischnorm(1.0, PetscRealPart(t2[i]));

309:         da[i] = 1.0 / ai - 1.0;
310:         db[i] = t2[i] / ai - 1.0;
311:       } else {
312:         bi = PetscRealPart(x[i]) - PetscRealPart(l[i]);
313:         ai = fischnorm(bi, PetscRealPart(f[i]));
314:         ai = PetscMax(PETSC_MACHINE_EPSILON, ai);

316:         da[i] = bi / ai - 1.0;
317:         db[i] = f[i] / ai - 1.0;
318:       }
319:     } else if (PetscRealPart(l[i]) == PetscRealPart(u[i])) {
320:       da[i] = -1.0;
321:       db[i] = 0.0;
322:     } else {
323:       if (PetscRealPart(db[i]) >= 1) {
324:         ai = fischnorm(1.0, PetscRealPart(t2[i]));

326:         ci = 1.0 / ai + 1.0;
327:         di = PetscRealPart(t2[i]) / ai + 1.0;
328:       } else {
329:         bi = PetscRealPart(x[i]) - PetscRealPart(u[i]);
330:         ai = fischnorm(bi, PetscRealPart(f[i]));
331:         ai = PetscMax(PETSC_MACHINE_EPSILON, ai);

333:         ci = bi / ai + 1.0;
334:         di = PetscRealPart(f[i]) / ai + 1.0;
335:       }

337:       if (PetscRealPart(da[i]) >= 1) {
338:         bi = ci + di*PetscRealPart(t2[i]);
339:         ai = fischnorm(1.0, bi);

341:         bi = bi / ai - 1.0;
342:         ai = 1.0 / ai - 1.0;
343:       } else {
344:         ei = Fischer(PetscRealPart(u[i]) - PetscRealPart(x[i]), -PetscRealPart(f[i]));
345:         ai = fischnorm(PetscRealPart(x[i]) - PetscRealPart(l[i]), ei);
346:         ai = PetscMax(PETSC_MACHINE_EPSILON, ai);

348:         bi = ei / ai - 1.0;
349:         ai = (PetscRealPart(x[i]) - PetscRealPart(l[i])) / ai - 1.0;
350:       }

352:       da[i] = ai + bi*ci;
353:       db[i] = bi*di;
354:     }
355:   }

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

369: /*@
370:    MatDSFischer - Calculates an element of the B-subdifferential of the
371:    smoothed Fischer-Burmeister function for complementarity problems.

373:    Collective on jac

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

385:    Output Parameter:
386: +  Da - diagonal perturbation component of the result
387: .  Db - row scaling component of the result
388: -  Dm - derivative with respect to scaling parameter

390:    Level: developer

392: .seealso MatDFischer()
393: @*/
394: PetscErrorCode MatDSFischer(Mat jac, Vec X, Vec Con,Vec XL, Vec XU, PetscReal mu,Vec T1, Vec T2,Vec Da, Vec Db, Vec Dm)
395: {
396:   PetscErrorCode    ierr;
397:   PetscInt          i,nn;
398:   const PetscScalar *x, *f, *l, *u;
399:   PetscScalar       *da, *db, *dm;
400:   PetscReal         ai, bi, ci, di, ei, fi;

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

416:     for (i = 0; i < nn; ++i) {
417:       if ((PetscRealPart(l[i]) <= PETSC_NINFINITY) && (PetscRealPart(u[i]) >= PETSC_INFINITY)) {
418:         da[i] = -mu;
419:         db[i] = -1.0;
420:         dm[i] = -x[i];
421:       } else if (PetscRealPart(l[i]) <= PETSC_NINFINITY) {
422:         bi = PetscRealPart(u[i]) - PetscRealPart(x[i]);
423:         ai = fischsnorm(bi, PetscRealPart(f[i]), mu);
424:         ai = PetscMax(PETSC_MACHINE_EPSILON, ai);

426:         da[i] = bi / ai - 1.0;
427:         db[i] = -PetscRealPart(f[i]) / ai - 1.0;
428:         dm[i] = 2.0 * mu / ai;
429:       } else if (PetscRealPart(u[i]) >=  PETSC_INFINITY) {
430:         bi = PetscRealPart(x[i]) - PetscRealPart(l[i]);
431:         ai = fischsnorm(bi, PetscRealPart(f[i]), mu);
432:         ai = PetscMax(PETSC_MACHINE_EPSILON, ai);

434:         da[i] = bi / ai - 1.0;
435:         db[i] = PetscRealPart(f[i]) / ai - 1.0;
436:         dm[i] = 2.0 * mu / ai;
437:       } else if (PetscRealPart(l[i]) == PetscRealPart(u[i])) {
438:         da[i] = -1.0;
439:         db[i] = 0.0;
440:         dm[i] = 0.0;
441:       } else {
442:         bi = PetscRealPart(x[i]) - PetscRealPart(u[i]);
443:         ai = fischsnorm(bi, PetscRealPart(f[i]), mu);
444:         ai = PetscMax(PETSC_MACHINE_EPSILON, ai);

446:         ci = bi / ai + 1.0;
447:         di = PetscRealPart(f[i]) / ai + 1.0;
448:         fi = 2.0 * mu / ai;

450:         ei = SFischer(PetscRealPart(u[i]) - PetscRealPart(x[i]), -PetscRealPart(f[i]), mu);
451:         ai = fischsnorm(PetscRealPart(x[i]) - PetscRealPart(l[i]), ei, mu);
452:         ai = PetscMax(PETSC_MACHINE_EPSILON, ai);

454:         bi = ei / ai - 1.0;
455:         ei = 2.0 * mu / ei;
456:         ai = (PetscRealPart(x[i]) - PetscRealPart(l[i])) / ai - 1.0;

458:         da[i] = ai + bi*ci;
459:         db[i] = bi*di;
460:         dm[i] = ei + bi*fi;
461:       }
462:     }

464:     VecRestoreArrayRead(X,&x);
465:     VecRestoreArrayRead(Con,&f);
466:     VecRestoreArrayRead(XL,&l);
467:     VecRestoreArrayRead(XU,&u);
468:     VecRestoreArray(Da,&da);
469:     VecRestoreArray(Db,&db);
470:     VecRestoreArray(Dm,&dm);
471:   }
472:   return(0);
473: }