Actual source code: vecnest.c

petsc-3.4.5 2014-06-29
 2:  #include ../src/vec/vec/impls/nest/vecnestimpl.h

  4: /* check all blocks are filled */
  7: static PetscErrorCode VecAssemblyBegin_Nest(Vec v)
  8: {
  9:   Vec_Nest       *vs = (Vec_Nest*)v->data;
 10:   PetscInt       i;

 14:   for (i=0; i<vs->nb; i++) {
 15:     if (!vs->v[i]) SETERRQ(PetscObjectComm((PetscObject)v),PETSC_ERR_SUP,"Nest  vector cannot contain NULL blocks");
 16:     VecAssemblyBegin(vs->v[i]);
 17:   }
 18:   return(0);
 19: }

 23: static PetscErrorCode VecAssemblyEnd_Nest(Vec v)
 24: {
 25:   Vec_Nest       *vs = (Vec_Nest*)v->data;
 26:   PetscInt       i;

 30:   for (i=0; i<vs->nb; i++) {
 31:     VecAssemblyEnd(vs->v[i]);
 32:   }
 33:   return(0);
 34: }

 38: static PetscErrorCode VecDestroy_Nest(Vec v)
 39: {
 40:   Vec_Nest       *vs = (Vec_Nest*)v->data;
 41:   PetscInt       i;

 45:   if (vs->v) {
 46:     for (i=0; i<vs->nb; i++) {
 47:       VecDestroy(&vs->v[i]);
 48:     }
 49:     PetscFree(vs->v);
 50:   }
 51:   for (i=0; i<vs->nb; i++) {
 52:     ISDestroy(&vs->is[i]);
 53:   }
 54:   PetscFree(vs->is);
 55:   PetscObjectComposeFunction((PetscObject)v,"",NULL);
 56:   PetscObjectComposeFunction((PetscObject)v,"",NULL);
 57:   PetscObjectComposeFunction((PetscObject)v,"",NULL);
 58:   PetscObjectComposeFunction((PetscObject)v,"",NULL);
 59:   PetscObjectComposeFunction((PetscObject)v,"",NULL);

 61:   PetscFree(vs);
 62:   return(0);
 63: }

 65: /* supports nested blocks */
 68: static PetscErrorCode VecCopy_Nest(Vec x,Vec y)
 69: {
 70:   Vec_Nest       *bx = (Vec_Nest*)x->data;
 71:   Vec_Nest       *by = (Vec_Nest*)y->data;
 72:   PetscInt       i;

 76:   VecNestCheckCompatible2(x,1,y,2);
 77:   for (i=0; i<bx->nb; i++) {
 78:     VecCopy(bx->v[i],by->v[i]);
 79:   }
 80:   return(0);
 81: }

 83: /* supports nested blocks */
 86: static PetscErrorCode VecDuplicate_Nest(Vec x,Vec *y)
 87: {
 88:   Vec_Nest       *bx = (Vec_Nest*)x->data;
 89:   Vec            Y;
 90:   Vec            *sub;
 91:   PetscInt       i;

 95:   PetscMalloc(sizeof(Vec)*bx->nb,&sub);
 96:   for (i=0; i<bx->nb; i++) {
 97:     VecDuplicate(bx->v[i],&sub[i]);
 98:   }
 99:   VecCreateNest(PetscObjectComm((PetscObject)x),bx->nb,bx->is,sub,&Y);
100:   for (i=0; i<bx->nb; i++) {
101:     VecDestroy(&sub[i]);
102:   }
103:   PetscFree(sub);
104:   *y   = Y;
105:   return(0);
106: }

108: /* supports nested blocks */
111: static PetscErrorCode VecDot_Nest(Vec x,Vec y,PetscScalar *val)
112: {
113:   Vec_Nest       *bx = (Vec_Nest*)x->data;
114:   Vec_Nest       *by = (Vec_Nest*)y->data;
115:   PetscInt       i,nr;
116:   PetscScalar    x_dot_y,_val;

120:   nr   = bx->nb;
121:   _val = 0.0;
122:   for (i=0; i<nr; i++) {
123:     VecDot(bx->v[i],by->v[i],&x_dot_y);
124:     _val = _val + x_dot_y;
125:   }
126:   *val = _val;
127:   return(0);
128: }

130: /* supports nested blocks */
133: static PetscErrorCode VecTDot_Nest(Vec x,Vec y,PetscScalar *val)
134: {
135:   Vec_Nest       *bx = (Vec_Nest*)x->data;
136:   Vec_Nest       *by = (Vec_Nest*)y->data;
137:   PetscInt       i,nr;
138:   PetscScalar    x_dot_y,_val;

142:   nr   = bx->nb;
143:   _val = 0.0;
144:   for (i=0; i<nr; i++) {
145:     VecTDot(bx->v[i],by->v[i],&x_dot_y);
146:     _val = _val + x_dot_y;
147:   }
148:   *val = _val;
149:   return(0);
150: }

154: static PetscErrorCode VecDotNorm2_Nest(Vec x,Vec y,PetscScalar *dp, PetscScalar *nm)
155: {
156:   Vec_Nest       *bx = (Vec_Nest*)x->data;
157:   Vec_Nest       *by = (Vec_Nest*)y->data;
158:   PetscInt       i,nr;
159:   PetscScalar    x_dot_y,_dp,_nm;
160:   PetscReal      norm2_y;

164:   nr  = bx->nb;
165:   _dp = 0.0;
166:   _nm = 0.0;
167:   for (i=0; i<nr; i++) {
168:     VecDotNorm2(bx->v[i],by->v[i],&x_dot_y,&norm2_y);
169:     _dp += x_dot_y;
170:     _nm += norm2_y;
171:   }
172:   *dp = _dp;
173:   *nm = _nm;
174:   return(0);
175: }

