Actual source code: pack.c

  1: #define PETSCDM_DLL
  2: 
 3:  #include petscda.h
 4:  #include petscmat.h

  6: /*
  7:    rstart is where an array/subvector starts in the global parallel vector, so arrays
  8:    rstarts are meaningless (and set to the previous one) except on processor 0
  9: */

 11: typedef enum {VECPACK_ARRAY, VECPACK_DA, VECPACK_VECSCATTER} VecPackLinkType;

 13: struct VecPackLink {
 14:   DA                 da;
 15:   PetscInt           n,rstart;      /* rstart is relative to this processor */
 16:   VecPackLinkType    type;
 17:   struct VecPackLink *next;
 18: };

 20: typedef struct _VecPackOps *VecPackOps;
 21: struct _VecPackOps {
 22:   PetscErrorCode (*view)(VecPack,PetscViewer);
 23:   PetscErrorCode (*createglobalvector)(VecPack,Vec*);
 24:   PetscErrorCode (*getcoloring)(VecPack,ISColoringType,ISColoring*);
 25:   PetscErrorCode (*getmatrix)(VecPack,MatType,Mat*);
 26:   PetscErrorCode (*getinterpolation)(VecPack,VecPack,Mat*,Vec*);
 27:   PetscErrorCode (*refine)(VecPack,MPI_Comm,VecPack*);
 28: };

 30: struct _p_VecPack {
 31:   PETSCHEADER(struct _VecPackOps);
 32:   PetscMPIInt        rank;
 33:   PetscInt           n,N,rstart;   /* rstart is relative to all processors */
 34:   Vec                globalvector;
 35:   PetscInt           nDA,nredundant;
 36:   struct VecPackLink *next;
 37: };

 41: /*@C
 42:     VecPackCreate - Creates a vector packer, used to generate "composite"
 43:       vectors made up of several subvectors.

 45:     Collective on MPI_Comm

 47:     Input Parameter:
 48: .   comm - the processors that will share the global vector

 50:     Output Parameters:
 51: .   packer - the packer object

 53:     Level: advanced

 55: .seealso VecPackDestroy(), VecPackAddArray(), VecPackAddDA(), VecPackScatter(),
 56:          VecPackGather(), VecPackCreateGlobalVector(), VecPackGetGlobalIndices(), VecPackGetAccess()
 57:          VecPackGetLocalVectors(), VecPackRestoreLocalVectors()

 59: @*/
 60: PetscErrorCode PETSCDM_DLLEXPORT VecPackCreate(MPI_Comm comm,VecPack *packer)
 61: {
 63:   VecPack        p;

 67:   *packer = PETSC_NULL;
 68: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
 69:   DMInitializePackage(PETSC_NULL);
 70: #endif

 72:   PetscHeaderCreate(p,_p_VecPack,struct _VecPackOps,DA_COOKIE,0,"VecPack",comm,VecPackDestroy,0);
 73:   p->n            = 0;
 74:   p->next         = PETSC_NULL;
 75:   p->comm         = comm;
 76:   p->globalvector = PETSC_NULL;
 77:   p->nredundant   = 0;
 78:   p->nDA          = 0;
 79:   MPI_Comm_rank(comm,&p->rank);

 81:   p->ops->createglobalvector = VecPackCreateGlobalVector;
 82:   p->ops->refine             = VecPackRefine;
 83:   p->ops->getinterpolation   = VecPackGetInterpolation;
 84:   *packer = p;
 85:   return(0);
 86: }

 90: /*@C
 91:     VecPackDestroy - Destroys a vector packer.

 93:     Collective on VecPack

 95:     Input Parameter:
 96: .   packer - the packer object

 98:     Level: advanced

100: .seealso VecPackCreate(), VecPackAddArray(), VecPackAddDA(), VecPackScatter(),
101:          VecPackGather(), VecPackCreateGlobalVector(), VecPackGetGlobalIndices(), VecPackGetAccess()

103: @*/
104: PetscErrorCode PETSCDM_DLLEXPORT VecPackDestroy(VecPack packer)
105: {
106:   PetscErrorCode     ierr;
107:   struct VecPackLink *next = packer->next,*prev;

110:   if (--packer->refct > 0) return(0);
111:   while (next) {
112:     prev = next;
113:     next = next->next;
114:     if (prev->type == VECPACK_DA) {
115:       DADestroy(prev->da);
116:     }
117:     PetscFree(prev);
118:   }
119:   if (packer->globalvector) {
120:     VecDestroy(packer->globalvector);
121:   }
122:   PetscHeaderDestroy(packer);
123:   return(0);
124: }

126: /* --------------------------------------------------------------------------------------*/

130: PetscErrorCode VecPackGetAccess_Array(VecPack packer,struct VecPackLink *mine,Vec vec,PetscScalar **array)
131: {
133:   PetscScalar    *varray;

136:   if (array) {
137:     if (!packer->rank) {
138:       VecGetArray(vec,&varray);
139:       *array  = varray + mine->rstart;
140:       VecRestoreArray(vec,&varray);
141:     } else {
142:       *array = 0;
143:     }
144:   }
145:   return(0);
146: }

150: PetscErrorCode VecPackGetAccess_DA(VecPack packer,struct VecPackLink *mine,Vec vec,Vec *global)
151: {
153:   PetscScalar    *array;

156:   if (global) {
157:     DAGetGlobalVector(mine->da,global);
158:     VecGetArray(vec,&array);
159:     VecPlaceArray(*global,array+mine->rstart);
160:     VecRestoreArray(vec,&array);
161:   }
162:   return(0);
163: }

