Actual source code: vscat.c

petsc-3.4.5 2014-06-29
  2: /*
  3:      Code for creating scatters between vectors. This file
  4:   includes the code for scattering between sequential vectors and
  5:   some special cases for parallel scatters.
  6: */

  8: #include <petsc-private/vecimpl.h>    /*I   "petscvec.h"    I*/

 10: /* Logging support */
 11: PetscClassId VEC_SCATTER_CLASSID;

 13: #if defined(PETSC_USE_DEBUG)
 14: /*
 15:      Checks if any indices are less than zero and generates an error
 16: */
 19: static PetscErrorCode VecScatterCheckIndices_Private(PetscInt nmax,PetscInt n,const PetscInt *idx)
 20: {
 21:   PetscInt i;

 24:   for (i=0; i<n; i++) {
 25:     if (idx[i] < 0)     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative index %D at %D location",idx[i],i);
 26:     if (idx[i] >= nmax) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Index %D at %D location greater than max %D",idx[i],i,nmax);
 27:   }
 28:   return(0);
 29: }
 30: #endif

 32: /*
 33:       This is special scatter code for when the entire parallel vector is copied to each processor.

 35:    This code was written by Cameron Cooper, Occidental College, Fall 1995,
 36:    will working at ANL as a SERS student.
 37: */
 40: PetscErrorCode VecScatterBegin_MPI_ToAll(VecScatter ctx,Vec x,Vec y,InsertMode addv,ScatterMode mode)
 41: {
 43:   PetscInt       yy_n,xx_n;
 44:   PetscScalar    *xv,*yv;

 47:   VecGetLocalSize(y,&yy_n);
 48:   VecGetLocalSize(x,&xx_n);
 49:   VecGetArray(y,&yv);
 50:   if (x != y) {VecGetArray(x,&xv);}

 52:   if (mode & SCATTER_REVERSE) {
 53:     PetscScalar          *xvt,*xvt2;
 54:     VecScatter_MPI_ToAll *scat = (VecScatter_MPI_ToAll*)ctx->todata;
 55:     PetscInt             i;
 56:     PetscMPIInt          *disply = scat->displx;

 58:     if (addv == INSERT_VALUES) {
 59:       PetscInt rstart,rend;
 60:       /*
 61:          copy the correct part of the local vector into the local storage of
 62:          the MPI one.  Note: this operation only makes sense if all the local
 63:          vectors have the same values
 64:       */
 65:       VecGetOwnershipRange(y,&rstart,&rend);
 66:       PetscMemcpy(yv,xv+rstart,yy_n*sizeof(PetscScalar));
 67:     } else {
 68:       MPI_Comm    comm;
 69:       PetscMPIInt rank;
 70:       PetscObjectGetComm((PetscObject)y,&comm);
 71:       MPI_Comm_rank(comm,&rank);
 72:       if (scat->work1) xvt = scat->work1;
 73:       else {
 74:         PetscMalloc(xx_n*sizeof(PetscScalar),&xvt);
 75:         scat->work1 = xvt;
 76:       }
 77:       if (!rank) { /* I am the zeroth processor, values are accumulated here */
 78:         if   (scat->work2) xvt2 = scat->work2;
 79:         else {
 80:           PetscMalloc(xx_n*sizeof(PetscScalar),&xvt2);
 81:           scat->work2 = xvt2;
 82:         }
 83:         MPI_Gatherv(yv,yy_n,MPIU_SCALAR,xvt2,scat->count,disply,MPIU_SCALAR,0,PetscObjectComm((PetscObject)ctx));
 84:         MPI_Reduce(xv,xvt,xx_n,MPIU_SCALAR,MPIU_SUM,0,PetscObjectComm((PetscObject)ctx));
 85:         if (addv == ADD_VALUES) {
 86:           for (i=0; i<xx_n; i++) xvt[i] += xvt2[i];
 87: #if !defined(PETSC_USE_COMPLEX)
 88:         } else if (addv == MAX_VALUES) {
 89:           for (i=0; i<xx_n; i++) xvt[i] = PetscMax(xvt[i],xvt2[i]);
 90: #endif
 91:         } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Wrong insert option");
 92:         MPI_Scatterv(xvt,scat->count,disply,MPIU_SCALAR,yv,yy_n,MPIU_SCALAR,0,PetscObjectComm((PetscObject)ctx));
 93:       } else {
 94:         MPI_Gatherv(yv,yy_n,MPIU_SCALAR,0, 0,0,MPIU_SCALAR,0,PetscObjectComm((PetscObject)ctx));
 95:         MPI_Reduce(xv,xvt,xx_n,MPIU_SCALAR,MPIU_SUM,0,PetscObjectComm((PetscObject)ctx));
 96:         MPI_Scatterv(0,scat->count,disply,MPIU_SCALAR,yv,yy_n,MPIU_SCALAR,0,PetscObjectComm((PetscObject)ctx));
 97:       }
 98:     }
 99:   } else {
100:     PetscScalar          *yvt;
101:     VecScatter_MPI_ToAll *scat = (VecScatter_MPI_ToAll*)ctx->todata;
102:     PetscInt             i;
103:     PetscMPIInt          *displx = scat->displx;

105:     if (addv == INSERT_VALUES) {
106:       MPI_Allgatherv(xv,xx_n,MPIU_SCALAR,yv,scat->count,displx,MPIU_SCALAR,PetscObjectComm((PetscObject)ctx));
107:     } else {
108:       if (scat->work1) yvt = scat->work1;
109:       else {
110:         PetscMalloc(yy_n*sizeof(PetscScalar),&yvt);
111:         scat->work1 = yvt;
112:       }
113:       MPI_Allgatherv(xv,xx_n,MPIU_SCALAR,yvt,scat->count,displx,MPIU_SCALAR,PetscObjectComm((PetscObject)ctx));
114:       if (addv == ADD_VALUES) {
115:         for (i=0; i<yy_n; i++) yv[i] += yvt[i];
116: #if !defined(PETSC_USE_COMPLEX)
117:       } else if (addv == MAX_VALUES) {
118:         for (i=0; i<yy_n; i++) yv[i] = PetscMax(yv[i],yvt[i]);
119: #endif
120:       } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Wrong insert option");
121:     }
122:   }
123:   VecRestoreArray(y,&yv);
124:   if (x != y) {VecRestoreArray(x,&xv);}
125:   return(0);
126: }

130: PetscErrorCode VecScatterView_MPI_ToAll(VecScatter in,PetscViewer viewer)
131: {
133:   PetscBool      isascii;

136:   PetscObjectTypeCompare((PetscObject)in,PETSCVIEWERASCII,&isascii);
137:   if (isascii) {
138:     PetscViewerASCIIPrintf(viewer,"Entire parallel vector is copied to each process\n");
139:   }
140:   return(0);
141: }

143: /*
144:       This is special scatter code for when the entire parallel vector is  copied to processor 0.

146: */
149: PetscErrorCode VecScatterBegin_MPI_ToOne(VecScatter ctx,Vec x,Vec y,InsertMode addv,ScatterMode mode)
150: {
152:   PetscMPIInt    rank;
153:   PetscInt       yy_n,xx_n;
154:   PetscScalar    *xv,*yv;
155:   MPI_Comm       comm;

158:   VecGetLocalSize(y,&yy_n);
159:   VecGetLocalSize(x,&xx_n);
160:   VecGetArray(x,&xv);
161:   VecGetArray(y,&yv);

163:   PetscObjectGetComm((PetscObject)x,&comm);
164:   MPI_Comm_rank(comm,&rank);

166:   /* --------  Reverse scatter; spread from processor 0 to other processors */
167:   if (mode & SCATTER_REVERSE) {
168:     PetscScalar          *yvt;
169:     VecScatter_MPI_ToAll *scat = (VecScatter_MPI_ToAll*)ctx->todata;
170:     PetscInt             i;
171:     PetscMPIInt          *disply = scat->displx;

173:     if (addv == INSERT_VALUES) {
174:       MPI_Scatterv(xv,scat->count,disply,MPIU_SCALAR,yv,yy_n,MPIU_SCALAR,0,PetscObjectComm((PetscObject)ctx));
175:     } else {
176:       if (scat->work2) yvt = scat->work2;
177:       else {
178:         PetscMalloc(xx_n*sizeof(PetscScalar),&yvt);
179:         scat->work2 = yvt;
180:       }
181:       MPI_Scatterv(xv,scat->count,disply,MPIU_SCALAR,yvt,yy_n,MPIU_SCALAR,0,PetscObjectComm((PetscObject)ctx));
182:       if (addv == ADD_VALUES) {
183:         for (i=0; i<yy_n; i++) yv[i] += yvt[i];
184: #if !defined(PETSC_USE_COMPLEX)
185:       } else if (addv == MAX_VALUES) {
186:         for (i=0; i<yy_n; i++) yv[i] = PetscMax(yv[i],yvt[i]);
187: #endif
188:       } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Wrong insert option");
189:     }
190:   /* ---------  Forward scatter; gather all values onto processor 0 */
191:   } else {
192:     PetscScalar          *yvt  = 0;
193:     VecScatter_MPI_ToAll *scat = (VecScatter_MPI_ToAll*)ctx->todata;
194:     PetscInt             i;
195:     PetscMPIInt          *displx = scat->displx;

197:     if (addv == INSERT_VALUES) {
198:       MPI_Gatherv(xv,xx_n,MPIU_SCALAR,yv,scat->count,displx,MPIU_SCALAR,0,PetscObjectComm((PetscObject)ctx));
199:     } else {
200:       if (!rank) {
201:         if (scat->work1) yvt = scat->work1;
202:         else {
203:           PetscMalloc(yy_n*sizeof(PetscScalar),&yvt);
204:           scat->work1 = yvt;
205:         }
206:       }
207:       MPI_Gatherv(xv,xx_n,MPIU_SCALAR,yvt,scat->count,displx,MPIU_SCALAR,0,PetscObjectComm((PetscObject)ctx));
208:       if (!rank) {
209:         if (addv == ADD_VALUES) {
210:           for (i=0; i<yy_n; i++) yv[i] += yvt[i];
211: #if !defined(PETSC_USE_COMPLEX)
212:         } else if (addv == MAX_VALUES) {
213:           for (i=0; i<yy_n; i++) yv[i] = PetscMax(yv[i],yvt[i]);
214: #endif
215:         }  else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Wrong insert option");
216:       }
217:     }
218:   }
219:   VecRestoreArray(x,&xv);
220:   VecRestoreArray(y,&yv);
221:   return(0);
222: }

224: /*
225:        The follow to are used for both VecScatterBegin_MPI_ToAll() and VecScatterBegin_MPI_ToOne()
226: */
229: PetscErrorCode VecScatterDestroy_MPI_ToAll(VecScatter ctx)
230: {
231:   VecScatter_MPI_ToAll *scat = (VecScatter_MPI_ToAll*)ctx->todata;
232:   PetscErrorCode       ierr;

235:   PetscFree(scat->work1);
236:   PetscFree(scat->work2);
237:   PetscFree3(ctx->todata,scat->count,scat->displx);
238:   return(0);
239: }

