Actual source code: vinv.c

  1: /*
  2:      Some useful vector utility functions.
  3: */
 4:  #include vecimpl.h


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

 15:    Collective on Vec

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

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

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

 28:    Level: advanced

 30:    Concepts: scale^on stride of vector
 31:    Concepts: stride^scale

 33: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideScale()
 34: @*/
 35: PetscErrorCode VecStrideScale(Vec v,PetscInt start,PetscScalar *scale)
 36: {
 38:   PetscInt       i,n,bs;
 39:   PetscScalar    *x,xscale = *scale;

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

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

 54:   for (i=0; i<n; i+=bs) {
 55:     x[i] *= xscale;
 56:   }
 57:   x -= start;
 58:   VecRestoreArray(v,&x);
 59:   return(0);
 60: }

 64: /*@C
 65:    VecStrideNorm - Computes the norm of subvector of a vector defined 
 66:    by a starting point and a stride.

 68:    Collective on Vec

 70:    Input Parameter:
 71: +  v - the vector 
 72: .  start - starting point of the subvector (defined by a stride)
 73: -  ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY

 75:    Output Parameter:
 76: .  norm - the norm

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

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

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

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

 90:    Level: advanced

 92:    Concepts: norm^on stride of vector
 93:    Concepts: stride^norm

 95: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
 96: @*/
 97: PetscErrorCode VecStrideNorm(Vec v,PetscInt start,NormType ntype,PetscReal *nrm)
 98: {
100:   PetscInt       i,n,bs;
101:   PetscScalar    *x;
102:   PetscReal      tnorm;
103:   MPI_Comm       comm;

108:   VecGetLocalSize(v,&n);
109:   VecGetArray(v,&x);
110:   PetscObjectGetComm((PetscObject)v,&comm);

112:   bs   = v->bs;
113:   if (start >= bs) {
114:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
115:             Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
116:   }
117:   x += start;

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

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

147:   VecRestoreArray(v,&x);
148:   return(0);
149: }

