Actual source code: dm.c

petsc-3.9.2 2018-05-20
Report Typos and Errors
  1:  #include <petsc/private/dmimpl.h>
  2:  #include <petsc/private/dmlabelimpl.h>
  3:  #include <petsc/private/petscdsimpl.h>
  4:  #include <petscdmplex.h>
  5:  #include <petscsf.h>
  6:  #include <petscds.h>

  8: PetscClassId  DM_CLASSID;
  9: PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal, DM_LocatePoints, DM_Coarsen, DM_Refine, DM_CreateInterpolation, DM_CreateRestriction;

 11: const char *const DMBoundaryTypes[] = {"NONE","GHOSTED","MIRROR","PERIODIC","TWIST","DM_BOUNDARY_",0};

 13: static PetscErrorCode DMHasCreateInjection_Default(DM dm, PetscBool *flg)
 14: {
 18:   *flg = PETSC_FALSE;
 19:   return(0);
 20: }

 22: /*@
 23:   DMCreate - Creates an empty DM object. The type can then be set with DMSetType().

 25:    If you never  call DMSetType()  it will generate an
 26:    error when you try to use the vector.

 28:   Collective on MPI_Comm

 30:   Input Parameter:
 31: . comm - The communicator for the DM object

 33:   Output Parameter:
 34: . dm - The DM object

 36:   Level: beginner

 38: .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE, DMPLEX, DMMOAB, DMNETWORK
 39: @*/
 40: PetscErrorCode  DMCreate(MPI_Comm comm,DM *dm)
 41: {
 42:   DM             v;

 47:   *dm = NULL;
 48:   PetscSysInitializePackage();
 49:   VecInitializePackage();
 50:   MatInitializePackage();
 51:   DMInitializePackage();

 53:   PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);

 55:   v->ltogmap                  = NULL;
 56:   v->bs                       = 1;
 57:   v->coloringtype             = IS_COLORING_GLOBAL;
 58:   PetscSFCreate(comm, &v->sf);
 59:   PetscSFCreate(comm, &v->defaultSF);
 60:   v->labels                   = NULL;
 61:   v->depthLabel               = NULL;
 62:   v->defaultSection           = NULL;
 63:   v->defaultGlobalSection     = NULL;
 64:   v->defaultConstraintSection = NULL;
 65:   v->defaultConstraintMat     = NULL;
 66:   v->L                        = NULL;
 67:   v->maxCell                  = NULL;
 68:   v->bdtype                   = NULL;
 69:   v->dimEmbed                 = PETSC_DEFAULT;
 70:   {
 71:     PetscInt i;
 72:     for (i = 0; i < 10; ++i) {
 73:       v->nullspaceConstructors[i] = NULL;
 74:     }
 75:   }
 76:   PetscDSCreate(comm, &v->prob);
 77:   v->dmBC = NULL;
 78:   v->coarseMesh = NULL;
 79:   v->outputSequenceNum = -1;
 80:   v->outputSequenceVal = 0.0;
 81:   DMSetVecType(v,VECSTANDARD);
 82:   DMSetMatType(v,MATAIJ);
 83:   PetscNew(&(v->labels));
 84:   v->labels->refct = 1;

 86:   v->ops->hascreateinjection = DMHasCreateInjection_Default;

 88:   *dm = v;
 89:   return(0);
 90: }

 92: /*@
 93:   DMClone - Creates a DM object with the same topology as the original.

 95:   Collective on MPI_Comm

 97:   Input Parameter:
 98: . dm - The original DM object

100:   Output Parameter:
101: . newdm  - The new DM object

103:   Level: beginner

105: .keywords: DM, topology, create
106: @*/
107: PetscErrorCode DMClone(DM dm, DM *newdm)
108: {
109:   PetscSF        sf;
110:   Vec            coords;
111:   void          *ctx;
112:   PetscInt       dim, cdim;

118:   DMCreate(PetscObjectComm((PetscObject) dm), newdm);
119:   PetscFree((*newdm)->labels);
120:   dm->labels->refct++;
121:   (*newdm)->labels = dm->labels;
122:   (*newdm)->depthLabel = dm->depthLabel;
123:   DMGetDimension(dm, &dim);
124:   DMSetDimension(*newdm, dim);
125:   if (dm->ops->clone) {
126:     (*dm->ops->clone)(dm, newdm);
127:   }
128:   (*newdm)->setupcalled = dm->setupcalled;
129:   DMGetPointSF(dm, &sf);
130:   DMSetPointSF(*newdm, sf);
131:   DMGetApplicationContext(dm, &ctx);
132:   DMSetApplicationContext(*newdm, ctx);
133:   if (dm->coordinateDM) {
134:     DM           ncdm;
135:     PetscSection cs;
136:     PetscInt     pEnd = -1, pEndMax = -1;

138:     DMGetDefaultSection(dm->coordinateDM, &cs);
139:     if (cs) {PetscSectionGetChart(cs, NULL, &pEnd);}
140:     MPI_Allreduce(&pEnd,&pEndMax,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));
141:     if (pEndMax >= 0) {
142:       DMClone(dm->coordinateDM, &ncdm);
143:       DMSetDefaultSection(ncdm, cs);
144:       DMSetCoordinateDM(*newdm, ncdm);
145:       DMDestroy(&ncdm);
146:     }
147:   }
148:   DMGetCoordinateDim(dm, &cdim);
149:   DMSetCoordinateDim(*newdm, cdim);
150:   DMGetCoordinatesLocal(dm, &coords);
151:   if (coords) {
152:     DMSetCoordinatesLocal(*newdm, coords);
153:   } else {
154:     DMGetCoordinates(dm, &coords);
155:     if (coords) {DMSetCoordinates(*newdm, coords);}
156:   }
157:   {
158:     PetscBool             isper;
159:     const PetscReal      *maxCell, *L;
160:     const DMBoundaryType *bd;
161:     DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);
162:     DMSetPeriodicity(*newdm, isper, maxCell,  L,  bd);
163:   }
164:   return(0);
165: }

167: /*@C
168:        DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()

170:    Logically Collective on DM

172:    Input Parameter:
173: +  da - initial distributed array
174: .  ctype - the vector type, currently either VECSTANDARD, VECCUDA, or VECVIENNACL

176:    Options Database:
177: .   -dm_vec_type ctype

179:    Level: intermediate

181: .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType, DMGetVecType()
182: @*/
183: PetscErrorCode  DMSetVecType(DM da,VecType ctype)
184: {

189:   PetscFree(da->vectype);
190:   PetscStrallocpy(ctype,(char**)&da->vectype);
191:   return(0);
192: }

194: /*@C
195:        DMGetVecType - Gets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()

197:    Logically Collective on DM

199:    Input Parameter:
200: .  da - initial distributed array

202:    Output Parameter:
203: .  ctype - the vector type

205:    Level: intermediate

207: .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType
208: @*/
209: PetscErrorCode  DMGetVecType(DM da,VecType *ctype)
210: {
213:   *ctype = da->vectype;
214:   return(0);
215: }

217: /*@
218:   VecGetDM - Gets the DM defining the data layout of the vector

220:   Not collective

222:   Input Parameter:
223: . v - The Vec

225:   Output Parameter:
226: . dm - The DM

228:   Level: intermediate

230: .seealso: VecSetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType()
231: @*/
232: PetscErrorCode VecGetDM(Vec v, DM *dm)
233: {

239:   PetscObjectQuery((PetscObject) v, "__PETSc_dm", (PetscObject*) dm);
240:   return(0);
241: }

243: /*@
244:   VecSetDM - Sets the DM defining the data layout of the vector.

246:   Not collective

248:   Input Parameters:
249: + v - The Vec
250: - dm - The DM

252:   Note: This is NOT the same as DMCreateGlobalVector() since it does not change the view methods or perform other customization, but merely sets the DM member.

254:   Level: intermediate

256: .seealso: VecGetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType()
257: @*/
258: PetscErrorCode VecSetDM(Vec v, DM dm)
259: {

265:   PetscObjectCompose((PetscObject) v, "__PETSc_dm", (PetscObject) dm);
266:   return(0);
267: }

269: /*@C
270:        DMSetISColoringType - Sets the type of coloring, global or local, that is created by the DM

272:    Logically Collective on DM

274:    Input Parameters:
275: +  dm - the DM context
276: -  ctype - the matrix type

278:    Options Database:
279: .   -dm_is_coloring_type - global or local

281:    Level: intermediate

283: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(),
284:           DMGetISColoringType()
285: @*/
286: PetscErrorCode  DMSetISColoringType(DM dm,ISColoringType ctype)
287: {
290:   dm->coloringtype = ctype;
291:   return(0);
292: }

294: /*@C
295:        DMGetISColoringType - Gets the type of coloring, global or local, that is created by the DM

297:    Logically Collective on DM

299:    Input Parameter:
300: .  dm - the DM context

302:    Output Parameter:
303: .  ctype - the matrix type

305:    Options Database:
306: .   -dm_is_coloring_type - global or local

308:    Level: intermediate

310: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(),
311:           DMGetISColoringType()
312: @*/
313: PetscErrorCode  DMGetISColoringType(DM dm,ISColoringType *ctype)
314: {
317:   *ctype = dm->coloringtype;
318:   return(0);
319: }

321: /*@C
322:        DMSetMatType - Sets the type of matrix created with DMCreateMatrix()

324:    Logically Collective on DM

326:    Input Parameters:
327: +  dm - the DM context
328: -  ctype - the matrix type

330:    Options Database:
331: .   -dm_mat_type ctype

333:    Level: intermediate

335: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType()
336: @*/
337: PetscErrorCode  DMSetMatType(DM dm,MatType ctype)
338: {

343:   PetscFree(dm->mattype);
344:   PetscStrallocpy(ctype,(char**)&dm->mattype);
345:   return(0);
346: }

348: /*@C
349:        DMGetMatType - Gets the type of matrix created with DMCreateMatrix()

351:    Logically Collective on DM

353:    Input Parameter:
354: .  dm - the DM context

356:    Output Parameter:
357: .  ctype - the matrix type

359:    Options Database:
360: .   -dm_mat_type ctype

362:    Level: intermediate

364: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMSetMatType()
365: @*/
366: PetscErrorCode  DMGetMatType(DM dm,MatType *ctype)
367: {
370:   *ctype = dm->mattype;
371:   return(0);
372: }

374: /*@
375:   MatGetDM - Gets the DM defining the data layout of the matrix

377:   Not collective

379:   Input Parameter:
380: . A - The Mat

382:   Output Parameter:
383: . dm - The DM

385:   Level: intermediate

387:   Developer Note: Since the Mat class doesn't know about the DM class the DM object is associated with 
388:                   the Mat through a PetscObjectCompose() operation

390: .seealso: MatSetDM(), DMCreateMatrix(), DMSetMatType()
391: @*/
392: PetscErrorCode MatGetDM(Mat A, DM *dm)
393: {

399:   PetscObjectQuery((PetscObject) A, "__PETSc_dm", (PetscObject*) dm);
400:   return(0);
401: }

403: /*@
404:   MatSetDM - Sets the DM defining the data layout of the matrix

406:   Not collective

408:   Input Parameters:
409: + A - The Mat
410: - dm - The DM

412:   Level: intermediate

414:   Developer Note: Since the Mat class doesn't know about the DM class the DM object is associated with 
415:                   the Mat through a PetscObjectCompose() operation


418: .seealso: MatGetDM(), DMCreateMatrix(), DMSetMatType()
419: @*/
420: PetscErrorCode MatSetDM(Mat A, DM dm)
421: {

427:   PetscObjectCompose((PetscObject) A, "__PETSc_dm", (PetscObject) dm);
428:   return(0);
429: }

431: /*@C
432:    DMSetOptionsPrefix - Sets the prefix used for searching for all
433:    DM options in the database.

435:    Logically Collective on DM

437:    Input Parameter:
438: +  da - the DM context
439: -  prefix - the prefix to prepend to all option names

441:    Notes:
442:    A hyphen (-) must NOT be given at the beginning of the prefix name.
443:    The first character of all runtime options is AUTOMATICALLY the hyphen.

445:    Level: advanced

447: .keywords: DM, set, options, prefix, database

449: .seealso: DMSetFromOptions()
450: @*/
451: PetscErrorCode  DMSetOptionsPrefix(DM dm,const char prefix[])
452: {

457:   PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);
458:   if (dm->sf) {
459:     PetscObjectSetOptionsPrefix((PetscObject)dm->sf,prefix);
460:   }
461:   if (dm->defaultSF) {
462:     PetscObjectSetOptionsPrefix((PetscObject)dm->defaultSF,prefix);
463:   }
464:   return(0);
465: }

467: /*@C
468:    DMAppendOptionsPrefix - Appends to the prefix used for searching for all
469:    DM options in the database.

471:    Logically Collective on DM

473:    Input Parameters:
474: +  dm - the DM context
475: -  prefix - the prefix string to prepend to all DM option requests

477:    Notes:
478:    A hyphen (-) must NOT be given at the beginning of the prefix name.
479:    The first character of all runtime options is AUTOMATICALLY the hyphen.

481:    Level: advanced

483: .keywords: DM, append, options, prefix, database

485: .seealso: DMSetOptionsPrefix(), DMGetOptionsPrefix()
486: @*/
487: PetscErrorCode  DMAppendOptionsPrefix(DM dm,const char prefix[])
488: {

493:   PetscObjectAppendOptionsPrefix((PetscObject)dm,prefix);
494:   return(0);
495: }

497: /*@C
498:    DMGetOptionsPrefix - Gets the prefix used for searching for all
499:    DM options in the database.

501:    Not Collective

503:    Input Parameters:
504: .  dm - the DM context

506:    Output Parameters:
507: .  prefix - pointer to the prefix string used is returned

509:    Notes: On the fortran side, the user should pass in a string 'prefix' of
510:    sufficient length to hold the prefix.

512:    Level: advanced

514: .keywords: DM, set, options, prefix, database

516: .seealso: DMSetOptionsPrefix(), DMAppendOptionsPrefix()
517: @*/
518: PetscErrorCode  DMGetOptionsPrefix(DM dm,const char *prefix[])
519: {

524:   PetscObjectGetOptionsPrefix((PetscObject)dm,prefix);
525:   return(0);
526: }

528: static PetscErrorCode DMCountNonCyclicReferences(DM dm, PetscBool recurseCoarse, PetscBool recurseFine, PetscInt *ncrefct)
529: {
530:   PetscInt i, refct = ((PetscObject) dm)->refct;
531:   DMNamedVecLink nlink;

535:   *ncrefct = 0;
536:   /* count all the circular references of DM and its contained Vecs */
537:   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
538:     if (dm->localin[i])  refct--;
539:     if (dm->globalin[i]) refct--;
540:   }
541:   for (nlink=dm->namedglobal; nlink; nlink=nlink->next) refct--;
542:   for (nlink=dm->namedlocal; nlink; nlink=nlink->next) refct--;
543:   if (dm->x) {
544:     DM obj;
545:     VecGetDM(dm->x, &obj);
546:     if (obj == dm) refct--;
547:   }
548:   if (dm->coarseMesh && dm->coarseMesh->fineMesh == dm) {
549:     refct--;
550:     if (recurseCoarse) {
551:       PetscInt coarseCount;

553:       DMCountNonCyclicReferences(dm->coarseMesh, PETSC_TRUE, PETSC_FALSE,&coarseCount);
554:       refct += coarseCount;
555:     }
556:   }
557:   if (dm->fineMesh && dm->fineMesh->coarseMesh == dm) {
558:     refct--;
559:     if (recurseFine) {
560:       PetscInt fineCount;

562:       DMCountNonCyclicReferences(dm->fineMesh, PETSC_FALSE, PETSC_TRUE,&fineCount);
563:       refct += fineCount;
564:     }
565:   }
566:   *ncrefct = refct;
567:   return(0);
568: }

570: PetscErrorCode DMDestroyLabelLinkList(DM dm)
571: {

575:   if (!--(dm->labels->refct)) {
576:     DMLabelLink next = dm->labels->next;

578:     /* destroy the labels */
579:     while (next) {
580:       DMLabelLink tmp = next->next;

582:       DMLabelDestroy(&next->label);
583:       PetscFree(next);
584:       next = tmp;
585:     }
586:     PetscFree(dm->labels);
587:   }
588:   return(0);
589: }

591: /*@
592:     DMDestroy - Destroys a vector packer or DM.

594:     Collective on DM

596:     Input Parameter:
597: .   dm - the DM object to destroy

599:     Level: developer

601: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()

603: @*/
604: PetscErrorCode  DMDestroy(DM *dm)
605: {
606:   PetscInt       i, cnt;
607:   DMNamedVecLink nlink,nnext;

611:   if (!*dm) return(0);

614:   /* count all non-cyclic references in the doubly-linked list of coarse<->fine meshes */
615:   DMCountNonCyclicReferences(*dm,PETSC_TRUE,PETSC_TRUE,&cnt);
616:   --((PetscObject)(*dm))->refct;
617:   if (--cnt > 0) {*dm = 0; return(0);}
618:   /*
619:      Need this test because the dm references the vectors that
620:      reference the dm, so destroying the dm calls destroy on the
621:      vectors that cause another destroy on the dm
622:   */
623:   if (((PetscObject)(*dm))->refct < 0) return(0);
624:   ((PetscObject) (*dm))->refct = 0;
625:   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
626:     if ((*dm)->localout[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Destroying a DM that has a local vector obtained with DMGetLocalVector()");
627:     VecDestroy(&(*dm)->localin[i]);
628:   }
629:   nnext=(*dm)->namedglobal;
630:   (*dm)->namedglobal = NULL;
631:   for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named vectors */
632:     nnext = nlink->next;
633:     if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name);
634:     PetscFree(nlink->name);
635:     VecDestroy(&nlink->X);
636:     PetscFree(nlink);
637:   }
638:   nnext=(*dm)->namedlocal;
639:   (*dm)->namedlocal = NULL;
640:   for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named local vectors */
641:     nnext = nlink->next;
642:     if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name);
643:     PetscFree(nlink->name);
644:     VecDestroy(&nlink->X);
645:     PetscFree(nlink);
646:   }

648:   /* Destroy the list of hooks */
649:   {
650:     DMCoarsenHookLink link,next;
651:     for (link=(*dm)->coarsenhook; link; link=next) {
652:       next = link->next;
653:       PetscFree(link);
654:     }
655:     (*dm)->coarsenhook = NULL;
656:   }
657:   {
658:     DMRefineHookLink link,next;
659:     for (link=(*dm)->refinehook; link; link=next) {
660:       next = link->next;
661:       PetscFree(link);
662:     }
663:     (*dm)->refinehook = NULL;
664:   }
665:   {
666:     DMSubDomainHookLink link,next;
667:     for (link=(*dm)->subdomainhook; link; link=next) {
668:       next = link->next;
669:       PetscFree(link);
670:     }
671:     (*dm)->subdomainhook = NULL;
672:   }
673:   {
674:     DMGlobalToLocalHookLink link,next;
675:     for (link=(*dm)->gtolhook; link; link=next) {
676:       next = link->next;
677:       PetscFree(link);
678:     }
679:     (*dm)->gtolhook = NULL;
680:   }
681:   {
682:     DMLocalToGlobalHookLink link,next;
683:     for (link=(*dm)->ltoghook; link; link=next) {
684:       next = link->next;
685:       PetscFree(link);
686:     }
687:     (*dm)->ltoghook = NULL;
688:   }
689:   /* Destroy the work arrays */
690:   {
691:     DMWorkLink link,next;
692:     if ((*dm)->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out");
693:     for (link=(*dm)->workin; link; link=next) {
694:       next = link->next;
695:       PetscFree(link->mem);
696:       PetscFree(link);
697:     }
698:     (*dm)->workin = NULL;
699:   }
700:   if (!--((*dm)->labels->refct)) {
701:     DMLabelLink next = (*dm)->labels->next;

703:     /* destroy the labels */
704:     while (next) {
705:       DMLabelLink tmp = next->next;

707:       DMLabelDestroy(&next->label);
708:       PetscFree(next);
709:       next = tmp;
710:     }
711:     PetscFree((*dm)->labels);
712:   }
713:   {
714:     DMBoundary next = (*dm)->boundary;
715:     while (next) {
716:       DMBoundary b = next;

718:       next = b->next;
719:       PetscFree(b);
720:     }
721:   }

723:   PetscObjectDestroy(&(*dm)->dmksp);
724:   PetscObjectDestroy(&(*dm)->dmsnes);
725:   PetscObjectDestroy(&(*dm)->dmts);

727:   if ((*dm)->ctx && (*dm)->ctxdestroy) {
728:     (*(*dm)->ctxdestroy)(&(*dm)->ctx);
729:   }
730:   VecDestroy(&(*dm)->x);
731:   MatFDColoringDestroy(&(*dm)->fd);
732:   DMClearGlobalVectors(*dm);
733:   ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);
734:   PetscFree((*dm)->vectype);
735:   PetscFree((*dm)->mattype);

737:   PetscSectionDestroy(&(*dm)->defaultSection);
738:   PetscSectionDestroy(&(*dm)->defaultGlobalSection);
739:   PetscLayoutDestroy(&(*dm)->map);
740:   PetscSectionDestroy(&(*dm)->defaultConstraintSection);
741:   MatDestroy(&(*dm)->defaultConstraintMat);
742:   PetscSFDestroy(&(*dm)->sf);
743:   PetscSFDestroy(&(*dm)->defaultSF);
744:   if ((*dm)->useNatural) {
745:     if ((*dm)->sfNatural) {
746:       PetscSFDestroy(&(*dm)->sfNatural);
747:     }
748:     PetscObjectDereference((PetscObject) (*dm)->sfMigration);
749:   }
750:   if ((*dm)->coarseMesh && (*dm)->coarseMesh->fineMesh == *dm) {
751:     DMSetFineDM((*dm)->coarseMesh,NULL);
752:   }
753:   DMDestroy(&(*dm)->coarseMesh);
754:   if ((*dm)->fineMesh && (*dm)->fineMesh->coarseMesh == *dm) {
755:     DMSetCoarseDM((*dm)->fineMesh,NULL);
756:   }
757:   DMDestroy(&(*dm)->fineMesh);
758:   DMDestroy(&(*dm)->coordinateDM);
759:   VecDestroy(&(*dm)->coordinates);
760:   VecDestroy(&(*dm)->coordinatesLocal);
761:   PetscFree3((*dm)->L,(*dm)->maxCell,(*dm)->bdtype);

