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