PageRenderTime 72ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/filter.f

https://bitbucket.org/christophermarkstrickland/pyssm
FORTRAN Legacy | 3656 lines | 1381 code | 489 blank | 1786 comment | 105 complexity | b8a2dca2e237f97466547fdf677454f5 MD5 | raw file
  1. c Fortran 77 source code for the Python library PySSM
  2. c Copyright (C) 2010 Chris Strickland
  3. c This program is free software: you can redistribute it and/or modify
  4. c it under the terms of the GNU General Public License as published by
  5. c the Free Software Foundation, either version 2 or verion 3 of the
  6. c License.
  7. c This program is distributed in the hope that it will be useful,
  8. c but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. c GNU General Public License for more details.
  11. c You should have received a copy of the GNU General Public License
  12. c along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. c ------------------------------------------------------------------
  14. c Filtering and smoothing code + associated functions
  15. c ------------------------------------------------------------------
  16. c Note: Matrix Types [ std = 0, eye = 1, diag = 2, inv = 3, chol = 4 ]
  17. c If type = 3 then matrix is actually the inverse
  18. c If type = 4 then matrix is the cholesky decomposition
  19. c -----------------------------------------------------------------
  20. c fortran code to simulate disturbance vector for state space model
  21. c note fl = 1 if rvs on exit is qt & rvs, 0 otherwise
  22. c note if fl = 1 then gcqt should be gt, otherwise gcqt
  23. subroutine calc_st_er(gcqt,cqt,rvs,ser,fl,m,r,n,n_q,n_gq)
  24. implicit none
  25. integer m,r,n,t,n_q,n_gq,t_q,t_gq,timet,fl
  26. real*8 gcqt(m,r,n_gq),cqt(r,r,n_q),rvs(r,n),ser(m,n)
  27. real*8 alpha,beta
  28. c ----------------------
  29. cf2py intent(in) gcqt
  30. cf2py intent(in) cqt
  31. cf2py intent(inplace) rvs
  32. cf2py intent(inplace) ser
  33. cf2py intent(in) fl
  34. cf2py intent(in) m
  35. cf2py intent(in) r
  36. cf2py intent(in) b
  37. c ----------------------
  38. alpha = 1.0
  39. beta = 0.0
  40. c$omp parallel default(shared) private(t, t_q, t_gq)
  41. c$omp do schedule(static)
  42. do t = 1, n
  43. t_q = timet(n_q, t)
  44. t_gq = timet(n_gq, t)
  45. if (fl.eq.1) then
  46. call dtrmv('l','n','n',r,cqt(:,:,t_q),r,rvs(:,t),1)
  47. endif
  48. call dgemv('n',m,r,alpha,gcqt(:,:,t_gq),m,rvs(:,t),1,beta,
  49. + ser(:,t),1)
  50. enddo
  51. c$omp end do
  52. c$omp end parallel
  53. end
  54. c ------------------------------------------------------------------
  55. c fortran code to simulate disturbance vector for state space model
  56. c note fl = 1 if rvs on exit is qt & rvs, 0 otherwise
  57. c note if fl = 1 then gcqt should be gt, otherwise gcqt
  58. subroutine nt_calc_st_er(gcqt,cqt,rvs,ser,fl,m,r,n)
  59. implicit none
  60. integer m,r,n,fl
  61. real*8 gcqt(m,r),cqt(r,r),rvs(r,n),ser(m,n)
  62. real*8 alpha,beta
  63. c ----------------------
  64. cf2py intent(in) cqt
  65. cf2py intent(in) gcqt
  66. cf2py intent(inplace) rvs
  67. cf2py intent(inplace) ser
  68. cf2py intent(in) fl
  69. cf2py intent(in) m
  70. cf2py intent(in) r
  71. cf2py intent(in) b
  72. c ----------------------
  73. alpha = 1.0
  74. beta = 0.0
  75. if (fl.eq.1) then
  76. call dtrmm('l','l','n','n',r,n,alpha,cqt,r,rvs,r)
  77. endif
  78. call dgemm('n','n',m,n,r,alpha,gcqt,m,rvs,r,beta,ser,m)
  79. end
  80. c ------------------------------------------------------------------
  81. c **/** NEW OPENMP ADDED - UNTESTED **/**
  82. c fortran code for standard filtering and smoothing algorithms
  83. c simulates data for standard state space model
  84. subroutine simssm(y,zt,cht,tt,ser,rvm,av,n,p,m, n_z, n_t, n_h)
  85. implicit none
  86. integer n,p,m,t, t_t, t_z, n_z, n_t, t_h, n_h, timet
  87. real*8 y(p,n), zt(p,m,n_z), cht(p,p,n_h), tt(m,m,n_t)
  88. real*8 rvm(p,n), ser(m,n), av(m,n)
  89. real*8 alpha, beta
  90. c cht is the sqrt of the ht. recall that ht is a vector
  91. c ----------------------
  92. cf2py intent(inout) y
  93. cf2py intent(in) zt
  94. cf2py intent(in) ch
  95. cf2py intent(in) tt
  96. cf2py intent(in) rvm
  97. cf2py intent(in) ser
  98. cf2py intent(inout) av
  99. cf2py intent(in) n
  100. cf2py intent(in) p
  101. cf2py intent(in) m
  102. cf2py intent(in) n_z
  103. cf2py intent(in) n_t
  104. cf2py intent(in) n_h
  105. c ----------------------
  106. alpha = 1.0
  107. beta = 1.0
  108. do t = 1, n-1
  109. t_t = timet(n_t, t)
  110. c Initialise: av(t+1) = ser(t)
  111. call dcopy(m,ser(:,t),1,av(:,t+1),1)
  112. c Compute: av(t+1) = av(t+1) + tt * av(t)
  113. call dgemv('n',m,m,alpha,tt(:,:,t_t),m,av(:,t),1,beta,
  114. + av(:,t+1),1)
  115. enddo
  116. c$omp parallel default(shared) private(t, t_z, t_h, beta)
  117. c$omp do schedule(static)
  118. do t = 1, n
  119. t_z = timet(n_z, t)
  120. t_h = timet(n_h, t)
  121. c Compute: y(t) = cht(t) * rvm(t)
  122. beta = 0.0
  123. call dgemv('n',p,p,alpha,cht(:,:,t_h),p,rvm(:,t),1,beta,
  124. + y(:,t),1)
  125. c Compute: y(t) = y(t) + zt(t) * av(t)
  126. beta = 1.0
  127. call dgemv('n',p,m,alpha,zt(:,:,t_z),p,av(:,t),1, beta,
  128. + y(:,t),1)
  129. enddo
  130. c$omp end do
  131. c$omp end parallel
  132. end
  133. c ------------------------------------------------------------------
  134. c non time varying version that simulates data
  135. subroutine ntsimssm(y,zt,ch,tt,ser,rvm,av,n,p,m)
  136. integer n,p,m,t
  137. real*8 y(p,n), zt(p,m), ch(p,p), tt(m,m)
  138. real*8 rvm(p,n),av(m,n),ser(m,n)
  139. real*8 alpha, beta
  140. c cht is the sqrt of ht. recall that ht is a vector
  141. c ----------------------
  142. cf2py intent(inout) y
  143. cf2py intent(in) zt
  144. cf2py intent(in) ch
  145. cf2py intent(in) tt
  146. cf2py intent(in) ser
  147. cf2py intent(in) rvm
  148. cf2py intent(inout) av
  149. cf2py intent(in) n
  150. cf2py intent(in) p
  151. cf2py intent(in) m
  152. c ----------------------
  153. alpha = 1.0
  154. beta = 1.0
  155. do t = 1, n-1
  156. c Initialise: av(t+1) = ser(t)
  157. call dcopy(m,ser(:,t),1,av(:,t+1),1)
  158. c Compute: av(t+1) = av(t+1) + tt(t) * av(t)
  159. call dgemv('n',m,m,alpha,tt,m,av(:,t),1,beta, av(:,t+1),1)
  160. enddo
  161. beta = 0.0
  162. call dgemm('n','n',p,n,p,alpha,ch,p,rvm,p,beta,y,p)
  163. beta = 1.0
  164. call dgemm('n','n',p,n,m,alpha,zt,p,av,m,beta,y,p)
  165. end
  166. c ------------------------------------------------------------------
  167. c subroutine for filtering with the standard state SSM
  168. subroutine filter(y, z, h, tt, qt, nu, k, f, s, a, at, pt, ps,
  169. + mt, w, ls, lk, wl, ifo, ptt, ilike, pmiss, m, p, n, n_z, n_t,
  170. + n_q, n_h)
  171. integer m, p, n, t, i, ifo, ptt, info, ilike
  172. integer timet, n_z, n_t, n_q, t_z, t_t, t_q, t_h, pmiss(n)
  173. real*8 y(p,n), z(p,m,n_z), h(p,p,n_h), tt(m,m,n_t), qt(m,m,n_q)
  174. real*8 nu(p,n), k(m,p,n), s(p,m,n), ls(m,m,n), a(m,n)
  175. real*8 ps(m,m,n), mt(m,p), at(m), pt(m,m), f(p,p), w(m,m)
  176. real*8 alpha, beta, lk(*), wl(p), logdet, ddot, llike
  177. c ----------------------
  178. cf2py intent(in) y
  179. cf2py intent(in) z
  180. cf2py intent(in) h
  181. cf2py intent(in) tt
  182. cf2py intent(in) qt
  183. cf2py intent(inout) nu
  184. cf2py intent(inout) k
  185. cf2py intent(in) f
  186. cf2py intent(inout) s
  187. cf2py intent(inout) a
  188. cf2py intent(in) at
  189. cf2py intent(in) pt
  190. cf2py intent(inout) ps
  191. cf2py intent(in) mt
  192. cf2py intent(in) w
  193. cf2py intent(inplace) lk
  194. cf2py intent(inplace) ifo
  195. cf2py intent(in) pmiss
  196. cf2py intent(in) ptt
  197. cf2py intent(in) m
  198. cf2py intent(in) p
  199. cf2py intent(in) n
  200. cf2py intent(in) n_z
  201. cf2py intent(in) n_t
  202. cf2py intent(in) n_h
  203. cf2py intent(in) n_q
  204. c ----------------------
  205. c note if lk(1).lt.-1 then calculate likelihood and return in lk(1)
  206. ifo = 0
  207. llike = 0.0
  208. do t = 1, n
  209. t_z = timet(n_z, t)
  210. t_t = timet(n_t, t)
  211. t_q = timet(n_q, t)
  212. t_h = timet(n_h, t)
  213. c 1. Initialise: a(:,t) = at
  214. call dcopy(m,at,1,a(:,t),1)
  215. c -------------------------------------------------------------
  216. c 2. Initialise: ps(:,i,t) = pt(:,i)
  217. do i = 1, m
  218. call dcopy(m, pt(:,i), 1, ps(:,i,t), 1)
  219. enddo
  220. c -------------------------------------------------------------
  221. c 3. Compute: Nu(t) = Y(t) - Z(t) * a(t)
  222. c 3a. Initialise: nu(:,t) = y(:,t)
  223. if (pmiss(t).eq.0) then
  224. !data not missing
  225. call dcopy(p, y(:,t), 1, nu(:,t), 1)
  226. c 3b. Compute: nu = nu - z * at
  227. alpha = -1.0
  228. beta = 1.0
  229. call dgemv('n',p,m,alpha,z(:,:,t_z),p,at,1,beta,nu(:,t),1)
  230. c -------------------------------------------------------------
  231. c 4. Compute: m(t) = P(t)*Z(t)' [i.e. (m,p) = (m,m) *(m,p) ]
  232. alpha = 1.0
  233. beta = 0.0
  234. call dgemm('n','t',m,p,m,alpha,pt,m,z(:,:,t_z),p,beta,mt,
  235. + m)
  236. c -------------------------------------------------------------
  237. c 5. Compute: F(t) = Z(t)*m(t) + H(t) [i.e. (p,p) = (p,m)*(m,p) ]
  238. c 5a. Initialise: f(:,i) = h(:,i,t_h)
  239. !column of y not missing
  240. do i = 1, p
  241. call dcopy(p, h(:,i,t_h), 1, f(:,i), 1)
  242. enddo
  243. c 5b. Compute: f = f + z * mt
  244. beta = 1.0
  245. call dgemm('n','n',p,p,m,alpha,z(:,:,t_z),p,mt,m,beta,f,p)
  246. ! print *, "ft =", f
  247. c -------------------------------------------------------------
  248. c 6. Compute: S(t) = inv(F(t))*Z(t) [i.e. solve F.S = Z ]
  249. c 6a. Initialise: s = z
  250. do i = 1, m
  251. call dcopy(p, z(:,i,t_z), 1, s(:,i,t), 1)
  252. enddo
  253. c 6b. Solve: f * x = s [Note: store x in s] [i.e. (p,p) *(p,m) = (p,m) ]
  254. call dposv('u',p,m,f,p,s(:,:,t),p,info)
  255. if (info.ne.0) then
  256. ifo = 1
  257. endif
  258. !else
  259. !column of y missing so set S(t)=0
  260. ! do i=1,m
  261. ! do j=1,m
  262. ! S(i,j,t)=0.0
  263. ! enddo
  264. ! enddo
  265. c ------------------------------------------------------------
  266. if (ilike.eq.0) then
  267. c Compute: logdet = 2.0 * sum(i: log(f(i,i))
  268. logdet = 0.0
  269. do i = 1, p
  270. logdet = logdet + log(f(i,i))
  271. enddo
  272. logdet = 2.0 * logdet
  273. c Initialise: wl = nu(:,t)
  274. call dcopy(p, nu(:,t), 1, wl, 1)
  275. c Solve: f.x = wl (i.e. Compute: x = inv[f]*wl ) (Note: store x as wl)
  276. call dtrsv('u','t','n',p,f,p,wl,1)
  277. c Subtract: -(0.5 * nu^2) - (0.5 * logdet)
  278. llike = llike - 0.5 * (logdet + ddot(p,wl,1,wl,1))
  279. endif
  280. c -------------------------------------------------------------
  281. c 7. Compute: W(t) = T(t)*P(t)
  282. beta = 0.0
  283. if (ptt.eq.0) then
  284. c 7a. Compute: w = tt * pt
  285. call dgemm('n','n', m, m, m, alpha, tt(:,:,t_t),
  286. + m, pt, m, beta, w, m)
  287. else
  288. c 7b. Initialise: w = pt
  289. do i = 1, m
  290. call dcopy(m,pt(:,i),1,w(:,i),1)
  291. enddo
  292. endif
  293. c -------------------------------------------------------------
  294. c 8. Compute: K(t) = W(t) * S(t)'
  295. call dgemm('n','t',m,p,m,alpha,w,m,s(:,:,t),p,beta,
  296. + k(:,:,t),m)
  297. ! print *, "kt =", k(:,:,t)
  298. c -------------------------------------------------------------
  299. c 9. Compute: L(t) = T(t) - K(t)*Z(t) [i.e. (m,m) = (m,p) * (p,m) ]
  300. c 9a. Initialise: ls(:,i,t) = tt(:,t,t_t)
  301. do i = 1, m
  302. call dcopy(m,tt(:,i,t_t),1,ls(:,i,t),1)
  303. enddo
  304. c 9b. Compute: ls = ls - k(:,:,t) * z(:,:,t_z) [i.e. (m,m) = (m,p) * (p,m) ]
  305. alpha = -1.0
  306. beta = 1.0
  307. call dgemm('n','n',m,m,p,alpha,k(:,:,t),m,z(:,:,t_z),p,
  308. + beta,
  309. + ls(:,:,t),m)
  310. ! print *, "lt =", ls(:,:,t)
  311. c -------------------------------------------------------------
  312. c 10. Compute: a(t+1) = T(t)*a(t) + K(t)*nu(t)
  313. alpha = 1.0
  314. beta = 0.0
  315. if (ptt.eq.0) then
  316. c 10a. Compute: at = tt(:,:,t_t) * a(:,t)
  317. call dgemv('n',m,m,alpha,tt(:,:,t_t),m,a(:,t),1,beta,
  318. + at,1)
  319. else
  320. c 10a. Initialise: at = a(:,t)
  321. call dcopy(m, a(:,t), 1, at, 1)
  322. endif
  323. c 10b. Compute: at = at + k(:,:,t) * nu(:,t) [i.e. (m) = (m,p) *(p) ]
  324. beta = 1.0
  325. call dgemv('n',m,p,alpha,k(:,:,t),m,nu(:,t),1,beta,at,1)
  326. beta = 0.0
  327. ! print *, "at =", at
  328. else
  329. !Compute L(t)=T(t)
  330. do i = 1, m
  331. call dcopy(m,tt(:,i,t_t),1,ls(:,i,t),1)
  332. enddo
  333. c 10b. Compute a(t+1) = T(t)*a(t)
  334. alpha = 1.0
  335. beta = 0.0
  336. if (ptt.eq.0) then
  337. c 10a. Compute: at = tt(:,:,t_t) * a(:,t)
  338. call dgemv('n',m,m,alpha,tt(:,:,t_t),m,a(:,t),1,beta,
  339. + at,1)
  340. else
  341. c 10a. Initialise: at = a(:,t)
  342. call dcopy(m, a(:,t), 1, at, 1)
  343. endif
  344. c 10b. Compute: W(t) = T(t)*P(t)
  345. beta = 0.0
  346. if (ptt.eq.0) then
  347. c Compute: w = tt * pt
  348. call dgemm('n','n', m, m, m, alpha, tt(:,:,t_t),
  349. + m, pt, m, beta, w, m)
  350. else
  351. c Initialise: w = pt
  352. do i = 1, m
  353. call dcopy(m,pt(:,i),1,w(:,i),1)
  354. enddo
  355. endif
  356. endif
  357. c -------------------------------------------------------------
  358. c 11. Compute: P(t+1) = W(t)*L(t)' + Q(t)
  359. c call dgemm('n','n',m,m,m,alpha,tt(:,:,t),m,pt,m,beta,w,m)
  360. c 11a. Initialise: pt = qt(:,:,t_q)
  361. do i = 1, m
  362. call dcopy(m, qt(:,i,t_q), 1, pt(:,i), 1)
  363. enddo
  364. c 11b. Compute: pt = pt + w * ls' where w = tt * pt
  365. c [i.e. (m,m) = (m,m) * (m,m) * (m,m) ]
  366. beta = 1.0
  367. call dgemm('n','t',m,m,m,alpha,w,m,ls(:,:,t),m,beta,pt,m)
  368. enddo
  369. c -------------------------------------------------------------
  370. lk(1)=llike
  371. end
  372. c ------------------------------------------------------------------
  373. c subroutine for filtering with the standard non time varying state SSM
  374. subroutine ntfilter(y,z,h,tt,qt,nu,k,f,s,a,at,pt,ps,mt,w,ls,lt,
  375. + lk,wl,ifo,ilike,m,p,n)
  376. integer m,p,n,t,i,ifo,info,chk,indr,lt,ilike
  377. real*8 y(p,n),z(p,m),h(p,p),tt(m,m),qt(m,m),lk,wl(p)
  378. real*8 nu(p,n),k(m,p,n),s(p,m,n),ls(m,m,n),a(m,n)
  379. real*8 ps(m,m,n),mt(m,p),at(m),pt(m,m),f(p,p),w(m,m)
  380. real*8 alpha, beta,fnorm, tol,logdet,llike,ddot, temp
  381. c ----------------------
  382. cf2py intent(in) y
  383. cf2py intent(in) z
  384. cf2py intent(in) h
  385. cf2py intent(in) tt
  386. cf2py intent(in) qt
  387. cf2py intent(inplace) nu
  388. cf2py intent(inplace) k
  389. cf2py intent(in) f
  390. cf2py intent(inplace) s
  391. cf2py intent(inplace) a
  392. cf2py intent(in) at
  393. cf2py intent(in) pt
  394. cf2py intent(inplace) ps
  395. cf2py intent(in) mt
  396. cf2py intent(in) w
  397. cf2py intent(inout) lk
  398. cf2py intent(in) wl
  399. cf2py intent(inout) ifo
  400. cf2py intent(inout) lt
  401. cf2py intent(in) m
  402. cf2py intent(in) p
  403. cf2py intent(in) n
  404. c ----------------------
  405. ifo = 0
  406. tol = 1E-10
  407. chk = 10
  408. indr = 0 ! Indicator for steady state
  409. lt = n+1
  410. llike = 0.0
  411. do t = 1, n
  412. c Not yet reached steady state:
  413. if (indr.eq.0) then
  414. c 1. Initialise: a(:,t) = at
  415. call dcopy(m,at,1,a(:,t),1)
  416. c ------------------------------
  417. c 2. Initialise: ps(:,:,t) = pt
  418. do i = 1, m
  419. call dcopy(m,pt(:,i),1,ps(:,i,t),1)
  420. enddo
  421. c ------------------------------
  422. c 3. Compute: Nu(t) = Y(t) - Z(t)*a(t)
  423. c 3a. Initialise nu(:,t) = y(:, t)
  424. call dcopy(p, y(:,t), 1, nu(:,t), 1)
  425. c 3b. Compute: nu(:,t) = nu(:,t) - z * at
  426. alpha = -1.0
  427. beta = 1.0
  428. call dgemv('n',p,m,alpha,z,p,at,1,beta,nu(:,t),1)
  429. c ------------------------------
  430. c 4. Compute: m(t) = P(t)*Z(t)' , i.e. mt = pt * z
  431. alpha = 1.0
  432. beta = 0.0
  433. call dgemm('n','t',m,p,m,alpha,pt,m,z,p,beta,mt,m)
  434. c ------------------------------
  435. c 5. Compute: F(t) = Z(t)*m(t) + H(t)
  436. c 5a. Initialise f(:,i) = h(:,i)
  437. do i = 1, p
  438. call dcopy(p,h(:,i),1,f(:,i),1)
  439. enddo
  440. c 5b. Compute: f = f + z*mt
  441. beta = 1.0
  442. call dgemm('n','n',p,p,m,alpha,z,p,mt,m,beta,f,p)
  443. c ------------------------------
  444. c 6. Compute: F(t)*S(t) = Z(t); solve for S(t)=inv(F(t))*Z(t)
  445. c 6a.Initialise s(:,:,t) = z
  446. do i = 1, m
  447. call dcopy(p,z(:,i),1,s(:,i,t),1)
  448. enddo
  449. c 6b. Solve f . x = s and set s = x
  450. call dposv('u',p,m,f,p,s(:,:,t),p,info)
  451. if (info.ne.0) then
  452. ifo = 1
  453. endif
  454. ! if(t.eq.1) then
  455. ! print *, "S = ", s(:,:,t)
  456. ! endif
  457. c ------------------------------
  458. beta = 0.0
  459. if (ilike.eq.0) then
  460. logdet = 0.0
  461. do i = 1, p
  462. logdet = logdet + log(f(i,i))
  463. enddo
  464. logdet = 2.0 * logdet
  465. c Initialise wl = nu(:,t)
  466. call dcopy(p,nu(:,t),1,wl,1)
  467. call dtrsv('u','t','n',p,f,p,wl,1)
  468. llike = llike-0.5*(logdet+ddot(p,wl,1,wl,1))
  469. c call dcopy(p,nu(:,t),1,wl,1)
  470. c call dtrsm('l','u','t','n',p,1,alpha,f,p,wl,p)
  471. c call dtrsm('l','u','n','n',p,1,alpha,f,p,wl,p)
  472. c llike = llike-0.5*(logdet+ddot(p,wl,1,nu(:,t),1))
  473. endif
  474. c ------------------------------
  475. c 7. Compute: W(t) = T(t)*P(t), i.e. w = tt * pt
  476. call dgemm('n','n',m,m,m,alpha,tt,m,pt,m,beta,w,m)
  477. c ------------------------------
  478. c 8. Compute: K(t) = W(t)*S(t)', i.e. k = w * s
  479. call dgemm('n','t',m,p,m,alpha,w,m,s(:,:,t),p,beta,
  480. + k(:,:,t),m)
  481. ! if(t.eq.1) then
  482. ! print *, "K = ", k(:,:,t)
  483. ! endif
  484. c ------------------------------
  485. c 9. Compute: L(t)= T(t) - K(t)*Z(t)
  486. c 9a. Initialise ls(:,:,t) = tt
  487. do i = 1, m
  488. call dcopy(m,tt(:,i),1,ls(:,i,t),1)
  489. enddo
  490. c 9b. Compute: ls = ls - k * z
  491. alpha = -1.0
  492. beta = 1.0
  493. call dgemm('n','n',m,m,p,alpha,k(:,:,t),m,z,p,beta,
  494. + ls(:,:,t),m)
  495. ! if(t.eq.1) then
  496. ! print *, "L = ", ls(:,:,t)
  497. ! endif
  498. c ------------------------------
  499. c Monitor convergence to steady state
  500. if(t.gt.chk) then
  501. if(mod(t,chk).eq.0) then
  502. temp = fnorm(ps(:,:,t),ps(:,:,t-chk),m,m)
  503. if(temp.lt.tol) then
  504. indr = 1
  505. lt = t
  506. endif
  507. endif
  508. endif
  509. c ------------------------------
  510. c 10. Compute: a(t+1)= T(t)*a(t) + K(t)*nu(t)
  511. c 10a. Compute: at = tt * a
  512. alpha = 1.0
  513. beta = 0.0
  514. call dgemv('n',m,m,alpha,tt,m,a(:,t),1,beta,at,1)
  515. c 10b. Compute: at = at + k * nu
  516. beta = 1.0
  517. call dgemv('n',m,p,alpha,k(:,:,t),m,nu(:,t),1,beta,at,1)
  518. c ------------------------------
  519. c 11. Compute: P(t+1)= W(t)*L(t)' + Q(t)
  520. c 11a. Initialise: pt = qt
  521. do i = 1, m
  522. call dcopy(m,qt(:,i),1,pt(:,i),1)
  523. enddo
  524. c 11b. Compute: pt = pt + w*ls
  525. beta = 1.0
  526. call dgemm('n','t',m,m,m,alpha,w,m,ls(:,:,t),m,beta,pt,m)
  527. c Reached steady state:
  528. else
  529. call dcopy(m,at,1,a(:,t),1)
  530. c do i=1,m
  531. c call dcopy(m,pt(:,i),1,ps(:,i,t),1)
  532. c enddo
  533. c ------------------------------
  534. c 12. Compute: Nu(t)= Y(t) - Z(t)*a(t)
  535. c 12a. Initialise: nu = y
  536. call dcopy(p,y(:,t),1,nu(:,t),1)
  537. c 12b. Compute: nu = nu + z * at
  538. alpha = -1.0
  539. beta = 1.0
  540. call dgemv('n',p,m,alpha,z,p,at,1,beta,nu(:,t),1)
  541. ! if(t.eq.1) then
  542. ! print *, "nu = ", nu(:,t)
  543. ! endif
  544. c ----------------------------------------
  545. if (ilike.eq.0) then
  546. call dcopy(p,nu(:,t),1,wl,1)
  547. call dtrsv('u','t','n',p,f,p,wl,1)
  548. llike = llike - 0.5*(logdet+ddot(p,wl,1,wl,1))
  549. c call dtrsm('l','u','t','n',p,1,alpha,f,p,wl,p)
  550. c call dtrsm('l','u','n','n',p,1,alpha,f,p,wl,p)
  551. c llike=llike-0.5*(logdet+ddot(p,wl,1,nu(:,t),1))
  552. endif
  553. c ------------------------------
  554. c 13. Compute: a(t+1)= T(t)*a(t)+K(t)*nu(t)
  555. c 13a. Compute: at = tt * a
  556. alpha = 1.0
  557. beta = 0.0
  558. call dgemv('n',m,m,alpha,tt,m,a(:,t),1,beta,at,1)
  559. c ------------------------------
  560. c 14. Compute: at = at + k * nu
  561. c Note: lt replaces t in k, i.e. k(:,:,lt)
  562. beta = 1.0
  563. call dgemv('n',m,p,alpha,k(:,:,lt),m,nu(:,t),1,beta,at,1)
  564. beta = 0.0
  565. c ------------------------------
  566. c P(t+1) = W(t)*L(t)' + Q(t)
  567. do i=1,m
  568. call dcopy(m,qt(:,i),1,pt(:,i),1)
  569. enddo
  570. beta = 1.0
  571. call dgemm('n','t',m,m,m,alpha,w,m,ls(:,:,lt),m,beta,pt,m)
  572. endif
  573. enddo
  574. lk = llike
  575. end
  576. c ------------------------------------------------------------------
  577. c benchmark subroutine for filtering with the standard state SSM
  578. subroutine bfilter(y,z,h,tt,qt,nu,k,f,fi,wz,a,at,pt,ps,mt,w,ls,
  579. + ifo, m, p, n, n_h, n_t, n_q, n_z)
  580. integer m,p,n,t,i,ifo, info
  581. integer n_h, n_t, n_q, n_z, t_t, t_z, t_h, t_q, timet
  582. real*8 y(p,n),z(p,m,n_z),h(p,p,n_h),tt(m,m,n_t),qt(m,m,n_q)
  583. real*8 nu(p,n),k(m,p,n),fi(p,p,n),ls(m,m,n),a(m,n),wz(m,p)
  584. real*8 ps(m,m,n),mt(m,p),at(m),pt(m,m),f(p,p),w(m,m)
  585. real*8 alpha, beta
  586. c ----------------------
  587. cf2py intent(in) y
  588. cf2py intent(in) z
  589. cf2py intent(in) h
  590. cf2py intent(in) tt
  591. cf2py intent(in) qt
  592. cf2py intent(inout) nu
  593. cf2py intent(inout) k
  594. cf2py intent(in) f
  595. cf2py intent(inout) fi
  596. cf2py intent(in) wz
  597. cf2py intent(inout) s
  598. cf2py intent(inout) a
  599. cf2py intent(in) at
  600. cf2py intent(in) pt
  601. cf2py intent(inout) ps
  602. cf2py intent(in) mt
  603. cf2py intent(in) w
  604. cf2py intent(inout) ifo
  605. cf2py intent(in) m
  606. cf2py intent(in) p
  607. cf2py intent(in) n
  608. cf2py intent(in) n_z
  609. cf2py intent(in) n_t
  610. cf2py intent(in) n_h
  611. cf2py intent(in) n_q
  612. c ----------------------
  613. ifo = 0
  614. do t = 1, n
  615. t_q = timet(n_q, t)
  616. t_z = timet(n_z, t)
  617. t_h = timet(n_h, t)
  618. t_t = timet(n_t, t)
  619. call dcopy(m,at,1,a(:,t),1)
  620. do i = 1, m
  621. call dcopy(m,pt(:,i),1,ps(:,i,t),1)
  622. enddo
  623. c Nu(t)= Y(t) - Z(t)*a(t)
  624. call dcopy(p,y(:,t),1,nu(:,t),1)
  625. alpha=-1.0
  626. beta=1.0
  627. call dgemv('n',p,m,alpha,z(:,:,t_z),p,at,1,beta,nu(:,t),1)
  628. alpha=1.0
  629. beta=0.0
  630. c m(t) = P(t)*Z(t)'
  631. call dgemm('n','t',m,p,m,alpha,pt,m,z(:,:,t_z),p,beta,mt,m)
  632. c F(t) = Z(t)*m(t)+H(t)
  633. do i=1,p
  634. call dcopy(p,h(:,i,t_h),1,f(:,i),1)
  635. enddo
  636. beta=1.0
  637. call dgemm('n','n',p,p,m,alpha,z(:,:,t_z),p,mt,m,beta,f,p)
  638. c calculate fi = inverse(f)
  639. call eye(fi(:,:,t),p)
  640. call dposv('u',p,p,f,p,fi(:,:,t),p,info)
  641. if (info.ne.0) then
  642. ifo=1
  643. endif
  644. beta=0.0
  645. c W(t) = T(t)*P(t)
  646. call dgemm('n','n',m,m,m,alpha,tt(:,:,t_t),m,pt,m,beta,w,m)
  647. c K(t) = W(t)*Z(t)'*inv(F(t))
  648. call dgemm('n','t',m,p,m,alpha,w,m,z(:,:,t_z),p,beta,wz,m)
  649. call dgemm('n','n',m,p,p,alpha,wz,m,fi(:,:,t),p,beta,
  650. + k(:,:,t),m)
  651. c L(t)=T(t)-K(t)*Z(t)
  652. do i=1,m
  653. call dcopy(m,tt(:,i,t_t),1,ls(:,i,t),1)
  654. enddo
  655. alpha=-1.0
  656. beta=1.0
  657. call dgemm('n','n',m,m,p,alpha,k(:,:,t),m,z(:,:,t_z),p,beta,
  658. + ls(:,:,t),m)
  659. alpha=1.0
  660. beta=0.0
  661. c a(t+1)=T(t)*a(t)+K(t)*nu(t)
  662. call dgemv('n',m,m,alpha,tt(:,:,t_t),m,a(:,t),1,beta,at,1)
  663. beta=1.0
  664. call dgemv('n',m,p,alpha,k(:,:,t),m,nu(:,t),1,beta,at,1)
  665. beta=0.0
  666. c P(t+1)=W(t)*L(t)'+Q(t)
  667. c call dgemm('n','n',m,m,m,alpha,tt(:,:,t),m,pt,m,beta,w,m)
  668. do i=1,m
  669. call dcopy(m,qt(:,i,t_q),1,pt(:,i),1)
  670. enddo
  671. beta=1.0
  672. call dgemm('n','t',m,m,m,alpha,w,m,ls(:,:,t),m,beta,pt,m)
  673. enddo
  674. end
  675. c ------------------------------------------------------------------
  676. c contemporaneous version of the kalman filter
  677. c subroutine for filtering with the standard state SSM
  678. subroutine cfilter(y,z,h,tt,qt,nu,f,s,a,at,pt,ps,mt,w,lk,wl,ifo,
  679. + ilike, m, p, n, n_z, n_t, n_h, n_q)
  680. integer m,p,n,t,i,ifo, info,ilike
  681. integer n_z, n_t, n_h, n_q, t_z, t_t, t_h, t_q, timet
  682. real*8 y(p,n),z(p,m,n_z),h(p,p,n_h),tt(m,m,n_t),qt(m,m,n_q)
  683. real*8 nu(p,n),s(p,m,n),a(m,n+1)
  684. real*8 ps(m,m,n+1),mt(p,m),at(m,n),pt(m,m,n),f(p,p),w(m,m,n)
  685. real*8 alpha, beta,lk(*),logdet,ddot,llike,wl(p)
  686. c ----------------------
  687. cf2py intent(in) y
  688. cf2py intent(in) z
  689. cf2py intent(in) h
  690. cf2py intent(in) tt
  691. cf2py intent(in) qt
  692. cf2py intent(inout) nu
  693. cf2py intent(inout) k
  694. cf2py intent(in) f
  695. cf2py intent(inout) s
  696. cf2py intent(inout) a
  697. cf2py intent(in) at
  698. cf2py intent(in) pt
  699. cf2py intent(inout) ps
  700. cf2py intent(in) mt
  701. cf2py intent(in) w
  702. cf2py intent(inout) lk
  703. cf2py intent(in) wl
  704. cf2py intent(inout) ifo
  705. cf2py intent(in) m
  706. cf2py intent(in) p
  707. cf2py intent(in) n
  708. cf2py intent(in) n_t
  709. cf2py intent(in) n_q
  710. cf2py intent(in) n_z
  711. cf2py intent(in) n_h
  712. c ----------------------
  713. c note if lk(1).lt.-1 then calculate likelihood and return in lk(1)
  714. ifo=0
  715. llike=0.0
  716. do t=1,n
  717. t_t = timet(n_t, t)
  718. t_z = timet(n_z, t)
  719. t_q = timet(n_q, t)
  720. t_h = timet(n_h, t)
  721. c Nu(t)= Y(t) - Z(t)*a(t)
  722. call dcopy(p,y(:,t),1,nu(:,t),1)
  723. alpha=-1.0
  724. beta=1.0
  725. call dgemv('n',p,m,alpha,z(:,:,t_z),p,a(:,t),1,beta,nu(:,t),1)
  726. alpha=1.0
  727. beta=0.0
  728. c m(t) = Z(t)*P(t)
  729. call dgemm('n','n',p,m,m,alpha,z(:,:,t_z),p,ps(:,:,t),m,beta,
  730. + mt,p)
  731. c F(t) = m(t)*Z(t)'+H(t)
  732. do i=1,p
  733. call dcopy(p,h(:,i,t_h),1,f(:,i),1)
  734. enddo
  735. beta=1.0
  736. call dgemm('n','t',p,p,m,alpha,mt,p,z(:,:,t_h),p,beta,f,p)
  737. c F(t)*S(t) = m(t); solve for S(t)=inv(F(t))*m(t)
  738. do i=1,m
  739. call dcopy(p,mt(:,i),1,s(:,i,t),1)
  740. enddo
  741. call dposv('u',p,m,f,p,s(:,:,t),p,info)
  742. if (info.ne.0) then
  743. ifo=1
  744. endif
  745. beta=0.0
  746. if (ilike.eq.0) then
  747. logdet=0.0
  748. do i=1,p
  749. logdet=logdet+log(f(i,i))
  750. enddo
  751. logdet=2.0*logdet
  752. call dcopy(p,nu(:,t),1,wl,1)
  753. call dtrsv('u','t','n',p,f,p,wl,1)
  754. llike=llike-0.5*(logdet+ddot(p,wl,1,wl,1))
  755. c call dtrsm('l','u','t','n',p,1,alpha,f,p,wl,p)
  756. c call dtrsm('l','u','n','n',p,1,alpha,f,p,wl,p)
  757. c llike=llike-0.5*(logdet+ddot(p,wl,1,nu(:,t),1))
  758. endif
  759. c a(t|t)=a(t)+S(t)'nu(t)
  760. alpha=1.0
  761. beta=1.0
  762. call dcopy(m,a(:,t),1,at(:,t),1)
  763. call dgemv('t',p,m,alpha,s(:,:,t),p,nu(:,t),1,beta,at(:,t),1)
  764. c P(t|t)=P(t)-m(t)'S(t)
  765. do i=1,m
  766. call dcopy(m,ps(:,i,t),1,pt(:,i,t),1)
  767. enddo
  768. alpha=-1.0
  769. beta=1.0
  770. call dgemm('t','n',m,m,p,alpha,mt,p,s(:,:,t),p,beta,
  771. + pt(:,:,t),m)
  772. c W(t) = P(t)*T(t)'
  773. alpha=1.0
  774. beta=0.0
  775. call dgemm('n','t',m,m,m,alpha,pt(:,:,t),m,tt(:,:,t_t),m,beta,
  776. + w(:,:,t), m)
  777. c a(t+1)=T(t)*a(t|t)
  778. call dgemv('n',m,m,alpha,tt(:,:,t_t),m,at(:,t),1,beta,
  779. + a(:,t+1), 1)
  780. c P(t+1)=T(t)*W(t)+Q(t)
  781. beta=1.0
  782. do i=1,m
  783. call dcopy(m,qt(:,i,t),1,ps(:,i,t+1),1)
  784. enddo
  785. call dgemm('n','n',m,m,m,alpha,tt(:,:,t),m,w(:,:,t),m,beta,
  786. + ps(:,:,t+1),m)
  787. enddo
  788. lk(1)=llike
  789. end
  790. c ------------------------------------------------------------------
  791. c contemporaneous version of the kalman filter
  792. c subroutine for filtering with the standard state SSM
  793. c non-time varying system matricies
  794. subroutine ntcfilter(t_last,y,z,h,tt,qt,nu,f,s,a,at,pt,ps,mt,
  795. + w, lk, wl,ifo, ilike, m,p,n)
  796. integer m,p,n,t,it,t_last,i,ifo,info,ilike,chk,flag_steady
  797. real*8 y(p,n),z(p,m),h(p,p),tt(m,m),qt(m,m), tol
  798. real*8 nu(p,n),s(p,m,n),a(m,n+1),fnorm
  799. real*8 ps(m,m,n+1),mt(p,m),at(m,n),pt(m,m,n),f(p,p),w(m,m,n)
  800. real*8 alpha, beta,lk(*),logdet,ddot,llike,wl(p), temp
  801. c ----------------------
  802. cf2py intent(inout) t_last
  803. cf2py intent(in) y
  804. cf2py intent(in) z
  805. cf2py intent(in) h
  806. cf2py intent(in) tt
  807. cf2py intent(in) qt
  808. cf2py intent(inout) nu
  809. cf2py intent(inout) k
  810. cf2py intent(in) f
  811. cf2py intent(inout) s
  812. cf2py intent(inout) a
  813. cf2py intent(inout) at
  814. cf2py intent(in) pt
  815. cf2py intent(inout) ps
  816. cf2py intent(in) mt
  817. cf2py intent(in) w
  818. cf2py intent(inout) lk
  819. cf2py intent(in) wl
  820. cf2py intent(inout) ifo
  821. cf2py intent(in) m
  822. cf2py intent(in) p
  823. cf2py intent(in) n
  824. c ----------------------
  825. c Note: ps == P(t)
  826. c note if lk(1).lt.-1 then calculate likelihood and return in lk(1)
  827. chk = 10
  828. ifo = 0
  829. t_last = n + 1
  830. tol = 1E-10
  831. logdet = 0.0
  832. llike = 0.0
  833. flag_steady = 0 ! Indicator that steady state reached
  834. do t = 1, n
  835. c 1. Compute: Nu(t)= Y(t) - Z(t)*a(t)
  836. c 1a. Initialise: nu(:,t) = y(:,t)
  837. call dcopy(p,y(:,t),1,nu(:,t),1)
  838. c 1b. Compute: nu(:,t) = nu(:,t) + z * a(:,t)
  839. alpha = -1.0
  840. beta = 1.0
  841. call dgemv('n',p,m,alpha,z,p,a(:,t),1,beta,nu(:,t),1)
  842. c ---------------------------------------
  843. c NOTE: Step 2 - 7 do not need to be computed once steady state reached
  844. if(flag_steady.eq.0) then
  845. c 2. Compute: m(t) = Z(t)*P(t), i.e. mt = z * ps(:,:,t)
  846. alpha = 1.0
  847. beta = 0.0
  848. call dgemm('n','n',p,m,m,alpha,z,p,ps(:,:,t),m,beta,
  849. + mt,p)
  850. c ---------------------------------------
  851. c 3. Compute: F(t) = m(t)*Z(t)'+ H(t)
  852. c 3a. Initialise: f(:,:) = h(:,:)
  853. do i = 1, p
  854. call dcopy(p, h(:,i), 1, f(:,i), 1)
  855. enddo
  856. c 3b. Compute: f = f + mt * z'
  857. beta = 1.0
  858. call dgemm('n','t',p,p,m,alpha,mt,p,z,p,beta,f,p)
  859. c ---------------------------------------
  860. c Calculate log-likelihood component
  861. if (ilike.eq.0) then
  862. logdet = 0.0
  863. do i = 1, p
  864. logdet = logdet + 2.0 * log(f(i,i))
  865. enddo
  866. endif
  867. c ---------------------------------------
  868. c 4. Compute: S(t) = inv(F(t)) * m(t)
  869. c by solving system F(t)*S(t) = m(t)
  870. c 4a. Initialise s(:,:,t) = mt
  871. do i = 1, m
  872. call dcopy(p,mt(:,i),1,s(:,i,t),1)
  873. enddo
  874. c 4b. Solve f x = s and set s = x
  875. call dposv('u',p,m,f,p,s(:,:,t),p,info)
  876. if (info.ne.0) then
  877. ifo = 1
  878. print *, 'Error: Failed to solve [ntcfilter:4b]'
  879. endif
  880. c ---------------------------------------
  881. c 5. Compute: P(t|t) = P(t) - S(t)'m(t)
  882. c 5a. Initialise: pt(:,:,t) = ps(:,:,t)
  883. do i = 1, m
  884. call dcopy(m,ps(:,i,t),1,pt(:,i,t),1)
  885. enddo
  886. c 5b. Compute: pt = pt - s' * mt
  887. alpha = -1.0
  888. beta = 1.0
  889. call dgemm('t','n',m,m,p,alpha,s(:,:,t),p,mt,p,beta,
  890. + pt(:,:,t),m)
  891. c ---------------------------------------
  892. c 6. Compute: W(t) = T(t) * P(t|t), i.e. w = tt * pt
  893. alpha = 1.0
  894. beta = 0.0
  895. call dgemm('n','t',m,m,m,alpha,tt,m,pt(:,:,t),m,beta,
  896. + w(:,:,t), m)
  897. c ---------------------------------------
  898. c 7. Compute: P(t+1) = W(t)*T(t)' + Q(t)
  899. c 7a. Initialise: ps(:,:, t+1) = qt
  900. beta = 1.0
  901. do i = 1, m
  902. call dcopy(m,qt(:,i),1,ps(:,i,t+1),1)
  903. enddo
  904. c 7b. Compute: ps = ps + w * tt'
  905. call dgemm('n','t',m,m,m,alpha,w(:,:,t),m,tt,m,beta,
  906. + ps(:,:,t+1),m)
  907. c ---------------------------------------
  908. endif ! FINISH CALCS FOR NO STEADY STATE SITUATION
  909. c ----------------------------------------------------
  910. c NOTE: This must always be computed at time t
  911. if (ilike.eq.0) then
  912. c Initialise: wl = nu(:,t)
  913. call dcopy(p,nu(:,t),1,wl,1)
  914. c Solve: f x = wl and set wl = x
  915. call dtrsv('u','t','n',p,f,p,wl,1)
  916. llike = llike -0.5*(logdet + ddot(p,wl,1,wl,1))
  917. endif
  918. if (flag_steady.eq.0) then
  919. it = t
  920. else
  921. it = t_last
  922. endif
  923. c ---------------------------------------
  924. c NOTE: Step 8 and 9 must always be computed at time t
  925. c 8. Compute: a(t|t) = a(t) + S(t)'nu(t)
  926. alpha = 1.0
  927. beta = 1.0
  928. c 8a. Initialise: at(:,t) = a(:,t)
  929. call dcopy(m,a(:,t),1,at(:,t),1)
  930. c 8b. Compute: at = at + s' * nu
  931. c NOTE: s(:,:,t or lt) depending on whether steady state reached
  932. call dgemv('t',p,m,alpha,s(:,:,it),p,nu(:,t),1,beta,at(:,t),1)
  933. c ---------------------------------------
  934. c 9. Compute: a(t+1) = T(t) * a(t|t), i.e. a = tt * at
  935. call dgemv('n',m,m,alpha,tt,m,at(:,t),1,beta,a(:,t+1),
  936. + 1)
  937. c ---------------------------------------
  938. c Monitor convergence to steady state if not already occurred
  939. if (flag_steady.eq.0) then ! i.e Not yet reached
  940. if(t.gt.chk) then
  941. if (mod(t,chk).eq.0) then ! i.e. check regularly
  942. temp = fnorm(ps(:,:,t),ps(:,:,t-chk),m,m)
  943. if(temp.lt.tol) then
  944. flag_steady = 1 ! Update flag
  945. t_last = t ! Record when steady state occurs
  946. endif
  947. endif
  948. endif
  949. endif
  950. enddo
  951. lk(1) = llike
  952. end
  953. c ------------------------------------------------------------------
  954. c subroutine for smoothing. Standard state space model. Time varying
  955. c system matricies.
  956. subroutine smoother(ah,s,nu,ls,r,ltr,as,ps,pmiss,p,m,n)
  957. integer p,m,n,t,i,pmiss(n)
  958. real*8 ah(m,n),s(p,m,n),nu(p,n),ls(m,m,n),r(m),ltr(m)
  959. real*8 as(m,n), ps(m,m,n)
  960. real*8 alpha, beta
  961. c ----------------------
  962. cf2py intent(inout) ah
  963. cf2py intent(in) s
  964. cf2py intent(in) nu
  965. cf2py intent(in) ls
  966. cf2py intent(in) r
  967. cf2py intent(in) ltr
  968. cf2py intent(in) as
  969. cf2py intent(in) ps
  970. cf2py intent(in) p
  971. cf2py intent(in) m
  972. cf2py intent(in) n
  973. c ----------------------
  974. c Initialise vector
  975. do i = 1, m
  976. r(i) = 0.0
  977. enddo
  978. alpha = 1.0
  979. do t = n, 1, -1
  980. c Step 1: Compute r(t-1) = S(t)' * nu(t) + L(t)' * r(t)
  981. beta = 0.0
  982. c 1a. Compute: ltr = ls(:,:,t) * r
  983. call dgemv('t',m,m,alpha,ls(:,:,t),m,r,1,beta,ltr,1)
  984. c 1b. Initialise r: i.e. r = ltr
  985. call dcopy(m, ltr, 1, r, 1)
  986. if (pmiss(t).eq.0) then
  987. !data not missing
  988. beta = 1.0
  989. c 1c. Compute: r = (s * nu) + r
  990. call dgemv('t',p,m,alpha,s(:,:,t),p,nu(:,t),1,beta,r,1)
  991. endif
  992. c Step 2: Compute ahat(t) = a(t) + P(t) * r(t-1)
  993. c 2a. Initialise as: i.e. ah(:,t) = as(:, t)
  994. call dcopy(m, as(:,t), 1, ah(:,t), 1)
  995. c 2b. Compute: ah = ah + ps*r
  996. beta = 1.0
  997. call dgemv('n',m,m,alpha, ps(:,:,t), m, r,1, beta, ah(:,t),1)
  998. enddo
  999. end
  1000. c ------------------------------------------------------------------
  1001. c subroutine for smoothing. Standard state space model. Non time varying system matricies.
  1002. subroutine ntsmoother(ah,s,nu,ls,r,ltr,as,ps,lt,p,m,n)
  1003. integer p,m,n,t,i,lt,it
  1004. real*8 ah(m,n),s(p,m,n),nu(p,n),ls(m,m,n),r(m),ltr(m)
  1005. real*8 as(m,n), ps(m,m,n)
  1006. real*8 alpha, beta
  1007. c ----------------------
  1008. cf2py intent(inout) ah
  1009. cf2py intent(in) s
  1010. cf2py intent(in) nu
  1011. cf2py intent(in) ls
  1012. cf2py intent(in) r
  1013. cf2py intent(in) ltr
  1014. cf2py intent(in) as
  1015. cf2py intent(in) ps
  1016. cf2py intent(in) lt
  1017. cf2py intent(in) p
  1018. cf2py intent(in) m
  1019. cf2py intent(in) n
  1020. c ----------------------
  1021. c Initialise vector
  1022. do i = 1, m
  1023. r(i) = 0.0
  1024. enddo
  1025. alpha = 1.0
  1026. do t = n, 1, -1
  1027. if (t.gt.lt) then
  1028. it = lt
  1029. else
  1030. it = t
  1031. endif
  1032. c Step 1: Compute r(t-1) = S(t)'*nu(t) + L(t)'r(t)
  1033. beta = 0.0
  1034. c 1a. Compute: ltr = ls * r
  1035. call dgemv('t',m,m,alpha,ls(:,:,it),m,r,1,beta,ltr,1)
  1036. c 1b. Initialise: r = ltr
  1037. call dcopy(m,ltr,1,r,1)
  1038. c 1c. Compute: r = r + s * nu
  1039. beta = 1.0
  1040. call dgemv('t',p,m,alpha,s(:,:,it),p,nu(:,t),1,beta,r,1)
  1041. c -----------------------------------------------
  1042. c Step 2: Compute ahat(t) = a(t) + P(t)*r(t-1)
  1043. c 2. Initialise ah = as
  1044. call dcopy(m,as(:,t),1,ah(:,t),1)
  1045. c 2b. Compute: ah = ah + ps * r
  1046. call dgemv('n',m,m,alpha,ps(:,:,it),m,r,1,beta,ah(:,t),1)
  1047. enddo
  1048. end
  1049. c ------------------------------------------------------------------
  1050. c subroutine for state disturbance smoother
  1051. subroutine dsmoother(ehat,nu,st,jt,rt,ls,ltr,pmiss,p,m,n,r)
  1052. implicit none
  1053. integer p, m, n, r, t, i, pmiss(n)
  1054. real*8 nu(p,n), st(p,m,n), jt(r,m,n), rt(m), ls(m,m,n)
  1055. real*8 alpha, beta, ehat(r,n), ltr(m)
  1056. c ----------------------
  1057. cf2py intent(in) nu
  1058. cf2py intent(in) st
  1059. cf2py intent(in) jt
  1060. cf2py intent(in) rt
  1061. cf2py intent(in) ls
  1062. cf2py intent(inout) ehat
  1063. cf2py intent(in) ltr
  1064. cf2py intent(in) pmiss
  1065. cf2py intent(in) p
  1066. cf2py intent(in) m
  1067. cf2py intent(in) n
  1068. cf2py intent(in) r
  1069. c ----------------------
  1070. c Initialise rt array
  1071. do i = 1, m
  1072. rt(i) = 0.0
  1073. enddo
  1074. alpha = 1.0
  1075. do t = n, 1, -1
  1076. c 1. Compute: ehat(t) = J(t) * rt
  1077. beta = 0.0
  1078. call dgemv('n',r,m,alpha,jt(:,:,t),r,rt,1,beta,ehat(:,t),1)
  1079. c ---------------------------------------------
  1080. c 2. Compute: r(t-1) = S(t)'.nu(t) + L(t)'.r(t)
  1081. beta = 0.0
  1082. c 2a. Compute: ltr = ls(t)' * rt
  1083. call dgemv('t',m,m,alpha,ls(:,:,t),m,rt,1,beta,ltr,1)
  1084. c 2b. Initialise: rt = ltr
  1085. call dcopy(m,ltr,1,rt,1)
  1086. beta = 1.0
  1087. if (pmiss(t).eq.0) then
  1088. c 2c. Compute: rt = rt + st'.nu
  1089. call dgemv('t',p,m,alpha,st(:,:,t),p,nu(:,t),1,beta,rt,1)
  1090. endif
  1091. enddo
  1092. end
  1093. c ------------------------------------------------------------------
  1094. c subroutine for state disturbance smoother
  1095. subroutine ntdsmoother(ehat,nu,st,jt,rt,ls,ltr,lt,p,m,n,r)
  1096. implicit none
  1097. integer p,m,n,r,lt,it,t,i
  1098. real*8 nu(p,n),st(p,m,n),jt(r,m),rt(m),ls(m,m,n)
  1099. real*8 alpha,beta,ehat(r,n),ltr(m)
  1100. c NOTE: r(t) is input, used in calcs, then over written with r(t-1)
  1101. c ----------------------
  1102. cf2py intent(in) nu
  1103. cf2py intent(in) st
  1104. cf2py intent(in) jt
  1105. cf2py intent(in) rt
  1106. cf2py intent(in) ls
  1107. cf2py intent(inout) ehat
  1108. cf2py intent(in) ltr
  1109. cf2py intent(in) lt
  1110. cf2py intent(in) p
  1111. cf2py intent(in) m
  1112. cf2py intent(in) n
  1113. cf2py intent(in) r
  1114. c ----------------------
  1115. c Initialise rt array
  1116. do i = 1, m
  1117. rt(i) = 0.0
  1118. enddo
  1119. alpha = 1.0
  1120. do t = n, 1, -1
  1121. if (t.gt.lt) then
  1122. it = lt
  1123. else
  1124. it = t
  1125. endif
  1126. c --------------------------------
  1127. c 1. Compute: etahat = J(t)*r(t)
  1128. beta = 0.0
  1129. call dgemv('n',r,m,alpha,jt,r,rt,1,beta,ehat(:,t),1)
  1130. c -----------------------------------------------
  1131. c 2. Compute: r(t-1) = S(t)'.nu(t) + L(t)'.r(t)
  1132. c 2a. Compute: ltr = ls'.rt
  1133. beta = 0.0
  1134. call dgemv('t',m,m,alpha,ls(:,:,it),m,rt,1,beta,ltr,1)
  1135. c 2b. Initialise: rt = ltr
  1136. call dcopy(m,ltr,1,rt,1)
  1137. beta = 1.0
  1138. c 2c. Compute: rt = rt + st'.nu
  1139. call dgemv('t',p,m,alpha,st(:,:,it),p,nu(:,t),1,beta,rt,1)
  1140. enddo
  1141. end
  1142. c ------------------------------------------------------------------
  1143. c subroutine calculates the Frobenius norm for the difference of two matrices
  1144. real*8 function fnorm(a,b,m,n)
  1145. implicit none
  1146. integer m,n,i,j
  1147. real*8 a(m,n), b(m,n), sumd
  1148. sumd = 0.0
  1149. do j = 1, n
  1150. do i = 1, m
  1151. sumd = sumd + (a(i,j)-b(i,j))**2
  1152. enddo
  1153. enddo
  1154. fnorm = sqrt(sumd)
  1155. return
  1156. end
  1157. c ------------------------------------------------------------------
  1158. c benchmark simulation smoothing routine
  1159. subroutine bsmoother(ah,z,fi,fn,nu,ls,r,ltr,as,ps,p,m,n, n_z)
  1160. integer p,m,n,t,i, n_z, t_z, timet
  1161. real*8 ah(m,n),z(p,m,n_z),fi(p,p,n),fn(p),nu(p,n),ls(m,m,n),r(m)
  1162. real*8 as(m,n), ps(m,m,n),ltr(m)
  1163. real*8 alpha, beta
  1164. c ----------------------
  1165. cf2py intent(inout) ah
  1166. cf2py intent(in) fi
  1167. cf2py intent(in) fn
  1168. cf2py intent(in) nu
  1169. cf2py intent(in) ls
  1170. cf2py intent(in) r
  1171. cf2py intent(in) ltr
  1172. cf2py intent(in) as
  1173. cf2py intent(in) ps
  1174. cf2py intent(in) p
  1175. cf2py intent(in) m
  1176. cf2py intent(in) n
  1177. cf2py intent(in) n_z
  1178. c ----------------------
  1179. do i = 1,m
  1180. r(i) = 0.0
  1181. enddo
  1182. alpha = 1.0
  1183. do t = n, 1, -1
  1184. t_z = timet(n_z, t)
  1185. c r(t-1)=Z(t)'inv(F(t))*nu(t)+L(t)'r(t)
  1186. beta = 0.0
  1187. call dgemv('t',m,m,alpha,ls(:,:,t),m,r,1,beta,ltr,1)
  1188. call dcopy(m,ltr,1,r,1)
  1189. call dgemv('n',p,p,alpha,fi(:,:,t),p,nu(:,t),1,beta,fn,1)
  1190. beta = 1.0
  1191. call dgemv('t',p,m,alpha,z(:,:,t_z),p,fn,1,beta,ltr,1)
  1192. call dcopy(m,ltr,1,r,1)
  1193. c ahat(t)=a(t)+P(t)*r(t-1)
  1194. call dcopy(m,as(:,t),1,ah(:,t),1)
  1195. call dgemv('n',m,m,alpha,ps(:,:,t),m,r,1,beta,ah(:,t),1)
  1196. enddo
  1197. end
  1198. c ------------------------------------------------------------------
  1199. c Procedure to initialise an identity matrix of specified dimension
  1200. subroutine eye(a,m)
  1201. integer m, i, j
  1202. real*8 a(m,m)
  1203. do i = 1, m
  1204. do j = 1, m
  1205. a(i,j) = 0.0
  1206. enddo
  1207. a(i,i) = 1.0
  1208. enddo
  1209. end
  1210. c ------------------------------------------------------------------
  1211. c de Jong and Shephard simulation smoother
  1212. subroutine dssimsm(eta,s,nu,z,w,u,ls,rt,nt,v,nl,jt,
  1213. + ct,nj,lr,qt,ifo,pmiss,p,m,r,n, n_z, n_q)
  1214. implicit none
  1215. integer ifo,info,p,m,r,n,t,i,j, t_z, n_z, t_q, n_q, timet
  1216. integer pmiss(n)
  1217. real*8 eta(r,n),s(p,m,n),nu(p,n), z(p,m,n_z), w(r,m), u(r)
  1218. real*8 ls(m,m,n),rt(m),nt(m,m),v(r,m),nl(m,m),jt(r,m,n)
  1219. real*8 ct(r,r),nj(m,r),lr(m), qt(r,r,n_q)
  1220. real*8 alpha,beta
  1221. c on entry eta is a matrix of random normals on exit it is a
  1222. c sample of eta
  1223. c ----------------------
  1224. cf2py intent(inout) eta
  1225. cf2py intent(in) s
  1226. cf2py intent(in) nu
  1227. cf2py intent(in) z
  1228. cf2py intent(in) w
  1229. cf2py intent(in) u
  1230. cf2py intent(in) ls
  1231. cf2py intent(inout) rt
  1232. cf2py intent(in) nt
  1233. cf2py intent(in) v
  1234. cf2py intent(in) nl
  1235. cf2py intent(in) jt
  1236. cf2py intent(in) ct
  1237. cf2py intent(in) nj
  1238. cf2py intent(in) lr
  1239. cf2py intent(in) qt
  1240. cf2py intent(in) pmiss
  1241. cf2py intent(inout) ifo
  1242. cf2py intent(in) p
  1243. cf2py intent(in) m
  1244. cf2py intent(in) r
  1245. cf2py intent(in) n
  1246. cf2py intent(in) n_z
  1247. cf2py intent(in) n_q
  1248. c ----------------------
  1249. do j = 1, m
  1250. rt(j) = 0.0
  1251. do i = 1, m
  1252. nt(i,j) = 0.0
  1253. enddo
  1254. enddo
  1255. do t = n, 1, -1
  1256. t_z = timet(n_z, t)
  1257. t_q = timet(n_q, t)
  1258. alpha = 1.0
  1259. beta = 0.0
  1260. c NL(t) = N(t) * L(t)
  1261. call dgemm('n','n',m,m,m,alpha,nt,m,ls(:,:,t),m,beta,nl,m)
  1262. c W(t) = J(t) * NL(t)
  1263. call dgemm('n','n',r,m,m,alpha,jt(:,:,t),r,nl,m,beta,w,r)
  1264. c NJ(t) = N(t) * J(t)'
  1265. call dgemm('n','t',m,r,m,alpha,nt,m,jt(:,:,t),r,beta,nj,m)
  1266. c C(t) = Q(t)-J(t) * NJ(t)
  1267. do i=1,r
  1268. call dcopy(r,qt(:,i,t_q),1,ct(:,i),1)
  1269. enddo
  1270. alpha = -1.0
  1271. beta = 1.0
  1272. call dgemm('n','n',r,r,m,alpha,jt(:,:,t),r,nj,m,beta,ct,r)
  1273. c C(t) * V(t) = W(t); solve for V(t)
  1274. do i = 1, m
  1275. call dcopy(r,w(:,i),1,v(:,i),1)
  1276. enddo
  1277. call dposv('u',r,m,ct,r,v,r,info)
  1278. if (info.ne.0) then
  1279. ifo = 1
  1280. endif
  1281. c d(t)~N(0,C(t)); on exit eta(:,t) = d(t)
  1282. call dtrmv('u','t','n',r,ct,r,eta(:,t),1)
  1283. c C(t) * U(t) = d(t); solve for U(t)
  1284. call dcopy(r,eta(:,t),1,u,1)
  1285. call dtrsv('u','t','n',r,ct,r,u,1)
  1286. call dtrsv('u','n','n',r,ct,r,u,1)
  1287. c eta = d(t) + J(t) * r(t)
  1288. alpha = 1.0
  1289. beta = 1.0
  1290. call dgemv('n',r,m,alpha,jt(:,:,t),r,rt,1,beta,eta(:,t),1)
  1291. c r(t) = S(t)' * nu(t) - W(t)' * U(t) + l(t)'r(t)
  1292. beta = 0.0
  1293. call dgemv('t',m,m,alpha,ls(:,:,t),m,rt,1,beta,lr,1)
  1294. call dcopy(m,lr,1,rt,1)
  1295. alpha = -1.0
  1296. beta = 1.0
  1297. call dgemv('t',r,m,alpha,w,r,u,1,beta,rt,1)
  1298. alpha = 1.0
  1299. if (pmiss(t).eq.0) then
  1300. call dgemv('t',p,m,alpha,s(:,:,t),p,nu(:,t),1,beta,rt,1)
  1301. endif
  1302. c N(t) = S(t)'Z(t) + W(t)'V(t) +L(t)'NL(t)
  1303. beta = 0.0
  1304. call dgemm('t','n',m,m,m,alpha,ls(:,:,t),m,nl,m,beta,nt,m)
  1305. beta = 1.0
  1306. call dgemm('t','n',m,m,r,alpha,w,r,v,r,beta,nt,m)
  1307. if (pmiss(t).eq.0) then
  1308. call dgemm('t','n',m,m,p,alpha,s(:,:,t),p,z(:,:,t_z),p,
  1309. + beta,nt,m)
  1310. endif
  1311. enddo
  1312. end
  1313. c ------------------------------------------------------------------
  1314. c de Jong and Shephard simulation smoother non time varying system
  1315. c matricies
  1316. subroutine ntdssimsm(eta,s,nu,z,w,u,ls,rt,nt,v,nl,jt,
  1317. + ct,nj,lr,qt,lt,ifo,p,m,r,n)
  1318. implicit none
  1319. integer ifo,info,lt,it,p,m,r,n,t,i,j
  1320. real*8 eta(r,n),s(p,m,n),nu(p,n),z(p,m),w(r,m),u(r)
  1321. real*8 ls(m,m,n),rt(m),nt(m,m),v(r,m),nl(m,m),jt(r,m)
  1322. real*8 ct(r,r),nj(m,r),lr(m),qt(r,r)
  1323. real*8 alpha,beta
  1324. c on entry eta is a matrix of random normals on exit it is a
  1325. c sample of eta
  1326. c ----------------------
  1327. cf2py intent(inout) eta
  1328. cf2py intent(in) s
  1329. cf2py intent(in) nu
  1330. cf2py intent(in) z
  1331. cf2py intent(in) w
  1332. cf2py intent(in) u
  1333. cf2py intent(in) ls
  1334. cf2py intent(inout) rt
  1335. cf2py intent(in) nt
  1336. cf2py intent(in) lt
  1337. cf2py intent(in) v
  1338. cf2py intent(in) nl
  1339. cf2py intent(in) jt
  1340. cf2py intent(in) ct
  1341. cf2py intent(in) nj
  1342. cf2py intent(in) lr
  1343. cf2py intent(in) qt
  1344. cf2py intent(inout) ifo
  1345. cf2py intent(in) p
  1346. cf2py intent(in) m
  1347. cf2py intent(in) r
  1348. cf2py intent(in) n
  1349. c ----------------------
  1350. do j = 1, m
  1351. rt(j) = 0.0
  1352. do i = 1, m
  1353. nt(i,j) = 0.0
  1354. enddo
  1355. enddo
  1356. do t = n, 1, -1
  1357. if (t.lt.lt) then
  1358. it = t
  1359. else
  1360. it = lt
  1361. endif
  1362. alpha = 1.0
  1363. beta = 0.0
  1364. c NL(t) = N(t) * L(t)
  1365. call dgemm('n','n',m,m,m,alpha,nt,m,ls(:,:,it),m,beta,nl,m)
  1366. c W(t) = J(t) * NL(t)
  1367. call dgemm('n','n',r,m,m,alpha,jt,r,nl,m,beta,w,r)
  1368. c NJ(t) = N(t) * J(t)'
  1369. call dgemm('n','t',m,r,m,alpha,nt,m,jt,r,beta,nj,m)
  1370. c C(t) = Q(t)-J(t) * NJ(t)
  1371. do i = 1, r
  1372. call dcopy(r,qt(:,i),1,ct(:,i),1)
  1373. enddo
  1374. alpha = -1.0
  1375. beta = 1.0
  1376. call dgemm('n','n',r,r,m,alpha,jt,r,nj,m,beta,ct,r)
  1377. c C(t) * V(t) = W(t); solve for V(t)
  1378. do i = 1, m
  1379. call dcopy(r,w(:,i),1,v(:,i),1)
  1380. enddo
  1381. call dposv('u',r,m,ct,r,v,r,info)
  1382. if (info.ne.0) then
  1383. ifo = 1
  1384. endif
  1385. c d(t)~N(0,C(t)); on exit eta(:,t) = d(t)
  1386. call dtrmv('u','t','n',r,ct,r,eta(:,t),1)
  1387. c C(t) * U(t) = d(t); solve for U(t)
  1388. call dcopy(r,eta(:,t),1,u,1)
  1389. call dtrsv('u','t','n',r,ct,r,u,1)
  1390. call dtrsv('u','n','n',r,ct,r,u,1)
  1391. c eta = d(t) + J(t) * r(t)
  1392. alpha = 1.0
  1393. beta = 1.0
  1394. call dgemv('n',r,m,alpha,jt,r,rt,1,beta,eta(:,t),1)
  1395. c r(t) = S(t)' * nu(t) - W(t)' * U(t) + l(t)'r(t)
  1396. beta = 0.0
  1397. call dgemv('t',m,m,alpha,ls(:,:,it),m,rt,1,beta,lr,1)
  1398. call dcopy(m,lr,1,rt,1)
  1399. alpha = -1.0
  1400. beta = 1.0
  1401. call dgemv('t',r,m,alpha,w,r,u,1,beta,rt,1)
  1402. alpha = 1.0
  1403. call dgemv('t',p,m,alpha,s(:,:,it),p,nu(:,t),1,beta,rt,1)
  1404. c N(t) = S(t)'Z(t) + W(t)'V(t) +L(t)'NL(t)
  1405. beta = 0.0
  1406. call dgemm('t','n',m,m,m,alpha,ls(:,:,it),m,nl,m,beta,nt,m)
  1407. beta = 1.0
  1408. call dgemm('t','n',m,m,r,alpha,w,r,v,r,beta,nt,m)
  1409. call dgemm('t','n',m,m,p,alpha,s(:,:,it),p,z,p,beta,
  1410. + nt,m)
  1411. enddo
  1412. end
  1413. c ------------------------------------------------------------------
  1414. c subroutine to update J(t) in the time varying case
  1415. subroutine update_jt(jt,qt,gt,r,m,n, n_q, n_g)
  1416. implicit none
  1417. integer n,r,m,t, n_g, n_q, t_q, t_g, timet
  1418. real*8 jt(r,m,n),qt(r,r,n_q),gt(m,r,n_g)
  1419. real*8 alpha, beta
  1420. c ----------------------
  1421. cf2py intent(inout) jt
  1422. cf2py intent(in) qt
  1423. cf2py intent(in) gt
  1424. cf2py intent(in) r
  1425. cf2py intent(in) m
  1426. c ----------------------
  1427. alpha = 1.0
  1428. beta = 0.0
  1429. c$omp parallel default(shared) private(t, t_g, t_q)
  1430. c$omp do schedule(static)
  1431. do t = 1, n
  1432. t_q = timet(n_q, t)
  1433. t_g = timet(n_g, t)
  1434. c Compute: j(t) = q(t) * g(t)'
  1435. call dgemm('n','t',r,m,r,alpha,qt(:,:,t_q),r,gt(:,:,t_g),
  1436. + m, beta, jt(:,:,t),r)
  1437. enddo
  1438. c$omp end do
  1439. c$omp end parallel
  1440. end
  1441. c ------------------------------------------------------------------
  1442. c **/** NEW OPENMP ADDED - TESTED **/**
  1443. c subroutine to calculate the state vector given the initial state
  1444. c and the state disturbances
  1445. subroutine genstate(eta,tt,gt,st,m,r,n, n_t, n_g)
  1446. implicit none
  1447. integer n,m,r,t, n_g, n_t, t_t, t_g, timet
  1448. real*8 eta(r,n), tt(m,m,n_t), gt(m,r,n_g), st(m,n)
  1449. real*8 alpha,beta
  1450. c ----------------------
  1451. cf2py intent(in) eta
  1452. cf2py intent(in) tt
  1453. cf2py intent(in) gt
  1454. cf2py intent(inout) st
  1455. cf2py intent(in) m
  1456. cf2py intent(in) r
  1457. cf2py intent(in) n_t
  1458. cf2py intent(in) n_g
  1459. c ----------------------
  1460. alpha = 1.0
  1461. beta = 0.0
  1462. ! NON OPENMP VERSION:
  1463. ! do t = 1, n-1
  1464. ! t_t = timet(n_t, t)
  1465. ! t_g = timet(n_g, t)
  1466. ! beta = 0.0
  1467. c Compute: st(:,t+1) = tt . st(:,t)
  1468. ! call dgemv('n',m,m, alpha, tt(:,:,t_t), m, st(:,t), 1,
  1469. ! + beta, st(:,t+1), 1)
  1470. ! beta = 1.0
  1471. c Compute: st(:,t+1) = st(:,t+1) + gt * eta(:,t)
  1472. ! call dgemv('n',m,r,alpha,gt(:,:,t_g),m,eta(:,t),1,beta,
  1473. ! + st(:,t+1),1)
  1474. ! enddo
  1475. ! OPENMP VERSION: Re-ordering of tasks necessary
  1476. beta = 0.0
  1477. c$omp parallel default(shared) private(t, t_g)
  1478. c$omp do schedule(static)
  1479. do t = 1, n-1
  1480. t_g = timet(n_g, t)
  1481. c Compute: st(:,t+1) = gt * eta(:,t)
  1482. call dgemv('n',m,r,alpha,gt(:,:,t_g),m,eta(:,t),1,beta,
  1483. + st(:,t+1),1)
  1484. enddo
  1485. c$omp end do
  1486. c$omp end parallel
  1487. beta = 1
  1488. do t = 1, n-1
  1489. t_t = timet(n_t, t)
  1490. c Compute: st(:,t+1) = st(:,t+1) + tt . st(:,t)
  1491. call dgemv('n',m,m, alpha, tt(:,:,t_t), m, st(:,t), 1,
  1492. + beta, st(:,t+1), 1)
  1493. enddo
  1494. end
  1495. c ------------------------------------------------------------------
  1496. c **/** NEW OPENMP ADDED - TESTED **/**
  1497. c subroutine to calculate the state vector given the initial state
  1498. c and the state disturbances and non time varying system matricies
  1499. subroutine ntgenstate(eta,tt,gt,st,m,r,n)
  1500. implicit none
  1501. integer n,m,r,t
  1502. real*8 eta(r,n),tt(m,m),gt(m,r),st(m,n)
  1503. real*8 alpha,beta
  1504. c ----------------------
  1505. cf2py intent(in) eta
  1506. cf2py intent(in) tt
  1507. cf2py intent(in) gt
  1508. cf2py intent(inout) st
  1509. cf2py intent(in) m
  1510. cf2py intent(in) r
  1511. cf2py intent(in) n
  1512. c ----------------------
  1513. alpha = 1.0
  1514. beta = 0.0
  1515. c$omp parallel default(shared) private(t)
  1516. c$omp do schedule(static)
  1517. do t = 1, n-1
  1518. c Compute: st(:,t+1) = gt * eta(:,t)
  1519. call dgemv('n',m,r,alpha,gt,m,eta(:,t),1,beta,st(:,t+1),
  1520. + 1)
  1521. enddo
  1522. c$omp end do
  1523. c$omp end parallel
  1524. beta = 1.0
  1525. do t = 1, n-1
  1526. c Compute: st(:,t+1) = st(:,t+1) + tt . st(:,t)
  1527. call dgemv('n',m,m,alpha,tt,m,st(:,t),1,beta,st(:,t+1),
  1528. + 1)
  1529. enddo
  1530. end
  1531. c ------------------------------------------------------------------
  1532. c subroutine returns the kernel for the log probability of the state
  1533. c subroutine lnprst(pr,res,cqt,gcqt,r,n,nq,ngq,m)
  1534. subroutine lnprst(pr,res,cqt,gqg,cgqg,w,wk,ifo,fl,lw,r,n,nq,ngq,m)
  1535. implicit none
  1536. integer r, m, n, t, nq, t_q, ngq, t_gq, timet, lw, ifo, fl
  1537. real*8 res(r,n-1), cqt(r,r,nq), gqg(m,m,ngq), w(*)
  1538. real*8 pr, alpha, ddot, gldet, wk(lw), cgqg(m,m), ldet
  1539. c ----------------------
  1540. cf2py intent(inout) pr
  1541. cf2py intent(in) res
  1542. cf2py intent(in) cqt
  1543. cf2py intent(in) r
  1544. cf2py intent(in) n
  1545. c ----------------------
  1546. pr = 0.0
  1547. alpha = 1.0
  1548. if (fl.eq.0) then
  1549. ldet = gldet(gqg(:,:,1),cgqg,w,wk,ifo,lw,m)
  1550. c$omp parallel default(shared) private(t, t_q, t_gq)
  1551. c$omp do reduction(-:pr)
  1552. do t = 1, n-1
  1553. t_q = timet(nq, t)
  1554. t_gq = timet(ngq,t)
  1555. call dtrsm('l','l','n','n',r,1,alpha,cqt(:,:,t_q),r,
  1556. + res(:,t),r)
  1557. c pr = pr-ddot(r,res(:,t),1,res(:,t),1)-glogdetchol(gcqt(:,:,
  1558. c + t_gq),m,r)
  1559. pr = pr - ddot(r,res(:,t),1,res(:,t),1) - ldet
  1560. enddo
  1561. c$omp end do
  1562. c$omp end parallel
  1563. pr = pr * 0.5
  1564. else
  1565. c need to modify for the case where ngq and nq eq 1
  1566. c$omp parallel default(shared) private(t, t_q, t_gq, cgqg, wk, ldet)
  1567. c$omp do reduction(-:pr)
  1568. do t = 1, n-1
  1569. t_q = timet(nq, t)
  1570. t_gq = timet(ngq,t)
  1571. call dtrsm('l','l','n','n',r,1,alpha,cqt(:,:,t_q),r,
  1572. + res(:,t),r)
  1573. c pr = pr-ddot(r,res(:,t),1,res(:,t),1)-glogdetchol(gcqt(:,:,
  1574. c + t_gq),m,r)
  1575. ldet = gldet(gqg(:,:,t_gq),cgqg,w,wk,ifo,lw,m)
  1576. pr = pr - ddot(r,res(:,t),1,res(:,t),1) - ldet
  1577. enddo
  1578. c$omp end do
  1579. c$omp end parallel
  1580. pr = pr * 0.5
  1581. endif
  1582. end
  1583. c -----------------------------------------------------------------
  1584. c computes generalised log determinant of a matrix a where the
  1585. c generalised determinant is the sum of the log of the non zero
  1586. c eigenvalues
  1587. real*8 function gldet(a,ca,w,wk,ifo,lw,m)
  1588. implicit none
  1589. integer m,lw,i,ifo
  1590. real*8 a(m,m), ca(m,m), w(m), wk(lw), tol
  1591. c tolerance
  1592. tol = 1D-10
  1593. c 1. Initialise: ca = a
  1594. do i = 1, m
  1595. call dcopy(m,a(:,i),1,ca(:,i),1)
  1596. enddo
  1597. c 2. Compute: w = eigenvalues of ca
  1598. call dsyev('n','u',m,ca,m,w,wk,lw,ifo)
  1599. c 3. Compute: determinant. Ignore zero values
  1600. gldet = 0.0
  1601. do i = 1, m
  1602. if (w(i).gt.tol) then
  1603. gldet = gldet + log(w(i))
  1604. endif
  1605. enddo
  1606. return
  1607. end function gldet
  1608. c ------------------------------------------------------------------
  1609. c simulation smoother of Fruwirth Snatter(1994) and Carter and
  1610. c Kohn(1994) to simulate the state
  1611. subroutine fscksimsm(st, as, pt, at, wt, ps, ab, pb, rs, wk,
  1612. + ifo, lt, m, n)
  1613. implicit none
  1614. integer ifo, m, n, t, info, i, lt, it
  1615. real*8 st(m,n), as(m,n+1), at(m,n), pt(m,m,n), wt(m,m,n)
  1616. real*8 ps(m,m,n+1), pb(m,m), rs(m), alpha, beta, wk(m,m), ab(m)
  1617. c ----------------------
  1618. cf2py intent(inout) st
  1619. cf2py intent(in) as
  1620. cf2py intent(in) pt
  1621. cf2py intent(in) at
  1622. cf2py intent(in) wt
  1623. cf2py intent(in) ps
  1624. cf2py intent(in) ab
  1625. cf2py intent(in) pb
  1626. cf2py intent(in) rs
  1627. cf2py intent(in) wk
  1628. cf2py intent(inout) ifo
  1629. cf2py intent(in) m
  1630. cf2py intent(in) n
  1631. cf2py intent(in) lt
  1632. c ----------------------
  1633. c Note: On exit st is the state. On entry st is a matrix of random numbers
  1634. c Note: pb on entry should equal P(n|n). pb is then used to store pbar(t)
  1635. c Note: ab on entry should equal a(n|n)
  1636. c Note: ps is abrev for pstore
  1637. c Note: pt, at equivalent to p(t|t) & a(t|t) (i.e. pt_t & at_t)
  1638. c Note: ab used to store a(n|n)
  1639. c Note: as used to store a(t)
  1640. c Note: lt used to differentiate between time varying & non time (nt) varying situation
  1641. c Note: lt = time of steady state occurrence. No results stored after this time in nt version
  1642. c 1. Compute cholesky factorization of P(n|n) ( == L.L^T). Assign as pb
  1643. call dpotrf('u', m, pb, m, info)
  1644. if (info.ne.0) then
  1645. ifo = 1
  1646. print *, 'Erorr: Failed to solve [fscksimsm:1]'
  1647. endif
  1648. c Sampling step part 1: In general alpha = a(n|n) + L.randval where L = pb^T
  1649. c 2. Compute: st(:,n) = pb^T * st(:,n) where pb is upper triangular
  1650. call dtrmv('u','t','n', m, pb, m, st(:,n), 1)
  1651. c Sampling step part 2: Add mean a(n|n)
  1652. c 3. Compute: st(:,n) = st(:,n) + alpha * ab
  1653. alpha = 1.0
  1654. call daxpy(m, alpha, ab, 1, st(:,n), 1)
  1655. do t = n-1, 1, -1
  1656. if (t.gt.lt) then
  1657. it = lt
  1658. else
  1659. it = t
  1660. endif
  1661. c Initialise pb as P(t|t)
  1662. do i = 1, m
  1663. call dcopy(m, pt(:,i,t), 1, pb(:,i), 1)
  1664. enddo
  1665. c 4. abar(t) calc
  1666. c Compute: rs = st(:,t+1) - as(:,t)
  1667. do i = 1, m
  1668. rs(i) = st(i,t+1) - as(i,t)
  1669. enddo
  1670. c 5. Compute P(t)^-1 * (alpha(t+1) - a(t)) == ps^-1 * rs
  1671. c i.e. Solve ps * x = rs where ps is upper triangular
  1672. c On exit: rs = inv(ps) * rs
  1673. call dposv('u', m, 1, ps(:,:,it), m, rs, m, info)
  1674. if (info.ne.0) then
  1675. ifo = 1
  1676. print *, 'Error: Failed to solve [fscksimsm:5]'
  1677. endif
  1678. c 6. Initialise abar(t), i.e assign ab = at(:,t)
  1679. call dcopy(m, at(:,t), 1, ab, 1)
  1680. c 7. abar(t) calc: final part, put everything together
  1681. c Update: ab = ab + wt(:,:,t) * rs
  1682. alpha = 1.0
  1683. beta = 1.0
  1684. call dgemv('n',m,m, alpha, wt(:,:,it), m, rs, 1, beta, ab, 1)
  1685. c 8. Make a copy: wk = wt(:,:,t)
  1686. do i = 1, m
  1687. call dcopy(m, wt(:,i,it), 1, wk(:,i), 1)
  1688. enddo
  1689. c 9. Split P(t)^-1 into L. L^T => (W(t).L^-T) * (L^-1. W(t)^T)
  1690. c Compute: W(t) .L^-T == wk .L^-T == y
  1691. c i.e. Solve y .L = wk; Note: wk = y on exit
  1692. call dtrsm('r','u','n','n', m, m, alpha, ps(:,:,it), m, wk, m)
  1693. c 10. Update: pb = pb - wk * wk^T
  1694. alpha = -1.0
  1695. beta = 1.0
  1696. call dgemm('n','t',m,m,m, alpha, wk, m, wk, m, beta, pb, m)
  1697. c 11. Compute cholesky factorization of matrix 'pb'
  1698. call dpotrf('u', m, pb, m, info)
  1699. if (info.ne.0) then
  1700. ifo = 1
  1701. print *, ifo, 'Error: Failed to solve [fscksimsm:11]'
  1702. print *, 'pb = ', pb(1,:)
  1703. print *, 'pb = ', pb(2,:)
  1704. print *,t
  1705. stop
  1706. endif
  1707. c 12. Compute: st(:,t) = pb^T * st(:,t) where pb is upper triangular
  1708. c i.e. st(:,n) = chol(pb) * st(:,t)
  1709. call dtrmv('u','t','n', m, pb, m, st(:,t), 1)
  1710. c 13. Compute: st(:,t) = st(:,t) + alpha * ab
  1711. alpha = 1.0
  1712. call daxpy(m, alpha, ab, 1, st(:,t), 1)
  1713. enddo
  1714. end
  1715. ! -------------------------------------------------------------------
  1716. c subroutine returns the kernel for the log probability of the state
  1717. c non-time varying system matricies
  1718. subroutine ntlnprst(pr,res,cqt,r,n)
  1719. implicit none
  1720. integer r,n,t
  1721. real*8 res(r,n),cqt(r,r)
  1722. real*8 pr,alpha,ddot,logdetchol
  1723. c ----------------------
  1724. cf2py intent(inout) pr
  1725. cf2py intent(in) res
  1726. cf2py intent(in) cqt
  1727. cf2py intent(in) r
  1728. cf2py intent(in) n
  1729. c ----------------------
  1730. pr = 0.0
  1731. alpha = 1.0
  1732. call dtrsm('l','l','n','n',r,n,alpha,cqt,r,res,r)
  1733. do t = 1, n
  1734. pr = pr + ddot(r,res(:,t),1,res(:,t),1)
  1735. enddo
  1736. pr = -0.5*pr
  1737. end
  1738. c ------------------------------------------------------------------
  1739. c subroutine calculates the log determinant from the cholesky decompsion
  1740. c of a matrix.
  1741. real*8 function logdetchol(ch,m)
  1742. implicit none
  1743. integer m,i
  1744. real*8 ch(m,m)
  1745. logdetchol = 0.0
  1746. do i = 1, m
  1747. logdetchol = logdetchol + log(ch(i,i))
  1748. enddo
  1749. logdetchol = 2.0*logdetchol
  1750. end
  1751. c ------------------------------------------------------------------
  1752. c subroutine calculates the log determinant for gqg. This is really
  1753. c a generalised determinant as gqg does not need to be positive
  1754. c definite. Instead we need the determinant for the parts of gqg for
  1755. c which the diagonal is not zero
  1756. real*8 function glogdetchol(gcqt,m,r)
  1757. implicit none
  1758. integer m,r,i
  1759. real*8 gcqt(m,r),alpha
  1760. glogdetchol = 0.0
  1761. do i = 1, r
  1762. if (gcqt(i,i).eq.0.0) then
  1763. alpha = 0.0
  1764. else
  1765. alpha = log(gcqt(i,i))
  1766. endif
  1767. glogdetchol = glogdetchol + alpha
  1768. enddo
  1769. glogdetchol = 2.0*glogdetchol
  1770. end
  1771. c ------------------------------------------------------------------
  1772. subroutine printm(a,m,n)
  1773. implicit none
  1774. integer m,n,i,j
  1775. real*8 a(m,n)
  1776. do i = 1, m
  1777. write(*,*) (a(i,j),j=1,n)
  1778. enddo
  1779. end
  1780. c ------------------------------------------------------------------
  1781. subroutine setflag(info, ifo)
  1782. implicit none
  1783. integer info, ifo
  1784. if (info.ne.0) then
  1785. ifo = ifo + 1
  1786. c ifo = 1 (Optional)
  1787. endif
  1788. end
  1789. c ======================================================================
  1790. c PARALLELISABLE "NONAME" SIMSM CODE BELOW
  1791. c ======================================================================
  1792. c code to initialise a matrix with zeros
  1793. subroutine initm(a,m,n)
  1794. implicit none
  1795. integer i, j, m, n
  1796. real*8 a(m,n)
  1797. c$omp parallel default(shared) private(i,j)
  1798. c$omp do schedule(static)
  1799. do i = 1, m
  1800. do j = 1, n
  1801. a(i,j) = 0.0
  1802. enddo
  1803. enddo
  1804. c$omp end do
  1805. c$omp end parallel
  1806. end
  1807. c ----------------------------------------------------------------------
  1808. c Make a copy of the transpose of a matrix, i.e. set b = a'
  1809. subroutine mcopytr(a, b, m, n)
  1810. implicit none
  1811. integer m, n, j
  1812. real*8 a(m,n), b(n,m)
  1813. c$omp parallel default(shared) private(j)
  1814. c$omp do schedule(static)
  1815. do j = 1, n
  1816. c Compute: b(j,i) = a(i,j) forall i
  1817. call dcopy(m,a(:,j),1,b(j,:),1)
  1818. enddo
  1819. c$omp end do
  1820. c$omp end parallel
  1821. end
  1822. c ----------------------------------------------------------------------
  1823. c Make a copy of a matrix, i.e. set b(i,j) = a(i,j) forall (i,j)
  1824. subroutine mcopy(a, b, m, n)
  1825. implicit none
  1826. integer m, n, j
  1827. real*8 a(m,n), b(m,n)
  1828. c$omp parallel default(shared) private(j)
  1829. c$omp do schedule(static)
  1830. do j = 1, n
  1831. c Compute: b(i,j) = a(i,j) forall i
  1832. call dcopy(m, a(:,j), 1, b(:,j), 1)
  1833. enddo
  1834. c$omp end do
  1835. c$omp end parallel
  1836. end
  1837. c ---------------------------------------------------------------------
  1838. c Matrix plus matrix, i.e. b(i,j) = b(i,j) + a(i,j)
  1839. subroutine mplusm(a, b, m, n)
  1840. implicit none
  1841. integer m, n, j
  1842. real*8 a(m,n), b(m,n), alpha
  1843. alpha = 1.0
  1844. c$omp parallel default(shared) private(j)
  1845. c$omp do schedule(static)
  1846. do j = 1, n
  1847. call daxpy(m, alpha, a(:,j), 1, b(:,j), 1)
  1848. enddo
  1849. c$omp end do
  1850. c$omp end parallel
  1851. end
  1852. c ----------------------------------------------------------------------
  1853. c Matrix plus matrix, i.e. c(i,j) = a(i,j) + b(i,j) forall (i,j)
  1854. subroutine mplusm2(a, b, c, m, n)
  1855. implicit none
  1856. integer m, n, j
  1857. real*8 a(m,n), b(m,n), c(m,n), alpha
  1858. alpha = 1.0
  1859. c$omp parallel default(shared) private(j)
  1860. c$omp do schedule(static)
  1861. do j = 1, n
  1862. c Compute: c(:,j) = a(:,j)
  1863. call dcopy(m, a(:,j), 1, c(:,j), 1)
  1864. c Compute: c(:,j) = c(:,j) + b(:,j)
  1865. call daxpy(m, alpha, b(:,j), 1, c(:,j), 1)
  1866. enddo
  1867. c$omp end do
  1868. c$omp end parallel
  1869. end
  1870. c ----------------------------------------------------------------------
  1871. c This procedure computes gqg as: gqg = gt_i'.inv[qt].gt_i
  1872. subroutine compute_gqg(qt_type, gt_type, qt, gt_i, gqg, m,r, ifo)
  1873. implicit none
  1874. integer m, r, qt_type, gt_type, info, ifo
  1875. real*8 gqg(m,m), alpha, beta
  1876. real*8 qt(r,r), qtcopy(r,r)
  1877. real*8 gt_i(r,m), gt_i_copy(r,m), temp(m,r)
  1878. alpha = 1.0
  1879. beta = 0.0
  1880. ifo = 0
  1881. if(gt_type.eq.1) then ! gt is an identity matrix
  1882. c Assert (r == m )
  1883. if(qt_type.eq.3) then ! qt is the inverse of qt
  1884. call mcopy(qt, gqg, m, m) ! gqg = qt
  1885. else
  1886. call eye(gqg,m) ! Initialise gqg as Im
  1887. if(qt_type.eq.4) then! qt is the cholesky factorisation of qt
  1888. ! Compute inv[Q] by solving Q. inv[Q] = I
  1889. alpha = 1.0
  1890. call dtrsm('l','l','n','n',r,r,alpha,qt,r,gqg,m)
  1891. else ! qt is not a special case
  1892. call mcopy(qt, qtcopy,r,r) ! qtcopy = qt
  1893. c Compute: gqg = inv[Q], i.e. solve: Q.inv[Q] = I
  1894. call dposv('u',r,m,qtcopy,r,gqg,m,info)
  1895. call setflag(info, ifo)
  1896. endif
  1897. endif
  1898. c -----------------------------------------------
  1899. else ! i.e. gt_type != 1 and G is not an identity matrix
  1900. if(qt_type.eq.1) then ! qt is an identity matrix
  1901. c Compute: gqg = gt_i'.gt_i [i.e. (m,r) x (r,m)]
  1902. call dgemm('t','n', m, m, r, alpha, gt_i, m, gt_i, m,
  1903. + beta, gqg, m)
  1904. elseif(qt_type.eq.3) then ! input qt is the inverse of qt
  1905. c Compute: temp = gt_i' * qt & gqg = temp * gt_i
  1906. call dgemm('t','n', m, r, r, alpha, gt_i, r, qt, r,
  1907. + beta, temp, m)
  1908. call dgemm('n','n', m, m, r, alpha, temp, m, gt_i, m,
  1909. + beta, gqg, m)
  1910. elseif(qt_type.eq.4) then ! input qt is the chol fact of qt
  1911. call mcopy(gt_i, gt_i_copy,r,m) ! gt_i_copy = gt_i
  1912. c a. Compute: inv[qt].gt_i by solving qt.x = gt_i
  1913. call dtrsm('l','l','n','n', r, m, alpha, qt,
  1914. + r, gt_i_copy, r)
  1915. c b. Compute gqg = gt_i'.x
  1916. call dgemm('t','n', m, m, r, alpha, gt_i, r, gt_i_copy,
  1917. + r, beta, gqg, m)
  1918. else
  1919. c Compute: qt_i = inv[G]'.inv[Q].inv[G]
  1920. c Note: inv[G]'.inv[Q].inv[G] = inv[G]'.inv[L.L'].inv[G]
  1921. c = inv[G]'.inv[L'].inv[L].inv[G]
  1922. c = (inv[L].inv[G])'.(inv[L].inv[G])
  1923. c = x'.x where x = inv[L].inv[G]
  1924. c a. Compute cholesky decomposition of qt, i.e. of qtcopy
  1925. call mcopy(qt, qtcopy, r, r) ! qtcopy = qt
  1926. call dpotrf('l', r, qtcopy, r, info)
  1927. call mcopy(gt_i, gt_i_copy,r,m) ! gt_i_copy = gt_i
  1928. ! POTENTIAL ERROR? ZERO UPPER PART OF gt_i_copy?
  1929. c b. Solve: L.x = inv[G]
  1930. call dtrsm('l','l','n','n', r, m, alpha, qtcopy,
  1931. + r, gt_i_copy, r)
  1932. c c. Compute: gqg = x'.x
  1933. call dgemm('t','n', m, m, r, alpha, gt_i_copy,
  1934. + r, gt_i_copy, r, beta, gqg, m)
  1935. endif
  1936. endif
  1937. if(ifo.gt.0) print *, 'Error: Failed to solve [compute_gqg]'
  1938. end
  1939. c ----------------------------------------------------------
  1940. c Compute: z_h = Z'.inv[H]
  1941. subroutine compute_zh(ht_type, ht, zt, z_h, p, m, n_p)
  1942. implicit none
  1943. integer p, m, ht_type, info, j, n_p
  1944. real*8 htcopy(p,p), ht(p,n_p), zt(p,m), z_h(m,p), alpha, beta
  1945. call mcopytr(zt, z_h, p, m) ! z_h = zt'
  1946. ! Note: if(ht_type.eq.1) then do nothing
  1947. if(ht_type.eq.2) then ! diagonal matrix
  1948. c$omp parallel default(shared)
  1949. c$omp do schedule(static) private(j, alpha)
  1950. do j = 1, p ! Iterate through columns of z_h
  1951. alpha = 1.0 / ht(j,1)
  1952. c Compute: z_h(:,j) = alpha *z_h(:,j)
  1953. call dscal(m, alpha, z_h(:,j), 1)
  1954. enddo
  1955. c$omp end do
  1956. c$omp end parallel
  1957. elseif(ht_type.eq.3) then! ht is the inverse of ht
  1958. alpha = 1.0
  1959. beta = 0.0
  1960. c Compute: z_h = Z'* ht
  1961. call dgemm('t','n',m,p,p,alpha, zt, p, ht, p, beta, z_h, m)
  1962. elseif(ht_type.eq.4) then ! ht is the cholesky fact of ht
  1963. c Compute: z_h = Z' * ht_i by solving for z_h in z_h * ht = Z'
  1964. alpha = 1.0
  1965. call dtrsm('r','l','n','n',m,p,alpha,ht,p,z_h,m)
  1966. else ! None of the above special cases
  1967. call mcopy(ht,htcopy,p,p) ! htcopy = ht
  1968. c Compute cholesky decomposition of htcopy:
  1969. call dpotrf('l', p, htcopy, p, info)
  1970. if(info.gt.0) print *, 'Error: Failed to solve [compute_zh]'
  1971. c Compute: z_h = Z' * ht_i => Solve for z_h in z_h * ht = Z'
  1972. alpha = 1.0
  1973. call dtrsm('r','l','n','n',m,p,alpha,htcopy,p,z_h,m)
  1974. endif
  1975. end
  1976. c -----------------------------------------------------------
  1977. c Compute: z_h_z = z_h * z if beta = 0.0
  1978. c OR z_h_z += z_h * z if beta = 1.0
  1979. subroutine compute_zhz(zt_type, z_h, zt, z_h_z, beta, m, p)
  1980. implicit none
  1981. integer zt_type, m, p
  1982. real*8 z_h_z(m,m), z_h(m,p), zt(p,m), alpha, beta
  1983. alpha = 1.0
  1984. if(zt_type.eq.1) then ! zt is an identity matrix
  1985. !Assert (p == m)
  1986. if(beta.eq.0.0) then
  1987. call mcopy(z_h, z_h_z, m, m) ! z_h_z = z_h
  1988. else
  1989. call mplusm(z_h, z_h_z, m, m)! z_h_z = z_h_z + z_h
  1990. endif
  1991. else ! zt is not an identity matrix. Do multiplication
  1992. call dgemm('n','n',m,m,p,alpha,z_h,m,zt,p,beta,z_h_z,m)
  1993. endif
  1994. end
  1995. c --------------------------------------------------------------
  1996. c Compute: tgqgt = T'.gqgt if beta = 0.0
  1997. c OR tgqgt += T'.gqgt if beta = 1.0
  1998. subroutine compute_tgqgt(tt_type, tt, gqgt, tgqgt, beta, m)
  1999. c Note: temp may be initialised as temp = z_h_z
  2000. implicit none
  2001. integer tt_type, m
  2002. real*8 tgqgt(m,m), gqgt(m,m), tt(m,m), alpha, beta
  2003. alpha = 1.0
  2004. if(tt_type.eq.1) then ! is an identity matrix
  2005. if(beta.eq.0.0) then
  2006. call mcopy(gqgt, tgqgt, m, m) ! tgqgt = gqgt
  2007. else
  2008. call mplusm(gqgt, tgqgt, m, m)! tgqgt += gqgt
  2009. endif
  2010. else ! not identity matrix. Do multiplication
  2011. call dgemm('t','n',m,m,m,alpha,tt,m,gqgt,m,beta,tgqgt,m)
  2012. endif
  2013. end
  2014. c ------------------------------------------------------------
  2015. c Procedure to calculate the pseudo inverse of a rectangular matrix
  2016. subroutine compute_pseudoinv(mat, pinv, m, r, lwk)
  2017. implicit none
  2018. integer r, m, i, j, k, info, lwk
  2019. real*8 mat(m,r), smat(m,r), pinv(r,m), alpha, beta
  2020. real*8 umat(m,m), vtmat(r,r), v_si(r,m)
  2021. real*8 wk(lwk), tol
  2022. cf2py intent(in) mat
  2023. cf2py intent(inout) pinv
  2024. cf2py intent(in) m
  2025. cf2py intent(in) r
  2026. cf2py intent(in) lwk
  2027. c Note: SVD of matrix A is A = U.S.V' where S is diagonal
  2028. c Note: pinv = inv[A] = V.inv[S].U'
  2029. c Note: |inv[S]| = rxm.
  2030. c Note: To get inv[S] take recipricols of diagonals (and transpose)
  2031. tol = 0.00000001
  2032. c Compute singular value decomposition:
  2033. call dgesvd('a','a',m, r, mat, m, smat, umat, m, vtmat, r,
  2034. + wk, lwk, info)
  2035. if(info.gt.0) print *, 'Error: SVD failed [compute_pseudoinv]'
  2036. c Compute: v_si = v.inv[S] i.e. (r,m) = (r,r) * (r,m)
  2037. k = min(m,r)
  2038. c$omp parallel default(shared) private(alpha, i, j)
  2039. c$omp do schedule(static)
  2040. do j = 1, k
  2041. alpha = 0.0
  2042. ! Check whether smat(j,j) is zero or not
  2043. ! otherwise recipricol will be infinity
  2044. if(smat(j,j).gt.tol) then
  2045. alpha = 1.0 / smat(j,j)
  2046. endif
  2047. ! Row j of vtmat becomes column j. Multiply elements by alpha.
  2048. do i = 1, r
  2049. v_si(i,j) = alpha * vtmat(j,i)
  2050. enddo
  2051. enddo
  2052. c$omp end do
  2053. ! Zero remaining columns
  2054. c$omp do schedule(static)
  2055. do j = k+1, m
  2056. do i = 1, r
  2057. v_si(i,j) = 0.0
  2058. enddo
  2059. enddo
  2060. c$omp end do
  2061. c$omp end parallel
  2062. c Compute: pinv = v_si * u', (r,m) = (r,m) * (m,m)
  2063. alpha = 1.0
  2064. beta = 0.0
  2065. call dgemm('n','t', r, m, m, alpha, v_si, r, umat,
  2066. + m, beta, pinv, r)
  2067. end
  2068. c -----------------------------------------------------------
  2069. c This procedure converts the diagonal and below diagonal blocks
  2070. c to the banded matrix storage scheme.
  2071. subroutine update_bands(bmat, block1, block2, t, m, two_m, mn)
  2072. implicit none
  2073. integer i, j, t, m, st, en, jstar, two_m, mn
  2074. real*8 bmat(two_m, mn)
  2075. real*8 block1(m,m), block2(m,m)
  2076. jstar = (t-1)*m
  2077. c$omp parallel default(shared) private(j, i, st, en)
  2078. c$omp do schedule(static)
  2079. do j = 1, m ! Iterate through columns of the t-th block
  2080. st = 1
  2081. en = 1 + m - j ! One element less per column
  2082. bmat(st:en, jstar + j) = block1(j:m, j) ! Copy below diagonal only
  2083. st = en + 1
  2084. en = st + m - 1
  2085. ! Copy all of block2. i.e. bmat(st:en, jstar + j) = - block2(:, j)
  2086. do i = 1, m
  2087. bmat(st + i - 1, jstar + j) = -1 * block2(i,j)
  2088. enddo
  2089. ! Add zeros at the end of the column. Reason:
  2090. ! 1) band continues outside block, OR
  2091. ! 2) subdiagonal band has fewer elements than main diagonal
  2092. do i = en+1, two_m
  2093. bmat(i, jstar + j) = 0.0
  2094. enddo
  2095. enddo
  2096. c$omp end do
  2097. c$omp end parallel
  2098. end
  2099. c -----------------------------------------------------------------
  2100. c This procedure converts the last block to the banded matrix storage scheme
  2101. subroutine finalise_bands(bmat, block, t, m, two_m, mn)
  2102. implicit none
  2103. integer t, m, st, en, jstar, i, j, two_m, mn
  2104. real*8 bmat(two_m, mn)
  2105. real*8 block(m,m)
  2106. jstar = (t-1)*m
  2107. c$omp parallel default(shared) private(i, j, st, en)
  2108. c$omp do schedule(static)
  2109. do j = 1, m ! Iterate through columns of the t-th block
  2110. st = 1
  2111. en = 1 + m - j
  2112. bmat(st:en, jstar + j) = block(j:m, j) ! Copy below diagonal only
  2113. ! Add zeros at the end of the column. Reason:
  2114. ! 1) band continues outside block, OR
  2115. ! 2) subdiagonal band has fewer elements than main diagonal
  2116. do i = en+1, two_m
  2117. bmat(i, jstar + j) = 0.0
  2118. enddo
  2119. enddo
  2120. c$omp end do
  2121. c$omp end parallel
  2122. end
  2123. c -----------------------------------------------------------------
  2124. subroutine convert_banded(bmat, dense, m, n, sym)
  2125. c Input: bmat is a lower triangular banded matrix in special structure
  2126. c Output: dense is a copy of bmat in std matrix format
  2127. c Note: dense is symmetric
  2128. implicit none
  2129. integer b, i, j, m, n, sym
  2130. real*8 bmat(m, n), dense(n,n)
  2131. c$omp parallel default(shared) private(i, j, b)
  2132. c$omp do schedule(static)
  2133. do i = 1, n
  2134. do j = 1, n
  2135. dense(i,j) = 0.0
  2136. enddo
  2137. enddo
  2138. c$omp end do
  2139. c$omp do schedule(static)
  2140. do b = 1, m ! For band b
  2141. do j = 1, n + 1 - b ! For jth element in band b
  2142. dense(b - 1 + j, j) = bmat(b, j)
  2143. enddo
  2144. enddo
  2145. c$omp end do
  2146. if (sym.eq.1) then
  2147. c$omp do schedule(static)
  2148. do b = 1, m ! For band b
  2149. do j = 1, n + 1 - b ! For jth element in band b
  2150. dense(j, b - 1 + j) = bmat(b,j) ! Symmetric component
  2151. enddo
  2152. enddo
  2153. c$omp end do
  2154. endif
  2155. c$omp end parallel
  2156. end
  2157. c --------------------------------------------------------------
  2158. c Sampling procedure, i.e. state ~ Nc(bmat.mu, bmat) = N(mu, inv[bmat])
  2159. subroutine sample_state(bmat, mu, state, mn, two_m)
  2160. implicit none
  2161. integer info, mn, two_m
  2162. real*8 bmat(two_m, mn), dense(mn,mn)
  2163. real*8 state(mn), mu(mn), alpha
  2164. info = 0
  2165. c Solve: bmat.mu = rhs where rhs is recorded in variable mu initially
  2166. c Note: bmat overwritten with cholesky decomposition, i.e. matrix L
  2167. call dpbsv('l', mn, two_m-1, 1, bmat, two_m, mu, mn, info)
  2168. if(info.gt.0) then
  2169. print *, info, 'Error: Failed to sovlve [sample state]'
  2170. print *, 'bmat =', bmat(1, :5)
  2171. print *, 'bmat =', bmat(2, :5)
  2172. print *, 'bmat =', bmat(3, :5)
  2173. print *, 'bmat =', bmat(4, :5)
  2174. call convert_banded(bmat, dense, two_m, mn, 1)
  2175. print *, dense(1,:6)
  2176. print *, dense(2,:6)
  2177. print *, dense(3,:6)
  2178. print *, dense(4,:6)
  2179. stop
  2180. endif
  2181. c Sampling step compute: sta = mu + inv[L'].randval
  2182. c a. Set x = inv[L'].randval => L'.x = sta => Solve for x
  2183. c Note: sta overwritten with x
  2184. call dtbsv('l','t','n', mn, two_m - 1, bmat, two_m, state, 1) ! original code
  2185. c b. Compute: sta = mu + x, i.e. sta = sta + mu
  2186. alpha = 1.0
  2187. call daxpy(mn, alpha, mu, 1, state, 1)
  2188. end
  2189. c ----------------------------------------------------------------------
  2190. c Non time varying version of noname sim smoother
  2191. subroutine nt_noname_simsm(dense, rhs, sta, y, tt, ht, zt,
  2192. + qt, gt_i, p1, a1, ht_type, zt_type, qt_type, gt_type, tt_type,
  2193. + ifo, two_m, mn, m, n, p, r, n_p)
  2194. c Special: Calcs altered when zt, ht, qt, tt are special matrices
  2195. c Note: nseries stored as p; nstate stored as m
  2196. c Note: nobs stored as n; rstate stored as r
  2197. c Note: T stored as tt; P(1) stored as p1
  2198. c Note: Q stored as qt; Z stored as zt
  2199. c Note: inv[G] stored as gt_i; H stored as ht
  2200. c Note: a(1) stored as a1; y(t) stored as yt
  2201. c Note: On exit sta is the state vector.
  2202. c Note: On entry sta is a vector of random numbers
  2203. implicit none
  2204. integer m, n, p, r, ifo, info, mn, two_m, t, st, n_p
  2205. integer ht_type, qt_type, gt_type, tt_type, zt_type
  2206. real*8 tt(m,m), ht(p,n_p), zt(p,m), qt(r,r), gt_i(r,m), z_h(m,p)
  2207. real*8 p1(m,m), a1(m), y(p,n), alpha, beta
  2208. real*8 sta(mn)
  2209. real*8 gqg(m,m), gqgt(m,m)
  2210. real*8 temp(m,m), diag_1(m,m), diag_2(m,m), diag_3(m,m)
  2211. real*8 mu(mn), p1_i(m,m), p1copy(m,m)
  2212. real*8 bmat(two_m, mn)
  2213. real*8 dense(mn,mn), lblock(m,m), rhs(mn)
  2214. c ----------------------
  2215. cf2py intent(in) y
  2216. cf2py intent(in) tt
  2217. cf2py intent(in) ht
  2218. cf2py intent(in) zt
  2219. cf2py intent(in) qt
  2220. cf2py intent(in) gt_i
  2221. cf2py intent(in) p1
  2222. cf2py intent(in) a1
  2223. cf2py intent(in) ht_type
  2224. cf2py intent(in) qt_type
  2225. cf2py intent(in) gt_type
  2226. cf2py intent(in) tt_type
  2227. cf2py intent(in) zt_type
  2228. cf2py intent(in) p
  2229. cf2py intent(in) m
  2230. cf2py intent(in) n
  2231. cf2py intent(in) r
  2232. cf2py intent(in) n_p
  2233. cf2py intent(in) mn
  2234. cf2py intent(in) two_m
  2235. cf2py intent(inout) ifo
  2236. cf2py intent(inout) sta
  2237. cf2py intent(inout) dense
  2238. cf2py intent(inout) rhs
  2239. c ----------------------
  2240. alpha = 1.0
  2241. beta = 0.0
  2242. c ------------------------------------------------------------------
  2243. c$omp parallel default(shared)
  2244. c$omp sections
  2245. c$omp section
  2246. c Compute: p1_i = inv(p1) => Solve p1 * p1_i = I
  2247. call eye(p1_i, m) ! Initialise as identity , i.e. p1_i = Im
  2248. c$omp section
  2249. c Make a copy: p1copy = p1
  2250. call mcopy(p1, p1copy, m, m)
  2251. c$omp end sections
  2252. c Wait for the above to be completed
  2253. c$omp single
  2254. c Now do solve; Note: p1copy overwritten
  2255. call dposv('u',m,m,p1copy,m,p1_i,m,info)
  2256. call setflag(info, ifo)
  2257. if(info.gt.0) print *, 'Error: Failed to solve [nt_noname_simsm]'
  2258. c$omp end single
  2259. c ------------------------------------------------------------------
  2260. c$omp sections
  2261. c$omp section
  2262. c Compute: z_h = Z'.inv[H]
  2263. call compute_zh(ht_type, ht, zt, z_h, p, m, n_p)
  2264. c ------------------------------------------------------------------
  2265. c$omp section
  2266. c Compute: gqg = inv[G]'.inv[Q].inv[G]
  2267. call compute_gqg(qt_type, gt_type, qt, gt_i, gqg, m, r, ifo)
  2268. c ------------------------------------------------------------------
  2269. c Compute: gqgt = gqg * T;
  2270. if(tt_type.eq.1) then ! is an identity matrix
  2271. call mcopy(gqg, gqgt, m, m)
  2272. else ! not identity matrix
  2273. call dgemm('n','n',m,m,m,alpha,gqg,m,tt,m,beta,gqgt,m)
  2274. endif
  2275. c ------------------------------------------------------------------
  2276. c$omp end sections
  2277. c Wait for the above to be completed
  2278. c$omp single
  2279. c Compute: temp = z_h * Z
  2280. beta = 0.0
  2281. call compute_zhz(zt_type, z_h, zt, temp, beta, m, p)
  2282. call mcopy(temp, diag_3, m,m) ! Set diag_3 = temp
  2283. c ------------------------------------------------------------------
  2284. c Compute: temp += T'.gqgt
  2285. beta = 1.0
  2286. call compute_tgqgt(tt_type, tt, gqgt, temp, beta, m)
  2287. c$omp end single
  2288. c Wait for the above to be completed
  2289. c diag_1 and diag_2 calcs:
  2290. c$omp sections
  2291. c$omp section
  2292. call mplusm2(temp, p1_i, diag_1, m, m) ! diag_1 = temp + p1_i
  2293. c$omp section
  2294. call mplusm2(temp, gqg, diag_2, m, m) ! diag_2 = temp + gqg
  2295. c$omp section
  2296. call mplusm(gqg, diag_3, m, m) ! diag_3 += gqg
  2297. c$omp end sections
  2298. c -----------------------------------------------------------------
  2299. c$omp single
  2300. c Compute: mu
  2301. t = 1
  2302. c Compute: mu = z_h * y ( == z_h_y)
  2303. beta = 0.0
  2304. call dgemv('n', m, p, alpha, z_h, m, y(:,1), 1, beta, mu(1:m), 1)
  2305. c Compute: mu = mu + p1_i * a1
  2306. beta = 1.0
  2307. call dgemv('n',m,m,alpha, p1_i, m, a1, 1, beta, mu(1:m), 1)
  2308. beta = 0.0
  2309. !st = m + 1 Use code when run sequentially
  2310. c$omp end single
  2311. c ------------------------------------------------------------------
  2312. c$omp do schedule(static) private(t, st)
  2313. do t = 2, n
  2314. st = (t-1)*m + 1 ! Use code when run in parallel
  2315. c Compute: mu = z_h * y(t) ( == z_h_y)
  2316. call dgemv('n', m, p, alpha, z_h, m, y(:,t), 1, beta,
  2317. + mu(st:st + m - 1), 1)
  2318. !st = st + m ! Use code when run sequentially
  2319. enddo
  2320. c$omp end do
  2321. c ------------------------------------------------------------------
  2322. call mcopy(gqgt, lblock, m, m) ! Set lblock = gqgt
  2323. c$omp single
  2324. c Build banded matrix: (Copy column vectors from block matrices)
  2325. t = 1
  2326. call update_bands(bmat, diag_1, lblock, t, m, two_m, mn)
  2327. c$omp end single
  2328. c ------------------------------------------------------------------
  2329. c$omp do schedule(static) private(t)
  2330. do t = 2, n-1
  2331. call update_bands(bmat, diag_2, lblock, t, m, two_m, mn)
  2332. enddo
  2333. c$omp end do
  2334. c$omp end parallel
  2335. t = n
  2336. call finalise_bands(bmat, diag_3, t, m, two_m, mn)
  2337. c -----------------------------------------------------------
  2338. ! Debugging only: Remove from code completely
  2339. call convert_banded(bmat, dense, two_m, mn, 1)
  2340. call dcopy(mn, mu, 1, rhs, 1) ! rhs = mu
  2341. c --------------------------------------------------------------
  2342. c Sample state from ~ N(mu, inv[bmat])
  2343. call sample_state(bmat, mu, sta, mn, two_m) ! banded matrix input
  2344. end
  2345. c ------------------------------------------------------------------
  2346. c Procedure determines index of time varying system matrix
  2347. integer function timet(n, t)
  2348. implicit none
  2349. integer n, t
  2350. c Choose t th matrix or first. n > 1 => time varying
  2351. timet = 1
  2352. if(n.gt.1) then
  2353. timet = t
  2354. endif
  2355. return
  2356. end function timet
  2357. c ------------------------------------------------------------------
  2358. c Time varying (non parallel) version of noname smoother
  2359. subroutine tv_noname_simsm(sta, y, tt, ht, zt, qt, gt, p1,
  2360. + a1, ht_type, zt_type, qt_type, gt_type, tt_type, ifo, two_m, mn,
  2361. + m, n, p, r, n_t, n_h, n_z, n_q, n_g, n_p)
  2362. implicit none
  2363. c Note: Calcs altered when zt, ht, qt, tt are be identity matrices
  2364. c Note: nseries stored as p; nstate stored as m
  2365. c Note: rstate stored as r; nobs stored as n
  2366. c Note: T(t) stored as tt; P(t) stored as pt
  2367. c Note: H(t) stored as ht; G(t) stored as gt
  2368. c Note: Z(t) stored as zt; Q(t) stored as qt
  2369. c Note: On exit st is the state. On entry st is a matrix of random numbers
  2370. c Input variables:
  2371. integer m, n, p, r, mn, two_m
  2372. integer ht_type, qt_type, gt_type, tt_type, zt_type ! matrix indicators
  2373. integer n_t, n_h, n_z, n_q, n_g , n_p
  2374. real*8 tt(m,m,n_t), qt(r,r,n_q), y(p,n)
  2375. real*8 ht(p,n_p,n_h), zt(p,m,n_z), gt(r,m,n)
  2376. real*8 p1(m,m), a1(m), alpha, beta, sta(mn)
  2377. c Local variables:
  2378. integer t, info, ifo, st, lwk, timet
  2379. integer t_z, t_h, t_t, t_q, t_g
  2380. real*8 z_h(m,p), gqg(m,m), gt_i(m,r), gqg_prev(m,m)
  2381. real*8 p1_i(m,m), p1copy(m,m), diag(m,m)
  2382. real*8 gqgt(m,m), mu(mn) , zhz(m,m), tgqgt(m,m)
  2383. real*8 bmat(two_m, mn), lblock(m,m)
  2384. c ----------------------
  2385. cf2py intent(in) y
  2386. cf2py intent(in) tt
  2387. cf2py intent(in) ht
  2388. cf2py intent(in) zt
  2389. cf2py intent(in) qt
  2390. cf2py intent(in) p1
  2391. cf2py intent(in) a1
  2392. cf2py intent(in) ht_type
  2393. cf2py intent(in) qt_type
  2394. cf2py intent(in) gt_type
  2395. cf2py intent(in) tt_type
  2396. cf2py intent(in) zt_type
  2397. cf2py intent(in) p
  2398. cf2py intent(in) m
  2399. cf2py intent(in) n
  2400. cf2py intent(in) r
  2401. cf2py intent(in) mn
  2402. cf2py intent(in) two_m
  2403. cf2py intent(inout) ifo
  2404. cf2py intent(inout) st
  2405. cf2py intent(in) n_h
  2406. cf2py intent(in) n_q
  2407. cf2py intent(in) n_g
  2408. cf2py intent(in) n_t
  2409. cf2py intent(in) n_z
  2410. cf2py intent(in) n_p
  2411. c ----------------------
  2412. alpha = 1.0
  2413. ! Initialise parameter for DGESVD function
  2414. lwk = 50
  2415. c ------------------------------------------
  2416. c Compute: p1_i = inv(p1) => Solve p1 * p1_i = I
  2417. call eye(p1_i,m) ! Initialise as identity
  2418. c Make a copy: set p1copy = p1
  2419. call mcopy(p1,p1copy,m,m)
  2420. c Now do solve. Note: p1copy overwritten
  2421. call dposv('u',m,m,p1copy,m,p1_i,m,info)
  2422. call setflag(info, ifo)
  2423. if(info.gt.0) print *, "Error: Failed to solve [tv_noname_simsm]"
  2424. c ------------------------------------------
  2425. st = 1
  2426. do t = 1, n-1
  2427. c Time varying matrix selection: choose t th matrix or first
  2428. t_t = timet(n_t, t)
  2429. t_z = timet(n_z, t)
  2430. t_h = timet(n_h, t)
  2431. t_q = timet(n_q, t)
  2432. t_g = timet(n_g, t)
  2433. c -----------------------------------------------
  2434. c Compute: z_h
  2435. c Note: Computed at least once. Always computed if z or h are time varying
  2436. if((t.eq.1).or.(n_z.gt.1).or.(n_h.gt.1)) then
  2437. call compute_zh(ht_type, ht(:,:,t_h), zt(:,:,t_z),
  2438. + z_h, p, m, n_p)
  2439. endif
  2440. c -----------------------------------------------
  2441. c Compute: gt_i using singular value decomposition
  2442. c Note: Computed at least once. Always computed if g is time varying
  2443. if((t.eq.1.).or.(n_g.gt.1)) then
  2444. call compute_pseudoinv(gt(:,:,t_g), gt_i, r, m, lwk)
  2445. endif
  2446. c -------------------------------------------------------
  2447. c Compute: gqg(t) = inv[G(t)]'.inv[Q(t)].inv[G(t)]
  2448. c Note: Computed at least once. Always computed if g or q are time varying
  2449. if((t.eq.1).or.(n_g.gt.1).or.(n_q.gt.1)) then
  2450. call compute_gqg(qt_type, gt_type, qt(:,:,t_q), gt_i,
  2451. + gqg, m, r, ifo)
  2452. endif
  2453. c ----------------------------------
  2454. c Compute: gqgt(t) = gqg(t) * T;
  2455. if((t.eq.1).or.(n_g.gt.1).or.(n_q.gt.1).or.(n_t.gt.1)) then
  2456. if(tt_type.eq.1) then ! is an identity matrix
  2457. call mcopy(gqg, gqgt, m, m)
  2458. else ! not identity matrix
  2459. beta = 0.0
  2460. call dgemm('n','n',m,m,m, alpha, gqg, m, tt(:,:,t_t),
  2461. + m, beta, gqgt, m)
  2462. endif
  2463. endif
  2464. c ----------------------------------
  2465. c Compute: diag = Z'.inv[H].Z + T'.inv[Q].T
  2466. beta = 0.0
  2467. c Note: Computed at least once. Always computed if z or h are time varying
  2468. if((t.eq.1).or.(n_z.gt.1).or.(n_h.gt.1)) then
  2469. call compute_zhz(zt_type, z_h, zt(:,:,t_z), zhz,
  2470. + beta, m, p)
  2471. endif
  2472. if((t.eq.1).or.(n_t.gt.1).or.(n_g.gt.1).or.(n_q.gt.1)) then
  2473. call compute_tgqgt(tt_type, tt(:,:,t_t), gqgt,
  2474. + tgqgt, beta, m)
  2475. endif
  2476. call mcopy(zhz, diag, m , m)
  2477. call mplusm(tgqgt, diag, m, m)
  2478. c ----------------------------------
  2479. c Main diagonal block calcs:
  2480. if(t.eq.1) then ! Compute: diag += p1_i
  2481. call mplusm(p1_i, diag, m, m)
  2482. else ! t > 1 => Compute: diag += gqg(t-1)
  2483. call mplusm(gqg_prev, diag, m, m)
  2484. endif
  2485. c -----------------------------------
  2486. c mu calcs:
  2487. c Compute: mu = z_h(t) * y(t) ( == z_h_y)
  2488. beta = 0.0
  2489. call dgemv('n',m,p,alpha,z_h,m,y(:,t),1,beta,mu(st:st+m-1),1)
  2490. if(t.eq.1) then
  2491. c Compute: mu = mu + p1_i * a1
  2492. beta = 1.0
  2493. call dgemv('n',m,m,alpha,p1_i,m,a1,1,beta,mu(1:m),1)
  2494. endif
  2495. st = st + m ! Compute next start pos, i.e. st = (t-1)*m + 1
  2496. c ---------------------------------------------------
  2497. call mcopytr(gqgt, lblock, m, m) ! Set lblock = transpose[gqgt]
  2498. c Continue construction of banded system
  2499. c Copy column vectors from current block matrices
  2500. call update_bands(bmat, diag, lblock, t, m, two_m, mn)
  2501. c -------------------------------------------------
  2502. gqg_prev = gqg ! Make a copy for next time step
  2503. enddo
  2504. c -----------------------------------------------------------
  2505. t = n
  2506. c Time varying matrix selection: choose t th matrix or first
  2507. t_z = timet(n_z, t)
  2508. t_h = timet(n_h, t)
  2509. t_q = timet(n_q, t)
  2510. t_g = timet(n_g, t)
  2511. if((t.eq.1).or.(n_g.gt.1)) then
  2512. call compute_pseudoinv(gt(:,:,t_g), gt_i, r, m, lwk)
  2513. endif
  2514. c Compute: gqg = inv[G(t)]'.inv[Q(t)].inv[G(t)]
  2515. if((t.eq.1).or.(n_g.gt.1).or.(n_q.gt.1)) then
  2516. call compute_gqg(qt_type, gt_type, qt(:,:,t_q), gt_i,
  2517. + gqg, m, r, ifo)
  2518. endif
  2519. c Compute: z_h
  2520. if((n_z.gt.1).or.(n_h.gt.1)) then
  2521. call compute_zh(ht_type, ht(:,:,t_h), zt(:,:,t_z), z_h,
  2522. + p, m, n_p)
  2523. endif
  2524. c Compute: diag = z_h_z
  2525. beta = 0.0
  2526. call compute_zhz(zt_type, z_h, zt(:,:,t_z), diag, beta, m, p)
  2527. c Compute: diag += gqg
  2528. call mplusm(gqg, diag, m, m)
  2529. c Compute: mu = z_h(t) * y(t) ( == z_h_y)
  2530. beta = 0.0
  2531. call dgemv('n', m, p, alpha, z_h, m, y(:,t), 1,
  2532. + beta, mu(st:st+m-1), 1)
  2533. call finalise_bands(bmat, diag, t, m, two_m, mn)
  2534. c ----------------------------------------------------
  2535. call sample_state(bmat, mu, sta, mn, two_m)
  2536. end
  2537. c ---------------------------------------------------------------------
  2538. c Time varying (parallel) version of noname smootherc
  2539. c WARNING 1: MEMORY REQUIREMENTS ARE MUCH LARGER - MUST STORE ALL gqg
  2540. c AND EACH THREAD MUST HAVE A gqgt, diag, z_h, etc
  2541. subroutine tv_noname_simsmp(sta, y, tt, ht, zt, qt, gt,
  2542. + p1, a1, ht_type, zt_type, qt_type, gt_type, tt_type, ifo,
  2543. + two_m, mn, m, n, p, r, n_t, n_h, n_z, n_q, n_g, n_p)
  2544. implicit none
  2545. c Note: Calcs altered when zt, ht, qt, tt are be identity matrices
  2546. c Note: nseries stored as p; nstate stored as m
  2547. c Note: rstate stored as r; nobs stored as n
  2548. c Note: T(t) stored as tt; P(t) stored as pt
  2549. c Note: H(t) stored as ht; G(t) stored as gt
  2550. c Note: Z(t) stored as zt; Q(t) stored as qt
  2551. c Note: On exit st is the state. On entry st is a matrix of random numbers
  2552. c Input variables:
  2553. integer m, n, p, r, mn, two_m
  2554. integer n_t, n_h, n_z, n_q, n_g, n_p
  2555. integer ht_type, qt_type, gt_type, tt_type, zt_type ! matrix indicators
  2556. real*8 tt(m,m,n_t), qt(r,r,n_q), y(p,n)
  2557. real*8 ht(p,n_p,n_h), zt(p,m,n_z), gt(r,m,n_g)
  2558. real*8 p1(m,m), a1(m), alpha, beta, sta(mn)
  2559. c Local variables:
  2560. integer t, info, ifo, st, lwk, timet
  2561. integer t_z, t_h, t_t, t_q, t_g
  2562. real*8 z_h(m,p), gqg(m,m,n), gt_i(m,r)
  2563. real*8 p1_i(m,m), p1copy(m,m), diag(m,m)
  2564. real*8 gqgt(m,m), mu(mn), zhz(m,m), tgqgt(m,m)
  2565. real*8 bmat(two_m, mn), lblock(m,m)
  2566. c ----------------------
  2567. cf2py intent(in) y
  2568. cf2py intent(in) tt
  2569. cf2py intent(in) ht
  2570. cf2py intent(in) zt
  2571. cf2py intent(in) qt
  2572. cf2py intent(in) p1
  2573. cf2py intent(in) a1
  2574. cf2py intent(in) ht_type
  2575. cf2py intent(in) qt_type
  2576. cf2py intent(in) gt_type
  2577. cf2py intent(in) tt_type
  2578. cf2py intent(in) zt_type
  2579. cf2py intent(in) p
  2580. cf2py intent(in) m
  2581. cf2py intent(in) n
  2582. cf2py intent(in) r
  2583. cf2py intent(in) mn
  2584. cf2py intent(in) two_m
  2585. cf2py intent(inout) ifo
  2586. cf2py intent(inout) st
  2587. cf2py intent(in) n_h
  2588. cf2py intent(in) n_q
  2589. cf2py intent(in) n_g
  2590. cf2py intent(in) n_t
  2591. cf2py intent(in) n_z
  2592. cf2py intent(in) n_p
  2593. c ----------------------
  2594. alpha = 1.0
  2595. c WARNING 2: Initialise parameter for DGESVD function.
  2596. c Setting incorrect value may cause issues
  2597. lwk = 50
  2598. c ------------------------------------------
  2599. c$omp parallel default(shared)
  2600. c$omp sections
  2601. c$omp section
  2602. c Compute: p1_i = inv(p1) => Solve p1 * p1_i = I
  2603. call eye(p1_i,m) ! Initialise as identity
  2604. c$omp section
  2605. c Make a copy: set p1copy = p1
  2606. call mcopy(p1,p1copy,m,m)
  2607. c$omp end sections
  2608. c$omp single
  2609. c Now do solve. Note: p1copy overwritten
  2610. call dposv('u',m,m,p1copy,m,p1_i,m,info)
  2611. call setflag(info, ifo)
  2612. if(info.gt.0) print *, "Error: Failed to solve [tv_noname_simsmp]"
  2613. c$omp end single
  2614. c ------------------------------------------
  2615. c$omp do schedule(static) private(t, gt_i, t_q, t_g)
  2616. do t = 1, n
  2617. c Time varying matrix selection: choose t th matrix or first
  2618. t_q = timet(n_q, t)
  2619. t_g = timet(n_g, t)
  2620. c -----------------------------------------------
  2621. ! Compute: gt_i using singular value decomposition
  2622. if((t.eq.1.).or.(n_g.gt.1)) then
  2623. call compute_pseudoinv(gt(:,:,t_g), gt_i, r, m, lwk)
  2624. endif
  2625. c -----------------------------------------------
  2626. c Compute: gqg(t) = inv[G(t)]'.inv[Q(t)].inv[G(t)]
  2627. if((t.eq.1).or.(n_g.gt.1).or.(n_q.gt.1)) then
  2628. call compute_gqg(qt_type, gt_type, qt(:,:,t_q), gt_i,
  2629. + gqg(:,:,t), m, r, ifo)
  2630. endif
  2631. c -----------------------------------------------
  2632. enddo
  2633. c$omp end do
  2634. c -----------------------------------------
  2635. c$omp do schedule(static)
  2636. c$omp& private(t_t,t_z,t_h,st,beta,gqgt,z_h,diag,zhz,tgqgt,lblock)
  2637. do t = 1, n-1
  2638. st = (t-1)*m + 1
  2639. c ----------------------------------
  2640. c Time varying matrix selection: choose t th matrix or first
  2641. t_t = timet(n_t, t)
  2642. t_z = timet(n_z, t)
  2643. t_h = timet(n_h, t)
  2644. c ----------------------------------
  2645. if((t.eq.1).or.(n_z.gt.1).or.(n_h.gt.1)) then
  2646. c Compute: z_h
  2647. call compute_zh(ht_type, ht(:,:,t_h), zt(:,:,t_z),
  2648. + z_h, p, m, n_p)
  2649. c Compute: zhz
  2650. beta = 0.0
  2651. call compute_zhz(zt_type, z_h, zt(:,:,t_z), zhz,
  2652. + beta, m, p)
  2653. endif
  2654. c ----------------------------------
  2655. if((t.eq.1).or.(n_g.gt.1).or.(n_q.gt.1).or.(n_t.gt.1)) then
  2656. c Compute: gqgt(t) = gqg(t) * T;
  2657. if(tt_type.eq.1) then ! is an identity matrix
  2658. call mcopy(gqg(:,:,t), gqgt, m, m)
  2659. else ! not identity matrix
  2660. beta = 0.0
  2661. call dgemm('n','n',m,m,m, alpha, gqg(:,:,t), m,
  2662. + tt(:,:,t_t), m, beta, gqgt, m)
  2663. endif
  2664. c Compute: tgqgt = T'.gqgt
  2665. call compute_tgqgt(tt_type, tt(:,:,t_t), gqgt,
  2666. + tgqgt, beta, m)
  2667. endif
  2668. c ----------------------------------
  2669. c Compute: diag = Z'.inv[H].Z + T'.inv[Q].T
  2670. call mcopy(zhz, diag, m , m)
  2671. call mplusm(tgqgt, diag, m, m)
  2672. c ----------------------------------
  2673. c Main diagonal block calcs:
  2674. if(t.eq.1) then ! Compute: diag += p1_i
  2675. call mplusm(p1_i, diag, m, m)
  2676. else ! t > 1 => Compute: diag += gqg(t-1)
  2677. call mplusm(gqg(:,:,t-1), diag, m, m)
  2678. endif
  2679. c -----------------------------------
  2680. c mu calcs:
  2681. c Compute: mu = z_h(t) * y(t) ( == z_h_y)
  2682. beta = 0.0
  2683. call dgemv('n',m,p,alpha, z_h, m, y(:,t), 1,
  2684. + beta, mu(st:st+m-1), 1)
  2685. if(t.eq.1) then
  2686. c Compute: mu = mu + p1_i * a1
  2687. beta = 1.0
  2688. call dgemv('n',m,m,alpha,p1_i,m,a1,1,beta,mu(1:m),1)
  2689. endif
  2690. c ---------------------------------------------------
  2691. call mcopytr(gqgt, lblock, m, m) ! Set lblock = transpose[gqgt]
  2692. c Continue construction of banded system
  2693. c Copy column vectors from current block matrices
  2694. call update_bands(bmat, diag, lblock, t, m, two_m, mn)
  2695. c -------------------------------------------------
  2696. enddo
  2697. c$omp end do
  2698. c -----------------------------------------------------------
  2699. c$omp single
  2700. t = n
  2701. st = (t-1)*m + 1
  2702. c Time varying matrix selection: choose t th matrix or first
  2703. t_z = timet(n_z, t)
  2704. t_h = timet(n_h, t)
  2705. if((n_z.gt.1).or.(n_h.gt.1)) then
  2706. c Compute: z_h
  2707. call compute_zh(ht_type, ht(:,:,t_h), zt(:,:,t_z),
  2708. + z_h, p, m, n_p)
  2709. c Compute: z_h_z
  2710. beta = 0.0
  2711. call compute_zhz(zt_type, z_h, zt(:,:,t_z), zhz, beta, m, p)
  2712. endif
  2713. call mcopy(zhz, diag, m , m)
  2714. c$omp end single
  2715. c$omp sections
  2716. c$omp section
  2717. c Compute: diag += gqg
  2718. call mplusm(gqg(:,:,t), diag, m, m)
  2719. c$omp section
  2720. c Compute: mu = z_h(t) * y(t) ( == z_h_y)
  2721. beta = 0.0
  2722. call dgemv('n', m, p, alpha, z_h, m, y(:,t), 1,
  2723. + beta, mu(st:st+m-1), 1)
  2724. c$omp end sections
  2725. c$omp end parallel
  2726. call finalise_bands(bmat, diag, t, m, two_m, mn)
  2727. call sample_state(bmat, mu, sta, mn, two_m)
  2728. end
  2729. c ----------------------------------------------------------------------
  2730. c Procedure calculates the transpose of a banded lower triangular matrix
  2731. subroutine transpose_banded_lower(a, at, m, n)
  2732. c Input: a is a banded lower triangular matrix
  2733. c Output: at is a banded upper triangular matrix
  2734. c Note: at is pre initialised as zeros
  2735. implicit none
  2736. real*8 a(m,n), at(m,n)
  2737. integer m, n, i, num
  2738. c ----------------------
  2739. cf2py intent(in) a
  2740. cf2py intent(inout) at
  2741. cf2py intent(in) m
  2742. cf2py intent(in) n
  2743. c ----------------------
  2744. c$omp parallel default(shared) private(i, num)
  2745. c$omp do schedule(static)
  2746. do i = 1, m ! Iterate through rows of a
  2747. num = n - i + 1 ! i.e. n - #zeros where #zeros = i - 1
  2748. at(m-i+1, i:n) = a(i, 1:num)
  2749. enddo
  2750. c$omp end do
  2751. c$omp end parallel
  2752. end
  2753. c ----------------------------------------------------------------------
  2754. c Procedure to solve a lower or upper triangular system L.x = B
  2755. c Wrapper for function dtrsm
  2756. subroutine solve_trsm(up, lu, b, m, n, k)
  2757. implicit none
  2758. integer m, n, k, up
  2759. real*8 lu(m,n), b(m,k), alpha
  2760. c Note: lu(m,n) * x(n,k) = b(m,k)
  2761. c -----------------------
  2762. cf2py intent(in) l
  2763. cf2py intent(in) up
  2764. cf2py intent(in) b
  2765. cf2py intent(in) m
  2766. cf2py intent(in) n
  2767. cf2py intent(in) k
  2768. c -------------------
  2769. alpha = 1.0
  2770. if (up.eq.1) then
  2771. call dtrsm('l','u','n','n',m, k, alpha, lu, m, b, m)
  2772. else
  2773. call dtrsm('l','l','n','n',m, k, alpha, lu, m, b, m)
  2774. endif
  2775. end
  2776. c ----------------------------------------------------------------------
  2777. c Procedure to compute inv[ht] for the time varying case
  2778. c Note: cholesky factorisation cht also stored. It is a by
  2779. c product of solution process
  2780. c Note: on entry cht is a copy of ht
  2781. subroutine compute_tv_inv_ht(ht, cht, info, p, n)
  2782. implicit none
  2783. integer t, i, j, p, n, info
  2784. real*8 ht(p,p,n), cht(p,p,n)
  2785. c ----------------------
  2786. cf2py intent(inout) ht
  2787. cf2py intent(inout) cht
  2788. cf2py intent(inout) info
  2789. cf2py intent(in) m
  2790. cf2py intent(in) n
  2791. c ----------------------
  2792. c$omp parallel default(shared)
  2793. c$omp do schedule(static) private(t, i, j)
  2794. do t = 1, n
  2795. c Initialise: ht(:,:,t) = I
  2796. call eye(ht(:,:,t), p)
  2797. c Solve: ht.inv[ht] = I (i.e. Ax = B, where A = ht, B = cht)
  2798. c On exit: ht is replaced with inv[ht]; cht is replaced with U
  2799. call dposv('u', p, p, cht(:,:,t), p, ht(:,:,t), p, info)
  2800. if(info.ne.0) print *,
  2801. + "Error: Failed to solve [compute_tv_inv_ht]"
  2802. c Zero lower triangular component of matrix
  2803. do i = 1, p
  2804. do j = 1, i-1
  2805. cht(i, j, t) = 0.0
  2806. enddo
  2807. enddo
  2808. enddo
  2809. c$omp end do
  2810. c$omp end parallel
  2811. end
  2812. c ----------------------------------------------------------------------
  2813. subroutine mult_diag_diag(diag1, diag2, res, p)
  2814. implicit none
  2815. integer i,p
  2816. real*8 diag1(p), diag2(p), res(p)
  2817. do i = 1, p
  2818. res(i) = diag1(i) * diag2(i)
  2819. enddo
  2820. end subroutine mult_diag_diag
  2821. c ----------------------------------------------------------------------
  2822. subroutine mult_dense_diag(dense, diag, res, n, p)
  2823. c Compute: res = dense * diag
  2824. implicit none
  2825. integer i, p, n
  2826. real*8 dense(n,p), diag(p), res(n,p)
  2827. do i = 1, p
  2828. c Compute: res(:,i) = dense(:,i) [i.e. copy column i]
  2829. call dcopy(p, dense(:,i), 1, res(:,i), 1)
  2830. c Compute: res(:,i) = diag(i) * res(:,i) [i.e. mult column by scalar]
  2831. call dscal(p, diag(i), res(:,i), 1)
  2832. enddo
  2833. end subroutine mult_dense_diag
  2834. c ----------------------------------------------------------------------
  2835. subroutine mult_diag_dense(diag, dense, res, n, p)
  2836. c Compute: res = diag * dense
  2837. implicit none
  2838. integer i, p, n
  2839. real*8 dense(p,n), diag(p), res(p,n)
  2840. do i = 1, p
  2841. c Compute: res(i,:) = dense(i,:) [i.e. copy row i]
  2842. call dcopy(p, dense(i,:), 1, res(i,:), 1)
  2843. c Compute: res(i,:) = diag(i) * res(i,:) [i.e. mult row by scalar]
  2844. call dscal(p, diag(i), res(i,:), 1)
  2845. enddo
  2846. end subroutine mult_diag_dense
  2847. c ----------------------------------------------------------------------
  2848. subroutine rhr_dense(rt, ht, rt_ht, rhr, p, n_rt, n_ht, n_rhr)
  2849. c Purpose: Compute rt * ht * rt
  2850. c where: rt and ht are dense
  2851. implicit none
  2852. integer p, t, n_rt, n_ht, n_rhr, timet, t_rt, t_ht, t_rhr, n
  2853. real*8 rt(p,p,n_rt), ht(p,p,n_ht), rhr(p,p,n_rhr)
  2854. real*8 rt_ht(p,p)
  2855. real*8 alpha, beta
  2856. c ----------------------
  2857. cf2py intent(in) rt
  2858. cf2py intent(in) ht
  2859. cf2py intent(inout) rt_ht
  2860. cf2py intent(inout) rhr
  2861. cf2py intent(in) p
  2862. cf2py intent(in) n_rt
  2863. cf2py intent(in) n_ht
  2864. cf2py intent(in) n_rhr
  2865. c ----------------------
  2866. alpha = 1.0
  2867. beta = 0.0
  2868. c Note: If both are non time varying then n = 1
  2869. n = max(n_ht, n_rt)
  2870. c$omp parallel default(shared) private(t, t_ht, t_rt, t_rhr, rt_ht)
  2871. c$omp do schedule(static)
  2872. do t = 1, n
  2873. t_ht = timet(n_ht,t)
  2874. t_rt = timet(n_rt,t)
  2875. t_rhr = timet(n_rhr,t)
  2876. c Compute: rt_ht = rt * ht
  2877. call dgemm('n','n',p,p,p,alpha, rt(:,:,t_rt), p, ht(:,:,t_ht),
  2878. + p, beta, rt_ht, p)
  2879. c Compute: rt_ht * rt'
  2880. call dgemm('n','t',p,p,p,alpha, rt_ht, p, rt(:,:,t_rt),
  2881. + p, beta, rhr(:,:,t_rhr), p)
  2882. enddo
  2883. c$omp end do
  2884. c$omp end parallel
  2885. end subroutine rhr_dense
  2886. c ----------------------------------------------------------------------
  2887. subroutine rhr_diag_rt_ht(rt, ht, rt_ht, rhr, p,
  2888. + n_rt, n_ht, n_rhr)
  2889. c Purpose: Compute rt * ht * rt
  2890. c Where: rt is diag, ht is diag
  2891. implicit none
  2892. integer t_ht, t_rt, t_rhr, n, timet, p, n_rt, n_ht, n_rhr, t
  2893. real*8 rt(p,1,n_rt), ht(p,1,n_ht), rhr(p,1,n_rhr)
  2894. real*8 rt_ht(p,1)
  2895. c ----------------------
  2896. cf2py intent(in) rt
  2897. cf2py intent(in) ht
  2898. cf2py intent(in) rt_ht
  2899. cf2py intent(inout) rhr
  2900. cf2py intent(in) p
  2901. cf2py intent(in) n_rt
  2902. cf2py intent(in) n_ht
  2903. cf2py intent(in) n_rhr
  2904. c ----------------------
  2905. c Note: If both are non time varying then n = 1
  2906. n = max(n_ht, n_rt)
  2907. c$omp parallel default(shared) private(t, t_ht, t_rt, t_rhr, rt_ht)
  2908. c$omp do schedule(static)
  2909. do t = 1, n
  2910. t_ht = timet(n_ht,t)
  2911. t_rt = timet(n_rt,t)
  2912. t_rhr = timet(n_rhr,t)
  2913. call mult_diag_diag(rt(:,1,t_rt), ht(:,1,t_ht),
  2914. + rt_ht(:,1), p)
  2915. call mult_diag_diag(rt_ht(:,1), rt(:,1,t_rt),
  2916. + rhr(:,1,t_rhr), p)
  2917. enddo
  2918. c$omp end do
  2919. c$omp end parallel
  2920. end subroutine rhr_diag_rt_ht
  2921. c ----------------------------------------------------------------------
  2922. subroutine rhr_diag_ht(rt, ht, rt_ht, rhr, p, n_rt, n_ht, n_rhr)
  2923. c Purpose: Compute rt * ht * rt
  2924. c where: rt is dense, ht is diag
  2925. implicit none
  2926. integer p, t, n_rt, n_ht, n_rhr, timet, t_rt, t_ht, t_rhr, n
  2927. real*8 rt(p,p,n_rt), ht(p,1,n_ht), rhr(p,p,n_rhr)
  2928. real*8 rt_ht(p,p)
  2929. real*8 alpha, beta
  2930. c ------------------------
  2931. cf2py intent(in) rt
  2932. cf2py intent(in) ht
  2933. cf2py intent(inout) rt_ht
  2934. cf2py intent(inout) rhr
  2935. cf2py intent(in) p
  2936. cf2py intent(in) n_rt
  2937. cf2py intent(in) n_ht
  2938. cf2py intent(in) n_rhr
  2939. c ---------------------
  2940. alpha = 1.0
  2941. beta = 0.0
  2942. c Note: If both are non time varying then n = 1
  2943. n = max(n_ht, n_rt)
  2944. c$omp parallel default(shared) private(t, t_ht, t_rt, t_rhr, rt_ht)
  2945. c$omp do schedule(static)
  2946. do t = 1, n
  2947. t_ht = timet(n_ht,t)
  2948. t_rt = timet(n_rt,t)
  2949. t_rhr = timet(n_rhr,t)
  2950. c 1. Compute: rt_ht = rt * ht
  2951. call mult_dense_diag(rt(:,:,t_rt), ht(:,1,t_ht), rt_ht, p, p)
  2952. c 2. Compute: rt_ht * rt.T
  2953. call dgemm('n','t',p,p,p,alpha, rt_ht, p, rt(:,:,t_rt),
  2954. + p, beta, rhr(:,:,t_rhr), p)
  2955. enddo
  2956. c$omp end do
  2957. c$omp end parallel
  2958. end subroutine rhr_diag_ht
  2959. c ----------------------------------------------------------------------
  2960. subroutine rhr_diag_rt(rt, ht, rt_ht, rhr, p, n_rt, n_ht, n_rhr)
  2961. c Purpose: Compute rt * ht * rt
  2962. c where: ht is dense, rt is diag
  2963. implicit none
  2964. integer p, t, n_rt, n_ht, n_rhr, timet, t_rt, t_ht, t_rhr, n
  2965. real*8 rt(p,n_rt), ht(p,p,n_ht), rhr(p,p,n_rhr)
  2966. real*8 rt_ht(p,p)
  2967. real*8 alpha, beta
  2968. c ----------------------
  2969. cf2py intent(in) rt
  2970. cf2py intent(in) ht
  2971. cf2py intent(inout) rhr
  2972. cf2py intent(in) p
  2973. cf2py intent(in) n_rt
  2974. cf2py intent(in) n_ht
  2975. cf2py intent(in) n_rhr
  2976. c ----------------------
  2977. alpha = 1.0
  2978. beta = 0.0
  2979. c Note: If both are non time varying then n = 1
  2980. n = max(n_ht, n_rt)
  2981. c$omp parallel default(shared) private(t, t_ht, t_rt, t_rhr, rt_ht)
  2982. c$omp do schedule(static)
  2983. do t = 1, n
  2984. t_ht = timet(n_ht,t)
  2985. t_rt = timet(n_rt,t)
  2986. t_rhr = timet(n_rhr,t)
  2987. c 1. Compute: rt_ht = rt * ht
  2988. call mult_diag_dense(rt(:,t_rt), ht(:,:,t_ht), rt_ht, p, p)
  2989. c 2.Compute: rhr = rt_ht * rt
  2990. call mult_dense_diag(rt_ht, rt(:,t_rt), rhr(:,:,t_rhr), p, p)
  2991. enddo
  2992. c$omp end do
  2993. c$omp end parallel
  2994. end subroutine rhr_diag_rt
  2995. c ----------------------------------------------------------------------
  2996. subroutine rcht_dense(rt, cht, rcht, p, n_rt, n_cht, n_rcht)
  2997. c Purpose: Compute rt * cht for all t
  2998. c where: rt and cht are dense
  2999. implicit none
  3000. integer p, t, n_rt, n_cht, n_rcht, timet, t_rt, t_cht, t_rcht, n
  3001. real*8 rt(p,p,n_rt), cht(p,p,n_cht), rcht(p,p,n_rcht)
  3002. real*8 alpha, beta
  3003. c ----------------------
  3004. cf2py intent(in) rt
  3005. cf2py intent(in) cht
  3006. cf2py intent(inout) rcht
  3007. cf2py intent(in) p
  3008. cf2py intent(in) n_rt
  3009. cf2py intent(in) n_cht
  3010. cf2py intent(in) n_rcht
  3011. c ----------------------
  3012. alpha = 1.0
  3013. beta = 0.0
  3014. n = max(n_cht, n_rt)
  3015. c$omp parallel default(shared) private(t, t_cht, t_rt, t_rcht)
  3016. c$omp do schedule(static)
  3017. do t = 1, n
  3018. t_cht = timet(n_cht,t)
  3019. t_rt = timet(n_rt,t)
  3020. t_rcht = timet(n_rcht,t)
  3021. c Compute: rcht = rt * cht
  3022. call dgemm('n','n',p, p, p,alpha, rt(:,:,t_rt), p,
  3023. + cht(:,:,t_cht), p, beta, rcht(:,:,t_rcht), p)
  3024. enddo
  3025. c$omp end do
  3026. c$omp end parallel
  3027. end subroutine rcht_dense
  3028. c ----------------------------------------------------------------------
  3029. subroutine rcht_diag_rt(rt, cht, rcht, p, n_rt, n_cht, n_rcht)
  3030. c Purpose: Compute rt * cht for all t
  3031. c where: rt is diag and cht is dense
  3032. implicit none
  3033. integer p, t, n_rt, n_cht, n_rcht, timet, t_rt, t_cht, t_rcht, n
  3034. real*8 rt(p,1,n_rt), cht(p,p,n_cht), rcht(p,p,n_rcht)
  3035. real*8 alpha, beta
  3036. c ----------------------
  3037. cf2py intent(in) rt
  3038. cf2py intent(in) cht
  3039. cf2py intent(inout) rcht
  3040. cf2py intent(in) p
  3041. cf2py intent(in) n_rt
  3042. cf2py intent(in) n_cht
  3043. cf2py intent(in) n_rcht
  3044. c ----------------------
  3045. alpha = 1.0
  3046. beta = 0.0
  3047. n = max(n_cht, n_rt)
  3048. c$omp parallel default(shared) private(t, t_cht, t_rt, t_rcht)
  3049. c$omp do schedule(static)
  3050. do t = 1, n
  3051. t_cht = timet(n_cht,t)
  3052. t_rt = timet(n_rt,t)
  3053. t_rcht = timet(n_rcht,t)
  3054. call mult_diag_dense(rt(:,1,t_rt), cht(:,:,t_cht),
  3055. + rcht(:,:,t_rcht), p, p)
  3056. enddo
  3057. c$omp end do
  3058. c$omp end parallel
  3059. end subroutine rcht_diag_rt
  3060. c ----------------------------------------------------------------------
  3061. subroutine rcht_diag_cht(rt, cht, rcht, p, n_rt, n_cht, n_rcht)
  3062. c Purpose: Compute rt * cht for all t
  3063. c where: rt is dense and cht is diag
  3064. implicit none
  3065. integer p, t, n_rt, n_cht, n_rcht, timet, t_rt, t_cht, t_rcht, n
  3066. real*8 rt(p,p,n_rt), cht(p,n_cht), rcht(p,p,n_rcht)
  3067. real*8 alpha, beta
  3068. c ----------------------
  3069. cf2py intent(in) rt
  3070. cf2py intent(in) cht
  3071. cf2py intent(inout) rcht
  3072. cf2py intent(in) p
  3073. cf2py intent(in) n_rt
  3074. cf2py intent(in) n_cht
  3075. cf2py intent(in) n_rcht
  3076. c ----------------------
  3077. alpha = 1.0
  3078. beta = 0.0
  3079. n = max(n_cht, n_rt)
  3080. c$omp parallel default(shared) private(t, t_cht, t_rt, t_rcht)
  3081. c$omp do schedule(static)
  3082. do t = 1, n
  3083. t_cht = timet(n_cht,t)
  3084. t_rt = timet(n_rt,t)
  3085. t_rcht = timet(n_rcht,t)
  3086. call mult_dense_diag(rt(:,:,t_rt), cht(:,t_cht),
  3087. + rcht(:,:,t_rcht), p, p)
  3088. enddo
  3089. c$omp end do
  3090. c$omp end parallel
  3091. end subroutine rcht_diag_cht
  3092. c ----------------------------------------------------------------------
  3093. subroutine calc_zt_s_ntv(st,zt,zts,p,m,n)
  3094. implicit none
  3095. integer p,m,n
  3096. real*8 st(m,n),zt(p,m),zts(p,n)
  3097. real*8 alpha,beta
  3098. cf2py intent(in) st
  3099. cf2py intent(in) zt
  3100. cf2py intent(inout) zts
  3101. cf2py intent(in) p
  3102. cf2py intent(in) m
  3103. cf2py intent(in) n
  3104. alpha = 1.0
  3105. beta = 0.0
  3106. call dgemm('n','n',p,n,m,alpha,zt,p,st,m,beta,zts,p)
  3107. end subroutine calc_zt_s_ntv
  3108. c ----------------------------------------------------------------------
  3109. subroutine calc_zt_s_tv(st,zt,zts,p,m,n,nz)
  3110. implicit none
  3111. integer p,m,n,nz,t_z,t,timet
  3112. real*8 st(m,n),zt(p,m,nz),zts(p,n)
  3113. real*8 alpha,beta
  3114. cf2py intent(in) st
  3115. cf2py intent(in) zt
  3116. cf2py intent(inout) zts
  3117. cf2py intent(in) p
  3118. cf2py intent(in) m
  3119. cf2py intent(in) n
  3120. cf2py intent(in) nz
  3121. alpha = 1.0
  3122. beta = 0.0
  3123. do t=1,n
  3124. t_z = timet(nz,t)
  3125. call dgemv('n',p,m,alpha,zt(:,:,t_z),p,st(:,t),1,beta,
  3126. + zts(:,t),1)
  3127. enddo
  3128. end subroutine calc_zt_s_tv
  3129. c Fortran 77 function to check if entire column is nan
  3130. c return index 0 - entire column not nan
  3131. c return index 1 - partial column is nan
  3132. c return index 2 - entire column is nan
  3133. subroutine ck_col_nan(y,ind,p,n)
  3134. implicit none
  3135. !inputs
  3136. integer p,n,ind(n),misnan
  3137. real*8 y(p,n)
  3138. !counters
  3139. integer i,t,co
  3140. cf2py intent(in) y
  3141. cf2py intent(inout) ind
  3142. !main part of procedure
  3143. do t=1,n
  3144. co=0
  3145. do i=1,p
  3146. co=co+misnan(y(i,t))
  3147. enddo
  3148. if (co.eq.p) then
  3149. ind(t)=2 !all nan
  3150. else if(co.eq.0) then
  3151. ind(t)=0 !no nan
  3152. else
  3153. ind(t)=1 !partial nan
  3154. endif
  3155. enddo
  3156. end subroutine ck_col_nan
  3157. c Function returns 1 if a is nan, and 0 otherwise.
  3158. integer function misnan(a)
  3159. implicit none
  3160. real*8 a
  3161. if(isnan(a)) then
  3162. misnan = 1
  3163. else
  3164. misnan = 0
  3165. endif
  3166. return
  3167. end function misnan