xref: /petsc/src/dm/impls/shell/dmshell.c (revision 4dfa11a44d5adf2389f1d3acbc8f3c1116dc6c3a)
1fe1899a2SJed Brown #include <petscdmshell.h> /*I    "petscdmshell.h"  I*/
207475bc1SBarry Smith #include <petscmat.h>
3af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
4fe1899a2SJed Brown 
5fe1899a2SJed Brown typedef struct {
6fe1899a2SJed Brown   Vec        Xglobal;
7dc43b69eSJed Brown   Vec        Xlocal;
8fe1899a2SJed Brown   Mat        A;
9a94b16f6SRichard Tran Mills   VecScatter gtol;
10a94b16f6SRichard Tran Mills   VecScatter ltog;
11f089877aSRichard Tran Mills   VecScatter ltol;
12fef3a512SBarry Smith   void      *ctx;
1309904cd0SBarry Smith   PetscErrorCode (*destroyctx)(void *);
14fe1899a2SJed Brown } DM_Shell;
15fe1899a2SJed Brown 
167a108d1dSBarry Smith /*@
177a108d1dSBarry Smith    DMGlobalToLocalBeginDefaultShell - Uses the GlobalToLocal VecScatter context set by the user to begin a global to local scatter
188d359177SBarry Smith    Collective
198d359177SBarry Smith 
204165533cSJose E. Roman    Input Parameters:
218d359177SBarry Smith +  dm - shell DM
228d359177SBarry Smith .  g - global vector
238d359177SBarry Smith .  mode - InsertMode
248d359177SBarry Smith -  l - local vector
258d359177SBarry Smith 
267a108d1dSBarry Smith    Level: advanced
278d359177SBarry Smith 
287a108d1dSBarry Smith    Note:  This is not normally called directly by user code, generally user code calls DMGlobalToLocalBegin() and DMGlobalToLocalEnd(). If the user provides their own custom routines to DMShellSetLocalToGlobal() then those routines might have reason to call this function.
297a108d1dSBarry Smith 
30db781477SPatrick Sanan .seealso: `DMGlobalToLocalEndDefaultShell()`
318d359177SBarry Smith @*/
329371c9d4SSatish Balay PetscErrorCode DMGlobalToLocalBeginDefaultShell(DM dm, Vec g, InsertMode mode, Vec l) {
338d359177SBarry Smith   DM_Shell *shell = (DM_Shell *)dm->data;
348d359177SBarry Smith 
358d359177SBarry Smith   PetscFunctionBegin;
367a8be351SBarry Smith   PetscCheck(shell->gtol, ((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
379566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(shell->gtol, g, l, mode, SCATTER_FORWARD));
388d359177SBarry Smith   PetscFunctionReturn(0);
398d359177SBarry Smith }
408d359177SBarry Smith 
417a108d1dSBarry Smith /*@
427a108d1dSBarry Smith    DMGlobalToLocalEndDefaultShell - Uses the GlobalToLocal VecScatter context set by the user to end a global to local scatter
438d359177SBarry Smith    Collective
448d359177SBarry Smith 
454165533cSJose E. Roman    Input Parameters:
468d359177SBarry Smith +  dm - shell DM
478d359177SBarry Smith .  g - global vector
488d359177SBarry Smith .  mode - InsertMode
498d359177SBarry Smith -  l - local vector
508d359177SBarry Smith 
517a108d1dSBarry Smith    Level: advanced
528d359177SBarry Smith 
53db781477SPatrick Sanan .seealso: `DMGlobalToLocalBeginDefaultShell()`
548d359177SBarry Smith @*/
559371c9d4SSatish Balay PetscErrorCode DMGlobalToLocalEndDefaultShell(DM dm, Vec g, InsertMode mode, Vec l) {
568d359177SBarry Smith   DM_Shell *shell = (DM_Shell *)dm->data;
578d359177SBarry Smith 
588d359177SBarry Smith   PetscFunctionBegin;
597a8be351SBarry Smith   PetscCheck(shell->gtol, ((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
609566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(shell->gtol, g, l, mode, SCATTER_FORWARD));
618d359177SBarry Smith   PetscFunctionReturn(0);
628d359177SBarry Smith }
638d359177SBarry Smith 
64c5076b69SRichard Tran Mills /*@
65c5076b69SRichard Tran Mills    DMLocalToGlobalBeginDefaultShell - Uses the LocalToGlobal VecScatter context set by the user to begin a local to global scatter
66c5076b69SRichard Tran Mills    Collective
67c5076b69SRichard Tran Mills 
684165533cSJose E. Roman    Input Parameters:
69c5076b69SRichard Tran Mills +  dm - shell DM
70c5076b69SRichard Tran Mills .  l - local vector
71c5076b69SRichard Tran Mills .  mode - InsertMode
72c5076b69SRichard Tran Mills -  g - global vector
73c5076b69SRichard Tran Mills 
74c5076b69SRichard Tran Mills    Level: advanced
75c5076b69SRichard Tran Mills 
76c5076b69SRichard Tran Mills    Note:  This is not normally called directly by user code, generally user code calls DMLocalToGlobalBegin() and DMLocalToGlobalEnd(). If the user provides their own custom routines to DMShellSetLocalToGlobal() then those routines might have reason to call this function.
77c5076b69SRichard Tran Mills 
78db781477SPatrick Sanan .seealso: `DMLocalToGlobalEndDefaultShell()`
79c5076b69SRichard Tran Mills @*/
809371c9d4SSatish Balay PetscErrorCode DMLocalToGlobalBeginDefaultShell(DM dm, Vec l, InsertMode mode, Vec g) {
81c5076b69SRichard Tran Mills   DM_Shell *shell = (DM_Shell *)dm->data;
82c5076b69SRichard Tran Mills 
83c5076b69SRichard Tran Mills   PetscFunctionBegin;
847a8be351SBarry Smith   PetscCheck(shell->ltog, ((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()");
859566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(shell->ltog, l, g, mode, SCATTER_FORWARD));
86c5076b69SRichard Tran Mills   PetscFunctionReturn(0);
87c5076b69SRichard Tran Mills }
88c5076b69SRichard Tran Mills 
89c5076b69SRichard Tran Mills /*@
90c5076b69SRichard Tran Mills    DMLocalToGlobalEndDefaultShell - Uses the LocalToGlobal VecScatter context set by the user to end a local to global scatter
91c5076b69SRichard Tran Mills    Collective
92c5076b69SRichard Tran Mills 
934165533cSJose E. Roman    Input Parameters:
94c5076b69SRichard Tran Mills +  dm - shell DM
95c5076b69SRichard Tran Mills .  l - local vector
96c5076b69SRichard Tran Mills .  mode - InsertMode
97c5076b69SRichard Tran Mills -  g - global vector
98c5076b69SRichard Tran Mills 
99c5076b69SRichard Tran Mills    Level: advanced
100c5076b69SRichard Tran Mills 
101db781477SPatrick Sanan .seealso: `DMLocalToGlobalBeginDefaultShell()`
102c5076b69SRichard Tran Mills @*/
1039371c9d4SSatish Balay PetscErrorCode DMLocalToGlobalEndDefaultShell(DM dm, Vec l, InsertMode mode, Vec g) {
104c5076b69SRichard Tran Mills   DM_Shell *shell = (DM_Shell *)dm->data;
105c5076b69SRichard Tran Mills 
106c5076b69SRichard Tran Mills   PetscFunctionBegin;
1077a8be351SBarry Smith   PetscCheck(shell->ltog, ((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()");
1089566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(shell->ltog, l, g, mode, SCATTER_FORWARD));
109c5076b69SRichard Tran Mills   PetscFunctionReturn(0);
110c5076b69SRichard Tran Mills }
111c5076b69SRichard Tran Mills 
112f3db62a7SRichard Tran Mills /*@
113f3db62a7SRichard Tran Mills    DMLocalToLocalBeginDefaultShell - Uses the LocalToLocal VecScatter context set by the user to begin a local to local scatter
114f3db62a7SRichard Tran Mills    Collective
115f3db62a7SRichard Tran Mills 
1164165533cSJose E. Roman    Input Parameters:
117f3db62a7SRichard Tran Mills +  dm - shell DM
118f3db62a7SRichard Tran Mills .  g - the original local vector
119f3db62a7SRichard Tran Mills -  mode - InsertMode
120f3db62a7SRichard Tran Mills 
121f3db62a7SRichard Tran Mills    Output Parameter:
122f3db62a7SRichard Tran Mills .  l  - the local vector with correct ghost values
123f3db62a7SRichard Tran Mills 
124f3db62a7SRichard Tran Mills    Level: advanced
125f3db62a7SRichard Tran Mills 
126f3db62a7SRichard Tran Mills    Note:  This is not normally called directly by user code, generally user code calls DMLocalToLocalBegin() and DMLocalToLocalEnd(). If the user provides their own custom routines to DMShellSetLocalToLocal() then those routines might have reason to call this function.
127f3db62a7SRichard Tran Mills 
128db781477SPatrick Sanan .seealso: `DMLocalToLocalEndDefaultShell()`
129f3db62a7SRichard Tran Mills @*/
1309371c9d4SSatish Balay PetscErrorCode DMLocalToLocalBeginDefaultShell(DM dm, Vec g, InsertMode mode, Vec l) {
131f3db62a7SRichard Tran Mills   DM_Shell *shell = (DM_Shell *)dm->data;
132f3db62a7SRichard Tran Mills 
133f3db62a7SRichard Tran Mills   PetscFunctionBegin;
1347a8be351SBarry Smith   PetscCheck(shell->ltol, ((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToLocalVecScatter()");
1359566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(shell->ltol, g, l, mode, SCATTER_FORWARD));
136f3db62a7SRichard Tran Mills   PetscFunctionReturn(0);
137f3db62a7SRichard Tran Mills }
138f3db62a7SRichard Tran Mills 
139f3db62a7SRichard Tran Mills /*@
140f3db62a7SRichard Tran Mills    DMLocalToLocalEndDefaultShell - Uses the LocalToLocal VecScatter context set by the user to end a local to local scatter
141f3db62a7SRichard Tran Mills    Collective
142f3db62a7SRichard Tran Mills 
1434165533cSJose E. Roman    Input Parameters:
144f3db62a7SRichard Tran Mills +  dm - shell DM
145f3db62a7SRichard Tran Mills .  g - the original local vector
146f3db62a7SRichard Tran Mills -  mode - InsertMode
147f3db62a7SRichard Tran Mills 
148f3db62a7SRichard Tran Mills    Output Parameter:
149f3db62a7SRichard Tran Mills .  l  - the local vector with correct ghost values
150f3db62a7SRichard Tran Mills 
151f3db62a7SRichard Tran Mills    Level: advanced
152f3db62a7SRichard Tran Mills 
153db781477SPatrick Sanan .seealso: `DMLocalToLocalBeginDefaultShell()`
154f3db62a7SRichard Tran Mills @*/
1559371c9d4SSatish Balay PetscErrorCode DMLocalToLocalEndDefaultShell(DM dm, Vec g, InsertMode mode, Vec l) {
156f3db62a7SRichard Tran Mills   DM_Shell *shell = (DM_Shell *)dm->data;
157f3db62a7SRichard Tran Mills 
158f3db62a7SRichard Tran Mills   PetscFunctionBegin;
1597a8be351SBarry Smith   PetscCheck(shell->ltol, ((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
1609566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(shell->ltol, g, l, mode, SCATTER_FORWARD));
161f3db62a7SRichard Tran Mills   PetscFunctionReturn(0);
162f3db62a7SRichard Tran Mills }
163c5076b69SRichard Tran Mills 
1649371c9d4SSatish Balay static PetscErrorCode DMCreateMatrix_Shell(DM dm, Mat *J) {
165fe1899a2SJed Brown   DM_Shell *shell = (DM_Shell *)dm->data;
166fe1899a2SJed Brown   Mat       A;
167fe1899a2SJed Brown 
168fe1899a2SJed Brown   PetscFunctionBegin;
169fe1899a2SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
170064a246eSJacob Faibussowitsch   PetscValidPointer(J, 2);
1717bde9f88SJed Brown   if (!shell->A) {
1727bde9f88SJed Brown     if (shell->Xglobal) {
1737bde9f88SJed Brown       PetscInt m, M;
1749566063dSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "Naively creating matrix using global vector distribution without preallocation\n"));
1759566063dSJacob Faibussowitsch       PetscCall(VecGetSize(shell->Xglobal, &M));
1769566063dSJacob Faibussowitsch       PetscCall(VecGetLocalSize(shell->Xglobal, &m));
1779566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), &shell->A));
1789566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(shell->A, m, m, M, M));
1799566063dSJacob Faibussowitsch       PetscCall(MatSetType(shell->A, dm->mattype));
1809566063dSJacob Faibussowitsch       PetscCall(MatSetUp(shell->A));
181ce94432eSBarry Smith     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMShellSetMatrix(), DMShellSetCreateMatrix(), or provide a vector");
1827bde9f88SJed Brown   }
183fe1899a2SJed Brown   A = shell->A;
1849566063dSJacob Faibussowitsch   PetscCall(MatDuplicate(A, MAT_SHARE_NONZERO_PATTERN, J));
1859566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*J, dm));
186fe1899a2SJed Brown   PetscFunctionReturn(0);
187fe1899a2SJed Brown }
188fe1899a2SJed Brown 
1899371c9d4SSatish Balay PetscErrorCode DMCreateGlobalVector_Shell(DM dm, Vec *gvec) {
190fe1899a2SJed Brown   DM_Shell *shell = (DM_Shell *)dm->data;
191fe1899a2SJed Brown   Vec       X;
192fe1899a2SJed Brown 
193fe1899a2SJed Brown   PetscFunctionBegin;
194fe1899a2SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
195fe1899a2SJed Brown   PetscValidPointer(gvec, 2);
196ea78f98cSLisandro Dalcin   *gvec = NULL;
197fe1899a2SJed Brown   X     = shell->Xglobal;
1987a8be351SBarry Smith   PetscCheck(X, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMShellSetGlobalVector() or DMShellSetCreateGlobalVector()");
19906f803f6SStefano Zampini   /* Need to create a copy in order to attach the DM to the vector */
2009566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(X, gvec));
2019566063dSJacob Faibussowitsch   PetscCall(VecZeroEntries(*gvec));
2029566063dSJacob Faibussowitsch   PetscCall(VecSetDM(*gvec, dm));
203fe1899a2SJed Brown   PetscFunctionReturn(0);
204fe1899a2SJed Brown }
205fe1899a2SJed Brown 
2069371c9d4SSatish Balay PetscErrorCode DMCreateLocalVector_Shell(DM dm, Vec *gvec) {
207dc43b69eSJed Brown   DM_Shell *shell = (DM_Shell *)dm->data;
208dc43b69eSJed Brown   Vec       X;
209dc43b69eSJed Brown 
210dc43b69eSJed Brown   PetscFunctionBegin;
211dc43b69eSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
212dc43b69eSJed Brown   PetscValidPointer(gvec, 2);
213ea78f98cSLisandro Dalcin   *gvec = NULL;
214dc43b69eSJed Brown   X     = shell->Xlocal;
2157a8be351SBarry Smith   PetscCheck(X, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMShellSetLocalVector() or DMShellSetCreateLocalVector()");
21606f803f6SStefano Zampini   /* Need to create a copy in order to attach the DM to the vector */
2179566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(X, gvec));
2189566063dSJacob Faibussowitsch   PetscCall(VecZeroEntries(*gvec));
2199566063dSJacob Faibussowitsch   PetscCall(VecSetDM(*gvec, dm));
220dc43b69eSJed Brown   PetscFunctionReturn(0);
221dc43b69eSJed Brown }
222dc43b69eSJed Brown 
223fef3a512SBarry Smith /*@
22409904cd0SBarry Smith    DMShellSetDestroyContext - set a function that destroys the context provided with `DMShellSetContext()`
22509904cd0SBarry Smith 
22609904cd0SBarry Smith    Collective
22709904cd0SBarry Smith 
22809904cd0SBarry Smith    Input Parameters:
22909904cd0SBarry Smith .  ctx - the context
23009904cd0SBarry Smith 
23109904cd0SBarry Smith    Level: advanced
23209904cd0SBarry Smith 
23309904cd0SBarry Smith .seealso: `DMShellSetContext()`, `DMShellGetContext()`
23409904cd0SBarry Smith @*/
23509904cd0SBarry Smith PetscErrorCode DMShellSetDestroyContext(DM dm, PetscErrorCode (*destroyctx)(void *)) {
23609904cd0SBarry Smith   DM_Shell *shell = (DM_Shell *)dm->data;
23709904cd0SBarry Smith   PetscBool isshell;
23809904cd0SBarry Smith 
23909904cd0SBarry Smith   PetscFunctionBegin;
24009904cd0SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24109904cd0SBarry Smith   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
24209904cd0SBarry Smith   if (!isshell) PetscFunctionReturn(0);
24309904cd0SBarry Smith   shell->destroyctx = destroyctx;
24409904cd0SBarry Smith   PetscFunctionReturn(0);
24509904cd0SBarry Smith }
24609904cd0SBarry Smith 
24709904cd0SBarry Smith /*@
248fef3a512SBarry Smith    DMShellSetContext - set some data to be usable by this DM
249fef3a512SBarry Smith 
250fef3a512SBarry Smith    Collective
251fef3a512SBarry Smith 
2524165533cSJose E. Roman    Input Parameters:
253fef3a512SBarry Smith +  dm - shell DM
254fef3a512SBarry Smith -  ctx - the context
255fef3a512SBarry Smith 
256fef3a512SBarry Smith    Level: advanced
257fef3a512SBarry Smith 
258db781477SPatrick Sanan .seealso: `DMCreateMatrix()`, `DMShellGetContext()`
259fef3a512SBarry Smith @*/
2609371c9d4SSatish Balay PetscErrorCode DMShellSetContext(DM dm, void *ctx) {
261fef3a512SBarry Smith   DM_Shell *shell = (DM_Shell *)dm->data;
262fef3a512SBarry Smith   PetscBool isshell;
263fef3a512SBarry Smith 
264fef3a512SBarry Smith   PetscFunctionBegin;
265fef3a512SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2669566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
267fef3a512SBarry Smith   if (!isshell) PetscFunctionReturn(0);
268fef3a512SBarry Smith   shell->ctx = ctx;
269fef3a512SBarry Smith   PetscFunctionReturn(0);
270fef3a512SBarry Smith }
271fef3a512SBarry Smith 
272fef3a512SBarry Smith /*@
273bf890c61SBoris Boutkov    DMShellGetContext - Returns the user-provided context associated to the DM
274fef3a512SBarry Smith 
275fef3a512SBarry Smith    Collective
276fef3a512SBarry Smith 
2774165533cSJose E. Roman    Input Parameter:
278fef3a512SBarry Smith .  dm - shell DM
279fef3a512SBarry Smith 
2804165533cSJose E. Roman    Output Parameter:
281fef3a512SBarry Smith .  ctx - the context
282fef3a512SBarry Smith 
283fef3a512SBarry Smith    Level: advanced
284fef3a512SBarry Smith 
285db781477SPatrick Sanan .seealso: `DMCreateMatrix()`, `DMShellSetContext()`
286fef3a512SBarry Smith @*/
2879371c9d4SSatish Balay PetscErrorCode DMShellGetContext(DM dm, void *ctx) {
288fef3a512SBarry Smith   DM_Shell *shell = (DM_Shell *)dm->data;
289fef3a512SBarry Smith   PetscBool isshell;
290fef3a512SBarry Smith 
291fef3a512SBarry Smith   PetscFunctionBegin;
292fef3a512SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2939566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
2947a8be351SBarry Smith   PetscCheck(isshell, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Can only use with DMSHELL type DMs");
2953ec1f749SStefano Zampini   *(void **)ctx = shell->ctx;
296fef3a512SBarry Smith   PetscFunctionReturn(0);
297fef3a512SBarry Smith }
298fef3a512SBarry Smith 
299fe1899a2SJed Brown /*@
300fe1899a2SJed Brown    DMShellSetMatrix - sets a template matrix associated with the DMShell
301fe1899a2SJed Brown 
302fe1899a2SJed Brown    Collective
303fe1899a2SJed Brown 
3044165533cSJose E. Roman    Input Parameters:
305fe1899a2SJed Brown +  dm - shell DM
306fe1899a2SJed Brown -  J - template matrix
307fe1899a2SJed Brown 
308fe1899a2SJed Brown    Level: advanced
309fe1899a2SJed Brown 
31006f803f6SStefano Zampini    Developer Notes:
31106f803f6SStefano Zampini     To avoid circular references, if J is already associated to the same DM, then MatDuplicate(SHARE_NONZERO_PATTERN) is called, followed by removing the DM reference from the private template.
31206f803f6SStefano Zampini 
313db781477SPatrick Sanan .seealso: `DMCreateMatrix()`, `DMShellSetCreateMatrix()`, `DMShellSetContext()`, `DMShellGetContext()`
314fe1899a2SJed Brown @*/
3159371c9d4SSatish Balay PetscErrorCode DMShellSetMatrix(DM dm, Mat J) {
316fe1899a2SJed Brown   DM_Shell *shell = (DM_Shell *)dm->data;
3178c87107bSJed Brown   PetscBool isshell;
31806f803f6SStefano Zampini   DM        mdm;
319fe1899a2SJed Brown 
320fe1899a2SJed Brown   PetscFunctionBegin;
3218c87107bSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3228c87107bSJed Brown   PetscValidHeaderSpecific(J, MAT_CLASSID, 2);
3239566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
3248c87107bSJed Brown   if (!isshell) PetscFunctionReturn(0);
32506f803f6SStefano Zampini   if (J == shell->A) PetscFunctionReturn(0);
3269566063dSJacob Faibussowitsch   PetscCall(MatGetDM(J, &mdm));
3279566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)J));
3289566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&shell->A));
32906f803f6SStefano Zampini   if (mdm == dm) {
3309566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(J, MAT_SHARE_NONZERO_PATTERN, &shell->A));
3319566063dSJacob Faibussowitsch     PetscCall(MatSetDM(shell->A, NULL));
33206f803f6SStefano Zampini   } else shell->A = J;
333fe1899a2SJed Brown   PetscFunctionReturn(0);
334fe1899a2SJed Brown }
335fe1899a2SJed Brown 
336fe1899a2SJed Brown /*@C
337fe1899a2SJed Brown    DMShellSetCreateMatrix - sets the routine to create a matrix associated with the shell DM
338fe1899a2SJed Brown 
339d083f849SBarry Smith    Logically Collective on dm
340fe1899a2SJed Brown 
3414165533cSJose E. Roman    Input Parameters:
342fe1899a2SJed Brown +  dm - the shell DM
343fe1899a2SJed Brown -  func - the function to create a matrix
344fe1899a2SJed Brown 
345fe1899a2SJed Brown    Level: advanced
346fe1899a2SJed Brown 
347db781477SPatrick Sanan .seealso: `DMCreateMatrix()`, `DMShellSetMatrix()`, `DMShellSetContext()`, `DMShellGetContext()`
348fe1899a2SJed Brown @*/
3499371c9d4SSatish Balay PetscErrorCode DMShellSetCreateMatrix(DM dm, PetscErrorCode (*func)(DM, Mat *)) {
350fe1899a2SJed Brown   PetscFunctionBegin;
351fe1899a2SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
352fe1899a2SJed Brown   dm->ops->creatematrix = func;
353fe1899a2SJed Brown   PetscFunctionReturn(0);
354fe1899a2SJed Brown }
355fe1899a2SJed Brown 
356fe1899a2SJed Brown /*@
357fe1899a2SJed Brown    DMShellSetGlobalVector - sets a template global vector associated with the DMShell
358fe1899a2SJed Brown 
359d083f849SBarry Smith    Logically Collective on dm
360fe1899a2SJed Brown 
3614165533cSJose E. Roman    Input Parameters:
362fe1899a2SJed Brown +  dm - shell DM
363fe1899a2SJed Brown -  X - template vector
364fe1899a2SJed Brown 
365fe1899a2SJed Brown    Level: advanced
366fe1899a2SJed Brown 
367db781477SPatrick Sanan .seealso: `DMCreateGlobalVector()`, `DMShellSetMatrix()`, `DMShellSetCreateGlobalVector()`
368fe1899a2SJed Brown @*/
3699371c9d4SSatish Balay PetscErrorCode DMShellSetGlobalVector(DM dm, Vec X) {
370fe1899a2SJed Brown   DM_Shell *shell = (DM_Shell *)dm->data;
3718c87107bSJed Brown   PetscBool isshell;
372cca7ec1eSBarry Smith   DM        vdm;
373fe1899a2SJed Brown 
374fe1899a2SJed Brown   PetscFunctionBegin;
3758c87107bSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3768c87107bSJed Brown   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
3779566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
3788c87107bSJed Brown   if (!isshell) PetscFunctionReturn(0);
3799566063dSJacob Faibussowitsch   PetscCall(VecGetDM(X, &vdm));
380cca7ec1eSBarry Smith   /*
381cca7ec1eSBarry Smith       if the vector proposed as the new base global vector for the DM is a DM vector associated
382cca7ec1eSBarry Smith       with the same DM then the current base global vector for the DM is ok and if we replace it with the new one
383cca7ec1eSBarry Smith       we get a circular dependency that prevents the DM from being destroy when it should be.
384cca7ec1eSBarry Smith       This occurs when SNESSet/GetNPC() is used with a SNES that does not have a user provided
385cca7ec1eSBarry Smith       DM attached to it since the inner SNES (which shares the DM with the outer SNES) tries
386cca7ec1eSBarry Smith       to set its input vector (which is associated with the DM) as the base global vector.
387cca7ec1eSBarry Smith       Thanks to Juan P. Mendez Granado Re: [petsc-maint] Nonlinear conjugate gradien
388cca7ec1eSBarry Smith       for pointing out the problem.
389cca7ec1eSBarry Smith    */
390cca7ec1eSBarry Smith   if (vdm == dm) PetscFunctionReturn(0);
3919566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)X));
3929566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&shell->Xglobal));
393fe1899a2SJed Brown   shell->Xglobal = X;
394fe1899a2SJed Brown   PetscFunctionReturn(0);
395fe1899a2SJed Brown }
396fe1899a2SJed Brown 
39704d741b1SMatthew G. Knepley /*@
39804d741b1SMatthew G. Knepley   DMShellGetGlobalVector - Returns the template global vector associated with the DMShell, or NULL if it was not set
39904d741b1SMatthew G. Knepley 
40004d741b1SMatthew G. Knepley    Not collective
40104d741b1SMatthew G. Knepley 
4024165533cSJose E. Roman    Input Parameters:
40304d741b1SMatthew G. Knepley +  dm - shell DM
40404d741b1SMatthew G. Knepley -  X - template vector
40504d741b1SMatthew G. Knepley 
40604d741b1SMatthew G. Knepley    Level: advanced
40704d741b1SMatthew G. Knepley 
408db781477SPatrick Sanan .seealso: `DMShellSetGlobalVector()`, `DMShellSetCreateGlobalVector()`, `DMCreateGlobalVector()`
40904d741b1SMatthew G. Knepley @*/
4109371c9d4SSatish Balay PetscErrorCode DMShellGetGlobalVector(DM dm, Vec *X) {
41104d741b1SMatthew G. Knepley   DM_Shell *shell = (DM_Shell *)dm->data;
41204d741b1SMatthew G. Knepley   PetscBool isshell;
41304d741b1SMatthew G. Knepley 
41404d741b1SMatthew G. Knepley   PetscFunctionBegin;
41504d741b1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
41604d741b1SMatthew G. Knepley   PetscValidPointer(X, 2);
4179566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
41804d741b1SMatthew G. Knepley   if (!isshell) PetscFunctionReturn(0);
41904d741b1SMatthew G. Knepley   *X = shell->Xglobal;
42004d741b1SMatthew G. Knepley   PetscFunctionReturn(0);
42104d741b1SMatthew G. Knepley }
42204d741b1SMatthew G. Knepley 
423fe1899a2SJed Brown /*@C
424fe1899a2SJed Brown    DMShellSetCreateGlobalVector - sets the routine to create a global vector associated with the shell DM
425fe1899a2SJed Brown 
426fe1899a2SJed Brown    Logically Collective
427fe1899a2SJed Brown 
4284165533cSJose E. Roman    Input Parameters:
429fe1899a2SJed Brown +  dm - the shell DM
430fe1899a2SJed Brown -  func - the creation routine
431fe1899a2SJed Brown 
432fe1899a2SJed Brown    Level: advanced
433fe1899a2SJed Brown 
434db781477SPatrick Sanan .seealso: `DMShellSetGlobalVector()`, `DMShellSetCreateMatrix()`, `DMShellSetContext()`, `DMShellGetContext()`
435fe1899a2SJed Brown @*/
4369371c9d4SSatish Balay PetscErrorCode DMShellSetCreateGlobalVector(DM dm, PetscErrorCode (*func)(DM, Vec *)) {
437fe1899a2SJed Brown   PetscFunctionBegin;
438fe1899a2SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
439fe1899a2SJed Brown   dm->ops->createglobalvector = func;
440fe1899a2SJed Brown   PetscFunctionReturn(0);
441fe1899a2SJed Brown }
442fe1899a2SJed Brown 
443dc43b69eSJed Brown /*@
444dc43b69eSJed Brown    DMShellSetLocalVector - sets a template local vector associated with the DMShell
445dc43b69eSJed Brown 
446d083f849SBarry Smith    Logically Collective on dm
447dc43b69eSJed Brown 
4484165533cSJose E. Roman    Input Parameters:
449dc43b69eSJed Brown +  dm - shell DM
450dc43b69eSJed Brown -  X - template vector
451dc43b69eSJed Brown 
452dc43b69eSJed Brown    Level: advanced
453dc43b69eSJed Brown 
454db781477SPatrick Sanan .seealso: `DMCreateLocalVector()`, `DMShellSetMatrix()`, `DMShellSetCreateLocalVector()`
455dc43b69eSJed Brown @*/
4569371c9d4SSatish Balay PetscErrorCode DMShellSetLocalVector(DM dm, Vec X) {
457dc43b69eSJed Brown   DM_Shell *shell = (DM_Shell *)dm->data;
458dc43b69eSJed Brown   PetscBool isshell;
459cca7ec1eSBarry Smith   DM        vdm;
460dc43b69eSJed Brown 
461dc43b69eSJed Brown   PetscFunctionBegin;
462dc43b69eSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
463dc43b69eSJed Brown   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
4649566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
465dc43b69eSJed Brown   if (!isshell) PetscFunctionReturn(0);
4669566063dSJacob Faibussowitsch   PetscCall(VecGetDM(X, &vdm));
467cca7ec1eSBarry Smith   /*
468cca7ec1eSBarry Smith       if the vector proposed as the new base global vector for the DM is a DM vector associated
469cca7ec1eSBarry Smith       with the same DM then the current base global vector for the DM is ok and if we replace it with the new one
470cca7ec1eSBarry Smith       we get a circular dependency that prevents the DM from being destroy when it should be.
471cca7ec1eSBarry Smith       This occurs when SNESSet/GetNPC() is used with a SNES that does not have a user provided
472cca7ec1eSBarry Smith       DM attached to it since the inner SNES (which shares the DM with the outer SNES) tries
473cca7ec1eSBarry Smith       to set its input vector (which is associated with the DM) as the base global vector.
474cca7ec1eSBarry Smith       Thanks to Juan P. Mendez Granado Re: [petsc-maint] Nonlinear conjugate gradien
475cca7ec1eSBarry Smith       for pointing out the problem.
476cca7ec1eSBarry Smith    */
477cca7ec1eSBarry Smith   if (vdm == dm) PetscFunctionReturn(0);
4789566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)X));
4799566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&shell->Xlocal));
480dc43b69eSJed Brown   shell->Xlocal = X;
481dc43b69eSJed Brown   PetscFunctionReturn(0);
482dc43b69eSJed Brown }
483dc43b69eSJed Brown 
484dc43b69eSJed Brown /*@C
485dc43b69eSJed Brown    DMShellSetCreateLocalVector - sets the routine to create a local vector associated with the shell DM
486dc43b69eSJed Brown 
487dc43b69eSJed Brown    Logically Collective
488dc43b69eSJed Brown 
4894165533cSJose E. Roman    Input Parameters:
490dc43b69eSJed Brown +  dm - the shell DM
491dc43b69eSJed Brown -  func - the creation routine
492dc43b69eSJed Brown 
493dc43b69eSJed Brown    Level: advanced
494dc43b69eSJed Brown 
495db781477SPatrick Sanan .seealso: `DMShellSetLocalVector()`, `DMShellSetCreateMatrix()`, `DMShellSetContext()`, `DMShellGetContext()`
496dc43b69eSJed Brown @*/
4979371c9d4SSatish Balay PetscErrorCode DMShellSetCreateLocalVector(DM dm, PetscErrorCode (*func)(DM, Vec *)) {
498dc43b69eSJed Brown   PetscFunctionBegin;
499dc43b69eSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
500dc43b69eSJed Brown   dm->ops->createlocalvector = func;
501dc43b69eSJed Brown   PetscFunctionReturn(0);
502dc43b69eSJed Brown }
503dc43b69eSJed Brown 
5048339e6d0SRichard Tran Mills /*@C
5058339e6d0SRichard Tran Mills    DMShellSetGlobalToLocal - Sets the routines used to perform a global to local scatter
5068339e6d0SRichard Tran Mills 
507d083f849SBarry Smith    Logically Collective on dm
5088339e6d0SRichard Tran Mills 
5094165533cSJose E. Roman    Input Parameters
5108339e6d0SRichard Tran Mills +  dm - the shell DM
5118339e6d0SRichard Tran Mills .  begin - the routine that begins the global to local scatter
5128339e6d0SRichard Tran Mills -  end - the routine that ends the global to local scatter
5138339e6d0SRichard Tran Mills 
51495452b02SPatrick Sanan    Notes:
51595452b02SPatrick Sanan     If these functions are not provided but DMShellSetGlobalToLocalVecScatter() is called then
516f3db62a7SRichard Tran Mills    DMGlobalToLocalBeginDefaultShell()/DMGlobalToLocalEndDefaultShell() are used to to perform the transfers
5177a108d1dSBarry Smith 
5188339e6d0SRichard Tran Mills    Level: advanced
5198339e6d0SRichard Tran Mills 
520db781477SPatrick Sanan .seealso: `DMShellSetLocalToGlobal()`, `DMGlobalToLocalBeginDefaultShell()`, `DMGlobalToLocalEndDefaultShell()`
5218339e6d0SRichard Tran Mills @*/
5229371c9d4SSatish Balay PetscErrorCode DMShellSetGlobalToLocal(DM dm, PetscErrorCode (*begin)(DM, Vec, InsertMode, Vec), PetscErrorCode (*end)(DM, Vec, InsertMode, Vec)) {
5238339e6d0SRichard Tran Mills   PetscFunctionBegin;
5242d1bcd87SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5258339e6d0SRichard Tran Mills   dm->ops->globaltolocalbegin = begin;
5268339e6d0SRichard Tran Mills   dm->ops->globaltolocalend   = end;
5278339e6d0SRichard Tran Mills   PetscFunctionReturn(0);
5288339e6d0SRichard Tran Mills }
5298339e6d0SRichard Tran Mills 
5308339e6d0SRichard Tran Mills /*@C
5318339e6d0SRichard Tran Mills    DMShellSetLocalToGlobal - Sets the routines used to perform a local to global scatter
5328339e6d0SRichard Tran Mills 
533d083f849SBarry Smith    Logically Collective on dm
5348339e6d0SRichard Tran Mills 
5354165533cSJose E. Roman    Input Parameters
5368339e6d0SRichard Tran Mills +  dm - the shell DM
5378339e6d0SRichard Tran Mills .  begin - the routine that begins the local to global scatter
5388339e6d0SRichard Tran Mills -  end - the routine that ends the local to global scatter
5398339e6d0SRichard Tran Mills 
54095452b02SPatrick Sanan    Notes:
54195452b02SPatrick Sanan     If these functions are not provided but DMShellSetLocalToGlobalVecScatter() is called then
542f3db62a7SRichard Tran Mills    DMLocalToGlobalBeginDefaultShell()/DMLocalToGlobalEndDefaultShell() are used to to perform the transfers
543f3db62a7SRichard Tran Mills 
5448339e6d0SRichard Tran Mills    Level: advanced
5458339e6d0SRichard Tran Mills 
546db781477SPatrick Sanan .seealso: `DMShellSetGlobalToLocal()`
5478339e6d0SRichard Tran Mills @*/
5489371c9d4SSatish Balay PetscErrorCode DMShellSetLocalToGlobal(DM dm, PetscErrorCode (*begin)(DM, Vec, InsertMode, Vec), PetscErrorCode (*end)(DM, Vec, InsertMode, Vec)) {
5498339e6d0SRichard Tran Mills   PetscFunctionBegin;
5502d1bcd87SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5518339e6d0SRichard Tran Mills   dm->ops->localtoglobalbegin = begin;
5528339e6d0SRichard Tran Mills   dm->ops->localtoglobalend   = end;
5538339e6d0SRichard Tran Mills   PetscFunctionReturn(0);
5548339e6d0SRichard Tran Mills }
5558339e6d0SRichard Tran Mills 
556f3db62a7SRichard Tran Mills /*@C
557f3db62a7SRichard Tran Mills    DMShellSetLocalToLocal - Sets the routines used to perform a local to local scatter
558f3db62a7SRichard Tran Mills 
559d083f849SBarry Smith    Logically Collective on dm
560f3db62a7SRichard Tran Mills 
5614165533cSJose E. Roman    Input Parameters
562f3db62a7SRichard Tran Mills +  dm - the shell DM
563f3db62a7SRichard Tran Mills .  begin - the routine that begins the local to local scatter
564f3db62a7SRichard Tran Mills -  end - the routine that ends the local to local scatter
565f3db62a7SRichard Tran Mills 
56695452b02SPatrick Sanan    Notes:
56795452b02SPatrick Sanan     If these functions are not provided but DMShellSetLocalToLocalVecScatter() is called then
568f3db62a7SRichard Tran Mills    DMLocalToLocalBeginDefaultShell()/DMLocalToLocalEndDefaultShell() are used to to perform the transfers
569f3db62a7SRichard Tran Mills 
570f3db62a7SRichard Tran Mills    Level: advanced
571f3db62a7SRichard Tran Mills 
572db781477SPatrick Sanan .seealso: `DMShellSetGlobalToLocal()`, `DMLocalToLocalBeginDefaultShell()`, `DMLocalToLocalEndDefaultShell()`
573f3db62a7SRichard Tran Mills @*/
5749371c9d4SSatish Balay PetscErrorCode DMShellSetLocalToLocal(DM dm, PetscErrorCode (*begin)(DM, Vec, InsertMode, Vec), PetscErrorCode (*end)(DM, Vec, InsertMode, Vec)) {
575f3db62a7SRichard Tran Mills   PetscFunctionBegin;
5762d1bcd87SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
577f3db62a7SRichard Tran Mills   dm->ops->localtolocalbegin = begin;
578f3db62a7SRichard Tran Mills   dm->ops->localtolocalend   = end;
579f3db62a7SRichard Tran Mills   PetscFunctionReturn(0);
580f3db62a7SRichard Tran Mills }
581f3db62a7SRichard Tran Mills 
58281634712SRichard Tran Mills /*@
58381634712SRichard Tran Mills    DMShellSetGlobalToLocalVecScatter - Sets a VecScatter context for global to local communication
58481634712SRichard Tran Mills 
585d083f849SBarry Smith    Logically Collective on dm
58681634712SRichard Tran Mills 
5874165533cSJose E. Roman    Input Parameters
58881634712SRichard Tran Mills +  dm - the shell DM
58981634712SRichard Tran Mills -  gtol - the global to local VecScatter context
59081634712SRichard Tran Mills 
59181634712SRichard Tran Mills    Level: advanced
59281634712SRichard Tran Mills 
593db781477SPatrick Sanan .seealso: `DMShellSetGlobalToLocal()`, `DMGlobalToLocalBeginDefaultShell()`, `DMGlobalToLocalEndDefaultShell()`
59481634712SRichard Tran Mills @*/
5959371c9d4SSatish Balay PetscErrorCode DMShellSetGlobalToLocalVecScatter(DM dm, VecScatter gtol) {
59681634712SRichard Tran Mills   DM_Shell *shell = (DM_Shell *)dm->data;
59781634712SRichard Tran Mills 
598b300e4a8SRichard Tran Mills   PetscFunctionBegin;
5992d1bcd87SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
60097929ea7SJunchao Zhang   PetscValidHeaderSpecific(gtol, PETSCSF_CLASSID, 2);
6019566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)gtol));
6029566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&shell->gtol));
60381634712SRichard Tran Mills   shell->gtol = gtol;
60481634712SRichard Tran Mills   PetscFunctionReturn(0);
60581634712SRichard Tran Mills }
60681634712SRichard Tran Mills 
607988ea7d6SRichard Tran Mills /*@
608988ea7d6SRichard Tran Mills    DMShellSetLocalToGlobalVecScatter - Sets a VecScatter context for local to global communication
609988ea7d6SRichard Tran Mills 
610d083f849SBarry Smith    Logically Collective on dm
611988ea7d6SRichard Tran Mills 
6124165533cSJose E. Roman    Input Parameters
613988ea7d6SRichard Tran Mills +  dm - the shell DM
614988ea7d6SRichard Tran Mills -  ltog - the local to global VecScatter context
615988ea7d6SRichard Tran Mills 
616988ea7d6SRichard Tran Mills    Level: advanced
617988ea7d6SRichard Tran Mills 
618db781477SPatrick Sanan .seealso: `DMShellSetLocalToGlobal()`, `DMLocalToGlobalBeginDefaultShell()`, `DMLocalToGlobalEndDefaultShell()`
619988ea7d6SRichard Tran Mills @*/
6209371c9d4SSatish Balay PetscErrorCode DMShellSetLocalToGlobalVecScatter(DM dm, VecScatter ltog) {
621988ea7d6SRichard Tran Mills   DM_Shell *shell = (DM_Shell *)dm->data;
622988ea7d6SRichard Tran Mills 
623988ea7d6SRichard Tran Mills   PetscFunctionBegin;
6242d1bcd87SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
62597929ea7SJunchao Zhang   PetscValidHeaderSpecific(ltog, PETSCSF_CLASSID, 2);
6269566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ltog));
6279566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&shell->ltog));
628988ea7d6SRichard Tran Mills   shell->ltog = ltog;
629988ea7d6SRichard Tran Mills   PetscFunctionReturn(0);
630988ea7d6SRichard Tran Mills }
631988ea7d6SRichard Tran Mills 
632f3db62a7SRichard Tran Mills /*@
633f3db62a7SRichard Tran Mills    DMShellSetLocalToLocalVecScatter - Sets a VecScatter context for local to local communication
634f3db62a7SRichard Tran Mills 
635d083f849SBarry Smith    Logically Collective on dm
636f3db62a7SRichard Tran Mills 
6374165533cSJose E. Roman    Input Parameters
638f3db62a7SRichard Tran Mills +  dm - the shell DM
639f3db62a7SRichard Tran Mills -  ltol - the local to local VecScatter context
640f3db62a7SRichard Tran Mills 
641f3db62a7SRichard Tran Mills    Level: advanced
642f3db62a7SRichard Tran Mills 
643db781477SPatrick Sanan .seealso: `DMShellSetLocalToLocal()`, `DMLocalToLocalBeginDefaultShell()`, `DMLocalToLocalEndDefaultShell()`
644f3db62a7SRichard Tran Mills @*/
6459371c9d4SSatish Balay PetscErrorCode DMShellSetLocalToLocalVecScatter(DM dm, VecScatter ltol) {
646f3db62a7SRichard Tran Mills   DM_Shell *shell = (DM_Shell *)dm->data;
647f3db62a7SRichard Tran Mills 
648f3db62a7SRichard Tran Mills   PetscFunctionBegin;
6492d1bcd87SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
65097929ea7SJunchao Zhang   PetscValidHeaderSpecific(ltol, PETSCSF_CLASSID, 2);
6519566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ltol));
6529566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&shell->ltol));
653f3db62a7SRichard Tran Mills   shell->ltol = ltol;
654f3db62a7SRichard Tran Mills   PetscFunctionReturn(0);
655f3db62a7SRichard Tran Mills }
656f3db62a7SRichard Tran Mills 
6579bf9660cSLawrence Mitchell /*@C
6589bf9660cSLawrence Mitchell    DMShellSetCoarsen - Set the routine used to coarsen the shell DM
6599bf9660cSLawrence Mitchell 
660d083f849SBarry Smith    Logically Collective on dm
6619bf9660cSLawrence Mitchell 
6624165533cSJose E. Roman    Input Parameters
6639bf9660cSLawrence Mitchell +  dm - the shell DM
6649bf9660cSLawrence Mitchell -  coarsen - the routine that coarsens the DM
6659bf9660cSLawrence Mitchell 
6669bf9660cSLawrence Mitchell    Level: advanced
6679bf9660cSLawrence Mitchell 
668db781477SPatrick Sanan .seealso: `DMShellSetRefine()`, `DMCoarsen()`, `DMShellGetCoarsen()`, `DMShellSetContext()`, `DMShellGetContext()`
6699bf9660cSLawrence Mitchell @*/
6709371c9d4SSatish Balay PetscErrorCode DMShellSetCoarsen(DM dm, PetscErrorCode (*coarsen)(DM, MPI_Comm, DM *)) {
671f572501eSLawrence Mitchell   PetscBool isshell;
672f572501eSLawrence Mitchell 
673f572501eSLawrence Mitchell   PetscFunctionBegin;
674f572501eSLawrence Mitchell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6759566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
676f572501eSLawrence Mitchell   if (!isshell) PetscFunctionReturn(0);
677f572501eSLawrence Mitchell   dm->ops->coarsen = coarsen;
678f572501eSLawrence Mitchell   PetscFunctionReturn(0);
679f572501eSLawrence Mitchell }
680f572501eSLawrence Mitchell 
6819bf9660cSLawrence Mitchell /*@C
6824363ddcaSBoris Boutkov    DMShellGetCoarsen - Get the routine used to coarsen the shell DM
6834363ddcaSBoris Boutkov 
684d083f849SBarry Smith    Logically Collective on dm
6854363ddcaSBoris Boutkov 
6864165533cSJose E. Roman    Input Parameter:
6874363ddcaSBoris Boutkov .  dm - the shell DM
6884363ddcaSBoris Boutkov 
6894165533cSJose E. Roman    Output Parameter:
6904363ddcaSBoris Boutkov .  coarsen - the routine that coarsens the DM
6914363ddcaSBoris Boutkov 
6924363ddcaSBoris Boutkov    Level: advanced
6934363ddcaSBoris Boutkov 
694db781477SPatrick Sanan .seealso: `DMShellSetCoarsen()`, `DMCoarsen()`, `DMShellSetRefine()`, `DMRefine()`
6954363ddcaSBoris Boutkov @*/
6969371c9d4SSatish Balay PetscErrorCode DMShellGetCoarsen(DM dm, PetscErrorCode (**coarsen)(DM, MPI_Comm, DM *)) {
6974363ddcaSBoris Boutkov   PetscBool isshell;
6984363ddcaSBoris Boutkov 
6994363ddcaSBoris Boutkov   PetscFunctionBegin;
7004363ddcaSBoris Boutkov   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
7027a8be351SBarry Smith   PetscCheck(isshell, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Can only use with DMSHELL type DMs");
7034363ddcaSBoris Boutkov   *coarsen = dm->ops->coarsen;
7044363ddcaSBoris Boutkov   PetscFunctionReturn(0);
7054363ddcaSBoris Boutkov }
7064363ddcaSBoris Boutkov 
7074363ddcaSBoris Boutkov /*@C
7089bf9660cSLawrence Mitchell    DMShellSetRefine - Set the routine used to refine the shell DM
7099bf9660cSLawrence Mitchell 
710d083f849SBarry Smith    Logically Collective on dm
7119bf9660cSLawrence Mitchell 
7124165533cSJose E. Roman    Input Parameters
7139bf9660cSLawrence Mitchell +  dm - the shell DM
7149bf9660cSLawrence Mitchell -  refine - the routine that refines the DM
7159bf9660cSLawrence Mitchell 
7169bf9660cSLawrence Mitchell    Level: advanced
7179bf9660cSLawrence Mitchell 
718db781477SPatrick Sanan .seealso: `DMShellSetCoarsen()`, `DMRefine()`, `DMShellGetRefine()`, `DMShellSetContext()`, `DMShellGetContext()`
7199bf9660cSLawrence Mitchell @*/
7209371c9d4SSatish Balay PetscErrorCode DMShellSetRefine(DM dm, PetscErrorCode (*refine)(DM, MPI_Comm, DM *)) {
721f572501eSLawrence Mitchell   PetscBool isshell;
722f572501eSLawrence Mitchell 
723f572501eSLawrence Mitchell   PetscFunctionBegin;
724f572501eSLawrence Mitchell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7259566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
726f572501eSLawrence Mitchell   if (!isshell) PetscFunctionReturn(0);
727f572501eSLawrence Mitchell   dm->ops->refine = refine;
728f572501eSLawrence Mitchell   PetscFunctionReturn(0);
729f572501eSLawrence Mitchell }
730f572501eSLawrence Mitchell 
7319bf9660cSLawrence Mitchell /*@C
7324363ddcaSBoris Boutkov    DMShellGetRefine - Get the routine used to refine the shell DM
7334363ddcaSBoris Boutkov 
734d083f849SBarry Smith    Logically Collective on dm
7354363ddcaSBoris Boutkov 
7364165533cSJose E. Roman    Input Parameter:
7374363ddcaSBoris Boutkov .  dm - the shell DM
7384363ddcaSBoris Boutkov 
7394165533cSJose E. Roman    Output Parameter:
7404363ddcaSBoris Boutkov .  refine - the routine that refines the DM
7414363ddcaSBoris Boutkov 
7424363ddcaSBoris Boutkov    Level: advanced
7434363ddcaSBoris Boutkov 
744db781477SPatrick Sanan .seealso: `DMShellSetCoarsen()`, `DMCoarsen()`, `DMShellSetRefine()`, `DMRefine()`
7454363ddcaSBoris Boutkov @*/
7469371c9d4SSatish Balay PetscErrorCode DMShellGetRefine(DM dm, PetscErrorCode (**refine)(DM, MPI_Comm, DM *)) {
7474363ddcaSBoris Boutkov   PetscBool isshell;
7484363ddcaSBoris Boutkov 
7494363ddcaSBoris Boutkov   PetscFunctionBegin;
7504363ddcaSBoris Boutkov   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7519566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
7527a8be351SBarry Smith   PetscCheck(isshell, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Can only use with DMSHELL type DMs");
7534363ddcaSBoris Boutkov   *refine = dm->ops->refine;
7544363ddcaSBoris Boutkov   PetscFunctionReturn(0);
7554363ddcaSBoris Boutkov }
7564363ddcaSBoris Boutkov 
7574363ddcaSBoris Boutkov /*@C
7589bf9660cSLawrence Mitchell    DMShellSetCreateInterpolation - Set the routine used to create the interpolation operator
7599bf9660cSLawrence Mitchell 
760d083f849SBarry Smith    Logically Collective on dm
7619bf9660cSLawrence Mitchell 
7624165533cSJose E. Roman    Input Parameters
7639bf9660cSLawrence Mitchell +  dm - the shell DM
7649bf9660cSLawrence Mitchell -  interp - the routine to create the interpolation
7659bf9660cSLawrence Mitchell 
7669bf9660cSLawrence Mitchell    Level: advanced
7679bf9660cSLawrence Mitchell 
768db781477SPatrick Sanan .seealso: `DMShellSetCreateInjection()`, `DMCreateInterpolation()`, `DMShellGetCreateInterpolation()`, `DMShellSetCreateRestriction()`, `DMShellSetContext()`, `DMShellGetContext()`
7699bf9660cSLawrence Mitchell @*/
7709371c9d4SSatish Balay PetscErrorCode DMShellSetCreateInterpolation(DM dm, PetscErrorCode (*interp)(DM, DM, Mat *, Vec *)) {
771f572501eSLawrence Mitchell   PetscBool isshell;
772f572501eSLawrence Mitchell 
773f572501eSLawrence Mitchell   PetscFunctionBegin;
774f572501eSLawrence Mitchell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7759566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
776f572501eSLawrence Mitchell   if (!isshell) PetscFunctionReturn(0);
777f572501eSLawrence Mitchell   dm->ops->createinterpolation = interp;
778f572501eSLawrence Mitchell   PetscFunctionReturn(0);
779f572501eSLawrence Mitchell }
780f572501eSLawrence Mitchell 
7813ad4599aSBarry Smith /*@C
7824363ddcaSBoris Boutkov    DMShellGetCreateInterpolation - Get the routine used to create the interpolation operator
7834363ddcaSBoris Boutkov 
784d083f849SBarry Smith    Logically Collective on dm
7854363ddcaSBoris Boutkov 
7864165533cSJose E. Roman    Input Parameter:
7874165533cSJose E. Roman .  dm - the shell DM
788a4a986ddSBoris Boutkov 
7894165533cSJose E. Roman    Output Parameter:
7904165533cSJose E. Roman .  interp - the routine to create the interpolation
7914363ddcaSBoris Boutkov 
7924363ddcaSBoris Boutkov    Level: advanced
7934363ddcaSBoris Boutkov 
794db781477SPatrick Sanan .seealso: `DMShellGetCreateInjection()`, `DMCreateInterpolation()`, `DMShellGetCreateRestriction()`, `DMShellSetContext()`, `DMShellGetContext()`
7954363ddcaSBoris Boutkov @*/
7969371c9d4SSatish Balay PetscErrorCode DMShellGetCreateInterpolation(DM dm, PetscErrorCode (**interp)(DM, DM, Mat *, Vec *)) {
7974363ddcaSBoris Boutkov   PetscBool isshell;
7984363ddcaSBoris Boutkov 
7994363ddcaSBoris Boutkov   PetscFunctionBegin;
8004363ddcaSBoris Boutkov   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
8027a8be351SBarry Smith   PetscCheck(isshell, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Can only use with DMSHELL type DMs");
8034363ddcaSBoris Boutkov   *interp = dm->ops->createinterpolation;
8044363ddcaSBoris Boutkov   PetscFunctionReturn(0);
8054363ddcaSBoris Boutkov }
8064363ddcaSBoris Boutkov 
8074363ddcaSBoris Boutkov /*@C
8083ad4599aSBarry Smith    DMShellSetCreateRestriction - Set the routine used to create the restriction operator
8093ad4599aSBarry Smith 
810d083f849SBarry Smith    Logically Collective on dm
8113ad4599aSBarry Smith 
8124165533cSJose E. Roman    Input Parameters
8133ad4599aSBarry Smith +  dm - the shell DM
8143ad4599aSBarry Smith -  striction- the routine to create the restriction
8153ad4599aSBarry Smith 
8163ad4599aSBarry Smith    Level: advanced
8173ad4599aSBarry Smith 
818db781477SPatrick Sanan .seealso: `DMShellSetCreateInjection()`, `DMCreateInterpolation()`, `DMShellGetCreateRestriction()`, `DMShellSetContext()`, `DMShellGetContext()`
8193ad4599aSBarry Smith @*/
8209371c9d4SSatish Balay PetscErrorCode DMShellSetCreateRestriction(DM dm, PetscErrorCode (*restriction)(DM, DM, Mat *)) {
8213ad4599aSBarry Smith   PetscBool isshell;
8223ad4599aSBarry Smith 
8233ad4599aSBarry Smith   PetscFunctionBegin;
8243ad4599aSBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8259566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
8263ad4599aSBarry Smith   if (!isshell) PetscFunctionReturn(0);
8273ad4599aSBarry Smith   dm->ops->createrestriction = restriction;
8283ad4599aSBarry Smith   PetscFunctionReturn(0);
8293ad4599aSBarry Smith }
8303ad4599aSBarry Smith 
8319bf9660cSLawrence Mitchell /*@C
8324363ddcaSBoris Boutkov    DMShellGetCreateRestriction - Get the routine used to create the restriction operator
8334363ddcaSBoris Boutkov 
834d083f849SBarry Smith    Logically Collective on dm
8354363ddcaSBoris Boutkov 
8364165533cSJose E. Roman    Input Parameter:
8374165533cSJose E. Roman .  dm - the shell DM
838a4a986ddSBoris Boutkov 
8394165533cSJose E. Roman    Output Parameter:
8404165533cSJose E. Roman .  restriction - the routine to create the restriction
8414363ddcaSBoris Boutkov 
8424363ddcaSBoris Boutkov    Level: advanced
8434363ddcaSBoris Boutkov 
844db781477SPatrick Sanan .seealso: `DMShellSetCreateInjection()`, `DMCreateInterpolation()`, `DMShellSetContext()`, `DMShellGetContext()`
8454363ddcaSBoris Boutkov @*/
8469371c9d4SSatish Balay PetscErrorCode DMShellGetCreateRestriction(DM dm, PetscErrorCode (**restriction)(DM, DM, Mat *)) {
8474363ddcaSBoris Boutkov   PetscBool isshell;
8484363ddcaSBoris Boutkov 
8494363ddcaSBoris Boutkov   PetscFunctionBegin;
8504363ddcaSBoris Boutkov   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8519566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
8527a8be351SBarry Smith   PetscCheck(isshell, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Can only use with DMSHELL type DMs");
8534363ddcaSBoris Boutkov   *restriction = dm->ops->createrestriction;
8544363ddcaSBoris Boutkov   PetscFunctionReturn(0);
8554363ddcaSBoris Boutkov }
8564363ddcaSBoris Boutkov 
8574363ddcaSBoris Boutkov /*@C
8589bf9660cSLawrence Mitchell    DMShellSetCreateInjection - Set the routine used to create the injection operator
8599bf9660cSLawrence Mitchell 
860d083f849SBarry Smith    Logically Collective on dm
8619bf9660cSLawrence Mitchell 
8624165533cSJose E. Roman    Input Parameters:
8639bf9660cSLawrence Mitchell +  dm - the shell DM
8649bf9660cSLawrence Mitchell -  inject - the routine to create the injection
8659bf9660cSLawrence Mitchell 
8669bf9660cSLawrence Mitchell    Level: advanced
8679bf9660cSLawrence Mitchell 
868db781477SPatrick Sanan .seealso: `DMShellSetCreateInterpolation()`, `DMCreateInjection()`, `DMShellGetCreateInjection()`, `DMShellSetContext()`, `DMShellGetContext()`
8699bf9660cSLawrence Mitchell @*/
8709371c9d4SSatish Balay PetscErrorCode DMShellSetCreateInjection(DM dm, PetscErrorCode (*inject)(DM, DM, Mat *)) {
871f572501eSLawrence Mitchell   PetscBool isshell;
872f572501eSLawrence Mitchell 
873f572501eSLawrence Mitchell   PetscFunctionBegin;
874f572501eSLawrence Mitchell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8759566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
876f572501eSLawrence Mitchell   if (!isshell) PetscFunctionReturn(0);
8775a84ad33SLisandro Dalcin   dm->ops->createinjection = inject;
878f572501eSLawrence Mitchell   PetscFunctionReturn(0);
879f572501eSLawrence Mitchell }
880f572501eSLawrence Mitchell 
8814363ddcaSBoris Boutkov /*@C
8824363ddcaSBoris Boutkov    DMShellGetCreateInjection - Get the routine used to create the injection operator
8834363ddcaSBoris Boutkov 
884d083f849SBarry Smith    Logically Collective on dm
8854363ddcaSBoris Boutkov 
8864165533cSJose E. Roman    Input Parameter:
8874165533cSJose E. Roman .  dm - the shell DM
888a4a986ddSBoris Boutkov 
8894165533cSJose E. Roman    Output Parameter:
8904165533cSJose E. Roman .  inject - the routine to create the injection
8914363ddcaSBoris Boutkov 
8924363ddcaSBoris Boutkov    Level: advanced
8934363ddcaSBoris Boutkov 
894db781477SPatrick Sanan .seealso: `DMShellGetCreateInterpolation()`, `DMCreateInjection()`, `DMShellSetContext()`, `DMShellGetContext()`
8954363ddcaSBoris Boutkov @*/
8969371c9d4SSatish Balay PetscErrorCode DMShellGetCreateInjection(DM dm, PetscErrorCode (**inject)(DM, DM, Mat *)) {
8974363ddcaSBoris Boutkov   PetscBool isshell;
8984363ddcaSBoris Boutkov 
8994363ddcaSBoris Boutkov   PetscFunctionBegin;
9004363ddcaSBoris Boutkov   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
9027a8be351SBarry Smith   PetscCheck(isshell, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Can only use with DMSHELL type DMs");
9035a84ad33SLisandro Dalcin   *inject = dm->ops->createinjection;
9044363ddcaSBoris Boutkov   PetscFunctionReturn(0);
9054363ddcaSBoris Boutkov }
9064363ddcaSBoris Boutkov 
9079bf9660cSLawrence Mitchell /*@C
9089bf9660cSLawrence Mitchell    DMShellSetCreateFieldDecomposition - Set the routine used to create a decomposition of fields for the shell DM
9099bf9660cSLawrence Mitchell 
910d083f849SBarry Smith    Logically Collective on dm
9119bf9660cSLawrence Mitchell 
9124165533cSJose E. Roman    Input Parameters:
9139bf9660cSLawrence Mitchell +  dm - the shell DM
9149bf9660cSLawrence Mitchell -  decomp - the routine to create the decomposition
9159bf9660cSLawrence Mitchell 
9169bf9660cSLawrence Mitchell    Level: advanced
9179bf9660cSLawrence Mitchell 
918db781477SPatrick Sanan .seealso: `DMCreateFieldDecomposition()`, `DMShellSetContext()`, `DMShellGetContext()`
9199bf9660cSLawrence Mitchell @*/
9209371c9d4SSatish Balay PetscErrorCode DMShellSetCreateFieldDecomposition(DM dm, PetscErrorCode (*decomp)(DM, PetscInt *, char ***, IS **, DM **)) {
9215e2259d5SLawrence Mitchell   PetscBool isshell;
9225e2259d5SLawrence Mitchell 
9235e2259d5SLawrence Mitchell   PetscFunctionBegin;
9245e2259d5SLawrence Mitchell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9259566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
9265e2259d5SLawrence Mitchell   if (!isshell) PetscFunctionReturn(0);
9275e2259d5SLawrence Mitchell   dm->ops->createfielddecomposition = decomp;
9285e2259d5SLawrence Mitchell   PetscFunctionReturn(0);
9295e2259d5SLawrence Mitchell }
9305e2259d5SLawrence Mitchell 
931c00061e5SLawrence Mitchell /*@C
932e734121bSPatrick Farrell    DMShellSetCreateDomainDecomposition - Set the routine used to create a domain decomposition for the shell DM
933e734121bSPatrick Farrell 
934d083f849SBarry Smith    Logically Collective on dm
935e734121bSPatrick Farrell 
9364165533cSJose E. Roman    Input Parameters:
937e734121bSPatrick Farrell +  dm - the shell DM
938e734121bSPatrick Farrell -  decomp - the routine to create the decomposition
939e734121bSPatrick Farrell 
940e734121bSPatrick Farrell    Level: advanced
941e734121bSPatrick Farrell 
942db781477SPatrick Sanan .seealso: `DMCreateDomainDecomposition()`, `DMShellSetContext()`, `DMShellGetContext()`
943e734121bSPatrick Farrell @*/
9449371c9d4SSatish Balay PetscErrorCode DMShellSetCreateDomainDecomposition(DM dm, PetscErrorCode (*decomp)(DM, PetscInt *, char ***, IS **, IS **, DM **)) {
945e734121bSPatrick Farrell   PetscBool isshell;
946e734121bSPatrick Farrell 
947e734121bSPatrick Farrell   PetscFunctionBegin;
948e734121bSPatrick Farrell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9499566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
950e734121bSPatrick Farrell   if (!isshell) PetscFunctionReturn(0);
951e734121bSPatrick Farrell   dm->ops->createdomaindecomposition = decomp;
952e734121bSPatrick Farrell   PetscFunctionReturn(0);
953e734121bSPatrick Farrell }
954e734121bSPatrick Farrell 
955e734121bSPatrick Farrell /*@C
956eef9d6cdSPatrick Farrell    DMShellSetCreateDomainDecompositionScatters - Set the routine used to create the scatter contexts for domain decomposition with a shell DM
957eef9d6cdSPatrick Farrell 
958d083f849SBarry Smith    Logically Collective on dm
959eef9d6cdSPatrick Farrell 
9604165533cSJose E. Roman    Input Parameters:
961eef9d6cdSPatrick Farrell +  dm - the shell DM
962eef9d6cdSPatrick Farrell -  scatter - the routine to create the scatters
963eef9d6cdSPatrick Farrell 
964eef9d6cdSPatrick Farrell    Level: advanced
965eef9d6cdSPatrick Farrell 
966db781477SPatrick Sanan .seealso: `DMCreateDomainDecompositionScatters()`, `DMShellSetContext()`, `DMShellGetContext()`
967eef9d6cdSPatrick Farrell @*/
9689371c9d4SSatish Balay PetscErrorCode DMShellSetCreateDomainDecompositionScatters(DM dm, PetscErrorCode (*scatter)(DM, PetscInt, DM *, VecScatter **, VecScatter **, VecScatter **)) {
969eef9d6cdSPatrick Farrell   PetscBool isshell;
970eef9d6cdSPatrick Farrell 
971eef9d6cdSPatrick Farrell   PetscFunctionBegin;
972eef9d6cdSPatrick Farrell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9739566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
974eef9d6cdSPatrick Farrell   if (!isshell) PetscFunctionReturn(0);
975eef9d6cdSPatrick Farrell   dm->ops->createddscatters = scatter;
976eef9d6cdSPatrick Farrell   PetscFunctionReturn(0);
977eef9d6cdSPatrick Farrell }
978eef9d6cdSPatrick Farrell 
979eef9d6cdSPatrick Farrell /*@C
980c00061e5SLawrence Mitchell    DMShellSetCreateSubDM - Set the routine used to create a sub DM from the shell DM
981c00061e5SLawrence Mitchell 
982d083f849SBarry Smith    Logically Collective on dm
983c00061e5SLawrence Mitchell 
9844165533cSJose E. Roman    Input Parameters:
985c00061e5SLawrence Mitchell +  dm - the shell DM
986c00061e5SLawrence Mitchell -  subdm - the routine to create the decomposition
987c00061e5SLawrence Mitchell 
988c00061e5SLawrence Mitchell    Level: advanced
989c00061e5SLawrence Mitchell 
990db781477SPatrick Sanan .seealso: `DMCreateSubDM()`, `DMShellGetCreateSubDM()`, `DMShellSetContext()`, `DMShellGetContext()`
991c00061e5SLawrence Mitchell @*/
9929371c9d4SSatish Balay PetscErrorCode DMShellSetCreateSubDM(DM dm, PetscErrorCode (*subdm)(DM, PetscInt, const PetscInt[], IS *, DM *)) {
993c00061e5SLawrence Mitchell   PetscBool isshell;
994c00061e5SLawrence Mitchell 
995c00061e5SLawrence Mitchell   PetscFunctionBegin;
996c00061e5SLawrence Mitchell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9979566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
998c00061e5SLawrence Mitchell   if (!isshell) PetscFunctionReturn(0);
999c00061e5SLawrence Mitchell   dm->ops->createsubdm = subdm;
1000c00061e5SLawrence Mitchell   PetscFunctionReturn(0);
1001c00061e5SLawrence Mitchell }
1002c00061e5SLawrence Mitchell 
10034363ddcaSBoris Boutkov /*@C
10044363ddcaSBoris Boutkov    DMShellGetCreateSubDM - Get the routine used to create a sub DM from the shell DM
10054363ddcaSBoris Boutkov 
1006d083f849SBarry Smith    Logically Collective on dm
10074363ddcaSBoris Boutkov 
10084165533cSJose E. Roman    Input Parameter:
10094165533cSJose E. Roman .  dm - the shell DM
1010a4a986ddSBoris Boutkov 
10114165533cSJose E. Roman    Output Parameter:
10124165533cSJose E. Roman .  subdm - the routine to create the decomposition
10134363ddcaSBoris Boutkov 
10144363ddcaSBoris Boutkov    Level: advanced
10154363ddcaSBoris Boutkov 
1016db781477SPatrick Sanan .seealso: `DMCreateSubDM()`, `DMShellSetCreateSubDM()`, `DMShellSetContext()`, `DMShellGetContext()`
10174363ddcaSBoris Boutkov @*/
10189371c9d4SSatish Balay PetscErrorCode DMShellGetCreateSubDM(DM dm, PetscErrorCode (**subdm)(DM, PetscInt, const PetscInt[], IS *, DM *)) {
10194363ddcaSBoris Boutkov   PetscBool isshell;
10204363ddcaSBoris Boutkov 
10214363ddcaSBoris Boutkov   PetscFunctionBegin;
10224363ddcaSBoris Boutkov   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10239566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
10247a8be351SBarry Smith   PetscCheck(isshell, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Can only use with DMSHELL type DMs");
10254363ddcaSBoris Boutkov   *subdm = dm->ops->createsubdm;
10264363ddcaSBoris Boutkov   PetscFunctionReturn(0);
10274363ddcaSBoris Boutkov }
10284363ddcaSBoris Boutkov 
10299371c9d4SSatish Balay static PetscErrorCode DMDestroy_Shell(DM dm) {
1030fe1899a2SJed Brown   DM_Shell *shell = (DM_Shell *)dm->data;
1031fe1899a2SJed Brown 
1032fe1899a2SJed Brown   PetscFunctionBegin;
103309904cd0SBarry Smith   if (shell->destroyctx) PetscCallBack("Destroy Context", (*shell->destroyctx)(shell->ctx));
10349566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&shell->A));
10359566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&shell->Xglobal));
10369566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&shell->Xlocal));
10379566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&shell->gtol));
10389566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&shell->ltog));
10399566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&shell->ltol));
10407b6ad80cSMatthew G Knepley   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
10419566063dSJacob Faibussowitsch   PetscCall(PetscFree(shell));
1042fe1899a2SJed Brown   PetscFunctionReturn(0);
1043fe1899a2SJed Brown }
1044fe1899a2SJed Brown 
10459371c9d4SSatish Balay static PetscErrorCode DMView_Shell(DM dm, PetscViewer v) {
10462d53ad75SBarry Smith   DM_Shell *shell = (DM_Shell *)dm->data;
10472d53ad75SBarry Smith 
10482d53ad75SBarry Smith   PetscFunctionBegin;
104901f8681bSStefano Zampini   if (shell->Xglobal) PetscCall(VecView(shell->Xglobal, v));
10502d53ad75SBarry Smith   PetscFunctionReturn(0);
10512d53ad75SBarry Smith }
10522d53ad75SBarry Smith 
10539371c9d4SSatish Balay static PetscErrorCode DMLoad_Shell(DM dm, PetscViewer v) {
10542d53ad75SBarry Smith   DM_Shell *shell = (DM_Shell *)dm->data;
10552d53ad75SBarry Smith 
10562d53ad75SBarry Smith   PetscFunctionBegin;
10579566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &shell->Xglobal));
10589566063dSJacob Faibussowitsch   PetscCall(VecLoad(shell->Xglobal, v));
10592d53ad75SBarry Smith   PetscFunctionReturn(0);
10602d53ad75SBarry Smith }
1061fe1899a2SJed Brown 
10629371c9d4SSatish Balay PetscErrorCode DMCreateSubDM_Shell(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) {
10636e44b4cfSMatthew G. Knepley   PetscFunctionBegin;
10649566063dSJacob Faibussowitsch   if (subdm) PetscCall(DMShellCreate(PetscObjectComm((PetscObject)dm), subdm));
10659566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm));
10666e44b4cfSMatthew G. Knepley   PetscFunctionReturn(0);
10676e44b4cfSMatthew G. Knepley }
10686e44b4cfSMatthew G. Knepley 
10699371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode DMCreate_Shell(DM dm) {
1070fe1899a2SJed Brown   DM_Shell *shell;
1071fe1899a2SJed Brown 
1072fe1899a2SJed Brown   PetscFunctionBegin;
1073*4dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&shell));
10748c87107bSJed Brown   dm->data = shell;
1075fe1899a2SJed Brown 
10768c87107bSJed Brown   dm->ops->destroy            = DMDestroy_Shell;
10778c87107bSJed Brown   dm->ops->createglobalvector = DMCreateGlobalVector_Shell;
1078dc43b69eSJed Brown   dm->ops->createlocalvector  = DMCreateLocalVector_Shell;
10798c87107bSJed Brown   dm->ops->creatematrix       = DMCreateMatrix_Shell;
10802d53ad75SBarry Smith   dm->ops->view               = DMView_Shell;
10812d53ad75SBarry Smith   dm->ops->load               = DMLoad_Shell;
10827a108d1dSBarry Smith   dm->ops->globaltolocalbegin = DMGlobalToLocalBeginDefaultShell;
10837a108d1dSBarry Smith   dm->ops->globaltolocalend   = DMGlobalToLocalEndDefaultShell;
108455daaa54SRichard Tran Mills   dm->ops->localtoglobalbegin = DMLocalToGlobalBeginDefaultShell;
108555daaa54SRichard Tran Mills   dm->ops->localtoglobalend   = DMLocalToGlobalEndDefaultShell;
108663731094SRichard Tran Mills   dm->ops->localtolocalbegin  = DMLocalToLocalBeginDefaultShell;
108763731094SRichard Tran Mills   dm->ops->localtolocalend    = DMLocalToLocalEndDefaultShell;
10886e44b4cfSMatthew G. Knepley   dm->ops->createsubdm        = DMCreateSubDM_Shell;
10899566063dSJacob Faibussowitsch   PetscCall(DMSetMatType(dm, MATDENSE));
1090fe1899a2SJed Brown   PetscFunctionReturn(0);
1091fe1899a2SJed Brown }
1092fe1899a2SJed Brown 
1093fe1899a2SJed Brown /*@
1094fe1899a2SJed Brown     DMShellCreate - Creates a shell DM object, used to manage user-defined problem data
1095fe1899a2SJed Brown 
1096d083f849SBarry Smith     Collective
1097fe1899a2SJed Brown 
1098fe1899a2SJed Brown     Input Parameter:
1099fe1899a2SJed Brown .   comm - the processors that will share the global vector
1100fe1899a2SJed Brown 
1101fe1899a2SJed Brown     Output Parameters:
1102fe1899a2SJed Brown .   shell - the shell DM
1103fe1899a2SJed Brown 
1104fe1899a2SJed Brown     Level: advanced
1105fe1899a2SJed Brown 
1106db781477SPatrick Sanan .seealso `DMDestroy()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`, `DMShellSetContext()`, `DMShellGetContext()`
1107fe1899a2SJed Brown @*/
11089371c9d4SSatish Balay PetscErrorCode DMShellCreate(MPI_Comm comm, DM *dm) {
1109fe1899a2SJed Brown   PetscFunctionBegin;
1110fe1899a2SJed Brown   PetscValidPointer(dm, 2);
11119566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
11129566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMSHELL));
11139566063dSJacob Faibussowitsch   PetscCall(DMSetUp(*dm));
1114fe1899a2SJed Brown   PetscFunctionReturn(0);
1115fe1899a2SJed Brown }
1116