Actual source code: randomc.c

petsc-3.11.4 2019-09-28
Report Typos and Errors

  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>
 16:  #include <petscviewer.h>

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

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

 25:    Collective on PetscRandom

 27:    Intput Parameter:
 28: .  r  - the random number generator context

 30:    Level: intermediate

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

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


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

 53:    Not collective

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

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

 61:    Level: intermediate

 63:    Concepts: random numbers^seed

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

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

 81:    Not collective

 83:    Input Parameters:
 84: +  r  - The random number generator context
 85: -  seed - The random seed

 87:    Level: intermediate

 89:    Usage:
 90:       PetscRandomSetSeed(r,a positive integer);
 91:       PetscRandomSeed(r);  PetscRandomGetValue() will now start with the new seed.

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

 96:    Concepts: random numbers^seed

 98: .seealso: PetscRandomCreate(), PetscRandomGetSeed(), PetscRandomSeed()
 99: @*/
100: PetscErrorCode  PetscRandomSetSeed(PetscRandom r,unsigned long seed)
101: {

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

111: /* ------------------------------------------------------------------- */
112: /*
113:   PetscRandomSetTypeFromOptions_Private - Sets the type of random generator from user options. Defaults to type PETSCRAND48 or PETSCRAND.

115:   Collective on PetscRandom

117:   Input Parameter:
118: . rnd - The random number generator context

120:   Level: intermediate

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

133:   if (((PetscObject)rnd)->type_name) {
134:     defaultType = ((PetscObject)rnd)->type_name;
135:   } else {
136:     defaultType = PETSCRANDER48;
137:   }

139:   PetscRandomRegisterAll();
140:   PetscOptionsFList("-random_type","PetscRandom type","PetscRandomSetType",PetscRandomList,defaultType,typeName,256,&opt);
141:   if (opt) {
142:     PetscRandomSetType(rnd, typeName);
143:   } else {
144:     PetscRandomSetType(rnd, defaultType);
145:   }
146:   return(0);
147: }

149: /*@
150:   PetscRandomSetFromOptions - Configures the random number generator from the options database.

152:   Collective on PetscRandom

154:   Input Parameter:
155: . rnd - The random number generator context

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

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.

166:   Level: beginner

168: .keywords: PetscRandom, set, options, database
169: .seealso: PetscRandomCreate(), PetscRandomSetType()
170: @*/
171: PetscErrorCode  PetscRandomSetFromOptions(PetscRandom rnd)
172: {
174:   PetscBool      set,noimaginary = PETSC_FALSE;
175:   PetscInt       seed;


180:   PetscObjectOptionsBegin((PetscObject)rnd);

182:   /* Handle PetscRandom type options */
183:   PetscRandomSetTypeFromOptions_Private(PetscOptionsObject,rnd);

185:   /* Handle specific random generator's options */
186:   if (rnd->ops->setfromoptions) {
187:     (*rnd->ops->setfromoptions)(PetscOptionsObject,rnd);
188:   }
189:   PetscOptionsInt("-random_seed","Seed to use to generate random numbers","PetscRandomSetSeed",0,&seed,&set);
190:   if (set) {
191:     PetscRandomSetSeed(rnd,(unsigned long int)seed);
192:     PetscRandomSeed(rnd);
193:   }
194:   PetscOptionsBool("-random_no_imaginary_part","The imaginary part of the random number will be zero","PetscRandomSetInterval",noimaginary,&noimaginary,&set);
195: #if defined(PETSC_HAVE_COMPLEX)
196:   if (set) {
197:     if (noimaginary) {
198:       PetscScalar low,high;
199:       PetscRandomGetInterval(rnd,&low,&high);
200:       low  = low - PetscImaginaryPart(low);
201:       high = high - PetscImaginaryPart(high);
202:       PetscRandomSetInterval(rnd,low,high);
203:     }
204:   }
205: #endif
206:   PetscOptionsEnd();
207:   PetscRandomViewFromOptions(rnd,NULL, "-random_view");
208:   return(0);
209: }

211: #if defined(PETSC_HAVE_SAWS)
212:  #include <petscviewersaws.h>
213: #endif
214: /*@C
215:    PetscRandomView - Views a random number generator object.

217:    Collective on PetscRandom

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

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.

231:    You can change the format the vector is printed using the
232:    option PetscViewerPushFormat().

234:    Level: beginner

236: .seealso:  PetscRealView(), PetscScalarView(), PetscIntView()
237: @*/
238: PetscErrorCode  PetscRandomView(PetscRandom rnd,PetscViewer viewer)
239: {
241:   PetscBool      iascii;
242: #if defined(PETSC_HAVE_SAWS)
243:   PetscBool      issaws;
244: #endif

249:   if (!viewer) {
250:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)rnd),&viewer);
251:   }
254:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
255: #if defined(PETSC_HAVE_SAWS)
256:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws);
257: #endif
258:   if (iascii) {
259:     PetscMPIInt rank;
260:     PetscObjectPrintClassNamePrefixType((PetscObject)rnd,viewer);
261:     MPI_Comm_rank(PetscObjectComm((PetscObject)rnd),&rank);
262:     PetscViewerASCIIPushSynchronized(viewer);
263:     PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Random type %s, seed %lu\n",rank,((PetscObject)rnd)->type_name,rnd->seed);
264:     PetscViewerFlush(viewer);
265:     PetscViewerASCIIPopSynchronized(viewer);
266: #if defined(PETSC_HAVE_SAWS)
267:   } else if (issaws) {
268:     PetscMPIInt rank;
269:     const char  *name;

271:     PetscObjectGetName((PetscObject)rnd,&name);
272:     MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
273:     if (!((PetscObject)rnd)->amsmem && !rank) {
274:       char       dir[1024];

276:       PetscObjectViewSAWs((PetscObject)rnd,viewer);
277:       PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/Low",name);
278:       PetscStackCallSAWs(SAWs_Register,(dir,&rnd->low,1,SAWs_READ,SAWs_DOUBLE));
279:     }
280: #endif
281:   }
282:   return(0);
283: }

