Actual source code: random.c
1: #define PETSC_DLL
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
16: #if defined (PETSC_HAVE_STDLIB_H)
17: #include <stdlib.h>
18: #endif
20: /* Logging support */
21: PetscCookie PETSC_RANDOM_COOKIE = 0;
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: {
43: if (--((PetscObject)r)->refct > 0) return(0);
44: PetscHeaderDestroy(r);
45: return(0);
46: }
50: /*@C
51: PetscRandomGetInterval - Gets the interval over which the random numbers
52: will be randomly distributed. By default, this interval is [0,1).
54: Not collective
56: Input Parameters:
57: . r - the random number generator context
59: Output Parameters:
60: + low - The lower bound of the interval
61: - high - The upper bound of the interval
63: Level: intermediate
65: Concepts: random numbers^range
67: .seealso: PetscRandomCreate(), PetscRandomSetInterval()
68: @*/
69: PetscErrorCode PetscRandomGetInterval(PetscRandom r,PetscScalar *low,PetscScalar *high)
70: {
73: if (low) {
75: *low = r->low;
76: }
77: if (high) {
79: *high = r->low+r->width;
80: }
81: return(0);
82: }
86: /*@C
87: PetscRandomSetInterval - Sets the interval over which the random numbers
88: will be randomly distributed. By default, this interval is [0,1).
90: Not collective
92: Input Parameters:
93: + r - the random number generator context
94: . low - The lower bound of the interval
95: - high - The upper bound of the interval
97: Level: intermediate
99: Concepts: random numbers^range
101: .seealso: PetscRandomCreate(), PetscRandomGetInterval()
102: @*/
103: PetscErrorCode PetscRandomSetInterval(PetscRandom r,PetscScalar low,PetscScalar high)
104: {
107: #if defined(PETSC_USE_COMPLEX)
108: if (PetscRealPart(low) >= PetscRealPart(high)) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"only low < high");
109: if (PetscImaginaryPart(low) >= PetscImaginaryPart(high)) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"only low < high");
110: #else
111: if (low >= high) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"only low < high: Instead %G %G",low,high);
112: #endif
113: r->low = low;
114: r->width = high-low;
115: r->iset = PETSC_TRUE;
116: return(0);
117: }
121: /*@C
122: PetscRandomGetSeed - Gets the random seed.
124: Not collective
126: Input Parameters:
127: . r - The random number generator context
129: Output Parameter:
130: . seed - The random seed
132: Level: intermediate
134: Concepts: random numbers^seed
136: .seealso: PetscRandomCreate(), PetscRandomSetSeed(), PetscRandomSeed()
137: @*/
138: PetscErrorCode PetscRandomGetSeed(PetscRandom r,unsigned long *seed)
139: {
142: if (seed) {
144: *seed = r->seed;
145: }
146: return(0);
147: }
151: /*@C
152: PetscRandomSetSeed - Sets the random seed.
154: Not collective
156: Input Parameters:
157: + r - The random number generator context
158: - seed - The random seed
160: Level: intermediate
162: Usage:
163: PetscRandomSetSeed(r,a positive integer);
164: PetscRandomSeed(r); PetscRandomGetValue() will now start with the new seed.
166: PetscRandomSeed(r) without a call to PetscRandomSetSeed() re-initializes
167: the seed. The random numbers generated will be the same as before.
169: Concepts: random numbers^seed
171: .seealso: PetscRandomCreate(), PetscRandomGetSeed(), PetscRandomSeed()
172: @*/
173: PetscErrorCode PetscRandomSetSeed(PetscRandom r,unsigned long seed)
174: {
177: r->seed = seed;
178: return(0);
179: }
181: /* ------------------------------------------------------------------- */
184: /*
185: PetscRandomSetTypeFromOptions_Private - Sets the type of random generator from user options. Defaults to type PETSCRAND48 or PETSCRAND.
187: Collective on PetscRandom
189: Input Parameter:
190: . rnd - The random number generator context
192: Level: intermediate
194: .keywords: PetscRandom, set, options, database, type
195: .seealso: PetscRandomSetFromOptions(), PetscRandomSetType()
196: */
197: static PetscErrorCode PetscRandomSetTypeFromOptions_Private(PetscRandom rnd)
198: {
199: PetscTruth opt;
200: const char *defaultType;
201: char typeName[256];
205: if (((PetscObject)rnd)->type_name) {
206: defaultType = ((PetscObject)rnd)->type_name;
207: } else {
208: #if defined(PETSC_HAVE_DRAND48)
209: defaultType = PETSCRAND48;
210: #elif defined(PETSC_HAVE_RAND)
211: defaultType = PETSCRAND;
212: #endif
213: }
215: if (!PetscRandomRegisterAllCalled) {
216: PetscRandomRegisterAll(PETSC_NULL);
217: }
218: PetscOptionsList("-random_type","PetscRandom type","PetscRandomSetType",PetscRandomList,defaultType,typeName,256,&opt);
219: if (opt) {
220: PetscRandomSetType(rnd, typeName);
221: } else {
222: PetscRandomSetType(rnd, defaultType);
223: }
224: return(0);
225: }
229: /*@
230: PetscRandomSetFromOptions - Configures the random number generator from the options database.
232: Collective on PetscRandom
234: Input Parameter:
235: . rnd - The random number generator context
237: Notes: To see all options, run your program with the -help option, or consult the users manual.
238: Must be called after PetscRandomCreate() but before the rnd is used.
240: Level: beginner
242: .keywords: PetscRandom, set, options, database
243: .seealso: PetscRandomCreate(), PetscRandomSetType()
244: @*/
245: PetscErrorCode PetscRandomSetFromOptions(PetscRandom rnd)
246: {
252: PetscOptionsBegin(((PetscObject)rnd)->comm, ((PetscObject)rnd)->prefix, "PetscRandom options", "PetscRandom");
254: /* Handle PetscRandom type options */
255: PetscRandomSetTypeFromOptions_Private(rnd);
257: /* Handle specific random generator's options */
258: if (rnd->ops->setfromoptions) {
259: (*rnd->ops->setfromoptions)(rnd);
260: }
261: PetscOptionsEnd();
262: PetscRandomViewFromOptions(rnd, ((PetscObject)rnd)->name);
263: return(0);
264: }
268: /*@C
269: PetscRandomView - Views a random number generator object.
271: Collective on PetscRandom
273: Input Parameters:
274: + rnd - The random number generator context
275: - viewer - an optional visualization context
277: Notes:
278: The available visualization contexts include
279: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
280: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
281: output where only the first processor opens
282: the file. All other processors send their
283: data to the first processor to print.
285: You can change the format the vector is printed using the
286: option PetscViewerSetFormat().
288: Level: beginner
290: .seealso: PetscRealView(), PetscScalarView(), PetscIntView()
291: @*/
292: PetscErrorCode PetscRandomView(PetscRandom rnd,PetscViewer viewer)
293: {
294: PetscErrorCode ierr;
295: PetscTruth iascii;
300: if (!viewer) {
301: PetscViewerASCIIGetStdout(((PetscObject)rnd)->comm,&viewer);
302: }
305: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
306: if (iascii) {
307: PetscMPIInt rank;
308: MPI_Comm_rank(((PetscObject)rnd)->comm,&rank);
309: PetscViewerASCIISynchronizedPrintf(viewer,"[%D] Random type %s, seed %D\n",rank,((PetscObject)rnd)->type_name,rnd->seed);
310: PetscViewerFlush(viewer);
311: } else {
312: const char *tname;
313: PetscObjectGetName((PetscObject)viewer,&tname);
314: SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for this object",tname);
315: }
316: return(0);
317: }
319: #undef __FUNCT__
321: /*@
322: PetscRandomViewFromOptions - This function visualizes the type and the seed of the generated random numbers based upon user options.
324: Collective on PetscRandom
326: Input Parameters:
327: . rnd - The random number generator context
328: . title - The title
330: Level: intermediate
332: .keywords: PetscRandom, view, options, database
333: .seealso: PetscRandomSetFromOptions()
334: @*/
335: PetscErrorCode PetscRandomViewFromOptions(PetscRandom rnd, char *title)
336: {
337: PetscTruth opt;
338: PetscViewer viewer;
339: char typeName[1024];
340: char fileName[PETSC_MAX_PATH_LEN];
341: size_t len;
342:
346: PetscOptionsHasName(((PetscObject)rnd)->prefix, "-random_view", &opt);
347: if (opt) {
348: PetscOptionsGetString(((PetscObject)rnd)->prefix, "-random_view", typeName, 1024, &opt);
349: PetscStrlen(typeName, &len);
350: if (len > 0) {
351: PetscViewerCreate(((PetscObject)rnd)->comm, &viewer);
352: PetscViewerSetType(viewer, typeName);
353: PetscOptionsGetString(((PetscObject)rnd)->prefix, "-random_view_file", fileName, 1024, &opt);
354: if (opt) {
355: PetscViewerFileSetName(viewer, fileName);
356: } else {
357: PetscViewerFileSetName(viewer, ((PetscObject)rnd)->name);
358: }
359: PetscRandomView(rnd, viewer);
360: PetscViewerFlush(viewer);
361: PetscViewerDestroy(viewer);
362: } else {
363: PetscViewer viewer;
364: PetscViewerASCIIGetStdout(((PetscObject)rnd)->comm,&viewer);
365: PetscRandomView(rnd, viewer);
366: }
367: }
368: return(0);
369: }
374: /*@
375: PetscRandomCreate - Creates a context for generating random numbers,
376: and initializes the random-number generator.
378: Collective on MPI_Comm
380: Input Parameters:
381: + comm - MPI communicator
383: Output Parameter:
384: . r - the random number generator context
386: Level: intermediate
388: Notes:
389: The random type has to be set by PetscRandomSetType().
391: This is only a primative "parallel" random number generator, it should NOT
392: be used for sophisticated parallel Monte Carlo methods since it will very likely
393: not have the correct statistics across processors. You can provide your own
394: parallel generator using PetscRandomRegister();
396: If you create a PetscRandom() using PETSC_COMM_SELF on several processors then
397: the SAME random numbers will be generated on all those processors. Use PETSC_COMM_WORLD
398: or the appropriate parallel communicator to eliminate this issue.
400: Use VecSetRandom() to set the elements of a vector to random numbers.
402: Example of Usage:
403: .vb
404: PetscRandomCreate(PETSC_COMM_SELF,&r);
405: PetscRandomSetType(r,PETSCRAND48);
406: PetscRandomGetValue(r,&value1);
407: PetscRandomGetValueReal(r,&value2);
408: PetscRandomGetValueImaginary(r,&value3);
409: PetscRandomDestroy(r);
410: .ve
412: Concepts: random numbers^creating
414: .seealso: PetscRandomSetType(), PetscRandomGetValue(), PetscRandomGetValueReal(), PetscRandomGetValueImaginary(), PetscRandomSetInterval(),
415: PetscRandomDestroy(), VecSetRandom(), PetscRandomType
416: @*/
418: PetscErrorCode PetscRandomCreate(MPI_Comm comm,PetscRandom *r)
419: {
420: PetscRandom rr;
422: PetscMPIInt rank;
426: *r = PETSC_NULL;
427: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
428: PetscRandomInitializePackage(PETSC_NULL);
429: #endif
431: PetscHeaderCreate(rr,_p_PetscRandom,struct _PetscRandomOps,PETSC_RANDOM_COOKIE,-1,"PetscRandom",comm,PetscRandomDestroy,0);
433: MPI_Comm_rank(comm,&rank);
434: rr->data = PETSC_NULL;
435: rr->low = 0.0;
436: rr->width = 1.0;
437: rr->iset = PETSC_FALSE;
438: rr->seed = 0x12345678 + 76543*rank;
439: *r = rr;
440: return(0);
441: }
445: /*@C
446: PetscRandomSeed - Seed the generator.
448: Not collective
450: Input Parameters:
451: . r - The random number generator context
453: Level: intermediate
455: Usage:
456: PetscRandomSetSeed(r,a positive integer);
457: PetscRandomSeed(r); PetscRandomGetValue() will now start with the new seed.
459: PetscRandomSeed(r) without a call to PetscRandomSetSeed() re-initializes
460: the seed. The random numbers generated will be the same as before.
462: Concepts: random numbers^seed
464: .seealso: PetscRandomCreate(), PetscRandomGetSeed(), PetscRandomSetSeed()
465: @*/
466: PetscErrorCode PetscRandomSeed(PetscRandom r)
467: {
474: (*r->ops->seed)(r);
475: PetscObjectStateIncrease((PetscObject)r);
476: return(0);
477: }
481: /*@
482: PetscRandomGetValue - Generates a random number. Call this after first calling
483: PetscRandomCreate().
485: Not Collective
487: Intput Parameter:
488: . r - the random number generator context
490: Output Parameter:
491: . val - the value
493: Level: intermediate
495: Notes:
496: Use VecSetRandom() to set the elements of a vector to random numbers.
498: Example of Usage:
499: .vb
500: PetscRandomCreate(PETSC_COMM_WORLD,&r);
501: PetscRandomGetValue(r,&value1);
502: PetscRandomGetValue(r,&value2);
503: PetscRandomGetValue(r,&value3);
504: PetscRandomDestroy(r);
505: .ve
507: Concepts: random numbers^getting
509: .seealso: PetscRandomCreate(), PetscRandomDestroy(), VecSetRandom()
510: @*/
511: PetscErrorCode PetscRandomGetValue(PetscRandom r,PetscScalar *val)
512: {
520: (*r->ops->getvalue)(r,val);
521: PetscObjectStateIncrease((PetscObject)r);
522: return(0);
523: }
527: /*@
528: PetscRandomGetValueReal - Generates a random number. Call this after first calling
529: PetscRandomCreate().
531: Not Collective
533: Intput Parameter:
534: . r - the random number generator context
536: Output Parameter:
537: . val - the value
539: Level: intermediate
541: Notes:
542: Use VecSetRandom() to set the elements of a vector to random numbers.
544: Example of Usage:
545: .vb
546: PetscRandomCreate(PETSC_COMM_WORLD,&r);
547: PetscRandomGetValueReal(r,&value1);
548: PetscRandomGetValueReal(r,&value2);
549: PetscRandomGetValueReal(r,&value3);
550: PetscRandomDestroy(r);
551: .ve
553: Concepts: random numbers^getting
555: .seealso: PetscRandomCreate(), PetscRandomDestroy(), VecSetRandom()
556: @*/
557: PetscErrorCode PetscRandomGetValueReal(PetscRandom r,PetscReal *val)
558: {
566: (*r->ops->getvaluereal)(r,val);
567: PetscObjectStateIncrease((PetscObject)r);
568: return(0);
569: }
573: /*@
574: PetscRandomGetValueImaginary - Generates a random number. Call this after first calling
575: PetscRandomCreate().
577: Not Collective
579: Intput Parameter:
580: . r - the random number generator context
582: Output Parameter:
583: . val - the value
585: Options Database Keys:
586: + -random_type rand48
587: . -random_type rand
588: - -random_type sprng, uses SPRNG package
590: Level: intermediate
592: Notes:
593: Use VecSetRandom() to set the elements of a vector to random numbers.
595: Example of Usage:
596: .vb
597: PetscRandomCreate(PETSC_COMM_WORLD,&r);
598: PetscRandomGetValueImaginary(r,&value1);
599: PetscRandomGetValueImaginary(r,&value2);
600: PetscRandomGetValueImaginary(r,&value3);
601: PetscRandomDestroy(r);
602: .ve
604: Concepts: random numbers^getting
606: .seealso: PetscRandomCreate(), PetscRandomDestroy(), VecSetRandom()
607: @*/
608: PetscErrorCode PetscRandomGetValueImaginary(PetscRandom r,PetscScalar *val)
609: {
617: (*r->ops->getvalueimaginary)(r,val);
618: PetscObjectStateIncrease((PetscObject)r);
619: return(0);
620: }