xref: /petsc/src/sys/classes/random/interface/randomc.c (revision 1b95c6fd894075560ffb9feb52b5487dcfbc03ec)
1 
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:
6 
7     Numbers can be shuffled for use as random tuples
8 
9     Multiple random number generators may be used
10 
11     We are still not sure what interface we want here.  There should be
12     one to reinitialize and set the seed.
13  */
14 
15 #include <../src/sys/classes/random/randomimpl.h>                              /*I "petscsys.h" I*/
16 #include <petscviewer.h>
17 
18 /* Logging support */
19 PetscClassId PETSC_RANDOM_CLASSID;
20 
21 #undef __FUNCT__
22 #define __FUNCT__ "PetscRandomDestroy"
23 /*@
24    PetscRandomDestroy - Destroys a context that has been formed by
25    PetscRandomCreate().
26 
27    Collective on PetscRandom
28 
29    Intput Parameter:
30 .  r  - the random number generator context
31 
32    Level: intermediate
33 
34 .seealso: PetscRandomGetValue(), PetscRandomCreate(), VecSetRandom()
35 @*/
36 PetscErrorCode  PetscRandomDestroy(PetscRandom *r)
37 {
38   PetscErrorCode ierr;
39 
40   PetscFunctionBegin;
41   if (!*r) PetscFunctionReturn(0);
42   PetscValidHeaderSpecific(*r,PETSC_RANDOM_CLASSID,1);
43   if (--((PetscObject)(*r))->refct > 0) {*r = 0; PetscFunctionReturn(0);}
44   if ((*r)->ops->destroy) {
45     ierr = (*(*r)->ops->destroy)(*r);CHKERRQ(ierr);
46   }
47   ierr = PetscHeaderDestroy(r);CHKERRQ(ierr);
48   PetscFunctionReturn(0);
49 }
50 
51 
52 #undef __FUNCT__
53 #define __FUNCT__ "PetscRandomGetSeed"
54 /*@
55    PetscRandomGetSeed - Gets the random seed.
56 
57    Not collective
58 
59    Input Parameters:
60 .  r - The random number generator context
61 
62    Output Parameter:
63 .  seed - The random seed
64 
65    Level: intermediate
66 
67    Concepts: random numbers^seed
68 
69 .seealso: PetscRandomCreate(), PetscRandomSetSeed(), PetscRandomSeed()
70 @*/
71 PetscErrorCode  PetscRandomGetSeed(PetscRandom r,unsigned long *seed)
72 {
73   PetscFunctionBegin;
74   PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1);
75   if (seed) {
76     PetscValidPointer(seed,2);
77     *seed = r->seed;
78   }
79   PetscFunctionReturn(0);
80 }
81 
82 #undef __FUNCT__
83 #define __FUNCT__ "PetscRandomSetSeed"
84 /*@
85    PetscRandomSetSeed - Sets the random seed. You MUST call PetscRandomSeed() after this call to have the new seed used.
86 
87    Not collective
88 
89    Input Parameters:
90 +  r  - The random number generator context
91 -  seed - The random seed
92 
93    Level: intermediate
94 
95    Usage:
96       PetscRandomSetSeed(r,a positive integer);
97       PetscRandomSeed(r);  PetscRandomGetValue() will now start with the new seed.
98 
99       PetscRandomSeed(r) without a call to PetscRandomSetSeed() re-initializes
100         the seed. The random numbers generated will be the same as before.
101 
102    Concepts: random numbers^seed
103 
104 .seealso: PetscRandomCreate(), PetscRandomGetSeed(), PetscRandomSeed()
105 @*/
106 PetscErrorCode  PetscRandomSetSeed(PetscRandom r,unsigned long seed)
107 {
108   PetscErrorCode ierr;
109 
110   PetscFunctionBegin;
111   PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1);
112   r->seed = seed;
113   ierr    = PetscInfo1(NULL,"Setting seed to %d\n",(int)seed);CHKERRQ(ierr);
114   PetscFunctionReturn(0);
115 }
116 
117 /* ------------------------------------------------------------------- */
118 #undef __FUNCT__
119 #define __FUNCT__ "PetscRandomSetTypeFromOptions_Private"
120 /*
121   PetscRandomSetTypeFromOptions_Private - Sets the type of random generator from user options. Defaults to type PETSCRAND48 or PETSCRAND.
122 
123   Collective on PetscRandom
124 
125   Input Parameter:
126 . rnd - The random number generator context
127 
128   Level: intermediate
129 
130 .keywords: PetscRandom, set, options, database, type
131 .seealso: PetscRandomSetFromOptions(), PetscRandomSetType()
132 */
133 static PetscErrorCode PetscRandomSetTypeFromOptions_Private(PetscOptions *PetscOptionsObject,PetscRandom rnd)
134 {
135   PetscBool      opt;
136   const char     *defaultType;
137   char           typeName[256];
138   PetscErrorCode ierr;
139 
140   PetscFunctionBegin;
141   if (((PetscObject)rnd)->type_name) {
142     defaultType = ((PetscObject)rnd)->type_name;
143   } else {
144     defaultType = PETSCRANDER48;
145   }
146 
147   ierr = PetscRandomRegisterAll();CHKERRQ(ierr);
148   ierr = PetscOptionsFList("-random_type","PetscRandom type","PetscRandomSetType",PetscRandomList,defaultType,typeName,256,&opt);CHKERRQ(ierr);
149   if (opt) {
150     ierr = PetscRandomSetType(rnd, typeName);CHKERRQ(ierr);
151   } else {
152     ierr = PetscRandomSetType(rnd, defaultType);CHKERRQ(ierr);
153   }
154   PetscFunctionReturn(0);
155 }
156 
157 #undef __FUNCT__
158 #define __FUNCT__ "PetscRandomSetFromOptions"
159 /*@
160   PetscRandomSetFromOptions - Configures the random number generator from the options database.
161 
162   Collective on PetscRandom
163 
164   Input Parameter:
165 . rnd - The random number generator context
166 
167   Options Database:
168 .  -random_seed <integer> - provide a seed to the random number generater
169 
170   Notes:  To see all options, run your program with the -help option.
171           Must be called after PetscRandomCreate() but before the rnd is used.
172 
173   Level: beginner
174 
175 .keywords: PetscRandom, set, options, database
176 .seealso: PetscRandomCreate(), PetscRandomSetType()
177 @*/
178 PetscErrorCode  PetscRandomSetFromOptions(PetscRandom rnd)
179 {
180   PetscErrorCode ierr;
181   PetscBool      set;
182   PetscInt       seed;
183 
184   PetscFunctionBegin;
185   PetscValidHeaderSpecific(rnd,PETSC_RANDOM_CLASSID,1);
186 
187   ierr = PetscObjectOptionsBegin((PetscObject)rnd);CHKERRQ(ierr);
188 
189   /* Handle PetscRandom type options */
190   ierr = PetscRandomSetTypeFromOptions_Private(PetscOptionsObject,rnd);CHKERRQ(ierr);
191 
192   /* Handle specific random generator's options */
193   if (rnd->ops->setfromoptions) {
194     ierr = (*rnd->ops->setfromoptions)(PetscOptionsObject,rnd);CHKERRQ(ierr);
195   }
196   ierr = PetscOptionsInt("-random_seed","Seed to use to generate random numbers","PetscRandomSetSeed",0,&seed,&set);CHKERRQ(ierr);
197   if (set) {
198     ierr = PetscRandomSetSeed(rnd,(unsigned long int)seed);CHKERRQ(ierr);
199     ierr = PetscRandomSeed(rnd);CHKERRQ(ierr);
200   }
201   ierr = PetscOptionsEnd();CHKERRQ(ierr);
202   ierr = PetscRandomViewFromOptions(rnd,NULL, "-random_view");CHKERRQ(ierr);
203   PetscFunctionReturn(0);
204 }
205 
206 #if defined(PETSC_HAVE_SAWS)
207 #include <petscviewersaws.h>
208 #endif
209 #undef __FUNCT__
210 #define __FUNCT__ "PetscRandomView"
211 /*@C
212    PetscRandomView - Views a random number generator object.
213 
214    Collective on PetscRandom
215 
216    Input Parameters:
217 +  rnd - The random number generator context
218 -  viewer - an optional visualization context
219 
220    Notes:
221    The available visualization contexts include
222 +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
223 -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
224          output where only the first processor opens
225          the file.  All other processors send their
226          data to the first processor to print.
227 
228    You can change the format the vector is printed using the
229    option PetscViewerSetFormat().
230 
231    Level: beginner
232 
233 .seealso:  PetscRealView(), PetscScalarView(), PetscIntView()
234 @*/
235 PetscErrorCode  PetscRandomView(PetscRandom rnd,PetscViewer viewer)
236 {
237   PetscErrorCode ierr;
238   PetscBool      iascii;
239 #if defined(PETSC_HAVE_SAWS)
240   PetscBool      issaws;
241 #endif
242 
243   PetscFunctionBegin;
244   PetscValidHeaderSpecific(rnd,PETSC_RANDOM_CLASSID,1);
245   PetscValidType(rnd,1);
246   if (!viewer) {
247     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)rnd),&viewer);CHKERRQ(ierr);
248   }
249   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
250   PetscCheckSameComm(rnd,1,viewer,2);
251   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
252 #if defined(PETSC_HAVE_SAWS)
253   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws);CHKERRQ(ierr);
254 #endif
255   if (iascii) {
256     PetscMPIInt rank;
257     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)rnd,viewer);CHKERRQ(ierr);
258     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)rnd),&rank);CHKERRQ(ierr);
259     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
260     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Random type %s, seed %D\n",rank,((PetscObject)rnd)->type_name,rnd->seed);CHKERRQ(ierr);
261     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
262     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
263 #if defined(PETSC_HAVE_SAWS)
264   } else if (issaws) {
265     PetscMPIInt rank;
266     const char  *name;
267 
268     ierr = PetscObjectGetName((PetscObject)rnd,&name);CHKERRQ(ierr);
269     ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
270     if (!((PetscObject)rnd)->amsmem && !rank) {
271       char       dir[1024];
272 
273       ierr = PetscObjectViewSAWs((PetscObject)rnd,viewer);CHKERRQ(ierr);
274       ierr = PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/Low",name);CHKERRQ(ierr);
275       PetscStackCallSAWs(SAWs_Register,(dir,&rnd->low,1,SAWs_READ,SAWs_DOUBLE));
276     }
277 #endif
278   }
279   PetscFunctionReturn(0);
280 }
281 
282 #undef __FUNCT__
283 #define __FUNCT__ "PetscRandomCreate"
284 /*@
285    PetscRandomCreate - Creates a context for generating random numbers,
286    and initializes the random-number generator.
287 
288    Collective on MPI_Comm
289 
290    Input Parameters:
291 +  comm - MPI communicator
292 
293    Output Parameter:
294 .  r  - the random number generator context
295 
296    Level: intermediate
297 
298    Notes:
299    The random type has to be set by PetscRandomSetType().
300 
301    This is only a primative "parallel" random number generator, it should NOT
302    be used for sophisticated parallel Monte Carlo methods since it will very likely
303    not have the correct statistics across processors. You can provide your own
304    parallel generator using PetscRandomRegister();
305 
306    If you create a PetscRandom() using PETSC_COMM_SELF on several processors then
307    the SAME random numbers will be generated on all those processors. Use PETSC_COMM_WORLD
308    or the appropriate parallel communicator to eliminate this issue.
309 
310    Use VecSetRandom() to set the elements of a vector to random numbers.
311 
312    Example of Usage:
313 .vb
314       PetscRandomCreate(PETSC_COMM_SELF,&r);
315       PetscRandomSetType(r,PETSCRAND48);
316       PetscRandomGetValue(r,&value1);
317       PetscRandomGetValueReal(r,&value2);
318       PetscRandomDestroy(&r);
319 .ve
320 
321    Concepts: random numbers^creating
322 
323 .seealso: PetscRandomSetType(), PetscRandomGetValue(), PetscRandomGetValueReal(), PetscRandomSetInterval(),
324           PetscRandomDestroy(), VecSetRandom(), PetscRandomType
325 @*/
326 
327 PetscErrorCode  PetscRandomCreate(MPI_Comm comm,PetscRandom *r)
328 {
329   PetscRandom    rr;
330   PetscErrorCode ierr;
331   PetscMPIInt    rank;
332 
333   PetscFunctionBegin;
334   PetscValidPointer(r,3);
335   *r = NULL;
336   ierr = PetscRandomInitializePackage();CHKERRQ(ierr);
337 
338   ierr = PetscHeaderCreate(rr,PETSC_RANDOM_CLASSID,"PetscRandom","Random number generator","Sys",comm,PetscRandomDestroy,NULL);CHKERRQ(ierr);
339 
340   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
341 
342   rr->data  = NULL;
343   rr->low   = 0.0;
344   rr->width = 1.0;
345   rr->iset  = PETSC_FALSE;
346   rr->seed  = 0x12345678 + 76543*rank;
347   ierr = PetscRandomSetType(rr,PETSCRANDER48);CHKERRQ(ierr);
348   *r = rr;
349   PetscFunctionReturn(0);
350 }
351 
352 #undef __FUNCT__
353 #define __FUNCT__ "PetscRandomSeed"
354 /*@
355    PetscRandomSeed - Seed the generator.
356 
357    Not collective
358 
359    Input Parameters:
360 .  r - The random number generator context
361 
362    Level: intermediate
363 
364    Usage:
365       PetscRandomSetSeed(r,a positive integer);
366       PetscRandomSeed(r);  PetscRandomGetValue() will now start with the new seed.
367 
368       PetscRandomSeed(r) without a call to PetscRandomSetSeed() re-initializes
369         the seed. The random numbers generated will be the same as before.
370 
371    Concepts: random numbers^seed
372 
373 .seealso: PetscRandomCreate(), PetscRandomGetSeed(), PetscRandomSetSeed()
374 @*/
375 PetscErrorCode  PetscRandomSeed(PetscRandom r)
376 {
377   PetscErrorCode ierr;
378 
379   PetscFunctionBegin;
380   PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1);
381   PetscValidType(r,1);
382 
383   ierr = (*r->ops->seed)(r);CHKERRQ(ierr);
384   ierr = PetscObjectStateIncrease((PetscObject)r);CHKERRQ(ierr);
385   PetscFunctionReturn(0);
386 }
387 
388