243: PetscErrorCode VecScatterDestroy_SGToSG(VecScatter ctx)
244: {

248:   PetscFree2(((VecScatter_Seq_General*)ctx->todata)->vslots,((VecScatter_Seq_General*)ctx->fromdata)->vslots);
249:   PetscFree2(ctx->todata,ctx->fromdata);
250:   return(0);
251: }

255: PetscErrorCode VecScatterDestroy_SGToSS(VecScatter ctx)
256: {

260:   PetscFree(((VecScatter_Seq_General*)ctx->fromdata)->vslots);
261:   PetscFree2(ctx->todata,ctx->fromdata);
262:   return(0);
263: }

267: PetscErrorCode VecScatterDestroy_SSToSG(VecScatter ctx)
268: {

272:   PetscFree(((VecScatter_Seq_General*)ctx->todata)->vslots);
273:   PetscFree2(ctx->todata,ctx->fromdata);
274:   return(0);
275: }

279: PetscErrorCode VecScatterDestroy_SSToSS(VecScatter ctx)
280: {

284:   PetscFree2(ctx->todata,ctx->fromdata);
285:   return(0);
286: }

288: /* -------------------------------------------------------------------------*/
291: PetscErrorCode VecScatterCopy_MPI_ToAll(VecScatter in,VecScatter out)
292: {
293:   VecScatter_MPI_ToAll *in_to = (VecScatter_MPI_ToAll*)in->todata,*sto;
294:   PetscErrorCode       ierr;
295:   PetscMPIInt          size,*count,*displx;
296:   PetscInt             i;

299:   out->begin   = in->begin;
300:   out->end     = in->end;
301:   out->copy    = in->copy;
302:   out->destroy = in->destroy;
303:   out->view    = in->view;

305:   MPI_Comm_size(PetscObjectComm((PetscObject)out),&size);
306:   PetscMalloc3(1,VecScatter_MPI_ToAll,&sto,size,PetscMPIInt,&count,size,PetscMPIInt,&displx);
307:   sto->type   = in_to->type;
308:   sto->count  = count;
309:   sto->displx = displx;
310:   for (i=0; i<size; i++) {
311:     sto->count[i]  = in_to->count[i];
312:     sto->displx[i] = in_to->displx[i];
313:   }
314:   sto->work1    = 0;
315:   sto->work2    = 0;
316:   out->todata   = (void*)sto;
317:   out->fromdata = (void*)0;
318:   return(0);
319: }

