Actual source code: snesmfj.c
1: /*$Id: snesmfj.c,v 1.119 2001/04/10 19:36:54 bsmith Exp $*/
3: #include "src/snes/snesimpl.h"
4: #include "src/snes/mf/snesmfj.h" /*I "petscsnes.h" I*/
6: PetscFList MatSNESMPetscFList = 0;
7: PetscTruth MatSNESMFRegisterAllCalled = PETSC_FALSE;
9: /*@C
10: MatSNESMFSetType - Sets the method that is used to compute the
11: differencing parameter for finite differene matrix-free formulations.
13: Input Parameters:
14: + mat - the "matrix-free" matrix created via MatCreateSNESMF()
15: - ftype - the type requested
17: Level: advanced
19: Notes:
20: For example, such routines can compute h for use in
21: Jacobian-vector products of the form
23: F(x+ha) - F(x)
24: F'(u)a ~= ----------------
25: h
27: .seealso: MatCreateSNESMF(), MatSNESMFRegisterDynamic)
28: @*/
29: int MatSNESMFSetType(Mat mat,MatSNESMFType ftype)
30: {
31: int ierr,(*r)(MatSNESMFCtx);
32: MatSNESMFCtx ctx;
33: PetscTruth match;
34:
39: MatShellGetContext(mat,(void **)&ctx);
41: /* already set, so just return */
42: PetscTypeCompare((PetscObject)ctx,ftype,&match);
43: if (match) return(0);
45: /* destroy the old one if it exists */
46: if (ctx->ops->destroy) {
47: (*ctx->ops->destroy)(ctx);
48: }
50: /* Get the function pointers for the requrested method */
51: if (!MatSNESMFRegisterAllCalled) {MatSNESMFRegisterAll(PETSC_NULL);}
53: PetscFListFind(ctx->comm,MatSNESMPetscFList,ftype,(void (**)(void)) &r);
55: if (!r) SETERRQ(1,"Unknown MatSNESMF type given");
57: (*r)(ctx);
59: PetscObjectChangeTypeName((PetscObject)ctx,ftype);
61: return(0);
62: }
64: /*MC
65: MatSNESMFRegisterDynamic - Adds a method to the MatSNESMF registry.
67: Synopsis:
68: MatSNESMFRegisterDynamicchar *name_solver,char *path,char *name_create,int (*routine_create)(MatSNESMF))
70: Not Collective
72: Input Parameters:
73: + name_solver - name of a new user-defined compute-h module
74: . path - path (either absolute or relative) the library containing this solver
75: . name_create - name of routine to create method context
76: - routine_create - routine to create method context
78: Level: developer
80: Notes:
81: MatSNESMFRegisterDynamic) may be called multiple times to add several user-defined solvers.
83: If dynamic libraries are used, then the fourth input argument (routine_create)
84: is ignored.
86: Sample usage:
87: .vb
88: MatSNESMFRegisterDynamic"my_h",/home/username/my_lib/lib/libO/solaris/mylib.a,
89: "MyHCreate",MyHCreate);
90: .ve
92: Then, your solver can be chosen with the procedural interface via
93: $ MatSNESMFSetType(mfctx,"my_h")
94: or at runtime via the option
95: $ -snes_mf_type my_h
97: .keywords: MatSNESMF, register
99: .seealso: MatSNESMFRegisterAll(), MatSNESMFRegisterDestroy()
100: M*/
102: int MatSNESMFRegister(char *sname,char *path,char *name,int (*function)(MatSNESMFCtx))
103: {
105: char fullname[256];
108: PetscFListConcat(path,name,fullname);
109: PetscFListAdd(&MatSNESMPetscFList,sname,fullname,(void (*)())function);
110: return(0);
111: }
114: /*@C
115: MatSNESMFRegisterDestroy - Frees the list of MatSNESMF methods that were
116: registered by MatSNESMFRegisterDynamic).
118: Not Collective
120: Level: developer
122: .keywords: MatSNESMF, register, destroy
124: .seealso: MatSNESMFRegisterDynamic), MatSNESMFRegisterAll()
125: @*/
126: int MatSNESMFRegisterDestroy(void)
127: {
131: if (MatSNESMPetscFList) {
132: PetscFListDestroy(&MatSNESMPetscFList);
133: MatSNESMPetscFList = 0;
134: }
135: MatSNESMFRegisterAllCalled = PETSC_FALSE;
136: return(0);
137: }
139: /* ----------------------------------------------------------------------------------------*/
140: int MatSNESMFDestroy_Private(Mat mat)
141: {
142: int ierr;
143: MatSNESMFCtx ctx;
146: MatShellGetContext(mat,(void **)&ctx);
147: VecDestroy(ctx->w);
148: if (ctx->ops->destroy) {(*ctx->ops->destroy)(ctx);}
149: if (ctx->sp) {MatNullSpaceDestroy(ctx->sp);}
150: PetscHeaderDestroy(ctx);
151: return(0);
152: }
154: /*
155: MatSNESMFView_Private - Views matrix-free parameters.
157: */
158: int MatSNESMFView_Private(Mat J,PetscViewer viewer)
159: {
160: int ierr;
161: MatSNESMFCtx ctx;
162: PetscTruth isascii;
165: MatShellGetContext(J,(void **)&ctx);
166: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
167: if (isascii) {
168: PetscViewerASCIIPrintf(viewer," SNES matrix-free approximation:n");
169: PetscViewerASCIIPrintf(viewer," err=%g (relative error in function evaluation)n",ctx->error_rel);
170: if (!ctx->type_name) {
171: PetscViewerASCIIPrintf(viewer," The compute h routine has not yet been setn");
172: } else {
173: PetscViewerASCIIPrintf(viewer," Using %s compute h routinen",ctx->type_name);
174: }
175: if (ctx->ops->view) {
176: (*ctx->ops->view)(ctx,viewer);
177: }
178: } else {
179: SETERRQ1(1,"Viewer type %s not supported for SNES matrix free matrix",((PetscObject)viewer)->type_name);
180: }
181: return(0);
182: }
184: /*
185: MatSNESMFAssemblyEnd_Private - Resets the ctx->ncurrenth to zero. This
186: allows the user to indicate the beginning of a new linear solve by calling
187: MatAssemblyXXX() on the matrix free matrix. This then allows the
188: MatSNESMFCreate_WP() to properly compute ||U|| only the first time
189: in the linear solver rather than every time.
190: */
191: int MatSNESMFAssemblyEnd_Private(Mat J)
192: {
193: int ierr;
194: MatSNESMFCtx j;
197: MatSNESMFResetHHistory(J);
198: MatShellGetContext(J,(void **)&j);
199: if (j->usesnes) {
200: SNESGetSolution(j->snes,&j->current_u);
201: if (j->snes->method_class == SNES_NONLINEAR_EQUATIONS) {
202: SNESGetFunction(j->snes,&j->current_f,PETSC_NULL,PETSC_NULL);
203: } else if (j->snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
204: SNESGetGradient(j->snes,&j->current_f,PETSC_NULL);
205: } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Invalid method class");
206: }
207: return(0);
208: }
211: /*
212: MatSNESMFMult_Private - Default matrix-free form for Jacobian-vector
213: product, y = F'(u)*a:
215: y ~= (F(u + ha) - F(u))/h,
216: where F = nonlinear function, as set by SNESSetFunction()
217: u = current iterate
218: h = difference interval
219: */
220: int MatSNESMFMult_Private(Mat mat,Vec a,Vec y)
221: {
222: MatSNESMFCtx ctx;
223: SNES snes;
224: Scalar h,mone = -1.0;
225: Vec w,U,F;
226: int ierr,(*eval_fct)(SNES,Vec,Vec)=0;
229: /* We log matrix-free matrix-vector products separately, so that we can
230: separate the performance monitoring from the cases that use conventional
231: storage. We may eventually modify event logging to associate events
232: with particular objects, hence alleviating the more general problem. */
233: PetscLogEventBegin(MAT_MatrixFreeMult,a,y,0,0);
235: MatShellGetContext(mat,(void **)&ctx);
236: snes = ctx->snes;
237: w = ctx->w;
238: U = ctx->current_u;
240: /*
241: Compute differencing parameter
242: */
243: if (!ctx->ops->compute) {
244: MatSNESMFSetType(mat,MATSNESMF_DEFAULT);
245: MatSNESMFSetFromOptions(mat);
246: }
247: (*ctx->ops->compute)(ctx,U,a,&h);
249: /* keep a record of the current differencing parameter h */
250: ctx->currenth = h;
251: #if defined(PETSC_USE_COMPLEX)
252: PetscLogInfo(mat,"MatSNESMFMult_Private:Current differencing parameter: %g + %g in",PetscRealPart(h),PetscImaginaryPart(h));
253: #else
254: PetscLogInfo(mat,"MatSNESMFMult_Private:Current differencing parameter: %15.12en",h);
255: #endif
256: if (ctx->historyh && ctx->ncurrenth < ctx->maxcurrenth) {
257: ctx->historyh[ctx->ncurrenth] = h;
258: }
259: ctx->ncurrenth++;
261: /* w = u + ha */
262: VecWAXPY(&h,a,U,w);
264: if (ctx->usesnes) {
265: if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
266: eval_fct = SNESComputeFunction;
267: } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
268: eval_fct = SNESComputeGradient;
269: } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Invalid method class");
270: F = ctx->current_f;
271: if (!F) SETERRQ(1,"You must call MatAssembly() even on matrix-free matrices");
272: (*eval_fct)(snes,w,y);
273: } else {
274: F = ctx->funcvec;
275: /* compute func(U) as base for differencing */
276: if (ctx->ncurrenth == 1) {
277: (*ctx->func)(snes,U,F,ctx->funcctx);
278: }
279: (*ctx->func)(snes,w,y,ctx->funcctx);
280: }
282: VecAXPY(&mone,F,y);
283: h = 1.0/h;
284: VecScale(&h,y);
285: if (ctx->sp) {MatNullSpaceRemove(ctx->sp,y,PETSC_NULL);}
287: PetscLogEventEnd(MAT_MatrixFreeMult,a,y,0,0);
288: return(0);
289: }
291: /*@C
292: MatCreateSNESMF - Creates a matrix-free matrix context for use with
293: a SNES solver. This matrix can be used as the Jacobian argument for
294: the routine SNESSetJacobian().
296: Collective on SNES and Vec
298: Input Parameters:
299: + snes - the SNES context
300: - x - vector where SNES solution is to be stored.
302: Output Parameter:
303: . J - the matrix-free matrix
305: Level: advanced
307: Notes:
308: The matrix-free matrix context merely contains the function pointers
309: and work space for performing finite difference approximations of
310: Jacobian-vector products, F'(u)*a,
312: The default code uses the following approach to compute h
314: .vb
315: F'(u)*a = [F(u+h*a) - F(u)]/h where
316: h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1}
317: = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 otherwise
318: where
319: error_rel = square root of relative error in function evaluation
320: umin = minimum iterate parameter
321: .ve
323: The user can set the error_rel via MatSNESMFSetFunctionError() and
324: umin via MatSNESMFDefaultSetUmin(); see the nonlinear solvers chapter
325: of the users manual for details.
327: The user should call MatDestroy() when finished with the matrix-free
328: matrix context.
330: Options Database Keys:
331: + -snes_mf_err <error_rel> - Sets error_rel
332: . -snes_mf_unim <umin> - Sets umin (for default PETSc routine that computes h only)
333: - -snes_mf_ksp_monitor - KSP monitor routine that prints differencing h
335: .keywords: SNES, default, matrix-free, create, matrix
337: .seealso: MatDestroy(), MatSNESMFSetFunctionError(), MatSNESMFDefaultSetUmin()
338: MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), MatCreateMF(),
339: MatSNESMFGetH(),MatSNESMFKSPMonitor(), MatSNESMFRegisterDynamic), MatSNESMFFormJacobian()
340:
341: @*/
342: int MatCreateSNESMF(SNES snes,Vec x,Mat *J)
343: {
344: MatSNESMFCtx mfctx;
345: int ierr;
348: MatCreateMF(x,J);
349: MatShellGetContext(*J,(void **)&mfctx);
350: mfctx->snes = snes;
351: mfctx->usesnes = PETSC_TRUE;
352: PetscLogObjectParent(snes,*J);
353: return(0);
354: }
356: /*@C
357: MatCreateMF - Creates a matrix-free matrix. See also MatCreateSNESMF()
359: Collective on Vec
361: Input Parameters:
362: . x - vector that defines layout of the vectors and matrices
364: Output Parameter:
365: . J - the matrix-free matrix
367: Level: advanced
369: Notes:
370: The matrix-free matrix context merely contains the function pointers
371: and work space for performing finite difference approximations of
372: Jacobian-vector products, F'(u)*a,
374: The default code uses the following approach to compute h
376: .vb
377: F'(u)*a = [F(u+h*a) - F(u)]/h where
378: h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1}
379: = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 otherwise
380: where
381: error_rel = square root of relative error in function evaluation
382: umin = minimum iterate parameter
383: .ve
385: The user can set the error_rel via MatSNESMFSetFunctionError() and
386: umin via MatSNESMFDefaultSetUmin(); see the nonlinear solvers chapter
387: of the users manual for details.
389: The user should call MatDestroy() when finished with the matrix-free
390: matrix context.
392: Options Database Keys:
393: + -snes_mf_err <error_rel> - Sets error_rel
394: . -snes_mf_unim <umin> - Sets umin (for default PETSc routine that computes h only)
395: - -snes_mf_ksp_monitor - KSP monitor routine that prints differencing h
397: .keywords: default, matrix-free, create, matrix
399: .seealso: MatDestroy(), MatSNESMFSetFunctionError(), MatSNESMFDefaultSetUmin()
400: MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), MatCreateSNESMF(),
401: MatSNESMFGetH(),MatSNESMFKSPMonitor(), MatSNESMFRegisterDynamic),, MatSNESMFFormJacobian()
402:
403: @*/
404: int MatCreateMF(Vec x,Mat *J)
405: {
406: MPI_Comm comm;
407: MatSNESMFCtx mfctx;
408: int n,nloc,ierr;
411: PetscObjectGetComm((PetscObject)x,&comm);
412: PetscHeaderCreate(mfctx,_p_MatSNESMFCtx,struct _MFOps,MATSNESMFCTX_COOKIE,0,"SNESMF",comm,MatSNESMFDestroy_Private,MatSNESMFView_Private);
413: PetscLogObjectCreate(mfctx);
414: mfctx->sp = 0;
415: mfctx->snes = 0;
416: mfctx->error_rel = 1.e-8; /* assumes PetscReal precision */
417: mfctx->recomputeperiod = 1;
418: mfctx->count = 0;
419: mfctx->currenth = 0.0;
420: mfctx->historyh = PETSC_NULL;
421: mfctx->ncurrenth = 0;
422: mfctx->maxcurrenth = 0;
423: mfctx->type_name = 0;
424: mfctx->usesnes = PETSC_FALSE;
426: /*
427: Create the empty data structure to contain compute-h routines.
428: These will be filled in below from the command line options or
429: a later call with MatSNESMFSetType() or if that is not called
430: then it will default in the first use of MatSNESMFMult_private()
431: */
432: mfctx->ops->compute = 0;
433: mfctx->ops->destroy = 0;
434: mfctx->ops->view = 0;
435: mfctx->ops->setfromoptions = 0;
436: mfctx->hctx = 0;
438: mfctx->func = 0;
439: mfctx->funcctx = 0;
440: mfctx->funcvec = 0;
442: VecDuplicate(x,&mfctx->w);
443: VecGetSize(mfctx->w,&n);
444: VecGetLocalSize(mfctx->w,&nloc);
445: MatCreateShell(comm,nloc,nloc,n,n,mfctx,J);
446: MatShellSetOperation(*J,MATOP_MULT,(void(*)())MatSNESMFMult_Private);
447: MatShellSetOperation(*J,MATOP_DESTROY,(void(*)())MatSNESMFDestroy_Private);
448: MatShellSetOperation(*J,MATOP_VIEW,(void(*)())MatSNESMFView_Private);
449: MatShellSetOperation(*J,MATOP_ASSEMBLY_END,(void(*)())MatSNESMFAssemblyEnd_Private);
450: PetscLogObjectParent(*J,mfctx->w);
452: mfctx->mat = *J;
453: return(0);
454: }
456: /*@
457: MatSNESMFSetFromOptions - Sets the MatSNESMF options from the command line
458: parameter.
460: Collective on Mat
462: Input Parameters:
463: . mat - the matrix obtained with MatCreateSNESMF()
465: Options Database Keys:
466: + -snes_mf_type - <default,wp>
467: - -snes_mf_err - square root of estimated relative error in function evaluation
468: - -snes_mf_period - how often h is recomputed, defaults to 1, everytime
470: Level: advanced
472: .keywords: SNES, matrix-free, parameters
474: .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(),
475: MatSNESMFResetHHistory(), MatSNESMFKSPMonitor()
476: @*/
477: int MatSNESMFSetFromOptions(Mat mat)
478: {
479: MatSNESMFCtx mfctx;
480: int ierr;
481: PetscTruth flg;
482: char ftype[256];
485: MatShellGetContext(mat,(void **)&mfctx);
486: if (mfctx) {
487: if (!MatSNESMFRegisterAllCalled) {MatSNESMFRegisterAll(PETSC_NULL);}
488:
489: PetscOptionsBegin(mfctx->comm,mfctx->prefix,"Set matrix free computation parameters","MatSNESMF");
490: PetscOptionsList("-snes_mf_type","Matrix free type","MatSNESMFSetType",MatSNESMPetscFList,mfctx->type_name,ftype,256,&flg);
491: if (flg) {
492: MatSNESMFSetType(mat,ftype);
493: }
495: PetscOptionsDouble("-snes_mf_err","set sqrt relative error in function","MatSNESMFSetFunctionError",mfctx->error_rel,&mfctx->error_rel,0);
496: PetscOptionsInt("-snes_mf_period","how often h is recomputed","MatSNESMFSetPeriod",mfctx->recomputeperiod,&mfctx->recomputeperiod,0);
497: if (mfctx->snes) {
498: PetscOptionsName("-snes_mf_ksp_monitor","Monitor matrix-free parameters","MatSNESMFKSPMonitor",&flg);
499: if (flg) {
500: SLES sles;
501: KSP ksp;
502: SNESGetSLES(mfctx->snes,&sles);
503: SLESGetKSP(sles,&ksp);
504: KSPSetMonitor(ksp,MatSNESMFKSPMonitor,PETSC_NULL,0);
505: }
506: }
507: if (mfctx->ops->setfromoptions) {
508: (*mfctx->ops->setfromoptions)(mfctx);
509: }
510: PetscOptionsEnd();
512: }
513: return(0);
514: }
516: /*@
517: MatSNESMFGetH - Gets the last value that was used as the differencing
518: parameter.
520: Not Collective
522: Input Parameters:
523: . mat - the matrix obtained with MatCreateSNESMF()
525: Output Paramter:
526: . h - the differencing step size
528: Level: advanced
530: .keywords: SNES, matrix-free, parameters
532: .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(),
533: MatSNESMFResetHHistory(),MatSNESMFKSPMonitor()
534: @*/
535: int MatSNESMFGetH(Mat mat,Scalar *h)
536: {
537: MatSNESMFCtx ctx;
538: int ierr;
541: MatShellGetContext(mat,(void **)&ctx);
542: if (ctx) {
543: *h = ctx->currenth;
544: }
545: return(0);
546: }
548: /*
549: MatSNESMFKSPMonitor - A KSP monitor for use with the default PETSc
550: SNES matrix free routines. Prints the differencing parameter used at
551: each step.
552: */
553: int MatSNESMFKSPMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy)
554: {
555: PC pc;
556: MatSNESMFCtx ctx;
557: int ierr;
558: Mat mat;
559: MPI_Comm comm;
560: PetscTruth nonzeroinitialguess;
563: PetscObjectGetComm((PetscObject)ksp,&comm);
564: KSPGetPC(ksp,&pc);
565: KSPGetInitialGuessNonzero(ksp,&nonzeroinitialguess);
566: PCGetOperators(pc,&mat,PETSC_NULL,PETSC_NULL);
567: MatShellGetContext(mat,(void **)&ctx);
568: if (!ctx) {
569: SETERRQ(1,"Matrix is not a matrix free shell matrix");
570: }
571: if (n > 0 || nonzeroinitialguess) {
572: #if defined(PETSC_USE_COMPLEX)
573: PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g + %g in",n,rnorm,
574: PetscRealPart(ctx->currenth),PetscImaginaryPart(ctx->currenth));
575: #else
576: PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g n",n,rnorm,ctx->currenth);
577: #endif
578: } else {
579: PetscPrintf(comm,"%d KSP Residual norm %14.12en",n,rnorm);
580: }
581: return(0);
582: }
584: /*@C
585: MatSNESMFSetFunction - Sets the function used in applying the matrix free.
587: Collective on Mat
589: Input Parameters:
590: + mat - the matrix free matrix created via MatCreateSNESMF()
591: . v - workspace vector
592: . func - the function to use
593: - funcctx - optional function context passed to function
595: Level: advanced
597: Notes:
598: If you use this you MUST call MatAssemblyBegin()/MatAssemblyEnd() on the matrix free
599: matrix inside your compute Jacobian routine
601: If this is not set then it will use the function set with SNESSetFunction()
603: .keywords: SNES, matrix-free, function
605: .seealso: MatCreateSNESMF(),MatSNESMFGetH(),
606: MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
607: MatSNESMFKSPMonitor(), SNESetFunction()
608: @*/
609: int MatSNESMFSetFunction(Mat mat,Vec v,int (*func)(SNES,Vec,Vec,void *),void *funcctx)
610: {
611: MatSNESMFCtx ctx;
612: int ierr;
615: MatShellGetContext(mat,(void **)&ctx);
616: if (ctx) {
617: ctx->func = func;
618: ctx->funcctx = funcctx;
619: ctx->funcvec = v;
620: }
621: return(0);
622: }
625: /*@
626: MatSNESMFSetPeriod - Sets how often h is recomputed, by default it is everytime
628: Collective on Mat
630: Input Parameters:
631: + mat - the matrix free matrix created via MatCreateSNESMF()
632: - period - 1 for everytime, 2 for every second etc
634: Options Database Keys:
635: + -snes_mf_period <period>
637: Level: advanced
640: .keywords: SNES, matrix-free, parameters
642: .seealso: MatCreateSNESMF(),MatSNESMFGetH(),
643: MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
644: MatSNESMFKSPMonitor()
645: @*/
646: int MatSNESMFSetPeriod(Mat mat,int period)
647: {
648: MatSNESMFCtx ctx;
649: int ierr;
652: MatShellGetContext(mat,(void **)&ctx);
653: if (ctx) {
654: ctx->recomputeperiod = period;
655: }
656: return(0);
657: }
659: /*@
660: MatSNESMFSetFunctionError - Sets the error_rel for the approximation of
661: matrix-vector products using finite differences.
663: Collective on Mat
665: Input Parameters:
666: + mat - the matrix free matrix created via MatCreateSNESMF()
667: - error_rel - relative error (should be set to the square root of
668: the relative error in the function evaluations)
670: Options Database Keys:
671: + -snes_mf_err <error_rel> - Sets error_rel
673: Level: advanced
675: Notes:
676: The default matrix-free matrix-vector product routine computes
677: .vb
678: F'(u)*a = [F(u+h*a) - F(u)]/h where
679: h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1}
680: = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 else
681: .ve
683: .keywords: SNES, matrix-free, parameters
685: .seealso: MatCreateSNESMF(),MatSNESMFGetH(),
686: MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
687: MatSNESMFKSPMonitor()
688: @*/
689: int MatSNESMFSetFunctionError(Mat mat,PetscReal error)
690: {
691: MatSNESMFCtx ctx;
692: int ierr;
695: MatShellGetContext(mat,(void **)&ctx);
696: if (ctx) {
697: if (error != PETSC_DEFAULT) ctx->error_rel = error;
698: }
699: return(0);
700: }
702: /*@
703: MatSNESMFAddNullSpace - Provides a null space that an operator is
704: supposed to have. Since roundoff will create a small component in
705: the null space, if you know the null space you may have it
706: automatically removed.
708: Collective on Mat
710: Input Parameters:
711: + J - the matrix-free matrix context
712: - nullsp - object created with MatNullSpaceCreate()
714: Level: advanced
716: .keywords: SNES, matrix-free, null space
718: .seealso: MatNullSpaceCreate(), MatSNESMFGetH(), MatCreateSNESMF(),
719: MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
720: MatSNESMFKSPMonitor(), MatSNESMFErrorRel()
721: @*/
722: int MatSNESMFAddNullSpace(Mat J,MatNullSpace nullsp)
723: {
724: int ierr;
725: MatSNESMFCtx ctx;
726: MPI_Comm comm;
729: PetscObjectGetComm((PetscObject)J,&comm);
731: MatShellGetContext(J,(void **)&ctx);
732: /* no context indicates that it is not the "matrix free" matrix type */
733: if (!ctx) return(0);
734: ctx->sp = nullsp;
735: PetscObjectReference((PetscObject)nullsp);
736: return(0);
737: }
739: /*@
740: MatSNESMFSetHHistory - Sets an array to collect a history of the
741: differencing values (h) computed for the matrix-free product.
743: Collective on Mat
745: Input Parameters:
746: + J - the matrix-free matrix context
747: . histroy - space to hold the history
748: - nhistory - number of entries in history, if more entries are generated than
749: nhistory, then the later ones are discarded
751: Level: advanced
753: Notes:
754: Use MatSNESMFResetHHistory() to reset the history counter and collect
755: a new batch of differencing parameters, h.
757: .keywords: SNES, matrix-free, h history, differencing history
759: .seealso: MatSNESMFGetH(), MatCreateSNESMF(),
760: MatSNESMFResetHHistory(),
761: MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError()
763: @*/
764: int MatSNESMFSetHHistory(Mat J,Scalar *history,int nhistory)
765: {
766: int ierr;
767: MatSNESMFCtx ctx;
771: MatShellGetContext(J,(void **)&ctx);
772: /* no context indicates that it is not the "matrix free" matrix type */
773: if (!ctx) return(0);
774: ctx->historyh = history;
775: ctx->maxcurrenth = nhistory;
776: ctx->currenth = 0;
778: return(0);
779: }
781: /*@
782: MatSNESMFResetHHistory - Resets the counter to zero to begin
783: collecting a new set of differencing histories.
785: Collective on Mat
787: Input Parameters:
788: . J - the matrix-free matrix context
790: Level: advanced
792: Notes:
793: Use MatSNESMFSetHHistory() to create the original history counter.
795: .keywords: SNES, matrix-free, h history, differencing history
797: .seealso: MatSNESMFGetH(), MatCreateSNESMF(),
798: MatSNESMFSetHHistory(),
799: MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError()
801: @*/
802: int MatSNESMFResetHHistory(Mat J)
803: {
804: int ierr;
805: MatSNESMFCtx ctx;
809: MatShellGetContext(J,(void **)&ctx);
810: /* no context indicates that it is not the "matrix free" matrix type */
811: if (!ctx) return(0);
812: ctx->ncurrenth = 0;
814: return(0);
815: }
817: int MatSNESMFFormJacobian(SNES snes,Vec x,Mat *jac,Mat *B,MatStructure *flag,void *dummy)
818: {
821: MatAssemblyBegin(*jac,MAT_FINAL_ASSEMBLY);
822: MatAssemblyEnd(*jac,MAT_FINAL_ASSEMBLY);
823: return(0);
824: }
826: int MatSNESMFSetBase(Mat J,Vec U)
827: {
828: int ierr;
829: MatSNESMFCtx ctx;
835: MatShellGetContext(J,(void **)&ctx);
836: ctx->current_u = U;
837: ctx->usesnes = PETSC_FALSE;
838: return(0);
839: }