xref: /petsc/src/sys/classes/random/interface/random.c (revision 8fd105b637c659b5723a6c3ba83a32bc84aa12fb)
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 {
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    Notes:
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: `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: `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++) {
133       PetscCall((*r->ops->getvalue)(r,val+i));
134     }
135   } else PetscUseTypeMethod(r,getvalues ,n,val);
136   PetscCall(PetscObjectStateIncrease((PetscObject)r));
137   PetscFunctionReturn(0);
138 }
139 
140 /*@
141    PetscRandomGetValuesReal - Generates a sequence of real random numbers.  Call this after first calling
142    PetscRandomCreate().
143 
144    Not Collective
145 
146    Input Parameters:
147 +  r  - the random number generator context
148 -  n  - number of random numbers to generate
149 
150    Output Parameter:
151 .  val - the array to hold the values
152 
153    Level: intermediate
154 
155    Notes:
156    Use VecSetRandom() to set the elements of a vector to random numbers.
157 
158 .seealso: `PetscRandomCreate()`, `PetscRandomDestroy()`, `VecSetRandom()`, `PetscRandomGetValues()`
159 @*/
160 PetscErrorCode  PetscRandomGetValuesReal(PetscRandom r, PetscInt n, PetscReal *val)
161 {
162   PetscFunctionBegin;
163   PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1);
164   PetscValidType(r,1);
165   if (!r->ops->getvaluesreal) {
166     PetscInt i;
167     for (i = 0; i < n; i++) {
168       PetscCall((*r->ops->getvaluereal)(r,val+i));
169     }
170   } else PetscUseTypeMethod(r,getvaluesreal ,n,val);
171   PetscCall(PetscObjectStateIncrease((PetscObject)r));
172   PetscFunctionReturn(0);
173 }
174 
175 /*@
176    PetscRandomGetInterval - Gets the interval over which the random numbers
177    will be randomly distributed.  By default, this interval is [0,1).
178 
179    Not collective
180 
181    Input Parameter:
182 .  r  - the random number generator context
183 
184    Output Parameters:
185 +  low - The lower bound of the interval
186 -  high - The upper bound of the interval
187 
188    Level: intermediate
189 
190 .seealso: `PetscRandomCreate()`, `PetscRandomSetInterval()`
191 @*/
192 PetscErrorCode  PetscRandomGetInterval(PetscRandom r,PetscScalar *low,PetscScalar *high)
193 {
194   PetscFunctionBegin;
195   PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1);
196   if (low) {
197     PetscValidScalarPointer(low,2);
198     *low = r->low;
199   }
200   if (high) {
201     PetscValidScalarPointer(high,3);
202     *high = r->low+r->width;
203   }
204   PetscFunctionReturn(0);
205 }
206 
207 /*@
208    PetscRandomSetInterval - Sets the interval over which the random numbers
209    will be randomly distributed.  By default, this interval is [0,1).
210 
211    Not collective
212 
213    Input Parameters:
214 +  r  - the random number generator context
215 .  low - The lower bound of the interval
216 -  high - The upper bound of the interval
217 
218    Level: intermediate
219 
220    Notes:
221     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.
222     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.
223 
224 .seealso: `PetscRandomCreate()`, `PetscRandomGetInterval()`
225 @*/
226 PetscErrorCode  PetscRandomSetInterval(PetscRandom r,PetscScalar low,PetscScalar high)
227 {
228   PetscFunctionBegin;
229   PetscValidHeaderSpecific(r,PETSC_RANDOM_CLASSID,1);
230 #if defined(PETSC_USE_COMPLEX)
231   PetscCheck(PetscRealPart(low) <= PetscRealPart(high),PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"only low <= high");
232   PetscCheck(PetscImaginaryPart(low) <= PetscImaginaryPart(high),PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"only low <= high");
233 #else
234   PetscCheck(low < high,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"only low <= high: Instead %g %g",(double)low,(double)high);
235 #endif
236   r->low   = low;
237   r->width = high-low;
238   r->iset  = PETSC_TRUE;
239   PetscFunctionReturn(0);
240 }
241