167: PetscErrorCode VecPackRestoreAccess_Array(VecPack packer,struct VecPackLink *mine,Vec vec,PetscScalar **array)
168: {
170:   return(0);
171: }

175: PetscErrorCode VecPackRestoreAccess_DA(VecPack packer,struct VecPackLink *mine,Vec vec,Vec *global)
176: {

180:   if (global) {
181:     VecResetArray(*global);
182:     DARestoreGlobalVector(mine->da,global);
183:   }
184:   return(0);
185: }

189: PetscErrorCode VecPackScatter_Array(VecPack packer,struct VecPackLink *mine,Vec vec,PetscScalar *array)
190: {
192:   PetscScalar    *varray;


196:   if (!packer->rank) {
197:     VecGetArray(vec,&varray);
198:     PetscMemcpy(array,varray+mine->rstart,mine->n*sizeof(PetscScalar));
199:     VecRestoreArray(vec,&varray);
200:   }
201:   MPI_Bcast(array,mine->n,MPIU_SCALAR,0,packer->comm);
202:   return(0);
203: }

207: PetscErrorCode VecPackScatter_DA(VecPack packer,struct VecPackLink *mine,Vec vec,Vec local)
208: {
210:   PetscScalar    *array;
211:   Vec            global;

214:   DAGetGlobalVector(mine->da,&global);
215:   VecGetArray(vec,&array);
216:   VecPlaceArray(global,array+mine->rstart);
217:   DAGlobalToLocalBegin(mine->da,global,INSERT_VALUES,local);
218:   DAGlobalToLocalEnd(mine->da,global,INSERT_VALUES,local);
219:   VecRestoreArray(vec,&array);
220:   VecResetArray(global);
221:   DARestoreGlobalVector(mine->da,&global);
222:   return(0);
223: }

227: PetscErrorCode VecPackGather_Array(VecPack packer,struct VecPackLink *mine,Vec vec,PetscScalar *array)
228: {
230:   PetscScalar    *varray;

233:   if (!packer->rank) {
234:     VecGetArray(vec,&varray);
235:     if (varray+mine->rstart == array) SETERRQ(PETSC_ERR_ARG_WRONG,"You need not VecPackGather() into objects obtained via VecPackGetAccess()");
236:     PetscMemcpy(varray+mine->rstart,array,mine->n*sizeof(PetscScalar));
237:     VecRestoreArray(vec,&varray);
238:   }
239:   return(0);
240: }

244: PetscErrorCode VecPackGather_DA(VecPack packer,struct VecPackLink *mine,Vec vec,Vec local)
245: {
247:   PetscScalar    *array;
248:   Vec            global;

251:   DAGetGlobalVector(mine->da,&global);
252:   VecGetArray(vec,&array);
253:   VecPlaceArray(global,array+mine->rstart);
254:   DALocalToGlobal(mine->da,local,INSERT_VALUES,global);
255:   VecRestoreArray(vec,&array);
256:   VecResetArray(global);
257:   DARestoreGlobalVector(mine->da,&global);
258:   return(0);
259: }

261: /* ----------------------------------------------------------------------------------*/

263: #include <stdarg.h>

267: /*@C
268:     VecPackGetAccess - Allows one to access the individual packed vectors in their global
269:        representation.

271:     Collective on VecPack

273:     Input Parameter:
274: +    packer - the packer object
275: .    gvec - the global vector
276: -    ... - the individual sequential or parallel objects (arrays or vectors)
277:  
278:     Level: advanced

280: .seealso VecPackDestroy(), VecPackAddArray(), VecPackAddDA(), VecPackCreateGlobalVector(),
281:          VecPackGather(), VecPackCreate(), VecPackGetGlobalIndices(), VecPackScatter(),
282:          VecPackRestoreAccess(), VecPackGetLocalVectors(), VecPackRestoreLocalVectors()

284: @*/
285: PetscErrorCode PETSCDM_DLLEXPORT VecPackGetAccess(VecPack packer,Vec gvec,...)
286: {
287:   va_list            Argp;
288:   PetscErrorCode     ierr;
289:   struct VecPackLink *next = packer->next;

292:   if (!packer->globalvector) {
293:     SETERRQ(PETSC_ERR_ORDER,"Must first create global vector with VecPackCreateGlobalVector()");
294:   }

296:   /* loop over packed objects, handling one at at time */
297:   va_start(Argp,gvec);
298:   while (next) {
299:     if (next->type == VECPACK_ARRAY) {
300:       PetscScalar **array;
301:       array = va_arg(Argp, PetscScalar**);
302:       VecPackGetAccess_Array(packer,next,gvec,array);
303:     } else if (next->type == VECPACK_DA) {
304:       Vec *vec;
305:       vec  = va_arg(Argp, Vec*);
306:       VecPackGetAccess_DA(packer,next,gvec,vec);
307:     } else {
308:       SETERRQ(PETSC_ERR_SUP,"Cannot handle that object type yet");
309:     }
310:     next = next->next;
311:   }
312:   va_end(Argp);
313:   return(0);
314: }

