source: dynamico_lmdz/simple_physics/phyparam/physics/solar.F90 @ 4207

Last change on this file since 4207 was 4201, checked in by dubos, 6 years ago

simple_physics : cleanup

File size: 14.2 KB
Line 
1MODULE solar
2  IMPLICIT NONE
3
4  PRIVATE
5
6  REAL, PARAMETER :: pi_local = 4.0 * ATAN(1.0), deux_pi_local = 2.0 * pi_local
7
8  PUBLIC :: solang, zenang, mucorr
9
10CONTAINS
11
12  PURE SUBROUTINE solang ( kgrid,psilon,pcolon,psilat,pcolat, &
13       ptim1,ptim2,ptim3,pmu0,pfract )
14   
15    !-----------------------------------------------------------------------
16    !          CALCULATES THE SOLAR ANGLE FOR ALL THE POINTS OF THE GRID
17    !
18    !     ==== INPUTS  ===
19    !
20    ! PSILON(KGRID)   : SINUS OF THE LONGITUDE
21    ! PCOLON(KGRID)   : COSINUS OF THE LONGITUDE
22    ! PSILAT(KGRID)   : SINUS OF THE LATITUDE
23    ! PCOLAT(KGRID)   : COSINUS OF THE LATITUDE
24    ! PTIM1           : SIN(DECLI)
25    ! PTIM2           : COS(DECLI)*COS(TIME)
26    ! PTIM3           : SIN(DECLI)*SIN(TIME)
27    !
28    !     ==== OUTPUTS ===
29    !
30    ! PMU0 (KGRID)    : SOLAR ANGLE
31    ! PFRACT(KGRID)   : DAY FRACTION OF THE TIME INTERVAL
32    !
33    !     REFERENCE.
34    !     ----------
35    !
36    !         RADIATIVE PROCESSES IN METEOROLOGIE AND CLIMATOLOGIE
37    !         PALTRIDGE AND PLATT
38    !
39    !     AUTHOR.
40    !     -------
41    !        FREDERIC HOURDIN
42    !
43    !     MODIFICATIONS.
44    !     --------------
45    !        ORIGINAL :90-01-14
46    !                  92-02-14 CALCULATIONS DONE THE ENTIER GRID (J.Polcher)
47    !-----------------------------------------------------------------------
48
49    INTEGER, INTENT(IN)  :: kgrid
50    REAL,    INTENT(IN)  :: ptim1,ptim2,ptim3
51    REAL,    INTENT(IN)  :: psilon(kgrid), pcolon(kgrid)
52    REAL,    INTENT(IN)  :: psilat(kgrid), pcolat(kgrid)
53    REAL,    INTENT(OUT) :: pmu0(kgrid), pfract(kgrid)
54
55    INTEGER jl
56    REAL ztim1,ztim2,ztim3
57    !------------------------------------------------------------------------
58    !------------------------------------------------------------------------
59    !------------------------------------------------------------------------
60    !
61    !------------------------------------------------------------------------
62    !
63    !*     1.     INITIALISATION
64    !             --------------
65    !
66    !
67    DO jl=1,kgrid
68       pmu0(jl)=0.
69       pfract(jl)=0.
70    ENDDO
71    !
72    !*     1.1     COMPUTATION OF THE SOLAR ANGLE
73    !              ------------------------------
74    !
75    DO jl=1,kgrid
76       ztim1=psilat(jl)*ptim1
77       ztim2=pcolat(jl)*ptim2
78       ztim3=pcolat(jl)*ptim3
79       pmu0(jl)=ztim1+ztim2*pcolon(jl)+ztim3*psilon(jl)
80    ENDDO
81    !
82    !*     1.2      DISTINCTION BETWEEN DAY AND NIGHT
83    !               ---------------------------------
84    !
85    DO jl=1,kgrid
86       IF (pmu0(jl).gt.0.) THEN
87          pfract(jl)=1.
88       ELSE
89          pmu0(jl)=0.
90          pfract(jl)=0.
91       ENDIF
92    ENDDO
93   
94  END SUBROUTINE solang
95
96  SUBROUTINE zenang(klon,longi,gmtime,pdtrad,lat,long,              &
97       &                  pmu0,frac)                                     
98    USE astronomy
99   
100    !=============================================================         
101    ! Auteur : O. Boucher (LMD/CNRS)                                       
102    !          d'apres les routines zenith et angle de Z.X. Li             
103    ! Objet  : calculer les valeurs moyennes du cos de l'angle zenithal     
104    !          et l'ensoleillement moyen entre gmtime1 et gmtime2           
105    !          connaissant la declinaison, la latitude et la longitude.     
106    ! Rque   : Different de la routine angle en ce sens que zenang         
107    !          fournit des moyennes de pmu0 et non des valeurs             
108    !          instantanees, du coup frac prend toutes les valeurs         
109    !          entre 0 et 1.                                               
110    ! Date   : premiere version le 13 decembre 1994                         
111    !          revu pour  GCM  le 30 septembre 1996                         
112    !===============================================================       
113    ! longi----INPUT : la longitude vraie de la terre dans son plan         
114    !                  solaire a partir de l'equinoxe de printemps (degre) 
115    ! gmtime---INPUT : temps universel en fraction de jour                 
116    ! pdtrad---INPUT : pas de temps du rayonnement (secondes)               
117    ! lat------INPUT : latitude en degres                                   
118    ! long-----INPUT : longitude en degres                                 
119    ! pmu0-----OUTPUT: angle zenithal moyen entre gmtime et gmtime+pdtrad   
120    ! frac-----OUTPUT: ensoleillement moyen entre gmtime et gmtime+pdtrad   
121    !================================================================       
122    integer klon
123    !================================================================       
124    real longi, gmtime, pdtrad
125    real lat(klon), long(klon), pmu0(klon), frac(klon)
126    !================================================================       
127    integer i
128    real gmtime1, gmtime2
129    real incl
130    real omega1, omega2, omega
131    ! omega1, omega2 : temps 1 et 2 exprime en radian avec 0 a midi.       
132    ! omega : heure en radian du coucher de soleil                         
133    ! -omega est donc l'heure en radian de lever du soleil                 
134    real omegadeb, omegafin
135    real zfrac1, zfrac2, z1_mu, z2_mu
136    ! declinaison en radian                     
137    real lat_sun
138    ! longitude solaire en radian               
139    real lon_sun
140    ! latitude du pt de grille en radian       
141    real latr
142    !================================================================       
143    !                                                                       
144    !     incl=R_incl * pi_local / 180.                                     
145    print*,'Obliquite =' ,obliquit
146    incl=obliquit * pi_local / 180.
147    !                                                                       
148    !     lon_sun = longi * pi_local / 180.0                               
149    lon_sun = longi
150    lat_sun = ASIN (SIN(lon_sun)*SIN(incl) )
151    !                                                                       
152    gmtime1=gmtime*86400.
153    gmtime2=gmtime*86400.+pdtrad
154    !                                                                       
155    DO i = 1, klon
156       !                                                                       
157       !     latr = lat(i) * pi_local / 180.                                   
158       latr = lat(i)
159       !                                                                       
160       !--pose probleme quand lat=+/-90 degres                                 
161       !                                                                       
162       !      omega = -TAN(latr)*TAN(lat_sun)                                 
163       !      omega = ACOS(omega)                                             
164       !      IF (latr.GE.(pi_local/2.+lat_sun)                               
165       !     .    .OR. latr.LE.(-pi_local/2.+lat_sun)) THEN                   
166       !         omega = 0.0       ! nuit polaire                             
167       !      ENDIF                                                           
168       !      IF (latr.GE.(pi_local/2.-lat_sun)                               
169       !     .          .OR. latr.LE.(-pi_local/2.-lat_sun)) THEN             
170       !         omega = pi_local  ! journee polaire                           
171       !      ENDIF                                                           
172       !                                                                       
173       !--remplace par cela (le cas par defaut est different)                 
174       !                                                                       
175       !--nuit polaire                                       
176       omega=0.0
177       IF (latr.GE.(pi_local/2.-lat_sun)                                 &
178            &          .OR. latr.LE.(-pi_local/2.-lat_sun)) THEN               
179          ! journee polaire                           
180          omega = pi_local
181       ENDIF
182       IF (latr.LT.(pi_local/2.+lat_sun).AND.                            &
183            &    latr.GT.(-pi_local/2.+lat_sun).AND.                           &
184            &    latr.LT.(pi_local/2.-lat_sun).AND.                            &
185            &    latr.GT.(-pi_local/2.-lat_sun)) THEN                         
186          omega = -TAN(latr)*TAN(lat_sun)
187          omega = ACOS(omega)
188       ENDIF
189       !                                                                       
190       omega1 = gmtime1 + long(i)*86400.0/360.0
191       omega1 = omega1 / 86400.0*deux_pi_local
192       omega1 = MOD (omega1+deux_pi_local, deux_pi_local)
193       omega1 = omega1 - pi_local
194       !                                                                       
195       omega2 = gmtime2 + long(i)*86400.0/360.0
196       omega2 = omega2 / 86400.0*deux_pi_local
197       omega2 = MOD (omega2+deux_pi_local, deux_pi_local)
198       omega2 = omega2 - pi_local
199       !                                                                       
200       !--on est dans la meme journee locale
201       IF (omega1.LE.omega2) THEN
202          !                                                                       
203          IF (omega2.LE.-omega .OR. omega1.GE.omega .OR. omega.LT.1e-5)  &
204               THEN                                                           
205             !--nuit           
206             frac(i)=0.0
207             pmu0(i)=0.0
208             !--jour+nuit/jou
209          ELSE
210             omegadeb=MAX(-omega,omega1)
211             omegafin=MIN(omega,omega2)
212             frac(i)=(omegafin-omegadeb)/(omega2-omega1)
213             pmu0(i)=SIN(latr)*SIN(lat_sun) + COS(latr)*COS(lat_sun)*    &
214                  (SIN(omegafin)-SIN(omegadeb))/ (omegafin-omegadeb)         
215          ENDIF
216          !                                                                       
217          !---omega1 GT omega2 -- a cheval sur deux journees         
218       ELSE
219          !                                                                       
220          !-------------------entre omega1 et pi                                 
221          !--nuit                               
222          IF (omega1.GE.omega) THEN
223             zfrac1=0.0
224             z1_mu =0.0
225             !--jour+nuit                           
226          ELSE
227             omegadeb=MAX(-omega,omega1)
228             omegafin=omega
229             zfrac1=omegafin-omegadeb
230             z1_mu =SIN(latr)*SIN(lat_sun) + COS(latr)*COS(lat_sun)*     &
231                  (SIN(omegafin)-SIN(omegadeb))/ (omegafin-omegadeb)         
232          ENDIF
233          !---------------------entre -pi et omega2                               
234          !--nuit                             
235          IF (omega2.LE.-omega) THEN
236             zfrac2=0.0
237             z2_mu =0.0
238             !--jour+nuit                         
239          ELSE
240             omegadeb=-omega
241             omegafin=MIN(omega,omega2)
242             zfrac2=omegafin-omegadeb
243             z2_mu =SIN(latr)*SIN(lat_sun) + COS(latr)*COS(lat_sun)*     &
244                  (SIN(omegafin)-SIN(omegadeb))/ (omegafin-omegadeb)         
245             !                                                                       
246          ENDIF
247          !-----------------------moyenne                                         
248          frac(i)=(zfrac1+zfrac2)/(omega2+deux_pi_local-omega1)
249          pmu0(i)=(zfrac1*z1_mu+zfrac2*z2_mu)/MAX(zfrac1+zfrac2,1.E-10)
250          !                                                                       
251          !---comparaison omega1 et omega2                         
252       ENDIF
253       !                                                                       
254    ENDDO
255    !                                                                       
256  END SUBROUTINE zenang
257 
258  PURE SUBROUTINE mucorr(npts,pdeclin, plat, pmu, pfract,phaut,prad)
259   
260    !=======================================================================
261    !
262    !   Calcul of equivalent solar angle and and fraction of day whithout
263    !   diurnal cycle.
264    !
265    !   parmeters :
266    !   -----------
267    !
268    !      Input :
269    !      -------
270    !         npts             number of points
271    !         pdeclin          solar declinaison
272    !         plat(npts)        latitude
273    !         phaut            hauteur typique de l'atmosphere
274    !         prad             rayon planetaire
275    !
276    !      Output :
277    !      --------
278    !         pmu(npts)          equivalent cosinus of the solar angle
279    !         pfract(npts)       fractionnal day
280    !
281    !=======================================================================
282   
283    !-----------------------------------------------------------------------
284    !
285    !    0. Declarations :
286    !    -----------------
287   
288    !     Arguments :
289    !     -----------
290    INTEGER, INTENT(IN) :: npts
291    REAL, INTENT(IN)    :: phaut, prad, pdeclin, plat(npts)
292    REAL, INTENT(OUT)   :: pmu(npts), pfract(npts)
293    !
294    !     Local variables :
295    !     -----------------
296    INTEGER j
297    REAL z,cz,sz,tz,phi,cphi,sphi,tphi
298    REAL ap,a,t,b
299    REAL alph
300
301    REAL, PARAMETER :: pi=2.*asin(1.)
302
303    !-----------------------------------------------------------------------
304   
305!    print*,'npts,pdeclin',npts,pdeclin
306    z = pdeclin
307    cz = cos (z)
308    sz = sin (z)
309!    print*,'cz,sz',cz,sz
310   
311    DO j = 1, npts
312       
313       phi = plat(j)
314       cphi = cos(phi)
315       if (cphi.le.1.e-9) cphi=1.e-9
316       sphi = sin(phi)
317       tphi = sphi / cphi
318       b = cphi * cz
319       t = -tphi * sz / cz
320       a = 1.0 - t*t
321       ap = a
322       
323       IF(t.eq.0.) then
324          t=0.5*pi
325       ELSE
326          IF (a.lt.0.) a = 0.
327          t = sqrt(a) / t
328          IF (t.lt.0.) then
329             t = -atan (-t) + pi
330          ELSE
331             t = atan(t)
332          ENDIF
333       ENDIF
334       
335       pmu(j) = (sphi*sz*t) / pi + b*sin(t)/pi
336       pfract(j) = t / pi
337       IF (ap .lt.0.) then
338          pmu(j) = sphi * sz
339          pfract(j) = 1.0
340       ENDIF
341       IF (pmu(j).le.0.0) pmu(j) = 0.0
342       pmu(j) = pmu(j) / pfract(j)
343       IF (pmu(j).eq.0.) pfract(j) = 0.
344       
345    END DO
346   
347    !-----------------------------------------------------------------------
348    !   correction de rotondite:
349    !   ------------------------
350   
351    alph=phaut/prad
352    DO j=1,npts
353       ! !!!!!!
354       pmu(j)=sqrt(1224.*pmu(j)*pmu(j)+1.)/35.
355       !    $          (sqrt(alph*alph*pmu(j)*pmu(j)+2.*alph+1.)-alph*pmu(j))
356    END DO
357   
358  END SUBROUTINE mucorr
359
360END MODULE solar
Note: See TracBrowser for help on using the repository browser.