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
Line 
1! $Id: nuage.f90 5828 2025-09-23 14:32:02Z rkazeroni $
2MODULE nuage_mod
3  PRIVATE
4
5  PUBLIC nuage, diagcld1, diagcld2
6
7  CONTAINS
8
9SUBROUTINE nuage(paprs, pplay, t, pqlwp,picefra, pclc, pcltau, pclemi, pch, pcl, pcm, &
10    pct, pctlwp, ok_aie, mass_solu_aero, mass_solu_aero_pi, bl95_b0, bl95_b1, distcltop, &
11    temp_cltop, cldtaupi, re, fl)
12  USE clesphys_mod_h
13  USE yomcst_mod_h
14  USE dimphy
15  USE lmdz_lscp_tools, only: icefrac_lscp
16  USE icefrac_lsc_mod ! computes ice fraction (JBM 3/14)
17  USE lmdz_lscp_ini, only : iflag_t_glace
18  USE phys_local_var_mod, ONLY: ptconv
19  USE nuage_params_mod_h
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)
28  ! picefra--inout-R-fraction de glace dans les nuages (-)
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 (    -"-      )
36
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)
53  REAL pqlwp(klon, klev), picefra(klon,klev)
54  REAL pcltau(klon, klev), pclemi(klon, klev)
55
56  REAL pct(klon), pctlwp(klon), pch(klon), pcl(klon), pcm(klon)
57  REAL distcltop(klon,klev)
58  REAL temp_cltop(klon,klev)
59  LOGICAL lo
60
61  REAL cetahb, cetamb
62  PARAMETER (cetahb=0.45, cetamb=0.80)
63
64  INTEGER i, k
65  REAL zflwp, zradef, zfice(klon), zmsac
66
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)
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)
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
82
83
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
102  REAl dzfice(klon)
103  REAL :: pp_ratio(klon)
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
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)
118! JBM: icefrac_lsc is now a function contained in icefrac_lsc_mod
119!       zfice(i) = icefrac_lsc(t(i,k), t_glace_min, &
120!                           t_glace_max, exposant_glace)
121        IF (ok_new_lscp) THEN
122            CALL icefrac_lscp(klon,t(:,k),iflag_ice_thermo,distcltop(:,k),temp_cltop(:,k),zfice(:),dzfice(:))
123        ELSE
124            pp_ratio(1:klon) = pplay(1:klon,k)/paprs(1:klon,1)
125            CALL icefrac_lsc(klon,t(:,k),pp_ratio(:),zfice(:))
126
127        ENDIF
128
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)
136        ENDIF
137        ENDDO
138    ENDIF
139
140
141     ENDIF
142
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          !
186        fl(i, k) = pclc(i, k)*(1.-zfice(i))
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* &
195          1000.*cdnc_pi(i,k)))**(1./3.), 3.)*(1.-zfice(i)) + rad_froid*zfice(i)
196        cldtaupi(i, k) = 3.0/2.0*zflwp/radius
197      END IF ! ok_aie
198
199      radius = rad_chaud*(1.-zfice(i)) + rad_froid*zfice(i)
200      coef = coef_chau*(1.-zfice(i)) + coef_froi*zfice(i)
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
267
268SUBROUTINE diagcld1(paprs, pplay, rain, snow, kbot, ktop, diafra, dialiq)
269  USE dimphy
270  USE yomcst_mod_h
271IMPLICIT NONE
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
281
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
351
352SUBROUTINE diagcld2(paprs, pplay, t, q, diafra, dialiq)
353  USE dimphy
354  USE yomcst_mod_h
355  USE yoethf_mod_h
356IMPLICIT NONE
357
358
359
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
443
444END MODULE nuage_mod
Note: See TracBrowser for help on using the repository browser.