!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE MINIMIZATION               ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Main driver for gradient check and minimization.
!
!-----------------------------------------------------------------------
!
!  AUTHOR:
!
!  Jidong Gao, CAPS, July, 2000
!
!-----------------------------------------------------------------------
!

SUBROUTINE minimization(nx,ny,nz,                                       & 1,33
           nvar,nvarradin,nvarrad,nzua,nzrdr,nzret,                     &
           mapfct,j1,j2,j3,aj3x,aj3y,aj3z,j3inv,rhostr,                 &
           mxsng,mxua,mxrad,mxcolrad,mxret,mxcolret,                    &
           nsrcsng,nsrcua,nsrcrad,nsrcret,ncat,                         &
           mxpass,ipass,iwstat,                                         &
           xs,ys,zs,x,y,z,zp,hterain,                                   &
           icatg,xcor,nam_var,                                          &
           xsng,ysng,hgtsng,thesng,                                     &
           odifsng,qobsng,qualsng,isrcsng,icatsng,nobsng,               &
           xua,yua,hgtua,theua,                                         &
           odifua,qobsua,qualua,isrcua,nlevsua,nobsua,                  &
           elvrad,xradc,yradc,                                          &
           distrad,uazmrad,vazmrad,hgtradc,theradc,dsdr,dhdr,           &
           odifrad,qobsrad,qualrad,                                     &
           irad,isrcrad,nlevrad,ncolrad,                                &
           xretc,yretc,hgtretc,theretc,                                 &
           odifret,qobsret,qualret,                                     &
           iret,isrcret,nlevret,ncolret,                                &
           srcsng,srcua,srcrad,srcret,                                  &
           ianxtyp,iusesng,iuseua,iuserad,iuseret,                      &
           xyrange,kpvrsq,wlim,zrange,zwlim,                            &
           thrng,rngsqi,knt,wgtsum,zsum,                                &
           corsng,corua,corrad,corret,                                  &
           oanxsng,oanxua,oanxrad,oanxret,                              &
           nz_tab,hqback,qback,                                         &
           nsngfil,nuafil,nradfil,nretfil,                              &
           anx,tem1,tem2,tem3,ibegin,iend,istatus)
!
!
!  INPUT:
!
!    nx         Number of grid points in the x-direction (east/west)
!    ny         Number of grid points in the y-direction (north/south)
!    nz         Number of grid points in the vertical
!    nvar       Number of analysis variables
!    nvarradin  Number of variables in the obsrad array
!    nvarrad    Number of variables in the odifrad array
!    nzua       Maximumnumber of levels in UA observations
!    nzrdr      Maximum number of levels in a radar column
!    nzret      Maximum number of levels in a retrieval column
!    mxsng      Maximum number of single level data
!    mxua       Maximum number of upper air observations
!    mxrad      Maximum number of radars
!    mxcolrad   Maximum number of radar columns
!    mxcolret   Maximum number of retrieval columns
!    mxpass     Maximum number of iterations
!    npass      Number of iterations
!    iwstat     Status indicator for writing statistics
!
!    xs         x location of scalar pts (m)
!    ys         y location of scalar pts (m)
!    zs         z location of scalar pts (m)
!
!    xsng       x location of single-level data
!    ysng       y location of single-level data
!    hgtsng     elevation of single-level data
!    thesng     theta (potential temperature) of single-level data
!
!    obsng      single-level observations
!    odifsng    difference between single-level obs and analysis
!    qobsng     normalized observation error
!    qualsng    single-level data quality indicator
!    isrcsng    index of single-level data source
!    nobsng     number of single-level observations
!
!    xua        x location of upper air data
!    yua        y location of upper air data
!    hgtua      elevation of upper air data
!    theua      theta (potential temperature) of upper air data
!
!    obsua      upper air observations
!    odifua     difference between upper air obs and analysis
!    qobsua     normalized observation error
!    qualua     upper air data quality indicator
!    isrcua     index of upper air data source
!    nlevsua    number of levels of data for each upper air location
!    nobsua     number of upper air observations
!
!    anx        Analyzed variables (or first guess)
!    qback      Background (first guess) error
!
!    nradfil    number of radar files
!    fradname   file name for radar dataset
!    srcrad     name of radar sources
!
!    latrad   latitude of radar  (degrees N)
!    lonrad   longitude of radar (degrees E)
!    elvrad   elevation of feed horn of radar (m MSL)
!    xradc    x location of radar column
!    yradc    y location of radar column
!    irad     radar number
!    nlevrad  number of levels of radar data in each column
!    distrad  distance of radar column from source radar
!    uazmrad  u-component of radar beam for each column
!    vazmrad  v-component of radar beam for each column
!    hgtradc  height (m MSL) of radar observations
!    obsrad   radar observations
!    oanxrad  analysis (first guess) value at radar data location
!    odifrad  difference between radar observation and analysis
!    qobsrad  normalized observation error
!    qualrad  radar data quality indicator
!    ncolrad  number of radar columns read-in
!    istatus  status indicator
!
!    latret   latitude of retrieval radar  (degrees N)
!    lonret   longitude of retrieval radar (degrees E)
!    xretc    x location of retrieval column
!    yretc    y location of retrieval column
!    iret     retrieval number
!    nlevret  number of levels of retrieval data in each column
!    hgtretc  height (m MSL) of retrieval observations
!    obsret   retrieval observations
!    odifret  difference between retrieval observation and analysis
!    qobsret  normalized observation error
!    qualret  retrieval data quality indicator
!    ncolret  number of retr columns read-in
!    istatus  status indicator
!
!-----------------------------------------------------------------------
!
!  Variable Declarations:
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE

  INCLUDE 'grid.inc'
  INCLUDE 'varpara.inc'

  INCLUDE '3dvarcputime.inc'

!-----------------------------------------------------------------------
!
!  Input Sizing Arguments
!
!-----------------------------------------------------------------------
!
  INTEGER :: nx,ny,nz
  INTEGER :: nvar,nvarradin,nvarrad
  INTEGER :: nzua,nzrdr,nzret
  INTEGER :: mxsng,mxua,mxrad,mxcolrad,mxret,mxcolret
  INTEGER :: nsrcsng,nsrcua,nsrcrad,nsrcret,ncat
  INTEGER :: mxpass,ipass
  INTEGER :: nsngfil,nuafil,nradfil,nretfil
!
!-----------------------------------------------------------------------
!
!  Input Grid Arguments
!
!-----------------------------------------------------------------------
!
  REAL :: x     (nx)           ! The x-coord. of the physical and
                               ! computational grid. Defined at u-point.
  REAL :: y     (ny)           ! The y-coord. of the physical and
                               ! computational grid. Defined at v-point.
  REAL :: z     (nz)           ! The z-coord. of the computational grid.
                               ! Defined at w-point on the staggered grid.
  REAL :: zp    (nx,ny,nz)     ! The physical height coordinate defined at
                               ! w-point of the staggered grid.
  REAL :: hterain(nx,ny)       ! The height of the terrain.

  REAL :: mapfct(nx,ny,8)      ! Map factors at scalar, u and v points

  REAL :: j1    (nx,ny,nz)     ! Coordinate transformation Jacobian
                               ! defined as - d( zp )/d( x ).
  REAL :: j2    (nx,ny,nz)     ! Coordinate transformation Jacobian
                               ! defined as - d( zp )/d( y ).
  REAL :: j3    (nx,ny,nz)     ! Coordinate transformation Jacobian
                               ! defined as d( zp )/d( z ).
  REAL :: aj3x  (nx,ny,nz)     ! Coordinate transformation Jacobian defined
                               ! as d( zp )/d( z ) AVERAGED IN THE X-DIR.
  REAL :: aj3y  (nx,ny,nz)     ! Coordinate transformation Jacobian defined
                               ! as d( zp )/d( z ) AVERAGED IN THE Y-DIR.
  REAL :: aj3z  (nx,ny,nz)     ! Coordinate transformation Jacobian defined
                               ! as d( zp )/d( z ) AVERAGED IN THE Z-DIR.
  REAL :: j3inv (nx,ny,nz)     ! Inverse of j3
  REAL :: rhostr(nx,ny,nz)     ! Base state density rhobar times j3