179: static PetscErrorCode VecAXPY_Nest(Vec y,PetscScalar alpha,Vec x)
180: {
181:   Vec_Nest       *bx = (Vec_Nest*)x->data;
182:   Vec_Nest       *by = (Vec_Nest*)y->data;
183:   PetscInt       i,nr;

187:   nr = bx->nb;
188:   for (i=0; i<nr; i++) {
189:     VecAXPY(by->v[i],alpha,bx->v[i]);
190:   }
191:   return(0);
192: }

196: static PetscErrorCode VecAYPX_Nest(Vec y,PetscScalar alpha,Vec x)
197: {
198:   Vec_Nest       *bx = (Vec_Nest*)x->data;
199:   Vec_Nest       *by = (Vec_Nest*)y->data;
200:   PetscInt       i,nr;

204:   nr = bx->nb;
205:   for (i=0; i<nr; i++) {
206:     VecAYPX(by->v[i],alpha,bx->v[i]);
207:   }
208:   return(0);
209: }

213: static PetscErrorCode VecAXPBY_Nest(Vec y,PetscScalar alpha,PetscScalar beta,Vec x)
214: {
215:   Vec_Nest       *bx = (Vec_Nest*)x->data;
216:   Vec_Nest       *by = (Vec_Nest*)y->data;
217:   PetscInt       i,nr;

221:   nr = bx->nb;
222:   for (i=0; i<nr; i++) {
223:     VecAXPBY(by->v[i],alpha,beta,bx->v[i]);
224:   }
225:   return(0);
226: }

230: static PetscErrorCode VecScale_Nest(Vec x,PetscScalar alpha)
231: {
232:   Vec_Nest       *bx = (Vec_Nest*)x->data;
233:   PetscInt       i,nr;

237:   nr = bx->nb;
238:   for (i=0; i<nr; i++) {
239:     VecScale(bx->v[i],alpha);
240:   }
241:   return(0);
242: }

246: static PetscErrorCode VecPointwiseMult_Nest(Vec w,Vec x,Vec y)
247: {
248:   Vec_Nest       *bx = (Vec_Nest*)x->data;
249:   Vec_Nest       *by = (Vec_Nest*)y->data;
250:   Vec_Nest       *bw = (Vec_Nest*)w->data;
251:   PetscInt       i,nr;

255:   VecNestCheckCompatible3(w,1,x,3,y,4);
256:   nr = bx->nb;
257:   for (i=0; i<nr; i++) {
258:     VecPointwiseMult(bw->v[i],bx->v[i],by->v[i]);
259:   }
260:   return(0);
261: }

265: static PetscErrorCode VecPointwiseDivide_Nest(Vec w,Vec x,Vec y)
266: {
267:   Vec_Nest       *bx = (Vec_Nest*)x->data;
268:   Vec_Nest       *by = (Vec_Nest*)y->data;
269:   Vec_Nest       *bw = (Vec_Nest*)w->data;
270:   PetscInt       i,nr;

274:   VecNestCheckCompatible3(w,1,x,2,y,3);

276:   nr = bx->nb;
277:   for (i=0; i<nr; i++) {
278:     VecPointwiseDivide(bw->v[i],bx->v[i],by->v[i]);
279:   }
280:   return(0);
281: }

285: static PetscErrorCode VecReciprocal_Nest(Vec x)
286: {
287:   Vec_Nest       *bx = (Vec_Nest*)x->data;
288:   PetscInt       i,nr;

292:   nr = bx->nb;
293:   for (i=0; i<nr; i++) {
294:     VecReciprocal(bx->v[i]);
295:   }
296:   return(0);
297: }

301: static PetscErrorCode VecNorm_Nest(Vec xin,NormType type,PetscReal *z)
302: {
303:   Vec_Nest       *bx = (Vec_Nest*)xin->data;
304:   PetscInt       i,nr;
305:   PetscReal      z_i;
306:   PetscReal      _z;

310:   nr = bx->nb;
311:   _z = 0.0;

313:   if (type == NORM_2) {
314:     PetscScalar dot;
315:     VecDot(xin,xin,&dot);
316:     _z = PetscAbsScalar(PetscSqrtScalar(dot));
317:   } else if (type == NORM_1) {
318:     for (i=0; i<nr; i++) {
319:       VecNorm(bx->v[i],type,&z_i);
320:       _z = _z + z_i;
321:     }
322:   } else if (type == NORM_INFINITY) {
323:     for (i=0; i<nr; i++) {
324:       VecNorm(bx->v[i],type,&z_i);
325:       if (z_i > _z) _z = z_i;
326:     }
327:   }

329:   *z = _z;
330:   return(0);
331: }

335: static PetscErrorCode VecMAXPY_Nest(Vec y,PetscInt nv,const PetscScalar alpha[],Vec *x)
336: {
337:   PetscInt       v;

341:   for (v=0; v<nv; v++) {
342:     /* Do axpy on each vector,v */
343:     VecAXPY(y,alpha[v],x[v]);
344:   }
345:   return(0);
346: }

