xref: /petsc/src/sys/utils/pdisplay.c (revision 98d129c30f3ee9fdddc40fdbc5a989b7be64f888)
1 #include <petscsys.h>
2 
3 /*@C
4   PetscOptionsGetenv - Gets an environmental variable, broadcasts to all
5   processors in communicator from MPI rank zero
6 
7   Collective
8 
9   Input Parameters:
10 + comm - communicator to share variable
11 . name - name of environmental variable
12 - len  - amount of space allocated to hold variable
13 
14   Output Parameters:
15 + flag - if not `NULL` indicates if the variable was found
16 - env  - value of variable
17 
18   Level: advanced
19 
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`
25 
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
29 
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;
37 
38   PetscFunctionBegin;
39   /* first check options database */
40   PetscCall(PetscStrncmp(name, "PETSC_", 6, &spetsc));
41 
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));
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(PETSC_SUCCESS);
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(PETSC_SUCCESS);
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(PETSC_SUCCESS);
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(PETSC_SUCCESS);
140 }
141 
142 /*@C
143   PetscGetDisplay - Gets the X windows display variable for all processors.
144 
145   Input Parameter:
146 . n - length of string display
147 
148   Output Parameter:
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(PETSC_SUCCESS);
165 }
166