!
  REAL :: xs(nx)
  REAL :: ys(ny)
  REAL :: zs(nx,ny,nz)
!
  INTEGER :: icatg(nx,ny)
  REAL :: xcor(ncat,ncat)
!
!-----------------------------------------------------------------------
!
!  Input Observation Arguments
!
!-----------------------------------------------------------------------
!
  CHARACTER (LEN=6) :: nam_var(nvar)
  REAL :: xsng(mxsng)
  REAL :: ysng(mxsng)
  REAL, DIMENSION(:), allocatable:: xsng_p, ysng_p 
  REAL, DIMENSION(:), allocatable:: zsng_1, zsng_2 
  INTEGER, DIMENSION(:), allocatable:: ihgtsng
  REAL :: hgtsng(mxsng)
  REAL :: thesng(mxsng)
  REAL :: obsng(nvar,mxsng)
  REAL :: odifsng(nvar,mxsng)
  REAL :: qobsng(nvar,mxsng)
  INTEGER :: qualsng(nvar,mxsng)
  INTEGER :: isrcsng(mxsng)
  INTEGER :: icatsng(mxsng)
  INTEGER :: nobsng
!
  REAL :: xua(mxua)
  REAL :: yua(mxua)
  REAL, DIMENSION(:), allocatable:: xua_p, yua_p 
  REAL, DIMENSION(:,:), allocatable:: zua_1, zua_2 
  INTEGER, DIMENSION(:,:), allocatable:: ihgtua
  REAL :: hgtua(nzua,mxua)
  REAL :: theua(nzua,mxua)
  REAL :: obsua(nvar,nzua,mxua)
  REAL :: odifua(nvar,nzua,mxua)
  REAL :: qobsua(nvar,nzua,mxua)
  INTEGER :: qualua(nvar,nzua,mxua)
  INTEGER :: nlevsua(mxua)
  INTEGER :: isrcua(mxua)
  INTEGER :: nobsua
!
  REAL :: elvrad(mxrad)
  REAL :: xradc(mxcolrad)
  REAL :: yradc(mxcolrad)
  REAL, DIMENSION(:), allocatable:: xradc_p, yradc_p 
  REAL, DIMENSION(:,:), allocatable:: zradc_1, zradc_2 
  INTEGER, DIMENSION(:,:), allocatable:: ihgtradc
  REAL :: distrad(mxcolrad)
  REAL :: uazmrad(mxcolrad)
  REAL :: vazmrad(mxcolrad)
  REAL :: hgtradc(nzrdr,mxcolrad)
  REAL :: theradc(nzrdr,mxcolrad)
  REAL :: dsdr(nzrdr,mxcolrad)
  REAL :: dhdr(nzrdr,mxcolrad)
  REAL :: obsrad(nvarradin,nzrdr,mxcolrad)
  REAL :: odifrad(nvarrad,nzrdr,mxcolrad)
  REAL :: qobsrad(nvarrad,nzrdr,mxcolrad)
  INTEGER :: qualrad(nvarrad,nzrdr,mxcolrad)
  INTEGER :: nlevrad(mxcolrad)
  INTEGER :: irad(mxcolrad)
  INTEGER :: isrcrad(0:mxrad)
  INTEGER :: ncolrad
!
  REAL :: xretc(mxcolret)
  REAL :: yretc(mxcolret)
  REAL :: hgtretc(nzret,mxcolret)
  REAL :: theretc(nzret,mxcolret)
  REAL :: obsret(nvar,nzret,mxcolret)
  REAL :: odifret(nvar,nzret,mxcolret)
  REAL :: qobsret(nvar,nzret,mxcolret)
  INTEGER :: qualret(nvar,nzret,mxcolret)
  INTEGER :: nlevret(mxcolret)
  INTEGER :: iret(mxcolret)
  INTEGER :: isrcret(0:mxret)
  INTEGER :: ncolret
!
!-----------------------------------------------------------------------
!
!  Input Analysis Control Variables
!
!-----------------------------------------------------------------------
!
  CHARACTER (LEN=8) :: srcsng(nsrcsng)
  CHARACTER (LEN=8) :: srcua (nsrcua )
  CHARACTER (LEN=8) :: srcrad(nsrcrad)
  CHARACTER (LEN=8) :: srcret(nsrcret)

  INTEGER :: ianxtyp(mxpass)
  INTEGER :: iusesng(0:nsrcsng,mxpass)
  INTEGER :: iuseua(0:nsrcua,mxpass)
  INTEGER :: iuserad(0:nsrcrad,mxpass)
  INTEGER :: iuseret(0:nsrcret,mxpass)

  REAL :: xyrange(mxpass)
  REAL :: kpvrsq(nvar)
  REAL :: wlim
  REAL :: zrange(mxpass)
  REAL :: zwlim
  REAL :: thrng(mxpass)
  INTEGER :: iwstat
!
!-----------------------------------------------------------------------
!
!  Scratch Space
!
!-----------------------------------------------------------------------
!
  REAL :: rngsqi(nvar)
  INTEGER :: knt(nvar,nz)
  REAL :: wgtsum(nvar,nz)
  REAL :: zsum(nvar,nz)
!
!-----------------------------------------------------------------------
!
!  Output Variables at Observation Locations
!
!-----------------------------------------------------------------------
!
  REAL :: corsng(mxsng,nvar)
  REAL :: corua(nzua,mxua,nvar)
  REAL :: corrad(nzrdr,mxcolrad,nvarrad)
  REAL :: corret(nzret,mxcolret,nvar)
!
  REAL :: oanxsng(nvar,mxsng)
  REAL :: oanxua(nvar,nzua,mxua)
  REAL :: oanxrad(nvarrad,nzrdr,mxcolrad)
  REAL :: oanxret(nvar,nzret,mxcolret)
!
  INTEGER :: nz_tab
  REAL :: hqback(nz_tab)
  REAL :: qback(nvar,nz_tab)
!
  REAL,DIMENSION(nz_tab) :: qback_wk
  REAL,DIMENSION(nz_tab) :: hqback_wk
!
!-----------------------------------------------------------------------
!
!  Output Grid
!
!-----------------------------------------------------------------------
!
  REAL :: anx(nx,ny,nz,nvar)
!
!
!
!-----------------------------------------------------------------------
!
!  variable declarations for varirational analysis: by gao
!
!-----------------------------------------------------------------------
!
!
  INTEGER :: numctr
!
  INTEGER :: ndim,mgra,nxm,nwork
!
  REAL :: cfun,eps,gtol,ftol
  REAL :: cfun_single(nvar+1),cfun_total
  INTEGER :: mp,lp,iprint(2),iflag,point
  LOGICAL :: diagco
  COMMON /va15dd/mp,lp, gtol
!
  INTEGER :: icall
!
  REAL, DIMENSION(:), allocatable:: ctrv,grad,xgus
  REAL, DIMENSION(:), allocatable:: swork,ywork,diag,work
!
!
  REAL :: cfun1,rchek,gxnn
  REAL,DIMENSION(:), allocatable:: fa, fr
  REAL,DIMENSION(:,:,:), allocatable:: gdscal
  REAL,DIMENSION(:,:,:), allocatable:: gdu_err,gdv_err,                 &
                       gdp_err,gdt_err,gdq_err,gdw_err
  REAL,DIMENSION (:,:,:), allocatable ::                                &
                   u_ctr,v_ctr,p_ctr,t_ctr,q_ctr,w_ctr,psi,phi
  REAL,DIMENSION (:,:,:), allocatable ::                                &
                   rhostru, rhostrv,rhostrw,div3
!
!
!-----------------------------------------------------------------------
!
!  end of variable declarations for variational anaylsis:
!
!-----------------------------------------------------------------------
!
!
!-----------------------------------------------------------------------
!
!  Work arrays
!
!-----------------------------------------------------------------------
!
  REAL :: tem1(nx,ny,nz)
  REAL :: tem2(nx,ny,nz)
  REAL :: tem3(nx,ny,nz)
  INTEGER :: ibegin(ny)
  INTEGER :: iend(ny)
!
!-----------------------------------------------------------------------
!
!  Return status
!
!-----------------------------------------------------------------------
!
  INTEGER :: istatus,ierr
