Actual source code: vinv.c

  1: #define PETSCVEC_DLL

  3: /*
  4:      Some useful vector utility functions.
  5: */
 6:  #include private/vecimpl.h


 13: /*@
 14:    VecStrideScale - Scales a subvector of a vector defined 
 15:    by a starting point and a stride.

 17:    Collective on Vec

 19:    Input Parameter:
 20: +  v - the vector 
 21: .  start - starting point of the subvector (defined by a stride)
 22: -  scale - value to multiply each subvector entry by

 24:    Notes:
 25:    One must call VecSetBlockSize() before this routine to set the stride 
 26:    information, or use a vector created from a multicomponent DA.

 28:    This will only work if the desire subvector is a stride subvector

 30:    Level: advanced

 32:    Concepts: scale^on stride of vector
 33:    Concepts: stride^scale

 35: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideScale()
 36: @*/
 37: PetscErrorCode  VecStrideScale(Vec v,PetscInt start,PetscScalar scale)
 38: {
 40:   PetscInt       i,n,bs;
 41:   PetscScalar    *x;

 45:   VecGetLocalSize(v,&n);
 46:   VecGetArray(v,&x);

 48:   bs   = v->map->bs;
 49:   if (start < 0) {
 50:     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
 51:   } else if (start >= bs) {
 52:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
 53:             Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
 54:   }
 55:   x += start;

 57:   for (i=0; i<n; i+=bs) {
 58:     x[i] *= scale;
 59:   }
 60:   x -= start;

 62:   VecRestoreArray(v,&x);
 63:   return(0);
 64: }

 68: /*@
 69:    VecStrideNorm - Computes the norm of subvector of a vector defined 
 70:    by a starting point and a stride.

 72:    Collective on Vec

 74:    Input Parameter:
 75: +  v - the vector 
 76: .  start - starting point of the subvector (defined by a stride)
 77: -  ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY

 79:    Output Parameter:
 80: .  norm - the norm

 82:    Notes:
 83:    One must call VecSetBlockSize() before this routine to set the stride 
 84:    information, or use a vector created from a multicomponent DA.

 86:    If x is the array representing the vector x then this computes the norm 
 87:    of the array (x[start],x[start+stride],x[start+2*stride], ....)

 89:    This is useful for computing, say the norm of the pressure variable when
 90:    the pressure is stored (interlaced) with other variables, say density etc.

 92:    This will only work if the desire subvector is a stride subvector

 94:    Level: advanced

 96:    Concepts: norm^on stride of vector
 97:    Concepts: stride^norm

 99: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
100: @*/
101: PetscErrorCode  VecStrideNorm(Vec v,PetscInt start,NormType ntype,PetscReal *nrm)
102: {
104:   PetscInt       i,n,bs;
105:   PetscScalar    *x;
106:   PetscReal      tnorm;
107:   MPI_Comm       comm;

112:   VecGetLocalSize(v,&n);
113:   VecGetArray(v,&x);
114:   PetscObjectGetComm((PetscObject)v,&comm);

116:   bs   = v->map->bs;
117:   if (start < 0) {
118:     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
119:   } else if (start >= bs) {
120:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
121:             Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
122:   }
123:   x += start;

125:   if (ntype == NORM_2) {
126:     PetscScalar sum = 0.0;
127:     for (i=0; i<n; i+=bs) {
128:       sum += x[i]*(PetscConj(x[i]));
129:     }
130:     tnorm  = PetscRealPart(sum);
131:     MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPI_SUM,comm);
132:     *nrm = sqrt(*nrm);
133:   } else if (ntype == NORM_1) {
134:     tnorm = 0.0;
135:     for (i=0; i<n; i+=bs) {
136:       tnorm += PetscAbsScalar(x[i]);
137:     }
138:     MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPI_SUM,comm);
139:   } else if (ntype == NORM_INFINITY) {
140:     PetscReal tmp;
141:     tnorm = 0.0;

143:     for (i=0; i<n; i+=bs) {
144:       if ((tmp = PetscAbsScalar(x[i])) > tnorm) tnorm = tmp;
145:       /* check special case of tmp == NaN */
146:       if (tmp != tmp) {tnorm = tmp; break;}
147:     }
148:     MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPI_MAX,comm);
149:   } else {
150:     SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown norm type");
151:   }

153:   VecRestoreArray(v,&x);
154:   return(0);
155: }

