FV3DYCORE  Version 2.0.0
multi_gases.F90
Go to the documentation of this file.
1 !***********************************************************************
2 !* GNU Lesser General Public License
3 !*
4 !* This file is part of the FV3 dynamical core.
5 !*
6 !* The FV3 dynamical core is free software: you can redistribute it
7 !* and/or modify it under the terms of the
8 !* GNU Lesser General Public License as published by the
9 !* Free Software Foundation, either version 3 of the License, or
10 !* (at your option) any later version.
11 !*
12 !* The FV3 dynamical core is distributed in the hope that it will be
13 !* useful, but WITHOUT ANYWARRANTY; without even the implied warranty
14 !* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 !* See the GNU General Public License for more details.
16 !*
17 !* You should have received a copy of the GNU Lesser General Public
18 !* License along with the FV3 dynamical core.
19 !* If not, see <http://www.gnu.org/licenses/>.
20 !***********************************************************************
21 
24 
26 
27 ! Modules Included:
28 ! <table>
29 ! <tr>
30 ! <th>Module Name</th>
31 ! <th>Functions Included</th>
32 ! </tr>
33 ! <tr>
34 ! <td>constants_mod</td>
35 ! <td>rdgas, cp_air</td>
36 ! </tr>
37 ! </table>
38 
39  use constants_mod, only: rdgas, rvgas, cp_air
40  use fv_mp_mod, only: is_master
41  use mpp_mod, only: stdlog, input_nml_file
42  use fms_mod, only: check_nml_error, open_namelist_file, close_file
43 
44 
45  implicit none
46  integer num_gas
47  integer ind_gas
48  integer num_wat
49  integer sphum, sphump1
50  real, allocatable :: ri(:)
51  real, allocatable :: cpi(:)
52  real, allocatable :: vir(:)
53  real, allocatable :: vicp(:)
54  real, allocatable :: vicv(:)
55 
56  private num_wat, sphum, sphump1
57  public vir, vicp, vicv, ind_gas, num_gas
59  public virq
60  public virq_max
61  public virqd
62  public vicpqd
63  public virq_nodq
64  public virq_qpz
65  public vicpqd_qpz
66  public vicvqd
67  public vicvqd_qpz
68 
69  CONTAINS
70 ! --------------------------------------------------------
71  subroutine multi_gases_init(ngas, nwat)
72 !--------------------------------------------
73 ! !OUTPUT PARAMETERS
74 ! Ouput: vir(i): ri/rdgas - r0/rdgas
75 ! vir(0): r0/rdgas
76 ! vicp(i): cpi/cp_air - cp0/cp_air
77 ! vicp(0): cp0/cp_air
78 ! cv_air = cp_air - rdgas
79 ! vicv(i): cvi/cv_air - cv0/cv_air
80 ! vicv(0): cv0/cv_air
81 !--------------------------------------------
82  integer, intent(in):: ngas, nwat
83 ! Local:
84  integer n
85  real cvi(0:ngas)
86  real cv_air
87  logical :: default_gas=.false.
88 
89  sphum = 1
90  sphump1 = sphum+1
91  num_wat = nwat
92  ind_gas = num_wat+1
93  do n=0,ngas
94  if( ri(n).ne.0.0 .or. cpi(n).ne.0.0 ) num_gas=n
95  enddo
96  if ( num_gas.eq.1 ) default_gas=.true.
97  allocate( vir(0:num_gas) )
98  allocate( vicp(0:num_gas) )
99  allocate( vicv(0:num_gas) )
100 
101  cv_air = cp_air - rdgas
102  do n=0,num_gas
103  cvi(n) = cpi(n) - ri(n)
104  enddo
105 
106  vir(0) = ri(0)/rdgas
107  vicp(0) = cpi(0)/cp_air
108  vicv(0) = cvi(0)/cv_air
109  if( default_gas ) then
110  vir(0) = 1.0
111  vicp(0) = 1.0
112  vicv(0) = 1.0
113  endif
114  do n=1,num_gas
115  vir(n) = 0.0
116  if( ri(n).gt.0.0 ) vir(n) = ri(n)/rdgas - vir(0)
117  vicp(n) = 0.0
118  if( cpi(n).gt.0.0 ) vicp(n) = cpi(n)/cp_air - vicp(0)
119  vicv(n) = 0.0
120  if( cvi(n).gt.0.0 ) vicv(n) = cvi(n)/cv_air - vicv(0)
121  enddo
122 
123  if( is_master() ) then
124  write(*,*) ' multi_gases_init with ind_gas=',ind_gas
125  write(*,*) ' multi_gases_init with num_gas=',num_gas
126  write(*,*) ' multi_gases_init with vir =',vir
127  write(*,*) ' multi_gases_init with vicp=',vicp
128  write(*,*) ' multi_gases_init with vicv=',vicv
129  endif
130 
131  return
132  end subroutine multi_gases_init
133  subroutine read_namelist_multi_gases_nml(nml_filename,ncnst,nwat)
135  character(*), intent(IN) :: nml_filename
136  integer, intent(IN) :: ncnst, nwat
137  integer :: ierr, f_unit, unit, ios
138 
139  namelist /multi_gases_nml/ ri,cpi
140 
141  unit = stdlog()
142 
143  allocate (ri(0:ncnst))
144  allocate (cpi(0:ncnst))
145 
146  ri = 0.0
147  cpi = 0.0
148  ri(0) = rdgas
149  ri(1) = rvgas
150  cpi(0) = cp_air
151  cpi(1) = 4*cp_air
152 #ifdef INTERNAL_FILE_NML
153 
154  ! Read multi_gases namelist
155  read (input_nml_file,multi_gases_nml,iostat=ios)
156  ierr = check_nml_error(ios,'multi_gases_nml')
157 
158 #else
159  ! Read multi_gases namelist
160  f_unit = open_namelist_file(nml_filename)
161 
162  rewind(f_unit)
163  read (f_unit,multi_gases_nml,iostat=ios)
164  ierr = check_nml_error(ios,'multi_gases_nml')
165  call close_file(f_unit)
166 #endif
167  write(unit, nml=multi_gases_nml)
168  call multi_gases_init(ncnst,nwat)
169 
170  return
171  end subroutine read_namelist_multi_gases_nml
172 
173 
174 ! ----------------------------------------------------------------
175 
176 ! --------------------------------------------------------
177  pure real function virq(q)
178 !--------------------------------------------
179 ! !OUTPUT PARAMETERS
180 ! Ouput: variable gas 1+zvir/(1-qc)
181 !--------------------------------------------
182  real, intent(in) :: q(num_gas)
183 ! Local:
184  integer :: n
185 
186  virq = vir(sphum)*q(sphum)
187  do n=ind_gas,num_gas
188  virq = virq+vir(n)*q(sphum+n-1)
189  end do
190  virq = vir(0)+virq/(1.0-sum(q(sphump1:sphum+num_wat-1)))
191 
192  return
193  end function
194 !--------------------------------------------
195 
196 ! --------------------------------------------------------
197  pure real function virq_nodq(q)
198 !--------------------------------------------
199 ! !OUTPUT PARAMETERS
200 ! Ouput: variable gas 1+zvir without dividing by 1-qv or 1-qv-qc
201 !--------------------------------------------
202  real, intent(in) :: q(num_gas)
203 ! Local:
204  integer :: n
205 
206  virq_nodq = vir(0)+vir(sphum)*q(sphum)
207  do n=ind_gas,num_gas
208  virq_nodq = virq_nodq+vir(n)*q(sphum+n-1)
209  end do
210 
211  return
212  end function
213 !--------------------------------------------
214 
215 ! --------------------------------------------------------
216  pure real function virq_max(q, qmin)
217 !--------------------------------------------
218 ! !OUTPUT PARAMETERS
219 ! Ouput: variable gas 1+zvir using max(qmin,q(sphum))
220 !--------------------------------------------
221  real, intent(in) :: q(num_gas)
222  real, intent(in) :: qmin
223 ! Local:
224  integer :: n
225 
226  virq_max = vir(sphum)*max(qmin,q(sphum))
227  do n=ind_gas,num_gas
228  virq_max = virq_max+vir(n)*q(sphum+n-1)
229  end do
230  virq_max = vir(0)+virq_max/(1.0-sum(q(sphump1:sphum+num_wat-1)))
231 
232 
233  return
234  end function
235 !--------------------------------------------
236 
237 ! --------------------------------------------------------
238  pure real function virq_qpz(q, qpz)
239 !--------------------------------------------
240 ! !OUTPUT PARAMETERS
241 ! Ouput: variable gas 1+zvir/(1.-qpz): qpz in place of qv+qc from q
242 !--------------------------------------------
243  real, intent(in) :: q(num_gas)
244  real, intent(in) :: qpz
245 ! Local:
246  integer :: n
247 
248  virq_qpz = vir(sphum)*q(sphum)
249  do n=ind_gas,num_gas
250  virq_qpz = virq_qpz+vir(n)*q(sphum+n-1)
251  end do
252  virq_qpz = vir(0)+virq_qpz/(1.0-qpz)
253 
254 
255  return
256  end function
257 !--------------------------------------------
258 
259 ! --------------------------------------------------------
260  pure real function virqd(q)
261 !--------------------------------------------
262 ! !OUTPUT PARAMETERS
263 ! Ouput: variable gas 1+zvir/(1-(qv+qc)) (dry)
264 !--------------------------------------------
265  real, intent(in) :: q(num_gas)
266 ! Local:
267  integer :: n
268 
269  virqd = 0.0
270  do n=ind_gas,num_gas
271  virqd = virqd+vir(n)*q(sphum+n-1)
272  end do
273  virqd = vir(0)+virqd/(1.0-sum(q(sphum:sphum+num_wat-1)))
274 
275  return
276  end function
277 !--------------------------------------------
278 
279 ! --------------------------------------------------------
280  pure real function vicpqd(q)
281 !--------------------------------------------
282 ! !OUTPUT PARAMETERS
283 ! Ouput: variable gas cp (dry)
284 !--------------------------------------------
285  real, intent(in) :: q(num_gas)
286 ! Local:
287  integer :: n
288 
289  vicpqd = 0.0
290  do n=ind_gas,num_gas
291  vicpqd = vicpqd+vicp(n)*q(sphum+n-1)
292  end do
293  vicpqd = vicp(0)+vicpqd/(1.0-sum(q(sphum:sphum+num_wat-1)))
294 
295  return
296  end function
297 !--------------------------------------------
298 
299 ! --------------------------------------------------------
300  pure real function vicpqd_qpz(q, qpz)
301 !--------------------------------------------
302 ! !OUTPUT PARAMETERS
303 ! Ouput: variable gas cp (dry) with qpz in place of qv+qc from q
304 !--------------------------------------------
305  real, intent(in) :: q(num_gas)
306  real, intent(in) :: qpz
307 ! Local:
308  integer :: n
309 
310  vicpqd_qpz = 0.0
311  do n=ind_gas,num_gas
312  vicpqd_qpz = vicpqd_qpz+vicp(n)*q(sphum+n-1)
313  end do
314  vicpqd_qpz = vicp(0)+vicpqd_qpz/(1.0-qpz)
315 
316  return
317  end function
318 !--------------------------------------------
319 
320 ! --------------------------------------------------------
321  pure real function vicvqd(q)
322 !--------------------------------------------
323 ! !OUTPUT PARAMETERS
324 ! Ouput: variable gas cv (dry)
325 !--------------------------------------------
326  real, intent(in) :: q(num_gas)
327 ! Local:
328  integer :: n
329 
330  vicvqd = 0.0
331  do n=ind_gas,num_gas
332  vicvqd = vicvqd+vicv(n)*q(sphum+n-1)
333  end do
334  vicvqd = vicv(0)+vicvqd/(1.0-sum(q(sphum:sphum+num_wat-1)))
335 
336  return
337  end function
338 !--------------------------------------------
339 
340 ! --------------------------------------------------------
341  pure real function vicvqd_qpz(q,qpz)
342 !--------------------------------------------
343 ! !OUTPUT PARAMETERS
344 ! Ouput: variable gas cv (dry) with qpz in place of qv+qc from q
345 !--------------------------------------------
346  real, intent(in) :: q(num_gas)
347  real, intent(in) :: qpz
348 ! Local:
349  integer :: n
350 
351  vicvqd_qpz = 0.0
352  do n=ind_gas,num_gas
353  vicvqd_qpz = vicvqd_qpz+vicv(n)*q(sphum+n-1)
354  end do
355  vicvqd_qpz = vicv(0)+vicvqd_qpz/(1.0-qpz)
356 
357  return
358  end function
359 !--------------------------------------------
360 
361 end module multi_gases_mod
real, dimension(:), allocatable, public vir
Definition: multi_gases.F90:52
pure real function, public vicpqd(q)
The module &#39;fv_mp_mod&#39; is a single program multiple data (SPMD) parallel decompostion/communication m...
Definition: fv_mp_mod.F90:24
integer, public num_gas
Definition: multi_gases.F90:46
The module &#39;multi_gases&#39; peforms multi constitutents computations.
Definition: multi_gases.F90:25
pure real function, public vicvqd_qpz(q, qpz)
pure real function, public virq_max(q, qmin)
subroutine, public read_namelist_multi_gases_nml(nml_filename, ncnst, nwat)
pure real function, public virq_qpz(q, qpz)
real, dimension(:), allocatable ri
Definition: multi_gases.F90:50
pure real function, public virqd(q)
pure real function, public virq_nodq(q)
pure real function, public virq(q)
integer, public ind_gas
Definition: multi_gases.F90:47
integer, private sphum
Definition: multi_gases.F90:49
integer, private num_wat
Definition: multi_gases.F90:48
subroutine, public multi_gases_init(ngas, nwat)
Definition: multi_gases.F90:72
real, dimension(:), allocatable cpi
Definition: multi_gases.F90:51
real, dimension(:), allocatable, public vicv
Definition: multi_gases.F90:54
real, dimension(:), allocatable, public vicp
Definition: multi_gases.F90:53
pure real function, public vicpqd_qpz(q, qpz)
pure real function, public vicvqd(q)
integer, private sphump1
Definition: multi_gases.F90:49