source: trunk/LMDZ.EARTH/libf/phylmd/regr_lat_time_climoz_m.F90 @ 357

Last change on this file since 357 was 52, checked in by aslmd, 14 years ago

chantier principal du commit
--- version LMDZ5 qui fonctionne pour tests geantes
--- prochaine etape, tests sur GNOME

M libf/dyn3dpar/comconst.h
M libf/dyn3dpar/conf_planete.F90
ajout du flux de chaleur intrinseque: ihf
[par defaut il est nul]

M libf/dyn3dpar/gcm.F
changements cosmetiques
[pour diff plus efficace avec version non par]

M libf/dyn3dpar/iniacademic.F
possibilites de variations latitudinales
de temperature plus originales
[seulement pour planet_type.eq."giant"]

M libf/dyn3dpar/leapfrog_p.F

  1. ajout d'une tendance causee par le flux de chaleur intrinseque

(seulement prise en compte si planet_type.eq."giant")

  1. correction bugs problematiques a la compilation et au run

--> probleme dans les boucles (l'indice etait llm et non l)
--> ajout de SAVE pour les variables paralleles
--> correction des declarations de variables manquantes

M libf/dyn3dpar/calfis_p.F
correction d'une deuxieme parenthese manquante sur ALLOCATE(zteta(klon,llm))

M libf/phylmd/regr_lat_time_climoz_m.F90
erreur a la compilation avec FCM... il s'agit d'une routine terrestre
il y a visiblement un probleme avec o3_in
en attendant, les lignes sont commentees avec !AS

A deftanks/giant 8 fichiers
ajout de fichiers de configuration typiques pour les geantes gazeuses
[experimental pour le moment... on est loin de jupiter]

--> comparaisons entre un run ancien [avec LMDZ5-dev sur SVN ipsl sans cp var]
et run avec version sur ce SVN planeto donne des resultats similaires

pratique

A ioipsl
A ioipsl/compile_ioipsl.bash
A ioipsl/util 16 fichiers
script et utilitaire pour compiler IOIPSL de facon independante
il suffit d'executer ./compile_ioipsl.bash

M arch/arch-AMD64_CICLAD.path
si IOIPSL a ete compile avec la methode precedente, les bons
PATH sont definis dans ce fichier [le NETCDF est aussi OK]

M 000-README-svn
mise a jour options "svn status"

M mars/libf/phymars/meso_callkeys.h
mise a jour mineure du fichier
[ecri_phys etait defini mais pas dans la liste]

File size: 16.7 KB
Line 
1! $Id$
2module regr_lat_time_climoz_m
3
4  ! Author: Lionel GUEZ
5
6  implicit none
7
8  private
9  public regr_lat_time_climoz
10
11contains
12
13  subroutine regr_lat_time_climoz(read_climoz)
14
15    ! "regr_lat_time_climoz" stands for "regrid latitude time
16    ! climatology ozone".
17
18    ! This procedure reads a climatology of ozone from a NetCDF file,
19    ! regrids it in latitude and time, and writes the regridded field
20    ! to a new NetCDF file.
21
22    ! The input field depends on time, pressure level and latitude.
23
24    ! If the input field has missing values, they must be signaled by
25    ! the "missing_value" attribute.
26
27    ! We assume that the input field is a step function of latitude
28    ! and that the input latitude coordinate gives the centers of steps.
29    ! Regridding in latitude is made by averaging, with a cosine of
30    ! latitude factor.
31    ! The target LMDZ latitude grid is the "scalar" grid: "rlatu".
32    ! The values of "rlatu" are taken to be the centers of intervals.
33
34    ! We assume that in the input file:
35
36    ! -- Latitude is in degrees.
37
38    ! -- Latitude and pressure are strictly monotonic (as all NetCDF
39    ! coordinate variables should be).
40
41    ! -- The time coordinate is in ascending order (even though we do
42    ! not use its values).
43    ! The input file may contain either values for 12 months or values
44    ! for 14 months.
45    ! If there are 14 months then we assume that we have (in that order):
46    ! December, January, February, ..., November, December, January
47
48    ! -- Missing values are contiguous, at the bottom of
49    ! the vertical domain and at the latitudinal boundaries.
50
51    ! If values are all missing at a given latitude and date, then we
52    ! replace those missing values by values at the closest latitude,
53    ! equatorward, with valid values.
54    ! Then, at each latitude and each date, the missing values are replaced
55    ! by the lowest valid value above missing values.
56
57    ! Regridding in time is by linear interpolation.
58    ! Monthly values are processed to get daily values, on the basis
59    ! of a 360-day calendar.
60    ! If there are 14 months, we use the first December value to
61    ! interpolate values between January 1st and mid-January.
62    ! We use the last January value to interpolate values between
63    ! mid-December and end of December.
64    ! If there are only 12 months in the input file then we assume
65    ! periodicity for interpolation at the beginning and at the end of the
66    ! year.
67
68    use regr1_step_av_m, only: regr1_step_av
69    use regr3_lint_m, only: regr3_lint
70    use netcdf95, only: handle_err, nf95_close, nf95_get_att, nf95_gw_var, &
71         nf95_inq_dimid, nf95_inq_varid, nf95_inquire_dimension, nf95_open, &
72         nf95_put_var
73    use netcdf, only: nf90_get_att, nf90_get_var, nf90_noerr, nf90_nowrite
74    use assert_m, only: assert
75
76    integer, intent(in):: read_climoz ! read ozone climatology
77    ! Allowed values are 1 and 2
78    ! 1: read a single ozone climatology that will be used day and night
79    ! 2: read two ozone climatologies, the average day and night
80    ! climatology and the daylight climatology
81
82    ! Variables local to the procedure:
83
84    include "dimensions.h"
85    ! (for "jjm")
86    include "paramet.h"
87    ! (for the other included files)
88    include "comgeom2.h"
89    ! (for "rlatv")
90    include "comconst.h"
91    ! (for "pi")
92
93    integer n_plev ! number of pressure levels in the input data
94    integer n_lat ! number of latitudes in the input data
95    integer n_month ! number of months in the input data
96
97    real, pointer:: latitude(:)
98    ! (of input data, converted to rad, sorted in strictly ascending order)
99
100    real, allocatable:: lat_in_edg(:)
101    ! (edges of latitude intervals for input data, in rad, in strictly
102    ! ascending order)
103
104    real, pointer:: plev(:)
105    ! pressure levels of input data, sorted in strictly ascending
106    ! order, converted to hPa
107
108    logical desc_lat ! latitude in descending order in the input file
109    logical desc_plev ! pressure levels in descending order in the input file
110
111    real, allocatable:: o3_in(:, :, :, :)
112    ! (n_lat, n_plev, n_month, read_climoz)
113    ! ozone climatologies from the input file
114    ! "o3_in(j, k, :, :)" is at latitude "latitude(j)" and pressure
115    ! level "plev(k)".
116    ! Third dimension is month index, first value may be December or January.
117    ! "o3_in(:, :, :, 1)" is for the day- night average, "o3_in(:, :, :, 2)"
118    ! is for daylight.
119
120    real missing_value
121
122    real, allocatable:: o3_regr_lat(:, :, :, :)
123    ! (jjm + 1, n_plev, 0:13, read_climoz)
124    ! mean of "o3_in" over a latitude interval of LMDZ
125    ! First dimension is latitude interval.
126    ! The latitude interval for "o3_regr_lat(j,:, :, :)" contains "rlatu(j)".
127    ! If "j" is between 2 and "jjm" then the interval is:
128    ! [rlatv(j), rlatv(j-1)]
129    ! If "j" is 1 or "jjm + 1" then the interval is:
130    ! [rlatv(1), pi / 2]
131    ! or:
132    ! [- pi / 2, rlatv(jjm)]
133    ! respectively.
134    ! "o3_regr_lat(:, k, :, :)" is for pressure level "plev(k)".
135    ! Third dimension is month number, 1 for January.
136    ! "o3_regr_lat(:, :, :, 1)" is average day and night,
137    ! "o3_regr_lat(:, :, :, 2)" is for daylight.
138
139    real, allocatable:: o3_out(:, :, :, :)
140    ! (jjm + 1, n_plev, 360, read_climoz)
141    ! regridded ozone climatology
142    ! "o3_out(j, k, l, :)" is at latitude "rlatu(j)", pressure
143    ! level "plev(k)" and date "January 1st 0h" + "tmidday(l)", in a
144    ! 360-day calendar.
145    ! "o3_out(:, :, :, 1)" is average day and night,
146    ! "o3_out(:, :, :, 2)" is for daylight.
147
148    integer j, k, l,m
149
150    ! For NetCDF:
151    integer ncid_in, ncid_out ! IDs for input and output files
152    integer varid_plev, varid_time, varid, ncerr, dimid
153    character(len=80) press_unit ! pressure unit
154
155    integer varid_in(read_climoz), varid_out(read_climoz)
156    ! index 1 is for average ozone day and night, index 2 is for
157    ! daylight ozone.
158
159    real, parameter:: tmidmonth(0:13) = (/(-15. + 30. * l, l = 0, 13)/)
160    ! (time to middle of month, in days since January 1st 0h, in a
161    ! 360-day calendar)
162    ! (We add values -15 and 375 so that, for example, day 3 of the year is
163    ! interpolated between the December and the January value.)
164
165    real, parameter:: tmidday(360) = (/(l + 0.5, l = 0, 359)/)
166    ! (time to middle of day, in days since January 1st 0h, in a
167    ! 360-day calendar)
168
169    !---------------------------------
170
171    print *, "Call sequence information: regr_lat_time_climoz"
172    call assert(read_climoz == 1 .or. read_climoz == 2, "regr_lat_time_climoz")
173
174    call nf95_open("climoz.nc", nf90_nowrite, ncid_in)
175
176    ! Get coordinates from the input file:
177
178    call nf95_inq_varid(ncid_in, "latitude", varid)
179    call nf95_gw_var(ncid_in, varid, latitude)
180    ! Convert from degrees to rad, because we will take the sine of latitude:
181    latitude = latitude / 180. * pi
182    n_lat = size(latitude)
183    ! We need to supply the latitudes to "regr1_step_av" in
184    ! ascending order, so invert order if necessary:
185    desc_lat = latitude(1) > latitude(n_lat)
186    if (desc_lat) latitude = latitude(n_lat:1:-1)
187
188    ! Compute edges of latitude intervals:
189    allocate(lat_in_edg(n_lat + 1))
190    lat_in_edg(1) = - pi / 2
191    forall (j = 2:n_lat) lat_in_edg(j) = (latitude(j - 1) + latitude(j)) / 2
192    lat_in_edg(n_lat + 1) = pi / 2
193    deallocate(latitude) ! pointer
194
195    call nf95_inq_varid(ncid_in, "plev", varid)
196    call nf95_gw_var(ncid_in, varid, plev)
197    n_plev = size(plev)
198    ! We only need the pressure coordinate to copy it to the output file.
199    ! The program "gcm" will assume that pressure levels are in
200    ! ascending order in the regridded climatology so invert order if
201    ! necessary:
202    desc_plev = plev(1) > plev(n_plev)
203    if (desc_plev) plev = plev(n_plev:1:-1)
204    call nf95_get_att(ncid_in, varid, "units", press_unit)
205    if (press_unit == "Pa") then
206       ! Convert to hPa:
207       plev = plev / 100.
208    elseif (press_unit /= "hPa") then
209       print *, "regr_lat_time_climoz: the only recognized units are Pa " &
210            // "and hPa."
211       stop 1
212    end if
213
214    ! Create the output file and get the variable IDs:
215    call prepare_out(ncid_in, n_plev, ncid_out, varid_out, varid_plev, &
216         varid_time)
217
218    ! Write remaining coordinate variables:
219    call nf95_put_var(ncid_out, varid_plev, plev)
220    call nf95_put_var(ncid_out, varid_time, tmidday)
221
222    deallocate(plev) ! pointer
223
224    ! Get the  number of months:
225    call nf95_inq_dimid(ncid_in, "time", dimid)
226    call nf95_inquire_dimension(ncid_in, dimid, len=n_month)
227
228    allocate(o3_in(n_lat, n_plev, n_month, read_climoz))
229
230    call nf95_inq_varid(ncid_in, "tro3", varid_in(1))
231    ncerr = nf90_get_var(ncid_in, varid_in(1), o3_in(:, :, :, 1))
232    call handle_err("regr_lat_time_climoz nf90_get_var tro3", ncerr, ncid_in)
233
234    if (read_climoz == 2) then
235       call nf95_inq_varid(ncid_in, "tro3_daylight", varid_in(2))
236       ncerr = nf90_get_var(ncid_in, varid_in(2), o3_in(:, :, :, 2))
237       call handle_err("regr_lat_time_climoz nf90_get_var tro3_daylight", &
238            ncerr, ncid_in, varid_in(2))
239    end if
240
241    !!!! Aymeric; problem with compilation here.... pb with o3_in
242    !AS if (desc_lat) o3_in = o3_in(n_lat:1:-1, :, :, :)
243    !AS if (desc_plev) o3_in = o3_in(:, n_plev:1:-1, :, :)
244
245    do m = 1, read_climoz
246       ncerr = nf90_get_att(ncid_in, varid_in(m), "missing_value", &
247            missing_value)
248       if (ncerr == nf90_noerr) then
249          do l = 1, n_month
250             ! Take care of latitudes where values are all missing:
251
252             ! Next to the south pole:
253             j = 1
254!AS             do while (o3_in(j, 1, l, m) == missing_value)
255!AS                j = j + 1
256!AS             end do
257!AS             if (j > 1) o3_in(:j-1, :, l, m) = &
258!AS                  spread(o3_in(j, :, l, m), dim=1, ncopies=j-1)
259             
260             ! Next to the north pole:
261             j = n_lat
262!AS             do while (o3_in(j, 1, l, m) == missing_value)
263!AS                j = j - 1
264!AS             end do
265!AS             if (j < n_lat) o3_in(j+1:, :, l, m) = &
266!AS                  spread(o3_in(j, :, l, m), dim=1, ncopies=n_lat-j)
267
268             ! Take care of missing values at high pressure:
269             do j = 1, n_lat
270                ! Find missing values, starting from top of atmosphere
271                ! and going down.
272                ! We have already taken care of latitudes full of
273                ! missing values so the highest level has a valid value.
274                k = 2
275!AS                do while  (o3_in(j, k, l, m) /= missing_value .and. k < n_plev)
276!AS                   k = k + 1
277!AS                end do
278                ! Replace missing values with the valid value at the
279                ! lowest level above missing values:
280!AS                if (o3_in(j, k, l, m) == missing_value) &
281!AS                     o3_in(j, k:n_plev, l, m) = o3_in(j, k-1, l, m)
282             end do
283          end do
284       else
285          print *, "regr_lat_time_climoz: field ", m, &
286               ", no missing value attribute"
287       end if
288    end do
289
290    call nf95_close(ncid_in)
291
292    allocate(o3_regr_lat(jjm + 1, n_plev, 0:13, read_climoz))
293    allocate(o3_out(jjm + 1, n_plev, 360, read_climoz))
294
295    ! Regrid in latitude:
296    ! We average with respect to sine of latitude, which is
297    ! equivalent to weighting by cosine of latitude:
298    if (n_month == 12) then
299       print *, &
300            "Found 12 months in ozone climatologies, assuming periodicity..."
301!AS       o3_regr_lat(jjm+1:1:-1, :, 1:12, :) = regr1_step_av(o3_in, &
302!AS            xs=sin(lat_in_edg), xt=sin((/- pi / 2, rlatv(jjm:1:-1), pi / 2/)))
303       ! (invert order of indices in "o3_regr_lat" because "rlatu" is
304       ! in descending order)
305
306       ! Duplicate January and December values, in preparation of time
307       ! interpolation:
308       o3_regr_lat(:, :, 0, :) = o3_regr_lat(:, :, 12, :)
309       o3_regr_lat(:, :, 13, :) = o3_regr_lat(:, :, 1, :)
310    else
311       print *, "Using 14 months in ozone climatologies..."
312!AS       o3_regr_lat(jjm+1:1:-1, :, :, :) = regr1_step_av(o3_in, &
313!AS            xs=sin(lat_in_edg), xt=sin((/- pi / 2, rlatv(jjm:1:-1), pi / 2/)))
314       ! (invert order of indices in "o3_regr_lat" because "rlatu" is
315       ! in descending order)
316    end if
317
318    ! Regrid in time by linear interpolation:
319    o3_out = regr3_lint(o3_regr_lat, tmidmonth, tmidday)
320
321    ! Write to file:
322    do m = 1, read_climoz
323       call nf95_put_var(ncid_out, varid_out(m), o3_out(jjm+1:1:-1, :, :, m))
324       ! (The order of "rlatu" is inverted in the output file)
325    end do
326
327    call nf95_close(ncid_out)
328
329  end subroutine regr_lat_time_climoz
330
331  !********************************************
332
333  subroutine prepare_out(ncid_in, n_plev, ncid_out, varid_out, varid_plev, &
334       varid_time)
335
336    ! This subroutine creates the NetCDF output file, defines
337    ! dimensions and variables, and writes one of the coordinate variables.
338
339    use netcdf95, only: nf95_create, nf95_def_dim, nf95_def_var, &
340         nf95_put_att, nf95_enddef, nf95_copy_att, nf95_put_var
341    use netcdf, only: nf90_clobber, nf90_float, nf90_global
342
343    integer, intent(in):: ncid_in, n_plev
344    integer, intent(out):: ncid_out, varid_plev, varid_time
345
346    integer, intent(out):: varid_out(:) ! dim(1 or 2)
347    ! "varid_out(1)" is for average ozone day and night,
348    ! "varid_out(2)" is for daylight ozone.
349
350    ! Variables local to the procedure:
351
352    include "dimensions.h"
353    ! (for "jjm")
354    include "paramet.h"
355    ! (for the other included files)
356    include "comgeom2.h"
357    ! (for "rlatu")
358    include "comconst.h"
359    ! (for "pi")
360
361    integer ncerr
362    integer dimid_rlatu, dimid_plev, dimid_time
363    integer varid_rlatu
364
365    !---------------------------
366
367    print *, "Call sequence information: prepare_out"
368
369    call nf95_create("climoz_LMDZ.nc", nf90_clobber, ncid_out)
370
371    ! Dimensions:
372    call nf95_def_dim(ncid_out, "time", 360, dimid_time)
373    call nf95_def_dim(ncid_out, "plev", n_plev, dimid_plev)
374    call nf95_def_dim(ncid_out, "rlatu", jjm + 1, dimid_rlatu)
375
376    ! Define coordinate variables:
377
378    call nf95_def_var(ncid_out, "time", nf90_float, dimid_time, varid_time)
379    call nf95_put_att(ncid_out, varid_time, "units", "days since 2000-1-1")
380    call nf95_put_att(ncid_out, varid_time, "calendar", "360_day")
381    call nf95_put_att(ncid_out, varid_time, "standard_name", "time")
382
383    call nf95_def_var(ncid_out, "plev", nf90_float, dimid_plev, varid_plev)
384    call nf95_put_att(ncid_out, varid_plev, "units", "millibar")
385    call nf95_put_att(ncid_out, varid_plev, "standard_name", "air_pressure")
386    call nf95_put_att(ncid_out, varid_plev, "long_name", "air pressure")
387
388    call nf95_def_var(ncid_out, "rlatu", nf90_float, dimid_rlatu, varid_rlatu)
389    call nf95_put_att(ncid_out, varid_rlatu, "units", "degrees_north")
390    call nf95_put_att(ncid_out, varid_rlatu, "standard_name", "latitude")
391
392    ! Define the primary variables:
393
394    call nf95_def_var(ncid_out, "tro3", nf90_float, &
395         (/dimid_rlatu, dimid_plev, dimid_time/), varid_out(1))
396    call nf95_put_att(ncid_out, varid_out(1), "long_name", &
397         "ozone mole fraction")
398    call nf95_put_att(ncid_out, varid_out(1), "standard_name", &
399         "mole_fraction_of_ozone_in_air")
400
401    if (size(varid_out) == 2) then
402       call nf95_def_var(ncid_out, "tro3_daylight", nf90_float, &
403            (/dimid_rlatu, dimid_plev, dimid_time/), varid_out(2))
404       call nf95_put_att(ncid_out, varid_out(2), "long_name", &
405            "ozone mole fraction in daylight")
406    end if
407
408    ! Global attributes:
409
410    ! The following commands, copying attributes, may fail.
411    ! That is OK.
412    ! It should just mean that the attribute is not defined in the input file.
413
414    call nf95_copy_att(ncid_in, nf90_global, "Conventions", ncid_out, &
415         nf90_global, ncerr)
416    call handle_err_copy_att("Conventions")
417
418    call nf95_copy_att(ncid_in, nf90_global, "title", ncid_out, nf90_global, &
419         ncerr)
420    call handle_err_copy_att("title")
421
422    call nf95_copy_att(ncid_in, nf90_global, "institution", ncid_out, &
423         nf90_global, ncerr)
424    call handle_err_copy_att("institution")
425
426    call nf95_copy_att(ncid_in, nf90_global, "source", ncid_out, nf90_global, &
427         ncerr)
428    call handle_err_copy_att("source")
429
430    call nf95_put_att(ncid_out, nf90_global, "comment", "Regridded for LMDZ")
431
432    call nf95_enddef(ncid_out)
433
434    ! Write one of the coordinate variables:
435    call nf95_put_var(ncid_out, varid_rlatu, rlatu(jjm+1:1:-1) / pi * 180.)
436    ! (convert from rad to degrees and sort in ascending order)
437
438  contains
439
440    subroutine handle_err_copy_att(att_name)
441
442      use netcdf, only: nf90_noerr, nf90_strerror
443
444      character(len=*), intent(in):: att_name
445
446      !----------------------------------------
447
448      if (ncerr /= nf90_noerr) then
449         print *, "regr_lat_time_climoz_m prepare_out nf95_copy_att " &
450              // att_name // " -- " // trim(nf90_strerror(ncerr))
451      end if
452
453    end subroutine handle_err_copy_att
454
455  end subroutine prepare_out
456
457end module regr_lat_time_climoz_m
Note: See TracBrowser for help on using the repository browser.