159: /*@
160:    VecStrideMax - Computes the maximum of subvector of a vector defined 
161:    by a starting point and a stride and optionally its location.

163:    Collective on Vec

165:    Input Parameter:
166: +  v - the vector 
167: -  start - starting point of the subvector (defined by a stride)

169:    Output Parameter:
170: +  index - the location where the maximum occurred  (pass PETSC_NULL if not required)
171: -  nrm - the max

173:    Notes:
174:    One must call VecSetBlockSize() before this routine to set the stride 
175:    information, or use a vector created from a multicomponent DA.

177:    If xa is the array representing the vector x, then this computes the max
178:    of the array (xa[start],xa[start+stride],xa[start+2*stride], ....)

180:    This is useful for computing, say the maximum of the pressure variable when
181:    the pressure is stored (interlaced) with other variables, e.g., density, etc.
182:    This will only work if the desire subvector is a stride subvector.

184:    Level: advanced

186:    Concepts: maximum^on stride of vector
187:    Concepts: stride^maximum

189: .seealso: VecMax(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin()
190: @*/
191: PetscErrorCode  VecStrideMax(Vec v,PetscInt start,PetscInt *idex,PetscReal *nrm)
192: {
194:   PetscInt       i,n,bs,id;
195:   PetscScalar    *x;
196:   PetscReal      max,tmp;
197:   MPI_Comm       comm;


203:   VecGetLocalSize(v,&n);
204:   VecGetArray(v,&x);
205:   PetscObjectGetComm((PetscObject)v,&comm);

207:   bs   = v->map->bs;
208:   if (start < 0) {
209:     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
210:   } else if (start >= bs) {
211:     SETERRQ2(PETSC_ERR_ARG_WRONG,"Start of stride subvector (%D) is too large for stride\n\
212:             Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
213:   }
214:   x += start;

216:   id = -1;
217:   if (!n) {
218:     max = PETSC_MIN;
219:   } else {
220:     id  = 0;
221: #if defined(PETSC_USE_COMPLEX)
222:     max = PetscRealPart(x[0]);
223: #else
224:     max = x[0];
225: #endif
226:     for (i=bs; i<n; i+=bs) {
227: #if defined(PETSC_USE_COMPLEX)
228:       if ((tmp = PetscRealPart(x[i])) > max) { max = tmp; id = i;}
229: #else
230:       if ((tmp = x[i]) > max) { max = tmp; id = i;}
231: #endif
232:     }
233:   }
234:   VecRestoreArray(v,&x);

236:   if (!idex) {
237:     MPI_Allreduce(&max,nrm,1,MPIU_REAL,MPI_MAX,comm);
238:   } else {
239:     PetscReal in[2],out[2];
240:     PetscInt  rstart;

242:     VecGetOwnershipRange(v,&rstart,PETSC_NULL);
243:     in[0] = max;
244:     in[1] = rstart+id+start;
245:     MPI_Allreduce(in,out,2,MPIU_REAL,VecMax_Local_Op,((PetscObject)v)->comm);
246:     *nrm  = out[0];
247:     *idex = (PetscInt)out[1];
248:   }

250:   return(0);
251: }

255: /*@
256:    VecStrideMin - Computes the minimum of subvector of a vector defined 
257:    by a starting point and a stride and optionally its location.

259:    Collective on Vec

261:    Input Parameter:
262: +  v - the vector 
263: -  start - starting point of the subvector (defined by a stride)

265:    Output Parameter:
266: +  idex - the location where the minimum occurred. (pass PETSC_NULL if not required)
267: -  nrm - the min

269:    Level: advanced

271:    Notes:
272:    One must call VecSetBlockSize() before this routine to set the stride 
273:    information, or use a vector created from a multicomponent DA.

275:    If xa is the array representing the vector x, then this computes the min
276:    of the array (xa[start],xa[start+stride],xa[start+2*stride], ....)

278:    This is useful for computing, say the minimum of the pressure variable when
279:    the pressure is stored (interlaced) with other variables, e.g., density, etc.
280:    This will only work if the desire subvector is a stride subvector.

282:    Concepts: minimum^on stride of vector
283:    Concepts: stride^minimum

285: .seealso: VecMin(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMax()
286: @*/
287: PetscErrorCode  VecStrideMin(Vec v,PetscInt start,PetscInt *idex,PetscReal *nrm)
288: {
290:   PetscInt       i,n,bs,id;
291:   PetscScalar    *x;
292:   PetscReal      min,tmp;
293:   MPI_Comm       comm;


299:   VecGetLocalSize(v,&n);
300:   VecGetArray(v,&x);
301:   PetscObjectGetComm((PetscObject)v,&comm);

303:   bs   = v->map->bs;
304:   if (start < 0) {
305:     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
306:   } else if (start >= bs) {
307:     SETERRQ2(PETSC_ERR_ARG_WRONG,"Start of stride subvector (%D) is too large for stride\n\
308:             Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
309:   }
310:   x += start;

312:   id = -1;
313:   if (!n) {
314:     min = PETSC_MAX;
315:   } else {
316:     id = 0;
317: #if defined(PETSC_USE_COMPLEX)
318:     min = PetscRealPart(x[0]);
319: #else
320:     min = x[0];
321: #endif
322:     for (i=bs; i<n; i+=bs) {
323: #if defined(PETSC_USE_COMPLEX)
324:       if ((tmp = PetscRealPart(x[i])) < min) { min = tmp; id = i;}
325: #else
326:       if ((tmp = x[i]) < min) { min = tmp; id = i;}
327: #endif
328:     }
329:   }
330:   VecRestoreArray(v,&x);

332:   if (!idex) {
333:     MPI_Allreduce(&min,nrm,1,MPIU_REAL,MPI_MIN,comm);
334:   } else {
335:     PetscReal in[2],out[2];
336:     PetscInt  rstart;

338:     VecGetOwnershipRange(v,&rstart,PETSC_NULL);
339:     in[0] = min;
340:     in[1] = rstart+id;
341:     MPI_Allreduce(in,out,2,MPIU_REAL,VecMin_Local_Op,((PetscObject)v)->comm);
342:     *nrm  = out[0];
343:     *idex = (PetscInt)out[1];
344:   }

346:   return(0);
347: }

351: /*@
352:    VecStrideScaleAll - Scales the subvectors of a vector defined 
353:    by a starting point and a stride.

355:    Collective on Vec

357:    Input Parameter:
358: +  v - the vector 
359: -  scales - values to multiply each subvector entry by

361:    Notes:
362:    One must call VecSetBlockSize() before this routine to set the stride 
363:    information, or use a vector created from a multicomponent DA.


366:    Level: advanced

368:    Concepts: scale^on stride of vector
369:    Concepts: stride^scale

371: .seealso: VecNorm(), VecStrideScale(), VecScale(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
372: @*/
373: PetscErrorCode  VecStrideScaleAll(Vec v,PetscScalar *scales)
374: {
376:   PetscInt       i,j,n,bs;
377:   PetscScalar    *x;

382:   VecGetLocalSize(v,&n);
383:   VecGetArray(v,&x);

385:   bs   = v->map->bs;

387:   /* need to provide optimized code for each bs */
388:   for (i=0; i<n; i+=bs) {
389:     for (j=0; j<bs; j++) {
390:       x[i+j] *= scales[j];
391:     }
392:   }
393:   VecRestoreArray(v,&x);
394:   return(0);
395: }

399: /*@
400:    VecStrideNormAll - Computes the norms  subvectors of a vector defined 
401:    by a starting point and a stride.

403:    Collective on Vec

405:    Input Parameter:
406: +  v - the vector 
407: -  ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY

409:    Output Parameter:
410: .  nrm - the norms

412:    Notes:
413:    One must call VecSetBlockSize() before this routine to set the stride 
414:    information, or use a vector created from a multicomponent DA.

416:    If x is the array representing the vector x then this computes the norm 
417:    of the array (x[start],x[start+stride],x[start+2*stride], ....)

419:    This is useful for computing, say the norm of the pressure variable when
420:    the pressure is stored (interlaced) with other variables, say density etc.

422:    This will only work if the desire subvector is a stride subvector

424:    Level: advanced

426:    Concepts: norm^on stride of vector
427:    Concepts: stride^norm

429: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
430: @*/
431: PetscErrorCode  VecStrideNormAll(Vec v,NormType ntype,PetscReal nrm[])
432: {
434:   PetscInt       i,j,n,bs;
435:   PetscScalar    *x;
436:   PetscReal      tnorm[128];
437:   MPI_Comm       comm;

442:   VecGetLocalSize(v,&n);
443:   VecGetArray(v,&x);
444:   PetscObjectGetComm((PetscObject)v,&comm);

446:   bs   = v->map->bs;
447:   if (bs > 128) SETERRQ(PETSC_ERR_SUP,"Currently supports only blocksize up to 128");

449:   if (ntype == NORM_2) {
450:     PetscScalar sum[128];
451:     for (j=0; j<bs; j++) sum[j] = 0.0;
452:     for (i=0; i<n; i+=bs) {
453:       for (j=0; j<bs; j++) {
454:         sum[j] += x[i+j]*(PetscConj(x[i+j]));
455:       }
456:     }
457:     for (j=0; j<bs; j++) {
458:       tnorm[j]  = PetscRealPart(sum[j]);
459:     }
460:     MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_SUM,comm);
461:     for (j=0; j<bs; j++) {
462:       nrm[j] = sqrt(nrm[j]);
463:     }
464:   } else if (ntype == NORM_1) {
465:     for (j=0; j<bs; j++) {
466:       tnorm[j] = 0.0;
467:     }
468:     for (i=0; i<n; i+=bs) {
469:       for (j=0; j<bs; j++) {
470:         tnorm[j] += PetscAbsScalar(x[i+j]);
471:       }
472:     }
473:     MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_SUM,comm);
474:   } else if (ntype == NORM_INFINITY) {
475:     PetscReal tmp;
476:     for (j=0; j<bs; j++) {
477:       tnorm[j] = 0.0;
478:     }

480:     for (i=0; i<n; i+=bs) {
481:       for (j=0; j<bs; j++) {
482:         if ((tmp = PetscAbsScalar(x[i+j])) > tnorm[j]) tnorm[j] = tmp;
483:         /* check special case of tmp == NaN */
484:         if (tmp != tmp) {tnorm[j] = tmp; break;}
485:       }
486:     }
487:     MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_MAX,comm);
488:   } else {
489:     SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown norm type");
490:   }

