xref: /petsc/src/dm/impls/shell/dmshell.c (revision c688c0463f6c25494d0d243b2a43b2b3454e025c)
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   }
72*c688c046SMatthew 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 
203fe1899a2SJed Brown 
204fe1899a2SJed Brown #undef __FUNCT__
205fe1899a2SJed Brown #define __FUNCT__ "DMCreate_Shell"
2068c87107bSJed Brown PETSC_EXTERN_C PetscErrorCode  DMCreate_Shell(DM dm)
207fe1899a2SJed Brown {
208fe1899a2SJed Brown   PetscErrorCode ierr;
209fe1899a2SJed Brown   DM_Shell      *shell;
210fe1899a2SJed Brown 
211fe1899a2SJed Brown   PetscFunctionBegin;
2128c87107bSJed Brown   ierr = PetscNewLog(dm,DM_Shell,&shell);CHKERRQ(ierr);
2138c87107bSJed Brown   dm->data = shell;
214fe1899a2SJed Brown 
2158c87107bSJed Brown   ierr = PetscObjectChangeTypeName((PetscObject)dm,DMSHELL);CHKERRQ(ierr);
2168c87107bSJed Brown   dm->ops->destroy            = DMDestroy_Shell;
2178c87107bSJed Brown   dm->ops->createglobalvector = DMCreateGlobalVector_Shell;
2188c87107bSJed Brown   dm->ops->creatematrix       = DMCreateMatrix_Shell;
219fe1899a2SJed Brown   PetscFunctionReturn(0);
220fe1899a2SJed Brown }
221fe1899a2SJed Brown 
222fe1899a2SJed Brown #undef __FUNCT__
223fe1899a2SJed Brown #define __FUNCT__ "DMShellCreate"
224fe1899a2SJed Brown /*@
225fe1899a2SJed Brown     DMShellCreate - Creates a shell DM object, used to manage user-defined problem data
226fe1899a2SJed Brown 
227fe1899a2SJed Brown     Collective on MPI_Comm
228fe1899a2SJed Brown 
229fe1899a2SJed Brown     Input Parameter:
230fe1899a2SJed Brown .   comm - the processors that will share the global vector
231fe1899a2SJed Brown 
232fe1899a2SJed Brown     Output Parameters:
233fe1899a2SJed Brown .   shell - the shell DM
234fe1899a2SJed Brown 
235fe1899a2SJed Brown     Level: advanced
236fe1899a2SJed Brown 
237fe1899a2SJed Brown .seealso DMDestroy(), DMCreateGlobalVector()
238fe1899a2SJed Brown @*/
239fe1899a2SJed Brown PetscErrorCode  DMShellCreate(MPI_Comm comm,DM *dm)
240fe1899a2SJed Brown {
241fe1899a2SJed Brown   PetscErrorCode ierr;
242fe1899a2SJed Brown 
243fe1899a2SJed Brown   PetscFunctionBegin;
244fe1899a2SJed Brown   PetscValidPointer(dm,2);
245fe1899a2SJed Brown   ierr = DMCreate(comm,dm);CHKERRQ(ierr);
246fe1899a2SJed Brown   ierr = DMSetType(*dm,DMSHELL);CHKERRQ(ierr);
247fe1899a2SJed Brown   PetscFunctionReturn(0);
248fe1899a2SJed Brown }
249