318: /*@C
319:     VecPackRestoreAccess - Allows one to access the individual packed vectors in their global
320:        representation.

322:     Collective on VecPack

324:     Input Parameter:
325: +    packer - the packer object
326: .    gvec - the global vector
327: -    ... - the individual sequential or parallel objects (arrays or vectors)
328:  
329:     Level: advanced

331: .seealso VecPackDestroy(), VecPackAddArray(), VecPackAddDA(), VecPackCreateGlobalVector(),
332:          VecPackGather(), VecPackCreate(), VecPackGetGlobalIndices(), VecPackScatter(),
333:          VecPackRestoreAccess()

335: @*/
336: PetscErrorCode PETSCDM_DLLEXPORT VecPackRestoreAccess(VecPack packer,Vec gvec,...)
337: {
338:   va_list            Argp;
339:   PetscErrorCode     ierr;
340:   struct VecPackLink *next = packer->next;

343:   if (!packer->globalvector) {
344:     SETERRQ(PETSC_ERR_ORDER,"Must first create global vector with VecPackCreateGlobalVector()");
345:   }

347:   /* loop over packed objects, handling one at at time */
348:   va_start(Argp,gvec);
349:   while (next) {
350:     if (next->type == VECPACK_ARRAY) {
351:       PetscScalar **array;
352:       array = va_arg(Argp, PetscScalar**);
353:       VecPackRestoreAccess_Array(packer,next,gvec,array);
354:     } else if (next->type == VECPACK_DA) {
355:       Vec *vec;
356:       vec  = va_arg(Argp, Vec*);
357:       VecPackRestoreAccess_DA(packer,next,gvec,vec);
358:     } else {
359:       SETERRQ(PETSC_ERR_SUP,"Cannot handle that object type yet");
360:     }
361:     next = next->next;
362:   }
363:   va_end(Argp);
364:   return(0);
365: }

369: /*@C
370:     VecPackScatter - Scatters from a global packed vector into its individual local vectors

372:     Collective on VecPack

374:     Input Parameter:
375: +    packer - the packer object
376: .    gvec - the global vector
377: -    ... - the individual sequential objects (arrays or vectors)
378:  
379:     Level: advanced

381: .seealso VecPackDestroy(), VecPackAddArray(), VecPackAddDA(), VecPackCreateGlobalVector(),
382:          VecPackGather(), VecPackCreate(), VecPackGetGlobalIndices(), VecPackGetAccess(),
383:          VecPackGetLocalVectors(), VecPackRestoreLocalVectors()

385: @*/
386: PetscErrorCode PETSCDM_DLLEXPORT VecPackScatter(VecPack packer,Vec gvec,...)
387: {
388:   va_list            Argp;
389:   PetscErrorCode     ierr;
390:   struct VecPackLink *next = packer->next;

393:   if (!packer->globalvector) {
394:     SETERRQ(PETSC_ERR_ORDER,"Must first create global vector with VecPackCreateGlobalVector()");
395:   }

397:   /* loop over packed objects, handling one at at time */
398:   va_start(Argp,gvec);
399:   while (next) {
400:     if (next->type == VECPACK_ARRAY) {
401:       PetscScalar *array;
402:       array = va_arg(Argp, PetscScalar*);
403:       VecPackScatter_Array(packer,next,gvec,array);
404:     } else if (next->type == VECPACK_DA) {
405:       Vec vec;
406:       vec = va_arg(Argp, Vec);
408:       VecPackScatter_DA(packer,next,gvec,vec);
409:     } else {
410:       SETERRQ(PETSC_ERR_SUP,"Cannot handle that object type yet");
411:     }
412:     next = next->next;
413:   }
414:   va_end(Argp);
415:   return(0);
416: }

420: /*@C
421:     VecPackGather - Gathers into a global packed vector from its individual local vectors

423:     Collective on VecPack

425:     Input Parameter:
426: +    packer - the packer object
427: .    gvec - the global vector
428: -    ... - the individual sequential objects (arrays or vectors)
429:  
430:     Level: advanced

432: .seealso VecPackDestroy(), VecPackAddArray(), VecPackAddDA(), VecPackCreateGlobalVector(),
433:          VecPackScatter(), VecPackCreate(), VecPackGetGlobalIndices(), VecPackGetAccess(),
434:          VecPackGetLocalVectors(), VecPackRestoreLocalVectors()

436: @*/
437: PetscErrorCode PETSCDM_DLLEXPORT VecPackGather(VecPack packer,Vec gvec,...)
438: {
439:   va_list            Argp;
440:   PetscErrorCode     ierr;
441:   struct VecPackLink *next = packer->next;

444:   if (!packer->globalvector) {
445:     SETERRQ(PETSC_ERR_ORDER,"Must first create global vector with VecPackCreateGlobalVector()");
446:   }

448:   /* loop over packed objects, handling one at at time */
449:   va_start(Argp,gvec);
450:   while (next) {
451:     if (next->type == VECPACK_ARRAY) {
452:       PetscScalar *array;
453:       array = va_arg(Argp, PetscScalar*);
454:       VecPackGather_Array(packer,next,gvec,array);
455:     } else if (next->type == VECPACK_DA) {
456:       Vec vec;
457:       vec = va_arg(Argp, Vec);
459:       VecPackGather_DA(packer,next,gvec,vec);
460:     } else {
461:       SETERRQ(PETSC_ERR_SUP,"Cannot handle that object type yet");
462:     }
463:     next = next->next;
464:   }
465:   va_end(Argp);
466:   return(0);
467: }