350: static PetscErrorCode VecMDot_Nest(Vec x,PetscInt nv,const Vec y[],PetscScalar *val)
351: {
352:   PetscInt       j;

356:   for (j=0; j<nv; j++) {
357:     VecDot(x,y[j],&val[j]);
358:   }
359:   return(0);
360: }

364: static PetscErrorCode VecMTDot_Nest(Vec x,PetscInt nv,const Vec y[],PetscScalar *val)
365: {
366:   PetscInt       j;

370:   for (j=0; j<nv; j++) {
371:     VecTDot(x,y[j],&val[j]);
372:   }
373:   return(0);
374: }

378: static PetscErrorCode VecSet_Nest(Vec x,PetscScalar alpha)
379: {
380:   Vec_Nest       *bx = (Vec_Nest*)x->data;
381:   PetscInt       i,nr;

385:   nr = bx->nb;
386:   for (i=0; i<nr; i++) {
387:     VecSet(bx->v[i],alpha);
388:   }
389:   return(0);
390: }

394: static PetscErrorCode VecConjugate_Nest(Vec x)
395: {
396:   Vec_Nest       *bx = (Vec_Nest*)x->data;
397:   PetscInt       j,nr;

401:   nr = bx->nb;
402:   for (j=0; j<nr; j++) {
403:     VecConjugate(bx->v[j]);
404:   }
405:   return(0);
406: }

410: static PetscErrorCode VecSwap_Nest(Vec x,Vec y)
411: {
412:   Vec_Nest       *bx = (Vec_Nest*)x->data;
413:   Vec_Nest       *by = (Vec_Nest*)y->data;
414:   PetscInt       i,nr;

418:   VecNestCheckCompatible2(x,1,y,2);
419:   nr = bx->nb;
420:   for (i=0; i<nr; i++) {
421:     VecSwap(bx->v[i],by->v[i]);
422:   }
423:   return(0);
424: }

428: static PetscErrorCode VecWAXPY_Nest(Vec w,PetscScalar alpha,Vec x,Vec y)
429: {
430:   Vec_Nest       *bx = (Vec_Nest*)x->data;
431:   Vec_Nest       *by = (Vec_Nest*)y->data;
432:   Vec_Nest       *bw = (Vec_Nest*)w->data;
433:   PetscInt       i,nr;

437:   VecNestCheckCompatible3(w,1,x,3,y,4);

439:   nr = bx->nb;
440:   for (i=0; i<nr; i++) {
441:     VecWAXPY(bw->v[i],alpha,bx->v[i],by->v[i]);
442:   }
443:   return(0);
444: }

448: static PetscErrorCode VecMax_Nest_Recursive(Vec x,PetscInt *cnt,PetscInt *p,PetscReal *max)
449: {
450:   Vec_Nest       *bx;
451:   PetscInt       i,nr;
452:   PetscBool      isnest;
453:   PetscInt       L;
454:   PetscInt       _entry_loc;
455:   PetscReal      _entry_val;

459:   PetscObjectTypeCompare((PetscObject)x,VECNEST,&isnest);
460:   if (!isnest) {
461:     /* Not nest */
462:     VecMax(x,&_entry_loc,&_entry_val);
463:     if (_entry_val > *max) {
464:       *max = _entry_val;
465:       *p   = _entry_loc + *cnt;
466:     }
467:     VecGetSize(x,&L);
468:     *cnt = *cnt + L;
469:     return(0);
470:   }

472:   /* Otherwise we have a nest */
473:   bx = (Vec_Nest*)x->data;
474:   nr = bx->nb;

476:   /* now descend recursively */
477:   for (i=0; i<nr; i++) {
478:     VecMax_Nest_Recursive(bx->v[i],cnt,p,max);
479:   }
480:   return(0);
481: }

483: /* supports nested blocks */
486: static PetscErrorCode VecMax_Nest(Vec x,PetscInt *p,PetscReal *max)
487: {
488:   PetscInt       cnt;

492:   cnt  = 0;
493:   *p   = 0;
494:   *max = 0.0;
495:   VecMax_Nest_Recursive(x,&cnt,p,max);
496:   return(0);
497: }

501: static PetscErrorCode VecMin_Nest_Recursive(Vec x,PetscInt *cnt,PetscInt *p,PetscReal *min)
502: {
503:   Vec_Nest       *bx = (Vec_Nest*)x->data;
504:   PetscInt       i,nr,L,_entry_loc;
505:   PetscBool      isnest;
506:   PetscReal      _entry_val;

510:   PetscObjectTypeCompare((PetscObject)x,VECNEST,&isnest);
511:   if (!isnest) {
512:     /* Not nest */
513:     VecMin(x,&_entry_loc,&_entry_val);
514:     if (_entry_val < *min) {
515:       *min = _entry_val;
516:       *p   = _entry_loc + *cnt;
517:     }
518:     VecGetSize(x,&L);
519:     *cnt = *cnt + L;
520:     return(0);
521:   }

523:   /* Otherwise we have a nest */
524:   bx = (Vec_Nest*)x->data;
525:   nr = bx->nb;

527:   /* now descend recursively */
528:   for (i=0; i<nr; i++) {
529:     VecMin_Nest_Recursive(bx->v[i],cnt,p,min);
530:   }
531:   return(0);
532: }

