Date: 2026-07-30T21:14:23+00:00

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: }