SCALE-RM
scale_atmos_sub_thermodyn.F90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
16 !-------------------------------------------------------------------------------
17 #include "macro_thermodyn.h"
18 #include "inc_openmp.h"
20  !-----------------------------------------------------------------------------
21  !
22  !++ used modules
23  !
24  use scale_precision
25  use scale_stdio
26  use scale_prof
28  use scale_tracer
29 
30  use scale_const, only: &
31  eps => const_eps, &
32  rdry => const_rdry, &
33  cpdry => const_cpdry, &
34  cpvap => const_cpvap, &
35  cvdry => const_cvdry, &
36  cl => const_cl, &
37  ci => const_ci, &
38  rvap => const_rvap, &
39  lhv0 => const_lhv0, &
40  lhs0 => const_lhs0, &
41  lhf0 => const_lhf0, &
42  psat0 => const_psat0, &
43  pre00 => const_pre00, &
44  tem00 => const_tem00
45  !-----------------------------------------------------------------------------
46  implicit none
47  private
48 
49  !-----------------------------------------------------------------------------
50  !
51  !++ Public procedure
52  !
53  public :: atmos_thermodyn_setup
54 
55  public :: atmos_thermodyn_qd
56  public :: atmos_thermodyn_cv
57  public :: atmos_thermodyn_cp
58  public :: atmos_thermodyn_pott
59  public :: atmos_thermodyn_rhoe
60  public :: atmos_thermodyn_rhot
61  public :: atmos_thermodyn_temp_pres
62  public :: atmos_thermodyn_temp_pres_e
63  public :: atmos_thermodyn_templhv
64  public :: atmos_thermodyn_templhs
65  public :: atmos_thermodyn_templhf
66  public :: atmos_thermodyn_entr
67 
68  interface atmos_thermodyn_qd
69  module procedure atmos_thermodyn_qd_0d
70  module procedure atmos_thermodyn_qd_3d
71  end interface atmos_thermodyn_qd
72 
73  interface atmos_thermodyn_cp
74  module procedure atmos_thermodyn_cp_0d
75  module procedure atmos_thermodyn_cp_3d
76  end interface atmos_thermodyn_cp
77 
78  interface atmos_thermodyn_cv
79  module procedure atmos_thermodyn_cv_0d
80  module procedure atmos_thermodyn_cv_3d
81  end interface atmos_thermodyn_cv
82 
83  interface atmos_thermodyn_rhoe
84  module procedure atmos_thermodyn_rhoe_0d
85  module procedure atmos_thermodyn_rhoe_3d
86  end interface atmos_thermodyn_rhoe
87 
88  interface atmos_thermodyn_rhot
89  module procedure atmos_thermodyn_rhot_0d
90  module procedure atmos_thermodyn_rhot_3d
91  end interface atmos_thermodyn_rhot
92 
93  interface atmos_thermodyn_pott
94  module procedure atmos_thermodyn_pott_0d
95  module procedure atmos_thermodyn_pott_3d
96  end interface atmos_thermodyn_pott
97 
98  interface atmos_thermodyn_temp_pres
99  module procedure atmos_thermodyn_temp_pres_0d
100  module procedure atmos_thermodyn_temp_pres_3d
101  end interface atmos_thermodyn_temp_pres
102 
103  interface atmos_thermodyn_temp_pres_e
104  module procedure atmos_thermodyn_temp_pres_e_0d
105  module procedure atmos_thermodyn_temp_pres_e_3d
106  end interface atmos_thermodyn_temp_pres_e
107 
108  interface atmos_thermodyn_templhv
109  module procedure atmos_thermodyn_templhv_0d
110  module procedure atmos_thermodyn_templhv_2d
111  module procedure atmos_thermodyn_templhv_3d
112  end interface atmos_thermodyn_templhv
113 
114  interface atmos_thermodyn_templhs
115  module procedure atmos_thermodyn_templhs_0d
116  module procedure atmos_thermodyn_templhs_2d
117  module procedure atmos_thermodyn_templhs_3d
118  end interface atmos_thermodyn_templhs
119 
120  interface atmos_thermodyn_templhf
121  module procedure atmos_thermodyn_templhf_0d
122  module procedure atmos_thermodyn_templhf_2d
123  module procedure atmos_thermodyn_templhf_3d
124  end interface atmos_thermodyn_templhf
125 
126  interface atmos_thermodyn_entr
127  module procedure atmos_thermodyn_entr_0d
128  module procedure atmos_thermodyn_entr_2d
129  module procedure atmos_thermodyn_entr_3d
130  end interface atmos_thermodyn_entr
131 
132  public :: atmos_thermodyn_tempre
133  public :: atmos_thermodyn_tempre2
134 
135  !-----------------------------------------------------------------------------
136  !
137  !++ Public parameters & variables
138  !
139  real(RP), public :: thermodyn_emask = 0.0_rp
140 
141  real(RP), public, allocatable :: aq_cp(:)
142  real(RP), public, allocatable :: aq_cv(:)
143 
144  !-----------------------------------------------------------------------------
145  !
146  !++ Private procedure
147  !
148  !-----------------------------------------------------------------------------
149  !
150  !++ Private parameters & variables
151  !
152 
153  !-----------------------------------------------------------------------------
154 contains
155  !-----------------------------------------------------------------------------
157  subroutine atmos_thermodyn_setup
158  use scale_process, only: &
160  use scale_const, only: &
161  cpvap => const_cpvap, &
162  cvvap => const_cvvap, &
163  cl => const_cl, &
164  ci => const_ci, &
165  thermodyn_type => const_thermodyn_type
166  implicit none
167 
168  integer :: n
169  !---------------------------------------------------------------------------
170 
171  if( io_l ) write(io_fid_log,*)
172  if( io_l ) write(io_fid_log,*) '++++++ Module[THERMODYN] / Categ[ATMOS SHARE] / Origin[SCALElib]'
173 
174  allocate( aq_cp(qqa) )
175  allocate( aq_cv(qqa) )
176 
177  if ( thermodyn_type == 'EXACT' ) then
178  thermodyn_emask = 1.0_rp
179 
180  aq_cp(i_qv) = cpvap
181  aq_cv(i_qv) = cvvap
182 
183  if ( qws /= 0 ) then
184  do n = qws, qwe
185  aq_cp(n) = cl
186  aq_cv(n) = cl
187  enddo
188  endif
189 
190  if ( qis /= 0 ) then
191  do n = qis, qie
192  aq_cp(n) = ci
193  aq_cv(n) = ci
194  enddo
195  endif
196  elseif( thermodyn_type == 'SIMPLE' ) then
197  thermodyn_emask = 0.0_rp
198 
199  aq_cp(i_qv) = cpdry
200  aq_cv(i_qv) = cvdry
201 
202  if ( qws /= 0 ) then
203  do n = qws, qwe
204  aq_cp(n) = cvdry
205  aq_cv(n) = cvdry
206  enddo
207  endif
208 
209  if ( qis /= 0 ) then
210  do n = qis, qie
211  aq_cp(n) = cvdry
212  aq_cv(n) = cvdry
213  enddo
214  endif
215  endif
216 
217  return
218  end subroutine atmos_thermodyn_setup
219 
220  !-----------------------------------------------------------------------------
222  subroutine atmos_thermodyn_qd_0d( &
223  qdry, &
224  q )
225  implicit none
226 
227  real(RP), intent(out) :: qdry
228  real(RP), intent(in) :: q(qa)
229 
230  integer :: iqw
231  !-----------------------------------------------------------------------------
232 
233  qdry = 1.0_rp
234 #ifndef DRY
235  do iqw = qqs, qqe
236  qdry = qdry - q(iqw)
237  enddo
238 #endif
239 
240  return
241  end subroutine atmos_thermodyn_qd_0d
242 
243  !-----------------------------------------------------------------------------
245  subroutine atmos_thermodyn_qd_3d( &
246  qdry, &
247  q )
248  implicit none
249 
250  real(RP), intent(out) :: qdry(ka,ia,ja)
251  real(RP), intent(in) :: q (ka,ia,ja,qa)
252 
253  integer :: k, i, j, iqw
254  !-----------------------------------------------------------------------------
255 
256  !$omp parallel do private(i,j,k,iqw) OMP_SCHEDULE_ collapse(2)
257  do j = jsb, jeb
258  do i = isb, ieb
259  do k = ks, ke
260 
261 ! qdry(k,i,j) = 1.0_RP
262 ! do iqw = QQS, QQE
263 ! qdry(k,i,j) = qdry(k,i,j) - q(k,i,j,iqw)
264 ! enddo
265  calc_qdry( qdry(k,i,j), q, k, i, j, iqw )
266 
267  enddo
268  enddo
269  enddo
270 
271  return
272  end subroutine atmos_thermodyn_qd_3d
273 
274  !-----------------------------------------------------------------------------
276  subroutine atmos_thermodyn_cp_0d( &
277  CPtot, &
278  q, &
279  qdry )
280  implicit none
281 
282  real(RP), intent(out) :: CPtot
283  real(RP), intent(in) :: q(qa)
284  real(RP), intent(in) :: qdry
285 
286  integer :: iqw
287  !---------------------------------------------------------------------------
288 
289  cptot = qdry * cpdry
290 #ifndef DRY
291  do iqw = qqs, qqe
292  cptot = cptot + q(iqw) * aq_cp(iqw)
293  enddo
294 #endif
295 
296  return
297  end subroutine atmos_thermodyn_cp_0d
298 
299  !-----------------------------------------------------------------------------
301  subroutine atmos_thermodyn_cp_3d( &
302  CPtot, &
303  q, &
304  qdry )
305  implicit none
306 
307  real(RP), intent(out) :: CPtot(ka,ia,ja)
308  real(RP), intent(in) :: q (ka,ia,ja,qa)
309  real(RP), intent(in) :: qdry (ka,ia,ja)
310 
311  integer :: k, i, j, iqw
312  !---------------------------------------------------------------------------
313 
314  !$omp parallel do private(i,j,k,iqw) OMP_SCHEDULE_ collapse(2)
315  do j = jsb, jeb
316  do i = isb, ieb
317  do k = ks, ke
318 
319 ! CPtot(k,i,j) = qdry(k,i,j) * CPdry
320 ! do iqw = QQS, QQE
321 ! CPtot(k,i,j) = CPtot(k,i,j) + q(k,i,j,iqw) * AQ_CP(iqw)
322 ! enddo
323 
324  calc_cp(cptot(k,i,j), qdry(k,i,j), q, k, i, j, iqw, cpdry, aq_cp)
325 
326  enddo
327  enddo
328  enddo
329 
330  return
331  end subroutine atmos_thermodyn_cp_3d
332 
333  !-----------------------------------------------------------------------------
335  subroutine atmos_thermodyn_cv_0d( &
336  CVtot, &
337  q, &
338  qdry )
339  implicit none
340 
341  real(RP), intent(out) :: CVtot
342  real(RP), intent(in) :: q(qa)
343  real(RP), intent(in) :: qdry
344 
345  integer :: iqw
346  !---------------------------------------------------------------------------
347 
348  cvtot = qdry * cvdry
349 #ifndef DRY
350  do iqw = qqs, qqe
351  cvtot = cvtot + q(iqw) * aq_cv(iqw)
352  enddo
353 #endif
354 
355  return
356  end subroutine atmos_thermodyn_cv_0d
357 
358  !-----------------------------------------------------------------------------
360  subroutine atmos_thermodyn_cv_3d( &
361  CVtot, &
362  q, &
363  qdry )
364  implicit none
365 
366  real(RP), intent(out) :: CVtot(ka,ia,ja)
367  real(RP), intent(in) :: q (ka,ia,ja,qa)
368  real(RP), intent(in) :: qdry (ka,ia,ja)
369 
370  integer :: k, i, j, iqw
371  !---------------------------------------------------------------------------
372 
373  !$omp parallel do private(i,j,k,iqw) OMP_SCHEDULE_ collapse(2)
374  do j = jsb, jeb
375  do i = isb, ieb
376  do k = ks, ke
377 
378 ! CVtot(k,i,j) = qdry(k,i,j) * CVdry
379 ! do iqw = QQS, QQE
380 ! CVtot(k,i,j) = CVtot(k,i,j) + q(k,i,j,iqw) * AQ_CV(iqw)
381 ! enddo
382 
383  calc_cv(cvtot(k,i,j), qdry(k,i,j), q, k, i, j, iqw, cvdry, aq_cv)
384 
385  enddo
386  enddo
387  enddo
388 
389  return
390  end subroutine atmos_thermodyn_cv_3d
391 
392  !-----------------------------------------------------------------------------
393  subroutine atmos_thermodyn_pott_0d( &
394  pott, &
395  temp, &
396  pres, &
397  q )
398  implicit none
399 
400  real(RP), intent(out) :: pott ! potential temperature [K]
401  real(RP), intent(in) :: temp ! temperature [K]
402  real(RP), intent(in) :: pres ! pressure [Pa]
403  real(RP), intent(in) :: q(qa) ! mass concentration [kg/kg]
404 
405  real(RP) :: qdry
406  real(RP) :: Rtot, CVtot, RovCP
407 
408  integer :: iqw
409  !---------------------------------------------------------------------------
410 
411 #ifdef DRY
412  cvtot = cvdry
413  rtot = rdry
414 #else
415  qdry = 1.0_rp
416  cvtot = 0.0_rp
417  do iqw = qqs, qqe
418  qdry = qdry - q(iqw)
419  cvtot = cvtot + q(iqw) * aq_cv(iqw)
420  enddo
421  cvtot = cvdry * qdry + cvtot
422  rtot = rdry * qdry + rvap * q(i_qv)
423 #endif
424 
425  rovcp = rtot / ( cvtot + rtot )
426 
427  pott = temp * ( pre00 / pres )**rovcp
428 
429  return
430  end subroutine atmos_thermodyn_pott_0d
431 
432  !-----------------------------------------------------------------------------
433  subroutine atmos_thermodyn_pott_3d( &
434  pott, &
435  temp, &
436  pres, &
437  q )
438  implicit none
439 
440  real(RP), intent(out) :: pott(ka,ia,ja) ! potential temperature [K]
441  real(RP), intent(in) :: temp(ka,ia,ja) ! temperature [K]
442  real(RP), intent(in) :: pres(ka,ia,ja) ! pressure [Pa]
443  real(RP), intent(in) :: q (ka,ia,ja,qa) ! mass concentration [kg/kg]
444 
445  real(RP) :: qdry
446  real(RP) :: Rtot, CVtot, RovCP
447 
448  integer :: k, i, j, iqw
449  !---------------------------------------------------------------------------
450 
451  do j = jsb, jeb
452  do i = isb, ieb
453  do k = ks, ke
454 #ifdef DRY
455  cvtot = cvdry
456  rtot = rdry
457 #else
458  qdry = 1.0_rp
459  cvtot = 0.0_rp
460  do iqw = qqs, qqe
461  qdry = qdry - q(k,i,j,iqw)
462  cvtot = cvtot + q(k,i,j,iqw) * aq_cv(iqw)
463  enddo
464  cvtot = cvdry * qdry + cvtot
465  rtot = rdry * qdry + rvap * q(k,i,j,i_qv)
466 #endif
467 
468  rovcp = rtot / ( cvtot + rtot )
469 
470  pott(k,i,j) = temp(k,i,j) * ( pre00 / pres(k,i,j) )**rovcp
471  enddo
472  enddo
473  enddo
474 
475  return
476  end subroutine atmos_thermodyn_pott_3d
477 
478  !-----------------------------------------------------------------------------
480  subroutine atmos_thermodyn_rhoe_0d( &
481  rhoe, &
482  rhot, &
483  q )
484  implicit none
485 
486  real(RP), intent(out) :: rhoe
487  real(RP), intent(in) :: rhot
488  real(RP), intent(in) :: q(qa)
489 
490  real(RP) :: qdry
491  real(RP) :: pres
492  real(RP) :: Rtot, CVtot, CPovCV
493 
494  integer :: iqw
495  !---------------------------------------------------------------------------
496 
497 #ifdef DRY
498  cvtot = cvdry
499  rtot = rdry
500 #else
501  qdry = 1.0_rp
502  cvtot = 0.0_rp
503  do iqw = qqs, qqe
504  qdry = qdry - q(iqw)
505  cvtot = cvtot + q(iqw) * aq_cv(iqw)
506  enddo
507  cvtot = cvdry * qdry + cvtot
508  rtot = rdry * qdry + rvap * q(i_qv)
509 #endif
510 
511  cpovcv = ( cvtot + rtot ) / cvtot
512 
513  pres = pre00 * ( rhot * rtot / pre00 )**cpovcv
514 
515  rhoe = pres / rtot * cvtot
516 
517  return
518  end subroutine atmos_thermodyn_rhoe_0d
519 
520  !-----------------------------------------------------------------------------
522  subroutine atmos_thermodyn_rhoe_3d( &
523  rhoe, &
524  rhot, &
525  q )
526  implicit none
527 
528  real(RP), intent(out) :: rhoe(ka,ia,ja)
529  real(RP), intent(in) :: rhot(ka,ia,ja)
530  real(RP), intent(in) :: q (ka,ia,ja,qa)
531 
532  real(RP) :: qdry
533  real(RP) :: pres
534  real(RP) :: Rtot, CVtot, CPovCV
535 
536  integer :: k, i, j, iqw
537  !---------------------------------------------------------------------------
538 
539  !$omp parallel do private(i,j,k,iqw,qdry,pres,Rtot,CVtot,CPovCV) OMP_SCHEDULE_ collapse(2)
540  do j = jsb, jeb
541  do i = isb, ieb
542  do k = ks, ke
543 #ifdef DRY
544  cvtot = cvdry
545  rtot = rdry
546 #else
547  qdry = 1.0_rp
548  cvtot = 0.0_rp
549  do iqw = qqs, qqe
550  qdry = qdry - q(k,i,j,iqw)
551  cvtot = cvtot + q(k,i,j,iqw) * aq_cv(iqw)
552  enddo
553  cvtot = cvdry * qdry + cvtot
554  rtot = rdry * qdry + rvap * q(k,i,j,i_qv)
555 #endif
556 
557 
558  cpovcv = ( cvtot + rtot ) / cvtot
559 
560  pres = pre00 * ( rhot(k,i,j) * rtot / pre00 )**cpovcv
561 
562  rhoe(k,i,j) = pres / rtot * cvtot
563  enddo
564  enddo
565  enddo
566 
567  return
568  end subroutine atmos_thermodyn_rhoe_3d
569 
570  !-----------------------------------------------------------------------------
572  subroutine atmos_thermodyn_rhot_0d( &
573  rhot, &
574  rhoe, &
575  q )
576  implicit none
577 
578  real(RP), intent(out) :: rhot
579  real(RP), intent(in) :: rhoe
580  real(RP), intent(in) :: q(qa)
581 
582  real(RP) :: qdry
583  real(RP) :: pres
584  real(RP) :: Rtot, CVtot, RovCP
585 
586  integer :: iqw
587  !---------------------------------------------------------------------------
588 
589 #ifdef DRY
590  cvtot = cvdry
591  rtot = rdry
592 #else
593  qdry = 1.0_rp
594  cvtot = 0.0_rp
595  do iqw = qqs, qqe
596  qdry = qdry - q(iqw)
597  cvtot = cvtot + q(iqw) * aq_cv(iqw)
598  enddo
599  cvtot = cvdry * qdry + cvtot
600  rtot = rdry * qdry + rvap * q(i_qv)
601 #endif
602 
603  rovcp = rtot / ( cvtot + rtot )
604 
605  pres = rhoe * rtot / cvtot
606 
607  rhot = rhoe / cvtot * ( pre00 / pres )**rovcp
608 
609  return
610  end subroutine atmos_thermodyn_rhot_0d
611 
612  !-----------------------------------------------------------------------------
614  subroutine atmos_thermodyn_rhot_3d( &
615  rhot, &
616  rhoe, &
617  q )
618  implicit none
619 
620  real(RP), intent(out) :: rhot(ka,ia,ja)
621  real(RP), intent(in) :: rhoe(ka,ia,ja)
622  real(RP), intent(in) :: q (ka,ia,ja,qa)
623 
624  real(RP) :: qdry
625  real(RP) :: pres
626  real(RP) :: Rtot, CVtot, RovCP
627 
628  integer :: k, i, j, iqw
629  !---------------------------------------------------------------------------
630 
631  !$omp parallel do private(i,j,k,iqw,qdry,pres,Rtot,CVtot,RovCP) OMP_SCHEDULE_ collapse(2)
632  do j = jsb, jeb
633  do i = isb, ieb
634  do k = ks, ke
635 
636 #ifdef DRY
637  cvtot = cvdry
638  rtot = rdry
639 #else
640  qdry = 1.0_rp
641  cvtot = 0.0_rp
642  do iqw = qqs, qqe
643  qdry = qdry - q(k,i,j,iqw)
644  cvtot = cvtot + q(k,i,j,iqw) * aq_cv(iqw)
645  enddo
646  cvtot = cvdry * qdry + cvtot
647  rtot = rdry * qdry + rvap * q(k,i,j,i_qv)
648 #endif
649 
650  rovcp = rtot / ( cvtot + rtot )
651 
652  pres = rhoe(k,i,j) * rtot / cvtot
653 
654  rhot(k,i,j) = rhoe(k,i,j) / cvtot * ( pre00 / pres )**rovcp
655  enddo
656  enddo
657  enddo
658 
659  return
660  end subroutine atmos_thermodyn_rhot_3d
661 
662  !-----------------------------------------------------------------------------
664  subroutine atmos_thermodyn_temp_pres_0d( &
665  temp, &
666  pres, &
667  dens, &
668  rhot, &
669  q )
670  implicit none
671 
672  real(RP), intent(out) :: temp
673  real(RP), intent(out) :: pres
674  real(RP), intent(in) :: dens
675  real(RP), intent(in) :: rhot
676  real(RP), intent(in) :: q(qa)
677 
678  real(RP) :: qdry
679  real(RP) :: Rtot, CVtot, CPovCV
680 
681  integer :: iqw
682  !---------------------------------------------------------------------------
683 
684 #ifdef DRY
685  cvtot = cvdry
686  rtot = rdry
687 #else
688  qdry = 1.0_rp
689  cvtot = 0.0_rp
690  do iqw = qqs, qqe
691  qdry = qdry - q(iqw)
692  cvtot = cvtot + q(iqw) * aq_cv(iqw)
693  enddo
694  cvtot = cvdry * qdry + cvtot
695  rtot = rdry * qdry + rvap * q(i_qv)
696 #endif
697 
698  cpovcv = ( cvtot + rtot ) / cvtot
699 
700  pres = pre00 * ( rhot * rtot / pre00 )**cpovcv
701  temp = pres / ( dens * rtot )
702 
703  return
704  end subroutine atmos_thermodyn_temp_pres_0d
705 
706  !-----------------------------------------------------------------------------
708  subroutine atmos_thermodyn_temp_pres_3d( &
709  temp, &
710  pres, &
711  dens, &
712  rhot, &
713  q )
714  implicit none
715 
716  real(RP), intent(out) :: temp(ka,ia,ja)
717  real(RP), intent(out) :: pres(ka,ia,ja)
718  real(RP), intent(in) :: dens(ka,ia,ja)
719  real(RP), intent(in) :: rhot(ka,ia,ja)
720  real(RP), intent(in) :: q (ka,ia,ja,qa)
721 
722  real(RP) :: qdry
723  real(RP) :: Rtot, CVtot, CPovCV
724 
725  integer :: k, i, j, iqw
726  !---------------------------------------------------------------------------
727 
728  !$omp parallel do private(i,j,k,iqw,qdry,Rtot,CVtot,CPovCV) OMP_SCHEDULE_ collapse(2)
729  do j = jsb, jeb
730  do i = isb, ieb
731  do k = ks, ke
732 #ifdef DRY
733  cvtot = cvdry
734  rtot = rdry
735 #else
736  qdry = 1.0_rp
737  cvtot = 0.0_rp
738  do iqw = qqs, qqe
739  qdry = qdry - q(k,i,j,iqw)
740  cvtot = cvtot + q(k,i,j,iqw) * aq_cv(iqw)
741  enddo
742  cvtot = cvdry * qdry + cvtot
743  rtot = rdry * qdry + rvap * q(k,i,j,i_qv)
744 #endif
745 
746  cpovcv = ( cvtot + rtot ) / cvtot
747 
748  pres(k,i,j) = pre00 * ( rhot(k,i,j) * rtot / pre00 )**cpovcv
749  temp(k,i,j) = pres(k,i,j) / ( dens(k,i,j) * rtot )
750  enddo
751  enddo
752  enddo
753 
754  return
755  end subroutine atmos_thermodyn_temp_pres_3d
756 
757  !-----------------------------------------------------------------------------
759  subroutine atmos_thermodyn_temp_pres_e_0d( &
760  temp, &
761  pres, &
762  dens, &
763  rhoe, &
764  q )
765  implicit none
766 
767  real(RP), intent(out) :: temp
768  real(RP), intent(out) :: pres
769  real(RP), intent(in) :: dens
770  real(RP), intent(in) :: rhoe
771  real(RP), intent(in) :: q(qa)
772 
773  real(RP) :: qdry
774  real(RP) :: Rtot, CVtot
775 
776  integer :: iqw
777  !---------------------------------------------------------------------------
778 
779 #ifdef DRY
780  cvtot = cvdry
781  rtot = rdry
782 #else
783  qdry = 1.0_rp
784  cvtot = 0.0_rp
785  do iqw = qqs, qqe
786  qdry = qdry - q(iqw)
787  cvtot = cvtot + q(iqw) * aq_cv(iqw)
788  enddo
789  cvtot = cvdry * qdry + cvtot
790  rtot = rdry * qdry + rvap * q(i_qv)
791 #endif
792 
793  temp = rhoe / ( dens * cvtot )
794  pres = dens * rtot * temp
795 
796  return
797  end subroutine atmos_thermodyn_temp_pres_e_0d
798 
799  !-----------------------------------------------------------------------------
801  subroutine atmos_thermodyn_temp_pres_e_3d( &
802  temp, &
803  pres, &
804  dens, &
805  rhoe, &
806  q )
807  implicit none
808 
809  real(RP), intent(out) :: temp(ka,ia,ja)
810  real(RP), intent(out) :: pres(ka,ia,ja)
811  real(RP), intent(in) :: dens(ka,ia,ja)
812  real(RP), intent(in) :: rhoe(ka,ia,ja)
813  real(RP), intent(in) :: q (ka,ia,ja,qa)
814 
815  real(RP) :: qdry
816  real(RP) :: Rtot, CVtot
817 
818  integer :: k, i, j, iqw
819  !---------------------------------------------------------------------------
820 
821  !$omp parallel do private(i,j,k,iqw,qdry,Rtot,CVtot) OMP_SCHEDULE_ collapse(2)
822  do j = jsb, jeb
823  do i = isb, ieb
824  do k = ks, ke
825 #ifdef DRY
826  cvtot = cvdry
827  rtot = rdry
828 #else
829  qdry = 1.0_rp
830  cvtot = 0.0_rp
831  do iqw = qqs, qqe
832  qdry = qdry - q(k,i,j,iqw)
833  cvtot = cvtot + q(k,i,j,iqw) * aq_cv(iqw)
834  enddo
835  cvtot = cvdry * qdry + cvtot
836  rtot = rdry * qdry + rvap * q(k,i,j,i_qv)
837 #endif
838 
839  temp(k,i,j) = rhoe(k,i,j) / ( dens(k,i,j) * cvtot )
840  pres(k,i,j) = dens(k,i,j) * rtot * temp(k,i,j)
841  enddo
842  enddo
843  enddo
844 
845  return
846  end subroutine atmos_thermodyn_temp_pres_e_3d
847 
848  !-----------------------------------------------------------------------------
849  subroutine atmos_thermodyn_templhv_0d( &
850  lhv, &
851  temp )
852  implicit none
853 
854  real(RP), intent(out) :: lhv ! potential temperature [K]
855  real(RP), intent(in) :: temp ! temperature [K]
856  !---------------------------------------------------------------------------
857 
858  lhv = lhv0 + ( cpvap - cl ) * ( temp - tem00 ) * thermodyn_emask
859 
860  return
861  end subroutine atmos_thermodyn_templhv_0d
862 
863  !-----------------------------------------------------------------------------
864  subroutine atmos_thermodyn_templhv_2d( &
865  lhv, &
866  temp )
867  implicit none
868 
869  real(RP), intent(out) :: lhv (ia,ja) ! potential temperature [K]
870  real(RP), intent(in) :: temp(ia,ja) ! temperature [K]
871 
872  integer :: i, j
873  !---------------------------------------------------------------------------
874 
875  do j = jsb, jeb
876  do i = isb, ieb
877  lhv(i,j) = lhv0 + ( cpvap - cl ) * ( temp(i,j) - tem00 ) * thermodyn_emask
878  enddo
879  enddo
880 
881  return
882  end subroutine atmos_thermodyn_templhv_2d
883 
884  !-----------------------------------------------------------------------------
885  subroutine atmos_thermodyn_templhv_3d( &
886  lhv, &
887  temp )
888  implicit none
889 
890  real(RP), intent(out) :: lhv (ka,ia,ja) ! potential temperature [K]
891  real(RP), intent(in) :: temp(ka,ia,ja) ! temperature [K]
892 
893  integer :: k, i, j
894  !---------------------------------------------------------------------------
895 
896  do j = jsb, jeb
897  do i = isb, ieb
898  do k = ks, ke
899  lhv(k,i,j) = lhv0 + ( cpvap - cl ) * ( temp(k,i,j) - tem00 ) * thermodyn_emask
900  enddo
901  enddo
902  enddo
903 
904  return
905  end subroutine atmos_thermodyn_templhv_3d
906 
907  !-----------------------------------------------------------------------------
908  subroutine atmos_thermodyn_templhs_0d( &
909  lhs, &
910  temp )
911  implicit none
912 
913  real(RP), intent(out) :: lhs ! potential temperature [K]
914  real(RP), intent(in) :: temp ! temperature [K]
915  !---------------------------------------------------------------------------
916 
917  lhs = lhs0 + ( cpvap - ci ) * ( temp - tem00 ) * thermodyn_emask
918 
919  return
920  end subroutine atmos_thermodyn_templhs_0d
921 
922  !-----------------------------------------------------------------------------
923  subroutine atmos_thermodyn_templhs_2d( &
924  lhs, &
925  temp )
926  implicit none
927 
928  real(RP), intent(out) :: lhs (ia,ja) ! potential temperature [K]
929  real(RP), intent(in) :: temp(ia,ja) ! temperature [K]
930 
931  integer :: i, j
932  !---------------------------------------------------------------------------
933 
934  do j = jsb, jeb
935  do i = isb, ieb
936  lhs(i,j) = lhs0 + ( cpvap - ci ) * ( temp(i,j) - tem00 ) * thermodyn_emask
937  enddo
938  enddo
939 
940  return
941  end subroutine atmos_thermodyn_templhs_2d
942 
943  !-----------------------------------------------------------------------------
944  subroutine atmos_thermodyn_templhs_3d( &
945  lhs, &
946  temp )
947  implicit none
948 
949  real(RP), intent(out) :: lhs (ka,ia,ja) ! potential temperature [K]
950  real(RP), intent(in) :: temp(ka,ia,ja) ! temperature [K]
951 
952  integer :: k, i, j
953  !---------------------------------------------------------------------------
954 
955  do j = jsb, jeb
956  do i = isb, ieb
957  do k = ks, ke
958  lhs(k,i,j) = lhs0 + ( cpvap - ci ) * ( temp(k,i,j) - tem00 ) * thermodyn_emask
959  enddo
960  enddo
961  enddo
962 
963  return
964  end subroutine atmos_thermodyn_templhs_3d
965 
966  !-----------------------------------------------------------------------------
967  subroutine atmos_thermodyn_templhf_0d( &
968  lhf, &
969  temp )
970  implicit none
971 
972  real(RP), intent(out) :: lhf ! potential temperature [K]
973  real(RP), intent(in) :: temp ! temperature [K]
974  !---------------------------------------------------------------------------
975 
976  lhf = lhf0 + ( cl - ci ) * ( temp - tem00 ) * thermodyn_emask
977 
978  return
979  end subroutine atmos_thermodyn_templhf_0d
980 
981  !-----------------------------------------------------------------------------
982  subroutine atmos_thermodyn_templhf_2d( &
983  lhf, &
984  temp )
985  implicit none
986 
987  real(RP), intent(out) :: lhf (ia,ja) ! potential temperature [K]
988  real(RP), intent(in) :: temp(ia,ja) ! temperature [K]
989 
990  integer :: i, j
991  !---------------------------------------------------------------------------
992 
993  do j = jsb, jeb
994  do i = isb, ieb
995  lhf(i,j) = lhf0 + ( cl - ci ) * ( temp(i,j) - tem00 ) * thermodyn_emask
996  enddo
997  enddo
998 
999  return
1000  end subroutine atmos_thermodyn_templhf_2d
1001 
1002  !-----------------------------------------------------------------------------
1003  subroutine atmos_thermodyn_templhf_3d( &
1004  lhf, &
1005  temp )
1006  implicit none
1007 
1008  real(RP), intent(out) :: lhf (ka,ia,ja) ! potential temperature [K]
1009  real(RP), intent(in) :: temp(ka,ia,ja) ! temperature [K]
1010 
1011  integer :: k, i, j
1012  !---------------------------------------------------------------------------
1013 
1014  do j = jsb, jeb
1015  do i = isb, ieb
1016  do k = ks, ke
1017  lhf(k,i,j) = lhf0 + ( cl - ci ) * ( temp(k,i,j) - tem00 ) * thermodyn_emask
1018  enddo
1019  enddo
1020  enddo
1021 
1022  return
1023  end subroutine atmos_thermodyn_templhf_3d
1024 
1025  !-----------------------------------------------------------------------------
1027  subroutine atmos_thermodyn_entr_0d( &
1028  entr, &
1029  temp, &
1030  pres, &
1031  q )
1032  implicit none
1033 
1034  real(RP), intent(out) :: entr
1035  real(RP), intent(in) :: temp
1036  real(RP), intent(in) :: pres
1037  real(RP), intent(in) :: q(qa)
1038 
1039  real(RP) :: lhv, lhf
1040  real(RP) :: qdry, Rtot
1041  real(RP) :: logT_T0, pres_dry, pres_vap
1042  real(RP) :: sq
1043 
1044  integer :: iqw
1045  !---------------------------------------------------------------------------
1046 
1047  lhv = lhv0 + ( cpvap - cl ) * ( temp - tem00 ) * thermodyn_emask
1048  lhf = lhf0 + ( cl - ci ) * ( temp - tem00 ) * thermodyn_emask
1049 
1050  qdry = 1.0_rp
1051  do iqw = qqs, qqe
1052  qdry = qdry - q(iqw)
1053  enddo
1054  rtot = rdry * qdry + rvap * q(i_qv)
1055 
1056  logt_t0 = log( temp / tem00 )
1057 
1058  ! dry air + vapor
1059  pres_dry = max( pres * qdry * rdry / rtot, eps )
1060  pres_vap = max( pres * q(i_qv) * rvap / rtot, eps )
1061 
1062  entr = qdry * cpdry * logt_t0 &
1063  - qdry * rdry * log( pres_dry / pre00 ) &
1064  + q(i_qv) * cpvap * logt_t0 &
1065  - q(i_qv) * rvap * log( pres_vap / psat0 ) &
1066  + q(i_qv) * lhv / tem00
1067 
1068  ! hydrometeors
1069  do iqw = qqs, qqe
1070  sq = 0.0_rp
1071 
1072  if( iqw == i_qc ) sq = q(i_qc) * cl * logt_t0
1073 
1074  if( iqw == i_qr ) sq = q(i_qr) * cl * logt_t0
1075 
1076  if( iqw == i_qi ) sq = q(i_qi) * ci * logt_t0 &
1077  - q(i_qi) * lhf / tem00
1078 
1079  if( iqw == i_qs ) sq = q(i_qs) * ci * logt_t0 &
1080  - q(i_qs) * lhf / tem00
1081 
1082  if( iqw == i_qg ) sq = q(i_qg) * ci * logt_t0 &
1083  - q(i_qg) * lhf / tem00
1084 
1085  entr = entr + sq
1086  enddo
1087 
1088  return
1089  end subroutine atmos_thermodyn_entr_0d
1090 
1091  !-----------------------------------------------------------------------------
1093  subroutine atmos_thermodyn_entr_2d( &
1094  entr, &
1095  temp, &
1096  pres, &
1097  q )
1098  implicit none
1099 
1100  real(RP), intent(out) :: entr(ia,ja)
1101  real(RP), intent(in) :: temp(ia,ja)
1102  real(RP), intent(in) :: pres(ia,ja)
1103  real(RP), intent(in) :: q (ia,ja,qa)
1104 
1105  real(RP) :: lhv, lhf
1106  real(RP) :: qdry, Rtot
1107  real(RP) :: logT_T0, pres_dry, pres_vap
1108  real(RP) :: sq
1109 
1110  integer :: i, j, iqw
1111  !---------------------------------------------------------------------------
1112 
1113  ! dry air + vapor
1114  do j = jsb, jeb
1115  do i = isb, ieb
1116  lhv = lhv0 + ( cpvap - cl ) * ( temp(i,j) - tem00 ) * thermodyn_emask
1117 
1118  qdry = 1.0_rp
1119  do iqw = qqs, qqe
1120  qdry = qdry - q(i,j,iqw)
1121  enddo
1122  rtot = rdry * qdry + rvap * q(i,j,i_qv)
1123 
1124  logt_t0 = log( temp(i,j) / tem00 )
1125 
1126  pres_dry = max( pres(i,j) * qdry * rdry / rtot, eps )
1127  pres_vap = max( pres(i,j) * q(i,j,i_qv) * rvap / rtot, eps )
1128 
1129  entr(i,j) = qdry * cpdry * logt_t0 &
1130  - qdry * rdry * log( pres_dry / pre00 ) &
1131  + q(i,j,i_qv) * cpvap * logt_t0 &
1132  - q(i,j,i_qv) * rvap * log( pres_vap / psat0 ) &
1133  + q(i,j,i_qv) * lhv / tem00
1134  enddo
1135  enddo
1136 
1137  ! hydrometeors
1138  do j = jsb, jeb
1139  do i = isb, ieb
1140  lhf = lhf0 + ( cl - ci ) * ( temp(i,j) - tem00 ) * thermodyn_emask
1141 
1142  logt_t0 = log( temp(i,j) / tem00 )
1143 
1144  do iqw = qqs, qqe
1145  sq = 0.0_rp
1146 
1147  if( iqw == i_qc ) sq = q(i,j,i_qc) * cl * logt_t0
1148  if( iqw == i_qr ) sq = q(i,j,i_qr) * cl * logt_t0
1149  if( iqw == i_qi ) sq = q(i,j,i_qi) * ( ci * logt_t0 - lhf / tem00 )
1150  if( iqw == i_qs ) sq = q(i,j,i_qs) * ( ci * logt_t0 - lhf / tem00 )
1151  if( iqw == i_qg ) sq = q(i,j,i_qg) * ( ci * logt_t0 - lhf / tem00 )
1152 
1153  entr(i,j) = entr(i,j) + sq
1154  enddo
1155  enddo
1156  enddo
1157 
1158  return
1159  end subroutine atmos_thermodyn_entr_2d
1160 
1161  !-----------------------------------------------------------------------------
1163  subroutine atmos_thermodyn_entr_3d( &
1164  entr, &
1165  temp, &
1166  pres, &
1167  q )
1168  implicit none
1169 
1170  real(RP), intent(out) :: entr(ka,ia,ja)
1171  real(RP), intent(in) :: temp(ka,ia,ja)
1172  real(RP), intent(in) :: pres(ka,ia,ja)
1173  real(RP), intent(in) :: q (ka,ia,ja,qa)
1174 
1175  real(RP) :: lhv, lhf
1176  real(RP) :: qdry, Rtot
1177  real(RP) :: logT_T0, pres_dry, pres_vap
1178  real(RP) :: sq
1179 
1180  integer :: k, i, j, iqw
1181  !---------------------------------------------------------------------------
1182 
1183  ! dry air + vapor
1184  do j = jsb, jeb
1185  do i = isb, ieb
1186  do k = ks, ke
1187  lhv = lhv0 + ( cpvap - cl ) * ( temp(k,i,j) - tem00 ) * thermodyn_emask
1188 
1189  qdry = 1.0_rp
1190  do iqw = qqs, qqe
1191  qdry = qdry - q(k,i,j,iqw)
1192  enddo
1193  rtot = rdry * qdry + rvap * q(k,i,j,i_qv)
1194 
1195  logt_t0 = log( temp(k,i,j) / tem00 )
1196 
1197  pres_dry = max( pres(k,i,j) * qdry * rdry / rtot, eps )
1198  pres_vap = max( pres(k,i,j) * q(k,i,j,i_qv) * rvap / rtot, eps )
1199 
1200  entr(k,i,j) = qdry * cpdry * logt_t0 &
1201  - qdry * rdry * log( pres_dry / pre00 ) &
1202  + q(k,i,j,i_qv) * cpvap * logt_t0 &
1203  - q(k,i,j,i_qv) * rvap * log( pres_vap / psat0 ) &
1204  + q(k,i,j,i_qv) * lhv / tem00
1205  enddo
1206  enddo
1207  enddo
1208 
1209  ! hydrometeors
1210  do j = jsb, jeb
1211  do i = isb, ieb
1212  do k = ks, ke
1213  lhf = lhf0 + ( cl - ci ) * ( temp(k,i,j) - tem00 ) * thermodyn_emask
1214 
1215  logt_t0 = log( temp(k,i,j) / tem00 )
1216 
1217  do iqw = qqs, qqe
1218  sq = 0.0_rp
1219 
1220  if( iqw == i_qc ) sq = q(k,i,j,i_qc) * cl * logt_t0
1221  if( iqw == i_qr ) sq = q(k,i,j,i_qr) * cl * logt_t0
1222  if( iqw == i_qi ) sq = q(k,i,j,i_qi) * ( ci * logt_t0 - lhf / tem00 )
1223  if( iqw == i_qs ) sq = q(k,i,j,i_qs) * ( ci * logt_t0 - lhf / tem00 )
1224  if( iqw == i_qg ) sq = q(k,i,j,i_qg) * ( ci * logt_t0 - lhf / tem00 )
1225 
1226  entr(k,i,j) = entr(k,i,j) + sq
1227  enddo
1228  enddo
1229  enddo
1230  enddo
1231 
1232  return
1233  end subroutine atmos_thermodyn_entr_3d
1234 
1235  !-----------------------------------------------------------------------------
1236  subroutine atmos_thermodyn_tempre( &
1237  temp, pres, &
1238  Ein, dens, qdry, q )
1239  implicit none
1240 
1241  real(RP), intent(out) :: temp(ka,ia,ja) ! temperature
1242  real(RP), intent(out) :: pres(ka,ia,ja) ! pressure
1243  real(RP), intent(in) :: Ein (ka,ia,ja) ! internal energy
1244  real(RP), intent(in) :: dens(ka,ia,ja) ! density
1245  real(RP), intent(in) :: qdry(ka,ia,ja) ! dry concentration
1246  real(RP), intent(in) :: q (ka,ia,ja,qa) ! water concentration
1247 
1248  real(RP) :: cv, Rmoist
1249 
1250  integer :: i, j, k, iqw
1251  !---------------------------------------------------------------------------
1252 
1253  !$omp parallel do private(i,j,k,iqw,cv,Rmoist) OMP_SCHEDULE_ collapse(2)
1254  do j = jsb, jeb
1255  do i = isb, ieb
1256  do k = ks, ke
1257 
1258  calc_cv(cv, qdry(k,i,j), q, k, i, j, iqw, cvdry, aq_cv)
1259  calc_r(rmoist, q(k,i,j,i_qv), qdry(k,i,j), rdry, rvap)
1260 
1261  temp(k,i,j) = ein(k,i,j) / cv
1262 
1263  pres(k,i,j) = dens(k,i,j) * rmoist * temp(k,i,j)
1264 
1265  enddo
1266  enddo
1267  enddo
1268 
1269  return
1270  end subroutine atmos_thermodyn_tempre
1271 
1272  !-----------------------------------------------------------------------------
1273  subroutine atmos_thermodyn_tempre2( &
1274  temp, pres, &
1275  dens, pott, qdry, q )
1276  implicit none
1277 
1278  real(RP), intent(out) :: temp(ka,ia,ja) ! temperature
1279  real(RP), intent(out) :: pres(ka,ia,ja) ! pressure
1280  real(RP), intent(in) :: dens(ka,ia,ja) ! density
1281  real(RP), intent(in) :: pott(ka,ia,ja) ! potential temperature
1282  real(RP), intent(in) :: qdry(ka,ia,ja) ! dry concentration
1283  real(RP), intent(in) :: q (ka,ia,ja,qa) ! water concentration
1284 
1285  real(RP) :: Rmoist, cp
1286 
1287  integer :: i, j, k, iqw
1288  !---------------------------------------------------------------------------
1289 
1290  !$omp parallel do private(i,j,k,iqw,cp,Rmoist) OMP_SCHEDULE_ collapse(2)
1291  do j = jsb, jeb
1292  do i = isb, ieb
1293  do k = ks, ke
1294 
1295  calc_cp(cp, qdry(k,i,j), q, k, i, j, iqw, cpdry, aq_cp)
1296  calc_r(rmoist, q(k,i,j,i_qv), qdry(k,i,j), rdry, rvap)
1297  calc_pre(pres(k,i,j), dens(k,i,j), pott(k,i,j), rmoist, cp, pre00)
1298 
1299  temp(k,i,j) = pres(k,i,j) / ( dens(k,i,j) * rmoist )
1300 
1301  enddo
1302  enddo
1303  enddo
1304 
1305  return
1306  end subroutine atmos_thermodyn_tempre2
1307 
1308 end module scale_atmos_thermodyn
integer, public qie
real(rp), public const_cvdry
specific heat (dry air,constant volume) [J/kg/K]
Definition: scale_const.F90:59
real(rp), parameter, public const_psat0
saturate pressure of water vapor at 0C [Pa]
Definition: scale_const.F90:86
real(rp), public const_cpdry
specific heat (dry air,constant pressure) [J/kg/K]
Definition: scale_const.F90:58
subroutine, public prc_mpistop
Abort MPI.
integer, public jeb
real(rp), parameter, public const_ci
specific heat (ice) [J/kg/K]
Definition: scale_const.F90:69
real(rp), dimension(:), allocatable, public aq_cp
CP for each hydrometeors [J/kg/K].
integer, public qqe
logical, public io_l
output log or not? (this process)
Definition: scale_stdio.F90:59
integer, public qwe
real(rp), parameter, public const_cl
specific heat (liquid water) [J/kg/K]
Definition: scale_const.F90:68
module STDIO
Definition: scale_stdio.F90:12
integer, public ke
end point of inner domain: z, local
real(rp), public thermodyn_emask
=0: SIMPLE, 1: EXACT
real(rp), parameter, public const_tem00
temperature reference (0C) [K]
Definition: scale_const.F90:95
integer, public qa
subroutine atmos_thermodyn_qd_0d(qdry, q)
calc dry air mass (0D)
integer, public qws
real(rp), public const_cvvap
specific heat (water vapor, constant volume) [J/kg/K]
Definition: scale_const.F90:67
integer, public qis
real(rp), public const_lhf0
latent heat of fusion at 0C [J/kg]
Definition: scale_const.F90:84
real(rp), public const_rdry
specific gas constant (dry air) [J/kg/K]
Definition: scale_const.F90:57
integer, public ieb
real(rp), parameter, public const_lhs0
latent heat of sublimation at 0C [J/kg]
Definition: scale_const.F90:82
subroutine, public atmos_thermodyn_tempre(temp, pres, Ein, dens, qdry, q)
module grid index
module TRACER
integer, public ia
of x whole cells (local, with HALO)
integer, public ka
of z whole cells (local, with HALO)
integer, public i_qv
real(rp), parameter, public const_lhv0
latent heat of vaporizaion at 0C [J/kg]
Definition: scale_const.F90:80
real(rp), public const_pre00
pressure reference [Pa]
Definition: scale_const.F90:93
integer, public qqa
module PROCESS
subroutine, public atmos_thermodyn_setup
Setup.
subroutine, public log(type, message)
Definition: dc_log.f90:133
real(rp), parameter, public const_rvap
specific gas constant (water vapor) [J/kg/K]
Definition: scale_const.F90:65
module CONSTANT
Definition: scale_const.F90:14
real(rp), dimension(:), allocatable, public aq_cv
CV for each hydrometeors [J/kg/K].
integer, public ks
start point of inner domain: z, local
integer, public i_qs
module profiler
Definition: scale_prof.F90:10
integer, public i_qi
real(rp), public const_eps
small number
Definition: scale_const.F90:36
module ATMOSPHERE / Thermodynamics
subroutine, public atmos_thermodyn_tempre2(temp, pres, dens, pott, qdry, q)
integer, public qqs
integer, public i_qg
module PRECISION
integer, public isb
integer, public io_fid_log
Log file ID.
Definition: scale_stdio.F90:56
real(rp), parameter, public const_cpvap
specific heat (water vapor, constant pressure) [J/kg/K]
Definition: scale_const.F90:66
integer, public jsb
character(len=h_short), public const_thermodyn_type
internal energy type
integer, public i_qr
integer, public i_qc
integer, public ja
of y whole cells (local, with HALO)