EMPIRE DA  v1.9.1
Data assimilation codes using EMPIRE communication
 All Classes Files Functions Variables Pages
equivalent_weights_filter_zhu.f90
Go to the documentation of this file.
1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2 !!! Time-stamp: <2016-10-18 15:03:15 pbrowne>
3 !!!
4 !!! Computes the equal weights step in the New Schem Equal Weights Particle Filter
5 !!! Copyright (C) 2015 Mengbin Zhu
6 !!!
7 !!! This program is free software: you can redistribute it and/or modify
8 !!! it under the terms of the GNU General Public License as published by
9 !!! the Free Software Foundation, either version 3 of the License, or
10 !!! (at your option) any later version.
11 !!!
12 !!! This program is distributed in the hope that it will be useful,
13 !!! but WITHOUT ANY WARRANTY; without even the implied warranty of
14 !!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 !!! GNU General Public License for more details.
16 !!!
17 !!! You should have received a copy of the GNU General Public License
18 !!! along with this program. If not, see <http://www.gnu.org/licenses/>.
19 !!!
20 !!! Email: p.browne @ reading.ac.uk EMPIRE
21 !!! zhumengbin@gmail.com new scheme equal weights particle filter
22 !!! Mail: School of Mathematical and Physical Sciences,
23 !!! University of Reading,
24 !!! Reading, UK
25 !!! RG6 6BB
26 !!!
27 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
33  use output_empire, only : emp_e
34  use timestep_data
35  use pf_control
36  use sizes
37  use random
38  use comms
39  implicit none
40  include 'mpif.h'
41  integer, parameter :: rk = kind(1.0d0)
42  real(kind=rk), dimension(pf%count) :: alpha,c
43  real(kind=rk), dimension(pf%count) :: epsiloni,epsilon_n,epsilon_p,gammai,ce,win,wsolve
44  real(kind=rk), dimension(pf%nens) :: csorted
45  real(kind=rk), dimension(pf%nens) :: weight_an
46  real(kind=rk) :: cmax,xs1,xs2
47  integer :: particle,i,mpi_err,rc!,tag
48  real(kind=rk) :: percentage,randc
49  real(kind=rk), dimension(obs_dim) :: y !y, !//!<the observations
50  real(kind=rk), dimension(obs_dim,pf%count) :: Hfpsi !H(f(psi^(n-1))) !< \f$H(f(x^{n-1}))\f$
51  real(kind=rk), dimension(obs_dim,pf%count) :: y_Hfpsin1 !y-H(f(psi^(n-1))) !< \f$y-H(f(x^{n-1}))\f$
52  real(kind=rk), dimension(state_dim,pf%count) :: fpsi !f(psi^(n-1)) !< \f$f(x^{n-1})\f$
53  real(kind=rk), dimension(state_dim) :: psimean
54  real(kind=rk), dimension(state_dim,pf%count) :: kgain !QH^T(HQH^T+R)^(-1)(y-H(f(psi^(n-1)))) !< \f$QH^T(HQH^T+R)^{-1}(y-H(f(x^{n-1})))\f$
55  real(kind=rk), dimension(state_dim,pf%count) :: betan !the random variable
56  real(kind=rk), dimension(state_dim,pf%count) :: statev
57  real(kind=rk) :: w
58 
59  real(kind=rk), parameter :: pi = 4.0D0*atan(1.0d0)
60 
61  real(kind=rk), dimension(pf%count) :: weight_temp2
62  real(kind=rk) :: ddot
63 
64  integer :: ensemble_comm
65  real(kind=rk) :: gammaitemp
66 
67  percentage = 0.5
68  rc=1
69 
70 
71 
72  if(comm_version .eq. 1 .or. comm_version .eq. 2) then
73  ensemble_comm = pf_mpi_comm
74  elseif(comm_version .eq. 3) then
75  ensemble_comm = pf_ens_comm
76  else
77  write(emp_e,*) 'EMPIRE VERSION ',comm_version,' NOT SUPPORTED IN propos&
78  &al_filter'
79  write(emp_e,*) 'THIS IS AN ERROR. STOPPING'
80  stop '-24'
81  end if
82 
83  !start the model integration
84  call send_all_models(state_dim,pf%count,pf%psi,1)
85 
86  !get the next observation and store it in vector y
87  call get_observation_data(y,pf%timestep)
88 
89  !recv the models after integration
90  call recv_all_models(state_dim,pf%count,fpsi)
91 
92  call h(obs_dim,pf%count,fpsi,hfpsi,pf%timestep)
93 
94  !compute c for each particle on this mpi thread
95  do i = 1,pf%count
96  particle = pf%particles(i)
97  y_hfpsin1(:,i) = y - hfpsi(:,i)
98 
99  call innerhqht_plus_r_1(y_hfpsin1(:,i),w,pf%timestep)
100 
101  c(i) = 2.0*pf%weight(particle) + w
102  end do
103 
104 
105  !communicate c to all the mpi threads
106  call mpi_allgatherv(c,pf%count,mpi_double_precision,csorted,gblcount&
107  &,gbldisp,mpi_double_precision,ensemble_comm,mpi_err)
108 
109  !calculate cmax
110  call quicksort_d(csorted,pf%nens)
111  cmax = csorted(pf%nens)
112 
113 
114  psimean = 0.0_rk
115 
116 
117  !compute the kalman gain
118  call k(y_hfpsin1,kgain)
119 
120  !generate the unit normal random numbers for all particles ~ xi
121  call normalrandomnumbers2d(0.0d0,1.0d0,state_dim,pf%count,statev)
122 
123  !calculate epsiloni for the particles
124  xs1=-0.90d0
125  xs2=2.1d0
126  do i = 1,pf%count
127  gammai(i) = ddot(state_dim,statev(:,i),1,statev(:,i),1)
128  if(comm_version .eq. 3) then
129  !need to perform the sum across all parts of the state vector
130  gammaitemp=gammai(i)
131  call mpi_allreduce(gammaitemp,gammai(i),1,mpi_double_precision,mpi_sum&
132  &,pf_member_comm,mpi_err)
133  end if
134 
135 
136  ce(i) = cmax - c(i)
137 
138  win(i) = (-gammai(i)/state_dim_g)*exp(-gammai(i)/state_dim_g)*exp(-ce(i)/state_dim_g)
139  call lambertw(0,win(i),wsolve(i))
140  if(ce(i) .eq. 0.0) then
141  wsolve(i) = -(gammai(i)/state_dim_g)
142  end if
143  epsilon_n(i) = (-state_dim_g/gammai(i))*wsolve(i) - 1
144 
145  !call newton(xs1,gammai(i),state_dim,c(i),cmax,epsilon_n(i))
146 
147  call lambertw(-1,win(i),wsolve(i))
148  epsilon_p(i) = (-state_dim_g/gammai(i))*wsolve(i) - 1
149 
150  !call newton(xs2,gammai(i),state_dim,c(i),cmax,epsilon_p(i))
151  end do
152 
153  do i = 1,pf%count
154  if(comm_version .eq. 1 .or. comm_version .eq. 2) then
155  call random_number(randc)
156  else
157  if(pf_member_rank .eq. 0) then
158  call random_number(randc)
159  end if
160  call mpi_scatter(randc,1,mpi_double_precision,randc,1&
161  &,mpi_double_precision,0,pf_member_rank,mpi_err)
162  end if
163  if(randc .ge. 0.5) then
164  epsiloni(i) = epsilon_p(i)
165  else
166  epsiloni(i) = epsilon_n(i)
167  end if
168  end do
169 
170 
171  !compute alpha for each particle on this mpi thread
172  do i = 1,pf%count
173  alpha(i) = 1.0 + epsiloni(i)
174  end do
175 
176  !compute the random term of the analysis
177  call phalf(pf%count,statev,betan)
178 
179  !update the weights and the new state
180  do i = 1,pf%count
181  particle = pf%particles(i)
182  weight_an(particle) = 0.0
183  if(alpha(i) .eq. 0.0) then
184  alpha(i) = alpha(i) + 1.0e-16
185  end if
186  weight_an(particle) = gammai(i)*epsiloni(i)-state_dim_g*log(alpha(i))+c(i)
187  weight_an(particle) = 0.5*weight_an(particle)
188  if(alpha(i) .eq. 1.0e-16) then
189  weight_an(particle) = 0.5*cmax
190  end if
191  pf%Weight(particle) = weight_an(particle)
192 
193  !now do the following
194  !x^n = f(x^(n-1)) + K (y-Hf(x_i^n-1)) + alpha(i)^(1/2) P^(1/2) xi
195  call update_state(pf%psi(:,i),fpsi(:,i),kgain(:,i),sqrt(alpha(i))*betan(:,i))
196  psimean = psimean + pf%psi(:,i)
197  end do
198 
199  !store in weight_temp2 only those weights on this mpi thread
200  weight_temp2 = -huge(1.0d0)
201  do i = 1,pf%count
202  weight_temp2(i) = pf%weight(pf%particles(i))
203  end do
204 
205  !communicate the weights of all particles to each mpi thread
206  call mpi_allgatherv(weight_temp2,pf%count,mpi_double_precision,pf%weight,gblcount&
207  &,gbldisp,mpi_double_precision,ensemble_comm,mpi_err)
208 
209  !normalise the weights
210  pf%weight = exp(-pf%weight+maxval(pf%weight))
211  pf%weight = pf%weight/sum(pf%weight)
212  pf%weight = -log(pf%weight)
213  !=========================================================================
214 
215 
217  if(pf%use_talagrand) call diagnostics
218 
219 end subroutine equivalent_weights_filter_zhu
subroutine normalrandomnumbers2d(mean, stdev, n, k, phi)
generate two dimensional Normal random numbers
Definition: gen_rand.f90:109
subroutine send_all_models(stateDim, nrhs, x, tag)
subroutine to send all the model states to the models
Definition: comms.f90:945
subroutine phalf(nrhs, x, Px)
subroutine to take a full state vector x and return in state space.
Definition: phalf.f90:11
Module containing EMPIRE coupling data.
Definition: comms.f90:57
subroutine equivalent_weights_filter_zhu
subroutine to do the new scheme equal weights last time-step
Module that stores the information about the outputting from empire.
Module that stores the information about the timestepping process.
subroutine update_state(state, fpsi, kgain, betan)
Subroutine to update the state.
subroutine recv_all_models(stateDim, nrhs, x)
subroutine to receive all the model states from the models after
Definition: comms.f90:993
subroutine lambertw(K, X, W)
subroutine to implement the lambertw function see https://en.wikipedia.org/wiki/Lambert_W_function ...
Definition: lambertw.f90:30
Module that stores the dimension of observation and state spaces.
Definition: sizes.f90:29
subroutine diagnostics
Subroutine to give output diagnositics such as rank histograms.
Definition: diagnostics.f90:31
subroutine h(obsDim, nrhs, x, hx, t)
subroutine to take a full state vector x and return H(x) in observation space.
subroutine innerhqht_plus_r_1(y, w, t)
subroutine to compute the inner product with
module pf_control holds all the information to control the the main program
Definition: pf_control.f90:29
subroutine timestep_data_set_is_analysis
subroutine to define if the current ensemble is an analysis
subroutine get_observation_data(y, t)
Subroutine to read observation from a file .
A module for random number generation from the following distributions:
Definition: random_d.f90:22
recursive subroutine quicksort_d(a, na)
subroutine to sort using the quicksort algorithm
Definition: quicksort.f90:9
subroutine k(y, x)
Subroutine to apply to a vector y in observation space where .