subroutine setuppm10(lunin,mype,nreal,nobs,isis,is,conv_diagsave)

!$$$  subprogram documentation block
!                .      .    .
! subprogram:    setuppm10 --- Compute rhs of oi for in-situ pm10 obs
!
!   prgrmmr:     parrish          org: np22                date: 1990-10-06
!
! abstract:      For pm10 observations, this routine
!                  a) reads obs assigned to given mpi task (geographic region),
!                  b) simulates obs from guess,
!                  c) apply some quality control to obs,
!                  d) load weight and innovation arrays used in minimization
!                  e) collects statistics for runtime diagnostic output
!                  f) writes additional diagnostic information to output file
!
! program history log:
!   2016-02-20  pagowski - based on setupmp2_5; converted for pm10
!   2016-04-04  guo      - full res obvsr: index to allow redistribution of obsdiags
!   2016-05-18  guo     - replaced ob_type with polymorphic obsNode through type casting
!   2016-06-24  guo     - fixed the default value of obsdiags(:,:)%tail%luse to luse(i)
!                       . removed (%dlat,%dlon) debris.
!   2017-02-06  todling - add netcdf_diag capability; hidden as contained code
!
!   input argument list:
!     lunin          - unit from which to read observations
!     mype           - mpi task id
!     nreal          - number of pieces of info (location, time, etc) per obs
!     nobs           - number of observations
!     isis           - sensor/instrument/satellite id
!     is             - integer(i_kind) counter for number of obs types to process
!     
!     obstype        - type of pm10 obs
!
! attributes:
!   language: f90
!   machine:  ibm RS/6000 SP; SGI Origin 2000; Compaq HP
!
!$$$ end documentation block
     
! !uses:

  use mpeu_util, only: die,perr
  use kinds, only: r_kind,i_kind,r_single
  
  use constants, only : zero,half,one,two,tiny_r_kind
  use constants, only : cg_term,wgtlim
  use constants, only: huge_single,r10
  use constants, only: r1000,rd,max_varname_length

  use m_obsdiags, only : pm10head
  use m_obsNode , only : obsNode
  use m_pm10Node, only : pm10Node
  use m_obsLList, only : obsLList_appendNode
  use obsmod    , only : i_pm10_ob_type,time_offset
  use obsmod, only : obsdiags,lobsdiag_allocated,lobsdiagsave
  use obsmod, only : obs_diag,luse_obsdiag

  use obsmod, only: netcdf_diag, binary_diag, dirname, ianldate
  use nc_diag_write_mod, only: nc_diag_init, nc_diag_header, nc_diag_metadata, &
       nc_diag_write, nc_diag_data2d
  use nc_diag_read_mod, only: nc_diag_read_init, nc_diag_read_get_dim, nc_diag_read_close

  use qcmod, only : dfact,dfact1
  
  use gsi_4dvar, only: nobs_bins,hr_obsbin
  
  use gridmod, only : get_ij,get_ijk
  
  use guess_grids, only : nfldsig,hrdifsig
  use gsi_bundlemod, only : gsi_bundlegetpointer,GSI_BundlePrint
  use gsi_chemguess_mod, only : gsi_chemguess_get,gsi_chemguess_bundle
  use gsi_metguess_mod, only : gsi_metguess_get,gsi_metguess_bundle
  
  use convinfo, only: cgross,cvar_b,cvar_pg,&
        icuse,ictype,icsubtype
  
  use jfunc, only : jiter,last,miter
  
  use m_dtime, only: dtime_setup, dtime_check

  use chemmod, only : &
        iconc,ierror,ilat,ilon,itime,iid,ielev,isite,iikx,&
        elev_tolerance,elev_missing,pm10_teom_max,ilate,ilone
  use chemmod, only : oneobtest_chem
  use chemmod, only : d_10,nh4_mfac,oc_mfac
  use chemmod, only: naero_gocart_wrf,aeronames_gocart_wrf,&
      upper2lower,lower2upper,laeroana_gocart


  use gridmod, only : cmaq_regional,wrf_mass_regional

  implicit none
  
! !input parameters:

  character(len=3) :: cvar='pm1'
  integer(i_kind)                  , intent(in   ) :: lunin  ! unit from which to read observations
  integer(i_kind)                  , intent(in   ) :: mype   ! mpi task id
  integer(i_kind)                  , intent(in   ) :: nreal  ! number of pieces of non-co info (location, time, etc) per obs
  integer(i_kind)                  , intent(inout) :: nobs   ! number of observations
  character(20)                    , intent(in   ) :: isis   ! sensor/instrument/satellite id
  integer(i_kind)                  , intent(in   ) :: is     
  logical                          , intent(in   ) :: conv_diagsave   ! logical to save innovation dignostics
  
! a function of level
!-------------------------------------------------------------------------
  
! declare local parameters  

  character(len=*),parameter:: myname="setuppm10"
  
