Actual source code: destroy.c

  1: /*
  2:      Provides utility routines for manulating any type of PETSc object.
  3: */
  4: #include <petsc/private/petscimpl.h>
  5: #include <petscviewer.h>

  7: static PetscErrorCode DestroyComposedData(void ***composed_star, PetscObjectState **state_star, PetscInt *count_star, void **composed, PetscObjectState **state)
  8: {
  9:   void **tmp_star = *composed_star;

 11:   PetscFunctionBegin;
 12:   for (PetscInt i = 0, imax = *count_star; i < imax; ++i) PetscCall(PetscFree(tmp_star[i]));
 13:   PetscCall(PetscFree2(*composed_star, *state_star));
 14:   PetscCall(PetscFree2(*composed, *state));
 15:   *count_star = 0;
 16:   PetscFunctionReturn(PETSC_SUCCESS);
 17: }

 19: PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj)
 20: {
 21:   PetscFunctionBegin;
 23:   PetscCall(DestroyComposedData((void ***)&obj->intstarcomposeddata, &obj->intstarcomposedstate, &obj->intstar_idmax, (void **)&obj->intcomposeddata, &obj->intcomposedstate));
 24:   PetscCall(DestroyComposedData((void ***)&obj->realstarcomposeddata, &obj->realstarcomposedstate, &obj->realstar_idmax, (void **)&obj->realcomposeddata, &obj->realcomposedstate));
 25: #if PetscDefined(USE_COMPLEX)
 26:   PetscCall(DestroyComposedData((void ***)&obj->scalarstarcomposeddata, &obj->scalarstarcomposedstate, &obj->scalarstar_idmax, (void **)&obj->scalarcomposeddata, &obj->scalarcomposedstate));
 27: #endif
 28:   PetscFunctionReturn(PETSC_SUCCESS);
 29: }

 31: /*@
 32:   PetscObjectDestroy - Destroys a `PetscObject`, regardless of the type.

 34:   Collective

 36:   Input Parameter:
 37: . obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`\*), for example,
 38:         `PetscObjectDestroy`((`PetscObject`\*)&mat);

 40:   Level: beginner

 42: .seealso: `PetscObject`
 43: @*/
 44: PetscErrorCode PetscObjectDestroy(PetscObject *obj)
 45: {
 46:   PetscFunctionBegin;
 47:   if (!obj || !*obj) PetscFunctionReturn(PETSC_SUCCESS);
 49:   PetscCheck((*obj)->bops->destroy, PETSC_COMM_SELF, PETSC_ERR_PLIB, "This PETSc object of class %s does not have a generic destroy routine", (*obj)->class_name);
 50:   PetscCall((*(*obj)->bops->destroy)(obj));
 51:   PetscFunctionReturn(PETSC_SUCCESS);
 52: }

 54: /*@C
 55:   PetscObjectView - Views a `PetscObject` regardless of the type.

 57:   Collective

 59:   Input Parameters:
 60: + obj    - any PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`), for example,
 61:            `PetscObjectView`((`PetscObject`)mat,`viewer`);
 62: - viewer - any PETSc viewer

 64:   Level: intermediate

 66: .seealso: `PetscObject`, `PetscObjectViewFromOptions()`, `PetscViewer`
 67: @*/
 68: PetscErrorCode PetscObjectView(PetscObject obj, PetscViewer viewer)
 69: {
 70:   PetscFunctionBegin;
 72:   PetscCheck(obj->bops->view, PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic viewer routine");
 73:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(obj->comm, &viewer));

 76:   PetscCall((*obj->bops->view)(obj, viewer));
 77:   PetscFunctionReturn(PETSC_SUCCESS);
 78: }

 80: /*@C
 81:   PetscObjectViewFromOptions - Processes command line options to determine if/how a `PetscObject` is to be viewed.

 83:   Collective

 85:   Input Parameters:
 86: + obj        - the object
 87: . bobj       - optional other object that provides prefix (if `NULL` then the prefix in `obj` is used)
 88: - optionname - option string that is used to activate viewing

 90:   Options Database Key:
 91: . -optionname_view [viewertype]:... - option name and values. In actual usage this would be something like `-mat_coarse_view`

 93:   Level: developer

 95:   Notes:
 96:   The argument has the following form
 97: .vb
 98:     type:filename:format:filemode
 99: .ve
100:   where all parts are optional, but you need to include the colon to access the next part. For example, to read from an HDF5 file, use
101: .vb
102:     hdf5:sol.h5::read
103: .ve

105: .vb
106:     If no value is provided ascii:stdout is used
107:        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
108:                                                   for example ascii::ascii_info prints just the information about the object not all details
109:                                                   unless :append is given filename opens in write mode, overwriting what was already there
110:        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
111:        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
112:        socket[:port]                             defaults to the standard output port
113:        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
114: .ve

116:   This is not called directly but is called by, for example, `MatViewFromOptions()`

118: .seealso: `PetscObject`, `PetscObjectView()`, `PetscOptionsGetViewer()`
119: @*/
120: PetscErrorCode PetscObjectViewFromOptions(PetscObject obj, PetscObject bobj, const char optionname[])
121: {
122:   PetscViewer       viewer;
123:   PetscBool         flg;
124:   static PetscBool  incall = PETSC_FALSE;
125:   PetscViewerFormat format;
126:   const char       *prefix;

128:   PetscFunctionBegin;
131:   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
132:   incall = PETSC_TRUE;
133:   prefix = bobj ? bobj->prefix : obj->prefix;
134:   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)obj), obj->options, prefix, optionname, &viewer, &format, &flg));
135:   if (flg) {
136:     PetscCall(PetscViewerPushFormat(viewer, format));
137:     PetscCall(PetscObjectView(obj, viewer));
138:     PetscCall(PetscViewerFlush(viewer));
139:     PetscCall(PetscViewerPopFormat(viewer));
140:     PetscCall(PetscOptionsRestoreViewer(&viewer));
141:   }
142:   incall = PETSC_FALSE;
143:   PetscFunctionReturn(PETSC_SUCCESS);
144: }