536: static PetscErrorCode VecMin_Nest(Vec x,PetscInt *p,PetscReal *min)
537: {
538:   PetscInt       cnt;

542:   cnt  = 0;
543:   *p   = 0;
544:   *min = 1.0e308;
545:   VecMin_Nest_Recursive(x,&cnt,p,min);
546:   return(0);
547: }

549: /* supports nested blocks */
552: static PetscErrorCode VecView_Nest(Vec x,PetscViewer viewer)
553: {
554:   Vec_Nest       *bx = (Vec_Nest*)x->data;
555:   PetscBool      isascii;
556:   PetscInt       i;

560:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
561:   if (isascii) {
562:     PetscViewerASCIIPrintf(viewer,"Vector Object:\n");
563:     PetscViewerASCIIPushTab(viewer);         /* push0 */
564:     PetscViewerASCIIPrintf(viewer,"type=nest, rows=%d \n",bx->nb);

566:     PetscViewerASCIIPrintf(viewer,"VecNest  structure: \n");
567:     for (i=0; i<bx->nb; i++) {
568:       VecType  type;
569:       char     name[256] = "",prefix[256] = "";
570:       PetscInt NR;

572:       VecGetSize(bx->v[i],&NR);
573:       VecGetType(bx->v[i],&type);
574:       if (((PetscObject)bx->v[i])->name) {PetscSNPrintf(name,sizeof(name),"name=\"%s\", ",((PetscObject)bx->v[i])->name);}
575:       if (((PetscObject)bx->v[i])->prefix) {PetscSNPrintf(prefix,sizeof(prefix),"prefix=\"%s\", ",((PetscObject)bx->v[i])->prefix);}

577:       PetscViewerASCIIPrintf(viewer,"(%D) : %s%stype=%s, rows=%D \n",i,name,prefix,type,NR);

579:       PetscViewerASCIIPushTab(viewer);             /* push1 */
580:       VecView(bx->v[i],viewer);
581:       PetscViewerASCIIPopTab(viewer);              /* pop1 */
582:     }
583:     PetscViewerASCIIPopTab(viewer);                /* pop0 */
584:   }
585:   return(0);
586: }

590: static PetscErrorCode VecSize_Nest_Recursive(Vec x,PetscBool globalsize,PetscInt *L)
591: {
592:   Vec_Nest       *bx;
593:   PetscInt       size,i,nr;
594:   PetscBool      isnest;

598:   PetscObjectTypeCompare((PetscObject)x,VECNEST,&isnest);
599:   if (!isnest) {
600:     /* Not nest */
601:     if (globalsize) { VecGetSize(x,&size); }
602:     else {            VecGetLocalSize(x,&size); }
603:     *L = *L + size;
604:     return(0);
605:   }

607:   /* Otherwise we have a nest */
608:   bx = (Vec_Nest*)x->data;
609:   nr = bx->nb;

611:   /* now descend recursively */
612:   for (i=0; i<nr; i++) {
613:     VecSize_Nest_Recursive(bx->v[i],globalsize,L);
614:   }
615:   return(0);
616: }

618: /* Returns the sum of the global size of all the consituent vectors in the nest */
621: static PetscErrorCode VecGetSize_Nest(Vec x,PetscInt *N)
622: {
624:   *N = x->map->N;
625:   return(0);
626: }

628: /* Returns the sum of the local size of all the consituent vectors in the nest */
631: static PetscErrorCode VecGetLocalSize_Nest(Vec x,PetscInt *n)
632: {
634:   *n = x->map->n;
635:   return(0);
636: }

640: static PetscErrorCode VecMaxPointwiseDivide_Nest(Vec x,Vec y,PetscReal *max)
641: {
642:   Vec_Nest       *bx = (Vec_Nest*)x->data;
643:   Vec_Nest       *by = (Vec_Nest*)y->data;
644:   PetscInt       i,nr;
645:   PetscReal      local_max,m;

649:   VecNestCheckCompatible2(x,1,y,2);
650:   nr = bx->nb;
651:   m  = 0.0;
652:   for (i=0; i<nr; i++) {
653:     VecMaxPointwiseDivide(bx->v[i],by->v[i],&local_max);
654:     if (local_max > m) m = local_max;
655:   }
656:   *max = m;
657:   return(0);
658: }

662: static PetscErrorCode  VecGetSubVector_Nest(Vec X,IS is,Vec *x)
663: {
664:   Vec_Nest       *bx = (Vec_Nest*)X->data;
665:   PetscInt       i;

669:   *x = NULL;
670:   for (i=0; i<bx->nb; i++) {
671:     PetscBool issame = PETSC_FALSE;
672:     ISEqual(is,bx->is[i],&issame);
673:     if (issame) {
674:       *x   = bx->v[i];
675:       PetscObjectReference((PetscObject)(*x));
676:       break;
677:     }
678:   }
679:   if (!*x) SETERRQ(PetscObjectComm((PetscObject)is),PETSC_ERR_ARG_OUTOFRANGE,"Index set not found in nested Vec");
680:   return(0);
681: }

685: static PetscErrorCode  VecRestoreSubVector_Nest(Vec X,IS is,Vec *x)
686: {

690:   VecDestroy(x);
691:   return(0);
692: }