153: /*@
154:    VecStrideMax - Computes the maximum of subvector of a vector defined 
155:    by a starting point and a stride and optionally its location.

157:    Collective on Vec

159:    Input Parameter:
160: +  v - the vector 
161: -  start - starting point of the subvector (defined by a stride)

163:    Output Parameter:
164: +  index - the location where the maximum occurred  (pass PETSC_NULL if not required)
165: -  nrm - the max

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

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

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

178:    Level: advanced

180:    Concepts: maximum^on stride of vector
181:    Concepts: stride^maximum

183: .seealso: VecMax(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin()
184: @*/
185: PetscErrorCode VecStrideMax(Vec v,PetscInt start,PetscInt *idex,PetscReal *nrm)
186: {
188:   PetscInt       i,n,bs,id;
189:   PetscScalar    *x;
190:   PetscReal      max,tmp;
191:   MPI_Comm       comm;


197:   VecGetLocalSize(v,&n);
198:   VecGetArray(v,&x);
199:   PetscObjectGetComm((PetscObject)v,&comm);

201:   bs   = v->bs;
202:   if (start >= bs) {
203:     SETERRQ2(PETSC_ERR_ARG_WRONG,"Start of stride subvector (%D) is too large for stride\n\
204:             Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
205:   }
206:   x += start;

208:   id = -1;
209:   if (!n) {
210:     max = PETSC_MIN;
211:   } else {
212: #if defined(PETSC_USE_COMPLEX)
213:     max = PetscRealPart(x[0]);
214: #else
215:     max = x[0];
216: #endif
217:     for (i=bs; i<n; i+=bs) {
218: #if defined(PETSC_USE_COMPLEX)
219:       if ((tmp = PetscRealPart(x[i])) > max) { max = tmp; id = i;}
220: #else
221:       if ((tmp = x[i]) > max) { max = tmp; id = i;}
222: #endif
223:     }
224:   }
225:   VecRestoreArray(v,&x);

227:   if (!idex) {
228:     MPI_Allreduce(&max,nrm,1,MPIU_REAL,MPI_MAX,comm);
229:   } else {
230:     PetscReal in[2],out[2];
231:     PetscInt  rstart;

233:     VecGetOwnershipRange(v,&rstart,PETSC_NULL);
234:     in[0] = max;
235:     in[1] = rstart+id;
236:     MPI_Allreduce(in,out,2,MPIU_REAL,VecMax_Local_Op,v->comm);
237:     *nrm  = out[0];
238:     *idex = (PetscInt)out[1];
239:   }

241:   return(0);
242: }

246: /*@
247:    VecStrideMin - Computes the minimum of subvector of a vector defined 
248:    by a starting point and a stride and optionally its location.

250:    Collective on Vec

252:    Input Parameter:
253: +  v - the vector 
254: -  start - starting point of the subvector (defined by a stride)

256:    Output Parameter:
257: +  idex - the location where the minimum occurred. (pass PETSC_NULL if not required)
258: -  nrm - the min

260:    Level: advanced

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

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

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

273:    Concepts: minimum^on stride of vector
274:    Concepts: stride^minimum

276: .seealso: VecMin(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMax()
277: @*/
278: PetscErrorCode VecStrideMin(Vec v,PetscInt start,PetscInt *idex,PetscReal *nrm)
279: {
281:   PetscInt       i,n,bs,id;
282:   PetscScalar    *x;
283:   PetscReal      min,tmp;
284:   MPI_Comm       comm;


290:   VecGetLocalSize(v,&n);
291:   VecGetArray(v,&x);
292:   PetscObjectGetComm((PetscObject)v,&comm);

294:   bs   = v->bs;
295:   if (start >= bs) {
296:     SETERRQ2(PETSC_ERR_ARG_WRONG,"Start of stride subvector (%D) is too large for stride\n\
297:             Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
298:   }
299:   x += start;

301:   id = -1;
302:   if (!n) {
303:     min = PETSC_MAX;
304:   } else {
305: #if defined(PETSC_USE_COMPLEX)
306:     min = PetscRealPart(x[0]);
307: #else
308:     min = x[0];
309: #endif
310:     for (i=bs; i<n; i+=bs) {
311: #if defined(PETSC_USE_COMPLEX)
312:       if ((tmp = PetscRealPart(x[i])) < min) { min = tmp; id = i;}
313: #else
314:       if ((tmp = x[i]) < min) { min = tmp; id = i;}
315: #endif
316:     }
317:   }
318:   VecRestoreArray(v,&x);

320:   if (!idex) {
321:     MPI_Allreduce(&min,nrm,1,MPIU_REAL,MPI_MIN,comm);
322:   } else {
323:     PetscReal in[2],out[2];
324:     PetscInt  rstart;

326:     VecGetOwnershipRange(v,&rstart,PETSC_NULL);
327:     in[0] = min;
328:     in[1] = rstart+id;
329:     MPI_Allreduce(in,out,2,MPIU_REAL,VecMin_Local_Op,v->comm);
330:     *nrm  = out[0];
331:     *idex = (PetscInt)out[1];
332:   }

334:   return(0);
335: }

339: /*@
340:    VecStrideScaleAll - Scales the subvectors of a vector defined 
341:    by a starting point and a stride.

343:    Collective on Vec

345:    Input Parameter:
346: +  v - the vector 
347: -  scales - values to multiply each subvector entry by

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


354:    Level: advanced

356:    Concepts: scale^on stride of vector
357:    Concepts: stride^scale

359: .seealso: VecNorm(), VecStrideScale(), VecScale(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
360: @*/
361: PetscErrorCode VecStrideScaleAll(Vec v,PetscScalar *scales)
362: {
364:   PetscInt         i,j,n,bs;
365:   PetscScalar *x;

370:   VecGetLocalSize(v,&n);
371:   VecGetArray(v,&x);

373:   bs   = v->bs;

375:   /* need to provide optimized code for each bs */
376:   for (i=0; i<n; i+=bs) {
377:     for (j=0; j<bs; j++) {
378:       x[i+j] *= scales[j];
379:     }
380:   }
381:   VecRestoreArray(v,&x);
382:   return(0);
383: }

387: /*@
388:    VecStrideNormAll - Computes the norms  subvectors of a vector defined 
389:    by a starting point and a stride.

391:    Collective on Vec

393:    Input Parameter:
394: +  v - the vector 
395: -  ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY

397:    Output Parameter:
398: .  nrm - the norms

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

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

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

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

412:    Level: advanced

414:    Concepts: norm^on stride of vector
415:    Concepts: stride^norm

417: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
418: @*/
419: PetscErrorCode VecStrideNormAll(Vec v,NormType ntype,PetscReal *nrm)
420: {
422:   PetscInt         i,j,n,bs;
423:   PetscScalar *x;
424:   PetscReal   tnorm[128];
425:   MPI_Comm    comm;

430:   VecGetLocalSize(v,&n);
431:   VecGetArray(v,&x);
432:   PetscObjectGetComm((PetscObject)v,&comm);

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

437:   if (ntype == NORM_2) {
438:     PetscScalar sum[128];
439:     for (j=0; j<bs; j++) sum[j] = 0.0;
440:     for (i=0; i<n; i+=bs) {
441:       for (j=0; j<bs; j++) {
442:         sum[j] += x[i+j]*(PetscConj(x[i+j]));
443:       }
444:     }
445:     for (j=0; j<bs; j++) {
446:       tnorm[j]  = PetscRealPart(sum[j]);
447:     }
448:     MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_SUM,comm);
449:     for (j=0; j<bs; j++) {
450:       nrm[j] = sqrt(nrm[j]);
451:     }
452:   } else if (ntype == NORM_1) {
453:     for (j=0; j<bs; j++) {
454:       tnorm[j] = 0.0;
455:     }
456:     for (i=0; i<n; i+=bs) {
457:       for (j=0; j<bs; j++) {
458:         tnorm[j] += PetscAbsScalar(x[i+j]);
459:       }
460:     }
461:     MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_SUM,comm);
462:   } else if (ntype == NORM_INFINITY) {
463:     PetscReal tmp;
464:     for (j=0; j<bs; j++) {
465:       tnorm[j] = 0.0;
466:     }

468:     for (i=0; i<n; i+=bs) {
469:       for (j=0; j<bs; j++) {
470:         if ((tmp = PetscAbsScalar(x[i+j])) > tnorm[j]) tnorm[j] = tmp;
471:         /* check special case of tmp == NaN */
472:         if (tmp != tmp) {tnorm[j] = tmp; break;}
473:       }
474:     }
475:     MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_MAX,comm);
476:   } else {
477:     SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown norm type");
478:   }