763:   PetscDSDestroy(&(*dm)->prob);
764:   DMDestroy(&(*dm)->dmBC);
765:   /* if memory was published with SAWs then destroy it */
766:   PetscObjectSAWsViewOff((PetscObject)*dm);

768:   (*(*dm)->ops->destroy)(*dm);
769:   /* We do not destroy (*dm)->data here so that we can reference count backend objects */
770:   PetscHeaderDestroy(dm);
771:   return(0);
772: }

774: /*@
775:     DMSetUp - sets up the data structures inside a DM object

777:     Collective on DM

779:     Input Parameter:
780: .   dm - the DM object to setup

782:     Level: developer

784: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()

786: @*/
787: PetscErrorCode  DMSetUp(DM dm)
788: {

793:   if (dm->setupcalled) return(0);
794:   if (dm->ops->setup) {
795:     (*dm->ops->setup)(dm);
796:   }
797:   dm->setupcalled = PETSC_TRUE;
798:   return(0);
799: }

801: /*@
802:     DMSetFromOptions - sets parameters in a DM from the options database

804:     Collective on DM

806:     Input Parameter:
807: .   dm - the DM object to set options for

809:     Options Database:
810: +   -dm_preallocate_only - Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros
811: .   -dm_vec_type <type>  - type of vector to create inside DM
812: .   -dm_mat_type <type>  - type of matrix to create inside DM
813: -   -dm_is_coloring_type - <global or local>

815:     Level: developer

817: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()

819: @*/
820: PetscErrorCode  DMSetFromOptions(DM dm)
821: {
822:   char           typeName[256];
823:   PetscBool      flg;

828:   if (dm->prob) {
829:     PetscDSSetFromOptions(dm->prob);
830:   }
831:   if (dm->sf) {
832:     PetscSFSetFromOptions(dm->sf);
833:   }
834:   if (dm->defaultSF) {
835:     PetscSFSetFromOptions(dm->defaultSF);
836:   }
837:   PetscObjectOptionsBegin((PetscObject)dm);
838:   PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,NULL);
839:   PetscOptionsFList("-dm_vec_type","Vector type used for created vectors","DMSetVecType",VecList,dm->vectype,typeName,256,&flg);
840:   if (flg) {
841:     DMSetVecType(dm,typeName);
842:   }
843:   PetscOptionsFList("-dm_mat_type","Matrix type used for created matrices","DMSetMatType",MatList,dm->mattype ? dm->mattype : typeName,typeName,sizeof(typeName),&flg);
844:   if (flg) {
845:     DMSetMatType(dm,typeName);
846:   }
847:   PetscOptionsEnum("-dm_is_coloring_type","Global or local coloring of Jacobian","DMSetISColoringType",ISColoringTypes,(PetscEnum)dm->coloringtype,(PetscEnum*)&dm->coloringtype,NULL);
848:   if (dm->ops->setfromoptions) {
849:     (*dm->ops->setfromoptions)(PetscOptionsObject,dm);
850:   }
851:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
852:   PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) dm);
853:   PetscOptionsEnd();
854:   return(0);
855: }

857: /*@C
858:     DMView - Views a DM

860:     Collective on DM

862:     Input Parameter:
863: +   dm - the DM object to view
864: -   v - the viewer

866:     Level: beginner

868: .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()

870: @*/
871: PetscErrorCode  DMView(DM dm,PetscViewer v)
872: {
873:   PetscErrorCode    ierr;
874:   PetscBool         isbinary;
875:   PetscMPIInt       size;
876:   PetscViewerFormat format;
877:   PetscInt          tabs;

881:   if (!v) {
882:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm),&v);
883:   }
884:   PetscViewerGetFormat(v,&format);
885:   MPI_Comm_size(PetscObjectComm((PetscObject)dm),&size);
886:   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) return(0);
887:   PetscViewerASCIIGetTab(v, &tabs);
888:   PetscViewerASCIISetTab(v, ((PetscObject)dm)->tablevel);
889:   PetscObjectPrintClassNamePrefixType((PetscObject)dm,v);
890:   PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERBINARY,&isbinary);
891:   if (isbinary) {
892:     PetscInt classid = DM_FILE_CLASSID;
893:     char     type[256];

895:     PetscViewerBinaryWrite(v,&classid,1,PETSC_INT,PETSC_FALSE);
896:     PetscStrncpy(type,((PetscObject)dm)->type_name,256);
897:     PetscViewerBinaryWrite(v,type,256,PETSC_CHAR,PETSC_FALSE);
898:   }
899:   if (dm->ops->view) {
900:     (*dm->ops->view)(dm,v);
901:   }
902:   PetscViewerASCIISetTab(v, tabs);
903:   return(0);
904: }

906: /*@
907:     DMCreateGlobalVector - Creates a global vector from a DM object

909:     Collective on DM

911:     Input Parameter:
912: .   dm - the DM object

914:     Output Parameter:
915: .   vec - the global vector

917:     Level: beginner

919: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()

921: @*/
922: PetscErrorCode  DMCreateGlobalVector(DM dm,Vec *vec)
923: {

928:   (*dm->ops->createglobalvector)(dm,vec);
929:   return(0);
930: }

932: /*@
933:     DMCreateLocalVector - Creates a local vector from a DM object

935:     Not Collective

937:     Input Parameter:
938: .   dm - the DM object

940:     Output Parameter:
941: .   vec - the local vector

943:     Level: beginner

945: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()

947: @*/
948: PetscErrorCode  DMCreateLocalVector(DM dm,Vec *vec)
949: {

954:   (*dm->ops->createlocalvector)(dm,vec);
955:   return(0);
956: }

958: /*@
959:    DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM.

961:    Collective on DM

963:    Input Parameter:
964: .  dm - the DM that provides the mapping

966:    Output Parameter:
967: .  ltog - the mapping

969:    Level: intermediate

971:    Notes:
972:    This mapping can then be used by VecSetLocalToGlobalMapping() or
973:    MatSetLocalToGlobalMapping().

975: .seealso: DMCreateLocalVector()
976: @*/
977: PetscErrorCode DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog)
978: {
979:   PetscInt       bs = -1, bsLocal[2], bsMinMax[2];

985:   if (!dm->ltogmap) {
986:     PetscSection section, sectionGlobal;

988:     DMGetDefaultSection(dm, &section);
989:     if (section) {
990:       const PetscInt *cdofs;
991:       PetscInt       *ltog;
992:       PetscInt        pStart, pEnd, n, p, k, l;

994:       DMGetDefaultGlobalSection(dm, &sectionGlobal);
995:       PetscSectionGetChart(section, &pStart, &pEnd);
996:       PetscSectionGetStorageSize(section, &n);
997:       PetscMalloc1(n, &ltog); /* We want the local+overlap size */
998:       for (p = pStart, l = 0; p < pEnd; ++p) {
999:         PetscInt bdof, cdof, dof, off, c, cind = 0;

1001:         /* Should probably use constrained dofs */
1002:         PetscSectionGetDof(section, p, &dof);
1003:         PetscSectionGetConstraintDof(section, p, &cdof);
1004:         PetscSectionGetConstraintIndices(section, p, &cdofs);
1005:         PetscSectionGetOffset(sectionGlobal, p, &off);
1006:         /* If you have dofs, and constraints, and they are unequal, we set the blocksize to 1 */
1007:         bdof = cdof && (dof-cdof) ? 1 : dof;
1008:         if (dof) {
1009:           if (bs < 0)          {bs = bdof;}
1010:           else if (bs != bdof) {bs = 1;}
1011:         }
1012:         for (c = 0; c < dof; ++c, ++l) {
1013:           if ((cind < cdof) && (c == cdofs[cind])) ltog[l] = off < 0 ? off-c : off+c;
1014:           else                                     ltog[l] = (off < 0 ? -(off+1) : off) + c;
1015:         }
1016:       }
1017:       /* Must have same blocksize on all procs (some might have no points) */
1018:       bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs;
1019:       PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);
1020:       if (bsMinMax[0] != bsMinMax[1]) {bs = 1;}
1021:       else                            {bs = bsMinMax[0];}
1022:       bs = bs < 0 ? 1 : bs;
1023:       /* Must reduce indices by blocksize */
1024:       if (bs > 1) {
1025:         for (l = 0, k = 0; l < n; l += bs, ++k) ltog[k] = ltog[l]/bs;
1026:         n /= bs;
1027:       }
1028:       ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, n, ltog, PETSC_OWN_POINTER, &dm->ltogmap);
1029:       PetscLogObjectParent((PetscObject)dm, (PetscObject)dm->ltogmap);
1030:     } else {
1031:       if (!dm->ops->getlocaltoglobalmapping) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM can not create LocalToGlobalMapping");
1032:       (*dm->ops->getlocaltoglobalmapping)(dm);
1033:     }
1034:   }
1035:   *ltog = dm->ltogmap;
1036:   return(0);
1037: }

1039: /*@
1040:    DMGetBlockSize - Gets the inherent block size associated with a DM

1042:    Not Collective

1044:    Input Parameter:
1045: .  dm - the DM with block structure

1047:    Output Parameter:
1048: .  bs - the block size, 1 implies no exploitable block structure

1050:    Level: intermediate

1052: .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMapping()
1053: @*/
1054: PetscErrorCode  DMGetBlockSize(DM dm,PetscInt *bs)
1055: {
1059:   if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet");
1060:   *bs = dm->bs;
1061:   return(0);
1062: }

1064: /*@
1065:     DMCreateInterpolation - Gets interpolation matrix between two DM objects

1067:     Collective on DM

1069:     Input Parameter:
1070: +   dm1 - the DM object
1071: -   dm2 - the second, finer DM object

1073:     Output Parameter:
1074: +  mat - the interpolation
1075: -  vec - the scaling (optional)

1077:     Level: developer

1079:     Notes:  For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
1080:         DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation.

1082:         For DMDA objects you can use this interpolation (more precisely the interpolation from the DMGetCoordinateDM()) to interpolate the mesh coordinate vectors
1083:         EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic.


1086: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateRestriction()

1088: @*/
1089: PetscErrorCode  DMCreateInterpolation(DM dm1,DM dm2,Mat *mat,Vec *vec)
1090: {

1096:   PetscLogEventBegin(DM_CreateInterpolation,dm1,dm2,0,0);
1097:   (*dm1->ops->createinterpolation)(dm1,dm2,mat,vec);
1098:   PetscLogEventEnd(DM_CreateInterpolation,dm1,dm2,0,0);
1099:   return(0);
1100: }

1102: /*@
1103:     DMCreateRestriction - Gets restriction matrix between two DM objects

1105:     Collective on DM

1107:     Input Parameter:
1108: +   dm1 - the DM object
1109: -   dm2 - the second, finer DM object

1111:     Output Parameter:
1112: .  mat - the restriction


1115:     Level: developer

1117:     Notes:  For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
1118:         DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation.


1121: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateInterpolation()

1123: @*/
1124: PetscErrorCode  DMCreateRestriction(DM dm1,DM dm2,Mat *mat)
1125: {

1131:   PetscLogEventBegin(DM_CreateRestriction,dm1,dm2,0,0);
1132:   if (!dm1->ops->createrestriction) SETERRQ(PetscObjectComm((PetscObject)dm1),PETSC_ERR_SUP,"DMCreateRestriction not implemented for this type");
1133:   (*dm1->ops->createrestriction)(dm1,dm2,mat);
1134:   PetscLogEventEnd(DM_CreateRestriction,dm1,dm2,0,0);
1135:   return(0);
1136: }

1138: /*@
1139:     DMCreateInjection - Gets injection matrix between two DM objects

1141:     Collective on DM

1143:     Input Parameter:
1144: +   dm1 - the DM object
1145: -   dm2 - the second, finer DM object

1147:     Output Parameter:
1148: .   mat - the injection

1150:     Level: developer

1152:    Notes:  For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
1153:         DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection.

1155: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMCreateInterpolation()

1157: @*/
1158: PetscErrorCode  DMCreateInjection(DM dm1,DM dm2,Mat *mat)
1159: {

1165:   if (!dm1->ops->getinjection) SETERRQ(PetscObjectComm((PetscObject)dm1),PETSC_ERR_SUP,"DMCreateInjection not implemented for this type");
1166:   (*dm1->ops->getinjection)(dm1,dm2,mat);
1167:   return(0);
1168: }

1170: /*@
1171:   DMCreateMassMatrix - Gets mass matrix between two DM objects, M_ij = \int \phi_i \psi_j

1173:   Collective on DM

1175:   Input Parameter:
1176: + dm1 - the DM object
1177: - dm2 - the second, finer DM object

1179:   Output Parameter:
1180: . mat - the interpolation

1182:   Level: developer

1184: .seealso DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateRestriction(), DMCreateInterpolation(), DMCreateInjection()
1185: @*/
1186: PetscErrorCode DMCreateMassMatrix(DM dm1, DM dm2, Mat *mat)
1187: {

1193:   (*dm1->ops->createmassmatrix)(dm1, dm2, mat);
1194:   return(0);
1195: }

1197: /*@
1198:     DMCreateColoring - Gets coloring for a DM

1200:     Collective on DM

1202:     Input Parameter:
1203: +   dm - the DM object
1204: -   ctype - IS_COLORING_LOCAL or IS_COLORING_GLOBAL

1206:     Output Parameter:
1207: .   coloring - the coloring

1209:     Level: developer

1211: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateMatrix(), DMSetMatType()

1213: @*/
1214: PetscErrorCode  DMCreateColoring(DM dm,ISColoringType ctype,ISColoring *coloring)
1215: {

1220:   if (!dm->ops->getcoloring) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No coloring for this type of DM yet");
1221:   (*dm->ops->getcoloring)(dm,ctype,coloring);
1222:   return(0);
1223: }

1225: /*@
1226:     DMCreateMatrix - Gets empty Jacobian for a DM

1228:     Collective on DM

1230:     Input Parameter:
1231: .   dm - the DM object

1233:     Output Parameter:
1234: .   mat - the empty Jacobian

1236:     Level: beginner

1238:     Notes: This properly preallocates the number of nonzeros in the sparse matrix so you
1239:        do not need to do it yourself.

1241:        By default it also sets the nonzero structure and puts in the zero entries. To prevent setting
1242:        the nonzero pattern call DMSetMatrixPreallocateOnly()

1244:        For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used
1245:        internally by PETSc.

1247:        For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires
1248:        the indices for the global numbering for DMDAs which is complicated.

1250: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMSetMatType()

1252: @*/
1253: PetscErrorCode  DMCreateMatrix(DM dm,Mat *mat)
1254: {

1259:   MatInitializePackage();
1262:   (*dm->ops->creatematrix)(dm,mat);
1263:   return(0);
1264: }

1266: /*@
1267:   DMSetMatrixPreallocateOnly - When DMCreateMatrix() is called the matrix will be properly
1268:     preallocated but the nonzero structure and zero values will not be set.

1270:   Logically Collective on DM

1272:   Input Parameter:
1273: + dm - the DM
1274: - only - PETSC_TRUE if only want preallocation

1276:   Level: developer
1277: .seealso DMCreateMatrix(), DMSetMatrixStructureOnly()
1278: @*/
1279: PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only)
1280: {
1283:   dm->prealloc_only = only;
1284:   return(0);
1285: }

1287: /*@
1288:   DMSetMatrixStructureOnly - When DMCreateMatrix() is called, the matrix structure will be created
1289:     but the array for values will not be allocated.

1291:   Logically Collective on DM

1293:   Input Parameter:
1294: + dm - the DM
1295: - only - PETSC_TRUE if only want matrix stucture

1297:   Level: developer
1298: .seealso DMCreateMatrix(), DMSetMatrixPreallocateOnly()
1299: @*/
1300: PetscErrorCode DMSetMatrixStructureOnly(DM dm, PetscBool only)
1301: {
1304:   dm->structure_only = only;
1305:   return(0);
1306: }

1308: /*@C
1309:   DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray()

1311:   Not Collective

1313:   Input Parameters:
1314: + dm - the DM object
1315: . count - The minium size
1316: - dtype - MPI data type, often MPIU_REAL, MPIU_SCALAR, MPIU_INT)

1318:   Output Parameter:
1319: . array - the work array

1321:   Level: developer

1323: .seealso DMDestroy(), DMCreate()
1324: @*/
1325: PetscErrorCode DMGetWorkArray(DM dm,PetscInt count,MPI_Datatype dtype,void *mem)
1326: {
1328:   DMWorkLink     link;
1329:   PetscMPIInt    dsize;

1334:   if (dm->workin) {
1335:     link       = dm->workin;
1336:     dm->workin = dm->workin->next;
1337:   } else {
1338:     PetscNewLog(dm,&link);
1339:   }
1340:   MPI_Type_size(dtype,&dsize);
1341:   if (((size_t)dsize*count) > link->bytes) {
1342:     PetscFree(link->mem);
1343:     PetscMalloc(dsize*count,&link->mem);
1344:     link->bytes = dsize*count;
1345:   }
1346:   link->next   = dm->workout;
1347:   dm->workout  = link;
1348:   *(void**)mem = link->mem;
1349:   return(0);
1350: }

1352: /*@C
1353:   DMRestoreWorkArray - Restores a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray()

1355:   Not Collective

1357:   Input Parameters:
1358: + dm - the DM object
1359: . count - The minium size
1360: - dtype - MPI data type, often MPIU_REAL, MPIU_SCALAR, MPIU_INT

1362:   Output Parameter:
1363: . array - the work array

1365:   Level: developer

1367:   Developer Notes: count and dtype are ignored, they are only needed for DMGetWorkArray()
1368: .seealso DMDestroy(), DMCreate()
1369: @*/
1370: PetscErrorCode DMRestoreWorkArray(DM dm,PetscInt count,MPI_Datatype dtype,void *mem)
1371: {
1372:   DMWorkLink *p,link;

1377:   for (p=&dm->workout; (link=*p); p=&link->next) {
1378:     if (link->mem == *(void**)mem) {
1379:       *p           = link->next;
1380:       link->next   = dm->workin;
1381:       dm->workin   = link;
1382:       *(void**)mem = NULL;
1383:       return(0);
1384:     }
1385:   }
1386:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out");
1387: }

1389: PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt field, MatNullSpace *nullSpace))
1390: {
1393:   if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field);
1394:   dm->nullspaceConstructors[field] = nullsp;
1395:   return(0);
1396: }

1398: /*@C
1399:   DMCreateFieldIS - Creates a set of IS objects with the global indices of dofs for each field

1401:   Not collective

1403:   Input Parameter:
1404: . dm - the DM object

1406:   Output Parameters:
1407: + numFields  - The number of fields (or NULL if not requested)
1408: . fieldNames - The name for each field (or NULL if not requested)
1409: - fields     - The global indices for each field (or NULL if not requested)

1411:   Level: intermediate

1413:   Notes:
1414:   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1415:   PetscFree(), every entry of fields should be destroyed with ISDestroy(), and both arrays should be freed with
1416:   PetscFree().

1418: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
1419: @*/
1420: PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields)
1421: {
1422:   PetscSection   section, sectionGlobal;

1427:   if (numFields) {
1429:     *numFields = 0;
1430:   }
1431:   if (fieldNames) {
1433:     *fieldNames = NULL;
1434:   }
1435:   if (fields) {
1437:     *fields = NULL;
1438:   }
1439:   DMGetDefaultSection(dm, &section);
1440:   if (section) {
1441:     PetscInt *fieldSizes, **fieldIndices;
1442:     PetscInt nF, f, pStart, pEnd, p;

1444:     DMGetDefaultGlobalSection(dm, &sectionGlobal);
1445:     PetscSectionGetNumFields(section, &nF);
1446:     PetscMalloc2(nF,&fieldSizes,nF,&fieldIndices);
1447:     PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);
1448:     for (f = 0; f < nF; ++f) {
1449:       fieldSizes[f] = 0;
1450:     }
1451:     for (p = pStart; p < pEnd; ++p) {
1452:       PetscInt gdof;

1454:       PetscSectionGetDof(sectionGlobal, p, &gdof);
1455:       if (gdof > 0) {
1456:         for (f = 0; f < nF; ++f) {
1457:           PetscInt fdof, fcdof;

1459:           PetscSectionGetFieldDof(section, p, f, &fdof);
1460:           PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);
1461:           fieldSizes[f] += fdof-fcdof;
1462:         }
1463:       }
1464:     }
1465:     for (f = 0; f < nF; ++f) {
1466:       PetscMalloc1(fieldSizes[f], &fieldIndices[f]);
1467:       fieldSizes[f] = 0;
1468:     }
1469:     for (p = pStart; p < pEnd; ++p) {
1470:       PetscInt gdof, goff;

1472:       PetscSectionGetDof(sectionGlobal, p, &gdof);
1473:       if (gdof > 0) {
1474:         PetscSectionGetOffset(sectionGlobal, p, &goff);
1475:         for (f = 0; f < nF; ++f) {
1476:           PetscInt fdof, fcdof, fc;

1478:           PetscSectionGetFieldDof(section, p, f, &fdof);
1479:           PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);
1480:           for (fc = 0; fc < fdof-fcdof; ++fc, ++fieldSizes[f]) {
1481:             fieldIndices[f][fieldSizes[f]] = goff++;
1482:           }
1483:         }
1484:       }
1485:     }
1486:     if (numFields) *numFields = nF;
1487:     if (fieldNames) {
1488:       PetscMalloc1(nF, fieldNames);
1489:       for (f = 0; f < nF; ++f) {
1490:         const char *fieldName;

1492:         PetscSectionGetFieldName(section, f, &fieldName);
1493:         PetscStrallocpy(fieldName, (char**) &(*fieldNames)[f]);
1494:       }
1495:     }
1496:     if (fields) {
1497:       PetscMalloc1(nF, fields);
1498:       for (f = 0; f < nF; ++f) {
1499:         ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]);
1500:       }
1501:     }
1502:     PetscFree2(fieldSizes,fieldIndices);
1503:   } else if (dm->ops->createfieldis) {
1504:     (*dm->ops->createfieldis)(dm, numFields, fieldNames, fields);
1505:   }
1506:   return(0);
1507: }


