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