492:   VecRestoreArray(v,&x);
493:   return(0);
494: }

498: /*@
499:    VecStrideMaxAll - Computes the maximums of subvectors of a vector defined 
500:    by a starting point and a stride and optionally its location.

502:    Collective on Vec

504:    Input Parameter:
505: .  v - the vector 

507:    Output Parameter:
508: +  index - the location where the maximum occurred (not supported, pass PETSC_NULL,
509:            if you need this, send mail to petsc-maint@mcs.anl.gov to request it)
510: -  nrm - the maximums

512:    Notes:
513:    One must call VecSetBlockSize() before this routine to set the stride 
514:    information, or use a vector created from a multicomponent DA.

516:    This is useful for computing, say the maximum of the pressure variable when
517:    the pressure is stored (interlaced) with other variables, e.g., density, etc.
518:    This will only work if the desire subvector is a stride subvector.

520:    Level: advanced

522:    Concepts: maximum^on stride of vector
523:    Concepts: stride^maximum

525: .seealso: VecMax(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin()
526: @*/
527: PetscErrorCode  VecStrideMaxAll(Vec v,PetscInt idex[],PetscReal nrm[])
528: {
530:   PetscInt       i,j,n,bs;
531:   PetscScalar    *x;
532:   PetscReal      max[128],tmp;
533:   MPI_Comm       comm;

538:   if (idex) {
539:     SETERRQ(PETSC_ERR_SUP,"No support yet for returning index; send mail to petsc-maint@mcs.anl.gov asking for it");
540:   }
541:   VecGetLocalSize(v,&n);
542:   VecGetArray(v,&x);
543:   PetscObjectGetComm((PetscObject)v,&comm);

545:   bs   = v->map->bs;
546:   if (bs > 128) SETERRQ(PETSC_ERR_SUP,"Currently supports only blocksize up to 128");

548:   if (!n) {
549:     for (j=0; j<bs; j++) {
550:       max[j] = PETSC_MIN;
551:     }
552:   } else {
553:     for (j=0; j<bs; j++) {
554: #if defined(PETSC_USE_COMPLEX)
555:       max[j] = PetscRealPart(x[j]);
556: #else
557:       max[j] = x[j];
558: #endif
559:     }
560:     for (i=bs; i<n; i+=bs) {
561:       for (j=0; j<bs; j++) {
562: #if defined(PETSC_USE_COMPLEX)
563:         if ((tmp = PetscRealPart(x[i+j])) > max[j]) { max[j] = tmp;}
564: #else
565:         if ((tmp = x[i+j]) > max[j]) { max[j] = tmp; }
566: #endif
567:       }
568:     }
569:   }
570:   MPI_Allreduce(max,nrm,bs,MPIU_REAL,MPI_MAX,comm);

572:   VecRestoreArray(v,&x);
573:   return(0);
574: }

