LCOV - code coverage report
Current view: top level - chemistry/aerosol - modal_aero_data.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 457 0.0 %
Date: 2025-01-13 21:54:50 Functions: 0 9 0.0 %

          Line data    Source code
       1             :       module modal_aero_data
       2             : 
       3             : !--------------------------------------------------------------
       4             : ! ... Basic aerosol mode parameters and arrays
       5             : !--------------------------------------------------------------
       6             :       use shr_kind_mod,    only: r8 => shr_kind_r8
       7             :       use constituents,    only: pcnst, cnst_mw, cnst_name, cnst_get_ind, cnst_set_convtran2, &
       8             :                                  cnst_set_spec_class, cnst_spec_class_aerosol, cnst_spec_class_undefined, &
       9             :                                  cnst_species_class, cnst_spec_class_gas
      10             :       use physics_buffer,  only: pbuf_add_field, dtype_r8
      11             :       use time_manager,    only: is_first_step
      12             :       use phys_control,    only: phys_getopts
      13             :       use infnan,          only: nan, assignment(=)
      14             :       use cam_logfile,     only: iulog
      15             :       use cam_abortutils,  only: endrun
      16             :       use spmd_utils,      only: masterproc
      17             :       use ppgrid,          only: pcols, pver, begchunk, endchunk
      18             :       use mo_tracname,     only: solsym
      19             :       use chem_mods,       only: gas_pcnst
      20             :       use radconstants,    only: nswbands, nlwbands
      21             :       use shr_const_mod,   only: pi => shr_const_pi
      22             :       use rad_constituents,only: rad_cnst_get_info, rad_cnst_get_aer_props, rad_cnst_get_mode_props
      23             :       use physics_buffer,  only: physics_buffer_desc, pbuf_get_chunk
      24             : 
      25             :       implicit none
      26             :       private
      27             : 
      28             :       public :: modal_aero_data_init
      29             :       public :: modal_aero_data_reg
      30             :       public :: qqcw_get_field
      31             : 
      32             :       integer, public, protected :: nsoa = 0
      33             :       integer, public, protected :: npoa = 0
      34             :       integer, public, protected :: nbc = 0
      35             :       integer, public, protected :: nspec_max = 0
      36             :       integer, public, protected :: ntot_amode = 0
      37             :       integer, public, protected :: nSeaSalt=0, nDust=0
      38             :       integer, public, protected :: nSO4=0, nNH4=0
      39             : 
      40             :       !
      41             :       ! definitions for aerosol chemical components
      42             :       !
      43             : 
      44             :       real(r8), public, protected, allocatable :: specmw_amode(:,:)
      45             :       character(len=16), public, protected, allocatable :: modename_amode(:)
      46             : 
      47             :       integer, public, protected, allocatable :: nspec_amode(:)
      48             : 
      49             :       character(len=20), public, protected :: cnst_name_cw( pcnst )
      50             : 
      51             :       !   input mprognum_amode, mdiagnum_amode, mprogsfc_amode, mcalcwater_amode
      52             :       integer, public, protected, allocatable :: mprognum_amode(:)
      53             :       integer, public, protected, allocatable :: mdiagnum_amode(:)
      54             :       integer, public, protected, allocatable :: mprogsfc_amode(:)
      55             :       integer, public, protected, allocatable :: mcalcwater_amode(:)
      56             : 
      57             :       !   input dgnum_amode, dgnumlo_amode, dgnumhi_amode (units = m)
      58             :       real(r8), public, protected, allocatable :: dgnum_amode(:)
      59             :       real(r8), public, protected, allocatable :: dgnumlo_amode(:)
      60             :       real(r8), public, protected, allocatable :: dgnumhi_amode(:)
      61             :       integer,  public, protected, allocatable :: mode_size_order(:)
      62             : 
      63             :       !   input sigmag_amode
      64             :       real(r8), public, protected, allocatable :: sigmag_amode(:)
      65             : 
      66             :       !   input crystalization and deliquescence points
      67             :       real(r8), allocatable :: rhcrystal_amode(:)
      68             :       real(r8), allocatable :: rhdeliques_amode(:)
      69             : 
      70             : 
      71             :       integer, public, protected, allocatable :: &
      72             :            lmassptr_amode( :, : ),   &
      73             :            lmassptrcw_amode( :, : ), &
      74             :            numptr_amode( : ),        &
      75             :            numptrcw_amode( : )
      76             : 
      77             :       real(r8), public, protected, allocatable :: &
      78             :            alnsg_amode( : ),              &
      79             :            voltonumb_amode( : ),          &
      80             :            voltonumblo_amode( : ),        &
      81             :            voltonumbhi_amode( : ),        &
      82             :            alnv2n_amode( : ),             &
      83             :            alnv2nlo_amode( : ),           &
      84             :            alnv2nhi_amode( : ),           &
      85             :            specdens_amode(:,:),   &
      86             :            spechygro(:,:)
      87             : 
      88             :       integer, public, protected, allocatable ::  &
      89             :            lptr_so4_a_amode(:),     lptr_so4_cw_amode(:), &
      90             :            lptr_msa_a_amode(:),     lptr_msa_cw_amode(:), &
      91             :            lptr_nh4_a_amode(:),     lptr_nh4_cw_amode(:), &
      92             :            lptr_no3_a_amode(:),     lptr_no3_cw_amode(:), &
      93             :            lptr_nacl_a_amode(:),    lptr_nacl_cw_amode(:),&
      94             :            lptr_dust_a_amode(:),    lptr_dust_cw_amode(:)
      95             : 
      96             :       integer, public, protected :: &
      97             :            modeptr_accum,  modeptr_aitken,                               &
      98             :            modeptr_ufine,  modeptr_coarse,                               &
      99             :            modeptr_pcarbon,                                              &
     100             :            modeptr_finedust,  modeptr_fineseas,                          &
     101             :            modeptr_coardust,  modeptr_coarseas, modeptr_stracoar
     102             : 
     103             :       !2D lptr variables added by RCE to access speciated species
     104             :       integer, public, protected, allocatable :: &
     105             :            lptr2_bc_a_amode(:,:),   lptr2_bc_cw_amode(:,:), &
     106             :            lptr2_pom_a_amode(:,:),  lptr2_pom_cw_amode(:,:), &
     107             :            lptr2_soa_a_amode(:,:),  lptr2_soa_cw_amode(:,:), &
     108             :            lptr2_soa_g_amode(:)
     109             : 
     110             :       real(r8), public, protected :: specmw_so4_amode
     111             : 
     112             :       logical, public, protected :: soa_multi_species = .false.
     113             : 
     114             :       character(len=16), allocatable :: xname_massptr(:,:)     ! names of species in each mode
     115             :       character(len=16), allocatable :: xname_massptrcw(:,:)   ! names of cloud-borne species in each mode
     116             : 
     117             :       complex(r8), allocatable :: &
     118             :            specrefndxsw( :,:,: ), &
     119             :            specrefndxlw( :,:,: )
     120             : 
     121             :       character(len=8), allocatable :: &
     122             :            aodvisname(: ), &
     123             :            ssavisname(: )
     124             :       character(len=48), allocatable :: &
     125             :            aodvislongname(: ), &
     126             :            ssavislongname(: )
     127             : 
     128             :       character(len=8), allocatable :: &
     129             :            fnactname(: ), &
     130             :            fmactname(: ), &
     131             :            nactname(: )
     132             : 
     133             :       character(len=48), allocatable :: &
     134             :            fnactlongname(: ), &
     135             :            fmactlongname(: ), &
     136             :            nactlongname(: )
     137             : 
     138             : 
     139             :       !   threshold for reporting negatives from subr qneg3
     140             :       real(r8) :: qneg3_worst_thresh_amode(pcnst)
     141             : 
     142             :       integer :: qqcw(pcnst)=-1 ! Remaps modal_aero indices into pbuf
     143             : 
     144             :       logical :: convproc_do_aer
     145             :       logical :: cam_do_aero_conv = .true.
     146             :     contains
     147             : 
     148             : !--------------------------------------------------------------
     149             : !--------------------------------------------------------------
     150           0 :   subroutine modal_aero_data_reg
     151             : 
     152             :     character(len=6) :: xname_numptr, xname_numptrcw
     153             :     character(len=1) :: modechr
     154             :     integer :: m, l, iptr,i, idx
     155             :     character(len=3) :: trnum       ! used to hold mode number (as characters)
     156             : 
     157             :     character(len=32) :: spec_name, mode_type
     158             :     character(len=1) :: modestr
     159             : 
     160           0 :     call rad_cnst_get_info( 0, nmodes=ntot_amode )
     161           0 :     allocate( nspec_amode(ntot_amode) )
     162           0 :     allocate( numptr_amode(ntot_amode) )
     163           0 :     allocate( numptrcw_amode(ntot_amode) )
     164           0 :     allocate(modename_amode(ntot_amode))
     165           0 :     allocate(mprognum_amode(ntot_amode))
     166           0 :     allocate(mdiagnum_amode(ntot_amode))
     167           0 :     allocate(mprogsfc_amode(ntot_amode))
     168           0 :     allocate(mcalcwater_amode(ntot_amode))
     169           0 :     mprognum_amode(:) = 1
     170           0 :     mdiagnum_amode(:) = 0
     171           0 :     mprogsfc_amode(:) = 0
     172           0 :     if (ntot_amode==7) then
     173           0 :        mcalcwater_amode(:) = 1
     174             :     else
     175           0 :        mcalcwater_amode(:) = 0
     176             :     endif
     177           0 :     allocate(dgnum_amode(ntot_amode))
     178           0 :     allocate(mode_size_order(ntot_amode))
     179           0 :     allocate(dgnumlo_amode(ntot_amode))
     180           0 :     allocate(dgnumhi_amode(ntot_amode))
     181           0 :     allocate(sigmag_amode(ntot_amode))
     182           0 :     allocate(rhcrystal_amode(ntot_amode))
     183           0 :     allocate(rhdeliques_amode(ntot_amode))
     184             :     allocate( &
     185           0 :          alnsg_amode( ntot_amode ),              &   !
     186           0 :          voltonumb_amode( ntot_amode ),          &   !
     187           0 :          voltonumblo_amode( ntot_amode ),        &   !
     188           0 :          voltonumbhi_amode( ntot_amode ),        &   !
     189           0 :          alnv2n_amode( ntot_amode ),             &   !
     190           0 :          alnv2nlo_amode( ntot_amode ),           &   !
     191           0 :          alnv2nhi_amode( ntot_amode ),           &   !
     192           0 :          aodvisname(ntot_amode ), &
     193           0 :          ssavisname(ntot_amode ), &
     194           0 :          fnactname(ntot_amode ), &
     195           0 :          fmactname(ntot_amode ), &
     196           0 :          nactname(ntot_amode ), &
     197           0 :          fnactlongname(ntot_amode ), &
     198           0 :          fmactlongname(ntot_amode ), &
     199           0 :          nactlongname(ntot_amode ), &
     200           0 :          lptr_so4_a_amode(ntot_amode), lptr_so4_cw_amode(ntot_amode), &
     201           0 :          lptr_msa_a_amode(ntot_amode), lptr_msa_cw_amode(ntot_amode), &
     202           0 :          lptr_nh4_a_amode(ntot_amode), lptr_nh4_cw_amode(ntot_amode), &
     203           0 :          lptr_nacl_a_amode(ntot_amode), lptr_nacl_cw_amode(ntot_amode), &
     204           0 :          lptr_dust_a_amode(ntot_amode), lptr_dust_cw_amode(ntot_amode), &
     205           0 :          lptr_no3_a_amode(ntot_amode), lptr_no3_cw_amode(ntot_amode) &
     206           0 :     )
     207             : 
     208             :     allocate( &
     209           0 :          aodvislongname(ntot_amode ), &
     210           0 :          ssavislongname(ntot_amode ) &
     211           0 :     )
     212             : 
     213           0 :     do m = 1, ntot_amode
     214           0 :        call rad_cnst_get_info(0, m, mode_type=mode_type, nspec=nspec_amode(m))
     215           0 :        modename_amode(m) = mode_type
     216             :        ! count number of soa, poa, and bc bins in mode 1
     217           0 :        if (m==1) then
     218           0 :           do l = 1, nspec_amode(m)
     219           0 :              call rad_cnst_get_info(0, m, l, spec_name=spec_name )
     220           0 :              if (spec_name(:3) == 'soa') nsoa=nsoa+1
     221           0 :              if (spec_name(:3) == 'pom') npoa=npoa+1
     222           0 :              if (spec_name(:2) == 'bc' ) nbc =nbc +1
     223             :           enddo
     224             :        endif
     225             :     enddo
     226             : 
     227           0 :     soa_multi_species = nsoa > 1
     228             : 
     229           0 :     nspec_max = maxval( nspec_amode )
     230             : 
     231           0 :     allocate ( specdens_amode(nspec_max,ntot_amode) )
     232           0 :     allocate ( spechygro(nspec_max,ntot_amode) )
     233           0 :     allocate ( specmw_amode(nspec_max,ntot_amode) )
     234           0 :     allocate ( xname_massptr(nspec_max,ntot_amode) )
     235           0 :     allocate ( xname_massptrcw(nspec_max,ntot_amode) )
     236           0 :     specmw_amode = nan
     237           0 :     xname_massptr(:,:) = ' '
     238           0 :     xname_massptrcw(:,:) = ' '
     239             : 
     240           0 :     do m = 1, ntot_amode
     241           0 :        do l = 1, nspec_amode(m)
     242           0 :           call rad_cnst_get_info(0, m, l, spec_name=spec_name )
     243           0 :           xname_massptr(l,m) = spec_name
     244           0 :           write(modestr,'(I1)') m
     245           0 :           idx = index( xname_massptr(l,m), '_' )
     246           0 :           xname_massptrcw(l,m) = xname_massptr(l,m)(:idx-1)//'_c'//modestr
     247           0 :           if (xname_massptr(l,m)(:3) == 'dst') nDust=nDust+1
     248           0 :           if (xname_massptr(l,m)(:3) == 'ncl') nSeaSalt=nSeaSalt+1
     249           0 :           if (xname_massptr(l,m)(:3) == 'nh4') nNH4=nNH4+1
     250           0 :           if (xname_massptr(l,m)(:3) == 'so4') nSO4=nSO4+1
     251             :        enddo
     252             :     enddo
     253             : 
     254             :     allocate( &
     255           0 :          lmassptr_amode( nspec_max, ntot_amode ),&
     256           0 :          lmassptrcw_amode( nspec_max, ntot_amode ),&
     257           0 :          lptr2_pom_a_amode(ntot_amode,npoa),  lptr2_pom_cw_amode(ntot_amode,npoa), &
     258           0 :          lptr2_soa_a_amode(ntot_amode,nsoa),  lptr2_soa_cw_amode(ntot_amode,nsoa), &
     259           0 :          lptr2_bc_a_amode(ntot_amode,nbc),   lptr2_bc_cw_amode(ntot_amode,nbc), &
     260           0 :          lptr2_soa_g_amode(nsoa) &
     261           0 :          )
     262           0 :     lmassptr_amode = -999999
     263           0 :     lptr2_soa_g_amode = -999999
     264             : 
     265           0 :     allocate( specrefndxsw(nswbands,nspec_max,ntot_amode ) )
     266           0 :     allocate( specrefndxlw(nlwbands,nspec_max,ntot_amode) )
     267             : 
     268           0 :     do m = 1, ntot_amode
     269           0 :        if(nspec_amode(m).gt.nspec_max)then
     270           0 :           write(iulog,*)'modal_aero_data_reg: nspec_amode(m).gt.nspec_max '
     271           0 :           write(iulog,*)'modal_aero_data_reg: m,nspec_amode(m), nspec_max=',m, nspec_amode(m), nspec_max
     272           0 :           call endrun('modal_aero_data_reg: nspec_amode(m).gt.nspec_max ')
     273             :        end if
     274             :     end do
     275             : 
     276           0 :     call phys_getopts(convproc_do_aer_out = convproc_do_aer)
     277           0 :     if (convproc_do_aer) cam_do_aero_conv = .false.
     278             : 
     279           0 :     do m = 1, ntot_amode
     280           0 :        write(modechr,fmt='(I1)') m
     281           0 :        xname_numptr = 'num_a'//modechr
     282           0 :        xname_numptrcw  = 'num_c'//modechr
     283             : 
     284           0 :        if (masterproc) then
     285           0 :           write(iulog,9231) m, modename_amode(m)
     286             :           write(iulog,9232)                                          &
     287           0 :                'nspec                       ',                         &
     288           0 :                nspec_amode(m)
     289             :           write(iulog,9232)                                          &
     290           0 :                'mprognum, mdiagnum, mprogsfc',                         &
     291           0 :                mprognum_amode(m), mdiagnum_amode(m), mprogsfc_amode(m)
     292             :           write(iulog,9232)                                          &
     293           0 :                'mcalcwater                  ',                         &
     294           0 :                mcalcwater_amode(m)
     295             :        endif
     296             : 
     297             :        !    define species to hold interstitial & activated number
     298             :        call search_list_of_names(                                      &
     299           0 :             xname_numptr, numptr_amode(m), cnst_name, pcnst )
     300           0 :        if (numptr_amode(m) .le. 0) then
     301           0 :           write(iulog,9061) 'xname_numptr', xname_numptr, m
     302           0 :           call endrun('modal_aero_data_reg: numptr_amode(m) .le. 0')
     303             :        end if
     304           0 :        if (numptr_amode(m) .gt. pcnst) then
     305           0 :           write(iulog,9061) 'numptr_amode', numptr_amode(m), m
     306           0 :           write(iulog,9061) 'xname_numptr', xname_numptr, m
     307           0 :           call endrun('modal_aero_data_reg: numptr_amode(m) .gt. pcnst')
     308             :        end if
     309             : 
     310           0 :        call cnst_set_spec_class(numptr_amode(m), cnst_spec_class_aerosol)
     311           0 :        call cnst_set_convtran2(numptr_amode(m), cam_do_aero_conv)
     312             : 
     313           0 :        numptrcw_amode(m) = numptr_amode(m)  !use the same index for Q and QQCW arrays
     314           0 :        if (numptrcw_amode(m) .le. 0) then
     315           0 :           write(iulog,9061) 'xname_numptrcw', xname_numptrcw, m
     316           0 :           call endrun('modal_aero_data_reg: numptrcw_amode(m) .le. 0')
     317             :        end if
     318           0 :        if (numptrcw_amode(m) .gt. pcnst) then
     319           0 :           write(iulog,9061) 'numptrcw_amode', numptrcw_amode(m), m
     320           0 :           write(iulog,9061) 'xname_numptrcw', xname_numptrcw, m
     321           0 :           call endrun('modal_aero_data_reg: numptrcw_amode(m) .gt. pcnst')
     322             :        end if
     323             : 
     324           0 :        call pbuf_add_field(xname_numptrcw,'global',dtype_r8,(/pcols,pver/),iptr)
     325           0 :        call qqcw_set_ptr(numptrcw_amode(m),iptr)
     326             : 
     327             :        !   output mode information
     328           0 :        if ( masterproc ) then
     329           0 :           write(iulog,9233) 'numptr         ',                           &
     330           0 :                numptr_amode(m), xname_numptr
     331           0 :           write(iulog,9233) 'numptrcw       ',                           &
     332           0 :                numptrcw_amode(m), xname_numptrcw
     333             :        end if
     334             : 
     335             :        !   define the chemical species for the mode
     336           0 :        do l = 1, nspec_amode(m)
     337             : 
     338             :           call search_list_of_names(                                  &
     339           0 :                xname_massptr(l,m), lmassptr_amode(l,m), cnst_name, pcnst )
     340           0 :           if (lmassptr_amode(l,m) .le. 0) then
     341           0 :              write(iulog,9062) 'xname_massptr', xname_massptr(l,m), l, m
     342           0 :              write(iulog,'(10(a8,1x))')(cnst_name(i),i=1,pcnst)
     343           0 :              call endrun('modal_aero_data_reg: lmassptr_amode(l,m) .le. 0')
     344             :           end if
     345           0 :           call cnst_set_spec_class(lmassptr_amode(l,m), cnst_spec_class_aerosol)
     346           0 :           call cnst_set_convtran2(lmassptr_amode(l,m), cam_do_aero_conv)
     347             : 
     348           0 :           lmassptrcw_amode(l,m) = lmassptr_amode(l,m)  !use the same index for Q and QQCW arrays
     349           0 :           if (lmassptrcw_amode(l,m) .le. 0) then
     350           0 :              write(iulog,9062) 'xname_massptrcw', xname_massptrcw(l,m), l, m
     351           0 :              call endrun('modal_aero_data_reg: lmassptrcw_amode(l,m) .le. 0')
     352             :           end if
     353           0 :           call pbuf_add_field(xname_massptrcw(l,m),'global',dtype_r8,(/pcols,pver/),iptr)
     354           0 :           call qqcw_set_ptr(lmassptrcw_amode(l,m), iptr)
     355             : 
     356           0 :           if ( masterproc ) then
     357           0 :              write(iulog,9236) 'spec, massptr  ', l,                    &
     358           0 :                   lmassptr_amode(l,m), xname_massptr(l,m)
     359           0 :              write(iulog,9236) 'spec, massptrcw', l,                    &
     360           0 :                   lmassptrcw_amode(l,m), xname_massptrcw(l,m)
     361             :           end if
     362             : 
     363             :        end do
     364             : 
     365             :        !   set names for aodvis and ssavis
     366           0 :        write(unit=trnum,fmt='(i3)') m+100
     367             : 
     368           0 :        aodvisname(m) = 'AODVIS'//trnum(2:3)
     369           0 :        aodvislongname(m) = 'Aerosol optical depth for mode '//trnum(2:3)
     370           0 :        ssavisname(m) = 'SSAVIS'//trnum(2:3)
     371           0 :        ssavislongname(m) = 'Single-scatter albedo for mode '//trnum(2:3)
     372           0 :        fnactname(m) = 'FNACT'//trnum(2:3)
     373           0 :        fnactlongname(m) = 'Number faction activated for mode '//trnum(2:3)
     374           0 :        fmactname(m) = 'FMACT'//trnum(2:3)
     375           0 :        fmactlongname(m) = 'Fraction mass activated for mode'//trnum(2:3)
     376             :     end do
     377             : 
     378             :     ! At this point, species_class is either undefined or aerosol.
     379             :     ! For the "chemistry species" set the undefined ones to gas,
     380             :     ! and leave the aerosol ones as is
     381             :     do i = 1, gas_pcnst
     382             :        call cnst_get_ind(solsym(i), idx, abort=.false.)
     383             :        if (idx > 0) then
     384             :           if (cnst_species_class(idx) == cnst_spec_class_undefined) then
     385             :              call cnst_set_spec_class(idx, cnst_spec_class_gas)
     386             :           end if
     387             :        end if
     388             :     end do
     389             : 
     390           0 :        if (masterproc) write(iulog,9230)
     391             : 9230   format( // '*** init_aer_modes mode definitions' )
     392             : 9231   format( 'mode = ', i4, ' = "', a, '"' )
     393             : 9232   format( 4x, a, 4(1x, i5 ) )
     394             : 9233   format( 4x, a15, 4x, i7, '="', a, '"' )
     395             : 9236   format( 4x, a15, i4, i7, '="', a, '"' )
     396             : 9061   format( '*** subr modesmodal_aero_data_reg - bad ', a /                   &
     397             :             5x, 'name, m =  ', a, 5x, i5 )
     398             : 9062   format( '*** subr modal_aero_data_reg - bad ', a /                       &
     399             :             5x, 'name, l, m =  ', a, 5x, 2i5 )
     400           0 :  end subroutine modal_aero_data_reg
     401             : 
     402             : !--------------------------------------------------------------
     403             : !--------------------------------------------------------------
     404           0 :     subroutine modal_aero_data_init(pbuf2d)
     405             : 
     406             :        type(physics_buffer_desc), pointer :: pbuf2d(:,:)
     407             : 
     408             :        !--------------------------------------------------------------
     409             :        ! ... local variables
     410             :        !--------------------------------------------------------------
     411             :        integer :: l, m, i, lchnk, tmp
     412             : 
     413             :        integer :: qArrIndex
     414           0 :        complex(r8), pointer  :: refindex_aer_sw(:), &
     415           0 :             refindex_aer_lw(:)
     416           0 :        real(r8), pointer :: qqcw(:,:)
     417             :        real(r8), parameter :: huge_r8 = huge(1._r8)
     418             :        character(len=*), parameter :: routine='modal_aero_initialize'
     419             :        character(len=32) :: spec_type
     420             :        integer :: soa_ndx
     421             : 
     422             :        !-----------------------------------------------------------------------
     423             : 
     424             :        ! Mode specific properties.
     425           0 :        do m = 1, ntot_amode
     426             :           call rad_cnst_get_mode_props(0, m, &
     427           0 :              sigmag=sigmag_amode(m), dgnum=dgnum_amode(m), dgnumlo=dgnumlo_amode(m), &
     428           0 :              dgnumhi=dgnumhi_amode(m), rhcrystal=rhcrystal_amode(m), rhdeliques=rhdeliques_amode(m))
     429             : 
     430           0 :           mode_size_order(m) = m
     431             : 
     432             :           !   compute frequently used parameters: ln(sigmag),
     433             :           !   volume-to-number and volume-to-surface conversions, ...
     434           0 :           alnsg_amode(m) = log( sigmag_amode(m) )
     435             : 
     436           0 :           voltonumb_amode(m) = 1._r8 / ( (pi/6._r8)*                            &
     437           0 :              (dgnum_amode(m)**3._r8)*exp(4.5_r8*alnsg_amode(m)**2._r8) )
     438           0 :           voltonumblo_amode(m) = 1._r8 / ( (pi/6._r8)*                          &
     439           0 :              (dgnumlo_amode(m)**3._r8)*exp(4.5_r8*alnsg_amode(m)**2._r8) )
     440           0 :           voltonumbhi_amode(m) = 1._r8 / ( (pi/6._r8)*                          &
     441           0 :              (dgnumhi_amode(m)**3._r8)*exp(4.5_r8*alnsg_amode(m)**2._r8) )
     442             : 
     443           0 :           alnv2n_amode(m)   = log( voltonumb_amode(m) )
     444           0 :           alnv2nlo_amode(m) = log( voltonumblo_amode(m) )
     445           0 :           alnv2nhi_amode(m) = log( voltonumbhi_amode(m) )
     446             : 
     447             :        end do
     448             : 
     449           0 :        do i = 1, ntot_amode-1 ! order from largest to smallest
     450           0 :           do m = 2, ntot_amode
     451           0 :              if (dgnum_amode(mode_size_order(m-1))<dgnum_amode(mode_size_order(m))) then
     452           0 :                 tmp = mode_size_order(m-1)
     453           0 :                 mode_size_order(m-1)= mode_size_order(m)
     454           0 :                 mode_size_order(m) = tmp
     455             :              endif
     456             :           enddo
     457             :        enddo
     458             : 
     459           0 :        lptr2_soa_g_amode(:) = -1
     460           0 :        soa_ndx = 0
     461           0 :        do i = 1, pcnst
     462           0 :           if (cnst_name(i)(:4) == 'SOAG' .and. cnst_name(i)(:5) /= 'SOAGX') then
     463           0 :              soa_ndx = soa_ndx+1
     464           0 :              lptr2_soa_g_amode(soa_ndx) = i
     465             :           endif
     466             :        enddo
     467           0 :        if (.not.any(lptr2_soa_g_amode>0)) call endrun('modal_aero_data_init: lptr2_soa_g_amode is not set properly')
     468             :        ! Properties of mode specie types.
     469             : 
     470             :        !     values from Koepke, Hess, Schult and Shettle, Global Aerosol Data Set
     471             :        !     Report #243, Max-Planck Institute for Meteorology, 1997a
     472             :        !     See also Hess, Koepke and Schult, Optical Properties of Aerosols and Clouds (OPAC)
     473             :        !     BAMS, 1998.
     474             : 
     475             :        !      specrefndxsw(:ntot_aspectype)     = (/ (1.53,  0.01),   (1.53,  0.01),  (1.53,  0.01), &
     476             :        !                                           (1.55,  0.01),   (1.55,  0.01),  (1.90, 0.60), &
     477             :        !                                           (1.50, 1.0e-8), (1.50, 0.005) /)
     478             :        !      specrefndxlw(:ntot_aspectype)   = (/ (2.0, 0.5),   (2.0, 0.5), (2.0, 0.5), &
     479             :        !                                           (1.7, 0.5),   (1.7, 0.5), (2.22, 0.73), &
     480             :        !                                           (1.50, 0.02), (2.6, 0.6) /)
     481             :        !     get refractive indices from phys_prop files
     482             : 
     483             :        ! The following use of the rad_constituent interfaces makes the assumption that the
     484             :        ! prognostic modes are used in the mode climate (index 0) list.
     485             : 
     486           0 :        if (masterproc) write(iulog,9210)
     487           0 :        do m = 1, ntot_amode
     488           0 :           do l = 1, nspec_amode(m)
     489           0 :              qArrIndex =  lmassptr_amode(l,m)     !index of the species in the state%q array
     490             :              call rad_cnst_get_aer_props(0, m, l , &
     491             :                   refindex_aer_sw=refindex_aer_sw, &
     492             :                   refindex_aer_lw=refindex_aer_lw, &
     493           0 :                   density_aer=specdens_amode(l,m), &
     494           0 :                   hygro_aer=spechygro(l,m)         )
     495             : 
     496           0 :                  specmw_amode(l,m) = cnst_mw(qArrIndex)
     497             : 
     498           0 :              if(masterproc) then
     499           0 :                 write(iulog,9212) '        name : ', cnst_name(qArrIndex)
     500           0 :                 write(iulog,9213) ' density, MW : ', specdens_amode(l,m), specmw_amode(l,m)
     501           0 :                 write(iulog,9213) '       hygro : ', spechygro(l,m)
     502             :              endif
     503           0 :              do i=1,nswbands
     504           0 :                 specrefndxsw(i,l,m)=refindex_aer_sw(i)
     505           0 :                 if(masterproc) write(iulog,9213) 'ref index sw    ', (specrefndxsw(i,l,m))
     506             :              end do
     507           0 :              do i=1,nlwbands
     508           0 :                 specrefndxlw(i,l,m)=refindex_aer_lw(i)
     509           0 :                 if(masterproc) write(iulog,9213) 'ref index ir    ', (specrefndxlw(i,l,m))
     510             :              end do
     511             : 
     512             :           enddo
     513             :        enddo
     514             : 
     515             : 9210   format( // '*** init_aer_modes aerosol species-types' )
     516             : 9211   format( 'spectype =', i4)
     517             : 9212   format( 4x, a, 3x, '"', a, '"' )
     518             : 9213   format( 4x, a, 5(1pe14.5) )
     519             : 
     520             :        !   set cnst_name_cw
     521           0 :        call initaermodes_set_cnstnamecw()
     522             : 
     523             : 
     524             :        !
     525             :        !   set the lptr_so4_a_amode(m), lptr_so4_cw_amode(m), ...
     526             :        !
     527           0 :        call initaermodes_setspecptrs
     528             : 
     529             :        !
     530             :        !   set threshold for reporting negatives from subr qneg3
     531             :        !   for aerosol number species set this to
     532             :        !      1e3 #/kg ~= 1e-3 #/cm3 for accum, aitken, pcarbon, ufine modes
     533             :        !      3e1 #/kg ~= 3e-5 #/cm3 for fineseas and finedust modes
     534             :        !      1e0 #/kg ~= 1e-6 #/cm3 for other modes which are coarse
     535             :        !   for other species, set this to zero so that it will be ignored
     536             :        !      by qneg3
     537             :        !
     538           0 :        if ( masterproc ) write(iulog,'(/a)') &
     539           0 :             'mode, modename_amode, qneg3_worst_thresh_amode'
     540           0 :        qneg3_worst_thresh_amode(:) = 0.0_r8
     541           0 :        do m = 1, ntot_amode
     542           0 :           l = numptr_amode(m)
     543           0 :           if ((l <= 0) .or. (l > pcnst)) cycle
     544             : 
     545           0 :           if      (m == modeptr_accum) then
     546           0 :              qneg3_worst_thresh_amode(l) = 1.0e3_r8
     547           0 :           else if (m == modeptr_aitken) then
     548           0 :              qneg3_worst_thresh_amode(l) = 1.0e3_r8
     549           0 :           else if (m == modeptr_pcarbon) then
     550           0 :              qneg3_worst_thresh_amode(l) = 1.0e3_r8
     551           0 :           else if (m == modeptr_ufine) then
     552           0 :              qneg3_worst_thresh_amode(l) = 1.0e3_r8
     553             : 
     554           0 :           else if (m == modeptr_fineseas) then
     555           0 :              qneg3_worst_thresh_amode(l) = 3.0e1_r8
     556           0 :           else if (m == modeptr_finedust) then
     557           0 :              qneg3_worst_thresh_amode(l) = 3.0e1_r8
     558             : 
     559             :           else
     560           0 :              qneg3_worst_thresh_amode(l) = 1.0e0_r8
     561             :           end if
     562             : 
     563           0 :           if ( masterproc ) write(iulog,'(i3,2x,a,1p,e12.3)') &
     564           0 :                m, modename_amode(m), qneg3_worst_thresh_amode(l)
     565             :        end do
     566             : 
     567           0 :        if (is_first_step()) then
     568             :           ! initialize cloud bourne constituents in physics buffer
     569             : 
     570           0 :           do i = 1, pcnst
     571           0 :              do lchnk = begchunk, endchunk
     572           0 :                 qqcw => qqcw_get_field(pbuf_get_chunk(pbuf2d,lchnk), i, lchnk, .true.)
     573           0 :                 if (associated(qqcw)) then
     574           0 :                    qqcw = 1.e-38_r8
     575             :                 end if
     576             :              end do
     577             :           end do
     578             :        end if
     579             : 
     580           0 :     end subroutine modal_aero_data_init
     581             : 
     582             : !--------------------------------------------------------------
     583             : !--------------------------------------------------------------
     584           0 :         subroutine qqcw_set_ptr(index, iptr)
     585             :           use cam_abortutils, only : endrun
     586             : 
     587             : 
     588             :           integer, intent(in) :: index, iptr
     589             : 
     590           0 :           if(index>0 .and. index <= pcnst ) then
     591           0 :              qqcw(index)=iptr
     592             :           else
     593           0 :              call endrun('qqcw_set_ptr: attempting to set qqcw pointer already defined')
     594             :           end if
     595           0 :         end subroutine qqcw_set_ptr
     596             : 
     597             : !--------------------------------------------------------------
     598             : !--------------------------------------------------------------
     599           0 :         function qqcw_get_field(pbuf, index, lchnk, errorhandle)
     600             :           use cam_abortutils, only : endrun
     601             :           use physics_buffer, only : physics_buffer_desc, pbuf_get_field
     602             : 
     603             :           integer, intent(in) :: index, lchnk
     604             :           real(r8), pointer :: qqcw_get_field(:,:)
     605             :           logical, optional :: errorhandle
     606             :           type(physics_buffer_desc), pointer :: pbuf(:)
     607             : 
     608             :           logical :: error
     609             : 
     610           0 :           nullify(qqcw_get_field)
     611           0 :           error = .false.
     612           0 :           if (index>0 .and. index <= pcnst) then
     613           0 :              if (qqcw(index)>0) then
     614             :                 call pbuf_get_field(pbuf, qqcw(index), qqcw_get_field)
     615             :              else
     616             :                 error = .true.
     617             :              endif
     618             :           else
     619             :              error = .true.
     620             :           end if
     621             : 
     622           0 :           if (error .and. .not. present(errorhandle)) then
     623           0 :              call endrun('qqcw_get_field: attempt to access undefined qqcw')
     624             :           end if
     625             : 
     626           0 :         end function qqcw_get_field
     627             : 
     628             : !----------------------------------------------------------------
     629             : !
     630             : !   nspec_max = maximum allowable number of chemical species
     631             : !       in each aerosol mode
     632             : !
     633             : !   ntot_amode = number of aerosol modes
     634             : !   ( ntot_amode_gchm = number of aerosol modes in gchm
     635             : !     ntot_amode_ccm2 = number of aerosol modes to be made known to ccm2
     636             : !       These are temporary until multi-mode activation scavenging is going.
     637             : !       Until then, ntot_amode is set to either ntot_amode_gchm or
     638             : !       ntot_amode_ccm2 depending on which code is active )
     639             : !
     640             : !   msectional - if positive, moving-center sectional code is utilized,
     641             : !       and each mode is actually a section.
     642             : !   msectional_concinit - if positive, special code is used to initialize
     643             : !       the mixing ratios of all the sections.
     644             : !
     645             : !   nspec_amode(m) = number of chemical species in aerosol mode m
     646             : !   nspec_amode_ccm2(m) = . . .  while in ccm2 code
     647             : !   nspec_amode_gchm(m) = . . .  while in gchm code
     648             : !   nspec_amode_nontracer(m) = number of "non-tracer" chemical
     649             : !       species while in gchm code
     650             : !   lspectype_amode(l,m) = species type/i.d. for chemical species l
     651             : !       in aerosol mode m.  (1=sulfate, others to be defined)
     652             : !   lmassptr_amode(l,m) = gchm r-array index for the mixing ratio
     653             : !       (moles-x/mole-air) for chemical species l in aerosol mode m
     654             : !       that is in clear air or interstitial air (but not in cloud water)
     655             : !   lmassptrcw_amode(l,m) = gchm r-array index for the mixing ratio
     656             : !       (moles-x/mole-air) for chemical species l in aerosol mode m
     657             : !       that is currently bound/dissolved in cloud water
     658             : !   lwaterptr_amode(m) = gchm r-array index for the mixing ratio
     659             : !       (moles-water/mole-air) for water associated with aerosol mode m
     660             : !       that is in clear air or interstitial air
     661             : !   lkohlercptr_amode(m) = gchm r-array index for the kohler "c" parameter
     662             : !       for aerosol mode m.  This is defined on a per-dry-particle-mass basis:
     663             : !           c = r(i,j,k,lkohlercptr_amode) * [rhodry * (4*pi/3) * rdry^3]
     664             : !   numptr_amode(m) = gchm r-array index for the number mixing ratio
     665             : !       (particles/mole-air) for aerosol mode m that is in clear air or
     666             : !       interstitial are (but not in cloud water).  If zero or negative,
     667             : !       then number is not being simulated.
     668             : !   ( numptr_amode_gchm(m) = same thing but for within gchm
     669             : !     numptr_amode_ccm2(m) = same thing but for within ccm2
     670             : !       These are temporary, to allow testing number in gchm before ccm2 )
     671             : !   numptrcw_amode(m) = gchm r-array index for the number mixing ratio
     672             : !       (particles/mole-air) for aerosol mode m
     673             : !       that is currently bound/dissolved in cloud water
     674             : !   lsfcptr_amode(m) = gchm r-array index for the surface area mixing ratio
     675             : !       (cm^2/mole-air) for aerosol mode m that is in clear air or
     676             : !       interstitial are (but not in cloud water).  If zero or negative,
     677             : !       then surface area is not being simulated.
     678             : !   lsfcptrcw_amode(m) = gchm r-array index for the surface area mixing ratio
     679             : !       (cm^2/mole-air) for aerosol mode m that is currently
     680             : !       bound/dissolved in cloud water.
     681             : !   lsigptr_amode(m) = gchm r-array index for sigmag for aerosol mode m
     682             : !       that is in clear air or interstitial are (but not in cloud water).
     683             : !       If zero or negative, then the constant sigmag_amode(m) is used.
     684             : !   lsigptrcw_amode(m) = gchm r-array index for sigmag for aerosol mode m
     685             : !       that is currently bound/dissolved in cloud water.
     686             : !       If zero or negative, then the constant sigmag_amode(m) is used.
     687             : !   lsigptrac_amode(m) = gchm r-array index for sigmag for aerosol mode m
     688             : !       for combined clear-air/interstial plus bound/dissolved in cloud water.
     689             : !       If zero or negative, then the constant sigmag_amode(m) is used.
     690             : !
     691             : !   dgnum_amode(m) = geometric dry mean diameter (m) of the number
     692             : !       distribution for aerosol mode m.
     693             : !       (Only used when numptr_amode(m) is zero or negative.)
     694             : !   dgnumlo_amode(m), dgnumhi_amode(m) = lower and upper limits on the
     695             : !       geometric dry mean diameter (m) of the number distribution
     696             : !       (Used when mprognum_amode>0, to limit dgnum to reasonable values)
     697             : !   sigmag_amode(m) = geometric standard deviation for aerosol mode m
     698             : !   sigmaglo_amode(m), sigmaghi_amode(m) = lower and upper limits on the
     699             : !       geometric standard deviation of the number distribution
     700             : !       (Used when mprogsfc_amode>0, to limit sigmag to reasonable values)
     701             : !   alnsg_amode(m) = alog( sigmag_amode(m) )
     702             : !   alnsglo_amode(m), alnsghi_amode(m) = alog( sigmaglo/hi_amode(m) )
     703             : !   voltonumb_amode(m) = ratio of number to volume for mode m
     704             : !   voltonumblo_amode(m), voltonumbhi_amode(m) = ratio of number to volume
     705             : !       when dgnum = dgnumlo_amode or dgnumhi_amode, respectively
     706             : !   voltosfc_amode(m), voltosfclo_amode(m), voltosfchi_amode(m) - ratio of
     707             : !       surface to volume for mode m (like the voltonumb_amode's)
     708             : !   alnv2n_amode(m), alnv2nlo_amode(m), alnv2nhi_amode(m) -
     709             : !       alnv2n_amode(m) = alog( voltonumblo_amode(m) ), ...
     710             : !   alnv2s_amode(m), alnv2slo_amode(m), alnv2shi_amode(m) -
     711             : !       alnv2s_amode(m) = alog( voltosfclo_amode(m) ), ...
     712             : !   rhcrystal_amode(m) = crystalization r.h. for mode m
     713             : !   rhdeliques_amode(m) = deliquescence r.h. for mode m
     714             : !   (*** these r.h. values are 0-1 fractions, not 0-100 percentages)
     715             : !
     716             : !   mcalcwater_amode(m) - if positive, water content for mode m will be
     717             : !       calculated and stored in rclm(k,lwaterptr_amode(m)).  Otherwise, no.
     718             : !   mprognum_amode(m) - if positive, number mixing-ratio for mode m will
     719             : !       be prognosed.  Otherwise, no.
     720             : !   mdiagnum_amode(m) - if positive, number mixing-ratio for mode m will
     721             : !       be diagnosed and put into rclm(k,numptr_amode(m)).  Otherwise, no.
     722             : !   mprogsfc_amode(m) - if positive, surface area mixing-ratio for mode m will
     723             : !       be prognosed, and sigmag will vary temporally and spatially.
     724             : !       Otherwise, sigmag is constant.
     725             : !       *** currently surface area is not prognosed when msectional>0 ***
     726             : !
     727             : !   ntot_aspectype = overall number of aerosol chemical species defined (over all modes)
     728             : !   specdens_amode(l) = dry density (kg/m^3) of aerosol chemical species type l
     729             : !   specmw_amode(l) = molecular weight (kg/kmol) of aerosol chemical species type l
     730             : !   specname_amode(l) = name of aerosol chemical species type l
     731             : !   specrefndxsw(l) = complex refractive index (visible wavelengths)
     732             : !                   of aerosol chemical species type l
     733             : !   specrefndxlw(l) = complex refractive index (infrared wavelengths)
     734             : !                   of aerosol chemical species type l
     735             : !   spechygro(l) = hygroscopicity of aerosol chemical species type l
     736             : !
     737             : !   lptr_so4_a_amode(m), lptr_so4_cw_amode(m) = gchm r-array index for the
     738             : !       mixing ratio for sulfate associated with aerosol mode m
     739             : !       ("a" and "cw" phases)
     740             : !   (similar for msa, oc, bc, nacl, dust)
     741             : !
     742             : !   modename_amode(m) = character-variable name for mode m,
     743             : !       read from mirage2.inp
     744             : !   modeptr_accum - mode index for the main accumulation mode
     745             : !       if modeptr_accum = 1, then mode 1 is the main accumulation mode,
     746             : !       and modename_amode(1) = "accum"
     747             : !   modeptr_aitken - mode index for the main aitken mode
     748             : !       if modeptr_aitken = 2, then mode 2 is the main aitken mode,
     749             : !       and modename_amode(2) = "aitken"
     750             : !   modeptr_ufine - mode index for the ultrafine mode
     751             : !       if modeptr_ufine = 3, then mode 3 is the ultrafine mode,
     752             : !       and modename_amode(3) = "ufine"
     753             : !   modeptr_coarseas - mode index for the coarse sea-salt mode
     754             : !       if modeptr_coarseas = 4, then mode 4 is the coarse sea-salt mode,
     755             : !       and modename_amode(4) = "coarse_seasalt"
     756             : !   modeptr_coardust - mode index for the coarse dust mode
     757             : !       if modeptr_coardust = 5, then mode 5 is the coarse dust mode,
     758             : !       and modename_amode(5) = "coarse_dust"
     759             : !
     760             : !   specdens_XX_amode = dry density (kg/m^3) of aerosol chemical species type XX
     761             : !       where XX is so4, om, bc, dust, seasalt
     762             : !       contains same values as the specdens_amode array
     763             : !       allows values to be referenced differently
     764             : !   specmw_XX_amode = molecular weight (kg/kmol) of aerosol chemical species type XX
     765             : !       contains same values as the specmw_amode array
     766             : !
     767             : !-----------------------------------------------------------------------
     768             : 
     769             : 
     770             : !--------------------------------------------------------------
     771             : !
     772             : ! ... aerosol size information for the current chunk
     773             : !
     774             : !--------------------------------------------------------------
     775             : !
     776             : !  dgncur = current geometric mean diameters (cm) for number distributions
     777             : !  dgncur_a - for unactivated particles, dry
     778             : !             (in physics buffer as DGNUM)
     779             : !  dgncur_awet - for unactivated particles, wet at grid-cell ambient RH
     780             : !             (in physics buffer as DGNUMWET)
     781             : !
     782             : !  the dgncur are computed from current mass and number
     783             : !  mixing ratios in the grid cell, BUT are then adjusted to be within
     784             : !  the bounds defined by dgnumlo/hi_amode
     785             : !
     786             : !  v2ncur = current (number/volume) ratio based on dgncur and sgcur
     787             : !              (volume in cm^3/whatever, number in particles/whatever)
     788             : !         == 1.0 / ( pi/6 * dgncur**3 * exp(4.5*((log(sgcur))**2)) )
     789             : !  v2ncur_a - for unactivated particles
     790             : !             (currently just defined locally)
     791             : !
     792             : 
     793             :      !==============================================================
     794           0 :      subroutine search_list_of_names(                                &
     795           0 :           name_to_find, name_id, list_of_names, list_length )
     796             :        !
     797             :        !   searches for a name in a list of names
     798             :        !
     799             :        !   name_to_find - the name to be found in the list  [input]
     800             :        !   name_id - the position of "name_to_find" in the "list_of_names".
     801             :        !       If the name is not found in the list, then name_id=0.  [output]
     802             :        !   list_of_names - the list of names to be searched  [input]
     803             :        !   list_length - the number of names in the list  [input]
     804             :        !
     805             :        character(len=*), intent(in):: name_to_find, list_of_names(:)
     806             :        integer, intent(in) :: list_length
     807             :        integer, intent(out) :: name_id
     808             : 
     809             :        integer :: i
     810           0 :        name_id = -999888777
     811           0 :        if (name_to_find .ne. ' ') then
     812           0 :           do i = 1, list_length
     813           0 :              if (name_to_find .eq. list_of_names(i)) then
     814           0 :                 name_id = i
     815           0 :                 exit
     816             :              end if
     817             :           end do
     818             :        end if
     819           0 :      end subroutine search_list_of_names
     820             : 
     821             : 
     822             :      !==============================================================
     823           0 :      subroutine initaermodes_setspecptrs
     824             :        !
     825             :        !   sets the lptr_so4_a_amode(m), lptr_so4_cw_amode(m), ...
     826             :        !       and writes them to iulog
     827             :        !   ALSO sets the mode-pointers:  modeptr_accum, modeptr_aitken, ...
     828             :        !       and writes them to iulog
     829             :        !   ALSO sets values of specdens_XX_amode and specmw_XX_amode
     830             :        !       (XX = so4, om, bc, dust, seasalt)
     831             :        !
     832             :        implicit none
     833             : 
     834             :        !   local variables
     835             :        integer :: i, l, lmassa, lmassc, m
     836             :        character(len=1000) :: msg
     837             :        character*8 :: dumname
     838             :        character*3 :: tmpch3
     839             :        integer, parameter :: init_val=-999888777
     840             :        integer :: bc_ndx, soa_ndx, pom_ndx
     841             : 
     842             :        !   all processes set the pointers
     843             : 
     844           0 :        modeptr_accum = init_val
     845           0 :        modeptr_aitken = init_val
     846           0 :        modeptr_ufine = init_val
     847           0 :        modeptr_coarse = init_val
     848           0 :        modeptr_pcarbon = init_val
     849           0 :        modeptr_fineseas = init_val
     850           0 :        modeptr_finedust = init_val
     851           0 :        modeptr_coarseas = init_val
     852           0 :        modeptr_coardust = init_val
     853           0 :        modeptr_stracoar = init_val
     854             : 
     855           0 :        do m = 1, ntot_amode
     856           0 :           if (modename_amode(m) .eq. 'accum') then
     857           0 :              modeptr_accum = m
     858           0 :           else if (modename_amode(m) .eq. 'aitken') then
     859           0 :              modeptr_aitken = m
     860           0 :           else if (modename_amode(m) .eq. 'ufine') then
     861           0 :              modeptr_ufine = m
     862           0 :           else if (modename_amode(m) .eq. 'coarse') then
     863           0 :              modeptr_coarse = m
     864           0 :           else if (modename_amode(m) .eq. 'primary_carbon') then
     865           0 :              modeptr_pcarbon = m
     866           0 :           else if (modename_amode(m) .eq. 'fine_seasalt') then
     867           0 :              modeptr_fineseas = m
     868           0 :           else if (modename_amode(m) .eq. 'fine_dust') then
     869           0 :              modeptr_finedust = m
     870           0 :           else if (modename_amode(m) .eq. 'coarse_seasalt') then
     871           0 :              modeptr_coarseas = m
     872           0 :           else if (modename_amode(m) .eq. 'coarse_dust') then
     873           0 :              modeptr_coardust = m
     874           0 :           else if (modename_amode(m) .eq. 'coarse_strat') then
     875           0 :              modeptr_stracoar = m
     876             :           end if
     877             :        end do
     878             : 
     879           0 :        lptr2_pom_a_amode   = init_val
     880           0 :        lptr2_pom_cw_amode  = init_val
     881           0 :        lptr2_soa_a_amode   = init_val
     882           0 :        lptr2_soa_cw_amode  = init_val
     883           0 :        lptr2_bc_a_amode    = init_val
     884           0 :        lptr2_bc_cw_amode   = init_val
     885             : 
     886           0 :        do m = 1, ntot_amode
     887             : 
     888           0 :           lptr_so4_a_amode(m)    = init_val
     889           0 :           lptr_so4_cw_amode(m)   = init_val
     890           0 :           lptr_msa_a_amode(m)    = init_val
     891           0 :           lptr_msa_cw_amode(m)   = init_val
     892           0 :           lptr_nh4_a_amode(m)    = init_val
     893           0 :           lptr_nh4_cw_amode(m)   = init_val
     894           0 :           lptr_no3_a_amode(m)    = init_val
     895           0 :           lptr_no3_cw_amode(m)   = init_val
     896           0 :           lptr_nacl_a_amode(m)   = init_val
     897           0 :           lptr_nacl_cw_amode(m)  = init_val
     898           0 :           lptr_dust_a_amode(m)   = init_val
     899           0 :           lptr_dust_cw_amode(m)  = init_val
     900             : 
     901           0 :           pom_ndx = 0
     902           0 :           soa_ndx = 0
     903           0 :           bc_ndx = 0
     904             : 
     905           0 :           do l = 1, nspec_amode(m)
     906           0 :              lmassa  = lmassptr_amode(l,m)
     907           0 :              lmassc = lmassptrcw_amode(l,m)
     908             : 
     909           0 :              if (lmassa > 0 .and. lmassa <= pcnst) then
     910             :                 write( msg, '(2a,3(1x,i12),2x,a)' ) &
     911           0 :                      'subr initaermodes_setspecptrs error setting lptr_', &
     912           0 :                      ' - m, l, lmassa, cnst_name = ', m, l, lmassa, cnst_name(lmassa)
     913             :              else
     914             :                 write( msg, '(2a,3(1x,i12),2x,a)' ) &
     915           0 :                      'subr initaermodes_setspecptrs error setting lptr_', &
     916           0 :                      ' - m, l, lmassa, cnst_name = ', m, l, lmassa, 'UNDEF '
     917           0 :                 call endrun( trim(msg) )
     918             :              end if
     919             : 
     920           0 :              tmpch3 = cnst_name(lmassa)(:3)
     921           0 :              select case (tmpch3)
     922             :              case('so4')
     923           0 :                 lptr_so4_a_amode(m)  = lmassa
     924           0 :                 lptr_so4_cw_amode(m) = lmassc
     925             :              case('msa')
     926           0 :                 lptr_msa_a_amode(m)  = lmassa
     927           0 :                 lptr_msa_cw_amode(m) = lmassc
     928             :              case('nh4')
     929           0 :                 lptr_nh4_a_amode(m)  = lmassa
     930           0 :                 lptr_nh4_cw_amode(m) = lmassc
     931             :              case('no3')
     932           0 :                 lptr_no3_a_amode(m)  = lmassa
     933           0 :                 lptr_no3_cw_amode(m) = lmassc
     934             :              case('dst')
     935           0 :                 lptr_dust_a_amode(m)  = lmassa
     936           0 :                 lptr_dust_cw_amode(m) = lmassc
     937             :              case('ncl')
     938           0 :                 lptr_nacl_a_amode(m)  = lmassa
     939           0 :                 lptr_nacl_cw_amode(m) = lmassc
     940             :              case('pom')
     941           0 :                 pom_ndx = pom_ndx+1
     942           0 :                 lptr2_pom_a_amode(m,pom_ndx)  = lmassa
     943           0 :                 lptr2_pom_cw_amode(m,pom_ndx) = lmassc
     944             :              case('soa')
     945           0 :                 soa_ndx = soa_ndx+1
     946           0 :                 lptr2_soa_a_amode(m,soa_ndx)  = lmassa
     947           0 :                 lptr2_soa_cw_amode(m,soa_ndx) = lmassc
     948             :              case('bc_','bcf','bcb')
     949           0 :                 bc_ndx = bc_ndx+1
     950           0 :                 lptr2_bc_a_amode(m,bc_ndx)  = lmassa
     951           0 :                 lptr2_bc_cw_amode(m,bc_ndx) = lmassc
     952             :              case default
     953           0 :                 call endrun( trim(msg) )
     954             :              end select
     955             :           end do ! l
     956             :        end do ! m
     957             : 
     958           0 :        specmw_so4_amode = 1.0_r8
     959             : 
     960           0 :        do m = 1, ntot_amode
     961           0 :           do l = 1, nspec_amode(m)
     962           0 :              dumname = trim(adjustl(xname_massptr(l,m)))
     963           0 :              tmpch3  = trim(adjustl(dumname(:3)))
     964           0 :              if(trim(adjustl(tmpch3)) == 'so4' .or. trim(adjustl(tmpch3)) == 'SO4') then
     965           0 :                 specmw_so4_amode = specmw_amode(l,m)
     966             :              endif
     967             :           enddo
     968             :        enddo
     969             : 
     970             : 
     971             :        !   masterproc writes out the pointers
     972           0 :        if ( .not. ( masterproc ) ) return
     973             : 
     974           0 :        write(iulog,9230)
     975           0 :        write(iulog,*) 'modeptr_accum    =', modeptr_accum
     976           0 :        write(iulog,*) 'modeptr_aitken   =', modeptr_aitken
     977           0 :        write(iulog,*) 'modeptr_ufine    =', modeptr_ufine
     978           0 :        write(iulog,*) 'modeptr_coarse   =', modeptr_coarse
     979           0 :        write(iulog,*) 'modeptr_pcarbon  =', modeptr_pcarbon
     980           0 :        write(iulog,*) 'modeptr_fineseas =', modeptr_fineseas
     981           0 :        write(iulog,*) 'modeptr_finedust =', modeptr_finedust
     982           0 :        write(iulog,*) 'modeptr_coarseas =', modeptr_coarseas
     983           0 :        write(iulog,*) 'modeptr_coardust =', modeptr_coardust
     984           0 :        write(iulog,*) 'modeptr_stracoar =', modeptr_stracoar
     985             : 
     986           0 :        dumname = 'none'
     987           0 :        write(iulog,9240)
     988           0 :        write(iulog,9000) 'sulfate    '
     989           0 :        do m = 1, ntot_amode
     990             :           call initaermodes_setspecptrs_write2( m,                    &
     991           0 :                lptr_so4_a_amode(m), lptr_so4_cw_amode(m),  'so4' )
     992             :        end do
     993             : 
     994           0 :        write(iulog,9000) 'msa        '
     995           0 :        do m = 1, ntot_amode
     996             :           call initaermodes_setspecptrs_write2( m,                    &
     997           0 :                lptr_msa_a_amode(m), lptr_msa_cw_amode(m),  'msa' )
     998             :        end do
     999             : 
    1000           0 :        write(iulog,9000) 'ammonium   '
    1001           0 :        do m = 1, ntot_amode
    1002             :           call initaermodes_setspecptrs_write2( m,                    &
    1003           0 :                lptr_nh4_a_amode(m), lptr_nh4_cw_amode(m),  'nh4' )
    1004             :        end do
    1005             : 
    1006           0 :        write(iulog,9000) 'nitrate    '
    1007           0 :        do m = 1, ntot_amode
    1008             :           call initaermodes_setspecptrs_write2( m,                    &
    1009           0 :                lptr_no3_a_amode(m), lptr_no3_cw_amode(m),  'no3' )
    1010             :        end do
    1011             : 
    1012           0 :        write(iulog,9000) 'p-organic  '
    1013           0 :        do m = 1, ntot_amode
    1014           0 :           do i = 1, npoa
    1015           0 :              write(dumname,'(a,i2.2)') 'pom', i
    1016             :              call initaermodes_setspecptrs_write2b( m, &
    1017           0 :                   lptr2_pom_a_amode(m,i), lptr2_pom_cw_amode(m,i),  dumname(1:5) )
    1018             :           end do
    1019             :        end do
    1020             : 
    1021           0 :        write(iulog,9000) 's-organic  '
    1022           0 :        do m = 1, ntot_amode
    1023           0 :           do i = 1, nsoa
    1024           0 :              write(dumname,'(a,i2.2)') 'soa', i
    1025             :              call initaermodes_setspecptrs_write2b( m, &
    1026           0 :                   lptr2_soa_a_amode(m,i), lptr2_soa_cw_amode(m,i), dumname(1:5) )
    1027             :           end do
    1028             :        end do
    1029           0 :        do i = 1, nsoa
    1030           0 :           l = lptr2_soa_g_amode(i)
    1031           0 :           write(iulog,'(i4,2x,i12,2x,a,20x,a,i2.2,a)') i, l, cnst_name(l), 'lptr2_soa', i, '_g'
    1032             :        end do
    1033             : 
    1034           0 :        write(iulog,9000) 'black-c    '
    1035           0 :        do m = 1, ntot_amode
    1036           0 :           do i = 1, nbc
    1037           0 :              write(dumname,'(a,i2.2)') 'bc', i
    1038             :              call initaermodes_setspecptrs_write2b( m, &
    1039           0 :                   lptr2_bc_a_amode(m,i), lptr2_bc_cw_amode(m,i), dumname(1:5) )
    1040             :           end do
    1041             :        end do
    1042             : 
    1043           0 :        write(iulog,9000) 'seasalt   '
    1044           0 :        do m = 1, ntot_amode
    1045             :           call initaermodes_setspecptrs_write2( m,                    &
    1046           0 :                lptr_nacl_a_amode(m), lptr_nacl_cw_amode(m),  'nacl' )
    1047             :        end do
    1048             : 
    1049           0 :        write(iulog,9000) 'dust       '
    1050           0 :        do m = 1, ntot_amode
    1051             :           call initaermodes_setspecptrs_write2( m,                    &
    1052           0 :                lptr_dust_a_amode(m), lptr_dust_cw_amode(m),  'dust' )
    1053             :        end do
    1054             : 
    1055             : 9000   format( a )
    1056             : 9230   format(                                                         &
    1057             :             / 'mode-pointer output from subr initaermodes_setspecptrs' )
    1058             : 9240   format(                                                         &
    1059             :             / 'species-pointer output from subr initaermodes_setspecptrs' / &
    1060             :             'mode', 12x, 'id  name_a  ', 12x, 'id  name_cw' )
    1061             : 
    1062             :        return
    1063             :      end subroutine initaermodes_setspecptrs
    1064             : 
    1065             : 
    1066             :      !==============================================================
    1067           0 :      subroutine initaermodes_setspecptrs_write2(                     &
    1068             :           m, laptr, lcptr, txtdum )
    1069             :        !
    1070             :        !   does some output for initaermodes_setspecptrs
    1071             : 
    1072             :        use constituents, only: pcnst, cnst_name
    1073             : 
    1074             :        implicit none
    1075             : 
    1076             :        !   subr arguments
    1077             :        integer, intent(in) :: m, laptr, lcptr
    1078             :        character*(*), intent(in) ::  txtdum
    1079             : 
    1080             :        !   local variables
    1081             :        character*8 dumnamea, dumnamec
    1082             : 
    1083           0 :        dumnamea = 'none'
    1084           0 :        dumnamec = 'none'
    1085           0 :        if (laptr > pcnst .or. lcptr > pcnst ) then
    1086           0 :           call endrun('initaermodes_setspecptrs_write2: ERROR')
    1087             :        endif
    1088           0 :        if (laptr .gt. 0) dumnamea = cnst_name(laptr)
    1089           0 :        if (lcptr .gt. 0) dumnamec = cnst_name(lcptr)
    1090           0 :        write(iulog,9241) m, laptr, dumnamea, lcptr, dumnamec, txtdum
    1091             : 
    1092             : 9241   format( i4, 2( 2x, i12, 2x, a ),                                &
    1093             :             4x, 'lptr_', a, '_a/cw_amode' )
    1094             : 
    1095           0 :        return
    1096             :      end subroutine initaermodes_setspecptrs_write2
    1097             : 
    1098             : 
    1099             :      !==============================================================
    1100           0 :      subroutine initaermodes_setspecptrs_write2b( &
    1101             :           m, laptr, lcptr, txtdum )
    1102             :        !
    1103             :        !   does some output for initaermodes_setspecptrs
    1104             : 
    1105             :        implicit none
    1106             : 
    1107             :        !   subr arguments
    1108             :        integer, intent(in) :: m, laptr, lcptr
    1109             :        character*(*), intent(in) :: txtdum
    1110             : 
    1111             :        !   local variables
    1112             :        character*8 dumnamea, dumnamec
    1113             : 
    1114           0 :        dumnamea = 'none'
    1115           0 :        dumnamec = 'none'
    1116           0 :        if (laptr .gt. 0) dumnamea = cnst_name(laptr)
    1117           0 :        if (lcptr .gt. 0) dumnamec = cnst_name(lcptr)
    1118           0 :        write(iulog,9241) m, laptr, dumnamea, lcptr, dumnamec, txtdum
    1119             : 
    1120             : 9241   format( i4, 2( 2x, i12, 2x, a ),                                &
    1121             :             4x, 'lptr2_', a, '_a/cw_amode' )
    1122             : 
    1123           0 :        return
    1124             :      end subroutine initaermodes_setspecptrs_write2b
    1125             : 
    1126             :      !==============================================================
    1127           0 :      subroutine initaermodes_set_cnstnamecw
    1128             :        !
    1129             :        !   sets the cnst_name_cw
    1130             :        !
    1131             :        use constituents, only: pcnst, cnst_name
    1132             :        implicit none
    1133             : 
    1134             :        !   subr arguments (none)
    1135             : 
    1136             :        !   local variables
    1137             :        integer j, l, la, lc, ll, m
    1138             : 
    1139             :        !   set cnst_name_cw
    1140           0 :        cnst_name_cw = ' '
    1141           0 :        do m = 1, ntot_amode
    1142           0 :           do ll = 0, nspec_amode(m)
    1143           0 :              if (ll == 0) then
    1144           0 :                 la = numptr_amode(m)
    1145           0 :                 lc = numptrcw_amode(m)
    1146             :              else
    1147           0 :                 la = lmassptr_amode(ll,m)
    1148           0 :                 lc = lmassptrcw_amode(ll,m)
    1149             :              end if
    1150             :              if ((la < 1) .or. (la > pcnst) .or.   &
    1151           0 :                   (lc < 1) .or. (lc > pcnst)) then
    1152             :                 write(*,'(/2a/a,5(1x,i10))')   &
    1153           0 :                      '*** initaermodes_set_cnstnamecw error',   &
    1154           0 :                      ' -- bad la or lc',   &
    1155           0 :                      '    m, ll, la, lc, pcnst =', m, ll, la, lc, pcnst
    1156           0 :                 call endrun( '*** initaermodes_set_cnstnamecw error' )
    1157             :              end if
    1158           0 :              do j = 2, len( cnst_name(la) ) - 1
    1159           0 :                 if (cnst_name(la)(j:j+1) == '_a') then
    1160           0 :                    cnst_name_cw(lc) = cnst_name(la)
    1161           0 :                    cnst_name_cw(lc)(j:j+1) = '_c'
    1162           0 :                    exit
    1163           0 :                 else if (cnst_name(la)(j:j+1) == '_A') then
    1164           0 :                    cnst_name_cw(lc) = cnst_name(la)
    1165           0 :                    cnst_name_cw(lc)(j:j+1) = '_C'
    1166           0 :                    exit
    1167             :                 end if
    1168             :              end do
    1169           0 :              if (cnst_name_cw(lc) == ' ') then
    1170             :                 write(*,'(/2a/a,3(1x,i10),2x,a)')   &
    1171           0 :                      '*** initaermodes_set_cnstnamecw error',   &
    1172           0 :                      ' -- bad cnst_name(la)',   &
    1173           0 :                      '    m, ll, la, cnst_name(la) =',   &
    1174           0 :                      m, ll, la, cnst_name(la)
    1175           0 :                 call endrun( '*** initaermodes_set_cnstnamecw error' )
    1176             :              end if
    1177             :           end do   ! ll = 0, nspec_amode(m)
    1178             :        end do   ! m = 1, ntot_amode
    1179             : 
    1180           0 :        if ( masterproc ) then
    1181           0 :           write(*,'(/a)') 'l, cnst_name(l), cnst_name_cw(l)'
    1182           0 :           do l = 1, pcnst
    1183           0 :              write(*,'(i4,2(2x,a))') l, cnst_name(l), cnst_name_cw(l)
    1184             :           end do
    1185             :        end if
    1186             : 
    1187           0 :        return
    1188             :      end subroutine initaermodes_set_cnstnamecw
    1189             : 
    1190             :   end module modal_aero_data

Generated by: LCOV version 1.14