Actual source code: randomc.c

petsc-3.3-p7 2013-05-11
  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:

  7:     Numbers can be shuffled for use as random tuples

  9:     Multiple random number generators may be used

 11:     We are still not sure what interface we want here.  There should be
 12:     one to reinitialize and set the seed.
 13:  */

 15: #include <../src/sys/random/randomimpl.h>                              /*I "petscsys.h" I*/
 16: #if defined (PETSC_HAVE_STDLIB_H)
 17: #include <stdlib.h>
 18: #endif

 20: /* Logging support */
 21: PetscClassId  PETSC_RANDOM_CLASSID;

 25: /*@
 26:    PetscRandomDestroy - Destroys a context that has been formed by 
 27:    PetscRandomCreate().

 29:    Collective on PetscRandom

 31:    Intput Parameter:
 32: .  r  - the random number generator context

 34:    Level: intermediate

 36: .seealso: PetscRandomGetValue(), PetscRandomCreate(), VecSetRandom()
 37: @*/
 38: PetscErrorCode  PetscRandomDestroy(PetscRandom *r)
 39: {
 42:   if (!*r) return(0);
 44:   if (--((PetscObject)(*r))->refct > 0) {*r = 0; return(0);}
 45:   PetscHeaderDestroy(r);
 46:   return(0);
 47: }


 52: /*@
 53:    PetscRandomGetSeed - Gets the random seed.

 55:    Not collective

 57:    Input Parameters:
 58: .  r - The random number generator context

 60:    Output Parameter:
 61: .  seed - The random seed

 63:    Level: intermediate

 65:    Concepts: random numbers^seed

 67: .seealso: PetscRandomCreate(), PetscRandomSetSeed(), PetscRandomSeed()
 68: @*/
 69: PetscErrorCode  PetscRandomGetSeed(PetscRandom r,unsigned long *seed)
 70: {
 73:   if (seed) {
 75:     *seed = r->seed;
 76:   }
 77:   return(0);
 78: }

 82: /*@
 83:    PetscRandomSetSeed - Sets the random seed. You MUST call PetscRandomSeed() after this call to have the new seed used.

 85:    Not collective

 87:    Input Parameters:
 88: +  r  - The random number generator context
 89: -  seed - The random seed

 91:    Level: intermediate

 93:    Usage:
 94:       PetscRandomSetSeed(r,a positive integer);
 95:       PetscRandomSeed(r);  PetscRandomGetValue() will now start with the new seed.

 97:       PetscRandomSeed(r) without a call to PetscRandomSetSeed() re-initializes
 98:         the seed. The random numbers generated will be the same as before.

100:    Concepts: random numbers^seed

102: .seealso: PetscRandomCreate(), PetscRandomGetSeed(), PetscRandomSeed()
103: @*/
104: PetscErrorCode  PetscRandomSetSeed(PetscRandom r,unsigned long seed)
105: {

110:   r->seed = seed;
111:   PetscInfo1(PETSC_NULL,"Setting seed to %d\n",(int)seed);
112:   return(0);
113: }

115: /* ------------------------------------------------------------------- */
118: /*
119:   PetscRandomSetTypeFromOptions_Private - Sets the type of random generator from user options. Defaults to type PETSCRAND48 or PETSCRAND.

121:   Collective on PetscRandom

123:   Input Parameter:
124: . rnd - The random number generator context

126:   Level: intermediate

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];

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:   }

149:   if (!PetscRandomRegisterAllCalled) {PetscRandomRegisterAll(PETSC_NULL);}
150:   PetscOptionsList("-random_type","PetscRandom type","PetscRandomSetType",PetscRandomList,defaultType,typeName,256,&opt);
151:   if (opt) {
152:     PetscRandomSetType(rnd, typeName);
153:   } else {
154:     PetscRandomSetType(rnd, defaultType);
155:   }
156:   return(0);
157: }

161: /*@
162:   PetscRandomSetFromOptions - Configures the random number generator from the options database.

164:   Collective on PetscRandom

166:   Input Parameter:
167: . rnd - The random number generator context

169:   Options Database:
170: .  -random_seed <integer> - provide a seed to the random number generater

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.

175:   Level: beginner

177: .keywords: PetscRandom, set, options, database
178: .seealso: PetscRandomCreate(), PetscRandomSetType()
179: @*/
180: PetscErrorCode  PetscRandomSetFromOptions(PetscRandom rnd)
181: {
183:   PetscBool      set;
184:   PetscInt       seed;


189:   PetscObjectOptionsBegin((PetscObject)rnd);

191:     /* Handle PetscRandom type options */
192:     PetscRandomSetTypeFromOptions_Private(rnd);

194:     /* Handle specific random generator's options */
195:     if (rnd->ops->setfromoptions) {
196:       (*rnd->ops->setfromoptions)(rnd);
197:     }
198:     PetscOptionsInt("-random_seed","Seed to use to generate random numbers","PetscRandomSetSeed",0,&seed,&set);
199:     if (set) {
200:       PetscRandomSetSeed(rnd,(unsigned long int)seed);
201:       PetscRandomSeed(rnd);
202:     }
203:   PetscOptionsEnd();
204:   PetscRandomViewFromOptions(rnd, ((PetscObject)rnd)->name);
205:   return(0);
206: }