578: /*@
579:    VecStrideMinAll - Computes the minimum of subvector of a vector defined 
580:    by a starting point and a stride and optionally its location.

582:    Collective on Vec

584:    Input Parameter:
585: .  v - the vector 

587:    Output Parameter:
588: +  idex - the location where the minimum occurred (not supported, pass PETSC_NULL,
589:            if you need this, send mail to petsc-maint@mcs.anl.gov to request it)
590: -  nrm - the minimums

592:    Level: advanced

594:    Notes:
595:    One must call VecSetBlockSize() before this routine to set the stride 
596:    information, or use a vector created from a multicomponent DA.

598:    This is useful for computing, say the minimum of the pressure variable when
599:    the pressure is stored (interlaced) with other variables, e.g., density, etc.
600:    This will only work if the desire subvector is a stride subvector.

602:    Concepts: minimum^on stride of vector
603:    Concepts: stride^minimum

605: .seealso: VecMin(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMax()
606: @*/
607: PetscErrorCode  VecStrideMinAll(Vec v,PetscInt idex[],PetscReal nrm[])
608: {
610:   PetscInt       i,n,bs,j;
611:   PetscScalar    *x;
612:   PetscReal      min[128],tmp;
613:   MPI_Comm       comm;

618:   if (idex) {
619:     SETERRQ(PETSC_ERR_SUP,"No support yet for returning index; send mail to petsc-maint@mcs.anl.gov asking for it");
620:   }
621:   VecGetLocalSize(v,&n);
622:   VecGetArray(v,&x);
623:   PetscObjectGetComm((PetscObject)v,&comm);

625:   bs   = v->map->bs;
626:   if (bs > 128) SETERRQ(PETSC_ERR_SUP,"Currently supports only blocksize up to 128");

628:   if (!n) {
629:     for (j=0; j<bs; j++) {
630:       min[j] = PETSC_MAX;
631:     }
632:   } else {
633:     for (j=0; j<bs; j++) {
634: #if defined(PETSC_USE_COMPLEX)
635:       min[j] = PetscRealPart(x[j]);
636: #else
637:       min[j] = x[j];
638: #endif
639:     }
640:     for (i=bs; i<n; i+=bs) {
641:       for (j=0; j<bs; j++) {
642: #if defined(PETSC_USE_COMPLEX)
643:         if ((tmp = PetscRealPart(x[i+j])) < min[j]) { min[j] = tmp;}
644: #else
645:         if ((tmp = x[i+j]) < min[j]) { min[j] = tmp; }
646: #endif
647:       }
648:     }
649:   }
650:   MPI_Allreduce(min,nrm,bs,MPIU_REAL,MPI_MIN,comm);

652:   VecRestoreArray(v,&x);
653:   return(0);
654: }

