35 real(kind=kind(1.0d0)),
allocatable,
dimension(:,:) :: usiut
36 real(kind=kind(1.0d0)),
allocatable,
dimension(:) :: ud
43 integer,
intent(in) :: N
60 integer,
parameter :: rk = kind(1.0d0)
64 real(kind=rk),
dimension(state_dim,pf%count) :: x_p
67 real(kind=rk),
dimension(obs_dim) :: y
71 real(kind=rk),
dimension(:,:),
allocatable :: V
72 real(kind=rk),
dimension(:),
allocatable :: S
73 real(kind=rk),
dimension(pf%nens,pf%nens) :: UT
75 real(kind=rk),
dimension(pf%nens,pf%nens) :: U
77 real(kind=rk),
dimension(:),
allocatable :: WORK
80 real(kind=rk),
dimension(state_dim) :: mean_x
81 real(kind=rk),
dimension(:),
allocatable :: mean_xa
82 real(kind=rk),
dimension(state_dim,pf%count) :: Xp_p
84 real(kind=rk),
dimension(:,:),
allocatable :: Xp
85 real(kind=rk),
dimension(:,:),
allocatable :: Xa
86 real(kind=rk),
dimension(obs_dim) :: mean_yf,d,dd
87 real(kind=rk),
dimension(obs_dim_g) :: dd_g
88 real(kind=rk),
dimension(obs_dim,pf%nens) :: yf,Ysf
89 real(kind=rk),
dimension(obs_dim_g,pf%nens) :: Ysf_g
90 real(kind=rk),
dimension(obs_dim,pf%count) :: yf_p
91 integer :: i,j,number_gridpoints
95 real(kind=rk),
parameter :: maxscal=exp(8.0d0)
96 real(kind=rk),
dimension(obs_dim_g) :: scal
97 logical,
dimension(obs_dim_g) :: yes
99 real(kind=rk),
allocatable,
dimension(:,:) :: Ysf_red
100 real(kind=rk),
allocatable,
dimension(:) :: dd_red
105 integer,
dimension(npfs) :: start_var,stop_var
106 integer :: ensemble_comm
109 if(comm_version .eq. 1 .or. comm_version .eq. 2)
then
110 ensemble_comm = pf_mpi_comm
111 elseif(comm_version .eq. 3)
then
112 ensemble_comm = pf_ens_comm
114 write(emp_e,*)
'EMPIRE VERSION ',comm_version,
' NOT SUPPORTED IN letks_filter_state'
115 write(emp_e,*)
'THIS IS AN ERROR. STOPPING'
125 mean_x = sum(pf%psi,dim=2)
128 call mpi_allreduce(mpi_in_place,mean_x,state_dim,mpi_double_precision&
129 &,mpi_sum,ensemble_comm,mpi_err)
133 mean_x = mean_x/
real(pf%nens,rk)
138 xp_p(:,i) = pf%psi(:,i) - mean_x
142 xp_p = (1.0_rk + pf%rho) * xp_p
145 x_p(:,i) = mean_x + xp_p(:,i)
149 xp_p = xp_p/sqrt(
real(pf%nens-1,rk))
157 call
h(obs_dim,pf%count,x_p,yf_p,pf%timestep)
162 call mpi_allgatherv(yf_p,pf%count*obs_dim,mpi_double_precision,yf&
163 &,gblcount*obs_dim,gbldisp*obs_dim,mpi_double_precision&
164 &,ensemble_comm,mpi_err)
167 mean_yf = sum(yf,dim=2)/
real(pf%nens,rk)
169 yf(:,i) = yf(:,i) - mean_yf
173 yf = yf/sqrt(
real(pf%nens-1,rk))
175 call
solve_rhalf(obs_dim,pf%nens,yf,ysf,pf%timestep)
181 start_var(i) = (i-1)*ceiling(
real(state_dim,rk)/
real(npfs,rk) )+1
182 stop_var(i) = min( i*ceiling(
real(state_dim,rk)/
real(npfs,rk)) ,state_dim)
186 allocate(xp(stop_var(pfrank+1)-start_var(pfrank+1)+1,pf%nens))
187 allocate(xa(stop_var(pfrank+1)-start_var(pfrank+1)+1,pf%nens))
188 allocate(mean_xa(stop_var(pfrank+1)-start_var(pfrank+1)+1))
189 mean_xa = mean_x(start_var(pfrank+1):stop_var(pfrank+1))
193 number_gridpoints = stop_var(i)-start_var(i)+1
195 call mpi_gatherv(xp_p(start_var(i):stop_var(i),:),&
196 pf%count*number_gridpoints,&
197 mpi_double_precision,&
199 gblcount*number_gridpoints,&
200 gbldisp*number_gridpoints,&
201 mpi_double_precision,&
211 if(comm_version .eq. 1 .or. comm_version .eq. 2)
then
214 elseif(comm_version .eq. 3)
then
215 call mpi_allgatherv(dd,obs_dim,mpi_double_precision,dd_g,obs_dims&
216 &,obs_displacements,mpi_double_precision,pf_member_comm&
218 call mpi_allgatherv(ysf,obs_dim*pf%nens,mpi_double_precision&
219 &,ysf_g,obs_dims*pf%nens,obs_displacements*pf%nens&
220 &,mpi_double_precision,pf_member_comm,mpi_err)
222 print*,
'should not enter here. error. stopping :('
226 number_gridpoints = stop_var(pfrank+1)-start_var(pfrank+1)+1
236 do j = 1,number_gridpoints
246 call
dist_st_ob(j+start_var(pfrank+1)-1,i,dist,pf%timestep)
254 red_obsdim = count(yes)
258 lsd(j)%red_obsdim = red_obsdim
261 if(red_obsdim .gt. 0)
then
263 allocate(ysf_red(red_obsdim,pf%nens))
269 ysf_red(:,i) = pack(ysf_g(:,i),yes)*pack(scal,yes)
273 r = min(red_obsdim,pf%nens)
276 allocate(lsd(j)%Ud(pf%nens))
277 allocate(lsd(j)%USIUT(pf%nens,pf%nens))
280 allocate(v(red_obsdim,r))
282 lwork = 2*max( 3*r+max(red_obsdim,pf%nens), 5*r )
284 allocate(work(lwork))
286 call dgesvd(
'S',
'A',red_obsdim,pf%nens,ysf_red,red_obsdim,s,v,red_obsdim,ut,pf%nens,work,lwork,info)
288 write(emp_e,*)
'EMPIRE ERROR in letks_filter_stage with t&
290 write(emp_e,*)
'SVD failed with INFO = ',info
291 write(emp_e,*)
'FYI WORK(1) = ',work(1)
292 write(emp_e,*)
'STOPPING'
301 call dgemm(
'N',
'T',statedim,pf%nens,pf%nens,1.0d0,xp(j,:),statedim,ut,pf%nens,0.0d0,xa(j,:),statedim)
307 allocate(dd_red(red_obsdim))
308 dd_red = pack(dd_g,yes)*pack(scal,yes)
312 call dgemv(
'T',red_obsdim,r,1.0d0,v,red_obsdim,dd_red,1,0.0d0,d,1)
314 d(1:r) = s * d(1:r) / (1.0_rk + s**2)
317 call dgemv(
'T',r,pf%nens,1.0d0,ut,r,d(1:r),1,0.0d0&
326 call dgemv(
'N',statedim,r,1.0d0,xa(j,:),statedim,d,1,1.0d0,mean_xa(j),1)
331 xa(j,i) = xa(j,i) / sqrt(1.0_rk + s(i)**2)
338 u(:,i) = u(:,i) / sqrt(1.0_rk + s(i)**2)
340 call dgemm(
'N',
'N',pf%nens,pf%nens,pf%nens,1.0d0,u,pf%nens&
341 &,ut,pf%nens,0.0d0,lsd(j)%USIUT,pf%nens)
344 call dgemm(
'N',
'N',statedim,pf%nens,pf%nens,1.0d0,xa(j,:),statedim,ut,pf%nens,0.0d0,xp(j,:),statedim)
349 xa(j,:) = sqrt(
real(pf%nens-1,rk))*xp(j,:)
351 xa(j,i) = mean_xa(j) + xa(j,i)
364 xa(j,i) = mean_xa(j) + xp(j,i)
376 number_gridpoints = stop_var(i)-start_var(i)+1
378 call mpi_scatterv(xa,&
379 gblcount*number_gridpoints,&
380 gbldisp*number_gridpoints,&
381 mpi_double_precision,&
382 pf%psi(start_var(i):stop_var(i),:),&
383 pf%count*number_gridpoints,&
384 mpi_double_precision,&
404 integer,
parameter :: rk = kind(1.0d0)
407 real(kind=rk),
intent(in),
dimension(state_dim,pf%count) :: psi
409 real(kind=rk),
intent(out),
dimension(state_dim,pf%count) :: inc
415 real(kind=rk),
dimension(state_dim,pf%count) :: x_p
422 real(kind=rk),
dimension(state_dim) :: mean_x
423 real(kind=rk),
dimension(:),
allocatable :: mean_xa
424 real(kind=rk),
dimension(state_dim,pf%count) :: Xp_p
426 real(kind=rk),
dimension(:,:),
allocatable :: Xp
427 real(kind=rk),
dimension(:,:),
allocatable :: Xa
428 integer :: i,j,number_gridpoints
431 integer :: red_obsdim
436 integer,
dimension(npfs) :: start_var,stop_var
437 integer :: ensemble_comm
440 if(comm_version .eq. 1 .or. comm_version .eq. 2)
then
441 ensemble_comm = pf_mpi_comm
442 elseif(comm_version .eq. 3)
then
443 ensemble_comm = pf_ens_comm
445 write(emp_e,*)
'EMPIRE VERSION ',comm_version,
' NOT SUPPORTED IN letks_increment'
446 write(emp_e,*)
'THIS IS AN ERROR. STOPPING'
454 mean_x = sum(psi,dim=2)
457 call mpi_allreduce(mpi_in_place,mean_x,state_dim,mpi_double_precision&
458 &,mpi_sum,ensemble_comm,mpi_err)
462 mean_x = mean_x/
real(pf%nens,rk)
467 xp_p(:,i) = psi(:,i) - mean_x
471 xp_p = (1.0_rk + pf%rho) * xp_p
474 x_p(:,i) = mean_x + xp_p(:,i)
478 xp_p = xp_p/sqrt(
real(pf%nens-1,rk))
484 start_var(i) = (i-1)*ceiling(
real(state_dim,rk)/
real(npfs,rk) )+1
485 stop_var(i) = min( i*ceiling(
real(state_dim,rk)/
real(npfs,rk)) ,state_dim)
489 allocate(xp(stop_var(pfrank+1)-start_var(pfrank+1)+1,pf%nens))
490 allocate(xa(stop_var(pfrank+1)-start_var(pfrank+1)+1,pf%nens))
491 allocate(mean_xa(stop_var(pfrank+1)-start_var(pfrank+1)+1))
494 mean_xa = mean_x(start_var(pfrank+1):stop_var(pfrank+1))
498 number_gridpoints = stop_var(i)-start_var(i)+1
500 call mpi_gatherv(xp_p(start_var(i):stop_var(i),:),&
501 pf%count*number_gridpoints,&
502 mpi_double_precision,&
504 gblcount*number_gridpoints,&
505 gbldisp*number_gridpoints,&
506 mpi_double_precision,&
515 number_gridpoints = stop_var(pfrank+1)-start_var(pfrank+1)+1
519 do j = 1,number_gridpoints
525 red_obsdim = lsd(j)%red_obsdim
529 if(red_obsdim .gt. 0)
then
533 r = min(red_obsdim,pf%nens)
538 call dgemv(
'N',statedim,pf%nens,1.0d0,xp(j,:),statedim,lsd(j)%Ud,1,1.0d0,mean_xa(j),1)
544 call dgemm(
'N',
'N',statedim,pf%nens,pf%nens,1.0d0,xp(j,:),statedim,lsd(j)%USIUT,pf%nens,0.0d0,xa(j,:),statedim)
547 xp(j,:) = sqrt(
real(pf%nens-1,rk))*xa(j,:)
549 xa(j,i) = mean_xa(j) + xp(j,i)
556 xa(j,i) = mean_xa(j) + xp(j,i)
568 number_gridpoints = stop_var(i)-start_var(i)+1
570 call mpi_scatterv(xa,&
571 gblcount*number_gridpoints,&
572 gbldisp*number_gridpoints,&
573 mpi_double_precision,&
574 inc(start_var(i):stop_var(i),:),&
575 pf%count*number_gridpoints,&
576 mpi_double_precision,&
module for doing things related to the LETKS:
Module containing EMPIRE coupling data.
Module that stores the information about the outputting from empire.
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 deallocate_letks()
subroutine solve_rhalf(obsdim, nrhs, y, v, t)
subroutine to take an observation vector y and return v in observation space.
subroutine letks_increment(psi, inc)
subroutine to compute the LETKS increments
module pf_control holds all the information to control the the main program
subroutine letks_filter_stage
subroutine to compute the data for the LETKS, so that the increments can subsquently be computed ...
subroutine get_observation_data(y, t)
Subroutine to read observation from a file .
subroutine allocate_letks(N)
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...