123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518 |
- ! File: p_fixhycom.F90
- !
- ! Created: ???
- !
- ! Last modified: 29/06/2010
- !
- ! Purpose: Fixes EnKF output.
- !
- ! Description:
- !
- ! Modifications:
- ! 1/03/2011 Ehouarn:
- ! -modification of the fixhycom subroutine: interpolation of
- ! biogeochemical tracers on the analysis grid according to
- ! hycom remapping in order to insure conservation.
- ! 29/06/2010 PS:
- ! - set the maximum ICEC to 0.995 to match the model
- ! ?/?/? KAL:
- ! - Modification of the "fixhycom" subroutine, into separate
- ! program, working on a file-by-file basis
- ! Prior history:
- ! Not documented.
- ! KAL -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
- ! KAL -- Input arguments:
- ! KAL -- template restart file
- ! KAL -- ensemble member
- ! KAL -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
- ! KAL -- TODO: Fix for ice fields
- program fixhycom_eco
- use mod_raw_io
- use m_parse_blkdat
- use m_put_mod_fld
- use m_get_mod_fld
- use m_get_mod_grid
- #if defined (ECO)
- use m_fixhycom_eco_metno
- #endif
- implicit none
- integer*4, external :: iargc
- real, parameter :: onem=9806.
- real, parameter :: PSTARB0 = 1000;
- integer imem ! ensemble member
- character(len=80) :: restart,icerestart ! restart template
- character(len=80) :: afile,newfile, char80
- integer :: fnd, rstind, tmpindx, iafile
- logical :: ex, allok, nomatch
- character(len=8) :: cfld, ctmp
- character(len=3) :: cproc,cmem
- integer :: tlevel, vlevel, nproc
- real :: bmin, bmax, rdummy
- integer :: idm,jdm,kdm
- real, allocatable:: fld(:,:)
- real*8, allocatable, dimension(:,:) :: &
- ficem,hicem,hsnwm,ticem,tsrfm
- real, allocatable, dimension(:,:) :: depths,modlon,modlat,saln
- real*4, allocatable:: fldr4(:,:)
- real*4 :: spval,amin,amax
- real, allocatable :: press(:)
- real, allocatable, dimension(:,:) :: dpsum
- real, allocatable, dimension(:,:,:) :: dp, dpold
- integer,parameter :: numfields=2
- integer :: ios,ios2, reclICE,ifld
- integer :: i,j,k,ktr
- real :: mindx,meandx
-
- #if defined (ECO)
- real,dimension(:,:,:), allocatable::dpfor,cfi
- character(len=80) :: restfor
- real,dimension(:,:,:,:), allocatable::tracerf
- real, dimension(:,:), allocatable::trcraij
- real, dimension(:), allocatable::prsf,dpf
- integer::ntracr,ktrcr
- real::dpthin
- character(2)::ctrcr
- logical, dimension(:), allocatable::lcm
-
- real, dimension(:,:,:), allocatable::temp,sal
- integer::kisop
- #endif
- icerestart=''
- if (iargc()==2 .or. iargc()==3) then
- call getarg(1,restart)
- call getarg(2,ctmp)
- read(ctmp,*) imem
- write(cmem,'(i3.3)') imem
- if (iargc()==3) call getarg(3,icerestart)
- else
- print *,'"fixhycom" -- A crude routine to correct restart files for obvious errors'
- print *
- print *,'usage: '
- print *,' fixhycom restart_file ensemble_member <ice_file>'
- print *,' "restart_file" the restart file you want to fix (.a-file)"'
- print *,' "ensemble_member" is the ensemble member - should corr. to that of restart file'
- print *,' "ice_file" is optional - it is the restart file for ice fields'
- call exit(1)
- endif
- ! Get dimensions from blkdat
- call parse_blkdat('idm ','integer',rdummy,idm)
- call parse_blkdat('jdm ','integer',rdummy,jdm)
- call parse_blkdat('kdm ','integer',rdummy,kdm)
- #if defined (ECO)
- call parse_blkdat('ntracr','integer',rdummy,ntracr)
- #endif
-
- if (idm>0 .and. idm < 1e4 .and. jdm>0 .and. jdm<1e4) then
- allocate(fld (idm,jdm))
- allocate(fldr4(idm,jdm))
- allocate(saln (idm,jdm))
- allocate(ficem(idm,jdm))
- allocate(hicem(idm,jdm))
- allocate(hsnwm(idm,jdm))
- allocate(ticem(idm,jdm))
- allocate(tsrfm(idm,jdm))
- allocate(dpsum(idm,jdm))
- allocate(depths(idm,jdm))
- allocate(modlon(idm,jdm))
- allocate(modlat(idm,jdm))
- allocate(dpold(idm,jdm,kdm))
- allocate(dp (idm,jdm,kdm))
- allocate(press(kdm+1))
- #if defined (ECO)
- allocate(dpfor(idm,jdm,kdm))
- allocate(cfi(kdm,ntracr,2))
- allocate(prsf(kdm+1))
- allocate(tracerf(idm,jdm,kdm,ntracr))
- allocate(trcraij(kdm,ntracr))
- allocate(lcm(kdm))
- allocate(dpf(kdm))
- allocate(sal(idm,jdm,kdm))
- allocate(temp(idm,jdm,kdm))
- #endif
- else
- print *,'fld allocate error'
- stop '(EnKF_postprocess)'
- end if
- ! Remove postfix of restart file
- fnd=max(index(restart,'.a'),index(restart,'.b'))
- ! Inquire for existence
- inquire(exist=ex,file=restart(1:fnd-1)//'.b')
- if (.not.ex) then
- write(*,*) 'Can not find '//restart(1:fnd-1)//'.b'
- stop '(EnKF_postprocess)'
- end if
- print *,restart(1:fnd-1)//'.b'
- newfile='fix'//restart(1:fnd-1)
- ! Get model grid
- call get_mod_grid(modlon,modlat,depths,mindx,meandx,idm,jdm)
- #if defined (ECO)
- !files where are stored the forecast fields!
- restfor='forecast'//cmem
- dpthin = onem*0.001
- #endif
- ! Get layer thickness
- dpsum=0.
- do k=1,kdm
- !call get_mod_fld(dp(:,:,k),1,'dp ',k,1)
- call get_mod_fld_new(restart(1:fnd-1),dp(:,:,k),imem,'dp ',k,1,idm,jdm)
- dpsum=dpsum+dp(:,:,k)
- #if defined (ECO)
- !reading of forecast fields: tracers, T and S
- call get_mod_fld_new(trim(restfor),dpfor(:,:,k),imem,'dp ',k,1,idm,jdm)
- do ktrcr=1,ntracr
- write(ctrcr,'(i2.2)') ktrcr
- cfld='tracer'//ctrcr
- call get_mod_fld_new(trim(restfor),tracerf(:,:,k,ktrcr),imem,cfld,k,1,idm,jdm)
- enddo
- call get_mod_fld_new(trim(restfor),temp(:,:,k),imem,'temp ',k,1,idm,jdm)
- call get_mod_fld_new(trim(restfor),sal(:,:,k),imem,'saln ',k,1,idm,jdm)
- #endif
- end do
- print *,maxval(dpsum-depths*onem)
- dpold=dp
- ! DP correction
- do j=1,jdm
- do i=1,idm
- !!! Move negative layers to neighbouring layers.
- do k = 1, kdm-1
- dp(i,j,k+1) = dp(i,j,k+1) + min(0.0,dp(i,j,k))
- dp(i,j,k ) = max(dp(i,j,k),0.0)
- !dp(i,j,k ) = max(dp(i,j,k),1.e-3*onem)
- end do
- !!! Go backwards to fix lowermost layer.
- do k = kdm, 3, -1
- dp(i,j,k-1) = dp(i,j,k-1) + min(0.0,dp(i,j,k))
- dp(i,j,k) = max(dp(i,j,k),0.0)
- !dp(i,j,k) = max(dp(i,j,k),1.e-3*onem)
- end do
- !!! No layers below the sea bed.
- press( 1) = 0.0
- #if defined (ECO)
- !computation of the forecast layer interfaces (prsf)!
- prsf(1)=0.
- #endif
- do k = 1, kdm-1
- press(k+1) = press(k) + dp(i,j,k)
- press(k+1) = min(depths(i,j)*onem,press(k+1))
- #if defined (ECO)
- prsf(k+1) = prsf(k) + dpfor(i,j,k)
- #endif
- end do
- press(kdm+1) = depths(i,j)*onem
- #if defined (ECO)
- prsf(kdm+1)=depths(i,j)*onem
- #endif
- do k = 1, kdm
- dp(i,j,k) = press(k+1) - press(k)
- #if defined (ECO)
- !definition of the isopycnal layers!
- dpf(k)=max(dpfor(i,j,k),dpthin)
- kisop=compute_kisop(temp(i,j,:),sal(i,j,:),kdm)
- if (k.le.max(2,kisop)) then
- lcm(k) = .false. !fixed layers are never PCM
- else
- ! --- thin and isopycnal layers remapped with PCM.
- lcm(k) = dpfor(i,j,k).le.dpthin
- endif
- #endif
- end do
- !eho 2/11/11
- if(depths(i,j)>10000. .or. depths(i,j)<1.)then
- dp(i,j,:)=dpold(i,j,:)
- endif
-
- #if defined (ECO)
- ! if(depths(i,j)==0.)then
- if(depths(i,j)>10000. .or. depths(i,j)<1.)then
- cycle
- else
- call hybgen_weno_coefs(tracerf(i,j,:,:),dpf,lcm,cfi,kdm,ntracr,dpthin)
- call hybgen_weno_remap(tracerf(i,j,:,:),prsf,dpfor(i,j,:),cfi,trcraij,&
- press,kdm,kdm,ntracr,dpthin)
- tracerf(i,j,1:kdm,1:ntracr)=trcraij(1:kdm,1:ntracr)
- endif
-
- #endif
-
- end do
- end do
- do k = 1, kdm
- print *,maxval(dpold(:,:,k)-dp(:,:,k))/onem
- end do
- #if defined (ECO)
- deallocate(trcraij,dpf,lcm,cfi,prsf,dpfor)
- #endif
- ! Loop over restart file
- rstind=1 ! Restart index
- allok=.true.
- do while ( allok)
- ! Get header info from restart
- call rst_header_from_index(restart(1:fnd-1)//'.b', &
- cfld,vlevel,tlevel,rstind,bmin,bmax,.true.)
- allok=tlevel/=-1 ! test to see if read was ok
- print *,cfld
- if (allok) then
- ! Get actual field - for now we use the READRAW routine (later on we
- ! should switch to m_get_mod_fld
- ! call READRAW(fldr4,amin,amax,idm,jdm,.false.,spval,restart(1:fnd-1)//'.a',rstind)
- ! fld=fldr4
- ! Sjekk p at vi har lest rett - samanlign max/min fr filene
- ! if (abs(amin-bmin).gt.abs(bmin)*1.e-4 .or. &
- ! abs(bmax-amax).gt.abs(bmax)*1.e-4 ) then
- ! print *,'Inconsistency between .a and .b files'
- ! print *,'.a : ',amin,amax
- ! print *,'.b : ',bmin,bmax
- ! print *,cfld,vlevel,tlevel
- ! call exit(1)
- ! end if
- call get_mod_fld_new(restart(1:fnd-1),fld(:,:),imem,cfld,vlevel,1,idm,jdm)
- if (trim(cfld)=='temp') then
- ! need salinity as well
- call get_mod_fld_new(restart(1:fnd-1),saln(:,:),imem,'saln ',vlevel,1,idm,jdm)
- !if (tlevel==-1) then
- ! print *,'Could not get salinity field'
- ! call exit(1)
- !end if
- ! keep water warmer than freezing point
- do j=1,jdm
- do i=1,idm
- fld(i,j)=max(-.057*saln(i,j),fld(i,j))
- fld(i,j)=min(35.,fld(i,j)) !FC: cut off values that are too warm
- end do
- end do
- else if (trim(cfld)=='saln') then
- do j=1,jdm
- do i=1,idm
- fld(i,j)=max(5.,fld(i,j)) ! LB :no water fresher than 5 psu (Baltic)
- fld(i,j)=min(41.,fld(i,j))! FC: no water saltier than 40 psu
- end do
- end do
- else if (trim(cfld)=='pstarb') then
- fld(:,:) = (sqrt(PSTARB0 ** 2 + fld(:,:) ** 2) + fld(:,:)) / 2.0d0;
- else if (trim(cfld)=='dp') then
- fld = dp(:,:,vlevel) ! NB, one time level
- #if defined (ECO)
- else if (cfld(1:6)=='tracer') then
- !updating the file!
- ktrcr=tracr_get_incr(cfld(7:8))
- if (ktrcr==-1)then
- print*,'alert tracer unknow'
- exit
- endif
- fld(:,:)= tracerf(:,:,vlevel,ktrcr)
-
- #endif
- end if ! No correction for other fields in the hycom restart file
- call put_mod_fld(trim(newfile),fld,imem,cfld,vlevel,tlevel,rstind,idm,jdm)
-
- rstind=rstind+1
- end if ! read of template was ok
- end do
- #if defined (ECO)
- deallocate(tracerf)
- #endif
- ! put_mod_fld does not include the header from the original file
- open(10,file=trim(newfile)//'.b',status='old')
- open(20,file=restart(1:fnd-1)//'.b',status='old')
- ! Supports parallel execution with different members
- open(11,file='tmp'//cmem//'.b',status='replace')
- ! Header from original file
- read(20,'(a80)') char80 ; write(11,'(a80)') char80
- read(20,'(a80)') char80 ; write(11,'(a80)') char80
- close(20)
- ! The rest from the newly created file
- ios=0
- do while(ios==0)
- read(10,'(a80)',iostat=ios) char80
- if (ios==0) write(11,'(a80)') char80
- end do
- close(10)
- close(11)
- close(20)
- ! Move the new .b file to "newfile"
- !SERIAL call system('mv tmp'//cmem//'.b '//trim(newfile)//'.b')
- !###################################################################
- !####################### FIX ICE MODEL #########################
- !###################################################################
- if (iargc()==3) then
- inquire(exist=ex,file=trim(icerestart))
- if (.not.ex) then
- print *,icerestart//' does not exist!'
- print *,'(fixhycom)'
- stop
- end if
- inquire(iolength=reclICE)ficem,hicem,hsnwm,ticem,tsrfm !,iceU,iceV
- open(10,file=icerestart,form='unformatted',access='direct',recl=reclICE)
- read(10,rec=imem)ficem,hicem,hsnwm,ticem,tsrfm !,iceU,iceV
- close(10)
- ! PS 25/06/2010 max(ficem) = 0.995 - max the model allows
- ficem=min(max(0.,ficem), 0.995)
- hicem=min(max(0.,hicem),15.)
- hsnwm=min(max(0.,hsnwm), 4.)
- open (10,file='fix'//trim(icerestart),form='unformatted',access='direct',recl=reclICE)
- write(10,rec=imem)ficem,hicem,hsnwm,ticem,tsrfm !,iceU,iceV
- close(10)
- end if
-
- !KAL
- !KAL ! This is to make it easier for supporting programs
- !KAL open(10,file='file.EnKF_postprocess',status='replace')
- !KAL write(10,'(a)') 'analysis'//cmem
- !KAL close(10)
- !KAL
- !KAL
- !KAL
- !KAL ! ice processing Loop over restart file
- !KAL print *
- !KAL print *
- !KAL print *,'processing ice restart file'
- !KAL rstind=1 ! Restart index
- !KAL allok=.true.
- !KAL call system("cp ensemble_TMP_ICE.uf ensemble_TMP_ICE_final.uf")
- !KAL do ifld=1,numfields
- !KAL cfld= fieldnames (ifld)
- !KAL vlevel=fieldlevels(ifld)
- !KAL if (trim(cfld)=='icec' .or. trim(cfld)=='hice') then
- !KAL nomatch=.true.
- !KAL do iafile=1,nproc ! List of procs used in analysis
- !KAL write(cproc,'(i3.3)') iafile-1
- !KAL
- !KAL ! NB - time level=1
- !KAL ! NB2 - the files dumped in the analysis lack a header (last argument
- !KAL ! is false)
- !KAL call rst_index_from_header(trim(afile)//'.b',cfld,vlevel,1, &
- !KAL tmpindx,bmin,bmax,.false.)
- !KAL
- !KAL
- !KAL if (tmpindx/=-1) then
- !KAL print '(a8," -- layer:",i4," match : record, file",i4," ",a)', cfld, vlevel,tmpindx,trim(afile)
- !KAL nomatch=.false.
- !KAL exit
- !KAL end if
- !KAL
- !KAL ! Read field from analysed file
- !KAL call READRAW(fldr4,amin,amax,idm,jdm,.false.,spval,trim(afile)//'.a',tmpindx)
- !KAL fld=fldr4
- !KAL
- !KAL ! Sjekk p at vi har lest rett - samanlign max/min fr filene
- !KAL if (abs(amin-bmin).gt.abs(bmin)*1.e-4 .or. &
- !KAL abs(bmax-amax).gt.abs(bmax)*1.e-4 ) then
- !KAL print *,'Inconsistency between .a and .b files'
- !KAL print *,'.a : ',amin,amax
- !KAL print *,'.b : ',bmin,bmax
- !KAL print *,cfld,vlevel,tlevel
- !KAL call exit(1)
- !KAL end if
- !KAL
- !KAL end do
- !KAL
- !KAL
- !KAL ! Check if we got ice concentration or ice thickness
- !KAL if (.not.nomatch) then
- !KAL
- !KAL
- !KAL inquire(iolength=reclICE)ficem,hicem,hsnwm,ticem,tsrfm !,iceU,iceV
- !KAL open(10,file=trim(icetemplate),form='unformatted',access='direct',recl=reclICE,status='old')
- !KAL open(11,file='ensemble_TMP_ICE_final.uf',form='unformatted',access='direct',recl=reclICE,status='unknown')
- !KAL read(10,rec=imem,iostat=ios)ficem,hicem,hsnwm,ticem,tsrfm !,iceU,iceV
- !KAL if (trim(cfld)=='icec') ficem=fld
- !KAL if (trim(cfld)=='hice') hicem=fld
- !KAL write(11,rec=imem,iostat=ios2)ficem,hicem,hsnwm,ticem,tsrfm !,iceU,iceV
- !KAL close(10)
- !KAL close(11)
- !KAL
- !KAL if (ios/=0 .or.ios2/=0) then
- !KAL print *,ios
- !KAL print *,ios2
- !KAL print *,'Error when writing to ice ens file'
- !KAL call exit(1)
- !KAL end if
- !KAL end if
- !KAL end if
- !KAL end do
- !KAL
- !KAL
- !KAL print *,'Normal exit of EnKF_postprocess'
- !KAL print *,'TODO: Process dp inconsistencies'
- !KAL call exit(0)
- !KAL
- !KAL
- !KAL
- end program
|