Actual source code: vecnest.c
  2: #include <../src/vec/vec/impls/nest/vecnestimpl.h>
  4: /* check all blocks are filled */
  5: static PetscErrorCode VecAssemblyBegin_Nest(Vec v)
  6: {
  7:   Vec_Nest       *vs = (Vec_Nest*)v->data;
  8:   PetscInt       i;
 12:   for (i=0; i<vs->nb; i++) {
 13:     if (!vs->v[i]) SETERRQ(PetscObjectComm((PetscObject)v),PETSC_ERR_SUP,"Nest  vector cannot contain NULL blocks");
 14:     VecAssemblyBegin(vs->v[i]);
 15:   }
 16:   return(0);
 17: }
 19: static PetscErrorCode VecAssemblyEnd_Nest(Vec v)
 20: {
 21:   Vec_Nest       *vs = (Vec_Nest*)v->data;
 22:   PetscInt       i;
 26:   for (i=0; i<vs->nb; i++) {
 27:     VecAssemblyEnd(vs->v[i]);
 28:   }
 29:   return(0);
 30: }
 32: static PetscErrorCode VecDestroy_Nest(Vec v)
 33: {
 34:   Vec_Nest       *vs = (Vec_Nest*)v->data;
 35:   PetscInt       i;
 39:   if (vs->v) {
 40:     for (i=0; i<vs->nb; i++) {
 41:       VecDestroy(&vs->v[i]);
 42:     }
 43:     PetscFree(vs->v);
 44:   }
 45:   for (i=0; i<vs->nb; i++) {
 46:     ISDestroy(&vs->is[i]);
 47:   }
 48:   PetscFree(vs->is);
 49:   PetscObjectComposeFunction((PetscObject)v,"",NULL);
 50:   PetscObjectComposeFunction((PetscObject)v,"",NULL);
 51:   PetscObjectComposeFunction((PetscObject)v,"",NULL);
 52:   PetscObjectComposeFunction((PetscObject)v,"",NULL);
 53:   PetscObjectComposeFunction((PetscObject)v,"",NULL);
 55:   PetscFree(vs);
 56:   return(0);
 57: }
 59: /* supports nested blocks */
 60: static PetscErrorCode VecCopy_Nest(Vec x,Vec y)
 61: {
 62:   Vec_Nest       *bx = (Vec_Nest*)x->data;
 63:   Vec_Nest       *by = (Vec_Nest*)y->data;
 64:   PetscInt       i;
 68:   VecNestCheckCompatible2(x,1,y,2);
 69:   for (i=0; i<bx->nb; i++) {
 70:     VecCopy(bx->v[i],by->v[i]);
 71:   }
 72:   return(0);
 73: }
 75: /* supports nested blocks */
 76: static PetscErrorCode VecDuplicate_Nest(Vec x,Vec *y)
 77: {
 78:   Vec_Nest       *bx = (Vec_Nest*)x->data;
 79:   Vec            Y;
 80:   Vec            *sub;
 81:   PetscInt       i;
 85:   PetscMalloc1(bx->nb,&sub);
 86:   for (i=0; i<bx->nb; i++) {
 87:     VecDuplicate(bx->v[i],&sub[i]);
 88:   }
 89:   VecCreateNest(PetscObjectComm((PetscObject)x),bx->nb,bx->is,sub,&Y);
 90:   for (i=0; i<bx->nb; i++) {
 91:     VecDestroy(&sub[i]);
 92:   }
 93:   PetscFree(sub);
 94:   *y   = Y;
 95:   return(0);
 96: }
 98: /* supports nested blocks */
 99: static PetscErrorCode VecDot_Nest(Vec x,Vec y,PetscScalar *val)