471: /*@C
472:     VecPackAddArray - adds an "redundant" array to a VecPack. The array values will 
473:        be stored in part of the array on processor 0.

475:     Collective on VecPack

477:     Input Parameter:
478: +    packer - the packer object
479: -    n - the length of the array
480:  
481:     Level: advanced

483: .seealso VecPackDestroy(), VecPackGather(), VecPackAddDA(), VecPackCreateGlobalVector(),
484:          VecPackScatter(), VecPackCreate(), VecPackGetGlobalIndices(), VecPackGetAccess(),
485:          VecPackGetLocalVectors(), VecPackRestoreLocalVectors()

487: @*/
488: PetscErrorCode PETSCDM_DLLEXPORT VecPackAddArray(VecPack packer,PetscInt n)
489: {
490:   struct VecPackLink *mine,*next = packer->next;
491:   PetscErrorCode     ierr;

494:   if (packer->globalvector) {
495:     SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Cannot add an array once you have called VecPackCreateGlobalVector()");
496:   }

498:   /* create new link */
499:   PetscNew(struct VecPackLink,&mine);
500:   mine->n             = n;
501:   mine->da            = PETSC_NULL;
502:   mine->type          = VECPACK_ARRAY;
503:   mine->next          = PETSC_NULL;
504:   if (!packer->rank) packer->n += n;

506:   /* add to end of list */
507:   if (!next) {
508:     packer->next = mine;
509:   } else {
510:     while (next->next) next = next->next;
511:     next->next = mine;
512:   }
513:   packer->nredundant++;
514:   return(0);
515: }

519: /*@C
520:     VecPackAddDA - adds a DA vector to a VecPack

522:     Collective on VecPack

524:     Input Parameter:
525: +    packer - the packer object
526: -    da - the DA object
527:  
528:     Level: advanced

530: .seealso VecPackDestroy(), VecPackGather(), VecPackAddDA(), VecPackCreateGlobalVector(),
531:          VecPackScatter(), VecPackCreate(), VecPackGetGlobalIndices(), VecPackGetAccess(),
532:          VecPackGetLocalVectors(), VecPackRestoreLocalVectors()

534: @*/
535: PetscErrorCode PETSCDM_DLLEXPORT VecPackAddDA(VecPack packer,DA da)
536: {
537:   PetscErrorCode     ierr;
538:   PetscInt           n;
539:   struct VecPackLink *mine,*next = packer->next;
540:   Vec                global;

543:   if (packer->globalvector) {
544:     SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Cannot add a DA once you have called VecPackCreateGlobalVector()");
545:   }

547:   /* create new link */
548:   PetscNew(struct VecPackLink,&mine);
549:   PetscObjectReference((PetscObject)da);
550:   DAGetGlobalVector(da,&global);
551:   VecGetLocalSize(global,&n);
552:   DARestoreGlobalVector(da,&global);
553:   mine->n      = n;
554:   mine->da     = da;
555:   mine->type   = VECPACK_DA;
556:   mine->next   = PETSC_NULL;
557:   packer->n   += n;

559:   /* add to end of list */
560:   if (!next) {
561:     packer->next = mine;
562:   } else {
563:     while (next->next) next = next->next;
564:     next->next = mine;
565:   }
566:   packer->nDA++;
567:   return(0);
568: }

572: /*@C
573:     VecPackCreateGlobalVector - Creates a vector of the correct size to be gathered into 
574:         by the packer.

576:     Collective on VecPack

578:     Input Parameter:
579: .    packer - the packer object

581:     Output Parameters:
582: .   gvec - the global vector

584:     Level: advanced

586:     Notes: Once this has been created you cannot add additional arrays or vectors to be packed.

588: .seealso VecPackDestroy(), VecPackAddArray(), VecPackAddDA(), VecPackScatter(),
589:          VecPackGather(), VecPackCreate(), VecPackGetGlobalIndices(), VecPackGetAccess(),
590:          VecPackGetLocalVectors(), VecPackRestoreLocalVectors()

592: @*/
593: PetscErrorCode PETSCDM_DLLEXPORT VecPackCreateGlobalVector(VecPack packer,Vec *gvec)
594: {
595:   PetscErrorCode     ierr;
596:   PetscInt           nprev = 0;
597:   PetscMPIInt        rank;
598:   struct VecPackLink *next = packer->next;

601:   if (packer->globalvector) {
602:     VecDuplicate(packer->globalvector,gvec);
603:   } else {
604:     VecCreateMPI(packer->comm,packer->n,PETSC_DETERMINE,gvec);
605:     PetscObjectReference((PetscObject)*gvec);
606:     packer->globalvector = *gvec;

608:     VecGetSize(*gvec,&packer->N);
609:     VecGetOwnershipRange(*gvec,&packer->rstart,PETSC_NULL);
610: 
611:     /* now set the rstart for each linked array/vector */
612:     MPI_Comm_rank(packer->comm,&rank);
613:     while (next) {
614:       next->rstart = nprev;
615:       if (!rank || next->type != VECPACK_ARRAY) nprev += next->n;
616:       next = next->next;
617:     }
618:   }
619:   return(0);
620: }

