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