| 1 |
afe |
1.1 |
c*** ensemble kalman filter subroutine |
| 2 |
|
|
|
| 3 |
|
|
subroutine EnKF(A,z,H,ns,no,varmes,nrsamp) |
| 4 |
|
|
|
| 5 |
|
|
c*** A is the matrix of ensemble forecasts, z is the observation, |
| 6 |
|
|
c*** H is the observation operator, ns is the size of the model |
| 7 |
|
|
c*** state, no is the number of observation locations, varmes is |
| 8 |
|
|
c*** the observational uncertainty, and nrsamp is the ensemble size. |
| 9 |
|
|
|
| 10 |
|
|
integer ns, no, nrsamp |
| 11 |
|
|
integer ijim |
| 12 |
|
|
|
| 13 |
|
|
real, intent(inout) :: A(ns,nrsamp) |
| 14 |
|
|
real, intent(in) :: z(no) |
| 15 |
|
|
|
| 16 |
|
|
integer i,j,m,mm,info,idum,ibawk |
| 17 |
|
|
real rcond |
| 18 |
|
|
real H(no,ns) |
| 19 |
|
|
real vave(ns), vvar(ns), varmes(no) |
| 20 |
|
|
real temp |
| 21 |
|
|
|
| 22 |
|
|
real, allocatable :: K(:,:) |
| 23 |
|
|
real, allocatable :: RR(:,:) |
| 24 |
|
|
real, allocatable :: RRR(:,:) |
| 25 |
|
|
real, allocatable :: w(:) |
| 26 |
|
|
real, allocatable :: tmp(:,:) |
| 27 |
|
|
real, allocatable :: d(:) |
| 28 |
|
|
real, allocatable :: pd(:,:) |
| 29 |
|
|
real, allocatable :: transA(:,:) |
| 30 |
|
|
real, allocatable :: transtmp(:,:) |
| 31 |
|
|
real, allocatable :: tmp2(:,:) |
| 32 |
|
|
|
| 33 |
|
|
|
| 34 |
|
|
allocate (K(no,ns), RR(no,no), RRR(no,no)) |
| 35 |
|
|
allocate (transA(nrsamp,ns),transtmp(nrsamp,no)) |
| 36 |
|
|
allocate (w(ns), tmp(no,nrsamp)) |
| 37 |
|
|
allocate (d(no), pd(1,ns), tmp2(1,ns)) |
| 38 |
|
|
|
| 39 |
|
|
c*** initialising the observational error covariance matrix and |
| 40 |
|
|
c*** the projector from model space to observational space. |
| 41 |
|
|
RR=0.0 |
| 42 |
|
|
|
| 43 |
|
|
c*** define obs error covariance matrix as a diagonal matrix |
| 44 |
|
|
do m=1,no |
| 45 |
|
|
RR(m,m)=varmes(m) |
| 46 |
|
|
enddo |
| 47 |
|
|
|
| 48 |
|
|
c*** calculate ensemble mean |
| 49 |
|
|
call ranmean2(A,w,ns,nrsamp) |
| 50 |
|
|
|
| 51 |
|
|
c*** remove ensemble mean from the ensemble members |
| 52 |
|
|
do i=1,nrsamp |
| 53 |
|
|
A(:,i)=A(:,i)-w(:) |
| 54 |
|
|
enddo |
| 55 |
|
|
|
| 56 |
|
|
c*** tmp takes on the product of the observation projector and |
| 57 |
|
|
c*** the ensemble anomalies. |
| 58 |
|
|
tmp=matmul(H,A) |
| 59 |
|
|
|
| 60 |
|
|
c*** K takes on the value of H(A-ABAR)(A-ABAR)^T |
| 61 |
|
|
K=matmul(tmp,transpose(A)) |
| 62 |
|
|
|
| 63 |
|
|
c*** K is what is called B in eqn (6) |
| 64 |
|
|
K=(1.0/(float(nrsamp)-1.0))*K |
| 65 |
|
|
|
| 66 |
|
|
c*** restore A by adding back ensemble mean value. |
| 67 |
|
|
do i=1,nrsamp |
| 68 |
|
|
A(:,i)=A(:,i)+w(:) |
| 69 |
|
|
enddo |
| 70 |
|
|
|
| 71 |
|
|
c*** RR is obs error cov matrix, and the forecast error cov is added to |
| 72 |
|
|
c*** it, making it the first half of the right hand side of equation (8). |
| 73 |
|
|
c*** if one was to wipe out spurious long distance correlations, it would |
| 74 |
|
|
c*** happen here. |
| 75 |
|
|
RR=RR+(1./(float(nrsamp)-1.))*matmul(tmp,transpose(tmp)) |
| 76 |
|
|
|
| 77 |
|
|
c*** standard solver for coefficients beta |
| 78 |
|
|
call spoco(RR,no,no,rcond,w,info) |
| 79 |
|
|
|
| 80 |
|
|
c*** correct each member of the ensemble |
| 81 |
|
|
do j=1,nrsamp |
| 82 |
|
|
|
| 83 |
|
|
call random2(d,no) |
| 84 |
|
|
d=z+sqrt(varmes)*d-matmul(H,A(:,j)) |
| 85 |
|
|
call sposl(RR,no,no,d) |
| 86 |
|
|
A(:,j)=A(:,j)+matmul(d,K) |
| 87 |
|
|
|
| 88 |
|
|
enddo !A has now been corrected by the data. |
| 89 |
|
|
|
| 90 |
|
|
deallocate (K, RR, RRR) |
| 91 |
|
|
deallocate (transA, transtmp) |
| 92 |
|
|
deallocate (w, tmp) |
| 93 |
|
|
deallocate (d,pd,tmp2) |
| 94 |
|
|
|
| 95 |
|
|
return |
| 96 |
|
|
end |
| 97 |
|
|
|
| 98 |
|
|
|
| 99 |
|
|
|
| 100 |
|
|
|
| 101 |
|
|
|