Actual source code: projection.c

  1: #include <petsc/private/vecimpl.h>

  3: /*@
  4:   VecWhichEqual - Creates an index set containing the indices
  5:              where the vectors `Vec1` and `Vec2` have identical elements.

  7:   Collective

  9:   Input Parameters:
 10: + Vec1 - the first vector to compare
 11: - Vec2 - the second two vector to compare

 13:   OutputParameter:
 14: . S - The index set containing the indices i where vec1[i] == vec2[i]

 16:   Level: advanced

 18:   Note:
 19:   The two vectors must have the same parallel layout

 21: .seealso: `Vec`
 22: @*/
 23: PetscErrorCode VecWhichEqual(Vec Vec1, Vec Vec2, IS *S)
 24: {
 25:   PetscInt           i, n_same = 0;
 26:   PetscInt           n, low, high;
 27:   PetscInt          *same = NULL;
 28:   const PetscScalar *v1, *v2;

 30:   PetscFunctionBegin;
 33:   PetscCheckSameComm(Vec1, 1, Vec2, 2);
 34:   VecCheckSameSize(Vec1, 1, Vec2, 2);

 36:   PetscCall(VecGetOwnershipRange(Vec1, &low, &high));
 37:   PetscCall(VecGetLocalSize(Vec1, &n));
 38:   if (n > 0) {
 39:     if (Vec1 == Vec2) {
 40:       PetscCall(VecGetArrayRead(Vec1, &v1));
 41:       v2 = v1;
 42:     } else {
 43:       PetscCall(VecGetArrayRead(Vec1, &v1));
 44:       PetscCall(VecGetArrayRead(Vec2, &v2));
 45:     }

 47:     PetscCall(PetscMalloc1(n, &same));

 49:     for (i = 0; i < n; ++i) {
 50:       if (v1[i] == v2[i]) {
 51:         same[n_same] = low + i;
 52:         ++n_same;
 53:       }
 54:     }

 56:     if (Vec1 == Vec2) {
 57:       PetscCall(VecRestoreArrayRead(Vec1, &v1));
 58:     } else {
 59:       PetscCall(VecRestoreArrayRead(Vec1, &v1));
 60:       PetscCall(VecRestoreArrayRead(Vec2, &v2));
 61:     }
 62:   }
 63:   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)Vec1), n_same, same, PETSC_OWN_POINTER, S));
 64:   PetscFunctionReturn(PETSC_SUCCESS);
 65: }

 67: /*@
 68:   VecWhichLessThan - Creates an index set containing the indices
 69:   where the vectors `Vec1` < `Vec2`

 71:   Collective

 73:   Input Parameters:
 74: + Vec1 - the first vector to compare
 75: - Vec2 - the second vector to compare

 77:   OutputParameter:
 78: . S - The index set containing the indices i where vec1[i] < vec2[i]

 80:   Level: advanced

 82:   Notes:
 83:   The two vectors must have the same parallel layout

 85:   For complex numbers this only compares the real part

 87: .seealso: `Vec`
 88: @*/
 89: PetscErrorCode VecWhichLessThan(Vec Vec1, Vec Vec2, IS *S)
 90: {
 91:   PetscInt           i, n_lt = 0;
 92:   PetscInt           n, low, high;
 93:   PetscInt          *lt = NULL;
 94:   const PetscScalar *v1, *v2;

 96:   PetscFunctionBegin;
 99:   PetscCheckSameComm(Vec1, 1, Vec2, 2);
100:   VecCheckSameSize(Vec1, 1, Vec2, 2);

102:   PetscCall(VecGetOwnershipRange(Vec1, &low, &high));
103:   PetscCall(VecGetLocalSize(Vec1, &n));
104:   if (n > 0) {
105:     if (Vec1 == Vec2) {
106:       PetscCall(VecGetArrayRead(Vec1, &v1));
107:       v2 = v1;
108:     } else {
109:       PetscCall(VecGetArrayRead(Vec1, &v1));
110:       PetscCall(VecGetArrayRead(Vec2, &v2));
111:     }

113:     PetscCall(PetscMalloc1(n, &lt));

115:     for (i = 0; i < n; ++i) {
116:       if (PetscRealPart(v1[i]) < PetscRealPart(v2[i])) {
117:         lt[n_lt] = low + i;
118:         ++n_lt;
119:       }
120:     }

122:     if (Vec1 == Vec2) {
123:       PetscCall(VecRestoreArrayRead(Vec1, &v1));
124:     } else {
125:       PetscCall(VecRestoreArrayRead(Vec1, &v1));
126:       PetscCall(VecRestoreArrayRead(Vec2, &v2));
127:     }
128:   }
129:   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)Vec1), n_lt, lt, PETSC_OWN_POINTER, S));
130:   PetscFunctionReturn(PETSC_SUCCESS);
131: }

