xref: /petsc/src/tao/interface/taosolver_bounds.c (revision 4e8208cbcbc709572b8abe32f33c78b69c819375)
1 #include <petsc/private/taoimpl.h> /*I "petsctao.h" I*/
2 
3 /*@
4   TaoSetVariableBounds - Sets the upper and lower bounds for the optimization problem
5 
6   Logically Collective
7 
8   Input Parameters:
9 + tao - the `Tao` context
10 . XL  - vector of lower bounds
11 - XU  - vector of upper bounds
12 
13   Level: beginner
14 
15 .seealso: [](ch_tao), `Tao`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoGetVariableBounds()`
16 @*/
TaoSetVariableBounds(Tao tao,Vec XL,Vec XU)17 PetscErrorCode TaoSetVariableBounds(Tao tao, Vec XL, Vec XU)
18 {
19   PetscFunctionBegin;
20   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
21   if (XL) PetscValidHeaderSpecific(XL, VEC_CLASSID, 2);
22   if (XU) PetscValidHeaderSpecific(XU, VEC_CLASSID, 3);
23   PetscCall(PetscObjectReference((PetscObject)XL));
24   PetscCall(PetscObjectReference((PetscObject)XU));
25   PetscCall(VecDestroy(&tao->XL));
26   PetscCall(VecDestroy(&tao->XU));
27   tao->XL      = XL;
28   tao->XU      = XU;
29   tao->bounded = (PetscBool)(XL || XU);
30   PetscFunctionReturn(PETSC_SUCCESS);
31 }
32 
33 /*@C
34   TaoSetVariableBoundsRoutine - Sets a function to be used to compute lower and upper variable bounds for the optimization
35 
36   Logically Collective
37 
38   Input Parameters:
39 + tao  - the `Tao` context
40 . func - the bounds computation routine
41 - ctx  - [optional] user-defined context for private data for the bounds computation (may be `NULL`)
42 
43   Calling sequence of `func`:
44 + tao - the `Tao` solver
45 . xl  - vector of lower bounds
46 . xu  - vector of upper bounds
47 - ctx - the (optional) user-defined function context
48 
49   Level: beginner
50 
51   Note:
52   The func passed to `TaoSetVariableBoundsRoutine()` takes precedence over any values set in `TaoSetVariableBounds()`.
53 
54 .seealso: [](ch_tao), `Tao`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoSetVariableBounds()`
55 @*/
TaoSetVariableBoundsRoutine(Tao tao,PetscErrorCode (* func)(Tao tao,Vec xl,Vec xu,PetscCtx ctx),PetscCtx ctx)56 PetscErrorCode TaoSetVariableBoundsRoutine(Tao tao, PetscErrorCode (*func)(Tao tao, Vec xl, Vec xu, PetscCtx ctx), PetscCtx ctx)
57 {
58   PetscFunctionBegin;
59   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
60   tao->user_boundsP       = ctx;
61   tao->ops->computebounds = func;
62   tao->bounded            = func ? PETSC_TRUE : PETSC_FALSE;
63   PetscFunctionReturn(PETSC_SUCCESS);
64 }
65 
66 /*@
67   TaoGetVariableBounds - Gets the upper and lower bounds vectors set with `TaoSetVariableBounds()`
68 
69   Not Collective
70 
71   Input Parameter:
72 . tao - the `Tao` context
73 
74   Output Parameters:
75 + XL - vector of lower bounds
76 - XU - vector of upper bounds
77 
78   Level: beginner
79 
80 .seealso: [](ch_tao), `Tao`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoSetVariableBounds()`
81 @*/
TaoGetVariableBounds(Tao tao,Vec * XL,Vec * XU)82 PetscErrorCode TaoGetVariableBounds(Tao tao, Vec *XL, Vec *XU)
83 {
84   PetscFunctionBegin;
85   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
86   if (XL) *XL = tao->XL;
87   if (XU) *XU = tao->XU;
88   PetscFunctionReturn(PETSC_SUCCESS);
89 }
90 
91 /*@
92   TaoComputeVariableBounds - Compute the variable bounds using the
93   routine set by `TaoSetVariableBoundsRoutine()`.
94 
95   Collective
96 
97   Input Parameter:
98 . tao - the `Tao` context
99 
100   Level: developer
101 
102 .seealso: [](ch_tao), `Tao`, `TaoSetVariableBoundsRoutine()`, `TaoSetVariableBounds()`
103 @*/
TaoComputeVariableBounds(Tao tao)104 PetscErrorCode TaoComputeVariableBounds(Tao tao)
105 {
106   PetscFunctionBegin;
107   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
108   if (tao->ops->computebounds) {
109     if (!tao->XL) {
110       PetscCall(VecDuplicate(tao->solution, &tao->XL));
111       PetscCall(VecSet(tao->XL, PETSC_NINFINITY));
112     }
113     if (!tao->XU) {
114       PetscCall(VecDuplicate(tao->solution, &tao->XU));
115       PetscCall(VecSet(tao->XU, PETSC_INFINITY));
116     }
117     PetscCallBack("Tao callback variable bounds", (*tao->ops->computebounds)(tao, tao->XL, tao->XU, tao->user_boundsP));
118   }
119   PetscFunctionReturn(PETSC_SUCCESS);
120 }
121 
122 /*@
123   TaoSetInequalityBounds - Sets the upper and lower bounds
124 
125   Logically Collective
126 
127   Input Parameters:
128 + tao - the `Tao` context
129 . IL  - vector of lower bounds
130 - IU  - vector of upper bounds
131 
132   Level: beginner
133 
134 .seealso: [](ch_tao), `Tao`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoGetInequalityBounds()`
135 @*/
TaoSetInequalityBounds(Tao tao,Vec IL,Vec IU)136 PetscErrorCode TaoSetInequalityBounds(Tao tao, Vec IL, Vec IU)
137 {
138   PetscFunctionBegin;
139   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
140   if (IL) PetscValidHeaderSpecific(IL, VEC_CLASSID, 2);
141   if (IU) PetscValidHeaderSpecific(IU, VEC_CLASSID, 3);
142   PetscCall(PetscObjectReference((PetscObject)IL));
143   PetscCall(PetscObjectReference((PetscObject)IU));
144   PetscCall(VecDestroy(&tao->IL));
145   PetscCall(VecDestroy(&tao->IU));
146   tao->IL               = IL;
147   tao->IU               = IU;
148   tao->ineq_doublesided = (PetscBool)(IL || IU);
149   PetscFunctionReturn(PETSC_SUCCESS);
150 }
151 
152 /*@
153   TaoGetInequalityBounds - Gets the upper and lower bounds set via `TaoSetInequalityBounds()`
154 
155   Logically Collective
156 
157   Input Parameter:
158 . tao - the `Tao` context
159 
160   Output Parameters:
161 + IL - vector of lower bounds
162 - IU - vector of upper bounds
163 
164   Level: beginner
165 
166 .seealso: [](ch_tao), `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoSetInequalityBounds()`
167 @*/
TaoGetInequalityBounds(Tao tao,Vec * IL,Vec * IU)168 PetscErrorCode TaoGetInequalityBounds(Tao tao, Vec *IL, Vec *IU)
169 {
170   PetscFunctionBegin;
171   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
172   if (IL) *IL = tao->IL;
173   if (IU) *IU = tao->IU;
174   PetscFunctionReturn(PETSC_SUCCESS);
175 }
176 
177 /*@
178   TaoComputeConstraints - Compute the variable bounds using the
179   routine set by `TaoSetConstraintsRoutine()`.
180 
181   Collective
182 
183   Input Parameters:
184 + tao - the `Tao` context
185 - X   - location to evaluate the constraints
186 
187   Output Parameter:
188 . C - the constraints
189 
190   Level: developer
191 
192 .seealso: [](ch_tao), `Tao`, `TaoSetConstraintsRoutine()`, `TaoComputeJacobian()`
193 @*/
TaoComputeConstraints(Tao tao,Vec X,Vec C)194 PetscErrorCode TaoComputeConstraints(Tao tao, Vec X, Vec C)
195 {
196   PetscFunctionBegin;
197   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
198   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
199   PetscValidHeaderSpecific(C, VEC_CLASSID, 3);
200   PetscCheckSameComm(tao, 1, X, 2);
201   PetscCheckSameComm(tao, 1, C, 3);
202   PetscCall(PetscLogEventBegin(TAO_ConstraintsEval, tao, X, C, NULL));
203   PetscCallBack("Tao callback constraints", (*tao->ops->computeconstraints)(tao, X, C, tao->user_conP));
204   PetscCall(PetscLogEventEnd(TAO_ConstraintsEval, tao, X, C, NULL));
205   tao->nconstraints++;
206   PetscFunctionReturn(PETSC_SUCCESS);
207 }
208 
209 /*@C
210   TaoSetConstraintsRoutine - Sets a function to be used to compute constraints.  Tao only handles constraints under certain conditions, see [](ch_tao) for details
211 
212   Logically Collective
213 
214   Input Parameters:
215 + tao  - the `Tao` context
216 . c    - A vector that will be used to store constraint evaluation
217 . func - the bounds computation routine
218 - ctx  - [optional] user-defined context for private data for the constraints computation (may be `NULL`)
219 
220   Calling sequence of `func`:
221 + tao - the `Tao` solver
222 . x   - point to evaluate constraints
223 . c   - vector constraints evaluated at `x`
224 - ctx - the (optional) user-defined function context
225 
226   Level: intermediate
227 
228 .seealso: [](ch_tao), `Tao`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoSetVariablevBounds()`
229 @*/
TaoSetConstraintsRoutine(Tao tao,Vec c,PetscErrorCode (* func)(Tao tao,Vec x,Vec c,PetscCtx ctx),PetscCtx ctx)230 PetscErrorCode TaoSetConstraintsRoutine(Tao tao, Vec c, PetscErrorCode (*func)(Tao tao, Vec x, Vec c, PetscCtx ctx), PetscCtx ctx)
231 {
232   PetscFunctionBegin;
233   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
234   if (c) PetscValidHeaderSpecific(c, VEC_CLASSID, 2);
235   PetscCall(PetscObjectReference((PetscObject)c));
236   PetscCall(VecDestroy(&tao->constraints));
237   tao->constrained             = func ? PETSC_TRUE : PETSC_FALSE;
238   tao->constraints             = c;
239   tao->user_conP               = ctx;
240   tao->ops->computeconstraints = func;
241   PetscFunctionReturn(PETSC_SUCCESS);
242 }
243 
244 /*@
245   TaoComputeDualVariables - Computes the dual vectors corresponding to the bounds
246   of the variables
247 
248   Collective
249 
250   Input Parameter:
251 . tao - the `Tao` context
252 
253   Output Parameters:
254 + DL - dual variable vector for the lower bounds
255 - DU - dual variable vector for the upper bounds
256 
257   Level: advanced
258 
259   Note:
260   DL and DU should be created before calling this routine.  If calling
261   this routine after using an unconstrained solver, `DL` and `DU` are set to all
262   zeros.
263 
264 .seealso: [](ch_tao), `Tao`, `TaoComputeObjective()`, `TaoSetVariableBounds()`
265 @*/
TaoComputeDualVariables(Tao tao,Vec DL,Vec DU)266 PetscErrorCode TaoComputeDualVariables(Tao tao, Vec DL, Vec DU)
267 {
268   PetscFunctionBegin;
269   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
270   PetscValidHeaderSpecific(DL, VEC_CLASSID, 2);
271   PetscValidHeaderSpecific(DU, VEC_CLASSID, 3);
272   PetscCheckSameComm(tao, 1, DL, 2);
273   PetscCheckSameComm(tao, 1, DU, 3);
274   if (tao->ops->computedual) {
275     PetscUseTypeMethod(tao, computedual, DL, DU);
276   } else {
277     PetscCall(VecSet(DL, 0.0));
278     PetscCall(VecSet(DU, 0.0));
279   }
280   PetscFunctionReturn(PETSC_SUCCESS);
281 }
282 
283 /*@
284   TaoGetDualVariables - Gets the dual vectors
285 
286   Collective
287 
288   Input Parameter:
289 . tao - the `Tao` context
290 
291   Output Parameters:
292 + DE - dual variable vector for the lower bounds
293 - DI - dual variable vector for the upper bounds
294 
295   Level: advanced
296 
297 .seealso: [](ch_tao), `Tao`, `TaoComputeDualVariables()`
298 @*/
TaoGetDualVariables(Tao tao,Vec * DE,Vec * DI)299 PetscErrorCode TaoGetDualVariables(Tao tao, Vec *DE, Vec *DI)
300 {
301   PetscFunctionBegin;
302   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
303   if (DE) *DE = tao->DE;
304   if (DI) *DI = tao->DI;
305   PetscFunctionReturn(PETSC_SUCCESS);
306 }
307 
308 /*@C
309   TaoSetEqualityConstraintsRoutine - Sets a function to be used to compute constraints.  Tao only handles constraints under certain conditions, see [](ch_tao) for details
310 
311   Logically Collective
312 
313   Input Parameters:
314 + tao  - the `Tao` context
315 . ce   - A vector that will be used to store equality constraint evaluation
316 . func - the bounds computation routine
317 - ctx  - [optional] user-defined context for private data for the equality constraints computation (may be `NULL`)
318 
319   Calling sequence of `func`:
320 + tao - the `Tao` solver
321 . x   - point to evaluate equality constraints
322 . ce  - vector of equality constraints evaluated at x
323 - ctx - the (optional) user-defined function context
324 
325   Level: intermediate
326 
327 .seealso: [](ch_tao), `Tao`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoSetVariableBounds()`
328 @*/
TaoSetEqualityConstraintsRoutine(Tao tao,Vec ce,PetscErrorCode (* func)(Tao tao,Vec x,Vec ce,PetscCtx ctx),PetscCtx ctx)329 PetscErrorCode TaoSetEqualityConstraintsRoutine(Tao tao, Vec ce, PetscErrorCode (*func)(Tao tao, Vec x, Vec ce, PetscCtx ctx), PetscCtx ctx)
330 {
331   PetscFunctionBegin;
332   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
333   if (ce) PetscValidHeaderSpecific(ce, VEC_CLASSID, 2);
334   PetscCall(PetscObjectReference((PetscObject)ce));
335   PetscCall(VecDestroy(&tao->constraints_equality));
336   tao->eq_constrained                  = func ? PETSC_TRUE : PETSC_FALSE;
337   tao->constraints_equality            = ce;
338   tao->user_con_equalityP              = ctx;
339   tao->ops->computeequalityconstraints = func;
340   PetscFunctionReturn(PETSC_SUCCESS);
341 }
342 
343 /*@C
344   TaoGetEqualityConstraintsRoutine - Gets the function used to compute equality constraints.
345 
346   Not Collective
347 
348   Input Parameter:
349 . tao - the `Tao` context
350 
351   Output Parameters:
352 + ci   - the vector to internally hold the constraint computation
353 . func - the bounds computation routine
354 - ctx  - the (optional) user-defined context
355 
356   Calling sequence of `func`:
357 + tao - the `Tao` solver
358 . x   - point to evaluate equality constraints
359 . ci  - vector of equality constraints evaluated at x
360 - ctx - the (optional) user-defined function context
361 
362   Level: intermediate
363 
364 .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoGetObjective()`, `TaoGetGradient()`, `TaoGetHessian()`, `TaoGetObjectiveAndGradient()`, `TaoGetInequalityConstraintsRoutine()`
365 @*/
TaoGetEqualityConstraintsRoutine(Tao tao,Vec * ci,PetscErrorCode (** func)(Tao tao,Vec x,Vec ci,PetscCtx ctx),PetscCtxRt ctx)366 PetscErrorCode TaoGetEqualityConstraintsRoutine(Tao tao, Vec *ci, PetscErrorCode (**func)(Tao tao, Vec x, Vec ci, PetscCtx ctx), PetscCtxRt ctx)
367 {
368   PetscFunctionBegin;
369   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
370   if (ci) *ci = tao->constraints_equality;
371   if (func) *func = tao->ops->computeequalityconstraints;
372   if (ctx) *(void **)ctx = tao->user_con_equalityP;
373   PetscFunctionReturn(PETSC_SUCCESS);
374 }
375 
376 /*@C
377   TaoSetInequalityConstraintsRoutine - Sets a function to be used to compute constraints.  Tao only handles constraints under certain conditions, see [](ch_tao) for details
378 
379   Logically Collective
380 
381   Input Parameters:
382 + tao  - the `Tao` context
383 . ci   - A vector that will be used to store inequality constraint evaluation
384 . func - the bounds computation routine
385 - ctx  - [optional] user-defined context for private data for the inequality constraints computation (may be `NULL`)
386 
387   Calling sequence of `func`:
388 + tao - the `Tao` solver
389 . x   - point to evaluate inequality constraints
390 . ci  - vector of inequality constraints evaluated at x
391 - ctx - the (optional) user-defined function context
392 
393   Level: intermediate
394 
395 .seealso: [](ch_tao), `Tao`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoSetVariableBounds()`
396 @*/
TaoSetInequalityConstraintsRoutine(Tao tao,Vec ci,PetscErrorCode (* func)(Tao tao,Vec x,Vec ci,PetscCtx ctx),PetscCtx ctx)397 PetscErrorCode TaoSetInequalityConstraintsRoutine(Tao tao, Vec ci, PetscErrorCode (*func)(Tao tao, Vec x, Vec ci, PetscCtx ctx), PetscCtx ctx)
398 {
399   PetscFunctionBegin;
400   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
401   if (ci) PetscValidHeaderSpecific(ci, VEC_CLASSID, 2);
402   PetscCall(PetscObjectReference((PetscObject)ci));
403   PetscCall(VecDestroy(&tao->constraints_inequality));
404   tao->constraints_inequality            = ci;
405   tao->ineq_constrained                  = func ? PETSC_TRUE : PETSC_FALSE;
406   tao->user_con_inequalityP              = ctx;
407   tao->ops->computeinequalityconstraints = func;
408   PetscFunctionReturn(PETSC_SUCCESS);
409 }
410 
411 /*@C
412   TaoGetInequalityConstraintsRoutine - Gets the function used to compute inequality constraints.
413 
414   Not Collective
415 
416   Input Parameter:
417 . tao - the `Tao` context
418 
419   Output Parameters:
420 + ci   - the vector to internally hold the constraint computation
421 . func - the bounds computation routine
422 - ctx  - the (optional) user-defined context
423 
424   Calling sequence of `func`:
425 + tao - the `Tao` solver
426 . x   - point to evaluate inequality constraints
427 . ci  - vector of inequality constraints evaluated at x
428 - ctx - the (optional) user-defined function context
429 
430   Level: intermediate
431 
432 .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoGetObjective()`, `TaoGetGradient()`, `TaoGetHessian()`, `TaoGetObjectiveAndGradient()`, `TaoGetEqualityConstraintsRoutine()`
433 @*/
TaoGetInequalityConstraintsRoutine(Tao tao,Vec * ci,PetscErrorCode (** func)(Tao tao,Vec x,Vec ci,PetscCtx ctx),PetscCtxRt ctx)434 PetscErrorCode TaoGetInequalityConstraintsRoutine(Tao tao, Vec *ci, PetscErrorCode (**func)(Tao tao, Vec x, Vec ci, PetscCtx ctx), PetscCtxRt ctx)
435 {
436   PetscFunctionBegin;
437   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
438   if (ci) *ci = tao->constraints_inequality;
439   if (func) *func = tao->ops->computeinequalityconstraints;
440   if (ctx) *(void **)ctx = tao->user_con_inequalityP;
441   PetscFunctionReturn(PETSC_SUCCESS);
442 }
443 
444 /*@
445   TaoComputeEqualityConstraints - Compute the variable bounds using the
446   routine set by `TaoSetEqualityConstraintsRoutine()`.
447 
448   Collective
449 
450   Input Parameter:
451 . tao - the `Tao` context
452 
453   Output Parameters:
454 + X  - point the equality constraints were evaluated on
455 - CE - vector of equality constraints evaluated at X
456 
457   Level: developer
458 
459 .seealso: [](ch_tao), `Tao`, `TaoSetEqualityConstraintsRoutine()`, `TaoComputeJacobianEquality()`, `TaoComputeInequalityConstraints()`
460 @*/
TaoComputeEqualityConstraints(Tao tao,Vec X,Vec CE)461 PetscErrorCode TaoComputeEqualityConstraints(Tao tao, Vec X, Vec CE)
462 {
463   PetscFunctionBegin;
464   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
465   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
466   PetscValidHeaderSpecific(CE, VEC_CLASSID, 3);
467   PetscCheckSameComm(tao, 1, X, 2);
468   PetscCheckSameComm(tao, 1, CE, 3);
469   PetscCall(PetscLogEventBegin(TAO_ConstraintsEval, tao, X, CE, NULL));
470   PetscCallBack("Tao callback equality constraints", (*tao->ops->computeequalityconstraints)(tao, X, CE, tao->user_con_equalityP));
471   PetscCall(PetscLogEventEnd(TAO_ConstraintsEval, tao, X, CE, NULL));
472   tao->nconstraints++;
473   PetscFunctionReturn(PETSC_SUCCESS);
474 }
475 
476 /*@
477   TaoComputeInequalityConstraints - Compute the variable bounds using the
478   routine set by `TaoSetInequalityConstraintsRoutine()`.
479 
480   Collective
481 
482   Input Parameter:
483 . tao - the `Tao` context
484 
485   Output Parameters:
486 + X  - point the inequality constraints were evaluated on
487 - CI - vector of inequality constraints evaluated at X
488 
489   Level: developer
490 
491 .seealso: [](ch_tao), `Tao`, `TaoSetInequalityConstraintsRoutine()`, `TaoComputeJacobianInequality()`, `TaoComputeEqualityConstraints()`
492 @*/
TaoComputeInequalityConstraints(Tao tao,Vec X,Vec CI)493 PetscErrorCode TaoComputeInequalityConstraints(Tao tao, Vec X, Vec CI)
494 {
495   PetscFunctionBegin;
496   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
497   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
498   PetscValidHeaderSpecific(CI, VEC_CLASSID, 3);
499   PetscCheckSameComm(tao, 1, X, 2);
500   PetscCheckSameComm(tao, 1, CI, 3);
501   PetscCall(PetscLogEventBegin(TAO_ConstraintsEval, tao, X, CI, NULL));
502   PetscCallBack("Tao callback inequality constraints", (*tao->ops->computeinequalityconstraints)(tao, X, CI, tao->user_con_inequalityP));
503   PetscCall(PetscLogEventEnd(TAO_ConstraintsEval, tao, X, CI, NULL));
504   tao->nconstraints++;
505   PetscFunctionReturn(PETSC_SUCCESS);
506 }
507