Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file symplectic_generic.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221# 1 "src/ode/symplectic/symplectic_generic.ml"(*
* OWL - OCaml Scientific and Engineering Computing
* OWL-ODE - Ordinary Differential Equation Solvers
*
* Copyright (c) 2019 Ta-Chu Kao <tck29@cam.ac.uk>
* Copyright (c) 2019 Marcello Seri <m.seri@rug.nl>
*)openTypesmoduleMake(M:Owl_types_ndarray_algodiff.Sigwithtypeelt=float)=structmoduleC=Common.Make(M)typef_t=M.arr*M.arr->float->M.arrmoduleM=structincludeM(* TODO: implement this in owl *)let(*$)=M.mul_scalarlet(+)=M.addendletpreparestepf(x0,p0)tspec()=lettspan,dt=matchtspecwith|T1{t0;duration;dt}->(t0,t0+.duration),dt|T2{tspan;dt}->tspan,dt|T3_->raiseOwl_exception.(NOT_IMPLEMENTED"T3 not implemented")inletstep=stepf~dtinC.symplectic_integrate~step~tspan~dt(x0,p0)letsymplectic_euler_s(f:f_t)~dt(xs,ps)t0=lett=t0+.dtinletfxs=f(xs,ps)tinletps'=M.(ps+(fxs*$dt))inletxs'=M.(xs+(ps'*$dt))in(xs',ps'),tletsymplectic_euler=(modulestructtypestate=M.arr*M.arrtypef=M.arr*M.arr->float->M.arrtypestep_output=(M.arr*M.arr)*floattypesolve_output=M.arr*M.arr*M.arrletstep=symplectic_euler_sletsolve=preparestepend:Solverwithtypestate=M.arr*M.arrandtypef=M.arr*M.arr->float->M.arrandtypestep_output=(M.arr*M.arr)*floatandtypesolve_output=M.arr*M.arr*M.arr)letleapfrog_s(f:f_t)~dt(xs,ps)t0=lett=t0+.dtinletfxs=f(xs,ps)tinletxs'=M.(xs+(ps*$dt)+(fxs*$(dt*.dt*.0.5)))inletfxs'=f(xs',ps)(t+.dt)inletps'=M.(ps+((fxs+fxs')*$(dt*.0.5)))in(xs',ps'),tletleapfrog=(modulestructtypestate=M.arr*M.arrtypef=M.arr*M.arr->float->M.arrtypestep_output=(M.arr*M.arr)*floattypesolve_output=M.arr*M.arr*M.arrletstep=leapfrog_sletsolve=preparestepend:Solverwithtypestate=M.arr*M.arrandtypef=M.arr*M.arr->float->M.arrandtypestep_output=(M.arr*M.arr)*floatandtypesolve_output=M.arr*M.arr*M.arr)(* For the values used in the implementations below
see Candy-Rozmus (https://www.sciencedirect.com/science/article/pii/002199919190299Z)
and https://en.wikipedia.org/wiki/Symplectic_integrator *)letsymint~coeffs(f:f_t)~dt=letsymint_step~coeffsf(xs,ps)tdt=List.fold_left(fun((xs,ps),t)(ai,bi)->letps'=M.(ps+(f(xs,ps)t*$(dt*.bi)))inletxs'=M.(xs+(ps'*$(dt*.ai)))inlett=t+.(dt*.ai)in(xs',ps'),t)((xs,ps),t)coeffsinfun(xs,ps)t->symint_step~coeffsf(xs,ps)tdtletleapfrog_c=[0.5,0.0;0.5,1.0]letpseudoleapfrog_c=[1.0,0.5;0.0,0.5]letruth3_c=[2.0/.3.0,7.0/.24.0;-2.0/.3.0,0.75;1.0,-1.0/.24.0]letruth4_c=letc=Owl.Maths.pow2.0(1.0/.3.0)in[0.5,0.0;0.5*.(1.0-.c),1.0;0.5*.(1.0-.c),-.c;0.5,1.0]|>List.map(fun(v1,v2)->v1/.(2.0-.c),v2/.(2.0-.c))let_leapfrog_s'f~dt=symint~coeffs:leapfrog_cf~dtletpseudoleapfrog_sf~dt=symint~coeffs:pseudoleapfrog_cf~dtletpseudoleapfrog=(modulestructtypestate=M.arr*M.arrtypef=M.arr*M.arr->float->M.arrtypestep_output=(M.arr*M.arr)*floattypesolve_output=M.arr*M.arr*M.arrletstep=pseudoleapfrog_sletsolve=preparestepend:Solverwithtypestate=M.arr*M.arrandtypef=M.arr*M.arr->float->M.arrandtypestep_output=(M.arr*M.arr)*floatandtypesolve_output=M.arr*M.arr*M.arr)letruth3_sf~dt=symint~coeffs:ruth3_cf~dtletruth3=(modulestructtypestate=M.arr*M.arrtypef=M.arr*M.arr->float->M.arrtypestep_output=(M.arr*M.arr)*floattypesolve_output=M.arr*M.arr*M.arrletstep=ruth3_sletsolve=preparestepend:Solverwithtypestate=M.arr*M.arrandtypef=M.arr*M.arr->float->M.arrandtypestep_output=(M.arr*M.arr)*floatandtypesolve_output=M.arr*M.arr*M.arr)letruth4_sf~dt=symint~coeffs:ruth4_cf~dtletruth4=(modulestructtypestate=M.arr*M.arrtypef=M.arr*M.arr->float->M.arrtypestep_output=(M.arr*M.arr)*floattypesolve_output=M.arr*M.arr*M.arrletstep=ruth4_sletsolve=preparestepend:Solverwithtypestate=M.arr*M.arrandtypef=M.arr*M.arr->float->M.arrandtypestep_output=(M.arr*M.arr)*floatandtypesolve_output=M.arr*M.arr*M.arr)(*
(* XXX:
We would like to do
pint = so.fsolve(
lambda pint: p - pint + 0.5*h*acc(x, pint, t0+i*h),
p
)[0]
xnew = x + h*pint
pnew = pint + 0.5*h*acc(xnew, pint, t0+(i+1)*h)
sol[i+1] = np.array((pnew, xnew))
but http://ocaml.xyz/apidoc/owl_M.arrhs_root.html does not seem
powerful enough for that in general.
*)
let leapfrog_implicit ~f y0 (t0, t1) dt =
let _, elts = M.shape y0 in
assert (M.s.is_even elts);
let steps = steps t0 t1 dt in
let sol = M.empty steps elts in
sol.${[[0]]}<- y0;
for idx = 1 to steps-1 do
(* TODO *)
()
done;
sol
*)(* ----- helper functions ----- *)letto_state_array?(axis=0)(dim1,dim2)xsps=letunpack=ifaxis=0thenM.to_rowselseifaxis=1thenM.to_colselseraiseOwl_exception.INDEX_OUT_OF_BOUNDinletxs=unpackxsinletps=unpackpsinifM.numelxs.(0)<>dim1*dim2thenraiseOwl_exception.(DIFFERENT_SHAPE([|M.numelxs.(0)|],[|dim1*dim2|]));ifM.numelps.(0)<>dim1*dim2thenraiseOwl_exception.(DIFFERENT_SHAPE([|M.numelps.(0)|],[|dim1*dim2|]));(Array.map(funx->M.reshapex[|dim1;dim2|])xs,Array.map(funp->M.reshapep[|dim1;dim2|])ps)end