|
1 |
| - |
2 |
| -using Sundials |
| 1 | +using Sundials, Compat |
3 | 2 |
|
4 | 3 | ## f routine. Compute function f(t,y).
|
5 | 4 |
|
6 |
| -function f(t, y, ydot, user_data) |
7 |
| - y = Sundials.asarray(y) |
8 |
| - ydot = Sundials.asarray(ydot) |
| 5 | +function f(t, y_nv, ydot_nv, user_data) |
| 6 | + y = convert(Vector, y_nv) |
| 7 | + ydot = convert(Vector, ydot_nv) |
9 | 8 | ydot[1] = -0.04*y[1] + 1.0e4*y[2]*y[3]
|
10 | 9 | ydot[3] = 3.0e7*y[2]*y[2]
|
11 | 10 | ydot[2] = -ydot[1] - ydot[3]
|
12 |
| - return Int32(0) |
| 11 | + return Sundials.CV_SUCCESS |
13 | 12 | end
|
14 | 13 |
|
15 | 14 |
|
16 | 15 | ## g routine. Compute functions g_i(t,y) for i = 0,1.
|
17 | 16 |
|
18 |
| -function g(t, y, gout, user_data) |
19 |
| - y = Sundials.asarray(y) |
20 |
| - gout = Sundials.asarray(gout, (2,)) |
| 17 | +function g(t, y_nv, gout_ptr, user_data) |
| 18 | + y = convert(Vector, y_nv) |
| 19 | + gout = Sundials.asarray(gout_ptr, (2,)) |
21 | 20 | gout[1] = y[1] - 0.0001
|
22 | 21 | gout[2] = y[3] - 0.01
|
23 |
| - return Int32(0) |
| 22 | + return Sundials.CV_SUCCESS |
24 | 23 | end
|
25 | 24 |
|
26 | 25 | ## Jacobian routine. Compute J(t,y) = df/dy.
|
27 |
| - |
28 |
| -# Using StrPack |
29 |
| -# -- it works |
30 |
| -# -- it's clunky and dependent on Sundials version |
31 |
| -# Note: this is for Sundials v 2.4; the structure changed for v 2.5 |
32 |
| -# Because of this, I'm commenting this out. |
33 |
| -## using StrPack |
34 |
| -## @struct type J_DlsMat |
35 |
| -## typ::Int32 |
36 |
| -## M::Int32 |
37 |
| -## N::Int32 |
38 |
| -## ldim::Int32 |
39 |
| -## mu::Int32 |
40 |
| -## ml::Int32 |
41 |
| -## s_mu::Int32 |
42 |
| -## data::Ptr{Float64} |
43 |
| -## ldata::Int32 |
44 |
| -## cols::Ptr{Ptr{Float64}} |
45 |
| -## end |
46 |
| -# Note: Here is the (untested) structure for v 2.5 |
47 |
| -## using StrPack |
48 |
| -## @struct type J_DlsMat |
49 |
| -## typ::Int32 |
50 |
| -## M::Int |
51 |
| -## N::Int |
52 |
| -## ldim::Int |
53 |
| -## mu::Int |
54 |
| -## ml::Int |
55 |
| -## s_mu::Int |
56 |
| -## data::Ptr{Float64} |
57 |
| -## ldata::Int |
58 |
| -## cols::Ptr{Ptr{Float64}} |
59 |
| -## end |
60 |
| - |
61 |
| -# The following works if the code above is uncommented. |
62 |
| -function Jac(N, t, y, fy, Jptr, user_data, |
63 |
| - tmp1, tmp2, tmp3) |
64 |
| - y = Sundials.asarray(y) |
65 |
| - dlsmat = unpack(IOString(pointer_to_array(convert(Ptr{UInt8}, Jptr), |
66 |
| - (sum(map(sizeof, J_DlsMat.types))+10,))), |
67 |
| - J_DlsMat) |
68 |
| - J = pointer_to_array(unsafe_ref(dlsmat.cols), (int(neq), int(neq)), false) |
| 26 | +# broken -- needs a wrapper from Sundials._DlsMat to Matrix and Jac user function wrapper |
| 27 | +function Jac(N, t, ny, fy, Jptr, user_data, tmp1, tmp2, tmp3) |
| 28 | + y = convert(Vector, ny) |
| 29 | + dlsmat = unpack(IOString(@compat unsafe_wrap(convert(Ptr{UInt8}, Jptr), |
| 30 | + (sum(map(sizeof, Sundials._DlsMat))+10,), false)), |
| 31 | + Sundials._DlsMat) |
| 32 | + J = @compat unsafe_wrap(unsafe_ref(dlsmat.cols), (Int(neq), Int(neq)), false) |
69 | 33 | J[1,1] = -0.04
|
70 | 34 | J[1,2] = 1.0e4*y[3]
|
71 | 35 | J[1,3] = 1.0e4*y[2]
|
72 | 36 | J[2,1] = 0.04
|
73 | 37 | J[2,2] = -1.0e4*y[3] - 6.0e7*y[2]
|
74 | 38 | J[2,3] = -1.0e4*y[2]
|
75 | 39 | J[3,2] = 6.0e7*y[2]
|
76 |
| - return Int32(0) |
| 40 | + return Sundials.CV_SUCCESS |
77 | 41 | end
|
78 | 42 |
|
79 |
| -neq = 3 |
| 43 | +const neq = 3 |
80 | 44 |
|
81 |
| -t0 = 0.0 |
82 |
| -t1 = 0.4 |
83 |
| -tmult = 10.0 |
84 |
| -nout = 12 |
85 |
| -y = [1.0,0.0,0.0] |
86 |
| -reltol = 1e-4 |
87 |
| -abstol = [1e-8, 1e-14, 1e-6] |
| 45 | +const t0 = 0.0 |
| 46 | +const t1 = 0.4 |
| 47 | +const tmult = 10.0 |
| 48 | +const nout = 12 |
| 49 | +const y0 = [1.0, 0.0, 0.0] |
| 50 | +const reltol = 1e-4 |
| 51 | +const abstol = [1e-8, 1e-14, 1e-6] |
88 | 52 |
|
89 | 53 | cvode_mem = Sundials.CVodeCreate(Sundials.CV_BDF, Sundials.CV_NEWTON)
|
90 |
| -flag = Sundials.CVodeInit(cvode_mem, f, t0, y) |
91 |
| -flag = Sundials.CVodeSVtolerances(cvode_mem, reltol, abstol) |
92 |
| -flag = Sundials.CVodeRootInit(cvode_mem, 2, g) |
93 |
| -flag = Sundials.CVDense(cvode_mem, neq) |
94 |
| -## flag = Sundials.CVDlsSetDenseJacFn(cvode_mem, Jac) # works, but clunky, see above |
| 54 | +Sundials.@checkflag Sundials.CVodeInit(cvode_mem, f, t0, y0) |
| 55 | +Sundials.@checkflag Sundials.CVodeSVtolerances(cvode_mem, reltol, abstol) |
| 56 | +Sundials.@checkflag Sundials.CVodeRootInit(cvode_mem, 2, g) |
| 57 | +Sundials.@checkflag Sundials.CVDense(cvode_mem, neq) |
| 58 | +#Sundials.@checkflag Sundials.CVDlsSetDenseJacFn(cvode_mem, Jac) |
95 | 59 |
|
96 | 60 | iout = 0
|
97 | 61 | tout = t1
|
| 62 | +const t = [t0] |
98 | 63 |
|
99 |
| -rootsfound = round(Int32,[0, 0]) |
100 |
| -t = [t0] |
101 |
| - |
102 |
| -while true |
| 64 | +while iout < nout |
| 65 | + y = similar(y0) |
103 | 66 | flag = Sundials.CVode(cvode_mem, tout, y, t, Sundials.CV_NORMAL)
|
104 |
| - println("T = ", tout, ", Y = ", y) |
| 67 | + println("T=", tout, ", Y=", y) |
105 | 68 | if flag == Sundials.CV_ROOT_RETURN
|
106 |
| - flagr = Sundials.CVodeGetRootInfo(cvode_mem, pointer(rootsfound)) |
107 |
| - println("roots = ", rootsfound) |
108 |
| - end |
109 |
| - if flag == Sundials.CV_SUCCESS |
| 69 | + rootsfound = zeros(Cint, 2) |
| 70 | + Sundials.@checkflag Sundials.CVodeGetRootInfo(cvode_mem, rootsfound) |
| 71 | + println("roots=", rootsfound) |
| 72 | + elseif flag == Sundials.CV_SUCCESS |
110 | 73 | iout += 1
|
111 | 74 | tout *= tmult
|
112 | 75 | end
|
113 |
| - if iout == nout break end |
114 | 76 | end
|
0 commit comments