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