!=============================================================================== ! SVN $Id: seq_diag_mct.F90 19586 2009-11-23 21:50:15Z kauff $ ! SVN $URL: https://svn-ccsm-models.cgd.ucar.edu/drv/seq_mct/branch_tags/cesm1_0_rel_tags/cesm1_0_rel01_drvseq3_1_32/driver/seq_diag_mct.F90 $ !=============================================================================== !BOP =========================================================================== ! ! !MODULE: seq_diag_mod -- computes spatial \& time averages of fluxed quatities ! ! !DESCRIPTION: ! The coupler is required to do certain diagnostics, those calculations are ! located in this module. ! ! !REMARKS: ! Sign convention: ! positive value <=> the model is gaining water, heat, momentum, etc. ! Unit convention: ! heat flux ~ W/m^2 ! momentum flux ~ N/m^2 ! water flux ~ (kg/s)/m^2 ! salt flux ~ (kg/s)/m^2 ! ! !REVISION HISTORY: ! 2008-jul-10 - T. Craig - updated budget implementation ! 2007-may-07 - B. Kauffman - initial port to cpl7. ! 2002-nov-21 - R. Jacob - initial port to cpl6. ! 199x-mmm-dd - B. Kauffman - original version in cpl4. ! ! !INTERFACE: ------------------------------------------------------------------ module seq_diag_mct 3,10 ! !USES: use shr_kind_mod, only: r8 => shr_kind_r8, in=>shr_kind_in use shr_kind_mod, only: i8 => shr_kind_i8, cl=>shr_kind_cl use shr_sys_mod ! system calls use shr_mpi_mod ! mpi wrappers use shr_const_mod ! shared constants use mct_mod ! mct wrappers use esmf_mod use seq_flds_indices ! shared field indicies use seq_comm_mct ! mpi comm groups & related use seq_cdata_mod use seq_timemgr_mod implicit none private ! !PUBLIC TYPES: ! none !PUBLIC MEMBER FUNCTIONS: public seq_diag_zero_mct public seq_diag_atm_mct public seq_diag_lnd_mct public seq_diag_rtm_mct public seq_diag_ocn_mct public seq_diag_ice_mct public seq_diag_accum_mct public seq_diag_sum0_mct public seq_diag_print_mct public seq_diag_avect_mct public seq_diag_avdiff_mct !EOP !---------------------------------------------------------------------------- ! Local data !---------------------------------------------------------------------------- !----- local constants ----- real(r8),parameter :: HFLXtoWFLX = & ! water flux implied by latent heat of fusion & - (shr_const_ocn_ref_sal-shr_const_ice_ref_sal) / & & (shr_const_ocn_ref_sal*shr_const_latice) !--- C for component --- !--- "r" is recieve in the coupler, "s" is send from the coupler integer(in),parameter :: c_size = 18 integer(in),parameter :: c_atm_as = 1 ! model index: atm integer(in),parameter :: c_atm_ar = 2 ! model index: atm integer(in),parameter :: c_inh_is = 3 ! model index: ice, northern integer(in),parameter :: c_inh_ir = 4 ! model index: ice, northern integer(in),parameter :: c_ish_is = 5 ! model index: ice, southern integer(in),parameter :: c_ish_ir = 6 ! model index: ice, southern integer(in),parameter :: c_lnd_ls = 7 ! model index: lnd integer(in),parameter :: c_lnd_lr = 8 ! model index: lnd integer(in),parameter :: c_ocn_os = 9 ! model index: ocn integer(in),parameter :: c_ocn_or =10 ! model index: ocn ! --- on atm grid --- integer(in),parameter :: c_inh_as =11 ! model index: ice, northern integer(in),parameter :: c_inh_ar =12 ! model index: ice, northern integer(in),parameter :: c_ish_as =13 ! model index: ice, southern integer(in),parameter :: c_ish_ar =14 ! model index: ice, southern integer(in),parameter :: c_lnd_as =15 ! model index: lnd integer(in),parameter :: c_lnd_ar =16 ! model index: lnd integer(in),parameter :: c_ocn_as =17 ! model index: ocn integer(in),parameter :: c_ocn_ar =18 ! model index: ocn character(len=8),parameter :: cname(c_size) = & (/' c2a_atm',' a2c_atm',' c2i_inh',' i2c_inh',' c2i_ish',' i2c_ish', & ' c2l_lnd',' l2c_lnd',' c2o_ocn',' o2c_ocn', & ' c2a_inh',' a2c_inh',' c2a_ish',' a2c_ish', & ' c2a_lnd',' a2c_lnd',' c2a_ocn',' a2c_ocn' /) !--- F for field --- integer(in),parameter :: f_size = 17 integer(in),parameter :: f_a = 1 ! index for area integer(in),parameter :: f_h = 2 ! 1st index for heat integer(in),parameter :: f_w = 11 ! 1st index for water integer(in),parameter :: f_area = 1 ! area (wrt to unit sphere) integer(in),parameter :: f_hfrz = 2 ! heat : latent, freezing integer(in),parameter :: f_hmelt = 3 ! heat : latent, melting integer(in),parameter :: f_hswnet = 4 ! heat : short wave, net integer(in),parameter :: f_hlwdn = 5 ! heat : longwave down integer(in),parameter :: f_hlwup = 6 ! heat : longwave up integer(in),parameter :: f_hlatv = 7 ! heat : latent, vaporization integer(in),parameter :: f_hlatf = 8 ! heat : latent, fusion, snow integer(in),parameter :: f_hioff = 9 ! heat : latent, fusion, frozen runoff integer(in),parameter :: f_hsen =10 ! heat : sensible integer(in),parameter :: f_wfrz =11 ! water: freezing integer(in),parameter :: f_wmelt =12 ! water: melting integer(in),parameter :: f_wrain =13 ! water: precip, liquid integer(in),parameter :: f_wsnow =14 ! water: precip, frozen integer(in),parameter :: f_wevap =15 ! water: evaporation integer(in),parameter :: f_wroff =16 ! water: runoff integer(in),parameter :: f_wioff =17 ! water: frozen runoff character(len=8),parameter :: fname(f_size) = & (/' area',' hfreeze',' hmelt',' hnetsw',' hlwdn', & ' hlwup',' hlatvap',' hlatfus',' hiroff',' hsen', & ' wfreeze',' wmelt',' wrain',' wsnow', & ' wevap',' wrunoff',' wfrzrof' /) !--- P for period --- integer(in),parameter :: p_size = 5 integer(in),parameter :: p_inst = 1 integer(in),parameter :: p_day = 2 integer(in),parameter :: p_mon = 3 integer(in),parameter :: p_ann = 4 integer(in),parameter :: p_inf = 5 character(len=8),parameter :: pname(p_size) = & (/' inst',' daily',' monthly',' annual','all_time' /) ! !PUBLIC DATA MEMBERS !--- time-averaged (annual?) global budge diagnostics --- !--- note: call sum0 then save budg_dataG and budg_ns on restart from/to root pe --- real(r8),public :: budg_dataL(f_size,c_size,p_size) ! local sum, valid on all pes real(r8),public :: budg_dataG(f_size,c_size,p_size) ! global sum, valid only on root pe real(r8),public :: budg_ns (f_size,c_size,p_size) ! counter, valid only on root pe character(len=*),parameter :: afldname = 'aream' character(len=*),parameter :: latname = 'lat' character(len=*),parameter :: afracname = 'afrac' character(len=*),parameter :: lfracname = 'lfrac' character(len=*),parameter :: ofracname = 'ofrac' character(len=*),parameter :: ifracname = 'ifrac' character(len=*),parameter :: ascalname = 'ascale' character(len=*),parameter :: lfrinname = 'lfrin' character(*),parameter :: modName = "(seq_diag_mct) " integer(in),parameter :: debug = 0 ! internal debug level !=============================================================================== contains !=============================================================================== !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: seq_diag_zero_mct - zero out global budget diagnostic data. ! ! !DESCRIPTION: ! Zero out global budget diagnostic data. ! ! !REVISION HISTORY: ! 2008-jul-11 - T. Craig - update ! ! !INTERFACE: ------------------------------------------------------------------ subroutine seq_diag_zero_mct(EClock,mode) 2,3 ! !INPUT/OUTPUT PARAMETERS: type(ESMF_Clock), intent(in),optional :: EClock character(len=*), intent(in),optional :: mode !EOP integer(IN) :: ip,yr,mon,day,sec !----- formats ----- character(*),parameter :: subName = '(seq_diag_zero_mct) ' !------------------------------------------------------------------------------- ! !------------------------------------------------------------------------------- if (.not. present(EClock) .and. .not. present(mode)) then call shr_sys_abort(subName//' ERROR EClock or mode should be present') endif if (present(EClock)) then call seq_timemgr_EClockGetData(EClock,curr_yr=yr, & curr_mon=mon,curr_day=day,curr_tod=sec) do ip = 1,p_size if (ip == p_inst) then budg_dataL(:,:,ip) = 0.0_r8 budg_dataG(:,:,ip) = 0.0_r8 budg_ns(:,:,ip) = 0.0_r8 endif if (ip==p_day .and. sec==0) then budg_dataL(:,:,ip) = 0.0_r8 budg_dataG(:,:,ip) = 0.0_r8 budg_ns(:,:,ip) = 0.0_r8 endif if (ip==p_mon .and. day==1 .and. sec==0) then budg_dataL(:,:,ip) = 0.0_r8 budg_dataG(:,:,ip) = 0.0_r8 budg_ns(:,:,ip) = 0.0_r8 endif if (ip==p_ann .and. mon==1 .and. day==1 .and. sec==0) then budg_dataL(:,:,ip) = 0.0_r8 budg_dataG(:,:,ip) = 0.0_r8 budg_ns(:,:,ip) = 0.0_r8 endif enddo endif if (present(mode)) then if (trim(mode) == 'inst') then budg_dataL(:,:,p_inst) = 0.0_r8 budg_dataG(:,:,p_inst) = 0.0_r8 budg_ns(:,:,p_inst) = 0.0_r8 elseif (trim(mode) == 'day') then budg_dataL(:,:,p_day) = 0.0_r8 budg_dataG(:,:,p_day) = 0.0_r8 budg_ns(:,:,p_day) = 0.0_r8 elseif (trim(mode) == 'mon') then budg_dataL(:,:,p_mon) = 0.0_r8 budg_dataG(:,:,p_mon) = 0.0_r8 budg_ns(:,:,p_mon) = 0.0_r8 elseif (trim(mode) == 'ann') then budg_dataL(:,:,p_ann) = 0.0_r8 budg_dataG(:,:,p_ann) = 0.0_r8 budg_ns(:,:,p_ann) = 0.0_r8 elseif (trim(mode) == 'inf') then budg_dataL(:,:,p_inf) = 0.0_r8 budg_dataG(:,:,p_inf) = 0.0_r8 budg_ns(:,:,p_inf) = 0.0_r8 elseif (trim(mode) == 'all') then budg_dataL(:,:,:) = 0.0_r8 budg_dataG(:,:,:) = 0.0_r8 budg_ns(:,:,:) = 0.0_r8 else call shr_sys_abort(subname//' ERROR in mode '//trim(mode)) endif endif end subroutine seq_diag_zero_mct !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: seq_diag_accum_mct - accum out global budget diagnostic data. ! ! !DESCRIPTION: ! Accum out global budget diagnostic data. ! ! !REVISION HISTORY: ! 2008-jul-11 - T. Craig - update ! ! !INTERFACE: ------------------------------------------------------------------ subroutine seq_diag_accum_mct() 1 ! !INPUT/OUTPUT PARAMETERS: !EOP integer(in) :: ip !----- formats ----- character(*),parameter :: subName = '(seq_diag_accum_mct) ' !------------------------------------------------------------------------------- ! !------------------------------------------------------------------------------- do ip = p_inst+1,p_size budg_dataL(:,:,ip) = budg_dataL(:,:,ip) + budg_dataL(:,:,p_inst) enddo budg_ns(:,:,:) = budg_ns(:,:,:) + 1.0_r8 end subroutine seq_diag_accum_mct !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: seq_diag_sum0_mct - sum local to global on root ! ! !DESCRIPTION: ! Sum local values to global on root ! ! !REVISION HISTORY: ! 2008-jul-19 - T. Craig - update ! ! !INTERFACE: ------------------------------------------------------------------ subroutine seq_diag_sum0_mct() 1,1 ! !INPUT/OUTPUT PARAMETERS: !EOP real(r8) :: budg_dataGtmp(f_size,c_size,p_size) ! temporary sum integer(in) :: mpicom ! mpi comm !----- formats ----- character(*),parameter :: subName = '(seq_diag_sum0_mct) ' !------------------------------------------------------------------------------- ! !------------------------------------------------------------------------------- call seq_comm_setptrs(CPLID,mpicom=mpicom) budg_dataGtmp = 0.0_r8 call shr_mpi_sum(budg_dataL,budg_dataGtmp,mpicom,subName) budg_dataG = budg_dataG + budg_dataGtmp budg_dataL = 0.0_r8 end subroutine seq_diag_sum0_mct !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: seq_diag_atm_mct - compute global atm input/output flux diagnostics ! ! !DESCRIPTION: ! Compute global atm input/output flux diagnostics ! ! !REVISION HISTORY: ! 2008-jul-10 - T. Craig - update ! ! !INTERFACE: ------------------------------------------------------------------ subroutine seq_diag_atm_mct( dom_a, frac_a, a2x_a, x2a_a ) 1,1 ! !INPUT/OUTPUT PARAMETERS: type(mct_gGrid),intent(in) :: dom_a ! model domain type(mct_aVect),intent(in) :: frac_a ! domain fractions type(mct_aVect),intent(in),optional :: a2x_a ! model to drv bundle type(mct_aVect),intent(in),optional :: x2a_a ! drv to model bundle !EOP !----- local ----- integer(in) :: k,n,ic,if,ip ! generic index integer(in) :: kArea ! index of area field in aVect integer(in) :: kLat ! index of lat field in aVect integer(in) :: kl,ka,ko,ki ! fraction indices integer(in) :: lSize ! size of aVect real(r8) :: da,di,do,dl ! area of a grid cell !----- formats ----- character(*),parameter :: subName = '(seq_diag_atm_mct) ' !------------------------------------------------------------------------------- ! !------------------------------------------------------------------------------- if (.not. present(a2x_a) .and. .not. present(x2a_a)) then call shr_sys_abort(subName//"ERROR: must input a bundle") end if kArea = mct_aVect_indexRA(dom_a%data,afldname) kLat = mct_aVect_indexRA(dom_a%data,latname) ka = mct_aVect_indexRA(frac_a,afracname) kl = mct_aVect_indexRA(frac_a,lfracname) ko = mct_aVect_indexRA(frac_a,ofracname) ki = mct_aVect_indexRA(frac_a,ifracname) !--------------------------------------------------------------------------- ! add values found in this bundle to the budget table !--------------------------------------------------------------------------- ip = p_inst if (present(a2x_a)) then lSize = mct_avect_lSize(a2x_a) do n=1,lSize do k=1,4 if (k == 1) then ic = c_atm_ar da = -dom_a%data%rAttr(kArea,n) * frac_a%rAttr(ka,n) elseif (k == 2) then ic = c_lnd_ar da = dom_a%data%rAttr(kArea,n) * frac_a%rAttr(kl,n) elseif (k == 3) then ic = c_ocn_ar da = dom_a%data%rAttr(kArea,n) * frac_a%rAttr(ko,n) elseif (k == 4) then if (dom_a%data%rAttr(kLat,n) > 0.0_r8) then ic = c_inh_ar else ic = c_ish_ar endif da = dom_a%data%rAttr(kArea,n) * frac_a%rAttr(ki,n) endif if = f_area ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + da if = f_hswnet; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + da*a2x_a%rAttr(index_a2x_Faxa_swnet,n) if = f_hlwdn ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + da*a2x_a%rAttr(index_a2x_Faxa_lwdn,n) if = f_wrain ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + da*a2x_a%rAttr(index_a2x_Faxa_rainc,n) & + da*a2x_a%rAttr(index_a2x_Faxa_rainl,n) if = f_wsnow ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + da*a2x_a%rAttr(index_a2x_Faxa_snowc,n) & + da*a2x_a%rAttr(index_a2x_Faxa_snowl,n) enddo enddo ! --- heat implied by snow flux --- ic = c_atm_ar; budg_dataL(f_hlatf,ic,ip) = -budg_dataL(f_wsnow,ic,ip)*shr_const_latice ic = c_lnd_ar; budg_dataL(f_hlatf,ic,ip) = -budg_dataL(f_wsnow,ic,ip)*shr_const_latice ic = c_ocn_ar; budg_dataL(f_hlatf,ic,ip) = -budg_dataL(f_wsnow,ic,ip)*shr_const_latice ic = c_inh_ar; budg_dataL(f_hlatf,ic,ip) = -budg_dataL(f_wsnow,ic,ip)*shr_const_latice ic = c_ish_ar; budg_dataL(f_hlatf,ic,ip) = -budg_dataL(f_wsnow,ic,ip)*shr_const_latice end if if (present(x2a_a)) then lSize = mct_avect_lSize(x2a_a) do n=1,lSize do k=1,4 if (k == 1) then ic = c_atm_as da = -dom_a%data%rAttr(kArea,n) * frac_a%rAttr(ka,n) elseif (k == 2) then ic = c_lnd_as da = dom_a%data%rAttr(kArea,n) * frac_a%rAttr(kl,n) elseif (k == 3) then ic = c_ocn_as da = dom_a%data%rAttr(kArea,n) * frac_a%rAttr(ko,n) elseif (k == 4) then if (dom_a%data%rAttr(kLat,n) > 0.0_r8) then ic = c_inh_as else ic = c_ish_as endif da = dom_a%data%rAttr(kArea,n) * frac_a%rAttr(ki,n) endif if = f_area ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + da if = f_hlwup; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + da*x2a_a%rAttr(index_x2a_Faxx_lwup,n) if = f_hlatv; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + da*x2a_a%rAttr(index_x2a_Faxx_lat,n) if = f_hsen ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + da*x2a_a%rAttr(index_x2a_Faxx_sen,n) if = f_wevap; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + da*x2a_a%rAttr(index_x2a_Faxx_evap,n) enddo enddo end if end subroutine seq_diag_atm_mct !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: seq_diag_lnd_mct - compute global lnd input/output flux diagnostics ! ! !DESCRIPTION: ! Compute global lnd input/output flux diagnostics ! ! !REVISION HISTORY: ! 2008-jul-10 - T. Craig - update ! ! !INTERFACE: ------------------------------------------------------------------ subroutine seq_diag_lnd_mct( dom_l, frac_l, l2x_l, x2l_l) 1,1 type(mct_gGrid),intent(in) :: dom_l ! model domain type(mct_aVect),intent(in) :: frac_l ! frac bundle type(mct_aVect),intent(in),optional :: l2x_l ! model to drv bundle type(mct_aVect),intent(in),optional :: x2l_l ! drv to model bundle !EOP !----- local ----- integer(in) :: k,n,ic,if,ip ! generic index integer(in) :: kArea ! index of area field in aVect integer(in) :: kLat ! index of lat field in aVect integer(in) :: kl,ka,ko,ki ! fraction indices integer(in) :: lSize ! size of aVect real(r8) :: da,di,do,dl ! area of a grid cell !----- formats ----- character(*),parameter :: subName = '(seq_diag_lnd_mct) ' !------------------------------------------------------------------------------- ! !------------------------------------------------------------------------------- if (.not. present(l2x_l) .and. .not. present(x2l_l)) then call shr_sys_abort(subName//"ERROR: must input a bundle") end if !--------------------------------------------------------------------------- ! add values found in this bundle to the budget table !--------------------------------------------------------------------------- ip = p_inst kArea = mct_aVect_indexRA(dom_l%data,afldname) kl = mct_aVect_indexRA(frac_l,lfrinname) ka = mct_aVect_indexRA(dom_l%data,ascalname) if (present(l2x_l)) then lSize = mct_avect_lSize(l2x_l) ic = c_lnd_lr do n=1,lSize dl = dom_l%data%rAttr(kArea,n) * frac_l%rAttr(kl,n) * dom_l%data%rAttr(ka,n) if = f_area ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + dl if = f_hswnet; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + dl*l2x_l%rAttr(index_l2x_Fall_swnet,n) if = f_hlwup ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + dl*l2x_l%rAttr(index_l2x_Fall_lwup,n) if = f_hlatv ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + dl*l2x_l%rAttr(index_l2x_Fall_lat,n) if = f_hsen ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + dl*l2x_l%rAttr(index_l2x_Fall_sen,n) if = f_wevap ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + dl*l2x_l%rAttr(index_l2x_Fall_evap,n) end do end if if (present(x2l_l)) then lSize = mct_avect_lSize(x2l_l) ic = c_lnd_ls do n=1,lSize dl = dom_l%data%rAttr(kArea,n) * frac_l%rAttr(kl,n) * dom_l%data%rAttr(ka,n) if = f_area ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + dl if = f_hlwdn; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + dl*x2l_l%rAttr(index_x2l_Faxa_lwdn,n) if = f_wrain; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + dl*x2l_l%rAttr(index_x2l_Faxa_rainc,n) & + dl*x2l_l%rAttr(index_x2l_Faxa_rainl,n) if = f_wsnow; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + dl*x2l_l%rAttr(index_x2l_Faxa_snowc,n) & + dl*x2l_l%rAttr(index_x2l_Faxa_snowl,n) end do budg_dataL(f_hlatf,ic,ip) = -budg_dataL(f_wsnow,ic,ip)*shr_const_latice end if end subroutine seq_diag_lnd_mct !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: seq_diag_rtm_mct - compute global rtm input/output flux diagnostics ! ! !DESCRIPTION: ! Compute global rtm input/output flux diagnostics ! ! !REVISION HISTORY: ! 2008-jul-10 - T. Craig - update ! ! !INTERFACE: ------------------------------------------------------------------ subroutine seq_diag_rtm_mct( dom_r, r2x_r) 1 type(mct_gGrid),intent(in) :: dom_r ! model domain type(mct_aVect),intent(in) :: r2x_r ! model to drv bundle !EOP !----- local ----- integer(in) :: k,n,ic,if,ip ! generic index integer(in) :: kArea ! index of area field in aVect integer(in) :: kLat ! index of lat field in aVect integer(in) :: kl,ka,ko,ki ! fraction indices integer(in) :: lSize ! size of aVect real(r8) :: da,di,do,dl ! area of a grid cell !----- formats ----- character(*),parameter :: subName = '(seq_diag_rtm_mct) ' !------------------------------------------------------------------------------- ! !------------------------------------------------------------------------------- !--------------------------------------------------------------------------- ! add values found in this bundle to the budget table !--------------------------------------------------------------------------- ip = p_inst ic = c_lnd_lr kArea = mct_aVect_indexRA(dom_r%data,afldname) lSize = mct_avect_lSize(r2x_r) do n=1,lSize dl = dom_r%data%rAttr(kArea,n) if = f_wroff; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) - dl*r2x_r%rAttr(index_r2x_Forr_roff,n) if = f_wioff; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) - dl*r2x_r%rAttr(index_r2x_Forr_ioff,n) end do budg_dataL(f_hioff,ic,ip) = -budg_dataL(f_wioff,ic,ip)*shr_const_latice end subroutine seq_diag_rtm_mct !BOP =========================================================================== ! ! !IROUTINE: seq_diag_ocn_mct - compute global ocn input/output flux diagnostics ! ! !DESCRIPTION: ! Compute global ocn input/output flux diagnostics ! ! !REVISION HISTORY: ! 2008-jul-10 - T. Craig - update ! ! !INTERFACE: ------------------------------------------------------------------ subroutine seq_diag_ocn_mct( dom_o, frac_o, o2x_o, x2o_o, xao_o, r2x_o) 1,1 type(mct_gGrid),intent(in) :: dom_o ! model domain type(mct_aVect),intent(in) :: frac_o ! frac bundle type(mct_aVect),intent(in),optional :: o2x_o ! model to drv bundle type(mct_aVect),intent(in),optional :: x2o_o ! drv to model bundle type(mct_aVect),intent(in),optional :: xao_o ! drv to model bundle type(mct_aVect),intent(in),optional :: r2x_o ! roff to drv bundle !EOP !----- local ----- integer(in) :: k,n,if,ic,ip ! generic index integer(in) :: kArea ! index of area field in aVect integer(in) :: kLat ! index of lat field in aVect integer(in) :: kl,ka,ko,ki ! fraction indices integer(in) :: lSize ! size of aVect real(r8) :: da,di,do,dl ! area of a grid cell !----- formats ----- character(*),parameter :: subName = '(seq_diag_ocn_mct) ' !------------------------------------------------------------------------------- ! !------------------------------------------------------------------------------- if (.not. present(o2x_o) .and. .not. present(x2o_o) .and. .not. present(xao_o)) then call shr_sys_abort(subName//"ERROR: must input a bundle") end if !--------------------------------------------------------------------------- ! add values found in this bundle to the budget table !--------------------------------------------------------------------------- ip = p_inst kArea = mct_aVect_indexRA(dom_o%data,afldname) ko = mct_aVect_indexRA(frac_o,ofracname) ki = mct_aVect_indexRA(frac_o,ifracname) if (present(o2x_o)) then lSize = mct_avect_lSize(o2x_o) ic = c_ocn_or do n=1,lSize do = dom_o%data%rAttr(kArea,n) * frac_o%rAttr(ko,n) di = dom_o%data%rAttr(kArea,n) * frac_o%rAttr(ki,n) if = f_area; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + do if = f_hfrz; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + (do+di)*max(0.0_r8,o2x_o%rAttr(index_o2x_Fioo_q,n)) end do budg_dataL(f_wfrz,ic,ip) = budg_dataL(f_hfrz,ic,ip) * HFLXtoWFLX end if if (present(xao_o)) then lSize = mct_avect_lSize(xao_o) ic = c_ocn_or do n=1,lSize do = dom_o%data%rAttr(kArea,n) * frac_o%rAttr(ko,n) if = f_hlwup; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + do*xao_o%rAttr(index_xao_Faox_lwup,n) if = f_hlatv; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + do*xao_o%rAttr(index_xao_Faox_lat,n) if = f_hsen ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + do*xao_o%rAttr(index_xao_Faox_sen,n) if = f_wevap; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + do*xao_o%rAttr(index_xao_Faox_evap,n) end do end if if (present(x2o_o)) then lSize = mct_avect_lSize(x2o_o) ic = c_ocn_os do n=1,lSize do = dom_o%data%rAttr(kArea,n) * frac_o%rAttr(ko,n) di = dom_o%data%rAttr(kArea,n) * frac_o%rAttr(ki,n) if = f_area ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + do if = f_hmelt ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + (do+di)*x2o_o%rAttr(index_x2o_Foxx_melth,n) if = f_hswnet; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + (do+di)*x2o_o%rAttr(index_x2o_Foxx_swnet,n) if = f_hlwdn ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + (do+di)*x2o_o%rAttr(index_x2o_Foxx_lwdn,n) if = f_wmelt ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + (do+di)*x2o_o%rAttr(index_x2o_Foxx_meltw,n) if = f_wrain ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + (do+di)*x2o_o%rAttr(index_x2o_Foxx_rain,n) if = f_wsnow ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + (do+di)*x2o_o%rAttr(index_x2o_Foxx_snow,n) ! if = f_wroff ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + (do+di)*x2o_o%rAttr(index_x2o_Forr_roff,n) ! if = f_wioff ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + (do+di)*x2o_o%rAttr(index_x2o_Forr_ioff,n) end do budg_dataL(f_hlatf,ic,ip) = -budg_dataL(f_wsnow,ic,ip)*shr_const_latice end if if (present(r2x_o)) then lSize = mct_avect_lSize(r2x_o) ic = c_ocn_os do n=1,lSize do = dom_o%data%rAttr(kArea,n) * frac_o%rAttr(ko,n) di = dom_o%data%rAttr(kArea,n) * frac_o%rAttr(ki,n) if = f_wroff ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + (do+di)*r2x_o%rAttr(index_r2x_Forr_roff,n) if = f_wioff ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + (do+di)*r2x_o%rAttr(index_r2x_Forr_ioff,n) end do budg_dataL(f_hioff,ic,ip) = -budg_dataL(f_wioff,ic,ip)*shr_const_latice end if end subroutine seq_diag_ocn_mct !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: seq_diag_ice_mct - compute global ice input/output flux diagnostics ! ! !DESCRIPTION: ! Compute global ice input/output flux diagnostics ! ! !REVISION HISTORY: ! 2008-jul-10 - T. Craig - update ! ! !INTERFACE: ------------------------------------------------------------------ subroutine seq_diag_ice_mct( dom_i, frac_i, i2x_i, x2i_i) 2,1 type(mct_gGrid),intent(in) :: dom_i ! model domain type(mct_aVect),intent(in) :: frac_i ! frac bundle type(mct_aVect),intent(in),optional :: i2x_i ! model to drv bundle type(mct_aVect),intent(in),optional :: x2i_i ! drv to model bundle !EOP !----- local ----- integer(in) :: k,n,ic,if,ip ! generic index integer(in) :: kArea ! index of area field in aVect integer(in) :: kLat ! index of lat field in aVect integer(in) :: kl,ka,ko,ki ! fraction indices integer(in) :: lSize ! size of aVect real(r8) :: da,di,do,dl ! area of a grid cell !----- formats ----- character(*),parameter :: subName = '(seq_diag_ice_mct) ' !------------------------------------------------------------------------------- ! !------------------------------------------------------------------------------- if (.not. present(i2x_i) .and. .not. present(x2i_i)) then call shr_sys_abort(subName//"ERROR: must input a bundle") end if !--------------------------------------------------------------------------- ! add values found in this bundle to the budget table !--------------------------------------------------------------------------- ip = p_inst kArea = mct_aVect_indexRA(dom_i%data,afldname) kLat = mct_aVect_indexRA(dom_i%data,latname) ki = mct_aVect_indexRA(frac_i,ifracname) ko = mct_aVect_indexRA(frac_i,ofracname) if (present(i2x_i)) then lSize = mct_avect_lSize(i2x_i) do n=1,lSize if (dom_i%data%rAttr(kLat,n) > 0.0_r8) then ic = c_inh_ir else ic = c_ish_ir endif di = dom_i%data%rAttr(kArea,n) * frac_i%rAttr(ki,n) if = f_area ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + di if = f_hmelt ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) - di*i2x_i%rAttr(index_i2x_Fioi_melth,n) if = f_wmelt ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) - di*i2x_i%rAttr(index_i2x_Fioi_meltw,n) if = f_hswnet; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + di*i2x_i%rAttr(index_i2x_Faii_swnet,n) & - di*i2x_i%rAttr(index_i2x_Fioi_swpen,n) if = f_hlwup ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + di*i2x_i%rAttr(index_i2x_Faii_lwup,n) if = f_hlatv ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + di*i2x_i%rAttr(index_i2x_Faii_lat,n) if = f_hsen ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + di*i2x_i%rAttr(index_i2x_Faii_sen,n) if = f_wevap ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + di*i2x_i%rAttr(index_i2x_Faii_evap,n) end do end if if (present(x2i_i)) then lSize = mct_avect_lSize(x2i_i) do n=1,lSize if (dom_i%data%rAttr(kLat,n) > 0.0_r8) then ic = c_inh_is else ic = c_ish_is endif do = dom_i%data%rAttr(kArea,n) * frac_i%rAttr(ko,n) di = dom_i%data%rAttr(kArea,n) * frac_i%rAttr(ki,n) if = f_area ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + di if = f_hlwdn; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + di*x2i_i%rAttr(index_x2i_Faxa_lwdn,n) if = f_wrain; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + di*x2i_i%rAttr(index_x2i_Faxa_rain,n) if = f_wsnow; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) + di*x2i_i%rAttr(index_x2i_Faxa_snow,n) if = f_hfrz ; budg_dataL(if,ic,ip) = budg_dataL(if,ic,ip) - (do+di)*max(0.0_r8,x2i_i%rAttr(index_x2i_Fioo_q,n)) end do ic = c_inh_is budg_dataL(f_hlatf,ic,ip) = -budg_dataL(f_wsnow,ic,ip)*shr_const_latice budg_dataL(f_wfrz ,ic,ip) = budg_dataL(f_hfrz ,ic,ip)*HFLXtoWFLX ic = c_ish_is budg_dataL(f_hlatf,ic,ip) = -budg_dataL(f_wsnow,ic,ip)*shr_const_latice budg_dataL(f_wfrz ,ic,ip) = budg_dataL(f_hfrz ,ic,ip)*HFLXtoWFLX end if end subroutine seq_diag_ice_mct !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: seq_diag_print_mct - print global budget diagnostics ! ! !DESCRIPTION: ! Print global budget diagnostics. ! ! !REVISION HISTORY: ! ! !INTERFACE: ------------------------------------------------------------------ SUBROUTINE seq_diag_print_mct(EClock,stop_alarm, & 1,5 budg_print_inst, budg_print_daily, budg_print_month, & budg_print_ann, budg_print_ltann, budg_print_ltend) implicit none ! !INPUT/OUTPUT PARAMETERS: type(ESMF_Clock), intent(in) :: EClock logical,intent(in) :: stop_alarm integer,intent(in) :: budg_print_inst integer,intent(in) :: budg_print_daily integer,intent(in) :: budg_print_month integer,intent(in) :: budg_print_ann integer,intent(in) :: budg_print_ltann integer,intent(in) :: budg_print_ltend !EOP !--- local --- integer(in) :: ic,if,ip ! data array indicies integer(in) :: ica,icl,icn,ics,ico integer(in) :: icar,icxs,icxr,icas integer(in) :: n ! loop counter integer(in) :: nday ! number of days in time avg integer(in) :: cdate,sec ! coded date, seconds integer(in) :: yr,mon,day ! date integer(in) :: iam ! pe number integer(in) :: plev ! print level logical :: sumdone ! has a sum been computed yet character(len=40):: str ! string real(r8) :: dataGpr (f_size,c_size,p_size) ! values to print, scaled and such !----- formats ----- character(*),parameter :: subName = '(seq_diag_print_mct) ' character(*),parameter :: F00 = "('(seq_diag_print_mct) ',4a)" !----- formats ----- character(*),parameter :: FAH="(4a,i9,i6)" character(*),parameter :: FA0="(' ',8x,6(6x,a8,1x))" character(*),parameter :: FA1="(' ',a8,6f15.8)" !------------------------------------------------------------------------------- ! print instantaneous budget data !------------------------------------------------------------------------------- sumdone = .false. call seq_comm_setptrs(CPLID,iam=iam) call seq_timemgr_EClockGetData(EClock,curr_yr=yr, & curr_mon=mon,curr_day=day,curr_tod=sec) cdate = yr*10000+mon*100+day do ip = 1,p_size plev = 0 if (ip == p_inst) then plev = max(plev,budg_print_inst) endif if (ip==p_day .and. sec==0) then plev = max(plev,budg_print_daily) endif if (ip==p_mon .and. day==1 .and. sec==0) then plev = max(plev,budg_print_month) endif if (ip==p_ann .and. mon==1 .and. day==1 .and. sec==0) then plev = max(plev,budg_print_ann) endif if (ip==p_inf .and. mon==1 .and. day==1 .and. sec==0) then plev = max(plev,budg_print_ltann) endif if (ip==p_inf .and. stop_alarm) then plev = max(plev,budg_print_ltend) endif if (plev > 0) then ! ---- doprint ---- doprint ---- doprint ---- if (.not.sumdone) then call seq_diag_sum0_mct() dataGpr = budg_dataG sumdone = .true. ! old budget normalizations (global area and 1e6 for water) dataGpr = dataGpr/(4.0_r8*shr_const_pi) dataGpr(f_w:f_size,:,:) = dataGpr(f_w:f_size,:,:) * 1.0e6_r8 dataGpr = dataGpr/budg_ns if (iam /= 0) return endif ! --------------------------------------------------------- ! ---- detail atm budgets and breakdown into components --- ! --------------------------------------------------------- if (plev >= 3) then do ic = 1,2 if (ic == 1) then ica = c_atm_ar icl = c_lnd_ar icn = c_inh_ar ics = c_ish_ar ico = c_ocn_ar str = "ATM_to_CPL" elseif (ic == 2) then ica = c_atm_as icl = c_lnd_as icn = c_inh_as ics = c_ish_as ico = c_ocn_as str = "CPL_TO_ATM" else call shr_sys_abort(subname//' ERROR in ic index code 411') endif write(logunit,*) ' ' write(logunit,FAH) subname,trim(str)//' AREA BUDGET (m2/m2): period = ',trim(pname(ip)),': date = ',cdate,sec write(logunit,FA0) cname(ica),cname(icl),cname(icn),cname(ics),cname(ico),' *SUM* ' do if = f_a, f_h-1 write(logunit,FA1) fname(if),dataGpr(if,ica,ip),dataGpr(if,icl,ip), & dataGpr(if,icn,ip),dataGpr(if,ics,ip),dataGpr(if,ico,ip), & dataGpr(if,ica,ip)+dataGpr(if,icl,ip)+ & dataGpr(if,icn,ip)+dataGpr(if,ics,ip)+dataGpr(if,ico,ip) enddo write(logunit,*) ' ' write(logunit,FAH) subname,trim(str)//' HEAT BUDGET (W/m2): period = ',trim(pname(ip)),': date = ',cdate,sec write(logunit,FA0) cname(ica),cname(icl),cname(icn),cname(ics),cname(ico),' *SUM* ' do if = f_h, f_w-1 write(logunit,FA1) fname(if),dataGpr(if,ica,ip),dataGpr(if,icl,ip), & dataGpr(if,icn,ip),dataGpr(if,ics,ip),dataGpr(if,ico,ip), & dataGpr(if,ica,ip)+dataGpr(if,icl,ip)+ & dataGpr(if,icn,ip)+dataGpr(if,ics,ip)+dataGpr(if,ico,ip) enddo write(logunit,FA1) ' *SUM*',sum(dataGpr(f_h:f_w-1,ica,ip)),sum(dataGpr(f_h:f_w-1,icl,ip)), & sum(dataGpr(f_h:f_w-1,icn,ip)),sum(dataGpr(f_h:f_w-1,ics,ip)),sum(dataGpr(f_h:f_w-1,ico,ip)), & sum(dataGpr(f_h:f_w-1,ica,ip))+sum(dataGpr(f_h:f_w-1,icl,ip))+ & sum(dataGpr(f_h:f_w-1,icn,ip))+sum(dataGpr(f_h:f_w-1,ics,ip))+sum(dataGpr(f_h:f_w-1,ico,ip)) write(logunit,*) ' ' write(logunit,FAH) subname,trim(str)//' WATER BUDGET (kg/m2s*1e6): period = ',trim(pname(ip)),': date = ',cdate,sec write(logunit,FA0) cname(ica),cname(icl),cname(icn),cname(ics),cname(ico),' *SUM* ' do if = f_w, f_size write(logunit,FA1) fname(if),dataGpr(if,ica,ip),dataGpr(if,icl,ip), & dataGpr(if,icn,ip),dataGpr(if,ics,ip),dataGpr(if,ico,ip), & dataGpr(if,ica,ip)+dataGpr(if,icl,ip)+ & dataGpr(if,icn,ip)+dataGpr(if,ics,ip)+dataGpr(if,ico,ip) enddo write(logunit,FA1) ' *SUM*',sum(dataGpr(f_w:f_size,ica,ip)),sum(dataGpr(f_w:f_size,icl,ip)), & sum(dataGpr(f_w:f_size,icn,ip)),sum(dataGpr(f_w:f_size,ics,ip)),sum(dataGpr(f_w:f_size,ico,ip)), & sum(dataGpr(f_w:f_size,ica,ip))+sum(dataGpr(f_w:f_size,icl,ip))+ & sum(dataGpr(f_w:f_size,icn,ip))+sum(dataGpr(f_w:f_size,ics,ip))+sum(dataGpr(f_w:f_size,ico,ip)) enddo endif ! plev ! --------------------------------------------------------- ! ---- detail lnd/ocn/ice component budgets ---- ! --------------------------------------------------------- if (plev >= 2) then do ic = 1,4 if (ic == 1) then icar = c_lnd_ar icxs = c_lnd_ls icxr = c_lnd_lr icas = c_lnd_as str = "LND" elseif (ic == 2) then icar = c_ocn_ar icxs = c_ocn_os icxr = c_ocn_or icas = c_ocn_as str = "OCN" elseif (ic == 3) then icar = c_inh_ar icxs = c_inh_is icxr = c_inh_ir icas = c_inh_as str = "ICE_NH" elseif (ic == 4) then icar = c_ish_ar icxs = c_ish_is icxr = c_ish_ir icas = c_ish_as str = "ICE_SH" else call shr_sys_abort(subname//' ERROR in ic index code 412') endif write(logunit,*) ' ' write(logunit,FAH) subname,trim(str)//' HEAT BUDGET (W/m2): period = ',trim(pname(ip)),': date = ',cdate,sec write(logunit,FA0) cname(icar),cname(icxs),cname(icxr),cname(icas),' *SUM* ' do if = f_h, f_w-1 write(logunit,FA1) fname(if),-dataGpr(if,icar,ip),dataGpr(if,icxs,ip), & dataGpr(if,icxr,ip),-dataGpr(if,icas,ip), & -dataGpr(if,icar,ip)+dataGpr(if,icxs,ip)+ & dataGpr(if,icxr,ip)-dataGpr(if,icas,ip) enddo write(logunit,FA1) ' *SUM*',-sum(dataGpr(f_h:f_w-1,icar,ip)),sum(dataGpr(f_h:f_w-1,icxs,ip)), & sum(dataGpr(f_h:f_w-1,icxr,ip)),-sum(dataGpr(f_h:f_w-1,icas,ip)), & -sum(dataGpr(f_h:f_w-1,icar,ip))+sum(dataGpr(f_h:f_w-1,icxs,ip))+ & sum(dataGpr(f_h:f_w-1,icxr,ip))-sum(dataGpr(f_h:f_w-1,icas,ip)) write(logunit,*) ' ' write(logunit,FAH) subname,trim(str)//' WATER BUDGET (kg/m2s*1e6): period = ',trim(pname(ip)),': date = ',cdate,sec write(logunit,FA0) cname(icar),cname(icxs),cname(icxr),cname(icas),' *SUM* ' do if = f_w, f_size write(logunit,FA1) fname(if),-dataGpr(if,icar,ip),dataGpr(if,icxs,ip), & dataGpr(if,icxr,ip),-dataGpr(if,icas,ip), & -dataGpr(if,icar,ip)+dataGpr(if,icxs,ip)+ & dataGpr(if,icxr,ip)-dataGpr(if,icas,ip) enddo write(logunit,FA1) ' *SUM*',-sum(dataGpr(f_w:f_size,icar,ip)),sum(dataGpr(f_w:f_size,icxs,ip)), & sum(dataGpr(f_w:f_size,icxr,ip)),-sum(dataGpr(f_w:f_size,icas,ip)), & -sum(dataGpr(f_w:f_size,icar,ip))+sum(dataGpr(f_w:f_size,icxs,ip))+ & sum(dataGpr(f_w:f_size,icxr,ip))-sum(dataGpr(f_w:f_size,icas,ip)) enddo endif ! plev ! --------------------------------------------------------- ! ---- net summary budgets ---- ! --------------------------------------------------------- if (plev >= 1) then write(logunit,*) ' ' write(logunit,FAH) subname,'NET AREA BUDGET (m2/m2): period = ',trim(pname(ip)),': date = ',cdate,sec write(logunit,FA0) ' atm',' lnd',' ocn',' ice nh',' ice sh',' *SUM* ' do if = 1,f_h-1 write(logunit,FA1) fname(if),dataGpr(if,c_atm_ar,ip), & dataGpr(if,c_lnd_lr,ip), & dataGpr(if,c_ocn_or,ip), & dataGpr(if,c_inh_ir,ip), & dataGpr(if,c_ish_ir,ip), & dataGpr(if,c_atm_ar,ip)+ & dataGpr(if,c_lnd_lr,ip)+ & dataGpr(if,c_ocn_or,ip)+ & dataGpr(if,c_inh_ir,ip)+ & dataGpr(if,c_ish_ir,ip) enddo write(logunit,*) ' ' write(logunit,FAH) subname,'NET HEAT BUDGET (W/m2): period = ',trim(pname(ip)),': date = ',cdate,sec write(logunit,FA0) ' atm',' lnd',' ocn',' ice nh',' ice sh',' *SUM* ' do if = f_h, f_w-1 write(logunit,FA1) fname(if),dataGpr(if,c_atm_ar,ip)+dataGpr(if,c_atm_as,ip), & dataGpr(if,c_lnd_lr,ip)+dataGpr(if,c_lnd_ls,ip), & dataGpr(if,c_ocn_or,ip)+dataGpr(if,c_ocn_os,ip), & dataGpr(if,c_inh_ir,ip)+dataGpr(if,c_inh_is,ip), & dataGpr(if,c_ish_ir,ip)+dataGpr(if,c_ish_is,ip), & dataGpr(if,c_atm_ar,ip)+dataGpr(if,c_atm_as,ip)+ & dataGpr(if,c_lnd_lr,ip)+dataGpr(if,c_lnd_ls,ip)+ & dataGpr(if,c_ocn_or,ip)+dataGpr(if,c_ocn_os,ip)+ & dataGpr(if,c_inh_ir,ip)+dataGpr(if,c_inh_is,ip)+ & dataGpr(if,c_ish_ir,ip)+dataGpr(if,c_ish_is,ip) enddo write(logunit,FA1) ' *SUM*',sum(dataGpr(f_h:f_w-1,c_atm_ar,ip))+sum(dataGpr(f_h:f_w-1,c_atm_as,ip)), & sum(dataGpr(f_h:f_w-1,c_lnd_lr,ip))+sum(dataGpr(f_h:f_w-1,c_lnd_ls,ip)), & sum(dataGpr(f_h:f_w-1,c_ocn_or,ip))+sum(dataGpr(f_h:f_w-1,c_ocn_os,ip)), & sum(dataGpr(f_h:f_w-1,c_inh_ir,ip))+sum(dataGpr(f_h:f_w-1,c_inh_is,ip)), & sum(dataGpr(f_h:f_w-1,c_ish_ir,ip))+sum(dataGpr(f_h:f_w-1,c_ish_is,ip)), & sum(dataGpr(f_h:f_w-1,c_atm_ar,ip))+sum(dataGpr(f_h:f_w-1,c_atm_as,ip))+ & sum(dataGpr(f_h:f_w-1,c_lnd_lr,ip))+sum(dataGpr(f_h:f_w-1,c_lnd_ls,ip))+ & sum(dataGpr(f_h:f_w-1,c_ocn_or,ip))+sum(dataGpr(f_h:f_w-1,c_ocn_os,ip))+ & sum(dataGpr(f_h:f_w-1,c_inh_ir,ip))+sum(dataGpr(f_h:f_w-1,c_inh_is,ip))+ & sum(dataGpr(f_h:f_w-1,c_ish_ir,ip))+sum(dataGpr(f_h:f_w-1,c_ish_is,ip)) write(logunit,*) ' ' write(logunit,FAH) subname,'NET WATER BUDGET (kg/m2s*1e6): period = ',trim(pname(ip)),': date = ',cdate,sec write(logunit,FA0) ' atm',' lnd',' ocn',' ice nh',' ice sh',' *SUM* ' do if = f_w, f_size write(logunit,FA1) fname(if),dataGpr(if,c_atm_ar,ip)+dataGpr(if,c_atm_as,ip), & dataGpr(if,c_lnd_lr,ip)+dataGpr(if,c_lnd_ls,ip), & dataGpr(if,c_ocn_or,ip)+dataGpr(if,c_ocn_os,ip), & dataGpr(if,c_inh_ir,ip)+dataGpr(if,c_inh_is,ip), & dataGpr(if,c_ish_ir,ip)+dataGpr(if,c_ish_is,ip), & dataGpr(if,c_atm_ar,ip)+dataGpr(if,c_atm_as,ip)+ & dataGpr(if,c_lnd_lr,ip)+dataGpr(if,c_lnd_ls,ip)+ & dataGpr(if,c_ocn_or,ip)+dataGpr(if,c_ocn_os,ip)+ & dataGpr(if,c_inh_ir,ip)+dataGpr(if,c_inh_is,ip)+ & dataGpr(if,c_ish_ir,ip)+dataGpr(if,c_ish_is,ip) enddo write(logunit,FA1) ' *SUM*',sum(dataGpr(f_w:f_size,c_atm_ar,ip))+sum(dataGpr(f_w:f_size,c_atm_as,ip)), & sum(dataGpr(f_w:f_size,c_lnd_lr,ip))+sum(dataGpr(f_w:f_size,c_lnd_ls,ip)), & sum(dataGpr(f_w:f_size,c_ocn_or,ip))+sum(dataGpr(f_w:f_size,c_ocn_os,ip)), & sum(dataGpr(f_w:f_size,c_inh_ir,ip))+sum(dataGpr(f_w:f_size,c_inh_is,ip)), & sum(dataGpr(f_w:f_size,c_ish_ir,ip))+sum(dataGpr(f_w:f_size,c_ish_is,ip)), & sum(dataGpr(f_w:f_size,c_atm_ar,ip))+sum(dataGpr(f_w:f_size,c_atm_as,ip))+ & sum(dataGpr(f_w:f_size,c_lnd_lr,ip))+sum(dataGpr(f_w:f_size,c_lnd_ls,ip))+ & sum(dataGpr(f_w:f_size,c_ocn_or,ip))+sum(dataGpr(f_w:f_size,c_ocn_os,ip))+ & sum(dataGpr(f_w:f_size,c_inh_ir,ip))+sum(dataGpr(f_w:f_size,c_inh_is,ip))+ & sum(dataGpr(f_w:f_size,c_ish_ir,ip))+sum(dataGpr(f_w:f_size,c_ish_is,ip)) endif write(logunit,*) ' ' ! ---- doprint ---- doprint ---- doprint ---- endif ! plev > 0 enddo ! ip = 1,p_size end subroutine seq_diag_print_mct !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: seq_diag_avect_mct - print global budget diagnostics ! ! !DESCRIPTION: ! Print global diagnostics for AV/ID. ! ! !REVISION HISTORY: ! ! !INTERFACE: ------------------------------------------------------------------ SUBROUTINE seq_diag_avect_mct(cdata,AV,comment) 23,6 use seq_infodata_mod implicit none ! !INPUT/OUTPUT PARAMETERS: type(seq_cdata) , intent(in) :: cdata type(mct_aVect) , intent(in) :: AV character(len=*), intent(in), optional :: comment !EOP !--- local --- type(mct_gGrid) ,pointer :: dom type(seq_infodata_type),pointer :: infodata type(mct_gsMap) ,pointer :: gsmap integer(in) :: ID logical :: bfbflag integer(in) :: n,k ! counters integer(in) :: npts,nptsg ! number of local/global pts in AV integer(in) :: kflds ! number of fields in AV real(r8),pointer :: sumbuf (:) ! sum buffer real(r8),pointer :: minbuf (:) ! min buffer real(r8),pointer :: maxbuf (:) ! max buffer real(r8),pointer :: sumbufg(:) ! sum buffer reduced real(r8),pointer :: minbufg(:) ! min buffer reduced real(r8),pointer :: maxbufg(:) ! max buffer reduced integer(i8),pointer :: isumbuf (:) ! integer local sum integer(i8),pointer :: isumbufg(:) ! integer global sum integer(i8) :: ihuge ! huge integer(in) :: mpicom ! mpi comm integer(in) :: iam ! pe number integer(in) :: km,ka ! field indices integer(in) :: ns ! size of local AV integer(in) :: rcode ! error code real(r8),pointer :: weight(:) ! weight type(mct_string) :: mstring ! mct char type character(CL) :: lcomment ! should be long enough character(CL) :: itemc ! string converted to char type(mct_avect) :: AV1 ! local avect with one field type(mct_avect) :: AVr1 ! avect on root with one field type(mct_avect) :: AVr2 ! avect on root with one field !----- formats ----- character(*),parameter :: subName = '(seq_diag_avect_mct) ' character(*),parameter :: F00 = "('(seq_diag_avect_mct) ',4a)" !------------------------------------------------------------------------------- ! print instantaneous budget data !------------------------------------------------------------------------------- call seq_cdata_setptrs(cdata,ID=ID,infodata=infodata,dom=dom,gsmap=gsmap) call seq_comm_setptrs(ID,mpicom=mpicom,iam=iam) call seq_infodata_GetData(infodata,bfbflag=bfbflag) lcomment = '' if (present(comment)) then lcomment=trim(comment) endif ns = mct_aVect_lsize(AV) npts = mct_aVect_lsize(dom%data) if (ns /= npts) call shr_sys_abort(trim(subname)//' ERROR: size of AV,dom') km = mct_aVect_indexRA(dom%data,'mask') ka = mct_aVect_indexRA(dom%data,afldname) kflds = mct_aVect_nRattr(AV) allocate(sumbuf(kflds),sumbufg(kflds)) sumbuf = 0.0_r8 if (bfbflag) then npts = mct_aVect_lsize(AV) allocate(weight(npts)) weight(:) = 1.0_r8 do n = 1,npts if (dom%data%rAttr(km,n) <= 1.0e-06_R8) then weight(n) = 0.0_r8 else weight(n) = dom%data%rAttr(ka,n)*shr_const_rearth*shr_const_rearth endif enddo allocate(maxbuf(kflds),maxbufg(kflds)) maxbuf = 0.0_r8 do n = 1,npts do k = 1,kflds if (AV%rAttr(k,n) > 1.01_r8*shr_const_spval .or. & AV%rAttr(k,n) < 0.99_r8*shr_const_spval) then maxbuf(k) = max(maxbuf(k),abs(AV%rAttr(k,n)*weight(n))) endif enddo enddo call shr_mpi_max(maxbuf,maxbufg,mpicom,subname,all=.true.) call shr_mpi_sum(npts,nptsg,mpicom,subname,all=.true.) do k = 1,kflds if (maxbufg(k) < 1000.0*TINY(maxbufg(k)) .or. & maxbufg(k) > HUGE(maxbufg(k))/(2.0_r8*nptsg)) then maxbufg(k) = 0.0_r8 else maxbufg(k) = (1.1_r8) * maxbufg(k) * nptsg endif enddo allocate(isumbuf(kflds),isumbufg(kflds)) isumbuf = 0 ihuge = HUGE(isumbuf) do n = 1,npts do k = 1,kflds if (AV%rAttr(k,n) > 1.01_r8*shr_const_spval .or. & AV%rAttr(k,n) < 0.99_r8*shr_const_spval) then if (abs(maxbufg(k)) > 1000.0_r8 * TINY(maxbufg)) then isumbuf(k) = isumbuf(k) + int((AV%rAttr(k,n)*weight(n)/maxbufg(k))*ihuge,i8) endif endif enddo enddo call shr_mpi_sum(isumbuf,isumbufg,mpicom,subname) do k = 1,kflds sumbufg(k) = isumbufg(k)*maxbufg(k)/ihuge enddo deallocate(weight) deallocate(maxbuf,maxbufg) deallocate(isumbuf,isumbufg) #if (1 == 0) ! OLD VERSION call mct_aVect_init(AV1,rList='varf1',lsize=ns) AV1%rAttr(1,1:ns) = dom%data%rAttr(km,1:ns) ! mask = AVr1 call mct_aVect_gather(AV1,AVr1,gsmap,0,mpicom,rcode) AV1%rAttr(1,1:ns) = dom%data%rAttr(ka,1:ns) ! area = AVr2 call mct_aVect_gather(AV1,AVr2,gsmap,0,mpicom,rcode) ! --- compute weight on root pe if (iam == 0) then npts = mct_aVect_lsize(AVr1) allocate(weight(npts)) weight(:) = 1.0_r8 do n = 1,npts if (AVr1%rAttr(1,n) <= 1.0e-06_R8) then weight(n) = 0.0_r8 else weight(n) = AVr2%rAttr(1,n)*shr_const_rearth*shr_const_rearth endif enddo ! write(logunit,*) trim(subname),'tcx1 ',ns,npts,km,ka,kflds,minval(AVr2%rAttr),maxval(AVr2%rAttr) ! write(logunit,*) trim(subname),'tcx2 ',size(AVr1%rAttr),size(AVr2%rAttr),minval(AVr1%rAttr),maxval(AVr1%rAttr) endif ! --- gather and compute stats one field at a time (to minimize memory) do k = 1,kflds AV1%rAttr(1,1:ns) = AV%rAttr(k,1:ns) ! fld k = AVr2 call mct_aVect_gather(AV1,AVr2,gsmap,0,mpicom,rcode) if (iam == 0) then npts = mct_aVect_lsize(AVr2) ! write(logunit,*) trim(subname),'tcx3 ',ns,npts,k,size(AVr2%rAttr),minval(AVr2%rAttr),maxval(AVr2%rAttr) ! write(logunit,*) trim(subname),'tcx4 ',size(weight),minval(weight),maxval(weight) do n = 1,npts if (AVr2%rAttr(1,n) > 1.01_r8*shr_const_spval .or. & AVr2%rAttr(1,n) < 0.99_r8*shr_const_spval) then sumbuf(k) = sumbuf(k) + AVr2%rAttr(1,n)*weight(n) endif enddo endif enddo ! --- local copy, relevant only on root pe sumbufg = sumbuf call mct_avect_clean(AV1) if (iam == 0) then call mct_aVect_clean(AVr1) call mct_aVect_clean(AVr2) endif #endif else npts = mct_aVect_lsize(AV) allocate(weight(npts)) weight(:) = 1.0_r8 do n = 1,npts if (dom%data%rAttr(km,n) <= 1.0e-06_R8) then weight(n) = 0.0_r8 else weight(n) = dom%data%rAttr(ka,n)*shr_const_rearth*shr_const_rearth endif enddo do n = 1,npts do k = 1,kflds if (AV%rAttr(k,n) > 1.01_r8*shr_const_spval .or. & AV%rAttr(k,n) < 0.99_r8*shr_const_spval) then sumbuf(k) = sumbuf(k) + AV%rAttr(k,n)*weight(n) endif enddo enddo !--- global reduction --- call shr_mpi_sum(sumbuf,sumbufg,mpicom,subname) deallocate(weight) endif if (iam == 0) then ! write(logunit,*) 'sdAV: *** writing ',trim(lcomment),': k fld min/max/sum ***' do k = 1,kflds call mct_aVect_getRList(mstring,k,AV) itemc = mct_string_toChar(mstring) call mct_string_clean(mstring) if (len_trim(lcomment) > 0) then write(logunit,100) 'xxx','sorr',k,sumbufg(k),trim(lcomment),trim(itemc) else write(logunit,101) 'xxx','sorr',k,sumbufg(k),trim(itemc) endif enddo call shr_sys_flush(logunit) endif deallocate(sumbuf,sumbufg) 100 format('comm_diag ',a3,1x,a4,1x,i3,es26.19,1x,a,1x,a) 101 format('comm_diag ',a3,1x,a4,1x,i3,es26.19,1x,a) end subroutine seq_diag_avect_mct !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: seq_diag_avdiff_mct - print global budget diagnostics ! ! !DESCRIPTION: ! Print global diagnostics for AV/ID. ! ! !REVISION HISTORY: ! ! !INTERFACE: ------------------------------------------------------------------ SUBROUTINE seq_diag_avdiff_mct(AV1,AV2,ID,comment),1 implicit none ! !INPUT/OUTPUT PARAMETERS: type(mct_aVect) , intent(in) :: AV1 type(mct_aVect) , intent(in) :: AV2 integer , intent(in) :: ID character(len=*), intent(in), optional :: comment !EOP !--- local --- integer(in) :: n,k,n1,k1,n2,k2 ! counters integer(in) :: iam ! pe number integer(in) :: cnt ! counter real(r8) :: adiff,rdiff ! diff values type(mct_string) :: mstring ! mct char type character(len=64):: lcomment ! should be long enough !----- formats ----- character(*),parameter :: subName = '(seq_diag_avdiff_mct) ' character(*),parameter :: F00 = "('(seq_diag_avdiff_mct) ',4a)" !------------------------------------------------------------------------------- ! print instantaneous budget data !------------------------------------------------------------------------------- call seq_comm_setptrs(ID,iam=iam) lcomment = '' if (present(comment)) then lcomment=trim(comment) endif n1 = mct_aVect_lsize(AV1) k1 = mct_aVect_nRattr(AV1) n2 = mct_aVect_lsize(AV2) k2 = mct_aVect_nRattr(AV2) if (n1 /= n2 .or. k1 /= k2) then write(s_logunit,*) subname,trim(lcomment),' AV sizes different ',n1,n2,k1,k2 return endif do k = 1,k1 cnt = 0 adiff = 0. rdiff = 0. do n = 1,n1 if (AV1%rAttr(k,n) /= AV2%rAttr(k,n)) then cnt = cnt + 1 adiff = max(adiff, abs(AV1%rAttr(k,n)-AV2%rAttr(k,n))) rdiff = max(rdiff, abs(AV1%rAttr(k,n)-AV2%rAttr(k,n))/(abs(AV1%rAttr(k,n))+abs(AV2%rAttr(k,n)))) endif enddo if (cnt > 0) then call mct_aVect_getRList(mstring,k,AV1) write(s_logunit,*) subname,trim(lcomment),' AVs fld k diff ', & iam,mct_string_toChar(mstring),cnt,adiff,rdiff, & minval(AV1%rAttr(k,:)),minval(AV1%rAttr(k,:)), & maxval(AV1%rAttr(k,:)),maxval(AV2%rAttr(k,:)) call mct_string_clean(mstring) endif enddo end subroutine seq_diag_avdiff_mct !=============================================================================== end module seq_diag_mct