1 #include <petsc/private/kspimpl.h> /*I "petscksp.h"  I*/
2 
3 PetscFunctionList KSPGuessList = NULL;
4 static PetscBool KSPGuessRegisterAllCalled;
5 
6 /*
7   KSPGuessRegister -  Adds a method for initial guess computation in Krylov subspace solver package.
8 
9    Not Collective
10 
11    Input Parameters:
12 +  name_solver - name of a new user-defined solver
13 -  routine_create - routine to create method context
14 
15    Notes:
16    KSPGuessRegister() may be called multiple times to add several user-defined solvers.
17 
18    Sample usage:
19 .vb
20    KSPGuessRegister("my_initial_guess",MyInitialGuessCreate);
21 .ve
22 
23    Then, it can be chosen with the procedural interface via
24 $     KSPSetGuessType(ksp,"my_initial_guess")
25    or at runtime via the option
26 $     -ksp_guess_type my_initial_guess
27 
28    Level: advanced
29 
30 .seealso: KSPGuess, KSPGuessRegisterAll()
31 
32 @*/
KSPGuessRegister(const char sname[],PetscErrorCode (* function)(KSPGuess))33 PetscErrorCode  KSPGuessRegister(const char sname[],PetscErrorCode (*function)(KSPGuess))
34 {
35   PetscErrorCode ierr;
36 
37   PetscFunctionBegin;
38   ierr = KSPInitializePackage();CHKERRQ(ierr);
39   ierr = PetscFunctionListAdd(&KSPGuessList,sname,function);CHKERRQ(ierr);
40   PetscFunctionReturn(0);
41 }
42 
43 /*
44   KSPGuessRegisterAll - Registers all KSPGuess implementations in the KSP package.
45 
46   Not Collective
47 
48   Level: advanced
49 
50 .seealso: KSPRegisterAll(),  KSPInitializePackage()
51 */
KSPGuessRegisterAll(void)52 PetscErrorCode KSPGuessRegisterAll(void)
53 {
54   PetscErrorCode ierr;
55 
56   PetscFunctionBegin;
57   if (KSPGuessRegisterAllCalled) PetscFunctionReturn(0);
58   KSPGuessRegisterAllCalled = PETSC_TRUE;
59   ierr = KSPGuessRegister(KSPGUESSFISCHER,KSPGuessCreate_Fischer);CHKERRQ(ierr);
60   ierr = KSPGuessRegister(KSPGUESSPOD,KSPGuessCreate_POD);CHKERRQ(ierr);
61   PetscFunctionReturn(0);
62 }
63 
64 /*@
65     KSPGuessSetFromOptions - Sets the options for a KSPGuess from the options database
66 
67     Collective on guess
68 
69     Input Parameter:
70 .    guess - KSPGuess object
71 
72    Level: intermediate
73 
74 .seealso: KSPGuess, KSPGetGuess(), KSPSetGuessType(), KSPGuessType
75 @*/
KSPGuessSetFromOptions(KSPGuess guess)76 PetscErrorCode KSPGuessSetFromOptions(KSPGuess guess)
77 {
78   PetscErrorCode ierr;
79 
80   PetscFunctionBegin;
81   PetscValidHeaderSpecific(guess,KSPGUESS_CLASSID,1);
82   if (guess->ops->setfromoptions) { ierr = (*guess->ops->setfromoptions)(guess);CHKERRQ(ierr); }
83   PetscFunctionReturn(0);
84 }
85 
86 /*@
87    KSPGuessDestroy - Destroys KSPGuess context.
88 
89    Collective on kspGuess
90 
91    Input Parameter:
92 .  guess - initial guess object
93 
94    Level: beginner
95 
96 .seealso: KSPGuessCreate(), KSPGuess, KSPGuessType
97 @*/
KSPGuessDestroy(KSPGuess * guess)98 PetscErrorCode  KSPGuessDestroy(KSPGuess *guess)
99 {
100   PetscErrorCode ierr;
101 
102   PetscFunctionBegin;
103   if (!*guess) PetscFunctionReturn(0);
104   PetscValidHeaderSpecific((*guess),KSPGUESS_CLASSID,1);
105   if (--((PetscObject)(*guess))->refct > 0) {*guess = NULL; PetscFunctionReturn(0);}
106   if ((*guess)->ops->destroy) { ierr = (*(*guess)->ops->destroy)(*guess);CHKERRQ(ierr); }
107   ierr = MatDestroy(&(*guess)->A);CHKERRQ(ierr);
108   ierr = PetscHeaderDestroy(guess);CHKERRQ(ierr);
109   PetscFunctionReturn(0);
110 }
111 
112 /*@C
113    KSPGuessView - View the KSPGuess object
114 
115    Logically Collective on guess
116 
117    Input Parameters:
118 +  guess  - the initial guess object for the Krylov method
119 -  viewer - the viewer object
120 
121    Notes:
122 
123   Level: intermediate
124 
125 .seealso: KSP, KSPGuess, KSPGuessType, KSPGuessRegister(), KSPGuessCreate(), PetscViewer
126 @*/
KSPGuessView(KSPGuess guess,PetscViewer view)127 PetscErrorCode  KSPGuessView(KSPGuess guess, PetscViewer view)
128 {
129   PetscErrorCode ierr;
130   PetscBool      ascii;
131 
132   PetscFunctionBegin;
133   PetscValidHeaderSpecific(guess,KSPGUESS_CLASSID,1);
134   if (!view) {
135     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)guess),&view);CHKERRQ(ierr);
136   }
137   PetscValidHeaderSpecific(view,PETSC_VIEWER_CLASSID,2);
138   PetscCheckSameComm(guess,1,view,2);
139   ierr = PetscObjectTypeCompare((PetscObject)view,PETSCVIEWERASCII,&ascii);CHKERRQ(ierr);
140   if (ascii) {
141     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)guess,view);CHKERRQ(ierr);
142     if (guess->ops->view) {
143       ierr = PetscViewerASCIIPushTab(view);CHKERRQ(ierr);
144       ierr = (*guess->ops->view)(guess,view);CHKERRQ(ierr);
145       ierr = PetscViewerASCIIPopTab(view);CHKERRQ(ierr);
146     }
147   }
148   PetscFunctionReturn(0);
149 }
150 
151 /*@
152    KSPGuessCreate - Creates the default KSPGuess context.
153 
154    Collective
155 
156    Input Parameter:
157 .  comm - MPI communicator
158 
159    Output Parameter:
160 .  guess - location to put the KSPGuess context
161 
162    Notes:
163    The default KSPGuess type is XXX
164 
165    Level: beginner
166 
167 .seealso: KSPSolve(), KSPGuessDestroy(), KSPGuess, KSPGuessType, KSP
168 @*/
KSPGuessCreate(MPI_Comm comm,KSPGuess * guess)169 PetscErrorCode  KSPGuessCreate(MPI_Comm comm,KSPGuess *guess)
170 {
171   KSPGuess       tguess;
172   PetscErrorCode ierr;
173 
174   PetscFunctionBegin;
175   PetscValidPointer(guess,2);
176   *guess = NULL;
177   ierr = KSPInitializePackage();CHKERRQ(ierr);
178   ierr = PetscHeaderCreate(tguess,KSPGUESS_CLASSID,"KSPGuess","Initial guess for Krylov Method","KSPGuess",comm,KSPGuessDestroy,KSPGuessView);CHKERRQ(ierr);
179   tguess->omatstate = -1;
180   *guess = tguess;
181   PetscFunctionReturn(0);
182 }
183 
184 /*@C
185    KSPGuessSetType - Sets the type of a KSPGuess
186 
187    Logically Collective on guess
188 
189    Input Parameters:
190 +  guess - the initial guess object for the Krylov method
191 -  type  - a known KSPGuess method
192 
193    Options Database Key:
194 .  -ksp_guess_type  <method> - Sets the method; use -help for a list
195     of available methods
196 
197    Notes:
198 
199   Level: intermediate
200 
201 .seealso: KSP, KSPGuess, KSPGuessType, KSPGuessRegister(), KSPGuessCreate()
202 
203 @*/
KSPGuessSetType(KSPGuess guess,KSPGuessType type)204 PetscErrorCode  KSPGuessSetType(KSPGuess guess, KSPGuessType type)
205 {
206   PetscErrorCode ierr,(*r)(KSPGuess);
207   PetscBool      match;
208 
209   PetscFunctionBegin;
210   PetscValidHeaderSpecific(guess,KSPGUESS_CLASSID,1);
211   PetscValidCharPointer(type,2);
212 
213   ierr = PetscObjectTypeCompare((PetscObject)guess,type,&match);CHKERRQ(ierr);
214   if (match) PetscFunctionReturn(0);
215 
216   ierr =  PetscFunctionListFind(KSPGuessList,type,&r);CHKERRQ(ierr);
217   if (!r) SETERRQ1(PetscObjectComm((PetscObject)guess),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested KSPGuess type %s",type);
218   if (guess->ops->destroy) {
219     ierr                = (*guess->ops->destroy)(guess);CHKERRQ(ierr);
220     guess->ops->destroy = NULL;
221   }
222   ierr = PetscMemzero(guess->ops,sizeof(struct _KSPGuessOps));CHKERRQ(ierr);
223   ierr = PetscObjectChangeTypeName((PetscObject)guess,type);CHKERRQ(ierr);
224   ierr = (*r)(guess);CHKERRQ(ierr);
225   PetscFunctionReturn(0);
226 }
227 
228 /*@C
229    KSPGuessGetType - Gets the KSPGuess type as a string from the KSPGuess object.
230 
231    Not Collective
232 
233    Input Parameter:
234 .  guess - the initial guess context
235 
236    Output Parameter:
237 .  name - name of KSPGuess method
238 
239    Level: intermediate
240 
241 .seealso: KSPGuessSetType()
242 @*/
KSPGuessGetType(KSPGuess guess,KSPGuessType * type)243 PetscErrorCode  KSPGuessGetType(KSPGuess guess,KSPGuessType *type)
244 {
245   PetscFunctionBegin;
246   PetscValidHeaderSpecific(guess,KSPGUESS_CLASSID,1);
247   PetscValidPointer(type,2);
248   *type = ((PetscObject)guess)->type_name;
249   PetscFunctionReturn(0);
250 }
251 
252 /*@
253     KSPGuessUpdate - Updates the guess object with the current solution and rhs vector
254 
255    Collective on guess
256 
257    Input Parameter:
258 +  guess - the initial guess context
259 .  rhs   - the corresponding rhs
260 -  sol   - the computed solution
261 
262    Level: intermediate
263 
264 .seealso: KSPGuessCreate(), KSPGuess
265 @*/
KSPGuessUpdate(KSPGuess guess,Vec rhs,Vec sol)266 PetscErrorCode  KSPGuessUpdate(KSPGuess guess, Vec rhs, Vec sol)
267 {
268   PetscErrorCode ierr;
269 
270   PetscFunctionBegin;
271   PetscValidHeaderSpecific(guess,KSPGUESS_CLASSID,1);
272   PetscValidHeaderSpecific(rhs,VEC_CLASSID,2);
273   PetscValidHeaderSpecific(sol,VEC_CLASSID,3);
274   if (guess->ops->update) { ierr = (*guess->ops->update)(guess,rhs,sol);CHKERRQ(ierr); }
275   PetscFunctionReturn(0);
276 }
277 
278 /*@
279     KSPGuessFormGuess - Form the initial guess
280 
281    Collective on guess
282 
283    Input Parameter:
284 +  guess - the initial guess context
285 .  rhs   - the current rhs vector
286 -  sol   - the initial guess vector
287 
288    Level: intermediate
289 
290 .seealso: KSPGuessCreate(), KSPGuess
291 @*/
KSPGuessFormGuess(KSPGuess guess,Vec rhs,Vec sol)292 PetscErrorCode  KSPGuessFormGuess(KSPGuess guess, Vec rhs, Vec sol)
293 {
294   PetscErrorCode ierr;
295 
296   PetscFunctionBegin;
297   PetscValidHeaderSpecific(guess,KSPGUESS_CLASSID,1);
298   PetscValidHeaderSpecific(rhs,VEC_CLASSID,2);
299   PetscValidHeaderSpecific(sol,VEC_CLASSID,3);
300   if (guess->ops->formguess) { ierr = (*guess->ops->formguess)(guess,rhs,sol);CHKERRQ(ierr); }
301   PetscFunctionReturn(0);
302 }
303 
304 /*@
305     KSPGuessSetUp - Setup the initial guess object
306 
307    Collective on guess
308 
309    Input Parameter:
310 -  guess - the initial guess context
311 
312    Level: intermediate
313 
314 .seealso: KSPGuessCreate(), KSPGuess
315 @*/
KSPGuessSetUp(KSPGuess guess)316 PetscErrorCode  KSPGuessSetUp(KSPGuess guess)
317 {
318   PetscErrorCode   ierr;
319   PetscObjectState matstate;
320   PetscInt         oM = 0, oN = 0, M, N;
321   Mat              omat = NULL;
322   PC               pc;
323   PetscBool        reuse;
324 
325   PetscFunctionBegin;
326   PetscValidHeaderSpecific(guess,KSPGUESS_CLASSID,1);
327   if (guess->A) {
328     omat = guess->A;
329     ierr = MatGetSize(guess->A,&oM,&oN);CHKERRQ(ierr);
330   }
331   ierr = KSPGetOperators(guess->ksp,&guess->A,NULL);CHKERRQ(ierr);
332   ierr = KSPGetPC(guess->ksp,&pc);CHKERRQ(ierr);
333   ierr = PCGetReusePreconditioner(pc,&reuse);CHKERRQ(ierr);
334   ierr = PetscObjectReference((PetscObject)guess->A);CHKERRQ(ierr);
335   ierr = MatGetSize(guess->A,&M,&N);CHKERRQ(ierr);
336   ierr = PetscObjectStateGet((PetscObject)guess->A,&matstate);CHKERRQ(ierr);
337   if (M != oM || N != oN) {
338     ierr = PetscInfo4(guess,"Resetting KSPGuess since matrix sizes have changed (%D != %D, %D != %D)\n",oM,M,oN,N);CHKERRQ(ierr);
339   } else if (!reuse && (omat != guess->A || guess->omatstate != matstate)) {
340     ierr = PetscInfo1(guess,"Resetting KSPGuess since %s has changed\n",omat != guess->A ? "matrix" : "matrix state");CHKERRQ(ierr);
341     if (guess->ops->reset) { ierr = (*guess->ops->reset)(guess);CHKERRQ(ierr); }
342   } else if (reuse) {
343     ierr = PetscInfo(guess,"Not resettting KSPGuess since reuse preconditioner has been specified\n");CHKERRQ(ierr);
344   } else {
345     ierr = PetscInfo(guess,"KSPGuess status unchanged\n");CHKERRQ(ierr);
346   }
347   if (guess->ops->setup) { ierr = (*guess->ops->setup)(guess);CHKERRQ(ierr); }
348   guess->omatstate = matstate;
349   ierr = MatDestroy(&omat);CHKERRQ(ierr);
350   PetscFunctionReturn(0);
351 }
352