321: /* --------------------------------------------------------------------------------------*/
322: /*
323:         Scatter: sequential general to sequential general
324: */
327: PetscErrorCode VecScatterBegin_SGToSG(VecScatter ctx,Vec x,Vec y,InsertMode addv,ScatterMode mode)
328: {
329:   VecScatter_Seq_General *gen_to   = (VecScatter_Seq_General*)ctx->todata;
330:   VecScatter_Seq_General *gen_from = (VecScatter_Seq_General*)ctx->fromdata;
331:   PetscErrorCode         ierr;
332:   PetscInt               i,n = gen_from->n,*fslots,*tslots;
333:   PetscScalar            *xv,*yv;

336:   VecGetArray(x,&xv);
337:   if (x != y) {
338:     VecGetArray(y,&yv);
339:   } else yv = xv;

341:   if (mode & SCATTER_REVERSE) {
342:     gen_to   = (VecScatter_Seq_General*)ctx->fromdata;
343:     gen_from = (VecScatter_Seq_General*)ctx->todata;
344:   }
345:   fslots = gen_from->vslots;
346:   tslots = gen_to->vslots;

348:   if (addv == INSERT_VALUES) {
349:     for (i=0; i<n; i++) yv[tslots[i]]  = xv[fslots[i]];
350:   } else if (addv == ADD_VALUES) {
351:     for (i=0; i<n; i++) yv[tslots[i]] += xv[fslots[i]];
352: #if !defined(PETSC_USE_COMPLEX)
353:   } else if (addv == MAX_VALUES) {
354:     for (i=0; i<n; i++) yv[tslots[i]] = PetscMax(yv[tslots[i]],xv[fslots[i]]);
355: #endif
356:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Wrong insert option");
357:   VecRestoreArray(x,&xv);
358:   if (x != y) {VecRestoreArray(y,&yv);}
359:   return(0);
360: }

362: /*
363:     Scatter: sequential general to sequential stride 1
364: */
367: PetscErrorCode VecScatterBegin_SGToSS_Stride1(VecScatter ctx,Vec x,Vec y,InsertMode addv,ScatterMode mode)
368: {
369:   VecScatter_Seq_Stride  *gen_to   = (VecScatter_Seq_Stride*)ctx->todata;
370:   VecScatter_Seq_General *gen_from = (VecScatter_Seq_General*)ctx->fromdata;
371:   PetscInt               i,n = gen_from->n,*fslots = gen_from->vslots;
372:   PetscErrorCode         ierr;
373:   PetscInt               first = gen_to->first;
374:   PetscScalar            *xv,*yv;

377:   VecGetArray(x,&xv);
378:   if (x != y) {
379:     VecGetArray(y,&yv);
380:   } else yv = xv;
381:   if (mode & SCATTER_REVERSE) {
382:     xv += first;
383:     if (addv == INSERT_VALUES) {
384:       for (i=0; i<n; i++) yv[fslots[i]] = xv[i];
385:     } else if (addv == ADD_VALUES) {
386:       for (i=0; i<n; i++) yv[fslots[i]] += xv[i];
387: #if !defined(PETSC_USE_COMPLEX)
388:     } else if (addv == MAX_VALUES) {
389:       for (i=0; i<n; i++) yv[fslots[i]] = PetscMax(yv[fslots[i]],xv[i]);
390: #endif
391:     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Wrong insert option");
392:   } else {
393:     yv += first;
394:     if (addv == INSERT_VALUES) {
395:       for (i=0; i<n; i++) yv[i] = xv[fslots[i]];
396:     } else if (addv == ADD_VALUES) {
397:       for (i=0; i<n; i++) yv[i] += xv[fslots[i]];
398: #if !defined(PETSC_USE_COMPLEX)
399:     } else if (addv == MAX_VALUES) {
400:       for (i=0; i<n; i++) yv[i] = PetscMax(yv[i],xv[fslots[i]]);
401: #endif
402:     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Wrong insert option");
403:   }
404:   VecRestoreArray(x,&xv);
405:   if (x != y) {VecRestoreArray(y,&yv);}
406:   return(0);
407: }

409: /*
410:    Scatter: sequential general to sequential stride
411: */
414: PetscErrorCode VecScatterBegin_SGToSS(VecScatter ctx,Vec x,Vec y,InsertMode addv,ScatterMode mode)
415: {
416:   VecScatter_Seq_Stride  *gen_to   = (VecScatter_Seq_Stride*)ctx->todata;
417:   VecScatter_Seq_General *gen_from = (VecScatter_Seq_General*)ctx->fromdata;
418:   PetscInt               i,n = gen_from->n,*fslots = gen_from->vslots;
419:   PetscErrorCode         ierr;
420:   PetscInt               first = gen_to->first,step = gen_to->step;
421:   PetscScalar            *xv,*yv;

424:   VecGetArray(x,&xv);
425:   if (x != y) {
426:     VecGetArray(y,&yv);
427:   } else yv = xv;

429:   if (mode & SCATTER_REVERSE) {
430:     if (addv == INSERT_VALUES) {
431:       for (i=0; i<n; i++) yv[fslots[i]] = xv[first + i*step];
432:     } else if (addv == ADD_VALUES) {
433:       for (i=0; i<n; i++) yv[fslots[i]] += xv[first + i*step];
434: #if !defined(PETSC_USE_COMPLEX)
435:     } else if (addv == MAX_VALUES) {
436:       for (i=0; i<n; i++) yv[fslots[i]] = PetscMax(yv[fslots[i]],xv[first + i*step]);
437: #endif
438:     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Wrong insert option");
439:   } else {
440:     if (addv == INSERT_VALUES) {
441:       for (i=0; i<n; i++) yv[first + i*step] = xv[fslots[i]];
442:     } else if (addv == ADD_VALUES) {
443:       for (i=0; i<n; i++) yv[first + i*step] += xv[fslots[i]];
444: #if !defined(PETSC_USE_COMPLEX)
445:     } else if (addv == MAX_VALUES) {
446:       for (i=0; i<n; i++) yv[first + i*step] = PetscMax(yv[first + i*step],xv[fslots[i]]);
447: #endif
448:     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Wrong insert option");
449:   }
450:   VecRestoreArray(x,&xv);
451:   if (x != y) {VecRestoreArray(y,&yv);}
452:   return(0);
453: }

455: /*
456:     Scatter: sequential stride 1 to sequential general
457: */
460: PetscErrorCode VecScatterBegin_SSToSG_Stride1(VecScatter ctx,Vec x,Vec y,InsertMode addv,ScatterMode mode)
461: {
462:   VecScatter_Seq_Stride  *gen_from = (VecScatter_Seq_Stride*)ctx->fromdata;
463:   VecScatter_Seq_General *gen_to   = (VecScatter_Seq_General*)ctx->todata;
464:   PetscInt               i,n = gen_from->n,*fslots = gen_to->vslots;
465:   PetscErrorCode         ierr;
466:   PetscInt               first = gen_from->first;
467:   PetscScalar            *xv,*yv;

470:   VecGetArray(x,&xv);
471:   if (x != y) {
472:     VecGetArray(y,&yv);
473:   } else yv = xv;

475:   if (mode & SCATTER_REVERSE) {
476:     yv += first;
477:     if (addv == INSERT_VALUES) {
478:       for (i=0; i<n; i++) yv[i] = xv[fslots[i]];
479:     } else  if (addv == ADD_VALUES) {
480:       for (i=0; i<n; i++) yv[i] += xv[fslots[i]];
481: #if !defined(PETSC_USE_COMPLEX)
482:     } else  if (addv == MAX_VALUES) {
483:       for (i=0; i<n; i++) yv[i] = PetscMax(yv[i],xv[fslots[i]]);
484: #endif
485:     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Wrong insert option");
486:   } else {
487:     xv += first;
488:     if (addv == INSERT_VALUES) {
489:       for (i=0; i<n; i++) yv[fslots[i]] = xv[i];
490:     } else  if (addv == ADD_VALUES) {
491:       for (i=0; i<n; i++) yv[fslots[i]] += xv[i];
492: #if !defined(PETSC_USE_COMPLEX)
493:     } else  if (addv == MAX_VALUES) {
494:       for (i=0; i<n; i++) yv[fslots[i]] = PetscMax(yv[fslots[i]],xv[i]);
495: #endif
496:     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Wrong insert option");
497:   }
498:   VecRestoreArray(x,&xv);
499:   if (x != y) {VecRestoreArray(y,&yv);}
500:   return(0);
501: }

505: /*
506:    Scatter: sequential stride to sequential general
507: */
508: PetscErrorCode VecScatterBegin_SSToSG(VecScatter ctx,Vec x,Vec y,InsertMode addv,ScatterMode mode)
509: {
510:   VecScatter_Seq_Stride  *gen_from = (VecScatter_Seq_Stride*)ctx->fromdata;
511:   VecScatter_Seq_General *gen_to   = (VecScatter_Seq_General*)ctx->todata;
512:   PetscInt               i,n = gen_from->n,*fslots = gen_to->vslots;
513:   PetscErrorCode         ierr;
514:   PetscInt               first = gen_from->first,step = gen_from->step;
515:   PetscScalar            *xv,*yv;

518:   VecGetArray(x,&xv);
519:   if (x != y) {
520:     VecGetArray(y,&yv);
521:   } else yv = xv;

523:   if (mode & SCATTER_REVERSE) {
524:     if (addv == INSERT_VALUES) {
525:       for (i=0; i<n; i++) yv[first + i*step] = xv[fslots[i]];
526:     } else if (addv == ADD_VALUES) {
527:       for (i=0; i<n; i++) yv[first + i*step] += xv[fslots[i]];
528: #if !defined(PETSC_USE_COMPLEX)
529:     } else if (addv == MAX_VALUES) {
530:       for (i=0; i<n; i++) yv[first + i*step] = PetscMax(yv[first + i*step],xv[fslots[i]]);
531: #endif
532:     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Wrong insert option");
533:   } else {
534:     if (addv == INSERT_VALUES) {
535:       for (i=0; i<n; i++) yv[fslots[i]] = xv[first + i*step];
536:     } else if (addv == ADD_VALUES) {
537:       for (i=0; i<n; i++) yv[fslots[i]] += xv[first + i*step];
538: #if !defined(PETSC_USE_COMPLEX)
539:     } else if (addv == MAX_VALUES) {
540:       for (i=0; i<n; i++) yv[fslots[i]] = PetscMax(yv[fslots[i]],xv[first + i*step]);
541: #endif
542:     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Wrong insert option");
543:   }
544:   VecRestoreArray(x,&xv);
545:   if (x != y) {VecRestoreArray(y,&yv);}
546:   return(0);
547: }

551: PetscErrorCode VecScatterView_SSToSG(VecScatter in,PetscViewer viewer)
552: {
553:   PetscErrorCode         ierr;
554:   VecScatter_Seq_Stride  *in_from = (VecScatter_Seq_Stride*)in->todata;
555:   VecScatter_Seq_General *in_to   = (VecScatter_Seq_General*)in->fromdata;
556:   PetscInt               i;
557:   PetscBool              isascii;

560:   PetscObjectTypeCompare((PetscObject)in,PETSCVIEWERASCII,&isascii);
561:   if (isascii) {
562:     PetscViewerASCIIPrintf(viewer,"Sequential stride to general scatter\n");
563:     for (i=0; i<in_to->n; i++) {
564:       PetscViewerASCIIPrintf(viewer,"%D to %D\n",in_from->first + in_from->step*i,in_to->vslots[i]);
565:     }
566:   }
567:   return(0);
568: }
569: /*
570:      Scatter: sequential stride to sequential stride
571: */
574: PetscErrorCode VecScatterBegin_SSToSS(VecScatter ctx,Vec x,Vec y,InsertMode addv,ScatterMode mode)
575: {
576:   VecScatter_Seq_Stride *gen_to   = (VecScatter_Seq_Stride*)ctx->todata;
577:   VecScatter_Seq_Stride *gen_from = (VecScatter_Seq_Stride*)ctx->fromdata;
578:   PetscInt              i,n = gen_from->n,to_first = gen_to->first,to_step = gen_to->step;
579:   PetscErrorCode        ierr;
580:   PetscInt              from_first = gen_from->first,from_step = gen_from->step;
581:   PetscScalar           *xv,*yv;

584:   VecGetArrayRead(x,(const PetscScalar **)&xv);
585:   if (x != y) {
586:     VecGetArray(y,&yv);
587:   } else yv = xv;

589:   if (mode & SCATTER_REVERSE) {
590:     from_first = gen_to->first;
591:     to_first   = gen_from->first;
592:     from_step  = gen_to->step;
593:     to_step    = gen_from->step;
594:   }

596:   if (addv == INSERT_VALUES) {
597:     if (to_step == 1 && from_step == 1) {
598:       PetscMemcpy(yv+to_first,xv+from_first,n*sizeof(PetscScalar));
599:     } else  {
600:       for (i=0; i<n; i++) yv[to_first + i*to_step] = xv[from_first+i*from_step];
601:     }
602:   } else if (addv == ADD_VALUES) {
603:     if (to_step == 1 && from_step == 1) {
604:       yv += to_first; xv += from_first;
605:       for (i=0; i<n; i++) yv[i] += xv[i];
606:     } else {
607:       for (i=0; i<n; i++) yv[to_first + i*to_step] += xv[from_first+i*from_step];
608:     }
609: #if !defined(PETSC_USE_COMPLEX)
610:   } else if (addv == MAX_VALUES) {
611:     if (to_step == 1 && from_step == 1) {
612:       yv += to_first; xv += from_first;
613:       for (i=0; i<n; i++) yv[i] = PetscMax(yv[i],xv[i]);
614:     } else {
615:       for (i=0; i<n; i++) yv[to_first + i*to_step] = PetscMax(yv[to_first + i*to_step],xv[from_first+i*from_step]);
616:     }
617: #endif
618:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Wrong insert option");
619:   VecRestoreArrayRead(x,(const PetscScalar**)&xv);
620:   if (x != y) {VecRestoreArray(y,&yv);}
621:   return(0);
622: }

624: /* --------------------------------------------------------------------------*/


629: PetscErrorCode VecScatterCopy_SGToSG(VecScatter in,VecScatter out)
630: {
631:   PetscErrorCode         ierr;
632:   VecScatter_Seq_General *in_to   = (VecScatter_Seq_General*)in->todata,*out_to = NULL;
633:   VecScatter_Seq_General *in_from = (VecScatter_Seq_General*)in->fromdata,*out_from = NULL;

636:   out->begin   = in->begin;
637:   out->end     = in->end;
638:   out->copy    = in->copy;
639:   out->destroy = in->destroy;
640:   out->view    = in->view;

642:   PetscMalloc2(1,VecScatter_Seq_General,&out_to,1,VecScatter_Seq_General,&out_from);
643:   PetscMalloc2(in_to->n,PetscInt,&out_to->vslots,in_from->n,PetscInt,&out_from->vslots);
644:   out_to->n                    = in_to->n;
645:   out_to->type                 = in_to->type;
646:   out_to->nonmatching_computed = PETSC_FALSE;
647:   out_to->slots_nonmatching    = 0;
648:   out_to->is_copy              = PETSC_FALSE;
649:   PetscMemcpy(out_to->vslots,in_to->vslots,(out_to->n)*sizeof(PetscInt));

651:   out_from->n                    = in_from->n;
652:   out_from->type                 = in_from->type;
653:   out_from->nonmatching_computed = PETSC_FALSE;
654:   out_from->slots_nonmatching    = 0;
655:   out_from->is_copy              = PETSC_FALSE;
656:   PetscMemcpy(out_from->vslots,in_from->vslots,(out_from->n)*sizeof(PetscInt));

658:   out->todata   = (void*)out_to;
659:   out->fromdata = (void*)out_from;
660:   return(0);
661: }

665: PetscErrorCode VecScatterView_SGToSG(VecScatter in,PetscViewer viewer)
666: {
667:   PetscErrorCode         ierr;
668:   VecScatter_Seq_General *in_to   = (VecScatter_Seq_General*)in->todata;
669:   VecScatter_Seq_General *in_from = (VecScatter_Seq_General*)in->fromdata;
670:   PetscInt               i;
671:   PetscBool              isascii;

674:   PetscObjectTypeCompare((PetscObject)in,PETSCVIEWERASCII,&isascii);
675:   if (isascii) {
676:     PetscViewerASCIIPrintf(viewer,"Sequential general scatter\n");
677:     for (i=0; i<in_to->n; i++) {
678:       PetscViewerASCIIPrintf(viewer,"%D to %D\n",in_from->vslots[i],in_to->vslots[i]);
679:     }
680:   }
681:   return(0);
682: }


687: PetscErrorCode VecScatterCopy_SGToSS(VecScatter in,VecScatter out)
688: {
689:   PetscErrorCode         ierr;
690:   VecScatter_Seq_Stride  *in_to   = (VecScatter_Seq_Stride*)in->todata,*out_to = NULL;
691:   VecScatter_Seq_General *in_from = (VecScatter_Seq_General*)in->fromdata,*out_from = NULL;

694:   out->begin   = in->begin;
695:   out->end     = in->end;
696:   out->copy    = in->copy;
697:   out->destroy = in->destroy;
698:   out->view    = in->view;

700:   PetscMalloc2(1,VecScatter_Seq_Stride,&out_to,1,VecScatter_Seq_General,&out_from);
701:   PetscMalloc(in_from->n*sizeof(PetscInt),&out_from->vslots);
702:   out_to->n     = in_to->n;
703:   out_to->type  = in_to->type;
704:   out_to->first = in_to->first;
705:   out_to->step  = in_to->step;
706:   out_to->type  = in_to->type;

708:   out_from->n                    = in_from->n;
709:   out_from->type                 = in_from->type;
710:   out_from->nonmatching_computed = PETSC_FALSE;
711:   out_from->slots_nonmatching    = 0;
712:   out_from->is_copy              = PETSC_FALSE;
713:   PetscMemcpy(out_from->vslots,in_from->vslots,(out_from->n)*sizeof(PetscInt));

715:   out->todata   = (void*)out_to;
716:   out->fromdata = (void*)out_from;
717:   return(0);
718: }

722: PetscErrorCode VecScatterView_SGToSS(VecScatter in,PetscViewer viewer)
723: {
724:   PetscErrorCode         ierr;
725:   VecScatter_Seq_Stride  *in_to   = (VecScatter_Seq_Stride*)in->todata;
726:   VecScatter_Seq_General *in_from = (VecScatter_Seq_General*)in->fromdata;
727:   PetscInt               i;
728:   PetscBool              isascii;

731:   PetscObjectTypeCompare((PetscObject)in,PETSCVIEWERASCII,&isascii);
732:   if (isascii) {
733:     PetscViewerASCIIPrintf(viewer,"Sequential general scatter to stride\n");
734:     for (i=0; i<in_to->n; i++) {
735:       PetscViewerASCIIPrintf(viewer,"%D to %D\n",in_from->vslots[i],in_to->first + in_to->step*i);
736:     }
737:   }
738:   return(0);
739: }

741: /* --------------------------------------------------------------------------*/
742: /*
743:     Scatter: parallel to sequential vector, sequential strides for both.
744: */
747: PetscErrorCode VecScatterCopy_SSToSS(VecScatter in,VecScatter out)
748: {
749:   VecScatter_Seq_Stride *in_to   = (VecScatter_Seq_Stride*)in->todata,*out_to = NULL;
750:   VecScatter_Seq_Stride *in_from = (VecScatter_Seq_Stride*)in->fromdata,*out_from = NULL;
751:   PetscErrorCode        ierr;

754:   out->begin   = in->begin;
755:   out->end     = in->end;
756:   out->copy    = in->copy;
757:   out->destroy = in->destroy;
758:   out->view    = in->view;

760:   PetscMalloc2(1,VecScatter_Seq_Stride,&out_to,1,VecScatter_Seq_Stride,&out_from);
761:   out_to->n       = in_to->n;
762:   out_to->type    = in_to->type;
763:   out_to->first   = in_to->first;
764:   out_to->step    = in_to->step;
765:   out_to->type    = in_to->type;
766:   out_from->n     = in_from->n;
767:   out_from->type  = in_from->type;
768:   out_from->first = in_from->first;
769:   out_from->step  = in_from->step;
770:   out_from->type  = in_from->type;
771:   out->todata     = (void*)out_to;
772:   out->fromdata   = (void*)out_from;
773:   return(0);
774: }

778: PetscErrorCode VecScatterView_SSToSS(VecScatter in,PetscViewer viewer)
779: {
780:   VecScatter_Seq_Stride *in_to   = (VecScatter_Seq_Stride*)in->todata;
781:   VecScatter_Seq_Stride *in_from = (VecScatter_Seq_Stride*)in->fromdata;
782:   PetscErrorCode        ierr;
783:   PetscBool             isascii;

786:   PetscObjectTypeCompare((PetscObject)in,PETSCVIEWERASCII,&isascii);
787:   if (isascii) {
788:     PetscViewerASCIIPrintf(viewer,"Sequential stride count %D start %D step to start %D stride %D\n",in_to->n,in_to->first,in_to->step,in_from->first,in_from->step);
789:   }
790:   return(0);
791: }


794: extern PetscErrorCode VecScatterCreate_PtoS(PetscInt,const PetscInt*,PetscInt,const PetscInt*,Vec,Vec,PetscInt,VecScatter);
795: extern PetscErrorCode VecScatterCreate_PtoP(PetscInt,const PetscInt*,PetscInt,const PetscInt*,Vec,Vec,PetscInt,VecScatter);
796: extern PetscErrorCode VecScatterCreate_StoP(PetscInt,const PetscInt*,PetscInt,const PetscInt*,Vec,Vec,PetscInt,VecScatter);

798: /* =======================================================================*/
799: #define VEC_SEQ_ID 0
800: #define VEC_MPI_ID 1
801: #define IS_GENERAL_ID 0
802: #define IS_STRIDE_ID  1
803: #define IS_BLOCK_ID   2

805: /*
806:    Blocksizes we have optimized scatters for
807: */

809: #define VecScatterOptimizedBS(mbs) ((2 <= mbs && mbs <= 8) || mbs == 12)

811: PetscErrorCode  VecScatterCreateEmpty(MPI_Comm comm,VecScatter *newctx)
812: {
813:   VecScatter     ctx;

817:   PetscHeaderCreate(ctx,_p_VecScatter,int,VEC_SCATTER_CLASSID,"VecScatter","VecScatter","Vec",comm,VecScatterDestroy,VecScatterView);
818:   ctx->inuse               = PETSC_FALSE;
819:   ctx->beginandendtogether = PETSC_FALSE;
820:   PetscOptionsGetBool(NULL,"-vecscatter_merge",&ctx->beginandendtogether,NULL);
821:   if (ctx->beginandendtogether) {
822:     PetscInfo(ctx,"Using combined (merged) vector scatter begin and end\n");
823:   }
824:   ctx->packtogether = PETSC_FALSE;
825:   PetscOptionsGetBool(NULL,"-vecscatter_packtogether",&ctx->packtogether,NULL);
826:   if (ctx->packtogether) {
827:     PetscInfo(ctx,"Pack all messages before sending\n");
828:   }
829:   *newctx = ctx;
830:   return(0);
831: }

835: /*@C
836:    VecScatterCreate - Creates a vector scatter context.

838:    Collective on Vec

840:    Input Parameters:
841: +  xin - a vector that defines the shape (parallel data layout of the vector)
842:          of vectors from which we scatter
843: .  yin - a vector that defines the shape (parallel data layout of the vector)
844:          of vectors to which we scatter
845: .  ix - the indices of xin to scatter (if NULL scatters all values)
846: -  iy - the indices of yin to hold results (if NULL fills entire vector yin)

848:    Output Parameter:
849: .  newctx - location to store the new scatter context

851:    Options Database Keys: (uses regular MPI_Sends by default)
852: +  -vecscatter_view         - Prints detail of communications
853: .  -vecscatter_view ::ascii_info    - Print less details about communication
854: .  -vecscatter_ssend        - Uses MPI_Ssend_init() instead of MPI_Send_init()
855: .  -vecscatter_rsend           - use ready receiver mode for MPI sends
856: .  -vecscatter_merge        - VecScatterBegin() handles all of the communication, VecScatterEnd() is a nop
857:                               eliminates the chance for overlap of computation and communication
858: .  -vecscatter_sendfirst    - Posts sends before receives
859: .  -vecscatter_packtogether - Pack all messages before sending, receive all messages before unpacking
860: .  -vecscatter_alltoall     - Uses MPI all to all communication for scatter
861: .  -vecscatter_window       - Use MPI 2 window operations to move data
862: .  -vecscatter_nopack       - Avoid packing to work vector when possible (if used with -vecscatter_alltoall then will use MPI_Alltoallw()
863: -  -vecscatter_reproduce    - insure that the order of the communications are done the same for each scatter, this under certain circumstances
864:                               will make the results of scatters deterministic when otherwise they are not (it may be slower also).

866: $
867: $                                                                                    --When packing is used--
868: $                               MPI Datatypes (no packing)  sendfirst   merge        packtogether  persistent*
869: $                                _nopack                   _sendfirst    _merge      _packtogether                -vecscatter_
870: $ ----------------------------------------------------------------------------------------------------------------------------
871: $    Message passing    Send       p                           X            X           X         always
872: $                      Ssend       p                           X            X           X         always          _ssend
873: $                      Rsend       p                        nonsense        X           X         always          _rsend
874: $    AlltoAll  v or w              X                        nonsense     always         X         nonsense        _alltoall
875: $    MPI_Win                       p                        nonsense        p           p         nonsense        _window
876: $
877: $   Since persistent sends and receives require a constant memory address they can only be used when data is packed into the work vector
878: $   because the in and out array may be different for each call to VecScatterBegin/End().
879: $
880: $    p indicates possible, but not implemented. X indicates implemented
881: $

883:     Level: intermediate

885:   Notes:
886:    In calls to VecScatter() you can use different vectors than the xin and
887:    yin you used above; BUT they must have the same parallel data layout, for example,
888:    they could be obtained from VecDuplicate().
889:    A VecScatter context CANNOT be used in two or more simultaneous scatters;
890:    that is you cannot call a second VecScatterBegin() with the same scatter
891:    context until the VecScatterEnd() has been called on the first VecScatterBegin().
892:    In this case a separate VecScatter is needed for each concurrent scatter.

894:    Currently the MPI_Send(), MPI_Ssend() and MPI_Rsend() all use PERSISTENT versions.
895:    (this unfortunately requires that the same in and out arrays be used for each use, this
896:     is why when not using MPI_alltoallw() we always need to pack the input into the work array before sending
897:     and unpack upon receeving instead of using MPI datatypes to avoid the packing/unpacking).

899:    Both ix and iy cannot be NULL at the same time.

901:    Concepts: scatter^between vectors
902:    Concepts: gather^between vectors

904: .seealso: VecScatterDestroy(), VecScatterCreateToAll(), VecScatterCreateToZero()
905: @*/
906: PetscErrorCode  VecScatterCreate(Vec xin,IS ix,Vec yin,IS iy,VecScatter *newctx)
907: {
908:   VecScatter        ctx;
909:   PetscErrorCode    ierr;
910:   PetscMPIInt       size;
911:   PetscInt          xin_type = VEC_SEQ_ID,yin_type = VEC_SEQ_ID,*range;
912:   PetscInt          ix_type  = IS_GENERAL_ID,iy_type = IS_GENERAL_ID;
913:   MPI_Comm          comm,ycomm;
914:   PetscBool         totalv,ixblock,iyblock,iystride,islocal,cando,flag;
915:   IS                tix = 0,tiy = 0;
916:   PetscViewer       viewer;
917:   PetscViewerFormat format;

920:   if (!ix && !iy) SETERRQ(PetscObjectComm((PetscObject)xin),PETSC_ERR_SUP,"Cannot pass default in for both input and output indices");

922:   /*
923:       Determine if the vectors are "parallel", ie. it shares a comm with other processors, or
924:       sequential (it does not share a comm). The difference is that parallel vectors treat the
925:       index set as providing indices in the global parallel numbering of the vector, with
926:       sequential vectors treat the index set as providing indices in the local sequential
927:       numbering
928:   */
929:   PetscObjectGetComm((PetscObject)xin,&comm);
930:   MPI_Comm_size(comm,&size);
931:   if (size > 1) xin_type = VEC_MPI_ID;

933:   PetscObjectGetComm((PetscObject)yin,&ycomm);
934:   MPI_Comm_size(ycomm,&size);
935:   if (size > 1) {comm = ycomm; yin_type = VEC_MPI_ID;}

937:   /* generate the Scatter context */
938:   PetscHeaderCreate(ctx,_p_VecScatter,int,VEC_SCATTER_CLASSID,"VecScatter","VecScatter","Vec",comm,VecScatterDestroy,VecScatterView);
939:   ctx->inuse               = PETSC_FALSE;

941:   ctx->beginandendtogether = PETSC_FALSE;
942:   PetscOptionsGetBool(NULL,"-vecscatter_merge",&ctx->beginandendtogether,NULL);
943:   if (ctx->beginandendtogether) {
944:     PetscInfo(ctx,"Using combined (merged) vector scatter begin and end\n");
945:   }
946:   ctx->packtogether = PETSC_FALSE;
947:   PetscOptionsGetBool(NULL,"-vecscatter_packtogether",&ctx->packtogether,NULL);
948:   if (ctx->packtogether) {
949:     PetscInfo(ctx,"Pack all messages before sending\n");
950:   }

952:   VecGetLocalSize(xin,&ctx->from_n);
953:   VecGetLocalSize(yin,&ctx->to_n);

955:   /*
956:       if ix or iy is not included; assume just grabbing entire vector
957:   */
958:   if (!ix && xin_type == VEC_SEQ_ID) {
959:     ISCreateStride(comm,ctx->from_n,0,1,&ix);
960:     tix  = ix;
961:   } else if (!ix && xin_type == VEC_MPI_ID) {
962:     if (yin_type == VEC_MPI_ID) {
963:       PetscInt ntmp, low;
964:       VecGetLocalSize(xin,&ntmp);
965:       VecGetOwnershipRange(xin,&low,NULL);
966:       ISCreateStride(comm,ntmp,low,1,&ix);
967:     } else {
968:       PetscInt Ntmp;
969:       VecGetSize(xin,&Ntmp);
970:       ISCreateStride(comm,Ntmp,0,1,&ix);
971:     }
972:     tix = ix;
973:   } else if (!ix) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"ix not given, but not Seq or MPI vector");

975:   if (!iy && yin_type == VEC_SEQ_ID) {
976:     ISCreateStride(comm,ctx->to_n,0,1,&iy);
977:     tiy  = iy;
978:   } else if (!iy && yin_type == VEC_MPI_ID) {
979:     if (xin_type == VEC_MPI_ID) {
980:       PetscInt ntmp, low;
981:       VecGetLocalSize(yin,&ntmp);
982:       VecGetOwnershipRange(yin,&low,NULL);
983:       ISCreateStride(comm,ntmp,low,1,&iy);
984:     } else {
985:       PetscInt Ntmp;
986:       VecGetSize(yin,&Ntmp);
987:       ISCreateStride(comm,Ntmp,0,1,&iy);
988:     }
989:     tiy = iy;
990:   } else if (!iy) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"iy not given, but not Seq or MPI vector");

992:   /*
993:      Determine types of index sets
994:   */
995:   PetscObjectTypeCompare((PetscObject)ix,ISBLOCK,&flag);
996:   if (flag) ix_type = IS_BLOCK_ID;
997:   PetscObjectTypeCompare((PetscObject)iy,ISBLOCK,&flag);
998:   if (flag) iy_type = IS_BLOCK_ID;
999:   PetscObjectTypeCompare((PetscObject)ix,ISSTRIDE,&flag);
1000:   if (flag) ix_type = IS_STRIDE_ID;
1001:   PetscObjectTypeCompare((PetscObject)iy,ISSTRIDE,&flag);
1002:   if (flag) iy_type = IS_STRIDE_ID;

1004:   /* ===========================================================================================================
1005:         Check for special cases
1006:      ==========================================================================================================*/
1007:   /* ---------------------------------------------------------------------------*/
1008:   if (xin_type == VEC_SEQ_ID && yin_type == VEC_SEQ_ID) {
1009:     if (ix_type == IS_GENERAL_ID && iy_type == IS_GENERAL_ID) {
1010:       PetscInt               nx,ny;
1011:       const PetscInt         *idx,*idy;
1012:       VecScatter_Seq_General *to = NULL,*from = NULL;

1014:       ISGetLocalSize(ix,&nx);
1015:       ISGetLocalSize(iy,&ny);
1016:       if (nx != ny) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local scatter sizes don't match");
1017:       ISGetIndices(ix,&idx);
1018:       ISGetIndices(iy,&idy);
1019:       PetscMalloc2(1,VecScatter_Seq_General,&to,1,VecScatter_Seq_General,&from);
1020:       PetscMalloc2(nx,PetscInt,&to->vslots,nx,PetscInt,&from->vslots);
1021:       to->n = nx;
1022: #if defined(PETSC_USE_DEBUG)
1023:       VecScatterCheckIndices_Private(ctx->to_n,ny,idy);
1024: #endif
1025:       PetscMemcpy(to->vslots,idy,nx*sizeof(PetscInt));
1026:       from->n = nx;
1027: #if defined(PETSC_USE_DEBUG)
1028:       VecScatterCheckIndices_Private(ctx->from_n,nx,idx);
1029: #endif
1030:        PetscMemcpy(from->vslots,idx,nx*sizeof(PetscInt));
1031:       to->type      = VEC_SCATTER_SEQ_GENERAL;
1032:       from->type    = VEC_SCATTER_SEQ_GENERAL;
1033:       ctx->todata   = (void*)to;
1034:       ctx->fromdata = (void*)from;
1035:       ctx->begin    = VecScatterBegin_SGToSG;
1036:       ctx->end      = 0;
1037:       ctx->destroy  = VecScatterDestroy_SGToSG;
1038:       ctx->copy     = VecScatterCopy_SGToSG;
1039:       ctx->view     = VecScatterView_SGToSG;
1040:       PetscInfo(xin,"Special case: sequential vector general scatter\n");
1041:       goto functionend;
1042:     } else if (ix_type == IS_STRIDE_ID &&  iy_type == IS_STRIDE_ID) {
1043:       PetscInt              nx,ny,to_first,to_step,from_first,from_step;
1044:       VecScatter_Seq_Stride *from8 = NULL,*to8 = NULL;

1046:       ISGetLocalSize(ix,&nx);
1047:       ISGetLocalSize(iy,&ny);
1048:       if (nx != ny) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local scatter sizes don't match");
1049:       ISStrideGetInfo(iy,&to_first,&to_step);
1050:       ISStrideGetInfo(ix,&from_first,&from_step);
1051:       PetscMalloc2(1,VecScatter_Seq_Stride,&to8,1,VecScatter_Seq_Stride,&from8);
1052:       to8->n        = nx;
1053:       to8->first    = to_first;
1054:       to8->step     = to_step;
1055:       from8->n      = nx;
1056:       from8->first  = from_first;
1057:       from8->step   = from_step;
1058:       to8->type     = VEC_SCATTER_SEQ_STRIDE;
1059:       from8->type   = VEC_SCATTER_SEQ_STRIDE;
1060:       ctx->todata   = (void*)to8;
1061:       ctx->fromdata = (void*)from8;
1062:       ctx->begin    = VecScatterBegin_SSToSS;
1063:       ctx->end      = 0;
1064:       ctx->destroy  = VecScatterDestroy_SSToSS;
1065:       ctx->copy     = VecScatterCopy_SSToSS;
1066:       ctx->view     = VecScatterView_SSToSS;
1067:       PetscInfo(xin,"Special case: sequential vector stride to stride\n");
1068:       goto functionend;
1069:     } else if (ix_type == IS_GENERAL_ID && iy_type == IS_STRIDE_ID) {
1070:       PetscInt               nx,ny,first,step;
1071:       const PetscInt         *idx;
1072:       VecScatter_Seq_General *from9 = NULL;
1073:       VecScatter_Seq_Stride  *to9   = NULL;

1075:       ISGetLocalSize(ix,&nx);
1076:       ISGetIndices(ix,&idx);
1077:       ISGetLocalSize(iy,&ny);
1078:       ISStrideGetInfo(iy,&first,&step);
1079:       if (nx != ny) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local scatter sizes don't match");
1080:       PetscMalloc2(1,VecScatter_Seq_Stride,&to9,1,VecScatter_Seq_General,&from9);
1081:       PetscMalloc(nx*sizeof(PetscInt),&from9->vslots);
1082:       to9->n     = nx;
1083:       to9->first = first;
1084:       to9->step  = step;
1085:       from9->n   = nx;
1086: #if defined(PETSC_USE_DEBUG)
1087:       VecScatterCheckIndices_Private(ctx->from_n,nx,idx);
1088: #endif
1089:       PetscMemcpy(from9->vslots,idx,nx*sizeof(PetscInt));
1090:       ctx->todata    = (void*)to9; ctx->fromdata = (void*)from9;
1091:       if (step == 1)  ctx->begin = VecScatterBegin_SGToSS_Stride1;
1092:       else            ctx->begin = VecScatterBegin_SGToSS;
1093:       ctx->destroy   = VecScatterDestroy_SGToSS;
1094:       ctx->end       = 0;
1095:       ctx->copy      = VecScatterCopy_SGToSS;
1096:       ctx->view      = VecScatterView_SGToSS;
1097:       to9->type      = VEC_SCATTER_SEQ_STRIDE;
1098:       from9->type    = VEC_SCATTER_SEQ_GENERAL;
1099:       PetscInfo(xin,"Special case: sequential vector general to stride\n");
1100:       goto functionend;
1101:     } else if (ix_type == IS_STRIDE_ID && iy_type == IS_GENERAL_ID) {
1102:       PetscInt               nx,ny,first,step;
1103:       const PetscInt         *idy;
1104:       VecScatter_Seq_General *to10 = NULL;
1105:       VecScatter_Seq_Stride  *from10 = NULL;

1107:       ISGetLocalSize(ix,&nx);
1108:       ISGetIndices(iy,&idy);
1109:       ISGetLocalSize(iy,&ny);
1110:       ISStrideGetInfo(ix,&first,&step);
1111:       if (nx != ny) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local scatter sizes don't match");
1112:       PetscMalloc2(1,VecScatter_Seq_General,&to10,1,VecScatter_Seq_Stride,&from10);
1113:       PetscMalloc(nx*sizeof(PetscInt),&to10->vslots);
1114:       from10->n     = nx;
1115:       from10->first = first;
1116:       from10->step  = step;
1117:       to10->n       = nx;
1118: #if defined(PETSC_USE_DEBUG)
1119:       VecScatterCheckIndices_Private(ctx->to_n,ny,idy);
1120: #endif
1121:       PetscMemcpy(to10->vslots,idy,nx*sizeof(PetscInt));
1122:       ctx->todata   = (void*)to10;
1123:       ctx->fromdata = (void*)from10;
1124:       if (step == 1) ctx->begin = VecScatterBegin_SSToSG_Stride1;
1125:       else           ctx->begin = VecScatterBegin_SSToSG;
1126:       ctx->destroy = VecScatterDestroy_SSToSG;
1127:       ctx->end     = 0;
1128:       ctx->copy    = 0;
1129:       ctx->view    = VecScatterView_SSToSG;
1130:       to10->type   = VEC_SCATTER_SEQ_GENERAL;
1131:       from10->type = VEC_SCATTER_SEQ_STRIDE;
1132:       PetscInfo(xin,"Special case: sequential vector stride to general\n");
1133:       goto functionend;
1134:     } else {
1135:       PetscInt               nx,ny;
1136:       const PetscInt         *idx,*idy;
1137:       VecScatter_Seq_General *to11 = NULL,*from11 = NULL;
1138:       PetscBool              idnx,idny;

1140:       ISGetLocalSize(ix,&nx);
1141:       ISGetLocalSize(iy,&ny);
1142:       if (nx != ny) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local scatter sizes don't match, in %D out %D",nx,ny);

1144:       ISIdentity(ix,&idnx);
1145:       ISIdentity(iy,&idny);
1146:       if (idnx && idny) {
1147:         VecScatter_Seq_Stride *to13 = NULL,*from13 = NULL;
1148:         PetscMalloc2(1,VecScatter_Seq_Stride,&to13,1,VecScatter_Seq_Stride,&from13);
1149:         to13->n       = nx;
1150:         to13->first   = 0;
1151:         to13->step    = 1;
1152:         from13->n     = nx;
1153:         from13->first = 0;
1154:         from13->step  = 1;
1155:         to13->type    = VEC_SCATTER_SEQ_STRIDE;
1156:         from13->type  = VEC_SCATTER_SEQ_STRIDE;
1157:         ctx->todata   = (void*)to13;
1158:         ctx->fromdata = (void*)from13;
1159:         ctx->begin    = VecScatterBegin_SSToSS;
1160:         ctx->end      = 0;
1161:         ctx->destroy  = VecScatterDestroy_SSToSS;
1162:         ctx->copy     = VecScatterCopy_SSToSS;
1163:         ctx->view     = VecScatterView_SSToSS;
1164:         PetscInfo(xin,"Special case: sequential copy\n");
1165:         goto functionend;
1166:       }

1168:       ISGetIndices(iy,&idy);
1169:       ISGetIndices(ix,&idx);
1170:       PetscMalloc2(1,VecScatter_Seq_General,&to11,1,VecScatter_Seq_General,&from11);
1171:       PetscMalloc2(nx,PetscInt,&to11->vslots,nx,PetscInt,&from11->vslots);
1172:       to11->n = nx;
1173: #if defined(PETSC_USE_DEBUG)
1174:       VecScatterCheckIndices_Private(ctx->to_n,ny,idy);
1175: #endif
1176:       PetscMemcpy(to11->vslots,idy,nx*sizeof(PetscInt));
1177:       from11->n = nx;
1178: #if defined(PETSC_USE_DEBUG)
1179:       VecScatterCheckIndices_Private(ctx->from_n,nx,idx);
1180: #endif
1181:       PetscMemcpy(from11->vslots,idx,nx*sizeof(PetscInt));
1182:       to11->type    = VEC_SCATTER_SEQ_GENERAL;
1183:       from11->type  = VEC_SCATTER_SEQ_GENERAL;
1184:       ctx->todata   = (void*)to11;
1185:       ctx->fromdata = (void*)from11;
1186:       ctx->begin    = VecScatterBegin_SGToSG;
1187:       ctx->end      = 0;
1188:       ctx->destroy  = VecScatterDestroy_SGToSG;
1189:       ctx->copy     = VecScatterCopy_SGToSG;
1190:       ctx->view     = VecScatterView_SGToSG;
1191:       ISRestoreIndices(ix,&idx);
1192:       ISRestoreIndices(iy,&idy);
1193:       PetscInfo(xin,"Sequential vector scatter with block indices\n");
1194:       goto functionend;
1195:     }
1196:   }
1197:   /* ---------------------------------------------------------------------------*/
1198:   if (xin_type == VEC_MPI_ID && yin_type == VEC_SEQ_ID) {

1200:     /* ===========================================================================================================
1201:           Check for special cases
1202:        ==========================================================================================================*/
1203:     islocal = PETSC_FALSE;
1204:     /* special case extracting (subset of) local portion */
1205:     if (ix_type == IS_STRIDE_ID && iy_type == IS_STRIDE_ID) {
1206:       PetscInt              nx,ny,to_first,to_step,from_first,from_step;
1207:       PetscInt              start,end,min,max;
1208:       VecScatter_Seq_Stride *from12 = NULL,*to12 = NULL;

1210:       VecGetOwnershipRange(xin,&start,&end);
1211:       ISGetLocalSize(ix,&nx);
1212:       ISStrideGetInfo(ix,&from_first,&from_step);
1213:       ISGetLocalSize(iy,&ny);
1214:       ISStrideGetInfo(iy,&to_first,&to_step);
1215:       if (nx != ny) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local scatter sizes don't match");
1216:       ISGetMinMax(ix,&min,&max);
1217:       if (min >= start && max < end) islocal = PETSC_TRUE;
1218:       else islocal = PETSC_FALSE;
1219:       MPI_Allreduce(&islocal,&cando,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)xin));
1220:       if (cando) {
1221:         PetscMalloc2(1,VecScatter_Seq_Stride,&to12,1,VecScatter_Seq_Stride,&from12);
1222:         to12->n       = nx;
1223:         to12->first   = to_first;
1224:         to12->step    = to_step;
1225:         from12->n     = nx;
1226:         from12->first = from_first-start;
1227:         from12->step  = from_step;
1228:         to12->type    = VEC_SCATTER_SEQ_STRIDE;
1229:         from12->type  = VEC_SCATTER_SEQ_STRIDE;
1230:         ctx->todata   = (void*)to12;
1231:         ctx->fromdata = (void*)from12;
1232:         ctx->begin    = VecScatterBegin_SSToSS;
1233:         ctx->end      = 0;
1234:         ctx->destroy  = VecScatterDestroy_SSToSS;
1235:         ctx->copy     = VecScatterCopy_SSToSS;
1236:         ctx->view     = VecScatterView_SSToSS;
1237:         PetscInfo(xin,"Special case: processors only getting local values\n");
1238:         goto functionend;
1239:       }
1240:     } else {
1241:       MPI_Allreduce(&islocal,&cando,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)xin));
1242:     }

1244:     /* test for special case of all processors getting entire vector */
1245:     /* contains check that PetscMPIInt can handle the sizes needed */
1246:     totalv = PETSC_FALSE;
1247:     if (ix_type == IS_STRIDE_ID && iy_type == IS_STRIDE_ID) {
1248:       PetscInt             i,nx,ny,to_first,to_step,from_first,from_step,N;
1249:       PetscMPIInt          *count = NULL,*displx;
1250:       VecScatter_MPI_ToAll *sto   = NULL;

1252:       ISGetLocalSize(ix,&nx);
1253:       ISStrideGetInfo(ix,&from_first,&from_step);
1254:       ISGetLocalSize(iy,&ny);
1255:       ISStrideGetInfo(iy,&to_first,&to_step);
1256:       if (nx != ny) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local scatter sizes don't match");
1257:       VecGetSize(xin,&N);
1258:       if (nx != N) totalv = PETSC_FALSE;
1259:       else if (from_first == 0 && from_step == 1 && from_first == to_first && from_step == to_step) totalv = PETSC_TRUE;
1260:       else totalv = PETSC_FALSE;
1261:       MPI_Allreduce(&totalv,&cando,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)xin));

1263: #if defined(PETSC_USE_64BIT_INDICES)
1264:       if (cando && (yin->map->N < PETSC_MPI_INT_MAX)) {
1265: #else
1266:       if (cando) {
1267: #endif
1268:         MPI_Comm_size(PetscObjectComm((PetscObject)ctx),&size);
1269:         PetscMalloc3(1,VecScatter_MPI_ToAll,&sto,size,PetscMPIInt,&count,size,PetscMPIInt,&displx);
1270:         range = xin->map->range;
1271:         for (i=0; i<size; i++) {
1272:           PetscMPIIntCast(range[i+1] - range[i],count+i);
1273:           PetscMPIIntCast(range[i],displx+i);
1274:         }
1275:         sto->count    = count;
1276:         sto->displx   = displx;
1277:         sto->work1    = 0;
1278:         sto->work2    = 0;
1279:         sto->type     = VEC_SCATTER_MPI_TOALL;
1280:         ctx->todata   = (void*)sto;
1281:         ctx->fromdata = 0;
1282:         ctx->begin    = VecScatterBegin_MPI_ToAll;
1283:         ctx->end      = 0;
1284:         ctx->destroy  = VecScatterDestroy_MPI_ToAll;
1285:         ctx->copy     = VecScatterCopy_MPI_ToAll;
1286:         ctx->view     = VecScatterView_MPI_ToAll;
1287:         PetscInfo(xin,"Special case: all processors get entire parallel vector\n");
1288:         goto functionend;
1289:       }
1290:     } else {
1291:       MPI_Allreduce(&totalv,&cando,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)xin));
1292:     }

1294:     /* test for special case of processor 0 getting entire vector */
1295:     /* contains check that PetscMPIInt can handle the sizes needed */
1296:     totalv = PETSC_FALSE;
1297:     if (ix_type == IS_STRIDE_ID && iy_type == IS_STRIDE_ID) {
1298:       PetscInt             i,nx,ny,to_first,to_step,from_first,from_step,N;
1299:       PetscMPIInt          rank,*count = NULL,*displx;
1300:       VecScatter_MPI_ToAll *sto = NULL;

1302:       PetscObjectGetComm((PetscObject)xin,&comm);
1303:       MPI_Comm_rank(comm,&rank);
1304:       ISGetLocalSize(ix,&nx);
1305:       ISStrideGetInfo(ix,&from_first,&from_step);
1306:       ISGetLocalSize(iy,&ny);
1307:       ISStrideGetInfo(iy,&to_first,&to_step);
1308:       if (nx != ny) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local scatter sizes don't match");
1309:       if (!rank) {
1310:         VecGetSize(xin,&N);
1311:         if (nx != N) totalv = PETSC_FALSE;
1312:         else if (from_first == 0        && from_step == 1 &&
1313:                  from_first == to_first && from_step == to_step) totalv = PETSC_TRUE;
1314:         else totalv = PETSC_FALSE;
1315:       } else {
1316:         if (!nx) totalv = PETSC_TRUE;
1317:         else     totalv = PETSC_FALSE;
1318:       }
1319:       MPI_Allreduce(&totalv,&cando,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)xin));

1321: #if defined(PETSC_USE_64BIT_INDICES)
1322:       if (cando && (yin->map->N < PETSC_MPI_INT_MAX)) {
1323: #else
1324:       if (cando) {
1325: #endif
1326:         MPI_Comm_size(PetscObjectComm((PetscObject)ctx),&size);
1327:         PetscMalloc3(1,VecScatter_MPI_ToAll,&sto,size,PetscMPIInt,&count,size,PetscMPIInt,&displx);
1328:         range = xin->map->range;
1329:         for (i=0; i<size; i++) {
1330:           PetscMPIIntCast(range[i+1] - range[i],count+i);
1331:           PetscMPIIntCast(range[i],displx+i);
1332:         }
1333:         sto->count    = count;
1334:         sto->displx   = displx;
1335:         sto->work1    = 0;
1336:         sto->work2    = 0;
1337:         sto->type     = VEC_SCATTER_MPI_TOONE;
1338:         ctx->todata   = (void*)sto;
1339:         ctx->fromdata = 0;
1340:         ctx->begin    = VecScatterBegin_MPI_ToOne;
1341:         ctx->end      = 0;
1342:         ctx->destroy  = VecScatterDestroy_MPI_ToAll;
1343:         ctx->copy     = VecScatterCopy_MPI_ToAll;
1344:         ctx->view     = VecScatterView_MPI_ToAll;
1345:         PetscInfo(xin,"Special case: processor zero gets entire parallel vector, rest get none\n");
1346:         goto functionend;
1347:       }
1348:     } else {
1349:       MPI_Allreduce(&totalv,&cando,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)xin));
1350:     }

