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(NULL);CHKERRQ(ierr);} 149 ierr = PetscOptionsList("-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, "-random_view");CHKERRQ(ierr); 204 PetscFunctionReturn(0); 205 } 206 207 #undef __FUNCT__ 208 #define __FUNCT__ "PetscRandomView" 209 /*@C 210 PetscRandomView - Views a random number generator object. 211 212 Collective on PetscRandom 213 214 Input Parameters: 215 + rnd - The random number generator context 216 - viewer - an optional visualization context 217 218 Notes: 219 The available visualization contexts include 220 + PETSC_VIEWER_STDOUT_SELF - standard output (default) 221 - PETSC_VIEWER_STDOUT_WORLD - synchronized standard 222 output where only the first processor opens 223 the file. All other processors send their 224 data to the first processor to print. 225 226 You can change the format the vector is printed using the 227 option PetscViewerSetFormat(). 228 229 Level: beginner 230 231 .seealso: PetscRealView(), PetscScalarView(), PetscIntView() 232 @*/ 233 PetscErrorCode PetscRandomView(PetscRandom rnd,PetscViewer viewer) 234 { 235 PetscErrorCode ierr; 236 PetscBool iascii; 237 238 PetscFunctionBegin; 239 PetscValidHeaderSpecific(rnd,PETSC_RANDOM_CLASSID,1); 240 PetscValidType(rnd,1); 241 if (!viewer) { 242 ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)rnd),&viewer);CHKERRQ(ierr); 243 } 244 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 245 PetscCheckSameComm(rnd,1,viewer,2); 246 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 247 if (iascii) { 248 PetscMPIInt rank; 249 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)rnd),&rank);CHKERRQ(ierr); 250 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr); 251 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%D] Random type %s, seed %D\n",rank,((PetscObject)rnd)->type_name,rnd->seed);CHKERRQ(ierr); 252 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 253 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr); 254 } else { 255 const char *tname; 256 ierr = PetscObjectGetName((PetscObject)viewer,&tname);CHKERRQ(ierr); 257 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for this object",tname); 258 } 259 PetscFunctionReturn(0); 260 } 261 262 #undef __FUNCT__ 263 #define __FUNCT__ "PetscRandomViewFromOptions" 264 /*@ 265 PetscRandomViewFromOptions - This function visualizes the type and the seed of the generated random numbers based upon user options. 266 267 Collective on PetscRandom 268 269 Input Parameters: 270 . rnd - The random number generator context 271 . title - The title 272 273 Level: intermediate 274 275 .keywords: PetscRandom, view, options, database 276 .seealso: PetscRandomSetFromOptions() 277 @*/ 278 PetscErrorCode PetscRandomViewFromOptions(PetscRandom rnd, const char optionname[]) 279 { 280 PetscBool flg; 281 PetscViewer viewer; 282 PetscErrorCode ierr; 283 PetscViewerFormat format; 284 285 PetscFunctionBegin; 286 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)rnd),((PetscObject)rnd)->prefix,optionname,&viewer,&format,&flg);CHKERRQ(ierr); 287 if (flg) { 288 ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr); 289 ierr = PetscRandomView(rnd,viewer);CHKERRQ(ierr); 290 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 291 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 292 } 293 PetscFunctionReturn(0); 294 } 295 296 #if defined(PETSC_HAVE_AMS) 297 #include <petscviewerams.h> 298 #undef __FUNCT__ 299 #define __FUNCT__ "PetscObjectAMSPublish_Random" 300 static PetscErrorCode PetscObjectAMSPublish_Random(PetscObject obj) 301 { 302 PetscRandom rand = (PetscRandom) obj; 303 PetscErrorCode ierr; 304 305 PetscFunctionBegin; 306 ierr = AMS_Memory_add_field(obj->amsmem,"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 = NULL; 365 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 366 ierr = PetscRandomInitializePackage(NULL);CHKERRQ(ierr); 367 #endif 368 369 ierr = PetscHeaderCreate(rr,_p_PetscRandom,struct _PetscRandomOps,PETSC_RANDOM_CLASSID,"PetscRandom","Random number generator","Sys",comm,PetscRandomDestroy,0);CHKERRQ(ierr); 370 371 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 372 373 rr->data = NULL; 374 rr->low = 0.0; 375 rr->width = 1.0; 376 rr->iset = PETSC_FALSE; 377 rr->seed = 0x12345678 + 76543*rank; 378 #if defined(PETSC_HAVE_AMS) 379 ((PetscObject)rr)->bops->publish = PetscObjectAMSPublish_Random; 380 #endif 381 *r = rr; 382 PetscFunctionReturn(0); 383 } 384 385 #undef __FUNCT__ 386 #define __FUNCT__ "PetscRandomSeed" 387 /*@ 388 PetscRandomSeed - Seed the generator. 389 390 Not collective 391 392 Input Parameters: 393 . r - The random number generator context 394 395 Level: intermediate 396 397 Usage: 398 PetscRandomSetSeed(r,a positive integer); 399 PetscRandomSeed(r); PetscRandomGetValue() will now start with the new seed. 400 401 PetscRandomSeed(r) without a call to PetscRandomSetSeed() re-initializes 402 the seed. The random numbers generated will be the same as before. 403 404 Concepts: random numbers^seed 405 406 .seealso: PetscRandomCreate(), PetscRandomGetSeed(), PetscRandomSetSeed() 407 @*/ 408 PetscErrorCode PetscRandomSeed(PetscRandom r) 409 { 410 PetscErrorCode ierr; 411 412 PetscFunctionBegin; 413 PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1); 414 PetscValidType(r,1); 415 416 ierr = (*r->ops->seed)(r);CHKERRQ(ierr); 417 ierr = PetscObjectStateIncrease((PetscObject)r);CHKERRQ(ierr); 418 PetscFunctionReturn(0); 419 } 420 421