File: test_multiroots.pro

package info (click to toggle)
gnudatalanguage 1.1.3-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 80,832 kB
  • sloc: cpp: 198,435; ansic: 47,740; sh: 691; python: 474; makefile: 149; xml: 69; f90: 28
file content (147 lines) | stat: -rw-r--r-- 5,585 bytes parent folder | download | duplicates (9)
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
; by Sylwester Arabas <slayoo (at) igf.fuw.edu.pl>
; testing newton() and broyden() by solving a moist isentrope eq. set

; usage:
; GDL> test_multiroots

function foo, x  
  return, [x[0]^2 + x[1]^3 - 9, x[0] + x[1] - 3]
end  

function constant, x
  return, [1, 2]
end

function pseudo_constant, x
  return, 1 + dindgen(2)
end

function buggy, x
  return, undefined_var_to_cause_an_error
end

; highly-obfuscated moist isentrope equation set below
; based on a file from the Univ. of Wyoming Cloud Parcel Model:
; http://www-das.uwyo.edu/~jsnider/parcel/parcel_model_2006_1/

function moist_isentrope_init
  common multiroots_constants, sratio_start, R, mw_h2o, mw_air, Ra, $
    Rv, tk_o, cp_air_o, ew_o, p_base, tk_base, epsilon, lv_o, $
    cw_h2o_o, cp_h2o_o

  ; physical constants
  R            = 8.3144d         ; [J/K/mol] ideal gas constant 
  mw_h2o       = 0.018015d       ; [kg/mol]  molecular weight of water 
  mw_air       = 0.028964d       ; [kg/mol]  molecular weight of air
  Ra           = R / mw_air      ; [J/K/kg]  dry air specific gas constant 
  Rv           = R / mw_h2o      ; [J/K/kg]  water vapour specific gas constant
  tk_o         = 273.15d         ; [K]       reference temperature : 0C
  cp_air_o     = 1005.2d         ; [J/K/kg]  specific heat capacity for dry air at 0C and 800 mb
  cp_h2o_o     = 1869.4d         ; [J/K/kg]  specific heat capacity for water v. at 0C and 800 mb
  cw_h2o_o     = 4218.0d         ; [J/kg/K]  water heat capacity 
  ew_o         = 610.7d          ; [Pa]      saturation vapor pressure of water vapor at the triple point 
  epsilon      = mw_h2o / mw_air ; [1]       molecular weight ratio
  lv_o         = 2500800.d       ; [J/kg]    latent heat of vapourisation of water

  ; other parameters
  sratio_start = 0.95d           ; [1]       initial supersaturation ratio
  p_base       = 90000d          ; [Pa]      cloud-base pressure
  tk_base      = 10 + 273.15     ; [K]       cloud-base temperature

  ; initial guess
  x0 = dblarr(10)
  x0[0] = .001                          ; [1]
  x0[1] = 100.                          ; [Pa]
  x0[2] = .001                          ; [1]
  x0[3] = 100.                          ; [Pa]
  x0[4] = p_base                        ; [Pa]     pressure 
  x0[5] = tk_base                       ; [K]      temperature
  x0[6] = cp_air_o * alog(tk_base/tk_o) ; [J/K/kg]                
  x0[7] = p_base                        ; [Pa]
  x0[8] = cp_air_o * alog(tk_base/tk_o) ; [J/K/kg]
  x0[9] = p_base                        ; [Pa]

  return, x0
end

function m_i_cp, T, p1, p2, x
  common multiroots_constants
  return, cp_air_o * alog(T/tk_o) - Ra * alog(p1) + x * (cp_h2o_o * alog(T/tk_o) - Rv * alog(p2)) 
end

function m_i_es, T
  common multiroots_constants
  return, ew_o * exp( $
    ((lv_o + (cw_h2o_o - cp_h2o_o) * tk_o) * (1.d / tk_o - 1.d / T) - (cw_h2o_o - cp_h2o_o) * alog(T / tk_o)) / Rv $
  )
end

function m_i_lm, licz, mian1, mian2
  common multiroots_constants
  return, epsilon * licz / (mian1 - mian2)
end

function moist_isentrope, x
  common multiroots_constants
  cwmcp = cw_h2o_o - cp_h2o_o
  f = dblarr(10)
  f[0] = x[0] - m_i_lm(x[1], p_base, x[1])
  f[1] = x[1] - m_i_es(tk_base)
  f[2] = x[2] - m_i_lm(x[3], x[4], x[3])
  f[3] = x[3] - m_i_es(x[5]) * sratio_start
  f[4] = x[6] - m_i_cp(tk_base, x[7], x[1], x[0])
  f[5] = x[8] - m_i_cp(x[5],    x[9], x[3], x[2])
  f[6] = x[0] - x[2]
  f[7] = x[6] - x[8]
  f[8] = p_base - x[7] - x[1]
  f[9] = x[4] - x[9] - x[3]
  return, f
end

pro test_multiroots

  x0 = moist_isentrope_init()

  ; testing newton & broyden parameters (defaults are: tolf=1d-4 & tolx=1d-7)
  ; (note: not all IDL stopping constraints are implemented in GDL)
  out = newton(x0, 'moist_isentrope', it=3)                        ; it=2 breaks in IDL & GDL 
  out = newton(x0, 'moist_isentrope', it=4, tolf=1d-9)             ; it=3 breaks in IDL & GDL
  out = newton(x0, 'moist_isentrope', it=2, tolf=1d-1)             ; it=1 breaks in IDL & GDL
  out = newton(x0, 'moist_isentrope', it=5, tolx=1d-9, tolf=1d-10) ; it=4 breaks in IDL
  out = newton(x0, 'moist_isentrope', it=2, tolx=1d-1)             ; it=1 breaks in IDL & GDL

  out = broyden(x0, 'moist_isentrope', it=5)                       ; it=4 breaks in IDL & GDL
  out = broyden(x0, 'moist_isentrope', it=6, tolf=1d-5)            ; it=5 breaks in IDL & GDL
  out = broyden(x0, 'moist_isentrope', it=4, tolf=1d-3)            ; it=3 breaks in IDL & GDL
  out = broyden(x0, 'moist_isentrope', it=6, tolx=1d-8, tolf=1d-99); it=5 breaks in IDL & GDL 
  out = broyden(x0, 'moist_isentrope', it=4, tolx=1d-5)            ; it=3 breaks in IDL & GDL

  ; testing the /DOUBLE keyword
  if 5 ne size(newton(x0,        'moist_isentrope'         ), /type) then begin
    message, "failed 1", /conti
    exit, status=1
  endif
  if 4 ne size(newton(float(x0), 'moist_isentrope'         ), /type) then begin
    message, "failed 2", /conti
    exit, status=1
  endif
  if 5 ne size(newton(float(x0), 'moist_isentrope', /double), /type) then begin
    message, "failed 3", /conti
    exit, status=1
  endif
  if 4 ne size(newton(long(x0),  'moist_isentrope'         ), /type) then begin
    message, "failed 4", /conti
  endif

  message, "tests of newton() and broyden() passed", /continue

  ; testing GSL error handler
  message, "testing the GSL error handler, a GSL warning message should appear below...", /continue
  out = broyden([3., 0.], 'foo')

  ; testing behaviour with costant-returning user func
  out = newton([1., 2.], 'pseudo_constant')
  out = newton([3., 0.], 'constant')

end