100: {
101:   Vec_Nest       *bx = (Vec_Nest*)x->data;
102:   Vec_Nest       *by = (Vec_Nest*)y->data;
103:   PetscInt       i,nr;
104:   PetscScalar    x_dot_y,_val;
108:   nr   = bx->nb;
109:   _val = 0.0;
110:   for (i=0; i<nr; i++) {
111:     VecDot(bx->v[i],by->v[i],&x_dot_y);
112:     _val = _val + x_dot_y;
113:   }
114:   *val = _val;
115:   return(0);
116: }
118: /* supports nested blocks */
119: static PetscErrorCode VecTDot_Nest(Vec x,Vec y,PetscScalar *val)
120: {
121:   Vec_Nest       *bx = (Vec_Nest*)x->data;
122:   Vec_Nest       *by = (Vec_Nest*)y->data;
123:   PetscInt       i,nr;
124:   PetscScalar    x_dot_y,_val;
128:   nr   = bx->nb;
129:   _val = 0.0;
130:   for (i=0; i<nr; i++) {
131:     VecTDot(bx->v[i],by->v[i],&x_dot_y);
132:     _val = _val + x_dot_y;
133:   }
134:   *val = _val;
135:   return(0);
136: }
138: static PetscErrorCode VecDotNorm2_Nest(Vec x,Vec y,PetscScalar *dp, PetscScalar *nm)
139: {
140:   Vec_Nest       *bx = (Vec_Nest*)x->data;
141:   Vec_Nest       *by = (Vec_Nest*)y->data;
142:   PetscInt       i,nr;
143:   PetscScalar    x_dot_y,_dp,_nm;
144:   PetscReal      norm2_y;
148:   nr  = bx->nb;
149:   _dp = 0.0;
150:   _nm = 0.0;
151:   for (i=0; i<nr; i++) {
152:     VecDotNorm2(bx->v[i],by->v[i],&x_dot_y,&norm2_y);
153:     _dp += x_dot_y;
154:     _nm += norm2_y;
155:   }
156:   *dp = _dp;
157:   *nm = _nm;
158:   return(0);
159: }
161: static PetscErrorCode VecAXPY_Nest(Vec y,PetscScalar alpha,Vec x)
162: {
163:   Vec_Nest       *bx = (Vec_Nest*)x->data;
164:   Vec_Nest       *by = (Vec_Nest*)y->data;
165:   PetscInt       i,nr;
169:   nr = bx->nb;
170:   for (i=0; i<nr; i++) {
171:     VecAXPY(by->v[i],alpha,bx->v[i]);
172:   }
173:   return(0);
174: }
176: static PetscErrorCode VecAYPX_Nest(Vec y,PetscScalar alpha,Vec x)
177: {
178:   Vec_Nest       *bx = (Vec_Nest*)x->data;
179:   Vec_Nest       *by = (Vec_Nest*)y->data;
180:   PetscInt       i,nr;
184:   nr = bx->nb;
185:   for (i=0; i<nr; i++) {
186:     VecAYPX(by->v[i],alpha,bx->v[i]);
187:   }
188:   return(0);
189: }
191: static PetscErrorCode VecAXPBY_Nest(Vec y,PetscScalar alpha,PetscScalar beta,Vec x)
192: {
193:   Vec_Nest       *bx = (Vec_Nest*)x->data;
194:   Vec_Nest       *by = (Vec_Nest*)y->data;
195:   PetscInt       i,nr;
199:   nr = bx->nb;
200:   for (i=0; i<nr; i++) {
201:     VecAXPBY(by->v[i],alpha,beta,bx->v[i]);
202:   }
203:   return(0);
204: }
206: static PetscErrorCode VecAXPBYPCZ_Nest(Vec z,PetscScalar alpha,PetscScalar beta,PetscScalar gamma,Vec x,Vec y)
207: {
208:   Vec_Nest       *bx = (Vec_Nest*)x->data;
209:   Vec_Nest       *by = (Vec_Nest*)y->data;
210:   Vec_Nest       *bz = (Vec_Nest*)z->data;
211:   PetscInt       i,nr;
215:   nr = bx->nb;
216:   for (i=0; i<nr; i++) {
217:     VecAXPBYPCZ(bz->v[i],alpha,beta,gamma,bx->v[i],by->v[i]);
218:   }
219:   return(0);
220: }
222: static PetscErrorCode VecScale_Nest(Vec x,PetscScalar alpha)
223: {
224:   Vec_Nest       *bx = (Vec_Nest*)x->data;
225:   PetscInt       i,nr;
229:   nr = bx->nb;
230:   for (i=0; i<nr; i++) {
231:     VecScale(bx->v[i],alpha);
232:   }
233:   return(0);
234: }
236: static PetscErrorCode VecPointwiseMult_Nest(Vec w,Vec x,Vec y)
237: {
238:   Vec_Nest       *bx = (Vec_Nest*)x->data;
239:   Vec_Nest       *by = (Vec_Nest*)y->data;
240:   Vec_Nest       *bw = (Vec_Nest*)w->data;
241:   PetscInt       i,nr;
245:   VecNestCheckCompatible3(w,1,x,3,y,4);
246:   nr = bx->nb;
247:   for (i=0; i<nr; i++) {
248:     VecPointwiseMult(bw->v[i],bx->v[i],by->v[i]);
249:   }
250:   return(0);
251: }
253: static PetscErrorCode VecPointwiseDivide_Nest(Vec w,Vec x,Vec y)
254: {
255:   Vec_Nest       *bx = (Vec_Nest*)x->data;
256:   Vec_Nest       *by = (Vec_Nest*)y->data;
257:   Vec_Nest       *bw = (Vec_Nest*)w->data;
258:   PetscInt       i,nr;
262:   VecNestCheckCompatible3(w,1,x,2,y,3);
264:   nr = bx->nb;
265:   for (i=0; i<nr; i++) {
266:     VecPointwiseDivide(bw->v[i],bx->v[i],by->v[i]);
267:   }
268:   return(0);
269: }
271: static PetscErrorCode VecReciprocal_Nest(Vec x)
272: {
273:   Vec_Nest       *bx = (Vec_Nest*)x->data;
274:   PetscInt       i,nr;
278:   nr = bx->nb;
279:   for (i=0; i<nr; i++) {
280:     VecReciprocal(bx->v[i]);
281:   }
282:   return(0);
283: }
285: static PetscErrorCode VecNorm_Nest(Vec xin,NormType type,PetscReal *z)
286: {
287:   Vec_Nest       *bx = (Vec_Nest*)xin->data;
288:   PetscInt       i,nr;
289:   PetscReal      z_i;
290:   PetscReal      _z;
294:   nr = bx->nb;
295:   _z = 0.0;
297:   if (type == NORM_2) {
298:     PetscScalar dot;
299:     VecDot(xin,xin,&dot);
300:     _z = PetscAbsScalar(PetscSqrtScalar(dot));
301:   } else if (type == NORM_1) {
302:     for (i=0; i<nr; i++) {
303:       VecNorm(bx->v[i],type,&z_i);
304:       _z = _z + z_i;
305:     }
306:   } else if (type == NORM_INFINITY) {
307:     for (i=0; i<nr; i++) {
308:       VecNorm(bx->v[i],type,&z_i);
309:       if (z_i > _z) _z = z_i;
310:     }
311:   }
313:   *z = _z;
314:   return(0);
315: }
317: static PetscErrorCode VecMAXPY_Nest(Vec y,PetscInt nv,const PetscScalar alpha[],Vec *x)
318: {
319:   PetscInt       v;
323:   for (v=0; v<nv; v++) {
324:     /* Do axpy on each vector,v */
325:     VecAXPY(y,alpha[v],x[v]);
326:   }
327:   return(0);
328: }
330: static PetscErrorCode VecMDot_Nest(Vec x,PetscInt nv,const Vec y[],PetscScalar *val)
331: {
332:   PetscInt       j;
336:   for (j=0; j<nv; j++) {
337:     VecDot(x,y[j],&val[j]);
338:   }
339:   return(0);
340: }
342: static PetscErrorCode VecMTDot_Nest(Vec x,PetscInt nv,const Vec y[],PetscScalar *val)
343: {
344:   PetscInt       j;
348:   for (j=0; j<nv; j++) {
349:     VecTDot(x,y[j],&val[j]);
350:   }
351:   return(0);
352: }
354: static PetscErrorCode VecSet_Nest(Vec x,PetscScalar alpha)
355: {
356:   Vec_Nest       *bx = (Vec_Nest*)x->data;
357:   PetscInt       i,nr;
361:   nr = bx->nb;
362:   for (i=0; i<nr; i++) {
363:     VecSet(bx->v[i],alpha);
364:   }
365:   return(0);
366: }
368: static PetscErrorCode VecConjugate_Nest(Vec x)
369: {
370:   Vec_Nest       *bx = (Vec_Nest*)x->data;
371:   PetscInt       j,nr;
375:   nr = bx->nb;
376:   for (j=0; j<nr; j++) {
377:     VecConjugate(bx->v[j]);
378:   }
379:   return(0);
380: }
382: static PetscErrorCode VecSwap_Nest(Vec x,Vec y)
383: {
384:   Vec_Nest       *bx = (Vec_Nest*)x->data;
385:   Vec_Nest       *by = (Vec_Nest*)y->data;
386:   PetscInt       i,nr;
390:   VecNestCheckCompatible2(x,1,y,2);
391:   nr = bx->nb;
392:   for (i=0; i<nr; i++) {
393:     VecSwap(bx->v[i],by->v[i]);
394:   }
395:   return(0);
396: }
398: static PetscErrorCode VecWAXPY_Nest(Vec w,PetscScalar alpha,Vec x,Vec y)
399: {
400:   Vec_Nest       *bx = (Vec_Nest*)x->data;
401:   Vec_Nest       *by = (Vec_Nest*)y->data;
402:   Vec_Nest       *bw = (Vec_Nest*)w->data;
403:   PetscInt       i,nr;
407:   VecNestCheckCompatible3(w,1,x,3,y,4);
409:   nr = bx->nb;
410:   for (i=0; i<nr; i++) {
411:     VecWAXPY(bw->v[i],alpha,bx->v[i],by->v[i]);
412:   }
413:   return(0);
414: }
416: static PetscErrorCode VecMax_Nest_Recursive(Vec x,PetscInt *cnt,PetscInt *p,PetscReal *max)
417: {
418:   Vec_Nest       *bx;
419:   PetscInt       i,nr;
420:   PetscBool      isnest;
421:   PetscInt       L;
422:   PetscInt       _entry_loc;
423:   PetscReal      _entry_val;
427:   PetscObjectTypeCompare((PetscObject)x,VECNEST,&isnest);
428:   if (!isnest) {
429:     /* Not nest */
430:     VecMax(x,&_entry_loc,&_entry_val);
431:     if (_entry_val > *max) {
432:       *max = _entry_val;
433:       if (p) *p = _entry_loc + *cnt;
434:     }
435:     VecGetSize(x,&L);
436:     *cnt = *cnt + L;
437:     return(0);
438:   }
440:   /* Otherwise we have a nest */
441:   bx = (Vec_Nest*)x->data;
442:   nr = bx->nb;
444:   /* now descend recursively */
445:   for (i=0; i<nr; i++) {
446:     VecMax_Nest_Recursive(bx->v[i],cnt,p,max);
447:   }
448:   return(0);
449: }
451: /* supports nested blocks */
452: static PetscErrorCode VecMax_Nest(Vec x,PetscInt *p,PetscReal *max)
453: {
454:   PetscInt       cnt;
458:   cnt  = 0;
459:   if (p) *p = 0;
460:   *max = PETSC_MIN_REAL;
461:   VecMax_Nest_Recursive(x,&cnt,p,max);
462:   return(0);
463: }
465: static PetscErrorCode VecMin_Nest_Recursive(Vec x,PetscInt *cnt,PetscInt *p,PetscReal *min)
466: {
467:   Vec_Nest       *bx = (Vec_Nest*)x->data;
468:   PetscInt       i,nr,L,_entry_loc;
469:   PetscBool      isnest;
470:   PetscReal      _entry_val;
474:   PetscObjectTypeCompare((PetscObject)x,VECNEST,&isnest);
475:   if (!isnest) {
476:     /* Not nest */
477:     VecMin(x,&_entry_loc,&_entry_val);
478:     if (_entry_val < *min) {
479:       *min = _entry_val;
480:       if (p) *p = _entry_loc + *cnt;
481:     }
482:     VecGetSize(x,&L);
483:     *cnt = *cnt + L;
484:     return(0);
485:   }
487:   /* Otherwise we have a nest */
488:   nr = bx->nb;
490:   /* now descend recursively */
491:   for (i=0; i<nr; i++) {
492:     VecMin_Nest_Recursive(bx->v[i],cnt,p,min);
493:   }
494:   return(0);
495: }
497: static PetscErrorCode VecMin_Nest(Vec x,PetscInt *p,PetscReal *min)
498: {
499:   PetscInt       cnt;
503:   cnt  = 0;
504:   if (p) *p = 0;
505:   *min = PETSC_MAX_REAL;
506:   VecMin_Nest_Recursive(x,&cnt,p,min);
507:   return(0);
508: }
510: /* supports nested blocks */
511: static PetscErrorCode VecView_Nest(Vec x,PetscViewer viewer)
512: {
513:   Vec_Nest       *bx = (Vec_Nest*)x->data;
514:   PetscBool      isascii;
515:   PetscInt       i;
519:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
520:   if (isascii) {
521:     PetscViewerASCIIPushTab(viewer);
522:     PetscViewerASCIIPrintf(viewer,"VecNest, rows=%D,  structure: \n",bx->nb);
523:     for (i=0; i<bx->nb; i++) {
524:       VecType  type;
525:       char     name[256] = "",prefix[256] = "";
526:       PetscInt NR;
528:       VecGetSize(bx->v[i],&NR);
529:       VecGetType(bx->v[i],&type);
530:       if (((PetscObject)bx->v[i])->name) {PetscSNPrintf(name,sizeof(name),"name=\"%s\", ",((PetscObject)bx->v[i])->name);}
531:       if (((PetscObject)bx->v[i])->prefix) {PetscSNPrintf(prefix,sizeof(prefix),"prefix=\"%s\", ",((PetscObject)bx->v[i])->prefix);}
533:       PetscViewerASCIIPrintf(viewer,"(%D) : %s%stype=%s, rows=%D \n",i,name,prefix,type,NR);
535:       PetscViewerASCIIPushTab(viewer);             /* push1 */
536:       VecView(bx->v[i],viewer);
537:       PetscViewerASCIIPopTab(viewer);              /* pop1 */
538:     }
539:     PetscViewerASCIIPopTab(viewer);                /* pop0 */
540:   }
541:   return(0);
542: }
544: static PetscErrorCode VecSize_Nest_Recursive(Vec x,PetscBool globalsize,PetscInt *L)
545: {
546:   Vec_Nest       *bx;
547:   PetscInt       size,i,nr;
548:   PetscBool      isnest;
552:   PetscObjectTypeCompare((PetscObject)x,VECNEST,&isnest);
553:   if (!isnest) {
554:     /* Not nest */
555:     if (globalsize) { VecGetSize(x,&size); }
556:     else {            VecGetLocalSize(x,&size); }
557:     *L = *L + size;
558:     return(0);
559:   }
561:   /* Otherwise we have a nest */
562:   bx = (Vec_Nest*)x->data;
563:   nr = bx->nb;
565:   /* now descend recursively */
566:   for (i=0; i<nr; i++) {
567:     VecSize_Nest_Recursive(bx->v[i],globalsize,L);
568:   }
569:   return(0);
570: }
572: /* Returns the sum of the global size of all the consituent vectors in the nest */
573: static PetscErrorCode VecGetSize_Nest(Vec x,PetscInt *N)
574: {
576:   *N = x->map->N;
577:   return(0);
578: }
580: /* Returns the sum of the local size of all the consituent vectors in the nest */
581: static PetscErrorCode VecGetLocalSize_Nest(Vec x,PetscInt *n)
582: {
584:   *n = x->map->n;
585:   return(0);
586: }
588: static PetscErrorCode VecMaxPointwiseDivide_Nest(Vec x,Vec y,PetscReal *max)
589: {
590:   Vec_Nest       *bx = (Vec_Nest*)x->data;
591:   Vec_Nest       *by = (Vec_Nest*)y->data;
592:   PetscInt       i,nr;
593:   PetscReal      local_max,m;
597:   VecNestCheckCompatible2(x,1,y,2);
598:   nr = bx->nb;
599:   m  = 0.0;
600:   for (i=0; i<nr; i++) {
601:     VecMaxPointwiseDivide(bx->v[i],by->v[i],&local_max);
602:     if (local_max > m) m = local_max;
603:   }
604:   *max = m;
605:   return(0);
606: }
608: static PetscErrorCode  VecGetSubVector_Nest(Vec X,IS is,Vec *x)
609: {
610:   Vec_Nest       *bx = (Vec_Nest*)X->data;
611:   PetscInt       i;
615:   *x = NULL;
616:   for (i=0; i<bx->nb; i++) {
617:     PetscBool issame = PETSC_FALSE;
618:     ISEqual(is,bx->is[i],&issame);
619:     if (issame) {
620:       *x   = bx->v[i];
621:       PetscObjectReference((PetscObject)(*x));
622:       break;
623:     }
624:   }
625:   if (!*x) SETERRQ(PetscObjectComm((PetscObject)is),PETSC_ERR_ARG_OUTOFRANGE,"Index set not found in nested Vec");
626:   return(0);
627: }
629: static PetscErrorCode  VecRestoreSubVector_Nest(Vec X,IS is,Vec *x)
630: {
634:   VecDestroy(x);
635:   return(0);
636: }
638: static PetscErrorCode VecGetArray_Nest(Vec X,PetscScalar **x)
639: {
640:   Vec_Nest       *bx = (Vec_Nest*)X->data;
641:   PetscInt       i,m,rstart,rend;
645:   VecGetOwnershipRange(X,&rstart,&rend);
646:   VecGetLocalSize(X,&m);
647:   PetscMalloc1(m,x);
648:   for (i=0; i<bx->nb; i++) {
649:     Vec               subvec = bx->v[i];
650:     IS                isy    = bx->is[i];
651:     PetscInt          j,sm;
652:     const PetscInt    *ixy;
653:     const PetscScalar *y;
654:     VecGetLocalSize(subvec,&sm);
655:     VecGetArrayRead(subvec,&y);
656:     ISGetIndices(isy,&ixy);
657:     for (j=0; j<sm; j++) {
658:       PetscInt ix = ixy[j];
659:       if (ix < rstart || rend <= ix) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for getting array from nonlocal subvec");
660:       (*x)[ix-rstart] = y[j];
661:     }
662:     ISRestoreIndices(isy,&ixy);
663:     VecRestoreArrayRead(subvec,&y);
664:   }
665:   return(0);
666: }
668: static PetscErrorCode VecRestoreArray_Nest(Vec X,PetscScalar **x)
669: {
670:   Vec_Nest       *bx = (Vec_Nest*)X->data;
671:   PetscInt       i,m,rstart,rend;
675:   VecGetOwnershipRange(X,&rstart,&rend);
676:   VecGetLocalSize(X,&m);
677:   for (i=0; i<bx->nb; i++) {
678:     Vec            subvec = bx->v[i];
679:     IS             isy    = bx->is[i];
680:     PetscInt       j,sm;
681:     const PetscInt *ixy;
682:     PetscScalar    *y;
683:     VecGetLocalSize(subvec,&sm);
684:     VecGetArray(subvec,&y);
685:     ISGetIndices(isy,&ixy);
686:     for (j=0; j<sm; j++) {
687:       PetscInt ix = ixy[j];
688:       if (ix < rstart || rend <= ix) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for getting array from nonlocal subvec");
689:       y[j] = (*x)[ix-rstart];
690:     }
691:     ISRestoreIndices(isy,&ixy);
692:     VecRestoreArray(subvec,&y);
693:   }
694:   PetscFree(*x);
695:   return(0);
696: }
698: static PetscErrorCode VecRestoreArrayRead_Nest(Vec X,const PetscScalar **x)
699: {
703:   PetscFree(*x);
704:   return(0);
705: }
707: static PetscErrorCode VecConcatenate_Nest(PetscInt nx, const Vec X[], Vec *Y, IS *x_is[])
708: {
710:   SETERRQ(PetscObjectComm((PetscObject)(*X)), PETSC_ERR_SUP, "VecConcatenate() is not supported for VecNest");
711: }
713: static PetscErrorCode VecNestSetOps_Private(struct _VecOps *ops)
714: {
716:   ops->duplicate               = VecDuplicate_Nest;
717:   ops->duplicatevecs           = VecDuplicateVecs_Default;
718:   ops->destroyvecs             = VecDestroyVecs_Default;
719:   ops->dot                     = VecDot_Nest;
720:   ops->mdot                    = VecMDot_Nest;
721:   ops->norm                    = VecNorm_Nest;
722:   ops->tdot                    = VecTDot_Nest;
723:   ops->mtdot                   = VecMTDot_Nest;
724:   ops->scale                   = VecScale_Nest;
725:   ops->copy                    = VecCopy_Nest;
726:   ops->set                     = VecSet_Nest;
727:   ops->swap                    = VecSwap_Nest;
728:   ops->axpy                    = VecAXPY_Nest;
729:   ops->axpby                   = VecAXPBY_Nest;
730:   ops->maxpy                   = VecMAXPY_Nest;
731:   ops->aypx                    = VecAYPX_Nest;
732:   ops->waxpy                   = VecWAXPY_Nest;
733:   ops->axpbypcz                = NULL;
734:   ops->pointwisemult           = VecPointwiseMult_Nest;
735:   ops->pointwisedivide         = VecPointwiseDivide_Nest;
736:   ops->setvalues               = NULL;
737:   ops->assemblybegin           = VecAssemblyBegin_Nest;
738:   ops->assemblyend             = VecAssemblyEnd_Nest;
739:   ops->getarray                = VecGetArray_Nest;
740:   ops->getsize                 = VecGetSize_Nest;
741:   ops->getlocalsize            = VecGetLocalSize_Nest;
742:   ops->restorearray            = VecRestoreArray_Nest;
743:   ops->restorearrayread        = VecRestoreArrayRead_Nest;
744:   ops->max                     = VecMax_Nest;
745:   ops->min                     = VecMin_Nest;
746:   ops->setrandom               = NULL;
747:   ops->setoption               = NULL;
748:   ops->setvaluesblocked        = NULL;
749:   ops->destroy                 = VecDestroy_Nest;
750:   ops->view                    = VecView_Nest;
751:   ops->placearray              = NULL;
752:   ops->replacearray            = NULL;
753:   ops->dot_local               = VecDot_Nest;
754:   ops->tdot_local              = VecTDot_Nest;
755:   ops->norm_local              = VecNorm_Nest;
756:   ops->mdot_local              = VecMDot_Nest;
757:   ops->mtdot_local             = VecMTDot_Nest;
758:   ops->load                    = NULL;
759:   ops->reciprocal              = VecReciprocal_Nest;
760:   ops->conjugate               = VecConjugate_Nest;
761:   ops->setlocaltoglobalmapping = NULL;
762:   ops->setvalueslocal          = NULL;
763:   ops->resetarray              = NULL;
764:   ops->setfromoptions          = NULL;
765:   ops->maxpointwisedivide      = VecMaxPointwiseDivide_Nest;
766:   ops->load                    = NULL;
767:   ops->pointwisemax            = NULL;
768:   ops->pointwisemaxabs         = NULL;
769:   ops->pointwisemin            = NULL;
770:   ops->getvalues               = NULL;
771:   ops->sqrt                    = NULL;
772:   ops->abs                     = NULL;
773:   ops->exp                     = NULL;
774:   ops->shift                   = NULL;
775:   ops->create                  = NULL;
776:   ops->stridegather            = NULL;
777:   ops->stridescatter           = NULL;
778:   ops->dotnorm2                = VecDotNorm2_Nest;
779:   ops->getsubvector            = VecGetSubVector_Nest;
780:   ops->restoresubvector        = VecRestoreSubVector_Nest;
781:   ops->axpbypcz                = VecAXPBYPCZ_Nest;
782:   ops->concatenate             = VecConcatenate_Nest;
783:   return(0);
784: }
786: static PetscErrorCode VecNestGetSubVecs_Private(Vec x,PetscInt m,const PetscInt idxm[],Vec vec[])
787: {
788:   Vec_Nest *b = (Vec_Nest*)x->data;
789:   PetscInt i;
790:   PetscInt row;
793:   if (!m) return(0);
794:   for (i=0; i<m; i++) {
795:     row = idxm[i];
796:     if (row >= b->nb) SETERRQ2(PetscObjectComm((PetscObject)x),PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,b->nb-1);
797:     vec[i] = b->v[row];
798:   }
799:   return(0);
800: }
802: PetscErrorCode  VecNestGetSubVec_Nest(Vec X,PetscInt idxm,Vec *sx)
803: {
807:   VecNestGetSubVecs_Private(X,1,&idxm,sx);
808:   return(0);
809: }
811: /*@
812:  VecNestGetSubVec - Returns a single, sub-vector from a nest vector.
814:  Not collective
816:  Input Parameters:
817: +  X  - nest vector
818: -  idxm - index of the vector within the nest
820:  Output Parameter:
821: .  sx - vector at index idxm within the nest
823:  Notes:
825:  Level: developer
827: .seealso: VecNestGetSize(), VecNestGetSubVecs()
828: @*/
829: PetscErrorCode  VecNestGetSubVec(Vec X,PetscInt idxm,Vec *sx)
830: {
834:   PetscUseMethod(X,"VecNestGetSubVec_C",(Vec,PetscInt,Vec*),(X,idxm,sx));
835:   return(0);
836: }
838: PetscErrorCode  VecNestGetSubVecs_Nest(Vec X,PetscInt *N,Vec **sx)
839: {
840:   Vec_Nest *b = (Vec_Nest*)X->data;
843:   if (N)  *N  = b->nb;
844:   if (sx) *sx = b->v;
845:   return(0);
846: }
848: /*@C
849:  VecNestGetSubVecs - Returns the entire array of vectors defining a nest vector.
851:  Not collective
853:  Input Parameter:
854: .  X  - nest vector
856:  Output Parameters:
857: +  N - number of nested vecs
858: -  sx - array of vectors
860:  Notes:
861:  The user should not free the array sx.
863:  Fortran Notes:
864:  The caller must allocate the array to hold the subvectors.
866:  Level: developer
868: .seealso: VecNestGetSize(), VecNestGetSubVec()
869: @*/
870: PetscErrorCode  VecNestGetSubVecs(Vec X,PetscInt *N,Vec **sx)
871: {
875:   PetscUseMethod(X,"VecNestGetSubVecs_C",(Vec,PetscInt*,Vec**),(X,N,sx));
876:   return(0);
877: }
879: static PetscErrorCode  VecNestSetSubVec_Private(Vec X,PetscInt idxm,Vec x)
880: {
881:   Vec_Nest       *bx = (Vec_Nest*)X->data;
882:   PetscInt       i,offset=0,n=0,bs;
883:   IS             is;
885:   PetscBool      issame = PETSC_FALSE;
886:   PetscInt       N=0;
888:   /* check if idxm < bx->nb */
889:   if (idxm >= bx->nb) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Out of range index value %D maximum %D",idxm,bx->nb);
892:   VecDestroy(&bx->v[idxm]);       /* destroy the existing vector */
893:   VecDuplicate(x,&bx->v[idxm]);   /* duplicate the layout of given vector */
894:   VecCopy(x,bx->v[idxm]);         /* copy the contents of the given vector */
896:   /* check if we need to update the IS for the block */
897:   offset = X->map->rstart;
898:   for (i=0; i<idxm; i++) {
899:     n=0;
900:     VecGetLocalSize(bx->v[i],&n);
901:     offset += n;
902:   }
904:   /* get the local size and block size */
905:   VecGetLocalSize(x,&n);
906:   VecGetBlockSize(x,&bs);
908:   /* create the new IS */
909:   ISCreateStride(PetscObjectComm((PetscObject)x),n,offset,1,&is);
910:   ISSetBlockSize(is,bs);
912:   /* check if they are equal */
913:   ISEqual(is,bx->is[idxm],&issame);
915:   if (!issame) {
916:     /* The IS of given vector has a different layout compared to the existing block vector.
917:      Destroy the existing reference and update the IS. */
918:     ISDestroy(&bx->is[idxm]);
919:     ISDuplicate(is,&bx->is[idxm]);
920:     ISCopy(is,bx->is[idxm]);
922:     offset += n;
923:     /* Since the current IS[idxm] changed, we need to update all the subsequent IS */
924:     for (i=idxm+1; i<bx->nb; i++) {
925:       /* get the local size and block size */
926:       VecGetLocalSize(bx->v[i],&n);
927:       VecGetBlockSize(bx->v[i],&bs);
929:       /* destroy the old and create the new IS */
930:       ISDestroy(&bx->is[i]);
931:       ISCreateStride(((PetscObject)bx->v[i])->comm,n,offset,1,&bx->is[i]);
932:       ISSetBlockSize(bx->is[i],bs);
934:       offset += n;
935:     }
937:     n=0;
938:     VecSize_Nest_Recursive(X,PETSC_TRUE,&N);
939:     VecSize_Nest_Recursive(X,PETSC_FALSE,&n);
940:     PetscLayoutSetSize(X->map,N);
941:     PetscLayoutSetLocalSize(X->map,n);
942:   }
944:   ISDestroy(&is);
945:   return(0);
946: }
948: PetscErrorCode  VecNestSetSubVec_Nest(Vec X,PetscInt idxm,Vec sx)
949: {
953:   VecNestSetSubVec_Private(X,idxm,sx);
954:   return(0);
955: }
957: /*@
958:    VecNestSetSubVec - Set a single component vector in a nest vector at specified index.
960:    Not collective
962:    Input Parameters:
963: +  X  - nest vector
964: .  idxm - index of the vector within the nest vector
965: -  sx - vector at index idxm within the nest vector
967:    Notes:
968:    The new vector sx does not have to be of same size as X[idxm]. Arbitrary vector layouts are allowed.
970:    Level: developer
972: .seealso: VecNestSetSubVecs(), VecNestGetSubVec()
973: @*/
974: PetscErrorCode  VecNestSetSubVec(Vec X,PetscInt idxm,Vec sx)
975: {
979:   PetscUseMethod(X,"VecNestSetSubVec_C",(Vec,PetscInt,Vec),(X,idxm,sx));
980:   return(0);
981: }
983: PetscErrorCode  VecNestSetSubVecs_Nest(Vec X,PetscInt N,PetscInt *idxm,Vec *sx)
984: {
985:   PetscInt       i;
989:   for (i=0; i<N; i++) {
990:     VecNestSetSubVec_Private(X,idxm[i],sx[i]);
991:   }
992:   return(0);
993: }
995: /*@C
996:    VecNestSetSubVecs - Sets the component vectors at the specified indices in a nest vector.
998:    Not collective
1000:    Input Parameters:
1001: +  X  - nest vector
1002: .  N - number of component vecs in sx
1003: .  idxm - indices of component vecs that are to be replaced
1004: -  sx - array of vectors
1006:    Notes:
1007:    The components in the vector array sx do not have to be of the same size as corresponding
1008:    components in X. The user can also free the array "sx" after the call.
1010:    Level: developer
1012: .seealso: VecNestGetSize(), VecNestGetSubVec()
1013: @*/
1014: PetscErrorCode  VecNestSetSubVecs(Vec X,PetscInt N,PetscInt *idxm,Vec *sx)
1015: {
1019:   PetscUseMethod(X,"VecNestSetSubVecs_C",(Vec,PetscInt,PetscInt*,Vec*),(X,N,idxm,sx));
1020:   return(0);
1021: }
1023: PetscErrorCode  VecNestGetSize_Nest(Vec X,PetscInt *N)
1024: {
1025:   Vec_Nest *b = (Vec_Nest*)X->data;
1028:   *N = b->nb;
1029:   return(0);
1030: }
1032: /*@
1033:  VecNestGetSize - Returns the size of the nest vector.
1035:  Not collective
1037:  Input Parameter:
1038: .  X  - nest vector
1040:  Output Parameter:
1041: .  N - number of nested vecs
1043:  Notes:
1045:  Level: developer
1047: .seealso: VecNestGetSubVec(), VecNestGetSubVecs()
1048: @*/
1049: PetscErrorCode  VecNestGetSize(Vec X,PetscInt *N)
1050: {
1056:   PetscUseMethod(X,"VecNestGetSize_C",(Vec,PetscInt*),(X,N));
1057:   return(0);
1058: }
1060: static PetscErrorCode VecSetUp_Nest_Private(Vec V,PetscInt nb,Vec x[])
1061: {
1062:   Vec_Nest       *ctx = (Vec_Nest*)V->data;
1063:   PetscInt       i;
1067:   if (ctx->setup_called) return(0);
1069:   ctx->nb = nb;
1070:   if (ctx->nb < 0) SETERRQ(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_WRONG,"Cannot create VECNEST with < 0 blocks.");
1072:   /* Create space */
1073:   PetscMalloc1(ctx->nb,&ctx->v);
1074:   for (i=0; i<ctx->nb; i++) {
1075:     ctx->v[i] = x[i];
1076:     PetscObjectReference((PetscObject)x[i]);
1077:     /* Do not allocate memory for internal sub blocks */
1078:   }
1080:   PetscMalloc1(ctx->nb,&ctx->is);
1082:   ctx->setup_called = PETSC_TRUE;
1083:   return(0);
1084: }
1086: static PetscErrorCode VecSetUp_NestIS_Private(Vec V,PetscInt nb,IS is[])
1087: {
1088:   Vec_Nest       *ctx = (Vec_Nest*)V->data;
1089:   PetscInt       i,offset,m,n,M,N;
1093:   if (is) {                     /* Do some consistency checks and reference the is */
1094:     offset = V->map->rstart;
1095:     for (i=0; i<ctx->nb; i++) {
1096:       ISGetSize(is[i],&M);
1097:       VecGetSize(ctx->v[i],&N);
1098:       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);
1099:       ISGetLocalSize(is[i],&m);
1100:       VecGetLocalSize(ctx->v[i],&n);
1101:       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);
1102:       if (PetscDefined(USE_DEBUG)) { /* This test can be expensive */
1103:         PetscInt  start;
1104:         PetscBool contiguous;
1105:         ISContiguousLocal(is[i],offset,offset+n,&start,&contiguous);
1106:         if (!contiguous) SETERRQ1(PetscObjectComm((PetscObject)V),PETSC_ERR_SUP,"Index set %D is not contiguous with layout of matching vector",i);
1107:         if (start != 0) SETERRQ1(PetscObjectComm((PetscObject)V),PETSC_ERR_SUP,"Index set %D introduces overlap or a hole",i);
1108:       }
1109:       PetscObjectReference((PetscObject)is[i]);
1110:       ctx->is[i] = is[i];
1111:       offset += n;
1112:     }
1113:   } else {                      /* Create a contiguous ISStride for each entry */
1114:     offset = V->map->rstart;
1115:     for (i=0; i<ctx->nb; i++) {
1116:       PetscInt bs;
1117:       VecGetLocalSize(ctx->v[i],&n);
1118:       VecGetBlockSize(ctx->v[i],&bs);
1119:       ISCreateStride(((PetscObject)ctx->v[i])->comm,n,offset,1,&ctx->is[i]);
1120:       ISSetBlockSize(ctx->is[i],bs);
1121:       offset += n;
1122:     }
1123:   }
1124:   return(0);
1125: }
1127: /*@C
1128:    VecCreateNest - Creates a new vector containing several nested subvectors, each stored separately
1130:    Collective on Vec
1132:    Input Parameters:
1133: +  comm - Communicator for the new Vec
1134: .  nb - number of nested blocks
1135: .  is - array of nb index sets describing each nested block, or NULL to pack subvectors contiguously
1136: -  x - array of nb sub-vectors
1138:    Output Parameter:
1139: .  Y - new vector
1141:    Level: advanced
1143: .seealso: VecCreate(), MatCreateNest(), DMSetVecType(), VECNEST
1144: @*/
1145: PetscErrorCode  VecCreateNest(MPI_Comm comm,PetscInt nb,IS is[],Vec x[],Vec *Y)
1146: {
1147:   Vec            V;
1148:   Vec_Nest       *s;
1149:   PetscInt       n,N;
1153:   VecCreate(comm,&V);
1154:   PetscObjectChangeTypeName((PetscObject)V,VECNEST);
1156:   /* allocate and set pointer for implememtation data */
1157:   PetscNew(&s);
1158:   V->data          = (void*)s;
1159:   s->setup_called  = PETSC_FALSE;
1160:   s->nb            = -1;
1161:   s->v             = NULL;
1163:   VecSetUp_Nest_Private(V,nb,x);
1165:   n = N = 0;
1166:   VecSize_Nest_Recursive(V,PETSC_TRUE,&N);
1167:   VecSize_Nest_Recursive(V,PETSC_FALSE,&n);
1168:   PetscLayoutSetSize(V->map,N);
1169:   PetscLayoutSetLocalSize(V->map,n);
1170:   PetscLayoutSetBlockSize(V->map,1);
1171:   PetscLayoutSetUp(V->map);
1173:   VecSetUp_NestIS_Private(V,nb,is);
1175:   VecNestSetOps_Private(V->ops);
1176:   V->petscnative = PETSC_FALSE;
1179:   /* expose block api's */
1180:   PetscObjectComposeFunction((PetscObject)V,"VecNestGetSubVec_C",VecNestGetSubVec_Nest);
1181:   PetscObjectComposeFunction((PetscObject)V,"VecNestGetSubVecs_C",VecNestGetSubVecs_Nest);
1182:   PetscObjectComposeFunction((PetscObject)V,"VecNestSetSubVec_C",VecNestSetSubVec_Nest);
1183:   PetscObjectComposeFunction((PetscObject)V,"VecNestSetSubVecs_C",VecNestSetSubVecs_Nest);
1184:   PetscObjectComposeFunction((PetscObject)V,"VecNestGetSize_C",VecNestGetSize_Nest);
1186:   *Y = V;
1187:   return(0);
1188: }
1190: /*MC
1191:   VECNEST - VECNEST = "nest" - Vector type consisting of nested subvectors, each stored separately.
1193:   Level: intermediate
1195:   Notes:
1196:   This vector type reduces the number of copies for certain solvers applied to multi-physics problems.
1197:   It is usually used with MATNEST and DMComposite via DMSetVecType().
1199: .seealso: VecCreate(), VecType, VecCreateNest(), MatCreateNest()
1200: M*/