EMPIRE DA  v1.9.1
Data assimilation codes using EMPIRE communication
 All Classes Files Functions Variables Pages
equivalent_weights_filter.f90
Go to the documentation of this file.
1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2 !!! Time-stamp: <2016-10-18 15:06:05 pbrowne>
3 !!!
4 !!! Computes the equivalent weights step in the EWPF
5 !!! Copyright (C) 2014 Philip A. Browne
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
21 !!! Mail: School of Mathematical and Physical Sciences,
22 !!! University of Reading,
23 !!! Reading, UK
24 !!! RG6 6BB
25 !!!
26 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
30  use output_empire, only : emp_e
31  use timestep_data
32  use pf_control
33  use sizes
34  use random
35  use comms
36  implicit none
37  include 'mpif.h'
38  integer, parameter :: rk = kind(1.0d0)
39  real(kind=rk), dimension(pf%count) :: a,b,alpha,c
40  real(kind=rk), dimension(pf%nens) :: csorted
41  real(kind=rk) :: cmax
42  integer :: particle,i,mpi_err!,tag
43  real(kind=rk), dimension(obs_dim) :: y !y, !//!<the observations
44  real(kind=rk), dimension(obs_dim,pf%count) :: Hfpsi !H(f(psi^(n-1))) !< \f$H(f(x^{n-1}))\f$
45  real(kind=rk), dimension(obs_dim,pf%count) :: y_Hfpsin1 !y-H(f(psi^(n-1))) !< \f$y-H(f(x^{n-1}))\f$
46  real(kind=rk), dimension(state_dim,pf%count) :: fpsi !f(psi^(n-1)) !< \f$f(x^{n-1})\f$
47  real(kind=rk), dimension(state_dim) :: psimean
48  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$
49  real(kind=rk), dimension(state_dim,pf%count) :: betan !the mixture random variable
50  real(kind=rk), dimension(state_dim,pf%count) :: statev
51  real(kind=rk), dimension(obs_dim,pf%count) :: obsv,obsvv
52  real(kind=rk) :: w
53  real(kind=rk), dimension(pf%count) :: e !e = d_i^t R^(-1) d_i
54  real(kind=rk), parameter :: pi = 4.0D0*atan(1.0d0)
55  logical, dimension(pf%count) :: uniform
56 
57  real(kind=rk) :: ddot,wtemp,betanTbetan
58  integer :: ensemble_comm
59 
60  if(comm_version .eq. 1 .or. comm_version .eq. 2) then
61  ensemble_comm = pf_mpi_comm
62  elseif(comm_version .eq. 3) then
63  ensemble_comm = pf_ens_comm
64  else
65  write(emp_e,*) 'EMPIRE VERSION ',comm_version,' NOT SUPPORTED IN &
66  &equivalent_weights_filter'
67  write(emp_e,*) 'THIS IS AN ERROR. STOPPING'
68  stop '-24'
69  end if
70 
71 
72  call send_all_models(state_dim,pf%count,pf%psi,1)
73 
74  !get the next observation and store it in vector y
75  call get_observation_data(y,pf%timestep)
76 
77  call recv_all_models(state_dim,pf%count,fpsi)
78 
79  call h(obs_dim,pf%count,fpsi,hfpsi,pf%timestep)
80 
81  !compute c for each particle on this mpi thread
82  do i = 1,pf%count
83  particle = pf%particles(i)
84  y_hfpsin1(:,i) = y - hfpsi(:,i)
85 
86  call innerhqht_plus_r_1(y_hfpsin1(:,i),w,pf%timestep)
87 
88  if(comm_version .eq. 3) then
89  !need to perform the sum across all parts of the state vector
90  wtemp=w
91  call mpi_allreduce(wtemp,w,1,mpi_double_precision,mpi_sum&
92  &,pf_member_comm,mpi_err)
93  end if
94 
95  c(i) = pf%weight(particle) + 0.5d0*w
96  end do
97 
98 
99  !communicate c to all the mpi threads
100  call mpi_allgatherv(c,pf%count,mpi_double_precision,csorted,gblcount&
101  &,gbldisp,mpi_double_precision,ensemble_comm,mpi_err)
102 
103  !calculate cmax
104  call quicksort_d(csorted,pf%nens)
105  cmax = csorted(nint(pf%keep*pf%nens))
106 
107  psimean = 0.0_rk
108 
109  !compute the kalman gain
110  call k(y_hfpsin1,kgain)
111  call h(obs_dim,pf%count,kgain,obsv,pf%timestep)
112  call solve_r(obs_dim,pf%count,obsv,obsvv,pf%timestep)
113 
114  !compute a for each particle on this mpi thread
115  do i = 1,pf%count
116  a(i) = 0.5d0*ddot(obs_dim,obsvv(:,i),1,y_hfpsin1(:,i),1)
117 
118  if(comm_version .eq. 3) then
119  !need to perform the sum across all parts of the observation vector
120  wtemp=a(i)
121  call mpi_allreduce(wtemp,a(i),1,mpi_double_precision,mpi_sum&
122  &,pf_member_comm,mpi_err)
123  end if
124  end do
125 
126  call innerr_1(obs_dim,pf%count,y_hfpsin1,e,pf%timestep)
127 
128  !compute alpha for each particle on this mpi thread
129  do i = 1,pf%count
130  particle = pf%particles(i)
131  b(i) = 0.5d0*e(i) - cmax + pf%weight(particle)
132  !note the plus sign in the below equation. See Ades & van Leeuwen 2012.
133  alpha(i) = 1.0d0 + sqrt(1.0d0 - b(i)/a(i) + 1.0d-6)
134 
135  if(alpha(i) .ne. alpha(i)) alpha(i) = 1.0d0 !ensure that
136  !alpha(i) is not a NaN because of roundoff errors.
137  end do
138 
139 
140  !draw from a mixture density for the random noise then correlate it
141  call mixturerandomnumbers2d(0.0d0,pf%nfac,pf%ufac,pf%efac,state_dim&
142  &,pf%count,statev,uniform)
143  call qhalf(pf%count,statev,betan)
144 
145  !update the weights and the new state
146  do i = 1,pf%count
147  if(c(i) .le. cmax) then
148  particle = pf%particles(i)
149  if(uniform(i)) then
150  pf%weight(particle) = pf%weight(particle) +&
151  (alpha(i)**2.0_rk - 2.0_rk*alpha(i))*a(i) + &
152  0.5_rk*e(i)
153  else
154  betantbetan = sum(betan(:,i)*betan(:,i))
155  if(comm_version .eq. 3) then
156  !need to perform the sum across all parts of the state vector
157  wtemp=betantbetan
158  call mpi_allreduce(wtemp,betantbetan,1,mpi_double_precision,mpi_sum&
159  &,pf_member_comm,mpi_err)
160  end if
161  pf%weight(particle) = pf%weight(particle) +&
162  (alpha(i)**2.0_rk - 2.0_rk*alpha(i))*a(i) + &
163  0.5_rk*e(i) &
164  + 2**(-real(state_dim_g,rk)/2.0_rk)*pi**(real(state_dim_g,rk)&
165  &/2.0_rk)*pf%nfac*pf%ufac**(-real(state_dim_g,rk))*((1.0_rk&
166  &-pf%efac)/pf%efac)*exp(0.5_rk*(betanTbetan))
167  end if !if(uniform)
168 
169  !now do the following
170  !x^n = f(x^(n-1)) + alpha(i) K (y-Hf(x_i^n-1)) + beta
171  call update_state(pf%psi(:,i),fpsi(:,i),alpha(i)*kgain(:,i)&
172  &,betan(:,i))
173  psimean = psimean + pf%psi(:,i)
174  else
175  pf%weight(pf%particles(i)) = huge(1.0d0)
176  end if
177  end do
178 
179 
180 !=========================================================================
181 
182 
183 
184  if(pf%use_talagrand) call diagnostics
185  !print*,'entering resample step'
186  print*,'time until resample = ',mpi_wtime()-pf%time
187  call flush(6)
188  call resample
189 
191 end subroutine equivalent_weights_filter
subroutine solve_r(obsDim, nrhs, y, v, t)
subroutine to take an observation vector y and return v in observation space.
subroutine send_all_models(stateDim, nrhs, x, tag)
subroutine to send all the model states to the models
Definition: comms.f90:945
subroutine resample
Subroutine to perform Universal Importance Resampling.
Definition: resample.f90:28
Module containing EMPIRE coupling data.
Definition: comms.f90:57
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
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 innerr_1(n, c, y, w, t)
subroutine to compute the inner product with
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
subroutine qhalf(nrhs, x, Qx)
subroutine to take a full state vector x and return in state space.
subroutine mixturerandomnumbers2d(mean, stdev, ufac, epsi, n, k, phi, uniform)
generate two dimensional vector, each drawn from mixture density
Definition: gen_rand.f90:207
subroutine equivalent_weights_filter
subroutine to do the equivalent weights step
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 .