480:   VecRestoreArray(v,&x);
481:   return(0);
482: }

486: /*@
487:    VecStrideMaxAll - Computes the maximums of subvectors of a vector defined 
488:    by a starting point and a stride and optionally its location.

490:    Collective on Vec

492:    Input Parameter:
493: .  v - the vector 

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

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

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

508:    Level: advanced

510:    Concepts: maximum^on stride of vector
511:    Concepts: stride^maximum

513: .seealso: VecMax(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin()
514: @*/
515: PetscErrorCode VecStrideMaxAll(Vec v,PetscInt *idex,PetscReal *nrm)
516: {
518:   PetscInt         i,j,n,bs;
519:   PetscScalar *x;
520:   PetscReal   max[128],tmp;
521:   MPI_Comm    comm;

526:   if (idex) {
527:     SETERRQ(PETSC_ERR_SUP,"No support yet for returning index; send mail to petsc-maint@mcs.anl.gov asking for it");
528:   }
529:   VecGetLocalSize(v,&n);
530:   VecGetArray(v,&x);
531:   PetscObjectGetComm((PetscObject)v,&comm);

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

536:   if (!n) {
537:     for (j=0; j<bs; j++) {
538:       max[j] = PETSC_MIN;
539:     }
540:   } else {
541:     for (j=0; j<bs; j++) {
542: #if defined(PETSC_USE_COMPLEX)
543:       max[j] = PetscRealPart(x[j]);
544: #else
545:       max[j] = x[j];
546: #endif
547:     }
548:     for (i=bs; i<n; i+=bs) {
549:       for (j=0; j<bs; j++) {
550: #if defined(PETSC_USE_COMPLEX)
551:         if ((tmp = PetscRealPart(x[i+j])) > max[j]) { max[j] = tmp;}
552: #else
553:         if ((tmp = x[i+j]) > max[j]) { max[j] = tmp; }
554: #endif
555:       }
556:     }
557:   }
558:   MPI_Allreduce(max,nrm,bs,MPIU_REAL,MPI_MAX,comm);

560:   VecRestoreArray(v,&x);
561:   return(0);
562: }

