| 1 | afe | 1.1 | subroutine greg_sqrt(xens,yo,H,ngp,mobs,RRs,nens) | 
| 2 |  |  |  | 
| 3 |  |  | c      implicit none | 
| 4 |  |  |  | 
| 5 |  |  | include 'mpif.h' | 
| 6 |  |  |  | 
| 7 |  |  | integer   MASTER, FROM_MASTER, FROM_WORKER | 
| 8 |  |  | parameter (MASTER = 0) | 
| 9 |  |  | parameter (FROM_MASTER = 1) | 
| 10 |  |  | parameter (FROM_WORKER = 2) | 
| 11 |  |  |  | 
| 12 |  |  | integer   taskid, ierr, numtasks, numworkers, snumworkers | 
| 13 |  |  | integer   source, dest, mtype, num, avenum, extra, offset | 
| 14 |  |  | integer   status(MPI_STATUS_SIZE) | 
| 15 |  |  |  | 
| 16 |  |  | ! Arguments | 
| 17 |  |  | integer, intent(in)    :: nens, mobs, ngp | 
| 18 |  |  | real,    intent(inout) :: xens(ngp,nens) | 
| 19 |  |  | real,    intent(in)    :: yo(mobs), RRs(mobs), H(mobs,ngp) | 
| 20 |  |  |  | 
| 21 |  |  | ! Local Variables | 
| 22 |  |  | integer :: rad, xob(mobs), yob(mobs), ind, nx, ny | 
| 23 |  |  | integer :: k, j, i, r2, kk, jj, ko, jo, kj, g | 
| 24 |  |  | real    :: PHT(ngp), HPHT, Ks(ngp), Khat(ngp), alpha | 
| 25 |  |  | real    :: xp(ngp), xa(ngp), zp(ngp,nens), R, Rs, boost | 
| 26 |  |  | real, parameter :: eps = 1.e-6 ! corresponds to verr = 0.001 | 
| 27 |  |  | ! Filter Stuff | 
| 28 |  |  | integer :: d, fexp | 
| 29 |  |  | real    :: dr, fcoef, filt | 
| 30 |  |  |  | 
| 31 |  |  | call MPI_COMM_RANK(MPI_COMM_WORLD,taskid,ierr) | 
| 32 |  |  | call MPI_COMM_SIZE(MPI_COMM_WORLD,numtasks,ierr) | 
| 33 |  |  |  | 
| 34 |  |  |  | 
| 35 |  |  | if (taskid.eq.MASTER) then | 
| 36 |  |  |  | 
| 37 |  |  |  | 
| 38 |  |  | write(6,*) 'a' | 
| 39 |  |  |  | 
| 40 |  |  | nx = 33 | 
| 41 |  |  | ny = 65 | 
| 42 |  |  |  | 
| 43 |  |  | Rs = RRs(1) | 
| 44 |  |  | R = sqrt(Rs) | 
| 45 |  |  |  | 
| 46 |  |  | rad = 20 | 
| 47 |  |  | rad = 100 | 
| 48 |  |  | r2 = rad*rad | 
| 49 |  |  |  | 
| 50 |  |  | fexp = 2 | 
| 51 |  |  | fcoef = 0.05 | 
| 52 |  |  | boost = 1.05 | 
| 53 |  |  | boost =1.0 | 
| 54 |  |  |  | 
| 55 |  |  | zp = xens | 
| 56 |  |  |  | 
| 57 |  |  | !*** Transform 2D state vector into 1D vector.... | 
| 58 |  |  | !  do j = 1, nens | 
| 59 |  |  | !     do k = 1, ny | 
| 60 |  |  | !        zp(nx*(k-1)+1:k*nx,j) = xens(:,k,j) | 
| 61 |  |  | !     end do | 
| 62 |  |  | !  end do | 
| 63 |  |  |  | 
| 64 |  |  | write(6,*) 'b' | 
| 65 |  |  |  | 
| 66 |  |  | !*** Find the initial ensemble mean | 
| 67 |  |  | do j = 1, ngp | 
| 68 |  |  | xp(j) = sum(zp(j,:))/float(nens) | 
| 69 |  |  | end do | 
| 70 |  |  |  | 
| 71 |  |  | !*** Apply inflation factor to initial ensemble | 
| 72 |  |  | do k = 1, nens | 
| 73 |  |  | zp(:,k) = boost*(zp(:,k) - xp) + xp | 
| 74 |  |  | end do | 
| 75 |  |  |  | 
| 76 |  |  | write(6,*) 'c' | 
| 77 |  |  |  | 
| 78 |  |  | !*** Find the xob and yob arrays from H | 
| 79 |  |  | do j = 1, ngp | 
| 80 |  |  | do k = 1, mobs | 
| 81 |  |  | if ( H(k,j) == 1. ) then | 
| 82 |  |  | xob(k) = mod(j-1,nx) + 1 | 
| 83 |  |  | yob(k) = (j-1)/nx + 1 | 
| 84 |  |  | end if | 
| 85 |  |  | end do | 
| 86 |  |  | end do | 
| 87 |  |  |  | 
| 88 |  |  |  | 
| 89 |  |  | write(6,*) 'd' | 
| 90 |  |  |  | 
| 91 |  |  | !*** Now process each observation sequentially abiding by cut-off radius | 
| 92 |  |  | do j = 1, mobs | 
| 93 |  |  | ind = nx*( yob(j) - 1 ) + xob(j) | 
| 94 |  |  |  | 
| 95 |  |  | write(6,*) 'e' | 
| 96 |  |  |  | 
| 97 |  |  | !*** Find PH' first | 
| 98 |  |  | PHT = 0.0 | 
| 99 |  |  | do jj = yob(j)-rad, yob(j)+rad | 
| 100 |  |  | do kk = xob(j)-rad, xob(j)+rad | 
| 101 |  |  | jo = jj | 
| 102 |  |  | ko = kk | 
| 103 |  |  |  | 
| 104 |  |  | write(6,*) 'f', j, jo, ko | 
| 105 |  |  |  | 
| 106 |  |  | !*** Point is within block of radius, but it may not be within the | 
| 107 |  |  | !      basin boundaries | 
| 108 |  |  | if ( ko>0 .and. ko<=nx .and. jo>0 .and. jo<=ny ) then | 
| 109 |  |  |  | 
| 110 |  |  | !*** Since we've sequestered a square of side 2*rad and the | 
| 111 |  |  | !      cut-off radius assumes a circle, we need to check to | 
| 112 |  |  | !      make sure the point we're considering is actually | 
| 113 |  |  | !      within the circle. | 
| 114 |  |  |  | 
| 115 |  |  | write(6,*) 'g' | 
| 116 |  |  |  | 
| 117 |  |  | d = (ko - xob(j))**2 + (jo - yob(j))**2 | 
| 118 |  |  |  | 
| 119 |  |  | write(6,*) 'h' | 
| 120 |  |  |  | 
| 121 |  |  | if ( d <= r2 ) then | 
| 122 |  |  |  | 
| 123 |  |  | dr = sqrt( float( d ) ) | 
| 124 |  |  |  | 
| 125 |  |  | !*** The element of interest in the 1D vector according to addresses | 
| 126 |  |  | !      kk and jj is: | 
| 127 |  |  | kj = nx*(jo-1) + ko | 
| 128 |  |  |  | 
| 129 |  |  | write(6,*) 'i' | 
| 130 |  |  |  | 
| 131 |  |  | !*** Evaluate the filter coefficient based on distance from center d | 
| 132 |  |  | filt = 1.0 - exp( -fcoef*( (float(rad) - dr)**fexp ) ) | 
| 133 |  |  | filt = 1.0 | 
| 134 |  |  |  | 
| 135 |  |  | write(6,*) 'j' | 
| 136 |  |  |  | 
| 137 |  |  | !*** Now contribute to PHT sum | 
| 138 |  |  | do g = 1, nens | 
| 139 |  |  | PHT(kj) = PHT(kj) + filt*(zp(kj,g) - xp(kj))* | 
| 140 |  |  | &                  (zp(ind,g) - xp(ind)) | 
| 141 |  |  | end do | 
| 142 |  |  |  | 
| 143 |  |  | write(6,*) 'k' | 
| 144 |  |  |  | 
| 145 |  |  | end if | 
| 146 |  |  | end if | 
| 147 |  |  | end do | 
| 148 |  |  | end do | 
| 149 |  |  | PHT = PHT/float(nens - 1) | 
| 150 |  |  |  | 
| 151 |  |  | !*** Now find HPH' from PH'.  Because of cut-off radius, there is a | 
| 152 |  |  | !      (good) chance that HPH' will be zero. | 
| 153 |  |  | HPHT = PHT(ind) | 
| 154 |  |  |  | 
| 155 |  |  | !*** Evaluate Ks | 
| 156 |  |  | Ks = PHT/( HPHT + Rs ) | 
| 157 |  |  |  | 
| 158 |  |  | !*** Update all effected elements in the mean | 
| 159 |  |  | xa = xp + Ks*( yo(j) - xp(ind) ) | 
| 160 |  |  |  | 
| 161 |  |  | !*** Now update all ensemble members as perturbations about mean | 
| 162 |  |  | alpha = 1.0/( 1.0 + sqrt( Rs/( HPHT + Rs ) ) ) | 
| 163 |  |  | Khat = alpha*Ks | 
| 164 |  |  |  | 
| 165 |  |  | do g = 1, nens | 
| 166 |  |  | zp(:,g) = ((zp(:,g) - xp) - Khat*( zp(ind,g) - | 
| 167 |  |  | &           xp(ind) )) + xa | 
| 168 |  |  | end do | 
| 169 |  |  |  | 
| 170 |  |  | !*** Use analysis ensemble as the background for the next observation | 
| 171 |  |  | xp = xa | 
| 172 |  |  |  | 
| 173 |  |  | end do | 
| 174 |  |  |  | 
| 175 |  |  | print*, 'EnSRF:: Done Mobs Loop' | 
| 176 |  |  |  | 
| 177 |  |  | xens = zp | 
| 178 |  |  |  | 
| 179 |  |  | endif | 
| 180 |  |  |  | 
| 181 |  |  | return | 
| 182 |  |  |  | 
| 183 |  |  | end subroutine greg_sqrt | 
| 184 |  |  |  | 
| 185 |  |  |  |