Actual source code: tao_util.c
petsc-dev 2014-02-02
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: }