696: static PetscErrorCode VecGetArray_Nest(Vec X,PetscScalar **x)
697: {
698:   Vec_Nest       *bx = (Vec_Nest*)X->data;
699:   PetscInt       i,m,rstart,rend;

703:   VecGetOwnershipRange(X,&rstart,&rend);
704:   VecGetLocalSize(X,&m);
705:   PetscMalloc(m*sizeof(PetscScalar),x);
706:   for (i=0; i<bx->nb; i++) {
707:     Vec               subvec = bx->v[i];
708:     IS                isy    = bx->is[i];
709:     PetscInt          j,sm;
710:     const PetscInt    *ixy;
711:     const PetscScalar *y;
712:     VecGetLocalSize(subvec,&sm);
713:     VecGetArrayRead(subvec,&y);
714:     ISGetIndices(isy,&ixy);
715:     for (j=0; j<sm; j++) {
716:       PetscInt ix = ixy[j];
717:       if (ix < rstart || rend <= ix) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for getting array from nonlocal subvec");
718:       (*x)[ix-rstart] = y[j];
719:     }
720:     ISRestoreIndices(isy,&ixy);
721:     VecRestoreArrayRead(subvec,&y);
722:   }
723:   return(0);
724: }

728: static PetscErrorCode VecRestoreArray_Nest(Vec X,PetscScalar **x)
729: {
730:   Vec_Nest       *bx = (Vec_Nest*)X->data;
731:   PetscInt       i,m,rstart,rend;

735:   VecGetOwnershipRange(X,&rstart,&rend);
736:   VecGetLocalSize(X,&m);
737:   for (i=0; i<bx->nb; i++) {
738:     Vec            subvec = bx->v[i];
739:     IS             isy    = bx->is[i];
740:     PetscInt       j,sm;
741:     const PetscInt *ixy;
742:     PetscScalar    *y;
743:     VecGetLocalSize(subvec,&sm);
744:     VecGetArray(subvec,&y);
745:     ISGetIndices(isy,&ixy);
746:     for (j=0; j<sm; j++) {
747:       PetscInt ix = ixy[j];
748:       if (ix < rstart || rend <= ix) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for getting array from nonlocal subvec");
749:       y[j] = (*x)[ix-rstart];
750:     }
751:     ISRestoreIndices(isy,&ixy);
752:     VecRestoreArray(subvec,&y);
753:   }
754:   PetscFree(*x);
755:   return(0);
756: }


761: static PetscErrorCode VecNestSetOps_Private(struct _VecOps *ops)
762: {
764:   /* 0 */
765:   ops->duplicate               = VecDuplicate_Nest;
766:   ops->duplicatevecs           = VecDuplicateVecs_Default;
767:   ops->destroyvecs             = VecDestroyVecs_Default;
768:   ops->dot                     = VecDot_Nest;
769:   ops->mdot                    = VecMDot_Nest;

771:   /* 5 */
772:   ops->norm                    = VecNorm_Nest;
773:   ops->tdot                    = VecTDot_Nest;
774:   ops->mtdot                   = VecMTDot_Nest;
775:   ops->scale                   = VecScale_Nest;
776:   ops->copy                    = VecCopy_Nest;

778:   /* 10 */
779:   ops->set                     = VecSet_Nest;
780:   ops->swap                    = VecSwap_Nest;
781:   ops->axpy                    = VecAXPY_Nest;
782:   ops->axpby                   = VecAXPBY_Nest;
783:   ops->maxpy                   = VecMAXPY_Nest;

785:   /* 15 */
786:   ops->aypx                    = VecAYPX_Nest;
787:   ops->waxpy                   = VecWAXPY_Nest;
788:   ops->axpbypcz                = 0;
789:   ops->pointwisemult           = VecPointwiseMult_Nest;
790:   ops->pointwisedivide         = VecPointwiseDivide_Nest;
791:   /* 20 */
792:   ops->setvalues               = 0;
793:   ops->assemblybegin           = VecAssemblyBegin_Nest;
794:   ops->assemblyend             = VecAssemblyEnd_Nest;
795:   ops->getarray                = VecGetArray_Nest;
796:   ops->getsize                 = VecGetSize_Nest;

798:   /* 25 */
799:   ops->getlocalsize            = VecGetLocalSize_Nest;
800:   ops->restorearray            = VecRestoreArray_Nest;
801:   ops->max                     = VecMax_Nest;
802:   ops->min                     = VecMin_Nest;
803:   ops->setrandom               = 0;

805:   /* 30 */
806:   ops->setoption               = 0;
807:   ops->setvaluesblocked        = 0;
808:   ops->destroy                 = VecDestroy_Nest;
809:   ops->view                    = VecView_Nest;
810:   ops->placearray              = 0;

812:   /* 35 */
813:   ops->replacearray            = 0;
814:   ops->dot_local               = VecDot_Nest;
815:   ops->tdot_local              = VecTDot_Nest;
816:   ops->norm_local              = VecNorm_Nest;
817:   ops->mdot_local              = VecMDot_Nest;

819:   /* 40 */
820:   ops->mtdot_local             = VecMTDot_Nest;
821:   ops->load                    = 0;
822:   ops->reciprocal              = VecReciprocal_Nest;
823:   ops->conjugate               = VecConjugate_Nest;
824:   ops->setlocaltoglobalmapping = 0;

826:   /* 45 */
827:   ops->setvalueslocal          = 0;
828:   ops->resetarray              = 0;
829:   ops->setfromoptions          = 0;
830:   ops->maxpointwisedivide      = VecMaxPointwiseDivide_Nest;
831:   ops->load                    = 0;

833:   /* 50 */
834:   ops->pointwisemax            = 0;
835:   ops->pointwisemaxabs         = 0;
836:   ops->pointwisemin            = 0;
837:   ops->getvalues               = 0;
838:   ops->sqrt                    = 0;

840:   /* 55 */
841:   ops->abs                     = 0;
842:   ops->exp                     = 0;
843:   ops->shift                   = 0;
844:   ops->create                  = 0;
845:   ops->stridegather            = 0;

847:   /* 60 */
848:   ops->stridescatter           = 0;
849:   ops->dotnorm2                = VecDotNorm2_Nest;
850:   ops->getsubvector            = VecGetSubVector_Nest;
851:   ops->restoresubvector        = VecRestoreSubVector_Nest;
852:   return(0);
853: }