1510: /*@C
1511:   DMCreateFieldDecomposition - Returns a list of IS objects defining a decomposition of a problem into subproblems
1512:                           corresponding to different fields: each IS contains the global indices of the dofs of the
1513:                           corresponding field. The optional list of DMs define the DM for each subproblem.
1514:                           Generalizes DMCreateFieldIS().

1516:   Not collective

1518:   Input Parameter:
1519: . dm - the DM object

1521:   Output Parameters:
1522: + len       - The number of subproblems in the field decomposition (or NULL if not requested)
1523: . namelist  - The name for each field (or NULL if not requested)
1524: . islist    - The global indices for each field (or NULL if not requested)
1525: - dmlist    - The DMs for each field subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined)

1527:   Level: intermediate

1529:   Notes:
1530:   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1531:   PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(),
1532:   and all of the arrays should be freed with PetscFree().

1534: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1535: @*/
1536: PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
1537: {

1542:   if (len) {
1544:     *len = 0;
1545:   }
1546:   if (namelist) {
1548:     *namelist = 0;
1549:   }
1550:   if (islist) {
1552:     *islist = 0;
1553:   }
1554:   if (dmlist) {
1556:     *dmlist = 0;
1557:   }
1558:   /*
1559:    Is it a good idea to apply the following check across all impls?
1560:    Perhaps some impls can have a well-defined decomposition before DMSetUp?
1561:    This, however, follows the general principle that accessors are not well-behaved until the object is set up.
1562:    */
1563:   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
1564:   if (!dm->ops->createfielddecomposition) {
1565:     PetscSection section;
1566:     PetscInt     numFields, f;

1568:     DMGetDefaultSection(dm, &section);
1569:     if (section) {PetscSectionGetNumFields(section, &numFields);}
1570:     if (section && numFields && dm->ops->createsubdm) {
1571:       if (len) *len = numFields;
1572:       if (namelist) {PetscMalloc1(numFields,namelist);}
1573:       if (islist)   {PetscMalloc1(numFields,islist);}
1574:       if (dmlist)   {PetscMalloc1(numFields,dmlist);}
1575:       for (f = 0; f < numFields; ++f) {
1576:         const char *fieldName;

1578:         DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL);
1579:         if (namelist) {
1580:           PetscSectionGetFieldName(section, f, &fieldName);
1581:           PetscStrallocpy(fieldName, (char**) &(*namelist)[f]);
1582:         }
1583:       }
1584:     } else {
1585:       DMCreateFieldIS(dm, len, namelist, islist);
1586:       /* By default there are no DMs associated with subproblems. */
1587:       if (dmlist) *dmlist = NULL;
1588:     }
1589:   } else {
1590:     (*dm->ops->createfielddecomposition)(dm,len,namelist,islist,dmlist);
1591:   }
1592:   return(0);
1593: }

1595: /*@
1596:   DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in.
1597:                   The fields are defined by DMCreateFieldIS().

1599:   Not collective

1601:   Input Parameters:
1602: + dm        - The DM object
1603: . numFields - The number of fields in this subproblem
1604: - fields    - The field numbers of the selected fields

1606:   Output Parameters:
1607: + is - The global indices for the subproblem
1608: - subdm - The DM for the subproblem

1610:   Level: intermediate

1612: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1613: @*/
1614: PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
1615: {

1623:   if (dm->ops->createsubdm) {
1624:     (*dm->ops->createsubdm)(dm, numFields, fields, is, subdm);
1625:   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateSubDM implementation defined");
1626:   return(0);
1627: }

1629: /*@C
1630:   DMCreateSuperDM - Returns an arrays of ISes and DM encapsulating a superproblem defined by the DMs passed in.

1632:   Not collective

1634:   Input Parameter:
1635: + dms - The DM objects
1636: - len - The number of DMs

1638:   Output Parameters:
1639: + is - The global indices for the subproblem
1640: - superdm - The DM for the superproblem

1642:   Level: intermediate

1644: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1645: @*/
1646: PetscErrorCode DMCreateSuperDM(DM dms[], PetscInt len, IS **is, DM *superdm)
1647: {
1648:   PetscInt       i;

1656:   if (len < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of DMs must be nonnegative: %D", len);
1657:   if (len) {
1658:     if (dms[0]->ops->createsuperdm) {
1659:       (*dms[0]->ops->createsuperdm)(dms, len, is, superdm);
1660:     } else SETERRQ(PetscObjectComm((PetscObject) dms[0]), PETSC_ERR_SUP, "This type has no DMCreateSuperDM implementation defined");
1661:   }
1662:   return(0);
1663: }


1666: /*@C
1667:   DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems
1668:                           corresponding to restrictions to pairs nested subdomains: each IS contains the global
1669:                           indices of the dofs of the corresponding subdomains.  The inner subdomains conceptually
1670:                           define a nonoverlapping covering, while outer subdomains can overlap.
1671:                           The optional list of DMs define the DM for each subproblem.

1673:   Not collective

1675:   Input Parameter:
1676: . dm - the DM object

1678:   Output Parameters:
1679: + len         - The number of subproblems in the domain decomposition (or NULL if not requested)
1680: . namelist    - The name for each subdomain (or NULL if not requested)
1681: . innerislist - The global indices for each inner subdomain (or NULL, if not requested)
1682: . outerislist - The global indices for each outer subdomain (or NULL, if not requested)
1683: - dmlist      - The DMs for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined)

1685:   Level: intermediate

1687:   Notes:
1688:   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1689:   PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(),
1690:   and all of the arrays should be freed with PetscFree().

1692: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateDomainDecompositionDM(), DMCreateFieldDecomposition()
1693: @*/
1694: PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist)
1695: {
1696:   PetscErrorCode      ierr;
1697:   DMSubDomainHookLink link;
1698:   PetscInt            i,l;

1707:   /*
1708:    Is it a good idea to apply the following check across all impls?
1709:    Perhaps some impls can have a well-defined decomposition before DMSetUp?
1710:    This, however, follows the general principle that accessors are not well-behaved until the object is set up.
1711:    */
1712:   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
1713:   if (dm->ops->createdomaindecomposition) {
1714:     (*dm->ops->createdomaindecomposition)(dm,&l,namelist,innerislist,outerislist,dmlist);
1715:     /* copy subdomain hooks and context over to the subdomain DMs */
1716:     if (dmlist && *dmlist) {
1717:       for (i = 0; i < l; i++) {
1718:         for (link=dm->subdomainhook; link; link=link->next) {
1719:           if (link->ddhook) {(*link->ddhook)(dm,(*dmlist)[i],link->ctx);}
1720:         }
1721:         if (dm->ctx) (*dmlist)[i]->ctx = dm->ctx;
1722:       }
1723:     }
1724:     if (len) *len = l;
1725:   }
1726:   return(0);
1727: }


1730: /*@C
1731:   DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector

1733:   Not collective

1735:   Input Parameters:
1736: + dm - the DM object
1737: . n  - the number of subdomain scatters
1738: - subdms - the local subdomains

1740:   Output Parameters:
1741: + n     - the number of scatters returned
1742: . iscat - scatter from global vector to nonoverlapping global vector entries on subdomain
1743: . oscat - scatter from global vector to overlapping global vector entries on subdomain
1744: - gscat - scatter from global vector to local vector on subdomain (fills in ghosts)

1746:   Notes: This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution
1747:   of general nonlinear problems with overlapping subdomain methods.  While merely having index sets that enable subsets
1748:   of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of
1749:   solution and residual data.

1751:   Level: developer

1753: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1754: @*/
1755: PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat)
1756: {

1762:   if (dm->ops->createddscatters) {
1763:     (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);
1764:   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateDomainDecompositionScatter implementation defined");
1765:   return(0);
1766: }

1768: /*@
1769:   DMRefine - Refines a DM object

1771:   Collective on DM

1773:   Input Parameter:
1774: + dm   - the DM object
1775: - comm - the communicator to contain the new DM object (or MPI_COMM_NULL)

1777:   Output Parameter:
1778: . dmf - the refined DM, or NULL

1780:   Note: If no refinement was done, the return value is NULL

1782:   Level: developer

1784: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
1785: @*/
1786: PetscErrorCode  DMRefine(DM dm,MPI_Comm comm,DM *dmf)
1787: {
1788:   PetscErrorCode   ierr;
1789:   DMRefineHookLink link;

1793:   PetscLogEventBegin(DM_Refine,dm,0,0,0);
1794:   if (!dm->ops->refine) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM cannot refine");
1795:   (*dm->ops->refine)(dm,comm,dmf);
1796:   if (*dmf) {
1797:     (*dmf)->ops->creatematrix = dm->ops->creatematrix;

1799:     PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);

1801:     (*dmf)->ctx       = dm->ctx;
1802:     (*dmf)->leveldown = dm->leveldown;
1803:     (*dmf)->levelup   = dm->levelup + 1;

1805:     DMSetMatType(*dmf,dm->mattype);
1806:     for (link=dm->refinehook; link; link=link->next) {
1807:       if (link->refinehook) {
1808:         (*link->refinehook)(dm,*dmf,link->ctx);
1809:       }
1810:     }
1811:   }
1812:   PetscLogEventEnd(DM_Refine,dm,0,0,0);
1813:   return(0);
1814: }

1816: /*@C
1817:    DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid

1819:    Logically Collective

1821:    Input Arguments:
1822: +  coarse - nonlinear solver context on which to run a hook when restricting to a coarser level
1823: .  refinehook - function to run when setting up a coarser level
1824: .  interphook - function to run to update data on finer levels (once per SNESSolve())
1825: -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)

1827:    Calling sequence of refinehook:
1828: $    refinehook(DM coarse,DM fine,void *ctx);

1830: +  coarse - coarse level DM
1831: .  fine - fine level DM to interpolate problem to
1832: -  ctx - optional user-defined function context

1834:    Calling sequence for interphook:
1835: $    interphook(DM coarse,Mat interp,DM fine,void *ctx)

1837: +  coarse - coarse level DM
1838: .  interp - matrix interpolating a coarse-level solution to the finer grid
1839: .  fine - fine level DM to update
1840: -  ctx - optional user-defined function context

1842:    Level: advanced

1844:    Notes:
1845:    This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing

1847:    If this function is called multiple times, the hooks will be run in the order they are added.

1849:    This function is currently not available from Fortran.

1851: .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1852: @*/
1853: PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx)
1854: {
1855:   PetscErrorCode   ierr;
1856:   DMRefineHookLink link,*p;

1860:   for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */
1861:     if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) return(0);
1862:   }
1863:   PetscNew(&link);
1864:   link->refinehook = refinehook;
1865:   link->interphook = interphook;
1866:   link->ctx        = ctx;
1867:   link->next       = NULL;
1868:   *p               = link;
1869:   return(0);
1870: }

1872: /*@C
1873:    DMRefineHookRemove - remove a callback from the list of hooks to be run when interpolating a nonlinear problem to a finer grid

1875:    Logically Collective

1877:    Input Arguments:
1878: +  coarse - nonlinear solver context on which to run a hook when restricting to a coarser level
1879: .  refinehook - function to run when setting up a coarser level
1880: .  interphook - function to run to update data on finer levels (once per SNESSolve())
1881: -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)

1883:    Level: advanced

1885:    Notes:
1886:    This function does nothing if the hook is not in the list.

1888:    This function is currently not available from Fortran.

1890: .seealso: DMCoarsenHookRemove(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1891: @*/
1892: PetscErrorCode DMRefineHookRemove(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx)
1893: {
1894:   PetscErrorCode   ierr;
1895:   DMRefineHookLink link,*p;

1899:   for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Search the list of current hooks */
1900:     if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) {
1901:       link = *p;
1902:       *p = link->next;
1903:       PetscFree(link);
1904:       break;
1905:     }
1906:   }
1907:   return(0);
1908: }

1910: /*@
1911:    DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd()

1913:    Collective if any hooks are

1915:    Input Arguments:
1916: +  coarse - coarser DM to use as a base
1917: .  interp - interpolation matrix, apply using MatInterpolate()
1918: -  fine - finer DM to update

1920:    Level: developer

1922: .seealso: DMRefineHookAdd(), MatInterpolate()
1923: @*/
1924: PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine)
1925: {
1926:   PetscErrorCode   ierr;
1927:   DMRefineHookLink link;

1930:   for (link=fine->refinehook; link; link=link->next) {
1931:     if (link->interphook) {
1932:       (*link->interphook)(coarse,interp,fine,link->ctx);
1933:     }
1934:   }
1935:   return(0);
1936: }

1938: /*@
1939:     DMGetRefineLevel - Get's the number of refinements that have generated this DM.

1941:     Not Collective

1943:     Input Parameter:
1944: .   dm - the DM object

1946:     Output Parameter:
1947: .   level - number of refinements

1949:     Level: developer

1951: .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()

1953: @*/
1954: PetscErrorCode  DMGetRefineLevel(DM dm,PetscInt *level)
1955: {
1958:   *level = dm->levelup;
1959:   return(0);
1960: }

1962: /*@
1963:     DMSetRefineLevel - Set's the number of refinements that have generated this DM.

1965:     Not Collective

1967:     Input Parameter:
1968: +   dm - the DM object
1969: -   level - number of refinements

1971:     Level: advanced

1973:     Notes: This value is used by PCMG to determine how many multigrid levels to use

1975: .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()

1977: @*/
1978: PetscErrorCode  DMSetRefineLevel(DM dm,PetscInt level)
1979: {
1982:   dm->levelup = level;
1983:   return(0);
1984: }

1986: /*@C
1987:    DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called

1989:    Logically Collective

1991:    Input Arguments:
1992: +  dm - the DM
1993: .  beginhook - function to run at the beginning of DMGlobalToLocalBegin()
1994: .  endhook - function to run after DMGlobalToLocalEnd() has completed
1995: -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)

1997:    Calling sequence for beginhook:
1998: $    beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)

2000: +  dm - global DM
2001: .  g - global vector
2002: .  mode - mode
2003: .  l - local vector
2004: -  ctx - optional user-defined function context


2007:    Calling sequence for endhook:
2008: $    endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)

2010: +  global - global DM
2011: -  ctx - optional user-defined function context

2013:    Level: advanced

2015: .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2016: @*/
2017: PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx)
2018: {
2019:   PetscErrorCode          ierr;
2020:   DMGlobalToLocalHookLink link,*p;

2024:   for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2025:   PetscNew(&link);
2026:   link->beginhook = beginhook;
2027:   link->endhook   = endhook;
2028:   link->ctx       = ctx;
2029:   link->next      = NULL;
2030:   *p              = link;
2031:   return(0);
2032: }

2034: static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx)
2035: {
2036:   Mat cMat;
2037:   Vec cVec;
2038:   PetscSection section, cSec;
2039:   PetscInt pStart, pEnd, p, dof;

2044:   DMGetDefaultConstraints(dm,&cSec,&cMat);
2045:   if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) {
2046:     PetscInt nRows;

2048:     MatGetSize(cMat,&nRows,NULL);
2049:     if (nRows <= 0) return(0);
2050:     DMGetDefaultSection(dm,&section);
2051:     MatCreateVecs(cMat,NULL,&cVec);
2052:     MatMult(cMat,l,cVec);
2053:     PetscSectionGetChart(cSec,&pStart,&pEnd);
2054:     for (p = pStart; p < pEnd; p++) {
2055:       PetscSectionGetDof(cSec,p,&dof);
2056:       if (dof) {
2057:         PetscScalar *vals;
2058:         VecGetValuesSection(cVec,cSec,p,&vals);
2059:         VecSetValuesSection(l,section,p,vals,INSERT_ALL_VALUES);
2060:       }
2061:     }
2062:     VecDestroy(&cVec);
2063:   }
2064:   return(0);
2065: }

2067: /*@
2068:     DMGlobalToLocalBegin - Begins updating local vectors from global vector

2070:     Neighbor-wise Collective on DM

2072:     Input Parameters:
2073: +   dm - the DM object
2074: .   g - the global vector
2075: .   mode - INSERT_VALUES or ADD_VALUES
2076: -   l - the local vector


2079:     Level: beginner

2081: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()

2083: @*/
2084: PetscErrorCode  DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
2085: {
2086:   PetscSF                 sf;
2087:   PetscErrorCode          ierr;
2088:   DMGlobalToLocalHookLink link;

2092:   for (link=dm->gtolhook; link; link=link->next) {
2093:     if (link->beginhook) {
2094:       (*link->beginhook)(dm,g,mode,l,link->ctx);
2095:     }
2096:   }
2097:   DMGetDefaultSF(dm, &sf);
2098:   if (sf) {
2099:     const PetscScalar *gArray;
2100:     PetscScalar       *lArray;

2102:     if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2103:     VecGetArray(l, &lArray);
2104:     VecGetArrayRead(g, &gArray);
2105:     PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);
2106:     VecRestoreArray(l, &lArray);
2107:     VecRestoreArrayRead(g, &gArray);
2108:   } else {
2109:     (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
2110:   }
2111:   return(0);
2112: }

2114: /*@
2115:     DMGlobalToLocalEnd - Ends updating local vectors from global vector

2117:     Neighbor-wise Collective on DM

2119:     Input Parameters:
2120: +   dm - the DM object
2121: .   g - the global vector
2122: .   mode - INSERT_VALUES or ADD_VALUES
2123: -   l - the local vector


2126:     Level: beginner

2128: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()

2130: @*/
2131: PetscErrorCode  DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
2132: {
2133:   PetscSF                 sf;
2134:   PetscErrorCode          ierr;
2135:   const PetscScalar      *gArray;
2136:   PetscScalar            *lArray;
2137:   DMGlobalToLocalHookLink link;

2141:   DMGetDefaultSF(dm, &sf);
2142:   if (sf) {
2143:     if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);

2145:     VecGetArray(l, &lArray);
2146:     VecGetArrayRead(g, &gArray);
2147:     PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);
2148:     VecRestoreArray(l, &lArray);
2149:     VecRestoreArrayRead(g, &gArray);
2150:   } else {
2151:     (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
2152:   }
2153:   DMGlobalToLocalHook_Constraints(dm,g,mode,l,NULL);
2154:   for (link=dm->gtolhook; link; link=link->next) {
2155:     if (link->endhook) {(*link->endhook)(dm,g,mode,l,link->ctx);}
2156:   }
2157:   return(0);
2158: }

2160: /*@C
2161:    DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called

2163:    Logically Collective

2165:    Input Arguments:
2166: +  dm - the DM
2167: .  beginhook - function to run at the beginning of DMLocalToGlobalBegin()
2168: .  endhook - function to run after DMLocalToGlobalEnd() has completed
2169: -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)

2171:    Calling sequence for beginhook:
2172: $    beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)

2174: +  dm - global DM
2175: .  l - local vector
2176: .  mode - mode
2177: .  g - global vector
2178: -  ctx - optional user-defined function context


2181:    Calling sequence for endhook:
2182: $    endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)

2184: +  global - global DM
2185: .  l - local vector
2186: .  mode - mode
2187: .  g - global vector
2188: -  ctx - optional user-defined function context

2190:    Level: advanced

2192: .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2193: @*/
2194: PetscErrorCode DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx)
2195: {
2196:   PetscErrorCode          ierr;
2197:   DMLocalToGlobalHookLink link,*p;

2201:   for (p=&dm->ltoghook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2202:   PetscNew(&link);
2203:   link->beginhook = beginhook;
2204:   link->endhook   = endhook;
2205:   link->ctx       = ctx;
2206:   link->next      = NULL;
2207:   *p              = link;
2208:   return(0);
2209: }

2211: static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx)
2212: {
2213:   Mat cMat;
2214:   Vec cVec;
2215:   PetscSection section, cSec;
2216:   PetscInt pStart, pEnd, p, dof;

2221:   DMGetDefaultConstraints(dm,&cSec,&cMat);
2222:   if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) {
2223:     PetscInt nRows;

2225:     MatGetSize(cMat,&nRows,NULL);
2226:     if (nRows <= 0) return(0);
2227:     DMGetDefaultSection(dm,&section);
2228:     MatCreateVecs(cMat,NULL,&cVec);
2229:     PetscSectionGetChart(cSec,&pStart,&pEnd);
2230:     for (p = pStart; p < pEnd; p++) {
2231:       PetscSectionGetDof(cSec,p,&dof);
2232:       if (dof) {
2233:         PetscInt d;
2234:         PetscScalar *vals;
2235:         VecGetValuesSection(l,section,p,&vals);
2236:         VecSetValuesSection(cVec,cSec,p,vals,mode);
2237:         /* for this to be the true transpose, we have to zero the values that
2238:          * we just extracted */
2239:         for (d = 0; d < dof; d++) {
2240:           vals[d] = 0.;
2241:         }
2242:       }
2243:     }
2244:     MatMultTransposeAdd(cMat,cVec,l,l);
2245:     VecDestroy(&cVec);
2246:   }
2247:   return(0);
2248: }

