xref: /petsc/src/dm/impls/shell/dmshell.c (revision 55daaa54699ee49b06f05d8aec7fa1c97c98aca7)
1fe1899a2SJed Brown #include <petscdmshell.h>       /*I    "petscdmshell.h"  I*/
207475bc1SBarry Smith #include <petscmat.h>
307475bc1SBarry Smith #include <petsc-private/dmimpl.h>
4fe1899a2SJed Brown 
5fe1899a2SJed Brown typedef struct  {
6fe1899a2SJed Brown   Vec        Xglobal;
7dc43b69eSJed Brown   Vec        Xlocal;
8fe1899a2SJed Brown   Mat        A;
981634712SRichard Tran Mills   VecScatter *gtol;
1081634712SRichard Tran Mills   VecScatter *ltog;
11fe1899a2SJed Brown } DM_Shell;
12fe1899a2SJed Brown 
13fe1899a2SJed Brown #undef __FUNCT__
147a108d1dSBarry Smith #define __FUNCT__ "DMGlobalToLocalBeginDefaultShell"
157a108d1dSBarry Smith /*@
167a108d1dSBarry Smith    DMGlobalToLocalBeginDefaultShell - Uses the GlobalToLocal VecScatter context set by the user to begin a global to local scatter
178d359177SBarry Smith    Collective
188d359177SBarry Smith 
198d359177SBarry Smith    Input Arguments:
208d359177SBarry Smith +  dm - shell DM
218d359177SBarry Smith .  g - global vector
228d359177SBarry Smith .  mode - InsertMode
238d359177SBarry Smith -  l - local vector
248d359177SBarry Smith 
257a108d1dSBarry Smith    Level: advanced
268d359177SBarry Smith 
277a108d1dSBarry 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.
287a108d1dSBarry Smith 
297a108d1dSBarry Smith .seealso: DMGlobalToLocalEndDefaultShell()
308d359177SBarry Smith @*/
317a108d1dSBarry Smith PetscErrorCode DMGlobalToLocalBeginDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
328d359177SBarry Smith {
338d359177SBarry Smith   PetscErrorCode ierr;
348d359177SBarry Smith   DM_Shell       *shell = (DM_Shell*)dm->data;
358d359177SBarry Smith 
368d359177SBarry Smith   PetscFunctionBegin;
377a108d1dSBarry Smith   if (!shell->gtol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
388d359177SBarry Smith   ierr = VecScatterBegin(*(shell->gtol),g,l,mode,SCATTER_FORWARD);CHKERRQ(ierr);
398d359177SBarry Smith   PetscFunctionReturn(0);
408d359177SBarry Smith }
418d359177SBarry Smith 
428d359177SBarry Smith #undef __FUNCT__
437a108d1dSBarry Smith #define __FUNCT__ "DMGlobalToLocalEndDefaultShell"
447a108d1dSBarry Smith /*@
457a108d1dSBarry Smith    DMGlobalToLocalEndDefaultShell - Uses the GlobalToLocal VecScatter context set by the user to end a global to local scatter
468d359177SBarry Smith    Collective
478d359177SBarry Smith 
488d359177SBarry Smith    Input Arguments:
498d359177SBarry Smith +  dm - shell DM
508d359177SBarry Smith .  g - global vector
518d359177SBarry Smith .  mode - InsertMode
528d359177SBarry Smith -  l - local vector
538d359177SBarry Smith 
547a108d1dSBarry Smith    Level: advanced
558d359177SBarry Smith 
567a108d1dSBarry Smith .seealso: DMGlobalToLocalBeginDefaultShell()
578d359177SBarry Smith @*/
587a108d1dSBarry Smith PetscErrorCode DMGlobalToLocalEndDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
598d359177SBarry Smith {
608d359177SBarry Smith   PetscErrorCode ierr;
618d359177SBarry Smith   DM_Shell       *shell = (DM_Shell*)dm->data;
628d359177SBarry Smith 
638d359177SBarry Smith   PetscFunctionBegin;
647a108d1dSBarry Smith    if (!shell->gtol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
657a108d1dSBarry Smith   ierr = VecScatterEnd(*(shell->gtol),g,l,mode,SCATTER_FORWARD);CHKERRQ(ierr);
668d359177SBarry Smith   PetscFunctionReturn(0);
678d359177SBarry Smith }
688d359177SBarry Smith 
698d359177SBarry Smith #undef __FUNCT__
70c5076b69SRichard Tran Mills #define __FUNCT__ "DMLocalToGlobalBeginDefaultShell"
71c5076b69SRichard Tran Mills /*@
72c5076b69SRichard Tran Mills    DMLocalToGlobalBeginDefaultShell - Uses the LocalToGlobal VecScatter context set by the user to begin a local to global scatter
73c5076b69SRichard Tran Mills    Collective
74c5076b69SRichard Tran Mills 
75c5076b69SRichard Tran Mills    Input Arguments:
76c5076b69SRichard Tran Mills +  dm - shell DM
77c5076b69SRichard Tran Mills .  l - local vector
78c5076b69SRichard Tran Mills .  mode - InsertMode
79c5076b69SRichard Tran Mills -  g - global vector
80c5076b69SRichard Tran Mills 
81c5076b69SRichard Tran Mills    Level: advanced
82c5076b69SRichard Tran Mills 
83c5076b69SRichard 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.
84c5076b69SRichard Tran Mills 
85c5076b69SRichard Tran Mills .seealso: DMLocalToGlobalEndDefaultShell()
86c5076b69SRichard Tran Mills @*/
87c5076b69SRichard Tran Mills PetscErrorCode DMLocalToGlobalBeginDefaultShell(DM dm,Vec l,InsertMode mode,Vec g)
88c5076b69SRichard Tran Mills {
89c5076b69SRichard Tran Mills   PetscErrorCode ierr;
90c5076b69SRichard Tran Mills   DM_Shell       *shell = (DM_Shell*)dm->data;
91c5076b69SRichard Tran Mills 
92c5076b69SRichard Tran Mills   PetscFunctionBegin;
93c5076b69SRichard Tran Mills   if (!shell->ltog) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()");
94c5076b69SRichard Tran Mills   ierr = VecScatterBegin(*(shell->ltog),l,g,mode,SCATTER_FORWARD);CHKERRQ(ierr);
95c5076b69SRichard Tran Mills   PetscFunctionReturn(0);
96c5076b69SRichard Tran Mills }
97c5076b69SRichard Tran Mills 
98c5076b69SRichard Tran Mills #undef __FUNCT__
99c5076b69SRichard Tran Mills #define __FUNCT__ "DMLocalToGlobalEndDefaultShell"
100c5076b69SRichard Tran Mills /*@
101c5076b69SRichard Tran Mills    DMLocalToGlobalEndDefaultShell - Uses the LocalToGlobal VecScatter context set by the user to end a local to global scatter
102c5076b69SRichard Tran Mills    Collective
103c5076b69SRichard Tran Mills 
104c5076b69SRichard Tran Mills    Input Arguments:
105c5076b69SRichard Tran Mills +  dm - shell DM
106c5076b69SRichard Tran Mills .  l - local vector
107c5076b69SRichard Tran Mills .  mode - InsertMode
108c5076b69SRichard Tran Mills -  g - global vector
109c5076b69SRichard Tran Mills 
110c5076b69SRichard Tran Mills    Level: advanced
111c5076b69SRichard Tran Mills 
112c5076b69SRichard Tran Mills .seealso: DMLocalToGlobalBeginDefaultShell()
113c5076b69SRichard Tran Mills @*/
114c5076b69SRichard Tran Mills PetscErrorCode DMLocalToGlobalEndDefaultShell(DM dm,Vec l,InsertMode mode,Vec g)
115c5076b69SRichard Tran Mills {
116c5076b69SRichard Tran Mills   PetscErrorCode ierr;
117c5076b69SRichard Tran Mills   DM_Shell       *shell = (DM_Shell*)dm->data;
118c5076b69SRichard Tran Mills 
119c5076b69SRichard Tran Mills   PetscFunctionBegin;
120c5076b69SRichard Tran Mills    if (!shell->ltog) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()");
121c5076b69SRichard Tran Mills   ierr = VecScatterEnd(*(shell->ltog),l,g,mode,SCATTER_FORWARD);CHKERRQ(ierr);
122c5076b69SRichard Tran Mills   PetscFunctionReturn(0);
123c5076b69SRichard Tran Mills }
124c5076b69SRichard Tran Mills 
125c5076b69SRichard Tran Mills 
126c5076b69SRichard Tran Mills #undef __FUNCT__
127fe1899a2SJed Brown #define __FUNCT__ "DMCreateMatrix_Shell"
12819fd82e9SBarry Smith static PetscErrorCode DMCreateMatrix_Shell(DM dm,MatType mtype,Mat *J)
129fe1899a2SJed Brown {
130fe1899a2SJed Brown   PetscErrorCode ierr;
131fe1899a2SJed Brown   DM_Shell       *shell = (DM_Shell*)dm->data;
132fe1899a2SJed Brown   Mat            A;
133fe1899a2SJed Brown 
134fe1899a2SJed Brown   PetscFunctionBegin;
135fe1899a2SJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
136fe1899a2SJed Brown   PetscValidPointer(J,3);
1377bde9f88SJed Brown   if (!shell->A) {
1387bde9f88SJed Brown     if (shell->Xglobal) {
1397bde9f88SJed Brown       PetscInt m,M;
1407bde9f88SJed Brown       ierr = PetscInfo(dm,"Naively creating matrix using global vector distribution without preallocation");CHKERRQ(ierr);
1417bde9f88SJed Brown       ierr = VecGetSize(shell->Xglobal,&M);CHKERRQ(ierr);
1427bde9f88SJed Brown       ierr = VecGetLocalSize(shell->Xglobal,&m);CHKERRQ(ierr);
143ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)dm),&shell->A);CHKERRQ(ierr);
1447bde9f88SJed Brown       ierr = MatSetSizes(shell->A,m,m,M,M);CHKERRQ(ierr);
1457bde9f88SJed Brown       if (mtype) {ierr = MatSetType(shell->A,mtype);CHKERRQ(ierr);}
1467bde9f88SJed Brown       ierr = MatSetUp(shell->A);CHKERRQ(ierr);
147ce94432eSBarry Smith     } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetMatrix(), DMShellSetCreateMatrix(), or provide a vector");
1487bde9f88SJed Brown   }
149fe1899a2SJed Brown   A = shell->A;
150ad6bc421SBarry Smith   /* the check below is tacky and incomplete */
151fe1899a2SJed Brown   if (mtype) {
152ad6bc421SBarry Smith     PetscBool flg,aij,seqaij,mpiaij;
153251f4c67SDmitry Karpeev     ierr = PetscObjectTypeCompare((PetscObject)A,mtype,&flg);CHKERRQ(ierr);
154ad6bc421SBarry Smith     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
155ad6bc421SBarry Smith     ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&mpiaij);CHKERRQ(ierr);
156ad6bc421SBarry Smith     ierr = PetscStrcmp(mtype,MATAIJ,&aij);CHKERRQ(ierr);
157ad6bc421SBarry Smith     if (!flg) {
158ce94432eSBarry Smith       if (!(aij & (seqaij || mpiaij))) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_NOTSAMETYPE,"Requested matrix of type %s, but only %s available",mtype,((PetscObject)A)->type_name);
159ad6bc421SBarry Smith     }
160fe1899a2SJed Brown   }
161fe1899a2SJed Brown   if (((PetscObject)A)->refct < 2) { /* We have an exclusive reference so we can give it out */
162fe1899a2SJed Brown     ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
163fe1899a2SJed Brown     ierr = MatZeroEntries(A);CHKERRQ(ierr);
164fe1899a2SJed Brown     *J   = A;
165fe1899a2SJed Brown   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
166fe1899a2SJed Brown     ierr = MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,J);CHKERRQ(ierr);
167fe1899a2SJed Brown     ierr = MatZeroEntries(*J);CHKERRQ(ierr);
168fe1899a2SJed Brown   }
169fe1899a2SJed Brown   PetscFunctionReturn(0);
170fe1899a2SJed Brown }
171fe1899a2SJed Brown 
172fe1899a2SJed Brown #undef __FUNCT__
173fe1899a2SJed Brown #define __FUNCT__ "DMCreateGlobalVector_Shell"
174fe1899a2SJed Brown PetscErrorCode DMCreateGlobalVector_Shell(DM dm,Vec *gvec)
175fe1899a2SJed Brown {
176fe1899a2SJed Brown   PetscErrorCode ierr;
177fe1899a2SJed Brown   DM_Shell       *shell = (DM_Shell*)dm->data;
178fe1899a2SJed Brown   Vec            X;
179fe1899a2SJed Brown 
180fe1899a2SJed Brown   PetscFunctionBegin;
181fe1899a2SJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
182fe1899a2SJed Brown   PetscValidPointer(gvec,2);
183fe1899a2SJed Brown   *gvec = 0;
184fe1899a2SJed Brown   X     = shell->Xglobal;
185ce94432eSBarry Smith   if (!X) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetGlobalVector() or DMShellSetCreateGlobalVector()");
186fe1899a2SJed Brown   if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */
187fe1899a2SJed Brown     ierr  = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
188fe1899a2SJed Brown     ierr  = VecZeroEntries(X);CHKERRQ(ierr);
189fe1899a2SJed Brown     *gvec = X;
190fe1899a2SJed Brown   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
191fe1899a2SJed Brown     ierr = VecDuplicate(X,gvec);CHKERRQ(ierr);
192fe1899a2SJed Brown     ierr = VecZeroEntries(*gvec);CHKERRQ(ierr);
193fe1899a2SJed Brown   }
194c688c046SMatthew G Knepley   ierr = VecSetDM(*gvec,dm);CHKERRQ(ierr);
195fe1899a2SJed Brown   PetscFunctionReturn(0);
196fe1899a2SJed Brown }
197fe1899a2SJed Brown 
198fe1899a2SJed Brown #undef __FUNCT__
199dc43b69eSJed Brown #define __FUNCT__ "DMCreateLocalVector_Shell"
200dc43b69eSJed Brown PetscErrorCode DMCreateLocalVector_Shell(DM dm,Vec *gvec)
201dc43b69eSJed Brown {
202dc43b69eSJed Brown   PetscErrorCode ierr;
203dc43b69eSJed Brown   DM_Shell       *shell = (DM_Shell*)dm->data;
204dc43b69eSJed Brown   Vec            X;
205dc43b69eSJed Brown 
206dc43b69eSJed Brown   PetscFunctionBegin;
207dc43b69eSJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
208dc43b69eSJed Brown   PetscValidPointer(gvec,2);
209dc43b69eSJed Brown   *gvec = 0;
210dc43b69eSJed Brown   X     = shell->Xlocal;
211ce94432eSBarry Smith   if (!X) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetLocalVector() or DMShellSetCreateLocalVector()");
212dc43b69eSJed Brown   if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */
213dc43b69eSJed Brown     ierr  = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
214dc43b69eSJed Brown     ierr  = VecZeroEntries(X);CHKERRQ(ierr);
215dc43b69eSJed Brown     *gvec = X;
216dc43b69eSJed Brown   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
217dc43b69eSJed Brown     ierr = VecDuplicate(X,gvec);CHKERRQ(ierr);
218dc43b69eSJed Brown     ierr = VecZeroEntries(*gvec);CHKERRQ(ierr);
219dc43b69eSJed Brown   }
2206e4cbd8bSMark F. Adams   ierr = VecSetDM(*gvec,dm);CHKERRQ(ierr);
221dc43b69eSJed Brown   PetscFunctionReturn(0);
222dc43b69eSJed Brown }
223dc43b69eSJed Brown 
224dc43b69eSJed Brown #undef __FUNCT__
225fe1899a2SJed Brown #define __FUNCT__ "DMShellSetMatrix"
226fe1899a2SJed Brown /*@
227fe1899a2SJed Brown    DMShellSetMatrix - sets a template matrix associated with the DMShell
228fe1899a2SJed Brown 
229fe1899a2SJed Brown    Collective
230fe1899a2SJed Brown 
231fe1899a2SJed Brown    Input Arguments:
232fe1899a2SJed Brown +  dm - shell DM
233fe1899a2SJed Brown -  J - template matrix
234fe1899a2SJed Brown 
235fe1899a2SJed Brown    Level: advanced
236fe1899a2SJed Brown 
237fe1899a2SJed Brown .seealso: DMCreateMatrix(), DMShellSetCreateMatrix()
238fe1899a2SJed Brown @*/
239fe1899a2SJed Brown PetscErrorCode DMShellSetMatrix(DM dm,Mat J)
240fe1899a2SJed Brown {
241fe1899a2SJed Brown   DM_Shell       *shell = (DM_Shell*)dm->data;
242fe1899a2SJed Brown   PetscErrorCode ierr;
2438c87107bSJed Brown   PetscBool      isshell;
244fe1899a2SJed Brown 
245fe1899a2SJed Brown   PetscFunctionBegin;
2468c87107bSJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2478c87107bSJed Brown   PetscValidHeaderSpecific(J,MAT_CLASSID,2);
248251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
2498c87107bSJed Brown   if (!isshell) PetscFunctionReturn(0);
250fe1899a2SJed Brown   ierr     = PetscObjectReference((PetscObject)J);CHKERRQ(ierr);
251fe1899a2SJed Brown   ierr     = MatDestroy(&shell->A);CHKERRQ(ierr);
252fe1899a2SJed Brown   shell->A = J;
253fe1899a2SJed Brown   PetscFunctionReturn(0);
254fe1899a2SJed Brown }
255fe1899a2SJed Brown 
256fe1899a2SJed Brown #undef __FUNCT__
257fe1899a2SJed Brown #define __FUNCT__ "DMShellSetCreateMatrix"
258fe1899a2SJed Brown /*@C
259fe1899a2SJed Brown    DMShellSetCreateMatrix - sets the routine to create a matrix associated with the shell DM
260fe1899a2SJed Brown 
261fe1899a2SJed Brown    Logically Collective on DM
262fe1899a2SJed Brown 
263fe1899a2SJed Brown    Input Arguments:
264fe1899a2SJed Brown +  dm - the shell DM
265fe1899a2SJed Brown -  func - the function to create a matrix
266fe1899a2SJed Brown 
267fe1899a2SJed Brown    Level: advanced
268fe1899a2SJed Brown 
269fe1899a2SJed Brown .seealso: DMCreateMatrix(), DMShellSetMatrix()
270fe1899a2SJed Brown @*/
27119fd82e9SBarry Smith PetscErrorCode DMShellSetCreateMatrix(DM dm,PetscErrorCode (*func)(DM,MatType,Mat*))
272fe1899a2SJed Brown {
273fe1899a2SJed Brown 
274fe1899a2SJed Brown   PetscFunctionBegin;
275fe1899a2SJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
276fe1899a2SJed Brown   dm->ops->creatematrix = func;
277fe1899a2SJed Brown   PetscFunctionReturn(0);
278fe1899a2SJed Brown }
279fe1899a2SJed Brown 
280fe1899a2SJed Brown #undef __FUNCT__
281fe1899a2SJed Brown #define __FUNCT__ "DMShellSetGlobalVector"
282fe1899a2SJed Brown /*@
283fe1899a2SJed Brown    DMShellSetGlobalVector - sets a template global vector associated with the DMShell
284fe1899a2SJed Brown 
285fe1899a2SJed Brown    Logically Collective on DM
286fe1899a2SJed Brown 
287fe1899a2SJed Brown    Input Arguments:
288fe1899a2SJed Brown +  dm - shell DM
289fe1899a2SJed Brown -  X - template vector
290fe1899a2SJed Brown 
291fe1899a2SJed Brown    Level: advanced
292fe1899a2SJed Brown 
293fe1899a2SJed Brown .seealso: DMCreateGlobalVector(), DMShellSetMatrix(), DMShellSetCreateGlobalVector()
294fe1899a2SJed Brown @*/
295fe1899a2SJed Brown PetscErrorCode DMShellSetGlobalVector(DM dm,Vec X)
296fe1899a2SJed Brown {
297fe1899a2SJed Brown   DM_Shell       *shell = (DM_Shell*)dm->data;
298fe1899a2SJed Brown   PetscErrorCode ierr;
2998c87107bSJed Brown   PetscBool      isshell;
300fe1899a2SJed Brown 
301fe1899a2SJed Brown   PetscFunctionBegin;
3028c87107bSJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3038c87107bSJed Brown   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
304251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
3058c87107bSJed Brown   if (!isshell) PetscFunctionReturn(0);
306fe1899a2SJed Brown   ierr           = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
307fe1899a2SJed Brown   ierr           = VecDestroy(&shell->Xglobal);CHKERRQ(ierr);
308fe1899a2SJed Brown   shell->Xglobal = X;
309fe1899a2SJed Brown   PetscFunctionReturn(0);
310fe1899a2SJed Brown }
311fe1899a2SJed Brown 
312fe1899a2SJed Brown #undef __FUNCT__
313fe1899a2SJed Brown #define __FUNCT__ "DMShellSetCreateGlobalVector"
314fe1899a2SJed Brown /*@C
315fe1899a2SJed Brown    DMShellSetCreateGlobalVector - sets the routine to create a global vector associated with the shell DM
316fe1899a2SJed Brown 
317fe1899a2SJed Brown    Logically Collective
318fe1899a2SJed Brown 
319fe1899a2SJed Brown    Input Arguments:
320fe1899a2SJed Brown +  dm - the shell DM
321fe1899a2SJed Brown -  func - the creation routine
322fe1899a2SJed Brown 
323fe1899a2SJed Brown    Level: advanced
324fe1899a2SJed Brown 
325fe1899a2SJed Brown .seealso: DMShellSetGlobalVector(), DMShellSetCreateMatrix()
326fe1899a2SJed Brown @*/
327fe1899a2SJed Brown PetscErrorCode DMShellSetCreateGlobalVector(DM dm,PetscErrorCode (*func)(DM,Vec*))
328fe1899a2SJed Brown {
329fe1899a2SJed Brown 
330fe1899a2SJed Brown   PetscFunctionBegin;
331fe1899a2SJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
332fe1899a2SJed Brown   dm->ops->createglobalvector = func;
333fe1899a2SJed Brown   PetscFunctionReturn(0);
334fe1899a2SJed Brown }
335fe1899a2SJed Brown 
336fe1899a2SJed Brown #undef __FUNCT__
337dc43b69eSJed Brown #define __FUNCT__ "DMShellSetLocalVector"
338dc43b69eSJed Brown /*@
339dc43b69eSJed Brown    DMShellSetLocalVector - sets a template local vector associated with the DMShell
340dc43b69eSJed Brown 
341dc43b69eSJed Brown    Logically Collective on DM
342dc43b69eSJed Brown 
343dc43b69eSJed Brown    Input Arguments:
344dc43b69eSJed Brown +  dm - shell DM
345dc43b69eSJed Brown -  X - template vector
346dc43b69eSJed Brown 
347dc43b69eSJed Brown    Level: advanced
348dc43b69eSJed Brown 
349dc43b69eSJed Brown .seealso: DMCreateLocalVector(), DMShellSetMatrix(), DMShellSetCreateLocalVector()
350dc43b69eSJed Brown @*/
351dc43b69eSJed Brown PetscErrorCode DMShellSetLocalVector(DM dm,Vec X)
352dc43b69eSJed Brown {
353dc43b69eSJed Brown   DM_Shell       *shell = (DM_Shell*)dm->data;
354dc43b69eSJed Brown   PetscErrorCode ierr;
355dc43b69eSJed Brown   PetscBool      isshell;
356dc43b69eSJed Brown 
357dc43b69eSJed Brown   PetscFunctionBegin;
358dc43b69eSJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
359dc43b69eSJed Brown   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
360dc43b69eSJed Brown   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
361dc43b69eSJed Brown   if (!isshell) PetscFunctionReturn(0);
362dc43b69eSJed Brown   ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
363dc43b69eSJed Brown   ierr = VecDestroy(&shell->Xlocal);CHKERRQ(ierr);
364dc43b69eSJed Brown   shell->Xlocal = X;
365dc43b69eSJed Brown   PetscFunctionReturn(0);
366dc43b69eSJed Brown }
367dc43b69eSJed Brown 
368dc43b69eSJed Brown #undef __FUNCT__
369dc43b69eSJed Brown #define __FUNCT__ "DMShellSetCreateLocalVector"
370dc43b69eSJed Brown /*@C
371dc43b69eSJed Brown    DMShellSetCreateLocalVector - sets the routine to create a local vector associated with the shell DM
372dc43b69eSJed Brown 
373dc43b69eSJed Brown    Logically Collective
374dc43b69eSJed Brown 
375dc43b69eSJed Brown    Input Arguments:
376dc43b69eSJed Brown +  dm - the shell DM
377dc43b69eSJed Brown -  func - the creation routine
378dc43b69eSJed Brown 
379dc43b69eSJed Brown    Level: advanced
380dc43b69eSJed Brown 
381dc43b69eSJed Brown .seealso: DMShellSetLocalVector(), DMShellSetCreateMatrix()
382dc43b69eSJed Brown @*/
383dc43b69eSJed Brown PetscErrorCode DMShellSetCreateLocalVector(DM dm,PetscErrorCode (*func)(DM,Vec*))
384dc43b69eSJed Brown {
385dc43b69eSJed Brown 
386dc43b69eSJed Brown   PetscFunctionBegin;
387dc43b69eSJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
388dc43b69eSJed Brown   dm->ops->createlocalvector = func;
389dc43b69eSJed Brown   PetscFunctionReturn(0);
390dc43b69eSJed Brown }
391dc43b69eSJed Brown 
392dc43b69eSJed Brown #undef __FUNCT__
3938339e6d0SRichard Tran Mills #define __FUNCT__ "DMShellSetGlobalToLocal"
3948339e6d0SRichard Tran Mills /*@C
3958339e6d0SRichard Tran Mills    DMShellSetGlobalToLocal - Sets the routines used to perform a global to local scatter
3968339e6d0SRichard Tran Mills 
3978339e6d0SRichard Tran Mills    Logically Collective on DM
3988339e6d0SRichard Tran Mills 
3998339e6d0SRichard Tran Mills    Input Arguments
4008339e6d0SRichard Tran Mills +  dm - the shell DM
4018339e6d0SRichard Tran Mills .  begin - the routine that begins the global to local scatter
4028339e6d0SRichard Tran Mills -  end - the routine that ends the global to local scatter
4038339e6d0SRichard Tran Mills 
4047a108d1dSBarry Smith    Notes: If these functions are not provided but DMShellSetGlobalToLocalVecScatter() is called then
4057a108d1dSBarry Smith    DMGlobalToLocalBeginDefaultShell() are used to to perform the transfers DMGlobalToLocalEndDefaultShell()
4067a108d1dSBarry Smith 
4078339e6d0SRichard Tran Mills    Level: advanced
4088339e6d0SRichard Tran Mills 
4097a108d1dSBarry Smith .seealso: DMShellSetLocalToGlobal(), DMGlobalToLocalBeginDefaultShell(), DMGlobalToLocalEndDefaultShell()
4108339e6d0SRichard Tran Mills @*/
4118339e6d0SRichard Tran Mills PetscErrorCode DMShellSetGlobalToLocal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
4128339e6d0SRichard Tran Mills   PetscFunctionBegin;
4138339e6d0SRichard Tran Mills   dm->ops->globaltolocalbegin = begin;
4148339e6d0SRichard Tran Mills   dm->ops->globaltolocalend = end;
4158339e6d0SRichard Tran Mills   PetscFunctionReturn(0);
4168339e6d0SRichard Tran Mills }
4178339e6d0SRichard Tran Mills 
4188339e6d0SRichard Tran Mills #undef __FUNCT__
4198339e6d0SRichard Tran Mills #define __FUNCT__ "DMShellSetLocalToGlobal"
4208339e6d0SRichard Tran Mills /*@C
4218339e6d0SRichard Tran Mills    DMShellSetLocalToGlobal - Sets the routines used to perform a local to global scatter
4228339e6d0SRichard Tran Mills 
4238339e6d0SRichard Tran Mills    Logically Collective on DM
4248339e6d0SRichard Tran Mills 
4258339e6d0SRichard Tran Mills    Input Arguments
4268339e6d0SRichard Tran Mills +  dm - the shell DM
4278339e6d0SRichard Tran Mills .  begin - the routine that begins the local to global scatter
4288339e6d0SRichard Tran Mills -  end - the routine that ends the local to global scatter
4298339e6d0SRichard Tran Mills 
4308339e6d0SRichard Tran Mills    Level: advanced
4318339e6d0SRichard Tran Mills 
4328339e6d0SRichard Tran Mills .seealso: DMShellSetGlobalToLocal()
4338339e6d0SRichard Tran Mills @*/
4348339e6d0SRichard Tran Mills PetscErrorCode DMShellSetLocalToGlobal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
4358339e6d0SRichard Tran Mills   PetscFunctionBegin;
4368339e6d0SRichard Tran Mills   dm->ops->localtoglobalbegin = begin;
4378339e6d0SRichard Tran Mills   dm->ops->localtoglobalend = end;
4388339e6d0SRichard Tran Mills   PetscFunctionReturn(0);
4398339e6d0SRichard Tran Mills }
4408339e6d0SRichard Tran Mills 
4418339e6d0SRichard Tran Mills #undef __FUNCT__
44281634712SRichard Tran Mills #define __FUNCT__ "DMShellSetGlobalToLocalVecScatter"
44381634712SRichard Tran Mills /*@
44481634712SRichard Tran Mills    DMShellSetGlobalToLocalVecScatter - Sets a VecScatter context for global to local communication
44581634712SRichard Tran Mills 
44681634712SRichard Tran Mills    Logically Collective on DM
44781634712SRichard Tran Mills 
44881634712SRichard Tran Mills    Input Arguments
44981634712SRichard Tran Mills +  dm - the shell DM
45081634712SRichard Tran Mills -  gtol - the global to local VecScatter context
45181634712SRichard Tran Mills 
45281634712SRichard Tran Mills    Level: advanced
45381634712SRichard Tran Mills 
45481634712SRichard Tran Mills .seealso: DMShellSetGlobalToLocal()
45581634712SRichard Tran Mills @*/
45681634712SRichard Tran Mills PetscErrorCode DMShellSetGlobalToLocalVecScatter(DM dm, VecScatter *gtol)
45781634712SRichard Tran Mills {
45881634712SRichard Tran Mills   DM_Shell       *shell = (DM_Shell*)dm->data;
45981634712SRichard Tran Mills 
460b300e4a8SRichard Tran Mills   PetscFunctionBegin;
46181634712SRichard Tran Mills   shell->gtol = gtol;
46281634712SRichard Tran Mills   PetscFunctionReturn(0);
46381634712SRichard Tran Mills }
46481634712SRichard Tran Mills 
46581634712SRichard Tran Mills #undef __FUNCT__
466988ea7d6SRichard Tran Mills #define __FUNCT__ "DMShellSetLocalToGlobalVecScatter"
467988ea7d6SRichard Tran Mills /*@
468988ea7d6SRichard Tran Mills    DMShellSetLocalToGlobalVecScatter - Sets a VecScatter context for local to global communication
469988ea7d6SRichard Tran Mills 
470988ea7d6SRichard Tran Mills    Logically Collective on DM
471988ea7d6SRichard Tran Mills 
472988ea7d6SRichard Tran Mills    Input Arguments
473988ea7d6SRichard Tran Mills +  dm - the shell DM
474988ea7d6SRichard Tran Mills -  ltog - the local to global VecScatter context
475988ea7d6SRichard Tran Mills 
476988ea7d6SRichard Tran Mills    Level: advanced
477988ea7d6SRichard Tran Mills 
478988ea7d6SRichard Tran Mills .seealso: DMShellSetLocalToGlobal()
479988ea7d6SRichard Tran Mills @*/
480988ea7d6SRichard Tran Mills PetscErrorCode DMShellSetLocalToGlobalVecScatter(DM dm, VecScatter *ltog)
481988ea7d6SRichard Tran Mills {
482988ea7d6SRichard Tran Mills   DM_Shell       *shell = (DM_Shell*)dm->data;
483988ea7d6SRichard Tran Mills 
484988ea7d6SRichard Tran Mills   PetscFunctionBegin;
485988ea7d6SRichard Tran Mills   shell->ltog = ltog;
486988ea7d6SRichard Tran Mills   PetscFunctionReturn(0);
487988ea7d6SRichard Tran Mills }
488988ea7d6SRichard Tran Mills 
489988ea7d6SRichard Tran Mills #undef __FUNCT__
490fe1899a2SJed Brown #define __FUNCT__ "DMDestroy_Shell"
491fe1899a2SJed Brown static PetscErrorCode DMDestroy_Shell(DM dm)
492fe1899a2SJed Brown {
493fe1899a2SJed Brown   PetscErrorCode ierr;
494fe1899a2SJed Brown   DM_Shell       *shell = (DM_Shell*)dm->data;
495fe1899a2SJed Brown 
496fe1899a2SJed Brown   PetscFunctionBegin;
497fe1899a2SJed Brown   ierr = MatDestroy(&shell->A);CHKERRQ(ierr);
498fe1899a2SJed Brown   ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr);
499dc43b69eSJed Brown   ierr = VecDestroy(&shell->Xlocal);CHKERRQ(ierr);
5007b6ad80cSMatthew G Knepley   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
5017b6ad80cSMatthew G Knepley   ierr = PetscFree(shell);CHKERRQ(ierr);
502fe1899a2SJed Brown   PetscFunctionReturn(0);
503fe1899a2SJed Brown }
504fe1899a2SJed Brown 
5052d53ad75SBarry Smith #undef __FUNCT__
5062d53ad75SBarry Smith #define __FUNCT__ "DMView_Shell"
5072d53ad75SBarry Smith static PetscErrorCode DMView_Shell(DM dm,PetscViewer v)
5082d53ad75SBarry Smith {
5092d53ad75SBarry Smith   PetscErrorCode ierr;
5102d53ad75SBarry Smith   DM_Shell       *shell = (DM_Shell*)dm->data;
5112d53ad75SBarry Smith 
5122d53ad75SBarry Smith   PetscFunctionBegin;
5132d53ad75SBarry Smith   ierr = VecView(shell->Xglobal,v);CHKERRQ(ierr);
5142d53ad75SBarry Smith   PetscFunctionReturn(0);
5152d53ad75SBarry Smith }
5162d53ad75SBarry Smith 
5172d53ad75SBarry Smith #undef __FUNCT__
5182d53ad75SBarry Smith #define __FUNCT__ "DMLoad_Shell"
5192d53ad75SBarry Smith static PetscErrorCode DMLoad_Shell(DM dm,PetscViewer v)
5202d53ad75SBarry Smith {
5212d53ad75SBarry Smith   PetscErrorCode ierr;
5222d53ad75SBarry Smith   DM_Shell       *shell = (DM_Shell*)dm->data;
5232d53ad75SBarry Smith 
5242d53ad75SBarry Smith   PetscFunctionBegin;
525ce94432eSBarry Smith   ierr = VecCreate(PetscObjectComm((PetscObject)dm),&shell->Xglobal);CHKERRQ(ierr);
5262d53ad75SBarry Smith   ierr = VecLoad(shell->Xglobal,v);CHKERRQ(ierr);
5272d53ad75SBarry Smith   PetscFunctionReturn(0);
5282d53ad75SBarry Smith }
529fe1899a2SJed Brown 
530fe1899a2SJed Brown #undef __FUNCT__
531fe1899a2SJed Brown #define __FUNCT__ "DMCreate_Shell"
5328cc058d9SJed Brown PETSC_EXTERN PetscErrorCode DMCreate_Shell(DM dm)
533fe1899a2SJed Brown {
534fe1899a2SJed Brown   PetscErrorCode ierr;
535fe1899a2SJed Brown   DM_Shell       *shell;
536fe1899a2SJed Brown 
537fe1899a2SJed Brown   PetscFunctionBegin;
5388c87107bSJed Brown   ierr     = PetscNewLog(dm,DM_Shell,&shell);CHKERRQ(ierr);
5398c87107bSJed Brown   dm->data = shell;
540fe1899a2SJed Brown 
5418c87107bSJed Brown   ierr = PetscObjectChangeTypeName((PetscObject)dm,DMSHELL);CHKERRQ(ierr);
5428865f1eaSKarl Rupp 
5438c87107bSJed Brown   dm->ops->destroy            = DMDestroy_Shell;
5448c87107bSJed Brown   dm->ops->createglobalvector = DMCreateGlobalVector_Shell;
545dc43b69eSJed Brown   dm->ops->createlocalvector  = DMCreateLocalVector_Shell;
5468c87107bSJed Brown   dm->ops->creatematrix       = DMCreateMatrix_Shell;
5472d53ad75SBarry Smith   dm->ops->view               = DMView_Shell;
5482d53ad75SBarry Smith   dm->ops->load               = DMLoad_Shell;
5497a108d1dSBarry Smith   dm->ops->globaltolocalbegin = DMGlobalToLocalBeginDefaultShell;
5507a108d1dSBarry Smith   dm->ops->globaltolocalend   = DMGlobalToLocalEndDefaultShell;
551*55daaa54SRichard Tran Mills   dm->ops->localtoglobalbegin = DMLocalToGlobalBeginDefaultShell;
552*55daaa54SRichard Tran Mills   dm->ops->localtoglobalend   = DMLocalToGlobalEndDefaultShell;
553fe1899a2SJed Brown   PetscFunctionReturn(0);
554fe1899a2SJed Brown }
555fe1899a2SJed Brown 
556fe1899a2SJed Brown #undef __FUNCT__
557fe1899a2SJed Brown #define __FUNCT__ "DMShellCreate"
558fe1899a2SJed Brown /*@
559fe1899a2SJed Brown     DMShellCreate - Creates a shell DM object, used to manage user-defined problem data
560fe1899a2SJed Brown 
561fe1899a2SJed Brown     Collective on MPI_Comm
562fe1899a2SJed Brown 
563fe1899a2SJed Brown     Input Parameter:
564fe1899a2SJed Brown .   comm - the processors that will share the global vector
565fe1899a2SJed Brown 
566fe1899a2SJed Brown     Output Parameters:
567fe1899a2SJed Brown .   shell - the shell DM
568fe1899a2SJed Brown 
569fe1899a2SJed Brown     Level: advanced
570fe1899a2SJed Brown 
571dc43b69eSJed Brown .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateLocalVector()
572fe1899a2SJed Brown @*/
573fe1899a2SJed Brown PetscErrorCode  DMShellCreate(MPI_Comm comm,DM *dm)
574fe1899a2SJed Brown {
575fe1899a2SJed Brown   PetscErrorCode ierr;
576fe1899a2SJed Brown 
577fe1899a2SJed Brown   PetscFunctionBegin;
578fe1899a2SJed Brown   PetscValidPointer(dm,2);
579fe1899a2SJed Brown   ierr = DMCreate(comm,dm);CHKERRQ(ierr);
580fe1899a2SJed Brown   ierr = DMSetType(*dm,DMSHELL);CHKERRQ(ierr);
581fe1899a2SJed Brown   PetscFunctionReturn(0);
582fe1899a2SJed Brown }
58381634712SRichard Tran Mills 
584