1352:     PetscObjectTypeCompare((PetscObject)ix,ISBLOCK,&ixblock);
1353:     PetscObjectTypeCompare((PetscObject)iy,ISBLOCK,&iyblock);
1354:     PetscObjectTypeCompare((PetscObject)iy,ISSTRIDE,&iystride);
1355:     if (ixblock) {
1356:       /* special case block to block */
1357:       if (iyblock) {
1358:         PetscInt       nx,ny,bsx,bsy;
1359:         const PetscInt *idx,*idy;
1360:         ISGetBlockSize(iy,&bsy);
1361:         ISGetBlockSize(ix,&bsx);
1362:         if (bsx == bsy && VecScatterOptimizedBS(bsx)) {
1363:           ISBlockGetLocalSize(ix,&nx);
1364:           ISBlockGetIndices(ix,&idx);
1365:           ISBlockGetLocalSize(iy,&ny);
1366:           ISBlockGetIndices(iy,&idy);
1367:           if (nx != ny) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local scatter sizes don't match");
1368:           VecScatterCreate_PtoS(nx,idx,ny,idy,xin,yin,bsx,ctx);
1369:           ISBlockRestoreIndices(ix,&idx);
1370:           ISBlockRestoreIndices(iy,&idy);
1371:           PetscInfo(xin,"Special case: blocked indices\n");
1372:           goto functionend;
1373:         }
1374:         /* special case block to stride */
1375:       } else if (iystride) {
1376:         PetscInt ystart,ystride,ysize,bsx;
1377:         ISStrideGetInfo(iy,&ystart,&ystride);
1378:         ISGetLocalSize(iy,&ysize);
1379:         ISGetBlockSize(ix,&bsx);
1380:         /* see if stride index set is equivalent to block index set */
1381:         if (VecScatterOptimizedBS(bsx) && ((ystart % bsx) == 0) && (ystride == 1) && ((ysize % bsx) == 0)) {
1382:           PetscInt       nx,il,*idy;
1383:           const PetscInt *idx;
1384:           ISBlockGetLocalSize(ix,&nx);
1385:           ISBlockGetIndices(ix,&idx);
1386:           if (ysize != bsx*nx) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local scatter sizes don't match");
1387:           PetscMalloc(nx*sizeof(PetscInt),&idy);
1388:           if (nx) {
1389:             idy[0] = ystart/bsx;
1390:             for (il=1; il<nx; il++) idy[il] = idy[il-1] + 1;
1391:           }
1392:           VecScatterCreate_PtoS(nx,idx,nx,idy,xin,yin,bsx,ctx);
1393:           PetscFree(idy);
1394:           ISBlockRestoreIndices(ix,&idx);
1395:           PetscInfo(xin,"Special case: blocked indices to stride\n");
1396:           goto functionend;
1397:         }
1398:       }
1399:     }
1400:     /* left over general case */
1401:     {
1402:       PetscInt       nx,ny;
1403:       const PetscInt *idx,*idy;
1404:       ISGetLocalSize(ix,&nx);
1405:       ISGetIndices(ix,&idx);
1406:       ISGetLocalSize(iy,&ny);
1407:       ISGetIndices(iy,&idy);
1408:       if (nx != ny) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local scatter sizes don't match (%d %d)",nx,ny);
1409:       VecScatterCreate_PtoS(nx,idx,ny,idy,xin,yin,1,ctx);
1410:       ISRestoreIndices(ix,&idx);
1411:       ISRestoreIndices(iy,&idy);
1412:       PetscInfo(xin,"General case: MPI to Seq\n");
1413:       goto functionend;
1414:     }
1415:   }
1416:   /* ---------------------------------------------------------------------------*/
1417:   if (xin_type == VEC_SEQ_ID && yin_type == VEC_MPI_ID) {
1418:     /* ===========================================================================================================
1419:           Check for special cases
1420:        ==========================================================================================================*/
1421:     /* special case local copy portion */
1422:     islocal = PETSC_FALSE;
1423:     if (ix_type == IS_STRIDE_ID && iy_type == IS_STRIDE_ID) {
1424:       PetscInt              nx,ny,to_first,to_step,from_step,start,end,from_first,min,max;
1425:       VecScatter_Seq_Stride *from = NULL,*to = NULL;

1427:       VecGetOwnershipRange(yin,&start,&end);
1428:       ISGetLocalSize(ix,&nx);
1429:       ISStrideGetInfo(ix,&from_first,&from_step);
1430:       ISGetLocalSize(iy,&ny);
1431:       ISStrideGetInfo(iy,&to_first,&to_step);
1432:       if (nx != ny) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local scatter sizes don't match");
1433:       ISGetMinMax(iy,&min,&max);
1434:       if (min >= start && max < end) islocal = PETSC_TRUE;
1435:       else islocal = PETSC_FALSE;
1436:       MPI_Allreduce(&islocal,&cando,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)yin));
1437:       if (cando) {
1438:         PetscMalloc2(1,VecScatter_Seq_Stride,&to,1,VecScatter_Seq_Stride,&from);
1439:         to->n         = nx;
1440:         to->first     = to_first-start;
1441:         to->step      = to_step;
1442:         from->n       = nx;
1443:         from->first   = from_first;
1444:         from->step    = from_step;
1445:         to->type      = VEC_SCATTER_SEQ_STRIDE;
1446:         from->type    = VEC_SCATTER_SEQ_STRIDE;
1447:         ctx->todata   = (void*)to;
1448:         ctx->fromdata = (void*)from;
1449:         ctx->begin    = VecScatterBegin_SSToSS;
1450:         ctx->end      = 0;
1451:         ctx->destroy  = VecScatterDestroy_SSToSS;
1452:         ctx->copy     = VecScatterCopy_SSToSS;
1453:         ctx->view     = VecScatterView_SSToSS;
1454:         PetscInfo(xin,"Special case: sequential stride to MPI stride\n");
1455:         goto functionend;
1456:       }
1457:     } else {
1458:       MPI_Allreduce(&islocal,&cando,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)yin));
1459:     }
1460:     /* special case block to stride */
1461:     if (ix_type == IS_BLOCK_ID && iy_type == IS_STRIDE_ID) {
1462:       PetscInt ystart,ystride,ysize,bsx;
1463:       ISStrideGetInfo(iy,&ystart,&ystride);
1464:       ISGetLocalSize(iy,&ysize);
1465:       ISGetBlockSize(ix,&bsx);
1466:       /* see if stride index set is equivalent to block index set */
1467:       if (VecScatterOptimizedBS(bsx) && ((ystart % bsx) == 0) && (ystride == 1) && ((ysize % bsx) == 0)) {
1468:         PetscInt       nx,il,*idy;
1469:         const PetscInt *idx;
1470:         ISBlockGetLocalSize(ix,&nx);
1471:         ISBlockGetIndices(ix,&idx);
1472:         if (ysize != bsx*nx) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local scatter sizes don't match");
1473:         PetscMalloc(nx*sizeof(PetscInt),&idy);
1474:         if (nx) {
1475:           idy[0] = ystart/bsx;
1476:           for (il=1; il<nx; il++) idy[il] = idy[il-1] + 1;
1477:         }
1478:         VecScatterCreate_StoP(nx,idx,nx,idy,xin,yin,bsx,ctx);
1479:         PetscFree(idy);
1480:         ISBlockRestoreIndices(ix,&idx);
1481:         PetscInfo(xin,"Special case: Blocked indices to stride\n");
1482:         goto functionend;
1483:       }
1484:     }

