diff --git a/docs/FV3_citations.bib b/docs/FV3_citations.bib
index 825323bae..074367fb9 100644
--- a/docs/FV3_citations.bib
+++ b/docs/FV3_citations.bib
@@ -33,6 +33,16 @@ @article{chen2013seasonal
doi={10.1175/JCLI-D-12-00061.1}
}
+@article{zhou2019toward,
+ title={Toward Convective-Scale Prediction within the Next Generation Global Prediction System},
+ author={Zhou, Linjiong and Lin, Shian-Jiann and Chen, Jan-Huey and Harris, Lucas M. and Chen, Xi and Rees, Shannon L.},
+ journal={Bulletin of the American Meteorological Society},
+ volume={100},
+ issue={7},
+ year={2019},
+ doi={10.1175/bams-d-17-0246.1}
+}
+
@article {deng2008cirrus,
author = {Deng, Min and Mace, Gerald G.},
title = {Cirrus cloud microphysical properties and air motion statistics using cloud radar Doppler moments: Water content, particle size, and sedimentation relationships},
diff --git a/driver/fvGFS/atmosphere.F90 b/driver/fvGFS/atmosphere.F90
index 48b8d1d54..36d8fabd6 100644
--- a/driver/fvGFS/atmosphere.F90
+++ b/driver/fvGFS/atmosphere.F90
@@ -112,7 +112,7 @@ module atmosphere_mod
!
! | mpp_mod |
! mpp_error, stdout, FATAL, NOTE, input_nml_file, mpp_root_pe,
-! mpp_npes, mpp_pe, mpp_chksum,mpp_get_current_pelist,
+! mpp_npes, mpp_pe, mpp_chksum,mpp_get_current_pelist,
! mpp_set_current_pelist |
!
!
@@ -183,7 +183,7 @@ module atmosphere_mod
use fv_nggps_diags_mod, only: fv_nggps_diag_init, fv_nggps_diag, fv_nggps_tavg
use fv_restart_mod, only: fv_restart, fv_write_restart
use fv_timing_mod, only: timing_on, timing_off
-use fv_mp_mod, only: switch_current_Atm
+use fv_mp_mod, only: switch_current_Atm, is_master
use fv_sg_mod, only: fv_subgrid_z
use fv_update_phys_mod, only: fv_update_phys
use fv_nwp_nudge_mod, only: fv_nwp_nudge_init, fv_nwp_nudge_end, do_adiabatic_init
@@ -194,6 +194,7 @@ module atmosphere_mod
a_step, p_step, current_time_in_seconds
use mpp_domains_mod, only: mpp_get_data_domain, mpp_get_compute_domain
+use fv_grid_utils_mod, only: g_sum
implicit none
private
@@ -269,30 +270,13 @@ module atmosphere_mod
!! and diagnostics.
subroutine atmosphere_init (Time_init, Time, Time_step, Grid_box, area)
#ifdef CCPP
-#ifdef STATIC
-! For static builds, the ccpp_physics_{init,run,finalize} calls
-! are not pointing to code in the CCPP framework, but to auto-generated
-! ccpp_suite_cap and ccpp_group_*_cap modules behind a ccpp_static_api
- use ccpp_api, only: ccpp_init
use ccpp_static_api, only: ccpp_physics_init
-#else
- use iso_c_binding, only: c_loc
- use ccpp_api, only: ccpp_init, &
- ccpp_physics_init, &
- ccpp_field_add, &
- ccpp_error
-#endif
use CCPP_data, only: ccpp_suite, &
cdata => cdata_tile, &
CCPP_interstitial
#ifdef OPENMP
use omp_lib
#endif
-#ifndef STATIC
-! Begin include auto-generated list of modules for ccpp
-#include "ccpp_modules_fast_physics.inc"
-! End include auto-generated list of modules for ccpp
-#endif
#endif
type (time_type), intent(in) :: Time_init, Time, Time_step
type(grid_box_type), intent(inout) :: Grid_box
@@ -442,15 +426,8 @@ subroutine atmosphere_init (Time_init, Time, Time_step, Grid_box, area)
#ifdef CCPP
! Do CCPP fast physics initialization before call to adiabatic_init (since this calls fv_dynamics)
- ! Initialize the cdata structure
- call ccpp_init(trim(ccpp_suite), cdata, ierr)
- if (ierr/=0) then
- cdata%errmsg = ' atmosphere_dynamics: error in ccpp_init: ' // trim(cdata%errmsg)
- call mpp_error (FATAL, cdata%errmsg)
- end if
-
- ! For fast physics running over the entire domain, block and thread
- ! number are not used; set to safe values
+ ! For fast physics running over the entire domain, block
+ ! and thread number are not used; set to safe values
cdata%blk_no = 1
cdata%thrd_no = 1
@@ -486,18 +463,9 @@ subroutine atmosphere_init (Time_init, Time, Time_step, Grid_box, area)
#endif
mpirank=mpp_pe(), mpiroot=mpp_root_pe())
-#ifndef STATIC
-! Populate cdata structure with fields required to run fast physics (auto-generated).
-#include "ccpp_fields_fast_physics.inc"
-#endif
-
if (Atm(mytile)%flagstruct%do_sat_adj) then
! Initialize fast physics
-#ifdef STATIC
call ccpp_physics_init(cdata, suite_name=trim(ccpp_suite), group_name="fast_physics", ierr=ierr)
-#else
- call ccpp_physics_init(cdata, group_name="fast_physics", ierr=ierr)
-#endif
if (ierr/=0) then
cdata%errmsg = ' atmosphere_dynamics: error in ccpp_physics_init for group fast_physics: ' // trim(cdata%errmsg)
call mpp_error (FATAL, cdata%errmsg)
@@ -508,7 +476,7 @@ subroutine atmosphere_init (Time_init, Time, Time_step, Grid_box, area)
! --- initiate the start for a restarted regional forecast
if ( Atm(mytile)%gridstruct%regional .and. Atm(mytile)%flagstruct%warm_start ) then
- call start_regional_restart(Atm(1), &
+ call start_regional_restart(Atm(1), dt_atmos, &
isc, iec, jsc, jec, &
isd, ied, jsd, jed )
endif
@@ -712,32 +680,22 @@ end subroutine atmosphere_dynamics
!>@brief The subroutine 'atmosphere_end' is an API for the termination of the
!! FV3 dynamical core responsible for writing out a restart and final diagnostic state.
- subroutine atmosphere_end (Time, Grid_box)
+ subroutine atmosphere_end (Time, Grid_box, restart_endfcst)
#ifdef CCPP
-#ifdef STATIC
-! For static builds, the ccpp_physics_{init,run,finalize} calls
-! are not pointing to code in the CCPP framework, but to auto-generated
-! ccpp_suite_cap and ccpp_group_*_cap modules behind a ccpp_static_api
use ccpp_static_api, only: ccpp_physics_finalize
use CCPP_data, only: ccpp_suite
-#else
- use ccpp_api, only: ccpp_physics_finalize
-#endif
use CCPP_data, only: cdata => cdata_tile
#endif
type (time_type), intent(in) :: Time
type(grid_box_type), intent(inout) :: Grid_box
+ logical, intent(in) :: restart_endfcst
#ifdef CCPP
integer :: ierr
if (Atm(mytile)%flagstruct%do_sat_adj) then
! Finalize fast physics
-#ifdef STATIC
call ccpp_physics_finalize(cdata, suite_name=trim(ccpp_suite), group_name="fast_physics", ierr=ierr)
-#else
- call ccpp_physics_finalize(cdata, group_name="fast_physics", ierr=ierr)
-#endif
if (ierr/=0) then
cdata%errmsg = ' atmosphere_dynamics: error in ccpp_physics_finalize for group fast_physics: ' // trim(cdata%errmsg)
call mpp_error (FATAL, cdata%errmsg)
@@ -754,7 +712,7 @@ subroutine atmosphere_end (Time, Grid_box)
call timing_off('FV_DIAG')
endif
- call fv_end(Atm, grids_on_this_pe)
+ call fv_end(Atm, grids_on_this_pe, restart_endfcst)
deallocate (Atm)
deallocate( u_dt, v_dt, t_dt, pref, dum1d )
@@ -1267,7 +1225,6 @@ subroutine atmosphere_get_bottom_layer (Atm_block, DYCORE_Data)
rrg = rdgas / grav
if (first_time) then
- print *, 'calculating slp kr value'
! determine 0.8 sigma reference level
sigtop = Atm(mytile)%ak(1)/pstd_mks+Atm(mytile)%bk(1)
do k = 1, npz
@@ -1394,6 +1351,7 @@ subroutine atmosphere_state_update (Time, IPD_Data, IAU_Data, Atm_block, flip_vc
integer :: i, j, ix, k, k1, n, w_diff, nt_dyn, iq
integer :: nb, blen, nwat, dnats, nq_adv
real(kind=kind_phys):: rcp, q0, qwat(nq), qt, rdt
+ real psum, qsum, psumb, qsumb, betad
Time_prev = Time
Time_next = Time + Time_step_atmos
rdt = 1.d0 / dt_atmos
@@ -1406,6 +1364,18 @@ subroutine atmosphere_state_update (Time, IPD_Data, IAU_Data, Atm_block, flip_vc
if( nq<3 ) call mpp_error(FATAL, 'GFS phys must have 3 interactive tracers')
if (IAU_Data%in_interval) then
+ if (IAU_Data%drymassfixer) then
+ ! global mean total pressure and water before IAU
+ psumb = g_sum(Atm(n)%domain,sum(Atm(n)%delp(isc:iec,jsc:jec,1:npz),dim=3),&
+ isc,iec,jsc,jec,Atm(n)%ng,Atm(n)%gridstruct%area_64,1,reproduce=.true.)
+ qsumb = g_sum(Atm(n)%domain,&
+ sum(Atm(n)%delp(isc:iec,jsc:jec,1:npz)*sum(Atm(n)%q(isc:iec,jsc:jec,1:npz,1:nwat),4),dim=3),&
+ isc,iec,jsc,jec,Atm(n)%ng,Atm(n)%gridstruct%area_64,1,reproduce=.true.)
+ if (is_master()) then
+ print *,'dry ps before IAU/physics',psumb+Atm(n)%ptop-qsumb
+ endif
+ endif
+
! IAU increments are in units of 1/sec
! add analysis increment to u,v,t tendencies
@@ -1468,11 +1438,11 @@ subroutine atmosphere_state_update (Time, IPD_Data, IAU_Data, Atm_block, flip_vc
call fill_gfs(blen, npz, IPD_Data(nb)%Statein%prsi, IPD_Data(nb)%Stateout%gq0, 1.e-9_kind_phys)
do k = 1, npz
- if(flip_vc) then
- k1 = npz+1-k !reverse the k direction
- else
- k1 = k
- endif
+ if(flip_vc) then
+ k1 = npz+1-k !reverse the k direction
+ else
+ k1 = k
+ endif
do ix = 1, blen
i = Atm_block%index(nb)%ii(ix)
j = Atm_block%index(nb)%jj(ix)
@@ -1514,11 +1484,11 @@ subroutine atmosphere_state_update (Time, IPD_Data, IAU_Data, Atm_block, flip_vc
!--- See Note in statein...
do iq = nq+1, ncnst
do k = 1, npz
- if(flip_vc) then
- k1 = npz+1-k !reverse the k direction
- else
- k1 = k
- endif
+ if(flip_vc) then
+ k1 = npz+1-k !reverse the k direction
+ else
+ k1 = k
+ endif
do ix = 1, blen
i = Atm_block%index(nb)%ii(ix)
j = Atm_block%index(nb)%jj(ix)
@@ -1529,6 +1499,29 @@ subroutine atmosphere_state_update (Time, IPD_Data, IAU_Data, Atm_block, flip_vc
enddo ! nb-loop
+! dry mass fixer in IAU interval following
+! https://onlinelibrary.wiley.com/doi/full/10.1111/j.1600-0870.2007.00299.x
+ if (IAU_Data%in_interval .and. IAU_data%drymassfixer) then
+ ! global mean total pressure
+ psum = g_sum(Atm(n)%domain,sum(Atm(n)%delp(isc:iec,jsc:jec,1:npz),dim=3),&
+ isc,iec,jsc,jec,Atm(n)%ng,Atm(n)%gridstruct%area_64,1,reproduce=.true.)
+ ! global mean total water (before adjustment)
+ qsum = g_sum(Atm(n)%domain,&
+ sum(Atm(n)%delp(isc:iec,jsc:jec,1:npz)*sum(Atm(n)%q(isc:iec,jsc:jec,1:npz,1:nwat),4),dim=3),&
+ isc,iec,jsc,jec,Atm(n)%ng,Atm(n)%gridstruct%area_64,1,reproduce=.true.)
+ betad = (psum - (psumb - qsumb))/qsum
+ if (is_master()) then
+ print *,'dry ps after IAU/physics',psum+Atm(n)%ptop-qsum
+ endif
+ Atm(n)%q(:,:,:,1:nwat) = betad*Atm(n)%q(:,:,:,1:nwat)
+ !qsum = g_sum(Atm(n)%domain,&
+ ! sum(Atm(n)%delp(isc:iec,jsc:jec,1:npz)*sum(Atm(n)%q(isc:iec,jsc:jec,1:npz,1:nwat),4),dim=3),&
+ ! isc,iec,jsc,jec,Atm(n)%ng,Atm(n)%gridstruct%area_64,1)
+ !if (is_master()) then
+ ! print *,'dry ps after iau_drymassfixer',psum+Atm(n)%ptop-qsum
+ !endif
+ endif
+
call timing_off('GFS_TENDENCIES')
w_diff = get_tracer_index (MODEL_ATMOS, 'w_diff' )
@@ -1592,6 +1585,7 @@ subroutine atmosphere_state_update (Time, IPD_Data, IAU_Data, Atm_block, flip_vc
call nullify_domain()
call timing_on('FV_DIAG')
+
call fv_diag(Atm(mytile:mytile), zvir, fv_time, Atm(mytile)%flagstruct%print_freq)
first_diag = .false.
call timing_off('FV_DIAG')
@@ -1905,6 +1899,10 @@ subroutine atmos_phys_driver_statein (IPD_Data, Atm_block,flip_vc)
real(kind=kind_phys) :: pk0inv, ptop, pktop
real(kind=kind_phys) :: rTv, dm, qgrs_rad
integer :: nb, blen, npz, i, j, k, ix, k1, kz, dnats, nq_adv
+#ifdef MULTI_GASES
+ real :: q_grs(nq), q_min
+#endif
+
!!! NOTES: lmh 6nov15
!!! - "Layer" means "layer mean", ie. the average value in a layer
@@ -1925,7 +1923,13 @@ subroutine atmos_phys_driver_statein (IPD_Data, Atm_block,flip_vc)
!$OMP shared (Atm_block, Atm, IPD_Data, npz, nq, ncnst, sphum, liq_wat, &
!$OMP ice_wat, rainwat, snowwat, graupel, pk0inv, ptop, &
!$OMP pktop, zvir, mytile, dnats, nq_adv, flip_vc) &
+#ifdef MULTI_GASES
+
+!$OMP private (dm, nb, blen, i, j, ix, k1, kz, rTv, qgrs_rad, q_min, q_grs)
+
+#else
!$OMP private (dm, nb, blen, i, j, ix, k1, kz, rTv, qgrs_rad)
+#endif
do nb = 1,Atm_block%nblks
! gas_phase_mass <-- prsl
@@ -2032,7 +2036,9 @@ subroutine atmos_phys_driver_statein (IPD_Data, Atm_block,flip_vc)
do i=1,blen
! Geo-potential at interfaces:
#ifdef MULTI_GASES
- rTv = rdgas*IPD_Data(nb)%Statein%tgrs(i,k)*virq_max(IPD_Data(nb)%Statein%qgrs(i,k,:),qmin)
+ q_grs(1:nq_adv) = IPD_Data(nb)%Statein%qgrs(i,k,1:nq_adv)
+ q_min = qmin
+ rTv = rdgas*IPD_Data(nb)%Statein%tgrs(i,k)*virq_max(q_grs(:),q_min)
#else
qgrs_rad = max(qmin,IPD_Data(nb)%Statein%qgrs(i,k,sphum))
rTv = rdgas*IPD_Data(nb)%Statein%tgrs(i,k)*(1.+zvir*qgrs_rad)
diff --git a/driver/fvGFS/fv_nggps_diag.F90 b/driver/fvGFS/fv_nggps_diag.F90
index f8c8f94b9..07a471c32 100644
--- a/driver/fvGFS/fv_nggps_diag.F90
+++ b/driver/fvGFS/fv_nggps_diag.F90
@@ -93,13 +93,13 @@ module fv_nggps_diags_mod
real, parameter:: stndrd_atmos_lapse = 0.0065
logical master
- integer :: id_ua, id_va, id_pt, id_delp, id_pfhy, id_pfnh
- integer :: id_w, id_delz, id_diss, id_ps, id_hs, id_dbz
+ integer :: id_ua, id_va, id_pt, id_delp, id_pfhy, id_pfnh
+ integer :: id_w, id_delz, id_diss, id_ps, id_hs, id_dbz, id_omga
integer :: kstt_ua, kstt_va, kstt_pt, kstt_delp, kstt_pfhy
integer :: kstt_pfnh, kstt_w, kstt_delz, kstt_diss, kstt_ps,kstt_hs
integer :: kend_ua, kend_va, kend_pt, kend_delp, kend_pfhy
integer :: kend_pfnh, kend_w, kend_delz, kend_diss, kend_ps,kend_hs
- integer :: kstt_dbz, kend_dbz
+ integer :: kstt_dbz, kend_dbz, kstt_omga, kend_omga
integer :: kstt_windvect, kend_windvect
integer :: id_wmaxup,id_wmaxdn,kstt_wup, kend_wup,kstt_wdn,kend_wdn
integer :: id_uhmax03,id_uhmin03,id_uhmax25,id_uhmin25,id_maxvort01
@@ -236,6 +236,13 @@ subroutine fv_nggps_diag_init(Atm, axes, Time)
endif
endif
+ id_omga = register_diag_field ( trim(file_name), 'omga', axes(1:3), Time, &
+ 'Vertical pressure velocity', 'pa/sec', missing_value=missing_value )
+ if (id_omga>0) then
+ kstt_omga = nlevs+1; kend_omga = nlevs+npzo
+ nlevs = nlevs + npzo
+ endif
+
id_pt = register_diag_field ( trim(file_name), 'temp', axes(1:3), Time, &
'temperature', 'K', missing_value=missing_value, range=trange )
if (id_pt>0) then
@@ -482,6 +489,11 @@ subroutine fv_nggps_diag(Atm, zvir, Time)
call store_data(id_w, Atm(n)%w(isco:ieco,jsco:jeco,:), Time, kstt_w, kend_w)
endif
+ !--- OMGA (non-hydrostatic)
+ if ( id_omga>0 ) then
+ call store_data(id_omga, Atm(n)%omga(isco:ieco,jsco:jeco,:), Time, kstt_omga, kend_omga)
+ endif
+
!--- TEMPERATURE
if(id_pt > 0) call store_data(id_pt, Atm(n)%pt(isco:ieco,jsco:jeco,:), Time, kstt_pt, kend_pt)
@@ -502,7 +514,7 @@ subroutine fv_nggps_diag(Atm, zvir, Time)
do k=1,npzo
do j=jsco,jeco
do i=isco,ieco
- wk(i,j,k) = -Atm(n)%delz(i,j,k)
+ wk(i,j,k) = Atm(n)%delz(i,j,k)
enddo
enddo
enddo
@@ -1172,6 +1184,13 @@ subroutine fv_dyn_bundle_setup(axes, dyn_bundle, fcst_grid, quilting, rc)
if(rc==0) num_field_dyn=num_field_dyn+1
endif
endif
+!
+ if( id_omga>0 ) then
+ call find_outputname(trim(file_name),'omga',output_name)
+ call add_field_to_bundle(trim(output_name),'Vertical pressure velocity', 'pa/sec', "time: point", &
+ axes(1:3), fcst_grid, kstt_omga,kend_omga, dyn_bundle, output_file, rcd=rc)
+ if(rc==0) num_field_dyn=num_field_dyn+1
+ endif
!
if(id_pt > 0) then
call find_outputname(trim(file_name),'temp',output_name)
diff --git a/makefile b/makefile
index 7b029e0ee..523dc111b 100644
--- a/makefile
+++ b/makefile
@@ -96,7 +96,6 @@ $(LIBRARY): $(OBJS)
./model/nh_utils.o : ./model/nh_utils.F90
$(FC) $(CPPDEFS) $(FPPFLAGS) $(FFLAGS) $(OTHER_FFLAGS) $(FAST) -c $< -o $@
-# For PROD/TRANSITION, this is overwritten below
./model/fv_mapz.o : ./model/fv_mapz.F90
$(FC) $(CPPDEFS) $(FPPFLAGS) $(FFLAGS) $(OTHER_FFLAGS) $(FAST) -c $< -o $@
@@ -107,20 +106,6 @@ $(LIBRARY): $(OBJS)
./driver/fvGFS/atmosphere.o : ./driver/fvGFS/atmosphere.F90
$(FC) $(CPPDEFS) $(FPPFLAGS) $(FFLAGS) $(OTHER_FFLAGS) $(ESMF_INC) -c $< -o $@
-# For CCPP acceptance: reduce optimization for certain files to
-# obtain bit-for-bit identical results in PROD mode on Theia/Intel 15
-ifneq (,$(findstring TRANSITION,$(CPPDEFS)))
-FFLAGS_LOPT=$(subst CORE-AVX2,CORE-AVX-I,\
- $(subst no-prec-div,prec-div,\
- $(subst no-prec-sqrt,prec-sqrt,$(FFLAGS))))
-./model/dyn_core.o : ./model/dyn_core.F90
- $(FC) $(CPPDEFS) $(FPPFLAGS) $(FFLAGS_LOPT) $(OTHER_FFLAGS) -c $< -o $@
-./model/fv_mapz.o : ./model/fv_mapz.F90
- $(FC) $(CPPDEFS) $(FPPFLAGS) $(FFLAGS_LOPT) $(OTHER_FFLAGS) $(FAST) -c $< -o $@
-./model/fv_cmp.o : ./model/fv_cmp.F90
- $(FC) $(CPPDEFS) $(FPPFLAGS) $(FFLAGS_LOPT) $(OTHER_FFLAGS) -c $< -o $@
-endif # (,$(findstring TRANSITION,$(CPPDEFS)))
-
.PHONY: clean
clean:
@echo "Cleaning fv3core ... "
diff --git a/model/dyn_core.F90 b/model/dyn_core.F90
index 763654714..32e5ca97e 100644
--- a/model/dyn_core.F90
+++ b/model/dyn_core.F90
@@ -364,10 +364,10 @@ subroutine dyn_core(npx, npy, npz, ng, sphum, nq, bdt, n_split, zvir, cp, akap,
allocate( dv(isd:ied+1,jsd:jed, npz) )
call init_ijk_mem(isd,ied+1, jsd,jed , npz, dv, 0.)
endif
-!$OMP parallel do default(none) shared(is,ie,js,je,npz,diss_est)
+!$OMP parallel do default(none) shared(isd,ied,jsd,jed,npz,diss_est)
do k=1,npz
- do j=js,je
- do i=is,ie
+ do j=jsd,jed
+ do i=isd,ied
diss_est(i,j,k) = 0.
enddo
enddo
diff --git a/model/fv_arrays.F90 b/model/fv_arrays.F90
index 1e7c6a686..d6a818857 100644
--- a/model/fv_arrays.F90
+++ b/model/fv_arrays.F90
@@ -985,6 +985,7 @@ module fv_arrays_mod
!< The default value is 4 (recommended); fourth-order interpolation
!< is used unless c2l_ord = 2.
+ integer :: nrows_blend = 0 !< # of blending rows in the outer integration domain.
real(kind=R_GRID) :: dx_const = 1000. !< Specifies the (uniform) grid-cell-width in the x-direction
!< on a doubly-periodic grid (grid_type = 4) in meters.
@@ -1006,6 +1007,10 @@ module fv_arrays_mod
integer :: bc_update_interval = 3 !< Default setting for interval (hours) between external regional BC data files.
+ logical :: regional_bcs_from_gsi = .false. !< Default setting for using DA-updated BC files.
+
+ logical :: write_restart_with_bcs = .false. !< Default setting for writing restart files with boundary rows.
+
!>Convenience pointers
integer, pointer :: grid_number
diff --git a/model/fv_cmp.F90 b/model/fv_cmp.F90
index aacf69dbe..16b679b9f 100644
--- a/model/fv_cmp.F90
+++ b/model/fv_cmp.F90
@@ -50,7 +50,7 @@ module fv_cmp_mod
! | gfdl_cloud_microphys_mod |
! ql_gen, qi_gen, qi0_max, ql_mlt, ql0_max, qi_lim, qs_mlt,
! tau_r2g, tau_smlt, tau_i2s, tau_v2l, tau_l2v, tau_imlt, tau_l2r,
-! rad_rain, rad_snow, rad_graupel, dw_ocean, dw_land |
+! rad_rain, rad_snow, rad_graupel, dw_ocean, dw_land, tintqs
!
!
@@ -60,7 +60,7 @@ module fv_cmp_mod
use gfdl_cloud_microphys_mod, only: ql_gen, qi_gen, qi0_max, ql_mlt, ql0_max, qi_lim, qs_mlt
use gfdl_cloud_microphys_mod, only: icloud_f, sat_adj0, t_sub, cld_min
use gfdl_cloud_microphys_mod, only: tau_r2g, tau_smlt, tau_i2s, tau_v2l, tau_l2v, tau_imlt, tau_l2r
- use gfdl_cloud_microphys_mod, only: rad_rain, rad_snow, rad_graupel, dw_ocean, dw_land
+ use gfdl_cloud_microphys_mod, only: rad_rain, rad_snow, rad_graupel, dw_ocean, dw_land, tintqs
#ifdef MULTI_GASES
use multi_gases_mod, only: virq_qpz, vicpqd_qpz, vicvqd_qpz, num_gas
#endif
@@ -774,9 +774,13 @@ subroutine fv_sat_adj (mdt, zvir, is, ie, js, je, ng, hydrostatic, consv_te, te0
do i = is, ie
- tin = pt1 (i) - (lcp2 (i) * q_cond (i) + icp2 (i) * q_sol (i)) ! minimum temperature
+ if(tintqs) then
+ tin = pt1(i)
+ else
+ tin = pt1 (i) - (lcp2 (i) * q_cond (i) + icp2 (i) * q_sol (i)) ! minimum temperature
! tin = pt1 (i) - ((lv00 + d0_vap * pt1 (i)) * q_cond (i) + &
! (li00 + dc_ice * pt1 (i)) * q_sol (i)) / (mc_air (i) + qpz (i) * c_vap)
+ endif
! -----------------------------------------------------------------------
! determine saturated specific humidity
@@ -820,14 +824,14 @@ subroutine fv_sat_adj (mdt, zvir, is, ie, js, je, ng, hydrostatic, consv_te, te0
! icloud_f = 2: binary cloud scheme (0 / 1)
! -----------------------------------------------------------------------
- if (rh > 0.75 .and. qpz (i) > 1.e-6) then
+ if (rh > 0.75 .and. qpz (i) > 1.e-8) then
dq = hvar (i) * qpz (i)
q_plus = qpz (i) + dq
q_minus = qpz (i) - dq
if (icloud_f == 2) then
if (qpz (i) > qstar (i)) then
qa (i, j) = 1.
- elseif (qstar (i) < q_plus .and. q_cond (i) > 1.e-6) then
+ elseif (qstar (i) < q_plus .and. q_cond (i) > 1.e-8) then
qa (i, j) = ((q_plus - qstar (i)) / dq) ** 2
qa (i, j) = min (1., qa (i, j))
else
@@ -847,7 +851,7 @@ subroutine fv_sat_adj (mdt, zvir, is, ie, js, je, ng, hydrostatic, consv_te, te0
qa (i, j) = 0.
endif
! impose minimum cloudiness if substantial q_cond (i) exist
- if (q_cond (i) > 1.e-6) then
+ if (q_cond (i) > 1.e-8) then
qa (i, j) = max (cld_min, qa (i, j))
endif
qa (i, j) = min (1., qa (i, j))
diff --git a/model/fv_control.F90 b/model/fv_control.F90
index e87b01963..25eef2317 100644
--- a/model/fv_control.F90
+++ b/model/fv_control.F90
@@ -331,6 +331,9 @@ module fv_control_mod
logical, pointer :: nested, twowaynest
logical, pointer :: regional
integer, pointer :: bc_update_interval
+ integer, pointer :: nrows_blend
+ logical, pointer :: regional_bcs_from_gsi
+ logical, pointer :: write_restart_with_bcs
integer, pointer :: parent_tile, refinement, nestbctype, nestupdate, nsponge, ioffset, joffset
real, pointer :: s_weight, update_blend
@@ -592,17 +595,18 @@ end subroutine fv_init
!>@brief The subroutine 'fv_end' terminates FV3, deallocates memory,
!! saves restart files, and stops I/O.
- subroutine fv_end(Atm, grids_on_this_pe)
+ subroutine fv_end(Atm, grids_on_this_pe, restart_endfcst)
type(fv_atmos_type), intent(inout) :: Atm(:)
logical, intent(INOUT) :: grids_on_this_pe(:)
+ logical, intent(in) :: restart_endfcst
integer :: n
call timing_off('TOTAL')
call timing_prt( gid )
- call fv_restart_end(Atm, grids_on_this_pe)
+ call fv_restart_end(Atm, grids_on_this_pe, restart_endfcst)
call fv_io_exit()
! Free temporary memory from sw_core routines
@@ -669,7 +673,8 @@ subroutine run_setup(Atm, dt_atmos, grids_on_this_pe, p_split)
nested, twowaynest, parent_grid_num, parent_tile, nudge_qv, &
refinement, nestbctype, nestupdate, nsponge, s_weight, &
ioffset, joffset, check_negative, nudge_ic, halo_update_type, gfs_phil, agrid_vel_rst, &
- do_uni_zfull, adj_mass_vmr, fac_n_spl, fhouri, regional, bc_update_interval
+ do_uni_zfull, adj_mass_vmr, fac_n_spl, fhouri, regional, bc_update_interval, &
+ regional_bcs_from_gsi, write_restart_with_bcs, nrows_blend
namelist /test_case_nml/test_case, bubble_do, alpha, nsolitons, soliton_Umax, soliton_size
#ifdef MULTI_GASES
@@ -891,6 +896,12 @@ subroutine run_setup(Atm, dt_atmos, grids_on_this_pe, p_split)
Atm(n)%neststruct%refinement = -1
end if
+ if (Atm(n)%flagstruct%regional) then
+ if ( consv_te > 0.) then
+ call mpp_error(FATAL, 'The global energy fixer cannot be used on a regional grid. consv_te must be set to 0.')
+ end if
+ end if
+
if (Atm(n)%neststruct%nested) then
if (Atm(n)%flagstruct%grid_type >= 4 .and. Atm(n)%parent_grid%flagstruct%grid_type >= 4) then
Atm(n)%flagstruct%dx_const = Atm(n)%parent_grid%flagstruct%dx_const / real(Atm(n)%neststruct%refinement)
@@ -1232,6 +1243,9 @@ subroutine setup_pointers(Atm)
target_lon => Atm%flagstruct%target_lon
regional => Atm%flagstruct%regional
bc_update_interval => Atm%flagstruct%bc_update_interval
+ nrows_blend => Atm%flagstruct%nrows_blend
+ regional_bcs_from_gsi => Atm%flagstruct%regional_bcs_from_gsi
+ write_restart_with_bcs => Atm%flagstruct%write_restart_with_bcs
reset_eta => Atm%flagstruct%reset_eta
p_fac => Atm%flagstruct%p_fac
a_imp => Atm%flagstruct%a_imp
diff --git a/model/fv_mapz.F90 b/model/fv_mapz.F90
index 222aac9c5..5eaf9f11a 100644
--- a/model/fv_mapz.F90
+++ b/model/fv_mapz.F90
@@ -95,17 +95,10 @@ module fv_mapz_mod
#ifndef CCPP
use fv_cmp_mod, only: qs_init, fv_sat_adj
#else
-#ifdef STATIC
-! For static builds, the ccpp_physics_{init,run,finalize} calls
-! are not pointing to code in the CCPP framework, but to auto-generated
-! ccpp_suite_cap and ccpp_group_*_cap modules behind a ccpp_static_api
- use ccpp_api, only: ccpp_initialized
use ccpp_static_api, only: ccpp_physics_run
use CCPP_data, only: ccpp_suite
-#else
- use ccpp_api, only: ccpp_initialized, ccpp_physics_run
-#endif
- use CCPP_data, only: cdata => cdata_tile, CCPP_interstitial
+ use CCPP_data, only: cdata => cdata_tile
+ use CCPP_data, only: CCPP_interstitial
#endif
#ifdef MULTI_GASES
use multi_gases_mod, only: virq, virqd, vicpqd, vicvqd, num_gas
@@ -201,10 +194,6 @@ subroutine Lagrangian_to_Eulerian(last_step, consv, ps, pe, delp, pkz, pk, &
real, intent(inout):: dtdt(is:ie,js:je,km)
real, intent(out):: pkz(is:ie,js:je,km) !< layer-mean pk for converting t to pt
real, intent(out):: te(isd:ied,jsd:jed,km)
-#if !defined(CCPP) && defined(TRANSITION)
- ! For bit-for-bit reproducibility
- real, volatile:: volatile_var
-#endif
! !DESCRIPTION:
!
@@ -263,7 +252,7 @@ subroutine Lagrangian_to_Eulerian(last_step, consv, ps, pe, delp, pkz, pk, &
endif
!$OMP parallel do default(none) shared(is,ie,js,je,km,pe,ptop,kord_tm,hydrostatic, &
-!$OMP pt,pk,rg,peln,q,nwat,liq_wat,rainwat,ice_wat,snowwat, &
+!$OMP pt,pk,rg,peln,q,nwat,liq_wat,rainwat,ice_wat,snowwat, &
!$OMP graupel,q_con,sphum,cappa,r_vir,rcp,k1k,delp, &
!$OMP delz,akap,pkz,te,u,v,ps, gridstruct, last_step, &
!$OMP ak,bk,nq,isd,ied,jsd,jed,kord_tr,fill, adiabatic, &
@@ -631,9 +620,7 @@ subroutine Lagrangian_to_Eulerian(last_step, consv, ps, pe, delp, pkz, pk, &
!$OMP ng,gridstruct,E_Flux,pdt,dtmp,reproduce_sum,q, &
!$OMP mdt,cld_amt,cappa,dtdt,out_dt,rrg,akap,do_sat_adj, &
!$OMP kord_tm,cdata,CCPP_interstitial) &
-#ifdef STATIC
!$OMP shared(ccpp_suite) &
-#endif
#ifdef MULTI_GASES
!$OMP shared(num_gas) &
#endif
@@ -647,9 +634,7 @@ subroutine Lagrangian_to_Eulerian(last_step, consv, ps, pe, delp, pkz, pk, &
!$OMP ng,gridstruct,E_Flux,pdt,dtmp,reproduce_sum,q, &
!$OMP mdt,cld_amt,cappa,dtdt,out_dt,rrg,akap,do_sat_adj, &
!$OMP fast_mp_consv,kord_tm,cdata, CCPP_interstitial) &
-#ifdef STATIC
!$OMP shared(ccpp_suite) &
-#endif
#ifdef MULTI_GASES
!$OMP shared(num_gas) &
#endif
@@ -663,9 +648,6 @@ subroutine Lagrangian_to_Eulerian(last_step, consv, ps, pe, delp, pkz, pk, &
!$OMP ng,gridstruct,E_Flux,pdt,dtmp,reproduce_sum,q, &
!$OMP mdt,cld_amt,cappa,dtdt,out_dt,rrg,akap,do_sat_adj, &
!$OMP fast_mp_consv,kord_tm) &
-#ifdef TRANSITION
-!$OMP private(volatile_var) &
-#endif
#ifdef MULTI_GASES
!$OMP shared(num_gas) &
#endif
@@ -815,15 +797,11 @@ subroutine Lagrangian_to_Eulerian(last_step, consv, ps, pe, delp, pkz, pk, &
if ( do_sat_adj ) then
call timing_on('sat_adj2')
#ifdef CCPP
- if (ccpp_initialized(cdata)) then
-#ifdef STATIC
+ if (cdata%initialized()) then
call ccpp_physics_run(cdata, suite_name=trim(ccpp_suite), group_name='fast_physics', ierr=ierr)
-#else
- call ccpp_physics_run(cdata, group_name='fast_physics', ierr=ierr)
-#endif
if (ierr/=0) call mpp_error(FATAL, "Call to ccpp_physics_run for group 'fast_physics' failed")
else
- call mpp_error (FATAL, 'Lagrangian_to_Eulerian: can not call CCPP fast physics because cdata not initialized')
+ call mpp_error (FATAL, 'Lagrangian_to_Eulerian: can not call CCPP fast physics because CCPP not initialized')
endif
#else
!$OMP do
@@ -854,28 +832,13 @@ subroutine Lagrangian_to_Eulerian(last_step, consv, ps, pe, delp, pkz, pk, &
do j=js,je
do i=is,ie
#ifdef MOIST_CAPPA
-#ifdef TRANSITION
- volatile_var = log(rrg*delp(i,j,k)/delz(i,j,k)*pt(i,j,k))
- pkz(i,j,k) = exp(cappa(i,j,k)*volatile_var)
-#else
pkz(i,j,k) = exp(cappa(i,j,k)*log(rrg*delp(i,j,k)/delz(i,j,k)*pt(i,j,k)))
-#endif
-#else
-#ifdef TRANSITION
-#ifdef MULTI_GASES
- volatile_var = log(rrg*delp(i,j,k)/delz(i,j,k)*pt(i,j,k))
- pkz(i,j,k) = exp(akap*(virqd(q(i,j,k,1:num_gas))/vicpqd(q(i,j,k,1:num_gas))*volatile_var)
-#else
- volatile_var = log(rrg*delp(i,j,k)/delz(i,j,k)*pt(i,j,k))
- pkz(i,j,k) = exp(akap*volatile_var)
-#endif
#else
#ifdef MULTI_GASES
pkz(i,j,k) = exp(akap*(virqd(q(i,j,k,1:num_gas))/vicpqd(q(i,j,k,1:num_gas))*log(rrg*delp(i,j,k)/delz(i,j,k)*pt(i,j,k)))
#else
pkz(i,j,k) = exp(akap*log(rrg*delp(i,j,k)/delz(i,j,k)*pt(i,j,k)))
#endif
-#endif
#endif
enddo
enddo
@@ -3487,12 +3450,25 @@ subroutine moist_cv(is,ie, isd,ied, jsd,jed, km, j, k, nwat, sphum, liq_wat, rai
enddo
case(4) ! K_warm_rain with fake ice
do i=is,ie
+#ifndef CCPP
qv(i) = q(i,j,k,sphum)
qd(i) = q(i,j,k,liq_wat) + q(i,j,k,rainwat)
#ifdef MULTI_GASES
cvm(i) = (1.-(qv(i)+qd(i)))*cv_air*vicvqd(q(i,j,k,1:num_gas)) + qv(i)*cv_vap + qd(i)*c_liq
#else
cvm(i) = (1.-(qv(i)+qd(i)))*cv_air + qv(i)*cv_vap + qd(i)*c_liq
+#endif
+#else
+ qv(i) = q(i,j,k,sphum)
+ ql(i) = q(i,j,k,liq_wat) + q(i,j,k,rainwat)
+ qs(i) = q(i,j,k,ice_wat)
+ qd(i) = ql(i) + qs(i)
+#ifdef MULTI_GASES
+ cvm(i) = (1.-(qv(i)+qd(i)))*cv_air*vicvqd(q(i,j,k,1:num_gas)) + qv(i)*cv_vap + ql(i)*c_liq + qs(i)*c_ice
+#else
+ cvm(i) = (1.-(qv(i)+qd(i)))*cv_air + qv(i)*cv_vap + ql(i)*c_liq + qs(i)*c_ice
+#endif
+
#endif
enddo
case(5)
@@ -3596,12 +3572,26 @@ subroutine moist_cp(is,ie, isd,ied, jsd,jed, km, j, k, nwat, sphum, liq_wat, rai
enddo
case(4) ! K_warm_rain scheme with fake ice
do i=is,ie
+#ifndef CCPP
qv(i) = q(i,j,k,sphum)
qd(i) = q(i,j,k,liq_wat) + q(i,j,k,rainwat)
#ifdef MULTI_GASES
cpm(i) = (1.-(qv(i)+qd(i)))*cp_air*vicpqd(q(i,j,k,:)) + qv(i)*cp_vapor + qd(i)*c_liq
#else
cpm(i) = (1.-(qv(i)+qd(i)))*cp_air + qv(i)*cp_vapor + qd(i)*c_liq
+#endif
+#else
+ qv(i) = q(i,j,k,sphum)
+ ql(i) = q(i,j,k,liq_wat) + q(i,j,k,rainwat)
+ qs(i) = q(i,j,k,ice_wat)
+ qd(i) = ql(i) + qs(i)
+#ifdef MULTI_GASES
+ cpm(i) = (1.-(qv(i)+qd(i)))*cp_air*vicpqd(q(i,j,k,:)) + qv(i)*cp_vapor + ql(i)*c_liq + qs(i)*c_ice
+#else
+ cpm(i) = (1.-(qv(i)+qd(i)))*cp_air + qv(i)*cp_vapor + ql(i)*c_liq + qs(i)*c_ice
+#endif
+
+
#endif
enddo
case(5)
diff --git a/model/fv_regional_bc.F90 b/model/fv_regional_bc.F90
index 8b6d11db8..9bd8e2b8a 100644
--- a/model/fv_regional_bc.F90
+++ b/model/fv_regional_bc.F90
@@ -34,7 +34,7 @@ module fv_regional_mod
use mpp_mod, only: FATAL, input_nml_file, &
mpp_error ,mpp_pe, mpp_sync, &
mpp_npes, mpp_root_pe, mpp_gather, &
- mpp_get_current_pelist, NULL_PE
+ mpp_get_current_pelist, NOTE, NULL_PE
use mpp_io_mod
use tracer_manager_mod,only: get_tracer_index,get_tracer_names
use field_manager_mod, only: MODEL_ATMOS
@@ -78,11 +78,12 @@ module fv_regional_mod
,start_regional_restart &
,dump_field &
,current_time_in_seconds &
- ,a_step, p_step, k_step, n_step, get_data_source
+ ,a_step, p_step, k_step, n_step, get_data_source &
+ ,write_full_fields
integer,parameter :: nhalo_data =4 &
,nhalo_model=3
-
+!
integer, public, parameter :: H_STAGGER = 1
integer, public, parameter :: U_STAGGER = 2
integer, public, parameter :: V_STAGGER = 3
@@ -105,11 +106,37 @@ module fv_regional_mod
! integer, parameter :: iend_nest = 1346
! integer, parameter :: jend_nest = 1290
+ integer,parameter :: nvars_core=7 & !<-- # of prognostic variables in restart file
+ ,nvars_tracers=8 !<-- # of prognostic variables in restart file
+
+ real,parameter :: blend_exp1=0.5,blend_exp2=10. !<-- Define the exponential dropoff of weights
+ ! for prescribed external values in the
+ ! blending rows inside the domain boundary.
real :: current_time_in_seconds
+!
integer,save :: ncid,next_time_to_read_bcs,npz,ntracers
- integer,save :: liq_water_index,sphum_index !<-- Locations of tracer vbls in the tracers array
+!
+ integer,save :: k_split,n_split
+!
integer,save :: bc_hour, ntimesteps_per_bc_update
-
+!
+ integer,save :: cld_amt_index & !<--
+ ,graupel_index & !
+ ,ice_water_index & ! Locations of
+ ,liq_water_index & ! tracer vbls
+ ,o3mr_index & ! in the tracers
+ ,rain_water_index & ! array.
+ ,snow_water_index & !
+ ,sphum_index !<--
+!
+ integer,save :: lbnd_x_tracers,lbnd_y_tracers & !<-- Local lower bounds of x,y for tracer arrays
+ ,ubnd_x_tracers,ubnd_y_tracers !<-- Local upper bounds of x,y for tracer arrays
+!
+ integer,save :: nrows_blend !<-- # of blending rows in the BC data files.
+!
+ real,save :: dt_atmos & !<-- The physics (large) timestep (sec)
+ ,dyn_timestep !<-- The dynamics timestep (sec)
+!
real(kind=R_GRID),dimension(:,:,:),allocatable :: agrid_reg & !<-- Lon/lat of cell centers
,grid_reg !<-- Lon/lat of cell corners
@@ -120,6 +147,11 @@ module fv_regional_mod
logical,save :: north_bc,south_bc,east_bc,west_bc &
,begin_regional_restart=.true.
+ character(len=50) :: filename_core='INPUT/fv_core.res.temp.nc'
+ character(len=50) :: filename_core_new='RESTART/fv_core.res.tile1_new.nc'
+ character(len=50) :: filename_tracers='INPUT/fv_tracer.res.temp.nc'
+ character(len=50) :: filename_tracers_new='RESTART/fv_tracer.res.tile1_new.nc'
+
type fv_regional_BC_variables
real,dimension(:,:,:),allocatable :: delp_BC, divgd_BC, u_BC, v_BC, uc_BC, vc_BC
real,dimension(:,:,:,:),allocatable :: q_BC
@@ -138,6 +170,16 @@ module fv_regional_mod
type(fv_regional_BC_variables) :: north, south, east, west
end type fv_domain_sides
+ type vars_2d
+ real,dimension(:,:),pointer :: ptr
+ character(len=10) :: name
+ end type vars_2d
+
+ type vars_3d
+ real,dimension(:,:,:),pointer :: ptr
+ character(len=10) :: name
+ end type vars_3d
+
type(fv_domain_sides),target,save :: BC_t0, BC_t1 !<-- Boundary values for all BC variables at successive times from the regional BC file
type(fv_regional_BC_variables),pointer,save :: bc_north_t0 &
@@ -153,6 +195,9 @@ module fv_regional_mod
type(fv_regional_bc_bounds_type),pointer,save :: regional_bounds
+ type(vars_3d),dimension(:),allocatable :: fields_core &
+ ,fields_tracers
+
real,parameter :: tice=273.16 &
,t_i0=15.
real, parameter :: c_liq = 4185.5 ! gfdl: heat capacity of liquid at 15 deg c
@@ -178,7 +223,7 @@ module fv_regional_mod
module procedure dump_field_2d
end interface dump_field
- integer,save :: bc_update_interval
+ integer,save :: bc_update_interval, nrows_blend_user
integer :: a_step, p_step, k_step, n_step
!
@@ -187,7 +232,7 @@ module fv_regional_mod
!-----------------------------------------------------------------------
!
- subroutine setup_regional_BC(Atm &
+ subroutine setup_regional_BC(Atm, dt_atmos &
,isd,ied,jsd,jed &
,npx,npy )
!
@@ -204,6 +249,8 @@ subroutine setup_regional_BC(Atm &
!---------------------
!
integer,intent(in) :: isd,ied,jsd,jed,npx,npy
+!
+ real,intent(in) :: dt_atmos !<-- The large (physics) timestep (sec)
!
type(fv_atmos_type),target,intent(inout) :: Atm !<-- Atm object for the current domain
!
@@ -211,9 +258,15 @@ subroutine setup_regional_BC(Atm &
!*** Local variables
!--------------------
!
- integer :: i,i_start,i_end,j,j_start,j_end,klev_out
+ integer :: dimid,i,i_start,i_end,j,j_start,j_end,klev_out &
+ ,nrows_bc_data,nrows_blend_in_data,sec
!
real :: ps1
+!
+ character(len=2) :: char2_1,char2_2
+ character(len=3) :: int_to_char
+ character(len=6) :: fmt='(i3.3)'
+ character(len=50) :: file_name
!
!-----------------------------------------------------------------------
!***********************************************************************
@@ -260,6 +313,7 @@ subroutine setup_regional_BC(Atm &
east_bc =.false.
west_bc =.false.
!
+! write(0,*)' enter setup_regional_BC isd=',isd,' ied=',ied,' jsd=',jsd,' jed=',jed
!-----------------------------------------------------------------------
!*** Which side(s) of the domain does this task lie on if any?
!-----------------------------------------------------------------------
@@ -282,18 +336,62 @@ subroutine setup_regional_BC(Atm &
!
bc_update_interval=Atm%flagstruct%bc_update_interval
!
- if(.not.(north_bc.or.south_bc.or.east_bc.or.west_bc))then
- return !<-- This task is not on the domain boundary so exit.
+ k_split=Atm%flagstruct%k_split
+ n_split=Atm%flagstruct%n_split
+!
+ dyn_timestep=dt_atmos/real(k_split*n_split)
+!
+!-----------------------------------------------------------------------
+!*** Is blending row data present in the BC file and if so how many
+!*** rows of data are there? All blending data that is present will
+!*** be read even if the user requests fewer rows be applied.
+!*** Construct the name of the regional BC file to be read.
+!*** We must know whether this is a standard BC file from chgres
+!*** or a new BC file generated from DA-updated data from enlarged
+!*** restart files that include the boundary rows.
+!-----------------------------------------------------------------------
+!
+ write(int_to_char,fmt) bc_hour
+ if(.not.Atm%flagstruct%regional_bcs_from_gsi)then
+ file_name='INPUT/gfs_bndy.tile7.'//int_to_char//'.nc' !<-- The standard BC file from chgres.
+ else
+ file_name='INPUT/gfs_bndy.tile7.'//int_to_char//'_gsi.nc' !<-- The DA-updated BC file.
+ endif
+!
+ if (is_master()) then
+ write(*,20011)trim(file_name)
+20011 format(' regional_bc_data file_name=',a)
endif
+!-----------------------------------------------------------------------
+!*** Open the regional BC file.
+!-----------------------------------------------------------------------
!
+ call check(nf90_open(file_name,nf90_nowrite,ncid)) !<-- Open the BC file; get the file ID.
+ if (is_master()) then
+ write(0,*)' opened BC file ',trim(file_name)
+ endif
!
!-----------------------------------------------------------------------
+!*** Check if the desired number of blending rows are present in
+!*** the boundary files.
+!-----------------------------------------------------------------------
!
- ntracers=Atm%ncnst - Atm%flagstruct%dnats !<-- # of advected tracers
- npz=Atm%npz !<-- # of layers in vertical configuration of integration
- klev_out=npz
+ nrows_blend_user=Atm%flagstruct%nrows_blend !<-- # of blending rows the user wnats to apply.
!
- regional_bounds=>Atm%regional_bc_bounds
+ call check(nf90_inq_dimid(ncid,'halo',dimid)) !<-- ID of the halo dimension.
+ call check(nf90_inquire_dimension(ncid,dimid,len=nrows_bc_data)) !<-- Total # of rows of BC data (bndry + blending)
+!
+ nrows_blend_in_data=nrows_bc_data-nhalo_data !<-- # of blending rows in the BC files.
+!
+ if(nrows_blend_user>nrows_blend_in_data)then !<-- User wants more blending rows than are in the BC file.
+ write(char2_1,'(I2.2)')nrows_blend_user
+ write(char2_2,'(I2.2)')nrows_blend_in_data
+ call mpp_error(FATAL,'User wants to use '//char2_1//' blending rows but only '//char2_2//' blending rows are in the BC file!')
+ else
+ nrows_blend=nrows_blend_in_data !<-- # of blending rows in the BC files.
+ endif
+!
+ call check(nf90_close(ncid)) !<-- Close the BC file for now.
!
!-----------------------------------------------------------------------
!*** Compute the index limits within the boundary region on each
@@ -305,8 +403,28 @@ subroutine setup_regional_BC(Atm &
!
call compute_regional_bc_indices(Atm%regional_bc_bounds)
!
- liq_water_index = get_tracer_index(MODEL_ATMOS, 'liq_wat')
- sphum_index = get_tracer_index(MODEL_ATMOS, 'sphum')
+ sphum_index =get_tracer_index(MODEL_ATMOS, 'sphum')
+ liq_water_index =get_tracer_index(MODEL_ATMOS, 'liq_wat')
+ ice_water_index =get_tracer_index(MODEL_ATMOS, 'ice_wat')
+ rain_water_index=get_tracer_index(MODEL_ATMOS, 'rainwat')
+ snow_water_index=get_tracer_index(MODEL_ATMOS, 'snowwat')
+ graupel_index =get_tracer_index(MODEL_ATMOS, 'graupel')
+ cld_amt_index =get_tracer_index(MODEL_ATMOS, 'cld_amt')
+ o3mr_index =get_tracer_index(MODEL_ATMOS, 'o3mr')
+!
+!-----------------------------------------------------------------------
+!
+ if(.not.(north_bc.or.south_bc.or.east_bc.or.west_bc))then
+ return !<-- This task is not on the domain boundary so exit.
+ endif
+!
+!-----------------------------------------------------------------------
+!
+ ntracers=Atm%ncnst - Atm%flagstruct%dnats !<-- # of advected tracers
+ npz=Atm%npz !<-- # of layers in vertical configuration of integration
+ klev_out=npz
+!
+ regional_bounds=>Atm%regional_bc_bounds
!
!-----------------------------------------------------------------------
!*** Allocate the objects that will hold the boundary variables
@@ -704,6 +822,9 @@ subroutine compute_regional_bc_indices(regional_bc_bounds)
!-----------------------------------------------------------------------
!*** These must reach one row beyond nhalo_model since we must
!*** surround the wind points on the cell edges with mass points.
+!
+!*** NOTE: The value of nrows_blend is the total number of
+!*** blending rows in the BC files.
!-----------------------------------------------------------------------
!
halo_diff=nhalo_data-nhalo_model
@@ -713,11 +834,11 @@ subroutine compute_regional_bc_indices(regional_bc_bounds)
!-----------
!
if (north_bc) then
- regional_bc_bounds%is_north=isd-1
- regional_bc_bounds%ie_north=ied+1
+ regional_bc_bounds%is_north=isd-1
+ regional_bc_bounds%ie_north=ied+1
!
- regional_bc_bounds%js_north=jsd-1
- regional_bc_bounds%je_north=0
+ regional_bc_bounds%js_north=jsd-1
+ regional_bc_bounds%je_north=nrows_blend
endif
!
!-----------
@@ -725,11 +846,11 @@ subroutine compute_regional_bc_indices(regional_bc_bounds)
!-----------
!
if (south_bc) then
- regional_bc_bounds%is_south=isd-1
- regional_bc_bounds%ie_south=ied+1
+ regional_bc_bounds%is_south=isd-1
+ regional_bc_bounds%ie_south=ied+1
!
- regional_bc_bounds%js_south=jed-nhalo_model+1
- regional_bc_bounds%je_south=jed+1
+ regional_bc_bounds%js_south=jed-nhalo_model-nrows_blend+1
+ regional_bc_bounds%je_south=jed+1
endif
!
!----------
@@ -737,18 +858,18 @@ subroutine compute_regional_bc_indices(regional_bc_bounds)
!----------
!
if (east_bc) then
- regional_bc_bounds%is_east=isd-1
- regional_bc_bounds%ie_east=0
+ regional_bc_bounds%is_east=isd-1
+ regional_bc_bounds%ie_east=nrows_blend
!
- regional_bc_bounds%js_east=jsd-1
- if(north_bc)then
- regional_bc_bounds%js_east=1
- endif
+ regional_bc_bounds%js_east=jsd-1
+ if(north_bc)then
+ regional_bc_bounds%js_east=1
+ endif
!
- regional_bc_bounds%je_east=jed+1
- if(south_bc)then
- regional_bc_bounds%je_east=jed-nhalo_model
- endif
+ regional_bc_bounds%je_east=jed+1
+ if(south_bc)then
+ regional_bc_bounds%je_east=jed-nhalo_model
+ endif
endif
!
!----------
@@ -756,18 +877,18 @@ subroutine compute_regional_bc_indices(regional_bc_bounds)
!----------
!
if (west_bc) then
- regional_bc_bounds%is_west=ied-nhalo_model+1
- regional_bc_bounds%ie_west=ied+1
+ regional_bc_bounds%is_west=ied-nhalo_model-nrows_blend+1
+ regional_bc_bounds%ie_west=ied+1
!
- regional_bc_bounds%js_west=jsd-1
- if(north_bc)then
- regional_bc_bounds%js_west=1
- endif
+ regional_bc_bounds%js_west=jsd-1
+ if(north_bc)then
+ regional_bc_bounds%js_west=1
+ endif
!
- regional_bc_bounds%je_west=jed+1
- if(south_bc)then
- regional_bc_bounds%je_west=jed-nhalo_model
- endif
+ regional_bc_bounds%je_west=jed+1
+ if(south_bc)then
+ regional_bc_bounds%je_west=jed-nhalo_model
+ endif
endif
!
!-----------------------------------------------------------------------
@@ -779,19 +900,17 @@ subroutine compute_regional_bc_indices(regional_bc_bounds)
!-----------
!
if (north_bc) then
- regional_bc_bounds%is_north_uvs=isd
- regional_bc_bounds%ie_north_uvs=ied
+ regional_bc_bounds%is_north_uvs=isd
+ regional_bc_bounds%ie_north_uvs=ied
!
- regional_bc_bounds%js_north_uvs=jsd
-!xxxxxx regional_bc_bounds%je_north_uvs=0
-!xxxxxx regional_bc_bounds%je_north_uvs=1
- regional_bc_bounds%je_north_uvs=1
+ regional_bc_bounds%js_north_uvs=jsd
+ regional_bc_bounds%je_north_uvs=nrows_blend+1
!
- regional_bc_bounds%is_north_uvw=isd
- regional_bc_bounds%ie_north_uvw=ied+1
+ regional_bc_bounds%is_north_uvw=isd
+ regional_bc_bounds%ie_north_uvw=ied+1
!
- regional_bc_bounds%js_north_uvw=jsd
- regional_bc_bounds%je_north_uvw=0
+ regional_bc_bounds%js_north_uvw=jsd
+ regional_bc_bounds%je_north_uvw=nrows_blend
endif
!
!-----------
@@ -799,18 +918,17 @@ subroutine compute_regional_bc_indices(regional_bc_bounds)
!-----------
!
if (south_bc) then
- regional_bc_bounds%is_south_uvs=isd
- regional_bc_bounds%ie_south_uvs=ied
+ regional_bc_bounds%is_south_uvs=isd
+ regional_bc_bounds%ie_south_uvs=ied
!
-!xxxxxregional_bc_bounds%js_south_uvs=jed-nhalo_model+2
- regional_bc_bounds%js_south_uvs=jed-nhalo_model+1
- regional_bc_bounds%je_south_uvs=jed+1
+ regional_bc_bounds%js_south_uvs=jed-nhalo_model-nrows_blend+1
+ regional_bc_bounds%je_south_uvs=jed+1
!
- regional_bc_bounds%is_south_uvw=isd
- regional_bc_bounds%ie_south_uvw=ied+1
+ regional_bc_bounds%is_south_uvw=isd
+ regional_bc_bounds%ie_south_uvw=ied+1
!
- regional_bc_bounds%js_south_uvw=jed-nhalo_model+1
- regional_bc_bounds%je_south_uvw=jed
+ regional_bc_bounds%js_south_uvw=jed-nhalo_model-nrows_blend+1
+ regional_bc_bounds%je_south_uvw=jed
endif
!
!----------
@@ -818,33 +936,31 @@ subroutine compute_regional_bc_indices(regional_bc_bounds)
!----------
!
if (east_bc) then
- regional_bc_bounds%is_east_uvs=isd
- regional_bc_bounds%ie_east_uvs=0
+ regional_bc_bounds%is_east_uvs=isd
+ regional_bc_bounds%ie_east_uvs=nrows_blend
!
- regional_bc_bounds%js_east_uvs=jsd
- if(north_bc)then
-!xxxx regional_bc_bounds%js_east_uvs=2 !<-- north side of cell at j=2 (north bdry contains north side of j=1)
- regional_bc_bounds%js_east_uvs=1 !<-- north side of cell at j=1 (north bdry contains north side of j=1)
- endif
+ regional_bc_bounds%js_east_uvs=jsd
+ if(north_bc)then
+ regional_bc_bounds%js_east_uvs=1 !<-- north side of cell at j=1 (north bdry contains north side of j=1)
+ endif
!
- regional_bc_bounds%je_east_uvs=jed+1
- if(south_bc)then
-!xxxx regional_bc_bounds%je_east_uvs=jed-nhalo_model
- regional_bc_bounds%je_east_uvs=jed-nhalo_model+1
- endif
+ regional_bc_bounds%je_east_uvs=jed+1
+ if(south_bc)then
+ regional_bc_bounds%je_east_uvs=jed-nhalo_model+1
+ endif
!
-! regional_bc_bounds%is_east_uvw=isd-1
- regional_bc_bounds%is_east_uvw=isd
- regional_bc_bounds%ie_east_uvw=0 !<-- east side of cell at i=0
+! regional_bc_bounds%is_east_uvw=isd-1
+ regional_bc_bounds%is_east_uvw=isd
+ regional_bc_bounds%ie_east_uvw=nrows_blend !<-- east side of cell at i=nrows_blend
!
- regional_bc_bounds%js_east_uvw=jsd
- if(north_bc)then
- regional_bc_bounds%js_east_uvw=1
- endif
- regional_bc_bounds%je_east_uvw=jed
- if(south_bc)then
- regional_bc_bounds%je_east_uvw=jed-nhalo_model
- endif
+ regional_bc_bounds%js_east_uvw=jsd
+ if(north_bc)then
+ regional_bc_bounds%js_east_uvw=1
+ endif
+ regional_bc_bounds%je_east_uvw=jed
+ if(south_bc)then
+ regional_bc_bounds%je_east_uvw=jed-nhalo_model
+ endif
endif
!
!----------
@@ -852,33 +968,31 @@ subroutine compute_regional_bc_indices(regional_bc_bounds)
!----------
!
if (west_bc) then
- regional_bc_bounds%is_west_uvs=ied-nhalo_model+1
- regional_bc_bounds%ie_west_uvs=ied
+ regional_bc_bounds%is_west_uvs=ied-nhalo_model-nrows_blend+1
+ regional_bc_bounds%ie_west_uvs=ied
!
- regional_bc_bounds%js_west_uvs=jsd
- if(north_bc)then
-!xxxx regional_bc_bounds%js_west_uvs=2
- regional_bc_bounds%js_west_uvs=1
- endif
+ regional_bc_bounds%js_west_uvs=jsd
+ if(north_bc)then
+ regional_bc_bounds%js_west_uvs=1
+ endif
!
- regional_bc_bounds%je_west_uvs=jed+1
- if(south_bc)then
-!xxxx regional_bc_bounds%je_west_uvs=jed-nhalo_model
- regional_bc_bounds%je_west_uvs=jed-nhalo_model+1
- endif
+ regional_bc_bounds%je_west_uvs=jed+1
+ if(south_bc)then
+ regional_bc_bounds%je_west_uvs=jed-nhalo_model+1
+ endif
!
- regional_bc_bounds%is_west_uvw=ied-nhalo_model+2
- regional_bc_bounds%ie_west_uvw=ied+1
+ regional_bc_bounds%is_west_uvw=ied-nhalo_model-nrows_blend+1
+ regional_bc_bounds%ie_west_uvw=ied+1
!
- regional_bc_bounds%js_west_uvw=jsd
- if(north_bc)then
- regional_bc_bounds%js_west_uvw=1
- endif
+ regional_bc_bounds%js_west_uvw=jsd
+ if(north_bc)then
+ regional_bc_bounds%js_west_uvw=1
+ endif
!
- regional_bc_bounds%je_west_uvw=jed
- if(south_bc)then
- regional_bc_bounds%je_west_uvw=jed-nhalo_model
- endif
+ regional_bc_bounds%je_west_uvw=jed
+ if(south_bc)then
+ regional_bc_bounds%je_west_uvw=jed-nhalo_model
+ endif
endif
!
!-----------------------------------------------------------------------
@@ -914,14 +1028,15 @@ subroutine read_regional_lon_lat
!-----------------------------------------------------------------------
!
!-----------------------------------------------------------------------
-!*** Open the data file.
+!*** Open the grid data file.
!-----------------------------------------------------------------------
!
filename='INPUT/'//trim(grid_data)
!
- call check(nf90_open(filename,nf90_nowrite,ncid_grid)) !<-- Open the netcdf file; get the file ID.
+ call check(nf90_open(filename,nf90_nowrite,ncid_grid)) !<-- Open the grid data netcdf file; get the file ID.
+!
+ call mpp_error(NOTE,' opened grid file '//trim(filename))
!
-! write(0,*)' opened grid file',trim(filename)
!-----------------------------------------------------------------------
!*** The longitude and latitude are on the super grid. We need only
!*** the points on each corner of the grid cells which is every other
@@ -1011,14 +1126,15 @@ subroutine read_regional_filtered_topo
!-----------------------------------------------------------------------
!
!-----------------------------------------------------------------------
-!*** Get the name of the working directory. Open the data file.
+!*** Get the name of the working directory. Open the topography data
+!*** file.
!-----------------------------------------------------------------------
!
filename='INPUT/'//trim(oro_data)
if (is_master()) then
- write(*,23421)trim(filename)
-23421 format(' topo filename=',a)
+ write(*,23421)trim(filename)
+23421 format(' topo filename=',a)
endif
!
call check(nf90_open(filename,nf90_nowrite,ncid_oro)) !<-- Open the netcdf file; get the file ID.
@@ -1062,7 +1178,7 @@ end subroutine setup_regional_BC
!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
!-----------------------------------------------------------------------
!
- subroutine start_regional_cold_start(Atm, ak, bk, levp &
+ subroutine start_regional_cold_start(Atm, dt_atmos, ak, bk, levp &
,is ,ie ,js ,je &
,isd,ied,jsd,jed )
!
@@ -1082,6 +1198,7 @@ subroutine start_regional_cold_start(Atm, ak, bk, levp &
,isd,ied,jsd,jed & !<-- Memory limits of task subdomain
,levp
!
+ real,intent(in) :: dt_atmos !<-- The large (physics) timestep (sec)
real,intent(in) :: ak(1:levp+1), bk(1:levp+1)
!
!---------------------
@@ -1094,11 +1211,13 @@ subroutine start_regional_cold_start(Atm, ak, bk, levp &
!***********************************************************************
!-----------------------------------------------------------------------
!
-! get the source of the input data
+!-----------------------------------------------------------------------
+!*** Get the source of the input data
+!-----------------------------------------------------------------------
!
call get_data_source(data_source,Atm%flagstruct%regional)
!
- call setup_regional_BC(Atm &
+ call setup_regional_BC(Atm, dt_atmos &
,isd, ied, jsd, jed &
,Atm%npx, Atm%npy )
!
@@ -1113,6 +1232,16 @@ subroutine start_regional_cold_start(Atm, ak, bk, levp &
,Atm%regional_bc_bounds ) !
!
bc_hour=bc_hour+bc_update_interval
+!
+!-----------------------------------------------------------------------
+!*** If this is a DA run and the first BC file was updated by
+!*** the GSI then reset the gsi flag so that all subsequent
+!*** BC files are read normally.
+!-----------------------------------------------------------------------
+!
+ if(Atm%flagstruct%regional_bcs_from_gsi)then
+ Atm%flagstruct%regional_bcs_from_gsi=.false.
+ endif
!
call regional_bc_data(Atm, bc_hour & !<-- Fill time level t1
,is, ie, js, je & ! from the 2nd time level
@@ -1127,6 +1256,16 @@ subroutine start_regional_cold_start(Atm, ak, bk, levp &
enddo
!
!-----------------------------------------------------------------------
+!*** If the GSI will need a restart file that includes the
+!*** fields' boundary rows then create that file and define
+!*** its dimensions and variables.
+!-----------------------------------------------------------------------
+!
+ if(Atm%flagstruct%write_restart_with_bcs)then
+ call create_restart_with_bcs(Atm)
+ endif
+!
+!-----------------------------------------------------------------------
!
end subroutine start_regional_cold_start
!
@@ -1134,7 +1273,7 @@ end subroutine start_regional_cold_start
!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
!-----------------------------------------------------------------------
!
- subroutine start_regional_restart(Atm &
+ subroutine start_regional_restart(Atm, dt_atmos &
,isc,iec,jsc,jec &
,isd,ied,jsd,jed )
!
@@ -1149,6 +1288,8 @@ subroutine start_regional_restart(Atm &
!------------------------
!
type(fv_atmos_type),intent(inout) :: Atm !<-- Atm object for the current domain
+!
+ real,intent(in) :: dt_atmos !<-- The large (physics) timestep (sec)
!
integer ,intent(in) :: isc,iec,jsc,jec & !<-- Integration limits of task subdomain
,isd,ied,jsd,jed !<-- Memory limits of task subdomain
@@ -1183,31 +1324,59 @@ subroutine start_regional_restart(Atm &
endif
!
!-----------------------------------------------------------------------
+!*** Get the source of the input data.
+!-----------------------------------------------------------------------
+!
+ call get_data_source(data_source,Atm%flagstruct%regional)
+!
+!-----------------------------------------------------------------------
!*** Preliminary setup for the forecast.
!-----------------------------------------------------------------------
!
- call setup_regional_BC(Atm &
- ,isd, ied, jsd, jed &
- ,Atm%npx, Atm%npy )
+ call setup_regional_BC(Atm, dt_atmos &
+ ,isd, ied, jsd, jed &
+ ,Atm%npx, Atm%npy )
!
- allocate (wk2(levp+1,2))
- allocate (ak_in(levp+1)) !<-- Save the input vertical structure for
- allocate (bk_in(levp+1)) ! remapping BC updates during the forecast.
- call read_data('INPUT/gfs_ctrl.nc','vcoord',wk2, no_domain=.TRUE.)
- ak_in(1:levp+1) = wk2(1:levp+1,1)
- ak_in(1) = 1.e-9
- bk_in(1:levp+1) = wk2(1:levp+1,2)
- deallocate(wk2)
- bc_hour=nint(current_time_in_seconds/3600.)
+ allocate (wk2(levp+1,2))
+ allocate (ak_in(levp+1)) !<-- Save the input vertical structure for
+ allocate (bk_in(levp+1)) ! remapping BC updates during the forecast.
+ call read_data('INPUT/gfs_ctrl.nc','vcoord',wk2, no_domain=.TRUE.)
+ ak_in(1:levp+1) = wk2(1:levp+1,1)
+ ak_in(1) = 1.e-9
+ bk_in(1:levp+1) = wk2(1:levp+1,2)
+ deallocate(wk2)
+ bc_hour=nint(current_time_in_seconds/3600.)
!
!-----------------------------------------------------------------------
!*** Fill time level t1 from the BC file at the restart time.
!-----------------------------------------------------------------------
!
- call regional_bc_data(Atm, bc_hour &
- ,isc, iec, jsc, jec &
- ,isd, ied, jsd, jed &
- ,ak_in, bk_in )
+ call regional_bc_data(Atm, bc_hour &
+ ,isc, iec, jsc, jec &
+ ,isd, ied, jsd, jed &
+ ,ak_in, bk_in )
+!
+!-----------------------------------------------------------------------
+!*** If this is a DA run and the first BC file was updated by
+!*** the GSI then that file was read differently in the preceding
+!*** call to subroutine regional_bc_data. Now reset the gsi
+!*** flag so that all subsequent BC files are read normally.
+!-----------------------------------------------------------------------
+!
+ if(Atm%flagstruct%regional_bcs_from_gsi)then
+ Atm%flagstruct%regional_bcs_from_gsi=.false.
+ endif
+!
+!-----------------------------------------------------------------------
+!*** If the GSI will need a restart file that includes the
+!*** fields' boundary rows after this forecast or forecast
+!*** segment completes then create that file and define
+!*** its dimensions and variables.
+!-----------------------------------------------------------------------
+!
+ if(Atm%flagstruct%write_restart_with_bcs)then
+ call create_restart_with_bcs(Atm)
+ endif
!
!-----------------------------------------------------------------------
!
@@ -1348,11 +1517,14 @@ subroutine regional_bc_data(Atm,bc_hour &
integer :: is_input,ie_input,js_input,je_input
!
integer :: i_start,i_end,j_start,j_end
+!
+ integer :: nside,nt,index
!
real,dimension(:,:,:),allocatable :: ud,vd,uc,vc
!
real,dimension(:,:),allocatable :: ps_reg
- real,dimension(:,:,:),allocatable :: ps_input,t_input &
+ real,dimension(:,:,:),allocatable :: delp_input,delz_input &
+ ,ps_input,t_input &
,w_input,zh_input
real,dimension(:,:,:),allocatable :: u_s_input,v_s_input &
,u_w_input,v_w_input
@@ -1377,11 +1549,8 @@ subroutine regional_bc_data(Atm,bc_hour &
character(len=6) :: fmt='(i3.3)'
!
character(len=50) :: file_name
-!
- integer,save :: kount1=0,kount2=0
!
character(len=60) :: var_name_root
- integer :: nside,nt,index
logical :: required
!
logical :: call_remap
@@ -1397,7 +1566,6 @@ subroutine regional_bc_data(Atm,bc_hour &
if(.not.(north_bc.or.south_bc.or.east_bc.or.west_bc))then
return
endif
-!if (data_source == 'FV3GFS GAUSSIAN NEMSIO FILE')
!
!-----------------------------------------------------------------------
!
@@ -1405,21 +1573,31 @@ subroutine regional_bc_data(Atm,bc_hour &
!
!-----------------------------------------------------------------------
!*** Construct the name of the regional BC file to be read.
+!*** We must know whether this is a standard BC file from chgres
+!*** or a new BC file generated from DA-updated data from enlarged
+!*** restart files that include the boundary rows.
!-----------------------------------------------------------------------
!
write(int_to_char,fmt) bc_hour
- file_name='INPUT/gfs_bndy.tile7.'//int_to_char//'.nc'
+ if(.not.Atm%flagstruct%regional_bcs_from_gsi)then
+ file_name='INPUT/gfs_bndy.tile7.'//int_to_char//'.nc' !<-- The standard BC file from chgres.
+ else
+ file_name='INPUT/gfs_bndy.tile7.'//int_to_char//'_gsi.nc' !<-- The DA-updated BC file.
+ endif
!
if (is_master()) then
- write(*,22211)trim(file_name)
-22211 format(' regional_bc_data file_name=',a)
+ write(*,22211)trim(file_name)
+22211 format(' regional_bc_data file_name=',a)
endif
!-----------------------------------------------------------------------
!*** Open the regional BC file.
!*** Find the # of layers (klev_in) in the BC input.
!-----------------------------------------------------------------------
!
- call check(nf90_open(file_name,nf90_nowrite,ncid)) !<-- Open the netcdf file; get the file ID.
+ call check(nf90_open(file_name,nf90_nowrite,ncid)) !<-- Open the BC file; get the file ID.
+ if (is_master()) then
+ write(0,*)' opened BC file ',trim(file_name)
+ endif
!
call check(nf90_inq_dimid(ncid,'lev',dimid)) !<-- Get the vertical dimension's NetCDF ID.
call check(nf90_inquire_dimension(ncid,dimid,len=klev_in)) !<-- Get the vertical dimension's value (klev_in).
@@ -1436,11 +1614,17 @@ subroutine regional_bc_data(Atm,bc_hour &
allocate( ps_input(is_input:ie_input,js_input:je_input,1)) ; ps_input=real_snan !<-- Sfc pressure
allocate( t_input(is_input:ie_input,js_input:je_input,1:klev_in)) ; t_input=real_snan !<-- Sensible temperature
allocate( w_input(is_input:ie_input,js_input:je_input,1:klev_in)) ; w_input=real_snan !<-- Vertical velocity
- allocate( zh_input(is_input:ie_input,js_input:je_input,1:klev_in+1)) ; zh_input=real_snan !<-- Interface heights
allocate(u_s_input(is_input:ie_input,js_input:je_input,1:klev_in)) ; u_s_input=real_snan !<-- D-grid u component
allocate(v_s_input(is_input:ie_input,js_input:je_input,1:klev_in)) ; v_s_input=real_snan !<-- C-grid v component
allocate(u_w_input(is_input:ie_input,js_input:je_input,1:klev_in)) ; u_w_input=real_snan !<-- C-grid u component
allocate(v_w_input(is_input:ie_input,js_input:je_input,1:klev_in)) ; v_w_input=real_snan !<-- D-grid v component
+!
+ if(Atm%flagstruct%regional_bcs_from_gsi)then
+ allocate(delp_input(is_input:ie_input,js_input:je_input,1:klev_in)) ; delp_input=real_snan !<-- Lyr pressure depth (Pa)
+ allocate(delz_input(is_input:ie_input,js_input:je_input,1:klev_in)) ; delz_input=real_snan !<-- Lyr geometric depth (m)
+ else
+ allocate( zh_input(is_input:ie_input,js_input:je_input,1:klev_in+1)) ; zh_input=real_snan !<-- Lyr interface heights (m)
+ endif
!
allocate(tracers_input(is_input:ie_input,js_input:je_input,klev_in,ntracers)) ; tracers_input=real_snan
!
@@ -1479,14 +1663,15 @@ subroutine regional_bc_data(Atm,bc_hour &
!*** Interface heights
!-----------------------
!
- nlev=klev_in+1
- var_name_root='zh'
- call read_regional_bc_file(is_input,ie_input,js_input,je_input &
- ,nlev &
- ,ntracers &
-! ,Atm%regional_bc_bounds &
- ,var_name_root &
- ,array_3d=zh_input)
+ if(.not.Atm%flagstruct%regional_bcs_from_gsi)then
+ nlev=klev_in+1
+ var_name_root='zh'
+ call read_regional_bc_file(is_input,ie_input,js_input,je_input &
+ ,nlev &
+ ,ntracers &
+ ,var_name_root &
+ ,array_3d=zh_input)
+ endif
!
!--------------------------
!*** Sensible temperature
@@ -1554,9 +1739,31 @@ subroutine regional_bc_data(Atm,bc_hour &
! ,Atm%regional_bc_bounds &
,var_name_root &
,array_3d=v_w_input)
-!----------------------
-!*** tracers
-!-----------------------
+!
+!-----------------------------------------------------------------------
+!*** If this is a DA-updated BC file then also read in the layer
+!*** pressure depths.
+!-----------------------------------------------------------------------
+!
+ if(Atm%flagstruct%regional_bcs_from_gsi)then
+ nlev=klev_in
+ var_name_root='delp'
+ call read_regional_bc_file(is_input,ie_input,js_input,je_input &
+ ,nlev &
+ ,ntracers &
+ ,var_name_root &
+ ,array_3d=delp_input)
+ var_name_root='delz'
+ call read_regional_bc_file(is_input,ie_input,js_input,je_input &
+ ,nlev &
+ ,ntracers &
+ ,var_name_root &
+ ,array_3d=delz_input)
+ endif
+!
+!-------------
+!*** Tracers
+!-------------
nlev=klev_in
!
@@ -1585,19 +1792,23 @@ subroutine regional_bc_data(Atm,bc_hour &
enddo
!
!-----------------------------------------------------------------------
-!*** We now have the boundary variables from the BC file on the
-!*** levels of the input data. Before remapping the 3-D variables
-!*** from the input levels to the model integration levels we will
-!*** simply copy the 2-D sfc pressure (ps) into the model array.
+!*** For a DA-updated BC file we can simply transfer the data
+!*** from the *_input arrays into the model's boundary arrays
+!*** since they came out of restart files. Otherwise proceed
+!*** with vertical remapping from input layers to model forecast
+!*** layers and rotate the winds from geographic lat/lon to the
+!*** integration grid.
!-----------------------------------------------------------------------
!
-! do j=jsd,jed
-! do i=isd,ied
-! Atm%ps(i,j)=ps(i,j)
-! enddo
-! enddo
+ data_to_BC: if(Atm%flagstruct%regional_bcs_from_gsi)then !<-- Fill BC arrays directly from the BC file data
+!
+!-----------------------------------------------------------------------
+!
+ call fill_BC_for_DA
+!
+!-----------------------------------------------------------------------
!
-! deallocate(ps%north,ps%south,ps%east,ps%west)
+ else !<-- Rotate winds and vertically remap BC file data
!
!-----------------------------------------------------------------------
!*** One final array needs to be allocated. It is the sfc pressure
@@ -1607,7 +1818,7 @@ subroutine regional_bc_data(Atm,bc_hour &
!*** the integration levels.
!-----------------------------------------------------------------------
!
- allocate(ps_reg(is_input:ie_input,js_input:je_input)) ; ps_reg=-9999999 ! for now don't set to snan until remap dwinds is changed
+ allocate(ps_reg(is_input:ie_input,js_input:je_input)) ; ps_reg=-9999999 ! for now don't set to snan until remap dwinds is changed
!
!-----------------------------------------------------------------------
!*** We have the boundary variables from the BC file on the levels
@@ -1620,76 +1831,76 @@ subroutine regional_bc_data(Atm,bc_hour &
!-----------------------------------------------------------------------
!
!-----------------------------------------------------------------------
- sides_scalars: do nside=1,4
+ sides_scalars: do nside=1,4
!-----------------------------------------------------------------------
!
- call_remap=.false.
+ call_remap=.false.
!
- if(nside==1)then
- if(north_bc)then
- call_remap=.true.
- side='north'
- bc_side_t1=>BC_t1%north
+ if(nside==1)then
+ if(north_bc)then
+ call_remap=.true.
+ side='north'
+ bc_side_t1=>BC_t1%north
+ endif
endif
- endif
!
- if(nside==2)then
- if(south_bc)then
- call_remap=.true.
- side='south'
- bc_side_t1=>BC_t1%south
+ if(nside==2)then
+ if(south_bc)then
+ call_remap=.true.
+ side='south'
+ bc_side_t1=>BC_t1%south
+ endif
endif
- endif
!
- if(nside==3)then
- if(east_bc)then
- call_remap=.true.
- side='east '
- bc_side_t1=>BC_t1%east
+ if(nside==3)then
+ if(east_bc)then
+ call_remap=.true.
+ side='east '
+ bc_side_t1=>BC_t1%east
+ endif
endif
- endif
!
- if(nside==4)then
- if(west_bc)then
- call_remap=.true.
- side='west '
- bc_side_t1=>BC_t1%west
+ if(nside==4)then
+ if(west_bc)then
+ call_remap=.true.
+ side='west '
+ bc_side_t1=>BC_t1%west
+ endif
endif
- endif
!
- if(call_remap)then
- call remap_scalar_nggps_regional_bc(Atm &
- ,side &
+ if(call_remap)then
+ call remap_scalar_nggps_regional_bc(Atm &
+ ,side &
- ,isd,ied,jsd,jed & !<-- Atm array indices w/halo
+ ,isd,ied,jsd,jed & !<-- Atm array indices w/halo
- ,is_input & !<--
- ,ie_input & ! Input array
- ,js_input & ! index limits.
- ,je_input & !<--
+ ,is_input & !<--
+ ,ie_input & ! Input array
+ ,js_input & ! index limits.
+ ,je_input & !<--
- ,klev_in, klev_out &
- ,ntracers &
- ,ak, bk &
+ ,klev_in, klev_out &
+ ,ntracers &
+ ,ak, bk &
- ,ps_input & !<--
- ,t_input & ! BC vbls
- ,tracers_input & ! on input
- ,w_input & ! model levels
- ,zh_input & !<--
+ ,ps_input & !<--
+ ,t_input & ! BC vbls
+ ,tracers_input & ! on input
+ ,w_input & ! model levels
+ ,zh_input & !<--
- ,phis_reg & !<-- Filtered topography
+ ,phis_reg & !<-- Filtered topography
- ,ps_reg & !<-- Derived FV3 psfc in regional domain boundary region
+ ,ps_reg & !<-- Derived FV3 psfc in regional domain boundary region
- ,bc_side_t1 ) !<-- BC vbls on final integration levels
+ ,bc_side_t1 ) !<-- BC vbls on final integration levels
!
- call set_delp_and_tracers(bc_side_t1,Atm%npz,Atm%flagstruct%nwat)
+ call set_delp_and_tracers(bc_side_t1,Atm%npz,Atm%flagstruct%nwat)
!
- endif
+ endif
!
!-----------------------------------------------------------------------
- enddo sides_scalars
+ enddo sides_scalars
!-----------------------------------------------------------------------
!
!-----------------------------------------------------------------------
@@ -1699,43 +1910,43 @@ subroutine regional_bc_data(Atm,bc_hour &
!-----------------------------------------------------------------------
!
!-----------------------------------------------------------------------
-!*** Transform the D-grid wind components on the north side of
+!*** Transform the D-grid wind components on the four sides of
!*** the regional domain then remap them from the input levels
!*** to the integration levels.
!-----------------------------------------------------------------------
!
#ifdef USE_FMS_READ
- isc2 = 2*(isd-1+nhalo_data)-1
- iec2 = 2*(ied+2+nhalo_data)-1
- jsc2 = 2*(jsd-1+nhalo_data)-1
- jec2 = 2*(jed+2+nhalo_data)-1
- allocate(tmpx(isc2:iec2, jsc2:jec2)) ; tmpx=dbl_snan
- allocate(tmpy(isc2:iec2, jsc2:jec2)) ; tmpy=dbl_snan
- start = 1; nread = 1
- start(1) = isc2; nread(1) = iec2 - isc2 + 1
- start(2) = jsc2; nread(2) = jec2 - jsc2 + 1
- call read_data("INPUT/grid.tile7.halo4.nc", 'x', tmpx, start, nread, no_domain=.TRUE.)
- call read_data("INPUT/grid.tile7.halo4.nc", 'y', tmpy, start, nread, no_domain=.TRUE.)
-
- allocate(reg_grid(isd-1:ied+2,jsd-1:jed+2,1:2)) ; reg_grid=dbl_snan
- do j = jsd-1, jed+2
- do i = isd-1, ied+2
- reg_grid(i,j,1) = tmpx(2*(i+nhalo_data)-1, 2*(j+nhalo_data)-1)*pi/180.
- reg_grid(i,j,2) = tmpy(2*(i+nhalo_data)-1, 2*(j+nhalo_data)-1)*pi/180.
- if ( reg_grid(i,j,1) /= grid_reg(i,j,1) ) then
- write(0,*)' reg_grid(i,j,1) /= grid_reg(i,j,1) ',i,j, reg_grid(i,j,1),grid_reg(i,j,1)
- endif
- enddo
- enddo
+ isc2 = 2*(isd-1+nhalo_data)-1
+ iec2 = 2*(ied+2+nhalo_data)-1
+ jsc2 = 2*(jsd-1+nhalo_data)-1
+ jec2 = 2*(jed+2+nhalo_data)-1
+ allocate(tmpx(isc2:iec2, jsc2:jec2)) ; tmpx=dbl_snan
+ allocate(tmpy(isc2:iec2, jsc2:jec2)) ; tmpy=dbl_snan
+ start = 1; nread = 1
+ start(1) = isc2; nread(1) = iec2 - isc2 + 1
+ start(2) = jsc2; nread(2) = jec2 - jsc2 + 1
+ call read_data("INPUT/grid.tile7.halo4.nc", 'x', tmpx, start, nread, no_domain=.TRUE.)
+ call read_data("INPUT/grid.tile7.halo4.nc", 'y', tmpy, start, nread, no_domain=.TRUE.)
+
+ allocate(reg_grid(isd-1:ied+2,jsd-1:jed+2,1:2)) ; reg_grid=dbl_snan
+ do j = jsd-1, jed+2
+ do i = isd-1, ied+2
+ reg_grid(i,j,1) = tmpx(2*(i+nhalo_data)-1, 2*(j+nhalo_data)-1)*pi/180.
+ reg_grid(i,j,2) = tmpy(2*(i+nhalo_data)-1, 2*(j+nhalo_data)-1)*pi/180.
+ if ( reg_grid(i,j,1) /= grid_reg(i,j,1) ) then
+ write(0,*)' reg_grid(i,j,1) /= grid_reg(i,j,1) ',i,j, reg_grid(i,j,1),grid_reg(i,j,1)
+ endif
+ enddo
+ enddo
- allocate(reg_agrid(isd-1:ied+1,jsd-1:jed+1,1:2)) ; reg_agrid=dbl_snan
- do j=jsd-1,jed+1
- do i=isd-1,ied+1
- call cell_center2(reg_grid(i,j, 1:2), reg_grid(i+1,j, 1:2), &
- reg_grid(i,j+1,1:2), reg_grid(i+1,j+1,1:2), &
- reg_agrid(i,j,1:2) )
- enddo
- enddo
+ allocate(reg_agrid(isd-1:ied+1,jsd-1:jed+1,1:2)) ; reg_agrid=dbl_snan
+ do j=jsd-1,jed+1
+ do i=isd-1,ied+1
+ call cell_center2(reg_grid(i,j, 1:2), reg_grid(i+1,j, 1:2), &
+ reg_grid(i,j+1,1:2), reg_grid(i+1,j+1,1:2), &
+ reg_agrid(i,j,1:2) )
+ enddo
+ enddo
#endif
!
!-----------------------------------------------------------------------
@@ -1743,156 +1954,156 @@ subroutine regional_bc_data(Atm,bc_hour &
!-----------------------------------------------------------------------
!
!-----------------------------------------------------------------------
- sides_winds: do nside=1,4
+ sides_winds: do nside=1,4
!-----------------------------------------------------------------------
!
- call_remap=.false.
+ call_remap=.false.
- if(nside==1)then
- if(north_bc)then
- call_remap=.true.
- bc_side_t1=>BC_t1%north
-!
- is_u=Atm%regional_bc_bounds%is_north_uvs
- ie_u=Atm%regional_bc_bounds%ie_north_uvs
- js_u=Atm%regional_bc_bounds%js_north_uvs
- je_u=Atm%regional_bc_bounds%je_north_uvs
-!
- is_v=Atm%regional_bc_bounds%is_north_uvw
- ie_v=Atm%regional_bc_bounds%ie_north_uvw
- js_v=Atm%regional_bc_bounds%js_north_uvw
- je_v=Atm%regional_bc_bounds%je_north_uvw
+ if(nside==1)then
+ if(north_bc)then
+ call_remap=.true.
+ bc_side_t1=>BC_t1%north
+!
+ is_u=Atm%regional_bc_bounds%is_north_uvs
+ ie_u=Atm%regional_bc_bounds%ie_north_uvs
+ js_u=Atm%regional_bc_bounds%js_north_uvs
+ je_u=Atm%regional_bc_bounds%je_north_uvs
+!
+ is_v=Atm%regional_bc_bounds%is_north_uvw
+ ie_v=Atm%regional_bc_bounds%ie_north_uvw
+ js_v=Atm%regional_bc_bounds%js_north_uvw
+ je_v=Atm%regional_bc_bounds%je_north_uvw
+ endif
endif
- endif
-!
- if(nside==2)then
- if(south_bc)then
- call_remap=.true.
- bc_side_t1=>BC_t1%south
!
- is_u=Atm%regional_bc_bounds%is_south_uvs
- ie_u=Atm%regional_bc_bounds%ie_south_uvs
- js_u=Atm%regional_bc_bounds%js_south_uvs
- je_u=Atm%regional_bc_bounds%je_south_uvs
-!
- is_v=Atm%regional_bc_bounds%is_south_uvw
- ie_v=Atm%regional_bc_bounds%ie_south_uvw
- js_v=Atm%regional_bc_bounds%js_south_uvw
- je_v=Atm%regional_bc_bounds%je_south_uvw
+ if(nside==2)then
+ if(south_bc)then
+ call_remap=.true.
+ bc_side_t1=>BC_t1%south
+!
+ is_u=Atm%regional_bc_bounds%is_south_uvs
+ ie_u=Atm%regional_bc_bounds%ie_south_uvs
+ js_u=Atm%regional_bc_bounds%js_south_uvs
+ je_u=Atm%regional_bc_bounds%je_south_uvs
+!
+ is_v=Atm%regional_bc_bounds%is_south_uvw
+ ie_v=Atm%regional_bc_bounds%ie_south_uvw
+ js_v=Atm%regional_bc_bounds%js_south_uvw
+ je_v=Atm%regional_bc_bounds%je_south_uvw
+ endif
endif
- endif
!
- if(nside==3)then
- if(east_bc)then
- call_remap=.true.
- bc_side_t1=>BC_t1%east
+ if(nside==3)then
+ if(east_bc)then
+ call_remap=.true.
+ bc_side_t1=>BC_t1%east
!
- is_u=Atm%regional_bc_bounds%is_east_uvs
- ie_u=Atm%regional_bc_bounds%ie_east_uvs
- js_u=Atm%regional_bc_bounds%js_east_uvs
- je_u=Atm%regional_bc_bounds%je_east_uvs
+ is_u=Atm%regional_bc_bounds%is_east_uvs
+ ie_u=Atm%regional_bc_bounds%ie_east_uvs
+ js_u=Atm%regional_bc_bounds%js_east_uvs
+ je_u=Atm%regional_bc_bounds%je_east_uvs
!
- is_v=Atm%regional_bc_bounds%is_east_uvw
- ie_v=Atm%regional_bc_bounds%ie_east_uvw
- js_v=Atm%regional_bc_bounds%js_east_uvw
- je_v=Atm%regional_bc_bounds%je_east_uvw
+ is_v=Atm%regional_bc_bounds%is_east_uvw
+ ie_v=Atm%regional_bc_bounds%ie_east_uvw
+ js_v=Atm%regional_bc_bounds%js_east_uvw
+ je_v=Atm%regional_bc_bounds%je_east_uvw
+ endif
endif
- endif
!
- if(nside==4)then
- if(west_bc)then
- call_remap=.true.
- bc_side_t1=>BC_t1%west
+ if(nside==4)then
+ if(west_bc)then
+ call_remap=.true.
+ bc_side_t1=>BC_t1%west
!
- is_u=Atm%regional_bc_bounds%is_west_uvs
- ie_u=Atm%regional_bc_bounds%ie_west_uvs
- js_u=Atm%regional_bc_bounds%js_west_uvs
- je_u=Atm%regional_bc_bounds%je_west_uvs
+ is_u=Atm%regional_bc_bounds%is_west_uvs
+ ie_u=Atm%regional_bc_bounds%ie_west_uvs
+ js_u=Atm%regional_bc_bounds%js_west_uvs
+ je_u=Atm%regional_bc_bounds%je_west_uvs
!
- is_v=Atm%regional_bc_bounds%is_west_uvw
- ie_v=Atm%regional_bc_bounds%ie_west_uvw
- js_v=Atm%regional_bc_bounds%js_west_uvw
- je_v=Atm%regional_bc_bounds%je_west_uvw
+ is_v=Atm%regional_bc_bounds%is_west_uvw
+ ie_v=Atm%regional_bc_bounds%ie_west_uvw
+ js_v=Atm%regional_bc_bounds%js_west_uvw
+ je_v=Atm%regional_bc_bounds%je_west_uvw
+ endif
endif
- endif
!
- if(call_remap)then
+ if(call_remap)then
!
- allocate(ud(is_u:ie_u,js_u:je_u,1:nlev)) ; ud=real_snan
- allocate(vd(is_v:ie_v,js_v:je_v,1:nlev)) ; vd=real_snan
- allocate(vc(is_u:ie_u,js_u:je_u,1:nlev)) ; vc=real_snan
- allocate(uc(is_v:ie_v,js_v:je_v,1:nlev)) ; uc=real_snan
-!
- do k=1,nlev
- do j=js_u,je_u
- do i=is_u,ie_u
- p1(:) = grid_reg(i, j,1:2)
- p2(:) = grid_reg(i+1,j,1:2)
- call mid_pt_sphere(p1, p2, p3)
- call get_unit_vect2(p1, p2, e1)
- call get_latlon_vector(p3, ex, ey)
- ud(i,j,k) = u_s_input(i,j,k)*inner_prod(e1,ex)+v_s_input(i,j,k)*inner_prod(e1,ey)
- p4(:) = agrid_reg(i,j,1:2) ! cell centroid
- call get_unit_vect2(p3, p4, e2) !C-grid V-wind unit vector
- vc(i,j,k) = u_s_input(i,j,k)*inner_prod(e2,ex)+v_s_input(i,j,k)*inner_prod(e2,ey)
- enddo
- enddo
+ allocate(ud(is_u:ie_u,js_u:je_u,1:nlev)) ; ud=real_snan
+ allocate(vd(is_v:ie_v,js_v:je_v,1:nlev)) ; vd=real_snan
+ allocate(vc(is_u:ie_u,js_u:je_u,1:nlev)) ; vc=real_snan
+ allocate(uc(is_v:ie_v,js_v:je_v,1:nlev)) ; uc=real_snan
!
- do j=js_v,je_v
- do i=is_v,ie_v
- p1(:) = grid_reg(i,j ,1:2)
- p2(:) = grid_reg(i,j+1,1:2)
+ do k=1,nlev
+ do j=js_u,je_u
+ do i=is_u,ie_u
+ p1(:) = grid_reg(i, j,1:2)
+ p2(:) = grid_reg(i+1,j,1:2)
call mid_pt_sphere(p1, p2, p3)
- call get_unit_vect2(p1, p2, e2)
+ call get_unit_vect2(p1, p2, e1)
call get_latlon_vector(p3, ex, ey)
- vd(i,j,k) = u_w_input(i,j,k)*inner_prod(e2,ex)+v_w_input(i,j,k)*inner_prod(e2,ey)
+ ud(i,j,k) = u_s_input(i,j,k)*inner_prod(e1,ex)+v_s_input(i,j,k)*inner_prod(e1,ey)
p4(:) = agrid_reg(i,j,1:2) ! cell centroid
- call get_unit_vect2(p3, p4, e1) !C-grid U-wind unit vector
- uc(i,j,k) = u_w_input(i,j,k)*inner_prod(e1,ex)+v_w_input(i,j,k)*inner_prod(e1,ey)
+ call get_unit_vect2(p3, p4, e2) !C-grid V-wind unit vector
+ vc(i,j,k) = u_s_input(i,j,k)*inner_prod(e2,ex)+v_s_input(i,j,k)*inner_prod(e2,ey)
+ enddo
+ enddo
+!
+ do j=js_v,je_v
+ do i=is_v,ie_v
+ p1(:) = grid_reg(i,j ,1:2)
+ p2(:) = grid_reg(i,j+1,1:2)
+ call mid_pt_sphere(p1, p2, p3)
+ call get_unit_vect2(p1, p2, e2)
+ call get_latlon_vector(p3, ex, ey)
+ vd(i,j,k) = u_w_input(i,j,k)*inner_prod(e2,ex)+v_w_input(i,j,k)*inner_prod(e2,ey)
+ p4(:) = agrid_reg(i,j,1:2) ! cell centroid
+ call get_unit_vect2(p3, p4, e1) !C-grid U-wind unit vector
+ uc(i,j,k) = u_w_input(i,j,k)*inner_prod(e1,ex)+v_w_input(i,j,k)*inner_prod(e1,ey)
+ enddo
enddo
enddo
- enddo
!
- call remap_dwinds_regional_bc(Atm &
-
- ,is_input & !<--
- ,ie_input & ! Index limits for scalars
- ,js_input & ! at center of north BC region grid cells.
- ,je_input & !<--
+ call remap_dwinds_regional_bc(Atm &
- ,is_u & !<--
- ,ie_u & ! Index limits for u component
- ,js_u & ! on north edge of BC region grid cells.
- ,je_u & !<--
+ ,is_input & !<--
+ ,ie_input & ! Index limits for scalars
+ ,js_input & ! at center of north BC region grid cells.
+ ,je_input & !<--
- ,is_v & !<--
- ,ie_v & ! Index limits for v component
- ,js_v & ! on north edge of BC region grid cells.
- ,je_v & !<--
+ ,is_u & !<--
+ ,ie_u & ! Index limits for u component
+ ,js_u & ! on north edge of BC region grid cells.
+ ,je_u & !<--
- ,klev_in, klev_out & !<-- data / model levels
- ,ak, bk &
+ ,is_v & !<--
+ ,ie_v & ! Index limits for v component
+ ,js_v & ! on north edge of BC region grid cells.
+ ,je_v & !<--
- ,ps_reg & !<-- BC values of sfc pressure
- ,ud ,vd & !<-- BC values of D-grid u and v
- ,uc ,vc & !<-- BC values of C-grid u and v
- ,bc_side_t1 ) !<-- North BC vbls on final integration levels
+ ,klev_in, klev_out & !<-- data / model levels
+ ,ak, bk &
+ ,ps_reg & !<-- BC values of sfc pressure
+ ,ud ,vd & !<-- BC values of D-grid u and v
+ ,uc ,vc & !<-- BC values of C-grid u and v
+ ,bc_side_t1 ) !<-- North BC vbls on final integration levels
!
- deallocate(ud,vd,uc,vc)
+ deallocate(ud,vd,uc,vc)
!
- endif
+ endif
!
!-----------------------------------------------------------------------
- enddo sides_winds
+ enddo sides_winds
!-----------------------------------------------------------------------
+!
+ endif data_to_BC
!
!-----------------------------------------------------------------------
!*** Close the boundary file.
!-----------------------------------------------------------------------
!
call check(nf90_close(ncid))
-! write(0,*)' closed BC netcdf file'
!
!-----------------------------------------------------------------------
!*** Deallocate working arrays.
@@ -1926,6 +2137,12 @@ subroutine regional_bc_data(Atm,bc_hour &
if(allocated(v_w_input))then
deallocate(v_w_input)
endif
+ if(allocated(delp_input))then
+ deallocate(delp_input)
+ endif
+ if(allocated(delz_input))then
+ deallocate(delz_input)
+ endif
!
!-----------------------------------------------------------------------
!*** Fill the remaining boundary arrays starting with the divergence.
@@ -1975,12 +2192,290 @@ subroutine regional_bc_data(Atm,bc_hour &
!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
!-----------------------------------------------------------------------
!
- subroutine fill_divgd_BC
+ subroutine fill_BC_for_DA
!
!-----------------------------------------------------------------------
-!*** For now fill the boundary divergence with zero.
+!*** Transfer the input boundary data directly into the BC object.
!-----------------------------------------------------------------------
- implicit none
+!
+!---------------------
+!*** Local variables
+!---------------------
+!
+ integer :: i,j,k,n
+!
+!-----------------------------------------------------------------------
+!***********************************************************************
+!-----------------------------------------------------------------------
+!
+!-----------------------------------------------------------------------
+!*** Since corner tasks are on more than one side we cannot
+!*** generalize the transfer of data into a given side's
+!*** arrays. Do each side separately.
+!
+!*** Simply obtain the loop limits from the bounds of one of the
+!*** BC arrays to be filled.
+!-----------------------------------------------------------------------
+!
+!-----------
+!*** North
+!-----------
+!
+ if(north_bc)then
+!
+ is_input=lbound(BC_t1%north%delp_BC,1) !<--
+ ie_input=ubound(BC_t1%north%delp_BC,1) ! Index limits for
+ js_input=lbound(BC_t1%north%delp_BC,2) ! mass variables.
+ je_input=ubound(BC_t1%north%delp_BC,2) !<--
+!
+ do k=1,klev_in
+ do j=js_input,je_input
+ do i=is_input,ie_input
+ BC_t1%north%delp_BC(i,j,k)=delp_input(i,j,k)
+ BC_t1%north%pt_BC(i,j,k)=t_input(i,j,k)
+ BC_t1%north%w_BC(i,j,k)=w_input(i,j,k)
+ BC_t1%north%delz_BC(i,j,k)=delz_input(i,j,k)
+ enddo
+ enddo
+ enddo
+!
+ do n=1,ntracers
+ do k=1,klev_in
+ do j=js_input,je_input
+ do i=is_input,ie_input
+ BC_t1%north%q_BC(i,j,k,n)=tracers_input(i,j,k,n)
+ enddo
+ enddo
+ enddo
+ enddo
+!
+ is_input=lbound(BC_t1%north%u_BC,1) !<--
+ ie_input=ubound(BC_t1%north%u_BC,1) ! Index limits for
+ js_input=lbound(BC_t1%north%u_BC,2) ! D-grid u and C-grid v.
+ je_input=ubound(BC_t1%north%u_BC,2) !<--
+!
+ do k=1,klev_in
+ do j=js_input,je_input
+ do i=is_input,ie_input
+ BC_t1%north%u_BC(i,j,k)=u_s_input(i,j,k)
+ BC_t1%north%vc_BC(i,j,k)=v_s_input(i,j,k)
+ enddo
+ enddo
+ enddo
+!
+ is_input=lbound(BC_t1%north%v_BC,1) !<--
+ ie_input=ubound(BC_t1%north%v_BC,1) ! Index limits for
+ js_input=lbound(BC_t1%north%v_BC,2) ! D-grid v and C-grid u.
+ je_input=ubound(BC_t1%north%v_BC,2) !<--
+!
+ do k=1,klev_in
+ do j=js_input,je_input
+ do i=is_input,ie_input
+ BC_t1%north%v_BC(i,j,k)=v_w_input(i,j,k)
+ BC_t1%north%uc_BC(i,j,k)=u_w_input(i,j,k)
+ enddo
+ enddo
+ enddo
+!
+ endif
+!
+!-----------
+!*** South
+!-----------
+!
+ if(south_bc)then
+ is_input=lbound(BC_t1%south%delp_BC,1) !<---
+ ie_input=ubound(BC_t1%south%delp_BC,1) ! Index limits for
+ js_input=lbound(BC_t1%south%delp_BC,2) ! mass variables.
+ je_input=ubound(BC_t1%south%delp_BC,2) !<--
+!
+ do k=1,klev_in
+ do j=js_input,je_input
+ do i=is_input,ie_input
+ BC_t1%south%delp_BC(i,j,k)=delp_input(i,j,k)
+ BC_t1%south%pt_BC(i,j,k)=t_input(i,j,k)
+ BC_t1%south%w_BC(i,j,k)=w_input(i,j,k)
+ BC_t1%south%delz_BC(i,j,k)=delz_input(i,j,k)
+ enddo
+ enddo
+ enddo
+!
+ do n=1,ntracers
+ do k=1,klev_in
+ do j=js_input,je_input
+ do i=is_input,ie_input
+ BC_t1%south%q_BC(i,j,k,n)=tracers_input(i,j,k,n)
+ enddo
+ enddo
+ enddo
+ enddo
+!
+ is_input=lbound(BC_t1%south%u_BC,1) !<--
+ ie_input=ubound(BC_t1%south%u_BC,1) ! Index limits for
+ js_input=lbound(BC_t1%south%u_BC,2) ! D-grid u and C-grid v.
+ je_input=ubound(BC_t1%south%u_BC,2) !<--
+!
+ do k=1,klev_in
+ do j=js_input,je_input
+ do i=is_input,ie_input
+ BC_t1%south%u_BC(i,j,k)=u_s_input(i,j,k)
+ BC_t1%south%vc_BC(i,j,k)=v_s_input(i,j,k)
+ enddo
+ enddo
+ enddo
+!
+ is_input=lbound(BC_t1%south%v_BC,1) !<--
+ ie_input=ubound(BC_t1%south%v_BC,1) ! Index limits for
+ js_input=lbound(BC_t1%south%v_BC,2) ! D-grid v and C-grid u.
+ je_input=ubound(BC_t1%south%v_BC,2) !<--
+!
+ do k=1,klev_in
+ do j=js_input,je_input
+ do i=is_input,ie_input
+ BC_t1%south%v_BC(i,j,k)=v_w_input(i,j,k)
+ BC_t1%south%uc_BC(i,j,k)=u_w_input(i,j,k)
+ enddo
+ enddo
+ enddo
+!
+ endif
+!
+!----------
+!*** East
+!----------
+!
+ if(east_bc)then
+ is_input=lbound(BC_t1%east%delp_BC,1) !<--
+ ie_input=ubound(BC_t1%east%delp_BC,1) ! Index limits
+ js_input=lbound(BC_t1%east%delp_BC,2) ! for mass variables.
+ je_input=ubound(BC_t1%east%delp_BC,2) !<--
+!
+ do k=1,klev_in
+ do j=js_input,je_input
+ do i=is_input,ie_input
+ BC_t1%east%delp_BC(i,j,k)=delp_input(i,j,k)
+ BC_t1%east%pt_BC(i,j,k)=t_input(i,j,k)
+ BC_t1%east%w_BC(i,j,k)=w_input(i,j,k)
+ BC_t1%east%delz_BC(i,j,k)=delz_input(i,j,k)
+ enddo
+ enddo
+ enddo
+!
+ do n=1,ntracers
+ do k=1,klev_in
+ do j=js_input,je_input
+ do i=is_input,ie_input
+ BC_t1%east%q_BC(i,j,k,n)=tracers_input(i,j,k,n)
+ enddo
+ enddo
+ enddo
+ enddo
+!
+ is_input=lbound(BC_t1%east%u_BC,1) !<--
+ ie_input=ubound(BC_t1%east%u_BC,1) ! Index limits for
+ js_input=lbound(BC_t1%east%u_BC,2) ! D-grid u and C-grid v.
+ je_input=ubound(BC_t1%east%u_BC,2) !<--
+!
+ do k=1,klev_in
+ do j=js_input,je_input
+ do i=is_input,ie_input
+ BC_t1%east%u_BC(i,j,k)=u_s_input(i,j,k)
+ BC_t1%east%vc_BC(i,j,k)=v_s_input(i,j,k)
+ enddo
+ enddo
+ enddo
+!
+ is_input=lbound(BC_t1%east%v_BC,1) !<--
+ ie_input=ubound(BC_t1%east%v_BC,1) ! Index limits for
+ js_input=lbound(BC_t1%east%v_BC,2) ! D-grid v and C-grid u.
+ je_input=ubound(BC_t1%east%v_BC,2) !<--
+!
+ do k=1,klev_in
+ do j=js_input,je_input
+ do i=is_input,ie_input
+ BC_t1%east%v_BC(i,j,k)=v_w_input(i,j,k)
+ BC_t1%east%uc_BC(i,j,k)=u_w_input(i,j,k)
+ enddo
+ enddo
+ enddo
+!
+ endif
+!
+!----------
+!*** West
+!----------
+!
+ if(west_bc)then
+ is_input=lbound(BC_t1%west%delp_BC,1) !<--
+ ie_input=ubound(BC_t1%west%delp_BC,1) ! Index limits for
+ js_input=lbound(BC_t1%west%delp_BC,2) ! mass variables.
+ je_input=ubound(BC_t1%west%delp_BC,2) !<--
+!
+ do k=1,klev_in
+ do j=js_input,je_input
+ do i=is_input,ie_input
+ BC_t1%west%delp_BC(i,j,k)=delp_input(i,j,k)
+ BC_t1%west%pt_BC(i,j,k)=t_input(i,j,k)
+ BC_t1%west%w_BC(i,j,k)=w_input(i,j,k)
+ BC_t1%west%delz_BC(i,j,k)=delz_input(i,j,k)
+ enddo
+ enddo
+ enddo
+!
+ do n=1,ntracers
+ do k=1,klev_in
+ do j=js_input,je_input
+ do i=is_input,ie_input
+ BC_t1%west%q_BC(i,j,k,n)=tracers_input(i,j,k,n)
+ enddo
+ enddo
+ enddo
+ enddo
+!
+ is_input=lbound(BC_t1%west%u_BC,1) !<--
+ ie_input=ubound(BC_t1%west%u_BC,1) ! Index limits for
+ js_input=lbound(BC_t1%west%u_BC,2) ! D-grid u and C-grid v.
+ je_input=ubound(BC_t1%west%u_BC,2) !<--
+!
+ do k=1,klev_in
+ do j=js_input,je_input
+ do i=is_input,ie_input
+ BC_t1%west%u_BC(i,j,k)=u_s_input(i,j,k)
+ BC_t1%west%vc_BC(i,j,k)=v_s_input(i,j,k)
+ enddo
+ enddo
+ enddo
+!
+ is_input=lbound(BC_t1%west%v_BC,1) !<--
+ ie_input=ubound(BC_t1%west%v_BC,1) ! Index limits for
+ js_input=lbound(BC_t1%west%v_BC,2) ! D-grid v and C-grid u.
+ je_input=ubound(BC_t1%west%v_BC,2) !<--
+!
+ do k=1,klev_in
+ do j=js_input,je_input
+ do i=is_input,ie_input
+ BC_t1%west%v_BC(i,j,k)=v_w_input(i,j,k)
+ BC_t1%west%uc_BC(i,j,k)=u_w_input(i,j,k)
+ enddo
+ enddo
+ enddo
+!
+ endif
+!
+!-----------------------------------------------------------------------
+!
+ end subroutine fill_BC_for_DA
+!
+!-----------------------------------------------------------------------
+!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+!-----------------------------------------------------------------------
+!
+ subroutine fill_divgd_BC
+!
+!-----------------------------------------------------------------------
+!*** For now fill the boundary divergence with zero.
+!-----------------------------------------------------------------------
+ implicit none
!-----------------------------------------------------------------------
!
!--------------------
@@ -2415,15 +2910,16 @@ subroutine read_regional_bc_file(is_input,ie_input &
i_end_array =ie_input
j_start_array=js_input
if(trim(var_name_root)=='u_s'.or.trim(var_name_root)=='v_s')then
- j_end_array=js_input+nhalo_data
+ j_end_array=js_input+nhalo_data+nrows_blend
else
- j_end_array=js_input+nhalo_data-1
+ j_end_array=js_input+nhalo_data+nrows_blend-1
endif
!
i_start_data=i_start_array+nhalo_data
i_count=i_end_array-i_start_array+1
j_start_data=1
j_count=j_end_array-j_start_array+1
+!
endif
endif
!
@@ -2439,13 +2935,14 @@ subroutine read_regional_bc_file(is_input,ie_input &
!
i_start_array=is_input
i_end_array =ie_input
- j_start_array=je_input-nhalo_data+1
+ j_start_array=je_input-nhalo_data-nrows_blend+1
j_end_array =je_input
!
i_start_data=i_start_array+nhalo_data
i_count=i_end_array-i_start_array+1
j_start_data=1
j_count=j_end_array-j_start_array+1
+!
endif
endif
!
@@ -2465,9 +2962,9 @@ subroutine read_regional_bc_file(is_input,ie_input &
i_start_array=is_input
!
if(trim(var_name_root)=='u_w'.or.trim(var_name_root)=='v_w')then
- i_end_array=is_input+nhalo_data
+ i_end_array=is_input+nhalo_data+nrows_blend
else
- i_end_array=is_input+nhalo_data-1
+ i_end_array=is_input+nhalo_data+nrows_blend-1
endif
!
if(north_bc)then
@@ -2489,6 +2986,7 @@ subroutine read_regional_bc_file(is_input,ie_input &
j_start_data=j_start_array
endif
j_count=j_end_array-j_start_array+1
+!
endif
endif
!
@@ -2505,7 +3003,7 @@ subroutine read_regional_bc_file(is_input,ie_input &
j_start_array=js_input
j_end_array =je_input
!
- i_start_array=ie_input-nhalo_data+1
+ i_start_array=ie_input-nhalo_data-nrows_blend+1
i_end_array=ie_input
!
if(north_bc)then
@@ -2528,19 +3026,23 @@ subroutine read_regional_bc_file(is_input,ie_input &
j_start_data=j_start_array
endif
j_count=j_end_array-j_start_array+1
+!
endif
endif
!
!-----------------------------------------------------------------------
!*** Fill this task's subset of boundary data for this 3-D
-!*** or 4-D variable. If the variable is a tracer then
-!*** check if it is present in the input data. If it is
-!*** not then print a warning and set it to zero.
+!*** or 4-D variable. This includes the data in the domain's
+!*** halo region as well as the blending region that overlaps
+!*** the outer nhalo_blend rows of the integration domain.
+!*** If the variable is a tracer then check if it is present
+!*** in the input data. If it is not then print a warning
+!*** and set it to zero.
!-----------------------------------------------------------------------
!
if(call_get_var)then
if (present(array_4d)) then !<-- 4-D variable
- status=nf90_inq_varid(ncid,trim(var_name),var_id)
+ status=nf90_inq_varid(ncid,trim(var_name),var_id) !<-- Get this variable's ID.
if (required_local) then
call check(status)
endif
@@ -2554,6 +3056,7 @@ subroutine read_regional_bc_file(is_input,ie_input &
,1:nlev, tlev) &
,start=(/i_start_data,j_start_data,1,tlev/) & !<-- Start reading the data array here.
,count=(/i_count,j_count,nlev,1/))) !<-- Extent of data to read in each dimension.
+!
endif
!
else !<-- 3-D variable
@@ -2564,6 +3067,7 @@ subroutine read_regional_bc_file(is_input,ie_input &
,1:nlev) &
,start=(/i_start_data,j_start_data,1/) & !<-- Start reading the data array here.
,count=(/i_count,j_count,nlev/))) !<-- Extent of data to read in each dimension.
+!
endif
endif
!
@@ -2581,11 +3085,9 @@ subroutine check(status)
integer,intent(in) :: status
!
if(status /= nf90_noerr) then
- write(0,*)' check netcdf status=',status
- write(0,10001)trim(nf90_strerror(status))
-10001 format(' NetCDF error ',a)
- stop "Stopped"
+ call mpp_error(FATAL,' NetCDF error '//trim(nf90_strerror(status)))
endif
+!
end subroutine check
!
!-----------------------------------------------------------------------
@@ -2691,7 +3193,6 @@ subroutine remap_scalar_nggps_regional_bc(Atm &
real, intent(in), dimension(is_bc:ie_bc,js_bc:je_bc,km):: omga
real, intent(in), dimension(is_bc:ie_bc,js_bc:je_bc,km,ncnst):: qa
real, intent(in), dimension(is_bc:ie_bc,js_bc:je_bc,km+1):: zh
-!xreal, intent(in), dimension(isd-1:ied+1,jsd-1:jed+1):: phis_reg !<-- Filtered sfc geopotential from preprocessing.
real, intent(inout), dimension(isd-1:ied+1,jsd-1:jed+1):: phis_reg !<-- Filtered sfc geopotential from preprocessing.
real, intent(out),dimension(is_bc:ie_bc,js_bc:je_bc) :: ps !<-- sfc p in regional domain boundary region
character(len=5),intent(in) :: side
@@ -2749,22 +3250,22 @@ subroutine remap_scalar_nggps_regional_bc(Atm &
!
is=is_bc
if(side=='west')then
- is=ie_bc-nhalo_data+1
+ is=ie_bc-nhalo_data-nrows_blend+1
endif
!
ie=ie_bc
if(side=='east')then
- ie=is_bc+nhalo_data-1
+ ie=is_bc+nhalo_data+nrows_blend-1
endif
!
js=js_bc
if(side=='south')then
- js=je_bc-nhalo_data+1
+ js=je_bc-nhalo_data-nrows_blend+1
endif
!
je=je_bc
if(side=='north')then
- je=js_bc+nhalo_data-1
+ je=js_bc+nhalo_data+nrows_blend-1
endif
!
allocate(pe0(is:ie,km+1)) ; pe0=real_snan
@@ -2828,7 +3329,8 @@ subroutine remap_scalar_nggps_regional_bc(Atm &
enddo
!
!---------------------------------------------------------------------------------
-!*** Now compute over the normal boundary regions with halo=nhalo_model.
+!*** Now compute over the normal boundary regions with halo=nhalo_model
+!*** extended through nrows_blend rows into the integration domain.
!*** Use the dimensions of one of the permanent BC variables in Atm
!*** as the loop limits so any side of the domain can be addressed.
!---------------------------------------------------------------------------------
@@ -2890,7 +3392,6 @@ subroutine remap_scalar_nggps_regional_bc(Atm &
BC_side%q_BC(i,j,k,iq) = qn1(i,k)
enddo
enddo
-!jaa endif ! for remapping only the tracers included in the data that is read in
endif ! skip cld_amt in the remap since it is not included in the input
enddo
@@ -2971,7 +3472,7 @@ subroutine remap_scalar_nggps_regional_bc(Atm &
enddo i_loop
!-----------------------------------------------------------------------
-! seperate cloud water and cloud ice
+! separate cloud water and cloud ice
! From Jan-Huey Chen's HiRAM code
!-----------------------------------------------------------------------
!
@@ -3077,22 +3578,22 @@ subroutine remap_scalar_nggps_regional_bc(Atm &
enddo jloop2
! Add some diagnostics:
-!xxxcall p_maxmin('PS_model (mb)', Atm%ps(is:ie,js:je), is, ie, js, je, 1, 0.01)
-!xxxcall p_maxmin('PT_model', Atm%pt(is:ie,js:je,1:npz), is, ie, js, je, npz, 1.)
+! call p_maxmin('PS_model (mb)', Atm%ps(is:ie,js:je), is, ie, js, je, 1, 0.01)
+! call p_maxmin('PT_model', Atm%pt(is:ie,js:je,1:npz), is, ie, js, je, npz, 1.)
do j=js,je
do i=is,ie
wk(i,j) = phis_reg(i,j)/grav - zh(i,j,km+1)
enddo
enddo
-!xxxcall pmaxmn('ZS_diff (m)', wk, is, ie, js, je, 1, 1., Atm%gridstruct%area_64, Atm%domain)
+! call pmaxmn('ZS_diff (m)', wk, is, ie, js, je, 1, 1., Atm%gridstruct%area_64, Atm%domain)
do j=js,je
do i=is,ie
wk(i,j) = ps(i,j) - psc(i,j)
enddo
enddo
-!xxxcall pmaxmn('PS_diff (mb)', wk, is, ie, js, je, 1, 0.01, Atm%gridstruct%area_64, Atm%domain)
- deallocate (pe0,qn1,dp2,pe1,qp)
+! call pmaxmn('PS_diff (mb)', wk, is, ie, js, je, 1, 0.01, Atm%gridstruct%area_64, Atm%domain)
+ deallocate (pe0,qn1,dp2,pe1,qp)
if (is_master()) write(*,*) 'done remap_scalar_nggps_regional_bc'
!---------------------------------------------------------------------
@@ -3234,10 +3735,11 @@ subroutine set_regional_BCs(delp,delz,w,pt &
,fcst_time )
!
!---------------------------------------------------------------------
-!*** Select the given variable's boundary data at the two
+!*** Select the boundary variables' boundary data at the two
!*** bracketing time levels and apply them to the updating
-!*** of the variable's boundary region at the appropriate
-!*** forecast time.
+!*** of the variables' boundary regions at the appropriate
+!*** forecast time. This is done at the beginning of every
+!*** large timestep in fv_dynamics.
!---------------------------------------------------------------------
implicit none
!---------------------------------------------------------------------
@@ -3435,11 +3937,22 @@ subroutine bc_values_into_arrays(side_t0,side_t1 &
pt(i,j,k)=side_t0%pt_BC(i,j,k) &
+(side_t1%pt_BC(i,j,k)-side_t0%pt_BC(i,j,k)) &
*fraction_interval
+ delz(i,j,k)=side_t0%delz_BC(i,j,k) &
+ +(side_t1%delz_BC(i,j,k)-side_t0%delz_BC(i,j,k)) &
+ *fraction_interval
#ifdef MOIST_CAPPA
cappa(i,j,k)=side_t0%cappa_BC(i,j,k) &
+(side_t1%cappa_BC(i,j,k)-side_t0%cappa_BC(i,j,k)) &
*fraction_interval
#endif
+#ifdef USE_COND
+ q_con(i,j,k)=side_t0%q_con_BC(i,j,k) &
+ +(side_t1%q_con_BC(i,j,k)-side_t0%q_con_BC(i,j,k)) &
+ *fraction_interval
+#endif
+ w(i,j,k)=side_t0%w_BC(i,j,k) &
+ +(side_t1%w_BC(i,j,k)-side_t0%w_BC(i,j,k)) &
+ *fraction_interval
enddo
enddo
!
@@ -3469,24 +3982,6 @@ subroutine bc_values_into_arrays(side_t0,side_t1 &
ie=min(ubound(side_t0%delz_BC,1),ubound(delz,1))
je=min(ubound(side_t0%delz_BC,2),ubound(delz,2))
nz=ubound(delz,3)
-!
- do k=1,nz
- do j=jstart,jend
- do i=i1,ie
- delz(i,j,k)=side_t0%delz_BC(i,j,k) &
- +(side_t1%delz_BC(i,j,k)-side_t0%delz_BC(i,j,k)) &
- *fraction_interval
-#ifdef USE_COND
- q_con(i,j,k)=side_t0%q_con_BC(i,j,k) &
- +(side_t1%q_con_BC(i,j,k)-side_t0%q_con_BC(i,j,k)) &
- *fraction_interval
-#endif
- w(i,j,k)=side_t0%w_BC(i,j,k) &
- +(side_t1%w_BC(i,j,k)-side_t0%w_BC(i,j,k)) &
- *fraction_interval
- enddo
- enddo
- enddo
!
do nt=1,ntracers
do k=1,nz
@@ -3557,6 +4052,8 @@ subroutine regional_boundary_update(array &
!---------------------
!
integer :: i1,i2,j1,j2 !<-- Horizontal limits of region updated.
+ integer :: i_bc,j_bc !<-- Innermost bndry index (anchor point for blending)
+ integer :: i1_blend,i2_blend,j1_blend,j2_blend !<-- Limits of updated blending region.
integer :: lbnd1,ubnd1,lbnd2,ubnd2 !<-- Horizontal limits of BC update arrays.
integer :: iq !<-- Tracer index
integer :: nside
@@ -3607,6 +4104,17 @@ subroutine regional_boundary_update(array &
!
j1=jsd
j2=js-1
+!
+ i1_blend=is
+ i2_blend=ie
+ if(trim(bc_vbl_name)=='uc'.or.trim(bc_vbl_name)=='v')then
+ i2_blend=ie+1
+ endif
+ j1_blend=js
+ j2_blend=js+nrows_blend_user-1
+ i_bc=-9e9
+ j_bc=j2
+!
endif
endif
!
@@ -3632,6 +4140,20 @@ subroutine regional_boundary_update(array &
j1=je+2
j2=jed+1
endif
+!
+ i1_blend=is
+ i2_blend=ie
+ if(trim(bc_vbl_name)=='uc'.or.trim(bc_vbl_name)=='v')then
+ i2_blend=ie+1
+ endif
+ j2_blend=je
+ if(trim(bc_vbl_name)=='u'.or.trim(bc_vbl_name)=='vc')then
+ j2_blend=je+1
+ endif
+ j1_blend=j2_blend-nrows_blend_user+1
+ i_bc=-9e9
+ j_bc=j1
+!
endif
endif
!
@@ -3660,6 +4182,23 @@ subroutine regional_boundary_update(array &
j2=je+1
endif
endif
+!
+ i1_blend=is
+ i2_blend=is+nrows_blend_user-1
+ j1_blend=js
+ j2_blend=je
+ if(north_bc)then
+ j1_blend=js+nrows_blend_user !<-- North BC already handles nrows_blend_user blending rows
+ endif
+ if(south_bc)then
+ j2_blend=je-nrows_blend_user !<-- South BC already handles nrows_blend_user blending rows
+ endif
+ if(trim(bc_vbl_name)=='u'.or.trim(bc_vbl_name)=='vc')then
+ j2_blend=j2_blend+1
+ endif
+ i_bc=i2
+ j_bc=-9e9
+!
endif
endif
!
@@ -3692,6 +4231,23 @@ subroutine regional_boundary_update(array &
j2=je+1
endif
endif
+!
+ i1_blend=i1-nrows_blend_user
+ i2_blend=i1-1
+ j1_blend=js
+ j2_blend=je
+ if(north_bc)then
+ j1_blend=js+nrows_blend_user !<-- North BC already handled nrows_blend_user blending rows.
+ endif
+ if(south_bc)then
+ j2_blend=je-nrows_blend_user !<-- South BC already handled nrows_blend_user blending rows.
+ endif
+ if(trim(bc_vbl_name)=='u'.or.trim(bc_vbl_name)=='vc')then
+ j2_blend=j2_blend+1
+ endif
+ i_bc=i1
+ j_bc=-9e9
+!
endif
endif
!
@@ -3714,16 +4270,19 @@ subroutine regional_boundary_update(array &
,bc_t0,bc_t1 &
,lbnd1,ubnd1,lbnd2,ubnd2 &
,i1,i2,j1,j2 &
+ ,is,ie,js,je &
,fcst_time &
- ,bc_update_interval )
+ ,bc_update_interval &
+ ,i1_blend,i2_blend,j1_blend,j2_blend &
+ ,i_bc,j_bc, nside, bc_vbl_name )
endif
!
!---------------------------------------------------------------------
+!
enddo sides
-!---------------------------------------------------------------------
!
!---------------------------------------------------------------------
-
+!
end subroutine regional_boundary_update
!---------------------------------------------------------------------
@@ -3795,8 +4354,7 @@ subroutine retrieve_bc_variable_data(bc_vbl_name &
#endif
case ('q')
if(iq<1)then
- write(0,101)
- 101 format(' iq<1 is not a valid index for q_BC array in retrieve_bc_variable_data')
+ call mpp_error(FATAL,' iq<1 is not a valid index for q_BC array in retrieve_bc_variable_data')
endif
lbnd1=lbound(bc_side_t0%q_BC,1)
lbnd2=lbound(bc_side_t0%q_BC,2)
@@ -3834,16 +4392,19 @@ end subroutine retrieve_bc_variable_data
!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
!---------------------------------------------------------------------
!
- subroutine bc_time_interpolation(array &
- ,lbnd_x, ubnd_x &
- ,lbnd_y, ubnd_y &
- ,ubnd_z &
- ,bc_t0, bc_t1 &
- ,lbnd1, ubnd1 &
- ,lbnd2, ubnd2 &
- ,i1,i2,j1,j2 &
- ,fcst_time &
- ,bc_update_interval )
+ subroutine bc_time_interpolation(array &
+ ,lbnd_x, ubnd_x &
+ ,lbnd_y, ubnd_y &
+ ,ubnd_z &
+ ,bc_t0, bc_t1 &
+ ,lbnd1, ubnd1 &
+ ,lbnd2, ubnd2 &
+ ,i1,i2,j1,j2 &
+ ,is,ie,js,je &
+ ,fcst_time &
+ ,bc_update_interval &
+ ,i1_blend,i2_blend,j1_blend,j2_blend &
+ ,i_bc,j_bc,nside, bc_vbl_name )
!---------------------------------------------------------------------
!*** Update the boundary region of the input array at the given
@@ -3861,14 +4422,23 @@ subroutine bc_time_interpolation(array &
!
integer,intent(in) :: lbnd1,ubnd1,lbnd2,ubnd2 !<-- Index limits of the BC arrays.
!
- integer,intent(in) :: i1,i2,j1,j2 !<-- Index limits of the updated region.
+ integer,intent(in) :: i1,i2,j1,j2 & !<-- Index limits of the updated boundary region.
+ ,i_bc,j_bc & !<-- Innermost bndry indices (anchor pts for blending)
+ ,i1_blend,i2_blend,j1_blend,j2_blend & !<-- Index limits of the updated blending region.
+ ,nside
+!
+ integer,intent(in) :: is,ie,js,je !<-- Min/Max index limits on task's computational subdomain
!
integer,intent(in) :: bc_update_interval !<-- Time (hours) between BC data states
!
real,intent(in) :: fcst_time !<-- Current forecast time (sec)
+!
+ real :: rdenom
!
real,dimension(lbnd1:ubnd1,lbnd2:ubnd2,1:ubnd_z) :: bc_t0 & !<-- Interpolate between these
,bc_t1 ! two boundary region states.
+!
+ character(len=*),intent(in) :: bc_vbl_name
!
!---------------------
!*** Output variables
@@ -3883,7 +4453,7 @@ subroutine bc_time_interpolation(array &
!
integer :: i,j,k
!
- real :: fraction_interval
+ real :: blend_value,factor_dist,fraction_interval
!
!---------------------------------------------------------------------
!*********************************************************************
@@ -3909,144 +4479,94 @@ subroutine bc_time_interpolation(array &
enddo
!
!---------------------------------------------------------------------
-
- end subroutine bc_time_interpolation
-!---------------------------------------------------------------------
-!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+!*** Use specified external data to blend with integration values
+!*** across nrows_blend rows immediately within the domain's
+!*** boundary rows. The weighting of the external data drops
+!*** off exponentially.
!---------------------------------------------------------------------
!
- subroutine bc_time_interpolation_general(is,ie,js,je &
- ,is_s,ie_s,js_s,je_s &
- ,is_w,ie_w,js_w,je_w &
- ,fraction &
- ,t0,t1 &
- ,Atm )
-!
-!---------------------------------------------------------------------
-!*** Execute the linear time interpolation between t0 and t1
-!*** generically for any side of the regional domain's boundary
-!*** region.
-!---------------------------------------------------------------------
- implicit none
-!---------------------------------------------------------------------
+!-----------
+!*** North
+!-----------
!
-!------------------------
-!*** Argument variables
-!------------------------
+ if(nside==1.and.north_bc)then
+ rdenom=1./real(j2_blend-j_bc-1)
+ do k=1,ubnd_z
+ do j=j1_blend,j2_blend
+ factor_dist=exp(-(blend_exp1+blend_exp2*(j-j_bc-1)*rdenom)) !<-- Exponential falloff of blending weights.
+ do i=i1_blend,i2_blend
+ blend_value=bc_t0(i,j,k) & !<-- Blend data interpolated
+ +(bc_t1(i,j,k)-bc_t0(i,j,k))*fraction_interval ! between t0 and t1.
!
- integer,intent(in) :: is,ie,js,je & !<-- Index limits for centers of grid cells
- ,is_s,ie_s,js_s,je_s & !<-- Index limits for south/north edges of grid cells
- ,is_w,ie_w,js_w,je_w !<-- Index limits for west/east edges of grid cells
+ array(i,j,k)=(1.-factor_dist)*array(i,j,k)+factor_dist*blend_value
+ enddo
+ enddo
+ enddo
+ endif
!
- real,intent(in) :: fraction !<-- Current time is this fraction between t0 ad t1.
+!-----------
+!*** South
+!-----------
!
- type(fv_regional_BC_variables),intent(in) :: t0,t1 !<-- BC variables at time levels t0 and t1.
+ if(nside==2.and.south_bc)then
+ rdenom=1./real(j_bc-j1_blend-1)
+ do k=1,ubnd_z
+ do j=j1_blend,j2_blend
+ factor_dist=exp(-(blend_exp1+blend_exp2*(j_bc-j-1)*rdenom)) !<-- Exponential falloff of blending weights.
+ do i=i1_blend,i2_blend
+ blend_value=bc_t0(i,j,k) & !<-- Blend data interpolated
+ +(bc_t1(i,j,k)-bc_t0(i,j,k))*fraction_interval ! between t0 and t1.
+ array(i,j,k)=(1.-factor_dist)*array(i,j,k)+factor_dist*blend_value
+ enddo
+ enddo
+ enddo
+ endif
!
- type(fv_atmos_type),intent(inout) :: Atm !<-- The Atm object
+!----------
+!*** East
+!----------
!
-!---------------------
-!*** Local variables
-!---------------------
+ if(nside==3.and.east_bc)then
+ rdenom=1./real(i2_blend-i_bc-1)
+ do k=1,ubnd_z
+ do j=j1_blend,j2_blend
+ do i=i1_blend,i2_blend
!
- integer :: i,j,k,n,nlayers!,ntracers
+ blend_value=bc_t0(i,j,k) & !<-- Blend data interpolated
+ +(bc_t1(i,j,k)-bc_t0(i,j,k))*fraction_interval ! between t0 and t1.
!
-!---------------------------------------------------------------------
-!*********************************************************************
-!---------------------------------------------------------------------
+ factor_dist=exp(-(blend_exp1+blend_exp2*(i-i_bc-1)*rdenom)) !<-- Exponential falloff of blending weights.
!
- nlayers =Atm%npz !<-- # of layers in vertical configuration of integration
-! ntracers=Atm%ncnst !<-- # of advected tracers
+ array(i,j,k)=(1.-factor_dist)*array(i,j,k)+factor_dist*blend_value
+ enddo
+ enddo
+ enddo
+ endif
!
-!---------------------------------------------------------------------
+!----------
+!*** West
+!----------
!
- k_loop: do k=1,nlayers
+ if(nside==4.and.west_bc)then
+ rdenom=1./real(i_bc-i1_blend-1)
+ do k=1,ubnd_z
+ do j=j1_blend,j2_blend
+ do i=i1_blend,i2_blend
!
-!---------------------------------------------------------------------
+ blend_value=bc_t0(i,j,k) & !<-- Blend data interpolated
+ +(bc_t1(i,j,k)-bc_t0(i,j,k))*fraction_interval ! between t0 and t1.
!
-!-------------
-!*** Scalars
-!-------------
+ factor_dist=exp(-(blend_exp1+blend_exp2*(i_bc-i-1)*rdenom)) !<-- Exponential falloff of blending weights.
!
- do j=js,je
- do i=is,ie
-!
- Atm%delp(i,j,k)=t0%delp_BC(i,j,k) & !<-- Update layer pressure thickness.
- +(t1%delp_BC(i,j,k)-t0%delp_BC(i,j,k)) &
- *fraction
-!
-#ifndef SW_DYNAMICS
- Atm%delz(i,j,k)=t0%delz_BC(i,j,k) & !<-- Update layer height thickness.
- +(t1%delz_BC(i,j,k)-t0%delz_BC(i,j,k)) &
- *fraction
-!
- Atm%w(i,j,k)=t0%w_BC(i,j,k) & !<-- Update vertical motion.
- +(t1%w_BC(i,j,k)-t0%w_BC(i,j,k)) &
- *fraction
-!
- Atm%pt(i,j,k)=t0%pt_BC(i,j,k) & !<-- Update thetav.
- +(t1%pt_BC(i,j,k)-t0%pt_BC(i,j,k)) &
- *fraction
-#ifdef USE_COND
- Atm%q_con(i,j,k)=t0%q_con_BC(i,j,k) & !<-- Update water condensate.
- +(t1%q_con_BC(i,j,k)-t0%q_con_BC(i,j,k)) &
- *fraction
-#ifdef MOIST_CAPPA
-! Atm%cappa(i,j,k)=t0%pt_BC(i,j,k) & !<-- Update cappa.
-! +(t1%cappa_BC(i,j,k)-t0%cappa_BC(i,j,k)) &
-! *fraction
-#endif
-#endif
-#endif
-!
- enddo
- enddo
-!
- do n=1,ntracers
-!
- do j=js,je
- do i=is,ie
- Atm%q(i,j,k,n)=t0%q_BC(i,j,k,n) & !<-- Update tracers.
- +(t1%q_BC(i,j,k,n)-t0%q_BC(i,j,k,n)) &
- *fraction
- enddo
+ array(i,j,k)=(1.-factor_dist)*array(i,j,k)+factor_dist*blend_value
+ enddo
enddo
-!
- enddo
-!
-!-----------
-!*** Winds
-!-----------
-!
- do j=js_s,je_s
- do i=is_s,ie_s
- Atm%u(i,j,k)=t0%u_BC(i,j,k) & !<-- Update D-grid u component.
- +(t1%u_BC(i,j,k)-t0%u_BC(i,j,k)) &
- *fraction
- Atm%vc(i,j,k)=t0%vc_BC(i,j,k) & !<-- Update C-grid v component.
- +(t1%vc_BC(i,j,k)-t0%vc_BC(i,j,k)) &
- *fraction
- enddo
- enddo
-!
-!
- do j=js_w,je_w
- do i=is_w,ie_w
- Atm%v(i,j,k)=t0%v_BC(i,j,k) & !<-- Update D-grid v component.
- +(t1%v_BC(i,j,k)-t0%v_BC(i,j,k)) &
- *fraction
- Atm%uc(i,j,k)=t0%uc_BC(i,j,k) & !<-- Update C-grid u component.
- +(t1%uc_BC(i,j,k)-t0%uc_BC(i,j,k)) &
- *fraction
- enddo
enddo
+ endif
!
!---------------------------------------------------------------------
!
- enddo k_loop
-!
-!---------------------------------------------------------------------
-!
- end subroutine bc_time_interpolation_general
+ end subroutine bc_time_interpolation
!
!---------------------------------------------------------------------
!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -4775,6 +5295,14 @@ end subroutine nudge_qv_bc
subroutine dump_field_3d (domain, name, field, isd, ied, jsd, jed, nlev, stag)
+!-----------------------------------------------------------------------
+!*** Subroutines dump_field_2d and dump_field_3d are module
+!*** procedures with the generic interface 'dump_field'.
+!*** Use these routines to write out NetCDF files containing
+!*** FULL fields that include the variables' boundary region.
+!*** See the following four examples for guidance on how to
+!*** call the routines.
+!-----------------------------------------------------------------------
! call dump_field(Atm(1)%domain,"atm_pt", Atm(1)%pt, isd, ied, jsd, jed, Atm(1)%npz, stag=H_STAGGER)
! call dump_field(Atm(1)%domain,"atm_u", Atm(1)%u, isd, ied, jsd, jed+1, Atm(1)%npz, stag=U_STAGGER)
! call dump_field(Atm(1)%domain,"atm_v", Atm(1)%v, isd, ied+1, jsd, jed, Atm(1)%npz, stag=V_STAGGER)
@@ -4849,7 +5377,7 @@ subroutine dump_field_3d (domain, name, field, isd, ied, jsd, jed, nlev, stag)
call mpp_gather(isection_s,isection_e,jsection_s,jsection_e, nz, &
pelist, field(isection_s:isection_e,jsection_s:jsection_e,:), glob_field, is_root_pe, halo, halo)
- call mpp_open( unit, trim(fname), action=MPP_WRONLY, form=MPP_NETCDF, threading=MPP_SINGLE)
+ call mpp_open( unit, trim(fname), action=MPP_OVERWR, form=MPP_NETCDF, threading=MPP_SINGLE)
call mpp_write_meta( unit, x, 'grid_xt', 'km', 'X distance', 'X', domain=xdom, data=(/(i*1.0,i=1,nxg)/) )
call mpp_write_meta( unit, y, 'grid_yt', 'km', 'Y distance', 'Y', domain=ydom, data=(/(j*1.0,j=1,nyg)/) )
@@ -4901,7 +5429,7 @@ subroutine dump_field_2d (domain, name, field, isd, ied, jsd, jed, stag)
integer :: isection_s, isection_e, jsection_s, jsection_e
write(fname,"(A,A,A,I1.1,A)") "regional_",name,".tile", 7 , ".nc"
-! write(0,*)'dump_field_3d: file name = |', trim(fname) , '|'
+ write(0,*)'dump_field_3d: file name = |', trim(fname) , '|'
call mpp_get_domain_components( domain, xdom, ydom )
call mpp_get_compute_domain( domain, is, ie, js, je )
@@ -4947,7 +5475,7 @@ subroutine dump_field_2d (domain, name, field, isd, ied, jsd, jed, stag)
call mpp_gather(isection_s,isection_e,jsection_s,jsection_e, &
pelist, field(isection_s:isection_e,jsection_s:jsection_e), glob_field, is_root_pe, halo, halo)
- call mpp_open( unit, trim(fname), action=MPP_WRONLY, form=MPP_NETCDF, threading=MPP_SINGLE)
+ call mpp_open( unit, trim(fname), action=MPP_OVERWR, form=MPP_NETCDF, threading=MPP_SINGLE)
call mpp_write_meta( unit, x, 'grid_xt', 'km', 'X distance', 'X', domain=xdom, data=(/(i*1.0,i=1,nxg)/) )
call mpp_write_meta( unit, y, 'grid_yt', 'km', 'Y distance', 'Y', domain=ydom, data=(/(j*1.0,j=1,nyg)/) )
@@ -4974,6 +5502,755 @@ subroutine dump_field_2d (domain, name, field, isd, ied, jsd, jed, stag)
end subroutine dump_field_2d
+!-----------------------------------------------------------------------
+!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+!-----------------------------------------------------------------------
+!
+ subroutine create_restart_with_bcs(Atm)
+!
+!-----------------------------------------------------------------------
+!*** Create the netcdf files into which full fields of the
+!*** restart variables will be written INCLUDING BOUNDARY ROWS
+!*** so the GSI can update both the interior and BCs.
+!-----------------------------------------------------------------------
+!
+ integer,parameter :: ndims_core=6 & !<-- # of core restart dimensions
+ ,ndims_tracers=4 !<-- # of tracer restart dimensions
+!
+ type(fv_atmos_type),target,intent(inout) :: Atm !<-- Atm object for the current domain
+!
+ integer :: dimid,n,na,natts &
+ ,ncid_core,ncid_core_new &
+ ,ncid_tracers,ncid_tracers_new &
+ ,nctype,ndims,ngatts,nn,nv_core,nv_tracers,var_id
+!
+ integer,dimension(ndims_core) :: dim_lengths_core
+ integer,dimension(ndims_tracers) :: dim_lengths_tracers
+!
+ integer,dimension(1:4) :: dimids=(/0,0,0,0/)
+!
+ real,dimension(:),allocatable :: dim_values
+!
+ character(len=50) :: att_name,var_name
+!
+ character(len=9),dimension(ndims_core) :: dim_names_core=(/ &
+ 'xaxis_1' &
+ ,'xaxis_2' &
+ ,'yaxis_1' &
+ ,'yaxis_2' &
+ ,'zaxis_1' &
+ ,'Time ' &
+ /)
+!
+ character(len=9),dimension(ndims_tracers) :: dim_names_tracers=(/ &
+ 'xaxis_1' &
+ ,'yaxis_1' &
+ ,'zaxis_1' &
+ ,'Time ' &
+ /)
+!
+!-----------------------------------------------------------------------
+!***********************************************************************
+!-----------------------------------------------------------------------
+!
+!-----------------------------------------------------------------------
+!*** The first file to be handled is the core restart file.
+!-----------------------------------------------------------------------
+!
+!-----------------------------------------------------------------------
+!*** All tasks are given pointers into the model data that will
+!*** be written to the new restart file. The following are the
+!*** prognostic variables in the core rstart file.
+!-----------------------------------------------------------------------
+!
+ allocate(fields_core(1:nvars_core))
+!
+ fields_core(1)%ptr=>Atm%u
+ fields_core(1)%name='u'
+!
+ fields_core(2)%ptr=>Atm%v
+ fields_core(2)%name='v'
+!
+ fields_core(3)%ptr=>Atm%w
+ fields_core(3)%name='W'
+!
+ fields_core(4)%ptr=>Atm%delz
+ fields_core(4)%name='DZ'
+!
+ fields_core(5)%ptr=>Atm%pt
+ fields_core(5)%name='T'
+!
+ fields_core(6)%ptr=>Atm%delp
+ fields_core(6)%name='delp'
+!
+ allocate(fields_core(7)%ptr(lbound(Atm%phis,1):ubound(Atm%phis,1) &
+ ,lbound(Atm%phis,2):ubound(Atm%phis,2) &
+ ,1:1))
+ fields_core(7)%ptr(:,:,1)=Atm%phis(:,:) !<-- For generality treat the 2-D phis as 3-D
+ fields_core(7)%name='phis'
+!
+!-----------------------------------------------------------------------
+!*** Also point at the proper tracer arrays and set their names.
+!-----------------------------------------------------------------------
+!
+ allocate(fields_tracers(1:nvars_tracers))
+!
+ lbnd_x_tracers=lbound(Atm%q,1)
+ ubnd_x_tracers=ubound(Atm%q,1)
+ lbnd_y_tracers=lbound(Atm%q,2)
+ ubnd_y_tracers=ubound(Atm%q,2)
+!
+ fields_tracers(1)%ptr=>Atm%q(:,:,:,sphum_index)
+ fields_tracers(1)%name='sphum'
+!
+ fields_tracers(2)%ptr=>Atm%q(:,:,:,liq_water_index)
+ fields_tracers(2)%name='liq_wat'
+!
+ fields_tracers(3)%ptr=>Atm%q(:,:,:,ice_water_index)
+ fields_tracers(3)%name='ice_wat'
+!
+ fields_tracers(4)%ptr=>Atm%q(:,:,:,rain_water_index)
+ fields_tracers(4)%name='rainwat'
+!
+ fields_tracers(5)%ptr=>Atm%q(:,:,:,snow_water_index)
+ fields_tracers(5)%name='snowwat'
+!
+ fields_tracers(6)%ptr=>Atm%q(:,:,:,graupel_index)
+ fields_tracers(6)%name='graupel'
+!
+ fields_tracers(7)%ptr=>Atm%q(:,:,:,o3mr_index)
+ fields_tracers(7)%name='o3mr'
+!
+ fields_tracers(8)%ptr=>Atm%q(:,:,:,cld_amt_index)
+ fields_tracers(8)%name='cld_amt'
+!
+!-----------------------------------------------------------------------
+!*** Only one compute task prepares the new restart files. The task
+!*** with the highest rank knows the upper bounds of the domain so
+!*** it does the work. All other tasks may exit.
+!-----------------------------------------------------------------------
+!
+ if(mpp_pe()/=Atm%layout(1)*Atm%layout(2)-1)then
+ return
+ endif
+!
+ call check(nf90_create(filename_core_new &
+ ,cmode=or(nf90_clobber,nf90_64bit_offset) &
+ ,ncid=ncid_core_new))
+!
+!-----------------------------------------------------------------------
+!*** Define the output file's dimensions and insert them into the file.
+!-----------------------------------------------------------------------
+!
+ dim_lengths_core(1)=Atm%bd%ied+nhalo_model !<-- x
+ dim_lengths_core(2)=dim_lengths_core(1)+1 !<-- x+1
+ dim_lengths_core(3)=Atm%bd%jed+nhalo_model+1 !<-- y+1
+ dim_lengths_core(4)=dim_lengths_core(3)-1 !<-- y
+ dim_lengths_core(5)=Atm%npz !<-- z
+ dim_lengths_core(6)=nf90_unlimited !<-- time
+!
+ do n=1,ndims_core
+ call check(nf90_def_dim(ncid_core_new &
+ ,dim_names_core(n) &
+ ,dim_lengths_core(n) &
+ ,dimid))
+ enddo
+!
+!-----------------------------------------------------------------------
+!*** The new file's variables must be defined while that file
+!*** is still in define mode. Define each of the restart file's
+!*** variables in the new file.
+!-----------------------------------------------------------------------
+!
+ call check(nf90_open(filename_core,nf90_nowrite,ncid_core)) !<-- The core restart file's ID
+!
+ call check(nf90_inquire(ncid_core,nvariables=nv_core)) !<-- The TOTAL number of core restart file variables
+!
+ do n=1,nv_core
+ var_id=n
+ call check(nf90_inquire_variable(ncid_core,var_id,var_name,nctype & !<-- Name and type of this variable
+ ,ndims,dimids,natts)) !<-- # of dimensions and attributes in this variable
+!
+ call check(nf90_def_var(ncid_core_new,var_name,nctype,dimids(1:ndims),var_id)) !<-- Define the variable in the new file.
+!
+!-----------------------------------------------------------------------
+!*** Copy this variable's attributes to the new core file's
+!*** variable.
+!-----------------------------------------------------------------------
+!
+ if(natts>0)then
+ do na=1,natts
+ call check(nf90_inq_attname(ncid_core,var_id,na,att_name)) !<-- Get the attribute's name and ID from restart.
+ call check(nf90_copy_att(ncid_core,var_id,att_name,ncid_core_new,var_id)) !<-- Copy to the new file.
+ enddo
+ endif
+!
+ enddo
+!
+!-----------------------------------------------------------------------
+!*** Find the number of global attributes in the restart file and
+!*** copy them to the new file.
+!-----------------------------------------------------------------------
+!
+ call check(nf90_inquire(ncid_core,nattributes=ngatts))
+!
+ do n=1,ngatts
+ call check(nf90_inq_attname(ncid_core,nf90_global,n,att_name))
+ call check(nf90_copy_att(ncid_core,nf90_global,att_name,ncid_core_new,nf90_global))
+ enddo
+!
+!-----------------------------------------------------------------------
+!
+ call check(nf90_enddef(ncid_core_new)) !<-- Put the output file into data mode.
+!
+!-----------------------------------------------------------------------
+!*** Insert the dimension values.
+!-----------------------------------------------------------------------
+!
+ do n=1,ndims_core-1
+ allocate(dim_values(1:dim_lengths_core(n)))
+ do nn=1,dim_lengths_core(n)
+ dim_values(nn)=nn
+ enddo
+ var_id=n
+ call check(nf90_put_var(ncid_core_new,var_id &
+ ,dim_values(:) &
+ ,start=(/1/) &
+ ,count=(/dim_lengths_core(n)/)))
+ deallocate(dim_values)
+ enddo
+!
+ write( 0,*)' nf90_unlimited=',nf90_unlimited
+ var_id=ndims_core !<-- Time is the final dimension; treat it separately.
+ allocate(dim_values(1))
+ dim_values(1)=1
+ call check(nf90_put_var(ncid_core_new,var_id &
+ ,dim_values(:)))
+ deallocate(dim_values)
+!
+!-----------------------------------------------------------------------
+!
+ call check(nf90_close(ncid_core_new))
+ call check(nf90_close(ncid_core))
+!
+!-----------------------------------------------------------------------
+!*** The second file to be handled is the tracer restart file.
+!-----------------------------------------------------------------------
+!
+ call check(nf90_create(filename_tracers_new &
+ ,cmode=or(nf90_clobber,nf90_64bit_offset) &
+ ,ncid=ncid_tracers_new))
+!
+!-----------------------------------------------------------------------
+!*** Define the output file's dimensions and insert them into the file.
+!-----------------------------------------------------------------------
+!
+ dim_lengths_tracers(1)=Atm%bd%ied+nhalo_model !<-- x
+ dim_lengths_tracers(2)=Atm%bd%jed+nhalo_model !<-- y
+ dim_lengths_tracers(3)=Atm%npz !<-- z
+ dim_lengths_tracers(4)=nf90_unlimited !<-- time
+!
+ do n=1,ndims_tracers
+ call check(nf90_def_dim(ncid_tracers_new &
+ ,dim_names_tracers(n) &
+ ,dim_lengths_tracers(n) &
+ ,dimid))
+ enddo
+!
+!-----------------------------------------------------------------------
+!*** The new file's variables must be defined while that file
+!*** is still in define mode. Define each of the restart file's
+!*** variables in the new file.
+!-----------------------------------------------------------------------
+!
+ call check(nf90_open(filename_tracers,nf90_nowrite,ncid_tracers)) !<-- The tracer restart file's ID
+!
+ call check(nf90_inquire(ncid_tracers,nvariables=nv_tracers)) !<-- The TOTAL number of tracer restart file variables
+!
+ do n=1,nv_tracers
+ var_id=n
+ call check(nf90_inquire_variable(ncid_tracers,var_id,var_name,nctype & !<-- Name and type of this variable
+ ,ndims,dimids,natts)) !<-- # of dimensions and attributes in this variable
+!
+ call check(nf90_def_var(ncid_tracers_new,var_name,nctype,dimids(1:ndims),var_id)) !<-- Define the variable in the new file.
+!
+!-----------------------------------------------------------------------
+!*** Copy this variable's attributes to the new tracers file's
+!*** variable.
+!-----------------------------------------------------------------------
+!
+ if(natts>0)then
+ do na=1,natts
+ call check(nf90_inq_attname(ncid_tracers,var_id,na,att_name)) !<-- Get the attribute's name and ID from restart.
+ call check(nf90_copy_att(ncid_tracers,var_id,att_name,ncid_tracers_new,var_id)) !<-- Copy to the new file.
+ enddo
+ endif
+!
+ enddo
+!
+!-----------------------------------------------------------------------
+!*** Find the number of global attributes in the restart file and
+!*** copy them to the new file.
+!-----------------------------------------------------------------------
+!
+ call check(nf90_inquire(ncid_tracers,nattributes=ngatts))
+!
+ do n=1,ngatts
+ call check(nf90_inq_attname(ncid_tracers,nf90_global,n,att_name))
+ call check(nf90_copy_att(ncid_tracers,nf90_global,att_name,ncid_tracers_new,nf90_global))
+ enddo
+!
+!-----------------------------------------------------------------------
+!
+ call check(nf90_enddef(ncid_tracers_new)) !<-- Put the output file into data mode.
+!
+!-----------------------------------------------------------------------
+!*** Insert the dimension values.
+!-----------------------------------------------------------------------
+!
+ do n=1,ndims_tracers-1
+ allocate(dim_values(1:dim_lengths_tracers(n)))
+ do nn=1,dim_lengths_tracers(n)
+ dim_values(nn)=nn
+ enddo
+ var_id=n
+ call check(nf90_put_var(ncid_tracers_new,var_id &
+ ,dim_values(:) &
+ ,start=(/1/) &
+ ,count=(/dim_lengths_tracers(n)/)))
+ deallocate(dim_values)
+ enddo
+!
+ var_id=ndims_tracers !<-- Time is the final dimension; treat it separately.
+ allocate(dim_values(1))
+ dim_values(1)=1
+ call check(nf90_put_var(ncid_tracers_new,var_id &
+ ,dim_values(:)))
+ deallocate(dim_values)
+!
+!-----------------------------------------------------------------------
+!
+ call check(nf90_close(ncid_tracers_new))
+ call check(nf90_close(ncid_tracers))
+!
+!-----------------------------------------------------------------------
+!
+ end subroutine create_restart_with_bcs
+!
+!-----------------------------------------------------------------------
+!--------------------------------------------------------------------------------------
+!
+ subroutine write_full_fields(Atm)
+!
+!--------------------------------------------------------------------------------------
+!*** Write out full fields of the primary restart variables
+!*** INCLUDING BOUNDARY ROWS so the GSI can include BCs in its
+!*** update. This is done in a restart look-alike file.
+!--------------------------------------------------------------------------------------
+!
+ type(fv_atmos_type), intent(inout), target :: Atm(:)
+!
+ integer :: count_i,count_j
+ integer :: iend,istart,jend,jstart,kend,kstart,nz
+ integer :: iend_ptr,istart_ptr,jend_ptr,jstart_ptr
+ integer :: iend_g,istart_g,jend_g,jstart_g
+ integer :: ieg,iext,isg,jeg,jext,jsg,k
+ integer :: n,ncid_core_new,ncid_tracers_new,nv,var_id
+ integer :: halo
+!
+ integer,dimension(:),allocatable :: pelist
+!
+ real,dimension(:,:,:),allocatable :: global_field
+ real,dimension(:,:,:),pointer :: field_3d
+!
+ character(len=10) :: var_name
+!
+ logical :: is_root_pe
+!
+!-----------------------------------------------------------------------
+!***********************************************************************
+!-----------------------------------------------------------------------
+!
+ allocate( pelist(mpp_npes()) )
+ call mpp_get_current_pelist(pelist)
+ write(0,*)' pelist=',pelist
+!
+ halo=nhalo_model
+!
+ is_root_pe = (mpp_pe()==mpp_root_pe())
+ if(is_root_pe)then
+ call check(nf90_open(filename_core_new,nf90_write,ncid_core_new)) !<-- Open the new netcdf file
+ write(0,*)' Opened core restart with BCs: ',trim(filename_core_new)
+ endif
+!
+!-----------------------------------------------------------------------
+!*** Save the global limits of the domain and its vertical extent.
+!-----------------------------------------------------------------------
+!
+ call mpp_get_global_domain (Atm(1)%domain, isg, ieg, jsg, jeg, position=CENTER )
+!
+!-----------------------------------------------------------------------
+!*** Begin with the core restart file.
+!*** Loop through that file's prognostic variables.
+!-----------------------------------------------------------------------
+!
+ vbls_core: do nv=1,nvars_core
+!
+ var_name=fields_core(nv)%name
+ if(is_root_pe)then
+ call check(nf90_inq_varid(ncid_core_new,var_name,var_id)) !<-- Get this variable's ID
+ endif
+!
+!-----------------------------------------------------------------------
+!*** What is the full domain extent of this variable including
+!*** boundary rows?
+!-----------------------------------------------------------------------
+!
+ iext=0
+ jext=0
+ if(var_name=='u'.or.var_name=='vc')then
+ jext=1
+ endif
+ if(var_name=='v'.or.var_name=='uc')then
+ iext=1
+ endif
+!
+ call mpp_get_global_domain (atm(1)%domain, isg, ieg, jsg, jeg, position=CENTER )
+ istart_g=isg-halo
+ iend_g =ieg+halo+iext
+ jstart_g=jsg-halo
+ jend_g =jeg+halo+jext
+!
+ count_i=iend_g-istart_g+1
+ count_j=jend_g-jstart_g+1
+!
+ nz=size(fields_core(nv)%ptr,3)
+!
+ allocate( global_field(istart_g:iend_g, jstart_g:jend_g, 1:nz) )
+!
+!-----------------------------------------------------------------------
+!*** What is the local extent of the variable on the task subdomain?
+!*** We must exclude inner halo data since the data is not updated
+!*** there in some of the variables. Of course the outer halo data
+!*** around the domain boundary is included.
+!-----------------------------------------------------------------------
+!
+ istart=lbound(fields_core(nv)%ptr,1)
+ if(istart>1)then
+ istart=istart+halo
+ endif
+!
+ iend =ubound(fields_core(nv)%ptr,1)
+ if(iend1)then
+ jstart=jstart+halo
+ endif
+!
+ jend =ubound(fields_core(nv)%ptr,2)
+ if(jend1)then
+ istart=istart+halo
+ endif
+!
+ iend =ubnd_x_tracers
+ if(iend1)then
+ jstart=jstart+halo
+ endif
+!
+ jend =ubnd_y_tracers
+ if(jend Atm%q(:,:,:,sphum_index) rather than as was done
+!*** for the core arrays which was ptr => Atm%u .
+!-----------------------------------------------------------------------
+!
+ istart_ptr=halo+1
+ iend_ptr =ubnd_x_tracers-lbnd_x_tracers+1-halo
+ jstart_ptr=halo+1
+ jend_ptr =ubnd_y_tracers-lbnd_y_tracers+1-halo
+!
+ if(north_bc)then
+ jstart_ptr=1
+ endif
+ if(south_bc)then
+ jend_ptr=ubnd_y_tracers-lbnd_y_tracers+1
+ endif
+ if(east_bc)then
+ istart_ptr=1
+ endif
+ if(west_bc)then
+ iend_ptr=ubnd_x_tracers-lbnd_x_tracers+1
+ endif
+!
+!-----------------------------------------------------------------------
+!*** Loop through that file's prognostic tracers.
+!-----------------------------------------------------------------------
+!
+ vbls_tracers: do nv=1,nvars_tracers
+!
+ var_name=fields_tracers(nv)%name
+ if(is_root_pe)then
+ call check(nf90_inq_varid(ncid_tracers_new,var_name,var_id)) !<-- Get this variable's ID
+ endif
+!
+!-----------------------------------------------------------------------
+!*** Since we are gathering onto a single task then do so one layer
+!*** at a time to avoid potential memory problems for large high
+!*** resolution domains. Then that task writes the full data to the
+!*** new file.
+!-----------------------------------------------------------------------
+!
+ do k=1,nz
+ call mpp_gather(istart,iend,jstart,jend &
+ ,pelist, fields_tracers(nv)%ptr(istart_ptr:iend_ptr,jstart_ptr:jend_ptr,k) &
+ ,global_field(:,:,k), is_root_pe, halo, halo)
+!
+ if(is_root_pe)then
+ call check(nf90_put_var(ncid_tracers_new,var_id &
+ ,global_field(:,:,k) &
+ ,start=(/1,1,k/) &
+ ,count=(/count_i,count_j,1/)))
+ endif
+ enddo
+!
+ enddo vbls_tracers
+!
+ deallocate(global_field)
+!
+ if(is_root_pe)then
+ call check(nf90_close(ncid_tracers_new))
+ endif
+!
+!---------------------------------------------------------------------
+ end subroutine write_full_fields
+!---------------------------------------------------------------------
+!---------------------------------------------------------------------
+!
+ subroutine sensible_temp(istart,iend,jstart,jend,nz &
+ ,Atm &
+ ,temp)
+!
+!---------------------------------------------------------------------
+!*** Convert the special potential temperature in the domain
+!*** halo rows to sensible temperature.
+!---------------------------------------------------------------------
+!
+!------------------------
+!*** Argument variables
+!------------------------
+!
+ integer,intent(in) :: istart,iend,jstart,jend
+!
+ type(fv_atmos_type),intent(inout) :: Atm
+!
+ real,dimension(istart:iend,jstart:jend,1:nz),intent(inout) :: temp
+!
+!---------------------
+!*** Local variables
+!---------------------
+!
+ integer :: i1,i2,j1,j2,nz
+!
+ real :: rdg
+!
+!---------------------------------------------------------------------
+!*********************************************************************
+!---------------------------------------------------------------------
+!
+ if(.not.(north_bc.or.south_bc.or.east_bc.or.west_bc))then
+ return !<-- Tasks not on the boundary may exit.
+ endif
+!
+ rdg=-rdgas/grav
+!
+!---------------------------------------------------------------------
+!
+ if(north_bc)then
+ i1=istart
+ i2=iend
+ j1=jstart
+ j2=jstart+nhalo_model-1
+ call compute_halo_t
+ endif
+!
+ if(south_bc)then
+ i1=istart
+ i2=iend
+ j1=jend-nhalo_model+1
+ j2=jend
+ call compute_halo_t
+ endif
+!
+ if(east_bc)then
+ i1=istart
+ i2=istart+nhalo_model-1
+ j1=jstart
+ j2=jend
+ if(north_bc)then
+ j1=jstart+nhalo_model
+ elseif(south_bc)then
+ j2=jend-nhalo_model
+ endif
+ call compute_halo_t
+ endif
+!
+ if(west_bc)then
+ i1=iend-nhalo_model+1
+ i2=iend
+ j1=jstart
+ j2=jend
+ if(north_bc)then
+ j1=jstart+nhalo_model
+ elseif(south_bc)then
+ j2=jend-nhalo_model
+ endif
+ call compute_halo_t
+ endif
+!
+!---------------------------------------------------------------------
+ contains
+!---------------------------------------------------------------------
+!
+ subroutine compute_halo_t
+!
+!---------------------------------------------------------------------
+!
+ integer :: i,j,k
+!
+ real :: cappa,cvm,dp1,part1,part2
+!
+!---------------------------------------------------------------------
+!*********************************************************************
+!---------------------------------------------------------------------
+!
+ do k=1,nz
+ do j=j1,j2
+ do i=i1,i2
+ dp1 = zvir*Atm%q(i,j,k,sphum_index)
+ cvm=(1.-Atm%q(i,j,k,sphum_index)+Atm%q_con(i,j,k))*cv_air &
+ +Atm%q(i,j,k,sphum_index)*cv_vap &
+ +Atm%q(i,j,k,liq_water_index)*c_liq
+ cappa=rdgas/(rdgas+cvm/(1.+dp1))
+!
+ part1=(1.+dp1)*(1.-Atm%q_con(i,j,k))
+ part2=rdg*Atm%delp(i,j,k)*(1.+dp1)*(1.-Atm%q_con(i,j,k)) &
+ /Atm%delz(i,j,k)
+ temp(i,j,k)=exp((log(temp(i,j,k))-log(part1)+cappa*log(part2)) &
+ /(1.-cappa))
+ enddo
+ enddo
+ enddo
+!
+!---------------------------------------------------------------------
+ end subroutine compute_halo_t
+!---------------------------------------------------------------------
+!
+ end subroutine sensible_temp
+!
!---------------------------------------------------------------------
!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
!---------------------------------------------------------------------
@@ -5158,6 +6435,10 @@ subroutine exch_uv(domain, bd, npz, u, v)
end subroutine exch_uv
+!---------------------------------------------------------------------
+!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+!---------------------------------------------------------------------
+
subroutine get_data_source(source,regional)
!
! This routine extracts the data source information if it is present in the datafile.
@@ -5179,6 +6460,10 @@ subroutine get_data_source(source,regional)
endif
end subroutine get_data_source
+!---------------------------------------------------------------------
+!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+!---------------------------------------------------------------------
+
subroutine set_delp_and_tracers(BC_side,npz,nwat)
!
! This routine mimics what is done in external_ic to add mass back to delp
diff --git a/model/fv_sg.F90 b/model/fv_sg.F90
index 594e54873..a88cfdfe1 100644
--- a/model/fv_sg.F90
+++ b/model/fv_sg.F90
@@ -299,6 +299,7 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, &
enddo
elseif ( nwat==4 ) then
do i=is,ie
+#ifndef CCPP
q_liq = q0(i,k,liq_wat) + q0(i,k,rainwat)
#ifdef MULTI_GASES
cpm(i) = (1.-(q0(i,k,sphum)+q_liq))*cp_air*vicpqd(q0(i,k,:)) + q0(i,k,sphum)*cp_vapor + q_liq*c_liq
@@ -306,6 +307,20 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, &
#else
cpm(i) = (1.-(q0(i,k,sphum)+q_liq))*cp_air + q0(i,k,sphum)*cp_vapor + q_liq*c_liq
cvm(i) = (1.-(q0(i,k,sphum)+q_liq))*cv_air + q0(i,k,sphum)*cv_vap + q_liq*c_liq
+#endif
+
+#else
+ q_liq = q0(i,k,liq_wat) + q0(i,k,rainwat)
+ q_sol = q0(i,k,ice_wat)
+#ifdef MULTI_GASES
+ cpm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cp_air*vicpqd(q0(i,k,:)) + q0(i,k,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice
+ cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air*vicvqd(q0(i,k,:)) + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice
+#else
+ cpm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cp_air + q0(i,k,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice
+ cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice
+#endif
+
+
#endif
enddo
elseif ( nwat==5 ) then
@@ -382,7 +397,11 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, &
elseif ( nwat==4 ) then
do k=1,kbot
do i=is,ie
+#ifndef CCPP
qcon(i,k) = q0(i,k,liq_wat) + q0(i,k,rainwat)
+#else
+ qcon(i,k) = q0(i,k,liq_wat) + q0(i,k,rainwat) + q0(i,k,ice_wat)
+#endif
enddo
enddo
elseif ( nwat==5 ) then
@@ -451,7 +470,12 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, &
elseif ( nwat==3 ) then ! AM3/AM4
qcon(i,km1) = q0(i,km1,liq_wat) + q0(i,km1,ice_wat)
elseif ( nwat==4 ) then ! K_warm_rain scheme with fake ice
+#ifndef CCPP
qcon(i,km1) = q0(i,km1,liq_wat) + q0(i,km1,rainwat)
+#else
+ qcon(i,km1) = q0(i,km1,liq_wat) + q0(i,km1,ice_wat) + &
+ q0(i,km1,rainwat)
+#endif
elseif ( nwat==5 ) then ! K_warm_rain scheme with fake ice
qcon(i,km1) = q0(i,km1,liq_wat) + q0(i,km1,ice_wat) + &
q0(i,km1,snowwat) + q0(i,km1,rainwat)
@@ -572,6 +596,7 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, &
enddo
elseif ( nwat == 4 ) then
do i=is,ie
+#ifndef CCPP
q_liq = q0(i,kk,liq_wat) + q0(i,kk,rainwat)
#ifdef MULTI_GASES
cpm(i) = (1.-(q0(i,kk,sphum)+q_liq))*cp_air*vicpqd(q0(i,kk,:)) + q0(i,kk,sphum)*cp_vapor + q_liq*c_liq
@@ -579,6 +604,19 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, &
#else
cpm(i) = (1.-(q0(i,kk,sphum)+q_liq))*cp_air + q0(i,kk,sphum)*cp_vapor + q_liq*c_liq
cvm(i) = (1.-(q0(i,kk,sphum)+q_liq))*cv_air + q0(i,kk,sphum)*cv_vap + q_liq*c_liq
+#endif
+#else
+ q_liq = q0(i,kk,liq_wat) + q0(i,kk,rainwat)
+ q_sol = q0(i,kk,ice_wat)
+#ifdef MULTI_GASES
+ cpm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cp_air*vicpqd(q0(i,kk,:)) + q0(i,kk,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice
+ cvm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cv_air*vicvqd(q0(i,kk,:)) + q0(i,kk,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice
+#else
+ cpm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cp_air + q0(i,kk,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice
+ cvm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cv_air + q0(i,kk,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice
+#endif
+
+
#endif
enddo
elseif ( nwat == 5 ) then
@@ -850,6 +888,7 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, &
enddo
elseif ( nwat==4 ) then
do i=is,ie
+#ifndef CCPP
q_liq = q0(i,k,liq_wat) + q0(i,k,rainwat)
#ifdef MULTI_GASES
cpm(i) = (1.-(q0(i,k,sphum)+q_liq))*cp_air*vicpqd(q0(i,k,:)) + q0(i,k,sphum)*cp_vapor + q_liq*c_liq
@@ -857,6 +896,18 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, &
#else
cpm(i) = (1.-(q0(i,k,sphum)+q_liq))*cp_air + q0(i,k,sphum)*cp_vapor + q_liq*c_liq
cvm(i) = (1.-(q0(i,k,sphum)+q_liq))*cv_air + q0(i,k,sphum)*cv_vap + q_liq*c_liq
+#endif
+#else
+ q_liq = q0(i,k,liq_wat) + q0(i,k,rainwat)
+ q_sol = q0(i,k,ice_wat)
+#ifdef MULTI_GASES
+ cpm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cp_air*vicpqd(q0(i,k,:)) + q0(i,k,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice
+ cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air*vicvqd(q0(i,k,:)) + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice
+#else
+ cpm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cp_air + q0(i,k,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice
+ cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice
+#endif
+
#endif
enddo
elseif ( nwat==5 ) then
@@ -933,7 +984,11 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, &
elseif ( nwat==4 ) then
do k=1,kbot
do i=is,ie
+#ifndef CCPP
qcon(i,k) = q0(i,k,liq_wat) + q0(i,k,rainwat)
+#else
+ qcon(i,k) = q0(i,k,liq_wat) + q0(i,k,rainwat) + q0(i,k,ice_wat)
+#endif
enddo
enddo
elseif ( nwat==5 ) then
@@ -998,7 +1053,11 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, &
elseif ( nwat==3 ) then ! AM3/AM4
qcon(i,km1) = q0(i,km1,liq_wat) + q0(i,km1,ice_wat)
elseif ( nwat==4 ) then ! K_warm_rain scheme with fake ice
+#ifndef CCPP
qcon(i,km1) = q0(i,km1,liq_wat) + q0(i,km1,rainwat)
+#else
+ qcon(i,km1) = q0(i,km1,liq_wat) + q0(i,km1,rainwat) + q0(i,km1,ice_wat)
+#endif
elseif ( nwat==5 ) then
qcon(i,km1) = q0(i,km1,liq_wat) + q0(i,km1,ice_wat) + &
q0(i,km1,snowwat) + q0(i,km1,rainwat)
@@ -1118,6 +1177,7 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, &
enddo
elseif ( nwat == 4 ) then
do i=is,ie
+#ifndef CCPP
q_liq = q0(i,kk,liq_wat) + q0(i,kk,rainwat)
#ifdef MULTI_GASES
cpm(i) = (1.-(q0(i,kk,sphum)+q_liq))*cp_air*vicpqd(q0(i,kk,:)) + q0(i,kk,sphum)*cp_vapor + q_liq*c_liq
@@ -1125,6 +1185,18 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, &
#else
cpm(i) = (1.-(q0(i,kk,sphum)+q_liq))*cp_air + q0(i,kk,sphum)*cp_vapor + q_liq*c_liq
cvm(i) = (1.-(q0(i,kk,sphum)+q_liq))*cv_air + q0(i,kk,sphum)*cv_vap + q_liq*c_liq
+#endif
+#else
+ q_liq = q0(i,kk,liq_wat) + q0(i,kk,rainwat)
+ q_sol = q0(i,kk,ice_wat)
+#ifdef MULTI_GASES
+ cpm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cp_air*vicpqd(q0(i,kk,:)) + q0(i,kk,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice
+ cvm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cv_air*vicvqd(q0(i,kk,:)) + q0(i,kk,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice
+#else
+ cpm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cp_air + q0(i,kk,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice
+ cvm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cv_air + q0(i,kk,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice
+#endif
+
#endif
enddo
elseif ( nwat == 5 ) then
diff --git a/tools/external_ic.F90 b/tools/external_ic.F90
index 66157aa5e..c0d416921 100644
--- a/tools/external_ic.F90
+++ b/tools/external_ic.F90
@@ -207,11 +207,12 @@ module external_ic_mod
contains
- subroutine get_external_ic( Atm, fv_domain, cold_start )
+ subroutine get_external_ic( Atm, fv_domain, cold_start, dt_atmos )
type(fv_atmos_type), intent(inout), target :: Atm(:)
type(domain2d), intent(inout) :: fv_domain
logical, intent(IN) :: cold_start
+ real, intent(IN) :: dt_atmos
real:: alpha = 0.
real rdg
integer i,j,k,nq
@@ -288,7 +289,7 @@ subroutine get_external_ic( Atm, fv_domain, cold_start )
#endif
elseif ( Atm(1)%flagstruct%nggps_ic ) then
call timing_on('NGGPS_IC')
- call get_nggps_ic( Atm, fv_domain )
+ call get_nggps_ic( Atm, fv_domain, dt_atmos )
call timing_off('NGGPS_IC')
elseif ( Atm(1)%flagstruct%ecmwf_ic ) then
if( is_master() ) write(*,*) 'Calling get_ecmwf_ic'
@@ -442,7 +443,7 @@ end subroutine get_cubed_sphere_terrain
!>@brief The subroutine 'get_nggps_ic' reads in data after it has been preprocessed with
!! NCEP/EMC orography maker and 'global_chgres', and has been horiztontally
!! interpolated to the current cubed-sphere grid
- subroutine get_nggps_ic (Atm, fv_domain)
+ subroutine get_nggps_ic (Atm, fv_domain, dt_atmos )
!>variables read in from 'gfs_ctrl.nc'
!> VCOORD - level information
@@ -471,6 +472,7 @@ subroutine get_nggps_ic (Atm, fv_domain)
type(fv_atmos_type), intent(inout) :: Atm(:)
type(domain2d), intent(inout) :: fv_domain
+ real, intent(in) :: dt_atmos
! local:
real, dimension(:), allocatable:: ak, bk
real, dimension(:,:), allocatable:: wk2, ps, oro_g
@@ -840,14 +842,6 @@ subroutine get_nggps_ic (Atm, fv_domain)
Atm(n)%ak(1:npz+1) = ak(itoa:levp+1)
Atm(n)%bk(1:npz+1) = bk(itoa:levp+1)
call set_external_eta (Atm(n)%ak, Atm(n)%bk, Atm(n)%ptop, Atm(n)%ks)
- else
- if ( npz <= 64 ) then
- Atm(n)%ak(:) = ak_sj(:)
- Atm(n)%bk(:) = bk_sj(:)
- Atm(n)%ptop = Atm(n)%ak(1)
- else
- call set_eta(npz, ks, Atm(n)%ptop, Atm(n)%ak, Atm(n)%bk)
- endif
endif
! call vertical remapping algorithms
if(is_master()) write(*,*) 'GFS ak =', ak,' FV3 ak=',Atm(n)%ak
@@ -861,7 +855,7 @@ subroutine get_nggps_ic (Atm, fv_domain)
if (n==1.and.Atm(1)%flagstruct%regional) then !<-- Select the parent regional domain.
- call start_regional_cold_start(Atm(1), ak, bk, levp, &
+ call start_regional_cold_start(Atm(1), dt_atmos, ak, bk, levp, &
is, ie, js, je, &
isd, ied, jsd, jed )
endif
@@ -1581,13 +1575,13 @@ subroutine get_ecmwf_ic( Atm, fv_domain )
! Set up model's ak and bk
- if ( npz <= 64 ) then
- Atm(1)%ak(:) = ak_sj(:)
- Atm(1)%bk(:) = bk_sj(:)
- Atm(1)%ptop = Atm(1)%ak(1)
- else
- call set_eta(npz, ks, Atm(1)%ptop, Atm(1)%ak, Atm(1)%bk)
- endif
+! if ( npz <= 64 ) then
+! Atm(1)%ak(:) = ak_sj(:)
+! Atm(1)%bk(:) = bk_sj(:)
+! Atm(1)%ptop = Atm(1)%ak(1)
+! else
+! call set_eta(npz, ks, Atm(1)%ptop, Atm(1)%ak, Atm(1)%bk)
+! endif
!! Read in model terrain from oro_data.tile?.nc
if (filtered_terrain) then
diff --git a/tools/external_ic.F90_65lyrs b/tools/external_ic.F90_65lyrs
new file mode 100644
index 000000000..d525f8419
--- /dev/null
+++ b/tools/external_ic.F90_65lyrs
@@ -0,0 +1,4287 @@
+
+!***********************************************************************
+!* GNU Lesser General Public License
+!*
+!* This file is part of the FV3 dynamical core.
+!*
+!* The FV3 dynamical core is free software: you can redistribute it
+!* and/or modify it under the terms of the
+!* GNU Lesser General Public License as published by the
+!* Free Software Foundation, either version 3 of the License, or
+!* (at your option) any later version.
+!*
+!* The FV3 dynamical core is distributed in the hope that it will be
+!* useful, but WITHOUT ANYWARRANTY; without even the implied warranty
+!* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+!* See the GNU General Public License for more details.
+!*
+!* You should have received a copy of the GNU Lesser General Public
+!* License along with the FV3 dynamical core.
+!* If not, see .
+!***********************************************************************
+
+#ifdef OVERLOAD_R4
+#define _GET_VAR1 get_var1_real
+#else
+#define _GET_VAR1 get_var1_double
+#endif
+
+!>@brief The module 'external_ic_mod' contains routines that read in and
+!! remap initial conditions.
+
+module external_ic_mod
+
+!
+!
+! | Module Name |
+! Functions Included |
+!
+!
+! | constants_mod |
+! pi=>pi_8, omega, grav, kappa, rdgas, rvgas, cp_air |
+!
+!
+! | external_sst_mod |
+! i_sst, j_sst, sst_ncep |
+!
+!
+! | field_manager_mod |
+! MODEL_ATMOS |
+!
+!
+! | fms_mod |
+! file_exist, read_data, field_exist, write_version_number,
+! open_namelist_file, check_nml_error, close_file,
+! get_mosaic_tile_file, read_data, error_mesg |
+!
+!
+! | fms_io_mod |
+! get_tile_string, field_size, free_restart_type,
+! restart_file_type, register_restart_field,
+! save_restart, restore_state |
+!
+!
+! | fv_arrays_mod |
+! fv_atmos_type, fv_grid_type, fv_grid_bounds_type, R_GRID |
+!
+!
+! | fv_control_mod |
+! fv_init, fv_end, ngrids |
+!
+!
+! | fv_diagnostics_mod |
+! prt_maxmin, prt_gb_nh_sh, prt_height |
+!
+!
+! | fv_eta_mod |
+! set_eta, set_external_eta |
+!
+!
+! | fv_fill_mod |
+! fillz |
+!
+!
+! | fv_grid_utils_mod |
+! ptop_min, g_sum,mid_pt_sphere,get_unit_vect2,
+! get_latlon_vector,inner_prod |
+!
+!
+! | fv_io_mod |
+! fv_io_read_tracers |
+!
+!
+! | fv_mp_mod |
+! ng, is_master, fill_corners, YDir, mp_reduce_min, mp_reduce_max |
+!
+!
+! | fv_mapz_mod |
+! mappm |
+!
+!
+! | fv_nwp_nudge_mod |
+! T_is_Tv |
+!
+!
+! | fv_surf_map_mod |
+! surfdrv, FV3_zs_filter,sgh_g, oro_g,del2_cubed_sphere, del4_cubed_sphere |
+!
+!
+! | fv_timing_mod |
+! timing_on, timing_off |
+!
+!
+! | fv_update_phys_mod |
+! fv_update_phys |
+!
+!
+! | init_hydro_mod |
+! p_var |
+!
+!
+! | mpp_mod |
+! mpp_error, FATAL, NOTE, mpp_pe, mpp_root_pe,stdlog, input_nml_file |
+!
+!
+! | mpp_domains_mod |
+! mpp_get_tile_id, domain2d, mpp_update_domains, NORTH, EAST |
+!
+!
+! | mpp_parameter_mod |
+! AGRID_PARAM=>AGRID |
+!
+!
+! | sim_nc_mod |
+! open_ncfile, close_ncfile, get_ncdim1, get_var1_double, get_var2_real,
+! get_var3_r4, get_var2_r4, get_var1_real, get_var_att_double |
+!
+!
+! | tracer_manager_mod |
+! get_tracer_names, get_number_tracers, get_tracer_index, set_tracer_profile |
+!
+!
+! | test_cases_mod |
+! checker_tracers |
+!
+!
+
+ use netcdf
+ use external_sst_mod, only: i_sst, j_sst, sst_ncep
+ use fms_mod, only: file_exist, read_data, field_exist, write_version_number
+ use fms_mod, only: open_namelist_file, check_nml_error, close_file
+ use fms_mod, only: get_mosaic_tile_file, read_data, error_mesg
+ use fms_io_mod, only: get_tile_string, field_size, free_restart_type
+ use fms_io_mod, only: restart_file_type, register_restart_field
+ use fms_io_mod, only: save_restart, restore_state
+ use mpp_mod, only: mpp_error, FATAL, NOTE, mpp_pe, mpp_root_pe
+ use mpp_mod, only: stdlog, input_nml_file
+ use mpp_parameter_mod, only: AGRID_PARAM=>AGRID
+ use mpp_domains_mod, only: mpp_get_tile_id, domain2d, mpp_update_domains, NORTH, EAST
+ use tracer_manager_mod, only: get_tracer_names, get_number_tracers, get_tracer_index
+ use tracer_manager_mod, only: set_tracer_profile
+ use field_manager_mod, only: MODEL_ATMOS
+
+ use constants_mod, only: pi=>pi_8, omega, grav, kappa, rdgas, rvgas, cp_air
+ use fv_arrays_mod, only: fv_atmos_type, fv_grid_type, fv_grid_bounds_type, R_GRID
+ use fv_diagnostics_mod,only: prt_maxmin, prt_gb_nh_sh, prt_height
+ use fv_grid_utils_mod, only: ptop_min, g_sum,mid_pt_sphere,get_unit_vect2,get_latlon_vector,inner_prod
+ use fv_io_mod, only: fv_io_read_tracers
+ use fv_mapz_mod, only: mappm
+
+ use fv_regional_mod, only: dump_field, H_STAGGER, U_STAGGER, V_STAGGER, get_data_source
+ use fv_mp_mod, only: ng, is_master, fill_corners, YDir, mp_reduce_min, mp_reduce_max
+ use fv_regional_mod, only: start_regional_cold_start
+ use fv_surf_map_mod, only: surfdrv, FV3_zs_filter
+ use fv_surf_map_mod, only: sgh_g, oro_g
+ use fv_surf_map_mod, only: del2_cubed_sphere, del4_cubed_sphere
+ use fv_timing_mod, only: timing_on, timing_off
+ use init_hydro_mod, only: p_var
+ use fv_fill_mod, only: fillz
+ use fv_eta_mod, only: set_eta, set_external_eta
+ use sim_nc_mod, only: open_ncfile, close_ncfile, get_ncdim1, get_var1_double, get_var2_real, &
+ get_var3_r4, get_var2_r4, get_var1_real, get_var_att_double
+ use fv_nwp_nudge_mod, only: T_is_Tv
+ use test_cases_mod, only: checker_tracers
+
+! The "T" field in NCEP analysis is actually virtual temperature (Larry H. post processing)
+! BEFORE 20051201
+
+ use boundary_mod, only: nested_grid_BC, extrapolation_BC
+ use mpp_domains_mod, only: mpp_get_data_domain, mpp_get_global_domain, mpp_get_compute_domain
+
+#ifdef MULTI_GASES
+ use multi_gases_mod, only: virq, virqd, vicpqd
+#endif
+
+ implicit none
+ private
+
+ real, parameter:: zvir = rvgas/rdgas - 1.
+ real(kind=R_GRID), parameter :: cnst_0p20=0.20d0
+ real :: deg2rad
+ character (len = 80) :: source ! This tells what the input source was for the data
+ public get_external_ic, get_cubed_sphere_terrain
+
+! version number of this module
+! Include variable "version" to be written to log file.
+#include
+
+contains
+
+ subroutine get_external_ic( Atm, fv_domain, cold_start, dt_atmos )
+
+ type(fv_atmos_type), intent(inout), target :: Atm(:)
+ type(domain2d), intent(inout) :: fv_domain
+ logical, intent(IN) :: cold_start
+ real, intent(IN) :: dt_atmos
+ real:: alpha = 0.
+ real rdg
+ integer i,j,k,nq
+
+ real, pointer, dimension(:,:,:) :: grid, agrid
+ real, pointer, dimension(:,:) :: fC, f0
+
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+ integer :: sphum, liq_wat, ice_wat, rainwat, snowwat, graupel
+#ifdef CCPP
+ integer :: liq_aero, ice_aero
+#endif
+#ifdef MULTI_GASES
+ integer :: spfo, spfo2, spfo3
+#else
+ integer :: o3mr
+#endif
+
+ is = Atm(1)%bd%is
+ ie = Atm(1)%bd%ie
+ js = Atm(1)%bd%js
+ je = Atm(1)%bd%je
+ isd = Atm(1)%bd%isd
+ ied = Atm(1)%bd%ied
+ jsd = Atm(1)%bd%jsd
+ jed = Atm(1)%bd%jed
+
+ grid => Atm(1)%gridstruct%grid
+ agrid => Atm(1)%gridstruct%agrid
+
+ fC => Atm(1)%gridstruct%fC
+ f0 => Atm(1)%gridstruct%f0
+
+! * Initialize coriolis param:
+
+ do j=jsd,jed+1
+ do i=isd,ied+1
+ fc(i,j) = 2.*omega*( -1.*cos(grid(i,j,1))*cos(grid(i,j,2))*sin(alpha) + &
+ sin(grid(i,j,2))*cos(alpha) )
+ enddo
+ enddo
+
+ do j=jsd,jed
+ do i=isd,ied
+ f0(i,j) = 2.*omega*( -1.*cos(agrid(i,j,1))*cos(agrid(i,j,2))*sin(alpha) + &
+ sin(agrid(i,j,2))*cos(alpha) )
+ enddo
+ enddo
+
+ call mpp_update_domains( f0, fv_domain )
+ if ( Atm(1)%gridstruct%cubed_sphere .and. (.not. (Atm(1)%neststruct%nested .or. Atm(1)%flagstruct%regional)))then
+ call fill_corners(f0, Atm(1)%npx, Atm(1)%npy, YDir)
+ endif
+
+! Read in cubed_sphere terrain
+ if ( Atm(1)%flagstruct%mountain ) then
+ call get_cubed_sphere_terrain(Atm, fv_domain)
+ else
+ if (.not. Atm(1)%neststruct%nested) Atm(1)%phis = 0.
+ endif
+
+! Read in the specified external dataset and do all the needed transformation
+ if ( Atm(1)%flagstruct%ncep_ic ) then
+ nq = 1
+ call timing_on('NCEP_IC')
+ call get_ncep_ic( Atm, fv_domain, nq )
+ call timing_off('NCEP_IC')
+#ifdef FV_TRACERS
+ if (.not. cold_start) then
+ call fv_io_read_tracers( fv_domain, Atm )
+ if(is_master()) write(*,*) 'All tracers except sphum replaced by FV IC'
+ endif
+#endif
+ elseif ( Atm(1)%flagstruct%nggps_ic ) then
+ call timing_on('NGGPS_IC')
+ call get_nggps_ic( Atm, fv_domain, dt_atmos )
+ call timing_off('NGGPS_IC')
+ elseif ( Atm(1)%flagstruct%ecmwf_ic ) then
+ if( is_master() ) write(*,*) 'Calling get_ecmwf_ic'
+ call timing_on('ECMWF_IC')
+ call get_ecmwf_ic( Atm, fv_domain )
+ call timing_off('ECMWF_IC')
+ else
+! The following is to read in legacy lat-lon FV core restart file
+! is Atm%q defined in all cases?
+ nq = size(Atm(1)%q,4)
+ call get_fv_ic( Atm, fv_domain, nq )
+ endif
+
+ call prt_maxmin('PS', Atm(1)%ps, is, ie, js, je, ng, 1, 0.01)
+ call prt_maxmin('T', Atm(1)%pt, is, ie, js, je, ng, Atm(1)%npz, 1.)
+ if (.not.Atm(1)%flagstruct%hydrostatic) call prt_maxmin('W', Atm(1)%w, is, ie, js, je, ng, Atm(1)%npz, 1.)
+ call prt_maxmin('SPHUM', Atm(1)%q(:,:,:,1), is, ie, js, je, ng, Atm(1)%npz, 1.)
+ if ( Atm(1)%flagstruct%nggps_ic ) then
+ call prt_maxmin('TS', Atm(1)%ts, is, ie, js, je, 0, 1, 1.)
+ endif
+ if ( Atm(1)%flagstruct%nggps_ic .or. Atm(1)%flagstruct%ecmwf_ic ) then
+ sphum = get_tracer_index(MODEL_ATMOS, 'sphum')
+ liq_wat = get_tracer_index(MODEL_ATMOS, 'liq_wat')
+ ice_wat = get_tracer_index(MODEL_ATMOS, 'ice_wat')
+ rainwat = get_tracer_index(MODEL_ATMOS, 'rainwat')
+ snowwat = get_tracer_index(MODEL_ATMOS, 'snowwat')
+ graupel = get_tracer_index(MODEL_ATMOS, 'graupel')
+#ifdef MULTI_GASES
+ spfo = get_tracer_index(MODEL_ATMOS, 'spfo')
+ spfo2 = get_tracer_index(MODEL_ATMOS, 'spfo2')
+ spfo3 = get_tracer_index(MODEL_ATMOS, 'spfo3')
+#else
+ o3mr = get_tracer_index(MODEL_ATMOS, 'o3mr')
+#endif
+#ifdef CCPP
+ liq_aero = get_tracer_index(MODEL_ATMOS, 'liq_aero')
+ ice_aero = get_tracer_index(MODEL_ATMOS, 'ice_aero')
+#endif
+
+ if ( liq_wat > 0 ) &
+ call prt_maxmin('liq_wat', Atm(1)%q(:,:,:,liq_wat), is, ie, js, je, ng, Atm(1)%npz, 1.)
+ if ( ice_wat > 0 ) &
+ call prt_maxmin('ice_wat', Atm(1)%q(:,:,:,ice_wat), is, ie, js, je, ng, Atm(1)%npz, 1.)
+ if ( rainwat > 0 ) &
+ call prt_maxmin('rainwat', Atm(1)%q(:,:,:,rainwat), is, ie, js, je, ng, Atm(1)%npz, 1.)
+ if ( snowwat > 0 ) &
+ call prt_maxmin('snowwat', Atm(1)%q(:,:,:,snowwat), is, ie, js, je, ng, Atm(1)%npz, 1.)
+ if ( graupel > 0 ) &
+ call prt_maxmin('graupel', Atm(1)%q(:,:,:,graupel), is, ie, js, je, ng, Atm(1)%npz, 1.)
+#ifdef MULTI_GASES
+ if ( spfo > 0 ) &
+ call prt_maxmin('SPFO', Atm(1)%q(:,:,:,spfo), is, ie, js, je, ng, Atm(1)%npz, 1.)
+ if ( spfo2 > 0 ) &
+ call prt_maxmin('SPFO2', Atm(1)%q(:,:,:,spfo2), is, ie, js, je, ng, Atm(1)%npz, 1.)
+ if ( spfo3 > 0 ) &
+ call prt_maxmin('SPFO3', Atm(1)%q(:,:,:,spfo3), is, ie, js, je, ng, Atm(1)%npz, 1.)
+#else
+ if ( o3mr > 0 ) &
+ call prt_maxmin('O3MR', Atm(1)%q(:,:,:,o3mr), is, ie, js, je, ng, Atm(1)%npz, 1.)
+#endif
+#ifdef CCPP
+ if ( liq_aero > 0) &
+ call prt_maxmin('liq_aero',Atm(1)%q(:,:,:,liq_aero),is, ie, js, je, ng, Atm(1)%npz, 1.)
+ if ( ice_aero > 0) &
+ call prt_maxmin('ice_aero',Atm(1)%q(:,:,:,ice_aero),is, ie, js, je, ng, Atm(1)%npz, 1.)
+#endif
+ endif
+
+ call p_var(Atm(1)%npz, is, ie, js, je, Atm(1)%ak(1), ptop_min, &
+ Atm(1)%delp, Atm(1)%delz, Atm(1)%pt, Atm(1)%ps, &
+ Atm(1)%pe, Atm(1)%peln, Atm(1)%pk, Atm(1)%pkz, &
+ kappa, Atm(1)%q, ng, Atm(1)%ncnst, Atm(1)%gridstruct%area_64, Atm(1)%flagstruct%dry_mass, &
+ Atm(1)%flagstruct%adjust_dry_mass, Atm(1)%flagstruct%mountain, Atm(1)%flagstruct%moist_phys, &
+ Atm(1)%flagstruct%hydrostatic, Atm(1)%flagstruct%nwat, Atm(1)%domain, Atm(1)%flagstruct%make_nh)
+
+ end subroutine get_external_ic
+
+
+!------------------------------------------------------------------
+ subroutine get_cubed_sphere_terrain( Atm, fv_domain )
+ type(fv_atmos_type), intent(inout), target :: Atm(:)
+ type(domain2d), intent(inout) :: fv_domain
+ integer :: ntileMe
+ integer, allocatable :: tile_id(:)
+ character(len=64) :: fname
+ character(len=7) :: gn
+ integer :: n
+ integer :: jbeg, jend
+ real ftop
+ real, allocatable :: g_dat2(:,:,:)
+ real, allocatable :: pt_coarse(:,:,:)
+ integer isc_p, iec_p, jsc_p, jec_p, isg, ieg, jsg,jeg
+
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+
+ is = Atm(1)%bd%is
+ ie = Atm(1)%bd%ie
+ js = Atm(1)%bd%js
+ je = Atm(1)%bd%je
+ isd = Atm(1)%bd%isd
+ ied = Atm(1)%bd%ied
+ jsd = Atm(1)%bd%jsd
+ jed = Atm(1)%bd%jed
+
+ if (Atm(1)%grid_number > 1) then
+ !write(gn,'(A2, I1)') ".g", Atm(1)%grid_number
+ write(gn,'(A5, I2.2)') ".nest", Atm(1)%grid_number
+ else
+ gn = ''
+ end if
+
+ ntileMe = size(Atm(:)) ! This will have to be modified for mult tiles per PE
+ ! ASSUMED always one at this point
+
+ allocate( tile_id(ntileMe) )
+ tile_id = mpp_get_tile_id( fv_domain )
+ do n=1,ntileMe
+
+ call get_tile_string(fname, 'INPUT/fv_core.res'//trim(gn)//'.tile', tile_id(n), '.nc' )
+ if (mpp_pe() == mpp_root_pe()) print*, 'external_ic: looking for ', fname
+
+
+ if( file_exist(fname) ) then
+ call read_data(fname, 'phis', Atm(n)%phis(is:ie,js:je), &
+ domain=fv_domain, tile_count=n)
+ else
+ call surfdrv( Atm(n)%npx, Atm(n)%npy, Atm(n)%gridstruct%grid_64, Atm(n)%gridstruct%agrid_64, &
+ Atm(n)%gridstruct%area_64, Atm(n)%gridstruct%dx, Atm(n)%gridstruct%dy, &
+ Atm(n)%gridstruct%dxa, Atm(n)%gridstruct%dya, &
+ Atm(n)%gridstruct%dxc, Atm(n)%gridstruct%dyc, Atm(n)%gridstruct%sin_sg, &
+ Atm(n)%phis, Atm(n)%flagstruct%stretch_fac, &
+ Atm(n)%neststruct%nested, Atm(n)%neststruct%npx_global, Atm(N)%domain, &
+ Atm(n)%flagstruct%grid_number, Atm(n)%bd, Atm(n)%flagstruct%regional )
+ call mpp_error(NOTE,'terrain datasets generated using USGS data')
+ endif
+
+ end do
+
+! Needed for reproducibility. DON'T REMOVE THIS!!
+ call mpp_update_domains( Atm(1)%phis, Atm(1)%domain )
+ ftop = g_sum(Atm(1)%domain, Atm(1)%phis(is:ie,js:je), is, ie, js, je, ng, Atm(1)%gridstruct%area_64, 1)
+
+ call prt_maxmin('ZS', Atm(1)%phis, is, ie, js, je, ng, 1, 1./grav)
+ if(is_master()) write(*,*) 'mean terrain height (m)=', ftop/grav
+
+ deallocate( tile_id )
+
+ end subroutine get_cubed_sphere_terrain
+
+!>@brief The subroutine 'get_nggps_ic' reads in data after it has been preprocessed with
+!! NCEP/EMC orography maker and 'global_chgres', and has been horiztontally
+!! interpolated to the current cubed-sphere grid
+ subroutine get_nggps_ic (Atm, fv_domain, dt_atmos )
+
+!>variables read in from 'gfs_ctrl.nc'
+!> VCOORD - level information
+!> maps to 'ak & bk'
+!> variables read in from 'sfc_data.nc'
+!> land_frac - land-sea-ice mask (L:0 / S:1)
+!> maps to 'oro'
+!> TSEA - surface skin temperature (k)
+!> maps to 'ts'
+!> variables read in from 'gfs_data.nc'
+!> ZH - GFS grid height at edges (m)
+!> PS - surface pressure (Pa)
+!> U_W - D-grid west face tangential wind component (m/s)
+!> V_W - D-grid west face normal wind component (m/s)
+!> U_S - D-grid south face tangential wind component (m/s)
+!> V_S - D-grid south face normal wind component (m/s)
+!> OMGA- vertical velocity 'omega' (Pa/s)
+!> Q - prognostic tracer fields
+!> Namelist variables
+!> filtered_terrain - use orography maker filtered terrain mapping
+#ifdef __PGI
+ use GFS_restart, only : GFS_restart_type
+
+ implicit none
+#endif
+
+ type(fv_atmos_type), intent(inout) :: Atm(:)
+ type(domain2d), intent(inout) :: fv_domain
+ real, intent(in) :: dt_atmos
+! local:
+ real, dimension(:), allocatable:: ak, bk
+ real, dimension(:,:), allocatable:: wk2, ps, oro_g
+ real, dimension(:,:,:), allocatable:: ud, vd, u_w, v_w, u_s, v_s, omga, temp
+ real, dimension(:,:,:), allocatable:: zh(:,:,:) ! 3D height at 65 edges
+ real, dimension(:,:,:,:), allocatable:: q
+ real, dimension(:,:), allocatable :: phis_coarse ! lmh
+ real rdg, wt, qt, m_fac
+ integer:: n, npx, npy, npz, itoa, nt, ntprog, ntdiag, ntracers, ntrac, iq
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+ integer :: ios, ierr, unit, id_res
+ type (restart_file_type) :: ORO_restart, SFC_restart, GFS_restart
+ character(len=6) :: gn, stile_name
+ character(len=64) :: tracer_name
+ character(len=64) :: fn_gfs_ctl = 'gfs_ctrl.nc'
+ character(len=64) :: fn_gfs_ics = 'gfs_data.nc'
+ character(len=64) :: fn_sfc_ics = 'sfc_data.nc'
+ character(len=64) :: fn_oro_ics = 'oro_data.nc'
+ ! DH* character(len=64) :: fn_aero_ics = 'aero_data.nc' *DH
+ logical :: remap
+ logical :: filtered_terrain = .true.
+ logical :: gfs_dwinds = .true.
+ integer :: levp = 64
+ logical :: checker_tr = .false.
+ integer :: nt_checker = 0
+ real(kind=R_GRID), dimension(2):: p1, p2, p3
+ real(kind=R_GRID), dimension(3):: e1, e2, ex, ey
+ integer:: i,j,k,nts, ks
+ integer:: liq_wat, ice_wat, rainwat, snowwat, graupel, ntclamt
+ namelist /external_ic_nml/ filtered_terrain, levp, gfs_dwinds, &
+ checker_tr, nt_checker
+#ifdef GFSL64
+ real, dimension(65):: ak_sj, bk_sj
+ data ak_sj/20.00000, 68.00000, 137.79000, &
+ 221.95800, 318.26600, 428.43400, &
+ 554.42400, 698.45700, 863.05803, &
+ 1051.07995, 1265.75194, 1510.71101, &
+ 1790.05098, 2108.36604, 2470.78817, &
+ 2883.03811, 3351.46002, 3883.05187, &
+ 4485.49315, 5167.14603, 5937.04991, &
+ 6804.87379, 7780.84698, 8875.64338, &
+ 9921.40745, 10760.99844, 11417.88354, &
+ 11911.61193, 12258.61668, 12472.89642, &
+ 12566.58298, 12550.43517, 12434.26075, &
+ 12227.27484, 11938.39468, 11576.46910, &
+ 11150.43640, 10669.41063, 10142.69482, &
+ 9579.72458, 8989.94947, 8382.67090, &
+ 7766.85063, 7150.91171, 6542.55077, &
+ 5948.57894, 5374.81094, 4825.99383, &
+ 4305.79754, 3816.84622, 3360.78848, &
+ 2938.39801, 2549.69756, 2194.08449, &
+ 1870.45732, 1577.34218, 1313.00028, &
+ 1075.52114, 862.90778, 673.13815, &
+ 504.22118, 354.22752, 221.32110, &
+ 103.78014, 0./
+ data bk_sj/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00179, 0.00705, 0.01564, &
+ 0.02749, 0.04251, 0.06064, &
+ 0.08182, 0.10595, 0.13294, &
+ 0.16266, 0.19492, 0.22950, &
+ 0.26615, 0.30455, 0.34435, &
+ 0.38516, 0.42656, 0.46815, &
+ 0.50949, 0.55020, 0.58989, &
+ 0.62825, 0.66498, 0.69987, &
+ 0.73275, 0.76351, 0.79208, &
+ 0.81845, 0.84264, 0.86472, &
+ 0.88478, 0.90290, 0.91923, &
+ 0.93388, 0.94697, 0.95865, &
+ 0.96904, 0.97826, 0.98642, &
+ 0.99363, 1./
+#else
+! The following L63 setting is the same as NCEP GFS's L64 except the top layer
+ real, dimension(64):: ak_sj, bk_sj
+ data ak_sj/64.247, 137.790, 221.958, &
+ 318.266, 428.434, 554.424, &
+ 698.457, 863.05803, 1051.07995, &
+ 1265.75194, 1510.71101, 1790.05098, &
+ 2108.36604, 2470.78817, 2883.03811, &
+ 3351.46002, 3883.05187, 4485.49315, &
+ 5167.14603, 5937.04991, 6804.87379, &
+ 7780.84698, 8875.64338, 10100.20534, &
+ 11264.35673, 12190.64366, 12905.42546, &
+ 13430.87867, 13785.88765, 13986.77987, &
+ 14047.96335, 13982.46770, 13802.40331, &
+ 13519.33841, 13144.59486, 12689.45608, &
+ 12165.28766, 11583.57006, 10955.84778, &
+ 10293.60402, 9608.08306, 8910.07678, &
+ 8209.70131, 7516.18560, 6837.69250, &
+ 6181.19473, 5552.39653, 4955.72632, &
+ 4394.37629, 3870.38682, 3384.76586, &
+ 2937.63489, 2528.37666, 2155.78385, &
+ 1818.20722, 1513.68173, 1240.03585, &
+ 994.99144, 776.23591, 581.48797, &
+ 408.53400, 255.26520, 119.70243, 0. /
+
+ data bk_sj/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00201, 0.00792, 0.01755, &
+ 0.03079, 0.04751, 0.06761, &
+ 0.09097, 0.11746, 0.14690, &
+ 0.17911, 0.21382, 0.25076, &
+ 0.28960, 0.32994, 0.37140, &
+ 0.41353, 0.45589, 0.49806, &
+ 0.53961, 0.58015, 0.61935, &
+ 0.65692, 0.69261, 0.72625, &
+ 0.75773, 0.78698, 0.81398, &
+ 0.83876, 0.86138, 0.88192, &
+ 0.90050, 0.91722, 0.93223, &
+ 0.94565, 0.95762, 0.96827, &
+ 0.97771, 0.98608, 0.99347, 1./
+#endif
+
+#ifdef TEMP_GFSPLV
+ real, dimension(64):: ak_sj, bk_sj
+ data ak_sj/64.247, 137.79, 221.958, &
+ 318.266, 428.434, 554.424, &
+ 698.457, 863.058, 1051.08, &
+ 1265.752, 1510.711, 1790.051, &
+ 2108.366, 2470.788, 2883.038, &
+ 3351.46, 3883.052, 4485.493, &
+ 5167.146, 5937.05, 6804.874, &
+ 7777.15, 8832.537, 9936.614, &
+ 11054.85, 12152.94, 13197.07, &
+ 14154.32, 14993.07, 15683.49, &
+ 16197.97, 16511.74, 16611.6, &
+ 16503.14, 16197.32, 15708.89, &
+ 15056.34, 14261.43, 13348.67, &
+ 12344.49, 11276.35, 10171.71, &
+ 9057.051, 7956.908, 6893.117, &
+ 5884.206, 4945.029, 4086.614, &
+ 3316.217, 2637.553, 2051.15, &
+ 1554.789, 1143.988, 812.489, &
+ 552.72, 356.223, 214.015, &
+ 116.899, 55.712, 21.516, &
+ 5.741, 0.575, 0., 0. /
+
+ data bk_sj/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00003697, 0.00043106, 0.00163591, &
+ 0.00410671, 0.00829402, 0.01463712, &
+ 0.02355588, 0.03544162, 0.05064684, &
+ 0.06947458, 0.09216691, 0.1188122, &
+ 0.1492688, 0.1832962, 0.2205702, &
+ 0.2606854, 0.3031641, 0.3474685, &
+ 0.3930182, 0.4392108, 0.4854433, &
+ 0.5311348, 0.5757467, 0.6187996, &
+ 0.659887, 0.6986829, 0.7349452, &
+ 0.7685147, 0.7993097, 0.8273188, &
+ 0.8525907, 0.8752236, 0.895355, &
+ 0.913151, 0.9287973, 0.9424911, &
+ 0.9544341, 0.9648276, 0.9738676, &
+ 0.9817423, 0.9886266, 0.9946712, 1./
+#endif
+
+ call mpp_error(NOTE,'Using external_IC::get_nggps_ic which is valid only for data which has been &
+ &horizontally interpolated to the current cubed-sphere grid')
+#ifdef INTERNAL_FILE_NML
+ read (input_nml_file,external_ic_nml,iostat=ios)
+ ierr = check_nml_error(ios,'external_ic_nml')
+#else
+ unit=open_namelist_file()
+ read (unit,external_ic_nml,iostat=ios)
+ ierr = check_nml_error(ios,'external_ic_nml')
+ call close_file(unit)
+#endif
+
+ unit = stdlog()
+ call write_version_number ( 'EXTERNAL_IC_mod::get_nggps_ic', version )
+ write(unit, nml=external_ic_nml)
+
+ remap = .true.
+ if (Atm(1)%flagstruct%external_eta) then
+ if (filtered_terrain) then
+ call mpp_error(NOTE,'External_IC::get_nggps_ic - use externally-generated, filtered terrain &
+ &and NCEP pressure levels (no vertical remapping)')
+ else if (.not. filtered_terrain) then
+ call mpp_error(NOTE,'External_IC::get_nggps_ic - use externally-generated, raw terrain &
+ &and NCEP pressure levels (no vertical remapping)')
+ endif
+ else ! (.not.external_eta)
+ if (filtered_terrain) then
+ call mpp_error(NOTE,'External_IC::get_nggps_ic - use externally-generated, filtered terrain &
+ &and FV3 pressure levels (vertical remapping)')
+ else if (.not. filtered_terrain) then
+ call mpp_error(NOTE,'External_IC::get_nggps_ic - use externally-generated, raw terrain &
+ &and FV3 pressure levels (vertical remapping)')
+ endif
+ endif
+
+ is = Atm(1)%bd%is
+ ie = Atm(1)%bd%ie
+ js = Atm(1)%bd%js
+ je = Atm(1)%bd%je
+ isd = Atm(1)%bd%isd
+ ied = Atm(1)%bd%ied
+ jsd = Atm(1)%bd%jsd
+ jed = Atm(1)%bd%jed
+ npz = Atm(1)%npz
+ write(*,22001)is,ie,js,je,isd,ied,jsd,jed
+22001 format(' enter get_nggps_ic is=',i4,' ie=',i4,' js=',i4,' je=',i4,' isd=',i4,' ied=',i4,' jsd=',i4,' jed=',i4)
+ call get_number_tracers(MODEL_ATMOS, num_tracers=ntracers, num_prog=ntprog)
+ ntdiag = ntracers-ntprog
+
+!--- test for existence of the GFS control file
+ if (.not. file_exist('INPUT/'//trim(fn_gfs_ctl), no_domain=.TRUE.)) then
+ call mpp_error(FATAL,'==> Error in External_ic::get_nggps_ic: file '//trim(fn_gfs_ctl)//' for NGGPS IC does not exist')
+ endif
+ call mpp_error(NOTE,'==> External_ic::get_nggps_ic: using control file '//trim(fn_gfs_ctl)//' for NGGPS IC')
+
+!--- read in the number of tracers in the NCEP NGGPS ICs
+ call read_data ('INPUT/'//trim(fn_gfs_ctl), 'ntrac', ntrac, no_domain=.TRUE.)
+ if (ntrac > ntracers) call mpp_error(FATAL,'==> External_ic::get_nggps_ic: more NGGPS tracers &
+ &than defined in field_table '//trim(fn_gfs_ctl)//' for NGGPS IC')
+
+!--- read in ak and bk from the gfs control file using fms_io read_data ---
+ allocate (wk2(levp+1,2))
+ allocate (ak(levp+1))
+ allocate (bk(levp+1))
+ call read_data('INPUT/'//trim(fn_gfs_ctl),'vcoord',wk2, no_domain=.TRUE.)
+ ak(1:levp+1) = wk2(1:levp+1,1)
+ bk(1:levp+1) = wk2(1:levp+1,2)
+ deallocate (wk2)
+
+ if (.not. file_exist('INPUT/'//trim(fn_oro_ics), domain=Atm(1)%domain)) then
+ call mpp_error(FATAL,'==> Error in External_ic::get_nggps_ic: tiled file '//trim(fn_oro_ics)//' for NGGPS IC does not exist')
+ endif
+ call mpp_error(NOTE,'==> External_ic::get_nggps_ic: using tiled data file '//trim(fn_oro_ics)//' for NGGPS IC')
+
+ if (.not. file_exist('INPUT/'//trim(fn_sfc_ics), domain=Atm(1)%domain)) then
+ call mpp_error(FATAL,'==> Error in External_ic::get_nggps_ic: tiled file '//trim(fn_sfc_ics)//' for NGGPS IC does not exist')
+ endif
+ call mpp_error(NOTE,'==> External_ic::get_nggps_ic: using tiled data file '//trim(fn_sfc_ics)//' for NGGPS IC')
+
+ if (.not. file_exist('INPUT/'//trim(fn_gfs_ics), domain=Atm(1)%domain)) then
+ call mpp_error(FATAL,'==> Error in External_ic::get_nggps_ic: tiled file '//trim(fn_gfs_ics)//' for NGGPS IC does not exist')
+ endif
+ call mpp_error(NOTE,'==> External_ic::get_nggps_ic: using tiled data file '//trim(fn_gfs_ics)//' for NGGPS IC')
+!
+ call get_data_source(source,Atm(1)%flagstruct%regional)
+!
+ allocate (zh(is:ie,js:je,levp+1)) ! SJL
+ allocate (ps(is:ie,js:je))
+ allocate (omga(is:ie,js:je,levp))
+ allocate (q (is:ie,js:je,levp,ntracers))
+ allocate ( u_w(is:ie+1, js:je, 1:levp) )
+ allocate ( v_w(is:ie+1, js:je, 1:levp) )
+ allocate ( u_s(is:ie, js:je+1, 1:levp) )
+ allocate ( v_s(is:ie, js:je+1, 1:levp) )
+ allocate (temp(is:ie,js:je,levp))
+
+ do n = 1,size(Atm(:))
+
+ !!! If a nested grid, save the filled coarse-grid topography for blending
+ if (Atm(n)%neststruct%nested) then
+ allocate(phis_coarse(isd:ied,jsd:jed))
+ do j=jsd,jed
+ do i=isd,ied
+ phis_coarse(i,j) = Atm(n)%phis(i,j)
+ enddo
+ enddo
+ endif
+
+!--- read in surface temperature (k) and land-frac
+ ! surface skin temperature
+ id_res = register_restart_field (SFC_restart, fn_sfc_ics, 'tsea', Atm(n)%ts, domain=Atm(n)%domain)
+
+ ! terrain surface height -- (needs to be transformed into phis = zs*grav)
+ if (filtered_terrain) then
+ id_res = register_restart_field (ORO_restart, fn_oro_ics, 'orog_filt', Atm(n)%phis, domain=Atm(n)%domain)
+ elseif (.not. filtered_terrain) then
+ id_res = register_restart_field (ORO_restart, fn_oro_ics, 'orog_raw', Atm(n)%phis, domain=Atm(n)%domain)
+ endif
+
+ if ( Atm(n)%flagstruct%full_zs_filter) then
+ allocate (oro_g(isd:ied,jsd:jed))
+ oro_g = 0.
+ ! land-frac
+ id_res = register_restart_field (ORO_restart, fn_oro_ics, 'land_frac', oro_g, domain=Atm(n)%domain)
+ call mpp_update_domains(oro_g, Atm(n)%domain)
+ if (Atm(n)%neststruct%nested) then
+ call extrapolation_BC(oro_g, 0, 0, Atm(n)%npx, Atm(n)%npy, Atm(n)%bd, .true.)
+ endif
+ endif
+
+ if ( Atm(n)%flagstruct%fv_land ) then
+ ! stddev
+ id_res = register_restart_field (ORO_restart, fn_oro_ics, 'stddev', Atm(n)%sgh, domain=Atm(n)%domain)
+ ! land-frac
+ id_res = register_restart_field (ORO_restart, fn_oro_ics, 'land_frac', Atm(n)%oro, domain=Atm(n)%domain)
+ endif
+
+ ! surface pressure (Pa)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'ps', ps, domain=Atm(n)%domain)
+
+ ! D-grid west face tangential wind component (m/s)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'u_w', u_w, domain=Atm(n)%domain,position=EAST)
+ ! D-grid west face normal wind component (m/s)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'v_w', v_w, domain=Atm(n)%domain,position=EAST)
+ ! D-grid south face tangential wind component (m/s)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'u_s', u_s, domain=Atm(n)%domain,position=NORTH)
+ ! D-grid south face normal wind component (m/s)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'v_s', v_s, domain=Atm(n)%domain,position=NORTH)
+
+ ! vertical velocity 'omega' (Pa/s)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'w', omga, domain=Atm(n)%domain)
+ ! GFS grid height at edges (including surface height)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'ZH', zh, domain=Atm(n)%domain)
+ ! real temperature (K)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 't', temp, mandatory=.false., &
+ domain=Atm(n)%domain)
+ ! prognostic tracers
+ do nt = 1, ntracers
+ call get_tracer_names(MODEL_ATMOS, nt, tracer_name)
+ ! DH* if aerosols are in separate file, need to test for indices liq_aero and ice_aero and change fn_gfs_ics to fn_aero_ics *DH
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, trim(tracer_name), q(:,:,:,nt), &
+ mandatory=.false.,domain=Atm(n)%domain)
+ enddo
+
+ ! initialize all tracers to default values prior to being input
+ do nt = 1, ntprog
+ call get_tracer_names(MODEL_ATMOS, nt, tracer_name)
+ ! set all tracers to an initial profile value
+ call set_tracer_profile (MODEL_ATMOS, nt, Atm(n)%q(:,:,:,nt) )
+ enddo
+ do nt = ntprog+1, ntracers
+ call get_tracer_names(MODEL_ATMOS, nt, tracer_name)
+ ! set all tracers to an initial profile value
+ call set_tracer_profile (MODEL_ATMOS, nt, Atm(n)%qdiag(:,:,:,nt) )
+ enddo
+
+ ! read in the restart
+ call restore_state (ORO_restart)
+ call restore_state (SFC_restart)
+ call restore_state (GFS_restart)
+
+ ! free the restart type to be re-used by the nest
+ call free_restart_type(ORO_restart)
+ call free_restart_type(SFC_restart)
+ call free_restart_type(GFS_restart)
+
+ ! multiply NCEP ICs terrain 'phis' by gravity to be true geopotential
+ Atm(n)%phis = Atm(n)%phis*grav
+
+ ! set the pressure levels and ptop to be used
+ if (Atm(1)%flagstruct%external_eta) then
+ itoa = levp - npz + 1
+ Atm(n)%ptop = ak(itoa)
+ Atm(n)%ak(1:npz+1) = ak(itoa:levp+1)
+ Atm(n)%bk(1:npz+1) = bk(itoa:levp+1)
+ call set_external_eta (Atm(n)%ak, Atm(n)%bk, Atm(n)%ptop, Atm(n)%ks)
+ else
+ if ( npz <= 64 ) then
+ Atm(n)%ak(:) = ak_sj(:)
+ Atm(n)%bk(:) = bk_sj(:)
+ Atm(n)%ptop = Atm(n)%ak(1)
+ else
+ call set_eta(npz, ks, Atm(n)%ptop, Atm(n)%ak, Atm(n)%bk)
+ endif
+ endif
+ ! call vertical remapping algorithms
+ if(is_master()) write(*,*) 'GFS ak =', ak,' FV3 ak=',Atm(n)%ak
+ ak(1) = max(1.e-9, ak(1))
+
+!*** For regional runs read in each of the BC variables from the NetCDF boundary file
+!*** and remap in the vertical from the input levels to the model integration levels.
+!*** Here in the initialization we begn by allocating the regional domain's boundary
+!*** objects. Then we need to read the first two regional BC files so the integration
+!*** can begin interpolating between those two times as the forecast proceeds.
+
+ if (n==1.and.Atm(1)%flagstruct%regional) then !<-- Select the parent regional domain.
+
+ call start_regional_cold_start(Atm(1), dt_atmos, ak, bk, levp, &
+ is, ie, js, je, &
+ isd, ied, jsd, jed )
+ endif
+
+!
+!*** Remap the variables in the compute domain.
+!
+ call remap_scalar_nggps(Atm(n), levp, npz, ntracers, ak, bk, ps, temp, q, omga, zh)
+
+ allocate ( ud(is:ie, js:je+1, 1:levp) )
+ allocate ( vd(is:ie+1,js:je, 1:levp) )
+
+!$OMP parallel do default(none) shared(is,ie,js,je,levp,Atm,ud,vd,u_s,v_s,u_w,v_w) &
+!$OMP private(p1,p2,p3,e1,e2,ex,ey)
+ do k=1,levp
+ do j=js,je+1
+ do i=is,ie
+ p1(:) = Atm(1)%gridstruct%grid(i, j,1:2)
+ p2(:) = Atm(1)%gridstruct%grid(i+1,j,1:2)
+ call mid_pt_sphere(p1, p2, p3)
+ call get_unit_vect2(p1, p2, e1)
+ call get_latlon_vector(p3, ex, ey)
+ ud(i,j,k) = u_s(i,j,k)*inner_prod(e1,ex) + v_s(i,j,k)*inner_prod(e1,ey)
+ enddo
+ enddo
+ do j=js,je
+ do i=is,ie+1
+ p1(:) = Atm(1)%gridstruct%grid(i,j ,1:2)
+ p2(:) = Atm(1)%gridstruct%grid(i,j+1,1:2)
+ call mid_pt_sphere(p1, p2, p3)
+ call get_unit_vect2(p1, p2, e2)
+ call get_latlon_vector(p3, ex, ey)
+ vd(i,j,k) = u_w(i,j,k)*inner_prod(e2,ex) + v_w(i,j,k)*inner_prod(e2,ey)
+ enddo
+ enddo
+ enddo
+ deallocate ( u_w )
+ deallocate ( v_w )
+ deallocate ( u_s )
+ deallocate ( v_s )
+
+ call remap_dwinds(levp, npz, ak, bk, ps, ud, vd, Atm(n))
+
+ deallocate ( ud )
+ deallocate ( vd )
+
+ if (Atm(n)%neststruct%nested) then
+ if (is_master()) write(*,*) 'Blending nested and coarse grid topography'
+ npx = Atm(n)%npx
+ npy = Atm(n)%npy
+ do j=jsd,jed
+ do i=isd,ied
+ wt = max(0.,min(1.,real(5 - min(i,j,npx-i,npy-j,5))/5. ))
+ Atm(n)%phis(i,j) = (1.-wt)*Atm(n)%phis(i,j) + wt*phis_coarse(i,j)
+ enddo
+ enddo
+ endif
+
+
+ !!! Perform terrain smoothing, if desired
+ if ( Atm(n)%flagstruct%full_zs_filter ) then
+
+ call mpp_update_domains(Atm(n)%phis, Atm(n)%domain)
+
+ call FV3_zs_filter( Atm(n)%bd, isd, ied, jsd, jed, npx, npy, Atm(n)%neststruct%npx_global, &
+ Atm(n)%flagstruct%stretch_fac, Atm(n)%neststruct%nested, Atm(n)%domain, &
+ Atm(n)%gridstruct%area_64, Atm(n)%gridstruct%dxa, Atm(n)%gridstruct%dya, &
+ Atm(n)%gridstruct%dx, Atm(n)%gridstruct%dy, Atm(n)%gridstruct%dxc, &
+ Atm(n)%gridstruct%dyc, Atm(n)%gridstruct%grid_64, Atm(n)%gridstruct%agrid_64, &
+ Atm(n)%gridstruct%sin_sg, Atm(n)%phis, oro_g, Atm(n)%flagstruct%regional)
+ deallocate(oro_g)
+ endif
+
+
+ if ( Atm(n)%flagstruct%n_zs_filter > 0 ) then
+
+ if ( Atm(n)%flagstruct%nord_zs_filter == 2 ) then
+ call del2_cubed_sphere(Atm(n)%npx, Atm(n)%npy, Atm(n)%phis, &
+ Atm(n)%gridstruct%area_64, Atm(n)%gridstruct%dx, Atm(n)%gridstruct%dy, &
+ Atm(n)%gridstruct%dxc, Atm(n)%gridstruct%dyc, Atm(n)%gridstruct%sin_sg, &
+ Atm(n)%flagstruct%n_zs_filter, cnst_0p20*Atm(n)%gridstruct%da_min, &
+ .false., oro_g, Atm(n)%neststruct%nested, Atm(n)%domain, Atm(n)%bd, Atm(n)%flagstruct%regional)
+ if ( is_master() ) write(*,*) 'Warning !!! del-2 terrain filter has been applied ', &
+ Atm(n)%flagstruct%n_zs_filter, ' times'
+ else if( Atm(n)%flagstruct%nord_zs_filter == 4 ) then
+ call del4_cubed_sphere(Atm(n)%npx, Atm(n)%npy, Atm(n)%phis, Atm(n)%gridstruct%area_64, &
+ Atm(n)%gridstruct%dx, Atm(n)%gridstruct%dy, &
+ Atm(n)%gridstruct%dxc, Atm(n)%gridstruct%dyc, Atm(n)%gridstruct%sin_sg, &
+ Atm(n)%flagstruct%n_zs_filter, .false., oro_g, Atm(n)%neststruct%nested, &
+ Atm(n)%domain, Atm(n)%bd, Atm(n)%flagstruct%regional)
+ if ( is_master() ) write(*,*) 'Warning !!! del-4 terrain filter has been applied ', &
+ Atm(n)%flagstruct%n_zs_filter, ' times'
+ endif
+
+ endif
+
+ if ( Atm(n)%neststruct%nested .and. ( Atm(n)%flagstruct%n_zs_filter > 0 .or. Atm(n)%flagstruct%full_zs_filter ) ) then
+ npx = Atm(n)%npx
+ npy = Atm(n)%npy
+ do j=jsd,jed
+ do i=isd,ied
+ wt = max(0.,min(1.,real(5 - min(i,j,npx-i,npy-j,5))/5. ))
+ Atm(n)%phis(i,j) = (1.-wt)*Atm(n)%phis(i,j) + wt*phis_coarse(i,j)
+ enddo
+ enddo
+ deallocate(phis_coarse)
+ endif
+
+ call mpp_update_domains( Atm(n)%phis, Atm(n)%domain, complete=.true. )
+ liq_wat = get_tracer_index(MODEL_ATMOS, 'liq_wat')
+ ice_wat = get_tracer_index(MODEL_ATMOS, 'ice_wat')
+ rainwat = get_tracer_index(MODEL_ATMOS, 'rainwat')
+ snowwat = get_tracer_index(MODEL_ATMOS, 'snowwat')
+ graupel = get_tracer_index(MODEL_ATMOS, 'graupel')
+ ntclamt = get_tracer_index(MODEL_ATMOS, 'cld_amt')
+ if (trim(source) == 'FV3GFS GAUSSIAN NEMSIO FILE') then
+ do k=1,npz
+ do j=js,je
+ do i=is,ie
+ wt = Atm(n)%delp(i,j,k)
+ if ( Atm(n)%flagstruct%nwat == 6 ) then
+ qt = wt*(1. + Atm(n)%q(i,j,k,liq_wat) + &
+ Atm(n)%q(i,j,k,ice_wat) + &
+ Atm(n)%q(i,j,k,rainwat) + &
+ Atm(n)%q(i,j,k,snowwat) + &
+ Atm(n)%q(i,j,k,graupel))
+ else ! all other values of nwat
+ qt = wt*(1. + sum(Atm(n)%q(i,j,k,2:Atm(n)%flagstruct%nwat)))
+ endif
+ Atm(n)%delp(i,j,k) = qt
+ if (ntclamt > 0) Atm(n)%q(i,j,k,ntclamt) = 0.0 ! Moorthi
+ enddo
+ enddo
+ enddo
+ else
+!--- Add cloud condensate from GFS to total MASS
+! 20160928: Adjust the mixing ratios consistently...
+ do k=1,npz
+ do j=js,je
+ do i=is,ie
+ wt = Atm(n)%delp(i,j,k)
+ if ( Atm(n)%flagstruct%nwat == 6 ) then
+ qt = wt*(1. + Atm(n)%q(i,j,k,liq_wat) + &
+ Atm(n)%q(i,j,k,ice_wat) + &
+ Atm(n)%q(i,j,k,rainwat) + &
+ Atm(n)%q(i,j,k,snowwat) + &
+ Atm(n)%q(i,j,k,graupel))
+ else ! all other values of nwat
+ qt = wt*(1. + sum(Atm(n)%q(i,j,k,2:Atm(n)%flagstruct%nwat)))
+ endif
+ m_fac = wt / qt
+ do iq=1,ntracers
+ Atm(n)%q(i,j,k,iq) = m_fac * Atm(n)%q(i,j,k,iq)
+ enddo
+ Atm(n)%delp(i,j,k) = qt
+ if (ntclamt > 0) Atm(n)%q(i,j,k,ntclamt) = 0.0 ! Moorthi
+ enddo
+ enddo
+ enddo
+ endif !end trim(source) test
+
+!--- reset the tracers beyond condensate to a checkerboard pattern
+ if (checker_tr) then
+ nts = ntracers - nt_checker+1
+ call checker_tracers(is,ie, js,je, isd,ied, jsd,jed, nt_checker, &
+ npz, Atm(n)%q(:,:,:,nts:ntracers), &
+ Atm(n)%gridstruct%agrid_64(is:ie,js:je,1), &
+ Atm(n)%gridstruct%agrid_64(is:ie,js:je,2), 9., 9.)
+ endif
+ enddo ! n-loop
+
+ Atm(1)%flagstruct%make_nh = .false.
+
+ deallocate (ak)
+ deallocate (bk)
+ deallocate (ps)
+ deallocate (q )
+ deallocate (temp)
+ deallocate (omga)
+
+ end subroutine get_nggps_ic
+!------------------------------------------------------------------
+!------------------------------------------------------------------
+!>@brief The subroutine 'get_ncep_ic' reads in the specified NCEP analysis or reanalysis dataset
+ subroutine get_ncep_ic( Atm, fv_domain, nq )
+ type(fv_atmos_type), intent(inout) :: Atm(:)
+ type(domain2d), intent(inout) :: fv_domain
+ integer, intent(in):: nq
+! local:
+#ifdef HIWPP_ETA
+ real :: ak_HIWPP(65), bk_HIWPP(65)
+ data ak_HIWPP/ &
+ 0, 0.00064247, 0.0013779, 0.00221958, 0.00318266, 0.00428434, &
+ 0.00554424, 0.00698457, 0.00863058, 0.0105108, 0.01265752, 0.01510711, &
+ 0.01790051, 0.02108366, 0.02470788, 0.02883038, 0.0335146, 0.03883052, &
+ 0.04485493, 0.05167146, 0.0593705, 0.06804874, 0.0777715, 0.08832537, &
+ 0.09936614, 0.1105485, 0.1215294, 0.1319707, 0.1415432, 0.1499307, &
+ 0.1568349, 0.1619797, 0.1651174, 0.166116, 0.1650314, 0.1619731, &
+ 0.1570889, 0.1505634, 0.1426143, 0.1334867, 0.1234449, 0.1127635, &
+ 0.1017171, 0.09057051, 0.07956908, 0.06893117, 0.05884206, 0.04945029, &
+ 0.04086614, 0.03316217, 0.02637553, 0.0205115, 0.01554789, 0.01143988, &
+ 0.00812489, 0.0055272, 0.00356223, 0.00214015, 0.00116899, 0.00055712, &
+ 0.00021516, 5.741e-05, 5.75e-06, 0, 0 /
+
+ data bk_HIWPP/ &
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &
+ 3.697e-05, 0.00043106, 0.00163591, 0.00410671, 0.00829402, 0.01463712, &
+ 0.02355588, 0.03544162, 0.05064684, 0.06947458, 0.09216691, 0.1188122, &
+ 0.1492688, 0.1832962, 0.2205702, 0.2606854, 0.3031641, 0.3474685, &
+ 0.3930182, 0.4392108, 0.4854433, 0.5311348, 0.5757467, 0.6187996, &
+ 0.659887, 0.6986829, 0.7349452, 0.7685147, 0.7993097, 0.8273188, &
+ 0.8525907, 0.8752236, 0.895355, 0.913151, 0.9287973, 0.9424911, &
+ 0.9544341, 0.9648276, 0.9738676, 0.9817423, 0.9886266, 0.9946712, 1 /
+#endif
+ character(len=128) :: fname
+ real(kind=4), allocatable:: wk1(:), wk2(:,:), wk3(:,:,:)
+ real, allocatable:: tp(:,:,:), qp(:,:,:)
+ real, allocatable:: ua(:,:,:), va(:,:,:)
+ real, allocatable:: lat(:), lon(:), ak0(:), bk0(:)
+ real:: s2c(Atm(1)%bd%is:Atm(1)%bd%ie,Atm(1)%bd%js:Atm(1)%bd%je,4)
+ integer, dimension(Atm(1)%bd%is:Atm(1)%bd%ie,Atm(1)%bd%js:Atm(1)%bd%je):: id1, id2, jdc
+ real psc(Atm(1)%bd%is:Atm(1)%bd%ie,Atm(1)%bd%js:Atm(1)%bd%je)
+ real gzc(Atm(1)%bd%is:Atm(1)%bd%ie,Atm(1)%bd%js:Atm(1)%bd%je)
+ real tmean
+ integer:: i, j, k, im, jm, km, npz, npt
+ integer:: i1, i2, j1, ncid
+ integer:: jbeg, jend
+ integer tsize(3)
+ logical:: read_ts = .true.
+ logical:: land_ts = .false.
+ logical:: found
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+
+ is = Atm(1)%bd%is
+ ie = Atm(1)%bd%ie
+ js = Atm(1)%bd%js
+ je = Atm(1)%bd%je
+ isd = Atm(1)%bd%isd
+ ied = Atm(1)%bd%ied
+ jsd = Atm(1)%bd%jsd
+ jed = Atm(1)%bd%jed
+
+ deg2rad = pi/180.
+
+ npz = Atm(1)%npz
+
+! Zero out all initial tracer fields:
+! SJL: 20110716
+! Atm(1)%q = 0.
+
+ fname = Atm(1)%flagstruct%res_latlon_dynamics
+
+ if( file_exist(fname) ) then
+ call open_ncfile( fname, ncid ) ! open the file
+ call get_ncdim1( ncid, 'lon', tsize(1) )
+ call get_ncdim1( ncid, 'lat', tsize(2) )
+ call get_ncdim1( ncid, 'lev', tsize(3) )
+
+ im = tsize(1); jm = tsize(2); km = tsize(3)
+
+ if(is_master()) write(*,*) fname
+ if(is_master()) write(*,*) ' NCEP IC dimensions:', tsize
+
+ allocate ( lon(im) )
+ allocate ( lat(jm) )
+
+ call _GET_VAR1(ncid, 'lon', im, lon )
+ call _GET_VAR1(ncid, 'lat', jm, lat )
+
+! Convert to radian
+ do i=1,im
+ lon(i) = lon(i) * deg2rad ! lon(1) = 0.
+ enddo
+ do j=1,jm
+ lat(j) = lat(j) * deg2rad
+ enddo
+
+ allocate ( ak0(km+1) )
+ allocate ( bk0(km+1) )
+
+#ifdef HIWPP_ETA
+! The HIWPP data from Jeff does not contain (ak,bk)
+ do k=1, km+1
+ ak0(k) = ak_HIWPP (k)
+ bk0(k) = bk_HIWPP (k)
+ enddo
+#else
+ call _GET_VAR1(ncid, 'hyai', km+1, ak0, found )
+ if ( .not. found ) ak0(:) = 0.
+
+ call _GET_VAR1(ncid, 'hybi', km+1, bk0 )
+#endif
+ if( is_master() ) then
+ do k=1,km+1
+ write(*,*) k, ak0(k), bk0(k)
+ enddo
+ endif
+
+! Note: definition of NCEP hybrid is p(k) = a(k)*1.E5 + b(k)*ps
+ ak0(:) = ak0(:) * 1.E5
+
+! Limiter to prevent NAN at top during remapping
+ if ( bk0(1) < 1.E-9 ) ak0(1) = max(1.e-9, ak0(1))
+
+ else
+ call mpp_error(FATAL,'==> Error in get_external_ic: Expected file '//trim(fname)//' for NCEP IC does not exist')
+ endif
+
+! Initialize lat-lon to Cubed bi-linear interpolation coeff:
+ call remap_coef( is, ie, js, je, isd, ied, jsd, jed, &
+ im, jm, lon, lat, id1, id2, jdc, s2c , Atm(1)%gridstruct%agrid)
+
+! Find bounding latitudes:
+ jbeg = jm-1; jend = 2
+ do j=js,je
+ do i=is,ie
+ j1 = jdc(i,j)
+ jbeg = min(jbeg, j1)
+ jend = max(jend, j1+1)
+ enddo
+ enddo
+
+! remap surface pressure and height:
+
+ allocate ( wk2(im,jbeg:jend) )
+ call get_var3_r4( ncid, 'PS', 1,im, jbeg,jend, 1,1, wk2 )
+
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ psc(i,j) = s2c(i,j,1)*wk2(i1,j1 ) + s2c(i,j,2)*wk2(i2,j1 ) + &
+ s2c(i,j,3)*wk2(i2,j1+1) + s2c(i,j,4)*wk2(i1,j1+1)
+ enddo
+ enddo
+
+ call get_var3_r4( ncid, 'PHIS', 1,im, jbeg,jend, 1,1, wk2 )
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ gzc(i,j) = s2c(i,j,1)*wk2(i1,j1 ) + s2c(i,j,2)*wk2(i2,j1 ) + &
+ s2c(i,j,3)*wk2(i2,j1+1) + s2c(i,j,4)*wk2(i1,j1+1)
+ enddo
+ enddo
+
+ deallocate ( wk2 )
+ allocate ( wk2(im,jm) )
+
+ if ( read_ts ) then ! read skin temperature; could be used for SST
+
+ call get_var2_real( ncid, 'TS', im, jm, wk2 )
+
+ if ( .not. land_ts ) then
+ allocate ( wk1(im) )
+
+ do j=1,jm
+! Read NCEP ORO (1; land; 0: ocean; 2: sea_ice)
+ call get_var3_r4( ncid, 'ORO', 1,im, j,j, 1,1, wk1 )
+ tmean = 0.
+ npt = 0
+ do i=1,im
+ if( abs(wk1(i)-1.) > 0.99 ) then ! ocean or sea ice
+ tmean = tmean + wk2(i,j)
+ npt = npt + 1
+ endif
+ enddo
+!------------------------------------------------------
+! Replace TS over interior land with zonal mean SST/Ice
+!------------------------------------------------------
+ if ( npt /= 0 ) then
+ tmean= tmean / real(npt)
+ do i=1,im
+ if( abs(wk1(i)-1.) <= 0.99 ) then ! Land points
+ if ( i==1 ) then
+ i1 = im; i2 = 2
+ elseif ( i==im ) then
+ i1 = im-1; i2 = 1
+ else
+ i1 = i-1; i2 = i+1
+ endif
+ if ( abs(wk1(i2)-1.)>0.99 ) then ! east side has priority
+ wk2(i,j) = wk2(i2,j)
+ elseif ( abs(wk1(i1)-1.)>0.99 ) then ! west side
+ wk2(i,j) = wk2(i1,j)
+ else
+ wk2(i,j) = tmean
+ endif
+ endif
+ enddo
+ endif
+ enddo ! j-loop
+ deallocate ( wk1 )
+ endif !(.not.land_ts)
+
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ Atm(1)%ts(i,j) = s2c(i,j,1)*wk2(i1,j1 ) + s2c(i,j,2)*wk2(i2,j1 ) + &
+ s2c(i,j,3)*wk2(i2,j1+1) + s2c(i,j,4)*wk2(i1,j1+1)
+ enddo
+ enddo
+ call prt_maxmin('SST_model', Atm(1)%ts, is, ie, js, je, 0, 1, 1.)
+
+! Perform interp to FMS SST format/grid
+#ifndef DYCORE_SOLO
+ call ncep2fms(im, jm, lon, lat, wk2)
+ if( is_master() ) then
+ write(*,*) 'External_ic_mod: i_sst=', i_sst, ' j_sst=', j_sst
+ call pmaxmin( 'SST_ncep_fms', sst_ncep, i_sst, j_sst, 1.)
+ endif
+#endif
+ endif !(read_ts)
+
+ deallocate ( wk2 )
+
+! Read in temperature:
+ allocate ( wk3(1:im,jbeg:jend, 1:km) )
+ call get_var3_r4( ncid, 'T', 1,im, jbeg,jend, 1,km, wk3 )
+
+ allocate ( tp(is:ie,js:je,km) )
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ tp(i,j,k) = s2c(i,j,1)*wk3(i1,j1 ,k) + s2c(i,j,2)*wk3(i2,j1 ,k) + &
+ s2c(i,j,3)*wk3(i2,j1+1,k) + s2c(i,j,4)*wk3(i1,j1+1,k)
+ enddo
+ enddo
+ enddo
+
+! Read in tracers: only sphum at this point
+ call get_var3_r4( ncid, 'Q', 1,im, jbeg,jend, 1,km, wk3 )
+
+ allocate ( qp(is:ie,js:je,km) )
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ qp(i,j,k) = s2c(i,j,1)*wk3(i1,j1 ,k) + s2c(i,j,2)*wk3(i2,j1 ,k) + &
+ s2c(i,j,3)*wk3(i2,j1+1,k) + s2c(i,j,4)*wk3(i1,j1+1,k)
+ enddo
+ enddo
+ enddo
+
+ call remap_scalar(im, jm, km, npz, nq, nq, ak0, bk0, psc, gzc, tp, qp, Atm(1))
+ deallocate ( tp )
+ deallocate ( qp )
+
+! Winds:
+ call get_var3_r4( ncid, 'U', 1,im, jbeg,jend, 1,km, wk3 )
+
+ allocate ( ua(is:ie,js:je,km) )
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ ua(i,j,k) = s2c(i,j,1)*wk3(i1,j1 ,k) + s2c(i,j,2)*wk3(i2,j1 ,k) + &
+ s2c(i,j,3)*wk3(i2,j1+1,k) + s2c(i,j,4)*wk3(i1,j1+1,k)
+ enddo
+ enddo
+ enddo
+
+ call get_var3_r4( ncid, 'V', 1,im, jbeg,jend, 1,km, wk3 )
+ call close_ncfile ( ncid )
+
+ allocate ( va(is:ie,js:je,km) )
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ va(i,j,k) = s2c(i,j,1)*wk3(i1,j1 ,k) + s2c(i,j,2)*wk3(i2,j1 ,k) + &
+ s2c(i,j,3)*wk3(i2,j1+1,k) + s2c(i,j,4)*wk3(i1,j1+1,k)
+ enddo
+ enddo
+ enddo
+ deallocate ( wk3 )
+ call remap_winds(im, jm, km, npz, ak0, bk0, psc, ua, va, Atm(1))
+
+ deallocate ( ua )
+ deallocate ( va )
+
+ deallocate ( ak0 )
+ deallocate ( bk0 )
+ deallocate ( lat )
+ deallocate ( lon )
+
+ end subroutine get_ncep_ic
+
+!>@brief The subroutine 'get_ecmwf_ic' reads in initial conditions from ECMWF analyses
+!! (EXPERIMENTAL: contact Jan-Huey Chen jan-huey.chen@noaa.gov for support)
+!>@authors Jan-Huey Chen, Xi Chen, Shian-Jiann Lin
+ subroutine get_ecmwf_ic( Atm, fv_domain )
+
+#ifdef __PGI
+ use GFS_restart, only : GFS_restart_type
+
+ implicit none
+#endif
+
+ type(fv_atmos_type), intent(inout) :: Atm(:)
+ type(domain2d), intent(inout) :: fv_domain
+! local:
+ real :: ak_ec(138), bk_ec(138)
+ data ak_ec/ 0.000000, 2.000365, 3.102241, 4.666084, 6.827977, 9.746966, &
+ 13.605424, 18.608931, 24.985718, 32.985710, 42.879242, 54.955463, &
+ 69.520576, 86.895882, 107.415741, 131.425507, 159.279404, 191.338562, &
+ 227.968948, 269.539581, 316.420746, 368.982361, 427.592499, 492.616028, &
+ 564.413452, 643.339905, 729.744141, 823.967834, 926.344910, 1037.201172, &
+ 1156.853638, 1285.610352, 1423.770142, 1571.622925, 1729.448975, 1897.519287, &
+ 2076.095947, 2265.431641, 2465.770508, 2677.348145, 2900.391357, 3135.119385, &
+ 3381.743652, 3640.468262, 3911.490479, 4194.930664, 4490.817383, 4799.149414, &
+ 5119.895020, 5452.990723, 5798.344727, 6156.074219, 6526.946777, 6911.870605, &
+ 7311.869141, 7727.412109, 8159.354004, 8608.525391, 9076.400391, 9562.682617, &
+ 10065.978516, 10584.631836, 11116.662109, 11660.067383, 12211.547852, 12766.873047, &
+ 13324.668945, 13881.331055, 14432.139648, 14975.615234, 15508.256836, 16026.115234, &
+ 16527.322266, 17008.789063, 17467.613281, 17901.621094, 18308.433594, 18685.718750, &
+ 19031.289063, 19343.511719, 19620.042969, 19859.390625, 20059.931641, 20219.664063, &
+ 20337.863281, 20412.308594, 20442.078125, 20425.718750, 20361.816406, 20249.511719, &
+ 20087.085938, 19874.025391, 19608.572266, 19290.226563, 18917.460938, 18489.707031, &
+ 18006.925781, 17471.839844, 16888.687500, 16262.046875, 15596.695313, 14898.453125, &
+ 14173.324219, 13427.769531, 12668.257813, 11901.339844, 11133.304688, 10370.175781, &
+ 9617.515625, 8880.453125, 8163.375000, 7470.343750, 6804.421875, 6168.531250, &
+ 5564.382813, 4993.796875, 4457.375000, 3955.960938, 3489.234375, 3057.265625, &
+ 2659.140625, 2294.242188, 1961.500000, 1659.476563, 1387.546875, 1143.250000, &
+ 926.507813, 734.992188, 568.062500, 424.414063, 302.476563, 202.484375, &
+ 122.101563, 62.781250, 22.835938, 3.757813, 0.000000, 0.000000 /
+
+ data bk_ec/ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000007, 0.000024, 0.000059, 0.000112, 0.000199, &
+ 0.000340, 0.000562, 0.000890, 0.001353, 0.001992, 0.002857, &
+ 0.003971, 0.005378, 0.007133, 0.009261, 0.011806, 0.014816, &
+ 0.018318, 0.022355, 0.026964, 0.032176, 0.038026, 0.044548, &
+ 0.051773, 0.059728, 0.068448, 0.077958, 0.088286, 0.099462, &
+ 0.111505, 0.124448, 0.138313, 0.153125, 0.168910, 0.185689, &
+ 0.203491, 0.222333, 0.242244, 0.263242, 0.285354, 0.308598, &
+ 0.332939, 0.358254, 0.384363, 0.411125, 0.438391, 0.466003, &
+ 0.493800, 0.521619, 0.549301, 0.576692, 0.603648, 0.630036, &
+ 0.655736, 0.680643, 0.704669, 0.727739, 0.749797, 0.770798, &
+ 0.790717, 0.809536, 0.827256, 0.843881, 0.859432, 0.873929, &
+ 0.887408, 0.899900, 0.911448, 0.922096, 0.931881, 0.940860, &
+ 0.949064, 0.956550, 0.963352, 0.969513, 0.975078, 0.980072, &
+ 0.984542, 0.988500, 0.991984, 0.995003, 0.997630, 1.000000 /
+
+! The following L63 will be used in the model
+! The setting is the same as NCEP GFS's L64 except the top layer
+ real, dimension(64):: ak_sj, bk_sj
+ data ak_sj/64.247, 137.790, 221.958, &
+ 318.266, 428.434, 554.424, &
+ 698.457, 863.05803, 1051.07995, &
+ 1265.75194, 1510.71101, 1790.05098, &
+ 2108.36604, 2470.78817, 2883.03811, &
+ 3351.46002, 3883.05187, 4485.49315, &
+ 5167.14603, 5937.04991, 6804.87379, &
+ 7780.84698, 8875.64338, 10100.20534, &
+ 11264.35673, 12190.64366, 12905.42546, &
+ 13430.87867, 13785.88765, 13986.77987, &
+ 14047.96335, 13982.46770, 13802.40331, &
+ 13519.33841, 13144.59486, 12689.45608, &
+ 12165.28766, 11583.57006, 10955.84778, &
+ 10293.60402, 9608.08306, 8910.07678, &
+ 8209.70131, 7516.18560, 6837.69250, &
+ 6181.19473, 5552.39653, 4955.72632, &
+ 4394.37629, 3870.38682, 3384.76586, &
+ 2937.63489, 2528.37666, 2155.78385, &
+ 1818.20722, 1513.68173, 1240.03585, &
+ 994.99144, 776.23591, 581.48797, &
+ 408.53400, 255.26520, 119.70243, 0. /
+
+ data bk_sj/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00201, 0.00792, 0.01755, &
+ 0.03079, 0.04751, 0.06761, &
+ 0.09097, 0.11746, 0.14690, &
+ 0.17911, 0.21382, 0.25076, &
+ 0.28960, 0.32994, 0.37140, &
+ 0.41353, 0.45589, 0.49806, &
+ 0.53961, 0.58015, 0.61935, &
+ 0.65692, 0.69261, 0.72625, &
+ 0.75773, 0.78698, 0.81398, &
+ 0.83876, 0.86138, 0.88192, &
+ 0.90050, 0.91722, 0.93223, &
+ 0.94565, 0.95762, 0.96827, &
+ 0.97771, 0.98608, 0.99347, 1./
+
+ character(len=128) :: fname
+ real, allocatable:: wk2(:,:)
+ real(kind=4), allocatable:: wk2_r4(:,:)
+ real, dimension(:,:,:), allocatable:: ud, vd
+ real, allocatable:: wc(:,:,:)
+ real(kind=4), allocatable:: uec(:,:,:), vec(:,:,:), tec(:,:,:), wec(:,:,:)
+ real(kind=4), allocatable:: psec(:,:), zsec(:,:), zhec(:,:,:), qec(:,:,:,:)
+ real(kind=4), allocatable:: psc(:,:)
+ real(kind=4), allocatable:: sphumec(:,:,:)
+ real, allocatable:: psc_r8(:,:), zhc(:,:,:), qc(:,:,:,:)
+ real, allocatable:: lat(:), lon(:), ak0(:), bk0(:)
+ real, allocatable:: pt_c(:,:,:), pt_d(:,:,:)
+ real:: s2c(Atm(1)%bd%is:Atm(1)%bd%ie,Atm(1)%bd%js:Atm(1)%bd%je,4)
+ real:: s2c_c(Atm(1)%bd%is:Atm(1)%bd%ie+1,Atm(1)%bd%js:Atm(1)%bd%je,4)
+ real:: s2c_d(Atm(1)%bd%is:Atm(1)%bd%ie,Atm(1)%bd%js:Atm(1)%bd%je+1,4)
+ integer, dimension(Atm(1)%bd%is:Atm(1)%bd%ie,Atm(1)%bd%js:Atm(1)%bd%je):: &
+ id1, id2, jdc
+ integer, dimension(Atm(1)%bd%is:Atm(1)%bd%ie+1,Atm(1)%bd%js:Atm(1)%bd%je):: &
+ id1_c, id2_c, jdc_c
+ integer, dimension(Atm(1)%bd%is:Atm(1)%bd%ie,Atm(1)%bd%js:Atm(1)%bd%je+1):: &
+ id1_d, id2_d, jdc_d
+ real:: utmp, vtmp
+ integer:: i, j, k, n, im, jm, km, npz, npt
+ integer:: i1, i2, j1, ncid
+ integer:: jbeg, jend, jn
+ integer tsize(3)
+ logical:: read_ts = .true.
+ logical:: land_ts = .false.
+ logical:: found
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+ integer :: sphum, liq_wat, ice_wat, rainwat, snowwat, graupel
+#ifdef MULTI_GASES
+ integer :: spfo, spfo2, spfo3
+#else
+ integer :: o3mr
+#endif
+ real:: wt, qt, m_fac
+ real(kind=8) :: scale_value, offset, ptmp
+ real(kind=R_GRID), dimension(2):: p1, p2, p3
+ real(kind=R_GRID), dimension(3):: e1, e2, ex, ey
+ real, allocatable:: ps_gfs(:,:), zh_gfs(:,:,:)
+#ifdef MULTI_GASES
+ real, allocatable:: spfo_gfs(:,:,:), spfo2_gfs(:,:,:), spfo3_gfs(:,:,:)
+#else
+ real, allocatable:: o3mr_gfs(:,:,:)
+#endif
+ real, allocatable:: ak_gfs(:), bk_gfs(:)
+ integer :: id_res, ntprog, ntracers, ks, iq, nt
+ character(len=64) :: tracer_name
+ integer :: levp_gfs = 64
+ type (restart_file_type) :: ORO_restart, GFS_restart
+ character(len=64) :: fn_oro_ics = 'oro_data.nc'
+ character(len=64) :: fn_gfs_ics = 'gfs_data.nc'
+ character(len=64) :: fn_gfs_ctl = 'gfs_ctrl.nc'
+ logical :: filtered_terrain = .true.
+ namelist /external_ic_nml/ filtered_terrain
+
+ is = Atm(1)%bd%is
+ ie = Atm(1)%bd%ie
+ js = Atm(1)%bd%js
+ je = Atm(1)%bd%je
+ isd = Atm(1)%bd%isd
+ ied = Atm(1)%bd%ied
+ jsd = Atm(1)%bd%jsd
+ jed = Atm(1)%bd%jed
+
+ deg2rad = pi/180.
+
+ npz = Atm(1)%npz
+ call get_number_tracers(MODEL_ATMOS, num_tracers=ntracers, num_prog=ntprog)
+ if(is_master()) write(*,*) 'ntracers = ', ntracers, 'ntprog = ',ntprog
+
+ sphum = get_tracer_index(MODEL_ATMOS, 'sphum')
+ liq_wat = get_tracer_index(MODEL_ATMOS, 'liq_wat')
+ ice_wat = get_tracer_index(MODEL_ATMOS, 'ice_wat')
+ rainwat = get_tracer_index(MODEL_ATMOS, 'rainwat')
+ snowwat = get_tracer_index(MODEL_ATMOS, 'snowwat')
+ graupel = get_tracer_index(MODEL_ATMOS, 'graupel')
+#ifdef MULTI_GASES
+ spfo = get_tracer_index(MODEL_ATMOS, 'spfo')
+ spfo2 = get_tracer_index(MODEL_ATMOS, 'spfo2')
+ spfo3 = get_tracer_index(MODEL_ATMOS, 'spfo3')
+#else
+ o3mr = get_tracer_index(MODEL_ATMOS, 'o3mr')
+#endif
+
+ if (is_master()) then
+ print *, 'sphum = ', sphum
+ print *, 'liq_wat = ', liq_wat
+ if ( Atm(1)%flagstruct%nwat .eq. 6 ) then
+ print *, 'rainwat = ', rainwat
+ print *, 'iec_wat = ', ice_wat
+ print *, 'snowwat = ', snowwat
+ print *, 'graupel = ', graupel
+ endif
+#ifdef MULTI_GASES
+ print *, ' spfo3 = ', spfo3
+ print *, ' spfo = ', spfo
+ print *, ' spfo2 = ', spfo2
+#else
+ print *, ' o3mr = ', o3mr
+#endif
+ endif
+
+
+! Set up model's ak and bk
+ if ( npz <= 64 ) then
+ Atm(1)%ak(:) = ak_sj(:)
+ Atm(1)%bk(:) = bk_sj(:)
+ Atm(1)%ptop = Atm(1)%ak(1)
+ else
+ call set_eta(npz, ks, Atm(1)%ptop, Atm(1)%ak, Atm(1)%bk)
+ endif
+
+!! Read in model terrain from oro_data.tile?.nc
+ if (filtered_terrain) then
+ id_res = register_restart_field (ORO_restart, fn_oro_ics, 'orog_filt', Atm(1)%phis, domain=Atm(1)%domain)
+ elseif (.not. filtered_terrain) then
+ id_res = register_restart_field (ORO_restart, fn_oro_ics, 'orog_raw', Atm(1)%phis, domain=Atm(1)%domain)
+ endif
+ call restore_state (ORO_restart)
+ call free_restart_type(ORO_restart)
+ Atm(1)%phis = Atm(1)%phis*grav
+ if(is_master()) write(*,*) 'done reading model terrain from oro_data.nc'
+ call mpp_update_domains( Atm(1)%phis, Atm(1)%domain )
+
+!! Read in o3mr, ps and zh from GFS_data.tile?.nc
+#ifdef MULTI_GASES
+ allocate (spfo3_gfs(is:ie,js:je,levp_gfs))
+ allocate ( spfo_gfs(is:ie,js:je,levp_gfs))
+ allocate (spfo2_gfs(is:ie,js:je,levp_gfs))
+#else
+ allocate (o3mr_gfs(is:ie,js:je,levp_gfs))
+#endif
+ allocate (ps_gfs(is:ie,js:je))
+ allocate (zh_gfs(is:ie,js:je,levp_gfs+1))
+
+#ifdef MULTI_GASES
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'spfo3', spfo3_gfs, &
+ mandatory=.false.,domain=Atm(1)%domain)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'spfo', spfo_gfs, &
+ mandatory=.false.,domain=Atm(1)%domain)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'spfo2', spfo2_gfs, &
+ mandatory=.false.,domain=Atm(1)%domain)
+#else
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'o3mr', o3mr_gfs, &
+ mandatory=.false.,domain=Atm(1)%domain)
+#endif
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'ps', ps_gfs, domain=Atm(1)%domain)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'ZH', zh_gfs, domain=Atm(1)%domain)
+ call restore_state (GFS_restart)
+ call free_restart_type(GFS_restart)
+
+
+ ! Get GFS ak, bk for o3mr vertical interpolation
+ allocate (wk2(levp_gfs+1,2))
+ allocate (ak_gfs(levp_gfs+1))
+ allocate (bk_gfs(levp_gfs+1))
+ call read_data('INPUT/'//trim(fn_gfs_ctl),'vcoord',wk2, no_domain=.TRUE.)
+ ak_gfs(1:levp_gfs+1) = wk2(1:levp_gfs+1,1)
+ bk_gfs(1:levp_gfs+1) = wk2(1:levp_gfs+1,2)
+ deallocate (wk2)
+
+ if ( bk_gfs(1) < 1.E-9 ) ak_gfs(1) = max(1.e-9, ak_gfs(1))
+
+#ifdef MULTI_GASES
+ iq = spfo3
+ if(is_master()) write(*,*) 'Reading spfo3 from GFS_data.nc:'
+ if(is_master()) write(*,*) 'spfo3 =', iq
+ call remap_scalar_single(Atm(1), levp_gfs, npz, ak_gfs, bk_gfs, ps_gfs, spfo3_gfs, zh_gfs, iq)
+ iq = spfo
+ if(is_master()) write(*,*) 'Reading spfo from GFS_data.nc:'
+ if(is_master()) write(*,*) 'spfo =', iq
+ call remap_scalar_single(Atm(1), levp_gfs, npz, ak_gfs, bk_gfs, ps_gfs, spfo_gfs, zh_gfs, iq)
+ iq = spfo2
+ if(is_master()) write(*,*) 'Reading spfo2 from GFS_data.nc:'
+ if(is_master()) write(*,*) 'spfo2 =', iq
+ call remap_scalar_single(Atm(1), levp_gfs, npz, ak_gfs, bk_gfs, ps_gfs, spfo2_gfs, zh_gfs, iq)
+#else
+ iq = o3mr
+ if(is_master()) write(*,*) 'Reading o3mr from GFS_data.nc:'
+ if(is_master()) write(*,*) 'o3mr =', iq
+ call remap_scalar_single(Atm(1), levp_gfs, npz, ak_gfs, bk_gfs, ps_gfs, o3mr_gfs, zh_gfs, iq)
+#endif
+
+ deallocate (ak_gfs, bk_gfs)
+ deallocate (ps_gfs, zh_gfs)
+#ifdef MULTI_GASES
+ deallocate (spfo3_gfs)
+ deallocate ( spfo_gfs)
+ deallocate (spfo2_gfs)
+#else
+ deallocate (o3mr_gfs)
+#endif
+
+!! Start to read EC data
+ fname = Atm(1)%flagstruct%res_latlon_dynamics
+
+ if( file_exist(fname) ) then
+ call open_ncfile( fname, ncid ) ! open the file
+
+ call get_ncdim1( ncid, 'longitude', tsize(1) )
+ call get_ncdim1( ncid, 'latitude', tsize(2) )
+ call get_ncdim1( ncid, 'level', tsize(3) )
+
+ im = tsize(1); jm = tsize(2); km = tsize(3)
+
+ if(is_master()) write(*,*) fname
+ if(is_master()) write(*,*) ' ECMWF IC dimensions:', tsize
+
+ allocate ( lon(im) )
+ allocate ( lat(jm) )
+
+ call _GET_VAR1(ncid, 'longitude', im, lon )
+ call _GET_VAR1(ncid, 'latitude', jm, lat )
+
+!! Convert to radian
+ do i = 1, im
+ lon(i) = lon(i) * deg2rad ! lon(1) = 0.
+ enddo
+ do j = 1, jm
+ lat(j) = lat(j) * deg2rad
+ enddo
+
+ allocate ( ak0(km+1) )
+ allocate ( bk0(km+1) )
+
+! The ECMWF data from does not contain (ak,bk)
+ do k=1, km+1
+ ak0(k) = ak_ec(k)
+ bk0(k) = bk_ec(k)
+ enddo
+
+ if( is_master() ) then
+ do k=1,km+1
+ write(*,*) k, ak0(k), bk0(k)
+ enddo
+ endif
+
+! Limiter to prevent NAN at top during remapping
+ if ( bk0(1) < 1.E-9 ) ak0(1) = max(1.e-9, ak0(1))
+
+ else
+ call mpp_error(FATAL,'==> Error in get_external_ic: Expected file '//trim(fname)//' for NCEP IC does not exist')
+ endif
+
+! Initialize lat-lon to Cubed bi-linear interpolation coeff:
+ call remap_coef( is, ie, js, je, isd, ied, jsd, jed, &
+ im, jm, lon, lat, id1, id2, jdc, s2c , Atm(1)%gridstruct%agrid )
+
+! Find bounding latitudes:
+ jbeg = jm-1; jend = 2
+ do j=js,je
+ do i=is,ie
+ j1 = jdc(i,j)
+ jbeg = min(jbeg, j1)
+ jend = max(jend, j1+1)
+ enddo
+ enddo
+
+ if(is_master()) write(*,*) 'jbeg, jend = ', jbeg, jend
+! read in surface pressure and height:
+ allocate ( psec(im,jbeg:jend) )
+ allocate ( zsec(im,jbeg:jend) )
+ allocate ( wk2_r4(im,jbeg:jend) )
+
+ call get_var2_r4( ncid, 'lnsp', 1,im, jbeg,jend, wk2_r4 )
+ call get_var_att_double ( ncid, 'lnsp', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'lnsp', 'add_offset', offset )
+ psec(:,:) = exp(wk2_r4(:,:)*scale_value + offset)
+ if(is_master()) write(*,*) 'done reading psec'
+
+ call get_var2_r4( ncid, 'z', 1,im, jbeg,jend, wk2_r4 )
+ call get_var_att_double ( ncid, 'z', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'z', 'add_offset', offset )
+ zsec(:,:) = (wk2_r4(:,:)*scale_value + offset)/grav
+ if(is_master()) write(*,*) 'done reading zsec'
+
+ deallocate ( wk2_r4 )
+
+! Read in temperature:
+ allocate ( tec(1:im,jbeg:jend, 1:km) )
+
+ call get_var3_r4( ncid, 't', 1,im, jbeg,jend, 1,km, tec )
+ call get_var_att_double ( ncid, 't', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 't', 'add_offset', offset )
+ tec(:,:,:) = tec(:,:,:)*scale_value + offset
+ if(is_master()) write(*,*) 'done reading tec'
+
+! read in specific humidity:
+ allocate ( sphumec(1:im,jbeg:jend, 1:km) )
+
+ call get_var3_r4( ncid, 'q', 1,im, jbeg,jend, 1,km, sphumec(:,:,:) )
+ call get_var_att_double ( ncid, 'q', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'q', 'add_offset', offset )
+ sphumec(:,:,:) = sphumec(:,:,:)*scale_value + offset
+ if(is_master()) write(*,*) 'done reading sphum ec'
+
+! Read in other tracers from EC data and remap them into cubic sphere grid:
+ allocate ( qec(1:im,jbeg:jend,1:km,5) )
+
+ do n = 1, 5
+ if (n == sphum) then
+ qec(:,:,:,sphum) = sphumec(:,:,:)
+ deallocate ( sphumec )
+ else if (n == liq_wat) then
+ call get_var3_r4( ncid, 'clwc', 1,im, jbeg,jend, 1,km, qec(:,:,:,liq_wat) )
+ call get_var_att_double ( ncid, 'clwc', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'clwc', 'add_offset', offset )
+ qec(:,:,:,liq_wat) = qec(:,:,:,liq_wat)*scale_value + offset
+ if(is_master()) write(*,*) 'done reading clwc ec'
+ else if (n == rainwat) then
+ call get_var3_r4( ncid, 'crwc', 1,im, jbeg,jend, 1,km, qec(:,:,:,rainwat) )
+ call get_var_att_double ( ncid, 'crwc', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'crwc', 'add_offset', offset )
+ qec(:,:,:,rainwat) = qec(:,:,:,rainwat)*scale_value + offset
+ if(is_master()) write(*,*) 'done reading crwc ec'
+ else if (n == ice_wat) then
+ call get_var3_r4( ncid, 'ciwc', 1,im, jbeg,jend, 1,km, qec(:,:,:,ice_wat) )
+ call get_var_att_double ( ncid, 'ciwc', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'ciwc', 'add_offset', offset )
+ qec(:,:,:,ice_wat) = qec(:,:,:,ice_wat)*scale_value + offset
+ if(is_master()) write(*,*) 'done reading ciwc ec'
+ else if (n == snowwat) then
+ call get_var3_r4( ncid, 'cswc', 1,im, jbeg,jend, 1,km, qec(:,:,:,snowwat) )
+ call get_var_att_double ( ncid, 'cswc', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'cswc', 'add_offset', offset )
+ qec(:,:,:,snowwat) = qec(:,:,:,snowwat)*scale_value + offset
+ if(is_master()) write(*,*) 'done reading cswc ec'
+ else
+ if(is_master()) write(*,*) 'nq is more then 5!'
+ endif
+
+ enddo
+
+
+!!!! Compute height on edges, zhec [ use psec, zsec, tec, sphum]
+ allocate ( zhec(1:im,jbeg:jend, km+1) )
+ jn = jend - jbeg + 1
+
+ call compute_zh(im, jn, km, ak0, bk0, psec, zsec, tec, qec, 5, zhec )
+ if(is_master()) write(*,*) 'done compute zhec'
+
+! convert zhec, psec, zsec from EC grid to cubic grid
+ allocate (psc(is:ie,js:je))
+ allocate (psc_r8(is:ie,js:je))
+
+#ifdef LOGP_INTP
+ do j=jbeg,jend
+ do i=1,im
+ psec(i,j) = log(psec(i,j))
+ enddo
+ enddo
+#endif
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+#ifdef LOGP_INTP
+ ptmp = s2c(i,j,1)*psec(i1,j1 ) + s2c(i,j,2)*psec(i2,j1 ) + &
+ s2c(i,j,3)*psec(i2,j1+1) + s2c(i,j,4)*psec(i1,j1+1)
+ psc(i,j) = exp(ptmp)
+#else
+ psc(i,j) = s2c(i,j,1)*psec(i1,j1 ) + s2c(i,j,2)*psec(i2,j1 ) + &
+ s2c(i,j,3)*psec(i2,j1+1) + s2c(i,j,4)*psec(i1,j1+1)
+#endif
+ enddo
+ enddo
+ deallocate ( psec )
+ deallocate ( zsec )
+
+ allocate (zhc(is:ie,js:je,km+1))
+!$OMP parallel do default(none) shared(is,ie,js,je,km,s2c,id1,id2,jdc,zhc,zhec) &
+!$OMP private(i1,i2,j1)
+ do k=1,km+1
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ zhc(i,j,k) = s2c(i,j,1)*zhec(i1,j1 ,k) + s2c(i,j,2)*zhec(i2,j1 ,k) + &
+ s2c(i,j,3)*zhec(i2,j1+1,k) + s2c(i,j,4)*zhec(i1,j1+1,k)
+ enddo
+ enddo
+ enddo
+ deallocate ( zhec )
+
+ if(is_master()) write(*,*) 'done interpolate psec/zsec/zhec into cubic grid psc/zhc!'
+
+! Read in other tracers from EC data and remap them into cubic sphere grid:
+ allocate ( qc(is:ie,js:je,km,6) )
+
+ do n = 1, 5
+!$OMP parallel do default(none) shared(n,is,ie,js,je,km,s2c,id1,id2,jdc,qc,qec) &
+!$OMP private(i1,i2,j1)
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ qc(i,j,k,n) = s2c(i,j,1)*qec(i1,j1 ,k,n) + s2c(i,j,2)*qec(i2,j1 ,k,n) + &
+ s2c(i,j,3)*qec(i2,j1+1,k,n) + s2c(i,j,4)*qec(i1,j1+1,k,n)
+ enddo
+ enddo
+ enddo
+ enddo
+
+ qc(:,:,:,graupel) = 0. ! note Graupel must be tracer #6
+
+ deallocate ( qec )
+ if(is_master()) write(*,*) 'done interpolate tracers (qec) into cubic (qc)'
+
+! Read in vertical wind from EC data and remap them into cubic sphere grid:
+ allocate ( wec(1:im,jbeg:jend, 1:km) )
+ allocate ( wc(is:ie,js:je,km))
+
+ call get_var3_r4( ncid, 'w', 1,im, jbeg,jend, 1,km, wec )
+ call get_var_att_double ( ncid, 'w', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'w', 'add_offset', offset )
+ wec(:,:,:) = wec(:,:,:)*scale_value + offset
+ !call p_maxmin('wec', wec, 1, im, jbeg, jend, km, 1.)
+
+!$OMP parallel do default(none) shared(is,ie,js,je,km,id1,id2,jdc,s2c,wc,wec) &
+!$OMP private(i1,i2,j1)
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ wc(i,j,k) = s2c(i,j,1)*wec(i1,j1 ,k) + s2c(i,j,2)*wec(i2,j1 ,k) + &
+ s2c(i,j,3)*wec(i2,j1+1,k) + s2c(i,j,4)*wec(i1,j1+1,k)
+ enddo
+ enddo
+ enddo
+ !call p_maxmin('wc', wc, is, ie, js, je, km, 1.)
+
+ deallocate ( wec )
+ if(is_master()) write(*,*) 'done reading and interpolate vertical wind (w) into cubic'
+
+! remap tracers
+ psc_r8(:,:) = psc(:,:)
+ deallocate ( psc )
+
+ call remap_scalar_ec(Atm(1), km, npz, 6, ak0, bk0, psc_r8, qc, wc, zhc )
+ call mpp_update_domains(Atm(1)%phis, Atm(1)%domain)
+ if(is_master()) write(*,*) 'done remap_scalar_ec'
+
+ deallocate ( zhc )
+ deallocate ( wc )
+ deallocate ( qc )
+
+!! Winds:
+ ! get lat/lon values of pt_c and pt_d from grid data (pt_b)
+ allocate (pt_c(isd:ied+1,jsd:jed ,2))
+ allocate (pt_d(isd:ied ,jsd:jed+1,2))
+ allocate (ud(is:ie , js:je+1, km))
+ allocate (vd(is:ie+1, js:je , km))
+
+ call get_staggered_grid( is, ie, js, je, &
+ isd, ied, jsd, jed, &
+ Atm(1)%gridstruct%grid, pt_c, pt_d)
+
+ !------ pt_c part ------
+ ! Initialize lat-lon to Cubed bi-linear interpolation coeff:
+ call remap_coef( is, ie+1, js, je, isd, ied+1, jsd, jed, &
+ im, jm, lon, lat, id1_c, id2_c, jdc_c, s2c_c, pt_c)
+
+ ! Find bounding latitudes:
+ jbeg = jm-1; jend = 2
+ do j=js,je
+ do i=is,ie+1
+ j1 = jdc_c(i,j)
+ jbeg = min(jbeg, j1)
+ jend = max(jend, j1+1)
+ enddo
+ enddo
+
+ ! read in EC wind data
+ allocate ( uec(1:im,jbeg:jend, 1:km) )
+ allocate ( vec(1:im,jbeg:jend, 1:km) )
+
+ call get_var3_r4( ncid, 'u', 1,im, jbeg,jend, 1,km, uec )
+ call get_var_att_double ( ncid, 'u', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'u', 'add_offset', offset )
+ do k=1,km
+ do j=jbeg, jend
+ do i=1,im
+ uec(i,j,k) = uec(i,j,k)*scale_value + offset
+ enddo
+ enddo
+ enddo
+ if(is_master()) write(*,*) 'first time done reading uec'
+
+ call get_var3_r4( ncid, 'v', 1,im, jbeg,jend, 1,km, vec )
+ call get_var_att_double ( ncid, 'v', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'v', 'add_offset', offset )
+ do k=1,km
+ do j=jbeg, jend
+ do i=1,im
+ vec(i,j,k) = vec(i,j,k)*scale_value + offset
+ enddo
+ enddo
+ enddo
+
+ if(is_master()) write(*,*) 'first time done reading vec'
+
+!$OMP parallel do default(none) shared(is,ie,js,je,km,s2c_c,id1_c,id2_c,jdc_c,uec,vec,Atm,vd) &
+!$OMP private(i1,i2,j1,p1,p2,p3,e2,ex,ey,utmp,vtmp)
+ do k=1,km
+ do j=js,je
+ do i=is,ie+1
+ i1 = id1_c(i,j)
+ i2 = id2_c(i,j)
+ j1 = jdc_c(i,j)
+ p1(:) = Atm(1)%gridstruct%grid(i,j ,1:2)
+ p2(:) = Atm(1)%gridstruct%grid(i,j+1,1:2)
+ call mid_pt_sphere(p1, p2, p3)
+ call get_unit_vect2(p1, p2, e2)
+ call get_latlon_vector(p3, ex, ey)
+ utmp = s2c_c(i,j,1)*uec(i1,j1 ,k) + &
+ s2c_c(i,j,2)*uec(i2,j1 ,k) + &
+ s2c_c(i,j,3)*uec(i2,j1+1,k) + &
+ s2c_c(i,j,4)*uec(i1,j1+1,k)
+ vtmp = s2c_c(i,j,1)*vec(i1,j1 ,k) + &
+ s2c_c(i,j,2)*vec(i2,j1 ,k) + &
+ s2c_c(i,j,3)*vec(i2,j1+1,k) + &
+ s2c_c(i,j,4)*vec(i1,j1+1,k)
+ vd(i,j,k) = utmp*inner_prod(e2,ex) + vtmp*inner_prod(e2,ey)
+ enddo
+ enddo
+ enddo
+
+ deallocate ( uec, vec )
+
+ !------ pt_d part ------
+ ! Initialize lat-lon to Cubed bi-linear interpolation coeff:
+ call remap_coef( is, ie, js, je+1, isd, ied, jsd, jed+1, &
+ im, jm, lon, lat, id1_d, id2_d, jdc_d, s2c_d, pt_d)
+ deallocate ( pt_c, pt_d )
+
+ ! Find bounding latitudes:
+ jbeg = jm-1; jend = 2
+ do j=js,je+1
+ do i=is,ie
+ j1 = jdc_d(i,j)
+ jbeg = min(jbeg, j1)
+ jend = max(jend, j1+1)
+ enddo
+ enddo
+
+ ! read in EC wind data
+ allocate ( uec(1:im,jbeg:jend, 1:km) )
+ allocate ( vec(1:im,jbeg:jend, 1:km) )
+
+ call get_var3_r4( ncid, 'u', 1,im, jbeg,jend, 1,km, uec )
+ call get_var_att_double ( ncid, 'u', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'u', 'add_offset', offset )
+ uec(:,:,:) = uec(:,:,:)*scale_value + offset
+ if(is_master()) write(*,*) 'second time done reading uec'
+
+ call get_var3_r4( ncid, 'v', 1,im, jbeg,jend, 1,km, vec )
+ call get_var_att_double ( ncid, 'v', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'v', 'add_offset', offset )
+ vec(:,:,:) = vec(:,:,:)*scale_value + offset
+ if(is_master()) write(*,*) 'second time done reading vec'
+
+!$OMP parallel do default(none) shared(is,ie,js,je,km,id1_d,id2_d,jdc_d,s2c_d,uec,vec,Atm,ud) &
+!$OMP private(i1,i2,j1,p1,p2,p3,e1,ex,ey,utmp,vtmp)
+ do k=1,km
+ do j=js,je+1
+ do i=is,ie
+ i1 = id1_d(i,j)
+ i2 = id2_d(i,j)
+ j1 = jdc_d(i,j)
+ p1(:) = Atm(1)%gridstruct%grid(i, j,1:2)
+ p2(:) = Atm(1)%gridstruct%grid(i+1,j,1:2)
+ call mid_pt_sphere(p1, p2, p3)
+ call get_unit_vect2(p1, p2, e1)
+ call get_latlon_vector(p3, ex, ey)
+ utmp = s2c_d(i,j,1)*uec(i1,j1 ,k) + &
+ s2c_d(i,j,2)*uec(i2,j1 ,k) + &
+ s2c_d(i,j,3)*uec(i2,j1+1,k) + &
+ s2c_d(i,j,4)*uec(i1,j1+1,k)
+ vtmp = s2c_d(i,j,1)*vec(i1,j1 ,k) + &
+ s2c_d(i,j,2)*vec(i2,j1 ,k) + &
+ s2c_d(i,j,3)*vec(i2,j1+1,k) + &
+ s2c_d(i,j,4)*vec(i1,j1+1,k)
+ ud(i,j,k) = utmp*inner_prod(e1,ex) + vtmp*inner_prod(e1,ey)
+ enddo
+ enddo
+ enddo
+ deallocate ( uec, vec )
+
+ call remap_dwinds(km, npz, ak0, bk0, psc_r8, ud, vd, Atm(1))
+ deallocate ( ud, vd )
+
+#ifndef COND_IFS_IC
+! Add cloud condensate from IFS to total MASS
+! Adjust the mixing ratios consistently...
+ do k=1,npz
+ do j=js,je
+ do i=is,ie
+ wt = Atm(1)%delp(i,j,k)
+ if ( Atm(1)%flagstruct%nwat .eq. 2 ) then
+ qt = wt*(1.+Atm(1)%q(i,j,k,liq_wat))
+ elseif ( Atm(1)%flagstruct%nwat .eq. 6 ) then
+ qt = wt*(1. + Atm(1)%q(i,j,k,liq_wat) + &
+ Atm(1)%q(i,j,k,ice_wat) + &
+ Atm(1)%q(i,j,k,rainwat) + &
+ Atm(1)%q(i,j,k,snowwat) + &
+ Atm(1)%q(i,j,k,graupel))
+ endif
+ m_fac = wt / qt
+ do iq=1,ntracers
+ Atm(1)%q(i,j,k,iq) = m_fac * Atm(1)%q(i,j,k,iq)
+ enddo
+ Atm(1)%delp(i,j,k) = qt
+ enddo
+ enddo
+ enddo
+#endif
+
+ deallocate ( ak0, bk0 )
+! deallocate ( psc )
+ deallocate ( psc_r8 )
+ deallocate ( lat, lon )
+
+ Atm(1)%flagstruct%make_nh = .false.
+
+ end subroutine get_ecmwf_ic
+!------------------------------------------------------------------
+!------------------------------------------------------------------
+ subroutine get_fv_ic( Atm, fv_domain, nq )
+ type(fv_atmos_type), intent(inout) :: Atm(:)
+ type(domain2d), intent(inout) :: fv_domain
+ integer, intent(in):: nq
+
+ character(len=128) :: fname, tracer_name
+ real, allocatable:: ps0(:,:), gz0(:,:), u0(:,:,:), v0(:,:,:), t0(:,:,:), dp0(:,:,:), q0(:,:,:,:)
+ real, allocatable:: ua(:,:,:), va(:,:,:)
+ real, allocatable:: lat(:), lon(:), ak0(:), bk0(:)
+ integer :: i, j, k, im, jm, km, npz, tr_ind
+ integer tsize(3)
+! integer sphum, liq_wat, ice_wat, cld_amt ! GFDL AM2 physics
+ logical found
+
+ npz = Atm(1)%npz
+
+! Zero out all initial tracer fields:
+ Atm(1)%q = 0.
+
+! Read in lat-lon FV core restart file
+ fname = Atm(1)%flagstruct%res_latlon_dynamics
+
+ if( file_exist(fname) ) then
+ call field_size(fname, 'T', tsize, field_found=found)
+ if(is_master()) write(*,*) 'Using lat-lon FV restart:', fname
+
+ if ( found ) then
+ im = tsize(1); jm = tsize(2); km = tsize(3)
+ if(is_master()) write(*,*) 'External IC dimensions:', tsize
+ else
+ call mpp_error(FATAL,'==> Error in get_external_ic: field not found')
+ endif
+
+! Define the lat-lon coordinate:
+ allocate ( lon(im) )
+ allocate ( lat(jm) )
+
+ do i=1,im
+ lon(i) = (0.5 + real(i-1)) * 2.*pi/real(im)
+ enddo
+
+ do j=1,jm
+ lat(j) = -0.5*pi + real(j-1)*pi/real(jm-1) ! SP to NP
+ enddo
+
+ allocate ( ak0(1:km+1) )
+ allocate ( bk0(1:km+1) )
+ allocate ( ps0(1:im,1:jm) )
+ allocate ( gz0(1:im,1:jm) )
+ allocate ( u0(1:im,1:jm,1:km) )
+ allocate ( v0(1:im,1:jm,1:km) )
+ allocate ( t0(1:im,1:jm,1:km) )
+ allocate ( dp0(1:im,1:jm,1:km) )
+
+ call read_data (fname, 'ak', ak0)
+ call read_data (fname, 'bk', bk0)
+ call read_data (fname, 'Surface_geopotential', gz0)
+ call read_data (fname, 'U', u0)
+ call read_data (fname, 'V', v0)
+ call read_data (fname, 'T', t0)
+ call read_data (fname, 'DELP', dp0)
+
+! Share the load
+ if(is_master()) call pmaxmin( 'ZS_data', gz0, im, jm, 1./grav)
+ if(mpp_pe()==1) call pmaxmin( 'U_data', u0, im*jm, km, 1.)
+ if(mpp_pe()==1) call pmaxmin( 'V_data', v0, im*jm, km, 1.)
+ if(mpp_pe()==2) call pmaxmin( 'T_data', t0, im*jm, km, 1.)
+ if(mpp_pe()==3) call pmaxmin( 'DEL-P', dp0, im*jm, km, 0.01)
+
+
+ else
+ call mpp_error(FATAL,'==> Error in get_external_ic: Expected file '//trim(fname)//' for dynamics does not exist')
+ endif
+
+! Read in tracers: only AM2 "physics tracers" at this point
+ fname = Atm(1)%flagstruct%res_latlon_tracers
+
+ if( file_exist(fname) ) then
+ if(is_master()) write(*,*) 'Using lat-lon tracer restart:', fname
+
+ allocate ( q0(im,jm,km,Atm(1)%ncnst) )
+ q0 = 0.
+
+ do tr_ind = 1, nq
+ call get_tracer_names(MODEL_ATMOS, tr_ind, tracer_name)
+ if (field_exist(fname,tracer_name)) then
+ call read_data(fname, tracer_name, q0(1:im,1:jm,1:km,tr_ind))
+ call mpp_error(NOTE,'==> Have read tracer '//trim(tracer_name)//' from '//trim(fname))
+ cycle
+ endif
+ enddo
+ else
+ call mpp_error(FATAL,'==> Error in get_external_ic: Expected file '//trim(fname)//' for tracers does not exist')
+ endif
+
+! D to A transform on lat-lon grid:
+ allocate ( ua(im,jm,km) )
+ allocate ( va(im,jm,km) )
+
+ call d2a3d(u0, v0, ua, va, im, jm, km, lon)
+
+ deallocate ( u0 )
+ deallocate ( v0 )
+
+ if(mpp_pe()==4) call pmaxmin( 'UA', ua, im*jm, km, 1.)
+ if(mpp_pe()==4) call pmaxmin( 'VA', va, im*jm, km, 1.)
+
+ do j=1,jm
+ do i=1,im
+ ps0(i,j) = ak0(1)
+ enddo
+ enddo
+
+ do k=1,km
+ do j=1,jm
+ do i=1,im
+ ps0(i,j) = ps0(i,j) + dp0(i,j,k)
+ enddo
+ enddo
+ enddo
+
+ if (is_master()) call pmaxmin( 'PS_data (mb)', ps0, im, jm, 0.01)
+
+! Horizontal interpolation to the cubed sphere grid center
+! remap vertically with terrain adjustment
+
+ call remap_xyz( im, 1, jm, jm, km, npz, nq, Atm(1)%ncnst, lon, lat, ak0, bk0, &
+ ps0, gz0, ua, va, t0, q0, Atm(1) )
+
+ deallocate ( ak0 )
+ deallocate ( bk0 )
+ deallocate ( ps0 )
+ deallocate ( gz0 )
+ deallocate ( t0 )
+ deallocate ( q0 )
+ deallocate ( dp0 )
+ deallocate ( ua )
+ deallocate ( va )
+ deallocate ( lat )
+ deallocate ( lon )
+
+ end subroutine get_fv_ic
+!------------------------------------------------------------------
+!------------------------------------------------------------------
+#ifndef DYCORE_SOLO
+ subroutine ncep2fms(im, jm, lon, lat, wk)
+
+ integer, intent(in):: im, jm
+ real, intent(in):: lon(im), lat(jm)
+ real(kind=4), intent(in):: wk(im,jm)
+! local:
+ real :: rdlon(im)
+ real :: rdlat(jm)
+ real:: a1, b1
+ real:: delx, dely
+ real:: xc, yc ! "data" location
+ real:: c1, c2, c3, c4
+ integer i,j, i1, i2, jc, i0, j0, it, jt
+
+ do i=1,im-1
+ rdlon(i) = 1. / (lon(i+1) - lon(i))
+ enddo
+ rdlon(im) = 1. / (lon(1) + 2.*pi - lon(im))
+
+ do j=1,jm-1
+ rdlat(j) = 1. / (lat(j+1) - lat(j))
+ enddo
+
+! * Interpolate to "FMS" 1x1 SST data grid
+! lon: 0.5, 1.5, ..., 359.5
+! lat: -89.5, -88.5, ... , 88.5, 89.5
+
+ delx = 360./real(i_sst)
+ dely = 180./real(j_sst)
+
+ jt = 1
+ do 5000 j=1,j_sst
+
+ yc = (-90. + dely * (0.5+real(j-1))) * deg2rad
+ if ( yclat(jm) ) then
+ jc = jm-1
+ b1 = 1.
+ else
+ do j0=jt,jm-1
+ if ( yc>=lat(j0) .and. yc<=lat(j0+1) ) then
+ jc = j0
+ jt = j0
+ b1 = (yc-lat(jc)) * rdlat(jc)
+ go to 222
+ endif
+ enddo
+ endif
+222 continue
+ it = 1
+
+ do i=1,i_sst
+ xc = delx * (0.5+real(i-1)) * deg2rad
+ if ( xc>lon(im) ) then
+ i1 = im; i2 = 1
+ a1 = (xc-lon(im)) * rdlon(im)
+ elseif ( xc=lon(i0) .and. xc<=lon(i0+1) ) then
+ i1 = i0; i2 = i0+1
+ it = i0
+ a1 = (xc-lon(i1)) * rdlon(i0)
+ go to 111
+ endif
+ enddo
+ endif
+111 continue
+
+ if ( a1<0.0 .or. a1>1.0 .or. b1<0.0 .or. b1>1.0 ) then
+ write(*,*) 'gid=', mpp_pe(), i,j,a1, b1
+ endif
+
+ c1 = (1.-a1) * (1.-b1)
+ c2 = a1 * (1.-b1)
+ c3 = a1 * b1
+ c4 = (1.-a1) * b1
+! Interpolated surface pressure
+ sst_ncep(i,j) = c1*wk(i1,jc ) + c2*wk(i2,jc ) + &
+ c3*wk(i2,jc+1) + c4*wk(i1,jc+1)
+ enddo !i-loop
+5000 continue ! j-loop
+
+ end subroutine ncep2fms
+#endif
+
+
+ subroutine remap_coef( is, ie, js, je, isd, ied, jsd, jed, &
+ im, jm, lon, lat, id1, id2, jdc, s2c, agrid )
+
+ integer, intent(in):: is, ie, js, je, isd, ied, jsd, jed
+ integer, intent(in):: im, jm
+ real, intent(in):: lon(im), lat(jm)
+ real, intent(out):: s2c(is:ie,js:je,4)
+ integer, intent(out), dimension(is:ie,js:je):: id1, id2, jdc
+ real, intent(in):: agrid(isd:ied,jsd:jed,2)
+! local:
+ real :: rdlon(im)
+ real :: rdlat(jm)
+ real:: a1, b1
+ integer i,j, i1, i2, jc, i0, j0
+
+ do i=1,im-1
+ rdlon(i) = 1. / (lon(i+1) - lon(i))
+ enddo
+ rdlon(im) = 1. / (lon(1) + 2.*pi - lon(im))
+
+ do j=1,jm-1
+ rdlat(j) = 1. / (lat(j+1) - lat(j))
+ enddo
+
+! * Interpolate to cubed sphere cell center
+ do 5000 j=js,je
+
+ do i=is,ie
+
+ if ( agrid(i,j,1)>lon(im) ) then
+ i1 = im; i2 = 1
+ a1 = (agrid(i,j,1)-lon(im)) * rdlon(im)
+ elseif ( agrid(i,j,1)=lon(i0) .and. agrid(i,j,1)<=lon(i0+1) ) then
+ i1 = i0; i2 = i0+1
+ a1 = (agrid(i,j,1)-lon(i1)) * rdlon(i0)
+ go to 111
+ endif
+ enddo
+ endif
+111 continue
+
+ if ( agrid(i,j,2)lat(jm) ) then
+ jc = jm-1
+ b1 = 1.
+ else
+ do j0=1,jm-1
+ if ( agrid(i,j,2)>=lat(j0) .and. agrid(i,j,2)<=lat(j0+1) ) then
+ jc = j0
+ b1 = (agrid(i,j,2)-lat(jc)) * rdlat(jc)
+ go to 222
+ endif
+ enddo
+ endif
+222 continue
+
+ if ( a1<0.0 .or. a1>1.0 .or. b1<0.0 .or. b1>1.0 ) then
+ write(*,*) 'gid=', mpp_pe(), i,j,a1, b1
+ endif
+
+ s2c(i,j,1) = (1.-a1) * (1.-b1)
+ s2c(i,j,2) = a1 * (1.-b1)
+ s2c(i,j,3) = a1 * b1
+ s2c(i,j,4) = (1.-a1) * b1
+ id1(i,j) = i1
+ id2(i,j) = i2
+ jdc(i,j) = jc
+ enddo !i-loop
+5000 continue ! j-loop
+
+ end subroutine remap_coef
+
+
+ subroutine remap_scalar(im, jm, km, npz, nq, ncnst, ak0, bk0, psc, gzc, ta, qa, Atm)
+ type(fv_atmos_type), intent(inout) :: Atm
+ integer, intent(in):: im, jm, km, npz, nq, ncnst
+ real, intent(in):: ak0(km+1), bk0(km+1)
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je):: psc, gzc
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km):: ta
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km,ncnst):: qa
+! local:
+ real, dimension(Atm%bd%is:Atm%bd%ie,km):: tp
+ real, dimension(Atm%bd%is:Atm%bd%ie,km+1):: pe0, pn0
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz):: qn1
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz+1):: pe1, pn1
+ real(kind=R_GRID), dimension(2*km+1):: gz, pn
+ real pk0(km+1)
+ real qp(Atm%bd%is:Atm%bd%ie,km,ncnst)
+ real p1, p2, alpha, rdg
+ real(kind=R_GRID):: pst, pt0
+#ifdef MULTI_GASES
+ integer spfo, spfo2, spfo3
+#else
+ integer o3mr
+#endif
+ integer i,j,k, k2,l, iq
+ integer sphum, clwmr
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+
+ is = Atm%bd%is
+ ie = Atm%bd%ie
+ js = Atm%bd%js
+ je = Atm%bd%je
+ isd = Atm%bd%isd
+ ied = Atm%bd%ied
+ jsd = Atm%bd%jsd
+ jed = Atm%bd%jed
+
+ k2 = max(10, km/2)
+
+! nq is always 1
+ sphum = get_tracer_index(MODEL_ATMOS, 'sphum')
+
+ if (mpp_pe()==1) then
+ print *, 'sphum = ', sphum, ' ncnst=', ncnst
+ print *, 'T_is_Tv = ', T_is_Tv, ' zvir=', zvir, ' kappa=', kappa
+ endif
+
+ if ( sphum/=1 ) then
+ call mpp_error(FATAL,'SPHUM must be 1st tracer')
+ endif
+
+ call prt_maxmin('ZS_FV3', Atm%phis, is, ie, js, je, 3, 1, 1./grav)
+ call prt_maxmin('ZS_GFS', gzc, is, ie, js, je, 0, 1, 1./grav)
+ call prt_maxmin('PS_Data', psc, is, ie, js, je, 0, 1, 0.01)
+ call prt_maxmin('T_Data', ta, is, ie, js, je, 0, km, 1.)
+ call prt_maxmin('q_Data', qa(is:ie,js:je,1:km,1), is, ie, js, je, 0, km, 1.)
+
+ do 5000 j=js,je
+
+ do i=is,ie
+
+ do iq=1,ncnst
+ do k=1,km
+ qp(i,k,iq) = qa(i,j,k,iq)
+ enddo
+ enddo
+
+ if ( T_is_Tv ) then
+! The "T" field in NCEP analysis is actually virtual temperature (Larry H. post processing)
+! BEFORE 20051201
+ do k=1,km
+ tp(i,k) = ta(i,j,k)
+ enddo
+ else
+ do k=1,km
+#ifdef MULTI_GASES
+ tp(i,k) = ta(i,j,k)*virq(qp(i,k,:))
+#else
+ tp(i,k) = ta(i,j,k)*(1.+zvir*qp(i,k,sphum))
+#endif
+ enddo
+ endif
+! Tracers:
+
+ do k=1,km+1
+ pe0(i,k) = ak0(k) + bk0(k)*psc(i,j)
+ pn0(i,k) = log(pe0(i,k))
+ pk0(k) = pe0(i,k)**kappa
+ enddo
+! gzc is geopotential
+
+! Note the following line, gz is actully Z (from Jeff's data).
+ gz(km+1) = gzc(i,j)
+ do k=km,1,-1
+ gz(k) = gz(k+1) + rdgas*tp(i,k)*(pn0(i,k+1)-pn0(i,k))
+ enddo
+
+ do k=1,km+1
+ pn(k) = pn0(i,k)
+ enddo
+! Use log-p for interpolation/extrapolation
+! mirror image method:
+ do k=km+2, km+k2
+ l = 2*(km+1) - k
+ gz(k) = 2.*gz(km+1) - gz(l)
+ pn(k) = 2.*pn(km+1) - pn(l)
+ enddo
+ do k=km+k2-1, 2, -1
+ if( Atm%phis(i,j).le.gz(k) .and. Atm%phis(i,j).ge.gz(k+1) ) then
+ pst = pn(k) + (pn(k+1)-pn(k))*(gz(k)-Atm%phis(i,j))/(gz(k)-gz(k+1))
+ go to 123
+ endif
+ enddo
+123 Atm%ps(i,j) = exp(pst)
+ enddo ! i-loop
+
+ do i=is,ie
+ pe1(i,1) = Atm%ak(1)
+ pn1(i,1) = log(pe1(i,1))
+ enddo
+ do k=2,npz+1
+ do i=is,ie
+ pe1(i,k) = Atm%ak(k) + Atm%bk(k)*Atm%ps(i,j)
+ pn1(i,k) = log(pe1(i,k))
+ enddo
+ enddo
+
+! * Compute delp
+ do k=1,npz
+ do i=is,ie
+ Atm%delp(i,j,k) = pe1(i,k+1) - pe1(i,k)
+ enddo
+ enddo
+
+!---------------
+! map shpum, o3mr, clwmr tracers
+!----------------
+ do iq=1,ncnst
+ call mappm(km, pe0, qp(is,1,iq), npz, pe1, qn1, is,ie, 0, 11, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+ Atm%q(i,j,k,iq) = qn1(i,k)
+ enddo
+ enddo
+ enddo
+
+!-------------------------------------------------------------
+! map virtual temperature using geopotential conserving scheme.
+!-------------------------------------------------------------
+ call mappm(km, pn0, tp, npz, pn1, qn1, is,ie, 1, 9, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+#ifdef MULTI_GASES
+ Atm%pt(i,j,k) = qn1(i,k)/virq(Atm%q(i,j,k,:))
+#else
+ Atm%pt(i,j,k) = qn1(i,k)/(1.+zvir*Atm%q(i,j,k,sphum))
+#endif
+ enddo
+ enddo
+
+ if ( .not. Atm%flagstruct%hydrostatic .and. Atm%flagstruct%ncep_ic ) then
+! Replace delz with NCEP hydrostatic state
+ rdg = -rdgas / grav
+ do k=1,npz
+ do i=is,ie
+ atm%delz(i,j,k) = rdg*qn1(i,k)*(pn1(i,k+1)-pn1(i,k))
+ enddo
+ enddo
+ endif
+
+5000 continue
+
+ call prt_maxmin('PS_model', Atm%ps(is:ie,js:je), is, ie, js, je, 0, 1, 0.01)
+
+ if (is_master()) write(*,*) 'done remap_scalar'
+
+ end subroutine remap_scalar
+
+
+ subroutine remap_scalar_nggps(Atm, km, npz, ncnst, ak0, bk0, psc, t_in, qa, omga, zh)
+ type(fv_atmos_type), intent(inout) :: Atm
+ integer, intent(in):: km, npz, ncnst
+ real, intent(in):: ak0(km+1), bk0(km+1)
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je):: psc
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km):: t_in
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km):: omga
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km,ncnst):: qa
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km+1):: zh
+! local:
+ real, dimension(Atm%bd%is:Atm%bd%ie,km+1):: pe0
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz):: qn1, dp2
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz+1):: pe1
+ real qp(Atm%bd%is:Atm%bd%ie,km)
+ real wk(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je)
+ real, dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je):: z500
+!!! High-precision
+ real(kind=R_GRID), dimension(Atm%bd%is:Atm%bd%ie,npz+1):: pn1
+ real(kind=R_GRID):: gz_fv(npz+1)
+ real(kind=R_GRID), dimension(2*km+1):: gz, pn
+ real(kind=R_GRID), dimension(Atm%bd%is:Atm%bd%ie,km+1):: pn0
+ real(kind=R_GRID):: pst
+!!! High-precision
+ integer i,j,k,l,m, k2,iq
+ integer sphum, liq_wat, ice_wat, rainwat, snowwat, graupel, cld_amt, liq_aero, ice_aero
+#ifdef MULTI_GASES
+ integer spfo, spfo2, spfo3
+#else
+ integer o3mr
+#endif
+ integer :: is, ie, js, je
+
+ is = Atm%bd%is
+ ie = Atm%bd%ie
+ js = Atm%bd%js
+ je = Atm%bd%je
+
+ sphum = get_tracer_index(MODEL_ATMOS, 'sphum')
+ liq_wat = get_tracer_index(MODEL_ATMOS, 'liq_wat')
+ ice_wat = get_tracer_index(MODEL_ATMOS, 'ice_wat')
+ rainwat = get_tracer_index(MODEL_ATMOS, 'rainwat')
+ snowwat = get_tracer_index(MODEL_ATMOS, 'snowwat')
+ graupel = get_tracer_index(MODEL_ATMOS, 'graupel')
+ cld_amt = get_tracer_index(MODEL_ATMOS, 'cld_amt')
+#ifdef MULTI_GASES
+ spfo = get_tracer_index(MODEL_ATMOS, 'spfo')
+ spfo2 = get_tracer_index(MODEL_ATMOS, 'spfo2')
+ spfo3 = get_tracer_index(MODEL_ATMOS, 'spfo3')
+#else
+ o3mr = get_tracer_index(MODEL_ATMOS, 'o3mr')
+#endif
+ liq_aero = get_tracer_index(MODEL_ATMOS, 'liq_aero')
+ ice_aero = get_tracer_index(MODEL_ATMOS, 'ice_aero')
+
+ k2 = max(10, km/2)
+
+ if (mpp_pe()==1) then
+ print *, 'sphum = ', sphum
+ print *, 'clwmr = ', liq_wat
+#ifdef MULTI_GASES
+ print *, 'spfo3 = ', spfo3
+ print *, ' spfo = ', spfo
+ print *, 'spfo2 = ', spfo2
+#else
+ print *, ' o3mr = ', o3mr
+#endif
+ print *, 'liq_aero = ', liq_aero
+ print *, 'ice_aero = ', ice_aero
+ print *, 'ncnst = ', ncnst
+ endif
+
+ if ( sphum/=1 ) then
+ call mpp_error(FATAL,'SPHUM must be 1st tracer')
+ endif
+
+#ifdef USE_GFS_ZS
+ Atm%phis(is:ie,js:je) = zh(is:ie,js:je,km+1)*grav
+#endif
+
+!$OMP parallel do default(none) &
+!$OMP shared(sphum,liq_wat,rainwat,ice_wat,snowwat,graupel,liq_aero,ice_aero,source, &
+!$OMP cld_amt,ncnst,npz,is,ie,js,je,km,k2,ak0,bk0,psc,t_in,zh,omga,qa,Atm,z500) &
+!$OMP private(l,m,pst,pn,gz,pe0,pn0,pe1,pn1,dp2,qp,qn1,gz_fv)
+ do 5000 j=js,je
+ do k=1,km+1
+ do i=is,ie
+ pe0(i,k) = ak0(k) + bk0(k)*psc(i,j)
+ pn0(i,k) = log(pe0(i,k))
+ enddo
+ enddo
+
+ do i=is,ie
+ do k=1,km+1
+ pn(k) = pn0(i,k)
+ gz(k) = zh(i,j,k)*grav
+ enddo
+! Use log-p for interpolation/extrapolation
+! mirror image method:
+ do k=km+2, km+k2
+ l = 2*(km+1) - k
+ gz(k) = 2.*gz(km+1) - gz(l)
+ pn(k) = 2.*pn(km+1) - pn(l)
+ enddo
+
+ do k=km+k2-1, 2, -1
+ if( Atm%phis(i,j).le.gz(k) .and. Atm%phis(i,j).ge.gz(k+1) ) then
+ pst = pn(k) + (pn(k+1)-pn(k))*(gz(k)-Atm%phis(i,j))/(gz(k)-gz(k+1))
+ go to 123
+ endif
+ enddo
+123 Atm%ps(i,j) = exp(pst)
+
+! ------------------
+! Find 500-mb height
+! ------------------
+ pst = log(500.e2)
+ do k=km+k2-1, 2, -1
+ if( pst.le.pn(k+1) .and. pst.ge.pn(k) ) then
+ z500(i,j) = (gz(k+1) + (gz(k)-gz(k+1))*(pn(k+1)-pst)/(pn(k+1)-pn(k)))/grav
+ go to 124
+ endif
+ enddo
+124 continue
+
+ enddo ! i-loop
+
+ do i=is,ie
+ pe1(i,1) = Atm%ak(1)
+ pn1(i,1) = log(pe1(i,1))
+ enddo
+ do k=2,npz+1
+ do i=is,ie
+ pe1(i,k) = Atm%ak(k) + Atm%bk(k)*Atm%ps(i,j)
+ pn1(i,k) = log(pe1(i,k))
+ enddo
+ enddo
+
+! * Compute delp
+ do k=1,npz
+ do i=is,ie
+ dp2(i,k) = pe1(i,k+1) - pe1(i,k)
+ Atm%delp(i,j,k) = dp2(i,k)
+ enddo
+ enddo
+
+! map tracers
+ do iq=1,ncnst
+ do k=1,km
+ do i=is,ie
+ qp(i,k) = qa(i,j,k,iq)
+ enddo
+ enddo
+ call mappm(km, pe0, qp, npz, pe1, qn1, is,ie, 0, 8, Atm%ptop)
+ if ( iq==sphum ) then
+ call fillq(ie-is+1, npz, 1, qn1, dp2)
+ else
+ call fillz(ie-is+1, npz, 1, qn1, dp2)
+ endif
+! The HiRam step of blending model sphum with NCEP data is obsolete because nggps is always cold starting...
+ do k=1,npz
+ do i=is,ie
+ Atm%q(i,j,k,iq) = qn1(i,k)
+ enddo
+ enddo
+ enddo
+
+!---------------------------------------------------
+! Retrive temperature using GFS geopotential height
+!---------------------------------------------------
+ do i=is,ie
+! Make sure FV3 top is lower than GFS; can not do extrapolation above the top at this point
+ if ( pn1(i,1) .lt. pn0(i,1) ) then
+ call mpp_error(FATAL,'FV3 top higher than NCEP/GFS')
+ endif
+
+ do k=1,km+1
+ pn(k) = pn0(i,k)
+ gz(k) = zh(i,j,k)*grav
+ enddo
+!-------------------------------------------------
+ do k=km+2, km+k2
+ l = 2*(km+1) - k
+ gz(k) = 2.*gz(km+1) - gz(l)
+ pn(k) = 2.*pn(km+1) - pn(l)
+ enddo
+!-------------------------------------------------
+
+ gz_fv(npz+1) = Atm%phis(i,j)
+
+ m = 1
+
+ do k=1,npz
+! Searching using FV3 log(pe): pn1
+#ifdef USE_ISOTHERMO
+ do l=m,km
+ if ( (pn1(i,k).le.pn(l+1)) .and. (pn1(i,k).ge.pn(l)) ) then
+ gz_fv(k) = gz(l) + (gz(l+1)-gz(l))*(pn1(i,k)-pn(l))/(pn(l+1)-pn(l))
+ goto 555
+ elseif ( pn1(i,k) .gt. pn(km+1) ) then
+! Isothermal under ground; linear in log-p extra-polation
+ gz_fv(k) = gz(km+1) + (gz_fv(npz+1)-gz(km+1))*(pn1(i,k)-pn(km+1))/(pn1(i,npz+1)-pn(km+1))
+ goto 555
+ endif
+ enddo
+#else
+ do l=m,km+k2-1
+ if ( (pn1(i,k).le.pn(l+1)) .and. (pn1(i,k).ge.pn(l)) ) then
+ gz_fv(k) = gz(l) + (gz(l+1)-gz(l))*(pn1(i,k)-pn(l))/(pn(l+1)-pn(l))
+ goto 555
+ endif
+ enddo
+#endif
+555 m = l
+ enddo
+
+ do k=1,npz+1
+ Atm%peln(i,k,j) = pn1(i,k)
+ enddo
+
+!----------------------------------------------------
+! Compute true temperature using hydrostatic balance
+!----------------------------------------------------
+ if (trim(source) /= 'FV3GFS GAUSSIAN NEMSIO FILE') then
+ do k=1,npz
+#ifdef MULTI_GASES
+ Atm%pt(i,j,k) = (gz_fv(k)-gz_fv(k+1))/( rdgas*(pn1(i,k+1)-pn1(i,k))*virq(Atm%q(i,j,k,:)) )
+#else
+ Atm%pt(i,j,k) = (gz_fv(k)-gz_fv(k+1))/( rdgas*(pn1(i,k+1)-pn1(i,k))*(1.+zvir*Atm%q(i,j,k,sphum)) )
+#endif
+ enddo
+!------------------------------
+! Remap input T linearly in p.
+!------------------------------
+ else
+ do k=1,km
+ qp(i,k) = t_in(i,j,k)
+ enddo
+
+ call mappm(km, pe0, qp, npz, pe1, qn1, is,ie, 2, 4, Atm%ptop)
+
+ do k=1,npz
+ Atm%pt(i,j,k) = qn1(i,k)
+ enddo
+ endif
+
+ if ( .not. Atm%flagstruct%hydrostatic ) then
+ do k=1,npz
+ Atm%delz(i,j,k) = (gz_fv(k+1) - gz_fv(k)) / grav
+ enddo
+ endif
+
+ enddo ! i-loop
+
+!-----------------------------------------------------------------------
+! seperate cloud water and cloud ice
+! From Jan-Huey Chen's HiRAM code
+!-----------------------------------------------------------------------
+ if (cld_amt .gt. 0) Atm%q(:,:,:,cld_amt) = 0.
+ if (trim(source) /= 'FV3GFS GAUSSIAN NEMSIO FILE') then
+ if ( Atm%flagstruct%nwat .eq. 6 ) then
+ do k=1,npz
+ do i=is,ie
+ qn1(i,k) = Atm%q(i,j,k,liq_wat)
+ Atm%q(i,j,k,rainwat) = 0.
+ Atm%q(i,j,k,snowwat) = 0.
+ Atm%q(i,j,k,graupel) = 0.
+! if (cld_amt .gt. 0) Atm%q(i,j,k,cld_amt) = 0.
+ if ( Atm%pt(i,j,k) > 273.16 ) then ! > 0C all liq_wat
+ Atm%q(i,j,k,liq_wat) = qn1(i,k)
+ Atm%q(i,j,k,ice_wat) = 0.
+#ifdef ORIG_CLOUDS_PART
+ else if ( Atm%pt(i,j,k) < 258.16 ) then ! < -15C all ice_wat
+ Atm%q(i,j,k,liq_wat) = 0.
+ Atm%q(i,j,k,ice_wat) = qn1(i,k)
+ else ! between -15~0C: linear interpolation
+ Atm%q(i,j,k,liq_wat) = qn1(i,k)*((Atm%pt(i,j,k)-258.16)/15.)
+ Atm%q(i,j,k,ice_wat) = qn1(i,k) - Atm%q(i,j,k,liq_wat)
+ endif
+#else
+ else if ( Atm%pt(i,j,k) < 233.16 ) then ! < -40C all ice_wat
+ Atm%q(i,j,k,liq_wat) = 0.
+ Atm%q(i,j,k,ice_wat) = qn1(i,k)
+ else
+ if ( k.eq.1 ) then ! between [-40,0]: linear interpolation
+ Atm%q(i,j,k,liq_wat) = qn1(i,k)*((Atm%pt(i,j,k)-233.16)/40.)
+ Atm%q(i,j,k,ice_wat) = qn1(i,k) - Atm%q(i,j,k,liq_wat)
+ else
+ if (Atm%pt(i,j,k)<258.16 .and. Atm%q(i,j,k-1,ice_wat)>1.e-5 ) then
+ Atm%q(i,j,k,liq_wat) = 0.
+ Atm%q(i,j,k,ice_wat) = qn1(i,k)
+ else ! between [-40,0]: linear interpolation
+ Atm%q(i,j,k,liq_wat) = qn1(i,k)*((Atm%pt(i,j,k)-233.16)/40.)
+ Atm%q(i,j,k,ice_wat) = qn1(i,k) - Atm%q(i,j,k,liq_wat)
+ endif
+ endif
+ endif
+#endif
+ call mp_auto_conversion(Atm%q(i,j,k,liq_wat), Atm%q(i,j,k,rainwat), &
+ Atm%q(i,j,k,ice_wat), Atm%q(i,j,k,snowwat) )
+ enddo
+ enddo
+ endif
+ endif ! data source /= FV3GFS GAUSSIAN NEMSIO FILE
+
+! For GFS spectral input, omega in pa/sec is stored as w in the input data so actual w(m/s) is calculated
+! For GFS nemsio input, omega is 0, so best not to use for input since boundary data will not exist for w
+! For FV3GFS NEMSIO input, w is already in m/s (but the code reads in as omga) and just needs to be remapped
+!-------------------------------------------------------------
+! map omega
+!------- ------------------------------------------------------
+ if ( .not. Atm%flagstruct%hydrostatic ) then
+ do k=1,km
+ do i=is,ie
+ qp(i,k) = omga(i,j,k)
+ enddo
+ enddo
+ call mappm(km, pe0, qp, npz, pe1, qn1, is,ie, -1, 4, Atm%ptop)
+ if (trim(source) == 'FV3GFS GAUSSIAN NEMSIO FILE') then
+ do k=1,npz
+ do i=is,ie
+ atm%w(i,j,k) = qn1(i,k)
+ enddo
+ enddo
+
+ else
+ do k=1,npz
+ do i=is,ie
+ atm%w(i,j,k) = qn1(i,k)/atm%delp(i,j,k)*atm%delz(i,j,k)
+ enddo
+ enddo
+ endif
+ endif !.not. Atm%flagstruct%hydrostatic
+5000 continue
+
+! Add some diagnostics:
+ call p_maxmin('PS_model (mb)', Atm%ps(is:ie,js:je), is, ie, js, je, 1, 0.01)
+ call p_maxmin('PT_model', Atm%pt(is:ie,js:je,1:npz), is, ie, js, je, npz, 1.)
+ do j=js,je
+ do i=is,ie
+ wk(i,j) = Atm%phis(i,j)/grav - zh(i,j,km+1)
+ enddo
+ enddo
+ call pmaxmn('ZS_diff (m)', wk, is, ie, js, je, 1, 1., Atm%gridstruct%area_64, Atm%domain)
+
+ if (.not.Atm%neststruct%nested) then
+ call prt_gb_nh_sh('GFS_IC Z500', is,ie, js,je, z500, Atm%gridstruct%area_64(is:ie,js:je), Atm%gridstruct%agrid_64(is:ie,js:je,2))
+ if ( .not. Atm%flagstruct%hydrostatic ) &
+ call prt_height('fv3_IC Z500', is,ie, js,je, 3, npz, 500.E2, Atm%phis, Atm%delz, Atm%peln, &
+ Atm%gridstruct%area_64(is:ie,js:je), Atm%gridstruct%agrid_64(is:ie,js:je,2))
+ endif
+
+ do j=js,je
+ do i=is,ie
+ wk(i,j) = Atm%ps(i,j) - psc(i,j)
+ enddo
+ enddo
+ call pmaxmn('PS_diff (mb)', wk, is, ie, js, je, 1, 0.01, Atm%gridstruct%area_64, Atm%domain)
+
+ if (is_master()) write(*,*) 'done remap_scalar_nggps'
+
+ end subroutine remap_scalar_nggps
+
+ subroutine remap_scalar_ec(Atm, km, npz, ncnst, ak0, bk0, psc, qa, wc, zh)
+ type(fv_atmos_type), intent(inout) :: Atm
+ integer, intent(in):: km, npz, ncnst
+ real, intent(in):: ak0(km+1), bk0(km+1)
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je):: psc
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km):: wc
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km,ncnst):: qa
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km+1):: zh
+! local:
+ real, dimension(Atm%bd%is:Atm%bd%ie,km+1):: pe0
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz):: qn1, dp2
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz+1):: pe1
+ real qp(Atm%bd%is:Atm%bd%ie,km)
+ real wk(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je)
+!!! High-precision
+ real(kind=R_GRID), dimension(Atm%bd%is:Atm%bd%ie,npz+1):: pn1
+ real(kind=R_GRID):: gz_fv(npz+1)
+ real(kind=R_GRID), dimension(2*km+1):: gz, pn
+ real(kind=R_GRID), dimension(Atm%bd%is:Atm%bd%ie,km+1):: pn0
+ real(kind=R_GRID):: pst
+ real, dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je):: z500
+!!! High-precision
+ integer:: sphum, liq_wat, ice_wat, rainwat, snowwat, graupel, cld_amt
+#ifdef MULTI_GASES
+ integer:: spfo, spfo2, spfo3
+#else
+ integer:: o3mr
+#endif
+ integer:: i,j,k,l,m,k2, iq
+ integer:: is, ie, js, je
+
+ is = Atm%bd%is
+ ie = Atm%bd%ie
+ js = Atm%bd%js
+ je = Atm%bd%je
+
+ sphum = get_tracer_index(MODEL_ATMOS, 'sphum')
+ liq_wat = get_tracer_index(MODEL_ATMOS, 'liq_wat')
+
+ if ( Atm%flagstruct%nwat .eq. 6 ) then
+ ice_wat = get_tracer_index(MODEL_ATMOS, 'ice_wat')
+ rainwat = get_tracer_index(MODEL_ATMOS, 'rainwat')
+ snowwat = get_tracer_index(MODEL_ATMOS, 'snowwat')
+ graupel = get_tracer_index(MODEL_ATMOS, 'graupel')
+ cld_amt = get_tracer_index(MODEL_ATMOS, 'cld_amt')
+ endif
+ if (cld_amt .gt. 0) Atm%q(:,:,:,cld_amt) = 0.
+
+ k2 = max(10, km/2)
+
+ if (mpp_pe()==1) then
+ print *, 'In remap_scalar_ec:'
+ print *, 'ncnst = ', ncnst
+ print *, 'sphum = ', sphum
+ print *, 'liq_wat = ', liq_wat
+ if ( Atm%flagstruct%nwat .eq. 6 ) then
+ print *, 'rainwat = ', rainwat
+ print *, 'ice_wat = ', ice_wat
+ print *, 'snowwat = ', snowwat
+ print *, 'graupel = ', graupel
+ endif
+ endif
+
+!$OMP parallel do default(none) shared(sphum,ncnst,npz,is,ie,js,je,km,k2,ak0,bk0,psc,zh,qa,wc,Atm,z500) &
+!$OMP private(l,m,pst,pn,gz,pe0,pn0,pe1,pn1,dp2,qp,qn1,gz_fv)
+ do 5000 j=js,je
+ do k=1,km+1
+ do i=is,ie
+ pe0(i,k) = ak0(k) + bk0(k)*psc(i,j)
+ pn0(i,k) = log(pe0(i,k))
+ enddo
+ enddo
+
+ do i=is,ie
+ do k=1,km+1
+ pn(k) = pn0(i,k)
+ gz(k) = zh(i,j,k)*grav
+ enddo
+! Use log-p for interpolation/extrapolation
+! mirror image method:
+ do k=km+2, km+k2
+ l = 2*(km+1) - k
+ gz(k) = 2.*gz(km+1) - gz(l)
+ pn(k) = 2.*pn(km+1) - pn(l)
+ enddo
+
+ do k=km+k2-1, 2, -1
+ if( Atm%phis(i,j).le.gz(k) .and. Atm%phis(i,j).ge.gz(k+1) ) then
+ pst = pn(k) + (pn(k+1)-pn(k))*(gz(k)-Atm%phis(i,j))/(gz(k)-gz(k+1))
+ go to 123
+ endif
+ enddo
+123 Atm%ps(i,j) = exp(pst)
+
+! ------------------
+! Find 500-mb height
+! ------------------
+ pst = log(500.e2)
+ do k=km+k2-1, 2, -1
+ if( pst.le.pn(k+1) .and. pst.ge.pn(k) ) then
+ z500(i,j) = (gz(k+1) + (gz(k)-gz(k+1))*(pn(k+1)-pst)/(pn(k+1)-pn(k)))/grav
+ go to 125
+ endif
+ enddo
+125 continue
+
+ enddo ! i-loop
+
+ do i=is,ie
+ pe1(i,1) = Atm%ak(1)
+ pn1(i,1) = log(pe1(i,1))
+ enddo
+ do k=2,npz+1
+ do i=is,ie
+ pe1(i,k) = Atm%ak(k) + Atm%bk(k)*Atm%ps(i,j)
+ pn1(i,k) = log(pe1(i,k))
+ enddo
+ enddo
+
+! * Compute delp
+ do k=1,npz
+ do i=is,ie
+ dp2(i,k) = pe1(i,k+1) - pe1(i,k)
+ Atm%delp(i,j,k) = dp2(i,k)
+ enddo
+ enddo
+
+! map shpum, liq_wat, ice_wat, rainwat, snowwat tracers
+ do iq=1,ncnst
+ do k=1,km
+ do i=is,ie
+ qp(i,k) = qa(i,j,k,iq)
+ enddo
+ enddo
+ call mappm(km, pe0, qp, npz, pe1, qn1, is,ie, 0, 8, Atm%ptop)
+ if ( iq==1 ) then
+ call fillq(ie-is+1, npz, 1, qn1, dp2)
+ else
+ call fillz(ie-is+1, npz, 1, qn1, dp2)
+ endif
+! The HiRam step of blending model sphum with NCEP data is obsolete because nggps is always cold starting...
+ do k=1,npz
+ do i=is,ie
+ Atm%q(i,j,k,iq) = qn1(i,k)
+ enddo
+ enddo
+ enddo
+!---------------------------------------------------
+! Retrive temperature using EC geopotential height
+!---------------------------------------------------
+ do i=is,ie
+! Make sure FV3 top is lower than GFS; can not do extrapolation above the top at this point
+ if ( pn1(i,1) .lt. pn0(i,1) ) then
+ call mpp_error(FATAL,'FV3 top higher than ECMWF')
+ endif
+
+ do k=1,km+1
+ pn(k) = pn0(i,k)
+ gz(k) = zh(i,j,k)*grav
+ enddo
+!-------------------------------------------------
+ do k=km+2, km+k2
+ l = 2*(km+1) - k
+ gz(k) = 2.*gz(km+1) - gz(l)
+ pn(k) = 2.*pn(km+1) - pn(l)
+ enddo
+!-------------------------------------------------
+ gz_fv(npz+1) = Atm%phis(i,j)
+
+ m = 1
+ do k=1,npz
+! Searching using FV3 log(pe): pn1
+#ifdef USE_ISOTHERMO
+ do l=m,km
+ if ( (pn1(i,k).le.pn(l+1)) .and. (pn1(i,k).ge.pn(l)) ) then
+ gz_fv(k) = gz(l) + (gz(l+1)-gz(l))*(pn1(i,k)-pn(l))/(pn(l+1)-pn(l))
+ goto 555
+ elseif ( pn1(i,k) .gt. pn(km+1) ) then
+! Isothermal under ground; linear in log-p extra-polation
+ gz_fv(k) = gz(km+1) + (gz_fv(npz+1)-gz(km+1))*(pn1(i,k)-pn(km+1))/(pn1(i,npz+1)-pn(km+1))
+ goto 555
+ endif
+ enddo
+#else
+ do l=m,km+k2-1
+ if ( (pn1(i,k).le.pn(l+1)) .and. (pn1(i,k).ge.pn(l)) ) then
+ gz_fv(k) = gz(l) + (gz(l+1)-gz(l))*(pn1(i,k)-pn(l))/(pn(l+1)-pn(l))
+ goto 555
+ endif
+ enddo
+#endif
+555 m = l
+ enddo
+
+ do k=1,npz+1
+ Atm%peln(i,k,j) = pn1(i,k)
+ enddo
+
+! Compute true temperature using hydrostatic balance
+ do k=1,npz
+! qc = 1.-(Atm%q(i,j,k,liq_wat)+Atm%q(i,j,k,rainwat)+Atm%q(i,j,k,ice_wat)+Atm%q(i,j,k,snowwat))
+! Atm%pt(i,j,k) = (gz_fv(k)-gz_fv(k+1))*qc/( rdgas*(pn1(i,k+1)-pn1(i,k))*(1.+zvir*Atm%q(i,j,k,sphum)) )
+#ifdef MULTI_GASES
+ Atm%pt(i,j,k) = (gz_fv(k)-gz_fv(k+1))/( rdgas*(pn1(i,k+1)-pn1(i,k))*virq(Atm%q(i,j,k,:)) )
+#else
+ Atm%pt(i,j,k) = (gz_fv(k)-gz_fv(k+1))/( rdgas*(pn1(i,k+1)-pn1(i,k))*(1.+zvir*Atm%q(i,j,k,sphum)) )
+#endif
+ enddo
+ if ( .not. Atm%flagstruct%hydrostatic ) then
+ do k=1,npz
+ Atm%delz(i,j,k) = (gz_fv(k+1) - gz_fv(k)) / grav
+ enddo
+ endif
+
+ enddo ! i-loop
+
+!-------------------------------------------------------------
+! map omega
+!------- ------------------------------------------------------
+ if ( .not. Atm%flagstruct%hydrostatic ) then
+ do k=1,km
+ do i=is,ie
+ qp(i,k) = wc(i,j,k)
+ enddo
+ enddo
+ call mappm(km, pe0, qp, npz, pe1, qn1, is,ie, -1, 4, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+ atm%w(i,j,k) = qn1(i,k)/atm%delp(i,j,k)*atm%delz(i,j,k)
+ enddo
+ enddo
+ endif
+
+5000 continue
+
+! Add some diagnostics:
+ call p_maxmin('PS_model (mb)', Atm%ps(is:ie,js:je), is, ie, js, je, 1, 0.01)
+ call p_maxmin('PT_model', Atm%pt(is:ie,js:je,1:npz), is, ie, js, je, npz, 1.)
+ call pmaxmn('ZS_model', Atm%phis(is:ie,js:je)/grav, is, ie, js, je, 1, 1., Atm%gridstruct%area_64, Atm%domain)
+ call pmaxmn('ZS_EC', zh(is:ie,js:je,km+1), is, ie, js, je, 1, 1., Atm%gridstruct%area_64, Atm%domain)
+ do j=js,je
+ do i=is,ie
+ wk(i,j) = Atm%phis(i,j)/grav - zh(i,j,km+1)
+ ! if ((wk(i,j) > 1800.).or.(wk(i,j)<-1600.)) then
+ ! print *,' '
+ ! print *, 'Diff = ', wk(i,j), 'Atm%phis =', Atm%phis(i,j)/grav, 'zh = ', zh(i,j,km+1)
+ ! print *, 'lat = ', Atm%gridstruct%agrid(i,j,2)/deg2rad, 'lon = ', Atm%gridstruct%agrid(i,j,1)/deg2rad
+ ! endif
+ enddo
+ enddo
+ call pmaxmn('ZS_diff (m)', wk, is, ie, js, je, 1, 1., Atm%gridstruct%area_64, Atm%domain)
+
+ if (.not.Atm%neststruct%nested) then
+ call prt_gb_nh_sh('IFS_IC Z500', is,ie, js,je, z500, Atm%gridstruct%area_64(is:ie,js:je), Atm%gridstruct%agrid_64(is:ie,js:je,2))
+ if ( .not. Atm%flagstruct%hydrostatic ) &
+ call prt_height('fv3_IC Z500', is,ie, js,je, 3, npz, 500.E2, Atm%phis, Atm%delz, Atm%peln, &
+ Atm%gridstruct%area_64(is:ie,js:je), Atm%gridstruct%agrid_64(is:ie,js:je,2))
+ endif
+
+ do j=js,je
+ do i=is,ie
+ wk(i,j) = Atm%ps(i,j) - psc(i,j)
+ enddo
+ enddo
+ call pmaxmn('PS_diff (mb)', wk, is, ie, js, je, 1, 0.01, Atm%gridstruct%area_64, Atm%domain)
+
+ end subroutine remap_scalar_ec
+
+ subroutine remap_scalar_single(Atm, km, npz, ak0, bk0, psc, qa, zh ,iq)
+ type(fv_atmos_type), intent(inout) :: Atm
+ integer, intent(in):: km, npz, iq
+ real, intent(in):: ak0(km+1), bk0(km+1)
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je):: psc
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km):: qa
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km+1):: zh
+! local:
+ real, dimension(Atm%bd%is:Atm%bd%ie,km+1):: pe0
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz):: qn1, dp2
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz+1):: pe1
+ real qp(Atm%bd%is:Atm%bd%ie,km)
+ real wk(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je)
+!!! High-precision
+ real(kind=R_GRID), dimension(Atm%bd%is:Atm%bd%ie,npz+1):: pn1
+ real(kind=R_GRID):: gz_fv(npz+1)
+ real(kind=R_GRID), dimension(2*km+1):: gz, pn
+ real(kind=R_GRID), dimension(Atm%bd%is:Atm%bd%ie,km+1):: pn0
+ real(kind=R_GRID):: pst
+!!! High-precision
+ integer i,j,k, k2, l
+ integer :: is, ie, js, je
+ real, allocatable:: ps_temp(:,:)
+
+ is = Atm%bd%is
+ ie = Atm%bd%ie
+ js = Atm%bd%js
+ je = Atm%bd%je
+
+ k2 = max(10, km/2)
+
+ allocate(ps_temp(is:ie,js:je))
+
+ do 5000 j=js,je
+ do k=1,km+1
+ do i=is,ie
+ pe0(i,k) = ak0(k) + bk0(k)*psc(i,j)
+ pn0(i,k) = log(pe0(i,k))
+ enddo
+ enddo
+
+ do i=is,ie
+ do k=1,km+1
+ pn(k) = pn0(i,k)
+ gz(k) = zh(i,j,k)*grav
+ enddo
+! Use log-p for interpolation/extrapolation
+! mirror image method:
+ do k=km+2, km+k2
+ l = 2*(km+1) - k
+ gz(k) = 2.*gz(km+1) - gz(l)
+ pn(k) = 2.*pn(km+1) - pn(l)
+ enddo
+
+ do k=km+k2-1, 2, -1
+ if( Atm%phis(i,j).le.gz(k) .and. Atm%phis(i,j).ge.gz(k+1) ) then
+ pst = pn(k) + (pn(k+1)-pn(k))*(gz(k)-Atm%phis(i,j))/(gz(k)-gz(k+1))
+ go to 123
+ endif
+ enddo
+123 ps_temp(i,j) = exp(pst)
+ enddo ! i-loop
+
+ do i=is,ie
+ pe1(i,1) = Atm%ak(1)
+ pn1(i,1) = log(pe1(i,1))
+ enddo
+ do k=2,npz+1
+ do i=is,ie
+ pe1(i,k) = Atm%ak(k) + Atm%bk(k)*ps_temp(i,j)
+ pn1(i,k) = log(pe1(i,k))
+ enddo
+ enddo
+
+! * Compute delp
+ do k=1,npz
+ do i=is,ie
+ dp2(i,k) = pe1(i,k+1) - pe1(i,k)
+ enddo
+ enddo
+
+ ! map o3mr
+ do k=1,km
+ do i=is,ie
+ qp(i,k) = qa(i,j,k)
+ enddo
+ enddo
+ call mappm(km, pe0, qp, npz, pe1, qn1, is,ie, 0, 8, Atm%ptop)
+ if ( iq==1 ) then
+ call fillq(ie-is+1, npz, 1, qn1, dp2)
+ else
+ call fillz(ie-is+1, npz, 1, qn1, dp2)
+ endif
+! The HiRam step of blending model sphum with NCEP data is obsolete because nggps is always cold starting...
+ do k=1,npz
+ do i=is,ie
+ Atm%q(i,j,k,iq) = qn1(i,k)
+ enddo
+ enddo
+
+5000 continue
+ call p_maxmin('o3mr remap', Atm%q(is:ie,js:je,1:npz,iq), is, ie, js, je, npz, 1.)
+
+ deallocate(ps_temp)
+
+ end subroutine remap_scalar_single
+
+
+ subroutine mp_auto_conversion(ql, qr, qi, qs)
+ real, intent(inout):: ql, qr, qi, qs
+ real, parameter:: qi0_max = 2.0e-3
+ real, parameter:: ql0_max = 2.5e-3
+
+! Convert excess cloud water into rain:
+ if ( ql > ql0_max ) then
+ qr = ql - ql0_max
+ ql = ql0_max
+ endif
+! Convert excess cloud ice into snow:
+ if ( qi > qi0_max ) then
+ qs = qi - qi0_max
+ qi = qi0_max
+ endif
+
+ end subroutine mp_auto_conversion
+
+
+ subroutine remap_dwinds(km, npz, ak0, bk0, psc, ud, vd, Atm)
+ type(fv_atmos_type), intent(inout) :: Atm
+ integer, intent(in):: km, npz
+ real, intent(in):: ak0(km+1), bk0(km+1)
+ real, intent(in):: psc(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je)
+ real, intent(in):: ud(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je+1,km)
+ real, intent(in):: vd(Atm%bd%is:Atm%bd%ie+1,Atm%bd%js:Atm%bd%je,km)
+! local:
+ real, dimension(Atm%bd%isd:Atm%bd%ied,Atm%bd%jsd:Atm%bd%jed):: psd
+ real, dimension(Atm%bd%is:Atm%bd%ie+1, km+1):: pe0
+ real, dimension(Atm%bd%is:Atm%bd%ie+1,npz+1):: pe1
+ real, dimension(Atm%bd%is:Atm%bd%ie+1,npz):: qn1
+ integer i,j,k
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+
+ is = Atm%bd%is
+ ie = Atm%bd%ie
+ js = Atm%bd%js
+ je = Atm%bd%je
+ isd = Atm%bd%isd
+ ied = Atm%bd%ied
+ jsd = Atm%bd%jsd
+ jed = Atm%bd%jed
+
+ if (Atm%neststruct%nested .or. Atm%flagstruct%regional) then
+ do j=jsd,jed
+ do i=isd,ied
+ psd(i,j) = Atm%ps(i,j)
+ enddo
+ enddo
+ else
+ do j=js,je
+ do i=is,ie
+ psd(i,j) = psc(i,j)
+ enddo
+ enddo
+ endif
+ call mpp_update_domains( psd, Atm%domain, complete=.false. )
+ call mpp_update_domains( Atm%ps, Atm%domain, complete=.true. )
+
+!$OMP parallel do default(none) shared(is,ie,js,je,npz,km,ak0,bk0,Atm,psc,psd,ud,vd) &
+!$OMP private(pe1,pe0,qn1)
+ do 5000 j=js,je+1
+!------
+! map u
+!------
+ do k=1,km+1
+ do i=is,ie
+ pe0(i,k) = ak0(k) + bk0(k)*0.5*(psd(i,j-1)+psd(i,j))
+ enddo
+ enddo
+ do k=1,npz+1
+ do i=is,ie
+ pe1(i,k) = Atm%ak(k) + Atm%bk(k)*0.5*(Atm%ps(i,j-1)+Atm%ps(i,j))
+ enddo
+ enddo
+ call mappm(km, pe0(is:ie,1:km+1), ud(is:ie,j,1:km), npz, pe1(is:ie,1:npz+1), &
+ qn1(is:ie,1:npz), is,ie, -1, 8, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+ Atm%u(i,j,k) = qn1(i,k)
+ enddo
+ enddo
+!------
+! map v
+!------
+ if ( j/=(je+1) ) then
+
+ do k=1,km+1
+ do i=is,ie+1
+ pe0(i,k) = ak0(k) + bk0(k)*0.5*(psd(i-1,j)+psd(i,j))
+ enddo
+ enddo
+ do k=1,npz+1
+ do i=is,ie+1
+ pe1(i,k) = Atm%ak(k) + Atm%bk(k)*0.5*(Atm%ps(i-1,j)+Atm%ps(i,j))
+ enddo
+ enddo
+ call mappm(km, pe0(is:ie+1,1:km+1), vd(is:ie+1,j,1:km), npz, pe1(is:ie+1,1:npz+1), &
+ qn1(is:ie+1,1:npz), is,ie+1, -1, 8, Atm%ptop)
+ do k=1,npz
+ do i=is,ie+1
+ Atm%v(i,j,k) = qn1(i,k)
+ enddo
+ enddo
+
+ endif
+
+5000 continue
+
+ if (is_master()) write(*,*) 'done remap_dwinds'
+
+ end subroutine remap_dwinds
+
+
+ subroutine remap_winds(im, jm, km, npz, ak0, bk0, psc, ua, va, Atm)
+ type(fv_atmos_type), intent(inout) :: Atm
+ integer, intent(in):: im, jm, km, npz
+ real, intent(in):: ak0(km+1), bk0(km+1)
+ real, intent(in):: psc(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je)
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km):: ua, va
+! local:
+ real, dimension(Atm%bd%isd:Atm%bd%ied,Atm%bd%jsd:Atm%bd%jed,npz):: ut, vt ! winds
+ real, dimension(Atm%bd%is:Atm%bd%ie, km+1):: pe0
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz+1):: pe1
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz):: qn1
+ integer i,j,k
+
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+
+ is = Atm%bd%is
+ ie = Atm%bd%ie
+ js = Atm%bd%js
+ je = Atm%bd%je
+ isd = Atm%bd%isd
+ ied = Atm%bd%ied
+ jsd = Atm%bd%jsd
+ jed = Atm%bd%jed
+
+ do 5000 j=js,je
+
+ do k=1,km+1
+ do i=is,ie
+ pe0(i,k) = ak0(k) + bk0(k)*psc(i,j)
+ enddo
+ enddo
+
+ do k=1,npz+1
+ do i=is,ie
+ pe1(i,k) = Atm%ak(k) + Atm%bk(k)*Atm%ps(i,j)
+ enddo
+ enddo
+
+!------
+! map u
+!------
+ call mappm(km, pe0, ua(is:ie,j,1:km), npz, pe1, qn1, is,ie, -1, 8, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+ ut(i,j,k) = qn1(i,k)
+ enddo
+ enddo
+!------
+! map v
+!------
+ call mappm(km, pe0, va(is:ie,j,1:km), npz, pe1, qn1, is,ie, -1, 8, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+ vt(i,j,k) = qn1(i,k)
+ enddo
+ enddo
+
+5000 continue
+
+ call prt_maxmin('UT', ut, is, ie, js, je, ng, npz, 1.)
+ call prt_maxmin('VT', vt, is, ie, js, je, ng, npz, 1.)
+ call prt_maxmin('UA_top',ut(:,:,1), is, ie, js, je, ng, 1, 1.)
+
+!----------------------------------------------
+! winds: lat-lon ON A to Cubed-D transformation:
+!----------------------------------------------
+ call cubed_a2d(Atm%npx, Atm%npy, npz, ut, vt, Atm%u, Atm%v, Atm%gridstruct, Atm%domain, Atm%bd )
+
+ if (is_master()) write(*,*) 'done remap_winds'
+
+ end subroutine remap_winds
+
+
+ subroutine remap_xyz( im, jbeg, jend, jm, km, npz, nq, ncnst, lon, lat, ak0, bk0, ps0, gz0, &
+ ua, va, ta, qa, Atm )
+
+ type(fv_atmos_type), intent(inout), target :: Atm
+ integer, intent(in):: im, jm, km, npz, nq, ncnst
+ integer, intent(in):: jbeg, jend
+ real, intent(in):: lon(im), lat(jm), ak0(km+1), bk0(km+1)
+ real, intent(in):: gz0(im,jbeg:jend), ps0(im,jbeg:jend)
+ real, intent(in), dimension(im,jbeg:jend,km):: ua, va, ta
+ real, intent(in), dimension(im,jbeg:jend,km,ncnst):: qa
+
+ real, pointer, dimension(:,:,:) :: agrid
+
+! local:
+ real, dimension(Atm%bd%isd:Atm%bd%ied,Atm%bd%jsd:Atm%bd%jed,npz):: ut, vt ! winds
+ real, dimension(Atm%bd%is:Atm%bd%ie,km):: up, vp, tp
+ real, dimension(Atm%bd%is:Atm%bd%ie,km+1):: pe0, pn0
+ real pt0(km), gz(km+1), pk0(km+1)
+ real qp(Atm%bd%is:Atm%bd%ie,km,ncnst)
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz):: qn1
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz+1):: pe1, pn1
+ real :: rdlon(im)
+ real :: rdlat(jm)
+ real:: a1, b1, c1, c2, c3, c4
+ real:: gzc, psc, pst
+#ifdef MULTI_GASES
+ real:: kappax, pkx
+#endif
+ integer i,j,k, i1, i2, jc, i0, j0, iq
+! integer sphum, liq_wat, ice_wat, cld_amt
+ integer sphum
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+
+ is = Atm%bd%is
+ ie = Atm%bd%ie
+ js = Atm%bd%js
+ je = Atm%bd%je
+ isd = Atm%bd%isd
+ ied = Atm%bd%ied
+ jsd = Atm%bd%jsd
+ jed = Atm%bd%jed
+
+ !!NOTE: Only Atm is used in this routine.
+ agrid => Atm%gridstruct%agrid
+
+ sphum = get_tracer_index(MODEL_ATMOS, 'sphum')
+
+ if ( sphum/=1 ) then
+ call mpp_error(FATAL,'SPHUM must be 1st tracer')
+ endif
+
+ pk0(1) = ak0(1)**kappa
+
+ do i=1,im-1
+ rdlon(i) = 1. / (lon(i+1) - lon(i))
+ enddo
+ rdlon(im) = 1. / (lon(1) + 2.*pi - lon(im))
+
+ do j=1,jm-1
+ rdlat(j) = 1. / (lat(j+1) - lat(j))
+ enddo
+
+! * Interpolate to cubed sphere cell center
+ do 5000 j=js,je
+
+ do i=is,ie
+ pe0(i,1) = ak0(1)
+ pn0(i,1) = log(ak0(1))
+ enddo
+
+
+ do i=is,ie
+
+ if ( agrid(i,j,1)>lon(im) ) then
+ i1 = im; i2 = 1
+ a1 = (agrid(i,j,1)-lon(im)) * rdlon(im)
+ elseif ( agrid(i,j,1)=lon(i0) .and. agrid(i,j,1)<=lon(i0+1) ) then
+ i1 = i0; i2 = i0+1
+ a1 = (agrid(i,j,1)-lon(i1)) * rdlon(i0)
+ go to 111
+ endif
+ enddo
+ endif
+
+111 continue
+
+ if ( agrid(i,j,2)lat(jm) ) then
+ jc = jm-1
+ b1 = 1.
+ else
+ do j0=1,jm-1
+ if ( agrid(i,j,2)>=lat(j0) .and. agrid(i,j,2)<=lat(j0+1) ) then
+ jc = j0
+ b1 = (agrid(i,j,2)-lat(jc)) * rdlat(jc)
+ go to 222
+ endif
+ enddo
+ endif
+222 continue
+
+#ifndef DEBUG_REMAP
+ if ( a1<0.0 .or. a1>1.0 .or. b1<0.0 .or. b1>1.0 ) then
+ write(*,*) i,j,a1, b1
+ endif
+#endif
+ c1 = (1.-a1) * (1.-b1)
+ c2 = a1 * (1.-b1)
+ c3 = a1 * b1
+ c4 = (1.-a1) * b1
+
+! Interpolated surface pressure
+ psc = c1*ps0(i1,jc ) + c2*ps0(i2,jc ) + &
+ c3*ps0(i2,jc+1) + c4*ps0(i1,jc+1)
+
+! Interpolated surface geopotential
+ gzc = c1*gz0(i1,jc ) + c2*gz0(i2,jc ) + &
+ c3*gz0(i2,jc+1) + c4*gz0(i1,jc+1)
+
+! 3D fields:
+ do iq=1,ncnst
+! if ( iq==sphum .or. iq==liq_wat .or. iq==ice_wat .or. iq==cld_amt ) then
+ do k=1,km
+ qp(i,k,iq) = c1*qa(i1,jc, k,iq) + c2*qa(i2,jc, k,iq) + &
+ c3*qa(i2,jc+1,k,iq) + c4*qa(i1,jc+1,k,iq)
+ enddo
+! endif
+ enddo
+
+ do k=1,km
+ up(i,k) = c1*ua(i1,jc, k) + c2*ua(i2,jc, k) + &
+ c3*ua(i2,jc+1,k) + c4*ua(i1,jc+1,k)
+ vp(i,k) = c1*va(i1,jc, k) + c2*va(i2,jc, k) + &
+ c3*va(i2,jc+1,k) + c4*va(i1,jc+1,k)
+ tp(i,k) = c1*ta(i1,jc, k) + c2*ta(i2,jc, k) + &
+ c3*ta(i2,jc+1,k) + c4*ta(i1,jc+1,k)
+! Virtual effect:
+#ifdef MULTI_GASES
+ tp(i,k) = tp(i,k)*virq(qp(i,k,:))
+#else
+ tp(i,k) = tp(i,k)*(1.+zvir*qp(i,k,sphum))
+#endif
+ enddo
+! Tracers:
+
+ do k=2,km+1
+ pe0(i,k) = ak0(k) + bk0(k)*psc
+ pn0(i,k) = log(pe0(i,k))
+ pk0(k) = pe0(i,k)**kappa
+ enddo
+
+#ifdef USE_DATA_ZS
+ Atm% ps(i,j) = psc
+ Atm%phis(i,j) = gzc
+#else
+
+! * Adjust interpolated ps to model terrain
+ gz(km+1) = gzc
+ do k=km,1,-1
+ gz(k) = gz(k+1) + rdgas*tp(i,k)*(pn0(i,k+1)-pn0(i,k))
+ enddo
+! Only lowest layer potential temp is needed
+#ifdef MULTI_GASES
+ kappax = virqd(qp(i,km,:))/vicpqd(qp(i,km,:))
+ pkx = (pk0(km+1)-pk0(km))*(kappa*(pn0(i,km+1)-pn0(i,km)))
+ pkx = exp( kappax*log(pkx) )
+ pt0(km) = tp(i,km)/pkx
+#else
+ pt0(km) = tp(i,km)/(pk0(km+1)-pk0(km))*(kappa*(pn0(i,km+1)-pn0(i,km)))
+#endif
+ if( Atm%phis(i,j)>gzc ) then
+ do k=km,1,-1
+ if( Atm%phis(i,j) < gz(k) .and. &
+ Atm%phis(i,j) >= gz(k+1) ) then
+ pst = pk0(k) + (pk0(k+1)-pk0(k))*(gz(k)-Atm%phis(i,j))/(gz(k)-gz(k+1))
+ go to 123
+ endif
+ enddo
+ else
+! Extrapolation into the ground
+#ifdef MULTI_GASES
+ pst = pk0(km+1) + (gzc-Atm%phis(i,j))/(cp_air*pt0(km)*pkx)
+#else
+ pst = pk0(km+1) + (gzc-Atm%phis(i,j))/(cp_air*pt0(km))
+#endif
+ endif
+
+#ifdef MULTI_GASES
+123 Atm%ps(i,j) = pst**(1./(kappa*kappax))
+#else
+123 Atm%ps(i,j) = pst**(1./kappa)
+#endif
+#endif
+ enddo !i-loop
+
+
+! * Compute delp from ps
+ do i=is,ie
+ pe1(i,1) = Atm%ak(1)
+ pn1(i,1) = log(pe1(i,1))
+ enddo
+ do k=2,npz+1
+ do i=is,ie
+ pe1(i,k) = Atm%ak(k) + Atm%bk(k)*Atm%ps(i,j)
+ pn1(i,k) = log(pe1(i,k))
+ enddo
+ enddo
+
+ do k=1,npz
+ do i=is,ie
+ Atm%delp(i,j,k) = pe1(i,k+1) - pe1(i,k)
+ enddo
+ enddo
+
+! Use kord=9 for winds; kord=11 for tracers
+!------
+! map u
+!------
+ call mappm(km, pe0, up, npz, pe1, qn1, is,ie, -1, 9, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+ ut(i,j,k) = qn1(i,k)
+ enddo
+ enddo
+!------
+! map v
+!------
+ call mappm(km, pe0, vp, npz, pe1, qn1, is,ie, -1, 9, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+ vt(i,j,k) = qn1(i,k)
+ enddo
+ enddo
+
+!---------------
+! map tracers
+!----------------
+ do iq=1,ncnst
+! Note: AM2 physics tracers only
+! if ( iq==sphum .or. iq==liq_wat .or. iq==ice_wat .or. iq==cld_amt ) then
+ call mappm(km, pe0, qp(is,1,iq), npz, pe1, qn1, is,ie, 0, 11, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+ Atm%q(i,j,k,iq) = qn1(i,k)
+ enddo
+ enddo
+! endif
+ enddo
+
+!-------------------------------------------------------------
+! map virtual temperature using geopotential conserving scheme.
+!-------------------------------------------------------------
+ call mappm(km, pn0, tp, npz, pn1, qn1, is,ie, 1, 9, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+#ifdef MULTI_GASES
+ Atm%pt(i,j,k) = qn1(i,k)/virq(Atm%q(i,j,k,:))
+#else
+ Atm%pt(i,j,k) = qn1(i,k)/(1.+zvir*Atm%q(i,j,k,sphum))
+#endif
+ enddo
+ enddo
+
+5000 continue
+
+ call prt_maxmin('PS_model', Atm%ps, is, ie, js, je, ng, 1, 0.01)
+ call prt_maxmin('UT', ut, is, ie, js, je, ng, npz, 1.)
+ call prt_maxmin('VT', vt, is, ie, js, je, ng, npz, 1.)
+
+!----------------------------------------------
+! winds: lat-lon ON A to Cubed-D transformation:
+!----------------------------------------------
+ call cubed_a2d(Atm%npx, Atm%npy, npz, ut, vt, Atm%u, Atm%v, Atm%gridstruct, Atm%domain, Atm%bd )
+
+ if (is_master()) write(*,*) 'done remap_xyz'
+
+ end subroutine remap_xyz
+
+!>@brief The subroutine 'cubed_a2d' transforms the wind from the A Grid to the D Grid.
+ subroutine cubed_a2d( npx, npy, npz, ua, va, u, v, gridstruct, fv_domain, bd )
+ use mpp_domains_mod, only: mpp_update_domains
+
+ type(fv_grid_bounds_type), intent(IN) :: bd
+ integer, intent(in):: npx, npy, npz
+ real, intent(inout), dimension(bd%isd:bd%ied,bd%jsd:bd%jed,npz):: ua, va
+ real, intent(out):: u(bd%isd:bd%ied, bd%jsd:bd%jed+1,npz)
+ real, intent(out):: v(bd%isd:bd%ied+1,bd%jsd:bd%jed ,npz)
+ type(fv_grid_type), intent(IN), target :: gridstruct
+ type(domain2d), intent(INOUT) :: fv_domain
+! local:
+ real v3(3,bd%is-1:bd%ie+1,bd%js-1:bd%je+1)
+ real ue(3,bd%is-1:bd%ie+1,bd%js:bd%je+1) !< 3D winds at edges
+ real ve(3,bd%is:bd%ie+1,bd%js-1:bd%je+1) !< 3D winds at edges
+ real, dimension(bd%is:bd%ie):: ut1, ut2, ut3
+ real, dimension(bd%js:bd%je):: vt1, vt2, vt3
+ integer i, j, k, im2, jm2
+
+ real(kind=R_GRID), pointer, dimension(:,:,:) :: vlon, vlat
+ real(kind=R_GRID), pointer, dimension(:) :: edge_vect_w, edge_vect_e, edge_vect_s, edge_vect_n
+ real(kind=R_GRID), pointer, dimension(:,:,:,:) :: ew, es
+
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+
+ is = bd%is
+ ie = bd%ie
+ js = bd%js
+ je = bd%je
+ isd = bd%isd
+ ied = bd%ied
+ jsd = bd%jsd
+ jed = bd%jed
+
+ vlon => gridstruct%vlon
+ vlat => gridstruct%vlat
+
+ edge_vect_w => gridstruct%edge_vect_w
+ edge_vect_e => gridstruct%edge_vect_e
+ edge_vect_s => gridstruct%edge_vect_s
+ edge_vect_n => gridstruct%edge_vect_n
+
+ ew => gridstruct%ew
+ es => gridstruct%es
+
+ call mpp_update_domains(ua, fv_domain, complete=.false.)
+ call mpp_update_domains(va, fv_domain, complete=.true.)
+
+ im2 = (npx-1)/2
+ jm2 = (npy-1)/2
+
+ do k=1, npz
+! Compute 3D wind on A grid
+ do j=js-1,je+1
+ do i=is-1,ie+1
+ v3(1,i,j) = ua(i,j,k)*vlon(i,j,1) + va(i,j,k)*vlat(i,j,1)
+ v3(2,i,j) = ua(i,j,k)*vlon(i,j,2) + va(i,j,k)*vlat(i,j,2)
+ v3(3,i,j) = ua(i,j,k)*vlon(i,j,3) + va(i,j,k)*vlat(i,j,3)
+ enddo
+ enddo
+
+! A --> D
+! Interpolate to cell edges
+ do j=js,je+1
+ do i=is-1,ie+1
+ ue(1,i,j) = 0.5*(v3(1,i,j-1) + v3(1,i,j))
+ ue(2,i,j) = 0.5*(v3(2,i,j-1) + v3(2,i,j))
+ ue(3,i,j) = 0.5*(v3(3,i,j-1) + v3(3,i,j))
+ enddo
+ enddo
+
+ do j=js-1,je+1
+ do i=is,ie+1
+ ve(1,i,j) = 0.5*(v3(1,i-1,j) + v3(1,i,j))
+ ve(2,i,j) = 0.5*(v3(2,i-1,j) + v3(2,i,j))
+ ve(3,i,j) = 0.5*(v3(3,i-1,j) + v3(3,i,j))
+ enddo
+ enddo
+
+! --- E_W edges (for v-wind):
+ if (.not. gridstruct%nested) then
+ if ( is==1) then
+ i = 1
+ do j=js,je
+ if ( j>jm2 ) then
+ vt1(j) = edge_vect_w(j)*ve(1,i,j-1)+(1.-edge_vect_w(j))*ve(1,i,j)
+ vt2(j) = edge_vect_w(j)*ve(2,i,j-1)+(1.-edge_vect_w(j))*ve(2,i,j)
+ vt3(j) = edge_vect_w(j)*ve(3,i,j-1)+(1.-edge_vect_w(j))*ve(3,i,j)
+ else
+ vt1(j) = edge_vect_w(j)*ve(1,i,j+1)+(1.-edge_vect_w(j))*ve(1,i,j)
+ vt2(j) = edge_vect_w(j)*ve(2,i,j+1)+(1.-edge_vect_w(j))*ve(2,i,j)
+ vt3(j) = edge_vect_w(j)*ve(3,i,j+1)+(1.-edge_vect_w(j))*ve(3,i,j)
+ endif
+ enddo
+ do j=js,je
+ ve(1,i,j) = vt1(j)
+ ve(2,i,j) = vt2(j)
+ ve(3,i,j) = vt3(j)
+ enddo
+ endif
+
+ if ( (ie+1)==npx ) then
+ i = npx
+ do j=js,je
+ if ( j>jm2 ) then
+ vt1(j) = edge_vect_e(j)*ve(1,i,j-1)+(1.-edge_vect_e(j))*ve(1,i,j)
+ vt2(j) = edge_vect_e(j)*ve(2,i,j-1)+(1.-edge_vect_e(j))*ve(2,i,j)
+ vt3(j) = edge_vect_e(j)*ve(3,i,j-1)+(1.-edge_vect_e(j))*ve(3,i,j)
+ else
+ vt1(j) = edge_vect_e(j)*ve(1,i,j+1)+(1.-edge_vect_e(j))*ve(1,i,j)
+ vt2(j) = edge_vect_e(j)*ve(2,i,j+1)+(1.-edge_vect_e(j))*ve(2,i,j)
+ vt3(j) = edge_vect_e(j)*ve(3,i,j+1)+(1.-edge_vect_e(j))*ve(3,i,j)
+ endif
+ enddo
+ do j=js,je
+ ve(1,i,j) = vt1(j)
+ ve(2,i,j) = vt2(j)
+ ve(3,i,j) = vt3(j)
+ enddo
+ endif
+
+! N-S edges (for u-wind):
+ if ( js==1 ) then
+ j = 1
+ do i=is,ie
+ if ( i>im2 ) then
+ ut1(i) = edge_vect_s(i)*ue(1,i-1,j)+(1.-edge_vect_s(i))*ue(1,i,j)
+ ut2(i) = edge_vect_s(i)*ue(2,i-1,j)+(1.-edge_vect_s(i))*ue(2,i,j)
+ ut3(i) = edge_vect_s(i)*ue(3,i-1,j)+(1.-edge_vect_s(i))*ue(3,i,j)
+ else
+ ut1(i) = edge_vect_s(i)*ue(1,i+1,j)+(1.-edge_vect_s(i))*ue(1,i,j)
+ ut2(i) = edge_vect_s(i)*ue(2,i+1,j)+(1.-edge_vect_s(i))*ue(2,i,j)
+ ut3(i) = edge_vect_s(i)*ue(3,i+1,j)+(1.-edge_vect_s(i))*ue(3,i,j)
+ endif
+ enddo
+ do i=is,ie
+ ue(1,i,j) = ut1(i)
+ ue(2,i,j) = ut2(i)
+ ue(3,i,j) = ut3(i)
+ enddo
+ endif
+
+ if ( (je+1)==npy ) then
+ j = npy
+ do i=is,ie
+ if ( i>im2 ) then
+ ut1(i) = edge_vect_n(i)*ue(1,i-1,j)+(1.-edge_vect_n(i))*ue(1,i,j)
+ ut2(i) = edge_vect_n(i)*ue(2,i-1,j)+(1.-edge_vect_n(i))*ue(2,i,j)
+ ut3(i) = edge_vect_n(i)*ue(3,i-1,j)+(1.-edge_vect_n(i))*ue(3,i,j)
+ else
+ ut1(i) = edge_vect_n(i)*ue(1,i+1,j)+(1.-edge_vect_n(i))*ue(1,i,j)
+ ut2(i) = edge_vect_n(i)*ue(2,i+1,j)+(1.-edge_vect_n(i))*ue(2,i,j)
+ ut3(i) = edge_vect_n(i)*ue(3,i+1,j)+(1.-edge_vect_n(i))*ue(3,i,j)
+ endif
+ enddo
+ do i=is,ie
+ ue(1,i,j) = ut1(i)
+ ue(2,i,j) = ut2(i)
+ ue(3,i,j) = ut3(i)
+ enddo
+ endif
+
+ endif ! .not. nested
+
+ do j=js,je+1
+ do i=is,ie
+ u(i,j,k) = ue(1,i,j)*es(1,i,j,1) + &
+ ue(2,i,j)*es(2,i,j,1) + &
+ ue(3,i,j)*es(3,i,j,1)
+ enddo
+ enddo
+ do j=js,je
+ do i=is,ie+1
+ v(i,j,k) = ve(1,i,j)*ew(1,i,j,2) + &
+ ve(2,i,j)*ew(2,i,j,2) + &
+ ve(3,i,j)*ew(3,i,j,2)
+ enddo
+ enddo
+
+ enddo ! k-loop
+
+ end subroutine cubed_a2d
+
+
+ subroutine d2a3d(u, v, ua, va, im, jm, km, lon)
+ integer, intent(in):: im, jm, km ! Dimensions
+ real, intent(in ) :: lon(im)
+ real, intent(in ), dimension(im,jm,km):: u, v
+ real, intent(out), dimension(im,jm,km):: ua, va
+! local
+ real :: coslon(im),sinlon(im) ! Sine and cosine in longitude
+ integer i, j, k
+ integer imh
+ real un, vn, us, vs
+
+ integer :: ks, ke
+
+ imh = im/2
+
+ do i=1,im
+ sinlon(i) = sin(lon(i))
+ coslon(i) = cos(lon(i))
+ enddo
+
+ do k=1,km
+ do j=2,jm-1
+ do i=1,im
+ ua(i,j,k) = 0.5*(u(i,j,k) + u(i,j+1,k))
+ enddo
+ enddo
+
+ do j=2,jm-1
+ do i=1,im-1
+ va(i,j,k) = 0.5*(v(i,j,k) + v(i+1,j,k))
+ enddo
+ va(im,j,k) = 0.5*(v(im,j,k) + v(1,j,k))
+ enddo
+
+! Projection at SP
+ us = 0.
+ vs = 0.
+ do i=1,imh
+ us = us + (ua(i+imh,2,k)-ua(i,2,k))*sinlon(i) &
+ + (va(i,2,k)-va(i+imh,2,k))*coslon(i)
+ vs = vs + (ua(i+imh,2,k)-ua(i,2,k))*coslon(i) &
+ + (va(i+imh,2,k)-va(i,2,k))*sinlon(i)
+ enddo
+ us = us/im
+ vs = vs/im
+ do i=1,imh
+ ua(i,1,k) = -us*sinlon(i) - vs*coslon(i)
+ va(i,1,k) = us*coslon(i) - vs*sinlon(i)
+ ua(i+imh,1,k) = -ua(i,1,k)
+ va(i+imh,1,k) = -va(i,1,k)
+ enddo
+
+! Projection at NP
+ un = 0.
+ vn = 0.
+ do i=1,imh
+ un = un + (ua(i+imh,jm-1,k)-ua(i,jm-1,k))*sinlon(i) &
+ + (va(i+imh,jm-1,k)-va(i,jm-1,k))*coslon(i)
+ vn = vn + (ua(i,jm-1,k)-ua(i+imh,jm-1,k))*coslon(i) &
+ + (va(i+imh,jm-1,k)-va(i,jm-1,k))*sinlon(i)
+ enddo
+
+ un = un/im
+ vn = vn/im
+ do i=1,imh
+ ua(i,jm,k) = -un*sinlon(i) + vn*coslon(i)
+ va(i,jm,k) = -un*coslon(i) - vn*sinlon(i)
+ ua(i+imh,jm,k) = -ua(i,jm,k)
+ va(i+imh,jm,k) = -va(i,jm,k)
+ enddo
+ enddo
+
+ end subroutine d2a3d
+
+
+ subroutine pmaxmin( qname, a, im, jm, fac )
+
+ integer, intent(in):: im, jm
+ character(len=*) :: qname
+ integer i, j
+ real a(im,jm)
+
+ real qmin(jm), qmax(jm)
+ real pmax, pmin
+ real fac ! multiplication factor
+
+ do j=1,jm
+ pmax = a(1,j)
+ pmin = a(1,j)
+ do i=2,im
+ pmax = max(pmax, a(i,j))
+ pmin = min(pmin, a(i,j))
+ enddo
+ qmax(j) = pmax
+ qmin(j) = pmin
+ enddo
+!
+! Now find max/min of amax/amin
+!
+ pmax = qmax(1)
+ pmin = qmin(1)
+ do j=2,jm
+ pmax = max(pmax, qmax(j))
+ pmin = min(pmin, qmin(j))
+ enddo
+
+ write(*,*) qname, ' max = ', pmax*fac, ' min = ', pmin*fac
+
+ end subroutine pmaxmin
+
+subroutine pmaxmn(qname, q, is, ie, js, je, km, fac, area, domain)
+ character(len=*), intent(in):: qname
+ integer, intent(in):: is, ie, js, je
+ integer, intent(in):: km
+ real, intent(in):: q(is:ie, js:je, km)
+ real, intent(in):: fac
+ real(kind=R_GRID), intent(IN):: area(is-3:ie+3, js-3:je+3)
+ type(domain2d), intent(INOUT) :: domain
+!---local variables
+ real qmin, qmax, gmean
+ integer i,j,k
+
+ qmin = q(is,js,1)
+ qmax = qmin
+ gmean = 0.
+
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ if( q(i,j,k) < qmin ) then
+ qmin = q(i,j,k)
+ elseif( q(i,j,k) > qmax ) then
+ qmax = q(i,j,k)
+ endif
+ enddo
+ enddo
+ enddo
+
+ call mp_reduce_min(qmin)
+ call mp_reduce_max(qmax)
+
+ gmean = g_sum(domain, q(is,js,km), is, ie, js, je, 3, area, 1, reproduce=.true.)
+ if(is_master()) write(6,*) qname, qmax*fac, qmin*fac, gmean*fac
+
+ end subroutine pmaxmn
+
+ subroutine p_maxmin(qname, q, is, ie, js, je, km, fac)
+ character(len=*), intent(in):: qname
+ integer, intent(in):: is, ie, js, je, km
+ real, intent(in):: q(is:ie, js:je, km)
+ real, intent(in):: fac
+ real qmin, qmax
+ integer i,j,k
+
+ qmin = q(is,js,1)
+ qmax = qmin
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ if( q(i,j,k) < qmin ) then
+ qmin = q(i,j,k)
+ elseif( q(i,j,k) > qmax ) then
+ qmax = q(i,j,k)
+ endif
+ enddo
+ enddo
+ enddo
+ call mp_reduce_min(qmin)
+ call mp_reduce_max(qmax)
+ if(is_master()) write(6,*) qname, qmax*fac, qmin*fac
+
+ end subroutine p_maxmin
+
+ subroutine fillq(im, km, nq, q, dp)
+ integer, intent(in):: im !< No. of longitudes
+ integer, intent(in):: km !< No. of levels
+ integer, intent(in):: nq !< Total number of tracers
+ real , intent(in):: dp(im,km) !< pressure thickness
+ real , intent(inout) :: q(im,km,nq) !< tracer mixing ratio
+! !LOCAL VARIABLES:
+ integer i, k, ic, k1
+
+ do ic=1,nq
+! Bottom up:
+ do k=km,2,-1
+ k1 = k-1
+ do i=1,im
+ if( q(i,k,ic) < 0. ) then
+ q(i,k1,ic) = q(i,k1,ic) + q(i,k,ic)*dp(i,k)/dp(i,k1)
+ q(i,k ,ic) = 0.
+ endif
+ enddo
+ enddo
+! Top down:
+ do k=1,km-1
+ k1 = k+1
+ do i=1,im
+ if( q(i,k,ic) < 0. ) then
+ q(i,k1,ic) = q(i,k1,ic) + q(i,k,ic)*dp(i,k)/dp(i,k1)
+ q(i,k ,ic) = 0.
+ endif
+ enddo
+ enddo
+
+ enddo
+
+ end subroutine fillq
+
+ subroutine compute_zh(im, jm, levp, ak0, bk0, ps, zs, t, q, nq, zh )
+ implicit none
+ integer, intent(in):: levp, im,jm, nq
+ real, intent(in), dimension(levp+1):: ak0, bk0
+ real(kind=4), intent(in), dimension(im,jm):: ps, zs
+ real(kind=4), intent(in), dimension(im,jm,levp):: t
+ real(kind=4), intent(in), dimension(im,jm,levp,nq):: q
+ real(kind=4), intent(out), dimension(im,jm,levp+1):: zh
+ ! Local:
+ real, dimension(im,levp+1):: pe0, pn0
+! real:: qc
+ integer:: i,j,k
+
+!$OMP parallel do default(none) shared(im,jm,levp,ak0,bk0,zs,ps,t,q,zh) &
+!$OMP private(pe0,pn0)
+ do j = 1, jm
+
+ do i=1, im
+ pe0(i,1) = ak0(1)
+ pn0(i,1) = log(pe0(i,1))
+ zh(i,j,levp+1) = zs(i,j)
+ enddo
+
+ do k=2,levp+1
+ do i=1,im
+ pe0(i,k) = ak0(k) + bk0(k)*ps(i,j)
+ pn0(i,k) = log(pe0(i,k))
+ enddo
+ enddo
+
+ do k = levp, 1, -1
+ do i = 1, im
+! qc = 1.-(q(i,j,k,2)+q(i,j,k,3)+q(i,j,k,4)+q(i,j,k,5))
+ zh(i,j,k) = zh(i,j,k+1)+(t(i,j,k)*(1.+zvir*q(i,j,k,1))*(pn0(i,k+1)-pn0(i,k)))*(rdgas/grav)
+ enddo
+ enddo
+ enddo
+
+ !if(is_master()) call pmaxmin( 'zh levp+1', zh(:,:,levp+1), im, jm, 1.)
+
+ end subroutine compute_zh
+
+ subroutine get_staggered_grid( is, ie, js, je, isd, ied, jsd, jed, pt_b, pt_c, pt_d)
+ integer, intent(in):: is, ie, js, je, isd, ied, jsd, jed
+ real, dimension(isd:ied+1,jsd:jed+1,2), intent(in) :: pt_b
+ real, dimension(isd:ied+1,jsd:jed ,2), intent(out) :: pt_c
+ real, dimension(isd:ied ,jsd:jed+1,2), intent(out) :: pt_d
+ ! local
+ real(kind=R_GRID), dimension(2):: p1, p2, p3
+ integer :: i, j
+
+ do j=js,je+1
+ do i=is,ie
+ p1(:) = pt_b(i, j,1:2)
+ p2(:) = pt_b(i+1,j,1:2)
+ call mid_pt_sphere(p1, p2, p3)
+ pt_d(i,j,1:2) = p3(:)
+ enddo
+ enddo
+
+ do j=js,je
+ do i=is,ie+1
+ p1(:) = pt_b(i,j ,1:2)
+ p2(:) = pt_b(i,j+1,1:2)
+ call mid_pt_sphere(p1, p2, p3)
+ pt_c(i,j,1:2) = p3(:)
+ enddo
+ enddo
+
+ end subroutine get_staggered_grid
+
+ end module external_ic_mod
+
diff --git a/tools/external_ic.F90_NAM_lyrs b/tools/external_ic.F90_NAM_lyrs
new file mode 100644
index 000000000..c0d416921
--- /dev/null
+++ b/tools/external_ic.F90_NAM_lyrs
@@ -0,0 +1,4279 @@
+
+!***********************************************************************
+!* GNU Lesser General Public License
+!*
+!* This file is part of the FV3 dynamical core.
+!*
+!* The FV3 dynamical core is free software: you can redistribute it
+!* and/or modify it under the terms of the
+!* GNU Lesser General Public License as published by the
+!* Free Software Foundation, either version 3 of the License, or
+!* (at your option) any later version.
+!*
+!* The FV3 dynamical core is distributed in the hope that it will be
+!* useful, but WITHOUT ANYWARRANTY; without even the implied warranty
+!* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+!* See the GNU General Public License for more details.
+!*
+!* You should have received a copy of the GNU Lesser General Public
+!* License along with the FV3 dynamical core.
+!* If not, see .
+!***********************************************************************
+
+#ifdef OVERLOAD_R4
+#define _GET_VAR1 get_var1_real
+#else
+#define _GET_VAR1 get_var1_double
+#endif
+
+!>@brief The module 'external_ic_mod' contains routines that read in and
+!! remap initial conditions.
+
+module external_ic_mod
+
+!
+!
+! | Module Name |
+! Functions Included |
+!
+!
+! | constants_mod |
+! pi=>pi_8, omega, grav, kappa, rdgas, rvgas, cp_air |
+!
+!
+! | external_sst_mod |
+! i_sst, j_sst, sst_ncep |
+!
+!
+! | field_manager_mod |
+! MODEL_ATMOS |
+!
+!
+! | fms_mod |
+! file_exist, read_data, field_exist, write_version_number,
+! open_namelist_file, check_nml_error, close_file,
+! get_mosaic_tile_file, read_data, error_mesg |
+!
+!
+! | fms_io_mod |
+! get_tile_string, field_size, free_restart_type,
+! restart_file_type, register_restart_field,
+! save_restart, restore_state |
+!
+!
+! | fv_arrays_mod |
+! fv_atmos_type, fv_grid_type, fv_grid_bounds_type, R_GRID |
+!
+!
+! | fv_control_mod |
+! fv_init, fv_end, ngrids |
+!
+!
+! | fv_diagnostics_mod |
+! prt_maxmin, prt_gb_nh_sh, prt_height |
+!
+!
+! | fv_eta_mod |
+! set_eta, set_external_eta |
+!
+!
+! | fv_fill_mod |
+! fillz |
+!
+!
+! | fv_grid_utils_mod |
+! ptop_min, g_sum,mid_pt_sphere,get_unit_vect2,
+! get_latlon_vector,inner_prod |
+!
+!
+! | fv_io_mod |
+! fv_io_read_tracers |
+!
+!
+! | fv_mp_mod |
+! ng, is_master, fill_corners, YDir, mp_reduce_min, mp_reduce_max |
+!
+!
+! | fv_mapz_mod |
+! mappm |
+!
+!
+! | fv_nwp_nudge_mod |
+! T_is_Tv |
+!
+!
+! | fv_surf_map_mod |
+! surfdrv, FV3_zs_filter,sgh_g, oro_g,del2_cubed_sphere, del4_cubed_sphere |
+!
+!
+! | fv_timing_mod |
+! timing_on, timing_off |
+!
+!
+! | fv_update_phys_mod |
+! fv_update_phys |
+!
+!
+! | init_hydro_mod |
+! p_var |
+!
+!
+! | mpp_mod |
+! mpp_error, FATAL, NOTE, mpp_pe, mpp_root_pe,stdlog, input_nml_file |
+!
+!
+! | mpp_domains_mod |
+! mpp_get_tile_id, domain2d, mpp_update_domains, NORTH, EAST |
+!
+!
+! | mpp_parameter_mod |
+! AGRID_PARAM=>AGRID |
+!
+!
+! | sim_nc_mod |
+! open_ncfile, close_ncfile, get_ncdim1, get_var1_double, get_var2_real,
+! get_var3_r4, get_var2_r4, get_var1_real, get_var_att_double |
+!
+!
+! | tracer_manager_mod |
+! get_tracer_names, get_number_tracers, get_tracer_index, set_tracer_profile |
+!
+!
+! | test_cases_mod |
+! checker_tracers |
+!
+!
+
+ use netcdf
+ use external_sst_mod, only: i_sst, j_sst, sst_ncep
+ use fms_mod, only: file_exist, read_data, field_exist, write_version_number
+ use fms_mod, only: open_namelist_file, check_nml_error, close_file
+ use fms_mod, only: get_mosaic_tile_file, read_data, error_mesg
+ use fms_io_mod, only: get_tile_string, field_size, free_restart_type
+ use fms_io_mod, only: restart_file_type, register_restart_field
+ use fms_io_mod, only: save_restart, restore_state
+ use mpp_mod, only: mpp_error, FATAL, NOTE, mpp_pe, mpp_root_pe
+ use mpp_mod, only: stdlog, input_nml_file
+ use mpp_parameter_mod, only: AGRID_PARAM=>AGRID
+ use mpp_domains_mod, only: mpp_get_tile_id, domain2d, mpp_update_domains, NORTH, EAST
+ use tracer_manager_mod, only: get_tracer_names, get_number_tracers, get_tracer_index
+ use tracer_manager_mod, only: set_tracer_profile
+ use field_manager_mod, only: MODEL_ATMOS
+
+ use constants_mod, only: pi=>pi_8, omega, grav, kappa, rdgas, rvgas, cp_air
+ use fv_arrays_mod, only: fv_atmos_type, fv_grid_type, fv_grid_bounds_type, R_GRID
+ use fv_diagnostics_mod,only: prt_maxmin, prt_gb_nh_sh, prt_height
+ use fv_grid_utils_mod, only: ptop_min, g_sum,mid_pt_sphere,get_unit_vect2,get_latlon_vector,inner_prod
+ use fv_io_mod, only: fv_io_read_tracers
+ use fv_mapz_mod, only: mappm
+
+ use fv_regional_mod, only: dump_field, H_STAGGER, U_STAGGER, V_STAGGER, get_data_source
+ use fv_mp_mod, only: ng, is_master, fill_corners, YDir, mp_reduce_min, mp_reduce_max
+ use fv_regional_mod, only: start_regional_cold_start
+ use fv_surf_map_mod, only: surfdrv, FV3_zs_filter
+ use fv_surf_map_mod, only: sgh_g, oro_g
+ use fv_surf_map_mod, only: del2_cubed_sphere, del4_cubed_sphere
+ use fv_timing_mod, only: timing_on, timing_off
+ use init_hydro_mod, only: p_var
+ use fv_fill_mod, only: fillz
+ use fv_eta_mod, only: set_eta, set_external_eta
+ use sim_nc_mod, only: open_ncfile, close_ncfile, get_ncdim1, get_var1_double, get_var2_real, &
+ get_var3_r4, get_var2_r4, get_var1_real, get_var_att_double
+ use fv_nwp_nudge_mod, only: T_is_Tv
+ use test_cases_mod, only: checker_tracers
+
+! The "T" field in NCEP analysis is actually virtual temperature (Larry H. post processing)
+! BEFORE 20051201
+
+ use boundary_mod, only: nested_grid_BC, extrapolation_BC
+ use mpp_domains_mod, only: mpp_get_data_domain, mpp_get_global_domain, mpp_get_compute_domain
+
+#ifdef MULTI_GASES
+ use multi_gases_mod, only: virq, virqd, vicpqd
+#endif
+
+ implicit none
+ private
+
+ real, parameter:: zvir = rvgas/rdgas - 1.
+ real(kind=R_GRID), parameter :: cnst_0p20=0.20d0
+ real :: deg2rad
+ character (len = 80) :: source ! This tells what the input source was for the data
+ public get_external_ic, get_cubed_sphere_terrain
+
+! version number of this module
+! Include variable "version" to be written to log file.
+#include
+
+contains
+
+ subroutine get_external_ic( Atm, fv_domain, cold_start, dt_atmos )
+
+ type(fv_atmos_type), intent(inout), target :: Atm(:)
+ type(domain2d), intent(inout) :: fv_domain
+ logical, intent(IN) :: cold_start
+ real, intent(IN) :: dt_atmos
+ real:: alpha = 0.
+ real rdg
+ integer i,j,k,nq
+
+ real, pointer, dimension(:,:,:) :: grid, agrid
+ real, pointer, dimension(:,:) :: fC, f0
+
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+ integer :: sphum, liq_wat, ice_wat, rainwat, snowwat, graupel
+#ifdef CCPP
+ integer :: liq_aero, ice_aero
+#endif
+#ifdef MULTI_GASES
+ integer :: spfo, spfo2, spfo3
+#else
+ integer :: o3mr
+#endif
+
+ is = Atm(1)%bd%is
+ ie = Atm(1)%bd%ie
+ js = Atm(1)%bd%js
+ je = Atm(1)%bd%je
+ isd = Atm(1)%bd%isd
+ ied = Atm(1)%bd%ied
+ jsd = Atm(1)%bd%jsd
+ jed = Atm(1)%bd%jed
+
+ grid => Atm(1)%gridstruct%grid
+ agrid => Atm(1)%gridstruct%agrid
+
+ fC => Atm(1)%gridstruct%fC
+ f0 => Atm(1)%gridstruct%f0
+
+! * Initialize coriolis param:
+
+ do j=jsd,jed+1
+ do i=isd,ied+1
+ fc(i,j) = 2.*omega*( -1.*cos(grid(i,j,1))*cos(grid(i,j,2))*sin(alpha) + &
+ sin(grid(i,j,2))*cos(alpha) )
+ enddo
+ enddo
+
+ do j=jsd,jed
+ do i=isd,ied
+ f0(i,j) = 2.*omega*( -1.*cos(agrid(i,j,1))*cos(agrid(i,j,2))*sin(alpha) + &
+ sin(agrid(i,j,2))*cos(alpha) )
+ enddo
+ enddo
+
+ call mpp_update_domains( f0, fv_domain )
+ if ( Atm(1)%gridstruct%cubed_sphere .and. (.not. (Atm(1)%neststruct%nested .or. Atm(1)%flagstruct%regional)))then
+ call fill_corners(f0, Atm(1)%npx, Atm(1)%npy, YDir)
+ endif
+
+! Read in cubed_sphere terrain
+ if ( Atm(1)%flagstruct%mountain ) then
+ call get_cubed_sphere_terrain(Atm, fv_domain)
+ else
+ if (.not. Atm(1)%neststruct%nested) Atm(1)%phis = 0.
+ endif
+
+! Read in the specified external dataset and do all the needed transformation
+ if ( Atm(1)%flagstruct%ncep_ic ) then
+ nq = 1
+ call timing_on('NCEP_IC')
+ call get_ncep_ic( Atm, fv_domain, nq )
+ call timing_off('NCEP_IC')
+#ifdef FV_TRACERS
+ if (.not. cold_start) then
+ call fv_io_read_tracers( fv_domain, Atm )
+ if(is_master()) write(*,*) 'All tracers except sphum replaced by FV IC'
+ endif
+#endif
+ elseif ( Atm(1)%flagstruct%nggps_ic ) then
+ call timing_on('NGGPS_IC')
+ call get_nggps_ic( Atm, fv_domain, dt_atmos )
+ call timing_off('NGGPS_IC')
+ elseif ( Atm(1)%flagstruct%ecmwf_ic ) then
+ if( is_master() ) write(*,*) 'Calling get_ecmwf_ic'
+ call timing_on('ECMWF_IC')
+ call get_ecmwf_ic( Atm, fv_domain )
+ call timing_off('ECMWF_IC')
+ else
+! The following is to read in legacy lat-lon FV core restart file
+! is Atm%q defined in all cases?
+ nq = size(Atm(1)%q,4)
+ call get_fv_ic( Atm, fv_domain, nq )
+ endif
+
+ call prt_maxmin('PS', Atm(1)%ps, is, ie, js, je, ng, 1, 0.01)
+ call prt_maxmin('T', Atm(1)%pt, is, ie, js, je, ng, Atm(1)%npz, 1.)
+ if (.not.Atm(1)%flagstruct%hydrostatic) call prt_maxmin('W', Atm(1)%w, is, ie, js, je, ng, Atm(1)%npz, 1.)
+ call prt_maxmin('SPHUM', Atm(1)%q(:,:,:,1), is, ie, js, je, ng, Atm(1)%npz, 1.)
+ if ( Atm(1)%flagstruct%nggps_ic ) then
+ call prt_maxmin('TS', Atm(1)%ts, is, ie, js, je, 0, 1, 1.)
+ endif
+ if ( Atm(1)%flagstruct%nggps_ic .or. Atm(1)%flagstruct%ecmwf_ic ) then
+ sphum = get_tracer_index(MODEL_ATMOS, 'sphum')
+ liq_wat = get_tracer_index(MODEL_ATMOS, 'liq_wat')
+ ice_wat = get_tracer_index(MODEL_ATMOS, 'ice_wat')
+ rainwat = get_tracer_index(MODEL_ATMOS, 'rainwat')
+ snowwat = get_tracer_index(MODEL_ATMOS, 'snowwat')
+ graupel = get_tracer_index(MODEL_ATMOS, 'graupel')
+#ifdef MULTI_GASES
+ spfo = get_tracer_index(MODEL_ATMOS, 'spfo')
+ spfo2 = get_tracer_index(MODEL_ATMOS, 'spfo2')
+ spfo3 = get_tracer_index(MODEL_ATMOS, 'spfo3')
+#else
+ o3mr = get_tracer_index(MODEL_ATMOS, 'o3mr')
+#endif
+#ifdef CCPP
+ liq_aero = get_tracer_index(MODEL_ATMOS, 'liq_aero')
+ ice_aero = get_tracer_index(MODEL_ATMOS, 'ice_aero')
+#endif
+
+ if ( liq_wat > 0 ) &
+ call prt_maxmin('liq_wat', Atm(1)%q(:,:,:,liq_wat), is, ie, js, je, ng, Atm(1)%npz, 1.)
+ if ( ice_wat > 0 ) &
+ call prt_maxmin('ice_wat', Atm(1)%q(:,:,:,ice_wat), is, ie, js, je, ng, Atm(1)%npz, 1.)
+ if ( rainwat > 0 ) &
+ call prt_maxmin('rainwat', Atm(1)%q(:,:,:,rainwat), is, ie, js, je, ng, Atm(1)%npz, 1.)
+ if ( snowwat > 0 ) &
+ call prt_maxmin('snowwat', Atm(1)%q(:,:,:,snowwat), is, ie, js, je, ng, Atm(1)%npz, 1.)
+ if ( graupel > 0 ) &
+ call prt_maxmin('graupel', Atm(1)%q(:,:,:,graupel), is, ie, js, je, ng, Atm(1)%npz, 1.)
+#ifdef MULTI_GASES
+ if ( spfo > 0 ) &
+ call prt_maxmin('SPFO', Atm(1)%q(:,:,:,spfo), is, ie, js, je, ng, Atm(1)%npz, 1.)
+ if ( spfo2 > 0 ) &
+ call prt_maxmin('SPFO2', Atm(1)%q(:,:,:,spfo2), is, ie, js, je, ng, Atm(1)%npz, 1.)
+ if ( spfo3 > 0 ) &
+ call prt_maxmin('SPFO3', Atm(1)%q(:,:,:,spfo3), is, ie, js, je, ng, Atm(1)%npz, 1.)
+#else
+ if ( o3mr > 0 ) &
+ call prt_maxmin('O3MR', Atm(1)%q(:,:,:,o3mr), is, ie, js, je, ng, Atm(1)%npz, 1.)
+#endif
+#ifdef CCPP
+ if ( liq_aero > 0) &
+ call prt_maxmin('liq_aero',Atm(1)%q(:,:,:,liq_aero),is, ie, js, je, ng, Atm(1)%npz, 1.)
+ if ( ice_aero > 0) &
+ call prt_maxmin('ice_aero',Atm(1)%q(:,:,:,ice_aero),is, ie, js, je, ng, Atm(1)%npz, 1.)
+#endif
+ endif
+
+ call p_var(Atm(1)%npz, is, ie, js, je, Atm(1)%ak(1), ptop_min, &
+ Atm(1)%delp, Atm(1)%delz, Atm(1)%pt, Atm(1)%ps, &
+ Atm(1)%pe, Atm(1)%peln, Atm(1)%pk, Atm(1)%pkz, &
+ kappa, Atm(1)%q, ng, Atm(1)%ncnst, Atm(1)%gridstruct%area_64, Atm(1)%flagstruct%dry_mass, &
+ Atm(1)%flagstruct%adjust_dry_mass, Atm(1)%flagstruct%mountain, Atm(1)%flagstruct%moist_phys, &
+ Atm(1)%flagstruct%hydrostatic, Atm(1)%flagstruct%nwat, Atm(1)%domain, Atm(1)%flagstruct%make_nh)
+
+ end subroutine get_external_ic
+
+
+!------------------------------------------------------------------
+ subroutine get_cubed_sphere_terrain( Atm, fv_domain )
+ type(fv_atmos_type), intent(inout), target :: Atm(:)
+ type(domain2d), intent(inout) :: fv_domain
+ integer :: ntileMe
+ integer, allocatable :: tile_id(:)
+ character(len=64) :: fname
+ character(len=7) :: gn
+ integer :: n
+ integer :: jbeg, jend
+ real ftop
+ real, allocatable :: g_dat2(:,:,:)
+ real, allocatable :: pt_coarse(:,:,:)
+ integer isc_p, iec_p, jsc_p, jec_p, isg, ieg, jsg,jeg
+
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+
+ is = Atm(1)%bd%is
+ ie = Atm(1)%bd%ie
+ js = Atm(1)%bd%js
+ je = Atm(1)%bd%je
+ isd = Atm(1)%bd%isd
+ ied = Atm(1)%bd%ied
+ jsd = Atm(1)%bd%jsd
+ jed = Atm(1)%bd%jed
+
+ if (Atm(1)%grid_number > 1) then
+ !write(gn,'(A2, I1)') ".g", Atm(1)%grid_number
+ write(gn,'(A5, I2.2)') ".nest", Atm(1)%grid_number
+ else
+ gn = ''
+ end if
+
+ ntileMe = size(Atm(:)) ! This will have to be modified for mult tiles per PE
+ ! ASSUMED always one at this point
+
+ allocate( tile_id(ntileMe) )
+ tile_id = mpp_get_tile_id( fv_domain )
+ do n=1,ntileMe
+
+ call get_tile_string(fname, 'INPUT/fv_core.res'//trim(gn)//'.tile', tile_id(n), '.nc' )
+ if (mpp_pe() == mpp_root_pe()) print*, 'external_ic: looking for ', fname
+
+
+ if( file_exist(fname) ) then
+ call read_data(fname, 'phis', Atm(n)%phis(is:ie,js:je), &
+ domain=fv_domain, tile_count=n)
+ else
+ call surfdrv( Atm(n)%npx, Atm(n)%npy, Atm(n)%gridstruct%grid_64, Atm(n)%gridstruct%agrid_64, &
+ Atm(n)%gridstruct%area_64, Atm(n)%gridstruct%dx, Atm(n)%gridstruct%dy, &
+ Atm(n)%gridstruct%dxa, Atm(n)%gridstruct%dya, &
+ Atm(n)%gridstruct%dxc, Atm(n)%gridstruct%dyc, Atm(n)%gridstruct%sin_sg, &
+ Atm(n)%phis, Atm(n)%flagstruct%stretch_fac, &
+ Atm(n)%neststruct%nested, Atm(n)%neststruct%npx_global, Atm(N)%domain, &
+ Atm(n)%flagstruct%grid_number, Atm(n)%bd, Atm(n)%flagstruct%regional )
+ call mpp_error(NOTE,'terrain datasets generated using USGS data')
+ endif
+
+ end do
+
+! Needed for reproducibility. DON'T REMOVE THIS!!
+ call mpp_update_domains( Atm(1)%phis, Atm(1)%domain )
+ ftop = g_sum(Atm(1)%domain, Atm(1)%phis(is:ie,js:je), is, ie, js, je, ng, Atm(1)%gridstruct%area_64, 1)
+
+ call prt_maxmin('ZS', Atm(1)%phis, is, ie, js, je, ng, 1, 1./grav)
+ if(is_master()) write(*,*) 'mean terrain height (m)=', ftop/grav
+
+ deallocate( tile_id )
+
+ end subroutine get_cubed_sphere_terrain
+
+!>@brief The subroutine 'get_nggps_ic' reads in data after it has been preprocessed with
+!! NCEP/EMC orography maker and 'global_chgres', and has been horiztontally
+!! interpolated to the current cubed-sphere grid
+ subroutine get_nggps_ic (Atm, fv_domain, dt_atmos )
+
+!>variables read in from 'gfs_ctrl.nc'
+!> VCOORD - level information
+!> maps to 'ak & bk'
+!> variables read in from 'sfc_data.nc'
+!> land_frac - land-sea-ice mask (L:0 / S:1)
+!> maps to 'oro'
+!> TSEA - surface skin temperature (k)
+!> maps to 'ts'
+!> variables read in from 'gfs_data.nc'
+!> ZH - GFS grid height at edges (m)
+!> PS - surface pressure (Pa)
+!> U_W - D-grid west face tangential wind component (m/s)
+!> V_W - D-grid west face normal wind component (m/s)
+!> U_S - D-grid south face tangential wind component (m/s)
+!> V_S - D-grid south face normal wind component (m/s)
+!> OMGA- vertical velocity 'omega' (Pa/s)
+!> Q - prognostic tracer fields
+!> Namelist variables
+!> filtered_terrain - use orography maker filtered terrain mapping
+#ifdef __PGI
+ use GFS_restart, only : GFS_restart_type
+
+ implicit none
+#endif
+
+ type(fv_atmos_type), intent(inout) :: Atm(:)
+ type(domain2d), intent(inout) :: fv_domain
+ real, intent(in) :: dt_atmos
+! local:
+ real, dimension(:), allocatable:: ak, bk
+ real, dimension(:,:), allocatable:: wk2, ps, oro_g
+ real, dimension(:,:,:), allocatable:: ud, vd, u_w, v_w, u_s, v_s, omga, temp
+ real, dimension(:,:,:), allocatable:: zh(:,:,:) ! 3D height at 65 edges
+ real, dimension(:,:,:,:), allocatable:: q
+ real, dimension(:,:), allocatable :: phis_coarse ! lmh
+ real rdg, wt, qt, m_fac
+ integer:: n, npx, npy, npz, itoa, nt, ntprog, ntdiag, ntracers, ntrac, iq
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+ integer :: ios, ierr, unit, id_res
+ type (restart_file_type) :: ORO_restart, SFC_restart, GFS_restart
+ character(len=6) :: gn, stile_name
+ character(len=64) :: tracer_name
+ character(len=64) :: fn_gfs_ctl = 'gfs_ctrl.nc'
+ character(len=64) :: fn_gfs_ics = 'gfs_data.nc'
+ character(len=64) :: fn_sfc_ics = 'sfc_data.nc'
+ character(len=64) :: fn_oro_ics = 'oro_data.nc'
+ ! DH* character(len=64) :: fn_aero_ics = 'aero_data.nc' *DH
+ logical :: remap
+ logical :: filtered_terrain = .true.
+ logical :: gfs_dwinds = .true.
+ integer :: levp = 64
+ logical :: checker_tr = .false.
+ integer :: nt_checker = 0
+ real(kind=R_GRID), dimension(2):: p1, p2, p3
+ real(kind=R_GRID), dimension(3):: e1, e2, ex, ey
+ integer:: i,j,k,nts, ks
+ integer:: liq_wat, ice_wat, rainwat, snowwat, graupel, ntclamt
+ namelist /external_ic_nml/ filtered_terrain, levp, gfs_dwinds, &
+ checker_tr, nt_checker
+#ifdef GFSL64
+ real, dimension(65):: ak_sj, bk_sj
+ data ak_sj/20.00000, 68.00000, 137.79000, &
+ 221.95800, 318.26600, 428.43400, &
+ 554.42400, 698.45700, 863.05803, &
+ 1051.07995, 1265.75194, 1510.71101, &
+ 1790.05098, 2108.36604, 2470.78817, &
+ 2883.03811, 3351.46002, 3883.05187, &
+ 4485.49315, 5167.14603, 5937.04991, &
+ 6804.87379, 7780.84698, 8875.64338, &
+ 9921.40745, 10760.99844, 11417.88354, &
+ 11911.61193, 12258.61668, 12472.89642, &
+ 12566.58298, 12550.43517, 12434.26075, &
+ 12227.27484, 11938.39468, 11576.46910, &
+ 11150.43640, 10669.41063, 10142.69482, &
+ 9579.72458, 8989.94947, 8382.67090, &
+ 7766.85063, 7150.91171, 6542.55077, &
+ 5948.57894, 5374.81094, 4825.99383, &
+ 4305.79754, 3816.84622, 3360.78848, &
+ 2938.39801, 2549.69756, 2194.08449, &
+ 1870.45732, 1577.34218, 1313.00028, &
+ 1075.52114, 862.90778, 673.13815, &
+ 504.22118, 354.22752, 221.32110, &
+ 103.78014, 0./
+ data bk_sj/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00179, 0.00705, 0.01564, &
+ 0.02749, 0.04251, 0.06064, &
+ 0.08182, 0.10595, 0.13294, &
+ 0.16266, 0.19492, 0.22950, &
+ 0.26615, 0.30455, 0.34435, &
+ 0.38516, 0.42656, 0.46815, &
+ 0.50949, 0.55020, 0.58989, &
+ 0.62825, 0.66498, 0.69987, &
+ 0.73275, 0.76351, 0.79208, &
+ 0.81845, 0.84264, 0.86472, &
+ 0.88478, 0.90290, 0.91923, &
+ 0.93388, 0.94697, 0.95865, &
+ 0.96904, 0.97826, 0.98642, &
+ 0.99363, 1./
+#else
+! The following L63 setting is the same as NCEP GFS's L64 except the top layer
+ real, dimension(64):: ak_sj, bk_sj
+ data ak_sj/64.247, 137.790, 221.958, &
+ 318.266, 428.434, 554.424, &
+ 698.457, 863.05803, 1051.07995, &
+ 1265.75194, 1510.71101, 1790.05098, &
+ 2108.36604, 2470.78817, 2883.03811, &
+ 3351.46002, 3883.05187, 4485.49315, &
+ 5167.14603, 5937.04991, 6804.87379, &
+ 7780.84698, 8875.64338, 10100.20534, &
+ 11264.35673, 12190.64366, 12905.42546, &
+ 13430.87867, 13785.88765, 13986.77987, &
+ 14047.96335, 13982.46770, 13802.40331, &
+ 13519.33841, 13144.59486, 12689.45608, &
+ 12165.28766, 11583.57006, 10955.84778, &
+ 10293.60402, 9608.08306, 8910.07678, &
+ 8209.70131, 7516.18560, 6837.69250, &
+ 6181.19473, 5552.39653, 4955.72632, &
+ 4394.37629, 3870.38682, 3384.76586, &
+ 2937.63489, 2528.37666, 2155.78385, &
+ 1818.20722, 1513.68173, 1240.03585, &
+ 994.99144, 776.23591, 581.48797, &
+ 408.53400, 255.26520, 119.70243, 0. /
+
+ data bk_sj/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00201, 0.00792, 0.01755, &
+ 0.03079, 0.04751, 0.06761, &
+ 0.09097, 0.11746, 0.14690, &
+ 0.17911, 0.21382, 0.25076, &
+ 0.28960, 0.32994, 0.37140, &
+ 0.41353, 0.45589, 0.49806, &
+ 0.53961, 0.58015, 0.61935, &
+ 0.65692, 0.69261, 0.72625, &
+ 0.75773, 0.78698, 0.81398, &
+ 0.83876, 0.86138, 0.88192, &
+ 0.90050, 0.91722, 0.93223, &
+ 0.94565, 0.95762, 0.96827, &
+ 0.97771, 0.98608, 0.99347, 1./
+#endif
+
+#ifdef TEMP_GFSPLV
+ real, dimension(64):: ak_sj, bk_sj
+ data ak_sj/64.247, 137.79, 221.958, &
+ 318.266, 428.434, 554.424, &
+ 698.457, 863.058, 1051.08, &
+ 1265.752, 1510.711, 1790.051, &
+ 2108.366, 2470.788, 2883.038, &
+ 3351.46, 3883.052, 4485.493, &
+ 5167.146, 5937.05, 6804.874, &
+ 7777.15, 8832.537, 9936.614, &
+ 11054.85, 12152.94, 13197.07, &
+ 14154.32, 14993.07, 15683.49, &
+ 16197.97, 16511.74, 16611.6, &
+ 16503.14, 16197.32, 15708.89, &
+ 15056.34, 14261.43, 13348.67, &
+ 12344.49, 11276.35, 10171.71, &
+ 9057.051, 7956.908, 6893.117, &
+ 5884.206, 4945.029, 4086.614, &
+ 3316.217, 2637.553, 2051.15, &
+ 1554.789, 1143.988, 812.489, &
+ 552.72, 356.223, 214.015, &
+ 116.899, 55.712, 21.516, &
+ 5.741, 0.575, 0., 0. /
+
+ data bk_sj/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00003697, 0.00043106, 0.00163591, &
+ 0.00410671, 0.00829402, 0.01463712, &
+ 0.02355588, 0.03544162, 0.05064684, &
+ 0.06947458, 0.09216691, 0.1188122, &
+ 0.1492688, 0.1832962, 0.2205702, &
+ 0.2606854, 0.3031641, 0.3474685, &
+ 0.3930182, 0.4392108, 0.4854433, &
+ 0.5311348, 0.5757467, 0.6187996, &
+ 0.659887, 0.6986829, 0.7349452, &
+ 0.7685147, 0.7993097, 0.8273188, &
+ 0.8525907, 0.8752236, 0.895355, &
+ 0.913151, 0.9287973, 0.9424911, &
+ 0.9544341, 0.9648276, 0.9738676, &
+ 0.9817423, 0.9886266, 0.9946712, 1./
+#endif
+
+ call mpp_error(NOTE,'Using external_IC::get_nggps_ic which is valid only for data which has been &
+ &horizontally interpolated to the current cubed-sphere grid')
+#ifdef INTERNAL_FILE_NML
+ read (input_nml_file,external_ic_nml,iostat=ios)
+ ierr = check_nml_error(ios,'external_ic_nml')
+#else
+ unit=open_namelist_file()
+ read (unit,external_ic_nml,iostat=ios)
+ ierr = check_nml_error(ios,'external_ic_nml')
+ call close_file(unit)
+#endif
+
+ unit = stdlog()
+ call write_version_number ( 'EXTERNAL_IC_mod::get_nggps_ic', version )
+ write(unit, nml=external_ic_nml)
+
+ remap = .true.
+ if (Atm(1)%flagstruct%external_eta) then
+ if (filtered_terrain) then
+ call mpp_error(NOTE,'External_IC::get_nggps_ic - use externally-generated, filtered terrain &
+ &and NCEP pressure levels (no vertical remapping)')
+ else if (.not. filtered_terrain) then
+ call mpp_error(NOTE,'External_IC::get_nggps_ic - use externally-generated, raw terrain &
+ &and NCEP pressure levels (no vertical remapping)')
+ endif
+ else ! (.not.external_eta)
+ if (filtered_terrain) then
+ call mpp_error(NOTE,'External_IC::get_nggps_ic - use externally-generated, filtered terrain &
+ &and FV3 pressure levels (vertical remapping)')
+ else if (.not. filtered_terrain) then
+ call mpp_error(NOTE,'External_IC::get_nggps_ic - use externally-generated, raw terrain &
+ &and FV3 pressure levels (vertical remapping)')
+ endif
+ endif
+
+ is = Atm(1)%bd%is
+ ie = Atm(1)%bd%ie
+ js = Atm(1)%bd%js
+ je = Atm(1)%bd%je
+ isd = Atm(1)%bd%isd
+ ied = Atm(1)%bd%ied
+ jsd = Atm(1)%bd%jsd
+ jed = Atm(1)%bd%jed
+ npz = Atm(1)%npz
+ write(*,22001)is,ie,js,je,isd,ied,jsd,jed
+22001 format(' enter get_nggps_ic is=',i4,' ie=',i4,' js=',i4,' je=',i4,' isd=',i4,' ied=',i4,' jsd=',i4,' jed=',i4)
+ call get_number_tracers(MODEL_ATMOS, num_tracers=ntracers, num_prog=ntprog)
+ ntdiag = ntracers-ntprog
+
+!--- test for existence of the GFS control file
+ if (.not. file_exist('INPUT/'//trim(fn_gfs_ctl), no_domain=.TRUE.)) then
+ call mpp_error(FATAL,'==> Error in External_ic::get_nggps_ic: file '//trim(fn_gfs_ctl)//' for NGGPS IC does not exist')
+ endif
+ call mpp_error(NOTE,'==> External_ic::get_nggps_ic: using control file '//trim(fn_gfs_ctl)//' for NGGPS IC')
+
+!--- read in the number of tracers in the NCEP NGGPS ICs
+ call read_data ('INPUT/'//trim(fn_gfs_ctl), 'ntrac', ntrac, no_domain=.TRUE.)
+ if (ntrac > ntracers) call mpp_error(FATAL,'==> External_ic::get_nggps_ic: more NGGPS tracers &
+ &than defined in field_table '//trim(fn_gfs_ctl)//' for NGGPS IC')
+
+!--- read in ak and bk from the gfs control file using fms_io read_data ---
+ allocate (wk2(levp+1,2))
+ allocate (ak(levp+1))
+ allocate (bk(levp+1))
+ call read_data('INPUT/'//trim(fn_gfs_ctl),'vcoord',wk2, no_domain=.TRUE.)
+ ak(1:levp+1) = wk2(1:levp+1,1)
+ bk(1:levp+1) = wk2(1:levp+1,2)
+ deallocate (wk2)
+
+ if (.not. file_exist('INPUT/'//trim(fn_oro_ics), domain=Atm(1)%domain)) then
+ call mpp_error(FATAL,'==> Error in External_ic::get_nggps_ic: tiled file '//trim(fn_oro_ics)//' for NGGPS IC does not exist')
+ endif
+ call mpp_error(NOTE,'==> External_ic::get_nggps_ic: using tiled data file '//trim(fn_oro_ics)//' for NGGPS IC')
+
+ if (.not. file_exist('INPUT/'//trim(fn_sfc_ics), domain=Atm(1)%domain)) then
+ call mpp_error(FATAL,'==> Error in External_ic::get_nggps_ic: tiled file '//trim(fn_sfc_ics)//' for NGGPS IC does not exist')
+ endif
+ call mpp_error(NOTE,'==> External_ic::get_nggps_ic: using tiled data file '//trim(fn_sfc_ics)//' for NGGPS IC')
+
+ if (.not. file_exist('INPUT/'//trim(fn_gfs_ics), domain=Atm(1)%domain)) then
+ call mpp_error(FATAL,'==> Error in External_ic::get_nggps_ic: tiled file '//trim(fn_gfs_ics)//' for NGGPS IC does not exist')
+ endif
+ call mpp_error(NOTE,'==> External_ic::get_nggps_ic: using tiled data file '//trim(fn_gfs_ics)//' for NGGPS IC')
+!
+ call get_data_source(source,Atm(1)%flagstruct%regional)
+!
+ allocate (zh(is:ie,js:je,levp+1)) ! SJL
+ allocate (ps(is:ie,js:je))
+ allocate (omga(is:ie,js:je,levp))
+ allocate (q (is:ie,js:je,levp,ntracers))
+ allocate ( u_w(is:ie+1, js:je, 1:levp) )
+ allocate ( v_w(is:ie+1, js:je, 1:levp) )
+ allocate ( u_s(is:ie, js:je+1, 1:levp) )
+ allocate ( v_s(is:ie, js:je+1, 1:levp) )
+ allocate (temp(is:ie,js:je,levp))
+
+ do n = 1,size(Atm(:))
+
+ !!! If a nested grid, save the filled coarse-grid topography for blending
+ if (Atm(n)%neststruct%nested) then
+ allocate(phis_coarse(isd:ied,jsd:jed))
+ do j=jsd,jed
+ do i=isd,ied
+ phis_coarse(i,j) = Atm(n)%phis(i,j)
+ enddo
+ enddo
+ endif
+
+!--- read in surface temperature (k) and land-frac
+ ! surface skin temperature
+ id_res = register_restart_field (SFC_restart, fn_sfc_ics, 'tsea', Atm(n)%ts, domain=Atm(n)%domain)
+
+ ! terrain surface height -- (needs to be transformed into phis = zs*grav)
+ if (filtered_terrain) then
+ id_res = register_restart_field (ORO_restart, fn_oro_ics, 'orog_filt', Atm(n)%phis, domain=Atm(n)%domain)
+ elseif (.not. filtered_terrain) then
+ id_res = register_restart_field (ORO_restart, fn_oro_ics, 'orog_raw', Atm(n)%phis, domain=Atm(n)%domain)
+ endif
+
+ if ( Atm(n)%flagstruct%full_zs_filter) then
+ allocate (oro_g(isd:ied,jsd:jed))
+ oro_g = 0.
+ ! land-frac
+ id_res = register_restart_field (ORO_restart, fn_oro_ics, 'land_frac', oro_g, domain=Atm(n)%domain)
+ call mpp_update_domains(oro_g, Atm(n)%domain)
+ if (Atm(n)%neststruct%nested) then
+ call extrapolation_BC(oro_g, 0, 0, Atm(n)%npx, Atm(n)%npy, Atm(n)%bd, .true.)
+ endif
+ endif
+
+ if ( Atm(n)%flagstruct%fv_land ) then
+ ! stddev
+ id_res = register_restart_field (ORO_restart, fn_oro_ics, 'stddev', Atm(n)%sgh, domain=Atm(n)%domain)
+ ! land-frac
+ id_res = register_restart_field (ORO_restart, fn_oro_ics, 'land_frac', Atm(n)%oro, domain=Atm(n)%domain)
+ endif
+
+ ! surface pressure (Pa)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'ps', ps, domain=Atm(n)%domain)
+
+ ! D-grid west face tangential wind component (m/s)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'u_w', u_w, domain=Atm(n)%domain,position=EAST)
+ ! D-grid west face normal wind component (m/s)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'v_w', v_w, domain=Atm(n)%domain,position=EAST)
+ ! D-grid south face tangential wind component (m/s)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'u_s', u_s, domain=Atm(n)%domain,position=NORTH)
+ ! D-grid south face normal wind component (m/s)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'v_s', v_s, domain=Atm(n)%domain,position=NORTH)
+
+ ! vertical velocity 'omega' (Pa/s)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'w', omga, domain=Atm(n)%domain)
+ ! GFS grid height at edges (including surface height)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'ZH', zh, domain=Atm(n)%domain)
+ ! real temperature (K)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 't', temp, mandatory=.false., &
+ domain=Atm(n)%domain)
+ ! prognostic tracers
+ do nt = 1, ntracers
+ call get_tracer_names(MODEL_ATMOS, nt, tracer_name)
+ ! DH* if aerosols are in separate file, need to test for indices liq_aero and ice_aero and change fn_gfs_ics to fn_aero_ics *DH
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, trim(tracer_name), q(:,:,:,nt), &
+ mandatory=.false.,domain=Atm(n)%domain)
+ enddo
+
+ ! initialize all tracers to default values prior to being input
+ do nt = 1, ntprog
+ call get_tracer_names(MODEL_ATMOS, nt, tracer_name)
+ ! set all tracers to an initial profile value
+ call set_tracer_profile (MODEL_ATMOS, nt, Atm(n)%q(:,:,:,nt) )
+ enddo
+ do nt = ntprog+1, ntracers
+ call get_tracer_names(MODEL_ATMOS, nt, tracer_name)
+ ! set all tracers to an initial profile value
+ call set_tracer_profile (MODEL_ATMOS, nt, Atm(n)%qdiag(:,:,:,nt) )
+ enddo
+
+ ! read in the restart
+ call restore_state (ORO_restart)
+ call restore_state (SFC_restart)
+ call restore_state (GFS_restart)
+
+ ! free the restart type to be re-used by the nest
+ call free_restart_type(ORO_restart)
+ call free_restart_type(SFC_restart)
+ call free_restart_type(GFS_restart)
+
+ ! multiply NCEP ICs terrain 'phis' by gravity to be true geopotential
+ Atm(n)%phis = Atm(n)%phis*grav
+
+ ! set the pressure levels and ptop to be used
+ if (Atm(1)%flagstruct%external_eta) then
+ itoa = levp - npz + 1
+ Atm(n)%ptop = ak(itoa)
+ Atm(n)%ak(1:npz+1) = ak(itoa:levp+1)
+ Atm(n)%bk(1:npz+1) = bk(itoa:levp+1)
+ call set_external_eta (Atm(n)%ak, Atm(n)%bk, Atm(n)%ptop, Atm(n)%ks)
+ endif
+ ! call vertical remapping algorithms
+ if(is_master()) write(*,*) 'GFS ak =', ak,' FV3 ak=',Atm(n)%ak
+ ak(1) = max(1.e-9, ak(1))
+
+!*** For regional runs read in each of the BC variables from the NetCDF boundary file
+!*** and remap in the vertical from the input levels to the model integration levels.
+!*** Here in the initialization we begn by allocating the regional domain's boundary
+!*** objects. Then we need to read the first two regional BC files so the integration
+!*** can begin interpolating between those two times as the forecast proceeds.
+
+ if (n==1.and.Atm(1)%flagstruct%regional) then !<-- Select the parent regional domain.
+
+ call start_regional_cold_start(Atm(1), dt_atmos, ak, bk, levp, &
+ is, ie, js, je, &
+ isd, ied, jsd, jed )
+ endif
+
+!
+!*** Remap the variables in the compute domain.
+!
+ call remap_scalar_nggps(Atm(n), levp, npz, ntracers, ak, bk, ps, temp, q, omga, zh)
+
+ allocate ( ud(is:ie, js:je+1, 1:levp) )
+ allocate ( vd(is:ie+1,js:je, 1:levp) )
+
+!$OMP parallel do default(none) shared(is,ie,js,je,levp,Atm,ud,vd,u_s,v_s,u_w,v_w) &
+!$OMP private(p1,p2,p3,e1,e2,ex,ey)
+ do k=1,levp
+ do j=js,je+1
+ do i=is,ie
+ p1(:) = Atm(1)%gridstruct%grid(i, j,1:2)
+ p2(:) = Atm(1)%gridstruct%grid(i+1,j,1:2)
+ call mid_pt_sphere(p1, p2, p3)
+ call get_unit_vect2(p1, p2, e1)
+ call get_latlon_vector(p3, ex, ey)
+ ud(i,j,k) = u_s(i,j,k)*inner_prod(e1,ex) + v_s(i,j,k)*inner_prod(e1,ey)
+ enddo
+ enddo
+ do j=js,je
+ do i=is,ie+1
+ p1(:) = Atm(1)%gridstruct%grid(i,j ,1:2)
+ p2(:) = Atm(1)%gridstruct%grid(i,j+1,1:2)
+ call mid_pt_sphere(p1, p2, p3)
+ call get_unit_vect2(p1, p2, e2)
+ call get_latlon_vector(p3, ex, ey)
+ vd(i,j,k) = u_w(i,j,k)*inner_prod(e2,ex) + v_w(i,j,k)*inner_prod(e2,ey)
+ enddo
+ enddo
+ enddo
+ deallocate ( u_w )
+ deallocate ( v_w )
+ deallocate ( u_s )
+ deallocate ( v_s )
+
+ call remap_dwinds(levp, npz, ak, bk, ps, ud, vd, Atm(n))
+
+ deallocate ( ud )
+ deallocate ( vd )
+
+ if (Atm(n)%neststruct%nested) then
+ if (is_master()) write(*,*) 'Blending nested and coarse grid topography'
+ npx = Atm(n)%npx
+ npy = Atm(n)%npy
+ do j=jsd,jed
+ do i=isd,ied
+ wt = max(0.,min(1.,real(5 - min(i,j,npx-i,npy-j,5))/5. ))
+ Atm(n)%phis(i,j) = (1.-wt)*Atm(n)%phis(i,j) + wt*phis_coarse(i,j)
+ enddo
+ enddo
+ endif
+
+
+ !!! Perform terrain smoothing, if desired
+ if ( Atm(n)%flagstruct%full_zs_filter ) then
+
+ call mpp_update_domains(Atm(n)%phis, Atm(n)%domain)
+
+ call FV3_zs_filter( Atm(n)%bd, isd, ied, jsd, jed, npx, npy, Atm(n)%neststruct%npx_global, &
+ Atm(n)%flagstruct%stretch_fac, Atm(n)%neststruct%nested, Atm(n)%domain, &
+ Atm(n)%gridstruct%area_64, Atm(n)%gridstruct%dxa, Atm(n)%gridstruct%dya, &
+ Atm(n)%gridstruct%dx, Atm(n)%gridstruct%dy, Atm(n)%gridstruct%dxc, &
+ Atm(n)%gridstruct%dyc, Atm(n)%gridstruct%grid_64, Atm(n)%gridstruct%agrid_64, &
+ Atm(n)%gridstruct%sin_sg, Atm(n)%phis, oro_g, Atm(n)%flagstruct%regional)
+ deallocate(oro_g)
+ endif
+
+
+ if ( Atm(n)%flagstruct%n_zs_filter > 0 ) then
+
+ if ( Atm(n)%flagstruct%nord_zs_filter == 2 ) then
+ call del2_cubed_sphere(Atm(n)%npx, Atm(n)%npy, Atm(n)%phis, &
+ Atm(n)%gridstruct%area_64, Atm(n)%gridstruct%dx, Atm(n)%gridstruct%dy, &
+ Atm(n)%gridstruct%dxc, Atm(n)%gridstruct%dyc, Atm(n)%gridstruct%sin_sg, &
+ Atm(n)%flagstruct%n_zs_filter, cnst_0p20*Atm(n)%gridstruct%da_min, &
+ .false., oro_g, Atm(n)%neststruct%nested, Atm(n)%domain, Atm(n)%bd, Atm(n)%flagstruct%regional)
+ if ( is_master() ) write(*,*) 'Warning !!! del-2 terrain filter has been applied ', &
+ Atm(n)%flagstruct%n_zs_filter, ' times'
+ else if( Atm(n)%flagstruct%nord_zs_filter == 4 ) then
+ call del4_cubed_sphere(Atm(n)%npx, Atm(n)%npy, Atm(n)%phis, Atm(n)%gridstruct%area_64, &
+ Atm(n)%gridstruct%dx, Atm(n)%gridstruct%dy, &
+ Atm(n)%gridstruct%dxc, Atm(n)%gridstruct%dyc, Atm(n)%gridstruct%sin_sg, &
+ Atm(n)%flagstruct%n_zs_filter, .false., oro_g, Atm(n)%neststruct%nested, &
+ Atm(n)%domain, Atm(n)%bd, Atm(n)%flagstruct%regional)
+ if ( is_master() ) write(*,*) 'Warning !!! del-4 terrain filter has been applied ', &
+ Atm(n)%flagstruct%n_zs_filter, ' times'
+ endif
+
+ endif
+
+ if ( Atm(n)%neststruct%nested .and. ( Atm(n)%flagstruct%n_zs_filter > 0 .or. Atm(n)%flagstruct%full_zs_filter ) ) then
+ npx = Atm(n)%npx
+ npy = Atm(n)%npy
+ do j=jsd,jed
+ do i=isd,ied
+ wt = max(0.,min(1.,real(5 - min(i,j,npx-i,npy-j,5))/5. ))
+ Atm(n)%phis(i,j) = (1.-wt)*Atm(n)%phis(i,j) + wt*phis_coarse(i,j)
+ enddo
+ enddo
+ deallocate(phis_coarse)
+ endif
+
+ call mpp_update_domains( Atm(n)%phis, Atm(n)%domain, complete=.true. )
+ liq_wat = get_tracer_index(MODEL_ATMOS, 'liq_wat')
+ ice_wat = get_tracer_index(MODEL_ATMOS, 'ice_wat')
+ rainwat = get_tracer_index(MODEL_ATMOS, 'rainwat')
+ snowwat = get_tracer_index(MODEL_ATMOS, 'snowwat')
+ graupel = get_tracer_index(MODEL_ATMOS, 'graupel')
+ ntclamt = get_tracer_index(MODEL_ATMOS, 'cld_amt')
+ if (trim(source) == 'FV3GFS GAUSSIAN NEMSIO FILE') then
+ do k=1,npz
+ do j=js,je
+ do i=is,ie
+ wt = Atm(n)%delp(i,j,k)
+ if ( Atm(n)%flagstruct%nwat == 6 ) then
+ qt = wt*(1. + Atm(n)%q(i,j,k,liq_wat) + &
+ Atm(n)%q(i,j,k,ice_wat) + &
+ Atm(n)%q(i,j,k,rainwat) + &
+ Atm(n)%q(i,j,k,snowwat) + &
+ Atm(n)%q(i,j,k,graupel))
+ else ! all other values of nwat
+ qt = wt*(1. + sum(Atm(n)%q(i,j,k,2:Atm(n)%flagstruct%nwat)))
+ endif
+ Atm(n)%delp(i,j,k) = qt
+ if (ntclamt > 0) Atm(n)%q(i,j,k,ntclamt) = 0.0 ! Moorthi
+ enddo
+ enddo
+ enddo
+ else
+!--- Add cloud condensate from GFS to total MASS
+! 20160928: Adjust the mixing ratios consistently...
+ do k=1,npz
+ do j=js,je
+ do i=is,ie
+ wt = Atm(n)%delp(i,j,k)
+ if ( Atm(n)%flagstruct%nwat == 6 ) then
+ qt = wt*(1. + Atm(n)%q(i,j,k,liq_wat) + &
+ Atm(n)%q(i,j,k,ice_wat) + &
+ Atm(n)%q(i,j,k,rainwat) + &
+ Atm(n)%q(i,j,k,snowwat) + &
+ Atm(n)%q(i,j,k,graupel))
+ else ! all other values of nwat
+ qt = wt*(1. + sum(Atm(n)%q(i,j,k,2:Atm(n)%flagstruct%nwat)))
+ endif
+ m_fac = wt / qt
+ do iq=1,ntracers
+ Atm(n)%q(i,j,k,iq) = m_fac * Atm(n)%q(i,j,k,iq)
+ enddo
+ Atm(n)%delp(i,j,k) = qt
+ if (ntclamt > 0) Atm(n)%q(i,j,k,ntclamt) = 0.0 ! Moorthi
+ enddo
+ enddo
+ enddo
+ endif !end trim(source) test
+
+!--- reset the tracers beyond condensate to a checkerboard pattern
+ if (checker_tr) then
+ nts = ntracers - nt_checker+1
+ call checker_tracers(is,ie, js,je, isd,ied, jsd,jed, nt_checker, &
+ npz, Atm(n)%q(:,:,:,nts:ntracers), &
+ Atm(n)%gridstruct%agrid_64(is:ie,js:je,1), &
+ Atm(n)%gridstruct%agrid_64(is:ie,js:je,2), 9., 9.)
+ endif
+ enddo ! n-loop
+
+ Atm(1)%flagstruct%make_nh = .false.
+
+ deallocate (ak)
+ deallocate (bk)
+ deallocate (ps)
+ deallocate (q )
+ deallocate (temp)
+ deallocate (omga)
+
+ end subroutine get_nggps_ic
+!------------------------------------------------------------------
+!------------------------------------------------------------------
+!>@brief The subroutine 'get_ncep_ic' reads in the specified NCEP analysis or reanalysis dataset
+ subroutine get_ncep_ic( Atm, fv_domain, nq )
+ type(fv_atmos_type), intent(inout) :: Atm(:)
+ type(domain2d), intent(inout) :: fv_domain
+ integer, intent(in):: nq
+! local:
+#ifdef HIWPP_ETA
+ real :: ak_HIWPP(65), bk_HIWPP(65)
+ data ak_HIWPP/ &
+ 0, 0.00064247, 0.0013779, 0.00221958, 0.00318266, 0.00428434, &
+ 0.00554424, 0.00698457, 0.00863058, 0.0105108, 0.01265752, 0.01510711, &
+ 0.01790051, 0.02108366, 0.02470788, 0.02883038, 0.0335146, 0.03883052, &
+ 0.04485493, 0.05167146, 0.0593705, 0.06804874, 0.0777715, 0.08832537, &
+ 0.09936614, 0.1105485, 0.1215294, 0.1319707, 0.1415432, 0.1499307, &
+ 0.1568349, 0.1619797, 0.1651174, 0.166116, 0.1650314, 0.1619731, &
+ 0.1570889, 0.1505634, 0.1426143, 0.1334867, 0.1234449, 0.1127635, &
+ 0.1017171, 0.09057051, 0.07956908, 0.06893117, 0.05884206, 0.04945029, &
+ 0.04086614, 0.03316217, 0.02637553, 0.0205115, 0.01554789, 0.01143988, &
+ 0.00812489, 0.0055272, 0.00356223, 0.00214015, 0.00116899, 0.00055712, &
+ 0.00021516, 5.741e-05, 5.75e-06, 0, 0 /
+
+ data bk_HIWPP/ &
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &
+ 3.697e-05, 0.00043106, 0.00163591, 0.00410671, 0.00829402, 0.01463712, &
+ 0.02355588, 0.03544162, 0.05064684, 0.06947458, 0.09216691, 0.1188122, &
+ 0.1492688, 0.1832962, 0.2205702, 0.2606854, 0.3031641, 0.3474685, &
+ 0.3930182, 0.4392108, 0.4854433, 0.5311348, 0.5757467, 0.6187996, &
+ 0.659887, 0.6986829, 0.7349452, 0.7685147, 0.7993097, 0.8273188, &
+ 0.8525907, 0.8752236, 0.895355, 0.913151, 0.9287973, 0.9424911, &
+ 0.9544341, 0.9648276, 0.9738676, 0.9817423, 0.9886266, 0.9946712, 1 /
+#endif
+ character(len=128) :: fname
+ real(kind=4), allocatable:: wk1(:), wk2(:,:), wk3(:,:,:)
+ real, allocatable:: tp(:,:,:), qp(:,:,:)
+ real, allocatable:: ua(:,:,:), va(:,:,:)
+ real, allocatable:: lat(:), lon(:), ak0(:), bk0(:)
+ real:: s2c(Atm(1)%bd%is:Atm(1)%bd%ie,Atm(1)%bd%js:Atm(1)%bd%je,4)
+ integer, dimension(Atm(1)%bd%is:Atm(1)%bd%ie,Atm(1)%bd%js:Atm(1)%bd%je):: id1, id2, jdc
+ real psc(Atm(1)%bd%is:Atm(1)%bd%ie,Atm(1)%bd%js:Atm(1)%bd%je)
+ real gzc(Atm(1)%bd%is:Atm(1)%bd%ie,Atm(1)%bd%js:Atm(1)%bd%je)
+ real tmean
+ integer:: i, j, k, im, jm, km, npz, npt
+ integer:: i1, i2, j1, ncid
+ integer:: jbeg, jend
+ integer tsize(3)
+ logical:: read_ts = .true.
+ logical:: land_ts = .false.
+ logical:: found
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+
+ is = Atm(1)%bd%is
+ ie = Atm(1)%bd%ie
+ js = Atm(1)%bd%js
+ je = Atm(1)%bd%je
+ isd = Atm(1)%bd%isd
+ ied = Atm(1)%bd%ied
+ jsd = Atm(1)%bd%jsd
+ jed = Atm(1)%bd%jed
+
+ deg2rad = pi/180.
+
+ npz = Atm(1)%npz
+
+! Zero out all initial tracer fields:
+! SJL: 20110716
+! Atm(1)%q = 0.
+
+ fname = Atm(1)%flagstruct%res_latlon_dynamics
+
+ if( file_exist(fname) ) then
+ call open_ncfile( fname, ncid ) ! open the file
+ call get_ncdim1( ncid, 'lon', tsize(1) )
+ call get_ncdim1( ncid, 'lat', tsize(2) )
+ call get_ncdim1( ncid, 'lev', tsize(3) )
+
+ im = tsize(1); jm = tsize(2); km = tsize(3)
+
+ if(is_master()) write(*,*) fname
+ if(is_master()) write(*,*) ' NCEP IC dimensions:', tsize
+
+ allocate ( lon(im) )
+ allocate ( lat(jm) )
+
+ call _GET_VAR1(ncid, 'lon', im, lon )
+ call _GET_VAR1(ncid, 'lat', jm, lat )
+
+! Convert to radian
+ do i=1,im
+ lon(i) = lon(i) * deg2rad ! lon(1) = 0.
+ enddo
+ do j=1,jm
+ lat(j) = lat(j) * deg2rad
+ enddo
+
+ allocate ( ak0(km+1) )
+ allocate ( bk0(km+1) )
+
+#ifdef HIWPP_ETA
+! The HIWPP data from Jeff does not contain (ak,bk)
+ do k=1, km+1
+ ak0(k) = ak_HIWPP (k)
+ bk0(k) = bk_HIWPP (k)
+ enddo
+#else
+ call _GET_VAR1(ncid, 'hyai', km+1, ak0, found )
+ if ( .not. found ) ak0(:) = 0.
+
+ call _GET_VAR1(ncid, 'hybi', km+1, bk0 )
+#endif
+ if( is_master() ) then
+ do k=1,km+1
+ write(*,*) k, ak0(k), bk0(k)
+ enddo
+ endif
+
+! Note: definition of NCEP hybrid is p(k) = a(k)*1.E5 + b(k)*ps
+ ak0(:) = ak0(:) * 1.E5
+
+! Limiter to prevent NAN at top during remapping
+ if ( bk0(1) < 1.E-9 ) ak0(1) = max(1.e-9, ak0(1))
+
+ else
+ call mpp_error(FATAL,'==> Error in get_external_ic: Expected file '//trim(fname)//' for NCEP IC does not exist')
+ endif
+
+! Initialize lat-lon to Cubed bi-linear interpolation coeff:
+ call remap_coef( is, ie, js, je, isd, ied, jsd, jed, &
+ im, jm, lon, lat, id1, id2, jdc, s2c , Atm(1)%gridstruct%agrid)
+
+! Find bounding latitudes:
+ jbeg = jm-1; jend = 2
+ do j=js,je
+ do i=is,ie
+ j1 = jdc(i,j)
+ jbeg = min(jbeg, j1)
+ jend = max(jend, j1+1)
+ enddo
+ enddo
+
+! remap surface pressure and height:
+
+ allocate ( wk2(im,jbeg:jend) )
+ call get_var3_r4( ncid, 'PS', 1,im, jbeg,jend, 1,1, wk2 )
+
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ psc(i,j) = s2c(i,j,1)*wk2(i1,j1 ) + s2c(i,j,2)*wk2(i2,j1 ) + &
+ s2c(i,j,3)*wk2(i2,j1+1) + s2c(i,j,4)*wk2(i1,j1+1)
+ enddo
+ enddo
+
+ call get_var3_r4( ncid, 'PHIS', 1,im, jbeg,jend, 1,1, wk2 )
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ gzc(i,j) = s2c(i,j,1)*wk2(i1,j1 ) + s2c(i,j,2)*wk2(i2,j1 ) + &
+ s2c(i,j,3)*wk2(i2,j1+1) + s2c(i,j,4)*wk2(i1,j1+1)
+ enddo
+ enddo
+
+ deallocate ( wk2 )
+ allocate ( wk2(im,jm) )
+
+ if ( read_ts ) then ! read skin temperature; could be used for SST
+
+ call get_var2_real( ncid, 'TS', im, jm, wk2 )
+
+ if ( .not. land_ts ) then
+ allocate ( wk1(im) )
+
+ do j=1,jm
+! Read NCEP ORO (1; land; 0: ocean; 2: sea_ice)
+ call get_var3_r4( ncid, 'ORO', 1,im, j,j, 1,1, wk1 )
+ tmean = 0.
+ npt = 0
+ do i=1,im
+ if( abs(wk1(i)-1.) > 0.99 ) then ! ocean or sea ice
+ tmean = tmean + wk2(i,j)
+ npt = npt + 1
+ endif
+ enddo
+!------------------------------------------------------
+! Replace TS over interior land with zonal mean SST/Ice
+!------------------------------------------------------
+ if ( npt /= 0 ) then
+ tmean= tmean / real(npt)
+ do i=1,im
+ if( abs(wk1(i)-1.) <= 0.99 ) then ! Land points
+ if ( i==1 ) then
+ i1 = im; i2 = 2
+ elseif ( i==im ) then
+ i1 = im-1; i2 = 1
+ else
+ i1 = i-1; i2 = i+1
+ endif
+ if ( abs(wk1(i2)-1.)>0.99 ) then ! east side has priority
+ wk2(i,j) = wk2(i2,j)
+ elseif ( abs(wk1(i1)-1.)>0.99 ) then ! west side
+ wk2(i,j) = wk2(i1,j)
+ else
+ wk2(i,j) = tmean
+ endif
+ endif
+ enddo
+ endif
+ enddo ! j-loop
+ deallocate ( wk1 )
+ endif !(.not.land_ts)
+
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ Atm(1)%ts(i,j) = s2c(i,j,1)*wk2(i1,j1 ) + s2c(i,j,2)*wk2(i2,j1 ) + &
+ s2c(i,j,3)*wk2(i2,j1+1) + s2c(i,j,4)*wk2(i1,j1+1)
+ enddo
+ enddo
+ call prt_maxmin('SST_model', Atm(1)%ts, is, ie, js, je, 0, 1, 1.)
+
+! Perform interp to FMS SST format/grid
+#ifndef DYCORE_SOLO
+ call ncep2fms(im, jm, lon, lat, wk2)
+ if( is_master() ) then
+ write(*,*) 'External_ic_mod: i_sst=', i_sst, ' j_sst=', j_sst
+ call pmaxmin( 'SST_ncep_fms', sst_ncep, i_sst, j_sst, 1.)
+ endif
+#endif
+ endif !(read_ts)
+
+ deallocate ( wk2 )
+
+! Read in temperature:
+ allocate ( wk3(1:im,jbeg:jend, 1:km) )
+ call get_var3_r4( ncid, 'T', 1,im, jbeg,jend, 1,km, wk3 )
+
+ allocate ( tp(is:ie,js:je,km) )
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ tp(i,j,k) = s2c(i,j,1)*wk3(i1,j1 ,k) + s2c(i,j,2)*wk3(i2,j1 ,k) + &
+ s2c(i,j,3)*wk3(i2,j1+1,k) + s2c(i,j,4)*wk3(i1,j1+1,k)
+ enddo
+ enddo
+ enddo
+
+! Read in tracers: only sphum at this point
+ call get_var3_r4( ncid, 'Q', 1,im, jbeg,jend, 1,km, wk3 )
+
+ allocate ( qp(is:ie,js:je,km) )
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ qp(i,j,k) = s2c(i,j,1)*wk3(i1,j1 ,k) + s2c(i,j,2)*wk3(i2,j1 ,k) + &
+ s2c(i,j,3)*wk3(i2,j1+1,k) + s2c(i,j,4)*wk3(i1,j1+1,k)
+ enddo
+ enddo
+ enddo
+
+ call remap_scalar(im, jm, km, npz, nq, nq, ak0, bk0, psc, gzc, tp, qp, Atm(1))
+ deallocate ( tp )
+ deallocate ( qp )
+
+! Winds:
+ call get_var3_r4( ncid, 'U', 1,im, jbeg,jend, 1,km, wk3 )
+
+ allocate ( ua(is:ie,js:je,km) )
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ ua(i,j,k) = s2c(i,j,1)*wk3(i1,j1 ,k) + s2c(i,j,2)*wk3(i2,j1 ,k) + &
+ s2c(i,j,3)*wk3(i2,j1+1,k) + s2c(i,j,4)*wk3(i1,j1+1,k)
+ enddo
+ enddo
+ enddo
+
+ call get_var3_r4( ncid, 'V', 1,im, jbeg,jend, 1,km, wk3 )
+ call close_ncfile ( ncid )
+
+ allocate ( va(is:ie,js:je,km) )
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ va(i,j,k) = s2c(i,j,1)*wk3(i1,j1 ,k) + s2c(i,j,2)*wk3(i2,j1 ,k) + &
+ s2c(i,j,3)*wk3(i2,j1+1,k) + s2c(i,j,4)*wk3(i1,j1+1,k)
+ enddo
+ enddo
+ enddo
+ deallocate ( wk3 )
+ call remap_winds(im, jm, km, npz, ak0, bk0, psc, ua, va, Atm(1))
+
+ deallocate ( ua )
+ deallocate ( va )
+
+ deallocate ( ak0 )
+ deallocate ( bk0 )
+ deallocate ( lat )
+ deallocate ( lon )
+
+ end subroutine get_ncep_ic
+
+!>@brief The subroutine 'get_ecmwf_ic' reads in initial conditions from ECMWF analyses
+!! (EXPERIMENTAL: contact Jan-Huey Chen jan-huey.chen@noaa.gov for support)
+!>@authors Jan-Huey Chen, Xi Chen, Shian-Jiann Lin
+ subroutine get_ecmwf_ic( Atm, fv_domain )
+
+#ifdef __PGI
+ use GFS_restart, only : GFS_restart_type
+
+ implicit none
+#endif
+
+ type(fv_atmos_type), intent(inout) :: Atm(:)
+ type(domain2d), intent(inout) :: fv_domain
+! local:
+ real :: ak_ec(138), bk_ec(138)
+ data ak_ec/ 0.000000, 2.000365, 3.102241, 4.666084, 6.827977, 9.746966, &
+ 13.605424, 18.608931, 24.985718, 32.985710, 42.879242, 54.955463, &
+ 69.520576, 86.895882, 107.415741, 131.425507, 159.279404, 191.338562, &
+ 227.968948, 269.539581, 316.420746, 368.982361, 427.592499, 492.616028, &
+ 564.413452, 643.339905, 729.744141, 823.967834, 926.344910, 1037.201172, &
+ 1156.853638, 1285.610352, 1423.770142, 1571.622925, 1729.448975, 1897.519287, &
+ 2076.095947, 2265.431641, 2465.770508, 2677.348145, 2900.391357, 3135.119385, &
+ 3381.743652, 3640.468262, 3911.490479, 4194.930664, 4490.817383, 4799.149414, &
+ 5119.895020, 5452.990723, 5798.344727, 6156.074219, 6526.946777, 6911.870605, &
+ 7311.869141, 7727.412109, 8159.354004, 8608.525391, 9076.400391, 9562.682617, &
+ 10065.978516, 10584.631836, 11116.662109, 11660.067383, 12211.547852, 12766.873047, &
+ 13324.668945, 13881.331055, 14432.139648, 14975.615234, 15508.256836, 16026.115234, &
+ 16527.322266, 17008.789063, 17467.613281, 17901.621094, 18308.433594, 18685.718750, &
+ 19031.289063, 19343.511719, 19620.042969, 19859.390625, 20059.931641, 20219.664063, &
+ 20337.863281, 20412.308594, 20442.078125, 20425.718750, 20361.816406, 20249.511719, &
+ 20087.085938, 19874.025391, 19608.572266, 19290.226563, 18917.460938, 18489.707031, &
+ 18006.925781, 17471.839844, 16888.687500, 16262.046875, 15596.695313, 14898.453125, &
+ 14173.324219, 13427.769531, 12668.257813, 11901.339844, 11133.304688, 10370.175781, &
+ 9617.515625, 8880.453125, 8163.375000, 7470.343750, 6804.421875, 6168.531250, &
+ 5564.382813, 4993.796875, 4457.375000, 3955.960938, 3489.234375, 3057.265625, &
+ 2659.140625, 2294.242188, 1961.500000, 1659.476563, 1387.546875, 1143.250000, &
+ 926.507813, 734.992188, 568.062500, 424.414063, 302.476563, 202.484375, &
+ 122.101563, 62.781250, 22.835938, 3.757813, 0.000000, 0.000000 /
+
+ data bk_ec/ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000007, 0.000024, 0.000059, 0.000112, 0.000199, &
+ 0.000340, 0.000562, 0.000890, 0.001353, 0.001992, 0.002857, &
+ 0.003971, 0.005378, 0.007133, 0.009261, 0.011806, 0.014816, &
+ 0.018318, 0.022355, 0.026964, 0.032176, 0.038026, 0.044548, &
+ 0.051773, 0.059728, 0.068448, 0.077958, 0.088286, 0.099462, &
+ 0.111505, 0.124448, 0.138313, 0.153125, 0.168910, 0.185689, &
+ 0.203491, 0.222333, 0.242244, 0.263242, 0.285354, 0.308598, &
+ 0.332939, 0.358254, 0.384363, 0.411125, 0.438391, 0.466003, &
+ 0.493800, 0.521619, 0.549301, 0.576692, 0.603648, 0.630036, &
+ 0.655736, 0.680643, 0.704669, 0.727739, 0.749797, 0.770798, &
+ 0.790717, 0.809536, 0.827256, 0.843881, 0.859432, 0.873929, &
+ 0.887408, 0.899900, 0.911448, 0.922096, 0.931881, 0.940860, &
+ 0.949064, 0.956550, 0.963352, 0.969513, 0.975078, 0.980072, &
+ 0.984542, 0.988500, 0.991984, 0.995003, 0.997630, 1.000000 /
+
+! The following L63 will be used in the model
+! The setting is the same as NCEP GFS's L64 except the top layer
+ real, dimension(64):: ak_sj, bk_sj
+ data ak_sj/64.247, 137.790, 221.958, &
+ 318.266, 428.434, 554.424, &
+ 698.457, 863.05803, 1051.07995, &
+ 1265.75194, 1510.71101, 1790.05098, &
+ 2108.36604, 2470.78817, 2883.03811, &
+ 3351.46002, 3883.05187, 4485.49315, &
+ 5167.14603, 5937.04991, 6804.87379, &
+ 7780.84698, 8875.64338, 10100.20534, &
+ 11264.35673, 12190.64366, 12905.42546, &
+ 13430.87867, 13785.88765, 13986.77987, &
+ 14047.96335, 13982.46770, 13802.40331, &
+ 13519.33841, 13144.59486, 12689.45608, &
+ 12165.28766, 11583.57006, 10955.84778, &
+ 10293.60402, 9608.08306, 8910.07678, &
+ 8209.70131, 7516.18560, 6837.69250, &
+ 6181.19473, 5552.39653, 4955.72632, &
+ 4394.37629, 3870.38682, 3384.76586, &
+ 2937.63489, 2528.37666, 2155.78385, &
+ 1818.20722, 1513.68173, 1240.03585, &
+ 994.99144, 776.23591, 581.48797, &
+ 408.53400, 255.26520, 119.70243, 0. /
+
+ data bk_sj/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00201, 0.00792, 0.01755, &
+ 0.03079, 0.04751, 0.06761, &
+ 0.09097, 0.11746, 0.14690, &
+ 0.17911, 0.21382, 0.25076, &
+ 0.28960, 0.32994, 0.37140, &
+ 0.41353, 0.45589, 0.49806, &
+ 0.53961, 0.58015, 0.61935, &
+ 0.65692, 0.69261, 0.72625, &
+ 0.75773, 0.78698, 0.81398, &
+ 0.83876, 0.86138, 0.88192, &
+ 0.90050, 0.91722, 0.93223, &
+ 0.94565, 0.95762, 0.96827, &
+ 0.97771, 0.98608, 0.99347, 1./
+
+ character(len=128) :: fname
+ real, allocatable:: wk2(:,:)
+ real(kind=4), allocatable:: wk2_r4(:,:)
+ real, dimension(:,:,:), allocatable:: ud, vd
+ real, allocatable:: wc(:,:,:)
+ real(kind=4), allocatable:: uec(:,:,:), vec(:,:,:), tec(:,:,:), wec(:,:,:)
+ real(kind=4), allocatable:: psec(:,:), zsec(:,:), zhec(:,:,:), qec(:,:,:,:)
+ real(kind=4), allocatable:: psc(:,:)
+ real(kind=4), allocatable:: sphumec(:,:,:)
+ real, allocatable:: psc_r8(:,:), zhc(:,:,:), qc(:,:,:,:)
+ real, allocatable:: lat(:), lon(:), ak0(:), bk0(:)
+ real, allocatable:: pt_c(:,:,:), pt_d(:,:,:)
+ real:: s2c(Atm(1)%bd%is:Atm(1)%bd%ie,Atm(1)%bd%js:Atm(1)%bd%je,4)
+ real:: s2c_c(Atm(1)%bd%is:Atm(1)%bd%ie+1,Atm(1)%bd%js:Atm(1)%bd%je,4)
+ real:: s2c_d(Atm(1)%bd%is:Atm(1)%bd%ie,Atm(1)%bd%js:Atm(1)%bd%je+1,4)
+ integer, dimension(Atm(1)%bd%is:Atm(1)%bd%ie,Atm(1)%bd%js:Atm(1)%bd%je):: &
+ id1, id2, jdc
+ integer, dimension(Atm(1)%bd%is:Atm(1)%bd%ie+1,Atm(1)%bd%js:Atm(1)%bd%je):: &
+ id1_c, id2_c, jdc_c
+ integer, dimension(Atm(1)%bd%is:Atm(1)%bd%ie,Atm(1)%bd%js:Atm(1)%bd%je+1):: &
+ id1_d, id2_d, jdc_d
+ real:: utmp, vtmp
+ integer:: i, j, k, n, im, jm, km, npz, npt
+ integer:: i1, i2, j1, ncid
+ integer:: jbeg, jend, jn
+ integer tsize(3)
+ logical:: read_ts = .true.
+ logical:: land_ts = .false.
+ logical:: found
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+ integer :: sphum, liq_wat, ice_wat, rainwat, snowwat, graupel
+#ifdef MULTI_GASES
+ integer :: spfo, spfo2, spfo3
+#else
+ integer :: o3mr
+#endif
+ real:: wt, qt, m_fac
+ real(kind=8) :: scale_value, offset, ptmp
+ real(kind=R_GRID), dimension(2):: p1, p2, p3
+ real(kind=R_GRID), dimension(3):: e1, e2, ex, ey
+ real, allocatable:: ps_gfs(:,:), zh_gfs(:,:,:)
+#ifdef MULTI_GASES
+ real, allocatable:: spfo_gfs(:,:,:), spfo2_gfs(:,:,:), spfo3_gfs(:,:,:)
+#else
+ real, allocatable:: o3mr_gfs(:,:,:)
+#endif
+ real, allocatable:: ak_gfs(:), bk_gfs(:)
+ integer :: id_res, ntprog, ntracers, ks, iq, nt
+ character(len=64) :: tracer_name
+ integer :: levp_gfs = 64
+ type (restart_file_type) :: ORO_restart, GFS_restart
+ character(len=64) :: fn_oro_ics = 'oro_data.nc'
+ character(len=64) :: fn_gfs_ics = 'gfs_data.nc'
+ character(len=64) :: fn_gfs_ctl = 'gfs_ctrl.nc'
+ logical :: filtered_terrain = .true.
+ namelist /external_ic_nml/ filtered_terrain
+
+ is = Atm(1)%bd%is
+ ie = Atm(1)%bd%ie
+ js = Atm(1)%bd%js
+ je = Atm(1)%bd%je
+ isd = Atm(1)%bd%isd
+ ied = Atm(1)%bd%ied
+ jsd = Atm(1)%bd%jsd
+ jed = Atm(1)%bd%jed
+
+ deg2rad = pi/180.
+
+ npz = Atm(1)%npz
+ call get_number_tracers(MODEL_ATMOS, num_tracers=ntracers, num_prog=ntprog)
+ if(is_master()) write(*,*) 'ntracers = ', ntracers, 'ntprog = ',ntprog
+
+ sphum = get_tracer_index(MODEL_ATMOS, 'sphum')
+ liq_wat = get_tracer_index(MODEL_ATMOS, 'liq_wat')
+ ice_wat = get_tracer_index(MODEL_ATMOS, 'ice_wat')
+ rainwat = get_tracer_index(MODEL_ATMOS, 'rainwat')
+ snowwat = get_tracer_index(MODEL_ATMOS, 'snowwat')
+ graupel = get_tracer_index(MODEL_ATMOS, 'graupel')
+#ifdef MULTI_GASES
+ spfo = get_tracer_index(MODEL_ATMOS, 'spfo')
+ spfo2 = get_tracer_index(MODEL_ATMOS, 'spfo2')
+ spfo3 = get_tracer_index(MODEL_ATMOS, 'spfo3')
+#else
+ o3mr = get_tracer_index(MODEL_ATMOS, 'o3mr')
+#endif
+
+ if (is_master()) then
+ print *, 'sphum = ', sphum
+ print *, 'liq_wat = ', liq_wat
+ if ( Atm(1)%flagstruct%nwat .eq. 6 ) then
+ print *, 'rainwat = ', rainwat
+ print *, 'iec_wat = ', ice_wat
+ print *, 'snowwat = ', snowwat
+ print *, 'graupel = ', graupel
+ endif
+#ifdef MULTI_GASES
+ print *, ' spfo3 = ', spfo3
+ print *, ' spfo = ', spfo
+ print *, ' spfo2 = ', spfo2
+#else
+ print *, ' o3mr = ', o3mr
+#endif
+ endif
+
+
+! Set up model's ak and bk
+! if ( npz <= 64 ) then
+! Atm(1)%ak(:) = ak_sj(:)
+! Atm(1)%bk(:) = bk_sj(:)
+! Atm(1)%ptop = Atm(1)%ak(1)
+! else
+! call set_eta(npz, ks, Atm(1)%ptop, Atm(1)%ak, Atm(1)%bk)
+! endif
+
+!! Read in model terrain from oro_data.tile?.nc
+ if (filtered_terrain) then
+ id_res = register_restart_field (ORO_restart, fn_oro_ics, 'orog_filt', Atm(1)%phis, domain=Atm(1)%domain)
+ elseif (.not. filtered_terrain) then
+ id_res = register_restart_field (ORO_restart, fn_oro_ics, 'orog_raw', Atm(1)%phis, domain=Atm(1)%domain)
+ endif
+ call restore_state (ORO_restart)
+ call free_restart_type(ORO_restart)
+ Atm(1)%phis = Atm(1)%phis*grav
+ if(is_master()) write(*,*) 'done reading model terrain from oro_data.nc'
+ call mpp_update_domains( Atm(1)%phis, Atm(1)%domain )
+
+!! Read in o3mr, ps and zh from GFS_data.tile?.nc
+#ifdef MULTI_GASES
+ allocate (spfo3_gfs(is:ie,js:je,levp_gfs))
+ allocate ( spfo_gfs(is:ie,js:je,levp_gfs))
+ allocate (spfo2_gfs(is:ie,js:je,levp_gfs))
+#else
+ allocate (o3mr_gfs(is:ie,js:je,levp_gfs))
+#endif
+ allocate (ps_gfs(is:ie,js:je))
+ allocate (zh_gfs(is:ie,js:je,levp_gfs+1))
+
+#ifdef MULTI_GASES
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'spfo3', spfo3_gfs, &
+ mandatory=.false.,domain=Atm(1)%domain)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'spfo', spfo_gfs, &
+ mandatory=.false.,domain=Atm(1)%domain)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'spfo2', spfo2_gfs, &
+ mandatory=.false.,domain=Atm(1)%domain)
+#else
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'o3mr', o3mr_gfs, &
+ mandatory=.false.,domain=Atm(1)%domain)
+#endif
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'ps', ps_gfs, domain=Atm(1)%domain)
+ id_res = register_restart_field (GFS_restart, fn_gfs_ics, 'ZH', zh_gfs, domain=Atm(1)%domain)
+ call restore_state (GFS_restart)
+ call free_restart_type(GFS_restart)
+
+
+ ! Get GFS ak, bk for o3mr vertical interpolation
+ allocate (wk2(levp_gfs+1,2))
+ allocate (ak_gfs(levp_gfs+1))
+ allocate (bk_gfs(levp_gfs+1))
+ call read_data('INPUT/'//trim(fn_gfs_ctl),'vcoord',wk2, no_domain=.TRUE.)
+ ak_gfs(1:levp_gfs+1) = wk2(1:levp_gfs+1,1)
+ bk_gfs(1:levp_gfs+1) = wk2(1:levp_gfs+1,2)
+ deallocate (wk2)
+
+ if ( bk_gfs(1) < 1.E-9 ) ak_gfs(1) = max(1.e-9, ak_gfs(1))
+
+#ifdef MULTI_GASES
+ iq = spfo3
+ if(is_master()) write(*,*) 'Reading spfo3 from GFS_data.nc:'
+ if(is_master()) write(*,*) 'spfo3 =', iq
+ call remap_scalar_single(Atm(1), levp_gfs, npz, ak_gfs, bk_gfs, ps_gfs, spfo3_gfs, zh_gfs, iq)
+ iq = spfo
+ if(is_master()) write(*,*) 'Reading spfo from GFS_data.nc:'
+ if(is_master()) write(*,*) 'spfo =', iq
+ call remap_scalar_single(Atm(1), levp_gfs, npz, ak_gfs, bk_gfs, ps_gfs, spfo_gfs, zh_gfs, iq)
+ iq = spfo2
+ if(is_master()) write(*,*) 'Reading spfo2 from GFS_data.nc:'
+ if(is_master()) write(*,*) 'spfo2 =', iq
+ call remap_scalar_single(Atm(1), levp_gfs, npz, ak_gfs, bk_gfs, ps_gfs, spfo2_gfs, zh_gfs, iq)
+#else
+ iq = o3mr
+ if(is_master()) write(*,*) 'Reading o3mr from GFS_data.nc:'
+ if(is_master()) write(*,*) 'o3mr =', iq
+ call remap_scalar_single(Atm(1), levp_gfs, npz, ak_gfs, bk_gfs, ps_gfs, o3mr_gfs, zh_gfs, iq)
+#endif
+
+ deallocate (ak_gfs, bk_gfs)
+ deallocate (ps_gfs, zh_gfs)
+#ifdef MULTI_GASES
+ deallocate (spfo3_gfs)
+ deallocate ( spfo_gfs)
+ deallocate (spfo2_gfs)
+#else
+ deallocate (o3mr_gfs)
+#endif
+
+!! Start to read EC data
+ fname = Atm(1)%flagstruct%res_latlon_dynamics
+
+ if( file_exist(fname) ) then
+ call open_ncfile( fname, ncid ) ! open the file
+
+ call get_ncdim1( ncid, 'longitude', tsize(1) )
+ call get_ncdim1( ncid, 'latitude', tsize(2) )
+ call get_ncdim1( ncid, 'level', tsize(3) )
+
+ im = tsize(1); jm = tsize(2); km = tsize(3)
+
+ if(is_master()) write(*,*) fname
+ if(is_master()) write(*,*) ' ECMWF IC dimensions:', tsize
+
+ allocate ( lon(im) )
+ allocate ( lat(jm) )
+
+ call _GET_VAR1(ncid, 'longitude', im, lon )
+ call _GET_VAR1(ncid, 'latitude', jm, lat )
+
+!! Convert to radian
+ do i = 1, im
+ lon(i) = lon(i) * deg2rad ! lon(1) = 0.
+ enddo
+ do j = 1, jm
+ lat(j) = lat(j) * deg2rad
+ enddo
+
+ allocate ( ak0(km+1) )
+ allocate ( bk0(km+1) )
+
+! The ECMWF data from does not contain (ak,bk)
+ do k=1, km+1
+ ak0(k) = ak_ec(k)
+ bk0(k) = bk_ec(k)
+ enddo
+
+ if( is_master() ) then
+ do k=1,km+1
+ write(*,*) k, ak0(k), bk0(k)
+ enddo
+ endif
+
+! Limiter to prevent NAN at top during remapping
+ if ( bk0(1) < 1.E-9 ) ak0(1) = max(1.e-9, ak0(1))
+
+ else
+ call mpp_error(FATAL,'==> Error in get_external_ic: Expected file '//trim(fname)//' for NCEP IC does not exist')
+ endif
+
+! Initialize lat-lon to Cubed bi-linear interpolation coeff:
+ call remap_coef( is, ie, js, je, isd, ied, jsd, jed, &
+ im, jm, lon, lat, id1, id2, jdc, s2c , Atm(1)%gridstruct%agrid )
+
+! Find bounding latitudes:
+ jbeg = jm-1; jend = 2
+ do j=js,je
+ do i=is,ie
+ j1 = jdc(i,j)
+ jbeg = min(jbeg, j1)
+ jend = max(jend, j1+1)
+ enddo
+ enddo
+
+ if(is_master()) write(*,*) 'jbeg, jend = ', jbeg, jend
+! read in surface pressure and height:
+ allocate ( psec(im,jbeg:jend) )
+ allocate ( zsec(im,jbeg:jend) )
+ allocate ( wk2_r4(im,jbeg:jend) )
+
+ call get_var2_r4( ncid, 'lnsp', 1,im, jbeg,jend, wk2_r4 )
+ call get_var_att_double ( ncid, 'lnsp', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'lnsp', 'add_offset', offset )
+ psec(:,:) = exp(wk2_r4(:,:)*scale_value + offset)
+ if(is_master()) write(*,*) 'done reading psec'
+
+ call get_var2_r4( ncid, 'z', 1,im, jbeg,jend, wk2_r4 )
+ call get_var_att_double ( ncid, 'z', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'z', 'add_offset', offset )
+ zsec(:,:) = (wk2_r4(:,:)*scale_value + offset)/grav
+ if(is_master()) write(*,*) 'done reading zsec'
+
+ deallocate ( wk2_r4 )
+
+! Read in temperature:
+ allocate ( tec(1:im,jbeg:jend, 1:km) )
+
+ call get_var3_r4( ncid, 't', 1,im, jbeg,jend, 1,km, tec )
+ call get_var_att_double ( ncid, 't', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 't', 'add_offset', offset )
+ tec(:,:,:) = tec(:,:,:)*scale_value + offset
+ if(is_master()) write(*,*) 'done reading tec'
+
+! read in specific humidity:
+ allocate ( sphumec(1:im,jbeg:jend, 1:km) )
+
+ call get_var3_r4( ncid, 'q', 1,im, jbeg,jend, 1,km, sphumec(:,:,:) )
+ call get_var_att_double ( ncid, 'q', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'q', 'add_offset', offset )
+ sphumec(:,:,:) = sphumec(:,:,:)*scale_value + offset
+ if(is_master()) write(*,*) 'done reading sphum ec'
+
+! Read in other tracers from EC data and remap them into cubic sphere grid:
+ allocate ( qec(1:im,jbeg:jend,1:km,5) )
+
+ do n = 1, 5
+ if (n == sphum) then
+ qec(:,:,:,sphum) = sphumec(:,:,:)
+ deallocate ( sphumec )
+ else if (n == liq_wat) then
+ call get_var3_r4( ncid, 'clwc', 1,im, jbeg,jend, 1,km, qec(:,:,:,liq_wat) )
+ call get_var_att_double ( ncid, 'clwc', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'clwc', 'add_offset', offset )
+ qec(:,:,:,liq_wat) = qec(:,:,:,liq_wat)*scale_value + offset
+ if(is_master()) write(*,*) 'done reading clwc ec'
+ else if (n == rainwat) then
+ call get_var3_r4( ncid, 'crwc', 1,im, jbeg,jend, 1,km, qec(:,:,:,rainwat) )
+ call get_var_att_double ( ncid, 'crwc', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'crwc', 'add_offset', offset )
+ qec(:,:,:,rainwat) = qec(:,:,:,rainwat)*scale_value + offset
+ if(is_master()) write(*,*) 'done reading crwc ec'
+ else if (n == ice_wat) then
+ call get_var3_r4( ncid, 'ciwc', 1,im, jbeg,jend, 1,km, qec(:,:,:,ice_wat) )
+ call get_var_att_double ( ncid, 'ciwc', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'ciwc', 'add_offset', offset )
+ qec(:,:,:,ice_wat) = qec(:,:,:,ice_wat)*scale_value + offset
+ if(is_master()) write(*,*) 'done reading ciwc ec'
+ else if (n == snowwat) then
+ call get_var3_r4( ncid, 'cswc', 1,im, jbeg,jend, 1,km, qec(:,:,:,snowwat) )
+ call get_var_att_double ( ncid, 'cswc', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'cswc', 'add_offset', offset )
+ qec(:,:,:,snowwat) = qec(:,:,:,snowwat)*scale_value + offset
+ if(is_master()) write(*,*) 'done reading cswc ec'
+ else
+ if(is_master()) write(*,*) 'nq is more then 5!'
+ endif
+
+ enddo
+
+
+!!!! Compute height on edges, zhec [ use psec, zsec, tec, sphum]
+ allocate ( zhec(1:im,jbeg:jend, km+1) )
+ jn = jend - jbeg + 1
+
+ call compute_zh(im, jn, km, ak0, bk0, psec, zsec, tec, qec, 5, zhec )
+ if(is_master()) write(*,*) 'done compute zhec'
+
+! convert zhec, psec, zsec from EC grid to cubic grid
+ allocate (psc(is:ie,js:je))
+ allocate (psc_r8(is:ie,js:je))
+
+#ifdef LOGP_INTP
+ do j=jbeg,jend
+ do i=1,im
+ psec(i,j) = log(psec(i,j))
+ enddo
+ enddo
+#endif
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+#ifdef LOGP_INTP
+ ptmp = s2c(i,j,1)*psec(i1,j1 ) + s2c(i,j,2)*psec(i2,j1 ) + &
+ s2c(i,j,3)*psec(i2,j1+1) + s2c(i,j,4)*psec(i1,j1+1)
+ psc(i,j) = exp(ptmp)
+#else
+ psc(i,j) = s2c(i,j,1)*psec(i1,j1 ) + s2c(i,j,2)*psec(i2,j1 ) + &
+ s2c(i,j,3)*psec(i2,j1+1) + s2c(i,j,4)*psec(i1,j1+1)
+#endif
+ enddo
+ enddo
+ deallocate ( psec )
+ deallocate ( zsec )
+
+ allocate (zhc(is:ie,js:je,km+1))
+!$OMP parallel do default(none) shared(is,ie,js,je,km,s2c,id1,id2,jdc,zhc,zhec) &
+!$OMP private(i1,i2,j1)
+ do k=1,km+1
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ zhc(i,j,k) = s2c(i,j,1)*zhec(i1,j1 ,k) + s2c(i,j,2)*zhec(i2,j1 ,k) + &
+ s2c(i,j,3)*zhec(i2,j1+1,k) + s2c(i,j,4)*zhec(i1,j1+1,k)
+ enddo
+ enddo
+ enddo
+ deallocate ( zhec )
+
+ if(is_master()) write(*,*) 'done interpolate psec/zsec/zhec into cubic grid psc/zhc!'
+
+! Read in other tracers from EC data and remap them into cubic sphere grid:
+ allocate ( qc(is:ie,js:je,km,6) )
+
+ do n = 1, 5
+!$OMP parallel do default(none) shared(n,is,ie,js,je,km,s2c,id1,id2,jdc,qc,qec) &
+!$OMP private(i1,i2,j1)
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ qc(i,j,k,n) = s2c(i,j,1)*qec(i1,j1 ,k,n) + s2c(i,j,2)*qec(i2,j1 ,k,n) + &
+ s2c(i,j,3)*qec(i2,j1+1,k,n) + s2c(i,j,4)*qec(i1,j1+1,k,n)
+ enddo
+ enddo
+ enddo
+ enddo
+
+ qc(:,:,:,graupel) = 0. ! note Graupel must be tracer #6
+
+ deallocate ( qec )
+ if(is_master()) write(*,*) 'done interpolate tracers (qec) into cubic (qc)'
+
+! Read in vertical wind from EC data and remap them into cubic sphere grid:
+ allocate ( wec(1:im,jbeg:jend, 1:km) )
+ allocate ( wc(is:ie,js:je,km))
+
+ call get_var3_r4( ncid, 'w', 1,im, jbeg,jend, 1,km, wec )
+ call get_var_att_double ( ncid, 'w', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'w', 'add_offset', offset )
+ wec(:,:,:) = wec(:,:,:)*scale_value + offset
+ !call p_maxmin('wec', wec, 1, im, jbeg, jend, km, 1.)
+
+!$OMP parallel do default(none) shared(is,ie,js,je,km,id1,id2,jdc,s2c,wc,wec) &
+!$OMP private(i1,i2,j1)
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ i1 = id1(i,j)
+ i2 = id2(i,j)
+ j1 = jdc(i,j)
+ wc(i,j,k) = s2c(i,j,1)*wec(i1,j1 ,k) + s2c(i,j,2)*wec(i2,j1 ,k) + &
+ s2c(i,j,3)*wec(i2,j1+1,k) + s2c(i,j,4)*wec(i1,j1+1,k)
+ enddo
+ enddo
+ enddo
+ !call p_maxmin('wc', wc, is, ie, js, je, km, 1.)
+
+ deallocate ( wec )
+ if(is_master()) write(*,*) 'done reading and interpolate vertical wind (w) into cubic'
+
+! remap tracers
+ psc_r8(:,:) = psc(:,:)
+ deallocate ( psc )
+
+ call remap_scalar_ec(Atm(1), km, npz, 6, ak0, bk0, psc_r8, qc, wc, zhc )
+ call mpp_update_domains(Atm(1)%phis, Atm(1)%domain)
+ if(is_master()) write(*,*) 'done remap_scalar_ec'
+
+ deallocate ( zhc )
+ deallocate ( wc )
+ deallocate ( qc )
+
+!! Winds:
+ ! get lat/lon values of pt_c and pt_d from grid data (pt_b)
+ allocate (pt_c(isd:ied+1,jsd:jed ,2))
+ allocate (pt_d(isd:ied ,jsd:jed+1,2))
+ allocate (ud(is:ie , js:je+1, km))
+ allocate (vd(is:ie+1, js:je , km))
+
+ call get_staggered_grid( is, ie, js, je, &
+ isd, ied, jsd, jed, &
+ Atm(1)%gridstruct%grid, pt_c, pt_d)
+
+ !------ pt_c part ------
+ ! Initialize lat-lon to Cubed bi-linear interpolation coeff:
+ call remap_coef( is, ie+1, js, je, isd, ied+1, jsd, jed, &
+ im, jm, lon, lat, id1_c, id2_c, jdc_c, s2c_c, pt_c)
+
+ ! Find bounding latitudes:
+ jbeg = jm-1; jend = 2
+ do j=js,je
+ do i=is,ie+1
+ j1 = jdc_c(i,j)
+ jbeg = min(jbeg, j1)
+ jend = max(jend, j1+1)
+ enddo
+ enddo
+
+ ! read in EC wind data
+ allocate ( uec(1:im,jbeg:jend, 1:km) )
+ allocate ( vec(1:im,jbeg:jend, 1:km) )
+
+ call get_var3_r4( ncid, 'u', 1,im, jbeg,jend, 1,km, uec )
+ call get_var_att_double ( ncid, 'u', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'u', 'add_offset', offset )
+ do k=1,km
+ do j=jbeg, jend
+ do i=1,im
+ uec(i,j,k) = uec(i,j,k)*scale_value + offset
+ enddo
+ enddo
+ enddo
+ if(is_master()) write(*,*) 'first time done reading uec'
+
+ call get_var3_r4( ncid, 'v', 1,im, jbeg,jend, 1,km, vec )
+ call get_var_att_double ( ncid, 'v', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'v', 'add_offset', offset )
+ do k=1,km
+ do j=jbeg, jend
+ do i=1,im
+ vec(i,j,k) = vec(i,j,k)*scale_value + offset
+ enddo
+ enddo
+ enddo
+
+ if(is_master()) write(*,*) 'first time done reading vec'
+
+!$OMP parallel do default(none) shared(is,ie,js,je,km,s2c_c,id1_c,id2_c,jdc_c,uec,vec,Atm,vd) &
+!$OMP private(i1,i2,j1,p1,p2,p3,e2,ex,ey,utmp,vtmp)
+ do k=1,km
+ do j=js,je
+ do i=is,ie+1
+ i1 = id1_c(i,j)
+ i2 = id2_c(i,j)
+ j1 = jdc_c(i,j)
+ p1(:) = Atm(1)%gridstruct%grid(i,j ,1:2)
+ p2(:) = Atm(1)%gridstruct%grid(i,j+1,1:2)
+ call mid_pt_sphere(p1, p2, p3)
+ call get_unit_vect2(p1, p2, e2)
+ call get_latlon_vector(p3, ex, ey)
+ utmp = s2c_c(i,j,1)*uec(i1,j1 ,k) + &
+ s2c_c(i,j,2)*uec(i2,j1 ,k) + &
+ s2c_c(i,j,3)*uec(i2,j1+1,k) + &
+ s2c_c(i,j,4)*uec(i1,j1+1,k)
+ vtmp = s2c_c(i,j,1)*vec(i1,j1 ,k) + &
+ s2c_c(i,j,2)*vec(i2,j1 ,k) + &
+ s2c_c(i,j,3)*vec(i2,j1+1,k) + &
+ s2c_c(i,j,4)*vec(i1,j1+1,k)
+ vd(i,j,k) = utmp*inner_prod(e2,ex) + vtmp*inner_prod(e2,ey)
+ enddo
+ enddo
+ enddo
+
+ deallocate ( uec, vec )
+
+ !------ pt_d part ------
+ ! Initialize lat-lon to Cubed bi-linear interpolation coeff:
+ call remap_coef( is, ie, js, je+1, isd, ied, jsd, jed+1, &
+ im, jm, lon, lat, id1_d, id2_d, jdc_d, s2c_d, pt_d)
+ deallocate ( pt_c, pt_d )
+
+ ! Find bounding latitudes:
+ jbeg = jm-1; jend = 2
+ do j=js,je+1
+ do i=is,ie
+ j1 = jdc_d(i,j)
+ jbeg = min(jbeg, j1)
+ jend = max(jend, j1+1)
+ enddo
+ enddo
+
+ ! read in EC wind data
+ allocate ( uec(1:im,jbeg:jend, 1:km) )
+ allocate ( vec(1:im,jbeg:jend, 1:km) )
+
+ call get_var3_r4( ncid, 'u', 1,im, jbeg,jend, 1,km, uec )
+ call get_var_att_double ( ncid, 'u', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'u', 'add_offset', offset )
+ uec(:,:,:) = uec(:,:,:)*scale_value + offset
+ if(is_master()) write(*,*) 'second time done reading uec'
+
+ call get_var3_r4( ncid, 'v', 1,im, jbeg,jend, 1,km, vec )
+ call get_var_att_double ( ncid, 'v', 'scale_factor', scale_value )
+ call get_var_att_double ( ncid, 'v', 'add_offset', offset )
+ vec(:,:,:) = vec(:,:,:)*scale_value + offset
+ if(is_master()) write(*,*) 'second time done reading vec'
+
+!$OMP parallel do default(none) shared(is,ie,js,je,km,id1_d,id2_d,jdc_d,s2c_d,uec,vec,Atm,ud) &
+!$OMP private(i1,i2,j1,p1,p2,p3,e1,ex,ey,utmp,vtmp)
+ do k=1,km
+ do j=js,je+1
+ do i=is,ie
+ i1 = id1_d(i,j)
+ i2 = id2_d(i,j)
+ j1 = jdc_d(i,j)
+ p1(:) = Atm(1)%gridstruct%grid(i, j,1:2)
+ p2(:) = Atm(1)%gridstruct%grid(i+1,j,1:2)
+ call mid_pt_sphere(p1, p2, p3)
+ call get_unit_vect2(p1, p2, e1)
+ call get_latlon_vector(p3, ex, ey)
+ utmp = s2c_d(i,j,1)*uec(i1,j1 ,k) + &
+ s2c_d(i,j,2)*uec(i2,j1 ,k) + &
+ s2c_d(i,j,3)*uec(i2,j1+1,k) + &
+ s2c_d(i,j,4)*uec(i1,j1+1,k)
+ vtmp = s2c_d(i,j,1)*vec(i1,j1 ,k) + &
+ s2c_d(i,j,2)*vec(i2,j1 ,k) + &
+ s2c_d(i,j,3)*vec(i2,j1+1,k) + &
+ s2c_d(i,j,4)*vec(i1,j1+1,k)
+ ud(i,j,k) = utmp*inner_prod(e1,ex) + vtmp*inner_prod(e1,ey)
+ enddo
+ enddo
+ enddo
+ deallocate ( uec, vec )
+
+ call remap_dwinds(km, npz, ak0, bk0, psc_r8, ud, vd, Atm(1))
+ deallocate ( ud, vd )
+
+#ifndef COND_IFS_IC
+! Add cloud condensate from IFS to total MASS
+! Adjust the mixing ratios consistently...
+ do k=1,npz
+ do j=js,je
+ do i=is,ie
+ wt = Atm(1)%delp(i,j,k)
+ if ( Atm(1)%flagstruct%nwat .eq. 2 ) then
+ qt = wt*(1.+Atm(1)%q(i,j,k,liq_wat))
+ elseif ( Atm(1)%flagstruct%nwat .eq. 6 ) then
+ qt = wt*(1. + Atm(1)%q(i,j,k,liq_wat) + &
+ Atm(1)%q(i,j,k,ice_wat) + &
+ Atm(1)%q(i,j,k,rainwat) + &
+ Atm(1)%q(i,j,k,snowwat) + &
+ Atm(1)%q(i,j,k,graupel))
+ endif
+ m_fac = wt / qt
+ do iq=1,ntracers
+ Atm(1)%q(i,j,k,iq) = m_fac * Atm(1)%q(i,j,k,iq)
+ enddo
+ Atm(1)%delp(i,j,k) = qt
+ enddo
+ enddo
+ enddo
+#endif
+
+ deallocate ( ak0, bk0 )
+! deallocate ( psc )
+ deallocate ( psc_r8 )
+ deallocate ( lat, lon )
+
+ Atm(1)%flagstruct%make_nh = .false.
+
+ end subroutine get_ecmwf_ic
+!------------------------------------------------------------------
+!------------------------------------------------------------------
+ subroutine get_fv_ic( Atm, fv_domain, nq )
+ type(fv_atmos_type), intent(inout) :: Atm(:)
+ type(domain2d), intent(inout) :: fv_domain
+ integer, intent(in):: nq
+
+ character(len=128) :: fname, tracer_name
+ real, allocatable:: ps0(:,:), gz0(:,:), u0(:,:,:), v0(:,:,:), t0(:,:,:), dp0(:,:,:), q0(:,:,:,:)
+ real, allocatable:: ua(:,:,:), va(:,:,:)
+ real, allocatable:: lat(:), lon(:), ak0(:), bk0(:)
+ integer :: i, j, k, im, jm, km, npz, tr_ind
+ integer tsize(3)
+! integer sphum, liq_wat, ice_wat, cld_amt ! GFDL AM2 physics
+ logical found
+
+ npz = Atm(1)%npz
+
+! Zero out all initial tracer fields:
+ Atm(1)%q = 0.
+
+! Read in lat-lon FV core restart file
+ fname = Atm(1)%flagstruct%res_latlon_dynamics
+
+ if( file_exist(fname) ) then
+ call field_size(fname, 'T', tsize, field_found=found)
+ if(is_master()) write(*,*) 'Using lat-lon FV restart:', fname
+
+ if ( found ) then
+ im = tsize(1); jm = tsize(2); km = tsize(3)
+ if(is_master()) write(*,*) 'External IC dimensions:', tsize
+ else
+ call mpp_error(FATAL,'==> Error in get_external_ic: field not found')
+ endif
+
+! Define the lat-lon coordinate:
+ allocate ( lon(im) )
+ allocate ( lat(jm) )
+
+ do i=1,im
+ lon(i) = (0.5 + real(i-1)) * 2.*pi/real(im)
+ enddo
+
+ do j=1,jm
+ lat(j) = -0.5*pi + real(j-1)*pi/real(jm-1) ! SP to NP
+ enddo
+
+ allocate ( ak0(1:km+1) )
+ allocate ( bk0(1:km+1) )
+ allocate ( ps0(1:im,1:jm) )
+ allocate ( gz0(1:im,1:jm) )
+ allocate ( u0(1:im,1:jm,1:km) )
+ allocate ( v0(1:im,1:jm,1:km) )
+ allocate ( t0(1:im,1:jm,1:km) )
+ allocate ( dp0(1:im,1:jm,1:km) )
+
+ call read_data (fname, 'ak', ak0)
+ call read_data (fname, 'bk', bk0)
+ call read_data (fname, 'Surface_geopotential', gz0)
+ call read_data (fname, 'U', u0)
+ call read_data (fname, 'V', v0)
+ call read_data (fname, 'T', t0)
+ call read_data (fname, 'DELP', dp0)
+
+! Share the load
+ if(is_master()) call pmaxmin( 'ZS_data', gz0, im, jm, 1./grav)
+ if(mpp_pe()==1) call pmaxmin( 'U_data', u0, im*jm, km, 1.)
+ if(mpp_pe()==1) call pmaxmin( 'V_data', v0, im*jm, km, 1.)
+ if(mpp_pe()==2) call pmaxmin( 'T_data', t0, im*jm, km, 1.)
+ if(mpp_pe()==3) call pmaxmin( 'DEL-P', dp0, im*jm, km, 0.01)
+
+
+ else
+ call mpp_error(FATAL,'==> Error in get_external_ic: Expected file '//trim(fname)//' for dynamics does not exist')
+ endif
+
+! Read in tracers: only AM2 "physics tracers" at this point
+ fname = Atm(1)%flagstruct%res_latlon_tracers
+
+ if( file_exist(fname) ) then
+ if(is_master()) write(*,*) 'Using lat-lon tracer restart:', fname
+
+ allocate ( q0(im,jm,km,Atm(1)%ncnst) )
+ q0 = 0.
+
+ do tr_ind = 1, nq
+ call get_tracer_names(MODEL_ATMOS, tr_ind, tracer_name)
+ if (field_exist(fname,tracer_name)) then
+ call read_data(fname, tracer_name, q0(1:im,1:jm,1:km,tr_ind))
+ call mpp_error(NOTE,'==> Have read tracer '//trim(tracer_name)//' from '//trim(fname))
+ cycle
+ endif
+ enddo
+ else
+ call mpp_error(FATAL,'==> Error in get_external_ic: Expected file '//trim(fname)//' for tracers does not exist')
+ endif
+
+! D to A transform on lat-lon grid:
+ allocate ( ua(im,jm,km) )
+ allocate ( va(im,jm,km) )
+
+ call d2a3d(u0, v0, ua, va, im, jm, km, lon)
+
+ deallocate ( u0 )
+ deallocate ( v0 )
+
+ if(mpp_pe()==4) call pmaxmin( 'UA', ua, im*jm, km, 1.)
+ if(mpp_pe()==4) call pmaxmin( 'VA', va, im*jm, km, 1.)
+
+ do j=1,jm
+ do i=1,im
+ ps0(i,j) = ak0(1)
+ enddo
+ enddo
+
+ do k=1,km
+ do j=1,jm
+ do i=1,im
+ ps0(i,j) = ps0(i,j) + dp0(i,j,k)
+ enddo
+ enddo
+ enddo
+
+ if (is_master()) call pmaxmin( 'PS_data (mb)', ps0, im, jm, 0.01)
+
+! Horizontal interpolation to the cubed sphere grid center
+! remap vertically with terrain adjustment
+
+ call remap_xyz( im, 1, jm, jm, km, npz, nq, Atm(1)%ncnst, lon, lat, ak0, bk0, &
+ ps0, gz0, ua, va, t0, q0, Atm(1) )
+
+ deallocate ( ak0 )
+ deallocate ( bk0 )
+ deallocate ( ps0 )
+ deallocate ( gz0 )
+ deallocate ( t0 )
+ deallocate ( q0 )
+ deallocate ( dp0 )
+ deallocate ( ua )
+ deallocate ( va )
+ deallocate ( lat )
+ deallocate ( lon )
+
+ end subroutine get_fv_ic
+!------------------------------------------------------------------
+!------------------------------------------------------------------
+#ifndef DYCORE_SOLO
+ subroutine ncep2fms(im, jm, lon, lat, wk)
+
+ integer, intent(in):: im, jm
+ real, intent(in):: lon(im), lat(jm)
+ real(kind=4), intent(in):: wk(im,jm)
+! local:
+ real :: rdlon(im)
+ real :: rdlat(jm)
+ real:: a1, b1
+ real:: delx, dely
+ real:: xc, yc ! "data" location
+ real:: c1, c2, c3, c4
+ integer i,j, i1, i2, jc, i0, j0, it, jt
+
+ do i=1,im-1
+ rdlon(i) = 1. / (lon(i+1) - lon(i))
+ enddo
+ rdlon(im) = 1. / (lon(1) + 2.*pi - lon(im))
+
+ do j=1,jm-1
+ rdlat(j) = 1. / (lat(j+1) - lat(j))
+ enddo
+
+! * Interpolate to "FMS" 1x1 SST data grid
+! lon: 0.5, 1.5, ..., 359.5
+! lat: -89.5, -88.5, ... , 88.5, 89.5
+
+ delx = 360./real(i_sst)
+ dely = 180./real(j_sst)
+
+ jt = 1
+ do 5000 j=1,j_sst
+
+ yc = (-90. + dely * (0.5+real(j-1))) * deg2rad
+ if ( yclat(jm) ) then
+ jc = jm-1
+ b1 = 1.
+ else
+ do j0=jt,jm-1
+ if ( yc>=lat(j0) .and. yc<=lat(j0+1) ) then
+ jc = j0
+ jt = j0
+ b1 = (yc-lat(jc)) * rdlat(jc)
+ go to 222
+ endif
+ enddo
+ endif
+222 continue
+ it = 1
+
+ do i=1,i_sst
+ xc = delx * (0.5+real(i-1)) * deg2rad
+ if ( xc>lon(im) ) then
+ i1 = im; i2 = 1
+ a1 = (xc-lon(im)) * rdlon(im)
+ elseif ( xc=lon(i0) .and. xc<=lon(i0+1) ) then
+ i1 = i0; i2 = i0+1
+ it = i0
+ a1 = (xc-lon(i1)) * rdlon(i0)
+ go to 111
+ endif
+ enddo
+ endif
+111 continue
+
+ if ( a1<0.0 .or. a1>1.0 .or. b1<0.0 .or. b1>1.0 ) then
+ write(*,*) 'gid=', mpp_pe(), i,j,a1, b1
+ endif
+
+ c1 = (1.-a1) * (1.-b1)
+ c2 = a1 * (1.-b1)
+ c3 = a1 * b1
+ c4 = (1.-a1) * b1
+! Interpolated surface pressure
+ sst_ncep(i,j) = c1*wk(i1,jc ) + c2*wk(i2,jc ) + &
+ c3*wk(i2,jc+1) + c4*wk(i1,jc+1)
+ enddo !i-loop
+5000 continue ! j-loop
+
+ end subroutine ncep2fms
+#endif
+
+
+ subroutine remap_coef( is, ie, js, je, isd, ied, jsd, jed, &
+ im, jm, lon, lat, id1, id2, jdc, s2c, agrid )
+
+ integer, intent(in):: is, ie, js, je, isd, ied, jsd, jed
+ integer, intent(in):: im, jm
+ real, intent(in):: lon(im), lat(jm)
+ real, intent(out):: s2c(is:ie,js:je,4)
+ integer, intent(out), dimension(is:ie,js:je):: id1, id2, jdc
+ real, intent(in):: agrid(isd:ied,jsd:jed,2)
+! local:
+ real :: rdlon(im)
+ real :: rdlat(jm)
+ real:: a1, b1
+ integer i,j, i1, i2, jc, i0, j0
+
+ do i=1,im-1
+ rdlon(i) = 1. / (lon(i+1) - lon(i))
+ enddo
+ rdlon(im) = 1. / (lon(1) + 2.*pi - lon(im))
+
+ do j=1,jm-1
+ rdlat(j) = 1. / (lat(j+1) - lat(j))
+ enddo
+
+! * Interpolate to cubed sphere cell center
+ do 5000 j=js,je
+
+ do i=is,ie
+
+ if ( agrid(i,j,1)>lon(im) ) then
+ i1 = im; i2 = 1
+ a1 = (agrid(i,j,1)-lon(im)) * rdlon(im)
+ elseif ( agrid(i,j,1)=lon(i0) .and. agrid(i,j,1)<=lon(i0+1) ) then
+ i1 = i0; i2 = i0+1
+ a1 = (agrid(i,j,1)-lon(i1)) * rdlon(i0)
+ go to 111
+ endif
+ enddo
+ endif
+111 continue
+
+ if ( agrid(i,j,2)lat(jm) ) then
+ jc = jm-1
+ b1 = 1.
+ else
+ do j0=1,jm-1
+ if ( agrid(i,j,2)>=lat(j0) .and. agrid(i,j,2)<=lat(j0+1) ) then
+ jc = j0
+ b1 = (agrid(i,j,2)-lat(jc)) * rdlat(jc)
+ go to 222
+ endif
+ enddo
+ endif
+222 continue
+
+ if ( a1<0.0 .or. a1>1.0 .or. b1<0.0 .or. b1>1.0 ) then
+ write(*,*) 'gid=', mpp_pe(), i,j,a1, b1
+ endif
+
+ s2c(i,j,1) = (1.-a1) * (1.-b1)
+ s2c(i,j,2) = a1 * (1.-b1)
+ s2c(i,j,3) = a1 * b1
+ s2c(i,j,4) = (1.-a1) * b1
+ id1(i,j) = i1
+ id2(i,j) = i2
+ jdc(i,j) = jc
+ enddo !i-loop
+5000 continue ! j-loop
+
+ end subroutine remap_coef
+
+
+ subroutine remap_scalar(im, jm, km, npz, nq, ncnst, ak0, bk0, psc, gzc, ta, qa, Atm)
+ type(fv_atmos_type), intent(inout) :: Atm
+ integer, intent(in):: im, jm, km, npz, nq, ncnst
+ real, intent(in):: ak0(km+1), bk0(km+1)
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je):: psc, gzc
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km):: ta
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km,ncnst):: qa
+! local:
+ real, dimension(Atm%bd%is:Atm%bd%ie,km):: tp
+ real, dimension(Atm%bd%is:Atm%bd%ie,km+1):: pe0, pn0
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz):: qn1
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz+1):: pe1, pn1
+ real(kind=R_GRID), dimension(2*km+1):: gz, pn
+ real pk0(km+1)
+ real qp(Atm%bd%is:Atm%bd%ie,km,ncnst)
+ real p1, p2, alpha, rdg
+ real(kind=R_GRID):: pst, pt0
+#ifdef MULTI_GASES
+ integer spfo, spfo2, spfo3
+#else
+ integer o3mr
+#endif
+ integer i,j,k, k2,l, iq
+ integer sphum, clwmr
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+
+ is = Atm%bd%is
+ ie = Atm%bd%ie
+ js = Atm%bd%js
+ je = Atm%bd%je
+ isd = Atm%bd%isd
+ ied = Atm%bd%ied
+ jsd = Atm%bd%jsd
+ jed = Atm%bd%jed
+
+ k2 = max(10, km/2)
+
+! nq is always 1
+ sphum = get_tracer_index(MODEL_ATMOS, 'sphum')
+
+ if (mpp_pe()==1) then
+ print *, 'sphum = ', sphum, ' ncnst=', ncnst
+ print *, 'T_is_Tv = ', T_is_Tv, ' zvir=', zvir, ' kappa=', kappa
+ endif
+
+ if ( sphum/=1 ) then
+ call mpp_error(FATAL,'SPHUM must be 1st tracer')
+ endif
+
+ call prt_maxmin('ZS_FV3', Atm%phis, is, ie, js, je, 3, 1, 1./grav)
+ call prt_maxmin('ZS_GFS', gzc, is, ie, js, je, 0, 1, 1./grav)
+ call prt_maxmin('PS_Data', psc, is, ie, js, je, 0, 1, 0.01)
+ call prt_maxmin('T_Data', ta, is, ie, js, je, 0, km, 1.)
+ call prt_maxmin('q_Data', qa(is:ie,js:je,1:km,1), is, ie, js, je, 0, km, 1.)
+
+ do 5000 j=js,je
+
+ do i=is,ie
+
+ do iq=1,ncnst
+ do k=1,km
+ qp(i,k,iq) = qa(i,j,k,iq)
+ enddo
+ enddo
+
+ if ( T_is_Tv ) then
+! The "T" field in NCEP analysis is actually virtual temperature (Larry H. post processing)
+! BEFORE 20051201
+ do k=1,km
+ tp(i,k) = ta(i,j,k)
+ enddo
+ else
+ do k=1,km
+#ifdef MULTI_GASES
+ tp(i,k) = ta(i,j,k)*virq(qp(i,k,:))
+#else
+ tp(i,k) = ta(i,j,k)*(1.+zvir*qp(i,k,sphum))
+#endif
+ enddo
+ endif
+! Tracers:
+
+ do k=1,km+1
+ pe0(i,k) = ak0(k) + bk0(k)*psc(i,j)
+ pn0(i,k) = log(pe0(i,k))
+ pk0(k) = pe0(i,k)**kappa
+ enddo
+! gzc is geopotential
+
+! Note the following line, gz is actully Z (from Jeff's data).
+ gz(km+1) = gzc(i,j)
+ do k=km,1,-1
+ gz(k) = gz(k+1) + rdgas*tp(i,k)*(pn0(i,k+1)-pn0(i,k))
+ enddo
+
+ do k=1,km+1
+ pn(k) = pn0(i,k)
+ enddo
+! Use log-p for interpolation/extrapolation
+! mirror image method:
+ do k=km+2, km+k2
+ l = 2*(km+1) - k
+ gz(k) = 2.*gz(km+1) - gz(l)
+ pn(k) = 2.*pn(km+1) - pn(l)
+ enddo
+ do k=km+k2-1, 2, -1
+ if( Atm%phis(i,j).le.gz(k) .and. Atm%phis(i,j).ge.gz(k+1) ) then
+ pst = pn(k) + (pn(k+1)-pn(k))*(gz(k)-Atm%phis(i,j))/(gz(k)-gz(k+1))
+ go to 123
+ endif
+ enddo
+123 Atm%ps(i,j) = exp(pst)
+ enddo ! i-loop
+
+ do i=is,ie
+ pe1(i,1) = Atm%ak(1)
+ pn1(i,1) = log(pe1(i,1))
+ enddo
+ do k=2,npz+1
+ do i=is,ie
+ pe1(i,k) = Atm%ak(k) + Atm%bk(k)*Atm%ps(i,j)
+ pn1(i,k) = log(pe1(i,k))
+ enddo
+ enddo
+
+! * Compute delp
+ do k=1,npz
+ do i=is,ie
+ Atm%delp(i,j,k) = pe1(i,k+1) - pe1(i,k)
+ enddo
+ enddo
+
+!---------------
+! map shpum, o3mr, clwmr tracers
+!----------------
+ do iq=1,ncnst
+ call mappm(km, pe0, qp(is,1,iq), npz, pe1, qn1, is,ie, 0, 11, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+ Atm%q(i,j,k,iq) = qn1(i,k)
+ enddo
+ enddo
+ enddo
+
+!-------------------------------------------------------------
+! map virtual temperature using geopotential conserving scheme.
+!-------------------------------------------------------------
+ call mappm(km, pn0, tp, npz, pn1, qn1, is,ie, 1, 9, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+#ifdef MULTI_GASES
+ Atm%pt(i,j,k) = qn1(i,k)/virq(Atm%q(i,j,k,:))
+#else
+ Atm%pt(i,j,k) = qn1(i,k)/(1.+zvir*Atm%q(i,j,k,sphum))
+#endif
+ enddo
+ enddo
+
+ if ( .not. Atm%flagstruct%hydrostatic .and. Atm%flagstruct%ncep_ic ) then
+! Replace delz with NCEP hydrostatic state
+ rdg = -rdgas / grav
+ do k=1,npz
+ do i=is,ie
+ atm%delz(i,j,k) = rdg*qn1(i,k)*(pn1(i,k+1)-pn1(i,k))
+ enddo
+ enddo
+ endif
+
+5000 continue
+
+ call prt_maxmin('PS_model', Atm%ps(is:ie,js:je), is, ie, js, je, 0, 1, 0.01)
+
+ if (is_master()) write(*,*) 'done remap_scalar'
+
+ end subroutine remap_scalar
+
+
+ subroutine remap_scalar_nggps(Atm, km, npz, ncnst, ak0, bk0, psc, t_in, qa, omga, zh)
+ type(fv_atmos_type), intent(inout) :: Atm
+ integer, intent(in):: km, npz, ncnst
+ real, intent(in):: ak0(km+1), bk0(km+1)
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je):: psc
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km):: t_in
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km):: omga
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km,ncnst):: qa
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km+1):: zh
+! local:
+ real, dimension(Atm%bd%is:Atm%bd%ie,km+1):: pe0
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz):: qn1, dp2
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz+1):: pe1
+ real qp(Atm%bd%is:Atm%bd%ie,km)
+ real wk(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je)
+ real, dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je):: z500
+!!! High-precision
+ real(kind=R_GRID), dimension(Atm%bd%is:Atm%bd%ie,npz+1):: pn1
+ real(kind=R_GRID):: gz_fv(npz+1)
+ real(kind=R_GRID), dimension(2*km+1):: gz, pn
+ real(kind=R_GRID), dimension(Atm%bd%is:Atm%bd%ie,km+1):: pn0
+ real(kind=R_GRID):: pst
+!!! High-precision
+ integer i,j,k,l,m, k2,iq
+ integer sphum, liq_wat, ice_wat, rainwat, snowwat, graupel, cld_amt, liq_aero, ice_aero
+#ifdef MULTI_GASES
+ integer spfo, spfo2, spfo3
+#else
+ integer o3mr
+#endif
+ integer :: is, ie, js, je
+
+ is = Atm%bd%is
+ ie = Atm%bd%ie
+ js = Atm%bd%js
+ je = Atm%bd%je
+
+ sphum = get_tracer_index(MODEL_ATMOS, 'sphum')
+ liq_wat = get_tracer_index(MODEL_ATMOS, 'liq_wat')
+ ice_wat = get_tracer_index(MODEL_ATMOS, 'ice_wat')
+ rainwat = get_tracer_index(MODEL_ATMOS, 'rainwat')
+ snowwat = get_tracer_index(MODEL_ATMOS, 'snowwat')
+ graupel = get_tracer_index(MODEL_ATMOS, 'graupel')
+ cld_amt = get_tracer_index(MODEL_ATMOS, 'cld_amt')
+#ifdef MULTI_GASES
+ spfo = get_tracer_index(MODEL_ATMOS, 'spfo')
+ spfo2 = get_tracer_index(MODEL_ATMOS, 'spfo2')
+ spfo3 = get_tracer_index(MODEL_ATMOS, 'spfo3')
+#else
+ o3mr = get_tracer_index(MODEL_ATMOS, 'o3mr')
+#endif
+ liq_aero = get_tracer_index(MODEL_ATMOS, 'liq_aero')
+ ice_aero = get_tracer_index(MODEL_ATMOS, 'ice_aero')
+
+ k2 = max(10, km/2)
+
+ if (mpp_pe()==1) then
+ print *, 'sphum = ', sphum
+ print *, 'clwmr = ', liq_wat
+#ifdef MULTI_GASES
+ print *, 'spfo3 = ', spfo3
+ print *, ' spfo = ', spfo
+ print *, 'spfo2 = ', spfo2
+#else
+ print *, ' o3mr = ', o3mr
+#endif
+ print *, 'liq_aero = ', liq_aero
+ print *, 'ice_aero = ', ice_aero
+ print *, 'ncnst = ', ncnst
+ endif
+
+ if ( sphum/=1 ) then
+ call mpp_error(FATAL,'SPHUM must be 1st tracer')
+ endif
+
+#ifdef USE_GFS_ZS
+ Atm%phis(is:ie,js:je) = zh(is:ie,js:je,km+1)*grav
+#endif
+
+!$OMP parallel do default(none) &
+!$OMP shared(sphum,liq_wat,rainwat,ice_wat,snowwat,graupel,liq_aero,ice_aero,source, &
+!$OMP cld_amt,ncnst,npz,is,ie,js,je,km,k2,ak0,bk0,psc,t_in,zh,omga,qa,Atm,z500) &
+!$OMP private(l,m,pst,pn,gz,pe0,pn0,pe1,pn1,dp2,qp,qn1,gz_fv)
+ do 5000 j=js,je
+ do k=1,km+1
+ do i=is,ie
+ pe0(i,k) = ak0(k) + bk0(k)*psc(i,j)
+ pn0(i,k) = log(pe0(i,k))
+ enddo
+ enddo
+
+ do i=is,ie
+ do k=1,km+1
+ pn(k) = pn0(i,k)
+ gz(k) = zh(i,j,k)*grav
+ enddo
+! Use log-p for interpolation/extrapolation
+! mirror image method:
+ do k=km+2, km+k2
+ l = 2*(km+1) - k
+ gz(k) = 2.*gz(km+1) - gz(l)
+ pn(k) = 2.*pn(km+1) - pn(l)
+ enddo
+
+ do k=km+k2-1, 2, -1
+ if( Atm%phis(i,j).le.gz(k) .and. Atm%phis(i,j).ge.gz(k+1) ) then
+ pst = pn(k) + (pn(k+1)-pn(k))*(gz(k)-Atm%phis(i,j))/(gz(k)-gz(k+1))
+ go to 123
+ endif
+ enddo
+123 Atm%ps(i,j) = exp(pst)
+
+! ------------------
+! Find 500-mb height
+! ------------------
+ pst = log(500.e2)
+ do k=km+k2-1, 2, -1
+ if( pst.le.pn(k+1) .and. pst.ge.pn(k) ) then
+ z500(i,j) = (gz(k+1) + (gz(k)-gz(k+1))*(pn(k+1)-pst)/(pn(k+1)-pn(k)))/grav
+ go to 124
+ endif
+ enddo
+124 continue
+
+ enddo ! i-loop
+
+ do i=is,ie
+ pe1(i,1) = Atm%ak(1)
+ pn1(i,1) = log(pe1(i,1))
+ enddo
+ do k=2,npz+1
+ do i=is,ie
+ pe1(i,k) = Atm%ak(k) + Atm%bk(k)*Atm%ps(i,j)
+ pn1(i,k) = log(pe1(i,k))
+ enddo
+ enddo
+
+! * Compute delp
+ do k=1,npz
+ do i=is,ie
+ dp2(i,k) = pe1(i,k+1) - pe1(i,k)
+ Atm%delp(i,j,k) = dp2(i,k)
+ enddo
+ enddo
+
+! map tracers
+ do iq=1,ncnst
+ do k=1,km
+ do i=is,ie
+ qp(i,k) = qa(i,j,k,iq)
+ enddo
+ enddo
+ call mappm(km, pe0, qp, npz, pe1, qn1, is,ie, 0, 8, Atm%ptop)
+ if ( iq==sphum ) then
+ call fillq(ie-is+1, npz, 1, qn1, dp2)
+ else
+ call fillz(ie-is+1, npz, 1, qn1, dp2)
+ endif
+! The HiRam step of blending model sphum with NCEP data is obsolete because nggps is always cold starting...
+ do k=1,npz
+ do i=is,ie
+ Atm%q(i,j,k,iq) = qn1(i,k)
+ enddo
+ enddo
+ enddo
+
+!---------------------------------------------------
+! Retrive temperature using GFS geopotential height
+!---------------------------------------------------
+ do i=is,ie
+! Make sure FV3 top is lower than GFS; can not do extrapolation above the top at this point
+ if ( pn1(i,1) .lt. pn0(i,1) ) then
+ call mpp_error(FATAL,'FV3 top higher than NCEP/GFS')
+ endif
+
+ do k=1,km+1
+ pn(k) = pn0(i,k)
+ gz(k) = zh(i,j,k)*grav
+ enddo
+!-------------------------------------------------
+ do k=km+2, km+k2
+ l = 2*(km+1) - k
+ gz(k) = 2.*gz(km+1) - gz(l)
+ pn(k) = 2.*pn(km+1) - pn(l)
+ enddo
+!-------------------------------------------------
+
+ gz_fv(npz+1) = Atm%phis(i,j)
+
+ m = 1
+
+ do k=1,npz
+! Searching using FV3 log(pe): pn1
+#ifdef USE_ISOTHERMO
+ do l=m,km
+ if ( (pn1(i,k).le.pn(l+1)) .and. (pn1(i,k).ge.pn(l)) ) then
+ gz_fv(k) = gz(l) + (gz(l+1)-gz(l))*(pn1(i,k)-pn(l))/(pn(l+1)-pn(l))
+ goto 555
+ elseif ( pn1(i,k) .gt. pn(km+1) ) then
+! Isothermal under ground; linear in log-p extra-polation
+ gz_fv(k) = gz(km+1) + (gz_fv(npz+1)-gz(km+1))*(pn1(i,k)-pn(km+1))/(pn1(i,npz+1)-pn(km+1))
+ goto 555
+ endif
+ enddo
+#else
+ do l=m,km+k2-1
+ if ( (pn1(i,k).le.pn(l+1)) .and. (pn1(i,k).ge.pn(l)) ) then
+ gz_fv(k) = gz(l) + (gz(l+1)-gz(l))*(pn1(i,k)-pn(l))/(pn(l+1)-pn(l))
+ goto 555
+ endif
+ enddo
+#endif
+555 m = l
+ enddo
+
+ do k=1,npz+1
+ Atm%peln(i,k,j) = pn1(i,k)
+ enddo
+
+!----------------------------------------------------
+! Compute true temperature using hydrostatic balance
+!----------------------------------------------------
+ if (trim(source) /= 'FV3GFS GAUSSIAN NEMSIO FILE') then
+ do k=1,npz
+#ifdef MULTI_GASES
+ Atm%pt(i,j,k) = (gz_fv(k)-gz_fv(k+1))/( rdgas*(pn1(i,k+1)-pn1(i,k))*virq(Atm%q(i,j,k,:)) )
+#else
+ Atm%pt(i,j,k) = (gz_fv(k)-gz_fv(k+1))/( rdgas*(pn1(i,k+1)-pn1(i,k))*(1.+zvir*Atm%q(i,j,k,sphum)) )
+#endif
+ enddo
+!------------------------------
+! Remap input T linearly in p.
+!------------------------------
+ else
+ do k=1,km
+ qp(i,k) = t_in(i,j,k)
+ enddo
+
+ call mappm(km, pe0, qp, npz, pe1, qn1, is,ie, 2, 4, Atm%ptop)
+
+ do k=1,npz
+ Atm%pt(i,j,k) = qn1(i,k)
+ enddo
+ endif
+
+ if ( .not. Atm%flagstruct%hydrostatic ) then
+ do k=1,npz
+ Atm%delz(i,j,k) = (gz_fv(k+1) - gz_fv(k)) / grav
+ enddo
+ endif
+
+ enddo ! i-loop
+
+!-----------------------------------------------------------------------
+! seperate cloud water and cloud ice
+! From Jan-Huey Chen's HiRAM code
+!-----------------------------------------------------------------------
+ if (cld_amt .gt. 0) Atm%q(:,:,:,cld_amt) = 0.
+ if (trim(source) /= 'FV3GFS GAUSSIAN NEMSIO FILE') then
+ if ( Atm%flagstruct%nwat .eq. 6 ) then
+ do k=1,npz
+ do i=is,ie
+ qn1(i,k) = Atm%q(i,j,k,liq_wat)
+ Atm%q(i,j,k,rainwat) = 0.
+ Atm%q(i,j,k,snowwat) = 0.
+ Atm%q(i,j,k,graupel) = 0.
+! if (cld_amt .gt. 0) Atm%q(i,j,k,cld_amt) = 0.
+ if ( Atm%pt(i,j,k) > 273.16 ) then ! > 0C all liq_wat
+ Atm%q(i,j,k,liq_wat) = qn1(i,k)
+ Atm%q(i,j,k,ice_wat) = 0.
+#ifdef ORIG_CLOUDS_PART
+ else if ( Atm%pt(i,j,k) < 258.16 ) then ! < -15C all ice_wat
+ Atm%q(i,j,k,liq_wat) = 0.
+ Atm%q(i,j,k,ice_wat) = qn1(i,k)
+ else ! between -15~0C: linear interpolation
+ Atm%q(i,j,k,liq_wat) = qn1(i,k)*((Atm%pt(i,j,k)-258.16)/15.)
+ Atm%q(i,j,k,ice_wat) = qn1(i,k) - Atm%q(i,j,k,liq_wat)
+ endif
+#else
+ else if ( Atm%pt(i,j,k) < 233.16 ) then ! < -40C all ice_wat
+ Atm%q(i,j,k,liq_wat) = 0.
+ Atm%q(i,j,k,ice_wat) = qn1(i,k)
+ else
+ if ( k.eq.1 ) then ! between [-40,0]: linear interpolation
+ Atm%q(i,j,k,liq_wat) = qn1(i,k)*((Atm%pt(i,j,k)-233.16)/40.)
+ Atm%q(i,j,k,ice_wat) = qn1(i,k) - Atm%q(i,j,k,liq_wat)
+ else
+ if (Atm%pt(i,j,k)<258.16 .and. Atm%q(i,j,k-1,ice_wat)>1.e-5 ) then
+ Atm%q(i,j,k,liq_wat) = 0.
+ Atm%q(i,j,k,ice_wat) = qn1(i,k)
+ else ! between [-40,0]: linear interpolation
+ Atm%q(i,j,k,liq_wat) = qn1(i,k)*((Atm%pt(i,j,k)-233.16)/40.)
+ Atm%q(i,j,k,ice_wat) = qn1(i,k) - Atm%q(i,j,k,liq_wat)
+ endif
+ endif
+ endif
+#endif
+ call mp_auto_conversion(Atm%q(i,j,k,liq_wat), Atm%q(i,j,k,rainwat), &
+ Atm%q(i,j,k,ice_wat), Atm%q(i,j,k,snowwat) )
+ enddo
+ enddo
+ endif
+ endif ! data source /= FV3GFS GAUSSIAN NEMSIO FILE
+
+! For GFS spectral input, omega in pa/sec is stored as w in the input data so actual w(m/s) is calculated
+! For GFS nemsio input, omega is 0, so best not to use for input since boundary data will not exist for w
+! For FV3GFS NEMSIO input, w is already in m/s (but the code reads in as omga) and just needs to be remapped
+!-------------------------------------------------------------
+! map omega
+!------- ------------------------------------------------------
+ if ( .not. Atm%flagstruct%hydrostatic ) then
+ do k=1,km
+ do i=is,ie
+ qp(i,k) = omga(i,j,k)
+ enddo
+ enddo
+ call mappm(km, pe0, qp, npz, pe1, qn1, is,ie, -1, 4, Atm%ptop)
+ if (trim(source) == 'FV3GFS GAUSSIAN NEMSIO FILE') then
+ do k=1,npz
+ do i=is,ie
+ atm%w(i,j,k) = qn1(i,k)
+ enddo
+ enddo
+
+ else
+ do k=1,npz
+ do i=is,ie
+ atm%w(i,j,k) = qn1(i,k)/atm%delp(i,j,k)*atm%delz(i,j,k)
+ enddo
+ enddo
+ endif
+ endif !.not. Atm%flagstruct%hydrostatic
+5000 continue
+
+! Add some diagnostics:
+ call p_maxmin('PS_model (mb)', Atm%ps(is:ie,js:je), is, ie, js, je, 1, 0.01)
+ call p_maxmin('PT_model', Atm%pt(is:ie,js:je,1:npz), is, ie, js, je, npz, 1.)
+ do j=js,je
+ do i=is,ie
+ wk(i,j) = Atm%phis(i,j)/grav - zh(i,j,km+1)
+ enddo
+ enddo
+ call pmaxmn('ZS_diff (m)', wk, is, ie, js, je, 1, 1., Atm%gridstruct%area_64, Atm%domain)
+
+ if (.not.Atm%neststruct%nested) then
+ call prt_gb_nh_sh('GFS_IC Z500', is,ie, js,je, z500, Atm%gridstruct%area_64(is:ie,js:je), Atm%gridstruct%agrid_64(is:ie,js:je,2))
+ if ( .not. Atm%flagstruct%hydrostatic ) &
+ call prt_height('fv3_IC Z500', is,ie, js,je, 3, npz, 500.E2, Atm%phis, Atm%delz, Atm%peln, &
+ Atm%gridstruct%area_64(is:ie,js:je), Atm%gridstruct%agrid_64(is:ie,js:je,2))
+ endif
+
+ do j=js,je
+ do i=is,ie
+ wk(i,j) = Atm%ps(i,j) - psc(i,j)
+ enddo
+ enddo
+ call pmaxmn('PS_diff (mb)', wk, is, ie, js, je, 1, 0.01, Atm%gridstruct%area_64, Atm%domain)
+
+ if (is_master()) write(*,*) 'done remap_scalar_nggps'
+
+ end subroutine remap_scalar_nggps
+
+ subroutine remap_scalar_ec(Atm, km, npz, ncnst, ak0, bk0, psc, qa, wc, zh)
+ type(fv_atmos_type), intent(inout) :: Atm
+ integer, intent(in):: km, npz, ncnst
+ real, intent(in):: ak0(km+1), bk0(km+1)
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je):: psc
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km):: wc
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km,ncnst):: qa
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km+1):: zh
+! local:
+ real, dimension(Atm%bd%is:Atm%bd%ie,km+1):: pe0
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz):: qn1, dp2
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz+1):: pe1
+ real qp(Atm%bd%is:Atm%bd%ie,km)
+ real wk(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je)
+!!! High-precision
+ real(kind=R_GRID), dimension(Atm%bd%is:Atm%bd%ie,npz+1):: pn1
+ real(kind=R_GRID):: gz_fv(npz+1)
+ real(kind=R_GRID), dimension(2*km+1):: gz, pn
+ real(kind=R_GRID), dimension(Atm%bd%is:Atm%bd%ie,km+1):: pn0
+ real(kind=R_GRID):: pst
+ real, dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je):: z500
+!!! High-precision
+ integer:: sphum, liq_wat, ice_wat, rainwat, snowwat, graupel, cld_amt
+#ifdef MULTI_GASES
+ integer:: spfo, spfo2, spfo3
+#else
+ integer:: o3mr
+#endif
+ integer:: i,j,k,l,m,k2, iq
+ integer:: is, ie, js, je
+
+ is = Atm%bd%is
+ ie = Atm%bd%ie
+ js = Atm%bd%js
+ je = Atm%bd%je
+
+ sphum = get_tracer_index(MODEL_ATMOS, 'sphum')
+ liq_wat = get_tracer_index(MODEL_ATMOS, 'liq_wat')
+
+ if ( Atm%flagstruct%nwat .eq. 6 ) then
+ ice_wat = get_tracer_index(MODEL_ATMOS, 'ice_wat')
+ rainwat = get_tracer_index(MODEL_ATMOS, 'rainwat')
+ snowwat = get_tracer_index(MODEL_ATMOS, 'snowwat')
+ graupel = get_tracer_index(MODEL_ATMOS, 'graupel')
+ cld_amt = get_tracer_index(MODEL_ATMOS, 'cld_amt')
+ endif
+ if (cld_amt .gt. 0) Atm%q(:,:,:,cld_amt) = 0.
+
+ k2 = max(10, km/2)
+
+ if (mpp_pe()==1) then
+ print *, 'In remap_scalar_ec:'
+ print *, 'ncnst = ', ncnst
+ print *, 'sphum = ', sphum
+ print *, 'liq_wat = ', liq_wat
+ if ( Atm%flagstruct%nwat .eq. 6 ) then
+ print *, 'rainwat = ', rainwat
+ print *, 'ice_wat = ', ice_wat
+ print *, 'snowwat = ', snowwat
+ print *, 'graupel = ', graupel
+ endif
+ endif
+
+!$OMP parallel do default(none) shared(sphum,ncnst,npz,is,ie,js,je,km,k2,ak0,bk0,psc,zh,qa,wc,Atm,z500) &
+!$OMP private(l,m,pst,pn,gz,pe0,pn0,pe1,pn1,dp2,qp,qn1,gz_fv)
+ do 5000 j=js,je
+ do k=1,km+1
+ do i=is,ie
+ pe0(i,k) = ak0(k) + bk0(k)*psc(i,j)
+ pn0(i,k) = log(pe0(i,k))
+ enddo
+ enddo
+
+ do i=is,ie
+ do k=1,km+1
+ pn(k) = pn0(i,k)
+ gz(k) = zh(i,j,k)*grav
+ enddo
+! Use log-p for interpolation/extrapolation
+! mirror image method:
+ do k=km+2, km+k2
+ l = 2*(km+1) - k
+ gz(k) = 2.*gz(km+1) - gz(l)
+ pn(k) = 2.*pn(km+1) - pn(l)
+ enddo
+
+ do k=km+k2-1, 2, -1
+ if( Atm%phis(i,j).le.gz(k) .and. Atm%phis(i,j).ge.gz(k+1) ) then
+ pst = pn(k) + (pn(k+1)-pn(k))*(gz(k)-Atm%phis(i,j))/(gz(k)-gz(k+1))
+ go to 123
+ endif
+ enddo
+123 Atm%ps(i,j) = exp(pst)
+
+! ------------------
+! Find 500-mb height
+! ------------------
+ pst = log(500.e2)
+ do k=km+k2-1, 2, -1
+ if( pst.le.pn(k+1) .and. pst.ge.pn(k) ) then
+ z500(i,j) = (gz(k+1) + (gz(k)-gz(k+1))*(pn(k+1)-pst)/(pn(k+1)-pn(k)))/grav
+ go to 125
+ endif
+ enddo
+125 continue
+
+ enddo ! i-loop
+
+ do i=is,ie
+ pe1(i,1) = Atm%ak(1)
+ pn1(i,1) = log(pe1(i,1))
+ enddo
+ do k=2,npz+1
+ do i=is,ie
+ pe1(i,k) = Atm%ak(k) + Atm%bk(k)*Atm%ps(i,j)
+ pn1(i,k) = log(pe1(i,k))
+ enddo
+ enddo
+
+! * Compute delp
+ do k=1,npz
+ do i=is,ie
+ dp2(i,k) = pe1(i,k+1) - pe1(i,k)
+ Atm%delp(i,j,k) = dp2(i,k)
+ enddo
+ enddo
+
+! map shpum, liq_wat, ice_wat, rainwat, snowwat tracers
+ do iq=1,ncnst
+ do k=1,km
+ do i=is,ie
+ qp(i,k) = qa(i,j,k,iq)
+ enddo
+ enddo
+ call mappm(km, pe0, qp, npz, pe1, qn1, is,ie, 0, 8, Atm%ptop)
+ if ( iq==1 ) then
+ call fillq(ie-is+1, npz, 1, qn1, dp2)
+ else
+ call fillz(ie-is+1, npz, 1, qn1, dp2)
+ endif
+! The HiRam step of blending model sphum with NCEP data is obsolete because nggps is always cold starting...
+ do k=1,npz
+ do i=is,ie
+ Atm%q(i,j,k,iq) = qn1(i,k)
+ enddo
+ enddo
+ enddo
+!---------------------------------------------------
+! Retrive temperature using EC geopotential height
+!---------------------------------------------------
+ do i=is,ie
+! Make sure FV3 top is lower than GFS; can not do extrapolation above the top at this point
+ if ( pn1(i,1) .lt. pn0(i,1) ) then
+ call mpp_error(FATAL,'FV3 top higher than ECMWF')
+ endif
+
+ do k=1,km+1
+ pn(k) = pn0(i,k)
+ gz(k) = zh(i,j,k)*grav
+ enddo
+!-------------------------------------------------
+ do k=km+2, km+k2
+ l = 2*(km+1) - k
+ gz(k) = 2.*gz(km+1) - gz(l)
+ pn(k) = 2.*pn(km+1) - pn(l)
+ enddo
+!-------------------------------------------------
+ gz_fv(npz+1) = Atm%phis(i,j)
+
+ m = 1
+ do k=1,npz
+! Searching using FV3 log(pe): pn1
+#ifdef USE_ISOTHERMO
+ do l=m,km
+ if ( (pn1(i,k).le.pn(l+1)) .and. (pn1(i,k).ge.pn(l)) ) then
+ gz_fv(k) = gz(l) + (gz(l+1)-gz(l))*(pn1(i,k)-pn(l))/(pn(l+1)-pn(l))
+ goto 555
+ elseif ( pn1(i,k) .gt. pn(km+1) ) then
+! Isothermal under ground; linear in log-p extra-polation
+ gz_fv(k) = gz(km+1) + (gz_fv(npz+1)-gz(km+1))*(pn1(i,k)-pn(km+1))/(pn1(i,npz+1)-pn(km+1))
+ goto 555
+ endif
+ enddo
+#else
+ do l=m,km+k2-1
+ if ( (pn1(i,k).le.pn(l+1)) .and. (pn1(i,k).ge.pn(l)) ) then
+ gz_fv(k) = gz(l) + (gz(l+1)-gz(l))*(pn1(i,k)-pn(l))/(pn(l+1)-pn(l))
+ goto 555
+ endif
+ enddo
+#endif
+555 m = l
+ enddo
+
+ do k=1,npz+1
+ Atm%peln(i,k,j) = pn1(i,k)
+ enddo
+
+! Compute true temperature using hydrostatic balance
+ do k=1,npz
+! qc = 1.-(Atm%q(i,j,k,liq_wat)+Atm%q(i,j,k,rainwat)+Atm%q(i,j,k,ice_wat)+Atm%q(i,j,k,snowwat))
+! Atm%pt(i,j,k) = (gz_fv(k)-gz_fv(k+1))*qc/( rdgas*(pn1(i,k+1)-pn1(i,k))*(1.+zvir*Atm%q(i,j,k,sphum)) )
+#ifdef MULTI_GASES
+ Atm%pt(i,j,k) = (gz_fv(k)-gz_fv(k+1))/( rdgas*(pn1(i,k+1)-pn1(i,k))*virq(Atm%q(i,j,k,:)) )
+#else
+ Atm%pt(i,j,k) = (gz_fv(k)-gz_fv(k+1))/( rdgas*(pn1(i,k+1)-pn1(i,k))*(1.+zvir*Atm%q(i,j,k,sphum)) )
+#endif
+ enddo
+ if ( .not. Atm%flagstruct%hydrostatic ) then
+ do k=1,npz
+ Atm%delz(i,j,k) = (gz_fv(k+1) - gz_fv(k)) / grav
+ enddo
+ endif
+
+ enddo ! i-loop
+
+!-------------------------------------------------------------
+! map omega
+!------- ------------------------------------------------------
+ if ( .not. Atm%flagstruct%hydrostatic ) then
+ do k=1,km
+ do i=is,ie
+ qp(i,k) = wc(i,j,k)
+ enddo
+ enddo
+ call mappm(km, pe0, qp, npz, pe1, qn1, is,ie, -1, 4, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+ atm%w(i,j,k) = qn1(i,k)/atm%delp(i,j,k)*atm%delz(i,j,k)
+ enddo
+ enddo
+ endif
+
+5000 continue
+
+! Add some diagnostics:
+ call p_maxmin('PS_model (mb)', Atm%ps(is:ie,js:je), is, ie, js, je, 1, 0.01)
+ call p_maxmin('PT_model', Atm%pt(is:ie,js:je,1:npz), is, ie, js, je, npz, 1.)
+ call pmaxmn('ZS_model', Atm%phis(is:ie,js:je)/grav, is, ie, js, je, 1, 1., Atm%gridstruct%area_64, Atm%domain)
+ call pmaxmn('ZS_EC', zh(is:ie,js:je,km+1), is, ie, js, je, 1, 1., Atm%gridstruct%area_64, Atm%domain)
+ do j=js,je
+ do i=is,ie
+ wk(i,j) = Atm%phis(i,j)/grav - zh(i,j,km+1)
+ ! if ((wk(i,j) > 1800.).or.(wk(i,j)<-1600.)) then
+ ! print *,' '
+ ! print *, 'Diff = ', wk(i,j), 'Atm%phis =', Atm%phis(i,j)/grav, 'zh = ', zh(i,j,km+1)
+ ! print *, 'lat = ', Atm%gridstruct%agrid(i,j,2)/deg2rad, 'lon = ', Atm%gridstruct%agrid(i,j,1)/deg2rad
+ ! endif
+ enddo
+ enddo
+ call pmaxmn('ZS_diff (m)', wk, is, ie, js, je, 1, 1., Atm%gridstruct%area_64, Atm%domain)
+
+ if (.not.Atm%neststruct%nested) then
+ call prt_gb_nh_sh('IFS_IC Z500', is,ie, js,je, z500, Atm%gridstruct%area_64(is:ie,js:je), Atm%gridstruct%agrid_64(is:ie,js:je,2))
+ if ( .not. Atm%flagstruct%hydrostatic ) &
+ call prt_height('fv3_IC Z500', is,ie, js,je, 3, npz, 500.E2, Atm%phis, Atm%delz, Atm%peln, &
+ Atm%gridstruct%area_64(is:ie,js:je), Atm%gridstruct%agrid_64(is:ie,js:je,2))
+ endif
+
+ do j=js,je
+ do i=is,ie
+ wk(i,j) = Atm%ps(i,j) - psc(i,j)
+ enddo
+ enddo
+ call pmaxmn('PS_diff (mb)', wk, is, ie, js, je, 1, 0.01, Atm%gridstruct%area_64, Atm%domain)
+
+ end subroutine remap_scalar_ec
+
+ subroutine remap_scalar_single(Atm, km, npz, ak0, bk0, psc, qa, zh ,iq)
+ type(fv_atmos_type), intent(inout) :: Atm
+ integer, intent(in):: km, npz, iq
+ real, intent(in):: ak0(km+1), bk0(km+1)
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je):: psc
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km):: qa
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km+1):: zh
+! local:
+ real, dimension(Atm%bd%is:Atm%bd%ie,km+1):: pe0
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz):: qn1, dp2
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz+1):: pe1
+ real qp(Atm%bd%is:Atm%bd%ie,km)
+ real wk(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je)
+!!! High-precision
+ real(kind=R_GRID), dimension(Atm%bd%is:Atm%bd%ie,npz+1):: pn1
+ real(kind=R_GRID):: gz_fv(npz+1)
+ real(kind=R_GRID), dimension(2*km+1):: gz, pn
+ real(kind=R_GRID), dimension(Atm%bd%is:Atm%bd%ie,km+1):: pn0
+ real(kind=R_GRID):: pst
+!!! High-precision
+ integer i,j,k, k2, l
+ integer :: is, ie, js, je
+ real, allocatable:: ps_temp(:,:)
+
+ is = Atm%bd%is
+ ie = Atm%bd%ie
+ js = Atm%bd%js
+ je = Atm%bd%je
+
+ k2 = max(10, km/2)
+
+ allocate(ps_temp(is:ie,js:je))
+
+ do 5000 j=js,je
+ do k=1,km+1
+ do i=is,ie
+ pe0(i,k) = ak0(k) + bk0(k)*psc(i,j)
+ pn0(i,k) = log(pe0(i,k))
+ enddo
+ enddo
+
+ do i=is,ie
+ do k=1,km+1
+ pn(k) = pn0(i,k)
+ gz(k) = zh(i,j,k)*grav
+ enddo
+! Use log-p for interpolation/extrapolation
+! mirror image method:
+ do k=km+2, km+k2
+ l = 2*(km+1) - k
+ gz(k) = 2.*gz(km+1) - gz(l)
+ pn(k) = 2.*pn(km+1) - pn(l)
+ enddo
+
+ do k=km+k2-1, 2, -1
+ if( Atm%phis(i,j).le.gz(k) .and. Atm%phis(i,j).ge.gz(k+1) ) then
+ pst = pn(k) + (pn(k+1)-pn(k))*(gz(k)-Atm%phis(i,j))/(gz(k)-gz(k+1))
+ go to 123
+ endif
+ enddo
+123 ps_temp(i,j) = exp(pst)
+ enddo ! i-loop
+
+ do i=is,ie
+ pe1(i,1) = Atm%ak(1)
+ pn1(i,1) = log(pe1(i,1))
+ enddo
+ do k=2,npz+1
+ do i=is,ie
+ pe1(i,k) = Atm%ak(k) + Atm%bk(k)*ps_temp(i,j)
+ pn1(i,k) = log(pe1(i,k))
+ enddo
+ enddo
+
+! * Compute delp
+ do k=1,npz
+ do i=is,ie
+ dp2(i,k) = pe1(i,k+1) - pe1(i,k)
+ enddo
+ enddo
+
+ ! map o3mr
+ do k=1,km
+ do i=is,ie
+ qp(i,k) = qa(i,j,k)
+ enddo
+ enddo
+ call mappm(km, pe0, qp, npz, pe1, qn1, is,ie, 0, 8, Atm%ptop)
+ if ( iq==1 ) then
+ call fillq(ie-is+1, npz, 1, qn1, dp2)
+ else
+ call fillz(ie-is+1, npz, 1, qn1, dp2)
+ endif
+! The HiRam step of blending model sphum with NCEP data is obsolete because nggps is always cold starting...
+ do k=1,npz
+ do i=is,ie
+ Atm%q(i,j,k,iq) = qn1(i,k)
+ enddo
+ enddo
+
+5000 continue
+ call p_maxmin('o3mr remap', Atm%q(is:ie,js:je,1:npz,iq), is, ie, js, je, npz, 1.)
+
+ deallocate(ps_temp)
+
+ end subroutine remap_scalar_single
+
+
+ subroutine mp_auto_conversion(ql, qr, qi, qs)
+ real, intent(inout):: ql, qr, qi, qs
+ real, parameter:: qi0_max = 2.0e-3
+ real, parameter:: ql0_max = 2.5e-3
+
+! Convert excess cloud water into rain:
+ if ( ql > ql0_max ) then
+ qr = ql - ql0_max
+ ql = ql0_max
+ endif
+! Convert excess cloud ice into snow:
+ if ( qi > qi0_max ) then
+ qs = qi - qi0_max
+ qi = qi0_max
+ endif
+
+ end subroutine mp_auto_conversion
+
+
+ subroutine remap_dwinds(km, npz, ak0, bk0, psc, ud, vd, Atm)
+ type(fv_atmos_type), intent(inout) :: Atm
+ integer, intent(in):: km, npz
+ real, intent(in):: ak0(km+1), bk0(km+1)
+ real, intent(in):: psc(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je)
+ real, intent(in):: ud(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je+1,km)
+ real, intent(in):: vd(Atm%bd%is:Atm%bd%ie+1,Atm%bd%js:Atm%bd%je,km)
+! local:
+ real, dimension(Atm%bd%isd:Atm%bd%ied,Atm%bd%jsd:Atm%bd%jed):: psd
+ real, dimension(Atm%bd%is:Atm%bd%ie+1, km+1):: pe0
+ real, dimension(Atm%bd%is:Atm%bd%ie+1,npz+1):: pe1
+ real, dimension(Atm%bd%is:Atm%bd%ie+1,npz):: qn1
+ integer i,j,k
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+
+ is = Atm%bd%is
+ ie = Atm%bd%ie
+ js = Atm%bd%js
+ je = Atm%bd%je
+ isd = Atm%bd%isd
+ ied = Atm%bd%ied
+ jsd = Atm%bd%jsd
+ jed = Atm%bd%jed
+
+ if (Atm%neststruct%nested .or. Atm%flagstruct%regional) then
+ do j=jsd,jed
+ do i=isd,ied
+ psd(i,j) = Atm%ps(i,j)
+ enddo
+ enddo
+ else
+ do j=js,je
+ do i=is,ie
+ psd(i,j) = psc(i,j)
+ enddo
+ enddo
+ endif
+ call mpp_update_domains( psd, Atm%domain, complete=.false. )
+ call mpp_update_domains( Atm%ps, Atm%domain, complete=.true. )
+
+!$OMP parallel do default(none) shared(is,ie,js,je,npz,km,ak0,bk0,Atm,psc,psd,ud,vd) &
+!$OMP private(pe1,pe0,qn1)
+ do 5000 j=js,je+1
+!------
+! map u
+!------
+ do k=1,km+1
+ do i=is,ie
+ pe0(i,k) = ak0(k) + bk0(k)*0.5*(psd(i,j-1)+psd(i,j))
+ enddo
+ enddo
+ do k=1,npz+1
+ do i=is,ie
+ pe1(i,k) = Atm%ak(k) + Atm%bk(k)*0.5*(Atm%ps(i,j-1)+Atm%ps(i,j))
+ enddo
+ enddo
+ call mappm(km, pe0(is:ie,1:km+1), ud(is:ie,j,1:km), npz, pe1(is:ie,1:npz+1), &
+ qn1(is:ie,1:npz), is,ie, -1, 8, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+ Atm%u(i,j,k) = qn1(i,k)
+ enddo
+ enddo
+!------
+! map v
+!------
+ if ( j/=(je+1) ) then
+
+ do k=1,km+1
+ do i=is,ie+1
+ pe0(i,k) = ak0(k) + bk0(k)*0.5*(psd(i-1,j)+psd(i,j))
+ enddo
+ enddo
+ do k=1,npz+1
+ do i=is,ie+1
+ pe1(i,k) = Atm%ak(k) + Atm%bk(k)*0.5*(Atm%ps(i-1,j)+Atm%ps(i,j))
+ enddo
+ enddo
+ call mappm(km, pe0(is:ie+1,1:km+1), vd(is:ie+1,j,1:km), npz, pe1(is:ie+1,1:npz+1), &
+ qn1(is:ie+1,1:npz), is,ie+1, -1, 8, Atm%ptop)
+ do k=1,npz
+ do i=is,ie+1
+ Atm%v(i,j,k) = qn1(i,k)
+ enddo
+ enddo
+
+ endif
+
+5000 continue
+
+ if (is_master()) write(*,*) 'done remap_dwinds'
+
+ end subroutine remap_dwinds
+
+
+ subroutine remap_winds(im, jm, km, npz, ak0, bk0, psc, ua, va, Atm)
+ type(fv_atmos_type), intent(inout) :: Atm
+ integer, intent(in):: im, jm, km, npz
+ real, intent(in):: ak0(km+1), bk0(km+1)
+ real, intent(in):: psc(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je)
+ real, intent(in), dimension(Atm%bd%is:Atm%bd%ie,Atm%bd%js:Atm%bd%je,km):: ua, va
+! local:
+ real, dimension(Atm%bd%isd:Atm%bd%ied,Atm%bd%jsd:Atm%bd%jed,npz):: ut, vt ! winds
+ real, dimension(Atm%bd%is:Atm%bd%ie, km+1):: pe0
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz+1):: pe1
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz):: qn1
+ integer i,j,k
+
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+
+ is = Atm%bd%is
+ ie = Atm%bd%ie
+ js = Atm%bd%js
+ je = Atm%bd%je
+ isd = Atm%bd%isd
+ ied = Atm%bd%ied
+ jsd = Atm%bd%jsd
+ jed = Atm%bd%jed
+
+ do 5000 j=js,je
+
+ do k=1,km+1
+ do i=is,ie
+ pe0(i,k) = ak0(k) + bk0(k)*psc(i,j)
+ enddo
+ enddo
+
+ do k=1,npz+1
+ do i=is,ie
+ pe1(i,k) = Atm%ak(k) + Atm%bk(k)*Atm%ps(i,j)
+ enddo
+ enddo
+
+!------
+! map u
+!------
+ call mappm(km, pe0, ua(is:ie,j,1:km), npz, pe1, qn1, is,ie, -1, 8, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+ ut(i,j,k) = qn1(i,k)
+ enddo
+ enddo
+!------
+! map v
+!------
+ call mappm(km, pe0, va(is:ie,j,1:km), npz, pe1, qn1, is,ie, -1, 8, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+ vt(i,j,k) = qn1(i,k)
+ enddo
+ enddo
+
+5000 continue
+
+ call prt_maxmin('UT', ut, is, ie, js, je, ng, npz, 1.)
+ call prt_maxmin('VT', vt, is, ie, js, je, ng, npz, 1.)
+ call prt_maxmin('UA_top',ut(:,:,1), is, ie, js, je, ng, 1, 1.)
+
+!----------------------------------------------
+! winds: lat-lon ON A to Cubed-D transformation:
+!----------------------------------------------
+ call cubed_a2d(Atm%npx, Atm%npy, npz, ut, vt, Atm%u, Atm%v, Atm%gridstruct, Atm%domain, Atm%bd )
+
+ if (is_master()) write(*,*) 'done remap_winds'
+
+ end subroutine remap_winds
+
+
+ subroutine remap_xyz( im, jbeg, jend, jm, km, npz, nq, ncnst, lon, lat, ak0, bk0, ps0, gz0, &
+ ua, va, ta, qa, Atm )
+
+ type(fv_atmos_type), intent(inout), target :: Atm
+ integer, intent(in):: im, jm, km, npz, nq, ncnst
+ integer, intent(in):: jbeg, jend
+ real, intent(in):: lon(im), lat(jm), ak0(km+1), bk0(km+1)
+ real, intent(in):: gz0(im,jbeg:jend), ps0(im,jbeg:jend)
+ real, intent(in), dimension(im,jbeg:jend,km):: ua, va, ta
+ real, intent(in), dimension(im,jbeg:jend,km,ncnst):: qa
+
+ real, pointer, dimension(:,:,:) :: agrid
+
+! local:
+ real, dimension(Atm%bd%isd:Atm%bd%ied,Atm%bd%jsd:Atm%bd%jed,npz):: ut, vt ! winds
+ real, dimension(Atm%bd%is:Atm%bd%ie,km):: up, vp, tp
+ real, dimension(Atm%bd%is:Atm%bd%ie,km+1):: pe0, pn0
+ real pt0(km), gz(km+1), pk0(km+1)
+ real qp(Atm%bd%is:Atm%bd%ie,km,ncnst)
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz):: qn1
+ real, dimension(Atm%bd%is:Atm%bd%ie,npz+1):: pe1, pn1
+ real :: rdlon(im)
+ real :: rdlat(jm)
+ real:: a1, b1, c1, c2, c3, c4
+ real:: gzc, psc, pst
+#ifdef MULTI_GASES
+ real:: kappax, pkx
+#endif
+ integer i,j,k, i1, i2, jc, i0, j0, iq
+! integer sphum, liq_wat, ice_wat, cld_amt
+ integer sphum
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+
+ is = Atm%bd%is
+ ie = Atm%bd%ie
+ js = Atm%bd%js
+ je = Atm%bd%je
+ isd = Atm%bd%isd
+ ied = Atm%bd%ied
+ jsd = Atm%bd%jsd
+ jed = Atm%bd%jed
+
+ !!NOTE: Only Atm is used in this routine.
+ agrid => Atm%gridstruct%agrid
+
+ sphum = get_tracer_index(MODEL_ATMOS, 'sphum')
+
+ if ( sphum/=1 ) then
+ call mpp_error(FATAL,'SPHUM must be 1st tracer')
+ endif
+
+ pk0(1) = ak0(1)**kappa
+
+ do i=1,im-1
+ rdlon(i) = 1. / (lon(i+1) - lon(i))
+ enddo
+ rdlon(im) = 1. / (lon(1) + 2.*pi - lon(im))
+
+ do j=1,jm-1
+ rdlat(j) = 1. / (lat(j+1) - lat(j))
+ enddo
+
+! * Interpolate to cubed sphere cell center
+ do 5000 j=js,je
+
+ do i=is,ie
+ pe0(i,1) = ak0(1)
+ pn0(i,1) = log(ak0(1))
+ enddo
+
+
+ do i=is,ie
+
+ if ( agrid(i,j,1)>lon(im) ) then
+ i1 = im; i2 = 1
+ a1 = (agrid(i,j,1)-lon(im)) * rdlon(im)
+ elseif ( agrid(i,j,1)=lon(i0) .and. agrid(i,j,1)<=lon(i0+1) ) then
+ i1 = i0; i2 = i0+1
+ a1 = (agrid(i,j,1)-lon(i1)) * rdlon(i0)
+ go to 111
+ endif
+ enddo
+ endif
+
+111 continue
+
+ if ( agrid(i,j,2)lat(jm) ) then
+ jc = jm-1
+ b1 = 1.
+ else
+ do j0=1,jm-1
+ if ( agrid(i,j,2)>=lat(j0) .and. agrid(i,j,2)<=lat(j0+1) ) then
+ jc = j0
+ b1 = (agrid(i,j,2)-lat(jc)) * rdlat(jc)
+ go to 222
+ endif
+ enddo
+ endif
+222 continue
+
+#ifndef DEBUG_REMAP
+ if ( a1<0.0 .or. a1>1.0 .or. b1<0.0 .or. b1>1.0 ) then
+ write(*,*) i,j,a1, b1
+ endif
+#endif
+ c1 = (1.-a1) * (1.-b1)
+ c2 = a1 * (1.-b1)
+ c3 = a1 * b1
+ c4 = (1.-a1) * b1
+
+! Interpolated surface pressure
+ psc = c1*ps0(i1,jc ) + c2*ps0(i2,jc ) + &
+ c3*ps0(i2,jc+1) + c4*ps0(i1,jc+1)
+
+! Interpolated surface geopotential
+ gzc = c1*gz0(i1,jc ) + c2*gz0(i2,jc ) + &
+ c3*gz0(i2,jc+1) + c4*gz0(i1,jc+1)
+
+! 3D fields:
+ do iq=1,ncnst
+! if ( iq==sphum .or. iq==liq_wat .or. iq==ice_wat .or. iq==cld_amt ) then
+ do k=1,km
+ qp(i,k,iq) = c1*qa(i1,jc, k,iq) + c2*qa(i2,jc, k,iq) + &
+ c3*qa(i2,jc+1,k,iq) + c4*qa(i1,jc+1,k,iq)
+ enddo
+! endif
+ enddo
+
+ do k=1,km
+ up(i,k) = c1*ua(i1,jc, k) + c2*ua(i2,jc, k) + &
+ c3*ua(i2,jc+1,k) + c4*ua(i1,jc+1,k)
+ vp(i,k) = c1*va(i1,jc, k) + c2*va(i2,jc, k) + &
+ c3*va(i2,jc+1,k) + c4*va(i1,jc+1,k)
+ tp(i,k) = c1*ta(i1,jc, k) + c2*ta(i2,jc, k) + &
+ c3*ta(i2,jc+1,k) + c4*ta(i1,jc+1,k)
+! Virtual effect:
+#ifdef MULTI_GASES
+ tp(i,k) = tp(i,k)*virq(qp(i,k,:))
+#else
+ tp(i,k) = tp(i,k)*(1.+zvir*qp(i,k,sphum))
+#endif
+ enddo
+! Tracers:
+
+ do k=2,km+1
+ pe0(i,k) = ak0(k) + bk0(k)*psc
+ pn0(i,k) = log(pe0(i,k))
+ pk0(k) = pe0(i,k)**kappa
+ enddo
+
+#ifdef USE_DATA_ZS
+ Atm% ps(i,j) = psc
+ Atm%phis(i,j) = gzc
+#else
+
+! * Adjust interpolated ps to model terrain
+ gz(km+1) = gzc
+ do k=km,1,-1
+ gz(k) = gz(k+1) + rdgas*tp(i,k)*(pn0(i,k+1)-pn0(i,k))
+ enddo
+! Only lowest layer potential temp is needed
+#ifdef MULTI_GASES
+ kappax = virqd(qp(i,km,:))/vicpqd(qp(i,km,:))
+ pkx = (pk0(km+1)-pk0(km))*(kappa*(pn0(i,km+1)-pn0(i,km)))
+ pkx = exp( kappax*log(pkx) )
+ pt0(km) = tp(i,km)/pkx
+#else
+ pt0(km) = tp(i,km)/(pk0(km+1)-pk0(km))*(kappa*(pn0(i,km+1)-pn0(i,km)))
+#endif
+ if( Atm%phis(i,j)>gzc ) then
+ do k=km,1,-1
+ if( Atm%phis(i,j) < gz(k) .and. &
+ Atm%phis(i,j) >= gz(k+1) ) then
+ pst = pk0(k) + (pk0(k+1)-pk0(k))*(gz(k)-Atm%phis(i,j))/(gz(k)-gz(k+1))
+ go to 123
+ endif
+ enddo
+ else
+! Extrapolation into the ground
+#ifdef MULTI_GASES
+ pst = pk0(km+1) + (gzc-Atm%phis(i,j))/(cp_air*pt0(km)*pkx)
+#else
+ pst = pk0(km+1) + (gzc-Atm%phis(i,j))/(cp_air*pt0(km))
+#endif
+ endif
+
+#ifdef MULTI_GASES
+123 Atm%ps(i,j) = pst**(1./(kappa*kappax))
+#else
+123 Atm%ps(i,j) = pst**(1./kappa)
+#endif
+#endif
+ enddo !i-loop
+
+
+! * Compute delp from ps
+ do i=is,ie
+ pe1(i,1) = Atm%ak(1)
+ pn1(i,1) = log(pe1(i,1))
+ enddo
+ do k=2,npz+1
+ do i=is,ie
+ pe1(i,k) = Atm%ak(k) + Atm%bk(k)*Atm%ps(i,j)
+ pn1(i,k) = log(pe1(i,k))
+ enddo
+ enddo
+
+ do k=1,npz
+ do i=is,ie
+ Atm%delp(i,j,k) = pe1(i,k+1) - pe1(i,k)
+ enddo
+ enddo
+
+! Use kord=9 for winds; kord=11 for tracers
+!------
+! map u
+!------
+ call mappm(km, pe0, up, npz, pe1, qn1, is,ie, -1, 9, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+ ut(i,j,k) = qn1(i,k)
+ enddo
+ enddo
+!------
+! map v
+!------
+ call mappm(km, pe0, vp, npz, pe1, qn1, is,ie, -1, 9, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+ vt(i,j,k) = qn1(i,k)
+ enddo
+ enddo
+
+!---------------
+! map tracers
+!----------------
+ do iq=1,ncnst
+! Note: AM2 physics tracers only
+! if ( iq==sphum .or. iq==liq_wat .or. iq==ice_wat .or. iq==cld_amt ) then
+ call mappm(km, pe0, qp(is,1,iq), npz, pe1, qn1, is,ie, 0, 11, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+ Atm%q(i,j,k,iq) = qn1(i,k)
+ enddo
+ enddo
+! endif
+ enddo
+
+!-------------------------------------------------------------
+! map virtual temperature using geopotential conserving scheme.
+!-------------------------------------------------------------
+ call mappm(km, pn0, tp, npz, pn1, qn1, is,ie, 1, 9, Atm%ptop)
+ do k=1,npz
+ do i=is,ie
+#ifdef MULTI_GASES
+ Atm%pt(i,j,k) = qn1(i,k)/virq(Atm%q(i,j,k,:))
+#else
+ Atm%pt(i,j,k) = qn1(i,k)/(1.+zvir*Atm%q(i,j,k,sphum))
+#endif
+ enddo
+ enddo
+
+5000 continue
+
+ call prt_maxmin('PS_model', Atm%ps, is, ie, js, je, ng, 1, 0.01)
+ call prt_maxmin('UT', ut, is, ie, js, je, ng, npz, 1.)
+ call prt_maxmin('VT', vt, is, ie, js, je, ng, npz, 1.)
+
+!----------------------------------------------
+! winds: lat-lon ON A to Cubed-D transformation:
+!----------------------------------------------
+ call cubed_a2d(Atm%npx, Atm%npy, npz, ut, vt, Atm%u, Atm%v, Atm%gridstruct, Atm%domain, Atm%bd )
+
+ if (is_master()) write(*,*) 'done remap_xyz'
+
+ end subroutine remap_xyz
+
+!>@brief The subroutine 'cubed_a2d' transforms the wind from the A Grid to the D Grid.
+ subroutine cubed_a2d( npx, npy, npz, ua, va, u, v, gridstruct, fv_domain, bd )
+ use mpp_domains_mod, only: mpp_update_domains
+
+ type(fv_grid_bounds_type), intent(IN) :: bd
+ integer, intent(in):: npx, npy, npz
+ real, intent(inout), dimension(bd%isd:bd%ied,bd%jsd:bd%jed,npz):: ua, va
+ real, intent(out):: u(bd%isd:bd%ied, bd%jsd:bd%jed+1,npz)
+ real, intent(out):: v(bd%isd:bd%ied+1,bd%jsd:bd%jed ,npz)
+ type(fv_grid_type), intent(IN), target :: gridstruct
+ type(domain2d), intent(INOUT) :: fv_domain
+! local:
+ real v3(3,bd%is-1:bd%ie+1,bd%js-1:bd%je+1)
+ real ue(3,bd%is-1:bd%ie+1,bd%js:bd%je+1) !< 3D winds at edges
+ real ve(3,bd%is:bd%ie+1,bd%js-1:bd%je+1) !< 3D winds at edges
+ real, dimension(bd%is:bd%ie):: ut1, ut2, ut3
+ real, dimension(bd%js:bd%je):: vt1, vt2, vt3
+ integer i, j, k, im2, jm2
+
+ real(kind=R_GRID), pointer, dimension(:,:,:) :: vlon, vlat
+ real(kind=R_GRID), pointer, dimension(:) :: edge_vect_w, edge_vect_e, edge_vect_s, edge_vect_n
+ real(kind=R_GRID), pointer, dimension(:,:,:,:) :: ew, es
+
+ integer :: is, ie, js, je
+ integer :: isd, ied, jsd, jed
+
+ is = bd%is
+ ie = bd%ie
+ js = bd%js
+ je = bd%je
+ isd = bd%isd
+ ied = bd%ied
+ jsd = bd%jsd
+ jed = bd%jed
+
+ vlon => gridstruct%vlon
+ vlat => gridstruct%vlat
+
+ edge_vect_w => gridstruct%edge_vect_w
+ edge_vect_e => gridstruct%edge_vect_e
+ edge_vect_s => gridstruct%edge_vect_s
+ edge_vect_n => gridstruct%edge_vect_n
+
+ ew => gridstruct%ew
+ es => gridstruct%es
+
+ call mpp_update_domains(ua, fv_domain, complete=.false.)
+ call mpp_update_domains(va, fv_domain, complete=.true.)
+
+ im2 = (npx-1)/2
+ jm2 = (npy-1)/2
+
+ do k=1, npz
+! Compute 3D wind on A grid
+ do j=js-1,je+1
+ do i=is-1,ie+1
+ v3(1,i,j) = ua(i,j,k)*vlon(i,j,1) + va(i,j,k)*vlat(i,j,1)
+ v3(2,i,j) = ua(i,j,k)*vlon(i,j,2) + va(i,j,k)*vlat(i,j,2)
+ v3(3,i,j) = ua(i,j,k)*vlon(i,j,3) + va(i,j,k)*vlat(i,j,3)
+ enddo
+ enddo
+
+! A --> D
+! Interpolate to cell edges
+ do j=js,je+1
+ do i=is-1,ie+1
+ ue(1,i,j) = 0.5*(v3(1,i,j-1) + v3(1,i,j))
+ ue(2,i,j) = 0.5*(v3(2,i,j-1) + v3(2,i,j))
+ ue(3,i,j) = 0.5*(v3(3,i,j-1) + v3(3,i,j))
+ enddo
+ enddo
+
+ do j=js-1,je+1
+ do i=is,ie+1
+ ve(1,i,j) = 0.5*(v3(1,i-1,j) + v3(1,i,j))
+ ve(2,i,j) = 0.5*(v3(2,i-1,j) + v3(2,i,j))
+ ve(3,i,j) = 0.5*(v3(3,i-1,j) + v3(3,i,j))
+ enddo
+ enddo
+
+! --- E_W edges (for v-wind):
+ if (.not. gridstruct%nested) then
+ if ( is==1) then
+ i = 1
+ do j=js,je
+ if ( j>jm2 ) then
+ vt1(j) = edge_vect_w(j)*ve(1,i,j-1)+(1.-edge_vect_w(j))*ve(1,i,j)
+ vt2(j) = edge_vect_w(j)*ve(2,i,j-1)+(1.-edge_vect_w(j))*ve(2,i,j)
+ vt3(j) = edge_vect_w(j)*ve(3,i,j-1)+(1.-edge_vect_w(j))*ve(3,i,j)
+ else
+ vt1(j) = edge_vect_w(j)*ve(1,i,j+1)+(1.-edge_vect_w(j))*ve(1,i,j)
+ vt2(j) = edge_vect_w(j)*ve(2,i,j+1)+(1.-edge_vect_w(j))*ve(2,i,j)
+ vt3(j) = edge_vect_w(j)*ve(3,i,j+1)+(1.-edge_vect_w(j))*ve(3,i,j)
+ endif
+ enddo
+ do j=js,je
+ ve(1,i,j) = vt1(j)
+ ve(2,i,j) = vt2(j)
+ ve(3,i,j) = vt3(j)
+ enddo
+ endif
+
+ if ( (ie+1)==npx ) then
+ i = npx
+ do j=js,je
+ if ( j>jm2 ) then
+ vt1(j) = edge_vect_e(j)*ve(1,i,j-1)+(1.-edge_vect_e(j))*ve(1,i,j)
+ vt2(j) = edge_vect_e(j)*ve(2,i,j-1)+(1.-edge_vect_e(j))*ve(2,i,j)
+ vt3(j) = edge_vect_e(j)*ve(3,i,j-1)+(1.-edge_vect_e(j))*ve(3,i,j)
+ else
+ vt1(j) = edge_vect_e(j)*ve(1,i,j+1)+(1.-edge_vect_e(j))*ve(1,i,j)
+ vt2(j) = edge_vect_e(j)*ve(2,i,j+1)+(1.-edge_vect_e(j))*ve(2,i,j)
+ vt3(j) = edge_vect_e(j)*ve(3,i,j+1)+(1.-edge_vect_e(j))*ve(3,i,j)
+ endif
+ enddo
+ do j=js,je
+ ve(1,i,j) = vt1(j)
+ ve(2,i,j) = vt2(j)
+ ve(3,i,j) = vt3(j)
+ enddo
+ endif
+
+! N-S edges (for u-wind):
+ if ( js==1 ) then
+ j = 1
+ do i=is,ie
+ if ( i>im2 ) then
+ ut1(i) = edge_vect_s(i)*ue(1,i-1,j)+(1.-edge_vect_s(i))*ue(1,i,j)
+ ut2(i) = edge_vect_s(i)*ue(2,i-1,j)+(1.-edge_vect_s(i))*ue(2,i,j)
+ ut3(i) = edge_vect_s(i)*ue(3,i-1,j)+(1.-edge_vect_s(i))*ue(3,i,j)
+ else
+ ut1(i) = edge_vect_s(i)*ue(1,i+1,j)+(1.-edge_vect_s(i))*ue(1,i,j)
+ ut2(i) = edge_vect_s(i)*ue(2,i+1,j)+(1.-edge_vect_s(i))*ue(2,i,j)
+ ut3(i) = edge_vect_s(i)*ue(3,i+1,j)+(1.-edge_vect_s(i))*ue(3,i,j)
+ endif
+ enddo
+ do i=is,ie
+ ue(1,i,j) = ut1(i)
+ ue(2,i,j) = ut2(i)
+ ue(3,i,j) = ut3(i)
+ enddo
+ endif
+
+ if ( (je+1)==npy ) then
+ j = npy
+ do i=is,ie
+ if ( i>im2 ) then
+ ut1(i) = edge_vect_n(i)*ue(1,i-1,j)+(1.-edge_vect_n(i))*ue(1,i,j)
+ ut2(i) = edge_vect_n(i)*ue(2,i-1,j)+(1.-edge_vect_n(i))*ue(2,i,j)
+ ut3(i) = edge_vect_n(i)*ue(3,i-1,j)+(1.-edge_vect_n(i))*ue(3,i,j)
+ else
+ ut1(i) = edge_vect_n(i)*ue(1,i+1,j)+(1.-edge_vect_n(i))*ue(1,i,j)
+ ut2(i) = edge_vect_n(i)*ue(2,i+1,j)+(1.-edge_vect_n(i))*ue(2,i,j)
+ ut3(i) = edge_vect_n(i)*ue(3,i+1,j)+(1.-edge_vect_n(i))*ue(3,i,j)
+ endif
+ enddo
+ do i=is,ie
+ ue(1,i,j) = ut1(i)
+ ue(2,i,j) = ut2(i)
+ ue(3,i,j) = ut3(i)
+ enddo
+ endif
+
+ endif ! .not. nested
+
+ do j=js,je+1
+ do i=is,ie
+ u(i,j,k) = ue(1,i,j)*es(1,i,j,1) + &
+ ue(2,i,j)*es(2,i,j,1) + &
+ ue(3,i,j)*es(3,i,j,1)
+ enddo
+ enddo
+ do j=js,je
+ do i=is,ie+1
+ v(i,j,k) = ve(1,i,j)*ew(1,i,j,2) + &
+ ve(2,i,j)*ew(2,i,j,2) + &
+ ve(3,i,j)*ew(3,i,j,2)
+ enddo
+ enddo
+
+ enddo ! k-loop
+
+ end subroutine cubed_a2d
+
+
+ subroutine d2a3d(u, v, ua, va, im, jm, km, lon)
+ integer, intent(in):: im, jm, km ! Dimensions
+ real, intent(in ) :: lon(im)
+ real, intent(in ), dimension(im,jm,km):: u, v
+ real, intent(out), dimension(im,jm,km):: ua, va
+! local
+ real :: coslon(im),sinlon(im) ! Sine and cosine in longitude
+ integer i, j, k
+ integer imh
+ real un, vn, us, vs
+
+ integer :: ks, ke
+
+ imh = im/2
+
+ do i=1,im
+ sinlon(i) = sin(lon(i))
+ coslon(i) = cos(lon(i))
+ enddo
+
+ do k=1,km
+ do j=2,jm-1
+ do i=1,im
+ ua(i,j,k) = 0.5*(u(i,j,k) + u(i,j+1,k))
+ enddo
+ enddo
+
+ do j=2,jm-1
+ do i=1,im-1
+ va(i,j,k) = 0.5*(v(i,j,k) + v(i+1,j,k))
+ enddo
+ va(im,j,k) = 0.5*(v(im,j,k) + v(1,j,k))
+ enddo
+
+! Projection at SP
+ us = 0.
+ vs = 0.
+ do i=1,imh
+ us = us + (ua(i+imh,2,k)-ua(i,2,k))*sinlon(i) &
+ + (va(i,2,k)-va(i+imh,2,k))*coslon(i)
+ vs = vs + (ua(i+imh,2,k)-ua(i,2,k))*coslon(i) &
+ + (va(i+imh,2,k)-va(i,2,k))*sinlon(i)
+ enddo
+ us = us/im
+ vs = vs/im
+ do i=1,imh
+ ua(i,1,k) = -us*sinlon(i) - vs*coslon(i)
+ va(i,1,k) = us*coslon(i) - vs*sinlon(i)
+ ua(i+imh,1,k) = -ua(i,1,k)
+ va(i+imh,1,k) = -va(i,1,k)
+ enddo
+
+! Projection at NP
+ un = 0.
+ vn = 0.
+ do i=1,imh
+ un = un + (ua(i+imh,jm-1,k)-ua(i,jm-1,k))*sinlon(i) &
+ + (va(i+imh,jm-1,k)-va(i,jm-1,k))*coslon(i)
+ vn = vn + (ua(i,jm-1,k)-ua(i+imh,jm-1,k))*coslon(i) &
+ + (va(i+imh,jm-1,k)-va(i,jm-1,k))*sinlon(i)
+ enddo
+
+ un = un/im
+ vn = vn/im
+ do i=1,imh
+ ua(i,jm,k) = -un*sinlon(i) + vn*coslon(i)
+ va(i,jm,k) = -un*coslon(i) - vn*sinlon(i)
+ ua(i+imh,jm,k) = -ua(i,jm,k)
+ va(i+imh,jm,k) = -va(i,jm,k)
+ enddo
+ enddo
+
+ end subroutine d2a3d
+
+
+ subroutine pmaxmin( qname, a, im, jm, fac )
+
+ integer, intent(in):: im, jm
+ character(len=*) :: qname
+ integer i, j
+ real a(im,jm)
+
+ real qmin(jm), qmax(jm)
+ real pmax, pmin
+ real fac ! multiplication factor
+
+ do j=1,jm
+ pmax = a(1,j)
+ pmin = a(1,j)
+ do i=2,im
+ pmax = max(pmax, a(i,j))
+ pmin = min(pmin, a(i,j))
+ enddo
+ qmax(j) = pmax
+ qmin(j) = pmin
+ enddo
+!
+! Now find max/min of amax/amin
+!
+ pmax = qmax(1)
+ pmin = qmin(1)
+ do j=2,jm
+ pmax = max(pmax, qmax(j))
+ pmin = min(pmin, qmin(j))
+ enddo
+
+ write(*,*) qname, ' max = ', pmax*fac, ' min = ', pmin*fac
+
+ end subroutine pmaxmin
+
+subroutine pmaxmn(qname, q, is, ie, js, je, km, fac, area, domain)
+ character(len=*), intent(in):: qname
+ integer, intent(in):: is, ie, js, je
+ integer, intent(in):: km
+ real, intent(in):: q(is:ie, js:je, km)
+ real, intent(in):: fac
+ real(kind=R_GRID), intent(IN):: area(is-3:ie+3, js-3:je+3)
+ type(domain2d), intent(INOUT) :: domain
+!---local variables
+ real qmin, qmax, gmean
+ integer i,j,k
+
+ qmin = q(is,js,1)
+ qmax = qmin
+ gmean = 0.
+
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ if( q(i,j,k) < qmin ) then
+ qmin = q(i,j,k)
+ elseif( q(i,j,k) > qmax ) then
+ qmax = q(i,j,k)
+ endif
+ enddo
+ enddo
+ enddo
+
+ call mp_reduce_min(qmin)
+ call mp_reduce_max(qmax)
+
+ gmean = g_sum(domain, q(is,js,km), is, ie, js, je, 3, area, 1, reproduce=.true.)
+ if(is_master()) write(6,*) qname, qmax*fac, qmin*fac, gmean*fac
+
+ end subroutine pmaxmn
+
+ subroutine p_maxmin(qname, q, is, ie, js, je, km, fac)
+ character(len=*), intent(in):: qname
+ integer, intent(in):: is, ie, js, je, km
+ real, intent(in):: q(is:ie, js:je, km)
+ real, intent(in):: fac
+ real qmin, qmax
+ integer i,j,k
+
+ qmin = q(is,js,1)
+ qmax = qmin
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ if( q(i,j,k) < qmin ) then
+ qmin = q(i,j,k)
+ elseif( q(i,j,k) > qmax ) then
+ qmax = q(i,j,k)
+ endif
+ enddo
+ enddo
+ enddo
+ call mp_reduce_min(qmin)
+ call mp_reduce_max(qmax)
+ if(is_master()) write(6,*) qname, qmax*fac, qmin*fac
+
+ end subroutine p_maxmin
+
+ subroutine fillq(im, km, nq, q, dp)
+ integer, intent(in):: im !< No. of longitudes
+ integer, intent(in):: km !< No. of levels
+ integer, intent(in):: nq !< Total number of tracers
+ real , intent(in):: dp(im,km) !< pressure thickness
+ real , intent(inout) :: q(im,km,nq) !< tracer mixing ratio
+! !LOCAL VARIABLES:
+ integer i, k, ic, k1
+
+ do ic=1,nq
+! Bottom up:
+ do k=km,2,-1
+ k1 = k-1
+ do i=1,im
+ if( q(i,k,ic) < 0. ) then
+ q(i,k1,ic) = q(i,k1,ic) + q(i,k,ic)*dp(i,k)/dp(i,k1)
+ q(i,k ,ic) = 0.
+ endif
+ enddo
+ enddo
+! Top down:
+ do k=1,km-1
+ k1 = k+1
+ do i=1,im
+ if( q(i,k,ic) < 0. ) then
+ q(i,k1,ic) = q(i,k1,ic) + q(i,k,ic)*dp(i,k)/dp(i,k1)
+ q(i,k ,ic) = 0.
+ endif
+ enddo
+ enddo
+
+ enddo
+
+ end subroutine fillq
+
+ subroutine compute_zh(im, jm, levp, ak0, bk0, ps, zs, t, q, nq, zh )
+ implicit none
+ integer, intent(in):: levp, im,jm, nq
+ real, intent(in), dimension(levp+1):: ak0, bk0
+ real(kind=4), intent(in), dimension(im,jm):: ps, zs
+ real(kind=4), intent(in), dimension(im,jm,levp):: t
+ real(kind=4), intent(in), dimension(im,jm,levp,nq):: q
+ real(kind=4), intent(out), dimension(im,jm,levp+1):: zh
+ ! Local:
+ real, dimension(im,levp+1):: pe0, pn0
+! real:: qc
+ integer:: i,j,k
+
+!$OMP parallel do default(none) shared(im,jm,levp,ak0,bk0,zs,ps,t,q,zh) &
+!$OMP private(pe0,pn0)
+ do j = 1, jm
+
+ do i=1, im
+ pe0(i,1) = ak0(1)
+ pn0(i,1) = log(pe0(i,1))
+ zh(i,j,levp+1) = zs(i,j)
+ enddo
+
+ do k=2,levp+1
+ do i=1,im
+ pe0(i,k) = ak0(k) + bk0(k)*ps(i,j)
+ pn0(i,k) = log(pe0(i,k))
+ enddo
+ enddo
+
+ do k = levp, 1, -1
+ do i = 1, im
+! qc = 1.-(q(i,j,k,2)+q(i,j,k,3)+q(i,j,k,4)+q(i,j,k,5))
+ zh(i,j,k) = zh(i,j,k+1)+(t(i,j,k)*(1.+zvir*q(i,j,k,1))*(pn0(i,k+1)-pn0(i,k)))*(rdgas/grav)
+ enddo
+ enddo
+ enddo
+
+ !if(is_master()) call pmaxmin( 'zh levp+1', zh(:,:,levp+1), im, jm, 1.)
+
+ end subroutine compute_zh
+
+ subroutine get_staggered_grid( is, ie, js, je, isd, ied, jsd, jed, pt_b, pt_c, pt_d)
+ integer, intent(in):: is, ie, js, je, isd, ied, jsd, jed
+ real, dimension(isd:ied+1,jsd:jed+1,2), intent(in) :: pt_b
+ real, dimension(isd:ied+1,jsd:jed ,2), intent(out) :: pt_c
+ real, dimension(isd:ied ,jsd:jed+1,2), intent(out) :: pt_d
+ ! local
+ real(kind=R_GRID), dimension(2):: p1, p2, p3
+ integer :: i, j
+
+ do j=js,je+1
+ do i=is,ie
+ p1(:) = pt_b(i, j,1:2)
+ p2(:) = pt_b(i+1,j,1:2)
+ call mid_pt_sphere(p1, p2, p3)
+ pt_d(i,j,1:2) = p3(:)
+ enddo
+ enddo
+
+ do j=js,je
+ do i=is,ie+1
+ p1(:) = pt_b(i,j ,1:2)
+ p2(:) = pt_b(i,j+1,1:2)
+ call mid_pt_sphere(p1, p2, p3)
+ pt_c(i,j,1:2) = p3(:)
+ enddo
+ enddo
+
+ end subroutine get_staggered_grid
+
+ end module external_ic_mod
+
diff --git a/tools/fv_eta.F90 b/tools/fv_eta.F90
index 3c49530f8..7697c385c 100644
--- a/tools/fv_eta.F90
+++ b/tools/fv_eta.F90
@@ -753,50 +753,36 @@ subroutine set_eta(km, ks, ptop, ak, bk)
0.92626, 0.94552, 0.96286, &
0.97840, 0.99223, 1.00000 /
- data a60/ 1.7861000000e-01, 1.0805100000e+00, 3.9647100000e+00, &
- 9.7516000000e+00, 1.9816580000e+01, 3.6695950000e+01, &
- 6.2550570000e+01, 9.9199620000e+01, 1.4792505000e+02, &
- 2.0947487000e+02, 2.8422571000e+02, 3.7241721000e+02, &
- 4.7437835000e+02, 5.9070236000e+02, 7.2236063000e+02, &
- 8.7076746000e+02, 1.0378138800e+03, 1.2258877300e+03, &
- 1.4378924600e+03, 1.6772726600e+03, 1.9480506400e+03, &
- 2.2548762700e+03, 2.6030909400e+03, 2.9988059200e+03, &
- 3.4489952300e+03, 3.9616028900e+03, 4.5456641600e+03, &
- 5.2114401700e+03, 5.9705644000e+03, 6.8361981800e+03, &
- 7.8231906000e+03, 8.9482351000e+03, 1.0230010660e+04, &
- 1.1689289750e+04, 1.3348986860e+04, 1.5234111060e+04, &
- 1.7371573230e+04, 1.9789784580e+04, 2.2005564550e+04, &
- 2.3550115120e+04, 2.4468583320e+04, 2.4800548800e+04, &
- 2.4582445070e+04, 2.3849999620e+04, 2.2640519740e+04, &
- 2.0994737150e+04, 1.8957848730e+04, 1.6579413230e+04, &
- 1.4080071030e+04, 1.1753630920e+04, 9.6516996300e+03, &
- 7.7938009300e+03, 6.1769062800e+03, 4.7874276000e+03, &
- 3.6050497500e+03, 2.6059860700e+03, 1.7668328200e+03, &
- 1.0656131200e+03, 4.8226201000e+02, 0.0000000000e+00, &
- 0.0000000000e+00 /
-
-
- data b60/ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
- 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
- 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
- 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
- 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
- 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
- 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
- 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
- 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
- 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
- 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
- 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
- 0.0000000000e+00, 0.0000000000e+00, 5.0600000000e-03, &
- 2.0080000000e-02, 4.4900000000e-02, 7.9360000000e-02, &
- 1.2326000000e-01, 1.7634000000e-01, 2.3820000000e-01, &
- 3.0827000000e-01, 3.8581000000e-01, 4.6989000000e-01, &
- 5.5393000000e-01, 6.2958000000e-01, 6.9642000000e-01, &
- 7.5458000000e-01, 8.0463000000e-01, 8.4728000000e-01, &
- 8.8335000000e-01, 9.1368000000e-01, 9.3905000000e-01, &
- 9.6020000000e-01, 9.7775000000e-01, 9.9223000000e-01, &
- 1.0000000000e+00 /
+! NAM levels
+ data a60/200., 1311.4934, 2424.6044, 3541.7594,&
+ 4662.9584, 5790.2234, 6932.6534, 8095.3034,&
+ 9278.1734, 10501.4834, 11755.1234, 13049.2034,&
+ 14403.9434, 15809.2334, 17315.6234, 18953.4434,&
+ 20783.3534, 22815.4634, 25059.8834, 27567.1634,&
+ 30148.42896047, 32193.91776039, 33237.35176644, 33332.15200668,&
+ 32747.34688095, 31710.06232008, 30381.0344269, 28858.71577772,&
+ 27218.00439794, 25500.31691133, 23734.52294749, 21947.3406187,&
+ 20167.06984021, 18396.08144096, 16688.20978135, 15067.73749198,&
+ 13564.49530178, 12183.34512952, 10928.24869364, 9815.02787644,&
+ 8821.38325756, 7943.05793658, 7181.90985128, 6500.94645341,&
+ 5932.84856135, 5420.87683616, 4959.15585353, 4522.15047657,&
+ 4103.63596619, 3703.72540955, 3322.52525084, 2953.65688391,&
+ 2597.18532669, 2253.10764634, 1915.10585833, 1583.14516612,&
+ 1257.18953818, 937.3977544 , 623.60136981, 311.11085215,&
+ 0. /
+
+ data b60/0., 0., 0., 0., 0.,&
+ 0. , 0. , 0. , 0. , 0. ,&
+ 0. , 0. , 0. , 0. , 0. ,&
+ 0. , 0. , 0. , 0. , 0. ,&
+ 0.0014653 , 0.01021565, 0.0301554 , 0.06025816, 0.09756877,&
+ 0.13994493, 0.18550048, 0.23318371, 0.2819159 , 0.33120838,&
+ 0.38067633, 0.42985641, 0.47816985, 0.52569303, 0.57109611,&
+ 0.61383996, 0.6532309 , 0.68922093, 0.72177094, 0.75052515,&
+ 0.77610288, 0.79864598, 0.81813309, 0.83553022, 0.85001773,&
+ 0.86305395, 0.8747947 , 0.88589325, 0.89650986, 0.9066434 ,&
+ 0.91629284, 0.92562094, 0.93462705, 0.94331221, 0.95183659,&
+ 0.96020153, 0.96840839, 0.97645359, 0.98434181, 0.99219119, 1. /
! This is activated by USE_GFSL63
! Thfollowing L63 setting is the same as NCEP GFS's L64 except the top
@@ -1313,7 +1299,7 @@ subroutine set_eta(km, ks, ptop, ak, bk)
enddo
case (60)
- ks = 37
+ ks = 19
do k=1,km+1
ak(k) = a60(k)
bk(k) = b60(k)
diff --git a/tools/fv_eta.F90_65lyrs b/tools/fv_eta.F90_65lyrs
new file mode 100644
index 000000000..3c49530f8
--- /dev/null
+++ b/tools/fv_eta.F90_65lyrs
@@ -0,0 +1,3093 @@
+!***********************************************************************
+!* GNU Lesser General Public License
+!*
+!* This file is part of the FV3 dynamical core.
+!*
+!* The FV3 dynamical core is free software: you can redistribute it
+!* and/or modify it under the terms of the
+!* GNU Lesser General Public License as published by the
+!* Free Software Foundation, either version 3 of the License, or
+!* (at your option) any later version.
+!*
+!* The FV3 dynamical core is distributed in the hope that it will be
+!* useful, but WITHOUT ANYWARRANTY; without even the implied warranty
+!* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+!* See the GNU General Public License for more details.
+!*
+!* You should have received a copy of the GNU Lesser General Public
+!* License along with the FV3 dynamical core.
+!* If not, see .
+!***********************************************************************
+
+!>@brief The module 'fv_eta' contains routine to set up the reference
+!! (Eulerian) pressure coordinate
+
+module fv_eta_mod
+
+!
+!
+! | Module Name |
+! Functions Included |
+!
+!
+! | constants_mod |
+! kappa, grav, cp_air, rdgas |
+!
+!
+! | fv_mp_mod |
+! is_master |
+!
+!
+! | mpp_mod |
+! mpp_error, FATAL |
+!
+!
+
+ use constants_mod, only: kappa, grav, cp_air, rdgas
+ use fv_mp_mod, only: is_master
+ use mpp_mod, only: FATAL, mpp_error
+ implicit none
+ private
+ public set_eta, set_external_eta, get_eta_level, compute_dz_var, &
+ compute_dz_L32, compute_dz_L101, set_hybrid_z, compute_dz, &
+ gw_1d, sm1_edge, hybrid_z_dz
+
+ contains
+
+!!!NOTE: USE_VAR_ETA not used in fvGFS
+#ifdef USE_VAR_ETA
+ subroutine set_eta(km, ks, ptop, ak, bk)
+! This is the easy to use version of the set_eta
+ integer, intent(in):: km ! vertical dimension
+ integer, intent(out):: ks ! number of pure p layers
+ real:: a60(61),b60(61)
+! Thfollowing L63 setting is the same as NCEP GFS's L64 except the top
+! 3 layers
+ data a60/300.0000, 430.00000, 558.00000, &
+ 700.00000, 863.05803, 1051.07995, &
+ 1265.75194, 1510.71101, 1790.05098, &
+ 2108.36604, 2470.78817, 2883.03811, &
+ 3351.46002, 3883.05187, 4485.49315, &
+ 5167.14603, 5937.04991, 6804.87379, &
+ 7780.84698, 8875.64338, 10100.20534, &
+ 11264.35673, 12190.64366, 12905.42546, &
+ 13430.87867, 13785.88765, 13986.77987, &
+ 14047.96335, 13982.46770, 13802.40331, &
+ 13519.33841, 13144.59486, 12689.45608, &
+ 12165.28766, 11583.57006, 10955.84778, &
+ 10293.60402, 9608.08306, 8910.07678, &
+ 8209.70131, 7516.18560, 6837.69250, &
+ 6181.19473, 5552.39653, 4955.72632, &
+ 4394.37629, 3870.38682, 3384.76586, &
+ 2937.63489, 2528.37666, 2155.78385, &
+ 1818.20722, 1513.68173, 1240.03585, &
+ 994.99144, 776.23591, 581.48797, &
+ 408.53400, 255.26520, 119.70243, 0. /
+
+ data b60/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00201, 0.00792, 0.01755, &
+ 0.03079, 0.04751, 0.06761, &
+ 0.09097, 0.11746, 0.14690, &
+ 0.17911, 0.21382, 0.25076, &
+ 0.28960, 0.32994, 0.37140, &
+ 0.41353, 0.45589, 0.49806, &
+ 0.53961, 0.58015, 0.61935, &
+ 0.65692, 0.69261, 0.72625, &
+ 0.75773, 0.78698, 0.81398, &
+ 0.83876, 0.86138, 0.88192, &
+ 0.90050, 0.91722, 0.93223, &
+ 0.94565, 0.95762, 0.96827, &
+ 0.97771, 0.98608, 0.99347, 1./
+ real, intent(out):: ak(km+1)
+ real, intent(out):: bk(km+1)
+ real, intent(out):: ptop ! model top (Pa)
+ real pint, stretch_fac
+ integer k
+ real :: s_rate = -1.0 ! dummy value to not use var_les
+
+ pint = 100.E2
+
+!- Notes ---------------------------------
+! low-top: ptop = 100. ! ~45 km
+! mid-top: ptop = 10. ! ~60 km
+! hi -top: ptop = 1. ! ~80 km
+!-----------------------------------------
+ select case (km)
+
+! Optimal number = 8 * N -1 (for 8 openMP threads)
+! 16 * M -1 (for 16 openMP threads)
+
+#ifdef HIWPP
+#ifdef SUPER_K
+ case (20)
+ ptop = 56.e2
+ pint = ptop
+ stretch_fac = 1.03
+ case (24)
+ ptop = 56.e2
+ pint = ptop
+ stretch_fac = 1.03
+ case (30)
+ ptop = 56.e2
+ pint = ptop
+ stretch_fac = 1.03
+ case (40)
+ ptop = 56.e2
+ pint = ptop
+ stretch_fac = 1.03
+ case (50)
+ ptop = 56.e2
+ pint = ptop
+ stretch_fac = 1.03
+ case (60)
+ ptop = 56.e2
+ pint = ptop
+ stretch_fac = 1.03
+ case (80)
+ ptop = 56.e2
+ pint = ptop
+ stretch_fac = 1.03
+#else
+ case (30) ! For Baroclinic Instability Test
+ ptop = 2.26e2
+ pint = 250.E2
+ stretch_fac = 1.03
+ case (40)
+ ptop = 50.e2 ! For super cell test
+ pint = 300.E2
+ stretch_fac = 1.03
+ case (50) ! Mountain waves?
+ ptop = 30.e2
+ stretch_fac = 1.025
+ case (60) ! For Baroclinic Instability Test
+#ifdef GFSL60
+ ks = 20
+ ptop = a60(1)
+ pint = a60(ks+1)
+ do k=1,km+1
+ ak(k) = a60(k)
+ bk(k) = b60(k)
+ enddo
+#else
+ ptop = 3.e2
+! pint = 250.E2
+ pint = 300.E2 ! revised for Moist test
+ stretch_fac = 1.03
+#endif
+#endif
+ case (64)
+!!! ptop = 3.e2
+ ptop = 2.0e2
+ pint = 300.E2
+ stretch_fac = 1.03
+#else
+! *Very-low top: for idealized super-cell simulation:
+ case (50)
+ ptop = 50.e2
+ pint = 250.E2
+ stretch_fac = 1.03
+ case (60)
+ ptop = 40.e2
+ pint = 250.E2
+ stretch_fac = 1.03
+ case (90) ! super-duper cell
+ ptop = 40.e2
+ stretch_fac = 1.025
+#endif
+! Low-top:
+ case (31) ! N = 4, M=2
+ ptop = 100.
+ stretch_fac = 1.035
+ case (32) ! N = 4, M=2
+ ptop = 100.
+ stretch_fac = 1.035
+ case (39) ! N = 5
+ ptop = 100.
+ stretch_fac = 1.035
+ case (41)
+ ptop = 100.
+ stretch_fac = 1.035
+ case (47) ! N = 6, M=3
+ ptop = 100.
+ stretch_fac = 1.035
+ case (51)
+ ptop = 100.
+ stretch_fac = 1.03
+ case (52) ! very low top
+ ptop = 30.e2 ! for special DPM RCE experiments
+ stretch_fac = 1.03
+! Mid-top:
+ case (55) ! N = 7
+ ptop = 10.
+ stretch_fac = 1.035
+! Hi-top:
+ case (63) ! N = 8, M=4
+ ptop = 1.
+ ! c360 or c384
+ stretch_fac = 1.035
+ case (71) ! N = 9
+ ptop = 1.
+ stretch_fac = 1.03
+ case (79) ! N = 10, M=5
+ ptop = 1.
+ stretch_fac = 1.03
+ case (127) ! N = 10, M=5
+ ptop = 1.
+ stretch_fac = 1.03
+ case (151)
+ ptop = 75.e2
+ pint = 500.E2
+ s_rate = 1.01
+ case default
+ ptop = 1.
+ stretch_fac = 1.03
+ end select
+
+#ifdef MOUNTAIN_WAVES
+ call mount_waves(km, ak, bk, ptop, ks, pint)
+#else
+ if (s_rate > 0.) then
+ call var_les(km, ak, bk, ptop, ks, pint, s_rate)
+ else
+ if ( km > 79 ) then
+ call var_hi2(km, ak, bk, ptop, ks, pint, stretch_fac)
+ elseif (km==5 .or. km==10 ) then
+! Equivalent Shallow Water: for NGGPS, variable-resolution testing
+ ptop = 500.e2
+ ks = 0
+ do k=1,km+1
+ bk(k) = real(k-1) / real (km)
+ ak(k) = ptop*(1.-bk(k))
+ enddo
+ else
+#ifndef GFSL60
+ call var_hi(km, ak, bk, ptop, ks, pint, stretch_fac)
+#endif
+ endif
+#endif
+ endif
+
+ ptop = ak(1)
+ pint = ak(ks+1)
+
+ end subroutine set_eta
+
+ subroutine mount_waves(km, ak, bk, ptop, ks, pint)
+ integer, intent(in):: km
+ real, intent(out):: ak(km+1), bk(km+1)
+ real, intent(out):: ptop, pint
+ integer, intent(out):: ks
+! Local
+ real, parameter:: p00 = 1.E5
+ real, dimension(km+1):: ze, pe1, peln, eta
+ real, dimension(km):: dz, dlnp
+ real ztop, t0, dz0, sum1, tmp1
+ real ep, es, alpha, beta, gama, s_fac
+ integer k, k500
+
+ pint = 300.e2
+! s_fac = 1.05
+! dz0 = 500.
+ if ( km <= 60 ) then
+ s_fac = 1.0
+ dz0 = 500.
+ else
+ s_fac = 1.
+ dz0 = 250.
+ endif
+
+! Basic parameters for HIWPP mountain waves
+ t0 = 300.
+! ztop = 20.0e3; 500-m resolution in halft of the vertical domain
+! ztop = real(km-1)*500.
+!-----------------------
+! Compute temp ptop based on isothermal atm
+! ptop = p00*exp(-grav*ztop/(rdgas*t0))
+
+! Lowest half has constant resolution
+ ze(km+1) = 0.
+ do k=km, km-19, -1
+ ze(k) = ze(k+1) + dz0
+ enddo
+
+! Stretching from 10-km and up:
+ do k=km-20, 3, -1
+ dz0 = s_fac * dz0
+ ze(k) = ze(k+1) + dz0
+ enddo
+ ze(2) = ze(3) + sqrt(2.)*dz0
+ ze(1) = ze(2) + 2.0*dz0
+
+! call sm1_edge(1, 1, 1, 1, km, 1, 1, ze, 1)
+
+! Given z --> p
+ do k=1,km
+ dz(k) = ze(k) - ze(k+1)
+ dlnp(k) = grav*dz(k) / (rdgas*t0)
+ enddo
+
+ pe1(km+1) = p00
+ peln(km+1) = log(p00)
+ do k=km,1,-1
+ peln(k) = peln(k+1) - dlnp(k)
+ pe1(k) = exp(peln(k))
+ enddo
+
+! Comnpute new ptop
+ ptop = pe1(1)
+
+! Pe(k) = ak(k) + bk(k) * PS
+! Locate pint and KS
+ ks = 0
+ do k=2,km
+ if ( pint < pe1(k)) then
+ ks = k-1
+ exit
+ endif
+ enddo
+
+ if ( is_master() ) then
+ write(*,*) 'For (input) PINT=', 0.01*pint, ' KS=', ks, 'pint(computed)=', 0.01*pe1(ks+1)
+ write(*,*) 'Modified ptop =', ptop, ' ztop=', ze(1)/1000.
+ do k=1,km
+ write(*,*) k, 'ze =', ze(k)/1000.
+ enddo
+ endif
+ pint = pe1(ks+1)
+
+#ifdef NO_UKMO_HB
+ do k=1,ks+1
+ ak(k) = pe1(k)
+ bk(k) = 0.
+ enddo
+
+ do k=ks+2,km+1
+ bk(k) = (pe1(k) - pint) / (pe1(km+1)-pint) ! bk == sigma
+ ak(k) = pe1(k) - bk(k) * pe1(km+1)
+ enddo
+ bk(km+1) = 1.
+ ak(km+1) = 0.
+#else
+! Problematic for non-hydrostatic
+ do k=1,km+1
+ eta(k) = pe1(k) / pe1(km+1)
+ enddo
+ ep = eta(ks+1)
+ es = eta(km)
+! es = 1.
+ alpha = (ep**2-2.*ep*es) / (es-ep)**2
+ beta = 2.*ep*es**2 / (es-ep)**2
+ gama = -(ep*es)**2 / (es-ep)**2
+
+! Pure pressure:
+ do k=1,ks+1
+ ak(k) = eta(k)*1.e5
+ bk(k) = 0.
+ enddo
+
+ do k=ks+2, km
+ ak(k) = alpha*eta(k) + beta + gama/eta(k)
+ ak(k) = ak(k)*1.e5
+ enddo
+ ak(km+1) = 0.
+
+ do k=ks+2, km
+ bk(k) = (pe1(k) - ak(k))/pe1(km+1)
+ enddo
+ bk(km+1) = 1.
+#endif
+
+ if ( is_master() ) then
+ tmp1 = ak(ks+1)
+ do k=ks+1,km
+ tmp1 = max(tmp1, (ak(k)-ak(k+1))/max(1.E-5, (bk(k+1)-bk(k))) )
+ enddo
+ write(*,*) 'Hybrid Sigma-P: minimum allowable surface pressure (hpa)=', tmp1/100.
+ endif
+
+ end subroutine mount_waves
+
+#else
+ !>This is the version of set_eta used in fvGFS and AM4
+ !>@note 01/2018: 'set_eta' is being cleaned up.
+ subroutine set_eta(km, ks, ptop, ak, bk)
+ integer, intent(in):: km !< vertical dimension
+ integer, intent(out):: ks !< number of pure p layers
+ real, intent(out):: ak(km+1)
+ real, intent(out):: bk(km+1)
+ real, intent(out):: ptop !< model top (Pa)
+! local
+ real a24(25),b24(25) !< GFDL AM2L24
+ real a26(27),b26(27) !< Jablonowski & Williamson 26-level
+ real a32(33),b32(33)
+ real a32w(33),b32w(33)
+ real a47(48),b47(48)
+ real a48(49),b48(49)
+ real a52(53),b52(53)
+ real a54(55),b54(55)
+ real a56(57),b56(57)
+ real a60(61),b60(61)
+ real a63(64),b63(64)
+ real a64(65),b64(65)
+ real a68(69),b68(69) !< cjg: grid with enhanced PBL resolution
+ real a96(97),b96(97) !< cjg: grid with enhanced PBL resolution
+ real a100(101),b100(101)
+ real a104(105),b104(105)
+ real a125(126),b125(126)
+
+ real:: p0=1000.E2
+ real:: pc=200.E2
+
+ real pt, pint, lnpe, dlnp
+ real press(km+1), pt1(km)
+ integer k
+
+! Definition: press(i,j,k) = ak(k) + bk(k) * ps(i,j)
+
+!-----------------------------------------------
+! GFDL AM2-L24: modified by SJL at the model top
+!-----------------------------------------------
+! data a24 / 100.0000, 1050.0000, 3474.7942, 7505.5556, 12787.2428, &
+ data a24 / 100.0000, 903.4465, 3474.7942, 7505.5556, 12787.2428, &
+ 19111.3683, 21854.9274, 22884.1866, 22776.3058, 21716.1604, &
+ 20073.2963, 18110.5123, 16004.7832, 13877.6253, 11812.5452, &
+ 9865.8840, 8073.9726, 6458.0834, 5027.9899, 3784.6085, &
+ 2722.0086, 1828.9752, 1090.2396, 487.4595, 0.0000 /
+
+ data b24 / 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, &
+ 0.0000000, 0.0435679, 0.1102275, 0.1922249, 0.2817656, &
+ 0.3694997, 0.4532348, 0.5316253, 0.6038733, 0.6695556, &
+ 0.7285176, 0.7808017, 0.8265992, 0.8662148, 0.9000406, &
+ 0.9285364, 0.9522140, 0.9716252, 0.9873523, 1.0000000 /
+
+! Jablonowski & Williamson 26-level setup
+ data a26 / 219.4067, 489.5209, 988.2418, 1805.2010, 2983.7240, 4462.3340, &
+ 6160.5870, 7851.2430, 7731.2710, 7590.1310, 7424.0860, &
+ 7228.7440, 6998.9330, 6728.5740, 6410.5090, 6036.3220, &
+ 5596.1110, 5078.2250, 4468.9600, 3752.1910, 2908.9490, &
+ 2084.739, 1334.443, 708.499, 252.1360, 0.0, 0.0 /
+
+ data b26 / 0.0, 0.0, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,&
+ 0.0000000, 0.01505309, 0.03276228, 0.05359622, 0.07810627, &
+ 0.1069411, 0.1408637, 0.1807720, 0.2277220, 0.2829562, &
+ 0.3479364, 0.4243822, 0.5143168, 0.6201202, 0.7235355, &
+ 0.8176768, 0.8962153, 0.9534761, 0.9851122, 1.0000000 /
+
+
+! High-resolution troposphere setup
+#ifdef OLD_32
+! Revised Apr 14, 2004: PINT = 245.027 mb
+ data a32/100.00000, 400.00000, 818.60211, &
+ 1378.88653, 2091.79519, 2983.64084, &
+ 4121.78960, 5579.22148, 7419.79300, &
+ 9704.82578, 12496.33710, 15855.26306, &
+ 19839.62499, 24502.73262, 28177.10152, &
+ 29525.28447, 29016.34358, 27131.32792, &
+ 24406.11225, 21326.04907, 18221.18357, &
+ 15275.14642, 12581.67796, 10181.42843, &
+ 8081.89816, 6270.86956, 4725.35001, &
+ 3417.39199, 2317.75459, 1398.09473, &
+ 632.49506, 0.00000, 0.00000 /
+
+ data b32/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.01711, &
+ 0.06479, 0.13730, 0.22693, &
+ 0.32416, 0.42058, 0.51105, &
+ 0.59325, 0.66628, 0.73011, &
+ 0.78516, 0.83217, 0.87197, &
+ 0.90546, 0.93349, 0.95685, &
+ 0.97624, 0.99223, 1.00000 /
+#else
+! SJL June 26, 2012
+! pint= 55.7922
+ data a32/100.00000, 400.00000, 818.60211, &
+ 1378.88653, 2091.79519, 2983.64084, &
+ 4121.78960, 5579.22148, 6907.19063, &
+ 7735.78639, 8197.66476, 8377.95525, &
+ 8331.69594, 8094.72213, 7690.85756, &
+ 7139.01788, 6464.80251, 5712.35727, &
+ 4940.05347, 4198.60465, 3516.63294, &
+ 2905.19863, 2366.73733, 1899.19455, &
+ 1497.78137, 1156.25252, 867.79199, &
+ 625.59324, 423.21322, 254.76613, &
+ 115.06646, 0.00000, 0.00000 /
+
+ data b32/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00513, &
+ 0.01969, 0.04299, 0.07477, &
+ 0.11508, 0.16408, 0.22198, &
+ 0.28865, 0.36281, 0.44112, &
+ 0.51882, 0.59185, 0.65810, &
+ 0.71694, 0.76843, 0.81293, &
+ 0.85100, 0.88331, 0.91055, &
+ 0.93338, 0.95244, 0.96828, &
+ 0.98142, 0.99223, 1.00000 /
+#endif
+
+!---------------------
+! Wilson's 32L settings:
+!---------------------
+! Top changed to 0.01 mb
+ data a32w/ 1.00, 26.6378, 84.5529, 228.8592, &
+ 539.9597, 1131.7087, 2141.8082, 3712.0454, &
+ 5963.5317, 8974.1873, 12764.5388, 17294.5911, &
+ 20857.7007, 22221.8651, 22892.7202, 22891.1641, &
+ 22286.0724, 21176.0846, 19673.0671, 17889.0989, &
+ 15927.5060, 13877.6239, 11812.5474, 9865.8830, &
+ 8073.9717, 6458.0824, 5027.9893, 3784.6104, &
+ 2722.0093, 1828.9741, 1090.2397, 487.4575, &
+ 0.0000 /
+
+ data b32w/ 0.0000, 0.0000, 0.0000, 0.0000, &
+ 0.0000, 0.0000, 0.0000, 0.0000, &
+ 0.0000, 0.0000, 0.0000, 0.0000, &
+ 0.0159, 0.0586, 0.1117, 0.1734, &
+ 0.2415, 0.3137, 0.3878, 0.4619, &
+ 0.5344, 0.6039, 0.6696, 0.7285, &
+ 0.7808, 0.8266, 0.8662, 0.9000, &
+ 0.9285, 0.9522, 0.9716, 0.9874, &
+ 1.0000 /
+
+
+#ifdef OLD_L47
+! QBO setting with ptop = 0.1 mb and p_full=0.17 mb; pint ~ 100 mb
+ data a47/ 10.00000, 24.45365, 48.76776, &
+ 85.39458, 133.41983, 191.01402, &
+ 257.94919, 336.63306, 431.52741, &
+ 548.18995, 692.78825, 872.16512, &
+ 1094.18467, 1368.11917, 1704.99489, &
+ 2117.91945, 2622.42986, 3236.88281, &
+ 3982.89623, 4885.84733, 5975.43260, &
+ 7286.29500, 8858.72424, 10739.43477, &
+ 12982.41110, 15649.68745, 18811.37629, &
+ 22542.71275, 25724.93857, 27314.36781, &
+ 27498.59474, 26501.79312, 24605.92991, &
+ 22130.51655, 19381.30274, 16601.56419, &
+ 13952.53231, 11522.93244, 9350.82303, &
+ 7443.47723, 5790.77434, 4373.32696, &
+ 3167.47008, 2148.51663, 1293.15510, &
+ 581.62429, 0.00000, 0.00000 /
+
+ data b47/ 0.0000, 0.0000, 0.0000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.01188, 0.04650, &
+ 0.10170, 0.17401, 0.25832, &
+ 0.34850, 0.43872, 0.52448, &
+ 0.60307, 0.67328, 0.73492, &
+ 0.78834, 0.83418, 0.87320, &
+ 0.90622, 0.93399, 0.95723, &
+ 0.97650, 0.99223, 1.00000 /
+#else
+! Oct 23, 2012
+! QBO setting with ptop = 0.1 mb, pint ~ 60 mb
+ data a47/ 10.00000, 24.45365, 48.76776, &
+ 85.39458, 133.41983, 191.01402, &
+ 257.94919, 336.63306, 431.52741, &
+ 548.18995, 692.78825, 872.16512, &
+ 1094.18467, 1368.11917, 1704.99489, &
+ 2117.91945, 2622.42986, 3236.88281, &
+ 3982.89623, 4885.84733, 5975.43260, &
+ 7019.26669, 7796.15848, 8346.60209, &
+ 8700.31838, 8878.27554, 8894.27179, &
+ 8756.46404, 8469.60171, 8038.92687, &
+ 7475.89006, 6803.68067, 6058.68992, &
+ 5285.28859, 4526.01565, 3813.00206, &
+ 3164.95553, 2589.26318, 2085.96929, &
+ 1651.11596, 1278.81205, 962.38875, &
+ 695.07046, 470.40784, 282.61654, &
+ 126.92745, 0.00000, 0.00000 /
+ data b47/ 0.0000, 0.0000, 0.0000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00267, 0.01063, 0.02393, &
+ 0.04282, 0.06771, 0.09917, &
+ 0.13786, 0.18444, 0.23925, &
+ 0.30193, 0.37100, 0.44379, &
+ 0.51695, 0.58727, 0.65236, &
+ 0.71094, 0.76262, 0.80757, &
+ 0.84626, 0.87930, 0.90731, &
+ 0.93094, 0.95077, 0.96733, &
+ 0.98105, 0.99223, 1.00000 /
+#endif
+
+ data a48/ &
+ 1.00000, 2.69722, 5.17136, &
+ 8.89455, 14.24790, 22.07157, &
+ 33.61283, 50.48096, 74.79993, &
+ 109.40055, 158.00460, 225.44108, &
+ 317.89560, 443.19350, 611.11558, &
+ 833.74392, 1125.83405, 1505.20759, &
+ 1993.15829, 2614.86254, 3399.78420, &
+ 4382.06240, 5600.87014, 7100.73115, &
+ 8931.78242, 11149.97021, 13817.16841, &
+ 17001.20930, 20775.81856, 23967.33875, &
+ 25527.64563, 25671.22552, 24609.29622, &
+ 22640.51220, 20147.13482, 17477.63530, &
+ 14859.86462, 12414.92533, 10201.44191, &
+ 8241.50255, 6534.43202, 5066.17865, &
+ 3815.60705, 2758.60264, 1870.64631, &
+ 1128.33931, 510.47983, 0.00000, &
+ 0.00000 /
+
+ data b48/ &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.01253, &
+ 0.04887, 0.10724, 0.18455, &
+ 0.27461, 0.36914, 0.46103, &
+ 0.54623, 0.62305, 0.69099, &
+ 0.75016, 0.80110, 0.84453, &
+ 0.88127, 0.91217, 0.93803, &
+ 0.95958, 0.97747, 0.99223, &
+ 1.00000 /
+
+! High PBL resolution with top at 1 mb
+! SJL modified May 7, 2013 to ptop ~ 100 mb
+ data a54/100.00000, 254.83931, 729.54278, &
+ 1602.41121, 2797.50667, 4100.18977, &
+ 5334.87140, 6455.24153, 7511.80944, &
+ 8580.26355, 9714.44293, 10938.62253, &
+ 12080.36051, 12987.13921, 13692.75084, &
+ 14224.92180, 14606.55444, 14856.69953, &
+ 14991.32121, 15023.90075, 14965.91493, &
+ 14827.21612, 14616.33505, 14340.72252, &
+ 14006.94280, 13620.82849, 13187.60470, &
+ 12711.98873, 12198.27003, 11650.37451, &
+ 11071.91608, 10466.23819, 9836.44706, &
+ 9185.43852, 8515.96231, 7831.01080, &
+ 7135.14301, 6436.71659, 5749.00215, &
+ 5087.67188, 4465.67510, 3889.86419, &
+ 3361.63433, 2879.51065, 2441.02496, &
+ 2043.41345, 1683.80513, 1359.31122, &
+ 1067.09135, 804.40101, 568.62625, &
+ 357.32525, 168.33263, 0.00000, &
+ 0.00000 /
+
+ data b54/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00180, 0.00694, 0.01510, &
+ 0.02601, 0.03942, 0.05515, &
+ 0.07302, 0.09288, 0.11459, &
+ 0.13803, 0.16307, 0.18960, &
+ 0.21753, 0.24675, 0.27716, &
+ 0.30866, 0.34115, 0.37456, &
+ 0.40879, 0.44375, 0.47935, &
+ 0.51551, 0.55215, 0.58916, &
+ 0.62636, 0.66334, 0.69946, &
+ 0.73395, 0.76622, 0.79594, &
+ 0.82309, 0.84780, 0.87020, &
+ 0.89047, 0.90876, 0.92524, &
+ 0.94006, 0.95336, 0.96529, &
+ 0.97596, 0.98551, 0.99400, &
+ 1.00000 /
+
+
+! The 56-L setup
+ data a56/ 10.00000, 24.97818, 58.01160, &
+ 115.21466, 199.29210, 309.39897, &
+ 445.31785, 610.54747, 812.28518, &
+ 1059.80882, 1363.07092, 1732.09335, &
+ 2176.91502, 2707.68972, 3334.70962, &
+ 4068.31964, 4918.76594, 5896.01890, &
+ 7009.59166, 8268.36324, 9680.41211, &
+ 11252.86491, 12991.76409, 14901.95764, &
+ 16987.01313, 19249.15733, 21689.24182, &
+ 23845.11055, 25330.63353, 26243.52467, &
+ 26663.84998, 26657.94696, 26281.61371, &
+ 25583.05256, 24606.03265, 23393.39510, &
+ 21990.28845, 20445.82122, 18811.93894, &
+ 17139.59660, 15473.90350, 13850.50167, &
+ 12294.49060, 10821.62655, 9440.57746, &
+ 8155.11214, 6965.72496, 5870.70511, &
+ 4866.83822, 3949.90019, 3115.03562, &
+ 2357.07879, 1670.87329, 1051.65120, &
+ 495.51399, 0.00000, 0.00000 /
+
+ data b56 /0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00462, 0.01769, 0.03821, &
+ 0.06534, 0.09834, 0.13659, &
+ 0.17947, 0.22637, 0.27660, &
+ 0.32929, 0.38343, 0.43791, &
+ 0.49162, 0.54361, 0.59319, &
+ 0.63989, 0.68348, 0.72391, &
+ 0.76121, 0.79545, 0.82679, &
+ 0.85537, 0.88135, 0.90493, &
+ 0.92626, 0.94552, 0.96286, &
+ 0.97840, 0.99223, 1.00000 /
+
+ data a60/ 1.7861000000e-01, 1.0805100000e+00, 3.9647100000e+00, &
+ 9.7516000000e+00, 1.9816580000e+01, 3.6695950000e+01, &
+ 6.2550570000e+01, 9.9199620000e+01, 1.4792505000e+02, &
+ 2.0947487000e+02, 2.8422571000e+02, 3.7241721000e+02, &
+ 4.7437835000e+02, 5.9070236000e+02, 7.2236063000e+02, &
+ 8.7076746000e+02, 1.0378138800e+03, 1.2258877300e+03, &
+ 1.4378924600e+03, 1.6772726600e+03, 1.9480506400e+03, &
+ 2.2548762700e+03, 2.6030909400e+03, 2.9988059200e+03, &
+ 3.4489952300e+03, 3.9616028900e+03, 4.5456641600e+03, &
+ 5.2114401700e+03, 5.9705644000e+03, 6.8361981800e+03, &
+ 7.8231906000e+03, 8.9482351000e+03, 1.0230010660e+04, &
+ 1.1689289750e+04, 1.3348986860e+04, 1.5234111060e+04, &
+ 1.7371573230e+04, 1.9789784580e+04, 2.2005564550e+04, &
+ 2.3550115120e+04, 2.4468583320e+04, 2.4800548800e+04, &
+ 2.4582445070e+04, 2.3849999620e+04, 2.2640519740e+04, &
+ 2.0994737150e+04, 1.8957848730e+04, 1.6579413230e+04, &
+ 1.4080071030e+04, 1.1753630920e+04, 9.6516996300e+03, &
+ 7.7938009300e+03, 6.1769062800e+03, 4.7874276000e+03, &
+ 3.6050497500e+03, 2.6059860700e+03, 1.7668328200e+03, &
+ 1.0656131200e+03, 4.8226201000e+02, 0.0000000000e+00, &
+ 0.0000000000e+00 /
+
+
+ data b60/ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 5.0600000000e-03, &
+ 2.0080000000e-02, 4.4900000000e-02, 7.9360000000e-02, &
+ 1.2326000000e-01, 1.7634000000e-01, 2.3820000000e-01, &
+ 3.0827000000e-01, 3.8581000000e-01, 4.6989000000e-01, &
+ 5.5393000000e-01, 6.2958000000e-01, 6.9642000000e-01, &
+ 7.5458000000e-01, 8.0463000000e-01, 8.4728000000e-01, &
+ 8.8335000000e-01, 9.1368000000e-01, 9.3905000000e-01, &
+ 9.6020000000e-01, 9.7775000000e-01, 9.9223000000e-01, &
+ 1.0000000000e+00 /
+
+! This is activated by USE_GFSL63
+! Thfollowing L63 setting is the same as NCEP GFS's L64 except the top
+! 3 layers
+ data a63/64.247, 137.790, 221.958, &
+ 318.266, 428.434, 554.424, &
+ 698.457, 863.05803, 1051.07995, &
+ 1265.75194, 1510.71101, 1790.05098, &
+ 2108.36604, 2470.78817, 2883.03811, &
+ 3351.46002, 3883.05187, 4485.49315, &
+ 5167.14603, 5937.04991, 6804.87379, &
+ 7780.84698, 8875.64338, 10100.20534, &
+ 11264.35673, 12190.64366, 12905.42546, &
+ 13430.87867, 13785.88765, 13986.77987, &
+ 14047.96335, 13982.46770, 13802.40331, &
+ 13519.33841, 13144.59486, 12689.45608, &
+ 12165.28766, 11583.57006, 10955.84778, &
+ 10293.60402, 9608.08306, 8910.07678, &
+ 8209.70131, 7516.18560, 6837.69250, &
+ 6181.19473, 5552.39653, 4955.72632, &
+ 4394.37629, 3870.38682, 3384.76586, &
+ 2937.63489, 2528.37666, 2155.78385, &
+ 1818.20722, 1513.68173, 1240.03585, &
+ 994.99144, 776.23591, 581.48797, &
+ 408.53400, 255.26520, 119.70243, 0. /
+
+ data b63/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00201, 0.00792, 0.01755, &
+ 0.03079, 0.04751, 0.06761, &
+ 0.09097, 0.11746, 0.14690, &
+ 0.17911, 0.21382, 0.25076, &
+ 0.28960, 0.32994, 0.37140, &
+ 0.41353, 0.45589, 0.49806, &
+ 0.53961, 0.58015, 0.61935, &
+ 0.65692, 0.69261, 0.72625, &
+ 0.75773, 0.78698, 0.81398, &
+ 0.83876, 0.86138, 0.88192, &
+ 0.90050, 0.91722, 0.93223, &
+ 0.94565, 0.95762, 0.96827, &
+ 0.97771, 0.98608, 0.99347, 1./
+#ifdef GFSL64
+ data a64/20.00000, 68.00000, 137.79000, &
+ 221.95800, 318.26600, 428.43400, &
+ 554.42400, 698.45700, 863.05803, &
+ 1051.07995, 1265.75194, 1510.71101, &
+ 1790.05098, 2108.36604, 2470.78817, &
+ 2883.03811, 3351.46002, 3883.05187, &
+ 4485.49315, 5167.14603, 5937.04991, &
+ 6804.87379, 7780.84698, 8875.64338, &
+ 9921.40745, 10760.99844, 11417.88354, &
+ 11911.61193, 12258.61668, 12472.89642, &
+ 12566.58298, 12550.43517, 12434.26075, &
+ 12227.27484, 11938.39468, 11576.46910, &
+ 11150.43640, 10669.41063, 10142.69482, &
+ 9579.72458, 8989.94947, 8382.67090, &
+ 7766.85063, 7150.91171, 6542.55077, &
+ 5948.57894, 5374.81094, 4825.99383, &
+ 4305.79754, 3816.84622, 3360.78848, &
+ 2938.39801, 2549.69756, 2194.08449, &
+ 1870.45732, 1577.34218, 1313.00028, &
+ 1075.52114, 862.90778, 673.13815, &
+ 504.22118, 354.22752, 221.32110, &
+ 103.78014, 0./
+ data b64/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00179, 0.00705, 0.01564, &
+ 0.02749, 0.04251, 0.06064, &
+ 0.08182, 0.10595, 0.13294, &
+ 0.16266, 0.19492, 0.22950, &
+ 0.26615, 0.30455, 0.34435, &
+ 0.38516, 0.42656, 0.46815, &
+ 0.50949, 0.55020, 0.58989, &
+ 0.62825, 0.66498, 0.69987, &
+ 0.73275, 0.76351, 0.79208, &
+ 0.81845, 0.84264, 0.86472, &
+ 0.88478, 0.90290, 0.91923, &
+ 0.93388, 0.94697, 0.95865, &
+ 0.96904, 0.97826, 0.98642, &
+ 0.99363, 1./
+#else
+ data a64/1.00000, 3.90000, 8.70000, &
+ 15.42000, 24.00000, 34.50000, &
+ 47.00000, 61.50000, 78.60000, &
+ 99.13500, 124.12789, 154.63770, &
+ 191.69700, 236.49300, 290.38000, &
+ 354.91000, 431.82303, 523.09300, &
+ 630.92800, 757.79000, 906.45000, &
+ 1079.85000, 1281.00000, 1515.00000, &
+ 1788.00000, 2105.00000, 2470.00000, &
+ 2889.00000, 3362.00000, 3890.00000, &
+ 4475.00000, 5120.00000, 5830.00000, &
+ 6608.00000, 7461.00000, 8395.00000, &
+ 9424.46289, 10574.46880, 11864.80270, &
+ 13312.58890, 14937.03710, 16759.70700, &
+ 18804.78710, 21099.41210, 23674.03710, &
+ 26562.82810, 29804.11720, 32627.31640, &
+ 34245.89840, 34722.28910, 34155.19920, &
+ 32636.50390, 30241.08200, 27101.44920, &
+ 23362.20700, 19317.05270, 15446.17090, &
+ 12197.45210, 9496.39941, 7205.66992, &
+ 5144.64307, 3240.79346, 1518.62134, &
+ 0.00000, 0.00000 /
+
+ data b64/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00813, &
+ 0.03224, 0.07128, 0.12445, &
+ 0.19063, 0.26929, 0.35799, &
+ 0.45438, 0.55263, 0.64304, &
+ 0.71703, 0.77754, 0.82827, &
+ 0.87352, 0.91502, 0.95235, &
+ 0.98511, 1.00000 /
+#endif
+!-->cjg
+ data a68/1.00000, 2.68881, 5.15524, &
+ 8.86683, 14.20349, 22.00278, &
+ 33.50807, 50.32362, 74.56680, &
+ 109.05958, 157.51214, 224.73844, &
+ 316.90481, 441.81219, 609.21090, &
+ 831.14537, 1122.32514, 1500.51628, &
+ 1986.94617, 2606.71274, 3389.18802, &
+ 4368.40473, 5583.41379, 7078.60015, &
+ 8903.94455, 11115.21886, 13774.60566, &
+ 16936.82070, 20340.47045, 23193.71492, &
+ 24870.36141, 25444.59363, 25252.57081, &
+ 24544.26211, 23474.29096, 22230.65331, &
+ 20918.50731, 19589.96280, 18296.26682, &
+ 17038.02866, 15866.85655, 14763.18943, &
+ 13736.83624, 12794.11850, 11930.72442, &
+ 11137.17217, 10404.78946, 9720.03954, &
+ 9075.54055, 8466.72650, 7887.12346, &
+ 7333.90490, 6805.43028, 6297.33773, &
+ 5805.78227, 5327.94995, 4859.88765, &
+ 4398.63854, 3942.81761, 3491.08449, &
+ 3043.04531, 2598.71608, 2157.94527, &
+ 1720.87444, 1287.52805, 858.02944, &
+ 432.71276, 8.10905, 0.00000 /
+
+ data b68/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00283, 0.01590, &
+ 0.04412, 0.08487, 0.13284, &
+ 0.18470, 0.23828, 0.29120, &
+ 0.34211, 0.39029, 0.43518, &
+ 0.47677, 0.51536, 0.55091, &
+ 0.58331, 0.61263, 0.63917, &
+ 0.66333, 0.68552, 0.70617, &
+ 0.72555, 0.74383, 0.76117, &
+ 0.77765, 0.79335, 0.80838, &
+ 0.82287, 0.83693, 0.85069, &
+ 0.86423, 0.87760, 0.89082, &
+ 0.90392, 0.91689, 0.92973, &
+ 0.94244, 0.95502, 0.96747, &
+ 0.97979, 0.99200, 1.00000 /
+
+ data a96/1.00000, 2.35408, 4.51347, &
+ 7.76300, 12.43530, 19.26365, &
+ 29.33665, 44.05883, 65.28397, &
+ 95.48274, 137.90344, 196.76073, &
+ 277.45330, 386.81095, 533.37018, &
+ 727.67600, 982.60677, 1313.71685, &
+ 1739.59104, 2282.20281, 2967.26766, &
+ 3824.58158, 4888.33404, 6197.38450, &
+ 7795.49158, 9731.48414, 11969.71024, &
+ 14502.88894, 17304.52434, 20134.76139, &
+ 22536.63814, 24252.54459, 25230.65591, &
+ 25585.72044, 25539.91412, 25178.87141, &
+ 24644.84493, 23978.98781, 23245.49366, &
+ 22492.11600, 21709.93990, 20949.64473, &
+ 20225.94258, 19513.31158, 18829.32485, &
+ 18192.62250, 17589.39396, 17003.45386, &
+ 16439.01774, 15903.91204, 15396.39758, &
+ 14908.02140, 14430.65897, 13967.88643, &
+ 13524.16667, 13098.30227, 12687.56457, &
+ 12287.08757, 11894.41553, 11511.54106, &
+ 11139.22483, 10776.01912, 10419.75711, &
+ 10067.11881, 9716.63489, 9369.61967, &
+ 9026.69066, 8687.29884, 8350.04978, &
+ 8013.20925, 7677.12187, 7343.12994, &
+ 7011.62844, 6681.98102, 6353.09764, &
+ 6025.10535, 5699.10089, 5375.54503, &
+ 5053.63074, 4732.62740, 4413.38037, &
+ 4096.62775, 3781.79777, 3468.45371, &
+ 3157.19882, 2848.25306, 2541.19150, &
+ 2236.21942, 1933.50628, 1632.83741, &
+ 1334.35954, 1038.16655, 744.22318, &
+ 452.71094, 194.91899, 0.00000, &
+ 0.00000 /
+
+ data b96/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00193, &
+ 0.00974, 0.02538, 0.04876, &
+ 0.07817, 0.11081, 0.14514, &
+ 0.18007, 0.21486, 0.24866, &
+ 0.28088, 0.31158, 0.34030, &
+ 0.36701, 0.39210, 0.41554, &
+ 0.43733, 0.45774, 0.47707, &
+ 0.49540, 0.51275, 0.52922, &
+ 0.54495, 0.56007, 0.57459, &
+ 0.58850, 0.60186, 0.61471, &
+ 0.62715, 0.63922, 0.65095, &
+ 0.66235, 0.67348, 0.68438, &
+ 0.69510, 0.70570, 0.71616, &
+ 0.72651, 0.73675, 0.74691, &
+ 0.75700, 0.76704, 0.77701, &
+ 0.78690, 0.79672, 0.80649, &
+ 0.81620, 0.82585, 0.83542, &
+ 0.84492, 0.85437, 0.86375, &
+ 0.87305, 0.88229, 0.89146, &
+ 0.90056, 0.90958, 0.91854, &
+ 0.92742, 0.93623, 0.94497, &
+ 0.95364, 0.96223, 0.97074, &
+ 0.97918, 0.98723, 0.99460, &
+ 1.00000 /
+!<--cjg
+!
+! Ultra high troposphere resolution
+ data a100/100.00000, 300.00000, 800.00000, &
+ 1762.35235, 3106.43596, 4225.71874, &
+ 4946.40525, 5388.77387, 5708.35540, &
+ 5993.33124, 6277.73673, 6571.49996, &
+ 6877.05339, 7195.14327, 7526.24920, &
+ 7870.82981, 8229.35361, 8602.30193, &
+ 8990.16936, 9393.46399, 9812.70768, &
+ 10248.43625, 10701.19980, 11171.56286, &
+ 11660.10476, 12167.41975, 12694.11735, &
+ 13240.82253, 13808.17600, 14396.83442, &
+ 15007.47066, 15640.77407, 16297.45067, &
+ 16978.22343, 17683.83253, 18415.03554, &
+ 19172.60771, 19957.34218, 20770.05022, &
+ 21559.14829, 22274.03147, 22916.87519, &
+ 23489.70456, 23994.40187, 24432.71365, &
+ 24806.25734, 25116.52754, 25364.90190, &
+ 25552.64670, 25680.92203, 25750.78675, &
+ 25763.20311, 25719.04113, 25619.08274, &
+ 25464.02630, 25254.49482, 24991.06137, &
+ 24674.32737, 24305.11235, 23884.79781, &
+ 23415.77059, 22901.76510, 22347.84738, &
+ 21759.93950, 21144.07284, 20505.73136, &
+ 19849.54271, 19179.31412, 18498.23400, &
+ 17809.06809, 17114.28232, 16416.10343, &
+ 15716.54833, 15017.44246, 14320.43478, &
+ 13627.01116, 12938.50682, 12256.11762, &
+ 11580.91062, 10913.83385, 10255.72526, &
+ 9607.32122, 8969.26427, 8342.11044, &
+ 7726.33606, 7122.34405, 6530.46991, &
+ 5950.98721, 5384.11279, 4830.01153, &
+ 4288.80090, 3760.55514, 3245.30920, &
+ 2743.06250, 2253.78294, 1777.41285, &
+ 1313.88054, 863.12371, 425.13088, &
+ 0.00000, 0.00000 /
+
+
+ data b100/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00052, 0.00209, 0.00468, &
+ 0.00828, 0.01288, 0.01849, &
+ 0.02508, 0.03266, 0.04121, &
+ 0.05075, 0.06126, 0.07275, &
+ 0.08521, 0.09866, 0.11308, &
+ 0.12850, 0.14490, 0.16230, &
+ 0.18070, 0.20009, 0.22042, &
+ 0.24164, 0.26362, 0.28622, &
+ 0.30926, 0.33258, 0.35605, &
+ 0.37958, 0.40308, 0.42651, &
+ 0.44981, 0.47296, 0.49591, &
+ 0.51862, 0.54109, 0.56327, &
+ 0.58514, 0.60668, 0.62789, &
+ 0.64872, 0.66919, 0.68927, &
+ 0.70895, 0.72822, 0.74709, &
+ 0.76554, 0.78357, 0.80117, &
+ 0.81835, 0.83511, 0.85145, &
+ 0.86736, 0.88286, 0.89794, &
+ 0.91261, 0.92687, 0.94073, &
+ 0.95419, 0.96726, 0.97994, &
+ 0.99223, 1.00000 /
+
+ data a104/ &
+ 1.8827062944e-01, 7.7977549145e-01, 2.1950593583e+00, &
+ 4.9874566624e+00, 9.8041418997e+00, 1.7019717163e+01, &
+ 2.7216579591e+01, 4.0518628401e+01, 5.6749646818e+01, &
+ 7.5513868331e+01, 9.6315093333e+01, 1.1866706195e+02, &
+ 1.4216835396e+02, 1.6653733709e+02, 1.9161605772e+02, &
+ 2.1735580129e+02, 2.4379516604e+02, 2.7103771847e+02, &
+ 2.9923284173e+02, 3.2856100952e+02, 3.5922338766e+02, &
+ 3.9143507908e+02, 4.2542117983e+02, 4.6141487902e+02, &
+ 4.9965698106e+02, 5.4039638379e+02, 5.8389118154e+02, &
+ 6.3041016829e+02, 6.8023459505e+02, 7.3366009144e+02, &
+ 7.9099869949e+02, 8.5258099392e+02, 9.1875827946e+02, &
+ 9.8990486716e+02, 1.0664204381e+03, 1.1487325074e+03, &
+ 1.2372990044e+03, 1.3326109855e+03, 1.4351954993e+03, &
+ 1.5456186222e+03, 1.6644886848e+03, 1.7924597105e+03, &
+ 1.9302350870e+03, 2.0785714934e+03, 2.2382831070e+03, &
+ 2.4102461133e+03, 2.5954035462e+03, 2.7947704856e+03, &
+ 3.0094396408e+03, 3.2405873512e+03, 3.4894800360e+03, &
+ 3.7574811281e+03, 4.0460585279e+03, 4.3567926151e+03, &
+ 4.6913848588e+03, 5.0516670674e+03, 5.4396113207e+03, &
+ 5.8573406270e+03, 6.3071403487e+03, 6.7914704368e+03, &
+ 7.3129785102e+03, 7.8745138115e+03, 8.4791420557e+03, &
+ 9.1301611750e+03, 9.8311179338e+03, 1.0585825354e+04, &
+ 1.1398380836e+04, 1.2273184781e+04, 1.3214959424e+04, &
+ 1.4228767429e+04, 1.5320029596e+04, 1.6494540743e+04, &
+ 1.7758482452e+04, 1.9118430825e+04, 2.0422798801e+04, &
+ 2.1520147587e+04, 2.2416813461e+04, 2.3118184510e+04, &
+ 2.3628790785e+04, 2.3952411814e+04, 2.4092209011e+04, &
+ 2.4050892106e+04, 2.3830930156e+04, 2.3434818358e+04, &
+ 2.2865410898e+04, 2.2126326004e+04, 2.1222420323e+04, &
+ 2.0160313690e+04, 1.8948920926e+04, 1.7599915822e+04, &
+ 1.6128019809e+04, 1.4550987232e+04, 1.2889169132e+04, &
+ 1.1164595563e+04, 9.4227665517e+03, 7.7259097899e+03, &
+ 6.1538244381e+03, 4.7808126007e+03, 3.5967415552e+03, &
+ 2.5886394104e+03, 1.7415964865e+03, 1.0393721271e+03, &
+ 4.6478852032e+02, 7.0308342481e-13, 0.0000000000e+00 /
+
+
+ data b104/ &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 1.5648447298e-03, &
+ 6.2617046389e-03, 1.4104157933e-02, 2.5118187415e-02, &
+ 3.9340510972e-02, 5.6816335609e-02, 7.7596328431e-02, &
+ 1.0173255472e-01, 1.2927309709e-01, 1.6025505622e-01, &
+ 1.9469566981e-01, 2.3258141217e-01, 2.7385520518e-01, &
+ 3.1840233814e-01, 3.6603639170e-01, 4.1648734767e-01, &
+ 4.6939496013e-01, 5.2431098738e-01, 5.8071350676e-01, &
+ 6.3803478105e-01, 6.9495048840e-01, 7.4963750338e-01, &
+ 7.9975208897e-01, 8.4315257576e-01, 8.8034012292e-01, &
+ 9.1184389721e-01, 9.3821231526e-01, 9.6000677644e-01, &
+ 9.7779792223e-01, 9.9216315122e-01, 1.0000000000e+00 /
+
+! IFS-like L125(top 12 levels removed from IFSL137)
+ data a125/ 64., &
+ 86.895882, 107.415741, 131.425507, 159.279404, 191.338562, &
+ 227.968948, 269.539581, 316.420746, 368.982361, 427.592499, 492.616028, &
+ 564.413452, 643.339905, 729.744141, 823.967834, 926.344910, 1037.201172, &
+ 1156.853638, 1285.610352, 1423.770142, 1571.622925, 1729.448975, 1897.519287, &
+ 2076.095947, 2265.431641, 2465.770508, 2677.348145, 2900.391357, 3135.119385, &
+ 3381.743652, 3640.468262, 3911.490479, 4194.930664, 4490.817383, 4799.149414, &
+ 5119.895020, 5452.990723, 5798.344727, 6156.074219, 6526.946777, 6911.870605, &
+ 7311.869141, 7727.412109, 8159.354004, 8608.525391, 9076.400391, 9562.682617, &
+ 10065.978516, 10584.631836, 11116.662109, 11660.067383, 12211.547852, 12766.873047, &
+ 13324.668945, 13881.331055, 14432.139648, 14975.615234, 15508.256836, 16026.115234, &
+ 16527.322266, 17008.789063, 17467.613281, 17901.621094, 18308.433594, 18685.718750, &
+ 19031.289063, 19343.511719, 19620.042969, 19859.390625, 20059.931641, 20219.664063, &
+ 20337.863281, 20412.308594, 20442.078125, 20425.718750, 20361.816406, 20249.511719, &
+ 20087.085938, 19874.025391, 19608.572266, 19290.226563, 18917.460938, 18489.707031, &
+ 18006.925781, 17471.839844, 16888.687500, 16262.046875, 15596.695313, 14898.453125, &
+ 14173.324219, 13427.769531, 12668.257813, 11901.339844, 11133.304688, 10370.175781, &
+ 9617.515625, 8880.453125, 8163.375000, 7470.343750, 6804.421875, 6168.531250, &
+ 5564.382813, 4993.796875, 4457.375000, 3955.960938, 3489.234375, 3057.265625, &
+ 2659.140625, 2294.242188, 1961.500000, 1659.476563, 1387.546875, 1143.250000, &
+ 926.507813, 734.992188, 568.062500, 424.414063, 302.476563, 202.484375, &
+ 122.101563, 62.781250, 22.835938, 3.757813, 0.000000, 0.000000 /
+
+ data b125/ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000007, 0.000024, 0.000059, 0.000112, 0.000199, &
+ 0.000340, 0.000562, 0.000890, 0.001353, 0.001992, 0.002857, &
+ 0.003971, 0.005378, 0.007133, 0.009261, 0.011806, 0.014816, &
+ 0.018318, 0.022355, 0.026964, 0.032176, 0.038026, 0.044548, &
+ 0.051773, 0.059728, 0.068448, 0.077958, 0.088286, 0.099462, &
+ 0.111505, 0.124448, 0.138313, 0.153125, 0.168910, 0.185689, &
+ 0.203491, 0.222333, 0.242244, 0.263242, 0.285354, 0.308598, &
+ 0.332939, 0.358254, 0.384363, 0.411125, 0.438391, 0.466003, &
+ 0.493800, 0.521619, 0.549301, 0.576692, 0.603648, 0.630036, &
+ 0.655736, 0.680643, 0.704669, 0.727739, 0.749797, 0.770798, &
+ 0.790717, 0.809536, 0.827256, 0.843881, 0.859432, 0.873929, &
+ 0.887408, 0.899900, 0.911448, 0.922096, 0.931881, 0.940860, &
+ 0.949064, 0.956550, 0.963352, 0.969513, 0.975078, 0.980072, &
+ 0.984542, 0.988500, 0.991984, 0.995003, 0.997630, 1.000000 /
+
+ select case (km)
+
+ case (24)
+
+ ks = 5
+ do k=1,km+1
+ ak(k) = a24(k)
+ bk(k) = b24(k)
+ enddo
+
+ case (26)
+
+ ks = 7
+ do k=1,km+1
+ ak(k) = a26(k)
+ bk(k) = b26(k)
+ enddo
+
+ case (32)
+#ifdef OLD_32
+ ks = 13 ! high-res trop_32 setup
+#else
+ ks = 7
+#endif
+ do k=1,km+1
+ ak(k) = a32(k)
+ bk(k) = b32(k)
+ enddo
+
+ case (47)
+! ks = 27 ! high-res trop-strat
+ ks = 20 ! Oct 23, 2012
+ do k=1,km+1
+ ak(k) = a47(k)
+ bk(k) = b47(k)
+ enddo
+
+ case (48)
+ ks = 28
+ do k=1,km+1
+ ak(k) = a48(k)
+ bk(k) = b48(k)
+ enddo
+
+ case (52)
+ ks = 35 ! pint = 223
+ do k=1,km+1
+ ak(k) = a52(k)
+ bk(k) = b52(k)
+ enddo
+
+ case (54)
+ ks = 11 ! pint = 109.4
+ do k=1,km+1
+ ak(k) = a54(k)
+ bk(k) = b54(k)
+ enddo
+
+ case (56)
+ ks = 26
+ do k=1,km+1
+ ak(k) = a56(k)
+ bk(k) = b56(k)
+ enddo
+
+ case (60)
+ ks = 37
+ do k=1,km+1
+ ak(k) = a60(k)
+ bk(k) = b60(k)
+ enddo
+
+
+ case (64)
+#ifdef GFSL64
+ ks = 23
+#else
+ ks = 46
+#endif
+ do k=1,km+1
+ ak(k) = a64(k)
+ bk(k) = b64(k)
+ enddo
+!-->cjg
+ case (68)
+ ks = 27
+ do k=1,km+1
+ ak(k) = a68(k)
+ bk(k) = b68(k)
+ enddo
+
+ case (96)
+ ks = 27
+ do k=1,km+1
+ ak(k) = a96(k)
+ bk(k) = b96(k)
+ enddo
+!<--cjg
+
+ case (100)
+ ks = 38
+ do k=1,km+1
+ ak(k) = a100(k)
+ bk(k) = b100(k)
+ enddo
+
+ case (104)
+ ks = 73
+ do k=1,km+1
+ ak(k) = a104(k)
+ bk(k) = b104(k)
+ enddo
+
+#ifndef TEST_GWAVES
+ case (10)
+!--------------------------------------------------
+! Pure sigma-coordinate with uniform spacing in "z"
+!--------------------------------------------------
+!
+ pt = 2000. ! model top pressure (pascal)
+! pt = 100. ! 1 mb
+ press(1) = pt
+ press(km+1) = p0
+ dlnp = (log(p0) - log(pt)) / real(km)
+
+ lnpe = log(press(km+1))
+ do k=km,2,-1
+ lnpe = lnpe - dlnp
+ press(k) = exp(lnpe)
+ enddo
+
+! Search KS
+ ks = 0
+ do k=1,km
+ if(press(k) >= pc) then
+ ks = k-1
+ goto 123
+ endif
+ enddo
+123 continue
+
+ if(ks /= 0) then
+ do k=1,ks
+ ak(k) = press(k)
+ bk(k) = 0.
+ enddo
+ endif
+
+ pint = press(ks+1)
+ do k=ks+1,km
+ ak(k) = pint*(press(km)-press(k))/(press(km)-pint)
+ bk(k) = (press(k) - ak(k)) / press(km+1)
+ enddo
+ ak(km+1) = 0.
+ bk(km+1) = 1.
+
+! do k=2,km
+! bk(k) = real(k-1) / real(km)
+! ak(k) = pt * ( 1. - bk(k) )
+! enddo
+#endif
+
+! The following 4 selections are better for non-hydrostatic
+! Low top:
+ case (31)
+ ptop = 300.
+ pint = 100.E2
+ call var_dz(km, ak, bk, ptop, ks, pint, 1.035)
+#ifndef TEST_GWAVES
+ case (41)
+ ptop = 100.
+ pint = 100.E2
+ call var_hi(km, ak, bk, ptop, ks, pint, 1.035)
+#endif
+ case (51)
+ ptop = 100.
+ pint = 100.E2
+ call var_hi(km, ak, bk, ptop, ks, pint, 1.035)
+! Mid-top:
+ case (55)
+ ptop = 10.
+ pint = 100.E2
+! call var_dz(km, ak, bk, ptop, ks, pint, 1.035)
+ call var_hi(km, ak, bk, ptop, ks, pint, 1.035)
+#ifdef USE_GFSL63
+! GFS L64 equivalent setting
+ case (63)
+ ks = 23
+ ptop = a63(1)
+ pint = a63(ks+1)
+ do k=1,km+1
+ ak(k) = a63(k)
+ bk(k) = b63(k)
+ enddo
+#else
+ case (63)
+ ptop = 1. ! high top
+ pint = 100.E2
+ call var_hi(km, ak, bk, ptop, ks, pint, 1.035)
+#endif
+! NGGPS_GFS
+ case (91)
+ pint = 100.E2
+ ptop = 40.
+ call var_gfs(km, ak, bk, ptop, ks, pint, 1.029)
+! call var_gfs(km, ak, bk, ptop, ks, pint, 1.03)
+ case (95)
+! Mid-top settings:
+ pint = 100.E2
+ ptop = 20.
+ call var_gfs(km, ak, bk, ptop, ks, pint, 1.028)
+ case (127)
+ ptop = 1.
+ pint = 75.E2
+ call var_gfs(km, ak, bk, ptop, ks, pint, 1.028)
+! IFS-like L125
+ case (125)
+ ks = 33
+ ptop = a125(1)
+ pint = a125(ks+1)
+ do k=1,km+1
+ ak(k) = a125(k)
+ bk(k) = b125(k)
+ enddo
+ case default
+
+#ifdef TEST_GWAVES
+!--------------------------------------------------
+! Pure sigma-coordinate with uniform spacing in "z"
+!--------------------------------------------------
+ call gw_1d(km, 1000.E2, ak, bk, ptop, 10.E3, pt1)
+ ks = 0
+ pint = ak(1)
+#else
+
+!----------------------------------------------------------------
+! Sigma-coordinate with uniform spacing in sigma and ptop = 1 mb
+!----------------------------------------------------------------
+ pt = 100.
+! One pressure layer
+ ks = 1
+! pint = pt + 0.5*1.E5/real(km) ! SJL: 20120327
+ pint = pt + 1.E5/real(km)
+
+ ak(1) = pt
+ bk(1) = 0.
+ ak(2) = pint
+ bk(2) = 0.
+
+ do k=3,km+1
+ bk(k) = real(k-2) / real(km-1)
+ ak(k) = pint - bk(k)*pint
+ enddo
+ ak(km+1) = 0.
+ bk(km+1) = 1.
+#endif
+ end select
+ ptop = ak(1)
+ pint = ak(ks+1)
+
+ end subroutine set_eta
+#endif
+
+!>@brief The subroutine 'set_external_eta' sets 'ptop' (model top) and
+!! 'ks' (first level of pure pressure coordinates given the coefficients
+!! 'ak' and 'bk'
+ subroutine set_external_eta(ak, bk, ptop, ks)
+ implicit none
+ real, intent(in) :: ak(:)
+ real, intent(in) :: bk(:)
+ real, intent(out) :: ptop !< model top (Pa)
+ integer, intent(out) :: ks !< number of pure p layers
+ !--- local variables
+ integer :: k
+ real :: eps = 1.d-7
+
+ ptop = ak(1)
+ ks = 1
+ do k = 1, size(bk(:))
+ if (bk(k).lt.eps) ks = k
+ enddo
+ !--- change ks to layers from levels
+ ks = ks - 1
+ if (is_master()) write(6,*) ' ptop & ks ', ptop, ks
+
+ end subroutine set_external_eta
+
+
+ subroutine var_les(km, ak, bk, ptop, ks, pint, s_rate)
+ implicit none
+ integer, intent(in):: km
+ real, intent(in):: ptop
+ real, intent(in):: s_rate !< between [1. 1.1]
+ real, intent(out):: ak(km+1), bk(km+1)
+ real, intent(inout):: pint
+ integer, intent(out):: ks
+! Local
+ real, parameter:: p00 = 1.E5
+ real, dimension(km+1):: ze, pe1, peln, eta
+ real, dimension(km):: dz, s_fac, dlnp, pm, dp, dk
+ real ztop, t0, dz0, sum1, tmp1
+ real ep, es, alpha, beta, gama
+ real, parameter:: akap = 2./7.
+!---- Tunable parameters:
+ real:: k_inc = 10 !< number of layers from bottom up to near const dz region
+ real:: s0 = 0.8 !< lowest layer stretch factor
+!-----------------------
+ real:: s_inc
+ integer k
+
+ pe1(1) = ptop
+ peln(1) = log(pe1(1))
+ pe1(km+1) = p00
+ peln(km+1) = log(pe1(km+1))
+
+ t0 = 273.
+ ztop = rdgas/grav*t0*(peln(km+1) - peln(1))
+
+ s_inc = (1.-s0) / real(k_inc)
+ s_fac(km) = s0
+
+ do k=km-1, km-k_inc, -1
+ s_fac(k) = s_fac(k+1) + s_inc
+ enddo
+
+ s_fac(km-k_inc-1) = 0.5*(s_fac(km-k_inc) + s_rate)
+
+ do k=km-k_inc-2, 5, -1
+ s_fac(k) = s_rate * s_fac(k+1)
+ enddo
+
+ s_fac(4) = 0.5*(1.1+s_rate)*s_fac(5)
+ s_fac(3) = 1.1 *s_fac(4)
+ s_fac(2) = 1.1 *s_fac(3)
+ s_fac(1) = 1.1 *s_fac(2)
+
+ sum1 = 0.
+ do k=1,km
+ sum1 = sum1 + s_fac(k)
+ enddo
+
+ dz0 = ztop / sum1
+
+ do k=1,km
+ dz(k) = s_fac(k) * dz0
+ enddo
+
+ ze(km+1) = 0.
+ do k=km,1,-1
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+
+! Re-scale dz with the stretched ztop
+ do k=1,km
+ dz(k) = dz(k) * (ztop/ze(1))
+ enddo
+
+ do k=km,1,-1
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+! ze(1) = ztop
+
+ if ( is_master() ) then
+ write(*,*) 'var_les: computed model top (m)=', ztop, ' bottom/top dz=', dz(km), dz(1)
+! do k=1,km
+! write(*,*) k, s_fac(k)
+! enddo
+ endif
+
+ call sm1_edge(1, 1, 1, 1, km, 1, 1, ze, 2)
+
+! Given z --> p
+ do k=1,km
+ dz(k) = ze(k) - ze(k+1)
+ dlnp(k) = grav*dz(k) / (rdgas*t0)
+ !write(*,*) k, dz(k)
+ enddo
+ do k=2,km
+ peln(k) = peln(k-1) + dlnp(k-1)
+ pe1(k) = exp(peln(k))
+ enddo
+
+
+! Pe(k) = ak(k) + bk(k) * PS
+! Locate pint and KS
+ ks = 0
+ do k=2,km
+ if ( pint < pe1(k)) then
+ ks = k-1
+ exit
+ endif
+ enddo
+ if ( is_master() ) then
+ write(*,*) 'For (input) PINT=', 0.01*pint, ' KS=', ks, 'pint(computed)=', 0.01*pe1(ks+1)
+ endif
+ pint = pe1(ks+1)
+
+ do k=1,km+1
+ eta(k) = pe1(k) / pe1(km+1)
+ enddo
+
+ ep = eta(ks+1)
+ es = eta(km)
+! es = 1.
+ alpha = (ep**2-2.*ep*es) / (es-ep)**2
+ beta = 2.*ep*es**2 / (es-ep)**2
+ gama = -(ep*es)**2 / (es-ep)**2
+
+! Pure pressure:
+ do k=1,ks+1
+ ak(k) = eta(k)*1.e5
+ bk(k) = 0.
+ enddo
+
+ do k=ks+2, km
+ ak(k) = alpha*eta(k) + beta + gama/eta(k)
+ ak(k) = ak(k)*1.e5
+ enddo
+ ak(km+1) = 0.
+
+ do k=ks+2, km
+ bk(k) = (pe1(k) - ak(k))/pe1(km+1)
+ enddo
+ bk(km+1) = 1.
+
+ if ( is_master() ) then
+ ! write(*,*) 'KS=', ks, 'PINT (mb)=', pint/100.
+ ! do k=1,km
+ ! pm(k) = 0.5*(pe1(k)+pe1(k+1))/100.
+ ! write(*,*) k, pm(k), dz(k)
+ ! enddo
+ tmp1 = ak(ks+1)
+ do k=ks+1,km
+ tmp1 = max(tmp1, (ak(k)-ak(k+1))/max(1.E-5, (bk(k+1)-bk(k))) )
+ enddo
+ write(*,*) 'Hybrid Sigma-P: minimum allowable surface pressure (hpa)=', tmp1/100.
+ write(*,800) (pm(k), k=km,1,-1)
+ endif
+
+ do k=1,km
+ dp(k) = (pe1(k+1) - pe1(k))/100.
+ dk(k) = pe1(k+1)**akap - pe1(k)**akap
+ enddo
+
+800 format(1x,5(1x,f9.4))
+
+ end subroutine var_les
+
+
+
+ subroutine var_gfs(km, ak, bk, ptop, ks, pint, s_rate)
+ integer, intent(in):: km
+ real, intent(in):: ptop
+ real, intent(in):: s_rate !< between [1. 1.1]
+ real, intent(out):: ak(km+1), bk(km+1)
+ real, intent(inout):: pint
+ integer, intent(out):: ks
+! Local
+ real, parameter:: p00 = 1.E5
+ real, dimension(km+1):: ze, pe1, peln, eta
+ real, dimension(km):: dz, s_fac, dlnp
+ real ztop, t0, dz0, sum1, tmp1
+ real ep, es, alpha, beta, gama
+!---- Tunable parameters:
+ integer:: k_inc = 25 !< number of layers from bottom up to near const dz region
+ real:: s0 = 0.13 !< lowest layer stretch factor
+!-----------------------
+ real:: s_inc
+ integer k
+
+ pe1(1) = ptop
+ peln(1) = log(pe1(1))
+ pe1(km+1) = p00
+ peln(km+1) = log(pe1(km+1))
+
+ t0 = 270.
+ ztop = rdgas/grav*t0*(peln(km+1) - peln(1))
+
+ s_inc = (1.-s0) / real(k_inc)
+ s_fac(km) = s0
+
+ do k=km-1, km-k_inc, -1
+ s_fac(k) = s_fac(k+1) + s_inc
+ enddo
+
+ do k=km-k_inc-1, 9, -1
+ s_fac(k) = s_rate * s_fac(k+1)
+ enddo
+ s_fac(8) = 0.5*(1.1+s_rate)*s_fac(9)
+ s_fac(7) = 1.10*s_fac(8)
+ s_fac(6) = 1.15*s_fac(7)
+ s_fac(5) = 1.20*s_fac(6)
+ s_fac(4) = 1.26*s_fac(5)
+ s_fac(3) = 1.33*s_fac(4)
+ s_fac(2) = 1.41*s_fac(3)
+ s_fac(1) = 1.60*s_fac(2)
+
+ sum1 = 0.
+ do k=1,km
+ sum1 = sum1 + s_fac(k)
+ enddo
+
+ dz0 = ztop / sum1
+
+ do k=1,km
+ dz(k) = s_fac(k) * dz0
+ enddo
+
+ ze(km+1) = 0.
+ do k=km,1,-1
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+
+! Re-scale dz with the stretched ztop
+ do k=1,km
+ dz(k) = dz(k) * (ztop/ze(1))
+ enddo
+
+ do k=km,1,-1
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+! ze(1) = ztop
+
+ if ( is_master() ) then
+ write(*,*) 'var_gfs: computed model top (m)=', ztop*0.001, ' bottom/top dz=', dz(km), dz(1)
+! do k=1,km
+! write(*,*) k, s_fac(k)
+! enddo
+ endif
+
+! call sm1_edge(1, 1, 1, 1, km, 1, 1, ze, 3)
+
+! Given z --> p
+ do k=1,km
+ dz(k) = ze(k) - ze(k+1)
+ dlnp(k) = grav*dz(k) / (rdgas*t0)
+ enddo
+ do k=2,km
+ peln(k) = peln(k-1) + dlnp(k-1)
+ pe1(k) = exp(peln(k))
+ enddo
+
+! Pe(k) = ak(k) + bk(k) * PS
+! Locate pint and KS
+ ks = 0
+ do k=2,km
+ if ( pint < pe1(k)) then
+ ks = k-1
+ exit
+ endif
+ enddo
+ if ( is_master() ) then
+ write(*,*) 'For (input) PINT=', 0.01*pint, ' KS=', ks, 'pint(computed)=', 0.01*pe1(ks+1)
+ write(*,*) 'ptop =', ptop
+ endif
+ pint = pe1(ks+1)
+
+#ifdef NO_UKMO_HB
+ do k=1,ks+1
+ ak(k) = pe1(k)
+ bk(k) = 0.
+ enddo
+
+ do k=ks+2,km+1
+ bk(k) = (pe1(k) - pint) / (pe1(km+1)-pint) ! bk == sigma
+ ak(k) = pe1(k) - bk(k) * pe1(km+1)
+ enddo
+ bk(km+1) = 1.
+ ak(km+1) = 0.
+#else
+! Problematic for non-hydrostatic
+ do k=1,km+1
+ eta(k) = pe1(k) / pe1(km+1)
+ enddo
+
+ ep = eta(ks+1)
+ es = eta(km)
+! es = 1.
+ alpha = (ep**2-2.*ep*es) / (es-ep)**2
+ beta = 2.*ep*es**2 / (es-ep)**2
+ gama = -(ep*es)**2 / (es-ep)**2
+
+! Pure pressure:
+ do k=1,ks+1
+ ak(k) = eta(k)*1.e5
+ bk(k) = 0.
+ enddo
+
+ do k=ks+2, km
+ ak(k) = alpha*eta(k) + beta + gama/eta(k)
+ ak(k) = ak(k)*1.e5
+ enddo
+ ak(km+1) = 0.
+
+ do k=ks+2, km
+ bk(k) = (pe1(k) - ak(k))/pe1(km+1)
+ enddo
+ bk(km+1) = 1.
+#endif
+
+ if ( is_master() ) then
+ write(*,*) 'KS=', ks, 'PINT (mb)=', pint/100.
+ do k=1,km
+ write(*,*) k, 0.5*(pe1(k)+pe1(k+1))/100., dz(k)
+ enddo
+ tmp1 = ak(ks+1)
+ do k=ks+1,km
+ tmp1 = max(tmp1, (ak(k)-ak(k+1))/max(1.E-5, (bk(k+1)-bk(k))) )
+ enddo
+ write(*,*) 'Hybrid Sigma-P: minimum allowable surface pressure (hpa)=', tmp1/100.
+ endif
+
+ end subroutine var_gfs
+
+ subroutine var_hi(km, ak, bk, ptop, ks, pint, s_rate)
+ integer, intent(in):: km
+ real, intent(in):: ptop
+ real, intent(in):: s_rate !< between [1. 1.1]
+ real, intent(out):: ak(km+1), bk(km+1)
+ real, intent(inout):: pint
+ integer, intent(out):: ks
+! Local
+ real, parameter:: p00 = 1.E5
+ real, dimension(km+1):: ze, pe1, peln, eta
+ real, dimension(km):: dz, s_fac, dlnp
+ real ztop, t0, dz0, sum1, tmp1
+ real ep, es, alpha, beta, gama
+!---- Tunable parameters:
+ integer:: k_inc = 15 !@brief The subroutine 'get_eta_level' returns the interface and
+!! layer-mean pressures for reference.
+ subroutine get_eta_level(npz, p_s, pf, ph, ak, bk, pscale)
+ integer, intent(in) :: npz
+ real, intent(in) :: p_s !< unit: pascal
+ real, intent(in) :: ak(npz+1)
+ real, intent(in) :: bk(npz+1)
+ real, intent(in), optional :: pscale
+ real, intent(out) :: pf(npz)
+ real, intent(out) :: ph(npz+1)
+ integer k
+
+ ph(1) = ak(1)
+ do k=2,npz+1
+ ph(k) = ak(k) + bk(k)*p_s
+ enddo
+
+ if ( present(pscale) ) then
+ do k=1,npz+1
+ ph(k) = pscale*ph(k)
+ enddo
+ endif
+
+ if( ak(1) > 1.E-8 ) then
+ pf(1) = (ph(2) - ph(1)) / log(ph(2)/ph(1))
+ else
+ pf(1) = (ph(2) - ph(1)) * kappa/(kappa+1.)
+ endif
+
+ do k=2,npz
+ pf(k) = (ph(k+1) - ph(k)) / log(ph(k+1)/ph(k))
+ enddo
+
+ end subroutine get_eta_level
+
+
+
+ subroutine compute_dz(km, ztop, dz)
+
+ integer, intent(in):: km
+ real, intent(in):: ztop ! try 50.E3
+ real, intent(out):: dz(km)
+!------------------------------
+ real ze(km+1), dzt(km)
+ integer k
+
+
+! ztop = 30.E3
+ dz(1) = ztop / real(km)
+ dz(km) = 0.5*dz(1)
+
+ do k=2,km-1
+ dz(k) = dz(1)
+ enddo
+
+! Top:
+ dz(1) = 2.*dz(2)
+
+ ze(km+1) = 0.
+ do k=km,1,-1
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+
+ if ( is_master() ) then
+ write(*,*) 'Hybrid_z: dz, zm'
+ do k=1,km
+ dzt(k) = 0.5*(ze(k)+ze(k+1)) / 1000.
+ write(*,*) k, dz(k), dzt(k)
+ enddo
+ endif
+
+ end subroutine compute_dz
+
+ subroutine compute_dz_var(km, ztop, dz)
+
+ integer, intent(in):: km
+ real, intent(in):: ztop ! try 50.E3
+ real, intent(out):: dz(km)
+!------------------------------
+ real, parameter:: s_rate = 1.0
+ real ze(km+1)
+ real s_fac(km)
+ real sum1, dz0
+ integer k
+
+ s_fac(km ) = 0.125
+ s_fac(km-1) = 0.20
+ s_fac(km-2) = 0.30
+ s_fac(km-3) = 0.40
+ s_fac(km-4) = 0.50
+ s_fac(km-5) = 0.60
+ s_fac(km-6) = 0.70
+ s_fac(km-7) = 0.80
+ s_fac(km-8) = 0.90
+ s_fac(km-9) = 1.
+
+ do k=km-10, 9, -1
+ s_fac(k) = s_rate * s_fac(k+1)
+ enddo
+
+ s_fac(8) = 1.05*s_fac(9)
+ s_fac(7) = 1.1 *s_fac(8)
+ s_fac(6) = 1.15*s_fac(7)
+ s_fac(5) = 1.2 *s_fac(6)
+ s_fac(4) = 1.3 *s_fac(5)
+ s_fac(3) = 1.4 *s_fac(4)
+ s_fac(2) = 1.5 *s_fac(3)
+ s_fac(1) = 1.6 *s_fac(2)
+
+ sum1 = 0.
+ do k=1,km
+ sum1 = sum1 + s_fac(k)
+ enddo
+
+ dz0 = ztop / sum1
+
+ do k=1,km
+ dz(k) = s_fac(k) * dz0
+ enddo
+
+ ze(1) = ztop
+ ze(km+1) = 0.
+ do k=km,2,-1
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+
+! Re-scale dz with the stretched ztop
+ do k=1,km
+ dz(k) = dz(k) * (ztop/ze(1))
+ enddo
+
+ do k=km,2,-1
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+
+ call sm1_edge(1, 1, 1, 1, km, 1, 1, ze, 2)
+
+ do k=1,km
+ dz(k) = ze(k) - ze(k+1)
+ enddo
+
+ end subroutine compute_dz_var
+
+ subroutine compute_dz_L32(km, ztop, dz)
+
+ integer, intent(in):: km
+ real, intent(out):: dz(km)
+ real, intent(out):: ztop ! try 50.E3
+!------------------------------
+ real dzt(km)
+ real ze(km+1)
+ real dz0, dz1, dz2
+ real z0, z1, z2
+ integer k, k0, k1, k2, n
+
+!-------------------
+ k2 = 8
+ z2 = 30.E3
+!-------------------
+ k1 = 21
+ z1 = 10.0E3
+!-------------------
+ k0 = 2
+ z0 = 0.
+ dz0 = 75. ! meters
+!-------------------
+! Treat the surface layer as a special layer
+ ze(1) = z0
+ dz(1) = dz0
+
+ ze(2) = dz(1)
+ dz0 = 1.5*dz0
+ dz(2) = dz0
+
+ ze(3) = ze(2) + dz(2)
+
+ dz1 = 2.*(z1-ze(3) - k1*dz0) / (k1*(k1-1))
+
+ do k=k0+1,k0+k1
+ dz(k) = dz0 + (k-k0)*dz1
+ ze(k+1) = ze(k) + dz(k)
+ enddo
+
+ dz0 = dz(k1+k0)
+ dz2 = 2.*(z2-ze(k0+k1+1)-k2*dz0) / (k2*(k2-1))
+
+ do k=k0+k1+1,k0+k1+k2
+ dz(k) = dz0 + (k-k0-k1)*dz2
+ ze(k+1) = ze(k) + dz(k)
+ enddo
+
+ dz(km) = 2.*dz(km-1)
+ ztop = ze(km) + dz(km)
+ ze(km+1) = ze(km) + dz(km)
+
+ call zflip (dz, 1, km)
+
+ ze(km+1) = 0.
+ do k=km,1,-1
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+
+! if ( is_master() ) then
+! write(*,*) 'Hybrid_z: dz, zm'
+! do k=1,km
+! dzt(k) = 0.5*(ze(k)+ze(k+1)) / 1000.
+! write(*,*) k, dz(k), dzt(k)
+! enddo
+! endif
+
+ end subroutine compute_dz_L32
+
+ subroutine compute_dz_L101(km, ztop, dz)
+
+ integer, intent(in):: km ! km==101
+ real, intent(out):: dz(km)
+ real, intent(out):: ztop ! try 30.E3
+!------------------------------
+ real ze(km+1)
+ real dz0, dz1
+ real:: stretch_f = 1.16
+ integer k, k0, k1
+
+ k1 = 2
+ k0 = 25
+ dz0 = 40. ! meters
+
+ ze(km+1) = 0.
+
+ do k=km, k0, -1
+ dz(k) = dz0
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+
+ do k=k0+1, k1, -1
+ dz(k) = stretch_f * dz(k+1)
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+
+ dz(1) = 4.0*dz(2)
+ ze(1) = ze(2) + dz(1)
+ ztop = ze(1)
+
+ if ( is_master() ) then
+ write(*,*) 'Hybrid_z: dz, ze'
+ do k=1,km
+ write(*,*) k, 0.001*dz(k), 0.001*ze(k)
+ enddo
+! ztop (km) = 20.2859154
+ write(*,*) 'ztop (km) =', ztop * 0.001
+ endif
+
+ end subroutine compute_dz_L101
+
+ subroutine set_hybrid_z(is, ie, js, je, ng, km, ztop, dz, rgrav, hs, ze, dz3)
+
+ integer, intent(in):: is, ie, js, je, ng, km
+ real, intent(in):: rgrav, ztop
+ real, intent(in):: dz(km) !< Reference vertical resolution for zs=0
+ real, intent(in):: hs(is-ng:ie+ng,js-ng:je+ng)
+ real, intent(inout):: ze(is:ie,js:je,km+1)
+ real, optional, intent(out):: dz3(is-ng:ie+ng,js-ng:je+ng,km)
+! local
+ logical:: filter_xy = .false.
+ real, allocatable:: delz(:,:,:)
+ integer ntimes
+ real zint
+ real:: z1(is:ie,js:je)
+ real:: z(km+1)
+ real sig, z_rat
+ integer ks(is:ie,js:je)
+ integer i, j, k, ks_min, kint
+
+ z(km+1) = 0.
+ do k=km,1,-1
+ z(k) = z(k+1) + dz(k)
+ enddo
+
+ do j=js,je
+ do i=is,ie
+ ze(i,j, 1) = ztop
+ ze(i,j,km+1) = hs(i,j) * rgrav
+ enddo
+ enddo
+
+ do k=2,km
+ do j=js,je
+ do i=is,ie
+ ze(i,j,k) = z(k)
+ enddo
+ enddo
+ enddo
+
+! Set interface:
+#ifndef USE_VAR_ZINT
+ zint = 12.0E3
+ ntimes = 2
+ kint = 2
+ do k=2,km
+ if ( z(k)<=zint ) then
+ kint = k
+ exit
+ endif
+ enddo
+
+ if ( is_master() ) write(*,*) 'Z_coord interface set at k=',kint, ' ZE=', z(kint)
+
+ do j=js,je
+ do i=is,ie
+ z_rat = (ze(i,j,kint)-ze(i,j,km+1)) / (z(kint)-z(km+1))
+ do k=km,kint+1,-1
+ ze(i,j,k) = ze(i,j,k+1) + dz(k)*z_rat
+ enddo
+!--------------------------------------
+! Apply vertical smoother locally to dz
+!--------------------------------------
+ call sm1_edge(is, ie, js, je, km, i, j, ze, ntimes)
+ enddo
+ enddo
+#else
+! ZINT is a function of local terrain
+ ntimes = 4
+ do j=js,je
+ do i=is,ie
+ z1(i,j) = dim(ze(i,j,km+1), 2500.) + 7500.
+ enddo
+ enddo
+
+ ks_min = km
+ do j=js,je
+ do i=is,ie
+ do k=km,2,-1
+ if ( z(k)>=z1(i,j) ) then
+ ks(i,j) = k
+ ks_min = min(ks_min, k)
+ go to 555
+ endif
+ enddo
+555 continue
+ enddo
+ enddo
+
+ do j=js,je
+ do i=is,ie
+ kint = ks(i,j) + 1
+ z_rat = (ze(i,j,kint)-ze(i,j,km+1)) / (z(kint)-z(km+1))
+ do k=km,kint+1,-1
+ ze(i,j,k) = ze(i,j,k+1) + dz(k)*z_rat
+ enddo
+!--------------------------------------
+! Apply vertical smoother locally to dz
+!--------------------------------------
+ call sm1_edge(is, ie, js, je, km, i, j, ze, ntimes)
+ enddo
+ enddo
+#endif
+
+#ifdef DEV_ETA
+ if ( filter_xy ) then
+ allocate (delz(isd:ied, jsd:jed, km) )
+ ntimes = 2
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ delz(i,j,k) = ze(i,j,k+1) - ze(i,j,k)
+ enddo
+ enddo
+ enddo
+ call del2_cubed(delz, 0.2*da_min, npx, npy, km, ntimes)
+ do k=km,2,-1
+ do j=js,je
+ do i=is,ie
+ ze(i,j,k) = ze(i,j,k+1) - delz(i,j,k)
+ enddo
+ enddo
+ enddo
+ deallocate ( delz )
+ endif
+#endif
+ if ( present(dz3) ) then
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ dz3(i,j,k) = ze(i,j,k+1) - ze(i,j,k)
+ enddo
+ enddo
+ enddo
+ endif
+
+ end subroutine set_hybrid_z
+
+
+ subroutine sm1_edge(is, ie, js, je, km, i, j, ze, ntimes)
+ integer, intent(in):: is, ie, js, je, km
+ integer, intent(in):: ntimes, i, j
+ real, intent(inout):: ze(is:ie,js:je,km+1)
+! local:
+ real, parameter:: df = 0.25
+ real dz(km)
+ real flux(km+1)
+ integer k, n, k1, k2
+
+ k2 = km-1
+ do k=1,km
+ dz(k) = ze(i,j,k+1) - ze(i,j,k)
+ enddo
+
+ do n=1,ntimes
+ k1 = 2 + (ntimes-n)
+
+ flux(k1 ) = 0.
+ flux(k2+1) = 0.
+ do k=k1+1,k2
+ flux(k) = df*(dz(k) - dz(k-1))
+ enddo
+
+ do k=k1,k2
+ dz(k) = dz(k) - flux(k) + flux(k+1)
+ enddo
+ enddo
+
+ do k=km,1,-1
+ ze(i,j,k) = ze(i,j,k+1) - dz(k)
+ enddo
+
+ end subroutine sm1_edge
+
+
+
+ subroutine gw_1d(km, p0, ak, bk, ptop, ztop, pt1)
+ integer, intent(in):: km
+ real, intent(in):: p0, ztop
+ real, intent(inout):: ptop
+ real, intent(inout):: ak(km+1), bk(km+1)
+ real, intent(out):: pt1(km)
+! Local
+ logical:: isothermal
+ real, dimension(km+1):: ze, pe1, pk1
+ real, dimension(km):: dz1
+ real t0, n2, s0
+ integer k
+
+! Set up vertical coordinare with constant del-z spacing:
+ isothermal = .false.
+ t0 = 300.
+
+ if ( isothermal ) then
+ n2 = grav**2/(cp_air*t0)
+ else
+ n2 = 0.0001
+ endif
+
+ s0 = grav*grav / (cp_air*n2)
+
+ ze(km+1) = 0.
+ do k=km,1,-1
+ dz1(k) = ztop / real(km)
+ ze(k) = ze(k+1) + dz1(k)
+ enddo
+
+! Given z --> p
+ do k=1,km+1
+ pe1(k) = p0*( (1.-s0/t0) + s0/t0*exp(-n2*ze(k)/grav) )**(1./kappa)
+ enddo
+
+ ptop = pe1(1)
+! if ( is_master() ) write(*,*) 'GW_1D: computed model top (pa)=', ptop
+
+! Set up "sigma" coordinate
+ ak(1) = pe1(1)
+ bk(1) = 0.
+ do k=2,km
+ bk(k) = (pe1(k) - pe1(1)) / (pe1(km+1)-pe1(1)) ! bk == sigma
+ ak(k) = pe1(1)*(1.-bk(k))
+ enddo
+ ak(km+1) = 0.
+ bk(km+1) = 1.
+
+ do k=1,km+1
+ pk1(k) = pe1(k) ** kappa
+ enddo
+
+! Compute volume mean potential temperature with hydrostatic eqn:
+ do k=1,km
+ pt1(k) = grav*dz1(k) / ( cp_air*(pk1(k+1)-pk1(k)) )
+ enddo
+
+ end subroutine gw_1d
+
+
+
+ subroutine zflip(q, im, km)
+ integer, intent(in):: im, km
+ real, intent(inout):: q(im,km)
+!---
+ integer i, k
+ real qtmp
+
+ do i = 1, im
+ do k = 1, (km+1)/2
+ qtmp = q(i,k)
+ q(i,k) = q(i,km+1-k)
+ q(i,km+1-k) = qtmp
+ end do
+ end do
+
+ end subroutine zflip
+
+end module fv_eta_mod
diff --git a/tools/fv_eta.F90_NAM_lyrs b/tools/fv_eta.F90_NAM_lyrs
new file mode 100644
index 000000000..7697c385c
--- /dev/null
+++ b/tools/fv_eta.F90_NAM_lyrs
@@ -0,0 +1,3079 @@
+!***********************************************************************
+!* GNU Lesser General Public License
+!*
+!* This file is part of the FV3 dynamical core.
+!*
+!* The FV3 dynamical core is free software: you can redistribute it
+!* and/or modify it under the terms of the
+!* GNU Lesser General Public License as published by the
+!* Free Software Foundation, either version 3 of the License, or
+!* (at your option) any later version.
+!*
+!* The FV3 dynamical core is distributed in the hope that it will be
+!* useful, but WITHOUT ANYWARRANTY; without even the implied warranty
+!* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+!* See the GNU General Public License for more details.
+!*
+!* You should have received a copy of the GNU Lesser General Public
+!* License along with the FV3 dynamical core.
+!* If not, see .
+!***********************************************************************
+
+!>@brief The module 'fv_eta' contains routine to set up the reference
+!! (Eulerian) pressure coordinate
+
+module fv_eta_mod
+
+!
+!
+! | Module Name |
+! Functions Included |
+!
+!
+! | constants_mod |
+! kappa, grav, cp_air, rdgas |
+!
+!
+! | fv_mp_mod |
+! is_master |
+!
+!
+! | mpp_mod |
+! mpp_error, FATAL |
+!
+!
+
+ use constants_mod, only: kappa, grav, cp_air, rdgas
+ use fv_mp_mod, only: is_master
+ use mpp_mod, only: FATAL, mpp_error
+ implicit none
+ private
+ public set_eta, set_external_eta, get_eta_level, compute_dz_var, &
+ compute_dz_L32, compute_dz_L101, set_hybrid_z, compute_dz, &
+ gw_1d, sm1_edge, hybrid_z_dz
+
+ contains
+
+!!!NOTE: USE_VAR_ETA not used in fvGFS
+#ifdef USE_VAR_ETA
+ subroutine set_eta(km, ks, ptop, ak, bk)
+! This is the easy to use version of the set_eta
+ integer, intent(in):: km ! vertical dimension
+ integer, intent(out):: ks ! number of pure p layers
+ real:: a60(61),b60(61)
+! Thfollowing L63 setting is the same as NCEP GFS's L64 except the top
+! 3 layers
+ data a60/300.0000, 430.00000, 558.00000, &
+ 700.00000, 863.05803, 1051.07995, &
+ 1265.75194, 1510.71101, 1790.05098, &
+ 2108.36604, 2470.78817, 2883.03811, &
+ 3351.46002, 3883.05187, 4485.49315, &
+ 5167.14603, 5937.04991, 6804.87379, &
+ 7780.84698, 8875.64338, 10100.20534, &
+ 11264.35673, 12190.64366, 12905.42546, &
+ 13430.87867, 13785.88765, 13986.77987, &
+ 14047.96335, 13982.46770, 13802.40331, &
+ 13519.33841, 13144.59486, 12689.45608, &
+ 12165.28766, 11583.57006, 10955.84778, &
+ 10293.60402, 9608.08306, 8910.07678, &
+ 8209.70131, 7516.18560, 6837.69250, &
+ 6181.19473, 5552.39653, 4955.72632, &
+ 4394.37629, 3870.38682, 3384.76586, &
+ 2937.63489, 2528.37666, 2155.78385, &
+ 1818.20722, 1513.68173, 1240.03585, &
+ 994.99144, 776.23591, 581.48797, &
+ 408.53400, 255.26520, 119.70243, 0. /
+
+ data b60/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00201, 0.00792, 0.01755, &
+ 0.03079, 0.04751, 0.06761, &
+ 0.09097, 0.11746, 0.14690, &
+ 0.17911, 0.21382, 0.25076, &
+ 0.28960, 0.32994, 0.37140, &
+ 0.41353, 0.45589, 0.49806, &
+ 0.53961, 0.58015, 0.61935, &
+ 0.65692, 0.69261, 0.72625, &
+ 0.75773, 0.78698, 0.81398, &
+ 0.83876, 0.86138, 0.88192, &
+ 0.90050, 0.91722, 0.93223, &
+ 0.94565, 0.95762, 0.96827, &
+ 0.97771, 0.98608, 0.99347, 1./
+ real, intent(out):: ak(km+1)
+ real, intent(out):: bk(km+1)
+ real, intent(out):: ptop ! model top (Pa)
+ real pint, stretch_fac
+ integer k
+ real :: s_rate = -1.0 ! dummy value to not use var_les
+
+ pint = 100.E2
+
+!- Notes ---------------------------------
+! low-top: ptop = 100. ! ~45 km
+! mid-top: ptop = 10. ! ~60 km
+! hi -top: ptop = 1. ! ~80 km
+!-----------------------------------------
+ select case (km)
+
+! Optimal number = 8 * N -1 (for 8 openMP threads)
+! 16 * M -1 (for 16 openMP threads)
+
+#ifdef HIWPP
+#ifdef SUPER_K
+ case (20)
+ ptop = 56.e2
+ pint = ptop
+ stretch_fac = 1.03
+ case (24)
+ ptop = 56.e2
+ pint = ptop
+ stretch_fac = 1.03
+ case (30)
+ ptop = 56.e2
+ pint = ptop
+ stretch_fac = 1.03
+ case (40)
+ ptop = 56.e2
+ pint = ptop
+ stretch_fac = 1.03
+ case (50)
+ ptop = 56.e2
+ pint = ptop
+ stretch_fac = 1.03
+ case (60)
+ ptop = 56.e2
+ pint = ptop
+ stretch_fac = 1.03
+ case (80)
+ ptop = 56.e2
+ pint = ptop
+ stretch_fac = 1.03
+#else
+ case (30) ! For Baroclinic Instability Test
+ ptop = 2.26e2
+ pint = 250.E2
+ stretch_fac = 1.03
+ case (40)
+ ptop = 50.e2 ! For super cell test
+ pint = 300.E2
+ stretch_fac = 1.03
+ case (50) ! Mountain waves?
+ ptop = 30.e2
+ stretch_fac = 1.025
+ case (60) ! For Baroclinic Instability Test
+#ifdef GFSL60
+ ks = 20
+ ptop = a60(1)
+ pint = a60(ks+1)
+ do k=1,km+1
+ ak(k) = a60(k)
+ bk(k) = b60(k)
+ enddo
+#else
+ ptop = 3.e2
+! pint = 250.E2
+ pint = 300.E2 ! revised for Moist test
+ stretch_fac = 1.03
+#endif
+#endif
+ case (64)
+!!! ptop = 3.e2
+ ptop = 2.0e2
+ pint = 300.E2
+ stretch_fac = 1.03
+#else
+! *Very-low top: for idealized super-cell simulation:
+ case (50)
+ ptop = 50.e2
+ pint = 250.E2
+ stretch_fac = 1.03
+ case (60)
+ ptop = 40.e2
+ pint = 250.E2
+ stretch_fac = 1.03
+ case (90) ! super-duper cell
+ ptop = 40.e2
+ stretch_fac = 1.025
+#endif
+! Low-top:
+ case (31) ! N = 4, M=2
+ ptop = 100.
+ stretch_fac = 1.035
+ case (32) ! N = 4, M=2
+ ptop = 100.
+ stretch_fac = 1.035
+ case (39) ! N = 5
+ ptop = 100.
+ stretch_fac = 1.035
+ case (41)
+ ptop = 100.
+ stretch_fac = 1.035
+ case (47) ! N = 6, M=3
+ ptop = 100.
+ stretch_fac = 1.035
+ case (51)
+ ptop = 100.
+ stretch_fac = 1.03
+ case (52) ! very low top
+ ptop = 30.e2 ! for special DPM RCE experiments
+ stretch_fac = 1.03
+! Mid-top:
+ case (55) ! N = 7
+ ptop = 10.
+ stretch_fac = 1.035
+! Hi-top:
+ case (63) ! N = 8, M=4
+ ptop = 1.
+ ! c360 or c384
+ stretch_fac = 1.035
+ case (71) ! N = 9
+ ptop = 1.
+ stretch_fac = 1.03
+ case (79) ! N = 10, M=5
+ ptop = 1.
+ stretch_fac = 1.03
+ case (127) ! N = 10, M=5
+ ptop = 1.
+ stretch_fac = 1.03
+ case (151)
+ ptop = 75.e2
+ pint = 500.E2
+ s_rate = 1.01
+ case default
+ ptop = 1.
+ stretch_fac = 1.03
+ end select
+
+#ifdef MOUNTAIN_WAVES
+ call mount_waves(km, ak, bk, ptop, ks, pint)
+#else
+ if (s_rate > 0.) then
+ call var_les(km, ak, bk, ptop, ks, pint, s_rate)
+ else
+ if ( km > 79 ) then
+ call var_hi2(km, ak, bk, ptop, ks, pint, stretch_fac)
+ elseif (km==5 .or. km==10 ) then
+! Equivalent Shallow Water: for NGGPS, variable-resolution testing
+ ptop = 500.e2
+ ks = 0
+ do k=1,km+1
+ bk(k) = real(k-1) / real (km)
+ ak(k) = ptop*(1.-bk(k))
+ enddo
+ else
+#ifndef GFSL60
+ call var_hi(km, ak, bk, ptop, ks, pint, stretch_fac)
+#endif
+ endif
+#endif
+ endif
+
+ ptop = ak(1)
+ pint = ak(ks+1)
+
+ end subroutine set_eta
+
+ subroutine mount_waves(km, ak, bk, ptop, ks, pint)
+ integer, intent(in):: km
+ real, intent(out):: ak(km+1), bk(km+1)
+ real, intent(out):: ptop, pint
+ integer, intent(out):: ks
+! Local
+ real, parameter:: p00 = 1.E5
+ real, dimension(km+1):: ze, pe1, peln, eta
+ real, dimension(km):: dz, dlnp
+ real ztop, t0, dz0, sum1, tmp1
+ real ep, es, alpha, beta, gama, s_fac
+ integer k, k500
+
+ pint = 300.e2
+! s_fac = 1.05
+! dz0 = 500.
+ if ( km <= 60 ) then
+ s_fac = 1.0
+ dz0 = 500.
+ else
+ s_fac = 1.
+ dz0 = 250.
+ endif
+
+! Basic parameters for HIWPP mountain waves
+ t0 = 300.
+! ztop = 20.0e3; 500-m resolution in halft of the vertical domain
+! ztop = real(km-1)*500.
+!-----------------------
+! Compute temp ptop based on isothermal atm
+! ptop = p00*exp(-grav*ztop/(rdgas*t0))
+
+! Lowest half has constant resolution
+ ze(km+1) = 0.
+ do k=km, km-19, -1
+ ze(k) = ze(k+1) + dz0
+ enddo
+
+! Stretching from 10-km and up:
+ do k=km-20, 3, -1
+ dz0 = s_fac * dz0
+ ze(k) = ze(k+1) + dz0
+ enddo
+ ze(2) = ze(3) + sqrt(2.)*dz0
+ ze(1) = ze(2) + 2.0*dz0
+
+! call sm1_edge(1, 1, 1, 1, km, 1, 1, ze, 1)
+
+! Given z --> p
+ do k=1,km
+ dz(k) = ze(k) - ze(k+1)
+ dlnp(k) = grav*dz(k) / (rdgas*t0)
+ enddo
+
+ pe1(km+1) = p00
+ peln(km+1) = log(p00)
+ do k=km,1,-1
+ peln(k) = peln(k+1) - dlnp(k)
+ pe1(k) = exp(peln(k))
+ enddo
+
+! Comnpute new ptop
+ ptop = pe1(1)
+
+! Pe(k) = ak(k) + bk(k) * PS
+! Locate pint and KS
+ ks = 0
+ do k=2,km
+ if ( pint < pe1(k)) then
+ ks = k-1
+ exit
+ endif
+ enddo
+
+ if ( is_master() ) then
+ write(*,*) 'For (input) PINT=', 0.01*pint, ' KS=', ks, 'pint(computed)=', 0.01*pe1(ks+1)
+ write(*,*) 'Modified ptop =', ptop, ' ztop=', ze(1)/1000.
+ do k=1,km
+ write(*,*) k, 'ze =', ze(k)/1000.
+ enddo
+ endif
+ pint = pe1(ks+1)
+
+#ifdef NO_UKMO_HB
+ do k=1,ks+1
+ ak(k) = pe1(k)
+ bk(k) = 0.
+ enddo
+
+ do k=ks+2,km+1
+ bk(k) = (pe1(k) - pint) / (pe1(km+1)-pint) ! bk == sigma
+ ak(k) = pe1(k) - bk(k) * pe1(km+1)
+ enddo
+ bk(km+1) = 1.
+ ak(km+1) = 0.
+#else
+! Problematic for non-hydrostatic
+ do k=1,km+1
+ eta(k) = pe1(k) / pe1(km+1)
+ enddo
+ ep = eta(ks+1)
+ es = eta(km)
+! es = 1.
+ alpha = (ep**2-2.*ep*es) / (es-ep)**2
+ beta = 2.*ep*es**2 / (es-ep)**2
+ gama = -(ep*es)**2 / (es-ep)**2
+
+! Pure pressure:
+ do k=1,ks+1
+ ak(k) = eta(k)*1.e5
+ bk(k) = 0.
+ enddo
+
+ do k=ks+2, km
+ ak(k) = alpha*eta(k) + beta + gama/eta(k)
+ ak(k) = ak(k)*1.e5
+ enddo
+ ak(km+1) = 0.
+
+ do k=ks+2, km
+ bk(k) = (pe1(k) - ak(k))/pe1(km+1)
+ enddo
+ bk(km+1) = 1.
+#endif
+
+ if ( is_master() ) then
+ tmp1 = ak(ks+1)
+ do k=ks+1,km
+ tmp1 = max(tmp1, (ak(k)-ak(k+1))/max(1.E-5, (bk(k+1)-bk(k))) )
+ enddo
+ write(*,*) 'Hybrid Sigma-P: minimum allowable surface pressure (hpa)=', tmp1/100.
+ endif
+
+ end subroutine mount_waves
+
+#else
+ !>This is the version of set_eta used in fvGFS and AM4
+ !>@note 01/2018: 'set_eta' is being cleaned up.
+ subroutine set_eta(km, ks, ptop, ak, bk)
+ integer, intent(in):: km !< vertical dimension
+ integer, intent(out):: ks !< number of pure p layers
+ real, intent(out):: ak(km+1)
+ real, intent(out):: bk(km+1)
+ real, intent(out):: ptop !< model top (Pa)
+! local
+ real a24(25),b24(25) !< GFDL AM2L24
+ real a26(27),b26(27) !< Jablonowski & Williamson 26-level
+ real a32(33),b32(33)
+ real a32w(33),b32w(33)
+ real a47(48),b47(48)
+ real a48(49),b48(49)
+ real a52(53),b52(53)
+ real a54(55),b54(55)
+ real a56(57),b56(57)
+ real a60(61),b60(61)
+ real a63(64),b63(64)
+ real a64(65),b64(65)
+ real a68(69),b68(69) !< cjg: grid with enhanced PBL resolution
+ real a96(97),b96(97) !< cjg: grid with enhanced PBL resolution
+ real a100(101),b100(101)
+ real a104(105),b104(105)
+ real a125(126),b125(126)
+
+ real:: p0=1000.E2
+ real:: pc=200.E2
+
+ real pt, pint, lnpe, dlnp
+ real press(km+1), pt1(km)
+ integer k
+
+! Definition: press(i,j,k) = ak(k) + bk(k) * ps(i,j)
+
+!-----------------------------------------------
+! GFDL AM2-L24: modified by SJL at the model top
+!-----------------------------------------------
+! data a24 / 100.0000, 1050.0000, 3474.7942, 7505.5556, 12787.2428, &
+ data a24 / 100.0000, 903.4465, 3474.7942, 7505.5556, 12787.2428, &
+ 19111.3683, 21854.9274, 22884.1866, 22776.3058, 21716.1604, &
+ 20073.2963, 18110.5123, 16004.7832, 13877.6253, 11812.5452, &
+ 9865.8840, 8073.9726, 6458.0834, 5027.9899, 3784.6085, &
+ 2722.0086, 1828.9752, 1090.2396, 487.4595, 0.0000 /
+
+ data b24 / 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, &
+ 0.0000000, 0.0435679, 0.1102275, 0.1922249, 0.2817656, &
+ 0.3694997, 0.4532348, 0.5316253, 0.6038733, 0.6695556, &
+ 0.7285176, 0.7808017, 0.8265992, 0.8662148, 0.9000406, &
+ 0.9285364, 0.9522140, 0.9716252, 0.9873523, 1.0000000 /
+
+! Jablonowski & Williamson 26-level setup
+ data a26 / 219.4067, 489.5209, 988.2418, 1805.2010, 2983.7240, 4462.3340, &
+ 6160.5870, 7851.2430, 7731.2710, 7590.1310, 7424.0860, &
+ 7228.7440, 6998.9330, 6728.5740, 6410.5090, 6036.3220, &
+ 5596.1110, 5078.2250, 4468.9600, 3752.1910, 2908.9490, &
+ 2084.739, 1334.443, 708.499, 252.1360, 0.0, 0.0 /
+
+ data b26 / 0.0, 0.0, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,&
+ 0.0000000, 0.01505309, 0.03276228, 0.05359622, 0.07810627, &
+ 0.1069411, 0.1408637, 0.1807720, 0.2277220, 0.2829562, &
+ 0.3479364, 0.4243822, 0.5143168, 0.6201202, 0.7235355, &
+ 0.8176768, 0.8962153, 0.9534761, 0.9851122, 1.0000000 /
+
+
+! High-resolution troposphere setup
+#ifdef OLD_32
+! Revised Apr 14, 2004: PINT = 245.027 mb
+ data a32/100.00000, 400.00000, 818.60211, &
+ 1378.88653, 2091.79519, 2983.64084, &
+ 4121.78960, 5579.22148, 7419.79300, &
+ 9704.82578, 12496.33710, 15855.26306, &
+ 19839.62499, 24502.73262, 28177.10152, &
+ 29525.28447, 29016.34358, 27131.32792, &
+ 24406.11225, 21326.04907, 18221.18357, &
+ 15275.14642, 12581.67796, 10181.42843, &
+ 8081.89816, 6270.86956, 4725.35001, &
+ 3417.39199, 2317.75459, 1398.09473, &
+ 632.49506, 0.00000, 0.00000 /
+
+ data b32/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.01711, &
+ 0.06479, 0.13730, 0.22693, &
+ 0.32416, 0.42058, 0.51105, &
+ 0.59325, 0.66628, 0.73011, &
+ 0.78516, 0.83217, 0.87197, &
+ 0.90546, 0.93349, 0.95685, &
+ 0.97624, 0.99223, 1.00000 /
+#else
+! SJL June 26, 2012
+! pint= 55.7922
+ data a32/100.00000, 400.00000, 818.60211, &
+ 1378.88653, 2091.79519, 2983.64084, &
+ 4121.78960, 5579.22148, 6907.19063, &
+ 7735.78639, 8197.66476, 8377.95525, &
+ 8331.69594, 8094.72213, 7690.85756, &
+ 7139.01788, 6464.80251, 5712.35727, &
+ 4940.05347, 4198.60465, 3516.63294, &
+ 2905.19863, 2366.73733, 1899.19455, &
+ 1497.78137, 1156.25252, 867.79199, &
+ 625.59324, 423.21322, 254.76613, &
+ 115.06646, 0.00000, 0.00000 /
+
+ data b32/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00513, &
+ 0.01969, 0.04299, 0.07477, &
+ 0.11508, 0.16408, 0.22198, &
+ 0.28865, 0.36281, 0.44112, &
+ 0.51882, 0.59185, 0.65810, &
+ 0.71694, 0.76843, 0.81293, &
+ 0.85100, 0.88331, 0.91055, &
+ 0.93338, 0.95244, 0.96828, &
+ 0.98142, 0.99223, 1.00000 /
+#endif
+
+!---------------------
+! Wilson's 32L settings:
+!---------------------
+! Top changed to 0.01 mb
+ data a32w/ 1.00, 26.6378, 84.5529, 228.8592, &
+ 539.9597, 1131.7087, 2141.8082, 3712.0454, &
+ 5963.5317, 8974.1873, 12764.5388, 17294.5911, &
+ 20857.7007, 22221.8651, 22892.7202, 22891.1641, &
+ 22286.0724, 21176.0846, 19673.0671, 17889.0989, &
+ 15927.5060, 13877.6239, 11812.5474, 9865.8830, &
+ 8073.9717, 6458.0824, 5027.9893, 3784.6104, &
+ 2722.0093, 1828.9741, 1090.2397, 487.4575, &
+ 0.0000 /
+
+ data b32w/ 0.0000, 0.0000, 0.0000, 0.0000, &
+ 0.0000, 0.0000, 0.0000, 0.0000, &
+ 0.0000, 0.0000, 0.0000, 0.0000, &
+ 0.0159, 0.0586, 0.1117, 0.1734, &
+ 0.2415, 0.3137, 0.3878, 0.4619, &
+ 0.5344, 0.6039, 0.6696, 0.7285, &
+ 0.7808, 0.8266, 0.8662, 0.9000, &
+ 0.9285, 0.9522, 0.9716, 0.9874, &
+ 1.0000 /
+
+
+#ifdef OLD_L47
+! QBO setting with ptop = 0.1 mb and p_full=0.17 mb; pint ~ 100 mb
+ data a47/ 10.00000, 24.45365, 48.76776, &
+ 85.39458, 133.41983, 191.01402, &
+ 257.94919, 336.63306, 431.52741, &
+ 548.18995, 692.78825, 872.16512, &
+ 1094.18467, 1368.11917, 1704.99489, &
+ 2117.91945, 2622.42986, 3236.88281, &
+ 3982.89623, 4885.84733, 5975.43260, &
+ 7286.29500, 8858.72424, 10739.43477, &
+ 12982.41110, 15649.68745, 18811.37629, &
+ 22542.71275, 25724.93857, 27314.36781, &
+ 27498.59474, 26501.79312, 24605.92991, &
+ 22130.51655, 19381.30274, 16601.56419, &
+ 13952.53231, 11522.93244, 9350.82303, &
+ 7443.47723, 5790.77434, 4373.32696, &
+ 3167.47008, 2148.51663, 1293.15510, &
+ 581.62429, 0.00000, 0.00000 /
+
+ data b47/ 0.0000, 0.0000, 0.0000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.01188, 0.04650, &
+ 0.10170, 0.17401, 0.25832, &
+ 0.34850, 0.43872, 0.52448, &
+ 0.60307, 0.67328, 0.73492, &
+ 0.78834, 0.83418, 0.87320, &
+ 0.90622, 0.93399, 0.95723, &
+ 0.97650, 0.99223, 1.00000 /
+#else
+! Oct 23, 2012
+! QBO setting with ptop = 0.1 mb, pint ~ 60 mb
+ data a47/ 10.00000, 24.45365, 48.76776, &
+ 85.39458, 133.41983, 191.01402, &
+ 257.94919, 336.63306, 431.52741, &
+ 548.18995, 692.78825, 872.16512, &
+ 1094.18467, 1368.11917, 1704.99489, &
+ 2117.91945, 2622.42986, 3236.88281, &
+ 3982.89623, 4885.84733, 5975.43260, &
+ 7019.26669, 7796.15848, 8346.60209, &
+ 8700.31838, 8878.27554, 8894.27179, &
+ 8756.46404, 8469.60171, 8038.92687, &
+ 7475.89006, 6803.68067, 6058.68992, &
+ 5285.28859, 4526.01565, 3813.00206, &
+ 3164.95553, 2589.26318, 2085.96929, &
+ 1651.11596, 1278.81205, 962.38875, &
+ 695.07046, 470.40784, 282.61654, &
+ 126.92745, 0.00000, 0.00000 /
+ data b47/ 0.0000, 0.0000, 0.0000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00267, 0.01063, 0.02393, &
+ 0.04282, 0.06771, 0.09917, &
+ 0.13786, 0.18444, 0.23925, &
+ 0.30193, 0.37100, 0.44379, &
+ 0.51695, 0.58727, 0.65236, &
+ 0.71094, 0.76262, 0.80757, &
+ 0.84626, 0.87930, 0.90731, &
+ 0.93094, 0.95077, 0.96733, &
+ 0.98105, 0.99223, 1.00000 /
+#endif
+
+ data a48/ &
+ 1.00000, 2.69722, 5.17136, &
+ 8.89455, 14.24790, 22.07157, &
+ 33.61283, 50.48096, 74.79993, &
+ 109.40055, 158.00460, 225.44108, &
+ 317.89560, 443.19350, 611.11558, &
+ 833.74392, 1125.83405, 1505.20759, &
+ 1993.15829, 2614.86254, 3399.78420, &
+ 4382.06240, 5600.87014, 7100.73115, &
+ 8931.78242, 11149.97021, 13817.16841, &
+ 17001.20930, 20775.81856, 23967.33875, &
+ 25527.64563, 25671.22552, 24609.29622, &
+ 22640.51220, 20147.13482, 17477.63530, &
+ 14859.86462, 12414.92533, 10201.44191, &
+ 8241.50255, 6534.43202, 5066.17865, &
+ 3815.60705, 2758.60264, 1870.64631, &
+ 1128.33931, 510.47983, 0.00000, &
+ 0.00000 /
+
+ data b48/ &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.01253, &
+ 0.04887, 0.10724, 0.18455, &
+ 0.27461, 0.36914, 0.46103, &
+ 0.54623, 0.62305, 0.69099, &
+ 0.75016, 0.80110, 0.84453, &
+ 0.88127, 0.91217, 0.93803, &
+ 0.95958, 0.97747, 0.99223, &
+ 1.00000 /
+
+! High PBL resolution with top at 1 mb
+! SJL modified May 7, 2013 to ptop ~ 100 mb
+ data a54/100.00000, 254.83931, 729.54278, &
+ 1602.41121, 2797.50667, 4100.18977, &
+ 5334.87140, 6455.24153, 7511.80944, &
+ 8580.26355, 9714.44293, 10938.62253, &
+ 12080.36051, 12987.13921, 13692.75084, &
+ 14224.92180, 14606.55444, 14856.69953, &
+ 14991.32121, 15023.90075, 14965.91493, &
+ 14827.21612, 14616.33505, 14340.72252, &
+ 14006.94280, 13620.82849, 13187.60470, &
+ 12711.98873, 12198.27003, 11650.37451, &
+ 11071.91608, 10466.23819, 9836.44706, &
+ 9185.43852, 8515.96231, 7831.01080, &
+ 7135.14301, 6436.71659, 5749.00215, &
+ 5087.67188, 4465.67510, 3889.86419, &
+ 3361.63433, 2879.51065, 2441.02496, &
+ 2043.41345, 1683.80513, 1359.31122, &
+ 1067.09135, 804.40101, 568.62625, &
+ 357.32525, 168.33263, 0.00000, &
+ 0.00000 /
+
+ data b54/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00180, 0.00694, 0.01510, &
+ 0.02601, 0.03942, 0.05515, &
+ 0.07302, 0.09288, 0.11459, &
+ 0.13803, 0.16307, 0.18960, &
+ 0.21753, 0.24675, 0.27716, &
+ 0.30866, 0.34115, 0.37456, &
+ 0.40879, 0.44375, 0.47935, &
+ 0.51551, 0.55215, 0.58916, &
+ 0.62636, 0.66334, 0.69946, &
+ 0.73395, 0.76622, 0.79594, &
+ 0.82309, 0.84780, 0.87020, &
+ 0.89047, 0.90876, 0.92524, &
+ 0.94006, 0.95336, 0.96529, &
+ 0.97596, 0.98551, 0.99400, &
+ 1.00000 /
+
+
+! The 56-L setup
+ data a56/ 10.00000, 24.97818, 58.01160, &
+ 115.21466, 199.29210, 309.39897, &
+ 445.31785, 610.54747, 812.28518, &
+ 1059.80882, 1363.07092, 1732.09335, &
+ 2176.91502, 2707.68972, 3334.70962, &
+ 4068.31964, 4918.76594, 5896.01890, &
+ 7009.59166, 8268.36324, 9680.41211, &
+ 11252.86491, 12991.76409, 14901.95764, &
+ 16987.01313, 19249.15733, 21689.24182, &
+ 23845.11055, 25330.63353, 26243.52467, &
+ 26663.84998, 26657.94696, 26281.61371, &
+ 25583.05256, 24606.03265, 23393.39510, &
+ 21990.28845, 20445.82122, 18811.93894, &
+ 17139.59660, 15473.90350, 13850.50167, &
+ 12294.49060, 10821.62655, 9440.57746, &
+ 8155.11214, 6965.72496, 5870.70511, &
+ 4866.83822, 3949.90019, 3115.03562, &
+ 2357.07879, 1670.87329, 1051.65120, &
+ 495.51399, 0.00000, 0.00000 /
+
+ data b56 /0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00462, 0.01769, 0.03821, &
+ 0.06534, 0.09834, 0.13659, &
+ 0.17947, 0.22637, 0.27660, &
+ 0.32929, 0.38343, 0.43791, &
+ 0.49162, 0.54361, 0.59319, &
+ 0.63989, 0.68348, 0.72391, &
+ 0.76121, 0.79545, 0.82679, &
+ 0.85537, 0.88135, 0.90493, &
+ 0.92626, 0.94552, 0.96286, &
+ 0.97840, 0.99223, 1.00000 /
+
+! NAM levels
+ data a60/200., 1311.4934, 2424.6044, 3541.7594,&
+ 4662.9584, 5790.2234, 6932.6534, 8095.3034,&
+ 9278.1734, 10501.4834, 11755.1234, 13049.2034,&
+ 14403.9434, 15809.2334, 17315.6234, 18953.4434,&
+ 20783.3534, 22815.4634, 25059.8834, 27567.1634,&
+ 30148.42896047, 32193.91776039, 33237.35176644, 33332.15200668,&
+ 32747.34688095, 31710.06232008, 30381.0344269, 28858.71577772,&
+ 27218.00439794, 25500.31691133, 23734.52294749, 21947.3406187,&
+ 20167.06984021, 18396.08144096, 16688.20978135, 15067.73749198,&
+ 13564.49530178, 12183.34512952, 10928.24869364, 9815.02787644,&
+ 8821.38325756, 7943.05793658, 7181.90985128, 6500.94645341,&
+ 5932.84856135, 5420.87683616, 4959.15585353, 4522.15047657,&
+ 4103.63596619, 3703.72540955, 3322.52525084, 2953.65688391,&
+ 2597.18532669, 2253.10764634, 1915.10585833, 1583.14516612,&
+ 1257.18953818, 937.3977544 , 623.60136981, 311.11085215,&
+ 0. /
+
+ data b60/0., 0., 0., 0., 0.,&
+ 0. , 0. , 0. , 0. , 0. ,&
+ 0. , 0. , 0. , 0. , 0. ,&
+ 0. , 0. , 0. , 0. , 0. ,&
+ 0.0014653 , 0.01021565, 0.0301554 , 0.06025816, 0.09756877,&
+ 0.13994493, 0.18550048, 0.23318371, 0.2819159 , 0.33120838,&
+ 0.38067633, 0.42985641, 0.47816985, 0.52569303, 0.57109611,&
+ 0.61383996, 0.6532309 , 0.68922093, 0.72177094, 0.75052515,&
+ 0.77610288, 0.79864598, 0.81813309, 0.83553022, 0.85001773,&
+ 0.86305395, 0.8747947 , 0.88589325, 0.89650986, 0.9066434 ,&
+ 0.91629284, 0.92562094, 0.93462705, 0.94331221, 0.95183659,&
+ 0.96020153, 0.96840839, 0.97645359, 0.98434181, 0.99219119, 1. /
+
+! This is activated by USE_GFSL63
+! Thfollowing L63 setting is the same as NCEP GFS's L64 except the top
+! 3 layers
+ data a63/64.247, 137.790, 221.958, &
+ 318.266, 428.434, 554.424, &
+ 698.457, 863.05803, 1051.07995, &
+ 1265.75194, 1510.71101, 1790.05098, &
+ 2108.36604, 2470.78817, 2883.03811, &
+ 3351.46002, 3883.05187, 4485.49315, &
+ 5167.14603, 5937.04991, 6804.87379, &
+ 7780.84698, 8875.64338, 10100.20534, &
+ 11264.35673, 12190.64366, 12905.42546, &
+ 13430.87867, 13785.88765, 13986.77987, &
+ 14047.96335, 13982.46770, 13802.40331, &
+ 13519.33841, 13144.59486, 12689.45608, &
+ 12165.28766, 11583.57006, 10955.84778, &
+ 10293.60402, 9608.08306, 8910.07678, &
+ 8209.70131, 7516.18560, 6837.69250, &
+ 6181.19473, 5552.39653, 4955.72632, &
+ 4394.37629, 3870.38682, 3384.76586, &
+ 2937.63489, 2528.37666, 2155.78385, &
+ 1818.20722, 1513.68173, 1240.03585, &
+ 994.99144, 776.23591, 581.48797, &
+ 408.53400, 255.26520, 119.70243, 0. /
+
+ data b63/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00201, 0.00792, 0.01755, &
+ 0.03079, 0.04751, 0.06761, &
+ 0.09097, 0.11746, 0.14690, &
+ 0.17911, 0.21382, 0.25076, &
+ 0.28960, 0.32994, 0.37140, &
+ 0.41353, 0.45589, 0.49806, &
+ 0.53961, 0.58015, 0.61935, &
+ 0.65692, 0.69261, 0.72625, &
+ 0.75773, 0.78698, 0.81398, &
+ 0.83876, 0.86138, 0.88192, &
+ 0.90050, 0.91722, 0.93223, &
+ 0.94565, 0.95762, 0.96827, &
+ 0.97771, 0.98608, 0.99347, 1./
+#ifdef GFSL64
+ data a64/20.00000, 68.00000, 137.79000, &
+ 221.95800, 318.26600, 428.43400, &
+ 554.42400, 698.45700, 863.05803, &
+ 1051.07995, 1265.75194, 1510.71101, &
+ 1790.05098, 2108.36604, 2470.78817, &
+ 2883.03811, 3351.46002, 3883.05187, &
+ 4485.49315, 5167.14603, 5937.04991, &
+ 6804.87379, 7780.84698, 8875.64338, &
+ 9921.40745, 10760.99844, 11417.88354, &
+ 11911.61193, 12258.61668, 12472.89642, &
+ 12566.58298, 12550.43517, 12434.26075, &
+ 12227.27484, 11938.39468, 11576.46910, &
+ 11150.43640, 10669.41063, 10142.69482, &
+ 9579.72458, 8989.94947, 8382.67090, &
+ 7766.85063, 7150.91171, 6542.55077, &
+ 5948.57894, 5374.81094, 4825.99383, &
+ 4305.79754, 3816.84622, 3360.78848, &
+ 2938.39801, 2549.69756, 2194.08449, &
+ 1870.45732, 1577.34218, 1313.00028, &
+ 1075.52114, 862.90778, 673.13815, &
+ 504.22118, 354.22752, 221.32110, &
+ 103.78014, 0./
+ data b64/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00179, 0.00705, 0.01564, &
+ 0.02749, 0.04251, 0.06064, &
+ 0.08182, 0.10595, 0.13294, &
+ 0.16266, 0.19492, 0.22950, &
+ 0.26615, 0.30455, 0.34435, &
+ 0.38516, 0.42656, 0.46815, &
+ 0.50949, 0.55020, 0.58989, &
+ 0.62825, 0.66498, 0.69987, &
+ 0.73275, 0.76351, 0.79208, &
+ 0.81845, 0.84264, 0.86472, &
+ 0.88478, 0.90290, 0.91923, &
+ 0.93388, 0.94697, 0.95865, &
+ 0.96904, 0.97826, 0.98642, &
+ 0.99363, 1./
+#else
+ data a64/1.00000, 3.90000, 8.70000, &
+ 15.42000, 24.00000, 34.50000, &
+ 47.00000, 61.50000, 78.60000, &
+ 99.13500, 124.12789, 154.63770, &
+ 191.69700, 236.49300, 290.38000, &
+ 354.91000, 431.82303, 523.09300, &
+ 630.92800, 757.79000, 906.45000, &
+ 1079.85000, 1281.00000, 1515.00000, &
+ 1788.00000, 2105.00000, 2470.00000, &
+ 2889.00000, 3362.00000, 3890.00000, &
+ 4475.00000, 5120.00000, 5830.00000, &
+ 6608.00000, 7461.00000, 8395.00000, &
+ 9424.46289, 10574.46880, 11864.80270, &
+ 13312.58890, 14937.03710, 16759.70700, &
+ 18804.78710, 21099.41210, 23674.03710, &
+ 26562.82810, 29804.11720, 32627.31640, &
+ 34245.89840, 34722.28910, 34155.19920, &
+ 32636.50390, 30241.08200, 27101.44920, &
+ 23362.20700, 19317.05270, 15446.17090, &
+ 12197.45210, 9496.39941, 7205.66992, &
+ 5144.64307, 3240.79346, 1518.62134, &
+ 0.00000, 0.00000 /
+
+ data b64/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00813, &
+ 0.03224, 0.07128, 0.12445, &
+ 0.19063, 0.26929, 0.35799, &
+ 0.45438, 0.55263, 0.64304, &
+ 0.71703, 0.77754, 0.82827, &
+ 0.87352, 0.91502, 0.95235, &
+ 0.98511, 1.00000 /
+#endif
+!-->cjg
+ data a68/1.00000, 2.68881, 5.15524, &
+ 8.86683, 14.20349, 22.00278, &
+ 33.50807, 50.32362, 74.56680, &
+ 109.05958, 157.51214, 224.73844, &
+ 316.90481, 441.81219, 609.21090, &
+ 831.14537, 1122.32514, 1500.51628, &
+ 1986.94617, 2606.71274, 3389.18802, &
+ 4368.40473, 5583.41379, 7078.60015, &
+ 8903.94455, 11115.21886, 13774.60566, &
+ 16936.82070, 20340.47045, 23193.71492, &
+ 24870.36141, 25444.59363, 25252.57081, &
+ 24544.26211, 23474.29096, 22230.65331, &
+ 20918.50731, 19589.96280, 18296.26682, &
+ 17038.02866, 15866.85655, 14763.18943, &
+ 13736.83624, 12794.11850, 11930.72442, &
+ 11137.17217, 10404.78946, 9720.03954, &
+ 9075.54055, 8466.72650, 7887.12346, &
+ 7333.90490, 6805.43028, 6297.33773, &
+ 5805.78227, 5327.94995, 4859.88765, &
+ 4398.63854, 3942.81761, 3491.08449, &
+ 3043.04531, 2598.71608, 2157.94527, &
+ 1720.87444, 1287.52805, 858.02944, &
+ 432.71276, 8.10905, 0.00000 /
+
+ data b68/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00283, 0.01590, &
+ 0.04412, 0.08487, 0.13284, &
+ 0.18470, 0.23828, 0.29120, &
+ 0.34211, 0.39029, 0.43518, &
+ 0.47677, 0.51536, 0.55091, &
+ 0.58331, 0.61263, 0.63917, &
+ 0.66333, 0.68552, 0.70617, &
+ 0.72555, 0.74383, 0.76117, &
+ 0.77765, 0.79335, 0.80838, &
+ 0.82287, 0.83693, 0.85069, &
+ 0.86423, 0.87760, 0.89082, &
+ 0.90392, 0.91689, 0.92973, &
+ 0.94244, 0.95502, 0.96747, &
+ 0.97979, 0.99200, 1.00000 /
+
+ data a96/1.00000, 2.35408, 4.51347, &
+ 7.76300, 12.43530, 19.26365, &
+ 29.33665, 44.05883, 65.28397, &
+ 95.48274, 137.90344, 196.76073, &
+ 277.45330, 386.81095, 533.37018, &
+ 727.67600, 982.60677, 1313.71685, &
+ 1739.59104, 2282.20281, 2967.26766, &
+ 3824.58158, 4888.33404, 6197.38450, &
+ 7795.49158, 9731.48414, 11969.71024, &
+ 14502.88894, 17304.52434, 20134.76139, &
+ 22536.63814, 24252.54459, 25230.65591, &
+ 25585.72044, 25539.91412, 25178.87141, &
+ 24644.84493, 23978.98781, 23245.49366, &
+ 22492.11600, 21709.93990, 20949.64473, &
+ 20225.94258, 19513.31158, 18829.32485, &
+ 18192.62250, 17589.39396, 17003.45386, &
+ 16439.01774, 15903.91204, 15396.39758, &
+ 14908.02140, 14430.65897, 13967.88643, &
+ 13524.16667, 13098.30227, 12687.56457, &
+ 12287.08757, 11894.41553, 11511.54106, &
+ 11139.22483, 10776.01912, 10419.75711, &
+ 10067.11881, 9716.63489, 9369.61967, &
+ 9026.69066, 8687.29884, 8350.04978, &
+ 8013.20925, 7677.12187, 7343.12994, &
+ 7011.62844, 6681.98102, 6353.09764, &
+ 6025.10535, 5699.10089, 5375.54503, &
+ 5053.63074, 4732.62740, 4413.38037, &
+ 4096.62775, 3781.79777, 3468.45371, &
+ 3157.19882, 2848.25306, 2541.19150, &
+ 2236.21942, 1933.50628, 1632.83741, &
+ 1334.35954, 1038.16655, 744.22318, &
+ 452.71094, 194.91899, 0.00000, &
+ 0.00000 /
+
+ data b96/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00193, &
+ 0.00974, 0.02538, 0.04876, &
+ 0.07817, 0.11081, 0.14514, &
+ 0.18007, 0.21486, 0.24866, &
+ 0.28088, 0.31158, 0.34030, &
+ 0.36701, 0.39210, 0.41554, &
+ 0.43733, 0.45774, 0.47707, &
+ 0.49540, 0.51275, 0.52922, &
+ 0.54495, 0.56007, 0.57459, &
+ 0.58850, 0.60186, 0.61471, &
+ 0.62715, 0.63922, 0.65095, &
+ 0.66235, 0.67348, 0.68438, &
+ 0.69510, 0.70570, 0.71616, &
+ 0.72651, 0.73675, 0.74691, &
+ 0.75700, 0.76704, 0.77701, &
+ 0.78690, 0.79672, 0.80649, &
+ 0.81620, 0.82585, 0.83542, &
+ 0.84492, 0.85437, 0.86375, &
+ 0.87305, 0.88229, 0.89146, &
+ 0.90056, 0.90958, 0.91854, &
+ 0.92742, 0.93623, 0.94497, &
+ 0.95364, 0.96223, 0.97074, &
+ 0.97918, 0.98723, 0.99460, &
+ 1.00000 /
+!<--cjg
+!
+! Ultra high troposphere resolution
+ data a100/100.00000, 300.00000, 800.00000, &
+ 1762.35235, 3106.43596, 4225.71874, &
+ 4946.40525, 5388.77387, 5708.35540, &
+ 5993.33124, 6277.73673, 6571.49996, &
+ 6877.05339, 7195.14327, 7526.24920, &
+ 7870.82981, 8229.35361, 8602.30193, &
+ 8990.16936, 9393.46399, 9812.70768, &
+ 10248.43625, 10701.19980, 11171.56286, &
+ 11660.10476, 12167.41975, 12694.11735, &
+ 13240.82253, 13808.17600, 14396.83442, &
+ 15007.47066, 15640.77407, 16297.45067, &
+ 16978.22343, 17683.83253, 18415.03554, &
+ 19172.60771, 19957.34218, 20770.05022, &
+ 21559.14829, 22274.03147, 22916.87519, &
+ 23489.70456, 23994.40187, 24432.71365, &
+ 24806.25734, 25116.52754, 25364.90190, &
+ 25552.64670, 25680.92203, 25750.78675, &
+ 25763.20311, 25719.04113, 25619.08274, &
+ 25464.02630, 25254.49482, 24991.06137, &
+ 24674.32737, 24305.11235, 23884.79781, &
+ 23415.77059, 22901.76510, 22347.84738, &
+ 21759.93950, 21144.07284, 20505.73136, &
+ 19849.54271, 19179.31412, 18498.23400, &
+ 17809.06809, 17114.28232, 16416.10343, &
+ 15716.54833, 15017.44246, 14320.43478, &
+ 13627.01116, 12938.50682, 12256.11762, &
+ 11580.91062, 10913.83385, 10255.72526, &
+ 9607.32122, 8969.26427, 8342.11044, &
+ 7726.33606, 7122.34405, 6530.46991, &
+ 5950.98721, 5384.11279, 4830.01153, &
+ 4288.80090, 3760.55514, 3245.30920, &
+ 2743.06250, 2253.78294, 1777.41285, &
+ 1313.88054, 863.12371, 425.13088, &
+ 0.00000, 0.00000 /
+
+
+ data b100/0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00000, 0.00000, 0.00000, &
+ 0.00052, 0.00209, 0.00468, &
+ 0.00828, 0.01288, 0.01849, &
+ 0.02508, 0.03266, 0.04121, &
+ 0.05075, 0.06126, 0.07275, &
+ 0.08521, 0.09866, 0.11308, &
+ 0.12850, 0.14490, 0.16230, &
+ 0.18070, 0.20009, 0.22042, &
+ 0.24164, 0.26362, 0.28622, &
+ 0.30926, 0.33258, 0.35605, &
+ 0.37958, 0.40308, 0.42651, &
+ 0.44981, 0.47296, 0.49591, &
+ 0.51862, 0.54109, 0.56327, &
+ 0.58514, 0.60668, 0.62789, &
+ 0.64872, 0.66919, 0.68927, &
+ 0.70895, 0.72822, 0.74709, &
+ 0.76554, 0.78357, 0.80117, &
+ 0.81835, 0.83511, 0.85145, &
+ 0.86736, 0.88286, 0.89794, &
+ 0.91261, 0.92687, 0.94073, &
+ 0.95419, 0.96726, 0.97994, &
+ 0.99223, 1.00000 /
+
+ data a104/ &
+ 1.8827062944e-01, 7.7977549145e-01, 2.1950593583e+00, &
+ 4.9874566624e+00, 9.8041418997e+00, 1.7019717163e+01, &
+ 2.7216579591e+01, 4.0518628401e+01, 5.6749646818e+01, &
+ 7.5513868331e+01, 9.6315093333e+01, 1.1866706195e+02, &
+ 1.4216835396e+02, 1.6653733709e+02, 1.9161605772e+02, &
+ 2.1735580129e+02, 2.4379516604e+02, 2.7103771847e+02, &
+ 2.9923284173e+02, 3.2856100952e+02, 3.5922338766e+02, &
+ 3.9143507908e+02, 4.2542117983e+02, 4.6141487902e+02, &
+ 4.9965698106e+02, 5.4039638379e+02, 5.8389118154e+02, &
+ 6.3041016829e+02, 6.8023459505e+02, 7.3366009144e+02, &
+ 7.9099869949e+02, 8.5258099392e+02, 9.1875827946e+02, &
+ 9.8990486716e+02, 1.0664204381e+03, 1.1487325074e+03, &
+ 1.2372990044e+03, 1.3326109855e+03, 1.4351954993e+03, &
+ 1.5456186222e+03, 1.6644886848e+03, 1.7924597105e+03, &
+ 1.9302350870e+03, 2.0785714934e+03, 2.2382831070e+03, &
+ 2.4102461133e+03, 2.5954035462e+03, 2.7947704856e+03, &
+ 3.0094396408e+03, 3.2405873512e+03, 3.4894800360e+03, &
+ 3.7574811281e+03, 4.0460585279e+03, 4.3567926151e+03, &
+ 4.6913848588e+03, 5.0516670674e+03, 5.4396113207e+03, &
+ 5.8573406270e+03, 6.3071403487e+03, 6.7914704368e+03, &
+ 7.3129785102e+03, 7.8745138115e+03, 8.4791420557e+03, &
+ 9.1301611750e+03, 9.8311179338e+03, 1.0585825354e+04, &
+ 1.1398380836e+04, 1.2273184781e+04, 1.3214959424e+04, &
+ 1.4228767429e+04, 1.5320029596e+04, 1.6494540743e+04, &
+ 1.7758482452e+04, 1.9118430825e+04, 2.0422798801e+04, &
+ 2.1520147587e+04, 2.2416813461e+04, 2.3118184510e+04, &
+ 2.3628790785e+04, 2.3952411814e+04, 2.4092209011e+04, &
+ 2.4050892106e+04, 2.3830930156e+04, 2.3434818358e+04, &
+ 2.2865410898e+04, 2.2126326004e+04, 2.1222420323e+04, &
+ 2.0160313690e+04, 1.8948920926e+04, 1.7599915822e+04, &
+ 1.6128019809e+04, 1.4550987232e+04, 1.2889169132e+04, &
+ 1.1164595563e+04, 9.4227665517e+03, 7.7259097899e+03, &
+ 6.1538244381e+03, 4.7808126007e+03, 3.5967415552e+03, &
+ 2.5886394104e+03, 1.7415964865e+03, 1.0393721271e+03, &
+ 4.6478852032e+02, 7.0308342481e-13, 0.0000000000e+00 /
+
+
+ data b104/ &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 0.0000000000e+00, &
+ 0.0000000000e+00, 0.0000000000e+00, 1.5648447298e-03, &
+ 6.2617046389e-03, 1.4104157933e-02, 2.5118187415e-02, &
+ 3.9340510972e-02, 5.6816335609e-02, 7.7596328431e-02, &
+ 1.0173255472e-01, 1.2927309709e-01, 1.6025505622e-01, &
+ 1.9469566981e-01, 2.3258141217e-01, 2.7385520518e-01, &
+ 3.1840233814e-01, 3.6603639170e-01, 4.1648734767e-01, &
+ 4.6939496013e-01, 5.2431098738e-01, 5.8071350676e-01, &
+ 6.3803478105e-01, 6.9495048840e-01, 7.4963750338e-01, &
+ 7.9975208897e-01, 8.4315257576e-01, 8.8034012292e-01, &
+ 9.1184389721e-01, 9.3821231526e-01, 9.6000677644e-01, &
+ 9.7779792223e-01, 9.9216315122e-01, 1.0000000000e+00 /
+
+! IFS-like L125(top 12 levels removed from IFSL137)
+ data a125/ 64., &
+ 86.895882, 107.415741, 131.425507, 159.279404, 191.338562, &
+ 227.968948, 269.539581, 316.420746, 368.982361, 427.592499, 492.616028, &
+ 564.413452, 643.339905, 729.744141, 823.967834, 926.344910, 1037.201172, &
+ 1156.853638, 1285.610352, 1423.770142, 1571.622925, 1729.448975, 1897.519287, &
+ 2076.095947, 2265.431641, 2465.770508, 2677.348145, 2900.391357, 3135.119385, &
+ 3381.743652, 3640.468262, 3911.490479, 4194.930664, 4490.817383, 4799.149414, &
+ 5119.895020, 5452.990723, 5798.344727, 6156.074219, 6526.946777, 6911.870605, &
+ 7311.869141, 7727.412109, 8159.354004, 8608.525391, 9076.400391, 9562.682617, &
+ 10065.978516, 10584.631836, 11116.662109, 11660.067383, 12211.547852, 12766.873047, &
+ 13324.668945, 13881.331055, 14432.139648, 14975.615234, 15508.256836, 16026.115234, &
+ 16527.322266, 17008.789063, 17467.613281, 17901.621094, 18308.433594, 18685.718750, &
+ 19031.289063, 19343.511719, 19620.042969, 19859.390625, 20059.931641, 20219.664063, &
+ 20337.863281, 20412.308594, 20442.078125, 20425.718750, 20361.816406, 20249.511719, &
+ 20087.085938, 19874.025391, 19608.572266, 19290.226563, 18917.460938, 18489.707031, &
+ 18006.925781, 17471.839844, 16888.687500, 16262.046875, 15596.695313, 14898.453125, &
+ 14173.324219, 13427.769531, 12668.257813, 11901.339844, 11133.304688, 10370.175781, &
+ 9617.515625, 8880.453125, 8163.375000, 7470.343750, 6804.421875, 6168.531250, &
+ 5564.382813, 4993.796875, 4457.375000, 3955.960938, 3489.234375, 3057.265625, &
+ 2659.140625, 2294.242188, 1961.500000, 1659.476563, 1387.546875, 1143.250000, &
+ 926.507813, 734.992188, 568.062500, 424.414063, 302.476563, 202.484375, &
+ 122.101563, 62.781250, 22.835938, 3.757813, 0.000000, 0.000000 /
+
+ data b125/ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, &
+ 0.000000, 0.000007, 0.000024, 0.000059, 0.000112, 0.000199, &
+ 0.000340, 0.000562, 0.000890, 0.001353, 0.001992, 0.002857, &
+ 0.003971, 0.005378, 0.007133, 0.009261, 0.011806, 0.014816, &
+ 0.018318, 0.022355, 0.026964, 0.032176, 0.038026, 0.044548, &
+ 0.051773, 0.059728, 0.068448, 0.077958, 0.088286, 0.099462, &
+ 0.111505, 0.124448, 0.138313, 0.153125, 0.168910, 0.185689, &
+ 0.203491, 0.222333, 0.242244, 0.263242, 0.285354, 0.308598, &
+ 0.332939, 0.358254, 0.384363, 0.411125, 0.438391, 0.466003, &
+ 0.493800, 0.521619, 0.549301, 0.576692, 0.603648, 0.630036, &
+ 0.655736, 0.680643, 0.704669, 0.727739, 0.749797, 0.770798, &
+ 0.790717, 0.809536, 0.827256, 0.843881, 0.859432, 0.873929, &
+ 0.887408, 0.899900, 0.911448, 0.922096, 0.931881, 0.940860, &
+ 0.949064, 0.956550, 0.963352, 0.969513, 0.975078, 0.980072, &
+ 0.984542, 0.988500, 0.991984, 0.995003, 0.997630, 1.000000 /
+
+ select case (km)
+
+ case (24)
+
+ ks = 5
+ do k=1,km+1
+ ak(k) = a24(k)
+ bk(k) = b24(k)
+ enddo
+
+ case (26)
+
+ ks = 7
+ do k=1,km+1
+ ak(k) = a26(k)
+ bk(k) = b26(k)
+ enddo
+
+ case (32)
+#ifdef OLD_32
+ ks = 13 ! high-res trop_32 setup
+#else
+ ks = 7
+#endif
+ do k=1,km+1
+ ak(k) = a32(k)
+ bk(k) = b32(k)
+ enddo
+
+ case (47)
+! ks = 27 ! high-res trop-strat
+ ks = 20 ! Oct 23, 2012
+ do k=1,km+1
+ ak(k) = a47(k)
+ bk(k) = b47(k)
+ enddo
+
+ case (48)
+ ks = 28
+ do k=1,km+1
+ ak(k) = a48(k)
+ bk(k) = b48(k)
+ enddo
+
+ case (52)
+ ks = 35 ! pint = 223
+ do k=1,km+1
+ ak(k) = a52(k)
+ bk(k) = b52(k)
+ enddo
+
+ case (54)
+ ks = 11 ! pint = 109.4
+ do k=1,km+1
+ ak(k) = a54(k)
+ bk(k) = b54(k)
+ enddo
+
+ case (56)
+ ks = 26
+ do k=1,km+1
+ ak(k) = a56(k)
+ bk(k) = b56(k)
+ enddo
+
+ case (60)
+ ks = 19
+ do k=1,km+1
+ ak(k) = a60(k)
+ bk(k) = b60(k)
+ enddo
+
+
+ case (64)
+#ifdef GFSL64
+ ks = 23
+#else
+ ks = 46
+#endif
+ do k=1,km+1
+ ak(k) = a64(k)
+ bk(k) = b64(k)
+ enddo
+!-->cjg
+ case (68)
+ ks = 27
+ do k=1,km+1
+ ak(k) = a68(k)
+ bk(k) = b68(k)
+ enddo
+
+ case (96)
+ ks = 27
+ do k=1,km+1
+ ak(k) = a96(k)
+ bk(k) = b96(k)
+ enddo
+!<--cjg
+
+ case (100)
+ ks = 38
+ do k=1,km+1
+ ak(k) = a100(k)
+ bk(k) = b100(k)
+ enddo
+
+ case (104)
+ ks = 73
+ do k=1,km+1
+ ak(k) = a104(k)
+ bk(k) = b104(k)
+ enddo
+
+#ifndef TEST_GWAVES
+ case (10)
+!--------------------------------------------------
+! Pure sigma-coordinate with uniform spacing in "z"
+!--------------------------------------------------
+!
+ pt = 2000. ! model top pressure (pascal)
+! pt = 100. ! 1 mb
+ press(1) = pt
+ press(km+1) = p0
+ dlnp = (log(p0) - log(pt)) / real(km)
+
+ lnpe = log(press(km+1))
+ do k=km,2,-1
+ lnpe = lnpe - dlnp
+ press(k) = exp(lnpe)
+ enddo
+
+! Search KS
+ ks = 0
+ do k=1,km
+ if(press(k) >= pc) then
+ ks = k-1
+ goto 123
+ endif
+ enddo
+123 continue
+
+ if(ks /= 0) then
+ do k=1,ks
+ ak(k) = press(k)
+ bk(k) = 0.
+ enddo
+ endif
+
+ pint = press(ks+1)
+ do k=ks+1,km
+ ak(k) = pint*(press(km)-press(k))/(press(km)-pint)
+ bk(k) = (press(k) - ak(k)) / press(km+1)
+ enddo
+ ak(km+1) = 0.
+ bk(km+1) = 1.
+
+! do k=2,km
+! bk(k) = real(k-1) / real(km)
+! ak(k) = pt * ( 1. - bk(k) )
+! enddo
+#endif
+
+! The following 4 selections are better for non-hydrostatic
+! Low top:
+ case (31)
+ ptop = 300.
+ pint = 100.E2
+ call var_dz(km, ak, bk, ptop, ks, pint, 1.035)
+#ifndef TEST_GWAVES
+ case (41)
+ ptop = 100.
+ pint = 100.E2
+ call var_hi(km, ak, bk, ptop, ks, pint, 1.035)
+#endif
+ case (51)
+ ptop = 100.
+ pint = 100.E2
+ call var_hi(km, ak, bk, ptop, ks, pint, 1.035)
+! Mid-top:
+ case (55)
+ ptop = 10.
+ pint = 100.E2
+! call var_dz(km, ak, bk, ptop, ks, pint, 1.035)
+ call var_hi(km, ak, bk, ptop, ks, pint, 1.035)
+#ifdef USE_GFSL63
+! GFS L64 equivalent setting
+ case (63)
+ ks = 23
+ ptop = a63(1)
+ pint = a63(ks+1)
+ do k=1,km+1
+ ak(k) = a63(k)
+ bk(k) = b63(k)
+ enddo
+#else
+ case (63)
+ ptop = 1. ! high top
+ pint = 100.E2
+ call var_hi(km, ak, bk, ptop, ks, pint, 1.035)
+#endif
+! NGGPS_GFS
+ case (91)
+ pint = 100.E2
+ ptop = 40.
+ call var_gfs(km, ak, bk, ptop, ks, pint, 1.029)
+! call var_gfs(km, ak, bk, ptop, ks, pint, 1.03)
+ case (95)
+! Mid-top settings:
+ pint = 100.E2
+ ptop = 20.
+ call var_gfs(km, ak, bk, ptop, ks, pint, 1.028)
+ case (127)
+ ptop = 1.
+ pint = 75.E2
+ call var_gfs(km, ak, bk, ptop, ks, pint, 1.028)
+! IFS-like L125
+ case (125)
+ ks = 33
+ ptop = a125(1)
+ pint = a125(ks+1)
+ do k=1,km+1
+ ak(k) = a125(k)
+ bk(k) = b125(k)
+ enddo
+ case default
+
+#ifdef TEST_GWAVES
+!--------------------------------------------------
+! Pure sigma-coordinate with uniform spacing in "z"
+!--------------------------------------------------
+ call gw_1d(km, 1000.E2, ak, bk, ptop, 10.E3, pt1)
+ ks = 0
+ pint = ak(1)
+#else
+
+!----------------------------------------------------------------
+! Sigma-coordinate with uniform spacing in sigma and ptop = 1 mb
+!----------------------------------------------------------------
+ pt = 100.
+! One pressure layer
+ ks = 1
+! pint = pt + 0.5*1.E5/real(km) ! SJL: 20120327
+ pint = pt + 1.E5/real(km)
+
+ ak(1) = pt
+ bk(1) = 0.
+ ak(2) = pint
+ bk(2) = 0.
+
+ do k=3,km+1
+ bk(k) = real(k-2) / real(km-1)
+ ak(k) = pint - bk(k)*pint
+ enddo
+ ak(km+1) = 0.
+ bk(km+1) = 1.
+#endif
+ end select
+ ptop = ak(1)
+ pint = ak(ks+1)
+
+ end subroutine set_eta
+#endif
+
+!>@brief The subroutine 'set_external_eta' sets 'ptop' (model top) and
+!! 'ks' (first level of pure pressure coordinates given the coefficients
+!! 'ak' and 'bk'
+ subroutine set_external_eta(ak, bk, ptop, ks)
+ implicit none
+ real, intent(in) :: ak(:)
+ real, intent(in) :: bk(:)
+ real, intent(out) :: ptop !< model top (Pa)
+ integer, intent(out) :: ks !< number of pure p layers
+ !--- local variables
+ integer :: k
+ real :: eps = 1.d-7
+
+ ptop = ak(1)
+ ks = 1
+ do k = 1, size(bk(:))
+ if (bk(k).lt.eps) ks = k
+ enddo
+ !--- change ks to layers from levels
+ ks = ks - 1
+ if (is_master()) write(6,*) ' ptop & ks ', ptop, ks
+
+ end subroutine set_external_eta
+
+
+ subroutine var_les(km, ak, bk, ptop, ks, pint, s_rate)
+ implicit none
+ integer, intent(in):: km
+ real, intent(in):: ptop
+ real, intent(in):: s_rate !< between [1. 1.1]
+ real, intent(out):: ak(km+1), bk(km+1)
+ real, intent(inout):: pint
+ integer, intent(out):: ks
+! Local
+ real, parameter:: p00 = 1.E5
+ real, dimension(km+1):: ze, pe1, peln, eta
+ real, dimension(km):: dz, s_fac, dlnp, pm, dp, dk
+ real ztop, t0, dz0, sum1, tmp1
+ real ep, es, alpha, beta, gama
+ real, parameter:: akap = 2./7.
+!---- Tunable parameters:
+ real:: k_inc = 10 !< number of layers from bottom up to near const dz region
+ real:: s0 = 0.8 !< lowest layer stretch factor
+!-----------------------
+ real:: s_inc
+ integer k
+
+ pe1(1) = ptop
+ peln(1) = log(pe1(1))
+ pe1(km+1) = p00
+ peln(km+1) = log(pe1(km+1))
+
+ t0 = 273.
+ ztop = rdgas/grav*t0*(peln(km+1) - peln(1))
+
+ s_inc = (1.-s0) / real(k_inc)
+ s_fac(km) = s0
+
+ do k=km-1, km-k_inc, -1
+ s_fac(k) = s_fac(k+1) + s_inc
+ enddo
+
+ s_fac(km-k_inc-1) = 0.5*(s_fac(km-k_inc) + s_rate)
+
+ do k=km-k_inc-2, 5, -1
+ s_fac(k) = s_rate * s_fac(k+1)
+ enddo
+
+ s_fac(4) = 0.5*(1.1+s_rate)*s_fac(5)
+ s_fac(3) = 1.1 *s_fac(4)
+ s_fac(2) = 1.1 *s_fac(3)
+ s_fac(1) = 1.1 *s_fac(2)
+
+ sum1 = 0.
+ do k=1,km
+ sum1 = sum1 + s_fac(k)
+ enddo
+
+ dz0 = ztop / sum1
+
+ do k=1,km
+ dz(k) = s_fac(k) * dz0
+ enddo
+
+ ze(km+1) = 0.
+ do k=km,1,-1
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+
+! Re-scale dz with the stretched ztop
+ do k=1,km
+ dz(k) = dz(k) * (ztop/ze(1))
+ enddo
+
+ do k=km,1,-1
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+! ze(1) = ztop
+
+ if ( is_master() ) then
+ write(*,*) 'var_les: computed model top (m)=', ztop, ' bottom/top dz=', dz(km), dz(1)
+! do k=1,km
+! write(*,*) k, s_fac(k)
+! enddo
+ endif
+
+ call sm1_edge(1, 1, 1, 1, km, 1, 1, ze, 2)
+
+! Given z --> p
+ do k=1,km
+ dz(k) = ze(k) - ze(k+1)
+ dlnp(k) = grav*dz(k) / (rdgas*t0)
+ !write(*,*) k, dz(k)
+ enddo
+ do k=2,km
+ peln(k) = peln(k-1) + dlnp(k-1)
+ pe1(k) = exp(peln(k))
+ enddo
+
+
+! Pe(k) = ak(k) + bk(k) * PS
+! Locate pint and KS
+ ks = 0
+ do k=2,km
+ if ( pint < pe1(k)) then
+ ks = k-1
+ exit
+ endif
+ enddo
+ if ( is_master() ) then
+ write(*,*) 'For (input) PINT=', 0.01*pint, ' KS=', ks, 'pint(computed)=', 0.01*pe1(ks+1)
+ endif
+ pint = pe1(ks+1)
+
+ do k=1,km+1
+ eta(k) = pe1(k) / pe1(km+1)
+ enddo
+
+ ep = eta(ks+1)
+ es = eta(km)
+! es = 1.
+ alpha = (ep**2-2.*ep*es) / (es-ep)**2
+ beta = 2.*ep*es**2 / (es-ep)**2
+ gama = -(ep*es)**2 / (es-ep)**2
+
+! Pure pressure:
+ do k=1,ks+1
+ ak(k) = eta(k)*1.e5
+ bk(k) = 0.
+ enddo
+
+ do k=ks+2, km
+ ak(k) = alpha*eta(k) + beta + gama/eta(k)
+ ak(k) = ak(k)*1.e5
+ enddo
+ ak(km+1) = 0.
+
+ do k=ks+2, km
+ bk(k) = (pe1(k) - ak(k))/pe1(km+1)
+ enddo
+ bk(km+1) = 1.
+
+ if ( is_master() ) then
+ ! write(*,*) 'KS=', ks, 'PINT (mb)=', pint/100.
+ ! do k=1,km
+ ! pm(k) = 0.5*(pe1(k)+pe1(k+1))/100.
+ ! write(*,*) k, pm(k), dz(k)
+ ! enddo
+ tmp1 = ak(ks+1)
+ do k=ks+1,km
+ tmp1 = max(tmp1, (ak(k)-ak(k+1))/max(1.E-5, (bk(k+1)-bk(k))) )
+ enddo
+ write(*,*) 'Hybrid Sigma-P: minimum allowable surface pressure (hpa)=', tmp1/100.
+ write(*,800) (pm(k), k=km,1,-1)
+ endif
+
+ do k=1,km
+ dp(k) = (pe1(k+1) - pe1(k))/100.
+ dk(k) = pe1(k+1)**akap - pe1(k)**akap
+ enddo
+
+800 format(1x,5(1x,f9.4))
+
+ end subroutine var_les
+
+
+
+ subroutine var_gfs(km, ak, bk, ptop, ks, pint, s_rate)
+ integer, intent(in):: km
+ real, intent(in):: ptop
+ real, intent(in):: s_rate !< between [1. 1.1]
+ real, intent(out):: ak(km+1), bk(km+1)
+ real, intent(inout):: pint
+ integer, intent(out):: ks
+! Local
+ real, parameter:: p00 = 1.E5
+ real, dimension(km+1):: ze, pe1, peln, eta
+ real, dimension(km):: dz, s_fac, dlnp
+ real ztop, t0, dz0, sum1, tmp1
+ real ep, es, alpha, beta, gama
+!---- Tunable parameters:
+ integer:: k_inc = 25 !< number of layers from bottom up to near const dz region
+ real:: s0 = 0.13 !< lowest layer stretch factor
+!-----------------------
+ real:: s_inc
+ integer k
+
+ pe1(1) = ptop
+ peln(1) = log(pe1(1))
+ pe1(km+1) = p00
+ peln(km+1) = log(pe1(km+1))
+
+ t0 = 270.
+ ztop = rdgas/grav*t0*(peln(km+1) - peln(1))
+
+ s_inc = (1.-s0) / real(k_inc)
+ s_fac(km) = s0
+
+ do k=km-1, km-k_inc, -1
+ s_fac(k) = s_fac(k+1) + s_inc
+ enddo
+
+ do k=km-k_inc-1, 9, -1
+ s_fac(k) = s_rate * s_fac(k+1)
+ enddo
+ s_fac(8) = 0.5*(1.1+s_rate)*s_fac(9)
+ s_fac(7) = 1.10*s_fac(8)
+ s_fac(6) = 1.15*s_fac(7)
+ s_fac(5) = 1.20*s_fac(6)
+ s_fac(4) = 1.26*s_fac(5)
+ s_fac(3) = 1.33*s_fac(4)
+ s_fac(2) = 1.41*s_fac(3)
+ s_fac(1) = 1.60*s_fac(2)
+
+ sum1 = 0.
+ do k=1,km
+ sum1 = sum1 + s_fac(k)
+ enddo
+
+ dz0 = ztop / sum1
+
+ do k=1,km
+ dz(k) = s_fac(k) * dz0
+ enddo
+
+ ze(km+1) = 0.
+ do k=km,1,-1
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+
+! Re-scale dz with the stretched ztop
+ do k=1,km
+ dz(k) = dz(k) * (ztop/ze(1))
+ enddo
+
+ do k=km,1,-1
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+! ze(1) = ztop
+
+ if ( is_master() ) then
+ write(*,*) 'var_gfs: computed model top (m)=', ztop*0.001, ' bottom/top dz=', dz(km), dz(1)
+! do k=1,km
+! write(*,*) k, s_fac(k)
+! enddo
+ endif
+
+! call sm1_edge(1, 1, 1, 1, km, 1, 1, ze, 3)
+
+! Given z --> p
+ do k=1,km
+ dz(k) = ze(k) - ze(k+1)
+ dlnp(k) = grav*dz(k) / (rdgas*t0)
+ enddo
+ do k=2,km
+ peln(k) = peln(k-1) + dlnp(k-1)
+ pe1(k) = exp(peln(k))
+ enddo
+
+! Pe(k) = ak(k) + bk(k) * PS
+! Locate pint and KS
+ ks = 0
+ do k=2,km
+ if ( pint < pe1(k)) then
+ ks = k-1
+ exit
+ endif
+ enddo
+ if ( is_master() ) then
+ write(*,*) 'For (input) PINT=', 0.01*pint, ' KS=', ks, 'pint(computed)=', 0.01*pe1(ks+1)
+ write(*,*) 'ptop =', ptop
+ endif
+ pint = pe1(ks+1)
+
+#ifdef NO_UKMO_HB
+ do k=1,ks+1
+ ak(k) = pe1(k)
+ bk(k) = 0.
+ enddo
+
+ do k=ks+2,km+1
+ bk(k) = (pe1(k) - pint) / (pe1(km+1)-pint) ! bk == sigma
+ ak(k) = pe1(k) - bk(k) * pe1(km+1)
+ enddo
+ bk(km+1) = 1.
+ ak(km+1) = 0.
+#else
+! Problematic for non-hydrostatic
+ do k=1,km+1
+ eta(k) = pe1(k) / pe1(km+1)
+ enddo
+
+ ep = eta(ks+1)
+ es = eta(km)
+! es = 1.
+ alpha = (ep**2-2.*ep*es) / (es-ep)**2
+ beta = 2.*ep*es**2 / (es-ep)**2
+ gama = -(ep*es)**2 / (es-ep)**2
+
+! Pure pressure:
+ do k=1,ks+1
+ ak(k) = eta(k)*1.e5
+ bk(k) = 0.
+ enddo
+
+ do k=ks+2, km
+ ak(k) = alpha*eta(k) + beta + gama/eta(k)
+ ak(k) = ak(k)*1.e5
+ enddo
+ ak(km+1) = 0.
+
+ do k=ks+2, km
+ bk(k) = (pe1(k) - ak(k))/pe1(km+1)
+ enddo
+ bk(km+1) = 1.
+#endif
+
+ if ( is_master() ) then
+ write(*,*) 'KS=', ks, 'PINT (mb)=', pint/100.
+ do k=1,km
+ write(*,*) k, 0.5*(pe1(k)+pe1(k+1))/100., dz(k)
+ enddo
+ tmp1 = ak(ks+1)
+ do k=ks+1,km
+ tmp1 = max(tmp1, (ak(k)-ak(k+1))/max(1.E-5, (bk(k+1)-bk(k))) )
+ enddo
+ write(*,*) 'Hybrid Sigma-P: minimum allowable surface pressure (hpa)=', tmp1/100.
+ endif
+
+ end subroutine var_gfs
+
+ subroutine var_hi(km, ak, bk, ptop, ks, pint, s_rate)
+ integer, intent(in):: km
+ real, intent(in):: ptop
+ real, intent(in):: s_rate !< between [1. 1.1]
+ real, intent(out):: ak(km+1), bk(km+1)
+ real, intent(inout):: pint
+ integer, intent(out):: ks
+! Local
+ real, parameter:: p00 = 1.E5
+ real, dimension(km+1):: ze, pe1, peln, eta
+ real, dimension(km):: dz, s_fac, dlnp
+ real ztop, t0, dz0, sum1, tmp1
+ real ep, es, alpha, beta, gama
+!---- Tunable parameters:
+ integer:: k_inc = 15 !@brief The subroutine 'get_eta_level' returns the interface and
+!! layer-mean pressures for reference.
+ subroutine get_eta_level(npz, p_s, pf, ph, ak, bk, pscale)
+ integer, intent(in) :: npz
+ real, intent(in) :: p_s !< unit: pascal
+ real, intent(in) :: ak(npz+1)
+ real, intent(in) :: bk(npz+1)
+ real, intent(in), optional :: pscale
+ real, intent(out) :: pf(npz)
+ real, intent(out) :: ph(npz+1)
+ integer k
+
+ ph(1) = ak(1)
+ do k=2,npz+1
+ ph(k) = ak(k) + bk(k)*p_s
+ enddo
+
+ if ( present(pscale) ) then
+ do k=1,npz+1
+ ph(k) = pscale*ph(k)
+ enddo
+ endif
+
+ if( ak(1) > 1.E-8 ) then
+ pf(1) = (ph(2) - ph(1)) / log(ph(2)/ph(1))
+ else
+ pf(1) = (ph(2) - ph(1)) * kappa/(kappa+1.)
+ endif
+
+ do k=2,npz
+ pf(k) = (ph(k+1) - ph(k)) / log(ph(k+1)/ph(k))
+ enddo
+
+ end subroutine get_eta_level
+
+
+
+ subroutine compute_dz(km, ztop, dz)
+
+ integer, intent(in):: km
+ real, intent(in):: ztop ! try 50.E3
+ real, intent(out):: dz(km)
+!------------------------------
+ real ze(km+1), dzt(km)
+ integer k
+
+
+! ztop = 30.E3
+ dz(1) = ztop / real(km)
+ dz(km) = 0.5*dz(1)
+
+ do k=2,km-1
+ dz(k) = dz(1)
+ enddo
+
+! Top:
+ dz(1) = 2.*dz(2)
+
+ ze(km+1) = 0.
+ do k=km,1,-1
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+
+ if ( is_master() ) then
+ write(*,*) 'Hybrid_z: dz, zm'
+ do k=1,km
+ dzt(k) = 0.5*(ze(k)+ze(k+1)) / 1000.
+ write(*,*) k, dz(k), dzt(k)
+ enddo
+ endif
+
+ end subroutine compute_dz
+
+ subroutine compute_dz_var(km, ztop, dz)
+
+ integer, intent(in):: km
+ real, intent(in):: ztop ! try 50.E3
+ real, intent(out):: dz(km)
+!------------------------------
+ real, parameter:: s_rate = 1.0
+ real ze(km+1)
+ real s_fac(km)
+ real sum1, dz0
+ integer k
+
+ s_fac(km ) = 0.125
+ s_fac(km-1) = 0.20
+ s_fac(km-2) = 0.30
+ s_fac(km-3) = 0.40
+ s_fac(km-4) = 0.50
+ s_fac(km-5) = 0.60
+ s_fac(km-6) = 0.70
+ s_fac(km-7) = 0.80
+ s_fac(km-8) = 0.90
+ s_fac(km-9) = 1.
+
+ do k=km-10, 9, -1
+ s_fac(k) = s_rate * s_fac(k+1)
+ enddo
+
+ s_fac(8) = 1.05*s_fac(9)
+ s_fac(7) = 1.1 *s_fac(8)
+ s_fac(6) = 1.15*s_fac(7)
+ s_fac(5) = 1.2 *s_fac(6)
+ s_fac(4) = 1.3 *s_fac(5)
+ s_fac(3) = 1.4 *s_fac(4)
+ s_fac(2) = 1.5 *s_fac(3)
+ s_fac(1) = 1.6 *s_fac(2)
+
+ sum1 = 0.
+ do k=1,km
+ sum1 = sum1 + s_fac(k)
+ enddo
+
+ dz0 = ztop / sum1
+
+ do k=1,km
+ dz(k) = s_fac(k) * dz0
+ enddo
+
+ ze(1) = ztop
+ ze(km+1) = 0.
+ do k=km,2,-1
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+
+! Re-scale dz with the stretched ztop
+ do k=1,km
+ dz(k) = dz(k) * (ztop/ze(1))
+ enddo
+
+ do k=km,2,-1
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+
+ call sm1_edge(1, 1, 1, 1, km, 1, 1, ze, 2)
+
+ do k=1,km
+ dz(k) = ze(k) - ze(k+1)
+ enddo
+
+ end subroutine compute_dz_var
+
+ subroutine compute_dz_L32(km, ztop, dz)
+
+ integer, intent(in):: km
+ real, intent(out):: dz(km)
+ real, intent(out):: ztop ! try 50.E3
+!------------------------------
+ real dzt(km)
+ real ze(km+1)
+ real dz0, dz1, dz2
+ real z0, z1, z2
+ integer k, k0, k1, k2, n
+
+!-------------------
+ k2 = 8
+ z2 = 30.E3
+!-------------------
+ k1 = 21
+ z1 = 10.0E3
+!-------------------
+ k0 = 2
+ z0 = 0.
+ dz0 = 75. ! meters
+!-------------------
+! Treat the surface layer as a special layer
+ ze(1) = z0
+ dz(1) = dz0
+
+ ze(2) = dz(1)
+ dz0 = 1.5*dz0
+ dz(2) = dz0
+
+ ze(3) = ze(2) + dz(2)
+
+ dz1 = 2.*(z1-ze(3) - k1*dz0) / (k1*(k1-1))
+
+ do k=k0+1,k0+k1
+ dz(k) = dz0 + (k-k0)*dz1
+ ze(k+1) = ze(k) + dz(k)
+ enddo
+
+ dz0 = dz(k1+k0)
+ dz2 = 2.*(z2-ze(k0+k1+1)-k2*dz0) / (k2*(k2-1))
+
+ do k=k0+k1+1,k0+k1+k2
+ dz(k) = dz0 + (k-k0-k1)*dz2
+ ze(k+1) = ze(k) + dz(k)
+ enddo
+
+ dz(km) = 2.*dz(km-1)
+ ztop = ze(km) + dz(km)
+ ze(km+1) = ze(km) + dz(km)
+
+ call zflip (dz, 1, km)
+
+ ze(km+1) = 0.
+ do k=km,1,-1
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+
+! if ( is_master() ) then
+! write(*,*) 'Hybrid_z: dz, zm'
+! do k=1,km
+! dzt(k) = 0.5*(ze(k)+ze(k+1)) / 1000.
+! write(*,*) k, dz(k), dzt(k)
+! enddo
+! endif
+
+ end subroutine compute_dz_L32
+
+ subroutine compute_dz_L101(km, ztop, dz)
+
+ integer, intent(in):: km ! km==101
+ real, intent(out):: dz(km)
+ real, intent(out):: ztop ! try 30.E3
+!------------------------------
+ real ze(km+1)
+ real dz0, dz1
+ real:: stretch_f = 1.16
+ integer k, k0, k1
+
+ k1 = 2
+ k0 = 25
+ dz0 = 40. ! meters
+
+ ze(km+1) = 0.
+
+ do k=km, k0, -1
+ dz(k) = dz0
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+
+ do k=k0+1, k1, -1
+ dz(k) = stretch_f * dz(k+1)
+ ze(k) = ze(k+1) + dz(k)
+ enddo
+
+ dz(1) = 4.0*dz(2)
+ ze(1) = ze(2) + dz(1)
+ ztop = ze(1)
+
+ if ( is_master() ) then
+ write(*,*) 'Hybrid_z: dz, ze'
+ do k=1,km
+ write(*,*) k, 0.001*dz(k), 0.001*ze(k)
+ enddo
+! ztop (km) = 20.2859154
+ write(*,*) 'ztop (km) =', ztop * 0.001
+ endif
+
+ end subroutine compute_dz_L101
+
+ subroutine set_hybrid_z(is, ie, js, je, ng, km, ztop, dz, rgrav, hs, ze, dz3)
+
+ integer, intent(in):: is, ie, js, je, ng, km
+ real, intent(in):: rgrav, ztop
+ real, intent(in):: dz(km) !< Reference vertical resolution for zs=0
+ real, intent(in):: hs(is-ng:ie+ng,js-ng:je+ng)
+ real, intent(inout):: ze(is:ie,js:je,km+1)
+ real, optional, intent(out):: dz3(is-ng:ie+ng,js-ng:je+ng,km)
+! local
+ logical:: filter_xy = .false.
+ real, allocatable:: delz(:,:,:)
+ integer ntimes
+ real zint
+ real:: z1(is:ie,js:je)
+ real:: z(km+1)
+ real sig, z_rat
+ integer ks(is:ie,js:je)
+ integer i, j, k, ks_min, kint
+
+ z(km+1) = 0.
+ do k=km,1,-1
+ z(k) = z(k+1) + dz(k)
+ enddo
+
+ do j=js,je
+ do i=is,ie
+ ze(i,j, 1) = ztop
+ ze(i,j,km+1) = hs(i,j) * rgrav
+ enddo
+ enddo
+
+ do k=2,km
+ do j=js,je
+ do i=is,ie
+ ze(i,j,k) = z(k)
+ enddo
+ enddo
+ enddo
+
+! Set interface:
+#ifndef USE_VAR_ZINT
+ zint = 12.0E3
+ ntimes = 2
+ kint = 2
+ do k=2,km
+ if ( z(k)<=zint ) then
+ kint = k
+ exit
+ endif
+ enddo
+
+ if ( is_master() ) write(*,*) 'Z_coord interface set at k=',kint, ' ZE=', z(kint)
+
+ do j=js,je
+ do i=is,ie
+ z_rat = (ze(i,j,kint)-ze(i,j,km+1)) / (z(kint)-z(km+1))
+ do k=km,kint+1,-1
+ ze(i,j,k) = ze(i,j,k+1) + dz(k)*z_rat
+ enddo
+!--------------------------------------
+! Apply vertical smoother locally to dz
+!--------------------------------------
+ call sm1_edge(is, ie, js, je, km, i, j, ze, ntimes)
+ enddo
+ enddo
+#else
+! ZINT is a function of local terrain
+ ntimes = 4
+ do j=js,je
+ do i=is,ie
+ z1(i,j) = dim(ze(i,j,km+1), 2500.) + 7500.
+ enddo
+ enddo
+
+ ks_min = km
+ do j=js,je
+ do i=is,ie
+ do k=km,2,-1
+ if ( z(k)>=z1(i,j) ) then
+ ks(i,j) = k
+ ks_min = min(ks_min, k)
+ go to 555
+ endif
+ enddo
+555 continue
+ enddo
+ enddo
+
+ do j=js,je
+ do i=is,ie
+ kint = ks(i,j) + 1
+ z_rat = (ze(i,j,kint)-ze(i,j,km+1)) / (z(kint)-z(km+1))
+ do k=km,kint+1,-1
+ ze(i,j,k) = ze(i,j,k+1) + dz(k)*z_rat
+ enddo
+!--------------------------------------
+! Apply vertical smoother locally to dz
+!--------------------------------------
+ call sm1_edge(is, ie, js, je, km, i, j, ze, ntimes)
+ enddo
+ enddo
+#endif
+
+#ifdef DEV_ETA
+ if ( filter_xy ) then
+ allocate (delz(isd:ied, jsd:jed, km) )
+ ntimes = 2
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ delz(i,j,k) = ze(i,j,k+1) - ze(i,j,k)
+ enddo
+ enddo
+ enddo
+ call del2_cubed(delz, 0.2*da_min, npx, npy, km, ntimes)
+ do k=km,2,-1
+ do j=js,je
+ do i=is,ie
+ ze(i,j,k) = ze(i,j,k+1) - delz(i,j,k)
+ enddo
+ enddo
+ enddo
+ deallocate ( delz )
+ endif
+#endif
+ if ( present(dz3) ) then
+ do k=1,km
+ do j=js,je
+ do i=is,ie
+ dz3(i,j,k) = ze(i,j,k+1) - ze(i,j,k)
+ enddo
+ enddo
+ enddo
+ endif
+
+ end subroutine set_hybrid_z
+
+
+ subroutine sm1_edge(is, ie, js, je, km, i, j, ze, ntimes)
+ integer, intent(in):: is, ie, js, je, km
+ integer, intent(in):: ntimes, i, j
+ real, intent(inout):: ze(is:ie,js:je,km+1)
+! local:
+ real, parameter:: df = 0.25
+ real dz(km)
+ real flux(km+1)
+ integer k, n, k1, k2
+
+ k2 = km-1
+ do k=1,km
+ dz(k) = ze(i,j,k+1) - ze(i,j,k)
+ enddo
+
+ do n=1,ntimes
+ k1 = 2 + (ntimes-n)
+
+ flux(k1 ) = 0.
+ flux(k2+1) = 0.
+ do k=k1+1,k2
+ flux(k) = df*(dz(k) - dz(k-1))
+ enddo
+
+ do k=k1,k2
+ dz(k) = dz(k) - flux(k) + flux(k+1)
+ enddo
+ enddo
+
+ do k=km,1,-1
+ ze(i,j,k) = ze(i,j,k+1) - dz(k)
+ enddo
+
+ end subroutine sm1_edge
+
+
+
+ subroutine gw_1d(km, p0, ak, bk, ptop, ztop, pt1)
+ integer, intent(in):: km
+ real, intent(in):: p0, ztop
+ real, intent(inout):: ptop
+ real, intent(inout):: ak(km+1), bk(km+1)
+ real, intent(out):: pt1(km)
+! Local
+ logical:: isothermal
+ real, dimension(km+1):: ze, pe1, pk1
+ real, dimension(km):: dz1
+ real t0, n2, s0
+ integer k
+
+! Set up vertical coordinare with constant del-z spacing:
+ isothermal = .false.
+ t0 = 300.
+
+ if ( isothermal ) then
+ n2 = grav**2/(cp_air*t0)
+ else
+ n2 = 0.0001
+ endif
+
+ s0 = grav*grav / (cp_air*n2)
+
+ ze(km+1) = 0.
+ do k=km,1,-1
+ dz1(k) = ztop / real(km)
+ ze(k) = ze(k+1) + dz1(k)
+ enddo
+
+! Given z --> p
+ do k=1,km+1
+ pe1(k) = p0*( (1.-s0/t0) + s0/t0*exp(-n2*ze(k)/grav) )**(1./kappa)
+ enddo
+
+ ptop = pe1(1)
+! if ( is_master() ) write(*,*) 'GW_1D: computed model top (pa)=', ptop
+
+! Set up "sigma" coordinate
+ ak(1) = pe1(1)
+ bk(1) = 0.
+ do k=2,km
+ bk(k) = (pe1(k) - pe1(1)) / (pe1(km+1)-pe1(1)) ! bk == sigma
+ ak(k) = pe1(1)*(1.-bk(k))
+ enddo
+ ak(km+1) = 0.
+ bk(km+1) = 1.
+
+ do k=1,km+1
+ pk1(k) = pe1(k) ** kappa
+ enddo
+
+! Compute volume mean potential temperature with hydrostatic eqn:
+ do k=1,km
+ pt1(k) = grav*dz1(k) / ( cp_air*(pk1(k+1)-pk1(k)) )
+ enddo
+
+ end subroutine gw_1d
+
+
+
+ subroutine zflip(q, im, km)
+ integer, intent(in):: im, km
+ real, intent(inout):: q(im,km)
+!---
+ integer i, k
+ real qtmp
+
+ do i = 1, im
+ do k = 1, (km+1)/2
+ qtmp = q(i,k)
+ q(i,k) = q(i,km+1-k)
+ q(i,km+1-k) = qtmp
+ end do
+ end do
+
+ end subroutine zflip
+
+end module fv_eta_mod
diff --git a/tools/fv_iau_mod.F90 b/tools/fv_iau_mod.F90
index e9b961cbb..bf2a73ea1 100644
--- a/tools/fv_iau_mod.F90
+++ b/tools/fv_iau_mod.F90
@@ -93,6 +93,7 @@ module fv_iau_mod
real,allocatable :: delz_inc(:,:,:)
real,allocatable :: tracer_inc(:,:,:,:)
logical :: in_interval = .false.
+ logical :: drymassfixer = .false.
end type iau_external_data_type
type iau_state_type
type(iau_internal_data_type):: inc1
@@ -280,6 +281,7 @@ subroutine IAU_initialize (IPD_Control, IAU_Data,Init_parm)
call read_iau_forcing(IPD_Control,iau_state%inc2,'INPUT/'//trim(IPD_Control%iau_inc_files(2)))
endif
! print*,'in IAU init',dt,rdt
+ IAU_data%drymassfixer = IPD_control%iau_drymassfixer
end subroutine IAU_initialize
diff --git a/tools/fv_restart.F90 b/tools/fv_restart.F90
index 1632212ed..fbe46d676 100644
--- a/tools/fv_restart.F90
+++ b/tools/fv_restart.F90
@@ -165,6 +165,7 @@ module fv_restart_mod
use fv_timing_mod, only: timing_on, timing_off
use fms_mod, only: file_exist
use fv_treat_da_inc_mod, only: read_da_inc
+ use fv_regional_mod, only: write_full_fields
#ifdef MULTI_GASES
use multi_gases_mod, only: virq
#endif
@@ -354,7 +355,7 @@ subroutine fv_restart(fv_domain, Atm, dt_atmos, seconds, days, cold_start, grid_
endif
if ( Atm(n)%flagstruct%external_ic ) then
if( is_master() ) write(*,*) 'Calling get_external_ic'
- call get_external_ic(Atm(n:n), Atm(n)%domain, cold_start_grids(n))
+ call get_external_ic(Atm(n:n), Atm(n)%domain, cold_start_grids(n), dt_atmos)
if( is_master() ) write(*,*) 'IC generated from the specified external source'
endif
@@ -1434,9 +1435,10 @@ end subroutine fv_write_restart
!>@brief The subroutine 'fv_restart_end' writes ending restart files,
!! terminates I/O, and prints out diagnostics including global totals
!! and checksums.
- subroutine fv_restart_end(Atm, grids_on_this_pe)
+ subroutine fv_restart_end(Atm, grids_on_this_pe, restart_endfcst)
type(fv_atmos_type), intent(inout) :: Atm(:)
logical, intent(INOUT) :: grids_on_this_pe(:)
+ logical, intent(in) :: restart_endfcst
integer :: isc, iec, jsc, jec
integer :: iq, n, ntileMe, ncnst, ntprog, ntdiag
@@ -1447,7 +1449,6 @@ subroutine fv_restart_end(Atm, grids_on_this_pe)
character(len=128):: tracer_name
character(len=3):: gn
-
ntileMe = size(Atm(:))
do n = 1, ntileMe
@@ -1516,10 +1517,18 @@ subroutine fv_restart_end(Atm, grids_on_this_pe)
enddo
- call fv_io_write_restart(Atm, grids_on_this_pe)
- do n=1,ntileMe
- if (Atm(n)%neststruct%nested .and. grids_on_this_pe(n)) call fv_io_write_BCs(Atm(n))
- end do
+ if ( restart_endfcst ) then
+ call fv_io_write_restart(Atm, grids_on_this_pe)
+! print *,'af call fv_io_write_restart, restart_endfcst=',restart_endfcst
+ do n=1,ntileMe
+ if (Atm(n)%neststruct%nested .and. grids_on_this_pe(n)) call fv_io_write_BCs(Atm(n))
+ end do
+
+ if(Atm(1)%flagstruct%write_restart_with_bcs)then
+ call write_full_fields(Atm)
+ endif
+
+ endif
module_is_initialized = .FALSE.