xref: /petsc/src/sys/utils/pdisplay.c (revision 0619917b5a674bb687c64e7daba2ab22be99af31)
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 .seealso: `PetscOptionsHasName()`
32 @*/
33 PetscErrorCode PetscOptionsGetenv(MPI_Comm comm, const char name[], char env[], size_t len, PetscBool *flag)
34 {
35   PetscMPIInt rank;
36   char       *str, work[256];
37   PetscBool   flg = PETSC_FALSE, spetsc;
38 
39   PetscFunctionBegin;
40   /* first check options database */
41   PetscCall(PetscStrncmp(name, "PETSC_", 6, &spetsc));
42 
43   PetscCall(PetscStrncpy(work, "-", sizeof(work)));
44   if (spetsc) {
45     PetscCall(PetscStrlcat(work, name + 6, sizeof(work)));
46   } else {
47     PetscCall(PetscStrlcat(work, name, sizeof(work)));
48   }
49   PetscCall(PetscStrtolower(work));
50   if (env) {
51     PetscCall(PetscOptionsGetString(NULL, NULL, work, env, len, &flg));
52     if (flg) {
53       if (flag) *flag = PETSC_TRUE;
54     } else { /* now check environment */
55       PetscCall(PetscArrayzero(env, len));
56 
57       PetscCallMPI(MPI_Comm_rank(comm, &rank));
58       if (rank == 0) {
59         str = getenv(name);
60         if (str) flg = PETSC_TRUE;
61         if (str && env) PetscCall(PetscStrncpy(env, str, len));
62       }
63       PetscCallMPI(MPI_Bcast(&flg, 1, MPIU_BOOL, 0, comm));
64       PetscCallMPI(MPI_Bcast(env, len, MPI_CHAR, 0, comm));
65       if (flag) *flag = flg;
66     }
67   } else {
68     PetscCall(PetscOptionsHasName(NULL, NULL, work, flag));
69   }
70   PetscFunctionReturn(PETSC_SUCCESS);
71 }
72 
73 /*
74      PetscSetDisplay - Tries to set the X Windows display variable for all processors.
75                        The variable `PetscDisplay` contains the X Windows display variable.
76 
77 */
78 static char PetscDisplay[256];
79 
80 static PetscErrorCode PetscWorldIsSingleHost(PetscBool *onehost)
81 {
82   char        hostname[256], roothostname[256];
83   PetscMPIInt localmatch, allmatch;
84   PetscBool   flag;
85 
86   PetscFunctionBegin;
87   PetscCall(PetscGetHostName(hostname, sizeof(hostname)));
88   PetscCall(PetscMemcpy(roothostname, hostname, sizeof(hostname)));
89   PetscCallMPI(MPI_Bcast(roothostname, sizeof(roothostname), MPI_CHAR, 0, PETSC_COMM_WORLD));
90   PetscCall(PetscStrcmp(hostname, roothostname, &flag));
91 
92   localmatch = (PetscMPIInt)flag;
93 
94   PetscCall(MPIU_Allreduce(&localmatch, &allmatch, 1, MPI_INT, MPI_LAND, PETSC_COMM_WORLD));
95 
96   *onehost = (PetscBool)allmatch;
97   PetscFunctionReturn(PETSC_SUCCESS);
98 }
99 
100 PetscErrorCode PetscSetDisplay(void)
101 {
102   PetscMPIInt size, rank;
103   PetscBool   flag, singlehost = PETSC_FALSE;
104   char        display[sizeof(PetscDisplay)];
105   const char *str;
106 
107   PetscFunctionBegin;
108   PetscCall(PetscOptionsGetString(NULL, NULL, "-display", PetscDisplay, sizeof(PetscDisplay), &flag));
109   if (flag) PetscFunctionReturn(PETSC_SUCCESS);
110 
111   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
112   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
113 
114   PetscCall(PetscWorldIsSingleHost(&singlehost));
115 
116   str = getenv("DISPLAY");
117   if (!str) str = ":0.0";
118 #if defined(PETSC_HAVE_X)
119   flag = PETSC_FALSE;
120   PetscCall(PetscOptionsGetBool(NULL, NULL, "-x_virtual", &flag, NULL));
121   if (flag) {
122     /*  this is a crude hack, but better than nothing */
123     PetscCall(PetscPOpen(PETSC_COMM_WORLD, NULL, "pkill -9 Xvfb", "r", NULL));
124     PetscCall(PetscSleep(1));
125     PetscCall(PetscPOpen(PETSC_COMM_WORLD, NULL, "Xvfb :15 -screen 0 1600x1200x24", "r", NULL));
126     PetscCall(PetscSleep(5));
127     str = ":15";
128   }
129 #endif
130   if (str[0] != ':' || singlehost) {
131     PetscCall(PetscStrncpy(display, str, sizeof(display)));
132   } else if (rank == 0) {
133     PetscCall(PetscGetHostName(display, sizeof(display)));
134     PetscCall(PetscStrlcat(display, str, sizeof(display)));
135   }
136   PetscCallMPI(MPI_Bcast(display, sizeof(display), MPI_CHAR, 0, PETSC_COMM_WORLD));
137   PetscCall(PetscMemcpy(PetscDisplay, display, sizeof(PetscDisplay)));
138 
139   PetscDisplay[sizeof(PetscDisplay) - 1] = 0;
140   PetscFunctionReturn(PETSC_SUCCESS);
141 }
142 
143 /*@C
144   PetscGetDisplay - Gets the X windows display variable for all processors.
145 
146   Input Parameter:
147 . n - length of string display
148 
149   Output Parameter:
150 . display - the display string
151 
152   Options Database Keys:
153 + -display <display> - sets the display to use
154 - -x_virtual         - forces use of a X virtual display Xvfb that will not display anything but -draw_save will still work. Xvfb is automatically
155                 started up in PetscSetDisplay() with this option
156 
157   Level: advanced
158 
159 .seealso: `PETSC_DRAW_X`, `PetscDrawOpenX()`
160 @*/
161 PetscErrorCode PetscGetDisplay(char display[], size_t n)
162 {
163   PetscFunctionBegin;
164   PetscCall(PetscStrncpy(display, PetscDisplay, n));
165   PetscFunctionReturn(PETSC_SUCCESS);
166 }
167