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