857: static PetscErrorCode VecNestGetSubVecs_Private(Vec x,PetscInt m,const PetscInt idxm[],Vec vec[])
858: {
859:   Vec_Nest *b = (Vec_Nest*)x->data;
860:   PetscInt i;
861:   PetscInt row;

864:   if (!m) return(0);
865:   for (i=0; i<m; i++) {
866:     row = idxm[i];
867:     if (row >= b->nb) SETERRQ2(PetscObjectComm((PetscObject)x),PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,b->nb-1);
868:     vec[i] = b->v[row];
869:   }
870:   return(0);
871: }

875: PetscErrorCode  VecNestGetSubVec_Nest(Vec X,PetscInt idxm,Vec *sx)
876: {

880:   VecNestGetSubVecs_Private(X,1,&idxm,sx);
881:   return(0);
882: }

886: /*@
887:  VecNestGetSubVec - Returns a single, sub-vector from a nest vector.

889:  Not collective

891:  Input Parameters:
892:  .  X  - nest vector
893:  .  idxm - index of the vector within the nest

895:  Output Parameter:
896:  .  sx - vector at index idxm within the nest

898:  Notes:

900:  Level: developer

902:  .seealso: VecNestGetSize(), VecNestGetSubVecs()
903: @*/
904: PetscErrorCode  VecNestGetSubVec(Vec X,PetscInt idxm,Vec *sx)
905: {

909:   PetscUseMethod(X,"VecNestGetSubVec_C",(Vec,PetscInt,Vec*),(X,idxm,sx));
910:   return(0);
911: }

915: PetscErrorCode  VecNestGetSubVecs_Nest(Vec X,PetscInt *N,Vec **sx)
916: {
917:   Vec_Nest *b = (Vec_Nest*)X->data;

920:   if (N)  *N  = b->nb;
921:   if (sx) *sx = b->v;
922:   return(0);
923: }

927: /*@C
928:  VecNestGetSubVecs - Returns the entire array of vectors defining a nest vector.

930:  Not collective

932:  Input Parameters:
933: .  X  - nest vector

935:  Output Parameter:
936: +  N - number of nested vecs
937: -  sx - array of vectors

939:  Notes:
940:  The user should not free the array sx.

942:  Fortran Notes:
943:  The caller must allocate the array to hold the subvectors.

945:  Level: developer

947:  .seealso: VecNestGetSize(), VecNestGetSubVec()
948: @*/
949: PetscErrorCode  VecNestGetSubVecs(Vec X,PetscInt *N,Vec **sx)
950: {

954:   PetscUseMethod(X,"VecNestGetSubVecs_C",(Vec,PetscInt*,Vec**),(X,N,sx));
955:   return(0);
956: }

960: static PetscErrorCode  VecNestSetSubVec_Private(Vec X,PetscInt idxm,Vec x)
961: {
962:   Vec_Nest       *bx = (Vec_Nest*)X->data;
963:   PetscInt       i,offset=0,n=0,bs;
964:   IS             is;
966:   PetscBool      issame = PETSC_FALSE;
967:   PetscInt       N=0;

969:   /* check if idxm < bx->nb */
970:   if (idxm >= bx->nb) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Out of range index value %D maximum %D",idxm,bx->nb);

973:   VecDestroy(&bx->v[idxm]);       /* destroy the existing vector */
974:   VecDuplicate(x,&bx->v[idxm]);   /* duplicate the layout of given vector */
975:   VecCopy(x,bx->v[idxm]);         /* copy the contents of the given vector */

977:   /* check if we need to update the IS for the block */
978:   offset = X->map->rstart;
979:   for (i=0; i<idxm; i++) {
980:     n=0;
981:     VecGetLocalSize(bx->v[i],&n);
982:     offset += n;
983:   }

985:   /* get the local size and block size */
986:   VecGetLocalSize(x,&n);
987:   VecGetBlockSize(x,&bs);

989:   /* create the new IS */
990:   ISCreateStride(PetscObjectComm((PetscObject)x),n,offset,1,&is);
991:   ISSetBlockSize(is,bs);

993:   /* check if they are equal */
994:   ISEqual(is,bx->is[idxm],&issame);

996:   if (!issame) {
997:     /* The IS of given vector has a different layout compared to the existing block vector.
998:      Destroy the existing reference and update the IS. */
999:     ISDestroy(&bx->is[idxm]);
1000:     ISDuplicate(is,&bx->is[idxm]);
1001:     ISCopy(is,bx->is[idxm]);

1003:     offset += n;
1004:     /* Since the current IS[idxm] changed, we need to update all the subsequent IS */
1005:     for (i=idxm+1; i<bx->nb; i++) {
1006:       /* get the local size and block size */
1007:       VecGetLocalSize(bx->v[i],&n);
1008:       VecGetBlockSize(bx->v[i],&bs);

1010:       /* destroy the old and create the new IS */
1011:       ISDestroy(&bx->is[i]);
1012:       ISCreateStride(((PetscObject)bx->v[i])->comm,n,offset,1,&bx->is[i]);
1013:       ISSetBlockSize(bx->is[i],bs);

1015:       offset += n;
1016:     }

1018:     n=0;
1019:     VecSize_Nest_Recursive(X,PETSC_TRUE,&N);
1020:     VecSize_Nest_Recursive(X,PETSC_FALSE,&n);
1021:     PetscLayoutSetSize(X->map,N);
1022:     PetscLayoutSetLocalSize(X->map,n);
1023:   }

1025:   ISDestroy(&is);
1026:   return(0);
1027: }