566: /*@
567:    VecStrideMinAll - Computes the minimum of subvector of a vector defined 
568:    by a starting point and a stride and optionally its location.

570:    Collective on Vec

572:    Input Parameter:
573: .  v - the vector 

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

580:    Level: advanced

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

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

590:    Concepts: minimum^on stride of vector
591:    Concepts: stride^minimum

593: .seealso: VecMin(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMax()
594: @*/
595: PetscErrorCode VecStrideMinAll(Vec v,PetscInt *idex,PetscReal *nrm)
596: {
598:   PetscInt         i,n,bs,j;
599:   PetscScalar *x;
600:   PetscReal   min[128],tmp;
601:   MPI_Comm    comm;

606:   if (idex) {
607:     SETERRQ(PETSC_ERR_SUP,"No support yet for returning index; send mail to petsc-maint@mcs.anl.gov asking for it");
608:   }
609:   VecGetLocalSize(v,&n);
610:   VecGetArray(v,&x);
611:   PetscObjectGetComm((PetscObject)v,&comm);

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

616:   if (!n) {
617:     for (j=0; j<bs; j++) {
618:       min[j] = PETSC_MAX;
619:     }
620:   } else {
621:     for (j=0; j<bs; j++) {
622: #if defined(PETSC_USE_COMPLEX)
623:       min[j] = PetscRealPart(x[j]);
624: #else
625:       min[j] = x[j];
626: #endif
627:     }
628:     for (i=bs; i<n; i+=bs) {
629:       for (j=0; j<bs; j++) {
630: #if defined(PETSC_USE_COMPLEX)
631:         if ((tmp = PetscRealPart(x[i+j])) < min[j]) { min[j] = tmp;}
632: #else
633:         if ((tmp = x[i+j]) < min[j]) { min[j] = tmp; }
634: #endif
635:       }
636:     }
637:   }
638:   MPI_Allreduce(min,nrm,bs,MPIU_REAL,MPI_MIN,comm);

640:   VecRestoreArray(v,&x);
641:   return(0);
642: }