146: /*@C
147:   PetscObjectTypeCompare - Determines whether a PETSc object is of a particular type.

149:   Not Collective

151:   Input Parameters:
152: + obj       - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`), for example,
153:               `PetscObjectTypeCompare`((`PetscObject`)mat);
154: - type_name - string containing a type name

156:   Output Parameter:
157: . same - `PETSC_TRUE` if the type of `obj` and `type_name` are the same or both `NULL`, else `PETSC_FALSE`

159:   Level: intermediate

161: .seealso: `PetscObject`, `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()`, `PetscObjectObjectTypeCompare()`
162: @*/
163: PetscErrorCode PetscObjectTypeCompare(PetscObject obj, const char type_name[], PetscBool *same)
164: {
165:   PetscFunctionBegin;
166:   PetscAssertPointer(same, 3);
167:   if (!obj) *same = (PetscBool)!type_name;
168:   else {
170:     if (!type_name || !obj->type_name) *same = (PetscBool)(!obj->type_name == !type_name);
171:     else {
172:       PetscAssertPointer(type_name, 2);
173:       PetscCall(PetscStrcmp(obj->type_name, type_name, same));
174:     }
175:   }
176:   PetscFunctionReturn(PETSC_SUCCESS);
177: }

179: /*@C
180:   PetscObjectObjectTypeCompare - Determines whether two PETSc objects are of the same type

182:   Logically Collective

184:   Input Parameters:
185: + obj1 - any PETSc object, for example a `Vec`, `Mat` or `KSP`.
186: - obj2 - another PETSc object

188:   Output Parameter:
189: . same - `PETSC_TRUE` if they are the same or both unset, else `PETSC_FALSE`

191:   Level: intermediate

193: .seealso: `PetscObjectTypeCompare()`, `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()`

195: @*/
196: PetscErrorCode PetscObjectObjectTypeCompare(PetscObject obj1, PetscObject obj2, PetscBool *same)
197: {
198:   PetscFunctionBegin;
201:   PetscAssertPointer(same, 3);
202:   PetscCall(PetscStrcmp(obj1->type_name, obj2->type_name, same));
203:   PetscFunctionReturn(PETSC_SUCCESS);
204: }

