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