133: /*@
134:   VecWhichGreaterThan - Creates an index set containing the indices
135:   where the vectors `Vec1` > `Vec2`

137:   Collective

139:   Input Parameters:
140: + Vec1 - the first vector to compare
141: - Vec2 - the second vector to compare

143:   OutputParameter:
144: . S - The index set containing the indices i where vec1[i] > vec2[i]

146:   Level: advanced

148:   Notes:
149:   The two vectors must have the same parallel layout

151:   For complex numbers this only compares the real part

153: .seealso: `Vec`
154: @*/
155: PetscErrorCode VecWhichGreaterThan(Vec Vec1, Vec Vec2, IS *S)
156: {
157:   PetscInt           i, n_gt = 0;
158:   PetscInt           n, low, high;
159:   PetscInt          *gt = NULL;
160:   const PetscScalar *v1, *v2;

162:   PetscFunctionBegin;
165:   PetscCheckSameComm(Vec1, 1, Vec2, 2);
166:   VecCheckSameSize(Vec1, 1, Vec2, 2);

168:   PetscCall(VecGetOwnershipRange(Vec1, &low, &high));
169:   PetscCall(VecGetLocalSize(Vec1, &n));
170:   if (n > 0) {
171:     if (Vec1 == Vec2) {
172:       PetscCall(VecGetArrayRead(Vec1, &v1));
173:       v2 = v1;
174:     } else {
175:       PetscCall(VecGetArrayRead(Vec1, &v1));
176:       PetscCall(VecGetArrayRead(Vec2, &v2));
177:     }

179:     PetscCall(PetscMalloc1(n, &gt));

181:     for (i = 0; i < n; ++i) {
182:       if (PetscRealPart(v1[i]) > PetscRealPart(v2[i])) {
183:         gt[n_gt] = low + i;
184:         ++n_gt;
185:       }
186:     }

188:     if (Vec1 == Vec2) {
189:       PetscCall(VecRestoreArrayRead(Vec1, &v1));
190:     } else {
191:       PetscCall(VecRestoreArrayRead(Vec1, &v1));
192:       PetscCall(VecRestoreArrayRead(Vec2, &v2));
193:     }
194:   }
195:   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)Vec1), n_gt, gt, PETSC_OWN_POINTER, S));
196:   PetscFunctionReturn(PETSC_SUCCESS);
197: }

199: /*@
200:   VecWhichBetween - Creates an index set containing the indices
201:                where  `VecLow` < `V` < `VecHigh`

203:   Collective

205:   Input Parameters:
206: + VecLow - lower bound
207: . V - Vector to compare
208: - VecHigh - higher bound

210:   OutputParameter:
211: . S - The index set containing the indices i where veclow[i] < v[i] < vechigh[i]

213:   Level: advanced

215:   Notes:
216:   The vectors must have the same parallel layout

218:   For complex numbers this only compares the real part

220: .seealso: `Vec`
221: @*/
222: PetscErrorCode VecWhichBetween(Vec VecLow, Vec V, Vec VecHigh, IS *S)
223: {
224:   PetscInt           i, n_vm = 0;
225:   PetscInt           n, low, high;
226:   PetscInt          *vm = NULL;
227:   const PetscScalar *v1, *v2, *vmiddle;

229:   PetscFunctionBegin;
233:   PetscCheckSameComm(V, 2, VecLow, 1);
234:   PetscCheckSameComm(V, 2, VecHigh, 3);
235:   VecCheckSameSize(V, 2, VecLow, 1);
236:   VecCheckSameSize(V, 2, VecHigh, 3);

238:   PetscCall(VecGetOwnershipRange(VecLow, &low, &high));
239:   PetscCall(VecGetLocalSize(VecLow, &n));
240:   if (n > 0) {
241:     PetscCall(VecGetArrayRead(VecLow, &v1));
242:     if (VecLow != VecHigh) {
243:       PetscCall(VecGetArrayRead(VecHigh, &v2));
244:     } else {
245:       v2 = v1;
246:     }
247:     if (V != VecLow && V != VecHigh) {
248:       PetscCall(VecGetArrayRead(V, &vmiddle));
249:     } else if (V == VecLow) {
250:       vmiddle = v1;
251:     } else {
252:       vmiddle = v2;
253:     }

255:     PetscCall(PetscMalloc1(n, &vm));

257:     for (i = 0; i < n; ++i) {
258:       if (PetscRealPart(v1[i]) < PetscRealPart(vmiddle[i]) && PetscRealPart(vmiddle[i]) < PetscRealPart(v2[i])) {
259:         vm[n_vm] = low + i;
260:         ++n_vm;
261:       }
262:     }

264:     PetscCall(VecRestoreArrayRead(VecLow, &v1));
265:     if (VecLow != VecHigh) PetscCall(VecRestoreArrayRead(VecHigh, &v2));
266:     if (V != VecLow && V != VecHigh) PetscCall(VecRestoreArrayRead(V, &vmiddle));
267:   }
268:   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)V), n_vm, vm, PETSC_OWN_POINTER, S));
269:   PetscFunctionReturn(PETSC_SUCCESS);
270: }

272: /*@
273:   VecWhichBetweenOrEqual - Creates an index set containing the indices
274:   where  `VecLow` <= `V` <= `VecHigh`

276:   Collective

278:   Input Parameters:
279: + VecLow - lower bound
280: . V - Vector to compare
281: - VecHigh - higher bound

283:   OutputParameter:
284: . S - The index set containing the indices i where veclow[i] <= v[i] <= vechigh[i]

286:   Level: advanced

288: .seealso: `Vec`
289: @*/

