EMPIRE DA  v1.9.1
Data assimilation codes using EMPIRE communication
 All Classes Files Functions Variables Pages
enkf_specific.f90
Go to the documentation of this file.
1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2 !!! Time-stamp: <2014-09-18 10:09:54 pbrowne>
3 !!!
4 !!! {one line to give the program's name and a brief idea of what it does.}
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 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
27 subroutine h_local(num_hor,num_ver,this_hor,this_ver,boundary,nrhs,stateDim,x&
28  &,obsdim,y)
29  use pf_control
30  implicit none
31  integer, parameter :: rk = kind(1.0d0)
32  integer, intent(in) :: num_hor,num_ver,this_hor,this_ver,boundary,nrhs&
33  &,stateDim,obsDim
34  real(kind=rk), dimension(stateDim,nrhs), intent(in) :: x
35  real(kind=rk), dimension(obsDim,nrhs), intent(out) :: y
36  integer :: nx,ny,nnx,nny,start_x,end_x,start_y,end_y
37  integer :: i,j,k,ii,jj
38 
39  nx = 256/num_hor
40  ny = 256/num_ver
41 
42  start_x = max(nx*(this_hor-1)+1-boundary,1)
43  end_x = min(nx*(this_hor) + boundary,256)
44  nnx = end_x-start_x+1
45 
46  start_y = max(ny*(this_ver-1)+1-boundary,1)
47  end_y = min(ny*(this_ver)+boundary,256)
48  nny = end_y-start_y+1
49 
50 
51 ! print*,'h local nx = ',nx,'ny = ',ny,'nnx = ',nnx,'nny = ',nny
52 ! print*,'h local start_x = ',start_x,'end x = ',end_x
53 ! print*,'h local start_y = ',start_y,'end_y = ',end_y
54  k = 0
55  do i = start_x,end_x
56  ii = i-start_x+1
57  do j = start_y,end_y
58  jj = j - start_y + 1
59  if(mod(i,pf%redObs) .eq. 1 .and. mod(j,pf%redObs) .eq. 1) then
60  k = k + 1
61  y(k,:) = x((ii-1)*nny+jj,:)
62  end if
63  end do
64  end do
65 
66 end subroutine h_local
67 
68 
69 subroutine solve_rhalf_local(num_hor,num_ver,this_hor,this_ver,boundary,nrhs&
70  &,obsdim,y,v)
71  implicit none
72  integer, parameter :: rk = kind(1.0d0)
73  integer, intent(in) :: num_hor,num_ver,this_hor,this_ver,boundary,nrhs,obsDim
74 
75  real(kind=rk), dimension(obsDim,nrhs), intent(in) :: y
76  real(kind=rk), dimension(obsDim,nrhs), intent(out) :: v
77 
78  v = 0.0_rk
79  call daxpy(obsdim*nrhs,1.0_rk/0.05_rk,y,1,v,1)
80 
81 end subroutine solve_rhalf_local
82 
83 subroutine get_local_observation_data(num_hor,num_ver,this_hor,this_ver,boundary,obsDim,y)
84  use pf_control
85  use sizes
86  implicit none
87  integer, parameter :: rk = kind(1.0d0)
88  integer, intent(in) :: num_hor,num_ver,this_hor,this_ver,boundary,obsDim
89  real(kind=rk), dimension(obsDim), intent(out) :: y
90  real(kind=rk), dimension(obs_dim) :: yfull
91  integer :: obs_number,ios,i,j,k
92  integer :: nx,ny,nnx,nny,start_x,end_x,start_y,end_y
93  character(14) :: filename
94 
95  obs_number = ((pf%timestep-1)/pf%time_bwn_obs) + 1
96 
97  write(filename,'(A,i6.6)') 'obs_num_',obs_number
98 
99  open(67,file=filename,iostat=ios,action='read',status='old',form='unformatted')
100  if(ios .ne. 0) then
101  write(*,*) 'PARTICLE FILTER DATA ERROR!!!!! Cannot open file ',filename
102  write(*,*) 'Check it exists. I need a lie down.'
103  stop
104  end if
105  read(67) yfull
106  close(67)
107 
108  nx = (256/pf%redObs)/num_hor
109  ny = (256/pf%redObs)/num_ver
110 
111  start_x = max(nx*(this_hor-1)+1-(boundary/pf%redObs),1)
112  end_x = min(nx*(this_hor) + (boundary/pf%redObs),256/pf%redObs)
113 ! print*,'start_x = ',start_x,'end_x = ',end_x
114 ! print*,'this_nor = ',this_hor
115 ! print*,'nx*(this_hor-1)+1 = ',nx*(this_hor-1)+1
116 ! print*,'boundary/pf%redobs = ',(boundary/pf%redObs)
117  nnx = end_x-start_x+1
118 
119  start_y = max(ny*(this_ver-1)+1-(boundary/pf%redObs),1)
120  end_y = min(ny*(this_ver)+(boundary/pf%redObs),256/pf%redObs)
121  nny = end_y-start_y+1
122 ! print*,'get_local_obs: nx = ',nx,'ny=',ny,'nnx = ',nnx,'nny = ',nny
123 
124  k = 0
125  do i = start_x,end_x
126  do j = start_y,end_y
127  k = k + 1
128  y(k) = yfull((i-1)*nny+j)
129  end do
130  end do
131  if(k .ne. obsdim) then
132  print*,.ne.'WOAH!! k obsdim'
133  print*,k, obsdim
134  print*,this_hor,this_ver,nnx,nny
135  print*,start_x,end_x
136  print*,start_y,end_y
137  stop
138  end if
139 
140 end subroutine get_local_observation_data
141 
142 subroutine localise_enkf(enkf_analysis)
143 use sizes
144 use pf_control
145 use comms
146 implicit none
147 include 'mpif.h'
148 integer, parameter :: rk = kind(1.0d0)
149 integer, intent(in) :: enkf_analysis
150 real(kind=rk), dimension(state_dim,pf%count) :: x_analysis
151 real(kind=rk), dimension(:,:), allocatable :: x_local
152 integer :: mpi_err,particle,tag
153 integer :: num_hor,num_ver,boundary,stateDim,Obsdim,obsx,obsy
154 integer :: nx,ny,nnx,nny,start_x,end_x,start_y,end_y,k,ii,jj,i,j
155 integer, dimension(mpi_status_size) :: mpi_status
156 
157 
158 do k =1,pf%count
159  particle = pf%particles(k)
160  tag = 1
161  call mpi_send(pf%psi(:,k),state_dim,mpi_double_precision&
162  &,particle-1,tag,cpl_mpi_comm,mpi_err)
163 end do
164 
165 DO k = 1,pf%count
166  particle = pf%particles(k)
167  tag = 1
168  CALL mpi_recv(pf%psi(:,k), state_dim, mpi_double_precision, &
169  particle-1, tag, cpl_mpi_comm,mpi_status, mpi_err)
170 END DO
171 
172 
173 
174 
175 if(mod(pf%timestep,pf%time_bwn_obs) .eq. 0) then
176 num_hor = pf%enkfx
177 num_ver = pf%enkfy
178 boundary = pf%enkfb
179 
180 
181 
182 do i = 1, num_hor
183  do j = 1,num_ver
184 
185  nx = 256/num_hor
186  ny = 256/num_ver
187 ! print*,'nx = ',nx
188 ! print*,'ny = ',ny
189 
190  start_x = max(nx*(i-1)+1-boundary,1)
191  end_x = min(nx*(i) + boundary,256)
192  nnx = end_x-start_x+1
193 ! print*,'nnx = ',nnx
194  start_y = max(ny*(j-1)+1-boundary,1)
195  end_y = min(ny*(j)+boundary,256)
196  nny = end_y-start_y+1
197 ! print*,'nny = ',nny
198  statedim = nnx*nny
199 ! print*,'stateDim = ',stateDim
200  obsx = 0
201  do ii = start_x,end_x
202  if(mod(ii,pf%redObs) .eq. 1) obsx = obsx + 1
203  end do
204  obsy = 0
205  do jj = start_y,end_y
206  if(mod(jj,pf%redObs) .eq. 1) obsy = obsy + 1
207  end do
208  obsdim = obsx*obsy
209 ! print*,'obsDim = ',obsdim
210 
211  allocate(x_local(statedim,pf%count))
212  k = 0
213  do ii = start_x,end_x
214  do jj = start_y,end_y
215  k = k+1
216  x_local(k,:) = pf%psi((ii-1)*256 + jj,:)
217  end do
218  end do
219 
220 
221  if(enkf_analysis .eq. 3) then
222 ! print*,'before : '
223 ! print*,x_local(1:10,1)
224  call etkf_analysis(num_hor,num_ver,i,j,boundary,x_local,pf%count&
225  &,statedim,obsdim,pf%Qscale)
226 ! print*,'after : '
227 ! print*,x_local(1:10,1)
228  elseif(enkf_analysis .eq. 4) then
229  call eakf_analysis(num_hor,num_ver,i,j,boundary,x_local,pf%count&
230  &,statedim,obsdim,pf%Qscale)
231  else
232  do k = 1,500
233  print*,'I AM A FISH'
234  END do
235  stop 'ENKF SELECTED INCORRECTLY: 2013MONBLUE'
236  END if
237 
238  k = 0
239 ! print*,'i = ',i,' j = ',j
240 ! print*,'term 1:(i-1)*nx*ny*num_ver : ',(i-1)*nx*ny*num_ver
241  do ii = nx*(i-1)+1,nx*i
242 ! print*,'term 2: 256*mod(ii-1,nx) : ',256*mod(ii-1,nx)
243  do jj = ny*(j-1)+1,ny*j
244  !print*,'term 3: (j-1)*ny : ',(j-1)*ny
245  k = k + 1
246  !print*,k,ii,jj
247  !print*,k+nnx*boundary + (ii*2-1)*boundary
248  x_analysis((i-1)*nx*ny*num_ver + 256*mod(ii-1,nx) + jj,:)&
249  & = x_local(k+&
250  nny*( nx*(i-1)+1 - max(nx*(i-1)+1-boundary,1) ) +&
251  (ii-nx*(i-1) )*(ny*(j-1)+1 - max(ny*(j-1)+1-boundary,1) ) &
252  &+&
253  (ii-1-nx*(i-1))*(min(ny*(j)+boundary,256)-ny*j) ,:)
254 ! x_analysis(k+nx*ny*((i-1)*num_ver+(j-1)),:) = x_local(k+nnx*boundary + (ii*2-1)*boundary,:)
255  end do
256  end do
257  deallocate(x_local)
258  end do
259 end do
260 
261 pf%psi = x_analysis
262 
263 end if
264 
265 
266 end subroutine localise_enkf
subroutine h_local(num_hor, num_ver, this_hor, this_ver, boundary, nrhs, stateDim, x, obsDim, y)
Module containing EMPIRE coupling data.
Definition: comms.f90:57
subroutine eakf_analysis(num_hor, num_ver, this_hor, this_ver, boundary, x, N, stateDim, obsDim, rho)
subroutine etkf_analysis(num_hor, num_ver, this_hor, this_ver, boundary, x, N, stateDim, obsDim, rho)
subroutine to perform the ensemble transform Kalman filter
Module that stores the dimension of observation and state spaces.
Definition: sizes.f90:29
subroutine get_local_observation_data(num_hor, num_ver, this_hor, this_ver, boundary, obsDim, y)
subroutine localise_enkf(enkf_analysis)
module pf_control holds all the information to control the the main program
Definition: pf_control.f90:29
subroutine solve_rhalf_local(num_hor, num_ver, this_hor, this_ver, boundary, nrhs, obsDim, y, v)