1486:     /* general case */
1487:     {
1488:       PetscInt       nx,ny;
1489:       const PetscInt *idx,*idy;
1490:       ISGetLocalSize(ix,&nx);
1491:       ISGetIndices(ix,&idx);
1492:       ISGetLocalSize(iy,&ny);
1493:       ISGetIndices(iy,&idy);
1494:       if (nx != ny) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local scatter sizes don't match");
1495:       VecScatterCreate_StoP(nx,idx,ny,idy,xin,yin,1,ctx);
1496:       ISRestoreIndices(ix,&idx);
1497:       ISRestoreIndices(iy,&idy);
1498:       PetscInfo(xin,"General case: Seq to MPI\n");
1499:       goto functionend;
1500:     }
1501:   }
1502:   /* ---------------------------------------------------------------------------*/
1503:   if (xin_type == VEC_MPI_ID && yin_type == VEC_MPI_ID) {
1504:     /* no special cases for now */
1505:     PetscInt       nx,ny;
1506:     const PetscInt *idx,*idy;
1507:     ISGetLocalSize(ix,&nx);
1508:     ISGetIndices(ix,&idx);
1509:     ISGetLocalSize(iy,&ny);
1510:     ISGetIndices(iy,&idy);
1511:     if (nx != ny) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local scatter sizes don't match");
1512:     VecScatterCreate_PtoP(nx,idx,ny,idy,xin,yin,1,ctx);
1513:     ISRestoreIndices(ix,&idx);
1514:     ISRestoreIndices(iy,&idy);
1515:     PetscInfo(xin,"General case: MPI to MPI\n");
1516:     goto functionend;
1517:   }

