Actual source code: vinv.c

  1: #define PETSCVEC_DLL

  3: /*
  4:      Some useful vector utility functions.
  5: */
 6:  #include 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->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: /*@C
 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->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->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: #if defined(PETSC_USE_COMPLEX)
215:     max = PetscRealPart(x[0]);
216: #else
217:     max = x[0];
218: #endif
219:     for (i=bs; i<n; i+=bs) {
220: #if defined(PETSC_USE_COMPLEX)
221:       if ((tmp = PetscRealPart(x[i])) > max) { max = tmp; id = i;}
222: #else
223:       if ((tmp = x[i]) > max) { max = tmp; id = i;}
224: #endif
225:     }
226:   }
227:   VecRestoreArray(v,&x);

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

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

243:   return(0);
244: }

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

252:    Collective on Vec

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

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

262:    Level: advanced

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

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

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

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

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


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

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

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

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

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

336:   return(0);
337: }

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

345:    Collective on Vec

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

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


356:    Level: advanced

358:    Concepts: scale^on stride of vector
359:    Concepts: stride^scale

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

372:   VecGetLocalSize(v,&n);
373:   VecGetArray(v,&x);

375:   bs   = v->bs;

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

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

393:    Collective on Vec

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

399:    Output Parameter:
400: .  nrm - the norms

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

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

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

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

414:    Level: advanced

416:    Concepts: norm^on stride of vector
417:    Concepts: stride^norm

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

432:   VecGetLocalSize(v,&n);
433:   VecGetArray(v,&x);
434:   PetscObjectGetComm((PetscObject)v,&comm);

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

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

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

482:   VecRestoreArray(v,&x);
483:   return(0);
484: }

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

492:    Collective on Vec

494:    Input Parameter:
495: .  v - the vector 

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

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

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

510:    Level: advanced

512:    Concepts: maximum^on stride of vector
513:    Concepts: stride^maximum

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

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

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

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

562:   VecRestoreArray(v,&x);
563:   return(0);
564: }

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

572:    Collective on Vec

574:    Input Parameter:
575: .  v - the vector 

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

582:    Level: advanced

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

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

592:    Concepts: minimum^on stride of vector
593:    Concepts: stride^minimum

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

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

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

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

642:   VecRestoreArray(v,&x);
643:   return(0);
644: }

646: /*----------------------------------------------------------------------------------------------*/
649: /*@
650:    VecStrideGatherAll - Gathers all the single components from a multi-component vector into
651:    seperate vectors.

653:    Collective on Vec

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

659:    Output Parameter:
660: .  s - the location where the subvectors are stored

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

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

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

673:    Not optimized; could be easily

675:    Level: advanced

677:    Concepts: gather^into strided vector

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

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

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

710:   n =  n/bs;

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

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

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

760:    Collective on Vec

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

766:    Output Parameter:
767: .  v - the multicomponent vector 

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

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

776:    Not optimized; could be easily

778:    Level: advanced

780:    Concepts:  scatter^into strided vector

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

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

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

813:   n =  n/bs;

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

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

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

863:    Collective on Vec

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

870:    Output Parameter:
871: .  s - the location where the subvector is stored

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

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

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

883:    Not optimized; could be easily

885:    Level: advanced

887:    Concepts: gather^into strided vector

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

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

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

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

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

942: /*@
943:    VecStrideScatter - Scatters a single component from a vector into a multi-component vector.

945:    Collective on Vec

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

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

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

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

962:    Not optimized; could be easily

964:    Level: advanced

966:    Concepts: scatter^into strided vector

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

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

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


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


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

1023: PetscErrorCode VecReciprocal_Default(Vec v)
1024: {
1026:   PetscInt         i,n;
1027:   PetscScalar *x;

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

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

1044:   Not collective

1046:   Input Parameter:
1047: . v - The vector

1049:   Output Parameter:
1050: . v - The vector square root

1052:   Level: beginner

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

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

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

1077: /*@
1078:    VecSum - Computes the sum of all the components of a vector.

1080:    Collective on Vec

1082:    Input Parameter:
1083: .  v - the vector 

1085:    Output Parameter:
1086: .  sum - the result

1088:    Level: beginner

1090:    Concepts: sum^of vector entries

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

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

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

1119:    Collective on Vec

1121:    Input Parameters:
1122: +  v - the vector 
1123: -  shift - the shift

1125:    Output Parameter:
1126: .  v - the shifted vector 

1128:    Level: intermediate

1130:    Concepts: vector^adding constant

1132: @*/
1133: PetscErrorCode PETSCVEC_DLLEXPORT VecShift(Vec v,PetscScalar shift)
1134: {
1136:   PetscInt i,n;
1137:   PetscScalar *x;

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

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

1155:    Collective on Vec

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

1160:    Level: intermediate

1162:    Concepts: vector^absolute value

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

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

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

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

1192:   Level: beginner

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

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

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

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

1233:    Collective on Vec

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

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

1242:    Level: intermediate

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

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

1256:   if (vec1 == vec2) {
1257:     *flg = PETSC_TRUE;
1258:   } else {
1259:     VecGetSize(vec1,&n1);
1260:     VecGetSize(vec2,&n2);
1261:     if (n1 != n2) {
1262:       flg1 = PETSC_FALSE;
1263:     } else {
1264:       VecGetArray(vec1,&v1);
1265:       VecGetArray(vec2,&v2);
1266:       PetscMemcmp(v1,v2,n1*sizeof(PetscScalar),&flg1);
1267:       VecRestoreArray(vec1,&v1);
1268:       VecRestoreArray(vec2,&v2);
1269:     }
1270:     /* combine results from all processors */
1271:     MPI_Allreduce(&flg1,flg,1,MPI_INT,MPI_MIN,vec1->comm);
1272:   }
1273:   return(0);
1274: }