291: PetscErrorCode VecWhichBetweenOrEqual(Vec VecLow, Vec V, Vec VecHigh, IS *S)
292: {
293:   PetscInt           i, n_vm = 0;
294:   PetscInt           n, low, high;
295:   PetscInt          *vm = NULL;
296:   const PetscScalar *v1, *v2, *vmiddle;

298:   PetscFunctionBegin;
302:   PetscCheckSameComm(V, 2, VecLow, 1);
303:   PetscCheckSameComm(V, 2, VecHigh, 3);
304:   VecCheckSameSize(V, 2, VecLow, 1);
305:   VecCheckSameSize(V, 2, VecHigh, 3);

307:   PetscCall(VecGetOwnershipRange(VecLow, &low, &high));
308:   PetscCall(VecGetLocalSize(VecLow, &n));
309:   if (n > 0) {
310:     PetscCall(VecGetArrayRead(VecLow, &v1));
311:     if (VecLow != VecHigh) {
312:       PetscCall(VecGetArrayRead(VecHigh, &v2));
313:     } else {
314:       v2 = v1;
315:     }
316:     if (V != VecLow && V != VecHigh) {
317:       PetscCall(VecGetArrayRead(V, &vmiddle));
318:     } else if (V == VecLow) {
319:       vmiddle = v1;
320:     } else {
321:       vmiddle = v2;
322:     }

324:     PetscCall(PetscMalloc1(n, &vm));

326:     for (i = 0; i < n; ++i) {
327:       if (PetscRealPart(v1[i]) <= PetscRealPart(vmiddle[i]) && PetscRealPart(vmiddle[i]) <= PetscRealPart(v2[i])) {
328:         vm[n_vm] = low + i;
329:         ++n_vm;
330:       }
331:     }

333:     PetscCall(VecRestoreArrayRead(VecLow, &v1));
334:     if (VecLow != VecHigh) PetscCall(VecRestoreArrayRead(VecHigh, &v2));
335:     if (V != VecLow && V != VecHigh) PetscCall(VecRestoreArrayRead(V, &vmiddle));
336:   }
337:   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)V), n_vm, vm, PETSC_OWN_POINTER, S));
338:   PetscFunctionReturn(PETSC_SUCCESS);
339: }

341: /*@
342:    VecWhichInactive - Creates an index set containing the indices
343:   where one of the following holds:
344:     a) VecLow(i)  < V(i) < VecHigh(i)
345:     b) VecLow(i)  = V(i) and D(i) <= 0 (< 0 when Strong is true)
346:     c) VecHigh(i) = V(i) and D(i) >= 0 (> 0 when Strong is true)

348:   Collective

350:   Input Parameters:
351: + VecLow - lower bound
352: . V - Vector to compare
353: . D - Direction to compare
354: . VecHigh - higher bound
355: - Strong - indicator for applying strongly inactive test

357:   OutputParameter:
358: . S - The index set containing the indices i where the bound is inactive

360:   Level: advanced

362: .seealso: `Vec`
363: @*/

365: PetscErrorCode VecWhichInactive(Vec VecLow, Vec V, Vec D, Vec VecHigh, PetscBool Strong, IS *S)
366: {
367:   PetscInt           i, n_vm = 0;
368:   PetscInt           n, low, high;
369:   PetscInt          *vm = NULL;
370:   const PetscScalar *v1, *v2, *v, *d;

372:   PetscFunctionBegin;
373:   if (!VecLow && !VecHigh) {
374:     PetscCall(VecGetOwnershipRange(V, &low, &high));
375:     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)V), high - low, low, 1, S));
376:     PetscFunctionReturn(PETSC_SUCCESS);
377:   }
382:   PetscCheckSameComm(V, 2, VecLow, 1);
383:   PetscCheckSameComm(V, 2, D, 3);
384:   PetscCheckSameComm(V, 2, VecHigh, 4);
385:   VecCheckSameSize(V, 2, VecLow, 1);
386:   VecCheckSameSize(V, 2, D, 3);
387:   VecCheckSameSize(V, 2, VecHigh, 4);

389:   PetscCall(VecGetOwnershipRange(VecLow, &low, &high));
390:   PetscCall(VecGetLocalSize(VecLow, &n));
391:   if (n > 0) {
392:     PetscCall(VecGetArrayRead(VecLow, &v1));
393:     if (VecLow != VecHigh) {
394:       PetscCall(VecGetArrayRead(VecHigh, &v2));
395:     } else {
396:       v2 = v1;
397:     }
398:     if (V != VecLow && V != VecHigh) {
399:       PetscCall(VecGetArrayRead(V, &v));
400:     } else if (V == VecLow) {
401:       v = v1;
402:     } else {
403:       v = v2;
404:     }
405:     if (D != VecLow && D != VecHigh && D != V) {
406:       PetscCall(VecGetArrayRead(D, &d));
407:     } else if (D == VecLow) {
408:       d = v1;
409:     } else if (D == VecHigh) {
410:       d = v2;
411:     } else {
412:       d = v;
413:     }

415:     PetscCall(PetscMalloc1(n, &vm));

417:     if (Strong) {
418:       for (i = 0; i < n; ++i) {
419:         if (PetscRealPart(v1[i]) < PetscRealPart(v[i]) && PetscRealPart(v[i]) < PetscRealPart(v2[i])) {
420:           vm[n_vm] = low + i;
421:           ++n_vm;
422:         } else if (PetscRealPart(v1[i]) == PetscRealPart(v[i]) && PetscRealPart(d[i]) < 0) {
423:           vm[n_vm] = low + i;
424:           ++n_vm;
425:         } else if (PetscRealPart(v2[i]) == PetscRealPart(v[i]) && PetscRealPart(d[i]) > 0) {
426:           vm[n_vm] = low + i;
427:           ++n_vm;
428:         }
429:       }
430:     } else {
431:       for (i = 0; i < n; ++i) {
432:         if (PetscRealPart(v1[i]) < PetscRealPart(v[i]) && PetscRealPart(v[i]) < PetscRealPart(v2[i])) {
433:           vm[n_vm] = low + i;
434:           ++n_vm;
435:         } else if (PetscRealPart(v1[i]) == PetscRealPart(v[i]) && PetscRealPart(d[i]) <= 0) {
436:           vm[n_vm] = low + i;
437:           ++n_vm;
438:         } else if (PetscRealPart(v2[i]) == PetscRealPart(v[i]) && PetscRealPart(d[i]) >= 0) {
439:           vm[n_vm] = low + i;
440:           ++n_vm;
441:         }
442:       }
443:     }

445:     PetscCall(VecRestoreArrayRead(VecLow, &v1));
446:     if (VecLow != VecHigh) PetscCall(VecRestoreArrayRead(VecHigh, &v2));
447:     if (V != VecLow && V != VecHigh) PetscCall(VecRestoreArrayRead(V, &v));
448:     if (D != VecLow && D != VecHigh && D != V) PetscCall(VecRestoreArrayRead(D, &d));
449:   }
450:   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)V), n_vm, vm, PETSC_OWN_POINTER, S));
451:   PetscFunctionReturn(PETSC_SUCCESS);
452: }

