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