Line data Source code
1 : module ref_pres
2 : !--------------------------------------------------------------------------
3 : !
4 : ! Provides access to reference pressures for use by the physics
5 : ! parameterizations. The pressures are provided by the dynamical core
6 : ! since it determines the grid used by the physics.
7 : !
8 : ! Note that the init method for this module is called before the init
9 : ! method in physpkg; therefore, most physics modules can use these
10 : ! reference pressures during their init phases.
11 : !
12 : !--------------------------------------------------------------------------
13 :
14 : use shr_kind_mod, only: r8=>shr_kind_r8
15 : use ppgrid, only: pver, pverp
16 :
17 : implicit none
18 : public
19 : save
20 :
21 : ! Reference pressures (Pa)
22 : real(r8), protected :: pref_edge(pverp) ! Layer edges
23 : real(r8), protected :: pref_mid(pver) ! Layer midpoints
24 : real(r8), protected :: pref_mid_norm(pver) ! Layer midpoints normalized by
25 : ! surface pressure ('eta' coordinate)
26 :
27 : real(r8), protected :: ptop_ref ! Top of model
28 : real(r8), protected :: psurf_ref ! reference pressure
29 :
30 : ! Number of top levels using pure pressure representation
31 : integer, protected :: num_pr_lev
32 :
33 : ! Pressure used to set troposphere cloud physics top (Pa)
34 : real(r8), protected :: trop_cloud_top_press = 0._r8
35 : ! Top level for troposphere cloud physics
36 : integer, protected :: trop_cloud_top_lev
37 :
38 : ! Pressure used to set MAM process top (Pa)
39 : real(r8), protected :: clim_modal_aero_top_press = 0._r8
40 : ! Top level for MAM processes that impact climate
41 : integer, protected :: clim_modal_aero_top_lev
42 :
43 : ! Molecular diffusion is calculated only if the model top is below this
44 : ! pressure (Pa).
45 : real(r8), protected :: do_molec_press = 0.1_r8
46 : ! Pressure used to set bottom of molecular diffusion region (Pa).
47 : real(r8), protected :: molec_diff_bot_press = 50._r8
48 : ! Flag for molecular diffusion, and molecular diffusion level index.
49 : logical, protected :: do_molec_diff = .false.
50 : integer, protected :: nbot_molec = 0
51 :
52 : !====================================================================================
53 : contains
54 : !====================================================================================
55 :
56 1536 : subroutine ref_pres_readnl(nlfile)
57 :
58 : use spmd_utils, only: masterproc
59 : use cam_abortutils, only: endrun
60 : use namelist_utils, only: find_group_name
61 : use units, only: getunit, freeunit
62 : use mpishorthand
63 :
64 : character(len=*), intent(in) :: nlfile ! filepath for file containing namelist input
65 :
66 : ! Local variables
67 : integer :: unitn, ierr
68 : character(len=*), parameter :: subname = 'ref_pres_readnl'
69 :
70 : namelist /ref_pres_nl/ trop_cloud_top_press, clim_modal_aero_top_press,&
71 : do_molec_press, molec_diff_bot_press
72 : !-----------------------------------------------------------------------------
73 :
74 1536 : if (masterproc) then
75 2 : unitn = getunit()
76 2 : open( unitn, file=trim(nlfile), status='old' )
77 2 : call find_group_name(unitn, 'ref_pres_nl', status=ierr)
78 2 : if (ierr == 0) then
79 2 : read(unitn, ref_pres_nl, iostat=ierr)
80 2 : if (ierr /= 0) then
81 0 : call endrun(subname // ':: ERROR reading namelist')
82 : end if
83 : end if
84 2 : close(unitn)
85 2 : call freeunit(unitn)
86 :
87 : ! Check that top for modal aerosols is not lower than
88 : ! top for clouds.
89 2 : if (clim_modal_aero_top_press > trop_cloud_top_press) &
90 : call endrun("ERROR: clim_modal_aero_top press must be less &
91 0 : &than or equal to trop_cloud_top_press.")
92 : end if
93 :
94 : #ifdef SPMD
95 : ! Broadcast namelist variables
96 1536 : call mpibcast(trop_cloud_top_press, 1 , mpir8, 0, mpicom)
97 1536 : call mpibcast(clim_modal_aero_top_press, 1 , mpir8, 0, mpicom)
98 1536 : call mpibcast(do_molec_press, 1 , mpir8, 0, mpicom)
99 1536 : call mpibcast(molec_diff_bot_press, 1 , mpir8, 0, mpicom)
100 : #endif
101 :
102 1536 : end subroutine ref_pres_readnl
103 :
104 : !====================================================================================
105 :
106 1536 : subroutine ref_pres_init(pref_edge_in, pref_mid_in, num_pr_lev_in)
107 :
108 : ! Initialize reference pressures
109 :
110 : ! arguments
111 : real(r8), intent(in) :: pref_edge_in(:) ! reference pressure at layer edges (Pa)
112 : real(r8), intent(in) :: pref_mid_in(:) ! reference pressure at layer midpoints (Pa)
113 : integer, intent(in) :: num_pr_lev_in ! number of top levels using pure pressure representation
114 : !---------------------------------------------------------------------------
115 :
116 145920 : pref_edge = pref_edge_in
117 144384 : pref_mid = pref_mid_in
118 1536 : num_pr_lev = num_pr_lev_in
119 :
120 1536 : ptop_ref = pref_edge(1)
121 1536 : psurf_ref = pref_edge(pverp)
122 :
123 144384 : pref_mid_norm = pref_mid/psurf_ref
124 :
125 : ! Find level corresponding to the top of troposphere clouds.
126 : trop_cloud_top_lev = press_lim_idx(trop_cloud_top_press, &
127 1536 : top=.true.)
128 :
129 : ! Find level corresponding to the top for MAM processes.
130 : clim_modal_aero_top_lev = press_lim_idx(clim_modal_aero_top_press, &
131 1536 : top=.true.)
132 :
133 : ! Find level corresponding to the molecular diffusion bottom.
134 1536 : do_molec_diff = (ptop_ref < do_molec_press)
135 1536 : if (do_molec_diff) then
136 : nbot_molec = press_lim_idx(molec_diff_bot_press, &
137 0 : top=.false.)
138 : end if
139 :
140 1536 : end subroutine ref_pres_init
141 :
142 : !====================================================================================
143 :
144 : ! Convert pressure limiters to the appropriate level.
145 3072 : pure function press_lim_idx(p, top) result(k_lim)
146 : ! Pressure
147 : real(r8), intent(in) :: p
148 : ! Is this a top or bottom limit?
149 : logical, intent(in) :: top
150 : integer :: k_lim, k
151 :
152 3072 : if (top) then
153 16896 : k_lim = pver+1
154 16896 : do k = 1, pver
155 16896 : if (pref_mid(k) > p) then
156 : k_lim = k
157 : exit
158 : end if
159 : end do
160 : else
161 0 : k_lim = 0
162 0 : do k = pver, 1, -1
163 0 : if (pref_mid(k) < p) then
164 : k_lim = k
165 : exit
166 : end if
167 : end do
168 : end if
169 :
170 3072 : end function press_lim_idx
171 :
172 : !====================================================================================
173 :
174 : end module ref_pres
|