454: /*@
455:   VecISAXPY - Adds a reduced vector to the appropriate elements of a full-space vector.
456:                   vfull[is[i]] += alpha*vreduced[i]

458:   Input Parameters:
459: + vfull    - the full-space vector
460: . is       - the index set for the reduced space
461: . alpha    - the scalar coefficient
462: - vreduced - the reduced-space vector

464:   Output Parameter:
465: . vfull    - the sum of the full-space vector and reduced-space vector

467:   Level: advanced

469:   Notes:
470:     The index set identifies entries in the global vector.
471:     Negative indices are skipped; indices outside the ownership range of `vfull` will raise an error.

473: .seealso: `VecISCopy()`, `VecISSet()`, `VecAXPY()`
474: @*/
475: PetscErrorCode VecISAXPY(Vec vfull, IS is, PetscScalar alpha, Vec vreduced)
476: {
477:   PetscInt nfull, nreduced;

479:   PetscFunctionBegin;
483:   PetscCall(VecGetSize(vfull, &nfull));
484:   PetscCall(VecGetSize(vreduced, &nreduced));

486:   if (nfull == nreduced) { /* Also takes care of masked vectors */
487:     PetscCall(VecAXPY(vfull, alpha, vreduced));
488:   } else {
489:     PetscScalar       *y;
490:     const PetscScalar *x;
491:     PetscInt           i, n, m, rstart, rend;
492:     const PetscInt    *id;

494:     PetscCall(VecGetArray(vfull, &y));
495:     PetscCall(VecGetArrayRead(vreduced, &x));
496:     PetscCall(ISGetIndices(is, &id));
497:     PetscCall(ISGetLocalSize(is, &n));
498:     PetscCall(VecGetLocalSize(vreduced, &m));
499:     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "IS local length not equal to Vec local length");
500:     PetscCall(VecGetOwnershipRange(vfull, &rstart, &rend));
501:     y -= rstart;
502:     if (alpha == 1.0) {
503:       for (i = 0; i < n; ++i) {
504:         if (id[i] < 0) continue;
505:         PetscCheck(id[i] >= rstart && id[i] < rend, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only owned values supported");
506:         y[id[i]] += x[i];
507:       }
508:     } else {
509:       for (i = 0; i < n; ++i) {
510:         if (id[i] < 0) continue;
511:         PetscCheck(id[i] >= rstart && id[i] < rend, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only owned values supported");
512:         y[id[i]] += alpha * x[i];
513:       }
514:     }
515:     y += rstart;
516:     PetscCall(ISRestoreIndices(is, &id));
517:     PetscCall(VecRestoreArray(vfull, &y));
518:     PetscCall(VecRestoreArrayRead(vreduced, &x));
519:   }
520:   PetscFunctionReturn(PETSC_SUCCESS);
521: }

523: /*@
524:   VecISCopy - Copies between a reduced vector and the appropriate elements of a full-space vector.

526:   Input Parameters:
527: + vfull    - the full-space vector
528: . is       - the index set for the reduced space
529: . mode     - the direction of copying, `SCATTER_FORWARD` or `SCATTER_REVERSE`
530: - vreduced - the reduced-space vector

532:   Output Parameter:
533: . vfull    - the sum of the full-space vector and reduced-space vector

535:   Level: advanced

537:   Notes:
538:     The index set identifies entries in the global vector.
539:     Negative indices are skipped; indices outside the ownership range of `vfull` will raise an error.
540: .vb
541:     mode == SCATTER_FORWARD: vfull[is[i]] = vreduced[i]
542:     mode == SCATTER_REVERSE: vreduced[i] = vfull[is[i]]
543: .ve

545: .seealso: `VecISSet()`, `VecISAXPY()`, `VecCopy()`
546: @*/
547: PetscErrorCode VecISCopy(Vec vfull, IS is, ScatterMode mode, Vec vreduced)
548: {
549:   PetscInt nfull, nreduced;

551:   PetscFunctionBegin;
555:   PetscCall(VecGetSize(vfull, &nfull));
556:   PetscCall(VecGetSize(vreduced, &nreduced));

558:   if (nfull == nreduced) { /* Also takes care of masked vectors */
559:     if (mode == SCATTER_FORWARD) {
560:       PetscCall(VecCopy(vreduced, vfull));
561:     } else {
562:       PetscCall(VecCopy(vfull, vreduced));
563:     }
564:   } else {
565:     const PetscInt *id;
566:     PetscInt        i, n, m, rstart, rend;

568:     PetscCall(ISGetIndices(is, &id));
569:     PetscCall(ISGetLocalSize(is, &n));
570:     PetscCall(VecGetLocalSize(vreduced, &m));
571:     PetscCall(VecGetOwnershipRange(vfull, &rstart, &rend));
572:     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "IS local length %" PetscInt_FMT " not equal to Vec local length %" PetscInt_FMT, n, m);
573:     if (mode == SCATTER_FORWARD) {
574:       PetscScalar       *y;
575:       const PetscScalar *x;

577:       PetscCall(VecGetArray(vfull, &y));
578:       PetscCall(VecGetArrayRead(vreduced, &x));
579:       y -= rstart;
580:       for (i = 0; i < n; ++i) {
581:         if (id[i] < 0) continue;
582:         PetscCheck(id[i] >= rstart && id[i] < rend, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only owned values supported");
583:         y[id[i]] = x[i];
584:       }
585:       y += rstart;
586:       PetscCall(VecRestoreArrayRead(vreduced, &x));
587:       PetscCall(VecRestoreArray(vfull, &y));
588:     } else if (mode == SCATTER_REVERSE) {
589:       PetscScalar       *x;
590:       const PetscScalar *y;

592:       PetscCall(VecGetArrayRead(vfull, &y));
593:       PetscCall(VecGetArray(vreduced, &x));
594:       for (i = 0; i < n; ++i) {
595:         if (id[i] < 0) continue;
596:         PetscCheck(id[i] >= rstart && id[i] < rend, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only owned values supported");
597:         x[i] = y[id[i] - rstart];
598:       }
599:       PetscCall(VecRestoreArray(vreduced, &x));
600:       PetscCall(VecRestoreArrayRead(vfull, &y));
601:     } else SETERRQ(PetscObjectComm((PetscObject)vfull), PETSC_ERR_ARG_WRONG, "Only forward or reverse modes are legal");
602:     PetscCall(ISRestoreIndices(is, &id));
603:   }
604:   PetscFunctionReturn(PETSC_SUCCESS);
605: }

607: /*@
608:    ISComplementVec - Creates the complement of the index set relative to a layout defined by a `Vec`

610:    Collective

612:    Input Parameters:
613: +  S -  a PETSc `IS`
614: -  V - the reference vector space

616:    Output Parameter:
617: .  T -  the complement of S

619:    Level: advanced

621: .seealso: `IS`, `Vec`, `ISCreateGeneral()`
622: @*/
623: PetscErrorCode ISComplementVec(IS S, Vec V, IS *T)
624: {
625:   PetscInt start, end;

627:   PetscFunctionBegin;
628:   PetscCall(VecGetOwnershipRange(V, &start, &end));
629:   PetscCall(ISComplement(S, start, end, T));
630:   PetscFunctionReturn(PETSC_SUCCESS);
631: }

633: /*@
634:    VecISSet - Sets the elements of a vector, specified by an index set, to a constant

636:    Input Parameters:
637: +  V - the vector
638: .  S - index set for the locations in the vector
639: -  c - the constant

641:    Level: advanced

643:   Notes:
644:     The index set identifies entries in the global vector.
645:     Negative indices are skipped; indices outside the ownership range of V will raise an error.

647: .seealso: `VecISCopy()`, `VecISAXPY()`, `VecSet()`
648: @*/
649: PetscErrorCode VecISSet(Vec V, IS S, PetscScalar c)
650: {
651:   PetscInt        nloc, low, high, i;
652:   const PetscInt *s;
653:   PetscScalar    *v;

655:   PetscFunctionBegin;
656:   if (!S) PetscFunctionReturn(PETSC_SUCCESS); /* simply return with no-op if the index set is NULL */

661:   PetscCall(VecGetOwnershipRange(V, &low, &high));
662:   PetscCall(ISGetLocalSize(S, &nloc));
663:   PetscCall(ISGetIndices(S, &s));
664:   PetscCall(VecGetArray(V, &v));
665:   for (i = 0; i < nloc; ++i) {
666:     if (s[i] < 0) continue;
667:     PetscCheck(s[i] >= low && s[i] < high, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only owned values supported");
668:     v[s[i] - low] = c;
669:   }
670:   PetscCall(ISRestoreIndices(S, &s));
671:   PetscCall(VecRestoreArray(V, &v));
672:   PetscFunctionReturn(PETSC_SUCCESS);
673: }

675: #if !defined(PETSC_USE_COMPLEX)
676: /*@C
677:   VecBoundGradientProjection - Projects  vector according to this definition.
678:   If XL[i] < X[i] < XU[i], then GP[i] = G[i];
679:   If X[i] <= XL[i], then GP[i] = min(G[i],0);
680:   If X[i] >= XU[i], then GP[i] = max(G[i],0);

682:   Input Parameters:
683: + G - current gradient vector
684: . X - current solution vector with XL[i] <= X[i] <= XU[i]
685: . XL - lower bounds
686: - XU - upper bounds

688:   Output Parameter:
689: . GP - gradient projection vector

691:   Level: advanced

693:   Note:
694:     `GP` may be the same vector as `G`

696: .seealso: `Vec`
697: @*/
698: PetscErrorCode VecBoundGradientProjection(Vec G, Vec X, Vec XL, Vec XU, Vec GP)
699: {
700:   PetscInt         n, i;
701:   const PetscReal *xptr, *xlptr, *xuptr;
702:   PetscReal       *gptr, *gpptr;
703:   PetscReal        xval, gpval;

705:   /* Project variables at the lower and upper bound */
706:   PetscFunctionBegin;
712:   if (!XL && !XU) {
713:     PetscCall(VecCopy(G, GP));
714:     PetscFunctionReturn(PETSC_SUCCESS);
715:   }

717:   PetscCall(VecGetLocalSize(X, &n));

719:   PetscCall(VecGetArrayRead(X, &xptr));
720:   PetscCall(VecGetArrayRead(XL, &xlptr));
721:   PetscCall(VecGetArrayRead(XU, &xuptr));
722:   PetscCall(VecGetArrayPair(G, GP, &gptr, &gpptr));

724:   for (i = 0; i < n; ++i) {
725:     gpval = gptr[i];
726:     xval  = xptr[i];
727:     if (gpval > 0.0 && xval <= xlptr[i]) {
728:       gpval = 0.0;
729:     } else if (gpval < 0.0 && xval >= xuptr[i]) {
730:       gpval = 0.0;
731:     }
732:     gpptr[i] = gpval;
733:   }

735:   PetscCall(VecRestoreArrayRead(X, &xptr));
736:   PetscCall(VecRestoreArrayRead(XL, &xlptr));
737:   PetscCall(VecRestoreArrayRead(XU, &xuptr));
738:   PetscCall(VecRestoreArrayPair(G, GP, &gptr, &gpptr));
739:   PetscFunctionReturn(PETSC_SUCCESS);
740: }
741: #endif

743: /*@
744:      VecStepMaxBounded - See below

746:      Collective

748:      Input Parameters:
749: +      X  - vector with no negative entries
750: .      XL - lower bounds
751: .      XU - upper bounds
752: -      DX  - step direction, can have negative, positive or zero entries

754:      Output Parameter:
755: .     stepmax -   minimum value so that X[i] + stepmax*DX[i] <= XL[i]  or  XU[i] <= X[i] + stepmax*DX[i]

757:   Level: intermediate

759: .seealso: `Vec`
760: @*/
761: PetscErrorCode VecStepMaxBounded(Vec X, Vec DX, Vec XL, Vec XU, PetscReal *stepmax)
762: {
763:   PetscInt           i, nn;
764:   const PetscScalar *xx, *dx, *xl, *xu;
765:   PetscReal          localmax = 0;

767:   PetscFunctionBegin;

773:   PetscCall(VecGetArrayRead(X, &xx));
774:   PetscCall(VecGetArrayRead(XL, &xl));
775:   PetscCall(VecGetArrayRead(XU, &xu));
776:   PetscCall(VecGetArrayRead(DX, &dx));
777:   PetscCall(VecGetLocalSize(X, &nn));
778:   for (i = 0; i < nn; i++) {
779:     if (PetscRealPart(dx[i]) > 0) {
780:       localmax = PetscMax(localmax, PetscRealPart((xu[i] - xx[i]) / dx[i]));
781:     } else if (PetscRealPart(dx[i]) < 0) {
782:       localmax = PetscMax(localmax, PetscRealPart((xl[i] - xx[i]) / dx[i]));
783:     }
784:   }
785:   PetscCall(VecRestoreArrayRead(X, &xx));
786:   PetscCall(VecRestoreArrayRead(XL, &xl));
787:   PetscCall(VecRestoreArrayRead(XU, &xu));
788:   PetscCall(VecRestoreArrayRead(DX, &dx));
789:   PetscCall(MPIU_Allreduce(&localmax, stepmax, 1, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)X)));
790:   PetscFunctionReturn(PETSC_SUCCESS);
791: }

793: /*@
794:      VecStepBoundInfo - See below

796:      Collective

798:      Input Parameters:
799: +      X  - vector with no negative entries
800: .      XL - lower bounds
801: .      XU - upper bounds
802: -      DX  - step direction, can have negative, positive or zero entries

804:      Output Parameters:
805: +     boundmin -  (may be `NULL` this it is not computed) maximum value so that   XL[i] <= X[i] + boundmax*DX[i] <= XU[i]
806: .     wolfemin -  (may be `NULL` this it is not computed)
807: -     boundmax -   (may be `NULL` this it is not computed) minimum value so that X[i] + boundmax*DX[i] <= XL[i]  or  XU[i] <= X[i] + boundmax*DX[i]

809:   Level: advanced

811:      Note:
812:     For complex numbers only compares the real part

814: .seealso: `Vec`
815: @*/
816: PetscErrorCode VecStepBoundInfo(Vec X, Vec DX, Vec XL, Vec XU, PetscReal *boundmin, PetscReal *wolfemin, PetscReal *boundmax)
817: {
818:   PetscInt           n, i;
819:   const PetscScalar *x, *xl, *xu, *dx;
820:   PetscReal          t;
821:   PetscReal          localmin = PETSC_INFINITY, localwolfemin = PETSC_INFINITY, localmax = -1;
822:   MPI_Comm           comm;

824:   PetscFunctionBegin;

830:   PetscCall(VecGetArrayRead(X, &x));
831:   PetscCall(VecGetArrayRead(XL, &xl));
832:   PetscCall(VecGetArrayRead(XU, &xu));
833:   PetscCall(VecGetArrayRead(DX, &dx));
834:   PetscCall(VecGetLocalSize(X, &n));
835:   for (i = 0; i < n; ++i) {
836:     if (PetscRealPart(dx[i]) > 0 && PetscRealPart(xu[i]) < PETSC_INFINITY) {
837:       t        = PetscRealPart((xu[i] - x[i]) / dx[i]);
838:       localmin = PetscMin(t, localmin);
839:       if (localmin > 0) localwolfemin = PetscMin(t, localwolfemin);
840:       localmax = PetscMax(t, localmax);
841:     } else if (PetscRealPart(dx[i]) < 0 && PetscRealPart(xl[i]) > PETSC_NINFINITY) {
842:       t        = PetscRealPart((xl[i] - x[i]) / dx[i]);
843:       localmin = PetscMin(t, localmin);
844:       if (localmin > 0) localwolfemin = PetscMin(t, localwolfemin);
845:       localmax = PetscMax(t, localmax);
846:     }
847:   }

849:   PetscCall(VecRestoreArrayRead(X, &x));
850:   PetscCall(VecRestoreArrayRead(XL, &xl));
851:   PetscCall(VecRestoreArrayRead(XU, &xu));
852:   PetscCall(VecRestoreArrayRead(DX, &dx));
853:   PetscCall(PetscObjectGetComm((PetscObject)X, &comm));

855:   if (boundmin) {
856:     PetscCall(MPIU_Allreduce(&localmin, boundmin, 1, MPIU_REAL, MPIU_MIN, comm));
857:     PetscCall(PetscInfo(X, "Step Bound Info: Closest Bound: %20.19e\n", (double)*boundmin));
858:   }
859:   if (wolfemin) {
860:     PetscCall(MPIU_Allreduce(&localwolfemin, wolfemin, 1, MPIU_REAL, MPIU_MIN, comm));
861:     PetscCall(PetscInfo(X, "Step Bound Info: Wolfe: %20.19e\n", (double)*wolfemin));
862:   }
863:   if (boundmax) {
864:     PetscCall(MPIU_Allreduce(&localmax, boundmax, 1, MPIU_REAL, MPIU_MAX, comm));
865:     if (*boundmax < 0) *boundmax = PETSC_INFINITY;
866:     PetscCall(PetscInfo(X, "Step Bound Info: Max: %20.19e\n", (double)*boundmax));
867:   }
868:   PetscFunctionReturn(PETSC_SUCCESS);
869: }

871: /*@
872:      VecStepMax - Returns the largest value so that x[i] + step*DX[i] >= 0 for all i

874:      Collective

876:      Input Parameters:
877: +      X  - vector with no negative entries
878: -      DX  - a step direction, can have negative, positive or zero entries

880:      Output Parameter:
881: .    step - largest value such that x[i] + step*DX[i] >= 0 for all i

883:   Level: advanced

885:      Note:
886:     For complex numbers only compares the real part

888: .seealso: `Vec`
889: @*/
890: PetscErrorCode VecStepMax(Vec X, Vec DX, PetscReal *step)
891: {
892:   PetscInt           i, nn;
893:   PetscReal          stepmax = PETSC_INFINITY;
894:   const PetscScalar *xx, *dx;

896:   PetscFunctionBegin;

900:   PetscCall(VecGetLocalSize(X, &nn));
901:   PetscCall(VecGetArrayRead(X, &xx));
902:   PetscCall(VecGetArrayRead(DX, &dx));
903:   for (i = 0; i < nn; ++i) {
904:     PetscCheck(PetscRealPart(xx[i]) >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Vector must be positive");
905:     if (PetscRealPart(dx[i]) < 0) stepmax = PetscMin(stepmax, PetscRealPart(-xx[i] / dx[i]));
906:   }
907:   PetscCall(VecRestoreArrayRead(X, &xx));
908:   PetscCall(VecRestoreArrayRead(DX, &dx));
909:   PetscCall(MPIU_Allreduce(&stepmax, step, 1, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)X)));
910:   PetscFunctionReturn(PETSC_SUCCESS);
911: }