656: /*----------------------------------------------------------------------------------------------*/
659: /*@
660:    VecStrideGatherAll - Gathers all the single components from a multi-component vector into
661:    separate vectors.

663:    Collective on Vec

665:    Input Parameter:
666: +  v - the vector 
667: -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES

669:    Output Parameter:
670: .  s - the location where the subvectors are stored

672:    Notes:
673:    One must call VecSetBlockSize() before this routine to set the stride 
674:    information, or use a vector created from a multicomponent DA.

676:    If x is the array representing the vector x then this gathers
677:    the arrays (x[start],x[start+stride],x[start+2*stride], ....)
678:    for start=0,1,2,...bs-1

680:    The parallel layout of the vector and the subvector must be the same;
681:    i.e., nlocal of v = stride*(nlocal of s) 

683:    Not optimized; could be easily

685:    Level: advanced

687:    Concepts: gather^into strided vector

689: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGather(),
690:           VecStrideScatterAll()
691: @*/
692: PetscErrorCode  VecStrideGatherAll(Vec v,Vec s[],InsertMode addv)
693: {
695:   PetscInt       i,n,n2,bs,j,k,*bss = PETSC_NULL,nv,jj,nvc;
696:   PetscScalar    *x,**y;

702:   VecGetLocalSize(v,&n);
703:   VecGetLocalSize(s[0],&n2);
704:   VecGetArray(v,&x);
705:   bs   = v->map->bs;
706:   if (bs < 0) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set");

708:   PetscMalloc2(bs,PetscReal*,&y,bs,PetscInt,&bss);
709:   nv   = 0;
710:   nvc  = 0;
711:   for (i=0; i<bs; i++) {
712:     VecGetBlockSize(s[i],&bss[i]);
713:     if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1  Re: [PETSC #8241] VecStrideGatherAll */
714:     VecGetArray(s[i],&y[i]);
715:     nvc  += bss[i];
716:     nv++;
717:     if (nvc > bs)  SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of subvectors in subvectors > number of vectors in main vector");
718:     if (nvc == bs) break;
719:   }

721:   n =  n/bs;

723:   jj = 0;
724:   if (addv == INSERT_VALUES) {
725:     for (j=0; j<nv; j++) {
726:       for (k=0; k<bss[j]; k++) {
727:         for (i=0; i<n; i++) {
728:           y[j][i*bss[j] + k] = x[bs*i+jj+k];
729:         }
730:       }
731:       jj += bss[j];
732:     }
733:   } else if (addv == ADD_VALUES) {
734:     for (j=0; j<nv; j++) {
735:       for (k=0; k<bss[j]; k++) {
736:         for (i=0; i<n; i++) {
737:           y[j][i*bss[j] + k] += x[bs*i+jj+k];
738:         }
739:       }
740:       jj += bss[j];
741:     }
742: #if !defined(PETSC_USE_COMPLEX)
743:   } else if (addv == MAX_VALUES) {
744:     for (j=0; j<nv; j++) {
745:       for (k=0; k<bss[j]; k++) {
746:         for (i=0; i<n; i++) {
747:           y[j][i*bss[j] + k] = PetscMax(y[j][i*bss[j] + k],x[bs*i+jj+k]);
748:         }
749:       }
750:       jj += bss[j];
751:     }
752: #endif
753:   } else {
754:     SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
755:   }

757:   VecRestoreArray(v,&x);
758:   for (i=0; i<nv; i++) {
759:     VecRestoreArray(s[i],&y[i]);
760:   }

762:   PetscFree2(y,bss);
763:   return(0);
764: }

768: /*@
769:    VecStrideScatterAll - Scatters all the single components from separate vectors into 
770:      a multi-component vector.

772:    Collective on Vec

774:    Input Parameter:
775: +  s - the location where the subvectors are stored
776: -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES

778:    Output Parameter:
779: .  v - the multicomponent vector 

781:    Notes:
782:    One must call VecSetBlockSize() before this routine to set the stride 
783:    information, or use a vector created from a multicomponent DA.

785:    The parallel layout of the vector and the subvector must be the same;
786:    i.e., nlocal of v = stride*(nlocal of s) 

788:    Not optimized; could be easily

790:    Level: advanced

792:    Concepts:  scatter^into strided vector

794: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGather(),
795:           VecStrideScatterAll()
796: @*/
797: PetscErrorCode  VecStrideScatterAll(Vec s[],Vec v,InsertMode addv)
798: {
800:   PetscInt        i,n,n2,bs,j,jj,k,*bss = PETSC_NULL,nv,nvc;
801:   PetscScalar     *x,**y;

807:   VecGetLocalSize(v,&n);
808:   VecGetLocalSize(s[0],&n2);
809:   VecGetArray(v,&x);
810:   bs   = v->map->bs;
811:   if (bs < 0) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set");

813:   PetscMalloc2(bs,PetscScalar**,&y,bs,PetscInt,&bss);
814:   nv  = 0;
815:   nvc = 0;
816:   for (i=0; i<bs; i++) {
817:     VecGetBlockSize(s[i],&bss[i]);
818:     if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1  Re: [PETSC #8241] VecStrideGatherAll */
819:     VecGetArray(s[i],&y[i]);
820:     nvc  += bss[i];
821:     nv++;
822:     if (nvc > bs)  SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of subvectors in subvectors > number of vectors in main vector");
823:     if (nvc == bs) break;
824:   }

826:   n =  n/bs;

828:   jj = 0;
829:   if (addv == INSERT_VALUES) {
830:     for (j=0; j<nv; j++) {
831:       for (k=0; k<bss[j]; k++) {
832:         for (i=0; i<n; i++) {
833:           x[bs*i+jj+k] = y[j][i*bss[j] + k];
834:         }
835:       }
836:       jj += bss[j];
837:     }
838:   } else if (addv == ADD_VALUES) {
839:     for (j=0; j<nv; j++) {
840:       for (k=0; k<bss[j]; k++) {
841:         for (i=0; i<n; i++) {
842:           x[bs*i+jj+k] += y[j][i*bss[j] + k];
843:         }
844:       }
845:       jj += bss[j];
846:     }
847: #if !defined(PETSC_USE_COMPLEX)
848:   } else if (addv == MAX_VALUES) {
849:     for (j=0; j<nv; j++) {
850:       for (k=0; k<bss[j]; k++) {
851:         for (i=0; i<n; i++) {
852:           x[bs*i+jj+k] = PetscMax(x[bs*i+jj+k],y[j][i*bss[j] + k]);
853:         }
854:       }
855:       jj += bss[j];
856:     }
857: #endif
858:   } else {
859:     SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
860:   }

862:   VecRestoreArray(v,&x);
863:   for (i=0; i<nv; i++) {
864:     VecRestoreArray(s[i],&y[i]);
865:   }
866:   PetscFree2(y,bss);
867:   return(0);
868: }

872: /*@
873:    VecStrideGather - Gathers a single component from a multi-component vector into
874:    another vector.

876:    Collective on Vec

878:    Input Parameter:
879: +  v - the vector 
880: .  start - starting point of the subvector (defined by a stride)
881: -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES

883:    Output Parameter:
884: .  s - the location where the subvector is stored

886:    Notes:
887:    One must call VecSetBlockSize() before this routine to set the stride 
888:    information, or use a vector created from a multicomponent DA.

890:    If x is the array representing the vector x then this gathers
891:    the array (x[start],x[start+stride],x[start+2*stride], ....)

893:    The parallel layout of the vector and the subvector must be the same;
894:    i.e., nlocal of v = stride*(nlocal of s) 

896:    Not optimized; could be easily

898:    Level: advanced

900:    Concepts: gather^into strided vector

902: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(),
903:           VecStrideScatterAll()
904: @*/
905: PetscErrorCode  VecStrideGather(Vec v,PetscInt start,Vec s,InsertMode addv)
906: {
908:   PetscInt       i,n,bs,ns;
909:   PetscScalar    *x,*y;

914:   VecGetLocalSize(v,&n);
915:   VecGetLocalSize(s,&ns);
916:   VecGetArray(v,&x);
917:   VecGetArray(s,&y);

919:   bs   = v->map->bs;
920:   if (start < 0) {
921:     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
922:   } else if (start >= bs) {
923:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
924:             Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
925:   }
926:   if (n != ns*bs) {
927:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Subvector length * blocksize %D not correct for gather from original vector %D",ns*bs,n);
928:   }
929:   x += start;
930:   n =  n/bs;

932:   if (addv == INSERT_VALUES) {
933:     for (i=0; i<n; i++) {
934:       y[i] = x[bs*i];
935:     }
936:   } else if (addv == ADD_VALUES) {
937:     for (i=0; i<n; i++) {
938:       y[i] += x[bs*i];
939:     }
940: #if !defined(PETSC_USE_COMPLEX)
941:   } else if (addv == MAX_VALUES) {
942:     for (i=0; i<n; i++) {
943:       y[i] = PetscMax(y[i],x[bs*i]);
944:     }
945: #endif
946:   } else {
947:     SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
948:   }

950:   VecRestoreArray(v,&x);
951:   VecRestoreArray(s,&y);
952:   return(0);
953: }

957: /*@
958:    VecStrideScatter - Scatters a single component from a vector into a multi-component vector.

960:    Collective on Vec

962:    Input Parameter:
963: +  s - the single-component vector 
964: .  start - starting point of the subvector (defined by a stride)
965: -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES

967:    Output Parameter:
968: .  v - the location where the subvector is scattered (the multi-component vector)

970:    Notes:
971:    One must call VecSetBlockSize() on the multi-component vector before this
972:    routine to set the stride  information, or use a vector created from a multicomponent DA.

974:    The parallel layout of the vector and the subvector must be the same;
975:    i.e., nlocal of v = stride*(nlocal of s) 

977:    Not optimized; could be easily

979:    Level: advanced

981:    Concepts: scatter^into strided vector

983: .seealso: VecStrideNorm(), VecStrideGather(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(),
984:           VecStrideScatterAll()
985: @*/
986: PetscErrorCode  VecStrideScatter(Vec s,PetscInt start,Vec v,InsertMode addv)
987: {
989:   PetscInt       i,n,bs,ns;
990:   PetscScalar    *x,*y;

995:   VecGetLocalSize(v,&n);
996:   VecGetLocalSize(s,&ns);
997:   VecGetArray(v,&x);
998:   VecGetArray(s,&y);

1000:   bs   = v->map->bs;
1001:   if (start < 0) {
1002:     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
1003:   } else if (start >= bs) {
1004:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
1005:             Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
1006:   }
1007:   if (n != ns*bs) {
1008:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Subvector length * blocksize %D not correct for scatter to multicomponent vector %D",ns*bs,n);
1009:   }
1010:   x += start;
1011:   n =  n/bs;


1014:   if (addv == INSERT_VALUES) {
1015:     for (i=0; i<n; i++) {
1016:       x[bs*i] = y[i];
1017:     }
1018:   } else if (addv == ADD_VALUES) {
1019:     for (i=0; i<n; i++) {
1020:       x[bs*i] += y[i];
1021:     }
1022: #if !defined(PETSC_USE_COMPLEX)
1023:   } else if (addv == MAX_VALUES) {
1024:     for (i=0; i<n; i++) {
1025:       x[bs*i] = PetscMax(y[i],x[bs*i]);
1026:     }
1027: #endif
1028:   } else {
1029:     SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
1030:   }


1033:   VecRestoreArray(v,&x);
1034:   VecRestoreArray(s,&y);
1035:   return(0);
1036: }

1040: PetscErrorCode VecReciprocal_Default(Vec v)
1041: {
1043:   PetscInt       i,n;
1044:   PetscScalar    *x;

1047:   VecGetLocalSize(v,&n);
1048:   VecGetArray(v,&x);
1049:   for (i=0; i<n; i++) {
1050:     if (x[i] != 0.0) x[i] = 1.0/x[i];
1051:   }
1052:   VecRestoreArray(v,&x);
1053:   return(0);
1054: }

1058: /*@
1059:   VecExp - Replaces each component of a vector by e^x_i

1061:   Not collective

1063:   Input Parameter:
1064: . v - The vector

1066:   Output Parameter:
1067: . v - The vector of exponents

1069:   Level: beginner

1071: .seealso:  VecLog(), VecAbs(), VecSqrt()

1073: .keywords: vector, sqrt, square root
1074: @*/
1075: PetscErrorCode  VecExp(Vec v)
1076: {
1077:   PetscScalar    *x;
1078:   PetscInt       i, n;

1083:   if (v->ops->exp) {
1084:     (*v->ops->exp)(v);
1085:   } else {
1086:     VecGetLocalSize(v, &n);
1087:     VecGetArray(v, &x);
1088:     for(i = 0; i < n; i++) {
1089:       x[i] = PetscExpScalar(x[i]);
1090:     }
1091:     VecRestoreArray(v, &x);
1092:   }
1093:   return(0);
1094: }

1098: /*@
1099:   VecLog - Replaces each component of a vector by log(x_i)

1101:   Not collective

1103:   Input Parameter:
1104: . v - The vector

1106:   Output Parameter:
1107: . v - The vector of logs

1109:   Level: beginner

1111: .seealso:  VecExp(), VecAbs(), VecSqrt()

1113: .keywords: vector, sqrt, square root
1114: @*/
1115: PetscErrorCode  VecLog(Vec v)
1116: {
1117:   PetscScalar    *x;
1118:   PetscInt       i, n;

1123:   if (v->ops->log) {
1124:     (*v->ops->log)(v);
1125:   } else {
1126:     VecGetLocalSize(v, &n);
1127:     VecGetArray(v, &x);
1128:     for(i = 0; i < n; i++) {
1129:       x[i] = PetscLogScalar(x[i]);
1130:     }
1131:     VecRestoreArray(v, &x);
1132:   }
1133:   return(0);
1134: }

1138: /*@
1139:   VecSqrt - Replaces each component of a vector by the square root of its magnitude.

1141:   Not collective

1143:   Input Parameter:
1144: . v - The vector

1146:   Output Parameter:
1147: . v - The vector square root

1149:   Level: beginner

1151:   Note: The actual function is sqrt(|x_i|)

1153: .keywords: vector, sqrt, square root
1154: @*/
1155: PetscErrorCode  VecSqrt(Vec v)
1156: {
1157:   PetscScalar    *x;
1158:   PetscInt       i, n;

1163:   if (v->ops->sqrt) {
1164:     (*v->ops->sqrt)(v);
1165:   } else {
1166:     VecGetLocalSize(v, &n);
1167:     VecGetArray(v, &x);
1168:     for(i = 0; i < n; i++) {
1169:       x[i] = sqrt(PetscAbsScalar(x[i]));
1170:     }
1171:     VecRestoreArray(v, &x);
1172:   }
1173:   return(0);
1174: }

1178: /*@
1179:   VecDotNorm2 - computes the inner product of two vectors and the 2-norm squared of the second vector

1181:   Collective on Vec

1183:   Input Parameter:
1184: + s - first vector
1185: - t - second vector

1187:   Output Parameter:
1188: + dp - s't
1189: - nm - t't

1191:   Level: advanced

1193: .seealso:   VecDot(), VecNorm(), VecDotBegin(), VecNormBegin(), VecDotEnd(), VecNormEnd()

1195: .keywords: vector, sqrt, square root
1196: @*/
1197: PetscErrorCode  VecDotNorm2(Vec s,Vec t,PetscScalar *dp, PetscScalar *nm)
1198: {
1199:   PetscScalar    *sx, *tx, dpx = 0.0, nmx = 0.0,work[2],sum[2];
1200:   PetscInt       i, n;


1207:   PetscLogEventBarrierBegin(VEC_DotNormBarrier,s,t,0,0,((PetscObject)s)->comm);
1208:   VecGetLocalSize(s, &n);
1209:   VecGetArray(s, &sx);
1210:   VecGetArray(t, &tx);

1212:   for (i = 0; i<n; i++) {
1213:     dpx += sx[i]*PetscConj(tx[i]);
1214:     nmx += tx[i]*PetscConj(tx[i]);
1215:   }
1216:   work[0] = dpx;
1217:   work[1] = nmx;
1218:   MPI_Allreduce(&work,&sum,2,MPIU_SCALAR,MPIU_SUM,((PetscObject)s)->comm);
1219:   *dp  = sum[0];
1220:   *nm  = sum[1];
1221: 
1222:   VecRestoreArray(t, &tx);
1223:   VecRestoreArray(s, &sx);
1224:   PetscLogFlops(4.0*n);
1225:   PetscLogEventBarrierEnd(VEC_DotNormBarrier,s,t,0,0,((PetscObject)s)->comm);
1226:   return(0);
1227: }

1231: /*@
1232:    VecSum - Computes the sum of all the components of a vector.

1234:    Collective on Vec

1236:    Input Parameter:
1237: .  v - the vector 

1239:    Output Parameter:
1240: .  sum - the result

1242:    Level: beginner

1244:    Concepts: sum^of vector entries

1246: .seealso: VecNorm()
1247: @*/
1248: PetscErrorCode  VecSum(Vec v,PetscScalar *sum)
1249: {
1251:   PetscInt       i,n;
1252:   PetscScalar    *x,lsum = 0.0;

1257:   VecGetLocalSize(v,&n);
1258:   VecGetArray(v,&x);
1259:   for (i=0; i<n; i++) {
1260:     lsum += x[i];
1261:   }
1262:   MPI_Allreduce(&lsum,sum,1,MPIU_SCALAR,MPIU_SUM,((PetscObject)v)->comm);
1263:   VecRestoreArray(v,&x);
1264:   return(0);
1265: }

1269: /*@
1270:    VecShift - Shifts all of the components of a vector by computing
1271:    x[i] = x[i] + shift.

1273:    Collective on Vec

1275:    Input Parameters:
1276: +  v - the vector 
1277: -  shift - the shift

1279:    Output Parameter:
1280: .  v - the shifted vector 

1282:    Level: intermediate

1284:    Concepts: vector^adding constant

1286: @*/
1287: PetscErrorCode  VecShift(Vec v,PetscScalar shift)
1288: {
1290:   PetscInt       i,n;
1291:   PetscScalar    *x;

1295:   if (v->ops->shift) {
1296:     (*v->ops->shift)(v);
1297:   } else {
1298:     VecGetLocalSize(v,&n);
1299:     VecGetArray(v,&x);
1300:     for (i=0; i<n; i++) {
1301:       x[i] += shift;
1302:     }
1303:     VecRestoreArray(v,&x);
1304:   }
1305:   return(0);
1306: }

1310: /*@
1311:    VecAbs - Replaces every element in a vector with its absolute value.

1313:    Collective on Vec

1315:    Input Parameters:
1316: .  v - the vector 

1318:    Level: intermediate

1320:    Concepts: vector^absolute value

1322: @*/
1323: PetscErrorCode  VecAbs(Vec v)
1324: {
1326:   PetscInt       i,n;
1327:   PetscScalar    *x;

1331:   if (v->ops->abs) {
1332:     (*v->ops->abs)(v);
1333:   } else {
1334:     VecGetLocalSize(v,&n);
1335:     VecGetArray(v,&x);
1336:     for (i=0; i<n; i++) {
1337:       x[i] = PetscAbsScalar(x[i]);
1338:     }
1339:     VecRestoreArray(v,&x);
1340:   }
1341:   return(0);
1342: }

1346: /*@
1347:   VecPermute - Permutes a vector in place using the given ordering.

1349:   Input Parameters:
1350: + vec   - The vector
1351: . order - The ordering
1352: - inv   - The flag for inverting the permutation

1354:   Level: beginner

1356:   Note: This function does not yet support parallel Index Sets

1358: .seealso: MatPermute()
1359: .keywords: vec, permute
1360: @*/
1361: PetscErrorCode  VecPermute(Vec x, IS row, PetscTruth inv)
1362: {
1363:   PetscScalar    *array, *newArray;
1364:   const PetscInt *idx;
1365:   PetscInt       i;

1369:   ISGetIndices(row, &idx);
1370:   VecGetArray(x, &array);
1371:   PetscMalloc(x->map->n*sizeof(PetscScalar), &newArray);
1372: #ifdef PETSC_USE_DEBUG
1373:   for(i = 0; i < x->map->n; i++) {
1374:     if ((idx[i] < 0) || (idx[i] >= x->map->n)) {
1375:       SETERRQ2(PETSC_ERR_ARG_CORRUPT, "Permutation index %D is out of bounds: %D", i, idx[i]);
1376:     }
1377:   }
1378: #endif
1379:   if (!inv) {
1380:     for(i = 0; i < x->map->n; i++) newArray[i]      = array[idx[i]];
1381:   } else {
1382:     for(i = 0; i < x->map->n; i++) newArray[idx[i]] = array[i];
1383:   }
1384:   VecRestoreArray(x, &array);
1385:   ISRestoreIndices(row, &idx);
1386:   VecReplaceArray(x, newArray);
1387:   return(0);
1388: }

1392: /*@
1393:    VecEqual - Compares two vectors.

1395:    Collective on Vec

1397:    Input Parameters:
1398: +  vec1 - the first vector
1399: -  vec2 - the second vector

1401:    Output Parameter:
1402: .  flg - PETSC_TRUE if the vectors are equal; PETSC_FALSE otherwise.

1404:    Level: intermediate

1406:    Concepts: equal^two vectors
1407:    Concepts: vector^equality

1409: @*/
1410: PetscErrorCode  VecEqual(Vec vec1,Vec vec2,PetscTruth *flg)
1411: {
1412:   PetscScalar    *v1,*v2;
1414:   PetscInt       n1,n2,N1,N2;
1415:   PetscInt       state1,state2;
1416:   PetscTruth     flg1;
1417: 
1422:   if (vec1 == vec2) {
1423:     *flg = PETSC_TRUE;
1424:   } else {
1425:     VecGetSize(vec1,&N1);
1426:     VecGetSize(vec2,&N2);
1427:     if (N1 != N2) {
1428:       flg1 = PETSC_FALSE;
1429:     } else {
1430:       VecGetLocalSize(vec1,&n1);
1431:       VecGetLocalSize(vec2,&n2);
1432:       if (n1 != n2) {
1433:         flg1 = PETSC_FALSE;
1434:       } else {
1435:         PetscObjectStateQuery((PetscObject) vec1,&state1);
1436:         PetscObjectStateQuery((PetscObject) vec2,&state2);
1437:         VecGetArray(vec1,&v1);
1438:         VecGetArray(vec2,&v2);
1439: #if defined(PETSC_USE_COMPLEX)
1440:         PetscInt k;
1441:         for (k=0; k<n1; k++){
1442:           if (PetscRealPart(v1[k]) != PetscRealPart(v2[k]) || PetscImaginaryPart(v1[k]) != PetscImaginaryPart(v2[k])){
1443:             flg1 = PETSC_FALSE;
1444:             break;
1445:           }
1446:         }
1447: #else 
1448:         PetscMemcmp(v1,v2,n1*sizeof(PetscScalar),&flg1);
1449: #endif
1450:         VecRestoreArray(vec1,&v1);
1451:         VecRestoreArray(vec2,&v2);
1452:         PetscObjectSetState((PetscObject) vec1,state1);
1453:         PetscObjectSetState((PetscObject) vec2,state2);
1454:       }
1455:     }
1456:     /* combine results from all processors */
1457:     MPI_Allreduce(&flg1,flg,1,MPI_INT,MPI_MIN,((PetscObject)vec1)->comm);
1458:   }
1459:   return(0);
1460: }