285: /*@
286:    PetscRandomCreate - Creates a context for generating random numbers,
287:    and initializes the random-number generator.

289:    Collective on MPI_Comm

291:    Input Parameters:
292: .  comm - MPI communicator

294:    Output Parameter:
295: .  r  - the random number generator context

297:    Level: intermediate

299:    Notes:
300:    The random type has to be set by PetscRandomSetType().

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();

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.

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

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

322:    Concepts: random numbers^creating

324: .seealso: PetscRandomSetType(), PetscRandomGetValue(), PetscRandomGetValueReal(), PetscRandomSetInterval(),
325:           PetscRandomDestroy(), VecSetRandom(), PetscRandomType
326: @*/

328: PetscErrorCode  PetscRandomCreate(MPI_Comm comm,PetscRandom *r)
329: {
330:   PetscRandom    rr;
332:   PetscMPIInt    rank;

336:   *r = NULL;
337:   PetscRandomInitializePackage();

339:   PetscHeaderCreate(rr,PETSC_RANDOM_CLASSID,"PetscRandom","Random number generator","Sys",comm,PetscRandomDestroy,PetscRandomView);

341:   MPI_Comm_rank(comm,&rank);

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:   PetscRandomSetType(rr,PETSCRANDER48);
349:   *r = rr;
350:   return(0);
351: }

353: /*@
354:    PetscRandomSeed - Seed the generator.

356:    Not collective

358:    Input Parameters:
359: .  r - The random number generator context

361:    Level: intermediate

363:    Usage:
364:       PetscRandomSetSeed(r,a positive integer);
365:       PetscRandomSeed(r);  PetscRandomGetValue() will now start with the new seed.

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

370:    Concepts: random numbers^seed

372: .seealso: PetscRandomCreate(), PetscRandomGetSeed(), PetscRandomSetSeed()
373: @*/
374: PetscErrorCode  PetscRandomSeed(PetscRandom r)
375: {


382:   (*r->ops->seed)(r);
383:   PetscObjectStateIncrease((PetscObject)r);
384:   return(0);
385: }