1519:   functionend:
1520:   *newctx = ctx;
1521:   ISDestroy(&tix);
1522:   ISDestroy(&tiy);

1524:   PetscOptionsGetViewer(PetscObjectComm((PetscObject)ctx),((PetscObject)ctx)->prefix,"-vecscatter_view",&viewer,&format,&flag);
1525:   if (flag) {
1526:     PetscViewerPushFormat(viewer,format);
1527:     VecScatterView(ctx,viewer);
1528:     PetscViewerPopFormat(viewer);
1529:     PetscViewerDestroy(&viewer);
1530:   }
1531:   return(0);
1532: }

1534: /* ------------------------------------------------------------------*/
1537: /*@
1538:    VecScatterGetMerged - Returns true if the scatter is completed in the VecScatterBegin()
1539:       and the VecScatterEnd() does nothing

1541:    Not Collective

1543:    Input Parameter:
1544: .   ctx - scatter context created with VecScatterCreate()

1546:    Output Parameter:
1547: .   flg - PETSC_TRUE if the VecScatterBegin/End() are all done during the VecScatterBegin()

1549:    Level: developer

1551: .seealso: VecScatterCreate(), VecScatterEnd(), VecScatterBegin()
1552: @*/
1553: PetscErrorCode  VecScatterGetMerged(VecScatter ctx,PetscBool  *flg)
1554: {
1557:   *flg = ctx->beginandendtogether;
1558:   return(0);
1559: }