2250: /*@
2251:     DMLocalToGlobalBegin - updates global vectors from local vectors

2253:     Neighbor-wise Collective on DM

2255:     Input Parameters:
2256: +   dm - the DM object
2257: .   l - the local vector
2258: .   mode - if INSERT_VALUES then no parallel communication is used, if ADD_VALUES then all ghost points from the same base point accumulate into that base point.
2259: -   g - the global vector

2261:     Notes: In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation.
2262:            INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one.

2264:     Level: beginner

2266: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin()

2268: @*/
2269: PetscErrorCode  DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g)
2270: {
2271:   PetscSF                 sf;
2272:   PetscSection            s, gs;
2273:   DMLocalToGlobalHookLink link;
2274:   const PetscScalar      *lArray;
2275:   PetscScalar            *gArray;
2276:   PetscBool               isInsert;
2277:   PetscErrorCode          ierr;

2281:   for (link=dm->ltoghook; link; link=link->next) {
2282:     if (link->beginhook) {
2283:       (*link->beginhook)(dm,l,mode,g,link->ctx);
2284:     }
2285:   }
2286:   DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);
2287:   DMGetDefaultSF(dm, &sf);
2288:   DMGetDefaultSection(dm, &s);
2289:   switch (mode) {
2290:   case INSERT_VALUES:
2291:   case INSERT_ALL_VALUES:
2292:   case INSERT_BC_VALUES:
2293:     isInsert = PETSC_TRUE; break;
2294:   case ADD_VALUES:
2295:   case ADD_ALL_VALUES:
2296:   case ADD_BC_VALUES:
2297:     isInsert = PETSC_FALSE; break;
2298:   default:
2299:     SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2300:   }
2301:   if (sf && !isInsert) {
2302:     VecGetArrayRead(l, &lArray);
2303:     VecGetArray(g, &gArray);
2304:     PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);
2305:     VecRestoreArrayRead(l, &lArray);
2306:     VecRestoreArray(g, &gArray);
2307:   } else if (s && isInsert) {
2308:     PetscInt gStart, pStart, pEnd, p;

2310:     DMGetDefaultGlobalSection(dm, &gs);
2311:     PetscSectionGetChart(s, &pStart, &pEnd);
2312:     VecGetOwnershipRange(g, &gStart, NULL);
2313:     VecGetArrayRead(l, &lArray);
2314:     VecGetArray(g, &gArray);
2315:     for (p = pStart; p < pEnd; ++p) {
2316:       PetscInt dof, gdof, cdof, gcdof, off, goff, d, e;

2318:       PetscSectionGetDof(s, p, &dof);
2319:       PetscSectionGetDof(gs, p, &gdof);
2320:       PetscSectionGetConstraintDof(s, p, &cdof);
2321:       PetscSectionGetConstraintDof(gs, p, &gcdof);
2322:       PetscSectionGetOffset(s, p, &off);
2323:       PetscSectionGetOffset(gs, p, &goff);
2324:       /* Ignore off-process data and points with no global data */
2325:       if (!gdof || goff < 0) continue;
2326:       if (dof != gdof) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof);
2327:       /* If no constraints are enforced in the global vector */
2328:       if (!gcdof) {
2329:         for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d];
2330:       /* If constraints are enforced in the global vector */
2331:       } else if (cdof == gcdof) {
2332:         const PetscInt *cdofs;
2333:         PetscInt        cind = 0;

2335:         PetscSectionGetConstraintIndices(s, p, &cdofs);
2336:         for (d = 0, e = 0; d < dof; ++d) {
2337:           if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;}
2338:           gArray[goff-gStart+e++] = lArray[off+d];
2339:         }
2340:       } else SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof);
2341:     }
2342:     VecRestoreArrayRead(l, &lArray);
2343:     VecRestoreArray(g, &gArray);
2344:   } else {
2345:     (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);
2346:   }
2347:   return(0);
2348: }

2350: /*@
2351:     DMLocalToGlobalEnd - updates global vectors from local vectors

2353:     Neighbor-wise Collective on DM

2355:     Input Parameters:
2356: +   dm - the DM object
2357: .   l - the local vector
2358: .   mode - INSERT_VALUES or ADD_VALUES
2359: -   g - the global vector


2362:     Level: beginner

2364: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd()

2366: @*/
2367: PetscErrorCode  DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g)
2368: {
2369:   PetscSF                 sf;
2370:   PetscSection            s;
2371:   DMLocalToGlobalHookLink link;
2372:   PetscBool               isInsert;
2373:   PetscErrorCode          ierr;

2377:   DMGetDefaultSF(dm, &sf);
2378:   DMGetDefaultSection(dm, &s);
2379:   switch (mode) {
2380:   case INSERT_VALUES:
2381:   case INSERT_ALL_VALUES:
2382:     isInsert = PETSC_TRUE; break;
2383:   case ADD_VALUES:
2384:   case ADD_ALL_VALUES:
2385:     isInsert = PETSC_FALSE; break;
2386:   default:
2387:     SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2388:   }
2389:   if (sf && !isInsert) {
2390:     const PetscScalar *lArray;
2391:     PetscScalar       *gArray;

2393:     VecGetArrayRead(l, &lArray);
2394:     VecGetArray(g, &gArray);
2395:     PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);
2396:     VecRestoreArrayRead(l, &lArray);
2397:     VecRestoreArray(g, &gArray);
2398:   } else if (s && isInsert) {
2399:   } else {
2400:     (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);
2401:   }
2402:   for (link=dm->ltoghook; link; link=link->next) {
2403:     if (link->endhook) {(*link->endhook)(dm,g,mode,l,link->ctx);}
2404:   }
2405:   return(0);
2406: }

2408: /*@
2409:    DMLocalToLocalBegin - Maps from a local vector (including ghost points
2410:    that contain irrelevant values) to another local vector where the ghost
2411:    points in the second are set correctly. Must be followed by DMLocalToLocalEnd().

2413:    Neighbor-wise Collective on DM and Vec

2415:    Input Parameters:
2416: +  dm - the DM object
2417: .  g - the original local vector
2418: -  mode - one of INSERT_VALUES or ADD_VALUES

2420:    Output Parameter:
2421: .  l  - the local vector with correct ghost values

2423:    Level: intermediate

2425:    Notes:
2426:    The local vectors used here need not be the same as those
2427:    obtained from DMCreateLocalVector(), BUT they
2428:    must have the same parallel data layout; they could, for example, be
2429:    obtained with VecDuplicate() from the DM originating vectors.

2431: .keywords: DM, local-to-local, begin
2432: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()

2434: @*/
2435: PetscErrorCode  DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
2436: {
2437:   PetscErrorCode          ierr;

2441:   if (!dm->ops->localtolocalbegin) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps");
2442:   (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
2443:   return(0);
2444: }

2446: /*@
2447:    DMLocalToLocalEnd - Maps from a local vector (including ghost points
2448:    that contain irrelevant values) to another local vector where the ghost
2449:    points in the second are set correctly. Must be preceded by DMLocalToLocalBegin().

2451:    Neighbor-wise Collective on DM and Vec

2453:    Input Parameters:
2454: +  da - the DM object
2455: .  g - the original local vector
2456: -  mode - one of INSERT_VALUES or ADD_VALUES

2458:    Output Parameter:
2459: .  l  - the local vector with correct ghost values

2461:    Level: intermediate

2463:    Notes:
2464:    The local vectors used here need not be the same as those
2465:    obtained from DMCreateLocalVector(), BUT they
2466:    must have the same parallel data layout; they could, for example, be
2467:    obtained with VecDuplicate() from the DM originating vectors.

2469: .keywords: DM, local-to-local, end
2470: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()

2472: @*/
2473: PetscErrorCode  DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
2474: {
2475:   PetscErrorCode          ierr;

2479:   if (!dm->ops->localtolocalend) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps");
2480:   (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
2481:   return(0);
2482: }


2485: /*@
2486:     DMCoarsen - Coarsens a DM object

2488:     Collective on DM

2490:     Input Parameter:
2491: +   dm - the DM object
2492: -   comm - the communicator to contain the new DM object (or MPI_COMM_NULL)

2494:     Output Parameter:
2495: .   dmc - the coarsened DM

2497:     Level: developer

2499: .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()

2501: @*/
2502: PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
2503: {
2504:   PetscErrorCode    ierr;
2505:   DMCoarsenHookLink link;

2509:   if (!dm->ops->coarsen) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM cannot coarsen");
2510:   PetscLogEventBegin(DM_Coarsen,dm,0,0,0);
2511:   (*dm->ops->coarsen)(dm, comm, dmc);
2512:   if (!(*dmc)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced");
2513:   DMSetCoarseDM(dm,*dmc);
2514:   (*dmc)->ops->creatematrix = dm->ops->creatematrix;
2515:   PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);
2516:   (*dmc)->ctx               = dm->ctx;
2517:   (*dmc)->levelup           = dm->levelup;
2518:   (*dmc)->leveldown         = dm->leveldown + 1;
2519:   DMSetMatType(*dmc,dm->mattype);
2520:   for (link=dm->coarsenhook; link; link=link->next) {
2521:     if (link->coarsenhook) {(*link->coarsenhook)(dm,*dmc,link->ctx);}
2522:   }
2523:   PetscLogEventEnd(DM_Coarsen,dm,0,0,0);
2524:   return(0);
2525: }

2527: /*@C
2528:    DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid

2530:    Logically Collective

2532:    Input Arguments:
2533: +  fine - nonlinear solver context on which to run a hook when restricting to a coarser level
2534: .  coarsenhook - function to run when setting up a coarser level
2535: .  restricthook - function to run to update data on coarser levels (once per SNESSolve())
2536: -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)

2538:    Calling sequence of coarsenhook:
2539: $    coarsenhook(DM fine,DM coarse,void *ctx);

2541: +  fine - fine level DM
2542: .  coarse - coarse level DM to restrict problem to
2543: -  ctx - optional user-defined function context

2545:    Calling sequence for restricthook:
2546: $    restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx)

2548: +  fine - fine level DM
2549: .  mrestrict - matrix restricting a fine-level solution to the coarse grid
2550: .  rscale - scaling vector for restriction
2551: .  inject - matrix restricting by injection
2552: .  coarse - coarse level DM to update
2553: -  ctx - optional user-defined function context

2555:    Level: advanced

2557:    Notes:
2558:    This function is only needed if auxiliary data needs to be set up on coarse grids.

2560:    If this function is called multiple times, the hooks will be run in the order they are added.

2562:    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
2563:    extract the finest level information from its context (instead of from the SNES).

2565:    This function is currently not available from Fortran.

2567: .seealso: DMCoarsenHookRemove(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2568: @*/
2569: PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx)
2570: {
2571:   PetscErrorCode    ierr;
2572:   DMCoarsenHookLink link,*p;

2576:   for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */
2577:     if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) return(0);
2578:   }
2579:   PetscNew(&link);
2580:   link->coarsenhook  = coarsenhook;
2581:   link->restricthook = restricthook;
2582:   link->ctx          = ctx;
2583:   link->next         = NULL;
2584:   *p                 = link;
2585:   return(0);
2586: }

2588: /*@C
2589:    DMCoarsenHookRemove - remove a callback from the list of hooks to be run when restricting a nonlinear problem to the coarse grid

2591:    Logically Collective

2593:    Input Arguments:
2594: +  fine - nonlinear solver context on which to run a hook when restricting to a coarser level
2595: .  coarsenhook - function to run when setting up a coarser level
2596: .  restricthook - function to run to update data on coarser levels (once per SNESSolve())
2597: -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)

2599:    Level: advanced

2601:    Notes:
2602:    This function does nothing if the hook is not in the list.

2604:    This function is currently not available from Fortran.

2606: .seealso: DMCoarsenHookAdd(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2607: @*/
2608: PetscErrorCode DMCoarsenHookRemove(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx)
2609: {
2610:   PetscErrorCode    ierr;
2611:   DMCoarsenHookLink link,*p;

2615:   for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Search the list of current hooks */
2616:     if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
2617:       link = *p;
2618:       *p = link->next;
2619:       PetscFree(link);
2620:       break;
2621:     }
2622:   }
2623:   return(0);
2624: }


2627: /*@
2628:    DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd()

2630:    Collective if any hooks are

2632:    Input Arguments:
2633: +  fine - finer DM to use as a base
2634: .  restrct - restriction matrix, apply using MatRestrict()
2635: .  rscale - scaling vector for restriction
2636: .  inject - injection matrix, also use MatRestrict()
2637: -  coarse - coarser DM to update

2639:    Level: developer

2641: .seealso: DMCoarsenHookAdd(), MatRestrict()
2642: @*/
2643: PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse)
2644: {
2645:   PetscErrorCode    ierr;
2646:   DMCoarsenHookLink link;

2649:   for (link=fine->coarsenhook; link; link=link->next) {
2650:     if (link->restricthook) {
2651:       (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);
2652:     }
2653:   }
2654:   return(0);
2655: }

2657: /*@C
2658:    DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid

2660:    Logically Collective

2662:    Input Arguments:
2663: +  global - global DM
2664: .  ddhook - function to run to pass data to the decomposition DM upon its creation
2665: .  restricthook - function to run to update data on block solve (at the beginning of the block solve)
2666: -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)


2669:    Calling sequence for ddhook:
2670: $    ddhook(DM global,DM block,void *ctx)

2672: +  global - global DM
2673: .  block  - block DM
2674: -  ctx - optional user-defined function context

2676:    Calling sequence for restricthook:
2677: $    restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx)

2679: +  global - global DM
2680: .  out    - scatter to the outer (with ghost and overlap points) block vector
2681: .  in     - scatter to block vector values only owned locally
2682: .  block  - block DM
2683: -  ctx - optional user-defined function context

2685:    Level: advanced

2687:    Notes:
2688:    This function is only needed if auxiliary data needs to be set up on subdomain DMs.

2690:    If this function is called multiple times, the hooks will be run in the order they are added.

2692:    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
2693:    extract the global information from its context (instead of from the SNES).

2695:    This function is currently not available from Fortran.

2697: .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2698: @*/
2699: PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx)
2700: {
2701:   PetscErrorCode      ierr;
2702:   DMSubDomainHookLink link,*p;

2706:   for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */
2707:     if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) return(0);
2708:   }
2709:   PetscNew(&link);
2710:   link->restricthook = restricthook;
2711:   link->ddhook       = ddhook;
2712:   link->ctx          = ctx;
2713:   link->next         = NULL;
2714:   *p                 = link;
2715:   return(0);
2716: }

2718: /*@C
2719:    DMSubDomainHookRemove - remove a callback from the list to be run when restricting a problem to the coarse grid

2721:    Logically Collective

2723:    Input Arguments:
2724: +  global - global DM
2725: .  ddhook - function to run to pass data to the decomposition DM upon its creation
2726: .  restricthook - function to run to update data on block solve (at the beginning of the block solve)
2727: -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)

2729:    Level: advanced

2731:    Notes:

2733:    This function is currently not available from Fortran.

2735: .seealso: DMSubDomainHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2736: @*/
2737: PetscErrorCode DMSubDomainHookRemove(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx)
2738: {
2739:   PetscErrorCode      ierr;
2740:   DMSubDomainHookLink link,*p;

2744:   for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Search the list of current hooks */
2745:     if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
2746:       link = *p;
2747:       *p = link->next;
2748:       PetscFree(link);
2749:       break;
2750:     }
2751:   }
2752:   return(0);
2753: }

2755: /*@
2756:    DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd()

2758:    Collective if any hooks are

2760:    Input Arguments:
2761: +  fine - finer DM to use as a base
2762: .  oscatter - scatter from domain global vector filling subdomain global vector with overlap
2763: .  gscatter - scatter from domain global vector filling subdomain local vector with ghosts
2764: -  coarse - coarer DM to update

2766:    Level: developer

2768: .seealso: DMCoarsenHookAdd(), MatRestrict()
2769: @*/
2770: PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm)
2771: {
2772:   PetscErrorCode      ierr;
2773:   DMSubDomainHookLink link;

2776:   for (link=global->subdomainhook; link; link=link->next) {
2777:     if (link->restricthook) {
2778:       (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);
2779:     }
2780:   }
2781:   return(0);
2782: }

2784: /*@
2785:     DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM.

2787:     Not Collective

2789:     Input Parameter:
2790: .   dm - the DM object

2792:     Output Parameter:
2793: .   level - number of coarsenings

2795:     Level: developer

2797: .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()

2799: @*/
2800: PetscErrorCode  DMGetCoarsenLevel(DM dm,PetscInt *level)
2801: {
2804:   *level = dm->leveldown;
2805:   return(0);
2806: }



2810: /*@C
2811:     DMRefineHierarchy - Refines a DM object, all levels at once

2813:     Collective on DM

2815:     Input Parameter:
2816: +   dm - the DM object
2817: -   nlevels - the number of levels of refinement

2819:     Output Parameter:
2820: .   dmf - the refined DM hierarchy

2822:     Level: developer

2824: .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()

2826: @*/
2827: PetscErrorCode  DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[])
2828: {

2833:   if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
2834:   if (nlevels == 0) return(0);
2835:   if (dm->ops->refinehierarchy) {
2836:     (*dm->ops->refinehierarchy)(dm,nlevels,dmf);
2837:   } else if (dm->ops->refine) {
2838:     PetscInt i;

2840:     DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);
2841:     for (i=1; i<nlevels; i++) {
2842:       DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);
2843:     }
2844:   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet");
2845:   return(0);
2846: }

2848: /*@C
2849:     DMCoarsenHierarchy - Coarsens a DM object, all levels at once

2851:     Collective on DM

2853:     Input Parameter:
2854: +   dm - the DM object
2855: -   nlevels - the number of levels of coarsening

2857:     Output Parameter:
2858: .   dmc - the coarsened DM hierarchy

2860:     Level: developer

2862: .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()

2864: @*/
2865: PetscErrorCode  DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
2866: {

2871:   if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
2872:   if (nlevels == 0) return(0);
2874:   if (dm->ops->coarsenhierarchy) {
2875:     (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);
2876:   } else if (dm->ops->coarsen) {
2877:     PetscInt i;

2879:     DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);
2880:     for (i=1; i<nlevels; i++) {
2881:       DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);
2882:     }
2883:   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet");
2884:   return(0);
2885: }

2887: /*@
2888:    DMCreateAggregates - Gets the aggregates that map between
2889:    grids associated with two DMs.

2891:    Collective on DM

2893:    Input Parameters:
2894: +  dmc - the coarse grid DM
2895: -  dmf - the fine grid DM

2897:    Output Parameters:
2898: .  rest - the restriction matrix (transpose of the projection matrix)

2900:    Level: intermediate

2902: .keywords: interpolation, restriction, multigrid

2904: .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation()
2905: @*/
2906: PetscErrorCode  DMCreateAggregates(DM dmc, DM dmf, Mat *rest)
2907: {

2913:   (*dmc->ops->getaggregates)(dmc, dmf, rest);
2914:   return(0);
2915: }

2917: /*@C
2918:     DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed

2920:     Not Collective

2922:     Input Parameters:
2923: +   dm - the DM object
2924: -   destroy - the destroy function

2926:     Level: intermediate

2928: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()

2930: @*/
2931: PetscErrorCode  DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**))
2932: {
2935:   dm->ctxdestroy = destroy;
2936:   return(0);
2937: }

2939: /*@
2940:     DMSetApplicationContext - Set a user context into a DM object

2942:     Not Collective

2944:     Input Parameters:
2945: +   dm - the DM object
2946: -   ctx - the user context

2948:     Level: intermediate

2950: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()

2952: @*/
2953: PetscErrorCode  DMSetApplicationContext(DM dm,void *ctx)
2954: {
2957:   dm->ctx = ctx;
2958:   return(0);
2959: }

2961: /*@
2962:     DMGetApplicationContext - Gets a user context from a DM object

2964:     Not Collective

2966:     Input Parameter:
2967: .   dm - the DM object

2969:     Output Parameter:
2970: .   ctx - the user context

2972:     Level: intermediate

2974: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()

2976: @*/
2977: PetscErrorCode  DMGetApplicationContext(DM dm,void *ctx)
2978: {
2981:   *(void**)ctx = dm->ctx;
2982:   return(0);
2983: }

2985: /*@C
2986:     DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI.

2988:     Logically Collective on DM

2990:     Input Parameter:
2991: +   dm - the DM object
2992: -   f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set)

2994:     Level: intermediate

2996: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(),
2997:          DMSetJacobian()

2999: @*/
3000: PetscErrorCode  DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec))
3001: {
3003:   dm->ops->computevariablebounds = f;
3004:   return(0);
3005: }

