Date: 2025-03-29T05:58:46+00:00

Actual source code: pdisplay.c

      1: #include <petscsys.h>

      3: /*@C
      4:   PetscOptionsGetenv - Gets an environmental variable, broadcasts to all
      5:   processors in communicator from MPI rank zero

      7:   Collective

      9:   Input Parameters:
     10: + comm - communicator to share variable
     11: . name - name of environmental variable
     12: - len  - amount of space allocated to hold variable

     14:   Output Parameters:
     15: + flag - if not `NULL` indicates if the variable was found
     16: - env  - value of variable

     18:   Level: advanced

     20:   Notes:
     21:   You can also "set" the environmental variable by setting the options database value
     22:   -name "stringvalue" (with name in lower case). If name begins with PETSC_ this is
     23:   discarded before checking the database. For example, `PETSC_VIEWER_SOCKET_PORT` would
     24:   be given as `-viewer_socket_port 9000`

     26:   If comm does not contain the 0th process in the `MPI_COMM_WORLD` it is likely on
     27:   many systems that the environmental variable will not be set unless you
     28:   put it in a universal location like a .chsrc file

     30: .seealso: `PetscOptionsHasName()`
     31: @*/
     32: PetscErrorCode PetscOptionsGetenv(MPI_Comm comm, const char name[], char env[], size_t len, PetscBool *flag)
     33: {
     34:   PetscMPIInt rank;
     35:   char       *str, work[256];
     36:   PetscBool   flg = PETSC_FALSE, spetsc;

     38:   PetscFunctionBegin;
     39:   /* first check options database */
     40:   PetscCall(PetscStrncmp(name, "PETSC_", 6, &spetsc));

     42:   PetscCall(PetscStrncpy(work, "-", sizeof(work)));
     43:   if (spetsc) {
     44:     PetscCall(PetscStrlcat(work, name + 6, sizeof(work)));
     45:   } else {
     46:     PetscCall(PetscStrlcat(work, name, sizeof(work)));
     47:   }
     48:   PetscCall(PetscStrtolower(work));
     49:   if (env) {
     50:     PetscCall(PetscOptionsGetString(NULL, NULL, work, env, len, &flg));
     51:     if (flg) {
     52:       if (flag) *flag = PETSC_TRUE;
     53:     } else { /* now check environment */
     54:       PetscCall(PetscArrayzero(env, len));

     56:       PetscCallMPI(MPI_Comm_rank(comm, &rank));
     57:       if (rank == 0) {
     58:         str = getenv(name);
     59:         if (str) flg = PETSC_TRUE;
     60:         if (str && env) PetscCall(PetscStrncpy(env, str, len));
     61:       }
     62:       PetscCallMPI(MPI_Bcast(&flg, 1, MPIU_BOOL, 0, comm));
     63:       PetscCallMPI(MPI_Bcast(env, (PetscMPIInt)len, MPI_CHAR, 0, comm));
     64:       if (flag) *flag = flg;
     65:     }
     66:   } else {
     67:     PetscCall(PetscOptionsHasName(NULL, NULL, work, flag));
     68:   }
     69:   PetscFunctionReturn(PETSC_SUCCESS);
     70: }

     72: /*
     73:      PetscSetDisplay - Tries to set the X Windows display variable for all processors.
     74:                        The variable `PetscDisplay` contains the X Windows display variable.

     76: */
     77: static char PetscDisplay[256];

     79: static PetscErrorCode PetscWorldIsSingleHost(PetscBool *onehost)
     80: {
     81:   char        hostname[256], roothostname[256];
     82:   PetscMPIInt localmatch, allmatch;
     83:   PetscBool   flag;

     85:   PetscFunctionBegin;
     86:   PetscCall(PetscGetHostName(hostname, sizeof(hostname)));
     87:   PetscCall(PetscMemcpy(roothostname, hostname, sizeof(hostname)));
     88:   PetscCallMPI(MPI_Bcast(roothostname, sizeof(roothostname), MPI_CHAR, 0, PETSC_COMM_WORLD));
     89:   PetscCall(PetscStrcmp(hostname, roothostname, &flag));

     91:   localmatch = (PetscMPIInt)flag;

     93:   PetscCallMPI(MPIU_Allreduce(&localmatch, &allmatch, 1, MPI_INT, MPI_LAND, PETSC_COMM_WORLD));

     95:   *onehost = (PetscBool)allmatch;
     96:   PetscFunctionReturn(PETSC_SUCCESS);
     97: }

     99: PetscErrorCode PetscSetDisplay(void)
    100: {
    101:   PetscMPIInt size, rank;
    102:   PetscBool   flag, singlehost = PETSC_FALSE;
    103:   char        display[sizeof(PetscDisplay)];
    104:   const char *str;

    106:   PetscFunctionBegin;
    107:   PetscCall(PetscOptionsGetString(NULL, NULL, "-display", PetscDisplay, sizeof(PetscDisplay), &flag));
    108:   if (flag) PetscFunctionReturn(PETSC_SUCCESS);

    110:   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
    111:   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));

    113:   PetscCall(PetscWorldIsSingleHost(&singlehost));

    115:   str = getenv("DISPLAY");
    116:   if (!str) str = ":0.0";
    117: #if defined(PETSC_HAVE_X)
    118:   flag = PETSC_FALSE;
    119:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-x_virtual", &flag, NULL));
    120:   if (flag) {
    121:     /*  this is a crude hack, but better than nothing */
    122:     PetscCall(PetscPOpen(PETSC_COMM_WORLD, NULL, "pkill -15 Xvfb", "r", NULL));
    123:     PetscCall(PetscSleep(1));
    124:     PetscCall(PetscPOpen(PETSC_COMM_WORLD, NULL, "Xvfb :15 -screen 0 1600x1200x24", "r", NULL));
    125:     PetscCall(PetscSleep(5));
    126:     str = ":15";
    127:   }
    128: #endif
    129:   if (str[0] != ':' || singlehost) {
    130:     PetscCall(PetscStrncpy(display, str, sizeof(display)));
    131:   } else if (rank == 0) {
    132:     PetscCall(PetscGetHostName(display, sizeof(display)));
    133:     PetscCall(PetscStrlcat(display, str, sizeof(display)));
    134:   }
    135:   PetscCallMPI(MPI_Bcast(display, sizeof(display), MPI_CHAR, 0, PETSC_COMM_WORLD));
    136:   PetscCall(PetscMemcpy(PetscDisplay, display, sizeof(PetscDisplay)));

    138:   PetscDisplay[sizeof(PetscDisplay) - 1] = 0;
    139:   PetscFunctionReturn(PETSC_SUCCESS);
    140: }

    142: /*@C
    143:   PetscGetDisplay - Gets the X windows display variable for all processors.

    145:   Input Parameter:
    146: . n - length of string display

    148:   Output Parameter:
    149: . display - the display string

    151:   Options Database Keys:
    152: + -display <display> - sets the display to use
    153: - -x_virtual         - forces use of a X virtual display Xvfb that will not display anything but -draw_save will still work. Xvfb is automatically
    154:                 started up in PetscSetDisplay() with this option

    156:   Level: advanced

    158: .seealso: `PETSC_DRAW_X`, `PetscDrawOpenX()`
    159: @*/
    160: PetscErrorCode PetscGetDisplay(char display[], size_t n)
    161: {
    162:   PetscFunctionBegin;
    163:   PetscCall(PetscStrncpy(display, PetscDisplay, n));
    164:   PetscFunctionReturn(PETSC_SUCCESS);
    165: }