913: /*@
914:   VecPow - Replaces each component of a vector by x_i^p

916:   Logically Collective

918:   Input Parameters:
919: + v - the vector
920: - p - the exponent to use on each element

922:   Level: intermediate

924: .seealso: `Vec`
925: @*/
926: PetscErrorCode VecPow(Vec v, PetscScalar p)
927: {
928:   PetscInt     n, i;
929:   PetscScalar *v1;

931:   PetscFunctionBegin;

934:   PetscCall(VecGetArray(v, &v1));
935:   PetscCall(VecGetLocalSize(v, &n));

937:   if (1.0 == p) {
938:   } else if (-1.0 == p) {
939:     for (i = 0; i < n; ++i) v1[i] = 1.0 / v1[i];
940:   } else if (0.0 == p) {
941:     for (i = 0; i < n; ++i) {
942:       /*  Not-a-number left alone
943:           Infinity set to one  */
944:       if (v1[i] == v1[i]) v1[i] = 1.0;
945:     }
946:   } else if (0.5 == p) {
947:     for (i = 0; i < n; ++i) {
948:       if (PetscRealPart(v1[i]) >= 0) {
949:         v1[i] = PetscSqrtScalar(v1[i]);
950:       } else {
951:         v1[i] = PETSC_INFINITY;
952:       }
953:     }
954:   } else if (-0.5 == p) {
955:     for (i = 0; i < n; ++i) {
956:       if (PetscRealPart(v1[i]) >= 0) {
957:         v1[i] = 1.0 / PetscSqrtScalar(v1[i]);
958:       } else {
959:         v1[i] = PETSC_INFINITY;
960:       }
961:     }
962:   } else if (2.0 == p) {
963:     for (i = 0; i < n; ++i) v1[i] *= v1[i];
964:   } else if (-2.0 == p) {
965:     for (i = 0; i < n; ++i) v1[i] = 1.0 / (v1[i] * v1[i]);
966:   } else {
967:     for (i = 0; i < n; ++i) {
968:       if (PetscRealPart(v1[i]) >= 0) {
969:         v1[i] = PetscPowScalar(v1[i], p);
970:       } else {
971:         v1[i] = PETSC_INFINITY;
972:       }
973:     }
974:   }
975:   PetscCall(VecRestoreArray(v, &v1));
976:   PetscFunctionReturn(PETSC_SUCCESS);
977: }

