1 2 /* 3 This file contains routines for interfacing to random number generators. 4 This provides more than just an interface to some system random number 5 generator: 6 7 Numbers can be shuffled for use as random tuples 8 9 Multiple random number generators may be used 10 11 We are still not sure what interface we want here. There should be 12 one to reinitialize and set the seed. 13 */ 14 15 #include <../src/sys/classes/random/randomimpl.h> /*I "petscsys.h" I*/ 16 #include <petscviewer.h> 17 18 /* Logging support */ 19 PetscClassId PETSC_RANDOM_CLASSID; 20 21 #undef __FUNCT__ 22 #define __FUNCT__ "PetscRandomDestroy" 23 /*@ 24 PetscRandomDestroy - Destroys a context that has been formed by 25 PetscRandomCreate(). 26 27 Collective on PetscRandom 28 29 Intput Parameter: 30 . r - the random number generator context 31 32 Level: intermediate 33 34 .seealso: PetscRandomGetValue(), PetscRandomCreate(), VecSetRandom() 35 @*/ 36 PetscErrorCode PetscRandomDestroy(PetscRandom *r) 37 { 38 PetscErrorCode ierr; 39 40 PetscFunctionBegin; 41 if (!*r) PetscFunctionReturn(0); 42 PetscValidHeaderSpecific(*r,PETSC_RANDOM_CLASSID,1); 43 if (--((PetscObject)(*r))->refct > 0) {*r = 0; PetscFunctionReturn(0);} 44 ierr = PetscHeaderDestroy(r);CHKERRQ(ierr); 45 PetscFunctionReturn(0); 46 } 47 48 49 #undef __FUNCT__ 50 #define __FUNCT__ "PetscRandomGetSeed" 51 /*@ 52 PetscRandomGetSeed - Gets the random seed. 53 54 Not collective 55 56 Input Parameters: 57 . r - The random number generator context 58 59 Output Parameter: 60 . seed - The random seed 61 62 Level: intermediate 63 64 Concepts: random numbers^seed 65 66 .seealso: PetscRandomCreate(), PetscRandomSetSeed(), PetscRandomSeed() 67 @*/ 68 PetscErrorCode PetscRandomGetSeed(PetscRandom r,unsigned long *seed) 69 { 70 PetscFunctionBegin; 71 PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1); 72 if (seed) { 73 PetscValidPointer(seed,2); 74 *seed = r->seed; 75 } 76 PetscFunctionReturn(0); 77 } 78 79 #undef __FUNCT__ 80 #define __FUNCT__ "PetscRandomSetSeed" 81 /*@ 82 PetscRandomSetSeed - Sets the random seed. You MUST call PetscRandomSeed() after this call to have the new seed used. 83 84 Not collective 85 86 Input Parameters: 87 + r - The random number generator context 88 - seed - The random seed 89 90 Level: intermediate 91 92 Usage: 93 PetscRandomSetSeed(r,a positive integer); 94 PetscRandomSeed(r); PetscRandomGetValue() will now start with the new seed. 95 96 PetscRandomSeed(r) without a call to PetscRandomSetSeed() re-initializes 97 the seed. The random numbers generated will be the same as before. 98 99 Concepts: random numbers^seed 100 101 .seealso: PetscRandomCreate(), PetscRandomGetSeed(), PetscRandomSeed() 102 @*/ 103 PetscErrorCode PetscRandomSetSeed(PetscRandom r,unsigned long seed) 104 { 105 PetscErrorCode ierr; 106 107 PetscFunctionBegin; 108 PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1); 109 r->seed = seed; 110 ierr = PetscInfo1(NULL,"Setting seed to %d\n",(int)seed);CHKERRQ(ierr); 111 PetscFunctionReturn(0); 112 } 113 114 /* ------------------------------------------------------------------- */ 115 #undef __FUNCT__ 116 #define __FUNCT__ "PetscRandomSetTypeFromOptions_Private" 117 /* 118 PetscRandomSetTypeFromOptions_Private - Sets the type of random generator from user options. Defaults to type PETSCRAND48 or PETSCRAND. 119 120 Collective on PetscRandom 121 122 Input Parameter: 123 . rnd - The random number generator context 124 125 Level: intermediate 126 127 .keywords: PetscRandom, set, options, database, type 128 .seealso: PetscRandomSetFromOptions(), PetscRandomSetType() 129 */ 130 static PetscErrorCode PetscRandomSetTypeFromOptions_Private(PetscRandom rnd) 131 { 132 PetscBool opt; 133 const char *defaultType; 134 char typeName[256]; 135 PetscErrorCode ierr; 136 137 PetscFunctionBegin; 138 if (((PetscObject)rnd)->type_name) { 139 defaultType = ((PetscObject)rnd)->type_name; 140 } else { 141 #if defined(PETSC_HAVE_DRAND48) 142 defaultType = PETSCRAND48; 143 #elif defined(PETSC_HAVE_RAND) 144 defaultType = PETSCRAND; 145 #endif 146 } 147 148 if (!PetscRandomRegisterAllCalled) {ierr = PetscRandomRegisterAll();CHKERRQ(ierr);} 149 ierr = PetscOptionsFList("-random_type","PetscRandom type","PetscRandomSetType",PetscRandomList,defaultType,typeName,256,&opt);CHKERRQ(ierr); 150 if (opt) { 151 ierr = PetscRandomSetType(rnd, typeName);CHKERRQ(ierr); 152 } else { 153 ierr = PetscRandomSetType(rnd, defaultType);CHKERRQ(ierr); 154 } 155 PetscFunctionReturn(0); 156 } 157 158 #undef __FUNCT__ 159 #define __FUNCT__ "PetscRandomSetFromOptions" 160 /*@ 161 PetscRandomSetFromOptions - Configures the random number generator from the options database. 162 163 Collective on PetscRandom 164 165 Input Parameter: 166 . rnd - The random number generator context 167 168 Options Database: 169 . -random_seed <integer> - provide a seed to the random number generater 170 171 Notes: To see all options, run your program with the -help option. 172 Must be called after PetscRandomCreate() but before the rnd is used. 173 174 Level: beginner 175 176 .keywords: PetscRandom, set, options, database 177 .seealso: PetscRandomCreate(), PetscRandomSetType() 178 @*/ 179 PetscErrorCode PetscRandomSetFromOptions(PetscRandom rnd) 180 { 181 PetscErrorCode ierr; 182 PetscBool set; 183 PetscInt seed; 184 185 PetscFunctionBegin; 186 PetscValidHeaderSpecific(rnd,PETSC_RANDOM_CLASSID,1); 187 188 ierr = PetscObjectOptionsBegin((PetscObject)rnd);CHKERRQ(ierr); 189 190 /* Handle PetscRandom type options */ 191 ierr = PetscRandomSetTypeFromOptions_Private(rnd);CHKERRQ(ierr); 192 193 /* Handle specific random generator's options */ 194 if (rnd->ops->setfromoptions) { 195 ierr = (*rnd->ops->setfromoptions)(rnd);CHKERRQ(ierr); 196 } 197 ierr = PetscOptionsInt("-random_seed","Seed to use to generate random numbers","PetscRandomSetSeed",0,&seed,&set);CHKERRQ(ierr); 198 if (set) { 199 ierr = PetscRandomSetSeed(rnd,(unsigned long int)seed);CHKERRQ(ierr); 200 ierr = PetscRandomSeed(rnd);CHKERRQ(ierr); 201 } 202 ierr = PetscOptionsEnd();CHKERRQ(ierr); 203 ierr = PetscRandomViewFromOptions(rnd,NULL, "-random_view");CHKERRQ(ierr); 204 PetscFunctionReturn(0); 205 } 206 207 #if defined(PETSC_HAVE_SAWS) 208 #include <petscviewersaws.h> 209 #endif 210 #undef __FUNCT__ 211 #define __FUNCT__ "PetscRandomView" 212 /*@C 213 PetscRandomView - Views a random number generator object. 214 215 Collective on PetscRandom 216 217 Input Parameters: 218 + rnd - The random number generator context 219 - viewer - an optional visualization context 220 221 Notes: 222 The available visualization contexts include 223 + PETSC_VIEWER_STDOUT_SELF - standard output (default) 224 - PETSC_VIEWER_STDOUT_WORLD - synchronized standard 225 output where only the first processor opens 226 the file. All other processors send their 227 data to the first processor to print. 228 229 You can change the format the vector is printed using the 230 option PetscViewerSetFormat(). 231 232 Level: beginner 233 234 .seealso: PetscRealView(), PetscScalarView(), PetscIntView() 235 @*/ 236 PetscErrorCode PetscRandomView(PetscRandom rnd,PetscViewer viewer) 237 { 238 PetscErrorCode ierr; 239 PetscBool iascii; 240 #if defined(PETSC_HAVE_SAWS) 241 PetscBool isams; 242 #endif 243 244 PetscFunctionBegin; 245 PetscValidHeaderSpecific(rnd,PETSC_RANDOM_CLASSID,1); 246 PetscValidType(rnd,1); 247 if (!viewer) { 248 ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)rnd),&viewer);CHKERRQ(ierr); 249 } 250 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 251 PetscCheckSameComm(rnd,1,viewer,2); 252 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 253 #if defined(PETSC_HAVE_SAWS) 254 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&isams);CHKERRQ(ierr); 255 #endif 256 if (iascii) { 257 PetscMPIInt rank; 258 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)rnd),&rank);CHKERRQ(ierr); 259 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr); 260 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%D] Random type %s, seed %D\n",rank,((PetscObject)rnd)->type_name,rnd->seed);CHKERRQ(ierr); 261 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 262 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr); 263 #if defined(PETSC_HAVE_SAWS) 264 } else if (isams) { 265 PetscMPIInt rank; 266 const char *name; 267 268 ierr = PetscObjectGetName((PetscObject)rnd,&name);CHKERRQ(ierr); 269 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); 270 if (!((PetscObject)rnd)->amsmem && !rank) { 271 char dir[1024]; 272 273 ierr = PetscObjectViewSAWs((PetscObject)rnd,viewer);CHKERRQ(ierr); 274 ierr = PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/Low",name);CHKERRQ(ierr); 275 PetscStackCallSAWs(SAWs_Register,(dir,&rnd->low,1,SAWs_READ,SAWs_DOUBLE)); 276 } 277 #endif 278 } 279 PetscFunctionReturn(0); 280 } 281 282 #undef __FUNCT__ 283 #define __FUNCT__ "PetscRandomViewFromOptions" 284 /* 285 PetscRandomViewFromOptions - This function visualizes the type and the seed of the generated random numbers based upon user options. 286 287 Collective on PetscRandom 288 289 Input Parameters: 290 + rnd - The random number generator context 291 . prefix - prefix to use for viewing, or NULL to use prefix of 'rnd' 292 - optionname - option to activate viewing 293 294 Level: intermediate 295 296 .keywords: PetscRandom, view, options, database 297 .seealso: PetscRandomSetFromOptions() 298 */ 299 PetscErrorCode PetscRandomViewFromOptions(PetscRandom rnd, const char prefix[], const char optionname[]) 300 { 301 PetscBool flg; 302 PetscViewer viewer; 303 PetscErrorCode ierr; 304 PetscViewerFormat format; 305 306 PetscFunctionBegin; 307 if (prefix) { 308 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)rnd),prefix,optionname,&viewer,&format,&flg);CHKERRQ(ierr); 309 } else { 310 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)rnd),((PetscObject)rnd)->prefix,optionname,&viewer,&format,&flg);CHKERRQ(ierr); 311 } 312 if (flg) { 313 ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr); 314 ierr = PetscRandomView(rnd,viewer);CHKERRQ(ierr); 315 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 316 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 317 } 318 PetscFunctionReturn(0); 319 } 320 321 #undef __FUNCT__ 322 #define __FUNCT__ "PetscRandomCreate" 323 /*@ 324 PetscRandomCreate - Creates a context for generating random numbers, 325 and initializes the random-number generator. 326 327 Collective on MPI_Comm 328 329 Input Parameters: 330 + comm - MPI communicator 331 332 Output Parameter: 333 . r - the random number generator context 334 335 Level: intermediate 336 337 Notes: 338 The random type has to be set by PetscRandomSetType(). 339 340 This is only a primative "parallel" random number generator, it should NOT 341 be used for sophisticated parallel Monte Carlo methods since it will very likely 342 not have the correct statistics across processors. You can provide your own 343 parallel generator using PetscRandomRegister(); 344 345 If you create a PetscRandom() using PETSC_COMM_SELF on several processors then 346 the SAME random numbers will be generated on all those processors. Use PETSC_COMM_WORLD 347 or the appropriate parallel communicator to eliminate this issue. 348 349 Use VecSetRandom() to set the elements of a vector to random numbers. 350 351 Example of Usage: 352 .vb 353 PetscRandomCreate(PETSC_COMM_SELF,&r); 354 PetscRandomSetType(r,PETSCRAND48); 355 PetscRandomGetValue(r,&value1); 356 PetscRandomGetValueReal(r,&value2); 357 PetscRandomDestroy(&r); 358 .ve 359 360 Concepts: random numbers^creating 361 362 .seealso: PetscRandomSetType(), PetscRandomGetValue(), PetscRandomGetValueReal(), PetscRandomSetInterval(), 363 PetscRandomDestroy(), VecSetRandom(), PetscRandomType 364 @*/ 365 366 PetscErrorCode PetscRandomCreate(MPI_Comm comm,PetscRandom *r) 367 { 368 PetscRandom rr; 369 PetscErrorCode ierr; 370 PetscMPIInt rank; 371 372 PetscFunctionBegin; 373 PetscValidPointer(r,3); 374 *r = NULL; 375 ierr = PetscRandomInitializePackage();CHKERRQ(ierr); 376 377 ierr = PetscHeaderCreate(rr,_p_PetscRandom,struct _PetscRandomOps,PETSC_RANDOM_CLASSID,"PetscRandom","Random number generator","Sys",comm,PetscRandomDestroy,0);CHKERRQ(ierr); 378 379 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 380 381 rr->data = NULL; 382 rr->low = 0.0; 383 rr->width = 1.0; 384 rr->iset = PETSC_FALSE; 385 rr->seed = 0x12345678 + 76543*rank; 386 *r = rr; 387 PetscFunctionReturn(0); 388 } 389 390 #undef __FUNCT__ 391 #define __FUNCT__ "PetscRandomSeed" 392 /*@ 393 PetscRandomSeed - Seed the generator. 394 395 Not collective 396 397 Input Parameters: 398 . r - The random number generator context 399 400 Level: intermediate 401 402 Usage: 403 PetscRandomSetSeed(r,a positive integer); 404 PetscRandomSeed(r); PetscRandomGetValue() will now start with the new seed. 405 406 PetscRandomSeed(r) without a call to PetscRandomSetSeed() re-initializes 407 the seed. The random numbers generated will be the same as before. 408 409 Concepts: random numbers^seed 410 411 .seealso: PetscRandomCreate(), PetscRandomGetSeed(), PetscRandomSetSeed() 412 @*/ 413 PetscErrorCode PetscRandomSeed(PetscRandom r) 414 { 415 PetscErrorCode ierr; 416 417 PetscFunctionBegin; 418 PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1); 419 PetscValidType(r,1); 420 421 ierr = (*r->ops->seed)(r);CHKERRQ(ierr); 422 ierr = PetscObjectStateIncrease((PetscObject)r);CHKERRQ(ierr); 423 PetscFunctionReturn(0); 424 } 425 426