1 /* copyright 2016 Apache 2 sddekit authors */
5 typedef struct one_step_data
{
11 static uint32_t one_step_get_nx(sd_sch
*s
) { return ((one_step_data
*)s
->ptr
)->nx
; }
13 void one_step_free(sd_sch
*sch
)
15 one_step_data
*d
= sch
->ptr
;
23 new_one_step(uint32_t nx
)
27 if ((d
= sd_malloc(sizeof(one_step_data
))) == NULL
) {
28 sd_err("memory alloc for one step sch failed.");
32 one_step_data zero
= { 0 };
35 err
= (d
->f
= sd_malloc(sizeof(double)*nx
)) == NULL
;
36 err
|= (d
->g
= sd_malloc(sizeof(double)*nx
)) == NULL
;
37 err
|= (d
->z
= sd_malloc(sizeof(double)*nx
)) == NULL
;
39 if (d
->f
!=NULL
) sd_free(d
->f
);
40 if (d
->g
!=NULL
) sd_free(d
->g
);
41 if (d
->z
!=NULL
) sd_free(d
->z
);
42 if (d
!= NULL
) sd_free(d
);
43 sd_err("memory alloc for one step sch failed.");
48 d
->sch
.get_nx
= &one_step_get_nx
;
49 d
->sch
.free
= &one_step_free
;
53 static sd_stat
one_step_apply(
54 sd_sch
*sch
, sd_hist
*hist
, sd_rng
*rng
, sd_sys
*sys
,
56 uint32_t nx
, double * restrict x
,
57 uint32_t nc
, double * restrict c
)
61 one_step_data
*d
= sch
->ptr
;
62 hist
->get(hist
, t
, c
);
63 sd_sys_in in
= { .t
= t
, .nx
= nx
, .x
= x
, .nc
= nc
, .i
= c
, .hist
= hist
, .rng
= rng
};
64 sd_sys_out out
= {.f
=d
->f
, .g
=d
->g
, .o
=c
};
65 if ((stat
=sys
->apply(sys
, &in
, &out
))!=SD_OK
)
67 rng
->fill_norm(rng
, nx
, d
->z
);
68 /* compute step & set history */
72 static sd_stat
id_apply(
73 sd_sch
*sch
, sd_hist
*hist
, sd_rng
*rng
, sd_sys
*sys
,
75 uint32_t nx
, double * restrict x
,
76 uint32_t nc
, double * restrict c
)
80 one_step_data
*d
= sch
->ptr
;
81 if ((stat
= one_step_apply(sch
, hist
, rng
, sys
, t
, dt
, nx
, x
, nc
, c
))!=SD_OK
)
84 x
[i
] = d
->f
[i
] + d
->g
[i
] * d
->z
[i
];
85 hist
->set(hist
, t
, c
);
89 static sd_stat
em_apply(
90 sd_sch
*sch
, sd_hist
*hist
, sd_rng
*rng
, sd_sys
*sys
,
92 uint32_t nx
, double * restrict x
,
93 uint32_t nc
, double * restrict c
)
98 one_step_data
*d
= sch
->ptr
;
99 if ((stat
= one_step_apply(sch
, hist
, rng
, sys
, t
, dt
, nx
, x
, nc
, c
)) != SD_OK
)
103 x
[i
] += dt
* d
->f
[i
] + sqrt_dt
* d
->g
[i
] * d
->z
[i
];
104 hist
->set(hist
, t
, c
);
109 sd_sch
*sd_sch_new_id(uint32_t nx
)
111 sd_sch
*new = new_one_step(nx
);
112 new->apply
= &id_apply
;
116 sd_sch
*sd_sch_new_em(uint32_t nx
)
118 sd_sch
*new = new_one_step(nx
);
119 new->apply
= &em_apply
;
124 typedef struct emc_data
{
127 double *f
, *g
, *z
, *eps
, lam
;
131 emc_get_nx(sd_sch
*sch
)
133 return ((emc_data
*)sch
->ptr
)->nx
;
136 double sd_sch_emc_get_lam(sd_sch
*sch
)
138 return ((emc_data
*)sch
)->lam
;
142 emc_free(sd_sch
*sch
)
144 emc_data
*d
= sch
->ptr
;
146 sd_err("returning early due to NULL instance pointer");
149 if (d
->f
!=NULL
) sd_free(d
->f
);
150 if (d
->g
!=NULL
) sd_free(d
->g
);
151 if (d
->z
!=NULL
) sd_free(d
->z
);
152 if (d
->eps
!=NULL
) sd_free(d
->eps
);
157 static sd_stat
emc_apply(
158 sd_sch
*sch
, sd_hist
*hist
, sd_rng
*rng
, sd_sys
*sys
,
160 uint32_t nx
, double * restrict x
,
161 uint32_t nc
, double * restrict c
)
166 emc_data
*d
= sch
->ptr
;
167 sd_sys_in in
= { .t
= t
, .nx
= nx
, .x
= x
, .nc
= nc
, .i
= c
, .hist
= hist
, .rng
= rng
};
168 sd_sys_out out
= {.f
=d
->f
, .g
=d
->g
, .o
=c
};
170 rng
->fill_norm(rng
, nx
, d
->z
);
171 if ((stat
= sys
->apply(sys
, &in
, &out
)) != SD_OK
)
174 d
->eps
[i
] = sqrt(d
->g
[i
] * d
->lam
) * d
->z
[i
];
175 d
->first_call
= false;
177 E
= exp(-d
->lam
* dt
);
178 rng
->fill_norm(rng
, nx
, d
->z
);
179 hist
->get(hist
, t
, c
);
180 if ((stat
= sys
->apply(sys
, &in
, &out
)) != SD_OK
)
182 for (i
=0; i
<nx
; i
++) {
183 x
[i
] += dt
* (d
->f
[i
] + d
->eps
[i
]);
185 d
->eps
[i
] += sqrt(d
->g
[i
] * d
->lam
* (1 - E
*E
)) * d
->z
[i
];
187 hist
->set(hist
, t
, c
);
191 sd_sch
* sd_sch_new_emc(uint32_t nx
, double lam
)
196 if ((d
= sd_malloc(sizeof(emc_data
))) == NULL
) {
197 sd_err("memory alloc for one step sch failed.");
201 emc_data zero
= { 0 };
205 err
= (sch
= sd_malloc(sizeof(sd_sch
))) == NULL
;
206 err
|= (d
->f
=sd_malloc(sizeof(double)*nx
))==NULL
;
207 err
|= (d
->g
=sd_malloc(sizeof(double)*nx
))==NULL
;
208 err
|= (d
->z
=sd_malloc(sizeof(double)*nx
))==NULL
;
209 err
|= (d
->eps
=sd_malloc(sizeof(double)*nx
))==NULL
;
211 if (d
->f
!=NULL
) sd_free(d
->f
);
212 if (d
->g
!=NULL
) sd_free(d
->g
);
213 if (d
->z
!=NULL
) sd_free(d
->z
);
214 if (d
->eps
!=NULL
) sd_free(d
->eps
);
215 if (d
!= NULL
) sd_free(d
);
216 if (sch
!= NULL
) sd_free(sch
);
217 sd_err("memory alloc for sch em color failed.");
220 d
->first_call
= true;
223 sch
->get_nx
= &emc_get_nx
;
224 sch
->apply
= &emc_apply
;
225 sch
->free
= &emc_free
;
229 typedef struct heun_data
{
231 double *fl
, *fr
, *gl
, *gr
, *z
, *xr
;
235 heun_get_nx(sd_sch
*sch
)
237 return ((heun_data
*)sch
->ptr
)->nx
;
241 heun_free(sd_sch
*sch
)
243 heun_data
*d
= sch
->ptr
;
254 static sd_stat
heun_apply(
255 sd_sch
*sch
, sd_hist
*hist
, sd_rng
*rng
, sd_sys
*sys
,
257 uint32_t nx
, double * restrict x
,
258 uint32_t nc
, double * restrict c
)
263 heun_data
*d
= sch
->ptr
;
264 sd_sys_in in
= { .t
= t
, .nx
= nx
, .x
= x
, .nc
= nc
, .i
= c
, .hist
= hist
, .rng
= rng
};
265 sd_sys_out out
= { .f
= d
->fl
, .g
= d
->gl
, .o
= c
};
267 hist
->get(hist
, t
, c
);
268 if ((stat
= sys
->apply(sys
, &in
, &out
)) != SD_OK
)
271 d
->xr
[i
] = x
[i
] + dt
* d
->fl
[i
];
272 hist
->set(hist
, t
, c
);
274 hist
->get(hist
, t
+ dt
, c
);
279 if ((stat
= sys
->apply(sys
, &in
, &out
)) != SD_OK
)
281 rng
->fill_norm(rng
, nx
, d
->z
);
284 x
[i
] += 0.5 * (dt
*(d
->fl
[i
] + d
->fr
[i
])
285 + sqrt_dt
*(d
->gl
[i
] + d
->gr
[i
])*d
->z
[i
]);
286 hist
->set(hist
, t
+ dt
, c
);
291 sd_sch_new_heun(uint32_t nx
)
296 if ((d
= sd_malloc(sizeof(heun_data
))) == NULL
)
298 sd_err("memory alloc for heun scheme failed.");
302 heun_data zero
= { 0 };
306 err
= (sch
= sd_malloc(sizeof(sd_sch
)))==NULL
;
307 err
|= (d
->fl
=sd_malloc(sizeof(double)*nx
))==NULL
;
308 err
|= (d
->fr
=sd_malloc(sizeof(double)*nx
))==NULL
;
309 err
|= (d
->gl
=sd_malloc(sizeof(double)*nx
))==NULL
;
310 err
|= (d
->gr
=sd_malloc(sizeof(double)*nx
))==NULL
;
311 err
|= (d
->z
=sd_malloc(sizeof(double)*nx
))==NULL
;
312 err
|= (d
->xr
=sd_malloc(sizeof(double)*nx
))==NULL
;
314 if (d
->fl
!=NULL
) sd_free(d
->fl
);;
315 if (d
->fr
!=NULL
) sd_free(d
->fr
);;
316 if (d
->gl
!=NULL
) sd_free(d
->gl
);;
317 if (d
->gr
!=NULL
) sd_free(d
->gr
);;
318 if (d
->z
!=NULL
) sd_free(d
->z
);;
319 if (d
->xr
!=NULL
) sd_free(d
->xr
);;
320 if (d
!= NULL
) sd_free(d
);
321 if (sch
!= NULL
) sd_free(sch
);
322 sd_err("memory alloc durong sch em init failed.");
326 sch
->get_nx
= &heun_get_nx
;
327 sch
->apply
= &heun_apply
;
328 sch
->free
= &heun_free
;