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