xref: /petsc/src/sys/utils/pdisplay.c (revision df4cd43f92eaa320656440c40edb1046daee8f75)
1 
2 #include <petscsys.h>
3 
4 /*@C
5      PetscOptionsGetenv - Gets an environmental variable, broadcasts to all
6           processors in communicator from MPI rank zero
7 
8      Collective
9 
10    Input Parameters:
11 +    comm - communicator to share variable
12 .    name - name of environmental variable
13 -    len - amount of space allocated to hold variable
14 
15    Output Parameters:
16 +    flag - if not `NULL` indicates if the variable was found
17 -    env - value of variable
18 
19   Level: advanced
20 
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
26 
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;
36 
37   PetscFunctionBegin;
38   /* first check options database */
39   PetscCall(PetscStrncmp(name, "PETSC_", 6, &spetsc));
40 
41   PetscCall(PetscStrcpy(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));
54 
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 }
70 
71 /*
72      PetscSetDisplay - Tries to set the X Windows display variable for all processors.
73                        The variable `PetscDisplay` contains the X Windows display variable.
74 
75 */
76 static char PetscDisplay[256];
77 
78 static PetscErrorCode PetscWorldIsSingleHost(PetscBool *onehost)
79 {
80   char        hostname[256], roothostname[256];
81   PetscMPIInt localmatch, allmatch;
82   PetscBool   flag;
83 
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));
89 
90   localmatch = (PetscMPIInt)flag;
91 
92   PetscCall(MPIU_Allreduce(&localmatch, &allmatch, 1, MPI_INT, MPI_LAND, PETSC_COMM_WORLD));
93 
94   *onehost = (PetscBool)allmatch;
95   PetscFunctionReturn(PETSC_SUCCESS);
96 }
97 
98 PetscErrorCode PetscSetDisplay(void)
99 {
100   PetscMPIInt size, rank;
101   PetscBool   flag, singlehost = PETSC_FALSE;
102   char        display[sizeof(PetscDisplay)];
103   const char *str;
104 
105   PetscFunctionBegin;
106   PetscCall(PetscOptionsGetString(NULL, NULL, "-display", PetscDisplay, sizeof(PetscDisplay), &flag));
107   if (flag) PetscFunctionReturn(PETSC_SUCCESS);
108 
109   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
110   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
111 
112   PetscCall(PetscWorldIsSingleHost(&singlehost));
113 
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)));
136 
137   PetscDisplay[sizeof(PetscDisplay) - 1] = 0;
138   PetscFunctionReturn(PETSC_SUCCESS);
139 }
140 
141 /*@C
142      PetscGetDisplay - Gets the X windows display variable for all processors.
143 
144   Input Parameters:
145 .   n - length of string display
146 
147   Output Parameters:
148 .   display - the display string
149 
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
154 
155   Level: advanced
156 
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 }
165