source: LMDZ4/branches/LMDZ4V5.0-dev/libf/phylmd/o3_chem_m.F90 @ 5225

Last change on this file since 5225 was 1379, checked in by lguez, 15 years ago

Added optional ozone tracer with chemistry parameterized by Daniel
Cariolle. This tracer is passive: it has no influence on the rest of
the simulation.

Added variable "zmasse" in file "histrac.nc". Corrected long name of
variable "pplay" in "histrac.nc". Changed name of variable "t" to "T"
in "histrac.nc", corrected long name and unit.

In "phytrac", moved definition of "zmasse" toward the beginning of the
procedure, so that "zmasse" can be given as argument to
"traclmdz". Also added arguments "julien", "gmtime" and "xlon" to
"traclmdz". The four additional arguments are required for the ozone
tracer.

In module "traclmdz_mod", factorized declaration "implicit none" that
was in each procedure. There is now an equivalent single declaration
at the module level.

In procedure "traclmdz", removed variable "delp". Use "zmasse * rg"
instead since we now have "zmasse" as an argument.

Tests. Compilations on Brodie only, with optimization options "-debug"
and "-dev", parallelization options "none", "mpi", "omp" and
"mpi_omp", this revision and revision 1373. Run cases with and without
ozone tracer, 1 and 2 MPI processes, 1 and 2 OpenMP
threads. Comparisons of all cases are ok, except for strange
variations in variables "d_tr_cl_RN" and "d_tr_cl_PB" of file
"histrac.nc", variables "RN" and "PB" of "restart.nc", variables
"trs_RN" and "trs_PB" of "restartphy.nc". Relative variations of these
variables between cases are of order 1e-7 or less, after one day of
simulation.

