ASCOT5
Toggle main menu visibility
Loading...
Searching...
No Matches
simulate
mccc
mccc_wiener.c
Go to the documentation of this file.
1
9
#include <stdlib.h>
10
#include <stdio.h>
11
#include <
math.h
>
12
#include "
../../math.h
"
13
#include "
../../ascot5.h
"
14
#include "
../../consts.h
"
15
#include "
../../error.h
"
16
#include "
mccc_wiener.h
"
17
19
#ifdef _OPENACC
20
const
int
MCCC_EMPTY
= -1;
21
#pragma acc declare copyin(MCCC_EMPTY)
22
#elif defined(_OPENMP)
23
DECLARE_TARGET
24
const
int
MCCC_EMPTY
= -1;
25
DECLARE_TARGET_END
26
#else
27
const
int
MCCC_EMPTY
= -1;
28
#endif
29
36
void
mccc_wiener_initialize
(
mccc_wienarr
* w,
real
initime){
37
38
/* Initialize position instances indicating all slots are empty */
39
for
(
int
i=0; i<
MCCC_NSLOTS
; i++){
40
w->
nextslot
[i] =
MCCC_EMPTY
;
41
}
42
43
/* W(t_0) = 0 by the definition of the Wiener process */
44
w->
nextslot
[0] = 0;
45
w->
time
[0] = initime;
46
for
(
int
i = 0; i <
MCCC_NDIM
; i++){
47
w->
wiener
[i] = 0.0;
48
}
49
}
50
57
void
mccc_wiener_offload
(
mccc_wienarr
* w,
int
mrk_array_size) {
58
GPU_MAP_TO_DEVICE(w[0:mrk_array_size])
59
for
(
int
i = 0; i < mrk_array_size; i++) {
60
GPU_MAP_TO_DEVICE( w[i].nextslot[0:
MCCC_NSLOTS
] )
61
GPU_MAP_TO_DEVICE( w[i].time[0:
MCCC_NSLOTS
] )
62
GPU_MAP_TO_DEVICE( w[i].wiener[0:
MCCC_NDIM
*
MCCC_NSLOTS
] )
63
}
64
65
}
66
73
void
mccc_wiener_onload
(
mccc_wienarr
* w,
int
mrk_array_size) {
74
for
(
int
i = 0; i < mrk_array_size; i++) {
75
GPU_UPDATE_FROM_DEVICE( w[i].nextslot )
76
GPU_UPDATE_FROM_DEVICE( w[i].time )
77
GPU_UPDATE_FROM_DEVICE( w[i].wiener )
78
}
79
}
80
96
a5err
mccc_wiener_generate
(
mccc_wienarr
* w,
real
t,
int
* windex,
real
* rand5){
97
a5err
err = 0;
98
int
eidx;
/* Helper variables */
99
int
im, ip;
/* Indices of the Wiener processes for which tm < t < tp */
100
101
windex[0] = -1;
102
im = 0;
103
ip = -1;
/* There isn't necessarily a Wiener process tp > t */
104
105
/* Find im and ip */
106
int
idx = 0, breakloop = 0;
107
for
(
int
i=0; i<
MCCC_NSLOTS
; i++){
108
if
(!breakloop) {
109
if
(w->
nextslot
[idx] == idx){
110
/* Reached last process. Break loop */
111
breakloop = 1;
112
}
113
if
(w->
time
[idx] == t) {
114
/* Process already exists */
115
windex[0] = idx;
116
breakloop = 1;
117
}
118
else
{
119
if
(w->
time
[idx] < t ) {
120
/* Process i for which t_i < t */
121
im = idx;
122
}
123
if
(w->
time
[w->
nextslot
[idx]] > t) {
124
/* Process i for which t_i > t */
125
ip = w->
nextslot
[idx];
126
breakloop = 1;
127
}
128
}
129
idx = w->
nextslot
[idx];
130
}
131
}
132
133
if
(windex[0] == -1) {
134
/* Find an empty slot for the next process */
135
eidx = 0;
136
for
(
int
i=0; i<
MCCC_NSLOTS
; i++){
137
if
( w->
nextslot
[i] ==
MCCC_EMPTY
){
138
eidx = i;
139
i =
MCCC_NSLOTS
;
140
}
141
}
142
if
(eidx == 0){
143
/* It seems that we have exceeded capacity of the Wiener array
144
* Produce an error. */
145
err = error_raise(
ERR_WIENER_ARRAY
, __LINE__,
EF_MCCC_WIENER
);
146
}
147
148
if
(!err) {
149
if
(ip == -1){
150
/* There are no Wiener processes existing for tp > t. *
151
* The generated Wiener process then has a mean W(tm) and *
152
* variance t-tm. */
153
154
w->
nextslot
[eidx] = eidx;
155
w->
time
[eidx] = t;
156
for
(
int
i=0; i<
MCCC_NDIM
; i++){
157
w->
wiener
[i + eidx*
MCCC_NDIM
] = w->
wiener
[i + im*
MCCC_NDIM
]
158
+ sqrt(t-w->
time
[im])*rand5[i];
159
}
160
windex[0] = eidx;
161
w->
nextslot
[im] = eidx;
162
}
163
else
{
164
/* A Wiener process for tp > t exist. Generate a new process
165
* using the rules set by the Brownian bridge. The rules are:
166
*
167
* mean = W(tm) + ( W(ip)-W(im) )*(t-tm)/(tp-tm)
168
* variance = (t-tm)*(tp-t)/(tp-tm) */
169
w->
time
[eidx] = t;
170
for
(
int
i=0; i<
MCCC_NDIM
; i++){
171
w->
wiener
[i+eidx*
MCCC_NDIM
] =
172
w->
wiener
[i+im*
MCCC_NDIM
]
173
+ ( w->
wiener
[i + ip*
MCCC_NDIM
]
174
- w->
wiener
[i + im*
MCCC_NDIM
] )
175
* ( t - w->
time
[im] ) / ( w->
time
[ip] - w->
time
[im] )
176
+ sqrt( ( t - w->
time
[im] ) * ( w->
time
[ip] - t )
177
/ ( w->
time
[ip] - w->
time
[im] ) ) * rand5[i];
178
}
179
180
/* Sort new wiener process to its correct place */
181
w->
nextslot
[eidx] = ip;
182
w->
nextslot
[im] = eidx;
183
windex[0] = eidx;
184
}
185
}
186
}
187
188
return
err;
189
}
190
203
a5err
mccc_wiener_clean
(
mccc_wienarr
* w,
real
t){
204
a5err
err = 0;
205
int
idx, nextidx;
206
207
/* Remove processes W(t_i) until ti = t */
208
idx = 0;
209
real
ti = w->
time
[idx];
210
while
(ti < t){
211
nextidx = w->
nextslot
[idx];
212
if
(idx == nextidx){
213
err = error_raise(
ERR_WIENER_ARRAY
, __LINE__,
EF_MCCC_WIENER
);
214
t = ti;
// Breaks the loop
215
}
216
else
{
217
w->
nextslot
[idx] =
MCCC_EMPTY
;
218
idx = nextidx;
219
ti = w->
time
[idx];
220
}
221
}
222
223
if
(idx!=0 && !err){
224
/* Move W(t) process as the first one */
225
w->
nextslot
[0] = w->
nextslot
[idx];
226
227
w->
time
[0] = w->
time
[idx];
228
for
(
int
i=0; i<
MCCC_NDIM
; i++){
229
w->
wiener
[i] = w->
wiener
[idx*
MCCC_NDIM
+i];
230
}
231
232
/* Check if the process is also the last one */
233
if
( w->
nextslot
[idx] == idx ){
234
w->
nextslot
[0] = 0;
235
}
236
w->
nextslot
[idx] =
MCCC_EMPTY
;
237
}
238
239
return
err;
240
}
ascot5.h
Main header file for ASCOT5.
real
double real
Definition
ascot5.h:85
consts.h
Header file containing physical and mathematical constants.
error.h
Error module for ASCOT5.
a5err
unsigned long int a5err
Simulation error flag.
Definition
error.h:17
EF_MCCC_WIENER
@ EF_MCCC_WIENER
Definition
error.h:26
ERR_WIENER_ARRAY
@ ERR_WIENER_ARRAY
Definition
error.h:70
math.h
Header file for math.c.
MCCC_EMPTY
const int MCCC_EMPTY
Definition
mccc_wiener.c:27
mccc_wiener_generate
a5err mccc_wiener_generate(mccc_wienarr *w, real t, int *windex, real *rand5)
Generates a new Wiener process at a given time instant.
Definition
mccc_wiener.c:96
mccc_wiener_onload
void mccc_wiener_onload(mccc_wienarr *w, int mrk_array_size)
Onload data from the GPU.
Definition
mccc_wiener.c:73
mccc_wiener_clean
a5err mccc_wiener_clean(mccc_wienarr *w, real t)
Removes Wiener processes from the array that are no longer required.
Definition
mccc_wiener.c:203
mccc_wiener_offload
void mccc_wiener_offload(mccc_wienarr *w, int mrk_array_size)
Offload data to the accelerator.
Definition
mccc_wiener.c:57
mccc_wiener_initialize
void mccc_wiener_initialize(mccc_wienarr *w, real initime)
Initializes a struct that stores generated Wiener processes.
Definition
mccc_wiener.c:36
mccc_wiener.h
header file for mccc_wiener.c
MCCC_NSLOTS
#define MCCC_NSLOTS
Definition
mccc_wiener.h:21
MCCC_NDIM
#define MCCC_NDIM
Definition
mccc_wiener.h:15
mccc_wienarr
Struct for storing Wiener processes.
Definition
mccc_wiener.h:28
mccc_wienarr::time
real time[MCCC_NSLOTS]
Definition
mccc_wiener.h:33
mccc_wienarr::nextslot
int nextslot[MCCC_NSLOTS]
Definition
mccc_wiener.h:29
mccc_wienarr::wiener
real wiener[MCCC_NDIM *MCCC_NSLOTS]
Definition
mccc_wiener.h:35
Generated on
for ASCOT5 by
1.18.0