Actual source code: drawreg.c

  1: /*
  2:        Provides the registration process for PETSc PetscDraw routines
  3: */
  4: #include <petsc/private/drawimpl.h>
  5: #include <petscviewer.h>
  6: #if PetscDefined(HAVE_SAWS)
  7: #include <petscviewersaws.h>
  8: #endif

 10: /*
 11:    Contains the list of registered PetscDraw routines
 12: */
 13: PetscFunctionList PetscDrawList = NULL;

 15: /*@
 16:   PetscDrawView - Prints the `PetscDraw` data structure.

 18:   Collective

 20:   Input Parameters:
 21: + indraw - the `PetscDraw` context
 22: - viewer - visualization context

 24:    See PetscDrawSetFromOptions() for options database keys

 26:   Note:
 27:   The available visualization contexts include
 28: +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
 29: -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
 30:   output where only the first processor opens
 31:   the file.  All other processors send their
 32:   data to the first processor to print.

 34:   The user can open an alternative visualization context with
 35:   `PetscViewerASCIIOpen()` - output to a specified file.

 37:   Level: beginner

 39: .seealso: `PetscDraw`, `PetscViewerASCIIOpen()`, `PetscViewer`
 40: @*/
 41: PetscErrorCode PetscDrawView(PetscDraw indraw, PetscViewer viewer)
 42: {
 43:   PetscBool isdraw;
 44: #if PetscDefined(HAVE_SAWS)
 45:   PetscBool issaws;
 46: #endif

 48:   PetscFunctionBegin;
 50:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)indraw), &viewer));
 52:   PetscCheckSameComm(indraw, 1, viewer, 2);

 54:   PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)indraw, viewer));
 55:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
 56: #if PetscDefined(HAVE_SAWS)
 57:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
 58: #endif
 59:   if (isdraw) {
 60:     PetscDraw draw;
 61:     char      str[36];
 62:     PetscReal x, y, bottom, h;

 64:     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
 65:     PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
 66:     PetscCall(PetscStrncpy(str, "PetscDraw: ", sizeof(str)));
 67:     PetscCall(PetscStrlcat(str, ((PetscObject)indraw)->type_name, sizeof(str)));
 68:     PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_RED, PETSC_DRAW_BLACK, str, NULL, &h));
 69:     bottom = y - h;
 70:     PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
 71: #if PetscDefined(HAVE_SAWS)
 72:   } else if (issaws) {
 73:     PetscMPIInt rank;

 75:     PetscCall(PetscObjectName((PetscObject)indraw));
 76:     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
 77:     if (!((PetscObject)indraw)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)indraw, viewer));
 78: #endif
 79:   } else PetscTryTypeMethod(indraw, view, viewer);
 80:   PetscFunctionReturn(PETSC_SUCCESS);
 81: }

 83: /*@
 84:   PetscDrawViewFromOptions - View a `PetscDraw` from the option database

 86:   Collective

 88:   Input Parameters:
 89: + A    - the `PetscDraw` context
 90: . obj  - optional object that provides the prefix for the option names, pass `NULL` to use the options prefix of `A`
 91: - name - command line option

 93:   Options Database Key:
 94: . -name viewer_specification - See `PetscOptionsCreateViewer()` for the values of `viewer_specification`

 96:   Level: intermediate

 98:   Note:
 99:   This checks the options database, creates the viewer on-the-fly, uses it and then destroys it. Hence it should not be called in heavily used routines,
100:   rather `PetscOptionsCreateViewer()` should be used to construct the viewer once which can then be utilized in the heavily used routine.

102: .seealso: `PetscDraw`, `PetscDrawView()`, `PetscObjectViewFromOptions()`, `PetscDrawCreate()`, `PetscOptionsCreateViewer()`
103: @*/
104: PetscErrorCode PetscDrawViewFromOptions(PetscDraw A, PetscObject obj, const char name[])
105: {
106:   PetscFunctionBegin;
108:   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
109:   PetscFunctionReturn(PETSC_SUCCESS);
110: }