3007: /*@
3008:     DMHasVariableBounds - does the DM object have a variable bounds function?

3010:     Not Collective

3012:     Input Parameter:
3013: .   dm - the DM object to destroy

3015:     Output Parameter:
3016: .   flg - PETSC_TRUE if the variable bounds function exists

3018:     Level: developer

3020: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()

3022: @*/
3023: PetscErrorCode  DMHasVariableBounds(DM dm,PetscBool  *flg)
3024: {
3026:   *flg =  (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE;
3027:   return(0);
3028: }

3030: /*@C
3031:     DMComputeVariableBounds - compute variable bounds used by SNESVI.

3033:     Logically Collective on DM

3035:     Input Parameters:
3036: .   dm - the DM object

3038:     Output parameters:
3039: +   xl - lower bound
3040: -   xu - upper bound

3042:     Level: advanced

3044:     Notes: This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds()

3046: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()

3048: @*/
3049: PetscErrorCode  DMComputeVariableBounds(DM dm, Vec xl, Vec xu)
3050: {

3056:   if (dm->ops->computevariablebounds) {
3057:     (*dm->ops->computevariablebounds)(dm, xl,xu);
3058:   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds.");
3059:   return(0);
3060: }

3062: /*@
3063:     DMHasColoring - does the DM object have a method of providing a coloring?

3065:     Not Collective

3067:     Input Parameter:
3068: .   dm - the DM object

3070:     Output Parameter:
3071: .   flg - PETSC_TRUE if the DM has facilities for DMCreateColoring().

3073:     Level: developer

3075: .seealso DMHasFunction(), DMCreateColoring()

3077: @*/
3078: PetscErrorCode  DMHasColoring(DM dm,PetscBool  *flg)
3079: {
3081:   *flg =  (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE;
3082:   return(0);
3083: }

3085: /*@
3086:     DMHasCreateRestriction - does the DM object have a method of providing a restriction?

3088:     Not Collective

3090:     Input Parameter:
3091: .   dm - the DM object

3093:     Output Parameter:
3094: .   flg - PETSC_TRUE if the DM has facilities for DMCreateRestriction().

3096:     Level: developer

3098: .seealso DMHasFunction(), DMCreateRestriction()

3100: @*/
3101: PetscErrorCode  DMHasCreateRestriction(DM dm,PetscBool  *flg)
3102: {
3104:   *flg =  (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE;
3105:   return(0);
3106: }


3109: /*@
3110:     DMHasCreateInjection - does the DM object have a method of providing an injection?

3112:     Not Collective

3114:     Input Parameter:
3115: .   dm - the DM object

3117:     Output Parameter:
3118: .   flg - PETSC_TRUE if the DM has facilities for DMCreateInjection().

3120:     Level: developer

3122: .seealso DMHasFunction(), DMCreateInjection()

3124: @*/
3125: PetscErrorCode  DMHasCreateInjection(DM dm,PetscBool  *flg)
3126: {
3129:   if (!dm->ops->hascreateinjection) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DMHasCreateInjection not implemented for this type");
3130:   (*dm->ops->hascreateinjection)(dm,flg);
3131:   return(0);
3132: }

3134: /*@C
3135:     DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear.

3137:     Collective on DM

3139:     Input Parameter:
3140: +   dm - the DM object
3141: -   x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems.

3143:     Level: developer

3145: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()

3147: @*/
3148: PetscErrorCode  DMSetVec(DM dm,Vec x)
3149: {

3153:   if (x) {
3154:     if (!dm->x) {
3155:       DMCreateGlobalVector(dm,&dm->x);
3156:     }
3157:     VecCopy(x,dm->x);
3158:   } else if (dm->x) {
3159:     VecDestroy(&dm->x);
3160:   }
3161:   return(0);
3162: }

3164: PetscFunctionList DMList              = NULL;
3165: PetscBool         DMRegisterAllCalled = PETSC_FALSE;

3167: /*@C
3168:   DMSetType - Builds a DM, for a particular DM implementation.

3170:   Collective on DM

3172:   Input Parameters:
3173: + dm     - The DM object
3174: - method - The name of the DM type

3176:   Options Database Key:
3177: . -dm_type <type> - Sets the DM type; use -help for a list of available types

3179:   Notes:
3180:   See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D).

3182:   Level: intermediate

3184: .keywords: DM, set, type
3185: .seealso: DMGetType(), DMCreate()
3186: @*/
3187: PetscErrorCode  DMSetType(DM dm, DMType method)
3188: {
3189:   PetscErrorCode (*r)(DM);
3190:   PetscBool      match;

3195:   PetscObjectTypeCompare((PetscObject) dm, method, &match);
3196:   if (match) return(0);

3198:   DMRegisterAll();
3199:   PetscFunctionListFind(DMList,method,&r);
3200:   if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);

3202:   if (dm->ops->destroy) {
3203:     (*dm->ops->destroy)(dm);
3204:     dm->ops->destroy = NULL;
3205:   }
3206:   (*r)(dm);
3207:   PetscObjectChangeTypeName((PetscObject)dm,method);
3208:   return(0);
3209: }

3211: /*@C
3212:   DMGetType - Gets the DM type name (as a string) from the DM.

3214:   Not Collective

3216:   Input Parameter:
3217: . dm  - The DM

3219:   Output Parameter:
3220: . type - The DM type name

3222:   Level: intermediate

3224: .keywords: DM, get, type, name
3225: .seealso: DMSetType(), DMCreate()
3226: @*/
3227: PetscErrorCode  DMGetType(DM dm, DMType *type)
3228: {

3234:   DMRegisterAll();
3235:   *type = ((PetscObject)dm)->type_name;
3236:   return(0);
3237: }

3239: /*@C
3240:   DMConvert - Converts a DM to another DM, either of the same or different type.

3242:   Collective on DM

3244:   Input Parameters:
3245: + dm - the DM
3246: - newtype - new DM type (use "same" for the same type)

3248:   Output Parameter:
3249: . M - pointer to new DM

3251:   Notes:
3252:   Cannot be used to convert a sequential DM to parallel or parallel to sequential,
3253:   the MPI communicator of the generated DM is always the same as the communicator
3254:   of the input DM.

3256:   Level: intermediate

3258: .seealso: DMCreate()
3259: @*/
3260: PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M)
3261: {
3262:   DM             B;
3263:   char           convname[256];
3264:   PetscBool      sametype/*, issame */;

3271:   PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);
3272:   /* PetscStrcmp(newtype, "same", &issame); */
3273:   if (sametype) {
3274:     *M   = dm;
3275:     PetscObjectReference((PetscObject) dm);
3276:     return(0);
3277:   } else {
3278:     PetscErrorCode (*conv)(DM, DMType, DM*) = NULL;

3280:     /*
3281:        Order of precedence:
3282:        1) See if a specialized converter is known to the current DM.
3283:        2) See if a specialized converter is known to the desired DM class.
3284:        3) See if a good general converter is registered for the desired class
3285:        4) See if a good general converter is known for the current matrix.
3286:        5) Use a really basic converter.
3287:     */

3289:     /* 1) See if a specialized converter is known to the current DM and the desired class */
3290:     PetscStrncpy(convname,"DMConvert_",sizeof(convname));
3291:     PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));
3292:     PetscStrlcat(convname,"_",sizeof(convname));
3293:     PetscStrlcat(convname,newtype,sizeof(convname));
3294:     PetscStrlcat(convname,"_C",sizeof(convname));
3295:     PetscObjectQueryFunction((PetscObject)dm,convname,&conv);
3296:     if (conv) goto foundconv;

3298:     /* 2)  See if a specialized converter is known to the desired DM class. */
3299:     DMCreate(PetscObjectComm((PetscObject)dm), &B);
3300:     DMSetType(B, newtype);
3301:     PetscStrncpy(convname,"DMConvert_",sizeof(convname));
3302:     PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));
3303:     PetscStrlcat(convname,"_",sizeof(convname));
3304:     PetscStrlcat(convname,newtype,sizeof(convname));
3305:     PetscStrlcat(convname,"_C",sizeof(convname));
3306:     PetscObjectQueryFunction((PetscObject)B,convname,&conv);
3307:     if (conv) {
3308:       DMDestroy(&B);
3309:       goto foundconv;
3310:     }

3312: #if 0
3313:     /* 3) See if a good general converter is registered for the desired class */
3314:     conv = B->ops->convertfrom;
3315:     DMDestroy(&B);
3316:     if (conv) goto foundconv;

3318:     /* 4) See if a good general converter is known for the current matrix */
3319:     if (dm->ops->convert) {
3320:       conv = dm->ops->convert;
3321:     }
3322:     if (conv) goto foundconv;
3323: #endif

3325:     /* 5) Use a really basic converter. */
3326:     SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype);

3328: foundconv:
3329:     PetscLogEventBegin(DM_Convert,dm,0,0,0);
3330:     (*conv)(dm,newtype,M);
3331:     /* Things that are independent of DM type: We should consult DMClone() here */
3332:     {
3333:       PetscBool             isper;
3334:       const PetscReal      *maxCell, *L;
3335:       const DMBoundaryType *bd;
3336:       DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);
3337:       DMSetPeriodicity(*M, isper, maxCell,  L,  bd);
3338:     }
3339:     PetscLogEventEnd(DM_Convert,dm,0,0,0);
3340:   }
3341:   PetscObjectStateIncrease((PetscObject) *M);
3342:   return(0);
3343: }

3345: /*--------------------------------------------------------------------------------------------------------------------*/

3347: /*@C
3348:   DMRegister -  Adds a new DM component implementation

3350:   Not Collective

3352:   Input Parameters:
3353: + name        - The name of a new user-defined creation routine
3354: - create_func - The creation routine itself

3356:   Notes:
3357:   DMRegister() may be called multiple times to add several user-defined DMs


3360:   Sample usage:
3361: .vb
3362:     DMRegister("my_da", MyDMCreate);
3363: .ve

3365:   Then, your DM type can be chosen with the procedural interface via
3366: .vb
3367:     DMCreate(MPI_Comm, DM *);
3368:     DMSetType(DM,"my_da");
3369: .ve
3370:    or at runtime via the option
3371: .vb
3372:     -da_type my_da
3373: .ve

3375:   Level: advanced

3377: .keywords: DM, register
3378: .seealso: DMRegisterAll(), DMRegisterDestroy()

3380: @*/
3381: PetscErrorCode  DMRegister(const char sname[],PetscErrorCode (*function)(DM))
3382: {

3386:   PetscFunctionListAdd(&DMList,sname,function);
3387:   return(0);
3388: }

3390: /*@C
3391:   DMLoad - Loads a DM that has been stored in binary  with DMView().

3393:   Collective on PetscViewer

3395:   Input Parameters:
3396: + newdm - the newly loaded DM, this needs to have been created with DMCreate() or
3397:            some related function before a call to DMLoad().
3398: - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or
3399:            HDF5 file viewer, obtained from PetscViewerHDF5Open()

3401:    Level: intermediate

3403:   Notes:
3404:    The type is determined by the data in the file, any type set into the DM before this call is ignored.

3406:   Notes for advanced users:
3407:   Most users should not need to know the details of the binary storage
3408:   format, since DMLoad() and DMView() completely hide these details.
3409:   But for anyone who's interested, the standard binary matrix storage
3410:   format is
3411: .vb
3412:      has not yet been determined
3413: .ve

3415: .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad()
3416: @*/
3417: PetscErrorCode  DMLoad(DM newdm, PetscViewer viewer)
3418: {
3419:   PetscBool      isbinary, ishdf5;

3425:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
3426:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);
3427:   if (isbinary) {
3428:     PetscInt classid;
3429:     char     type[256];

3431:     PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);
3432:     if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid);
3433:     PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);
3434:     DMSetType(newdm, type);
3435:     if (newdm->ops->load) {(*newdm->ops->load)(newdm,viewer);}
3436:   } else if (ishdf5) {
3437:     if (newdm->ops->load) {(*newdm->ops->load)(newdm,viewer);}
3438:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()");
3439:   return(0);
3440: }

3442: /******************************** FEM Support **********************************/

3444: PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[])
3445: {
3446:   PetscInt       f;

3450:   PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);
3451:   for (f = 0; f < len; ++f) {
3452:     PetscPrintf(PETSC_COMM_SELF, "  | %g |\n", (double)PetscRealPart(x[f]));
3453:   }
3454:   return(0);
3455: }

3457: PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[])
3458: {
3459:   PetscInt       f, g;

3463:   PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);
3464:   for (f = 0; f < rows; ++f) {
3465:     PetscPrintf(PETSC_COMM_SELF, "  |");
3466:     for (g = 0; g < cols; ++g) {
3467:       PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));
3468:     }
3469:     PetscPrintf(PETSC_COMM_SELF, " |\n");
3470:   }
3471:   return(0);
3472: }

3474: PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X)
3475: {
3476:   PetscInt          localSize, bs;
3477:   PetscMPIInt       size;
3478:   Vec               x, xglob;
3479:   const PetscScalar *xarray;
3480:   PetscErrorCode    ierr;

3483:   MPI_Comm_size(PetscObjectComm((PetscObject) dm),&size);
3484:   VecDuplicate(X, &x);
3485:   VecCopy(X, x);
3486:   VecChop(x, tol);
3487:   PetscPrintf(PetscObjectComm((PetscObject) dm),"%s:\n",name);
3488:   if (size > 1) {
3489:     VecGetLocalSize(x,&localSize);
3490:     VecGetArrayRead(x,&xarray);
3491:     VecGetBlockSize(x,&bs);
3492:     VecCreateMPIWithArray(PetscObjectComm((PetscObject) dm),bs,localSize,PETSC_DETERMINE,xarray,&xglob);
3493:   } else {
3494:     xglob = x;
3495:   }
3496:   VecView(xglob,PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject) dm)));
3497:   if (size > 1) {
3498:     VecDestroy(&xglob);
3499:     VecRestoreArrayRead(x,&xarray);
3500:   }
3501:   VecDestroy(&x);
3502:   return(0);
3503: }

3505: /*@
3506:   DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM.

3508:   Input Parameter:
3509: . dm - The DM

3511:   Output Parameter:
3512: . section - The PetscSection

3514:   Level: intermediate

3516:   Note: This gets a borrowed reference, so the user should not destroy this PetscSection.

3518: .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
3519: @*/
3520: PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section)
3521: {

3527:   if (!dm->defaultSection && dm->ops->createdefaultsection) {
3528:     (*dm->ops->createdefaultsection)(dm);
3529:     if (dm->defaultSection) {PetscObjectViewFromOptions((PetscObject) dm->defaultSection, NULL, "-dm_petscsection_view");}
3530:   }
3531:   *section = dm->defaultSection;
3532:   return(0);
3533: }

3535: /*@
3536:   DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM.

3538:   Input Parameters:
3539: + dm - The DM
3540: - section - The PetscSection

3542:   Level: intermediate

3544:   Note: Any existing Section will be destroyed

3546: .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
3547: @*/
3548: PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section)
3549: {
3550:   PetscInt       numFields = 0;
3551:   PetscInt       f;

3556:   if (section) {
3558:     PetscObjectReference((PetscObject)section);
3559:   }
3560:   PetscSectionDestroy(&dm->defaultSection);
3561:   dm->defaultSection = section;
3562:   if (section) {PetscSectionGetNumFields(dm->defaultSection, &numFields);}
3563:   if (numFields) {
3564:     DMSetNumFields(dm, numFields);
3565:     for (f = 0; f < numFields; ++f) {
3566:       PetscObject disc;
3567:       const char *name;

3569:       PetscSectionGetFieldName(dm->defaultSection, f, &name);
3570:       DMGetField(dm, f, &disc);
3571:       PetscObjectSetName(disc, name);
3572:     }
3573:   }
3574:   /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */
3575:   PetscSectionDestroy(&dm->defaultGlobalSection);
3576:   return(0);
3577: }

3579: /*@
3580:   DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation.

3582:   not collective

3584:   Input Parameter:
3585: . dm - The DM

3587:   Output Parameter:
3588: + section - The PetscSection describing the range of the constraint matrix: relates rows of the constraint matrix to dofs of the default section.  Returns NULL if there are no local constraints.
3589: - mat - The Mat that interpolates local constraints: its width should be the layout size of the default section.  Returns NULL if there are no local constraints.

3591:   Level: advanced

3593:   Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat.

3595: .seealso: DMSetDefaultConstraints()
3596: @*/
3597: PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat)
3598: {

3603:   if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {(*dm->ops->createdefaultconstraints)(dm);}
3604:   if (section) {*section = dm->defaultConstraintSection;}
3605:   if (mat) {*mat = dm->defaultConstraintMat;}
3606:   return(0);
3607: }

3609: /*@
3610:   DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation.

3612:   If a constraint matrix is specified, then it is applied during DMGlobalToLocalEnd() when mode is INSERT_VALUES, INSERT_BC_VALUES, or INSERT_ALL_VALUES.  Without a constraint matrix, the local vector l returned by DMGlobalToLocalEnd() contains values that have been scattered from a global vector without modification; with a constraint matrix A, l is modified by computing c = A * l, l[s[i]] = c[i], where the scatter s is defined by the PetscSection returned by DMGetDefaultConstraintMatrix().

3614:   If a constraint matrix is specified, then its adjoint is applied during DMLocalToGlobalBegin() when mode is ADD_VALUES, ADD_BC_VALUES, or ADD_ALL_VALUES.  Without a constraint matrix, the local vector l is accumulated into a global vector without modification; with a constraint matrix A, l is first modified by computing c[i] = l[s[i]], l[s[i]] = 0, l = l + A'*c, which is the adjoint of the operation described above.

3616:   collective on dm

3618:   Input Parameters:
3619: + dm - The DM
3620: + section - The PetscSection describing the range of the constraint matrix: relates rows of the constraint matrix to dofs of the default section.  Must have a local communicator (PETSC_COMM_SELF or derivative).
3621: - mat - The Mat that interpolates local constraints: its width should be the layout size of the default section:  NULL indicates no constraints.  Must have a local communicator (PETSC_COMM_SELF or derivative).

3623:   Level: advanced

3625:   Note: This increments the references of the PetscSection and the Mat, so they user can destroy them

3627: .seealso: DMGetDefaultConstraints()
3628: @*/
3629: PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat)
3630: {
3631:   PetscMPIInt result;

3636:   if (section) {
3638:     MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);
3639:     if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator");
3640:   }
3641:   if (mat) {
3643:     MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);
3644:     if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator");
3645:   }
3646:   PetscObjectReference((PetscObject)section);
3647:   PetscSectionDestroy(&dm->defaultConstraintSection);
3648:   dm->defaultConstraintSection = section;
3649:   PetscObjectReference((PetscObject)mat);
3650:   MatDestroy(&dm->defaultConstraintMat);
3651:   dm->defaultConstraintMat = mat;
3652:   return(0);
3653: }

3655: #ifdef PETSC_USE_DEBUG
3656: /*
3657:   DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections.

3659:   Input Parameters:
3660: + dm - The DM
3661: . localSection - PetscSection describing the local data layout
3662: - globalSection - PetscSection describing the global data layout

3664:   Level: intermediate

3666: .seealso: DMGetDefaultSF(), DMSetDefaultSF()
3667: */
3668: static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection)
3669: {
3670:   MPI_Comm        comm;
3671:   PetscLayout     layout;
3672:   const PetscInt *ranges;
3673:   PetscInt        pStart, pEnd, p, nroots;
3674:   PetscMPIInt     size, rank;
3675:   PetscBool       valid = PETSC_TRUE, gvalid;
3676:   PetscErrorCode  ierr;

3679:   PetscObjectGetComm((PetscObject)dm,&comm);
3681:   MPI_Comm_size(comm, &size);
3682:   MPI_Comm_rank(comm, &rank);
3683:   PetscSectionGetChart(globalSection, &pStart, &pEnd);
3684:   PetscSectionGetConstrainedStorageSize(globalSection, &nroots);
3685:   PetscLayoutCreate(comm, &layout);
3686:   PetscLayoutSetBlockSize(layout, 1);
3687:   PetscLayoutSetLocalSize(layout, nroots);
3688:   PetscLayoutSetUp(layout);
3689:   PetscLayoutGetRanges(layout, &ranges);
3690:   for (p = pStart; p < pEnd; ++p) {
3691:     PetscInt       dof, cdof, off, gdof, gcdof, goff, gsize, d;

3693:     PetscSectionGetDof(localSection, p, &dof);
3694:     PetscSectionGetOffset(localSection, p, &off);
3695:     PetscSectionGetConstraintDof(localSection, p, &cdof);
3696:     PetscSectionGetDof(globalSection, p, &gdof);
3697:     PetscSectionGetConstraintDof(globalSection, p, &gcdof);
3698:     PetscSectionGetOffset(globalSection, p, &goff);
3699:     if (!gdof) continue; /* Censored point */
3700:     if ((gdof < 0 ? -(gdof+1) : gdof) != dof) {PetscSynchronizedPrintf(comm, "[%d]Global dof %d for point %d not equal to local dof %d\n", rank, gdof, p, dof); valid = PETSC_FALSE;}
3701:     if (gcdof && (gcdof != cdof)) {PetscSynchronizedPrintf(comm, "[%d]Global constraints %d for point %d not equal to local constraints %d\n", rank, gcdof, p, cdof); valid = PETSC_FALSE;}
3702:     if (gdof < 0) {
3703:       gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3704:       for (d = 0; d < gsize; ++d) {
3705:         PetscInt offset = -(goff+1) + d, r;

3707:         PetscFindInt(offset,size+1,ranges,&r);
3708:         if (r < 0) r = -(r+2);
3709:         if ((r < 0) || (r >= size)) {PetscSynchronizedPrintf(comm, "[%d]Point %d mapped to invalid process %d (%d, %d)\n", rank, p, r, gdof, goff); valid = PETSC_FALSE;break;}
3710:       }
3711:     }
3712:   }
3713:   PetscLayoutDestroy(&layout);
3714:   PetscSynchronizedFlush(comm, NULL);
3715:   MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);
3716:   if (!gvalid) {
3717:     DMView(dm, NULL);
3718:     SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections");
3719:   }
3720:   return(0);
3721: }
3722: #endif

3724: /*@
3725:   DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM.

3727:   Collective on DM

3729:   Input Parameter:
3730: . dm - The DM

3732:   Output Parameter:
3733: . section - The PetscSection

3735:   Level: intermediate

3737:   Note: This gets a borrowed reference, so the user should not destroy this PetscSection.

3739: .seealso: DMSetDefaultSection(), DMGetDefaultSection()
3740: @*/
3741: PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section)
3742: {

3748:   if (!dm->defaultGlobalSection) {
3749:     PetscSection s;

3751:     DMGetDefaultSection(dm, &s);
3752:     if (!s)  SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection");
3753:     if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection");
3754:     PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->defaultGlobalSection);
3755:     PetscLayoutDestroy(&dm->map);
3756:     PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);
3757:     PetscSectionViewFromOptions(dm->defaultGlobalSection, NULL, "-global_section_view");
3758:   }
3759:   *section = dm->defaultGlobalSection;
3760:   return(0);
3761: }

3763: /*@
3764:   DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM.

3766:   Input Parameters:
3767: + dm - The DM
3768: - section - The PetscSection, or NULL

3770:   Level: intermediate

3772:   Note: Any existing Section will be destroyed

3774: .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection()
3775: @*/
3776: PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section)
3777: {

3783:   PetscObjectReference((PetscObject)section);
3784:   PetscSectionDestroy(&dm->defaultGlobalSection);
3785:   dm->defaultGlobalSection = section;
3786: #ifdef PETSC_USE_DEBUG
3787:   if (section) {DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);}
3788: #endif
3789:   return(0);
3790: }

3792: /*@
3793:   DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set,
3794:   it is created from the default PetscSection layouts in the DM.

3796:   Input Parameter:
3797: . dm - The DM

3799:   Output Parameter:
3800: . sf - The PetscSF

3802:   Level: intermediate

3804:   Note: This gets a borrowed reference, so the user should not destroy this PetscSF.

3806: .seealso: DMSetDefaultSF(), DMCreateDefaultSF()
3807: @*/
3808: PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf)
3809: {
3810:   PetscInt       nroots;

3816:   PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);
3817:   if (nroots < 0) {
3818:     PetscSection section, gSection;

3820:     DMGetDefaultSection(dm, &section);
3821:     if (section) {
3822:       DMGetDefaultGlobalSection(dm, &gSection);
3823:       DMCreateDefaultSF(dm, section, gSection);
3824:     } else {
3825:       *sf = NULL;
3826:       return(0);
3827:     }
3828:   }
3829:   *sf = dm->defaultSF;
3830:   return(0);
3831: }

3833: /*@
3834:   DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM

3836:   Input Parameters:
3837: + dm - The DM
3838: - sf - The PetscSF

3840:   Level: intermediate

3842:   Note: Any previous SF is destroyed

3844: .seealso: DMGetDefaultSF(), DMCreateDefaultSF()
3845: @*/
3846: PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf)
3847: {

3853:   PetscSFDestroy(&dm->defaultSF);
3854:   dm->defaultSF = sf;
3855:   return(0);
3856: }

