xref: /petsc/src/sys/utils/pdisplay.c (revision d5b43468fb8780a8feea140ccd6fa3e6a50411cc)
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 tells if variable found or not
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 MPIEXEC 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 @*/
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;
37 
38   PetscFunctionBegin;
39   /* first check options database */
40   PetscCall(PetscStrncmp(name, "PETSC_", 6, &spetsc));
41 
42   PetscCall(PetscStrcpy(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));
55 
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, len, MPI_CHAR, 0, comm));
64       if (flag) *flag = flg;
65     }
66   } else {
67     PetscCall(PetscOptionsHasName(NULL, NULL, work, flag));
68   }
69   PetscFunctionReturn(0);
70 }
71 
72 /*
73      PetscSetDisplay - Tries to set the X Windows display variable for all processors.
74                        The variable `PetscDisplay` contains the X Windows display variable.
75 
76 */
77 static char PetscDisplay[256];
78 
79 static PetscErrorCode PetscWorldIsSingleHost(PetscBool *onehost)
80 {
81   char        hostname[256], roothostname[256];
82   PetscMPIInt localmatch, allmatch;
83   PetscBool   flag;
84 
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));
90 
91   localmatch = (PetscMPIInt)flag;
92 
93   PetscCall(MPIU_Allreduce(&localmatch, &allmatch, 1, MPI_INT, MPI_LAND, PETSC_COMM_WORLD));
94 
95   *onehost = (PetscBool)allmatch;
96   PetscFunctionReturn(0);
97 }
98 
99 PetscErrorCode PetscSetDisplay(void)
100 {
101   PetscMPIInt size, rank;
102   PetscBool   flag, singlehost = PETSC_FALSE;
103   char        display[sizeof(PetscDisplay)];
104   const char *str;
105 
106   PetscFunctionBegin;
107   PetscCall(PetscOptionsGetString(NULL, NULL, "-display", PetscDisplay, sizeof(PetscDisplay), &flag));
108   if (flag) PetscFunctionReturn(0);
109 
110   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
111   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
112 
113   PetscCall(PetscWorldIsSingleHost(&singlehost));
114 
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 -9 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)));
137 
138   PetscDisplay[sizeof(PetscDisplay) - 1] = 0;
139   PetscFunctionReturn(0);
140 }
141 
142 /*@C
143      PetscGetDisplay - Gets the X windows display variable for all processors.
144 
145   Input Parameters:
146 .   n - length of string display
147 
148   Output Parameters:
149 .   display - the display string
150 
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
155 
156   Level: advanced
157 
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(0);
165 }
166