xref: /petsc/src/sys/classes/random/interface/random.c (revision d5b43468fb8780a8feea140ccd6fa3e6a50411cc)
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(0);
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(0);
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     PetscInt i;
132     for (i = 0; i < n; i++) PetscCall((*r->ops->getvalue)(r, val + i));
133   } else PetscUseTypeMethod(r, getvalues, n, val);
134   PetscCall(PetscObjectStateIncrease((PetscObject)r));
135   PetscFunctionReturn(0);
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 @*/
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++) PetscCall((*r->ops->getvaluereal)(r, val + i));
166   } else PetscUseTypeMethod(r, getvaluesreal, n, val);
167   PetscCall(PetscObjectStateIncrease((PetscObject)r));
168   PetscFunctionReturn(0);
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 @*/
188 PetscErrorCode PetscRandomGetInterval(PetscRandom r, PetscScalar *low, PetscScalar *high)
189 {
190   PetscFunctionBegin;
191   PetscValidHeaderSpecific(r, PETSC_RANDOM_CLASSID, 1);
192   if (low) {
193     PetscValidScalarPointer(low, 2);
194     *low = r->low;
195   }
196   if (high) {
197     PetscValidScalarPointer(high, 3);
198     *high = r->low + r->width;
199   }
200   PetscFunctionReturn(0);
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 @*/
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(0);
237 }
238