diff --git a/CMakeLists.txt b/CMakeLists.txt index 1cbfafdc..fc6c8f49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,6 +94,8 @@ target_compile_definitions(CCTM PUBLIC SUBST_FILES_ID="FILES_CTM.EXT" SUBST_COMM=NOOP_COMM SUBST_BARRIER=NOOP_BARRIER SUBST_SUBGRID_INDEX=NOOP_SUBGRID_INDEX + AQCHEM=DUMMY_AQCHEM + CONVCLD_ACM=DUMMY_CONVCLD_ACM EDDYX=DUMMY_EDDYX MOSAIC_MOD=MOSAIC_MODULE Mosaic_Mod=Mosaic_Module diff --git a/aqm_files.cmake b/aqm_files.cmake index bba274bc..3216ca42 100644 --- a/aqm_files.cmake +++ b/aqm_files.cmake @@ -9,15 +9,16 @@ list(APPEND aqm_files list(APPEND aqm_shr_files src/shr/aqm_config_mod.F90 src/shr/aqm_const_mod.F90 - src/shr/aqm_domain_mod.F90 + src/shr/aqm_domain_mod.F90 src/shr/aqm_emis_mod.F90 + src/shr/aqm_prod_mod.F90 src/shr/aqm_fires_mod.F90 src/shr/aqm_internal_mod.F90 - src/shr/aqm_model_mod.F90 + src/shr/aqm_model_mod.F90 src/shr/aqm_rc_mod.F90 src/shr/aqm_methods.F90 src/shr/aqm_species_mod.F90 - src/shr/aqm_state_mod.F90 + src/shr/aqm_state_mod.F90 src/shr/aqm_tools_mod.F90 src/shr/aqm_types_mod.F90 ) @@ -114,6 +115,13 @@ list(APPEND aqm_CCTM_files ${BIOG}/tmpbeis.F ${BIOG}/wrdaymsg.f ${CLOUD}/hlconst.F + ${CLOUD}/cldproc_acm.F + ${CLOUD}/getalpha.F + ${CLOUD}/indexn.f + ${CLOUD}/rescld.F + ${CLOUD}/scavwdep.F + ${CLOUD}/aq_map.F + ${CLOUD}/AQ_DATA.F ${DEPV}/ABFLUX_MOD.F ${DEPV}/BIDI_MOD.F ${DEPV}/cgrid_depv.F diff --git a/examples/aqm.rc b/examples/aqm.rc index b09c9e5f..db18f4fd 100644 --- a/examples/aqm.rc +++ b/examples/aqm.rc @@ -35,9 +35,15 @@ omi_data: /scratch1/NCEPDEV/nems/Raffaele.Montuoro/dev/aqm/epa/data/omi_cmaq_ init_concentrations: true # -# Run aerosol module +# Run options: +# +# - enable aerosol module # run_aerosol: true +# +# - enable wet deposition processes in resolved-scale clouds +# +run_rescld: true # # Microphysics scheme used by coupled atmospheric model diff --git a/src/aqm_comp_mod.F90 b/src/aqm_comp_mod.F90 index 788fac9b..edbdaa75 100644 --- a/src/aqm_comp_mod.F90 +++ b/src/aqm_comp_mod.F90 @@ -8,6 +8,7 @@ module aqm_comp_mod use aqm_types_mod, only : AQM_MAXSTR use aqm_model_mod use aqm_emis_mod + use aqm_prod_mod use aqm_internal_mod use cmaq_model_mod @@ -92,6 +93,12 @@ subroutine aqm_comp_create(model, rc) msg="Failed to initialize emissions subsystem", & line=__LINE__, file=__FILE__, rcToReturn=rc)) return ! bail out + ! -- initialize products + call aqm_prod_init(model, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, & + msg="Failed to initialize products", & + line=__LINE__, file=__FILE__, rcToReturn=rc)) return ! bail out + end subroutine aqm_comp_create subroutine aqm_comp_init(rc) @@ -198,6 +205,13 @@ subroutine aqm_comp_advance(model, rc) return ! bail out end if + ! -- update output products if needed + call aqm_prod_update(model, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg="Failed to update products", & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + end subroutine aqm_comp_advance !----------------------------------------------------------------------------- diff --git a/src/drv/cmaq_mod.F90 b/src/drv/cmaq_mod.F90 index 88404340..6495435d 100644 --- a/src/drv/cmaq_mod.F90 +++ b/src/drv/cmaq_mod.F90 @@ -4,6 +4,7 @@ module cmaq_mod use aqm_types_mod use aqm_const_mod, only : onebg, rdgas, grav, mwair, zero use aqm_emis_mod + use aqm_prod_mod use aqm_tools_mod, only : aqm_units_conv use PAGRD_DEFN @@ -43,6 +44,9 @@ module cmaq_mod public :: cmaq_emis_init public :: cmaq_emis_finalize public :: cmaq_emis_print + public :: cmaq_prod_init + public :: cmaq_prod_units_get + public :: cmaq_prod_update public :: cmaq_species_read public :: cmaq_export public :: cmaq_import @@ -116,10 +120,10 @@ subroutine cmaq_init(rc) end subroutine cmaq_init - subroutine cmaq_advance(jdate, jtime, tstep, run_aero, rc) + subroutine cmaq_advance(jdate, jtime, tstep, run_aero, run_rescld, rc) integer, intent(in) :: jdate, jtime, tstep(3) - logical, intent(in) :: run_aero + logical, intent(in) :: run_aero, run_rescld integer, optional, intent(out) :: rc ! -- local variables @@ -131,6 +135,11 @@ SUBROUTINE VDIFF ( CGRID, JDATE, JTIME, TSTEP ) INTEGER :: JDATE, JTIME INTEGER :: TSTEP( 3 ) END SUBROUTINE VDIFF + SUBROUTINE CLDPROC ( CGRID, JDATE, JTIME, TSTEP ) + REAL, POINTER :: CGRID( :,:,:,: ) + INTEGER :: JDATE, JTIME + INTEGER :: TSTEP( 3 ) + END SUBROUTINE CLDPROC SUBROUTINE CHEM ( CGRID, JDATE, JTIME, TSTEP ) REAL, POINTER :: CGRID( :,:,:,: ) INTEGER :: JDATE, JTIME @@ -149,6 +158,10 @@ END SUBROUTINE AERO ! -- advance all physical and chemical processes on a grid CALL VDIFF ( CGRID, JDATE, JTIME, TSTEP ) + if (run_rescld) then + CALL CLDPROC ( CGRID, JDATE, JTIME, TSTEP ) + end if + CALL CHEM ( CGRID, JDATE, JTIME, TSTEP ) if (run_aero) then @@ -239,17 +252,21 @@ subroutine cmaq_import(tracers, prl, phii, temp, start_index, rc) end subroutine cmaq_import - subroutine cmaq_export(tracers, prl, temp, start_index, rc) + subroutine cmaq_export(tracers, prl, temp, start_index, diag_index, rc) real(AQM_KIND_R8), intent(out) :: tracers(:,:,:,:) real(AQM_KIND_R8), intent(in) :: prl(:,:,:) real(AQM_KIND_R8), intent(in) :: temp(:,:,:) integer, intent(in) :: start_index + integer, intent(in) :: diag_index integer, optional, intent(out) :: rc + ! -- local variables integer :: c, r, l, n, off, spc, v real(AQM_KIND_R8) :: rdens + real :: pm25(my_ncols,my_nrows,nlays,1) + integer :: localrc ! -- begin if (present(rc)) rc = AQM_RC_SUCCESS @@ -306,6 +323,18 @@ subroutine cmaq_export(tracers, prl, temp, start_index, rc) end do end if + ! -- pm2.5 + + call cmaq_prod_pm25( pm25, cgrid, tracers, diag_index, nlays) + n = diag_index + 3 + do l = 1, nlays + do r = 1, my_nrows + do c = 1, my_ncols + tracers( c,r,l,n ) = pm25( c,r,l,1 ) + end do + end do + end do + end subroutine cmaq_export subroutine cmaq_conc_init(jdate, jtime, tstep, rc) @@ -642,4 +671,179 @@ subroutine cmaq_domain_log(label) end subroutine cmaq_domain_log + subroutine cmaq_prod_init(rc) + + integer, optional, intent(out) :: rc + + ! -- local variables + integer :: item, n + character(len=AQM_MAXSTR) :: units + type(aqm_internal_emis_type), pointer :: pdata(:) + type(aqm_internal_emis_type), pointer :: prod + + ! -- begin + if (present(rc)) rc = AQM_RC_SUCCESS + + nullify(pdata) + pdata => aqm_emis_data_get() + + if (associated(pdata)) then + + do item = 1, size(pdata) + nullify(prod) + if (trim(pdata(item) % type) == "product") then + prod => pdata(item) + do n = 1, size(prod % species) + call cmaq_prod_units_get( prod % species(n), units ) + call aqm_prod_units_set ( prod % fields(n), units ) + end do + end if + end do + + end if + + end subroutine cmaq_prod_init + + subroutine cmaq_prod_units_get( species, units ) + + character(len=*), intent(in) :: species + character(len=*), intent(out) :: units + + ! -- local variables + integer :: spc + + ! -- begin + units = "n/a" + select case ( trim(species) ) + case ("PM2.5") + ! --- diagnostic PM2.5 + units = "ug/m3" + case default + ! --- CMAQ species + ! --- 1. gas species + spc = index1( trim(species), n_gc_spc, gc_spc ) + if (spc > 0) then + units = "ppmV" + else + ! --- 2. aerosol species + spc = index1( trim(species), n_ae_spc, ae_spc ) + if (spc > 0) units = "ug/m3" + end if + end select + + end subroutine cmaq_prod_units_get + + subroutine cmaq_prod_update(tracers, start_index, rc) + + real(AQM_KIND_R8), intent(in) :: tracers(:,:,:,:) + integer, intent(in) :: start_index + integer, optional, intent(out) :: rc + + ! -- local variables + integer :: item, n, spc + real :: pm25(my_ncols,my_nrows,1,1) + type(aqm_internal_emis_type), pointer :: pdata(:) + type(aqm_internal_emis_type), pointer :: prod + + ! -- begin + nullify(pdata) + pdata => aqm_emis_data_get() + + if (associated(pdata)) then + + do item = 1, size(pdata) + nullify(prod) + if (trim(pdata(item) % type) == "product") then + prod => pdata(item) + do n = 1, size(prod % species) + select case ( trim(prod % species(n)) ) + case ("PM2.5") + ! --- diagnostic PM2.5 + if ( n_ae_spc > 0 ) then + call cmaq_prod_pm25( pm25, cgrid, tracers, start_index, 1) + call aqm_prod_compute( prod, pm25, n, 1 ) + end if + case default + ! --- CMAQ species + spc = 0 + ! --- 1. gas species + if ( n_gc_spc > 0 ) spc = index1( prod % species(n), n_gc_spc, gc_spc ) + if (spc > 0) then + spc = spc + gc_strt - 1 + call aqm_prod_compute( prod, cgrid, n, spc ) + else + ! --- 2. aerosol species + if ( n_ae_spc > 0 ) spc = index1( prod % species(n), n_ae_spc, ae_spc ) + if (spc > 0) then + spc = spc + ae_strt - 1 + call aqm_prod_compute( prod, cgrid, n, spc ) + end if + end if + end select + end do + end if + end do + + end if + + end subroutine cmaq_prod_update + + subroutine cmaq_prod_pm25( pm25, cgrid, frac, idx, nlays_in) + + real, intent(out) :: pm25(:,:,:,:) + real, intent(in) :: cgrid(:,:,:,:) + real(AQM_KIND_R8), intent(in) :: frac(:,:,:,:) + integer, intent(in) :: idx + integer, intent(in) :: nlays_in + + ! -- local variables + integer :: i, ibeg, iend, imod, mode, spc + integer :: c, r, l + + ! -- local parameters + character(len=*), parameter :: pm25_species(*) = & + (/ "ASO4I ", "ANO3I ", "ANH4I ", "ANAI ", "ACLI ", "AECI ", "AOTHRI ", & ! I-mode (Atken) + "ALVPO1I", "ASVPO1I", "ASVPO2I", "ALVOO1I", "ALVOO2I", "ASVOO1I", "ASVOO2I", & + "ASO4J ", "ANO3J ", "ANH4J ", "ANAJ ", "ACLJ ", "AECJ ", "AOTHRJ ", & ! J-mode (accum) + "ALVPO1J", "ASVPO1J", "ASVPO2J", "ASVPO3J", "AIVPO1J", & + "AXYL1J ", "AXYL2J ", "AXYL3J ", "ATOL1J ", "ATOL2J ", "ATOL3J ", "ABNZ1J ", "ABNZ2J ", & + "ABNZ3J ", "AISO1J ", "AISO2J ", "AISO3J ", "ATRP1J ", "ATRP2J ", "ASQTJ ", "AALK1J ", & + "AALK2J ", "APAH1J ", "APAH2J ", "APAH3J ", "AORGCJ ", "AOLGBJ ", "AOLGAJ ", & + "ALVOO1J", "ALVOO2J", "ASVOO1J", "ASVOO2J", "ASVOO3J", "APCSOJ ", & + "AFEJ ", "ASIJ ", "ATIJ ", "ACAJ ", "AMGJ ", "AMNJ ", "AALJ ", "AKJ ", & + "ASOIL ", "ACORS ", "ASEACAT", "ACLK ", "ASO4K ", "ANO3K ", "ANH4K " /) ! K-mode (coarse) + + integer, parameter :: nspc(3) = (/ 14, 49, 7 /) + + ! -- begin + pm25 = 0. + + if ( n_ae_spc > 0 ) then + ibeg = 0 + iend = 0 + + ! -- loop over I, J, K modes + imod = idx + do mode = 1, 3 + ibeg = iend + 1 + iend = iend + nspc(mode) + do i = ibeg, iend + spc = index1( pm25_species(i), n_ae_spc, ae_spc ) + if (spc > 0) then + spc = spc + ae_strt - 1 + do l = 1, nlays_in + do r = 1, my_nrows + do c = 1, my_ncols + pm25( c,r,l,1 ) = pm25( c,r,l,1 ) + frac( c,r,l,imod ) * cgrid( c,r,l,spc ) + end do + end do + end do + end if + end do + imod = imod + 1 + end do + end if + + end subroutine cmaq_prod_pm25 + end module cmaq_mod diff --git a/src/drv/cmaq_model_mod.F90 b/src/drv/cmaq_model_mod.F90 index 4fc0afff..f29f312d 100644 --- a/src/drv/cmaq_model_mod.F90 +++ b/src/drv/cmaq_model_mod.F90 @@ -74,7 +74,12 @@ subroutine cmaq_model_init(rc) ! -- initialize emissions call cmaq_emis_init(rc=localrc) - if (aqm_rc_check(localrc, msg="Failed to initialize CMAQ", & + if (aqm_rc_check(localrc, msg="Failed to initialize emissions", & + file=__FILE__, line=__LINE__, rc=rc)) return + + ! -- initialize products + call cmaq_prod_init(rc=localrc) + if (aqm_rc_check(localrc, msg="Failed to initialize products", & file=__FILE__, line=__LINE__, rc=rc)) return end subroutine cmaq_model_init @@ -122,14 +127,19 @@ subroutine cmaq_model_advance(jdate, jtime, tstep, rc) end if ! -- advance model - call cmaq_advance(jdate, jtime, tstep, config % run_aero, rc=localrc) + call cmaq_advance(jdate, jtime, tstep, config % run_aero, config % run_rescld, rc=localrc) if (aqm_rc_check(localrc, msg="Failed to advance CMAQ on local DE", & file=__FILE__, line=__LINE__, rc=rc)) return ! -- export updated species mixing ratios - call cmaq_export(stateOut % tr, stateIn % prl, stateIn % temp, config % species % p_aqm_beg) + call cmaq_export(stateOut % tr, stateIn % prl, stateIn % temp, config % species % p_aqm_beg, config % species % p_diag_beg) if (config % verbose) call cmaq_conc_log(trim(config % name) // ": export") + ! -- update products + call cmaq_prod_update(stateOut % tr, config % species % p_diag_beg, rc=localrc) + if (aqm_rc_check(localrc, msg="Failed to update products", & + file=__FILE__, line=__LINE__, rc=rc)) return + end subroutine cmaq_model_advance diff --git a/src/io/aqmio/aqmio.F90 b/src/io/aqmio/aqmio.F90 index bedc98a4..fc937e00 100644 --- a/src/io/aqmio/aqmio.F90 +++ b/src/io/aqmio/aqmio.F90 @@ -24,9 +24,14 @@ module AQMIO type(ioData), pointer :: IO => null() end type ioWrapper + integer, parameter :: AQMIO_FMT_BIN = 101, & + AQMIO_FMT_NETCDF = 102 private + public :: AQMIO_FMT_BIN + public :: AQMIO_FMT_NETCDF + public :: AQMIO_Create public :: AQMIO_Destroy public :: AQMIO_FileCreate @@ -34,6 +39,7 @@ module AQMIO public :: AQMIO_Close public :: AQMIO_Read public :: AQMIO_ReadTimes + public :: AQMIO_Sync public :: AQMIO_Write contains @@ -332,20 +338,20 @@ subroutine AQMIO_Open(IOComp, fileName, filePath, iomode, iofmt, rc) character(len=*), intent(in) :: fileName character(len=*), intent(in), optional :: filePath character(len=*), intent(in), optional :: iomode - type(ESMF_IOFmt_flag), intent(in), optional :: iofmt + integer, intent(in), optional :: iofmt integer, intent(out), optional :: rc ! -- local variables integer :: localrc integer :: ncStatus integer :: item, localDe, localDeCount, tileCount + integer :: liofmt integer :: cmode logical :: create character(len=ESMF_MAXPATHLEN) :: fullName character(len=6) :: liomode, fmode type(ioWrapper) :: is type(ESMF_Grid) :: grid - type(ESMF_IOFmt_flag) :: liofmt ! -- begin if (present(rc)) rc = ESMF_SUCCESS @@ -363,7 +369,7 @@ subroutine AQMIO_Open(IOComp, fileName, filePath, iomode, iofmt, rc) localDeCount = size(is % IO % IOLayout) - liofmt = ESMF_IOFMT_NETCDF + liofmt = AQMIO_FMT_NETCDF if (present(iofmt)) liofmt = iofmt liomode = "read" @@ -409,7 +415,7 @@ subroutine AQMIO_Open(IOComp, fileName, filePath, iomode, iofmt, rc) else call AQMIO_FileNameGet(fullName, fileName, filePath=filePath) end if - if (liofmt == ESMF_IOFMT_NETCDF) then + if (liofmt == AQMIO_FMT_NETCDF) then #if HAVE_NETCDF if (create) then ncStatus = nf90_create(trim(fullName), cmode, & @@ -442,7 +448,7 @@ subroutine AQMIO_Open(IOComp, fileName, filePath, iomode, iofmt, rc) rcToReturn=rc) return #endif - else if (liofmt == ESMF_IOFMT_BIN) then + else if (liofmt == AQMIO_FMT_BIN) then call ESMF_UtilIOUnitGet (unit=is % IO % IOLayout(localDe) % iounit, rc=localrc) if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & @@ -547,18 +553,18 @@ logical function AQMIO_IsOpen(IOComp, fileName, filePath, iofmt, rc) type(ESMF_GridComp), intent(inout) :: IOComp character(len=*), intent(in) :: fileName character(len=*), intent(in), optional :: filePath - type(ESMF_IOFmt_flag), intent(in), optional :: iofmt + integer, intent(in), optional :: iofmt integer, intent(out), optional :: rc ! -- local variables integer :: localrc integer :: ncStatus integer :: item, localDe, localDeCount, tileCount, pathLen + integer :: liofmt logical :: isFileOpen character(len=ESMF_MAXPATHLEN) :: fullName, pathIn type(ioWrapper) :: is type(ESMF_Grid) :: grid - type(ESMF_IOFmt_flag) :: liofmt ! -- begin if (present(rc)) rc = ESMF_SUCCESS @@ -578,7 +584,7 @@ logical function AQMIO_IsOpen(IOComp, fileName, filePath, iofmt, rc) localDeCount = size(is % IO % IOLayout) - liofmt = ESMF_IOFMT_NETCDF + liofmt = AQMIO_FMT_NETCDF if (present(iofmt)) liofmt = iofmt call ESMF_GridCompGet(IOComp, grid=grid, rc=localrc) @@ -602,7 +608,7 @@ logical function AQMIO_IsOpen(IOComp, fileName, filePath, iofmt, rc) else call AQMIO_FileNameGet(fullName, fileName, filePath=filePath) end if - if (liofmt == ESMF_IOFMT_NETCDF) then + if (liofmt == AQMIO_FMT_NETCDF) then #if HAVE_NETCDF if (is % IO % IOLayout(localDe) % ncid > 0) then ncStatus = nf90_inq_path(is % IO % IOLayout(localDe) % ncid, & @@ -632,6 +638,51 @@ logical function AQMIO_IsOpen(IOComp, fileName, filePath, iofmt, rc) end function AQMIO_IsOpen +!------------------------------------------------------------------------------ + + subroutine AQMIO_Sync(IOComp, rc) + type(ESMF_GridComp), intent(inout) :: IOComp + integer, intent(out), optional :: rc + + ! -- local variables + integer :: localrc + integer :: ncStatus + integer :: item, localDe, localDeCount + type(ioWrapper) :: is + + ! -- begin + if (present(rc)) rc = ESMF_SUCCESS + +#if HAVE_NETCDF + if (.not.ESMF_GridCompIsPetLocal(IOComp)) return + + call ESMF_GridCompGetInternalState(IOComp, is, localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) return ! bail out + + if (.not.associated(is % IO)) return + if (.not.associated(is % IO % IOLayout)) return + + localDeCount = size(is % IO % IOLayout) + + do localDe = 0, localDeCount - 1 + if (is % IO % IOLayout(localDe) % localIOflag) then + if (is % IO % IOLayout(localDe) % ncid > 0) then + ncStatus = nf90_sync(is % IO % IOLayout(localDe) % ncid) + if (ESMF_LogFoundNetCDFError(ncerrToCheck=ncStatus, & + msg="Error syncing NetCDF data set", & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) return ! bail out + end if + end if + end do +#endif + + end subroutine AQMIO_Sync + !------------------------------------------------------------------------------ subroutine AQMIO_Write(IOComp, fieldList, fieldNameList, timeSlice, & @@ -642,21 +693,21 @@ subroutine AQMIO_Write(IOComp, fieldList, fieldNameList, timeSlice, & integer, intent(in), optional :: timeSlice character(len=*), intent(in), optional :: fileName character(len=*), intent(in), optional :: filePath - type(ESMF_IOFmt_flag), intent(in), optional :: iofmt + integer, intent(in), optional :: iofmt integer, intent(out), optional :: rc ! -- local variables integer :: localrc integer :: item, localDe, localDeCount + integer :: liofmt type(ioWrapper) :: is - type(ESMF_IOFmt_flag) :: liofmt ! -- begin if (present(rc)) rc = ESMF_SUCCESS if (.not.ESMF_GridCompIsPetLocal(IOComp)) return - liofmt = ESMF_IOFMT_NETCDF + liofmt = AQMIO_FMT_NETCDF if (present(iofmt)) liofmt = iofmt if (present(fieldNameList)) then @@ -736,7 +787,7 @@ subroutine AQMIO_Read(IOComp, fieldList, fieldNameList, timeSlice, & integer, intent(in), optional :: timeSlice character(len=*), intent(in), optional :: fileName character(len=*), intent(in), optional :: filePath - type(ESMF_IOFmt_flag), intent(in), optional :: iofmt + integer, intent(in), optional :: iofmt integer, intent(out), optional :: rc ! -- local variables @@ -833,7 +884,7 @@ subroutine AQMIO_ReadTimes(IOComp, variableName, timesList, fileName, filePath, type(ESMF_Time), intent(inout), pointer :: timesList(:) character(len=*), intent(in), optional :: fileName character(len=*), intent(in), optional :: filePath - type(ESMF_IOFmt_flag), intent(in), optional :: iofmt + integer, intent(in), optional :: iofmt integer, intent(out), optional :: rc ! -- local variables @@ -857,7 +908,7 @@ subroutine AQMIO_ReadTimes(IOComp, variableName, timesList, fileName, filePath, if (.not.associated(is % IO % IOLayout)) return if (present(iofmt)) then - if (.not.(iofmt == ESMF_IOFMT_NETCDF)) then + if (.not.(iofmt == AQMIO_FMT_NETCDF)) then call ESMF_LogSetError(ESMF_RC_ARG_INCOMP, & msg="This function only supports NetCDF I/O", & line=__LINE__, & @@ -925,6 +976,7 @@ subroutine AQMIO_FieldAccess(IOComp, field, action, variableName, timeSlice, rc) integer :: localrc integer :: localDe, localDeCount, rank integer :: de, deCount, dimCount, tile, tileCount, ungriddedCount + integer :: iofmt integer, dimension(:), pointer :: ungriddedLBound, ungriddedUBound integer, dimension(:), allocatable :: deToTileMap, localDeToDeMap integer, dimension(:,:), allocatable :: minIndexPDe, maxIndexPDe @@ -936,7 +988,6 @@ subroutine AQMIO_FieldAccess(IOComp, field, action, variableName, timeSlice, rc) type(ESMF_GeomType_flag) :: geomtype type(ESMF_StaggerLoc) :: staggerloc type(ESMF_TypeKind_Flag) :: typekind - type(ESMF_IOFmt_flag) :: iofmt ! -- begin if (present(rc)) rc = ESMF_SUCCESS @@ -2573,8 +2624,10 @@ subroutine AQMIO_VariableCreate(IOLayout, field, unlimited, varId, rc) integer, dimension(:,:), allocatable :: minIndexPTile, maxIndexPTile character(len=ESMF_MAXSTR) :: fieldName character(len=ESMF_MAXSTR) :: dimName + character(len=ESMF_MAXSTR) :: units type(ESMF_DistGrid) :: distgrid type(ESMF_Grid) :: grid + type(ESMF_Info) :: info type(ESMF_StaggerLoc) :: staggerloc type(ESMF_TypeKind_Flag) :: typekind @@ -2745,6 +2798,28 @@ subroutine AQMIO_VariableCreate(IOLayout, field, unlimited, varId, rc) file=__FILE__, & rcToReturn=rc)) return ! bail out + ! -- add units if available + call ESMF_InfoGetFromHost(field, info, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) return ! bail out + + call ESMF_InfoGet(info, "units", units, default="", rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) return ! bail out + + if (len_trim(units) > 0) then + ncStatus = nf90_put_att(IOLayout % ncid, lvarId, "units", trim(units)) + if (ESMF_LogFoundNetCDFError(ncerrToCheck=ncStatus, & + msg="Error adding units to NetCDF variable: "//trim(fieldName), & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) return ! bail out + end if + ncStatus = nf90_enddef(IOLayout % ncid) if (ESMF_LogFoundNetCDFError(ncerrToCheck=ncStatus, & msg="Error defining NetCDF data set", & diff --git a/src/io/ioapi/Makefile.am b/src/io/ioapi/Makefile.am index a7087123..5676ec89 100644 --- a/src/io/ioapi/Makefile.am +++ b/src/io/ioapi/Makefile.am @@ -7,7 +7,7 @@ libioapi_a_SOURCES += crlf.F currec.f currstep.f dt2str.f findc.f getefile.F ind poly.f promptmfile.f sec2time.f secsdiff.F setlam.f sortic.f str2real.f time2sec.f upcase.f wkday.F yr2day.F libioapi_a_SOURCES += m3exit.F90 m3mesg.F90 m3msg2.F90 m3warn.F90 m3utilio.F90 -libioapi_a_FFLAGS = $(ESMF_F90COMPILEOPTS) $(ESMF_F90COMPILEPATHS) $(ESMF_F90COMPILEFREECPP) $(ESMF_F90COMPILECPPFLAGS) +libioapi_a_FFLAGS = $(CCTM_FFLAGS) $(ESMF_F90COMPILEOPTS) $(ESMF_F90COMPILEPATHS) $(ESMF_F90COMPILEFREECPP) $(ESMF_F90COMPILECPPFLAGS) libioapi_a_FCFLAGS = $(ESMF_F90COMPILEOPTS) $(ESMF_F90COMPILEPATHS) $(ESMF_F90COMPILEFREECPP) $(ESMF_F90COMPILECPPFLAGS) libioapi_a_FCFLAGS += -DSUBST_FILES_ID=\"FILES_CTM.EXT\" diff --git a/src/io/ioapi/Makefile.in b/src/io/ioapi/Makefile.in index 1401c367..6d52ee3e 100644 --- a/src/io/ioapi/Makefile.in +++ b/src/io/ioapi/Makefile.in @@ -326,7 +326,7 @@ libioapi_a_SOURCES = FDESC3.EXT PARMS3.EXT crlf.F currec.f currstep.f \ setlam.f sortic.f str2real.f time2sec.f upcase.f wkday.F \ yr2day.F m3exit.F90 m3mesg.F90 m3msg2.F90 m3warn.F90 \ m3utilio.F90 -libioapi_a_FFLAGS = $(ESMF_F90COMPILEOPTS) $(ESMF_F90COMPILEPATHS) $(ESMF_F90COMPILEFREECPP) $(ESMF_F90COMPILECPPFLAGS) +libioapi_a_FFLAGS = $(CCTM_FFLAGS) $(ESMF_F90COMPILEOPTS) $(ESMF_F90COMPILEPATHS) $(ESMF_F90COMPILEFREECPP) $(ESMF_F90COMPILECPPFLAGS) libioapi_a_FCFLAGS = $(ESMF_F90COMPILEOPTS) $(ESMF_F90COMPILEPATHS) \ $(ESMF_F90COMPILEFREECPP) $(ESMF_F90COMPILECPPFLAGS) \ -DSUBST_FILES_ID=\"FILES_CTM.EXT\" -I \ diff --git a/src/model/Makefile.am b/src/model/Makefile.am index 280d509c..c5fed5d3 100644 --- a/src/model/Makefile.am +++ b/src/model/Makefile.am @@ -53,6 +53,13 @@ CLOUD = $(CCTM)/cloud/acm_ae6 libCLOUD = $(CLOUD)/$(libCCTM)- libCCTM_a_SOURCES += \ $(CLOUD)/hlconst.F + $(CLOUD)/cldproc_acm.F + $(CLOUD)/getalpha.F + $(CLOUD)/indexn.f + $(CLOUD)/rescld.F + $(CLOUD)/scavwdep.F + $(CLOUD)/aq_map.F + $(CLOUD)/AQ_DATA.F # depv DEPV = $(CCTM)/depv/m3dry @@ -254,6 +261,7 @@ libCCTM_a_CPPFLAGS += -DSUBST_COMM=NOOP_COMM libCCTM_a_CPPFLAGS += -DSUBST_BARRIER=NOOP_BARRIER libCCTM_a_CPPFLAGS += -DSUBST_SUBGRID_INDEX=NOOP_SUBGRID_INDEX libCCTM_a_CPPFLAGS += -DMOSAIC_MOD=MOSAIC_MODULE -DMosaic_Mod=Mosaic_Module +libCCTM_a_CPPFLAGS += -DAQCHEM=DUMMY_AQCHEM -DCONVCLD_ACM=DUMMY_CONVCLD_ACM libCCTM_a_CPPFLAGS += -DEDDYX=DUMMY_EDDYX libCCTM_a_CPPFLAGS += -DOPCONC=DUMMY_OPCONC -DOPACONC=DUMMY_OPACONC libCCTM_a_CPPFLAGS += -DOPWDEP=DUMMY_OPWDEP -DWR_INIT=DUMMY_WR_INIT diff --git a/src/model/Makefile.in b/src/model/Makefile.in index 42b6fd24..4177970a 100644 --- a/src/model/Makefile.in +++ b/src/model/Makefile.in @@ -468,11 +468,11 @@ libCCTM_a_SOURCES = $(AERO)/AERO_DATA.F $(AERO)/aero_depv.F \ $(DEPV)/MOSAIC_MOD.F $(DEPV)/opdepv_diag.F \ $(DEPV)/opdepv_mos.F $(DEPV)/opdepv_fst.F $(DEPV)/m3dry.F \ $(EMIS)/BEIS_DEFN.F $(EMIS)/BIOG_EMIS.F $(EMIS)/cropcal.F \ - $(EMIS)/EMIS_DEFN.F $(EMIS)/LTNG_DEFN.F \ - $(EMIS)/LUS_DEFN.F $(EMIS)/MGEMIS.F $(EMIS)/opemis.F \ - $(EMIS)/PTBILIN.F $(EMIS)/SSEMIS.F $(EMIS)/STK_EMIS.F \ - $(EMIS)/STK_PRMS.F $(EMIS)/tfabove.F $(EMIS)/tfbelow.F \ - $(EMIS)/UDTYPES.F $(GAS)/degrade_data.F $(GAS)/degrade.F \ + $(EMIS)/EMIS_DEFN.F $(EMIS)/LTNG_DEFN.F $(EMIS)/LUS_DEFN.F \ + $(EMIS)/MGEMIS.F $(EMIS)/opemis.F $(EMIS)/PTBILIN.F \ + $(EMIS)/SSEMIS.F $(EMIS)/STK_EMIS.F $(EMIS)/STK_PRMS.F \ + $(EMIS)/tfabove.F $(EMIS)/tfbelow.F $(EMIS)/UDTYPES.F \ + $(GAS)/degrade_data.F $(GAS)/degrade.F \ $(GAS)/DEGRADE_SETUP_TOX.F $(GAS)/final_degrade.F \ $(GAS)/find_degraded.F $(GAS)/hrdata_mod.F $(GAS)/hrdriver.F \ $(GAS)/hrg1.F $(GAS)/hrg2.F $(GAS)/hrg3.F $(GAS)/hrg4.F \ @@ -504,14 +504,14 @@ libCCTM_a_SOURCES = $(AERO)/AERO_DATA.F $(AERO)/aero_depv.F \ $(STENEX)/noop_util_module.f $(UTIL)/bmatvec.F \ $(UTIL)/findex.f $(UTIL)/get_envlist.f $(UTIL)/setup_logdev.F \ $(UTIL)/subhdomain.F $(UTIL)/UTILIO_DEFN.F \ - $(VDIFF)/aero_sedv.F \ - $(VDIFF)/conv_cgrid.F $(VDIFF)/matrix1.F $(VDIFF)/opddep.F \ - $(VDIFF)/opddep_fst.F $(VDIFF)/opddep_mos.F $(VDIFF)/rddepv.F \ - $(VDIFF)/SEDIMENTATION.F $(VDIFF)/tri.F $(VDIFF)/VDIFF_DIAG.F \ - $(VDIFF)/VDIFF_MAP.F $(VDIFF)/vdiffproc.F \ - $(localCCTM)/o3totcol.f $(localCCTM)/vdiffacmx.F \ - $(localCCTM)/PTMAP.F $(localCCTM)/PT3D_DEFN.F \ - $(localCCTM)/ASX_DATA_MOD.F $(localCCTM)/DUST_EMIS.F + $(VDIFF)/aero_sedv.F $(VDIFF)/conv_cgrid.F $(VDIFF)/matrix1.F \ + $(VDIFF)/opddep.F $(VDIFF)/opddep_fst.F $(VDIFF)/opddep_mos.F \ + $(VDIFF)/rddepv.F $(VDIFF)/SEDIMENTATION.F $(VDIFF)/tri.F \ + $(VDIFF)/VDIFF_DIAG.F $(VDIFF)/VDIFF_MAP.F \ + $(VDIFF)/vdiffproc.F $(localCCTM)/o3totcol.f \ + $(localCCTM)/vdiffacmx.F $(localCCTM)/PTMAP.F \ + $(localCCTM)/PT3D_DEFN.F $(localCCTM)/ASX_DATA_MOD.F \ + $(localCCTM)/DUST_EMIS.F # local version of CCTM source files localCCTM = $(builddir)/src @@ -591,6 +591,7 @@ libCCTM_a_CPPFLAGS = -DSUBST_FILES_ID=\"FILES_CTM.EXT\" \ -DSUBST_BARRIER=NOOP_BARRIER \ -DSUBST_SUBGRID_INDEX=NOOP_SUBGRID_INDEX \ -DMOSAIC_MOD=MOSAIC_MODULE -DMosaic_Mod=Mosaic_Module \ + -DAQCHEM=DUMMY_AQCHEM -DCONVCLD_ACM=DUMMY_CONVCLD_ACM \ -DEDDYX=DUMMY_EDDYX -DOPCONC=DUMMY_OPCONC \ -DOPACONC=DUMMY_OPACONC -DOPWDEP=DUMMY_OPWDEP \ -DWR_INIT=DUMMY_WR_INIT -Dverbose_aero -Dverbose_gas -Dmpas \ @@ -1019,10 +1020,12 @@ $(localCCTM)/libCCTM_a-PTMAP.$(OBJEXT): $(localCCTM)/$(am__dirstamp) \ $(localCCTM)/libCCTM_a-PT3D_DEFN.$(OBJEXT): \ $(localCCTM)/$(am__dirstamp) \ $(localCCTM)/$(DEPDIR)/$(am__dirstamp) -$(localCCTM)/libCCTM_a-ASX_DATA_MOD.$(OBJEXT): $(localCCTM)/$(am__dirstamp) \ - $(localCCTM)/$(DEPDIR)/$(am__dirstamp) -$(localCCTM)/libCCTM_a-DUST_EMIS.$(OBJEXT): $(localCCTM)/$(am__dirstamp) \ - $(localCCTM)/$(DEPDIR)/$(am__dirstamp) +$(localCCTM)/libCCTM_a-ASX_DATA_MOD.$(OBJEXT): \ + $(localCCTM)/$(am__dirstamp) \ + $(localCCTM)/$(DEPDIR)/$(am__dirstamp) +$(localCCTM)/libCCTM_a-DUST_EMIS.$(OBJEXT): \ + $(localCCTM)/$(am__dirstamp) \ + $(localCCTM)/$(DEPDIR)/$(am__dirstamp) libCCTM.a: $(libCCTM_a_OBJECTS) $(libCCTM_a_DEPENDENCIES) $(EXTRA_libCCTM_a_DEPENDENCIES) $(AM_V_at)-rm -f libCCTM.a @@ -1274,14 +1277,6 @@ $(EMIS)/libCCTM_a-cropcal.o: $(EMIS)/cropcal.F $(EMIS)/libCCTM_a-cropcal.obj: $(EMIS)/cropcal.F $(AM_V_PPF77)$(F77) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCCTM_a_CPPFLAGS) $(CPPFLAGS) $(libCCTM_a_FFLAGS) $(FFLAGS) -c -o $(EMIS)/libCCTM_a-cropcal.obj `if test -f '$(EMIS)/cropcal.F'; then $(CYGPATH_W) '$(EMIS)/cropcal.F'; else $(CYGPATH_W) '$(srcdir)/$(EMIS)/cropcal.F'; fi` -$(localCCTM)/libCCTM_a-DUST_EMIS.o: $(localCCTM)/DUST_EMIS.F - $(AM_V_PPF77)$(F77) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCCTM_a_CPPFLAGS) $(CPPFLAGS) $(libCCTM_a_FFLAGS) $(FFLAGS) -c -o $(localCCTM)/libCCTM_a-DUST_EMIS.o `test -f '$(local -CCTM)/DUST_EMIS.F' || echo '$(srcdir)/'`$(localCCTM)/DUST_EMIS.F - -$(localCCTM)/libCCTM_a-DUST_EMIS.obj: $(localCCTM)/DUST_EMIS.F - $(AM_V_PPF77)$(F77) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCCTM_a_CPPFLAGS) $(CPPFLAGS) $(libCCTM_a_FFLAGS) $(FFLAGS) -c -o $(localCCTM)/libCCTM_a-DUST_EMIS.obj `if test -f '$( -localCCTM)/DUST_EMIS.F'; then $(CYGPATH_W) '$(localCCTM)/DUST_EMIS.F'; else $(CYGPATH_W) '$(srcdir)/$(localCCTM)/DUST_EMIS.F'; fi` - $(EMIS)/libCCTM_a-EMIS_DEFN.o: $(EMIS)/EMIS_DEFN.F $(AM_V_PPF77)$(F77) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCCTM_a_CPPFLAGS) $(CPPFLAGS) $(libCCTM_a_FFLAGS) $(FFLAGS) -c -o $(EMIS)/libCCTM_a-EMIS_DEFN.o `test -f '$(EMIS)/EMIS_DEFN.F' || echo '$(srcdir)/'`$(EMIS)/EMIS_DEFN.F @@ -1618,12 +1613,6 @@ $(VDIFF)/libCCTM_a-aero_sedv.o: $(VDIFF)/aero_sedv.F $(VDIFF)/libCCTM_a-aero_sedv.obj: $(VDIFF)/aero_sedv.F $(AM_V_PPF77)$(F77) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCCTM_a_CPPFLAGS) $(CPPFLAGS) $(libCCTM_a_FFLAGS) $(FFLAGS) -c -o $(VDIFF)/libCCTM_a-aero_sedv.obj `if test -f '$(VDIFF)/aero_sedv.F'; then $(CYGPATH_W) '$(VDIFF)/aero_sedv.F'; else $(CYGPATH_W) '$(srcdir)/$(VDIFF)/aero_sedv.F'; fi` -$(liblocalCCTM)/libCCTM_a-ASX_DATA_MOD.o: $(liblocalCCTM)/ASX_DATA_MOD.F - $(AM_V_PPF77)$(F77) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCCTM_a_CPPFLAGS) $(CPPFLAGS) $(libCCTM_a_FFLAGS) $(FFLAGS) -c -o $(liblocalCCTM)/libCCTM_a-ASX_DATA_MOD.o `test -f '$(liblocalCCTM)/ASX_DATA_MOD.F' || echo '$(srcdir)/'`$(liblocalCCTM)/ASX_DATA_MOD.F - -$(liblocalCCTM)/libCCTM_a-ASX_DATA_MOD.obj: $(liblocalCCTM)/ASX_DATA_MOD.F - $(AM_V_PPF77)$(F77) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCCTM_a_CPPFLAGS) $(CPPFLAGS) $(libCCTM_a_FFLAGS) $(FFLAGS) -c -o $(liblocalCCTM)/libCCTM_a-ASX_DATA_MOD.obj `if test -f '$(liblocalCCTM)/ASX_DATA_MOD.F'; then $(CYGPATH_W) '$(liblocalCCTM)/ASX_DATA_MOD.F'; else $(CYGPATH_W) '$(srcdir)/$(liblocalCCTM)/ASX_DATA_MOD.F'; fi` - $(VDIFF)/libCCTM_a-conv_cgrid.o: $(VDIFF)/conv_cgrid.F $(AM_V_PPF77)$(F77) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCCTM_a_CPPFLAGS) $(CPPFLAGS) $(libCCTM_a_FFLAGS) $(FFLAGS) -c -o $(VDIFF)/libCCTM_a-conv_cgrid.o `test -f '$(VDIFF)/conv_cgrid.F' || echo '$(srcdir)/'`$(VDIFF)/conv_cgrid.F @@ -1707,6 +1696,18 @@ $(localCCTM)/libCCTM_a-PT3D_DEFN.o: $(localCCTM)/PT3D_DEFN.F $(localCCTM)/libCCTM_a-PT3D_DEFN.obj: $(localCCTM)/PT3D_DEFN.F $(AM_V_PPF77)$(F77) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCCTM_a_CPPFLAGS) $(CPPFLAGS) $(libCCTM_a_FFLAGS) $(FFLAGS) -c -o $(localCCTM)/libCCTM_a-PT3D_DEFN.obj `if test -f '$(localCCTM)/PT3D_DEFN.F'; then $(CYGPATH_W) '$(localCCTM)/PT3D_DEFN.F'; else $(CYGPATH_W) '$(srcdir)/$(localCCTM)/PT3D_DEFN.F'; fi` + +$(localCCTM)/libCCTM_a-ASX_DATA_MOD.o: $(localCCTM)/ASX_DATA_MOD.F + $(AM_V_PPF77)$(F77) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCCTM_a_CPPFLAGS) $(CPPFLAGS) $(libCCTM_a_FFLAGS) $(FFLAGS) -c -o $(localCCTM)/libCCTM_a-ASX_DATA_MOD.o `test -f '$(localCCTM)/ASX_DATA_MOD.F' || echo '$(srcdir)/'`$(localCCTM)/ASX_DATA_MOD.F + +$(localCCTM)/libCCTM_a-ASX_DATA_MOD.obj: $(localCCTM)/ASX_DATA_MOD.F + $(AM_V_PPF77)$(F77) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCCTM_a_CPPFLAGS) $(CPPFLAGS) $(libCCTM_a_FFLAGS) $(FFLAGS) -c -o $(localCCTM)/libCCTM_a-ASX_DATA_MOD.obj `if test -f '$(localCCTM)/ASX_DATA_MOD.F'; then $(CYGPATH_W) '$(localCCTM)/ASX_DATA_MOD.F'; else $(CYGPATH_W) '$(srcdir)/$(localCCTM)/ASX_DATA_MOD.F'; fi` + +$(localCCTM)/libCCTM_a-DUST_EMIS.o: $(localCCTM)/DUST_EMIS.F + $(AM_V_PPF77)$(F77) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCCTM_a_CPPFLAGS) $(CPPFLAGS) $(libCCTM_a_FFLAGS) $(FFLAGS) -c -o $(localCCTM)/libCCTM_a-DUST_EMIS.o `test -f '$(localCCTM)/DUST_EMIS.F' || echo '$(srcdir)/'`$(localCCTM)/DUST_EMIS.F + +$(localCCTM)/libCCTM_a-DUST_EMIS.obj: $(localCCTM)/DUST_EMIS.F + $(AM_V_PPF77)$(F77) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCCTM_a_CPPFLAGS) $(CPPFLAGS) $(libCCTM_a_FFLAGS) $(FFLAGS) -c -o $(localCCTM)/libCCTM_a-DUST_EMIS.obj `if test -f '$(localCCTM)/DUST_EMIS.F'; then $(CYGPATH_W) '$(localCCTM)/DUST_EMIS.F'; else $(CYGPATH_W) '$(srcdir)/$(localCCTM)/DUST_EMIS.F'; fi` .F.f: $(F77COMPILE) -F $< @@ -2147,6 +2148,13 @@ uninstall-am: mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am + $(CLOUD)/cldproc_acm.F + $(CLOUD)/getalpha.F + $(CLOUD)/indexn.f + $(CLOUD)/rescld.F + $(CLOUD)/scavwdep.F + $(CLOUD)/aq_map.F + $(CLOUD)/AQ_DATA.F include $(ESMFMKFILE) @@ -2550,13 +2558,14 @@ $(liblocalCCTM)PT3D_DEFN.$(OBJEXT) : $(libAERO)AERO_DATA.$(OBJEXT) \ $(liblocalCCTM)PTMAP.$(OBJEXT) $(libMECHS)RXNS_DATA_MODULE.$(OBJEXT) \ $(libEMIS)STK_EMIS.$(OBJEXT) $(libUTIL)UTILIO_DEFN.$(OBJEXT) $(liblocalCCTM)ASX_DATA_MOD.$(OBJEXT) : $(ICL)/const/CONST.EXT $(ICL)/filenames/FILES_CTM.EXT $(ICL)/mpi/PE_COMM.EXT \ - $(libDEPV)DEPVVARS.$(OBJEXT) $(libGRID)GRID_CONF.$(OBJEXT) \ - $(libDEPV)LSM_MOD.$(OBJEXT) $(libSTENEX)noop_modules.$(OBJEXT) \ - $(libUTIL)UTILIO_DEFN.$(OBJEXT) + $(libDEPV)DEPVVARS.$(OBJEXT) $(libGRID)GRID_CONF.$(OBJEXT) \ + $(libDEPV)LSM_MOD.$(OBJEXT) $(libSTENEX)noop_modules.$(OBJEXT) \ + $(libUTIL)UTILIO_DEFN.$(OBJEXT) $(liblocalCCTM)DUST_EMIS.$(OBJEXT) : $(ICL)/const/CONST.EXT $(ICL)/filenames/FILES_CTM.EXT \ - $(libAERO)AERO_DATA.$(OBJEXT) $(liblocalCCTM)ASX_DATA_MOD.$(OBJEXT) \ - $(libGRID)GRID_CONF.$(OBJEXT) $(libGRID)HGRD_DEFN.$(OBJEXT) \ - $(libEMIS)LUS_DEFN.$(OBJEXT) $(libUTIL)UTILIO_DEFN.$(OBJEXT) + $(libAERO)AERO_DATA.$(OBJEXT) $(liblocalCCTM)ASX_DATA_MOD.$(OBJEXT) \ + $(libGRID)GRID_CONF.$(OBJEXT) $(libGRID)HGRD_DEFN.$(OBJEXT) \ + $(libEMIS)LUS_DEFN.$(OBJEXT) $(libUTIL)UTILIO_DEFN.$(OBJEXT) + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/src/shr/Makefile.am b/src/shr/Makefile.am index eb692999..58be7f69 100644 --- a/src/shr/Makefile.am +++ b/src/shr/Makefile.am @@ -2,7 +2,7 @@ noinst_LIBRARIES = libshr.a libshr_a_SOURCES = aqm_config_mod.F90 aqm_const_mod.F90 \ aqm_domain_mod.F90 aqm_emis_mod.F90 aqm_fires_mod.F90 aqm_internal_mod.F90 \ - aqm_model_mod.F90 aqm_rc_mod.F90 aqm_methods.F90 aqm_species_mod.F90 \ + aqm_model_mod.F90 aqm_rc_mod.F90 aqm_methods.F90 aqm_prod_mod.F90 aqm_species_mod.F90 \ aqm_state_mod.F90 aqm_tools_mod.F90 aqm_types_mod.F90 libshr_a_CPPFLAGS = -DSUBST_CONST=\"CONST.EXT\" -DSUBST_FILES_ID=\"FILES_CTM.EXT\" @@ -40,5 +40,7 @@ libshr_a-aqm_model_mod.$(OBJEXT): \ libshr_a-aqm_methods.$(OBJEXT): libshr_a-aqm_model_mod.$(OBJEXT) libshr_a-aqm_emis_mod.$(OBJEXT) \ libshr_a-aqm_rc_mod.$(OBJEXT) libshr_a-aqm_types_mod.$(OBJEXT) \ libshr_a-aqm_config_mod.$(OBJEXT) libshr_a-aqm_const_mod.$(OBJEXT) +libshr_a-aqm_prod_mod.$(OBJEXT): libshr_a-aqm_emis_mod.$(OBJEXT) \ + libshr_a-aqm_internal_mod.$(OBJEXT) libshr_a-aqm_rc_mod.$(OBJEXT) libshr_a-aqm_state_mod.$(OBJEXT): libshr_a-aqm_types_mod.$(OBJEXT) libshr_a-aqm_tools_mod.$(OBJEXT): libshr_a-aqm_types_mod.$(OBJEXT) diff --git a/src/shr/Makefile.in b/src/shr/Makefile.in index 05af7033..5d28411a 100644 --- a/src/shr/Makefile.in +++ b/src/shr/Makefile.in @@ -104,7 +104,7 @@ am_libshr_a_OBJECTS = libshr_a-aqm_config_mod.$(OBJEXT) \ libshr_a-aqm_fires_mod.$(OBJEXT) \ libshr_a-aqm_internal_mod.$(OBJEXT) \ libshr_a-aqm_model_mod.$(OBJEXT) libshr_a-aqm_rc_mod.$(OBJEXT) \ - libshr_a-aqm_methods.$(OBJEXT) \ + libshr_a-aqm_methods.$(OBJEXT) libshr_a-aqm_prod_mod.$(OBJEXT) \ libshr_a-aqm_species_mod.$(OBJEXT) \ libshr_a-aqm_state_mod.$(OBJEXT) \ libshr_a-aqm_tools_mod.$(OBJEXT) \ @@ -289,7 +289,7 @@ top_srcdir = @top_srcdir@ noinst_LIBRARIES = libshr.a libshr_a_SOURCES = aqm_config_mod.F90 aqm_const_mod.F90 \ aqm_domain_mod.F90 aqm_emis_mod.F90 aqm_fires_mod.F90 aqm_internal_mod.F90 \ - aqm_model_mod.F90 aqm_rc_mod.F90 aqm_methods.F90 aqm_species_mod.F90 \ + aqm_model_mod.F90 aqm_rc_mod.F90 aqm_methods.F90 aqm_prod_mod.F90 aqm_species_mod.F90 \ aqm_state_mod.F90 aqm_tools_mod.F90 aqm_types_mod.F90 libshr_a_CPPFLAGS = -DSUBST_CONST=\"CONST.EXT\" -DSUBST_FILES_ID=\"FILES_CTM.EXT\" @@ -408,6 +408,12 @@ libshr_a-aqm_methods.o: aqm_methods.F90 libshr_a-aqm_methods.obj: aqm_methods.F90 $(AM_V_PPFC)$(FC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshr_a_CPPFLAGS) $(CPPFLAGS) $(libshr_a_FCFLAGS) $(FCFLAGS) -c -o libshr_a-aqm_methods.obj `if test -f 'aqm_methods.F90'; then $(CYGPATH_W) 'aqm_methods.F90'; else $(CYGPATH_W) '$(srcdir)/aqm_methods.F90'; fi` +libshr_a-aqm_prod_mod.o: aqm_prod_mod.F90 + $(AM_V_PPFC)$(FC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshr_a_CPPFLAGS) $(CPPFLAGS) $(libshr_a_FCFLAGS) $(FCFLAGS) -c -o libshr_a-aqm_prod_mod.o `test -f 'aqm_prod_mod.F90' || echo '$(srcdir)/'`aqm_prod_mod.F90 + +libshr_a-aqm_prod_mod.obj: aqm_prod_mod.F90 + $(AM_V_PPFC)$(FC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshr_a_CPPFLAGS) $(CPPFLAGS) $(libshr_a_FCFLAGS) $(FCFLAGS) -c -o libshr_a-aqm_prod_mod.obj `if test -f 'aqm_prod_mod.F90'; then $(CYGPATH_W) 'aqm_prod_mod.F90'; else $(CYGPATH_W) '$(srcdir)/aqm_prod_mod.F90'; fi` + libshr_a-aqm_species_mod.o: aqm_species_mod.F90 $(AM_V_PPFC)$(FC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshr_a_CPPFLAGS) $(CPPFLAGS) $(libshr_a_FCFLAGS) $(FCFLAGS) -c -o libshr_a-aqm_species_mod.o `test -f 'aqm_species_mod.F90' || echo '$(srcdir)/'`aqm_species_mod.F90 @@ -656,6 +662,8 @@ libshr_a-aqm_model_mod.$(OBJEXT): \ libshr_a-aqm_methods.$(OBJEXT): libshr_a-aqm_model_mod.$(OBJEXT) libshr_a-aqm_emis_mod.$(OBJEXT) \ libshr_a-aqm_rc_mod.$(OBJEXT) libshr_a-aqm_types_mod.$(OBJEXT) \ libshr_a-aqm_config_mod.$(OBJEXT) libshr_a-aqm_const_mod.$(OBJEXT) +libshr_a-aqm_prod_mod.$(OBJEXT): libshr_a-aqm_emis_mod.$(OBJEXT) \ + libshr_a-aqm_internal_mod.$(OBJEXT) libshr_a-aqm_rc_mod.$(OBJEXT) libshr_a-aqm_state_mod.$(OBJEXT): libshr_a-aqm_types_mod.$(OBJEXT) libshr_a-aqm_tools_mod.$(OBJEXT): libshr_a-aqm_types_mod.$(OBJEXT) diff --git a/src/shr/aqm_config_mod.F90 b/src/shr/aqm_config_mod.F90 index 971f8b20..56e94019 100644 --- a/src/shr/aqm_config_mod.F90 +++ b/src/shr/aqm_config_mod.F90 @@ -35,6 +35,7 @@ module aqm_config_mod logical :: ctm_wb_dust = .false. logical :: init_conc = .false. logical :: run_aero = .false. + logical :: run_rescld = .false. logical :: fengsha_yn = .true. logical :: verbose = .false. type(aqm_species_type), pointer :: species => null() @@ -142,6 +143,14 @@ subroutine aqm_config_read(model, config, rc) rcToReturn=rc)) & return ! bail out + call ESMF_ConfigGetAttribute(cf, config % run_rescld, & + label="run_rescld:", default=.true., rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + ! -- read start up settings call ESMF_ConfigGetAttribute(cf, config % init_conc, & label="init_concentrations:", default=config % initial_run, rc=localrc) @@ -288,7 +297,7 @@ subroutine aqm_config_species_init(config, rc) end if ! -- initialize diagnostic tracers - if (config % ctm_pmdiag) config % species % ndiag = 3 + if (config % ctm_pmdiag) config % species % ndiag = 4 end subroutine aqm_config_species_init @@ -513,6 +522,13 @@ subroutine aqm_config_log(config, name, rc) call ESMF_LogWrite(trim(name) // ": config: read: run_aerosol: false", & ESMF_LOGMSG_INFO, rc=localrc) end if + if (config % run_rescld) then + call ESMF_LogWrite(trim(name) // ": config: read: run_rescld: true", & + ESMF_LOGMSG_INFO, rc=localrc) + else + call ESMF_LogWrite(trim(name) // ": config: read: run_rescld: false", & + ESMF_LOGMSG_INFO, rc=localrc) + end if if (config % fengsha_yn) then call ESMF_LogWrite(trim(name) // ": config: read: fengsha_yn: true", & ESMF_LOGMSG_INFO, rc=localrc) diff --git a/src/shr/aqm_emis_mod.F90 b/src/shr/aqm_emis_mod.F90 index 12cf8171..f9b4fa1b 100644 --- a/src/shr/aqm_emis_mod.F90 +++ b/src/shr/aqm_emis_mod.F90 @@ -23,6 +23,7 @@ module aqm_emis_mod public :: aqm_emis_init public :: aqm_emis_finalize + public :: aqm_emis_data_get public :: aqm_emis_get public :: aqm_emis_desc public :: aqm_emis_update @@ -196,8 +197,10 @@ subroutine aqm_emis_src_create(config, em, rc) em(item) % file = "" em(item) % frequency = "" em(item) % format = "netcdf" - em(item) % iofmt = ESMF_IOFMT_NETCDF + em(item) % iomode = "read" + em(item) % iofmt = AQMIO_FMT_NETCDF em(item) % irec = 0 + em(item) % sync = .false. em(item) % verbose = .false. em(item) % logprefix = "" em(item) % period = "" @@ -205,6 +208,7 @@ subroutine aqm_emis_src_create(config, em, rc) em(item) % specfile = "" em(item) % specprofile = "" nullify(em(item) % species) + nullify(em(item) % sources) nullify(em(item) % units) nullify(em(item) % factors) nullify(em(item) % fields) @@ -238,7 +242,7 @@ subroutine aqm_emis_src_init(model, em, rc) integer :: columnCount, rowCount integer :: fieldCount, spcsCount, item integer :: aqm_emis_num - logical :: eolFlag + logical :: eolFlag, readFactors character(len=ESMF_MAXSTR) :: value character(len=ESMF_MAXSTR) :: msgString character(len=ESMF_MAXSTR), allocatable :: tmpSourceList(:) @@ -311,9 +315,9 @@ subroutine aqm_emis_src_init(model, em, rc) select case (trim(em % format)) case ("binary") - em % iofmt = ESMF_IOFMT_BIN + em % iofmt = AQMIO_FMT_BIN case ("netcdf") - em % iofmt = ESMF_IOFMT_NETCDF + em % iofmt = AQMIO_FMT_NETCDF case default call ESMF_LogSetError(ESMF_RC_NOT_VALID, & msg="- invalid emission format: "//trim(em % format), & @@ -382,7 +386,7 @@ subroutine aqm_emis_src_init(model, em, rc) rcToReturn=rc)) & return ! bail out - if (em % iofmt == ESMF_IOFMT_BIN) then + if (em % iofmt == AQMIO_FMT_BIN) then if (trim(em % frequency) /= "static") then em % frequency = "static" if (em % verbose) then @@ -469,6 +473,8 @@ subroutine aqm_emis_src_init(model, em, rc) return ! bail out end if + readFactors = .true. + select case (trim(em % type)) case ("biogenic") call ESMF_ConfigGetAttribute(config, value, & @@ -560,6 +566,35 @@ subroutine aqm_emis_src_init(model, em, rc) rcToReturn=rc)) & return ! bail out end if + case ("product") + em % iomode = "create" + readFactors = .false. + call ESMF_ConfigGetAttribute(config, em % sync, & + label=trim(em % name)//"_sync:", default=.false., rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + if (em % verbose) then + if (em % sync) then + call ESMF_LogWrite(trim(em % logprefix)//": "//pName & + //": sync: true", ESMF_LOGMSG_INFO, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + else + call ESMF_LogWrite(trim(em % logprefix)//": "//pName & + //": sync: false", ESMF_LOGMSG_INFO, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + end if + end if end select call ESMF_ConfigGetDim(config, rowCount, columnCount, & @@ -613,24 +648,30 @@ subroutine aqm_emis_src_init(model, em, rc) file=__FILE__, & rcToReturn=rc)) & return ! bail out - ! -- scaling factor - call ESMF_ConfigGetAttribute(config, value, default="1.0", & - eolFlag=eolFlag, rc=localrc) - if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__, & - rcToReturn=rc)) & - return ! bail out - if (.not.eolFlag) then - read(value, *, iostat=stat) tmpFactorList(item) - if (stat /= 0) then - call ESMF_LogSetError(ESMF_RC_NOT_VALID, & - msg="- emission factor: "//trim(value), & - line=__LINE__, & - file=__FILE__, & - rcToReturn=rc) + if (readFactors) then + ! -- scaling factor + call ESMF_ConfigGetAttribute(config, value, default="1.0", & + eolFlag=eolFlag, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & return ! bail out + if (.not.eolFlag) then + read(value, *, iostat=stat) tmpFactorList(item) + if (stat /= 0) then + call ESMF_LogSetError(ESMF_RC_NOT_VALID, & + msg="- emission factor: "//trim(value), & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc) + return ! bail out + end if end if + else + eolFlag = .false. + end if + if (.not.eolFlag) then ! -- variable (netcdf) or file (binary) name call ESMF_ConfigGetAttribute(config, tmpSourceList(item), & default="", eolFlag=eolFlag, rc=localrc) @@ -694,8 +735,8 @@ subroutine aqm_emis_src_init(model, em, rc) end if ! -- open single netCDF file if selected - if (em % iofmt == ESMF_IOFMT_NETCDF) then - call AQMIO_Open(em % IO, em % file, filePath=em % path, iomode="read", & + if (em % iofmt == AQMIO_FMT_NETCDF) then + call AQMIO_Open(em % IO, em % file, filePath=em % path, iomode=em % iomode, & iofmt=em % iofmt, rc=localrc) if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & @@ -1009,12 +1050,16 @@ subroutine aqm_emis_update(model, rc) em => is % wrap % emis(item) - isRinging = ESMF_AlarmIsRinging(em % alarm, rc=localrc) - if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__, & - rcToReturn=rc)) & - return ! bail out + isRinging = (trim(em % iomode) == "read") + + if (isRinging) then + isRinging = ESMF_AlarmIsRinging(em % alarm, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + end if if (isRinging) then call ESMF_ClockGet(clock, currTime=currTime, rc=localrc) @@ -1038,7 +1083,7 @@ subroutine aqm_emis_update(model, rc) rcToReturn=rc)) & return ! bail out end if - if (em % iofmt == ESMF_IOFMT_BIN) then + if (em % iofmt == AQMIO_FMT_BIN) then do n = 1, size(em % sources) call AQMIO_Read(em % IO, (/ em % fields(n) /), fileName=em % sources(n), & filePath=em % path, iofmt=em % iofmt, rc=localrc) @@ -1088,6 +1133,15 @@ function aqm_emis_get(etype) result (ep) end function aqm_emis_get + function aqm_emis_data_get() result (ep) + type(aqm_internal_emis_type), pointer :: ep(:) + + nullify(ep) + + if (associated(aqm_emis_data)) ep => aqm_emis_data + + end function aqm_emis_data_get + subroutine aqm_emis_desc( etype, nlays, nvars, vnames, units ) character(len=*), intent(in) :: etype integer, intent(out) :: nlays @@ -1143,6 +1197,8 @@ subroutine aqm_emis_read(etype, spcname, buffer, localDe, rc) em => aqm_emis_get(etype) ! -- bail out if no emissions available if (.not.associated(em)) return + ! -- bail out if this is a product + if (trim(em % iomode) /= "read") return call aqm_model_get(stateIn=stateIn, rc=localrc) if (aqm_rc_check(localrc, msg="Failure to retrieve model input state", & diff --git a/src/shr/aqm_internal_mod.F90 b/src/shr/aqm_internal_mod.F90 index 9134d71d..0598b11e 100644 --- a/src/shr/aqm_internal_mod.F90 +++ b/src/shr/aqm_internal_mod.F90 @@ -16,9 +16,11 @@ module aqm_internal_mod character(len=ESMF_MAXSTR) :: specfile character(len=ESMF_MAXSTR) :: specprofile character(len=6) :: period - integer :: irec + logical :: sync logical :: verbose - type(ESMF_IOFmt_flag) :: iofmt + integer :: irec + integer :: iofmt + character(len=ESMF_MAXSTR) :: iomode type(ESMF_GridComp) :: IO type(ESMF_Alarm) :: alarm character(len=ESMF_MAXSTR), dimension(:), pointer :: sources => null() diff --git a/src/shr/aqm_methods.F90 b/src/shr/aqm_methods.F90 index b7a45d21..1afa0c49 100644 --- a/src/shr/aqm_methods.F90 +++ b/src/shr/aqm_methods.F90 @@ -76,8 +76,8 @@ LOGICAL FUNCTION DESC3( FNAME ) USE M3UTILIO, ONLY : & GDNAM3D, NLAYS3D, NVARS3D, VDESC3D, VGLVS3D, & VGSGPN3, VGTOP3D, VGTYP3D, VNAME3D, UNITS3D, & - NCOLS3D, NROWS3D - + NCOLS3D, NROWS3D, SDATE3D, STIME3D, TSTEP3D + USE aqm_emis_mod USE aqm_model_mod, ONLY : aqm_config_type, & aqm_model_get, aqm_model_domain_get @@ -101,6 +101,10 @@ LOGICAL FUNCTION DESC3( FNAME ) UNITS3D = "" VDESC3D = "" + SDATE3D = 0 + STIME3D = 0 + TSTEP3D = 0 + IF ( (TRIM(FNAME) .EQ. TRIM(INIT_GASC_1)) .OR. & (TRIM(FNAME) .EQ. TRIM(INIT_AERO_1)) .OR. & (TRIM(FNAME) .EQ. TRIM(INIT_NONR_1)) .OR. & @@ -155,7 +159,7 @@ LOGICAL FUNCTION DESC3( FNAME ) 'ZRUF ', & 'HFX ', 'WSPD10 ', & 'GSW ', 'RGRND ', & - 'RNA ', 'RCA ', & + 'RN ', 'RC ', & 'CFRAC ', 'CLDT ', & 'CLDB ', 'WBAR ', & 'RA ', 'RS ', & @@ -188,6 +192,14 @@ LOGICAL FUNCTION DESC3( FNAME ) '1 ', '1 ', & '1 ', 'M/S ' /) + call aqm_model_get(config=config, rc=localrc) + if (aqm_rc_check(localrc, msg="Failure to retrieve model input state", & + file=__FILE__, line=__LINE__)) return + + SDATE3D = config % ctm_stdate + STIME3D = config % ctm_sttime + TSTEP3D = config % ctm_tstep + ELSE IF ( TRIM( FNAME ) .EQ. TRIM( MET_CRO_3D ) ) THEN CALL aqm_model_domain_get(nl=NLAYS3D, rc=localrc) @@ -226,6 +238,10 @@ LOGICAL FUNCTION DESC3( FNAME ) if (aqm_rc_check(localrc, msg="Failure to retrieve model input state", & file=__FILE__, line=__LINE__)) return + SDATE3D = config % ctm_stdate + STIME3D = config % ctm_sttime + TSTEP3D = config % ctm_tstep + if (config % species % p_atm_qr > 0) then NVARS3D = NVARS3D + 1 VNAME3D( NVARS3D ) = 'QR' @@ -259,6 +275,14 @@ LOGICAL FUNCTION DESC3( FNAME ) (/ 'M/S ', 'M/S ', & 'KG/(M*S) ', 'KG/(M*S) ' /) + call aqm_model_get(config=config, rc=localrc) + if (aqm_rc_check(localrc, msg="Failure to retrieve model input state", & + file=__FILE__, line=__LINE__)) return + + SDATE3D = config % ctm_stdate + STIME3D = config % ctm_sttime + TSTEP3D = config % ctm_tstep + ELSE IF ( TRIM( FNAME ) .EQ. 'MODIS_FPAR' ) THEN NVARS3D = 1 VNAME3D( 1:NVARS3D ) = & @@ -1237,7 +1261,7 @@ LOGICAL FUNCTION WRITE3_REAL4D( FNAME, VNAME, JDATE, JTIME, BUFFER ) if (aqm_rc_check(localrc, msg="Failure to retrieve model output state", & file=__FILE__, line=__LINE__)) return - do s = 0, config % species % ndiag - 1 + do s = 0, config % species % ndiag - 2 stateOut % tr(:,:,:,config % species % p_diag_beg + s) = & buffer(:,:,:,p_pm25at + s) end do @@ -1252,6 +1276,46 @@ END FUNCTION WRITE3_REAL4D ! -- dummy subroutines +SUBROUTINE DUMMY_AQCHEM ( JDATE, JTIME, TEMP, PRES_PA, TAUCLD, PRCRATE, & + WCAVG, WTAVG, AIRM, ALFA0, ALFA2, ALFA3, GAS, & + AEROSOL, GASWDEP, AERWDEP, HPWDEP, BETASO4, DARK ) + INTEGER, INTENT( IN ) :: JDATE + INTEGER, INTENT( IN ) :: JTIME + REAL, INTENT( IN ) :: AIRM + REAL, INTENT( IN ) :: ALFA0 + REAL, INTENT( IN ) :: ALFA2 + REAL, INTENT( IN ) :: ALFA3 + REAL, INTENT( OUT ) :: HPWDEP + REAL( 8 ), INTENT( OUT ) :: BETASO4 + REAL, INTENT( IN ) :: PRCRATE + REAL, INTENT( IN ) :: PRES_PA + REAL, INTENT( IN ) :: TAUCLD + REAL, INTENT( IN ) :: TEMP + REAL, INTENT( IN ) :: WCAVG + REAL, INTENT( IN ) :: WTAVG + REAL( 8 ), INTENT( INOUT ) :: GAS ( : ) + REAL( 8 ), INTENT( INOUT ) :: AEROSOL( :,: ) + REAL( 8 ), INTENT( INOUT ) :: GASWDEP( : ) + REAL( 8 ), INTENT( INOUT ) :: AERWDEP( :,: ) + LOGICAL, INTENT( IN ) :: DARK + BETASO4 = 0.0D0 + HPWDEP = 0.0 +END SUBROUTINE DUMMY_AQCHEM + +SUBROUTINE DUMMY_CONVCLD_ACM ( CGRID, JDATE, JTIME, TSTEP, & + N_SPC_WDEP, WDEP_MAP, CONV_DEP, SUBTRANS ) + REAL, POINTER :: CGRID( :,:,:,: ) + INTEGER, INTENT( IN ) :: JDATE + INTEGER, INTENT( IN ) :: JTIME + INTEGER, INTENT( IN ) :: TSTEP( 3 ) + INTEGER, INTENT( IN ) :: N_SPC_WDEP + INTEGER, INTENT( IN ) :: WDEP_MAP( : ) + REAL, INTENT( INOUT ) :: CONV_DEP( :,:,: ) + REAL, INTENT( OUT ) :: SUBTRANS( :,:,: ) + CONV_DEP = 0.0 + SUBTRANS = 1.0 +END SUBROUTINE DUMMY_CONVCLD_ACM + SUBROUTINE DUMMY_EDDYX ( EDDYV ) REAL, INTENT( OUT ) :: EDDYV ( :,:,: ) EDDYV = 0.0 diff --git a/src/shr/aqm_prod_mod.F90 b/src/shr/aqm_prod_mod.F90 new file mode 100644 index 00000000..22d386fd --- /dev/null +++ b/src/shr/aqm_prod_mod.F90 @@ -0,0 +1,409 @@ +module aqm_prod_mod + + use ESMF + use NUOPC + use aqmio + use aqm_rc_mod + use aqm_emis_mod, only : aqm_internal_emis_type + use aqm_internal_mod + + implicit none + + ! -- parameters + character(len=*), parameter :: rName = "products" + + ! -- internal variables + + private + + public :: aqm_prod_init + public :: aqm_prod_compute + public :: aqm_prod_units_set + public :: aqm_prod_update + +contains + + subroutine aqm_prod_field_init(em, rc) + type(aqm_internal_emis_type) :: em + integer, optional, intent(out) :: rc + + ! -- local variables + integer :: n + integer :: localrc + real(ESMF_KIND_R8) :: initValue + + ! -- begin + if (present(rc)) rc = ESMF_SUCCESS + + ! -- reset product fields + do n = 1, size(em % fields) + select case (trim(em % units(n))) + case ("MIN") + initValue = huge(1._ESMF_KIND_R8) + case default + initValue = 0._ESMF_KIND_R8 + end select + call ESMF_FieldFill(em % fields(n), dataFillScheme="const", & + const1=initValue, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return + end do + + end subroutine aqm_prod_field_init + + subroutine aqm_prod_units_set(field, units, rc) + type(ESMF_Field) :: field + character(len=*), intent(in) :: units + integer, optional, intent(out) :: rc + + ! -- local variables + integer :: localrc + type(ESMF_Info) :: info + + ! -- begin + if (present(rc)) rc = ESMF_SUCCESS + + ! -- add units to field + call ESMF_InfoGetFromHost(field, info, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) return ! bail out + + call ESMF_InfoSet(info, "units", units, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) return ! bail out + + end subroutine aqm_prod_units_set + + subroutine aqm_prod_init(model, rc) + type(ESMF_GridComp) :: model + integer, optional, intent(out) :: rc + + ! -- local variables + integer :: localrc + integer :: verbosity + integer :: prodCount, item, n + integer(ESMF_KIND_I4) :: dts, ts + character(len=ESMF_MAXSTR) :: name + character(len=ESMF_MAXSTR) :: msgString + type(ESMF_Clock) :: clock + type(ESMF_Config) :: config + type(ESMF_TimeInterval) :: timeInterval + type(aqm_internal_state_type) :: is + type(aqm_internal_emis_type), pointer :: em + + character(len=*), parameter :: pName = "init" + + ! -- begin + if (present(rc)) rc = ESMF_SUCCESS + + ! -- get component's information + call NUOPC_CompGet(model, name=name, verbosity=verbosity, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + + ! -- get component's configuration + call ESMF_GridCompGet(model, clock=clock, config=config, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + + ! -- get component's internal state + call ESMF_GridCompGetInternalState(model, is, localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + + prodCount = 0 + if (associated(is % wrap % emis)) then + do item = 1, size(is % wrap % emis) + em => is % wrap % emis(item) + if (trim(em % type) == "product") then + prodCount = prodCount + 1 + ! -- set default log prefix label and verbosity + em % logprefix = trim(name)//": "//rName & + // ": " // em % name + em % verbose = btest(verbosity,8) + ! -- setup products + ! 1. initialize field payload to zero + call aqm_prod_field_init(em, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + ! 2. initialize weights + do n = 1, size(em % species) + if (trim(em % units(n)) == "AVERAGE") then + call ESMF_AlarmGet(em % alarm, ringInterval=timeInterval, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + call ESMF_TimeIntervalGet(timeInterval, s=ts, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + call ESMF_ClockGet(clock, timeStep=timeInterval, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + call ESMF_TimeIntervalGet(timeInterval, s=dts, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + em % factors(n) = real(dts, kind=ESMF_KIND_R4) / ts + else + em % factors(n) = 1._ESMF_KIND_R4 + end if + end do + end if + end do + end if + + if (prodCount > 0) then + + if (btest(verbosity,8)) then + write(msgString,'(a,": ",a,": ",a,": types[",i0,"]: ")') trim(name), & + trim(rName), trim(pName), prodCount + n = 0 + do item = 1, size(is % wrap % emis) + if (trim(is % wrap % emis(item) % type) == "product") then + n = n + 1 + msgString = trim(msgString) // " " // is % wrap % emis(item) % name + if (n < prodCount) msgString = trim(msgString) // "," + end if + end do + call ESMF_LogWrite(msgString, ESMF_LOGMSG_INFO, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + end if + + else + + if (btest(verbosity,8)) then + write(msgString,'(a,": ",a,": types : none")') trim(name), & + trim(rName), trim(pName) + call ESMF_LogWrite(msgString, ESMF_LOGMSG_INFO, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + end if + + end if + + end subroutine aqm_prod_init + + subroutine aqm_prod_compute(em, cgrid, n, spc, rc) + type(aqm_internal_emis_type), pointer :: em + real, intent(in) :: cgrid(:,:,:,:) + integer, intent(in) :: n + integer, intent(in) :: spc + integer, optional, intent(out) :: rc + + ! -- local variables + integer :: localrc + integer :: item + integer :: i, j, c, r + integer, dimension(2) :: lb, ub + real(ESMF_KIND_R4), pointer :: fptr(:,:) + + ! -- begin + if (present(rc)) rc = AQM_RC_SUCCESS + + ! -- return if no internal emission data set + if (.not.associated(em)) return + + if (trim(em % type) == "product") then + + call ESMF_FieldGet(em % fields(n), & + computationalLBound=lb, computationalUBound=ub, & + farrayPtr=fptr, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) then + if (present(rc)) rc = AQM_RC_FAILURE + return ! bail out + end if + select case (trim(em % units(n))) + case ("AVERAGE") + r = 0 + do j = lb(2), ub(2) + r = r + 1 + c = 0 + do i = lb(1), ub(1) + c = c + 1 + fptr(i,j) = fptr(i,j) + em % factors(n) * cgrid(c,r,1,spc) + end do + end do + case ("MIN") + r = 0 + do j = lb(2), ub(2) + r = r + 1 + c = 0 + do i = lb(1), ub(1) + c = c + 1 + fptr(i,j) = min(fptr(i,j), cgrid(c,r,1,spc)) + end do + end do + case ("MAX") + r = 0 + do j = lb(2), ub(2) + r = r + 1 + c = 0 + do i = lb(1), ub(1) + c = c + 1 + fptr(i,j) = max(fptr(i,j), cgrid(c,r,1,spc)) + end do + end do + case default + r = 0 + do j = lb(2), ub(2) + r = r + 1 + c = 0 + do i = lb(1), ub(1) + c = c + 1 + fptr(i,j) = cgrid(c,r,1,spc) + end do + end do + end select + + end if + + end subroutine aqm_prod_compute + + subroutine aqm_prod_update(model, rc) + type(ESMF_GridComp) :: model + integer, optional, intent(out) :: rc + + ! -- local variables + integer :: localrc + integer :: item + logical :: isRinging + character(len=ESMF_MAXSTR) :: timeString + type(ESMF_Clock) :: clock + type(ESMF_Time) :: currTime + type(aqm_internal_state_type) :: is + type(aqm_internal_emis_type), pointer :: em + + ! -- begin + if (present(rc)) rc = ESMF_SUCCESS + + ! -- get component's configuration + call ESMF_GridCompGet(model, clock=clock, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + + ! -- get component's internal state + call ESMF_GridCompGetInternalState(model, is, localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + + ! -- return if no internal data set + if (.not.associated(is % wrap)) return + ! -- return if no internal emission data set + if (.not.associated(is % wrap % emis)) return + + do item = 1, size(is % wrap % emis) + + em => is % wrap % emis(item) + + isRinging = (trim(em % type) == "product") + + if (isRinging) then + isRinging = ESMF_AlarmIsRinging(em % alarm, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + end if + + if (isRinging) then + call ESMF_ClockGet(clock, currTime=currTime, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + call ESMF_TimeGet(currTime, timeString=timeString, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + if (em % verbose) then + call ESMF_LogWrite(trim(em % logprefix)//": writing "//& + trim(em % name)//" @ "//trim(timeString), ESMF_LOGMSG_INFO, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + end if + em % irec = em % irec + 1 + call AQMIO_Write(em % IO, em % fields, timeSlice=em % irec, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + if ( em % sync ) then + call AQMIO_Sync(em % IO, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + end if + call ESMF_AlarmRingerOff(em % alarm, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + ! -- reset product fields + call aqm_prod_field_init(em, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__, & + rcToReturn=rc)) & + return ! bail out + end if + + end do + + end subroutine aqm_prod_update + +end module aqm_prod_mod