!
!-----------------------------------------------------------------------
!
!  Misc.local variables
!
!-----------------------------------------------------------------------
!
  REAL :: ftabinv,setexp
  INTEGER :: i,j,k,isrc,sngsw,uasw,radsw,retsw
  INTEGER :: num, numsingle
  REAL :: rpass,zrngsq,thrngsq
  REAL :: sum1,sum2,sum3,sum4,sum5,sum6
  REAL :: f_cputime
  REAL :: cpuin,cpuout
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!    sum1=0
!  do i = 1, nobsng
!    sum1=sum1+odifsng(3,i)**2
!  end do
!    print*,'sum1_odifsng==',sum1
!
!
!  allocate control variable array
!  -------------------------------------------------------
!
  numctr=6*nx*ny*nz
  numsingle=nx*ny*nz
  
 
  if( allocated(xgus) ) deallocate (xgus)
  allocate ( xgus(numctr), stat=ierr )

  if( allocated(ctrv) ) deallocate (ctrv)
  allocate ( ctrv(numctr) )

  if( allocated(grad) ) deallocate (grad)
  allocate ( grad(numctr) )

  if( allocated(gdu_err) ) deallocate (gdu_err)
  allocate ( gdu_err(nx,ny,nz) )

  if( allocated(gdv_err) ) deallocate (gdv_err)
  allocate ( gdv_err(nx,ny,nz) )

  if( allocated(gdp_err) ) deallocate (gdp_err)
  allocate ( gdp_err(nx,ny,nz) )

  if( allocated(gdt_err) ) deallocate (gdt_err)
  allocate ( gdt_err(nx,ny,nz) )

  if( allocated(gdq_err) ) deallocate (gdq_err)
  allocate ( gdq_err(nx,ny,nz) )

  if( allocated(gdw_err) ) deallocate (gdw_err)
  allocate ( gdw_err(nx,ny,nz) )
 
!------------------------------------------------------------------------
 
  if( allocated(  u_ctr) ) deallocate (  u_ctr)
  allocate (   u_ctr(nx,ny,nz) )

  if( allocated(  v_ctr) ) deallocate (  v_ctr)
  allocate (   v_ctr(nx,ny,nz) )

  if( allocated(    psi) ) deallocate (    psi)
  allocate (     psi(nx,ny,nz) )

  if( allocated(    phi) ) deallocate (    phi)
  allocate (     phi(nx,ny,nz) )

  if( allocated(  p_ctr) ) deallocate (  p_ctr)
  allocate (   p_ctr(nx,ny,nz) )

  if( allocated(  t_ctr) ) deallocate (  t_ctr)
  allocate (   t_ctr(nx,ny,nz) )

  if( allocated(  q_ctr) ) deallocate (  q_ctr)
  allocate (   q_ctr(nx,ny,nz) )

  if( allocated(  w_ctr) ) deallocate (  w_ctr)
  allocate (   w_ctr(nx,ny,nz) )

!-----------------------------------------------------------------------

  if( allocated(gdscal) ) deallocate (gdscal)
  allocate ( gdscal(nx,ny,nz) )

  if( allocated(rhostru) ) deallocate (rhostru)
  allocate ( rhostru(nx,ny,nz) )

  if( allocated(rhostrv) ) deallocate (rhostrv)
  allocate ( rhostrv(nx,ny,nz) )

  if( allocated(rhostrw) ) deallocate (rhostrw)
  allocate ( rhostrw(nx,ny,nz) )

  if( allocated(div3   ) ) deallocate (div3   )
  allocate ( div3   (nx,ny,nz) )
!
  CALL rhouvw(nx,ny,nz,rhostr,rhostru,rhostrv,rhostrw)

!
!    PRINT*,'qbackin=',(qback(1,i),i=1,nz_tab)
!
   DO k = 1,nz
     DO j = 1,ny
       DO i = 1,nx
         gdw_err(i,j,k) = 3.0
       end do
     end do
   end do
 
   num = 0
   DO isrc = 1, nz_tab
      if( qback(1,isrc) > -900.0) then
      num = num+1
      qback_wk(num) =  qback(1,isrc)
     hqback_wk(num) = hqback(isrc)
      end if
   END DO

   DO k = 1,nz
    DO j = 1,ny
     DO i = 1,nx
       CALL linear(num,hqback_wk,qback_wk,zs(i,j,k),gdu_err(i,j,k) )
     END DO
    END DO
   END DO
!
!
   num = 0
   DO isrc = 1, nz_tab
      if( qback(2,isrc) > -900.0) then
      num = num+1
      qback_wk(num) =  qback(2,isrc)
     hqback_wk(num) = hqback(isrc)
      end if
   END DO

   DO k = 1,nz
    DO j = 1,ny
     DO i = 1,nx
       CALL linear(num,hqback_wk,qback_wk,zs(i,j,k),gdv_err(i,j,k) )
     END DO
    END DO
   END DO
!
!
   num = 0
   DO isrc = 1, nz_tab
      if( qback(3,isrc) > -900.0) then
      num = num+1
      qback_wk(num) =  qback(3,isrc)
     hqback_wk(num) = hqback(isrc)
      end if
   END DO

   DO k = 1,nz
    DO j = 1,ny
     DO i = 1,nx
       CALL linear(num,hqback_wk,qback_wk,zs(i,j,k),gdp_err(i,j,k) )
     END DO
    END DO
   END DO
!
!
   num = 0
   DO isrc = 1, nz_tab
      if( qback(4,isrc) > -900.0) then
      num = num+1
      qback_wk(num) =  qback(4,isrc)
     hqback_wk(num) = hqback(isrc)
      end if
   END DO

   DO k = 1,nz
    DO j = 1,ny
     DO i = 1,nx
       CALL linear(num,hqback_wk,qback_wk,zs(i,j,k),gdt_err(i,j,k) )
     END DO
    END DO
   END DO

!
   num = 0
   DO isrc = 1, nz_tab
      if( qback(5,isrc) > -900.0) then
      num = num+1
      qback_wk(num) =  qback(5,isrc)
     hqback_wk(num) = hqback(isrc)
      end if
   END DO

   DO k = 1,nz
    DO j = 1,ny
     DO i = 1,nx
       CALL linear(num,hqback_wk,qback_wk,zs(i,j,k),gdq_err(i,j,k) )
     END DO
    END DO
   END DO
!
!
!  num = 0
!  DO isrc = 1, nz_tab
!     if( qback(1,isrc) > -900.0) then
!     num = num+1
!     qback_wk(num) =  qback(1,isrc)
!    hqback_wk(num) = hqback(isrc)
!     end if
!  END DO
!
!  DO k = 1,nz
!   DO j = 1,ny
!    DO i = 1,nx
!      call linear(num,hqback_wk,qback_wk,zs(i,j,k),gdw_err(i,j,k))
!    END DO
!   END DO
!  END DO
!
!
!----------------if ( cntl_var==0) u & v as control variable-------------
!
    IF(cntl_var == 0) THEN

   DO k = 1,nz
    DO j = 1,ny
     DO i = 1,nx
        gdu_err(i,j,k) = SQRT( gdu_err(i,j,k) )
        gdv_err(i,j,k) = SQRT( gdv_err(i,j,k) )
        gdp_err(i,j,k) = SQRT( gdp_err(i,j,k) )
        gdt_err(i,j,k) = SQRT( gdt_err(i,j,k) )
        gdq_err(i,j,k) = SQRT( gdq_err(i,j,k) )
        gdw_err(i,j,k) = sqrt( gdw_err(i,j,k) )
        IF( 2 == 1 ) THEN
          gdu_err(i,j,k) = 1.0
          gdv_err(i,j,k) = 1.0
          gdp_err(i,j,k) = 1.0
          gdt_err(i,j,k) = 1.0
          gdq_err(i,j,k) = 1.0
          gdw_err(i,j,k) = 1.0
        ENDIF
      END DO 
    END DO
  END DO

    ELSE 
!
   DO k = 1,nz
    DO j = 1,ny
     DO i = 1,nx
        gdu_err(i,j,k) = SQRT( gdu_err(i,j,k) )*(dx+dy)/2.
        gdv_err(i,j,k) = SQRT( gdv_err(i,j,k) )*(dx+dy)/2.
        gdp_err(i,j,k) = SQRT( gdp_err(i,j,k) )
        gdt_err(i,j,k) = SQRT( gdt_err(i,j,k) )
        gdq_err(i,j,k) = SQRT( gdq_err(i,j,k) )
        gdw_err(i,j,k) = sqrt( gdw_err(i,j,k) )
      END DO
    END DO
  END DO