206: /*@C
207:   PetscObjectBaseTypeCompare - Determines whether a `PetscObject` is of a given base type. For example the base type of `MATSEQAIJPERM` is `MATSEQAIJ`

209:   Not Collective

211:   Input Parameters:
212: + obj       - the object
213: - type_name - string containing a type name

215:   Output Parameter:
216: . same - `PETSC_TRUE` if the object is of the same base type identified by `type_name` or both `NULL`, `PETSC_FALSE` otherwise

218:   Level: intermediate

220: .seealso: `PetscObject`, `PetscObjectTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()`
221: @*/
222: PetscErrorCode PetscObjectBaseTypeCompare(PetscObject obj, const char type_name[], PetscBool *same)
223: {
224:   PetscFunctionBegin;
225:   PetscAssertPointer(same, 3);
226:   if (!obj) *same = (PetscBool)!type_name;
227:   else {
229:     if (!type_name || !obj->type_name) *same = (PetscBool)(!obj->type_name == !type_name);
230:     else {
231:       PetscAssertPointer(type_name, 2);
232:       PetscCall(PetscStrbeginswith(obj->type_name, type_name, same));
233:     }
234:   }
235:   PetscFunctionReturn(PETSC_SUCCESS);
236: }

238: /*@C
239:   PetscObjectTypeCompareAny - Determines whether a PETSc object is of any of a list of types.

241:   Not Collective

243:   Input Parameters:
244: + obj       - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`),
245:               for example, `PetscObjectTypeCompareAny`((`PetscObject`)mat,...);
246: - type_name - one or more string arguments containing type names, pass the empty string "" as the last argument

248:   Output Parameter:
249: . match - `PETSC_TRUE` if the type of `obj` matches any in the list, else `PETSC_FALSE`

251:   Level: intermediate

253: .seealso: `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectTypeCompare()`, `PetscObjectBaseTypeCompare()`
254: @*/
255: PetscErrorCode PetscObjectTypeCompareAny(PetscObject obj, PetscBool *match, const char type_name[], ...)
256: {
257:   va_list Argp;

259:   PetscFunctionBegin;
260:   PetscAssertPointer(match, 2);
261:   *match = PETSC_FALSE;
262:   if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
263:   va_start(Argp, type_name);
264:   while (type_name && type_name[0]) {
265:     PetscBool found;
266:     PetscCall(PetscObjectTypeCompare(obj, type_name, &found));
267:     if (found) {
268:       *match = PETSC_TRUE;
269:       break;
270:     }
271:     type_name = va_arg(Argp, const char *);
272:   }
273:   va_end(Argp);
274:   PetscFunctionReturn(PETSC_SUCCESS);
275: }

277: /*@C
278:   PetscObjectBaseTypeCompareAny - Determines whether a PETSc object has the base type of any of a list of types.

280:   Not Collective

282:   Input Parameters:
283: + obj       - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`),
284:               for example, `PetscObjectBaseTypeCompareAny`((`PetscObject`)mat,...);
285: - type_name - one or more string arguments containing type names, pass the empty string "" as the last argument

287:   Output Parameter:
288: . match - `PETSC_TRUE` if the type of `obj` matches any in the list, else `PETSC_FALSE`

290:   Level: intermediate

292: .seealso: `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectTypeCompare()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`
293: @*/
294: PetscErrorCode PetscObjectBaseTypeCompareAny(PetscObject obj, PetscBool *match, const char type_name[], ...)
295: {
296:   va_list Argp;

298:   PetscFunctionBegin;
299:   PetscAssertPointer(match, 2);
300:   *match = PETSC_FALSE;
301:   va_start(Argp, type_name);
302:   while (type_name && type_name[0]) {
303:     PetscBool found;
304:     PetscCall(PetscObjectBaseTypeCompare(obj, type_name, &found));
305:     if (found) {
306:       *match = PETSC_TRUE;
307:       break;
308:     }
309:     type_name = va_arg(Argp, const char *);
310:   }
311:   va_end(Argp);
312:   PetscFunctionReturn(PETSC_SUCCESS);
313: }

