xref: /petsc/src/dm/impls/shell/dmshell.c (revision b45d2f2cb7e031d9c0de5873eca80614ca7b863b) !
1fe1899a2SJed Brown #include <petscdmshell.h>       /*I    "petscdmshell.h"  I*/
2fe1899a2SJed Brown #include <petscmat.h>           /*I    "petscmat.h"      I*/
3*b45d2f2cSJed 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"
12fe1899a2SJed Brown static PetscErrorCode DMCreateMatrix_Shell(DM dm,const 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);
21fe1899a2SJed Brown   A = shell->A;
22fe1899a2SJed Brown   if (!A) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_USER,"Must call DMShellSetMatrix() or DMShellSetCreateMatrix()");
23fe1899a2SJed Brown   if (mtype) {
24fe1899a2SJed Brown     PetscBool flg;
25fe1899a2SJed Brown     ierr = PetscTypeCompare((PetscObject)A,mtype,&flg);CHKERRQ(ierr);
26fe1899a2SJed 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);
27fe1899a2SJed Brown   }
28fe1899a2SJed Brown   if (((PetscObject)A)->refct < 2) { /* We have an exclusive reference so we can give it out */
29fe1899a2SJed Brown     ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
30fe1899a2SJed Brown     ierr = MatZeroEntries(A);CHKERRQ(ierr);
31fe1899a2SJed Brown     *J = A;
32fe1899a2SJed Brown   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
33fe1899a2SJed Brown     ierr = MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,J);CHKERRQ(ierr);
34fe1899a2SJed Brown     ierr = MatZeroEntries(*J);CHKERRQ(ierr);
35fe1899a2SJed Brown   }
36fe1899a2SJed Brown   PetscFunctionReturn(0);
37fe1899a2SJed Brown }
38fe1899a2SJed Brown 
39fe1899a2SJed Brown #undef __FUNCT__
40fe1899a2SJed Brown #define __FUNCT__ "DMCreateGlobalVector_Shell"
41fe1899a2SJed Brown PetscErrorCode DMCreateGlobalVector_Shell(DM dm,Vec *gvec)
42fe1899a2SJed Brown {
43fe1899a2SJed Brown   PetscErrorCode ierr;
44fe1899a2SJed Brown   DM_Shell       *shell = (DM_Shell*)dm->data;
45fe1899a2SJed Brown   Vec            X;
46fe1899a2SJed Brown 
47fe1899a2SJed Brown   PetscFunctionBegin;
48fe1899a2SJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
49fe1899a2SJed Brown   PetscValidPointer(gvec,2);
50fe1899a2SJed Brown   *gvec = 0;
51fe1899a2SJed Brown   X = shell->Xglobal;
528c87107bSJed Brown   if (!X) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_USER,"Must call DMShellSetGlobalVector() or DMShellSetCreateGlobalVector()");
53fe1899a2SJed Brown   if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */
54fe1899a2SJed Brown     ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
55fe1899a2SJed Brown     ierr = VecZeroEntries(X);CHKERRQ(ierr);
56fe1899a2SJed Brown     *gvec = X;
57fe1899a2SJed Brown   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
58fe1899a2SJed Brown     ierr = VecDuplicate(X,gvec);CHKERRQ(ierr);
59fe1899a2SJed Brown     ierr = VecZeroEntries(*gvec);CHKERRQ(ierr);
60fe1899a2SJed Brown   }
61fe1899a2SJed Brown   ierr = PetscObjectCompose((PetscObject)*gvec,"DM",(PetscObject)dm);CHKERRQ(ierr);
62fe1899a2SJed Brown   PetscFunctionReturn(0);
63fe1899a2SJed Brown }
64fe1899a2SJed Brown 
65fe1899a2SJed Brown #undef __FUNCT__
66fe1899a2SJed Brown #define __FUNCT__ "DMShellSetMatrix"
67fe1899a2SJed Brown /*@
68fe1899a2SJed Brown    DMShellSetMatrix - sets a template matrix associated with the DMShell
69fe1899a2SJed Brown 
70fe1899a2SJed Brown    Collective
71fe1899a2SJed Brown 
72fe1899a2SJed Brown    Input Arguments:
73fe1899a2SJed Brown +  dm - shell DM
74fe1899a2SJed Brown -  J - template matrix
75fe1899a2SJed Brown 
76fe1899a2SJed Brown    Level: advanced
77fe1899a2SJed Brown 
78fe1899a2SJed Brown .seealso: DMCreateMatrix(), DMShellSetCreateMatrix()
79fe1899a2SJed Brown @*/
80fe1899a2SJed Brown PetscErrorCode DMShellSetMatrix(DM dm,Mat J)
81fe1899a2SJed Brown {
82fe1899a2SJed Brown   DM_Shell *shell = (DM_Shell*)dm->data;
83fe1899a2SJed Brown   PetscErrorCode ierr;
848c87107bSJed Brown   PetscBool isshell;
85fe1899a2SJed Brown 
86fe1899a2SJed Brown   PetscFunctionBegin;
878c87107bSJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
888c87107bSJed Brown   PetscValidHeaderSpecific(J,MAT_CLASSID,2);
898c87107bSJed Brown   ierr = PetscTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
908c87107bSJed Brown   if (!isshell) PetscFunctionReturn(0);
91fe1899a2SJed Brown   ierr = PetscObjectReference((PetscObject)J);CHKERRQ(ierr);
92fe1899a2SJed Brown   ierr = MatDestroy(&shell->A);CHKERRQ(ierr);
93fe1899a2SJed Brown   shell->A = J;
94fe1899a2SJed Brown   PetscFunctionReturn(0);
95fe1899a2SJed Brown }
96fe1899a2SJed Brown 
97fe1899a2SJed Brown #undef __FUNCT__
98fe1899a2SJed Brown #define __FUNCT__ "DMShellSetCreateMatrix"
99fe1899a2SJed Brown /*@C
100fe1899a2SJed Brown    DMShellSetCreateMatrix - sets the routine to create a matrix associated with the shell DM
101fe1899a2SJed Brown 
102fe1899a2SJed Brown    Logically Collective on DM
103fe1899a2SJed Brown 
104fe1899a2SJed Brown    Input Arguments:
105fe1899a2SJed Brown +  dm - the shell DM
106fe1899a2SJed Brown -  func - the function to create a matrix
107fe1899a2SJed Brown 
108fe1899a2SJed Brown    Level: advanced
109fe1899a2SJed Brown 
110fe1899a2SJed Brown .seealso: DMCreateMatrix(), DMShellSetMatrix()
111fe1899a2SJed Brown @*/
112fe1899a2SJed Brown PetscErrorCode DMShellSetCreateMatrix(DM dm,PetscErrorCode (*func)(DM,const MatType,Mat*))
113fe1899a2SJed Brown {
114fe1899a2SJed Brown 
115fe1899a2SJed Brown   PetscFunctionBegin;
116fe1899a2SJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
117fe1899a2SJed Brown   dm->ops->creatematrix = func;
118fe1899a2SJed Brown   PetscFunctionReturn(0);
119fe1899a2SJed Brown }
120fe1899a2SJed Brown 
121fe1899a2SJed Brown #undef __FUNCT__
122fe1899a2SJed Brown #define __FUNCT__ "DMShellSetGlobalVector"
123fe1899a2SJed Brown /*@
124fe1899a2SJed Brown    DMShellSetGlobalVector - sets a template global vector associated with the DMShell
125fe1899a2SJed Brown 
126fe1899a2SJed Brown    Logically Collective on DM
127fe1899a2SJed Brown 
128fe1899a2SJed Brown    Input Arguments:
129fe1899a2SJed Brown +  dm - shell DM
130fe1899a2SJed Brown -  X - template vector
131fe1899a2SJed Brown 
132fe1899a2SJed Brown    Level: advanced
133fe1899a2SJed Brown 
134fe1899a2SJed Brown .seealso: DMCreateGlobalVector(), DMShellSetMatrix(), DMShellSetCreateGlobalVector()
135fe1899a2SJed Brown @*/
136fe1899a2SJed Brown PetscErrorCode DMShellSetGlobalVector(DM dm,Vec X)
137fe1899a2SJed Brown {
138fe1899a2SJed Brown   DM_Shell *shell = (DM_Shell*)dm->data;
139fe1899a2SJed Brown   PetscErrorCode ierr;
1408c87107bSJed Brown   PetscBool isshell;
141fe1899a2SJed Brown 
142fe1899a2SJed Brown   PetscFunctionBegin;
1438c87107bSJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1448c87107bSJed Brown   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
1458c87107bSJed Brown   ierr = PetscTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
1468c87107bSJed Brown   if (!isshell) PetscFunctionReturn(0);
147fe1899a2SJed Brown   ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
148fe1899a2SJed Brown   ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr);
149fe1899a2SJed Brown   shell->Xglobal = X;
150fe1899a2SJed Brown   PetscFunctionReturn(0);
151fe1899a2SJed Brown }
152fe1899a2SJed Brown 
153fe1899a2SJed Brown #undef __FUNCT__
154fe1899a2SJed Brown #define __FUNCT__ "DMShellSetCreateGlobalVector"
155fe1899a2SJed Brown /*@C
156fe1899a2SJed Brown    DMShellSetCreateGlobalVector - sets the routine to create a global vector associated with the shell DM
157fe1899a2SJed Brown 
158fe1899a2SJed Brown    Logically Collective
159fe1899a2SJed Brown 
160fe1899a2SJed Brown    Input Arguments:
161fe1899a2SJed Brown +  dm - the shell DM
162fe1899a2SJed Brown -  func - the creation routine
163fe1899a2SJed Brown 
164fe1899a2SJed Brown    Level: advanced
165fe1899a2SJed Brown 
166fe1899a2SJed Brown .seealso: DMShellSetGlobalVector(), DMShellSetCreateMatrix()
167fe1899a2SJed Brown @*/
168fe1899a2SJed Brown PetscErrorCode DMShellSetCreateGlobalVector(DM dm,PetscErrorCode (*func)(DM,Vec*))
169fe1899a2SJed Brown {
170fe1899a2SJed Brown 
171fe1899a2SJed Brown   PetscFunctionBegin;
172fe1899a2SJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
173fe1899a2SJed Brown   dm->ops->createglobalvector = func;
174fe1899a2SJed Brown   PetscFunctionReturn(0);
175fe1899a2SJed Brown }
176fe1899a2SJed Brown 
177fe1899a2SJed Brown #undef __FUNCT__
178fe1899a2SJed Brown #define __FUNCT__ "DMDestroy_Shell"
179fe1899a2SJed Brown static PetscErrorCode DMDestroy_Shell(DM dm)
180fe1899a2SJed Brown {
181fe1899a2SJed Brown   PetscErrorCode ierr;
182fe1899a2SJed Brown   DM_Shell       *shell = (DM_Shell*)dm->data;
183fe1899a2SJed Brown 
184fe1899a2SJed Brown   PetscFunctionBegin;
185fe1899a2SJed Brown   ierr = MatDestroy(&shell->A);CHKERRQ(ierr);
186fe1899a2SJed Brown   ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr);
187fe1899a2SJed Brown   ierr = PetscFree(dm->data);CHKERRQ(ierr);
188fe1899a2SJed Brown   PetscFunctionReturn(0);
189fe1899a2SJed Brown }
190fe1899a2SJed Brown 
191fe1899a2SJed Brown 
192fe1899a2SJed Brown #undef __FUNCT__
193fe1899a2SJed Brown #define __FUNCT__ "DMCreate_Shell"
1948c87107bSJed Brown PETSC_EXTERN_C PetscErrorCode  DMCreate_Shell(DM dm)
195fe1899a2SJed Brown {
196fe1899a2SJed Brown   PetscErrorCode ierr;
197fe1899a2SJed Brown   DM_Shell      *shell;
198fe1899a2SJed Brown 
199fe1899a2SJed Brown   PetscFunctionBegin;
2008c87107bSJed Brown   ierr = PetscNewLog(dm,DM_Shell,&shell);CHKERRQ(ierr);
2018c87107bSJed Brown   dm->data = shell;
202fe1899a2SJed Brown 
2038c87107bSJed Brown   ierr = PetscObjectChangeTypeName((PetscObject)dm,DMSHELL);CHKERRQ(ierr);
2048c87107bSJed Brown   dm->ops->destroy            = DMDestroy_Shell;
2058c87107bSJed Brown   dm->ops->createglobalvector = DMCreateGlobalVector_Shell;
2068c87107bSJed Brown   dm->ops->creatematrix       = DMCreateMatrix_Shell;
207fe1899a2SJed Brown   PetscFunctionReturn(0);
208fe1899a2SJed Brown }
209fe1899a2SJed Brown 
210fe1899a2SJed Brown #undef __FUNCT__
211fe1899a2SJed Brown #define __FUNCT__ "DMShellCreate"
212fe1899a2SJed Brown /*@
213fe1899a2SJed Brown     DMShellCreate - Creates a shell DM object, used to manage user-defined problem data
214fe1899a2SJed Brown 
215fe1899a2SJed Brown     Collective on MPI_Comm
216fe1899a2SJed Brown 
217fe1899a2SJed Brown     Input Parameter:
218fe1899a2SJed Brown .   comm - the processors that will share the global vector
219fe1899a2SJed Brown 
220fe1899a2SJed Brown     Output Parameters:
221fe1899a2SJed Brown .   shell - the shell DM
222fe1899a2SJed Brown 
223fe1899a2SJed Brown     Level: advanced
224fe1899a2SJed Brown 
225fe1899a2SJed Brown .seealso DMDestroy(), DMCreateGlobalVector()
226fe1899a2SJed Brown @*/
227fe1899a2SJed Brown PetscErrorCode  DMShellCreate(MPI_Comm comm,DM *dm)
228fe1899a2SJed Brown {
229fe1899a2SJed Brown   PetscErrorCode ierr;
230fe1899a2SJed Brown 
231fe1899a2SJed Brown   PetscFunctionBegin;
232fe1899a2SJed Brown   PetscValidPointer(dm,2);
233fe1899a2SJed Brown   ierr = DMCreate(comm,dm);CHKERRQ(ierr);
234fe1899a2SJed Brown   ierr = DMSetType(*dm,DMSHELL);CHKERRQ(ierr);
235fe1899a2SJed Brown   PetscFunctionReturn(0);
236fe1899a2SJed Brown }
237