xref: /petsc/src/dm/impls/shell/dmshell.c (revision 2d53ad75667bd9af5ca32c6f75ade56f24a4fbe1)
1fe1899a2SJed Brown #include <petscdmshell.h>       /*I    "petscdmshell.h"  I*/
2fe1899a2SJed Brown #include <petscmat.h>           /*I    "petscmat.h"      I*/
3b45d2f2cSJed Brown #include <petsc-private/dmimpl.h>     /*I    "petscdm.h"       I*/
4fe1899a2SJed Brown 
5fe1899a2SJed Brown typedef struct  {
6fe1899a2SJed Brown   Vec Xglobal;
7fe1899a2SJed Brown   Mat A;
8fe1899a2SJed Brown } DM_Shell;
9fe1899a2SJed Brown 
10fe1899a2SJed Brown #undef __FUNCT__
11fe1899a2SJed Brown #define __FUNCT__ "DMCreateMatrix_Shell"
1219fd82e9SBarry Smith static PetscErrorCode DMCreateMatrix_Shell(DM dm,MatType mtype,Mat *J)
13fe1899a2SJed Brown {
14fe1899a2SJed Brown   PetscErrorCode ierr;
15fe1899a2SJed Brown   DM_Shell       *shell = (DM_Shell*)dm->data;
16fe1899a2SJed Brown   Mat            A;
17fe1899a2SJed Brown 
18fe1899a2SJed Brown   PetscFunctionBegin;
19fe1899a2SJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
20fe1899a2SJed Brown   PetscValidPointer(J,3);
217bde9f88SJed Brown   if (!shell->A) {
227bde9f88SJed Brown     if (shell->Xglobal) {
237bde9f88SJed Brown       PetscInt m,M;
247bde9f88SJed Brown       ierr = PetscInfo(dm,"Naively creating matrix using global vector distribution without preallocation");CHKERRQ(ierr);
257bde9f88SJed Brown       ierr = VecGetSize(shell->Xglobal,&M);CHKERRQ(ierr);
267bde9f88SJed Brown       ierr = VecGetLocalSize(shell->Xglobal,&m);CHKERRQ(ierr);
277bde9f88SJed Brown       ierr = MatCreate(((PetscObject)dm)->comm,&shell->A);CHKERRQ(ierr);
287bde9f88SJed Brown       ierr = MatSetSizes(shell->A,m,m,M,M);CHKERRQ(ierr);
297bde9f88SJed Brown       if (mtype) {ierr = MatSetType(shell->A,mtype);CHKERRQ(ierr);}
307bde9f88SJed Brown       ierr = MatSetUp(shell->A);CHKERRQ(ierr);
317bde9f88SJed Brown     } else SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_USER,"Must call DMShellSetMatrix(), DMShellSetCreateMatrix(), or provide a vector");
327bde9f88SJed Brown   }
33fe1899a2SJed Brown   A = shell->A;
34fe1899a2SJed Brown   if (mtype) {
35fe1899a2SJed Brown     PetscBool flg;
36251f4c67SDmitry Karpeev     ierr = PetscObjectTypeCompare((PetscObject)A,mtype,&flg);CHKERRQ(ierr);
37fe1899a2SJed Brown     if (!flg) SETERRQ2(((PetscObject)dm)->comm,PETSC_ERR_ARG_NOTSAMETYPE,"Requested matrix of type %s, but only %s available",mtype,((PetscObject)A)->type_name);
38fe1899a2SJed Brown   }
39fe1899a2SJed Brown   if (((PetscObject)A)->refct < 2) { /* We have an exclusive reference so we can give it out */
40fe1899a2SJed Brown     ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
41fe1899a2SJed Brown     ierr = MatZeroEntries(A);CHKERRQ(ierr);
42fe1899a2SJed Brown     *J = A;
43fe1899a2SJed Brown   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
44fe1899a2SJed Brown     ierr = MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,J);CHKERRQ(ierr);
45fe1899a2SJed Brown     ierr = MatZeroEntries(*J);CHKERRQ(ierr);
46fe1899a2SJed Brown   }
47fe1899a2SJed Brown   PetscFunctionReturn(0);
48fe1899a2SJed Brown }
49fe1899a2SJed Brown 
50fe1899a2SJed Brown #undef __FUNCT__
51fe1899a2SJed Brown #define __FUNCT__ "DMCreateGlobalVector_Shell"
52fe1899a2SJed Brown PetscErrorCode DMCreateGlobalVector_Shell(DM dm,Vec *gvec)
53fe1899a2SJed Brown {
54fe1899a2SJed Brown   PetscErrorCode ierr;
55fe1899a2SJed Brown   DM_Shell       *shell = (DM_Shell*)dm->data;
56fe1899a2SJed Brown   Vec            X;
57fe1899a2SJed Brown 
58fe1899a2SJed Brown   PetscFunctionBegin;
59fe1899a2SJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
60fe1899a2SJed Brown   PetscValidPointer(gvec,2);
61fe1899a2SJed Brown   *gvec = 0;
62fe1899a2SJed Brown   X = shell->Xglobal;
638c87107bSJed Brown   if (!X) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_USER,"Must call DMShellSetGlobalVector() or DMShellSetCreateGlobalVector()");
64fe1899a2SJed Brown   if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */
65fe1899a2SJed Brown     ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
66fe1899a2SJed Brown     ierr = VecZeroEntries(X);CHKERRQ(ierr);
67fe1899a2SJed Brown     *gvec = X;
68fe1899a2SJed Brown   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
69fe1899a2SJed Brown     ierr = VecDuplicate(X,gvec);CHKERRQ(ierr);
70fe1899a2SJed Brown     ierr = VecZeroEntries(*gvec);CHKERRQ(ierr);
71fe1899a2SJed Brown   }
72c688c046SMatthew G Knepley   ierr = VecSetDM(*gvec,dm);CHKERRQ(ierr);
73fe1899a2SJed Brown   PetscFunctionReturn(0);
74fe1899a2SJed Brown }
75fe1899a2SJed Brown 
76fe1899a2SJed Brown #undef __FUNCT__
77fe1899a2SJed Brown #define __FUNCT__ "DMShellSetMatrix"
78fe1899a2SJed Brown /*@
79fe1899a2SJed Brown    DMShellSetMatrix - sets a template matrix associated with the DMShell
80fe1899a2SJed Brown 
81fe1899a2SJed Brown    Collective
82fe1899a2SJed Brown 
83fe1899a2SJed Brown    Input Arguments:
84fe1899a2SJed Brown +  dm - shell DM
85fe1899a2SJed Brown -  J - template matrix
86fe1899a2SJed Brown 
87fe1899a2SJed Brown    Level: advanced
88fe1899a2SJed Brown 
89fe1899a2SJed Brown .seealso: DMCreateMatrix(), DMShellSetCreateMatrix()
90fe1899a2SJed Brown @*/
91fe1899a2SJed Brown PetscErrorCode DMShellSetMatrix(DM dm,Mat J)
92fe1899a2SJed Brown {
93fe1899a2SJed Brown   DM_Shell *shell = (DM_Shell*)dm->data;
94fe1899a2SJed Brown   PetscErrorCode ierr;
958c87107bSJed Brown   PetscBool isshell;
96fe1899a2SJed Brown 
97fe1899a2SJed Brown   PetscFunctionBegin;
988c87107bSJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
998c87107bSJed Brown   PetscValidHeaderSpecific(J,MAT_CLASSID,2);
100251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
1018c87107bSJed Brown   if (!isshell) PetscFunctionReturn(0);
102fe1899a2SJed Brown   ierr = PetscObjectReference((PetscObject)J);CHKERRQ(ierr);
103fe1899a2SJed Brown   ierr = MatDestroy(&shell->A);CHKERRQ(ierr);
104fe1899a2SJed Brown   shell->A = J;
105fe1899a2SJed Brown   PetscFunctionReturn(0);
106fe1899a2SJed Brown }
107fe1899a2SJed Brown 
108fe1899a2SJed Brown #undef __FUNCT__
109fe1899a2SJed Brown #define __FUNCT__ "DMShellSetCreateMatrix"
110fe1899a2SJed Brown /*@C
111fe1899a2SJed Brown    DMShellSetCreateMatrix - sets the routine to create a matrix associated with the shell DM
112fe1899a2SJed Brown 
113fe1899a2SJed Brown    Logically Collective on DM
114fe1899a2SJed Brown 
115fe1899a2SJed Brown    Input Arguments:
116fe1899a2SJed Brown +  dm - the shell DM
117fe1899a2SJed Brown -  func - the function to create a matrix
118fe1899a2SJed Brown 
119fe1899a2SJed Brown    Level: advanced
120fe1899a2SJed Brown 
121fe1899a2SJed Brown .seealso: DMCreateMatrix(), DMShellSetMatrix()
122fe1899a2SJed Brown @*/
12319fd82e9SBarry Smith PetscErrorCode DMShellSetCreateMatrix(DM dm,PetscErrorCode (*func)(DM,MatType,Mat*))
124fe1899a2SJed Brown {
125fe1899a2SJed Brown 
126fe1899a2SJed Brown   PetscFunctionBegin;
127fe1899a2SJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
128fe1899a2SJed Brown   dm->ops->creatematrix = func;
129fe1899a2SJed Brown   PetscFunctionReturn(0);
130fe1899a2SJed Brown }
131fe1899a2SJed Brown 
132fe1899a2SJed Brown #undef __FUNCT__
133fe1899a2SJed Brown #define __FUNCT__ "DMShellSetGlobalVector"
134fe1899a2SJed Brown /*@
135fe1899a2SJed Brown    DMShellSetGlobalVector - sets a template global vector associated with the DMShell
136fe1899a2SJed Brown 
137fe1899a2SJed Brown    Logically Collective on DM
138fe1899a2SJed Brown 
139fe1899a2SJed Brown    Input Arguments:
140fe1899a2SJed Brown +  dm - shell DM
141fe1899a2SJed Brown -  X - template vector
142fe1899a2SJed Brown 
143fe1899a2SJed Brown    Level: advanced
144fe1899a2SJed Brown 
145fe1899a2SJed Brown .seealso: DMCreateGlobalVector(), DMShellSetMatrix(), DMShellSetCreateGlobalVector()
146fe1899a2SJed Brown @*/
147fe1899a2SJed Brown PetscErrorCode DMShellSetGlobalVector(DM dm,Vec X)
148fe1899a2SJed Brown {
149fe1899a2SJed Brown   DM_Shell *shell = (DM_Shell*)dm->data;
150fe1899a2SJed Brown   PetscErrorCode ierr;
1518c87107bSJed Brown   PetscBool isshell;
152fe1899a2SJed Brown 
153fe1899a2SJed Brown   PetscFunctionBegin;
1548c87107bSJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1558c87107bSJed Brown   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
156251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
1578c87107bSJed Brown   if (!isshell) PetscFunctionReturn(0);
158fe1899a2SJed Brown   ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
159fe1899a2SJed Brown   ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr);
160fe1899a2SJed Brown   shell->Xglobal = X;
161fe1899a2SJed Brown   PetscFunctionReturn(0);
162fe1899a2SJed Brown }
163fe1899a2SJed Brown 
164fe1899a2SJed Brown #undef __FUNCT__
165fe1899a2SJed Brown #define __FUNCT__ "DMShellSetCreateGlobalVector"
166fe1899a2SJed Brown /*@C
167fe1899a2SJed Brown    DMShellSetCreateGlobalVector - sets the routine to create a global vector associated with the shell DM
168fe1899a2SJed Brown 
169fe1899a2SJed Brown    Logically Collective
170fe1899a2SJed Brown 
171fe1899a2SJed Brown    Input Arguments:
172fe1899a2SJed Brown +  dm - the shell DM
173fe1899a2SJed Brown -  func - the creation routine
174fe1899a2SJed Brown 
175fe1899a2SJed Brown    Level: advanced
176fe1899a2SJed Brown 
177fe1899a2SJed Brown .seealso: DMShellSetGlobalVector(), DMShellSetCreateMatrix()
178fe1899a2SJed Brown @*/
179fe1899a2SJed Brown PetscErrorCode DMShellSetCreateGlobalVector(DM dm,PetscErrorCode (*func)(DM,Vec*))
180fe1899a2SJed Brown {
181fe1899a2SJed Brown 
182fe1899a2SJed Brown   PetscFunctionBegin;
183fe1899a2SJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
184fe1899a2SJed Brown   dm->ops->createglobalvector = func;
185fe1899a2SJed Brown   PetscFunctionReturn(0);
186fe1899a2SJed Brown }
187fe1899a2SJed Brown 
188fe1899a2SJed Brown #undef __FUNCT__
189fe1899a2SJed Brown #define __FUNCT__ "DMDestroy_Shell"
190fe1899a2SJed Brown static PetscErrorCode DMDestroy_Shell(DM dm)
191fe1899a2SJed Brown {
192fe1899a2SJed Brown   PetscErrorCode ierr;
193fe1899a2SJed Brown   DM_Shell       *shell = (DM_Shell*)dm->data;
194fe1899a2SJed Brown 
195fe1899a2SJed Brown   PetscFunctionBegin;
196fe1899a2SJed Brown   ierr = MatDestroy(&shell->A);CHKERRQ(ierr);
197fe1899a2SJed Brown   ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr);
1987b6ad80cSMatthew G Knepley   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
1997b6ad80cSMatthew G Knepley   ierr = PetscFree(shell);CHKERRQ(ierr);
200fe1899a2SJed Brown   PetscFunctionReturn(0);
201fe1899a2SJed Brown }
202fe1899a2SJed Brown 
203*2d53ad75SBarry Smith #undef __FUNCT__
204*2d53ad75SBarry Smith #define __FUNCT__ "DMView_Shell"
205*2d53ad75SBarry Smith static PetscErrorCode DMView_Shell(DM dm,PetscViewer v)
206*2d53ad75SBarry Smith {
207*2d53ad75SBarry Smith   PetscErrorCode ierr;
208*2d53ad75SBarry Smith   DM_Shell       *shell = (DM_Shell*)dm->data;
209*2d53ad75SBarry Smith 
210*2d53ad75SBarry Smith   PetscFunctionBegin;
211*2d53ad75SBarry Smith   ierr = VecView(shell->Xglobal,v);CHKERRQ(ierr);
212*2d53ad75SBarry Smith   PetscFunctionReturn(0);
213*2d53ad75SBarry Smith }
214*2d53ad75SBarry Smith 
215*2d53ad75SBarry Smith #undef __FUNCT__
216*2d53ad75SBarry Smith #define __FUNCT__ "DMLoad_Shell"
217*2d53ad75SBarry Smith static PetscErrorCode DMLoad_Shell(DM dm,PetscViewer v)
218*2d53ad75SBarry Smith {
219*2d53ad75SBarry Smith   PetscErrorCode ierr;
220*2d53ad75SBarry Smith   DM_Shell       *shell = (DM_Shell*)dm->data;
221*2d53ad75SBarry Smith 
222*2d53ad75SBarry Smith   PetscFunctionBegin;
223*2d53ad75SBarry Smith   ierr = VecCreate(((PetscObject)dm)->comm,&shell->Xglobal);CHKERRQ(ierr);
224*2d53ad75SBarry Smith   ierr = VecLoad(shell->Xglobal,v);CHKERRQ(ierr);
225*2d53ad75SBarry Smith   PetscFunctionReturn(0);
226*2d53ad75SBarry Smith }
227fe1899a2SJed Brown 
228fe1899a2SJed Brown #undef __FUNCT__
229fe1899a2SJed Brown #define __FUNCT__ "DMCreate_Shell"
2308c87107bSJed Brown PETSC_EXTERN_C PetscErrorCode  DMCreate_Shell(DM dm)
231fe1899a2SJed Brown {
232fe1899a2SJed Brown   PetscErrorCode ierr;
233fe1899a2SJed Brown   DM_Shell      *shell;
234fe1899a2SJed Brown 
235fe1899a2SJed Brown   PetscFunctionBegin;
2368c87107bSJed Brown   ierr = PetscNewLog(dm,DM_Shell,&shell);CHKERRQ(ierr);
2378c87107bSJed Brown   dm->data = shell;
238fe1899a2SJed Brown 
2398c87107bSJed Brown   ierr = PetscObjectChangeTypeName((PetscObject)dm,DMSHELL);CHKERRQ(ierr);
2408c87107bSJed Brown   dm->ops->destroy            = DMDestroy_Shell;
2418c87107bSJed Brown   dm->ops->createglobalvector = DMCreateGlobalVector_Shell;
2428c87107bSJed Brown   dm->ops->creatematrix       = DMCreateMatrix_Shell;
243*2d53ad75SBarry Smith   dm->ops->view               = DMView_Shell;
244*2d53ad75SBarry Smith   dm->ops->load               = DMLoad_Shell;
245fe1899a2SJed Brown   PetscFunctionReturn(0);
246fe1899a2SJed Brown }
247fe1899a2SJed Brown 
248fe1899a2SJed Brown #undef __FUNCT__
249fe1899a2SJed Brown #define __FUNCT__ "DMShellCreate"
250fe1899a2SJed Brown /*@
251fe1899a2SJed Brown     DMShellCreate - Creates a shell DM object, used to manage user-defined problem data
252fe1899a2SJed Brown 
253fe1899a2SJed Brown     Collective on MPI_Comm
254fe1899a2SJed Brown 
255fe1899a2SJed Brown     Input Parameter:
256fe1899a2SJed Brown .   comm - the processors that will share the global vector
257fe1899a2SJed Brown 
258fe1899a2SJed Brown     Output Parameters:
259fe1899a2SJed Brown .   shell - the shell DM
260fe1899a2SJed Brown 
261fe1899a2SJed Brown     Level: advanced
262fe1899a2SJed Brown 
263fe1899a2SJed Brown .seealso DMDestroy(), DMCreateGlobalVector()
264fe1899a2SJed Brown @*/
265fe1899a2SJed Brown PetscErrorCode  DMShellCreate(MPI_Comm comm,DM *dm)
266fe1899a2SJed Brown {
267fe1899a2SJed Brown   PetscErrorCode ierr;
268fe1899a2SJed Brown 
269fe1899a2SJed Brown   PetscFunctionBegin;
270fe1899a2SJed Brown   PetscValidPointer(dm,2);
271fe1899a2SJed Brown   ierr = DMCreate(comm,dm);CHKERRQ(ierr);
272fe1899a2SJed Brown   ierr = DMSetType(*dm,DMSHELL);CHKERRQ(ierr);
273fe1899a2SJed Brown   PetscFunctionReturn(0);
274fe1899a2SJed Brown }
275