xref: /petsc/src/dm/impls/shell/dmshell.c (revision 20f4b53cbb5e9bd9ef12b76a8697d60d197cda17)
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 /*@
17*20f4b53cSBarry Smith    DMGlobalToLocalBeginDefaultShell - Uses the GlobalToLocal `VecScatter` context set by the user to begin a global to local scatter
18*20f4b53cSBarry Smith 
198d359177SBarry Smith   Collective
208d359177SBarry Smith 
214165533cSJose E. Roman    Input Parameters:
22*20f4b53cSBarry Smith +  dm - `DMSHELL`
238d359177SBarry Smith .  g - global vector
24*20f4b53cSBarry Smith .  mode - `InsertMode`
258d359177SBarry Smith -  l - local vector
268d359177SBarry Smith 
277a108d1dSBarry Smith    Level: advanced
288d359177SBarry Smith 
29*20f4b53cSBarry Smith    Note:
30*20f4b53cSBarry Smith    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.
317a108d1dSBarry Smith 
32*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMGlobalToLocalEndDefaultShell()`
338d359177SBarry Smith @*/
34d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocalBeginDefaultShell(DM dm, Vec g, InsertMode mode, Vec l)
35d71ae5a4SJacob Faibussowitsch {
368d359177SBarry Smith   DM_Shell *shell = (DM_Shell *)dm->data;
378d359177SBarry Smith 
388d359177SBarry Smith   PetscFunctionBegin;
397a8be351SBarry Smith   PetscCheck(shell->gtol, ((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
409566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(shell->gtol, g, l, mode, SCATTER_FORWARD));
413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
428d359177SBarry Smith }
438d359177SBarry Smith 
447a108d1dSBarry Smith /*@
45*20f4b53cSBarry Smith    DMGlobalToLocalEndDefaultShell - Uses the GlobalToLocal `VecScatter` context set by the user to end a global to local scatter
468d359177SBarry Smith    Collective
478d359177SBarry Smith 
484165533cSJose E. Roman    Input Parameters:
49*20f4b53cSBarry Smith +  dm - `DMSHELL`
508d359177SBarry Smith .  g - global vector
51*20f4b53cSBarry Smith .  mode - `InsertMode`
528d359177SBarry Smith -  l - local vector
538d359177SBarry Smith 
547a108d1dSBarry Smith    Level: advanced
558d359177SBarry Smith 
56*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMGlobalToLocalBeginDefaultShell()`
578d359177SBarry Smith @*/
58d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocalEndDefaultShell(DM dm, Vec g, InsertMode mode, Vec l)
59d71ae5a4SJacob Faibussowitsch {
608d359177SBarry Smith   DM_Shell *shell = (DM_Shell *)dm->data;
618d359177SBarry Smith 
628d359177SBarry Smith   PetscFunctionBegin;
637a8be351SBarry Smith   PetscCheck(shell->gtol, ((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
649566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(shell->gtol, g, l, mode, SCATTER_FORWARD));
653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
668d359177SBarry Smith }
678d359177SBarry Smith 
68c5076b69SRichard Tran Mills /*@
69*20f4b53cSBarry Smith    DMLocalToGlobalBeginDefaultShell - Uses the LocalToGlobal `VecScatter` context set by the user to begin a local to global scatter
70c5076b69SRichard Tran Mills    Collective
71c5076b69SRichard Tran Mills 
724165533cSJose E. Roman    Input Parameters:
73*20f4b53cSBarry Smith +  dm - `DMSHELL`
74c5076b69SRichard Tran Mills .  l - local vector
75*20f4b53cSBarry Smith .  mode - `InsertMode`
76c5076b69SRichard Tran Mills -  g - global vector
77c5076b69SRichard Tran Mills 
78c5076b69SRichard Tran Mills    Level: advanced
79c5076b69SRichard Tran Mills 
80*20f4b53cSBarry Smith    Note:
81*20f4b53cSBarry Smith    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.
82c5076b69SRichard Tran Mills 
83*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMLocalToGlobalEndDefaultShell()`
84c5076b69SRichard Tran Mills @*/
85d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobalBeginDefaultShell(DM dm, Vec l, InsertMode mode, Vec g)
86d71ae5a4SJacob Faibussowitsch {
87c5076b69SRichard Tran Mills   DM_Shell *shell = (DM_Shell *)dm->data;
88c5076b69SRichard Tran Mills 
89c5076b69SRichard Tran Mills   PetscFunctionBegin;
907a8be351SBarry Smith   PetscCheck(shell->ltog, ((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()");
919566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(shell->ltog, l, g, mode, SCATTER_FORWARD));
923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
93c5076b69SRichard Tran Mills }
94c5076b69SRichard Tran Mills 
95c5076b69SRichard Tran Mills /*@
96*20f4b53cSBarry Smith    DMLocalToGlobalEndDefaultShell - Uses the LocalToGlobal `VecScatter` context set by the user to end a local to global scatter
97c5076b69SRichard Tran Mills    Collective
98c5076b69SRichard Tran Mills 
994165533cSJose E. Roman    Input Parameters:
100*20f4b53cSBarry Smith +  dm - `DMSHELL`
101c5076b69SRichard Tran Mills .  l - local vector
102*20f4b53cSBarry Smith .  mode - `InsertMode`
103c5076b69SRichard Tran Mills -  g - global vector
104c5076b69SRichard Tran Mills 
105c5076b69SRichard Tran Mills    Level: advanced
106c5076b69SRichard Tran Mills 
107*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMLocalToGlobalBeginDefaultShell()`
108c5076b69SRichard Tran Mills @*/
109d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobalEndDefaultShell(DM dm, Vec l, InsertMode mode, Vec g)
110d71ae5a4SJacob Faibussowitsch {
111c5076b69SRichard Tran Mills   DM_Shell *shell = (DM_Shell *)dm->data;
112c5076b69SRichard Tran Mills 
113c5076b69SRichard Tran Mills   PetscFunctionBegin;
1147a8be351SBarry Smith   PetscCheck(shell->ltog, ((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()");
1159566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(shell->ltog, l, g, mode, SCATTER_FORWARD));
1163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
117c5076b69SRichard Tran Mills }
118c5076b69SRichard Tran Mills 
119f3db62a7SRichard Tran Mills /*@
120*20f4b53cSBarry Smith    DMLocalToLocalBeginDefaultShell - Uses the LocalToLocal `VecScatter` context set by the user to begin a local to local scatter
121f3db62a7SRichard Tran Mills    Collective
122f3db62a7SRichard Tran Mills 
1234165533cSJose E. Roman    Input Parameters:
124*20f4b53cSBarry Smith +  dm - `DMSHELL`
125f3db62a7SRichard Tran Mills .  g - the original local vector
126*20f4b53cSBarry Smith -  mode - `InsertMode`
127f3db62a7SRichard Tran Mills 
128f3db62a7SRichard Tran Mills    Output Parameter:
129f3db62a7SRichard Tran Mills .  l  - the local vector with correct ghost values
130f3db62a7SRichard Tran Mills 
131f3db62a7SRichard Tran Mills    Level: advanced
132f3db62a7SRichard Tran Mills 
133*20f4b53cSBarry Smith    Note:
134*20f4b53cSBarry Smith    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.
135f3db62a7SRichard Tran Mills 
136*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMLocalToLocalEndDefaultShell()`
137f3db62a7SRichard Tran Mills @*/
138d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToLocalBeginDefaultShell(DM dm, Vec g, InsertMode mode, Vec l)
139d71ae5a4SJacob Faibussowitsch {
140f3db62a7SRichard Tran Mills   DM_Shell *shell = (DM_Shell *)dm->data;
141f3db62a7SRichard Tran Mills 
142f3db62a7SRichard Tran Mills   PetscFunctionBegin;
1437a8be351SBarry Smith   PetscCheck(shell->ltol, ((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToLocalVecScatter()");
1449566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(shell->ltol, g, l, mode, SCATTER_FORWARD));
1453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
146f3db62a7SRichard Tran Mills }
147f3db62a7SRichard Tran Mills 
148f3db62a7SRichard Tran Mills /*@
149*20f4b53cSBarry Smith    DMLocalToLocalEndDefaultShell - Uses the LocalToLocal `VecScatter` context set by the user to end a local to local scatter
150f3db62a7SRichard Tran Mills    Collective
151f3db62a7SRichard Tran Mills 
1524165533cSJose E. Roman    Input Parameters:
153*20f4b53cSBarry Smith +  dm - `DMSHELL`
154f3db62a7SRichard Tran Mills .  g - the original local vector
155*20f4b53cSBarry Smith -  mode - `InsertMode`
156f3db62a7SRichard Tran Mills 
157f3db62a7SRichard Tran Mills    Output Parameter:
158f3db62a7SRichard Tran Mills .  l  - the local vector with correct ghost values
159f3db62a7SRichard Tran Mills 
160f3db62a7SRichard Tran Mills    Level: advanced
161f3db62a7SRichard Tran Mills 
162*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMLocalToLocalBeginDefaultShell()`
163f3db62a7SRichard Tran Mills @*/
164d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToLocalEndDefaultShell(DM dm, Vec g, InsertMode mode, Vec l)
165d71ae5a4SJacob Faibussowitsch {
166f3db62a7SRichard Tran Mills   DM_Shell *shell = (DM_Shell *)dm->data;
167f3db62a7SRichard Tran Mills 
168f3db62a7SRichard Tran Mills   PetscFunctionBegin;
1697a8be351SBarry Smith   PetscCheck(shell->ltol, ((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
1709566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(shell->ltol, g, l, mode, SCATTER_FORWARD));
1713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
172f3db62a7SRichard Tran Mills }
173c5076b69SRichard Tran Mills 
174d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMatrix_Shell(DM dm, Mat *J)
175d71ae5a4SJacob Faibussowitsch {
176fe1899a2SJed Brown   DM_Shell *shell = (DM_Shell *)dm->data;
177fe1899a2SJed Brown   Mat       A;
178fe1899a2SJed Brown 
179fe1899a2SJed Brown   PetscFunctionBegin;
180fe1899a2SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
181064a246eSJacob Faibussowitsch   PetscValidPointer(J, 2);
1827bde9f88SJed Brown   if (!shell->A) {
1837bde9f88SJed Brown     if (shell->Xglobal) {
1847bde9f88SJed Brown       PetscInt m, M;
1859566063dSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "Naively creating matrix using global vector distribution without preallocation\n"));
1869566063dSJacob Faibussowitsch       PetscCall(VecGetSize(shell->Xglobal, &M));
1879566063dSJacob Faibussowitsch       PetscCall(VecGetLocalSize(shell->Xglobal, &m));
1889566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), &shell->A));
1899566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(shell->A, m, m, M, M));
1909566063dSJacob Faibussowitsch       PetscCall(MatSetType(shell->A, dm->mattype));
1919566063dSJacob Faibussowitsch       PetscCall(MatSetUp(shell->A));
192ce94432eSBarry Smith     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMShellSetMatrix(), DMShellSetCreateMatrix(), or provide a vector");
1937bde9f88SJed Brown   }
194fe1899a2SJed Brown   A = shell->A;
1959566063dSJacob Faibussowitsch   PetscCall(MatDuplicate(A, MAT_SHARE_NONZERO_PATTERN, J));
1969566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*J, dm));
1973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
198fe1899a2SJed Brown }
199fe1899a2SJed Brown 
200d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateGlobalVector_Shell(DM dm, Vec *gvec)
201d71ae5a4SJacob Faibussowitsch {
202fe1899a2SJed Brown   DM_Shell *shell = (DM_Shell *)dm->data;
203fe1899a2SJed Brown   Vec       X;
204fe1899a2SJed Brown 
205fe1899a2SJed Brown   PetscFunctionBegin;
206fe1899a2SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
207fe1899a2SJed Brown   PetscValidPointer(gvec, 2);
208ea78f98cSLisandro Dalcin   *gvec = NULL;
209fe1899a2SJed Brown   X     = shell->Xglobal;
2107a8be351SBarry Smith   PetscCheck(X, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMShellSetGlobalVector() or DMShellSetCreateGlobalVector()");
21106f803f6SStefano Zampini   /* Need to create a copy in order to attach the DM to the vector */
2129566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(X, gvec));
2139566063dSJacob Faibussowitsch   PetscCall(VecZeroEntries(*gvec));
2149566063dSJacob Faibussowitsch   PetscCall(VecSetDM(*gvec, dm));
2153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
216fe1899a2SJed Brown }
217fe1899a2SJed Brown 
218d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLocalVector_Shell(DM dm, Vec *gvec)
219d71ae5a4SJacob Faibussowitsch {
220dc43b69eSJed Brown   DM_Shell *shell = (DM_Shell *)dm->data;
221dc43b69eSJed Brown   Vec       X;
222dc43b69eSJed Brown 
223dc43b69eSJed Brown   PetscFunctionBegin;
224dc43b69eSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
225dc43b69eSJed Brown   PetscValidPointer(gvec, 2);
226ea78f98cSLisandro Dalcin   *gvec = NULL;
227dc43b69eSJed Brown   X     = shell->Xlocal;
2287a8be351SBarry Smith   PetscCheck(X, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMShellSetLocalVector() or DMShellSetCreateLocalVector()");
22906f803f6SStefano Zampini   /* Need to create a copy in order to attach the DM to the vector */
2309566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(X, gvec));
2319566063dSJacob Faibussowitsch   PetscCall(VecZeroEntries(*gvec));
2329566063dSJacob Faibussowitsch   PetscCall(VecSetDM(*gvec, dm));
2333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
234dc43b69eSJed Brown }
235dc43b69eSJed Brown 
236fef3a512SBarry Smith /*@
23709904cd0SBarry Smith    DMShellSetDestroyContext - set a function that destroys the context provided with `DMShellSetContext()`
23809904cd0SBarry Smith 
23909904cd0SBarry Smith    Collective
24009904cd0SBarry Smith 
24109904cd0SBarry Smith    Input Parameters:
24209904cd0SBarry Smith .  ctx - the context
24309904cd0SBarry Smith 
24409904cd0SBarry Smith    Level: advanced
24509904cd0SBarry Smith 
246*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellSetContext()`, `DMShellGetContext()`
24709904cd0SBarry Smith @*/
248d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetDestroyContext(DM dm, PetscErrorCode (*destroyctx)(void *))
249d71ae5a4SJacob Faibussowitsch {
25009904cd0SBarry Smith   DM_Shell *shell = (DM_Shell *)dm->data;
25109904cd0SBarry Smith   PetscBool isshell;
25209904cd0SBarry Smith 
25309904cd0SBarry Smith   PetscFunctionBegin;
25409904cd0SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
25509904cd0SBarry Smith   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
2563ba16761SJacob Faibussowitsch   if (!isshell) PetscFunctionReturn(PETSC_SUCCESS);
25709904cd0SBarry Smith   shell->destroyctx = destroyctx;
2583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25909904cd0SBarry Smith }
26009904cd0SBarry Smith 
26109904cd0SBarry Smith /*@
262*20f4b53cSBarry Smith    DMShellSetContext - set some data to be usable by this `DMSHELL`
263fef3a512SBarry Smith 
264fef3a512SBarry Smith    Collective
265fef3a512SBarry Smith 
2664165533cSJose E. Roman    Input Parameters:
267*20f4b53cSBarry Smith +  dm - `DMSHELL`
268fef3a512SBarry Smith -  ctx - the context
269fef3a512SBarry Smith 
270fef3a512SBarry Smith    Level: advanced
271fef3a512SBarry Smith 
272*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMCreateMatrix()`, `DMShellGetContext()`
273fef3a512SBarry Smith @*/
274d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetContext(DM dm, void *ctx)
275d71ae5a4SJacob Faibussowitsch {
276fef3a512SBarry Smith   DM_Shell *shell = (DM_Shell *)dm->data;
277fef3a512SBarry Smith   PetscBool isshell;
278fef3a512SBarry Smith 
279fef3a512SBarry Smith   PetscFunctionBegin;
280fef3a512SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2819566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
2823ba16761SJacob Faibussowitsch   if (!isshell) PetscFunctionReturn(PETSC_SUCCESS);
283fef3a512SBarry Smith   shell->ctx = ctx;
2843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
285fef3a512SBarry Smith }
286fef3a512SBarry Smith 
287fef3a512SBarry Smith /*@
288*20f4b53cSBarry Smith    DMShellGetContext - Returns the user-provided context associated to the `DMSHELL`
289fef3a512SBarry Smith 
290fef3a512SBarry Smith    Collective
291fef3a512SBarry Smith 
2924165533cSJose E. Roman    Input Parameter:
293*20f4b53cSBarry Smith .  dm - `DMSHELL`
294fef3a512SBarry Smith 
2954165533cSJose E. Roman    Output Parameter:
296fef3a512SBarry Smith .  ctx - the context
297fef3a512SBarry Smith 
298fef3a512SBarry Smith    Level: advanced
299fef3a512SBarry Smith 
300*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMCreateMatrix()`, `DMShellSetContext()`
301fef3a512SBarry Smith @*/
302d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellGetContext(DM dm, void *ctx)
303d71ae5a4SJacob Faibussowitsch {
304fef3a512SBarry Smith   DM_Shell *shell = (DM_Shell *)dm->data;
305fef3a512SBarry Smith   PetscBool isshell;
306fef3a512SBarry Smith 
307fef3a512SBarry Smith   PetscFunctionBegin;
308fef3a512SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3099566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
3107a8be351SBarry Smith   PetscCheck(isshell, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Can only use with DMSHELL type DMs");
3113ec1f749SStefano Zampini   *(void **)ctx = shell->ctx;
3123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
313fef3a512SBarry Smith }
314fef3a512SBarry Smith 
315fe1899a2SJed Brown /*@
316*20f4b53cSBarry Smith    DMShellSetMatrix - sets a template matrix associated with the `DMSHELL`
317fe1899a2SJed Brown 
318fe1899a2SJed Brown    Collective
319fe1899a2SJed Brown 
3204165533cSJose E. Roman    Input Parameters:
321*20f4b53cSBarry Smith +  dm - `DMSHELL`
322fe1899a2SJed Brown -  J - template matrix
323fe1899a2SJed Brown 
324fe1899a2SJed Brown    Level: advanced
325fe1899a2SJed Brown 
32606f803f6SStefano Zampini    Developer Notes:
327*20f4b53cSBarry Smith     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.
32806f803f6SStefano Zampini 
329*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMCreateMatrix()`, `DMShellSetCreateMatrix()`, `DMShellSetContext()`, `DMShellGetContext()`
330fe1899a2SJed Brown @*/
331d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetMatrix(DM dm, Mat J)
332d71ae5a4SJacob Faibussowitsch {
333fe1899a2SJed Brown   DM_Shell *shell = (DM_Shell *)dm->data;
3348c87107bSJed Brown   PetscBool isshell;
33506f803f6SStefano Zampini   DM        mdm;
336fe1899a2SJed Brown 
337fe1899a2SJed Brown   PetscFunctionBegin;
3388c87107bSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3398c87107bSJed Brown   PetscValidHeaderSpecific(J, MAT_CLASSID, 2);
3409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
3413ba16761SJacob Faibussowitsch   if (!isshell) PetscFunctionReturn(PETSC_SUCCESS);
3423ba16761SJacob Faibussowitsch   if (J == shell->A) PetscFunctionReturn(PETSC_SUCCESS);
3439566063dSJacob Faibussowitsch   PetscCall(MatGetDM(J, &mdm));
3449566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)J));
3459566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&shell->A));
34606f803f6SStefano Zampini   if (mdm == dm) {
3479566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(J, MAT_SHARE_NONZERO_PATTERN, &shell->A));
3489566063dSJacob Faibussowitsch     PetscCall(MatSetDM(shell->A, NULL));
34906f803f6SStefano Zampini   } else shell->A = J;
3503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
351fe1899a2SJed Brown }
352fe1899a2SJed Brown 
353fe1899a2SJed Brown /*@C
354*20f4b53cSBarry Smith    DMShellSetCreateMatrix - sets the routine to create a matrix associated with the `DMSHELL`
355fe1899a2SJed Brown 
356*20f4b53cSBarry Smith    Logically Collective
357fe1899a2SJed Brown 
3584165533cSJose E. Roman    Input Parameters:
359*20f4b53cSBarry Smith +  dm - the `DMSHELL`
360fe1899a2SJed Brown -  func - the function to create a matrix
361fe1899a2SJed Brown 
362fe1899a2SJed Brown    Level: advanced
363fe1899a2SJed Brown 
364*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMCreateMatrix()`, `DMShellSetMatrix()`, `DMShellSetContext()`, `DMShellGetContext()`
365fe1899a2SJed Brown @*/
366d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetCreateMatrix(DM dm, PetscErrorCode (*func)(DM, Mat *))
367d71ae5a4SJacob Faibussowitsch {
368fe1899a2SJed Brown   PetscFunctionBegin;
369fe1899a2SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
370fe1899a2SJed Brown   dm->ops->creatematrix = func;
3713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
372fe1899a2SJed Brown }
373fe1899a2SJed Brown 
374fe1899a2SJed Brown /*@
375*20f4b53cSBarry Smith    DMShellSetGlobalVector - sets a template global vector associated with the `DMSHELL`
376fe1899a2SJed Brown 
377*20f4b53cSBarry Smith    Logically Collective
378fe1899a2SJed Brown 
3794165533cSJose E. Roman    Input Parameters:
380*20f4b53cSBarry Smith +  dm - `DMSHELL`
381fe1899a2SJed Brown -  X - template vector
382fe1899a2SJed Brown 
383fe1899a2SJed Brown    Level: advanced
384fe1899a2SJed Brown 
385*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMCreateGlobalVector()`, `DMShellSetMatrix()`, `DMShellSetCreateGlobalVector()`
386fe1899a2SJed Brown @*/
387d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetGlobalVector(DM dm, Vec X)
388d71ae5a4SJacob Faibussowitsch {
389fe1899a2SJed Brown   DM_Shell *shell = (DM_Shell *)dm->data;
3908c87107bSJed Brown   PetscBool isshell;
391cca7ec1eSBarry Smith   DM        vdm;
392fe1899a2SJed Brown 
393fe1899a2SJed Brown   PetscFunctionBegin;
3948c87107bSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3958c87107bSJed Brown   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
3969566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
3973ba16761SJacob Faibussowitsch   if (!isshell) PetscFunctionReturn(PETSC_SUCCESS);
3989566063dSJacob Faibussowitsch   PetscCall(VecGetDM(X, &vdm));
399cca7ec1eSBarry Smith   /*
400cca7ec1eSBarry Smith       if the vector proposed as the new base global vector for the DM is a DM vector associated
401cca7ec1eSBarry 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
402cca7ec1eSBarry Smith       we get a circular dependency that prevents the DM from being destroy when it should be.
403cca7ec1eSBarry Smith       This occurs when SNESSet/GetNPC() is used with a SNES that does not have a user provided
404cca7ec1eSBarry Smith       DM attached to it since the inner SNES (which shares the DM with the outer SNES) tries
405cca7ec1eSBarry Smith       to set its input vector (which is associated with the DM) as the base global vector.
406cca7ec1eSBarry Smith       Thanks to Juan P. Mendez Granado Re: [petsc-maint] Nonlinear conjugate gradien
407cca7ec1eSBarry Smith       for pointing out the problem.
408cca7ec1eSBarry Smith    */
4093ba16761SJacob Faibussowitsch   if (vdm == dm) PetscFunctionReturn(PETSC_SUCCESS);
4109566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)X));
4119566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&shell->Xglobal));
412fe1899a2SJed Brown   shell->Xglobal = X;
4133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
414fe1899a2SJed Brown }
415fe1899a2SJed Brown 
41604d741b1SMatthew G. Knepley /*@
417*20f4b53cSBarry Smith   DMShellGetGlobalVector - Returns the template global vector associated with the `DMSHELL`, or `NULL` if it was not set
41804d741b1SMatthew G. Knepley 
419*20f4b53cSBarry Smith    Not Collective
42004d741b1SMatthew G. Knepley 
4214165533cSJose E. Roman    Input Parameters:
422*20f4b53cSBarry Smith +  dm - `DMSHELL`
42304d741b1SMatthew G. Knepley -  X - template vector
42404d741b1SMatthew G. Knepley 
42504d741b1SMatthew G. Knepley    Level: advanced
42604d741b1SMatthew G. Knepley 
427*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellSetGlobalVector()`, `DMShellSetCreateGlobalVector()`, `DMCreateGlobalVector()`
42804d741b1SMatthew G. Knepley @*/
429d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellGetGlobalVector(DM dm, Vec *X)
430d71ae5a4SJacob Faibussowitsch {
43104d741b1SMatthew G. Knepley   DM_Shell *shell = (DM_Shell *)dm->data;
43204d741b1SMatthew G. Knepley   PetscBool isshell;
43304d741b1SMatthew G. Knepley 
43404d741b1SMatthew G. Knepley   PetscFunctionBegin;
43504d741b1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
43604d741b1SMatthew G. Knepley   PetscValidPointer(X, 2);
4379566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
4383ba16761SJacob Faibussowitsch   if (!isshell) PetscFunctionReturn(PETSC_SUCCESS);
43904d741b1SMatthew G. Knepley   *X = shell->Xglobal;
4403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44104d741b1SMatthew G. Knepley }
44204d741b1SMatthew G. Knepley 
443fe1899a2SJed Brown /*@C
444*20f4b53cSBarry Smith    DMShellSetCreateGlobalVector - sets the routine to create a global vector associated with the `DMSHELL`
445fe1899a2SJed Brown 
446fe1899a2SJed Brown    Logically Collective
447fe1899a2SJed Brown 
4484165533cSJose E. Roman    Input Parameters:
449*20f4b53cSBarry Smith +  dm - the `DMSHELL`
450fe1899a2SJed Brown -  func - the creation routine
451fe1899a2SJed Brown 
452fe1899a2SJed Brown    Level: advanced
453fe1899a2SJed Brown 
454*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellSetGlobalVector()`, `DMShellSetCreateMatrix()`, `DMShellSetContext()`, `DMShellGetContext()`
455fe1899a2SJed Brown @*/
456d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetCreateGlobalVector(DM dm, PetscErrorCode (*func)(DM, Vec *))
457d71ae5a4SJacob Faibussowitsch {
458fe1899a2SJed Brown   PetscFunctionBegin;
459fe1899a2SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
460fe1899a2SJed Brown   dm->ops->createglobalvector = func;
4613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
462fe1899a2SJed Brown }
463fe1899a2SJed Brown 
464dc43b69eSJed Brown /*@
465*20f4b53cSBarry Smith    DMShellSetLocalVector - sets a template local vector associated with the `DMSHELL`
466dc43b69eSJed Brown 
467*20f4b53cSBarry Smith    Logically Collective
468dc43b69eSJed Brown 
4694165533cSJose E. Roman    Input Parameters:
470*20f4b53cSBarry Smith +  dm - `DMSHELL`
471dc43b69eSJed Brown -  X - template vector
472dc43b69eSJed Brown 
473dc43b69eSJed Brown    Level: advanced
474dc43b69eSJed Brown 
475*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMCreateLocalVector()`, `DMShellSetMatrix()`, `DMShellSetCreateLocalVector()`
476dc43b69eSJed Brown @*/
477d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetLocalVector(DM dm, Vec X)
478d71ae5a4SJacob Faibussowitsch {
479dc43b69eSJed Brown   DM_Shell *shell = (DM_Shell *)dm->data;
480dc43b69eSJed Brown   PetscBool isshell;
481cca7ec1eSBarry Smith   DM        vdm;
482dc43b69eSJed Brown 
483dc43b69eSJed Brown   PetscFunctionBegin;
484dc43b69eSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
485dc43b69eSJed Brown   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
4869566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
4873ba16761SJacob Faibussowitsch   if (!isshell) PetscFunctionReturn(PETSC_SUCCESS);
4889566063dSJacob Faibussowitsch   PetscCall(VecGetDM(X, &vdm));
489cca7ec1eSBarry Smith   /*
490cca7ec1eSBarry Smith       if the vector proposed as the new base global vector for the DM is a DM vector associated
491cca7ec1eSBarry 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
492cca7ec1eSBarry Smith       we get a circular dependency that prevents the DM from being destroy when it should be.
493cca7ec1eSBarry Smith       This occurs when SNESSet/GetNPC() is used with a SNES that does not have a user provided
494cca7ec1eSBarry Smith       DM attached to it since the inner SNES (which shares the DM with the outer SNES) tries
495cca7ec1eSBarry Smith       to set its input vector (which is associated with the DM) as the base global vector.
496cca7ec1eSBarry Smith       Thanks to Juan P. Mendez Granado Re: [petsc-maint] Nonlinear conjugate gradien
497cca7ec1eSBarry Smith       for pointing out the problem.
498cca7ec1eSBarry Smith    */
4993ba16761SJacob Faibussowitsch   if (vdm == dm) PetscFunctionReturn(PETSC_SUCCESS);
5009566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)X));
5019566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&shell->Xlocal));
502dc43b69eSJed Brown   shell->Xlocal = X;
5033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
504dc43b69eSJed Brown }
505dc43b69eSJed Brown 
506dc43b69eSJed Brown /*@C
507*20f4b53cSBarry Smith    DMShellSetCreateLocalVector - sets the routine to create a local vector associated with the `DMSHELL`
508dc43b69eSJed Brown 
509dc43b69eSJed Brown    Logically Collective
510dc43b69eSJed Brown 
5114165533cSJose E. Roman    Input Parameters:
512*20f4b53cSBarry Smith +  dm - the `DMSHELL`
513dc43b69eSJed Brown -  func - the creation routine
514dc43b69eSJed Brown 
515dc43b69eSJed Brown    Level: advanced
516dc43b69eSJed Brown 
517*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellSetLocalVector()`, `DMShellSetCreateMatrix()`, `DMShellSetContext()`, `DMShellGetContext()`
518dc43b69eSJed Brown @*/
519d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetCreateLocalVector(DM dm, PetscErrorCode (*func)(DM, Vec *))
520d71ae5a4SJacob Faibussowitsch {
521dc43b69eSJed Brown   PetscFunctionBegin;
522dc43b69eSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
523dc43b69eSJed Brown   dm->ops->createlocalvector = func;
5243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
525dc43b69eSJed Brown }
526dc43b69eSJed Brown 
5278339e6d0SRichard Tran Mills /*@C
5288339e6d0SRichard Tran Mills    DMShellSetGlobalToLocal - Sets the routines used to perform a global to local scatter
5298339e6d0SRichard Tran Mills 
530d083f849SBarry Smith    Logically Collective on dm
5318339e6d0SRichard Tran Mills 
5324165533cSJose E. Roman    Input Parameters
533*20f4b53cSBarry Smith +  dm - the `DMSHELL`
5348339e6d0SRichard Tran Mills .  begin - the routine that begins the global to local scatter
5358339e6d0SRichard Tran Mills -  end - the routine that ends the global to local scatter
5368339e6d0SRichard Tran Mills 
5378339e6d0SRichard Tran Mills    Level: advanced
5388339e6d0SRichard Tran Mills 
539*20f4b53cSBarry Smith    Note:
540*20f4b53cSBarry Smith     If these functions are not provided but `DMShellSetGlobalToLocalVecScatter()` is called then
541*20f4b53cSBarry Smith    `DMGlobalToLocalBeginDefaultShell()`/`DMGlobalToLocalEndDefaultShell()` are used to to perform the transfers
542*20f4b53cSBarry Smith 
543*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellSetLocalToGlobal()`, `DMGlobalToLocalBeginDefaultShell()`, `DMGlobalToLocalEndDefaultShell()`
5448339e6d0SRichard Tran Mills @*/
545d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetGlobalToLocal(DM dm, PetscErrorCode (*begin)(DM, Vec, InsertMode, Vec), PetscErrorCode (*end)(DM, Vec, InsertMode, Vec))
546d71ae5a4SJacob Faibussowitsch {
5478339e6d0SRichard Tran Mills   PetscFunctionBegin;
5482d1bcd87SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5498339e6d0SRichard Tran Mills   dm->ops->globaltolocalbegin = begin;
5508339e6d0SRichard Tran Mills   dm->ops->globaltolocalend   = end;
5513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5528339e6d0SRichard Tran Mills }
5538339e6d0SRichard Tran Mills 
5548339e6d0SRichard Tran Mills /*@C
5558339e6d0SRichard Tran Mills    DMShellSetLocalToGlobal - Sets the routines used to perform a local to global scatter
5568339e6d0SRichard Tran Mills 
557d083f849SBarry Smith    Logically Collective on dm
5588339e6d0SRichard Tran Mills 
5594165533cSJose E. Roman    Input Parameters
560*20f4b53cSBarry Smith +  dm - the `DMSHELL`
5618339e6d0SRichard Tran Mills .  begin - the routine that begins the local to global scatter
5628339e6d0SRichard Tran Mills -  end - the routine that ends the local to global scatter
5638339e6d0SRichard Tran Mills 
5648339e6d0SRichard Tran Mills    Level: advanced
5658339e6d0SRichard Tran Mills 
566*20f4b53cSBarry Smith    Note:
567*20f4b53cSBarry Smith     If these functions are not provided but `DMShellSetLocalToGlobalVecScatter()` is called then
568*20f4b53cSBarry Smith    `DMLocalToGlobalBeginDefaultShell()`/`DMLocalToGlobalEndDefaultShell()` are used to to perform the transfers
569*20f4b53cSBarry Smith 
570*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellSetGlobalToLocal()`
5718339e6d0SRichard Tran Mills @*/
572d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetLocalToGlobal(DM dm, PetscErrorCode (*begin)(DM, Vec, InsertMode, Vec), PetscErrorCode (*end)(DM, Vec, InsertMode, Vec))
573d71ae5a4SJacob Faibussowitsch {
5748339e6d0SRichard Tran Mills   PetscFunctionBegin;
5752d1bcd87SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5768339e6d0SRichard Tran Mills   dm->ops->localtoglobalbegin = begin;
5778339e6d0SRichard Tran Mills   dm->ops->localtoglobalend   = end;
5783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5798339e6d0SRichard Tran Mills }
5808339e6d0SRichard Tran Mills 
581f3db62a7SRichard Tran Mills /*@C
582f3db62a7SRichard Tran Mills    DMShellSetLocalToLocal - Sets the routines used to perform a local to local scatter
583f3db62a7SRichard Tran Mills 
584d083f849SBarry Smith    Logically Collective on dm
585f3db62a7SRichard Tran Mills 
5864165533cSJose E. Roman    Input Parameters
587*20f4b53cSBarry Smith +  dm - the `DMSHELL`
588f3db62a7SRichard Tran Mills .  begin - the routine that begins the local to local scatter
589f3db62a7SRichard Tran Mills -  end - the routine that ends the local to local scatter
590f3db62a7SRichard Tran Mills 
591f3db62a7SRichard Tran Mills    Level: advanced
592f3db62a7SRichard Tran Mills 
593*20f4b53cSBarry Smith    Note:
594*20f4b53cSBarry Smith     If these functions are not provided but `DMShellSetLocalToLocalVecScatter()` is called then
595*20f4b53cSBarry Smith    `DMLocalToLocalBeginDefaultShell()`/`DMLocalToLocalEndDefaultShell()` are used to to perform the transfers
596*20f4b53cSBarry Smith 
597*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellSetGlobalToLocal()`, `DMLocalToLocalBeginDefaultShell()`, `DMLocalToLocalEndDefaultShell()`
598f3db62a7SRichard Tran Mills @*/
599d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetLocalToLocal(DM dm, PetscErrorCode (*begin)(DM, Vec, InsertMode, Vec), PetscErrorCode (*end)(DM, Vec, InsertMode, Vec))
600d71ae5a4SJacob Faibussowitsch {
601f3db62a7SRichard Tran Mills   PetscFunctionBegin;
6022d1bcd87SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
603f3db62a7SRichard Tran Mills   dm->ops->localtolocalbegin = begin;
604f3db62a7SRichard Tran Mills   dm->ops->localtolocalend   = end;
6053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
606f3db62a7SRichard Tran Mills }
607f3db62a7SRichard Tran Mills 
60881634712SRichard Tran Mills /*@
609*20f4b53cSBarry Smith    DMShellSetGlobalToLocalVecScatter - Sets a `VecScatter` context for global to local communication
61081634712SRichard Tran Mills 
611d083f849SBarry Smith    Logically Collective on dm
61281634712SRichard Tran Mills 
6134165533cSJose E. Roman    Input Parameters
614*20f4b53cSBarry Smith +  dm - the `DMSHELL`
615*20f4b53cSBarry Smith -  gtol - the global to local `VecScatter` context
61681634712SRichard Tran Mills 
61781634712SRichard Tran Mills    Level: advanced
61881634712SRichard Tran Mills 
619*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellSetGlobalToLocal()`, `DMGlobalToLocalBeginDefaultShell()`, `DMGlobalToLocalEndDefaultShell()`
62081634712SRichard Tran Mills @*/
621d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetGlobalToLocalVecScatter(DM dm, VecScatter gtol)
622d71ae5a4SJacob Faibussowitsch {
62381634712SRichard Tran Mills   DM_Shell *shell = (DM_Shell *)dm->data;
62481634712SRichard Tran Mills 
625b300e4a8SRichard Tran Mills   PetscFunctionBegin;
6262d1bcd87SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
62797929ea7SJunchao Zhang   PetscValidHeaderSpecific(gtol, PETSCSF_CLASSID, 2);
6289566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)gtol));
6299566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&shell->gtol));
63081634712SRichard Tran Mills   shell->gtol = gtol;
6313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
63281634712SRichard Tran Mills }
63381634712SRichard Tran Mills 
634988ea7d6SRichard Tran Mills /*@
635*20f4b53cSBarry Smith    DMShellSetLocalToGlobalVecScatter - Sets a` VecScatter` context for local to global communication
636988ea7d6SRichard Tran Mills 
637d083f849SBarry Smith    Logically Collective on dm
638988ea7d6SRichard Tran Mills 
6394165533cSJose E. Roman    Input Parameters
640*20f4b53cSBarry Smith +  dm - the `DMSHELL`
641*20f4b53cSBarry Smith -  ltog - the local to global `VecScatter` context
642988ea7d6SRichard Tran Mills 
643988ea7d6SRichard Tran Mills    Level: advanced
644988ea7d6SRichard Tran Mills 
645*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellSetLocalToGlobal()`, `DMLocalToGlobalBeginDefaultShell()`, `DMLocalToGlobalEndDefaultShell()`
646988ea7d6SRichard Tran Mills @*/
647d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetLocalToGlobalVecScatter(DM dm, VecScatter ltog)
648d71ae5a4SJacob Faibussowitsch {
649988ea7d6SRichard Tran Mills   DM_Shell *shell = (DM_Shell *)dm->data;
650988ea7d6SRichard Tran Mills 
651988ea7d6SRichard Tran Mills   PetscFunctionBegin;
6522d1bcd87SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
65397929ea7SJunchao Zhang   PetscValidHeaderSpecific(ltog, PETSCSF_CLASSID, 2);
6549566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ltog));
6559566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&shell->ltog));
656988ea7d6SRichard Tran Mills   shell->ltog = ltog;
6573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
658988ea7d6SRichard Tran Mills }
659988ea7d6SRichard Tran Mills 
660f3db62a7SRichard Tran Mills /*@
661*20f4b53cSBarry Smith    DMShellSetLocalToLocalVecScatter - Sets a `VecScatter` context for local to local communication
662f3db62a7SRichard Tran Mills 
663*20f4b53cSBarry Smith    Logically Collective
664f3db62a7SRichard Tran Mills 
6654165533cSJose E. Roman    Input Parameters
666*20f4b53cSBarry Smith +  dm - the `DMSHELL`
667*20f4b53cSBarry Smith -  ltol - the local to local `VecScatter` context
668f3db62a7SRichard Tran Mills 
669f3db62a7SRichard Tran Mills    Level: advanced
670f3db62a7SRichard Tran Mills 
671*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellSetLocalToLocal()`, `DMLocalToLocalBeginDefaultShell()`, `DMLocalToLocalEndDefaultShell()`
672f3db62a7SRichard Tran Mills @*/
673d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetLocalToLocalVecScatter(DM dm, VecScatter ltol)
674d71ae5a4SJacob Faibussowitsch {
675f3db62a7SRichard Tran Mills   DM_Shell *shell = (DM_Shell *)dm->data;
676f3db62a7SRichard Tran Mills 
677f3db62a7SRichard Tran Mills   PetscFunctionBegin;
6782d1bcd87SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
67997929ea7SJunchao Zhang   PetscValidHeaderSpecific(ltol, PETSCSF_CLASSID, 2);
6809566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ltol));
6819566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&shell->ltol));
682f3db62a7SRichard Tran Mills   shell->ltol = ltol;
6833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
684f3db62a7SRichard Tran Mills }
685f3db62a7SRichard Tran Mills 
6869bf9660cSLawrence Mitchell /*@C
687*20f4b53cSBarry Smith    DMShellSetCoarsen - Set the routine used to coarsen the `DMSHELL`
6889bf9660cSLawrence Mitchell 
689*20f4b53cSBarry Smith    Logically Collective
6909bf9660cSLawrence Mitchell 
6914165533cSJose E. Roman    Input Parameters
692*20f4b53cSBarry Smith +  dm - the `DMSHELL`
693*20f4b53cSBarry Smith -  coarsen - the routine that coarsens the `DM`
6949bf9660cSLawrence Mitchell 
6959bf9660cSLawrence Mitchell    Level: advanced
6969bf9660cSLawrence Mitchell 
697*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellSetRefine()`, `DMCoarsen()`, `DMShellGetCoarsen()`, `DMShellSetContext()`, `DMShellGetContext()`
6989bf9660cSLawrence Mitchell @*/
699d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetCoarsen(DM dm, PetscErrorCode (*coarsen)(DM, MPI_Comm, DM *))
700d71ae5a4SJacob Faibussowitsch {
701f572501eSLawrence Mitchell   PetscBool isshell;
702f572501eSLawrence Mitchell 
703f572501eSLawrence Mitchell   PetscFunctionBegin;
704f572501eSLawrence Mitchell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7059566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
7063ba16761SJacob Faibussowitsch   if (!isshell) PetscFunctionReturn(PETSC_SUCCESS);
707f572501eSLawrence Mitchell   dm->ops->coarsen = coarsen;
7083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
709f572501eSLawrence Mitchell }
710f572501eSLawrence Mitchell 
7119bf9660cSLawrence Mitchell /*@C
712*20f4b53cSBarry Smith    DMShellGetCoarsen - Get the routine used to coarsen the `DMSHELL`
7134363ddcaSBoris Boutkov 
714*20f4b53cSBarry Smith    Logically Collective
7154363ddcaSBoris Boutkov 
7164165533cSJose E. Roman    Input Parameter:
717*20f4b53cSBarry Smith .  dm - the `DMSHELL`
7184363ddcaSBoris Boutkov 
7194165533cSJose E. Roman    Output Parameter:
720*20f4b53cSBarry Smith .  coarsen - the routine that coarsens the `DM`
7214363ddcaSBoris Boutkov 
7224363ddcaSBoris Boutkov    Level: advanced
7234363ddcaSBoris Boutkov 
724*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellSetCoarsen()`, `DMCoarsen()`, `DMShellSetRefine()`, `DMRefine()`
7254363ddcaSBoris Boutkov @*/
726d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellGetCoarsen(DM dm, PetscErrorCode (**coarsen)(DM, MPI_Comm, DM *))
727d71ae5a4SJacob Faibussowitsch {
7284363ddcaSBoris Boutkov   PetscBool isshell;
7294363ddcaSBoris Boutkov 
7304363ddcaSBoris Boutkov   PetscFunctionBegin;
7314363ddcaSBoris Boutkov   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7329566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
7337a8be351SBarry Smith   PetscCheck(isshell, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Can only use with DMSHELL type DMs");
7344363ddcaSBoris Boutkov   *coarsen = dm->ops->coarsen;
7353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7364363ddcaSBoris Boutkov }
7374363ddcaSBoris Boutkov 
7384363ddcaSBoris Boutkov /*@C
739*20f4b53cSBarry Smith    DMShellSetRefine - Set the routine used to refine the `DMSHELL`
7409bf9660cSLawrence Mitchell 
741*20f4b53cSBarry Smith    Logically Collective
7429bf9660cSLawrence Mitchell 
7434165533cSJose E. Roman    Input Parameters
744*20f4b53cSBarry Smith +  dm - the `DMSHELL`
745*20f4b53cSBarry Smith -  refine - the routine that refines the `DM`
7469bf9660cSLawrence Mitchell 
7479bf9660cSLawrence Mitchell    Level: advanced
7489bf9660cSLawrence Mitchell 
749*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellSetCoarsen()`, `DMRefine()`, `DMShellGetRefine()`, `DMShellSetContext()`, `DMShellGetContext()`
7509bf9660cSLawrence Mitchell @*/
751d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetRefine(DM dm, PetscErrorCode (*refine)(DM, MPI_Comm, DM *))
752d71ae5a4SJacob Faibussowitsch {
753f572501eSLawrence Mitchell   PetscBool isshell;
754f572501eSLawrence Mitchell 
755f572501eSLawrence Mitchell   PetscFunctionBegin;
756f572501eSLawrence Mitchell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
7583ba16761SJacob Faibussowitsch   if (!isshell) PetscFunctionReturn(PETSC_SUCCESS);
759f572501eSLawrence Mitchell   dm->ops->refine = refine;
7603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
761f572501eSLawrence Mitchell }
762f572501eSLawrence Mitchell 
7639bf9660cSLawrence Mitchell /*@C
764*20f4b53cSBarry Smith    DMShellGetRefine - Get the routine used to refine the `DMSHELL`
7654363ddcaSBoris Boutkov 
766*20f4b53cSBarry Smith    Logically Collective
7674363ddcaSBoris Boutkov 
7684165533cSJose E. Roman    Input Parameter:
769*20f4b53cSBarry Smith .  dm - the `DMSHELL`
7704363ddcaSBoris Boutkov 
7714165533cSJose E. Roman    Output Parameter:
772*20f4b53cSBarry Smith .  refine - the routine that refines the `DM`
7734363ddcaSBoris Boutkov 
7744363ddcaSBoris Boutkov    Level: advanced
7754363ddcaSBoris Boutkov 
776*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellSetCoarsen()`, `DMCoarsen()`, `DMShellSetRefine()`, `DMRefine()`
7774363ddcaSBoris Boutkov @*/
778d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellGetRefine(DM dm, PetscErrorCode (**refine)(DM, MPI_Comm, DM *))
779d71ae5a4SJacob Faibussowitsch {
7804363ddcaSBoris Boutkov   PetscBool isshell;
7814363ddcaSBoris Boutkov 
7824363ddcaSBoris Boutkov   PetscFunctionBegin;
7834363ddcaSBoris Boutkov   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7849566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
7857a8be351SBarry Smith   PetscCheck(isshell, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Can only use with DMSHELL type DMs");
7864363ddcaSBoris Boutkov   *refine = dm->ops->refine;
7873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7884363ddcaSBoris Boutkov }
7894363ddcaSBoris Boutkov 
7904363ddcaSBoris Boutkov /*@C
7919bf9660cSLawrence Mitchell    DMShellSetCreateInterpolation - Set the routine used to create the interpolation operator
7929bf9660cSLawrence Mitchell 
793*20f4b53cSBarry Smith    Logically Collective
7949bf9660cSLawrence Mitchell 
7954165533cSJose E. Roman    Input Parameters
796*20f4b53cSBarry Smith +  dm - the `DMSHELL`
7979bf9660cSLawrence Mitchell -  interp - the routine to create the interpolation
7989bf9660cSLawrence Mitchell 
7999bf9660cSLawrence Mitchell    Level: advanced
8009bf9660cSLawrence Mitchell 
801*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellSetCreateInjection()`, `DMCreateInterpolation()`, `DMShellGetCreateInterpolation()`, `DMShellSetCreateRestriction()`, `DMShellSetContext()`, `DMShellGetContext()`
8029bf9660cSLawrence Mitchell @*/
803d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetCreateInterpolation(DM dm, PetscErrorCode (*interp)(DM, DM, Mat *, Vec *))
804d71ae5a4SJacob Faibussowitsch {
805f572501eSLawrence Mitchell   PetscBool isshell;
806f572501eSLawrence Mitchell 
807f572501eSLawrence Mitchell   PetscFunctionBegin;
808f572501eSLawrence Mitchell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8099566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
8103ba16761SJacob Faibussowitsch   if (!isshell) PetscFunctionReturn(PETSC_SUCCESS);
811f572501eSLawrence Mitchell   dm->ops->createinterpolation = interp;
8123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
813f572501eSLawrence Mitchell }
814f572501eSLawrence Mitchell 
8153ad4599aSBarry Smith /*@C
8164363ddcaSBoris Boutkov    DMShellGetCreateInterpolation - Get the routine used to create the interpolation operator
8174363ddcaSBoris Boutkov 
818*20f4b53cSBarry Smith    Logically Collective
8194363ddcaSBoris Boutkov 
8204165533cSJose E. Roman    Input Parameter:
821*20f4b53cSBarry Smith .  dm - the `DMSHELL`
822a4a986ddSBoris Boutkov 
8234165533cSJose E. Roman    Output Parameter:
8244165533cSJose E. Roman .  interp - the routine to create the interpolation
8254363ddcaSBoris Boutkov 
8264363ddcaSBoris Boutkov    Level: advanced
8274363ddcaSBoris Boutkov 
828*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellGetCreateInjection()`, `DMCreateInterpolation()`, `DMShellGetCreateRestriction()`, `DMShellSetContext()`, `DMShellGetContext()`
8294363ddcaSBoris Boutkov @*/
830d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellGetCreateInterpolation(DM dm, PetscErrorCode (**interp)(DM, DM, Mat *, Vec *))
831d71ae5a4SJacob Faibussowitsch {
8324363ddcaSBoris Boutkov   PetscBool isshell;
8334363ddcaSBoris Boutkov 
8344363ddcaSBoris Boutkov   PetscFunctionBegin;
8354363ddcaSBoris Boutkov   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8369566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
8377a8be351SBarry Smith   PetscCheck(isshell, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Can only use with DMSHELL type DMs");
8384363ddcaSBoris Boutkov   *interp = dm->ops->createinterpolation;
8393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8404363ddcaSBoris Boutkov }
8414363ddcaSBoris Boutkov 
8424363ddcaSBoris Boutkov /*@C
8433ad4599aSBarry Smith    DMShellSetCreateRestriction - Set the routine used to create the restriction operator
8443ad4599aSBarry Smith 
845*20f4b53cSBarry Smith    Logically Collective
8463ad4599aSBarry Smith 
8474165533cSJose E. Roman    Input Parameters
848*20f4b53cSBarry Smith +  dm - the `DMSHELL`
8493ad4599aSBarry Smith -  striction- the routine to create the restriction
8503ad4599aSBarry Smith 
8513ad4599aSBarry Smith    Level: advanced
8523ad4599aSBarry Smith 
853*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellSetCreateInjection()`, `DMCreateInterpolation()`, `DMShellGetCreateRestriction()`, `DMShellSetContext()`, `DMShellGetContext()`
8543ad4599aSBarry Smith @*/
855d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetCreateRestriction(DM dm, PetscErrorCode (*restriction)(DM, DM, Mat *))
856d71ae5a4SJacob Faibussowitsch {
8573ad4599aSBarry Smith   PetscBool isshell;
8583ad4599aSBarry Smith 
8593ad4599aSBarry Smith   PetscFunctionBegin;
8603ad4599aSBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8619566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
8623ba16761SJacob Faibussowitsch   if (!isshell) PetscFunctionReturn(PETSC_SUCCESS);
8633ad4599aSBarry Smith   dm->ops->createrestriction = restriction;
8643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8653ad4599aSBarry Smith }
8663ad4599aSBarry Smith 
8679bf9660cSLawrence Mitchell /*@C
8684363ddcaSBoris Boutkov    DMShellGetCreateRestriction - Get the routine used to create the restriction operator
8694363ddcaSBoris Boutkov 
870*20f4b53cSBarry Smith    Logically Collective
8714363ddcaSBoris Boutkov 
8724165533cSJose E. Roman    Input Parameter:
873*20f4b53cSBarry Smith .  dm - the `DMSHELL`
874a4a986ddSBoris Boutkov 
8754165533cSJose E. Roman    Output Parameter:
8764165533cSJose E. Roman .  restriction - the routine to create the restriction
8774363ddcaSBoris Boutkov 
8784363ddcaSBoris Boutkov    Level: advanced
8794363ddcaSBoris Boutkov 
880*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellSetCreateInjection()`, `DMCreateInterpolation()`, `DMShellSetContext()`, `DMShellGetContext()`
8814363ddcaSBoris Boutkov @*/
882d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellGetCreateRestriction(DM dm, PetscErrorCode (**restriction)(DM, DM, Mat *))
883d71ae5a4SJacob Faibussowitsch {
8844363ddcaSBoris Boutkov   PetscBool isshell;
8854363ddcaSBoris Boutkov 
8864363ddcaSBoris Boutkov   PetscFunctionBegin;
8874363ddcaSBoris Boutkov   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8889566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
8897a8be351SBarry Smith   PetscCheck(isshell, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Can only use with DMSHELL type DMs");
8904363ddcaSBoris Boutkov   *restriction = dm->ops->createrestriction;
8913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8924363ddcaSBoris Boutkov }
8934363ddcaSBoris Boutkov 
8944363ddcaSBoris Boutkov /*@C
8959bf9660cSLawrence Mitchell    DMShellSetCreateInjection - Set the routine used to create the injection operator
8969bf9660cSLawrence Mitchell 
897*20f4b53cSBarry Smith    Logically Collective
8989bf9660cSLawrence Mitchell 
8994165533cSJose E. Roman    Input Parameters:
900*20f4b53cSBarry Smith +  dm - the `DMSHELL`
9019bf9660cSLawrence Mitchell -  inject - the routine to create the injection
9029bf9660cSLawrence Mitchell 
9039bf9660cSLawrence Mitchell    Level: advanced
9049bf9660cSLawrence Mitchell 
905*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellSetCreateInterpolation()`, `DMCreateInjection()`, `DMShellGetCreateInjection()`, `DMShellSetContext()`, `DMShellGetContext()`
9069bf9660cSLawrence Mitchell @*/
907d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetCreateInjection(DM dm, PetscErrorCode (*inject)(DM, DM, Mat *))
908d71ae5a4SJacob Faibussowitsch {
909f572501eSLawrence Mitchell   PetscBool isshell;
910f572501eSLawrence Mitchell 
911f572501eSLawrence Mitchell   PetscFunctionBegin;
912f572501eSLawrence Mitchell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9139566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
9143ba16761SJacob Faibussowitsch   if (!isshell) PetscFunctionReturn(PETSC_SUCCESS);
9155a84ad33SLisandro Dalcin   dm->ops->createinjection = inject;
9163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
917f572501eSLawrence Mitchell }
918f572501eSLawrence Mitchell 
9194363ddcaSBoris Boutkov /*@C
9204363ddcaSBoris Boutkov    DMShellGetCreateInjection - Get the routine used to create the injection operator
9214363ddcaSBoris Boutkov 
922*20f4b53cSBarry Smith    Logically Collective
9234363ddcaSBoris Boutkov 
9244165533cSJose E. Roman    Input Parameter:
925*20f4b53cSBarry Smith .  dm - the `DMSHELL`
926a4a986ddSBoris Boutkov 
9274165533cSJose E. Roman    Output Parameter:
9284165533cSJose E. Roman .  inject - the routine to create the injection
9294363ddcaSBoris Boutkov 
9304363ddcaSBoris Boutkov    Level: advanced
9314363ddcaSBoris Boutkov 
932*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMShellGetCreateInterpolation()`, `DMCreateInjection()`, `DMShellSetContext()`, `DMShellGetContext()`
9334363ddcaSBoris Boutkov @*/
934d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellGetCreateInjection(DM dm, PetscErrorCode (**inject)(DM, DM, Mat *))
935d71ae5a4SJacob Faibussowitsch {
9364363ddcaSBoris Boutkov   PetscBool isshell;
9374363ddcaSBoris Boutkov 
9384363ddcaSBoris Boutkov   PetscFunctionBegin;
9394363ddcaSBoris Boutkov   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
9417a8be351SBarry Smith   PetscCheck(isshell, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Can only use with DMSHELL type DMs");
9425a84ad33SLisandro Dalcin   *inject = dm->ops->createinjection;
9433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9444363ddcaSBoris Boutkov }
9454363ddcaSBoris Boutkov 
9469bf9660cSLawrence Mitchell /*@C
947*20f4b53cSBarry Smith    DMShellSetCreateFieldDecomposition - Set the routine used to create a decomposition of fields for the `DMSHELL`
9489bf9660cSLawrence Mitchell 
949*20f4b53cSBarry Smith    Logically Collective
9509bf9660cSLawrence Mitchell 
9514165533cSJose E. Roman    Input Parameters:
952*20f4b53cSBarry Smith +  dm - the `DMSHELL`
9539bf9660cSLawrence Mitchell -  decomp - the routine to create the decomposition
9549bf9660cSLawrence Mitchell 
9559bf9660cSLawrence Mitchell    Level: advanced
9569bf9660cSLawrence Mitchell 
957*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMCreateFieldDecomposition()`, `DMShellSetContext()`, `DMShellGetContext()`
9589bf9660cSLawrence Mitchell @*/
959d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetCreateFieldDecomposition(DM dm, PetscErrorCode (*decomp)(DM, PetscInt *, char ***, IS **, DM **))
960d71ae5a4SJacob Faibussowitsch {
9615e2259d5SLawrence Mitchell   PetscBool isshell;
9625e2259d5SLawrence Mitchell 
9635e2259d5SLawrence Mitchell   PetscFunctionBegin;
9645e2259d5SLawrence Mitchell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9659566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
9663ba16761SJacob Faibussowitsch   if (!isshell) PetscFunctionReturn(PETSC_SUCCESS);
9675e2259d5SLawrence Mitchell   dm->ops->createfielddecomposition = decomp;
9683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9695e2259d5SLawrence Mitchell }
9705e2259d5SLawrence Mitchell 
971c00061e5SLawrence Mitchell /*@C
972*20f4b53cSBarry Smith    DMShellSetCreateDomainDecomposition - Set the routine used to create a domain decomposition for the `DMSHELL`
973e734121bSPatrick Farrell 
974*20f4b53cSBarry Smith    Logically Collective
975e734121bSPatrick Farrell 
9764165533cSJose E. Roman    Input Parameters:
977*20f4b53cSBarry Smith +  dm - the `DMSHELL`
978e734121bSPatrick Farrell -  decomp - the routine to create the decomposition
979e734121bSPatrick Farrell 
980e734121bSPatrick Farrell    Level: advanced
981e734121bSPatrick Farrell 
982*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMCreateDomainDecomposition()`, `DMShellSetContext()`, `DMShellGetContext()`
983e734121bSPatrick Farrell @*/
984d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetCreateDomainDecomposition(DM dm, PetscErrorCode (*decomp)(DM, PetscInt *, char ***, IS **, IS **, DM **))
985d71ae5a4SJacob Faibussowitsch {
986e734121bSPatrick Farrell   PetscBool isshell;
987e734121bSPatrick Farrell 
988e734121bSPatrick Farrell   PetscFunctionBegin;
989e734121bSPatrick Farrell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9909566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
9913ba16761SJacob Faibussowitsch   if (!isshell) PetscFunctionReturn(PETSC_SUCCESS);
992e734121bSPatrick Farrell   dm->ops->createdomaindecomposition = decomp;
9933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
994e734121bSPatrick Farrell }
995e734121bSPatrick Farrell 
996e734121bSPatrick Farrell /*@C
997*20f4b53cSBarry Smith    DMShellSetCreateDomainDecompositionScatters - Set the routine used to create the scatter contexts for domain decomposition with a `DMSHELL`
998eef9d6cdSPatrick Farrell 
999*20f4b53cSBarry Smith    Logically Collective
1000eef9d6cdSPatrick Farrell 
10014165533cSJose E. Roman    Input Parameters:
1002*20f4b53cSBarry Smith +  dm - the `DMSHELL`
1003eef9d6cdSPatrick Farrell -  scatter - the routine to create the scatters
1004eef9d6cdSPatrick Farrell 
1005eef9d6cdSPatrick Farrell    Level: advanced
1006eef9d6cdSPatrick Farrell 
1007*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMCreateDomainDecompositionScatters()`, `DMShellSetContext()`, `DMShellGetContext()`
1008eef9d6cdSPatrick Farrell @*/
1009d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetCreateDomainDecompositionScatters(DM dm, PetscErrorCode (*scatter)(DM, PetscInt, DM *, VecScatter **, VecScatter **, VecScatter **))
1010d71ae5a4SJacob Faibussowitsch {
1011eef9d6cdSPatrick Farrell   PetscBool isshell;
1012eef9d6cdSPatrick Farrell 
1013eef9d6cdSPatrick Farrell   PetscFunctionBegin;
1014eef9d6cdSPatrick Farrell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10159566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
10163ba16761SJacob Faibussowitsch   if (!isshell) PetscFunctionReturn(PETSC_SUCCESS);
1017eef9d6cdSPatrick Farrell   dm->ops->createddscatters = scatter;
10183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1019eef9d6cdSPatrick Farrell }
1020eef9d6cdSPatrick Farrell 
1021eef9d6cdSPatrick Farrell /*@C
1022*20f4b53cSBarry Smith    DMShellSetCreateSubDM - Set the routine used to create a sub `DM` from the `DMSHELL`
1023c00061e5SLawrence Mitchell 
1024*20f4b53cSBarry Smith    Logically Collective
1025c00061e5SLawrence Mitchell 
10264165533cSJose E. Roman    Input Parameters:
1027*20f4b53cSBarry Smith +  dm - the `DMSHELL`
1028c00061e5SLawrence Mitchell -  subdm - the routine to create the decomposition
1029c00061e5SLawrence Mitchell 
1030c00061e5SLawrence Mitchell    Level: advanced
1031c00061e5SLawrence Mitchell 
1032*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMCreateSubDM()`, `DMShellGetCreateSubDM()`, `DMShellSetContext()`, `DMShellGetContext()`
1033c00061e5SLawrence Mitchell @*/
1034d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellSetCreateSubDM(DM dm, PetscErrorCode (*subdm)(DM, PetscInt, const PetscInt[], IS *, DM *))
1035d71ae5a4SJacob Faibussowitsch {
1036c00061e5SLawrence Mitchell   PetscBool isshell;
1037c00061e5SLawrence Mitchell 
1038c00061e5SLawrence Mitchell   PetscFunctionBegin;
1039c00061e5SLawrence Mitchell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
10413ba16761SJacob Faibussowitsch   if (!isshell) PetscFunctionReturn(PETSC_SUCCESS);
1042c00061e5SLawrence Mitchell   dm->ops->createsubdm = subdm;
10433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1044c00061e5SLawrence Mitchell }
1045c00061e5SLawrence Mitchell 
10464363ddcaSBoris Boutkov /*@C
1047*20f4b53cSBarry Smith    DMShellGetCreateSubDM - Get the routine used to create a sub DM from the `DMSHELL`
10484363ddcaSBoris Boutkov 
1049*20f4b53cSBarry Smith    Logically Collective
10504363ddcaSBoris Boutkov 
10514165533cSJose E. Roman    Input Parameter:
1052*20f4b53cSBarry Smith .  dm - the `DMSHELL`
1053a4a986ddSBoris Boutkov 
10544165533cSJose E. Roman    Output Parameter:
10554165533cSJose E. Roman .  subdm - the routine to create the decomposition
10564363ddcaSBoris Boutkov 
10574363ddcaSBoris Boutkov    Level: advanced
10584363ddcaSBoris Boutkov 
1059*20f4b53cSBarry Smith .seealso: `DM`, `DMSHELL`, `DMCreateSubDM()`, `DMShellSetCreateSubDM()`, `DMShellSetContext()`, `DMShellGetContext()`
10604363ddcaSBoris Boutkov @*/
1061d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellGetCreateSubDM(DM dm, PetscErrorCode (**subdm)(DM, PetscInt, const PetscInt[], IS *, DM *))
1062d71ae5a4SJacob Faibussowitsch {
10634363ddcaSBoris Boutkov   PetscBool isshell;
10644363ddcaSBoris Boutkov 
10654363ddcaSBoris Boutkov   PetscFunctionBegin;
10664363ddcaSBoris Boutkov   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10679566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSHELL, &isshell));
10687a8be351SBarry Smith   PetscCheck(isshell, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Can only use with DMSHELL type DMs");
10694363ddcaSBoris Boutkov   *subdm = dm->ops->createsubdm;
10703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10714363ddcaSBoris Boutkov }
10724363ddcaSBoris Boutkov 
1073d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMDestroy_Shell(DM dm)
1074d71ae5a4SJacob Faibussowitsch {
1075fe1899a2SJed Brown   DM_Shell *shell = (DM_Shell *)dm->data;
1076fe1899a2SJed Brown 
1077fe1899a2SJed Brown   PetscFunctionBegin;
107809904cd0SBarry Smith   if (shell->destroyctx) PetscCallBack("Destroy Context", (*shell->destroyctx)(shell->ctx));
10799566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&shell->A));
10809566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&shell->Xglobal));
10819566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&shell->Xlocal));
10829566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&shell->gtol));
10839566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&shell->ltog));
10849566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&shell->ltol));
10857b6ad80cSMatthew G Knepley   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
10869566063dSJacob Faibussowitsch   PetscCall(PetscFree(shell));
10873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1088fe1899a2SJed Brown }
1089fe1899a2SJed Brown 
1090d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_Shell(DM dm, PetscViewer v)
1091d71ae5a4SJacob Faibussowitsch {
10922d53ad75SBarry Smith   DM_Shell *shell = (DM_Shell *)dm->data;
10932d53ad75SBarry Smith 
10942d53ad75SBarry Smith   PetscFunctionBegin;
109501f8681bSStefano Zampini   if (shell->Xglobal) PetscCall(VecView(shell->Xglobal, v));
10963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10972d53ad75SBarry Smith }
10982d53ad75SBarry Smith 
1099d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLoad_Shell(DM dm, PetscViewer v)
1100d71ae5a4SJacob Faibussowitsch {
11012d53ad75SBarry Smith   DM_Shell *shell = (DM_Shell *)dm->data;
11022d53ad75SBarry Smith 
11032d53ad75SBarry Smith   PetscFunctionBegin;
11049566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &shell->Xglobal));
11059566063dSJacob Faibussowitsch   PetscCall(VecLoad(shell->Xglobal, v));
11063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11072d53ad75SBarry Smith }
1108fe1899a2SJed Brown 
1109d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Shell(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
1110d71ae5a4SJacob Faibussowitsch {
11116e44b4cfSMatthew G. Knepley   PetscFunctionBegin;
11129566063dSJacob Faibussowitsch   if (subdm) PetscCall(DMShellCreate(PetscObjectComm((PetscObject)dm), subdm));
11139566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm));
11143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11156e44b4cfSMatthew G. Knepley }
11166e44b4cfSMatthew G. Knepley 
1117d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Shell(DM dm)
1118d71ae5a4SJacob Faibussowitsch {
1119fe1899a2SJed Brown   DM_Shell *shell;
1120fe1899a2SJed Brown 
1121fe1899a2SJed Brown   PetscFunctionBegin;
11224dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&shell));
11238c87107bSJed Brown   dm->data = shell;
1124fe1899a2SJed Brown 
11258c87107bSJed Brown   dm->ops->destroy            = DMDestroy_Shell;
11268c87107bSJed Brown   dm->ops->createglobalvector = DMCreateGlobalVector_Shell;
1127dc43b69eSJed Brown   dm->ops->createlocalvector  = DMCreateLocalVector_Shell;
11288c87107bSJed Brown   dm->ops->creatematrix       = DMCreateMatrix_Shell;
11292d53ad75SBarry Smith   dm->ops->view               = DMView_Shell;
11302d53ad75SBarry Smith   dm->ops->load               = DMLoad_Shell;
11317a108d1dSBarry Smith   dm->ops->globaltolocalbegin = DMGlobalToLocalBeginDefaultShell;
11327a108d1dSBarry Smith   dm->ops->globaltolocalend   = DMGlobalToLocalEndDefaultShell;
113355daaa54SRichard Tran Mills   dm->ops->localtoglobalbegin = DMLocalToGlobalBeginDefaultShell;
113455daaa54SRichard Tran Mills   dm->ops->localtoglobalend   = DMLocalToGlobalEndDefaultShell;
113563731094SRichard Tran Mills   dm->ops->localtolocalbegin  = DMLocalToLocalBeginDefaultShell;
113663731094SRichard Tran Mills   dm->ops->localtolocalend    = DMLocalToLocalEndDefaultShell;
11376e44b4cfSMatthew G. Knepley   dm->ops->createsubdm        = DMCreateSubDM_Shell;
11389566063dSJacob Faibussowitsch   PetscCall(DMSetMatType(dm, MATDENSE));
11393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1140fe1899a2SJed Brown }
1141fe1899a2SJed Brown 
1142fe1899a2SJed Brown /*@
1143*20f4b53cSBarry Smith     DMShellCreate - Creates a `DMSHELL` object, used to manage user-defined problem data
1144fe1899a2SJed Brown 
1145d083f849SBarry Smith     Collective
1146fe1899a2SJed Brown 
1147fe1899a2SJed Brown     Input Parameter:
1148fe1899a2SJed Brown .   comm - the processors that will share the global vector
1149fe1899a2SJed Brown 
1150fe1899a2SJed Brown     Output Parameters:
1151*20f4b53cSBarry Smith .   shell - the `DMSHELL`
1152fe1899a2SJed Brown 
1153fe1899a2SJed Brown     Level: advanced
1154fe1899a2SJed Brown 
1155db781477SPatrick Sanan .seealso `DMDestroy()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`, `DMShellSetContext()`, `DMShellGetContext()`
1156fe1899a2SJed Brown @*/
1157d71ae5a4SJacob Faibussowitsch PetscErrorCode DMShellCreate(MPI_Comm comm, DM *dm)
1158d71ae5a4SJacob Faibussowitsch {
1159fe1899a2SJed Brown   PetscFunctionBegin;
1160fe1899a2SJed Brown   PetscValidPointer(dm, 2);
11619566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
11629566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMSHELL));
11639566063dSJacob Faibussowitsch   PetscCall(DMSetUp(*dm));
11643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1165fe1899a2SJed Brown }
1166