source: LMDZ6/trunk/libf/phylmd/nuage.f90 @ 5833

Last change on this file since 5833 was 5828, checked in by rkazeroni, 2 months ago

For GPU porting of call_cloud_optics_prop routine:

  • Add "horizontal" comment to specify possible names of horizontal variables
  • Put routine into module (speeds up source-to-source transformation)
  • Move declaration of variable with SAVE attribute outside of the compute routine to the module
  • Record event with a 2D "first" array instead of a scalar to enable GPU porting
  • Perform reduction on this "first" array and print (once) outside of the compute routine since this cannot be done on GPU in the current form
  • Property copyright set to
    Name of program: LMDZ
    Creation date: 1984
    Version: LMDZ5
    License: CeCILL version 2
    Holder: Laboratoire de m\'et\'eorologie dynamique, CNRS, UMR 8539
    See the license file in the root directory
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.9 KB
RevLine 
[1279]1! $Id: nuage.f90 5828 2025-09-23 14:32:02Z rkazeroni $
[5828]2MODULE nuage_mod
3  PRIVATE
[524]4
[5828]5  PUBLIC nuage, diagcld1, diagcld2
6
7  CONTAINS
8
[3999]9SUBROUTINE nuage(paprs, pplay, t, pqlwp,picefra, pclc, pcltau, pclemi, pch, pcl, pcm, &
[4562]10    pct, pctlwp, ok_aie, mass_solu_aero, mass_solu_aero_pi, bl95_b0, bl95_b1, distcltop, &
[4639]11    temp_cltop, cldtaupi, re, fl)
[5282]12  USE clesphys_mod_h
[5285]13  USE yomcst_mod_h
[1992]14  USE dimphy
[4664]15  USE lmdz_lscp_tools, only: icefrac_lscp
[2109]16  USE icefrac_lsc_mod ! computes ice fraction (JBM 3/14)
[4664]17  USE lmdz_lscp_ini, only : iflag_t_glace
[3999]18  USE phys_local_var_mod, ONLY: ptconv
[5305]19  USE nuage_params_mod_h
[1992]20  IMPLICIT NONE
21  ! ======================================================================
22  ! Auteur(s): Z.X. Li (LMD/CNRS) date: 19930910
23  ! Objet: Calculer epaisseur optique et emmissivite des nuages
24  ! ======================================================================
25  ! Arguments:
26  ! t-------input-R-temperature
27  ! pqlwp---input-R-eau liquide nuageuse dans l'atmosphere (kg/kg)
[3999]28  ! picefra--inout-R-fraction de glace dans les nuages (-)
[1992]29  ! pclc----input-R-couverture nuageuse pour le rayonnement (0 a 1)
30  ! ok_aie--input-L-apply aerosol indirect effect or not
31  ! mass_solu_aero-----input-R-total mass concentration for all soluble
32  ! aerosols[ug/m^3]
33  ! mass_solu_aero_pi--input-R-dito, pre-industrial value
34  ! bl95_b0-input-R-a parameter, may be varied for tests (s-sea, l-land)
35  ! bl95_b1-input-R-a parameter, may be varied for tests (    -"-      )
[524]36
[1992]37  ! cldtaupi-output-R-pre-industrial value of cloud optical thickness,
38  ! needed for the diagnostics of the aerosol indirect
39  ! radiative forcing (see radlwsw)
40  ! re------output-R-Cloud droplet effective radius multiplied by fl [um]
41  ! fl------output-R-Denominator to re, introduced to avoid problems in
42  ! the averaging of the output. fl is the fraction of liquid
43  ! water clouds within a grid cell
44
45  ! pcltau--output-R-epaisseur optique des nuages
46  ! pclemi--output-R-emissivite des nuages (0 a 1)
47  ! ======================================================================
48
49  REAL paprs(klon, klev+1), pplay(klon, klev)
50  REAL t(klon, klev)
51
52  REAL pclc(klon, klev)
[3999]53  REAL pqlwp(klon, klev), picefra(klon,klev)
[1992]54  REAL pcltau(klon, klev), pclemi(klon, klev)
55
56  REAL pct(klon), pctlwp(klon), pch(klon), pcl(klon), pcm(klon)
[4562]57  REAL distcltop(klon,klev)
[4639]58  REAL temp_cltop(klon,klev)
[1992]59  LOGICAL lo
60
61  REAL cetahb, cetamb
62  PARAMETER (cetahb=0.45, cetamb=0.80)
63
64  INTEGER i, k
[2077]65  REAL zflwp, zradef, zfice(klon), zmsac
[1992]66
[2006]67  REAL radius, rad_chaud
68! JBM (3/14) parameters already defined in nuage.h:
69! REAL rad_froid, rad_chau1, rad_chau2
70! PARAMETER (rad_chau1=13.0, rad_chau2=9.0, rad_froid=35.0)
[1992]71  ! cc      PARAMETER (rad_chaud=15.0, rad_froid=35.0)
72  ! sintex initial      PARAMETER (rad_chaud=10.0, rad_froid=30.0)
73  REAL coef, coef_froi, coef_chau
74  PARAMETER (coef_chau=0.13, coef_froi=0.09)
[2006]75  REAL seuil_neb
76  PARAMETER (seuil_neb=0.001)
77! JBM (3/14) nexpo is replaced by exposant_glace
78! REAL nexpo ! exponentiel pour glace/eau
79! PARAMETER (nexpo=6.)
80  REAL, PARAMETER :: t_glace_min_old = 258.
81  INTEGER, PARAMETER :: exposant_glace_old = 6
[1992]82
[2006]83
[1992]84  ! jq for the aerosol indirect effect
85  ! jq introduced by Johannes Quaas (quaas@lmd.jussieu.fr), 27/11/2003
86  ! jq
87  LOGICAL ok_aie ! Apply AIE or not?
88
89  REAL mass_solu_aero(klon, klev) ! total mass concentration for all soluble aerosols[ug m-3]
90  REAL mass_solu_aero_pi(klon, klev) ! - " - pre-industrial value
91  REAL cdnc(klon, klev) ! cloud droplet number concentration [m-3]
92  REAL re(klon, klev) ! cloud droplet effective radius [um]
93  REAL cdnc_pi(klon, klev) ! cloud droplet number concentration [m-3] (pi value)
94  REAL re_pi(klon, klev) ! cloud droplet effective radius [um] (pi value)
95
96  REAL fl(klon, klev) ! xliq * rneb (denominator to re; fraction of liquid water clouds
97  ! within the grid cell)
98
99  REAL bl95_b0, bl95_b1 ! Parameter in B&L 95-Formula
100
101  REAL cldtaupi(klon, klev) ! pre-industrial cloud opt thickness for diag
[3999]102  REAl dzfice(klon)
[5828]103  REAL :: pp_ratio(klon)
[1992]104  ! jq-end
105
106  ! cc      PARAMETER (nexpo=1)
107
108  ! Calculer l'epaisseur optique et l'emmissivite des nuages
109
110  DO k = 1, klev
[2077]111     IF (iflag_t_glace.EQ.0) THEN
112       DO i = 1, klon
113        zfice(i) = 1.0 - (t(i,k)-t_glace_min_old)/(273.13-t_glace_min_old)
114        zfice(i) = min(max(zfice(i),0.0), 1.0)
115        zfice(i) = zfice(i)**exposant_glace_old
116       ENDDO
117     ELSE ! of IF (iflag_t_glace.EQ.0)
[2109]118! JBM: icefrac_lsc is now a function contained in icefrac_lsc_mod
[2077]119!       zfice(i) = icefrac_lsc(t(i,k), t_glace_min, &
120!                           t_glace_max, exposant_glace)
[3999]121        IF (ok_new_lscp) THEN
[4639]122            CALL icefrac_lscp(klon,t(:,k),iflag_ice_thermo,distcltop(:,k),temp_cltop(:,k),zfice(:),dzfice(:))
[3999]123        ELSE
[5828]124            pp_ratio(1:klon) = pplay(1:klon,k)/paprs(1:klon,1)
125            CALL icefrac_lsc(klon,t(:,k),pp_ratio(:),zfice(:))
[3999]126
127        ENDIF
128
[4715]129    IF (ok_new_lscp .AND. ok_icefra_lscp) THEN
130    ! EV: take the ice fraction directly from the lscp code
131    ! consistent only for non convective grid points
132    ! critical for mixed phase clouds
133        DO i=1,klon
134        IF (.NOT. ptconv(i,k)) THEN
135           zfice(i)=picefra(i,k)
[3999]136        ENDIF
[4715]137        ENDDO
138    ENDIF
[3999]139
140
[2077]141     ENDIF
142
[1992]143    DO i = 1, klon
144      rad_chaud = rad_chau1
145      IF (k<=3) rad_chaud = rad_chau2
146
147      pclc(i, k) = max(pclc(i,k), seuil_neb)
148      zflwp = 1000.*pqlwp(i, k)/rg/pclc(i, k)*(paprs(i,k)-paprs(i,k+1))
149
150      IF (ok_aie) THEN
151          ! Formula "D" of Boucher and Lohmann, Tellus, 1995
152          !
153        cdnc(i, k) = 10.**(bl95_b0+bl95_b1*log(max(mass_solu_aero(i,k), &
154          1.E-4))/log(10.))*1.E6 !-m-3
155          ! Cloud droplet number concentration (CDNC) is restricted
156          ! to be within [20, 1000 cm^3]
157          !
158        cdnc(i, k) = min(1000.E6, max(20.E6,cdnc(i,k)))
159        cdnc_pi(i, k) = 10.**(bl95_b0+bl95_b1*log(max(mass_solu_aero_pi(i,k), &
160          1.E-4))/log(10.))*1.E6 !-m-3
161        cdnc_pi(i, k) = min(1000.E6, max(20.E6,cdnc_pi(i,k)))
162          !
163          !
164          ! air density: pplay(i,k) / (RD * zT(i,k))
165          ! factor 1.1: derive effective radius from volume-mean radius
166          ! factor 1000 is the water density
167          ! _chaud means that this is the CDR for liquid water clouds
168          !
169        rad_chaud = 1.1*((pqlwp(i,k)*pplay(i,k)/(rd*t(i,k)))/(4./3.*rpi*1000. &
170          *cdnc(i,k)))**(1./3.)
171          !
172          ! Convert to um. CDR shall be at least 3 um.
173          !
174        rad_chaud = max(rad_chaud*1.E6, 3.)
175
176          ! For output diagnostics
177          !
178          ! Cloud droplet effective radius [um]
179          !
180          ! we multiply here with f * xl (fraction of liquid water
181          ! clouds in the grid cell) to avoid problems in the
182          ! averaging of the output.
183          ! In the output of IOIPSL, derive the real cloud droplet
184          ! effective radius as re/fl
185          !
[2077]186        fl(i, k) = pclc(i, k)*(1.-zfice(i))
[1992]187        re(i, k) = rad_chaud*fl(i, k)
188
189          ! Pre-industrial cloud opt thickness
190          !
191          ! "radius" is calculated as rad_chaud above (plus the
192          ! ice cloud contribution) but using cdnc_pi instead of
193          ! cdnc.
194        radius = max(1.1E6*((pqlwp(i,k)*pplay(i,k)/(rd*t(i,k)))/(4./3.*rpi* &
[2077]195          1000.*cdnc_pi(i,k)))**(1./3.), 3.)*(1.-zfice(i)) + rad_froid*zfice(i)
[1992]196        cldtaupi(i, k) = 3.0/2.0*zflwp/radius
197      END IF ! ok_aie
198
[2077]199      radius = rad_chaud*(1.-zfice(i)) + rad_froid*zfice(i)
200      coef = coef_chau*(1.-zfice(i)) + coef_froi*zfice(i)
[1992]201      pcltau(i, k) = 3.0/2.0*zflwp/radius
202      pclemi(i, k) = 1.0 - exp(-coef*zflwp)
203      lo = (pclc(i,k)<=seuil_neb)
204      IF (lo) pclc(i, k) = 0.0
205      IF (lo) pcltau(i, k) = 0.0
206      IF (lo) pclemi(i, k) = 0.0
207
208      IF (.NOT. ok_aie) cldtaupi(i, k) = pcltau(i, k)
209    END DO
210  END DO
211  ! cc      DO k = 1, klev
212  ! cc      DO i = 1, klon
213  ! cc         t(i,k) = t(i,k)
214  ! cc         pclc(i,k) = MAX( 1.e-5 , pclc(i,k) )
215  ! cc         lo = pclc(i,k) .GT. (2.*1.e-5)
216  ! cc         zflwp = pqlwp(i,k)*1000.*(paprs(i,k)-paprs(i,k+1))
217  ! cc     .          /(rg*pclc(i,k))
218  ! cc         zradef = 10.0 + (1.-sigs(k))*45.0
219  ! cc         pcltau(i,k) = 1.5 * zflwp / zradef
220  ! cc         zfice=1.0-MIN(MAX((t(i,k)-263.)/(273.-263.),0.0),1.0)
221  ! cc         zmsac = 0.13*(1.0-zfice) + 0.08*zfice
222  ! cc         pclemi(i,k) = 1.-EXP(-zmsac*zflwp)
223  ! cc         if (.NOT.lo) pclc(i,k) = 0.0
224  ! cc         if (.NOT.lo) pcltau(i,k) = 0.0
225  ! cc         if (.NOT.lo) pclemi(i,k) = 0.0
226  ! cc      ENDDO
227  ! cc      ENDDO
228  ! ccccc      print*, 'pas de nuage dans le rayonnement'
229  ! ccccc      DO k = 1, klev
230  ! ccccc      DO i = 1, klon
231  ! ccccc         pclc(i,k) = 0.0
232  ! ccccc         pcltau(i,k) = 0.0
233  ! ccccc         pclemi(i,k) = 0.0
234  ! ccccc      ENDDO
235  ! ccccc      ENDDO
236
237  ! COMPUTE CLOUD LIQUID PATH AND TOTAL CLOUDINESS
238
239  DO i = 1, klon
240    pct(i) = 1.0
241    pch(i) = 1.0
242    pcm(i) = 1.0
243    pcl(i) = 1.0
244    pctlwp(i) = 0.0
245  END DO
246
247  DO k = klev, 1, -1
248    DO i = 1, klon
249      pctlwp(i) = pctlwp(i) + pqlwp(i, k)*(paprs(i,k)-paprs(i,k+1))/rg
250      pct(i) = pct(i)*(1.0-pclc(i,k))
251      IF (pplay(i,k)<=cetahb*paprs(i,1)) pch(i) = pch(i)*(1.0-pclc(i,k))
252      IF (pplay(i,k)>cetahb*paprs(i,1) .AND. pplay(i,k)<=cetamb*paprs(i,1)) &
253        pcm(i) = pcm(i)*(1.0-pclc(i,k))
254      IF (pplay(i,k)>cetamb*paprs(i,1)) pcl(i) = pcl(i)*(1.0-pclc(i,k))
255    END DO
256  END DO
257
258  DO i = 1, klon
259    pct(i) = 1. - pct(i)
260    pch(i) = 1. - pch(i)
261    pcm(i) = 1. - pcm(i)
262    pcl(i) = 1. - pcl(i)
263  END DO
264
265  RETURN
266END SUBROUTINE nuage
[5828]267
[1992]268SUBROUTINE diagcld1(paprs, pplay, rain, snow, kbot, ktop, diafra, dialiq)
269  USE dimphy
[5285]270  USE yomcst_mod_h
[5274]271IMPLICIT NONE
[1992]272
273  ! Laurent Li (LMD/CNRS), le 12 octobre 1998
274  ! (adaptation du code ECMWF)
275
276  ! Dans certains cas, le schema pronostique des nuages n'est
277  ! pas suffisament performant. On a donc besoin de diagnostiquer
278  ! ces nuages. Je dois avouer que c'est une frustration.
279
280
[5274]281
[1992]282  ! Arguments d'entree:
283  REAL paprs(klon, klev+1) ! pression (Pa) a inter-couche
284  REAL pplay(klon, klev) ! pression (Pa) au milieu de couche
285  REAL t(klon, klev) ! temperature (K)
286  REAL q(klon, klev) ! humidite specifique (Kg/Kg)
287  REAL rain(klon) ! pluie convective (kg/m2/s)
288  REAL snow(klon) ! neige convective (kg/m2/s)
289  INTEGER ktop(klon) ! sommet de la convection
290  INTEGER kbot(klon) ! bas de la convection
291
292  ! Arguments de sortie:
293  REAL diafra(klon, klev) ! fraction nuageuse diagnostiquee
294  REAL dialiq(klon, klev) ! eau liquide nuageuse
295
296  ! Constantes ajustables:
297  REAL canva, canvb, canvh
298  PARAMETER (canva=2.0, canvb=0.3, canvh=0.4)
299  REAL cca, ccb, ccc
300  PARAMETER (cca=0.125, ccb=1.5, ccc=0.8)
301  REAL ccfct, ccscal
302  PARAMETER (ccfct=0.400)
303  PARAMETER (ccscal=1.0E+11)
304  REAL cetahb, cetamb
305  PARAMETER (cetahb=0.45, cetamb=0.80)
306  REAL cclwmr
307  PARAMETER (cclwmr=1.E-04)
308  REAL zepscr
309  PARAMETER (zepscr=1.0E-10)
310
311  ! Variables locales:
312  INTEGER i, k
313  REAL zcc(klon)
314
315  ! Initialisation:
316
317  DO k = 1, klev
318    DO i = 1, klon
319      diafra(i, k) = 0.0
320      dialiq(i, k) = 0.0
321    END DO
322  END DO
323
324  DO i = 1, klon ! Calculer la fraction nuageuse
325    zcc(i) = 0.0
326    IF ((rain(i)+snow(i))>0.) THEN
327      zcc(i) = cca*log(max(zepscr,(rain(i)+snow(i))*ccscal)) - ccb
328      zcc(i) = min(ccc, max(0.0,zcc(i)))
329    END IF
330  END DO
331
332  DO i = 1, klon ! pour traiter les enclumes
333    diafra(i, ktop(i)) = max(diafra(i,ktop(i)), zcc(i)*ccfct)
334    IF ((zcc(i)>=canvh) .AND. (pplay(i,ktop(i))<=cetahb*paprs(i, &
335      1))) diafra(i, ktop(i)) = max(diafra(i,ktop(i)), max(zcc( &
336      i)*ccfct,canva*(zcc(i)-canvb)))
337    dialiq(i, ktop(i)) = cclwmr*diafra(i, ktop(i))
338  END DO
339
340  DO k = 1, klev ! nuages convectifs (sauf enclumes)
341    DO i = 1, klon
342      IF (k<ktop(i) .AND. k>=kbot(i)) THEN
343        diafra(i, k) = max(diafra(i,k), zcc(i)*ccfct)
344        dialiq(i, k) = cclwmr*diafra(i, k)
345      END IF
346    END DO
347  END DO
348
349  RETURN
350END SUBROUTINE diagcld1
[5828]351
[1992]352SUBROUTINE diagcld2(paprs, pplay, t, q, diafra, dialiq)
353  USE dimphy
[5285]354  USE yomcst_mod_h
[5284]355  USE yoethf_mod_h
[5274]356IMPLICIT NONE
[1992]357
358
[5274]359
[1992]360  ! Arguments d'entree:
361  REAL paprs(klon, klev+1) ! pression (Pa) a inter-couche
362  REAL pplay(klon, klev) ! pression (Pa) au milieu de couche
363  REAL t(klon, klev) ! temperature (K)
364  REAL q(klon, klev) ! humidite specifique (Kg/Kg)
365
366  ! Arguments de sortie:
367  REAL diafra(klon, klev) ! fraction nuageuse diagnostiquee
368  REAL dialiq(klon, klev) ! eau liquide nuageuse
369
370  REAL cetamb
371  PARAMETER (cetamb=0.80)
372  REAL cloia, cloib, cloic, cloid
373  PARAMETER (cloia=1.0E+02, cloib=-10.00, cloic=-0.6, cloid=5.0)
374  ! cc      PARAMETER (CLOIA=1.0E+02, CLOIB=-10.00, CLOIC=-0.9, CLOID=5.0)
375  REAL rgammas
376  PARAMETER (rgammas=0.05)
377  REAL crhl
378  PARAMETER (crhl=0.15)
379  ! cc      PARAMETER (CRHL=0.70)
380  REAL t_coup
381  PARAMETER (t_coup=234.0)
382
383  ! Variables locales:
384  INTEGER i, k, kb, invb(klon)
385  REAL zqs, zrhb, zcll, zdthmin(klon), zdthdp
386  REAL zdelta, zcor
387
388  ! Fonctions thermodynamiques:
389  include "FCTTRE.h"
390
391  ! Initialisation:
392
393  DO k = 1, klev
394    DO i = 1, klon
395      diafra(i, k) = 0.0
396      dialiq(i, k) = 0.0
397    END DO
398  END DO
399
400  DO i = 1, klon
401    invb(i) = klev
402    zdthmin(i) = 0.0
403  END DO
404
405  DO k = 2, klev/2 - 1
406    DO i = 1, klon
407      zdthdp = (t(i,k)-t(i,k+1))/(pplay(i,k)-pplay(i,k+1)) - &
408        rd*0.5*(t(i,k)+t(i,k+1))/rcpd/paprs(i, k+1)
409      zdthdp = zdthdp*cloia
410      IF (pplay(i,k)>cetamb*paprs(i,1) .AND. zdthdp<zdthmin(i)) THEN
411        zdthmin(i) = zdthdp
412        invb(i) = k
413      END IF
414    END DO
415  END DO
416
417  DO i = 1, klon
418    kb = invb(i)
419    IF (thermcep) THEN
420      zdelta = max(0., sign(1.,rtt-t(i,kb)))
421      zqs = r2es*foeew(t(i,kb), zdelta)/pplay(i, kb)
422      zqs = min(0.5, zqs)
423      zcor = 1./(1.-retv*zqs)
424      zqs = zqs*zcor
425    ELSE
426      IF (t(i,kb)<t_coup) THEN
427        zqs = qsats(t(i,kb))/pplay(i, kb)
428      ELSE
429        zqs = qsatl(t(i,kb))/pplay(i, kb)
430      END IF
431    END IF
432    zcll = cloib*zdthmin(i) + cloic
433    zcll = min(1.0, max(0.0,zcll))
434    zrhb = q(i, kb)/zqs
435    IF (zcll>0.0 .AND. zrhb<crhl) zcll = zcll*(1.-(crhl-zrhb)*cloid)
436    zcll = min(1.0, max(0.0,zcll))
437    diafra(i, kb) = max(diafra(i,kb), zcll)
438    dialiq(i, kb) = diafra(i, kb)*rgammas*zqs
439  END DO
440
441  RETURN
442END SUBROUTINE diagcld2
[5828]443
444END MODULE nuage_mod
Note: See TracBrowser for help on using the repository browser.