Date: 2026-06-01T23:13:41+00:00

Actual source code: dtri.c

      1: #include <petsc/private/drawimpl.h>

      3: /*@
      4:   PetscDrawTriangle - draws a triangle  onto a drawable.

      6:   Not Collective

      8:   Input Parameters:
      9: + draw - the drawing context
     10: . x1   - coordinate of the first vertex
     11: . y_1  - coordinate of the first vertex
     12: . x2   - coordinate of the second vertex
     13: . y2   - coordinate of the second vertex
     14: . x3   - coordinate of the third vertex
     15: . y3   - coordinate of the third vertex
     16: . c1   - color of the first vertex
     17: . c2   - color of the second vertex
     18: - c3   - color of the third vertext

     20:   Level: beginner

     22: .seealso: `PetscDraw`, `PetscDrawLine()`, `PetscDrawRectangle()`, `PetscDrawEllipse()`, `PetscDrawMarker()`, `PetscDrawPoint()`, `PetscDrawArrow()`
     23: @*/
     24: PetscErrorCode PetscDrawTriangle(PetscDraw draw, PetscReal x1, PetscReal y_1, PetscReal x2, PetscReal y2, PetscReal x3, PetscReal y3, int c1, int c2, int c3)
     25: {
     26:   PetscFunctionBegin;
     28:   PetscUseTypeMethod(draw, triangle, x1, y_1, x2, y2, x3, y3, c1, c2, c3);
     29:   PetscFunctionReturn(PETSC_SUCCESS);
     30: }

     32: /*@
     33:   PetscDrawScalePopup - draws a contour scale window.

     35:   Collective

     37:   Input Parameters:
     38: + popup - the window (often a window obtained via `PetscDrawGetPopup()`
     39: . min   - minimum value being plotted
     40: - max   - maximum value being plotted

     42:   Level: intermediate

     44:   Note:
     45:   All processors that share the draw MUST call this routine

     47: .seealso: `PetscDraw`, `PetscDrawGetPopup()`, `PetscDrawTensorContour()`
     48: @*/
     49: PetscErrorCode PetscDrawScalePopup(PetscDraw popup, PetscReal min, PetscReal max)
     50: {
     51:   PetscBool   isnull;
     52:   PetscReal   xl = 0.0, yl = 0.0, xr = 1.0, yr = 1.0;
     53:   PetscMPIInt rank;
     54:   int         i;
     55:   char        string[32];

     57:   PetscFunctionBegin;
     58:   if (!popup) PetscFunctionReturn(PETSC_SUCCESS);
     60:   PetscCall(PetscDrawIsNull(popup, &isnull));
     61:   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
     62:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)popup), &rank));

     64:   PetscCall(PetscDrawCheckResizedWindow(popup));
     65:   PetscCall(PetscDrawClear(popup));
     66:   PetscCall(PetscDrawSetTitle(popup, "Contour Scale"));
     67:   PetscCall(PetscDrawSetCoordinates(popup, xl, yl, xr, yr));
     68:   PetscDrawCollectiveBegin(popup);
     69:   if (rank == 0) {
     70:     for (i = 0; i < 10; i++) {
     71:       int c = PetscDrawRealToColor((PetscReal)i / 9, 0, 1);
     72:       PetscCall(PetscDrawRectangle(popup, xl, yl, xr, yr, c, c, c, c));
     73:       yl += 0.1;
     74:     }
     75:     for (i = 0; i < 10; i++) {
     76:       PetscReal value = min + ((PetscReal)i) * (max - min) / 9;
     77:       /* look for a value that should be zero, but is not due to round-off */
     78:       if (PetscAbsReal(value) < 1.e-10 && max - min > 1.e-6) value = 0.0;
     79:       PetscCall(PetscSNPrintf(string, sizeof(string), "%18.16e", (double)value));
     80:       PetscCall(PetscDrawString(popup, 0.2, 0.02 + i / 10.0, PETSC_DRAW_BLACK, string));
     81:     }
     82:   }
     83:   PetscDrawCollectiveEnd(popup);
     84:   PetscCall(PetscDrawFlush(popup));
     85:   PetscCall(PetscDrawSave(popup));
     86:   PetscFunctionReturn(PETSC_SUCCESS);
     87: }

     89: typedef struct {
     90:   int        m, n;
     91:   PetscReal *x, *y, min, max, *v;
     92:   PetscBool  showgrid;
     93: } ZoomCtx;

     95: static PetscErrorCode PetscDrawTensorContour_Zoom(PetscDraw win, void *dctx)
     96: {
     97:   int      i;
     98:   ZoomCtx *ctx = (ZoomCtx *)dctx;

    100:   PetscFunctionBegin;
    101:   PetscCall(PetscDrawTensorContourPatch(win, ctx->m, ctx->n, ctx->x, ctx->y, ctx->min, ctx->max, ctx->v));
    102:   if (ctx->showgrid) {
    103:     for (i = 0; i < ctx->m; i++) PetscCall(PetscDrawLine(win, ctx->x[i], ctx->y[0], ctx->x[i], ctx->y[ctx->n - 1], PETSC_DRAW_BLACK));
    104:     for (i = 0; i < ctx->n; i++) PetscCall(PetscDrawLine(win, ctx->x[0], ctx->y[i], ctx->x[ctx->m - 1], ctx->y[i], PETSC_DRAW_BLACK));
    105:   }
    106:   PetscFunctionReturn(PETSC_SUCCESS);
    107: }

    109: /*@
    110:   PetscDrawTensorContour - draws a contour plot for a two-dimensional array

    112:   Collective, but `draw` must be sequential

    114:   Input Parameters:
    115: + draw - the draw context
    116: . m    - the number of local mesh points in the x direction
    117: . n    - the number of local mesh points in the y direction
    118: . xi   - the locations of the global mesh points in the horizontal direction (optional, use `NULL` to indicate uniform spacing on [0,1])
    119: . yi   - the locations of the global mesh points in the vertical direction (optional, use `NULL` to indicate uniform spacing on [0,1])
    120: - v    - the values

    122:   Options Database Keys:
    123: + -draw_x_shared_colormap - Indicates use of private colormap
    124: - -draw_contour_grid      - draws grid contour

    126:   Level: intermediate

    128: .seealso: `PetscDraw`, `PetscDrawTensorContourPatch()`, `PetscDrawScalePopup()`
    129: @*/
    130: PetscErrorCode PetscDrawTensorContour(PetscDraw draw, int m, int n, const PetscReal xi[], const PetscReal yi[], PetscReal v[])
    131: {
    132:   int         N = m * n;
    133:   PetscBool   isnull;
    134:   PetscDraw   popup;
    135:   int         xin = 1, yin = 1, i;
    136:   PetscMPIInt size;
    137:   PetscReal   h;
    138:   ZoomCtx     ctx;

    140:   PetscFunctionBegin;
    142:   PetscCall(PetscDrawIsNull(draw, &isnull));
    143:   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
    144:   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)draw), &size));
    145:   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "May only be used with single processor PetscDraw");
    146:   PetscCheck(N > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n %d and m %d must be positive", m, n);

    148:   ctx.v   = v;
    149:   ctx.m   = m;
    150:   ctx.n   = n;
    151:   ctx.max = ctx.min = v[0];
    152:   for (i = 0; i < N; i++) {
    153:     if (ctx.max < ctx.v[i]) ctx.max = ctx.v[i];
    154:     if (ctx.min > ctx.v[i]) ctx.min = ctx.v[i];
    155:   }
    156:   if (ctx.max - ctx.min < 1.e-7) {
    157:     ctx.min -= 5.e-8;
    158:     ctx.max += 5.e-8;
    159:   }

    161:   /* PetscDraw the scale window */
    162:   PetscCall(PetscDrawGetPopup(draw, &popup));
    163:   PetscCall(PetscDrawScalePopup(popup, ctx.min, ctx.max));

    165:   ctx.showgrid = PETSC_FALSE;
    166:   PetscCall(PetscOptionsGetBool(((PetscObject)draw)->options, NULL, "-draw_contour_grid", &ctx.showgrid, NULL));

    168:   /* fill up x and y coordinates */
    169:   if (!xi) {
    170:     xin = 0;
    171:     PetscCall(PetscMalloc1(ctx.m, &ctx.x));
    172:     h        = 1.0 / (ctx.m - 1);
    173:     ctx.x[0] = 0.0;
    174:     for (i = 1; i < ctx.m; i++) ctx.x[i] = ctx.x[i - 1] + h;
    175:   } else ctx.x = (PetscReal *)xi;

    177:   if (!yi) {
    178:     yin = 0;
    179:     PetscCall(PetscMalloc1(ctx.n, &ctx.y));
    180:     h        = 1.0 / (ctx.n - 1);
    181:     ctx.y[0] = 0.0;
    182:     for (i = 1; i < ctx.n; i++) ctx.y[i] = ctx.y[i - 1] + h;
    183:   } else ctx.y = (PetscReal *)yi;

    185:   PetscCall(PetscDrawZoom(draw, PetscDrawTensorContour_Zoom, &ctx));

    187:   if (!xin) PetscCall(PetscFree(ctx.x));
    188:   if (!yin) PetscCall(PetscFree(ctx.y));
    189:   PetscFunctionReturn(PETSC_SUCCESS);
    190: }

    192: /*@
    193:   PetscDrawTensorContourPatch - draws a rectangular patch of a contour plot
    194:   for a two-dimensional array.

    196:   Not Collective

    198:   Input Parameters:
    199: + draw - the draw context
    200: . m    - the number of local mesh points in the x direction
    201: . n    - the number of local mesh points in the y direction
    202: . x    - the horizontal locations of the local mesh points
    203: . y    - the vertical locations of the local mesh points
    204: . min  - the minimum value in the entire contour
    205: . max  - the maximum value in the entire contour
    206: - v    - the data

    208:   Options Database Key:
    209: . -draw_x_shared_colormap - Activates private colormap

    211:   Level: advanced

    213:   Note:
    214:   This is a lower level support routine, usually the user will call
    215:   `PetscDrawTensorContour()`.

    217: .seealso: `PetscDraw`, `PetscDrawTensorContour()`
    218: @*/
    219: PetscErrorCode PetscDrawTensorContourPatch(PetscDraw draw, int m, int n, PetscReal *x, PetscReal *y, PetscReal min, PetscReal max, PetscReal *v)
    220: {
    221:   int       c1, c2, c3, c4, i, j;
    222:   PetscReal x1, x2, x3, x4, y_1, y2, y3, y4;

    224:   PetscFunctionBegin;
    226:   /* PetscDraw the contour plot patch */
    227:   for (j = 0; j < n - 1; j++) {
    228:     for (i = 0; i < m - 1; i++) {
    229:       x1  = x[i];
    230:       y_1 = y[j];
    231:       c1  = PetscDrawRealToColor(v[i + j * m], min, max);
    232:       x2  = x[i + 1];
    233:       y2  = y_1;
    234:       c2  = PetscDrawRealToColor(v[i + j * m + 1], min, max);
    235:       x3  = x2;
    236:       y3  = y[j + 1];
    237:       c3  = PetscDrawRealToColor(v[i + j * m + 1 + m], min, max);
    238:       x4  = x1;
    239:       y4  = y3;
    240:       c4  = PetscDrawRealToColor(v[i + j * m + m], min, max);

    242:       PetscCall(PetscDrawTriangle(draw, x1, y_1, x2, y2, x3, y3, c1, c2, c3));
    243:       PetscCall(PetscDrawTriangle(draw, x1, y_1, x3, y3, x4, y4, c1, c3, c4));
    244:     }
    245:   }
    246:   PetscFunctionReturn(PETSC_SUCCESS);
    247: }