3858: /*@C
3859:   DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections
3860:   describing the data layout.

3862:   Input Parameters:
3863: + dm - The DM
3864: . localSection - PetscSection describing the local data layout
3865: - globalSection - PetscSection describing the global data layout

3867:   Level: intermediate

3869: .seealso: DMGetDefaultSF(), DMSetDefaultSF()
3870: @*/
3871: PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection)
3872: {
3873:   MPI_Comm       comm;
3874:   PetscLayout    layout;
3875:   const PetscInt *ranges;
3876:   PetscInt       *local;
3877:   PetscSFNode    *remote;
3878:   PetscInt       pStart, pEnd, p, nroots, nleaves = 0, l;
3879:   PetscMPIInt    size, rank;

3883:   PetscObjectGetComm((PetscObject)dm,&comm);
3885:   MPI_Comm_size(comm, &size);
3886:   MPI_Comm_rank(comm, &rank);
3887:   PetscSectionGetChart(globalSection, &pStart, &pEnd);
3888:   PetscSectionGetConstrainedStorageSize(globalSection, &nroots);
3889:   PetscLayoutCreate(comm, &layout);
3890:   PetscLayoutSetBlockSize(layout, 1);
3891:   PetscLayoutSetLocalSize(layout, nroots);
3892:   PetscLayoutSetUp(layout);
3893:   PetscLayoutGetRanges(layout, &ranges);
3894:   for (p = pStart; p < pEnd; ++p) {
3895:     PetscInt gdof, gcdof;

3897:     PetscSectionGetDof(globalSection, p, &gdof);
3898:     PetscSectionGetConstraintDof(globalSection, p, &gcdof);
3899:     if (gcdof > (gdof < 0 ? -(gdof+1) : gdof)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d has %d constraints > %d dof", p, gcdof, (gdof < 0 ? -(gdof+1) : gdof));
3900:     nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3901:   }
3902:   PetscMalloc1(nleaves, &local);
3903:   PetscMalloc1(nleaves, &remote);
3904:   for (p = pStart, l = 0; p < pEnd; ++p) {
3905:     const PetscInt *cind;
3906:     PetscInt       dof, cdof, off, gdof, gcdof, goff, gsize, d, c;

3908:     PetscSectionGetDof(localSection, p, &dof);
3909:     PetscSectionGetOffset(localSection, p, &off);
3910:     PetscSectionGetConstraintDof(localSection, p, &cdof);
3911:     PetscSectionGetConstraintIndices(localSection, p, &cind);
3912:     PetscSectionGetDof(globalSection, p, &gdof);
3913:     PetscSectionGetConstraintDof(globalSection, p, &gcdof);
3914:     PetscSectionGetOffset(globalSection, p, &goff);
3915:     if (!gdof) continue; /* Censored point */
3916:     gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3917:     if (gsize != dof-cdof) {
3918:       if (gsize != dof) SETERRQ4(comm, PETSC_ERR_ARG_WRONG, "Global dof %d for point %d is neither the constrained size %d, nor the unconstrained %d", gsize, p, dof-cdof, dof);
3919:       cdof = 0; /* Ignore constraints */
3920:     }
3921:     for (d = 0, c = 0; d < dof; ++d) {
3922:       if ((c < cdof) && (cind[c] == d)) {++c; continue;}
3923:       local[l+d-c] = off+d;
3924:     }
3925:     if (gdof < 0) {
3926:       for (d = 0; d < gsize; ++d, ++l) {
3927:         PetscInt offset = -(goff+1) + d, r;

3929:         PetscFindInt(offset,size+1,ranges,&r);
3930:         if (r < 0) r = -(r+2);
3931:         if ((r < 0) || (r >= size)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d mapped to invalid process %d (%d, %d)", p, r, gdof, goff);
3932:         remote[l].rank  = r;
3933:         remote[l].index = offset - ranges[r];
3934:       }
3935:     } else {
3936:       for (d = 0; d < gsize; ++d, ++l) {
3937:         remote[l].rank  = rank;
3938:         remote[l].index = goff+d - ranges[rank];
3939:       }
3940:     }
3941:   }
3942:   if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves);
3943:   PetscLayoutDestroy(&layout);
3944:   PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);
3945:   return(0);
3946: }

3948: /*@
3949:   DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM.

3951:   Input Parameter:
3952: . dm - The DM

3954:   Output Parameter:
3955: . sf - The PetscSF

3957:   Level: intermediate

3959:   Note: This gets a borrowed reference, so the user should not destroy this PetscSF.

3961: .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
3962: @*/
3963: PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf)
3964: {
3968:   *sf = dm->sf;
3969:   return(0);
3970: }

3972: /*@
3973:   DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM.

3975:   Input Parameters:
3976: + dm - The DM
3977: - sf - The PetscSF

3979:   Level: intermediate

3981: .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
3982: @*/
3983: PetscErrorCode DMSetPointSF(DM dm, PetscSF sf)
3984: {

3990:   PetscSFDestroy(&dm->sf);
3991:   PetscObjectReference((PetscObject) sf);
3992:   dm->sf = sf;
3993:   return(0);
3994: }

3996: /*@
3997:   DMGetDS - Get the PetscDS

3999:   Input Parameter:
4000: . dm - The DM

4002:   Output Parameter:
4003: . prob - The PetscDS

4005:   Level: developer

4007: .seealso: DMSetDS()
4008: @*/
4009: PetscErrorCode DMGetDS(DM dm, PetscDS *prob)
4010: {
4014:   *prob = dm->prob;
4015:   return(0);
4016: }

4018: /*@
4019:   DMSetDS - Set the PetscDS

4021:   Input Parameters:
4022: + dm - The DM
4023: - prob - The PetscDS

4025:   Level: developer

4027: .seealso: DMGetDS()
4028: @*/
4029: PetscErrorCode DMSetDS(DM dm, PetscDS prob)
4030: {
4031:   PetscInt       dimEmbed;

4037:   PetscObjectReference((PetscObject) prob);
4038:   PetscDSDestroy(&dm->prob);
4039:   dm->prob = prob;
4040:   DMGetCoordinateDim(dm, &dimEmbed);
4041:   PetscDSSetCoordinateDimension(prob, dimEmbed);
4042:   return(0);
4043: }

4045: PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields)
4046: {

4051:   PetscDSGetNumFields(dm->prob, numFields);
4052:   return(0);
4053: }

4055: PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields)
4056: {
4057:   PetscInt       Nf, f;

4062:   PetscDSGetNumFields(dm->prob, &Nf);
4063:   for (f = Nf; f < numFields; ++f) {
4064:     PetscContainer obj;

4066:     PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);
4067:     PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);
4068:     PetscContainerDestroy(&obj);
4069:   }
4070:   return(0);
4071: }

4073: /*@
4074:   DMGetField - Return the discretization object for a given DM field

4076:   Not collective

4078:   Input Parameters:
4079: + dm - The DM
4080: - f  - The field number

4082:   Output Parameter:
4083: . field - The discretization object

4085:   Level: developer

4087: .seealso: DMSetField()
4088: @*/
4089: PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field)
4090: {

4095:   PetscDSGetDiscretization(dm->prob, f, field);
4096:   return(0);
4097: }

4099: /*@
4100:   DMSetField - Set the discretization object for a given DM field

4102:   Logically collective on DM

4104:   Input Parameters:
4105: + dm - The DM
4106: . f  - The field number
4107: - field - The discretization object

4109:   Level: developer

4111: .seealso: DMGetField()
4112: @*/
4113: PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field)
4114: {

4119:   PetscDSSetDiscretization(dm->prob, f, field);
4120:   return(0);
4121: }

4123: PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx)
4124: {
4125:   DM dm_coord,dmc_coord;
4127:   Vec coords,ccoords;
4128:   Mat inject;
4130:   DMGetCoordinateDM(dm,&dm_coord);
4131:   DMGetCoordinateDM(dmc,&dmc_coord);
4132:   DMGetCoordinates(dm,&coords);
4133:   DMGetCoordinates(dmc,&ccoords);
4134:   if (coords && !ccoords) {
4135:     DMCreateGlobalVector(dmc_coord,&ccoords);
4136:     PetscObjectSetName((PetscObject)ccoords,"coordinates");
4137:     DMCreateInjection(dmc_coord,dm_coord,&inject);
4138:     MatRestrict(inject,coords,ccoords);
4139:     MatDestroy(&inject);
4140:     DMSetCoordinates(dmc,ccoords);
4141:     VecDestroy(&ccoords);
4142:   }
4143:   return(0);
4144: }

4146: static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx)
4147: {
4148:   DM dm_coord,subdm_coord;
4150:   Vec coords,ccoords,clcoords;
4151:   VecScatter *scat_i,*scat_g;
4153:   DMGetCoordinateDM(dm,&dm_coord);
4154:   DMGetCoordinateDM(subdm,&subdm_coord);
4155:   DMGetCoordinates(dm,&coords);
4156:   DMGetCoordinates(subdm,&ccoords);
4157:   if (coords && !ccoords) {
4158:     DMCreateGlobalVector(subdm_coord,&ccoords);
4159:     PetscObjectSetName((PetscObject)ccoords,"coordinates");
4160:     DMCreateLocalVector(subdm_coord,&clcoords);
4161:     PetscObjectSetName((PetscObject)clcoords,"coordinates");
4162:     DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);
4163:     VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);
4164:     VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);
4165:     VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);
4166:     VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);
4167:     DMSetCoordinates(subdm,ccoords);
4168:     DMSetCoordinatesLocal(subdm,clcoords);
4169:     VecScatterDestroy(&scat_i[0]);
4170:     VecScatterDestroy(&scat_g[0]);
4171:     VecDestroy(&ccoords);
4172:     VecDestroy(&clcoords);
4173:     PetscFree(scat_i);
4174:     PetscFree(scat_g);
4175:   }
4176:   return(0);
4177: }

4179: /*@
4180:   DMGetDimension - Return the topological dimension of the DM

4182:   Not collective

4184:   Input Parameter:
4185: . dm - The DM

4187:   Output Parameter:
4188: . dim - The topological dimension

4190:   Level: beginner

4192: .seealso: DMSetDimension(), DMCreate()
4193: @*/
4194: PetscErrorCode DMGetDimension(DM dm, PetscInt *dim)
4195: {
4199:   *dim = dm->dim;
4200:   return(0);
4201: }

4203: /*@
4204:   DMSetDimension - Set the topological dimension of the DM

4206:   Collective on dm

4208:   Input Parameters:
4209: + dm - The DM
4210: - dim - The topological dimension

4212:   Level: beginner

4214: .seealso: DMGetDimension(), DMCreate()
4215: @*/
4216: PetscErrorCode DMSetDimension(DM dm, PetscInt dim)
4217: {

4223:   dm->dim = dim;
4224:   if (dm->prob->dimEmbed < 0) {PetscDSSetCoordinateDimension(dm->prob, dm->dim);}
4225:   return(0);
4226: }

4228: /*@
4229:   DMGetDimPoints - Get the half-open interval for all points of a given dimension

4231:   Collective on DM

4233:   Input Parameters:
4234: + dm - the DM
4235: - dim - the dimension

4237:   Output Parameters:
4238: + pStart - The first point of the given dimension
4239: . pEnd - The first point following points of the given dimension

4241:   Note:
4242:   The points are vertices in the Hasse diagram encoding the topology. This is explained in
4243:   http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme,
4244:   then the interval is empty.

4246:   Level: intermediate

4248: .keywords: point, Hasse Diagram, dimension
4249: .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum()
4250: @*/
4251: PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
4252: {
4253:   PetscInt       d;

4258:   DMGetDimension(dm, &d);
4259:   if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d);
4260:   (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);
4261:   return(0);
4262: }

4264: /*@
4265:   DMSetCoordinates - Sets into the DM a global vector that holds the coordinates

4267:   Collective on DM

4269:   Input Parameters:
4270: + dm - the DM
4271: - c - coordinate vector

4273:   Note:
4274:   The coordinates do include those for ghost points, which are in the local vector

4276:   Level: intermediate

4278: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4279: .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM()
4280: @*/
4281: PetscErrorCode DMSetCoordinates(DM dm, Vec c)
4282: {

4288:   PetscObjectReference((PetscObject) c);
4289:   VecDestroy(&dm->coordinates);
4290:   dm->coordinates = c;
4291:   VecDestroy(&dm->coordinatesLocal);
4292:   DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);
4293:   DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);
4294:   return(0);
4295: }

4297: /*@
4298:   DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates

4300:   Collective on DM

4302:    Input Parameters:
4303: +  dm - the DM
4304: -  c - coordinate vector

4306:   Note:
4307:   The coordinates of ghost points can be set using DMSetCoordinates()
4308:   followed by DMGetCoordinatesLocal(). This is intended to enable the
4309:   setting of ghost coordinates outside of the domain.

4311:   Level: intermediate

4313: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4314: .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM()
4315: @*/
4316: PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c)
4317: {

4323:   PetscObjectReference((PetscObject) c);
4324:   VecDestroy(&dm->coordinatesLocal);

4326:   dm->coordinatesLocal = c;

4328:   VecDestroy(&dm->coordinates);
4329:   return(0);
4330: }

4332: /*@
4333:   DMGetCoordinates - Gets a global vector with the coordinates associated with the DM.

4335:   Not Collective

4337:   Input Parameter:
4338: . dm - the DM

4340:   Output Parameter:
4341: . c - global coordinate vector

4343:   Note:
4344:   This is a borrowed reference, so the user should NOT destroy this vector

4346:   Each process has only the local coordinates (does NOT have the ghost coordinates).

4348:   For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
4349:   and (x_0,y_0,z_0,x_1,y_1,z_1...)

4351:   Level: intermediate

4353: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4354: .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM()
4355: @*/
4356: PetscErrorCode DMGetCoordinates(DM dm, Vec *c)
4357: {

4363:   if (!dm->coordinates && dm->coordinatesLocal) {
4364:     DM cdm = NULL;

4366:     DMGetCoordinateDM(dm, &cdm);
4367:     DMCreateGlobalVector(cdm, &dm->coordinates);
4368:     PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");
4369:     DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);
4370:     DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);
4371:   }
4372:   *c = dm->coordinates;
4373:   return(0);
4374: }

4376: /*@
4377:   DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM.

4379:   Collective on DM

4381:   Input Parameter:
4382: . dm - the DM

4384:   Output Parameter:
4385: . c - coordinate vector

4387:   Note:
4388:   This is a borrowed reference, so the user should NOT destroy this vector

4390:   Each process has the local and ghost coordinates

4392:   For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
4393:   and (x_0,y_0,z_0,x_1,y_1,z_1...)

4395:   Level: intermediate

4397: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4398: .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM()
4399: @*/
4400: PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c)
4401: {

4407:   if (!dm->coordinatesLocal && dm->coordinates) {
4408:     DM cdm = NULL;

4410:     DMGetCoordinateDM(dm, &cdm);
4411:     DMCreateLocalVector(cdm, &dm->coordinatesLocal);
4412:     PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");
4413:     DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);
4414:     DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);
4415:   }
4416:   *c = dm->coordinatesLocal;
4417:   return(0);
4418: }

4420: /*@
4421:   DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates

4423:   Collective on DM

4425:   Input Parameter:
4426: . dm - the DM

4428:   Output Parameter:
4429: . cdm - coordinate DM

4431:   Level: intermediate

4433: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4434: .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
4435: @*/
4436: PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm)
4437: {

4443:   if (!dm->coordinateDM) {
4444:     if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM");
4445:     (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);
4446:   }
4447:   *cdm = dm->coordinateDM;
4448:   return(0);
4449: }

4451: /*@
4452:   DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates

4454:   Logically Collective on DM

4456:   Input Parameters:
4457: + dm - the DM
4458: - cdm - coordinate DM

4460:   Level: intermediate

4462: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4463: .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
4464: @*/
4465: PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm)
4466: {

4472:   PetscObjectReference((PetscObject)cdm);
4473:   DMDestroy(&dm->coordinateDM);
4474:   dm->coordinateDM = cdm;
4475:   return(0);
4476: }

4478: /*@
4479:   DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values.

4481:   Not Collective

4483:   Input Parameter:
4484: . dm - The DM object

4486:   Output Parameter:
4487: . dim - The embedding dimension

4489:   Level: intermediate

4491: .keywords: mesh, coordinates
4492: .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection()
4493: @*/
4494: PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim)
4495: {
4499:   if (dm->dimEmbed == PETSC_DEFAULT) {
4500:     dm->dimEmbed = dm->dim;
4501:   }
4502:   *dim = dm->dimEmbed;
4503:   return(0);
4504: }

4506: /*@
4507:   DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values.

4509:   Not Collective

4511:   Input Parameters:
4512: + dm  - The DM object
4513: - dim - The embedding dimension

4515:   Level: intermediate

4517: .keywords: mesh, coordinates
4518: .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection()
4519: @*/
4520: PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim)
4521: {

4526:   dm->dimEmbed = dim;
4527:   PetscDSSetCoordinateDimension(dm->prob, dm->dimEmbed);
4528:   return(0);
4529: }

4531: /*@
4532:   DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh.

4534:   Not Collective

4536:   Input Parameter:
4537: . dm - The DM object

4539:   Output Parameter:
4540: . section - The PetscSection object

4542:   Level: intermediate

4544: .keywords: mesh, coordinates
4545: .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection()
4546: @*/
4547: PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section)
4548: {
4549:   DM             cdm;

4555:   DMGetCoordinateDM(dm, &cdm);
4556:   DMGetDefaultSection(cdm, section);
4557:   return(0);
4558: }

4560: /*@
4561:   DMSetCoordinateSection - Set the layout of coordinate values over the mesh.

4563:   Not Collective

4565:   Input Parameters:
4566: + dm      - The DM object
4567: . dim     - The embedding dimension, or PETSC_DETERMINE
4568: - section - The PetscSection object

4570:   Level: intermediate

4572: .keywords: mesh, coordinates
4573: .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection()
4574: @*/
4575: PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section)
4576: {
4577:   DM             cdm;

4583:   DMGetCoordinateDM(dm, &cdm);
4584:   DMSetDefaultSection(cdm, section);
4585:   if (dim == PETSC_DETERMINE) {
4586:     PetscInt d = PETSC_DEFAULT;
4587:     PetscInt pStart, pEnd, vStart, vEnd, v, dd;

4589:     PetscSectionGetChart(section, &pStart, &pEnd);
4590:     DMGetDimPoints(dm, 0, &vStart, &vEnd);
4591:     pStart = PetscMax(vStart, pStart);
4592:     pEnd   = PetscMin(vEnd, pEnd);
4593:     for (v = pStart; v < pEnd; ++v) {
4594:       PetscSectionGetDof(section, v, &dd);
4595:       if (dd) {d = dd; break;}
4596:     }
4597:     if (d < 0) d = PETSC_DEFAULT;
4598:     DMSetCoordinateDim(dm, d);
4599:   }
4600:   return(0);
4601: }

4603: /*@C
4604:   DMGetPeriodicity - Get the description of mesh periodicity

4606:   Input Parameters:
4607: . dm      - The DM object

4609:   Output Parameters:
4610: + per     - Whether the DM is periodic or not
4611: . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates
4612: . L       - If we assume the mesh is a torus, this is the length of each coordinate
4613: - bd      - This describes the type of periodicity in each topological dimension

4615:   Level: developer

4617: .seealso: DMGetPeriodicity()
4618: @*/
4619: PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd)
4620: {
4623:   if (per)     *per     = dm->periodic;
4624:   if (L)       *L       = dm->L;
4625:   if (maxCell) *maxCell = dm->maxCell;
4626:   if (bd)      *bd      = dm->bdtype;
4627:   return(0);
4628: }

4630: /*@C
4631:   DMSetPeriodicity - Set the description of mesh periodicity

4633:   Input Parameters:
4634: + dm      - The DM object
4635: . per     - Whether the DM is periodic or not. If maxCell is not provided, coordinates need to be localized
4636: . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates
4637: . L       - If we assume the mesh is a torus, this is the length of each coordinate
4638: - bd      - This describes the type of periodicity in each topological dimension

4640:   Level: developer

4642: .seealso: DMGetPeriodicity()
4643: @*/
4644: PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[])
4645: {
4646:   PetscInt       dim, d;

4652:   if (maxCell) {
4656:   }
4657:   PetscFree3(dm->L,dm->maxCell,dm->bdtype);
4658:   DMGetDimension(dm, &dim);
4659:   if (maxCell) {
4660:     PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);
4661:     for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];}
4662:     dm->periodic = PETSC_TRUE;
4663:   } else {
4664:     dm->periodic = per;
4665:   }
4666:   return(0);
4667: }

4669: /*@
4670:   DMLocalizeCoordinate - If a mesh is periodic (a torus with lengths L_i, some of which can be infinite), project the coordinate onto [0, L_i) in each dimension.

4672:   Input Parameters:
4673: + dm     - The DM
4674: . in     - The input coordinate point (dim numbers)
4675: - endpoint - Include the endpoint L_i

4677:   Output Parameter:
4678: . out - The localized coordinate point

4680:   Level: developer

4682: .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate()
4683: @*/
4684: PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[])
4685: {
4686:   PetscInt       dim, d;

4690:   DMGetCoordinateDim(dm, &dim);
4691:   if (!dm->maxCell) {
4692:     for (d = 0; d < dim; ++d) out[d] = in[d];
4693:   } else {
4694:     if (endpoint) {
4695:       for (d = 0; d < dim; ++d) {
4696:         if ((PetscAbsReal(PetscRealPart(in[d])/dm->L[d] - PetscFloorReal(PetscRealPart(in[d])/dm->L[d])) < PETSC_SMALL) && (PetscRealPart(in[d])/dm->L[d] > PETSC_SMALL)) {
4697:           out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1);
4698:         } else {
4699:           out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]);
4700:         }
4701:       }
4702:     } else {
4703:       for (d = 0; d < dim; ++d) {
4704:         out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]);
4705:       }
4706:     }
4707:   }
4708:   return(0);
4709: }

