Actual source code: randomc.c
1: /*
2: This file contains routines for interfacing to random number generators.
3: This provides more than just an interface to some system random number
4: generator:
6: Numbers can be shuffled for use as random tuples
8: Multiple random number generators may be used
10: We are still not sure what interface we want here. There should be
11: one to reinitialize and set the seed.
12: */
14: #include <petsc/private/randomimpl.h>
15: #include <petscviewer.h>
17: /* Logging support */
18: PetscClassId PETSC_RANDOM_CLASSID;
20: /*@
21: PetscRandomDestroy - Destroys a `PetscRandom` object that was created by `PetscRandomCreate()`.
23: Collective
25: Input Parameter:
26: . r - the random number generator object
28: Level: intermediate
30: .seealso: `PetscRandom`, `PetscRandomGetValue()`, `PetscRandomCreate()`, `VecSetRandom()`
31: @*/
32: PetscErrorCode PetscRandomDestroy(PetscRandom *r)
33: {
34: PetscFunctionBegin;
35: if (!*r) PetscFunctionReturn(PETSC_SUCCESS);
37: if (--((PetscObject)*r)->refct > 0) {
38: *r = NULL;
39: PetscFunctionReturn(PETSC_SUCCESS);
40: }
41: PetscTryTypeMethod(*r, destroy);
42: PetscCall(PetscHeaderDestroy(r));
43: PetscFunctionReturn(PETSC_SUCCESS);
44: }
46: /*@C
47: PetscRandomGetSeed - Gets the random seed.
49: Not collective
51: Input Parameter:
52: . r - The random number generator context
54: Output Parameter:
55: . seed - The random seed
57: Level: intermediate
59: .seealso: `PetscRandom`, `PetscRandomCreate()`, `PetscRandomSetSeed()`, `PetscRandomSeed()`
60: @*/
61: PetscErrorCode PetscRandomGetSeed(PetscRandom r, PetscInt64 *seed)
62: {
63: PetscFunctionBegin;
65: if (seed) {
66: PetscAssertPointer(seed, 2);
67: *seed = (PetscInt64)r->seed;
68: }
69: PetscFunctionReturn(PETSC_SUCCESS);
70: }
72: /*@C
73: PetscRandomSetSeed - Sets the random seed. You MUST call `PetscRandomSeed()` after this call to have the new seed used.
75: Not collective
77: Input Parameters:
78: + r - The random number generator context
79: - seed - The random seed
81: Level: intermediate
83: Example Usage:
84: .vb
85: PetscRandomSetSeed(r,a positive integer);
86: PetscRandomSeed(r);
87: PetscRandomGetValue() will now start with the new seed.
89: PetscRandomSeed(r) without a call to PetscRandomSetSeed() re-initializes
90: the seed. The random numbers generated will be the same as before.
91: .ve
93: .seealso: `PetscRandom`, `PetscRandomCreate()`, `PetscRandomGetSeed()`, `PetscRandomSeed()`
94: @*/
95: PetscErrorCode PetscRandomSetSeed(PetscRandom r, PetscInt64 seed)
96: {
97: PetscFunctionBegin;
99: r->seed = (unsigned long)seed;
100: PetscCall(PetscInfo(NULL, "Setting seed to %d\n", (int)seed));
101: PetscFunctionReturn(PETSC_SUCCESS);
102: }
104: /*
105: PetscRandomSetTypeFromOptions_Private - Sets the type of random generator from user options. Defaults to type PETSCRAND48 or PETSCRAND.
107: Collective
109: Input Parameter:
110: . rnd - The random number generator context
112: Level: intermediate
114: .seealso: `PetscRandomSetFromOptions()`, `PetscRandomSetType()`
115: */
116: static PetscErrorCode PetscRandomSetTypeFromOptions_Private(PetscRandom rnd, PetscOptionItems PetscOptionsObject)
117: {
118: PetscBool opt;
119: const char *defaultType;
120: char typeName[256];
122: PetscFunctionBegin;
123: if (((PetscObject)rnd)->type_name) {
124: defaultType = ((PetscObject)rnd)->type_name;
125: } else {
126: defaultType = PETSCRANDER48;
127: }
129: PetscCall(PetscRandomRegisterAll());
130: PetscCall(PetscOptionsFList("-random_type", "PetscRandom type", "PetscRandomSetType", PetscRandomList, defaultType, typeName, 256, &opt));
131: if (opt) {
132: PetscCall(PetscRandomSetType(rnd, typeName));
133: } else {
134: PetscCall(PetscRandomSetType(rnd, defaultType));
135: }
136: PetscFunctionReturn(PETSC_SUCCESS);
137: }
139: /*@
140: PetscRandomSetFromOptions - Configures the random number generator from the options database.
142: Collective
144: Input Parameter:
145: . rnd - The random number generator context
147: Options Database Keys:
148: + -random_seed seed - provide a seed to the random number generator
149: - -random_no_imaginary_part - makes the imaginary part of the random number zero, this is useful when you want the
150: same code to produce the same result when run with real numbers or complex numbers for regression testing purposes
152: Level: beginner
154: Note:
155: Must be called after `PetscRandomCreate()` but before the rnd is used.
157: .seealso: `PetscRandom`, `PetscRandomCreate()`, `PetscRandomSetType()`
158: @*/
159: PetscErrorCode PetscRandomSetFromOptions(PetscRandom rnd)
160: {
161: PetscBool set, noimaginary = PETSC_FALSE;
162: PetscInt seed;
164: PetscFunctionBegin;
167: PetscObjectOptionsBegin((PetscObject)rnd);
169: /* Handle PetscRandom type options */
170: PetscCall(PetscRandomSetTypeFromOptions_Private(rnd, PetscOptionsObject));
172: /* Handle specific random generator's options */
173: PetscTryTypeMethod(rnd, setfromoptions, PetscOptionsObject);
174: PetscCall(PetscOptionsInt("-random_seed", "Seed to use to generate random numbers", "PetscRandomSetSeed", 0, &seed, &set));
175: if (set) {
176: PetscCall(PetscRandomSetSeed(rnd, (unsigned long int)seed));
177: PetscCall(PetscRandomSeed(rnd));
178: }
179: PetscCall(PetscOptionsBool("-random_no_imaginary_part", "The imaginary part of the random number will be zero", "PetscRandomSetInterval", noimaginary, &noimaginary, &set));
180: #if defined(PETSC_HAVE_COMPLEX)
181: if (set) {
182: if (noimaginary) {
183: PetscScalar low, high;
184: PetscCall(PetscRandomGetInterval(rnd, &low, &high));
185: low = low - PetscImaginaryPart(low);
186: high = high - PetscImaginaryPart(high);
187: PetscCall(PetscRandomSetInterval(rnd, low, high));
188: }
189: }
190: #endif
191: PetscOptionsEnd();
192: PetscCall(PetscRandomViewFromOptions(rnd, NULL, "-random_view"));
193: PetscFunctionReturn(PETSC_SUCCESS);
194: }
196: /*@
197: PetscRandomSetOptionsPrefix - Sets the prefix used for searching for all
198: `PetscRandom` options in the database.
200: Logically Collective
202: Input Parameters:
203: + r - the random number generator context
204: - prefix - the prefix to prepend to all option names
206: Level: advanced
208: Note:
209: A hyphen (-) must NOT be given at the beginning of the prefix name.
210: The first character of all runtime options is AUTOMATICALLY the hyphen.
212: .seealso: `PetscRandom`, `PetscRandomAppendOptionsPrefix()`, `PetscRandomSetFromOptions()`
213: @*/
214: PetscErrorCode PetscRandomSetOptionsPrefix(PetscRandom r, const char prefix[])
215: {
216: PetscFunctionBegin;
218: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)r, prefix));
219: PetscFunctionReturn(PETSC_SUCCESS);
220: }
222: /*@
223: PetscRandomAppendOptionsPrefix - Appends to the prefix used for searching for all
224: `PetscRandom` options in the database.
226: Logically Collective
228: Input Parameters:
229: + r - the random number generator context
230: - prefix - the prefix string to prepend to all `PetscRandom` option requests
232: Level: advanced
234: Note:
235: A hyphen (-) must NOT be given at the beginning of the prefix name.
236: The first character of all runtime options is AUTOMATICALLY the hyphen.
238: .seealso: `PetscRandom`, `PetscRandomSetOptionsPrefix()`, `PetscRandomSetFromOptions()`
239: @*/
240: PetscErrorCode PetscRandomAppendOptionsPrefix(PetscRandom r, const char prefix[])
241: {
242: PetscFunctionBegin;
244: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)r, prefix));
245: PetscFunctionReturn(PETSC_SUCCESS);
246: }
248: /*@
249: PetscRandomGetOptionsPrefix - Gets the prefix used for searching for all
250: `PetscRandom` options in the database.
252: Not Collective
254: Input Parameter:
255: . r - the random number generator context
257: Output Parameter:
258: . prefix - pointer to the prefix string used
260: Level: advanced
262: .seealso: `PetscRandom`, `PetscRandomSetOptionsPrefix()`, `PetscRandomAppendOptionsPrefix()`
263: @*/
264: PetscErrorCode PetscRandomGetOptionsPrefix(PetscRandom r, const char *prefix[])
265: {
266: PetscFunctionBegin;
268: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)r, prefix));
269: PetscFunctionReturn(PETSC_SUCCESS);
270: }
272: #if defined(PETSC_HAVE_SAWS)
273: #include <petscviewersaws.h>
274: #endif
276: /*@
277: PetscRandomViewFromOptions - View a `PetscRandom` object based on the options database
279: Collective
281: Input Parameters:
282: + A - the random number generator context
283: . obj - Optional object
284: - name - command line option
286: Options Database Key:
287: . -name [viewertype][:...] - option name and values. See `PetscObjectViewFromOptions()` for the possible arguments
289: Level: intermediate
291: .seealso: `PetscRandom`, `PetscRandomView`, `PetscObjectViewFromOptions()`, `PetscRandomCreate()`
292: @*/
293: PetscErrorCode PetscRandomViewFromOptions(PetscRandom A, PetscObject obj, const char name[])
294: {
295: PetscFunctionBegin;
297: PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
298: PetscFunctionReturn(PETSC_SUCCESS);
299: }
301: /*@
302: PetscRandomView - Views a random number generator object.
304: Collective
306: Input Parameters:
307: + rnd - The random number generator context
308: - viewer - an optional visualization context
310: Level: beginner
312: Note:
313: The available visualization contexts include
314: + `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
315: - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
316: output where only the first processor opens
317: the file. All other processors send their
318: data to the first processor to print.
320: .seealso: `PetscRandom`, `PetscRealView()`, `PetscScalarView()`, `PetscIntView()`
321: @*/
322: PetscErrorCode PetscRandomView(PetscRandom rnd, PetscViewer viewer)
323: {
324: PetscBool isascii;
325: #if defined(PETSC_HAVE_SAWS)
326: PetscBool issaws;
327: #endif
329: PetscFunctionBegin;
332: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)rnd), &viewer));
334: PetscCheckSameComm(rnd, 1, viewer, 2);
335: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
336: #if defined(PETSC_HAVE_SAWS)
337: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
338: #endif
339: if (isascii) {
340: PetscMPIInt rank;
341: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)rnd, viewer));
342: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)rnd), &rank));
343: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
344: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Random type %s, seed %lu\n", rank, ((PetscObject)rnd)->type_name, rnd->seed));
345: PetscCall(PetscViewerFlush(viewer));
346: PetscCall(PetscViewerASCIIPopSynchronized(viewer));
347: #if defined(PETSC_HAVE_SAWS)
348: } else if (issaws) {
349: PetscMPIInt rank;
350: const char *name;
352: PetscCall(PetscObjectGetName((PetscObject)rnd, &name));
353: PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
354: if (!((PetscObject)rnd)->amsmem && rank == 0) {
355: char dir[1024];
357: PetscCall(PetscObjectViewSAWs((PetscObject)rnd, viewer));
358: PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/Low", name));
359: PetscCallSAWs(SAWs_Register, (dir, &rnd->low, 1, SAWs_READ, SAWs_DOUBLE));
360: }
361: #endif
362: }
363: PetscFunctionReturn(PETSC_SUCCESS);
364: }
366: /*@
367: PetscRandomCreate - Creates an object for generating random numbers,
368: and initializes the random-number generator.
370: Collective
372: Input Parameter:
373: . comm - MPI communicator
375: Output Parameter:
376: . r - the random number generator object
378: Level: intermediate
380: Notes:
381: The random type has to be set by `PetscRandomSetType()`.
383: This is only a primitive "parallel" random number generator, it should NOT
384: be used for sophisticated parallel Monte Carlo methods since it will very likely
385: not have the correct statistics across processors. You can provide your own
386: parallel generator using `PetscRandomRegister()`;
388: If you create a `PetscRandom()` using `PETSC_COMM_SELF` on several processors then
389: the SAME random numbers will be generated on all those processors. Use `PETSC_COMM_WORLD`
390: or the appropriate parallel communicator to eliminate this issue.
392: Use `VecSetRandom()` to set the elements of a vector to random numbers.
394: Example of Usage:
395: .vb
396: PetscRandomCreate(PETSC_COMM_SELF,&r);
397: PetscRandomSetType(r,PETSCRAND48);
398: PetscRandomGetValue(r,&value1);
399: PetscRandomGetValueReal(r,&value2);
400: PetscRandomDestroy(&r);
401: .ve
403: .seealso: `PetscRandomSetType()`, `PetscRandomGetValue()`, `PetscRandomGetValueReal()`, `PetscRandomSetInterval()`,
404: `PetscRandomDestroy()`, `VecSetRandom()`, `PetscRandomType`, `PetscRandom`
405: @*/
406: PetscErrorCode PetscRandomCreate(MPI_Comm comm, PetscRandom *r)
407: {
408: PetscRandom rr;
409: PetscMPIInt rank;
411: PetscFunctionBegin;
412: PetscAssertPointer(r, 2);
413: PetscCall(PetscRandomInitializePackage());
415: PetscCall(PetscHeaderCreate(rr, PETSC_RANDOM_CLASSID, "PetscRandom", "Random number generator", "Sys", comm, PetscRandomDestroy, PetscRandomView));
416: PetscCallMPI(MPI_Comm_rank(comm, &rank));
417: rr->data = NULL;
418: rr->low = 0.0;
419: rr->width = 1.0;
420: rr->iset = PETSC_FALSE;
421: rr->seed = 0x12345678 + 76543 * rank;
422: PetscCall(PetscRandomSetType(rr, PETSCRANDER48));
423: *r = rr;
424: PetscFunctionReturn(PETSC_SUCCESS);
425: }
427: /*@
428: PetscRandomSeed - Seed the random number generator.
430: Not collective
432: Input Parameter:
433: . r - The random number generator context
435: Level: intermediate
437: Example Usage:
438: .vb
439: PetscRandomSetSeed(r,a positive integer);
440: PetscRandomSeed(r);
441: PetscRandomGetValue() will now start with the new seed.
443: PetscRandomSeed(r) without a call to PetscRandomSetSeed() re-initializes
444: the seed. The random numbers generated will be the same as before.
445: .ve
447: .seealso: `PetscRandomCreate()`, `PetscRandomGetSeed()`, `PetscRandomSetSeed()`
448: @*/
449: PetscErrorCode PetscRandomSeed(PetscRandom r)
450: {
451: PetscFunctionBegin;
455: PetscUseTypeMethod(r, seed);
456: PetscCall(PetscObjectStateIncrease((PetscObject)r));
457: PetscFunctionReturn(PETSC_SUCCESS);
458: }