112: /*@
113:   PetscDrawCreate - Creates a graphics context.

115:   Collective

117:   Input Parameters:
118: + comm    - MPI communicator
119: . display - X display when using X Windows
120: . title   - optional title added to top of window
121: . x       - horizonatl coordinate of lower left corner of window or `PETSC_DECIDE`
122: . y       - vertical coordinate of lower left corner of window or `PETSC_DECIDE`
123: . w       - width of window, `PETSC_DECIDE`, `PETSC_DRAW_HALF_SIZE`, `PETSC_DRAW_FULL_SIZE`, `PETSC_DRAW_THIRD_SIZE` or `PETSC_DRAW_QUARTER_SIZE`
124: - h       - height of window, `PETSC_DECIDE`, `PETSC_DRAW_HALF_SIZE`, `PETSC_DRAW_FULL_SIZE`, `PETSC_DRAW_THIRD_SIZE` or `PETSC_DRAW_QUARTER_SIZE`

126:   Output Parameter:
127: . indraw - location to put the `PetscDraw` context

129:   Level: beginner

131: .seealso: `PetscDrawSetType()`, `PetscDrawSetFromOptions()`, `PetscDrawDestroy()`, `PetscDrawLGCreate()`, `PetscDrawSPCreate()`,
132:           `PetscDrawViewPortsCreate()`, `PetscDrawViewPortsSet()`, `PetscDrawAxisCreate()`, `PetscDrawHGCreate()`, `PetscDrawBarCreate()`,
133:           `PetscViewerDrawGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSetSaveMovie()`, `PetscDrawSetSaveFinalImage()`,
134:           `PetscDrawOpenX()`, `PetscDrawOpenImage()`, `PetscDrawIsNull()`, `PetscDrawGetPopup()`, `PetscDrawCheckResizedWindow()`, `PetscDrawResizeWindow()`,
135:           `PetscDrawGetWindowSize()`, `PetscDrawLine()`, `PetscDrawArrow()`, `PetscDrawLineSetWidth()`, `PetscDrawLineGetWidth()`, `PetscDrawMarker()`,
136:           `PetscDrawPoint()`, `PetscDrawRectangle()`, `PetscDrawTriangle()`, `PetscDrawEllipse()`, `PetscDrawString()`, `PetscDrawStringCentered()`,
137:           `PetscDrawStringBoxed()`, `PetscDrawStringVertical()`, `PetscDrawSetViewPort()`, `PetscDrawGetViewPort()`,
138:           `PetscDrawSplitViewPort()`, `PetscDrawSetTitle()`, `PetscDrawAppendTitle()`, `PetscDrawGetTitle()`, `PetscDrawSetPause()`, `PetscDrawGetPause()`,
139:           `PetscDrawPause()`, `PetscDrawSetDoubleBuffer()`, `PetscDrawClear()`, `PetscDrawFlush()`, `PetscDrawGetSingleton()`, `PetscDrawGetMouseButton()`,
140:           `PetscDrawZoom()`, `PetscDrawGetBoundingBox()`
141: @*/
142: PetscErrorCode PetscDrawCreate(MPI_Comm comm, const char display[], const char title[], int x, int y, int w, int h, PetscDraw *indraw)
143: {
144:   PetscDraw draw;
145:   PetscReal dpause = 0.0;
146:   PetscBool flag;

148:   PetscFunctionBegin;
149:   PetscAssertPointer(indraw, 8);
150:   PetscCall(PetscDrawInitializePackage());

152:   PetscCall(PetscHeaderCreate(draw, PETSC_DRAW_CLASSID, "Draw", "Graphics", "Draw", comm, PetscDrawDestroy, PetscDrawView));
153:   draw->data = NULL;
154:   PetscCall(PetscStrallocpy(display, &draw->display));
155:   PetscCall(PetscStrallocpy(title, &draw->title));
156:   draw->x       = x;
157:   draw->y       = y;
158:   draw->w       = w;
159:   draw->h       = h;
160:   draw->pause   = 0.0;
161:   draw->coor_xl = 0.0;
162:   draw->coor_xr = 1.0;
163:   draw->coor_yl = 0.0;
164:   draw->coor_yr = 1.0;
165:   draw->port_xl = 0.0;
166:   draw->port_xr = 1.0;
167:   draw->port_yl = 0.0;
168:   draw->port_yr = 1.0;
169:   draw->popup   = NULL;

171:   PetscCall(PetscOptionsGetReal(NULL, NULL, "-draw_pause", &dpause, &flag));
172:   if (flag) draw->pause = dpause;

174:   draw->savefilename   = NULL;
175:   draw->saveimageext   = NULL;
176:   draw->savemovieext   = NULL;
177:   draw->savefilecount  = 0;
178:   draw->savesinglefile = PETSC_FALSE;
179:   draw->savemoviefps   = PETSC_DECIDE;

181:   PetscCall(PetscDrawSetCurrentPoint(draw, .5, .9));

183:   draw->boundbox_xl = .5;
184:   draw->boundbox_xr = .5;
185:   draw->boundbox_yl = .9;
186:   draw->boundbox_yr = .9;

188:   *indraw = draw;
189:   PetscFunctionReturn(PETSC_SUCCESS);
190: }

