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 if ((*r)->ops->destroy) { 45 ierr = (*(*r)->ops->destroy)(*r);CHKERRQ(ierr); 46 } 47 ierr = PetscHeaderDestroy(r);CHKERRQ(ierr); 48 PetscFunctionReturn(0); 49 } 50 51 52 #undef __FUNCT__ 53 #define __FUNCT__ "PetscRandomGetSeed" 54 /*@ 55 PetscRandomGetSeed - Gets the random seed. 56 57 Not collective 58 59 Input Parameters: 60 . r - The random number generator context 61 62 Output Parameter: 63 . seed - The random seed 64 65 Level: intermediate 66 67 Concepts: random numbers^seed 68 69 .seealso: PetscRandomCreate(), PetscRandomSetSeed(), PetscRandomSeed() 70 @*/ 71 PetscErrorCode PetscRandomGetSeed(PetscRandom r,unsigned long *seed) 72 { 73 PetscFunctionBegin; 74 PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1); 75 if (seed) { 76 PetscValidPointer(seed,2); 77 *seed = r->seed; 78 } 79 PetscFunctionReturn(0); 80 } 81 82 #undef __FUNCT__ 83 #define __FUNCT__ "PetscRandomSetSeed" 84 /*@ 85 PetscRandomSetSeed - Sets the random seed. You MUST call PetscRandomSeed() after this call to have the new seed used. 86 87 Not collective 88 89 Input Parameters: 90 + r - The random number generator context 91 - seed - The random seed 92 93 Level: intermediate 94 95 Usage: 96 PetscRandomSetSeed(r,a positive integer); 97 PetscRandomSeed(r); PetscRandomGetValue() will now start with the new seed. 98 99 PetscRandomSeed(r) without a call to PetscRandomSetSeed() re-initializes 100 the seed. The random numbers generated will be the same as before. 101 102 Concepts: random numbers^seed 103 104 .seealso: PetscRandomCreate(), PetscRandomGetSeed(), PetscRandomSeed() 105 @*/ 106 PetscErrorCode PetscRandomSetSeed(PetscRandom r,unsigned long seed) 107 { 108 PetscErrorCode ierr; 109 110 PetscFunctionBegin; 111 PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1); 112 r->seed = seed; 113 ierr = PetscInfo1(NULL,"Setting seed to %d\n",(int)seed);CHKERRQ(ierr); 114 PetscFunctionReturn(0); 115 } 116 117 /* ------------------------------------------------------------------- */ 118 #undef __FUNCT__ 119 #define __FUNCT__ "PetscRandomSetTypeFromOptions_Private" 120 /* 121 PetscRandomSetTypeFromOptions_Private - Sets the type of random generator from user options. Defaults to type PETSCRAND48 or PETSCRAND. 122 123 Collective on PetscRandom 124 125 Input Parameter: 126 . rnd - The random number generator context 127 128 Level: intermediate 129 130 .keywords: PetscRandom, set, options, database, type 131 .seealso: PetscRandomSetFromOptions(), PetscRandomSetType() 132 */ 133 static PetscErrorCode PetscRandomSetTypeFromOptions_Private(PetscOptions *PetscOptionsObject,PetscRandom rnd) 134 { 135 PetscBool opt; 136 const char *defaultType; 137 char typeName[256]; 138 PetscErrorCode ierr; 139 140 PetscFunctionBegin; 141 if (((PetscObject)rnd)->type_name) { 142 defaultType = ((PetscObject)rnd)->type_name; 143 } else { 144 defaultType = PETSCRANDER48; 145 } 146 147 ierr = PetscRandomRegisterAll();CHKERRQ(ierr); 148 ierr = PetscOptionsFList("-random_type","PetscRandom type","PetscRandomSetType",PetscRandomList,defaultType,typeName,256,&opt);CHKERRQ(ierr); 149 if (opt) { 150 ierr = PetscRandomSetType(rnd, typeName);CHKERRQ(ierr); 151 } else { 152 ierr = PetscRandomSetType(rnd, defaultType);CHKERRQ(ierr); 153 } 154 PetscFunctionReturn(0); 155 } 156 157 #undef __FUNCT__ 158 #define __FUNCT__ "PetscRandomSetFromOptions" 159 /*@ 160 PetscRandomSetFromOptions - Configures the random number generator from the options database. 161 162 Collective on PetscRandom 163 164 Input Parameter: 165 . rnd - The random number generator context 166 167 Options Database: 168 . -random_seed <integer> - provide a seed to the random number generater 169 170 Notes: To see all options, run your program with the -help option. 171 Must be called after PetscRandomCreate() but before the rnd is used. 172 173 Level: beginner 174 175 .keywords: PetscRandom, set, options, database 176 .seealso: PetscRandomCreate(), PetscRandomSetType() 177 @*/ 178 PetscErrorCode PetscRandomSetFromOptions(PetscRandom rnd) 179 { 180 PetscErrorCode ierr; 181 PetscBool set; 182 PetscInt seed; 183 184 PetscFunctionBegin; 185 PetscValidHeaderSpecific(rnd,PETSC_RANDOM_CLASSID,1); 186 187 ierr = PetscObjectOptionsBegin((PetscObject)rnd);CHKERRQ(ierr); 188 189 /* Handle PetscRandom type options */ 190 ierr = PetscRandomSetTypeFromOptions_Private(PetscOptionsObject,rnd);CHKERRQ(ierr); 191 192 /* Handle specific random generator's options */ 193 if (rnd->ops->setfromoptions) { 194 ierr = (*rnd->ops->setfromoptions)(PetscOptionsObject,rnd);CHKERRQ(ierr); 195 } 196 ierr = PetscOptionsInt("-random_seed","Seed to use to generate random numbers","PetscRandomSetSeed",0,&seed,&set);CHKERRQ(ierr); 197 if (set) { 198 ierr = PetscRandomSetSeed(rnd,(unsigned long int)seed);CHKERRQ(ierr); 199 ierr = PetscRandomSeed(rnd);CHKERRQ(ierr); 200 } 201 ierr = PetscOptionsEnd();CHKERRQ(ierr); 202 ierr = PetscRandomViewFromOptions(rnd,NULL, "-random_view");CHKERRQ(ierr); 203 PetscFunctionReturn(0); 204 } 205 206 #if defined(PETSC_HAVE_SAWS) 207 #include <petscviewersaws.h> 208 #endif 209 #undef __FUNCT__ 210 #define __FUNCT__ "PetscRandomView" 211 /*@C 212 PetscRandomView - Views a random number generator object. 213 214 Collective on PetscRandom 215 216 Input Parameters: 217 + rnd - The random number generator context 218 - viewer - an optional visualization context 219 220 Notes: 221 The available visualization contexts include 222 + PETSC_VIEWER_STDOUT_SELF - standard output (default) 223 - PETSC_VIEWER_STDOUT_WORLD - synchronized standard 224 output where only the first processor opens 225 the file. All other processors send their 226 data to the first processor to print. 227 228 You can change the format the vector is printed using the 229 option PetscViewerSetFormat(). 230 231 Level: beginner 232 233 .seealso: PetscRealView(), PetscScalarView(), PetscIntView() 234 @*/ 235 PetscErrorCode PetscRandomView(PetscRandom rnd,PetscViewer viewer) 236 { 237 PetscErrorCode ierr; 238 PetscBool iascii; 239 #if defined(PETSC_HAVE_SAWS) 240 PetscBool issaws; 241 #endif 242 243 PetscFunctionBegin; 244 PetscValidHeaderSpecific(rnd,PETSC_RANDOM_CLASSID,1); 245 PetscValidType(rnd,1); 246 if (!viewer) { 247 ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)rnd),&viewer);CHKERRQ(ierr); 248 } 249 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 250 PetscCheckSameComm(rnd,1,viewer,2); 251 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 252 #if defined(PETSC_HAVE_SAWS) 253 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws);CHKERRQ(ierr); 254 #endif 255 if (iascii) { 256 PetscMPIInt rank; 257 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)rnd,viewer);CHKERRQ(ierr); 258 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)rnd),&rank);CHKERRQ(ierr); 259 ierr = PetscViewerASCIIPushSynchronized(viewer);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 = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 263 #if defined(PETSC_HAVE_SAWS) 264 } else if (issaws) { 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__ "PetscRandomCreate" 284 /*@ 285 PetscRandomCreate - Creates a context for generating random numbers, 286 and initializes the random-number generator. 287 288 Collective on MPI_Comm 289 290 Input Parameters: 291 + comm - MPI communicator 292 293 Output Parameter: 294 . r - the random number generator context 295 296 Level: intermediate 297 298 Notes: 299 The random type has to be set by PetscRandomSetType(). 300 301 This is only a primative "parallel" random number generator, it should NOT 302 be used for sophisticated parallel Monte Carlo methods since it will very likely 303 not have the correct statistics across processors. You can provide your own 304 parallel generator using PetscRandomRegister(); 305 306 If you create a PetscRandom() using PETSC_COMM_SELF on several processors then 307 the SAME random numbers will be generated on all those processors. Use PETSC_COMM_WORLD 308 or the appropriate parallel communicator to eliminate this issue. 309 310 Use VecSetRandom() to set the elements of a vector to random numbers. 311 312 Example of Usage: 313 .vb 314 PetscRandomCreate(PETSC_COMM_SELF,&r); 315 PetscRandomSetType(r,PETSCRAND48); 316 PetscRandomGetValue(r,&value1); 317 PetscRandomGetValueReal(r,&value2); 318 PetscRandomDestroy(&r); 319 .ve 320 321 Concepts: random numbers^creating 322 323 .seealso: PetscRandomSetType(), PetscRandomGetValue(), PetscRandomGetValueReal(), PetscRandomSetInterval(), 324 PetscRandomDestroy(), VecSetRandom(), PetscRandomType 325 @*/ 326 327 PetscErrorCode PetscRandomCreate(MPI_Comm comm,PetscRandom *r) 328 { 329 PetscRandom rr; 330 PetscErrorCode ierr; 331 PetscMPIInt rank; 332 333 PetscFunctionBegin; 334 PetscValidPointer(r,3); 335 *r = NULL; 336 ierr = PetscRandomInitializePackage();CHKERRQ(ierr); 337 338 ierr = PetscHeaderCreate(rr,PETSC_RANDOM_CLASSID,"PetscRandom","Random number generator","Sys",comm,PetscRandomDestroy,NULL);CHKERRQ(ierr); 339 340 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 341 342 rr->data = NULL; 343 rr->low = 0.0; 344 rr->width = 1.0; 345 rr->iset = PETSC_FALSE; 346 rr->seed = 0x12345678 + 76543*rank; 347 *r = rr; 348 PetscFunctionReturn(0); 349 } 350 351 #undef __FUNCT__ 352 #define __FUNCT__ "PetscRandomSeed" 353 /*@ 354 PetscRandomSeed - Seed the generator. 355 356 Not collective 357 358 Input Parameters: 359 . r - The random number generator context 360 361 Level: intermediate 362 363 Usage: 364 PetscRandomSetSeed(r,a positive integer); 365 PetscRandomSeed(r); PetscRandomGetValue() will now start with the new seed. 366 367 PetscRandomSeed(r) without a call to PetscRandomSetSeed() re-initializes 368 the seed. The random numbers generated will be the same as before. 369 370 Concepts: random numbers^seed 371 372 .seealso: PetscRandomCreate(), PetscRandomGetSeed(), PetscRandomSetSeed() 373 @*/ 374 PetscErrorCode PetscRandomSeed(PetscRandom r) 375 { 376 PetscErrorCode ierr; 377 378 PetscFunctionBegin; 379 PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1); 380 PetscValidType(r,1); 381 382 ierr = (*r->ops->seed)(r);CHKERRQ(ierr); 383 ierr = PetscObjectStateIncrease((PetscObject)r);CHKERRQ(ierr); 384 PetscFunctionReturn(0); 385 } 386 387