Actual source code: randomc.c

petsc-3.4.5 2014-06-29
  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/classes/random/randomimpl.h>                              /*I "petscsys.h" I*/
 16: #include <petscviewer.h>

 18: /* Logging support */
 19: PetscClassId PETSC_RANDOM_CLASSID;

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

 27:    Collective on PetscRandom

 29:    Intput Parameter:
 30: .  r  - the random number generator context

 32:    Level: intermediate

 34: .seealso: PetscRandomGetValue(), PetscRandomCreate(), VecSetRandom()
 35: @*/
 36: PetscErrorCode  PetscRandomDestroy(PetscRandom *r)
 37: {

 41:   if (!*r) return(0);
 43:   if (--((PetscObject)(*r))->refct > 0) {*r = 0; return(0);}
 44:   PetscHeaderDestroy(r);
 45:   return(0);
 46: }


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

 54:    Not collective

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

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

 62:    Level: intermediate

 64:    Concepts: random numbers^seed

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

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

 84:    Not collective

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

 90:    Level: intermediate

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

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

 99:    Concepts: random numbers^seed

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

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

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

120:   Collective on PetscRandom

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

125:   Level: intermediate

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

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

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

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

163:   Collective on PetscRandom

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

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

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.

174:   Level: beginner

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


188:   PetscObjectOptionsBegin((PetscObject)rnd);

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

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

207: #if defined(PETSC_HAVE_AMS)
208: #include <petscviewerams.h>
209: #endif
212: /*@C
213:    PetscRandomView - Views a random number generator object.

215:    Collective on PetscRandom

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

221:    Notes:
222:    The available visualization contexts include
223: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
224: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
225:          output where only the first processor opens
226:          the file.  All other processors send their
227:          data to the first processor to print.

229:    You can change the format the vector is printed using the
230:    option PetscViewerSetFormat().

232:    Level: beginner

234: .seealso:  PetscRealView(), PetscScalarView(), PetscIntView()
235: @*/
236: PetscErrorCode  PetscRandomView(PetscRandom rnd,PetscViewer viewer)
237: {
239:   PetscBool      iascii;
240: #if defined(PETSC_HAVE_AMS)
241:   PetscBool      isams;
242: #endif

247:   if (!viewer) {
248:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)rnd),&viewer);
249:   }
252:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
253: #if defined(PETSC_HAVE_AMS)
254:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERAMS,&isams);
255: #endif
256:   if (iascii) {
257:     PetscMPIInt rank;
258:     MPI_Comm_rank(PetscObjectComm((PetscObject)rnd),&rank);
259:     PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);
260:     PetscViewerASCIISynchronizedPrintf(viewer,"[%D] Random type %s, seed %D\n",rank,((PetscObject)rnd)->type_name,rnd->seed);
261:     PetscViewerFlush(viewer);
262:     PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);
263: #if defined(PETSC_HAVE_AMS)
264:   } else if (isams) {
265:     if (((PetscObject)rnd)->amsmem == -1) {
266:       PetscObjectViewAMS((PetscObject)rnd,viewer);
267:       PetscStackCallAMS(AMS_Memory_add_field,(((PetscObject)rnd)->amsmem,"Low",&rnd->low,1,AMS_DOUBLE,AMS_READ,AMS_COMMON,AMS_REDUCT_UNDEF));
268:     }
269: #endif
270:   }
271:   return(0);
272: }

274: #undef  __FUNCT__
276: /*
277:   PetscRandomViewFromOptions - This function visualizes the type and the seed of the generated random numbers based upon user options.

279:   Collective on PetscRandom

281:   Input Parameters:
282: + rnd   - The random number generator context
283: . prefix - prefix to use for viewing, or NULL to use prefix of 'rnd'
284: - optionname - option to activate viewing

286:   Level: intermediate

288: .keywords: PetscRandom, view, options, database
289: .seealso: PetscRandomSetFromOptions()
290: */
291: PetscErrorCode  PetscRandomViewFromOptions(PetscRandom rnd, const char prefix[], const char optionname[])
292: {
293:   PetscBool         flg;
294:   PetscViewer       viewer;
295:   PetscErrorCode    ierr;
296:   PetscViewerFormat format;

299:   if (prefix) {
300:     PetscOptionsGetViewer(PetscObjectComm((PetscObject)rnd),prefix,optionname,&viewer,&format,&flg);
301:   } else {
302:     PetscOptionsGetViewer(PetscObjectComm((PetscObject)rnd),((PetscObject)rnd)->prefix,optionname,&viewer,&format,&flg);
303:   }
304:   if (flg) {
305:     PetscViewerPushFormat(viewer,format);
306:     PetscRandomView(rnd,viewer);
307:     PetscViewerPopFormat(viewer);
308:     PetscViewerDestroy(&viewer);
309:   }
310:   return(0);
311: }

315: /*@
316:    PetscRandomCreate - Creates a context for generating random numbers,
317:    and initializes the random-number generator.

319:    Collective on MPI_Comm

321:    Input Parameters:
322: +  comm - MPI communicator

324:    Output Parameter:
325: .  r  - the random number generator context

327:    Level: intermediate

329:    Notes:
330:    The random type has to be set by PetscRandomSetType().

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

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

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

343:    Example of Usage:
344: .vb
345:       PetscRandomCreate(PETSC_COMM_SELF,&r);
346:       PetscRandomSetType(r,PETSCRAND48);
347:       PetscRandomGetValue(r,&value1);
348:       PetscRandomGetValueReal(r,&value2);
349:       PetscRandomDestroy(&r);
350: .ve

352:    Concepts: random numbers^creating

354: .seealso: PetscRandomSetType(), PetscRandomGetValue(), PetscRandomGetValueReal(), PetscRandomSetInterval(),
355:           PetscRandomDestroy(), VecSetRandom(), PetscRandomType
356: @*/

358: PetscErrorCode  PetscRandomCreate(MPI_Comm comm,PetscRandom *r)
359: {
360:   PetscRandom    rr;
362:   PetscMPIInt    rank;

366:   *r = NULL;
367: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
368:   PetscRandomInitializePackage();
369: #endif

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

373:   MPI_Comm_rank(comm,&rank);

375:   rr->data  = NULL;
376:   rr->low   = 0.0;
377:   rr->width = 1.0;
378:   rr->iset  = PETSC_FALSE;
379:   rr->seed  = 0x12345678 + 76543*rank;
380:   *r = rr;
381:   return(0);
382: }

386: /*@
387:    PetscRandomSeed - Seed the generator.

389:    Not collective

391:    Input Parameters:
392: .  r - The random number generator context

394:    Level: intermediate

396:    Usage:
397:       PetscRandomSetSeed(r,a positive integer);
398:       PetscRandomSeed(r);  PetscRandomGetValue() will now start with the new seed.

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

403:    Concepts: random numbers^seed

405: .seealso: PetscRandomCreate(), PetscRandomGetSeed(), PetscRandomSetSeed()
406: @*/
407: PetscErrorCode  PetscRandomSeed(PetscRandom r)
408: {


415:   (*r->ops->seed)(r);
416:   PetscObjectStateIncrease((PetscObject)r);
417:   return(0);
418: }