File size: 5.3 KB
RevLine 
[1379]1! $Id$
2module o3_chem_m
3
4  IMPLICIT none
5
6  private o3_prod
7
8contains
9
10  subroutine o3_chem(julien, gmtime, t_seri, zmasse, pdtphys, rlat, rlon, q)
11
12    ! This procedure evolves the ozone mass fraction through a time
13    ! step taking only chemistry into account.
14
15    ! All the 2-dimensional arrays are on the partial "physics" grid.
16    ! Their shape is "(/klon, llm/)".
17    ! Index "(i, :)" is for longitude "rlon(i)", latitude "rlat(i)".
18
19    use assert_m, only: assert
20    use dimphy, only: klon
21    use regr_pr_comb_coefoz_m, only: c_Mob, a4_mass, a2, r_het_interm
22
23    integer, intent(in):: julien ! jour julien, 1 <= julien <= 360
24    real, intent(in):: gmtime ! heure de la journée en fraction de jour
25    real, intent(in):: t_seri(:, :) ! (klon, llm) temperature, in K
26
27    real, intent(in):: zmasse(:, :) ! (klon, llm)
28    ! (column-density of mass of air in a cell, in kg m-2)
29    ! "zmasse(:, k)" is for layer "k".)
30
31    real, intent(in):: pdtphys ! time step for physics, in s
32
33    REAL, intent(in):: rlat(:), rlon(:)
34    ! (longitude and latitude of each horizontal position, in degrees)
35
36    real, intent(inout):: q(:, :) ! (klon, llm) mass fraction of ozone
37    ! "q(:, k)" is at middle of layer "k".)
38
39    ! Variables local to the procedure:
40    include "dimensions.h"
41    include "comconst.h"
42    ! (for "pi")
43    integer k
44
45    real c(klon, llm)
46    ! (constant term during a time step in the net mass production
47    ! rate of ozone by chemistry, per unit mass of air, in s-1)
48    ! "c(:, k)" is at middle of layer "k".)
49
50    real b(klon, llm)
51    ! (coefficient of "q" in the net mass production
52    ! rate of ozone by chemistry, per unit mass of air, in s-1)
53    ! "b(:, k)" is at middle of layer "k".)
54
55    real dq_o3_chem(klon, llm)
56    ! (variation of ozone mass fraction due to chemistry during a time step)
57    ! "dq_o3_chem(:, k)" is at middle of layer "k".)
58
59    real earth_long
60    ! (longitude vraie de la Terre dans son orbite solaire, par
61    ! rapport au point vernal (21 mars), en degrés)
62
63    real pmu0(klon) ! mean of cosine of solar zenith angle during "pdtphys"
64    real trash1
65    real trash2(klon)
66
67    !-------------------------------------------------------------
68
69    call assert(klon == (/size(q, 1), size(t_seri, 1), size(zmasse, 1), &
70         size(rlat), size(rlon)/), "o3_chem klon")
71    call assert(llm == (/size(q, 2), size(t_seri, 2), size(zmasse, 2)/), &
72         "o3_chem llm")
73
74    c = c_Mob + a4_mass * t_seri
75
76    ! Compute coefficient "b":
77
78    ! Heterogeneous chemistry is only at low temperature:
79    where (t_seri < 195.)
80       b = r_het_interm
81    elsewhere
82       b = 0.
83    end where
84
85    ! Heterogeneous chemistry is only during daytime:
86    call orbite(real(julien), earth_long, trash1)
87    call zenang(earth_long, gmtime, pdtphys, rlat, rlon, pmu0, trash2)
88    forall (k = 1: llm)
89       where (pmu0 <= cos(87. / 180. * pi)) b(:, k) = 0.
90    end forall
91
92    b = b + a2
93
94    ! Midpoint method:
95
96    ! Trial step to the midpoint:
97    dq_o3_chem = o3_prod(q, zmasse, c, b) * pdtphys  / 2
98    ! "Real" step across the whole interval:
99    dq_o3_chem = o3_prod(q + dq_o3_chem, zmasse, c, b) * pdtphys
100    q = q + dq_o3_chem
101
102    ! Confine the mass fraction:
103    q = min(max(q, 0.), .01)
104
105  end subroutine o3_chem
106
107  !*************************************************
108
109  function o3_prod(q, zmasse, c, b)
110
111    ! This function computes the production rate of ozone by chemistry.
112
113    ! All the 2-dimensional arrays are on the partial "physics" grid.
114    ! Their shape is "(/klon, llm/)".
115    ! Index "(i, :)" is for longitude "rlon(i)", latitude "rlat(i)".
116
117    use regr_pr_comb_coefoz_m, only: a6_mass
118    use assert_m, only: assert
119    use dimphy, only: klon
120
121    real, intent(in):: q(:, :) ! mass fraction of ozone
122    ! "q(:, k)" is at middle of layer "k".)
123
124    real, intent(in):: zmasse(:, :)
125    ! (column-density of mass of air in a layer, in kg m-2)
126    ! ("zmasse(:, k)" is for layer "k".)
127
128    real, intent(in):: c(:, :)
129    ! (constant term during a time step in the net mass production
130    ! rate of ozone by chemistry, per unit mass of air, in s-1)
131    ! "c(:, k)" is at middle of layer "k".)
132
133    real, intent(in):: b(:, :)
134    ! (coefficient of "q" in the net mass production rate of ozone by
135    ! chemistry, per unit mass of air, in s-1)
136    ! ("b(:, k)" is at middle of layer "k".)
137
138    include "dimensions.h"
139
140    real o3_prod(klon, llm)
141    ! (net mass production rate of ozone by chemistry, per unit mass
142    ! of air, in s-1)
143    ! ("o3_prod(:, k)" is at middle of layer "k".)
144
145    ! Variables local to the procedure:
146
147    real sigma_mass(klon, llm)
148    ! (mass column-density of ozone above point, in kg m-2)
149    ! ("sigma_mass(:, k)" is at middle of layer "k".)
150
151    integer k
152
153    !-------------------------------------------------------------------
154
155    call assert(klon == (/size(q, 1), size(zmasse, 1), size(c, 1), &
156         size(b, 1)/), "o3_prod 1")
157    call assert(llm == (/size(q, 2), size(zmasse, 2), size(c, 2), &
158         size(b, 2)/), "o3_prod 2")
159
160    ! Compute the column-density above the base of layer
161    ! "k", and, as a first approximation, take it as column-density
162    ! above the middle of layer "k":
163    sigma_mass(:, llm) = zmasse(:, llm) * q(:, llm) ! top layer
164    do k =  llm - 1, 1, -1
165       sigma_mass(:, k) = sigma_mass(:, k+1) + zmasse(:, k) * q(:, k)
166    end do
167
168    o3_prod = c + b * q + a6_mass * sigma_mass
169
170  end function o3_prod
171
172end module o3_chem_m
Note: See TracBrowser for help on using the repository browser.