Actual source code: random.c

  1: /*
  2:     This file contains routines for interfacing to random number generators.
  3:     This provides more than just an interface to some system random number
  4:     generator:

  6:     Numbers can be shuffled for use as random tuples

  8:     Multiple random number generators may be used

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

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

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

 20:   Not Collective

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

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

 28:   Level: intermediate

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

 33:   When PETSc is compiled for complex numbers this returns a complex number with random real and complex parts.
 34:   Use `PetscRandomGetValueReal()` to get a random real number.

 36:   To get a complex number with only a random real part, first call `PetscRandomSetInterval()` with a equal
 37:   low and high imaginary part. Similarly to get a complex number with only a random imaginary part call
 38:   `PetscRandomSetInterval()` with a equal low and high real part.

 40:   Example of Usage:
 41: .vb
 42:       PetscRandomCreate(PETSC_COMM_WORLD,&r);
 43:       PetscRandomGetValue(r,&value1);
 44:       PetscRandomGetValue(r,&value2);
 45:       PetscRandomGetValue(r,&value3);
 46:       PetscRandomDestroy(&r);
 47: .ve

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

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

 66:   Not Collective

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

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

 74:   Level: intermediate

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

 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

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

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

105:   Not Collective

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

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

114:   Level: intermediate

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

119:   When PETSc is compiled for complex numbers this returns an array of complex numbers with random real and complex parts.
120:   Use `PetscRandomGetValuesReal()` to get an array of random real numbers.

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

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

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

142:   Not Collective

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

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

151:   Level: intermediate

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

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

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

175:   Not Collective

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

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

184:   Level: intermediate

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

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

207:   Not Collective

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

214:   Level: intermediate

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

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

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