1563: /*@
1564:    VecScatterBegin - Begins a generalized scatter from one vector to
1565:    another. Complete the scattering phase with VecScatterEnd().

1567:    Neighbor-wise Collective on VecScatter and Vec

1569:    Input Parameters:
1570: +  inctx - scatter context generated by VecScatterCreate()
1571: .  x - the vector from which we scatter
1572: .  y - the vector to which we scatter
1573: .  addv - either ADD_VALUES or INSERT_VALUES, with INSERT_VALUES mode any location
1574:           not scattered to retains its old value; i.e. the vector is NOT first zeroed.
1575: -  mode - the scattering mode, usually SCATTER_FORWARD.  The available modes are:
1576:     SCATTER_FORWARD or SCATTER_REVERSE


1579:    Level: intermediate

1581:    Options Database: See VecScatterCreate()

1583:    Notes:
1584:    The vectors x and y need not be the same vectors used in the call
1585:    to VecScatterCreate(), but x must have the same parallel data layout
1586:    as that passed in as the x to VecScatterCreate(), similarly for the y.
1587:    Most likely they have been obtained from VecDuplicate().

1589:    You cannot change the values in the input vector between the calls to VecScatterBegin()
1590:    and VecScatterEnd().

1592:    If you use SCATTER_REVERSE the two arguments x and y should be reversed, from
1593:    the SCATTER_FORWARD.

1595:    y[iy[i]] = x[ix[i]], for i=0,...,ni-1

1597:    This scatter is far more general than the conventional
1598:    scatter, since it can be a gather or a scatter or a combination,
1599:    depending on the indices ix and iy.  If x is a parallel vector and y
1600:    is sequential, VecScatterBegin() can serve to gather values to a
1601:    single processor.  Similarly, if y is parallel and x sequential, the
1602:    routine can scatter from one processor to many processors.

1604:    Concepts: scatter^between vectors
1605:    Concepts: gather^between vectors

1607: .seealso: VecScatterCreate(), VecScatterEnd()
1608: @*/
1609: PetscErrorCode  VecScatterBegin(VecScatter inctx,Vec x,Vec y,InsertMode addv,ScatterMode mode)
1610: {
1612: #if defined(PETSC_USE_DEBUG)
1613:   PetscInt       to_n,from_n;
1614: #endif
1619:   if (inctx->inuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE," Scatter ctx already in use");

1621: #if defined(PETSC_USE_DEBUG)
1622:   /*
1623:      Error checking to make sure these vectors match the vectors used
1624:    to create the vector scatter context. -1 in the from_n and to_n indicate the
1625:    vector lengths are unknown (for example with mapped scatters) and thus
1626:    no error checking is performed.
1627:   */
1628:   if (inctx->from_n >= 0 && inctx->to_n >= 0) {
1629:     VecGetLocalSize(x,&from_n);
1630:     VecGetLocalSize(y,&to_n);
1631:     if (mode & SCATTER_REVERSE) {
1632:       if (to_n != inctx->from_n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Vector wrong size %D for scatter %D (scatter reverse and vector to != ctx from size)",to_n,inctx->from_n);
1633:       if (from_n != inctx->to_n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Vector wrong size %D for scatter %D (scatter reverse and vector from != ctx to size)",from_n,inctx->to_n);
1634:     } else {
1635:       if (to_n != inctx->to_n)     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Vector wrong size %D for scatter %D (scatter forward and vector to != ctx to size)",to_n,inctx->to_n);
1636:       if (from_n != inctx->from_n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Vector wrong size %D for scatter %D (scatter forward and vector from != ctx from size)",from_n,inctx->from_n);
1637:     }
1638:   }
1639: #endif

1641:   inctx->inuse = PETSC_TRUE;
1642:   PetscLogEventBarrierBegin(VEC_ScatterBarrier,0,0,0,0,PetscObjectComm((PetscObject)inctx));
1643:   (*inctx->begin)(inctx,x,y,addv,mode);
1644:   if (inctx->beginandendtogether && inctx->end) {
1645:     inctx->inuse = PETSC_FALSE;
1646:     (*inctx->end)(inctx,x,y,addv,mode);
1647:   }
1648:   PetscLogEventBarrierEnd(VEC_ScatterBarrier,0,0,0,0,PetscObjectComm((PetscObject)inctx));
1649:   return(0);
1650: }

1652: /* --------------------------------------------------------------------*/
1655: /*@
1656:    VecScatterEnd - Ends a generalized scatter from one vector to another.  Call
1657:    after first calling VecScatterBegin().

1659:    Neighbor-wise Collective on VecScatter and Vec

1661:    Input Parameters:
1662: +  ctx - scatter context generated by VecScatterCreate()
1663: .  x - the vector from which we scatter
1664: .  y - the vector to which we scatter
1665: .  addv - either ADD_VALUES or INSERT_VALUES.
1666: -  mode - the scattering mode, usually SCATTER_FORWARD.  The available modes are:
1667:      SCATTER_FORWARD, SCATTER_REVERSE

1669:    Level: intermediate

1671:    Notes:
1672:    If you use SCATTER_REVERSE the arguments x and y should be reversed, from the SCATTER_FORWARD.

1674:    y[iy[i]] = x[ix[i]], for i=0,...,ni-1

1676: .seealso: VecScatterBegin(), VecScatterCreate()
1677: @*/
1678: PetscErrorCode  VecScatterEnd(VecScatter ctx,Vec x,Vec y,InsertMode addv,ScatterMode mode)
1679: {

1686:   ctx->inuse = PETSC_FALSE;
1687:   if (!ctx->end) return(0);
1688:   if (!ctx->beginandendtogether) {
1689:     PetscLogEventBegin(VEC_ScatterEnd,ctx,x,y,0);
1690:     (*(ctx)->end)(ctx,x,y,addv,mode);
1691:     PetscLogEventEnd(VEC_ScatterEnd,ctx,x,y,0);
1692:   }
1693:   return(0);
1694: }

1698: /*@C
1699:    VecScatterDestroy - Destroys a scatter context created by
1700:    VecScatterCreate().

1702:    Collective on VecScatter

1704:    Input Parameter:
1705: .  ctx - the scatter context

1707:    Level: intermediate

1709: .seealso: VecScatterCreate(), VecScatterCopy()
1710: @*/
1711: PetscErrorCode  VecScatterDestroy(VecScatter *ctx)
1712: {

1716:   if (!*ctx) return(0);
1718:   if ((*ctx)->inuse) SETERRQ(((PetscObject)(*ctx))->comm,PETSC_ERR_ARG_WRONGSTATE,"Scatter context is in use");
1719:   if (--((PetscObject)(*ctx))->refct > 0) {*ctx = 0; return(0);}

1721:   /* if memory was published with AMS then destroy it */
1722:   PetscObjectAMSViewOff((PetscObject)(*ctx));
1723:   (*(*ctx)->destroy)(*ctx);
1724:   PetscHeaderDestroy(ctx);
1725:   return(0);
1726: }

1730: /*@
1731:    VecScatterCopy - Makes a copy of a scatter context.

1733:    Collective on VecScatter

1735:    Input Parameter:
1736: .  sctx - the scatter context

1738:    Output Parameter:
1739: .  ctx - the context copy

1741:    Level: advanced

1743: .seealso: VecScatterCreate(), VecScatterDestroy()
1744: @*/
1745: PetscErrorCode  VecScatterCopy(VecScatter sctx,VecScatter *ctx)
1746: {

1752:   if (!sctx->copy) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot copy this type");
1753:   PetscHeaderCreate(*ctx,_p_VecScatter,int,VEC_SCATTER_CLASSID,"VecScatter","VecScatter","Vec",PetscObjectComm((PetscObject)sctx),VecScatterDestroy,VecScatterView);
1754:   (*ctx)->to_n   = sctx->to_n;
1755:   (*ctx)->from_n = sctx->from_n;
1756:   (*sctx->copy)(sctx,*ctx);
1757:   return(0);
1758: }


1761: /* ------------------------------------------------------------------*/
1764: /*@
1765:    VecScatterView - Views a vector scatter context.

1767:    Collective on VecScatter

1769:    Input Parameters:
1770: +  ctx - the scatter context
1771: -  viewer - the viewer for displaying the context

1773:    Level: intermediate

1775: @*/
1776: PetscErrorCode  VecScatterView(VecScatter ctx,PetscViewer viewer)
1777: {

1782:   if (!viewer) {
1783:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)ctx),&viewer);
1784:   }
1786:   if (ctx->view) {
1787:     (*ctx->view)(ctx,viewer);
1788:   }
1789:   return(0);
1790: }

