Actual source code: drawreg.c


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

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

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

 19:    Collective

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

 25:    See PetscDrawSetFromOptions() for options database keys

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

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

 38:    Level: beginner

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

 49:   PetscFunctionBegin;
 51:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)indraw), &viewer));
 53:   PetscCheckSameComm(indraw, 1, viewer, 2);

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

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

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

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

 87:    Collective

 89:    Input Parameters:
 90: +  A - the `PetscDraw` context
 91: .  obj - Optional object
 92: -  name - command line option

 94:    Level: intermediate
 95: .seealso: `PetscDraw`, `PetscDrawView`, `PetscObjectViewFromOptions()`, `PetscDrawCreate()`
 96: @*/
 97: PetscErrorCode PetscDrawViewFromOptions(PetscDraw A, PetscObject obj, const char name[])
 98: {
 99:   PetscFunctionBegin;
101:   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
102:   PetscFunctionReturn(PETSC_SUCCESS);
103: }

105: /*@C
106:    PetscDrawCreate - Creates a graphics context.

108:    Collective

110:    Input Parameters:
111: +  comm - MPI communicator
112: .  display - X display when using X Windows
113: .  title - optional title added to top of window
114: .  x - horizonatl coordinate of lower left corner of window or `PETSC_DECIDE`
115: .  y - vertical coordinate of lower left corner of window or `PETSC_DECIDE`
116: .  w - width of window, `PETSC_DECIDE`, `PETSC_DRAW_HALF_SIZE`, `PETSC_DRAW_FULL_SIZE`, `PETSC_DRAW_THIRD_SIZE` or `PETSC_DRAW_QUARTER_SIZE`
117: -  h - height of window, `PETSC_DECIDE`, `PETSC_DRAW_HALF_SIZE`, `PETSC_DRAW_FULL_SIZE`, `PETSC_DRAW_THIRD_SIZE` or `PETSC_DRAW_QUARTER_SIZE`

119:    Output Parameter:
120: .  draw - location to put the `PetscDraw` context

122:    Level: beginner

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

141:   PetscFunctionBegin;
142:   PetscCall(PetscDrawInitializePackage());
143:   *indraw = NULL;
144:   PetscCall(PetscHeaderCreate(draw, PETSC_DRAW_CLASSID, "Draw", "Graphics", "Draw", comm, PetscDrawDestroy, PetscDrawView));

146:   draw->data = NULL;
147:   PetscCall(PetscStrallocpy(display, &draw->display));
148:   PetscCall(PetscStrallocpy(title, &draw->title));
149:   draw->x       = x;
150:   draw->y       = y;
151:   draw->w       = w;
152:   draw->h       = h;
153:   draw->pause   = 0.0;
154:   draw->coor_xl = 0.0;
155:   draw->coor_xr = 1.0;
156:   draw->coor_yl = 0.0;
157:   draw->coor_yr = 1.0;
158:   draw->port_xl = 0.0;
159:   draw->port_xr = 1.0;
160:   draw->port_yl = 0.0;
161:   draw->port_yr = 1.0;
162:   draw->popup   = NULL;

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

167:   draw->savefilename   = NULL;
168:   draw->saveimageext   = NULL;
169:   draw->savemovieext   = NULL;
170:   draw->savefilecount  = 0;
171:   draw->savesinglefile = PETSC_FALSE;
172:   draw->savemoviefps   = PETSC_DECIDE;

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

176:   draw->boundbox_xl = .5;
177:   draw->boundbox_xr = .5;
178:   draw->boundbox_yl = .9;
179:   draw->boundbox_yr = .9;

181:   *indraw = draw;
182:   PetscFunctionReturn(PETSC_SUCCESS);
183: }

185: /*@C
186:    PetscDrawSetType - Builds graphics object for a particular implementation

188:    Collective

190:    Input Parameters:
191: +  draw      - the graphics context
192: -  type      - for example, `PETSC_DRAW_X`

194:    Options Database Key:
195: .  -draw_type  <type> - Sets the type; use -help for a list of available methods (for instance, x)

197:    Level: intermediate

199:    Note:
200:    See `PetscDrawSetFromOptions()` for additional options database keys

202:    See "petsc/include/petscdraw.h" for available methods (for instance,
203:    `PETSC_DRAW_X`, `PETSC_DRAW_TIKZ` or `PETSC_DRAW_IMAGE`)

205: .seealso: `PetscDraw`, `PETSC_DRAW_X`, `PETSC_DRAW_TIKZ`, `PETSC_DRAW_IMAGE`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`, `PetscDrawType`
206: @*/
207: PetscErrorCode PetscDrawSetType(PetscDraw draw, PetscDrawType type)
208: {
209:   PetscBool match;
210:   PetscBool flg = PETSC_FALSE;
211:   PetscErrorCode (*r)(PetscDraw);

213:   PetscFunctionBegin;

217:   PetscCall(PetscObjectTypeCompare((PetscObject)draw, type, &match));
218:   if (match) PetscFunctionReturn(PETSC_SUCCESS);

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

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

244:   PetscCall(PetscStrcmp(type, PETSC_DRAW_NULL, &match));
245:   if (match) {
246:     PetscCall(PetscOptionsHasName(NULL, NULL, "-draw_double_buffer", NULL));
247:     PetscCall(PetscOptionsHasName(NULL, NULL, "-draw_virtual", NULL));
248:     PetscCall(PetscOptionsHasName(NULL, NULL, "-draw_fast", NULL));
249:     PetscCall(PetscOptionsHasName(NULL, NULL, "-draw_ports", NULL));
250:     PetscCall(PetscOptionsHasName(NULL, NULL, "-draw_coordinates", NULL));
251:   }

253:   PetscCall(PetscFunctionListFind(PetscDrawList, type, &r));
254:   PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDraw type given: %s", type);
255:   PetscTryTypeMethod(draw, destroy);
256:   PetscCall(PetscMemzero(draw->ops, sizeof(struct _PetscDrawOps)));
257:   PetscCall(PetscObjectChangeTypeName((PetscObject)draw, type));
258:   PetscCall((*r)(draw));
259:   PetscFunctionReturn(PETSC_SUCCESS);
260: }

