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