diff --git a/physics/GFS_surface_loop_control.F90 b/physics/GFS_surface_loop_control.F90 index 82c55c4ad..b16f04805 100644 --- a/physics/GFS_surface_loop_control.F90 +++ b/physics/GFS_surface_loop_control.F90 @@ -69,11 +69,9 @@ end subroutine GFS_surface_loop_control_part2_finalize !> \brief Brief description of the subroutine !! -#if 0 !! \section arg_table_GFS_surface_loop_control_part2_run Arguments !! \htmlinclude GFS_surface_loop_control_part2_run.html !! -#endif !! \section general General Algorithm !! \section detailed Detailed Algorithm !! @{ diff --git a/physics/module_mp_thompson.F90 b/physics/module_mp_thompson.F90 index dfe31f375..2628d33f4 100644 --- a/physics/module_mp_thompson.F90 +++ b/physics/module_mp_thompson.F90 @@ -63,7 +63,7 @@ MODULE module_mp_thompson USE module_mp_radar -#if !defined(SION) && defined(MPI) +#ifdef MPI use mpi #endif @@ -421,8 +421,7 @@ MODULE module_mp_thompson !..MPI communicator INTEGER:: mpi_communicator -!..If SIONlib isn't used, write Thompson tables with master MPI task -!.. after computing them in thompson_init +!..Write tables with master MPI task after computing them in thompson_init LOGICAL:: thompson_table_writer !+---+ @@ -453,12 +452,7 @@ SUBROUTINE thompson_init(is_aerosol_aware_in, & INTEGER:: i, j, k, l, m, n LOGICAL:: micro_init real :: stime, etime -#ifdef SION - INTEGER :: ierr - LOGICAL :: precomputed_tables -#else LOGICAL, PARAMETER :: precomputed_tables = .FALSE. -#endif ! Set module variable is_aerosol_aware is_aerosol_aware = is_aerosol_aware_in @@ -766,18 +760,7 @@ SUBROUTINE thompson_init(is_aerosol_aware_in, & ! Assign mpicomm to module variable mpi_communicator = mpicomm -#ifdef SION - call cpu_time(stime) - call readwrite_tables(thomp_table_file, "read", mpicomm, mpirank, mpiroot, ierr) - call cpu_time(etime) - if (ierr==0) then - precomputed_tables = .true. - if (mpirank==mpiroot) print '("Reading and broadcasting precomputed Thompson tables took ",f10.3," seconds.")', etime-stime - else - precomputed_tables = .false. - if (mpirank==mpiroot) write(0,*) "An error occurred reading Thompson tables from disk, recalculate" - end if -#endif + ! Standard tables are only written by master MPI task; ! (physics init cannot be called by multiple threads, ! hence no need to test for a specific thread number) @@ -899,9 +882,6 @@ SUBROUTINE thompson_init(is_aerosol_aware_in, & !> - Call table_ccnact() to read a static file containing CCN activation of aerosols. The !! data were created from a parcel model by Feingold & Heymsfield with !! further changes by Eidhammer and Kriedenweis - ! This computation is cheap compared to the others below, and - ! doing it always ensures that the correct data is in the SIONlib - ! file containing the precomputed tables *DH if (mpirank==mpiroot) write(0,*) ' calling table_ccnAct routine' call table_ccnAct(errmsg,errflg) if (.not. errflg==0) return @@ -971,17 +951,6 @@ SUBROUTINE thompson_init(is_aerosol_aware_in, & call cpu_time(etime) if (mpirank==mpiroot) print '("Calculating Thompson tables part 2 took ",f10.3," seconds.")', etime-stime -#ifdef SION - call cpu_time(stime) - call readwrite_tables(thomp_table_file, "write", mpicomm, mpirank, mpiroot, ierr) - if (ierr/=0) then - write(0,*) "An error occurred writing Thompson tables to disk" - stop 1 - end if - call cpu_time(etime) - if (mpirank==mpiroot) print '("Writing Thompson tables took ",f10.3," seconds.")', etime-stime -#endif - end if precomputed_tables_2 endif if_not_iiwarm @@ -1018,7 +987,8 @@ SUBROUTINE mp_gt_driver(qv, qc, qr, qi, qs, qg, ni, nr, nc, & ids,ide, jds,jde, kds,kde, & ! domain dims ims,ime, jms,jme, kms,kme, & ! memory dims its,ite, jts,jte, kts,kte, & ! tile dims - errmsg, errflg, reset) + reset_dBZ, istep, nsteps, & + errmsg, errflg) implicit none @@ -1058,9 +1028,11 @@ SUBROUTINE mp_gt_driver(qv, qc, qr, qi, qs, qg, ni, nr, nc, & refl_10cm REAL, DIMENSION(ims:ime, kms:kme, jms:jme), OPTIONAL, INTENT(INOUT):: & vt_dbz_wt - LOGICAL, OPTIONAL, INTENT(IN) :: first_time_step + LOGICAL, INTENT(IN) :: first_time_step REAL, INTENT(IN):: dt_in - LOGICAL, INTENT (IN) :: reset + ! To support subcycling: current step and maximum number of steps + INTEGER, INTENT (IN) :: istep, nsteps + LOGICAL, INTENT (IN) :: reset_dBZ !..Local variables REAL, DIMENSION(kts:kte):: & @@ -1093,63 +1065,66 @@ SUBROUTINE mp_gt_driver(qv, qc, qr, qi, qs, qg, ni, nr, nc, & if (present(errmsg)) errmsg = '' if (present(errflg)) errflg = 0 - ! DH* 2020-06-05: The stochastic perturbations code was retrofitted - ! from a newer version of the Thompson MP scheme, but it has not been - ! tested yet. - if (rand_perturb_on .ne. 0) then - errmsg = 'Logic error in mp_gt_driver: the stochastic perturbations code ' // & - 'has not been tested yet with this version of the Thompson scheme' - errflg = 1 - return - end if - ! Activate this code when removing the guard above - !if (rand_perturb_on .ne. 0 .and. .not. present(rand_pert)) then - ! errmsg = 'Logic error in mp_gt_driver: random perturbations are on, ' // & - ! 'but optional argument rand_pert is not present' - ! errflg = 1 - ! return - !end if - ! *DH 2020-06-05 - - if ( (present(tt) .and. (present(th) .or. present(pii))) .or. & - (.not.present(tt) .and. .not.(present(th) .and. present(pii))) ) then - if (present(errmsg)) then - write(errmsg, '(a)') 'Logic error in mp_gt_driver: provide either tt or th+pii' - else - write(*,'(a)') 'Logic error in mp_gt_driver: provide either tt or th+pii' - end if - if (present(errflg)) then - errflg = 1 - return - else - stop + ! No need to test for every subcycling step + test_only_once: if (first_time_step .and. istep==1) then + ! DH* 2020-06-05: The stochastic perturbations code was retrofitted + ! from a newer version of the Thompson MP scheme, but it has not been + ! tested yet. + if (rand_perturb_on .ne. 0) then + errmsg = 'Logic error in mp_gt_driver: the stochastic perturbations code ' // & + 'has not been tested yet with this version of the Thompson scheme' + errflg = 1 + return end if - end if - - if (is_aerosol_aware .and. (.not.present(nc) .or. & - .not.present(nwfa) .or. & - .not.present(nifa) .or. & - .not.present(nwfa2d) .or. & - .not.present(nifa2d) )) then - if (present(errmsg)) then - write(errmsg, '(*(a))') 'Logic error in mp_gt_driver: provide nc, nwfa, nifa, nwfa2d', & - ' and nifa2d for aerosol-aware version of Thompson microphysics' - else - write(*, '(*(a))') 'Logic error in mp_gt_driver: provide nc, nwfa, nifa, nwfa2d', & - ' and nifa2d for aerosol-aware version of Thompson microphysics' + ! Activate this code when removing the guard above + !if (rand_perturb_on .ne. 0 .and. .not. present(rand_pert)) then + ! errmsg = 'Logic error in mp_gt_driver: random perturbations are on, ' // & + ! 'but optional argument rand_pert is not present' + ! errflg = 1 + ! return + !end if + ! *DH 2020-06-05 + + if ( (present(tt) .and. (present(th) .or. present(pii))) .or. & + (.not.present(tt) .and. .not.(present(th) .and. present(pii))) ) then + if (present(errmsg)) then + write(errmsg, '(a)') 'Logic error in mp_gt_driver: provide either tt or th+pii' + else + write(*,'(a)') 'Logic error in mp_gt_driver: provide either tt or th+pii' + end if + if (present(errflg)) then + errflg = 1 + return + else + stop + end if end if - if (present(errflg)) then - errflg = 1 - return - else - stop + + if (is_aerosol_aware .and. (.not.present(nc) .or. & + .not.present(nwfa) .or. & + .not.present(nifa) .or. & + .not.present(nwfa2d) .or. & + .not.present(nifa2d) )) then + if (present(errmsg)) then + write(errmsg, '(*(a))') 'Logic error in mp_gt_driver: provide nc, nwfa, nifa, nwfa2d', & + ' and nifa2d for aerosol-aware version of Thompson microphysics' + else + write(*, '(*(a))') 'Logic error in mp_gt_driver: provide nc, nwfa, nifa, nwfa2d', & + ' and nifa2d for aerosol-aware version of Thompson microphysics' + end if + if (present(errflg)) then + errflg = 1 + return + else + stop + end if + else if (.not.is_aerosol_aware .and. (present(nwfa) .or. & + present(nifa) .or. & + present(nwfa2d) .or. & + present(nifa2d) )) then + write(*,*) 'WARNING, nc/nwfa/nifa/nwfa2d/nifa2d present but is_aerosol_aware is FALSE' end if - else if (.not.is_aerosol_aware .and. (present(nwfa) .or. & - present(nifa) .or. & - present(nwfa2d) .or. & - present(nifa2d) )) then - write(*,*) 'WARNING, nc/nwfa/nifa/nwfa2d/nifa2d present but is_aerosol_aware is FALSE' - end if + end if test_only_once !+---+ i_start = its @@ -1421,49 +1396,54 @@ SUBROUTINE mp_gt_driver(qv, qc, qr, qi, qs, qg, ni, nr, nc, & endif enddo + ! Diagnostic calculations only for last step + ! if Thompson MP is called multiple times + last_step_only: IF (istep == nsteps) THEN + !> - Call calc_refl10cm() - IF ( PRESENT (diagflag) ) THEN - if (diagflag .and. do_radar_ref == 1) then + diagflag_present: IF ( PRESENT (diagflag) ) THEN + if (diagflag .and. do_radar_ref == 1) then ! - ! Only set melti to true at the output times - if (reset) then + ! Only set melti to true at the output times + if (reset_dBZ) then melti=.true. - else + else melti=.false. - endif + endif ! - if (present(vt_dbz_wt) .and. present(first_time_step)) then - call calc_refl10cm (qv1d, qc1d, qr1d, nr1d, qs1d, qg1d, & - t1d, p1d, dBZ, rand1, kts, kte, i, j, & - melti, vt_dbz_wt(i,:,j), & - first_time_step) - else - call calc_refl10cm (qv1d, qc1d, qr1d, nr1d, qs1d, qg1d, & - t1d, p1d, dBZ, rand1, kts, kte, i, j, & - melti) - end if - do k = kts, kte - refl_10cm(i,k,j) = MAX(-35., dBZ(k)) - enddo - endif - ENDIF + !if (present(vt_dbz_wt) .and. present(first_time_step)) then + call calc_refl10cm (qv1d, qc1d, qr1d, nr1d, qs1d, qg1d, & + t1d, p1d, dBZ, rand1, kts, kte, i, j, & + melti, vt_dbz_wt(i,:,j), & + first_time_step) + !else + ! call calc_refl10cm (qv1d, qc1d, qr1d, nr1d, qs1d, qg1d, & + ! t1d, p1d, dBZ, rand1, kts, kte, i, j, & + ! melti) + !end if + do k = kts, kte + refl_10cm(i,k,j) = MAX(-35., dBZ(k)) + enddo + endif + ENDIF diagflag_present - IF (has_reqc.ne.0 .and. has_reqi.ne.0 .and. has_reqs.ne.0) THEN - do k = kts, kte - re_qc1d(k) = re_qc_min - re_qi1d(k) = re_qi_min - re_qs1d(k) = re_qs_min - enddo + IF (has_reqc.ne.0 .and. has_reqi.ne.0 .and. has_reqs.ne.0) THEN + do k = kts, kte + re_qc1d(k) = re_qc_min + re_qi1d(k) = re_qi_min + re_qs1d(k) = re_qs_min + enddo !> - Call calc_effectrad() - call calc_effectRad (t1d, p1d, qv1d, qc1d, nc1d, qi1d, ni1d, qs1d, & - re_qc1d, re_qi1d, re_qs1d, kts, kte) - do k = kts, kte - re_cloud(i,k,j) = MAX(re_qc_min, MIN(re_qc1d(k), re_qc_max)) - re_ice(i,k,j) = MAX(re_qi_min, MIN(re_qi1d(k), re_qi_max)) - re_snow(i,k,j) = MAX(re_qs_min, MIN(re_qs1d(k), re_qs_max)) - enddo - ENDIF + call calc_effectRad (t1d, p1d, qv1d, qc1d, nc1d, qi1d, ni1d, qs1d, & + re_qc1d, re_qi1d, re_qs1d, kts, kte) + do k = kts, kte + re_cloud(i,k,j) = MAX(re_qc_min, MIN(re_qc1d(k), re_qc_max)) + re_ice(i,k,j) = MAX(re_qi_min, MIN(re_qi1d(k), re_qi_max)) + re_snow(i,k,j) = MAX(re_qs_min, MIN(re_qs1d(k), re_qs_max)) + enddo + ENDIF + ENDIF last_step_only enddo i_loop enddo j_loop @@ -3853,10 +3833,10 @@ subroutine qr_acr_qg ENDIF IF (.NOT. good .EQ. 1 ) THEN -#ifndef SION - if (thompson_table_writer) write_thompson_tables = .true. -#endif - if (thompson_table_writer) write(0,*) "ThompMP: computing qr_acr_qg" + if (thompson_table_writer) then + write_thompson_tables = .true. + write(0,*) "ThompMP: computing qr_acr_qg" + endif do n2 = 1, nbr ! vr(n2) = av_r*Dr(n2)**bv_r * DEXP(-fv_r*Dr(n2)) vr(n2) = -0.1021 + 4.932E3*Dr(n2) - 0.9551E6*Dr(n2)*Dr(n2) & @@ -4035,10 +4015,10 @@ subroutine qr_acr_qs ENDIF IF (.NOT. good .EQ. 1 ) THEN -#ifndef SION - if (thompson_table_writer) write_thompson_tables = .true. -#endif - if (thompson_table_writer) write(0,*) "ThompMP: computing qr_acr_qs" + if (thompson_table_writer) then + write_thompson_tables = .true. + write(0,*) "ThompMP: computing qr_acr_qs" + endif do n2 = 1, nbr ! vr(n2) = av_r*Dr(n2)**bv_r * DEXP(-fv_r*Dr(n2)) vr(n2) = -0.1021 + 4.932E3*Dr(n2) - 0.9551E6*Dr(n2)*Dr(n2) & @@ -4290,10 +4270,10 @@ subroutine freezeH2O(threads) ENDIF IF (.NOT. good .EQ. 1 ) THEN -#ifndef SION - if (thompson_table_writer) write_thompson_tables = .true. -#endif - if (thompson_table_writer) write(0,*) "ThompMP: computing freezeH2O" + if (thompson_table_writer) then + write_thompson_tables = .true. + write(0,*) "ThompMP: computing freezeH2O" + endif orho_w = 1./rho_w @@ -5613,300 +5593,6 @@ subroutine calc_refl10cm (qv1d, qc1d, qr1d, nr1d, qs1d, qg1d, & end subroutine calc_refl10cm ! - -#ifdef SION -!>\ingroup aathompson - subroutine readwrite_tables(filename, mode, mpicomm, mpirank, mpiroot, ierr) - -#ifdef MPI - use mpi -#endif - use sion_f90 - - implicit none - - ! Interface variables - character(len=*), intent(in) :: filename - character(len=*), intent(in) :: mode - integer, intent(in) :: mpicomm - integer, intent(in) :: mpirank - integer, intent(in) :: mpiroot - integer, intent(out) :: ierr - -#ifdef MPI - ! MPI variables - integer :: mpierr -#endif - - ! SIONlib variables - integer :: SIONLIB_fsblksize - integer :: SIONLIB_numfiles - character*2 :: SIONLIB_filemode - ! - integer :: nprocs - integer, dimension(:), allocatable :: procs - integer*8, dimension(:), allocatable :: chunksizes - ! - integer*8 :: brw - integer :: sid - integer :: f_endian, s_endian - logical :: exists - integer*8 :: tables_size - real*8 :: checksum - - integer :: i - - continue - - ierr = 0 - - ! Test if SIONlib file containing pre-computed tables exists - inquire(file=trim(filename), exist=exists) - if (trim(mode)=="read") then - SIONLIB_filemode = "rb" - if (.not.exists) then - if (mpirank==mpiroot) write(0,*) "SIONlib file " // trim(filename) // & - " with precomputed Thompson MP tables not found" - ierr = 1 - return - end if - else if (trim(mode)=="write") then - SIONLIB_filemode = "wb" - SIONLIB_numfiles = 1 - if (exists) then - if (mpirank==mpiroot) write(0,*) "SIONlib file " // trim(filename) // & - " with precomputed Thompson MP tables already exists" - ierr = 1 - return - end if - end if - -#ifdef MPI - ! To avoid that MPI master task creates the file before - ! other tasks pass the inquire test above - call MPI_BARRIER(mpicomm, mpierr) -#endif - - mpi_master_io_only: if (mpirank==mpiroot) then - tables_size = sizeof(tcg_racg) - tables_size = tables_size + sizeof(tmr_racg) - tables_size = tables_size + sizeof(tcr_gacr) - tables_size = tables_size + sizeof(tmg_gacr) - tables_size = tables_size + sizeof(tnr_racg) - tables_size = tables_size + sizeof(tnr_gacr) - tables_size = tables_size + sizeof(tcs_racs1) - tables_size = tables_size + sizeof(tmr_racs1) - tables_size = tables_size + sizeof(tcs_racs2) - tables_size = tables_size + sizeof(tmr_racs2) - tables_size = tables_size + sizeof(tcr_sacr1) - tables_size = tables_size + sizeof(tms_sacr1) - tables_size = tables_size + sizeof(tcr_sacr2) - tables_size = tables_size + sizeof(tms_sacr2) - tables_size = tables_size + sizeof(tnr_racs1) - tables_size = tables_size + sizeof(tnr_racs2) - tables_size = tables_size + sizeof(tnr_sacr1) - tables_size = tables_size + sizeof(tnr_sacr2) - tables_size = tables_size + sizeof(tpi_qcfz) - tables_size = tables_size + sizeof(tni_qcfz) - tables_size = tables_size + sizeof(tpi_qrfz) - tables_size = tables_size + sizeof(tpg_qrfz) - tables_size = tables_size + sizeof(tni_qrfz) - tables_size = tables_size + sizeof(tnr_qrfz) - tables_size = tables_size + sizeof(tps_iaus) - tables_size = tables_size + sizeof(tni_iaus) - tables_size = tables_size + sizeof(tpi_ide) - tables_size = tables_size + sizeof(t_Efrw) - tables_size = tables_size + sizeof(t_Efsw) - tables_size = tables_size + sizeof(tnr_rev) - tables_size = tables_size + sizeof(tpc_wev) - tables_size = tables_size + sizeof(tnc_wev) - tables_size = tables_size + sizeof(tnccn_act) - - ! Autodetect SIONlib filesystem block size - SIONLIB_fsblksize = -1 - - nprocs = 1 - allocate (procs(1:nprocs)) - allocate (chunksizes(1:nprocs)) - do i=1,nprocs - procs(i) = i - chunksizes(i) = sizeof(checksum) + tables_size - end do - - write(0,'(a)') "Opening file " // trim(filename) - call fsion_open(trim(filename), SIONLIB_filemode, nprocs, SIONLIB_numfiles, chunksizes(1), SIONLIB_fsblksize, procs(1), sid) - if (sid<0) write(0,'(a)') "Error opening " // trim(filename) // " in " // trim(mode) // " mode" - - call fsion_seek(sid, mpirank, SION_CURRENT_BLK, SION_CURRENT_POS, ierr) - ! fsion_seek returns ierr=1 if cursor could be positioned as requested and 0 otherwise - if (ierr==1) ierr=0 - - if (trim(mode)=="read") then - ! Check that file endianness is identical to system endianness - call fsion_get_file_endianness(sid, f_endian) - call fsion_get_endianess(s_endian) - if (f_endian .ne. s_endian) then - write(0,'(a)') "Error, endianness of SIONlib file " // trim(filename) // " differs " // & - "from filesystem endianness; please delete file and recalculate tables!" - ierr = 1 - end if - if (ierr==0) then - ! Read checksum - call fsion_read(checksum, int(kind(checksum),8), int(1,8), sid, brw) - ! Read arrays tcg_racg through tnccn_act - call fsion_read(tcg_racg(1,1,1,1), int(kind(tcg_racg(1,1,1,1)),8), int(size(tcg_racg),8), sid, brw) - call fsion_read(tmr_racg(1,1,1,1), int(kind(tmr_racg(1,1,1,1)),8), int(size(tmr_racg),8), sid, brw) - call fsion_read(tcr_gacr(1,1,1,1), int(kind(tcr_gacr(1,1,1,1)),8), int(size(tcr_gacr),8), sid, brw) - call fsion_read(tmg_gacr(1,1,1,1), int(kind(tmg_gacr(1,1,1,1)),8), int(size(tmg_gacr),8), sid, brw) - call fsion_read(tnr_racg(1,1,1,1), int(kind(tnr_racg(1,1,1,1)),8), int(size(tnr_racg),8), sid, brw) - call fsion_read(tnr_gacr(1,1,1,1), int(kind(tnr_gacr(1,1,1,1)),8), int(size(tnr_gacr),8), sid, brw) - call fsion_read(tcs_racs1(1,1,1,1), int(kind(tcs_racs1(1,1,1,1)),8), int(size(tcs_racs1),8), sid, brw) - call fsion_read(tmr_racs1(1,1,1,1), int(kind(tmr_racs1(1,1,1,1)),8), int(size(tmr_racs1),8), sid, brw) - call fsion_read(tcs_racs2(1,1,1,1), int(kind(tcs_racs2(1,1,1,1)),8), int(size(tcs_racs2),8), sid, brw) - call fsion_read(tmr_racs2(1,1,1,1), int(kind(tmr_racs2(1,1,1,1)),8), int(size(tmr_racs2),8), sid, brw) - call fsion_read(tcr_sacr1(1,1,1,1), int(kind(tcr_sacr1(1,1,1,1)),8), int(size(tcr_sacr1),8), sid, brw) - call fsion_read(tms_sacr1(1,1,1,1), int(kind(tms_sacr1(1,1,1,1)),8), int(size(tms_sacr1),8), sid, brw) - call fsion_read(tcr_sacr2(1,1,1,1), int(kind(tcr_sacr2(1,1,1,1)),8), int(size(tcr_sacr2),8), sid, brw) - call fsion_read(tms_sacr2(1,1,1,1), int(kind(tms_sacr2(1,1,1,1)),8), int(size(tms_sacr2),8), sid, brw) - call fsion_read(tnr_racs1(1,1,1,1), int(kind(tnr_racs1(1,1,1,1)),8), int(size(tnr_racs1),8), sid, brw) - call fsion_read(tnr_racs2(1,1,1,1), int(kind(tnr_racs2(1,1,1,1)),8), int(size(tnr_racs2),8), sid, brw) - call fsion_read(tnr_sacr1(1,1,1,1), int(kind(tnr_sacr1(1,1,1,1)),8), int(size(tnr_sacr1),8), sid, brw) - call fsion_read(tnr_sacr2(1,1,1,1), int(kind(tnr_sacr2(1,1,1,1)),8), int(size(tnr_sacr2),8), sid, brw) - call fsion_read(tpi_qcfz(1,1,1,1), int(kind(tpi_qcfz(1,1,1,1)),8), int(size(tpi_qcfz),8), sid, brw) - call fsion_read(tni_qcfz(1,1,1,1), int(kind(tni_qcfz(1,1,1,1)),8), int(size(tni_qcfz),8), sid, brw) - call fsion_read(tpi_qrfz(1,1,1,1), int(kind(tpi_qrfz(1,1,1,1)),8), int(size(tpi_qrfz),8), sid, brw) - call fsion_read(tpg_qrfz(1,1,1,1), int(kind(tpg_qrfz(1,1,1,1)),8), int(size(tpg_qrfz),8), sid, brw) - call fsion_read(tni_qrfz(1,1,1,1), int(kind(tni_qrfz(1,1,1,1)),8), int(size(tni_qrfz),8), sid, brw) - call fsion_read(tnr_qrfz(1,1,1,1), int(kind(tnr_qrfz(1,1,1,1)),8), int(size(tnr_qrfz),8), sid, brw) - call fsion_read(tps_iaus(1,1), int(kind(tps_iaus(1,1)),8), int(size(tps_iaus),8), sid, brw) - call fsion_read(tni_iaus(1,1), int(kind(tni_iaus(1,1)),8), int(size(tni_iaus),8), sid, brw) - call fsion_read(tpi_ide(1,1), int(kind(tpi_ide(1,1)),8), int(size(tpi_ide),8), sid, brw) - call fsion_read(t_Efrw(1,1), int(kind(t_Efrw(1,1)),8), int(size(t_Efrw),8), sid, brw) - call fsion_read(t_Efsw(1,1), int(kind(t_Efsw(1,1)),8), int(size(t_Efsw),8), sid, brw) - call fsion_read(tnr_rev(1,1,1), int(kind(tnr_rev(1,1,1)),8), int(size(tnr_rev),8), sid, brw) - call fsion_read(tpc_wev(1,1,1), int(kind(tpc_wev(1,1,1)),8), int(size(tpc_wev),8), sid, brw) - call fsion_read(tnc_wev(1,1,1), int(kind(tnc_wev (1,1,1)),8), int(size(tnc_wev),8), sid, brw) - call fsion_read(tnccn_act(1,1,1,1,1), int(kind(tnccn_act(1,1,1,1,1)),8), int(size(tnccn_act),8), sid, brw) - else - ! Wrong endianness (ierr/=0) will force checksum match to fail - checksum = -1 - end if - else if (trim(mode)=="write") then - ! Calculate and write checksum - checksum = calculate_checksum() - call fsion_write(checksum, int(kind(checksum),8), int(1,8), sid, brw) - ! Write arrays tcg_racg through tnccn_act - call fsion_write(tcg_racg(1,1,1,1), int(kind(tcg_racg(1,1,1,1)),8), int(size(tcg_racg),8), sid, brw) - call fsion_write(tmr_racg(1,1,1,1), int(kind(tmr_racg(1,1,1,1)),8), int(size(tmr_racg),8), sid, brw) - call fsion_write(tcr_gacr(1,1,1,1), int(kind(tcr_gacr(1,1,1,1)),8), int(size(tcr_gacr),8), sid, brw) - call fsion_write(tmg_gacr(1,1,1,1), int(kind(tmg_gacr(1,1,1,1)),8), int(size(tmg_gacr),8), sid, brw) - call fsion_write(tnr_racg(1,1,1,1), int(kind(tnr_racg(1,1,1,1)),8), int(size(tnr_racg),8), sid, brw) - call fsion_write(tnr_gacr(1,1,1,1), int(kind(tnr_gacr(1,1,1,1)),8), int(size(tnr_gacr),8), sid, brw) - call fsion_write(tcs_racs1(1,1,1,1), int(kind(tcs_racs1(1,1,1,1)),8), int(size(tcs_racs1),8), sid, brw) - call fsion_write(tmr_racs1(1,1,1,1), int(kind(tmr_racs1(1,1,1,1)),8), int(size(tmr_racs1),8), sid, brw) - call fsion_write(tcs_racs2(1,1,1,1), int(kind(tcs_racs2(1,1,1,1)),8), int(size(tcs_racs2),8), sid, brw) - call fsion_write(tmr_racs2(1,1,1,1), int(kind(tmr_racs2(1,1,1,1)),8), int(size(tmr_racs2),8), sid, brw) - call fsion_write(tcr_sacr1(1,1,1,1), int(kind(tcr_sacr1(1,1,1,1)),8), int(size(tcr_sacr1),8), sid, brw) - call fsion_write(tms_sacr1(1,1,1,1), int(kind(tms_sacr1(1,1,1,1)),8), int(size(tms_sacr1),8), sid, brw) - call fsion_write(tcr_sacr2(1,1,1,1), int(kind(tcr_sacr2(1,1,1,1)),8), int(size(tcr_sacr2),8), sid, brw) - call fsion_write(tms_sacr2(1,1,1,1), int(kind(tms_sacr2(1,1,1,1)),8), int(size(tms_sacr2),8), sid, brw) - call fsion_write(tnr_racs1(1,1,1,1), int(kind(tnr_racs1(1,1,1,1)),8), int(size(tnr_racs1),8), sid, brw) - call fsion_write(tnr_racs2(1,1,1,1), int(kind(tnr_racs2(1,1,1,1)),8), int(size(tnr_racs2),8), sid, brw) - call fsion_write(tnr_sacr1(1,1,1,1), int(kind(tnr_sacr1(1,1,1,1)),8), int(size(tnr_sacr1),8), sid, brw) - call fsion_write(tnr_sacr2(1,1,1,1), int(kind(tnr_sacr2(1,1,1,1)),8), int(size(tnr_sacr2),8), sid, brw) - call fsion_write(tpi_qcfz(1,1,1,1), int(kind(tpi_qcfz(1,1,1,1)),8), int(size(tpi_qcfz),8), sid, brw) - call fsion_write(tni_qcfz(1,1,1,1), int(kind(tni_qcfz(1,1,1,1)),8), int(size(tni_qcfz),8), sid, brw) - call fsion_write(tpi_qrfz(1,1,1,1), int(kind(tpi_qrfz(1,1,1,1)),8), int(size(tpi_qrfz),8), sid, brw) - call fsion_write(tpg_qrfz(1,1,1,1), int(kind(tpg_qrfz(1,1,1,1)),8), int(size(tpg_qrfz),8), sid, brw) - call fsion_write(tni_qrfz(1,1,1,1), int(kind(tni_qrfz(1,1,1,1)),8), int(size(tni_qrfz),8), sid, brw) - call fsion_write(tnr_qrfz(1,1,1,1), int(kind(tnr_qrfz(1,1,1,1)),8), int(size(tnr_qrfz),8), sid, brw) - call fsion_write(tps_iaus(1,1), int(kind(tps_iaus(1,1)),8), int(size(tps_iaus),8), sid, brw) - call fsion_write(tni_iaus(1,1), int(kind(tni_iaus(1,1)),8), int(size(tni_iaus),8), sid, brw) - call fsion_write(tpi_ide(1,1), int(kind(tpi_ide(1,1)),8), int(size(tpi_ide),8), sid, brw) - call fsion_write(t_Efrw(1,1), int(kind(t_Efrw(1,1)),8), int(size(t_Efrw),8), sid, brw) - call fsion_write(t_Efsw(1,1), int(kind(t_Efsw(1,1)),8), int(size(t_Efsw),8), sid, brw) - call fsion_write(tnr_rev(1,1,1), int(kind(tnr_rev(1,1,1)),8), int(size(tnr_rev),8), sid, brw) - call fsion_write(tpc_wev(1,1,1), int(kind(tpc_wev(1,1,1)),8), int(size(tpc_wev),8), sid, brw) - call fsion_write(tnc_wev(1,1,1), int(kind(tnc_wev (1,1,1)),8), int(size(tnc_wev),8), sid, brw) - call fsion_write(tnccn_act(1,1,1,1,1), int(kind(tnccn_act(1,1,1,1,1)),8), int(size(tnccn_act),8), sid, brw) - end if - - write(0,'(a)') "Closing file " // trim(filename) - call fsion_close(sid, ierr) - - ierr = 0 - ! Test if checksum matches, this fails if wrong endianness (checksum=-1, see above) - if (trim(mode)=="read" .and. checksum/=calculate_checksum()) then - write(0,'(2(a,e20.9))') "Checksum mismatch, expected", calculate_checksum(), " but got", checksum - call system('rm -f ' // trim(filename)) - ierr = 1 - end if - - deallocate (procs) - deallocate (chunksizes) - - else - - ierr = 0 - - end if mpi_master_io_only - -#ifdef MPI - if (trim(mode)=="read") then - ! After reading the tables, broadcast the information to all MPI tasks. - ! First, broadcast the current error code from MPI master (0 = success) - call MPI_BCAST(ierr, 1, MPI_INTEGER, mpiroot, mpicomm, mpierr) - if (ierr/=0) return - call MPI_BCAST(tcg_racg, size(tcg_racg), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tmr_racg, size(tmr_racg), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tcr_gacr, size(tcr_gacr), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tmg_gacr, size(tmg_gacr), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tnr_racg, size(tnr_racg), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tnr_gacr, size(tnr_gacr), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tcs_racs1, size(tcs_racs1), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tmr_racs1, size(tmr_racs1), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tcs_racs2, size(tcs_racs2), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tmr_racs2, size(tmr_racs2), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tcr_sacr1, size(tcr_sacr1), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tms_sacr1, size(tms_sacr1), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tcr_sacr2, size(tcr_sacr2), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tms_sacr2, size(tms_sacr2), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tnr_racs1, size(tnr_racs1), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tnr_racs2, size(tnr_racs2), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tnr_sacr1, size(tnr_sacr1), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tnr_sacr2, size(tnr_sacr2), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tpi_qcfz, size(tpi_qcfz), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tni_qcfz, size(tni_qcfz), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tpi_qrfz, size(tpi_qrfz), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tpg_qrfz, size(tpg_qrfz), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tni_qrfz, size(tni_qrfz), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tnr_qrfz, size(tnr_qrfz), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tps_iaus, size(tps_iaus), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tni_iaus, size(tni_iaus), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tpi_ide, size(tpi_ide), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(t_Efrw, size(t_Efrw), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(t_Efsw, size(t_Efsw), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tnr_rev, size(tnr_rev), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tpc_wev, size(tpc_wev), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tnc_wev, size(tnc_wev), MPI_DOUBLE_PRECISION, mpiroot, mpicomm, mpierr) - call MPI_BCAST(tnccn_act, size(tnccn_act), MPI_REAL, mpiroot, mpicomm, mpierr) - else if (trim(mode)=="write") then - call MPI_BARRIER(mpicomm, mpierr) - end if -#endif - - return - - contains - - function calculate_checksum() result(checksum) - real*8 :: checksum - checksum = real(tables_size,8)*sum(tcg_racg) - end function calculate_checksum - - end subroutine readwrite_tables -#endif - !+---+-----------------------------------------------------------------+ !+---+-----------------------------------------------------------------+ END MODULE module_mp_thompson diff --git a/physics/mp_thompson.F90 b/physics/mp_thompson.F90 index 1ad4b2d4b..1d235c3e6 100644 --- a/physics/mp_thompson.F90 +++ b/physics/mp_thompson.F90 @@ -99,14 +99,6 @@ subroutine mp_thompson_init(ncol, nlev, con_g, con_rd, con_eps, & if (is_initialized) return - ! DH* temporary - if (mpirank==mpiroot) then - write(0,*) ' ----------------------------------------------------------------------------------------------------------------' - write(0,*) ' --- WARNING --- the CCPP Thompson MP scheme is currently under development, use at your own risk --- WARNING ---' - write(0,*) ' ----------------------------------------------------------------------------------------------------------------' - end if - ! *DH temporary - ! Consistency checks if (imp_physics/=imp_physics_thompson) then write(errmsg,'(*(a))') "Logic error: namelist choice of microphysics is different from Thompson MP" @@ -328,12 +320,13 @@ subroutine mp_thompson_run(ncol, nlev, con_g, con_rd, & spechum, qc, qr, qi, qs, qg, ni, nr, & is_aerosol_aware, nc, nwfa, nifa, & nwfa2d, nifa2d, & - tgrs, prsl, phii, omega, dtp, & + tgrs, prsl, phii, omega, & + dtp, first_time_step, istep, nsteps, & prcp, rain, graupel, ice, snow, sr, & - refl_10cm, reset, do_radar_ref, & + refl_10cm, reset_dBZ, do_radar_ref, & re_cloud, re_ice, re_snow, & mpicomm, mpirank, mpiroot, & - errmsg, errflg) + blkno, errmsg, errflg) implicit none @@ -356,7 +349,7 @@ subroutine mp_thompson_run(ncol, nlev, con_g, con_rd, & real(kind_phys), intent(inout) :: ni(:,:) real(kind_phys), intent(inout) :: nr(:,:) ! Aerosols - logical, intent(in) :: is_aerosol_aware, reset + logical, intent(in) :: is_aerosol_aware, reset_dBZ ! The following arrays are not allocated if is_aerosol_aware is false real(kind_phys), optional, intent(inout) :: nc(:,:) real(kind_phys), optional, intent(inout) :: nwfa(:,:) @@ -369,6 +362,8 @@ subroutine mp_thompson_run(ncol, nlev, con_g, con_rd, & real(kind_phys), intent(in ) :: phii(:,:) real(kind_phys), intent(in ) :: omega(:,:) real(kind_phys), intent(in ) :: dtp + logical, intent(in ) :: first_time_step + integer, intent(in ) :: istep, nsteps ! Precip/rain/snow/graupel fall amounts and fraction of frozen precip real(kind_phys), intent(inout) :: prcp(:) real(kind_phys), intent(inout) :: rain(:) @@ -383,7 +378,8 @@ subroutine mp_thompson_run(ncol, nlev, con_g, con_rd, & real(kind_phys), optional, intent( out) :: re_cloud(:,:) real(kind_phys), optional, intent( out) :: re_ice(:,:) real(kind_phys), optional, intent( out) :: re_snow(:,:) - ! MPI information + ! MPI and block information + integer, intent(in) :: blkno integer, intent(in) :: mpicomm integer, intent(in) :: mpirank integer, intent(in) :: mpiroot @@ -393,6 +389,8 @@ subroutine mp_thompson_run(ncol, nlev, con_g, con_rd, & ! Local variables + ! Reduced time step if subcycling is used + real(kind_phys) :: dtstep ! Air density real(kind_phys) :: rho(1:ncol,1:nlev) !< kg m-3 ! Water vapor mixing ratio (instead of specific humidity) @@ -439,23 +437,39 @@ subroutine mp_thompson_run(ncol, nlev, con_g, con_rd, & return end if - if (is_aerosol_aware .and. .not. (present(nc) .and. & - present(nwfa) .and. & - present(nifa) .and. & - present(nwfa2d) .and. & - present(nifa2d) )) then - write(errmsg,fmt='(*(a))') 'Logic error in mp_thompson_run:', & - ' aerosol-aware microphysics require all of the', & - ' following optional arguments:', & - ' nc, nwfa, nifa, nwfa2d, nifa2d' - errflg = 1 - return + ! Set reduced time step if subcycling is used + if (nsteps>1) then + dtstep = dtp/real(nsteps, kind=kind_phys) + else + dtstep = dtp + end if + if (first_time_step .and. istep==1 .and. mpirank==mpiroot .and. blkno==1) then + write(*,'(a,i0,a,a,f6.2,a)') 'Thompson MP is using ', nsteps, ' substep(s) per time step', & + ' with an effective time step of ', dtstep, ' seconds' + end if + + if (first_time_step .and. istep==1) then + if (is_aerosol_aware .and. .not. (present(nc) .and. & + present(nwfa) .and. & + present(nifa) .and. & + present(nwfa2d) .and. & + present(nifa2d) )) then + write(errmsg,fmt='(*(a))') 'Logic error in mp_thompson_run:', & + ' aerosol-aware microphysics require all of the', & + ' following optional arguments:', & + ' nc, nwfa, nifa, nwfa2d, nifa2d' + errflg = 1 + return + end if end if !> - Convert specific humidity to water vapor mixing ratio. !> - Also, hydrometeor variables are mass or number mixing ratio !> - either kg of species per kg of dry air, or per kg of (dry + vapor). + ! DH* - do this only if istep == 1? Would be ok if it was + ! guaranteed that nothing else in the same subcycle group + ! was using these arrays, but it is somewhat dangerous. qv = spechum/(1.0_kind_phys-spechum) if (convert_dry_rho) then @@ -473,6 +487,7 @@ subroutine mp_thompson_run(ncol, nlev, con_g, con_rd, & nifa = nifa/(1.0_kind_phys-spechum) end if end if + ! *DH !> - Density of air in kg m-3 rho = con_eps*prsl/(con_rd*tgrs*(qv+con_eps)) @@ -566,7 +581,8 @@ subroutine mp_thompson_run(ncol, nlev, con_g, con_rd, & ids=ids, ide=ide, jds=jds, jde=jde, kds=kds, kde=kde, & ims=ims, ime=ime, jms=jms, jme=jme, kms=kms, kme=kme, & its=its, ite=ite, jts=jts, jte=jte, kts=kts, kte=kte, & - errmsg=errmsg, errflg=errflg, reset=reset) + reset_dBZ=reset_dBZ, istep=istep, nsteps=nsteps, & + first_time_step=first_time_step, errmsg=errmsg, errflg=errflg) else call mp_gt_driver(qv=qv, qc=qc, qr=qr, qi=qi, qs=qs, qg=qg, ni=ni, nr=nr, & nc=nc, nwfa=nwfa, nifa=nifa, nwfa2d=nwfa2d, nifa2d=nifa2d, & @@ -585,7 +601,8 @@ subroutine mp_thompson_run(ncol, nlev, con_g, con_rd, & ids=ids, ide=ide, jds=jds, jde=jde, kds=kds, kde=kde, & ims=ims, ime=ime, jms=jms, jme=jme, kms=kms, kme=kme, & its=its, ite=ite, jts=jts, jte=jte, kts=kts, kte=kte, & - errmsg=errmsg, errflg=errflg, reset=reset) + reset_dBZ=reset_dBZ, istep=istep, nsteps=nsteps, & + first_time_step=first_time_step, errmsg=errmsg, errflg=errflg) end if else if (do_effective_radii) then @@ -606,7 +623,8 @@ subroutine mp_thompson_run(ncol, nlev, con_g, con_rd, & ids=ids, ide=ide, jds=jds, jde=jde, kds=kds, kde=kde, & ims=ims, ime=ime, jms=jms, jme=jme, kms=kms, kme=kme, & its=its, ite=ite, jts=jts, jte=jte, kts=kts, kte=kte, & - errmsg=errmsg, errflg=errflg, reset=reset) + reset_dBZ=reset_dBZ, istep=istep, nsteps=nsteps, & + first_time_step=first_time_step, errmsg=errmsg, errflg=errflg) else call mp_gt_driver(qv=qv, qc=qc, qr=qr, qi=qi, qs=qs, qg=qg, ni=ni, nr=nr, & tt=tgrs, p=prsl, w=w, dz=dz, dt_in=dtp, & @@ -624,11 +642,16 @@ subroutine mp_thompson_run(ncol, nlev, con_g, con_rd, & ids=ids, ide=ide, jds=jds, jde=jde, kds=kds, kde=kde, & ims=ims, ime=ime, jms=jms, jme=jme, kms=kms, kme=kme, & its=its, ite=ite, jts=jts, jte=jte, kts=kts, kte=kte, & - errmsg=errmsg, errflg=errflg, reset=reset) + reset_dBZ=reset_dBZ, istep=istep, nsteps=nsteps, & + first_time_step=first_time_step, errmsg=errmsg, errflg=errflg) end if end if if (errflg/=0) return + ! DH* - do this only if istep == nsteps? Would be ok if it was + ! guaranteed that nothing else in the same subcycle group + ! was using these arrays, but it is somewhat dangerous. + !> - Convert water vapor mixing ratio back to specific humidity spechum = qv/(1.0_kind_phys+qv) @@ -647,6 +670,7 @@ subroutine mp_thompson_run(ncol, nlev, con_g, con_rd, & nifa = nifa/(1.0_kind_phys+qv) end if end if + ! *DH !> - Convert rainfall deltas from mm to m (on physics timestep); add to inout variables ! "rain" in Thompson MP refers to precipitation (total of liquid rainfall+snow+graupel+ice) @@ -656,6 +680,12 @@ subroutine mp_thompson_run(ncol, nlev, con_g, con_rd, & snow = snow + max(0.0, delta_snow_mp/1000.0_kind_phys) rain = rain + max(0.0, (delta_rain_mp - (delta_graupel_mp + delta_ice_mp + delta_snow_mp))/1000.0_kind_phys) + ! Recompute sr at last subcycling step + if (nsteps>1 .and. istep == nsteps) then + ! Unlike inside mp_gt_driver, rain does not contain frozen precip + sr = (snow + graupel + ice)/(rain + snow + graupel + ice +1.e-12) + end if + end subroutine mp_thompson_run !>@} diff --git a/physics/mp_thompson.meta b/physics/mp_thompson.meta index 237890024..573bab6c8 100644 --- a/physics/mp_thompson.meta +++ b/physics/mp_thompson.meta @@ -545,6 +545,30 @@ kind = kind_phys intent = in optional = F +[first_time_step] + standard_name = flag_for_first_time_step + long_name = flag for first time step for time integration loop (cold/warmstart) + units = flag + dimensions = () + type = logical + intent = in + optional = F +[istep] + standard_name = ccpp_loop_counter + long_name = loop counter for subcycling loops in CCPP + units = index + dimensions = () + type = integer + intent = in + optional = F +[nsteps] + standard_name = ccpp_loop_extent + long_name = loop extent for subcycling loops in CCPP + units = count + dimensions = () + type = integer + intent = in + optional = F [prcp] standard_name = lwe_thickness_of_explicit_precipitation_amount long_name = explicit precipitation (rain, ice, snow, graupel) on physics timestep @@ -608,7 +632,7 @@ kind = kind_phys intent = out optional = F -[reset] +[reset_dBZ] standard_name = flag_for_resetting_radar_reflectivity_calculation long_name = flag for resetting radar reflectivity calculation units = flag @@ -675,6 +699,14 @@ type = integer intent = in optional = F +[blkno] + standard_name = ccpp_block_number + long_name = number of block for explicit data blocking in CCPP + units = index + dimensions = () + type = integer + intent = in + optional = F [errmsg] standard_name = ccpp_error_message long_name = error message for error handling in CCPP