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 /*@ 22 PetscRandomDestroy - Destroys a context that has been formed by 23 PetscRandomCreate(). 24 25 Collective on PetscRandom 26 27 Intput Parameter: 28 . r - the random number generator context 29 30 Level: intermediate 31 32 .seealso: PetscRandomGetValue(), PetscRandomCreate(), VecSetRandom() 33 @*/ 34 PetscErrorCode PetscRandomDestroy(PetscRandom *r) 35 { 36 PetscErrorCode ierr; 37 38 PetscFunctionBegin; 39 if (!*r) PetscFunctionReturn(0); 40 PetscValidHeaderSpecific(*r,PETSC_RANDOM_CLASSID,1); 41 if (--((PetscObject)(*r))->refct > 0) {*r = 0; PetscFunctionReturn(0);} 42 if ((*r)->ops->destroy) { 43 ierr = (*(*r)->ops->destroy)(*r);CHKERRQ(ierr); 44 } 45 ierr = PetscHeaderDestroy(r);CHKERRQ(ierr); 46 PetscFunctionReturn(0); 47 } 48 49 50 /*@C 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 /*@C 79 PetscRandomSetSeed - Sets the random seed. You MUST call PetscRandomSeed() after this call to have the new seed used. 80 81 Not collective 82 83 Input Parameters: 84 + r - The random number generator context 85 - seed - The random seed 86 87 Level: intermediate 88 89 Usage: 90 PetscRandomSetSeed(r,a positive integer); 91 PetscRandomSeed(r); PetscRandomGetValue() will now start with the new seed. 92 93 PetscRandomSeed(r) without a call to PetscRandomSetSeed() re-initializes 94 the seed. The random numbers generated will be the same as before. 95 96 Concepts: random numbers^seed 97 98 .seealso: PetscRandomCreate(), PetscRandomGetSeed(), PetscRandomSeed() 99 @*/ 100 PetscErrorCode PetscRandomSetSeed(PetscRandom r,unsigned long seed) 101 { 102 PetscErrorCode ierr; 103 104 PetscFunctionBegin; 105 PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1); 106 r->seed = seed; 107 ierr = PetscInfo1(NULL,"Setting seed to %d\n",(int)seed);CHKERRQ(ierr); 108 PetscFunctionReturn(0); 109 } 110 111 /* ------------------------------------------------------------------- */ 112 /* 113 PetscRandomSetTypeFromOptions_Private - Sets the type of random generator from user options. Defaults to type PETSCRAND48 or PETSCRAND. 114 115 Collective on PetscRandom 116 117 Input Parameter: 118 . rnd - The random number generator context 119 120 Level: intermediate 121 122 .keywords: PetscRandom, set, options, database, type 123 .seealso: PetscRandomSetFromOptions(), PetscRandomSetType() 124 */ 125 static PetscErrorCode PetscRandomSetTypeFromOptions_Private(PetscOptionItems *PetscOptionsObject,PetscRandom rnd) 126 { 127 PetscBool opt; 128 const char *defaultType; 129 char typeName[256]; 130 PetscErrorCode ierr; 131 132 PetscFunctionBegin; 133 if (((PetscObject)rnd)->type_name) { 134 defaultType = ((PetscObject)rnd)->type_name; 135 } else { 136 defaultType = PETSCRANDER48; 137 } 138 139 ierr = PetscRandomRegisterAll();CHKERRQ(ierr); 140 ierr = PetscOptionsFList("-random_type","PetscRandom type","PetscRandomSetType",PetscRandomList,defaultType,typeName,256,&opt);CHKERRQ(ierr); 141 if (opt) { 142 ierr = PetscRandomSetType(rnd, typeName);CHKERRQ(ierr); 143 } else { 144 ierr = PetscRandomSetType(rnd, defaultType);CHKERRQ(ierr); 145 } 146 PetscFunctionReturn(0); 147 } 148 149 /*@ 150 PetscRandomSetFromOptions - Configures the random number generator from the options database. 151 152 Collective on PetscRandom 153 154 Input Parameter: 155 . rnd - The random number generator context 156 157 Options Database: 158 + -random_seed <integer> - provide a seed to the random number generater 159 - -random_no_imaginary_part - makes the imaginary part of the random number zero, this is useful when you want the 160 same code to produce the same result when run with real numbers or complex numbers for regression testing purposes 161 162 Notes: 163 To see all options, run your program with the -help option. 164 Must be called after PetscRandomCreate() but before the rnd is used. 165 166 Level: beginner 167 168 .keywords: PetscRandom, set, options, database 169 .seealso: PetscRandomCreate(), PetscRandomSetType() 170 @*/ 171 PetscErrorCode PetscRandomSetFromOptions(PetscRandom rnd) 172 { 173 PetscErrorCode ierr; 174 PetscBool set,noimaginary = PETSC_FALSE; 175 PetscInt seed; 176 177 PetscFunctionBegin; 178 PetscValidHeaderSpecific(rnd,PETSC_RANDOM_CLASSID,1); 179 180 ierr = PetscObjectOptionsBegin((PetscObject)rnd);CHKERRQ(ierr); 181 182 /* Handle PetscRandom type options */ 183 ierr = PetscRandomSetTypeFromOptions_Private(PetscOptionsObject,rnd);CHKERRQ(ierr); 184 185 /* Handle specific random generator's options */ 186 if (rnd->ops->setfromoptions) { 187 ierr = (*rnd->ops->setfromoptions)(PetscOptionsObject,rnd);CHKERRQ(ierr); 188 } 189 ierr = PetscOptionsInt("-random_seed","Seed to use to generate random numbers","PetscRandomSetSeed",0,&seed,&set);CHKERRQ(ierr); 190 if (set) { 191 ierr = PetscRandomSetSeed(rnd,(unsigned long int)seed);CHKERRQ(ierr); 192 ierr = PetscRandomSeed(rnd);CHKERRQ(ierr); 193 } 194 ierr = PetscOptionsBool("-random_no_imaginary_part","The imaginary part of the random number will be zero","PetscRandomSetInterval",noimaginary,&noimaginary,&set);CHKERRQ(ierr); 195 #if defined(PETSC_HAVE_COMPLEX) 196 if (set) { 197 if (noimaginary) { 198 PetscScalar low,high; 199 ierr = PetscRandomGetInterval(rnd,&low,&high);CHKERRQ(ierr); 200 low = low - PetscImaginaryPart(low); 201 high = high - PetscImaginaryPart(high); 202 ierr = PetscRandomSetInterval(rnd,low,high);CHKERRQ(ierr); 203 } 204 } 205 #endif 206 ierr = PetscOptionsEnd();CHKERRQ(ierr); 207 ierr = PetscRandomViewFromOptions(rnd,NULL, "-random_view");CHKERRQ(ierr); 208 PetscFunctionReturn(0); 209 } 210 211 #if defined(PETSC_HAVE_SAWS) 212 #include <petscviewersaws.h> 213 #endif 214 /*@C 215 PetscRandomView - Views a random number generator object. 216 217 Collective on PetscRandom 218 219 Input Parameters: 220 + rnd - The random number generator context 221 - viewer - an optional visualization context 222 223 Notes: 224 The available visualization contexts include 225 + PETSC_VIEWER_STDOUT_SELF - standard output (default) 226 - PETSC_VIEWER_STDOUT_WORLD - synchronized standard 227 output where only the first processor opens 228 the file. All other processors send their 229 data to the first processor to print. 230 231 You can change the format the vector is printed using the 232 option PetscViewerPushFormat(). 233 234 Level: beginner 235 236 .seealso: PetscRealView(), PetscScalarView(), PetscIntView() 237 @*/ 238 PetscErrorCode PetscRandomView(PetscRandom rnd,PetscViewer viewer) 239 { 240 PetscErrorCode ierr; 241 PetscBool iascii; 242 #if defined(PETSC_HAVE_SAWS) 243 PetscBool issaws; 244 #endif 245 246 PetscFunctionBegin; 247 PetscValidHeaderSpecific(rnd,PETSC_RANDOM_CLASSID,1); 248 PetscValidType(rnd,1); 249 if (!viewer) { 250 ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)rnd),&viewer);CHKERRQ(ierr); 251 } 252 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 253 PetscCheckSameComm(rnd,1,viewer,2); 254 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 255 #if defined(PETSC_HAVE_SAWS) 256 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws);CHKERRQ(ierr); 257 #endif 258 if (iascii) { 259 PetscMPIInt rank; 260 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)rnd,viewer);CHKERRQ(ierr); 261 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)rnd),&rank);CHKERRQ(ierr); 262 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 263 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Random type %s, seed %lu\n",rank,((PetscObject)rnd)->type_name,rnd->seed);CHKERRQ(ierr); 264 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 265 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 266 #if defined(PETSC_HAVE_SAWS) 267 } else if (issaws) { 268 PetscMPIInt rank; 269 const char *name; 270 271 ierr = PetscObjectGetName((PetscObject)rnd,&name);CHKERRQ(ierr); 272 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); 273 if (!((PetscObject)rnd)->amsmem && !rank) { 274 char dir[1024]; 275 276 ierr = PetscObjectViewSAWs((PetscObject)rnd,viewer);CHKERRQ(ierr); 277 ierr = PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/Low",name);CHKERRQ(ierr); 278 PetscStackCallSAWs(SAWs_Register,(dir,&rnd->low,1,SAWs_READ,SAWs_DOUBLE)); 279 } 280 #endif 281 } 282 PetscFunctionReturn(0); 283 } 284 285 /*@ 286 PetscRandomCreate - Creates a context for generating random numbers, 287 and initializes the random-number generator. 288 289 Collective on MPI_Comm 290 291 Input Parameters: 292 . comm - MPI communicator 293 294 Output Parameter: 295 . r - the random number generator context 296 297 Level: intermediate 298 299 Notes: 300 The random type has to be set by PetscRandomSetType(). 301 302 This is only a primative "parallel" random number generator, it should NOT 303 be used for sophisticated parallel Monte Carlo methods since it will very likely 304 not have the correct statistics across processors. You can provide your own 305 parallel generator using PetscRandomRegister(); 306 307 If you create a PetscRandom() using PETSC_COMM_SELF on several processors then 308 the SAME random numbers will be generated on all those processors. Use PETSC_COMM_WORLD 309 or the appropriate parallel communicator to eliminate this issue. 310 311 Use VecSetRandom() to set the elements of a vector to random numbers. 312 313 Example of Usage: 314 .vb 315 PetscRandomCreate(PETSC_COMM_SELF,&r); 316 PetscRandomSetType(r,PETSCRAND48); 317 PetscRandomGetValue(r,&value1); 318 PetscRandomGetValueReal(r,&value2); 319 PetscRandomDestroy(&r); 320 .ve 321 322 Concepts: random numbers^creating 323 324 .seealso: PetscRandomSetType(), PetscRandomGetValue(), PetscRandomGetValueReal(), PetscRandomSetInterval(), 325 PetscRandomDestroy(), VecSetRandom(), PetscRandomType 326 @*/ 327 328 PetscErrorCode PetscRandomCreate(MPI_Comm comm,PetscRandom *r) 329 { 330 PetscRandom rr; 331 PetscErrorCode ierr; 332 PetscMPIInt rank; 333 334 PetscFunctionBegin; 335 PetscValidPointer(r,3); 336 *r = NULL; 337 ierr = PetscRandomInitializePackage();CHKERRQ(ierr); 338 339 ierr = PetscHeaderCreate(rr,PETSC_RANDOM_CLASSID,"PetscRandom","Random number generator","Sys",comm,PetscRandomDestroy,PetscRandomView);CHKERRQ(ierr); 340 341 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 342 343 rr->data = NULL; 344 rr->low = 0.0; 345 rr->width = 1.0; 346 rr->iset = PETSC_FALSE; 347 rr->seed = 0x12345678 + 76543*rank; 348 ierr = PetscRandomSetType(rr,PETSCRANDER48);CHKERRQ(ierr); 349 *r = rr; 350 PetscFunctionReturn(0); 351 } 352 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