1031: PetscErrorCode  VecNestSetSubVec_Nest(Vec X,PetscInt idxm,Vec sx)
1032: {

1036:   VecNestSetSubVec_Private(X,idxm,sx);
1037:   return(0);
1038: }

1042: /*@
1043:    VecNestSetSubVec - Set a single component vector in a nest vector at specified index.

1045:    Not collective

1047:    Input Parameters:
1048: +  X  - nest vector
1049: .  idxm - index of the vector within the nest vector
1050: -  sx - vector at index idxm within the nest vector

1052:    Notes:
1053:    The new vector sx does not have to be of same size as X[idxm]. Arbitrary vector layouts are allowed.

1055:    Level: developer

1057: .seealso: VecNestSetSubVecs(), VecNestGetSubVec()
1058: @*/
1059: PetscErrorCode  VecNestSetSubVec(Vec X,PetscInt idxm,Vec sx)
1060: {

1064:   PetscUseMethod(X,"VecNestSetSubVec_C",(Vec,PetscInt,Vec),(X,idxm,sx));
1065:   return(0);
1066: }

1070: PetscErrorCode  VecNestSetSubVecs_Nest(Vec X,PetscInt N,PetscInt *idxm,Vec *sx)
1071: {
1072:   PetscInt       i;

1076:   for (i=0; i<N; i++) {
1077:     VecNestSetSubVec_Private(X,idxm[i],sx[i]);
1078:   }
1079:   return(0);
1080: }

1084: /*@C
1085:    VecNestSetSubVecs - Sets the component vectors at the specified indices in a nest vector.

1087:    Not collective

1089:    Input Parameters:
1090: +  X  - nest vector
1091: .  N - number of component vecs in sx
1092: .  idxm - indices of component vecs that are to be replaced
1093: -  sx - array of vectors

1095:    Notes:
1096:    The components in the vector array sx do not have to be of the same size as corresponding
1097:    components in X. The user can also free the array "sx" after the call.

1099:    Level: developer

1101: .seealso: VecNestGetSize(), VecNestGetSubVec()
1102: @*/
1103: PetscErrorCode  VecNestSetSubVecs(Vec X,PetscInt N,PetscInt *idxm,Vec *sx)
1104: {

1108:   PetscUseMethod(X,"VecNestSetSubVecs_C",(Vec,PetscInt,PetscInt*,Vec*),(X,N,idxm,sx));
1109:   return(0);
1110: }

1114: PetscErrorCode  VecNestGetSize_Nest(Vec X,PetscInt *N)
1115: {
1116:   Vec_Nest *b = (Vec_Nest*)X->data;

1119:   *N = b->nb;
1120:   return(0);
1121: }

1125: /*@
1126:  VecNestGetSize - Returns the size of the nest vector.

1128:  Not collective

1130:  Input Parameters:
1131:  .  X  - nest vector

1133:  Output Parameter:
1134:  .  N - number of nested vecs

1136:  Notes:

1138:  Level: developer

1140:  .seealso: VecNestGetSubVec(), VecNestGetSubVecs()
1141: @*/
1142: PetscErrorCode  VecNestGetSize(Vec X,PetscInt *N)
1143: {

1149:   PetscUseMethod(X,"VecNestGetSize_C",(Vec,PetscInt*),(X,N));
1150:   return(0);
1151: }

1155: static PetscErrorCode VecSetUp_Nest_Private(Vec V,PetscInt nb,Vec x[])
1156: {
1157:   Vec_Nest       *ctx = (Vec_Nest*)V->data;
1158:   PetscInt       i;

1162:   if (ctx->setup_called) return(0);

1164:   ctx->nb = nb;
1165:   if (ctx->nb < 0) SETERRQ(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_WRONG,"Cannot create VECNEST with < 0 blocks.");

1167:   /* Create space */
1168:   PetscMalloc(ctx->nb*sizeof(Vec),&ctx->v);
1169:   for (i=0; i<ctx->nb; i++) {
1170:     ctx->v[i] = x[i];
1171:     PetscObjectReference((PetscObject)x[i]);
1172:     /* Do not allocate memory for internal sub blocks */
1173:   }

1175:   PetscMalloc(ctx->nb*sizeof(IS),&ctx->is);

1177:   ctx->setup_called = PETSC_TRUE;
1178:   return(0);
1179: }

