xref: /petsc/src/sys/classes/random/interface/randomc.c (revision dcca6d9d80ebd869fe6029bd05a3aa9faafef49e)
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   ierr = PetscHeaderDestroy(r);CHKERRQ(ierr);
45   PetscFunctionReturn(0);
46 }
47 
48 
49 #undef __FUNCT__
50 #define __FUNCT__ "PetscRandomGetSeed"
51 /*@
52    PetscRandomGetSeed - Gets the random seed.
53 
54    Not collective
55 
56    Input Parameters:
57 .  r - The random number generator context
58 
59    Output Parameter:
60 .  seed - The random seed
61 
62    Level: intermediate
63 
64    Concepts: random numbers^seed
65 
66 .seealso: PetscRandomCreate(), PetscRandomSetSeed(), PetscRandomSeed()
67 @*/
68 PetscErrorCode  PetscRandomGetSeed(PetscRandom r,unsigned long *seed)
69 {
70   PetscFunctionBegin;
71   PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1);
72   if (seed) {
73     PetscValidPointer(seed,2);
74     *seed = r->seed;
75   }
76   PetscFunctionReturn(0);
77 }
78 
79 #undef __FUNCT__
80 #define __FUNCT__ "PetscRandomSetSeed"
81 /*@
82    PetscRandomSetSeed - Sets the random seed. You MUST call PetscRandomSeed() after this call to have the new seed used.
83 
84    Not collective
85 
86    Input Parameters:
87 +  r  - The random number generator context
88 -  seed - The random seed
89 
90    Level: intermediate
91 
92    Usage:
93       PetscRandomSetSeed(r,a positive integer);
94       PetscRandomSeed(r);  PetscRandomGetValue() will now start with the new seed.
95 
96       PetscRandomSeed(r) without a call to PetscRandomSetSeed() re-initializes
97         the seed. The random numbers generated will be the same as before.
98 
99    Concepts: random numbers^seed
100 
101 .seealso: PetscRandomCreate(), PetscRandomGetSeed(), PetscRandomSeed()
102 @*/
103 PetscErrorCode  PetscRandomSetSeed(PetscRandom r,unsigned long seed)
104 {
105   PetscErrorCode ierr;
106 
107   PetscFunctionBegin;
108   PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1);
109   r->seed = seed;
110   ierr    = PetscInfo1(NULL,"Setting seed to %d\n",(int)seed);CHKERRQ(ierr);
111   PetscFunctionReturn(0);
112 }
113 
114 /* ------------------------------------------------------------------- */
115 #undef __FUNCT__
116 #define __FUNCT__ "PetscRandomSetTypeFromOptions_Private"
117 /*
118   PetscRandomSetTypeFromOptions_Private - Sets the type of random generator from user options. Defaults to type PETSCRAND48 or PETSCRAND.
119 
120   Collective on PetscRandom
121 
122   Input Parameter:
123 . rnd - The random number generator context
124 
125   Level: intermediate
126 
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];
135   PetscErrorCode ierr;
136 
137   PetscFunctionBegin;
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   }
147 
148   if (!PetscRandomRegisterAllCalled) {ierr = PetscRandomRegisterAll();CHKERRQ(ierr);}
149   ierr = PetscOptionsFList("-random_type","PetscRandom type","PetscRandomSetType",PetscRandomList,defaultType,typeName,256,&opt);CHKERRQ(ierr);
150   if (opt) {
151     ierr = PetscRandomSetType(rnd, typeName);CHKERRQ(ierr);
152   } else {
153     ierr = PetscRandomSetType(rnd, defaultType);CHKERRQ(ierr);
154   }
155   PetscFunctionReturn(0);
156 }
157 
158 #undef __FUNCT__
159 #define __FUNCT__ "PetscRandomSetFromOptions"
160 /*@
161   PetscRandomSetFromOptions - Configures the random number generator from the options database.
162 
163   Collective on PetscRandom
164 
165   Input Parameter:
166 . rnd - The random number generator context
167 
168   Options Database:
169 .  -random_seed <integer> - provide a seed to the random number generater
170 
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.
173 
174   Level: beginner
175 
176 .keywords: PetscRandom, set, options, database
177 .seealso: PetscRandomCreate(), PetscRandomSetType()
178 @*/
179 PetscErrorCode  PetscRandomSetFromOptions(PetscRandom rnd)
180 {
181   PetscErrorCode ierr;
182   PetscBool      set;
183   PetscInt       seed;
184 
185   PetscFunctionBegin;
186   PetscValidHeaderSpecific(rnd,PETSC_RANDOM_CLASSID,1);
187 
188   ierr = PetscObjectOptionsBegin((PetscObject)rnd);CHKERRQ(ierr);
189 
190   /* Handle PetscRandom type options */
191   ierr = PetscRandomSetTypeFromOptions_Private(rnd);CHKERRQ(ierr);
192 
193   /* Handle specific random generator's options */
194   if (rnd->ops->setfromoptions) {
195     ierr = (*rnd->ops->setfromoptions)(rnd);CHKERRQ(ierr);
196   }
197   ierr = PetscOptionsInt("-random_seed","Seed to use to generate random numbers","PetscRandomSetSeed",0,&seed,&set);CHKERRQ(ierr);
198   if (set) {
199     ierr = PetscRandomSetSeed(rnd,(unsigned long int)seed);CHKERRQ(ierr);
200     ierr = PetscRandomSeed(rnd);CHKERRQ(ierr);
201   }
202   ierr = PetscOptionsEnd();CHKERRQ(ierr);
203   ierr = PetscRandomViewFromOptions(rnd,NULL, "-random_view");CHKERRQ(ierr);
204   PetscFunctionReturn(0);
205 }
206 
207 #if defined(PETSC_HAVE_SAWS)
208 #include <petscviewersaws.h>
209 #endif
210 #undef __FUNCT__
211 #define __FUNCT__ "PetscRandomView"
212 /*@C
213    PetscRandomView - Views a random number generator object.
214 
215    Collective on PetscRandom
216 
217    Input Parameters:
218 +  rnd - The random number generator context
219 -  viewer - an optional visualization context
220 
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.
228 
229    You can change the format the vector is printed using the
230    option PetscViewerSetFormat().
231 
232    Level: beginner
233 
234 .seealso:  PetscRealView(), PetscScalarView(), PetscIntView()
235 @*/
236 PetscErrorCode  PetscRandomView(PetscRandom rnd,PetscViewer viewer)
237 {
238   PetscErrorCode ierr;
239   PetscBool      iascii;
240 #if defined(PETSC_HAVE_SAWS)
241   PetscBool      isams;
242 #endif
243 
244   PetscFunctionBegin;
245   PetscValidHeaderSpecific(rnd,PETSC_RANDOM_CLASSID,1);
246   PetscValidType(rnd,1);
247   if (!viewer) {
248     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)rnd),&viewer);CHKERRQ(ierr);
249   }
250   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
251   PetscCheckSameComm(rnd,1,viewer,2);
252   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
253 #if defined(PETSC_HAVE_SAWS)
254   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&isams);CHKERRQ(ierr);
255 #endif
256   if (iascii) {
257     PetscMPIInt rank;
258     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)rnd),&rank);CHKERRQ(ierr);
259     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);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 = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr);
263 #if defined(PETSC_HAVE_SAWS)
264   } else if (isams) {
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__ "PetscRandomViewFromOptions"
284 /*
285   PetscRandomViewFromOptions - This function visualizes the type and the seed of the generated random numbers based upon user options.
286 
287   Collective on PetscRandom
288 
289   Input Parameters:
290 + rnd   - The random number generator context
291 . prefix - prefix to use for viewing, or NULL to use prefix of 'rnd'
292 - optionname - option to activate viewing
293 
294   Level: intermediate
295 
296 .keywords: PetscRandom, view, options, database
297 .seealso: PetscRandomSetFromOptions()
298 */
299 PetscErrorCode  PetscRandomViewFromOptions(PetscRandom rnd, const char prefix[], const char optionname[])
300 {
301   PetscBool         flg;
302   PetscViewer       viewer;
303   PetscErrorCode    ierr;
304   PetscViewerFormat format;
305 
306   PetscFunctionBegin;
307   if (prefix) {
308     ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)rnd),prefix,optionname,&viewer,&format,&flg);CHKERRQ(ierr);
309   } else {
310     ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)rnd),((PetscObject)rnd)->prefix,optionname,&viewer,&format,&flg);CHKERRQ(ierr);
311   }
312   if (flg) {
313     ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr);
314     ierr = PetscRandomView(rnd,viewer);CHKERRQ(ierr);
315     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
316     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
317   }
318   PetscFunctionReturn(0);
319 }
320 
321 #undef __FUNCT__
322 #define __FUNCT__ "PetscRandomCreate"
323 /*@
324    PetscRandomCreate - Creates a context for generating random numbers,
325    and initializes the random-number generator.
326 
327    Collective on MPI_Comm
328 
329    Input Parameters:
330 +  comm - MPI communicator
331 
332    Output Parameter:
333 .  r  - the random number generator context
334 
335    Level: intermediate
336 
337    Notes:
338    The random type has to be set by PetscRandomSetType().
339 
340    This is only a primative "parallel" random number generator, it should NOT
341    be used for sophisticated parallel Monte Carlo methods since it will very likely
342    not have the correct statistics across processors. You can provide your own
343    parallel generator using PetscRandomRegister();
344 
345    If you create a PetscRandom() using PETSC_COMM_SELF on several processors then
346    the SAME random numbers will be generated on all those processors. Use PETSC_COMM_WORLD
347    or the appropriate parallel communicator to eliminate this issue.
348 
349    Use VecSetRandom() to set the elements of a vector to random numbers.
350 
351    Example of Usage:
352 .vb
353       PetscRandomCreate(PETSC_COMM_SELF,&r);
354       PetscRandomSetType(r,PETSCRAND48);
355       PetscRandomGetValue(r,&value1);
356       PetscRandomGetValueReal(r,&value2);
357       PetscRandomDestroy(&r);
358 .ve
359 
360    Concepts: random numbers^creating
361 
362 .seealso: PetscRandomSetType(), PetscRandomGetValue(), PetscRandomGetValueReal(), PetscRandomSetInterval(),
363           PetscRandomDestroy(), VecSetRandom(), PetscRandomType
364 @*/
365 
366 PetscErrorCode  PetscRandomCreate(MPI_Comm comm,PetscRandom *r)
367 {
368   PetscRandom    rr;
369   PetscErrorCode ierr;
370   PetscMPIInt    rank;
371 
372   PetscFunctionBegin;
373   PetscValidPointer(r,3);
374   *r = NULL;
375   ierr = PetscRandomInitializePackage();CHKERRQ(ierr);
376 
377   ierr = PetscHeaderCreate(rr,_p_PetscRandom,struct _PetscRandomOps,PETSC_RANDOM_CLASSID,"PetscRandom","Random number generator","Sys",comm,PetscRandomDestroy,0);CHKERRQ(ierr);
378 
379   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
380 
381   rr->data  = NULL;
382   rr->low   = 0.0;
383   rr->width = 1.0;
384   rr->iset  = PETSC_FALSE;
385   rr->seed  = 0x12345678 + 76543*rank;
386   *r = rr;
387   PetscFunctionReturn(0);
388 }
389 
390 #undef __FUNCT__
391 #define __FUNCT__ "PetscRandomSeed"
392 /*@
393    PetscRandomSeed - Seed the generator.
394 
395    Not collective
396 
397    Input Parameters:
398 .  r - The random number generator context
399 
400    Level: intermediate
401 
402    Usage:
403       PetscRandomSetSeed(r,a positive integer);
404       PetscRandomSeed(r);  PetscRandomGetValue() will now start with the new seed.
405 
406       PetscRandomSeed(r) without a call to PetscRandomSetSeed() re-initializes
407         the seed. The random numbers generated will be the same as before.
408 
409    Concepts: random numbers^seed
410 
411 .seealso: PetscRandomCreate(), PetscRandomGetSeed(), PetscRandomSetSeed()
412 @*/
413 PetscErrorCode  PetscRandomSeed(PetscRandom r)
414 {
415   PetscErrorCode ierr;
416 
417   PetscFunctionBegin;
418   PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1);
419   PetscValidType(r,1);
420 
421   ierr = (*r->ops->seed)(r);CHKERRQ(ierr);
422   ierr = PetscObjectStateIncrease((PetscObject)r);CHKERRQ(ierr);
423   PetscFunctionReturn(0);
424 }
425 
426