4711: /*
4712:   DMLocalizeCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer.

4714:   Input Parameters:
4715: + dm     - The DM
4716: . dim    - The spatial dimension
4717: . anchor - The anchor point, the input point can be no more than maxCell away from it
4718: - in     - The input coordinate point (dim numbers)

4720:   Output Parameter:
4721: . out - The localized coordinate point

4723:   Level: developer

4725:   Note: This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually the one of the vertices on a containing cell

4727: .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate()
4728: */
4729: PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[])
4730: {
4731:   PetscInt d;

4734:   if (!dm->maxCell) {
4735:     for (d = 0; d < dim; ++d) out[d] = in[d];
4736:   } else {
4737:     for (d = 0; d < dim; ++d) {
4738:       if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) {
4739:         out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d];
4740:       } else {
4741:         out[d] = in[d];
4742:       }
4743:     }
4744:   }
4745:   return(0);
4746: }
4747: PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[])
4748: {
4749:   PetscInt d;

4752:   if (!dm->maxCell) {
4753:     for (d = 0; d < dim; ++d) out[d] = in[d];
4754:   } else {
4755:     for (d = 0; d < dim; ++d) {
4756:       if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) {
4757:         out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d];
4758:       } else {
4759:         out[d] = in[d];
4760:       }
4761:     }
4762:   }
4763:   return(0);
4764: }

4766: /*
4767:   DMLocalizeAddCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer.

4769:   Input Parameters:
4770: + dm     - The DM
4771: . dim    - The spatial dimension
4772: . anchor - The anchor point, the input point can be no more than maxCell away from it
4773: . in     - The input coordinate delta (dim numbers)
4774: - out    - The input coordinate point (dim numbers)

4776:   Output Parameter:
4777: . out    - The localized coordinate in + out

4779:   Level: developer

4781:   Note: This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually the one of the vertices on a containing cell

4783: .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate()
4784: */
4785: PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[])
4786: {
4787:   PetscInt d;

4790:   if (!dm->maxCell) {
4791:     for (d = 0; d < dim; ++d) out[d] += in[d];
4792:   } else {
4793:     for (d = 0; d < dim; ++d) {
4794:       if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) {
4795:         out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d];
4796:       } else {
4797:         out[d] += in[d];
4798:       }
4799:     }
4800:   }
4801:   return(0);
4802: }

4804: /*@
4805:   DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells

4807:   Input Parameter:
4808: . dm - The DM

4810:   Output Parameter:
4811:   areLocalized - True if localized

4813:   Level: developer

4815: .seealso: DMLocalizeCoordinates()
4816: @*/
4817: PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized)
4818: {
4819:   DM             cdm;
4820:   PetscSection   coordSection;
4821:   PetscInt       cStart, cEnd, sStart, sEnd, c, dof;
4822:   PetscBool      isPlex, alreadyLocalized;


4829:   *areLocalized = PETSC_FALSE;
4830:   if (!dm->periodic) return(0); /* This is a hideous optimization hack! */

4832:   /* We need some generic way of refering to cells/vertices */
4833:   DMGetCoordinateDM(dm, &cdm);
4834:   DMGetCoordinateSection(dm, &coordSection);
4835:   PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);
4836:   if (!isPlex) SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM");

4838:   DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);
4839:   PetscSectionGetChart(coordSection, &sStart, &sEnd);
4840:   alreadyLocalized = PETSC_FALSE;
4841:   for (c = cStart; c < cEnd; ++c) {
4842:     if (c < sStart || c >= sEnd) continue;
4843:     PetscSectionGetDof(coordSection, c, &dof);
4844:     if (dof) { alreadyLocalized = PETSC_TRUE; break; }
4845:   }
4846:   MPIU_Allreduce(&alreadyLocalized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));
4847:   return(0);
4848: }


4851: /*@
4852:   DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces

4854:   Input Parameter:
4855: . dm - The DM

4857:   Level: developer

4859: .seealso: DMLocalizeCoordinate(), DMLocalizeAddCoordinate()
4860: @*/
4861: PetscErrorCode DMLocalizeCoordinates(DM dm)
4862: {
4863:   DM             cdm;
4864:   PetscSection   coordSection, cSection;
4865:   Vec            coordinates,  cVec;
4866:   PetscScalar   *coords, *coords2, *anchor, *localized;
4867:   PetscInt       Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize;
4868:   PetscBool      alreadyLocalized, alreadyLocalizedGlobal;
4869:   PetscInt       maxHeight = 0, h;
4870:   PetscInt       *pStart = NULL, *pEnd = NULL;

4875:   if (!dm->periodic) return(0);
4876:   DMGetCoordinatesLocalized(dm, &alreadyLocalized);
4877:   if (alreadyLocalized) return(0);

4879:   /* We need some generic way of refering to cells/vertices */
4880:   DMGetCoordinateDM(dm, &cdm);
4881:   {
4882:     PetscBool isplex;

4884:     PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);
4885:     if (isplex) {
4886:       DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);
4887:       DMPlexGetMaxProjectionHeight(cdm,&maxHeight);
4888:       DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);
4889:       pEnd = &pStart[maxHeight + 1];
4890:       newStart = vStart;
4891:       newEnd   = vEnd;
4892:       for (h = 0; h <= maxHeight; h++) {
4893:         DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);
4894:         newStart = PetscMin(newStart,pStart[h]);
4895:         newEnd   = PetscMax(newEnd,pEnd[h]);
4896:       }
4897:     } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM");
4898:   }
4899:   DMGetCoordinatesLocal(dm, &coordinates);
4900:   if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector");
4901:   DMGetCoordinateSection(dm, &coordSection);
4902:   VecGetBlockSize(coordinates, &bs);
4903:   PetscSectionGetChart(coordSection,&sStart,&sEnd);

4905:   PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);
4906:   PetscSectionSetNumFields(cSection, 1);
4907:   PetscSectionGetFieldComponents(coordSection, 0, &Nc);
4908:   PetscSectionSetFieldComponents(cSection, 0, Nc);
4909:   PetscSectionSetChart(cSection, newStart, newEnd);

4911:   DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);
4912:   localized = &anchor[bs];
4913:   alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE;
4914:   for (h = 0; h <= maxHeight; h++) {
4915:     PetscInt cStart = pStart[h], cEnd = pEnd[h], c;

4917:     for (c = cStart; c < cEnd; ++c) {
4918:       PetscScalar *cellCoords = NULL;
4919:       PetscInt     b;

4921:       if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE;
4922:       DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
4923:       for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b];
4924:       for (d = 0; d < dof/bs; ++d) {
4925:         DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);
4926:         for (b = 0; b < bs; b++) {
4927:           if (cellCoords[d*bs + b] != localized[b]) break;
4928:         }
4929:         if (b < bs) break;
4930:       }
4931:       if (d < dof/bs) {
4932:         if (c >= sStart && c < sEnd) {
4933:           PetscInt cdof;

4935:           PetscSectionGetDof(coordSection, c, &cdof);
4936:           if (cdof != dof) alreadyLocalized = PETSC_FALSE;
4937:         }
4938:         PetscSectionSetDof(cSection, c, dof);
4939:         PetscSectionSetFieldDof(cSection, c, 0, dof);
4940:       }
4941:       DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
4942:     }
4943:   }
4944:   MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));
4945:   if (alreadyLocalizedGlobal) {
4946:     DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);
4947:     PetscSectionDestroy(&cSection);
4948:     DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);
4949:     return(0);
4950:   }
4951:   for (v = vStart; v < vEnd; ++v) {
4952:     PetscSectionGetDof(coordSection, v, &dof);
4953:     PetscSectionSetDof(cSection,     v,  dof);
4954:     PetscSectionSetFieldDof(cSection, v, 0, dof);
4955:   }
4956:   PetscSectionSetUp(cSection);
4957:   PetscSectionGetStorageSize(cSection, &coordSize);
4958:   VecCreate(PETSC_COMM_SELF, &cVec);
4959:   PetscObjectSetName((PetscObject)cVec,"coordinates");
4960:   VecSetBlockSize(cVec,         bs);
4961:   VecSetSizes(cVec, coordSize, PETSC_DETERMINE);
4962:   VecSetType(cVec, VECSTANDARD);
4963:   VecGetArrayRead(coordinates, (const PetscScalar**)&coords);
4964:   VecGetArray(cVec, &coords2);
4965:   for (v = vStart; v < vEnd; ++v) {
4966:     PetscSectionGetDof(coordSection, v, &dof);
4967:     PetscSectionGetOffset(coordSection, v, &off);
4968:     PetscSectionGetOffset(cSection,     v, &off2);
4969:     for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d];
4970:   }
4971:   for (h = 0; h <= maxHeight; h++) {
4972:     PetscInt cStart = pStart[h], cEnd = pEnd[h], c;

4974:     for (c = cStart; c < cEnd; ++c) {
4975:       PetscScalar *cellCoords = NULL;
4976:       PetscInt     b, cdof;

4978:       PetscSectionGetDof(cSection,c,&cdof);
4979:       if (!cdof) continue;
4980:       DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
4981:       PetscSectionGetOffset(cSection, c, &off2);
4982:       for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b];
4983:       for (d = 0; d < dof/bs; ++d) {DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);}
4984:       DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
4985:     }
4986:   }
4987:   DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);
4988:   DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);
4989:   VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);
4990:   VecRestoreArray(cVec, &coords2);
4991:   DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);
4992:   DMSetCoordinatesLocal(dm, cVec);
4993:   VecDestroy(&cVec);
4994:   PetscSectionDestroy(&cSection);
4995:   return(0);
4996: }

4998: /*@
4999:   DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells

5001:   Collective on Vec v (see explanation below)

5003:   Input Parameters:
5004: + dm - The DM
5005: . v - The Vec of points
5006: . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST
5007: - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point.

5009:   Output Parameter:
5010: + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used
5011: - cells - The PetscSF containing the ranks and local indices of the containing points.


5014:   Level: developer

5016:   Notes:
5017:   To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator.
5018:   To do a search of all the cells in the distributed mesh, v should have the same communicator as dm.

5020:   If *cellSF is NULL on input, a PetscSF will be created.
5021:   If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses.

5023:   An array that maps each point to its containing cell can be obtained with

5025: $    const PetscSFNode *cells;
5026: $    PetscInt           nFound;
5027: $    const PetscSFNode *found;
5028: $
5029: $    PetscSFGetGraph(cells,NULL,&nFound,&found,&cells);

5031:   Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is
5032:   the index of the cell in its rank's local numbering.

5034: .keywords: point location, mesh
5035: .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType
5036: @*/
5037: PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF)
5038: {

5045:   if (*cellSF) {
5046:     PetscMPIInt result;

5049:     MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);
5050:     if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's");
5051:   } else {
5052:     PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);
5053:   }
5054:   PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);
5055:   if (dm->ops->locatepoints) {
5056:     (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);
5057:   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM");
5058:   PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);
5059:   return(0);
5060: }

5062: /*@
5063:   DMGetOutputDM - Retrieve the DM associated with the layout for output

5065:   Input Parameter:
5066: . dm - The original DM

5068:   Output Parameter:
5069: . odm - The DM which provides the layout for output

5071:   Level: intermediate

5073: .seealso: VecView(), DMGetDefaultGlobalSection()
5074: @*/
5075: PetscErrorCode DMGetOutputDM(DM dm, DM *odm)
5076: {
5077:   PetscSection   section;
5078:   PetscBool      hasConstraints, ghasConstraints;

5084:   DMGetDefaultSection(dm, &section);
5085:   PetscSectionHasConstraints(section, &hasConstraints);
5086:   MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));
5087:   if (!ghasConstraints) {
5088:     *odm = dm;
5089:     return(0);
5090:   }
5091:   if (!dm->dmBC) {
5092:     PetscDS      ds;
5093:     PetscSection newSection, gsection;
5094:     PetscSF      sf;

5096:     DMClone(dm, &dm->dmBC);
5097:     DMGetDS(dm, &ds);
5098:     DMSetDS(dm->dmBC, ds);
5099:     PetscSectionClone(section, &newSection);
5100:     DMSetDefaultSection(dm->dmBC, newSection);
5101:     PetscSectionDestroy(&newSection);
5102:     DMGetPointSF(dm->dmBC, &sf);
5103:     PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);
5104:     DMSetDefaultGlobalSection(dm->dmBC, gsection);
5105:     PetscSectionDestroy(&gsection);
5106:   }
5107:   *odm = dm->dmBC;
5108:   return(0);
5109: }

5111: /*@
5112:   DMGetOutputSequenceNumber - Retrieve the sequence number/value for output

5114:   Input Parameter:
5115: . dm - The original DM

5117:   Output Parameters:
5118: + num - The output sequence number
5119: - val - The output sequence value

5121:   Level: intermediate

5123:   Note: This is intended for output that should appear in sequence, for instance
5124:   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.

5126: .seealso: VecView()
5127: @*/
5128: PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val)
5129: {
5134:   return(0);
5135: }

5137: /*@
5138:   DMSetOutputSequenceNumber - Set the sequence number/value for output

5140:   Input Parameters:
5141: + dm - The original DM
5142: . num - The output sequence number
5143: - val - The output sequence value

5145:   Level: intermediate

5147:   Note: This is intended for output that should appear in sequence, for instance
5148:   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.

5150: .seealso: VecView()
5151: @*/
5152: PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val)
5153: {
5156:   dm->outputSequenceNum = num;
5157:   dm->outputSequenceVal = val;
5158:   return(0);
5159: }

5161: /*@C
5162:   DMOutputSequenceLoad - Retrieve the sequence value from a Viewer

5164:   Input Parameters:
5165: + dm   - The original DM
5166: . name - The sequence name
5167: - num  - The output sequence number

5169:   Output Parameter:
5170: . val  - The output sequence value

5172:   Level: intermediate

5174:   Note: This is intended for output that should appear in sequence, for instance
5175:   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.

5177: .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView()
5178: @*/
5179: PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val)
5180: {
5181:   PetscBool      ishdf5;

5188:   PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);
5189:   if (ishdf5) {
5190: #if defined(PETSC_HAVE_HDF5)
5191:     PetscScalar value;

5193:     DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);
5194:     *val = PetscRealPart(value);
5195: #endif
5196:   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
5197:   return(0);
5198: }

5200: /*@
5201:   DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution

5203:   Not collective

5205:   Input Parameter:
5206: . dm - The DM

5208:   Output Parameter:
5209: . useNatural - The flag to build the mapping to a natural order during distribution

5211:   Level: beginner

5213: .seealso: DMSetUseNatural(), DMCreate()
5214: @*/
5215: PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural)
5216: {
5220:   *useNatural = dm->useNatural;
5221:   return(0);
5222: }

5224: /*@
5225:   DMSetUseNatural - Set the flag for creating a mapping to the natural order on distribution

5227:   Collective on dm

5229:   Input Parameters:
5230: + dm - The DM
5231: - useNatural - The flag to build the mapping to a natural order during distribution

5233:   Level: beginner

5235: .seealso: DMGetUseNatural(), DMCreate()
5236: @*/
5237: PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural)
5238: {
5242:   dm->useNatural = useNatural;
5243:   return(0);
5244: }


5247: /*@C
5248:   DMCreateLabel - Create a label of the given name if it does not already exist

5250:   Not Collective

5252:   Input Parameters:
5253: + dm   - The DM object
5254: - name - The label name

5256:   Level: intermediate

5258: .keywords: mesh
5259: .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5260: @*/
5261: PetscErrorCode DMCreateLabel(DM dm, const char name[])
5262: {
5263:   DMLabelLink    next  = dm->labels->next;
5264:   PetscBool      flg   = PETSC_FALSE;

5270:   while (next) {
5271:     PetscStrcmp(name, next->label->name, &flg);
5272:     if (flg) break;
5273:     next = next->next;
5274:   }
5275:   if (!flg) {
5276:     DMLabelLink tmpLabel;

5278:     PetscCalloc1(1, &tmpLabel);
5279:     DMLabelCreate(name, &tmpLabel->label);
5280:     tmpLabel->output = PETSC_TRUE;
5281:     tmpLabel->next   = dm->labels->next;
5282:     dm->labels->next = tmpLabel;
5283:   }
5284:   return(0);
5285: }

5287: /*@C
5288:   DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default

5290:   Not Collective

5292:   Input Parameters:
5293: + dm   - The DM object
5294: . name - The label name
5295: - point - The mesh point

5297:   Output Parameter:
5298: . value - The label value for this point, or -1 if the point is not in the label

5300:   Level: beginner

5302: .keywords: mesh
5303: .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS()
5304: @*/
5305: PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value)
5306: {
5307:   DMLabel        label;

5313:   DMGetLabel(dm, name, &label);
5314:   if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);
5315:   DMLabelGetValue(label, point, value);
5316:   return(0);
5317: }

5319: /*@C
5320:   DMSetLabelValue - Add a point to a Sieve Label with given value

5322:   Not Collective

5324:   Input Parameters:
5325: + dm   - The DM object
5326: . name - The label name
5327: . point - The mesh point
5328: - value - The label value for this point

5330:   Output Parameter:

5332:   Level: beginner

5334: .keywords: mesh
5335: .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue()
5336: @*/
5337: PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
5338: {
5339:   DMLabel        label;

5345:   DMGetLabel(dm, name, &label);
5346:   if (!label) {
5347:     DMCreateLabel(dm, name);
5348:     DMGetLabel(dm, name, &label);
5349:   }
5350:   DMLabelSetValue(label, point, value);
5351:   return(0);
5352: }

5354: /*@C
5355:   DMClearLabelValue - Remove a point from a Sieve Label with given value

5357:   Not Collective

5359:   Input Parameters:
5360: + dm   - The DM object
5361: . name - The label name
5362: . point - The mesh point
5363: - value - The label value for this point

5365:   Output Parameter:

5367:   Level: beginner

5369: .keywords: mesh
5370: .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS()
5371: @*/
5372: PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
5373: {
5374:   DMLabel        label;

5380:   DMGetLabel(dm, name, &label);
5381:   if (!label) return(0);
5382:   DMLabelClearValue(label, point, value);
5383:   return(0);
5384: }

5386: /*@C
5387:   DMGetLabelSize - Get the number of different integer ids in a Label

5389:   Not Collective

5391:   Input Parameters:
5392: + dm   - The DM object
5393: - name - The label name

5395:   Output Parameter:
5396: . size - The number of different integer ids, or 0 if the label does not exist

5398:   Level: beginner

5400: .keywords: mesh
5401: .seealso: DMLabeGetNumValues(), DMSetLabelValue()
5402: @*/
5403: PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size)
5404: {
5405:   DMLabel        label;

5412:   DMGetLabel(dm, name, &label);
5413:   *size = 0;
5414:   if (!label) return(0);
5415:   DMLabelGetNumValues(label, size);
5416:   return(0);
5417: }

5419: /*@C
5420:   DMGetLabelIdIS - Get the integer ids in a label

5422:   Not Collective

5424:   Input Parameters:
5425: + mesh - The DM object
5426: - name - The label name

5428:   Output Parameter:
5429: . ids - The integer ids, or NULL if the label does not exist

5431:   Level: beginner

5433: .keywords: mesh
5434: .seealso: DMLabelGetValueIS(), DMGetLabelSize()
5435: @*/
5436: PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids)
5437: {
5438:   DMLabel        label;

5445:   DMGetLabel(dm, name, &label);
5446:   *ids = NULL;
5447:  if (label) {
5448:     DMLabelGetValueIS(label, ids);
5449:   } else {
5450:     /* returning an empty IS */
5451:     ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);
5452:   }
5453:   return(0);
5454: }

5456: /*@C
5457:   DMGetStratumSize - Get the number of points in a label stratum

5459:   Not Collective

5461:   Input Parameters:
5462: + dm - The DM object
5463: . name - The label name
5464: - value - The stratum value

5466:   Output Parameter:
5467: . size - The stratum size

5469:   Level: beginner

5471: .keywords: mesh
5472: .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds()
5473: @*/
5474: PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size)
5475: {
5476:   DMLabel        label;

5483:   DMGetLabel(dm, name, &label);
5484:   *size = 0;
5485:   if (!label) return(0);
5486:   DMLabelGetStratumSize(label, value, size);
5487:   return(0);
5488: }

5490: /*@C
5491:   DMGetStratumIS - Get the points in a label stratum

5493:   Not Collective

5495:   Input Parameters:
5496: + dm - The DM object
5497: . name - The label name
5498: - value - The stratum value

5500:   Output Parameter:
5501: . points - The stratum points, or NULL if the label does not exist or does not have that value

5503:   Level: beginner

5505: .keywords: mesh
5506: .seealso: DMLabelGetStratumIS(), DMGetStratumSize()
5507: @*/
5508: PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points)
5509: {
5510:   DMLabel        label;

5517:   DMGetLabel(dm, name, &label);
5518:   *points = NULL;
5519:   if (!label) return(0);
5520:   DMLabelGetStratumIS(label, value, points);
5521:   return(0);
5522: }

5524: /*@C
5525:   DMGetStratumIS - Set the points in a label stratum

5527:   Not Collective

5529:   Input Parameters:
5530: + dm - The DM object
5531: . name - The label name
5532: . value - The stratum value
5533: - points - The stratum points

5535:   Level: beginner

5537: .keywords: mesh
5538: .seealso: DMLabelSetStratumIS(), DMGetStratumSize()
5539: @*/
5540: PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points)
5541: {
5542:   DMLabel        label;

5549:   DMGetLabel(dm, name, &label);
5550:   if (!label) return(0);
5551:   DMLabelSetStratumIS(label, value, points);
5552:   return(0);
5553: }

5555: /*@C
5556:   DMClearLabelStratum - Remove all points from a stratum from a Sieve Label

5558:   Not Collective

5560:   Input Parameters:
5561: + dm   - The DM object
5562: . name - The label name
5563: - value - The label value for this point

5565:   Output Parameter:

5567:   Level: beginner

5569: .keywords: mesh
5570: .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue()
5571: @*/
5572: PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value)
5573: {
5574:   DMLabel        label;

5580:   DMGetLabel(dm, name, &label);
5581:   if (!label) return(0);
5582:   DMLabelClearStratum(label, value);
5583:   return(0);
5584: }

5586: /*@
5587:   DMGetNumLabels - Return the number of labels defined by the mesh

5589:   Not Collective

5591:   Input Parameter:
5592: . dm   - The DM object

5594:   Output Parameter:
5595: . numLabels - the number of Labels

5597:   Level: intermediate

5599: .keywords: mesh
5600: .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5601: @*/
5602: PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels)
5603: {
5604:   DMLabelLink next = dm->labels->next;
5605:   PetscInt  n    = 0;

5610:   while (next) {++n; next = next->next;}
5611:   *numLabels = n;
5612:   return(0);
5613: }