192: /*@
193:   PetscDrawSetType - Builds graphics object for a particular implementation

195:   Collective

197:   Input Parameters:
198: + draw - the graphics context
199: - type - for example, `PETSC_DRAW_X`

201:   Options Database Key:
202: . -draw_type (x|null|win32|tikz|image) - Sets the type; see `PetscDrawType`

204:   Level: intermediate

206:   Notes:
207:   See `PetscDrawSetFromOptions()` for additional options database keys

209:   See `PetscDrawType` for available methods (for instance,
210:   `PETSC_DRAW_X`, `PETSC_DRAW_TIKZ` or `PETSC_DRAW_IMAGE`)

212: .seealso: `PetscDraw`, `PETSC_DRAW_X`, `PETSC_DRAW_TIKZ`, `PETSC_DRAW_IMAGE`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`, `PetscDrawType`
213: @*/
214: PetscErrorCode PetscDrawSetType(PetscDraw draw, PetscDrawType type)
215: {
216:   PetscBool match;
217:   PetscBool flg = PETSC_FALSE;
218:   PetscErrorCode (*r)(PetscDraw);

220:   PetscFunctionBegin;
222:   PetscAssertPointer(type, 2);

224:   PetscCall(PetscObjectTypeCompare((PetscObject)draw, type, &match));
225:   if (match) PetscFunctionReturn(PETSC_SUCCESS);

227:   /*  User requests no graphics */
228:   PetscCall(PetscOptionsHasName(((PetscObject)draw)->options, NULL, "-nox", &flg));

230:   /*
231:      This is not ideal, but it allows codes to continue to run if X graphics
232:    was requested but is not installed on this machine. Mostly this is for
233:    testing.
234:    */
235: #if !PetscDefined(HAVE_X)
236:   if (!flg) {
237:     PetscCall(PetscStrcmp(type, PETSC_DRAW_X, &match));
238:     if (match) {
239:       PetscBool dontwarn = PETSC_TRUE;
240:       flg                = PETSC_TRUE;
241:       PetscCall(PetscOptionsHasName(NULL, NULL, "-nox_warning", &dontwarn));
242:       if (!dontwarn) PetscCall((*PetscErrorPrintf)("PETSc installed without X Windows on this machine\nproceeding without graphics\n"));
243:     }
244:   }
245: #endif
246:   if (flg) {
247:     PetscCall(PetscStrcmp(type, "tikz", &flg));
248:     if (!flg) type = PETSC_DRAW_NULL;
249:   }

251:   PetscCall(PetscStrcmp(type, PETSC_DRAW_NULL, &match));
252:   if (match) {
253:     PetscCall(PetscOptionsHasName(NULL, NULL, "-draw_double_buffer", NULL));
254:     PetscCall(PetscOptionsHasName(NULL, NULL, "-draw_virtual", NULL));
255:     PetscCall(PetscOptionsHasName(NULL, NULL, "-draw_fast", NULL));
256:     PetscCall(PetscOptionsHasName(NULL, NULL, "-draw_ports", NULL));
257:     PetscCall(PetscOptionsHasName(NULL, NULL, "-draw_coordinates", NULL));
258:   }

260:   PetscCall(PetscFunctionListFind(PetscDrawList, type, &r));
261:   PetscCheck(r, PetscObjectComm((PetscObject)draw), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDraw type given: %s", type);
262:   PetscTryTypeMethod(draw, destroy);
263:   PetscCall(PetscMemzero(draw->ops, sizeof(struct _PetscDrawOps)));
264:   PetscCall(PetscObjectChangeTypeName((PetscObject)draw, type));
265:   PetscCall((*r)(draw));
266:   PetscFunctionReturn(PETSC_SUCCESS);
267: }

269: /*@
270:   PetscDrawGetType - Gets the `PetscDraw` type as a string from the `PetscDraw` object.

272:   Not Collective

274:   Input Parameter:
275: . draw - Krylov context

277:   Output Parameter:
278: . type - name of PetscDraw method

280:   Level: advanced

282:   Note:
283:   `type` should not be retained for later use as it will be an invalid pointer if the `PetscDrawType` of `draw` is changed.

285: .seealso: `PetscDraw`, `PetscDrawType`, `PetscDrawSetType()`, `PetscDrawCreate()`, `PetscObjectTypeCompare()`, `PetscObjectTypeCompareAny()`
286: @*/
287: PetscErrorCode PetscDrawGetType(PetscDraw draw, PetscDrawType *type)
288: {
289:   PetscFunctionBegin;
291:   PetscAssertPointer(type, 2);
292:   *type = ((PetscObject)draw)->type_name;
293:   PetscFunctionReturn(PETSC_SUCCESS);
294: }

296: /*@
297:   PetscDrawRegister - Adds a method to the graphics package.

299:   Not Collective, No Fortran Support

301:   Input Parameters:
302: + sname    - name of a new user-defined graphics class
303: - function - routine to create method context

305:   Level: developer

307:   Note:
308:   `PetscDrawRegister()` may be called multiple times to add several user-defined graphics classes

310:   Example Usage:
311: .vb
312:    PetscDrawRegister("my_draw_type", MyDrawCreate);
313: .ve

315:   Then, your specific graphics package can be chosen with the procedural interface via
316: .vb
317:   PetscDrawSetType(ksp, "my_draw_type")
318: .ve
319:   or at runtime via the option
320: .vb
321:   -draw_type my_draw_type
322: .ve

324: .seealso: `PetscDraw`, `PetscDrawRegisterAll()`, `PetscDrawRegisterDestroy()`, `PetscDrawType`, `PetscDrawSetType()`
325: @*/
326: PetscErrorCode PetscDrawRegister(const char *sname, PetscErrorCode (*function)(PetscDraw))
327: {
328:   PetscFunctionBegin;
329:   PetscCall(PetscDrawInitializePackage());
330:   PetscCall(PetscFunctionListAdd(&PetscDrawList, sname, function));
331:   PetscFunctionReturn(PETSC_SUCCESS);
332: }

334: /*@
335:   PetscDrawSetOptionsPrefix - Sets the prefix used for searching for all
336:   `PetscDraw` options in the database.

338:   Logically Collective

340:   Input Parameters:
341: + draw   - the draw context
342: - prefix - the prefix to prepend to all option names

344:   Level: advanced

346: .seealso: `PetscDraw`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`
347: @*/
348: PetscErrorCode PetscDrawSetOptionsPrefix(PetscDraw draw, const char prefix[])
349: {
350:   PetscFunctionBegin;
352:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)draw, prefix));
353:   PetscFunctionReturn(PETSC_SUCCESS);
354: }

