xref: /petsc/src/sys/utils/pdisplay.c (revision a69119a591a03a9d906b29c0a4e9802e4d7c9795)
1 
2 #include <petscsys.h>
3 
4 /*@C
5      PetscOptionsGetenv - Gets an environmental variable, broadcasts to all
6           processors in communicator from first.
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   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(0);
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   char        hostname[256], roothostname[256];
80   PetscMPIInt localmatch, allmatch;
81   PetscBool   flag;
82 
83   PetscFunctionBegin;
84   PetscCall(PetscGetHostName(hostname, sizeof(hostname)));
85   PetscCall(PetscMemcpy(roothostname, hostname, sizeof(hostname)));
86   PetscCallMPI(MPI_Bcast(roothostname, sizeof(roothostname), MPI_CHAR, 0, PETSC_COMM_WORLD));
87   PetscCall(PetscStrcmp(hostname, roothostname, &flag));
88 
89   localmatch = (PetscMPIInt)flag;
90 
91   PetscCall(MPIU_Allreduce(&localmatch, &allmatch, 1, MPI_INT, MPI_LAND, PETSC_COMM_WORLD));
92 
93   *onehost = (PetscBool)allmatch;
94   PetscFunctionReturn(0);
95 }
96 
97 PetscErrorCode PetscSetDisplay(void) {
98   PetscMPIInt size, rank;
99   PetscBool   flag, singlehost = PETSC_FALSE;
100   char        display[sizeof(PetscDisplay)];
101   const char *str;
102 
103   PetscFunctionBegin;
104   PetscCall(PetscOptionsGetString(NULL, NULL, "-display", PetscDisplay, sizeof(PetscDisplay), &flag));
105   if (flag) PetscFunctionReturn(0);
106 
107   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
108   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
109 
110   PetscCall(PetscWorldIsSingleHost(&singlehost));
111 
112   str = getenv("DISPLAY");
113   if (!str) str = ":0.0";
114 #if defined(PETSC_HAVE_X)
115   flag = PETSC_FALSE;
116   PetscCall(PetscOptionsGetBool(NULL, NULL, "-x_virtual", &flag, NULL));
117   if (flag) {
118     /*  this is a crude hack, but better than nothing */
119     PetscCall(PetscPOpen(PETSC_COMM_WORLD, NULL, "pkill -9 Xvfb", "r", NULL));
120     PetscCall(PetscSleep(1));
121     PetscCall(PetscPOpen(PETSC_COMM_WORLD, NULL, "Xvfb :15 -screen 0 1600x1200x24", "r", NULL));
122     PetscCall(PetscSleep(5));
123     str = ":15";
124   }
125 #endif
126   if (str[0] != ':' || singlehost) {
127     PetscCall(PetscStrncpy(display, str, sizeof(display)));
128   } else if (rank == 0) {
129     PetscCall(PetscGetHostName(display, sizeof(display)));
130     PetscCall(PetscStrlcat(display, str, sizeof(display)));
131   }
132   PetscCallMPI(MPI_Bcast(display, sizeof(display), MPI_CHAR, 0, PETSC_COMM_WORLD));
133   PetscCall(PetscMemcpy(PetscDisplay, display, sizeof(PetscDisplay)));
134 
135   PetscDisplay[sizeof(PetscDisplay) - 1] = 0;
136   PetscFunctionReturn(0);
137 }
138 
139 /*
140      PetscGetDisplay - Gets the display variable for all processors.
141 
142   Input Parameters:
143 .   n - length of string display
144 
145   Output Parameters:
146 .   display - the display string
147 
148   Options Database:
149 +  -display <display> - sets the display to use
150 -  -x_virtual - forces use of a X virtual display Xvfb that will not display anything but -draw_save will still work. Xvfb is automatically
151                 started up in PetscSetDisplay() with this option
152 
153 */
154 PetscErrorCode PetscGetDisplay(char display[], size_t n) {
155   PetscFunctionBegin;
156   PetscCall(PetscStrncpy(display, PetscDisplay, n));
157   PetscFunctionReturn(0);
158 }
159