1183: static PetscErrorCode VecSetUp_NestIS_Private(Vec V,PetscInt nb,IS is[])
1184: {
1185:   Vec_Nest       *ctx = (Vec_Nest*)V->data;
1186:   PetscInt       i,offset,m,n,M,N;

1190:   if (is) {                     /* Do some consistency checks and reference the is */
1191:     offset = V->map->rstart;
1192:     for (i=0; i<ctx->nb; i++) {
1193:       ISGetSize(is[i],&M);
1194:       VecGetSize(ctx->v[i],&N);
1195:       if (M != N) SETERRQ3(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_INCOMP,"In slot %D, IS of size %D is not compatible with Vec of size %D",i,M,N);
1196:       ISGetLocalSize(is[i],&m);
1197:       VecGetLocalSize(ctx->v[i],&n);
1198:       if (m != n) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"In slot %D, IS of local size %D is not compatible with Vec of local size %D",i,m,n);
1199: #if defined(PETSC_USE_DEBUG)
1200:       {                         /* This test can be expensive */
1201:         PetscInt  start;
1202:         PetscBool contiguous;
1203:         ISContiguousLocal(is[i],offset,offset+n,&start,&contiguous);
1204:         if (!contiguous) SETERRQ1(PetscObjectComm((PetscObject)V),PETSC_ERR_SUP,"Index set %D is not contiguous with layout of matching vector",i);
1205:         if (start != 0) SETERRQ1(PetscObjectComm((PetscObject)V),PETSC_ERR_SUP,"Index set %D introduces overlap or a hole",i);
1206:       }
1207: #endif
1208:       PetscObjectReference((PetscObject)is[i]);
1209:       ctx->is[i] = is[i];
1210:       offset += n;
1211:     }
1212:   } else {                      /* Create a contiguous ISStride for each entry */
1213:     offset = V->map->rstart;
1214:     for (i=0; i<ctx->nb; i++) {
1215:       PetscInt bs;
1216:       VecGetLocalSize(ctx->v[i],&n);
1217:       VecGetBlockSize(ctx->v[i],&bs);
1218:       ISCreateStride(((PetscObject)ctx->v[i])->comm,n,offset,1,&ctx->is[i]);
1219:       ISSetBlockSize(ctx->is[i],bs);
1220:       offset += n;
1221:     }
1222:   }
1223:   return(0);
1224: }

1228: /*@C
1229:    VecCreateNest - Creates a new vector containing several nested subvectors, each stored separately

1231:    Collective on Vec

1233:    Input Parameter:
1234: +  comm - Communicator for the new Vec
1235: .  nb - number of nested blocks
1236: .  is - array of nb index sets describing each nested block, or NULL to pack subvectors contiguously
1237: -  x - array of nb sub-vectors

1239:    Output Parameter:
1240: .  Y - new vector

1242:    Level: advanced

1244: .seealso: VecCreate(), MatCreateNest(), DMSetVecType(), VECNEST
1245: @*/
1246: PetscErrorCode  VecCreateNest(MPI_Comm comm,PetscInt nb,IS is[],Vec x[],Vec *Y)
1247: {
1248:   Vec            V;
1249:   Vec_Nest       *s;
1250:   PetscInt       n,N;

1254:   VecCreate(comm,&V);
1255:   PetscObjectChangeTypeName((PetscObject)V,VECNEST);

1257:   /* allocate and set pointer for implememtation data */
1258:   PetscMalloc(sizeof(Vec_Nest),&s);
1259:   PetscMemzero(s,sizeof(Vec_Nest));
1260:   V->data          = (void*)s;
1261:   s->setup_called  = PETSC_FALSE;
1262:   s->nb            = -1;
1263:   s->v             = NULL;

1265:   VecSetUp_Nest_Private(V,nb,x);

1267:   n = N = 0;
1268:   VecSize_Nest_Recursive(V,PETSC_TRUE,&N);
1269:   VecSize_Nest_Recursive(V,PETSC_FALSE,&n);
1270:   PetscLayoutSetSize(V->map,N);
1271:   PetscLayoutSetLocalSize(V->map,n);
1272:   PetscLayoutSetBlockSize(V->map,1);
1273:   PetscLayoutSetUp(V->map);

1275:   VecSetUp_NestIS_Private(V,nb,is);

1277:   VecNestSetOps_Private(V->ops);
1278:   V->petscnative = PETSC_FALSE;


1281:   /* expose block api's */
1282:   PetscObjectComposeFunction((PetscObject)V,"VecNestGetSubVec_C",VecNestGetSubVec_Nest);
1283:   PetscObjectComposeFunction((PetscObject)V,"VecNestGetSubVecs_C",VecNestGetSubVecs_Nest);
1284:   PetscObjectComposeFunction((PetscObject)V,"VecNestSetSubVec_C",VecNestSetSubVec_Nest);
1285:   PetscObjectComposeFunction((PetscObject)V,"VecNestSetSubVecs_C",VecNestSetSubVecs_Nest);
1286:   PetscObjectComposeFunction((PetscObject)V,"VecNestGetSize_C",VecNestGetSize_Nest);

1288:   *Y = V;
1289:   return(0);
1290: }

1292: /*MC
1293:   VECNEST - VECNEST = "nest" - Vector type consisting of nested subvectors, each stored separately.

1295:   Level: intermediate

1297:   Notes:
1298:   This vector type reduces the number of copies for certain solvers applied to multi-physics problems.
1299:   It is usually used with MATNEST and DMComposite via DMSetVecType().

1301: .seealso: VecCreate(), VecType, VecCreateNest(), MatCreateNest()
1302: M*/