C $Header: /u/gcmpack/MITgcm/pkg/smooth/smooth_filtervar3d.F,v 1.5 2017/02/22 23:15:28 jmc Exp $ C $Name: $ #include "SMOOTH_OPTIONS.h" subroutine SMOOTH_FILTERVAR3D (smoothOpNb,myThid) C *==========================================================* C | SUBROUTINE smooth_filtervar3D C | o Routine that computes the filter variance C | field associated with a diffusion operator, as part C | a 3D spatial correlation operator (smooth_correld3D.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,Nr,nSx,nSy) _RL smoothTmpMean(1-OLx:sNx+OLx,1-OLy:sNy+OLy,Nr,nSx,nSy) _RL smoothTmpVar(1-OLx:sNx+OLx,1-OLy:sNy+OLy,Nr,nSx,nSy) jtlo = mybylo(myThid) jthi = mybyhi(myThid) itlo = mybxlo(myThid) ithi = mybxhi(myThid) c if smooth3Dfilter(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 (smooth3Dfilter(smoothOpNb).NE.0) then nbt_in=smooth3Dnbt(smoothOpNb)/2 c read smoothing [i.e diffusion] operator: write(fnamegeneric(1:80),'(1a,i3.3)') & 'smooth3Doperator',smoothOpNb CALL READ_REC_3D_RL( fnamegeneric,smoothprec, Nr,smooth3D_Kwx, & 1, 1, myThid ) CALL READ_REC_3D_RL( fnamegeneric,smoothprec, Nr,smooth3D_Kwy, & 2, 1, myThid ) CALL READ_REC_3D_RL( fnamegeneric,smoothprec, Nr,smooth3D_Kwz, & 3, 1, myThid ) CALL READ_REC_3D_RL( fnamegeneric,smoothprec, Nr,smooth3D_Kux, & 4, 1, myThid ) CALL READ_REC_3D_RL( fnamegeneric,smoothprec, Nr,smooth3D_Kvy, & 5, 1, myThid ) CALL READ_REC_3D_RL( fnamegeneric,smoothprec, Nr,smooth3D_Kuz, & 6, 1, myThid ) CALL READ_REC_3D_RL( fnamegeneric,smoothprec, Nr,smooth3D_Kvz, & 7, 1, myThid ) CALL READ_REC_3D_RL( fnamegeneric,smoothprec, Nr,smooth3D_Kuy, & 8, 1, myThid ) CALL READ_REC_3D_RL( fnamegeneric,smoothprec, Nr,smooth3D_Kvx, & 9, 1, myThid ) CALL READ_REC_3D_RL( fnamegeneric,smoothprec, Nr,smooth3D_kappaR, & 10,1, myThid ) CALL EXCH_XYZ_RL ( smooth3D_Kwx, myThid ) CALL EXCH_XYZ_RL ( smooth3D_Kwy, myThid ) CALL EXCH_XYZ_RL ( smooth3D_Kwz, myThid ) CALL EXCH_XYZ_RL ( smooth3D_Kux, myThid ) CALL EXCH_XYZ_RL ( smooth3D_Kvy, myThid ) CALL EXCH_XYZ_RL ( smooth3D_Kuz, myThid ) CALL EXCH_XYZ_RL ( smooth3D_Kvz, myThid ) CALL EXCH_XYZ_RL ( smooth3D_Kuy, myThid ) CALL EXCH_XYZ_RL ( smooth3D_Kvx, myThid ) CALL EXCH_XYZ_RL ( smooth3D_kappaR, myThid ) c initialize filter variance field: DO bj=jtlo,jthi DO bi=itlo,ithi DO k=1,Nr DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx smooth3Dnorm(i,j,k,bi,bj)=0. ENDDO ENDDO ENDDO ENDDO ENDDO IF (smooth3Dfilter(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) dkLoc=8 DO kk=1,dkLoc DO ii=1,diLoc,2 DO jj=1,djLoc,2 DO bj=jtlo,jthi DO bi=itlo,ithi DO k=1,Nr DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx smoothTmpFld(i,j,k,bi,bj)=0. ENDDO ENDDO ENDDO DO k=kk,Nr,dkLoc DO j=jj,sNy,djLoc DO i=ii,sNx,diLoc smoothTmpFld(i,j,k,bi,bj)=1. ENDDO 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_diff3D compiled and then:", & "uncomment the line below and comment the stop" CALL ALL_PROC_DIE( myThid ) STOP 'ABNORMAL END: S/R smooth_filtervar3D' c call adsmooth_diff3D(smoothTmpFld,nbt_in,myThid) c division by sqrt(volume)*sqrt(volume) [1 to end adj, 1 to begin fwd] DO bj=jtlo,jthi DO bi=itlo,ithi DO k=1,Nr DO j=1,sNy DO i=1,sNx c division by ~sqrt(volume): smoothTmpFld(i,j,k,bi,bj)=smoothTmpFld(i,j,k,bi,bj) & *(recip_rA(i,j,bi,bj)*recip_drF(k)) ENDDO 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_XYZ_RL ( smoothTmpFld , myThid ) c fwd: call SMOOTH_DIFF3D(smoothTmpFld,nbt_in,myThid) c convert variance to normalization factor: DO bj=jtlo,jthi DO bi=itlo,ithi DO k=1,Nr,dkLoc DO j=jj,sNy,djLoc DO i=ii,sNx,diLoc if (smoothTmpFld(i,j,k,bi,bj).NE.0.) then smooth3Dnorm(i,j,k,bi,bj)= & 1/sqrt(smoothTmpFld(i,j,k,bi,bj)) endif ENDDO ENDDO ENDDO ENDDO ENDDO ENDDO !DO ii=1,diLoc ENDDO !DO jj=1,djLoc ENDDO !DO kk=1,dkLoc ELSEIF (smooth3Dfilter(smoothOpNb).EQ.1) then c compute the normalization matrix using the approximate method DO bj=jtlo,jthi DO bi=itlo,ithi DO k=1,Nr DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx smoothTmpMean(i,j,k,bi,bj) = 0. _d 0 smoothTmpVar(i,j,k,bi,bj) = 0. _d 0 ENDDO ENDDO ENDDO ENDDO ENDDO c initialize random number generator smoothTmpFld(1,1,1,1,1)=port_rand(1.d0) nbRand=1000 DO ii=1,nbRand WRITE(standardMessageUnit,'(A,I4,A,I4)') & 'smooth_filtervar3D: ',ii,' members done out of ',nbRand c fill smoothTmpFld with random numbers: DO bj=jtlo,jthi DO bi=itlo,ithi DO k=1,Nr DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx smoothTmpFld(i,j,k,bi,bj) = 0. _d 0 if (maskC(i,j,k,bi,bj).NE.0) then smoothTmpFld(i,j,k,bi,bj)=port_rand_norm() endif c division by sqrt(volume): smoothTmpFld(i,j,k,bi,bj)=smoothTmpFld(i,j,k,bi,bj) & *sqrt(recip_rA(i,j,bi,bj)*recip_drF(k)) ENDDO ENDDO ENDDO ENDDO ENDDO CALL EXCH_XYZ_RL ( smoothTmpFld, myThid ) c smooth random number field call SMOOTH_DIFF3D(smoothTmpFld,nbt_in,myThid) c accumulate statistics (to compute the variance later) DO bj=jtlo,jthi DO bi=itlo,ithi DO k=1,Nr DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx smoothTmpVar(i,j,k,bi,bj)=smoothTmpVar(i,j,k,bi,bj) & +smoothTmpFld(i,j,k,bi,bj)*smoothTmpFld(i,j,k,bi,bj)/nbRand smoothTmpMean(i,j,k,bi,bj)=smoothTmpMean(i,j,k,bi,bj) & +smoothTmpFld(i,j,k,bi,bj)/nbRand ENDDO ENDDO ENDDO ENDDO ENDDO ENDDO c compute variance and convert it to normalization factor: DO bj=jtlo,jthi DO bi=itlo,ithi DO k=1,Nr DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx if (maskC(i,j,k,bi,bj).NE.0) then smooth3Dnorm(i,j,k,bi,bj)= & 1/sqrt ( nbRand/(nbRand-1)* ( smoothTmpVar(i,j,k,bi,bj) - & smoothTmpMean(i,j,k,bi,bj)*smoothTmpMean(i,j,k,bi,bj) & ) ) endif ENDDO ENDDO ENDDO ENDDO ENDDO ENDIF c write smooth3Dnorm_3D to file: write(fnamegeneric(1:80),'(1a,i3.3)') & 'smooth3Dnorm',smoothOpNb CALL WRITE_REC_3D_RL( fnamegeneric, smoothprec, & Nr, smooth3Dnorm, 1, 1, myThid ) CALL EXCH_XYZ_RL ( smooth3Dnorm, myThid ) ENDIF RETURN END