39 integer,
parameter :: rk = kind(1.0d0)
43 real(kind=rk),
dimension(state_dim,pf%count) :: x_p
46 real(kind=rk),
dimension(obs_dim) :: y
50 real(kind=rk),
dimension(:,:),
allocatable :: V
51 real(kind=rk),
dimension(:),
allocatable :: S
52 real(kind=rk),
dimension(pf%nens,pf%nens) :: UT
54 real(kind=rk),
dimension(:),
allocatable :: WORK
57 real(kind=rk),
dimension(state_dim) :: mean_x
58 real(kind=rk),
dimension(:),
allocatable :: mean_xa
59 real(kind=rk),
dimension(state_dim,pf%count) :: Xp_p
61 real(kind=rk),
dimension(:,:),
allocatable :: Xp
62 real(kind=rk),
dimension(:,:),
allocatable :: Xa
63 real(kind=rk),
dimension(obs_dim) :: mean_yf,d,dd
64 real(kind=rk),
dimension(obs_dim_g) :: dd_g
65 real(kind=rk),
dimension(obs_dim,pf%nens) :: yf,Ysf
66 real(kind=rk),
dimension(obs_dim_g,pf%nens) :: Ysf_g
67 real(kind=rk),
dimension(obs_dim,pf%count) :: yf_p
68 integer :: i,j,number_gridpoints
72 real(kind=rk),
parameter :: maxscal=exp(8.0d0)
73 real(kind=rk),
dimension(obs_dim_g) :: scal
74 logical,
dimension(obs_dim_g) :: yes
76 real(kind=rk),
allocatable,
dimension(:,:) :: Ysf_red
77 real(kind=rk),
allocatable,
dimension(:) :: dd_red
82 integer,
dimension(npfs) :: start_var,stop_var
83 integer :: ensemble_comm
86 if(comm_version .eq. 1 .or. comm_version .eq. 2)
then
87 ensemble_comm = pf_mpi_comm
88 elseif(comm_version .eq. 3)
then
89 ensemble_comm = pf_ens_comm
91 write(emp_e,*)
'EMPIRE VERSION ',comm_version,
' NOT SUPPORTED IN letkf_analysis'
92 write(emp_e,*)
'THIS IS AN ERROR. STOPPING'
102 mean_x = sum(pf%psi,dim=2)
105 call mpi_allreduce(mpi_in_place,mean_x,state_dim,mpi_double_precision&
106 &,mpi_sum,ensemble_comm,mpi_err)
110 mean_x = mean_x/
real(pf%nens,rk)
115 xp_p(:,i) = pf%psi(:,i) - mean_x
119 xp_p = (1.0_rk + pf%rho) * xp_p
122 x_p(:,i) = mean_x + xp_p(:,i)
126 xp_p = xp_p/sqrt(
real(pf%nens-1,rk))
134 call
h(obs_dim,pf%count,x_p,yf_p,pf%timestep)
139 call mpi_allgatherv(yf_p,pf%count*obs_dim,mpi_double_precision,yf&
140 &,gblcount*obs_dim,gbldisp*obs_dim,mpi_double_precision&
141 &,ensemble_comm,mpi_err)
144 mean_yf = sum(yf,dim=2)/
real(pf%nens,rk)
146 yf(:,i) = yf(:,i) - mean_yf
150 yf = yf/sqrt(
real(pf%nens-1,rk))
152 call
solve_rhalf(obs_dim,pf%nens,yf,ysf,pf%timestep)
158 start_var(i) = ((i-1)*state_dim)/npfs + 1
159 stop_var(i) = (i*state_dim)/npfs
163 allocate(xp(stop_var(pfrank+1)-start_var(pfrank+1)+1,pf%nens))
164 allocate(xa(stop_var(pfrank+1)-start_var(pfrank+1)+1,pf%nens))
165 allocate(mean_xa(stop_var(pfrank+1)-start_var(pfrank+1)+1))
166 mean_xa = mean_x(start_var(pfrank+1):stop_var(pfrank+1))
170 number_gridpoints = stop_var(i)-start_var(i)+1
172 call mpi_gatherv(xp_p(start_var(i):stop_var(i),:),&
173 pf%count*number_gridpoints,&
174 mpi_double_precision,&
176 gblcount*number_gridpoints,&
177 gbldisp*number_gridpoints,&
178 mpi_double_precision,&
188 if(comm_version .eq. 1 .or. comm_version .eq. 2)
then
191 elseif(comm_version .eq. 3)
then
192 call mpi_allgatherv(dd,obs_dim,mpi_double_precision,dd_g,obs_dims&
193 &,obs_displacements,mpi_double_precision,pf_member_comm&
195 call mpi_allgatherv(ysf,obs_dim*pf%nens,mpi_double_precision&
196 &,ysf_g,obs_dims*pf%nens,obs_displacements*pf%nens&
197 &,mpi_double_precision,pf_member_comm,mpi_err)
199 print*,
'should not enter here. error. stopping :('
203 number_gridpoints = stop_var(pfrank+1)-start_var(pfrank+1)+1
208 do j = 1,number_gridpoints
217 call
dist_st_ob(j+start_var(pfrank+1)-1,i,dist,pf%timestep)
225 red_obsdim = count(yes)
229 if(red_obsdim .gt. 0)
then
231 allocate(ysf_red(red_obsdim,pf%nens))
237 ysf_red(:,i) = pack(ysf_g(:,i),yes)*sqrt(pack(scal,yes))
241 r = min(red_obsdim,pf%nens)
242 allocate(v(red_obsdim,r))
244 lwork = 2*max( 3*r+max(red_obsdim,pf%nens), 5*r )
246 allocate(work(lwork))
248 call dgesvd(
'S',
'A',red_obsdim,pf%nens,ysf_red,red_obsdim,s,v,red_obsdim,ut,pf%nens,work,lwork,info)
250 write(emp_e,*)
'EMPIRE ERROR IN LETKF WITH THE SVD'
251 write(emp_e,*)
'SVD failed with INFO = ',info
252 write(emp_e,*)
'FYI WORK(1) = ',work(1)
253 write(emp_e,*)
'STOPPING'
262 call dgemm(
'N',
'T',statedim,pf%nens,pf%nens,1.0d0,xp(j,:),statedim,ut,pf%nens,0.0d0,xa(j,:),statedim)
268 allocate(dd_red(red_obsdim))
269 dd_red = pack(dd_g,yes)*sqrt(pack(scal,yes))
272 call dgemv(
'T',red_obsdim,r,1.0d0,v,red_obsdim,dd_red,1,0.0d0,d,1)
274 d(1:r) = s * d(1:r) / (1.0_rk + s**2)
277 call dgemv(
'N',statedim,r,1.0d0,xa(j,:),statedim,d,1,1.0d0,mean_xa(j),1)
281 xa(j,i) = xa(j,i) / sqrt(1.0_rk + s(i)**2)
283 call dgemm(
'N',
'N',statedim,pf%nens,pf%nens,1.0d0,xa(j,:),statedim,ut,pf%nens,0.0d0,xp(j,:),statedim)
286 xa(j,:) = sqrt(
real(pf%nens-1,rk))*xp(j,:)
288 xa(j,i) = mean_xa(j) + xa(j,i)
301 xa(j,i) = mean_xa(j) + xp(j,i)*sqrt(
real(pf%nens-1,rk))
313 number_gridpoints = stop_var(i)-start_var(i)+1
315 call mpi_scatterv(xa,&
316 gblcount*number_gridpoints,&
317 gbldisp*number_gridpoints,&
318 mpi_double_precision,&
319 pf%psi(start_var(i):stop_var(i),:),&
320 pf%count*number_gridpoints,&
321 mpi_double_precision,&
Module containing EMPIRE coupling data.
Module that stores the information about the outputting from empire.
Module that stores the information about the timestepping process.
subroutine letkf_analysis
subroutine to perform the ensemble transform Kalman filter as part of L-ETKF
Module that stores the dimension of observation and state spaces.
subroutine h(obsDim, nrhs, x, hx, t)
subroutine to take a full state vector x and return H(x) in observation space.
subroutine loc_function(loctype, dis, scal, inc)
subroutine to compute a localisation weighting based on a distance
subroutine solve_rhalf(obsdim, nrhs, y, v, t)
subroutine to take an observation vector y and return v in observation space.
module pf_control holds all the information to control the the main program
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 .
subroutine dist_st_ob(xp, yp, dis, t)
subroutine to compute the distance between the variable in the state vector and the variable in the o...