Actual source code: dm.c
petsc-3.9.1 2018-04-29
1: #include <petsc/private/dmimpl.h>
2: #include <petsc/private/dmlabelimpl.h>
3: #include <petsc/private/petscdsimpl.h>
4: #include <petscdmplex.h>
5: #include <petscsf.h>
6: #include <petscds.h>
8: PetscClassId DM_CLASSID;
9: PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal, DM_LocatePoints, DM_Coarsen, DM_Refine, DM_CreateInterpolation, DM_CreateRestriction;
11: const char *const DMBoundaryTypes[] = {"NONE","GHOSTED","MIRROR","PERIODIC","TWIST","DM_BOUNDARY_",0};
13: static PetscErrorCode DMHasCreateInjection_Default(DM dm, PetscBool *flg)
14: {
18: *flg = PETSC_FALSE;
19: return(0);
20: }
22: /*@
23: DMCreate - Creates an empty DM object. The type can then be set with DMSetType().
25: If you never call DMSetType() it will generate an
26: error when you try to use the vector.
28: Collective on MPI_Comm
30: Input Parameter:
31: . comm - The communicator for the DM object
33: Output Parameter:
34: . dm - The DM object
36: Level: beginner
38: .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE, DMPLEX, DMMOAB, DMNETWORK
39: @*/
40: PetscErrorCode DMCreate(MPI_Comm comm,DM *dm)
41: {
42: DM v;
47: *dm = NULL;
48: PetscSysInitializePackage();
49: VecInitializePackage();
50: MatInitializePackage();
51: DMInitializePackage();
53: PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);
55: v->ltogmap = NULL;
56: v->bs = 1;
57: v->coloringtype = IS_COLORING_GLOBAL;
58: PetscSFCreate(comm, &v->sf);
59: PetscSFCreate(comm, &v->defaultSF);
60: v->labels = NULL;
61: v->depthLabel = NULL;
62: v->defaultSection = NULL;
63: v->defaultGlobalSection = NULL;
64: v->defaultConstraintSection = NULL;
65: v->defaultConstraintMat = NULL;
66: v->L = NULL;
67: v->maxCell = NULL;
68: v->bdtype = NULL;
69: v->dimEmbed = PETSC_DEFAULT;
70: {
71: PetscInt i;
72: for (i = 0; i < 10; ++i) {
73: v->nullspaceConstructors[i] = NULL;
74: }
75: }
76: PetscDSCreate(comm, &v->prob);
77: v->dmBC = NULL;
78: v->coarseMesh = NULL;
79: v->outputSequenceNum = -1;
80: v->outputSequenceVal = 0.0;
81: DMSetVecType(v,VECSTANDARD);
82: DMSetMatType(v,MATAIJ);
83: PetscNew(&(v->labels));
84: v->labels->refct = 1;
86: v->ops->hascreateinjection = DMHasCreateInjection_Default;
88: *dm = v;
89: return(0);
90: }
92: /*@
93: DMClone - Creates a DM object with the same topology as the original.
95: Collective on MPI_Comm
97: Input Parameter:
98: . dm - The original DM object
100: Output Parameter:
101: . newdm - The new DM object
103: Level: beginner
105: .keywords: DM, topology, create
106: @*/
107: PetscErrorCode DMClone(DM dm, DM *newdm)
108: {
109: PetscSF sf;
110: Vec coords;
111: void *ctx;
112: PetscInt dim, cdim;
118: DMCreate(PetscObjectComm((PetscObject) dm), newdm);
119: PetscFree((*newdm)->labels);
120: dm->labels->refct++;
121: (*newdm)->labels = dm->labels;
122: (*newdm)->depthLabel = dm->depthLabel;
123: DMGetDimension(dm, &dim);
124: DMSetDimension(*newdm, dim);
125: if (dm->ops->clone) {
126: (*dm->ops->clone)(dm, newdm);
127: }
128: (*newdm)->setupcalled = dm->setupcalled;
129: DMGetPointSF(dm, &sf);
130: DMSetPointSF(*newdm, sf);
131: DMGetApplicationContext(dm, &ctx);
132: DMSetApplicationContext(*newdm, ctx);
133: if (dm->coordinateDM) {
134: DM ncdm;
135: PetscSection cs;
136: PetscInt pEnd = -1, pEndMax = -1;
138: DMGetDefaultSection(dm->coordinateDM, &cs);
139: if (cs) {PetscSectionGetChart(cs, NULL, &pEnd);}
140: MPI_Allreduce(&pEnd,&pEndMax,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));
141: if (pEndMax >= 0) {
142: DMClone(dm->coordinateDM, &ncdm);
143: DMSetDefaultSection(ncdm, cs);
144: DMSetCoordinateDM(*newdm, ncdm);
145: DMDestroy(&ncdm);
146: }
147: }
148: DMGetCoordinateDim(dm, &cdim);
149: DMSetCoordinateDim(*newdm, cdim);
150: DMGetCoordinatesLocal(dm, &coords);
151: if (coords) {
152: DMSetCoordinatesLocal(*newdm, coords);
153: } else {
154: DMGetCoordinates(dm, &coords);
155: if (coords) {DMSetCoordinates(*newdm, coords);}
156: }
157: {
158: PetscBool isper;
159: const PetscReal *maxCell, *L;
160: const DMBoundaryType *bd;
161: DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);
162: DMSetPeriodicity(*newdm, isper, maxCell, L, bd);
163: }
164: return(0);
165: }
167: /*@C
168: DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()
170: Logically Collective on DM
172: Input Parameter:
173: + da - initial distributed array
174: . ctype - the vector type, currently either VECSTANDARD, VECCUDA, or VECVIENNACL
176: Options Database:
177: . -dm_vec_type ctype
179: Level: intermediate
181: .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType, DMGetVecType()
182: @*/
183: PetscErrorCode DMSetVecType(DM da,VecType ctype)
184: {
189: PetscFree(da->vectype);
190: PetscStrallocpy(ctype,(char**)&da->vectype);
191: return(0);
192: }
194: /*@C
195: DMGetVecType - Gets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()
197: Logically Collective on DM
199: Input Parameter:
200: . da - initial distributed array
202: Output Parameter:
203: . ctype - the vector type
205: Level: intermediate
207: .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType
208: @*/
209: PetscErrorCode DMGetVecType(DM da,VecType *ctype)
210: {
213: *ctype = da->vectype;
214: return(0);
215: }
217: /*@
218: VecGetDM - Gets the DM defining the data layout of the vector
220: Not collective
222: Input Parameter:
223: . v - The Vec
225: Output Parameter:
226: . dm - The DM
228: Level: intermediate
230: .seealso: VecSetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType()
231: @*/
232: PetscErrorCode VecGetDM(Vec v, DM *dm)
233: {
239: PetscObjectQuery((PetscObject) v, "__PETSc_dm", (PetscObject*) dm);
240: return(0);
241: }
243: /*@
244: VecSetDM - Sets the DM defining the data layout of the vector.
246: Not collective
248: Input Parameters:
249: + v - The Vec
250: - dm - The DM
252: Note: This is NOT the same as DMCreateGlobalVector() since it does not change the view methods or perform other customization, but merely sets the DM member.
254: Level: intermediate
256: .seealso: VecGetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType()
257: @*/
258: PetscErrorCode VecSetDM(Vec v, DM dm)
259: {
265: PetscObjectCompose((PetscObject) v, "__PETSc_dm", (PetscObject) dm);
266: return(0);
267: }
269: /*@C
270: DMSetISColoringType - Sets the type of coloring, global or local, that is created by the DM
272: Logically Collective on DM
274: Input Parameters:
275: + dm - the DM context
276: - ctype - the matrix type
278: Options Database:
279: . -dm_is_coloring_type - global or local
281: Level: intermediate
283: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(),
284: DMGetISColoringType()
285: @*/
286: PetscErrorCode DMSetISColoringType(DM dm,ISColoringType ctype)
287: {
290: dm->coloringtype = ctype;
291: return(0);
292: }
294: /*@C
295: DMGetISColoringType - Gets the type of coloring, global or local, that is created by the DM
297: Logically Collective on DM
299: Input Parameter:
300: . dm - the DM context
302: Output Parameter:
303: . ctype - the matrix type
305: Options Database:
306: . -dm_is_coloring_type - global or local
308: Level: intermediate
310: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(),
311: DMGetISColoringType()
312: @*/
313: PetscErrorCode DMGetISColoringType(DM dm,ISColoringType *ctype)
314: {
317: *ctype = dm->coloringtype;
318: return(0);
319: }
321: /*@C
322: DMSetMatType - Sets the type of matrix created with DMCreateMatrix()
324: Logically Collective on DM
326: Input Parameters:
327: + dm - the DM context
328: - ctype - the matrix type
330: Options Database:
331: . -dm_mat_type ctype
333: Level: intermediate
335: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType()
336: @*/
337: PetscErrorCode DMSetMatType(DM dm,MatType ctype)
338: {
343: PetscFree(dm->mattype);
344: PetscStrallocpy(ctype,(char**)&dm->mattype);
345: return(0);
346: }
348: /*@C
349: DMGetMatType - Gets the type of matrix created with DMCreateMatrix()
351: Logically Collective on DM
353: Input Parameter:
354: . dm - the DM context
356: Output Parameter:
357: . ctype - the matrix type
359: Options Database:
360: . -dm_mat_type ctype
362: Level: intermediate
364: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMSetMatType()
365: @*/
366: PetscErrorCode DMGetMatType(DM dm,MatType *ctype)
367: {
370: *ctype = dm->mattype;
371: return(0);
372: }
374: /*@
375: MatGetDM - Gets the DM defining the data layout of the matrix
377: Not collective
379: Input Parameter:
380: . A - The Mat
382: Output Parameter:
383: . dm - The DM
385: Level: intermediate
387: Developer Note: Since the Mat class doesn't know about the DM class the DM object is associated with
388: the Mat through a PetscObjectCompose() operation
390: .seealso: MatSetDM(), DMCreateMatrix(), DMSetMatType()
391: @*/
392: PetscErrorCode MatGetDM(Mat A, DM *dm)
393: {
399: PetscObjectQuery((PetscObject) A, "__PETSc_dm", (PetscObject*) dm);
400: return(0);
401: }
403: /*@
404: MatSetDM - Sets the DM defining the data layout of the matrix
406: Not collective
408: Input Parameters:
409: + A - The Mat
410: - dm - The DM
412: Level: intermediate
414: Developer Note: Since the Mat class doesn't know about the DM class the DM object is associated with
415: the Mat through a PetscObjectCompose() operation
418: .seealso: MatGetDM(), DMCreateMatrix(), DMSetMatType()
419: @*/
420: PetscErrorCode MatSetDM(Mat A, DM dm)
421: {
427: PetscObjectCompose((PetscObject) A, "__PETSc_dm", (PetscObject) dm);
428: return(0);
429: }
431: /*@C
432: DMSetOptionsPrefix - Sets the prefix used for searching for all
433: DM options in the database.
435: Logically Collective on DM
437: Input Parameter:
438: + da - the DM context
439: - prefix - the prefix to prepend to all option names
441: Notes:
442: A hyphen (-) must NOT be given at the beginning of the prefix name.
443: The first character of all runtime options is AUTOMATICALLY the hyphen.
445: Level: advanced
447: .keywords: DM, set, options, prefix, database
449: .seealso: DMSetFromOptions()
450: @*/
451: PetscErrorCode DMSetOptionsPrefix(DM dm,const char prefix[])
452: {
457: PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);
458: if (dm->sf) {
459: PetscObjectSetOptionsPrefix((PetscObject)dm->sf,prefix);
460: }
461: if (dm->defaultSF) {
462: PetscObjectSetOptionsPrefix((PetscObject)dm->defaultSF,prefix);
463: }
464: return(0);
465: }
467: /*@C
468: DMAppendOptionsPrefix - Appends to the prefix used for searching for all
469: DM options in the database.
471: Logically Collective on DM
473: Input Parameters:
474: + dm - the DM context
475: - prefix - the prefix string to prepend to all DM option requests
477: Notes:
478: A hyphen (-) must NOT be given at the beginning of the prefix name.
479: The first character of all runtime options is AUTOMATICALLY the hyphen.
481: Level: advanced
483: .keywords: DM, append, options, prefix, database
485: .seealso: DMSetOptionsPrefix(), DMGetOptionsPrefix()
486: @*/
487: PetscErrorCode DMAppendOptionsPrefix(DM dm,const char prefix[])
488: {
493: PetscObjectAppendOptionsPrefix((PetscObject)dm,prefix);
494: return(0);
495: }
497: /*@C
498: DMGetOptionsPrefix - Gets the prefix used for searching for all
499: DM options in the database.
501: Not Collective
503: Input Parameters:
504: . dm - the DM context
506: Output Parameters:
507: . prefix - pointer to the prefix string used is returned
509: Notes: On the fortran side, the user should pass in a string 'prefix' of
510: sufficient length to hold the prefix.
512: Level: advanced
514: .keywords: DM, set, options, prefix, database
516: .seealso: DMSetOptionsPrefix(), DMAppendOptionsPrefix()
517: @*/
518: PetscErrorCode DMGetOptionsPrefix(DM dm,const char *prefix[])
519: {
524: PetscObjectGetOptionsPrefix((PetscObject)dm,prefix);
525: return(0);
526: }
528: static PetscErrorCode DMCountNonCyclicReferences(DM dm, PetscBool recurseCoarse, PetscBool recurseFine, PetscInt *ncrefct)
529: {
530: PetscInt i, refct = ((PetscObject) dm)->refct;
531: DMNamedVecLink nlink;
535: *ncrefct = 0;
536: /* count all the circular references of DM and its contained Vecs */
537: for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
538: if (dm->localin[i]) refct--;
539: if (dm->globalin[i]) refct--;
540: }
541: for (nlink=dm->namedglobal; nlink; nlink=nlink->next) refct--;
542: for (nlink=dm->namedlocal; nlink; nlink=nlink->next) refct--;
543: if (dm->x) {
544: DM obj;
545: VecGetDM(dm->x, &obj);
546: if (obj == dm) refct--;
547: }
548: if (dm->coarseMesh && dm->coarseMesh->fineMesh == dm) {
549: refct--;
550: if (recurseCoarse) {
551: PetscInt coarseCount;
553: DMCountNonCyclicReferences(dm->coarseMesh, PETSC_TRUE, PETSC_FALSE,&coarseCount);
554: refct += coarseCount;
555: }
556: }
557: if (dm->fineMesh && dm->fineMesh->coarseMesh == dm) {
558: refct--;
559: if (recurseFine) {
560: PetscInt fineCount;
562: DMCountNonCyclicReferences(dm->fineMesh, PETSC_FALSE, PETSC_TRUE,&fineCount);
563: refct += fineCount;
564: }
565: }
566: *ncrefct = refct;
567: return(0);
568: }
570: PetscErrorCode DMDestroyLabelLinkList(DM dm)
571: {
575: if (!--(dm->labels->refct)) {
576: DMLabelLink next = dm->labels->next;
578: /* destroy the labels */
579: while (next) {
580: DMLabelLink tmp = next->next;
582: DMLabelDestroy(&next->label);
583: PetscFree(next);
584: next = tmp;
585: }
586: PetscFree(dm->labels);
587: }
588: return(0);
589: }
591: /*@
592: DMDestroy - Destroys a vector packer or DM.
594: Collective on DM
596: Input Parameter:
597: . dm - the DM object to destroy
599: Level: developer
601: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
603: @*/
604: PetscErrorCode DMDestroy(DM *dm)
605: {
606: PetscInt i, cnt;
607: DMNamedVecLink nlink,nnext;
611: if (!*dm) return(0);
614: /* count all non-cyclic references in the doubly-linked list of coarse<->fine meshes */
615: DMCountNonCyclicReferences(*dm,PETSC_TRUE,PETSC_TRUE,&cnt);
616: --((PetscObject)(*dm))->refct;
617: if (--cnt > 0) {*dm = 0; return(0);}
618: /*
619: Need this test because the dm references the vectors that
620: reference the dm, so destroying the dm calls destroy on the
621: vectors that cause another destroy on the dm
622: */
623: if (((PetscObject)(*dm))->refct < 0) return(0);
624: ((PetscObject) (*dm))->refct = 0;
625: for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
626: if ((*dm)->localout[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Destroying a DM that has a local vector obtained with DMGetLocalVector()");
627: VecDestroy(&(*dm)->localin[i]);
628: }
629: nnext=(*dm)->namedglobal;
630: (*dm)->namedglobal = NULL;
631: for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named vectors */
632: nnext = nlink->next;
633: if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name);
634: PetscFree(nlink->name);
635: VecDestroy(&nlink->X);
636: PetscFree(nlink);
637: }
638: nnext=(*dm)->namedlocal;
639: (*dm)->namedlocal = NULL;
640: for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named local vectors */
641: nnext = nlink->next;
642: if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name);
643: PetscFree(nlink->name);
644: VecDestroy(&nlink->X);
645: PetscFree(nlink);
646: }
648: /* Destroy the list of hooks */
649: {
650: DMCoarsenHookLink link,next;
651: for (link=(*dm)->coarsenhook; link; link=next) {
652: next = link->next;
653: PetscFree(link);
654: }
655: (*dm)->coarsenhook = NULL;
656: }
657: {
658: DMRefineHookLink link,next;
659: for (link=(*dm)->refinehook; link; link=next) {
660: next = link->next;
661: PetscFree(link);
662: }
663: (*dm)->refinehook = NULL;
664: }
665: {
666: DMSubDomainHookLink link,next;
667: for (link=(*dm)->subdomainhook; link; link=next) {
668: next = link->next;
669: PetscFree(link);
670: }
671: (*dm)->subdomainhook = NULL;
672: }
673: {
674: DMGlobalToLocalHookLink link,next;
675: for (link=(*dm)->gtolhook; link; link=next) {
676: next = link->next;
677: PetscFree(link);
678: }
679: (*dm)->gtolhook = NULL;
680: }
681: {
682: DMLocalToGlobalHookLink link,next;
683: for (link=(*dm)->ltoghook; link; link=next) {
684: next = link->next;
685: PetscFree(link);
686: }
687: (*dm)->ltoghook = NULL;
688: }
689: /* Destroy the work arrays */
690: {
691: DMWorkLink link,next;
692: if ((*dm)->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out");
693: for (link=(*dm)->workin; link; link=next) {
694: next = link->next;
695: PetscFree(link->mem);
696: PetscFree(link);
697: }
698: (*dm)->workin = NULL;
699: }
700: if (!--((*dm)->labels->refct)) {
701: DMLabelLink next = (*dm)->labels->next;
703: /* destroy the labels */
704: while (next) {
705: DMLabelLink tmp = next->next;
707: DMLabelDestroy(&next->label);
708: PetscFree(next);
709: next = tmp;
710: }
711: PetscFree((*dm)->labels);
712: }
713: {
714: DMBoundary next = (*dm)->boundary;
715: while (next) {
716: DMBoundary b = next;
718: next = b->next;
719: PetscFree(b);
720: }
721: }
723: PetscObjectDestroy(&(*dm)->dmksp);
724: PetscObjectDestroy(&(*dm)->dmsnes);
725: PetscObjectDestroy(&(*dm)->dmts);
727: if ((*dm)->ctx && (*dm)->ctxdestroy) {
728: (*(*dm)->ctxdestroy)(&(*dm)->ctx);
729: }
730: VecDestroy(&(*dm)->x);
731: MatFDColoringDestroy(&(*dm)->fd);
732: DMClearGlobalVectors(*dm);
733: ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);
734: PetscFree((*dm)->vectype);
735: PetscFree((*dm)->mattype);
737: PetscSectionDestroy(&(*dm)->defaultSection);
738: PetscSectionDestroy(&(*dm)->defaultGlobalSection);
739: PetscLayoutDestroy(&(*dm)->map);
740: PetscSectionDestroy(&(*dm)->defaultConstraintSection);
741: MatDestroy(&(*dm)->defaultConstraintMat);
742: PetscSFDestroy(&(*dm)->sf);
743: PetscSFDestroy(&(*dm)->defaultSF);
744: if ((*dm)->useNatural) {
745: if ((*dm)->sfNatural) {
746: PetscSFDestroy(&(*dm)->sfNatural);
747: }
748: PetscObjectDereference((PetscObject) (*dm)->sfMigration);
749: }
750: if ((*dm)->coarseMesh && (*dm)->coarseMesh->fineMesh == *dm) {
751: DMSetFineDM((*dm)->coarseMesh,NULL);
752: }
753: DMDestroy(&(*dm)->coarseMesh);
754: if ((*dm)->fineMesh && (*dm)->fineMesh->coarseMesh == *dm) {
755: DMSetCoarseDM((*dm)->fineMesh,NULL);
756: }
757: DMDestroy(&(*dm)->fineMesh);
758: DMDestroy(&(*dm)->coordinateDM);
759: VecDestroy(&(*dm)->coordinates);
760: VecDestroy(&(*dm)->coordinatesLocal);
761: PetscFree3((*dm)->L,(*dm)->maxCell,(*dm)->bdtype);
763: PetscDSDestroy(&(*dm)->prob);
764: DMDestroy(&(*dm)->dmBC);
765: /* if memory was published with SAWs then destroy it */
766: PetscObjectSAWsViewOff((PetscObject)*dm);
768: (*(*dm)->ops->destroy)(*dm);
769: /* We do not destroy (*dm)->data here so that we can reference count backend objects */
770: PetscHeaderDestroy(dm);
771: return(0);
772: }
774: /*@
775: DMSetUp - sets up the data structures inside a DM object
777: Collective on DM
779: Input Parameter:
780: . dm - the DM object to setup
782: Level: developer
784: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
786: @*/
787: PetscErrorCode DMSetUp(DM dm)
788: {
793: if (dm->setupcalled) return(0);
794: if (dm->ops->setup) {
795: (*dm->ops->setup)(dm);
796: }
797: dm->setupcalled = PETSC_TRUE;
798: return(0);
799: }
801: /*@
802: DMSetFromOptions - sets parameters in a DM from the options database
804: Collective on DM
806: Input Parameter:
807: . dm - the DM object to set options for
809: Options Database:
810: + -dm_preallocate_only - Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros
811: . -dm_vec_type <type> - type of vector to create inside DM
812: . -dm_mat_type <type> - type of matrix to create inside DM
813: - -dm_is_coloring_type - <global or local>
815: Level: developer
817: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
819: @*/
820: PetscErrorCode DMSetFromOptions(DM dm)
821: {
822: char typeName[256];
823: PetscBool flg;
828: if (dm->prob) {
829: PetscDSSetFromOptions(dm->prob);
830: }
831: if (dm->sf) {
832: PetscSFSetFromOptions(dm->sf);
833: }
834: if (dm->defaultSF) {
835: PetscSFSetFromOptions(dm->defaultSF);
836: }
837: PetscObjectOptionsBegin((PetscObject)dm);
838: PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,NULL);
839: PetscOptionsFList("-dm_vec_type","Vector type used for created vectors","DMSetVecType",VecList,dm->vectype,typeName,256,&flg);
840: if (flg) {
841: DMSetVecType(dm,typeName);
842: }
843: PetscOptionsFList("-dm_mat_type","Matrix type used for created matrices","DMSetMatType",MatList,dm->mattype ? dm->mattype : typeName,typeName,sizeof(typeName),&flg);
844: if (flg) {
845: DMSetMatType(dm,typeName);
846: }
847: PetscOptionsEnum("-dm_is_coloring_type","Global or local coloring of Jacobian","DMSetISColoringType",ISColoringTypes,(PetscEnum)dm->coloringtype,(PetscEnum*)&dm->coloringtype,NULL);
848: if (dm->ops->setfromoptions) {
849: (*dm->ops->setfromoptions)(PetscOptionsObject,dm);
850: }
851: /* process any options handlers added with PetscObjectAddOptionsHandler() */
852: PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) dm);
853: PetscOptionsEnd();
854: return(0);
855: }
857: /*@C
858: DMView - Views a DM
860: Collective on DM
862: Input Parameter:
863: + dm - the DM object to view
864: - v - the viewer
866: Level: beginner
868: .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
870: @*/
871: PetscErrorCode DMView(DM dm,PetscViewer v)
872: {
873: PetscErrorCode ierr;
874: PetscBool isbinary;
875: PetscMPIInt size;
876: PetscViewerFormat format;
877: PetscInt tabs;
881: if (!v) {
882: PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm),&v);
883: }
884: PetscViewerGetFormat(v,&format);
885: MPI_Comm_size(PetscObjectComm((PetscObject)dm),&size);
886: if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) return(0);
887: PetscViewerASCIIGetTab(v, &tabs);
888: PetscViewerASCIISetTab(v, ((PetscObject)dm)->tablevel);
889: PetscObjectPrintClassNamePrefixType((PetscObject)dm,v);
890: PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERBINARY,&isbinary);
891: if (isbinary) {
892: PetscInt classid = DM_FILE_CLASSID;
893: char type[256];
895: PetscViewerBinaryWrite(v,&classid,1,PETSC_INT,PETSC_FALSE);
896: PetscStrncpy(type,((PetscObject)dm)->type_name,256);
897: PetscViewerBinaryWrite(v,type,256,PETSC_CHAR,PETSC_FALSE);
898: }
899: if (dm->ops->view) {
900: (*dm->ops->view)(dm,v);
901: }
902: PetscViewerASCIISetTab(v, tabs);
903: return(0);
904: }
906: /*@
907: DMCreateGlobalVector - Creates a global vector from a DM object
909: Collective on DM
911: Input Parameter:
912: . dm - the DM object
914: Output Parameter:
915: . vec - the global vector
917: Level: beginner
919: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
921: @*/
922: PetscErrorCode DMCreateGlobalVector(DM dm,Vec *vec)
923: {
928: (*dm->ops->createglobalvector)(dm,vec);
929: return(0);
930: }
932: /*@
933: DMCreateLocalVector - Creates a local vector from a DM object
935: Not Collective
937: Input Parameter:
938: . dm - the DM object
940: Output Parameter:
941: . vec - the local vector
943: Level: beginner
945: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
947: @*/
948: PetscErrorCode DMCreateLocalVector(DM dm,Vec *vec)
949: {
954: (*dm->ops->createlocalvector)(dm,vec);
955: return(0);
956: }
958: /*@
959: DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM.
961: Collective on DM
963: Input Parameter:
964: . dm - the DM that provides the mapping
966: Output Parameter:
967: . ltog - the mapping
969: Level: intermediate
971: Notes:
972: This mapping can then be used by VecSetLocalToGlobalMapping() or
973: MatSetLocalToGlobalMapping().
975: .seealso: DMCreateLocalVector()
976: @*/
977: PetscErrorCode DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog)
978: {
979: PetscInt bs = -1, bsLocal[2], bsMinMax[2];
985: if (!dm->ltogmap) {
986: PetscSection section, sectionGlobal;
988: DMGetDefaultSection(dm, §ion);
989: if (section) {
990: const PetscInt *cdofs;
991: PetscInt *ltog;
992: PetscInt pStart, pEnd, n, p, k, l;
994: DMGetDefaultGlobalSection(dm, §ionGlobal);
995: PetscSectionGetChart(section, &pStart, &pEnd);
996: PetscSectionGetStorageSize(section, &n);
997: PetscMalloc1(n, <og); /* We want the local+overlap size */
998: for (p = pStart, l = 0; p < pEnd; ++p) {
999: PetscInt bdof, cdof, dof, off, c, cind = 0;
1001: /* Should probably use constrained dofs */
1002: PetscSectionGetDof(section, p, &dof);
1003: PetscSectionGetConstraintDof(section, p, &cdof);
1004: PetscSectionGetConstraintIndices(section, p, &cdofs);
1005: PetscSectionGetOffset(sectionGlobal, p, &off);
1006: /* If you have dofs, and constraints, and they are unequal, we set the blocksize to 1 */
1007: bdof = cdof && (dof-cdof) ? 1 : dof;
1008: if (dof) {
1009: if (bs < 0) {bs = bdof;}
1010: else if (bs != bdof) {bs = 1;}
1011: }
1012: for (c = 0; c < dof; ++c, ++l) {
1013: if ((cind < cdof) && (c == cdofs[cind])) ltog[l] = off < 0 ? off-c : off+c;
1014: else ltog[l] = (off < 0 ? -(off+1) : off) + c;
1015: }
1016: }
1017: /* Must have same blocksize on all procs (some might have no points) */
1018: bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs;
1019: PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);
1020: if (bsMinMax[0] != bsMinMax[1]) {bs = 1;}
1021: else {bs = bsMinMax[0];}
1022: bs = bs < 0 ? 1 : bs;
1023: /* Must reduce indices by blocksize */
1024: if (bs > 1) {
1025: for (l = 0, k = 0; l < n; l += bs, ++k) ltog[k] = ltog[l]/bs;
1026: n /= bs;
1027: }
1028: ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, n, ltog, PETSC_OWN_POINTER, &dm->ltogmap);
1029: PetscLogObjectParent((PetscObject)dm, (PetscObject)dm->ltogmap);
1030: } else {
1031: if (!dm->ops->getlocaltoglobalmapping) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM can not create LocalToGlobalMapping");
1032: (*dm->ops->getlocaltoglobalmapping)(dm);
1033: }
1034: }
1035: *ltog = dm->ltogmap;
1036: return(0);
1037: }
1039: /*@
1040: DMGetBlockSize - Gets the inherent block size associated with a DM
1042: Not Collective
1044: Input Parameter:
1045: . dm - the DM with block structure
1047: Output Parameter:
1048: . bs - the block size, 1 implies no exploitable block structure
1050: Level: intermediate
1052: .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMapping()
1053: @*/
1054: PetscErrorCode DMGetBlockSize(DM dm,PetscInt *bs)
1055: {
1059: if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet");
1060: *bs = dm->bs;
1061: return(0);
1062: }
1064: /*@
1065: DMCreateInterpolation - Gets interpolation matrix between two DM objects
1067: Collective on DM
1069: Input Parameter:
1070: + dm1 - the DM object
1071: - dm2 - the second, finer DM object
1073: Output Parameter:
1074: + mat - the interpolation
1075: - vec - the scaling (optional)
1077: Level: developer
1079: Notes: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
1080: DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation.
1082: For DMDA objects you can use this interpolation (more precisely the interpolation from the DMGetCoordinateDM()) to interpolate the mesh coordinate vectors
1083: EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic.
1086: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateRestriction()
1088: @*/
1089: PetscErrorCode DMCreateInterpolation(DM dm1,DM dm2,Mat *mat,Vec *vec)
1090: {
1096: PetscLogEventBegin(DM_CreateInterpolation,dm1,dm2,0,0);
1097: (*dm1->ops->createinterpolation)(dm1,dm2,mat,vec);
1098: PetscLogEventEnd(DM_CreateInterpolation,dm1,dm2,0,0);
1099: return(0);
1100: }
1102: /*@
1103: DMCreateRestriction - Gets restriction matrix between two DM objects
1105: Collective on DM
1107: Input Parameter:
1108: + dm1 - the DM object
1109: - dm2 - the second, finer DM object
1111: Output Parameter:
1112: . mat - the restriction
1115: Level: developer
1117: Notes: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
1118: DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation.
1121: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateInterpolation()
1123: @*/
1124: PetscErrorCode DMCreateRestriction(DM dm1,DM dm2,Mat *mat)
1125: {
1131: PetscLogEventBegin(DM_CreateRestriction,dm1,dm2,0,0);
1132: if (!dm1->ops->createrestriction) SETERRQ(PetscObjectComm((PetscObject)dm1),PETSC_ERR_SUP,"DMCreateRestriction not implemented for this type");
1133: (*dm1->ops->createrestriction)(dm1,dm2,mat);
1134: PetscLogEventEnd(DM_CreateRestriction,dm1,dm2,0,0);
1135: return(0);
1136: }
1138: /*@
1139: DMCreateInjection - Gets injection matrix between two DM objects
1141: Collective on DM
1143: Input Parameter:
1144: + dm1 - the DM object
1145: - dm2 - the second, finer DM object
1147: Output Parameter:
1148: . mat - the injection
1150: Level: developer
1152: Notes: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
1153: DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection.
1155: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMCreateInterpolation()
1157: @*/
1158: PetscErrorCode DMCreateInjection(DM dm1,DM dm2,Mat *mat)
1159: {
1165: if (!dm1->ops->getinjection) SETERRQ(PetscObjectComm((PetscObject)dm1),PETSC_ERR_SUP,"DMCreateInjection not implemented for this type");
1166: (*dm1->ops->getinjection)(dm1,dm2,mat);
1167: return(0);
1168: }
1170: /*@
1171: DMCreateMassMatrix - Gets mass matrix between two DM objects, M_ij = \int \phi_i \psi_j
1173: Collective on DM
1175: Input Parameter:
1176: + dm1 - the DM object
1177: - dm2 - the second, finer DM object
1179: Output Parameter:
1180: . mat - the interpolation
1182: Level: developer
1184: .seealso DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateRestriction(), DMCreateInterpolation(), DMCreateInjection()
1185: @*/
1186: PetscErrorCode DMCreateMassMatrix(DM dm1, DM dm2, Mat *mat)
1187: {
1193: (*dm1->ops->createmassmatrix)(dm1, dm2, mat);
1194: return(0);
1195: }
1197: /*@
1198: DMCreateColoring - Gets coloring for a DM
1200: Collective on DM
1202: Input Parameter:
1203: + dm - the DM object
1204: - ctype - IS_COLORING_LOCAL or IS_COLORING_GLOBAL
1206: Output Parameter:
1207: . coloring - the coloring
1209: Level: developer
1211: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateMatrix(), DMSetMatType()
1213: @*/
1214: PetscErrorCode DMCreateColoring(DM dm,ISColoringType ctype,ISColoring *coloring)
1215: {
1220: if (!dm->ops->getcoloring) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No coloring for this type of DM yet");
1221: (*dm->ops->getcoloring)(dm,ctype,coloring);
1222: return(0);
1223: }
1225: /*@
1226: DMCreateMatrix - Gets empty Jacobian for a DM
1228: Collective on DM
1230: Input Parameter:
1231: . dm - the DM object
1233: Output Parameter:
1234: . mat - the empty Jacobian
1236: Level: beginner
1238: Notes: This properly preallocates the number of nonzeros in the sparse matrix so you
1239: do not need to do it yourself.
1241: By default it also sets the nonzero structure and puts in the zero entries. To prevent setting
1242: the nonzero pattern call DMSetMatrixPreallocateOnly()
1244: For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used
1245: internally by PETSc.
1247: For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires
1248: the indices for the global numbering for DMDAs which is complicated.
1250: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMSetMatType()
1252: @*/
1253: PetscErrorCode DMCreateMatrix(DM dm,Mat *mat)
1254: {
1259: MatInitializePackage();
1262: (*dm->ops->creatematrix)(dm,mat);
1263: return(0);
1264: }
1266: /*@
1267: DMSetMatrixPreallocateOnly - When DMCreateMatrix() is called the matrix will be properly
1268: preallocated but the nonzero structure and zero values will not be set.
1270: Logically Collective on DM
1272: Input Parameter:
1273: + dm - the DM
1274: - only - PETSC_TRUE if only want preallocation
1276: Level: developer
1277: .seealso DMCreateMatrix(), DMSetMatrixStructureOnly()
1278: @*/
1279: PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only)
1280: {
1283: dm->prealloc_only = only;
1284: return(0);
1285: }
1287: /*@
1288: DMSetMatrixStructureOnly - When DMCreateMatrix() is called, the matrix structure will be created
1289: but the array for values will not be allocated.
1291: Logically Collective on DM
1293: Input Parameter:
1294: + dm - the DM
1295: - only - PETSC_TRUE if only want matrix stucture
1297: Level: developer
1298: .seealso DMCreateMatrix(), DMSetMatrixPreallocateOnly()
1299: @*/
1300: PetscErrorCode DMSetMatrixStructureOnly(DM dm, PetscBool only)
1301: {
1304: dm->structure_only = only;
1305: return(0);
1306: }
1308: /*@C
1309: DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray()
1311: Not Collective
1313: Input Parameters:
1314: + dm - the DM object
1315: . count - The minium size
1316: - dtype - MPI data type, often MPIU_REAL, MPIU_SCALAR, MPIU_INT)
1318: Output Parameter:
1319: . array - the work array
1321: Level: developer
1323: .seealso DMDestroy(), DMCreate()
1324: @*/
1325: PetscErrorCode DMGetWorkArray(DM dm,PetscInt count,MPI_Datatype dtype,void *mem)
1326: {
1328: DMWorkLink link;
1329: PetscMPIInt dsize;
1334: if (dm->workin) {
1335: link = dm->workin;
1336: dm->workin = dm->workin->next;
1337: } else {
1338: PetscNewLog(dm,&link);
1339: }
1340: MPI_Type_size(dtype,&dsize);
1341: if (((size_t)dsize*count) > link->bytes) {
1342: PetscFree(link->mem);
1343: PetscMalloc(dsize*count,&link->mem);
1344: link->bytes = dsize*count;
1345: }
1346: link->next = dm->workout;
1347: dm->workout = link;
1348: *(void**)mem = link->mem;
1349: return(0);
1350: }
1352: /*@C
1353: DMRestoreWorkArray - Restores a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray()
1355: Not Collective
1357: Input Parameters:
1358: + dm - the DM object
1359: . count - The minium size
1360: - dtype - MPI data type, often MPIU_REAL, MPIU_SCALAR, MPIU_INT
1362: Output Parameter:
1363: . array - the work array
1365: Level: developer
1367: Developer Notes: count and dtype are ignored, they are only needed for DMGetWorkArray()
1368: .seealso DMDestroy(), DMCreate()
1369: @*/
1370: PetscErrorCode DMRestoreWorkArray(DM dm,PetscInt count,MPI_Datatype dtype,void *mem)
1371: {
1372: DMWorkLink *p,link;
1377: for (p=&dm->workout; (link=*p); p=&link->next) {
1378: if (link->mem == *(void**)mem) {
1379: *p = link->next;
1380: link->next = dm->workin;
1381: dm->workin = link;
1382: *(void**)mem = NULL;
1383: return(0);
1384: }
1385: }
1386: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out");
1387: }
1389: PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt field, MatNullSpace *nullSpace))
1390: {
1393: if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field);
1394: dm->nullspaceConstructors[field] = nullsp;
1395: return(0);
1396: }
1398: /*@C
1399: DMCreateFieldIS - Creates a set of IS objects with the global indices of dofs for each field
1401: Not collective
1403: Input Parameter:
1404: . dm - the DM object
1406: Output Parameters:
1407: + numFields - The number of fields (or NULL if not requested)
1408: . fieldNames - The name for each field (or NULL if not requested)
1409: - fields - The global indices for each field (or NULL if not requested)
1411: Level: intermediate
1413: Notes:
1414: The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1415: PetscFree(), every entry of fields should be destroyed with ISDestroy(), and both arrays should be freed with
1416: PetscFree().
1418: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
1419: @*/
1420: PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields)
1421: {
1422: PetscSection section, sectionGlobal;
1427: if (numFields) {
1429: *numFields = 0;
1430: }
1431: if (fieldNames) {
1433: *fieldNames = NULL;
1434: }
1435: if (fields) {
1437: *fields = NULL;
1438: }
1439: DMGetDefaultSection(dm, §ion);
1440: if (section) {
1441: PetscInt *fieldSizes, **fieldIndices;
1442: PetscInt nF, f, pStart, pEnd, p;
1444: DMGetDefaultGlobalSection(dm, §ionGlobal);
1445: PetscSectionGetNumFields(section, &nF);
1446: PetscMalloc2(nF,&fieldSizes,nF,&fieldIndices);
1447: PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);
1448: for (f = 0; f < nF; ++f) {
1449: fieldSizes[f] = 0;
1450: }
1451: for (p = pStart; p < pEnd; ++p) {
1452: PetscInt gdof;
1454: PetscSectionGetDof(sectionGlobal, p, &gdof);
1455: if (gdof > 0) {
1456: for (f = 0; f < nF; ++f) {
1457: PetscInt fdof, fcdof;
1459: PetscSectionGetFieldDof(section, p, f, &fdof);
1460: PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);
1461: fieldSizes[f] += fdof-fcdof;
1462: }
1463: }
1464: }
1465: for (f = 0; f < nF; ++f) {
1466: PetscMalloc1(fieldSizes[f], &fieldIndices[f]);
1467: fieldSizes[f] = 0;
1468: }
1469: for (p = pStart; p < pEnd; ++p) {
1470: PetscInt gdof, goff;
1472: PetscSectionGetDof(sectionGlobal, p, &gdof);
1473: if (gdof > 0) {
1474: PetscSectionGetOffset(sectionGlobal, p, &goff);
1475: for (f = 0; f < nF; ++f) {
1476: PetscInt fdof, fcdof, fc;
1478: PetscSectionGetFieldDof(section, p, f, &fdof);
1479: PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);
1480: for (fc = 0; fc < fdof-fcdof; ++fc, ++fieldSizes[f]) {
1481: fieldIndices[f][fieldSizes[f]] = goff++;
1482: }
1483: }
1484: }
1485: }
1486: if (numFields) *numFields = nF;
1487: if (fieldNames) {
1488: PetscMalloc1(nF, fieldNames);
1489: for (f = 0; f < nF; ++f) {
1490: const char *fieldName;
1492: PetscSectionGetFieldName(section, f, &fieldName);
1493: PetscStrallocpy(fieldName, (char**) &(*fieldNames)[f]);
1494: }
1495: }
1496: if (fields) {
1497: PetscMalloc1(nF, fields);
1498: for (f = 0; f < nF; ++f) {
1499: ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]);
1500: }
1501: }
1502: PetscFree2(fieldSizes,fieldIndices);
1503: } else if (dm->ops->createfieldis) {
1504: (*dm->ops->createfieldis)(dm, numFields, fieldNames, fields);
1505: }
1506: return(0);
1507: }
1510: /*@C
1511: DMCreateFieldDecomposition - Returns a list of IS objects defining a decomposition of a problem into subproblems
1512: corresponding to different fields: each IS contains the global indices of the dofs of the
1513: corresponding field. The optional list of DMs define the DM for each subproblem.
1514: Generalizes DMCreateFieldIS().
1516: Not collective
1518: Input Parameter:
1519: . dm - the DM object
1521: Output Parameters:
1522: + len - The number of subproblems in the field decomposition (or NULL if not requested)
1523: . namelist - The name for each field (or NULL if not requested)
1524: . islist - The global indices for each field (or NULL if not requested)
1525: - dmlist - The DMs for each field subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined)
1527: Level: intermediate
1529: Notes:
1530: The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1531: PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(),
1532: and all of the arrays should be freed with PetscFree().
1534: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1535: @*/
1536: PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
1537: {
1542: if (len) {
1544: *len = 0;
1545: }
1546: if (namelist) {
1548: *namelist = 0;
1549: }
1550: if (islist) {
1552: *islist = 0;
1553: }
1554: if (dmlist) {
1556: *dmlist = 0;
1557: }
1558: /*
1559: Is it a good idea to apply the following check across all impls?
1560: Perhaps some impls can have a well-defined decomposition before DMSetUp?
1561: This, however, follows the general principle that accessors are not well-behaved until the object is set up.
1562: */
1563: if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
1564: if (!dm->ops->createfielddecomposition) {
1565: PetscSection section;
1566: PetscInt numFields, f;
1568: DMGetDefaultSection(dm, §ion);
1569: if (section) {PetscSectionGetNumFields(section, &numFields);}
1570: if (section && numFields && dm->ops->createsubdm) {
1571: if (len) *len = numFields;
1572: if (namelist) {PetscMalloc1(numFields,namelist);}
1573: if (islist) {PetscMalloc1(numFields,islist);}
1574: if (dmlist) {PetscMalloc1(numFields,dmlist);}
1575: for (f = 0; f < numFields; ++f) {
1576: const char *fieldName;
1578: DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL);
1579: if (namelist) {
1580: PetscSectionGetFieldName(section, f, &fieldName);
1581: PetscStrallocpy(fieldName, (char**) &(*namelist)[f]);
1582: }
1583: }
1584: } else {
1585: DMCreateFieldIS(dm, len, namelist, islist);
1586: /* By default there are no DMs associated with subproblems. */
1587: if (dmlist) *dmlist = NULL;
1588: }
1589: } else {
1590: (*dm->ops->createfielddecomposition)(dm,len,namelist,islist,dmlist);
1591: }
1592: return(0);
1593: }
1595: /*@
1596: DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in.
1597: The fields are defined by DMCreateFieldIS().
1599: Not collective
1601: Input Parameters:
1602: + dm - The DM object
1603: . numFields - The number of fields in this subproblem
1604: - fields - The field numbers of the selected fields
1606: Output Parameters:
1607: + is - The global indices for the subproblem
1608: - subdm - The DM for the subproblem
1610: Level: intermediate
1612: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1613: @*/
1614: PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
1615: {
1623: if (dm->ops->createsubdm) {
1624: (*dm->ops->createsubdm)(dm, numFields, fields, is, subdm);
1625: } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateSubDM implementation defined");
1626: return(0);
1627: }
1629: /*@C
1630: DMCreateSuperDM - Returns an arrays of ISes and DM encapsulating a superproblem defined by the DMs passed in.
1632: Not collective
1634: Input Parameter:
1635: + dms - The DM objects
1636: - len - The number of DMs
1638: Output Parameters:
1639: + is - The global indices for the subproblem
1640: - superdm - The DM for the superproblem
1642: Level: intermediate
1644: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1645: @*/
1646: PetscErrorCode DMCreateSuperDM(DM dms[], PetscInt len, IS **is, DM *superdm)
1647: {
1648: PetscInt i;
1656: if (len < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of DMs must be nonnegative: %D", len);
1657: if (len) {
1658: if (dms[0]->ops->createsuperdm) {
1659: (*dms[0]->ops->createsuperdm)(dms, len, is, superdm);
1660: } else SETERRQ(PetscObjectComm((PetscObject) dms[0]), PETSC_ERR_SUP, "This type has no DMCreateSuperDM implementation defined");
1661: }
1662: return(0);
1663: }
1666: /*@C
1667: DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems
1668: corresponding to restrictions to pairs nested subdomains: each IS contains the global
1669: indices of the dofs of the corresponding subdomains. The inner subdomains conceptually
1670: define a nonoverlapping covering, while outer subdomains can overlap.
1671: The optional list of DMs define the DM for each subproblem.
1673: Not collective
1675: Input Parameter:
1676: . dm - the DM object
1678: Output Parameters:
1679: + len - The number of subproblems in the domain decomposition (or NULL if not requested)
1680: . namelist - The name for each subdomain (or NULL if not requested)
1681: . innerislist - The global indices for each inner subdomain (or NULL, if not requested)
1682: . outerislist - The global indices for each outer subdomain (or NULL, if not requested)
1683: - dmlist - The DMs for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined)
1685: Level: intermediate
1687: Notes:
1688: The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1689: PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(),
1690: and all of the arrays should be freed with PetscFree().
1692: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateDomainDecompositionDM(), DMCreateFieldDecomposition()
1693: @*/
1694: PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist)
1695: {
1696: PetscErrorCode ierr;
1697: DMSubDomainHookLink link;
1698: PetscInt i,l;
1707: /*
1708: Is it a good idea to apply the following check across all impls?
1709: Perhaps some impls can have a well-defined decomposition before DMSetUp?
1710: This, however, follows the general principle that accessors are not well-behaved until the object is set up.
1711: */
1712: if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
1713: if (dm->ops->createdomaindecomposition) {
1714: (*dm->ops->createdomaindecomposition)(dm,&l,namelist,innerislist,outerislist,dmlist);
1715: /* copy subdomain hooks and context over to the subdomain DMs */
1716: if (dmlist && *dmlist) {
1717: for (i = 0; i < l; i++) {
1718: for (link=dm->subdomainhook; link; link=link->next) {
1719: if (link->ddhook) {(*link->ddhook)(dm,(*dmlist)[i],link->ctx);}
1720: }
1721: if (dm->ctx) (*dmlist)[i]->ctx = dm->ctx;
1722: }
1723: }
1724: if (len) *len = l;
1725: }
1726: return(0);
1727: }
1730: /*@C
1731: DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector
1733: Not collective
1735: Input Parameters:
1736: + dm - the DM object
1737: . n - the number of subdomain scatters
1738: - subdms - the local subdomains
1740: Output Parameters:
1741: + n - the number of scatters returned
1742: . iscat - scatter from global vector to nonoverlapping global vector entries on subdomain
1743: . oscat - scatter from global vector to overlapping global vector entries on subdomain
1744: - gscat - scatter from global vector to local vector on subdomain (fills in ghosts)
1746: Notes: This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution
1747: of general nonlinear problems with overlapping subdomain methods. While merely having index sets that enable subsets
1748: of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of
1749: solution and residual data.
1751: Level: developer
1753: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1754: @*/
1755: PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat)
1756: {
1762: if (dm->ops->createddscatters) {
1763: (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);
1764: } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateDomainDecompositionScatter implementation defined");
1765: return(0);
1766: }
1768: /*@
1769: DMRefine - Refines a DM object
1771: Collective on DM
1773: Input Parameter:
1774: + dm - the DM object
1775: - comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
1777: Output Parameter:
1778: . dmf - the refined DM, or NULL
1780: Note: If no refinement was done, the return value is NULL
1782: Level: developer
1784: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
1785: @*/
1786: PetscErrorCode DMRefine(DM dm,MPI_Comm comm,DM *dmf)
1787: {
1788: PetscErrorCode ierr;
1789: DMRefineHookLink link;
1793: PetscLogEventBegin(DM_Refine,dm,0,0,0);
1794: if (!dm->ops->refine) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM cannot refine");
1795: (*dm->ops->refine)(dm,comm,dmf);
1796: if (*dmf) {
1797: (*dmf)->ops->creatematrix = dm->ops->creatematrix;
1799: PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);
1801: (*dmf)->ctx = dm->ctx;
1802: (*dmf)->leveldown = dm->leveldown;
1803: (*dmf)->levelup = dm->levelup + 1;
1805: DMSetMatType(*dmf,dm->mattype);
1806: for (link=dm->refinehook; link; link=link->next) {
1807: if (link->refinehook) {
1808: (*link->refinehook)(dm,*dmf,link->ctx);
1809: }
1810: }
1811: }
1812: PetscLogEventEnd(DM_Refine,dm,0,0,0);
1813: return(0);
1814: }
1816: /*@C
1817: DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid
1819: Logically Collective
1821: Input Arguments:
1822: + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level
1823: . refinehook - function to run when setting up a coarser level
1824: . interphook - function to run to update data on finer levels (once per SNESSolve())
1825: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
1827: Calling sequence of refinehook:
1828: $ refinehook(DM coarse,DM fine,void *ctx);
1830: + coarse - coarse level DM
1831: . fine - fine level DM to interpolate problem to
1832: - ctx - optional user-defined function context
1834: Calling sequence for interphook:
1835: $ interphook(DM coarse,Mat interp,DM fine,void *ctx)
1837: + coarse - coarse level DM
1838: . interp - matrix interpolating a coarse-level solution to the finer grid
1839: . fine - fine level DM to update
1840: - ctx - optional user-defined function context
1842: Level: advanced
1844: Notes:
1845: This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing
1847: If this function is called multiple times, the hooks will be run in the order they are added.
1849: This function is currently not available from Fortran.
1851: .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1852: @*/
1853: PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx)
1854: {
1855: PetscErrorCode ierr;
1856: DMRefineHookLink link,*p;
1860: for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */
1861: if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) return(0);
1862: }
1863: PetscNew(&link);
1864: link->refinehook = refinehook;
1865: link->interphook = interphook;
1866: link->ctx = ctx;
1867: link->next = NULL;
1868: *p = link;
1869: return(0);
1870: }
1872: /*@C
1873: DMRefineHookRemove - remove a callback from the list of hooks to be run when interpolating a nonlinear problem to a finer grid
1875: Logically Collective
1877: Input Arguments:
1878: + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level
1879: . refinehook - function to run when setting up a coarser level
1880: . interphook - function to run to update data on finer levels (once per SNESSolve())
1881: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
1883: Level: advanced
1885: Notes:
1886: This function does nothing if the hook is not in the list.
1888: This function is currently not available from Fortran.
1890: .seealso: DMCoarsenHookRemove(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1891: @*/
1892: PetscErrorCode DMRefineHookRemove(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx)
1893: {
1894: PetscErrorCode ierr;
1895: DMRefineHookLink link,*p;
1899: for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Search the list of current hooks */
1900: if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) {
1901: link = *p;
1902: *p = link->next;
1903: PetscFree(link);
1904: break;
1905: }
1906: }
1907: return(0);
1908: }
1910: /*@
1911: DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd()
1913: Collective if any hooks are
1915: Input Arguments:
1916: + coarse - coarser DM to use as a base
1917: . interp - interpolation matrix, apply using MatInterpolate()
1918: - fine - finer DM to update
1920: Level: developer
1922: .seealso: DMRefineHookAdd(), MatInterpolate()
1923: @*/
1924: PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine)
1925: {
1926: PetscErrorCode ierr;
1927: DMRefineHookLink link;
1930: for (link=fine->refinehook; link; link=link->next) {
1931: if (link->interphook) {
1932: (*link->interphook)(coarse,interp,fine,link->ctx);
1933: }
1934: }
1935: return(0);
1936: }
1938: /*@
1939: DMGetRefineLevel - Get's the number of refinements that have generated this DM.
1941: Not Collective
1943: Input Parameter:
1944: . dm - the DM object
1946: Output Parameter:
1947: . level - number of refinements
1949: Level: developer
1951: .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
1953: @*/
1954: PetscErrorCode DMGetRefineLevel(DM dm,PetscInt *level)
1955: {
1958: *level = dm->levelup;
1959: return(0);
1960: }
1962: /*@
1963: DMSetRefineLevel - Set's the number of refinements that have generated this DM.
1965: Not Collective
1967: Input Parameter:
1968: + dm - the DM object
1969: - level - number of refinements
1971: Level: advanced
1973: Notes: This value is used by PCMG to determine how many multigrid levels to use
1975: .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
1977: @*/
1978: PetscErrorCode DMSetRefineLevel(DM dm,PetscInt level)
1979: {
1982: dm->levelup = level;
1983: return(0);
1984: }
1986: /*@C
1987: DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called
1989: Logically Collective
1991: Input Arguments:
1992: + dm - the DM
1993: . beginhook - function to run at the beginning of DMGlobalToLocalBegin()
1994: . endhook - function to run after DMGlobalToLocalEnd() has completed
1995: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
1997: Calling sequence for beginhook:
1998: $ beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)
2000: + dm - global DM
2001: . g - global vector
2002: . mode - mode
2003: . l - local vector
2004: - ctx - optional user-defined function context
2007: Calling sequence for endhook:
2008: $ endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)
2010: + global - global DM
2011: - ctx - optional user-defined function context
2013: Level: advanced
2015: .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2016: @*/
2017: PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx)
2018: {
2019: PetscErrorCode ierr;
2020: DMGlobalToLocalHookLink link,*p;
2024: for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2025: PetscNew(&link);
2026: link->beginhook = beginhook;
2027: link->endhook = endhook;
2028: link->ctx = ctx;
2029: link->next = NULL;
2030: *p = link;
2031: return(0);
2032: }
2034: static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx)
2035: {
2036: Mat cMat;
2037: Vec cVec;
2038: PetscSection section, cSec;
2039: PetscInt pStart, pEnd, p, dof;
2044: DMGetDefaultConstraints(dm,&cSec,&cMat);
2045: if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) {
2046: PetscInt nRows;
2048: MatGetSize(cMat,&nRows,NULL);
2049: if (nRows <= 0) return(0);
2050: DMGetDefaultSection(dm,§ion);
2051: MatCreateVecs(cMat,NULL,&cVec);
2052: MatMult(cMat,l,cVec);
2053: PetscSectionGetChart(cSec,&pStart,&pEnd);
2054: for (p = pStart; p < pEnd; p++) {
2055: PetscSectionGetDof(cSec,p,&dof);
2056: if (dof) {
2057: PetscScalar *vals;
2058: VecGetValuesSection(cVec,cSec,p,&vals);
2059: VecSetValuesSection(l,section,p,vals,INSERT_ALL_VALUES);
2060: }
2061: }
2062: VecDestroy(&cVec);
2063: }
2064: return(0);
2065: }
2067: /*@
2068: DMGlobalToLocalBegin - Begins updating local vectors from global vector
2070: Neighbor-wise Collective on DM
2072: Input Parameters:
2073: + dm - the DM object
2074: . g - the global vector
2075: . mode - INSERT_VALUES or ADD_VALUES
2076: - l - the local vector
2079: Level: beginner
2081: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2083: @*/
2084: PetscErrorCode DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
2085: {
2086: PetscSF sf;
2087: PetscErrorCode ierr;
2088: DMGlobalToLocalHookLink link;
2092: for (link=dm->gtolhook; link; link=link->next) {
2093: if (link->beginhook) {
2094: (*link->beginhook)(dm,g,mode,l,link->ctx);
2095: }
2096: }
2097: DMGetDefaultSF(dm, &sf);
2098: if (sf) {
2099: const PetscScalar *gArray;
2100: PetscScalar *lArray;
2102: if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2103: VecGetArray(l, &lArray);
2104: VecGetArrayRead(g, &gArray);
2105: PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);
2106: VecRestoreArray(l, &lArray);
2107: VecRestoreArrayRead(g, &gArray);
2108: } else {
2109: (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
2110: }
2111: return(0);
2112: }
2114: /*@
2115: DMGlobalToLocalEnd - Ends updating local vectors from global vector
2117: Neighbor-wise Collective on DM
2119: Input Parameters:
2120: + dm - the DM object
2121: . g - the global vector
2122: . mode - INSERT_VALUES or ADD_VALUES
2123: - l - the local vector
2126: Level: beginner
2128: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2130: @*/
2131: PetscErrorCode DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
2132: {
2133: PetscSF sf;
2134: PetscErrorCode ierr;
2135: const PetscScalar *gArray;
2136: PetscScalar *lArray;
2137: DMGlobalToLocalHookLink link;
2141: DMGetDefaultSF(dm, &sf);
2142: if (sf) {
2143: if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2145: VecGetArray(l, &lArray);
2146: VecGetArrayRead(g, &gArray);
2147: PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);
2148: VecRestoreArray(l, &lArray);
2149: VecRestoreArrayRead(g, &gArray);
2150: } else {
2151: (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
2152: }
2153: DMGlobalToLocalHook_Constraints(dm,g,mode,l,NULL);
2154: for (link=dm->gtolhook; link; link=link->next) {
2155: if (link->endhook) {(*link->endhook)(dm,g,mode,l,link->ctx);}
2156: }
2157: return(0);
2158: }
2160: /*@C
2161: DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called
2163: Logically Collective
2165: Input Arguments:
2166: + dm - the DM
2167: . beginhook - function to run at the beginning of DMLocalToGlobalBegin()
2168: . endhook - function to run after DMLocalToGlobalEnd() has completed
2169: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2171: Calling sequence for beginhook:
2172: $ beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)
2174: + dm - global DM
2175: . l - local vector
2176: . mode - mode
2177: . g - global vector
2178: - ctx - optional user-defined function context
2181: Calling sequence for endhook:
2182: $ endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)
2184: + global - global DM
2185: . l - local vector
2186: . mode - mode
2187: . g - global vector
2188: - ctx - optional user-defined function context
2190: Level: advanced
2192: .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2193: @*/
2194: PetscErrorCode DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx)
2195: {
2196: PetscErrorCode ierr;
2197: DMLocalToGlobalHookLink link,*p;
2201: for (p=&dm->ltoghook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2202: PetscNew(&link);
2203: link->beginhook = beginhook;
2204: link->endhook = endhook;
2205: link->ctx = ctx;
2206: link->next = NULL;
2207: *p = link;
2208: return(0);
2209: }
2211: static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx)
2212: {
2213: Mat cMat;
2214: Vec cVec;
2215: PetscSection section, cSec;
2216: PetscInt pStart, pEnd, p, dof;
2221: DMGetDefaultConstraints(dm,&cSec,&cMat);
2222: if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) {
2223: PetscInt nRows;
2225: MatGetSize(cMat,&nRows,NULL);
2226: if (nRows <= 0) return(0);
2227: DMGetDefaultSection(dm,§ion);
2228: MatCreateVecs(cMat,NULL,&cVec);
2229: PetscSectionGetChart(cSec,&pStart,&pEnd);
2230: for (p = pStart; p < pEnd; p++) {
2231: PetscSectionGetDof(cSec,p,&dof);
2232: if (dof) {
2233: PetscInt d;
2234: PetscScalar *vals;
2235: VecGetValuesSection(l,section,p,&vals);
2236: VecSetValuesSection(cVec,cSec,p,vals,mode);
2237: /* for this to be the true transpose, we have to zero the values that
2238: * we just extracted */
2239: for (d = 0; d < dof; d++) {
2240: vals[d] = 0.;
2241: }
2242: }
2243: }
2244: MatMultTransposeAdd(cMat,cVec,l,l);
2245: VecDestroy(&cVec);
2246: }
2247: return(0);
2248: }
2250: /*@
2251: DMLocalToGlobalBegin - updates global vectors from local vectors
2253: Neighbor-wise Collective on DM
2255: Input Parameters:
2256: + dm - the DM object
2257: . l - the local vector
2258: . mode - if INSERT_VALUES then no parallel communication is used, if ADD_VALUES then all ghost points from the same base point accumulate into that base point.
2259: - g - the global vector
2261: Notes: In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation.
2262: INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one.
2264: Level: beginner
2266: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin()
2268: @*/
2269: PetscErrorCode DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g)
2270: {
2271: PetscSF sf;
2272: PetscSection s, gs;
2273: DMLocalToGlobalHookLink link;
2274: const PetscScalar *lArray;
2275: PetscScalar *gArray;
2276: PetscBool isInsert;
2277: PetscErrorCode ierr;
2281: for (link=dm->ltoghook; link; link=link->next) {
2282: if (link->beginhook) {
2283: (*link->beginhook)(dm,l,mode,g,link->ctx);
2284: }
2285: }
2286: DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);
2287: DMGetDefaultSF(dm, &sf);
2288: DMGetDefaultSection(dm, &s);
2289: switch (mode) {
2290: case INSERT_VALUES:
2291: case INSERT_ALL_VALUES:
2292: case INSERT_BC_VALUES:
2293: isInsert = PETSC_TRUE; break;
2294: case ADD_VALUES:
2295: case ADD_ALL_VALUES:
2296: case ADD_BC_VALUES:
2297: isInsert = PETSC_FALSE; break;
2298: default:
2299: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2300: }
2301: if (sf && !isInsert) {
2302: VecGetArrayRead(l, &lArray);
2303: VecGetArray(g, &gArray);
2304: PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);
2305: VecRestoreArrayRead(l, &lArray);
2306: VecRestoreArray(g, &gArray);
2307: } else if (s && isInsert) {
2308: PetscInt gStart, pStart, pEnd, p;
2310: DMGetDefaultGlobalSection(dm, &gs);
2311: PetscSectionGetChart(s, &pStart, &pEnd);
2312: VecGetOwnershipRange(g, &gStart, NULL);
2313: VecGetArrayRead(l, &lArray);
2314: VecGetArray(g, &gArray);
2315: for (p = pStart; p < pEnd; ++p) {
2316: PetscInt dof, gdof, cdof, gcdof, off, goff, d, e;
2318: PetscSectionGetDof(s, p, &dof);
2319: PetscSectionGetDof(gs, p, &gdof);
2320: PetscSectionGetConstraintDof(s, p, &cdof);
2321: PetscSectionGetConstraintDof(gs, p, &gcdof);
2322: PetscSectionGetOffset(s, p, &off);
2323: PetscSectionGetOffset(gs, p, &goff);
2324: /* Ignore off-process data and points with no global data */
2325: if (!gdof || goff < 0) continue;
2326: if (dof != gdof) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof);
2327: /* If no constraints are enforced in the global vector */
2328: if (!gcdof) {
2329: for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d];
2330: /* If constraints are enforced in the global vector */
2331: } else if (cdof == gcdof) {
2332: const PetscInt *cdofs;
2333: PetscInt cind = 0;
2335: PetscSectionGetConstraintIndices(s, p, &cdofs);
2336: for (d = 0, e = 0; d < dof; ++d) {
2337: if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;}
2338: gArray[goff-gStart+e++] = lArray[off+d];
2339: }
2340: } else SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof);
2341: }
2342: VecRestoreArrayRead(l, &lArray);
2343: VecRestoreArray(g, &gArray);
2344: } else {
2345: (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);
2346: }
2347: return(0);
2348: }
2350: /*@
2351: DMLocalToGlobalEnd - updates global vectors from local vectors
2353: Neighbor-wise Collective on DM
2355: Input Parameters:
2356: + dm - the DM object
2357: . l - the local vector
2358: . mode - INSERT_VALUES or ADD_VALUES
2359: - g - the global vector
2362: Level: beginner
2364: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd()
2366: @*/
2367: PetscErrorCode DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g)
2368: {
2369: PetscSF sf;
2370: PetscSection s;
2371: DMLocalToGlobalHookLink link;
2372: PetscBool isInsert;
2373: PetscErrorCode ierr;
2377: DMGetDefaultSF(dm, &sf);
2378: DMGetDefaultSection(dm, &s);
2379: switch (mode) {
2380: case INSERT_VALUES:
2381: case INSERT_ALL_VALUES:
2382: isInsert = PETSC_TRUE; break;
2383: case ADD_VALUES:
2384: case ADD_ALL_VALUES:
2385: isInsert = PETSC_FALSE; break;
2386: default:
2387: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2388: }
2389: if (sf && !isInsert) {
2390: const PetscScalar *lArray;
2391: PetscScalar *gArray;
2393: VecGetArrayRead(l, &lArray);
2394: VecGetArray(g, &gArray);
2395: PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);
2396: VecRestoreArrayRead(l, &lArray);
2397: VecRestoreArray(g, &gArray);
2398: } else if (s && isInsert) {
2399: } else {
2400: (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);
2401: }
2402: for (link=dm->ltoghook; link; link=link->next) {
2403: if (link->endhook) {(*link->endhook)(dm,g,mode,l,link->ctx);}
2404: }
2405: return(0);
2406: }
2408: /*@
2409: DMLocalToLocalBegin - Maps from a local vector (including ghost points
2410: that contain irrelevant values) to another local vector where the ghost
2411: points in the second are set correctly. Must be followed by DMLocalToLocalEnd().
2413: Neighbor-wise Collective on DM and Vec
2415: Input Parameters:
2416: + dm - the DM object
2417: . g - the original local vector
2418: - mode - one of INSERT_VALUES or ADD_VALUES
2420: Output Parameter:
2421: . l - the local vector with correct ghost values
2423: Level: intermediate
2425: Notes:
2426: The local vectors used here need not be the same as those
2427: obtained from DMCreateLocalVector(), BUT they
2428: must have the same parallel data layout; they could, for example, be
2429: obtained with VecDuplicate() from the DM originating vectors.
2431: .keywords: DM, local-to-local, begin
2432: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2434: @*/
2435: PetscErrorCode DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
2436: {
2437: PetscErrorCode ierr;
2441: if (!dm->ops->localtolocalbegin) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps");
2442: (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
2443: return(0);
2444: }
2446: /*@
2447: DMLocalToLocalEnd - Maps from a local vector (including ghost points
2448: that contain irrelevant values) to another local vector where the ghost
2449: points in the second are set correctly. Must be preceded by DMLocalToLocalBegin().
2451: Neighbor-wise Collective on DM and Vec
2453: Input Parameters:
2454: + da - the DM object
2455: . g - the original local vector
2456: - mode - one of INSERT_VALUES or ADD_VALUES
2458: Output Parameter:
2459: . l - the local vector with correct ghost values
2461: Level: intermediate
2463: Notes:
2464: The local vectors used here need not be the same as those
2465: obtained from DMCreateLocalVector(), BUT they
2466: must have the same parallel data layout; they could, for example, be
2467: obtained with VecDuplicate() from the DM originating vectors.
2469: .keywords: DM, local-to-local, end
2470: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2472: @*/
2473: PetscErrorCode DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
2474: {
2475: PetscErrorCode ierr;
2479: if (!dm->ops->localtolocalend) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps");
2480: (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
2481: return(0);
2482: }
2485: /*@
2486: DMCoarsen - Coarsens a DM object
2488: Collective on DM
2490: Input Parameter:
2491: + dm - the DM object
2492: - comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
2494: Output Parameter:
2495: . dmc - the coarsened DM
2497: Level: developer
2499: .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2501: @*/
2502: PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
2503: {
2504: PetscErrorCode ierr;
2505: DMCoarsenHookLink link;
2509: if (!dm->ops->coarsen) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM cannot coarsen");
2510: PetscLogEventBegin(DM_Coarsen,dm,0,0,0);
2511: (*dm->ops->coarsen)(dm, comm, dmc);
2512: if (!(*dmc)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced");
2513: DMSetCoarseDM(dm,*dmc);
2514: (*dmc)->ops->creatematrix = dm->ops->creatematrix;
2515: PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);
2516: (*dmc)->ctx = dm->ctx;
2517: (*dmc)->levelup = dm->levelup;
2518: (*dmc)->leveldown = dm->leveldown + 1;
2519: DMSetMatType(*dmc,dm->mattype);
2520: for (link=dm->coarsenhook; link; link=link->next) {
2521: if (link->coarsenhook) {(*link->coarsenhook)(dm,*dmc,link->ctx);}
2522: }
2523: PetscLogEventEnd(DM_Coarsen,dm,0,0,0);
2524: return(0);
2525: }
2527: /*@C
2528: DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid
2530: Logically Collective
2532: Input Arguments:
2533: + fine - nonlinear solver context on which to run a hook when restricting to a coarser level
2534: . coarsenhook - function to run when setting up a coarser level
2535: . restricthook - function to run to update data on coarser levels (once per SNESSolve())
2536: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2538: Calling sequence of coarsenhook:
2539: $ coarsenhook(DM fine,DM coarse,void *ctx);
2541: + fine - fine level DM
2542: . coarse - coarse level DM to restrict problem to
2543: - ctx - optional user-defined function context
2545: Calling sequence for restricthook:
2546: $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx)
2548: + fine - fine level DM
2549: . mrestrict - matrix restricting a fine-level solution to the coarse grid
2550: . rscale - scaling vector for restriction
2551: . inject - matrix restricting by injection
2552: . coarse - coarse level DM to update
2553: - ctx - optional user-defined function context
2555: Level: advanced
2557: Notes:
2558: This function is only needed if auxiliary data needs to be set up on coarse grids.
2560: If this function is called multiple times, the hooks will be run in the order they are added.
2562: In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
2563: extract the finest level information from its context (instead of from the SNES).
2565: This function is currently not available from Fortran.
2567: .seealso: DMCoarsenHookRemove(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2568: @*/
2569: PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx)
2570: {
2571: PetscErrorCode ierr;
2572: DMCoarsenHookLink link,*p;
2576: for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */
2577: if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) return(0);
2578: }
2579: PetscNew(&link);
2580: link->coarsenhook = coarsenhook;
2581: link->restricthook = restricthook;
2582: link->ctx = ctx;
2583: link->next = NULL;
2584: *p = link;
2585: return(0);
2586: }
2588: /*@C
2589: DMCoarsenHookRemove - remove a callback from the list of hooks to be run when restricting a nonlinear problem to the coarse grid
2591: Logically Collective
2593: Input Arguments:
2594: + fine - nonlinear solver context on which to run a hook when restricting to a coarser level
2595: . coarsenhook - function to run when setting up a coarser level
2596: . restricthook - function to run to update data on coarser levels (once per SNESSolve())
2597: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2599: Level: advanced
2601: Notes:
2602: This function does nothing if the hook is not in the list.
2604: This function is currently not available from Fortran.
2606: .seealso: DMCoarsenHookAdd(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2607: @*/
2608: PetscErrorCode DMCoarsenHookRemove(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx)
2609: {
2610: PetscErrorCode ierr;
2611: DMCoarsenHookLink link,*p;
2615: for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Search the list of current hooks */
2616: if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
2617: link = *p;
2618: *p = link->next;
2619: PetscFree(link);
2620: break;
2621: }
2622: }
2623: return(0);
2624: }
2627: /*@
2628: DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd()
2630: Collective if any hooks are
2632: Input Arguments:
2633: + fine - finer DM to use as a base
2634: . restrct - restriction matrix, apply using MatRestrict()
2635: . rscale - scaling vector for restriction
2636: . inject - injection matrix, also use MatRestrict()
2637: - coarse - coarser DM to update
2639: Level: developer
2641: .seealso: DMCoarsenHookAdd(), MatRestrict()
2642: @*/
2643: PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse)
2644: {
2645: PetscErrorCode ierr;
2646: DMCoarsenHookLink link;
2649: for (link=fine->coarsenhook; link; link=link->next) {
2650: if (link->restricthook) {
2651: (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);
2652: }
2653: }
2654: return(0);
2655: }
2657: /*@C
2658: DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid
2660: Logically Collective
2662: Input Arguments:
2663: + global - global DM
2664: . ddhook - function to run to pass data to the decomposition DM upon its creation
2665: . restricthook - function to run to update data on block solve (at the beginning of the block solve)
2666: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2669: Calling sequence for ddhook:
2670: $ ddhook(DM global,DM block,void *ctx)
2672: + global - global DM
2673: . block - block DM
2674: - ctx - optional user-defined function context
2676: Calling sequence for restricthook:
2677: $ restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx)
2679: + global - global DM
2680: . out - scatter to the outer (with ghost and overlap points) block vector
2681: . in - scatter to block vector values only owned locally
2682: . block - block DM
2683: - ctx - optional user-defined function context
2685: Level: advanced
2687: Notes:
2688: This function is only needed if auxiliary data needs to be set up on subdomain DMs.
2690: If this function is called multiple times, the hooks will be run in the order they are added.
2692: In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
2693: extract the global information from its context (instead of from the SNES).
2695: This function is currently not available from Fortran.
2697: .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2698: @*/
2699: PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx)
2700: {
2701: PetscErrorCode ierr;
2702: DMSubDomainHookLink link,*p;
2706: for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */
2707: if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) return(0);
2708: }
2709: PetscNew(&link);
2710: link->restricthook = restricthook;
2711: link->ddhook = ddhook;
2712: link->ctx = ctx;
2713: link->next = NULL;
2714: *p = link;
2715: return(0);
2716: }
2718: /*@C
2719: DMSubDomainHookRemove - remove a callback from the list to be run when restricting a problem to the coarse grid
2721: Logically Collective
2723: Input Arguments:
2724: + global - global DM
2725: . ddhook - function to run to pass data to the decomposition DM upon its creation
2726: . restricthook - function to run to update data on block solve (at the beginning of the block solve)
2727: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2729: Level: advanced
2731: Notes:
2733: This function is currently not available from Fortran.
2735: .seealso: DMSubDomainHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2736: @*/
2737: PetscErrorCode DMSubDomainHookRemove(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx)
2738: {
2739: PetscErrorCode ierr;
2740: DMSubDomainHookLink link,*p;
2744: for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Search the list of current hooks */
2745: if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
2746: link = *p;
2747: *p = link->next;
2748: PetscFree(link);
2749: break;
2750: }
2751: }
2752: return(0);
2753: }
2755: /*@
2756: DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd()
2758: Collective if any hooks are
2760: Input Arguments:
2761: + fine - finer DM to use as a base
2762: . oscatter - scatter from domain global vector filling subdomain global vector with overlap
2763: . gscatter - scatter from domain global vector filling subdomain local vector with ghosts
2764: - coarse - coarer DM to update
2766: Level: developer
2768: .seealso: DMCoarsenHookAdd(), MatRestrict()
2769: @*/
2770: PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm)
2771: {
2772: PetscErrorCode ierr;
2773: DMSubDomainHookLink link;
2776: for (link=global->subdomainhook; link; link=link->next) {
2777: if (link->restricthook) {
2778: (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);
2779: }
2780: }
2781: return(0);
2782: }
2784: /*@
2785: DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM.
2787: Not Collective
2789: Input Parameter:
2790: . dm - the DM object
2792: Output Parameter:
2793: . level - number of coarsenings
2795: Level: developer
2797: .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2799: @*/
2800: PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level)
2801: {
2804: *level = dm->leveldown;
2805: return(0);
2806: }
2810: /*@C
2811: DMRefineHierarchy - Refines a DM object, all levels at once
2813: Collective on DM
2815: Input Parameter:
2816: + dm - the DM object
2817: - nlevels - the number of levels of refinement
2819: Output Parameter:
2820: . dmf - the refined DM hierarchy
2822: Level: developer
2824: .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2826: @*/
2827: PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[])
2828: {
2833: if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
2834: if (nlevels == 0) return(0);
2835: if (dm->ops->refinehierarchy) {
2836: (*dm->ops->refinehierarchy)(dm,nlevels,dmf);
2837: } else if (dm->ops->refine) {
2838: PetscInt i;
2840: DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);
2841: for (i=1; i<nlevels; i++) {
2842: DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);
2843: }
2844: } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet");
2845: return(0);
2846: }
2848: /*@C
2849: DMCoarsenHierarchy - Coarsens a DM object, all levels at once
2851: Collective on DM
2853: Input Parameter:
2854: + dm - the DM object
2855: - nlevels - the number of levels of coarsening
2857: Output Parameter:
2858: . dmc - the coarsened DM hierarchy
2860: Level: developer
2862: .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2864: @*/
2865: PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
2866: {
2871: if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
2872: if (nlevels == 0) return(0);
2874: if (dm->ops->coarsenhierarchy) {
2875: (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);
2876: } else if (dm->ops->coarsen) {
2877: PetscInt i;
2879: DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);
2880: for (i=1; i<nlevels; i++) {
2881: DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);
2882: }
2883: } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet");
2884: return(0);
2885: }
2887: /*@
2888: DMCreateAggregates - Gets the aggregates that map between
2889: grids associated with two DMs.
2891: Collective on DM
2893: Input Parameters:
2894: + dmc - the coarse grid DM
2895: - dmf - the fine grid DM
2897: Output Parameters:
2898: . rest - the restriction matrix (transpose of the projection matrix)
2900: Level: intermediate
2902: .keywords: interpolation, restriction, multigrid
2904: .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation()
2905: @*/
2906: PetscErrorCode DMCreateAggregates(DM dmc, DM dmf, Mat *rest)
2907: {
2913: (*dmc->ops->getaggregates)(dmc, dmf, rest);
2914: return(0);
2915: }
2917: /*@C
2918: DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed
2920: Not Collective
2922: Input Parameters:
2923: + dm - the DM object
2924: - destroy - the destroy function
2926: Level: intermediate
2928: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2930: @*/
2931: PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**))
2932: {
2935: dm->ctxdestroy = destroy;
2936: return(0);
2937: }
2939: /*@
2940: DMSetApplicationContext - Set a user context into a DM object
2942: Not Collective
2944: Input Parameters:
2945: + dm - the DM object
2946: - ctx - the user context
2948: Level: intermediate
2950: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2952: @*/
2953: PetscErrorCode DMSetApplicationContext(DM dm,void *ctx)
2954: {
2957: dm->ctx = ctx;
2958: return(0);
2959: }
2961: /*@
2962: DMGetApplicationContext - Gets a user context from a DM object
2964: Not Collective
2966: Input Parameter:
2967: . dm - the DM object
2969: Output Parameter:
2970: . ctx - the user context
2972: Level: intermediate
2974: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2976: @*/
2977: PetscErrorCode DMGetApplicationContext(DM dm,void *ctx)
2978: {
2981: *(void**)ctx = dm->ctx;
2982: return(0);
2983: }
2985: /*@C
2986: DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI.
2988: Logically Collective on DM
2990: Input Parameter:
2991: + dm - the DM object
2992: - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set)
2994: Level: intermediate
2996: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(),
2997: DMSetJacobian()
2999: @*/
3000: PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec))
3001: {
3003: dm->ops->computevariablebounds = f;
3004: return(0);
3005: }
3007: /*@
3008: DMHasVariableBounds - does the DM object have a variable bounds function?
3010: Not Collective
3012: Input Parameter:
3013: . dm - the DM object to destroy
3015: Output Parameter:
3016: . flg - PETSC_TRUE if the variable bounds function exists
3018: Level: developer
3020: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
3022: @*/
3023: PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg)
3024: {
3026: *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE;
3027: return(0);
3028: }
3030: /*@C
3031: DMComputeVariableBounds - compute variable bounds used by SNESVI.
3033: Logically Collective on DM
3035: Input Parameters:
3036: . dm - the DM object
3038: Output parameters:
3039: + xl - lower bound
3040: - xu - upper bound
3042: Level: advanced
3044: Notes: This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds()
3046: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
3048: @*/
3049: PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu)
3050: {
3056: if (dm->ops->computevariablebounds) {
3057: (*dm->ops->computevariablebounds)(dm, xl,xu);
3058: } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds.");
3059: return(0);
3060: }
3062: /*@
3063: DMHasColoring - does the DM object have a method of providing a coloring?
3065: Not Collective
3067: Input Parameter:
3068: . dm - the DM object
3070: Output Parameter:
3071: . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring().
3073: Level: developer
3075: .seealso DMHasFunction(), DMCreateColoring()
3077: @*/
3078: PetscErrorCode DMHasColoring(DM dm,PetscBool *flg)
3079: {
3081: *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE;
3082: return(0);
3083: }
3085: /*@
3086: DMHasCreateRestriction - does the DM object have a method of providing a restriction?
3088: Not Collective
3090: Input Parameter:
3091: . dm - the DM object
3093: Output Parameter:
3094: . flg - PETSC_TRUE if the DM has facilities for DMCreateRestriction().
3096: Level: developer
3098: .seealso DMHasFunction(), DMCreateRestriction()
3100: @*/
3101: PetscErrorCode DMHasCreateRestriction(DM dm,PetscBool *flg)
3102: {
3104: *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE;
3105: return(0);
3106: }
3109: /*@
3110: DMHasCreateInjection - does the DM object have a method of providing an injection?
3112: Not Collective
3114: Input Parameter:
3115: . dm - the DM object
3117: Output Parameter:
3118: . flg - PETSC_TRUE if the DM has facilities for DMCreateInjection().
3120: Level: developer
3122: .seealso DMHasFunction(), DMCreateInjection()
3124: @*/
3125: PetscErrorCode DMHasCreateInjection(DM dm,PetscBool *flg)
3126: {
3129: if (!dm->ops->hascreateinjection) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DMHasCreateInjection not implemented for this type");
3130: (*dm->ops->hascreateinjection)(dm,flg);
3131: return(0);
3132: }
3134: /*@C
3135: DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear.
3137: Collective on DM
3139: Input Parameter:
3140: + dm - the DM object
3141: - x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems.
3143: Level: developer
3145: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
3147: @*/
3148: PetscErrorCode DMSetVec(DM dm,Vec x)
3149: {
3153: if (x) {
3154: if (!dm->x) {
3155: DMCreateGlobalVector(dm,&dm->x);
3156: }
3157: VecCopy(x,dm->x);
3158: } else if (dm->x) {
3159: VecDestroy(&dm->x);
3160: }
3161: return(0);
3162: }
3164: PetscFunctionList DMList = NULL;
3165: PetscBool DMRegisterAllCalled = PETSC_FALSE;
3167: /*@C
3168: DMSetType - Builds a DM, for a particular DM implementation.
3170: Collective on DM
3172: Input Parameters:
3173: + dm - The DM object
3174: - method - The name of the DM type
3176: Options Database Key:
3177: . -dm_type <type> - Sets the DM type; use -help for a list of available types
3179: Notes:
3180: See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D).
3182: Level: intermediate
3184: .keywords: DM, set, type
3185: .seealso: DMGetType(), DMCreate()
3186: @*/
3187: PetscErrorCode DMSetType(DM dm, DMType method)
3188: {
3189: PetscErrorCode (*r)(DM);
3190: PetscBool match;
3195: PetscObjectTypeCompare((PetscObject) dm, method, &match);
3196: if (match) return(0);
3198: DMRegisterAll();
3199: PetscFunctionListFind(DMList,method,&r);
3200: if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);
3202: if (dm->ops->destroy) {
3203: (*dm->ops->destroy)(dm);
3204: dm->ops->destroy = NULL;
3205: }
3206: (*r)(dm);
3207: PetscObjectChangeTypeName((PetscObject)dm,method);
3208: return(0);
3209: }
3211: /*@C
3212: DMGetType - Gets the DM type name (as a string) from the DM.
3214: Not Collective
3216: Input Parameter:
3217: . dm - The DM
3219: Output Parameter:
3220: . type - The DM type name
3222: Level: intermediate
3224: .keywords: DM, get, type, name
3225: .seealso: DMSetType(), DMCreate()
3226: @*/
3227: PetscErrorCode DMGetType(DM dm, DMType *type)
3228: {
3234: DMRegisterAll();
3235: *type = ((PetscObject)dm)->type_name;
3236: return(0);
3237: }
3239: /*@C
3240: DMConvert - Converts a DM to another DM, either of the same or different type.
3242: Collective on DM
3244: Input Parameters:
3245: + dm - the DM
3246: - newtype - new DM type (use "same" for the same type)
3248: Output Parameter:
3249: . M - pointer to new DM
3251: Notes:
3252: Cannot be used to convert a sequential DM to parallel or parallel to sequential,
3253: the MPI communicator of the generated DM is always the same as the communicator
3254: of the input DM.
3256: Level: intermediate
3258: .seealso: DMCreate()
3259: @*/
3260: PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M)
3261: {
3262: DM B;
3263: char convname[256];
3264: PetscBool sametype/*, issame */;
3271: PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);
3272: /* PetscStrcmp(newtype, "same", &issame); */
3273: if (sametype) {
3274: *M = dm;
3275: PetscObjectReference((PetscObject) dm);
3276: return(0);
3277: } else {
3278: PetscErrorCode (*conv)(DM, DMType, DM*) = NULL;
3280: /*
3281: Order of precedence:
3282: 1) See if a specialized converter is known to the current DM.
3283: 2) See if a specialized converter is known to the desired DM class.
3284: 3) See if a good general converter is registered for the desired class
3285: 4) See if a good general converter is known for the current matrix.
3286: 5) Use a really basic converter.
3287: */
3289: /* 1) See if a specialized converter is known to the current DM and the desired class */
3290: PetscStrncpy(convname,"DMConvert_",sizeof(convname));
3291: PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));
3292: PetscStrlcat(convname,"_",sizeof(convname));
3293: PetscStrlcat(convname,newtype,sizeof(convname));
3294: PetscStrlcat(convname,"_C",sizeof(convname));
3295: PetscObjectQueryFunction((PetscObject)dm,convname,&conv);
3296: if (conv) goto foundconv;
3298: /* 2) See if a specialized converter is known to the desired DM class. */
3299: DMCreate(PetscObjectComm((PetscObject)dm), &B);
3300: DMSetType(B, newtype);
3301: PetscStrncpy(convname,"DMConvert_",sizeof(convname));
3302: PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));
3303: PetscStrlcat(convname,"_",sizeof(convname));
3304: PetscStrlcat(convname,newtype,sizeof(convname));
3305: PetscStrlcat(convname,"_C",sizeof(convname));
3306: PetscObjectQueryFunction((PetscObject)B,convname,&conv);
3307: if (conv) {
3308: DMDestroy(&B);
3309: goto foundconv;
3310: }
3312: #if 0
3313: /* 3) See if a good general converter is registered for the desired class */
3314: conv = B->ops->convertfrom;
3315: DMDestroy(&B);
3316: if (conv) goto foundconv;
3318: /* 4) See if a good general converter is known for the current matrix */
3319: if (dm->ops->convert) {
3320: conv = dm->ops->convert;
3321: }
3322: if (conv) goto foundconv;
3323: #endif
3325: /* 5) Use a really basic converter. */
3326: SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype);
3328: foundconv:
3329: PetscLogEventBegin(DM_Convert,dm,0,0,0);
3330: (*conv)(dm,newtype,M);
3331: /* Things that are independent of DM type: We should consult DMClone() here */
3332: {
3333: PetscBool isper;
3334: const PetscReal *maxCell, *L;
3335: const DMBoundaryType *bd;
3336: DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);
3337: DMSetPeriodicity(*M, isper, maxCell, L, bd);
3338: }
3339: PetscLogEventEnd(DM_Convert,dm,0,0,0);
3340: }
3341: PetscObjectStateIncrease((PetscObject) *M);
3342: return(0);
3343: }
3345: /*--------------------------------------------------------------------------------------------------------------------*/
3347: /*@C
3348: DMRegister - Adds a new DM component implementation
3350: Not Collective
3352: Input Parameters:
3353: + name - The name of a new user-defined creation routine
3354: - create_func - The creation routine itself
3356: Notes:
3357: DMRegister() may be called multiple times to add several user-defined DMs
3360: Sample usage:
3361: .vb
3362: DMRegister("my_da", MyDMCreate);
3363: .ve
3365: Then, your DM type can be chosen with the procedural interface via
3366: .vb
3367: DMCreate(MPI_Comm, DM *);
3368: DMSetType(DM,"my_da");
3369: .ve
3370: or at runtime via the option
3371: .vb
3372: -da_type my_da
3373: .ve
3375: Level: advanced
3377: .keywords: DM, register
3378: .seealso: DMRegisterAll(), DMRegisterDestroy()
3380: @*/
3381: PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM))
3382: {
3386: PetscFunctionListAdd(&DMList,sname,function);
3387: return(0);
3388: }
3390: /*@C
3391: DMLoad - Loads a DM that has been stored in binary with DMView().
3393: Collective on PetscViewer
3395: Input Parameters:
3396: + newdm - the newly loaded DM, this needs to have been created with DMCreate() or
3397: some related function before a call to DMLoad().
3398: - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or
3399: HDF5 file viewer, obtained from PetscViewerHDF5Open()
3401: Level: intermediate
3403: Notes:
3404: The type is determined by the data in the file, any type set into the DM before this call is ignored.
3406: Notes for advanced users:
3407: Most users should not need to know the details of the binary storage
3408: format, since DMLoad() and DMView() completely hide these details.
3409: But for anyone who's interested, the standard binary matrix storage
3410: format is
3411: .vb
3412: has not yet been determined
3413: .ve
3415: .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad()
3416: @*/
3417: PetscErrorCode DMLoad(DM newdm, PetscViewer viewer)
3418: {
3419: PetscBool isbinary, ishdf5;
3425: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
3426: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);
3427: if (isbinary) {
3428: PetscInt classid;
3429: char type[256];
3431: PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);
3432: if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid);
3433: PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);
3434: DMSetType(newdm, type);
3435: if (newdm->ops->load) {(*newdm->ops->load)(newdm,viewer);}
3436: } else if (ishdf5) {
3437: if (newdm->ops->load) {(*newdm->ops->load)(newdm,viewer);}
3438: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()");
3439: return(0);
3440: }
3442: /******************************** FEM Support **********************************/
3444: PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[])
3445: {
3446: PetscInt f;
3450: PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);
3451: for (f = 0; f < len; ++f) {
3452: PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));
3453: }
3454: return(0);
3455: }
3457: PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[])
3458: {
3459: PetscInt f, g;
3463: PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);
3464: for (f = 0; f < rows; ++f) {
3465: PetscPrintf(PETSC_COMM_SELF, " |");
3466: for (g = 0; g < cols; ++g) {
3467: PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));
3468: }
3469: PetscPrintf(PETSC_COMM_SELF, " |\n");
3470: }
3471: return(0);
3472: }
3474: PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X)
3475: {
3476: PetscInt localSize, bs;
3477: PetscMPIInt size;
3478: Vec x, xglob;
3479: const PetscScalar *xarray;
3480: PetscErrorCode ierr;
3483: MPI_Comm_size(PetscObjectComm((PetscObject) dm),&size);
3484: VecDuplicate(X, &x);
3485: VecCopy(X, x);
3486: VecChop(x, tol);
3487: PetscPrintf(PetscObjectComm((PetscObject) dm),"%s:\n",name);
3488: if (size > 1) {
3489: VecGetLocalSize(x,&localSize);
3490: VecGetArrayRead(x,&xarray);
3491: VecGetBlockSize(x,&bs);
3492: VecCreateMPIWithArray(PetscObjectComm((PetscObject) dm),bs,localSize,PETSC_DETERMINE,xarray,&xglob);
3493: } else {
3494: xglob = x;
3495: }
3496: VecView(xglob,PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject) dm)));
3497: if (size > 1) {
3498: VecDestroy(&xglob);
3499: VecRestoreArrayRead(x,&xarray);
3500: }
3501: VecDestroy(&x);
3502: return(0);
3503: }
3505: /*@
3506: DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM.
3508: Input Parameter:
3509: . dm - The DM
3511: Output Parameter:
3512: . section - The PetscSection
3514: Level: intermediate
3516: Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
3518: .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
3519: @*/
3520: PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section)
3521: {
3527: if (!dm->defaultSection && dm->ops->createdefaultsection) {
3528: (*dm->ops->createdefaultsection)(dm);
3529: if (dm->defaultSection) {PetscObjectViewFromOptions((PetscObject) dm->defaultSection, NULL, "-dm_petscsection_view");}
3530: }
3531: *section = dm->defaultSection;
3532: return(0);
3533: }
3535: /*@
3536: DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM.
3538: Input Parameters:
3539: + dm - The DM
3540: - section - The PetscSection
3542: Level: intermediate
3544: Note: Any existing Section will be destroyed
3546: .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
3547: @*/
3548: PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section)
3549: {
3550: PetscInt numFields = 0;
3551: PetscInt f;
3556: if (section) {
3558: PetscObjectReference((PetscObject)section);
3559: }
3560: PetscSectionDestroy(&dm->defaultSection);
3561: dm->defaultSection = section;
3562: if (section) {PetscSectionGetNumFields(dm->defaultSection, &numFields);}
3563: if (numFields) {
3564: DMSetNumFields(dm, numFields);
3565: for (f = 0; f < numFields; ++f) {
3566: PetscObject disc;
3567: const char *name;
3569: PetscSectionGetFieldName(dm->defaultSection, f, &name);
3570: DMGetField(dm, f, &disc);
3571: PetscObjectSetName(disc, name);
3572: }
3573: }
3574: /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */
3575: PetscSectionDestroy(&dm->defaultGlobalSection);
3576: return(0);
3577: }
3579: /*@
3580: DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation.
3582: not collective
3584: Input Parameter:
3585: . dm - The DM
3587: Output Parameter:
3588: + section - The PetscSection describing the range of the constraint matrix: relates rows of the constraint matrix to dofs of the default section. Returns NULL if there are no local constraints.
3589: - mat - The Mat that interpolates local constraints: its width should be the layout size of the default section. Returns NULL if there are no local constraints.
3591: Level: advanced
3593: Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat.
3595: .seealso: DMSetDefaultConstraints()
3596: @*/
3597: PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat)
3598: {
3603: if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {(*dm->ops->createdefaultconstraints)(dm);}
3604: if (section) {*section = dm->defaultConstraintSection;}
3605: if (mat) {*mat = dm->defaultConstraintMat;}
3606: return(0);
3607: }
3609: /*@
3610: DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation.
3612: If a constraint matrix is specified, then it is applied during DMGlobalToLocalEnd() when mode is INSERT_VALUES, INSERT_BC_VALUES, or INSERT_ALL_VALUES. Without a constraint matrix, the local vector l returned by DMGlobalToLocalEnd() contains values that have been scattered from a global vector without modification; with a constraint matrix A, l is modified by computing c = A * l, l[s[i]] = c[i], where the scatter s is defined by the PetscSection returned by DMGetDefaultConstraintMatrix().
3614: If a constraint matrix is specified, then its adjoint is applied during DMLocalToGlobalBegin() when mode is ADD_VALUES, ADD_BC_VALUES, or ADD_ALL_VALUES. Without a constraint matrix, the local vector l is accumulated into a global vector without modification; with a constraint matrix A, l is first modified by computing c[i] = l[s[i]], l[s[i]] = 0, l = l + A'*c, which is the adjoint of the operation described above.
3616: collective on dm
3618: Input Parameters:
3619: + dm - The DM
3620: + section - The PetscSection describing the range of the constraint matrix: relates rows of the constraint matrix to dofs of the default section. Must have a local communicator (PETSC_COMM_SELF or derivative).
3621: - mat - The Mat that interpolates local constraints: its width should be the layout size of the default section: NULL indicates no constraints. Must have a local communicator (PETSC_COMM_SELF or derivative).
3623: Level: advanced
3625: Note: This increments the references of the PetscSection and the Mat, so they user can destroy them
3627: .seealso: DMGetDefaultConstraints()
3628: @*/
3629: PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat)
3630: {
3631: PetscMPIInt result;
3636: if (section) {
3638: MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);
3639: if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator");
3640: }
3641: if (mat) {
3643: MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);
3644: if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator");
3645: }
3646: PetscObjectReference((PetscObject)section);
3647: PetscSectionDestroy(&dm->defaultConstraintSection);
3648: dm->defaultConstraintSection = section;
3649: PetscObjectReference((PetscObject)mat);
3650: MatDestroy(&dm->defaultConstraintMat);
3651: dm->defaultConstraintMat = mat;
3652: return(0);
3653: }
3655: #ifdef PETSC_USE_DEBUG
3656: /*
3657: DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections.
3659: Input Parameters:
3660: + dm - The DM
3661: . localSection - PetscSection describing the local data layout
3662: - globalSection - PetscSection describing the global data layout
3664: Level: intermediate
3666: .seealso: DMGetDefaultSF(), DMSetDefaultSF()
3667: */
3668: static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection)
3669: {
3670: MPI_Comm comm;
3671: PetscLayout layout;
3672: const PetscInt *ranges;
3673: PetscInt pStart, pEnd, p, nroots;
3674: PetscMPIInt size, rank;
3675: PetscBool valid = PETSC_TRUE, gvalid;
3676: PetscErrorCode ierr;
3679: PetscObjectGetComm((PetscObject)dm,&comm);
3681: MPI_Comm_size(comm, &size);
3682: MPI_Comm_rank(comm, &rank);
3683: PetscSectionGetChart(globalSection, &pStart, &pEnd);
3684: PetscSectionGetConstrainedStorageSize(globalSection, &nroots);
3685: PetscLayoutCreate(comm, &layout);
3686: PetscLayoutSetBlockSize(layout, 1);
3687: PetscLayoutSetLocalSize(layout, nroots);
3688: PetscLayoutSetUp(layout);
3689: PetscLayoutGetRanges(layout, &ranges);
3690: for (p = pStart; p < pEnd; ++p) {
3691: PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d;
3693: PetscSectionGetDof(localSection, p, &dof);
3694: PetscSectionGetOffset(localSection, p, &off);
3695: PetscSectionGetConstraintDof(localSection, p, &cdof);
3696: PetscSectionGetDof(globalSection, p, &gdof);
3697: PetscSectionGetConstraintDof(globalSection, p, &gcdof);
3698: PetscSectionGetOffset(globalSection, p, &goff);
3699: if (!gdof) continue; /* Censored point */
3700: if ((gdof < 0 ? -(gdof+1) : gdof) != dof) {PetscSynchronizedPrintf(comm, "[%d]Global dof %d for point %d not equal to local dof %d\n", rank, gdof, p, dof); valid = PETSC_FALSE;}
3701: if (gcdof && (gcdof != cdof)) {PetscSynchronizedPrintf(comm, "[%d]Global constraints %d for point %d not equal to local constraints %d\n", rank, gcdof, p, cdof); valid = PETSC_FALSE;}
3702: if (gdof < 0) {
3703: gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3704: for (d = 0; d < gsize; ++d) {
3705: PetscInt offset = -(goff+1) + d, r;
3707: PetscFindInt(offset,size+1,ranges,&r);
3708: if (r < 0) r = -(r+2);
3709: if ((r < 0) || (r >= size)) {PetscSynchronizedPrintf(comm, "[%d]Point %d mapped to invalid process %d (%d, %d)\n", rank, p, r, gdof, goff); valid = PETSC_FALSE;break;}
3710: }
3711: }
3712: }
3713: PetscLayoutDestroy(&layout);
3714: PetscSynchronizedFlush(comm, NULL);
3715: MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);
3716: if (!gvalid) {
3717: DMView(dm, NULL);
3718: SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections");
3719: }
3720: return(0);
3721: }
3722: #endif
3724: /*@
3725: DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM.
3727: Collective on DM
3729: Input Parameter:
3730: . dm - The DM
3732: Output Parameter:
3733: . section - The PetscSection
3735: Level: intermediate
3737: Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
3739: .seealso: DMSetDefaultSection(), DMGetDefaultSection()
3740: @*/
3741: PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section)
3742: {
3748: if (!dm->defaultGlobalSection) {
3749: PetscSection s;
3751: DMGetDefaultSection(dm, &s);
3752: if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection");
3753: if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection");
3754: PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->defaultGlobalSection);
3755: PetscLayoutDestroy(&dm->map);
3756: PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);
3757: PetscSectionViewFromOptions(dm->defaultGlobalSection, NULL, "-global_section_view");
3758: }
3759: *section = dm->defaultGlobalSection;
3760: return(0);
3761: }
3763: /*@
3764: DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM.
3766: Input Parameters:
3767: + dm - The DM
3768: - section - The PetscSection, or NULL
3770: Level: intermediate
3772: Note: Any existing Section will be destroyed
3774: .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection()
3775: @*/
3776: PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section)
3777: {
3783: PetscObjectReference((PetscObject)section);
3784: PetscSectionDestroy(&dm->defaultGlobalSection);
3785: dm->defaultGlobalSection = section;
3786: #ifdef PETSC_USE_DEBUG
3787: if (section) {DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);}
3788: #endif
3789: return(0);
3790: }
3792: /*@
3793: DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set,
3794: it is created from the default PetscSection layouts in the DM.
3796: Input Parameter:
3797: . dm - The DM
3799: Output Parameter:
3800: . sf - The PetscSF
3802: Level: intermediate
3804: Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
3806: .seealso: DMSetDefaultSF(), DMCreateDefaultSF()
3807: @*/
3808: PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf)
3809: {
3810: PetscInt nroots;
3816: PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);
3817: if (nroots < 0) {
3818: PetscSection section, gSection;
3820: DMGetDefaultSection(dm, §ion);
3821: if (section) {
3822: DMGetDefaultGlobalSection(dm, &gSection);
3823: DMCreateDefaultSF(dm, section, gSection);
3824: } else {
3825: *sf = NULL;
3826: return(0);
3827: }
3828: }
3829: *sf = dm->defaultSF;
3830: return(0);
3831: }
3833: /*@
3834: DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM
3836: Input Parameters:
3837: + dm - The DM
3838: - sf - The PetscSF
3840: Level: intermediate
3842: Note: Any previous SF is destroyed
3844: .seealso: DMGetDefaultSF(), DMCreateDefaultSF()
3845: @*/
3846: PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf)
3847: {
3853: PetscSFDestroy(&dm->defaultSF);
3854: dm->defaultSF = sf;
3855: return(0);
3856: }
3858: /*@C
3859: DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections
3860: describing the data layout.
3862: Input Parameters:
3863: + dm - The DM
3864: . localSection - PetscSection describing the local data layout
3865: - globalSection - PetscSection describing the global data layout
3867: Level: intermediate
3869: .seealso: DMGetDefaultSF(), DMSetDefaultSF()
3870: @*/
3871: PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection)
3872: {
3873: MPI_Comm comm;
3874: PetscLayout layout;
3875: const PetscInt *ranges;
3876: PetscInt *local;
3877: PetscSFNode *remote;
3878: PetscInt pStart, pEnd, p, nroots, nleaves = 0, l;
3879: PetscMPIInt size, rank;
3883: PetscObjectGetComm((PetscObject)dm,&comm);
3885: MPI_Comm_size(comm, &size);
3886: MPI_Comm_rank(comm, &rank);
3887: PetscSectionGetChart(globalSection, &pStart, &pEnd);
3888: PetscSectionGetConstrainedStorageSize(globalSection, &nroots);
3889: PetscLayoutCreate(comm, &layout);
3890: PetscLayoutSetBlockSize(layout, 1);
3891: PetscLayoutSetLocalSize(layout, nroots);
3892: PetscLayoutSetUp(layout);
3893: PetscLayoutGetRanges(layout, &ranges);
3894: for (p = pStart; p < pEnd; ++p) {
3895: PetscInt gdof, gcdof;
3897: PetscSectionGetDof(globalSection, p, &gdof);
3898: PetscSectionGetConstraintDof(globalSection, p, &gcdof);
3899: if (gcdof > (gdof < 0 ? -(gdof+1) : gdof)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d has %d constraints > %d dof", p, gcdof, (gdof < 0 ? -(gdof+1) : gdof));
3900: nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3901: }
3902: PetscMalloc1(nleaves, &local);
3903: PetscMalloc1(nleaves, &remote);
3904: for (p = pStart, l = 0; p < pEnd; ++p) {
3905: const PetscInt *cind;
3906: PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c;
3908: PetscSectionGetDof(localSection, p, &dof);
3909: PetscSectionGetOffset(localSection, p, &off);
3910: PetscSectionGetConstraintDof(localSection, p, &cdof);
3911: PetscSectionGetConstraintIndices(localSection, p, &cind);
3912: PetscSectionGetDof(globalSection, p, &gdof);
3913: PetscSectionGetConstraintDof(globalSection, p, &gcdof);
3914: PetscSectionGetOffset(globalSection, p, &goff);
3915: if (!gdof) continue; /* Censored point */
3916: gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3917: if (gsize != dof-cdof) {
3918: if (gsize != dof) SETERRQ4(comm, PETSC_ERR_ARG_WRONG, "Global dof %d for point %d is neither the constrained size %d, nor the unconstrained %d", gsize, p, dof-cdof, dof);
3919: cdof = 0; /* Ignore constraints */
3920: }
3921: for (d = 0, c = 0; d < dof; ++d) {
3922: if ((c < cdof) && (cind[c] == d)) {++c; continue;}
3923: local[l+d-c] = off+d;
3924: }
3925: if (gdof < 0) {
3926: for (d = 0; d < gsize; ++d, ++l) {
3927: PetscInt offset = -(goff+1) + d, r;
3929: PetscFindInt(offset,size+1,ranges,&r);
3930: if (r < 0) r = -(r+2);
3931: if ((r < 0) || (r >= size)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d mapped to invalid process %d (%d, %d)", p, r, gdof, goff);
3932: remote[l].rank = r;
3933: remote[l].index = offset - ranges[r];
3934: }
3935: } else {
3936: for (d = 0; d < gsize; ++d, ++l) {
3937: remote[l].rank = rank;
3938: remote[l].index = goff+d - ranges[rank];
3939: }
3940: }
3941: }
3942: if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves);
3943: PetscLayoutDestroy(&layout);
3944: PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);
3945: return(0);
3946: }
3948: /*@
3949: DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM.
3951: Input Parameter:
3952: . dm - The DM
3954: Output Parameter:
3955: . sf - The PetscSF
3957: Level: intermediate
3959: Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
3961: .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
3962: @*/
3963: PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf)
3964: {
3968: *sf = dm->sf;
3969: return(0);
3970: }
3972: /*@
3973: DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM.
3975: Input Parameters:
3976: + dm - The DM
3977: - sf - The PetscSF
3979: Level: intermediate
3981: .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
3982: @*/
3983: PetscErrorCode DMSetPointSF(DM dm, PetscSF sf)
3984: {
3990: PetscSFDestroy(&dm->sf);
3991: PetscObjectReference((PetscObject) sf);
3992: dm->sf = sf;
3993: return(0);
3994: }
3996: /*@
3997: DMGetDS - Get the PetscDS
3999: Input Parameter:
4000: . dm - The DM
4002: Output Parameter:
4003: . prob - The PetscDS
4005: Level: developer
4007: .seealso: DMSetDS()
4008: @*/
4009: PetscErrorCode DMGetDS(DM dm, PetscDS *prob)
4010: {
4014: *prob = dm->prob;
4015: return(0);
4016: }
4018: /*@
4019: DMSetDS - Set the PetscDS
4021: Input Parameters:
4022: + dm - The DM
4023: - prob - The PetscDS
4025: Level: developer
4027: .seealso: DMGetDS()
4028: @*/
4029: PetscErrorCode DMSetDS(DM dm, PetscDS prob)
4030: {
4031: PetscInt dimEmbed;
4037: PetscObjectReference((PetscObject) prob);
4038: PetscDSDestroy(&dm->prob);
4039: dm->prob = prob;
4040: DMGetCoordinateDim(dm, &dimEmbed);
4041: PetscDSSetCoordinateDimension(prob, dimEmbed);
4042: return(0);
4043: }
4045: PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields)
4046: {
4051: PetscDSGetNumFields(dm->prob, numFields);
4052: return(0);
4053: }
4055: PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields)
4056: {
4057: PetscInt Nf, f;
4062: PetscDSGetNumFields(dm->prob, &Nf);
4063: for (f = Nf; f < numFields; ++f) {
4064: PetscContainer obj;
4066: PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);
4067: PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);
4068: PetscContainerDestroy(&obj);
4069: }
4070: return(0);
4071: }
4073: /*@
4074: DMGetField - Return the discretization object for a given DM field
4076: Not collective
4078: Input Parameters:
4079: + dm - The DM
4080: - f - The field number
4082: Output Parameter:
4083: . field - The discretization object
4085: Level: developer
4087: .seealso: DMSetField()
4088: @*/
4089: PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field)
4090: {
4095: PetscDSGetDiscretization(dm->prob, f, field);
4096: return(0);
4097: }
4099: /*@
4100: DMSetField - Set the discretization object for a given DM field
4102: Logically collective on DM
4104: Input Parameters:
4105: + dm - The DM
4106: . f - The field number
4107: - field - The discretization object
4109: Level: developer
4111: .seealso: DMGetField()
4112: @*/
4113: PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field)
4114: {
4119: PetscDSSetDiscretization(dm->prob, f, field);
4120: return(0);
4121: }
4123: PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx)
4124: {
4125: DM dm_coord,dmc_coord;
4127: Vec coords,ccoords;
4128: Mat inject;
4130: DMGetCoordinateDM(dm,&dm_coord);
4131: DMGetCoordinateDM(dmc,&dmc_coord);
4132: DMGetCoordinates(dm,&coords);
4133: DMGetCoordinates(dmc,&ccoords);
4134: if (coords && !ccoords) {
4135: DMCreateGlobalVector(dmc_coord,&ccoords);
4136: PetscObjectSetName((PetscObject)ccoords,"coordinates");
4137: DMCreateInjection(dmc_coord,dm_coord,&inject);
4138: MatRestrict(inject,coords,ccoords);
4139: MatDestroy(&inject);
4140: DMSetCoordinates(dmc,ccoords);
4141: VecDestroy(&ccoords);
4142: }
4143: return(0);
4144: }
4146: static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx)
4147: {
4148: DM dm_coord,subdm_coord;
4150: Vec coords,ccoords,clcoords;
4151: VecScatter *scat_i,*scat_g;
4153: DMGetCoordinateDM(dm,&dm_coord);
4154: DMGetCoordinateDM(subdm,&subdm_coord);
4155: DMGetCoordinates(dm,&coords);
4156: DMGetCoordinates(subdm,&ccoords);
4157: if (coords && !ccoords) {
4158: DMCreateGlobalVector(subdm_coord,&ccoords);
4159: PetscObjectSetName((PetscObject)ccoords,"coordinates");
4160: DMCreateLocalVector(subdm_coord,&clcoords);
4161: PetscObjectSetName((PetscObject)clcoords,"coordinates");
4162: DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);
4163: VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);
4164: VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);
4165: VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);
4166: VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);
4167: DMSetCoordinates(subdm,ccoords);
4168: DMSetCoordinatesLocal(subdm,clcoords);
4169: VecScatterDestroy(&scat_i[0]);
4170: VecScatterDestroy(&scat_g[0]);
4171: VecDestroy(&ccoords);
4172: VecDestroy(&clcoords);
4173: PetscFree(scat_i);
4174: PetscFree(scat_g);
4175: }
4176: return(0);
4177: }
4179: /*@
4180: DMGetDimension - Return the topological dimension of the DM
4182: Not collective
4184: Input Parameter:
4185: . dm - The DM
4187: Output Parameter:
4188: . dim - The topological dimension
4190: Level: beginner
4192: .seealso: DMSetDimension(), DMCreate()
4193: @*/
4194: PetscErrorCode DMGetDimension(DM dm, PetscInt *dim)
4195: {
4199: *dim = dm->dim;
4200: return(0);
4201: }
4203: /*@
4204: DMSetDimension - Set the topological dimension of the DM
4206: Collective on dm
4208: Input Parameters:
4209: + dm - The DM
4210: - dim - The topological dimension
4212: Level: beginner
4214: .seealso: DMGetDimension(), DMCreate()
4215: @*/
4216: PetscErrorCode DMSetDimension(DM dm, PetscInt dim)
4217: {
4223: dm->dim = dim;
4224: if (dm->prob->dimEmbed < 0) {PetscDSSetCoordinateDimension(dm->prob, dm->dim);}
4225: return(0);
4226: }
4228: /*@
4229: DMGetDimPoints - Get the half-open interval for all points of a given dimension
4231: Collective on DM
4233: Input Parameters:
4234: + dm - the DM
4235: - dim - the dimension
4237: Output Parameters:
4238: + pStart - The first point of the given dimension
4239: . pEnd - The first point following points of the given dimension
4241: Note:
4242: The points are vertices in the Hasse diagram encoding the topology. This is explained in
4243: http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme,
4244: then the interval is empty.
4246: Level: intermediate
4248: .keywords: point, Hasse Diagram, dimension
4249: .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum()
4250: @*/
4251: PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
4252: {
4253: PetscInt d;
4258: DMGetDimension(dm, &d);
4259: if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d);
4260: (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);
4261: return(0);
4262: }
4264: /*@
4265: DMSetCoordinates - Sets into the DM a global vector that holds the coordinates
4267: Collective on DM
4269: Input Parameters:
4270: + dm - the DM
4271: - c - coordinate vector
4273: Note:
4274: The coordinates do include those for ghost points, which are in the local vector
4276: Level: intermediate
4278: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4279: .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM()
4280: @*/
4281: PetscErrorCode DMSetCoordinates(DM dm, Vec c)
4282: {
4288: PetscObjectReference((PetscObject) c);
4289: VecDestroy(&dm->coordinates);
4290: dm->coordinates = c;
4291: VecDestroy(&dm->coordinatesLocal);
4292: DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);
4293: DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);
4294: return(0);
4295: }
4297: /*@
4298: DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates
4300: Collective on DM
4302: Input Parameters:
4303: + dm - the DM
4304: - c - coordinate vector
4306: Note:
4307: The coordinates of ghost points can be set using DMSetCoordinates()
4308: followed by DMGetCoordinatesLocal(). This is intended to enable the
4309: setting of ghost coordinates outside of the domain.
4311: Level: intermediate
4313: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4314: .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM()
4315: @*/
4316: PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c)
4317: {
4323: PetscObjectReference((PetscObject) c);
4324: VecDestroy(&dm->coordinatesLocal);
4326: dm->coordinatesLocal = c;
4328: VecDestroy(&dm->coordinates);
4329: return(0);
4330: }
4332: /*@
4333: DMGetCoordinates - Gets a global vector with the coordinates associated with the DM.
4335: Not Collective
4337: Input Parameter:
4338: . dm - the DM
4340: Output Parameter:
4341: . c - global coordinate vector
4343: Note:
4344: This is a borrowed reference, so the user should NOT destroy this vector
4346: Each process has only the local coordinates (does NOT have the ghost coordinates).
4348: For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
4349: and (x_0,y_0,z_0,x_1,y_1,z_1...)
4351: Level: intermediate
4353: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4354: .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM()
4355: @*/
4356: PetscErrorCode DMGetCoordinates(DM dm, Vec *c)
4357: {
4363: if (!dm->coordinates && dm->coordinatesLocal) {
4364: DM cdm = NULL;
4366: DMGetCoordinateDM(dm, &cdm);
4367: DMCreateGlobalVector(cdm, &dm->coordinates);
4368: PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");
4369: DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);
4370: DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);
4371: }
4372: *c = dm->coordinates;
4373: return(0);
4374: }
4376: /*@
4377: DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM.
4379: Collective on DM
4381: Input Parameter:
4382: . dm - the DM
4384: Output Parameter:
4385: . c - coordinate vector
4387: Note:
4388: This is a borrowed reference, so the user should NOT destroy this vector
4390: Each process has the local and ghost coordinates
4392: For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
4393: and (x_0,y_0,z_0,x_1,y_1,z_1...)
4395: Level: intermediate
4397: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4398: .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM()
4399: @*/
4400: PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c)
4401: {
4407: if (!dm->coordinatesLocal && dm->coordinates) {
4408: DM cdm = NULL;
4410: DMGetCoordinateDM(dm, &cdm);
4411: DMCreateLocalVector(cdm, &dm->coordinatesLocal);
4412: PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");
4413: DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);
4414: DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);
4415: }
4416: *c = dm->coordinatesLocal;
4417: return(0);
4418: }
4420: /*@
4421: DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates
4423: Collective on DM
4425: Input Parameter:
4426: . dm - the DM
4428: Output Parameter:
4429: . cdm - coordinate DM
4431: Level: intermediate
4433: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4434: .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
4435: @*/
4436: PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm)
4437: {
4443: if (!dm->coordinateDM) {
4444: if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM");
4445: (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);
4446: }
4447: *cdm = dm->coordinateDM;
4448: return(0);
4449: }
4451: /*@
4452: DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates
4454: Logically Collective on DM
4456: Input Parameters:
4457: + dm - the DM
4458: - cdm - coordinate DM
4460: Level: intermediate
4462: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4463: .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
4464: @*/
4465: PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm)
4466: {
4472: PetscObjectReference((PetscObject)cdm);
4473: DMDestroy(&dm->coordinateDM);
4474: dm->coordinateDM = cdm;
4475: return(0);
4476: }
4478: /*@
4479: DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values.
4481: Not Collective
4483: Input Parameter:
4484: . dm - The DM object
4486: Output Parameter:
4487: . dim - The embedding dimension
4489: Level: intermediate
4491: .keywords: mesh, coordinates
4492: .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection()
4493: @*/
4494: PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim)
4495: {
4499: if (dm->dimEmbed == PETSC_DEFAULT) {
4500: dm->dimEmbed = dm->dim;
4501: }
4502: *dim = dm->dimEmbed;
4503: return(0);
4504: }
4506: /*@
4507: DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values.
4509: Not Collective
4511: Input Parameters:
4512: + dm - The DM object
4513: - dim - The embedding dimension
4515: Level: intermediate
4517: .keywords: mesh, coordinates
4518: .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection()
4519: @*/
4520: PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim)
4521: {
4526: dm->dimEmbed = dim;
4527: PetscDSSetCoordinateDimension(dm->prob, dm->dimEmbed);
4528: return(0);
4529: }
4531: /*@
4532: DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh.
4534: Not Collective
4536: Input Parameter:
4537: . dm - The DM object
4539: Output Parameter:
4540: . section - The PetscSection object
4542: Level: intermediate
4544: .keywords: mesh, coordinates
4545: .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection()
4546: @*/
4547: PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section)
4548: {
4549: DM cdm;
4555: DMGetCoordinateDM(dm, &cdm);
4556: DMGetDefaultSection(cdm, section);
4557: return(0);
4558: }
4560: /*@
4561: DMSetCoordinateSection - Set the layout of coordinate values over the mesh.
4563: Not Collective
4565: Input Parameters:
4566: + dm - The DM object
4567: . dim - The embedding dimension, or PETSC_DETERMINE
4568: - section - The PetscSection object
4570: Level: intermediate
4572: .keywords: mesh, coordinates
4573: .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection()
4574: @*/
4575: PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section)
4576: {
4577: DM cdm;
4583: DMGetCoordinateDM(dm, &cdm);
4584: DMSetDefaultSection(cdm, section);
4585: if (dim == PETSC_DETERMINE) {
4586: PetscInt d = PETSC_DEFAULT;
4587: PetscInt pStart, pEnd, vStart, vEnd, v, dd;
4589: PetscSectionGetChart(section, &pStart, &pEnd);
4590: DMGetDimPoints(dm, 0, &vStart, &vEnd);
4591: pStart = PetscMax(vStart, pStart);
4592: pEnd = PetscMin(vEnd, pEnd);
4593: for (v = pStart; v < pEnd; ++v) {
4594: PetscSectionGetDof(section, v, &dd);
4595: if (dd) {d = dd; break;}
4596: }
4597: if (d < 0) d = PETSC_DEFAULT;
4598: DMSetCoordinateDim(dm, d);
4599: }
4600: return(0);
4601: }
4603: /*@C
4604: DMGetPeriodicity - Get the description of mesh periodicity
4606: Input Parameters:
4607: . dm - The DM object
4609: Output Parameters:
4610: + per - Whether the DM is periodic or not
4611: . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates
4612: . L - If we assume the mesh is a torus, this is the length of each coordinate
4613: - bd - This describes the type of periodicity in each topological dimension
4615: Level: developer
4617: .seealso: DMGetPeriodicity()
4618: @*/
4619: PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd)
4620: {
4623: if (per) *per = dm->periodic;
4624: if (L) *L = dm->L;
4625: if (maxCell) *maxCell = dm->maxCell;
4626: if (bd) *bd = dm->bdtype;
4627: return(0);
4628: }
4630: /*@C
4631: DMSetPeriodicity - Set the description of mesh periodicity
4633: Input Parameters:
4634: + dm - The DM object
4635: . per - Whether the DM is periodic or not. If maxCell is not provided, coordinates need to be localized
4636: . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates
4637: . L - If we assume the mesh is a torus, this is the length of each coordinate
4638: - bd - This describes the type of periodicity in each topological dimension
4640: Level: developer
4642: .seealso: DMGetPeriodicity()
4643: @*/
4644: PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[])
4645: {
4646: PetscInt dim, d;
4652: if (maxCell) {
4656: }
4657: PetscFree3(dm->L,dm->maxCell,dm->bdtype);
4658: DMGetDimension(dm, &dim);
4659: if (maxCell) {
4660: PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);
4661: for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];}
4662: dm->periodic = PETSC_TRUE;
4663: } else {
4664: dm->periodic = per;
4665: }
4666: return(0);
4667: }
4669: /*@
4670: DMLocalizeCoordinate - If a mesh is periodic (a torus with lengths L_i, some of which can be infinite), project the coordinate onto [0, L_i) in each dimension.
4672: Input Parameters:
4673: + dm - The DM
4674: . in - The input coordinate point (dim numbers)
4675: - endpoint - Include the endpoint L_i
4677: Output Parameter:
4678: . out - The localized coordinate point
4680: Level: developer
4682: .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate()
4683: @*/
4684: PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[])
4685: {
4686: PetscInt dim, d;
4690: DMGetCoordinateDim(dm, &dim);
4691: if (!dm->maxCell) {
4692: for (d = 0; d < dim; ++d) out[d] = in[d];
4693: } else {
4694: if (endpoint) {
4695: for (d = 0; d < dim; ++d) {
4696: if ((PetscAbsReal(PetscRealPart(in[d])/dm->L[d] - PetscFloorReal(PetscRealPart(in[d])/dm->L[d])) < PETSC_SMALL) && (PetscRealPart(in[d])/dm->L[d] > PETSC_SMALL)) {
4697: out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1);
4698: } else {
4699: out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]);
4700: }
4701: }
4702: } else {
4703: for (d = 0; d < dim; ++d) {
4704: out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]);
4705: }
4706: }
4707: }
4708: return(0);
4709: }
4711: /*
4712: DMLocalizeCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer.
4714: Input Parameters:
4715: + dm - The DM
4716: . dim - The spatial dimension
4717: . anchor - The anchor point, the input point can be no more than maxCell away from it
4718: - in - The input coordinate point (dim numbers)
4720: Output Parameter:
4721: . out - The localized coordinate point
4723: Level: developer
4725: Note: This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually the one of the vertices on a containing cell
4727: .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate()
4728: */
4729: PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[])
4730: {
4731: PetscInt d;
4734: if (!dm->maxCell) {
4735: for (d = 0; d < dim; ++d) out[d] = in[d];
4736: } else {
4737: for (d = 0; d < dim; ++d) {
4738: if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) {
4739: out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d];
4740: } else {
4741: out[d] = in[d];
4742: }
4743: }
4744: }
4745: return(0);
4746: }
4747: PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[])
4748: {
4749: PetscInt d;
4752: if (!dm->maxCell) {
4753: for (d = 0; d < dim; ++d) out[d] = in[d];
4754: } else {
4755: for (d = 0; d < dim; ++d) {
4756: if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) {
4757: out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d];
4758: } else {
4759: out[d] = in[d];
4760: }
4761: }
4762: }
4763: return(0);
4764: }
4766: /*
4767: DMLocalizeAddCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer.
4769: Input Parameters:
4770: + dm - The DM
4771: . dim - The spatial dimension
4772: . anchor - The anchor point, the input point can be no more than maxCell away from it
4773: . in - The input coordinate delta (dim numbers)
4774: - out - The input coordinate point (dim numbers)
4776: Output Parameter:
4777: . out - The localized coordinate in + out
4779: Level: developer
4781: Note: This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually the one of the vertices on a containing cell
4783: .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate()
4784: */
4785: PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[])
4786: {
4787: PetscInt d;
4790: if (!dm->maxCell) {
4791: for (d = 0; d < dim; ++d) out[d] += in[d];
4792: } else {
4793: for (d = 0; d < dim; ++d) {
4794: if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) {
4795: out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d];
4796: } else {
4797: out[d] += in[d];
4798: }
4799: }
4800: }
4801: return(0);
4802: }
4804: /*@
4805: DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells
4807: Input Parameter:
4808: . dm - The DM
4810: Output Parameter:
4811: areLocalized - True if localized
4813: Level: developer
4815: .seealso: DMLocalizeCoordinates()
4816: @*/
4817: PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized)
4818: {
4819: DM cdm;
4820: PetscSection coordSection;
4821: PetscInt cStart, cEnd, sStart, sEnd, c, dof;
4822: PetscBool isPlex, alreadyLocalized;
4829: *areLocalized = PETSC_FALSE;
4830: if (!dm->periodic) return(0); /* This is a hideous optimization hack! */
4832: /* We need some generic way of refering to cells/vertices */
4833: DMGetCoordinateDM(dm, &cdm);
4834: DMGetCoordinateSection(dm, &coordSection);
4835: PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);
4836: if (!isPlex) SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM");
4838: DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);
4839: PetscSectionGetChart(coordSection, &sStart, &sEnd);
4840: alreadyLocalized = PETSC_FALSE;
4841: for (c = cStart; c < cEnd; ++c) {
4842: if (c < sStart || c >= sEnd) continue;
4843: PetscSectionGetDof(coordSection, c, &dof);
4844: if (dof) { alreadyLocalized = PETSC_TRUE; break; }
4845: }
4846: MPIU_Allreduce(&alreadyLocalized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));
4847: return(0);
4848: }
4851: /*@
4852: DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces
4854: Input Parameter:
4855: . dm - The DM
4857: Level: developer
4859: .seealso: DMLocalizeCoordinate(), DMLocalizeAddCoordinate()
4860: @*/
4861: PetscErrorCode DMLocalizeCoordinates(DM dm)
4862: {
4863: DM cdm;
4864: PetscSection coordSection, cSection;
4865: Vec coordinates, cVec;
4866: PetscScalar *coords, *coords2, *anchor, *localized;
4867: PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize;
4868: PetscBool alreadyLocalized, alreadyLocalizedGlobal;
4869: PetscInt maxHeight = 0, h;
4870: PetscInt *pStart = NULL, *pEnd = NULL;
4875: if (!dm->periodic) return(0);
4876: DMGetCoordinatesLocalized(dm, &alreadyLocalized);
4877: if (alreadyLocalized) return(0);
4879: /* We need some generic way of refering to cells/vertices */
4880: DMGetCoordinateDM(dm, &cdm);
4881: {
4882: PetscBool isplex;
4884: PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);
4885: if (isplex) {
4886: DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);
4887: DMPlexGetMaxProjectionHeight(cdm,&maxHeight);
4888: DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);
4889: pEnd = &pStart[maxHeight + 1];
4890: newStart = vStart;
4891: newEnd = vEnd;
4892: for (h = 0; h <= maxHeight; h++) {
4893: DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);
4894: newStart = PetscMin(newStart,pStart[h]);
4895: newEnd = PetscMax(newEnd,pEnd[h]);
4896: }
4897: } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM");
4898: }
4899: DMGetCoordinatesLocal(dm, &coordinates);
4900: if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector");
4901: DMGetCoordinateSection(dm, &coordSection);
4902: VecGetBlockSize(coordinates, &bs);
4903: PetscSectionGetChart(coordSection,&sStart,&sEnd);
4905: PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);
4906: PetscSectionSetNumFields(cSection, 1);
4907: PetscSectionGetFieldComponents(coordSection, 0, &Nc);
4908: PetscSectionSetFieldComponents(cSection, 0, Nc);
4909: PetscSectionSetChart(cSection, newStart, newEnd);
4911: DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);
4912: localized = &anchor[bs];
4913: alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE;
4914: for (h = 0; h <= maxHeight; h++) {
4915: PetscInt cStart = pStart[h], cEnd = pEnd[h], c;
4917: for (c = cStart; c < cEnd; ++c) {
4918: PetscScalar *cellCoords = NULL;
4919: PetscInt b;
4921: if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE;
4922: DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
4923: for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b];
4924: for (d = 0; d < dof/bs; ++d) {
4925: DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);
4926: for (b = 0; b < bs; b++) {
4927: if (cellCoords[d*bs + b] != localized[b]) break;
4928: }
4929: if (b < bs) break;
4930: }
4931: if (d < dof/bs) {
4932: if (c >= sStart && c < sEnd) {
4933: PetscInt cdof;
4935: PetscSectionGetDof(coordSection, c, &cdof);
4936: if (cdof != dof) alreadyLocalized = PETSC_FALSE;
4937: }
4938: PetscSectionSetDof(cSection, c, dof);
4939: PetscSectionSetFieldDof(cSection, c, 0, dof);
4940: }
4941: DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
4942: }
4943: }
4944: MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));
4945: if (alreadyLocalizedGlobal) {
4946: DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);
4947: PetscSectionDestroy(&cSection);
4948: DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);
4949: return(0);
4950: }
4951: for (v = vStart; v < vEnd; ++v) {
4952: PetscSectionGetDof(coordSection, v, &dof);
4953: PetscSectionSetDof(cSection, v, dof);
4954: PetscSectionSetFieldDof(cSection, v, 0, dof);
4955: }
4956: PetscSectionSetUp(cSection);
4957: PetscSectionGetStorageSize(cSection, &coordSize);
4958: VecCreate(PETSC_COMM_SELF, &cVec);
4959: PetscObjectSetName((PetscObject)cVec,"coordinates");
4960: VecSetBlockSize(cVec, bs);
4961: VecSetSizes(cVec, coordSize, PETSC_DETERMINE);
4962: VecSetType(cVec, VECSTANDARD);
4963: VecGetArrayRead(coordinates, (const PetscScalar**)&coords);
4964: VecGetArray(cVec, &coords2);
4965: for (v = vStart; v < vEnd; ++v) {
4966: PetscSectionGetDof(coordSection, v, &dof);
4967: PetscSectionGetOffset(coordSection, v, &off);
4968: PetscSectionGetOffset(cSection, v, &off2);
4969: for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d];
4970: }
4971: for (h = 0; h <= maxHeight; h++) {
4972: PetscInt cStart = pStart[h], cEnd = pEnd[h], c;
4974: for (c = cStart; c < cEnd; ++c) {
4975: PetscScalar *cellCoords = NULL;
4976: PetscInt b, cdof;
4978: PetscSectionGetDof(cSection,c,&cdof);
4979: if (!cdof) continue;
4980: DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
4981: PetscSectionGetOffset(cSection, c, &off2);
4982: for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b];
4983: for (d = 0; d < dof/bs; ++d) {DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);}
4984: DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
4985: }
4986: }
4987: DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);
4988: DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);
4989: VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);
4990: VecRestoreArray(cVec, &coords2);
4991: DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);
4992: DMSetCoordinatesLocal(dm, cVec);
4993: VecDestroy(&cVec);
4994: PetscSectionDestroy(&cSection);
4995: return(0);
4996: }
4998: /*@
4999: DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells
5001: Collective on Vec v (see explanation below)
5003: Input Parameters:
5004: + dm - The DM
5005: . v - The Vec of points
5006: . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST
5007: - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point.
5009: Output Parameter:
5010: + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used
5011: - cells - The PetscSF containing the ranks and local indices of the containing points.
5014: Level: developer
5016: Notes:
5017: To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator.
5018: To do a search of all the cells in the distributed mesh, v should have the same communicator as dm.
5020: If *cellSF is NULL on input, a PetscSF will be created.
5021: If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses.
5023: An array that maps each point to its containing cell can be obtained with
5025: $ const PetscSFNode *cells;
5026: $ PetscInt nFound;
5027: $ const PetscSFNode *found;
5028: $
5029: $ PetscSFGetGraph(cells,NULL,&nFound,&found,&cells);
5031: Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is
5032: the index of the cell in its rank's local numbering.
5034: .keywords: point location, mesh
5035: .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType
5036: @*/
5037: PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF)
5038: {
5045: if (*cellSF) {
5046: PetscMPIInt result;
5049: MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);
5050: if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's");
5051: } else {
5052: PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);
5053: }
5054: PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);
5055: if (dm->ops->locatepoints) {
5056: (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);
5057: } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM");
5058: PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);
5059: return(0);
5060: }
5062: /*@
5063: DMGetOutputDM - Retrieve the DM associated with the layout for output
5065: Input Parameter:
5066: . dm - The original DM
5068: Output Parameter:
5069: . odm - The DM which provides the layout for output
5071: Level: intermediate
5073: .seealso: VecView(), DMGetDefaultGlobalSection()
5074: @*/
5075: PetscErrorCode DMGetOutputDM(DM dm, DM *odm)
5076: {
5077: PetscSection section;
5078: PetscBool hasConstraints, ghasConstraints;
5084: DMGetDefaultSection(dm, §ion);
5085: PetscSectionHasConstraints(section, &hasConstraints);
5086: MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));
5087: if (!ghasConstraints) {
5088: *odm = dm;
5089: return(0);
5090: }
5091: if (!dm->dmBC) {
5092: PetscDS ds;
5093: PetscSection newSection, gsection;
5094: PetscSF sf;
5096: DMClone(dm, &dm->dmBC);
5097: DMGetDS(dm, &ds);
5098: DMSetDS(dm->dmBC, ds);
5099: PetscSectionClone(section, &newSection);
5100: DMSetDefaultSection(dm->dmBC, newSection);
5101: PetscSectionDestroy(&newSection);
5102: DMGetPointSF(dm->dmBC, &sf);
5103: PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);
5104: DMSetDefaultGlobalSection(dm->dmBC, gsection);
5105: PetscSectionDestroy(&gsection);
5106: }
5107: *odm = dm->dmBC;
5108: return(0);
5109: }
5111: /*@
5112: DMGetOutputSequenceNumber - Retrieve the sequence number/value for output
5114: Input Parameter:
5115: . dm - The original DM
5117: Output Parameters:
5118: + num - The output sequence number
5119: - val - The output sequence value
5121: Level: intermediate
5123: Note: This is intended for output that should appear in sequence, for instance
5124: a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
5126: .seealso: VecView()
5127: @*/
5128: PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val)
5129: {
5134: return(0);
5135: }
5137: /*@
5138: DMSetOutputSequenceNumber - Set the sequence number/value for output
5140: Input Parameters:
5141: + dm - The original DM
5142: . num - The output sequence number
5143: - val - The output sequence value
5145: Level: intermediate
5147: Note: This is intended for output that should appear in sequence, for instance
5148: a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
5150: .seealso: VecView()
5151: @*/
5152: PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val)
5153: {
5156: dm->outputSequenceNum = num;
5157: dm->outputSequenceVal = val;
5158: return(0);
5159: }
5161: /*@C
5162: DMOutputSequenceLoad - Retrieve the sequence value from a Viewer
5164: Input Parameters:
5165: + dm - The original DM
5166: . name - The sequence name
5167: - num - The output sequence number
5169: Output Parameter:
5170: . val - The output sequence value
5172: Level: intermediate
5174: Note: This is intended for output that should appear in sequence, for instance
5175: a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
5177: .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView()
5178: @*/
5179: PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val)
5180: {
5181: PetscBool ishdf5;
5188: PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);
5189: if (ishdf5) {
5190: #if defined(PETSC_HAVE_HDF5)
5191: PetscScalar value;
5193: DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);
5194: *val = PetscRealPart(value);
5195: #endif
5196: } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
5197: return(0);
5198: }
5200: /*@
5201: DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution
5203: Not collective
5205: Input Parameter:
5206: . dm - The DM
5208: Output Parameter:
5209: . useNatural - The flag to build the mapping to a natural order during distribution
5211: Level: beginner
5213: .seealso: DMSetUseNatural(), DMCreate()
5214: @*/
5215: PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural)
5216: {
5220: *useNatural = dm->useNatural;
5221: return(0);
5222: }
5224: /*@
5225: DMSetUseNatural - Set the flag for creating a mapping to the natural order on distribution
5227: Collective on dm
5229: Input Parameters:
5230: + dm - The DM
5231: - useNatural - The flag to build the mapping to a natural order during distribution
5233: Level: beginner
5235: .seealso: DMGetUseNatural(), DMCreate()
5236: @*/
5237: PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural)
5238: {
5242: dm->useNatural = useNatural;
5243: return(0);
5244: }
5247: /*@C
5248: DMCreateLabel - Create a label of the given name if it does not already exist
5250: Not Collective
5252: Input Parameters:
5253: + dm - The DM object
5254: - name - The label name
5256: Level: intermediate
5258: .keywords: mesh
5259: .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5260: @*/
5261: PetscErrorCode DMCreateLabel(DM dm, const char name[])
5262: {
5263: DMLabelLink next = dm->labels->next;
5264: PetscBool flg = PETSC_FALSE;
5270: while (next) {
5271: PetscStrcmp(name, next->label->name, &flg);
5272: if (flg) break;
5273: next = next->next;
5274: }
5275: if (!flg) {
5276: DMLabelLink tmpLabel;
5278: PetscCalloc1(1, &tmpLabel);
5279: DMLabelCreate(name, &tmpLabel->label);
5280: tmpLabel->output = PETSC_TRUE;
5281: tmpLabel->next = dm->labels->next;
5282: dm->labels->next = tmpLabel;
5283: }
5284: return(0);
5285: }
5287: /*@C
5288: DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default
5290: Not Collective
5292: Input Parameters:
5293: + dm - The DM object
5294: . name - The label name
5295: - point - The mesh point
5297: Output Parameter:
5298: . value - The label value for this point, or -1 if the point is not in the label
5300: Level: beginner
5302: .keywords: mesh
5303: .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS()
5304: @*/
5305: PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value)
5306: {
5307: DMLabel label;
5313: DMGetLabel(dm, name, &label);
5314: if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);
5315: DMLabelGetValue(label, point, value);
5316: return(0);
5317: }
5319: /*@C
5320: DMSetLabelValue - Add a point to a Sieve Label with given value
5322: Not Collective
5324: Input Parameters:
5325: + dm - The DM object
5326: . name - The label name
5327: . point - The mesh point
5328: - value - The label value for this point
5330: Output Parameter:
5332: Level: beginner
5334: .keywords: mesh
5335: .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue()
5336: @*/
5337: PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
5338: {
5339: DMLabel label;
5345: DMGetLabel(dm, name, &label);
5346: if (!label) {
5347: DMCreateLabel(dm, name);
5348: DMGetLabel(dm, name, &label);
5349: }
5350: DMLabelSetValue(label, point, value);
5351: return(0);
5352: }
5354: /*@C
5355: DMClearLabelValue - Remove a point from a Sieve Label with given value
5357: Not Collective
5359: Input Parameters:
5360: + dm - The DM object
5361: . name - The label name
5362: . point - The mesh point
5363: - value - The label value for this point
5365: Output Parameter:
5367: Level: beginner
5369: .keywords: mesh
5370: .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS()
5371: @*/
5372: PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
5373: {
5374: DMLabel label;
5380: DMGetLabel(dm, name, &label);
5381: if (!label) return(0);
5382: DMLabelClearValue(label, point, value);
5383: return(0);
5384: }
5386: /*@C
5387: DMGetLabelSize - Get the number of different integer ids in a Label
5389: Not Collective
5391: Input Parameters:
5392: + dm - The DM object
5393: - name - The label name
5395: Output Parameter:
5396: . size - The number of different integer ids, or 0 if the label does not exist
5398: Level: beginner
5400: .keywords: mesh
5401: .seealso: DMLabeGetNumValues(), DMSetLabelValue()
5402: @*/
5403: PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size)
5404: {
5405: DMLabel label;
5412: DMGetLabel(dm, name, &label);
5413: *size = 0;
5414: if (!label) return(0);
5415: DMLabelGetNumValues(label, size);
5416: return(0);
5417: }
5419: /*@C
5420: DMGetLabelIdIS - Get the integer ids in a label
5422: Not Collective
5424: Input Parameters:
5425: + mesh - The DM object
5426: - name - The label name
5428: Output Parameter:
5429: . ids - The integer ids, or NULL if the label does not exist
5431: Level: beginner
5433: .keywords: mesh
5434: .seealso: DMLabelGetValueIS(), DMGetLabelSize()
5435: @*/
5436: PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids)
5437: {
5438: DMLabel label;
5445: DMGetLabel(dm, name, &label);
5446: *ids = NULL;
5447: if (label) {
5448: DMLabelGetValueIS(label, ids);
5449: } else {
5450: /* returning an empty IS */
5451: ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);
5452: }
5453: return(0);
5454: }
5456: /*@C
5457: DMGetStratumSize - Get the number of points in a label stratum
5459: Not Collective
5461: Input Parameters:
5462: + dm - The DM object
5463: . name - The label name
5464: - value - The stratum value
5466: Output Parameter:
5467: . size - The stratum size
5469: Level: beginner
5471: .keywords: mesh
5472: .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds()
5473: @*/
5474: PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size)
5475: {
5476: DMLabel label;
5483: DMGetLabel(dm, name, &label);
5484: *size = 0;
5485: if (!label) return(0);
5486: DMLabelGetStratumSize(label, value, size);
5487: return(0);
5488: }
5490: /*@C
5491: DMGetStratumIS - Get the points in a label stratum
5493: Not Collective
5495: Input Parameters:
5496: + dm - The DM object
5497: . name - The label name
5498: - value - The stratum value
5500: Output Parameter:
5501: . points - The stratum points, or NULL if the label does not exist or does not have that value
5503: Level: beginner
5505: .keywords: mesh
5506: .seealso: DMLabelGetStratumIS(), DMGetStratumSize()
5507: @*/
5508: PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points)
5509: {
5510: DMLabel label;
5517: DMGetLabel(dm, name, &label);
5518: *points = NULL;
5519: if (!label) return(0);
5520: DMLabelGetStratumIS(label, value, points);
5521: return(0);
5522: }
5524: /*@C
5525: DMGetStratumIS - Set the points in a label stratum
5527: Not Collective
5529: Input Parameters:
5530: + dm - The DM object
5531: . name - The label name
5532: . value - The stratum value
5533: - points - The stratum points
5535: Level: beginner
5537: .keywords: mesh
5538: .seealso: DMLabelSetStratumIS(), DMGetStratumSize()
5539: @*/
5540: PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points)
5541: {
5542: DMLabel label;
5549: DMGetLabel(dm, name, &label);
5550: if (!label) return(0);
5551: DMLabelSetStratumIS(label, value, points);
5552: return(0);
5553: }
5555: /*@C
5556: DMClearLabelStratum - Remove all points from a stratum from a Sieve Label
5558: Not Collective
5560: Input Parameters:
5561: + dm - The DM object
5562: . name - The label name
5563: - value - The label value for this point
5565: Output Parameter:
5567: Level: beginner
5569: .keywords: mesh
5570: .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue()
5571: @*/
5572: PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value)
5573: {
5574: DMLabel label;
5580: DMGetLabel(dm, name, &label);
5581: if (!label) return(0);
5582: DMLabelClearStratum(label, value);
5583: return(0);
5584: }
5586: /*@
5587: DMGetNumLabels - Return the number of labels defined by the mesh
5589: Not Collective
5591: Input Parameter:
5592: . dm - The DM object
5594: Output Parameter:
5595: . numLabels - the number of Labels
5597: Level: intermediate
5599: .keywords: mesh
5600: .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5601: @*/
5602: PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels)
5603: {
5604: DMLabelLink next = dm->labels->next;
5605: PetscInt n = 0;
5610: while (next) {++n; next = next->next;}
5611: *numLabels = n;
5612: return(0);
5613: }
5615: /*@C
5616: DMGetLabelName - Return the name of nth label
5618: Not Collective
5620: Input Parameters:
5621: + dm - The DM object
5622: - n - the label number
5624: Output Parameter:
5625: . name - the label name
5627: Level: intermediate
5629: .keywords: mesh
5630: .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5631: @*/
5632: PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name)
5633: {
5634: DMLabelLink next = dm->labels->next;
5635: PetscInt l = 0;
5640: while (next) {
5641: if (l == n) {
5642: *name = next->label->name;
5643: return(0);
5644: }
5645: ++l;
5646: next = next->next;
5647: }
5648: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n);
5649: }
5651: /*@C
5652: DMHasLabel - Determine whether the mesh has a label of a given name
5654: Not Collective
5656: Input Parameters:
5657: + dm - The DM object
5658: - name - The label name
5660: Output Parameter:
5661: . hasLabel - PETSC_TRUE if the label is present
5663: Level: intermediate
5665: .keywords: mesh
5666: .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5667: @*/
5668: PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel)
5669: {
5670: DMLabelLink next = dm->labels->next;
5677: *hasLabel = PETSC_FALSE;
5678: while (next) {
5679: PetscStrcmp(name, next->label->name, hasLabel);
5680: if (*hasLabel) break;
5681: next = next->next;
5682: }
5683: return(0);
5684: }
5686: /*@C
5687: DMGetLabel - Return the label of a given name, or NULL
5689: Not Collective
5691: Input Parameters:
5692: + dm - The DM object
5693: - name - The label name
5695: Output Parameter:
5696: . label - The DMLabel, or NULL if the label is absent
5698: Level: intermediate
5700: .keywords: mesh
5701: .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5702: @*/
5703: PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label)
5704: {
5705: DMLabelLink next = dm->labels->next;
5706: PetscBool hasLabel;
5713: *label = NULL;
5714: while (next) {
5715: PetscStrcmp(name, next->label->name, &hasLabel);
5716: if (hasLabel) {
5717: *label = next->label;
5718: break;
5719: }
5720: next = next->next;
5721: }
5722: return(0);
5723: }
5725: /*@C
5726: DMGetLabelByNum - Return the nth label
5728: Not Collective
5730: Input Parameters:
5731: + dm - The DM object
5732: - n - the label number
5734: Output Parameter:
5735: . label - the label
5737: Level: intermediate
5739: .keywords: mesh
5740: .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5741: @*/
5742: PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label)
5743: {
5744: DMLabelLink next = dm->labels->next;
5745: PetscInt l = 0;
5750: while (next) {
5751: if (l == n) {
5752: *label = next->label;
5753: return(0);
5754: }
5755: ++l;
5756: next = next->next;
5757: }
5758: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n);
5759: }
5761: /*@C
5762: DMAddLabel - Add the label to this mesh
5764: Not Collective
5766: Input Parameters:
5767: + dm - The DM object
5768: - label - The DMLabel
5770: Level: developer
5772: .keywords: mesh
5773: .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5774: @*/
5775: PetscErrorCode DMAddLabel(DM dm, DMLabel label)
5776: {
5777: DMLabelLink tmpLabel;
5778: PetscBool hasLabel;
5783: DMHasLabel(dm, label->name, &hasLabel);
5784: if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", label->name);
5785: PetscCalloc1(1, &tmpLabel);
5786: tmpLabel->label = label;
5787: tmpLabel->output = PETSC_TRUE;
5788: tmpLabel->next = dm->labels->next;
5789: dm->labels->next = tmpLabel;
5790: return(0);
5791: }
5793: /*@C
5794: DMRemoveLabel - Remove the label from this mesh
5796: Not Collective
5798: Input Parameters:
5799: + dm - The DM object
5800: - name - The label name
5802: Output Parameter:
5803: . label - The DMLabel, or NULL if the label is absent
5805: Level: developer
5807: .keywords: mesh
5808: .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5809: @*/
5810: PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label)
5811: {
5812: DMLabelLink next = dm->labels->next;
5813: DMLabelLink last = NULL;
5814: PetscBool hasLabel;
5819: DMHasLabel(dm, name, &hasLabel);
5820: *label = NULL;
5821: if (!hasLabel) return(0);
5822: while (next) {
5823: PetscStrcmp(name, next->label->name, &hasLabel);
5824: if (hasLabel) {
5825: if (last) last->next = next->next;
5826: else dm->labels->next = next->next;
5827: next->next = NULL;
5828: *label = next->label;
5829: PetscStrcmp(name, "depth", &hasLabel);
5830: if (hasLabel) {
5831: dm->depthLabel = NULL;
5832: }
5833: PetscFree(next);
5834: break;
5835: }
5836: last = next;
5837: next = next->next;
5838: }
5839: return(0);
5840: }
5842: /*@C
5843: DMGetLabelOutput - Get the output flag for a given label
5845: Not Collective
5847: Input Parameters:
5848: + dm - The DM object
5849: - name - The label name
5851: Output Parameter:
5852: . output - The flag for output
5854: Level: developer
5856: .keywords: mesh
5857: .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5858: @*/
5859: PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output)
5860: {
5861: DMLabelLink next = dm->labels->next;
5868: while (next) {
5869: PetscBool flg;
5871: PetscStrcmp(name, next->label->name, &flg);
5872: if (flg) {*output = next->output; return(0);}
5873: next = next->next;
5874: }
5875: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
5876: }
5878: /*@C
5879: DMSetLabelOutput - Set the output flag for a given label
5881: Not Collective
5883: Input Parameters:
5884: + dm - The DM object
5885: . name - The label name
5886: - output - The flag for output
5888: Level: developer
5890: .keywords: mesh
5891: .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5892: @*/
5893: PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output)
5894: {
5895: DMLabelLink next = dm->labels->next;
5901: while (next) {
5902: PetscBool flg;
5904: PetscStrcmp(name, next->label->name, &flg);
5905: if (flg) {next->output = output; return(0);}
5906: next = next->next;
5907: }
5908: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
5909: }
5912: /*@
5913: DMCopyLabels - Copy labels from one mesh to another with a superset of the points
5915: Collective on DM
5917: Input Parameter:
5918: . dmA - The DM object with initial labels
5920: Output Parameter:
5921: . dmB - The DM object with copied labels
5923: Level: intermediate
5925: Note: This is typically used when interpolating or otherwise adding to a mesh
5927: .keywords: mesh
5928: .seealso: DMCopyCoordinates(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection()
5929: @*/
5930: PetscErrorCode DMCopyLabels(DM dmA, DM dmB)
5931: {
5932: PetscInt numLabels, l;
5936: if (dmA == dmB) return(0);
5937: DMGetNumLabels(dmA, &numLabels);
5938: for (l = 0; l < numLabels; ++l) {
5939: DMLabel label, labelNew;
5940: const char *name;
5941: PetscBool flg;
5943: DMGetLabelName(dmA, l, &name);
5944: PetscStrcmp(name, "depth", &flg);
5945: if (flg) continue;
5946: DMGetLabel(dmA, name, &label);
5947: DMLabelDuplicate(label, &labelNew);
5948: DMAddLabel(dmB, labelNew);
5949: }
5950: return(0);
5951: }
5953: /*@
5954: DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement
5956: Input Parameter:
5957: . dm - The DM object
5959: Output Parameter:
5960: . cdm - The coarse DM
5962: Level: intermediate
5964: .seealso: DMSetCoarseDM()
5965: @*/
5966: PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm)
5967: {
5971: *cdm = dm->coarseMesh;
5972: return(0);
5973: }
5975: /*@
5976: DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement
5978: Input Parameters:
5979: + dm - The DM object
5980: - cdm - The coarse DM
5982: Level: intermediate
5984: .seealso: DMGetCoarseDM()
5985: @*/
5986: PetscErrorCode DMSetCoarseDM(DM dm, DM cdm)
5987: {
5993: PetscObjectReference((PetscObject)cdm);
5994: DMDestroy(&dm->coarseMesh);
5995: dm->coarseMesh = cdm;
5996: return(0);
5997: }
5999: /*@
6000: DMGetFineDM - Get the fine mesh from which this was obtained by refinement
6002: Input Parameter:
6003: . dm - The DM object
6005: Output Parameter:
6006: . fdm - The fine DM
6008: Level: intermediate
6010: .seealso: DMSetFineDM()
6011: @*/
6012: PetscErrorCode DMGetFineDM(DM dm, DM *fdm)
6013: {
6017: *fdm = dm->fineMesh;
6018: return(0);
6019: }
6021: /*@
6022: DMSetFineDM - Set the fine mesh from which this was obtained by refinement
6024: Input Parameters:
6025: + dm - The DM object
6026: - fdm - The fine DM
6028: Level: intermediate
6030: .seealso: DMGetFineDM()
6031: @*/
6032: PetscErrorCode DMSetFineDM(DM dm, DM fdm)
6033: {
6039: PetscObjectReference((PetscObject)fdm);
6040: DMDestroy(&dm->fineMesh);
6041: dm->fineMesh = fdm;
6042: return(0);
6043: }
6045: /*=== DMBoundary code ===*/
6047: PetscErrorCode DMCopyBoundary(DM dm, DM dmNew)
6048: {
6052: PetscDSCopyBoundary(dm->prob,dmNew->prob);
6053: return(0);
6054: }
6056: /*@C
6057: DMAddBoundary - Add a boundary condition to the model
6059: Input Parameters:
6060: + dm - The DM, with a PetscDS that matches the problem being constrained
6061: . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
6062: . name - The BC name
6063: . labelname - The label defining constrained points
6064: . field - The field to constrain
6065: . numcomps - The number of constrained field components
6066: . comps - An array of constrained component numbers
6067: . bcFunc - A pointwise function giving boundary values
6068: . numids - The number of DMLabel ids for constrained points
6069: . ids - An array of ids for constrained points
6070: - ctx - An optional user context for bcFunc
6072: Options Database Keys:
6073: + -bc_<boundary name> <num> - Overrides the boundary ids
6074: - -bc_<boundary name>_comp <num> - Overrides the boundary components
6076: Level: developer
6078: .seealso: DMGetBoundary()
6079: @*/
6080: PetscErrorCode DMAddBoundary(DM dm, DMBoundaryConditionType type, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(void), PetscInt numids, const PetscInt *ids, void *ctx)
6081: {
6086: PetscDSAddBoundary(dm->prob,type,name,labelname,field,numcomps,comps,bcFunc,numids,ids,ctx);
6087: return(0);
6088: }
6090: /*@
6091: DMGetNumBoundary - Get the number of registered BC
6093: Input Parameters:
6094: . dm - The mesh object
6096: Output Parameters:
6097: . numBd - The number of BC
6099: Level: intermediate
6101: .seealso: DMAddBoundary(), DMGetBoundary()
6102: @*/
6103: PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd)
6104: {
6109: PetscDSGetNumBoundary(dm->prob,numBd);
6110: return(0);
6111: }
6113: /*@C
6114: DMGetBoundary - Get a model boundary condition
6116: Input Parameters:
6117: + dm - The mesh object
6118: - bd - The BC number
6120: Output Parameters:
6121: + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
6122: . name - The BC name
6123: . labelname - The label defining constrained points
6124: . field - The field to constrain
6125: . numcomps - The number of constrained field components
6126: . comps - An array of constrained component numbers
6127: . bcFunc - A pointwise function giving boundary values
6128: . numids - The number of DMLabel ids for constrained points
6129: . ids - An array of ids for constrained points
6130: - ctx - An optional user context for bcFunc
6132: Options Database Keys:
6133: + -bc_<boundary name> <num> - Overrides the boundary ids
6134: - -bc_<boundary name>_comp <num> - Overrides the boundary components
6136: Level: developer
6138: .seealso: DMAddBoundary()
6139: @*/
6140: PetscErrorCode DMGetBoundary(DM dm, PetscInt bd, DMBoundaryConditionType *type, const char **name, const char **labelname, PetscInt *field, PetscInt *numcomps, const PetscInt **comps, void (**func)(void), PetscInt *numids, const PetscInt **ids, void **ctx)
6141: {
6146: PetscDSGetBoundary(dm->prob,bd,type,name,labelname,field,numcomps,comps,func,numids,ids,ctx);
6147: return(0);
6148: }
6150: static PetscErrorCode DMPopulateBoundary(DM dm)
6151: {
6152: DMBoundary *lastnext;
6153: DSBoundary dsbound;
6157: dsbound = dm->prob->boundary;
6158: if (dm->boundary) {
6159: DMBoundary next = dm->boundary;
6161: /* quick check to see if the PetscDS has changed */
6162: if (next->dsboundary == dsbound) return(0);
6163: /* the PetscDS has changed: tear down and rebuild */
6164: while (next) {
6165: DMBoundary b = next;
6167: next = b->next;
6168: PetscFree(b);
6169: }
6170: dm->boundary = NULL;
6171: }
6173: lastnext = &(dm->boundary);
6174: while (dsbound) {
6175: DMBoundary dmbound;
6177: PetscNew(&dmbound);
6178: dmbound->dsboundary = dsbound;
6179: DMGetLabel(dm, dsbound->labelname, &(dmbound->label));
6180: if (!dmbound->label) PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);
6181: /* push on the back instead of the front so that it is in the same order as in the PetscDS */
6182: *lastnext = dmbound;
6183: lastnext = &(dmbound->next);
6184: dsbound = dsbound->next;
6185: }
6186: return(0);
6187: }
6189: PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd)
6190: {
6191: DMBoundary b;
6197: *isBd = PETSC_FALSE;
6198: DMPopulateBoundary(dm);
6199: b = dm->boundary;
6200: while (b && !(*isBd)) {
6201: DMLabel label = b->label;
6202: DSBoundary dsb = b->dsboundary;
6204: if (label) {
6205: PetscInt i;
6207: for (i = 0; i < dsb->numids && !(*isBd); ++i) {
6208: DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);
6209: }
6210: }
6211: b = b->next;
6212: }
6213: return(0);
6214: }
6216: /*@C
6217: DMProjectFunction - This projects the given function into the function space provided.
6219: Input Parameters:
6220: + dm - The DM
6221: . time - The time
6222: . funcs - The coordinate functions to evaluate, one per field
6223: . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null.
6224: - mode - The insertion mode for values
6226: Output Parameter:
6227: . X - vector
6229: Calling sequence of func:
6230: $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx);
6232: + dim - The spatial dimension
6233: . x - The coordinates
6234: . Nf - The number of fields
6235: . u - The output field values
6236: - ctx - optional user-defined function context
6238: Level: developer
6240: .seealso: DMComputeL2Diff()
6241: @*/
6242: PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X)
6243: {
6244: Vec localX;
6249: DMGetLocalVector(dm, &localX);
6250: DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);
6251: DMLocalToGlobalBegin(dm, localX, mode, X);
6252: DMLocalToGlobalEnd(dm, localX, mode, X);
6253: DMRestoreLocalVector(dm, &localX);
6254: return(0);
6255: }
6257: PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
6258: {
6264: if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name);
6265: (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);
6266: return(0);
6267: }
6269: PetscErrorCode DMProjectFunctionLabel(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X)
6270: {
6271: Vec localX;
6276: DMGetLocalVector(dm, &localX);
6277: DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);
6278: DMLocalToGlobalBegin(dm, localX, mode, X);
6279: DMLocalToGlobalEnd(dm, localX, mode, X);
6280: DMRestoreLocalVector(dm, &localX);
6281: return(0);
6282: }
6284: PetscErrorCode DMProjectFunctionLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
6285: {
6291: if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name);
6292: (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);
6293: return(0);
6294: }
6296: PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU,
6297: void (**funcs)(PetscInt, PetscInt, PetscInt,
6298: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
6299: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
6300: PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
6301: InsertMode mode, Vec localX)
6302: {
6309: if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name);
6310: (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);
6311: return(0);
6312: }
6314: PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU,
6315: void (**funcs)(PetscInt, PetscInt, PetscInt,
6316: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
6317: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
6318: PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
6319: InsertMode mode, Vec localX)
6320: {
6327: if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name);
6328: (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);
6329: return(0);
6330: }
6332: /*@C
6333: DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h.
6335: Input Parameters:
6336: + dm - The DM
6337: . time - The time
6338: . funcs - The functions to evaluate for each field component
6339: . ctxs - Optional array of contexts to pass to each function, or NULL.
6340: - X - The coefficient vector u_h, a global vector
6342: Output Parameter:
6343: . diff - The diff ||u - u_h||_2
6345: Level: developer
6347: .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff()
6348: @*/
6349: PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff)
6350: {
6356: if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name);
6357: (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);
6358: return(0);
6359: }
6361: /*@C
6362: DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h.
6364: Input Parameters:
6365: + dm - The DM
6366: , time - The time
6367: . funcs - The gradient functions to evaluate for each field component
6368: . ctxs - Optional array of contexts to pass to each function, or NULL.
6369: . X - The coefficient vector u_h, a global vector
6370: - n - The vector to project along
6372: Output Parameter:
6373: . diff - The diff ||(grad u - grad u_h) . n||_2
6375: Level: developer
6377: .seealso: DMProjectFunction(), DMComputeL2Diff()
6378: @*/
6379: PetscErrorCode DMComputeL2GradientDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, const PetscReal n[], PetscReal *diff)
6380: {
6386: if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name);
6387: (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);
6388: return(0);
6389: }
6391: /*@C
6392: DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components.
6394: Input Parameters:
6395: + dm - The DM
6396: . time - The time
6397: . funcs - The functions to evaluate for each field component
6398: . ctxs - Optional array of contexts to pass to each function, or NULL.
6399: - X - The coefficient vector u_h, a global vector
6401: Output Parameter:
6402: . diff - The array of differences, ||u^f - u^f_h||_2
6404: Level: developer
6406: .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff()
6407: @*/
6408: PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[])
6409: {
6415: if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name);
6416: (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);
6417: return(0);
6418: }
6420: /*@C
6421: DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have
6422: specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN.
6424: Collective on dm
6426: Input parameters:
6427: + dm - the pre-adaptation DM object
6428: - label - label with the flags
6430: Output parameters:
6431: . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced.
6433: Level: intermediate
6435: .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine()
6436: @*/
6437: PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt)
6438: {
6445: *dmAdapt = NULL;
6446: if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name);
6447: (dm->ops->adaptlabel)(dm, label, dmAdapt);
6448: return(0);
6449: }
6451: /*@C
6452: DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library.
6454: Input Parameters:
6455: + dm - The DM object
6456: . metric - The metric to which the mesh is adapted, defined vertex-wise.
6457: - bdLabel - Label for boundary tags, which will be preserved in the output mesh. bdLabel should be NULL if there is no such label, and should be different from "_boundary_".
6459: Output Parameter:
6460: . dmAdapt - Pointer to the DM object containing the adapted mesh
6462: Note: The label in the adapted mesh will be registered under the name of the input DMLabel object
6464: Level: advanced
6466: .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine()
6467: @*/
6468: PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt)
6469: {
6477: *dmAdapt = NULL;
6478: if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name);
6479: (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);
6480: return(0);
6481: }
6483: /*@C
6484: DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors
6486: Not Collective
6488: Input Parameter:
6489: . dm - The DM
6491: Output Parameter:
6492: . nranks - the number of neighbours
6493: . ranks - the neighbors ranks
6495: Notes:
6496: Do not free the array, it is freed when the DM is destroyed.
6498: Level: beginner
6500: .seealso: DMDAGetNeighbors(), PetscSFGetRanks()
6501: @*/
6502: PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[])
6503: {
6508: if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name);
6509: (dm->ops->getneighbors)(dm,nranks,ranks);
6510: return(0);
6511: }
6513: #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */
6515: /*
6516: Converts the input vector to a ghosted vector and then calls the standard coloring code.
6517: This has be a different function because it requires DM which is not defined in the Mat library
6518: */
6519: PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx)
6520: {
6524: if (coloring->ctype == IS_COLORING_LOCAL) {
6525: Vec x1local;
6526: DM dm;
6527: MatGetDM(J,&dm);
6528: if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM");
6529: DMGetLocalVector(dm,&x1local);
6530: DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);
6531: DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);
6532: x1 = x1local;
6533: }
6534: MatFDColoringApply_AIJ(J,coloring,x1,sctx);
6535: if (coloring->ctype == IS_COLORING_LOCAL) {
6536: DM dm;
6537: MatGetDM(J,&dm);
6538: DMRestoreLocalVector(dm,&x1);
6539: }
6540: return(0);
6541: }
6543: /*@
6544: MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring
6546: Input Parameter:
6547: . coloring - the MatFDColoring object
6549: Developer Notes: this routine exists because the PETSc Mat library does not know about the DM objects
6551: Level: advanced
6553: .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType
6554: @*/
6555: PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring)
6556: {
6558: coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM;
6559: return(0);
6560: }