C $Header: /u/gcmpack/MITgcm/pkg/smooth/smooth_filtervar2d.F,v 1.5 2017/02/22 23:15:28 jmc Exp $ C $Name: $ #include "SMOOTH_OPTIONS.h" subroutine SMOOTH_FILTERVAR2D (smoothOpNb,mythid) C *==========================================================* C | SUBROUTINE smooth_filtervar2D C | o Routine that computes the filter variance C | field associated with a diffusion operator, as part C | a 2D spatial correlation operator (smooth_correld2D.F) C | See Weaver and Courtier 01 for details. C *==========================================================* IMPLICIT NONE #include "SIZE.h" #include "EEPARAMS.h" #include "PARAMS.h" #include "GRID.h" #include "SMOOTH.h" integer smoothOpNb, myThid Real*8 port_rand, port_rand_norm EXTERNAL , PORT_RAND_NORM integer i,j,k, bi, bj, ii, jj, kk integer itlo,ithi,jtlo,jthi integer diLoc,djLoc,dkLoc integer nbRand, nbt_in character*( 80) fnamegeneric _RL smoothTmpFld (1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy) _RL smoothTmpVar (1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy) _RL smoothTmpMean(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy) jtlo = mybylo(mythid) jthi = mybyhi(mythid) itlo = mybxlo(mythid) ithi = mybxhi(mythid) c if smooth2Dfilter(smoothOpNb)=0: the filter variance field c has been computed earlier and is already in the run directory c so this routine does not do anything IF (smooth2Dfilter(smoothOpNb).NE.0) then nbt_in=smooth2Dnbt(smoothOpNb)/2 c read smoothing [i.e diffusion] operator: write(fnamegeneric(1:80),'(1a,i3.3)') & 'smooth2Doperator',smoothOpNb CALL READ_REC_3D_RL(fnamegeneric,smoothprec, & 1,smooth2D_Kux,1,1,mythid) CALL READ_REC_3D_RL(fnamegeneric,smoothprec, & 1,smooth2D_Kvy,2,1,mythid) CALL EXCH_XY_RL ( smooth2D_Kux, myThid ) CALL EXCH_XY_RL ( smooth2D_Kvy, myThid ) c initialize filter variance field: DO bj=jtlo,jthi DO bi=itlo,ithi DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx smooth2Dnorm(i,j,bi,bj)=0. ENDDO ENDDO ENDDO ENDDO IF (smooth2Dfilter(smoothOpNb).EQ.2) then c compute the normalization matrix using the approximate method c c This method can be quite expensive -- so that the approximate c method (see below) is usually the prefered one. c The exact method can be used to check the accuracy c of the approximate method results (that can be predicted). c c note: the exact method requires the adjoint of smooth_diff2D.F (see below) diLoc=15 !int(5*smooth_L/smooth_dx) djLoc=20 !int(5*smooth_L/smooth_dx) DO ii=1,diLoc DO jj=1,djLoc DO bj=jtlo,jthi DO bi=itlo,ithi DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx smoothTmpFld(i,j,bi,bj)=0. ENDDO ENDDO DO j=jj,sNy,djLoc DO i=ii,sNx,diLoc smoothTmpFld(i,j,bi,bj)=1. ENDDO ENDDO ENDDO ENDDO c note: as we go to adjoint part, we need to have 0 in overlaps c so we must NOT have done an exchange for smoothTmpFld c adjoint: WRITE(errorMessageUnit,'(A,/,A)' ) & "you need to have adsmooth_diff2D compiled and then:", & "uncomment the line below and comment the stop" CALL ALL_PROC_DIE( myThid ) STOP 'ABNORMAL END: S/R smooth_filtervar2D' c call adsmooth_diff2D(smoothTmpFld,maskc,nbt_in,mythid) c division by sqrt(area)*sqrt(area) [1 to end adj, 1 to begin fwd] DO bj = jtlo,jthi DO bi = itlo,ithi DO j = 1,sNy DO i = 1,sNx c division by ~volume: smoothTmpFld(i,j,bi,bj)=smoothTmpFld(i,j,bi,bj) & *recip_rA(i,j,bi,bj) ENDDO ENDDO ENDDO ENDDO c coming out of adjoint part: overlaps are 0 c going in fwd part: we need to fill them up CALL EXCH_XY_RL ( smoothTmpFld,myThid ) c fwd: CALL SMOOTH_DIFF2D(smoothTmpFld,maskc,nbt_in,mythid) c convert variance to normalization factor: DO bj=jtlo,jthi DO bi=itlo,ithi DO j=jj,sNy,djLoc DO i=ii,sNx,diLoc if (maskc(i,j,1,bi,bj).NE.0) then smooth2Dnorm(i,j,bi,bj)= & 1/sqrt(smoothTmpFld(i,j,bi,bj)) endif ENDDO ENDDO ENDDO ENDDO ENDDO !DO ii=1,diLoc ENDDO !DO jj=1,djLoc ELSEIF (smooth2Dfilter(smoothOpNb).EQ.1) then c compute the normalization matrix using the approximate method DO bj=jtlo,jthi DO bi=itlo,ithi DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx smoothTmpMean(i,j,bi,bj) = 0. _d 0 smoothTmpVar(i,j,bi,bj) = 0. _d 0 ENDDO ENDDO ENDDO ENDDO c initialize random number generator smoothTmpFld(1,1,1,1)=port_rand(1.d0) nbRand=1000 DO ii=1,nbRand WRITE(standardMessageUnit,'(A,I4,A,I4)') & 'smooth_filtervar2D: ',ii,' members done out of',nbRand c fill smoothTmpFld with random numbers: DO bj=jtlo,jthi DO bi=itlo,ithi DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx smoothTmpFld(i,j,bi,bj) = 0. _d 0 if (maskC(i,j,1,bi,bj).NE.0) then smoothTmpFld(i,j,bi,bj)=port_rand_norm() endif c division by sqrt(area): smoothTmpFld(i,j,bi,bj)=smoothTmpFld(i,j,bi,bj) & *sqrt(recip_rA(i,j,bi,bj)) ENDDO ENDDO ENDDO ENDDO CALL EXCH_XY_RL ( smoothTmpFld, myThid ) c smooth random number field call SMOOTH_DIFF2D(smoothTmpFld,maskc,nbt_in,mythid) c accumulate statistics (to compute the variance later) DO bj=jtlo,jthi DO bi=itlo,ithi DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx smoothTmpVar(i,j,bi,bj)=smoothTmpVar(i,j,bi,bj) & +smoothTmpFld(i,j,bi,bj)*smoothTmpFld(i,j,bi,bj)/nbRand smoothTmpMean(i,j,bi,bj)=smoothTmpMean(i,j,bi,bj) & +smoothTmpFld(i,j,bi,bj)/nbRand ENDDO ENDDO ENDDO ENDDO ENDDO c compute variance and convert it to normalization factor: DO bj=jtlo,jthi DO bi=itlo,ithi DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx if (maskC(i,j,1,bi,bj).NE.0) then smooth2Dnorm(i,j,bi,bj)= & 1/sqrt ( nbRand/(nbRand-1)* ( smoothTmpVar(i,j,bi,bj) - & smoothTmpMean(i,j,bi,bj)*smoothTmpMean(i,j,bi,bj) & ) ) endif ENDDO ENDDO ENDDO ENDDO ENDIF c write smooth2Dnorm to file: write(fnamegeneric(1:80),'(1a,i3.3)') & 'smooth2Dnorm',smoothOpNb CALL WRITE_REC_3D_RL(fnamegeneric,smoothprec, & 1,smooth2Dnorm,1,1,mythid) CALL EXCH_XY_RL ( smooth2Dnorm, myThid ) ENDIF END