262: /*@C
263:    PetscDrawGetType - Gets the `PetscDraw` type as a string from the `PetscDraw` object.

265:    Not Collective

267:    Input Parameter:
268: .  draw - Krylov context

270:    Output Parameter:
271: .  name - name of PetscDraw method

273:    Level: advanced

275: .seealso: `PetscDraw`, `PetscDrawType`, `PetscDrawSetType()`, `PetscDrawCreate()
276: @*/
277: PetscErrorCode PetscDrawGetType(PetscDraw draw, PetscDrawType *type)
278: {
279:   PetscFunctionBegin;
282:   *type = ((PetscObject)draw)->type_name;
283:   PetscFunctionReturn(PETSC_SUCCESS);
284: }

286: /*@C
287:    PetscDrawRegister - Adds a method to the graphics package.

289:    Not Collective

291:    Input Parameters:
292: +  name_solver - name of a new user-defined graphics class
293: -  routine_create - routine to create method context

295:    Level: developer

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

300:    Sample usage:
301: .vb
302:    PetscDrawRegister("my_draw_type", MyDrawCreate);
303: .ve

305:    Then, your specific graphics package can be chosen with the procedural interface via
306: $     PetscDrawSetType(ksp, "my_draw_type")
307:    or at runtime via the option
308: $     -draw_type my_draw_type

310: .seealso: `PetscDraw`, `PetscDrawRegisterAll()`, `PetscDrawRegisterDestroy()`, `PetscDrawType`, `PetscDrawSetType()`
311: @*/
312: PetscErrorCode PetscDrawRegister(const char *sname, PetscErrorCode (*function)(PetscDraw))
313: {
314:   PetscFunctionBegin;
315:   PetscCall(PetscDrawInitializePackage());
316:   PetscCall(PetscFunctionListAdd(&PetscDrawList, sname, function));
317:   PetscFunctionReturn(PETSC_SUCCESS);
318: }

320: /*@C
321:    PetscDrawSetOptionsPrefix - Sets the prefix used for searching for all
322:    `PetscDraw` options in the database.

324:    Logically Collective

326:    Input Parameters:
327: +  draw - the draw context
328: -  prefix - the prefix to prepend to all option names

330:    Level: advanced

332: .seealso: `PetscDraw`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`
333: @*/
334: PetscErrorCode PetscDrawSetOptionsPrefix(PetscDraw draw, const char prefix[])
335: {
336:   PetscFunctionBegin;
338:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)draw, prefix));
339:   PetscFunctionReturn(PETSC_SUCCESS);
340: }

342: /*@
343:    PetscDrawSetFromOptions - Sets the graphics type from the options database.
344:       Defaults to a PETSc X Windows graphics.

346:    Collective

348:    Input Parameter:
349: .     draw - the graphics context

351:    Options Database Keys:
352: +   -nox - do not use X graphics (ignore graphics calls, but run program correctly)
353: .   -nox_warning - when X Windows support is not installed this prevents the warning message from being printed
354: .   -draw_pause <pause amount> -- -1 indicates wait for mouse input, -2 indicates pause when window is to be destroyed
355: .   -draw_marker_type - <x,point>
356: .   -draw_save [optional filename] - (X Windows only) saves each image before it is cleared to a file
357: .   -draw_save_final_image [optional filename] - (X Windows only) saves the final image displayed in a window
358: .   -draw_save_movie - converts image files to a movie  at the end of the run. See PetscDrawSetSave()
359: .   -draw_save_single_file - saves each new image in the same file, normally each new image is saved in a new file with 'filename/filename_%d.ext'
360: .   -draw_save_on_clear - saves an image on each clear, mainly for debugging
361: -   -draw_save_on_flush - saves an image on each flush, mainly for debugging

363:    Level: intermediate

365:    Note:
366:     Must be called after `PetscDrawCreate()` before the `PetscDraw` is used.

368: .seealso: `PetscDraw`, `PetscDrawCreate()`, `PetscDrawSetType()`, `PetscDrawSetSave()`, `PetscDrawSetSaveFinalImage()`, `PetscDrawPause()`, `PetscDrawSetPause()`
369: @*/
370: PetscErrorCode PetscDrawSetFromOptions(PetscDraw draw)
371: {
372:   PetscBool   flg, nox;
373:   char        vtype[256];
374:   const char *def;
375: #if !defined(PETSC_USE_WINDOWS_GRAPHICS) && !defined(PETSC_HAVE_X)
376:   PetscBool warn;
377: #endif

379:   PetscFunctionBegin;

382:   PetscCall(PetscDrawRegisterAll());

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

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

428:   PetscCall(PetscDrawViewFromOptions(draw, NULL, "-draw_view"));
429:   PetscOptionsEnd();
430:   PetscFunctionReturn(PETSC_SUCCESS);
431: }