Actual source code: pdisplay.c


  2: #include <petscsys.h>

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

  8:      Collective

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

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

 19:   Level: advanced

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

 27:     If comm does not contain the 0th process in the `MPI_COMM_WORLD` it is likely on
 28:     many systems that the environmental variable will not be set unless you
 29:     put it in a universal location like a .chsrc file
 30: @*/
 31: PetscErrorCode PetscOptionsGetenv(MPI_Comm comm, const char name[], char env[], size_t len, PetscBool *flag)
 32: {
 33:   PetscMPIInt rank;
 34:   char       *str, work[256];
 35:   PetscBool   flg = PETSC_FALSE, spetsc;

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

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

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

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

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

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

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

 90:   localmatch = (PetscMPIInt)flag;

 92:   PetscCall(MPIU_Allreduce(&localmatch, &allmatch, 1, MPI_INT, MPI_LAND, PETSC_COMM_WORLD));

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

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

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

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

112:   PetscCall(PetscWorldIsSingleHost(&singlehost));

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

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

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

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

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

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

155:   Level: advanced

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