315: typedef struct {
316:   PetscErrorCode (*func)(void);
317: } PetscFinalizeFunction;

319: typedef struct {
320:   PetscErrorCode (*func)(void *);
321:   void *ctx;
322: } PetscFinalizeFunctionWithCtx;

324: typedef enum {
325:   PETSC_FINALIZE_EMPTY,
326:   PETSC_FINALIZE_OBJECT,
327:   PETSC_FINALIZE_FUNC,
328:   PETSC_FINALIZE_FUNC_WITH_CTX
329: } PetscFinalizeType;

331: static const char *const PetscFinalizeTypes[] = {"PETSC_FINALIZE_EMPTY", "PETSC_FINALIZE_OBJECT", "PETSC_FINALIZE_FUNC", "PETSC_FINALIZE_FUNC_WITH_CTX", PETSC_NULLPTR};

333: typedef struct {
334:   union ThunkUnion
335:   {
336:     PetscObject                  obj;
337:     PetscFinalizeFunction        fn;
338:     PetscFinalizeFunctionWithCtx fnctx;
339:   } thunk;
340:   PetscFinalizeType type;
341: } PetscFinalizerContainer;

343: #define PETSC_MAX_REGISTERED_FINALIZERS 256
344: static int                     reg_count = 0;
345: static PetscFinalizerContainer regfin[PETSC_MAX_REGISTERED_FINALIZERS];

347: static PetscErrorCode PetscRunRegisteredFinalizers(void)
348: {
349:   PetscFunctionBegin;
350:   while (reg_count) {
351:     PetscFinalizerContainer top = regfin[--reg_count];

353:     regfin[reg_count].type = PETSC_FINALIZE_EMPTY;
354:     PetscCall(PetscArrayzero(&regfin[reg_count].thunk, 1));
355:     switch (top.type) {
356:     case PETSC_FINALIZE_OBJECT:
357:       top.thunk.obj->persistent = PETSC_FALSE;
358:       PetscCall(PetscObjectDestroy(&top.thunk.obj));
359:       break;
360:     case PETSC_FINALIZE_FUNC:
361:       PetscCall((*top.thunk.fn.func)());
362:       break;
363:     case PETSC_FINALIZE_FUNC_WITH_CTX:
364:       PetscCall((*top.thunk.fnctx.func)(top.thunk.fnctx.ctx));
365:       break;
366:     case PETSC_FINALIZE_EMPTY:
367:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Finalizer at position %d is empty, yet registration count %d != 0", reg_count, reg_count);
368:       break;
369:     }
370:   }
371:   PetscFunctionReturn(PETSC_SUCCESS);
372: }

374: static int PetscFinalizerContainerEqual(const PetscFinalizerContainer *a, const PetscFinalizerContainer *b)
375: {
376:   if (a->type != b->type) return 0;
377:   switch (a->type) {
378:   case PETSC_FINALIZE_EMPTY:
379:     break;
380:   case PETSC_FINALIZE_OBJECT:
381:     return a->thunk.obj == b->thunk.obj;
382:   case PETSC_FINALIZE_FUNC:
383:     return a->thunk.fn.func == b->thunk.fn.func;
384:   case PETSC_FINALIZE_FUNC_WITH_CTX:
385:     return a->thunk.fnctx.func == b->thunk.fnctx.func && a->thunk.fnctx.ctx == b->thunk.fnctx.ctx;
386:   }
387:   return 1;
388: }