979: /*@
980:   VecMedian - Computes the componentwise median of three vectors
981:   and stores the result in this vector.  Used primarily for projecting
982:   a vector within upper and lower bounds.

984:   Logically Collective

986:   Input Parameters:
987: + Vec1 - The first vector
988: . Vec2 - The second vector
989: - Vec3 - The third vector

991:   Output Parameter:
992: . VMedian - The median vector (this can be any one of the input vectors)

994:   Level: advanced

996: .seealso: `Vec`
997: @*/
998: PetscErrorCode VecMedian(Vec Vec1, Vec Vec2, Vec Vec3, Vec VMedian)
999: {
1000:   PetscInt           i, n, low1, high1;
1001:   const PetscScalar *v1, *v2, *v3;
1002:   PetscScalar       *vmed;

1004:   PetscFunctionBegin;

1010:   if (!Vec1 && !Vec3) {
1011:     PetscCall(VecCopy(Vec2, VMedian));
1012:     PetscFunctionReturn(PETSC_SUCCESS);
1013:   }
1014:   if (Vec1 == Vec2 || Vec1 == Vec3) {
1015:     PetscCall(VecCopy(Vec1, VMedian));
1016:     PetscFunctionReturn(PETSC_SUCCESS);
1017:   }
1018:   if (Vec2 == Vec3) {
1019:     PetscCall(VecCopy(Vec2, VMedian));
1020:     PetscFunctionReturn(PETSC_SUCCESS);
1021:   }

1023:   /* Assert that Vec1 != Vec2 and Vec2 != Vec3 */
1028:   PetscCheckSameType(Vec1, 1, Vec2, 2);
1029:   PetscCheckSameType(Vec1, 1, Vec3, 3);
1030:   PetscCheckSameType(Vec1, 1, VMedian, 4);
1031:   PetscCheckSameComm(Vec1, 1, Vec2, 2);
1032:   PetscCheckSameComm(Vec1, 1, Vec3, 3);
1033:   PetscCheckSameComm(Vec1, 1, VMedian, 4);
1034:   VecCheckSameSize(Vec1, 1, Vec2, 2);
1035:   VecCheckSameSize(Vec1, 1, Vec3, 3);
1036:   VecCheckSameSize(Vec1, 1, VMedian, 4);

1038:   PetscCall(VecGetOwnershipRange(Vec1, &low1, &high1));
1039:   PetscCall(VecGetLocalSize(Vec1, &n));
1040:   if (n > 0) {
1041:     PetscCall(VecGetArray(VMedian, &vmed));
1042:     if (Vec1 != VMedian) {
1043:       PetscCall(VecGetArrayRead(Vec1, &v1));
1044:     } else {
1045:       v1 = vmed;
1046:     }
1047:     if (Vec2 != VMedian) {
1048:       PetscCall(VecGetArrayRead(Vec2, &v2));
1049:     } else {
1050:       v2 = vmed;
1051:     }
1052:     if (Vec3 != VMedian) {
1053:       PetscCall(VecGetArrayRead(Vec3, &v3));
1054:     } else {
1055:       v3 = vmed;
1056:     }

1058:     for (i = 0; i < n; ++i) vmed[i] = PetscMax(PetscMax(PetscMin(PetscRealPart(v1[i]), PetscRealPart(v2[i])), PetscMin(PetscRealPart(v1[i]), PetscRealPart(v3[i]))), PetscMin(PetscRealPart(v2[i]), PetscRealPart(v3[i])));

1060:     PetscCall(VecRestoreArray(VMedian, &vmed));
1061:     if (VMedian != Vec1) PetscCall(VecRestoreArrayRead(Vec1, &v1));
1062:     if (VMedian != Vec2) PetscCall(VecRestoreArrayRead(Vec2, &v2));
1063:     if (VMedian != Vec3) PetscCall(VecRestoreArrayRead(Vec3, &v3));
1064:   }
1065:   PetscFunctionReturn(PETSC_SUCCESS);
1066: }