source: LMDZ4/tags/Merge_V3_conv/libf/phylmd/readsulfate.F

Last change on this file was 766, checked in by Laurent Fairhead, 17 years ago

Merge entre la version V3_conv et le HEAD
YM, JG, LF

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.5 KB
Line 
1!
2! $Header$
3!
4      SUBROUTINE readsulfate (r_day, first, sulfate_p)
5      USE dimphy, klon=>klon2,klon2=>klon
6      IMPLICIT none
7     
8c Content:
9c --------
10c This routine reads in monthly mean values of sulfate aerosols and
11c returns a linearly interpolated dayly-mean field.     
12c
13c
14c Author:
15c -------
16c Johannes Quaas (quaas@lmd.jussieu.fr)
17c 26/04/01
18c
19c Modifications:
20c --------------
21c 21/06/01: Make integrations of more than one year possible ;-)     
22c           ATTENTION!! runs are supposed to start with Jan, 1. 1930
23c                       (rday=1)     
24c
25c 27/06/01: Correction: The model always has 360 days per year!
26c 27/06/01: SO4 concentration rather than mixing ratio     
27c 27/06/01: 10yr-mean-values to interpolate     
28c 20/08/01: Correct the error through integer-values in interpolations     
29c 21/08/01: Introduce flag to read in just one decade
30c     
31c Include-files:
32c --------------     
33#include "YOMCST.h"
34#include "chem.h"     
35#include "dimensions.h"     
36cym#include "dimphy.h"     
37#include "temps.h"     
38c
39c Input:
40c ------
41      REAL*8  r_day                   ! Day of integration
42      LOGICAL first                 ! First timestep
43                                    ! (and therefore initialization necessary)
44c     
45c Output:     
46c -------     
47      REAL*8  sulfate_p(klon_omp,klev)
48      REAL*8  sulfate (klon, klev)  ! Mass of sulfate (monthly mean data,
49                                  !  from file) [ug SO4/m3]
50      REAL*8,SAVE,ALLOCATABLE :: sulfate_mpi(:,:)
51c     
52c Local Variables:
53c ----------------     
54      INTEGER i, ig, k, it
55      INTEGER j, iday, ny, iyr, iyr1, iyr2
56      parameter (ny=jjm+1)
57     
58      INTEGER ismaller
59CJLD      INTEGER idec1, idec2 ! The two decadal data read ini
60      CHARACTER*4 cyear
61     
62      INTEGER im, day1, day2, im2
63      REAL*8 so4_1(iim, jjm+1, klev, 12)
64      REAL*8 so4_2(iim, jjm+1, klev, 12)   ! The sulfate distributions
65     
66cym      REAL*8 so4(klon, klev, 12)  ! SO4 in right dimension
67cym      SAVE so4
68cym      REAL*8 so4_out(klon, klev)
69cym      SAVE so4_out
70
71      REAL*8,allocatable,save :: so4(:, :, :)  ! SO4 in right dimension
72      REAL*8,allocatable,save :: so4_out(:, :)
73c$OMP THREADPRIVATE(so4,so4_out)
74     
75      LOGICAL lnewday
76      LOGICAL lonlyone
77      PARAMETER (lonlyone=.FALSE.)
78      logical,save :: first2=.true.
79c$OMP THREADPRIVATE(first2)
80
81c$OMP MASTER
82      if (first2) then
83     
84        allocate( so4(klon, klev, 12) )
85        allocate( so4_out(klon, klev))
86        allocate(sulfate_mpi(klon_mpi,klev)) 
87        first2=.false.
88       
89      endif
90
91      if (phy_rank==0) then
92           
93      iday = INT(r_day)
94     
95      ! Get the year of the run
96      iyr  = iday/360
97     
98      ! Get the day of the actual year:
99      iday = iday-iyr*360
100     
101      ! 0.02 is about 0.5/24, namly less than half an hour
102      lnewday = (r_day-FLOAT(iday).LT.0.02)
103     
104! ---------------------------------------------
105! All has to be done only, if a new day begins!       
106! ---------------------------------------------
107
108      IF (lnewday.OR.first) THEN
109         
110      im = iday/30 +1 ! the actual month
111      ! annee_ref is the initial year (defined in temps.h)
112      iyr = iyr + annee_ref
113     
114      ! Do I have to read new data? (Is this the first day of a year?)
115      IF (first.OR.iday.EQ.1.) THEN
116      ! Initialize values
117      DO it=1,12
118      DO k=1,klev
119         DO i=1,klon
120            so4(i,k,it)=0.
121         ENDDO
122      ENDDO
123      ENDDO
124
125
126      IF (iyr .lt. 1850) THEN
127         cyear='.nat'
128         WRITE(*,*) 'getso4  iyr=', iyr,'   ',cyear
129         CALL getso4fromfile(cyear, so4_1)
130      ELSE IF (iyr .ge. 2100) THEN
131         cyear='2100'
132         WRITE(*,*) 'getso4  iyr=', iyr,'   ',cyear
133         CALL getso4fromfile(cyear, so4_1)
134      ELSE
135
136        ! Read in data:
137      ! a) from actual 10-yr-period
138
139      IF (iyr.LT.1900) THEN
140         iyr1 = 1850
141         iyr2 = 1900
142      ELSE IF (iyr.ge.1900.and.iyr.lt.1920) THEN
143         iyr1 = 1900
144         iyr2 = 1920
145      ELSE
146         iyr1 = INT(iyr/10)*10
147         iyr2 = INT(1+iyr/10)*10
148      ENDIF
149      WRITE(cyear,'(I4)') iyr1
150      WRITE(*,*) 'getso4  iyr=', iyr,'   ',cyear
151      CALL getso4fromfile(cyear, so4_1)
152
153     
154      ! If to read two decades:
155      IF (.NOT.lonlyone) THEN
156         
157      ! b) from the next following one
158      WRITE(cyear,'(I4)') iyr2
159      WRITE(*,*) 'getso4  iyr=', iyr,'   ',cyear
160      CALL getso4fromfile(cyear, so4_2)
161
162      ENDIF
163 
164      ! Interpolate linarily to the actual year:
165      DO it=1,12
166         DO k=1,klev
167            DO j=1,jjm
168               DO i=1,iim
169                  so4_1(i,j,k,it)=so4_1(i,j,k,it)
170     .                 - FLOAT(iyr-iyr1)/FLOAT(iyr2-iyr1)
171     .                 * (so4_1(i,j,k,it) - so4_2(i,j,k,it))
172               ENDDO
173            ENDDO
174         ENDDO
175      ENDDO                           
176     
177      ENDIF !lonlyone
178     
179      ! Transform the horizontal 2D-field into the physics-field
180      ! (Also the levels and the latitudes have to be inversed)
181     
182      DO it=1,12
183      DO k=1, klev         
184         ! a) at the poles, use the zonal mean:
185         DO i=1,iim
186            ! North pole
187            so4(1,k,it)=so4(1,k,it)+so4_1(i,jjm+1,klev+1-k,it)
188            ! South pole
189            so4(klon,k,it)=so4(klon,k,it)+so4_1(i,1,klev+1-k,it)
190         ENDDO
191         so4(1,k,it)=so4(1,k,it)/FLOAT(iim)
192         so4(klon,k,it)=so4(klon,k,it)/FLOAT(iim)
193     
194         ! b) the values between the poles:
195         ig=1
196         DO j=2,jjm
197            DO i=1,iim
198               ig=ig+1
199               if (ig.gt.klon) write (*,*) 'shit'
200               so4(ig,k,it) = so4_1(i,jjm+1-j,klev+1-k,it)
201            ENDDO
202         ENDDO
203         IF (ig.NE.klon-1) STOP 'Error in readsulfate (var conversion)'
204      ENDDO ! Loop over k (vertical)
205      ENDDO ! Loop over it (months)
206               
207
208      ENDIF ! Had to read new data?
209     
210     
211      ! Interpolate to actual day:
212      IF (iday.LT.im*30-15) THEN         
213         ! in the first half of the month use month before and actual month
214         im2=im-1
215         day2 = im2*30-15
216         day1 = im2*30+15
217         IF (im2.LE.0) THEN
218            ! the month is january, thus the month before december
219            im2=12
220         ENDIF
221         DO k=1,klev
222            DO i=1,klon
223               sulfate(i,k) = so4(i,k,im2) 
224     .              - FLOAT(iday-day2)/FLOAT(day1-day2)
225     .              * (so4(i,k,im2) - so4(i,k,im))
226               IF (sulfate(i,k).LT.0.) THEN
227                  IF (iday-day2.LT.0.) write(*,*) 'iday-day2',iday-day2
228                  IF (so4(i,k,im2) - so4(i,k,im).LT.0.)
229     . write(*,*) 'so4(i,k,im2) - so4(i,k,im)',
230     . so4(i,k,im2) - so4(i,k,im)
231                  IF (day1-day2.LT.0.) write(*,*) 'day1-day2',day1-day2
232                  stop 'sulfate'
233               endif
234            ENDDO
235         ENDDO
236      ELSE
237         ! the second half of the month
238         im2=im+1
239         IF (im2.GT.12) THEN
240            ! the month is december, the following thus january
241            im2=1
242         ENDIF
243         day2 = im*30-15
244         day1 = im*30+15
245         DO k=1,klev
246            DO i=1,klon
247               sulfate(i,k) = so4(i,k,im2) 
248     .              - FLOAT(iday-day2)/FLOAT(day1-day2)
249     .              * (so4(i,k,im2) - so4(i,k,im))
250               IF (sulfate(i,k).LT.0.) THEN
251                  IF (iday-day2.LT.0.) write(*,*) 'iday-day2',iday-day2
252                  IF (so4(i,k,im2) - so4(i,k,im).LT.0.)
253     . write(*,*) 'so4(i,k,im2) - so4(i,k,im)',
254     . so4(i,k,im2) - so4(i,k,im)
255                  IF (day1-day2.LT.0.) write(*,*) 'day1-day2',day1-day2
256                  stop 'sulfate'
257               endif
258            ENDDO
259         ENDDO
260      ENDIF
261
262     
263CJLD      ! The sulfate concentration [molec cm-3] is read in.
264CJLD      ! Convert it into mass [ug SO4/m3]
265CJLD      ! masse_so4 in [g/mol], n_avogadro in [molec/mol]
266      ! The sulfate mass [ug SO4/m3] is read in.
267      DO k=1,klev
268         DO i=1,klon
269CJLD            sulfate(i,k) = sulfate(i,k)*masse_so4
270CJLD     .           /n_avogadro*1.e+12
271            so4_out(i,k) = sulfate(i,k)
272            IF (so4_out(i,k).LT.0)
273     .          stop 'WAS SOLL DER SCHEISS ? '
274         ENDDO
275      ENDDO
276      ELSE ! if no new day, use old data:
277      DO k=1,klev
278         DO i=1,klon
279            sulfate(i,k) = so4_out(i,k)
280            IF (so4_out(i,k).LT.0)
281     .          stop 'WAS SOLL DER SCHEISS ? '
282         ENDDO
283      ENDDO
284         
285
286      ENDIF ! Did I have to do anything (was it a new day?)
287
288      endif   ! phy_rank==0
289     
290      call ScatterField(real(sulfate),real(sulfate_mpi),klev)
291c$OMP END MASTER
292      call ScatterField_omp(real(sulfate_mpi),real(sulfate_p)
293     . ,klev)           
294
295      RETURN
296      END
297
298     
299     
300     
301     
302c-----------------------------------------------------------------------------
303c Read in /calculate pre-industrial values of sulfate     
304c-----------------------------------------------------------------------------
305     
306      SUBROUTINE readsulfate_preind (r_day, first, pi_sulfate_p)
307      USE dimphy, klon=>klon2,klon2=>klon
308      IMPLICIT none
309     
310c Content:
311c --------
312c This routine reads in monthly mean values of sulfate aerosols and
313c returns a linearly interpolated dayly-mean field.     
314c
315c It does so for the preindustriel values of the sulfate, to a large part
316c analogous to the routine readsulfate above.     
317c
318c Only Pb: Variables must be saved and don t have to be overwritten!
319c     
320c Author:
321c -------
322c Johannes Quaas (quaas@lmd.jussieu.fr)
323c 26/06/01
324c
325c Modifications:
326c --------------
327c see above
328c     
329c Include-files:
330c --------------     
331#include "YOMCST.h"
332#include "chem.h"     
333#include "dimensions.h"     
334cym#include "dimphy.h"     
335#include "temps.h"     
336c
337c Input:
338c ------
339      REAL*8  r_day                   ! Day of integration
340      LOGICAL first                 ! First timestep
341                                    ! (and therefore initialization necessary)
342c     
343c Output:     
344c -------     
345      REAL*8  pi_sulfate_p (klon_omp, klev) 
346                                 
347      REAL*8  pi_sulfate (klon, klev)  ! Number conc. sulfate (monthly mean data,
348                                  !  from fil
349      REAL*8,SAVE,ALLOCATABLE :: pi_sulfate_mpi(:,:)                     
350c     
351c Local Variables:
352c ----------------     
353      INTEGER i, ig, k, it
354      INTEGER j, iday, ny, iyr
355      parameter (ny=jjm+1)
356     
357      INTEGER im, day1, day2, im2, ismaller
358      REAL*8 pi_so4_1(iim, jjm+1, klev, 12)
359
360cym      REAL*8 pi_so4(klon, klev, 12)  ! SO4 in right dimension
361cym      SAVE pi_so4
362cym      REAL*8 pi_so4_out(klon, klev)
363cym      SAVE pi_so4_out
364
365      REAL*8,allocatable,save :: pi_so4(:, :, :)  ! SO4 in right dimension
366      REAL*8,allocatable,save :: pi_so4_out(:, :)
367c$OMP THREADPRIVATE(pi_so4,pi_so4_out)           
368     
369      CHARACTER*4 cyear
370      LOGICAL lnewday
371      logical,save :: first2=.true.
372c$OMP THREADPRIVATE(first2)
373
374c$OMP MASTER
375      if (first2) then
376     
377        allocate( pi_so4(klon, klev, 12) )
378        allocate( pi_so4_out(klon, klev))
379        allocate(pi_sulfate_mpi (klon_mpi, klev)) 
380        first2=.false.
381       
382      endif
383
384      if (phy_rank==0) then
385   
386     
387
388      iday = INT(r_day)
389     
390      ! Get the year of the run
391      iyr  = iday/360
392     
393      ! Get the day of the actual year:
394      iday = iday-iyr*360
395     
396      ! 0.02 is about 0.5/24, namly less than half an hour
397      lnewday = (r_day-FLOAT(iday).LT.0.02)
398     
399! ---------------------------------------------
400! All has to be done only, if a new day begins!       
401! ---------------------------------------------
402
403      IF (lnewday.OR.first) THEN
404         
405      im = iday/30 +1 ! the actual month
406     
407      ! annee_ref is the initial year (defined in temps.h)
408      iyr = iyr + annee_ref     
409     
410     
411      IF (first) THEN
412         cyear='.nat'
413         CALL getso4fromfile(cyear,pi_so4_1)
414
415               ! Transform the horizontal 2D-field into the physics-field
416               ! (Also the levels and the latitudes have to be inversed)
417
418         ! Initialize field
419         DO it=1,12
420            DO k=1,klev
421               DO i=1,klon
422                  pi_so4(i,k,it)=0.
423               ENDDO
424            ENDDO
425         ENDDO
426         
427         write (*,*) 'preind: finished reading', FLOAT(iim)
428      DO it=1,12
429      DO k=1, klev         
430         ! a) at the poles, use the zonal mean:
431         DO i=1,iim
432            ! North pole
433            pi_so4(1,k,it)=pi_so4(1,k,it)+pi_so4_1(i,jjm+1,klev+1-k,it)
434            ! South pole
435           pi_so4(klon,k,it)=pi_so4(klon,k,it)+pi_so4_1(i,1,klev+1-k,it)
436         ENDDO
437         pi_so4(1,k,it)=pi_so4(1,k,it)/FLOAT(iim)
438         pi_so4(klon,k,it)=pi_so4(klon,k,it)/FLOAT(iim)
439     
440         ! b) the values between the poles:
441         ig=1
442         DO j=2,jjm
443            DO i=1,iim
444               ig=ig+1
445               if (ig.gt.klon) write (*,*) 'shit'
446               pi_so4(ig,k,it) = pi_so4_1(i,jjm+1-j,klev+1-k,it)
447            ENDDO
448         ENDDO
449         IF (ig.NE.klon-1) STOP 'Error in readsulfate (var conversion)'
450      ENDDO ! Loop over k (vertical)
451      ENDDO ! Loop over it (months)
452
453      ENDIF                     ! Had to read new data?
454     
455     
456      ! Interpolate to actual day:
457      IF (iday.LT.im*30-15) THEN         
458         ! in the first half of the month use month before and actual month
459         im2=im-1
460         day1 = im2*30+15
461         day2 = im2*30-15
462         IF (im2.LE.0) THEN
463            ! the month is january, thus the month before december
464            im2=12
465         ENDIF
466         DO k=1,klev
467            DO i=1,klon
468               pi_sulfate(i,k) = pi_so4(i,k,im2) 
469     .              - FLOAT(iday-day2)/FLOAT(day1-day2)
470     .              * (pi_so4(i,k,im2) - pi_so4(i,k,im))
471               IF (pi_sulfate(i,k).LT.0.) THEN
472                  IF (iday-day2.LT.0.) write(*,*) 'iday-day2',iday-day2
473                  IF (pi_so4(i,k,im2) - pi_so4(i,k,im).LT.0.)
474     . write(*,*) 'pi_so4(i,k,im2) - pi_so4(i,k,im)',
475     . pi_so4(i,k,im2) - pi_so4(i,k,im)
476                  IF (day1-day2.LT.0.) write(*,*) 'day1-day2',day1-day2
477                  stop 'pi_sulfate'
478               endif
479            ENDDO
480         ENDDO
481      ELSE
482         ! the second half of the month
483         im2=im+1
484         day1 = im*30+15
485         IF (im2.GT.12) THEN
486            ! the month is december, the following thus january
487            im2=1
488         ENDIF
489         day2 = im*30-15
490         
491         DO k=1,klev
492            DO i=1,klon
493               pi_sulfate(i,k) = pi_so4(i,k,im2) 
494     .              - FLOAT(iday-day2)/FLOAT(day1-day2)
495     .              * (pi_so4(i,k,im2) - pi_so4(i,k,im))
496               IF (pi_sulfate(i,k).LT.0.) THEN
497                  IF (iday-day2.LT.0.) write(*,*) 'iday-day2',iday-day2
498                  IF (pi_so4(i,k,im2) - pi_so4(i,k,im).LT.0.)
499     . write(*,*) 'pi_so4(i,k,im2) - pi_so4(i,k,im)',
500     . pi_so4(i,k,im2) - pi_so4(i,k,im)
501                  IF (day1-day2.LT.0.) write(*,*) 'day1-day2',day1-day2
502                  stop 'pi_sulfate'
503               endif
504            ENDDO
505         ENDDO
506      ENDIF
507
508     
509CJLD      ! The sulfate concentration [molec cm-3] is read in.
510CJLD      ! Convert it into mass [ug SO4/m3]
511CJLD      ! masse_so4 in [g/mol], n_avogadro in [molec/mol]
512      DO k=1,klev
513         DO i=1,klon
514CJLD            pi_sulfate(i,k) = pi_sulfate(i,k)*masse_so4
515CJLD     .           /n_avogadro*1.e+12
516            pi_so4_out(i,k) = pi_sulfate(i,k)
517         ENDDO
518      ENDDO
519     
520      ELSE ! If no new day, use old data:
521      DO k=1,klev
522         DO i=1,klon
523            pi_sulfate(i,k) = pi_so4_out(i,k)           
524         ENDDO
525      ENDDO
526         
527
528      ENDIF ! Was this the beginning of a new day?
529
530      endif   ! phy_rank==0
531     
532      call ScatterField(real(pi_sulfate),real(pi_sulfate_mpi),klev)
533c$OMP END MASTER
534      call ScatterField_omp(real(pi_sulfate_mpi),real(pi_sulfate_p)
535     .,klev)           
536
537      RETURN
538      END
539
540     
541     
542     
543     
544     
545     
546     
547     
548     
549c-----------------------------------------------------------------------------
550c Routine for reading SO4 data from files
551c-----------------------------------------------------------------------------
552           
553
554      SUBROUTINE getso4fromfile (cyr, so4)
555#include "netcdf.inc"
556#include "dimensions.h"     
557#include "dimphy.h"
558      CHARACTER*15 fname
559      CHARACTER*4 cyr
560     
561      CHARACTER*6 cvar
562      INTEGER START(3), COUNT(3)
563      INTEGER  STATUS, NCID, VARID
564      INTEGER imth, i, j, k, ny
565      PARAMETER (ny=jjm+1)
566     
567           
568      REAL*8 so4mth(iim, ny, klev)
569c      REAL*8 so4mth(klev, ny, iim)
570      REAL*8 so4(iim, ny, klev, 12)
571
572 
573      fname = 'so4.run'//cyr//'.cdf'
574
575      write (*,*) 'reading ', fname
576      STATUS = NF_OPEN (fname, NF_NOWRITE, NCID)
577      IF (STATUS .NE. NF_NOERR) write (*,*) 'err in open ',status
578           
579      DO imth=1, 12
580         IF (imth.eq.1) THEN
581            cvar='SO4JAN'
582         ELSEIF (imth.eq.2) THEN
583            cvar='SO4FEB'
584         ELSEIF (imth.eq.3) THEN
585            cvar='SO4MAR'
586         ELSEIF (imth.eq.4) THEN
587            cvar='SO4APR'
588         ELSEIF (imth.eq.5) THEN
589            cvar='SO4MAY'
590         ELSEIF (imth.eq.6) THEN
591            cvar='SO4JUN'
592         ELSEIF (imth.eq.7) THEN
593            cvar='SO4JUL'
594         ELSEIF (imth.eq.8) THEN
595            cvar='SO4AUG'
596         ELSEIF (imth.eq.9) THEN
597            cvar='SO4SEP'
598         ELSEIF (imth.eq.10) THEN
599            cvar='SO4OCT'
600         ELSEIF (imth.eq.11) THEN
601            cvar='SO4NOV'
602         ELSEIF (imth.eq.12) THEN
603            cvar='SO4DEC'
604         ENDIF
605         start(1)=1
606         start(2)=1
607         start(3)=1
608         count(1)=iim
609         count(2)=ny
610         count(3)=klev
611c         write(*,*) 'here i am'
612         STATUS = NF_INQ_VARID (NCID, cvar, VARID)
613         write (*,*) ncid,imth,cvar, varid
614c         STATUS = NF_INQ_VARID (NCID, VARMONTHS(i), VARID(i))
615         IF (STATUS .NE. NF_NOERR) write (*,*) 'err in read ',status     
616         STATUS = NF_GET_VARA_DOUBLE
617     .    (NCID, VARID, START,COUNT, so4mth)
618         IF (STATUS .NE. NF_NOERR) write (*,*) 'err in read data',status
619         
620         DO k=1,klev
621            DO j=1,jjm+1
622               DO i=1,iim
623                  IF (so4mth(i,j,k).LT.0.) then
624                     write(*,*) 'this is shit'
625                     write(*,*) 'so4(',i,j,k,') =',so4mth(i,j,k)
626                  endif
627                  so4(i,j,k,imth)=so4mth(i,j,k)
628c                  so4(i,j,k,imth)=so4mth(k,j,i)
629               ENDDO
630            ENDDO
631         ENDDO
632      ENDDO
633     
634      STATUS = NF_CLOSE(NCID)
635      END ! subroutine getso4fromfile
636     
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
Note: See TracBrowser for help on using the repository browser.