Actual source code: tao_util.c
petsc-3.7.3 2016-08-01
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: }