1794: /*@C
1795:    VecScatterRemap - Remaps the "from" and "to" indices in a
1796:    vector scatter context. FOR EXPERTS ONLY!

1798:    Collective on VecScatter

1800:    Input Parameters:
1801: +  scat - vector scatter context
1802: .  from - remapping for "from" indices (may be NULL)
1803: -  to   - remapping for "to" indices (may be NULL)

1805:    Level: developer

1807:    Notes: In the parallel case the todata is actually the indices
1808:           from which the data is TAKEN! The from stuff is where the
1809:           data is finally put. This is VERY VERY confusing!

1811:           In the sequential case the todata is the indices where the
1812:           data is put and the fromdata is where it is taken from.
1813:           This is backwards from the paralllel case! CRY! CRY! CRY!

1815: @*/
1816: PetscErrorCode  VecScatterRemap(VecScatter scat,PetscInt *rto,PetscInt *rfrom)
1817: {
1818:   VecScatter_Seq_General *to,*from;
1819:   VecScatter_MPI_General *mto;
1820:   PetscInt               i;


1827:   from = (VecScatter_Seq_General*)scat->fromdata;
1828:   mto  = (VecScatter_MPI_General*)scat->todata;

1830:   if (mto->type == VEC_SCATTER_MPI_TOALL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Not for to all scatter");

1832:   if (rto) {
1833:     if (mto->type == VEC_SCATTER_MPI_GENERAL) {
1834:       /* handle off processor parts */
1835:       for (i=0; i<mto->starts[mto->n]; i++) mto->indices[i] = rto[mto->indices[i]];

1837:       /* handle local part */
1838:       to = &mto->local;
1839:       for (i=0; i<to->n; i++) to->vslots[i] = rto[to->vslots[i]];
1840:     } else if (from->type == VEC_SCATTER_SEQ_GENERAL) {
1841:       for (i=0; i<from->n; i++) from->vslots[i] = rto[from->vslots[i]];
1842:     } else if (from->type == VEC_SCATTER_SEQ_STRIDE) {
1843:       VecScatter_Seq_Stride *sto = (VecScatter_Seq_Stride*)from;

1845:       /* if the remapping is the identity and stride is identity then skip remap */
1846:       if (sto->step == 1 && sto->first == 0) {
1847:         for (i=0; i<sto->n; i++) {
1848:           if (rto[i] != i) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Unable to remap such scatters");
1849:         }
1850:       } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Unable to remap such scatters");
1851:     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Unable to remap such scatters");
1852:   }

1854:   if (rfrom) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unable to remap the FROM in scatters yet");

1856:   /*
1857:      Mark then vector lengths as unknown because we do not know the
1858:    lengths of the remapped vectors
1859:   */
1860:   scat->from_n = -1;
1861:   scat->to_n   = -1;
1862:   return(0);
1863: }