source: trunk/LMDZ.GENERIC/libf/phystd/condense_cloud.F90 @ 848

Last change on this file since 848 was 787, checked in by aslmd, 12 years ago

LMDZ.GENERIC. (Sorry for long text but this is a quite major commit)

Paving the path for parallel computations. And moving towards a more flexible code.

Automatic allocation is used within all routines in phystd. No further mention to ngridmx and nqmx.

  1. ngridmx and nqmx are still used in LMDZ.GENERIC in the dyn3d part
  2. if the LMDZ4/LMDZ5 dynamical core is used, there is no more fixed dimensions ngridmx and nqmx --> a fully flexible parallel implementation is now possible (e.g. no need to recompile when changing numbers of processors)

The important stuff :

  • Compilation checked with ifort. OK with and without debug mode. No errors. Checked for: gcm, newstart, rcm1d, kcm1d
  • RUN GCM: Running an Earth test case. Comparison with previous revision --> debug mode : perfect match. bit by bit (diff command). checked with plots --> O1 mode : close match (checked with plots) --> O2 mode : sometimes up to 0.5 K departure.... BUT in this new version O2 and O1 are quite close while in previous version O1 and O2 differed by about, well, typically 0.5 K (pictures available on request)
  • RUN NEWSTART : perfect match (bit-by-bit) in either debug or normal mode.
  • RUN RCM1D : perfect match in normal mode.
  • RUN KCM1D : not tested (I don't know what is the use of kcm1d)

List of main changes :

  • Additional arguments to some subroutines (ngrid and nq)
  • F77 include strategy is obsolete and replaced by F90 module strategy In this new strategy arrays are allocatable and allocated once at first use This has to be done for all common featuring arrays defined with ngridmx or nqmx

surfdat.h >> surfdat_h.F90
tracer.h >> tracer_h.F90
comsaison.h >> comsaison_h.F90
comgeomfi.h >> comgeomfi_h.F90
comsoil.h >> comsoil_h.F90
comdiurn.h >> comdiurn_h.F90
fisice.h >> DELETED. was not used. probably a fossil.
watercap.h >> DELETED. variable put in surfdat_h.F90

  • F77 'save' strategy is obsolete and replaced by F90 'allocatable save' strategy (see previous point and e.g. new version of physiq.F90)
  • Suppressing any mention to advtrac.h which is a common in the dynamics and needs nqmx This was easily solved by adding an argument with tracer names, coming from the dynamics This is probably not a definitive solution, ... but this allows for generic physics to work easily with either LMDZ.GENERIC or LMDZ dynamical cores
  • Removing consistency tests between nq and nqmx ; and ngrid and ngridmx. No use now!
  • Adaptation of rcm1d, kcm1d, newstart given above-mentioned changes

A note on phyetat0 and soil_setting:

  • Now written so that a slice of horizontal size 'ngrid' starting at grid point 'cursor' is read in startfi.nc 'cursor' is defined in dimphys.h and initialized by inifis (or in newstart) this is useful for parallel computations. default behavior is the usual one : sequential runs, cursor is 1, size ngrid is the whole global domain

A note on an additional change :

  • nueffrad is now an argument to callcorrk as is the case for reffrad both are saved in physiq this is for consistency and lisibility (previously nueffrad was saved in callcorrk) ... but there is a call to a function which modifies nueffrad in physiq ... previously this was not modifying nueffrad (although it was quite cumbersome to detect this) ... to be conservative I kept this behaviour and highlighted it with an array nueffrad_dummy ... I added a comment because someone might want to change this
  • Property svn:executable set to *
File size: 16.7 KB
Line 
1      subroutine condense_cloud(ngrid,nlayer,nq,ptimestep, &
2          pcapcal,pplay,pplev,ptsrf,pt, &
3          pphi,pdt,pdu,pdv,pdtsrf,pu,pv,pq,pdq, &
4          piceco2,psolaralb,pemisurf, &
5          pdtc,pdtsrfc,pdpsrf,pduc,pdvc, &
6          pdqc,reffrad)
7
8      use radinc_h, only : naerkind
9      use gases_h
10      use radii_mod, only : co2_reffrad
11      use aerosol_mod, only : iaero_co2
12      USE surfdat_h
13      USE comgeomfi_h
14      USE tracer_h
15
16
17      implicit none
18
19!==================================================================
20!     Purpose
21!     -------
22!     Condense and/or sublime CO2 ice on the ground and in the
23!     atmosphere, and sediment the ice.
24
25!     Inputs
26!     ------
27!     ngrid                 Number of vertical columns
28!     nlayer                Number of layers
29!     pplay(ngrid,nlayer)   Pressure layers
30!     pplev(ngrid,nlayer+1) Pressure levels
31!     pt(ngrid,nlayer)      Temperature (in K)
32!     ptsrf(ngrid)          Surface temperature
33!     
34!     pdt(ngrid,nlayermx)   Time derivative before condensation/sublimation of pt
35!     pdtsrf(ngrid)         Time derivative before condensation/sublimation of ptsrf
36!     pqsurf(ngrid,nq)      Sedimentation flux at the surface (kg.m-2.s-1)
37!     
38!     Outputs
39!     -------
40!     pdpsrf(ngrid)         \  Contribution of condensation/sublimation
41!     pdtc(ngrid,nlayermx)  /  to the time derivatives of Ps, pt, and ptsrf
42!     pdtsrfc(ngrid)       /
43!     
44!     Both
45!     ----
46!     piceco2(ngrid)        CO2 ice at the surface (kg/m2)
47!     psolaralb(ngrid)      Albedo at the surface
48!     pemisurf(ngrid)       Emissivity of the surface
49!
50!     Authors
51!     -------
52!     Francois Forget (1996)
53!     Converted to Fortran 90 and slightly modified by R. Wordsworth (2009)
54!     Includes simplifed nucleation by J. Leconte (2011)
55!     
56!==================================================================
57
58#include "dimensions.h"
59#include "dimphys.h"
60#include "comcstfi.h"
61#include "comvert.h"
62#include "callkeys.h"
63
64!-----------------------------------------------------------------------
65!     Arguments
66
67      INTEGER ngrid, nlayer, nq
68
69      REAL ptimestep
70      REAL pplay(ngrid,nlayer),pplev(ngrid,nlayer+1)
71      REAL pcapcal(ngrid)
72      REAL pt(ngrid,nlayer)
73      REAL ptsrf(ngrid)
74      REAL pphi(ngrid,nlayer)
75      REAL pdt(ngrid,nlayer),pdtsrf(ngrid),pdtc(ngrid,nlayer)
76      REAL pdtsrfc(ngrid),pdpsrf(ngrid)
77!      REAL piceco2(ngrid),psolaralb(ngrid,2),pemisurf(ngrid)
78      REAL piceco2(ngrid),psolaralb(ngrid),pemisurf(ngrid)
79
80      REAL pu(ngrid,nlayer) ,  pv(ngrid,nlayer)
81      REAL pdu(ngrid,nlayer) , pdv(ngrid,nlayer)
82      REAL pduc(ngrid,nlayer) , pdvc(ngrid,nlayer)
83      REAL pq(ngrid,nlayer,nq),pdq(ngrid,nlayer,nq)
84      REAL pdqc(ngrid,nlayer,nq), pdqsc(ngrid,nq)
85
86      REAL reffrad(ngrid,nlayer,naerkind)
87
88
89
90!-----------------------------------------------------------------------
91!     Local variables
92
93      INTEGER l,ig,icap,ilay,it,iq
94
95      REAL*8 zt(ngrid,nlayermx)
96      REAL zq(ngrid,nlayermx,nq)
97      REAL zcpi
98      REAL ztcond (ngrid,nlayermx)
99      REAL ztnuc (ngrid,nlayermx)
100      REAL ztcondsol(ngrid)
101      REAL zdiceco2(ngrid)
102      REAL zcondicea(ngrid,nlayermx), zcondices(ngrid)
103      REAL zfallice(ngrid), Mfallice(ngrid)
104      REAL zmflux(nlayermx+1)
105      REAL zu(nlayermx),zv(nlayermx)
106      REAL ztsrf(ngrid)
107      REAL ztc(nlayermx), ztm(nlayermx+1)
108      REAL zum(nlayermx+1) , zvm(nlayermx+1)
109      LOGICAL condsub(ngrid)
110      REAL subptimestep
111      Integer Ntime
112      real masse (ngrid,nlayermx), w(ngrid,nlayermx,nq)
113      real wq(ngrid,nlayermx+1)
114      real vstokes,reff
115
116!     Special diagnostic variables
117      real tconda1(ngrid,nlayermx)
118      real tconda2(ngrid,nlayermx)
119      real zdtsig (ngrid,nlayermx)
120      real zdt (ngrid,nlayermx)
121
122!-----------------------------------------------------------------------
123!     Saved local variables
124
125      REAL latcond
126      REAL ccond
127      REAL cpice
128      REAL,SAVE,ALLOCATABLE,DIMENSION(:) :: emisref
129      SAVE cpice
130      SAVE latcond,ccond
131
132      LOGICAL firstcall
133      SAVE firstcall
134      REAL SSUM
135      EXTERNAL SSUM
136
137      DATA latcond /5.9e5/
138      DATA cpice /1000./
139      DATA firstcall/.true./
140
141      REAL CBRT
142      EXTERNAL CBRT
143
144      INTEGER,SAVE :: i_co2ice=0      ! co2 ice
145      CHARACTER(LEN=20) :: tracername ! to temporarily store text
146
147      integer igas
148      integer,save :: igasco2=0
149      character(len=3) :: gasname
150
151      real ppco2
152
153!-----------------------------------------------------------------------
154!     Initializations
155
156      call zerophys(ngrid*nlayer*nq,pdqc)
157      call zerophys(ngrid*nlayer*nq,pdtc)
158      call zerophys(ngrid*nlayermx*nq,zq)
159      call zerophys(ngrid*nlayermx,zt)
160
161!     Initialisation
162      IF (firstcall) THEN
163
164         ALLOCATE(emisref(ngrid)) !! this should be deallocated in lastcall...
165
166         ! find CO2 ice tracer
167         do iq=1,nq
168            tracername=noms(iq)
169            if (tracername.eq."co2_ice") then
170               i_co2ice=iq
171            endif
172         enddo
173         
174         ! find CO2 gas
175         do igas=1,ngasmx
176            gasname=gnom(igas)
177!            gasname=noms(igas) ! was a bug
178            if (gasname.eq."CO2") then
179               igasco2=igas
180            endif
181         enddo
182
183        write(*,*) "condense_cloud: i_co2ice=",i_co2ice       
184
185        if((i_co2ice.lt.1))then
186           print*,'In condens_cloud but no CO2 ice tracer, exiting.'
187           print*,'Still need generalisation to arbitrary species!'
188           stop
189        endif
190
191         ccond=cpp/(g*latcond)
192         print*,'In condens_cloud: ccond=',ccond,' latcond=',latcond
193
194!          Prepare special treatment if gas is not pure CO2
195             !if (addn2) then
196             !   m_co2   = 44.01E-3 ! CO2 molecular mass (kg/mol)   
197             !   m_noco2 = 28.02E-3 ! N2 molecular mass (kg/mol) 
198!               Compute A and B coefficient use to compute
199!               mean molecular mass Mair defined by
200!               1/Mair = q(ico2)/m_co2 + (1-q(ico2))/m_noco2
201!               1/Mair = A*q(ico2) + B
202             !   A = (1/m_co2 - 1/m_noco2)
203             !   B = 1/m_noco2
204             !endif
205
206!          Minimum CO2 mixing ratio below which mixing occurs with layer above:
207           !qco2min =0.75 
208
209           firstcall=.false.
210      ENDIF
211      zcpi=1./cpp
212
213!-----------------------------------------------------------------------
214!     Calculation of CO2 condensation / sublimation
215!
216!     Variables used:
217!     piceco2(ngrid)       amount of co2 ice on the ground  (kg/m2)
218!     zcondicea(ngrid,l)   condensation rate in layer l     (kg/m2/s)
219!     zcondices(ngrid)     condensation rate on the ground  (kg/m2/s)
220!     zfallice(ngrid)      flux of ice falling on surface   (kg/m2/s)
221!     pdtc(ngrid,nlayermx) dT/dt due to phase changes       (K/s)
222     
223
224!     Tendencies initially set to 0 (except pdtc)
225      DO l=1,nlayer
226         DO ig=1,ngrid
227            zcondicea(ig,l) = 0.
228            pduc(ig,l)  = 0
229            pdvc(ig,l)  = 0
230            pdqc(ig,l,i_co2ice)  = 0
231         END DO
232      END DO
233     
234      DO ig=1,ngrid
235         Mfallice(ig) = 0.
236         zfallice(ig) = 0.
237         zcondices(ig) = 0.
238         pdtsrfc(ig) = 0.
239         pdpsrf(ig) = 0.
240         condsub(ig) = .false.
241         zdiceco2(ig) = 0.
242      ENDDO
243
244!-----------------------------------------------------------------------
245!     Atmospheric condensation
246
247
248!     Compute CO2 Volume mixing ratio
249!     -------------------------------
250!      if (addn2) then
251!         DO l=1,nlayer
252!            DO ig=1,ngrid
253!              qco2=pq(ig,l,ico2)+pdq(ig,l,ico2)*ptimestep
254!!             Mean air molecular mass = 1/(q(ico2)/m_co2 + (1-q(ico2))/m_noco2)
255!              mmean=1/(A*qco2 +B)
256!              vmr_co2(ig,l) = qco2*mmean/m_co2
257!            ENDDO
258!         ENDDO
259!      else
260!         DO l=1,nlayer
261!            DO ig=1,ngrid
262!              vmr_co2(ig,l)=0.5
263!            ENDDO
264!         ENDDO
265!      end if
266
267!     Forecast the atmospheric frost temperature 'ztcond' and nucleation temperature 'ztnuc'
268      DO l=1,nlayer
269         DO ig=1,ngrid
270            ppco2=gfrac(igasco2)*pplay(ig,l)
271            call get_tcond_co2(ppco2,ztcond(ig,l))
272            call get_tnuc_co2(ppco2,ztnuc(ig,l))
273         ENDDO
274      ENDDO
275     
276!     Initialize zq and zt at the beginning of the sub-timestep loop
277      DO l=1,nlayer
278         DO ig=1,ngrid
279            zt(ig,l)=pt(ig,l)
280            zq(ig,l,i_co2ice)=pq(ig,l,i_co2ice)
281            IF( zq(ig,l,i_co2ice).lt.-1.e-6 ) THEN
282               print*,'Uh-oh, zq = ',zq(ig,l,i_co2ice),'at ig,l=',ig,l
283               if(l.eq.1)then
284                  print*,'Perhaps the atmosphere is collapsing on surface...?'
285               endif
286            END IF
287         ENDDO
288      ENDDO
289
290!     Calculate the mass of each atmospheric layer (kg.m-2)
291      do  ilay=1,nlayer
292         DO ig=1,ngrid
293            masse(ig,ilay)=(pplev(ig,ilay) - pplev(ig,ilay+1)) /g
294         end do
295      end do
296
297!     -----------------------------------------------
298!     START CONDENSATION/SEDIMENTATION SUB-TIME LOOP
299!     -----------------------------------------------
300      Ntime =  20               ! number of sub-timestep
301      subptimestep = ptimestep/float(Ntime)           
302
303      DO it=1,Ntime
304
305!     Add the tendencies from other physical processes at each subtimstep
306         DO l=1,nlayer
307            DO ig=1,ngrid
308               zt(ig,l)   = zt(ig,l)   + pdt(ig,l)   * subptimestep
309               zq(ig,l,i_co2ice) = zq(ig,l,i_co2ice) + pdq(ig,l,i_co2ice) * subptimestep
310            END DO
311         END DO
312
313
314!     Gravitational sedimentation
315           
316!     sedimentation computed from radius computed from q in module radii_mod
317         call co2_reffrad(ngrid,nq,zq,reffrad)
318         
319         do  ilay=1,nlayer
320            DO ig=1,ngrid
321
322               reff = reffrad(ig,ilay,iaero_co2)
323
324               call stokes                      &
325                   (pplev(ig,ilay),pt(ig,ilay), &
326                    reff,vstokes,rho_co2)
327
328               !w(ig,ilay,i_co2ice) = 0.0
329               w(ig,ilay,i_co2ice) = vstokes *  subptimestep * &
330                   pplev(ig,ilay)/(r*pt(ig,ilay))
331
332            end do
333         end do
334
335!     Computing q after sedimentation
336
337         call vlz_fi(ngrid,zq(1,1,i_co2ice),2.,masse,w(1,1,i_co2ice),wq)
338
339
340!     Progressively accumulating the flux to the ground
341!     Mfallice is the total amount of ice fallen to the ground
342         DO ig=1,ngrid
343            Mfallice(ig) =  Mfallice(ig) + wq(ig,i_co2ice)
344         end do
345
346
347!     Condensation / sublimation in the atmosphere
348!     --------------------------------------------
349!     (calculation of zcondicea, zfallice and pdtc)
350!     (MODIFICATIONS FOR EARLY MARS: falling heat neglected, condensation
351!     of CO2 into tracer i_co2ice)
352
353         DO l=nlayer , 1, -1
354            DO ig=1,ngrid
355               pdtc(ig,l)=0.
356
357
358   !     ztcond-> ztnuc in test beneath to nucleate only when super saturation occurs(JL 2011)
359               IF ((zt(ig,l).LT.ztnuc(ig,l)).or.(zq(ig,l,i_co2ice).gt.1.E-10)) THEN
360                  condsub(ig)=.true.
361                  pdtc(ig,l)   = (ztcond(ig,l) - zt(ig,l))/subptimestep
362                  pdqc(ig,l,i_co2ice) = pdtc(ig,l)*ccond*g
363
364!     Case when the ice from above sublimes entirely
365                  IF ((zq(ig,l,i_co2ice).lt.-pdqc(ig,l,i_co2ice)*subptimestep) &
366                      .AND. (zq(ig,l,i_co2ice).gt.0)) THEN
367
368                     pdqc(ig,l,i_co2ice) = -zq(ig,l,i_co2ice)/subptimestep
369                     pdtc(ig,l)   =-zq(ig,l,i_co2ice)/(ccond*g*subptimestep)
370
371                  END IF
372
373!     Temperature and q after condensation
374                  zt(ig,l)   = zt(ig,l)   + pdtc(ig,l)   * subptimestep
375                  zq(ig,l,i_co2ice) = zq(ig,l,i_co2ice) + pdqc(ig,l,i_co2ice) * subptimestep
376               END IF
377
378            ENDDO
379         ENDDO
380      ENDDO                     ! end of subtimestep loop
381
382!     Computing global tendencies after the subtimestep
383      DO l=1,nlayer
384         DO ig=1,ngrid
385            pdtc(ig,l) = &
386              (zt(ig,l) - (pt(ig,l) + pdt(ig,l)*ptimestep))/ptimestep
387            pdqc(ig,l,i_co2ice) = &
388              (zq(ig,l,i_co2ice)-(pq(ig,l,i_co2ice)+pdq(ig,l,i_co2ice)*ptimestep))/ptimestep
389         END DO
390      END DO
391      DO ig=1,ngrid
392         zfallice(ig) = Mfallice(ig)/ptimestep
393      END DO
394
395
396!-----------------------------------------------------------------------
397!     Condensation/sublimation on the ground
398!     (calculation of zcondices and pdtsrfc)
399
400!     forecast of ground temperature ztsrf and frost temperature ztcondsol
401      DO ig=1,ngrid
402         ppco2=gfrac(igasco2)*pplay(ig,1)
403         call get_tcond_co2(ppco2,ztcondsol(ig))
404         
405         ztsrf(ig) = ptsrf(ig)
406
407         if((ztsrf(ig).le.ztcondsol(ig)+2.0).and.(ngrid.eq.1))then
408            print*,'CO2 is condensing on the surface in 1D. This atmosphere is doomed.'
409            print*,'T_surf = ',ztsrf,'K'
410            print*,'T_cond = ',ztcondsol,'K'
411            open(116,file='surf_vals.out')
412            write(116,*) 0.0, pplev(1,1), 0.0, 0.0
413            close(116)
414            call abort
415         endif
416
417         ztsrf(ig) = ptsrf(ig) + pdtsrf(ig)*ptimestep
418
419      ENDDO
420     
421      DO ig=1,ngrid
422         IF(ig.GT.ngrid/2+1) THEN
423            icap=2
424         ELSE
425            icap=1
426         ENDIF
427
428!     Loop over where we have condensation / sublimation
429         IF ((ztsrf(ig) .LT. ztcondsol(ig)) .OR.           &        ! ground condensation
430                    (zfallice(ig).NE.0.) .OR.              &        ! falling snow
431                    ((ztsrf(ig) .GT. ztcondsol(ig)) .AND.  &        ! ground sublimation
432                    ((piceco2(ig)+zfallice(ig)*ptimestep) .NE. 0.))) THEN
433            condsub(ig) = .true.
434
435!     Condensation or partial sublimation of CO2 ice
436            zcondices(ig)=pcapcal(ig)*(ztcondsol(ig)-ztsrf(ig)) &
437                /(latcond*ptimestep)         
438            pdtsrfc(ig) = (ztcondsol(ig) - ztsrf(ig))/ptimestep
439
440!     If the entire CO_2 ice layer sublimes
441!     (including what has just condensed in the atmosphere)
442            IF((piceco2(ig)/ptimestep+zfallice(ig)).LE. &
443                -zcondices(ig))THEN
444               zcondices(ig) = -piceco2(ig)/ptimestep - zfallice(ig)
445               pdtsrfc(ig)=(latcond/pcapcal(ig))*       &
446                   (zcondices(ig))
447            END IF
448
449!     Changing CO2 ice amount and pressure
450
451            zdiceco2(ig) = zcondices(ig) + zfallice(ig)
452            piceco2(ig)  = piceco2(ig) + zdiceco2(ig)*ptimestep
453            pdpsrf(ig)   = -zdiceco2(ig)*g
454
455            IF(ABS(pdpsrf(ig)*ptimestep).GT.pplev(ig,1)) THEN
456               PRINT*,'STOP in condens'
457               PRINT*,'condensing more than total mass'
458               PRINT*,'Grid point ',ig
459               PRINT*,'Ps = ',pplev(ig,1)
460               PRINT*,'d Ps = ',pdpsrf(ig)
461               STOP
462            ENDIF
463         END IF
464      ENDDO
465
466!     Surface albedo and emissivity of the ground below the snow (emisref)
467!     --------------------------------------------------------------------
468      DO ig=1,ngrid
469         IF(ig.GT.ngrid/2+1) THEN
470            icap=2
471         ELSE
472            icap=1
473         ENDIF
474
475         if(.not.piceco2(ig).ge.0.) THEN
476            if(piceco2(ig).le.-1.e-8) print*,   &
477                'WARNING in condense_co2cloud: piceco2(',ig,')=', piceco2(ig)
478            piceco2(ig)=0.
479         endif
480         if (piceco2(ig).gt.0) then
481            psolaralb(ig) = albedice(icap)
482            emisref(ig)   = emisice(icap)
483         else
484            psolaralb(ig) = albedodat(ig)
485            emisref(ig)   = emissiv
486            pemisurf(ig)  = emissiv
487         end if
488      end do
489
490      return
491    end subroutine condense_cloud
492
493!-------------------------------------------------------------------------
494    subroutine get_tcond_co2(p,tcond)
495!   Calculates the condensation temperature for CO2
496
497      implicit none
498
499#include "callkeys.h"
500
501      real p, peff, tcond
502      real, parameter :: ptriple=518000.0
503
504      peff=p
505
506      if(peff.lt.ptriple)then
507         tcond = (-3167.8)/(log(.01*peff)-23.23) ! Fanale's formula
508      else
509         tcond = 684.2-92.3*log(peff)+4.32*log(peff)**2
510         ! liquid-vapour transition (based on CRC handbook 2003 data)
511      endif
512      return
513
514    end subroutine get_tcond_co2
515   
516   
517   
518 
519!-------------------------------------------------------------------------
520    subroutine get_tnuc_co2(p,tnuc)
521!   Calculates the nucleation temperature for CO2, based on a simple super saturation criterion
522!     (JL 2011)
523
524      implicit none
525
526#include "callkeys.h"
527
528      real p, peff, tnuc
529      real, parameter :: ptriple=518000.0
530
531      peff=p/co2supsat
532
533      if(peff.lt.ptriple)then
534         tnuc = (-3167.8)/(log(.01*peff)-23.23) ! Fanale's formula
535      else
536         tnuc = 684.2-92.3*log(peff)+4.32*log(peff)**2
537         ! liquid-vapour transition (based on CRC handbook 2003 data)
538      endif
539      return
540
541    end subroutine get_tnuc_co2
Note: See TracBrowser for help on using the repository browser.