! declare local variables  
  
  real(r_kind) rat_err2,dlat,dtime,dlon
  real(r_kind) cg_pm10,wgross,wnotgross,wgt,arg,exp_arg,term
  real(r_kind) :: pm10ges
  real(r_kind) :: ratio_errors,error
  real(r_kind) :: innov,innov_error2,rwgt,valqc,tfact,innov_error,elevges,&
        elevdiff,conc,elevobs,ps_ges,site_id,tv_ges
  real(r_kind) errinv_input,errinv_adjst,errinv_final
  real(r_kind) err_input,err_adjst,err_final

  real(r_kind) ,dimension(nreal,nobs):: data
  real(r_kind),pointer,dimension(:,:,:):: rank3
  
  INTEGER(i_kind) i,k,ier,ibin,l,istat,ikx,ii,jj,idia,ifld
  integer(i_kind) mm1
  integer(i_kind) :: nchar,nrealdiag


  character(len=8) :: station_id
  character(len=8),allocatable,dimension(:) :: cdiagbuf
  real(r_single),allocatable,dimension(:,:) :: rdiagbuf

  real(r_kind),dimension(4):: tempwij

  logical,dimension(nobs):: luse,muse
  integer(i_kind),dimension(nobs):: ioid ! initial (pre-distribution) obs ID
  integer(i_kind),dimension(nobs) :: dup

  logical:: in_curbin, in_anybin
  logical proceed
  integer(i_kind),dimension(nobs_bins) :: n_alloc
  integer(i_kind),dimension(nobs_bins) :: m_alloc
  class(obsNode), pointer:: my_node
  type(pm10Node), pointer:: my_head
  type(obs_diag), pointer:: my_diag

  real(r_kind),allocatable,dimension(:,:,:  ) :: ges_ps
  real(r_kind),allocatable,dimension(:,:,:  ) :: ges_z
  real(r_kind),allocatable,dimension(:,:,:,:) :: ges_pm10
  real(r_kind),allocatable,dimension(:,:,:,:) :: ges_tv

  character(len=max_varname_length) :: aeroname

  integer(i_kind) :: ipm10,n_gocart_var


! Check to see if required guess fields are available
  call check_vars_(proceed)
  if(.not.proceed) return  ! not all vars available, simply return

! If require guess vars available, extract from bundle ...
  call init_vars_

  n_alloc(:)=0
  m_alloc(:)=0

  nchar=1
  nrealdiag=19
  mm1=mype+1

!
!*********************************************************************************
! get pointer to pm10 guess state, if not present return 

  if (cmaq_regional) then
     WRITE(6,*) 'pm10 for cmaq not implemented. Stopping'
     CALL stop2(451)
  endif

  if (wrf_mass_regional .and. laeroana_gocart) then