!
    END IF
!
  DO i=1,numctr
    ctrv(i)=0.0
    xgus(i)=0.0
    grad(i)=0.0
  END DO
!
  IF( nsngfil == 0 ) THEN
    sngsw = 0
  ELSE
    sngsw = 1
  END IF

  IF( nuafil == 0 ) THEN
    uasw = 0
  ELSE
    uasw = 1 
  ENDIF

  IF( nradfil == 0 ) THEN
     radsw = 0
  ELSE
     radsw = 1
  END IF
 
  IF( nretfil == 0 ) THEN 
    retsw = 0
  ELSE
    retsw = 1
  END IF
!
!  caculating some parameters for interpolation ! added by Jidong Gao
!
  do i = 1, nobsng
    icatsng(i) = 1
  end do

  if( allocated(    xsng_p) ) deallocate (    xsng_p)
  allocate (     xsng_p(mxsng) )

  if( allocated(    ysng_p) ) deallocate (    ysng_p)
  allocate (     ysng_p(mxsng) )

  if( allocated(    zsng_1) ) deallocate (    zsng_1)
  allocate (     zsng_1(mxsng) )

  if( allocated(    zsng_2) ) deallocate (    zsng_2)
  allocate (     zsng_2(mxsng) )

  if( allocated(    ihgtsng) ) deallocate (   ihgtsng)
  allocate (    ihgtsng(mxsng) )

  call map_to_mod2(nx,ny,mxsng,nobsng,xs,ys,xsng,ysng,xsng_p,ysng_p)
  call map_to_modz(1, mxsng, icatsng, nobsng,nx,ny,nz,zs,         &
                  xsng_p,ysng_p,hgtsng,ihgtsng,zsng_1,zsng_2)
!do i=1,nobsng
!  print*,'xsng==',xsng_p(i),ysng_p(i) 
!end do
!do i=1,nobsng
!  print*,'hgtsng==',zsng_1(i),hgtsng(i),zsng_2(i),ihgtsng(i) 
!end do
!stop
!
  if( allocated(    xua_p) ) deallocate (    xua_p)
  allocate (     xua_p(mxua) )

  if( allocated(    yua_p) ) deallocate (    yua_p)
  allocate (     yua_p(mxua) )

  if( allocated(    zua_1) ) deallocate (    zua_1)
  allocate (     zua_1(nzua,mxua) )

  if( allocated(    zua_2) ) deallocate (    zua_2)
  allocate (     zua_2(nzua,mxua) )

  if( allocated(    ihgtua) ) deallocate (   ihgtua)
  allocate (    ihgtua(nzua,mxua) )

  call map_to_mod2(nx,ny,mxua,nobsua,xs,ys,xua,yua,xua_p,yua_p)
  call map_to_modz(nzua, mxua, nlevsua, nobsua, nx,ny,nz,zs,      &
                   xua_p,yua_p, hgtua, ihgtua,zua_1,zua_2)
!do i=1,nobsua
!  print*,'xua==',xua_p(i),yua_p(i) 
!end do
!do i=1,nobsua
! do j = 1, nlevsua(i)
!  print*,'hgtua=',zua_1(j,i),hgtua(j,i),zua_2(j,i),ihgtua(j,i) 
!end do
!end do
!stop
!

  if( allocated(    xradc_p) ) deallocate (    xradc_p)
  allocate (     xradc_p(mxcolrad) )

  if( allocated(    yradc_p) ) deallocate (    yradc_p)
  allocate (     yradc_p(mxcolrad) )

  if( allocated(    zradc_1) ) deallocate (    zradc_1)
  allocate (     zradc_1(nzrdr,mxcolrad) )

  if( allocated(    zradc_2) ) deallocate (    zradc_2)
  allocate (     zradc_2(nzrdr,mxcolrad) )

  if( allocated(    ihgtradc) ) deallocate (   ihgtradc)
  allocate (    ihgtradc(nzrdr,mxcolrad) )

  call map_to_mod2(nx,ny,mxcolrad,ncolrad,xs,ys,xradc,yradc,      &
                                         xradc_p,yradc_p)
  call map_to_modz(nzrdr, mxcolrad, nlevrad, ncolrad,nx,ny,nz,    &
      zs,xradc_p,yradc_p,hgtradc,ihgtradc,zradc_1,zradc_2)
!
!do i=1,ncolrad
!  print*,'xradc==',xradc_p(i),yradc_p(i) 
!end do
!  print*,'ncolrad===',ncolrad
!do i=1,ncolrad
! do j = 1, nlevrad(i)
!  print*,'hgtrad=',i,j,zradc_1(j,i),hgtradc(j,i),zradc_2(j,i),ihgtradc(j,i) 
!end do
!end do
!stop
!
!
!
!
!  end of caculating some parameters for interpolation ! added by Jidong
!
! print*,'maxin=',maxin   
! print*,'ipass_filt=',ipass_filt
! print*,' hradius=', hradius
! print*,'nradius_z=',nradius_z
! print*,'turn_chk=',turn_chk
! print*,'turn_3dda=',turn_3dda
! print*,'sngsw=',sngsw
! print*,'uasw=',uasw
! print*,'radsw=',radsw
! print*,'retsw=',retsw
! print*,'turn_div=',turn_div
! print*,'wei_div=',wei_div
! stop
!
  IF(turn_chk == 1) THEN
    ipass = 1
!
    CALL scale_factor(nx,ny,nz,gdscal,ipass_filt(1),hradius(1),nradius_z(1))

    rchek=1E-1
    allocate (fa(20))
    allocate (fr(20))
!
    PRINT*,'numctr====',numctr
!
!-----------------------------------------------------------------------
!
!      OBTAIN THE COST FUNCTION AND THE GRADIENT.
!
!-----------------------------------------------------------------------
!
    CALL costf(numctr,ctrv,cfun_single,                                 &
          gdu_err,gdv_err,gdp_err,gdt_err,gdq_err,gdw_err,              &
           u_ctr,v_ctr,p_ctr,t_ctr,q_ctr,w_ctr, psi, phi,               &
          gdscal,                                                       &
          nx,ny,nz,                                                     &
          nvar,nvarradin,nvarrad,nzua,nzrdr,nzret,                      &
          mapfct,j1,j2,j3,aj3x,aj3y,aj3z,j3inv,rhostr,                  &
          rhostru, rhostrv, rhostrw, div3,                              &
          mxsng,mxua,mxrad,mxcolrad,mxret,mxcolret,                     &
          nsrcsng,nsrcua,nsrcrad,nsrcret,ncat,                          &
          mxpass,ipass,iwstat,xs,ys,zs,x,y,z,zp,hterain,                &
          icatg,xcor,nam_var,xsng,ysng,hgtsng,thesng,                   &
          obsng,odifsng,qobsng,qualsng,isrcsng,icatsng,nobsng,          &
          xua,yua,hgtua,theua,                                          &
          obsua,odifua,qobsua,qualua,isrcua,nlevsua,nobsua,             &
          elvrad,xradc,yradc,                                           &
          distrad,uazmrad,vazmrad,hgtradc,theradc,dsdr,dhdr,            &
          obsrad,odifrad,qobsrad,qualrad,                               &
          irad,isrcrad,nlevrad,ncolrad,                                 &
          xretc,yretc,hgtretc,theretc,                                  &
          obsret,odifret,qobsret,qualret,                               &
          iret,isrcret,nlevret,ncolret,                                 &
          srcsng,srcua,srcrad,srcret,                                   &
!          ianxtyp,iusesng,iuseua,iuserad,iuseret,                        &
            ianxtyp,iusesng(0,ipass),iuseua(0,ipass),                   &
            iuserad(0,ipass),iuseret(0,ipass),                          &
          xyrange,kpvrsq,wlim,zrange,zwlim,                             &
          thrng,rngsqi,knt,wgtsum,zsum,                                 &
          corsng,corua,corrad,corret,                               &
          xsng_p,ysng_p,ihgtsng,xua_p,yua_p,ihgtua,                     &
          xradc_p,yradc_p,ihgtradc,zsng_1,zsng_2,                       &
          zua_1,zua_2,zradc_1,zradc_2,                                  &
          oanxsng,oanxua,oanxrad,oanxret,                               &
          sngsw,uasw,radsw,retsw,                                       &
          ipass_filt(ipass),hradius(ipass),nradius_z(ipass),            &
          turn_div,cntl_var,wei_div_h(ipass),wei_div_v(ipass),          &
          anx,tem1,tem2,tem3,ibegin,iend,istatus)