624: /*@C
625:     VecPackGetGlobalIndices - Gets the global indices for all the entries in the packed
626:       vectors.

628:     Collective on VecPack

630:     Input Parameter:
631: .    packer - the packer object

633:     Output Parameters:
634: .    idx - the individual indices for each packed vector/array
635:  
636:     Level: advanced

638:     Notes:
639:        The idx parameters should be freed by the calling routine with PetscFree()

641: .seealso VecPackDestroy(), VecPackAddArray(), VecPackAddDA(), VecPackCreateGlobalVector(),
642:          VecPackGather(), VecPackCreate(), VecPackGetAccess(),
643:          VecPackGetLocalVectors(), VecPackRestoreLocalVectors()

645: @*/
646: PetscErrorCode PETSCDM_DLLEXPORT VecPackGetGlobalIndices(VecPack packer,...)
647: {
648:   va_list            Argp;
649:   PetscErrorCode     ierr;
650:   PetscInt           i,**idx,n;
651:   struct VecPackLink *next = packer->next;
652:   Vec                global,dglobal;
653:   PF                 pf;
654:   PetscScalar        *array;

657:   VecPackCreateGlobalVector(packer,&global);

659:   /* put 0 to N-1 into the global vector */
660:   PFCreate(PETSC_COMM_WORLD,1,1,&pf);
661:   PFSetType(pf,PFIDENTITY,PETSC_NULL);
662:   PFApplyVec(pf,PETSC_NULL,global);
663:   PFDestroy(pf);

665:   /* loop over packed objects, handling one at at time */
666:   va_start(Argp,packer);
667:   while (next) {
668:     idx = va_arg(Argp, PetscInt**);

670:     if (next->type == VECPACK_ARRAY) {
671: 
672:       PetscMalloc(next->n*sizeof(PetscInt),idx);
673:       if (!packer->rank) {
674:         VecGetArray(global,&array);
675:         array += next->rstart;
676:         for (i=0; i<next->n; i++) (*idx)[i] = (PetscInt)PetscRealPart(array[i]);
677:         array -= next->rstart;
678:         VecRestoreArray(global,&array);
679:       }
680:       MPI_Bcast(*idx,next->n,MPIU_INT,0,packer->comm);

682:     } else if (next->type == VECPACK_DA) {
683:       Vec local;

685:       DACreateLocalVector(next->da,&local);
686:       VecGetArray(global,&array);
687:       array += next->rstart;
688:       DAGetGlobalVector(next->da,&dglobal);
689:       VecPlaceArray(dglobal,array);
690:       DAGlobalToLocalBegin(next->da,dglobal,INSERT_VALUES,local);
691:       DAGlobalToLocalEnd(next->da,dglobal,INSERT_VALUES,local);
692:       array -= next->rstart;
693:       VecRestoreArray(global,&array);
694:       VecResetArray(dglobal);
695:       DARestoreGlobalVector(next->da,&dglobal);

697:       VecGetArray(local,&array);
698:       VecGetSize(local,&n);
699:       PetscMalloc(n*sizeof(PetscInt),idx);
700:       for (i=0; i<n; i++) (*idx)[i] = (PetscInt)PetscRealPart(array[i]);
701:       VecRestoreArray(local,&array);
702:       VecDestroy(local);

704:     } else {
705:       SETERRQ(PETSC_ERR_SUP,"Cannot handle that object type yet");
706:     }
707:     next = next->next;
708:   }
709:   va_end(Argp);
710:   VecDestroy(global);
711:   return(0);
712: }

714: /* -------------------------------------------------------------------------------------*/
717: PetscErrorCode VecPackGetLocalVectors_Array(VecPack packer,struct VecPackLink *mine,PetscScalar **array)
718: {
721:   PetscMalloc(mine->n*sizeof(PetscScalar),array);
722:   return(0);
723: }

727: PetscErrorCode VecPackGetLocalVectors_DA(VecPack packer,struct VecPackLink *mine,Vec *local)
728: {
731:   DAGetLocalVector(mine->da,local);
732:   return(0);
733: }

737: PetscErrorCode VecPackRestoreLocalVectors_Array(VecPack packer,struct VecPackLink *mine,PetscScalar **array)
738: {
741:   PetscFree(*array);
742:   return(0);
743: }

747: PetscErrorCode VecPackRestoreLocalVectors_DA(VecPack packer,struct VecPackLink *mine,Vec *local)
748: {
751:   DARestoreLocalVector(mine->da,local);
752:   return(0);
753: }

757: /*@C
758:     VecPackGetLocalVectors - Gets local vectors and arrays for each part of a VecPack.'
759:        Use VecPakcRestoreLocalVectors() to return them.

761:     Collective on VecPack

763:     Input Parameter:
764: .    packer - the packer object
765:  
766:     Output Parameter:
767: .    ... - the individual sequential objects (arrays or vectors)
768:  
769:     Level: advanced

771: .seealso VecPackDestroy(), VecPackAddArray(), VecPackAddDA(), VecPackCreateGlobalVector(),
772:          VecPackGather(), VecPackCreate(), VecPackGetGlobalIndices(), VecPackGetAccess(), 
773:          VecPackRestoreLocalVectors()

775: @*/
776: PetscErrorCode PETSCDM_DLLEXPORT VecPackGetLocalVectors(VecPack packer,...)
777: {
778:   va_list            Argp;
779:   PetscErrorCode     ierr;
780:   struct VecPackLink *next = packer->next;


784:   /* loop over packed objects, handling one at at time */
785:   va_start(Argp,packer);
786:   while (next) {
787:     if (next->type == VECPACK_ARRAY) {
788:       PetscScalar **array;
789:       array = va_arg(Argp, PetscScalar**);
790:       VecPackGetLocalVectors_Array(packer,next,array);
791:     } else if (next->type == VECPACK_DA) {
792:       Vec *vec;
793:       vec = va_arg(Argp, Vec*);
794:       VecPackGetLocalVectors_DA(packer,next,vec);
795:     } else {
796:       SETERRQ(PETSC_ERR_SUP,"Cannot handle that object type yet");
797:     }
798:     next = next->next;
799:   }
800:   va_end(Argp);
801:   return(0);
802: }