!check if aerosol species in control

     call gsi_chemguess_get ( 'aerosols::3d', n_gocart_var, ier )

     if (n_gocart_var /= naero_gocart_wrf) then
        write(6,*) 'setuppm10: not all gocart aerosols in anavinfo'
        call stop2(451)
     endif

     do i=1,naero_gocart_wrf
        aeroname=upper2lower(aeronames_gocart_wrf(i))
        call gsi_chemguess_get ('var::'//trim(aeroname), ipm10, ier )
        if (ier > 0 .or. ipm10 <= 0) then
           write(6,*) 'convinfo: ',trim(aeroname),' missing in anavinfo'
           call stop2(452)
        endif
     enddo

     if (size(gsi_chemguess_bundle)==nfldsig) then
        aeroname='bc1'
        call gsi_bundlegetpointer(gsi_chemguess_bundle(1),trim(aeroname),&
             rank3,ier)
        if (ier==0) then
           allocate(ges_pm10(size(rank3,1),size(rank3,2),size(rank3,3),&
                nfldsig))
           ges_pm10(:,:,:,1)=rank3
           do ifld=2,nfldsig
              call gsi_bundlegetpointer(gsi_chemguess_bundle(ifld),trim(aeroname),rank3,ier)
              ges_pm10(:,:,:,ifld)=rank3
           enddo
        else
           write(6,*) 'setuppm10: ',trim(aeroname),' not found in chem bundle, ier= ',ier
           call stop2(453)
        endif

        aeroname='bc2'
        call gsi_bundlegetpointer(gsi_chemguess_bundle(1),trim(aeroname),&
             rank3,ier)
        if (ier==0) then
           ges_pm10(:,:,:,1)=ges_pm10(:,:,:,1)+rank3
           do ifld=2,nfldsig
              call gsi_bundlegetpointer(gsi_chemguess_bundle(ifld),trim(aeroname),rank3,ier)
              ges_pm10(:,:,:,ifld)=ges_pm10(:,:,:,ifld)+rank3
           enddo
        else
           write(6,*) 'setuppm10: ',trim(aeroname),' not found in chem bundle, ier= ',ier
           call stop2(453)
        endif

        aeroname='sulf'
        call gsi_bundlegetpointer(gsi_chemguess_bundle(1),trim(aeroname),&
             rank3,ier)
        if (ier==0) then
           ges_pm10(:,:,:,1)=ges_pm10(:,:,:,1)+rank3*nh4_mfac
           do ifld=2,nfldsig
              call gsi_bundlegetpointer(gsi_chemguess_bundle(ifld),trim(aeroname),rank3,ier)
              ges_pm10(:,:,:,ifld)=ges_pm10(:,:,:,ifld)+rank3*nh4_mfac
           enddo
        else
           write(6,*) 'setuppm10: ',trim(aeroname),' not found in chem bundle, ier= ',ier
           call stop2(453)
        endif

        aeroname='p25'
        call gsi_bundlegetpointer(gsi_chemguess_bundle(1),trim(aeroname),&
             rank3,ier)
        if (ier==0) then
           ges_pm10(:,:,:,1)=ges_pm10(:,:,:,1)+rank3
           do ifld=2,nfldsig
              call gsi_bundlegetpointer(gsi_chemguess_bundle(ifld),trim(aeroname),rank3,ier)
              ges_pm10(:,:,:,ifld)=ges_pm10(:,:,:,ifld)+rank3
           enddo
        else
           write(6,*) 'setuppm10: ',trim(aeroname),' not found in chem bundle, ier= ',ier
           call stop2(453)
        endif

        aeroname='oc1'
        call gsi_bundlegetpointer(gsi_chemguess_bundle(1),trim(aeroname),&
             rank3,ier)
        if (ier==0) then
           ges_pm10(:,:,:,1)=ges_pm10(:,:,:,1)+rank3*oc_mfac
           do ifld=2,nfldsig
              call gsi_bundlegetpointer(gsi_chemguess_bundle(ifld),trim(aeroname),rank3,ier)
              ges_pm10(:,:,:,ifld)=ges_pm10(:,:,:,ifld)+rank3*oc_mfac
           enddo
        else
           write(6,*) 'setuppm10: ',trim(aeroname),' not found in chem bundle, ier= ',ier
           call stop2(453)
        endif

        aeroname='oc2'
        call gsi_bundlegetpointer(gsi_chemguess_bundle(1),trim(aeroname),&
             rank3,ier)
        if (ier==0) then
           ges_pm10(:,:,:,1)=ges_pm10(:,:,:,1)+rank3*oc_mfac
           do ifld=2,nfldsig
              call gsi_bundlegetpointer(gsi_chemguess_bundle(ifld),trim(aeroname),rank3,ier)
              ges_pm10(:,:,:,ifld)=ges_pm10(:,:,:,ifld)+rank3*oc_mfac
           enddo
        else
           write(6,*) 'setuppm10: ',trim(aeroname),' not found in chem bundle, ier= ',ier
           call stop2(453)
        endif

        aeroname='seas1'
        call gsi_bundlegetpointer(gsi_chemguess_bundle(1),trim(aeroname),&
             rank3,ier)
        if (ier==0) then
           ges_pm10(:,:,:,1)=ges_pm10(:,:,:,1)+rank3
           do ifld=2,nfldsig
              call gsi_bundlegetpointer(gsi_chemguess_bundle(ifld),trim(aeroname),rank3,ier)
              ges_pm10(:,:,:,ifld)=ges_pm10(:,:,:,ifld)+rank3
           enddo
        else
           write(6,*) 'setuppm10: ',trim(aeroname),' not found in chem bundle, ier= ',ier
           call stop2(453)
        endif

        aeroname='seas2'
        call gsi_bundlegetpointer(gsi_chemguess_bundle(1),trim(aeroname),&
             rank3,ier)
        if (ier==0) then
           ges_pm10(:,:,:,1)=ges_pm10(:,:,:,1)+rank3
           do ifld=2,nfldsig
              call gsi_bundlegetpointer(gsi_chemguess_bundle(ifld),trim(aeroname),rank3,ier)
              ges_pm10(:,:,:,ifld)=ges_pm10(:,:,:,ifld)+rank3
           enddo
        else
           write(6,*) 'setuppm10: ',trim(aeroname),' not found in chem bundle, ier= ',ier
           call stop2(453)
        endif

        aeroname='seas3'
        call gsi_bundlegetpointer(gsi_chemguess_bundle(1),TRIM(aeroname),&
             rank3,ier)
        if (ier==0) then
           ges_pm10(:,:,:,1)=ges_pm10(:,:,:,1)+rank3
           do ifld=2,nfldsig
              call gsi_bundlegetpointer(gsi_chemguess_bundle(ifld),TRIM(aeroname),rank3,ier)
              ges_pm10(:,:,:,ifld)=ges_pm10(:,:,:,ifld)+rank3
           enddo
        else
           write(6,*) 'setuppm10: ',TRIM(aeroname),' not found in chem bundle, ier= ',ier
           call stop2(453)
        endif

        aeroname='dust1'
        call gsi_bundlegetpointer(gsi_chemguess_bundle(1),trim(aeroname),&
             rank3,ier)
        if (ier==0) then
           ges_pm10(:,:,:,1)=ges_pm10(:,:,:,1)+rank3
           do ifld=2,nfldsig
              call gsi_bundlegetpointer(gsi_chemguess_bundle(ifld),trim(aeroname),rank3,ier)
              ges_pm10(:,:,:,ifld)=ges_pm10(:,:,:,ifld)+rank3
           enddo
        else
           write(6,*) 'setuppm10: ',trim(aeroname),' not found in chem bundle, ier= ',ier
           call stop2(453)
        endif

        aeroname='dust2'
        call gsi_bundlegetpointer(gsi_chemguess_bundle(1),trim(aeroname),&
             rank3,ier)
        if (ier==0) then
           ges_pm10(:,:,:,1)=ges_pm10(:,:,:,1)+rank3
           do ifld=2,nfldsig
              call gsi_bundlegetpointer(gsi_chemguess_bundle(ifld),trim(aeroname),rank3,ier)
              ges_pm10(:,:,:,ifld)=ges_pm10(:,:,:,ifld)+rank3
           enddo
        else
           write(6,*) 'setuppm10: ',trim(aeroname),' not found in chem bundle, ier= ',ier
           call stop2(453)
        endif

        aeroname='dust3'
        call gsi_bundlegetpointer(gsi_chemguess_bundle(1),TRIM(aeroname),&
             rank3,ier)
        if (ier==0) then
           ges_pm10(:,:,:,1)=ges_pm10(:,:,:,1)+rank3
           do ifld=2,nfldsig
              call gsi_bundlegetpointer(gsi_chemguess_bundle(ifld),TRIM(aeroname),rank3,ier)
              ges_pm10(:,:,:,ifld)=ges_pm10(:,:,:,ifld)+rank3
           enddo
        else
           write(6,*) 'setuppm10: ',TRIM(aeroname),' not found in chem bundle, ier= ',ier
           call stop2(453)
        endif

        aeroname='dust4'
        call gsi_bundlegetpointer(gsi_chemguess_bundle(1),TRIM(aeroname),&
             rank3,ier)
        if (ier==0) then
           ges_pm10(:,:,:,1)=ges_pm10(:,:,:,1)+rank3*d_10
           do ifld=2,nfldsig
              call gsi_bundlegetpointer(gsi_chemguess_bundle(ifld),TRIM(aeroname),rank3,ier)
              ges_pm10(:,:,:,ifld)=ges_pm10(:,:,:,ifld)+rank3*d_10
           enddo
        else
           write(6,*) 'setuppm10: ',TRIM(aeroname),' not found in chem bundle, ier= ',ier
           call stop2(453)
        endif


     else
        write(6,*) 'setuppm10: inconsistent vector sizes (nfldsig,size(chemguess_bundle) ',&
             nfldsig,size(gsi_chemguess_bundle)
        call stop2(420)
     endif

  endif


! initialize arrays

  read(lunin)data,luse,ioid

  dup=one

  do i=1,nobs
     muse(i) = (icuse(nint(data(iikx,i))) <= jiter)
  enddo

  do k=1,nobs
     do l=k+1,nobs
        if(data(ilat,k) == data(ilat,l) .and.  &
             data(ilon,k) == data(ilon,l) .and.  &
             data(ielev,k) == data(ielev,l) .and.  &
             data(isite,k) == data(isite,l) .and.  &
             muse(k) .and. muse(l)) then
           tfact = min(one,abs(data(itime,k)-data(itime,l))/dfact1)
           dup(k)=dup(k)+one-tfact*tfact*(one-dfact)
           dup(l)=dup(l)+one-tfact*tfact*(one-dfact)
        end if
     end do
  end do
  
! if requested, save select data for output to diagnostic file
  if(conv_diagsave)then
     ii=0
     if (lobsdiagsave) nrealdiag=nrealdiag+4*miter+1
     allocate(cdiagbuf(nobs),rdiagbuf(nrealdiag,nobs))
     if (netcdf_diag) call init_netcdf_diag_
  end if
  mm1=mype+1


  call dtime_setup()
  
  if (oneobtest_chem) then
     WRITE(6,*)'setuppm10: oneobtest_chem available only for pm2_5'
     CALL stop2(424)
  endif
     

  if (trim(isis)=='TEOM') then

     DO i=1,nobs
        
        dtime=data(itime,i)

        call dtime_check(dtime, in_curbin, in_anybin)
        if(.not.in_anybin) cycle

        if (nobs_bins > 1) then
           ibin = nint( dtime/hr_obsbin ) + 1
        else
           ibin = 1
        endif

        if (ibin < 1 .or. ibin > nobs_bins) &
              write(6,*)mype,'error nobs_bins,ibin= ',nobs_bins,ibin
        
!    link obs to diagnostics structure
        if(luse_obsdiag)then
           if (.not.lobsdiag_allocated) then
              if (.not.associated(obsdiags(i_pm10_ob_type,ibin)%head)) then
                 obsdiags(i_pm10_ob_type,ibin)%n_alloc = 0
                 allocate(obsdiags(i_pm10_ob_type,ibin)%head,stat=istat)
                 if (istat/=0) then
                    write(6,*)'setupq: failure to allocate obsdiags',istat
                    call stop2(421)
                 end if
                 obsdiags(i_pm10_ob_type,ibin)%tail => obsdiags(i_pm10_ob_type,ibin)%head
              else
                 allocate(obsdiags(i_pm10_ob_type,ibin)%tail%next,stat=istat)
                 if (istat/=0) then
                    write(6,*)'setupq: failure to allocate obsdiags',istat
                    call stop2(422)
                 end if
                 obsdiags(i_pm10_ob_type,ibin)%tail => obsdiags(i_pm10_ob_type,ibin)%tail%next
              end if
              obsdiags(i_pm10_ob_type,ibin)%n_alloc = obsdiags(i_pm10_ob_type,ibin)%n_alloc +1

              allocate(obsdiags(i_pm10_ob_type,ibin)%tail%muse(miter+1))
              allocate(obsdiags(i_pm10_ob_type,ibin)%tail%nldepart(miter+1))
              allocate(obsdiags(i_pm10_ob_type,ibin)%tail%tldepart(miter))
              allocate(obsdiags(i_pm10_ob_type,ibin)%tail%obssen(miter))

              obsdiags(i_pm10_ob_type,ibin)%tail%indxglb=ioid(i)
              obsdiags(i_pm10_ob_type,ibin)%tail%nchnperobs=-99999
              obsdiags(i_pm10_ob_type,ibin)%tail%luse=luse(i)
              obsdiags(i_pm10_ob_type,ibin)%tail%muse(:)=.false.
              obsdiags(i_pm10_ob_type,ibin)%tail%nldepart(:)=-huge(zero)
              obsdiags(i_pm10_ob_type,ibin)%tail%tldepart(:)=zero
              obsdiags(i_pm10_ob_type,ibin)%tail%wgtjo=-huge(zero)
              obsdiags(i_pm10_ob_type,ibin)%tail%obssen(:)=zero
           
              n_alloc(ibin) = n_alloc(ibin) +1
              my_diag => obsdiags(i_pm10_ob_type,ibin)%tail
              my_diag%idv = is
              my_diag%iob = ioid(i)
              my_diag%ich = 1
              my_diag%elat= data(ilate,i)
              my_diag%elon= data(ilone,i)

           else
              if (.not.associated(obsdiags(i_pm10_ob_type,ibin)%tail)) then
                 obsdiags(i_pm10_ob_type,ibin)%tail => obsdiags(i_pm10_ob_type,ibin)%head
              else
                 obsdiags(i_pm10_ob_type,ibin)%tail => obsdiags(i_pm10_ob_type,ibin)%tail%next
              end if
              if (.not.associated(obsdiags(i_pm10_ob_type,ibin)%tail)) then
                  call die(myname,'.not.associated(obsdiags(i_pm10_ob_type,ibin)%tail)')
              end if
              if (obsdiags(i_pm10_ob_type,ibin)%tail%indxglb/=ioid(i)) then
                 write(6,*)'setuppm10: index error'
                 call stop2(423)
              end if
           endif
        endif
        
        if(.not.in_curbin) cycle
        
        dlat=data(ilat,i)
        dlon=data(ilon,i)
        conc=data(iconc,i)
        elevobs=data(ielev,i)
        ikx=nint(data(iikx,i))
        site_id=data(iid,i)

        call tintrp2a11(ges_z,elevges,dlat,dlon,dtime,hrdifsig,&
             mype,nfldsig)
        
!obs are conc
!wrf state vars are as mix ratio
!cmaq pm10 is as conc
!might convert for cmaq at some point as well


        if (wrf_mass_regional) then
           call tintrp2a11(ges_ps,ps_ges,dlat,dlon,dtime,hrdifsig,&
                mype,nfldsig)

           call tintrp2a11(ges_tv(:,:,1,nfldsig),tv_ges,dlat,dlon,dtime,hrdifsig,&
                mype,nfldsig)

           conc=conc/(ps_ges*r1000/(rd*tv_ges))
        endif



!if elevobs is known than calculate difference otherwise
!assume that difference is acceptable
        
        if (elevobs > elev_missing) then
           elevdiff=abs(elevobs-elevges)
        else
           elevdiff=zero
!if elevation unknown include observation nevertheless
        endif
        
        call tintrp2a11(ges_pm10,pm10ges,dlat,dlon,dtime,hrdifsig,&
             mype,nfldsig)
        innov = conc - pm10ges

        error=one/data(ierror,i)
        ratio_errors=one/sqrt(real(dup(i)))
        innov_error = error*innov
        
        if (abs(innov) > cgross(ikx) .or. &
              conc > pm10_teom_max  .or. &
              elevdiff > elev_tolerance) then
           muse(i)=.false.
        endif

        rat_err2 = ratio_errors**2
        
        if(luse(i))then
           
           innov_error2     = innov_error*innov_error
           exp_arg = -half*innov_error2
           rat_err2 = ratio_errors**2
                 
           if (cvar_pg(ikx) > tiny_r_kind ) then
              arg  = exp(exp_arg)
              wnotgross= one-cvar_pg(ikx)
              cg_pm10=cvar_b(ikx)
              wgross = cg_term*cvar_pg(ikx)/(cg_pm10*wnotgross)
              term = log((arg+wgross)/(one+wgross))
              wgt  = one-wgross/(arg+wgross)
              rwgt = wgt/wgtlim
           else
              term = exp_arg
              wgt  = wgtlim
              rwgt = wgt/wgtlim
           endif
           
           valqc = -two*rat_err2*term

        endif

        if(luse_obsdiag)then
           obsdiags(i_pm10_ob_type,ibin)%tail%muse(jiter)=muse(i)
           obsdiags(i_pm10_ob_type,ibin)%tail%nldepart(jiter)=innov
           obsdiags(i_pm10_ob_type,ibin)%tail%wgtjo= (error*ratio_errors)**2
        end if

        if (.not. last .and. muse(i)) then
           
           allocate(my_head)
           m_alloc(ibin) = m_alloc(ibin) +1
           my_node => my_head
           call obsLList_appendNode(pm10head(ibin),my_node)
           my_node => null()

           my_head%idv = is
           my_head%iob = ioid(i)
           my_head%elat= data(ilate,i)
           my_head%elon= data(ilone,i)

           call get_ij(mm1,dlat,dlon,&
                 my_head%ij,tempwij)

           my_head%ij (5:8)=my_head%ij(1:4)
           my_head%wij(1:4)=tempwij
           my_head%wij(5:8)=zero
           my_head%res    = innov
           my_head%err2   = error**2
           my_head%raterr2= ratio_errors**2
           my_head%time   = dtime
           my_head%b      = cvar_b(ikx)
           my_head%pg     = cvar_pg(ikx)
           my_head%luse   = luse(i)

           if(luse_obsdiag)then
              my_head%diags => &
                    obsdiags(i_pm10_ob_type,ibin)%tail

              my_diag => my_head%diags
              if(my_head%idv /= my_diag%idv .or. &
                   my_head%iob /= my_diag%iob ) then
                 call perr(myname,'mismatching %[head,diags]%(idv,iob,ibin) =',&
                       (/is,ioid(i),ibin/))
                 call perr(myname,'my_head%(idv,iob) =',(/my_head%idv,my_head%iob/))
                 call perr(myname,'my_diag%(idv,iob) =',(/my_diag%idv,my_diag%iob/))
                 call die(myname)
              endif
           end if

           my_head => null()
        endif
        
! save select output for diagnostic file
        if (conv_diagsave) then

           ii=ii+1

           call tintrp2a11(ges_ps,ps_ges,dlat,dlon,dtime,hrdifsig,&
                mype,nfldsig)

           ps_ges=ps_ges*r10 ! convert from cb to hpa

           write(station_id,'(Z8)')nint(site_id)

           err_input = data(ierror,i)
           err_adjst = data(ierror,i)
           if (ratio_errors*error>tiny_r_kind) then
              err_final = one/(ratio_errors*error)
           else
              err_final = huge_single
           endif
           
           errinv_input = huge_single
           errinv_adjst = huge_single
           errinv_final = huge_single
           if (err_input>tiny_r_kind) errinv_input=one/err_input
           if (err_adjst>tiny_r_kind) errinv_adjst=one/err_adjst
           if (err_final>tiny_r_kind) errinv_final=one/err_final
           
           if (binary_diag) call contents_binary_diag_
           if (netcdf_diag) call contents_netcdf_diag_

        endif

! end of loop over observations
     enddo

  else
     
     
!!will be similar except for get_ijk 
!!if not teom isis fill in 
!!should be used for other in-situ obs e.g. soundings/aircraft e.g.
     
  endif

! Release memory of local guess arrays
  call final_vars_

!! write information to diagnostic file
  if(conv_diagsave) then
    if(netcdf_diag) call nc_diag_write
    if(binary_diag .and.ii>0) then
       write(7)cvar,nchar,nrealdiag,ii,mype,nrealdiag
       write(7)cdiagbuf(1:ii),rdiagbuf(:,1:ii)
       deallocate(cdiagbuf,rdiagbuf)
    end if
  end if
!  
  return
  contains

  subroutine check_vars_ (proceed)
    use chemmod, only: naero_gocart_wrf,aeronames_gocart_wrf
  logical,intent(inout) :: proceed
  integer(i_kind) ivar, istatus
! Check to see if required guess fields are available
  call gsi_metguess_get ('var::ps', ivar, istatus )
  proceed=ivar>0
  call gsi_metguess_get ('var::z' , ivar, istatus )
  proceed=proceed.and.ivar>0
!
  if (wrf_mass_regional .and. laeroana_gocart) then
     do i=1,naero_gocart_wrf
        aeroname=upper2lower(aeronames_gocart_wrf(i))
        call gsi_chemguess_get ('var::'//trim(aeroname), ivar, istatus )
        if (ivar == 0) exit
     enddo
  endif

  proceed=proceed.and.ivar>0

  end subroutine check_vars_ 

  subroutine init_vars_

  real(r_kind),dimension(:,:  ),pointer:: rank2=>NULL()
  real(r_kind),dimension(:,:,:),pointer:: rank3=>NULL()
  character(len=5) :: varname
  integer(i_kind) ifld, istatus

! If require guess vars available, extract from bundle ...
  if(size(gsi_metguess_bundle)==nfldsig) then
!    get ps ...
     varname='ps'
     call gsi_bundlegetpointer(gsi_metguess_bundle(1),trim(varname),rank2,istatus)
     if (istatus==0) then
         if(allocated(ges_ps))then
            write(6,*) trim(myname), ': ', trim(varname), ' already incorrectly alloc '
            call stop2(999)
         endif
         allocate(ges_ps(size(rank2,1),size(rank2,2),nfldsig))
         ges_ps(:,:,1)=rank2
         do ifld=2,nfldsig
            call gsi_bundlegetpointer(gsi_metguess_bundle(ifld),trim(varname),rank2,istatus)
            ges_ps(:,:,ifld)=rank2
         enddo
     else
         write(6,*) trim(myname),': ', trim(varname), ' not found in met bundle, ier= ',istatus
         call stop2(999)
     endif
!    get z ...
     varname='z'
     call gsi_bundlegetpointer(gsi_metguess_bundle(1),trim(varname),rank2,istatus)
     if (istatus==0) then
         if(allocated(ges_z))then
            write(6,*) trim(myname), ': ', trim(varname), ' already incorrectly alloc '
            call stop2(999)
         endif
         allocate(ges_z(size(rank2,1),size(rank2,2),nfldsig))
         ges_z(:,:,1)=rank2
         do ifld=2,nfldsig
            call gsi_bundlegetpointer(gsi_metguess_bundle(ifld),trim(varname),rank2,istatus)
            ges_z(:,:,ifld)=rank2
         enddo
     else
         write(6,*) trim(myname),': ', trim(varname), ' not found in met bundle, ier= ',istatus
         call stop2(999)
     endif
!    get tv ...
     varname='tv'
     call gsi_bundlegetpointer(gsi_metguess_bundle(1),trim(varname),rank3,istatus)                   
     if (istatus==0) then
         if(allocated(ges_tv))then
            write(6,*) trim(myname), ': ', trim(varname), ' already incorrectly alloc '      
            call stop2(999)
         endif
         allocate(ges_tv(size(rank3,1),size(rank3,2),size(rank3,3),nfldsig))
         ges_tv(:,:,:,1)=rank3
         do ifld=2,nfldsig
            call gsi_bundlegetpointer(gsi_metguess_bundle(ifld),trim(varname),rank3,istatus)       
            ges_tv(:,:,:,ifld)=rank3
         enddo
     else
         write(6,*) trim(myname),': ', trim(varname), ' not found in met bundle, ier= ',istatus    
         call stop2(999)
     endif
  else
     write(6,*) trim(myname), ': inconsistent vector sizes (nfldsig,size(metguess_bundle) ',&
                 nfldsig,size(gsi_metguess_bundle)
     call stop2(999)
  endif
  end subroutine init_vars_

  subroutine init_netcdf_diag_
  character(len=80) string
  character(len=128) diag_conv_file
  integer(i_kind) ncd_fileid,ncd_nobs
  logical append_diag
  logical,parameter::verbose=.false. 
     write(string,900) jiter
900  format('conv_pm10_',i2.2,'.nc4')
     diag_conv_file=trim(dirname) // trim(string)

     inquire(file=diag_conv_file, exist=append_diag)

     if (append_diag) then
        call nc_diag_read_init(diag_conv_file,ncd_fileid)
        ncd_nobs = nc_diag_read_get_dim(ncd_fileid,'nobs')
        call nc_diag_read_close(diag_conv_file)

        if (ncd_nobs > 0) then
           if(verbose) print *,'file ' // trim(diag_conv_file) // ' exists.  Appending.  nobs,mype=',ncd_nobs,mype
        else
           if(verbose) print *,'file ' // trim(diag_conv_file) // ' exists but contains no obs.  Not appending. nobs,mype=',ncd_nobs,mype
           append_diag = .false. ! if there are no obs in existing file, then do not try to append
        endif
     end if

     call nc_diag_init(diag_conv_file, append=append_diag)

     if (.not. append_diag) then ! don't write headers on append - the module will break?
        call nc_diag_header("date_time",ianldate )
     endif
  end subroutine init_netcdf_diag_
  subroutine contents_binary_diag_
           cdiagbuf(ii)    = station_id         ! station id

           rdiagbuf(1,ii)  = ictype(ikx)        ! observation type

           rdiagbuf(2,ii)  = icsubtype(ikx)     ! observation subtype
           
           rdiagbuf(3,ii)  = data(ilate,i)      ! observation latitude (degrees)
           rdiagbuf(4,ii)  = data(ilone,i)      ! observation longitude (degrees)
           rdiagbuf(5,ii)  = data(ielev,i)      ! station elevation (meters)
           rdiagbuf(6,ii)  = ps_ges             ! observation pressure (hpa)
           rdiagbuf(7,ii)  = data(ielev,i)      ! observation height (meters)
           rdiagbuf(8,ii)  = dtime-time_offset  ! obs time (hours relative to analysis time)
           
           rdiagbuf(9,ii)  = zero !data(iqc,i)  input prepbufr qc or event mark
           rdiagbuf(10,ii) = zero !data(iqt,i)  setup qc or event mark (currently qtflg only)
           rdiagbuf(11,ii) = one                ! read_prepbufr data usage flag
           if(muse(i)) then
              rdiagbuf(12,ii) = one             ! analysis usage flag (1=use, -1=not used)
           else
              rdiagbuf(12,ii) = -one
           endif
           
           rdiagbuf(13,ii) = rwgt               ! nonlinear qc relative weight
           rdiagbuf(14,ii) = errinv_input       ! prepbufr inverse obs error (k**-1)
           rdiagbuf(15,ii) = errinv_adjst       ! read_prepbufr inverse obs error (k**-1)
           rdiagbuf(16,ii) = errinv_final       ! final inverse observation error (k**-1)
           
           rdiagbuf(17,ii) = data(iconc,i)       ! temperature observation (k)
           rdiagbuf(18,ii) = innov   ! obs-ges used in analysis (ugm^-3)
           rdiagbuf(19,ii) = innov   ! obs-ges w/o bias correction (ugm^-3) (future slot)

           idia=nrealdiag
           if (lobsdiagsave) then
              do jj=1,miter
                 idia=idia+1
                 if (obsdiags(i_pm10_ob_type,ibin)%tail%muse(jj)) then
                    rdiagbuf(idia,ii) = one
                 else
                    rdiagbuf(idia,ii) = -one
                 endif
              enddo
              
              do jj=1,miter+1
                 idia=idia+1
                 rdiagbuf(idia,ii) = obsdiags(i_pm10_ob_type,ibin)%tail%nldepart(jj)
              enddo

              do jj=1,miter
                 idia=idia+1
                 rdiagbuf(idia,ii) = obsdiags(i_pm10_ob_type,ibin)%tail%tldepart(jj)
              enddo

              do jj=1,miter
                 idia=idia+1
                 rdiagbuf(idia,ii) = obsdiags(i_pm10_ob_type,ibin)%tail%obssen(jj)
              enddo

           endif
  end subroutine contents_binary_diag_
  subroutine contents_netcdf_diag_
! Observation class
  character(7),parameter     :: obsclass = '   pm10'
  real(r_kind),dimension(miter) :: obsdiag_iuse
           call nc_diag_metadata("Station_ID",              station_id             )
           call nc_diag_metadata("Observation_Class",       obsclass               )
           call nc_diag_metadata("Observation_Type",        ictype(ikx)            )
           call nc_diag_metadata("Observation_Subtype",     icsubtype(ikx)         )
           call nc_diag_metadata("Latitude",                data(ilate,i)          )
           call nc_diag_metadata("Longitude",               data(ilone,i)          )
           call nc_diag_metadata("Station_Elevation",       data(ielev,i)          )
           call nc_diag_metadata("Pressure",                ps_ges                 )
           call nc_diag_metadata("Height",                  data(ielev,i)          )
           call nc_diag_metadata("Time",                    dtime-time_offset      )
           call nc_diag_metadata("Prep_QC_Mark",            zero                   )
           call nc_diag_metadata("Prep_Use_Flag",           one                    )
!          call nc_diag_metadata("Nonlinear_QC_Var_Jb",     var_jb                 )
           call nc_diag_metadata("Nonlinear_QC_Rel_Wgt",    rwgt                   )                 
           if(muse(i)) then
              call nc_diag_metadata("Analysis_Use_Flag",    one                    )
           else
              call nc_diag_metadata("Analysis_Use_Flag",    -one                   )              
           endif

           call nc_diag_metadata("Errinv_Input",            errinv_input           )
           call nc_diag_metadata("Errinv_Adjust",           errinv_adjst           )
           call nc_diag_metadata("Errinv_Final",            errinv_final           )

           call nc_diag_metadata("Observation",                   data(iconc,i)    )
           call nc_diag_metadata("Obs_Minus_Forecast_adjusted",   innov            )
           call nc_diag_metadata("Obs_Minus_Forecast_unadjusted", innov            )
 
           if (lobsdiagsave) then
              do jj=1,miter
                 if (obsdiags(i_pm10_ob_type,ibin)%tail%muse(jj)) then
                       obsdiag_iuse(jj) =  one
                 else
                       obsdiag_iuse(jj) = -one
                 endif
              enddo
   
              call nc_diag_data2d("ObsDiagSave_iuse",     obsdiag_iuse                             )
              call nc_diag_data2d("ObsDiagSave_nldepart", obsdiags(i_pm10_ob_type,ibin)%tail%nldepart )
              call nc_diag_data2d("ObsDiagSave_tldepart", obsdiags(i_pm10_ob_type,ibin)%tail%tldepart )
              call nc_diag_data2d("ObsDiagSave_obssen",   obsdiags(i_pm10_ob_type,ibin)%tail%obssen   )             
           endif
  end subroutine contents_netcdf_diag_

  subroutine final_vars_
    if(allocated(ges_tv)) deallocate(ges_tv)
    if(allocated(ges_pm10)) deallocate(ges_pm10)
    if(allocated(ges_z )) deallocate(ges_z )
    if(allocated(ges_ps)) deallocate(ges_ps)
  end subroutine final_vars_

end subroutine setuppm10