!
    cfun_total=0
    DO i=1,nvar+1
      cfun_total=cfun_total+cfun_single(i)
    ENDDO
    cfun=cfun_total
    PRINT*,'cfun====',cfun
!
!  do i = 1, ncolrad
!    if(iuserad(isrcrad(irad(i))).GT.0) THEN
!
!    do k=1,nlevrad(i)
!
!      print*,'obsrad in minim_drive==',k,i,obsrad(5,k,i)
!    end do
!    end if
!  end do
!    stop
!
    CALL gradt(numctr,ctrv,grad,                                        &
          gdu_err,gdv_err,gdp_err,gdt_err,gdq_err,gdw_err,              &
           u_ctr,v_ctr,p_ctr,t_ctr,q_ctr,w_ctr, psi, phi,               &
          gdscal,                                                       &
          nx,ny,nz,                                                     &
          nvar,nvarradin,nvarrad,nzua,nzrdr,nzret,                      &
          mapfct,j1,j2,j3,aj3x,aj3y,aj3z,j3inv,rhostr,                  &
          rhostru, rhostrv, rhostrw, div3,                              &
          mxsng,mxua,mxrad,mxcolrad,mxret,mxcolret,                     &
          nsrcsng,nsrcua,nsrcrad,nsrcret,ncat,                          &
          mxpass,ipass,iwstat,xs,ys,zs,x,y,z,zp,hterain,                &
          icatg,xcor,nam_var,xsng,ysng,hgtsng,thesng,                   &
          obsng,odifsng,qobsng,qualsng,isrcsng,icatsng,nobsng,          &
          xua,yua,hgtua,theua,                                          &
          obsua,odifua,qobsua,qualua,isrcua,nlevsua,nobsua,             &
          elvrad,xradc,yradc,                                           &
          distrad,uazmrad,vazmrad,hgtradc,theradc,dsdr,dhdr,            &
          obsrad,odifrad,qobsrad,qualrad,                               &
          irad,isrcrad,nlevrad,ncolrad,                                 &
          xretc,yretc,hgtretc,theretc,                                  &
          obsret,odifret,qobsret,qualret,                               &
          iret,isrcret,nlevret,ncolret,                                 &
          srcsng,srcua,srcrad,srcret,                                   &
!          ianxtyp,iusesng,iuseua,iuserad,iuseret,                       &
            ianxtyp,iusesng(0,ipass),iuseua(0,ipass),                   &
            iuserad(0,ipass),iuseret(0,ipass),                          &
          xyrange,kpvrsq,wlim,zrange,zwlim,                             &
          thrng,rngsqi,knt,wgtsum,zsum,                                 &
          corsng,corua,corrad,corret,                                 &
          xsng_p,ysng_p,ihgtsng,xua_p,yua_p,ihgtua,                     &
          xradc_p,yradc_p,ihgtradc,zsng_1,zsng_2,                       &
          zua_1,zua_2,zradc_1,zradc_2,                                  &
          oanxsng,oanxua,oanxrad,oanxret,                               &
          sngsw,uasw,radsw,retsw,                                       &
          ipass_filt(ipass),hradius(ipass),nradius_z(ipass),            &
          turn_div,cntl_var,wei_div_h(ipass),wei_div_v(ipass),          &
          anx,tem1,tem2,tem3,ibegin,iend,istatus)
!
    gxnn=0.
    DO i=1,numctr
      gxnn=gxnn+grad(i)*grad(i)
    END DO
    PRINT*,'gxnn====',gxnn
!  stop
!
    DO j=1,20
      rchek=rchek*1E-1
      DO i=1,numctr
        xgus(i)=ctrv(i)+rchek*grad(i)
      END DO
!
!-----------------------------------------------------------------------
!
!      OBTAIN THE COST FUNCTION AND THE GRADIENT.
!
!-----------------------------------------------------------------------
!
!
      CALL costf(numctr,xgus,cfun_single,                               &
            gdu_err,gdv_err,gdp_err,gdt_err,gdq_err,gdw_err,            &
           u_ctr,v_ctr,p_ctr,t_ctr,q_ctr,w_ctr, psi, phi,               &
            gdscal,                                                     &
            nx,ny,nz,                                                   &
            nvar,nvarradin,nvarrad,nzua,nzrdr,nzret,                    &
            mapfct,j1,j2,j3,aj3x,aj3y,aj3z,j3inv,rhostr,                &
            rhostru, rhostrv, rhostrw, div3,                            &
            mxsng,mxua,mxrad,mxcolrad,mxret,mxcolret,                   &
            nsrcsng,nsrcua,nsrcrad,nsrcret,ncat,                        &
            mxpass,ipass,iwstat,xs,ys,zs,x,y,z,zp,hterain,              &
            icatg,xcor,nam_var,xsng,ysng,hgtsng,thesng,                 &
            obsng,odifsng,qobsng,qualsng,isrcsng,icatsng,nobsng,        &
            xua,yua,hgtua,theua,                                        &
            obsua,odifua,qobsua,qualua,isrcua,nlevsua,nobsua,           &
            elvrad,xradc,yradc,                                         &
            distrad,uazmrad,vazmrad,hgtradc,theradc,dsdr,dhdr,          &
            obsrad,odifrad,qobsrad,qualrad,                             &
            irad,isrcrad,nlevrad,ncolrad,                               &
            xretc,yretc,hgtretc,theretc,                                &
            obsret,odifret,qobsret,qualret,                             &
            iret,isrcret,nlevret,ncolret,                               &
            srcsng,srcua,srcrad,srcret,                                 &
            ianxtyp,iusesng(0,ipass),iuseua(0,ipass),                   &
            iuserad(0,ipass),iuseret(0,ipass),                          &
            xyrange,kpvrsq,wlim,zrange,zwlim,                           &
            thrng,rngsqi,knt,wgtsum,zsum,                               &
            corsng,corua,corrad,corret,                               &
          xsng_p,ysng_p,ihgtsng,xua_p,yua_p,ihgtua,                     &
          xradc_p,yradc_p,ihgtradc,zsng_1,zsng_2,                       &
          zua_1,zua_2,zradc_1,zradc_2,                                  &
            oanxsng,oanxua,oanxrad,oanxret,                             &
            sngsw,uasw,radsw,retsw,                                     &
            ipass_filt(ipass),hradius(ipass),nradius_z(ipass),          &
            turn_div,cntl_var,wei_div_h(ipass),wei_div_v(ipass),        &
            anx,tem1,tem2,tem3,ibegin,iend,istatus)
!
!
         cfun_total=0
         DO i=1,nvar+1
           cfun_total=cfun_total+cfun_single(i)
         ENDDO
         cfun1=cfun_total
!
         PRINT*,'cfun1====',cfun1,cfun1-cfun
!    stop
!
      fa(j)=rchek
      fr(j)=(cfun1-cfun)/(gxnn*rchek)
    END DO
!
    OPEN(12,FILE='grad.chk',STATUS='unknown')
!
    DO j=1,16
      WRITE(*,*) '  Rchek=',fa(j),'  fr==',fr(j)
      WRITE(12,*) fa(j),fr(j)-1.0
    END DO
!
    CLOSE(12)
!
    deallocate (fa)
    deallocate (fr)
    STOP
!
  END IF
!
  IF(turn_3dda == 1) THEN
!
!-----------------------------------------------------------------------
!
!  Data assimilation begins here.
!  include file  in data assimilation
!
!-----------------------------------------------------------------------
!
!
    mgra=2
    ndim=numctr
    nxm=ndim*mgra
    nwork=ndim+2*mgra
    allocate ( swork(nxm)   )
    allocate ( ywork(nxm)   )
    allocate (  diag(ndim)  )
    allocate (  work(nwork) )
