xref: /petsc/src/sys/classes/random/interface/randreg.c (revision 98d129c30f3ee9fdddc40fdbc5a989b7be64f888)
1 #include <petsc/private/randomimpl.h> /*I "petscsys.h" I*/
2 
3 PetscFunctionList PetscRandomList              = NULL;
4 PetscBool         PetscRandomRegisterAllCalled = PETSC_FALSE;
5 
6 /*@C
7   PetscRandomSetType - Builds a context for generating a particular type of random numbers.
8 
9   Collective
10 
11   Input Parameters:
12 + rnd  - The random number generator context
13 - type - The name of the random type
14 
15   Options Database Key:
16 . -random_type <type> - Sets the random type; use -help for a list
17                      of available types
18 
19   Level: intermediate
20 
21   Note:
22   See `PetscRandomType` for available random types (for instance, `PETSCRAND48`, `PETSCRAND`).
23 
24 .seealso: `PetscRandom`, `PetscRandomType`, `PetscRandomGetType()`, `PetscRandomCreate()`
25 @*/
26 PetscErrorCode PetscRandomSetType(PetscRandom rnd, PetscRandomType type)
27 {
28   PetscErrorCode (*r)(PetscRandom);
29   PetscBool match;
30 
31   PetscFunctionBegin;
32   PetscValidHeaderSpecific(rnd, PETSC_RANDOM_CLASSID, 1);
33   PetscCall(PetscObjectTypeCompare((PetscObject)rnd, type, &match));
34   if (match) PetscFunctionReturn(PETSC_SUCCESS);
35 
36   PetscCall(PetscFunctionListFind(PetscRandomList, type, &r));
37   PetscCheck(r, PetscObjectComm((PetscObject)rnd), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown random type: %s", type);
38 
39   PetscTryTypeMethod(rnd, destroy);
40   rnd->ops->destroy = NULL;
41 
42   PetscCall((*r)(rnd));
43   PetscCall(PetscRandomSeed(rnd));
44 
45   PetscCall(PetscObjectChangeTypeName((PetscObject)rnd, type));
46   PetscFunctionReturn(PETSC_SUCCESS);
47 }
48 
49 /*@C
50   PetscRandomGetType - Gets the type name (as a string) from the `PetscRandom`.
51 
52   Not Collective
53 
54   Input Parameter:
55 . rnd - The random number generator context
56 
57   Output Parameter:
58 . type - The type name
59 
60   Level: intermediate
61 
62 .seealso: `PetscRandom`, `PetscRandomType`, `PetscRandomSetType()`, `PetscRandomCreate()`
63 @*/
64 PetscErrorCode PetscRandomGetType(PetscRandom rnd, PetscRandomType *type)
65 {
66   PetscFunctionBegin;
67   PetscValidHeaderSpecific(rnd, PETSC_RANDOM_CLASSID, 1);
68   PetscAssertPointer(type, 2);
69   *type = ((PetscObject)rnd)->type_name;
70   PetscFunctionReturn(PETSC_SUCCESS);
71 }
72 
73 /*@C
74   PetscRandomRegister -  Adds a new `PetscRandom` implementation
75 
76   Not Collective
77 
78   Input Parameters:
79 + sname    - The name of a new user-defined creation routine
80 - function - The creation routine
81 
82   Level: advanced
83 
84   Notes:
85   `PetscRandomRegister()` may be called multiple times to add several user-defined random number generators
86 
87   For an example of the code needed to interface your own random number generator see src/sys/random/impls/rand/rand.c
88 
89   Example Usage:
90 .vb
91     PetscRandomRegister("my_rand",  MyPetscRandomtorCreate);
92 .ve
93 
94   Then, your random type can be chosen with the procedural interface via
95 .vb
96     PetscRandomCreate(MPI_Comm, PetscRandom *);
97     PetscRandomSetType(PetscRandom,"my_random_name");
98 .ve
99   or at runtime via the option
100 .vb
101     -random_type my_random_name
102 .ve
103 
104 .seealso: `PetscRandom`, `PetscRandomRegisterAll()`, `PetscRandomRegisterDestroy()`
105 @*/
106 PetscErrorCode PetscRandomRegister(const char sname[], PetscErrorCode (*function)(PetscRandom))
107 {
108   PetscFunctionBegin;
109   PetscCall(PetscRandomInitializePackage());
110   PetscCall(PetscFunctionListAdd(&PetscRandomList, sname, function));
111   PetscFunctionReturn(PETSC_SUCCESS);
112 }
113 
114 #if defined(PETSC_HAVE_RAND)
115 PETSC_EXTERN PetscErrorCode PetscRandomCreate_Rand(PetscRandom);
116 #endif
117 #if defined(PETSC_HAVE_DRAND48)
118 PETSC_EXTERN PetscErrorCode PetscRandomCreate_Rand48(PetscRandom);
119 #endif
120 #if defined(PETSC_HAVE_SPRNG)
121 PETSC_EXTERN PetscErrorCode PetscRandomCreate_Sprng(PetscRandom);
122 #endif
123 PETSC_EXTERN PetscErrorCode PetscRandomCreate_Rander48(PetscRandom);
124 #if defined(PETSC_HAVE_RANDOM123)
125 PETSC_EXTERN PetscErrorCode PetscRandomCreate_Random123(PetscRandom);
126 #endif
127 #if defined(PETSC_HAVE_CUDA)
128 PETSC_EXTERN PetscErrorCode PetscRandomCreate_CURAND(PetscRandom);
129 #endif
130 
131 /*@C
132   PetscRandomRegisterAll - Registers all of the implementations in the `PetscRandom` package.
133 
134   Not Collective
135 
136   Level: advanced
137 
138 .seealso: `PetscRandom`, `PetscRandomType`, `PetscRandomRegister()`, `PetscRandomRegisterDestroy()`
139 @*/
140 PetscErrorCode PetscRandomRegisterAll(void)
141 {
142   PetscFunctionBegin;
143   if (PetscRandomRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
144   PetscRandomRegisterAllCalled = PETSC_TRUE;
145 #if defined(PETSC_HAVE_RAND)
146   PetscCall(PetscRandomRegister(PETSCRAND, PetscRandomCreate_Rand));
147 #endif
148 #if defined(PETSC_HAVE_DRAND48)
149   PetscCall(PetscRandomRegister(PETSCRAND48, PetscRandomCreate_Rand48));
150 #endif
151 #if defined(PETSC_HAVE_SPRNG)
152   PetscCall(PetscRandomRegister(PETSCSPRNG, PetscRandomCreate_Sprng));
153 #endif
154   PetscCall(PetscRandomRegister(PETSCRANDER48, PetscRandomCreate_Rander48));
155 #if defined(PETSC_HAVE_RANDOM123)
156   PetscCall(PetscRandomRegister(PETSCRANDOM123, PetscRandomCreate_Random123));
157 #endif
158 #if defined(PETSC_HAVE_CUDA)
159   PetscCall(PetscRandomRegister(PETSCCURAND, PetscRandomCreate_CURAND));
160 #endif
161   PetscFunctionReturn(PETSC_SUCCESS);
162 }
163