210: /*@C
211:    PetscRandomView - Views a random number generator object. 

213:    Collective on PetscRandom

215:    Input Parameters:
216: +  rnd - The random number generator context
217: -  viewer - an optional visualization context

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. 

227:    You can change the format the vector is printed using the 
228:    option PetscViewerSetFormat().

230:    Level: beginner

232: .seealso:  PetscRealView(), PetscScalarView(), PetscIntView()
233: @*/
234: PetscErrorCode  PetscRandomView(PetscRandom rnd,PetscViewer viewer)
235: {
236:   PetscErrorCode    ierr;
237:   PetscBool         iascii;

242:   if (!viewer) {
243:     PetscViewerASCIIGetStdout(((PetscObject)rnd)->comm,&viewer);
244:   }
247:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
248:   if (iascii) {
249:     PetscMPIInt rank;
250:     MPI_Comm_rank(((PetscObject)rnd)->comm,&rank);
251:     PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);
252:     PetscViewerASCIISynchronizedPrintf(viewer,"[%D] Random type %s, seed %D\n",rank,((PetscObject)rnd)->type_name,rnd->seed);
253:     PetscViewerFlush(viewer);
254:     PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);
255:   } else {
256:     const char *tname;
257:     PetscObjectGetName((PetscObject)viewer,&tname);
258:     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for this object",tname);
259:   }
260:   return(0);
261: }

263: #undef  __FUNCT__
265: /*@
266:   PetscRandomViewFromOptions - This function visualizes the type and the seed of the generated random numbers based upon user options.

268:   Collective on PetscRandom

270:   Input Parameters:
271: . rnd   - The random number generator context
272: . title - The title

274:   Level: intermediate

276: .keywords: PetscRandom, view, options, database
277: .seealso: PetscRandomSetFromOptions()
278: @*/
279: PetscErrorCode  PetscRandomViewFromOptions(PetscRandom rnd, char *title)
280: {
281:   PetscBool      opt = PETSC_FALSE;
282:   PetscViewer    viewer;
283:   char           typeName[1024];
284:   char           fileName[PETSC_MAX_PATH_LEN];
285:   size_t         len;
286: 

290:   PetscOptionsGetBool(((PetscObject)rnd)->prefix, "-random_view", &opt,PETSC_NULL);
291:   if (opt) {
292:     PetscOptionsGetString(((PetscObject)rnd)->prefix, "-random_view", typeName, 1024, &opt);
293:     PetscStrlen(typeName, &len);
294:     if (len > 0) {
295:       PetscViewerCreate(((PetscObject)rnd)->comm, &viewer);
296:       PetscViewerSetType(viewer, typeName);
297:       PetscOptionsGetString(((PetscObject)rnd)->prefix, "-random_view_file", fileName, 1024, &opt);
298:       if (opt) {
299:         PetscViewerFileSetName(viewer, fileName);
300:       } else {
301:         PetscViewerFileSetName(viewer, ((PetscObject)rnd)->name);
302:       }
303:       PetscRandomView(rnd, viewer);
304:       PetscViewerFlush(viewer);
305:       PetscViewerDestroy(&viewer);
306:     } else {
307:       PetscViewer viewer;
308:       PetscViewerASCIIGetStdout(((PetscObject)rnd)->comm,&viewer);
309:       PetscRandomView(rnd, viewer);
310:     }
311:   }
312:   return(0);
313: }

