Actual source code: dm.c
petsc-3.14.6 2021-03-30
1: #include <petscvec.h>
2: #include <petsc/private/dmimpl.h>
3: #include <petsc/private/dmlabelimpl.h>
4: #include <petsc/private/petscdsimpl.h>
5: #include <petscdmplex.h>
6: #include <petscdmfield.h>
7: #include <petscsf.h>
8: #include <petscds.h>
10: #if defined(PETSC_HAVE_VALGRIND)
11: # include <valgrind/memcheck.h>
12: #endif
14: PetscClassId DM_CLASSID;
15: PetscClassId DMLABEL_CLASSID;
16: PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal, DM_LocatePoints, DM_Coarsen, DM_Refine, DM_CreateInterpolation, DM_CreateRestriction, DM_CreateInjection, DM_CreateMatrix, DM_Load, DM_AdaptInterpolator;
18: const char *const DMBoundaryTypes[] = {"NONE","GHOSTED","MIRROR","PERIODIC","TWIST","DMBoundaryType","DM_BOUNDARY_", NULL};
19: const char *const DMBoundaryConditionTypes[] = {"INVALID","ESSENTIAL","NATURAL","INVALID","INVALID","ESSENTIAL_FIELD","NATURAL_FIELD","INVALID","INVALID","INVALID","NATURAL_RIEMANN","DMBoundaryConditionType","DM_BC_", NULL};
20: const char *const DMPolytopeTypes[] = {"vertex", "segment", "tensor_segment", "triangle", "quadrilateral", "tensor_quad", "tetrahedron", "hexahedron", "triangular_prism", "tensor_triangular_prism", "tensor_quadrilateral_prism", "FV_ghost_cell", "interior_ghost_cell", "unknown", "invalid", "DMPolytopeType", "DM_POLYTOPE_", NULL};
21: /*@
22: DMCreate - Creates an empty DM object. The type can then be set with DMSetType().
24: If you never call DMSetType() it will generate an
25: error when you try to use the vector.
27: Collective
29: Input Parameter:
30: . comm - The communicator for the DM object
32: Output Parameter:
33: . dm - The DM object
35: Level: beginner
37: .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE, DMPLEX, DMMOAB, DMNETWORK
38: @*/
39: PetscErrorCode DMCreate(MPI_Comm comm,DM *dm)
40: {
41: DM v;
42: PetscDS ds;
47: *dm = NULL;
48: DMInitializePackage();
50: PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);
52: v->setupcalled = PETSC_FALSE;
53: v->setfromoptionscalled = PETSC_FALSE;
54: v->ltogmap = NULL;
55: v->bs = 1;
56: v->coloringtype = IS_COLORING_GLOBAL;
57: PetscSFCreate(comm, &v->sf);
58: PetscSFCreate(comm, &v->sectionSF);
59: v->labels = NULL;
60: v->adjacency[0] = PETSC_FALSE;
61: v->adjacency[1] = PETSC_TRUE;
62: v->depthLabel = NULL;
63: v->celltypeLabel = NULL;
64: v->localSection = NULL;
65: v->globalSection = NULL;
66: v->defaultConstraintSection = NULL;
67: v->defaultConstraintMat = NULL;
68: v->L = NULL;
69: v->maxCell = NULL;
70: v->bdtype = NULL;
71: v->dimEmbed = PETSC_DEFAULT;
72: v->dim = PETSC_DETERMINE;
73: {
74: PetscInt i;
75: for (i = 0; i < 10; ++i) {
76: v->nullspaceConstructors[i] = NULL;
77: v->nearnullspaceConstructors[i] = NULL;
78: }
79: }
80: PetscDSCreate(PetscObjectComm((PetscObject) v), &ds);
81: DMSetRegionDS(v, NULL, NULL, ds);
82: PetscDSDestroy(&ds);
83: v->dmBC = NULL;
84: v->coarseMesh = NULL;
85: v->outputSequenceNum = -1;
86: v->outputSequenceVal = 0.0;
87: DMSetVecType(v,VECSTANDARD);
88: DMSetMatType(v,MATAIJ);
90: *dm = v;
91: return(0);
92: }
94: /*@
95: DMClone - Creates a DM object with the same topology as the original.
97: Collective
99: Input Parameter:
100: . dm - The original DM object
102: Output Parameter:
103: . newdm - The new DM object
105: Level: beginner
107: Notes:
108: For some DM implementations this is a shallow clone, the result of which may share (referent counted) information with its parent. For example,
109: DMClone() applied to a DMPLEX object will result in a new DMPLEX that shares the topology with the original DMPLEX. It does not
110: share the PetscSection of the original DM.
112: The clone is considered set up iff the original is.
114: .seealso: DMDestroy(), DMCreate(), DMSetType(), DMSetLocalSection(), DMSetGlobalSection()
116: @*/
117: PetscErrorCode DMClone(DM dm, DM *newdm)
118: {
119: PetscSF sf;
120: Vec coords;
121: void *ctx;
122: PetscInt dim, cdim;
128: DMCreate(PetscObjectComm((PetscObject) dm), newdm);
129: DMCopyLabels(dm, *newdm, PETSC_COPY_VALUES, PETSC_TRUE);
130: (*newdm)->leveldown = dm->leveldown;
131: (*newdm)->levelup = dm->levelup;
132: DMGetDimension(dm, &dim);
133: DMSetDimension(*newdm, dim);
134: if (dm->ops->clone) {
135: (*dm->ops->clone)(dm, newdm);
136: }
137: (*newdm)->setupcalled = dm->setupcalled;
138: DMGetPointSF(dm, &sf);
139: DMSetPointSF(*newdm, sf);
140: DMGetApplicationContext(dm, &ctx);
141: DMSetApplicationContext(*newdm, ctx);
142: if (dm->coordinateDM) {
143: DM ncdm;
144: PetscSection cs;
145: PetscInt pEnd = -1, pEndMax = -1;
147: DMGetLocalSection(dm->coordinateDM, &cs);
148: if (cs) {PetscSectionGetChart(cs, NULL, &pEnd);}
149: MPI_Allreduce(&pEnd,&pEndMax,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));
150: if (pEndMax >= 0) {
151: DMClone(dm->coordinateDM, &ncdm);
152: DMCopyDisc(dm->coordinateDM, ncdm);
153: DMSetLocalSection(ncdm, cs);
154: DMSetCoordinateDM(*newdm, ncdm);
155: DMDestroy(&ncdm);
156: }
157: }
158: DMGetCoordinateDim(dm, &cdim);
159: DMSetCoordinateDim(*newdm, cdim);
160: DMGetCoordinatesLocal(dm, &coords);
161: if (coords) {
162: DMSetCoordinatesLocal(*newdm, coords);
163: } else {
164: DMGetCoordinates(dm, &coords);
165: if (coords) {DMSetCoordinates(*newdm, coords);}
166: }
167: {
168: PetscBool isper;
169: const PetscReal *maxCell, *L;
170: const DMBoundaryType *bd;
171: DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);
172: DMSetPeriodicity(*newdm, isper, maxCell, L, bd);
173: }
174: {
175: PetscBool useCone, useClosure;
177: DMGetAdjacency(dm, PETSC_DEFAULT, &useCone, &useClosure);
178: DMSetAdjacency(*newdm, PETSC_DEFAULT, useCone, useClosure);
179: }
180: return(0);
181: }
183: /*@C
184: DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()
186: Logically Collective on da
188: Input Parameter:
189: + da - initial distributed array
190: . ctype - the vector type, currently either VECSTANDARD, VECCUDA, or VECVIENNACL
192: Options Database:
193: . -dm_vec_type ctype
195: Level: intermediate
197: .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType, DMGetVecType(), DMSetMatType(), DMGetMatType()
198: @*/
199: PetscErrorCode DMSetVecType(DM da,VecType ctype)
200: {
205: PetscFree(da->vectype);
206: PetscStrallocpy(ctype,(char**)&da->vectype);
207: return(0);
208: }
210: /*@C
211: DMGetVecType - Gets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()
213: Logically Collective on da
215: Input Parameter:
216: . da - initial distributed array
218: Output Parameter:
219: . ctype - the vector type
221: Level: intermediate
223: .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType, DMSetMatType(), DMGetMatType(), DMSetVecType()
224: @*/
225: PetscErrorCode DMGetVecType(DM da,VecType *ctype)
226: {
229: *ctype = da->vectype;
230: return(0);
231: }
233: /*@
234: VecGetDM - Gets the DM defining the data layout of the vector
236: Not collective
238: Input Parameter:
239: . v - The Vec
241: Output Parameter:
242: . dm - The DM
244: Level: intermediate
246: .seealso: VecSetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType()
247: @*/
248: PetscErrorCode VecGetDM(Vec v, DM *dm)
249: {
255: PetscObjectQuery((PetscObject) v, "__PETSc_dm", (PetscObject*) dm);
256: return(0);
257: }
259: /*@
260: VecSetDM - Sets the DM defining the data layout of the vector.
262: Not collective
264: Input Parameters:
265: + v - The Vec
266: - dm - The DM
268: 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.
270: Level: intermediate
272: .seealso: VecGetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType()
273: @*/
274: PetscErrorCode VecSetDM(Vec v, DM dm)
275: {
281: PetscObjectCompose((PetscObject) v, "__PETSc_dm", (PetscObject) dm);
282: return(0);
283: }
285: /*@C
286: DMSetISColoringType - Sets the type of coloring, global or local, that is created by the DM
288: Logically Collective on dm
290: Input Parameters:
291: + dm - the DM context
292: - ctype - the matrix type
294: Options Database:
295: . -dm_is_coloring_type - global or local
297: Level: intermediate
299: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(),
300: DMGetISColoringType()
301: @*/
302: PetscErrorCode DMSetISColoringType(DM dm,ISColoringType ctype)
303: {
306: dm->coloringtype = ctype;
307: return(0);
308: }
310: /*@C
311: DMGetISColoringType - Gets the type of coloring, global or local, that is created by the DM
313: Logically Collective on dm
315: Input Parameter:
316: . dm - the DM context
318: Output Parameter:
319: . ctype - the matrix type
321: Options Database:
322: . -dm_is_coloring_type - global or local
324: Level: intermediate
326: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(),
327: DMGetISColoringType()
328: @*/
329: PetscErrorCode DMGetISColoringType(DM dm,ISColoringType *ctype)
330: {
333: *ctype = dm->coloringtype;
334: return(0);
335: }
337: /*@C
338: DMSetMatType - Sets the type of matrix created with DMCreateMatrix()
340: Logically Collective on dm
342: Input Parameters:
343: + dm - the DM context
344: - ctype - the matrix type
346: Options Database:
347: . -dm_mat_type ctype
349: Level: intermediate
351: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(), DMSetMatType(), DMGetMatType()
352: @*/
353: PetscErrorCode DMSetMatType(DM dm,MatType ctype)
354: {
359: PetscFree(dm->mattype);
360: PetscStrallocpy(ctype,(char**)&dm->mattype);
361: return(0);
362: }
364: /*@C
365: DMGetMatType - Gets the type of matrix created with DMCreateMatrix()
367: Logically Collective on dm
369: Input Parameter:
370: . dm - the DM context
372: Output Parameter:
373: . ctype - the matrix type
375: Options Database:
376: . -dm_mat_type ctype
378: Level: intermediate
380: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMSetMatType(), DMSetMatType(), DMGetMatType()
381: @*/
382: PetscErrorCode DMGetMatType(DM dm,MatType *ctype)
383: {
386: *ctype = dm->mattype;
387: return(0);
388: }
390: /*@
391: MatGetDM - Gets the DM defining the data layout of the matrix
393: Not collective
395: Input Parameter:
396: . A - The Mat
398: Output Parameter:
399: . dm - The DM
401: Level: intermediate
403: Developer Note: Since the Mat class doesn't know about the DM class the DM object is associated with
404: the Mat through a PetscObjectCompose() operation
406: .seealso: MatSetDM(), DMCreateMatrix(), DMSetMatType()
407: @*/
408: PetscErrorCode MatGetDM(Mat A, DM *dm)
409: {
415: PetscObjectQuery((PetscObject) A, "__PETSc_dm", (PetscObject*) dm);
416: return(0);
417: }
419: /*@
420: MatSetDM - Sets the DM defining the data layout of the matrix
422: Not collective
424: Input Parameters:
425: + A - The Mat
426: - dm - The DM
428: Level: intermediate
430: Developer Note: Since the Mat class doesn't know about the DM class the DM object is associated with
431: the Mat through a PetscObjectCompose() operation
434: .seealso: MatGetDM(), DMCreateMatrix(), DMSetMatType()
435: @*/
436: PetscErrorCode MatSetDM(Mat A, DM dm)
437: {
443: PetscObjectCompose((PetscObject) A, "__PETSc_dm", (PetscObject) dm);
444: return(0);
445: }
447: /*@C
448: DMSetOptionsPrefix - Sets the prefix used for searching for all
449: DM options in the database.
451: Logically Collective on dm
453: Input Parameter:
454: + da - the DM context
455: - prefix - the prefix to prepend to all option names
457: Notes:
458: A hyphen (-) must NOT be given at the beginning of the prefix name.
459: The first character of all runtime options is AUTOMATICALLY the hyphen.
461: Level: advanced
463: .seealso: DMSetFromOptions()
464: @*/
465: PetscErrorCode DMSetOptionsPrefix(DM dm,const char prefix[])
466: {
471: PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);
472: if (dm->sf) {
473: PetscObjectSetOptionsPrefix((PetscObject)dm->sf,prefix);
474: }
475: if (dm->sectionSF) {
476: PetscObjectSetOptionsPrefix((PetscObject)dm->sectionSF,prefix);
477: }
478: return(0);
479: }
481: /*@C
482: DMAppendOptionsPrefix - Appends to the prefix used for searching for all
483: DM options in the database.
485: Logically Collective on dm
487: Input Parameters:
488: + dm - the DM context
489: - prefix - the prefix string to prepend to all DM option requests
491: Notes:
492: A hyphen (-) must NOT be given at the beginning of the prefix name.
493: The first character of all runtime options is AUTOMATICALLY the hyphen.
495: Level: advanced
497: .seealso: DMSetOptionsPrefix(), DMGetOptionsPrefix()
498: @*/
499: PetscErrorCode DMAppendOptionsPrefix(DM dm,const char prefix[])
500: {
505: PetscObjectAppendOptionsPrefix((PetscObject)dm,prefix);
506: return(0);
507: }
509: /*@C
510: DMGetOptionsPrefix - Gets the prefix used for searching for all
511: DM options in the database.
513: Not Collective
515: Input Parameters:
516: . dm - the DM context
518: Output Parameters:
519: . prefix - pointer to the prefix string used is returned
521: Notes:
522: On the fortran side, the user should pass in a string 'prefix' of
523: sufficient length to hold the prefix.
525: Level: advanced
527: .seealso: DMSetOptionsPrefix(), DMAppendOptionsPrefix()
528: @*/
529: PetscErrorCode DMGetOptionsPrefix(DM dm,const char *prefix[])
530: {
535: PetscObjectGetOptionsPrefix((PetscObject)dm,prefix);
536: return(0);
537: }
539: static PetscErrorCode DMCountNonCyclicReferences(DM dm, PetscBool recurseCoarse, PetscBool recurseFine, PetscInt *ncrefct)
540: {
541: PetscInt refct = ((PetscObject) dm)->refct;
545: *ncrefct = 0;
546: if (dm->coarseMesh && dm->coarseMesh->fineMesh == dm) {
547: refct--;
548: if (recurseCoarse) {
549: PetscInt coarseCount;
551: DMCountNonCyclicReferences(dm->coarseMesh, PETSC_TRUE, PETSC_FALSE,&coarseCount);
552: refct += coarseCount;
553: }
554: }
555: if (dm->fineMesh && dm->fineMesh->coarseMesh == dm) {
556: refct--;
557: if (recurseFine) {
558: PetscInt fineCount;
560: DMCountNonCyclicReferences(dm->fineMesh, PETSC_FALSE, PETSC_TRUE,&fineCount);
561: refct += fineCount;
562: }
563: }
564: *ncrefct = refct;
565: return(0);
566: }
568: PetscErrorCode DMDestroyLabelLinkList_Internal(DM dm)
569: {
570: DMLabelLink next = dm->labels;
574: /* destroy the labels */
575: while (next) {
576: DMLabelLink tmp = next->next;
578: if (next->label == dm->depthLabel) dm->depthLabel = NULL;
579: if (next->label == dm->celltypeLabel) dm->celltypeLabel = NULL;
580: DMLabelDestroy(&next->label);
581: PetscFree(next);
582: next = tmp;
583: }
584: dm->labels = NULL;
585: return(0);
586: }
588: /*@
589: DMDestroy - Destroys a vector packer or DM.
591: Collective on dm
593: Input Parameter:
594: . dm - the DM object to destroy
596: Level: developer
598: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
600: @*/
601: PetscErrorCode DMDestroy(DM *dm)
602: {
603: PetscInt cnt;
604: DMNamedVecLink nlink,nnext;
608: if (!*dm) return(0);
611: /* count all non-cyclic references in the doubly-linked list of coarse<->fine meshes */
612: DMCountNonCyclicReferences(*dm,PETSC_TRUE,PETSC_TRUE,&cnt);
613: --((PetscObject)(*dm))->refct;
614: if (--cnt > 0) {*dm = NULL; return(0);}
615: if (((PetscObject)(*dm))->refct < 0) return(0);
616: ((PetscObject)(*dm))->refct = 0;
618: DMClearGlobalVectors(*dm);
619: DMClearLocalVectors(*dm);
621: nnext=(*dm)->namedglobal;
622: (*dm)->namedglobal = NULL;
623: for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named vectors */
624: nnext = nlink->next;
625: if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name);
626: PetscFree(nlink->name);
627: VecDestroy(&nlink->X);
628: PetscFree(nlink);
629: }
630: nnext=(*dm)->namedlocal;
631: (*dm)->namedlocal = NULL;
632: for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named local vectors */
633: nnext = nlink->next;
634: if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name);
635: PetscFree(nlink->name);
636: VecDestroy(&nlink->X);
637: PetscFree(nlink);
638: }
640: /* Destroy the list of hooks */
641: {
642: DMCoarsenHookLink link,next;
643: for (link=(*dm)->coarsenhook; link; link=next) {
644: next = link->next;
645: PetscFree(link);
646: }
647: (*dm)->coarsenhook = NULL;
648: }
649: {
650: DMRefineHookLink link,next;
651: for (link=(*dm)->refinehook; link; link=next) {
652: next = link->next;
653: PetscFree(link);
654: }
655: (*dm)->refinehook = NULL;
656: }
657: {
658: DMSubDomainHookLink link,next;
659: for (link=(*dm)->subdomainhook; link; link=next) {
660: next = link->next;
661: PetscFree(link);
662: }
663: (*dm)->subdomainhook = NULL;
664: }
665: {
666: DMGlobalToLocalHookLink link,next;
667: for (link=(*dm)->gtolhook; link; link=next) {
668: next = link->next;
669: PetscFree(link);
670: }
671: (*dm)->gtolhook = NULL;
672: }
673: {
674: DMLocalToGlobalHookLink link,next;
675: for (link=(*dm)->ltoghook; link; link=next) {
676: next = link->next;
677: PetscFree(link);
678: }
679: (*dm)->ltoghook = NULL;
680: }
681: /* Destroy the work arrays */
682: {
683: DMWorkLink link,next;
684: if ((*dm)->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out");
685: for (link=(*dm)->workin; link; link=next) {
686: next = link->next;
687: PetscFree(link->mem);
688: PetscFree(link);
689: }
690: (*dm)->workin = NULL;
691: }
692: /* destroy the labels */
693: DMDestroyLabelLinkList_Internal(*dm);
694: /* destroy the fields */
695: DMClearFields(*dm);
696: /* destroy the boundaries */
697: {
698: DMBoundary next = (*dm)->boundary;
699: while (next) {
700: DMBoundary b = next;
702: next = b->next;
703: PetscFree(b);
704: }
705: }
707: PetscObjectDestroy(&(*dm)->dmksp);
708: PetscObjectDestroy(&(*dm)->dmsnes);
709: PetscObjectDestroy(&(*dm)->dmts);
711: if ((*dm)->ctx && (*dm)->ctxdestroy) {
712: (*(*dm)->ctxdestroy)(&(*dm)->ctx);
713: }
714: MatFDColoringDestroy(&(*dm)->fd);
715: ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);
716: PetscFree((*dm)->vectype);
717: PetscFree((*dm)->mattype);
719: PetscSectionDestroy(&(*dm)->localSection);
720: PetscSectionDestroy(&(*dm)->globalSection);
721: PetscLayoutDestroy(&(*dm)->map);
722: PetscSectionDestroy(&(*dm)->defaultConstraintSection);
723: MatDestroy(&(*dm)->defaultConstraintMat);
724: PetscSFDestroy(&(*dm)->sf);
725: PetscSFDestroy(&(*dm)->sectionSF);
726: if ((*dm)->useNatural) {
727: if ((*dm)->sfNatural) {
728: PetscSFDestroy(&(*dm)->sfNatural);
729: }
730: PetscObjectDereference((PetscObject) (*dm)->sfMigration);
731: }
732: if ((*dm)->coarseMesh && (*dm)->coarseMesh->fineMesh == *dm) {
733: DMSetFineDM((*dm)->coarseMesh,NULL);
734: }
736: DMDestroy(&(*dm)->coarseMesh);
737: if ((*dm)->fineMesh && (*dm)->fineMesh->coarseMesh == *dm) {
738: DMSetCoarseDM((*dm)->fineMesh,NULL);
739: }
740: DMDestroy(&(*dm)->fineMesh);
741: DMFieldDestroy(&(*dm)->coordinateField);
742: DMDestroy(&(*dm)->coordinateDM);
743: VecDestroy(&(*dm)->coordinates);
744: VecDestroy(&(*dm)->coordinatesLocal);
745: PetscFree((*dm)->L);
746: PetscFree((*dm)->maxCell);
747: PetscFree((*dm)->bdtype);
748: if ((*dm)->transformDestroy) {(*(*dm)->transformDestroy)(*dm, (*dm)->transformCtx);}
749: DMDestroy(&(*dm)->transformDM);
750: VecDestroy(&(*dm)->transform);
752: DMClearDS(*dm);
753: DMDestroy(&(*dm)->dmBC);
754: /* if memory was published with SAWs then destroy it */
755: PetscObjectSAWsViewOff((PetscObject)*dm);
757: if ((*dm)->ops->destroy) {
758: (*(*dm)->ops->destroy)(*dm);
759: }
760: DMMonitorCancel(*dm);
761: /* We do not destroy (*dm)->data here so that we can reference count backend objects */
762: PetscHeaderDestroy(dm);
763: return(0);
764: }
766: /*@
767: DMSetUp - sets up the data structures inside a DM object
769: Collective on dm
771: Input Parameter:
772: . dm - the DM object to setup
774: Level: developer
776: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
778: @*/
779: PetscErrorCode DMSetUp(DM dm)
780: {
785: if (dm->setupcalled) return(0);
786: if (dm->ops->setup) {
787: (*dm->ops->setup)(dm);
788: }
789: dm->setupcalled = PETSC_TRUE;
790: return(0);
791: }
793: /*@
794: DMSetFromOptions - sets parameters in a DM from the options database
796: Collective on dm
798: Input Parameter:
799: . dm - the DM object to set options for
801: Options Database:
802: + -dm_preallocate_only - Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros
803: . -dm_vec_type <type> - type of vector to create inside DM
804: . -dm_mat_type <type> - type of matrix to create inside DM
805: - -dm_is_coloring_type - <global or local>
807: DMPLEX Specific Checks
808: + -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric - DMPlexCheckSymmetry()
809: . -dm_plex_check_skeleton - Check that each cell has the correct number of vertices (only for homogeneous simplex or tensor meshes) - DMPlexCheckSkeleton()
810: . -dm_plex_check_faces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type - DMPlexCheckFaces()
811: . -dm_plex_check_geometry - Check that cells have positive volume - DMPlexCheckGeometry()
812: . -dm_plex_check_pointsf - Check some necessary conditions for PointSF - DMPlexCheckPointSF()
813: . -dm_plex_check_interface_cones - Check points on inter-partition interfaces have conforming order of cone points - DMPlexCheckInterfaceCones()
814: - -dm_plex_check_all - Perform all the checks above
816: Level: intermediate
818: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(),
819: DMPlexCheckSymmetry(), DMPlexCheckSkeleton(), DMPlexCheckFaces(), DMPlexCheckGeometry(), DMPlexCheckPointSF(), DMPlexCheckInterfaceCones()
821: @*/
822: PetscErrorCode DMSetFromOptions(DM dm)
823: {
824: char typeName[256];
825: PetscBool flg;
830: dm->setfromoptionscalled = PETSC_TRUE;
831: if (dm->sf) {PetscSFSetFromOptions(dm->sf);}
832: if (dm->sectionSF) {PetscSFSetFromOptions(dm->sectionSF);}
833: PetscObjectOptionsBegin((PetscObject)dm);
834: PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,NULL);
835: PetscOptionsFList("-dm_vec_type","Vector type used for created vectors","DMSetVecType",VecList,dm->vectype,typeName,256,&flg);
836: if (flg) {
837: DMSetVecType(dm,typeName);
838: }
839: PetscOptionsFList("-dm_mat_type","Matrix type used for created matrices","DMSetMatType",MatList,dm->mattype ? dm->mattype : typeName,typeName,sizeof(typeName),&flg);
840: if (flg) {
841: DMSetMatType(dm,typeName);
842: }
843: PetscOptionsEnum("-dm_is_coloring_type","Global or local coloring of Jacobian","DMSetISColoringType",ISColoringTypes,(PetscEnum)dm->coloringtype,(PetscEnum*)&dm->coloringtype,NULL);
844: if (dm->ops->setfromoptions) {
845: (*dm->ops->setfromoptions)(PetscOptionsObject,dm);
846: }
847: /* process any options handlers added with PetscObjectAddOptionsHandler() */
848: PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) dm);
849: PetscOptionsEnd();
850: return(0);
851: }
853: /*@C
854: DMViewFromOptions - View from Options
856: Collective on DM
858: Input Parameters:
859: + dm - the DM object
860: . obj - Optional object
861: - name - command line option
863: Level: intermediate
864: .seealso: DM, DMView, PetscObjectViewFromOptions(), DMCreate()
865: @*/
866: PetscErrorCode DMViewFromOptions(DM dm,PetscObject obj,const char name[])
867: {
872: PetscObjectViewFromOptions((PetscObject)dm,obj,name);
873: return(0);
874: }
876: /*@C
877: DMView - Views a DM
879: Collective on dm
881: Input Parameter:
882: + dm - the DM object to view
883: - v - the viewer
885: Level: beginner
887: .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
889: @*/
890: PetscErrorCode DMView(DM dm,PetscViewer v)
891: {
892: PetscErrorCode ierr;
893: PetscBool isbinary;
894: PetscMPIInt size;
895: PetscViewerFormat format;
899: if (!v) {
900: PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm),&v);
901: }
903: /* Ideally, we would like to have this test on.
904: However, it currently breaks socket viz via GLVis.
905: During DMView(parallel_mesh,glvis_viewer), each
906: process opens a sequential ASCII socket to visualize
907: the local mesh, and PetscObjectView(dm,local_socket)
908: is internally called inside VecView_GLVis, incurring
909: in an error here */
911: PetscViewerCheckWritable(v);
913: PetscViewerGetFormat(v,&format);
914: MPI_Comm_size(PetscObjectComm((PetscObject)dm),&size);
915: if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) return(0);
916: PetscObjectPrintClassNamePrefixType((PetscObject)dm,v);
917: PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERBINARY,&isbinary);
918: if (isbinary) {
919: PetscInt classid = DM_FILE_CLASSID;
920: char type[256];
922: PetscViewerBinaryWrite(v,&classid,1,PETSC_INT);
923: PetscStrncpy(type,((PetscObject)dm)->type_name,256);
924: PetscViewerBinaryWrite(v,type,256,PETSC_CHAR);
925: }
926: if (dm->ops->view) {
927: (*dm->ops->view)(dm,v);
928: }
929: return(0);
930: }
932: /*@
933: DMCreateGlobalVector - Creates a global vector from a DM object
935: Collective on dm
937: Input Parameter:
938: . dm - the DM object
940: Output Parameter:
941: . vec - the global vector
943: Level: beginner
945: .seealso DMCreateLocalVector(), DMGetGlobalVector(), DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
947: @*/
948: PetscErrorCode DMCreateGlobalVector(DM dm,Vec *vec)
949: {
955: if (!dm->ops->createglobalvector) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateGlobalVector",((PetscObject)dm)->type_name);
956: (*dm->ops->createglobalvector)(dm,vec);
957: if (PetscDefined(USE_DEBUG)) {
958: DM vdm;
960: VecGetDM(*vec,&vdm);
961: if (!vdm) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"DM type '%s' did not attach the DM to the vector\n",((PetscObject)dm)->type_name);
962: }
963: return(0);
964: }
966: /*@
967: DMCreateLocalVector - Creates a local vector from a DM object
969: Not Collective
971: Input Parameter:
972: . dm - the DM object
974: Output Parameter:
975: . vec - the local vector
977: Level: beginner
979: .seealso DMCreateGlobalVector(), DMGetLocalVector(), DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
981: @*/
982: PetscErrorCode DMCreateLocalVector(DM dm,Vec *vec)
983: {
989: if (!dm->ops->createlocalvector) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateLocalVector",((PetscObject)dm)->type_name);
990: (*dm->ops->createlocalvector)(dm,vec);
991: if (PetscDefined(USE_DEBUG)) {
992: DM vdm;
994: VecGetDM(*vec,&vdm);
995: if (!vdm) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"DM type '%s' did not attach the DM to the vector\n",((PetscObject)dm)->type_name);
996: }
997: return(0);
998: }
1000: /*@
1001: DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM.
1003: Collective on dm
1005: Input Parameter:
1006: . dm - the DM that provides the mapping
1008: Output Parameter:
1009: . ltog - the mapping
1011: Level: intermediate
1013: Notes:
1014: This mapping can then be used by VecSetLocalToGlobalMapping() or
1015: MatSetLocalToGlobalMapping().
1017: .seealso: DMCreateLocalVector()
1018: @*/
1019: PetscErrorCode DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog)
1020: {
1021: PetscInt bs = -1, bsLocal[2], bsMinMax[2];
1027: if (!dm->ltogmap) {
1028: PetscSection section, sectionGlobal;
1030: DMGetLocalSection(dm, §ion);
1031: if (section) {
1032: const PetscInt *cdofs;
1033: PetscInt *ltog;
1034: PetscInt pStart, pEnd, n, p, k, l;
1036: DMGetGlobalSection(dm, §ionGlobal);
1037: PetscSectionGetChart(section, &pStart, &pEnd);
1038: PetscSectionGetStorageSize(section, &n);
1039: PetscMalloc1(n, <og); /* We want the local+overlap size */
1040: for (p = pStart, l = 0; p < pEnd; ++p) {
1041: PetscInt bdof, cdof, dof, off, c, cind = 0;
1043: /* Should probably use constrained dofs */
1044: PetscSectionGetDof(section, p, &dof);
1045: PetscSectionGetConstraintDof(section, p, &cdof);
1046: PetscSectionGetConstraintIndices(section, p, &cdofs);
1047: PetscSectionGetOffset(sectionGlobal, p, &off);
1048: /* If you have dofs, and constraints, and they are unequal, we set the blocksize to 1 */
1049: bdof = cdof && (dof-cdof) ? 1 : dof;
1050: if (dof) {
1051: if (bs < 0) {bs = bdof;}
1052: else if (bs != bdof) {bs = 1;}
1053: }
1054: for (c = 0; c < dof; ++c, ++l) {
1055: if ((cind < cdof) && (c == cdofs[cind])) ltog[l] = off < 0 ? off-c : off+c;
1056: else ltog[l] = (off < 0 ? -(off+1) : off) + c;
1057: }
1058: }
1059: /* Must have same blocksize on all procs (some might have no points) */
1060: bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs;
1061: PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);
1062: if (bsMinMax[0] != bsMinMax[1]) {bs = 1;}
1063: else {bs = bsMinMax[0];}
1064: bs = bs < 0 ? 1 : bs;
1065: /* Must reduce indices by blocksize */
1066: if (bs > 1) {
1067: for (l = 0, k = 0; l < n; l += bs, ++k) ltog[k] = ltog[l]/bs;
1068: n /= bs;
1069: }
1070: ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, n, ltog, PETSC_OWN_POINTER, &dm->ltogmap);
1071: PetscLogObjectParent((PetscObject)dm, (PetscObject)dm->ltogmap);
1072: } else {
1073: if (!dm->ops->getlocaltoglobalmapping) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetLocalToGlobalMapping",((PetscObject)dm)->type_name);
1074: (*dm->ops->getlocaltoglobalmapping)(dm);
1075: }
1076: }
1077: *ltog = dm->ltogmap;
1078: return(0);
1079: }
1081: /*@
1082: DMGetBlockSize - Gets the inherent block size associated with a DM
1084: Not Collective
1086: Input Parameter:
1087: . dm - the DM with block structure
1089: Output Parameter:
1090: . bs - the block size, 1 implies no exploitable block structure
1092: Level: intermediate
1094: .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMapping()
1095: @*/
1096: PetscErrorCode DMGetBlockSize(DM dm,PetscInt *bs)
1097: {
1101: if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet");
1102: *bs = dm->bs;
1103: return(0);
1104: }
1106: /*@C
1107: DMCreateInterpolation - Gets interpolation matrix between two DM objects
1109: Collective on dmc
1111: Input Parameter:
1112: + dmc - the DM object
1113: - dmf - the second, finer DM object
1115: Output Parameter:
1116: + mat - the interpolation
1117: - vec - the scaling (optional)
1119: Level: developer
1121: Notes:
1122: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
1123: DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation.
1125: For DMDA objects you can use this interpolation (more precisely the interpolation from the DMGetCoordinateDM()) to interpolate the mesh coordinate vectors
1126: EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic.
1129: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateRestriction(), DMCreateInterpolationScale()
1131: @*/
1132: PetscErrorCode DMCreateInterpolation(DM dmc,DM dmf,Mat *mat,Vec *vec)
1133: {
1140: if (!dmc->ops->createinterpolation) SETERRQ1(PetscObjectComm((PetscObject)dmc),PETSC_ERR_SUP,"DM type %s does not implement DMCreateInterpolation",((PetscObject)dmc)->type_name);
1141: PetscLogEventBegin(DM_CreateInterpolation,dmc,dmf,0,0);
1142: (*dmc->ops->createinterpolation)(dmc,dmf,mat,vec);
1143: PetscLogEventEnd(DM_CreateInterpolation,dmc,dmf,0,0);
1144: return(0);
1145: }
1147: /*@
1148: DMCreateInterpolationScale - Forms L = 1/(R*1) such that diag(L)*R preserves scale and is thus suitable for state (versus residual) restriction.
1150: Input Parameters:
1151: + dac - DM that defines a coarse mesh
1152: . daf - DM that defines a fine mesh
1153: - mat - the restriction (or interpolation operator) from fine to coarse
1155: Output Parameter:
1156: . scale - the scaled vector
1158: Level: developer
1160: .seealso: DMCreateInterpolation()
1162: @*/
1163: PetscErrorCode DMCreateInterpolationScale(DM dac,DM daf,Mat mat,Vec *scale)
1164: {
1166: Vec fine;
1167: PetscScalar one = 1.0;
1170: DMCreateGlobalVector(daf,&fine);
1171: DMCreateGlobalVector(dac,scale);
1172: VecSet(fine,one);
1173: MatRestrict(mat,fine,*scale);
1174: VecDestroy(&fine);
1175: VecReciprocal(*scale);
1176: return(0);
1177: }
1179: /*@
1180: DMCreateRestriction - Gets restriction matrix between two DM objects
1182: Collective on dmc
1184: Input Parameter:
1185: + dmc - the DM object
1186: - dmf - the second, finer DM object
1188: Output Parameter:
1189: . mat - the restriction
1192: Level: developer
1194: Notes:
1195: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
1196: DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation.
1199: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateInterpolation()
1201: @*/
1202: PetscErrorCode DMCreateRestriction(DM dmc,DM dmf,Mat *mat)
1203: {
1210: if (!dmc->ops->createrestriction) SETERRQ1(PetscObjectComm((PetscObject)dmc),PETSC_ERR_SUP,"DM type %s does not implement DMCreateRestriction",((PetscObject)dmc)->type_name);
1211: PetscLogEventBegin(DM_CreateRestriction,dmc,dmf,0,0);
1212: (*dmc->ops->createrestriction)(dmc,dmf,mat);
1213: PetscLogEventEnd(DM_CreateRestriction,dmc,dmf,0,0);
1214: return(0);
1215: }
1217: /*@
1218: DMCreateInjection - Gets injection matrix between two DM objects
1220: Collective on dac
1222: Input Parameter:
1223: + dac - the DM object
1224: - daf - the second, finer DM object
1226: Output Parameter:
1227: . mat - the injection
1229: Level: developer
1231: Notes:
1232: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
1233: DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection.
1235: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMCreateInterpolation()
1237: @*/
1238: PetscErrorCode DMCreateInjection(DM dac,DM daf,Mat *mat)
1239: {
1246: if (!dac->ops->createinjection) SETERRQ1(PetscObjectComm((PetscObject)dac),PETSC_ERR_SUP,"DM type %s does not implement DMCreateInjection",((PetscObject)dac)->type_name);
1247: PetscLogEventBegin(DM_CreateInjection,dac,daf,0,0);
1248: (*dac->ops->createinjection)(dac,daf,mat);
1249: PetscLogEventEnd(DM_CreateInjection,dac,daf,0,0);
1250: return(0);
1251: }
1253: /*@
1254: DMCreateMassMatrix - Gets mass matrix between two DM objects, M_ij = \int \phi_i \psi_j
1256: Collective on dac
1258: Input Parameter:
1259: + dac - the DM object
1260: - daf - the second, finer DM object
1262: Output Parameter:
1263: . mat - the interpolation
1265: Level: developer
1267: .seealso DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateRestriction(), DMCreateInterpolation(), DMCreateInjection()
1268: @*/
1269: PetscErrorCode DMCreateMassMatrix(DM dac, DM daf, Mat *mat)
1270: {
1277: if (!dac->ops->createmassmatrix) SETERRQ1(PetscObjectComm((PetscObject)dac),PETSC_ERR_SUP,"DM type %s does not implement DMCreateMassMatrix",((PetscObject)dac)->type_name);
1278: (*dac->ops->createmassmatrix)(dac, daf, mat);
1279: return(0);
1280: }
1282: /*@
1283: DMCreateColoring - Gets coloring for a DM
1285: Collective on dm
1287: Input Parameter:
1288: + dm - the DM object
1289: - ctype - IS_COLORING_LOCAL or IS_COLORING_GLOBAL
1291: Output Parameter:
1292: . coloring - the coloring
1294: Notes:
1295: Coloring of matrices can be computed directly from the sparse matrix nonzero structure via the MatColoring object or from the mesh from which the
1296: matrix comes from. In general using the mesh produces a more optimal coloring (fewer colors).
1298: This produces a coloring with the distance of 2, see MatSetColoringDistance() which can be used for efficiently computing Jacobians with MatFDColoringCreate()
1300: Level: developer
1302: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateMatrix(), DMSetMatType(), MatColoring, MatFDColoringCreate()
1304: @*/
1305: PetscErrorCode DMCreateColoring(DM dm,ISColoringType ctype,ISColoring *coloring)
1306: {
1312: if (!dm->ops->getcoloring) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateColoring",((PetscObject)dm)->type_name);
1313: (*dm->ops->getcoloring)(dm,ctype,coloring);
1314: return(0);
1315: }
1317: /*@
1318: DMCreateMatrix - Gets empty Jacobian for a DM
1320: Collective on dm
1322: Input Parameter:
1323: . dm - the DM object
1325: Output Parameter:
1326: . mat - the empty Jacobian
1328: Level: beginner
1330: Notes:
1331: This properly preallocates the number of nonzeros in the sparse matrix so you
1332: do not need to do it yourself.
1334: By default it also sets the nonzero structure and puts in the zero entries. To prevent setting
1335: the nonzero pattern call DMSetMatrixPreallocateOnly()
1337: For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used
1338: internally by PETSc.
1340: For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires
1341: the indices for the global numbering for DMDAs which is complicated.
1343: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMSetMatType()
1345: @*/
1346: PetscErrorCode DMCreateMatrix(DM dm,Mat *mat)
1347: {
1353: if (!dm->ops->creatematrix) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateMatrix",((PetscObject)dm)->type_name);
1354: MatInitializePackage();
1355: PetscLogEventBegin(DM_CreateMatrix,0,0,0,0);
1356: (*dm->ops->creatematrix)(dm,mat);
1357: if (PetscDefined(USE_DEBUG)) {
1358: DM mdm;
1360: MatGetDM(*mat,&mdm);
1361: if (!mdm) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"DM type '%s' did not attach the DM to the matrix\n",((PetscObject)dm)->type_name);
1362: }
1363: /* Handle nullspace and near nullspace */
1364: if (dm->Nf) {
1365: MatNullSpace nullSpace;
1366: PetscInt Nf;
1368: DMGetNumFields(dm, &Nf);
1369: if (Nf == 1) {
1370: if (dm->nullspaceConstructors[0]) {
1371: (*dm->nullspaceConstructors[0])(dm, 0, 0, &nullSpace);
1372: MatSetNullSpace(*mat, nullSpace);
1373: MatNullSpaceDestroy(&nullSpace);
1374: }
1375: if (dm->nearnullspaceConstructors[0]) {
1376: (*dm->nearnullspaceConstructors[0])(dm, 0, 0, &nullSpace);
1377: MatSetNearNullSpace(*mat, nullSpace);
1378: MatNullSpaceDestroy(&nullSpace);
1379: }
1380: }
1381: }
1382: PetscLogEventEnd(DM_CreateMatrix,0,0,0,0);
1383: return(0);
1384: }
1386: /*@
1387: DMSetMatrixPreallocateOnly - When DMCreateMatrix() is called the matrix will be properly
1388: preallocated but the nonzero structure and zero values will not be set.
1390: Logically Collective on dm
1392: Input Parameter:
1393: + dm - the DM
1394: - only - PETSC_TRUE if only want preallocation
1396: Level: developer
1397: .seealso DMCreateMatrix(), DMSetMatrixStructureOnly()
1398: @*/
1399: PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only)
1400: {
1403: dm->prealloc_only = only;
1404: return(0);
1405: }
1407: /*@
1408: DMSetMatrixStructureOnly - When DMCreateMatrix() is called, the matrix structure will be created
1409: but the array for values will not be allocated.
1411: Logically Collective on dm
1413: Input Parameter:
1414: + dm - the DM
1415: - only - PETSC_TRUE if only want matrix stucture
1417: Level: developer
1418: .seealso DMCreateMatrix(), DMSetMatrixPreallocateOnly()
1419: @*/
1420: PetscErrorCode DMSetMatrixStructureOnly(DM dm, PetscBool only)
1421: {
1424: dm->structure_only = only;
1425: return(0);
1426: }
1428: /*@C
1429: DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray()
1431: Not Collective
1433: Input Parameters:
1434: + dm - the DM object
1435: . count - The minium size
1436: - dtype - MPI data type, often MPIU_REAL, MPIU_SCALAR, MPIU_INT)
1438: Output Parameter:
1439: . array - the work array
1441: Level: developer
1443: .seealso DMDestroy(), DMCreate()
1444: @*/
1445: PetscErrorCode DMGetWorkArray(DM dm,PetscInt count,MPI_Datatype dtype,void *mem)
1446: {
1448: DMWorkLink link;
1449: PetscMPIInt dsize;
1454: if (dm->workin) {
1455: link = dm->workin;
1456: dm->workin = dm->workin->next;
1457: } else {
1458: PetscNewLog(dm,&link);
1459: }
1460: MPI_Type_size(dtype,&dsize);
1461: if (((size_t)dsize*count) > link->bytes) {
1462: PetscFree(link->mem);
1463: PetscMalloc(dsize*count,&link->mem);
1464: link->bytes = dsize*count;
1465: }
1466: link->next = dm->workout;
1467: dm->workout = link;
1468: #if defined(PETSC_HAVE_VALGRIND)
1469: VALGRIND_MAKE_MEM_NOACCESS((char*)link->mem + (size_t)dsize*count, link->bytes - (size_t)dsize*count);
1470: VALGRIND_MAKE_MEM_UNDEFINED(link->mem, (size_t)dsize*count);
1471: #endif
1472: *(void**)mem = link->mem;
1473: return(0);
1474: }
1476: /*@C
1477: DMRestoreWorkArray - Restores a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray()
1479: Not Collective
1481: Input Parameters:
1482: + dm - the DM object
1483: . count - The minium size
1484: - dtype - MPI data type, often MPIU_REAL, MPIU_SCALAR, MPIU_INT
1486: Output Parameter:
1487: . array - the work array
1489: Level: developer
1491: Developer Notes:
1492: count and dtype are ignored, they are only needed for DMGetWorkArray()
1493: .seealso DMDestroy(), DMCreate()
1494: @*/
1495: PetscErrorCode DMRestoreWorkArray(DM dm,PetscInt count,MPI_Datatype dtype,void *mem)
1496: {
1497: DMWorkLink *p,link;
1502: for (p=&dm->workout; (link=*p); p=&link->next) {
1503: if (link->mem == *(void**)mem) {
1504: *p = link->next;
1505: link->next = dm->workin;
1506: dm->workin = link;
1507: *(void**)mem = NULL;
1508: return(0);
1509: }
1510: }
1511: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out");
1512: }
1514: /*@C
1515: DMSetNullSpaceConstructor - Provide a callback function which constructs the nullspace for a given field
1517: Logically collective on DM
1519: Input Parameters:
1520: + dm - The DM
1521: . field - The field number for the nullspace
1522: - nullsp - A callback to create the nullspace
1524: Notes:
1525: The callback is intended to provide nullspaces when function spaces are joined or split, such as in DMCreateSubDM(). The calling sequence is
1526: $ PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)
1527: $ dm - The present DM
1528: $ origField - The field number given above, in the original DM
1529: $ field - The field number in dm
1530: $ nullSpace - The nullspace for the given field
1532: This function is currently not available from Fortran.
1534: .seealso: DMGetNullSpaceConstructor(), DMSetNearNullSpaceConstructor(), DMGetNearNullSpaceConstructor(), DMCreateSubDM(), DMCreateSuperDM()
1535: */
1536: PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1537: {
1540: if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field);
1541: dm->nullspaceConstructors[field] = nullsp;
1542: return(0);
1543: }
1545: /*@C
1546: DMGetNullSpaceConstructor - Return the callback function which constructs the nullspace for a given field, or NULL
1548: Not collective
1550: Input Parameters:
1551: + dm - The DM
1552: - field - The field number for the nullspace
1554: Output Parameter:
1555: . nullsp - A callback to create the nullspace
1557: Notes:
1558: The callback is intended to provide nullspaces when function spaces are joined or split, such as in DMCreateSubDM(). The calling sequence is
1559: $ PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)
1560: $ dm - The present DM
1561: $ origField - The field number given above, in the original DM
1562: $ field - The field number in dm
1563: $ nullSpace - The nullspace for the given field
1565: This function is currently not available from Fortran.
1567: .seealso: DMSetNullSpaceConstructor(), DMSetNearNullSpaceConstructor(), DMGetNearNullSpaceConstructor(), DMCreateSubDM(), DMCreateSuperDM()
1568: */
1569: PetscErrorCode DMGetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1570: {
1574: if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field);
1575: *nullsp = dm->nullspaceConstructors[field];
1576: return(0);
1577: }
1579: /*@C
1580: DMSetNearNullSpaceConstructor - Provide a callback function which constructs the near-nullspace for a given field
1582: Logically collective on DM
1584: Input Parameters:
1585: + dm - The DM
1586: . field - The field number for the nullspace
1587: - nullsp - A callback to create the near-nullspace
1589: Notes:
1590: The callback is intended to provide nullspaces when function spaces are joined or split, such as in DMCreateSubDM(). The calling sequence is
1591: $ PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)
1592: $ dm - The present DM
1593: $ origField - The field number given above, in the original DM
1594: $ field - The field number in dm
1595: $ nullSpace - The nullspace for the given field
1597: This function is currently not available from Fortran.
1599: .seealso: DMGetNearNullSpaceConstructor(), DMSetNullSpaceConstructor(), DMGetNullSpaceConstructor(), DMCreateSubDM(), DMCreateSuperDM()
1600: */
1601: PetscErrorCode DMSetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1602: {
1605: if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field);
1606: dm->nearnullspaceConstructors[field] = nullsp;
1607: return(0);
1608: }
1610: /*@C
1611: DMGetNearNullSpaceConstructor - Return the callback function which constructs the near-nullspace for a given field, or NULL
1613: Not collective
1615: Input Parameters:
1616: + dm - The DM
1617: - field - The field number for the nullspace
1619: Output Parameter:
1620: . nullsp - A callback to create the near-nullspace
1622: Notes:
1623: The callback is intended to provide nullspaces when function spaces are joined or split, such as in DMCreateSubDM(). The calling sequence is
1624: $ PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)
1625: $ dm - The present DM
1626: $ origField - The field number given above, in the original DM
1627: $ field - The field number in dm
1628: $ nullSpace - The nullspace for the given field
1630: This function is currently not available from Fortran.
1632: .seealso: DMSetNearNullSpaceConstructor(), DMSetNullSpaceConstructor(), DMGetNullSpaceConstructor(), DMCreateSubDM(), DMCreateSuperDM()
1633: */
1634: PetscErrorCode DMGetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1635: {
1639: if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field);
1640: *nullsp = dm->nearnullspaceConstructors[field];
1641: return(0);
1642: }
1644: /*@C
1645: DMCreateFieldIS - Creates a set of IS objects with the global indices of dofs for each field
1647: Not collective
1649: Input Parameter:
1650: . dm - the DM object
1652: Output Parameters:
1653: + numFields - The number of fields (or NULL if not requested)
1654: . fieldNames - The name for each field (or NULL if not requested)
1655: - fields - The global indices for each field (or NULL if not requested)
1657: Level: intermediate
1659: Notes:
1660: The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1661: PetscFree(), every entry of fields should be destroyed with ISDestroy(), and both arrays should be freed with
1662: PetscFree().
1664: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
1665: @*/
1666: PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields)
1667: {
1668: PetscSection section, sectionGlobal;
1673: if (numFields) {
1675: *numFields = 0;
1676: }
1677: if (fieldNames) {
1679: *fieldNames = NULL;
1680: }
1681: if (fields) {
1683: *fields = NULL;
1684: }
1685: DMGetLocalSection(dm, §ion);
1686: if (section) {
1687: PetscInt *fieldSizes, *fieldNc, **fieldIndices;
1688: PetscInt nF, f, pStart, pEnd, p;
1690: DMGetGlobalSection(dm, §ionGlobal);
1691: PetscSectionGetNumFields(section, &nF);
1692: PetscMalloc3(nF,&fieldSizes,nF,&fieldNc,nF,&fieldIndices);
1693: PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);
1694: for (f = 0; f < nF; ++f) {
1695: fieldSizes[f] = 0;
1696: PetscSectionGetFieldComponents(section, f, &fieldNc[f]);
1697: }
1698: for (p = pStart; p < pEnd; ++p) {
1699: PetscInt gdof;
1701: PetscSectionGetDof(sectionGlobal, p, &gdof);
1702: if (gdof > 0) {
1703: for (f = 0; f < nF; ++f) {
1704: PetscInt fdof, fcdof, fpdof;
1706: PetscSectionGetFieldDof(section, p, f, &fdof);
1707: PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);
1708: fpdof = fdof-fcdof;
1709: if (fpdof && fpdof != fieldNc[f]) {
1710: /* Layout does not admit a pointwise block size */
1711: fieldNc[f] = 1;
1712: }
1713: fieldSizes[f] += fpdof;
1714: }
1715: }
1716: }
1717: for (f = 0; f < nF; ++f) {
1718: PetscMalloc1(fieldSizes[f], &fieldIndices[f]);
1719: fieldSizes[f] = 0;
1720: }
1721: for (p = pStart; p < pEnd; ++p) {
1722: PetscInt gdof, goff;
1724: PetscSectionGetDof(sectionGlobal, p, &gdof);
1725: if (gdof > 0) {
1726: PetscSectionGetOffset(sectionGlobal, p, &goff);
1727: for (f = 0; f < nF; ++f) {
1728: PetscInt fdof, fcdof, fc;
1730: PetscSectionGetFieldDof(section, p, f, &fdof);
1731: PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);
1732: for (fc = 0; fc < fdof-fcdof; ++fc, ++fieldSizes[f]) {
1733: fieldIndices[f][fieldSizes[f]] = goff++;
1734: }
1735: }
1736: }
1737: }
1738: if (numFields) *numFields = nF;
1739: if (fieldNames) {
1740: PetscMalloc1(nF, fieldNames);
1741: for (f = 0; f < nF; ++f) {
1742: const char *fieldName;
1744: PetscSectionGetFieldName(section, f, &fieldName);
1745: PetscStrallocpy(fieldName, (char**) &(*fieldNames)[f]);
1746: }
1747: }
1748: if (fields) {
1749: PetscMalloc1(nF, fields);
1750: for (f = 0; f < nF; ++f) {
1751: PetscInt bs, in[2], out[2];
1753: ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]);
1754: in[0] = -fieldNc[f];
1755: in[1] = fieldNc[f];
1756: MPIU_Allreduce(in, out, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));
1757: bs = (-out[0] == out[1]) ? out[1] : 1;
1758: ISSetBlockSize((*fields)[f], bs);
1759: }
1760: }
1761: PetscFree3(fieldSizes,fieldNc,fieldIndices);
1762: } else if (dm->ops->createfieldis) {
1763: (*dm->ops->createfieldis)(dm, numFields, fieldNames, fields);
1764: }
1765: return(0);
1766: }
1769: /*@C
1770: DMCreateFieldDecomposition - Returns a list of IS objects defining a decomposition of a problem into subproblems
1771: corresponding to different fields: each IS contains the global indices of the dofs of the
1772: corresponding field. The optional list of DMs define the DM for each subproblem.
1773: Generalizes DMCreateFieldIS().
1775: Not collective
1777: Input Parameter:
1778: . dm - the DM object
1780: Output Parameters:
1781: + len - The number of subproblems in the field decomposition (or NULL if not requested)
1782: . namelist - The name for each field (or NULL if not requested)
1783: . islist - The global indices for each field (or NULL if not requested)
1784: - dmlist - The DMs for each field subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined)
1786: Level: intermediate
1788: Notes:
1789: The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1790: PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(),
1791: and all of the arrays should be freed with PetscFree().
1793: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1794: @*/
1795: PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
1796: {
1801: if (len) {
1803: *len = 0;
1804: }
1805: if (namelist) {
1807: *namelist = NULL;
1808: }
1809: if (islist) {
1811: *islist = NULL;
1812: }
1813: if (dmlist) {
1815: *dmlist = NULL;
1816: }
1817: /*
1818: Is it a good idea to apply the following check across all impls?
1819: Perhaps some impls can have a well-defined decomposition before DMSetUp?
1820: This, however, follows the general principle that accessors are not well-behaved until the object is set up.
1821: */
1822: if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
1823: if (!dm->ops->createfielddecomposition) {
1824: PetscSection section;
1825: PetscInt numFields, f;
1827: DMGetLocalSection(dm, §ion);
1828: if (section) {PetscSectionGetNumFields(section, &numFields);}
1829: if (section && numFields && dm->ops->createsubdm) {
1830: if (len) *len = numFields;
1831: if (namelist) {PetscMalloc1(numFields,namelist);}
1832: if (islist) {PetscMalloc1(numFields,islist);}
1833: if (dmlist) {PetscMalloc1(numFields,dmlist);}
1834: for (f = 0; f < numFields; ++f) {
1835: const char *fieldName;
1837: DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL);
1838: if (namelist) {
1839: PetscSectionGetFieldName(section, f, &fieldName);
1840: PetscStrallocpy(fieldName, (char**) &(*namelist)[f]);
1841: }
1842: }
1843: } else {
1844: DMCreateFieldIS(dm, len, namelist, islist);
1845: /* By default there are no DMs associated with subproblems. */
1846: if (dmlist) *dmlist = NULL;
1847: }
1848: } else {
1849: (*dm->ops->createfielddecomposition)(dm,len,namelist,islist,dmlist);
1850: }
1851: return(0);
1852: }
1854: /*@
1855: DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in.
1856: The fields are defined by DMCreateFieldIS().
1858: Not collective
1860: Input Parameters:
1861: + dm - The DM object
1862: . numFields - The number of fields in this subproblem
1863: - fields - The field numbers of the selected fields
1865: Output Parameters:
1866: + is - The global indices for the subproblem
1867: - subdm - The DM for the subproblem
1869: Note: You need to call DMPlexSetMigrationSF() on the original DM if you want the Global-To-Natural map to be automatically constructed
1871: Level: intermediate
1873: .seealso DMPlexSetMigrationSF(), DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1874: @*/
1875: PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
1876: {
1884: if (!dm->ops->createsubdm) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateSubDM",((PetscObject)dm)->type_name);
1885: (*dm->ops->createsubdm)(dm, numFields, fields, is, subdm);
1886: return(0);
1887: }
1889: /*@C
1890: DMCreateSuperDM - Returns an arrays of ISes and DM encapsulating a superproblem defined by the DMs passed in.
1892: Not collective
1894: Input Parameter:
1895: + dms - The DM objects
1896: - len - The number of DMs
1898: Output Parameters:
1899: + is - The global indices for the subproblem, or NULL
1900: - superdm - The DM for the superproblem
1902: Note: You need to call DMPlexSetMigrationSF() on the original DM if you want the Global-To-Natural map to be automatically constructed
1904: Level: intermediate
1906: .seealso DMPlexSetMigrationSF(), DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1907: @*/
1908: PetscErrorCode DMCreateSuperDM(DM dms[], PetscInt len, IS **is, DM *superdm)
1909: {
1910: PetscInt i;
1918: if (len < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of DMs must be nonnegative: %D", len);
1919: if (len) {
1920: DM dm = dms[0];
1921: if (!dm->ops->createsuperdm) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateSuperDM",((PetscObject)dm)->type_name);
1922: (*dm->ops->createsuperdm)(dms, len, is, superdm);
1923: }
1924: return(0);
1925: }
1928: /*@C
1929: DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems
1930: corresponding to restrictions to pairs nested subdomains: each IS contains the global
1931: indices of the dofs of the corresponding subdomains. The inner subdomains conceptually
1932: define a nonoverlapping covering, while outer subdomains can overlap.
1933: The optional list of DMs define the DM for each subproblem.
1935: Not collective
1937: Input Parameter:
1938: . dm - the DM object
1940: Output Parameters:
1941: + len - The number of subproblems in the domain decomposition (or NULL if not requested)
1942: . namelist - The name for each subdomain (or NULL if not requested)
1943: . innerislist - The global indices for each inner subdomain (or NULL, if not requested)
1944: . outerislist - The global indices for each outer subdomain (or NULL, if not requested)
1945: - dmlist - The DMs for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined)
1947: Level: intermediate
1949: Notes:
1950: The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1951: PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(),
1952: and all of the arrays should be freed with PetscFree().
1954: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldDecomposition()
1955: @*/
1956: PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist)
1957: {
1958: PetscErrorCode ierr;
1959: DMSubDomainHookLink link;
1960: PetscInt i,l;
1969: /*
1970: Is it a good idea to apply the following check across all impls?
1971: Perhaps some impls can have a well-defined decomposition before DMSetUp?
1972: This, however, follows the general principle that accessors are not well-behaved until the object is set up.
1973: */
1974: if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
1975: if (dm->ops->createdomaindecomposition) {
1976: (*dm->ops->createdomaindecomposition)(dm,&l,namelist,innerislist,outerislist,dmlist);
1977: /* copy subdomain hooks and context over to the subdomain DMs */
1978: if (dmlist && *dmlist) {
1979: for (i = 0; i < l; i++) {
1980: for (link=dm->subdomainhook; link; link=link->next) {
1981: if (link->ddhook) {(*link->ddhook)(dm,(*dmlist)[i],link->ctx);}
1982: }
1983: if (dm->ctx) (*dmlist)[i]->ctx = dm->ctx;
1984: }
1985: }
1986: if (len) *len = l;
1987: }
1988: return(0);
1989: }
1992: /*@C
1993: DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector
1995: Not collective
1997: Input Parameters:
1998: + dm - the DM object
1999: . n - the number of subdomain scatters
2000: - subdms - the local subdomains
2002: Output Parameters:
2003: + n - the number of scatters returned
2004: . iscat - scatter from global vector to nonoverlapping global vector entries on subdomain
2005: . oscat - scatter from global vector to overlapping global vector entries on subdomain
2006: - gscat - scatter from global vector to local vector on subdomain (fills in ghosts)
2008: Notes:
2009: This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution
2010: of general nonlinear problems with overlapping subdomain methods. While merely having index sets that enable subsets
2011: of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of
2012: solution and residual data.
2014: Level: developer
2016: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
2017: @*/
2018: PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat)
2019: {
2025: if (!dm->ops->createddscatters) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateDomainDecompositionScatters",((PetscObject)dm)->type_name);
2026: (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);
2027: return(0);
2028: }
2030: /*@
2031: DMRefine - Refines a DM object
2033: Collective on dm
2035: Input Parameter:
2036: + dm - the DM object
2037: - comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
2039: Output Parameter:
2040: . dmf - the refined DM, or NULL
2042: Options Dtabase Keys:
2043: . -dm_plex_cell_refiner <strategy> - chooses the refinement strategy, e.g. regular, tohex
2045: Note: If no refinement was done, the return value is NULL
2047: Level: developer
2049: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2050: @*/
2051: PetscErrorCode DMRefine(DM dm,MPI_Comm comm,DM *dmf)
2052: {
2053: PetscErrorCode ierr;
2054: DMRefineHookLink link;
2058: if (!dm->ops->refine) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMRefine",((PetscObject)dm)->type_name);
2059: PetscLogEventBegin(DM_Refine,dm,0,0,0);
2060: (*dm->ops->refine)(dm,comm,dmf);
2061: if (*dmf) {
2062: (*dmf)->ops->creatematrix = dm->ops->creatematrix;
2064: PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);
2066: (*dmf)->ctx = dm->ctx;
2067: (*dmf)->leveldown = dm->leveldown;
2068: (*dmf)->levelup = dm->levelup + 1;
2070: DMSetMatType(*dmf,dm->mattype);
2071: for (link=dm->refinehook; link; link=link->next) {
2072: if (link->refinehook) {
2073: (*link->refinehook)(dm,*dmf,link->ctx);
2074: }
2075: }
2076: }
2077: PetscLogEventEnd(DM_Refine,dm,0,0,0);
2078: return(0);
2079: }
2081: /*@C
2082: DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid
2084: Logically Collective
2086: Input Arguments:
2087: + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level
2088: . refinehook - function to run when setting up a coarser level
2089: . interphook - function to run to update data on finer levels (once per SNESSolve())
2090: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2092: Calling sequence of refinehook:
2093: $ refinehook(DM coarse,DM fine,void *ctx);
2095: + coarse - coarse level DM
2096: . fine - fine level DM to interpolate problem to
2097: - ctx - optional user-defined function context
2099: Calling sequence for interphook:
2100: $ interphook(DM coarse,Mat interp,DM fine,void *ctx)
2102: + coarse - coarse level DM
2103: . interp - matrix interpolating a coarse-level solution to the finer grid
2104: . fine - fine level DM to update
2105: - ctx - optional user-defined function context
2107: Level: advanced
2109: Notes:
2110: This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing
2112: If this function is called multiple times, the hooks will be run in the order they are added.
2114: This function is currently not available from Fortran.
2116: .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2117: @*/
2118: PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx)
2119: {
2120: PetscErrorCode ierr;
2121: DMRefineHookLink link,*p;
2125: for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */
2126: if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) return(0);
2127: }
2128: PetscNew(&link);
2129: link->refinehook = refinehook;
2130: link->interphook = interphook;
2131: link->ctx = ctx;
2132: link->next = NULL;
2133: *p = link;
2134: return(0);
2135: }
2137: /*@C
2138: DMRefineHookRemove - remove a callback from the list of hooks to be run when interpolating a nonlinear problem to a finer grid
2140: Logically Collective
2142: Input Arguments:
2143: + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level
2144: . refinehook - function to run when setting up a coarser level
2145: . interphook - function to run to update data on finer levels (once per SNESSolve())
2146: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2148: Level: advanced
2150: Notes:
2151: This function does nothing if the hook is not in the list.
2153: This function is currently not available from Fortran.
2155: .seealso: DMCoarsenHookRemove(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2156: @*/
2157: PetscErrorCode DMRefineHookRemove(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx)
2158: {
2159: PetscErrorCode ierr;
2160: DMRefineHookLink link,*p;
2164: for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Search the list of current hooks */
2165: if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) {
2166: link = *p;
2167: *p = link->next;
2168: PetscFree(link);
2169: break;
2170: }
2171: }
2172: return(0);
2173: }
2175: /*@
2176: DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd()
2178: Collective if any hooks are
2180: Input Arguments:
2181: + coarse - coarser DM to use as a base
2182: . interp - interpolation matrix, apply using MatInterpolate()
2183: - fine - finer DM to update
2185: Level: developer
2187: .seealso: DMRefineHookAdd(), MatInterpolate()
2188: @*/
2189: PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine)
2190: {
2191: PetscErrorCode ierr;
2192: DMRefineHookLink link;
2195: for (link=fine->refinehook; link; link=link->next) {
2196: if (link->interphook) {
2197: (*link->interphook)(coarse,interp,fine,link->ctx);
2198: }
2199: }
2200: return(0);
2201: }
2203: /*@
2204: DMGetRefineLevel - Gets the number of refinements that have generated this DM.
2206: Not Collective
2208: Input Parameter:
2209: . dm - the DM object
2211: Output Parameter:
2212: . level - number of refinements
2214: Level: developer
2216: .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2218: @*/
2219: PetscErrorCode DMGetRefineLevel(DM dm,PetscInt *level)
2220: {
2223: *level = dm->levelup;
2224: return(0);
2225: }
2227: /*@
2228: DMSetRefineLevel - Sets the number of refinements that have generated this DM.
2230: Not Collective
2232: Input Parameter:
2233: + dm - the DM object
2234: - level - number of refinements
2236: Level: advanced
2238: Notes:
2239: This value is used by PCMG to determine how many multigrid levels to use
2241: .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2243: @*/
2244: PetscErrorCode DMSetRefineLevel(DM dm,PetscInt level)
2245: {
2248: dm->levelup = level;
2249: return(0);
2250: }
2252: PetscErrorCode DMGetBasisTransformDM_Internal(DM dm, DM *tdm)
2253: {
2257: *tdm = dm->transformDM;
2258: return(0);
2259: }
2261: PetscErrorCode DMGetBasisTransformVec_Internal(DM dm, Vec *tv)
2262: {
2266: *tv = dm->transform;
2267: return(0);
2268: }
2270: /*@
2271: DMHasBasisTransform - Whether we employ a basis transformation from functions in global vectors to functions in local vectors
2273: Input Parameter:
2274: . dm - The DM
2276: Output Parameter:
2277: . flg - PETSC_TRUE if a basis transformation should be done
2279: Level: developer
2281: .seealso: DMPlexGlobalToLocalBasis(), DMPlexLocalToGlobalBasis(), DMPlexCreateBasisRotation()
2282: @*/
2283: PetscErrorCode DMHasBasisTransform(DM dm, PetscBool *flg)
2284: {
2285: Vec tv;
2291: DMGetBasisTransformVec_Internal(dm, &tv);
2292: *flg = tv ? PETSC_TRUE : PETSC_FALSE;
2293: return(0);
2294: }
2296: PetscErrorCode DMConstructBasisTransform_Internal(DM dm)
2297: {
2298: PetscSection s, ts;
2299: PetscScalar *ta;
2300: PetscInt cdim, pStart, pEnd, p, Nf, f, Nc, dof;
2304: DMGetCoordinateDim(dm, &cdim);
2305: DMGetLocalSection(dm, &s);
2306: PetscSectionGetChart(s, &pStart, &pEnd);
2307: PetscSectionGetNumFields(s, &Nf);
2308: DMClone(dm, &dm->transformDM);
2309: DMGetLocalSection(dm->transformDM, &ts);
2310: PetscSectionSetNumFields(ts, Nf);
2311: PetscSectionSetChart(ts, pStart, pEnd);
2312: for (f = 0; f < Nf; ++f) {
2313: PetscSectionGetFieldComponents(s, f, &Nc);
2314: /* We could start to label fields by their transformation properties */
2315: if (Nc != cdim) continue;
2316: for (p = pStart; p < pEnd; ++p) {
2317: PetscSectionGetFieldDof(s, p, f, &dof);
2318: if (!dof) continue;
2319: PetscSectionSetFieldDof(ts, p, f, PetscSqr(cdim));
2320: PetscSectionAddDof(ts, p, PetscSqr(cdim));
2321: }
2322: }
2323: PetscSectionSetUp(ts);
2324: DMCreateLocalVector(dm->transformDM, &dm->transform);
2325: VecGetArray(dm->transform, &ta);
2326: for (p = pStart; p < pEnd; ++p) {
2327: for (f = 0; f < Nf; ++f) {
2328: PetscSectionGetFieldDof(ts, p, f, &dof);
2329: if (dof) {
2330: PetscReal x[3] = {0.0, 0.0, 0.0};
2331: PetscScalar *tva;
2332: const PetscScalar *A;
2334: /* TODO Get quadrature point for this dual basis vector for coordinate */
2335: (*dm->transformGetMatrix)(dm, x, PETSC_TRUE, &A, dm->transformCtx);
2336: DMPlexPointLocalFieldRef(dm->transformDM, p, f, ta, (void *) &tva);
2337: PetscArraycpy(tva, A, PetscSqr(cdim));
2338: }
2339: }
2340: }
2341: VecRestoreArray(dm->transform, &ta);
2342: return(0);
2343: }
2345: PetscErrorCode DMCopyTransform(DM dm, DM newdm)
2346: {
2352: newdm->transformCtx = dm->transformCtx;
2353: newdm->transformSetUp = dm->transformSetUp;
2354: newdm->transformDestroy = NULL;
2355: newdm->transformGetMatrix = dm->transformGetMatrix;
2356: if (newdm->transformSetUp) {DMConstructBasisTransform_Internal(newdm);}
2357: return(0);
2358: }
2360: /*@C
2361: DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called
2363: Logically Collective
2365: Input Arguments:
2366: + dm - the DM
2367: . beginhook - function to run at the beginning of DMGlobalToLocalBegin()
2368: . endhook - function to run after DMGlobalToLocalEnd() has completed
2369: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2371: Calling sequence for beginhook:
2372: $ beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)
2374: + dm - global DM
2375: . g - global vector
2376: . mode - mode
2377: . l - local vector
2378: - ctx - optional user-defined function context
2381: Calling sequence for endhook:
2382: $ endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)
2384: + global - global DM
2385: - ctx - optional user-defined function context
2387: Level: advanced
2389: .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2390: @*/
2391: PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx)
2392: {
2393: PetscErrorCode ierr;
2394: DMGlobalToLocalHookLink link,*p;
2398: for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2399: PetscNew(&link);
2400: link->beginhook = beginhook;
2401: link->endhook = endhook;
2402: link->ctx = ctx;
2403: link->next = NULL;
2404: *p = link;
2405: return(0);
2406: }
2408: static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx)
2409: {
2410: Mat cMat;
2411: Vec cVec;
2412: PetscSection section, cSec;
2413: PetscInt pStart, pEnd, p, dof;
2418: DMGetDefaultConstraints(dm,&cSec,&cMat);
2419: if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) {
2420: PetscInt nRows;
2422: MatGetSize(cMat,&nRows,NULL);
2423: if (nRows <= 0) return(0);
2424: DMGetLocalSection(dm,§ion);
2425: MatCreateVecs(cMat,NULL,&cVec);
2426: MatMult(cMat,l,cVec);
2427: PetscSectionGetChart(cSec,&pStart,&pEnd);
2428: for (p = pStart; p < pEnd; p++) {
2429: PetscSectionGetDof(cSec,p,&dof);
2430: if (dof) {
2431: PetscScalar *vals;
2432: VecGetValuesSection(cVec,cSec,p,&vals);
2433: VecSetValuesSection(l,section,p,vals,INSERT_ALL_VALUES);
2434: }
2435: }
2436: VecDestroy(&cVec);
2437: }
2438: return(0);
2439: }
2441: /*@
2442: DMGlobalToLocal - update local vectors from global vector
2444: Neighbor-wise Collective on dm
2446: Input Parameters:
2447: + dm - the DM object
2448: . g - the global vector
2449: . mode - INSERT_VALUES or ADD_VALUES
2450: - l - the local vector
2452: Notes:
2453: The communication involved in this update can be overlapped with computation by using
2454: DMGlobalToLocalBegin() and DMGlobalToLocalEnd().
2456: Level: beginner
2458: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMLocalToGlobal(), DMLocalToGlobalBegin(), DMLocalToGlobalEnd()
2460: @*/
2461: PetscErrorCode DMGlobalToLocal(DM dm,Vec g,InsertMode mode,Vec l)
2462: {
2466: DMGlobalToLocalBegin(dm,g,mode,l);
2467: DMGlobalToLocalEnd(dm,g,mode,l);
2468: return(0);
2469: }
2471: /*@
2472: DMGlobalToLocalBegin - Begins updating local vectors from global vector
2474: Neighbor-wise Collective on dm
2476: Input Parameters:
2477: + dm - the DM object
2478: . g - the global vector
2479: . mode - INSERT_VALUES or ADD_VALUES
2480: - l - the local vector
2482: Level: intermediate
2484: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMLocalToGlobal(), DMLocalToGlobalBegin(), DMLocalToGlobalEnd()
2486: @*/
2487: PetscErrorCode DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
2488: {
2489: PetscSF sf;
2490: PetscErrorCode ierr;
2491: DMGlobalToLocalHookLink link;
2496: for (link=dm->gtolhook; link; link=link->next) {
2497: if (link->beginhook) {
2498: (*link->beginhook)(dm,g,mode,l,link->ctx);
2499: }
2500: }
2501: DMGetSectionSF(dm, &sf);
2502: if (sf) {
2503: const PetscScalar *gArray;
2504: PetscScalar *lArray;
2505: PetscMemType lmtype,gmtype;
2507: if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2508: VecGetArrayInPlace_Internal(l, &lArray, &lmtype);
2509: VecGetArrayReadInPlace_Internal(g, &gArray, &gmtype);
2510: PetscSFBcastWithMemTypeBegin(sf, MPIU_SCALAR, gmtype, gArray, lmtype, lArray);
2511: VecRestoreArrayInPlace(l, &lArray);
2512: VecRestoreArrayReadInPlace(g, &gArray);
2513: } else {
2514: if (!dm->ops->globaltolocalbegin) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMGlobalToLocalBegin() for type %s",((PetscObject)dm)->type_name);
2515: (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
2516: }
2517: return(0);
2518: }
2520: /*@
2521: DMGlobalToLocalEnd - Ends updating local vectors from global vector
2523: Neighbor-wise Collective on dm
2525: Input Parameters:
2526: + dm - the DM object
2527: . g - the global vector
2528: . mode - INSERT_VALUES or ADD_VALUES
2529: - l - the local vector
2531: Level: intermediate
2533: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMLocalToGlobalBegin(), DMLocalToGlobal(), DMLocalToGlobalBegin(), DMLocalToGlobalEnd()
2535: @*/
2536: PetscErrorCode DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
2537: {
2538: PetscSF sf;
2539: PetscErrorCode ierr;
2540: const PetscScalar *gArray;
2541: PetscScalar *lArray;
2542: PetscBool transform;
2543: DMGlobalToLocalHookLink link;
2544: PetscMemType lmtype,gmtype;
2548: DMGetSectionSF(dm, &sf);
2549: DMHasBasisTransform(dm, &transform);
2550: if (sf) {
2551: if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2553: VecGetArrayInPlace_Internal(l, &lArray, &lmtype);
2554: VecGetArrayReadInPlace_Internal(g, &gArray, &gmtype);
2555: PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);
2556: VecRestoreArrayInPlace(l, &lArray);
2557: VecRestoreArrayReadInPlace(g, &gArray);
2558: if (transform) {DMPlexGlobalToLocalBasis(dm, l);}
2559: } else {
2560: if (!dm->ops->globaltolocalend) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMGlobalToLocalEnd() for type %s",((PetscObject)dm)->type_name);
2561: (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
2562: }
2563: DMGlobalToLocalHook_Constraints(dm,g,mode,l,NULL);
2564: for (link=dm->gtolhook; link; link=link->next) {
2565: if (link->endhook) {(*link->endhook)(dm,g,mode,l,link->ctx);}
2566: }
2567: return(0);
2568: }
2570: /*@C
2571: DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called
2573: Logically Collective
2575: Input Arguments:
2576: + dm - the DM
2577: . beginhook - function to run at the beginning of DMLocalToGlobalBegin()
2578: . endhook - function to run after DMLocalToGlobalEnd() has completed
2579: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2581: Calling sequence for beginhook:
2582: $ beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)
2584: + dm - global DM
2585: . l - local vector
2586: . mode - mode
2587: . g - global vector
2588: - ctx - optional user-defined function context
2591: Calling sequence for endhook:
2592: $ endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)
2594: + global - global DM
2595: . l - local vector
2596: . mode - mode
2597: . g - global vector
2598: - ctx - optional user-defined function context
2600: Level: advanced
2602: .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2603: @*/
2604: PetscErrorCode DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx)
2605: {
2606: PetscErrorCode ierr;
2607: DMLocalToGlobalHookLink link,*p;
2611: for (p=&dm->ltoghook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2612: PetscNew(&link);
2613: link->beginhook = beginhook;
2614: link->endhook = endhook;
2615: link->ctx = ctx;
2616: link->next = NULL;
2617: *p = link;
2618: return(0);
2619: }
2621: static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx)
2622: {
2623: Mat cMat;
2624: Vec cVec;
2625: PetscSection section, cSec;
2626: PetscInt pStart, pEnd, p, dof;
2631: DMGetDefaultConstraints(dm,&cSec,&cMat);
2632: if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) {
2633: PetscInt nRows;
2635: MatGetSize(cMat,&nRows,NULL);
2636: if (nRows <= 0) return(0);
2637: DMGetLocalSection(dm,§ion);
2638: MatCreateVecs(cMat,NULL,&cVec);
2639: PetscSectionGetChart(cSec,&pStart,&pEnd);
2640: for (p = pStart; p < pEnd; p++) {
2641: PetscSectionGetDof(cSec,p,&dof);
2642: if (dof) {
2643: PetscInt d;
2644: PetscScalar *vals;
2645: VecGetValuesSection(l,section,p,&vals);
2646: VecSetValuesSection(cVec,cSec,p,vals,mode);
2647: /* for this to be the true transpose, we have to zero the values that
2648: * we just extracted */
2649: for (d = 0; d < dof; d++) {
2650: vals[d] = 0.;
2651: }
2652: }
2653: }
2654: MatMultTransposeAdd(cMat,cVec,l,l);
2655: VecDestroy(&cVec);
2656: }
2657: return(0);
2658: }
2659: /*@
2660: DMLocalToGlobal - updates global vectors from local vectors
2662: Neighbor-wise Collective on dm
2664: Input Parameters:
2665: + dm - the DM object
2666: . l - the local vector
2667: . 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.
2668: - g - the global vector
2670: Notes:
2671: The communication involved in this update can be overlapped with computation by using
2672: DMLocalToGlobalBegin() and DMLocalToGlobalEnd().
2674: In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation.
2675: INSERT_VALUES is not supported for DMDA; in that case simply compute the values directly into a global vector instead of a local one.
2677: Level: beginner
2679: .seealso DMLocalToGlobalBegin(), DMLocalToGlobalEnd(), DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin()
2681: @*/
2682: PetscErrorCode DMLocalToGlobal(DM dm,Vec l,InsertMode mode,Vec g)
2683: {
2687: DMLocalToGlobalBegin(dm,l,mode,g);
2688: DMLocalToGlobalEnd(dm,l,mode,g);
2689: return(0);
2690: }
2692: /*@
2693: DMLocalToGlobalBegin - begins updating global vectors from local vectors
2695: Neighbor-wise Collective on dm
2697: Input Parameters:
2698: + dm - the DM object
2699: . l - the local vector
2700: . 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.
2701: - g - the global vector
2703: Notes:
2704: In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation.
2705: INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one.
2707: Level: intermediate
2709: .seealso DMLocalToGlobal(), DMLocalToGlobalEnd(), DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin()
2711: @*/
2712: PetscErrorCode DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g)
2713: {
2714: PetscSF sf;
2715: PetscSection s, gs;
2716: DMLocalToGlobalHookLink link;
2717: Vec tmpl;
2718: const PetscScalar *lArray;
2719: PetscScalar *gArray;
2720: PetscBool isInsert, transform, l_inplace = PETSC_FALSE, g_inplace = PETSC_FALSE;
2721: PetscErrorCode ierr;
2722: PetscMemType lmtype=PETSC_MEMTYPE_HOST,gmtype=PETSC_MEMTYPE_HOST;
2726: for (link=dm->ltoghook; link; link=link->next) {
2727: if (link->beginhook) {
2728: (*link->beginhook)(dm,l,mode,g,link->ctx);
2729: }
2730: }
2731: DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);
2732: DMGetSectionSF(dm, &sf);
2733: DMGetLocalSection(dm, &s);
2734: switch (mode) {
2735: case INSERT_VALUES:
2736: case INSERT_ALL_VALUES:
2737: case INSERT_BC_VALUES:
2738: isInsert = PETSC_TRUE; break;
2739: case ADD_VALUES:
2740: case ADD_ALL_VALUES:
2741: case ADD_BC_VALUES:
2742: isInsert = PETSC_FALSE; break;
2743: default:
2744: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2745: }
2746: if ((sf && !isInsert) || (s && isInsert)) {
2747: DMHasBasisTransform(dm, &transform);
2748: if (transform) {
2749: DMGetNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl);
2750: VecCopy(l, tmpl);
2751: DMPlexLocalToGlobalBasis(dm, tmpl);
2752: VecGetArrayRead(tmpl, &lArray);
2753: } else if (isInsert) {
2754: VecGetArrayRead(l, &lArray);
2755: } else {
2756: VecGetArrayReadInPlace_Internal(l, &lArray, &lmtype);
2757: l_inplace = PETSC_TRUE;
2758: }
2759: if (s && isInsert) {
2760: VecGetArray(g, &gArray);
2761: } else {
2762: VecGetArrayInPlace_Internal(g, &gArray, &gmtype);
2763: g_inplace = PETSC_TRUE;
2764: }
2765: if (sf && !isInsert) {
2766: PetscSFReduceWithMemTypeBegin(sf, MPIU_SCALAR, lmtype, lArray, gmtype, gArray, MPIU_SUM);
2767: } else if (s && isInsert) {
2768: PetscInt gStart, pStart, pEnd, p;
2770: DMGetGlobalSection(dm, &gs);
2771: PetscSectionGetChart(s, &pStart, &pEnd);
2772: VecGetOwnershipRange(g, &gStart, NULL);
2773: for (p = pStart; p < pEnd; ++p) {
2774: PetscInt dof, gdof, cdof, gcdof, off, goff, d, e;
2776: PetscSectionGetDof(s, p, &dof);
2777: PetscSectionGetDof(gs, p, &gdof);
2778: PetscSectionGetConstraintDof(s, p, &cdof);
2779: PetscSectionGetConstraintDof(gs, p, &gcdof);
2780: PetscSectionGetOffset(s, p, &off);
2781: PetscSectionGetOffset(gs, p, &goff);
2782: /* Ignore off-process data and points with no global data */
2783: if (!gdof || goff < 0) continue;
2784: 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);
2785: /* If no constraints are enforced in the global vector */
2786: if (!gcdof) {
2787: for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d];
2788: /* If constraints are enforced in the global vector */
2789: } else if (cdof == gcdof) {
2790: const PetscInt *cdofs;
2791: PetscInt cind = 0;
2793: PetscSectionGetConstraintIndices(s, p, &cdofs);
2794: for (d = 0, e = 0; d < dof; ++d) {
2795: if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;}
2796: gArray[goff-gStart+e++] = lArray[off+d];
2797: }
2798: } 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);
2799: }
2800: }
2801: if (g_inplace) {
2802: VecRestoreArrayInPlace(g, &gArray);
2803: } else {
2804: VecRestoreArray(g, &gArray);
2805: }
2806: if (transform) {
2807: VecRestoreArrayRead(tmpl, &lArray);
2808: DMRestoreNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl);
2809: } else if (l_inplace) {
2810: VecRestoreArrayReadInPlace(l, &lArray);
2811: } else {
2812: VecRestoreArrayRead(l, &lArray);
2813: }
2814: } else {
2815: if (!dm->ops->localtoglobalbegin) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMLocalToGlobalBegin() for type %s",((PetscObject)dm)->type_name);
2816: (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);
2817: }
2818: return(0);
2819: }
2821: /*@
2822: DMLocalToGlobalEnd - updates global vectors from local vectors
2824: Neighbor-wise Collective on dm
2826: Input Parameters:
2827: + dm - the DM object
2828: . l - the local vector
2829: . mode - INSERT_VALUES or ADD_VALUES
2830: - g - the global vector
2832: Level: intermediate
2834: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd()
2836: @*/
2837: PetscErrorCode DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g)
2838: {
2839: PetscSF sf;
2840: PetscSection s;
2841: DMLocalToGlobalHookLink link;
2842: PetscBool isInsert, transform;
2843: PetscErrorCode ierr;
2847: DMGetSectionSF(dm, &sf);
2848: DMGetLocalSection(dm, &s);
2849: switch (mode) {
2850: case INSERT_VALUES:
2851: case INSERT_ALL_VALUES:
2852: isInsert = PETSC_TRUE; break;
2853: case ADD_VALUES:
2854: case ADD_ALL_VALUES:
2855: isInsert = PETSC_FALSE; break;
2856: default:
2857: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2858: }
2859: if (sf && !isInsert) {
2860: const PetscScalar *lArray;
2861: PetscScalar *gArray;
2862: Vec tmpl;
2864: DMHasBasisTransform(dm, &transform);
2865: if (transform) {
2866: DMGetNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl);
2867: VecGetArrayRead(tmpl, &lArray);
2868: } else {
2869: VecGetArrayReadInPlace_Internal(l, &lArray, NULL);
2870: }
2871: VecGetArrayInPlace_Internal(g, &gArray, NULL);
2872: PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);
2873: if (transform) {
2874: VecRestoreArrayRead(tmpl, &lArray);
2875: DMRestoreNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl);
2876: } else {
2877: VecRestoreArrayReadInPlace(l, &lArray);
2878: }
2879: VecRestoreArrayInPlace(g, &gArray);
2880: } else if (s && isInsert) {
2881: } else {
2882: if (!dm->ops->localtoglobalend) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMLocalToGlobalEnd() for type %s",((PetscObject)dm)->type_name);
2883: (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);
2884: }
2885: for (link=dm->ltoghook; link; link=link->next) {
2886: if (link->endhook) {(*link->endhook)(dm,g,mode,l,link->ctx);}
2887: }
2888: return(0);
2889: }
2891: /*@
2892: DMLocalToLocalBegin - Maps from a local vector (including ghost points
2893: that contain irrelevant values) to another local vector where the ghost
2894: points in the second are set correctly. Must be followed by DMLocalToLocalEnd().
2896: Neighbor-wise Collective on dm
2898: Input Parameters:
2899: + dm - the DM object
2900: . g - the original local vector
2901: - mode - one of INSERT_VALUES or ADD_VALUES
2903: Output Parameter:
2904: . l - the local vector with correct ghost values
2906: Level: intermediate
2908: Notes:
2909: The local vectors used here need not be the same as those
2910: obtained from DMCreateLocalVector(), BUT they
2911: must have the same parallel data layout; they could, for example, be
2912: obtained with VecDuplicate() from the DM originating vectors.
2914: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2916: @*/
2917: PetscErrorCode DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
2918: {
2919: PetscErrorCode ierr;
2923: if (!dm->ops->localtolocalbegin) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps");
2924: (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
2925: return(0);
2926: }
2928: /*@
2929: DMLocalToLocalEnd - Maps from a local vector (including ghost points
2930: that contain irrelevant values) to another local vector where the ghost
2931: points in the second are set correctly. Must be preceded by DMLocalToLocalBegin().
2933: Neighbor-wise Collective on dm
2935: Input Parameters:
2936: + da - the DM object
2937: . g - the original local vector
2938: - mode - one of INSERT_VALUES or ADD_VALUES
2940: Output Parameter:
2941: . l - the local vector with correct ghost values
2943: Level: intermediate
2945: Notes:
2946: The local vectors used here need not be the same as those
2947: obtained from DMCreateLocalVector(), BUT they
2948: must have the same parallel data layout; they could, for example, be
2949: obtained with VecDuplicate() from the DM originating vectors.
2951: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2953: @*/
2954: PetscErrorCode DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
2955: {
2956: PetscErrorCode ierr;
2960: if (!dm->ops->localtolocalend) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps");
2961: (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
2962: return(0);
2963: }
2966: /*@
2967: DMCoarsen - Coarsens a DM object
2969: Collective on dm
2971: Input Parameter:
2972: + dm - the DM object
2973: - comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
2975: Output Parameter:
2976: . dmc - the coarsened DM
2978: Level: developer
2980: .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2982: @*/
2983: PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
2984: {
2985: PetscErrorCode ierr;
2986: DMCoarsenHookLink link;
2990: if (!dm->ops->coarsen) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCoarsen",((PetscObject)dm)->type_name);
2991: PetscLogEventBegin(DM_Coarsen,dm,0,0,0);
2992: (*dm->ops->coarsen)(dm, comm, dmc);
2993: if (*dmc) {
2994: DMSetCoarseDM(dm,*dmc);
2995: (*dmc)->ops->creatematrix = dm->ops->creatematrix;
2996: PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);
2997: (*dmc)->ctx = dm->ctx;
2998: (*dmc)->levelup = dm->levelup;
2999: (*dmc)->leveldown = dm->leveldown + 1;
3000: DMSetMatType(*dmc,dm->mattype);
3001: for (link=dm->coarsenhook; link; link=link->next) {
3002: if (link->coarsenhook) {(*link->coarsenhook)(dm,*dmc,link->ctx);}
3003: }
3004: }
3005: PetscLogEventEnd(DM_Coarsen,dm,0,0,0);
3006: if (!(*dmc)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced");
3007: return(0);
3008: }
3010: /*@C
3011: DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid
3013: Logically Collective
3015: Input Arguments:
3016: + fine - nonlinear solver context on which to run a hook when restricting to a coarser level
3017: . coarsenhook - function to run when setting up a coarser level
3018: . restricthook - function to run to update data on coarser levels (once per SNESSolve())
3019: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
3021: Calling sequence of coarsenhook:
3022: $ coarsenhook(DM fine,DM coarse,void *ctx);
3024: + fine - fine level DM
3025: . coarse - coarse level DM to restrict problem to
3026: - ctx - optional user-defined function context
3028: Calling sequence for restricthook:
3029: $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx)
3031: + fine - fine level DM
3032: . mrestrict - matrix restricting a fine-level solution to the coarse grid
3033: . rscale - scaling vector for restriction
3034: . inject - matrix restricting by injection
3035: . coarse - coarse level DM to update
3036: - ctx - optional user-defined function context
3038: Level: advanced
3040: Notes:
3041: This function is only needed if auxiliary data needs to be set up on coarse grids.
3043: If this function is called multiple times, the hooks will be run in the order they are added.
3045: In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
3046: extract the finest level information from its context (instead of from the SNES).
3048: This function is currently not available from Fortran.
3050: .seealso: DMCoarsenHookRemove(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
3051: @*/
3052: PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx)
3053: {
3054: PetscErrorCode ierr;
3055: DMCoarsenHookLink link,*p;
3059: for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */
3060: if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) return(0);
3061: }
3062: PetscNew(&link);
3063: link->coarsenhook = coarsenhook;
3064: link->restricthook = restricthook;
3065: link->ctx = ctx;
3066: link->next = NULL;
3067: *p = link;
3068: return(0);
3069: }
3071: /*@C
3072: DMCoarsenHookRemove - remove a callback from the list of hooks to be run when restricting a nonlinear problem to the coarse grid
3074: Logically Collective
3076: Input Arguments:
3077: + fine - nonlinear solver context on which to run a hook when restricting to a coarser level
3078: . coarsenhook - function to run when setting up a coarser level
3079: . restricthook - function to run to update data on coarser levels (once per SNESSolve())
3080: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
3082: Level: advanced
3084: Notes:
3085: This function does nothing if the hook is not in the list.
3087: This function is currently not available from Fortran.
3089: .seealso: DMCoarsenHookAdd(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
3090: @*/
3091: PetscErrorCode DMCoarsenHookRemove(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx)
3092: {
3093: PetscErrorCode ierr;
3094: DMCoarsenHookLink link,*p;
3098: for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Search the list of current hooks */
3099: if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
3100: link = *p;
3101: *p = link->next;
3102: PetscFree(link);
3103: break;
3104: }
3105: }
3106: return(0);
3107: }
3110: /*@
3111: DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd()
3113: Collective if any hooks are
3115: Input Arguments:
3116: + fine - finer DM to use as a base
3117: . restrct - restriction matrix, apply using MatRestrict()
3118: . rscale - scaling vector for restriction
3119: . inject - injection matrix, also use MatRestrict()
3120: - coarse - coarser DM to update
3122: Level: developer
3124: .seealso: DMCoarsenHookAdd(), MatRestrict()
3125: @*/
3126: PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse)
3127: {
3128: PetscErrorCode ierr;
3129: DMCoarsenHookLink link;
3132: for (link=fine->coarsenhook; link; link=link->next) {
3133: if (link->restricthook) {
3134: (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);
3135: }
3136: }
3137: return(0);
3138: }
3140: /*@C
3141: DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid
3143: Logically Collective on global
3145: Input Arguments:
3146: + global - global DM
3147: . ddhook - function to run to pass data to the decomposition DM upon its creation
3148: . restricthook - function to run to update data on block solve (at the beginning of the block solve)
3149: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
3152: Calling sequence for ddhook:
3153: $ ddhook(DM global,DM block,void *ctx)
3155: + global - global DM
3156: . block - block DM
3157: - ctx - optional user-defined function context
3159: Calling sequence for restricthook:
3160: $ restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx)
3162: + global - global DM
3163: . out - scatter to the outer (with ghost and overlap points) block vector
3164: . in - scatter to block vector values only owned locally
3165: . block - block DM
3166: - ctx - optional user-defined function context
3168: Level: advanced
3170: Notes:
3171: This function is only needed if auxiliary data needs to be set up on subdomain DMs.
3173: If this function is called multiple times, the hooks will be run in the order they are added.
3175: In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
3176: extract the global information from its context (instead of from the SNES).
3178: This function is currently not available from Fortran.
3180: .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
3181: @*/
3182: PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx)
3183: {
3184: PetscErrorCode ierr;
3185: DMSubDomainHookLink link,*p;
3189: for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */
3190: if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) return(0);
3191: }
3192: PetscNew(&link);
3193: link->restricthook = restricthook;
3194: link->ddhook = ddhook;
3195: link->ctx = ctx;
3196: link->next = NULL;
3197: *p = link;
3198: return(0);
3199: }
3201: /*@C
3202: DMSubDomainHookRemove - remove a callback from the list to be run when restricting a problem to the coarse grid
3204: Logically Collective
3206: Input Arguments:
3207: + global - global DM
3208: . ddhook - function to run to pass data to the decomposition DM upon its creation
3209: . restricthook - function to run to update data on block solve (at the beginning of the block solve)
3210: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
3212: Level: advanced
3214: Notes:
3216: This function is currently not available from Fortran.
3218: .seealso: DMSubDomainHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
3219: @*/
3220: PetscErrorCode DMSubDomainHookRemove(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx)
3221: {
3222: PetscErrorCode ierr;
3223: DMSubDomainHookLink link,*p;
3227: for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Search the list of current hooks */
3228: if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
3229: link = *p;
3230: *p = link->next;
3231: PetscFree(link);
3232: break;
3233: }
3234: }
3235: return(0);
3236: }
3238: /*@
3239: DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd()
3241: Collective if any hooks are
3243: Input Arguments:
3244: + fine - finer DM to use as a base
3245: . oscatter - scatter from domain global vector filling subdomain global vector with overlap
3246: . gscatter - scatter from domain global vector filling subdomain local vector with ghosts
3247: - coarse - coarer DM to update
3249: Level: developer
3251: .seealso: DMCoarsenHookAdd(), MatRestrict()
3252: @*/
3253: PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm)
3254: {
3255: PetscErrorCode ierr;
3256: DMSubDomainHookLink link;
3259: for (link=global->subdomainhook; link; link=link->next) {
3260: if (link->restricthook) {
3261: (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);
3262: }
3263: }
3264: return(0);
3265: }
3267: /*@
3268: DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM.
3270: Not Collective
3272: Input Parameter:
3273: . dm - the DM object
3275: Output Parameter:
3276: . level - number of coarsenings
3278: Level: developer
3280: .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
3282: @*/
3283: PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level)
3284: {
3288: *level = dm->leveldown;
3289: return(0);
3290: }
3292: /*@
3293: DMSetCoarsenLevel - Sets the number of coarsenings that have generated this DM.
3295: Not Collective
3297: Input Parameters:
3298: + dm - the DM object
3299: - level - number of coarsenings
3301: Level: developer
3303: .seealso DMCoarsen(), DMGetCoarsenLevel(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
3304: @*/
3305: PetscErrorCode DMSetCoarsenLevel(DM dm,PetscInt level)
3306: {
3309: dm->leveldown = level;
3310: return(0);
3311: }
3315: /*@C
3316: DMRefineHierarchy - Refines a DM object, all levels at once
3318: Collective on dm
3320: Input Parameter:
3321: + dm - the DM object
3322: - nlevels - the number of levels of refinement
3324: Output Parameter:
3325: . dmf - the refined DM hierarchy
3327: Level: developer
3329: .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
3331: @*/
3332: PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[])
3333: {
3338: if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
3339: if (nlevels == 0) return(0);
3341: if (dm->ops->refinehierarchy) {
3342: (*dm->ops->refinehierarchy)(dm,nlevels,dmf);
3343: } else if (dm->ops->refine) {
3344: PetscInt i;
3346: DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);
3347: for (i=1; i<nlevels; i++) {
3348: DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);
3349: }
3350: } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet");
3351: return(0);
3352: }
3354: /*@C
3355: DMCoarsenHierarchy - Coarsens a DM object, all levels at once
3357: Collective on dm
3359: Input Parameter:
3360: + dm - the DM object
3361: - nlevels - the number of levels of coarsening
3363: Output Parameter:
3364: . dmc - the coarsened DM hierarchy
3366: Level: developer
3368: .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
3370: @*/
3371: PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
3372: {
3377: if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
3378: if (nlevels == 0) return(0);
3380: if (dm->ops->coarsenhierarchy) {
3381: (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);
3382: } else if (dm->ops->coarsen) {
3383: PetscInt i;
3385: DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);
3386: for (i=1; i<nlevels; i++) {
3387: DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);
3388: }
3389: } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet");
3390: return(0);
3391: }
3393: /*@C
3394: DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed
3396: Not Collective
3398: Input Parameters:
3399: + dm - the DM object
3400: - destroy - the destroy function
3402: Level: intermediate
3404: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
3406: @*/
3407: PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**))
3408: {
3411: dm->ctxdestroy = destroy;
3412: return(0);
3413: }
3415: /*@
3416: DMSetApplicationContext - Set a user context into a DM object
3418: Not Collective
3420: Input Parameters:
3421: + dm - the DM object
3422: - ctx - the user context
3424: Level: intermediate
3426: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
3428: @*/
3429: PetscErrorCode DMSetApplicationContext(DM dm,void *ctx)
3430: {
3433: dm->ctx = ctx;
3434: return(0);
3435: }
3437: /*@
3438: DMGetApplicationContext - Gets a user context from a DM object
3440: Not Collective
3442: Input Parameter:
3443: . dm - the DM object
3445: Output Parameter:
3446: . ctx - the user context
3448: Level: intermediate
3450: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
3452: @*/
3453: PetscErrorCode DMGetApplicationContext(DM dm,void *ctx)
3454: {
3457: *(void**)ctx = dm->ctx;
3458: return(0);
3459: }
3461: /*@C
3462: DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI.
3464: Logically Collective on dm
3466: Input Parameter:
3467: + dm - the DM object
3468: - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set)
3470: Level: intermediate
3472: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(),
3473: DMSetJacobian()
3475: @*/
3476: PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec))
3477: {
3480: dm->ops->computevariablebounds = f;
3481: return(0);
3482: }
3484: /*@
3485: DMHasVariableBounds - does the DM object have a variable bounds function?
3487: Not Collective
3489: Input Parameter:
3490: . dm - the DM object to destroy
3492: Output Parameter:
3493: . flg - PETSC_TRUE if the variable bounds function exists
3495: Level: developer
3497: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
3499: @*/
3500: PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg)
3501: {
3505: *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE;
3506: return(0);
3507: }
3509: /*@C
3510: DMComputeVariableBounds - compute variable bounds used by SNESVI.
3512: Logically Collective on dm
3514: Input Parameters:
3515: . dm - the DM object
3517: Output parameters:
3518: + xl - lower bound
3519: - xu - upper bound
3521: Level: advanced
3523: Notes:
3524: This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds()
3526: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
3528: @*/
3529: PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu)
3530: {
3537: if (!dm->ops->computevariablebounds) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeVariableBounds",((PetscObject)dm)->type_name);
3538: (*dm->ops->computevariablebounds)(dm, xl,xu);
3539: return(0);
3540: }
3542: /*@
3543: DMHasColoring - does the DM object have a method of providing a coloring?
3545: Not Collective
3547: Input Parameter:
3548: . dm - the DM object
3550: Output Parameter:
3551: . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring().
3553: Level: developer
3555: .seealso DMCreateColoring()
3557: @*/
3558: PetscErrorCode DMHasColoring(DM dm,PetscBool *flg)
3559: {
3563: *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE;
3564: return(0);
3565: }
3567: /*@
3568: DMHasCreateRestriction - does the DM object have a method of providing a restriction?
3570: Not Collective
3572: Input Parameter:
3573: . dm - the DM object
3575: Output Parameter:
3576: . flg - PETSC_TRUE if the DM has facilities for DMCreateRestriction().
3578: Level: developer
3580: .seealso DMCreateRestriction()
3582: @*/
3583: PetscErrorCode DMHasCreateRestriction(DM dm,PetscBool *flg)
3584: {
3588: *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE;
3589: return(0);
3590: }
3593: /*@
3594: DMHasCreateInjection - does the DM object have a method of providing an injection?
3596: Not Collective
3598: Input Parameter:
3599: . dm - the DM object
3601: Output Parameter:
3602: . flg - PETSC_TRUE if the DM has facilities for DMCreateInjection().
3604: Level: developer
3606: .seealso DMCreateInjection()
3608: @*/
3609: PetscErrorCode DMHasCreateInjection(DM dm,PetscBool *flg)
3610: {
3616: if (dm->ops->hascreateinjection) {
3617: (*dm->ops->hascreateinjection)(dm,flg);
3618: } else {
3619: *flg = (dm->ops->createinjection) ? PETSC_TRUE : PETSC_FALSE;
3620: }
3621: return(0);
3622: }
3624: PetscFunctionList DMList = NULL;
3625: PetscBool DMRegisterAllCalled = PETSC_FALSE;
3627: /*@C
3628: DMSetType - Builds a DM, for a particular DM implementation.
3630: Collective on dm
3632: Input Parameters:
3633: + dm - The DM object
3634: - method - The name of the DM type
3636: Options Database Key:
3637: . -dm_type <type> - Sets the DM type; use -help for a list of available types
3639: Notes:
3640: See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D).
3642: Level: intermediate
3644: .seealso: DMGetType(), DMCreate()
3645: @*/
3646: PetscErrorCode DMSetType(DM dm, DMType method)
3647: {
3648: PetscErrorCode (*r)(DM);
3649: PetscBool match;
3654: PetscObjectTypeCompare((PetscObject) dm, method, &match);
3655: if (match) return(0);
3657: DMRegisterAll();
3658: PetscFunctionListFind(DMList,method,&r);
3659: if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);
3661: if (dm->ops->destroy) {
3662: (*dm->ops->destroy)(dm);
3663: }
3664: PetscMemzero(dm->ops,sizeof(*dm->ops));
3665: PetscObjectChangeTypeName((PetscObject)dm,method);
3666: (*r)(dm);
3667: return(0);
3668: }
3670: /*@C
3671: DMGetType - Gets the DM type name (as a string) from the DM.
3673: Not Collective
3675: Input Parameter:
3676: . dm - The DM
3678: Output Parameter:
3679: . type - The DM type name
3681: Level: intermediate
3683: .seealso: DMSetType(), DMCreate()
3684: @*/
3685: PetscErrorCode DMGetType(DM dm, DMType *type)
3686: {
3692: DMRegisterAll();
3693: *type = ((PetscObject)dm)->type_name;
3694: return(0);
3695: }
3697: /*@C
3698: DMConvert - Converts a DM to another DM, either of the same or different type.
3700: Collective on dm
3702: Input Parameters:
3703: + dm - the DM
3704: - newtype - new DM type (use "same" for the same type)
3706: Output Parameter:
3707: . M - pointer to new DM
3709: Notes:
3710: Cannot be used to convert a sequential DM to parallel or parallel to sequential,
3711: the MPI communicator of the generated DM is always the same as the communicator
3712: of the input DM.
3714: Level: intermediate
3716: .seealso: DMCreate()
3717: @*/
3718: PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M)
3719: {
3720: DM B;
3721: char convname[256];
3722: PetscBool sametype/*, issame */;
3729: PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);
3730: /* PetscStrcmp(newtype, "same", &issame); */
3731: if (sametype) {
3732: *M = dm;
3733: PetscObjectReference((PetscObject) dm);
3734: return(0);
3735: } else {
3736: PetscErrorCode (*conv)(DM, DMType, DM*) = NULL;
3738: /*
3739: Order of precedence:
3740: 1) See if a specialized converter is known to the current DM.
3741: 2) See if a specialized converter is known to the desired DM class.
3742: 3) See if a good general converter is registered for the desired class
3743: 4) See if a good general converter is known for the current matrix.
3744: 5) Use a really basic converter.
3745: */
3747: /* 1) See if a specialized converter is known to the current DM and the desired class */
3748: PetscStrncpy(convname,"DMConvert_",sizeof(convname));
3749: PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));
3750: PetscStrlcat(convname,"_",sizeof(convname));
3751: PetscStrlcat(convname,newtype,sizeof(convname));
3752: PetscStrlcat(convname,"_C",sizeof(convname));
3753: PetscObjectQueryFunction((PetscObject)dm,convname,&conv);
3754: if (conv) goto foundconv;
3756: /* 2) See if a specialized converter is known to the desired DM class. */
3757: DMCreate(PetscObjectComm((PetscObject)dm), &B);
3758: DMSetType(B, newtype);
3759: PetscStrncpy(convname,"DMConvert_",sizeof(convname));
3760: PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));
3761: PetscStrlcat(convname,"_",sizeof(convname));
3762: PetscStrlcat(convname,newtype,sizeof(convname));
3763: PetscStrlcat(convname,"_C",sizeof(convname));
3764: PetscObjectQueryFunction((PetscObject)B,convname,&conv);
3765: if (conv) {
3766: DMDestroy(&B);
3767: goto foundconv;
3768: }
3770: #if 0
3771: /* 3) See if a good general converter is registered for the desired class */
3772: conv = B->ops->convertfrom;
3773: DMDestroy(&B);
3774: if (conv) goto foundconv;
3776: /* 4) See if a good general converter is known for the current matrix */
3777: if (dm->ops->convert) {
3778: conv = dm->ops->convert;
3779: }
3780: if (conv) goto foundconv;
3781: #endif
3783: /* 5) Use a really basic converter. */
3784: SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype);
3786: foundconv:
3787: PetscLogEventBegin(DM_Convert,dm,0,0,0);
3788: (*conv)(dm,newtype,M);
3789: /* Things that are independent of DM type: We should consult DMClone() here */
3790: {
3791: PetscBool isper;
3792: const PetscReal *maxCell, *L;
3793: const DMBoundaryType *bd;
3794: DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);
3795: DMSetPeriodicity(*M, isper, maxCell, L, bd);
3796: }
3797: PetscLogEventEnd(DM_Convert,dm,0,0,0);
3798: }
3799: PetscObjectStateIncrease((PetscObject) *M);
3800: return(0);
3801: }
3803: /*--------------------------------------------------------------------------------------------------------------------*/
3805: /*@C
3806: DMRegister - Adds a new DM component implementation
3808: Not Collective
3810: Input Parameters:
3811: + name - The name of a new user-defined creation routine
3812: - create_func - The creation routine itself
3814: Notes:
3815: DMRegister() may be called multiple times to add several user-defined DMs
3818: Sample usage:
3819: .vb
3820: DMRegister("my_da", MyDMCreate);
3821: .ve
3823: Then, your DM type can be chosen with the procedural interface via
3824: .vb
3825: DMCreate(MPI_Comm, DM *);
3826: DMSetType(DM,"my_da");
3827: .ve
3828: or at runtime via the option
3829: .vb
3830: -da_type my_da
3831: .ve
3833: Level: advanced
3835: .seealso: DMRegisterAll(), DMRegisterDestroy()
3837: @*/
3838: PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM))
3839: {
3843: DMInitializePackage();
3844: PetscFunctionListAdd(&DMList,sname,function);
3845: return(0);
3846: }
3848: /*@C
3849: DMLoad - Loads a DM that has been stored in binary with DMView().
3851: Collective on viewer
3853: Input Parameters:
3854: + newdm - the newly loaded DM, this needs to have been created with DMCreate() or
3855: some related function before a call to DMLoad().
3856: - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or
3857: HDF5 file viewer, obtained from PetscViewerHDF5Open()
3859: Level: intermediate
3861: Notes:
3862: The type is determined by the data in the file, any type set into the DM before this call is ignored.
3864: Notes for advanced users:
3865: Most users should not need to know the details of the binary storage
3866: format, since DMLoad() and DMView() completely hide these details.
3867: But for anyone who's interested, the standard binary matrix storage
3868: format is
3869: .vb
3870: has not yet been determined
3871: .ve
3873: .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad()
3874: @*/
3875: PetscErrorCode DMLoad(DM newdm, PetscViewer viewer)
3876: {
3877: PetscBool isbinary, ishdf5;
3883: PetscViewerCheckReadable(viewer);
3884: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
3885: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);
3886: PetscLogEventBegin(DM_Load,viewer,0,0,0);
3887: if (isbinary) {
3888: PetscInt classid;
3889: char type[256];
3891: PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);
3892: if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid);
3893: PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);
3894: DMSetType(newdm, type);
3895: if (newdm->ops->load) {(*newdm->ops->load)(newdm,viewer);}
3896: } else if (ishdf5) {
3897: if (newdm->ops->load) {(*newdm->ops->load)(newdm,viewer);}
3898: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()");
3899: PetscLogEventEnd(DM_Load,viewer,0,0,0);
3900: return(0);
3901: }
3903: /*@
3904: DMGetLocalBoundingBox - Returns the bounding box for the piece of the DM on this process.
3906: Not collective
3908: Input Parameter:
3909: . dm - the DM
3911: Output Parameters:
3912: + lmin - local minimum coordinates (length coord dim, optional)
3913: - lmax - local maximim coordinates (length coord dim, optional)
3915: Level: beginner
3917: Note: If the DM is a DMDA and has no coordinates, the index bounds are returned instead.
3920: .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetBoundingBox()
3921: @*/
3922: PetscErrorCode DMGetLocalBoundingBox(DM dm, PetscReal lmin[], PetscReal lmax[])
3923: {
3924: Vec coords = NULL;
3925: PetscReal min[3] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MAX_REAL};
3926: PetscReal max[3] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
3927: const PetscScalar *local_coords;
3928: PetscInt N, Ni;
3929: PetscInt cdim, i, j;
3930: PetscErrorCode ierr;
3934: DMGetCoordinateDim(dm, &cdim);
3935: DMGetCoordinates(dm, &coords);
3936: if (coords) {
3937: VecGetArrayRead(coords, &local_coords);
3938: VecGetLocalSize(coords, &N);
3939: Ni = N/cdim;
3940: for (i = 0; i < Ni; ++i) {
3941: for (j = 0; j < 3; ++j) {
3942: min[j] = j < cdim ? PetscMin(min[j], PetscRealPart(local_coords[i*cdim+j])) : 0;
3943: max[j] = j < cdim ? PetscMax(max[j], PetscRealPart(local_coords[i*cdim+j])) : 0;
3944: }
3945: }
3946: VecRestoreArrayRead(coords, &local_coords);
3947: } else {
3948: PetscBool isda;
3950: PetscObjectTypeCompare((PetscObject) dm, DMDA, &isda);
3951: if (isda) {DMGetLocalBoundingIndices_DMDA(dm, min, max);}
3952: }
3953: if (lmin) {PetscArraycpy(lmin, min, cdim);}
3954: if (lmax) {PetscArraycpy(lmax, max, cdim);}
3955: return(0);
3956: }
3958: /*@
3959: DMGetBoundingBox - Returns the global bounding box for the DM.
3961: Collective
3963: Input Parameter:
3964: . dm - the DM
3966: Output Parameters:
3967: + gmin - global minimum coordinates (length coord dim, optional)
3968: - gmax - global maximim coordinates (length coord dim, optional)
3970: Level: beginner
3972: .seealso: DMGetLocalBoundingBox(), DMGetCoordinates(), DMGetCoordinatesLocal()
3973: @*/
3974: PetscErrorCode DMGetBoundingBox(DM dm, PetscReal gmin[], PetscReal gmax[])
3975: {
3976: PetscReal lmin[3], lmax[3];
3977: PetscInt cdim;
3978: PetscMPIInt count;
3983: DMGetCoordinateDim(dm, &cdim);
3984: PetscMPIIntCast(cdim, &count);
3985: DMGetLocalBoundingBox(dm, lmin, lmax);
3986: if (gmin) {MPIU_Allreduce(lmin, gmin, count, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject) dm));}
3987: if (gmax) {MPIU_Allreduce(lmax, gmax, count, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject) dm));}
3988: return(0);
3989: }
3991: /******************************** FEM Support **********************************/
3993: PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[])
3994: {
3995: PetscInt f;
3999: PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);
4000: for (f = 0; f < len; ++f) {
4001: PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));
4002: }
4003: return(0);
4004: }
4006: PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[])
4007: {
4008: PetscInt f, g;
4012: PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);
4013: for (f = 0; f < rows; ++f) {
4014: PetscPrintf(PETSC_COMM_SELF, " |");
4015: for (g = 0; g < cols; ++g) {
4016: PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));
4017: }
4018: PetscPrintf(PETSC_COMM_SELF, " |\n");
4019: }
4020: return(0);
4021: }
4023: PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X)
4024: {
4025: PetscInt localSize, bs;
4026: PetscMPIInt size;
4027: Vec x, xglob;
4028: const PetscScalar *xarray;
4029: PetscErrorCode ierr;
4032: MPI_Comm_size(PetscObjectComm((PetscObject) dm),&size);
4033: VecDuplicate(X, &x);
4034: VecCopy(X, x);
4035: VecChop(x, tol);
4036: PetscPrintf(PetscObjectComm((PetscObject) dm),"%s:\n",name);
4037: if (size > 1) {
4038: VecGetLocalSize(x,&localSize);
4039: VecGetArrayRead(x,&xarray);
4040: VecGetBlockSize(x,&bs);
4041: VecCreateMPIWithArray(PetscObjectComm((PetscObject) dm),bs,localSize,PETSC_DETERMINE,xarray,&xglob);
4042: } else {
4043: xglob = x;
4044: }
4045: VecView(xglob,PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject) dm)));
4046: if (size > 1) {
4047: VecDestroy(&xglob);
4048: VecRestoreArrayRead(x,&xarray);
4049: }
4050: VecDestroy(&x);
4051: return(0);
4052: }
4054: /*@
4055: DMGetSection - Get the PetscSection encoding the local data layout for the DM. This is equivalent to DMGetLocalSection(). Deprecated in v3.12
4057: Input Parameter:
4058: . dm - The DM
4060: Output Parameter:
4061: . section - The PetscSection
4063: Options Database Keys:
4064: . -dm_petscsection_view - View the Section created by the DM
4066: Level: advanced
4068: Notes:
4069: Use DMGetLocalSection() in new code.
4071: This gets a borrowed reference, so the user should not destroy this PetscSection.
4073: .seealso: DMGetLocalSection(), DMSetLocalSection(), DMGetGlobalSection()
4074: @*/
4075: PetscErrorCode DMGetSection(DM dm, PetscSection *section)
4076: {
4080: DMGetLocalSection(dm,section);
4081: return(0);
4082: }
4084: /*@
4085: DMGetLocalSection - Get the PetscSection encoding the local data layout for the DM.
4087: Input Parameter:
4088: . dm - The DM
4090: Output Parameter:
4091: . section - The PetscSection
4093: Options Database Keys:
4094: . -dm_petscsection_view - View the Section created by the DM
4096: Level: intermediate
4098: Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
4100: .seealso: DMSetLocalSection(), DMGetGlobalSection()
4101: @*/
4102: PetscErrorCode DMGetLocalSection(DM dm, PetscSection *section)
4103: {
4109: if (!dm->localSection && dm->ops->createlocalsection) {
4110: PetscInt d;
4112: if (dm->setfromoptionscalled) for (d = 0; d < dm->Nds; ++d) {PetscDSSetFromOptions(dm->probs[d].ds);}
4113: (*dm->ops->createlocalsection)(dm);
4114: if (dm->localSection) {PetscObjectViewFromOptions((PetscObject) dm->localSection, NULL, "-dm_petscsection_view");}
4115: }
4116: *section = dm->localSection;
4117: return(0);
4118: }
4120: /*@
4121: DMSetSection - Set the PetscSection encoding the local data layout for the DM. This is equivalent to DMSetLocalSection(). Deprecated in v3.12
4123: Input Parameters:
4124: + dm - The DM
4125: - section - The PetscSection
4127: Level: advanced
4129: Notes:
4130: Use DMSetLocalSection() in new code.
4132: Any existing Section will be destroyed
4134: .seealso: DMSetLocalSection(), DMGetLocalSection(), DMSetGlobalSection()
4135: @*/
4136: PetscErrorCode DMSetSection(DM dm, PetscSection section)
4137: {
4141: DMSetLocalSection(dm,section);
4142: return(0);
4143: }
4145: /*@
4146: DMSetLocalSection - Set the PetscSection encoding the local data layout for the DM.
4148: Input Parameters:
4149: + dm - The DM
4150: - section - The PetscSection
4152: Level: intermediate
4154: Note: Any existing Section will be destroyed
4156: .seealso: DMGetLocalSection(), DMSetGlobalSection()
4157: @*/
4158: PetscErrorCode DMSetLocalSection(DM dm, PetscSection section)
4159: {
4160: PetscInt numFields = 0;
4161: PetscInt f;
4167: PetscObjectReference((PetscObject)section);
4168: PetscSectionDestroy(&dm->localSection);
4169: dm->localSection = section;
4170: if (section) {PetscSectionGetNumFields(dm->localSection, &numFields);}
4171: if (numFields) {
4172: DMSetNumFields(dm, numFields);
4173: for (f = 0; f < numFields; ++f) {
4174: PetscObject disc;
4175: const char *name;
4177: PetscSectionGetFieldName(dm->localSection, f, &name);
4178: DMGetField(dm, f, NULL, &disc);
4179: PetscObjectSetName(disc, name);
4180: }
4181: }
4182: /* The global section will be rebuilt in the next call to DMGetGlobalSection(). */
4183: PetscSectionDestroy(&dm->globalSection);
4184: return(0);
4185: }
4187: /*@
4188: DMGetDefaultConstraints - Get the PetscSection and Mat that specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation.
4190: not collective
4192: Input Parameter:
4193: . dm - The DM
4195: Output Parameter:
4196: + 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.
4197: - 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.
4199: Level: advanced
4201: Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat.
4203: .seealso: DMSetDefaultConstraints()
4204: @*/
4205: PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat)
4206: {
4211: if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {(*dm->ops->createdefaultconstraints)(dm);}
4212: if (section) {*section = dm->defaultConstraintSection;}
4213: if (mat) {*mat = dm->defaultConstraintMat;}
4214: return(0);
4215: }
4217: /*@
4218: DMSetDefaultConstraints - Set the PetscSection and Mat that specify the local constraint interpolation.
4220: 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().
4222: 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.
4224: collective on dm
4226: Input Parameters:
4227: + dm - The DM
4228: + 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).
4229: - 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).
4231: Level: advanced
4233: Note: This increments the references of the PetscSection and the Mat, so they user can destroy them
4235: .seealso: DMGetDefaultConstraints()
4236: @*/
4237: PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat)
4238: {
4239: PetscMPIInt result;
4244: if (section) {
4246: MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);
4247: if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator");
4248: }
4249: if (mat) {
4251: MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);
4252: if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator");
4253: }
4254: PetscObjectReference((PetscObject)section);
4255: PetscSectionDestroy(&dm->defaultConstraintSection);
4256: dm->defaultConstraintSection = section;
4257: PetscObjectReference((PetscObject)mat);
4258: MatDestroy(&dm->defaultConstraintMat);
4259: dm->defaultConstraintMat = mat;
4260: return(0);
4261: }
4263: #if defined(PETSC_USE_DEBUG)
4264: /*
4265: DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections.
4267: Input Parameters:
4268: + dm - The DM
4269: . localSection - PetscSection describing the local data layout
4270: - globalSection - PetscSection describing the global data layout
4272: Level: intermediate
4274: .seealso: DMGetSectionSF(), DMSetSectionSF()
4275: */
4276: static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection)
4277: {
4278: MPI_Comm comm;
4279: PetscLayout layout;
4280: const PetscInt *ranges;
4281: PetscInt pStart, pEnd, p, nroots;
4282: PetscMPIInt size, rank;
4283: PetscBool valid = PETSC_TRUE, gvalid;
4284: PetscErrorCode ierr;
4287: PetscObjectGetComm((PetscObject)dm,&comm);
4289: MPI_Comm_size(comm, &size);
4290: MPI_Comm_rank(comm, &rank);
4291: PetscSectionGetChart(globalSection, &pStart, &pEnd);
4292: PetscSectionGetConstrainedStorageSize(globalSection, &nroots);
4293: PetscLayoutCreate(comm, &layout);
4294: PetscLayoutSetBlockSize(layout, 1);
4295: PetscLayoutSetLocalSize(layout, nroots);
4296: PetscLayoutSetUp(layout);
4297: PetscLayoutGetRanges(layout, &ranges);
4298: for (p = pStart; p < pEnd; ++p) {
4299: PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d;
4301: PetscSectionGetDof(localSection, p, &dof);
4302: PetscSectionGetOffset(localSection, p, &off);
4303: PetscSectionGetConstraintDof(localSection, p, &cdof);
4304: PetscSectionGetDof(globalSection, p, &gdof);
4305: PetscSectionGetConstraintDof(globalSection, p, &gcdof);
4306: PetscSectionGetOffset(globalSection, p, &goff);
4307: if (!gdof) continue; /* Censored point */
4308: 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;}
4309: 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;}
4310: if (gdof < 0) {
4311: gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
4312: for (d = 0; d < gsize; ++d) {
4313: PetscInt offset = -(goff+1) + d, r;
4315: PetscFindInt(offset,size+1,ranges,&r);
4316: if (r < 0) r = -(r+2);
4317: 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;}
4318: }
4319: }
4320: }
4321: PetscLayoutDestroy(&layout);
4322: PetscSynchronizedFlush(comm, NULL);
4323: MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);
4324: if (!gvalid) {
4325: DMView(dm, NULL);
4326: SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections");
4327: }
4328: return(0);
4329: }
4330: #endif
4332: /*@
4333: DMGetGlobalSection - Get the PetscSection encoding the global data layout for the DM.
4335: Collective on dm
4337: Input Parameter:
4338: . dm - The DM
4340: Output Parameter:
4341: . section - The PetscSection
4343: Level: intermediate
4345: Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
4347: .seealso: DMSetLocalSection(), DMGetLocalSection()
4348: @*/
4349: PetscErrorCode DMGetGlobalSection(DM dm, PetscSection *section)
4350: {
4356: if (!dm->globalSection) {
4357: PetscSection s;
4359: DMGetLocalSection(dm, &s);
4360: if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection");
4361: if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a point PetscSF in order to create a global PetscSection");
4362: PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->globalSection);
4363: PetscLayoutDestroy(&dm->map);
4364: PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->globalSection, &dm->map);
4365: PetscSectionViewFromOptions(dm->globalSection, NULL, "-global_section_view");
4366: }
4367: *section = dm->globalSection;
4368: return(0);
4369: }
4371: /*@
4372: DMSetGlobalSection - Set the PetscSection encoding the global data layout for the DM.
4374: Input Parameters:
4375: + dm - The DM
4376: - section - The PetscSection, or NULL
4378: Level: intermediate
4380: Note: Any existing Section will be destroyed
4382: .seealso: DMGetGlobalSection(), DMSetLocalSection()
4383: @*/
4384: PetscErrorCode DMSetGlobalSection(DM dm, PetscSection section)
4385: {
4391: PetscObjectReference((PetscObject)section);
4392: PetscSectionDestroy(&dm->globalSection);
4393: dm->globalSection = section;
4394: #if defined(PETSC_USE_DEBUG)
4395: if (section) {DMDefaultSectionCheckConsistency_Internal(dm, dm->localSection, section);}
4396: #endif
4397: return(0);
4398: }
4400: /*@
4401: DMGetSectionSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set,
4402: it is created from the default PetscSection layouts in the DM.
4404: Input Parameter:
4405: . dm - The DM
4407: Output Parameter:
4408: . sf - The PetscSF
4410: Level: intermediate
4412: Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
4414: .seealso: DMSetSectionSF(), DMCreateSectionSF()
4415: @*/
4416: PetscErrorCode DMGetSectionSF(DM dm, PetscSF *sf)
4417: {
4418: PetscInt nroots;
4424: if (!dm->sectionSF) {
4425: PetscSFCreate(PetscObjectComm((PetscObject)dm),&dm->sectionSF);
4426: }
4427: PetscSFGetGraph(dm->sectionSF, &nroots, NULL, NULL, NULL);
4428: if (nroots < 0) {
4429: PetscSection section, gSection;
4431: DMGetLocalSection(dm, §ion);
4432: if (section) {
4433: DMGetGlobalSection(dm, &gSection);
4434: DMCreateSectionSF(dm, section, gSection);
4435: } else {
4436: *sf = NULL;
4437: return(0);
4438: }
4439: }
4440: *sf = dm->sectionSF;
4441: return(0);
4442: }
4444: /*@
4445: DMSetSectionSF - Set the PetscSF encoding the parallel dof overlap for the DM
4447: Input Parameters:
4448: + dm - The DM
4449: - sf - The PetscSF
4451: Level: intermediate
4453: Note: Any previous SF is destroyed
4455: .seealso: DMGetSectionSF(), DMCreateSectionSF()
4456: @*/
4457: PetscErrorCode DMSetSectionSF(DM dm, PetscSF sf)
4458: {
4464: PetscObjectReference((PetscObject) sf);
4465: PetscSFDestroy(&dm->sectionSF);
4466: dm->sectionSF = sf;
4467: return(0);
4468: }
4470: /*@C
4471: DMCreateSectionSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections
4472: describing the data layout.
4474: Input Parameters:
4475: + dm - The DM
4476: . localSection - PetscSection describing the local data layout
4477: - globalSection - PetscSection describing the global data layout
4479: Notes: One usually uses DMGetSectionSF() to obtain the PetscSF
4481: Level: developer
4483: Developer Note: Since this routine has for arguments the two sections from the DM and puts the resulting PetscSF
4484: directly into the DM, perhaps this function should not take the local and global sections as
4485: input and should just obtain them from the DM?
4487: .seealso: DMGetSectionSF(), DMSetSectionSF(), DMGetLocalSection(), DMGetGlobalSection()
4488: @*/
4489: PetscErrorCode DMCreateSectionSF(DM dm, PetscSection localSection, PetscSection globalSection)
4490: {
4491: MPI_Comm comm;
4492: PetscLayout layout;
4493: const PetscInt *ranges;
4494: PetscInt *local;
4495: PetscSFNode *remote;
4496: PetscInt pStart, pEnd, p, nroots, nleaves = 0, l;
4497: PetscMPIInt size, rank;
4502: PetscObjectGetComm((PetscObject)dm,&comm);
4503: MPI_Comm_size(comm, &size);
4504: MPI_Comm_rank(comm, &rank);
4505: PetscSectionGetChart(globalSection, &pStart, &pEnd);
4506: PetscSectionGetConstrainedStorageSize(globalSection, &nroots);
4507: PetscLayoutCreate(comm, &layout);
4508: PetscLayoutSetBlockSize(layout, 1);
4509: PetscLayoutSetLocalSize(layout, nroots);
4510: PetscLayoutSetUp(layout);
4511: PetscLayoutGetRanges(layout, &ranges);
4512: for (p = pStart; p < pEnd; ++p) {
4513: PetscInt gdof, gcdof;
4515: PetscSectionGetDof(globalSection, p, &gdof);
4516: PetscSectionGetConstraintDof(globalSection, p, &gcdof);
4517: 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));
4518: nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
4519: }
4520: PetscMalloc1(nleaves, &local);
4521: PetscMalloc1(nleaves, &remote);
4522: for (p = pStart, l = 0; p < pEnd; ++p) {
4523: const PetscInt *cind;
4524: PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c;
4526: PetscSectionGetDof(localSection, p, &dof);
4527: PetscSectionGetOffset(localSection, p, &off);
4528: PetscSectionGetConstraintDof(localSection, p, &cdof);
4529: PetscSectionGetConstraintIndices(localSection, p, &cind);
4530: PetscSectionGetDof(globalSection, p, &gdof);
4531: PetscSectionGetConstraintDof(globalSection, p, &gcdof);
4532: PetscSectionGetOffset(globalSection, p, &goff);
4533: if (!gdof) continue; /* Censored point */
4534: gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
4535: if (gsize != dof-cdof) {
4536: 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);
4537: cdof = 0; /* Ignore constraints */
4538: }
4539: for (d = 0, c = 0; d < dof; ++d) {
4540: if ((c < cdof) && (cind[c] == d)) {++c; continue;}
4541: local[l+d-c] = off+d;
4542: }
4543: if (gdof < 0) {
4544: for (d = 0; d < gsize; ++d, ++l) {
4545: PetscInt offset = -(goff+1) + d, r;
4547: PetscFindInt(offset,size+1,ranges,&r);
4548: if (r < 0) r = -(r+2);
4549: 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);
4550: remote[l].rank = r;
4551: remote[l].index = offset - ranges[r];
4552: }
4553: } else {
4554: for (d = 0; d < gsize; ++d, ++l) {
4555: remote[l].rank = rank;
4556: remote[l].index = goff+d - ranges[rank];
4557: }
4558: }
4559: }
4560: if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves);
4561: PetscLayoutDestroy(&layout);
4562: PetscSFSetGraph(dm->sectionSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);
4563: return(0);
4564: }
4566: /*@
4567: DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM.
4569: Input Parameter:
4570: . dm - The DM
4572: Output Parameter:
4573: . sf - The PetscSF
4575: Level: intermediate
4577: Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
4579: .seealso: DMSetPointSF(), DMGetSectionSF(), DMSetSectionSF(), DMCreateSectionSF()
4580: @*/
4581: PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf)
4582: {
4586: *sf = dm->sf;
4587: return(0);
4588: }
4590: /*@
4591: DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM.
4593: Input Parameters:
4594: + dm - The DM
4595: - sf - The PetscSF
4597: Level: intermediate
4599: .seealso: DMGetPointSF(), DMGetSectionSF(), DMSetSectionSF(), DMCreateSectionSF()
4600: @*/
4601: PetscErrorCode DMSetPointSF(DM dm, PetscSF sf)
4602: {
4608: PetscObjectReference((PetscObject) sf);
4609: PetscSFDestroy(&dm->sf);
4610: dm->sf = sf;
4611: return(0);
4612: }
4614: static PetscErrorCode DMSetDefaultAdjacency_Private(DM dm, PetscInt f, PetscObject disc)
4615: {
4616: PetscClassId id;
4620: PetscObjectGetClassId(disc, &id);
4621: if (id == PETSCFE_CLASSID) {
4622: DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE);
4623: } else if (id == PETSCFV_CLASSID) {
4624: DMSetAdjacency(dm, f, PETSC_TRUE, PETSC_FALSE);
4625: } else {
4626: DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE);
4627: }
4628: return(0);
4629: }
4631: static PetscErrorCode DMFieldEnlarge_Static(DM dm, PetscInt NfNew)
4632: {
4633: RegionField *tmpr;
4634: PetscInt Nf = dm->Nf, f;
4638: if (Nf >= NfNew) return(0);
4639: PetscMalloc1(NfNew, &tmpr);
4640: for (f = 0; f < Nf; ++f) tmpr[f] = dm->fields[f];
4641: for (f = Nf; f < NfNew; ++f) {tmpr[f].disc = NULL; tmpr[f].label = NULL;}
4642: PetscFree(dm->fields);
4643: dm->Nf = NfNew;
4644: dm->fields = tmpr;
4645: return(0);
4646: }
4648: /*@
4649: DMClearFields - Remove all fields from the DM
4651: Logically collective on dm
4653: Input Parameter:
4654: . dm - The DM
4656: Level: intermediate
4658: .seealso: DMGetNumFields(), DMSetNumFields(), DMSetField()
4659: @*/
4660: PetscErrorCode DMClearFields(DM dm)
4661: {
4662: PetscInt f;
4667: for (f = 0; f < dm->Nf; ++f) {
4668: PetscObjectDestroy(&dm->fields[f].disc);
4669: DMLabelDestroy(&dm->fields[f].label);
4670: }
4671: PetscFree(dm->fields);
4672: dm->fields = NULL;
4673: dm->Nf = 0;
4674: return(0);
4675: }
4677: /*@
4678: DMGetNumFields - Get the number of fields in the DM
4680: Not collective
4682: Input Parameter:
4683: . dm - The DM
4685: Output Parameter:
4686: . Nf - The number of fields
4688: Level: intermediate
4690: .seealso: DMSetNumFields(), DMSetField()
4691: @*/
4692: PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields)
4693: {
4697: *numFields = dm->Nf;
4698: return(0);
4699: }
4701: /*@
4702: DMSetNumFields - Set the number of fields in the DM
4704: Logically collective on dm
4706: Input Parameters:
4707: + dm - The DM
4708: - Nf - The number of fields
4710: Level: intermediate
4712: .seealso: DMGetNumFields(), DMSetField()
4713: @*/
4714: PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields)
4715: {
4716: PetscInt Nf, f;
4721: DMGetNumFields(dm, &Nf);
4722: for (f = Nf; f < numFields; ++f) {
4723: PetscContainer obj;
4725: PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);
4726: DMAddField(dm, NULL, (PetscObject) obj);
4727: PetscContainerDestroy(&obj);
4728: }
4729: return(0);
4730: }
4732: /*@
4733: DMGetField - Return the discretization object for a given DM field
4735: Not collective
4737: Input Parameters:
4738: + dm - The DM
4739: - f - The field number
4741: Output Parameters:
4742: + label - The label indicating the support of the field, or NULL for the entire mesh
4743: - field - The discretization object
4745: Level: intermediate
4747: .seealso: DMAddField(), DMSetField()
4748: @*/
4749: PetscErrorCode DMGetField(DM dm, PetscInt f, DMLabel *label, PetscObject *field)
4750: {
4754: if ((f < 0) || (f >= dm->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, dm->Nf);
4755: if (label) *label = dm->fields[f].label;
4756: if (field) *field = dm->fields[f].disc;
4757: return(0);
4758: }
4760: /* Does not clear the DS */
4761: PetscErrorCode DMSetField_Internal(DM dm, PetscInt f, DMLabel label, PetscObject field)
4762: {
4766: DMFieldEnlarge_Static(dm, f+1);
4767: DMLabelDestroy(&dm->fields[f].label);
4768: PetscObjectDestroy(&dm->fields[f].disc);
4769: dm->fields[f].label = label;
4770: dm->fields[f].disc = field;
4771: PetscObjectReference((PetscObject) label);
4772: PetscObjectReference((PetscObject) field);
4773: return(0);
4774: }
4776: /*@
4777: DMSetField - Set the discretization object for a given DM field
4779: Logically collective on dm
4781: Input Parameters:
4782: + dm - The DM
4783: . f - The field number
4784: . label - The label indicating the support of the field, or NULL for the entire mesh
4785: - field - The discretization object
4787: Level: intermediate
4789: .seealso: DMAddField(), DMGetField()
4790: @*/
4791: PetscErrorCode DMSetField(DM dm, PetscInt f, DMLabel label, PetscObject field)
4792: {
4799: if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
4800: DMSetField_Internal(dm, f, label, field);
4801: DMSetDefaultAdjacency_Private(dm, f, field);
4802: DMClearDS(dm);
4803: return(0);
4804: }
4806: /*@
4807: DMAddField - Add the discretization object for the given DM field
4809: Logically collective on dm
4811: Input Parameters:
4812: + dm - The DM
4813: . label - The label indicating the support of the field, or NULL for the entire mesh
4814: - field - The discretization object
4816: Level: intermediate
4818: .seealso: DMSetField(), DMGetField()
4819: @*/
4820: PetscErrorCode DMAddField(DM dm, DMLabel label, PetscObject field)
4821: {
4822: PetscInt Nf = dm->Nf;
4829: DMFieldEnlarge_Static(dm, Nf+1);
4830: dm->fields[Nf].label = label;
4831: dm->fields[Nf].disc = field;
4832: PetscObjectReference((PetscObject) label);
4833: PetscObjectReference((PetscObject) field);
4834: DMSetDefaultAdjacency_Private(dm, Nf, field);
4835: DMClearDS(dm);
4836: return(0);
4837: }
4839: /*@
4840: DMCopyFields - Copy the discretizations for the DM into another DM
4842: Collective on dm
4844: Input Parameter:
4845: . dm - The DM
4847: Output Parameter:
4848: . newdm - The DM
4850: Level: advanced
4852: .seealso: DMGetField(), DMSetField(), DMAddField(), DMCopyDS(), DMGetDS(), DMGetCellDS()
4853: @*/
4854: PetscErrorCode DMCopyFields(DM dm, DM newdm)
4855: {
4856: PetscInt Nf, f;
4860: if (dm == newdm) return(0);
4861: DMGetNumFields(dm, &Nf);
4862: DMClearFields(newdm);
4863: for (f = 0; f < Nf; ++f) {
4864: DMLabel label;
4865: PetscObject field;
4866: PetscBool useCone, useClosure;
4868: DMGetField(dm, f, &label, &field);
4869: DMSetField(newdm, f, label, field);
4870: DMGetAdjacency(dm, f, &useCone, &useClosure);
4871: DMSetAdjacency(newdm, f, useCone, useClosure);
4872: }
4873: return(0);
4874: }
4876: /*@
4877: DMGetAdjacency - Returns the flags for determining variable influence
4879: Not collective
4881: Input Parameters:
4882: + dm - The DM object
4883: - f - The field number, or PETSC_DEFAULT for the default adjacency
4885: Output Parameter:
4886: + useCone - Flag for variable influence starting with the cone operation
4887: - useClosure - Flag for variable influence using transitive closure
4889: Notes:
4890: $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE
4891: $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE
4892: $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE
4893: Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another.
4895: Level: developer
4897: .seealso: DMSetAdjacency(), DMGetField(), DMSetField()
4898: @*/
4899: PetscErrorCode DMGetAdjacency(DM dm, PetscInt f, PetscBool *useCone, PetscBool *useClosure)
4900: {
4905: if (f < 0) {
4906: if (useCone) *useCone = dm->adjacency[0];
4907: if (useClosure) *useClosure = dm->adjacency[1];
4908: } else {
4909: PetscInt Nf;
4912: DMGetNumFields(dm, &Nf);
4913: if (f >= Nf) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, Nf);
4914: if (useCone) *useCone = dm->fields[f].adjacency[0];
4915: if (useClosure) *useClosure = dm->fields[f].adjacency[1];
4916: }
4917: return(0);
4918: }
4920: /*@
4921: DMSetAdjacency - Set the flags for determining variable influence
4923: Not collective
4925: Input Parameters:
4926: + dm - The DM object
4927: . f - The field number
4928: . useCone - Flag for variable influence starting with the cone operation
4929: - useClosure - Flag for variable influence using transitive closure
4931: Notes:
4932: $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE
4933: $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE
4934: $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE
4935: Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another.
4937: Level: developer
4939: .seealso: DMGetAdjacency(), DMGetField(), DMSetField()
4940: @*/
4941: PetscErrorCode DMSetAdjacency(DM dm, PetscInt f, PetscBool useCone, PetscBool useClosure)
4942: {
4945: if (f < 0) {
4946: dm->adjacency[0] = useCone;
4947: dm->adjacency[1] = useClosure;
4948: } else {
4949: PetscInt Nf;
4952: DMGetNumFields(dm, &Nf);
4953: if (f >= Nf) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, Nf);
4954: dm->fields[f].adjacency[0] = useCone;
4955: dm->fields[f].adjacency[1] = useClosure;
4956: }
4957: return(0);
4958: }
4960: /*@
4961: DMGetBasicAdjacency - Returns the flags for determining variable influence, using either the default or field 0 if it is defined
4963: Not collective
4965: Input Parameters:
4966: . dm - The DM object
4968: Output Parameter:
4969: + useCone - Flag for variable influence starting with the cone operation
4970: - useClosure - Flag for variable influence using transitive closure
4972: Notes:
4973: $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE
4974: $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE
4975: $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE
4977: Level: developer
4979: .seealso: DMSetBasicAdjacency(), DMGetField(), DMSetField()
4980: @*/
4981: PetscErrorCode DMGetBasicAdjacency(DM dm, PetscBool *useCone, PetscBool *useClosure)
4982: {
4983: PetscInt Nf;
4990: DMGetNumFields(dm, &Nf);
4991: if (!Nf) {
4992: DMGetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure);
4993: } else {
4994: DMGetAdjacency(dm, 0, useCone, useClosure);
4995: }
4996: return(0);
4997: }
4999: /*@
5000: DMSetBasicAdjacency - Set the flags for determining variable influence, using either the default or field 0 if it is defined
5002: Not collective
5004: Input Parameters:
5005: + dm - The DM object
5006: . useCone - Flag for variable influence starting with the cone operation
5007: - useClosure - Flag for variable influence using transitive closure
5009: Notes:
5010: $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE
5011: $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE
5012: $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE
5014: Level: developer
5016: .seealso: DMGetBasicAdjacency(), DMGetField(), DMSetField()
5017: @*/
5018: PetscErrorCode DMSetBasicAdjacency(DM dm, PetscBool useCone, PetscBool useClosure)
5019: {
5020: PetscInt Nf;
5025: DMGetNumFields(dm, &Nf);
5026: if (!Nf) {
5027: DMSetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure);
5028: } else {
5029: DMSetAdjacency(dm, 0, useCone, useClosure);
5030: }
5031: return(0);
5032: }
5034: /* Complete labels that are being used for FEM BC */
5035: static PetscErrorCode DMCompleteBoundaryLabel_Internal(DM dm, PetscDS ds, PetscInt field, PetscInt bdNum, const char labelname[])
5036: {
5037: DMLabel label;
5038: PetscObject obj;
5039: PetscClassId id;
5040: PetscInt Nbd, bd;
5041: PetscBool isFE = PETSC_FALSE;
5042: PetscBool duplicate = PETSC_FALSE;
5046: DMGetField(dm, field, NULL, &obj);
5047: PetscObjectGetClassId(obj, &id);
5048: if (id == PETSCFE_CLASSID) isFE = PETSC_TRUE;
5049: DMGetLabel(dm, labelname, &label);
5050: if (isFE && label) {
5051: /* Only want to modify label once */
5052: PetscDSGetNumBoundary(ds, &Nbd);
5053: for (bd = 0; bd < PetscMin(Nbd, bdNum); ++bd) {
5054: const char *lname;
5056: PetscDSGetBoundary(ds, bd, NULL, NULL, &lname, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
5057: PetscStrcmp(lname, labelname, &duplicate);
5058: if (duplicate) break;
5059: }
5060: if (!duplicate) {
5061: DM plex;
5063: DMConvert(dm, DMPLEX, &plex);
5064: if (plex) {DMPlexLabelComplete(plex, label);}
5065: DMDestroy(&plex);
5066: }
5067: }
5068: return(0);
5069: }
5071: static PetscErrorCode DMDSEnlarge_Static(DM dm, PetscInt NdsNew)
5072: {
5073: DMSpace *tmpd;
5074: PetscInt Nds = dm->Nds, s;
5078: if (Nds >= NdsNew) return(0);
5079: PetscMalloc1(NdsNew, &tmpd);
5080: for (s = 0; s < Nds; ++s) tmpd[s] = dm->probs[s];
5081: for (s = Nds; s < NdsNew; ++s) {tmpd[s].ds = NULL; tmpd[s].label = NULL; tmpd[s].fields = NULL;}
5082: PetscFree(dm->probs);
5083: dm->Nds = NdsNew;
5084: dm->probs = tmpd;
5085: return(0);
5086: }
5088: /*@
5089: DMGetNumDS - Get the number of discrete systems in the DM
5091: Not collective
5093: Input Parameter:
5094: . dm - The DM
5096: Output Parameter:
5097: . Nds - The number of PetscDS objects
5099: Level: intermediate
5101: .seealso: DMGetDS(), DMGetCellDS()
5102: @*/
5103: PetscErrorCode DMGetNumDS(DM dm, PetscInt *Nds)
5104: {
5108: *Nds = dm->Nds;
5109: return(0);
5110: }
5112: /*@
5113: DMClearDS - Remove all discrete systems from the DM
5115: Logically collective on dm
5117: Input Parameter:
5118: . dm - The DM
5120: Level: intermediate
5122: .seealso: DMGetNumDS(), DMGetDS(), DMSetField()
5123: @*/
5124: PetscErrorCode DMClearDS(DM dm)
5125: {
5126: PetscInt s;
5131: for (s = 0; s < dm->Nds; ++s) {
5132: PetscDSDestroy(&dm->probs[s].ds);
5133: DMLabelDestroy(&dm->probs[s].label);
5134: ISDestroy(&dm->probs[s].fields);
5135: }
5136: PetscFree(dm->probs);
5137: dm->probs = NULL;
5138: dm->Nds = 0;
5139: return(0);
5140: }
5142: /*@
5143: DMGetDS - Get the default PetscDS
5145: Not collective
5147: Input Parameter:
5148: . dm - The DM
5150: Output Parameter:
5151: . prob - The default PetscDS
5153: Level: intermediate
5155: .seealso: DMGetCellDS(), DMGetRegionDS()
5156: @*/
5157: PetscErrorCode DMGetDS(DM dm, PetscDS *prob)
5158: {
5164: if (dm->Nds <= 0) {
5165: PetscDS ds;
5167: PetscDSCreate(PetscObjectComm((PetscObject) dm), &ds);
5168: DMSetRegionDS(dm, NULL, NULL, ds);
5169: PetscDSDestroy(&ds);
5170: }
5171: *prob = dm->probs[0].ds;
5172: return(0);
5173: }
5175: /*@
5176: DMGetCellDS - Get the PetscDS defined on a given cell
5178: Not collective
5180: Input Parameters:
5181: + dm - The DM
5182: - point - Cell for the DS
5184: Output Parameter:
5185: . prob - The PetscDS defined on the given cell
5187: Level: developer
5189: .seealso: DMGetDS(), DMSetRegionDS()
5190: @*/
5191: PetscErrorCode DMGetCellDS(DM dm, PetscInt point, PetscDS *prob)
5192: {
5193: PetscDS probDef = NULL;
5194: PetscInt s;
5200: if (point < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point cannot be negative: %D", point);
5201: *prob = NULL;
5202: for (s = 0; s < dm->Nds; ++s) {
5203: PetscInt val;
5205: if (!dm->probs[s].label) {probDef = dm->probs[s].ds;}
5206: else {
5207: DMLabelGetValue(dm->probs[s].label, point, &val);
5208: if (val >= 0) {*prob = dm->probs[s].ds; break;}
5209: }
5210: }
5211: if (!*prob) *prob = probDef;
5212: return(0);
5213: }
5215: /*@
5216: DMGetRegionDS - Get the PetscDS for a given mesh region, defined by a DMLabel
5218: Not collective
5220: Input Parameters:
5221: + dm - The DM
5222: - label - The DMLabel defining the mesh region, or NULL for the entire mesh
5224: Output Parameters:
5225: + fields - The IS containing the DM field numbers for the fields in this DS, or NULL
5226: - prob - The PetscDS defined on the given region, or NULL
5228: Note: If the label is missing, this function returns an error
5230: Level: advanced
5232: .seealso: DMGetRegionNumDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS()
5233: @*/
5234: PetscErrorCode DMGetRegionDS(DM dm, DMLabel label, IS *fields, PetscDS *ds)
5235: {
5236: PetscInt Nds = dm->Nds, s;
5243: for (s = 0; s < Nds; ++s) {
5244: if (dm->probs[s].label == label) {
5245: if (fields) *fields = dm->probs[s].fields;
5246: if (ds) *ds = dm->probs[s].ds;
5247: return(0);
5248: }
5249: }
5250: return(0);
5251: }
5253: /*@
5254: DMSetRegionDS - Set the PetscDS for a given mesh region, defined by a DMLabel
5256: Collective on dm
5258: Input Parameters:
5259: + dm - The DM
5260: . label - The DMLabel defining the mesh region, or NULL for the entire mesh
5261: . fields - The IS containing the DM field numbers for the fields in this DS, or NULL for all fields
5262: - prob - The PetscDS defined on the given cell
5264: Note: If the label has a DS defined, it will be replaced. Otherwise, it will be added to the DM. If DS is replaced,
5265: the fields argument is ignored.
5267: Level: advanced
5269: .seealso: DMGetRegionDS(), DMSetRegionNumDS(), DMGetDS(), DMGetCellDS()
5270: @*/
5271: PetscErrorCode DMSetRegionDS(DM dm, DMLabel label, IS fields, PetscDS ds)
5272: {
5273: PetscInt Nds = dm->Nds, s;
5280: for (s = 0; s < Nds; ++s) {
5281: if (dm->probs[s].label == label) {
5282: PetscDSDestroy(&dm->probs[s].ds);
5283: dm->probs[s].ds = ds;
5284: return(0);
5285: }
5286: }
5287: DMDSEnlarge_Static(dm, Nds+1);
5288: PetscObjectReference((PetscObject) label);
5289: PetscObjectReference((PetscObject) fields);
5290: PetscObjectReference((PetscObject) ds);
5291: if (!label) {
5292: /* Put the NULL label at the front, so it is returned as the default */
5293: for (s = Nds-1; s >=0; --s) dm->probs[s+1] = dm->probs[s];
5294: Nds = 0;
5295: }
5296: dm->probs[Nds].label = label;
5297: dm->probs[Nds].fields = fields;
5298: dm->probs[Nds].ds = ds;
5299: return(0);
5300: }
5302: /*@
5303: DMGetRegionNumDS - Get the PetscDS for a given mesh region, defined by the region number
5305: Not collective
5307: Input Parameters:
5308: + dm - The DM
5309: - num - The region number, in [0, Nds)
5311: Output Parameters:
5312: + label - The region label, or NULL
5313: . fields - The IS containing the DM field numbers for the fields in this DS, or NULL
5314: - ds - The PetscDS defined on the given region, or NULL
5316: Level: advanced
5318: .seealso: DMGetRegionDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS()
5319: @*/
5320: PetscErrorCode DMGetRegionNumDS(DM dm, PetscInt num, DMLabel *label, IS *fields, PetscDS *ds)
5321: {
5322: PetscInt Nds;
5327: DMGetNumDS(dm, &Nds);
5328: if ((num < 0) || (num >= Nds)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Region number %D is not in [0, %D)", num, Nds);
5329: if (label) {
5331: *label = dm->probs[num].label;
5332: }
5333: if (fields) {
5335: *fields = dm->probs[num].fields;
5336: }
5337: if (ds) {
5339: *ds = dm->probs[num].ds;
5340: }
5341: return(0);
5342: }
5344: /*@
5345: DMSetRegionNumDS - Set the PetscDS for a given mesh region, defined by the region number
5347: Not collective
5349: Input Parameters:
5350: + dm - The DM
5351: . num - The region number, in [0, Nds)
5352: . label - The region label, or NULL
5353: . fields - The IS containing the DM field numbers for the fields in this DS, or NULL to prevent setting
5354: - ds - The PetscDS defined on the given region, or NULL to prevent setting
5356: Level: advanced
5358: .seealso: DMGetRegionDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS()
5359: @*/
5360: PetscErrorCode DMSetRegionNumDS(DM dm, PetscInt num, DMLabel label, IS fields, PetscDS ds)
5361: {
5362: PetscInt Nds;
5368: DMGetNumDS(dm, &Nds);
5369: if ((num < 0) || (num >= Nds)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Region number %D is not in [0, %D)", num, Nds);
5370: PetscObjectReference((PetscObject) label);
5371: DMLabelDestroy(&dm->probs[num].label);
5372: dm->probs[num].label = label;
5373: if (fields) {
5375: PetscObjectReference((PetscObject) fields);
5376: ISDestroy(&dm->probs[num].fields);
5377: dm->probs[num].fields = fields;
5378: }
5379: if (ds) {
5381: PetscObjectReference((PetscObject) ds);
5382: PetscDSDestroy(&dm->probs[num].ds);
5383: dm->probs[num].ds = ds;
5384: }
5385: return(0);
5386: }
5388: /*@
5389: DMFindRegionNum - Find the region number for a given PetscDS, or -1 if it is not found.
5391: Not collective
5393: Input Parameters:
5394: + dm - The DM
5395: - ds - The PetscDS defined on the given region
5397: Output Parameter:
5398: . num - The region number, in [0, Nds), or -1 if not found
5400: Level: advanced
5402: .seealso: DMGetRegionNumDS(), DMGetRegionDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS()
5403: @*/
5404: PetscErrorCode DMFindRegionNum(DM dm, PetscDS ds, PetscInt *num)
5405: {
5406: PetscInt Nds, n;
5413: DMGetNumDS(dm, &Nds);
5414: for (n = 0; n < Nds; ++n) if (ds == dm->probs[n].ds) break;
5415: if (n >= Nds) *num = -1;
5416: else *num = n;
5417: return(0);
5418: }
5420: /*@
5421: DMCreateDS - Create the discrete systems for the DM based upon the fields added to the DM
5423: Collective on dm
5425: Input Parameter:
5426: . dm - The DM
5428: Note: If the label has a DS defined, it will be replaced. Otherwise, it will be added to the DM.
5430: Level: intermediate
5432: .seealso: DMSetField, DMAddField(), DMGetDS(), DMGetCellDS(), DMGetRegionDS(), DMSetRegionDS()
5433: @*/
5434: PetscErrorCode DMCreateDS(DM dm)
5435: {
5436: MPI_Comm comm;
5437: PetscDS dsDef;
5438: DMLabel *labelSet;
5439: PetscInt dE, Nf = dm->Nf, f, s, Nl, l, Ndef;
5440: PetscBool doSetup = PETSC_TRUE;
5445: if (!dm->fields) return(0);
5446: PetscObjectGetComm((PetscObject) dm, &comm);
5447: DMGetCoordinateDim(dm, &dE);
5448: /* Determine how many regions we have */
5449: PetscMalloc1(Nf, &labelSet);
5450: Nl = 0;
5451: Ndef = 0;
5452: for (f = 0; f < Nf; ++f) {
5453: DMLabel label = dm->fields[f].label;
5454: PetscInt l;
5456: if (!label) {++Ndef; continue;}
5457: for (l = 0; l < Nl; ++l) if (label == labelSet[l]) break;
5458: if (l < Nl) continue;
5459: labelSet[Nl++] = label;
5460: }
5461: /* Create default DS if there are no labels to intersect with */
5462: DMGetRegionDS(dm, NULL, NULL, &dsDef);
5463: if (!dsDef && Ndef && !Nl) {
5464: IS fields;
5465: PetscInt *fld, nf;
5467: for (f = 0, nf = 0; f < Nf; ++f) if (!dm->fields[f].label) ++nf;
5468: if (nf) {
5469: PetscMalloc1(nf, &fld);
5470: for (f = 0, nf = 0; f < Nf; ++f) if (!dm->fields[f].label) fld[nf++] = f;
5471: ISCreate(PETSC_COMM_SELF, &fields);
5472: PetscObjectSetOptionsPrefix((PetscObject) fields, "dm_fields_");
5473: ISSetType(fields, ISGENERAL);
5474: ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER);
5476: PetscDSCreate(comm, &dsDef);
5477: DMSetRegionDS(dm, NULL, fields, dsDef);
5478: PetscDSDestroy(&dsDef);
5479: ISDestroy(&fields);
5480: }
5481: }
5482: DMGetRegionDS(dm, NULL, NULL, &dsDef);
5483: if (dsDef) {PetscDSSetCoordinateDimension(dsDef, dE);}
5484: /* Intersect labels with default fields */
5485: if (Ndef && Nl) {
5486: DM plex;
5487: DMLabel cellLabel;
5488: IS fieldIS, allcellIS, defcellIS = NULL;
5489: PetscInt *fields;
5490: const PetscInt *cells;
5491: PetscInt depth, nf = 0, n, c;
5493: DMConvert(dm, DMPLEX, &plex);
5494: DMPlexGetDepth(plex, &depth);
5495: DMGetStratumIS(plex, "dim", depth, &allcellIS);
5496: if (!allcellIS) {DMGetStratumIS(plex, "depth", depth, &allcellIS);}
5497: for (l = 0; l < Nl; ++l) {
5498: DMLabel label = labelSet[l];
5499: IS pointIS;
5501: ISDestroy(&defcellIS);
5502: DMLabelGetStratumIS(label, 1, &pointIS);
5503: ISDifference(allcellIS, pointIS, &defcellIS);
5504: ISDestroy(&pointIS);
5505: }
5506: ISDestroy(&allcellIS);
5508: DMLabelCreate(PETSC_COMM_SELF, "defaultCells", &cellLabel);
5509: ISGetLocalSize(defcellIS, &n);
5510: ISGetIndices(defcellIS, &cells);
5511: for (c = 0; c < n; ++c) {DMLabelSetValue(cellLabel, cells[c], 1);}
5512: ISRestoreIndices(defcellIS, &cells);
5513: ISDestroy(&defcellIS);
5514: DMPlexLabelComplete(plex, cellLabel);
5516: PetscMalloc1(Ndef, &fields);
5517: for (f = 0; f < Nf; ++f) if (!dm->fields[f].label) fields[nf++] = f;
5518: ISCreate(PETSC_COMM_SELF, &fieldIS);
5519: PetscObjectSetOptionsPrefix((PetscObject) fieldIS, "dm_fields_");
5520: ISSetType(fieldIS, ISGENERAL);
5521: ISGeneralSetIndices(fieldIS, nf, fields, PETSC_OWN_POINTER);
5523: PetscDSCreate(comm, &dsDef);
5524: DMSetRegionDS(dm, cellLabel, fieldIS, dsDef);
5525: DMLabelDestroy(&cellLabel);
5526: PetscDSSetCoordinateDimension(dsDef, dE);
5527: PetscDSDestroy(&dsDef);
5528: ISDestroy(&fieldIS);
5529: DMDestroy(&plex);
5530: }
5531: /* Create label DSes
5532: - WE ONLY SUPPORT IDENTICAL OR DISJOINT LABELS
5533: */
5534: /* TODO Should check that labels are disjoint */
5535: for (l = 0; l < Nl; ++l) {
5536: DMLabel label = labelSet[l];
5537: PetscDS ds;
5538: IS fields;
5539: PetscInt *fld, nf;
5541: PetscDSCreate(comm, &ds);
5542: for (f = 0, nf = 0; f < Nf; ++f) if (label == dm->fields[f].label || !dm->fields[f].label) ++nf;
5543: PetscMalloc1(nf, &fld);
5544: for (f = 0, nf = 0; f < Nf; ++f) if (label == dm->fields[f].label || !dm->fields[f].label) fld[nf++] = f;
5545: ISCreate(PETSC_COMM_SELF, &fields);
5546: PetscObjectSetOptionsPrefix((PetscObject) fields, "dm_fields_");
5547: ISSetType(fields, ISGENERAL);
5548: ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER);
5549: DMSetRegionDS(dm, label, fields, ds);
5550: ISDestroy(&fields);
5551: PetscDSSetCoordinateDimension(ds, dE);
5552: {
5553: DMPolytopeType ct;
5554: PetscInt lStart, lEnd;
5555: PetscBool isHybridLocal = PETSC_FALSE, isHybrid;
5557: DMLabelGetBounds(label, &lStart, &lEnd);
5558: if (lStart >= 0) {
5559: DMPlexGetCellType(dm, lStart, &ct);
5560: switch (ct) {
5561: case DM_POLYTOPE_POINT_PRISM_TENSOR:
5562: case DM_POLYTOPE_SEG_PRISM_TENSOR:
5563: case DM_POLYTOPE_TRI_PRISM_TENSOR:
5564: case DM_POLYTOPE_QUAD_PRISM_TENSOR:
5565: isHybridLocal = PETSC_TRUE;break;
5566: default: break;
5567: }
5568: }
5569: MPI_Allreduce(&isHybridLocal, &isHybrid, 1, MPIU_BOOL, MPI_LOR, comm);
5570: PetscDSSetHybrid(ds, isHybrid);
5571: }
5572: PetscDSDestroy(&ds);
5573: }
5574: PetscFree(labelSet);
5575: /* Set fields in DSes */
5576: for (s = 0; s < dm->Nds; ++s) {
5577: PetscDS ds = dm->probs[s].ds;
5578: IS fields = dm->probs[s].fields;
5579: const PetscInt *fld;
5580: PetscInt nf;
5582: ISGetLocalSize(fields, &nf);
5583: ISGetIndices(fields, &fld);
5584: for (f = 0; f < nf; ++f) {
5585: PetscObject disc = dm->fields[fld[f]].disc;
5586: PetscBool isHybrid;
5587: PetscClassId id;
5589: PetscDSGetHybrid(ds, &isHybrid);
5590: /* If this is a cohesive cell, then it needs the lower dimensional discretization */
5591: if (isHybrid && f < nf-1) {PetscFEGetHeightSubspace((PetscFE) disc, 1, (PetscFE *) &disc);}
5592: PetscDSSetDiscretization(ds, f, disc);
5593: /* We allow people to have placeholder fields and construct the Section by hand */
5594: PetscObjectGetClassId(disc, &id);
5595: if ((id != PETSCFE_CLASSID) && (id != PETSCFV_CLASSID)) doSetup = PETSC_FALSE;
5596: }
5597: ISRestoreIndices(fields, &fld);
5598: }
5599: /* Setup DSes */
5600: if (doSetup) {
5601: for (s = 0; s < dm->Nds; ++s) {PetscDSSetUp(dm->probs[s].ds);}
5602: }
5603: return(0);
5604: }
5606: /*@
5607: DMComputeExactSolution - Compute the exact solution for a given DM, using the PetscDS information.
5609: Collective on DM
5611: Input Parameters:
5612: + dm - The DM
5613: - time - The time
5615: Output Parameters:
5616: + u - The vector will be filled with exact solution values, or NULL
5617: - u_t - The vector will be filled with the time derivative of exact solution values, or NULL
5619: Note: The user must call PetscDSSetExactSolution() beforehand
5621: Level: developer
5623: .seealso: PetscDSSetExactSolution()
5624: @*/
5625: PetscErrorCode DMComputeExactSolution(DM dm, PetscReal time, Vec u, Vec u_t)
5626: {
5627: PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx);
5628: void **ectxs;
5629: PetscInt Nf, Nds, s;
5630: PetscErrorCode ierr;
5636: DMGetNumFields(dm, &Nf);
5637: PetscMalloc2(Nf, &exacts, Nf, &ectxs);
5638: DMGetNumDS(dm, &Nds);
5639: for (s = 0; s < Nds; ++s) {
5640: PetscDS ds;
5641: DMLabel label;
5642: IS fieldIS;
5643: const PetscInt *fields, id = 1;
5644: PetscInt dsNf, f;
5646: DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds);
5647: PetscDSGetNumFields(ds, &dsNf);
5648: ISGetIndices(fieldIS, &fields);
5649: PetscArrayzero(exacts, Nf);
5650: PetscArrayzero(ectxs, Nf);
5651: if (u) {
5652: for (f = 0; f < dsNf; ++f) {
5653: const PetscInt field = fields[f];
5654: PetscDSGetExactSolution(ds, field, &exacts[field], &ectxs[field]);
5655: }
5656: ISRestoreIndices(fieldIS, &fields);
5657: if (label) {
5658: DMProjectFunctionLabel(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, u);
5659: } else {
5660: DMProjectFunction(dm, time, exacts, ectxs, INSERT_ALL_VALUES, u);
5661: }
5662: }
5663: if (u_t) {
5664: PetscArrayzero(exacts, Nf);
5665: PetscArrayzero(ectxs, Nf);
5666: for (f = 0; f < dsNf; ++f) {
5667: const PetscInt field = fields[f];
5668: PetscDSGetExactSolutionTimeDerivative(ds, field, &exacts[field], &ectxs[field]);
5669: }
5670: ISRestoreIndices(fieldIS, &fields);
5671: if (label) {
5672: DMProjectFunctionLabel(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, u_t);
5673: } else {
5674: DMProjectFunction(dm, time, exacts, ectxs, INSERT_ALL_VALUES, u_t);
5675: }
5676: }
5677: }
5678: if (u) {
5679: PetscObjectSetName((PetscObject) u, "Exact Solution");
5680: PetscObjectSetOptionsPrefix((PetscObject) u, "exact_");
5681: }
5682: if (u_t) {
5683: PetscObjectSetName((PetscObject) u, "Exact Solution Time Derivative");
5684: PetscObjectSetOptionsPrefix((PetscObject) u_t, "exact_t_");
5685: }
5686: PetscFree2(exacts, ectxs);
5687: return(0);
5688: }
5690: /*@
5691: DMCopyDS - Copy the discrete systems for the DM into another DM
5693: Collective on dm
5695: Input Parameter:
5696: . dm - The DM
5698: Output Parameter:
5699: . newdm - The DM
5701: Level: advanced
5703: .seealso: DMCopyFields(), DMAddField(), DMGetDS(), DMGetCellDS(), DMGetRegionDS(), DMSetRegionDS()
5704: @*/
5705: PetscErrorCode DMCopyDS(DM dm, DM newdm)
5706: {
5707: PetscInt Nds, s;
5711: if (dm == newdm) return(0);
5712: DMGetNumDS(dm, &Nds);
5713: DMClearDS(newdm);
5714: for (s = 0; s < Nds; ++s) {
5715: DMLabel label;
5716: IS fields;
5717: PetscDS ds;
5718: PetscInt Nbd, bd;
5720: DMGetRegionNumDS(dm, s, &label, &fields, &ds);
5721: DMSetRegionDS(newdm, label, fields, ds);
5722: PetscDSGetNumBoundary(ds, &Nbd);
5723: for (bd = 0; bd < Nbd; ++bd) {
5724: const char *labelname, *name;
5725: PetscInt field;
5727: /* Do not check if label exists here, since p4est calls this for the reference tree which does not have the labels */
5728: PetscDSGetBoundary(ds, bd, NULL, &name, &labelname, &field, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
5729: DMCompleteBoundaryLabel_Internal(newdm, ds, field, bd, labelname);
5730: }
5731: }
5732: return(0);
5733: }
5735: /*@
5736: DMCopyDisc - Copy the fields and discrete systems for the DM into another DM
5738: Collective on dm
5740: Input Parameter:
5741: . dm - The DM
5743: Output Parameter:
5744: . newdm - The DM
5746: Level: advanced
5748: .seealso: DMCopyFields(), DMCopyDS()
5749: @*/
5750: PetscErrorCode DMCopyDisc(DM dm, DM newdm)
5751: {
5755: DMCopyFields(dm, newdm);
5756: DMCopyDS(dm, newdm);
5757: return(0);
5758: }
5760: PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx)
5761: {
5762: DM dm_coord,dmc_coord;
5764: Vec coords,ccoords;
5765: Mat inject;
5767: DMGetCoordinateDM(dm,&dm_coord);
5768: DMGetCoordinateDM(dmc,&dmc_coord);
5769: DMGetCoordinates(dm,&coords);
5770: DMGetCoordinates(dmc,&ccoords);
5771: if (coords && !ccoords) {
5772: DMCreateGlobalVector(dmc_coord,&ccoords);
5773: PetscObjectSetName((PetscObject)ccoords,"coordinates");
5774: DMCreateInjection(dmc_coord,dm_coord,&inject);
5775: MatRestrict(inject,coords,ccoords);
5776: MatDestroy(&inject);
5777: DMSetCoordinates(dmc,ccoords);
5778: VecDestroy(&ccoords);
5779: }
5780: return(0);
5781: }
5783: static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx)
5784: {
5785: DM dm_coord,subdm_coord;
5787: Vec coords,ccoords,clcoords;
5788: VecScatter *scat_i,*scat_g;
5790: DMGetCoordinateDM(dm,&dm_coord);
5791: DMGetCoordinateDM(subdm,&subdm_coord);
5792: DMGetCoordinates(dm,&coords);
5793: DMGetCoordinates(subdm,&ccoords);
5794: if (coords && !ccoords) {
5795: DMCreateGlobalVector(subdm_coord,&ccoords);
5796: PetscObjectSetName((PetscObject)ccoords,"coordinates");
5797: DMCreateLocalVector(subdm_coord,&clcoords);
5798: PetscObjectSetName((PetscObject)clcoords,"coordinates");
5799: DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);
5800: VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);
5801: VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);
5802: VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);
5803: VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);
5804: DMSetCoordinates(subdm,ccoords);
5805: DMSetCoordinatesLocal(subdm,clcoords);
5806: VecScatterDestroy(&scat_i[0]);
5807: VecScatterDestroy(&scat_g[0]);
5808: VecDestroy(&ccoords);
5809: VecDestroy(&clcoords);
5810: PetscFree(scat_i);
5811: PetscFree(scat_g);
5812: }
5813: return(0);
5814: }
5816: /*@
5817: DMGetDimension - Return the topological dimension of the DM
5819: Not collective
5821: Input Parameter:
5822: . dm - The DM
5824: Output Parameter:
5825: . dim - The topological dimension
5827: Level: beginner
5829: .seealso: DMSetDimension(), DMCreate()
5830: @*/
5831: PetscErrorCode DMGetDimension(DM dm, PetscInt *dim)
5832: {
5836: *dim = dm->dim;
5837: return(0);
5838: }
5840: /*@
5841: DMSetDimension - Set the topological dimension of the DM
5843: Collective on dm
5845: Input Parameters:
5846: + dm - The DM
5847: - dim - The topological dimension
5849: Level: beginner
5851: .seealso: DMGetDimension(), DMCreate()
5852: @*/
5853: PetscErrorCode DMSetDimension(DM dm, PetscInt dim)
5854: {
5855: PetscDS ds;
5861: dm->dim = dim;
5862: DMGetDS(dm, &ds);
5863: if (ds->dimEmbed < 0) {PetscDSSetCoordinateDimension(ds, dm->dim);}
5864: return(0);
5865: }
5867: /*@
5868: DMGetDimPoints - Get the half-open interval for all points of a given dimension
5870: Collective on dm
5872: Input Parameters:
5873: + dm - the DM
5874: - dim - the dimension
5876: Output Parameters:
5877: + pStart - The first point of the given dimension
5878: - pEnd - The first point following points of the given dimension
5880: Note:
5881: The points are vertices in the Hasse diagram encoding the topology. This is explained in
5882: https://arxiv.org/abs/0908.4427. If no points exist of this dimension in the storage scheme,
5883: then the interval is empty.
5885: Level: intermediate
5887: .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum()
5888: @*/
5889: PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
5890: {
5891: PetscInt d;
5896: DMGetDimension(dm, &d);
5897: if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d);
5898: if (!dm->ops->getdimpoints) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "DM type %s does not implement DMGetDimPoints",((PetscObject)dm)->type_name);
5899: (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);
5900: return(0);
5901: }
5903: /*@
5904: DMSetCoordinates - Sets into the DM a global vector that holds the coordinates
5906: Collective on dm
5908: Input Parameters:
5909: + dm - the DM
5910: - c - coordinate vector
5912: Notes:
5913: The coordinates do include those for ghost points, which are in the local vector.
5915: The vector c should be destroyed by the caller.
5917: Level: intermediate
5919: .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM()
5920: @*/
5921: PetscErrorCode DMSetCoordinates(DM dm, Vec c)
5922: {
5928: PetscObjectReference((PetscObject) c);
5929: VecDestroy(&dm->coordinates);
5930: dm->coordinates = c;
5931: VecDestroy(&dm->coordinatesLocal);
5932: DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);
5933: DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);
5934: return(0);
5935: }
5937: /*@
5938: DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates
5940: Not collective
5942: Input Parameters:
5943: + dm - the DM
5944: - c - coordinate vector
5946: Notes:
5947: The coordinates of ghost points can be set using DMSetCoordinates()
5948: followed by DMGetCoordinatesLocal(). This is intended to enable the
5949: setting of ghost coordinates outside of the domain.
5951: The vector c should be destroyed by the caller.
5953: Level: intermediate
5955: .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM()
5956: @*/
5957: PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c)
5958: {
5964: PetscObjectReference((PetscObject) c);
5965: VecDestroy(&dm->coordinatesLocal);
5967: dm->coordinatesLocal = c;
5969: VecDestroy(&dm->coordinates);
5970: return(0);
5971: }
5973: /*@
5974: DMGetCoordinates - Gets a global vector with the coordinates associated with the DM.
5976: Collective on dm
5978: Input Parameter:
5979: . dm - the DM
5981: Output Parameter:
5982: . c - global coordinate vector
5984: Note:
5985: This is a borrowed reference, so the user should NOT destroy this vector
5987: Each process has only the local coordinates (does NOT have the ghost coordinates).
5989: For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
5990: and (x_0,y_0,z_0,x_1,y_1,z_1...)
5992: Level: intermediate
5994: .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM()
5995: @*/
5996: PetscErrorCode DMGetCoordinates(DM dm, Vec *c)
5997: {
6003: if (!dm->coordinates && dm->coordinatesLocal) {
6004: DM cdm = NULL;
6005: PetscBool localized;
6007: DMGetCoordinateDM(dm, &cdm);
6008: DMCreateGlobalVector(cdm, &dm->coordinates);
6009: DMGetCoordinatesLocalized(dm, &localized);
6010: /* Block size is not correctly set by CreateGlobalVector() if coordinates are localized */
6011: if (localized) {
6012: PetscInt cdim;
6014: DMGetCoordinateDim(dm, &cdim);
6015: VecSetBlockSize(dm->coordinates, cdim);
6016: }
6017: PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");
6018: DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);
6019: DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);
6020: }
6021: *c = dm->coordinates;
6022: return(0);
6023: }
6025: /*@
6026: DMGetCoordinatesLocalSetUp - Prepares a local vector of coordinates, so that DMGetCoordinatesLocalNoncollective() can be used as non-collective afterwards.
6028: Collective on dm
6030: Input Parameter:
6031: . dm - the DM
6033: Level: advanced
6035: .seealso: DMGetCoordinatesLocalNoncollective()
6036: @*/
6037: PetscErrorCode DMGetCoordinatesLocalSetUp(DM dm)
6038: {
6043: if (!dm->coordinatesLocal && dm->coordinates) {
6044: DM cdm = NULL;
6045: PetscBool localized;
6047: DMGetCoordinateDM(dm, &cdm);
6048: DMCreateLocalVector(cdm, &dm->coordinatesLocal);
6049: DMGetCoordinatesLocalized(dm, &localized);
6050: /* Block size is not correctly set by CreateLocalVector() if coordinates are localized */
6051: if (localized) {
6052: PetscInt cdim;
6054: DMGetCoordinateDim(dm, &cdim);
6055: VecSetBlockSize(dm->coordinates, cdim);
6056: }
6057: PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");
6058: DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);
6059: DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);
6060: }
6061: return(0);
6062: }
6064: /*@
6065: DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM.
6067: Collective on dm
6069: Input Parameter:
6070: . dm - the DM
6072: Output Parameter:
6073: . c - coordinate vector
6075: Note:
6076: This is a borrowed reference, so the user should NOT destroy this vector
6078: Each process has the local and ghost coordinates
6080: For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
6081: and (x_0,y_0,z_0,x_1,y_1,z_1...)
6083: Level: intermediate
6085: .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM(), DMGetCoordinatesLocalNoncollective()
6086: @*/
6087: PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c)
6088: {
6094: DMGetCoordinatesLocalSetUp(dm);
6095: *c = dm->coordinatesLocal;
6096: return(0);
6097: }
6099: /*@
6100: DMGetCoordinatesLocalNoncollective - Non-collective version of DMGetCoordinatesLocal(). Fails if global coordinates have been set and DMGetCoordinatesLocalSetUp() not called.
6102: Not collective
6104: Input Parameter:
6105: . dm - the DM
6107: Output Parameter:
6108: . c - coordinate vector
6110: Level: advanced
6112: .seealso: DMGetCoordinatesLocalSetUp(), DMGetCoordinatesLocal(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM()
6113: @*/
6114: PetscErrorCode DMGetCoordinatesLocalNoncollective(DM dm, Vec *c)
6115: {
6119: if (!dm->coordinatesLocal && dm->coordinates) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called");
6120: *c = dm->coordinatesLocal;
6121: return(0);
6122: }
6124: /*@
6125: DMGetCoordinatesLocalTuple - Gets a local vector with the coordinates of specified points and section describing its layout.
6127: Not collective
6129: Input Parameter:
6130: + dm - the DM
6131: - p - the IS of points whose coordinates will be returned
6133: Output Parameter:
6134: + pCoordSection - the PetscSection describing the layout of pCoord, i.e. each point corresponds to one point in p, and DOFs correspond to coordinates
6135: - pCoord - the Vec with coordinates of points in p
6137: Note:
6138: DMGetCoordinatesLocalSetUp() must be called first. This function employs DMGetCoordinatesLocalNoncollective() so it is not collective.
6140: This creates a new vector, so the user SHOULD destroy this vector
6142: Each process has the local and ghost coordinates
6144: For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
6145: and (x_0,y_0,z_0,x_1,y_1,z_1...)
6147: Level: advanced
6149: .seealso: DMSetCoordinatesLocal(), DMGetCoordinatesLocal(), DMGetCoordinatesLocalNoncollective(), DMGetCoordinatesLocalSetUp(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM()
6150: @*/
6151: PetscErrorCode DMGetCoordinatesLocalTuple(DM dm, IS p, PetscSection *pCoordSection, Vec *pCoord)
6152: {
6153: PetscSection cs, newcs;
6154: Vec coords;
6155: const PetscScalar *arr;
6156: PetscScalar *newarr=NULL;
6157: PetscInt n;
6158: PetscErrorCode ierr;
6165: if (!dm->coordinatesLocal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called or coordinates not set");
6166: if (!dm->coordinateDM || !dm->coordinateDM->localSection) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM not supported");
6167: cs = dm->coordinateDM->localSection;
6168: coords = dm->coordinatesLocal;
6169: VecGetArrayRead(coords, &arr);
6170: PetscSectionExtractDofsFromArray(cs, MPIU_SCALAR, arr, p, &newcs, pCoord ? ((void**)&newarr) : NULL);
6171: VecRestoreArrayRead(coords, &arr);
6172: if (pCoord) {
6173: PetscSectionGetStorageSize(newcs, &n);
6174: /* set array in two steps to mimic PETSC_OWN_POINTER */
6175: VecCreateSeqWithArray(PetscObjectComm((PetscObject)p), 1, n, NULL, pCoord);
6176: VecReplaceArray(*pCoord, newarr);
6177: } else {
6178: PetscFree(newarr);
6179: }
6180: if (pCoordSection) {*pCoordSection = newcs;}
6181: else {PetscSectionDestroy(&newcs);}
6182: return(0);
6183: }
6185: PetscErrorCode DMGetCoordinateField(DM dm, DMField *field)
6186: {
6192: if (!dm->coordinateField) {
6193: if (dm->ops->createcoordinatefield) {
6194: (*dm->ops->createcoordinatefield)(dm,&dm->coordinateField);
6195: }
6196: }
6197: *field = dm->coordinateField;
6198: return(0);
6199: }
6201: PetscErrorCode DMSetCoordinateField(DM dm, DMField field)
6202: {
6208: PetscObjectReference((PetscObject)field);
6209: DMFieldDestroy(&dm->coordinateField);
6210: dm->coordinateField = field;
6211: return(0);
6212: }
6214: /*@
6215: DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates
6217: Collective on dm
6219: Input Parameter:
6220: . dm - the DM
6222: Output Parameter:
6223: . cdm - coordinate DM
6225: Level: intermediate
6227: .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
6228: @*/
6229: PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm)
6230: {
6236: if (!dm->coordinateDM) {
6237: DM cdm;
6239: if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM");
6240: (*dm->ops->createcoordinatedm)(dm, &cdm);
6241: /* Just in case the DM sets the coordinate DM when creating it (DMP4est can do this, because it may not setup
6242: * until the call to CreateCoordinateDM) */
6243: DMDestroy(&dm->coordinateDM);
6244: dm->coordinateDM = cdm;
6245: }
6246: *cdm = dm->coordinateDM;
6247: return(0);
6248: }
6250: /*@
6251: DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates
6253: Logically Collective on dm
6255: Input Parameters:
6256: + dm - the DM
6257: - cdm - coordinate DM
6259: Level: intermediate
6261: .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
6262: @*/
6263: PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm)
6264: {
6270: PetscObjectReference((PetscObject)cdm);
6271: DMDestroy(&dm->coordinateDM);
6272: dm->coordinateDM = cdm;
6273: return(0);
6274: }
6276: /*@
6277: DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values.
6279: Not Collective
6281: Input Parameter:
6282: . dm - The DM object
6284: Output Parameter:
6285: . dim - The embedding dimension
6287: Level: intermediate
6289: .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetLocalSection(), DMSetLocalSection()
6290: @*/
6291: PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim)
6292: {
6296: if (dm->dimEmbed == PETSC_DEFAULT) {
6297: dm->dimEmbed = dm->dim;
6298: }
6299: *dim = dm->dimEmbed;
6300: return(0);
6301: }
6303: /*@
6304: DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values.
6306: Not Collective
6308: Input Parameters:
6309: + dm - The DM object
6310: - dim - The embedding dimension
6312: Level: intermediate
6314: .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetLocalSection(), DMSetLocalSection()
6315: @*/
6316: PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim)
6317: {
6318: PetscDS ds;
6323: dm->dimEmbed = dim;
6324: DMGetDS(dm, &ds);
6325: PetscDSSetCoordinateDimension(ds, dim);
6326: return(0);
6327: }
6329: /*@
6330: DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh.
6332: Collective on dm
6334: Input Parameter:
6335: . dm - The DM object
6337: Output Parameter:
6338: . section - The PetscSection object
6340: Level: intermediate
6342: .seealso: DMGetCoordinateDM(), DMGetLocalSection(), DMSetLocalSection()
6343: @*/
6344: PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section)
6345: {
6346: DM cdm;
6352: DMGetCoordinateDM(dm, &cdm);
6353: DMGetLocalSection(cdm, section);
6354: return(0);
6355: }
6357: /*@
6358: DMSetCoordinateSection - Set the layout of coordinate values over the mesh.
6360: Not Collective
6362: Input Parameters:
6363: + dm - The DM object
6364: . dim - The embedding dimension, or PETSC_DETERMINE
6365: - section - The PetscSection object
6367: Level: intermediate
6369: .seealso: DMGetCoordinateSection(), DMGetLocalSection(), DMSetLocalSection()
6370: @*/
6371: PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section)
6372: {
6373: DM cdm;
6379: DMGetCoordinateDM(dm, &cdm);
6380: DMSetLocalSection(cdm, section);
6381: if (dim == PETSC_DETERMINE) {
6382: PetscInt d = PETSC_DEFAULT;
6383: PetscInt pStart, pEnd, vStart, vEnd, v, dd;
6385: PetscSectionGetChart(section, &pStart, &pEnd);
6386: DMGetDimPoints(dm, 0, &vStart, &vEnd);
6387: pStart = PetscMax(vStart, pStart);
6388: pEnd = PetscMin(vEnd, pEnd);
6389: for (v = pStart; v < pEnd; ++v) {
6390: PetscSectionGetDof(section, v, &dd);
6391: if (dd) {d = dd; break;}
6392: }
6393: if (d >= 0) {DMSetCoordinateDim(dm, d);}
6394: }
6395: return(0);
6396: }
6398: /*@
6399: DMProjectCoordinates - Project coordinates to a different space
6401: Input Parameters:
6402: + dm - The DM object
6403: - disc - The new coordinate discretization
6405: Level: intermediate
6407: .seealso: DMGetCoordinateField()
6408: @*/
6409: PetscErrorCode DMProjectCoordinates(DM dm, PetscFE disc)
6410: {
6411: PetscObject discOld;
6412: PetscClassId classid;
6413: DM cdmOld,cdmNew;
6414: Vec coordsOld,coordsNew;
6415: Mat matInterp;
6422: DMGetCoordinateDM(dm, &cdmOld);
6423: /* Check current discretization is compatible */
6424: DMGetField(cdmOld, 0, NULL, &discOld);
6425: PetscObjectGetClassId(discOld, &classid);
6426: if (classid != PETSCFE_CLASSID) SETERRQ(PetscObjectComm(discOld), PETSC_ERR_SUP, "Discretization type not supported");
6427: /* Make a fresh clone of the coordinate DM */
6428: DMClone(cdmOld, &cdmNew);
6429: DMSetField(cdmNew, 0, NULL, (PetscObject) disc);
6430: DMCreateDS(cdmNew);
6431: /* Project the coordinate vector from old to new space */
6432: DMGetCoordinates(dm, &coordsOld);
6433: DMCreateGlobalVector(cdmNew, &coordsNew);
6434: DMCreateInterpolation(cdmOld, cdmNew, &matInterp, NULL);
6435: MatInterpolate(matInterp, coordsOld, coordsNew);
6436: MatDestroy(&matInterp);
6437: /* Set new coordinate structures */
6438: DMSetCoordinateField(dm, NULL);
6439: DMSetCoordinateDM(dm, cdmNew);
6440: DMSetCoordinates(dm, coordsNew);
6441: VecDestroy(&coordsNew);
6442: DMDestroy(&cdmNew);
6443: return(0);
6444: }
6446: /*@C
6447: DMGetPeriodicity - Get the description of mesh periodicity
6449: Input Parameters:
6450: . dm - The DM object
6452: Output Parameters:
6453: + per - Whether the DM is periodic or not
6454: . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates
6455: . L - If we assume the mesh is a torus, this is the length of each coordinate
6456: - bd - This describes the type of periodicity in each topological dimension
6458: Level: developer
6460: .seealso: DMGetPeriodicity()
6461: @*/
6462: PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd)
6463: {
6466: if (per) *per = dm->periodic;
6467: if (L) *L = dm->L;
6468: if (maxCell) *maxCell = dm->maxCell;
6469: if (bd) *bd = dm->bdtype;
6470: return(0);
6471: }
6473: /*@C
6474: DMSetPeriodicity - Set the description of mesh periodicity
6476: Input Parameters:
6477: + dm - The DM object
6478: . per - Whether the DM is periodic or not.
6479: . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates. Pass NULL to remove such information.
6480: . L - If we assume the mesh is a torus, this is the length of each coordinate
6481: - bd - This describes the type of periodicity in each topological dimension
6483: Notes: If per is PETSC_TRUE and maxCell is not provided, coordinates need to be already localized, or must be localized by hand by the user.
6485: Level: developer
6487: .seealso: DMGetPeriodicity()
6488: @*/
6489: PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[])
6490: {
6491: PetscInt dim, d;
6500: DMGetDimension(dm, &dim);
6501: if (maxCell) {
6502: if (!dm->maxCell) {PetscMalloc1(dim, &dm->maxCell);}
6503: for (d = 0; d < dim; ++d) dm->maxCell[d] = maxCell[d];
6504: } else { /* remove maxCell information to disable automatic computation of localized vertices */
6505: PetscFree(dm->maxCell);
6506: }
6508: if (L) {
6509: if (!dm->L) {PetscMalloc1(dim, &dm->L);}
6510: for (d = 0; d < dim; ++d) dm->L[d] = L[d];
6511: }
6512: if (bd) {
6513: if (!dm->bdtype) {PetscMalloc1(dim, &dm->bdtype);}
6514: for (d = 0; d < dim; ++d) dm->bdtype[d] = bd[d];
6515: }
6516: dm->periodic = per;
6517: return(0);
6518: }
6520: /*@
6521: 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.
6523: Input Parameters:
6524: + dm - The DM
6525: . in - The input coordinate point (dim numbers)
6526: - endpoint - Include the endpoint L_i
6528: Output Parameter:
6529: . out - The localized coordinate point
6531: Level: developer
6533: .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate()
6534: @*/
6535: PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[])
6536: {
6537: PetscInt dim, d;
6541: DMGetCoordinateDim(dm, &dim);
6542: if (!dm->maxCell) {
6543: for (d = 0; d < dim; ++d) out[d] = in[d];
6544: } else {
6545: if (endpoint) {
6546: for (d = 0; d < dim; ++d) {
6547: 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)) {
6548: out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1);
6549: } else {
6550: out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]);
6551: }
6552: }
6553: } else {
6554: for (d = 0; d < dim; ++d) {
6555: out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]);
6556: }
6557: }
6558: }
6559: return(0);
6560: }
6562: /*
6563: 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.
6565: Input Parameters:
6566: + dm - The DM
6567: . dim - The spatial dimension
6568: . anchor - The anchor point, the input point can be no more than maxCell away from it
6569: - in - The input coordinate point (dim numbers)
6571: Output Parameter:
6572: . out - The localized coordinate point
6574: Level: developer
6576: 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
6578: .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate()
6579: */
6580: PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[])
6581: {
6582: PetscInt d;
6585: if (!dm->maxCell) {
6586: for (d = 0; d < dim; ++d) out[d] = in[d];
6587: } else {
6588: for (d = 0; d < dim; ++d) {
6589: if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) {
6590: out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d];
6591: } else {
6592: out[d] = in[d];
6593: }
6594: }
6595: }
6596: return(0);
6597: }
6599: PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[])
6600: {
6601: PetscInt d;
6604: if (!dm->maxCell) {
6605: for (d = 0; d < dim; ++d) out[d] = in[d];
6606: } else {
6607: for (d = 0; d < dim; ++d) {
6608: if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) {
6609: out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d];
6610: } else {
6611: out[d] = in[d];
6612: }
6613: }
6614: }
6615: return(0);
6616: }
6618: /*
6619: 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.
6621: Input Parameters:
6622: + dm - The DM
6623: . dim - The spatial dimension
6624: . anchor - The anchor point, the input point can be no more than maxCell away from it
6625: . in - The input coordinate delta (dim numbers)
6626: - out - The input coordinate point (dim numbers)
6628: Output Parameter:
6629: . out - The localized coordinate in + out
6631: Level: developer
6633: 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
6635: .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate()
6636: */
6637: PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[])
6638: {
6639: PetscInt d;
6642: if (!dm->maxCell) {
6643: for (d = 0; d < dim; ++d) out[d] += in[d];
6644: } else {
6645: for (d = 0; d < dim; ++d) {
6646: const PetscReal maxC = dm->maxCell[d];
6648: if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > maxC)) {
6649: const PetscScalar newCoord = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d];
6651: if (PetscAbsScalar(newCoord - anchor[d]) > maxC)
6652: SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "%D-Coordinate %g more than %g away from anchor %g", d, (double) PetscRealPart(in[d]), (double) maxC, (double) PetscRealPart(anchor[d]));
6653: out[d] += newCoord;
6654: } else {
6655: out[d] += in[d];
6656: }
6657: }
6658: }
6659: return(0);
6660: }
6662: /*@
6663: DMGetCoordinatesLocalizedLocal - Check if the DM coordinates have been localized for cells on this process
6665: Not collective
6667: Input Parameter:
6668: . dm - The DM
6670: Output Parameter:
6671: areLocalized - True if localized
6673: Level: developer
6675: .seealso: DMLocalizeCoordinates(), DMGetCoordinatesLocalized(), DMSetPeriodicity()
6676: @*/
6677: PetscErrorCode DMGetCoordinatesLocalizedLocal(DM dm,PetscBool *areLocalized)
6678: {
6679: DM cdm;
6680: PetscSection coordSection;
6681: PetscInt cStart, cEnd, sStart, sEnd, c, dof;
6682: PetscBool isPlex, alreadyLocalized;
6688: *areLocalized = PETSC_FALSE;
6690: /* We need some generic way of refering to cells/vertices */
6691: DMGetCoordinateDM(dm, &cdm);
6692: PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);
6693: if (!isPlex) return(0);
6695: DMGetCoordinateSection(dm, &coordSection);
6696: DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);
6697: PetscSectionGetChart(coordSection, &sStart, &sEnd);
6698: alreadyLocalized = PETSC_FALSE;
6699: for (c = cStart; c < cEnd; ++c) {
6700: if (c < sStart || c >= sEnd) continue;
6701: PetscSectionGetDof(coordSection, c, &dof);
6702: if (dof) { alreadyLocalized = PETSC_TRUE; break; }
6703: }
6704: *areLocalized = alreadyLocalized;
6705: return(0);
6706: }
6708: /*@
6709: DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells
6711: Collective on dm
6713: Input Parameter:
6714: . dm - The DM
6716: Output Parameter:
6717: areLocalized - True if localized
6719: Level: developer
6721: .seealso: DMLocalizeCoordinates(), DMSetPeriodicity(), DMGetCoordinatesLocalizedLocal()
6722: @*/
6723: PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized)
6724: {
6725: PetscBool localized;
6731: DMGetCoordinatesLocalizedLocal(dm,&localized);
6732: MPIU_Allreduce(&localized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));
6733: return(0);
6734: }
6736: /*@
6737: DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces
6739: Collective on dm
6741: Input Parameter:
6742: . dm - The DM
6744: Level: developer
6746: .seealso: DMSetPeriodicity(), DMLocalizeCoordinate(), DMLocalizeAddCoordinate()
6747: @*/
6748: PetscErrorCode DMLocalizeCoordinates(DM dm)
6749: {
6750: DM cdm;
6751: PetscSection coordSection, cSection;
6752: Vec coordinates, cVec;
6753: PetscScalar *coords, *coords2, *anchor, *localized;
6754: PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize;
6755: PetscBool alreadyLocalized, alreadyLocalizedGlobal;
6756: PetscInt maxHeight = 0, h;
6757: PetscInt *pStart = NULL, *pEnd = NULL;
6762: if (!dm->periodic) return(0);
6763: DMGetCoordinatesLocalized(dm, &alreadyLocalized);
6764: if (alreadyLocalized) return(0);
6766: /* We need some generic way of refering to cells/vertices */
6767: DMGetCoordinateDM(dm, &cdm);
6768: {
6769: PetscBool isplex;
6771: PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);
6772: if (isplex) {
6773: DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);
6774: DMPlexGetMaxProjectionHeight(cdm,&maxHeight);
6775: DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);
6776: pEnd = &pStart[maxHeight + 1];
6777: newStart = vStart;
6778: newEnd = vEnd;
6779: for (h = 0; h <= maxHeight; h++) {
6780: DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);
6781: newStart = PetscMin(newStart,pStart[h]);
6782: newEnd = PetscMax(newEnd,pEnd[h]);
6783: }
6784: } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM");
6785: }
6786: DMGetCoordinatesLocal(dm, &coordinates);
6787: if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector");
6788: DMGetCoordinateSection(dm, &coordSection);
6789: VecGetBlockSize(coordinates, &bs);
6790: PetscSectionGetChart(coordSection,&sStart,&sEnd);
6792: PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);
6793: PetscSectionSetNumFields(cSection, 1);
6794: PetscSectionGetFieldComponents(coordSection, 0, &Nc);
6795: PetscSectionSetFieldComponents(cSection, 0, Nc);
6796: PetscSectionSetChart(cSection, newStart, newEnd);
6798: DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);
6799: localized = &anchor[bs];
6800: alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE;
6801: for (h = 0; h <= maxHeight; h++) {
6802: PetscInt cStart = pStart[h], cEnd = pEnd[h], c;
6804: for (c = cStart; c < cEnd; ++c) {
6805: PetscScalar *cellCoords = NULL;
6806: PetscInt b;
6808: if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE;
6809: DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
6810: for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b];
6811: for (d = 0; d < dof/bs; ++d) {
6812: DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);
6813: for (b = 0; b < bs; b++) {
6814: if (cellCoords[d*bs + b] != localized[b]) break;
6815: }
6816: if (b < bs) break;
6817: }
6818: if (d < dof/bs) {
6819: if (c >= sStart && c < sEnd) {
6820: PetscInt cdof;
6822: PetscSectionGetDof(coordSection, c, &cdof);
6823: if (cdof != dof) alreadyLocalized = PETSC_FALSE;
6824: }
6825: PetscSectionSetDof(cSection, c, dof);
6826: PetscSectionSetFieldDof(cSection, c, 0, dof);
6827: }
6828: DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
6829: }
6830: }
6831: MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));
6832: if (alreadyLocalizedGlobal) {
6833: DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);
6834: PetscSectionDestroy(&cSection);
6835: DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);
6836: return(0);
6837: }
6838: for (v = vStart; v < vEnd; ++v) {
6839: PetscSectionGetDof(coordSection, v, &dof);
6840: PetscSectionSetDof(cSection, v, dof);
6841: PetscSectionSetFieldDof(cSection, v, 0, dof);
6842: }
6843: PetscSectionSetUp(cSection);
6844: PetscSectionGetStorageSize(cSection, &coordSize);
6845: VecCreate(PETSC_COMM_SELF, &cVec);
6846: PetscObjectSetName((PetscObject)cVec,"coordinates");
6847: VecSetBlockSize(cVec, bs);
6848: VecSetSizes(cVec, coordSize, PETSC_DETERMINE);
6849: VecSetType(cVec, VECSTANDARD);
6850: VecGetArrayRead(coordinates, (const PetscScalar**)&coords);
6851: VecGetArray(cVec, &coords2);
6852: for (v = vStart; v < vEnd; ++v) {
6853: PetscSectionGetDof(coordSection, v, &dof);
6854: PetscSectionGetOffset(coordSection, v, &off);
6855: PetscSectionGetOffset(cSection, v, &off2);
6856: for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d];
6857: }
6858: for (h = 0; h <= maxHeight; h++) {
6859: PetscInt cStart = pStart[h], cEnd = pEnd[h], c;
6861: for (c = cStart; c < cEnd; ++c) {
6862: PetscScalar *cellCoords = NULL;
6863: PetscInt b, cdof;
6865: PetscSectionGetDof(cSection,c,&cdof);
6866: if (!cdof) continue;
6867: DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
6868: PetscSectionGetOffset(cSection, c, &off2);
6869: for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b];
6870: for (d = 0; d < dof/bs; ++d) {DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);}
6871: DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
6872: }
6873: }
6874: DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);
6875: DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);
6876: VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);
6877: VecRestoreArray(cVec, &coords2);
6878: DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);
6879: DMSetCoordinatesLocal(dm, cVec);
6880: VecDestroy(&cVec);
6881: PetscSectionDestroy(&cSection);
6882: return(0);
6883: }
6885: /*@
6886: DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells
6888: Collective on v (see explanation below)
6890: Input Parameters:
6891: + dm - The DM
6892: . v - The Vec of points
6893: . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST
6894: - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point.
6896: Output Parameter:
6897: + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used
6898: - cells - The PetscSF containing the ranks and local indices of the containing points.
6901: Level: developer
6903: Notes:
6904: To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator.
6905: To do a search of all the cells in the distributed mesh, v should have the same communicator as dm.
6907: If *cellSF is NULL on input, a PetscSF will be created.
6908: If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses.
6910: An array that maps each point to its containing cell can be obtained with
6912: $ const PetscSFNode *cells;
6913: $ PetscInt nFound;
6914: $ const PetscInt *found;
6915: $
6916: $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells);
6918: Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is
6919: the index of the cell in its rank's local numbering.
6921: .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType
6922: @*/
6923: PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF)
6924: {
6931: if (*cellSF) {
6932: PetscMPIInt result;
6935: MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);
6936: if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's");
6937: } else {
6938: PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);
6939: }
6940: if (!dm->ops->locatepoints) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM");
6941: PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);
6942: (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);
6943: PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);
6944: return(0);
6945: }
6947: /*@
6948: DMGetOutputDM - Retrieve the DM associated with the layout for output
6950: Collective on dm
6952: Input Parameter:
6953: . dm - The original DM
6955: Output Parameter:
6956: . odm - The DM which provides the layout for output
6958: Level: intermediate
6960: .seealso: VecView(), DMGetGlobalSection()
6961: @*/
6962: PetscErrorCode DMGetOutputDM(DM dm, DM *odm)
6963: {
6964: PetscSection section;
6965: PetscBool hasConstraints, ghasConstraints;
6971: DMGetLocalSection(dm, §ion);
6972: PetscSectionHasConstraints(section, &hasConstraints);
6973: MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));
6974: if (!ghasConstraints) {
6975: *odm = dm;
6976: return(0);
6977: }
6978: if (!dm->dmBC) {
6979: PetscSection newSection, gsection;
6980: PetscSF sf;
6982: DMClone(dm, &dm->dmBC);
6983: DMCopyDisc(dm, dm->dmBC);
6984: PetscSectionClone(section, &newSection);
6985: DMSetLocalSection(dm->dmBC, newSection);
6986: PetscSectionDestroy(&newSection);
6987: DMGetPointSF(dm->dmBC, &sf);
6988: PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);
6989: DMSetGlobalSection(dm->dmBC, gsection);
6990: PetscSectionDestroy(&gsection);
6991: }
6992: *odm = dm->dmBC;
6993: return(0);
6994: }
6996: /*@
6997: DMGetOutputSequenceNumber - Retrieve the sequence number/value for output
6999: Input Parameter:
7000: . dm - The original DM
7002: Output Parameters:
7003: + num - The output sequence number
7004: - val - The output sequence value
7006: Level: intermediate
7008: Note: This is intended for output that should appear in sequence, for instance
7009: a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
7011: .seealso: VecView()
7012: @*/
7013: PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val)
7014: {
7019: return(0);
7020: }
7022: /*@
7023: DMSetOutputSequenceNumber - Set the sequence number/value for output
7025: Input Parameters:
7026: + dm - The original DM
7027: . num - The output sequence number
7028: - val - The output sequence value
7030: Level: intermediate
7032: Note: This is intended for output that should appear in sequence, for instance
7033: a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
7035: .seealso: VecView()
7036: @*/
7037: PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val)
7038: {
7041: dm->outputSequenceNum = num;
7042: dm->outputSequenceVal = val;
7043: return(0);
7044: }
7046: /*@C
7047: DMOutputSequenceLoad - Retrieve the sequence value from a Viewer
7049: Input Parameters:
7050: + dm - The original DM
7051: . name - The sequence name
7052: - num - The output sequence number
7054: Output Parameter:
7055: . val - The output sequence value
7057: Level: intermediate
7059: Note: This is intended for output that should appear in sequence, for instance
7060: a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
7062: .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView()
7063: @*/
7064: PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val)
7065: {
7066: PetscBool ishdf5;
7073: PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);
7074: if (ishdf5) {
7075: #if defined(PETSC_HAVE_HDF5)
7076: PetscScalar value;
7078: DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);
7079: *val = PetscRealPart(value);
7080: #endif
7081: } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
7082: return(0);
7083: }
7085: /*@
7086: DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution
7088: Not collective
7090: Input Parameter:
7091: . dm - The DM
7093: Output Parameter:
7094: . useNatural - The flag to build the mapping to a natural order during distribution
7096: Level: beginner
7098: .seealso: DMSetUseNatural(), DMCreate()
7099: @*/
7100: PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural)
7101: {
7105: *useNatural = dm->useNatural;
7106: return(0);
7107: }
7109: /*@
7110: DMSetUseNatural - Set the flag for creating a mapping to the natural order after distribution
7112: Collective on dm
7114: Input Parameters:
7115: + dm - The DM
7116: - useNatural - The flag to build the mapping to a natural order during distribution
7118: Note: This also causes the map to be build after DMCreateSubDM() and DMCreateSuperDM()
7120: Level: beginner
7122: .seealso: DMGetUseNatural(), DMCreate(), DMPlexDistribute(), DMCreateSubDM(), DMCreateSuperDM()
7123: @*/
7124: PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural)
7125: {
7129: dm->useNatural = useNatural;
7130: return(0);
7131: }
7134: /*@C
7135: DMCreateLabel - Create a label of the given name if it does not already exist
7137: Not Collective
7139: Input Parameters:
7140: + dm - The DM object
7141: - name - The label name
7143: Level: intermediate
7145: .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
7146: @*/
7147: PetscErrorCode DMCreateLabel(DM dm, const char name[])
7148: {
7149: PetscBool flg;
7150: DMLabel label;
7156: DMHasLabel(dm, name, &flg);
7157: if (!flg) {
7158: DMLabelCreate(PETSC_COMM_SELF, name, &label);
7159: DMAddLabel(dm, label);
7160: DMLabelDestroy(&label);
7161: }
7162: return(0);
7163: }
7165: /*@C
7166: DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default
7168: Not Collective
7170: Input Parameters:
7171: + dm - The DM object
7172: . name - The label name
7173: - point - The mesh point
7175: Output Parameter:
7176: . value - The label value for this point, or -1 if the point is not in the label
7178: Level: beginner
7180: .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS()
7181: @*/
7182: PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value)
7183: {
7184: DMLabel label;
7190: DMGetLabel(dm, name, &label);
7191: if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);
7192: DMLabelGetValue(label, point, value);
7193: return(0);
7194: }
7196: /*@C
7197: DMSetLabelValue - Add a point to a Sieve Label with given value
7199: Not Collective
7201: Input Parameters:
7202: + dm - The DM object
7203: . name - The label name
7204: . point - The mesh point
7205: - value - The label value for this point
7207: Output Parameter:
7209: Level: beginner
7211: .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue()
7212: @*/
7213: PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
7214: {
7215: DMLabel label;
7221: DMGetLabel(dm, name, &label);
7222: if (!label) {
7223: DMCreateLabel(dm, name);
7224: DMGetLabel(dm, name, &label);
7225: }
7226: DMLabelSetValue(label, point, value);
7227: return(0);
7228: }
7230: /*@C
7231: DMClearLabelValue - Remove a point from a Sieve Label with given value
7233: Not Collective
7235: Input Parameters:
7236: + dm - The DM object
7237: . name - The label name
7238: . point - The mesh point
7239: - value - The label value for this point
7241: Output Parameter:
7243: Level: beginner
7245: .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS()
7246: @*/
7247: PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
7248: {
7249: DMLabel label;
7255: DMGetLabel(dm, name, &label);
7256: if (!label) return(0);
7257: DMLabelClearValue(label, point, value);
7258: return(0);
7259: }
7261: /*@C
7262: DMGetLabelSize - Get the number of different integer ids in a Label
7264: Not Collective
7266: Input Parameters:
7267: + dm - The DM object
7268: - name - The label name
7270: Output Parameter:
7271: . size - The number of different integer ids, or 0 if the label does not exist
7273: Level: beginner
7275: .seealso: DMLabelGetNumValues(), DMSetLabelValue()
7276: @*/
7277: PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size)
7278: {
7279: DMLabel label;
7286: DMGetLabel(dm, name, &label);
7287: *size = 0;
7288: if (!label) return(0);
7289: DMLabelGetNumValues(label, size);
7290: return(0);
7291: }
7293: /*@C
7294: DMGetLabelIdIS - Get the integer ids in a label
7296: Not Collective
7298: Input Parameters:
7299: + mesh - The DM object
7300: - name - The label name
7302: Output Parameter:
7303: . ids - The integer ids, or NULL if the label does not exist
7305: Level: beginner
7307: .seealso: DMLabelGetValueIS(), DMGetLabelSize()
7308: @*/
7309: PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids)
7310: {
7311: DMLabel label;
7318: DMGetLabel(dm, name, &label);
7319: *ids = NULL;
7320: if (label) {
7321: DMLabelGetValueIS(label, ids);
7322: } else {
7323: /* returning an empty IS */
7324: ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);
7325: }
7326: return(0);
7327: }
7329: /*@C
7330: DMGetStratumSize - Get the number of points in a label stratum
7332: Not Collective
7334: Input Parameters:
7335: + dm - The DM object
7336: . name - The label name
7337: - value - The stratum value
7339: Output Parameter:
7340: . size - The stratum size
7342: Level: beginner
7344: .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds()
7345: @*/
7346: PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size)
7347: {
7348: DMLabel label;
7355: DMGetLabel(dm, name, &label);
7356: *size = 0;
7357: if (!label) return(0);
7358: DMLabelGetStratumSize(label, value, size);
7359: return(0);
7360: }
7362: /*@C
7363: DMGetStratumIS - Get the points in a label stratum
7365: Not Collective
7367: Input Parameters:
7368: + dm - The DM object
7369: . name - The label name
7370: - value - The stratum value
7372: Output Parameter:
7373: . points - The stratum points, or NULL if the label does not exist or does not have that value
7375: Level: beginner
7377: .seealso: DMLabelGetStratumIS(), DMGetStratumSize()
7378: @*/
7379: PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points)
7380: {
7381: DMLabel label;
7388: DMGetLabel(dm, name, &label);
7389: *points = NULL;
7390: if (!label) return(0);
7391: DMLabelGetStratumIS(label, value, points);
7392: return(0);
7393: }
7395: /*@C
7396: DMSetStratumIS - Set the points in a label stratum
7398: Not Collective
7400: Input Parameters:
7401: + dm - The DM object
7402: . name - The label name
7403: . value - The stratum value
7404: - points - The stratum points
7406: Level: beginner
7408: .seealso: DMLabelSetStratumIS(), DMGetStratumSize()
7409: @*/
7410: PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points)
7411: {
7412: DMLabel label;
7419: DMGetLabel(dm, name, &label);
7420: if (!label) return(0);
7421: DMLabelSetStratumIS(label, value, points);
7422: return(0);
7423: }
7425: /*@C
7426: DMClearLabelStratum - Remove all points from a stratum from a Sieve Label
7428: Not Collective
7430: Input Parameters:
7431: + dm - The DM object
7432: . name - The label name
7433: - value - The label value for this point
7435: Output Parameter:
7437: Level: beginner
7439: .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue()
7440: @*/
7441: PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value)
7442: {
7443: DMLabel label;
7449: DMGetLabel(dm, name, &label);
7450: if (!label) return(0);
7451: DMLabelClearStratum(label, value);
7452: return(0);
7453: }
7455: /*@
7456: DMGetNumLabels - Return the number of labels defined by the mesh
7458: Not Collective
7460: Input Parameter:
7461: . dm - The DM object
7463: Output Parameter:
7464: . numLabels - the number of Labels
7466: Level: intermediate
7468: .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
7469: @*/
7470: PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels)
7471: {
7472: DMLabelLink next = dm->labels;
7473: PetscInt n = 0;
7478: while (next) {++n; next = next->next;}
7479: *numLabels = n;
7480: return(0);
7481: }
7483: /*@C
7484: DMGetLabelName - Return the name of nth label
7486: Not Collective
7488: Input Parameters:
7489: + dm - The DM object
7490: - n - the label number
7492: Output Parameter:
7493: . name - the label name
7495: Level: intermediate
7497: .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
7498: @*/
7499: PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name)
7500: {
7501: DMLabelLink next = dm->labels;
7502: PetscInt l = 0;
7508: while (next) {
7509: if (l == n) {
7510: PetscObjectGetName((PetscObject) next->label, name);
7511: return(0);
7512: }
7513: ++l;
7514: next = next->next;
7515: }
7516: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n);
7517: }
7519: /*@C
7520: DMHasLabel - Determine whether the mesh has a label of a given name
7522: Not Collective
7524: Input Parameters:
7525: + dm - The DM object
7526: - name - The label name
7528: Output Parameter:
7529: . hasLabel - PETSC_TRUE if the label is present
7531: Level: intermediate
7533: .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
7534: @*/
7535: PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel)
7536: {
7537: DMLabelLink next = dm->labels;
7538: const char *lname;
7545: *hasLabel = PETSC_FALSE;
7546: while (next) {
7547: PetscObjectGetName((PetscObject) next->label, &lname);
7548: PetscStrcmp(name, lname, hasLabel);
7549: if (*hasLabel) break;
7550: next = next->next;
7551: }
7552: return(0);
7553: }
7555: /*@C
7556: DMGetLabel - Return the label of a given name, or NULL
7558: Not Collective
7560: Input Parameters:
7561: + dm - The DM object
7562: - name - The label name
7564: Output Parameter:
7565: . label - The DMLabel, or NULL if the label is absent
7567: Level: intermediate
7569: .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
7570: @*/
7571: PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label)
7572: {
7573: DMLabelLink next = dm->labels;
7574: PetscBool hasLabel;
7575: const char *lname;
7582: *label = NULL;
7583: while (next) {
7584: PetscObjectGetName((PetscObject) next->label, &lname);
7585: PetscStrcmp(name, lname, &hasLabel);
7586: if (hasLabel) {
7587: *label = next->label;
7588: break;
7589: }
7590: next = next->next;
7591: }
7592: return(0);
7593: }
7595: /*@C
7596: DMGetLabelByNum - Return the nth label
7598: Not Collective
7600: Input Parameters:
7601: + dm - The DM object
7602: - n - the label number
7604: Output Parameter:
7605: . label - the label
7607: Level: intermediate
7609: .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
7610: @*/
7611: PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label)
7612: {
7613: DMLabelLink next = dm->labels;
7614: PetscInt l = 0;
7619: while (next) {
7620: if (l == n) {
7621: *label = next->label;
7622: return(0);
7623: }
7624: ++l;
7625: next = next->next;
7626: }
7627: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n);
7628: }
7630: /*@C
7631: DMAddLabel - Add the label to this mesh
7633: Not Collective
7635: Input Parameters:
7636: + dm - The DM object
7637: - label - The DMLabel
7639: Level: developer
7641: .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
7642: @*/
7643: PetscErrorCode DMAddLabel(DM dm, DMLabel label)
7644: {
7645: DMLabelLink l, *p, tmpLabel;
7646: PetscBool hasLabel;
7647: const char *lname;
7648: PetscBool flg;
7653: PetscObjectGetName((PetscObject) label, &lname);
7654: DMHasLabel(dm, lname, &hasLabel);
7655: if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname);
7656: PetscCalloc1(1, &tmpLabel);
7657: tmpLabel->label = label;
7658: tmpLabel->output = PETSC_TRUE;
7659: for (p=&dm->labels; (l=*p); p=&l->next) {}
7660: *p = tmpLabel;
7661: PetscObjectReference((PetscObject)label);
7662: PetscStrcmp(lname, "depth", &flg);
7663: if (flg) dm->depthLabel = label;
7664: PetscStrcmp(lname, "celltype", &flg);
7665: if (flg) dm->celltypeLabel = label;
7666: return(0);
7667: }
7669: /*@C
7670: DMRemoveLabel - Remove the label given by name from this mesh
7672: Not Collective
7674: Input Parameters:
7675: + dm - The DM object
7676: - name - The label name
7678: Output Parameter:
7679: . label - The DMLabel, or NULL if the label is absent
7681: Level: developer
7683: Notes:
7684: DMRemoveLabel(dm,name,NULL) removes the label from dm and calls
7685: DMLabelDestroy() on the label.
7687: DMRemoveLabel(dm,name,&label) removes the label from dm, but it DOES NOT
7688: call DMLabelDestroy(). Instead, the label is returned and the user is
7689: responsible of calling DMLabelDestroy() at some point.
7691: .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel(), DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabelBySelf()
7692: @*/
7693: PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label)
7694: {
7695: DMLabelLink link, *pnext;
7696: PetscBool hasLabel;
7697: const char *lname;
7703: if (label) {
7705: *label = NULL;
7706: }
7707: for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) {
7708: PetscObjectGetName((PetscObject) link->label, &lname);
7709: PetscStrcmp(name, lname, &hasLabel);
7710: if (hasLabel) {
7711: *pnext = link->next; /* Remove from list */
7712: PetscStrcmp(name, "depth", &hasLabel);
7713: if (hasLabel) dm->depthLabel = NULL;
7714: PetscStrcmp(name, "celltype", &hasLabel);
7715: if (hasLabel) dm->celltypeLabel = NULL;
7716: if (label) *label = link->label;
7717: else {DMLabelDestroy(&link->label);}
7718: PetscFree(link);
7719: break;
7720: }
7721: }
7722: return(0);
7723: }
7725: /*@
7726: DMRemoveLabelBySelf - Remove the label from this mesh
7728: Not Collective
7730: Input Parameters:
7731: + dm - The DM object
7732: . label - (Optional) The DMLabel to be removed from the DM
7733: - failNotFound - Should it fail if the label is not found in the DM?
7735: Level: developer
7737: Notes:
7738: Only exactly the same instance is removed if found, name match is ignored.
7739: If the DM has an exclusive reference to the label, it gets destroyed and
7740: *label nullified.
7742: .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel() DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabel()
7743: @*/
7744: PetscErrorCode DMRemoveLabelBySelf(DM dm, DMLabel *label, PetscBool failNotFound)
7745: {
7746: DMLabelLink link, *pnext;
7747: PetscBool hasLabel = PETSC_FALSE;
7753: if (!*label && !failNotFound) return(0);
7756: for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) {
7757: if (*label == link->label) {
7758: hasLabel = PETSC_TRUE;
7759: *pnext = link->next; /* Remove from list */
7760: if (*label == dm->depthLabel) dm->depthLabel = NULL;
7761: if (*label == dm->celltypeLabel) dm->celltypeLabel = NULL;
7762: if (((PetscObject) link->label)->refct < 2) *label = NULL; /* nullify if exclusive reference */
7763: DMLabelDestroy(&link->label);
7764: PetscFree(link);
7765: break;
7766: }
7767: }
7768: if (!hasLabel && failNotFound) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Given label not found in DM");
7769: return(0);
7770: }
7772: /*@C
7773: DMGetLabelOutput - Get the output flag for a given label
7775: Not Collective
7777: Input Parameters:
7778: + dm - The DM object
7779: - name - The label name
7781: Output Parameter:
7782: . output - The flag for output
7784: Level: developer
7786: .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
7787: @*/
7788: PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output)
7789: {
7790: DMLabelLink next = dm->labels;
7791: const char *lname;
7798: while (next) {
7799: PetscBool flg;
7801: PetscObjectGetName((PetscObject) next->label, &lname);
7802: PetscStrcmp(name, lname, &flg);
7803: if (flg) {*output = next->output; return(0);}
7804: next = next->next;
7805: }
7806: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
7807: }
7809: /*@C
7810: DMSetLabelOutput - Set the output flag for a given label
7812: Not Collective
7814: Input Parameters:
7815: + dm - The DM object
7816: . name - The label name
7817: - output - The flag for output
7819: Level: developer
7821: .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
7822: @*/
7823: PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output)
7824: {
7825: DMLabelLink next = dm->labels;
7826: const char *lname;
7832: while (next) {
7833: PetscBool flg;
7835: PetscObjectGetName((PetscObject) next->label, &lname);
7836: PetscStrcmp(name, lname, &flg);
7837: if (flg) {next->output = output; return(0);}
7838: next = next->next;
7839: }
7840: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
7841: }
7843: /*@
7844: DMCopyLabels - Copy labels from one mesh to another with a superset of the points
7846: Collective on dmA
7848: Input Parameter:
7849: + dmA - The DM object with initial labels
7850: . dmB - The DM object with copied labels
7851: . mode - Copy labels by pointers (PETSC_OWN_POINTER) or duplicate them (PETSC_COPY_VALUES)
7852: - all - Copy all labels including "depth", "dim", and "celltype" (PETSC_TRUE) which are otherwise ignored (PETSC_FALSE)
7854: Level: intermediate
7856: Note: This is typically used when interpolating or otherwise adding to a mesh
7858: .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection(), DMShareLabels()
7859: @*/
7860: PetscErrorCode DMCopyLabels(DM dmA, DM dmB, PetscCopyMode mode, PetscBool all)
7861: {
7862: DMLabel label, labelNew;
7863: const char *name;
7864: PetscBool flg;
7865: DMLabelLink link;
7873: if (mode==PETSC_USE_POINTER) SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_SUP, "PETSC_USE_POINTER not supported for objects");
7874: if (dmA == dmB) return(0);
7875: for (link=dmA->labels; link; link=link->next) {
7876: label=link->label;
7877: PetscObjectGetName((PetscObject)label, &name);
7878: if (!all) {
7879: PetscStrcmp(name, "depth", &flg);
7880: if (flg) continue;
7881: PetscStrcmp(name, "dim", &flg);
7882: if (flg) continue;
7883: PetscStrcmp(name, "celltype", &flg);
7884: if (flg) continue;
7885: }
7886: if (mode==PETSC_COPY_VALUES) {
7887: DMLabelDuplicate(label, &labelNew);
7888: } else {
7889: labelNew = label;
7890: }
7891: DMAddLabel(dmB, labelNew);
7892: if (mode==PETSC_COPY_VALUES) {DMLabelDestroy(&labelNew);}
7893: }
7894: return(0);
7895: }
7897: /*@
7898: DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement
7900: Input Parameter:
7901: . dm - The DM object
7903: Output Parameter:
7904: . cdm - The coarse DM
7906: Level: intermediate
7908: .seealso: DMSetCoarseDM()
7909: @*/
7910: PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm)
7911: {
7915: *cdm = dm->coarseMesh;
7916: return(0);
7917: }
7919: /*@
7920: DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement
7922: Input Parameters:
7923: + dm - The DM object
7924: - cdm - The coarse DM
7926: Level: intermediate
7928: .seealso: DMGetCoarseDM()
7929: @*/
7930: PetscErrorCode DMSetCoarseDM(DM dm, DM cdm)
7931: {
7937: PetscObjectReference((PetscObject)cdm);
7938: DMDestroy(&dm->coarseMesh);
7939: dm->coarseMesh = cdm;
7940: return(0);
7941: }
7943: /*@
7944: DMGetFineDM - Get the fine mesh from which this was obtained by refinement
7946: Input Parameter:
7947: . dm - The DM object
7949: Output Parameter:
7950: . fdm - The fine DM
7952: Level: intermediate
7954: .seealso: DMSetFineDM()
7955: @*/
7956: PetscErrorCode DMGetFineDM(DM dm, DM *fdm)
7957: {
7961: *fdm = dm->fineMesh;
7962: return(0);
7963: }
7965: /*@
7966: DMSetFineDM - Set the fine mesh from which this was obtained by refinement
7968: Input Parameters:
7969: + dm - The DM object
7970: - fdm - The fine DM
7972: Level: intermediate
7974: .seealso: DMGetFineDM()
7975: @*/
7976: PetscErrorCode DMSetFineDM(DM dm, DM fdm)
7977: {
7983: PetscObjectReference((PetscObject)fdm);
7984: DMDestroy(&dm->fineMesh);
7985: dm->fineMesh = fdm;
7986: return(0);
7987: }
7989: /*=== DMBoundary code ===*/
7991: PetscErrorCode DMCopyBoundary(DM dm, DM dmNew)
7992: {
7993: PetscInt d;
7997: for (d = 0; d < dm->Nds; ++d) {
7998: PetscDSCopyBoundary(dm->probs[d].ds, dmNew->probs[d].ds);
7999: }
8000: return(0);
8001: }
8003: /*@C
8004: DMAddBoundary - Add a boundary condition to the model
8006: Collective on dm
8008: Input Parameters:
8009: + dm - The DM, with a PetscDS that matches the problem being constrained
8010: . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
8011: . name - The BC name
8012: . labelname - The label defining constrained points
8013: . field - The field to constrain
8014: . numcomps - The number of constrained field components (0 will constrain all fields)
8015: . comps - An array of constrained component numbers
8016: . bcFunc - A pointwise function giving boundary values
8017: . bcFunc_t - A pointwise function giving the time deriative of the boundary values, or NULL
8018: . numids - The number of DMLabel ids for constrained points
8019: . ids - An array of ids for constrained points
8020: - ctx - An optional user context for bcFunc
8022: Options Database Keys:
8023: + -bc_<boundary name> <num> - Overrides the boundary ids
8024: - -bc_<boundary name>_comp <num> - Overrides the boundary components
8026: Note:
8027: Both bcFunc abd bcFunc_t will depend on the boundary condition type. If the type if DM_BC_ESSENTIAL, Then the calling sequence is:
8029: $ bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])
8031: If the type is DM_BC_ESSENTIAL_FIELD or other _FIELD value, then the calling sequence is:
8033: $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
8034: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
8035: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
8036: $ PetscReal time, const PetscReal x[], PetscScalar bcval[])
8038: + dim - the spatial dimension
8039: . Nf - the number of fields
8040: . uOff - the offset into u[] and u_t[] for each field
8041: . uOff_x - the offset into u_x[] for each field
8042: . u - each field evaluated at the current point
8043: . u_t - the time derivative of each field evaluated at the current point
8044: . u_x - the gradient of each field evaluated at the current point
8045: . aOff - the offset into a[] and a_t[] for each auxiliary field
8046: . aOff_x - the offset into a_x[] for each auxiliary field
8047: . a - each auxiliary field evaluated at the current point
8048: . a_t - the time derivative of each auxiliary field evaluated at the current point
8049: . a_x - the gradient of auxiliary each field evaluated at the current point
8050: . t - current time
8051: . x - coordinates of the current point
8052: . numConstants - number of constant parameters
8053: . constants - constant parameters
8054: - bcval - output values at the current point
8056: Level: developer
8058: .seealso: DMGetBoundary(), PetscDSAddBoundary()
8059: @*/
8060: PetscErrorCode DMAddBoundary(DM dm, DMBoundaryConditionType type, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(void), void (*bcFunc_t)(void), PetscInt numids, const PetscInt *ids, void *ctx)
8061: {
8062: PetscDS ds;
8071: DMGetDS(dm, &ds);
8072: DMCompleteBoundaryLabel_Internal(dm, ds, field, PETSC_MAX_INT, labelname);
8073: PetscDSAddBoundary(ds, type,name, labelname, field, numcomps, comps, bcFunc, bcFunc_t, numids, ids, ctx);
8074: return(0);
8075: }
8077: /*@
8078: DMGetNumBoundary - Get the number of registered BC
8080: Input Parameters:
8081: . dm - The mesh object
8083: Output Parameters:
8084: . numBd - The number of BC
8086: Level: intermediate
8088: .seealso: DMAddBoundary(), DMGetBoundary()
8089: @*/
8090: PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd)
8091: {
8092: PetscDS ds;
8097: DMGetDS(dm, &ds);
8098: PetscDSGetNumBoundary(ds, numBd);
8099: return(0);
8100: }
8102: /*@C
8103: DMGetBoundary - Get a model boundary condition
8105: Input Parameters:
8106: + dm - The mesh object
8107: - bd - The BC number
8109: Output Parameters:
8110: + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
8111: . name - The BC name
8112: . labelname - The label defining constrained points
8113: . field - The field to constrain
8114: . numcomps - The number of constrained field components
8115: . comps - An array of constrained component numbers
8116: . bcFunc - A pointwise function giving boundary values
8117: . bcFunc_t - A pointwise function giving the time derviative of the boundary values
8118: . numids - The number of DMLabel ids for constrained points
8119: . ids - An array of ids for constrained points
8120: - ctx - An optional user context for bcFunc
8122: Options Database Keys:
8123: + -bc_<boundary name> <num> - Overrides the boundary ids
8124: - -bc_<boundary name>_comp <num> - Overrides the boundary components
8126: Level: developer
8128: .seealso: DMAddBoundary()
8129: @*/
8130: PetscErrorCode DMGetBoundary(DM dm, PetscInt bd, DMBoundaryConditionType *type, const char **name, const char **labelname, PetscInt *field, PetscInt *numcomps, const PetscInt **comps, void (**func)(void), void (**func_t)(void), PetscInt *numids, const PetscInt **ids, void **ctx)
8131: {
8132: PetscDS ds;
8137: DMGetDS(dm, &ds);
8138: PetscDSGetBoundary(ds, bd, type, name, labelname, field, numcomps, comps, func, func_t, numids, ids, ctx);
8139: return(0);
8140: }
8142: static PetscErrorCode DMPopulateBoundary(DM dm)
8143: {
8144: PetscDS ds;
8145: DMBoundary *lastnext;
8146: DSBoundary dsbound;
8150: DMGetDS(dm, &ds);
8151: dsbound = ds->boundary;
8152: if (dm->boundary) {
8153: DMBoundary next = dm->boundary;
8155: /* quick check to see if the PetscDS has changed */
8156: if (next->dsboundary == dsbound) return(0);
8157: /* the PetscDS has changed: tear down and rebuild */
8158: while (next) {
8159: DMBoundary b = next;
8161: next = b->next;
8162: PetscFree(b);
8163: }
8164: dm->boundary = NULL;
8165: }
8167: lastnext = &(dm->boundary);
8168: while (dsbound) {
8169: DMBoundary dmbound;
8171: PetscNew(&dmbound);
8172: dmbound->dsboundary = dsbound;
8173: DMGetLabel(dm, dsbound->labelname, &(dmbound->label));
8174: if (!dmbound->label) {PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);}
8175: /* push on the back instead of the front so that it is in the same order as in the PetscDS */
8176: *lastnext = dmbound;
8177: lastnext = &(dmbound->next);
8178: dsbound = dsbound->next;
8179: }
8180: return(0);
8181: }
8183: PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd)
8184: {
8185: DMBoundary b;
8191: *isBd = PETSC_FALSE;
8192: DMPopulateBoundary(dm);
8193: b = dm->boundary;
8194: while (b && !(*isBd)) {
8195: DMLabel label = b->label;
8196: DSBoundary dsb = b->dsboundary;
8198: if (label) {
8199: PetscInt i;
8201: for (i = 0; i < dsb->numids && !(*isBd); ++i) {
8202: DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);
8203: }
8204: }
8205: b = b->next;
8206: }
8207: return(0);
8208: }
8210: /*@C
8211: DMProjectFunction - This projects the given function into the function space provided, putting the coefficients in a global vector.
8213: Collective on DM
8215: Input Parameters:
8216: + dm - The DM
8217: . time - The time
8218: . funcs - The coordinate functions to evaluate, one per field
8219: . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null.
8220: - mode - The insertion mode for values
8222: Output Parameter:
8223: . X - vector
8225: Calling sequence of func:
8226: $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx);
8228: + dim - The spatial dimension
8229: . time - The time at which to sample
8230: . x - The coordinates
8231: . Nf - The number of fields
8232: . u - The output field values
8233: - ctx - optional user-defined function context
8235: Level: developer
8237: .seealso: DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff()
8238: @*/
8239: PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X)
8240: {
8241: Vec localX;
8246: DMGetLocalVector(dm, &localX);
8247: DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);
8248: DMLocalToGlobalBegin(dm, localX, mode, X);
8249: DMLocalToGlobalEnd(dm, localX, mode, X);
8250: DMRestoreLocalVector(dm, &localX);
8251: return(0);
8252: }
8254: /*@C
8255: DMProjectFunctionLocal - This projects the given function into the function space provided, putting the coefficients in a local vector.
8257: Not collective
8259: Input Parameters:
8260: + dm - The DM
8261: . time - The time
8262: . funcs - The coordinate functions to evaluate, one per field
8263: . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null.
8264: - mode - The insertion mode for values
8266: Output Parameter:
8267: . localX - vector
8269: Calling sequence of func:
8270: $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx);
8272: + dim - The spatial dimension
8273: . x - The coordinates
8274: . Nf - The number of fields
8275: . u - The output field values
8276: - ctx - optional user-defined function context
8278: Level: developer
8280: .seealso: DMProjectFunction(), DMProjectFunctionLabel(), DMComputeL2Diff()
8281: @*/
8282: PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
8283: {
8289: if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name);
8290: (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);
8291: return(0);
8292: }
8294: /*@C
8295: DMProjectFunctionLabel - This projects the given function into the function space provided, putting the coefficients in a global vector, setting values only for points in the given label.
8297: Collective on DM
8299: Input Parameters:
8300: + dm - The DM
8301: . time - The time
8302: . label - The DMLabel selecting the portion of the mesh for projection
8303: . funcs - The coordinate functions to evaluate, one per field
8304: . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null.
8305: - mode - The insertion mode for values
8307: Output Parameter:
8308: . X - vector
8310: Calling sequence of func:
8311: $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx);
8313: + dim - The spatial dimension
8314: . x - The coordinates
8315: . Nf - The number of fields
8316: . u - The output field values
8317: - ctx - optional user-defined function context
8319: Level: developer
8321: .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabelLocal(), DMComputeL2Diff()
8322: @*/
8323: 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)
8324: {
8325: Vec localX;
8330: DMGetLocalVector(dm, &localX);
8331: DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);
8332: DMLocalToGlobalBegin(dm, localX, mode, X);
8333: DMLocalToGlobalEnd(dm, localX, mode, X);
8334: DMRestoreLocalVector(dm, &localX);
8335: return(0);
8336: }
8338: /*@C
8339: DMProjectFunctionLabelLocal - This projects the given function into the function space provided, putting the coefficients in a local vector, setting values only for points in the given label.
8341: Not collective
8343: Input Parameters:
8344: + dm - The DM
8345: . time - The time
8346: . label - The DMLabel selecting the portion of the mesh for projection
8347: . funcs - The coordinate functions to evaluate, one per field
8348: . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null.
8349: - mode - The insertion mode for values
8351: Output Parameter:
8352: . localX - vector
8354: Calling sequence of func:
8355: $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx);
8357: + dim - The spatial dimension
8358: . x - The coordinates
8359: . Nf - The number of fields
8360: . u - The output field values
8361: - ctx - optional user-defined function context
8363: Level: developer
8365: .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff()
8366: @*/
8367: 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)
8368: {
8374: if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name);
8375: (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);
8376: return(0);
8377: }
8379: /*@C
8380: DMProjectFieldLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector.
8382: Not collective
8384: Input Parameters:
8385: + dm - The DM
8386: . time - The time
8387: . localU - The input field vector
8388: . funcs - The functions to evaluate, one per field
8389: - mode - The insertion mode for values
8391: Output Parameter:
8392: . localX - The output vector
8394: Calling sequence of func:
8395: $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux,
8396: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
8397: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
8398: $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
8400: + dim - The spatial dimension
8401: . Nf - The number of input fields
8402: . NfAux - The number of input auxiliary fields
8403: . uOff - The offset of each field in u[]
8404: . uOff_x - The offset of each field in u_x[]
8405: . u - The field values at this point in space
8406: . u_t - The field time derivative at this point in space (or NULL)
8407: . u_x - The field derivatives at this point in space
8408: . aOff - The offset of each auxiliary field in u[]
8409: . aOff_x - The offset of each auxiliary field in u_x[]
8410: . a - The auxiliary field values at this point in space
8411: . a_t - The auxiliary field time derivative at this point in space (or NULL)
8412: . a_x - The auxiliary field derivatives at this point in space
8413: . t - The current time
8414: . x - The coordinates of this point
8415: . numConstants - The number of constants
8416: . constants - The value of each constant
8417: - f - The value of the function at this point in space
8419: Note: There are three different DMs that potentially interact in this function. The output DM, dm, specifies the layout of the values calculates by funcs.
8420: The input DM, attached to U, may be different. For example, you can input the solution over the full domain, but output over a piece of the boundary, or
8421: a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the
8422: auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations.
8424: Level: intermediate
8426: .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff()
8427: @*/
8428: PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU,
8429: void (**funcs)(PetscInt, PetscInt, PetscInt,
8430: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
8431: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
8432: PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
8433: InsertMode mode, Vec localX)
8434: {
8441: if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name);
8442: (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);
8443: return(0);
8444: }
8446: /*@C
8447: DMProjectFieldLabelLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector, calculating only over the portion of the domain specified by the label.
8449: Not collective
8451: Input Parameters:
8452: + dm - The DM
8453: . time - The time
8454: . label - The DMLabel marking the portion of the domain to output
8455: . numIds - The number of label ids to use
8456: . ids - The label ids to use for marking
8457: . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components
8458: . comps - The components to set in the output, or NULL for all components
8459: . localU - The input field vector
8460: . funcs - The functions to evaluate, one per field
8461: - mode - The insertion mode for values
8463: Output Parameter:
8464: . localX - The output vector
8466: Calling sequence of func:
8467: $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux,
8468: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
8469: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
8470: $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
8472: + dim - The spatial dimension
8473: . Nf - The number of input fields
8474: . NfAux - The number of input auxiliary fields
8475: . uOff - The offset of each field in u[]
8476: . uOff_x - The offset of each field in u_x[]
8477: . u - The field values at this point in space
8478: . u_t - The field time derivative at this point in space (or NULL)
8479: . u_x - The field derivatives at this point in space
8480: . aOff - The offset of each auxiliary field in u[]
8481: . aOff_x - The offset of each auxiliary field in u_x[]
8482: . a - The auxiliary field values at this point in space
8483: . a_t - The auxiliary field time derivative at this point in space (or NULL)
8484: . a_x - The auxiliary field derivatives at this point in space
8485: . t - The current time
8486: . x - The coordinates of this point
8487: . numConstants - The number of constants
8488: . constants - The value of each constant
8489: - f - The value of the function at this point in space
8491: Note: There are three different DMs that potentially interact in this function. The output DM, dm, specifies the layout of the values calculates by funcs.
8492: The input DM, attached to U, may be different. For example, you can input the solution over the full domain, but output over a piece of the boundary, or
8493: a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the
8494: auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations.
8496: Level: intermediate
8498: .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff()
8499: @*/
8500: PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU,
8501: void (**funcs)(PetscInt, PetscInt, PetscInt,
8502: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
8503: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
8504: PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
8505: InsertMode mode, Vec localX)
8506: {
8513: if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLabelLocal",((PetscObject)dm)->type_name);
8514: (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);
8515: return(0);
8516: }
8518: /*@C
8519: DMProjectBdFieldLabelLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector, calculating only over the portion of the domain boundary specified by the label.
8521: Not collective
8523: Input Parameters:
8524: + dm - The DM
8525: . time - The time
8526: . label - The DMLabel marking the portion of the domain boundary to output
8527: . numIds - The number of label ids to use
8528: . ids - The label ids to use for marking
8529: . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components
8530: . comps - The components to set in the output, or NULL for all components
8531: . localU - The input field vector
8532: . funcs - The functions to evaluate, one per field
8533: - mode - The insertion mode for values
8535: Output Parameter:
8536: . localX - The output vector
8538: Calling sequence of func:
8539: $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux,
8540: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
8541: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
8542: $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
8544: + dim - The spatial dimension
8545: . Nf - The number of input fields
8546: . NfAux - The number of input auxiliary fields
8547: . uOff - The offset of each field in u[]
8548: . uOff_x - The offset of each field in u_x[]
8549: . u - The field values at this point in space
8550: . u_t - The field time derivative at this point in space (or NULL)
8551: . u_x - The field derivatives at this point in space
8552: . aOff - The offset of each auxiliary field in u[]
8553: . aOff_x - The offset of each auxiliary field in u_x[]
8554: . a - The auxiliary field values at this point in space
8555: . a_t - The auxiliary field time derivative at this point in space (or NULL)
8556: . a_x - The auxiliary field derivatives at this point in space
8557: . t - The current time
8558: . x - The coordinates of this point
8559: . n - The face normal
8560: . numConstants - The number of constants
8561: . constants - The value of each constant
8562: - f - The value of the function at this point in space
8564: Note:
8565: There are three different DMs that potentially interact in this function. The output DM, dm, specifies the layout of the values calculates by funcs.
8566: The input DM, attached to U, may be different. For example, you can input the solution over the full domain, but output over a piece of the boundary, or
8567: a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the
8568: auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations.
8570: Level: intermediate
8572: .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff()
8573: @*/
8574: PetscErrorCode DMProjectBdFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU,
8575: void (**funcs)(PetscInt, PetscInt, PetscInt,
8576: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
8577: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
8578: PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
8579: InsertMode mode, Vec localX)
8580: {
8587: if (!dm->ops->projectbdfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectBdFieldLabelLocal",((PetscObject)dm)->type_name);
8588: (dm->ops->projectbdfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);
8589: return(0);
8590: }
8592: /*@C
8593: DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h.
8595: Input Parameters:
8596: + dm - The DM
8597: . time - The time
8598: . funcs - The functions to evaluate for each field component
8599: . ctxs - Optional array of contexts to pass to each function, or NULL.
8600: - X - The coefficient vector u_h, a global vector
8602: Output Parameter:
8603: . diff - The diff ||u - u_h||_2
8605: Level: developer
8607: .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff()
8608: @*/
8609: PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff)
8610: {
8616: if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name);
8617: (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);
8618: return(0);
8619: }
8621: /*@C
8622: DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h.
8624: Collective on dm
8626: Input Parameters:
8627: + dm - The DM
8628: , time - The time
8629: . funcs - The gradient functions to evaluate for each field component
8630: . ctxs - Optional array of contexts to pass to each function, or NULL.
8631: . X - The coefficient vector u_h, a global vector
8632: - n - The vector to project along
8634: Output Parameter:
8635: . diff - The diff ||(grad u - grad u_h) . n||_2
8637: Level: developer
8639: .seealso: DMProjectFunction(), DMComputeL2Diff()
8640: @*/
8641: 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)
8642: {
8648: if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name);
8649: (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);
8650: return(0);
8651: }
8653: /*@C
8654: DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components.
8656: Collective on dm
8658: Input Parameters:
8659: + dm - The DM
8660: . time - The time
8661: . funcs - The functions to evaluate for each field component
8662: . ctxs - Optional array of contexts to pass to each function, or NULL.
8663: - X - The coefficient vector u_h, a global vector
8665: Output Parameter:
8666: . diff - The array of differences, ||u^f - u^f_h||_2
8668: Level: developer
8670: .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff()
8671: @*/
8672: PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[])
8673: {
8679: if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name);
8680: (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);
8681: return(0);
8682: }
8684: /*@C
8685: DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have
8686: specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN.
8688: Collective on dm
8690: Input parameters:
8691: + dm - the pre-adaptation DM object
8692: - label - label with the flags
8694: Output parameters:
8695: . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced.
8697: Level: intermediate
8699: .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine()
8700: @*/
8701: PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt)
8702: {
8709: *dmAdapt = NULL;
8710: if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name);
8711: (dm->ops->adaptlabel)(dm, label, dmAdapt);
8712: return(0);
8713: }
8715: /*@C
8716: DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library.
8718: Input Parameters:
8719: + dm - The DM object
8720: . metric - The metric to which the mesh is adapted, defined vertex-wise.
8721: - 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_".
8723: Output Parameter:
8724: . dmAdapt - Pointer to the DM object containing the adapted mesh
8726: Note: The label in the adapted mesh will be registered under the name of the input DMLabel object
8728: Level: advanced
8730: .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine()
8731: @*/
8732: PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt)
8733: {
8741: *dmAdapt = NULL;
8742: if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name);
8743: (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);
8744: return(0);
8745: }
8747: /*@C
8748: DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors
8750: Not Collective
8752: Input Parameter:
8753: . dm - The DM
8755: Output Parameters:
8756: + nranks - the number of neighbours
8757: - ranks - the neighbors ranks
8759: Notes:
8760: Do not free the array, it is freed when the DM is destroyed.
8762: Level: beginner
8764: .seealso: DMDAGetNeighbors(), PetscSFGetRootRanks()
8765: @*/
8766: PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[])
8767: {
8772: if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name);
8773: (dm->ops->getneighbors)(dm,nranks,ranks);
8774: return(0);
8775: }
8777: #include <petsc/private/matimpl.h>
8779: /*
8780: Converts the input vector to a ghosted vector and then calls the standard coloring code.
8781: This has be a different function because it requires DM which is not defined in the Mat library
8782: */
8783: PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx)
8784: {
8788: if (coloring->ctype == IS_COLORING_LOCAL) {
8789: Vec x1local;
8790: DM dm;
8791: MatGetDM(J,&dm);
8792: if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM");
8793: DMGetLocalVector(dm,&x1local);
8794: DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);
8795: DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);
8796: x1 = x1local;
8797: }
8798: MatFDColoringApply_AIJ(J,coloring,x1,sctx);
8799: if (coloring->ctype == IS_COLORING_LOCAL) {
8800: DM dm;
8801: MatGetDM(J,&dm);
8802: DMRestoreLocalVector(dm,&x1);
8803: }
8804: return(0);
8805: }
8807: /*@
8808: MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring
8810: Input Parameter:
8811: . coloring - the MatFDColoring object
8813: Developer Notes:
8814: this routine exists because the PETSc Mat library does not know about the DM objects
8816: Level: advanced
8818: .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType
8819: @*/
8820: PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring)
8821: {
8823: coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM;
8824: return(0);
8825: }
8827: /*@
8828: DMGetCompatibility - determine if two DMs are compatible
8830: Collective
8832: Input Parameters:
8833: + dm1 - the first DM
8834: - dm2 - the second DM
8836: Output Parameters:
8837: + compatible - whether or not the two DMs are compatible
8838: - set - whether or not the compatible value was set
8840: Notes:
8841: Two DMs are deemed compatible if they represent the same parallel decomposition
8842: of the same topology. This implies that the section (field data) on one
8843: "makes sense" with respect to the topology and parallel decomposition of the other.
8844: Loosely speaking, compatible DMs represent the same domain and parallel
8845: decomposition, but hold different data.
8847: Typically, one would confirm compatibility if intending to simultaneously iterate
8848: over a pair of vectors obtained from different DMs.
8850: For example, two DMDA objects are compatible if they have the same local
8851: and global sizes and the same stencil width. They can have different numbers
8852: of degrees of freedom per node. Thus, one could use the node numbering from
8853: either DM in bounds for a loop over vectors derived from either DM.
8855: Consider the operation of summing data living on a 2-dof DMDA to data living
8856: on a 1-dof DMDA, which should be compatible, as in the following snippet.
8857: .vb
8858: ...
8859: DMGetCompatibility(da1,da2,&compatible,&set);
8860: if (set && compatible) {
8861: DMDAVecGetArrayDOF(da1,vec1,&arr1);
8862: DMDAVecGetArrayDOF(da2,vec2,&arr2);
8863: DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL);
8864: for (j=y; j<y+n; ++j) {
8865: for (i=x; i<x+m, ++i) {
8866: arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1];
8867: }
8868: }
8869: DMDAVecRestoreArrayDOF(da1,vec1,&arr1);
8870: DMDAVecRestoreArrayDOF(da2,vec2,&arr2);
8871: } else {
8872: SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible");
8873: }
8874: ...
8875: .ve
8877: Checking compatibility might be expensive for a given implementation of DM,
8878: or might be impossible to unambiguously confirm or deny. For this reason,
8879: this function may decline to determine compatibility, and hence users should
8880: always check the "set" output parameter.
8882: A DM is always compatible with itself.
8884: In the current implementation, DMs which live on "unequal" communicators
8885: (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed
8886: incompatible.
8888: This function is labeled "Collective," as information about all subdomains
8889: is required on each rank. However, in DM implementations which store all this
8890: information locally, this function may be merely "Logically Collective".
8892: Developer Notes:
8893: Compatibility is assumed to be a symmetric concept; DM A is compatible with DM B
8894: iff B is compatible with A. Thus, this function checks the implementations
8895: of both dm and dmc (if they are of different types), attempting to determine
8896: compatibility. It is left to DM implementers to ensure that symmetry is
8897: preserved. The simplest way to do this is, when implementing type-specific
8898: logic for this function, is to check for existing logic in the implementation
8899: of other DM types and let *set = PETSC_FALSE if found.
8901: Level: advanced
8903: .seealso: DM, DMDACreateCompatibleDMDA(), DMStagCreateCompatibleDMStag()
8904: @*/
8906: PetscErrorCode DMGetCompatibility(DM dm1,DM dm2,PetscBool *compatible,PetscBool *set)
8907: {
8909: PetscMPIInt compareResult;
8910: DMType type,type2;
8911: PetscBool sameType;
8917: /* Declare a DM compatible with itself */
8918: if (dm1 == dm2) {
8919: *set = PETSC_TRUE;
8920: *compatible = PETSC_TRUE;
8921: return(0);
8922: }
8924: /* Declare a DM incompatible with a DM that lives on an "unequal"
8925: communicator. Note that this does not preclude compatibility with
8926: DMs living on "congruent" or "similar" communicators, but this must be
8927: determined by the implementation-specific logic */
8928: MPI_Comm_compare(PetscObjectComm((PetscObject)dm1),PetscObjectComm((PetscObject)dm2),&compareResult);
8929: if (compareResult == MPI_UNEQUAL) {
8930: *set = PETSC_TRUE;
8931: *compatible = PETSC_FALSE;
8932: return(0);
8933: }
8935: /* Pass to the implementation-specific routine, if one exists. */
8936: if (dm1->ops->getcompatibility) {
8937: (*dm1->ops->getcompatibility)(dm1,dm2,compatible,set);
8938: if (*set) return(0);
8939: }
8941: /* If dm1 and dm2 are of different types, then attempt to check compatibility
8942: with an implementation of this function from dm2 */
8943: DMGetType(dm1,&type);
8944: DMGetType(dm2,&type2);
8945: PetscStrcmp(type,type2,&sameType);
8946: if (!sameType && dm2->ops->getcompatibility) {
8947: (*dm2->ops->getcompatibility)(dm2,dm1,compatible,set); /* Note argument order */
8948: } else {
8949: *set = PETSC_FALSE;
8950: }
8951: return(0);
8952: }
8954: /*@C
8955: DMMonitorSet - Sets an ADDITIONAL function that is to be used after a solve to monitor discretization performance.
8957: Logically Collective on DM
8959: Input Parameters:
8960: + DM - the DM
8961: . f - the monitor function
8962: . mctx - [optional] user-defined context for private data for the monitor routine (use NULL if no context is desired)
8963: - monitordestroy - [optional] routine that frees monitor context (may be NULL)
8965: Options Database Keys:
8966: - -dm_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to DMMonitorSet(), but
8967: does not cancel those set via the options database.
8969: Notes:
8970: Several different monitoring routines may be set by calling
8971: DMMonitorSet() multiple times; all will be called in the
8972: order in which they were set.
8974: Fortran Notes:
8975: Only a single monitor function can be set for each DM object
8977: Level: intermediate
8979: .seealso: DMMonitorCancel()
8980: @*/
8981: PetscErrorCode DMMonitorSet(DM dm, PetscErrorCode (*f)(DM, void *), void *mctx, PetscErrorCode (*monitordestroy)(void**))
8982: {
8983: PetscInt m;
8988: for (m = 0; m < dm->numbermonitors; ++m) {
8989: PetscBool identical;
8991: PetscMonitorCompare((PetscErrorCode (*)(void)) f, mctx, monitordestroy, (PetscErrorCode (*)(void)) dm->monitor[m], dm->monitorcontext[m], dm->monitordestroy[m], &identical);
8992: if (identical) return(0);
8993: }
8994: if (dm->numbermonitors >= MAXDMMONITORS) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
8995: dm->monitor[dm->numbermonitors] = f;
8996: dm->monitordestroy[dm->numbermonitors] = monitordestroy;
8997: dm->monitorcontext[dm->numbermonitors++] = (void *) mctx;
8998: return(0);
8999: }
9001: /*@
9002: DMMonitorCancel - Clears all the monitor functions for a DM object.
9004: Logically Collective on DM
9006: Input Parameter:
9007: . dm - the DM
9009: Options Database Key:
9010: . -dm_monitor_cancel - cancels all monitors that have been hardwired
9011: into a code by calls to DMonitorSet(), but does not cancel those
9012: set via the options database
9014: Notes:
9015: There is no way to clear one specific monitor from a DM object.
9017: Level: intermediate
9019: .seealso: DMMonitorSet()
9020: @*/
9021: PetscErrorCode DMMonitorCancel(DM dm)
9022: {
9024: PetscInt m;
9028: for (m = 0; m < dm->numbermonitors; ++m) {
9029: if (dm->monitordestroy[m]) {(*dm->monitordestroy[m])(&dm->monitorcontext[m]);}
9030: }
9031: dm->numbermonitors = 0;
9032: return(0);
9033: }
9035: /*@C
9036: DMMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
9038: Collective on DM
9040: Input Parameters:
9041: + dm - DM object you wish to monitor
9042: . name - the monitor type one is seeking
9043: . help - message indicating what monitoring is done
9044: . manual - manual page for the monitor
9045: . monitor - the monitor function
9046: - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the DM or PetscViewer objects
9048: Output Parameter:
9049: . flg - Flag set if the monitor was created
9051: Level: developer
9053: .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(),
9054: PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool()
9055: PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(),
9056: PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(),
9057: PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(),
9058: PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(),
9059: PetscOptionsFList(), PetscOptionsEList()
9060: @*/
9061: PetscErrorCode DMMonitorSetFromOptions(DM dm, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(DM, void *), PetscErrorCode (*monitorsetup)(DM, PetscViewerAndFormat *), PetscBool *flg)
9062: {
9063: PetscViewer viewer;
9064: PetscViewerFormat format;
9065: PetscErrorCode ierr;
9069: PetscOptionsGetViewer(PetscObjectComm((PetscObject) dm), ((PetscObject) dm)->options, ((PetscObject) dm)->prefix, name, &viewer, &format, flg);
9070: if (*flg) {
9071: PetscViewerAndFormat *vf;
9073: PetscViewerAndFormatCreate(viewer, format, &vf);
9074: PetscObjectDereference((PetscObject) viewer);
9075: if (monitorsetup) {(*monitorsetup)(dm, vf);}
9076: DMMonitorSet(dm,(PetscErrorCode (*)(DM, void *)) monitor, vf, (PetscErrorCode (*)(void **)) PetscViewerAndFormatDestroy);
9077: }
9078: return(0);
9079: }
9081: /*@
9082: DMMonitor - runs the user provided monitor routines, if they exist
9084: Collective on DM
9086: Input Parameters:
9087: . dm - The DM
9089: Level: developer
9091: .seealso: DMMonitorSet()
9092: @*/
9093: PetscErrorCode DMMonitor(DM dm)
9094: {
9095: PetscInt m;
9099: if (!dm) return(0);
9101: for (m = 0; m < dm->numbermonitors; ++m) {
9102: (*dm->monitor[m])(dm, dm->monitorcontext[m]);
9103: }
9104: return(0);
9105: }