xref: /petsc/src/sys/classes/random/interface/random.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
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   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    Notes:
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: `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: `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    Notes:
151    Use VecSetRandom() to set the elements of a vector to random numbers.
152 
153 .seealso: `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 randomly 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: `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 randomly 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     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.
214 
215 .seealso: `PetscRandomCreate()`, `PetscRandomGetInterval()`
216 @*/
217 PetscErrorCode PetscRandomSetInterval(PetscRandom r, PetscScalar low, PetscScalar high) {
218   PetscFunctionBegin;
219   PetscValidHeaderSpecific(r, PETSC_RANDOM_CLASSID, 1);
220 #if defined(PETSC_USE_COMPLEX)
221   PetscCheck(PetscRealPart(low) <= PetscRealPart(high), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "only low <= high");
222   PetscCheck(PetscImaginaryPart(low) <= PetscImaginaryPart(high), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "only low <= high");
223 #else
224   PetscCheck(low < high, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "only low <= high: Instead %g %g", (double)low, (double)high);
225 #endif
226   r->low   = low;
227   r->width = high - low;
228   r->iset  = PETSC_TRUE;
229   PetscFunctionReturn(0);
230 }
231