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