xref: /petsc/src/dm/impls/shell/dmshell.c (revision 07475bc16356fc37e8c66fcce1957fb7d8feef24)
1fe1899a2SJed Brown #include <petscdmshell.h>       /*I    "petscdmshell.h"  I*/
2*07475bc1SBarry Smith #include <petscmat.h>
3*07475bc1SBarry Smith #include <petsc-private/dmimpl.h>
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;
34ad6bc421SBarry Smith   /* the check below is tacky and incomplete */
35fe1899a2SJed Brown   if (mtype) {
36ad6bc421SBarry Smith     PetscBool flg,aij,seqaij,mpiaij;
37251f4c67SDmitry Karpeev     ierr = PetscObjectTypeCompare((PetscObject)A,mtype,&flg);CHKERRQ(ierr);
38ad6bc421SBarry Smith     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
39ad6bc421SBarry Smith     ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&mpiaij);CHKERRQ(ierr);
40ad6bc421SBarry Smith     ierr = PetscStrcmp(mtype,MATAIJ,&aij);CHKERRQ(ierr);
41ad6bc421SBarry Smith     if (!flg) {
42ad6bc421SBarry Smith       if (!(aij & (seqaij || mpiaij))) SETERRQ2(((PetscObject)dm)->comm,PETSC_ERR_ARG_NOTSAMETYPE,"Requested matrix of type %s, but only %s available",mtype,((PetscObject)A)->type_name);
43ad6bc421SBarry Smith     }
44fe1899a2SJed Brown   }
45fe1899a2SJed Brown   if (((PetscObject)A)->refct < 2) { /* We have an exclusive reference so we can give it out */
46fe1899a2SJed Brown     ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
47fe1899a2SJed Brown     ierr = MatZeroEntries(A);CHKERRQ(ierr);
48fe1899a2SJed Brown     *J = A;
49fe1899a2SJed Brown   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
50fe1899a2SJed Brown     ierr = MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,J);CHKERRQ(ierr);
51fe1899a2SJed Brown     ierr = MatZeroEntries(*J);CHKERRQ(ierr);
52fe1899a2SJed Brown   }
53fe1899a2SJed Brown   PetscFunctionReturn(0);
54fe1899a2SJed Brown }
55fe1899a2SJed Brown 
56fe1899a2SJed Brown #undef __FUNCT__
57fe1899a2SJed Brown #define __FUNCT__ "DMCreateGlobalVector_Shell"
58fe1899a2SJed Brown PetscErrorCode DMCreateGlobalVector_Shell(DM dm,Vec *gvec)
59fe1899a2SJed Brown {
60fe1899a2SJed Brown   PetscErrorCode ierr;
61fe1899a2SJed Brown   DM_Shell       *shell = (DM_Shell*)dm->data;
62fe1899a2SJed Brown   Vec            X;
63fe1899a2SJed Brown 
64fe1899a2SJed Brown   PetscFunctionBegin;
65fe1899a2SJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
66fe1899a2SJed Brown   PetscValidPointer(gvec,2);
67fe1899a2SJed Brown   *gvec = 0;
68fe1899a2SJed Brown   X = shell->Xglobal;
698c87107bSJed Brown   if (!X) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_USER,"Must call DMShellSetGlobalVector() or DMShellSetCreateGlobalVector()");
70fe1899a2SJed Brown   if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */
71fe1899a2SJed Brown     ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
72fe1899a2SJed Brown     ierr = VecZeroEntries(X);CHKERRQ(ierr);
73fe1899a2SJed Brown     *gvec = X;
74fe1899a2SJed Brown   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
75fe1899a2SJed Brown     ierr = VecDuplicate(X,gvec);CHKERRQ(ierr);
76fe1899a2SJed Brown     ierr = VecZeroEntries(*gvec);CHKERRQ(ierr);
77fe1899a2SJed Brown   }
78c688c046SMatthew G Knepley   ierr = VecSetDM(*gvec,dm);CHKERRQ(ierr);
79fe1899a2SJed Brown   PetscFunctionReturn(0);
80fe1899a2SJed Brown }
81fe1899a2SJed Brown 
82fe1899a2SJed Brown #undef __FUNCT__
83fe1899a2SJed Brown #define __FUNCT__ "DMShellSetMatrix"
84fe1899a2SJed Brown /*@
85fe1899a2SJed Brown    DMShellSetMatrix - sets a template matrix associated with the DMShell
86fe1899a2SJed Brown 
87fe1899a2SJed Brown    Collective
88fe1899a2SJed Brown 
89fe1899a2SJed Brown    Input Arguments:
90fe1899a2SJed Brown +  dm - shell DM
91fe1899a2SJed Brown -  J - template matrix
92fe1899a2SJed Brown 
93fe1899a2SJed Brown    Level: advanced
94fe1899a2SJed Brown 
95fe1899a2SJed Brown .seealso: DMCreateMatrix(), DMShellSetCreateMatrix()
96fe1899a2SJed Brown @*/
97fe1899a2SJed Brown PetscErrorCode DMShellSetMatrix(DM dm,Mat J)
98fe1899a2SJed Brown {
99fe1899a2SJed Brown   DM_Shell *shell = (DM_Shell*)dm->data;
100fe1899a2SJed Brown   PetscErrorCode ierr;
1018c87107bSJed Brown   PetscBool isshell;
102fe1899a2SJed Brown 
103fe1899a2SJed Brown   PetscFunctionBegin;
1048c87107bSJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1058c87107bSJed Brown   PetscValidHeaderSpecific(J,MAT_CLASSID,2);
106251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
1078c87107bSJed Brown   if (!isshell) PetscFunctionReturn(0);
108fe1899a2SJed Brown   ierr = PetscObjectReference((PetscObject)J);CHKERRQ(ierr);
109fe1899a2SJed Brown   ierr = MatDestroy(&shell->A);CHKERRQ(ierr);
110fe1899a2SJed Brown   shell->A = J;
111fe1899a2SJed Brown   PetscFunctionReturn(0);
112fe1899a2SJed Brown }
113fe1899a2SJed Brown 
114fe1899a2SJed Brown #undef __FUNCT__
115fe1899a2SJed Brown #define __FUNCT__ "DMShellSetCreateMatrix"
116fe1899a2SJed Brown /*@C
117fe1899a2SJed Brown    DMShellSetCreateMatrix - sets the routine to create a matrix associated with the shell DM
118fe1899a2SJed Brown 
119fe1899a2SJed Brown    Logically Collective on DM
120fe1899a2SJed Brown 
121fe1899a2SJed Brown    Input Arguments:
122fe1899a2SJed Brown +  dm - the shell DM
123fe1899a2SJed Brown -  func - the function to create a matrix
124fe1899a2SJed Brown 
125fe1899a2SJed Brown    Level: advanced
126fe1899a2SJed Brown 
127fe1899a2SJed Brown .seealso: DMCreateMatrix(), DMShellSetMatrix()
128fe1899a2SJed Brown @*/
12919fd82e9SBarry Smith PetscErrorCode DMShellSetCreateMatrix(DM dm,PetscErrorCode (*func)(DM,MatType,Mat*))
130fe1899a2SJed Brown {
131fe1899a2SJed Brown 
132fe1899a2SJed Brown   PetscFunctionBegin;
133fe1899a2SJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
134fe1899a2SJed Brown   dm->ops->creatematrix = func;
135fe1899a2SJed Brown   PetscFunctionReturn(0);
136fe1899a2SJed Brown }
137fe1899a2SJed Brown 
138fe1899a2SJed Brown #undef __FUNCT__
139fe1899a2SJed Brown #define __FUNCT__ "DMShellSetGlobalVector"
140fe1899a2SJed Brown /*@
141fe1899a2SJed Brown    DMShellSetGlobalVector - sets a template global vector associated with the DMShell
142fe1899a2SJed Brown 
143fe1899a2SJed Brown    Logically Collective on DM
144fe1899a2SJed Brown 
145fe1899a2SJed Brown    Input Arguments:
146fe1899a2SJed Brown +  dm - shell DM
147fe1899a2SJed Brown -  X - template vector
148fe1899a2SJed Brown 
149fe1899a2SJed Brown    Level: advanced
150fe1899a2SJed Brown 
151fe1899a2SJed Brown .seealso: DMCreateGlobalVector(), DMShellSetMatrix(), DMShellSetCreateGlobalVector()
152fe1899a2SJed Brown @*/
153fe1899a2SJed Brown PetscErrorCode DMShellSetGlobalVector(DM dm,Vec X)
154fe1899a2SJed Brown {
155fe1899a2SJed Brown   DM_Shell *shell = (DM_Shell*)dm->data;
156fe1899a2SJed Brown   PetscErrorCode ierr;
1578c87107bSJed Brown   PetscBool isshell;
158fe1899a2SJed Brown 
159fe1899a2SJed Brown   PetscFunctionBegin;
1608c87107bSJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1618c87107bSJed Brown   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
162251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
1638c87107bSJed Brown   if (!isshell) PetscFunctionReturn(0);
164fe1899a2SJed Brown   ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
165fe1899a2SJed Brown   ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr);
166fe1899a2SJed Brown   shell->Xglobal = X;
167fe1899a2SJed Brown   PetscFunctionReturn(0);
168fe1899a2SJed Brown }
169fe1899a2SJed Brown 
170fe1899a2SJed Brown #undef __FUNCT__
171fe1899a2SJed Brown #define __FUNCT__ "DMShellSetCreateGlobalVector"
172fe1899a2SJed Brown /*@C
173fe1899a2SJed Brown    DMShellSetCreateGlobalVector - sets the routine to create a global vector associated with the shell DM
174fe1899a2SJed Brown 
175fe1899a2SJed Brown    Logically Collective
176fe1899a2SJed Brown 
177fe1899a2SJed Brown    Input Arguments:
178fe1899a2SJed Brown +  dm - the shell DM
179fe1899a2SJed Brown -  func - the creation routine
180fe1899a2SJed Brown 
181fe1899a2SJed Brown    Level: advanced
182fe1899a2SJed Brown 
183fe1899a2SJed Brown .seealso: DMShellSetGlobalVector(), DMShellSetCreateMatrix()
184fe1899a2SJed Brown @*/
185fe1899a2SJed Brown PetscErrorCode DMShellSetCreateGlobalVector(DM dm,PetscErrorCode (*func)(DM,Vec*))
186fe1899a2SJed Brown {
187fe1899a2SJed Brown 
188fe1899a2SJed Brown   PetscFunctionBegin;
189fe1899a2SJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
190fe1899a2SJed Brown   dm->ops->createglobalvector = func;
191fe1899a2SJed Brown   PetscFunctionReturn(0);
192fe1899a2SJed Brown }
193fe1899a2SJed Brown 
194fe1899a2SJed Brown #undef __FUNCT__
195fe1899a2SJed Brown #define __FUNCT__ "DMDestroy_Shell"
196fe1899a2SJed Brown static PetscErrorCode DMDestroy_Shell(DM dm)
197fe1899a2SJed Brown {
198fe1899a2SJed Brown   PetscErrorCode ierr;
199fe1899a2SJed Brown   DM_Shell       *shell = (DM_Shell*)dm->data;
200fe1899a2SJed Brown 
201fe1899a2SJed Brown   PetscFunctionBegin;
202fe1899a2SJed Brown   ierr = MatDestroy(&shell->A);CHKERRQ(ierr);
203fe1899a2SJed Brown   ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr);
2047b6ad80cSMatthew G Knepley   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
2057b6ad80cSMatthew G Knepley   ierr = PetscFree(shell);CHKERRQ(ierr);
206fe1899a2SJed Brown   PetscFunctionReturn(0);
207fe1899a2SJed Brown }
208fe1899a2SJed Brown 
2092d53ad75SBarry Smith #undef __FUNCT__
2102d53ad75SBarry Smith #define __FUNCT__ "DMView_Shell"
2112d53ad75SBarry Smith static PetscErrorCode DMView_Shell(DM dm,PetscViewer v)
2122d53ad75SBarry Smith {
2132d53ad75SBarry Smith   PetscErrorCode ierr;
2142d53ad75SBarry Smith   DM_Shell       *shell = (DM_Shell*)dm->data;
2152d53ad75SBarry Smith 
2162d53ad75SBarry Smith   PetscFunctionBegin;
2172d53ad75SBarry Smith   ierr = VecView(shell->Xglobal,v);CHKERRQ(ierr);
2182d53ad75SBarry Smith   PetscFunctionReturn(0);
2192d53ad75SBarry Smith }
2202d53ad75SBarry Smith 
2212d53ad75SBarry Smith #undef __FUNCT__
2222d53ad75SBarry Smith #define __FUNCT__ "DMLoad_Shell"
2232d53ad75SBarry Smith static PetscErrorCode DMLoad_Shell(DM dm,PetscViewer v)
2242d53ad75SBarry Smith {
2252d53ad75SBarry Smith   PetscErrorCode ierr;
2262d53ad75SBarry Smith   DM_Shell       *shell = (DM_Shell*)dm->data;
2272d53ad75SBarry Smith 
2282d53ad75SBarry Smith   PetscFunctionBegin;
2292d53ad75SBarry Smith   ierr = VecCreate(((PetscObject)dm)->comm,&shell->Xglobal);CHKERRQ(ierr);
2302d53ad75SBarry Smith   ierr = VecLoad(shell->Xglobal,v);CHKERRQ(ierr);
2312d53ad75SBarry Smith   PetscFunctionReturn(0);
2322d53ad75SBarry Smith }
233fe1899a2SJed Brown 
234fe1899a2SJed Brown #undef __FUNCT__
235fe1899a2SJed Brown #define __FUNCT__ "DMCreate_Shell"
2368c87107bSJed Brown PETSC_EXTERN_C PetscErrorCode  DMCreate_Shell(DM dm)
237fe1899a2SJed Brown {
238fe1899a2SJed Brown   PetscErrorCode ierr;
239fe1899a2SJed Brown   DM_Shell      *shell;
240fe1899a2SJed Brown 
241fe1899a2SJed Brown   PetscFunctionBegin;
2428c87107bSJed Brown   ierr = PetscNewLog(dm,DM_Shell,&shell);CHKERRQ(ierr);
2438c87107bSJed Brown   dm->data = shell;
244fe1899a2SJed Brown 
2458c87107bSJed Brown   ierr = PetscObjectChangeTypeName((PetscObject)dm,DMSHELL);CHKERRQ(ierr);
2468c87107bSJed Brown   dm->ops->destroy            = DMDestroy_Shell;
2478c87107bSJed Brown   dm->ops->createglobalvector = DMCreateGlobalVector_Shell;
2488c87107bSJed Brown   dm->ops->creatematrix       = DMCreateMatrix_Shell;
2492d53ad75SBarry Smith   dm->ops->view               = DMView_Shell;
2502d53ad75SBarry Smith   dm->ops->load               = DMLoad_Shell;
251fe1899a2SJed Brown   PetscFunctionReturn(0);
252fe1899a2SJed Brown }
253fe1899a2SJed Brown 
254fe1899a2SJed Brown #undef __FUNCT__
255fe1899a2SJed Brown #define __FUNCT__ "DMShellCreate"
256fe1899a2SJed Brown /*@
257fe1899a2SJed Brown     DMShellCreate - Creates a shell DM object, used to manage user-defined problem data
258fe1899a2SJed Brown 
259fe1899a2SJed Brown     Collective on MPI_Comm
260fe1899a2SJed Brown 
261fe1899a2SJed Brown     Input Parameter:
262fe1899a2SJed Brown .   comm - the processors that will share the global vector
263fe1899a2SJed Brown 
264fe1899a2SJed Brown     Output Parameters:
265fe1899a2SJed Brown .   shell - the shell DM
266fe1899a2SJed Brown 
267fe1899a2SJed Brown     Level: advanced
268fe1899a2SJed Brown 
269fe1899a2SJed Brown .seealso DMDestroy(), DMCreateGlobalVector()
270fe1899a2SJed Brown @*/
271fe1899a2SJed Brown PetscErrorCode  DMShellCreate(MPI_Comm comm,DM *dm)
272fe1899a2SJed Brown {
273fe1899a2SJed Brown   PetscErrorCode ierr;
274fe1899a2SJed Brown 
275fe1899a2SJed Brown   PetscFunctionBegin;
276fe1899a2SJed Brown   PetscValidPointer(dm,2);
277fe1899a2SJed Brown   ierr = DMCreate(comm,dm);CHKERRQ(ierr);
278fe1899a2SJed Brown   ierr = DMSetType(*dm,DMSHELL);CHKERRQ(ierr);
279fe1899a2SJed Brown   PetscFunctionReturn(0);
280fe1899a2SJed Brown }
281