356: /*@
357:   PetscDrawSetFromOptions - Sets the graphics type from the options database as well as other draw options.

359:   Collective

361:   Input Parameter:
362: . draw - the graphics context

364:   Options Database Keys:
365: + -nox                                        - do not use X graphics (ignore graphics calls, but run program correctly)
366: . -nox_warning                                - when X Windows support is not installed this prevents the warning message from being printed
367: . -draw_pause seconds                         - -1 indicates wait for mouse input, -2 indicates pause when window is to be destroyed
368: . -draw_marker_type (cross|point|plus|circle) - set the marker type, see `PetscDrawMarkerType`
369: . -draw_save [filename]                       - (X Windows only) saves each image before it is cleared to a file
370: . -draw_save_final_image [filename]           - (X Windows only) saves the final image displayed in a window
371: . -draw_save_movie [.ext]                     - converts image files to a movie  at the end of the run. See `PetscDrawSetSaveMovie()`
372: . -draw_save_single_file (true|false)         - saves each new image in the same file, normally each new image is saved in a new file with 'filename/filename_%d.ext'
373: . -draw_save_on_clear (true|false)            - saves an image on each clear, mainly for debugging
374: - -draw_save_on_flush (true|false)            - saves an image on each flush, mainly for debugging

376:   Level: intermediate

378:   Notes:
379:   Must be called after `PetscDrawCreate()` but before the `PetscDraw` is used.

381:   Defaults to a PETSc X Windows graphics.

383: .seealso: `PetscDraw`, `PetscDrawCreate()`, `PetscDrawSetType()`, `PetscDrawSetSave()`, `PetscDrawSetSaveFinalImage()`, `PetscDrawPause()`, `PetscDrawSetPause()`,
384:           `PetscDrawSetSaveMovie()`
385: @*/
386: PetscErrorCode PetscDrawSetFromOptions(PetscDraw draw)
387: {
388:   PetscBool   flg, nox;
389:   char        vtype[256];
390:   const char *def;
391: #if !PetscDefined(USE_WINDOWS_GRAPHICS) && !PetscDefined(HAVE_X)
392:   PetscBool warn;
393: #endif

395:   PetscFunctionBegin;

398:   PetscCall(PetscDrawRegisterAll());

400:   if (((PetscObject)draw)->type_name) def = ((PetscObject)draw)->type_name;
401:   else {
402:     PetscCall(PetscOptionsHasName(((PetscObject)draw)->options, NULL, "-nox", &nox));
403:     def = PETSC_DRAW_NULL;
404: #if PetscDefined(USE_WINDOWS_GRAPHICS)
405:     if (!nox) def = PETSC_DRAW_WIN32;
406: #elif PetscDefined(HAVE_X)
407:     if (!nox) def = PETSC_DRAW_X;
408: #else
409:     PetscCall(PetscOptionsHasName(NULL, NULL, "-nox_warning", &warn));
410:     if (!nox && !warn) PetscCall((*PetscErrorPrintf)("PETSc installed without X Windows or Microsoft Graphics on this machine\nproceeding without graphics\n"));
411: #endif
412:   }
413:   PetscObjectOptionsBegin((PetscObject)draw);
414:   PetscCall(PetscOptionsFList("-draw_type", "Type of graphical output", "PetscDrawSetType", PetscDrawList, def, vtype, sizeof(vtype), &flg));
415:   if (flg) {
416:     PetscCall(PetscDrawSetType(draw, vtype));
417:   } else if (!((PetscObject)draw)->type_name) {
418:     PetscCall(PetscDrawSetType(draw, def));
419:   }
420:   PetscCall(PetscOptionsName("-nox", "Run without graphics", "None", &nox));
421:   {
422:     char      filename[PETSC_MAX_PATH_LEN];
423:     char      movieext[32];
424:     PetscBool image, movie;
425:     PetscCall(PetscSNPrintf(filename, sizeof(filename), "%s%s", draw->savefilename ? draw->savefilename : "", draw->saveimageext ? draw->saveimageext : ""));
426:     PetscCall(PetscSNPrintf(movieext, sizeof(movieext), "%s", draw->savemovieext ? draw->savemovieext : ""));
427:     PetscCall(PetscOptionsString("-draw_save", "Save graphics to image file", "PetscDrawSetSave", filename, filename, sizeof(filename), &image));
428:     PetscCall(PetscOptionsString("-draw_save_movie", "Make a movie from saved images", "PetscDrawSetSaveMovie", movieext, movieext, sizeof(movieext), &movie));
429:     PetscCall(PetscOptionsInt("-draw_save_movie_fps", "Set frames per second in saved movie", PETSC_FUNCTION_NAME, draw->savemoviefps, &draw->savemoviefps, NULL));
430:     PetscCall(PetscOptionsBool("-draw_save_single_file", "Each new image replaces previous image in file", PETSC_FUNCTION_NAME, draw->savesinglefile, &draw->savesinglefile, NULL));
431:     if (image) PetscCall(PetscDrawSetSave(draw, filename));
432:     if (movie) PetscCall(PetscDrawSetSaveMovie(draw, movieext));
433:     PetscCall(PetscOptionsString("-draw_save_final_image", "Save final graphics to image file", "PetscDrawSetSaveFinalImage", filename, filename, sizeof(filename), &image));
434:     if (image) PetscCall(PetscDrawSetSaveFinalImage(draw, filename));
435:     PetscCall(PetscOptionsBool("-draw_save_on_clear", "Save graphics to file on each clear", PETSC_FUNCTION_NAME, draw->saveonclear, &draw->saveonclear, NULL));
436:     PetscCall(PetscOptionsBool("-draw_save_on_flush", "Save graphics to file on each flush", PETSC_FUNCTION_NAME, draw->saveonflush, &draw->saveonflush, NULL));
437:   }
438:   PetscCall(PetscOptionsReal("-draw_pause", "Amount of time that program pauses after plots", "PetscDrawSetPause", draw->pause, &draw->pause, NULL));
439:   PetscCall(PetscOptionsEnum("-draw_marker_type", "Type of marker to use on plots", "PetscDrawSetMarkerType", PetscDrawMarkerTypes, (PetscEnum)draw->markertype, (PetscEnum *)&draw->markertype, NULL));

441:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
442:   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)draw, PetscOptionsObject));

444:   PetscCall(PetscDrawViewFromOptions(draw, NULL, "-draw_view"));
445:   PetscOptionsEnd();
446:   PetscFunctionReturn(PETSC_SUCCESS);
447: }