5615: /*@C
5616:   DMGetLabelName - Return the name of nth label

5618:   Not Collective

5620:   Input Parameters:
5621: + dm - The DM object
5622: - n  - the label number

5624:   Output Parameter:
5625: . name - the label name

5627:   Level: intermediate

5629: .keywords: mesh
5630: .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5631: @*/
5632: PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name)
5633: {
5634:   DMLabelLink next = dm->labels->next;
5635:   PetscInt  l    = 0;

5640:   while (next) {
5641:     if (l == n) {
5642:       *name = next->label->name;
5643:       return(0);
5644:     }
5645:     ++l;
5646:     next = next->next;
5647:   }
5648:   SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n);
5649: }

5651: /*@C
5652:   DMHasLabel - Determine whether the mesh has a label of a given name

5654:   Not Collective

5656:   Input Parameters:
5657: + dm   - The DM object
5658: - name - The label name

5660:   Output Parameter:
5661: . hasLabel - PETSC_TRUE if the label is present

5663:   Level: intermediate

5665: .keywords: mesh
5666: .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5667: @*/
5668: PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel)
5669: {
5670:   DMLabelLink    next = dm->labels->next;

5677:   *hasLabel = PETSC_FALSE;
5678:   while (next) {
5679:     PetscStrcmp(name, next->label->name, hasLabel);
5680:     if (*hasLabel) break;
5681:     next = next->next;
5682:   }
5683:   return(0);
5684: }

5686: /*@C
5687:   DMGetLabel - Return the label of a given name, or NULL

5689:   Not Collective

5691:   Input Parameters:
5692: + dm   - The DM object
5693: - name - The label name

5695:   Output Parameter:
5696: . label - The DMLabel, or NULL if the label is absent

5698:   Level: intermediate

5700: .keywords: mesh
5701: .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5702: @*/
5703: PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label)
5704: {
5705:   DMLabelLink    next = dm->labels->next;
5706:   PetscBool      hasLabel;

5713:   *label = NULL;
5714:   while (next) {
5715:     PetscStrcmp(name, next->label->name, &hasLabel);
5716:     if (hasLabel) {
5717:       *label = next->label;
5718:       break;
5719:     }
5720:     next = next->next;
5721:   }
5722:   return(0);
5723: }

5725: /*@C
5726:   DMGetLabelByNum - Return the nth label

5728:   Not Collective

5730:   Input Parameters:
5731: + dm - The DM object
5732: - n  - the label number

5734:   Output Parameter:
5735: . label - the label

5737:   Level: intermediate

5739: .keywords: mesh
5740: .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5741: @*/
5742: PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label)
5743: {
5744:   DMLabelLink next = dm->labels->next;
5745:   PetscInt    l    = 0;

5750:   while (next) {
5751:     if (l == n) {
5752:       *label = next->label;
5753:       return(0);
5754:     }
5755:     ++l;
5756:     next = next->next;
5757:   }
5758:   SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n);
5759: }

5761: /*@C
5762:   DMAddLabel - Add the label to this mesh

5764:   Not Collective

5766:   Input Parameters:
5767: + dm   - The DM object
5768: - label - The DMLabel

5770:   Level: developer

5772: .keywords: mesh
5773: .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5774: @*/
5775: PetscErrorCode DMAddLabel(DM dm, DMLabel label)
5776: {
5777:   DMLabelLink    tmpLabel;
5778:   PetscBool      hasLabel;

5783:   DMHasLabel(dm, label->name, &hasLabel);
5784:   if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", label->name);
5785:   PetscCalloc1(1, &tmpLabel);
5786:   tmpLabel->label  = label;
5787:   tmpLabel->output = PETSC_TRUE;
5788:   tmpLabel->next   = dm->labels->next;
5789:   dm->labels->next = tmpLabel;
5790:   return(0);
5791: }

5793: /*@C
5794:   DMRemoveLabel - Remove the label from this mesh

5796:   Not Collective

5798:   Input Parameters:
5799: + dm   - The DM object
5800: - name - The label name

5802:   Output Parameter:
5803: . label - The DMLabel, or NULL if the label is absent

5805:   Level: developer

5807: .keywords: mesh
5808: .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5809: @*/
5810: PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label)
5811: {
5812:   DMLabelLink    next = dm->labels->next;
5813:   DMLabelLink    last = NULL;
5814:   PetscBool      hasLabel;

5819:   DMHasLabel(dm, name, &hasLabel);
5820:   *label = NULL;
5821:   if (!hasLabel) return(0);
5822:   while (next) {
5823:     PetscStrcmp(name, next->label->name, &hasLabel);
5824:     if (hasLabel) {
5825:       if (last) last->next       = next->next;
5826:       else      dm->labels->next = next->next;
5827:       next->next = NULL;
5828:       *label     = next->label;
5829:       PetscStrcmp(name, "depth", &hasLabel);
5830:       if (hasLabel) {
5831:         dm->depthLabel = NULL;
5832:       }
5833:       PetscFree(next);
5834:       break;
5835:     }
5836:     last = next;
5837:     next = next->next;
5838:   }
5839:   return(0);
5840: }

5842: /*@C
5843:   DMGetLabelOutput - Get the output flag for a given label

5845:   Not Collective

5847:   Input Parameters:
5848: + dm   - The DM object
5849: - name - The label name

5851:   Output Parameter:
5852: . output - The flag for output

5854:   Level: developer

5856: .keywords: mesh
5857: .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5858: @*/
5859: PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output)
5860: {
5861:   DMLabelLink    next = dm->labels->next;

5868:   while (next) {
5869:     PetscBool flg;

5871:     PetscStrcmp(name, next->label->name, &flg);
5872:     if (flg) {*output = next->output; return(0);}
5873:     next = next->next;
5874:   }
5875:   SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
5876: }

5878: /*@C
5879:   DMSetLabelOutput - Set the output flag for a given label

5881:   Not Collective

5883:   Input Parameters:
5884: + dm     - The DM object
5885: . name   - The label name
5886: - output - The flag for output

5888:   Level: developer

5890: .keywords: mesh
5891: .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5892: @*/
5893: PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output)
5894: {
5895:   DMLabelLink    next = dm->labels->next;

5901:   while (next) {
5902:     PetscBool flg;

5904:     PetscStrcmp(name, next->label->name, &flg);
5905:     if (flg) {next->output = output; return(0);}
5906:     next = next->next;
5907:   }
5908:   SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
5909: }


5912: /*@
5913:   DMCopyLabels - Copy labels from one mesh to another with a superset of the points

5915:   Collective on DM

5917:   Input Parameter:
5918: . dmA - The DM object with initial labels

5920:   Output Parameter:
5921: . dmB - The DM object with copied labels

5923:   Level: intermediate

5925:   Note: This is typically used when interpolating or otherwise adding to a mesh

5927: .keywords: mesh
5928: .seealso: DMCopyCoordinates(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection()
5929: @*/
5930: PetscErrorCode DMCopyLabels(DM dmA, DM dmB)
5931: {
5932:   PetscInt       numLabels, l;

5936:   if (dmA == dmB) return(0);
5937:   DMGetNumLabels(dmA, &numLabels);
5938:   for (l = 0; l < numLabels; ++l) {
5939:     DMLabel     label, labelNew;
5940:     const char *name;
5941:     PetscBool   flg;

5943:     DMGetLabelName(dmA, l, &name);
5944:     PetscStrcmp(name, "depth", &flg);
5945:     if (flg) continue;
5946:     DMGetLabel(dmA, name, &label);
5947:     DMLabelDuplicate(label, &labelNew);
5948:     DMAddLabel(dmB, labelNew);
5949:   }
5950:   return(0);
5951: }

5953: /*@
5954:   DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement

5956:   Input Parameter:
5957: . dm - The DM object

5959:   Output Parameter:
5960: . cdm - The coarse DM

5962:   Level: intermediate

5964: .seealso: DMSetCoarseDM()
5965: @*/
5966: PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm)
5967: {
5971:   *cdm = dm->coarseMesh;
5972:   return(0);
5973: }

5975: /*@
5976:   DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement

5978:   Input Parameters:
5979: + dm - The DM object
5980: - cdm - The coarse DM

5982:   Level: intermediate

5984: .seealso: DMGetCoarseDM()
5985: @*/
5986: PetscErrorCode DMSetCoarseDM(DM dm, DM cdm)
5987: {

5993:   PetscObjectReference((PetscObject)cdm);
5994:   DMDestroy(&dm->coarseMesh);
5995:   dm->coarseMesh = cdm;
5996:   return(0);
5997: }

5999: /*@
6000:   DMGetFineDM - Get the fine mesh from which this was obtained by refinement

6002:   Input Parameter:
6003: . dm - The DM object

6005:   Output Parameter:
6006: . fdm - The fine DM

6008:   Level: intermediate

6010: .seealso: DMSetFineDM()
6011: @*/
6012: PetscErrorCode DMGetFineDM(DM dm, DM *fdm)
6013: {
6017:   *fdm = dm->fineMesh;
6018:   return(0);
6019: }

6021: /*@
6022:   DMSetFineDM - Set the fine mesh from which this was obtained by refinement

6024:   Input Parameters:
6025: + dm - The DM object
6026: - fdm - The fine DM

6028:   Level: intermediate

6030: .seealso: DMGetFineDM()
6031: @*/
6032: PetscErrorCode DMSetFineDM(DM dm, DM fdm)
6033: {

6039:   PetscObjectReference((PetscObject)fdm);
6040:   DMDestroy(&dm->fineMesh);
6041:   dm->fineMesh = fdm;
6042:   return(0);
6043: }

6045: /*=== DMBoundary code ===*/

6047: PetscErrorCode DMCopyBoundary(DM dm, DM dmNew)
6048: {

6052:   PetscDSCopyBoundary(dm->prob,dmNew->prob);
6053:   return(0);
6054: }

6056: /*@C
6057:   DMAddBoundary - Add a boundary condition to the model

6059:   Input Parameters:
6060: + dm          - The DM, with a PetscDS that matches the problem being constrained
6061: . type        - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
6062: . name        - The BC name
6063: . labelname   - The label defining constrained points
6064: . field       - The field to constrain
6065: . numcomps    - The number of constrained field components
6066: . comps       - An array of constrained component numbers
6067: . bcFunc      - A pointwise function giving boundary values
6068: . numids      - The number of DMLabel ids for constrained points
6069: . ids         - An array of ids for constrained points
6070: - ctx         - An optional user context for bcFunc

6072:   Options Database Keys:
6073: + -bc_<boundary name> <num> - Overrides the boundary ids
6074: - -bc_<boundary name>_comp <num> - Overrides the boundary components

6076:   Level: developer

6078: .seealso: DMGetBoundary()
6079: @*/
6080: PetscErrorCode DMAddBoundary(DM dm, DMBoundaryConditionType type, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(void), PetscInt numids, const PetscInt *ids, void *ctx)
6081: {

6086:   PetscDSAddBoundary(dm->prob,type,name,labelname,field,numcomps,comps,bcFunc,numids,ids,ctx);
6087:   return(0);
6088: }

6090: /*@
6091:   DMGetNumBoundary - Get the number of registered BC

6093:   Input Parameters:
6094: . dm - The mesh object

6096:   Output Parameters:
6097: . numBd - The number of BC

6099:   Level: intermediate

6101: .seealso: DMAddBoundary(), DMGetBoundary()
6102: @*/
6103: PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd)
6104: {

6109:   PetscDSGetNumBoundary(dm->prob,numBd);
6110:   return(0);
6111: }

6113: /*@C
6114:   DMGetBoundary - Get a model boundary condition

6116:   Input Parameters:
6117: + dm          - The mesh object
6118: - bd          - The BC number

6120:   Output Parameters:
6121: + type        - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
6122: . name        - The BC name
6123: . labelname   - The label defining constrained points
6124: . field       - The field to constrain
6125: . numcomps    - The number of constrained field components
6126: . comps       - An array of constrained component numbers
6127: . bcFunc      - A pointwise function giving boundary values
6128: . numids      - The number of DMLabel ids for constrained points
6129: . ids         - An array of ids for constrained points
6130: - ctx         - An optional user context for bcFunc

6132:   Options Database Keys:
6133: + -bc_<boundary name> <num> - Overrides the boundary ids
6134: - -bc_<boundary name>_comp <num> - Overrides the boundary components

6136:   Level: developer

6138: .seealso: DMAddBoundary()
6139: @*/
6140: PetscErrorCode DMGetBoundary(DM dm, PetscInt bd, DMBoundaryConditionType *type, const char **name, const char **labelname, PetscInt *field, PetscInt *numcomps, const PetscInt **comps, void (**func)(void), PetscInt *numids, const PetscInt **ids, void **ctx)
6141: {

6146:   PetscDSGetBoundary(dm->prob,bd,type,name,labelname,field,numcomps,comps,func,numids,ids,ctx);
6147:   return(0);
6148: }

6150: static PetscErrorCode DMPopulateBoundary(DM dm)
6151: {
6152:   DMBoundary *lastnext;
6153:   DSBoundary dsbound;

6157:   dsbound = dm->prob->boundary;
6158:   if (dm->boundary) {
6159:     DMBoundary next = dm->boundary;

6161:     /* quick check to see if the PetscDS has changed */
6162:     if (next->dsboundary == dsbound) return(0);
6163:     /* the PetscDS has changed: tear down and rebuild */
6164:     while (next) {
6165:       DMBoundary b = next;

6167:       next = b->next;
6168:       PetscFree(b);
6169:     }
6170:     dm->boundary = NULL;
6171:   }

6173:   lastnext = &(dm->boundary);
6174:   while (dsbound) {
6175:     DMBoundary dmbound;

6177:     PetscNew(&dmbound);
6178:     dmbound->dsboundary = dsbound;
6179:     DMGetLabel(dm, dsbound->labelname, &(dmbound->label));
6180:     if (!dmbound->label) PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);
6181:     /* push on the back instead of the front so that it is in the same order as in the PetscDS */
6182:     *lastnext = dmbound;
6183:     lastnext = &(dmbound->next);
6184:     dsbound = dsbound->next;
6185:   }
6186:   return(0);
6187: }

6189: PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd)
6190: {
6191:   DMBoundary     b;

6197:   *isBd = PETSC_FALSE;
6198:   DMPopulateBoundary(dm);
6199:   b = dm->boundary;
6200:   while (b && !(*isBd)) {
6201:     DMLabel    label = b->label;
6202:     DSBoundary dsb = b->dsboundary;

6204:     if (label) {
6205:       PetscInt i;

6207:       for (i = 0; i < dsb->numids && !(*isBd); ++i) {
6208:         DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);
6209:       }
6210:     }
6211:     b = b->next;
6212:   }
6213:   return(0);
6214: }

6216: /*@C
6217:   DMProjectFunction - This projects the given function into the function space provided.

6219:   Input Parameters:
6220: + dm      - The DM
6221: . time    - The time
6222: . funcs   - The coordinate functions to evaluate, one per field
6223: . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
6224: - mode    - The insertion mode for values

6226:   Output Parameter:
6227: . X - vector

6229:    Calling sequence of func:
6230: $    func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx);

6232: +  dim - The spatial dimension
6233: .  x   - The coordinates
6234: .  Nf  - The number of fields
6235: .  u   - The output field values
6236: -  ctx - optional user-defined function context

6238:   Level: developer

6240: .seealso: DMComputeL2Diff()
6241: @*/
6242: PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X)
6243: {
6244:   Vec            localX;

6249:   DMGetLocalVector(dm, &localX);
6250:   DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);
6251:   DMLocalToGlobalBegin(dm, localX, mode, X);
6252:   DMLocalToGlobalEnd(dm, localX, mode, X);
6253:   DMRestoreLocalVector(dm, &localX);
6254:   return(0);
6255: }

6257: PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
6258: {

6264:   if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name);
6265:   (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);
6266:   return(0);
6267: }

6269: PetscErrorCode DMProjectFunctionLabel(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X)
6270: {
6271:   Vec            localX;

6276:   DMGetLocalVector(dm, &localX);
6277:   DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);
6278:   DMLocalToGlobalBegin(dm, localX, mode, X);
6279:   DMLocalToGlobalEnd(dm, localX, mode, X);
6280:   DMRestoreLocalVector(dm, &localX);
6281:   return(0);
6282: }

6284: PetscErrorCode DMProjectFunctionLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
6285: {

6291:   if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name);
6292:   (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);
6293:   return(0);
6294: }

6296: PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU,
6297:                                    void (**funcs)(PetscInt, PetscInt, PetscInt,
6298:                                                   const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
6299:                                                   const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
6300:                                                   PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
6301:                                    InsertMode mode, Vec localX)
6302: {

6309:   if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name);
6310:   (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);
6311:   return(0);
6312: }

6314: PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU,
6315:                                         void (**funcs)(PetscInt, PetscInt, PetscInt,
6316:                                                        const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
6317:                                                        const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
6318:                                                        PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
6319:                                         InsertMode mode, Vec localX)
6320: {

6327:   if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name);
6328:   (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);
6329:   return(0);
6330: }

6332: /*@C
6333:   DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h.

6335:   Input Parameters:
6336: + dm    - The DM
6337: . time  - The time
6338: . funcs - The functions to evaluate for each field component
6339: . ctxs  - Optional array of contexts to pass to each function, or NULL.
6340: - X     - The coefficient vector u_h, a global vector

6342:   Output Parameter:
6343: . diff - The diff ||u - u_h||_2

6345:   Level: developer

6347: .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff()
6348: @*/
6349: PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff)
6350: {

6356:   if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name);
6357:   (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);
6358:   return(0);
6359: }

6361: /*@C
6362:   DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h.

6364:   Input Parameters:
6365: + dm    - The DM
6366: , time  - The time
6367: . funcs - The gradient functions to evaluate for each field component
6368: . ctxs  - Optional array of contexts to pass to each function, or NULL.
6369: . X     - The coefficient vector u_h, a global vector
6370: - n     - The vector to project along

6372:   Output Parameter:
6373: . diff - The diff ||(grad u - grad u_h) . n||_2

6375:   Level: developer

6377: .seealso: DMProjectFunction(), DMComputeL2Diff()
6378: @*/
6379: PetscErrorCode DMComputeL2GradientDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, const PetscReal n[], PetscReal *diff)
6380: {

6386:   if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name);
6387:   (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);
6388:   return(0);
6389: }

6391: /*@C
6392:   DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components.

6394:   Input Parameters:
6395: + dm    - The DM
6396: . time  - The time
6397: . funcs - The functions to evaluate for each field component
6398: . ctxs  - Optional array of contexts to pass to each function, or NULL.
6399: - X     - The coefficient vector u_h, a global vector

6401:   Output Parameter:
6402: . diff - The array of differences, ||u^f - u^f_h||_2

6404:   Level: developer

6406: .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff()
6407: @*/
6408: PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[])
6409: {

6415:   if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name);
6416:   (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);
6417:   return(0);
6418: }

6420: /*@C
6421:   DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags.  Specific implementations of DM maybe have
6422:                  specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN.

6424:   Collective on dm

6426:   Input parameters:
6427: + dm - the pre-adaptation DM object
6428: - label - label with the flags

6430:   Output parameters:
6431: . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced.

6433:   Level: intermediate

6435: .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine()
6436: @*/
6437: PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt)
6438: {

6445:   *dmAdapt = NULL;
6446:   if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name);
6447:   (dm->ops->adaptlabel)(dm, label, dmAdapt);
6448:   return(0);
6449: }

6451: /*@C
6452:   DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library.

6454:   Input Parameters:
6455: + dm - The DM object
6456: . metric - The metric to which the mesh is adapted, defined vertex-wise.
6457: - bdLabel - Label for boundary tags, which will be preserved in the output mesh. bdLabel should be NULL if there is no such label, and should be different from "_boundary_".

6459:   Output Parameter:
6460: . dmAdapt  - Pointer to the DM object containing the adapted mesh

6462:   Note: The label in the adapted mesh will be registered under the name of the input DMLabel object

6464:   Level: advanced

6466: .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine()
6467: @*/
6468: PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt)
6469: {

6477:   *dmAdapt = NULL;
6478:   if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name);
6479:   (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);
6480:   return(0);
6481: }

6483: /*@C
6484:  DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors

6486:  Not Collective

6488:  Input Parameter:
6489:  . dm    - The DM

6491:  Output Parameter:
6492:  . nranks - the number of neighbours
6493:  . ranks - the neighbors ranks

6495:  Notes:
6496:  Do not free the array, it is freed when the DM is destroyed.

6498:  Level: beginner

6500:  .seealso: DMDAGetNeighbors(), PetscSFGetRanks()
6501: @*/
6502: PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[])
6503: {

6508:   if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name);
6509:   (dm->ops->getneighbors)(dm,nranks,ranks);
6510:   return(0);
6511: }

6513: #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */

6515: /*
6516:     Converts the input vector to a ghosted vector and then calls the standard coloring code.
6517:     This has be a different function because it requires DM which is not defined in the Mat library
6518: */
6519: PetscErrorCode  MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx)
6520: {

6524:   if (coloring->ctype == IS_COLORING_LOCAL) {
6525:     Vec x1local;
6526:     DM  dm;
6527:     MatGetDM(J,&dm);
6528:     if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM");
6529:     DMGetLocalVector(dm,&x1local);
6530:     DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);
6531:     DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);
6532:     x1   = x1local;
6533:   }
6534:   MatFDColoringApply_AIJ(J,coloring,x1,sctx);
6535:   if (coloring->ctype == IS_COLORING_LOCAL) {
6536:     DM  dm;
6537:     MatGetDM(J,&dm);
6538:     DMRestoreLocalVector(dm,&x1);
6539:   }
6540:   return(0);
6541: }

6543: /*@
6544:     MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring

6546:     Input Parameter:
6547: .    coloring - the MatFDColoring object

6549:     Developer Notes: this routine exists because the PETSc Mat library does not know about the DM objects

6551:     Level: advanced

6553: .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType
6554: @*/
6555: PetscErrorCode  MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring)
6556: {
6558:   coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM;
6559:   return(0);
6560: }