!
!
    DO i=1,numctr
      ctrv(i)=0.0        
    END DO
!
!-----------------------------------------------------------------------
!
!  Loop through ipass analysis iterations
!
!-----------------------------------------------------------------------
!
!  DO ipass=1,npass
    icall = 0
    eps = 1.0E-12
    ftol=1.0E-4
    iprint = 0
    iflag = 0 
    diagco = .false.
    grad = 0.0
!
!-----------------------------------------------------------------------
 
  CALL scale_factor(nx,ny,nz,gdscal,ipass_filt(ipass),                       &
                      hradius(ipass),nradius_z(ipass))

!-----------------------------------------------------------------------
!
!-----------------------------------------------------------------------
!
!  Set single-level usage switch based in iusesng
!
!-----------------------------------------------------------------------
!
    WRITE(6,'(/a,i4)') ' Source usage switches for pass ',ipass
    WRITE(6,'(/a,i4)') '   Single level data'
    sngsw=0
!
  IF( nsngfil /= 0 ) THEN
    DO isrc=1,nsrcsng
        IF(iusesng(isrc,ipass) > 0) THEN
        sngsw=1
        WRITE(6,'(a,a)') '        Using          ',srcsng(isrc)
        END IF
    END DO
  END IF
    IF(sngsw == 0) WRITE(6,'(a)') '         none'
!
!-----------------------------------------------------------------------
!
!  Set multiple-level usage switch based in iuseua
!
!-----------------------------------------------------------------------
!
    WRITE(6,'(/a,i4)') '   Multiple level data'
    uasw=0
  IF( nuafil /= 0 ) THEN
    DO isrc=1,nsrcua
        IF(iuseua(isrc,ipass) > 0) THEN
                uasw=1
                WRITE(6,'(a,a)') '        Using          ',srcua(isrc)
      END IF
    END DO
  ENDIF
        IF(uasw == 0) WRITE(6,'(a)') '        none'
!
!-----------------------------------------------------------------------
!
!  Set radar-data usage switch based in iuserad
!
!-----------------------------------------------------------------------
!
        WRITE(6,'(/a,i4)') '   Raw radar data'
    radsw=0
  IF( nradfil /= 0 ) THEN
        DO isrc=1,nsrcrad
        IF(iuserad(isrc,ipass) > 0) THEN
                radsw=1
                WRITE(6,'(a,a)') '        Using          ',srcrad(isrc)
      END IF
    END DO
  END IF
        IF(radsw == 0) WRITE(6,'(a)') '         none'
!
!-----------------------------------------------------------------------
!
!  Set ret usage switch based in iuseret
!
!-----------------------------------------------------------------------
!
        WRITE(6,'(/a,i4)') '   Retrieval radar data'
    retsw=0
  IF( nretfil /= 0 ) THEN 
        DO isrc=1,nsrcret
        IF(iuseret(isrc,ipass) > 0) THEN
                retsw=1
                WRITE(6,'(a,a)') '        Using          ',srcret(isrc)
      END IF
    END DO
  END IF
        IF(retsw == 0) WRITE(6,'(a)') '         none'
!
    20    CONTINUE
!-----------------------------------------------------------------------
!
!      OBTAIN THE COST FUNCTION AND THE GRADIENT.
!
!-----------------------------------------------------------------------
!
    print*,'icall===========',icall,sngsw,uasw,radsw
!
    cpuin=f_cputime()
    CALL costf(numctr,ctrv,cfun_single,                                 &
          gdu_err,gdv_err,gdp_err,gdt_err,gdq_err,gdw_err,              &
           u_ctr,v_ctr,p_ctr,t_ctr,q_ctr,w_ctr, psi, phi,               &
          gdscal,                                                       &
          nx,ny,nz,                                                     &
          nvar,nvarradin,nvarrad,nzua,nzrdr,nzret,                      &
          mapfct,j1,j2,j3,aj3x,aj3y,aj3z,j3inv,rhostr,                  &
          rhostru, rhostrv, rhostrw, div3,                              &
          mxsng,mxua,mxrad,mxcolrad,mxret,mxcolret,                     &
          nsrcsng,nsrcua,nsrcrad,nsrcret,ncat,                          &
          mxpass,ipass,iwstat,xs,ys,zs,x,y,z,zp,hterain,                &
          icatg,xcor,nam_var,xsng,ysng,hgtsng,thesng,                   &
          obsng,odifsng,qobsng,qualsng,isrcsng,icatsng,nobsng,          &
          xua,yua,hgtua,theua,                                          &
          obsua,odifua,qobsua,qualua,isrcua,nlevsua,nobsua,             &
          elvrad,xradc,yradc,                                           &
          distrad,uazmrad,vazmrad,hgtradc,theradc,dsdr,dhdr,            &
          obsrad,odifrad,qobsrad,qualrad,                               &
          irad,isrcrad,nlevrad,ncolrad,                                 &
          xretc,yretc,hgtretc,theretc,                                  &
          obsret,odifret,qobsret,qualret,                               &
          iret,isrcret,nlevret,ncolret,                                 &
          srcsng,srcua,srcrad,srcret,                                   &
            ianxtyp,iusesng(0,ipass),iuseua(0,ipass),                   &
            iuserad(0,ipass),iuseret(0,ipass),                          &
!          ianxtyp,iusesng,iuseua,iuserad,iuseret,                       &
          xyrange,kpvrsq,wlim,zrange,zwlim,                             &
          thrng,rngsqi,knt,wgtsum,zsum,                                 &
          corsng,corua,corrad,corret,                               &
          xsng_p,ysng_p,ihgtsng,xua_p,yua_p,ihgtua,                     &
          xradc_p,yradc_p,ihgtradc,zsng_1,zsng_2,                       &
          zua_1,zua_2,zradc_1,zradc_2,                                  &
          oanxsng,oanxua,oanxrad,oanxret,                               &
          sngsw,uasw,radsw,retsw,                                       &
          ipass_filt(ipass),hradius(ipass),nradius_z(ipass),            &
          turn_div,cntl_var,wei_div_h(ipass),wei_div_v(ipass),          &
          anx,tem1,tem2,tem3,ibegin,iend,istatus)
    cpuout=f_cputime()
    cputimearray(1)=cputimearray(1)+(cpuout-cpuin)
!
          cfun_total=0
          DO i=1,nvar+1
            cfun_total=cfun_total+cfun_single(i)
          ENDDO
!          cfun=cfun_single(5)
          cfun=cfun_total
!
    cpuin=f_cputime()
    CALL gradt(numctr,ctrv,grad,                                        &
          gdu_err,gdv_err,gdp_err,gdt_err,gdq_err,gdw_err,              &
           u_ctr,v_ctr,p_ctr,t_ctr,q_ctr,w_ctr, psi, phi,               &
          gdscal,                                                       &
          nx,ny,nz,                                                     &
          nvar,nvarradin,nvarrad,nzua,nzrdr,nzret,                      &
          mapfct,j1,j2,j3,aj3x,aj3y,aj3z,j3inv,rhostr,                  &
          rhostru, rhostrv, rhostrw, div3,                              &
          mxsng,mxua,mxrad,mxcolrad,mxret,mxcolret,                     &
          nsrcsng,nsrcua,nsrcrad,nsrcret,ncat,                          &
          mxpass,ipass,iwstat,xs,ys,zs,x,y,z,zp,hterain,                &
          icatg,xcor,nam_var,xsng,ysng,hgtsng,thesng,                   &
          obsng,odifsng,qobsng,qualsng,isrcsng,icatsng,nobsng,          &
          xua,yua,hgtua,theua,                                          &
          obsua,odifua,qobsua,qualua,isrcua,nlevsua,nobsua,             &
          elvrad,xradc,yradc,                                           &
          distrad,uazmrad,vazmrad,hgtradc,theradc,dsdr,dhdr,            &
          obsrad,odifrad,qobsrad,qualrad,                               &
          irad,isrcrad,nlevrad,ncolrad,                                 &
          xretc,yretc,hgtretc,theretc,                                  &
          obsret,odifret,qobsret,qualret,                               &
          iret,isrcret,nlevret,ncolret,                                 &
          srcsng,srcua,srcrad,srcret,                                   &
!          ianxtyp,iusesng,iuseua,iuserad,iuseret,                       &
            ianxtyp,iusesng(0,ipass),iuseua(0,ipass),                   &
            iuserad(0,ipass),iuseret(0,ipass),                          &
          xyrange,kpvrsq,wlim,zrange,zwlim,                             &
          thrng,rngsqi,knt,wgtsum,zsum,                                 &
          corsng,corua,corrad,corret,                               &
          xsng_p,ysng_p,ihgtsng,xua_p,yua_p,ihgtua,                     &
          xradc_p,yradc_p,ihgtradc,zsng_1,zsng_2,                       &
          zua_1,zua_2,zradc_1,zradc_2,                                  &
          oanxsng,oanxua,oanxrad,oanxret,                               &
          sngsw,uasw,radsw,retsw,                                       &
          ipass_filt(ipass),hradius(ipass),nradius_z(ipass),            &
          turn_div,cntl_var,wei_div_h(ipass),wei_div_v(ipass),          &
          anx,tem1,tem2,tem3,ibegin,iend,istatus)
    cpuout=f_cputime()
    cputimearray(2)=cputimearray(2)+(cpuout-cpuin)
