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, MPI_C_BOOL, 0, comm)); 63 PetscCallMPI(MPI_Bcast(env, (PetscMPIInt)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 PetscCallMPI(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 -15 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