806: /*@C
807:     VecPackRestoreLocalVectors - Restores local vectors and arrays for each part of a VecPack.'
808:        Use VecPakcRestoreLocalVectors() to return them.

810:     Collective on VecPack

812:     Input Parameter:
813: .    packer - the packer object
814:  
815:     Output Parameter:
816: .    ... - the individual sequential objects (arrays or vectors)
817:  
818:     Level: advanced

820: .seealso VecPackDestroy(), VecPackAddArray(), VecPackAddDA(), VecPackCreateGlobalVector(),
821:          VecPackGather(), VecPackCreate(), VecPackGetGlobalIndices(), VecPackGetAccess(), 
822:          VecPackGetLocalVectors()

824: @*/
825: PetscErrorCode PETSCDM_DLLEXPORT VecPackRestoreLocalVectors(VecPack packer,...)
826: {
827:   va_list            Argp;
828:   PetscErrorCode     ierr;
829:   struct VecPackLink *next = packer->next;


833:   /* loop over packed objects, handling one at at time */
834:   va_start(Argp,packer);
835:   while (next) {
836:     if (next->type == VECPACK_ARRAY) {
837:       PetscScalar **array;
838:       array = va_arg(Argp, PetscScalar**);
839:       VecPackRestoreLocalVectors_Array(packer,next,array);
840:     } else if (next->type == VECPACK_DA) {
841:       Vec *vec;
842:       vec = va_arg(Argp, Vec*);
843:       VecPackRestoreLocalVectors_DA(packer,next,vec);
844:     } else {
845:       SETERRQ(PETSC_ERR_SUP,"Cannot handle that object type yet");
846:     }
847:     next = next->next;
848:   }
849:   va_end(Argp);
850:   return(0);
851: }

853: /* -------------------------------------------------------------------------------------*/
856: PetscErrorCode VecPackGetEntries_Array(VecPack packer,struct VecPackLink *mine,PetscInt *n)
857: {
859:   if (n) *n = mine->n;
860:   return(0);
861: }

865: PetscErrorCode VecPackGetEntries_DA(VecPack packer,struct VecPackLink *mine,DA *da)
866: {
868:   if (da) *da = mine->da;
869:   return(0);
870: }

874: /*@C
875:     VecPackGetEntries - Gets the DA, redundant size, etc for each entry in a VecPack.
876:        Use VecPackRestoreEntries() to return them.

878:     Collective on VecPack

880:     Input Parameter:
881: .    packer - the packer object
882:  
883:     Output Parameter:
884: .    ... - the individual entries, DAs or integer sizes)
885:  
886:     Level: advanced

888: .seealso VecPackDestroy(), VecPackAddArray(), VecPackAddDA(), VecPackCreateGlobalVector(),
889:          VecPackGather(), VecPackCreate(), VecPackGetGlobalIndices(), VecPackGetAccess(), 
890:          VecPackRestoreLocalVectors(), VecPackGetLocalVectors(), VecPackRestoreEntries(),
891:          VecPackGetLocalVectors(), VecPackRestoreLocalVectors()

893: @*/
894: PetscErrorCode PETSCDM_DLLEXPORT VecPackGetEntries(VecPack packer,...)
895: {
896:   va_list            Argp;
897:   PetscErrorCode     ierr;
898:   struct VecPackLink *next = packer->next;


902:   /* loop over packed objects, handling one at at time */
903:   va_start(Argp,packer);
904:   while (next) {
905:     if (next->type == VECPACK_ARRAY) {
906:       PetscInt *n;
907:       n = va_arg(Argp, PetscInt*);
908:       VecPackGetEntries_Array(packer,next,n);
909:     } else if (next->type == VECPACK_DA) {
910:       DA *da;
911:       da = va_arg(Argp, DA*);
912:       VecPackGetEntries_DA(packer,next,da);
913:     } else {
914:       SETERRQ(PETSC_ERR_SUP,"Cannot handle that object type yet");
915:     }
916:     next = next->next;
917:   }
918:   va_end(Argp);
919:   return(0);
920: }

924: /*@C
925:     VecPackRefine - Refines a VecPack by refining all of its DAs

927:     Collective on VecPack

929:     Input Parameters:
930: +    packer - the packer object
931: -    comm - communicator to contain the new DM object, usually PETSC_NULL

933:     Output Parameter:
934: .    fine - new packer
935:  
936:     Level: advanced

938: .seealso VecPackDestroy(), VecPackAddArray(), VecPackAddDA(), VecPackCreateGlobalVector(),
939:          VecPackGather(), VecPackCreate(), VecPackGetGlobalIndices(), VecPackGetAccess(),
940:          VecPackGetLocalVectors(), VecPackRestoreLocalVectors()

942: @*/
943: PetscErrorCode PETSCDM_DLLEXPORT VecPackRefine(VecPack packer,MPI_Comm comm,VecPack *fine)
944: {
945:   PetscErrorCode     ierr;
946:   struct VecPackLink *next = packer->next;
947:   DA                 da;

950:   VecPackCreate(comm,fine);

952:   /* loop over packed objects, handling one at at time */
953:   while (next) {
954:     if (next->type == VECPACK_ARRAY) {
955:       VecPackAddArray(*fine,next->n);
956:     } else if (next->type == VECPACK_DA) {
957:       DARefine(next->da,comm,&da);
958:       VecPackAddDA(*fine,da);
959:       PetscObjectDereference((PetscObject)da);
960:     } else {
961:       SETERRQ(PETSC_ERR_SUP,"Cannot handle that object type yet");
962:     }
963:     next = next->next;
964:   }
965:   return(0);
966: }