!
!
!-----------------------------------------------------------------------
!
!    Call the LBFGS minimization algorithm.
!
!-----------------------------------------------------------------------
!
!
!    IF(2 == 1) THEN
!      DO i=1,4*numsingle
!        grad(i)=0.0
!      ENDDO
!      DO i=5*numsingle+1,6*numsingle
!        grad(i)=0.0
!      ENDDO
!    ENDIF
    cpuin=f_cputime()
    CALL va15ad(numctr,mgra,ctrv,cfun,grad,diagco,diag,iprint,          &
                      eps,swork,ywork,point,work,iflag,ftol)
    cpuout=f_cputime()
    cputimearray(3)=cputimearray(3)+(cpuout-cpuin)
!
!
    IF(iflag <= 0) GO TO 50
    icall=icall + 1
    IF(icall > maxin(ipass) ) GO TO 50
    GO TO 20
    50  CONTINUE
!
!  END DO  ! end of do loop over ipass
!
    deallocate ( swork  )
    deallocate ( ywork  )
    deallocate (  diag  )
    deallocate (  work  )
!
    PRINT*,'-----------------after minimization!---------------------'
!
!-----------------------------------------------------------------------
!
!c---------------------allocate the arrays   for ----------------------'
!c-----------------storing the optimal perturbation--------------------'
!c
!c
    DO k = 1,nz
      DO j = 1,ny
        DO i = 1,nx
          u_ctr(i,j,k) = 0.0
          v_ctr(i,j,k) = 0.0
            psi(i,j,k) = 0.0
            phi(i,j,k) = 0.0
          p_ctr(i,j,k) = 0.0
          t_ctr(i,j,k) = 0.0
          q_ctr(i,j,k) = 0.0
          w_ctr(i,j,k) = 0.0
        END DO
      END DO
    END DO
!
!
    CALL transi(numctr,nx,ny,nz,  psi, phi, p_ctr,                           &
                t_ctr,q_ctr,w_ctr,ctrv)
!
!
! --------------------------------------------------------

    CALL ctr_to_vbl(ipass_filt(ipass),hradius(ipass),nradius_z(ipass),       &
                                       nx,ny,nz,gdu_err, gdscal,  psi)

    CALL ctr_to_vbl(ipass_filt(ipass),hradius(ipass),nradius_z(ipass),       &
                                       nx,ny,nz,gdv_err, gdscal,  phi)

    CALL ctr_to_vbl(ipass_filt(ipass),hradius(ipass),nradius_z(ipass),       &
                                       nx,ny,nz,gdp_err, gdscal,p_ctr)

    CALL ctr_to_vbl(ipass_filt(ipass),hradius(ipass),nradius_z(ipass),       &
                                       nx,ny,nz,gdt_err, gdscal,t_ctr)

    CALL ctr_to_vbl(ipass_filt(ipass),hradius(ipass),nradius_z(ipass),       &
                                       nx,ny,nz,gdq_err, gdscal,q_ctr)

    CALL ctr_to_vbl(ipass_filt(ipass),hradius(ipass),nradius_z(ipass),       &
                                       nx,ny,nz,gdw_err, gdscal,w_ctr)

!
!------if cntl_var =0  option if U,V as control variables --------------------
!------else if cntl_var =1 option, then psi, phi as control variable----------
!
!
    IF(cntl_var  == 0 ) THEN
!
  DO k = 1, nz
    DO i = 1, nx
      DO j = 1, ny
        u_ctr(i,j,k) =  psi(i,j,k)
        v_ctr(i,j,k) =  phi(i,j,k)
      END DO
    END DO
  END DO

    ELSE
!
  DO k = 1, nz
    DO i = 2, nx-1
      DO j = 2, ny-1
      u_ctr(i,j,k) = ( psi(i-1,j+1,k)+psi(i,j+1,k)                      &
                      -psi(i-1,j-1,k)-psi(i,j-1,k) )/dy/4.              &
                    +( phi(i,  j,  k)-phi(i-1,j,k) )/dx
      u_ctr(i,j,k) = u_ctr(i,j,k)*mapfct(i,j,2)

      v_ctr(i,j,k) = ( psi(i+1,j-1,k)+psi(i+1,j,k)                      &
                      -psi(i-1,j-1,k)-psi(i-1,j,k) )/dx/4.              &
                    +( phi(i,  j,  k)-phi(i,j-1,k) )/dy
      v_ctr(i,j,k) = v_ctr(i,j,k)*mapfct(i,j,3)
      END DO
    END DO
!
    DO j=2,ny-1
      u_ctr( 1,j,k)=u_ctr( 2,j,k)+u_ctr( 2,j,k)-u_ctr( 3,j,k)
      v_ctr( 1,j,k)=v_ctr( 2,j,k)+v_ctr( 2,j,k)-v_ctr( 3,j,k)
      u_ctr(nx,j,k)=u_ctr(nx-1,j,k)+u_ctr(nx-1,j,k)-u_ctr(nx-2,j,k)
      v_ctr(nx,j,k)=v_ctr(nx-1,j,k)+v_ctr(nx-1,j,k)-v_ctr(nx-2,j,k)
    END DO

    DO i=2,nx-1
      u_ctr(i, 1,k)=u_ctr(i, 2,k)+u_ctr(i, 2,k)-u_ctr(i, 3,k)
      v_ctr(i, 1,k)=v_ctr(i, 2,k)+v_ctr(i, 2,k)-v_ctr(i, 3,k)
      u_ctr(i,ny,k)=u_ctr(i,ny-1,k)+u_ctr(i,ny-1,k)-u_ctr(i,ny-2,k)
      v_ctr(i,ny,k)=v_ctr(i,ny-1,k)+v_ctr(i,ny-1,k)-v_ctr(i,ny-2,k)
    END DO

    u_ctr(1,1 ,k)=0.5*( u_ctr(2,1,k)+u_ctr(1,2,k) )
    v_ctr(1,1 ,k)=0.5*( v_ctr(2,1,k)+v_ctr(1,2,k) )
    u_ctr(1,ny,k)=0.5*( u_ctr(1,ny-1,k)+u_ctr(2,ny,k) )
    v_ctr(1,ny,k)=0.5*( v_ctr(1,ny-1,k)+v_ctr(2,ny,k) )

    u_ctr(nx,1,k)=0.5*( u_ctr(nx-1,1,k)+u_ctr(nx,2,k) )
    v_ctr(nx,1,k)=0.5*( v_ctr(nx-1,1,k)+v_ctr(nx,2,k) )
    u_ctr(nx,ny,k)=0.5*( u_ctr(nx,ny-1,k)+u_ctr(nx-1,ny,k) )
    v_ctr(nx,ny,k)=0.5*( v_ctr(nx,ny-1,k)+v_ctr(nx-1,ny,k) )

  END DO
!
    END IF
