File: odeiv.ml

package info (click to toggle)
ocamlgsl 0.3.5-3
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 3,444 kB
  • ctags: 2,901
  • sloc: ml: 7,956; ansic: 6,796; makefile: 303; sh: 87; awk: 13
file content (129 lines) | stat: -rw-r--r-- 3,194 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

let f mu t y f =
  f.(0) <- y.(1) ;
  f.(1) <- -. y.(0) -. mu *. y.(1) *. (y.(0) *. y.(0) -. 1.)

let jac mu t y dfdy dfdt =
  dfdy.{0, 0} <- 0. ;
  dfdy.{0, 1} <- 1. ;
  dfdy.{1, 0} <- -. 2. *. mu *. y.(0) *. y.(1) -. 1. ;
  dfdy.{1, 1} <- -. mu *. (y.(0) *. y.(0) -. 1.) ;
  dfdt.(0) <- 0. ;
  dfdt.(1) <- 0.

let integ mu =
  let step    = Gsl_odeiv.make_step Gsl_odeiv.RK8PD ~dim:2 in
  let control = Gsl_odeiv.make_control_y_new ~eps_abs:1e-6 ~eps_rel:0. in
  let evolve  = Gsl_odeiv.make_evolve 2 in

  let system = Gsl_odeiv.make_system (f mu) ~jac:(jac mu) 2 in
  let (t, t1, h, y) = (0., 100., 1e-6, [| 1.; 0. |]) in
  
  let rec loop data t h =
    if t < t1 then begin
      let (t, h) = 
	Gsl_odeiv.evolve_apply evolve control step system
	  ~t ~t1 ~h ~y in
      loop ((t, y.(0), y.(1)) :: data) t h
    end 
    else List.rev data
  in
  loop [] t h



let integ2 mu = 
  let step    = Gsl_odeiv.make_step Gsl_odeiv.RK8PD ~dim:2 in
  let control = Gsl_odeiv.make_control_y_new ~eps_abs:1e-6 ~eps_rel:0. in
  let evolve  = Gsl_odeiv.make_evolve 2 in

  let system = Gsl_odeiv.make_system (f mu) ~jac:(jac mu) 2 in

  let t1 = 100. in
  let y = [| 1.; 0. |] in
  let state = ref (0., 1e-2) in
  let rec loop ti y = function
    | (t, h) when t < ti ->
	let new_state = 
	  Gsl_odeiv.evolve_apply evolve control step system
	    ~t ~t1:ti ~h ~y in
	loop ti y new_state
    | state -> state
  in
  let data = ref [] in
  for i=1 to 100 do
    let ti = float i *. t1 /. 100. in
    state := loop ti y !state ;
    let (t, _) = !state in
    data := (t, y.(0), y.(1)) :: !data
  done ;
  !data




let integ3 mu = 
  let step   = Gsl_odeiv.make_step Gsl_odeiv.RK4 ~dim:2 in
  let system = Gsl_odeiv.make_system (f mu) ~jac:(jac mu) 2 in

  let t1 = 100. in
  let t = ref 0. in
  let h = 1e-2 in
  let y = [| 1.; 0. |] in
  let yerr     = Array.make 2 0. in
  let dydt_in  = Array.make 2 0. in
  let dydt_out = Array.make 2 0. in
  let dfdy = Gsl_matrix.create 2 2 in

  let data = ref [] in
  jac mu t y dfdy dydt_in ;
  while !t < t1 do
    Gsl_odeiv.step_apply step ~t:!t ~h ~y ~yerr ~dydt_in ~dydt_out system ;
    Array.blit dydt_out 0 dydt_in 0 2 ;
    t := !t +. h ;
    data := (!t, y.(0), y.(1)) :: !data ;
  done ;
  List.rev !data




let with_temp_file f =
  let tmp = Filename.temp_file "gnuplot_" ".tmp" in
  let res = try f tmp with exn -> Sys.remove tmp ; raise exn in
  Sys.remove tmp ; res

let gnuplot script =
  with_temp_file
    (fun tmp ->
      let script_c = open_out tmp in
      List.iter
	(fun s -> Printf.fprintf script_c "%s\n" s)
	script ;
      close_out script_c ;
      match Unix.system
	(Printf.sprintf "gnuplot %s" tmp) with
      | Unix.WEXITED 0 -> ()
      | _ -> prerr_endline "hmm, problems with gnuplot ?" )



let main () = 
  Gsl_error.init () ;
  if Array.length Sys.argv < 2 then exit 1 ;
  let data = 
    match int_of_string Sys.argv.(1) with
    | 3 -> integ3 10.
    | 2 -> integ2 10.
    | _ -> integ 10.
  in
  let points = List.map 
      (fun (_, x, y) -> Printf.sprintf "%.5f %.5f" x y) data in
  gnuplot (List.concat
	     [ [ "plot '-' with lines" ] ; 
	       points ; 
	       [ "e" ; "pause -1" ] ])
    

let _ = 
  main ()