968:  #include petscmat.h

970: struct MatPackLink {
971:   Mat                A;
972:   struct MatPackLink *next;
973: };

975: struct MatPack {
976:   VecPack            right,left;
977:   struct MatPackLink *next;
978: };

982: PetscErrorCode MatMultBoth_Shell_Pack(Mat A,Vec x,Vec y,PetscTruth add)
983: {
984:   struct MatPack     *mpack;
985:   struct VecPackLink *xnext,*ynext;
986:   struct MatPackLink *anext;
987:   PetscScalar        *xarray,*yarray;
988:   PetscErrorCode     ierr;
989:   PetscInt           i;
990:   Vec                xglobal,yglobal;

993:   MatShellGetContext(A,(void**)&mpack);
994:   xnext = mpack->right->next;
995:   ynext = mpack->left->next;
996:   anext = mpack->next;

998:   while (xnext) {
999:     if (xnext->type == VECPACK_ARRAY) {
1000:       if (!mpack->right->rank) {
1001:         VecGetArray(x,&xarray);
1002:         VecGetArray(y,&yarray);
1003:         if (add) {
1004:           for (i=0; i<xnext->n; i++) {
1005:             yarray[ynext->rstart+i] += xarray[xnext->rstart+i];
1006:           }
1007:         } else {
1008:           PetscMemcpy(yarray+ynext->rstart,xarray+xnext->rstart,xnext->n*sizeof(PetscScalar));
1009:         }
1010:         VecRestoreArray(x,&xarray);
1011:         VecRestoreArray(y,&yarray);
1012:       }
1013:     } else if (xnext->type == VECPACK_DA) {
1014:       VecGetArray(x,&xarray);
1015:       VecGetArray(y,&yarray);
1016:       DAGetGlobalVector(xnext->da,&xglobal);
1017:       DAGetGlobalVector(ynext->da,&yglobal);
1018:       VecPlaceArray(xglobal,xarray+xnext->rstart);
1019:       VecPlaceArray(yglobal,yarray+ynext->rstart);
1020:       if (add) {
1021:         MatMultAdd(anext->A,xglobal,yglobal,yglobal);
1022:       } else {
1023:         MatMult(anext->A,xglobal,yglobal);
1024:       }
1025:       VecRestoreArray(x,&xarray);
1026:       VecRestoreArray(y,&yarray);
1027:       VecResetArray(xglobal);
1028:       VecResetArray(yglobal);
1029:       DARestoreGlobalVector(xnext->da,&xglobal);
1030:       DARestoreGlobalVector(ynext->da,&yglobal);
1031:       anext = anext->next;
1032:     } else {
1033:       SETERRQ(PETSC_ERR_SUP,"Cannot handle that object type yet");
1034:     }
1035:     xnext = xnext->next;
1036:     ynext = ynext->next;
1037:   }
1038:   return(0);
1039: }

1043: PetscErrorCode MatMultAdd_Shell_Pack(Mat A,Vec x,Vec y,Vec z)
1044: {
1047:   if (z != y) SETERRQ(PETSC_ERR_SUP,"Handles y == z only");
1048:   MatMultBoth_Shell_Pack(A,x,y,PETSC_TRUE);
1049:   return(0);
1050: }

1054: PetscErrorCode MatMult_Shell_Pack(Mat A,Vec x,Vec y)
1055: {
1058:   MatMultBoth_Shell_Pack(A,x,y,PETSC_FALSE);
1059:   return(0);
1060: }

1064: PetscErrorCode MatMultTranspose_Shell_Pack(Mat A,Vec x,Vec y)
1065: {
1066:   struct MatPack     *mpack;
1067:   struct VecPackLink *xnext,*ynext;
1068:   struct MatPackLink *anext;
1069:   PetscScalar        *xarray,*yarray;
1070:   PetscErrorCode     ierr;
1071:   Vec                xglobal,yglobal;

1074:   MatShellGetContext(A,(void**)&mpack);
1075:   xnext = mpack->left->next;
1076:   ynext = mpack->right->next;
1077:   anext = mpack->next;

1079:   while (xnext) {
1080:     if (xnext->type == VECPACK_ARRAY) {
1081:       if (!mpack->right->rank) {
1082:         VecGetArray(x,&xarray);
1083:         VecGetArray(y,&yarray);
1084:         PetscMemcpy(yarray+ynext->rstart,xarray+xnext->rstart,xnext->n*sizeof(PetscScalar));
1085:         VecRestoreArray(x,&xarray);
1086:         VecRestoreArray(y,&yarray);
1087:       }
1088:     } else if (xnext->type == VECPACK_DA) {
1089:       VecGetArray(x,&xarray);
1090:       VecGetArray(y,&yarray);
1091:       DAGetGlobalVector(xnext->da,&xglobal);
1092:       DAGetGlobalVector(ynext->da,&yglobal);
1093:       VecPlaceArray(xglobal,xarray+xnext->rstart);
1094:       VecPlaceArray(yglobal,yarray+ynext->rstart);
1095:       MatMultTranspose(anext->A,xglobal,yglobal);
1096:       VecRestoreArray(x,&xarray);
1097:       VecRestoreArray(y,&yarray);
1098:       VecResetArray(xglobal);
1099:       VecResetArray(yglobal);
1100:       DARestoreGlobalVector(xnext->da,&xglobal);
1101:       DARestoreGlobalVector(ynext->da,&yglobal);
1102:       anext = anext->next;
1103:     } else {
1104:       SETERRQ(PETSC_ERR_SUP,"Cannot handle that object type yet");
1105:     }
1106:     xnext = xnext->next;
1107:     ynext = ynext->next;
1108:   }
1109:   return(0);
1110: }

