Date: 2026-07-30T21:14:23+00:00

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 defined(PETSC_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 defined(PETSC_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 defined(PETSC_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 defined(PETSC_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
     91: - name - command line option

     93:   Options Database Key:
     94: . -name [viewertype][:...] - option name and values. See `PetscObjectViewFromOptions()` for the possible arguments

     96:   Level: intermediate

     98: .seealso: `PetscDraw`, `PetscDrawView`, `PetscObjectViewFromOptions()`, `PetscDrawCreate()`
     99: @*/
    100: PetscErrorCode PetscDrawViewFromOptions(PetscDraw A, PetscObject obj, const char name[])
    101: {
    102:   PetscFunctionBegin;
    104:   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
    105:   PetscFunctionReturn(PETSC_SUCCESS);
    106: }

    108: /*@
    109:   PetscDrawCreate - Creates a graphics context.

    111:   Collective

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

    122:   Output Parameter:
    123: . indraw - location to put the `PetscDraw` context

    125:   Level: beginner

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

    144:   PetscFunctionBegin;
    145:   PetscAssertPointer(indraw, 8);
    146:   PetscCall(PetscDrawInitializePackage());

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

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

    170:   draw->savefilename   = NULL;
    171:   draw->saveimageext   = NULL;
    172:   draw->savemovieext   = NULL;
    173:   draw->savefilecount  = 0;
    174:   draw->savesinglefile = PETSC_FALSE;
    175:   draw->savemoviefps   = PETSC_DECIDE;

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

    179:   draw->boundbox_xl = .5;
    180:   draw->boundbox_xr = .5;
    181:   draw->boundbox_yl = .9;
    182:   draw->boundbox_yr = .9;

    184:   *indraw = draw;
    185:   PetscFunctionReturn(PETSC_SUCCESS);
    186: }

    188: /*@
    189:   PetscDrawSetType - Builds graphics object for a particular implementation

    191:   Collective

    193:   Input Parameters:
    194: + draw - the graphics context
    195: - type - for example, `PETSC_DRAW_X`

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

    200:   Level: intermediate

    202:   Notes:
    203:   See `PetscDrawSetFromOptions()` for additional options database keys

    205:   See `PetscDrawType` for available methods (for instance,
    206:   `PETSC_DRAW_X`, `PETSC_DRAW_TIKZ` or `PETSC_DRAW_IMAGE`)

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

    216:   PetscFunctionBegin;
    218:   PetscAssertPointer(type, 2);

    220:   PetscCall(PetscObjectTypeCompare((PetscObject)draw, type, &match));
    221:   if (match) PetscFunctionReturn(PETSC_SUCCESS);

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

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

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

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

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

    268:   Not Collective

    270:   Input Parameter:
    271: . draw - Krylov context

    273:   Output Parameter:
    274: . type - name of PetscDraw method

    276:   Level: advanced

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

    281: .seealso: `PetscDraw`, `PetscDrawType`, `PetscDrawSetType()`, `PetscDrawCreate()`, `PetscObjectTypeCompare()`, `PetscObjectTypeCompareAny()`
    282: @*/
    283: PetscErrorCode PetscDrawGetType(PetscDraw draw, PetscDrawType *type)
    284: {
    285:   PetscFunctionBegin;
    287:   PetscAssertPointer(type, 2);
    288:   *type = ((PetscObject)draw)->type_name;
    289:   PetscFunctionReturn(PETSC_SUCCESS);
    290: }

    292: /*@C
    293:   PetscDrawRegister - Adds a method to the graphics package.

    295:   Not Collective, No Fortran Support

    297:   Input Parameters:
    298: + sname    - name of a new user-defined graphics class
    299: - function - routine to create method context

    301:   Level: developer

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

    306:   Example Usage:
    307: .vb
    308:    PetscDrawRegister("my_draw_type", MyDrawCreate);
    309: .ve

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

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

    330: /*@
    331:   PetscDrawSetOptionsPrefix - Sets the prefix used for searching for all
    332:   `PetscDraw` options in the database.

    334:   Logically Collective

    336:   Input Parameters:
    337: + draw   - the draw context
    338: - prefix - the prefix to prepend to all option names

    340:   Level: advanced

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

    352: /*@
    353:   PetscDrawSetFromOptions - Sets the graphics type from the options database.
    354:   Defaults to a PETSc X Windows graphics.

    356:   Collective

    358:   Input Parameter:
    359: . draw - the graphics context

    361:   Options Database Keys:
    362: + -nox                              - do not use X graphics (ignore graphics calls, but run program correctly)
    363: . -nox_warning                      - when X Windows support is not installed this prevents the warning message from being printed
    364: . -draw_pause seconds               - -1 indicates wait for mouse input, -2 indicates pause when window is to be destroyed
    365: . -draw_marker_type (x|point)       - set the marker type
    366: . -draw_save [filename]             - (X Windows only) saves each image before it is cleared to a file
    367: . -draw_save_final_image [filename] - (X Windows only) saves the final image displayed in a window
    368: . -draw_save_movie                  - converts image files to a movie  at the end of the run. See `PetscDrawSetSave()`
    369: . -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'
    370: . -draw_save_on_clear               - saves an image on each clear, mainly for debugging
    371: - -draw_save_on_flush               - saves an image on each flush, mainly for debugging

    373:   Level: intermediate

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

    378: .seealso: `PetscDraw`, `PetscDrawCreate()`, `PetscDrawSetType()`, `PetscDrawSetSave()`, `PetscDrawSetSaveFinalImage()`, `PetscDrawPause()`, `PetscDrawSetPause()`
    379: @*/
    380: PetscErrorCode PetscDrawSetFromOptions(PetscDraw draw)
    381: {
    382:   PetscBool   flg, nox;
    383:   char        vtype[256];
    384:   const char *def;
    385: #if !defined(PETSC_USE_WINDOWS_GRAPHICS) && !defined(PETSC_HAVE_X)
    386:   PetscBool warn;
    387: #endif

    389:   PetscFunctionBegin;

    392:   PetscCall(PetscDrawRegisterAll());

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

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

    438:   PetscCall(PetscDrawViewFromOptions(draw, NULL, "-draw_view"));
    439:   PetscOptionsEnd();
    440:   PetscFunctionReturn(PETSC_SUCCESS);
    441: }