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 PETSCVEC_DLLEXPORT VecStrideScale(Vec v,PetscInt start,PetscScalar *scale)
 38: {
 40:   PetscInt       i,n,bs;
 41:   PetscScalar    *x,xscale = *scale;

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

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

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

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

 70:    Collective on Vec

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

 77:    Output Parameter:
 78: .  norm - the norm

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

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

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

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

 92:    Level: advanced

 94:    Concepts: norm^on stride of vector
 95:    Concepts: stride^norm

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

110:   VecGetLocalSize(v,&n);
111:   VecGetArray(v,&x);
112:   PetscObjectGetComm((PetscObject)v,&comm);

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

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

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

149:   VecRestoreArray(v,&x);
150:   return(0);
151: }

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

159:    Collective on Vec

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

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

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

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

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

180:    Level: advanced

182:    Concepts: maximum^on stride of vector
183:    Concepts: stride^maximum

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


199:   VecGetLocalSize(v,&n);
200:   VecGetArray(v,&x);
201:   PetscObjectGetComm((PetscObject)v,&comm);

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

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

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

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

244:   return(0);
245: }

249: /*@
250:    VecStrideMin - Computes the minimum of subvector of a vector defined 
251:    by a starting point and a stride and optionally its location.

253:    Collective on Vec

255:    Input Parameter:
256: +  v - the vector 
257: -  start - starting point of the subvector (defined by a stride)

259:    Output Parameter:
260: +  idex - the location where the minimum occurred. (pass PETSC_NULL if not required)
261: -  nrm - the min

263:    Level: advanced

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

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

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

276:    Concepts: minimum^on stride of vector
277:    Concepts: stride^minimum

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


293:   VecGetLocalSize(v,&n);
294:   VecGetArray(v,&x);
295:   PetscObjectGetComm((PetscObject)v,&comm);

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

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

324:   if (!idex) {
325:     MPI_Allreduce(&min,nrm,1,MPIU_REAL,MPI_MIN,comm);
326:   } else {
327:     PetscReal in[2],out[2];
328:     PetscInt  rstart;

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

338:   return(0);
339: }

343: /*@
344:    VecStrideScaleAll - Scales the subvectors of a vector defined 
345:    by a starting point and a stride.

347:    Collective on Vec

349:    Input Parameter:
350: +  v - the vector 
351: -  scales - values to multiply each subvector entry by

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


358:    Level: advanced

360:    Concepts: scale^on stride of vector
361:    Concepts: stride^scale

363: .seealso: VecNorm(), VecStrideScale(), VecScale(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
364: @*/
365: PetscErrorCode PETSCVEC_DLLEXPORT VecStrideScaleAll(Vec v,PetscScalar *scales)
366: {
368:   PetscInt         i,j,n,bs;
369:   PetscScalar *x;

374:   VecGetLocalSize(v,&n);
375:   VecGetArray(v,&x);

377:   bs   = v->map.bs;

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

391: /*@
392:    VecStrideNormAll - Computes the norms  subvectors of a vector defined 
393:    by a starting point and a stride.

395:    Collective on Vec

397:    Input Parameter:
398: +  v - the vector 
399: -  ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY

401:    Output Parameter:
402: .  nrm - the norms

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

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

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

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

416:    Level: advanced

418:    Concepts: norm^on stride of vector
419:    Concepts: stride^norm

421: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
422: @*/
423: PetscErrorCode PETSCVEC_DLLEXPORT VecStrideNormAll(Vec v,NormType ntype,PetscReal *nrm)
424: {
426:   PetscInt         i,j,n,bs;
427:   PetscScalar *x;
428:   PetscReal   tnorm[128];
429:   MPI_Comm    comm;

434:   VecGetLocalSize(v,&n);
435:   VecGetArray(v,&x);
436:   PetscObjectGetComm((PetscObject)v,&comm);

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

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

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

484:   VecRestoreArray(v,&x);
485:   return(0);
486: }

490: /*@
491:    VecStrideMaxAll - Computes the maximums of subvectors of a vector defined 
492:    by a starting point and a stride and optionally its location.

494:    Collective on Vec

496:    Input Parameter:
497: .  v - the vector 

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

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

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

512:    Level: advanced

514:    Concepts: maximum^on stride of vector
515:    Concepts: stride^maximum

517: .seealso: VecMax(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin()
518: @*/
519: PetscErrorCode PETSCVEC_DLLEXPORT VecStrideMaxAll(Vec v,PetscInt *idex,PetscReal *nrm)
520: {
522:   PetscInt         i,j,n,bs;
523:   PetscScalar *x;
524:   PetscReal   max[128],tmp;
525:   MPI_Comm    comm;

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

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

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

564:   VecRestoreArray(v,&x);
565:   return(0);
566: }

570: /*@
571:    VecStrideMinAll - Computes the minimum of subvector of a vector defined 
572:    by a starting point and a stride and optionally its location.

574:    Collective on Vec

576:    Input Parameter:
577: .  v - the vector 

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

584:    Level: advanced

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

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

594:    Concepts: minimum^on stride of vector
595:    Concepts: stride^minimum

597: .seealso: VecMin(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMax()
598: @*/
599: PetscErrorCode PETSCVEC_DLLEXPORT VecStrideMinAll(Vec v,PetscInt *idex,PetscReal *nrm)
600: {
602:   PetscInt         i,n,bs,j;
603:   PetscScalar *x;
604:   PetscReal   min[128],tmp;
605:   MPI_Comm    comm;

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

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

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

644:   VecRestoreArray(v,&x);
645:   return(0);
646: }

648: /*----------------------------------------------------------------------------------------------*/
651: /*@
652:    VecStrideGatherAll - Gathers all the single components from a multi-component vector into
653:    separate vectors.

655:    Collective on Vec

657:    Input Parameter:
658: +  v - the vector 
659: -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES

661:    Output Parameter:
662: .  s - the location where the subvectors are stored

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

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

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

675:    Not optimized; could be easily

677:    Level: advanced

679:    Concepts: gather^into strided vector

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

694:   VecGetLocalSize(v,&n);
695:   VecGetArray(v,&x);
696:   bs   = v->map.bs;
697:   if (bs < 0) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set");

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

712:   n =  n/bs;

714:   jj = 0;
715:   if (addv == INSERT_VALUES) {
716:     for (j=0; j<nv; j++) {
717:       for (k=0; k<bss[j]; k++) {
718:         for (i=0; i<n; i++) {
719:           y[j][i*bss[j] + k] = x[bs*i+jj+k];
720:         }
721:       }
722:       jj += bss[j];
723:     }
724:   } else if (addv == ADD_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: #if !defined(PETSC_USE_COMPLEX)
734:   } else if (addv == MAX_VALUES) {
735:     for (j=0; j<nv; j++) {
736:       for (k=0; k<bss[j]; k++) {
737:         for (i=0; i<n; i++) {
738:           y[j][i*bss[j] + k] = PetscMax(y[j][i*bss[j] + k],x[bs*i+jj+k]);
739:         }
740:       }
741:       jj += bss[j];
742:     }
743: #endif
744:   } else {
745:     SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
746:   }

748:   VecRestoreArray(v,&x);
749:   for (i=0; i<nv; i++) {
750:     VecRestoreArray(s[i],&y[i]);
751:   }
752:   PetscFree2(y,bss);
753:   return(0);
754: }

758: /*@
759:    VecStrideScatterAll - Scatters all the single components from separate vectors into 
760:      a multi-component vector.

762:    Collective on Vec

764:    Input Parameter:
765: +  s - the location where the subvectors are stored
766: -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES

768:    Output Parameter:
769: .  v - the multicomponent vector 

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

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

778:    Not optimized; could be easily

780:    Level: advanced

782:    Concepts:  scatter^into strided vector

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

797:   VecGetLocalSize(v,&n);
798:   VecGetArray(v,&x);
799:   bs   = v->map.bs;
800:   if (bs < 0) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set");

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

815:   n =  n/bs;

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

851:   VecRestoreArray(v,&x);
852:   for (i=0; i<nv; i++) {
853:     VecRestoreArray(s[i],&y[i]);
854:   }
855:   PetscFree2(y,bss);
856:   return(0);
857: }

861: /*@
862:    VecStrideGather - Gathers a single component from a multi-component vector into
863:    another vector.

865:    Collective on Vec

867:    Input Parameter:
868: +  v - the vector 
869: .  start - starting point of the subvector (defined by a stride)
870: -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES

872:    Output Parameter:
873: .  s - the location where the subvector is stored

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

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

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

885:    Not optimized; could be easily

887:    Level: advanced

889:    Concepts: gather^into strided vector

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

903:   VecGetLocalSize(v,&n);
904:   VecGetLocalSize(s,&ns);
905:   VecGetArray(v,&x);
906:   VecGetArray(s,&y);

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

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

937:   VecRestoreArray(v,&x);
938:   VecRestoreArray(s,&y);
939:   return(0);
940: }

944: /*@
945:    VecStrideScatter - Scatters a single component from a vector into a multi-component vector.

947:    Collective on Vec

949:    Input Parameter:
950: +  s - the single-component vector 
951: .  start - starting point of the subvector (defined by a stride)
952: -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES

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

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

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

964:    Not optimized; could be easily

966:    Level: advanced

968:    Concepts: scatter^into strided vector

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

982:   VecGetLocalSize(v,&n);
983:   VecGetLocalSize(s,&ns);
984:   VecGetArray(v,&x);
985:   VecGetArray(s,&y);

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


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


1018:   VecRestoreArray(v,&x);
1019:   VecRestoreArray(s,&y);
1020:   return(0);
1021: }

1025: PetscErrorCode VecReciprocal_Default(Vec v)
1026: {
1028:   PetscInt         i,n;
1029:   PetscScalar *x;

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

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

1046:   Not collective

1048:   Input Parameter:
1049: . v - The vector

1051:   Output Parameter:
1052: . v - The vector square root

1054:   Level: beginner

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

1058: .keywords: vector, sqrt, square root
1059: @*/
1060: PetscErrorCode PETSCVEC_DLLEXPORT VecSqrt(Vec v)
1061: {
1062:   PetscScalar *x;
1063:   PetscInt         i, n;

1068:   VecGetLocalSize(v, &n);
1069:   VecGetArray(v, &x);
1070:   for(i = 0; i < n; i++) {
1071:     x[i] = sqrt(PetscAbsScalar(x[i]));
1072:   }
1073:   VecRestoreArray(v, &x);
1074:   return(0);
1075: }

1079: /*@
1080:    VecSum - Computes the sum of all the components of a vector.

1082:    Collective on Vec

1084:    Input Parameter:
1085: .  v - the vector 

1087:    Output Parameter:
1088: .  sum - the result

1090:    Level: beginner

1092:    Concepts: sum^of vector entries

1094: .seealso: VecNorm()
1095: @*/
1096: PetscErrorCode PETSCVEC_DLLEXPORT VecSum(Vec v,PetscScalar *sum)
1097: {
1099:   PetscInt         i,n;
1100:   PetscScalar *x,lsum = 0.0;

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

1117: /*@
1118:    VecShift - Shifts all of the components of a vector by computing
1119:    x[i] = x[i] + shift.

1121:    Collective on Vec

1123:    Input Parameters:
1124: +  v - the vector 
1125: -  shift - the shift

1127:    Output Parameter:
1128: .  v - the shifted vector 

1130:    Level: intermediate

1132:    Concepts: vector^adding constant

1134: @*/
1135: PetscErrorCode PETSCVEC_DLLEXPORT VecShift(Vec v,PetscScalar shift)
1136: {
1138:   PetscInt i,n;
1139:   PetscScalar *x;

1143:   VecGetLocalSize(v,&n);
1144:   VecGetArray(v,&x);
1145:   for (i=0; i<n; i++) {
1146:     x[i] += shift;
1147:   }
1148:   VecRestoreArray(v,&x);
1149:   return(0);
1150: }

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

1157:    Collective on Vec

1159:    Input Parameters:
1160: .  v - the vector 

1162:    Level: intermediate

1164:    Concepts: vector^absolute value

1166: @*/
1167: PetscErrorCode PETSCVEC_DLLEXPORT VecAbs(Vec v)
1168: {
1170:   PetscInt       i,n;
1171:   PetscScalar    *x;

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

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

1189:   Input Parameters:
1190: + vec   - The vector
1191: . order - The ordering
1192: - inv   - The flag for inverting the permutation

1194:   Level: beginner

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

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

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

1232: /*@
1233:    VecEqual - Compares two vectors.

1235:    Collective on Vec

1237:    Input Parameters:
1238: +  vec1 - the first matrix
1239: -  vec2 - the second matrix

1241:    Output Parameter:
1242: .  flg - PETSC_TRUE if the vectors are equal; PETSC_FALSE otherwise.

1244:    Level: intermediate

1246:    Concepts: equal^two vectors
1247:    Concepts: vector^equality

1249: @*/
1250: PetscErrorCode PETSCVEC_DLLEXPORT VecEqual(Vec vec1,Vec vec2,PetscTruth *flg)
1251: {
1252:   PetscScalar    *v1,*v2;
1254:   PetscInt       n1,n2,N1,N2;
1255:   PetscInt       state1,state2;
1256:   PetscTruth     flg1;
1257: 
1262:   if (vec1 == vec2) {
1263:     *flg = PETSC_TRUE;
1264:   } else {
1265:     VecGetSize(vec1,&N1);
1266:     VecGetSize(vec2,&N2);
1267:     if (N1 != N2) {
1268:       flg1 = PETSC_FALSE;
1269:     } else {
1270:       VecGetLocalSize(vec1,&n1);
1271:       VecGetLocalSize(vec2,&n2);
1272:       if (n1 != n2) {
1273:         flg1 = PETSC_FALSE;
1274:       } else {
1275:         PetscObjectStateQuery((PetscObject) vec1,&state1);
1276:         PetscObjectStateQuery((PetscObject) vec2,&state2);
1277:         VecGetArray(vec1,&v1);
1278:         VecGetArray(vec2,&v2);
1279:         PetscMemcmp(v1,v2,n1*sizeof(PetscScalar),&flg1);
1280:         VecRestoreArray(vec1,&v1);
1281:         VecRestoreArray(vec2,&v2);
1282:         PetscObjectSetState((PetscObject) vec1,state1);
1283:         PetscObjectSetState((PetscObject) vec2,state2);
1284:       }
1285:     }
1286:     /* combine results from all processors */
1287:     MPI_Allreduce(&flg1,flg,1,MPI_INT,MPI_MIN,vec1->comm);
1288:   }
1289:   return(0);
1290: }