!
!
!  call smooth ( u_ctr(1,1,1), NX, NY, NZ, NUM_SMTH, 1)
!  call smooth ( v_ctr(1,1,1), NX, NY, NZ, NUM_SMTH, 1)
!  call smooth ( p_ctr(1,1,1), NX, NY, NZ, NUM_SMTH, 0)
!  call smooth ( t_ctr(1,1,1), NX, NY, NZ, NUM_SMTH, 0)
!  call smooth ( q_ctr(1,1,1), NX, NY, NZ, NUM_SMTH, 0)
!  call smooth ( w_ctr(1,1,1), NX, NY, NZ, NUM_SMTH, 0)
!
!
!
!-----------------------------------------------------------------------
!
!c                 add the optimal perturbation to backgd
! 
!-----------------------------------------------------------------------
! 
!
!----------------temparily setting by Jidong Gao------------------------
!
    sum1=0.0
    sum2=0.0
    sum3=0.0
    sum4=0.0
    sum5=0.0
    sum6=0.0
    DO k = 1, nz
      DO j = 1, ny
        DO i = 1, nx
          sum1=sum1+u_ctr(i,j,k)
          sum2=sum2+v_ctr(i,j,k)
          sum3=sum3+p_ctr(i,j,k)
          sum4=sum4+t_ctr(i,j,k)
          sum5=sum5+q_ctr(i,j,k)
          sum6=sum6+w_ctr(i,j,k)
!
     anx(i,j,k,1) = anx(i,j,k,1) + u_ctr(i,j,k)
     anx(i,j,k,2) = anx(i,j,k,2) + v_ctr(i,j,k)
     anx(i,j,k,3) = anx(i,j,k,3) + p_ctr(i,j,k)
     anx(i,j,k,4) = anx(i,j,k,4) + t_ctr(i,j,k)
     anx(i,j,k,5) = anx(i,j,k,5) + q_ctr(i,j,k)
     anx(i,j,k,6) = anx(i,j,k,6) + w_ctr(i,j,k)
!
!
          IF ( anx(i,j,k,5) <= 0.) anx(i,j,k,5) = 0.0
!
        END DO
      END DO
    END DO
!
    IF(ipass == 1 ) THEN
      OPEN( 13, file='radialwind.dat',form='unformatted')
      write(13) u_ctr
      write(13) v_ctr
      write(13) w_ctr
      CLOSE(13)
      OPEN( 13, file='wind3d.dat',form='unformatted')
      write(13) (((anx(i,j,k,1),i=1,nx),j=1,ny),k=1,nz)
      write(13) (((anx(i,j,k,2),i=1,nx),j=1,ny),k=1,nz)
      write(13) (((anx(i,j,k,6),i=1,nx),j=1,ny),k=1,nz)
      CLOSE(13)
    ENDIF
!
!  print*,'GDSCAL====',GDSCAL
   IF(1==1) THEN
    PRINT*,'u_ctr_sum=',sum1
   DO j=1,8
!    write(*,'(10f10.4)') (u_ctr(i,j,nz/2),i=nx/2-4,nx/2+4)
    write(*,'(10f10.4)') (u_ctr(104+i,84+j,26),i=1,8)
   ENDDO
    PRINT*,'v_ctr_sum=',sum2
!   DO j=ny/2-4,ny/2+4
   DO j=1,8
    write(*,'(10f10.4)') (v_ctr(104+i,84+j,26),i=1,8)
   ENDDO
    PRINT*,'p_ctr_sum=',sum3
   DO j=ny/2-4,ny/2+4
!    write(*,'(10f10.4)') (p_ctr(i,j,nz/2),i=nx/2-4,nx/2+4)
   ENDDO
    PRINT*,'t_ctr_sum=',sum4
   DO j=ny/2-4,ny/2+4
!    write(*,'(10f10.4)') (t_ctr(i,j,nz/2),i=nx/2-4,nx/2+4)
   ENDDO
    PRINT*,'q_ctr_sum=',sum5
   DO j=ny/2-4,ny/2+4
!    write(*,'(10f10.4)') (q_ctr(i,j,nz/2),i=nx/2-4,nx/2+4)
   ENDDO
    PRINT*,'w_ctr_sum=',sum6
   ENDIF
!
!     K=20
!  DO I=1,NX
!    write(*,'(16f5.1)') (u_ctr(I,J,K),J=1,NY)
!  END DO
!  DO I=1,NX
!    write(*,'(16f5.1)') (v_ctr(I,J,K),J=1,NY)
!  END DO
!  DO K = 1, NZ
!  DO I=1,NX
!    write(*,'(16f5.1)') (w_ctr(I,J,K),J=1,NY)
!  END DO
!  END DO
!     print*,'stop here? 2'
!  stop
!c
!
    deallocate (u_ctr)
    deallocate (v_ctr)
    deallocate (p_ctr)
    deallocate (t_ctr)
    deallocate (q_ctr)
    deallocate (w_ctr)
!
  END IF
!
  deallocate ( xgus )
  deallocate ( ctrv )
  deallocate ( grad )

  deallocate ( gdu_err )
  deallocate ( gdv_err )
  deallocate ( gdp_err )
  deallocate ( gdt_err )
  deallocate ( gdq_err )
  deallocate ( gdw_err )
  deallocate ( gdscal )

  deallocate ( rhostru )
  deallocate ( rhostrv )
  deallocate ( rhostrw )
  deallocate ( div3    )
!
!
! IF(1 == 0) THEN
!
!
!-----------------------------------------------------------------------
!
!  Note in the following the analysis scratch arrays
!  are used to hold the output statistics
!
!-----------------------------------------------------------------------
!
!   CALL diffnst3d(nvar,                                                &
!                  nzua,nzret,mxsng,mxua,mxcolret,                      &
!                  obsng,odifsng,oanxsng,isrcsng,qualsng,nobsng,        &
!                  obsua,odifua,oanxua,isrcua,qualua,nlevsua,nobsua,    &
!                  obsret,odifret,oanxret,iret,                         &
!                  qualret,nlevret,ncolret,                             &
!                  knt,wgtsum,zsum)
!
!   820   FORMAT('  Statistics for analysis pass ',i4,/                 &
!                '  ivar  name    knt      bias        rms')
!   DO k=1,nvar
!     WRITE(6,812) k,nam_var(k),knt(k,1),wgtsum(k,1),zsum(k,1)
!   END DO
!   IF(iwstat > 0) THEN
!     DO k=1,nvar
!       WRITE(iwstat,812) k,nam_var(k),                                 &
!                         knt(k,1),wgtsum(k,1),zsum(k,1)
!     END DO
!     WRITE(iwstat,806)
!   END IF
!   CALL diffnstra(nvar,nvarrad,nvarradin,nzrdr,mxrad,mxcolrad,         &
!             elvrad,distrad,hgtradc,                                   &
!             uazmrad,vazmrad,qualrad,irad,                             &
!             obsrad,odifrad,oanxrad,                                   &
!             nlevrad,ncolrad,                                          &
!             knt,wgtsum,zsum)
!   WRITE(6,815)
!   DO k=1,nvar
!     WRITE(6,812) k,nam_var(k),knt(k,1),wgtsum(k,1),zsum(k,1)
!   END DO
!   WRITE(6,806)
! END IF
!
! 200 CONTINUE
!
  istatus=0
!
  RETURN
END SUBROUTINE minimization

!
!##################################################################
!##################################################################
!######                                                      ######
!######                 SUBROUTINE LINEAR                    ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!
!  Linear interplation in one direction.
!
!
!-----------------------------------------------------------------------
!
!  AUTHOR:
!
!  Jidong Gao, CAPS, July, 2000
!
!-----------------------------------------------------------------------
!

SUBROUTINE linear(n,xx,yy,u,f) 5

  INTEGER :: n
  REAL    :: xx(n),yy(n),u,f

  IF( u <= xx(1)) THEN

    a1=( u-xx(2))/(xx(1)-xx(2))
    a2=( u-xx(1))/(xx(2)-xx(1))
    f=a1*yy(1)+a2*yy(2)

  ELSE

    DO i=2,n
      IF( u <= xx(i) )  EXIT
    END DO
    i = min(i,n)

    a1=( u-xx(i)  )/(xx(i-1)-xx(i))
    a2=( u-xx(i-1))/(xx(i)-xx(i-1))
    f=a1*yy(i-1)+a2*yy(i)

  END IF
!     print*,"hqback==",xx
!     print*,"qback==",yy
!  stop
!
  RETURN
END SUBROUTINE linear