644: /*----------------------------------------------------------------------------------------------*/
647: /*@
648:    VecStrideGatherAll - Gathers all the single components from a multi-component vector into
649:    seperate vectors.

651:    Collective on Vec

653:    Input Parameter:
654: +  v - the vector 
655: -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES

657:    Output Parameter:
658: .  s - the location where the subvectors are stored

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

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

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

671:    Not optimized; could be easily

673:    Level: advanced

675:    Concepts: gather^into strided vector

677: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGather(),
678:           VecStrideScatterAll()
679: @*/
680: PetscErrorCode VecStrideGatherAll(Vec v,Vec *s,InsertMode addv)
681: {
683:   PetscInt       i,n,bs,j,k,*bss,nv,jj,nvc;
684:   PetscScalar    *x,**y;

690:   VecGetLocalSize(v,&n);
691:   VecGetArray(v,&x);
692:   bs   = v->bs;
693:   if (bs < 0) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set");

695:   PetscMalloc2(bs,PetscReal*,&y,bs,PetscInt,&bss);
696:   nv   = 0;
697:   nvc  = 0;
698:   for (i=0; i<bs; i++) {
699:     VecGetBlockSize(s[i],&bss[i]);
700:     if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1  Re: [PETSC #8241] VecStrideGatherAll */
701:     VecGetArray(s[i],&y[i]);
702:     nvc  += bss[i];
703:     nv++;
704:     if (nvc > bs)  SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of subvectors in subvectors > number of vectors in main vector");
705:     if (nvc == bs) break;
706:   }

708:   n =  n/bs;

710:   jj = 0;
711:   if (addv == INSERT_VALUES) {
712:     for (j=0; j<nv; j++) {
713:       for (k=0; k<bss[j]; k++) {
714:         for (i=0; i<n; i++) {
715:           y[j][i*bss[j] + k] = x[bs*i+jj+k];
716:         }
717:       }
718:       jj += bss[j];
719:     }
720:   } else if (addv == ADD_VALUES) {
721:     for (j=0; j<nv; j++) {
722:       for (k=0; k<bss[j]; k++) {
723:         for (i=0; i<n; i++) {
724:           y[j][i*bss[j] + k] += x[bs*i+jj+k];
725:         }
726:       }
727:       jj += bss[j];
728:     }
729: #if !defined(PETSC_USE_COMPLEX)
730:   } else if (addv == MAX_VALUES) {
731:     for (j=0; j<nv; j++) {
732:       for (k=0; k<bss[j]; k++) {
733:         for (i=0; i<n; i++) {
734:           y[j][i*bss[j] + k] = PetscMax(y[j][i*bss[j] + k],x[bs*i+jj+k]);
735:         }
736:       }
737:       jj += bss[j];
738:     }
739: #endif
740:   } else {
741:     SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
742:   }

744:   VecRestoreArray(v,&x);
745:   for (i=0; i<nv; i++) {
746:     VecRestoreArray(s[i],&y[i]);
747:   }
748:   PetscFree2(y,bss);
749:   return(0);
750: }

754: /*@
755:    VecStrideScatterAll - Scatters all the single components from seperate vectors into 
756:      a multi-component vector.

758:    Collective on Vec

760:    Input Parameter:
761: +  s - the location where the subvectors are stored
762: -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES

764:    Output Parameter:
765: .  v - the multicomponent vector 

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

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

774:    Not optimized; could be easily

776:    Level: advanced

778:    Concepts:  scatter^into strided vector

780: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGather(),
781:           VecStrideScatterAll()
782: @*/
783: PetscErrorCode VecStrideScatterAll(Vec *s,Vec v,InsertMode addv)
784: {
786:   PetscInt        i,n,bs,j,jj,k,*bss,nv,nvc;
787:   PetscScalar     *x,**y;

793:   VecGetLocalSize(v,&n);
794:   VecGetArray(v,&x);
795:   bs   = v->bs;
796:   if (bs < 0) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set");

798:   PetscMalloc2(bs,PetscScalar**,&y,bs,PetscInt,&bss);
799:   nv  = 0;
800:   nvc = 0;
801:   for (i=0; i<bs; i++) {
802:     VecGetBlockSize(s[i],&bss[i]);
803:     if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1  Re: [PETSC #8241] VecStrideGatherAll */
804:     VecGetArray(s[i],&y[i]);
805:     nvc  += bss[i];
806:     nv++;
807:     if (nvc > bs)  SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of subvectors in subvectors > number of vectors in main vector");
808:     if (nvc == bs) break;
809:   }

811:   n =  n/bs;

813:   jj = 0;
814:   if (addv == INSERT_VALUES) {
815:     for (j=0; j<nv; j++) {
816:       for (k=0; k<bss[j]; k++) {
817:         for (i=0; i<n; i++) {
818:           x[bs*i+jj+k] = y[j][i*bss[j] + k];
819:         }
820:       }
821:       jj += bss[j];
822:     }
823:   } else if (addv == ADD_VALUES) {
824:     for (j=0; j<nv; j++) {
825:       for (k=0; k<bss[j]; k++) {
826:         for (i=0; i<n; i++) {
827:           x[bs*i+jj+k] += y[j][i*bss[j] + k];
828:         }
829:       }
830:       jj += bss[j];
831:     }
832: #if !defined(PETSC_USE_COMPLEX)
833:   } else if (addv == MAX_VALUES) {
834:     for (j=0; j<nv; j++) {
835:       for (k=0; k<bss[j]; k++) {
836:         for (i=0; i<n; i++) {
837:           x[bs*i+jj+k] = PetscMax(x[bs*i+jj+k],y[j][i*bss[j] + k]);
838:         }
839:       }
840:       jj += bss[j];
841:     }
842: #endif
843:   } else {
844:     SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
845:   }

847:   VecRestoreArray(v,&x);
848:   for (i=0; i<nv; i++) {
849:     VecRestoreArray(s[i],&y[i]);
850:   }
851:   PetscFree2(y,bss);
852:   return(0);
853: }

857: /*@
858:    VecStrideGather - Gathers a single component from a multi-component vector into
859:    another vector.

861:    Collective on Vec

863:    Input Parameter:
864: +  v - the vector 
865: .  start - starting point of the subvector (defined by a stride)
866: -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES

868:    Output Parameter:
869: .  s - the location where the subvector is stored

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

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

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

881:    Not optimized; could be easily

883:    Level: advanced

885:    Concepts: gather^into strided vector

887: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(),
888:           VecStrideScatterAll()
889: @*/
890: PetscErrorCode VecStrideGather(Vec v,PetscInt start,Vec s,InsertMode addv)
891: {
893:   PetscInt       i,n,bs,ns;
894:   PetscScalar    *x,*y;

899:   VecGetLocalSize(v,&n);
900:   VecGetLocalSize(s,&ns);
901:   VecGetArray(v,&x);
902:   VecGetArray(s,&y);

904:   bs   = v->bs;
905:   if (start >= bs) {
906:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
907:             Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
908:   }
909:   if (n != ns*bs) {
910:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Subvector length * blocksize %D not correct for gather from original vector %D",ns*bs,n);
911:   }
912:   x += start;
913:   n =  n/bs;

915:   if (addv == INSERT_VALUES) {
916:     for (i=0; i<n; i++) {
917:       y[i] = x[bs*i];
918:     }
919:   } else if (addv == ADD_VALUES) {
920:     for (i=0; i<n; i++) {
921:       y[i] += x[bs*i];
922:     }
923: #if !defined(PETSC_USE_COMPLEX)
924:   } else if (addv == MAX_VALUES) {
925:     for (i=0; i<n; i++) {
926:       y[i] = PetscMax(y[i],x[bs*i]);
927:     }
928: #endif
929:   } else {
930:     SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
931:   }

933:   VecRestoreArray(v,&x);
934:   VecRestoreArray(s,&y);
935:   return(0);
936: }

940: /*@
941:    VecStrideScatter - Scatters a single component from a vector into a multi-component vector.

943:    Collective on Vec

945:    Input Parameter:
946: +  s - the single-component vector 
947: .  start - starting point of the subvector (defined by a stride)
948: -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES

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

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

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

960:    Not optimized; could be easily

962:    Level: advanced

964:    Concepts: scatter^into strided vector

966: .seealso: VecStrideNorm(), VecStrideGather(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(),
967:           VecStrideScatterAll()
968: @*/
969: PetscErrorCode VecStrideScatter(Vec s,PetscInt start,Vec v,InsertMode addv)
970: {
972:   PetscInt       i,n,bs,ns;
973:   PetscScalar    *x,*y;

978:   VecGetLocalSize(v,&n);
979:   VecGetLocalSize(s,&ns);
980:   VecGetArray(v,&x);
981:   VecGetArray(s,&y);

983:   bs   = v->bs;
984:   if (start >= bs) {
985:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
986:             Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
987:   }
988:   if (n != ns*bs) {
989:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Subvector length * blocksize %D not correct for scatter to multicomponent vector %D",ns*bs,n);
990:   }
991:   x += start;
992:   n =  n/bs;


995:   if (addv == INSERT_VALUES) {
996:     for (i=0; i<n; i++) {
997:       x[bs*i] = y[i];
998:     }
999:   } else if (addv == ADD_VALUES) {
1000:     for (i=0; i<n; i++) {
1001:       x[bs*i] += y[i];
1002:     }
1003: #if !defined(PETSC_USE_COMPLEX)
1004:   } else if (addv == MAX_VALUES) {
1005:     for (i=0; i<n; i++) {
1006:       x[bs*i] = PetscMax(y[i],x[bs*i]);
1007:     }
1008: #endif
1009:   } else {
1010:     SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
1011:   }


1014:   VecRestoreArray(v,&x);
1015:   VecRestoreArray(s,&y);
1016:   return(0);
1017: }

1021: PetscErrorCode VecReciprocal_Default(Vec v)
1022: {
1024:   PetscInt         i,n;
1025:   PetscScalar *x;

1028:   VecGetLocalSize(v,&n);
1029:   VecGetArray(v,&x);
1030:   for (i=0; i<n; i++) {
1031:     if (x[i] != 0.0) x[i] = 1.0/x[i];
1032:   }
1033:   VecRestoreArray(v,&x);
1034:   return(0);
1035: }

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

1042:   Not collective

1044:   Input Parameter:
1045: . v - The vector

1047:   Output Parameter:
1048: . v - The vector square root

1050:   Level: beginner

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

1054: .keywords: vector, sqrt, square root
1055: @*/
1056: PetscErrorCode VecSqrt(Vec v)
1057: {
1058:   PetscScalar *x;
1059:   PetscInt         i, n;

1064:   VecGetLocalSize(v, &n);
1065:   VecGetArray(v, &x);
1066:   for(i = 0; i < n; i++) {
1067:     x[i] = sqrt(PetscAbsScalar(x[i]));
1068:   }
1069:   VecRestoreArray(v, &x);
1070:   return(0);
1071: }

1075: /*@
1076:    VecSum - Computes the sum of all the components of a vector.

1078:    Collective on Vec

1080:    Input Parameter:
1081: .  v - the vector 

1083:    Output Parameter:
1084: .  sum - the result

1086:    Level: beginner

1088:    Concepts: sum^of vector entries

1090: .seealso: VecNorm()
1091: @*/
1092: PetscErrorCode VecSum(Vec v,PetscScalar *sum)
1093: {
1095:   PetscInt         i,n;
1096:   PetscScalar *x,lsum = 0.0;

1101:   VecGetLocalSize(v,&n);
1102:   VecGetArray(v,&x);
1103:   for (i=0; i<n; i++) {
1104:     lsum += x[i];
1105:   }
1106:   MPI_Allreduce(&lsum,sum,1,MPIU_SCALAR,PetscSum_Op,v->comm);
1107:   VecRestoreArray(v,&x);
1108:   return(0);
1109: }

1113: /*@
1114:    VecShift - Shifts all of the components of a vector by computing
1115:    x[i] = x[i] + shift.

1117:    Collective on Vec

1119:    Input Parameters:
1120: +  v - the vector 
1121: -  shift - the shift

1123:    Output Parameter:
1124: .  v - the shifted vector 

1126:    Level: intermediate

1128:    Concepts: vector^adding constant

1130: @*/
1131: PetscErrorCode VecShift(const PetscScalar *shift,Vec v)
1132: {
1134:   PetscInt         i,n;
1135:   PetscScalar *x,lsum = *shift;

1140:   VecGetLocalSize(v,&n);
1141:   VecGetArray(v,&x);
1142:   for (i=0; i<n; i++) {
1143:     x[i] += lsum;
1144:   }
1145:   VecRestoreArray(v,&x);
1146:   return(0);
1147: }

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

1154:    Collective on Vec

1156:    Input Parameters:
1157: .  v - the vector 

1159:    Level: intermediate

1161:    Concepts: vector^absolute value

1163: @*/
1164: PetscErrorCode VecAbs(Vec v)
1165: {
1167:   PetscInt       i,n;
1168:   PetscScalar    *x;

1172:   VecGetLocalSize(v,&n);
1173:   VecGetArray(v,&x);
1174:   for (i=0; i<n; i++) {
1175:     x[i] = PetscAbsScalar(x[i]);
1176:   }
1177:   VecRestoreArray(v,&x);
1178:   return(0);
1179: }

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

1186:   Input Parameters:
1187: + vec   - The vector
1188: . order - The ordering
1189: - inv   - The flag for inverting the permutation

1191:   Level: beginner

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

1195: .seealso: MatPermute()
1196: .keywords: vec, permute
1197: @*/
1198: PetscErrorCode VecPermute(Vec x, IS row, PetscTruth inv)
1199: {
1200:   PetscScalar    *array, *newArray;
1201:   PetscInt       *idx;
1202:   PetscInt       i;

1206:   ISGetIndices(row, &idx);
1207:   VecGetArray(x, &array);
1208:   PetscMalloc(x->n*sizeof(PetscScalar), &newArray);
1209: #ifdef PETSC_USE_BOPT_g
1210:   for(i = 0; i < x->n; i++) {
1211:     if ((idx[i] < 0) || (idx[i] >= x->n)) {
1212:       SETERRQ2(PETSC_ERR_ARG_CORRUPT, "Permutation index %D is out of bounds: %D", i, idx[i]);
1213:     }
1214:   }
1215: #endif
1216:   if (inv == PETSC_FALSE) {
1217:     for(i = 0; i < x->n; i++) newArray[i]      = array[idx[i]];
1218:   } else {
1219:     for(i = 0; i < x->n; i++) newArray[idx[i]] = array[i];
1220:   }
1221:   VecRestoreArray(x, &array);
1222:   ISRestoreIndices(row, &idx);
1223:   VecReplaceArray(x, newArray);
1224:   return(0);
1225: }

1229: /*@
1230:    VecEqual - Compares two vectors.

1232:    Collective on Vec

1234:    Input Parameters:
1235: +  vec1 - the first matrix
1236: -  vec2 - the second matrix

1238:    Output Parameter:
1239: .  flg - PETSC_TRUE if the vectors are equal; PETSC_FALSE otherwise.

1241:    Level: intermediate

1243:    Concepts: equal^two vectors
1244:    Concepts: vector^equality

1246: @*/
1247: PetscErrorCode VecEqual(Vec vec1,Vec vec2,PetscTruth *flg)
1248: {
1249:   PetscScalar    *v1,*v2;
1251:   PetscInt       n1,n2;
1252:   PetscTruth     flg1;

1255:   VecGetSize(vec1,&n1);
1256:   VecGetSize(vec2,&n2);
1257:   if (vec1 == vec2) {
1258:     flg1 = PETSC_TRUE;
1259:   } else if (n1 != n2) {
1260:     flg1 = PETSC_FALSE;
1261:   } else {
1262:     VecGetArray(vec1,&v1);
1263:     VecGetArray(vec2,&v2);
1264:     PetscMemcmp(v1,v2,n1*sizeof(PetscScalar),&flg1);
1265:     VecRestoreArray(vec1,&v1);
1266:     VecRestoreArray(vec2,&v2);
1267:   }

1269:   /* combine results from all processors */
1270:   MPI_Allreduce(&flg1,flg,1,MPI_INT,MPI_MIN,vec1->comm);
1271:   return(0);
1272: }