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