Actual source code: random.c


  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:

  7:     Numbers can be shuffled for use as random tuples

  9:     Multiple random number generators may be used

 11:     We are still not sure what interface we want here.  There should be
 12:     one to reinitialize and set the seed.
 13:  */

 15: #include <petsc/private/randomimpl.h>

 17: /*@
 18:    PetscRandomGetValue - Generates a random number.  Call this after first calling
 19:    `PetscRandomCreate()`.

 21:    Not Collective

 23:    Input Parameter:
 24: .  r  - the random number generator context

 26:    Output Parameter:
 27: .  val - the value

 29:    Level: intermediate

 31:    Notes:
 32:    Use `VecSetRandom()` to set the elements of a vector to random numbers.

 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.

 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.

 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

 50: .seealso: `PetscRandom`, `PetscRandomCreate()`, `PetscRandomDestroy()`, `VecSetRandom()`, `PetscRandomGetValueReal()`, `PetscRandomSetInterval()`
 51: @*/
 52: PetscErrorCode PetscRandomGetValue(PetscRandom r, PetscScalar *val)
 53: {
 54:   PetscFunctionBegin;
 57:   if (!r->ops->getvalue) PetscUseTypeMethod(r, getvalues, 1, val);
 58:   else PetscUseTypeMethod(r, getvalue, val);
 59:   PetscCall(PetscObjectStateIncrease((PetscObject)r));
 60:   PetscFunctionReturn(PETSC_SUCCESS);
 61: }

 63: /*@
 64:    PetscRandomGetValueReal - Generates a real random number.  Call this after first calling
 65:    `PetscRandomCreate()`.

 67:    Not Collective

 69:    Input Parameter:
 70: .  r  - the random number generator context

 72:    Output Parameter:
 73: .  val - the value

 75:    Level: intermediate

 77:    Note:
 78:    Use `VecSetRandom()` to set the elements of a vector to random numbers.

 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

 89: .seealso: `PetscRandom`, `PetscRandomCreate()`, `PetscRandomDestroy()`, `VecSetRandom()`, `PetscRandomGetValue()`
 90: @*/
 91: PetscErrorCode PetscRandomGetValueReal(PetscRandom r, PetscReal *val)
 92: {
 93:   PetscFunctionBegin;
 96:   if (!r->ops->getvaluereal) PetscUseTypeMethod(r, getvaluesreal, 1, val);
 97:   else PetscUseTypeMethod(r, getvaluereal, val);
 98:   PetscCall(PetscObjectStateIncrease((PetscObject)r));
 99:   PetscFunctionReturn(PETSC_SUCCESS);
100: }

102: /*@
103:    PetscRandomGetValues - Generates a sequence of random numbers.  Call this after first calling
104:    `PetscRandomCreate()`.

106:    Not Collective

108:    Input Parameters:
109: +  r  - the random number generator context
110: -  n  - number of random numbers to generate

112:    Output Parameter:
113: .  val - the array to hold the values

115:    Level: intermediate

117:    Notes:
118:    Use `VecSetRandom()` to set the elements of a vector to random numbers.

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.

123: .seealso: `PetscRandom`, `PetscRandomCreate()`, `PetscRandomDestroy()`, `VecSetRandom()`, `PetscRandomGetValue()`
124: @*/
125: PetscErrorCode PetscRandomGetValues(PetscRandom r, PetscInt n, PetscScalar *val)
126: {
127:   PetscFunctionBegin;
130:   if (!r->ops->getvalues) {
131:     PetscErrorCode (*const getvalue)(PetscRandom, PetscScalar *) = r->ops->getvalue;

133:     for (PetscInt i = 0; i < n; ++i) PetscCall(getvalue(r, val + i));
134:   } else PetscUseTypeMethod(r, getvalues, n, val);
135:   PetscCall(PetscObjectStateIncrease((PetscObject)r));
136:   PetscFunctionReturn(PETSC_SUCCESS);
137: }

139: /*@
140:    PetscRandomGetValuesReal - Generates a sequence of real random numbers.  Call this after first calling
141:    `PetscRandomCreate()`.

143:    Not Collective

145:    Input Parameters:
146: +  r  - the random number generator context
147: -  n  - number of random numbers to generate

149:    Output Parameter:
150: .  val - the array to hold the values

152:    Level: intermediate

154:    Note:
155:    Use `VecSetRandom()` to set the elements of a vector to random numbers.

157: .seealso: `PetscRandom`, `PetscRandomCreate()`, `PetscRandomDestroy()`, `VecSetRandom()`, `PetscRandomGetValues()`
158: @*/
159: PetscErrorCode PetscRandomGetValuesReal(PetscRandom r, PetscInt n, PetscReal *val)
160: {
161:   PetscFunctionBegin;
164:   if (!r->ops->getvaluesreal) {
165:     PetscInt i;
166:     for (i = 0; i < n; i++) PetscCall((*r->ops->getvaluereal)(r, val + i));
167:   } else PetscUseTypeMethod(r, getvaluesreal, n, val);
168:   PetscCall(PetscObjectStateIncrease((PetscObject)r));
169:   PetscFunctionReturn(PETSC_SUCCESS);
170: }

172: /*@
173:    PetscRandomGetInterval - Gets the interval over which the random numbers
174:    will be distributed.  By default, this interval is [0,1).

176:    Not Collective

178:    Input Parameter:
179: .  r  - the random number generator context

181:    Output Parameters:
182: +  low - The lower bound of the interval
183: -  high - The upper bound of the interval

185:    Level: intermediate

187: .seealso: `PetscRandom`, `PetscRandomCreate()`, `PetscRandomSetInterval()`
188: @*/
189: PetscErrorCode PetscRandomGetInterval(PetscRandom r, PetscScalar *low, PetscScalar *high)
190: {
191:   PetscFunctionBegin;
193:   if (low) {
195:     *low = r->low;
196:   }
197:   if (high) {
199:     *high = r->low + r->width;
200:   }
201:   PetscFunctionReturn(PETSC_SUCCESS);
202: }

204: /*@
205:    PetscRandomSetInterval - Sets the interval over which the random numbers
206:    will be distributed.  By default, this interval is [0,1).

208:    Not Collective

210:    Input Parameters:
211: +  r  - the random number generator context
212: .  low - The lower bound of the interval
213: -  high - The upper bound of the interval

215:    Level: intermediate

217:    Notes:
218:     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.

220:     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.

222: .seealso: `PetscRandomCreate()`, `PetscRandomGetInterval()`
223: @*/
224: PetscErrorCode PetscRandomSetInterval(PetscRandom r, PetscScalar low, PetscScalar high)
225: {
226:   PetscFunctionBegin;
228: #if defined(PETSC_USE_COMPLEX)
229:   PetscCheck(PetscRealPart(low) <= PetscRealPart(high), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "only low <= high");
230:   PetscCheck(PetscImaginaryPart(low) <= PetscImaginaryPart(high), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "only low <= high");
231: #else
232:   PetscCheck(low < high, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "only low <= high: Instead %g %g", (double)low, (double)high);
233: #endif
234:   r->low   = low;
235:   r->width = high - low;
236:   r->iset  = PETSC_TRUE;
237:   PetscFunctionReturn(PETSC_SUCCESS);
238: }