module lnd2atmMod !----------------------------------------------------------------------- ! !DESCRIPTION: ! Handle lnd2atm mapping ! ! !USES: #include "shr_assert.h" use shr_kind_mod , only : r8 => shr_kind_r8 use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) use shr_log_mod , only : errMsg => shr_log_errMsg use shr_megan_mod , only : shr_megan_mechcomps_n use shr_fire_emis_mod , only : shr_fire_emis_mechcomps_n use clm_varpar , only : numrad, ndst, nlevgrnd, nlevsoi !ndst = number of dust bins. use clm_varcon , only : rair, grav, cpair, hfus, tfrz, spval #ifdef USE_PDAF use clm_varcon , only : set_averaging_to_zero, averaging_var, aquifer_water_baseline #endif use clm_varctl , only : iulog, use_lch4 use seq_drydep_mod , only : n_drydep, drydep_method, DD_XLND use decompMod , only : bounds_type use subgridAveMod , only : p2g, c2g use lnd2atmType , only : lnd2atm_type use atm2lndType , only : atm2lnd_type use ch4Mod , only : ch4_type use DUSTMod , only : dust_type use DryDepVelocity , only : drydepvel_type use VocEmissionMod , only : vocemis_type use CNFireEmissionsMod , only : fireemis_type use EnergyFluxType , only : energyflux_type use FrictionVelocityMod , only : frictionvel_type use SolarAbsorbedType , only : solarabs_type use SurfaceAlbedoType , only : surfalb_type use TemperatureType , only : temperature_type use WaterFluxType , only : waterflux_type use WaterstateType , only : waterstate_type use IrrigationMod , only : irrigation_type use glcBehaviorMod , only : glc_behavior_type use glc2lndMod , only : glc2lnd_type use ColumnType , only : col use LandunitType , only : lun use GridcellType , only : grc use landunit_varcon , only : istice_mec, istsoil, istcrop #ifdef USE_PDAF use clm_time_manager , only : get_nstep use SoilHydrologyType , only : soilhydrology_type use SoilStateType , only : soilstate_type use PatchType , only : patch #endif ! ! !PUBLIC TYPES: implicit none private ! ! !PUBLIC MEMBER FUNCTIONS: public :: lnd2atm public :: lnd2atm_minimal ! ! !PRIVATE MEMBER FUNCTIONS: private :: handle_ice_runoff character(len=*), parameter, private :: sourcefile = & __FILE__ !------------------------------------------------------------------------ contains !------------------------------------------------------------------------ subroutine lnd2atm_minimal(bounds, & waterstate_inst, surfalb_inst, energyflux_inst, lnd2atm_inst) ! ! !DESCRIPTION: ! Compute clm_l2a_inst component of gridcell derived type. This routine computes ! the bare minimum of components necessary to get the first step of a ! run started. ! ! !USES: use clm_varcon, only : sb ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds type(waterstate_type) , intent(in) :: waterstate_inst type(surfalb_type) , intent(in) :: surfalb_inst type(energyflux_type) , intent(in) :: energyflux_inst type(lnd2atm_type) , intent(inout) :: lnd2atm_inst ! ! !LOCAL VARIABLES: integer :: g ! index real(r8), parameter :: amC = 12.0_r8 ! Atomic mass number for Carbon real(r8), parameter :: amO = 16.0_r8 ! Atomic mass number for Oxygen real(r8), parameter :: amCO2 = amC + 2.0_r8*amO ! Atomic mass number for CO2 ! The following converts g of C to kg of CO2 real(r8), parameter :: convertgC2kgCO2 = 1.0e-3_r8 * (amCO2/amC) !------------------------------------------------------------------------ call c2g(bounds, & waterstate_inst%h2osno_col (bounds%begc:bounds%endc), & lnd2atm_inst%h2osno_grc (bounds%begg:bounds%endg), & c2l_scale_type= 'urbanf', l2g_scale_type='unity') do g = bounds%begg,bounds%endg lnd2atm_inst%h2osno_grc(g) = lnd2atm_inst%h2osno_grc(g)/1000._r8 end do call c2g(bounds, nlevgrnd, & waterstate_inst%h2osoi_vol_col (bounds%begc:bounds%endc, :), & lnd2atm_inst%h2osoi_vol_grc (bounds%begg:bounds%endg, :), & c2l_scale_type= 'urbanf', l2g_scale_type='unity') call p2g(bounds, numrad, & surfalb_inst%albd_patch (bounds%begp:bounds%endp, :), & lnd2atm_inst%albd_grc (bounds%begg:bounds%endg, :), & p2c_scale_type='unity', c2l_scale_type= 'urbanf', l2g_scale_type='unity') call p2g(bounds, numrad, & surfalb_inst%albi_patch (bounds%begp:bounds%endp, :), & lnd2atm_inst%albi_grc (bounds%begg:bounds%endg, :), & p2c_scale_type='unity', c2l_scale_type= 'urbanf', l2g_scale_type='unity') call p2g(bounds, & energyflux_inst%eflx_lwrad_out_patch (bounds%begp:bounds%endp), & lnd2atm_inst%eflx_lwrad_out_grc (bounds%begg:bounds%endg), & p2c_scale_type='unity', c2l_scale_type= 'urbanf', l2g_scale_type='unity') do g = bounds%begg,bounds%endg lnd2atm_inst%t_rad_grc(g) = sqrt(sqrt(lnd2atm_inst%eflx_lwrad_out_grc(g)/sb)) end do end subroutine lnd2atm_minimal !------------------------------------------------------------------------ subroutine lnd2atm(bounds, & atm2lnd_inst, surfalb_inst, temperature_inst, frictionvel_inst, & waterstate_inst, waterflux_inst, irrigation_inst, energyflux_inst, & solarabs_inst, drydepvel_inst, & vocemis_inst, fireemis_inst, dust_inst, ch4_inst, glc_behavior, & lnd2atm_inst, & #ifdef USE_PDAF soilhydrology_inst, soilstate_inst, & #endif net_carbon_exchange_grc) ! ! !DESCRIPTION: ! Compute lnd2atm_inst component of gridcell derived type ! ! !USES: use ch4varcon , only : ch4offline ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds type(atm2lnd_type) , intent(in) :: atm2lnd_inst type(surfalb_type) , intent(in) :: surfalb_inst type(temperature_type) , intent(in) :: temperature_inst type(frictionvel_type) , intent(in) :: frictionvel_inst type(waterstate_type) , intent(inout) :: waterstate_inst type(waterflux_type) , intent(inout) :: waterflux_inst type(irrigation_type) , intent(in) :: irrigation_inst type(energyflux_type) , intent(in) :: energyflux_inst type(solarabs_type) , intent(in) :: solarabs_inst type(drydepvel_type) , intent(in) :: drydepvel_inst type(vocemis_type) , intent(in) :: vocemis_inst type(fireemis_type) , intent(in) :: fireemis_inst type(dust_type) , intent(in) :: dust_inst type(ch4_type) , intent(in) :: ch4_inst type(glc_behavior_type) , intent(in) :: glc_behavior type(lnd2atm_type) , intent(inout) :: lnd2atm_inst #ifdef USE_PDAF ! Yorck type(soilhydrology_type) , intent(inout) :: soilhydrology_inst type(soilstate_type) , intent(inout) :: soilstate_inst ! end Yorck #endif real(r8) , intent(in) :: net_carbon_exchange_grc( bounds%begg: ) ! net carbon exchange between land and atmosphere, positive for source (gC/m2/s) ! ! !LOCAL VARIABLES: integer :: c, g, j ! indices #ifdef USE_PDAF integer :: p, l, index, counter ! indices #endif real(r8) :: qflx_ice_runoff_col(bounds%begc:bounds%endc) ! total column-level ice runoff real(r8) :: eflx_sh_ice_to_liq_grc(bounds%begg:bounds%endg) ! sensible heat flux generated from the ice to liquid conversion, averaged to gridcell real(r8), parameter :: amC = 12.0_r8 ! Atomic mass number for Carbon real(r8), parameter :: amO = 16.0_r8 ! Atomic mass number for Oxygen real(r8), parameter :: amCO2 = amC + 2.0_r8*amO ! Atomic mass number for CO2 #ifdef USE_PDAF real(r8), parameter :: m_per_mm = 1.e-3_r8 ! 0.001 meters per mm real(r8), parameter :: sec_per_hr = 3600 ! 3600 s in 1 hour #endif ! The following converts g of C to kg of CO2 real(r8), parameter :: convertgC2kgCO2 = 1.0e-3_r8 * (amCO2/amC) #ifdef USE_PDAF integer :: nstep ! time step number REAL, allocatable :: h2osoi_liq_grc(:) REAL, allocatable :: h2osoi_ice_grc(:) REAL, allocatable :: h2osno_grc(:) REAL, allocatable :: h2osfc_grc(:) REAL, allocatable :: h2ocan_grc(:) logical, allocatable :: found(:) logical, allocatable :: found_patch(:) #endif !------------------------------------------------------------------------ SHR_ASSERT_ALL((ubound(net_carbon_exchange_grc) == (/bounds%endg/)), errMsg(sourcefile, __LINE__)) call handle_ice_runoff(bounds, waterflux_inst, glc_behavior, & melt_non_icesheet_ice_runoff = lnd2atm_inst%params%melt_non_icesheet_ice_runoff, & qflx_ice_runoff_col = qflx_ice_runoff_col(bounds%begc:bounds%endc), & qflx_liq_from_ice_col = lnd2atm_inst%qflx_liq_from_ice_col(bounds%begc:bounds%endc), & eflx_sh_ice_to_liq_col = lnd2atm_inst%eflx_sh_ice_to_liq_col(bounds%begc:bounds%endc)) !---------------------------------------------------- ! lnd -> atm !---------------------------------------------------- ! First, compute the "minimal" set of fields. call lnd2atm_minimal(bounds, & waterstate_inst, surfalb_inst, energyflux_inst, lnd2atm_inst) call p2g(bounds, & temperature_inst%t_ref2m_patch (bounds%begp:bounds%endp), & lnd2atm_inst%t_ref2m_grc (bounds%begg:bounds%endg), & p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity') call p2g(bounds, & waterstate_inst%q_ref2m_patch (bounds%begp:bounds%endp), & lnd2atm_inst%q_ref2m_grc (bounds%begg:bounds%endg), & p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity') call p2g(bounds, & frictionvel_inst%u10_clm_patch (bounds%begp:bounds%endp), & lnd2atm_inst%u_ref10m_grc (bounds%begg:bounds%endg), & p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity') call p2g(bounds, & energyflux_inst%taux_patch (bounds%begp:bounds%endp), & lnd2atm_inst%taux_grc (bounds%begg:bounds%endg), & p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity') call p2g(bounds, & energyflux_inst%tauy_patch (bounds%begp:bounds%endp), & lnd2atm_inst%tauy_grc (bounds%begg:bounds%endg), & p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity') call p2g(bounds, & waterflux_inst%qflx_evap_tot_patch (bounds%begp:bounds%endp), & lnd2atm_inst%qflx_evap_tot_grc (bounds%begg:bounds%endg), & p2c_scale_type='unity', c2l_scale_type= 'urbanf', l2g_scale_type='unity') call p2g(bounds, & solarabs_inst%fsa_patch (bounds%begp:bounds%endp), & lnd2atm_inst%fsa_grc (bounds%begg:bounds%endg), & p2c_scale_type='unity', c2l_scale_type= 'urbanf', l2g_scale_type='unity') call p2g(bounds, & frictionvel_inst%fv_patch (bounds%begp:bounds%endp), & lnd2atm_inst%fv_grc (bounds%begg:bounds%endg), & p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity') call p2g(bounds, & frictionvel_inst%ram1_patch (bounds%begp:bounds%endp), & lnd2atm_inst%ram1_grc (bounds%begg:bounds%endg), & p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity') call p2g( bounds, & energyflux_inst%eflx_sh_tot_patch (bounds%begp:bounds%endp), & lnd2atm_inst%eflx_sh_tot_grc (bounds%begg:bounds%endg), & p2c_scale_type='unity',c2l_scale_type='urbanf',l2g_scale_type='unity') call c2g( bounds, & energyflux_inst%eflx_sh_precip_conversion_col (bounds%begc:bounds%endc), & lnd2atm_inst%eflx_sh_precip_conversion_grc (bounds%begg:bounds%endg), & c2l_scale_type='urbanf', l2g_scale_type='unity') call c2g( bounds, & lnd2atm_inst%eflx_sh_ice_to_liq_col(bounds%begc:bounds%endc), & eflx_sh_ice_to_liq_grc(bounds%begg:bounds%endg), & c2l_scale_type='urbanf', l2g_scale_type='unity') do g = bounds%begg, bounds%endg lnd2atm_inst%eflx_sh_tot_grc(g) = lnd2atm_inst%eflx_sh_tot_grc(g) + & lnd2atm_inst%eflx_sh_precip_conversion_grc(g) + & eflx_sh_ice_to_liq_grc(g) - & energyflux_inst%eflx_dynbal_grc(g) enddo call p2g(bounds, & energyflux_inst%eflx_lh_tot_patch (bounds%begp:bounds%endp), & lnd2atm_inst%eflx_lh_tot_grc (bounds%begg:bounds%endg), & p2c_scale_type='unity', c2l_scale_type= 'urbanf', l2g_scale_type='unity') do g = bounds%begg, bounds%endg lnd2atm_inst%net_carbon_exchange_grc(g) = & net_carbon_exchange_grc(g) end do if (use_lch4) then if (.not. ch4offline) then ! Adjust flux of CO2 by the net conversion of mineralizing C to CH4 do g = bounds%begg,bounds%endg ! nem is in g C/m2/sec lnd2atm_inst%net_carbon_exchange_grc(g) = & lnd2atm_inst%net_carbon_exchange_grc(g) + lnd2atm_inst%nem_grc(g) end do end if end if ! Convert from gC/m2/s to kgCO2/m2/s do g = bounds%begg,bounds%endg lnd2atm_inst%net_carbon_exchange_grc(g) = & lnd2atm_inst%net_carbon_exchange_grc(g)*convertgC2kgCO2 end do ! drydepvel if ( n_drydep > 0 .and. drydep_method == DD_XLND ) then call p2g(bounds, n_drydep, & drydepvel_inst%velocity_patch (bounds%begp:bounds%endp, :), & lnd2atm_inst%ddvel_grc (bounds%begg:bounds%endg, :), & p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity') endif ! voc emission flux if (shr_megan_mechcomps_n>0) then call p2g(bounds, shr_megan_mechcomps_n, & vocemis_inst%vocflx_patch(bounds%begp:bounds%endp,:), & lnd2atm_inst%flxvoc_grc (bounds%begg:bounds%endg,:), & p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity') end if ! fire emissions fluxes if (shr_fire_emis_mechcomps_n>0) then call p2g(bounds, shr_fire_emis_mechcomps_n, & -fireemis_inst%fireflx_patch(bounds%begp:bounds%endp,:), & lnd2atm_inst%fireflx_grc (bounds%begg:bounds%endg,:), & p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity') call p2g(bounds, & fireemis_inst%ztop_patch (bounds%begp:bounds%endp), & lnd2atm_inst%fireztop_grc(bounds%begg:bounds%endg), & p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity') endif ! dust emission flux call p2g(bounds, ndst, & dust_inst%flx_mss_vrt_dst_patch(bounds%begp:bounds%endp, :), & lnd2atm_inst%flxdst_grc (bounds%begg:bounds%endg, :), & p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity') ! ch4 flux if (use_lch4) then call c2g( bounds, & ch4_inst%ch4_surf_flux_tot_col (bounds%begc:bounds%endc), & lnd2atm_inst%flux_ch4_grc (bounds%begg:bounds%endg), & c2l_scale_type= 'unity', l2g_scale_type='unity' ) end if #ifdef COUP_OAS_ICON call p2g(bounds, & temperature_inst%t_sf_patch (bounds%begp:bounds%endp), & lnd2atm_inst%t_sf_grc (bounds%begg:bounds%endg), & p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity') ! call p2g(bounds, & ! waterstate_inst%q_sf_patch (bounds%begp:bounds%endp), & ! lnd2atm_inst%q_sf_grc (bounds%begg:bounds%endg), & ! p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity') ! call p2g(bounds, & ! frictionvel_inst%rah1_patch (bounds%begp:bounds%endp), & ! lnd2atm_inst%rah1_grc (bounds%begg:bounds%endg), & ! p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity') #endif !---------------------------------------------------- ! lnd -> rof !---------------------------------------------------- call c2g( bounds, & waterflux_inst%qflx_surf_col (bounds%begc:bounds%endc), & lnd2atm_inst%qflx_rofliq_qsur_grc (bounds%begg:bounds%endg), & c2l_scale_type= 'urbanf', l2g_scale_type='unity' ) call c2g( bounds, & waterflux_inst%qflx_drain_col (bounds%begc:bounds%endc), & lnd2atm_inst%qflx_rofliq_qsub_grc (bounds%begg:bounds%endg), & c2l_scale_type= 'urbanf', l2g_scale_type='unity' ) do c = bounds%begc, bounds%endc if (col%active(c)) then ! It's not entirely appropriate to put qflx_liq_from_ice_col into ! qflx_qrgwl_col, since this isn't necessarily just glaciers, wetlands and ! lakes. But since we put the liquid portion of snow capping into ! qflx_qrgwl_col, it seems reasonable to put qflx_liq_from_ice_col there as ! well. waterflux_inst%qflx_qrgwl_col(c) = waterflux_inst%qflx_qrgwl_col(c) + & lnd2atm_inst%qflx_liq_from_ice_col(c) ! NOTE(wjs, 2018-12-05) Similarly, it's not entirely appropriate to put ! qflx_runoff_rain_to_snow_conversion_col into qflx_qrgwl_col, since again, this ! is generated over landunits other than glaciers, wetlands and lakes. I'm ! putting it in qflx_qrgwl_col partly because glacier landunits are typically ! the primary source of this flux, and partly just because I'm not sure where ! else to put it. waterflux_inst%qflx_qrgwl_col(c) = waterflux_inst%qflx_qrgwl_col(c) + & waterflux_inst%qflx_runoff_rain_to_snow_conversion_col(c) ! qflx_runoff is the sum of a number of terms, including qflx_qrgwl. Since we ! are adjusting qflx_qrgwl above, we need to adjust qflx_runoff analogously. waterflux_inst%qflx_runoff_col(c) = waterflux_inst%qflx_runoff_col(c) + & lnd2atm_inst%qflx_liq_from_ice_col(c) + & waterflux_inst%qflx_runoff_rain_to_snow_conversion_col(c) end if end do call c2g( bounds, & waterflux_inst%qflx_qrgwl_col (bounds%begc:bounds%endc), & lnd2atm_inst%qflx_rofliq_qgwl_grc (bounds%begg:bounds%endg), & c2l_scale_type= 'urbanf', l2g_scale_type='unity' ) call c2g( bounds, & waterflux_inst%qflx_runoff_col (bounds%begc:bounds%endc), & lnd2atm_inst%qflx_rofliq_grc (bounds%begg:bounds%endg), & c2l_scale_type= 'urbanf', l2g_scale_type='unity' ) do g = bounds%begg, bounds%endg lnd2atm_inst%qflx_rofliq_qgwl_grc(g) = lnd2atm_inst%qflx_rofliq_qgwl_grc(g) - waterflux_inst%qflx_liq_dynbal_grc(g) lnd2atm_inst%qflx_rofliq_grc(g) = lnd2atm_inst%qflx_rofliq_grc(g) - waterflux_inst%qflx_liq_dynbal_grc(g) enddo call c2g( bounds, & waterflux_inst%qflx_h2osfc_surf_col (bounds%begc:bounds%endc), & lnd2atm_inst%qflx_rofliq_h2osfc_grc(bounds%begg:bounds%endg), & c2l_scale_type= 'urbanf', l2g_scale_type='unity' ) call c2g( bounds, & waterflux_inst%qflx_drain_perched_col (bounds%begc:bounds%endc), & lnd2atm_inst%qflx_rofliq_drain_perched_grc(bounds%begg:bounds%endg), & c2l_scale_type= 'urbanf', l2g_scale_type='unity' ) call c2g( bounds, & irrigation_inst%qflx_irrig_col (bounds%begc:bounds%endc), & lnd2atm_inst%qirrig_grc(bounds%begg:bounds%endg), & c2l_scale_type= 'urbanf', l2g_scale_type='unity' ) call c2g( bounds, & qflx_ice_runoff_col(bounds%begc:bounds%endc), & lnd2atm_inst%qflx_rofice_grc(bounds%begg:bounds%endg), & c2l_scale_type= 'urbanf', l2g_scale_type='unity' ) do g = bounds%begg, bounds%endg lnd2atm_inst%qflx_rofice_grc(g) = lnd2atm_inst%qflx_rofice_grc(g) - waterflux_inst%qflx_ice_dynbal_grc(g) enddo ! calculate total water storage for history files ! first set tws to gridcell total endwb ! second add river storage as gridcell average depth (1.e-3 converts [m3/km2] to [mm]) ! TODO - this was in BalanceCheckMod - not sure where it belongs? call c2g( bounds, & waterstate_inst%endwb_col(bounds%begc:bounds%endc), & waterstate_inst%tws_grc (bounds%begg:bounds%endg), & c2l_scale_type= 'urbanf', l2g_scale_type='unity' ) do g = bounds%begg, bounds%endg waterstate_inst%tws_grc(g) = waterstate_inst%tws_grc(g) + atm2lnd_inst%volr_grc(g) / grc%area(g) * 1.e-3_r8 enddo #ifdef COUP_OAS_PFL ! Calculate Parflow water fluxes call c2g( bounds, nlevsoi, & waterflux_inst%qflx_parflow_col (bounds%begc:bounds%endc, :), & lnd2atm_inst%qflx_parflow_grc (bounds%begg:bounds%endg, :), & c2l_scale_type= 'unity', l2g_scale_type='unity' ) ! adjust nan values after c2g, need to be rechecked do g = bounds%begg, bounds%endg do j = 1, nlevsoi if (lnd2atm_inst%qflx_parflow_grc(g,j) == spval) then lnd2atm_inst%qflx_parflow_grc(g,j) = 0._r8 write(iulog,*)'WARNING: qflx_parflow_grc is nan at grid point ',g,' level',j,' replaced with 0.' end if end do enddo #endif #ifdef USE_PDAF ! Yorck: update also TWS of hydrological active cells if (allocated(h2osoi_liq_grc)) deallocate(h2osoi_liq_grc) allocate(h2osoi_liq_grc(bounds%begg:bounds%endg)) h2osoi_liq_grc(bounds%begg:bounds%endg) = spval if (allocated(h2osoi_ice_grc)) deallocate(h2osoi_ice_grc) allocate(h2osoi_ice_grc(bounds%begg:bounds%endg)) h2osoi_ice_grc(bounds%begg:bounds%endg) = spval if (allocated(h2osno_grc)) deallocate(h2osno_grc) allocate(h2osno_grc(bounds%begg:bounds%endg)) h2osno_grc(bounds%begg:bounds%endg) = spval if (allocated(h2osfc_grc)) deallocate(h2osfc_grc) allocate(h2osfc_grc(bounds%begg:bounds%endg)) h2osfc_grc(bounds%begg:bounds%endg) = spval if (allocated(h2ocan_grc)) deallocate(h2ocan_grc) allocate(h2ocan_grc(bounds%begg:bounds%endg)) h2ocan_grc(bounds%begg:bounds%endg) = spval if (allocated(found)) deallocate(found) allocate(found(bounds%begg:bounds%endg)) found(bounds%begg:bounds%endg) = .false. if (allocated(found_patch)) deallocate(found_patch) allocate(found_patch(bounds%begg:bounds%endg)) found_patch(bounds%begg:bounds%endg) = .false. do g = bounds%begg, bounds%endg counter = 0 do c = bounds%begc, bounds%endc if (col%hydrologically_active(c) .and. col%gridcell(c)==g) then do j = 1,nlevsoi if (j==1 .and. .not. found(g)) then found(g) = .true. h2osoi_liq_grc(g) = 0._r8 h2osoi_ice_grc(g) = 0._r8 h2osno_grc(g) = 0._r8 h2osfc_grc(g) = 0._r8 end if if (j<=col%nbedrock(c)) then h2osoi_liq_grc(g) = h2osoi_liq_grc(g) + waterstate_inst%h2osoi_liq_col(c,j) h2osoi_ice_grc(g) = h2osoi_ice_grc(g) + waterstate_inst%h2osoi_ice_col(c,j) end if end do h2osno_grc(g) = h2osno_grc(g) + waterstate_inst%h2osno_col(c) h2osfc_grc(g) = h2osfc_grc(g) + waterstate_inst%h2osfc_col(c) counter= counter+1 end if end do if (counter.ne.0) then h2osoi_liq_grc(g) = h2osoi_liq_grc(g)/counter h2osoi_ice_grc(g) = h2osoi_ice_grc(g)/counter h2osno_grc(g) = h2osno_grc(g)/counter h2osfc_grc(g) = h2osfc_grc(g)/counter end if counter = 0 do p = bounds%begp, bounds%endp c = patch%column(p) if (col%hydrologically_active(c) .and. col%gridcell(c)==g .and. patch%active(p)) then if (.not. found_patch(g)) then found_patch(g) = .true. h2ocan_grc(g) = 0 end if h2ocan_grc(g) = h2ocan_grc(g) + waterstate_inst%h2ocan_patch(p) counter = counter+1 end if end do if (counter.ne.0) then h2ocan_grc(g) = h2ocan_grc(g)/counter else h2ocan_grc(g) = 0 end if if (found(g)) then waterstate_inst%tws_hactive(g) = h2osoi_liq_grc(g) + h2osoi_ice_grc(g) + h2osno_grc(g) + h2osfc_grc(g) + h2ocan_grc(g) end if end do if (allocated(h2osoi_liq_grc)) deallocate(h2osoi_liq_grc) if (allocated(h2osoi_ice_grc)) deallocate(h2osoi_ice_grc) if (allocated(h2osno_grc)) deallocate(h2osno_grc) if (allocated(h2osfc_grc)) deallocate(h2osfc_grc) if (allocated(h2ocan_grc)) deallocate(h2ocan_grc) if (allocated(found)) deallocate(found) if (allocated(found_patch)) deallocate(found_patch) ! YORCK --> idea: when TWS is calculated at the end of a time step, update all running mean variables. ! this is done for all compartments of TWS, the variables are initialized in the respective type modules ! here because the update of all important variables inside CLM is finished! nstep = get_nstep() if (nstep.eq.set_averaging_to_zero) then averaging_var = 0 end if averaging_var = averaging_var+1 ! if averaging var was resetted, reset also running averages if (averaging_var == 1) then do c = bounds%begc, bounds%endc waterstate_inst%h2osno_col_mean(c) = 0._r8 soilhydrology_inst%wa_col_mean(c) = 0._r8 waterstate_inst%h2osfc_col_mean(c) = 0._r8 waterstate_inst%total_plant_stored_h2o_col_mean(c) = 0._r8 do j = 1,nlevgrnd waterstate_inst%h2osoi_liq_col_mean(c,j) = 0._r8 waterstate_inst%h2osoi_ice_col_mean(c,j) = 0._r8 end do end do do g = bounds%begg, bounds%endg atm2lnd_inst%volr_grc_mean(g) = 0._r8 waterstate_inst%tws_hactive_mean(g) = 0._r8 end do do p = bounds%begp, bounds%endp waterstate_inst%h2ocan_patch_mean(p) = 0._r8 waterstate_inst%snocan_patch_mean(p) = 0._r8 end do end if ! Yorck ! update running average with mean = (var + (count-1)*mean)/count for all variables that contribute to TWS do c = bounds%begc, bounds%endc waterstate_inst%h2osno_col_mean(c) = (waterstate_inst%h2osno_col(c)+(averaging_var-1)*waterstate_inst%h2osno_col_mean(c))/averaging_var soilhydrology_inst%wa_col_mean(c) = (soilhydrology_inst%wa_col(c)+(averaging_var-1)*soilhydrology_inst%wa_col_mean(c))/averaging_var waterstate_inst%h2osfc_col_mean(c) = (waterstate_inst%h2osfc_col(c)+(averaging_var-1)*waterstate_inst%h2osfc_col_mean(c))/averaging_var waterstate_inst%total_plant_stored_h2o_col_mean(c) = (waterstate_inst%total_plant_stored_h2o_col(c)+(averaging_var-1) * & waterstate_inst%total_plant_stored_h2o_col_mean(c))/averaging_var do j = 1,nlevgrnd waterstate_inst%h2osoi_liq_col_mean(c,j) = (waterstate_inst%h2osoi_liq_col(c,j)+(averaging_var-1)* waterstate_inst%h2osoi_liq_col_mean(c,j))/averaging_var waterstate_inst%h2osoi_ice_col_mean(c,j) = (waterstate_inst%h2osoi_ice_col(c,j)+(averaging_var-1)* waterstate_inst%h2osoi_ice_col_mean(c,j))/averaging_var end do end do do g = bounds%begg, bounds%endg atm2lnd_inst%volr_grc_mean(g) = (atm2lnd_inst%volr_grc(g)+(averaging_var-1)*atm2lnd_inst%volr_grc_mean(g))/averaging_var waterstate_inst%tws_hactive_mean(g) = (waterstate_inst%tws_hactive(g)+(averaging_var-1)*waterstate_inst%tws_hactive_mean(g))/averaging_var end do do p = bounds%begp, bounds%endp waterstate_inst%h2ocan_patch_mean(p) = (waterstate_inst%h2ocan_patch(p)+(averaging_var-1)*waterstate_inst%h2ocan_patch_mean(p))/averaging_var waterstate_inst%snocan_patch_mean(p) = (waterstate_inst%snocan_patch(p)+(averaging_var-1)*waterstate_inst%snocan_patch_mean(p))/averaging_var end do #endif end subroutine lnd2atm !----------------------------------------------------------------------- subroutine handle_ice_runoff(bounds, waterflux_inst, glc_behavior, & melt_non_icesheet_ice_runoff, & qflx_ice_runoff_col, qflx_liq_from_ice_col, eflx_sh_ice_to_liq_col) ! ! !DESCRIPTION: ! Take column-level ice runoff and divide it between (a) ice runoff, and (b) liquid ! runoff with a compensating negative sensible heat flux. ! ! The rationale here is: Ice runoff is largely meant to represent a crude ! parameterization of iceberg calving. Iceberg calving is mainly appropriate in ! regions where an ice sheet terminates at the land-ocean boundary. Elsewhere, in ! reality, we expect most ice runoff to flow downstream and melt before it reaches the ! ocean. Furthermore, sending ice runoff directly to the ocean can lead to runaway sea ! ice growth in some regions (around the Canadian archipelago, and possibly in more ! wide-spread regions of the Arctic Ocean); melting this ice before it reaches the ! ocean avoids this problem. ! ! If the river model were able to melt ice, then we might not need this routine. ! ! Note that this routine does NOT handle ice runoff generated via the dynamic ! landunits adjustment fluxes (i.e., the fluxes that compensate for a difference in ! ice content between the pre- and post-dynamic landunit areas). This is partly ! because those gridcell-level dynamic landunits adjustment fluxes do not fit well ! with this column-based infrastructure, and partly because either method of handling ! these fluxes (i.e., sending an ice runoff or sending a liquid runoff with a ! negative sensible heat flux) seems equally justifiable. ! ! !USES: ! ! !ARGUMENTS: type(bounds_type), intent(in) :: bounds type(waterflux_type), intent(in) :: waterflux_inst type(glc_behavior_type), intent(in) :: glc_behavior logical, intent(in) :: melt_non_icesheet_ice_runoff real(r8), intent(out) :: qflx_ice_runoff_col( bounds%begc: ) ! total column-level ice runoff (mm H2O /s) real(r8), intent(out) :: qflx_liq_from_ice_col( bounds%begc: ) ! liquid runoff from converted ice runoff (mm H2O /s) real(r8), intent(out) :: eflx_sh_ice_to_liq_col( bounds%begc: ) ! sensible heat flux generated from the ice to liquid conversion (W/m2) (+ to atm) ! ! !LOCAL VARIABLES: integer :: c, l, g logical :: do_conversion character(len=*), parameter :: subname = 'handle_ice_runoff' !----------------------------------------------------------------------- SHR_ASSERT_ALL((ubound(qflx_ice_runoff_col) == (/bounds%endc/)), errMsg(sourcefile, __LINE__)) SHR_ASSERT_ALL((ubound(qflx_liq_from_ice_col) == (/bounds%endc/)), errMsg(sourcefile, __LINE__)) SHR_ASSERT_ALL((ubound(eflx_sh_ice_to_liq_col) == (/bounds%endc/)), errMsg(sourcefile, __LINE__)) do c = bounds%begc, bounds%endc if (col%active(c)) then qflx_ice_runoff_col(c) = waterflux_inst%qflx_ice_runoff_snwcp_col(c) + & waterflux_inst%qflx_ice_runoff_xs_col(c) qflx_liq_from_ice_col(c) = 0._r8 eflx_sh_ice_to_liq_col(c) = 0._r8 end if end do if (melt_non_icesheet_ice_runoff) then do c = bounds%begc, bounds%endc if (col%active(c)) then l = col%landunit(c) g = col%gridcell(c) do_conversion = .false. if (lun%itype(l) /= istice_mec) then do_conversion = .true. else ! istice_mec if (glc_behavior%ice_runoff_melted_grc(g)) then do_conversion = .true. else do_conversion = .false. end if end if if (do_conversion) then ! ice to liquid absorbs energy, so results in a negative heat flux to atm ! Note that qflx_ice_runoff_col is in mm H2O/s, which is the same as kg ! m-2 s-1, so we can simply multiply by hfus. eflx_sh_ice_to_liq_col(c) = -qflx_ice_runoff_col(c) * hfus qflx_liq_from_ice_col(c) = qflx_ice_runoff_col(c) qflx_ice_runoff_col(c) = 0._r8 end if end if end do end if end subroutine handle_ice_runoff end module lnd2atmMod