xref: /petsc/src/sys/classes/random/interface/random.c (revision 71052fdfa316db9eff6713675d06cb2251c7acfb)
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 <petsc/private/randomimpl.h>                              /*I "petscsys.h" I*/
16 
17 /*@
18    PetscRandomGetValue - Generates a random number.  Call this after first calling
19    PetscRandomCreate().
20 
21    Not Collective
22 
23    Input Parameter:
24 .  r  - the random number generator context
25 
26    Output Parameter:
27 .  val - the value
28 
29    Level: intermediate
30 
31    Notes:
32    Use VecSetRandom() to set the elements of a vector to random numbers.
33 
34    When PETSc is compiled for complex numbers this returns a complex number with random real and complex parts.
35    Use PetscRandomGetValueReal() to get a random real number.
36 
37    To get a complex number with only a random real part, first call PetscRandomSetInterval() with a equal
38    low and high imaginary part. Similarly to get a complex number with only a random imaginary part call
39    PetscRandomSetInterval() with a equal low and high real part.
40 
41    Example of Usage:
42 .vb
43       PetscRandomCreate(PETSC_COMM_WORLD,&r);
44       PetscRandomGetValue(r,&value1);
45       PetscRandomGetValue(r,&value2);
46       PetscRandomGetValue(r,&value3);
47       PetscRandomDestroy(&r);
48 .ve
49 
50 .seealso: `PetscRandomCreate()`, `PetscRandomDestroy()`, `VecSetRandom()`, `PetscRandomGetValueReal()`
51 @*/
52 PetscErrorCode  PetscRandomGetValue(PetscRandom r,PetscScalar *val)
53 {
54   PetscFunctionBegin;
55   PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1);
56   PetscValidType(r,1);
57   if (!r->ops->getvalue) {
58     PetscCall((*r->ops->getvalues)(r,1,val));
59   } else {
60     PetscCall((*r->ops->getvalue)(r,val));
61   }
62   PetscCall(PetscObjectStateIncrease((PetscObject)r));
63   PetscFunctionReturn(0);
64 }
65 
66 /*@
67    PetscRandomGetValueReal - Generates a real random number.  Call this after first calling
68    PetscRandomCreate().
69 
70    Not Collective
71 
72    Input Parameter:
73 .  r  - the random number generator context
74 
75    Output Parameter:
76 .  val - the value
77 
78    Level: intermediate
79 
80    Notes:
81    Use VecSetRandom() to set the elements of a vector to random numbers.
82 
83    Example of Usage:
84 .vb
85       PetscRandomCreate(PETSC_COMM_WORLD,&r);
86       PetscRandomGetValueReal(r,&value1);
87       PetscRandomGetValueReal(r,&value2);
88       PetscRandomGetValueReal(r,&value3);
89       PetscRandomDestroy(&r);
90 .ve
91 
92 .seealso: `PetscRandomCreate()`, `PetscRandomDestroy()`, `VecSetRandom()`, `PetscRandomGetValue()`
93 @*/
94 PetscErrorCode  PetscRandomGetValueReal(PetscRandom r,PetscReal *val)
95 {
96   PetscFunctionBegin;
97   PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1);
98   PetscValidType(r,1);
99   if (!r->ops->getvaluereal) {
100     PetscCall((*r->ops->getvaluesreal)(r,1,val));
101   } else {
102     PetscCall((*r->ops->getvaluereal)(r,val));
103   }
104   PetscCall(PetscObjectStateIncrease((PetscObject)r));
105   PetscFunctionReturn(0);
106 }
107 
108 /*@
109    PetscRandomGetValues - Generates a sequence of random numbers.  Call this after first calling
110    PetscRandomCreate().
111 
112    Not Collective
113 
114    Input Parameters:
115 +  r  - the random number generator context
116 -  n  - number of random numbers to generate
117 
118    Output Parameter:
119 .  val - the array to hold the values
120 
121    Level: intermediate
122 
123    Notes:
124    Use VecSetRandom() to set the elements of a vector to random numbers.
125 
126    When PETSc is compiled for complex numbers this returns an array of complex numbers with random real and complex parts.
127    Use PetscRandomGetValuesReal() to get an array of random real numbers.
128 
129 .seealso: `PetscRandomCreate()`, `PetscRandomDestroy()`, `VecSetRandom()`, `PetscRandomGetValue()`
130 @*/
131 PetscErrorCode  PetscRandomGetValues(PetscRandom r, PetscInt n, PetscScalar *val)
132 {
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1);
135   PetscValidType(r,1);
136   if (!r->ops->getvalues) {
137     PetscInt i;
138     for (i = 0; i < n; i++) {
139       PetscCall((*r->ops->getvalue)(r,val+i));
140     }
141   } else {
142     PetscCall((*r->ops->getvalues)(r,n,val));
143   }
144   PetscCall(PetscObjectStateIncrease((PetscObject)r));
145   PetscFunctionReturn(0);
146 }
147 
148 /*@
149    PetscRandomGetValuesReal - Generates a sequence of real random numbers.  Call this after first calling
150    PetscRandomCreate().
151 
152    Not Collective
153 
154    Input Parameters:
155 +  r  - the random number generator context
156 -  n  - number of random numbers to generate
157 
158    Output Parameter:
159 .  val - the array to hold the values
160 
161    Level: intermediate
162 
163    Notes:
164    Use VecSetRandom() to set the elements of a vector to random numbers.
165 
166 .seealso: `PetscRandomCreate()`, `PetscRandomDestroy()`, `VecSetRandom()`, `PetscRandomGetValues()`
167 @*/
168 PetscErrorCode  PetscRandomGetValuesReal(PetscRandom r, PetscInt n, PetscReal *val)
169 {
170   PetscFunctionBegin;
171   PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1);
172   PetscValidType(r,1);
173   if (!r->ops->getvaluesreal) {
174     PetscInt i;
175     for (i = 0; i < n; i++) {
176       PetscCall((*r->ops->getvaluereal)(r,val+i));
177     }
178   } else {
179     PetscCall((*r->ops->getvaluesreal)(r,n,val));
180   }
181   PetscCall(PetscObjectStateIncrease((PetscObject)r));
182   PetscFunctionReturn(0);
183 }
184 
185 /*@
186    PetscRandomGetInterval - Gets the interval over which the random numbers
187    will be randomly distributed.  By default, this interval is [0,1).
188 
189    Not collective
190 
191    Input Parameter:
192 .  r  - the random number generator context
193 
194    Output Parameters:
195 +  low - The lower bound of the interval
196 -  high - The upper bound of the interval
197 
198    Level: intermediate
199 
200 .seealso: `PetscRandomCreate()`, `PetscRandomSetInterval()`
201 @*/
202 PetscErrorCode  PetscRandomGetInterval(PetscRandom r,PetscScalar *low,PetscScalar *high)
203 {
204   PetscFunctionBegin;
205   PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1);
206   if (low) {
207     PetscValidScalarPointer(low,2);
208     *low = r->low;
209   }
210   if (high) {
211     PetscValidScalarPointer(high,3);
212     *high = r->low+r->width;
213   }
214   PetscFunctionReturn(0);
215 }
216 
217 /*@
218    PetscRandomSetInterval - Sets the interval over which the random numbers
219    will be randomly distributed.  By default, this interval is [0,1).
220 
221    Not collective
222 
223    Input Parameters:
224 +  r  - the random number generator context
225 .  low - The lower bound of the interval
226 -  high - The upper bound of the interval
227 
228    Level: intermediate
229 
230    Notes:
231     for complex numbers either the real part or the imaginary part of high must be greater than its low part; or both of them can be greater.
232     If the real or imaginary part of low and high are the same then that value is always returned in the real or imaginary part.
233 
234 .seealso: `PetscRandomCreate()`, `PetscRandomGetInterval()`
235 @*/
236 PetscErrorCode  PetscRandomSetInterval(PetscRandom r,PetscScalar low,PetscScalar high)
237 {
238   PetscFunctionBegin;
239   PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1);
240 #if defined(PETSC_USE_COMPLEX)
241   PetscCheck(PetscRealPart(low) <= PetscRealPart(high),PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"only low <= high");
242   PetscCheck(PetscImaginaryPart(low) <= PetscImaginaryPart(high),PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"only low <= high");
243 #else
244   PetscCheck(low < high,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"only low <= high: Instead %g %g",(double)low,(double)high);
245 #endif
246   r->low   = low;
247   r->width = high-low;
248   r->iset  = PETSC_TRUE;
249   PetscFunctionReturn(0);
250 }
251