315: #if defined(PETSC_HAVE_AMS)
318: static PetscErrorCode PetscRandomPublish_Petsc(PetscObject obj)
319: {
320:   PetscRandom    rand = (PetscRandom) obj;

324:   AMS_Memory_add_field(obj->amem,"Low",&rand->low,1,AMS_DOUBLE,AMS_READ,AMS_COMMON,AMS_REDUCT_UNDEF);
325:   return(0);
326: }
327: #endif

331: /*@
332:    PetscRandomCreate - Creates a context for generating random numbers,
333:    and initializes the random-number generator.

335:    Collective on MPI_Comm

337:    Input Parameters:
338: +  comm - MPI communicator

340:    Output Parameter:
341: .  r  - the random number generator context

343:    Level: intermediate

345:    Notes:
346:    The random type has to be set by PetscRandomSetType().

348:    This is only a primative "parallel" random number generator, it should NOT
349:    be used for sophisticated parallel Monte Carlo methods since it will very likely
350:    not have the correct statistics across processors. You can provide your own
351:    parallel generator using PetscRandomRegister();

353:    If you create a PetscRandom() using PETSC_COMM_SELF on several processors then
354:    the SAME random numbers will be generated on all those processors. Use PETSC_COMM_WORLD
355:    or the appropriate parallel communicator to eliminate this issue.

357:    Use VecSetRandom() to set the elements of a vector to random numbers.

359:    Example of Usage:
360: .vb
361:       PetscRandomCreate(PETSC_COMM_SELF,&r);
362:       PetscRandomSetType(r,PETSCRAND48);
363:       PetscRandomGetValue(r,&value1);
364:       PetscRandomGetValueReal(r,&value2);
365:       PetscRandomDestroy(&r);
366: .ve

368:    Concepts: random numbers^creating

370: .seealso: PetscRandomSetType(), PetscRandomGetValue(), PetscRandomGetValueReal(), PetscRandomSetInterval(), 
371:           PetscRandomDestroy(), VecSetRandom(), PetscRandomType
372: @*/

374: PetscErrorCode  PetscRandomCreate(MPI_Comm comm,PetscRandom *r)
375: {
376:   PetscRandom    rr;
378:   PetscMPIInt    rank;

382:   *r = PETSC_NULL;
383: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
384:   PetscRandomInitializePackage(PETSC_NULL);
385: #endif

387:   PetscHeaderCreate(rr,_p_PetscRandom,struct _PetscRandomOps,PETSC_RANDOM_CLASSID,-1,"PetscRandom","Random number generator","Sys",comm,PetscRandomDestroy,0);

389:   MPI_Comm_rank(comm,&rank);
390:   rr->data  = PETSC_NULL;
391:   rr->low   = 0.0;
392:   rr->width = 1.0;
393:   rr->iset  = PETSC_FALSE;
394:   rr->seed  = 0x12345678 + 76543*rank;
395: #if defined(PETSC_HAVE_AMS)
396:   ((PetscObject)rr)->bops->publish = PetscRandomPublish_Petsc;
397: #endif
398:   *r = rr;
399:   return(0);
400: }

404: /*@
405:    PetscRandomSeed - Seed the generator.

407:    Not collective

409:    Input Parameters:
410: .  r - The random number generator context

412:    Level: intermediate

414:    Usage:
415:       PetscRandomSetSeed(r,a positive integer);
416:       PetscRandomSeed(r);  PetscRandomGetValue() will now start with the new seed.

418:       PetscRandomSeed(r) without a call to PetscRandomSetSeed() re-initializes
419:         the seed. The random numbers generated will be the same as before.

421:    Concepts: random numbers^seed

423: .seealso: PetscRandomCreate(), PetscRandomGetSeed(), PetscRandomSetSeed()
424: @*/
425: PetscErrorCode  PetscRandomSeed(PetscRandom r)
426: {


433:   (*r->ops->seed)(r);
434:   PetscObjectStateIncrease((PetscObject)r);
435:   return(0);
436: }