1114: PetscErrorCode MatDestroy_Shell_Pack(Mat A)
1115: {
1116:   struct MatPack     *mpack;
1117:   struct MatPackLink *anext,*oldanext;
1118:   PetscErrorCode     ierr;

1121:   MatShellGetContext(A,(void**)&mpack);
1122:   anext = mpack->next;

1124:   while (anext) {
1125:     MatDestroy(anext->A);
1126:     oldanext = anext;
1127:     anext    = anext->next;
1128:     PetscFree(oldanext);
1129:   }
1130:   PetscFree(mpack);
1131:   return(0);
1132: }

1136: /*@C
1137:     VecPackGetInterpolation - GetInterpolations a VecPack by refining all of its DAs

1139:     Collective on VecPack

1141:     Input Parameters:
1142: +    coarse - coarse grid packer
1143: -    fine - fine grid packer

1145:     Output Parameter:
1146: +    A - interpolation matrix
1147: -    v - scaling vector
1148:  
1149:     Level: advanced

1151: .seealso VecPackDestroy(), VecPackAddArray(), VecPackAddDA(), VecPackCreateGlobalVector(),
1152:          VecPackGather(), VecPackCreate(), VecPackGetGlobalIndices(), VecPackGetAccess(),
1153:          VecPackGetLocalVectors(), VecPackRestoreLocalVectors()

1155: @*/
1156: PetscErrorCode PETSCDM_DLLEXPORT VecPackGetInterpolation(VecPack coarse,VecPack fine,Mat *A,Vec *v)
1157: {
1158:   PetscErrorCode     ierr;
1159:   PetscInt           m,n,M,N;
1160:   struct VecPackLink *nextc  = coarse->next;
1161:   struct VecPackLink *nextf = fine->next;
1162:   struct MatPackLink *nextmat,*pnextmat = 0;
1163:   struct MatPack     *mpack;
1164:   Vec                gcoarse,gfine;

1167:   /* use global vectors only for determining matrix layout */
1168:   VecPackCreateGlobalVector(coarse,&gcoarse);
1169:   VecPackCreateGlobalVector(fine,&gfine);
1170:   VecGetLocalSize(gcoarse,&n);
1171:   VecGetLocalSize(gfine,&m);
1172:   VecGetSize(gcoarse,&N);
1173:   VecGetSize(gfine,&M);
1174:   VecDestroy(gcoarse);
1175:   VecDestroy(gfine);

1177:   PetscNew(struct MatPack,&mpack);
1178:   mpack->right = coarse;
1179:   mpack->left  = fine;
1180:   MatCreate(fine->comm,A);
1181:   MatSetSizes(*A,m,n,M,N);
1182:   MatSetType(*A,MATSHELL);
1183:   MatShellSetContext(*A,mpack);
1184:   MatShellSetOperation(*A,MATOP_MULT,(void(*)(void))MatMult_Shell_Pack);
1185:   MatShellSetOperation(*A,MATOP_MULT_TRANSPOSE,(void(*)(void))MatMultTranspose_Shell_Pack);
1186:   MatShellSetOperation(*A,MATOP_MULT_ADD,(void(*)(void))MatMultAdd_Shell_Pack);
1187:   MatShellSetOperation(*A,MATOP_DESTROY,(void(*)(void))MatDestroy_Shell_Pack);

1189:   /* loop over packed objects, handling one at at time */
1190:   while (nextc) {
1191:     if (nextc->type != nextf->type) SETERRQ(PETSC_ERR_ARG_INCOMP,"Two VecPack have different layout");

1193:     if (nextc->type == VECPACK_ARRAY) {
1194:       ;
1195:     } else if (nextc->type == VECPACK_DA) {
1196:       PetscNew(struct MatPackLink,&nextmat);
1197:       nextmat->next = 0;
1198:       if (pnextmat) {
1199:         pnextmat->next = nextmat;
1200:         pnextmat       = nextmat;
1201:       } else {
1202:         pnextmat    = nextmat;
1203:         mpack->next = nextmat;
1204:       }
1205:       DAGetInterpolation(nextc->da,nextf->da,&nextmat->A,PETSC_NULL);
1206:     } else {
1207:       SETERRQ(PETSC_ERR_SUP,"Cannot handle that object type yet");
1208:     }
1209:     nextc = nextc->next;
1210:     nextf = nextf->next;
1211:   }
1212:   return(0);
1213: }