Actual source code: dm.c
petsc-3.10.0 2018-09-12
1: #include <petsc/private/dmimpl.h>
2: #include <petsc/private/dmlabelimpl.h>
3: #include <petsc/private/petscdsimpl.h>
4: #include <petscdmplex.h>
5: #include <petscdmfield.h>
6: #include <petscsf.h>
7: #include <petscds.h>
9: PetscClassId DM_CLASSID;
10: PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal, DM_LocatePoints, DM_Coarsen, DM_Refine, DM_CreateInterpolation, DM_CreateRestriction;
12: const char *const DMBoundaryTypes[] = {"NONE","GHOSTED","MIRROR","PERIODIC","TWIST","DMBoundaryType","DM_BOUNDARY_",0};
14: static PetscErrorCode DMHasCreateInjection_Default(DM dm, PetscBool *flg)
15: {
19: *flg = PETSC_FALSE;
20: return(0);
21: }
23: /*@
24: DMCreate - Creates an empty DM object. The type can then be set with DMSetType().
26: If you never call DMSetType() it will generate an
27: error when you try to use the vector.
29: Collective on MPI_Comm
31: Input Parameter:
32: . comm - The communicator for the DM object
34: Output Parameter:
35: . dm - The DM object
37: Level: beginner
39: .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE, DMPLEX, DMMOAB, DMNETWORK
40: @*/
41: PetscErrorCode DMCreate(MPI_Comm comm,DM *dm)
42: {
43: DM v;
48: *dm = NULL;
49: PetscSysInitializePackage();
50: VecInitializePackage();
51: MatInitializePackage();
52: DMInitializePackage();
54: PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);
56: v->ltogmap = NULL;
57: v->bs = 1;
58: v->coloringtype = IS_COLORING_GLOBAL;
59: PetscSFCreate(comm, &v->sf);
60: PetscSFCreate(comm, &v->defaultSF);
61: v->labels = NULL;
62: v->depthLabel = NULL;
63: v->defaultSection = NULL;
64: v->defaultGlobalSection = NULL;
65: v->defaultConstraintSection = NULL;
66: v->defaultConstraintMat = NULL;
67: v->L = NULL;
68: v->maxCell = NULL;
69: v->bdtype = NULL;
70: v->dimEmbed = PETSC_DEFAULT;
71: v->dim = PETSC_DETERMINE;
72: {
73: PetscInt i;
74: for (i = 0; i < 10; ++i) {
75: v->nullspaceConstructors[i] = NULL;
76: }
77: }
78: PetscDSCreate(comm, &v->prob);
79: v->dmBC = NULL;
80: v->coarseMesh = NULL;
81: v->outputSequenceNum = -1;
82: v->outputSequenceVal = 0.0;
83: DMSetVecType(v,VECSTANDARD);
84: DMSetMatType(v,MATAIJ);
85: PetscNew(&(v->labels));
86: v->labels->refct = 1;
88: v->ops->hascreateinjection = DMHasCreateInjection_Default;
90: *dm = v;
91: return(0);
92: }
94: /*@
95: DMClone - Creates a DM object with the same topology as the original.
97: Collective on MPI_Comm
99: Input Parameter:
100: . dm - The original DM object
102: Output Parameter:
103: . newdm - The new DM object
105: Level: beginner
107: .keywords: DM, topology, create
108: @*/
109: PetscErrorCode DMClone(DM dm, DM *newdm)
110: {
111: PetscSF sf;
112: Vec coords;
113: void *ctx;
114: PetscInt dim, cdim;
120: DMCreate(PetscObjectComm((PetscObject) dm), newdm);
121: PetscFree((*newdm)->labels);
122: dm->labels->refct++;
123: (*newdm)->labels = dm->labels;
124: (*newdm)->depthLabel = dm->depthLabel;
125: DMGetDimension(dm, &dim);
126: DMSetDimension(*newdm, dim);
127: if (dm->ops->clone) {
128: (*dm->ops->clone)(dm, newdm);
129: }
130: (*newdm)->setupcalled = dm->setupcalled;
131: DMGetPointSF(dm, &sf);
132: DMSetPointSF(*newdm, sf);
133: DMGetApplicationContext(dm, &ctx);
134: DMSetApplicationContext(*newdm, ctx);
135: if (dm->coordinateDM) {
136: DM ncdm;
137: PetscSection cs;
138: PetscInt pEnd = -1, pEndMax = -1;
140: DMGetSection(dm->coordinateDM, &cs);
141: if (cs) {PetscSectionGetChart(cs, NULL, &pEnd);}
142: MPI_Allreduce(&pEnd,&pEndMax,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));
143: if (pEndMax >= 0) {
144: DMClone(dm->coordinateDM, &ncdm);
145: DMSetSection(ncdm, cs);
146: DMSetCoordinateDM(*newdm, ncdm);
147: DMDestroy(&ncdm);
148: }
149: }
150: DMGetCoordinateDim(dm, &cdim);
151: DMSetCoordinateDim(*newdm, cdim);
152: DMGetCoordinatesLocal(dm, &coords);
153: if (coords) {
154: DMSetCoordinatesLocal(*newdm, coords);
155: } else {
156: DMGetCoordinates(dm, &coords);
157: if (coords) {DMSetCoordinates(*newdm, coords);}
158: }
159: {
160: PetscBool isper;
161: const PetscReal *maxCell, *L;
162: const DMBoundaryType *bd;
163: DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);
164: DMSetPeriodicity(*newdm, isper, maxCell, L, bd);
165: }
166: return(0);
167: }
169: /*@C
170: DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()
172: Logically Collective on DM
174: Input Parameter:
175: + da - initial distributed array
176: . ctype - the vector type, currently either VECSTANDARD, VECCUDA, or VECVIENNACL
178: Options Database:
179: . -dm_vec_type ctype
181: Level: intermediate
183: .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType, DMGetVecType()
184: @*/
185: PetscErrorCode DMSetVecType(DM da,VecType ctype)
186: {
191: PetscFree(da->vectype);
192: PetscStrallocpy(ctype,(char**)&da->vectype);
193: return(0);
194: }
196: /*@C
197: DMGetVecType - Gets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()
199: Logically Collective on DM
201: Input Parameter:
202: . da - initial distributed array
204: Output Parameter:
205: . ctype - the vector type
207: Level: intermediate
209: .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType
210: @*/
211: PetscErrorCode DMGetVecType(DM da,VecType *ctype)
212: {
215: *ctype = da->vectype;
216: return(0);
217: }
219: /*@
220: VecGetDM - Gets the DM defining the data layout of the vector
222: Not collective
224: Input Parameter:
225: . v - The Vec
227: Output Parameter:
228: . dm - The DM
230: Level: intermediate
232: .seealso: VecSetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType()
233: @*/
234: PetscErrorCode VecGetDM(Vec v, DM *dm)
235: {
241: PetscObjectQuery((PetscObject) v, "__PETSc_dm", (PetscObject*) dm);
242: return(0);
243: }
245: /*@
246: VecSetDM - Sets the DM defining the data layout of the vector.
248: Not collective
250: Input Parameters:
251: + v - The Vec
252: - dm - The DM
254: 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.
256: Level: intermediate
258: .seealso: VecGetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType()
259: @*/
260: PetscErrorCode VecSetDM(Vec v, DM dm)
261: {
267: PetscObjectCompose((PetscObject) v, "__PETSc_dm", (PetscObject) dm);
268: return(0);
269: }
271: /*@C
272: DMSetISColoringType - Sets the type of coloring, global or local, that is created by the DM
274: Logically Collective on DM
276: Input Parameters:
277: + dm - the DM context
278: - ctype - the matrix type
280: Options Database:
281: . -dm_is_coloring_type - global or local
283: Level: intermediate
285: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(),
286: DMGetISColoringType()
287: @*/
288: PetscErrorCode DMSetISColoringType(DM dm,ISColoringType ctype)
289: {
292: dm->coloringtype = ctype;
293: return(0);
294: }
296: /*@C
297: DMGetISColoringType - Gets the type of coloring, global or local, that is created by the DM
299: Logically Collective on DM
301: Input Parameter:
302: . dm - the DM context
304: Output Parameter:
305: . ctype - the matrix type
307: Options Database:
308: . -dm_is_coloring_type - global or local
310: Level: intermediate
312: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(),
313: DMGetISColoringType()
314: @*/
315: PetscErrorCode DMGetISColoringType(DM dm,ISColoringType *ctype)
316: {
319: *ctype = dm->coloringtype;
320: return(0);
321: }
323: /*@C
324: DMSetMatType - Sets the type of matrix created with DMCreateMatrix()
326: Logically Collective on DM
328: Input Parameters:
329: + dm - the DM context
330: - ctype - the matrix type
332: Options Database:
333: . -dm_mat_type ctype
335: Level: intermediate
337: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType()
338: @*/
339: PetscErrorCode DMSetMatType(DM dm,MatType ctype)
340: {
345: PetscFree(dm->mattype);
346: PetscStrallocpy(ctype,(char**)&dm->mattype);
347: return(0);
348: }
350: /*@C
351: DMGetMatType - Gets the type of matrix created with DMCreateMatrix()
353: Logically Collective on DM
355: Input Parameter:
356: . dm - the DM context
358: Output Parameter:
359: . ctype - the matrix type
361: Options Database:
362: . -dm_mat_type ctype
364: Level: intermediate
366: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMSetMatType()
367: @*/
368: PetscErrorCode DMGetMatType(DM dm,MatType *ctype)
369: {
372: *ctype = dm->mattype;
373: return(0);
374: }
376: /*@
377: MatGetDM - Gets the DM defining the data layout of the matrix
379: Not collective
381: Input Parameter:
382: . A - The Mat
384: Output Parameter:
385: . dm - The DM
387: Level: intermediate
389: Developer Note: Since the Mat class doesn't know about the DM class the DM object is associated with
390: the Mat through a PetscObjectCompose() operation
392: .seealso: MatSetDM(), DMCreateMatrix(), DMSetMatType()
393: @*/
394: PetscErrorCode MatGetDM(Mat A, DM *dm)
395: {
401: PetscObjectQuery((PetscObject) A, "__PETSc_dm", (PetscObject*) dm);
402: return(0);
403: }
405: /*@
406: MatSetDM - Sets the DM defining the data layout of the matrix
408: Not collective
410: Input Parameters:
411: + A - The Mat
412: - dm - The DM
414: Level: intermediate
416: Developer Note: Since the Mat class doesn't know about the DM class the DM object is associated with
417: the Mat through a PetscObjectCompose() operation
420: .seealso: MatGetDM(), DMCreateMatrix(), DMSetMatType()
421: @*/
422: PetscErrorCode MatSetDM(Mat A, DM dm)
423: {
429: PetscObjectCompose((PetscObject) A, "__PETSc_dm", (PetscObject) dm);
430: return(0);
431: }
433: /*@C
434: DMSetOptionsPrefix - Sets the prefix used for searching for all
435: DM options in the database.
437: Logically Collective on DM
439: Input Parameter:
440: + da - the DM context
441: - prefix - the prefix to prepend to all option names
443: Notes:
444: A hyphen (-) must NOT be given at the beginning of the prefix name.
445: The first character of all runtime options is AUTOMATICALLY the hyphen.
447: Level: advanced
449: .keywords: DM, set, options, prefix, database
451: .seealso: DMSetFromOptions()
452: @*/
453: PetscErrorCode DMSetOptionsPrefix(DM dm,const char prefix[])
454: {
459: PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);
460: if (dm->sf) {
461: PetscObjectSetOptionsPrefix((PetscObject)dm->sf,prefix);
462: }
463: if (dm->defaultSF) {
464: PetscObjectSetOptionsPrefix((PetscObject)dm->defaultSF,prefix);
465: }
466: return(0);
467: }
469: /*@C
470: DMAppendOptionsPrefix - Appends to the prefix used for searching for all
471: DM options in the database.
473: Logically Collective on DM
475: Input Parameters:
476: + dm - the DM context
477: - prefix - the prefix string to prepend to all DM option requests
479: Notes:
480: A hyphen (-) must NOT be given at the beginning of the prefix name.
481: The first character of all runtime options is AUTOMATICALLY the hyphen.
483: Level: advanced
485: .keywords: DM, append, options, prefix, database
487: .seealso: DMSetOptionsPrefix(), DMGetOptionsPrefix()
488: @*/
489: PetscErrorCode DMAppendOptionsPrefix(DM dm,const char prefix[])
490: {
495: PetscObjectAppendOptionsPrefix((PetscObject)dm,prefix);
496: return(0);
497: }
499: /*@C
500: DMGetOptionsPrefix - Gets the prefix used for searching for all
501: DM options in the database.
503: Not Collective
505: Input Parameters:
506: . dm - the DM context
508: Output Parameters:
509: . prefix - pointer to the prefix string used is returned
511: Notes:
512: On the fortran side, the user should pass in a string 'prefix' of
513: sufficient length to hold the prefix.
515: Level: advanced
517: .keywords: DM, set, options, prefix, database
519: .seealso: DMSetOptionsPrefix(), DMAppendOptionsPrefix()
520: @*/
521: PetscErrorCode DMGetOptionsPrefix(DM dm,const char *prefix[])
522: {
527: PetscObjectGetOptionsPrefix((PetscObject)dm,prefix);
528: return(0);
529: }
531: static PetscErrorCode DMCountNonCyclicReferences(DM dm, PetscBool recurseCoarse, PetscBool recurseFine, PetscInt *ncrefct)
532: {
533: PetscInt i, refct = ((PetscObject) dm)->refct;
534: DMNamedVecLink nlink;
538: *ncrefct = 0;
539: /* count all the circular references of DM and its contained Vecs */
540: for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
541: if (dm->localin[i]) refct--;
542: if (dm->globalin[i]) refct--;
543: }
544: for (nlink=dm->namedglobal; nlink; nlink=nlink->next) refct--;
545: for (nlink=dm->namedlocal; nlink; nlink=nlink->next) refct--;
546: if (dm->x) {
547: DM obj;
548: VecGetDM(dm->x, &obj);
549: if (obj == dm) refct--;
550: }
551: if (dm->coarseMesh && dm->coarseMesh->fineMesh == dm) {
552: refct--;
553: if (recurseCoarse) {
554: PetscInt coarseCount;
556: DMCountNonCyclicReferences(dm->coarseMesh, PETSC_TRUE, PETSC_FALSE,&coarseCount);
557: refct += coarseCount;
558: }
559: }
560: if (dm->fineMesh && dm->fineMesh->coarseMesh == dm) {
561: refct--;
562: if (recurseFine) {
563: PetscInt fineCount;
565: DMCountNonCyclicReferences(dm->fineMesh, PETSC_FALSE, PETSC_TRUE,&fineCount);
566: refct += fineCount;
567: }
568: }
569: *ncrefct = refct;
570: return(0);
571: }
573: PetscErrorCode DMDestroyLabelLinkList(DM dm)
574: {
578: if (!--(dm->labels->refct)) {
579: DMLabelLink next = dm->labels->next;
581: /* destroy the labels */
582: while (next) {
583: DMLabelLink tmp = next->next;
585: DMLabelDestroy(&next->label);
586: PetscFree(next);
587: next = tmp;
588: }
589: PetscFree(dm->labels);
590: }
591: return(0);
592: }
594: /*@
595: DMDestroy - Destroys a vector packer or DM.
597: Collective on DM
599: Input Parameter:
600: . dm - the DM object to destroy
602: Level: developer
604: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
606: @*/
607: PetscErrorCode DMDestroy(DM *dm)
608: {
609: PetscInt i, cnt;
610: DMNamedVecLink nlink,nnext;
614: if (!*dm) return(0);
617: /* count all non-cyclic references in the doubly-linked list of coarse<->fine meshes */
618: DMCountNonCyclicReferences(*dm,PETSC_TRUE,PETSC_TRUE,&cnt);
619: --((PetscObject)(*dm))->refct;
620: if (--cnt > 0) {*dm = 0; return(0);}
621: /*
622: Need this test because the dm references the vectors that
623: reference the dm, so destroying the dm calls destroy on the
624: vectors that cause another destroy on the dm
625: */
626: if (((PetscObject)(*dm))->refct < 0) return(0);
627: ((PetscObject) (*dm))->refct = 0;
628: for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
629: if ((*dm)->localout[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Destroying a DM that has a local vector obtained with DMGetLocalVector()");
630: VecDestroy(&(*dm)->localin[i]);
631: }
632: nnext=(*dm)->namedglobal;
633: (*dm)->namedglobal = NULL;
634: for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named vectors */
635: nnext = nlink->next;
636: if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name);
637: PetscFree(nlink->name);
638: VecDestroy(&nlink->X);
639: PetscFree(nlink);
640: }
641: nnext=(*dm)->namedlocal;
642: (*dm)->namedlocal = NULL;
643: for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named local vectors */
644: nnext = nlink->next;
645: if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name);
646: PetscFree(nlink->name);
647: VecDestroy(&nlink->X);
648: PetscFree(nlink);
649: }
651: /* Destroy the list of hooks */
652: {
653: DMCoarsenHookLink link,next;
654: for (link=(*dm)->coarsenhook; link; link=next) {
655: next = link->next;
656: PetscFree(link);
657: }
658: (*dm)->coarsenhook = NULL;
659: }
660: {
661: DMRefineHookLink link,next;
662: for (link=(*dm)->refinehook; link; link=next) {
663: next = link->next;
664: PetscFree(link);
665: }
666: (*dm)->refinehook = NULL;
667: }
668: {
669: DMSubDomainHookLink link,next;
670: for (link=(*dm)->subdomainhook; link; link=next) {
671: next = link->next;
672: PetscFree(link);
673: }
674: (*dm)->subdomainhook = NULL;
675: }
676: {
677: DMGlobalToLocalHookLink link,next;
678: for (link=(*dm)->gtolhook; link; link=next) {
679: next = link->next;
680: PetscFree(link);
681: }
682: (*dm)->gtolhook = NULL;
683: }
684: {
685: DMLocalToGlobalHookLink link,next;
686: for (link=(*dm)->ltoghook; link; link=next) {
687: next = link->next;
688: PetscFree(link);
689: }
690: (*dm)->ltoghook = NULL;
691: }
692: /* Destroy the work arrays */
693: {
694: DMWorkLink link,next;
695: if ((*dm)->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out");
696: for (link=(*dm)->workin; link; link=next) {
697: next = link->next;
698: PetscFree(link->mem);
699: PetscFree(link);
700: }
701: (*dm)->workin = NULL;
702: }
703: if (!--((*dm)->labels->refct)) {
704: DMLabelLink next = (*dm)->labels->next;
706: /* destroy the labels */
707: while (next) {
708: DMLabelLink tmp = next->next;
710: DMLabelDestroy(&next->label);
711: PetscFree(next);
712: next = tmp;
713: }
714: PetscFree((*dm)->labels);
715: }
716: {
717: DMBoundary next = (*dm)->boundary;
718: while (next) {
719: DMBoundary b = next;
721: next = b->next;
722: PetscFree(b);
723: }
724: }
726: PetscObjectDestroy(&(*dm)->dmksp);
727: PetscObjectDestroy(&(*dm)->dmsnes);
728: PetscObjectDestroy(&(*dm)->dmts);
730: if ((*dm)->ctx && (*dm)->ctxdestroy) {
731: (*(*dm)->ctxdestroy)(&(*dm)->ctx);
732: }
733: VecDestroy(&(*dm)->x);
734: MatFDColoringDestroy(&(*dm)->fd);
735: DMClearGlobalVectors(*dm);
736: ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);
737: PetscFree((*dm)->vectype);
738: PetscFree((*dm)->mattype);
740: PetscSectionDestroy(&(*dm)->defaultSection);
741: PetscSectionDestroy(&(*dm)->defaultGlobalSection);
742: PetscLayoutDestroy(&(*dm)->map);
743: PetscSectionDestroy(&(*dm)->defaultConstraintSection);
744: MatDestroy(&(*dm)->defaultConstraintMat);
745: PetscSFDestroy(&(*dm)->sf);
746: PetscSFDestroy(&(*dm)->defaultSF);
747: if ((*dm)->useNatural) {
748: if ((*dm)->sfNatural) {
749: PetscSFDestroy(&(*dm)->sfNatural);
750: }
751: PetscObjectDereference((PetscObject) (*dm)->sfMigration);
752: }
753: if ((*dm)->coarseMesh && (*dm)->coarseMesh->fineMesh == *dm) {
754: DMSetFineDM((*dm)->coarseMesh,NULL);
755: }
756: DMDestroy(&(*dm)->coarseMesh);
757: if ((*dm)->fineMesh && (*dm)->fineMesh->coarseMesh == *dm) {
758: DMSetCoarseDM((*dm)->fineMesh,NULL);
759: }
760: DMDestroy(&(*dm)->fineMesh);
761: DMFieldDestroy(&(*dm)->coordinateField);
762: DMDestroy(&(*dm)->coordinateDM);
763: VecDestroy(&(*dm)->coordinates);
764: VecDestroy(&(*dm)->coordinatesLocal);
765: PetscFree3((*dm)->L,(*dm)->maxCell,(*dm)->bdtype);
767: PetscDSDestroy(&(*dm)->prob);
768: DMDestroy(&(*dm)->dmBC);
769: /* if memory was published with SAWs then destroy it */
770: PetscObjectSAWsViewOff((PetscObject)*dm);
772: if ((*dm)->ops->destroy) {
773: (*(*dm)->ops->destroy)(*dm);
774: }
775: /* We do not destroy (*dm)->data here so that we can reference count backend objects */
776: PetscHeaderDestroy(dm);
777: return(0);
778: }
780: /*@
781: DMSetUp - sets up the data structures inside a DM object
783: Collective on DM
785: Input Parameter:
786: . dm - the DM object to setup
788: Level: developer
790: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
792: @*/
793: PetscErrorCode DMSetUp(DM dm)
794: {
799: if (dm->setupcalled) return(0);
800: if (dm->ops->setup) {
801: (*dm->ops->setup)(dm);
802: }
803: dm->setupcalled = PETSC_TRUE;
804: return(0);
805: }
807: /*@
808: DMSetFromOptions - sets parameters in a DM from the options database
810: Collective on DM
812: Input Parameter:
813: . dm - the DM object to set options for
815: Options Database:
816: + -dm_preallocate_only - Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros
817: . -dm_vec_type <type> - type of vector to create inside DM
818: . -dm_mat_type <type> - type of matrix to create inside DM
819: - -dm_is_coloring_type - <global or local>
821: Level: developer
823: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
825: @*/
826: PetscErrorCode DMSetFromOptions(DM dm)
827: {
828: char typeName[256];
829: PetscBool flg;
834: if (dm->prob) {
835: PetscDSSetFromOptions(dm->prob);
836: }
837: if (dm->sf) {
838: PetscSFSetFromOptions(dm->sf);
839: }
840: if (dm->defaultSF) {
841: PetscSFSetFromOptions(dm->defaultSF);
842: }
843: PetscObjectOptionsBegin((PetscObject)dm);
844: PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,NULL);
845: PetscOptionsFList("-dm_vec_type","Vector type used for created vectors","DMSetVecType",VecList,dm->vectype,typeName,256,&flg);
846: if (flg) {
847: DMSetVecType(dm,typeName);
848: }
849: PetscOptionsFList("-dm_mat_type","Matrix type used for created matrices","DMSetMatType",MatList,dm->mattype ? dm->mattype : typeName,typeName,sizeof(typeName),&flg);
850: if (flg) {
851: DMSetMatType(dm,typeName);
852: }
853: PetscOptionsEnum("-dm_is_coloring_type","Global or local coloring of Jacobian","DMSetISColoringType",ISColoringTypes,(PetscEnum)dm->coloringtype,(PetscEnum*)&dm->coloringtype,NULL);
854: if (dm->ops->setfromoptions) {
855: (*dm->ops->setfromoptions)(PetscOptionsObject,dm);
856: }
857: /* process any options handlers added with PetscObjectAddOptionsHandler() */
858: PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) dm);
859: PetscOptionsEnd();
860: return(0);
861: }
863: /*@C
864: DMView - Views a DM
866: Collective on DM
868: Input Parameter:
869: + dm - the DM object to view
870: - v - the viewer
872: Level: beginner
874: .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
876: @*/
877: PetscErrorCode DMView(DM dm,PetscViewer v)
878: {
879: PetscErrorCode ierr;
880: PetscBool isbinary;
881: PetscMPIInt size;
882: PetscViewerFormat format;
886: if (!v) {
887: PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm),&v);
888: }
889: PetscViewerGetFormat(v,&format);
890: MPI_Comm_size(PetscObjectComm((PetscObject)dm),&size);
891: if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) return(0);
892: PetscObjectPrintClassNamePrefixType((PetscObject)dm,v);
893: PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERBINARY,&isbinary);
894: if (isbinary) {
895: PetscInt classid = DM_FILE_CLASSID;
896: char type[256];
898: PetscViewerBinaryWrite(v,&classid,1,PETSC_INT,PETSC_FALSE);
899: PetscStrncpy(type,((PetscObject)dm)->type_name,256);
900: PetscViewerBinaryWrite(v,type,256,PETSC_CHAR,PETSC_FALSE);
901: }
902: if (dm->ops->view) {
903: (*dm->ops->view)(dm,v);
904: }
905: return(0);
906: }
908: /*@
909: DMCreateGlobalVector - Creates a global vector from a DM object
911: Collective on DM
913: Input Parameter:
914: . dm - the DM object
916: Output Parameter:
917: . vec - the global vector
919: Level: beginner
921: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
923: @*/
924: PetscErrorCode DMCreateGlobalVector(DM dm,Vec *vec)
925: {
930: (*dm->ops->createglobalvector)(dm,vec);
931: return(0);
932: }
934: /*@
935: DMCreateLocalVector - Creates a local vector from a DM object
937: Not Collective
939: Input Parameter:
940: . dm - the DM object
942: Output Parameter:
943: . vec - the local vector
945: Level: beginner
947: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
949: @*/
950: PetscErrorCode DMCreateLocalVector(DM dm,Vec *vec)
951: {
956: (*dm->ops->createlocalvector)(dm,vec);
957: return(0);
958: }
960: /*@
961: DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM.
963: Collective on DM
965: Input Parameter:
966: . dm - the DM that provides the mapping
968: Output Parameter:
969: . ltog - the mapping
971: Level: intermediate
973: Notes:
974: This mapping can then be used by VecSetLocalToGlobalMapping() or
975: MatSetLocalToGlobalMapping().
977: .seealso: DMCreateLocalVector()
978: @*/
979: PetscErrorCode DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog)
980: {
981: PetscInt bs = -1, bsLocal[2], bsMinMax[2];
987: if (!dm->ltogmap) {
988: PetscSection section, sectionGlobal;
990: DMGetSection(dm, §ion);
991: if (section) {
992: const PetscInt *cdofs;
993: PetscInt *ltog;
994: PetscInt pStart, pEnd, n, p, k, l;
996: DMGetGlobalSection(dm, §ionGlobal);
997: PetscSectionGetChart(section, &pStart, &pEnd);
998: PetscSectionGetStorageSize(section, &n);
999: PetscMalloc1(n, <og); /* We want the local+overlap size */
1000: for (p = pStart, l = 0; p < pEnd; ++p) {
1001: PetscInt bdof, cdof, dof, off, c, cind = 0;
1003: /* Should probably use constrained dofs */
1004: PetscSectionGetDof(section, p, &dof);
1005: PetscSectionGetConstraintDof(section, p, &cdof);
1006: PetscSectionGetConstraintIndices(section, p, &cdofs);
1007: PetscSectionGetOffset(sectionGlobal, p, &off);
1008: /* If you have dofs, and constraints, and they are unequal, we set the blocksize to 1 */
1009: bdof = cdof && (dof-cdof) ? 1 : dof;
1010: if (dof) {
1011: if (bs < 0) {bs = bdof;}
1012: else if (bs != bdof) {bs = 1;}
1013: }
1014: for (c = 0; c < dof; ++c, ++l) {
1015: if ((cind < cdof) && (c == cdofs[cind])) ltog[l] = off < 0 ? off-c : off+c;
1016: else ltog[l] = (off < 0 ? -(off+1) : off) + c;
1017: }
1018: }
1019: /* Must have same blocksize on all procs (some might have no points) */
1020: bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs;
1021: PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);
1022: if (bsMinMax[0] != bsMinMax[1]) {bs = 1;}
1023: else {bs = bsMinMax[0];}
1024: bs = bs < 0 ? 1 : bs;
1025: /* Must reduce indices by blocksize */
1026: if (bs > 1) {
1027: for (l = 0, k = 0; l < n; l += bs, ++k) ltog[k] = ltog[l]/bs;
1028: n /= bs;
1029: }
1030: ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, n, ltog, PETSC_OWN_POINTER, &dm->ltogmap);
1031: PetscLogObjectParent((PetscObject)dm, (PetscObject)dm->ltogmap);
1032: } else {
1033: if (!dm->ops->getlocaltoglobalmapping) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM can not create LocalToGlobalMapping");
1034: (*dm->ops->getlocaltoglobalmapping)(dm);
1035: }
1036: }
1037: *ltog = dm->ltogmap;
1038: return(0);
1039: }
1041: /*@
1042: DMGetBlockSize - Gets the inherent block size associated with a DM
1044: Not Collective
1046: Input Parameter:
1047: . dm - the DM with block structure
1049: Output Parameter:
1050: . bs - the block size, 1 implies no exploitable block structure
1052: Level: intermediate
1054: .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMapping()
1055: @*/
1056: PetscErrorCode DMGetBlockSize(DM dm,PetscInt *bs)
1057: {
1061: if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet");
1062: *bs = dm->bs;
1063: return(0);
1064: }
1066: /*@
1067: DMCreateInterpolation - Gets interpolation matrix between two DM objects
1069: Collective on DM
1071: Input Parameter:
1072: + dm1 - the DM object
1073: - dm2 - the second, finer DM object
1075: Output Parameter:
1076: + mat - the interpolation
1077: - vec - the scaling (optional)
1079: Level: developer
1081: Notes:
1082: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
1083: DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation.
1085: For DMDA objects you can use this interpolation (more precisely the interpolation from the DMGetCoordinateDM()) to interpolate the mesh coordinate vectors
1086: EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic.
1089: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateRestriction()
1091: @*/
1092: PetscErrorCode DMCreateInterpolation(DM dm1,DM dm2,Mat *mat,Vec *vec)
1093: {
1099: PetscLogEventBegin(DM_CreateInterpolation,dm1,dm2,0,0);
1100: (*dm1->ops->createinterpolation)(dm1,dm2,mat,vec);
1101: PetscLogEventEnd(DM_CreateInterpolation,dm1,dm2,0,0);
1102: return(0);
1103: }
1105: /*@
1106: DMCreateRestriction - Gets restriction matrix between two DM objects
1108: Collective on DM
1110: Input Parameter:
1111: + dm1 - the DM object
1112: - dm2 - the second, finer DM object
1114: Output Parameter:
1115: . mat - the restriction
1118: Level: developer
1120: Notes:
1121: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
1122: DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation.
1125: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateInterpolation()
1127: @*/
1128: PetscErrorCode DMCreateRestriction(DM dm1,DM dm2,Mat *mat)
1129: {
1135: PetscLogEventBegin(DM_CreateRestriction,dm1,dm2,0,0);
1136: if (!dm1->ops->createrestriction) SETERRQ(PetscObjectComm((PetscObject)dm1),PETSC_ERR_SUP,"DMCreateRestriction not implemented for this type");
1137: (*dm1->ops->createrestriction)(dm1,dm2,mat);
1138: PetscLogEventEnd(DM_CreateRestriction,dm1,dm2,0,0);
1139: return(0);
1140: }
1142: /*@
1143: DMCreateInjection - Gets injection matrix between two DM objects
1145: Collective on DM
1147: Input Parameter:
1148: + dm1 - the DM object
1149: - dm2 - the second, finer DM object
1151: Output Parameter:
1152: . mat - the injection
1154: Level: developer
1156: Notes:
1157: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
1158: DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection.
1160: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMCreateInterpolation()
1162: @*/
1163: PetscErrorCode DMCreateInjection(DM dm1,DM dm2,Mat *mat)
1164: {
1170: if (!dm1->ops->getinjection) SETERRQ(PetscObjectComm((PetscObject)dm1),PETSC_ERR_SUP,"DMCreateInjection not implemented for this type");
1171: (*dm1->ops->getinjection)(dm1,dm2,mat);
1172: return(0);
1173: }
1175: /*@
1176: DMCreateMassMatrix - Gets mass matrix between two DM objects, M_ij = \int \phi_i \psi_j
1178: Collective on DM
1180: Input Parameter:
1181: + dm1 - the DM object
1182: - dm2 - the second, finer DM object
1184: Output Parameter:
1185: . mat - the interpolation
1187: Level: developer
1189: .seealso DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateRestriction(), DMCreateInterpolation(), DMCreateInjection()
1190: @*/
1191: PetscErrorCode DMCreateMassMatrix(DM dm1, DM dm2, Mat *mat)
1192: {
1198: (*dm1->ops->createmassmatrix)(dm1, dm2, mat);
1199: return(0);
1200: }
1202: /*@
1203: DMCreateColoring - Gets coloring for a DM
1205: Collective on DM
1207: Input Parameter:
1208: + dm - the DM object
1209: - ctype - IS_COLORING_LOCAL or IS_COLORING_GLOBAL
1211: Output Parameter:
1212: . coloring - the coloring
1214: Level: developer
1216: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateMatrix(), DMSetMatType()
1218: @*/
1219: PetscErrorCode DMCreateColoring(DM dm,ISColoringType ctype,ISColoring *coloring)
1220: {
1225: if (!dm->ops->getcoloring) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No coloring for this type of DM yet");
1226: (*dm->ops->getcoloring)(dm,ctype,coloring);
1227: return(0);
1228: }
1230: /*@
1231: DMCreateMatrix - Gets empty Jacobian for a DM
1233: Collective on DM
1235: Input Parameter:
1236: . dm - the DM object
1238: Output Parameter:
1239: . mat - the empty Jacobian
1241: Level: beginner
1243: Notes:
1244: This properly preallocates the number of nonzeros in the sparse matrix so you
1245: do not need to do it yourself.
1247: By default it also sets the nonzero structure and puts in the zero entries. To prevent setting
1248: the nonzero pattern call DMSetMatrixPreallocateOnly()
1250: For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used
1251: internally by PETSc.
1253: For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires
1254: the indices for the global numbering for DMDAs which is complicated.
1256: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMSetMatType()
1258: @*/
1259: PetscErrorCode DMCreateMatrix(DM dm,Mat *mat)
1260: {
1265: MatInitializePackage();
1268: (*dm->ops->creatematrix)(dm,mat);
1269: return(0);
1270: }
1272: /*@
1273: DMSetMatrixPreallocateOnly - When DMCreateMatrix() is called the matrix will be properly
1274: preallocated but the nonzero structure and zero values will not be set.
1276: Logically Collective on DM
1278: Input Parameter:
1279: + dm - the DM
1280: - only - PETSC_TRUE if only want preallocation
1282: Level: developer
1283: .seealso DMCreateMatrix(), DMSetMatrixStructureOnly()
1284: @*/
1285: PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only)
1286: {
1289: dm->prealloc_only = only;
1290: return(0);
1291: }
1293: /*@
1294: DMSetMatrixStructureOnly - When DMCreateMatrix() is called, the matrix structure will be created
1295: but the array for values will not be allocated.
1297: Logically Collective on DM
1299: Input Parameter:
1300: + dm - the DM
1301: - only - PETSC_TRUE if only want matrix stucture
1303: Level: developer
1304: .seealso DMCreateMatrix(), DMSetMatrixPreallocateOnly()
1305: @*/
1306: PetscErrorCode DMSetMatrixStructureOnly(DM dm, PetscBool only)
1307: {
1310: dm->structure_only = only;
1311: return(0);
1312: }
1314: /*@C
1315: DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray()
1317: Not Collective
1319: Input Parameters:
1320: + dm - the DM object
1321: . count - The minium size
1322: - dtype - MPI data type, often MPIU_REAL, MPIU_SCALAR, MPIU_INT)
1324: Output Parameter:
1325: . array - the work array
1327: Level: developer
1329: .seealso DMDestroy(), DMCreate()
1330: @*/
1331: PetscErrorCode DMGetWorkArray(DM dm,PetscInt count,MPI_Datatype dtype,void *mem)
1332: {
1334: DMWorkLink link;
1335: PetscMPIInt dsize;
1340: if (dm->workin) {
1341: link = dm->workin;
1342: dm->workin = dm->workin->next;
1343: } else {
1344: PetscNewLog(dm,&link);
1345: }
1346: MPI_Type_size(dtype,&dsize);
1347: if (((size_t)dsize*count) > link->bytes) {
1348: PetscFree(link->mem);
1349: PetscMalloc(dsize*count,&link->mem);
1350: link->bytes = dsize*count;
1351: }
1352: link->next = dm->workout;
1353: dm->workout = link;
1354: *(void**)mem = link->mem;
1355: return(0);
1356: }
1358: /*@C
1359: DMRestoreWorkArray - Restores a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray()
1361: Not Collective
1363: Input Parameters:
1364: + dm - the DM object
1365: . count - The minium size
1366: - dtype - MPI data type, often MPIU_REAL, MPIU_SCALAR, MPIU_INT
1368: Output Parameter:
1369: . array - the work array
1371: Level: developer
1373: Developer Notes:
1374: count and dtype are ignored, they are only needed for DMGetWorkArray()
1375: .seealso DMDestroy(), DMCreate()
1376: @*/
1377: PetscErrorCode DMRestoreWorkArray(DM dm,PetscInt count,MPI_Datatype dtype,void *mem)
1378: {
1379: DMWorkLink *p,link;
1384: for (p=&dm->workout; (link=*p); p=&link->next) {
1385: if (link->mem == *(void**)mem) {
1386: *p = link->next;
1387: link->next = dm->workin;
1388: dm->workin = link;
1389: *(void**)mem = NULL;
1390: return(0);
1391: }
1392: }
1393: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out");
1394: }
1396: PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt field, MatNullSpace *nullSpace))
1397: {
1400: if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field);
1401: dm->nullspaceConstructors[field] = nullsp;
1402: return(0);
1403: }
1405: PetscErrorCode DMGetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM dm, PetscInt field, MatNullSpace *nullSpace))
1406: {
1409: if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field);
1410: *nullsp = dm->nullspaceConstructors[field];
1411: return(0);
1412: }
1414: /*@C
1415: DMCreateFieldIS - Creates a set of IS objects with the global indices of dofs for each field
1417: Not collective
1419: Input Parameter:
1420: . dm - the DM object
1422: Output Parameters:
1423: + numFields - The number of fields (or NULL if not requested)
1424: . fieldNames - The name for each field (or NULL if not requested)
1425: - fields - The global indices for each field (or NULL if not requested)
1427: Level: intermediate
1429: Notes:
1430: The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1431: PetscFree(), every entry of fields should be destroyed with ISDestroy(), and both arrays should be freed with
1432: PetscFree().
1434: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
1435: @*/
1436: PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields)
1437: {
1438: PetscSection section, sectionGlobal;
1443: if (numFields) {
1445: *numFields = 0;
1446: }
1447: if (fieldNames) {
1449: *fieldNames = NULL;
1450: }
1451: if (fields) {
1453: *fields = NULL;
1454: }
1455: DMGetSection(dm, §ion);
1456: if (section) {
1457: PetscInt *fieldSizes, **fieldIndices;
1458: PetscInt nF, f, pStart, pEnd, p;
1460: DMGetGlobalSection(dm, §ionGlobal);
1461: PetscSectionGetNumFields(section, &nF);
1462: PetscMalloc2(nF,&fieldSizes,nF,&fieldIndices);
1463: PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);
1464: for (f = 0; f < nF; ++f) {
1465: fieldSizes[f] = 0;
1466: }
1467: for (p = pStart; p < pEnd; ++p) {
1468: PetscInt gdof;
1470: PetscSectionGetDof(sectionGlobal, p, &gdof);
1471: if (gdof > 0) {
1472: for (f = 0; f < nF; ++f) {
1473: PetscInt fdof, fcdof;
1475: PetscSectionGetFieldDof(section, p, f, &fdof);
1476: PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);
1477: fieldSizes[f] += fdof-fcdof;
1478: }
1479: }
1480: }
1481: for (f = 0; f < nF; ++f) {
1482: PetscMalloc1(fieldSizes[f], &fieldIndices[f]);
1483: fieldSizes[f] = 0;
1484: }
1485: for (p = pStart; p < pEnd; ++p) {
1486: PetscInt gdof, goff;
1488: PetscSectionGetDof(sectionGlobal, p, &gdof);
1489: if (gdof > 0) {
1490: PetscSectionGetOffset(sectionGlobal, p, &goff);
1491: for (f = 0; f < nF; ++f) {
1492: PetscInt fdof, fcdof, fc;
1494: PetscSectionGetFieldDof(section, p, f, &fdof);
1495: PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);
1496: for (fc = 0; fc < fdof-fcdof; ++fc, ++fieldSizes[f]) {
1497: fieldIndices[f][fieldSizes[f]] = goff++;
1498: }
1499: }
1500: }
1501: }
1502: if (numFields) *numFields = nF;
1503: if (fieldNames) {
1504: PetscMalloc1(nF, fieldNames);
1505: for (f = 0; f < nF; ++f) {
1506: const char *fieldName;
1508: PetscSectionGetFieldName(section, f, &fieldName);
1509: PetscStrallocpy(fieldName, (char**) &(*fieldNames)[f]);
1510: }
1511: }
1512: if (fields) {
1513: PetscMalloc1(nF, fields);
1514: for (f = 0; f < nF; ++f) {
1515: ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]);
1516: }
1517: }
1518: PetscFree2(fieldSizes,fieldIndices);
1519: } else if (dm->ops->createfieldis) {
1520: (*dm->ops->createfieldis)(dm, numFields, fieldNames, fields);
1521: }
1522: return(0);
1523: }
1526: /*@C
1527: DMCreateFieldDecomposition - Returns a list of IS objects defining a decomposition of a problem into subproblems
1528: corresponding to different fields: each IS contains the global indices of the dofs of the
1529: corresponding field. The optional list of DMs define the DM for each subproblem.
1530: Generalizes DMCreateFieldIS().
1532: Not collective
1534: Input Parameter:
1535: . dm - the DM object
1537: Output Parameters:
1538: + len - The number of subproblems in the field decomposition (or NULL if not requested)
1539: . namelist - The name for each field (or NULL if not requested)
1540: . islist - The global indices for each field (or NULL if not requested)
1541: - dmlist - The DMs for each field subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined)
1543: Level: intermediate
1545: Notes:
1546: The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1547: PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(),
1548: and all of the arrays should be freed with PetscFree().
1550: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1551: @*/
1552: PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
1553: {
1558: if (len) {
1560: *len = 0;
1561: }
1562: if (namelist) {
1564: *namelist = 0;
1565: }
1566: if (islist) {
1568: *islist = 0;
1569: }
1570: if (dmlist) {
1572: *dmlist = 0;
1573: }
1574: /*
1575: Is it a good idea to apply the following check across all impls?
1576: Perhaps some impls can have a well-defined decomposition before DMSetUp?
1577: This, however, follows the general principle that accessors are not well-behaved until the object is set up.
1578: */
1579: if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
1580: if (!dm->ops->createfielddecomposition) {
1581: PetscSection section;
1582: PetscInt numFields, f;
1584: DMGetSection(dm, §ion);
1585: if (section) {PetscSectionGetNumFields(section, &numFields);}
1586: if (section && numFields && dm->ops->createsubdm) {
1587: if (len) *len = numFields;
1588: if (namelist) {PetscMalloc1(numFields,namelist);}
1589: if (islist) {PetscMalloc1(numFields,islist);}
1590: if (dmlist) {PetscMalloc1(numFields,dmlist);}
1591: for (f = 0; f < numFields; ++f) {
1592: const char *fieldName;
1594: DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL);
1595: if (namelist) {
1596: PetscSectionGetFieldName(section, f, &fieldName);
1597: PetscStrallocpy(fieldName, (char**) &(*namelist)[f]);
1598: }
1599: }
1600: } else {
1601: DMCreateFieldIS(dm, len, namelist, islist);
1602: /* By default there are no DMs associated with subproblems. */
1603: if (dmlist) *dmlist = NULL;
1604: }
1605: } else {
1606: (*dm->ops->createfielddecomposition)(dm,len,namelist,islist,dmlist);
1607: }
1608: return(0);
1609: }
1611: /*@
1612: DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in.
1613: The fields are defined by DMCreateFieldIS().
1615: Not collective
1617: Input Parameters:
1618: + dm - The DM object
1619: . numFields - The number of fields in this subproblem
1620: - fields - The field numbers of the selected fields
1622: Output Parameters:
1623: + is - The global indices for the subproblem
1624: - subdm - The DM for the subproblem
1626: Level: intermediate
1628: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1629: @*/
1630: PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
1631: {
1639: if (dm->ops->createsubdm) {
1640: (*dm->ops->createsubdm)(dm, numFields, fields, is, subdm);
1641: } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateSubDM implementation defined");
1642: return(0);
1643: }
1645: /*@C
1646: DMCreateSuperDM - Returns an arrays of ISes and DM encapsulating a superproblem defined by the DMs passed in.
1648: Not collective
1650: Input Parameter:
1651: + dms - The DM objects
1652: - len - The number of DMs
1654: Output Parameters:
1655: + is - The global indices for the subproblem, or NULL
1656: - superdm - The DM for the superproblem
1658: Level: intermediate
1660: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1661: @*/
1662: PetscErrorCode DMCreateSuperDM(DM dms[], PetscInt len, IS **is, DM *superdm)
1663: {
1664: PetscInt i;
1672: if (len < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of DMs must be nonnegative: %D", len);
1673: if (len) {
1674: if (dms[0]->ops->createsuperdm) {(*dms[0]->ops->createsuperdm)(dms, len, is, superdm);}
1675: else SETERRQ(PetscObjectComm((PetscObject) dms[0]), PETSC_ERR_SUP, "This type has no DMCreateSuperDM implementation defined");
1676: }
1677: return(0);
1678: }
1681: /*@C
1682: DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems
1683: corresponding to restrictions to pairs nested subdomains: each IS contains the global
1684: indices of the dofs of the corresponding subdomains. The inner subdomains conceptually
1685: define a nonoverlapping covering, while outer subdomains can overlap.
1686: The optional list of DMs define the DM for each subproblem.
1688: Not collective
1690: Input Parameter:
1691: . dm - the DM object
1693: Output Parameters:
1694: + len - The number of subproblems in the domain decomposition (or NULL if not requested)
1695: . namelist - The name for each subdomain (or NULL if not requested)
1696: . innerislist - The global indices for each inner subdomain (or NULL, if not requested)
1697: . outerislist - The global indices for each outer subdomain (or NULL, if not requested)
1698: - dmlist - The DMs for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined)
1700: Level: intermediate
1702: Notes:
1703: The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1704: PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(),
1705: and all of the arrays should be freed with PetscFree().
1707: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateDomainDecompositionDM(), DMCreateFieldDecomposition()
1708: @*/
1709: PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist)
1710: {
1711: PetscErrorCode ierr;
1712: DMSubDomainHookLink link;
1713: PetscInt i,l;
1722: /*
1723: Is it a good idea to apply the following check across all impls?
1724: Perhaps some impls can have a well-defined decomposition before DMSetUp?
1725: This, however, follows the general principle that accessors are not well-behaved until the object is set up.
1726: */
1727: if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
1728: if (dm->ops->createdomaindecomposition) {
1729: (*dm->ops->createdomaindecomposition)(dm,&l,namelist,innerislist,outerislist,dmlist);
1730: /* copy subdomain hooks and context over to the subdomain DMs */
1731: if (dmlist && *dmlist) {
1732: for (i = 0; i < l; i++) {
1733: for (link=dm->subdomainhook; link; link=link->next) {
1734: if (link->ddhook) {(*link->ddhook)(dm,(*dmlist)[i],link->ctx);}
1735: }
1736: if (dm->ctx) (*dmlist)[i]->ctx = dm->ctx;
1737: }
1738: }
1739: if (len) *len = l;
1740: }
1741: return(0);
1742: }
1745: /*@C
1746: DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector
1748: Not collective
1750: Input Parameters:
1751: + dm - the DM object
1752: . n - the number of subdomain scatters
1753: - subdms - the local subdomains
1755: Output Parameters:
1756: + n - the number of scatters returned
1757: . iscat - scatter from global vector to nonoverlapping global vector entries on subdomain
1758: . oscat - scatter from global vector to overlapping global vector entries on subdomain
1759: - gscat - scatter from global vector to local vector on subdomain (fills in ghosts)
1761: Notes:
1762: This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution
1763: of general nonlinear problems with overlapping subdomain methods. While merely having index sets that enable subsets
1764: of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of
1765: solution and residual data.
1767: Level: developer
1769: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1770: @*/
1771: PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat)
1772: {
1778: if (dm->ops->createddscatters) {
1779: (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);
1780: } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateDomainDecompositionScatter implementation defined");
1781: return(0);
1782: }
1784: /*@
1785: DMRefine - Refines a DM object
1787: Collective on DM
1789: Input Parameter:
1790: + dm - the DM object
1791: - comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
1793: Output Parameter:
1794: . dmf - the refined DM, or NULL
1796: Note: If no refinement was done, the return value is NULL
1798: Level: developer
1800: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
1801: @*/
1802: PetscErrorCode DMRefine(DM dm,MPI_Comm comm,DM *dmf)
1803: {
1804: PetscErrorCode ierr;
1805: DMRefineHookLink link;
1809: PetscLogEventBegin(DM_Refine,dm,0,0,0);
1810: if (!dm->ops->refine) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM cannot refine");
1811: (*dm->ops->refine)(dm,comm,dmf);
1812: if (*dmf) {
1813: (*dmf)->ops->creatematrix = dm->ops->creatematrix;
1815: PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);
1817: (*dmf)->ctx = dm->ctx;
1818: (*dmf)->leveldown = dm->leveldown;
1819: (*dmf)->levelup = dm->levelup + 1;
1821: DMSetMatType(*dmf,dm->mattype);
1822: for (link=dm->refinehook; link; link=link->next) {
1823: if (link->refinehook) {
1824: (*link->refinehook)(dm,*dmf,link->ctx);
1825: }
1826: }
1827: }
1828: PetscLogEventEnd(DM_Refine,dm,0,0,0);
1829: return(0);
1830: }
1832: /*@C
1833: DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid
1835: Logically Collective
1837: Input Arguments:
1838: + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level
1839: . refinehook - function to run when setting up a coarser level
1840: . interphook - function to run to update data on finer levels (once per SNESSolve())
1841: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
1843: Calling sequence of refinehook:
1844: $ refinehook(DM coarse,DM fine,void *ctx);
1846: + coarse - coarse level DM
1847: . fine - fine level DM to interpolate problem to
1848: - ctx - optional user-defined function context
1850: Calling sequence for interphook:
1851: $ interphook(DM coarse,Mat interp,DM fine,void *ctx)
1853: + coarse - coarse level DM
1854: . interp - matrix interpolating a coarse-level solution to the finer grid
1855: . fine - fine level DM to update
1856: - ctx - optional user-defined function context
1858: Level: advanced
1860: Notes:
1861: This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing
1863: If this function is called multiple times, the hooks will be run in the order they are added.
1865: This function is currently not available from Fortran.
1867: .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1868: @*/
1869: PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx)
1870: {
1871: PetscErrorCode ierr;
1872: DMRefineHookLink link,*p;
1876: for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */
1877: if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) return(0);
1878: }
1879: PetscNew(&link);
1880: link->refinehook = refinehook;
1881: link->interphook = interphook;
1882: link->ctx = ctx;
1883: link->next = NULL;
1884: *p = link;
1885: return(0);
1886: }
1888: /*@C
1889: DMRefineHookRemove - remove a callback from the list of hooks to be run when interpolating a nonlinear problem to a finer grid
1891: Logically Collective
1893: Input Arguments:
1894: + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level
1895: . refinehook - function to run when setting up a coarser level
1896: . interphook - function to run to update data on finer levels (once per SNESSolve())
1897: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
1899: Level: advanced
1901: Notes:
1902: This function does nothing if the hook is not in the list.
1904: This function is currently not available from Fortran.
1906: .seealso: DMCoarsenHookRemove(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1907: @*/
1908: PetscErrorCode DMRefineHookRemove(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx)
1909: {
1910: PetscErrorCode ierr;
1911: DMRefineHookLink link,*p;
1915: for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Search the list of current hooks */
1916: if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) {
1917: link = *p;
1918: *p = link->next;
1919: PetscFree(link);
1920: break;
1921: }
1922: }
1923: return(0);
1924: }
1926: /*@
1927: DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd()
1929: Collective if any hooks are
1931: Input Arguments:
1932: + coarse - coarser DM to use as a base
1933: . interp - interpolation matrix, apply using MatInterpolate()
1934: - fine - finer DM to update
1936: Level: developer
1938: .seealso: DMRefineHookAdd(), MatInterpolate()
1939: @*/
1940: PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine)
1941: {
1942: PetscErrorCode ierr;
1943: DMRefineHookLink link;
1946: for (link=fine->refinehook; link; link=link->next) {
1947: if (link->interphook) {
1948: (*link->interphook)(coarse,interp,fine,link->ctx);
1949: }
1950: }
1951: return(0);
1952: }
1954: /*@
1955: DMGetRefineLevel - Get's the number of refinements that have generated this DM.
1957: Not Collective
1959: Input Parameter:
1960: . dm - the DM object
1962: Output Parameter:
1963: . level - number of refinements
1965: Level: developer
1967: .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
1969: @*/
1970: PetscErrorCode DMGetRefineLevel(DM dm,PetscInt *level)
1971: {
1974: *level = dm->levelup;
1975: return(0);
1976: }
1978: /*@
1979: DMSetRefineLevel - Set's the number of refinements that have generated this DM.
1981: Not Collective
1983: Input Parameter:
1984: + dm - the DM object
1985: - level - number of refinements
1987: Level: advanced
1989: Notes:
1990: This value is used by PCMG to determine how many multigrid levels to use
1992: .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
1994: @*/
1995: PetscErrorCode DMSetRefineLevel(DM dm,PetscInt level)
1996: {
1999: dm->levelup = level;
2000: return(0);
2001: }
2003: /*@C
2004: DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called
2006: Logically Collective
2008: Input Arguments:
2009: + dm - the DM
2010: . beginhook - function to run at the beginning of DMGlobalToLocalBegin()
2011: . endhook - function to run after DMGlobalToLocalEnd() has completed
2012: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2014: Calling sequence for beginhook:
2015: $ beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)
2017: + dm - global DM
2018: . g - global vector
2019: . mode - mode
2020: . l - local vector
2021: - ctx - optional user-defined function context
2024: Calling sequence for endhook:
2025: $ endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)
2027: + global - global DM
2028: - ctx - optional user-defined function context
2030: Level: advanced
2032: .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2033: @*/
2034: PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx)
2035: {
2036: PetscErrorCode ierr;
2037: DMGlobalToLocalHookLink link,*p;
2041: for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2042: PetscNew(&link);
2043: link->beginhook = beginhook;
2044: link->endhook = endhook;
2045: link->ctx = ctx;
2046: link->next = NULL;
2047: *p = link;
2048: return(0);
2049: }
2051: static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx)
2052: {
2053: Mat cMat;
2054: Vec cVec;
2055: PetscSection section, cSec;
2056: PetscInt pStart, pEnd, p, dof;
2061: DMGetDefaultConstraints(dm,&cSec,&cMat);
2062: if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) {
2063: PetscInt nRows;
2065: MatGetSize(cMat,&nRows,NULL);
2066: if (nRows <= 0) return(0);
2067: DMGetSection(dm,§ion);
2068: MatCreateVecs(cMat,NULL,&cVec);
2069: MatMult(cMat,l,cVec);
2070: PetscSectionGetChart(cSec,&pStart,&pEnd);
2071: for (p = pStart; p < pEnd; p++) {
2072: PetscSectionGetDof(cSec,p,&dof);
2073: if (dof) {
2074: PetscScalar *vals;
2075: VecGetValuesSection(cVec,cSec,p,&vals);
2076: VecSetValuesSection(l,section,p,vals,INSERT_ALL_VALUES);
2077: }
2078: }
2079: VecDestroy(&cVec);
2080: }
2081: return(0);
2082: }
2084: /*@
2085: DMGlobalToLocalBegin - Begins updating local vectors from global vector
2087: Neighbor-wise Collective on DM
2089: Input Parameters:
2090: + dm - the DM object
2091: . g - the global vector
2092: . mode - INSERT_VALUES or ADD_VALUES
2093: - l - the local vector
2096: Level: beginner
2098: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2100: @*/
2101: PetscErrorCode DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
2102: {
2103: PetscSF sf;
2104: PetscErrorCode ierr;
2105: DMGlobalToLocalHookLink link;
2109: for (link=dm->gtolhook; link; link=link->next) {
2110: if (link->beginhook) {
2111: (*link->beginhook)(dm,g,mode,l,link->ctx);
2112: }
2113: }
2114: DMGetDefaultSF(dm, &sf);
2115: if (sf) {
2116: const PetscScalar *gArray;
2117: PetscScalar *lArray;
2119: if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2120: VecGetArray(l, &lArray);
2121: VecGetArrayRead(g, &gArray);
2122: PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);
2123: VecRestoreArray(l, &lArray);
2124: VecRestoreArrayRead(g, &gArray);
2125: } else {
2126: (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
2127: }
2128: return(0);
2129: }
2131: /*@
2132: DMGlobalToLocalEnd - Ends updating local vectors from global vector
2134: Neighbor-wise Collective on DM
2136: Input Parameters:
2137: + dm - the DM object
2138: . g - the global vector
2139: . mode - INSERT_VALUES or ADD_VALUES
2140: - l - the local vector
2143: Level: beginner
2145: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2147: @*/
2148: PetscErrorCode DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
2149: {
2150: PetscSF sf;
2151: PetscErrorCode ierr;
2152: const PetscScalar *gArray;
2153: PetscScalar *lArray;
2154: DMGlobalToLocalHookLink link;
2158: DMGetDefaultSF(dm, &sf);
2159: if (sf) {
2160: if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2162: VecGetArray(l, &lArray);
2163: VecGetArrayRead(g, &gArray);
2164: PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);
2165: VecRestoreArray(l, &lArray);
2166: VecRestoreArrayRead(g, &gArray);
2167: } else {
2168: (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
2169: }
2170: DMGlobalToLocalHook_Constraints(dm,g,mode,l,NULL);
2171: for (link=dm->gtolhook; link; link=link->next) {
2172: if (link->endhook) {(*link->endhook)(dm,g,mode,l,link->ctx);}
2173: }
2174: return(0);
2175: }
2177: /*@C
2178: DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called
2180: Logically Collective
2182: Input Arguments:
2183: + dm - the DM
2184: . beginhook - function to run at the beginning of DMLocalToGlobalBegin()
2185: . endhook - function to run after DMLocalToGlobalEnd() has completed
2186: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2188: Calling sequence for beginhook:
2189: $ beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)
2191: + dm - global DM
2192: . l - local vector
2193: . mode - mode
2194: . g - global vector
2195: - ctx - optional user-defined function context
2198: Calling sequence for endhook:
2199: $ endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)
2201: + global - global DM
2202: . l - local vector
2203: . mode - mode
2204: . g - global vector
2205: - ctx - optional user-defined function context
2207: Level: advanced
2209: .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2210: @*/
2211: PetscErrorCode DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx)
2212: {
2213: PetscErrorCode ierr;
2214: DMLocalToGlobalHookLink link,*p;
2218: for (p=&dm->ltoghook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2219: PetscNew(&link);
2220: link->beginhook = beginhook;
2221: link->endhook = endhook;
2222: link->ctx = ctx;
2223: link->next = NULL;
2224: *p = link;
2225: return(0);
2226: }
2228: static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx)
2229: {
2230: Mat cMat;
2231: Vec cVec;
2232: PetscSection section, cSec;
2233: PetscInt pStart, pEnd, p, dof;
2238: DMGetDefaultConstraints(dm,&cSec,&cMat);
2239: if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) {
2240: PetscInt nRows;
2242: MatGetSize(cMat,&nRows,NULL);
2243: if (nRows <= 0) return(0);
2244: DMGetSection(dm,§ion);
2245: MatCreateVecs(cMat,NULL,&cVec);
2246: PetscSectionGetChart(cSec,&pStart,&pEnd);
2247: for (p = pStart; p < pEnd; p++) {
2248: PetscSectionGetDof(cSec,p,&dof);
2249: if (dof) {
2250: PetscInt d;
2251: PetscScalar *vals;
2252: VecGetValuesSection(l,section,p,&vals);
2253: VecSetValuesSection(cVec,cSec,p,vals,mode);
2254: /* for this to be the true transpose, we have to zero the values that
2255: * we just extracted */
2256: for (d = 0; d < dof; d++) {
2257: vals[d] = 0.;
2258: }
2259: }
2260: }
2261: MatMultTransposeAdd(cMat,cVec,l,l);
2262: VecDestroy(&cVec);
2263: }
2264: return(0);
2265: }
2267: /*@
2268: DMLocalToGlobalBegin - updates global vectors from local vectors
2270: Neighbor-wise Collective on DM
2272: Input Parameters:
2273: + dm - the DM object
2274: . l - the local vector
2275: . 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.
2276: - g - the global vector
2278: Notes:
2279: In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation.
2280: INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one.
2282: Level: beginner
2284: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin()
2286: @*/
2287: PetscErrorCode DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g)
2288: {
2289: PetscSF sf;
2290: PetscSection s, gs;
2291: DMLocalToGlobalHookLink link;
2292: const PetscScalar *lArray;
2293: PetscScalar *gArray;
2294: PetscBool isInsert;
2295: PetscErrorCode ierr;
2299: for (link=dm->ltoghook; link; link=link->next) {
2300: if (link->beginhook) {
2301: (*link->beginhook)(dm,l,mode,g,link->ctx);
2302: }
2303: }
2304: DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);
2305: DMGetDefaultSF(dm, &sf);
2306: DMGetSection(dm, &s);
2307: switch (mode) {
2308: case INSERT_VALUES:
2309: case INSERT_ALL_VALUES:
2310: case INSERT_BC_VALUES:
2311: isInsert = PETSC_TRUE; break;
2312: case ADD_VALUES:
2313: case ADD_ALL_VALUES:
2314: case ADD_BC_VALUES:
2315: isInsert = PETSC_FALSE; break;
2316: default:
2317: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2318: }
2319: if (sf && !isInsert) {
2320: VecGetArrayRead(l, &lArray);
2321: VecGetArray(g, &gArray);
2322: PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);
2323: VecRestoreArrayRead(l, &lArray);
2324: VecRestoreArray(g, &gArray);
2325: } else if (s && isInsert) {
2326: PetscInt gStart, pStart, pEnd, p;
2328: DMGetGlobalSection(dm, &gs);
2329: PetscSectionGetChart(s, &pStart, &pEnd);
2330: VecGetOwnershipRange(g, &gStart, NULL);
2331: VecGetArrayRead(l, &lArray);
2332: VecGetArray(g, &gArray);
2333: for (p = pStart; p < pEnd; ++p) {
2334: PetscInt dof, gdof, cdof, gcdof, off, goff, d, e;
2336: PetscSectionGetDof(s, p, &dof);
2337: PetscSectionGetDof(gs, p, &gdof);
2338: PetscSectionGetConstraintDof(s, p, &cdof);
2339: PetscSectionGetConstraintDof(gs, p, &gcdof);
2340: PetscSectionGetOffset(s, p, &off);
2341: PetscSectionGetOffset(gs, p, &goff);
2342: /* Ignore off-process data and points with no global data */
2343: if (!gdof || goff < 0) continue;
2344: 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);
2345: /* If no constraints are enforced in the global vector */
2346: if (!gcdof) {
2347: for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d];
2348: /* If constraints are enforced in the global vector */
2349: } else if (cdof == gcdof) {
2350: const PetscInt *cdofs;
2351: PetscInt cind = 0;
2353: PetscSectionGetConstraintIndices(s, p, &cdofs);
2354: for (d = 0, e = 0; d < dof; ++d) {
2355: if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;}
2356: gArray[goff-gStart+e++] = lArray[off+d];
2357: }
2358: } 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);
2359: }
2360: VecRestoreArrayRead(l, &lArray);
2361: VecRestoreArray(g, &gArray);
2362: } else {
2363: (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);
2364: }
2365: return(0);
2366: }
2368: /*@
2369: DMLocalToGlobalEnd - updates global vectors from local vectors
2371: Neighbor-wise Collective on DM
2373: Input Parameters:
2374: + dm - the DM object
2375: . l - the local vector
2376: . mode - INSERT_VALUES or ADD_VALUES
2377: - g - the global vector
2380: Level: beginner
2382: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd()
2384: @*/
2385: PetscErrorCode DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g)
2386: {
2387: PetscSF sf;
2388: PetscSection s;
2389: DMLocalToGlobalHookLink link;
2390: PetscBool isInsert;
2391: PetscErrorCode ierr;
2395: DMGetDefaultSF(dm, &sf);
2396: DMGetSection(dm, &s);
2397: switch (mode) {
2398: case INSERT_VALUES:
2399: case INSERT_ALL_VALUES:
2400: isInsert = PETSC_TRUE; break;
2401: case ADD_VALUES:
2402: case ADD_ALL_VALUES:
2403: isInsert = PETSC_FALSE; break;
2404: default:
2405: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2406: }
2407: if (sf && !isInsert) {
2408: const PetscScalar *lArray;
2409: PetscScalar *gArray;
2411: VecGetArrayRead(l, &lArray);
2412: VecGetArray(g, &gArray);
2413: PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);
2414: VecRestoreArrayRead(l, &lArray);
2415: VecRestoreArray(g, &gArray);
2416: } else if (s && isInsert) {
2417: } else {
2418: (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);
2419: }
2420: for (link=dm->ltoghook; link; link=link->next) {
2421: if (link->endhook) {(*link->endhook)(dm,g,mode,l,link->ctx);}
2422: }
2423: return(0);
2424: }
2426: /*@
2427: DMLocalToLocalBegin - Maps from a local vector (including ghost points
2428: that contain irrelevant values) to another local vector where the ghost
2429: points in the second are set correctly. Must be followed by DMLocalToLocalEnd().
2431: Neighbor-wise Collective on DM and Vec
2433: Input Parameters:
2434: + dm - the DM object
2435: . g - the original local vector
2436: - mode - one of INSERT_VALUES or ADD_VALUES
2438: Output Parameter:
2439: . l - the local vector with correct ghost values
2441: Level: intermediate
2443: Notes:
2444: The local vectors used here need not be the same as those
2445: obtained from DMCreateLocalVector(), BUT they
2446: must have the same parallel data layout; they could, for example, be
2447: obtained with VecDuplicate() from the DM originating vectors.
2449: .keywords: DM, local-to-local, begin
2450: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2452: @*/
2453: PetscErrorCode DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
2454: {
2455: PetscErrorCode ierr;
2459: if (!dm->ops->localtolocalbegin) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps");
2460: (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
2461: return(0);
2462: }
2464: /*@
2465: DMLocalToLocalEnd - Maps from a local vector (including ghost points
2466: that contain irrelevant values) to another local vector where the ghost
2467: points in the second are set correctly. Must be preceded by DMLocalToLocalBegin().
2469: Neighbor-wise Collective on DM and Vec
2471: Input Parameters:
2472: + da - the DM object
2473: . g - the original local vector
2474: - mode - one of INSERT_VALUES or ADD_VALUES
2476: Output Parameter:
2477: . l - the local vector with correct ghost values
2479: Level: intermediate
2481: Notes:
2482: The local vectors used here need not be the same as those
2483: obtained from DMCreateLocalVector(), BUT they
2484: must have the same parallel data layout; they could, for example, be
2485: obtained with VecDuplicate() from the DM originating vectors.
2487: .keywords: DM, local-to-local, end
2488: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2490: @*/
2491: PetscErrorCode DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
2492: {
2493: PetscErrorCode ierr;
2497: if (!dm->ops->localtolocalend) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps");
2498: (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
2499: return(0);
2500: }
2503: /*@
2504: DMCoarsen - Coarsens a DM object
2506: Collective on DM
2508: Input Parameter:
2509: + dm - the DM object
2510: - comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
2512: Output Parameter:
2513: . dmc - the coarsened DM
2515: Level: developer
2517: .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2519: @*/
2520: PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
2521: {
2522: PetscErrorCode ierr;
2523: DMCoarsenHookLink link;
2527: if (!dm->ops->coarsen) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM cannot coarsen");
2528: PetscLogEventBegin(DM_Coarsen,dm,0,0,0);
2529: (*dm->ops->coarsen)(dm, comm, dmc);
2530: if (!(*dmc)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced");
2531: DMSetCoarseDM(dm,*dmc);
2532: (*dmc)->ops->creatematrix = dm->ops->creatematrix;
2533: PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);
2534: (*dmc)->ctx = dm->ctx;
2535: (*dmc)->levelup = dm->levelup;
2536: (*dmc)->leveldown = dm->leveldown + 1;
2537: DMSetMatType(*dmc,dm->mattype);
2538: for (link=dm->coarsenhook; link; link=link->next) {
2539: if (link->coarsenhook) {(*link->coarsenhook)(dm,*dmc,link->ctx);}
2540: }
2541: PetscLogEventEnd(DM_Coarsen,dm,0,0,0);
2542: return(0);
2543: }
2545: /*@C
2546: DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid
2548: Logically Collective
2550: Input Arguments:
2551: + fine - nonlinear solver context on which to run a hook when restricting to a coarser level
2552: . coarsenhook - function to run when setting up a coarser level
2553: . restricthook - function to run to update data on coarser levels (once per SNESSolve())
2554: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2556: Calling sequence of coarsenhook:
2557: $ coarsenhook(DM fine,DM coarse,void *ctx);
2559: + fine - fine level DM
2560: . coarse - coarse level DM to restrict problem to
2561: - ctx - optional user-defined function context
2563: Calling sequence for restricthook:
2564: $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx)
2566: + fine - fine level DM
2567: . mrestrict - matrix restricting a fine-level solution to the coarse grid
2568: . rscale - scaling vector for restriction
2569: . inject - matrix restricting by injection
2570: . coarse - coarse level DM to update
2571: - ctx - optional user-defined function context
2573: Level: advanced
2575: Notes:
2576: This function is only needed if auxiliary data needs to be set up on coarse grids.
2578: If this function is called multiple times, the hooks will be run in the order they are added.
2580: In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
2581: extract the finest level information from its context (instead of from the SNES).
2583: This function is currently not available from Fortran.
2585: .seealso: DMCoarsenHookRemove(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2586: @*/
2587: PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx)
2588: {
2589: PetscErrorCode ierr;
2590: DMCoarsenHookLink link,*p;
2594: for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */
2595: if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) return(0);
2596: }
2597: PetscNew(&link);
2598: link->coarsenhook = coarsenhook;
2599: link->restricthook = restricthook;
2600: link->ctx = ctx;
2601: link->next = NULL;
2602: *p = link;
2603: return(0);
2604: }
2606: /*@C
2607: DMCoarsenHookRemove - remove a callback from the list of hooks to be run when restricting a nonlinear problem to the coarse grid
2609: Logically Collective
2611: Input Arguments:
2612: + fine - nonlinear solver context on which to run a hook when restricting to a coarser level
2613: . coarsenhook - function to run when setting up a coarser level
2614: . restricthook - function to run to update data on coarser levels (once per SNESSolve())
2615: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2617: Level: advanced
2619: Notes:
2620: This function does nothing if the hook is not in the list.
2622: This function is currently not available from Fortran.
2624: .seealso: DMCoarsenHookAdd(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2625: @*/
2626: PetscErrorCode DMCoarsenHookRemove(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx)
2627: {
2628: PetscErrorCode ierr;
2629: DMCoarsenHookLink link,*p;
2633: for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Search the list of current hooks */
2634: if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
2635: link = *p;
2636: *p = link->next;
2637: PetscFree(link);
2638: break;
2639: }
2640: }
2641: return(0);
2642: }
2645: /*@
2646: DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd()
2648: Collective if any hooks are
2650: Input Arguments:
2651: + fine - finer DM to use as a base
2652: . restrct - restriction matrix, apply using MatRestrict()
2653: . rscale - scaling vector for restriction
2654: . inject - injection matrix, also use MatRestrict()
2655: - coarse - coarser DM to update
2657: Level: developer
2659: .seealso: DMCoarsenHookAdd(), MatRestrict()
2660: @*/
2661: PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse)
2662: {
2663: PetscErrorCode ierr;
2664: DMCoarsenHookLink link;
2667: for (link=fine->coarsenhook; link; link=link->next) {
2668: if (link->restricthook) {
2669: (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);
2670: }
2671: }
2672: return(0);
2673: }
2675: /*@C
2676: DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid
2678: Logically Collective
2680: Input Arguments:
2681: + global - global DM
2682: . ddhook - function to run to pass data to the decomposition DM upon its creation
2683: . restricthook - function to run to update data on block solve (at the beginning of the block solve)
2684: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2687: Calling sequence for ddhook:
2688: $ ddhook(DM global,DM block,void *ctx)
2690: + global - global DM
2691: . block - block DM
2692: - ctx - optional user-defined function context
2694: Calling sequence for restricthook:
2695: $ restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx)
2697: + global - global DM
2698: . out - scatter to the outer (with ghost and overlap points) block vector
2699: . in - scatter to block vector values only owned locally
2700: . block - block DM
2701: - ctx - optional user-defined function context
2703: Level: advanced
2705: Notes:
2706: This function is only needed if auxiliary data needs to be set up on subdomain DMs.
2708: If this function is called multiple times, the hooks will be run in the order they are added.
2710: In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
2711: extract the global information from its context (instead of from the SNES).
2713: This function is currently not available from Fortran.
2715: .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2716: @*/
2717: PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx)
2718: {
2719: PetscErrorCode ierr;
2720: DMSubDomainHookLink link,*p;
2724: for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */
2725: if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) return(0);
2726: }
2727: PetscNew(&link);
2728: link->restricthook = restricthook;
2729: link->ddhook = ddhook;
2730: link->ctx = ctx;
2731: link->next = NULL;
2732: *p = link;
2733: return(0);
2734: }
2736: /*@C
2737: DMSubDomainHookRemove - remove a callback from the list to be run when restricting a problem to the coarse grid
2739: Logically Collective
2741: Input Arguments:
2742: + global - global DM
2743: . ddhook - function to run to pass data to the decomposition DM upon its creation
2744: . restricthook - function to run to update data on block solve (at the beginning of the block solve)
2745: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2747: Level: advanced
2749: Notes:
2751: This function is currently not available from Fortran.
2753: .seealso: DMSubDomainHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2754: @*/
2755: PetscErrorCode DMSubDomainHookRemove(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx)
2756: {
2757: PetscErrorCode ierr;
2758: DMSubDomainHookLink link,*p;
2762: for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Search the list of current hooks */
2763: if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
2764: link = *p;
2765: *p = link->next;
2766: PetscFree(link);
2767: break;
2768: }
2769: }
2770: return(0);
2771: }
2773: /*@
2774: DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd()
2776: Collective if any hooks are
2778: Input Arguments:
2779: + fine - finer DM to use as a base
2780: . oscatter - scatter from domain global vector filling subdomain global vector with overlap
2781: . gscatter - scatter from domain global vector filling subdomain local vector with ghosts
2782: - coarse - coarer DM to update
2784: Level: developer
2786: .seealso: DMCoarsenHookAdd(), MatRestrict()
2787: @*/
2788: PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm)
2789: {
2790: PetscErrorCode ierr;
2791: DMSubDomainHookLink link;
2794: for (link=global->subdomainhook; link; link=link->next) {
2795: if (link->restricthook) {
2796: (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);
2797: }
2798: }
2799: return(0);
2800: }
2802: /*@
2803: DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM.
2805: Not Collective
2807: Input Parameter:
2808: . dm - the DM object
2810: Output Parameter:
2811: . level - number of coarsenings
2813: Level: developer
2815: .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2817: @*/
2818: PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level)
2819: {
2822: *level = dm->leveldown;
2823: return(0);
2824: }
2828: /*@C
2829: DMRefineHierarchy - Refines a DM object, all levels at once
2831: Collective on DM
2833: Input Parameter:
2834: + dm - the DM object
2835: - nlevels - the number of levels of refinement
2837: Output Parameter:
2838: . dmf - the refined DM hierarchy
2840: Level: developer
2842: .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2844: @*/
2845: PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[])
2846: {
2851: if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
2852: if (nlevels == 0) return(0);
2853: if (dm->ops->refinehierarchy) {
2854: (*dm->ops->refinehierarchy)(dm,nlevels,dmf);
2855: } else if (dm->ops->refine) {
2856: PetscInt i;
2858: DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);
2859: for (i=1; i<nlevels; i++) {
2860: DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);
2861: }
2862: } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet");
2863: return(0);
2864: }
2866: /*@C
2867: DMCoarsenHierarchy - Coarsens a DM object, all levels at once
2869: Collective on DM
2871: Input Parameter:
2872: + dm - the DM object
2873: - nlevels - the number of levels of coarsening
2875: Output Parameter:
2876: . dmc - the coarsened DM hierarchy
2878: Level: developer
2880: .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2882: @*/
2883: PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
2884: {
2889: if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
2890: if (nlevels == 0) return(0);
2892: if (dm->ops->coarsenhierarchy) {
2893: (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);
2894: } else if (dm->ops->coarsen) {
2895: PetscInt i;
2897: DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);
2898: for (i=1; i<nlevels; i++) {
2899: DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);
2900: }
2901: } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet");
2902: return(0);
2903: }
2905: /*@
2906: DMCreateAggregates - Gets the aggregates that map between
2907: grids associated with two DMs.
2909: Collective on DM
2911: Input Parameters:
2912: + dmc - the coarse grid DM
2913: - dmf - the fine grid DM
2915: Output Parameters:
2916: . rest - the restriction matrix (transpose of the projection matrix)
2918: Level: intermediate
2920: .keywords: interpolation, restriction, multigrid
2922: .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation()
2923: @*/
2924: PetscErrorCode DMCreateAggregates(DM dmc, DM dmf, Mat *rest)
2925: {
2931: (*dmc->ops->getaggregates)(dmc, dmf, rest);
2932: return(0);
2933: }
2935: /*@C
2936: DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed
2938: Not Collective
2940: Input Parameters:
2941: + dm - the DM object
2942: - destroy - the destroy function
2944: Level: intermediate
2946: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2948: @*/
2949: PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**))
2950: {
2953: dm->ctxdestroy = destroy;
2954: return(0);
2955: }
2957: /*@
2958: DMSetApplicationContext - Set a user context into a DM object
2960: Not Collective
2962: Input Parameters:
2963: + dm - the DM object
2964: - ctx - the user context
2966: Level: intermediate
2968: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2970: @*/
2971: PetscErrorCode DMSetApplicationContext(DM dm,void *ctx)
2972: {
2975: dm->ctx = ctx;
2976: return(0);
2977: }
2979: /*@
2980: DMGetApplicationContext - Gets a user context from a DM object
2982: Not Collective
2984: Input Parameter:
2985: . dm - the DM object
2987: Output Parameter:
2988: . ctx - the user context
2990: Level: intermediate
2992: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2994: @*/
2995: PetscErrorCode DMGetApplicationContext(DM dm,void *ctx)
2996: {
2999: *(void**)ctx = dm->ctx;
3000: return(0);
3001: }
3003: /*@C
3004: DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI.
3006: Logically Collective on DM
3008: Input Parameter:
3009: + dm - the DM object
3010: - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set)
3012: Level: intermediate
3014: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(),
3015: DMSetJacobian()
3017: @*/
3018: PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec))
3019: {
3021: dm->ops->computevariablebounds = f;
3022: return(0);
3023: }
3025: /*@
3026: DMHasVariableBounds - does the DM object have a variable bounds function?
3028: Not Collective
3030: Input Parameter:
3031: . dm - the DM object to destroy
3033: Output Parameter:
3034: . flg - PETSC_TRUE if the variable bounds function exists
3036: Level: developer
3038: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
3040: @*/
3041: PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg)
3042: {
3044: *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE;
3045: return(0);
3046: }
3048: /*@C
3049: DMComputeVariableBounds - compute variable bounds used by SNESVI.
3051: Logically Collective on DM
3053: Input Parameters:
3054: . dm - the DM object
3056: Output parameters:
3057: + xl - lower bound
3058: - xu - upper bound
3060: Level: advanced
3062: Notes:
3063: This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds()
3065: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
3067: @*/
3068: PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu)
3069: {
3075: if (dm->ops->computevariablebounds) {
3076: (*dm->ops->computevariablebounds)(dm, xl,xu);
3077: } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds.");
3078: return(0);
3079: }
3081: /*@
3082: DMHasColoring - does the DM object have a method of providing a coloring?
3084: Not Collective
3086: Input Parameter:
3087: . dm - the DM object
3089: Output Parameter:
3090: . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring().
3092: Level: developer
3094: .seealso DMHasFunction(), DMCreateColoring()
3096: @*/
3097: PetscErrorCode DMHasColoring(DM dm,PetscBool *flg)
3098: {
3100: *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE;
3101: return(0);
3102: }
3104: /*@
3105: DMHasCreateRestriction - does the DM object have a method of providing a restriction?
3107: Not Collective
3109: Input Parameter:
3110: . dm - the DM object
3112: Output Parameter:
3113: . flg - PETSC_TRUE if the DM has facilities for DMCreateRestriction().
3115: Level: developer
3117: .seealso DMHasFunction(), DMCreateRestriction()
3119: @*/
3120: PetscErrorCode DMHasCreateRestriction(DM dm,PetscBool *flg)
3121: {
3123: *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE;
3124: return(0);
3125: }
3128: /*@
3129: DMHasCreateInjection - does the DM object have a method of providing an injection?
3131: Not Collective
3133: Input Parameter:
3134: . dm - the DM object
3136: Output Parameter:
3137: . flg - PETSC_TRUE if the DM has facilities for DMCreateInjection().
3139: Level: developer
3141: .seealso DMHasFunction(), DMCreateInjection()
3143: @*/
3144: PetscErrorCode DMHasCreateInjection(DM dm,PetscBool *flg)
3145: {
3148: if (!dm->ops->hascreateinjection) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DMHasCreateInjection not implemented for this type");
3149: (*dm->ops->hascreateinjection)(dm,flg);
3150: return(0);
3151: }
3153: /*@C
3154: DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear.
3156: Collective on DM
3158: Input Parameter:
3159: + dm - the DM object
3160: - x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems.
3162: Level: developer
3164: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
3166: @*/
3167: PetscErrorCode DMSetVec(DM dm,Vec x)
3168: {
3172: if (x) {
3173: if (!dm->x) {
3174: DMCreateGlobalVector(dm,&dm->x);
3175: }
3176: VecCopy(x,dm->x);
3177: } else if (dm->x) {
3178: VecDestroy(&dm->x);
3179: }
3180: return(0);
3181: }
3183: PetscFunctionList DMList = NULL;
3184: PetscBool DMRegisterAllCalled = PETSC_FALSE;
3186: /*@C
3187: DMSetType - Builds a DM, for a particular DM implementation.
3189: Collective on DM
3191: Input Parameters:
3192: + dm - The DM object
3193: - method - The name of the DM type
3195: Options Database Key:
3196: . -dm_type <type> - Sets the DM type; use -help for a list of available types
3198: Notes:
3199: See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D).
3201: Level: intermediate
3203: .keywords: DM, set, type
3204: .seealso: DMGetType(), DMCreate()
3205: @*/
3206: PetscErrorCode DMSetType(DM dm, DMType method)
3207: {
3208: PetscErrorCode (*r)(DM);
3209: PetscBool match;
3214: PetscObjectTypeCompare((PetscObject) dm, method, &match);
3215: if (match) return(0);
3217: DMRegisterAll();
3218: PetscFunctionListFind(DMList,method,&r);
3219: if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);
3221: if (dm->ops->destroy) {
3222: (*dm->ops->destroy)(dm);
3223: dm->ops->destroy = NULL;
3224: }
3225: (*r)(dm);
3226: PetscObjectChangeTypeName((PetscObject)dm,method);
3227: return(0);
3228: }
3230: /*@C
3231: DMGetType - Gets the DM type name (as a string) from the DM.
3233: Not Collective
3235: Input Parameter:
3236: . dm - The DM
3238: Output Parameter:
3239: . type - The DM type name
3241: Level: intermediate
3243: .keywords: DM, get, type, name
3244: .seealso: DMSetType(), DMCreate()
3245: @*/
3246: PetscErrorCode DMGetType(DM dm, DMType *type)
3247: {
3253: DMRegisterAll();
3254: *type = ((PetscObject)dm)->type_name;
3255: return(0);
3256: }
3258: /*@C
3259: DMConvert - Converts a DM to another DM, either of the same or different type.
3261: Collective on DM
3263: Input Parameters:
3264: + dm - the DM
3265: - newtype - new DM type (use "same" for the same type)
3267: Output Parameter:
3268: . M - pointer to new DM
3270: Notes:
3271: Cannot be used to convert a sequential DM to parallel or parallel to sequential,
3272: the MPI communicator of the generated DM is always the same as the communicator
3273: of the input DM.
3275: Level: intermediate
3277: .seealso: DMCreate()
3278: @*/
3279: PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M)
3280: {
3281: DM B;
3282: char convname[256];
3283: PetscBool sametype/*, issame */;
3290: PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);
3291: /* PetscStrcmp(newtype, "same", &issame); */
3292: if (sametype) {
3293: *M = dm;
3294: PetscObjectReference((PetscObject) dm);
3295: return(0);
3296: } else {
3297: PetscErrorCode (*conv)(DM, DMType, DM*) = NULL;
3299: /*
3300: Order of precedence:
3301: 1) See if a specialized converter is known to the current DM.
3302: 2) See if a specialized converter is known to the desired DM class.
3303: 3) See if a good general converter is registered for the desired class
3304: 4) See if a good general converter is known for the current matrix.
3305: 5) Use a really basic converter.
3306: */
3308: /* 1) See if a specialized converter is known to the current DM and the desired class */
3309: PetscStrncpy(convname,"DMConvert_",sizeof(convname));
3310: PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));
3311: PetscStrlcat(convname,"_",sizeof(convname));
3312: PetscStrlcat(convname,newtype,sizeof(convname));
3313: PetscStrlcat(convname,"_C",sizeof(convname));
3314: PetscObjectQueryFunction((PetscObject)dm,convname,&conv);
3315: if (conv) goto foundconv;
3317: /* 2) See if a specialized converter is known to the desired DM class. */
3318: DMCreate(PetscObjectComm((PetscObject)dm), &B);
3319: DMSetType(B, newtype);
3320: PetscStrncpy(convname,"DMConvert_",sizeof(convname));
3321: PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));
3322: PetscStrlcat(convname,"_",sizeof(convname));
3323: PetscStrlcat(convname,newtype,sizeof(convname));
3324: PetscStrlcat(convname,"_C",sizeof(convname));
3325: PetscObjectQueryFunction((PetscObject)B,convname,&conv);
3326: if (conv) {
3327: DMDestroy(&B);
3328: goto foundconv;
3329: }
3331: #if 0
3332: /* 3) See if a good general converter is registered for the desired class */
3333: conv = B->ops->convertfrom;
3334: DMDestroy(&B);
3335: if (conv) goto foundconv;
3337: /* 4) See if a good general converter is known for the current matrix */
3338: if (dm->ops->convert) {
3339: conv = dm->ops->convert;
3340: }
3341: if (conv) goto foundconv;
3342: #endif
3344: /* 5) Use a really basic converter. */
3345: SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype);
3347: foundconv:
3348: PetscLogEventBegin(DM_Convert,dm,0,0,0);
3349: (*conv)(dm,newtype,M);
3350: /* Things that are independent of DM type: We should consult DMClone() here */
3351: {
3352: PetscBool isper;
3353: const PetscReal *maxCell, *L;
3354: const DMBoundaryType *bd;
3355: DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);
3356: DMSetPeriodicity(*M, isper, maxCell, L, bd);
3357: }
3358: PetscLogEventEnd(DM_Convert,dm,0,0,0);
3359: }
3360: PetscObjectStateIncrease((PetscObject) *M);
3361: return(0);
3362: }
3364: /*--------------------------------------------------------------------------------------------------------------------*/
3366: /*@C
3367: DMRegister - Adds a new DM component implementation
3369: Not Collective
3371: Input Parameters:
3372: + name - The name of a new user-defined creation routine
3373: - create_func - The creation routine itself
3375: Notes:
3376: DMRegister() may be called multiple times to add several user-defined DMs
3379: Sample usage:
3380: .vb
3381: DMRegister("my_da", MyDMCreate);
3382: .ve
3384: Then, your DM type can be chosen with the procedural interface via
3385: .vb
3386: DMCreate(MPI_Comm, DM *);
3387: DMSetType(DM,"my_da");
3388: .ve
3389: or at runtime via the option
3390: .vb
3391: -da_type my_da
3392: .ve
3394: Level: advanced
3396: .keywords: DM, register
3397: .seealso: DMRegisterAll(), DMRegisterDestroy()
3399: @*/
3400: PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM))
3401: {
3405: PetscFunctionListAdd(&DMList,sname,function);
3406: return(0);
3407: }
3409: /*@C
3410: DMLoad - Loads a DM that has been stored in binary with DMView().
3412: Collective on PetscViewer
3414: Input Parameters:
3415: + newdm - the newly loaded DM, this needs to have been created with DMCreate() or
3416: some related function before a call to DMLoad().
3417: - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or
3418: HDF5 file viewer, obtained from PetscViewerHDF5Open()
3420: Level: intermediate
3422: Notes:
3423: The type is determined by the data in the file, any type set into the DM before this call is ignored.
3425: Notes for advanced users:
3426: Most users should not need to know the details of the binary storage
3427: format, since DMLoad() and DMView() completely hide these details.
3428: But for anyone who's interested, the standard binary matrix storage
3429: format is
3430: .vb
3431: has not yet been determined
3432: .ve
3434: .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad()
3435: @*/
3436: PetscErrorCode DMLoad(DM newdm, PetscViewer viewer)
3437: {
3438: PetscBool isbinary, ishdf5;
3444: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
3445: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);
3446: if (isbinary) {
3447: PetscInt classid;
3448: char type[256];
3450: PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);
3451: if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid);
3452: PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);
3453: DMSetType(newdm, type);
3454: if (newdm->ops->load) {(*newdm->ops->load)(newdm,viewer);}
3455: } else if (ishdf5) {
3456: if (newdm->ops->load) {(*newdm->ops->load)(newdm,viewer);}
3457: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()");
3458: return(0);
3459: }
3461: /******************************** FEM Support **********************************/
3463: PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[])
3464: {
3465: PetscInt f;
3469: PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);
3470: for (f = 0; f < len; ++f) {
3471: PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));
3472: }
3473: return(0);
3474: }
3476: PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[])
3477: {
3478: PetscInt f, g;
3482: PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);
3483: for (f = 0; f < rows; ++f) {
3484: PetscPrintf(PETSC_COMM_SELF, " |");
3485: for (g = 0; g < cols; ++g) {
3486: PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));
3487: }
3488: PetscPrintf(PETSC_COMM_SELF, " |\n");
3489: }
3490: return(0);
3491: }
3493: PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X)
3494: {
3495: PetscInt localSize, bs;
3496: PetscMPIInt size;
3497: Vec x, xglob;
3498: const PetscScalar *xarray;
3499: PetscErrorCode ierr;
3502: MPI_Comm_size(PetscObjectComm((PetscObject) dm),&size);
3503: VecDuplicate(X, &x);
3504: VecCopy(X, x);
3505: VecChop(x, tol);
3506: PetscPrintf(PetscObjectComm((PetscObject) dm),"%s:\n",name);
3507: if (size > 1) {
3508: VecGetLocalSize(x,&localSize);
3509: VecGetArrayRead(x,&xarray);
3510: VecGetBlockSize(x,&bs);
3511: VecCreateMPIWithArray(PetscObjectComm((PetscObject) dm),bs,localSize,PETSC_DETERMINE,xarray,&xglob);
3512: } else {
3513: xglob = x;
3514: }
3515: VecView(xglob,PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject) dm)));
3516: if (size > 1) {
3517: VecDestroy(&xglob);
3518: VecRestoreArrayRead(x,&xarray);
3519: }
3520: VecDestroy(&x);
3521: return(0);
3522: }
3524: /*@
3525: DMGetSection - Get the PetscSection encoding the local data layout for the DM.
3527: Input Parameter:
3528: . dm - The DM
3530: Output Parameter:
3531: . section - The PetscSection
3533: Options Database Keys:
3534: . -dm_petscsection_view - View the Section created by the DM
3536: Level: intermediate
3538: Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
3540: .seealso: DMSetSection(), DMGetGlobalSection()
3541: @*/
3542: PetscErrorCode DMGetSection(DM dm, PetscSection *section)
3543: {
3549: if (!dm->defaultSection && dm->ops->createdefaultsection) {
3550: (*dm->ops->createdefaultsection)(dm);
3551: if (dm->defaultSection) {PetscObjectViewFromOptions((PetscObject) dm->defaultSection, NULL, "-dm_petscsection_view");}
3552: }
3553: *section = dm->defaultSection;
3554: return(0);
3555: }
3557: /*@
3558: DMSetSection - Set the PetscSection encoding the local data layout for the DM.
3560: Input Parameters:
3561: + dm - The DM
3562: - section - The PetscSection
3564: Level: intermediate
3566: Note: Any existing Section will be destroyed
3568: .seealso: DMSetSection(), DMGetGlobalSection()
3569: @*/
3570: PetscErrorCode DMSetSection(DM dm, PetscSection section)
3571: {
3572: PetscInt numFields = 0;
3573: PetscInt f;
3578: if (section) {
3580: PetscObjectReference((PetscObject)section);
3581: }
3582: PetscSectionDestroy(&dm->defaultSection);
3583: dm->defaultSection = section;
3584: if (section) {PetscSectionGetNumFields(dm->defaultSection, &numFields);}
3585: if (numFields) {
3586: DMSetNumFields(dm, numFields);
3587: for (f = 0; f < numFields; ++f) {
3588: PetscObject disc;
3589: const char *name;
3591: PetscSectionGetFieldName(dm->defaultSection, f, &name);
3592: DMGetField(dm, f, &disc);
3593: PetscObjectSetName(disc, name);
3594: }
3595: }
3596: /* The global section will be rebuilt in the next call to DMGetGlobalSection(). */
3597: PetscSectionDestroy(&dm->defaultGlobalSection);
3598: return(0);
3599: }
3601: /*@
3602: DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation.
3604: not collective
3606: Input Parameter:
3607: . dm - The DM
3609: Output Parameter:
3610: + 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.
3611: - 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.
3613: Level: advanced
3615: Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat.
3617: .seealso: DMSetDefaultConstraints()
3618: @*/
3619: PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat)
3620: {
3625: if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {(*dm->ops->createdefaultconstraints)(dm);}
3626: if (section) {*section = dm->defaultConstraintSection;}
3627: if (mat) {*mat = dm->defaultConstraintMat;}
3628: return(0);
3629: }
3631: /*@
3632: DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation.
3634: 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().
3636: 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.
3638: collective on dm
3640: Input Parameters:
3641: + dm - The DM
3642: + 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).
3643: - 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).
3645: Level: advanced
3647: Note: This increments the references of the PetscSection and the Mat, so they user can destroy them
3649: .seealso: DMGetDefaultConstraints()
3650: @*/
3651: PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat)
3652: {
3653: PetscMPIInt result;
3658: if (section) {
3660: MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);
3661: if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator");
3662: }
3663: if (mat) {
3665: MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);
3666: if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator");
3667: }
3668: PetscObjectReference((PetscObject)section);
3669: PetscSectionDestroy(&dm->defaultConstraintSection);
3670: dm->defaultConstraintSection = section;
3671: PetscObjectReference((PetscObject)mat);
3672: MatDestroy(&dm->defaultConstraintMat);
3673: dm->defaultConstraintMat = mat;
3674: return(0);
3675: }
3677: #if defined(PETSC_USE_DEBUG)
3678: /*
3679: DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections.
3681: Input Parameters:
3682: + dm - The DM
3683: . localSection - PetscSection describing the local data layout
3684: - globalSection - PetscSection describing the global data layout
3686: Level: intermediate
3688: .seealso: DMGetDefaultSF(), DMSetDefaultSF()
3689: */
3690: static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection)
3691: {
3692: MPI_Comm comm;
3693: PetscLayout layout;
3694: const PetscInt *ranges;
3695: PetscInt pStart, pEnd, p, nroots;
3696: PetscMPIInt size, rank;
3697: PetscBool valid = PETSC_TRUE, gvalid;
3698: PetscErrorCode ierr;
3701: PetscObjectGetComm((PetscObject)dm,&comm);
3703: MPI_Comm_size(comm, &size);
3704: MPI_Comm_rank(comm, &rank);
3705: PetscSectionGetChart(globalSection, &pStart, &pEnd);
3706: PetscSectionGetConstrainedStorageSize(globalSection, &nroots);
3707: PetscLayoutCreate(comm, &layout);
3708: PetscLayoutSetBlockSize(layout, 1);
3709: PetscLayoutSetLocalSize(layout, nroots);
3710: PetscLayoutSetUp(layout);
3711: PetscLayoutGetRanges(layout, &ranges);
3712: for (p = pStart; p < pEnd; ++p) {
3713: PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d;
3715: PetscSectionGetDof(localSection, p, &dof);
3716: PetscSectionGetOffset(localSection, p, &off);
3717: PetscSectionGetConstraintDof(localSection, p, &cdof);
3718: PetscSectionGetDof(globalSection, p, &gdof);
3719: PetscSectionGetConstraintDof(globalSection, p, &gcdof);
3720: PetscSectionGetOffset(globalSection, p, &goff);
3721: if (!gdof) continue; /* Censored point */
3722: 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;}
3723: 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;}
3724: if (gdof < 0) {
3725: gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3726: for (d = 0; d < gsize; ++d) {
3727: PetscInt offset = -(goff+1) + d, r;
3729: PetscFindInt(offset,size+1,ranges,&r);
3730: if (r < 0) r = -(r+2);
3731: 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;}
3732: }
3733: }
3734: }
3735: PetscLayoutDestroy(&layout);
3736: PetscSynchronizedFlush(comm, NULL);
3737: MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);
3738: if (!gvalid) {
3739: DMView(dm, NULL);
3740: SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections");
3741: }
3742: return(0);
3743: }
3744: #endif
3746: /*@
3747: DMGetGlobalSection - Get the PetscSection encoding the global data layout for the DM.
3749: Collective on DM
3751: Input Parameter:
3752: . dm - The DM
3754: Output Parameter:
3755: . section - The PetscSection
3757: Level: intermediate
3759: Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
3761: .seealso: DMSetSection(), DMGetSection()
3762: @*/
3763: PetscErrorCode DMGetGlobalSection(DM dm, PetscSection *section)
3764: {
3770: if (!dm->defaultGlobalSection) {
3771: PetscSection s;
3773: DMGetSection(dm, &s);
3774: if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection");
3775: if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection");
3776: PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->defaultGlobalSection);
3777: PetscLayoutDestroy(&dm->map);
3778: PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);
3779: PetscSectionViewFromOptions(dm->defaultGlobalSection, NULL, "-global_section_view");
3780: }
3781: *section = dm->defaultGlobalSection;
3782: return(0);
3783: }
3785: /*@
3786: DMSetGlobalSection - Set the PetscSection encoding the global data layout for the DM.
3788: Input Parameters:
3789: + dm - The DM
3790: - section - The PetscSection, or NULL
3792: Level: intermediate
3794: Note: Any existing Section will be destroyed
3796: .seealso: DMGetGlobalSection(), DMSetSection()
3797: @*/
3798: PetscErrorCode DMSetGlobalSection(DM dm, PetscSection section)
3799: {
3805: PetscObjectReference((PetscObject)section);
3806: PetscSectionDestroy(&dm->defaultGlobalSection);
3807: dm->defaultGlobalSection = section;
3808: #if defined(PETSC_USE_DEBUG)
3809: if (section) {DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);}
3810: #endif
3811: return(0);
3812: }
3814: /*@
3815: DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set,
3816: it is created from the default PetscSection layouts in the DM.
3818: Input Parameter:
3819: . dm - The DM
3821: Output Parameter:
3822: . sf - The PetscSF
3824: Level: intermediate
3826: Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
3828: .seealso: DMSetDefaultSF(), DMCreateDefaultSF()
3829: @*/
3830: PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf)
3831: {
3832: PetscInt nroots;
3838: PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);
3839: if (nroots < 0) {
3840: PetscSection section, gSection;
3842: DMGetSection(dm, §ion);
3843: if (section) {
3844: DMGetGlobalSection(dm, &gSection);
3845: DMCreateDefaultSF(dm, section, gSection);
3846: } else {
3847: *sf = NULL;
3848: return(0);
3849: }
3850: }
3851: *sf = dm->defaultSF;
3852: return(0);
3853: }
3855: /*@
3856: DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM
3858: Input Parameters:
3859: + dm - The DM
3860: - sf - The PetscSF
3862: Level: intermediate
3864: Note: Any previous SF is destroyed
3866: .seealso: DMGetDefaultSF(), DMCreateDefaultSF()
3867: @*/
3868: PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf)
3869: {
3875: PetscSFDestroy(&dm->defaultSF);
3876: dm->defaultSF = sf;
3877: return(0);
3878: }
3880: /*@C
3881: DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections
3882: describing the data layout.
3884: Input Parameters:
3885: + dm - The DM
3886: . localSection - PetscSection describing the local data layout
3887: - globalSection - PetscSection describing the global data layout
3889: Level: intermediate
3891: .seealso: DMGetDefaultSF(), DMSetDefaultSF()
3892: @*/
3893: PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection)
3894: {
3895: MPI_Comm comm;
3896: PetscLayout layout;
3897: const PetscInt *ranges;
3898: PetscInt *local;
3899: PetscSFNode *remote;
3900: PetscInt pStart, pEnd, p, nroots, nleaves = 0, l;
3901: PetscMPIInt size, rank;
3905: PetscObjectGetComm((PetscObject)dm,&comm);
3907: MPI_Comm_size(comm, &size);
3908: MPI_Comm_rank(comm, &rank);
3909: PetscSectionGetChart(globalSection, &pStart, &pEnd);
3910: PetscSectionGetConstrainedStorageSize(globalSection, &nroots);
3911: PetscLayoutCreate(comm, &layout);
3912: PetscLayoutSetBlockSize(layout, 1);
3913: PetscLayoutSetLocalSize(layout, nroots);
3914: PetscLayoutSetUp(layout);
3915: PetscLayoutGetRanges(layout, &ranges);
3916: for (p = pStart; p < pEnd; ++p) {
3917: PetscInt gdof, gcdof;
3919: PetscSectionGetDof(globalSection, p, &gdof);
3920: PetscSectionGetConstraintDof(globalSection, p, &gcdof);
3921: 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));
3922: nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3923: }
3924: PetscMalloc1(nleaves, &local);
3925: PetscMalloc1(nleaves, &remote);
3926: for (p = pStart, l = 0; p < pEnd; ++p) {
3927: const PetscInt *cind;
3928: PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c;
3930: PetscSectionGetDof(localSection, p, &dof);
3931: PetscSectionGetOffset(localSection, p, &off);
3932: PetscSectionGetConstraintDof(localSection, p, &cdof);
3933: PetscSectionGetConstraintIndices(localSection, p, &cind);
3934: PetscSectionGetDof(globalSection, p, &gdof);
3935: PetscSectionGetConstraintDof(globalSection, p, &gcdof);
3936: PetscSectionGetOffset(globalSection, p, &goff);
3937: if (!gdof) continue; /* Censored point */
3938: gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3939: if (gsize != dof-cdof) {
3940: 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);
3941: cdof = 0; /* Ignore constraints */
3942: }
3943: for (d = 0, c = 0; d < dof; ++d) {
3944: if ((c < cdof) && (cind[c] == d)) {++c; continue;}
3945: local[l+d-c] = off+d;
3946: }
3947: if (gdof < 0) {
3948: for (d = 0; d < gsize; ++d, ++l) {
3949: PetscInt offset = -(goff+1) + d, r;
3951: PetscFindInt(offset,size+1,ranges,&r);
3952: if (r < 0) r = -(r+2);
3953: 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);
3954: remote[l].rank = r;
3955: remote[l].index = offset - ranges[r];
3956: }
3957: } else {
3958: for (d = 0; d < gsize; ++d, ++l) {
3959: remote[l].rank = rank;
3960: remote[l].index = goff+d - ranges[rank];
3961: }
3962: }
3963: }
3964: if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves);
3965: PetscLayoutDestroy(&layout);
3966: PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);
3967: return(0);
3968: }
3970: /*@
3971: DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM.
3973: Input Parameter:
3974: . dm - The DM
3976: Output Parameter:
3977: . sf - The PetscSF
3979: Level: intermediate
3981: Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
3983: .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
3984: @*/
3985: PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf)
3986: {
3990: *sf = dm->sf;
3991: return(0);
3992: }
3994: /*@
3995: DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM.
3997: Input Parameters:
3998: + dm - The DM
3999: - sf - The PetscSF
4001: Level: intermediate
4003: .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
4004: @*/
4005: PetscErrorCode DMSetPointSF(DM dm, PetscSF sf)
4006: {
4012: PetscSFDestroy(&dm->sf);
4013: PetscObjectReference((PetscObject) sf);
4014: dm->sf = sf;
4015: return(0);
4016: }
4018: /*@
4019: DMGetDS - Get the PetscDS
4021: Input Parameter:
4022: . dm - The DM
4024: Output Parameter:
4025: . prob - The PetscDS
4027: Level: developer
4029: .seealso: DMSetDS()
4030: @*/
4031: PetscErrorCode DMGetDS(DM dm, PetscDS *prob)
4032: {
4036: *prob = dm->prob;
4037: return(0);
4038: }
4040: /*@
4041: DMSetDS - Set the PetscDS
4043: Input Parameters:
4044: + dm - The DM
4045: - prob - The PetscDS
4047: Level: developer
4049: .seealso: DMGetDS()
4050: @*/
4051: PetscErrorCode DMSetDS(DM dm, PetscDS prob)
4052: {
4053: PetscInt dimEmbed;
4059: PetscObjectReference((PetscObject) prob);
4060: PetscDSDestroy(&dm->prob);
4061: dm->prob = prob;
4062: DMGetCoordinateDim(dm, &dimEmbed);
4063: PetscDSSetCoordinateDimension(prob, dimEmbed);
4064: return(0);
4065: }
4067: PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields)
4068: {
4073: PetscDSGetNumFields(dm->prob, numFields);
4074: return(0);
4075: }
4077: PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields)
4078: {
4079: PetscInt Nf, f;
4084: PetscDSGetNumFields(dm->prob, &Nf);
4085: for (f = Nf; f < numFields; ++f) {
4086: PetscContainer obj;
4088: PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);
4089: PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);
4090: PetscContainerDestroy(&obj);
4091: }
4092: return(0);
4093: }
4095: /*@
4096: DMGetField - Return the discretization object for a given DM field
4098: Not collective
4100: Input Parameters:
4101: + dm - The DM
4102: - f - The field number
4104: Output Parameter:
4105: . field - The discretization object
4107: Level: developer
4109: .seealso: DMSetField()
4110: @*/
4111: PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field)
4112: {
4117: PetscDSGetDiscretization(dm->prob, f, field);
4118: return(0);
4119: }
4121: /*@
4122: DMSetField - Set the discretization object for a given DM field
4124: Logically collective on DM
4126: Input Parameters:
4127: + dm - The DM
4128: . f - The field number
4129: - field - The discretization object
4131: Level: developer
4133: .seealso: DMGetField()
4134: @*/
4135: PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field)
4136: {
4141: PetscDSSetDiscretization(dm->prob, f, field);
4142: return(0);
4143: }
4145: PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx)
4146: {
4147: DM dm_coord,dmc_coord;
4149: Vec coords,ccoords;
4150: Mat inject;
4152: DMGetCoordinateDM(dm,&dm_coord);
4153: DMGetCoordinateDM(dmc,&dmc_coord);
4154: DMGetCoordinates(dm,&coords);
4155: DMGetCoordinates(dmc,&ccoords);
4156: if (coords && !ccoords) {
4157: DMCreateGlobalVector(dmc_coord,&ccoords);
4158: PetscObjectSetName((PetscObject)ccoords,"coordinates");
4159: DMCreateInjection(dmc_coord,dm_coord,&inject);
4160: MatRestrict(inject,coords,ccoords);
4161: MatDestroy(&inject);
4162: DMSetCoordinates(dmc,ccoords);
4163: VecDestroy(&ccoords);
4164: }
4165: return(0);
4166: }
4168: static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx)
4169: {
4170: DM dm_coord,subdm_coord;
4172: Vec coords,ccoords,clcoords;
4173: VecScatter *scat_i,*scat_g;
4175: DMGetCoordinateDM(dm,&dm_coord);
4176: DMGetCoordinateDM(subdm,&subdm_coord);
4177: DMGetCoordinates(dm,&coords);
4178: DMGetCoordinates(subdm,&ccoords);
4179: if (coords && !ccoords) {
4180: DMCreateGlobalVector(subdm_coord,&ccoords);
4181: PetscObjectSetName((PetscObject)ccoords,"coordinates");
4182: DMCreateLocalVector(subdm_coord,&clcoords);
4183: PetscObjectSetName((PetscObject)clcoords,"coordinates");
4184: DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);
4185: VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);
4186: VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);
4187: VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);
4188: VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);
4189: DMSetCoordinates(subdm,ccoords);
4190: DMSetCoordinatesLocal(subdm,clcoords);
4191: VecScatterDestroy(&scat_i[0]);
4192: VecScatterDestroy(&scat_g[0]);
4193: VecDestroy(&ccoords);
4194: VecDestroy(&clcoords);
4195: PetscFree(scat_i);
4196: PetscFree(scat_g);
4197: }
4198: return(0);
4199: }
4201: /*@
4202: DMGetDimension - Return the topological dimension of the DM
4204: Not collective
4206: Input Parameter:
4207: . dm - The DM
4209: Output Parameter:
4210: . dim - The topological dimension
4212: Level: beginner
4214: .seealso: DMSetDimension(), DMCreate()
4215: @*/
4216: PetscErrorCode DMGetDimension(DM dm, PetscInt *dim)
4217: {
4221: *dim = dm->dim;
4222: return(0);
4223: }
4225: /*@
4226: DMSetDimension - Set the topological dimension of the DM
4228: Collective on dm
4230: Input Parameters:
4231: + dm - The DM
4232: - dim - The topological dimension
4234: Level: beginner
4236: .seealso: DMGetDimension(), DMCreate()
4237: @*/
4238: PetscErrorCode DMSetDimension(DM dm, PetscInt dim)
4239: {
4245: dm->dim = dim;
4246: if (dm->prob->dimEmbed < 0) {PetscDSSetCoordinateDimension(dm->prob, dm->dim);}
4247: return(0);
4248: }
4250: /*@
4251: DMGetDimPoints - Get the half-open interval for all points of a given dimension
4253: Collective on DM
4255: Input Parameters:
4256: + dm - the DM
4257: - dim - the dimension
4259: Output Parameters:
4260: + pStart - The first point of the given dimension
4261: . pEnd - The first point following points of the given dimension
4263: Note:
4264: The points are vertices in the Hasse diagram encoding the topology. This is explained in
4265: http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme,
4266: then the interval is empty.
4268: Level: intermediate
4270: .keywords: point, Hasse Diagram, dimension
4271: .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum()
4272: @*/
4273: PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
4274: {
4275: PetscInt d;
4280: DMGetDimension(dm, &d);
4281: if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d);
4282: (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);
4283: return(0);
4284: }
4286: /*@
4287: DMSetCoordinates - Sets into the DM a global vector that holds the coordinates
4289: Collective on DM
4291: Input Parameters:
4292: + dm - the DM
4293: - c - coordinate vector
4295: Notes:
4296: The coordinates do include those for ghost points, which are in the local vector.
4298: The vector c should be destroyed by the caller.
4300: Level: intermediate
4302: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4303: .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM()
4304: @*/
4305: PetscErrorCode DMSetCoordinates(DM dm, Vec c)
4306: {
4312: PetscObjectReference((PetscObject) c);
4313: VecDestroy(&dm->coordinates);
4314: dm->coordinates = c;
4315: VecDestroy(&dm->coordinatesLocal);
4316: DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);
4317: DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);
4318: return(0);
4319: }
4321: /*@
4322: DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates
4324: Collective on DM
4326: Input Parameters:
4327: + dm - the DM
4328: - c - coordinate vector
4330: Notes:
4331: The coordinates of ghost points can be set using DMSetCoordinates()
4332: followed by DMGetCoordinatesLocal(). This is intended to enable the
4333: setting of ghost coordinates outside of the domain.
4335: The vector c should be destroyed by the caller.
4337: Level: intermediate
4339: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4340: .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM()
4341: @*/
4342: PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c)
4343: {
4349: PetscObjectReference((PetscObject) c);
4350: VecDestroy(&dm->coordinatesLocal);
4352: dm->coordinatesLocal = c;
4354: VecDestroy(&dm->coordinates);
4355: return(0);
4356: }
4358: /*@
4359: DMGetCoordinates - Gets a global vector with the coordinates associated with the DM.
4361: Not Collective
4363: Input Parameter:
4364: . dm - the DM
4366: Output Parameter:
4367: . c - global coordinate vector
4369: Note:
4370: This is a borrowed reference, so the user should NOT destroy this vector
4372: Each process has only the local coordinates (does NOT have the ghost coordinates).
4374: For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
4375: and (x_0,y_0,z_0,x_1,y_1,z_1...)
4377: Level: intermediate
4379: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4380: .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM()
4381: @*/
4382: PetscErrorCode DMGetCoordinates(DM dm, Vec *c)
4383: {
4389: if (!dm->coordinates && dm->coordinatesLocal) {
4390: DM cdm = NULL;
4392: DMGetCoordinateDM(dm, &cdm);
4393: DMCreateGlobalVector(cdm, &dm->coordinates);
4394: PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");
4395: DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);
4396: DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);
4397: }
4398: *c = dm->coordinates;
4399: return(0);
4400: }
4402: /*@
4403: DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM.
4405: Collective on DM
4407: Input Parameter:
4408: . dm - the DM
4410: Output Parameter:
4411: . c - coordinate vector
4413: Note:
4414: This is a borrowed reference, so the user should NOT destroy this vector
4416: Each process has the local and ghost coordinates
4418: For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
4419: and (x_0,y_0,z_0,x_1,y_1,z_1...)
4421: Level: intermediate
4423: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4424: .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM()
4425: @*/
4426: PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c)
4427: {
4433: if (!dm->coordinatesLocal && dm->coordinates) {
4434: DM cdm = NULL;
4436: DMGetCoordinateDM(dm, &cdm);
4437: DMCreateLocalVector(cdm, &dm->coordinatesLocal);
4438: PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");
4439: DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);
4440: DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);
4441: }
4442: *c = dm->coordinatesLocal;
4443: return(0);
4444: }
4446: PetscErrorCode DMGetCoordinateField(DM dm, DMField *field)
4447: {
4453: if (!dm->coordinateField) {
4454: if (dm->ops->createcoordinatefield) {
4455: (*dm->ops->createcoordinatefield)(dm,&dm->coordinateField);
4456: }
4457: }
4458: *field = dm->coordinateField;
4459: return(0);
4460: }
4462: PetscErrorCode DMSetCoordinateField(DM dm, DMField field)
4463: {
4469: PetscObjectReference((PetscObject)field);
4470: DMFieldDestroy(&dm->coordinateField);
4471: dm->coordinateField = field;
4472: return(0);
4473: }
4475: /*@
4476: DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates
4478: Collective on DM
4480: Input Parameter:
4481: . dm - the DM
4483: Output Parameter:
4484: . cdm - coordinate DM
4486: Level: intermediate
4488: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4489: .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
4490: @*/
4491: PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm)
4492: {
4498: if (!dm->coordinateDM) {
4499: if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM");
4500: (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);
4501: }
4502: *cdm = dm->coordinateDM;
4503: return(0);
4504: }
4506: /*@
4507: DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates
4509: Logically Collective on DM
4511: Input Parameters:
4512: + dm - the DM
4513: - cdm - coordinate DM
4515: Level: intermediate
4517: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4518: .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
4519: @*/
4520: PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm)
4521: {
4527: PetscObjectReference((PetscObject)cdm);
4528: DMDestroy(&dm->coordinateDM);
4529: dm->coordinateDM = cdm;
4530: return(0);
4531: }
4533: /*@
4534: DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values.
4536: Not Collective
4538: Input Parameter:
4539: . dm - The DM object
4541: Output Parameter:
4542: . dim - The embedding dimension
4544: Level: intermediate
4546: .keywords: mesh, coordinates
4547: .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetSection(), DMSetSection()
4548: @*/
4549: PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim)
4550: {
4554: if (dm->dimEmbed == PETSC_DEFAULT) {
4555: dm->dimEmbed = dm->dim;
4556: }
4557: *dim = dm->dimEmbed;
4558: return(0);
4559: }
4561: /*@
4562: DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values.
4564: Not Collective
4566: Input Parameters:
4567: + dm - The DM object
4568: - dim - The embedding dimension
4570: Level: intermediate
4572: .keywords: mesh, coordinates
4573: .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetSection(), DMSetSection()
4574: @*/
4575: PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim)
4576: {
4581: dm->dimEmbed = dim;
4582: PetscDSSetCoordinateDimension(dm->prob, dm->dimEmbed);
4583: return(0);
4584: }
4586: /*@
4587: DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh.
4589: Not Collective
4591: Input Parameter:
4592: . dm - The DM object
4594: Output Parameter:
4595: . section - The PetscSection object
4597: Level: intermediate
4599: .keywords: mesh, coordinates
4600: .seealso: DMGetCoordinateDM(), DMGetSection(), DMSetSection()
4601: @*/
4602: PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section)
4603: {
4604: DM cdm;
4610: DMGetCoordinateDM(dm, &cdm);
4611: DMGetSection(cdm, section);
4612: return(0);
4613: }
4615: /*@
4616: DMSetCoordinateSection - Set the layout of coordinate values over the mesh.
4618: Not Collective
4620: Input Parameters:
4621: + dm - The DM object
4622: . dim - The embedding dimension, or PETSC_DETERMINE
4623: - section - The PetscSection object
4625: Level: intermediate
4627: .keywords: mesh, coordinates
4628: .seealso: DMGetCoordinateSection(), DMGetSection(), DMSetSection()
4629: @*/
4630: PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section)
4631: {
4632: DM cdm;
4638: DMGetCoordinateDM(dm, &cdm);
4639: DMSetSection(cdm, section);
4640: if (dim == PETSC_DETERMINE) {
4641: PetscInt d = PETSC_DEFAULT;
4642: PetscInt pStart, pEnd, vStart, vEnd, v, dd;
4644: PetscSectionGetChart(section, &pStart, &pEnd);
4645: DMGetDimPoints(dm, 0, &vStart, &vEnd);
4646: pStart = PetscMax(vStart, pStart);
4647: pEnd = PetscMin(vEnd, pEnd);
4648: for (v = pStart; v < pEnd; ++v) {
4649: PetscSectionGetDof(section, v, &dd);
4650: if (dd) {d = dd; break;}
4651: }
4652: if (d < 0) d = PETSC_DEFAULT;
4653: DMSetCoordinateDim(dm, d);
4654: }
4655: return(0);
4656: }
4658: /*@C
4659: DMGetPeriodicity - Get the description of mesh periodicity
4661: Input Parameters:
4662: . dm - The DM object
4664: Output Parameters:
4665: + per - Whether the DM is periodic or not
4666: . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates
4667: . L - If we assume the mesh is a torus, this is the length of each coordinate
4668: - bd - This describes the type of periodicity in each topological dimension
4670: Level: developer
4672: .seealso: DMGetPeriodicity()
4673: @*/
4674: PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd)
4675: {
4678: if (per) *per = dm->periodic;
4679: if (L) *L = dm->L;
4680: if (maxCell) *maxCell = dm->maxCell;
4681: if (bd) *bd = dm->bdtype;
4682: return(0);
4683: }
4685: /*@C
4686: DMSetPeriodicity - Set the description of mesh periodicity
4688: Input Parameters:
4689: + dm - The DM object
4690: . per - Whether the DM is periodic or not. If maxCell is not provided, coordinates need to be localized
4691: . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates
4692: . L - If we assume the mesh is a torus, this is the length of each coordinate
4693: - bd - This describes the type of periodicity in each topological dimension
4695: Level: developer
4697: .seealso: DMGetPeriodicity()
4698: @*/
4699: PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[])
4700: {
4701: PetscInt dim, d;
4707: if (maxCell) {
4711: }
4712: PetscFree3(dm->L,dm->maxCell,dm->bdtype);
4713: DMGetDimension(dm, &dim);
4714: if (maxCell) {
4715: PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);
4716: for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];}
4717: dm->periodic = PETSC_TRUE;
4718: } else {
4719: dm->periodic = per;
4720: }
4721: return(0);
4722: }
4724: /*@
4725: 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.
4727: Input Parameters:
4728: + dm - The DM
4729: . in - The input coordinate point (dim numbers)
4730: - endpoint - Include the endpoint L_i
4732: Output Parameter:
4733: . out - The localized coordinate point
4735: Level: developer
4737: .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate()
4738: @*/
4739: PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[])
4740: {
4741: PetscInt dim, d;
4745: DMGetCoordinateDim(dm, &dim);
4746: if (!dm->maxCell) {
4747: for (d = 0; d < dim; ++d) out[d] = in[d];
4748: } else {
4749: if (endpoint) {
4750: for (d = 0; d < dim; ++d) {
4751: 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)) {
4752: out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1);
4753: } else {
4754: out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]);
4755: }
4756: }
4757: } else {
4758: for (d = 0; d < dim; ++d) {
4759: out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]);
4760: }
4761: }
4762: }
4763: return(0);
4764: }
4766: /*
4767: 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.
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 point (dim numbers)
4775: Output Parameter:
4776: . out - The localized coordinate point
4778: Level: developer
4780: 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
4782: .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate()
4783: */
4784: PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[])
4785: {
4786: PetscInt d;
4789: if (!dm->maxCell) {
4790: for (d = 0; d < dim; ++d) out[d] = in[d];
4791: } else {
4792: for (d = 0; d < dim; ++d) {
4793: if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) {
4794: out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d];
4795: } else {
4796: out[d] = in[d];
4797: }
4798: }
4799: }
4800: return(0);
4801: }
4802: PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[])
4803: {
4804: PetscInt d;
4807: if (!dm->maxCell) {
4808: for (d = 0; d < dim; ++d) out[d] = in[d];
4809: } else {
4810: for (d = 0; d < dim; ++d) {
4811: if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) {
4812: out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d];
4813: } else {
4814: out[d] = in[d];
4815: }
4816: }
4817: }
4818: return(0);
4819: }
4821: /*
4822: 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.
4824: Input Parameters:
4825: + dm - The DM
4826: . dim - The spatial dimension
4827: . anchor - The anchor point, the input point can be no more than maxCell away from it
4828: . in - The input coordinate delta (dim numbers)
4829: - out - The input coordinate point (dim numbers)
4831: Output Parameter:
4832: . out - The localized coordinate in + out
4834: Level: developer
4836: 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
4838: .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate()
4839: */
4840: PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[])
4841: {
4842: PetscInt d;
4845: if (!dm->maxCell) {
4846: for (d = 0; d < dim; ++d) out[d] += in[d];
4847: } else {
4848: for (d = 0; d < dim; ++d) {
4849: if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) {
4850: out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d];
4851: } else {
4852: out[d] += in[d];
4853: }
4854: }
4855: }
4856: return(0);
4857: }
4859: /*@
4860: DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells
4862: Input Parameter:
4863: . dm - The DM
4865: Output Parameter:
4866: areLocalized - True if localized
4868: Level: developer
4870: .seealso: DMLocalizeCoordinates()
4871: @*/
4872: PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized)
4873: {
4874: DM cdm;
4875: PetscSection coordSection;
4876: PetscInt cStart, cEnd, sStart, sEnd, c, dof;
4877: PetscBool isPlex, alreadyLocalized;
4884: *areLocalized = PETSC_FALSE;
4885: if (!dm->periodic) return(0); /* This is a hideous optimization hack! */
4887: /* We need some generic way of refering to cells/vertices */
4888: DMGetCoordinateDM(dm, &cdm);
4889: DMGetCoordinateSection(dm, &coordSection);
4890: PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);
4891: if (!isPlex) SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM");
4893: DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);
4894: PetscSectionGetChart(coordSection, &sStart, &sEnd);
4895: alreadyLocalized = PETSC_FALSE;
4896: for (c = cStart; c < cEnd; ++c) {
4897: if (c < sStart || c >= sEnd) continue;
4898: PetscSectionGetDof(coordSection, c, &dof);
4899: if (dof) { alreadyLocalized = PETSC_TRUE; break; }
4900: }
4901: MPIU_Allreduce(&alreadyLocalized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));
4902: return(0);
4903: }
4906: /*@
4907: DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces
4909: Input Parameter:
4910: . dm - The DM
4912: Level: developer
4914: .seealso: DMLocalizeCoordinate(), DMLocalizeAddCoordinate()
4915: @*/
4916: PetscErrorCode DMLocalizeCoordinates(DM dm)
4917: {
4918: DM cdm;
4919: PetscSection coordSection, cSection;
4920: Vec coordinates, cVec;
4921: PetscScalar *coords, *coords2, *anchor, *localized;
4922: PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize;
4923: PetscBool alreadyLocalized, alreadyLocalizedGlobal;
4924: PetscInt maxHeight = 0, h;
4925: PetscInt *pStart = NULL, *pEnd = NULL;
4930: if (!dm->periodic) return(0);
4931: DMGetCoordinatesLocalized(dm, &alreadyLocalized);
4932: if (alreadyLocalized) return(0);
4934: /* We need some generic way of refering to cells/vertices */
4935: DMGetCoordinateDM(dm, &cdm);
4936: {
4937: PetscBool isplex;
4939: PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);
4940: if (isplex) {
4941: DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);
4942: DMPlexGetMaxProjectionHeight(cdm,&maxHeight);
4943: DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);
4944: pEnd = &pStart[maxHeight + 1];
4945: newStart = vStart;
4946: newEnd = vEnd;
4947: for (h = 0; h <= maxHeight; h++) {
4948: DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);
4949: newStart = PetscMin(newStart,pStart[h]);
4950: newEnd = PetscMax(newEnd,pEnd[h]);
4951: }
4952: } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM");
4953: }
4954: DMGetCoordinatesLocal(dm, &coordinates);
4955: if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector");
4956: DMGetCoordinateSection(dm, &coordSection);
4957: VecGetBlockSize(coordinates, &bs);
4958: PetscSectionGetChart(coordSection,&sStart,&sEnd);
4960: PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);
4961: PetscSectionSetNumFields(cSection, 1);
4962: PetscSectionGetFieldComponents(coordSection, 0, &Nc);
4963: PetscSectionSetFieldComponents(cSection, 0, Nc);
4964: PetscSectionSetChart(cSection, newStart, newEnd);
4966: DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);
4967: localized = &anchor[bs];
4968: alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE;
4969: for (h = 0; h <= maxHeight; h++) {
4970: PetscInt cStart = pStart[h], cEnd = pEnd[h], c;
4972: for (c = cStart; c < cEnd; ++c) {
4973: PetscScalar *cellCoords = NULL;
4974: PetscInt b;
4976: if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE;
4977: DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
4978: for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b];
4979: for (d = 0; d < dof/bs; ++d) {
4980: DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);
4981: for (b = 0; b < bs; b++) {
4982: if (cellCoords[d*bs + b] != localized[b]) break;
4983: }
4984: if (b < bs) break;
4985: }
4986: if (d < dof/bs) {
4987: if (c >= sStart && c < sEnd) {
4988: PetscInt cdof;
4990: PetscSectionGetDof(coordSection, c, &cdof);
4991: if (cdof != dof) alreadyLocalized = PETSC_FALSE;
4992: }
4993: PetscSectionSetDof(cSection, c, dof);
4994: PetscSectionSetFieldDof(cSection, c, 0, dof);
4995: }
4996: DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
4997: }
4998: }
4999: MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));
5000: if (alreadyLocalizedGlobal) {
5001: DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);
5002: PetscSectionDestroy(&cSection);
5003: DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);
5004: return(0);
5005: }
5006: for (v = vStart; v < vEnd; ++v) {
5007: PetscSectionGetDof(coordSection, v, &dof);
5008: PetscSectionSetDof(cSection, v, dof);
5009: PetscSectionSetFieldDof(cSection, v, 0, dof);
5010: }
5011: PetscSectionSetUp(cSection);
5012: PetscSectionGetStorageSize(cSection, &coordSize);
5013: VecCreate(PETSC_COMM_SELF, &cVec);
5014: PetscObjectSetName((PetscObject)cVec,"coordinates");
5015: VecSetBlockSize(cVec, bs);
5016: VecSetSizes(cVec, coordSize, PETSC_DETERMINE);
5017: VecSetType(cVec, VECSTANDARD);
5018: VecGetArrayRead(coordinates, (const PetscScalar**)&coords);
5019: VecGetArray(cVec, &coords2);
5020: for (v = vStart; v < vEnd; ++v) {
5021: PetscSectionGetDof(coordSection, v, &dof);
5022: PetscSectionGetOffset(coordSection, v, &off);
5023: PetscSectionGetOffset(cSection, v, &off2);
5024: for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d];
5025: }
5026: for (h = 0; h <= maxHeight; h++) {
5027: PetscInt cStart = pStart[h], cEnd = pEnd[h], c;
5029: for (c = cStart; c < cEnd; ++c) {
5030: PetscScalar *cellCoords = NULL;
5031: PetscInt b, cdof;
5033: PetscSectionGetDof(cSection,c,&cdof);
5034: if (!cdof) continue;
5035: DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
5036: PetscSectionGetOffset(cSection, c, &off2);
5037: for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b];
5038: for (d = 0; d < dof/bs; ++d) {DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);}
5039: DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
5040: }
5041: }
5042: DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);
5043: DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);
5044: VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);
5045: VecRestoreArray(cVec, &coords2);
5046: DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);
5047: DMSetCoordinatesLocal(dm, cVec);
5048: VecDestroy(&cVec);
5049: PetscSectionDestroy(&cSection);
5050: return(0);
5051: }
5053: /*@
5054: DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells
5056: Collective on Vec v (see explanation below)
5058: Input Parameters:
5059: + dm - The DM
5060: . v - The Vec of points
5061: . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST
5062: - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point.
5064: Output Parameter:
5065: + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used
5066: - cells - The PetscSF containing the ranks and local indices of the containing points.
5069: Level: developer
5071: Notes:
5072: To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator.
5073: To do a search of all the cells in the distributed mesh, v should have the same communicator as dm.
5075: If *cellSF is NULL on input, a PetscSF will be created.
5076: If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses.
5078: An array that maps each point to its containing cell can be obtained with
5080: $ const PetscSFNode *cells;
5081: $ PetscInt nFound;
5082: $ const PetscInt *found;
5083: $
5084: $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells);
5086: Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is
5087: the index of the cell in its rank's local numbering.
5089: .keywords: point location, mesh
5090: .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType
5091: @*/
5092: PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF)
5093: {
5100: if (*cellSF) {
5101: PetscMPIInt result;
5104: MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);
5105: if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's");
5106: } else {
5107: PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);
5108: }
5109: PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);
5110: if (dm->ops->locatepoints) {
5111: (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);
5112: } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM");
5113: PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);
5114: return(0);
5115: }
5117: /*@
5118: DMGetOutputDM - Retrieve the DM associated with the layout for output
5120: Input Parameter:
5121: . dm - The original DM
5123: Output Parameter:
5124: . odm - The DM which provides the layout for output
5126: Level: intermediate
5128: .seealso: VecView(), DMGetGlobalSection()
5129: @*/
5130: PetscErrorCode DMGetOutputDM(DM dm, DM *odm)
5131: {
5132: PetscSection section;
5133: PetscBool hasConstraints, ghasConstraints;
5139: DMGetSection(dm, §ion);
5140: PetscSectionHasConstraints(section, &hasConstraints);
5141: MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));
5142: if (!ghasConstraints) {
5143: *odm = dm;
5144: return(0);
5145: }
5146: if (!dm->dmBC) {
5147: PetscDS ds;
5148: PetscSection newSection, gsection;
5149: PetscSF sf;
5151: DMClone(dm, &dm->dmBC);
5152: DMGetDS(dm, &ds);
5153: DMSetDS(dm->dmBC, ds);
5154: PetscSectionClone(section, &newSection);
5155: DMSetSection(dm->dmBC, newSection);
5156: PetscSectionDestroy(&newSection);
5157: DMGetPointSF(dm->dmBC, &sf);
5158: PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);
5159: DMSetGlobalSection(dm->dmBC, gsection);
5160: PetscSectionDestroy(&gsection);
5161: }
5162: *odm = dm->dmBC;
5163: return(0);
5164: }
5166: /*@
5167: DMGetOutputSequenceNumber - Retrieve the sequence number/value for output
5169: Input Parameter:
5170: . dm - The original DM
5172: Output Parameters:
5173: + num - The output sequence number
5174: - val - The output sequence value
5176: Level: intermediate
5178: Note: This is intended for output that should appear in sequence, for instance
5179: a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
5181: .seealso: VecView()
5182: @*/
5183: PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val)
5184: {
5189: return(0);
5190: }
5192: /*@
5193: DMSetOutputSequenceNumber - Set the sequence number/value for output
5195: Input Parameters:
5196: + dm - The original DM
5197: . num - The output sequence number
5198: - val - The output sequence value
5200: Level: intermediate
5202: Note: This is intended for output that should appear in sequence, for instance
5203: a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
5205: .seealso: VecView()
5206: @*/
5207: PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val)
5208: {
5211: dm->outputSequenceNum = num;
5212: dm->outputSequenceVal = val;
5213: return(0);
5214: }
5216: /*@C
5217: DMOutputSequenceLoad - Retrieve the sequence value from a Viewer
5219: Input Parameters:
5220: + dm - The original DM
5221: . name - The sequence name
5222: - num - The output sequence number
5224: Output Parameter:
5225: . val - The output sequence value
5227: Level: intermediate
5229: Note: This is intended for output that should appear in sequence, for instance
5230: a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
5232: .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView()
5233: @*/
5234: PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val)
5235: {
5236: PetscBool ishdf5;
5243: PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);
5244: if (ishdf5) {
5245: #if defined(PETSC_HAVE_HDF5)
5246: PetscScalar value;
5248: DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);
5249: *val = PetscRealPart(value);
5250: #endif
5251: } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
5252: return(0);
5253: }
5255: /*@
5256: DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution
5258: Not collective
5260: Input Parameter:
5261: . dm - The DM
5263: Output Parameter:
5264: . useNatural - The flag to build the mapping to a natural order during distribution
5266: Level: beginner
5268: .seealso: DMSetUseNatural(), DMCreate()
5269: @*/
5270: PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural)
5271: {
5275: *useNatural = dm->useNatural;
5276: return(0);
5277: }
5279: /*@
5280: DMSetUseNatural - Set the flag for creating a mapping to the natural order on distribution
5282: Collective on dm
5284: Input Parameters:
5285: + dm - The DM
5286: - useNatural - The flag to build the mapping to a natural order during distribution
5288: Level: beginner
5290: .seealso: DMGetUseNatural(), DMCreate()
5291: @*/
5292: PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural)
5293: {
5297: dm->useNatural = useNatural;
5298: return(0);
5299: }
5302: /*@C
5303: DMCreateLabel - Create a label of the given name if it does not already exist
5305: Not Collective
5307: Input Parameters:
5308: + dm - The DM object
5309: - name - The label name
5311: Level: intermediate
5313: .keywords: mesh
5314: .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5315: @*/
5316: PetscErrorCode DMCreateLabel(DM dm, const char name[])
5317: {
5318: DMLabelLink next = dm->labels->next;
5319: PetscBool flg = PETSC_FALSE;
5325: while (next) {
5326: PetscStrcmp(name, next->label->name, &flg);
5327: if (flg) break;
5328: next = next->next;
5329: }
5330: if (!flg) {
5331: DMLabelLink tmpLabel;
5333: PetscCalloc1(1, &tmpLabel);
5334: DMLabelCreate(name, &tmpLabel->label);
5335: tmpLabel->output = PETSC_TRUE;
5336: tmpLabel->next = dm->labels->next;
5337: dm->labels->next = tmpLabel;
5338: }
5339: return(0);
5340: }
5342: /*@C
5343: DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default
5345: Not Collective
5347: Input Parameters:
5348: + dm - The DM object
5349: . name - The label name
5350: - point - The mesh point
5352: Output Parameter:
5353: . value - The label value for this point, or -1 if the point is not in the label
5355: Level: beginner
5357: .keywords: mesh
5358: .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS()
5359: @*/
5360: PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value)
5361: {
5362: DMLabel label;
5368: DMGetLabel(dm, name, &label);
5369: if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);
5370: DMLabelGetValue(label, point, value);
5371: return(0);
5372: }
5374: /*@C
5375: DMSetLabelValue - Add a point to a Sieve Label with given value
5377: Not Collective
5379: Input Parameters:
5380: + dm - The DM object
5381: . name - The label name
5382: . point - The mesh point
5383: - value - The label value for this point
5385: Output Parameter:
5387: Level: beginner
5389: .keywords: mesh
5390: .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue()
5391: @*/
5392: PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
5393: {
5394: DMLabel label;
5400: DMGetLabel(dm, name, &label);
5401: if (!label) {
5402: DMCreateLabel(dm, name);
5403: DMGetLabel(dm, name, &label);
5404: }
5405: DMLabelSetValue(label, point, value);
5406: return(0);
5407: }
5409: /*@C
5410: DMClearLabelValue - Remove a point from a Sieve Label with given value
5412: Not Collective
5414: Input Parameters:
5415: + dm - The DM object
5416: . name - The label name
5417: . point - The mesh point
5418: - value - The label value for this point
5420: Output Parameter:
5422: Level: beginner
5424: .keywords: mesh
5425: .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS()
5426: @*/
5427: PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
5428: {
5429: DMLabel label;
5435: DMGetLabel(dm, name, &label);
5436: if (!label) return(0);
5437: DMLabelClearValue(label, point, value);
5438: return(0);
5439: }
5441: /*@C
5442: DMGetLabelSize - Get the number of different integer ids in a Label
5444: Not Collective
5446: Input Parameters:
5447: + dm - The DM object
5448: - name - The label name
5450: Output Parameter:
5451: . size - The number of different integer ids, or 0 if the label does not exist
5453: Level: beginner
5455: .keywords: mesh
5456: .seealso: DMLabeGetNumValues(), DMSetLabelValue()
5457: @*/
5458: PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size)
5459: {
5460: DMLabel label;
5467: DMGetLabel(dm, name, &label);
5468: *size = 0;
5469: if (!label) return(0);
5470: DMLabelGetNumValues(label, size);
5471: return(0);
5472: }
5474: /*@C
5475: DMGetLabelIdIS - Get the integer ids in a label
5477: Not Collective
5479: Input Parameters:
5480: + mesh - The DM object
5481: - name - The label name
5483: Output Parameter:
5484: . ids - The integer ids, or NULL if the label does not exist
5486: Level: beginner
5488: .keywords: mesh
5489: .seealso: DMLabelGetValueIS(), DMGetLabelSize()
5490: @*/
5491: PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids)
5492: {
5493: DMLabel label;
5500: DMGetLabel(dm, name, &label);
5501: *ids = NULL;
5502: if (label) {
5503: DMLabelGetValueIS(label, ids);
5504: } else {
5505: /* returning an empty IS */
5506: ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);
5507: }
5508: return(0);
5509: }
5511: /*@C
5512: DMGetStratumSize - Get the number of points in a label stratum
5514: Not Collective
5516: Input Parameters:
5517: + dm - The DM object
5518: . name - The label name
5519: - value - The stratum value
5521: Output Parameter:
5522: . size - The stratum size
5524: Level: beginner
5526: .keywords: mesh
5527: .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds()
5528: @*/
5529: PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size)
5530: {
5531: DMLabel label;
5538: DMGetLabel(dm, name, &label);
5539: *size = 0;
5540: if (!label) return(0);
5541: DMLabelGetStratumSize(label, value, size);
5542: return(0);
5543: }
5545: /*@C
5546: DMGetStratumIS - Get the points in a label stratum
5548: Not Collective
5550: Input Parameters:
5551: + dm - The DM object
5552: . name - The label name
5553: - value - The stratum value
5555: Output Parameter:
5556: . points - The stratum points, or NULL if the label does not exist or does not have that value
5558: Level: beginner
5560: .keywords: mesh
5561: .seealso: DMLabelGetStratumIS(), DMGetStratumSize()
5562: @*/
5563: PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points)
5564: {
5565: DMLabel label;
5572: DMGetLabel(dm, name, &label);
5573: *points = NULL;
5574: if (!label) return(0);
5575: DMLabelGetStratumIS(label, value, points);
5576: return(0);
5577: }
5579: /*@C
5580: DMSetStratumIS - Set the points in a label stratum
5582: Not Collective
5584: Input Parameters:
5585: + dm - The DM object
5586: . name - The label name
5587: . value - The stratum value
5588: - points - The stratum points
5590: Level: beginner
5592: .keywords: mesh
5593: .seealso: DMLabelSetStratumIS(), DMGetStratumSize()
5594: @*/
5595: PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points)
5596: {
5597: DMLabel label;
5604: DMGetLabel(dm, name, &label);
5605: if (!label) return(0);
5606: DMLabelSetStratumIS(label, value, points);
5607: return(0);
5608: }
5610: /*@C
5611: DMClearLabelStratum - Remove all points from a stratum from a Sieve Label
5613: Not Collective
5615: Input Parameters:
5616: + dm - The DM object
5617: . name - The label name
5618: - value - The label value for this point
5620: Output Parameter:
5622: Level: beginner
5624: .keywords: mesh
5625: .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue()
5626: @*/
5627: PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value)
5628: {
5629: DMLabel label;
5635: DMGetLabel(dm, name, &label);
5636: if (!label) return(0);
5637: DMLabelClearStratum(label, value);
5638: return(0);
5639: }
5641: /*@
5642: DMGetNumLabels - Return the number of labels defined by the mesh
5644: Not Collective
5646: Input Parameter:
5647: . dm - The DM object
5649: Output Parameter:
5650: . numLabels - the number of Labels
5652: Level: intermediate
5654: .keywords: mesh
5655: .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5656: @*/
5657: PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels)
5658: {
5659: DMLabelLink next = dm->labels->next;
5660: PetscInt n = 0;
5665: while (next) {++n; next = next->next;}
5666: *numLabels = n;
5667: return(0);
5668: }
5670: /*@C
5671: DMGetLabelName - Return the name of nth label
5673: Not Collective
5675: Input Parameters:
5676: + dm - The DM object
5677: - n - the label number
5679: Output Parameter:
5680: . name - the label name
5682: Level: intermediate
5684: .keywords: mesh
5685: .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5686: @*/
5687: PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name)
5688: {
5689: DMLabelLink next = dm->labels->next;
5690: PetscInt l = 0;
5695: while (next) {
5696: if (l == n) {
5697: *name = next->label->name;
5698: return(0);
5699: }
5700: ++l;
5701: next = next->next;
5702: }
5703: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n);
5704: }
5706: /*@C
5707: DMHasLabel - Determine whether the mesh has a label of a given name
5709: Not Collective
5711: Input Parameters:
5712: + dm - The DM object
5713: - name - The label name
5715: Output Parameter:
5716: . hasLabel - PETSC_TRUE if the label is present
5718: Level: intermediate
5720: .keywords: mesh
5721: .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5722: @*/
5723: PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel)
5724: {
5725: DMLabelLink next = dm->labels->next;
5732: *hasLabel = PETSC_FALSE;
5733: while (next) {
5734: PetscStrcmp(name, next->label->name, hasLabel);
5735: if (*hasLabel) break;
5736: next = next->next;
5737: }
5738: return(0);
5739: }
5741: /*@C
5742: DMGetLabel - Return the label of a given name, or NULL
5744: Not Collective
5746: Input Parameters:
5747: + dm - The DM object
5748: - name - The label name
5750: Output Parameter:
5751: . label - The DMLabel, or NULL if the label is absent
5753: Level: intermediate
5755: .keywords: mesh
5756: .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5757: @*/
5758: PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label)
5759: {
5760: DMLabelLink next = dm->labels->next;
5761: PetscBool hasLabel;
5768: *label = NULL;
5769: while (next) {
5770: PetscStrcmp(name, next->label->name, &hasLabel);
5771: if (hasLabel) {
5772: *label = next->label;
5773: break;
5774: }
5775: next = next->next;
5776: }
5777: return(0);
5778: }
5780: /*@C
5781: DMGetLabelByNum - Return the nth label
5783: Not Collective
5785: Input Parameters:
5786: + dm - The DM object
5787: - n - the label number
5789: Output Parameter:
5790: . label - the label
5792: Level: intermediate
5794: .keywords: mesh
5795: .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5796: @*/
5797: PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label)
5798: {
5799: DMLabelLink next = dm->labels->next;
5800: PetscInt l = 0;
5805: while (next) {
5806: if (l == n) {
5807: *label = next->label;
5808: return(0);
5809: }
5810: ++l;
5811: next = next->next;
5812: }
5813: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n);
5814: }
5816: /*@C
5817: DMAddLabel - Add the label to this mesh
5819: Not Collective
5821: Input Parameters:
5822: + dm - The DM object
5823: - label - The DMLabel
5825: Level: developer
5827: .keywords: mesh
5828: .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5829: @*/
5830: PetscErrorCode DMAddLabel(DM dm, DMLabel label)
5831: {
5832: DMLabelLink tmpLabel;
5833: PetscBool hasLabel;
5838: DMHasLabel(dm, label->name, &hasLabel);
5839: if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", label->name);
5840: PetscCalloc1(1, &tmpLabel);
5841: tmpLabel->label = label;
5842: tmpLabel->output = PETSC_TRUE;
5843: tmpLabel->next = dm->labels->next;
5844: dm->labels->next = tmpLabel;
5845: return(0);
5846: }
5848: /*@C
5849: DMRemoveLabel - Remove the label from this mesh
5851: Not Collective
5853: Input Parameters:
5854: + dm - The DM object
5855: - name - The label name
5857: Output Parameter:
5858: . label - The DMLabel, or NULL if the label is absent
5860: Level: developer
5862: .keywords: mesh
5863: .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5864: @*/
5865: PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label)
5866: {
5867: DMLabelLink next = dm->labels->next;
5868: DMLabelLink last = NULL;
5869: PetscBool hasLabel;
5874: DMHasLabel(dm, name, &hasLabel);
5875: *label = NULL;
5876: if (!hasLabel) return(0);
5877: while (next) {
5878: PetscStrcmp(name, next->label->name, &hasLabel);
5879: if (hasLabel) {
5880: if (last) last->next = next->next;
5881: else dm->labels->next = next->next;
5882: next->next = NULL;
5883: *label = next->label;
5884: PetscStrcmp(name, "depth", &hasLabel);
5885: if (hasLabel) {
5886: dm->depthLabel = NULL;
5887: }
5888: PetscFree(next);
5889: break;
5890: }
5891: last = next;
5892: next = next->next;
5893: }
5894: return(0);
5895: }
5897: /*@C
5898: DMGetLabelOutput - Get the output flag for a given label
5900: Not Collective
5902: Input Parameters:
5903: + dm - The DM object
5904: - name - The label name
5906: Output Parameter:
5907: . output - The flag for output
5909: Level: developer
5911: .keywords: mesh
5912: .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5913: @*/
5914: PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output)
5915: {
5916: DMLabelLink next = dm->labels->next;
5923: while (next) {
5924: PetscBool flg;
5926: PetscStrcmp(name, next->label->name, &flg);
5927: if (flg) {*output = next->output; return(0);}
5928: next = next->next;
5929: }
5930: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
5931: }
5933: /*@C
5934: DMSetLabelOutput - Set the output flag for a given label
5936: Not Collective
5938: Input Parameters:
5939: + dm - The DM object
5940: . name - The label name
5941: - output - The flag for output
5943: Level: developer
5945: .keywords: mesh
5946: .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5947: @*/
5948: PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output)
5949: {
5950: DMLabelLink next = dm->labels->next;
5956: while (next) {
5957: PetscBool flg;
5959: PetscStrcmp(name, next->label->name, &flg);
5960: if (flg) {next->output = output; return(0);}
5961: next = next->next;
5962: }
5963: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
5964: }
5967: /*@
5968: DMCopyLabels - Copy labels from one mesh to another with a superset of the points
5970: Collective on DM
5972: Input Parameter:
5973: . dmA - The DM object with initial labels
5975: Output Parameter:
5976: . dmB - The DM object with copied labels
5978: Level: intermediate
5980: Note: This is typically used when interpolating or otherwise adding to a mesh
5982: .keywords: mesh
5983: .seealso: DMCopyCoordinates(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection()
5984: @*/
5985: PetscErrorCode DMCopyLabels(DM dmA, DM dmB)
5986: {
5987: PetscInt numLabels, l;
5991: if (dmA == dmB) return(0);
5992: DMGetNumLabels(dmA, &numLabels);
5993: for (l = 0; l < numLabels; ++l) {
5994: DMLabel label, labelNew;
5995: const char *name;
5996: PetscBool flg;
5998: DMGetLabelName(dmA, l, &name);
5999: PetscStrcmp(name, "depth", &flg);
6000: if (flg) continue;
6001: PetscStrcmp(name, "dim", &flg);
6002: if (flg) continue;
6003: DMGetLabel(dmA, name, &label);
6004: DMLabelDuplicate(label, &labelNew);
6005: DMAddLabel(dmB, labelNew);
6006: }
6007: return(0);
6008: }
6010: /*@
6011: DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement
6013: Input Parameter:
6014: . dm - The DM object
6016: Output Parameter:
6017: . cdm - The coarse DM
6019: Level: intermediate
6021: .seealso: DMSetCoarseDM()
6022: @*/
6023: PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm)
6024: {
6028: *cdm = dm->coarseMesh;
6029: return(0);
6030: }
6032: /*@
6033: DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement
6035: Input Parameters:
6036: + dm - The DM object
6037: - cdm - The coarse DM
6039: Level: intermediate
6041: .seealso: DMGetCoarseDM()
6042: @*/
6043: PetscErrorCode DMSetCoarseDM(DM dm, DM cdm)
6044: {
6050: PetscObjectReference((PetscObject)cdm);
6051: DMDestroy(&dm->coarseMesh);
6052: dm->coarseMesh = cdm;
6053: return(0);
6054: }
6056: /*@
6057: DMGetFineDM - Get the fine mesh from which this was obtained by refinement
6059: Input Parameter:
6060: . dm - The DM object
6062: Output Parameter:
6063: . fdm - The fine DM
6065: Level: intermediate
6067: .seealso: DMSetFineDM()
6068: @*/
6069: PetscErrorCode DMGetFineDM(DM dm, DM *fdm)
6070: {
6074: *fdm = dm->fineMesh;
6075: return(0);
6076: }
6078: /*@
6079: DMSetFineDM - Set the fine mesh from which this was obtained by refinement
6081: Input Parameters:
6082: + dm - The DM object
6083: - fdm - The fine DM
6085: Level: intermediate
6087: .seealso: DMGetFineDM()
6088: @*/
6089: PetscErrorCode DMSetFineDM(DM dm, DM fdm)
6090: {
6096: PetscObjectReference((PetscObject)fdm);
6097: DMDestroy(&dm->fineMesh);
6098: dm->fineMesh = fdm;
6099: return(0);
6100: }
6102: /*=== DMBoundary code ===*/
6104: PetscErrorCode DMCopyBoundary(DM dm, DM dmNew)
6105: {
6109: PetscDSCopyBoundary(dm->prob,dmNew->prob);
6110: return(0);
6111: }
6113: /*@C
6114: DMAddBoundary - Add a boundary condition to the model
6116: Input Parameters:
6117: + dm - The DM, with a PetscDS that matches the problem being constrained
6118: . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
6119: . name - The BC name
6120: . labelname - The label defining constrained points
6121: . field - The field to constrain
6122: . numcomps - The number of constrained field components
6123: . comps - An array of constrained component numbers
6124: . bcFunc - A pointwise function giving boundary values
6125: . numids - The number of DMLabel ids for constrained points
6126: . ids - An array of ids for constrained points
6127: - ctx - An optional user context for bcFunc
6129: Options Database Keys:
6130: + -bc_<boundary name> <num> - Overrides the boundary ids
6131: - -bc_<boundary name>_comp <num> - Overrides the boundary components
6133: Level: developer
6135: .seealso: DMGetBoundary()
6136: @*/
6137: 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)
6138: {
6143: PetscDSAddBoundary(dm->prob,type,name,labelname,field,numcomps,comps,bcFunc,numids,ids,ctx);
6144: return(0);
6145: }
6147: /*@
6148: DMGetNumBoundary - Get the number of registered BC
6150: Input Parameters:
6151: . dm - The mesh object
6153: Output Parameters:
6154: . numBd - The number of BC
6156: Level: intermediate
6158: .seealso: DMAddBoundary(), DMGetBoundary()
6159: @*/
6160: PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd)
6161: {
6166: PetscDSGetNumBoundary(dm->prob,numBd);
6167: return(0);
6168: }
6170: /*@C
6171: DMGetBoundary - Get a model boundary condition
6173: Input Parameters:
6174: + dm - The mesh object
6175: - bd - The BC number
6177: Output Parameters:
6178: + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
6179: . name - The BC name
6180: . labelname - The label defining constrained points
6181: . field - The field to constrain
6182: . numcomps - The number of constrained field components
6183: . comps - An array of constrained component numbers
6184: . bcFunc - A pointwise function giving boundary values
6185: . numids - The number of DMLabel ids for constrained points
6186: . ids - An array of ids for constrained points
6187: - ctx - An optional user context for bcFunc
6189: Options Database Keys:
6190: + -bc_<boundary name> <num> - Overrides the boundary ids
6191: - -bc_<boundary name>_comp <num> - Overrides the boundary components
6193: Level: developer
6195: .seealso: DMAddBoundary()
6196: @*/
6197: 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)
6198: {
6203: PetscDSGetBoundary(dm->prob,bd,type,name,labelname,field,numcomps,comps,func,numids,ids,ctx);
6204: return(0);
6205: }
6207: static PetscErrorCode DMPopulateBoundary(DM dm)
6208: {
6209: DMBoundary *lastnext;
6210: DSBoundary dsbound;
6214: dsbound = dm->prob->boundary;
6215: if (dm->boundary) {
6216: DMBoundary next = dm->boundary;
6218: /* quick check to see if the PetscDS has changed */
6219: if (next->dsboundary == dsbound) return(0);
6220: /* the PetscDS has changed: tear down and rebuild */
6221: while (next) {
6222: DMBoundary b = next;
6224: next = b->next;
6225: PetscFree(b);
6226: }
6227: dm->boundary = NULL;
6228: }
6230: lastnext = &(dm->boundary);
6231: while (dsbound) {
6232: DMBoundary dmbound;
6234: PetscNew(&dmbound);
6235: dmbound->dsboundary = dsbound;
6236: DMGetLabel(dm, dsbound->labelname, &(dmbound->label));
6237: if (!dmbound->label) {PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);}
6238: /* push on the back instead of the front so that it is in the same order as in the PetscDS */
6239: *lastnext = dmbound;
6240: lastnext = &(dmbound->next);
6241: dsbound = dsbound->next;
6242: }
6243: return(0);
6244: }
6246: PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd)
6247: {
6248: DMBoundary b;
6254: *isBd = PETSC_FALSE;
6255: DMPopulateBoundary(dm);
6256: b = dm->boundary;
6257: while (b && !(*isBd)) {
6258: DMLabel label = b->label;
6259: DSBoundary dsb = b->dsboundary;
6261: if (label) {
6262: PetscInt i;
6264: for (i = 0; i < dsb->numids && !(*isBd); ++i) {
6265: DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);
6266: }
6267: }
6268: b = b->next;
6269: }
6270: return(0);
6271: }
6273: /*@C
6274: DMProjectFunction - This projects the given function into the function space provided.
6276: Input Parameters:
6277: + dm - The DM
6278: . time - The time
6279: . funcs - The coordinate functions to evaluate, one per field
6280: . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null.
6281: - mode - The insertion mode for values
6283: Output Parameter:
6284: . X - vector
6286: Calling sequence of func:
6287: $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx);
6289: + dim - The spatial dimension
6290: . x - The coordinates
6291: . Nf - The number of fields
6292: . u - The output field values
6293: - ctx - optional user-defined function context
6295: Level: developer
6297: .seealso: DMComputeL2Diff()
6298: @*/
6299: PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X)
6300: {
6301: Vec localX;
6306: DMGetLocalVector(dm, &localX);
6307: DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);
6308: DMLocalToGlobalBegin(dm, localX, mode, X);
6309: DMLocalToGlobalEnd(dm, localX, mode, X);
6310: DMRestoreLocalVector(dm, &localX);
6311: return(0);
6312: }
6314: PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
6315: {
6321: if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name);
6322: (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);
6323: return(0);
6324: }
6326: 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)
6327: {
6328: Vec localX;
6333: DMGetLocalVector(dm, &localX);
6334: DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);
6335: DMLocalToGlobalBegin(dm, localX, mode, X);
6336: DMLocalToGlobalEnd(dm, localX, mode, X);
6337: DMRestoreLocalVector(dm, &localX);
6338: return(0);
6339: }
6341: 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)
6342: {
6348: if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name);
6349: (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);
6350: return(0);
6351: }
6353: PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU,
6354: void (**funcs)(PetscInt, PetscInt, PetscInt,
6355: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
6356: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
6357: PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
6358: InsertMode mode, Vec localX)
6359: {
6366: if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name);
6367: (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);
6368: return(0);
6369: }
6371: PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU,
6372: void (**funcs)(PetscInt, PetscInt, PetscInt,
6373: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
6374: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
6375: PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
6376: InsertMode mode, Vec localX)
6377: {
6384: if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name);
6385: (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);
6386: return(0);
6387: }
6389: /*@C
6390: DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h.
6392: Input Parameters:
6393: + dm - The DM
6394: . time - The time
6395: . funcs - The functions to evaluate for each field component
6396: . ctxs - Optional array of contexts to pass to each function, or NULL.
6397: - X - The coefficient vector u_h, a global vector
6399: Output Parameter:
6400: . diff - The diff ||u - u_h||_2
6402: Level: developer
6404: .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff()
6405: @*/
6406: PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff)
6407: {
6413: if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name);
6414: (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);
6415: return(0);
6416: }
6418: /*@C
6419: DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h.
6421: Input Parameters:
6422: + dm - The DM
6423: , time - The time
6424: . funcs - The gradient functions to evaluate for each field component
6425: . ctxs - Optional array of contexts to pass to each function, or NULL.
6426: . X - The coefficient vector u_h, a global vector
6427: - n - The vector to project along
6429: Output Parameter:
6430: . diff - The diff ||(grad u - grad u_h) . n||_2
6432: Level: developer
6434: .seealso: DMProjectFunction(), DMComputeL2Diff()
6435: @*/
6436: 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)
6437: {
6443: if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name);
6444: (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);
6445: return(0);
6446: }
6448: /*@C
6449: DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components.
6451: Input Parameters:
6452: + dm - The DM
6453: . time - The time
6454: . funcs - The functions to evaluate for each field component
6455: . ctxs - Optional array of contexts to pass to each function, or NULL.
6456: - X - The coefficient vector u_h, a global vector
6458: Output Parameter:
6459: . diff - The array of differences, ||u^f - u^f_h||_2
6461: Level: developer
6463: .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff()
6464: @*/
6465: PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[])
6466: {
6472: if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name);
6473: (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);
6474: return(0);
6475: }
6477: /*@C
6478: DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have
6479: specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN.
6481: Collective on dm
6483: Input parameters:
6484: + dm - the pre-adaptation DM object
6485: - label - label with the flags
6487: Output parameters:
6488: . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced.
6490: Level: intermediate
6492: .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine()
6493: @*/
6494: PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt)
6495: {
6502: *dmAdapt = NULL;
6503: if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name);
6504: (dm->ops->adaptlabel)(dm, label, dmAdapt);
6505: return(0);
6506: }
6508: /*@C
6509: DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library.
6511: Input Parameters:
6512: + dm - The DM object
6513: . metric - The metric to which the mesh is adapted, defined vertex-wise.
6514: - 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_".
6516: Output Parameter:
6517: . dmAdapt - Pointer to the DM object containing the adapted mesh
6519: Note: The label in the adapted mesh will be registered under the name of the input DMLabel object
6521: Level: advanced
6523: .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine()
6524: @*/
6525: PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt)
6526: {
6534: *dmAdapt = NULL;
6535: if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name);
6536: (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);
6537: return(0);
6538: }
6540: /*@C
6541: DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors
6543: Not Collective
6545: Input Parameter:
6546: . dm - The DM
6548: Output Parameter:
6549: . nranks - the number of neighbours
6550: . ranks - the neighbors ranks
6552: Notes:
6553: Do not free the array, it is freed when the DM is destroyed.
6555: Level: beginner
6557: .seealso: DMDAGetNeighbors(), PetscSFGetRanks()
6558: @*/
6559: PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[])
6560: {
6565: if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name);
6566: (dm->ops->getneighbors)(dm,nranks,ranks);
6567: return(0);
6568: }
6570: #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */
6572: /*
6573: Converts the input vector to a ghosted vector and then calls the standard coloring code.
6574: This has be a different function because it requires DM which is not defined in the Mat library
6575: */
6576: PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx)
6577: {
6581: if (coloring->ctype == IS_COLORING_LOCAL) {
6582: Vec x1local;
6583: DM dm;
6584: MatGetDM(J,&dm);
6585: if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM");
6586: DMGetLocalVector(dm,&x1local);
6587: DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);
6588: DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);
6589: x1 = x1local;
6590: }
6591: MatFDColoringApply_AIJ(J,coloring,x1,sctx);
6592: if (coloring->ctype == IS_COLORING_LOCAL) {
6593: DM dm;
6594: MatGetDM(J,&dm);
6595: DMRestoreLocalVector(dm,&x1);
6596: }
6597: return(0);
6598: }
6600: /*@
6601: MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring
6603: Input Parameter:
6604: . coloring - the MatFDColoring object
6606: Developer Notes:
6607: this routine exists because the PETSc Mat library does not know about the DM objects
6609: Level: advanced
6611: .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType
6612: @*/
6613: PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring)
6614: {
6616: coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM;
6617: return(0);
6618: }
6620: /*@
6621: DMGetCompatibility - determine if two DMs are compatible
6623: Collective
6625: Input Parameters:
6626: + dm - the first DM
6627: - dm2 - the second DM
6629: Output Parameters:
6630: + compatible - whether or not the two DMs are compatible
6631: - set - whether or not the compatible value was set
6633: Notes:
6634: Two DMs are deemed compatible if they represent the same parallel decomposition
6635: of the same topology. This implies that the the section (field data) on one
6636: "makes sense" with respect to the topology and parallel decomposition of the other.
6637: Loosely speaking, compatibile DMs represent the same domain, with the same parallel
6638: decomposition, with different data.
6640: Typically, one would confirm compatibility if intending to simultaneously iterate
6641: over a pair of vectors obtained from different DMs.
6643: For example, two DMDA objects are compatible if they have the same local
6644: and global sizes and the same stencil width. They can have different numbers
6645: of degrees of freedom per node. Thus, one could use the node numbering from
6646: either DM in bounds for a loop over vectors derived from either DM.
6648: Consider the operation of summing data living on a 2-dof DMDA to data living
6649: on a 1-dof DMDA, which should be compatible, as in the following snippet.
6650: .vb
6651: ...
6652: DMGetCompatibility(da1,da2,&compatible,&set);
6653: if (set && compatible) {
6654: DMDAVecGetArrayDOF(da1,vec1,&arr1);
6655: DMDAVecGetArrayDOF(da2,vec2,&arr2);
6656: DMDAGetCorners(da1,&x,&y,NULL,&m,&n);
6657: for (j=y; j<y+n; ++j) {
6658: for (i=x; i<x+m, ++i) {
6659: arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1];
6660: }
6661: }
6662: DMDAVecRestoreArrayDOF(da1,vec1,&arr1);
6663: DMDAVecRestoreArrayDOF(da2,vec2,&arr2);
6664: } else {
6665: SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible");
6666: }
6667: ...
6668: .ve
6670: Checking compatibility might be expensive for a given implementation of DM,
6671: or might be impossible to unambiguously confirm or deny. For this reason,
6672: this function may decline to determine compatibility, and hence users should
6673: always check the "set" output parameter.
6675: A DM is always compatible with itself.
6677: In the current implementation, DMs which live on "unequal" communicators
6678: (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed
6679: incompatible.
6681: This function is labeled "Collective," as information about all subdomains
6682: is required on each rank. However, in DM implementations which store all this
6683: information locally, this function may be merely "Logically Collective".
6685: Developer Notes:
6686: Compatibility is assumed to be a symmetric concept; if DM A is compatible with DM B,
6687: the DM B is compatible with DM A. Thus, this function checks the implementations
6688: of both dm and dm2 (if they are of different types), attempting to determine
6689: compatibility. It is left to DM implementers to ensure that symmetry is
6690: preserved. The simplest way to do this is, when implementing type-specific
6691: logic for this function, to check for existing logic in the implementation
6692: of other DM types and let *set = PETSC_FALSE if found; the logic of this
6693: function will then call that logic.
6695: Level: advanced
6697: .seealso: DM, DMDACreateCompatibleDMDA()
6698: @*/
6700: PetscErrorCode DMGetCompatibility(DM dm,DM dm2,PetscBool *compatible,PetscBool *set)
6701: {
6703: PetscMPIInt compareResult;
6704: DMType type,type2;
6705: PetscBool sameType;
6711: /* Declare a DM compatible with itself */
6712: if (dm == dm2) {
6713: *set = PETSC_TRUE;
6714: *compatible = PETSC_TRUE;
6715: return(0);
6716: }
6718: /* Declare a DM incompatible with a DM that lives on an "unequal"
6719: communicator. Note that this does not preclude compatibility with
6720: DMs living on "congruent" or "similar" communicators, but this must be
6721: determined by the implementation-specific logic */
6722: MPI_Comm_compare(PetscObjectComm((PetscObject)dm),PetscObjectComm((PetscObject)dm2),&compareResult);
6723: if (compareResult == MPI_UNEQUAL) {
6724: *set = PETSC_TRUE;
6725: *compatible = PETSC_FALSE;
6726: return(0);
6727: }
6729: /* Pass to the implementation-specific routine, if one exists. */
6730: if (dm->ops->getcompatibility) {
6731: (*dm->ops->getcompatibility)(dm,dm2,compatible,set);
6732: if (*set) {
6733: return(0);
6734: }
6735: }
6737: /* If dm and dm2 are of different types, then attempt to check compatibility
6738: with an implementation of this function from dm2 */
6739: DMGetType(dm,&type);
6740: DMGetType(dm2,&type2);
6741: PetscStrcmp(type,type2,&sameType);
6742: if (!sameType && dm2->ops->getcompatibility) {
6743: (*dm2->ops->getcompatibility)(dm2,dm,compatible,set); /* Note argument order */
6744: } else {
6745: *set = PETSC_FALSE;
6746: }
6747: return(0);
6748: }