390: static PetscErrorCode RegisterFinalizer(PetscFinalizerContainer container)
391: {
392:   PetscFunctionBegin;
393:   PetscAssert(reg_count < (int)PETSC_STATIC_ARRAY_LENGTH(regfin), PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "No more room in array, limit %zu, recompile %s with larger value for " PetscStringize(regfin), PETSC_STATIC_ARRAY_LENGTH(regfin), __FILE__);
394:   PetscAssert(regfin[reg_count].type == PETSC_FINALIZE_EMPTY, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Finalizer type (%s) at position %d is not PETSC_FINALIZE_EMPTY!", PetscFinalizeTypes[regfin[reg_count].type], reg_count);
395:   if (PetscDefined(USE_DEBUG)) {
396:     for (int i = 0; i < reg_count; ++i) PetscCheck(!PetscFinalizerContainerEqual(regfin + i, &container), PETSC_COMM_SELF, PETSC_ERR_ORDER, "Finalizer (of type %s) already registered!", PetscFinalizeTypes[container.type]);
397:   }
398:   regfin[reg_count++] = container;
399:   PetscFunctionReturn(PETSC_SUCCESS);
400: }

402: /*@C
403:   PetscObjectRegisterDestroy - Registers a PETSc object to be destroyed when
404:   `PetscFinalize()` is called.

406:   Logically Collective

408:   Input Parameter:
409: . obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`), for example,
410:         `PetscObjectRegisterDestroy`((`PetscObject`)mat);

412:   Level: developer

414:   Note:
415:   This is used by, for example, `PETSC_VIEWER_XXX_()` routines to free the viewer
416:   when PETSc ends.

418: .seealso: `PetscObjectRegisterDestroyAll()`
419: @*/
420: PetscErrorCode PetscObjectRegisterDestroy(PetscObject obj)
421: {
422:   PetscFinalizerContainer container;

424:   PetscFunctionBegin;
426:   container.thunk.obj = obj;
427:   container.type      = PETSC_FINALIZE_OBJECT;
428:   PetscCall(RegisterFinalizer(container));
429:   PetscFunctionReturn(PETSC_SUCCESS);
430: }

432: /*@C
433:   PetscObjectRegisterDestroyAll - Frees all the PETSc objects that have been registered
434:   with `PetscObjectRegisterDestroy()`. Called by `PetscFinalize()`

436:   Logically Collective on the individual `PetscObject`s that are being processed

438:   Level: developer

440: .seealso: `PetscObjectRegisterDestroy()`
441: @*/
442: PetscErrorCode PetscObjectRegisterDestroyAll(void)
443: {
444:   PetscFunctionBegin;
445:   PetscCall(PetscRunRegisteredFinalizers());
446:   PetscFunctionReturn(PETSC_SUCCESS);
447: }

449: /*@C
450:   PetscRegisterFinalize - Registers a function that is to be called in `PetscFinalize()`

452:   Not Collective

454:   Input Parameter:
455: . f - function to be called

457:   Level: developer

459:   Notes:
460:   This is used by, for example, `DMInitializePackage()` to have `DMFinalizePackage()` called

462:   Use `PetscObjectRegisterDestroy()` to register the destruction of an object in `PetscFinalize()`

464: .seealso: `PetscRegisterFinalizeAll()`, `PetscObjectRegisterDestroy()`
465: @*/
466: PetscErrorCode PetscRegisterFinalize(PetscErrorCode (*f)(void))
467: {
468:   PetscFinalizerContainer container;

470:   PetscFunctionBegin;
472:   container.thunk.fn.func = f;
473:   container.type          = PETSC_FINALIZE_FUNC;
474:   PetscCall(RegisterFinalizer(container));
475:   PetscFunctionReturn(PETSC_SUCCESS);
476: }

478: /*@C
479:   PetscRegisterFinalizeAll - Runs all the finalize functions set with `PetscRegisterFinalize()`

481:   Not Collective unless registered functions are collective

483:   Level: developer

485: .seealso: `PetscRegisterFinalize()`, `PetscObjectRegisterDestroyAll()`
486: @*/
487: PetscErrorCode PetscRegisterFinalizeAll(void)
488: {
489:   PetscFunctionBegin;
490:   PetscCall(PetscRunRegisteredFinalizers());
491:   PetscFunctionReturn(PETSC_SUCCESS);
492: }