! module_cam_mam_init.F ! created by r.c.easter, june 2010 ! ! 2010-07-03 notes: ! 1. In CAM, stratiform-cloudborne aerosol species are held in the qqcw ! array (of physics buffer), interstital aerosol water species are held in ! the qaerwat array (of physics buffer), and other trace species (water vapor, ! "stratiform cloud microphysical", trace gases, interstitial aerosol) ! are held in the state%q array. Which interfacing to CAM routines, ! species must by transferred to/from the q and qqcw arrays. ! Initial implementations in WRF-Chem will use CBMZ gas-phase chemistry ! and CAM MAM aerosols, so the trace gases will differ from CAM5. ! The species in the q array will be ! a. Moisture species (pcnst_non_chem_modal_aero of them) ! b. Trace gas species with WRF-Chem indices between param_first_scalar ! and numgas. ! c. Interstitial aerosol species (except for aerosol water). ! !-------------------------------------------------------------- #include "MODAL_AERO_CPP_DEFINES.h" module module_cam_mam_init private public :: cam_mam_init ! in cam5, pom is assumed to by 10/14 carbon and 4/14 other elements (oxygen, etc) ! when the following 2 parameters are positive, a factor of 1.4 is applied ! in the emissions and IC/BC routines, so that pom in cam5 will be ! ~1.4x the equivalent mosaic and sorgam primary organic species ! when a flag is zero/negative, the factor is not applied ! *** the 2 integer parameters can be modified by user (normally all 0 or all 1), ! but the 2 real variables are set later based on the parameter values integer, parameter :: pom_emit_1p4_factor_flag = 0 integer, parameter :: pom_icbc_1p4_factor_flag = 0 real, public :: pom_emit_1p4_factor real, public :: pom_icbc_1p4_factor ! in 3-mode cam5, so4 is assumed to be ammonium-bisulfate (molec-wght = 115) ! when the following 3 parameters are positive, a factor of 115/96 ~= 1.2 is applied ! to so4 species in the emissions and IC/BC routines, and the so4 molec-wght ! is set to 115 (which affect so2->so4 gas and aqueous oxidation), ! so that so4 in cam5 will be ~1.2x the equivalent mosaic and sorgam primary organic species ! when a flag is zero/negative, the factor is not applied, or the molec-wght is set to 96 ! *** the 3 integer parameters can be modified by user (normally all 0 or all 1), ! but the 2 real variables are set later based on the parameter values integer, parameter :: so4_emit_1p2_factor_flag = 1 integer, parameter :: so4_icbc_1p2_factor_flag = 1 integer, parameter :: so4_mwgt_1p2_factor_flag = 1 real, public :: so4_emit_1p2_factor real, public :: so4_icbc_1p2_factor !Balwinder.Singh@pnnl.gov: cnst_name_loc is defined as a local array for this module !The cnst_name array of phys/constituent module is populated using 'cnst_add' calls !in this module to be consistent with the CAM way of populating cnst_name array character(len=16),allocatable, public :: cnst_name_loc(:) ! constituent names integer, parameter :: init_val = -999888777 LOGICAL :: CAM_INITIALIZED_CHEM = .FALSE. contains !============================================================== subroutine cam_mam_init( & id, numgas, config_flags, & ids,ide, jds,jde, kds,kde, & ims,ime, jms,jme, kms,kme, & its,ite, jts,jte, kts,kte ) !-------------------------------------------------------------- ! purpose: ! 1. call routines that allocated and initialize data structures used ! by cam modal aerosol (cam_mam) code ! 2. call routines that initialize aerosol mixing ratios ! for specific test scenarios !-------------------------------------------------------------- use module_state_description, only: num_chem,CBMZ_CAM_MAM3_NOAQ,CBMZ_CAM_MAM3_AQ,CBMZ_CAM_MAM7_NOAQ,CBMZ_CAM_MAM7_AQ use module_configure, only: grid_config_rec_type use shr_kind_mod, only: r8 => shr_kind_r8 use physconst, only: epsilo, latvap, latice, rh2o, cpair, tmelt use module_cam_esinti, only: esinti use module_cam_support, only: pver, pverp, pcols, & pcnst => pcnst_runtime, & endrun, masterproc use modal_aero_data, only: cnst_name_cw, ntot_aspectype, & qneg3_worst_thresh_amode, species_class, & specmw_amode, specname_amode, & specdens_so4_amode, specmw_so4_amode, & specdens_nh4_amode, specmw_nh4_amode, & specdens_no3_amode, specmw_no3_amode, & specdens_pom_amode, specmw_pom_amode, & specdens_soa_amode, specmw_soa_amode, & specdens_bc_amode, specmw_bc_amode, & specdens_dust_amode, specmw_dust_amode, & specdens_seasalt_amode, specmw_seasalt_amode use modal_aero_initialize_data, only: modal_aero_initialize, modal_aero_register, decouple_mam_mp use ndrop , only: activate_init USE module_cam_mam_cloudchem, only: cam_mam_cloudchem_inti USE module_cam_mam_gas_wetdep_driver, only: cam_mam_gas_wetdep_inti implicit none !-------------------------------------------------------------- ! ... arguments !-------------------------------------------------------------- type(grid_config_rec_type), intent(in) :: config_flags integer, intent(in) :: & id, numgas, & ids, ide, jds, jde, kds, kde, & ims, ime, jms, jme, kms, kme, & its, ite, jts, jte, kts, kte !-------------------------------------------------------------- ! ... local variables !-------------------------------------------------------------- integer :: ierr, l, m character(len=16) :: tmpname character(len=160) :: msg !Balwinder.Singh@pnnl.gov: Added a sanity check so that chem_opt package corresponds to the right CPP directive for 3 or 7 mode #if ( defined MODAL_AERO_3MODE ) if ( (config_flags%chem_opt /= CBMZ_CAM_MAM3_NOAQ) .and. & (config_flags%chem_opt /= CBMZ_CAM_MAM3_AQ ) ) then call wrf_error_fatal( 'cam_mam_init - MODAL_AERO_3MODE is defined but chem_opt is not a CAM_MAM3 package' ) end if #elif ( defined MODAL_AERO_7MODE ) if ( (config_flags%chem_opt /= CBMZ_CAM_MAM7_NOAQ) .and. & (config_flags%chem_opt /= CBMZ_CAM_MAM7_AQ ) ) then call wrf_error_fatal( 'cam_mam_init - MODAL_AERO_7MODE is defined but chem_opt is not a CAM_MAM7 package' ) end if #else call wrf_error_fatal( 'cam_mam_init - neither MODAL_AERO_3MODE or MODAL_AERO_7MODE is defined' ) #endif !Balwinder.Singh@pnnl.gov: Sanity check for cam_mam_mode variable in namelist if((config_flags%chem_opt == CBMZ_CAM_MAM3_NOAQ .OR. config_flags%chem_opt == CBMZ_CAM_MAM3_AQ) .AND. config_flags%cam_mam_mode .NE. 3)then call wrf_error_fatal( 'CAM_MAM_INIT - For MODAL_AERO_3MODE (chem_opt - 503 CAM_MAM3 package), cam_mam_mode in namelist should be set to 3' ) elseif((config_flags%chem_opt == CBMZ_CAM_MAM7_NOAQ .OR. config_flags%chem_opt == CBMZ_CAM_MAM7_AQ) .AND. config_flags%cam_mam_mode .NE. 7)then call wrf_error_fatal('CAM_MAM_INIT - For MODAL_AERO_7MODE (chem_opt - 504 CAM_MAM7 package), cam_mam_mode in namelist should be set to 7') endif !Balwinder.Singh@pnnl.gov: Sanity check for cam_mam_nspec variable in namelist !BSINGH (01/23/2014):Please make sure cam_mam_nspec is equal to pcnst in phys/module_physics_init.F and registry.chem if((config_flags%chem_opt == CBMZ_CAM_MAM3_NOAQ .OR. config_flags%chem_opt == CBMZ_CAM_MAM3_AQ) .AND. config_flags%cam_mam_nspec .NE. 85)then call wrf_error_fatal( 'CAM_MAM_INIT - For MODAL_AERO_3MODE (chem_opt - 503 CAM_MAM3 package), cam_mam_nspec in namelist should be set to 85' ) elseif((config_flags%chem_opt == CBMZ_CAM_MAM7_NOAQ .OR. config_flags%chem_opt == CBMZ_CAM_MAM7_AQ) .AND. config_flags%cam_mam_nspec .NE. 90)then !BSINGH (01/23/2014): DMS species are NOT included in MAM7 package. call wrf_error_fatal('CAM_MAM_INIT - For MODAL_AERO_7MODE (chem_opt - 504 CAM_MAM7 package), cam_mam_nspec in namelist should be set to 90') endif !-------------------------------------------------------------- ! ... executable !-------------------------------------------------------------- write(*,'(/a)') 'cam_mam_init' write(*,*) 'id, num_chem, pcnst =', id, num_chem, pcnst write(*,'(a,3(4x,2i5))') 'ids/e, j..., k... ', ids,ide, jds,jde, kds,kde write(*,'(a,3(4x,2i5))') 'ims/e, j..., k... ', ims,ime, jms,jme, kms,kme write(*,'(a,3(4x,2i5))') 'its/e, j..., k... ', its,ite, jts,jte, kts,kte write(*,'(a,3( i14))') 'pver, pverp, pcols', pver, pverp, pcols ! initialize water vapor saturation routines call esinti(epsilo, latvap, latice, rh2o, cpair, tmelt) ! set pver and pverp if ( (max(pver,pverp) > 0) .and. & (pver /= kte-kts+1) .and. & (pverp /= pver+1) ) then write( msg, '(2a,3i15)' ) & 'cam_mam_init fatal error ', & '- bad pver - id, pver, pverp = ', id, pver, pverp call wrf_error_fatal( msg ) end if if (pver <= 0) then pver = kde - kds pverp = pver + 1 end if write(*,'(a,3( i14))') 'pver, pverp, pcols', pver, pverp, pcols ! set pcnst and cnst_name_loc write(*,'(/a)') & 'cam_mam_init calling cam_mam_init_set_cnst' call cam_mam_init_set_cnst( id, numgas, config_flags ) !Balwinder.Singh@pnnl.gov: Before calling 'modal_aero_initialize', we have to !call 'modal_aero_register'[nuance of CAM5.1] write(*,'(/a)') & 'cam_mam_init calling modal_aero_register' call modal_aero_register ! do modal_aero_initialize_data write(*,'(/a)') & 'cam_mam_init calling modal_aero_initialize' call modal_aero_initialize !For assisting decoupled microphysics (MP) CAM MAM simulations (simulations, where MAM package is coupled with !radiation but decoupled with MP - i.e. MP runs with 'prescribed' aerosols) call decouple_mam_mp(config_flags%CAM_MP_MAM_cpled) !Balwinder.Singh@pnnl.gov: initialize aerosol activation call activate_init #if ( defined MODAL_AERO_3MODE ) if (so4_mwgt_1p2_factor_flag <= 0) then ! in this case, the so4 molec-wght will be 96 instead of 115, ! so do the following to override what was done in modal_aero_initialize do m = 1, ntot_aspectype if (specname_amode(m).eq.'sulfate ') then !specmw_amode(m) = 96.0_r8 !Balwinder.Singh@pnnl.gov: defined as a 'parameter' in module_data_cam_mam_aero.F specmw_so4_amode = specmw_amode(m) else if (specname_amode(m).eq.'ammonium ') then !specmw_amode(m) = 18.0_r8 !Balwinder.Singh@pnnl.gov: defined as a 'parameter' in module_data_cam_mam_aero.F specmw_nh4_amode = specmw_amode(m) end if end do end if #endif write(*,'(a,2f12.4)') 'so4 dens, mw', specdens_so4_amode, specmw_so4_amode write(*,'(a,2f12.4)') 'nh4 dens, mw', specdens_nh4_amode, specmw_nh4_amode write(*,'(a,2f12.4)') 'no3 dens, mw', specdens_no3_amode, specmw_no3_amode write(*,'(a,2f12.4)') 'pom dens, mw', specdens_pom_amode, specmw_pom_amode write(*,'(a,2f12.4)') 'soa dens, mw', specdens_soa_amode, specmw_soa_amode write(*,'(a,2f12.4)') 'bc dens, mw', specdens_bc_amode, specmw_bc_amode write(*,'(a,2f12.4)') 'dst dens, mw', specdens_dust_amode, specmw_dust_amode write(*,'(a,2f12.4)') 'ncl dens, mw', specdens_seasalt_amode, specmw_seasalt_amode ! set variables that contain the pom 1.4 or 1.0 factors ! and the so4 1.2 or 1.0 factors used with emissions and IC/BC pom_emit_1p4_factor = 1.0 pom_icbc_1p4_factor = 1.0 if (pom_emit_1p4_factor_flag > 0) pom_emit_1p4_factor = 1.4 if (pom_icbc_1p4_factor_flag > 0) pom_icbc_1p4_factor = 1.4 so4_emit_1p2_factor = 1.0 so4_icbc_1p2_factor = 1.0 #if ( defined MODAL_AERO_3MODE ) if (so4_emit_1p2_factor_flag > 0) so4_emit_1p2_factor = 115.0/96.0 if (so4_icbc_1p2_factor_flag > 0) so4_icbc_1p2_factor = 115.0/96.0 #endif write(*,'(/a,2f10.4)') 'pom_emit_1p4_factor & _init_', & pom_emit_1p4_factor, pom_icbc_1p4_factor write(*,'( a,2f10.4)') 'so4_emit_1p2_factor & _init_', & so4_emit_1p2_factor, so4_icbc_1p2_factor ! initialize the module_data_cam_mam_asect data write(*,'(/a)') & 'cam_mam_init calling cam_mam_init_asect' call cam_mam_init_asect( id, config_flags ) ! allocate and initialize arrays used to map aerosol and trace gas species ! between the wrf-chem "chem" array and the cam "q" array write(*,'(/a)') & 'cam_mam_init calling cam_mam_init_other' call cam_mam_init_other( id, numgas, config_flags ) !Initialize CAM Cloud Chemistry call cam_mam_cloudchem_inti() !Initialize CAM gas wetdep call cam_mam_gas_wetdep_inti deallocate(cnst_name_loc) ! done write(*,'(/a)') & 'cam_mam_init done' return end subroutine cam_mam_init !============================================================== subroutine cam_mam_init_set_cnst( id, numgas, config_flags ) !-------------------------------------------------------------- ! purpose: ! 1. set the value of the pcnst variable ! (which currently is pcnst_runtime in module_cam_support), ! and the pcnst_non_chem variable too. ! 2. load the cnst_name array of constituent module using 'cnst_add' calls ! and load it with appropriate trace species names ! ! Modified by Balwinder.Singh@pnnl.gov: pcnst is set up at runtime ! now. This subroutine serves ! as a test to check whether ! the value of pcnst is set ! approprately in ! module_physics_init.F !*NOTE*: As a quick solution, correct value for the Molecular weights ! of the constituents is updated in 'cam_mam_init_other'. In ! the current subroutine, molecular weights are set to 1. ! !*WARNING*: Minimum threshold for the constituents is set to ZERO here. ! This value is updated in 'cam_mam_init_other' subroutine !-------------------------------------------------------------- use module_configure, only: grid_config_rec_type use module_state_description, only: num_chem, param_first_scalar use module_scalar_tables, only: chem_dname_table use module_cam_support, only: pcnst => pcnst_runtime, & pcnst_non_chem => pcnst_non_chem_modal_aero, & gas_pcnst => gas_pcnst_modal_aero, & endrun, masterproc use modal_aero_data use constituents, only: cnst_add use physconst, only: cpair implicit none !-------------------------------------------------------------- ! ... arguments !-------------------------------------------------------------- type(grid_config_rec_type), intent(in) :: config_flags integer, intent(in) :: id ! domain index integer, intent(in) :: numgas !-------------------------------------------------------------- ! ... local variables !-------------------------------------------------------------- integer :: ierr, itmpa, dumind integer :: l, l2 integer :: p1st character(len=360) :: msg !-------------------------------------------------------------- ! ... executable !-------------------------------------------------------------- write(*,*) 'cam_mam_init_set_cnst' write(*,*) 'id, num_chem =', id, num_chem write(*,*) 'pcnst, gas_pcnst old =', pcnst, gas_pcnst ! set pcnst value (and pcnst_non_chem too) p1st = param_first_scalar pcnst_non_chem = 5 ! start with the non-chemistry trace species itmpa = pcnst_non_chem ! add on the trace gas species do l = p1st, numgas itmpa = itmpa + 1 end do ! add on the interstitial aerosol apecies ! (except aerosol water) ! *** their species names are assumed to end ! with "_aN", where N=1,2,...,9 *** do l = numgas+1, num_chem if ( cam_mam_is_q_aerosol_species( l, numgas ) ) then itmpa = itmpa + 1 end if end do if (pcnst == itmpa) then !Balwinder.Singh@pnnl.gov: check if pcnst has the correct value !pcnst = itmpa gas_pcnst = pcnst - pcnst_non_chem write(*,*) 'pcnst, gas_pcnst new =', pcnst, gas_pcnst else if (pcnst /= itmpa) then write( msg, * ) & 'CAM_MAM_INIT_SET_CNST fatal error: The value of PCNST should be set to:',itmpa, & ' in module_physics_init.F where pcnst is mentioned as', pcnst,'. ID is',id call wrf_error_fatal( msg ) end if ! allocate cnst_name_loc if ( .not. allocated(cnst_name_loc) ) then allocate( cnst_name_loc(pcnst) ) end if ! set cnst_name_loc values do l = 1, pcnst write( cnst_name_loc(l), '(a,i4.4)' ) 'empty_cnst_', l end do !First 5 constituents are already added in the phys/module_physics_init module. !Therefore cnst_add calls are not required for the same if (pcnst_non_chem >= 1) cnst_name_loc(1) = 'Q' if (pcnst_non_chem >= 2) cnst_name_loc(2) = 'CLDLIQ' if (pcnst_non_chem >= 3) cnst_name_loc(3) = 'CLDICE' if (pcnst_non_chem >= 4) cnst_name_loc(4) = 'NUMLIQ' if (pcnst_non_chem >= 5) cnst_name_loc(5) = 'NUMICE' l2 = pcnst_non_chem do l = p1st, numgas l2 = l2 + 1 IF(.NOT.CAM_INITIALIZED_CHEM) call cnst_add(trim(adjustl(chem_dname_table(1,l))), 1.0_r8, cpair, 0._r8, dumind) cnst_name_loc(l2) = chem_dname_table(1,l) end do do l = numgas+1, num_chem if ( cam_mam_is_q_aerosol_species( l, numgas ) ) then l2 = l2 + 1 IF(.NOT.CAM_INITIALIZED_CHEM) call cnst_add(trim(adjustl(chem_dname_table(1,l))), 1.0_r8, cpair, 0._r8, dumind) cnst_name_loc(l2) = chem_dname_table(1,l) end if end do if (l2 /= pcnst) then write( msg, '(2a,3i15)' ) & 'cam_mam_init_set_cnst fatal error 101', & 'for cnst_name, id, l2, pcnst = ', id, l2, pcnst call wrf_error_fatal( msg ) end if return end subroutine cam_mam_init_set_cnst !============================================================== function cam_mam_is_q_aerosol_species( lspec, numgas ) ! ! returns true if the wrf-chem species with index lspec is an aerosol species ! that belongs in the q array, otherwise returns false. ! the q array aerosol species are interstitial aerosol species ! other than aerosol water ! *** currently it is assumed that for these species, the ! wrf-chem species name ends with "_aN", where N=1,2,...,7 ! use module_state_description, only: num_chem, param_first_scalar use module_scalar_tables, only: chem_dname_table use modal_aero_data, only: ntot_amode implicit none logical :: cam_mam_is_q_aerosol_species integer, intent(in) :: lspec, numgas integer :: i, n integer, parameter :: upper_to_lower = iachar('a')-iachar('A') character(len=32) :: tmpname character(len=1) :: tmpch cam_mam_is_q_aerosol_species = .false. if ( (lspec < param_first_scalar) .or. & (lspec <= numgas) .or. & (lspec > num_chem) ) return call lower_case( chem_dname_table(1,lspec), tmpname ) ! aerosol water species are not in the q array if (tmpname(1:5) == 'wtr_a') return n = len( trim(tmpname) ) n = max( n, 4 ) if (tmpname(n-2:n) == '_a1') cam_mam_is_q_aerosol_species = .true. if (tmpname(n-2:n) == '_a2') cam_mam_is_q_aerosol_species = .true. if (tmpname(n-2:n) == '_a3') cam_mam_is_q_aerosol_species = .true. if (ntot_amode == 3) return if (tmpname(n-2:n) == '_a4') cam_mam_is_q_aerosol_species = .true. if (tmpname(n-2:n) == '_a5') cam_mam_is_q_aerosol_species = .true. if (tmpname(n-2:n) == '_a6') cam_mam_is_q_aerosol_species = .true. if (tmpname(n-2:n) == '_a7') cam_mam_is_q_aerosol_species = .true. if (ntot_amode == 7) return return end function cam_mam_is_q_aerosol_species !============================================================== subroutine lower_case( txt_in, txt_lc ) ! ! converts a character string (txt_in) to lowercase (txt_lc) ! implicit none character(len=*), intent(in) :: txt_in character(len=*), intent(out) :: txt_lc integer :: i, j integer, parameter :: iachar_lowera = iachar('a') integer, parameter :: iachar_uppera = iachar('A') integer, parameter :: iachar_upperz = iachar('Z') txt_lc = txt_in do i = 1, len( trim(txt_lc) ) j = iachar( txt_lc(i:i) ) if (j < iachar_uppera) cycle if (j > iachar_upperz) cycle txt_lc(i:i) = achar( j + iachar_lowera - iachar_uppera ) end do return end subroutine lower_case !============================================================== subroutine cam_mam_init_asect( id, config_flags ) !-------------------------------------------------------------- ! purpose: ! initialize the aerosol pointer and property (density, molec wght, ! hygroscopicity) variables in module_data_cam_mam_asect ! from information in module_data_cam_mam_aero ! the module_data_cam_mam_aero variables are an "older version" ! designed for the mirage code, and are used by cam routines ! the module_data_cam_mam_asect variables are a "newer version" ! designed for the wrf-chem code, and they are useful for ! the wrf-chem-->cam interface/driver routines !-------------------------------------------------------------- use module_state_description, only: num_chem,param_first_scalar,CBMZ_CAM_MAM3_AQ,CBMZ_CAM_MAM7_AQ use module_configure, only: grid_config_rec_type use module_scalar_tables, only: chem_dname_table use modal_aero_data, only: & dgnum_amode, lspectype_amode, nspec_amode, ntot_amode, ntot_aspectype, & sigmag_amode, specdens_amode, spechygro, specmw_amode, specname_amode use module_data_cam_mam_asect implicit none ! arguments integer, intent(in) :: id type(grid_config_rec_type), intent(in) :: config_flags ! local variables integer :: iphase, isize, itype integer :: l, l2, l3, l4, la, lc integer :: p1st real, parameter :: pi=3.1415926536 real :: dp_meanvol_tmp character(len=160) :: msg character(len=32) :: tmpname, tmpnamec, tmptxtaa p1st = param_first_scalar ! set master component information ntot_mastercomp_aer = ntot_aspectype do l = 1, ntot_mastercomp_aer name_mastercomp_aer(l) = specname_amode(l) ! densities in modal_aero_data are kg/m3 ! densities in module_data_cam_mam_asect are g/cm3 (for consistency with mosaic and sorgam) dens_mastercomp_aer(l) = specdens_amode(l)*1.0e-3 mw_mastercomp_aer(l) = specmw_amode(l) hygro_mastercomp_aer(l) = spechygro(l) if (name_mastercomp_aer(l) == 'sulfate') then mastercompindx_so4_aer = l namebb_mastercomp_aer(l) = 'so4' mw_so4_aer = mw_mastercomp_aer(l) dens_so4_aer = dens_mastercomp_aer(l) else if (name_mastercomp_aer(l) == 'ammonium') then mastercompindx_nh4_aer = l namebb_mastercomp_aer(l) = 'nh4' mw_nh4_aer = mw_mastercomp_aer(l) dens_nh4_aer = dens_mastercomp_aer(l) else if (name_mastercomp_aer(l) == 'nitrate') then mastercompindx_no3_aer = l namebb_mastercomp_aer(l) = 'no3' mw_no3_aer = mw_mastercomp_aer(l) dens_no3_aer = dens_mastercomp_aer(l) else if (name_mastercomp_aer(l) == 'p-organic') then mastercompindx_pom_aer = l namebb_mastercomp_aer(l) = 'pom' mw_pom_aer = mw_mastercomp_aer(l) dens_pom_aer = dens_mastercomp_aer(l) else if (name_mastercomp_aer(l) == 's-organic') then mastercompindx_soa_aer = l namebb_mastercomp_aer(l) = 'soa' mw_soa_aer = mw_mastercomp_aer(l) dens_soa_aer = dens_mastercomp_aer(l) else if (name_mastercomp_aer(l) == 'black-c') then mastercompindx_bc_aer = l namebb_mastercomp_aer(l) = 'bc' mw_bc_aer = mw_mastercomp_aer(l) dens_bc_aer = dens_mastercomp_aer(l) else if (name_mastercomp_aer(l) == 'seasalt') then mastercompindx_seas_aer = l namebb_mastercomp_aer(l) = 'ncl' mw_seas_aer = mw_mastercomp_aer(l) dens_seas_aer = dens_mastercomp_aer(l) else if (name_mastercomp_aer(l) == 'dust') then mastercompindx_dust_aer = l namebb_mastercomp_aer(l) = 'dst' mw_dust_aer = mw_mastercomp_aer(l) dens_dust_aer = dens_mastercomp_aer(l) else msg = '*** cam_mam_init_asect error 100 - mastercompindx' call wrf_message( msg ) write( msg, '(a,i4,2x,a)' ) 'l, specname_amode = ', & l, specname_amode(l) call wrf_error_fatal( msg ) end if end do ! l ! set number of phases nphase_aer = 1 ai_phase = 1 ! if (config_flags%chem_opt == ...) then if ((config_flags%chem_opt == CBMZ_CAM_MAM3_AQ) .or. & (config_flags%chem_opt == CBMZ_CAM_MAM7_AQ )) then nphase_aer = 2 cw_phase = 2 end if if (nphase_aer > 2) then msg = '*** cam_mam_init_asect error 120 - nphase_aer > 2' call wrf_error_fatal( msg ) end if nsize_aer(:) = 0 ncomp_aer(:) = 0 ncomp_plustracer_aer(:) = 0 mastercompptr_aer(:,:) = init_val massptr_aer(:,:,:,:) = init_val waterptr_aer(:,:) = init_val hyswptr_aer(:,:) = init_val numptr_aer(:,:,:) = init_val mprognum_aer(:,:,:) = 0 lptr_so4_aer(:,:,:) = init_val lptr_nh4_aer(:,:,:) = init_val lptr_no3_aer(:,:,:) = init_val lptr_pom_aer(:,:,:) = init_val lptr_soa_aer(:,:,:) = init_val lptr_bc_aer(:,:,:) = init_val lptr_dust_aer(:,:,:) = init_val lptr_seas_aer(:,:,:) = init_val volumcen_sect(:,:) = 0.0 volumlo_sect(:,:) = 0.0 volumhi_sect(:,:) = 0.0 dcen_sect(:,:) = 0.0 dlo_sect(:,:) = 0.0 dhi_sect(:,:) = 0.0 sigmag_aer(:,:) = 1.0 ! set mode information ! ! each cam_mam mode corresponds to a wrfchem type, ! and each wrfchm type has a single size bin ! (this differs from sorgam, where the aitken and accum. modes ! have the same species, and so can both have the same type) ! ntype_aer = ntot_amode do itype = 1, ntype_aer nsize_aer(itype) = 1 ncomp_aer(itype) = nspec_amode(itype) ncomp_plustracer_aer(itype) = ncomp_aer(itype) ! for sectional ! the dhi/dlo_sect are the upper/lower bounds for ! mean-volume diameter for a section/bin ! for modal ! they should be set to reasonable upper/lower ! bounds for mean-volume diameters of each modes ! they are primarily used to put reasonable bounds ! on number (in relation to mass/volume) ! the dcen_sect are used by initwet for the impaction scavenging ! lookup tables, and should represent a "base" mean-volume diameter ! dp_meanvol_tmp (below) is the cam-mam default value ! for mean-volume diameter (in cm) ! terminology: (pi/6) * (mean-volume diameter)**3 == ! (volume mixing ratio of section/mode)/(number mixing ratio) isize = 1 sigmag_aer(isize,itype) = sigmag_amode(itype) dp_meanvol_tmp = 1.0e2*dgnum_amode(itype) & ! 1.0e2 converts m to cm *exp( 1.5 * log(sigmag_aer(isize,itype))**2 ) dcen_sect(isize,itype) = dp_meanvol_tmp dhi_sect( isize,itype) = dp_meanvol_tmp*4.0 dlo_sect( isize,itype) = dp_meanvol_tmp/4.0 do isize = 1, nsize_aer(itype) volumcen_sect(isize,itype) = (pi/6.0)*(dcen_sect(isize,itype)**3) volumlo_sect( isize,itype) = (pi/6.0)*(dlo_sect( isize,itype)**3) volumhi_sect( isize,itype) = (pi/6.0)*(dhi_sect( isize,itype)**3) end do write(*,'(a,i3,1p,5e11.3)') 'type, sg, dg, dp, vol', itype, & sigmag_aer(1,itype), dgnum_amode(itype), dp_meanvol_tmp, volumcen_sect(1,itype) do l = 1, ncomp_aer(itype) l2 = lspectype_amode(l,itype) if ((l2 > 0) .and. (l2 <= ntot_mastercomp_aer)) then mastercompptr_aer(l,itype) = l2 else msg = '*** cam_mam_init_asect error 200 - mastercompptr' call wrf_message( msg ) write( msg, '(a,4(1x,i10))' ) & 'itype, l, l2, ntot_mastercomp_aer = ', & itype, l, l2, ntot_mastercomp_aer call wrf_error_fatal( msg ) end if dens_aer(l,itype) = dens_mastercomp_aer(l2) mw_aer(l,itype) = mw_mastercomp_aer(l2) hygro_aer(l,itype) = hygro_mastercomp_aer(l2) name_aer(l,itype) = name_mastercomp_aer(l2) end do isize = 1 do l = -1, ncomp_aer(itype) do iphase = 1, nphase_aer if (l == -1) then tmpname = 'num' else if (l == 0) then tmpname = 'wtr' if (iphase > 1) cycle else l2 = lspectype_amode(l,itype) tmpname = namebb_mastercomp_aer(l2) end if if (iphase == 1) then tmpname = trim(tmpname) // '_a' else tmpname = trim(tmpname) // '_c' end if write( tmptxtaa, '(i1)' ) itype tmpname = trim(tmpname) // tmptxtaa(1:1) l3 = 0 do l4 = p1st, num_chem if (chem_dname_table(1,l4) == tmpname) then l3 = l4 exit end if end do if (l3 <= 0) then msg = '*** cam_mam_init_asect error 300' // & ' - finding species - ' // tmpname call wrf_error_fatal( msg ) end if if (l == -1) then numptr_aer(isize,itype,iphase) = l3 mprognum_aer(isize,itype,iphase) = 1 else if (l == 0) then waterptr_aer(isize,itype) = l3 else massptr_aer(l,isize,itype,iphase) = l3 mastercompptr_aer(l,itype) = l2 if (l2 == mastercompindx_so4_aer) then lptr_so4_aer(isize,itype,iphase) = l3 else if (l2 == mastercompindx_nh4_aer) then lptr_nh4_aer(isize,itype,iphase) = l3 ! else if (l2 == mastercompindx_no3_aer) then ! lptr_no3_aer(isize,itype,iphase) = l3 else if (l2 == mastercompindx_pom_aer) then lptr_pom_aer(isize,itype,iphase) = l3 else if (l2 == mastercompindx_soa_aer) then lptr_soa_aer(isize,itype,iphase) = l3 else if (l2 == mastercompindx_bc_aer) then lptr_bc_aer(isize,itype,iphase) = l3 else if (l2 == mastercompindx_dust_aer) then lptr_dust_aer(isize,itype,iphase) = l3 else if (l2 == mastercompindx_seas_aer) then lptr_seas_aer(isize,itype,iphase) = l3 else msg = '*** cam_mam_init_asect error 400' // & ' - finding species type - ' // tmpname call wrf_error_fatal( msg ) end if end if end do ! iphase end do ! l end do ! itype ! diagnostics write(*,'(/a)') 'cam_mam_init_asect diagnostics' write(*,'(/a,i5)') 'ntot_mastercomp_aer', ntot_mastercomp_aer write(*,'(a)') 'mastercomp name, l, mw, dens, hygro' do l = 1, ntot_mastercomp_aer write(*,'(a,i5,1p,3e12.4)') name_mastercomp_aer(l), l, & mw_mastercomp_aer(l), dens_mastercomp_aer(l), hygro_mastercomp_aer(l) end do write(*,'(a)') & 'mastercompindx_so4_aer, nh4, no3, pom, soa, bc, seas, dust' write(*,'(4i12)') & mastercompindx_so4_aer, mastercompindx_nh4_aer, mastercompindx_no3_aer, & mastercompindx_pom_aer, mastercompindx_soa_aer, mastercompindx_bc_aer, & mastercompindx_seas_aer, mastercompindx_dust_aer write(*,'(a)') '........... mw_so4_aer, nh4, no3, pom, soa, bc, seas, dust' write(*,'(1p,4e12.4)') & mw_so4_aer, mw_nh4_aer, mw_no3_aer, & mw_pom_aer, mw_soa_aer, mw_bc_aer, & mw_seas_aer, mw_dust_aer write(*,'(a)') '......... dens_so4_aer, nh4, no3, pom, soa, bc, seas, dust' write(*,'(1p,4e12.4)') & dens_so4_aer, dens_nh4_aer, dens_no3_aer, & dens_pom_aer, dens_soa_aer, dens_bc_aer, & dens_seas_aer, dens_dust_aer write(*,'(/a/6i12)') 'nphase_aer, ai_phase, cw_phase', & nphase_aer, ai_phase, cw_phase do itype = 1, ntype_aer do isize = 1, nsize_aer(itype) write(*,'(/a,2i5,a)') 'info for itype, isize = ', itype, isize, & 'species; id, name for ai & cw; mw, dens, hygro' la = numptr_aer(isize,itype,1) lc = numptr_aer(isize,itype,2) tmpname = '---' if ((la >= p1st) .and. (la <= num_chem)) tmpname = chem_dname_table(1,la) tmpnamec = '---' if ((lc >= p1st) .and. (lc <= num_chem)) tmpnamec = chem_dname_table(1,la) write(*,'(a,i12,1x,a,i12,1x,a,1p,3e12.4)') 'number ', & la, tmpname(1:10), lc, tmpnamec(1:10) do l = 1, ncomp_aer(itype) la = massptr_aer(l,isize,itype,1) lc = massptr_aer(l,isize,itype,2) tmpname = '---' if ((la >= p1st) .and. (la <= num_chem)) tmpname = chem_dname_table(1,la) tmpnamec = '---' if ((lc >= p1st) .and. (lc <= num_chem)) tmpnamec = chem_dname_table(1,la) write(*,'(a,i12,1x,a,i12,1x,a,1p,3e12.4)') name_aer(l,itype), & la, tmpname(1:10), lc, tmpnamec(1:10), & mw_aer(l,itype), dens_aer(l,itype), hygro_aer(l,itype) end do ! l la = waterptr_aer(isize,itype) tmpname = '---' if ((la >= p1st) .and. (la <= num_chem)) tmpname = chem_dname_table(1,la) write(*,'(a,i12,1x,a,23x,1p,3e12.4)') 'water ', & la, tmpname(1:10) la = hyswptr_aer(isize,itype) tmpname = '---' if ((la >= p1st) .and. (la <= num_chem)) tmpname = chem_dname_table(1,la) write(*,'(a,i12,1x,a,23x,1p,3e12.4)') 'hys-water ', & la, tmpname(1:10) end do ! isize end do ! itype return end subroutine cam_mam_init_asect !============================================================== subroutine cam_mam_init_other( id, numgas, config_flags ) !-------------------------------------------------------------- ! purpose: ! allocate and initialize variables in module_data_cam_mam_asect ! that are used for mapping trace species mixing ratios from ! wrf-chem arrays (e.g., "chem") to cam arrays (q, qqcw, qaerwat) !-------------------------------------------------------------- use shr_kind_mod, only: r8 => shr_kind_r8 use module_state_description, only: num_chem, param_first_scalar use module_configure, only: grid_config_rec_type, & p_h2o2, p_hno3, p_nh3, p_o3, p_so2, p_soag, p_sulf use module_scalar_tables, only: chem_dname_table use module_cam_support, only: pcnst => pcnst_runtime, & pcnst_non_chem => pcnst_non_chem_modal_aero, & gas_pcnst => gas_pcnst_modal_aero use modal_aero_data, only: cnst_name_cw use module_data_cam_mam_asect use constituents, only: cnst_mw, cnst_rgas, cnst_cv, cnst_cp, & qmin,qmincg use physconst, only: r_universal use infnan, only: nan !Balwinder.Singh@pnnl.gov:*NOTE* cnst_cv and cnst_cp are set to 'nan' !as the cpair value for the chemical species is NOT set correctly. !The 'nan' assigment will produce an error whenever cnst_cv or !cnst_cp is used for any computation implicit none ! arguments integer, intent(in) :: id, numgas type(grid_config_rec_type), intent(in) :: config_flags ! local variables integer :: iphase, isize, itype, dumind integer :: l, ll, l2, l3, l4 integer :: p1st character(len=160) :: msg character(len=16) :: tmpname, tmpname2, tmpname3 real(r8) :: qmin_gas, qmin_aer,qmin_num IF(.NOT.CAM_INITIALIZED_CHEM) THEN qmin_gas = 1.0E-17_r8 !Typical val(H2SO4) : 1E-12 kg/kg; Negligible val: 1E-17 kg/kg - Balwinder.Singh@pnnl.gov qmin_aer = 1.0E-14_r8 !Typical val(accum or coarse) : 1E-9 kg/kg; Negligible val: 1E-14 kg/kg - Balwinder.Singh@pnnl.gov qmin_num = 1.0E+01_r8 !Typical val(coarse) : 1E5 #/kg; Negligible val: 1E1 #/kg - Balwinder.Singh@pnnl.gov ENDIF p1st = param_first_scalar ! allocate lptr_chem_to_..., factconv_chem_to_..., and mw_... arrays if ( .not. allocated(lptr_chem_to_q) ) then allocate( lptr_chem_to_q(num_chem) ) end if if ( .not. allocated(lptr_chem_to_qqcw) ) then allocate( lptr_chem_to_qqcw(num_chem) ) end if if ( .not. allocated(factconv_chem_to_q) ) then allocate( factconv_chem_to_q(num_chem) ) end if if ( .not. allocated(factconv_chem_to_qqcw) ) then allocate( factconv_chem_to_qqcw(num_chem) ) end if if ( .not. allocated(mw_chem_array) ) then allocate( mw_chem_array(num_chem) ) end if if ( .not. allocated(mw_q_array) ) then allocate( mw_q_array(pcnst) ) end if if ( .not. allocated(mw_q_mo_array) ) then allocate( mw_q_mo_array(gas_pcnst) ) end if ! set values of lptr_chem_to_... arrays lptr_chem_to_q(:) = init_val lptr_chem_to_qqcw(:) = init_val do l = p1st, num_chem tmpname = chem_dname_table(1,l) do l2 = 1, pcnst if (tmpname == cnst_name_loc(l2)) then lptr_chem_to_q(l) = l2 exit end if if (tmpname == cnst_name_cw(l2)) then lptr_chem_to_qqcw(l) = l2 exit end if end do end do ! set values of factconv_chem_to_..., and mw_... arrays factconv_chem_to_q(:) = 1.0 factconv_chem_to_qqcw(:) = 1.0 mw_chem_array(:) = 1.0 mw_q_array(:) = 1.0 mw_q_mo_array(:) = 1.0 l2 = pcnst_non_chem do l = p1st, numgas l2 = lptr_chem_to_q(l) if ((l2 < 1) .or. (l2 > pcnst)) cycle ! set molecular weights of gas species that may be used by cam_mam routines if (l == p_sulf) mw_chem_array(l) = 96.0 if (l == p_so2 ) mw_chem_array(l) = 64.0 if (l == p_nh3 ) mw_chem_array(l) = 17.0 if (l == p_hno3) mw_chem_array(l) = 63.0 if (l == p_soag) mw_chem_array(l) = 12.0 if (l == p_h2o2) mw_chem_array(l) = 34.0 if (l == p_o3 ) mw_chem_array(l) = 48.0 mw_q_array(l2) = mw_chem_array(l) IF(.NOT.CAM_INITIALIZED_CHEM) THEN cnst_mw(l2) = mw_q_array(l2) cnst_rgas(l2) = r_universal * cnst_mw(l2) cnst_cp (l2) = nan cnst_cv (l2) = nan qmin (l2) = qmin_gas qmincg (l2) = qmin(l2) ENDIF ! convert wrf-chem ppmv to cam kg/kg-air factconv_chem_to_q(l) = 1.0e-6*mw_chem_array(l)/28.966 end do iphase = ai_phase do itype = 1, ntype_aer do isize = 1, nsize_aer(itype) l = numptr_aer(isize,itype,iphase) mw_chem_array(l) = 1.0 l2 = lptr_chem_to_q(l) if ((l2 >= 1) .and. (l2 <= pcnst)) then mw_q_array(l2) = mw_chem_array(l) IF(.NOT.CAM_INITIALIZED_CHEM) THEN cnst_mw(l2) = mw_q_array(l2) cnst_rgas(l2) = r_universal * cnst_mw(l2) cnst_cp (l2) = nan cnst_cv (l2) = nan qmin (l2) = qmin_num qmincg (l2) = qmin(l2) ENDIF ! wrf-chem and cam units for number are identical (#/kg-air) factconv_chem_to_q(l) = 1.0 end if l = waterptr_aer(isize,itype) if ((l >= p1st) .and. (l <= num_chem)) then mw_chem_array(l) = 18.0 ! convert wrf-chem ug/kg-air to cam kg/kg-air factconv_chem_to_q(l) = 1.0e-9 end if do ll = 1, ncomp_aer(itype) l = massptr_aer(ll,isize,itype,iphase) mw_chem_array(l) = mw_aer(ll,itype) l2 = lptr_chem_to_q(l) if ((l2 >= 1) .and. (l2 <= pcnst)) then mw_q_array(l2) = mw_chem_array(l) IF(.NOT.CAM_INITIALIZED_CHEM) THEN cnst_mw(l2) = mw_q_array(l2) cnst_rgas(l2) = r_universal * cnst_mw(l2) cnst_cp (l2) = nan cnst_cv (l2) = nan qmin (l2) = qmin_aer qmincg (l2) = qmin(l2) ENDIF ! convert wrf-chem ug/kg-air to cam kg/kg-air factconv_chem_to_q(l) = 1.0e-9 end if end do end do ! isize end do ! itype ! conversion for cloud-borne aerosols if (nphase_aer > 1) then iphase = cw_phase do itype = 1, ntype_aer do isize = 1, nsize_aer(itype) l = numptr_aer(isize,itype,iphase) if (l < p1st .or. l > num_chem) then write(*,'(a,10i10)') '*** cw_phase numb error', iphase, itype, isize, l else mw_chem_array(l) = 1.0 l2 = lptr_chem_to_qqcw(l) if ((l2 >= 1) .and. (l2 <= pcnst)) then ! mw_qqcw_array(l2) = mw_chem_array(l) ! wrf-chem and cam units for number are identical (#/kg-air) factconv_chem_to_q(l) = 1.0 end if end if do ll = 1, ncomp_aer(itype) l = massptr_aer(ll,isize,itype,iphase) if (l < p1st .or. l > num_chem) then write(*,'(a,10i10)') '*** cw_phase mass error', iphase, itype, isize, ll, l else mw_chem_array(l) = mw_aer(ll,itype) l2 = lptr_chem_to_qqcw(l) if ((l2 >= 1) .and. (l2 <= pcnst)) then ! mw_qqcw_array(l2) = mw_chem_array(l) ! convert wrf-chem ug/kg-air to cam kg/kg-air factconv_chem_to_q(l) = 1.0e-9 end if end if end do end do ! isize end do ! itype end if ! mw_q_mo_array is equivalent to the cam adv_mass array mw_q_mo_array(1:gas_pcnst) = mw_q_array(pcnst_non_chem+1:pcnst) write( *, '(/2a)' ) & 'l, cnst_name, chem_name, l3, chem_name2, ', & 'lptr_chem_to_q, factconv_..., mw_...' do l = 1, max( pcnst, num_chem ) tmpname = ' ' tmpname2 = ' ' tmpname3 = ' ' if (l <= pcnst) then tmpname = cnst_name_loc(l) do l2 = p1st, num_chem if (lptr_chem_to_q(l2) == l) tmpname2 = chem_dname_table(1,l2) end do end if l3 = l l4 = init_val if ((l3 >= p1st) .and. (l3 <= num_chem)) then tmpname3 = chem_dname_table(1,l3) l4 = lptr_chem_to_q(l3) end if if (l3 <= num_chem) then write( *, '(i4,2(2x,a),i6,2x,a,i12,1p,2e10.2)' ) & l, tmpname, tmpname2, l3, tmpname3, l4, & factconv_chem_to_q(l3), mw_chem_array(l3) else write( *, '(i4,2(2x,a),i6,2x,a,i12,1p,e10.2)' ) & l, tmpname, tmpname2 end if end do IF(.NOT.CAM_INITIALIZED_CHEM) CAM_INITIALIZED_CHEM = .TRUE. return end subroutine cam_mam_init_other !============================================================== end module module_cam_mam_init