| Line |
Branch |
Exec |
Source |
| 1 |
|
|
! $Id$ |
| 2 |
|
|
module regr_pr_comb_coefoz_m |
| 3 |
|
|
|
| 4 |
|
|
implicit none |
| 5 |
|
|
|
| 6 |
|
|
! The five module variables declared here are on the partial |
| 7 |
|
|
! "physics" grid. |
| 8 |
|
|
! The value of each variable for index "(i, k)" is at longitude |
| 9 |
|
|
! "rlon(i)", latitude "rlat(i)" and middle of layer "k". |
| 10 |
|
|
|
| 11 |
|
|
real, allocatable, save:: c_Mob(:, :) |
| 12 |
|
|
! (sum of Mobidic terms in the net mass production rate of ozone |
| 13 |
|
|
! by chemistry, per unit mass of air, in s-1) |
| 14 |
|
|
|
| 15 |
|
|
real, allocatable, save:: a2(:, :) |
| 16 |
|
|
! (derivative of mass production rate of ozone per unit mass of |
| 17 |
|
|
! air with respect to ozone mass fraction, in s-1) |
| 18 |
|
|
|
| 19 |
|
|
real, allocatable, save:: a4_mass(:, :) |
| 20 |
|
|
! (derivative of mass production rate of ozone per unit mass of |
| 21 |
|
|
! air with respect to temperature, in s-1 K-1) |
| 22 |
|
|
|
| 23 |
|
|
real, allocatable, save:: a6_mass(:, :) |
| 24 |
|
|
! (derivative of mass production rate of ozone per unit mass of |
| 25 |
|
|
! air with respect to mass column-density of ozone above, in m2 s-1 kg-1) |
| 26 |
|
|
|
| 27 |
|
|
real, allocatable, save:: r_het_interm(:, :) |
| 28 |
|
|
! (net mass production rate by heterogeneous chemistry, per unit |
| 29 |
|
|
! mass of ozone, corrected for chlorine content and latitude, but |
| 30 |
|
|
! not for temperature and sun direction, in s-1) |
| 31 |
|
|
|
| 32 |
|
|
!$omp threadprivate(c_Mob, a2, a4_mass, a6_mass, r_het_interm) |
| 33 |
|
|
|
| 34 |
|
|
contains |
| 35 |
|
|
|
| 36 |
|
✗ |
subroutine alloc_coefoz |
| 37 |
|
|
|
| 38 |
|
|
! This procedure is called once per run. |
| 39 |
|
|
! It allocates module variables. |
| 40 |
|
|
|
| 41 |
|
|
use dimphy, only: klon |
| 42 |
|
|
use mod_grid_phy_lmdz, only: nbp_lev |
| 43 |
|
|
|
| 44 |
|
|
! Variables local to the procedure: |
| 45 |
|
|
|
| 46 |
|
|
!--------------------------------------- |
| 47 |
|
|
|
| 48 |
|
|
!$omp master |
| 49 |
|
✗ |
print *, "Call sequence information: alloc_coefoz" |
| 50 |
|
|
!$omp end master |
| 51 |
|
✗ |
allocate(c_Mob(klon, nbp_lev), a2(klon, nbp_lev), a4_mass(klon, nbp_lev)) |
| 52 |
|
✗ |
allocate(a6_mass(klon, nbp_lev), r_het_interm(klon, nbp_lev)) |
| 53 |
|
|
|
| 54 |
|
✗ |
end subroutine alloc_coefoz |
| 55 |
|
|
|
| 56 |
|
|
!******************************************************* |
| 57 |
|
|
|
| 58 |
|
✗ |
subroutine regr_pr_comb_coefoz(julien, rlat, paprs, pplay) |
| 59 |
|
|
|
| 60 |
|
|
! "regr_pr_comb_coefoz" stands for "regrid pressure combine |
| 61 |
|
|
! coefficients ozone". |
| 62 |
|
|
|
| 63 |
|
|
! In this subroutine: |
| 64 |
|
|
! -- the master thread of the root process reads from a file all |
| 65 |
|
|
! eight coefficients for ozone chemistry, at the current day; |
| 66 |
|
|
! -- the coefficients are packed to the "physics" horizontal grid |
| 67 |
|
|
! and scattered to all threads of all processes; |
| 68 |
|
|
! -- in all the threads of all the processes, the coefficients are |
| 69 |
|
|
! regridded in pressure to the LMDZ vertical grid; |
| 70 |
|
|
! -- in all the threads of all the processes, the eight |
| 71 |
|
|
! coefficients are combined to define the five module variables. |
| 72 |
|
|
|
| 73 |
|
|
use netcdf95, only: nf95_open, nf95_close |
| 74 |
|
|
use netcdf, only: nf90_nowrite |
| 75 |
|
|
use assert_m, only: assert |
| 76 |
|
|
use dimphy, only: klon |
| 77 |
|
|
use mod_phys_lmdz_mpi_data, only: is_mpi_root |
| 78 |
|
|
use regr_pr_time_av_m, only: regr_pr_time_av |
| 79 |
|
|
use regr_pr_int_m, only: regr_pr_int |
| 80 |
|
|
use press_coefoz_m, only: press_in_edg, plev |
| 81 |
|
|
use mod_grid_phy_lmdz, only: nbp_lev |
| 82 |
|
|
|
| 83 |
|
|
integer, intent(in):: julien ! jour julien, 1 <= julien <= 360 |
| 84 |
|
|
|
| 85 |
|
|
REAL, intent(in):: rlat(:) |
| 86 |
|
|
! (latitude on the partial "physics" grid, in degrees) |
| 87 |
|
|
|
| 88 |
|
|
real, intent(in):: paprs(:, :) ! (klon, nbp_lev + 1) |
| 89 |
|
|
! (pression pour chaque inter-couche, en Pa) |
| 90 |
|
|
|
| 91 |
|
|
real, intent(in):: pplay(:, :) ! (klon, nbp_lev) |
| 92 |
|
|
! (pression pour le mileu de chaque couche, en Pa) |
| 93 |
|
|
|
| 94 |
|
|
! Variables local to the procedure: |
| 95 |
|
|
|
| 96 |
|
|
integer ncid ! for NetCDF |
| 97 |
|
|
|
| 98 |
|
✗ |
real coefoz(klon, nbp_lev, 7) |
| 99 |
|
|
! (temporary storage for 7 ozone coefficients) |
| 100 |
|
|
! (On the partial "physics" grid. |
| 101 |
|
|
! "coefoz(i, k, :)" is at longitude "rlon(i)", latitude "rlat(i)", |
| 102 |
|
|
! middle of layer "k".) |
| 103 |
|
|
|
| 104 |
|
|
real a6(klon, nbp_lev) |
| 105 |
|
|
! (derivative of "P_net_Mob" with respect to column-density of ozone |
| 106 |
|
|
! above, in cm2 s-1) |
| 107 |
|
|
! (On the partial "physics" grid. |
| 108 |
|
|
! "a6(i, k)" is at longitude "rlon(i)", latitude "rlat(i)", |
| 109 |
|
|
! middle of layer "k".) |
| 110 |
|
|
|
| 111 |
|
|
real, parameter:: amu = 1.6605402e-27 ! atomic mass unit, in kg |
| 112 |
|
|
|
| 113 |
|
|
real, parameter:: Clx = 3.8e-9 |
| 114 |
|
|
! (total chlorine content in the upper stratosphere) |
| 115 |
|
|
|
| 116 |
|
|
integer k |
| 117 |
|
|
|
| 118 |
|
|
!------------------------------------ |
| 119 |
|
|
|
| 120 |
|
|
!!print *, "Call sequence information: regr_pr_comb_coefoz" |
| 121 |
|
|
call assert((/size(rlat), size(paprs, 1), size(pplay, 1)/) == klon, & |
| 122 |
|
✗ |
"regr_pr_comb_coefoz klon") |
| 123 |
|
|
call assert((/size(paprs, 2) - 1, size(pplay, 2)/) == nbp_lev, & |
| 124 |
|
✗ |
"regr_pr_comb_coefoz nbp_lev") |
| 125 |
|
|
|
| 126 |
|
|
!$omp master |
| 127 |
|
✗ |
if (is_mpi_root) call nf95_open("coefoz_LMDZ.nc", nf90_nowrite, ncid) |
| 128 |
|
|
!$omp end master |
| 129 |
|
|
|
| 130 |
|
|
call regr_pr_time_av(ncid, (/"a2 ", "a4 ", "a6 ", & |
| 131 |
|
|
"P_net_Mob ", "r_Mob ", "temp_Mob ", "R_Het "/), & |
| 132 |
|
✗ |
REAL(julien-1), 'I', press_in_edg, paprs, coefoz) |
| 133 |
|
✗ |
a2 = coefoz(:, :, 1) |
| 134 |
|
✗ |
a4_mass = coefoz(:, :, 2) * 48. / 29. |
| 135 |
|
|
|
| 136 |
|
|
! Compute "a6_mass" avoiding underflow, do not divide by 1e4 |
| 137 |
|
|
! before dividing by molecular mass: |
| 138 |
|
✗ |
a6_mass = coefoz(:, :, 3) / (1e4 * 29. * amu) |
| 139 |
|
|
! (factor 1e4: conversion from cm2 to m2) |
| 140 |
|
|
|
| 141 |
|
|
! We can overwrite "coefoz(:, :, 1)", which was saved to "a2": |
| 142 |
|
|
call regr_pr_int(ncid, "Sigma_Mob", julien, plev, pplay, top_value=0., & |
| 143 |
|
✗ |
v3=coefoz(:, :, 1)) |
| 144 |
|
|
|
| 145 |
|
|
! Combine coefficients to get "c_Mob": |
| 146 |
|
|
c_mob = (coefoz(:, :, 4) - a2 * coefoz(:, :, 5) & |
| 147 |
|
|
- coefoz(:, :, 3) * coefoz(:, :, 1)) * 48. / 29. & |
| 148 |
|
✗ |
- a4_mass * coefoz(:, :, 6) |
| 149 |
|
|
|
| 150 |
|
✗ |
r_het_interm = coefoz(:, :, 7) |
| 151 |
|
|
! Heterogeneous chemistry is only at high latitudes: |
| 152 |
|
✗ |
forall (k = 1: nbp_lev) |
| 153 |
|
|
where (abs(rlat) <= 45.) r_het_interm(:, k) = 0. |
| 154 |
|
|
end forall |
| 155 |
|
|
r_het_interm = r_het_interm * (Clx / 3.8e-9)**2 |
| 156 |
|
|
|
| 157 |
|
|
!$omp master |
| 158 |
|
✗ |
if (is_mpi_root) call nf95_close(ncid) |
| 159 |
|
|
!$omp end master |
| 160 |
|
|
|
| 161 |
|
✗ |
end subroutine regr_pr_comb_coefoz |
| 162 |
|
|
|
| 163 |
|
|
end module regr_pr_comb_coefoz_m |
| 164 |
|
|
|